From aebcff84edd4e51dc2e31bd0df1d1768936ae2a5 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 5 Jul 2017 18:59:48 -0500 Subject: [PATCH 0001/2137] Big squash e72eac2fc A few more sse instructions bdf83e0f0 temp rebase to resolve conflicts 58aa08353 replace all usage of modrm_byte with the set/get fns 7f1dbadf4 move registers to wasm memory 9a0432708 remove stdio inclusion 60f49f735 partial branch port of read_e8 747c51979 partial port of do_div32 8700c3042 remove wasm file from repo c69bc5c91 revert div32 to js ead0195b9 move last_op1 to wasm 16e9a2801 move last_op2 to wasm 4b5e749c8 move last_op_size to wasm 3a02ec98c move last_add_result, last_result, flags_changed to wasm 882b5476b implement add in C 8a8b15e11 move flags to wasm 4667917a9 implement getcf in C 1199537a1 implement adc in C a8a2f81ba implement sub in C 697cb4070 implement sbb in C 1e4e08079 implement inc in C 35259ddc3 implement dec in C 82498a632 implement neg in C 47fe549af copy opsize and reg constants 39c0f07aa implement mul8 in C 443aef4b2 implement imul8 in C afd2ec864 refactor memory accessing from C f937617bc implement mul16 in C af430b023 rewrite reg_* macros 6639f23a7 implement imul16 in C 6c490e88d add wasm build to makefile ea698b8bc refactor modrm_byte access 71899e821 split cpu.c into individual files 00dc878be capitalize flag constants e1ccf9477 remove unused buffer view f0175e480 refactor JS to wasm replacement f52c5f3a6 add assert.h ccf73539e implement imul_reg16 in C 8ae41facd implement do_mul32 in C and port mul32_result to wasm memory 77d3875eb implement do_imul32 in C af1cdc85d implement mul32 in C 820f514e3 implement imul32 in C e165f02e0 implement imul_reg32 in C fdee993e9 implement xadd8 in C 4e5d6f1c2 implement xadd16 in C 1c903565f implement xadd32 in C 1be111a93 implement getaf in C 4c2bc9f43 implement bcd_daa in C 3852cee61 implement bcd_das in C ed68e2777 implement bcd_aad in C b56c17640 implement bcd_aaa in C 5650e48c6 implement bcd_aas in C 99aeb5682 implement and in C 39d2308aa implement or in C c76e59a0b implement xor in C b14b87b95 async wasm instantiation 7f11605bc implement rol8 in C 161c662cf implement rol16 in C 37bf420f6 implement rol32 in C 921f06821 implement rcl8 in C 2f1bf0c2d implement rcl16 in C ad1d56ebe implement rcl32 in C ebcded69e implement ror8 in C 9bc225ff0 implement ror16 in C 403125717 implement ror32 in C 2a21a0896 implement rcr8 in C 80bf2667e implement rcr16 in C f8fe46c47 implement rcr32 in C 95493a272 split error_code flag in call_interrupt_vector a6f19110e export throw_cpu_exception to C dd5d8ce0d export call_interrupt_vector to C 537c08f65 implement raise_exception_with_code to C 8347e787e port instruction_pointer to wasm memory (offset 556) 0e62a7046 port previous_ip to wasm memory (offset 560) c09089e40 implement trigger_gp in C a4f0fed1b implement raise_exception in C 0b41949f4 implement trigger_de in C fc2a568a6 implement div8 in C acc6bbb54 implement idiv8 in C 5a3db2d09 implement div16 in C d77f0d151 Move wasm replacements to a dedicated function 135b19af0 port idtr_size and idtr_offset to wasm (offset 564, 568) 5f0ad7257 port gdtr_size to wasm (offset 572) dc17f7b7a port gdtr_offset to wasm (offset 576) 07876e86f port cr to wasm (offsets 580-608) 50b0213c2 port cpl to wasm (offset 612) 5cea3efcc port page_size_extensions to wasm (offset 616) 89d6fd6e8 port last_virt_eip to wasm (offset 620) 68f4111fd port eip_phys to wasm (offset 624) 73b146319 port last_virt_esp to wasm (offset 628) dbf920ff7 port esp_phys to wasm (offset 632) c05177c5a port sysenter_cs to wasm (offset 636) 63dd72194 port sysenter_esp to wasm (offset 640) 59d8aa686 port sysenter_eip to wasm (offset 644) c5e02dd8b port prefixes to wasm (offset 648) 259ca5d72 port tsc_offset to wasm (offset 652) 62ecc8825 port phys_addr to wasm (offset 656) 188ea275e port phys_addr_high to wasm (offset 660) f458cb2bb port timestamp_counter to wasm (offset 664) 890449fa3 port sreg to wasm (offsets 668-682) ebe65e6f3 port dreg to wasm (offsets 684-716) df6553220 port fw_value to wasm (offset 720) 0cd3b78ea port segment isnull, offsets and limits to wasm (offset 724-796) 4fb0ecebc Turn off verbose logging b55bc2cae fix unzip command in readme f5b897bc3 fix docs links to api.md ba03a7b4e Remove outdated test 930483ac4 Add elf parser 6597973c8 Shift addresses correctly 189903a7d Add comment to lss #ud 0a46ec4a9 Fix iret #gp error code (Windows XP) 28986b7ee Lower TIME_PER_FRAME 4ce987d71 Add acpi PM timer 43c31ea99 Handle access to debug registers when cr4.DE is set 283305215 Add run_hardware_timers c617846f2 A few more assertions for IO ports 32e7444f4 Make Closure Compiler happy a661c408c Buffer get written blocks 9306fd080 Add debug panel (#108) 795ff1a50 More complete APIC and IOAPIC implementation (#86) 4a4253956 Makefile: Refactor using addprefix ac1009331 More VGA logging 18ee4ecde Only check irqs when irr changed cdbc55e03 Add multiboot image loading, currently only supporting kvm-unit-test (#95, #129) 3ee9a1c85 Disable advanced optimisations for libv86. Fixes tests 12df5c76d Import kvm-unit-test into this repo 249f9ba37 Add kvm-unit-test (#129) 99b824f49 Mention than FreeBSD works 91fe8a3a1 ATA flush cache 0af630d99 PCI: Fix command/status 30fc01491 Rename function 569d1f3d6 APIC version write df376842c Split movsx/movzx into 16/32 bit versions dda21c5e2 CR3 ignored bits b1f039211 Implement #NP (kvm-unit-test) 57dd8358f Minor (style and logging) 17fd08e29 Less incomplete task switch implementation 797fd5bd8 cpuid level 5 24e66a43f Missing parameter a679829f0 PIC logging e68ea4573 Don't create new arrays in reset(), set to 0 instead 550e55186 Update readme regarding Arch Linux 3b565e54e Use local kolibriOS image on https. Temporary workaround for #141 1a0f804d6 Fix restoring state b397f1934 Leave ACPI disabled, fixes #151 83db7e871 add note about range header in SimpleHTTPServer a20794873 update linux 9p image mount hook doc 88e65312e Improve fprem instruction implementation to update FPU status word's condition codes 9844ef433 Remove comments from fprem instruction a429bbe73 Disable Oberon tests ba3092060 Add kvm-unit-test to travis CI (#129) 6a8813567 Travis fix 46da581de Travis fix (gcc-multilib) c78dcb105 Travis fix (switch to Trusty) dbc2ab704 Reduce memory for kvm-unit-test 2c6bd1889 Fix multiboot images smaller than 8192 bytes f5dead1f5 expand Archlinux doc with scripted install example a34cd08d9 fix raw RangeHTTPServer link to wget 35f9923fb change state to initial state in archlinux doc 2aed2636f extend archlinux doc with networking example 2aa8f3722 First entry in LDT is valid (#145) 7492c8d3c Basic 16-bit tss implementation. Fixes #127. Fixes #145. Fixes windows 3.0 098d84a02 Minor b9c93f8c6 Proper CD IDE DMA implementation, fixes #147, fixes #107 9b9123d6e Improved file loading in nodejs, simplify tests 40ee13f9b Add dummy screen a58bd7419 Fix test: Check if disk image is missing c8a7fd8dc Reenable Oberon tests bd63f49ad Minor: Semicolons d10f0b7ff Implement elcr in legacy pic aed5b441a Change virtio irq to 10, old one collides with ps2 mouse b93519c8a PS2 minor changes 25e64afa6 Update build command 5377f9457 Add maximum debug to emscripten build dac6ce6a4 Reduce logging f44f3b467 Convert argument for call from C e1808f222 Raise when C assertion fails bb6d38e6e Add cpu imports, in order to be called from C f3f909d5d Port constants 7bab32657 Port protected_mode, is_32 and stack_size_32 ee02cdd86 Port the main instruction table fe15a6cc0 fixes for prop mangling and closure type checks 11935fcc0 remove redundant pointer timestamp_counter a7021eb20 port read_imm8 to wasm f7a432691 strip useless brackets 90c7435f8 Reduce logging 047f0f405 Port a few small functions df293f8d4 Port get_seg* 37774b0d1 Remove useless comparison 47f7a89b9 Port instructions with 0F prefix 8a822bae4 Remove useless brackets again (lost in rebase) and use correct quote style 2f6e90023 port read_imm{8s,16,32s} 8f5ce2dbf remove redundant declaration 5785195ce port read_write_e8 and write_e8 5fa1a15af Make instruction functions static 4a2336d12 Port jmp_rel16, jmpcc8, jmpcc16, jmpcc32 8633cfad9 Port set_e* f024aec98 Port read_imm* aliases d39cb4d7b Port read_g* fa838388d Port read_e* 2f1c41d93 Port write_g* 43157269f Port logging and assertions ac2c937d5 Port read_write_e{16,32} and write_e{16,32} eeb7340c2 Port safe_read* 54d89b3d1 Port safe_write* c5557a227 Port diverged, branch_taken, branch_taken e3bb35939 Fix loading in node 00f6b2638 Remove useless `| 0` and `>> 0`. Use unsigned comparison 70fa762e3 Optimise read_imm8 4487917fd Port a20_enabled to wasm a8f16cb20 Fix a20_enabled booleans for closure compiler 95145ec53 Move mul32 result so offsets are reserved in order (and mention length) a3264e132 Move global pointer reservations to its own header file and make sure all .c files include all headers 78c779cbd Port FPU's stack_empty to wasm (offset 816) 4f25fc4b7 Port FPU's safe_tag_word function to wasm 8589a1c21 Port emms instruction to wasm feb5079c7 port memory_size to wasm (offset 812) 262559291 port in_mapped_range to C 8a72ad56c Port a20_enabled to wasm ce393e211 [wip] port read8 e936b49d1 port read8 to wasm 80cf98a3a port read16 to wasm 3a423372b port read_aligned16 to wasm 4725e1bac port read32s to wasm 60815b748 port write8 to wasm 5d64b295b port write16 to wasm 5fc83a791 port write32 to wasm 7148b6804 port push{16,32} to wasm 697222408 port pusha{16,32} to wasm 6adb5be15 Port paging, tlb_info, tlb_info_global and tlb_data c8ab560af Port translate_address_* 8bb3e4285 Port get_eflags and getzf c7a70a79b Port getsf 0d35dd621 Port getof e4d3ec252 Port getpf 9aacf2cfe Port test_* (branch conditions) 9cb64f970 Add v86-debug.wasm build target 37012099d Call mmap_* functions statically 8fb9da298 Add missing voids 0bcbe7ef4 Silence warning 6fb9db2fd Simplify translate_address_read and translate_address_write 28b66ca6b Optimized versions of resolve_modrm32 and resolve_sib cf4aea666 Silence warning b4915a2d2 Port adjust_stack_reg, get_stack_pointer and pop32s 7ddc14948 Optimised memory reads and writes --- .gitignore | 3 +- Makefile | 32 + src/arith.js | 583 ++++--- src/browser/lib.js | 36 + src/browser/starter.js | 189 +- src/config.js | 2 +- src/cpu.js | 1062 ++++++------ src/debug.js | 30 +- src/externs.js | 1 + src/fpu.js | 67 +- src/instructions.js | 818 +++++---- src/io.js | 4 +- src/ioapic.js | 2 +- src/log.js | 21 + src/main.js | 9 +- src/memory.js | 22 +- src/misc_instr.js | 76 +- src/native/all.c | 19 + src/native/arith.c | 825 +++++++++ src/native/const.h | 159 ++ src/native/cpu.c | 572 ++++++ src/native/fpu.c | 20 + src/native/global_pointers.h | 69 + src/native/instructions.c | 3171 ++++++++++++++++++++++++++++++++++ src/native/instructions_0f.c | 3155 +++++++++++++++++++++++++++++++++ src/native/log.c | 13 + src/native/memory.c | 112 ++ src/native/misc_instr.c | 232 +++ src/native/modrm.c | 230 +++ src/pci.js | 5 + src/string.js | 248 +-- src/virtio.js | 2 + tests/kvm-unit-tests/run.js | 2 +- 33 files changed, 10494 insertions(+), 1297 deletions(-) create mode 100644 src/native/all.c create mode 100644 src/native/arith.c create mode 100644 src/native/const.h create mode 100644 src/native/cpu.c create mode 100644 src/native/fpu.c create mode 100644 src/native/global_pointers.h create mode 100644 src/native/instructions.c create mode 100644 src/native/instructions_0f.c create mode 100644 src/native/log.c create mode 100644 src/native/memory.c create mode 100644 src/native/misc_instr.c create mode 100644 src/native/modrm.c diff --git a/.gitignore b/.gitignore index 70f4645f..8118bc7f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,8 +9,9 @@ closure-compiler/ images/ *.bak *.orig +*.wasm *.o *.bin *.img *.fixture -*.fuse_hidden* \ No newline at end of file +*.fuse_hidden* diff --git a/Makefile b/Makefile index 1dabe9cd..f22d696e 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,7 @@ NASM_TEST_DIR=./tests/nasm all: build/v86_all.js browser: build/v86_all.js +wasm: build/v86.wasm # Used for nodejs builds and in order to profile code. # `debug` gives identifiers a readable name, make sure it doesn't have any side effects. @@ -123,11 +124,42 @@ build/libv86.js: $(CLOSURE) src/*.js lib/*.js src/browser/*.js ls -lh build/libv86.js +build/v86.wasm: src/native/*.c src/native/*.h + mkdir -p build + -ls -lh build/v86.wasm + # --llvm-opts 3 + # -Wno-extra-semi + # EMCC_WASM_BACKEND=1 + emcc src/native/all.c \ + -Wall -Wpedantic -Wextra \ + -DDEBUG=false \ + -DNDEBUG \ + -Wno-bitwise-op-parentheses -Wno-gnu-binary-literal \ + -fcolor-diagnostics \ + -fwrapv \ + --llvm-opts 3 \ + -O3 \ + -g4 \ + -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 \ + -Wall -Wpedantic -Wextra \ + -Wno-bitwise-op-parentheses -Wno-gnu-binary-literal \ + -fcolor-diagnostics \ + -fwrapv \ + -Os \ + -g4 \ + -s WASM=1 -s SIDE_MODULE=1 -o build/v86-debug.wasm + ls -lh build/v86-debug.wasm + clean: -rm build/libv86.js -rm build/v86_all.js -rm build/libv86.js.map -rm build/v86_all.js.map + -rm build/v86.wasm $(MAKE) -C $(NASM_TEST_DIR) clean run: diff --git a/src/arith.js b/src/arith.js index 2bab9b6f..5334af8a 100644 --- a/src/arith.js +++ b/src/arith.js @@ -45,52 +45,52 @@ CPU.prototype.add = function(dest_operand, source_operand, op_size) { //if(this.safe_read32s(this.instruction_pointer + 1) === 0 && this.safe_read32s(this.instruction_pointer + 5) === 0) throw "0000000"; - this.last_op1 = dest_operand; - this.last_op2 = source_operand; - this.last_add_result = this.last_result = dest_operand + source_operand | 0; + this.last_op1[0] = dest_operand; + this.last_op2[0] = source_operand; + this.last_add_result[0] = this.last_result[0] = dest_operand + source_operand | 0; - this.last_op_size = op_size; - this.flags_changed = flags_all; + this.last_op_size[0] = op_size; + this.flags_changed[0] = flags_all; - return this.last_result; + return this.last_result[0]; } CPU.prototype.adc = function(dest_operand, source_operand, op_size) { var cf = this.getcf(); - this.last_op1 = dest_operand; - this.last_op2 = source_operand; - this.last_add_result = this.last_result = (dest_operand + source_operand | 0) + cf | 0; + this.last_op1[0] = dest_operand; + this.last_op2[0] = source_operand; + this.last_add_result[0] = this.last_result[0] = (dest_operand + source_operand | 0) + cf | 0; - this.last_op_size = op_size; - this.flags_changed = flags_all; + this.last_op_size[0] = op_size; + this.flags_changed[0] = flags_all; - return this.last_result; + return this.last_result[0]; } CPU.prototype.sub = function(dest_operand, source_operand, op_size) { - this.last_add_result = dest_operand; - this.last_op2 = source_operand; - this.last_op1 = this.last_result = dest_operand - source_operand | 0; + this.last_add_result[0] = dest_operand; + this.last_op2[0] = source_operand; + this.last_op1[0] = this.last_result[0] = dest_operand - source_operand | 0; - this.last_op_size = op_size; - this.flags_changed = flags_all; + this.last_op_size[0] = op_size; + this.flags_changed[0] = flags_all; - return this.last_result; + return this.last_result[0]; } CPU.prototype.sbb = function(dest_operand, source_operand, op_size) { var cf = this.getcf(); - this.last_add_result = dest_operand; - this.last_op2 = source_operand; - this.last_op1 = this.last_result = dest_operand - source_operand - cf | 0; - this.last_op_size = op_size; + this.last_add_result[0] = dest_operand; + this.last_op2[0] = source_operand; + this.last_op1[0] = this.last_result[0] = dest_operand - source_operand - cf | 0; + this.last_op_size[0] = op_size; - this.flags_changed = flags_all; + this.flags_changed[0] = flags_all; - return this.last_result; + return this.last_result[0]; } /* @@ -107,28 +107,28 @@ CPU.prototype.dec32 = function(dest) { return this.dec(dest, OPSIZE_32); } CPU.prototype.inc = function(dest_operand, op_size) { - this.flags = (this.flags & ~1) | this.getcf(); - this.last_op1 = dest_operand; - this.last_op2 = 1; - this.last_add_result = this.last_result = dest_operand + 1 | 0; - this.last_op_size = op_size; + this.flags[0] = (this.flags[0] & ~1) | this.getcf(); + this.last_op1[0] = dest_operand; + this.last_op2[0] = 1; + this.last_add_result[0] = this.last_result[0] = dest_operand + 1 | 0; + this.last_op_size[0] = op_size; - this.flags_changed = flags_all & ~1; + this.flags_changed[0] = flags_all & ~1; - return this.last_result; + return this.last_result[0]; } CPU.prototype.dec = function(dest_operand, op_size) { - this.flags = (this.flags & ~1) | this.getcf(); - this.last_add_result = dest_operand; - this.last_op2 = 1; - this.last_op1 = this.last_result = dest_operand - 1 | 0; - this.last_op_size = op_size; + this.flags[0] = (this.flags[0] & ~1) | this.getcf(); + this.last_add_result[0] = dest_operand; + this.last_op2[0] = 1; + this.last_op1[0] = this.last_result[0] = dest_operand - 1 | 0; + this.last_op_size[0] = op_size; - this.flags_changed = flags_all & ~1; + this.flags_changed[0] = flags_all & ~1; - return this.last_result; + return this.last_result[0]; } @@ -141,17 +141,16 @@ CPU.prototype.neg32 = function(dest) { return this.neg(dest, OPSIZE_32); } CPU.prototype.neg = function(dest_operand, op_size) { - this.last_op1 = this.last_result = -dest_operand | 0; + this.last_op1[0] = this.last_result[0] = -dest_operand | 0; - this.flags_changed = flags_all; - this.last_add_result = 0; - this.last_op2 = dest_operand; - this.last_op_size = op_size; + this.flags_changed[0] = flags_all; + this.last_add_result[0] = 0; + this.last_op2[0] = dest_operand; + this.last_op_size[0] = op_size; - return this.last_result; + return this.last_result[0]; } - /* * mul, imul, div, idiv * @@ -165,19 +164,19 @@ CPU.prototype.mul8 = function(source_operand) var result = source_operand * this.reg8[reg_al]; this.reg16[reg_ax] = result; - this.last_result = result & 0xFF; - this.last_op_size = OPSIZE_8; + this.last_result[0] = result & 0xFF; + this.last_op_size[0] = OPSIZE_8; if(result < 0x100) { - this.flags = this.flags & ~1 & ~flag_overflow; + this.flags[0] = this.flags[0] & ~1 & ~flag_overflow; } else { - this.flags = this.flags | 1 | flag_overflow; + this.flags[0] = this.flags[0] | 1 | flag_overflow; } - this.flags_changed = flags_all & ~1 & ~flag_overflow; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow; } CPU.prototype.imul8 = function(source_operand) @@ -185,18 +184,18 @@ CPU.prototype.imul8 = function(source_operand) var result = source_operand * this.reg8s[reg_al]; this.reg16[reg_ax] = result; - this.last_result = result & 0xFF; - this.last_op_size = OPSIZE_8; + this.last_result[0] = result & 0xFF; + this.last_op_size[0] = OPSIZE_8; if(result > 0x7F || result < -0x80) { - this.flags = this.flags | 1 | flag_overflow; + this.flags[0] = this.flags[0] | 1 | flag_overflow; } else { - this.flags = this.flags & ~1 & ~flag_overflow; + this.flags[0] = this.flags[0] & ~1 & ~flag_overflow; } - this.flags_changed = flags_all & ~1 & ~flag_overflow; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow; } CPU.prototype.mul16 = function(source_operand) @@ -208,18 +207,18 @@ CPU.prototype.mul16 = function(source_operand) this.reg16[reg_ax] = result; this.reg16[reg_dx] = high_result; - this.last_result = result & 0xFFFF; - this.last_op_size = OPSIZE_16; + this.last_result[0] = result & 0xFFFF; + this.last_op_size[0] = OPSIZE_16; if(high_result === 0) { - this.flags &= ~1 & ~flag_overflow; + this.flags[0] &= ~1 & ~flag_overflow; } else { - this.flags |= 1 | flag_overflow; + this.flags[0] |= 1 | flag_overflow; } - this.flags_changed = flags_all & ~1 & ~flag_overflow; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow; } /* @@ -233,18 +232,18 @@ CPU.prototype.imul16 = function(source_operand) this.reg16[reg_ax] = result; this.reg16[reg_dx] = result >> 16; - this.last_result = result & 0xFFFF; - this.last_op_size = OPSIZE_16; + this.last_result[0] = result & 0xFFFF; + this.last_op_size[0] = OPSIZE_16; if(result > 0x7FFF || result < -0x8000) { - this.flags |= 1 | flag_overflow; + this.flags[0] |= 1 | flag_overflow; } else { - this.flags &= ~1 & ~flag_overflow; + this.flags[0] &= ~1 & ~flag_overflow; } - this.flags_changed = flags_all & ~1 & ~flag_overflow; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow; } /* @@ -259,18 +258,18 @@ CPU.prototype.imul_reg16 = function(operand1, operand2) var result = operand1 * operand2; - this.last_result = result & 0xFFFF; - this.last_op_size = OPSIZE_16; + this.last_result[0] = result & 0xFFFF; + this.last_op_size[0] = OPSIZE_16; if(result > 0x7FFF || result < -0x8000) { - this.flags |= 1 | flag_overflow; + this.flags[0] |= 1 | flag_overflow; } else { - this.flags &= ~1 & ~flag_overflow; + this.flags[0] &= ~1 & ~flag_overflow; } - this.flags_changed = flags_all & ~1 & ~flag_overflow; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow; return result; } @@ -290,6 +289,14 @@ CPU.prototype.do_mul32 = function(a, b) return this.mul32_result; }; +//XXX: do_mul32 returns a typedarray object which we can't do from a wasm +//function, so we rewrite it here differently from other ports. Would +//change this when callers of do_mul32 are rewritten in wasm. +CPU.prototype.do_mul32 = function(a, b) { + this.wm.funcs['_do_mul32'](a, b); + return this.mul32_result; +}; + CPU.prototype.do_imul32 = function(a, b) { var is_neg = false; @@ -309,6 +316,12 @@ CPU.prototype.do_imul32 = function(a, b) return result; } +//XXX: same issue as do_mul32. rewrite after callers are ported to wasm +CPU.prototype.do_imul32 = function(a, b) { + this.wm.funcs['_do_imul32'](a, b); + return this.mul32_result; +}; + CPU.prototype.mul32 = function(source_operand) { var dest_operand = this.reg32s[reg_eax]; @@ -318,18 +331,18 @@ CPU.prototype.mul32 = function(source_operand) this.reg32s[reg_eax] = result[0]; this.reg32s[reg_edx] = result[1]; - this.last_result = result[0]; - this.last_op_size = OPSIZE_32; + this.last_result[0] = result[0]; + this.last_op_size[0] = OPSIZE_32; if(result[1] === 0) { - this.flags &= ~1 & ~flag_overflow; + this.flags[0] &= ~1 & ~flag_overflow; } else { - this.flags |= 1 | flag_overflow; + this.flags[0] |= 1 | flag_overflow; } - this.flags_changed = flags_all & ~1 & ~flag_overflow; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow; //console.log(h(source_operand >>> 0, 8) + " * " + h(dest_operand >>> 0, 8)); //console.log("= " + h(this.reg32[reg_edx], 8) + ":" + h(this.reg32[reg_eax], 8)); @@ -346,18 +359,18 @@ CPU.prototype.imul32 = function(source_operand) this.reg32s[reg_eax] = result[0]; this.reg32s[reg_edx] = result[1]; - this.last_result = result[0]; - this.last_op_size = OPSIZE_32; + this.last_result[0] = result[0]; + this.last_op_size[0] = OPSIZE_32; if(result[1] === (result[0] >> 31)) { - this.flags &= ~1 & ~flag_overflow; + this.flags[0] &= ~1 & ~flag_overflow; } else { - this.flags |= 1 | flag_overflow; + this.flags[0] |= 1 | flag_overflow; } - this.flags_changed = flags_all & ~1 & ~flag_overflow; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow; //console.log(target_operand + " * " + source_operand); //console.log("= " + h(this.reg32[reg_edx]) + " " + h(this.reg32[reg_eax])); @@ -375,18 +388,18 @@ CPU.prototype.imul_reg32 = function(operand1, operand2) var result = this.do_imul32(operand1, operand2); - this.last_result = result[0]; - this.last_op_size = OPSIZE_32; + this.last_result[0] = result[0]; + this.last_op_size[0] = OPSIZE_32; if(result[1] === (result[0] >> 31)) { - this.flags &= ~1 & ~flag_overflow; + this.flags[0] &= ~1 & ~flag_overflow; } else { - this.flags |= 1 | flag_overflow; + this.flags[0] |= 1 | flag_overflow; } - this.flags_changed = flags_all & ~1 & ~flag_overflow; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow; return result[0]; @@ -502,7 +515,7 @@ CPU.prototype.do_div32 = function(div_low, div_high, quot) this.trigger_de(); } - var result = 0; + var result = 0; if(div_high > 0x100000) { @@ -545,6 +558,7 @@ CPU.prototype.do_div32 = function(div_low, div_high, quot) CPU.prototype.div32 = function(source_operand) { + source_operand >>>= 0; dbg_assert(source_operand >= 0 && source_operand <= 0xffffffff); var dest_operand_low = this.reg32[reg_eax], @@ -666,23 +680,23 @@ CPU.prototype.bcd_daa = function() old_cf = this.getcf(), old_af = this.getaf(); - this.flags &= ~1 & ~flag_adjust + this.flags[0] &= ~1 & ~flag_adjust if((old_al & 0xF) > 9 || old_af) { this.reg8[reg_al] += 6; - this.flags |= flag_adjust; + this.flags[0] |= flag_adjust; } if(old_al > 0x99 || old_cf) { this.reg8[reg_al] += 0x60; - this.flags |= 1; + this.flags[0] |= 1; } - this.last_result = this.reg8[reg_al]; - this.last_op_size = OPSIZE_8; - this.last_op1 = this.last_op2 = 0; - this.flags_changed = flags_all & ~1 & ~flag_adjust & ~flag_overflow; + this.last_result[0] = this.reg8[reg_al]; + this.last_op_size[0] = OPSIZE_8; + this.last_op1[0] = this.last_op2[0] = 0; + this.flags_changed[0] = flags_all & ~1 & ~flag_adjust & ~flag_overflow; } CPU.prototype.bcd_das = function() @@ -692,29 +706,29 @@ CPU.prototype.bcd_das = function() var old_al = this.reg8[reg_al], old_cf = this.getcf(); - this.flags &= ~1; + this.flags[0] &= ~1; if((old_al & 0xF) > 9 || this.getaf()) { this.reg8[reg_al] -= 6; - this.flags |= flag_adjust; - this.flags = this.flags & ~1 | old_cf | (old_al < 6); + this.flags[0] |= flag_adjust; + this.flags[0] = this.flags[0] & ~1 | old_cf | (old_al < 6); } else { - this.flags &= ~flag_adjust; + this.flags[0] &= ~flag_adjust; } if(old_al > 0x99 || old_cf) { this.reg8[reg_al] -= 0x60; - this.flags |= 1; + this.flags[0] |= 1; } - this.last_result = this.reg8[reg_al]; - this.last_op_size = OPSIZE_8; - this.last_op1 = this.last_op2 = 0; - this.flags_changed = flags_all & ~1 & ~flag_adjust & ~flag_overflow; + this.last_result[0] = this.reg8[reg_al]; + this.last_op_size[0] = OPSIZE_8; + this.last_op1[0] = this.last_op2[0] = 0; + this.flags_changed[0] = flags_all & ~1 & ~flag_adjust & ~flag_overflow; } CPU.prototype.bcd_aam = function(imm8) @@ -732,10 +746,10 @@ CPU.prototype.bcd_aam = function(imm8) this.reg8[reg_ah] = temp / imm8; this.reg8[reg_al] = temp % imm8; - this.last_result = this.reg8[reg_al]; + this.last_result[0] = this.reg8[reg_al]; - this.flags_changed = flags_all & ~1 & ~flag_adjust & ~flag_overflow; - this.flags &= ~1 & ~flag_adjust & ~flag_overflow; + this.flags_changed[0] = flags_all & ~1 & ~flag_adjust & ~flag_overflow; + this.flags[0] &= ~1 & ~flag_adjust & ~flag_overflow; } } @@ -745,16 +759,16 @@ CPU.prototype.bcd_aad = function(imm8) // ascii adjust before division var result = this.reg8[reg_al] + this.reg8[reg_ah] * imm8; - this.last_result = result & 0xFF; - this.reg16[reg_ax] = this.last_result; - this.last_op_size = OPSIZE_8; + this.last_result[0] = result & 0xFF; + this.reg16[reg_ax] = this.last_result[0]; + this.last_op_size[0] = OPSIZE_8; - this.flags_changed = flags_all & ~1 & ~flag_adjust & ~flag_overflow; - this.flags &= ~1 & ~flag_adjust & ~flag_overflow; + this.flags_changed[0] = flags_all & ~1 & ~flag_adjust & ~flag_overflow; + this.flags[0] &= ~1 & ~flag_adjust & ~flag_overflow; if(result > 0xFFFF) { - this.flags |= 1; + this.flags[0] |= 1; } } @@ -765,15 +779,15 @@ CPU.prototype.bcd_aaa = function() { this.reg16[reg_ax] += 6; this.reg8[reg_ah] += 1; - this.flags |= flag_adjust | 1; + this.flags[0] |= flag_adjust | 1; } else { - this.flags &= ~flag_adjust & ~1; + this.flags[0] &= ~flag_adjust & ~1; } this.reg8[reg_al] &= 0xF; - this.flags_changed &= ~flag_adjust & ~1; + this.flags_changed[0] &= ~flag_adjust & ~1; }; @@ -784,15 +798,15 @@ CPU.prototype.bcd_aas = function() { this.reg16[reg_ax] -= 6; this.reg8[reg_ah] -= 1; - this.flags |= flag_adjust | 1; + this.flags[0] |= flag_adjust | 1; } else { - this.flags &= ~flag_adjust & ~1; + this.flags[0] &= ~flag_adjust & ~1; } this.reg8[reg_al] &= 0xF; - this.flags_changed &= ~flag_adjust & ~1; + this.flags_changed[0] &= ~flag_adjust & ~1; } @@ -826,35 +840,35 @@ CPU.prototype.xor32 = function(dest, src) { return this.xor(dest, src, OPSIZE_32 CPU.prototype.and = function(dest_operand, source_operand, op_size) { - this.last_result = dest_operand & source_operand; + this.last_result[0] = dest_operand & source_operand; - this.last_op_size = op_size; - this.flags &= ~1 & ~flag_overflow & ~flag_adjust; - this.flags_changed = flags_all & ~1 & ~flag_overflow & ~flag_adjust; + this.last_op_size[0] = op_size; + this.flags[0] &= ~1 & ~flag_overflow & ~flag_adjust; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow & ~flag_adjust; - return this.last_result; + return this.last_result[0]; } CPU.prototype.or = function(dest_operand, source_operand, op_size) { - this.last_result = dest_operand | source_operand; + this.last_result[0] = dest_operand | source_operand; - this.last_op_size = op_size; - this.flags &= ~1 & ~flag_overflow & ~flag_adjust; - this.flags_changed = flags_all & ~1 & ~flag_overflow & ~flag_adjust; + this.last_op_size[0] = op_size; + this.flags[0] &= ~1 & ~flag_overflow & ~flag_adjust; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow & ~flag_adjust; - return this.last_result; + return this.last_result[0]; } CPU.prototype.xor = function(dest_operand, source_operand, op_size) { - this.last_result = dest_operand ^ source_operand; + this.last_result[0] = dest_operand ^ source_operand; - this.last_op_size = op_size; - this.flags &= ~1 & ~flag_overflow & ~flag_adjust; - this.flags_changed = flags_all & ~1 & ~flag_overflow & ~flag_adjust; + this.last_op_size[0] = op_size; + this.flags[0] &= ~1 & ~flag_overflow & ~flag_adjust; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow & ~flag_adjust; - return this.last_result; + return this.last_result[0]; } @@ -872,8 +886,8 @@ CPU.prototype.rol8 = function(dest_operand, count) var result = dest_operand << count | dest_operand >> (8 - count); - this.flags_changed &= ~1 & ~flag_overflow; - this.flags = (this.flags & ~1 & ~flag_overflow) + this.flags_changed[0] &= ~1 & ~flag_overflow; + this.flags[0] = (this.flags[0] & ~1 & ~flag_overflow) | (result & 1) | (result << 11 ^ result << 4) & flag_overflow; @@ -890,8 +904,8 @@ CPU.prototype.rol16 = function(dest_operand, count) var result = dest_operand << count | dest_operand >> (16 - count); - this.flags_changed &= ~1 & ~flag_overflow; - this.flags = (this.flags & ~1 & ~flag_overflow) + this.flags_changed[0] &= ~1 & ~flag_overflow; + this.flags[0] = (this.flags[0] & ~1 & ~flag_overflow) | (result & 1) | (result << 11 ^ result >> 4) & flag_overflow; @@ -907,8 +921,8 @@ CPU.prototype.rol32 = function(dest_operand, count) var result = dest_operand << count | dest_operand >>> (32 - count); - this.flags_changed &= ~1 & ~flag_overflow; - this.flags = (this.flags & ~1 & ~flag_overflow) + this.flags_changed[0] &= ~1 & ~flag_overflow; + this.flags[0] = (this.flags[0] & ~1 & ~flag_overflow) | (result & 1) | (result << 11 ^ result >> 20) & flag_overflow; @@ -925,8 +939,8 @@ CPU.prototype.rcl8 = function(dest_operand, count) var result = dest_operand << count | this.getcf() << (count - 1) | dest_operand >> (9 - count); - this.flags_changed &= ~1 & ~flag_overflow; - this.flags = (this.flags & ~1 & ~flag_overflow) + this.flags_changed[0] &= ~1 & ~flag_overflow; + this.flags[0] = (this.flags[0] & ~1 & ~flag_overflow) | (result >> 8 & 1) | (result << 3 ^ result << 4) & flag_overflow; @@ -943,8 +957,8 @@ CPU.prototype.rcl16 = function(dest_operand, count) var result = dest_operand << count | this.getcf() << (count - 1) | dest_operand >> (17 - count); - this.flags_changed &= ~1 & ~flag_overflow; - this.flags = (this.flags & ~1 & ~flag_overflow) + this.flags_changed[0] &= ~1 & ~flag_overflow; + this.flags[0] = (this.flags[0] & ~1 & ~flag_overflow) | (result >> 16 & 1) | (result >> 5 ^ result >> 4) & flag_overflow; @@ -965,9 +979,9 @@ CPU.prototype.rcl32 = function(dest_operand, count) result |= dest_operand >>> (33 - count); } - this.flags_changed &= ~1 & ~flag_overflow; - this.flags = (this.flags & ~1 & ~flag_overflow) | (dest_operand >>> (32 - count) & 1); - this.flags |= (this.flags << 11 ^ result >> 20) & flag_overflow; + this.flags_changed[0] &= ~1 & ~flag_overflow; + this.flags[0] = (this.flags[0] & ~1 & ~flag_overflow) | (dest_operand >>> (32 - count) & 1); + this.flags[0] |= (this.flags[0] << 11 ^ result >> 20) & flag_overflow; return result; } @@ -982,8 +996,8 @@ CPU.prototype.ror8 = function(dest_operand, count) count &= 7; var result = dest_operand >> count | dest_operand << (8 - count); - this.flags_changed &= ~1 & ~flag_overflow; - this.flags = (this.flags & ~1 & ~flag_overflow) + this.flags_changed[0] &= ~1 & ~flag_overflow; + this.flags[0] = (this.flags[0] & ~1 & ~flag_overflow) | (result >> 7 & 1) | (result << 4 ^ result << 5) & flag_overflow; @@ -1000,8 +1014,8 @@ CPU.prototype.ror16 = function(dest_operand, count) count &= 15; var result = dest_operand >> count | dest_operand << (16 - count); - this.flags_changed &= ~1 & ~flag_overflow; - this.flags = (this.flags & ~1 & ~flag_overflow) + this.flags_changed[0] &= ~1 & ~flag_overflow; + this.flags[0] = (this.flags[0] & ~1 & ~flag_overflow) | (result >> 15 & 1) | (result >> 4 ^ result >> 3) & flag_overflow; @@ -1017,8 +1031,8 @@ CPU.prototype.ror32 = function(dest_operand, count) var result = dest_operand >>> count | dest_operand << (32 - count); - this.flags_changed &= ~1 & ~flag_overflow; - this.flags = (this.flags & ~1 & ~flag_overflow) + this.flags_changed[0] &= ~1 & ~flag_overflow; + this.flags[0] = (this.flags[0] & ~1 & ~flag_overflow) | (result >> 31 & 1) | (result >> 20 ^ result >> 19) & flag_overflow; @@ -1035,8 +1049,8 @@ CPU.prototype.rcr8 = function(dest_operand, count) var result = dest_operand >> count | this.getcf() << (8 - count) | dest_operand << (9 - count); - this.flags_changed &= ~1 & ~flag_overflow; - this.flags = (this.flags & ~1 & ~flag_overflow) + this.flags_changed[0] &= ~1 & ~flag_overflow; + this.flags[0] = (this.flags[0] & ~1 & ~flag_overflow) | (result >> 8 & 1) | (result << 4 ^ result << 5) & flag_overflow; @@ -1053,8 +1067,8 @@ CPU.prototype.rcr16 = function(dest_operand, count) var result = dest_operand >> count | this.getcf() << (16 - count) | dest_operand << (17 - count); - this.flags_changed &= ~1 & ~flag_overflow; - this.flags = (this.flags & ~1 & ~flag_overflow) + this.flags_changed[0] &= ~1 & ~flag_overflow; + this.flags[0] = (this.flags[0] & ~1 & ~flag_overflow) | (result >> 16 & 1) | (result >> 4 ^ result >> 3) & flag_overflow; @@ -1075,8 +1089,8 @@ CPU.prototype.rcr32 = function(dest_operand, count) result |= dest_operand << (33 - count); } - this.flags_changed &= ~1 & ~flag_overflow; - this.flags = (this.flags & ~1 & ~flag_overflow) + this.flags_changed[0] &= ~1 & ~flag_overflow; + this.flags[0] = (this.flags[0] & ~1 & ~flag_overflow) | (dest_operand >> (count - 1) & 1) | (result >> 20 ^ result >> 19) & flag_overflow; @@ -1090,15 +1104,15 @@ CPU.prototype.shl8 = function(dest_operand, count) return dest_operand; } - this.last_result = dest_operand << count; + this.last_result[0] = dest_operand << count; - this.last_op_size = OPSIZE_8; - this.flags_changed = flags_all & ~1 & ~flag_overflow; - this.flags = (this.flags & ~1 & ~flag_overflow) - | (this.last_result >> 8 & 1) - | (this.last_result << 3 ^ this.last_result << 4) & flag_overflow; + this.last_op_size[0] = OPSIZE_8; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow; + this.flags[0] = (this.flags[0] & ~1 & ~flag_overflow) + | (this.last_result[0] >> 8 & 1) + | (this.last_result[0] << 3 ^ this.last_result[0] << 4) & flag_overflow; - return this.last_result; + return this.last_result[0]; } CPU.prototype.shl16 = function(dest_operand, count) @@ -1108,15 +1122,15 @@ CPU.prototype.shl16 = function(dest_operand, count) return dest_operand; } - this.last_result = dest_operand << count; + this.last_result[0] = dest_operand << count; - this.last_op_size = OPSIZE_16; - this.flags_changed = flags_all & ~1 & ~flag_overflow; - this.flags = (this.flags & ~1 & ~flag_overflow) - | (this.last_result >> 16 & 1) - | (this.last_result >> 5 ^ this.last_result >> 4) & flag_overflow; + this.last_op_size[0] = OPSIZE_16; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow; + this.flags[0] = (this.flags[0] & ~1 & ~flag_overflow) + | (this.last_result[0] >> 16 & 1) + | (this.last_result[0] >> 5 ^ this.last_result[0] >> 4) & flag_overflow; - return this.last_result; + return this.last_result[0]; } CPU.prototype.shl32 = function(dest_operand, count) @@ -1126,15 +1140,15 @@ CPU.prototype.shl32 = function(dest_operand, count) return dest_operand; } - this.last_result = dest_operand << count; + this.last_result[0] = dest_operand << count; - this.last_op_size = OPSIZE_32; - this.flags_changed = flags_all & ~1 & ~flag_overflow; + this.last_op_size[0] = OPSIZE_32; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow; // test this - this.flags = (this.flags & ~1 & ~flag_overflow) | (dest_operand >>> (32 - count) & 1); - this.flags |= ((this.flags & 1) ^ (this.last_result >> 31 & 1)) << 11 & flag_overflow; + this.flags[0] = (this.flags[0] & ~1 & ~flag_overflow) | (dest_operand >>> (32 - count) & 1); + this.flags[0] |= ((this.flags[0] & 1) ^ (this.last_result[0] >> 31 & 1)) << 11 & flag_overflow; - return this.last_result; + return this.last_result[0]; } CPU.prototype.shr8 = function(dest_operand, count) @@ -1144,15 +1158,15 @@ CPU.prototype.shr8 = function(dest_operand, count) return dest_operand; } - this.last_result = dest_operand >> count; + this.last_result[0] = dest_operand >> count; - this.last_op_size = OPSIZE_8; - this.flags_changed = flags_all & ~1 & ~flag_overflow; - this.flags = (this.flags & ~1 & ~flag_overflow) + this.last_op_size[0] = OPSIZE_8; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow; + this.flags[0] = (this.flags[0] & ~1 & ~flag_overflow) | (dest_operand >> (count - 1) & 1) | (dest_operand >> 7 & 1) << 11 & flag_overflow; - return this.last_result; + return this.last_result[0]; } CPU.prototype.shr16 = function(dest_operand, count) @@ -1162,15 +1176,15 @@ CPU.prototype.shr16 = function(dest_operand, count) return dest_operand; } - this.last_result = dest_operand >> count; + this.last_result[0] = dest_operand >> count; - this.last_op_size = OPSIZE_16; - this.flags_changed = flags_all & ~1 & ~flag_overflow; - this.flags = (this.flags & ~1 & ~flag_overflow) + this.last_op_size[0] = OPSIZE_16; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow; + this.flags[0] = (this.flags[0] & ~1 & ~flag_overflow) | (dest_operand >> (count - 1) & 1) | (dest_operand >> 4) & flag_overflow; - return this.last_result; + return this.last_result[0]; } CPU.prototype.shr32 = function(dest_operand, count) @@ -1180,15 +1194,15 @@ CPU.prototype.shr32 = function(dest_operand, count) return dest_operand; } - this.last_result = dest_operand >>> count; + this.last_result[0] = dest_operand >>> count; - this.last_op_size = OPSIZE_32; - this.flags_changed = flags_all & ~1 & ~flag_overflow; - this.flags = (this.flags & ~1 & ~flag_overflow) + this.last_op_size[0] = OPSIZE_32; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow; + this.flags[0] = (this.flags[0] & ~1 & ~flag_overflow) | (dest_operand >>> (count - 1) & 1) | (dest_operand >> 20) & flag_overflow; - return this.last_result; + return this.last_result[0]; } CPU.prototype.sar8 = function(dest_operand, count) @@ -1200,20 +1214,20 @@ CPU.prototype.sar8 = function(dest_operand, count) if(count < 8) { - this.last_result = dest_operand << 24 >> count + 24; + this.last_result[0] = dest_operand << 24 >> count + 24; // of is zero - this.flags = (this.flags & ~1 & ~flag_overflow) | (dest_operand >> (count - 1) & 1); + this.flags[0] = (this.flags[0] & ~1 & ~flag_overflow) | (dest_operand >> (count - 1) & 1); } else { - this.last_result = dest_operand << 24 >> 31; - this.flags = (this.flags & ~1 & ~flag_overflow) | (this.last_result & 1); + this.last_result[0] = dest_operand << 24 >> 31; + this.flags[0] = (this.flags[0] & ~1 & ~flag_overflow) | (this.last_result[0] & 1); } - this.last_op_size = OPSIZE_8; - this.flags_changed = flags_all & ~1 & ~flag_overflow; + this.last_op_size[0] = OPSIZE_8; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow; - return this.last_result; + return this.last_result[0]; } CPU.prototype.sar16 = function(dest_operand, count) @@ -1225,19 +1239,19 @@ CPU.prototype.sar16 = function(dest_operand, count) if(count < 16) { - this.last_result = dest_operand << 16 >> count + 16; - this.flags = (this.flags & ~1 & ~flag_overflow) | (dest_operand >> (count - 1) & 1); + this.last_result[0] = dest_operand << 16 >> count + 16; + this.flags[0] = (this.flags[0] & ~1 & ~flag_overflow) | (dest_operand >> (count - 1) & 1); } else { - this.last_result = dest_operand << 16 >> 31; - this.flags = (this.flags & ~1 & ~flag_overflow) | (this.last_result & 1); + this.last_result[0] = dest_operand << 16 >> 31; + this.flags[0] = (this.flags[0] & ~1 & ~flag_overflow) | (this.last_result[0] & 1); } - this.last_op_size = OPSIZE_16; - this.flags_changed = flags_all & ~1 & ~flag_overflow; + this.last_op_size[0] = OPSIZE_16; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow; - return this.last_result; + return this.last_result[0]; } CPU.prototype.sar32 = function(dest_operand, count) @@ -1247,13 +1261,13 @@ CPU.prototype.sar32 = function(dest_operand, count) return dest_operand; } - this.last_result = dest_operand >> count; + this.last_result[0] = dest_operand >> count; - this.last_op_size = OPSIZE_32; - this.flags_changed = flags_all & ~1 & ~flag_overflow; - this.flags = (this.flags & ~1 & ~flag_overflow) | (dest_operand >>> (count - 1) & 1); + this.last_op_size[0] = OPSIZE_32; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow; + this.flags[0] = (this.flags[0] & ~1 & ~flag_overflow) | (dest_operand >>> (count - 1) & 1); - return this.last_result; + return this.last_result[0]; } @@ -1266,20 +1280,20 @@ CPU.prototype.shrd16 = function(dest_operand, source_operand, count) if(count <= 16) { - this.last_result = dest_operand >> count | source_operand << (16 - count); - this.flags = (this.flags & ~1) | (dest_operand >> (count - 1) & 1); + this.last_result[0] = dest_operand >> count | source_operand << (16 - count); + this.flags[0] = (this.flags[0] & ~1) | (dest_operand >> (count - 1) & 1); } else { - this.last_result = dest_operand << (32 - count) | source_operand >> (count - 16); - this.flags = (this.flags & ~1) | (source_operand >> (count - 17) & 1); + this.last_result[0] = dest_operand << (32 - count) | source_operand >> (count - 16); + this.flags[0] = (this.flags[0] & ~1) | (source_operand >> (count - 17) & 1); } - this.last_op_size = OPSIZE_16; - this.flags_changed = flags_all & ~1 & ~flag_overflow; - this.flags = (this.flags & ~flag_overflow) | ((this.last_result ^ dest_operand) >> 4 & flag_overflow); + this.last_op_size[0] = OPSIZE_16; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow; + this.flags[0] = (this.flags[0] & ~flag_overflow) | ((this.last_result[0] ^ dest_operand) >> 4 & flag_overflow); - return this.last_result; + return this.last_result[0]; } CPU.prototype.shrd32 = function(dest_operand, source_operand, count) @@ -1289,14 +1303,14 @@ CPU.prototype.shrd32 = function(dest_operand, source_operand, count) return dest_operand; } - this.last_result = dest_operand >>> count | source_operand << (32 - count); + this.last_result[0] = dest_operand >>> count | source_operand << (32 - count); - this.last_op_size = OPSIZE_32; - this.flags_changed = flags_all & ~1 & ~flag_overflow; - this.flags = (this.flags & ~1) | (dest_operand >>> (count - 1) & 1); - this.flags = (this.flags & ~flag_overflow) | ((this.last_result ^ dest_operand) >> 20 & flag_overflow); + this.last_op_size[0] = OPSIZE_32; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow; + this.flags[0] = (this.flags[0] & ~1) | (dest_operand >>> (count - 1) & 1); + this.flags[0] = (this.flags[0] & ~flag_overflow) | ((this.last_result[0] ^ dest_operand) >> 20 & flag_overflow); - return this.last_result; + return this.last_result[0]; } CPU.prototype.shld16 = function(dest_operand, source_operand, count) @@ -1308,20 +1322,20 @@ CPU.prototype.shld16 = function(dest_operand, source_operand, count) if(count <= 16) { - this.last_result = dest_operand << count | source_operand >>> (16 - count); - this.flags = (this.flags & ~1) | (dest_operand >>> (16 - count) & 1); + this.last_result[0] = dest_operand << count | source_operand >>> (16 - count); + this.flags[0] = (this.flags[0] & ~1) | (dest_operand >>> (16 - count) & 1); } else { - this.last_result = dest_operand >> (32 - count) | source_operand << (count - 16); - this.flags = (this.flags & ~1) | (source_operand >>> (32 - count) & 1); + this.last_result[0] = dest_operand >> (32 - count) | source_operand << (count - 16); + this.flags[0] = (this.flags[0] & ~1) | (source_operand >>> (32 - count) & 1); } - this.last_op_size = OPSIZE_16; - this.flags_changed = flags_all & ~1 & ~flag_overflow; - this.flags = (this.flags & ~flag_overflow) | ((this.flags & 1) ^ (this.last_result >> 15 & 1)) << 11; + this.last_op_size[0] = OPSIZE_16; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow; + this.flags[0] = (this.flags[0] & ~flag_overflow) | ((this.flags[0] & 1) ^ (this.last_result[0] >> 15 & 1)) << 11; - return this.last_result; + return this.last_result[0]; } CPU.prototype.shld32 = function(dest_operand, source_operand, count) @@ -1331,51 +1345,51 @@ CPU.prototype.shld32 = function(dest_operand, source_operand, count) return dest_operand; } - this.last_result = dest_operand << count | source_operand >>> (32 - count); + this.last_result[0] = dest_operand << count | source_operand >>> (32 - count); - this.last_op_size = OPSIZE_32; - this.flags_changed = flags_all & ~1 & ~flag_overflow; - this.flags = (this.flags & ~1) | (dest_operand >>> (32 - count) & 1); + this.last_op_size[0] = OPSIZE_32; + this.flags_changed[0] = flags_all & ~1 & ~flag_overflow; + this.flags[0] = (this.flags[0] & ~1) | (dest_operand >>> (32 - count) & 1); if(count === 1) { - this.flags = (this.flags & ~flag_overflow) | ((this.flags & 1) ^ (this.last_result >> 31 & 1)) << 11; + this.flags[0] = (this.flags[0] & ~flag_overflow) | ((this.flags[0] & 1) ^ (this.last_result[0] >> 31 & 1)) << 11; } else { - this.flags &= ~flag_overflow; + this.flags[0] &= ~flag_overflow; } - return this.last_result; + return this.last_result[0]; } CPU.prototype.bt_reg = function(bit_base, bit_offset) { - this.flags = (this.flags & ~1) | (bit_base >> bit_offset & 1); - this.flags_changed &= ~1; + this.flags[0] = (this.flags[0] & ~1) | (bit_base >> bit_offset & 1); + this.flags_changed[0] &= ~1; } CPU.prototype.btc_reg = function(bit_base, bit_offset) { - this.flags = (this.flags & ~1) | (bit_base >> bit_offset & 1); - this.flags_changed &= ~1; + this.flags[0] = (this.flags[0] & ~1) | (bit_base >> bit_offset & 1); + this.flags_changed[0] &= ~1; return bit_base ^ 1 << bit_offset; } CPU.prototype.bts_reg = function(bit_base, bit_offset) { - this.flags = (this.flags & ~1) | (bit_base >> bit_offset & 1); - this.flags_changed &= ~1; + this.flags[0] = (this.flags[0] & ~1) | (bit_base >> bit_offset & 1); + this.flags_changed[0] &= ~1; return bit_base | 1 << bit_offset; } CPU.prototype.btr_reg = function(bit_base, bit_offset) { - this.flags = (this.flags & ~1) | (bit_base >> bit_offset & 1); - this.flags_changed &= ~1; + this.flags[0] = (this.flags[0] & ~1) | (bit_base >> bit_offset & 1); + this.flags_changed[0] &= ~1; return bit_base & ~(1 << bit_offset); } @@ -1385,8 +1399,8 @@ CPU.prototype.bt_mem = function(virt_addr, bit_offset) var bit_base = this.safe_read8(virt_addr + (bit_offset >> 3) | 0); bit_offset &= 7; - this.flags = (this.flags & ~1) | (bit_base >> bit_offset & 1); - this.flags_changed &= ~1; + this.flags[0] = (this.flags[0] & ~1) | (bit_base >> bit_offset & 1); + this.flags_changed[0] &= ~1; } CPU.prototype.btc_mem = function(virt_addr, bit_offset) @@ -1396,8 +1410,8 @@ CPU.prototype.btc_mem = function(virt_addr, bit_offset) bit_offset &= 7; - this.flags = (this.flags & ~1) | (bit_base >> bit_offset & 1); - this.flags_changed &= ~1; + this.flags[0] = (this.flags[0] & ~1) | (bit_base >> bit_offset & 1); + this.flags_changed[0] &= ~1; this.write8(phys_addr, bit_base ^ 1 << bit_offset); } @@ -1409,8 +1423,8 @@ CPU.prototype.btr_mem = function(virt_addr, bit_offset) bit_offset &= 7; - this.flags = (this.flags & ~1) | (bit_base >> bit_offset & 1); - this.flags_changed &= ~1; + this.flags[0] = (this.flags[0] & ~1) | (bit_base >> bit_offset & 1); + this.flags_changed[0] &= ~1; this.write8(phys_addr, bit_base & ~(1 << bit_offset)); } @@ -1422,94 +1436,97 @@ CPU.prototype.bts_mem = function(virt_addr, bit_offset) bit_offset &= 7; - this.flags = (this.flags & ~1) | (bit_base >> bit_offset & 1); - this.flags_changed &= ~1; + this.flags[0] = (this.flags[0] & ~1) | (bit_base >> bit_offset & 1); + this.flags_changed[0] &= ~1; this.write8(phys_addr, bit_base | 1 << bit_offset); } CPU.prototype.bsf16 = function(old, bit_base) { - this.flags_changed = flags_all & ~flag_zero; - this.last_op_size = OPSIZE_16; + this.flags_changed[0] = flags_all & ~flag_zero; + this.last_op_size[0] = OPSIZE_16; if(bit_base === 0) { - this.flags |= flag_zero; - this.last_result = bit_base; + this.flags[0] |= flag_zero; + this.last_result[0] = bit_base; // not defined in the docs, but value doesn't change on my intel machine return old; } else { - this.flags &= ~flag_zero; + this.flags[0] &= ~flag_zero; // http://jsperf.com/lowest-bit-index - return this.last_result = v86util.int_log2(-bit_base & bit_base); + return this.last_result[0] = v86util.int_log2(-bit_base & bit_base); } } CPU.prototype.bsf32 = function(old, bit_base) { - this.flags_changed = flags_all & ~flag_zero; - this.last_op_size = OPSIZE_32; + this.flags_changed[0] = flags_all & ~flag_zero; + this.last_op_size[0] = OPSIZE_32; if(bit_base === 0) { - this.flags |= flag_zero; - this.last_result = bit_base; + this.flags[0] |= flag_zero; + this.last_result[0] = bit_base; + return old; } else { - this.flags &= ~flag_zero; + this.flags[0] &= ~flag_zero; - return this.last_result = v86util.int_log2((-bit_base & bit_base) >>> 0); + return this.last_result[0] = v86util.int_log2((-bit_base & bit_base) >>> 0); } } CPU.prototype.bsr16 = function(old, bit_base) { - this.flags_changed = flags_all & ~flag_zero; - this.last_op_size = OPSIZE_16; + this.flags_changed[0] = flags_all & ~flag_zero; + this.last_op_size[0] = OPSIZE_16; if(bit_base === 0) { - this.flags |= flag_zero; - this.last_result = bit_base; + this.flags[0] |= flag_zero; + this.last_result[0] = bit_base; + return old; } else { - this.flags &= ~flag_zero; + this.flags[0] &= ~flag_zero; - return this.last_result = v86util.int_log2(bit_base); + return this.last_result[0] = v86util.int_log2(bit_base); } } CPU.prototype.bsr32 = function(old, bit_base) { - this.flags_changed = flags_all & ~flag_zero; - this.last_op_size = OPSIZE_32; + this.flags_changed[0] = flags_all & ~flag_zero; + this.last_op_size[0] = OPSIZE_32; if(bit_base === 0) { - this.flags |= flag_zero; - this.last_result = bit_base; + this.flags[0] |= flag_zero; + this.last_result[0] = bit_base; + return old; } else { - this.flags &= ~flag_zero; - return this.last_result = v86util.int_log2(bit_base >>> 0); + this.flags[0] &= ~flag_zero; + return this.last_result[0] = v86util.int_log2(bit_base >>> 0); } } CPU.prototype.popcnt = function(v) { - this.flags_changed = 0; - this.flags &= ~flags_all; + this.flags_changed[0] = 0; + this.flags[0] &= ~flags_all; if(v) { @@ -1520,7 +1537,7 @@ CPU.prototype.popcnt = function(v) } else { - this.flags |= flag_zero; + this.flags[0] |= flag_zero; return 0; } }; diff --git a/src/browser/lib.js b/src/browser/lib.js index 368849fc..14c08b03 100644 --- a/src/browser/lib.js +++ b/src/browser/lib.js @@ -18,6 +18,42 @@ var ASYNC_SAFE = false; v86util.AsyncFileBuffer = AsyncFileBuffer; v86util.SyncFileBuffer = SyncFileBuffer; + v86util.load_wasm = function load_wasm(filename, imports, cb) { + if (!imports) { + imports = {}; + } + const STATIC_MEMORY_BASE = 64 * 1024 * 1024; // XXX + + v86util.load_file(filename, { done: function(buffer) + { + 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; + imports['env']['tableBase'] = 0; + imports['env']['memory'] = new WebAssembly.Memory({ ['initial']: 4096, }); + imports['env']['table'] = new WebAssembly.Table({ ['initial']: 18, ['element']: 'anyfunc' }); + return WebAssembly.instantiate(module, imports).then(instance => ({ instance, module })); + }) + .then(({ instance, module }) => { + cb({ + mem: imports['env']['memory'], + funcs: instance['exports'], + instance, + imports, + filename, + }); + }); + } + }); + }; + /** * @param {string} filename * @param {Object} options diff --git a/src/browser/starter.js b/src/browser/starter.js index 2cd969f6..7aa17b9e 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -92,7 +92,190 @@ function V86Starter(options) var bus = Bus.create(); var adapter_bus = this.bus = bus[0]; this.emulator_bus = bus[1]; - var emulator = this.v86 = new v86(this.emulator_bus); + var emulator; + var cpu; + var mem; + var wasm_shared_funcs = { + "_throw_cpu_exception": () => { throw MAGIC_CPU_EXCEPTION; }, + "_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); }, + "_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(); }, + "_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)); }, + + "_call_interrupt_vector": function(interrupt_nr, is_software_int, has_error_code, error_code) { + cpu.call_interrupt_vector(interrupt_nr, is_software_int, !!has_error_code, error_code); + }, + "_far_jump": function(eip, selector, is_call) { return cpu.far_jump(eip, selector, !!is_call); }, + "_far_return": function(eip, selector, stack_adjust) { return cpu.far_return(eip, selector, stack_adjust); }, + "_switch_seg": function(reg, selector) { cpu.switch_seg(reg, selector); }, + "_iret16": function() { return cpu.iret16(); }, + "_iret32": function() { return cpu.iret32(); }, + + "_io_port_read8": function(addr) { return cpu.io.port_read8(addr); }, + "_io_port_read16": function(addr) { return cpu.io.port_read16(addr); }, + "_io_port_read32": function(addr) { return cpu.io.port_read32(addr); }, + "_io_port_write8": function(addr, value) { cpu.io.port_write8(addr, value); }, + "_io_port_write16": function(addr, value) { cpu.io.port_write16(addr, value); }, + "_io_port_write32": function(addr, value) { cpu.io.port_write32(addr, value); }, + + "_mmap_read8": function(addr) { return cpu.mmap_read8(addr); }, + "_mmap_read16": function(addr) { return cpu.mmap_read16(addr); }, + "_mmap_read32": function(addr) { return cpu.mmap_read32(addr); }, + "_mmap_write8": function(addr, value) { return cpu.mmap_write8(addr, value); }, + "_mmap_write16": function(addr, value) { return cpu.mmap_write16(addr, value); }, + "_mmap_write32": function(addr, value) { return cpu.mmap_write32(addr, value); }, + + "_fpu_op_D8_reg": function() { return cpu.fpu.op_D8_reg.apply(cpu.fpu, arguments); }, + "_fpu_op_D9_reg": function() { return cpu.fpu.op_D9_reg.apply(cpu.fpu, arguments); }, + "_fpu_op_DA_reg": function() { return cpu.fpu.op_DA_reg.apply(cpu.fpu, arguments); }, + "_fpu_op_DB_reg": function() { return cpu.fpu.op_DB_reg.apply(cpu.fpu, arguments); }, + "_fpu_op_DC_reg": function() { return cpu.fpu.op_DC_reg.apply(cpu.fpu, arguments); }, + "_fpu_op_DD_reg": function() { return cpu.fpu.op_DD_reg.apply(cpu.fpu, arguments); }, + "_fpu_op_DE_reg": function() { return cpu.fpu.op_DE_reg.apply(cpu.fpu, arguments); }, + "_fpu_op_DF_reg": function() { return cpu.fpu.op_DF_reg.apply(cpu.fpu, arguments); }, + + "_fpu_op_D8_mem": function() { return cpu.fpu.op_D8_mem.apply(cpu.fpu, arguments); }, + "_fpu_op_D9_mem": function() { return cpu.fpu.op_D9_mem.apply(cpu.fpu, arguments); }, + "_fpu_op_DA_mem": function() { return cpu.fpu.op_DA_mem.apply(cpu.fpu, arguments); }, + "_fpu_op_DB_mem": function() { return cpu.fpu.op_DB_mem.apply(cpu.fpu, arguments); }, + "_fpu_op_DC_mem": function() { return cpu.fpu.op_DC_mem.apply(cpu.fpu, arguments); }, + "_fpu_op_DD_mem": function() { return cpu.fpu.op_DD_mem.apply(cpu.fpu, arguments); }, + "_fpu_op_DE_mem": function() { return cpu.fpu.op_DE_mem.apply(cpu.fpu, arguments); }, + "_fpu_op_DF_mem": function() { return cpu.fpu.op_DF_mem.apply(cpu.fpu, arguments); }, + "_fwait": function() { return cpu.fpu.fwait(); }, + + "_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); }, + "_read_moffs": function() { return cpu.read_moffs.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); }, + "_pop16": function() { return cpu.pop16.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); }, + "_set_stack_reg": function() { return cpu.set_stack_reg.apply(cpu, arguments); }, + "_getiopl": function() { return cpu.getiopl.apply(cpu, arguments); }, + "_vm86_mode": function() { return cpu.vm86_mode.apply(cpu, arguments); }, + "_shl8": function() { return cpu.shl8.apply(cpu, arguments); }, + "_shr8": function() { return cpu.shr8.apply(cpu, arguments); }, + "_sar8": function() { return cpu.sar8.apply(cpu, arguments); }, + "_shl16": function() { return cpu.shl16.apply(cpu, arguments); }, + "_shr16": function() { return cpu.shr16.apply(cpu, arguments); }, + "_sar16": function() { return cpu.sar16.apply(cpu, arguments); }, + "_shl32": function() { return cpu.shl32.apply(cpu, arguments); }, + "_shr32": function() { return cpu.shr32.apply(cpu, arguments); }, + "_sar32": function() { return cpu.sar32.apply(cpu, arguments); }, + + "_shrd16": function() { return cpu.shrd16.apply(cpu, arguments); }, + "_shrd32": function() { return cpu.shrd32.apply(cpu, arguments); }, + "_shld16": function() { return cpu.shld16.apply(cpu, arguments); }, + "_shld32": function() { return cpu.shld32.apply(cpu, arguments); }, + + "_bt_reg": function() { return cpu.bt_reg.apply(cpu, arguments); }, + "_bt_mem": function() { return cpu.bt_mem.apply(cpu, arguments); }, + "_btr_reg": function() { return cpu.btr_reg.apply(cpu, arguments); }, + "_btr_mem": function() { return cpu.btr_mem.apply(cpu, arguments); }, + "_btc_reg": function() { return cpu.btc_reg.apply(cpu, arguments); }, + "_btc_mem": function() { return cpu.btc_mem.apply(cpu, arguments); }, + "_bts_reg": function() { return cpu.bts_reg.apply(cpu, arguments); }, + "_bts_mem": function() { return cpu.bts_mem.apply(cpu, arguments); }, + + "_bsf16": function() { return cpu.bsf16.apply(cpu, arguments); }, + "_bsf32": function() { return cpu.bsf32.apply(cpu, arguments); }, + "_bsr16": function() { return cpu.bsr16.apply(cpu, arguments); }, + "_bsr32": function() { return cpu.bsr32.apply(cpu, arguments); }, + "_popcnt": function() { return cpu.popcnt.apply(cpu, arguments); }, + "_bswap": function() { return cpu.bswap.apply(cpu, arguments); }, + + "_setcc": function() { return cpu.setcc.apply(cpu, arguments); }, + "_cmovcc16": function() { return cpu.cmovcc16.apply(cpu, arguments); }, + "_cmovcc32": function() { return cpu.cmovcc32.apply(cpu, arguments); }, + + "_lar": function() { return cpu.lar.apply(cpu, arguments); }, + "_lsl": function() { return cpu.lsl.apply(cpu, arguments); }, + "_verw": function() { return cpu.verw.apply(cpu, arguments); }, + "_verr": function() { return cpu.verr.apply(cpu, arguments); }, + + "_full_clear_tlb": function() { return cpu.full_clear_tlb.apply(cpu, arguments); }, + "_invlpg": function() { return cpu.invlpg.apply(cpu, arguments); }, + "_writable_or_pagefault": function() { return cpu.writable_or_pagefault.apply(cpu, arguments); }, + + "_cpl_changed": function() { return cpu.cpl_changed.apply(cpu, arguments); }, + "_set_cr0": function() { return cpu.set_cr0.apply(cpu, arguments); }, + "_update_cs_size": function() { return cpu.update_cs_size.apply(cpu, arguments); }, + "_clear_tlb": function() { return cpu.clear_tlb.apply(cpu, arguments); }, + "_cpuid": function() { return cpu.cpuid.apply(cpu, arguments); }, + + "_load_ldt": function() { return cpu.load_ldt.apply(cpu, arguments); }, + "_load_tr": function() { return cpu.load_tr.apply(cpu, arguments); }, + + "_idiv16": function() { return cpu.idiv16.apply(cpu, arguments); }, + "_div32": function() { return cpu.div32.apply(cpu, arguments); }, + "_idiv32": function() { return cpu.idiv32.apply(cpu, arguments); }, + "_insb": function() { return cpu.insb.apply(cpu, arguments); }, + "_insw": function() { return cpu.insw.apply(cpu, arguments); }, + "_insd": function() { return cpu.insd.apply(cpu, arguments); }, + "_outsb": function() { return cpu.outsb.apply(cpu, arguments); }, + "_outsw": function() { return cpu.outsw.apply(cpu, arguments); }, + "_outsd": function() { return cpu.outsd.apply(cpu, arguments); }, + "_movsb": function() { return cpu.movsb.apply(cpu, arguments); }, + "_movsw": function() { return cpu.movsw.apply(cpu, arguments); }, + "_movsd": function() { return cpu.movsd.apply(cpu, arguments); }, + "_cmpsb": function() { return cpu.cmpsb.apply(cpu, arguments); }, + "_cmpsw": function() { return cpu.cmpsw.apply(cpu, arguments); }, + "_cmpsd": function() { return cpu.cmpsd.apply(cpu, arguments); }, + "_stosb": function() { return cpu.stosb.apply(cpu, arguments); }, + "_stosw": function() { return cpu.stosw.apply(cpu, arguments); }, + "_stosd": function() { return cpu.stosd.apply(cpu, arguments); }, + "_lodsb": function() { return cpu.lodsb.apply(cpu, arguments); }, + "_lodsw": function() { return cpu.lodsw.apply(cpu, arguments); }, + "_lodsd": function() { return cpu.lodsd.apply(cpu, arguments); }, + "_scasb": function() { return cpu.scasb.apply(cpu, arguments); }, + "_scasw": function() { return cpu.scasw.apply(cpu, arguments); }, + "_scasd": function() { return cpu.scasd.apply(cpu, arguments); }, + "_lss16": function() { return cpu.lss16.apply(cpu, arguments); }, + "_lss32": function() { return cpu.lss32.apply(cpu, arguments); }, + "_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); }, + "_get_real_eip": function() { return cpu.get_real_eip.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); }, + "_bcd_aam": function() { return cpu.bcd_aam.apply(cpu, arguments); }, + "_task_switch_test": function() { return cpu.task_switch_test.apply(cpu, arguments); }, + "_jcxz": function() { return cpu.jcxz.apply(cpu, arguments); }, + "_test_privileges_for_io": function() { return cpu.test_privileges_for_io.apply(cpu, arguments); }, + + "_fxsave": function() { return cpu.fxsave.apply(cpu, arguments); }, + "_fxrstor": function() { return cpu.fxrstor.apply(cpu, arguments); }, + }; + + let wasm_file = DEBUG ? "v86-debug.wasm" : "v86.wasm"; + v86util.load_wasm("build/" + wasm_file, { 'env': wasm_shared_funcs }, wm => { + emulator = this.v86 = new v86(this.emulator_bus, wm); + cpu = emulator.cpu; + mem = wm.mem.buffer; this.bus.register("emulator-stopped", function() { @@ -423,6 +606,8 @@ function V86Starter(options) }.bind(this), 0); }.bind(this), 0); } + + }); } /** @@ -627,7 +812,7 @@ V86Starter.prototype.get_instruction_counter = function() { if(this.v86) { - return this.v86.cpu.timestamp_counter; + return this.v86.cpu.timestamp_counter[0]; } else { diff --git a/src/config.js b/src/config.js index 6890fad4..4fe8dcbd 100644 --- a/src/config.js +++ b/src/config.js @@ -26,7 +26,7 @@ var LOG_PAGE_FAULTS = false; var LOG_LEVEL = LOG_ALL & ~LOG_PS2 & ~LOG_PIT & ~LOG_VIRTIO & ~LOG_9P & ~LOG_PIC & - ~LOG_DMA & ~LOG_SERIAL & ~LOG_NET & ~LOG_FLOPPY & ~LOG_DISK; + ~LOG_DMA & ~LOG_SERIAL & ~LOG_NET & ~LOG_FLOPPY & ~LOG_DISK & ~LOG_VGA; /** @const */ diff --git a/src/cpu.js b/src/cpu.js index 699f8dd4..ee350f91 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -1,7 +1,7 @@ "use strict"; /** @const */ -var CPU_LOG_VERBOSE = true; +var CPU_LOG_VERBOSE = false; // Resources: @@ -11,14 +11,17 @@ var CPU_LOG_VERBOSE = true; /** @constructor */ -function CPU(bus) +function CPU(bus, wm) { - /** @type {number} */ - this.memory_size = 0; + this.wm = wm; + this.wasm_patch(wm); + + this.memory_size = new Uint32Array(wm.mem.buffer, 812, 1); // Note: Currently unused (degrades performance and not required by any OS // that we support) - this.a20_enabled = true; + this.a20_enabled = new Int32Array(wm.mem.buffer, 552, 1); + this.a20_enabled[0] = +true; this.mem_page_infos = undefined; @@ -26,16 +29,16 @@ function CPU(bus) this.mem16 = new Uint16Array(this.mem8.buffer); this.mem32s = new Int32Array(this.mem8.buffer); - this.segment_is_null = new Uint8Array(8); - this.segment_limits = new Uint32Array(8); - //this.segment_infos = new Uint32Array(8); - this.segment_offsets = new Int32Array(8); + this.segment_is_null = new Uint8Array(wm.mem.buffer, 724, 8); + this.segment_offsets = new Int32Array(wm.mem.buffer, 736, 8); + this.segment_limits = new Uint32Array(wm.mem.buffer, 768, 8); + //this.segment_infos = []; /** * Translation Lookaside Buffer * @const */ - this.tlb_data = new Int32Array(1 << 20); + this.tlb_data = new Int32Array(wm.mem.buffer, 2048 + 0x100000*2, 0x100000); /** * Information about which pages are cached in the tlb. @@ -46,35 +49,27 @@ function CPU(bus) * 3 user, write * @const */ - this.tlb_info = new Uint8Array(1 << 20); + this.tlb_info = new Uint8Array(wm.mem.buffer, 2048, 0x100000); /** * Same as tlb_info, except it only contains global pages * @const */ - this.tlb_info_global = new Uint8Array(1 << 20); + this.tlb_info_global = new Uint8Array(wm.mem.buffer, 2048 + 0x100000, 0x100000); /** * Wheter or not in protected mode - * @type {boolean} */ - this.protected_mode = false; + this.protected_mode = new Int32Array(wm.mem.buffer, 800, 1); - /** - * interrupt descriptor table - * @type {number} - */ - this.idtr_size = 0; - /** @type {number} */ - this.idtr_offset = 0; + this.idtr_size = new Int32Array(wm.mem.buffer, 564, 1); + this.idtr_offset = new Int32Array(wm.mem.buffer, 568, 1); /** * global descriptor table register - * @type {number} */ - this.gdtr_size = 0; - /** @type {number} */ - this.gdtr_offset = 0; + this.gdtr_size = new Int32Array(wm.mem.buffer, 572, 1); + this.gdtr_offset = new Int32Array(wm.mem.buffer, 576, 1); this.tss_size_32 = false; @@ -83,7 +78,7 @@ function CPU(bus) */ this.page_fault = false; - this.cr = new Int32Array(8); + this.cr = new Int32Array(wm.mem.buffer, 580, 8); /** @type {number} */ this.cr[0] = 0; @@ -95,19 +90,15 @@ function CPU(bus) this.cr[4] = 0; // current privilege level - /** @type {number} */ - this.cpl = 0; + this.cpl = new Int32Array(wm.mem.buffer, 612, 1); // if false, pages are 4 KiB, else 4 Mib - /** @type {number} */ - this.page_size_extensions = 0; + this.page_size_extensions = new Int32Array(wm.mem.buffer, 616, 1); // current operand/address size - /** @type {boolean} */ - this.is_32 = false; + this.is_32 = new Int32Array(wm.mem.buffer, 804, 1); - /** @type {boolean} */ - this.stack_size_32 = false; + this.stack_size_32 = new Int32Array(wm.mem.buffer, 808, 1); /** * Was the last instruction a hlt? @@ -115,70 +106,52 @@ function CPU(bus) */ this.in_hlt = false; - /** @type {number} */ - this.last_virt_eip = 0; + this.last_virt_eip = new Int32Array(wm.mem.buffer, 620, 1); - /** @type {number} */ - this.eip_phys = 0; + this.eip_phys = new Int32Array(wm.mem.buffer, 624, 1); - /** @type {number} */ - this.last_virt_esp = 0; + this.last_virt_esp = new Int32Array(wm.mem.buffer, 628, 1); - /** @type {number} */ - this.esp_phys = 0; + this.esp_phys = new Int32Array(wm.mem.buffer, 632, 1); - /** @type {number} */ - this.sysenter_cs = 0; + this.sysenter_cs = new Int32Array(wm.mem.buffer, 636, 1); - /** @type {number} */ - this.sysenter_esp = 0; + this.sysenter_esp = new Int32Array(wm.mem.buffer, 640, 1); - /** @type {number} */ - this.sysenter_eip = 0; + this.sysenter_eip = new Int32Array(wm.mem.buffer, 644, 1); - /** @type {number} */ - this.prefixes = 0; + this.prefixes = new Int32Array(wm.mem.buffer, 648, 1); - /** @type {number} */ - this.flags = 0; + this.flags = new Int32Array(wm.mem.buffer, 536, 1); /** * bitmap of flags which are not updated in the flags variable * changed by arithmetic instructions, so only relevant to arithmetic flags - * @type {number} */ - this.flags_changed = 0; + this.flags_changed = new Int32Array(wm.mem.buffer, 532, 1); /** * the last 2 operators and the result and size of the last arithmetic operation - * @type {number} */ - this.last_op1 = 0; - /** @type {number} */ - this.last_op2 = 0; - /** @type {number} */ - this.last_op_size = 0; + this.last_op1 = new Int32Array(wm.mem.buffer, 512, 1); + this.last_op2 = new Int32Array(wm.mem.buffer, 516, 1); + this.last_op_size = new Int32Array(wm.mem.buffer, 520, 1); - /** @type {number} */ - this.last_add_result = 0; + this.last_add_result = new Int32Array(wm.mem.buffer, 524, 1); - /** @type {number} */ - this.last_result = 0; + this.last_result = new Int32Array(wm.mem.buffer, 528, 1); - this.mul32_result = new Int32Array(2); + this.mul32_result = new Int32Array(wm.mem.buffer, 544, 2); this.div32_result = new Float64Array(2); - this.tsc_offset = 0; + this.tsc_offset = new Int32Array(wm.mem.buffer, 652, 1); - /** @type {number} */ - this.modrm_byte = 0; + this.modrm_byte = new Int32Array(wm.mem.buffer, 540, 1); - /** @type {number} */ - this.phys_addr = 0; + this.phys_addr = new Int32Array(wm.mem.buffer, 656, 1); - /** @type {number} */ - this.phys_addr_high = 0; + this.phys_addr_high = new Int32Array(wm.mem.buffer, 660, 1); /** @type {!Object} */ this.devices = {}; @@ -186,46 +159,14 @@ function CPU(bus) this.table = []; // paging enabled - /** @type {boolean} */ - this.paging = false; + this.paging = new Uint8Array(wm.mem.buffer, 820, 1); - /** @type {number} */ - this.instruction_pointer = 0; + this.instruction_pointer = new Int32Array(wm.mem.buffer, 556, 1); - /** @type {number} */ - this.previous_ip = 0; + this.previous_ip = new Int32Array(wm.mem.buffer, 560, 1); this.apic_enabled = true; - /** - * @type {number} - */ - this.timestamp_counter = 0; - - // registers - this.reg32s = new Int32Array(8); - this.reg32 = new Uint32Array(this.reg32s.buffer); - this.reg16s = new Int16Array(this.reg32s.buffer); - this.reg16 = new Uint16Array(this.reg32s.buffer); - this.reg8s = new Int8Array(this.reg32s.buffer); - this.reg8 = new Uint8Array(this.reg32s.buffer); - - // mm0-mm7 split up into 32 bit pairs - this.reg_mmxs = new Int32Array(16); - this.reg_mmx = new Uint32Array(this.reg_mmxs.buffer); - this.reg_mmx8s = new Int8Array(this.reg_mmxs.buffer); - this.reg_mmx8 = new Uint8Array(this.reg_mmxs.buffer); - - this.reg_xmm32s = new Int32Array(8 * 4); - this.mxcsr = 0x1F80; - - // segment registers, tr and ldtr - this.sreg = new Uint16Array(8); - - // debug registers - this.dreg = new Int32Array(8); - - // managed in io.js /** @const */ this.memory_map_read8 = []; /** @const */ this.memory_map_write8 = []; @@ -241,8 +182,32 @@ function CPU(bus) vga: null, }; - /** @type {number} */ - this.fw_value = 0; + this.timestamp_counter = new Int32Array(wm.mem.buffer, 664, 1); + + // registers + this.reg32s = new Int32Array(wm.mem.buffer, 4, 8); + this.reg32 = new Uint32Array(this.reg32s.buffer, 4, 8); + this.reg16s = new Int16Array(this.reg32s.buffer, 4, 16); + this.reg16 = new Uint16Array(this.reg32s.buffer, 4, 16); + this.reg8s = new Int8Array(this.reg32s.buffer, 4, 32); + this.reg8 = new Uint8Array(this.reg32s.buffer, 4, 32); + + // mm0-mm7 split up into 32 bit pairs + this.reg_mmxs = new Int32Array(16); + this.reg_mmx = new Uint32Array(this.reg_mmxs.buffer); + this.reg_mmx8s = new Int8Array(this.reg_mmxs.buffer); + this.reg_mmx8 = new Uint8Array(this.reg_mmxs.buffer); + + this.reg_xmm32s = new Int32Array(8 * 4); + this.mxcsr = new Int32Array(wm.mem.buffer, 824, 1); + + // segment registers, tr and ldtr + this.sreg = new Uint16Array(wm.mem.buffer, 668, 8); + + // debug registers + this.dreg = new Int32Array(wm.mem.buffer, 684, 8); + + this.fw_value = new Int32Array(wm.mem.buffer, 720, 1); this.io = undefined; this.fpu = undefined; @@ -254,7 +219,7 @@ function CPU(bus) this.update_operand_size(); - this.tsc_offset = v86.microtick(); + this.tsc_offset[0] = v86.microtick(); this.debug_init(); @@ -263,44 +228,115 @@ function CPU(bus) //Object.seal(this); } +CPU.prototype.wasm_patch = function(wm) +{ + this.add = this.wm.funcs['_add']; + this.adc = this.wm.funcs['_adc']; + this.sub = this.wm.funcs['_sub']; + this.sbb = this.wm.funcs['_sbb']; + this.inc = this.wm.funcs['_inc']; + this.dec = this.wm.funcs['_dec']; + this.neg = this.wm.funcs['_neg']; + this.mul8 = this.wm.funcs['_mul8']; + this.imul8 = this.wm.funcs['_imul8']; + this.mul16 = this.wm.funcs['_mul16']; + this.imul16 = this.wm.funcs['_imul16']; + this.imul_reg16 = this.wm.funcs['_imul_reg16']; + this.mul32 = this.wm.funcs['_mul32']; + this.imul32 = this.wm.funcs['_imul32']; + this.imul_reg32 = this.wm.funcs['_imul_reg32']; + this.xadd8 = this.wm.funcs['_xadd8']; + this.xadd16 = this.wm.funcs['_xadd16']; + this.xadd32 = this.wm.funcs['_xadd32']; + this.bcd_daa = this.wm.funcs['_bcd_daa']; + this.bcd_das = this.wm.funcs['_bcd_das']; + this.bcd_aad = this.wm.funcs['_bcd_aad']; + this.bcd_aaa = this.wm.funcs['_bcd_aaa']; + this.bcd_aas = this.wm.funcs['_bcd_aas']; + this.and = this.wm.funcs['_and']; + this.or = this.wm.funcs['_or']; + this.xor = this.wm.funcs['_xor']; + this.rol8 = this.wm.funcs['_rol8']; + this.rol16 = this.wm.funcs['_rol16']; + this.rol32 = this.wm.funcs['_rol32']; + this.rcl8 = this.wm.funcs['_rcl8']; + this.rcl16 = this.wm.funcs['_rcl16']; + this.rcl32 = this.wm.funcs['_rcl32']; + this.ror8 = this.wm.funcs['_ror8']; + this.ror16 = this.wm.funcs['_ror16']; + this.ror32 = this.wm.funcs['_ror32']; + this.rcr8 = this.wm.funcs['_rcr8']; + this.rcr16 = this.wm.funcs['_rcr16']; + this.rcr32 = this.wm.funcs['_rcr32']; + this.div8 = this.wm.funcs['_div8']; + this.idiv8 = this.wm.funcs['_idiv8']; + this.div16 = this.wm.funcs['_div16']; + this.getcf = this.wm.funcs['_getcf']; + this.getaf = this.wm.funcs['_getaf']; + this.raise_exception = this.wm.funcs['_raise_exception']; + this.raise_exception_with_code = this.wm.funcs['_raise_exception_with_code']; + this.trigger_de = this.wm.funcs['_trigger_de']; + this.trigger_gp = this.wm.funcs['_trigger_gp']; + + this.do_many_cycles_unsafe = this.wm.funcs['_do_many_cycles_unsafe']; + + this.read_imm8 = this.wm.funcs['_read_imm8']; + this.read_imm8s = this.wm.funcs['_read_imm8s']; + this.read_imm16 = this.wm.funcs['_read_imm16']; + this.read_imm32s = this.wm.funcs['_read_imm32s']; + this.read_write_e8 = this.wm.funcs['_read_write_e8']; + this.write_e8 = this.wm.funcs['_write_e8']; + this.in_mapped_range = this.wm.funcs['_in_mapped_range']; + this.read16 = this.wm.funcs['_read16']; + this.read_aligned16 = this.wm.funcs['_read_aligned16']; + this.read32s = this.wm.funcs['_read32s']; + this.write8 = this.wm.funcs['_write8']; + this.write16 = this.wm.funcs['_write16']; + this.write32 = this.wm.funcs['_write32']; + this.push16 = this.wm.funcs['_push16']; + this.push32 = this.wm.funcs['_push32']; + this.pusha16 = this.wm.funcs['_pusha16']; + this.pusha32 = this.wm.funcs['_pusha32']; +}; + CPU.prototype.get_state = function() { var state = []; - state[0] = this.memory_size; + state[0] = this.memory_size[0]; state[1] = this.segment_is_null; state[2] = this.segment_offsets; state[3] = this.segment_limits; - state[4] = this.protected_mode; - state[5] = this.idtr_offset; - state[6] = this.idtr_size; - state[7] = this.gdtr_offset; - state[8] = this.gdtr_size; + state[4] = this.protected_mode[0]; + state[5] = this.idtr_offset[0]; + state[6] = this.idtr_size[0]; + state[7] = this.gdtr_offset[0]; + state[8] = this.gdtr_size[0]; state[9] = this.page_fault; state[10] = this.cr; - state[11] = this.cpl; - state[12] = this.page_size_extensions; - state[13] = this.is_32; + state[11] = this.cpl[0]; + state[12] = this.page_size_extensions[0]; + state[13] = this.is_32[0]; - state[16] = this.stack_size_32; + state[16] = this.stack_size_32[0]; state[17] = this.in_hlt; - state[18] = this.last_virt_eip; - state[19] = this.eip_phys; - state[20] = this.last_virt_esp; - state[21] = this.esp_phys; - state[22] = this.sysenter_cs; - state[23] = this.sysenter_eip; - state[24] = this.sysenter_esp; - state[25] = this.prefixes; + state[18] = this.last_virt_eip[0]; + state[19] = this.eip_phys[0]; + state[20] = this.last_virt_esp[0]; + state[21] = this.esp_phys[0]; + state[22] = this.sysenter_cs[0]; + state[23] = this.sysenter_eip[0]; + state[24] = this.sysenter_esp[0]; + state[25] = this.prefixes[0]; state[26] = this.flags; state[27] = this.flags_changed; state[28] = this.last_op1; state[29] = this.last_op2; state[30] = this.last_op_size; state[31] = this.last_add_result; - state[32] = this.modrm_byte; + state[32] = this.modrm_byte[0]; - state[36] = this.paging; + state[36] = this.paging[0]; state[37] = this.instruction_pointer; state[38] = this.previous_ip; state[39] = this.reg32s; @@ -326,8 +362,12 @@ CPU.prototype.get_state = function() state[59] = this.devices.net; state[60] = this.devices.pic; - state[61] = this.a20_enabled; - state[62] = this.fw_value; + state[61] = this.a20_enabled[0]; + state[62] = this.fw_value[0]; + + state[63] = this.devices.ioapic; + + state[64] = this.tss_size_32; state[63] = this.devices.ioapic; @@ -340,32 +380,32 @@ CPU.prototype.get_state = function() CPU.prototype.set_state = function(state) { - this.memory_size = state[0]; + this.memory_size[0] = state[0]; this.segment_is_null = state[1]; this.segment_offsets = state[2]; this.segment_limits = state[3]; - this.protected_mode = state[4]; - this.idtr_offset = state[5]; - this.idtr_size = state[6]; - this.gdtr_offset = state[7]; - this.gdtr_size = state[8]; + this.protected_mode[0] = state[4]; + this.idtr_offset[0] = state[5]; + this.idtr_size[0] = state[6]; + this.gdtr_offset[0] = state[7]; + this.gdtr_size[0] = state[8]; this.page_fault = state[9]; this.cr = state[10]; - this.cpl = state[11]; - this.page_size_extensions = state[12]; - this.is_32 = state[13]; + this.cpl[0] = state[11]; + this.page_size_extensions[0] = state[12]; + this.is_32[0] = state[13]; - this.stack_size_32 = state[16]; + this.stack_size_32[0] = state[16]; this.in_hlt = state[17]; - this.last_virt_eip = state[18]; - this.eip_phys = state[19]; - this.last_virt_esp = state[20]; - this.esp_phys = state[21]; - this.sysenter_cs = state[22]; - this.sysenter_eip = state[23]; - this.sysenter_esp = state[24]; - this.prefixes = state[25]; + this.last_virt_eip[0] = state[18]; + this.eip_phys[0] = state[19]; + this.last_virt_esp[0] = state[20]; + this.esp_phys[0] = state[21]; + this.sysenter_cs[0] = state[22]; + this.sysenter_eip[0] = state[23]; + this.sysenter_esp[0] = state[24]; + this.prefixes[0] = state[25]; this.flags = state[26]; this.flags_changed = state[27]; @@ -375,7 +415,7 @@ CPU.prototype.set_state = function(state) this.last_add_result = state[31]; this.modrm_byte = state[32]; - this.paging = state[36]; + this.paging[0] = state[36]; this.instruction_pointer = state[37]; this.previous_ip = state[38]; this.reg32s = state[39]; @@ -401,8 +441,12 @@ CPU.prototype.set_state = function(state) this.devices.net = state[59]; this.devices.pic = state[60]; - this.a20_enabled = state[61]; - this.fw_value = state[62]; + this.a20_enabled[0] = state[61]; + this.fw_value[0] = state[62]; + + this.devices.ioapic = state[63]; + + this.tss_size_32 = state[64]; this.devices.ioapic = state[63]; @@ -491,25 +535,17 @@ CPU.prototype.reboot_internal = function() CPU.prototype.reset = function() { - this.a20_enabled = true; + this.a20_enabled[0] = +true; - for(let i = 0; i < 8; i++) - { - this.segment_is_null[i] = 0; - this.segment_limits[i] = 0; - //this.segment_infos = new Uint32Array(8); - this.segment_offsets[i] = 0; - } + this.segment_is_null.fill(0); + this.segment_limits.fill(0); + //this.segment_infos = new Uint32Array(8); + this.segment_offsets.fill(0); - this.full_clear_tlb(); + this.reg32s.fill(0); - for(let i = 0; i < 8; i++) - { - this.reg32s[i] = 0; - this.sreg[i] = 0; - this.cr[i] = 0; - this.dreg[i] = 0; - } + this.sreg.fill(0); + this.dreg.fill(0); for(let i = 0; i < this.reg_mmxs.length; i++) { @@ -520,16 +556,18 @@ CPU.prototype.reset = function() { this.reg_xmm32s[i] = 0; } - this.mxcsr = 0x1F80; + this.mxcsr[0] = 0x1F80; - this.protected_mode = false; + this.full_clear_tlb(); + + this.protected_mode[0] = +false; // http://www.sandpile.org/x86/initial.htm - this.idtr_size = 0; - this.idtr_offset = 0; + this.idtr_size[0] = 0; + this.idtr_offset[0] = 0; - this.gdtr_size = 0; - this.gdtr_offset = 0; + this.gdtr_size[0] = 0; + this.gdtr_offset[0] = 0; this.page_fault = false; this.cr[0] = 1 << 30 | 1 << 29 | 1 << 4; @@ -538,38 +576,38 @@ CPU.prototype.reset = function() this.cr[4] = 0; this.dreg[6] = 0xFFFF0FF0|0; this.dreg[7] = 0x400; - this.cpl = 0; - this.paging = false; - this.page_size_extensions = 0; - this.is_32 = false; - this.stack_size_32 = false; - this.prefixes = 0; + this.cpl[0] = 0; + this.paging[0] = 0; + this.page_size_extensions[0] = 0; + this.is_32[0] = +false; + this.stack_size_32[0] = +false; + this.prefixes[0] = 0; - this.last_virt_eip = -1; - this.last_virt_esp = -1; + this.last_virt_eip[0] = -1; + this.last_virt_esp[0] = -1; this.update_operand_size(); - this.timestamp_counter = 0; - this.previous_ip = 0; + this.timestamp_counter[0] = 0; + this.previous_ip[0] = 0; this.in_hlt = false; - this.sysenter_cs = 0; - this.sysenter_esp = 0; - this.sysenter_eip = 0; + this.sysenter_cs[0] = 0; + this.sysenter_esp[0] = 0; + this.sysenter_eip[0] = 0; - this.flags = flags_default; - this.flags_changed = 0; + this.flags[0] = flags_default; + this.flags_changed.fill(0); - this.last_result = 0; - this.last_add_result = 0; - this.last_op1 = 0; - this.last_op2 = 0; - this.last_op_size = 0; + this.last_result.fill(0); + this.last_add_result.fill(0); + this.last_op1.fill(0); + this.last_op2.fill(0); + this.last_op_size.fill(0); - this.tsc_offset = v86.microtick(); + this.tsc_offset[0] = v86.microtick(); - this.instruction_pointer = 0xFFFF0; + this.instruction_pointer[0] = 0xFFFF0; this.switch_cs_real_mode(0xF000); this.switch_seg(reg_ss, 0x30); @@ -580,7 +618,7 @@ CPU.prototype.reset = function() this.devices.virtio.reset(); } - this.fw_value = 0; + this.fw_value[0] = 0; }; /** @export */ @@ -599,13 +637,13 @@ CPU.prototype.create_memory = function(size) dbg_assert((size | 0) > 0); dbg_assert((size & MMAP_BLOCK_SIZE - 1) === 0); - this.memory_size = size; + this.memory_size[0] = size; - var buffer = new ArrayBuffer(size); + var buffer = this.wm.mem.buffer; - this.mem8 = new Uint8Array(buffer); - this.mem16 = new Uint16Array(buffer); - this.mem32s = new Int32Array(buffer); + this.mem8 = new Uint8Array(buffer, 2048 + 0x100000 * 6); + this.mem16 = new Uint16Array(buffer, 2048 + 0x100000 * 6); + this.mem32s = new Int32Array(buffer, 2048 + 0x100000 * 6); }; CPU.prototype.init = function(settings, device_bus) @@ -645,8 +683,8 @@ CPU.prototype.init = function(settings, device_bus) io.register_read(0x511, this, function() { // bios config port (used by seabios and kvm-unit-test) - let result = this.fw_value & 0xFF; - this.fw_value >>>= 8; + let result = this.fw_value[0] & 0xFF; + this.fw_value[0] >>>= 8; return result; }); io.register_write(0x510, this, undefined, function(value) @@ -657,20 +695,20 @@ CPU.prototype.init = function(settings, device_bus) { // We could pretend to be QEMU here to control certain options in // seabios, but for now this isn't needed - this.fw_value = 0xfab0fab0|0; + this.fw_value[0] = 0xfab0fab0|0; } else if(value === FW_CFG_RAM_SIZE) { - this.fw_value = this.memory_size; + this.fw_value[0] = this.memory_size[0]; } else if(value === FW_CFG_NB_CPUS) { - this.fw_value = 1; + this.fw_value[0] = 1; } else { dbg_assert(false, "Unimplemented fw index: " + h(value)); - this.fw_value = 0; + this.fw_value[0] = 0; } }); @@ -811,10 +849,10 @@ CPU.prototype.load_multiboot = function(buffer) this.write32(multiboot_info_addr, 0); this.cr[0] = 1; - this.protected_mode = true; - this.flags = flags_default; + this.protected_mode[0] = +true; + this.flags[0] = flags_default; this.update_cs_size(true); - this.stack_size_32 = true; + this.stack_size_32[0] = +true; for(var i = 0; i < 6; i++) { @@ -860,7 +898,7 @@ CPU.prototype.load_multiboot = function(buffer) let blob = new Uint8Array(buffer, file_start, length); this.write_blob(blob, load_addr); - this.instruction_pointer = this.get_seg(reg_cs) + entry_addr | 0; + this.instruction_pointer[0] = this.get_seg(reg_cs) + entry_addr | 0; } else if(buf32[0] === ELF_MAGIC) { @@ -868,7 +906,7 @@ CPU.prototype.load_multiboot = function(buffer) let elf = read_elf(buffer); - this.instruction_pointer = this.get_seg(reg_cs) + elf.header.entry | 0; + this.instruction_pointer[0] = this.get_seg(reg_cs) + elf.header.entry | 0; for(let program of elf.program_headers) { @@ -964,9 +1002,9 @@ CPU.prototype.fill_cmos = function(rtc, settings) rtc.cmos_write(CMOS_MEM_BASE_HIGH, 640 >> 8); var memory_above_1m = 0; // in k - if(this.memory_size >= 1024 * 1024) + if(this.memory_size[0] >= 1024 * 1024) { - memory_above_1m = (this.memory_size - 1024 * 1024) >> 10; + memory_above_1m = (this.memory_size[0] - 1024 * 1024) >> 10; memory_above_1m = Math.min(memory_above_1m, 0xFFFF); } @@ -976,9 +1014,9 @@ CPU.prototype.fill_cmos = function(rtc, settings) rtc.cmos_write(CMOS_MEM_EXTMEM_HIGH, memory_above_1m >> 8 & 0xFF); var memory_above_16m = 0; // in 64k blocks - if(this.memory_size >= 16 * 1024 * 1024) + if(this.memory_size[0] >= 16 * 1024 * 1024) { - memory_above_16m = (this.memory_size - 16 * 1024 * 1024) >> 16; + memory_above_16m = (this.memory_size[0] - 16 * 1024 * 1024) >> 16; memory_above_16m = Math.min(memory_above_16m, 0xFFFF); } rtc.cmos_write(CMOS_MEM_EXTMEM2_LOW, memory_above_16m & 0xFF); @@ -1096,6 +1134,7 @@ CPU.prototype.do_many_cycles = function() CPU.prototype.do_many_cycles_unsafe = function() { + dbg_assert(false); // inner loop: // runs only cycles for(var k = LOOP_COUNTER; k--;) @@ -1151,9 +1190,9 @@ if(PROFILING) */ CPU.prototype.cycle_internal = function() { - this.previous_ip = this.instruction_pointer; + this.previous_ip[0] = this.instruction_pointer[0]; - this.timestamp_counter++; + this.timestamp_counter[0]++; if(PROFILING) { @@ -1165,7 +1204,7 @@ CPU.prototype.cycle_internal = function() if(DEBUG) { - this.debug.logop(this.instruction_pointer - 1 >>> 0, opcode); + this.debug.logop(this.instruction_pointer[0] - 1 >>> 0, opcode); } // call the instruction @@ -1178,7 +1217,7 @@ CPU.prototype.cycle_internal = function() instruction_count[opcode]++; } - if(this.flags & flag_trap) + if(this.flags[0] & flag_trap) { // TODO dbg_log("Trap flag: Ignored", LOG_CPU); @@ -1198,12 +1237,34 @@ CPU.prototype.cycle = function() } }; +CPU.prototype.run_instruction_0f = function() +{ + if(this.is_osize_32()) + { + this.table0F_32[this.read_op0F()](this); + } + else + { + this.table0F_16[this.read_op0F()](this); + } +}; + +CPU.prototype.dbg_log = function() +{ + dbg_log("from wasm: " + [].join.call(arguments)); +}; + +CPU.prototype.dbg_assert = function(x) +{ + dbg_assert(x); +}; + CPU.prototype.segment_prefix_op = function(sreg) { dbg_assert(sreg <= 5); - this.prefixes |= sreg + 1; + this.prefixes[0] |= sreg + 1; this.run_prefix_instruction(); - this.prefixes = 0; + this.prefixes[0] = 0; }; CPU.prototype.run_prefix_instruction = function() @@ -1220,7 +1281,7 @@ CPU.prototype.run_prefix_instruction = function() CPU.prototype.hlt_loop = function() { - dbg_assert(this.flags & flag_interrupt); + dbg_assert(this.flags[0] & flag_interrupt); //dbg_log("In HLT loop", LOG_CPU); this.run_hardware_timers(v86.microtick()); @@ -1252,7 +1313,7 @@ CPU.prototype.run_hardware_timers = function(now) CPU.prototype.clear_prefixes = function() { - this.prefixes = 0; + this.prefixes[0] = 0; }; CPU.prototype.set_cr0 = function(cr0) @@ -1276,14 +1337,13 @@ CPU.prototype.set_cr0 = function(cr0) var new_paging = (this.cr[0] & CR0_PG) === CR0_PG; - dbg_assert(typeof this.paging === "boolean"); - if(new_paging !== this.paging) + if(new_paging !== Boolean(this.paging[0])) { - this.paging = new_paging; + this.paging[0] = +new_paging; this.full_clear_tlb(); } - this.protected_mode = (this.cr[0] & CR0_PE) === CR0_PE; + this.protected_mode[0] = +((this.cr[0] & CR0_PE) === CR0_PE); }; CPU.prototype.set_cr4 = function(cr4) @@ -1309,7 +1369,7 @@ CPU.prototype.set_cr4 = function(cr4) } this.cr[4] = cr4; - this.page_size_extensions = (cr4 & CR4_PSE) ? PSE_ENABLED : 0; + this.page_size_extensions[0] = (cr4 & CR4_PSE) ? PSE_ENABLED : 0; if(cr4 & CR4_PAE) { @@ -1327,20 +1387,20 @@ CPU.prototype.set_cr4 = function(cr4) CPU.prototype.cpl_changed = function() { - this.last_virt_eip = -1; - this.last_virt_esp = -1; + this.last_virt_eip[0] = -1; + this.last_virt_esp[0] = -1; }; CPU.prototype.read_imm8 = function() { - if((this.instruction_pointer & ~0xFFF) ^ this.last_virt_eip) + if((this.instruction_pointer[0] & ~0xFFF) ^ this.last_virt_eip[0]) { - this.eip_phys = this.translate_address_read(this.instruction_pointer) ^ this.instruction_pointer; - this.last_virt_eip = this.instruction_pointer & ~0xFFF; + this.eip_phys[0] = this.translate_address_read(this.instruction_pointer[0]) ^ this.instruction_pointer[0]; + this.last_virt_eip[0] = this.instruction_pointer[0] & ~0xFFF; } - var data8 = this.read8(this.eip_phys ^ this.instruction_pointer); - this.instruction_pointer = this.instruction_pointer + 1 | 0; + var data8 = this.read8(this.eip_phys[0] ^ this.instruction_pointer[0]); + this.instruction_pointer[0] = this.instruction_pointer[0] + 1 | 0; return data8; }; @@ -1355,13 +1415,13 @@ CPU.prototype.read_imm16 = function() // Two checks in one comparison: // 1. Did the high 20 bits of eip change // or 2. Are the low 12 bits of eip 0xFFF (and this read crosses a page boundary) - if(((this.instruction_pointer ^ this.last_virt_eip) >>> 0) > 0xFFE) + if(((this.instruction_pointer[0] ^ this.last_virt_eip[0]) >>> 0) > 0xFFE) { return this.read_imm8() | this.read_imm8() << 8; } - var data16 = this.read16(this.eip_phys ^ this.instruction_pointer); - this.instruction_pointer = this.instruction_pointer + 2 | 0; + var data16 = this.read16(this.eip_phys[0] ^ this.instruction_pointer[0]); + this.instruction_pointer[0] = this.instruction_pointer[0] + 2 | 0; return data16; }; @@ -1369,13 +1429,13 @@ CPU.prototype.read_imm16 = function() CPU.prototype.read_imm32s = function() { // Analogue to the above comment - if(((this.instruction_pointer ^ this.last_virt_eip) >>> 0) > 0xFFC) + if(((this.instruction_pointer[0] ^ this.last_virt_eip[0]) >>> 0) > 0xFFC) { return this.read_imm16() | this.read_imm16() << 16; } - var data32 = this.read32s(this.eip_phys ^ this.instruction_pointer); - this.instruction_pointer = this.instruction_pointer + 4 | 0; + var data32 = this.read32s(this.eip_phys[0] ^ this.instruction_pointer[0]); + this.instruction_pointer[0] = this.instruction_pointer[0] + 4 | 0; return data32; }; @@ -1403,7 +1463,7 @@ CPU.prototype.create_atom128s = function(d0, d1, d2, d3) CPU.prototype.read_modrm_byte = function() { - this.modrm_byte = this.read_imm8(); + this.modrm_byte[0] = this.read_imm8(); }; CPU.prototype.read_op0F = CPU.prototype.read_imm8; @@ -1527,7 +1587,7 @@ CPU.prototype.safe_read8 = function(addr) CPU.prototype.safe_read16 = function(addr) { - if(this.paging && (addr & 0xFFF) === 0xFFF) + if(this.paging[0] && (addr & 0xFFF) === 0xFFF) { return this.safe_read8(addr) | this.safe_read8(addr + 1 | 0) << 8; } @@ -1539,7 +1599,7 @@ CPU.prototype.safe_read16 = function(addr) CPU.prototype.safe_read32s = function(addr) { - if(this.paging && (addr & 0xFFF) >= 0xFFD) + if(this.paging[0] && (addr & 0xFFF) >= 0xFFD) { return this.safe_read16(addr) | this.safe_read16(addr + 2 | 0) << 16; } @@ -1613,7 +1673,6 @@ CPU.prototype.safe_write32 = function(addr, value) if((addr & 0xFFF) >= 0xFFD) { - // XXX this.virt_boundary_write32(phys_low, this.translate_address_write(addr + 3 & ~3) | (addr + 3) & 3, value); } else @@ -1654,17 +1713,17 @@ CPU.prototype.read_moffs = function() CPU.prototype.getiopl = function() { - return this.flags >> 12 & 3; + return this.flags[0] >> 12 & 3; }; CPU.prototype.vm86_mode = function() { - return !!(this.flags & flag_vm); + return !!(this.flags[0] & flag_vm); }; CPU.prototype.get_eflags = function() { - return (this.flags & ~flags_all) | !!this.getcf() | !!this.getpf() << 2 | !!this.getaf() << 4 | + return (this.flags[0] & ~flags_all) | !!this.getcf() | !!this.getpf() << 2 | !!this.getaf() << 4 | !!this.getzf() << 6 | !!this.getsf() << 7 | !!this.getof() << 11; }; @@ -1676,7 +1735,7 @@ CPU.prototype.update_eflags = function(new_flags) var dont_update = flag_rf | flag_vm | flag_vip | flag_vif, clear = ~flag_vip & ~flag_vif & flags_mask; - if(this.flags & flag_vm) + if(this.flags[0] & flag_vm) { // other case needs to be handled in popf or iret dbg_assert(this.getiopl() === 3); @@ -1688,15 +1747,15 @@ CPU.prototype.update_eflags = function(new_flags) } else { - if(!this.protected_mode) dbg_assert(this.cpl === 0); + if(!this.protected_mode[0]) dbg_assert(this.cpl[0] === 0); - if(this.cpl) + if(this.cpl[0]) { // cpl > 0 // cannot update iopl dont_update |= flag_iopl; - if(this.cpl > this.getiopl()) + if(this.cpl[0] > this.getiopl()) { // cpl > iopl // cannot update interrupt flag @@ -1705,14 +1764,14 @@ CPU.prototype.update_eflags = function(new_flags) } } - this.flags = (new_flags ^ ((this.flags ^ new_flags) & dont_update)) & clear | flags_default; + this.flags[0] = (new_flags ^ ((this.flags[0] ^ new_flags) & dont_update)) & clear | flags_default; - this.flags_changed = 0; + this.flags_changed[0] = 0; }; CPU.prototype.get_stack_reg = function() { - if(this.stack_size_32) + if(this.stack_size_32[0]) { return this.reg32s[reg_esp]; } @@ -1724,7 +1783,7 @@ CPU.prototype.get_stack_reg = function() CPU.prototype.set_stack_reg = function(value) { - if(this.stack_size_32) + if(this.stack_size_32[0]) { this.reg32s[reg_esp] = value; } @@ -1736,7 +1795,7 @@ CPU.prototype.set_stack_reg = function(value) CPU.prototype.adjust_stack_reg = function(value) { - if(this.stack_size_32) + if(this.stack_size_32[0]) { this.reg32s[reg_esp] += value; } @@ -1748,7 +1807,7 @@ CPU.prototype.adjust_stack_reg = function(value) CPU.prototype.get_stack_pointer = function(mod) { - if(this.stack_size_32) + if(this.stack_size_32[0]) { return this.get_seg(reg_ss) + this.reg32s[reg_esp] + mod | 0; } @@ -1764,10 +1823,10 @@ CPU.prototype.get_stack_pointer = function(mod) */ CPU.prototype.get_real_eip = function() { - return this.instruction_pointer - this.get_seg(reg_cs) | 0; + return this.instruction_pointer[0] - this.get_seg(reg_cs) | 0; }; -CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, error_code) +CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, has_error_code, error_code) { //dbg_log("int " + h(interrupt_nr, 2) + " (" + (is_software_int ? "soft" : "hard") + "ware)", LOG_CPU); CPU_LOG_VERBOSE && this.debug.dump_state("int " + h(interrupt_nr) + " start" + @@ -1776,14 +1835,15 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, er this.debug.debug_interrupt(interrupt_nr); - dbg_assert(error_code === false || typeof error_code === "number"); + dbg_assert(typeof has_error_code === "boolean"); + dbg_assert(has_error_code === false || typeof error_code === "number"); // we have to leave hlt_loop at some point, this is a // good place to do it //this.in_hlt && dbg_log("Leave HLT loop", LOG_CPU); this.in_hlt = false; - if(this.protected_mode) + if(this.protected_mode[0]) { if(this.vm86_mode() && (this.cr[4] & CR4_VME)) { @@ -1797,17 +1857,17 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, er this.trigger_gp(0); } - if((interrupt_nr << 3 | 7) > this.idtr_size) + if((interrupt_nr << 3 | 7) > this.idtr_size[0]) { dbg_log(interrupt_nr, LOG_CPU); dbg_trace(LOG_CPU); throw this.debug.unimpl("#GP handler"); } - var addr = this.idtr_offset + (interrupt_nr << 3) | 0; + var addr = this.idtr_offset[0] + (interrupt_nr << 3) | 0; dbg_assert((addr & 0xFFF) < 0xFF8); - if(this.paging) + if(this.paging[0]) { addr = this.translate_address_system_read(addr); } @@ -1824,7 +1884,7 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, er throw this.debug.unimpl("#NP handler"); } - if(is_software_int && dpl < this.cpl) + if(is_software_int && dpl < this.cpl[0]) { dbg_log("#gp software interrupt (" + h(interrupt_nr, 2) + ") and dpl < cpl", LOG_CPU); dbg_trace(LOG_CPU); @@ -1864,7 +1924,7 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, er dbg_log("is null"); throw this.debug.unimpl("#GP handler"); } - if(!info.is_executable || info.dpl > this.cpl) + if(!info.is_executable || info.dpl > this.cpl[0]) { dbg_log("not exec"); throw this.debug.unimpl("#GP handler"); @@ -1878,9 +1938,9 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, er var old_flags = this.get_eflags(); - //dbg_log("interrupt " + h(interrupt_nr, 2) + " (" + (is_software_int ? "soft" : "hard") + "ware) from cpl=" + this.cpl + " vm=" + (this.flags & flag_vm) + " cs:eip=" + h(this.sreg[reg_cs], 4) + ":" + h(this.get_real_eip(), 8) + " to cpl=" + //dbg_log("interrupt " + h(interrupt_nr, 2) + " (" + (is_software_int ? "soft" : "hard") + "ware) from cpl=" + this.cpl[0] + " vm=" + (this.flags[0] & flag_vm) + " cs:eip=" + h(this.sreg[reg_cs], 4) + ":" + h(this.get_real_eip(), 8) + " to cpl=" - if(!info.dc_bit && info.dpl < this.cpl) + if(!info.dc_bit && info.dpl < this.cpl[0]) { // inter privilege level interrupt // interrupt from vm86 mode @@ -1935,7 +1995,7 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, er dbg_assert(info.dpl === 0, "switch to non-0 dpl from vm86 mode"); } - var stack_space = (is_16 ? 2 : 4) * (5 + (error_code !== false) + 4 * ((old_flags & flag_vm) === flag_vm)); + var stack_space = (is_16 ? 2 : 4) * (5 + (has_error_code === true) + 4 * ((old_flags & flag_vm) === flag_vm)); var new_stack_pointer = ss_info.base + (ss_info.size ? new_esp - stack_space : (new_esp - stack_space & 0xFFFF)); // XXX: with new cpl or with cpl 0? @@ -1944,12 +2004,12 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, er // no exceptions below - this.cpl = info.dpl; + this.cpl[0] = info.dpl; this.cpl_changed(); this.update_cs_size(info.size); - this.flags &= ~flag_vm & ~flag_rf; + this.flags[0] &= ~flag_vm & ~flag_rf; this.switch_seg(reg_ss, new_ss); this.set_stack_reg(new_esp); @@ -1980,22 +2040,22 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, er this.push32(old_esp); } } - else if(info.dc_bit || info.dpl === this.cpl) + else if(info.dc_bit || info.dpl === this.cpl[0]) { // intra privilege level interrupt //dbg_log("Intra privilege interrupt gate=" + h(selector, 4) + ":" + h(base >>> 0, 8) + // " trap=" + is_trap + " 16bit=" + is_16 + - // " cpl=" + this.cpl + " dpl=" + info.dpl + " conforming=" + +info.dc_bit, LOG_CPU); - //this.debug.dump_regs(); + // " cpl=" + this.cpl[0] + " dpl=" + info.dpl + " conforming=" + +info.dc_bit, LOG_CPU); + //this.debug.dump_regs_short(); - if(this.flags & flag_vm) + if(this.flags[0] & flag_vm) { dbg_assert(false, "check error code"); this.trigger_gp(selector & ~3); } - var stack_space = (is_16 ? 2 : 4) * (3 + (error_code !== false)); + var stack_space = (is_16 ? 2 : 4) * (3 + (has_error_code === true)); // XXX: with current cpl or with cpl 0? this.writable_or_pagefault(this.get_stack_pointer(-stack_space), stack_space); @@ -2013,7 +2073,7 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, er this.push16(this.sreg[reg_cs]); this.push16(this.get_real_eip()); - if(error_code !== false) + if(has_error_code === true) { this.push16(error_code); } @@ -2026,7 +2086,7 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, er this.push32(this.sreg[reg_cs]); this.push32(this.get_real_eip()); - if(error_code !== false) + if(has_error_code === true) { this.push32(error_code); } @@ -2040,22 +2100,22 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, er this.switch_seg(reg_es, 0); } - this.sreg[reg_cs] = selector & ~3 | this.cpl; - dbg_assert((this.sreg[reg_cs] & 3) === this.cpl); + this.sreg[reg_cs] = selector & ~3 | this.cpl[0]; + dbg_assert((this.sreg[reg_cs] & 3) === this.cpl[0]); this.update_cs_size(info.size); this.segment_limits[reg_cs] = info.effective_limit; this.segment_offsets[reg_cs] = info.base; - this.instruction_pointer = this.get_seg(reg_cs) + base | 0; + this.instruction_pointer[0] = this.get_seg(reg_cs) + base | 0; - this.flags &= ~flag_nt & ~flag_vm & ~flag_rf & ~flag_trap; + this.flags[0] &= ~flag_nt & ~flag_vm & ~flag_rf & ~flag_trap; if(!is_trap) { // clear int flag for interrupt gates - this.flags &= ~flag_interrupt; + this.flags[0] &= ~flag_interrupt; } else { @@ -2078,10 +2138,10 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, er this.push16(this.sreg[reg_cs]); this.push16(this.get_real_eip()); - this.flags &= ~flag_interrupt; + this.flags[0] &= ~flag_interrupt; this.switch_cs_real_mode(new_cs); - this.instruction_pointer = this.get_seg(reg_cs) + new_ip | 0; + this.instruction_pointer[0] = this.get_seg(reg_cs) + new_ip | 0; } //dbg_log("int to:", LOG_CPU); @@ -2124,7 +2184,7 @@ CPU.prototype.iret = function(is_16) var new_flags = this.safe_read32s(this.get_stack_pointer(8)); } - if(!this.protected_mode || (this.vm86_mode() && this.getiopl() === 3)) + if(!this.protected_mode[0] || (this.vm86_mode() && this.getiopl() === 3)) { if(new_eip & 0xFFFF0000) { @@ -2132,11 +2192,11 @@ CPU.prototype.iret = function(is_16) } this.switch_cs_real_mode(new_cs); - this.instruction_pointer = new_eip + this.get_seg(reg_cs) | 0; + this.instruction_pointer[0] = new_eip + this.get_seg(reg_cs) | 0; if(is_16) { - this.update_eflags(new_flags | this.flags & ~0xFFFF); + this.update_eflags(new_flags | this.flags[0] & ~0xFFFF); this.adjust_stack_reg(3 * 2); } else @@ -2154,7 +2214,7 @@ CPU.prototype.iret = function(is_16) dbg_assert(!this.vm86_mode()); - if(this.flags & flag_nt) + if(this.flags[0] & flag_nt) { if(DEBUG) throw this.debug.unimpl("nt"); this.trigger_gp(0); @@ -2162,7 +2222,7 @@ CPU.prototype.iret = function(is_16) if(new_flags & flag_vm) { - if(this.cpl === 0) + if(this.cpl[0] === 0) { // return to virtual 8086 mode @@ -2187,10 +2247,10 @@ CPU.prototype.iret = function(is_16) // no exceptions below this.update_eflags(new_flags); - this.flags |= flag_vm; + this.flags[0] |= flag_vm; this.switch_cs_real_mode(new_cs); - this.instruction_pointer = (new_eip & 0xFFFF) + this.get_seg(reg_cs) | 0; + this.instruction_pointer[0] = (new_eip & 0xFFFF) + this.get_seg(reg_cs) | 0; this.switch_seg(reg_es, new_es); this.switch_seg(reg_ds, new_ds); @@ -2202,7 +2262,7 @@ CPU.prototype.iret = function(is_16) this.reg32s[reg_esp] = temp_esp; this.switch_seg(reg_ss, temp_ss); - this.cpl = 3; + this.cpl[0] = 3; this.cpl_changed(); this.update_cs_size(false); @@ -2239,7 +2299,7 @@ CPU.prototype.iret = function(is_16) { throw this.debug.unimpl("not exec"); } - if(info.rpl < this.cpl) + if(info.rpl < this.cpl[0]) { throw this.debug.unimpl("rpl < cpl"); } @@ -2254,7 +2314,7 @@ CPU.prototype.iret = function(is_16) this.trigger_gp(new_cs & ~3); } - if(info.rpl > this.cpl) + if(info.rpl > this.cpl[0]) { // outer privilege return if(is_16) @@ -2300,42 +2360,42 @@ CPU.prototype.iret = function(is_16) if(is_16) { - this.update_eflags(new_flags | this.flags & ~0xFFFF); + this.update_eflags(new_flags | this.flags[0] & ~0xFFFF); } else { this.update_eflags(new_flags); } - this.cpl = info.rpl; + this.cpl[0] = info.rpl; this.cpl_changed(); - //dbg_log("outer privilege return: from=" + this.cpl + " to=" + info.rpl + " ss:esp=" + h(temp_ss, 4) + ":" + h(temp_esp >>> 0, 8), LOG_CPU); + //dbg_log("outer privilege return: from=" + this.cpl[0] + " to=" + info.rpl + " ss:esp=" + h(temp_ss, 4) + ":" + h(temp_esp >>> 0, 8), LOG_CPU); this.switch_seg(reg_ss, temp_ss); this.set_stack_reg(temp_esp); - if(this.cpl === 0) + if(this.cpl[0] === 0) { - this.flags = this.flags & ~flag_vif & ~flag_vip | (new_flags & (flag_vif | flag_vip)); + this.flags[0] = this.flags[0] & ~flag_vif & ~flag_vip | (new_flags & (flag_vif | flag_vip)); } // XXX: Set segment to 0 if it's not usable in the new cpl // XXX: Use cached segment information //var ds_info = this.lookup_segment_selector(this.sreg[reg_ds]); - //if(this.cpl > ds_info.dpl && (!ds_info.is_executable || !ds_info.dc_bit)) this.switch_seg(reg_ds, 0); + //if(this.cpl[0] > ds_info.dpl && (!ds_info.is_executable || !ds_info.dc_bit)) this.switch_seg(reg_ds, 0); // ... } - else if(info.rpl === this.cpl) + else if(info.rpl === this.cpl[0]) { // same privilege return // no exceptions below if(is_16) { this.adjust_stack_reg(3 * 2); - this.update_eflags(new_flags | this.flags & ~0xFFFF); + this.update_eflags(new_flags | this.flags[0] & ~0xFFFF); } else { @@ -2344,9 +2404,9 @@ CPU.prototype.iret = function(is_16) } // update vip and vif, which are not changed by update_eflags - if(this.cpl === 0) + if(this.cpl[0] === 0) { - this.flags = this.flags & ~flag_vif & ~flag_vip | (new_flags & (flag_vif | flag_vip)); + this.flags[0] = this.flags[0] & ~flag_vif & ~flag_vip | (new_flags & (flag_vif | flag_vip)); } } else @@ -2355,14 +2415,14 @@ CPU.prototype.iret = function(is_16) } this.sreg[reg_cs] = new_cs; - dbg_assert((new_cs & 3) === this.cpl); + dbg_assert((new_cs & 3) === this.cpl[0]); this.update_cs_size(info.size); this.segment_limits[reg_cs] = info.effective_limit; this.segment_offsets[reg_cs] = info.base; - this.instruction_pointer = new_eip + this.get_seg(reg_cs) | 0; + this.instruction_pointer[0] = new_eip + this.get_seg(reg_cs) | 0; CPU_LOG_VERBOSE && this.debug.dump_state("iret" + (is_16 ? "16" : "32") + " end"); @@ -2371,7 +2431,7 @@ CPU.prototype.iret = function(is_16) CPU.prototype.switch_cs_real_mode = function(selector) { - dbg_assert(!this.protected_mode || this.vm86_mode()); + dbg_assert(!this.protected_mode[0] || this.vm86_mode()); this.sreg[reg_cs] = selector; this.segment_is_null[reg_cs] = 0; @@ -2385,16 +2445,16 @@ CPU.prototype.far_return = function(eip, selector, stack_adjust) //dbg_log("far return eip=" + h(eip >>> 0, 8) + " cs=" + h(selector, 4) + " stack_adjust=" + h(stack_adjust), LOG_CPU); CPU_LOG_VERBOSE && this.debug.dump_state("far ret start"); - if(!this.protected_mode) + if(!this.protected_mode[0]) { - dbg_assert(!this.is_32); - //dbg_assert(!this.stack_size_32); + dbg_assert(!this.is_32[0]); + //dbg_assert(!this.stack_size_32[0]); } - if(!this.protected_mode || this.vm86_mode()) + if(!this.protected_mode[0] || this.vm86_mode()) { this.switch_cs_real_mode(selector); - this.instruction_pointer = this.get_seg(reg_cs) + eip | 0; + this.instruction_pointer[0] = this.get_seg(reg_cs) + eip | 0; this.adjust_stack_reg(2 * (this.is_osize_32() ? 4 : 2) + stack_adjust); return; } @@ -2425,7 +2485,7 @@ CPU.prototype.far_return = function(eip, selector, stack_adjust) this.trigger_gp(selector & ~3); } - if(info.rpl < this.cpl) + if(info.rpl < this.cpl[0]) { dbg_log("cs rpl < cpl: " + h(selector), LOG_CPU); this.trigger_gp(selector & ~3); @@ -2450,9 +2510,9 @@ CPU.prototype.far_return = function(eip, selector, stack_adjust) this.trigger_np(selector & ~3); } - if(info.rpl > this.cpl) + if(info.rpl > this.cpl[0]) { - dbg_log("far return privilege change cs: " + h(selector) + " from=" + this.cpl + " to=" + info.rpl + " is_16=" + this.is_osize_32(), LOG_CPU); + dbg_log("far return privilege change cs: " + h(selector) + " from=" + this.cpl[0] + " to=" + info.rpl + " is_16=" + this.is_osize_32(), LOG_CPU); if(this.is_osize_32()) { @@ -2469,7 +2529,7 @@ CPU.prototype.far_return = function(eip, selector, stack_adjust) var temp_ss = this.safe_read16(this.get_stack_pointer(stack_adjust + 6)); } - this.cpl = info.rpl; + this.cpl[0] = info.rpl; this.cpl_changed(); // XXX: Can raise, conditions should be checked before side effects @@ -2501,7 +2561,7 @@ CPU.prototype.far_return = function(eip, selector, stack_adjust) } } - //dbg_assert(this.cpl === info.dpl); + //dbg_assert(this.cpl[0] === info.dpl); this.update_cs_size(info.size); @@ -2511,10 +2571,9 @@ CPU.prototype.far_return = function(eip, selector, stack_adjust) this.segment_offsets[reg_cs] = info.base; this.sreg[reg_cs] = selector; + dbg_assert((selector & 3) === this.cpl[0]); - dbg_assert((selector & 3) === this.cpl); - - this.instruction_pointer = this.get_seg(reg_cs) + eip | 0; + this.instruction_pointer[0] = this.get_seg(reg_cs) + eip | 0; //dbg_log("far return to:", LOG_CPU) CPU_LOG_VERBOSE && this.debug.dump_state("far ret end"); @@ -2522,12 +2581,13 @@ CPU.prototype.far_return = function(eip, selector, stack_adjust) CPU.prototype.far_jump = function(eip, selector, is_call) { + is_call = !!is_call; dbg_assert(typeof selector === "number" && selector < 0x10000 && selector >= 0); //dbg_log("far " + ["jump", "call"][+is_call] + " eip=" + h(eip >>> 0, 8) + " cs=" + h(selector, 4), LOG_CPU); CPU_LOG_VERBOSE && this.debug.dump_state("far " + ["jump", "call"][+is_call]); - if(!this.protected_mode || this.vm86_mode()) + if(!this.protected_mode[0] || this.vm86_mode()) { if(is_call) { @@ -2545,7 +2605,7 @@ CPU.prototype.far_jump = function(eip, selector, is_call) } } this.switch_cs_real_mode(selector); - this.instruction_pointer = this.get_seg(reg_cs) + eip | 0; + this.instruction_pointer[0] = this.get_seg(reg_cs) + eip | 0; return; } @@ -2574,7 +2634,7 @@ CPU.prototype.far_jump = function(eip, selector, is_call) // call gate var is_16 = info.type === 4; - if(info.dpl < this.cpl || info.dpl < info.rpl) + if(info.dpl < this.cpl[0] || info.dpl < info.rpl) { dbg_log("#gp cs gate dpl < cpl or dpl < rpl: " + h(selector), LOG_CPU); this.trigger_gp(selector & ~3); @@ -2607,7 +2667,7 @@ CPU.prototype.far_jump = function(eip, selector, is_call) this.trigger_gp(cs_selector & ~3); } - if(cs_info.dpl > this.cpl) + if(cs_info.dpl > this.cpl[0]) { dbg_log("#gp dpl > cpl: " + h(cs_selector), LOG_CPU); this.trigger_gp(cs_selector & ~3); @@ -2619,9 +2679,9 @@ CPU.prototype.far_jump = function(eip, selector, is_call) this.trigger_np(cs_selector & ~3); } - if(!cs_info.dc_bit && cs_info.dpl < this.cpl) + if(!cs_info.dc_bit && cs_info.dpl < this.cpl[0]) { - dbg_log("more privilege call gate is_16=" + is_16 + " from=" + this.cpl + " to=" + cs_info.dpl); + dbg_log("more privilege call gate is_16=" + is_16 + " from=" + this.cpl[0] + " to=" + cs_info.dpl); var tss_stack_addr = this.get_tss_stack_addr(cs_info.dpl); if(this.tss_size_32) @@ -2685,7 +2745,7 @@ CPU.prototype.far_jump = function(eip, selector, is_call) //dbg_log("old_esp=" + h(old_esp)); - this.cpl = cs_info.dpl; + this.cpl[0] = cs_info.dpl; this.cpl_changed(); this.update_cs_size(cs_info.size); @@ -2739,7 +2799,7 @@ CPU.prototype.far_jump = function(eip, selector, is_call) } else { - dbg_log("same privilege call gate is_16=" + is_16 + " from=" + this.cpl + " to=" + cs_info.dpl + " conforming=" + cs_info.dc_bit); + dbg_log("same privilege call gate is_16=" + is_16 + " from=" + this.cpl[0] + " to=" + cs_info.dpl + " conforming=" + cs_info.dc_bit); // ok if(is_call) @@ -2775,10 +2835,10 @@ CPU.prototype.far_jump = function(eip, selector, is_call) this.segment_limits[reg_cs] = cs_info.effective_limit; //this.segment_infos[reg_cs] = 0; // TODO this.segment_offsets[reg_cs] = cs_info.base; - this.sreg[reg_cs] = cs_selector & ~3 | this.cpl; - dbg_assert((this.sreg[reg_cs] & 3) === this.cpl); + this.sreg[reg_cs] = cs_selector & ~3 | this.cpl[0]; + dbg_assert((this.sreg[reg_cs] & 3) === this.cpl[0]); - this.instruction_pointer = this.get_seg(reg_cs) + new_eip | 0; + this.instruction_pointer[0] = this.get_seg(reg_cs) + new_eip | 0; } else { @@ -2797,7 +2857,7 @@ CPU.prototype.far_jump = function(eip, selector, is_call) if(info.dc_bit) { // conforming code segment - if(info.dpl > this.cpl) + if(info.dpl > this.cpl[0]) { dbg_log("#gp cs dpl > cpl: " + h(selector), LOG_CPU); this.trigger_gp(selector & ~3); @@ -2807,7 +2867,7 @@ CPU.prototype.far_jump = function(eip, selector, is_call) { // non-conforming code segment - if(info.rpl > this.cpl || info.dpl !== this.cpl) + if(info.rpl > this.cpl[0] || info.dpl !== this.cpl[0]) { dbg_log("#gp cs rpl > cpl or dpl != cpl: " + h(selector), LOG_CPU); this.trigger_gp(selector & ~3); @@ -2846,9 +2906,9 @@ CPU.prototype.far_jump = function(eip, selector, is_call) //this.segment_infos[reg_cs] = 0; // TODO this.segment_offsets[reg_cs] = info.base; - this.sreg[reg_cs] = selector & ~3 | this.cpl; + this.sreg[reg_cs] = selector & ~3 | this.cpl[0]; - this.instruction_pointer = this.get_seg(reg_cs) + eip | 0; + this.instruction_pointer[0] = this.get_seg(reg_cs) + eip | 0; } //dbg_log("far " + ["jump", "call"][+is_call] + " to:", LOG_CPU) @@ -2883,7 +2943,7 @@ CPU.prototype.get_tss_stack_addr = function(dpl) dbg_assert((tss_stack_addr & 0xFFF) <= 0x1000 - 4); } - if(this.paging) + if(this.paging[0]) { tss_stack_addr = this.translate_address_system_read(tss_stack_addr); } @@ -2978,7 +3038,7 @@ CPU.prototype.do_task_switch = function(selector, error_code) var new_cr3 = this.safe_read32s(new_tsr_offset + TSR_CR3); - this.flags &= ~flag_vm; + this.flags[0] &= ~flag_vm; var new_eip = this.safe_read32s(new_tsr_offset + TSR_EIP); var new_cs = this.safe_read16(new_tsr_offset + TSR_CS); @@ -3054,7 +3114,7 @@ CPU.prototype.do_task_switch = function(selector, error_code) if(true /* call or int */) { - this.flags |= flag_nt; + this.flags[0] |= flag_nt; } var new_ldt = this.safe_read16(new_tsr_offset + TSR_LDT); @@ -3076,7 +3136,7 @@ CPU.prototype.do_task_switch = function(selector, error_code) this.switch_seg(reg_fs, this.safe_read16(new_tsr_offset + TSR_FS)); this.switch_seg(reg_gs, this.safe_read16(new_tsr_offset + TSR_GS)); - this.instruction_pointer = this.get_seg(reg_cs) + new_eip | 0; + this.instruction_pointer[0] = this.get_seg(reg_cs) + new_eip | 0; this.segment_offsets[reg_tr] = descriptor.base; this.segment_limits[reg_tr] = descriptor.effective_limit; @@ -3103,12 +3163,12 @@ CPU.prototype.do_task_switch = function(selector, error_code) CPU.prototype.hlt_op = function() { - if(this.cpl) + if(this.cpl[0]) { this.trigger_gp(0); } - if((this.flags & flag_interrupt) === 0) + if((this.flags[0] & flag_interrupt) === 0) { this.debug.show("cpu halted"); this.bus.send("cpu-event-halt"); @@ -3148,7 +3208,7 @@ CPU.prototype.raise_exception = function(interrupt_nr) // this.debug.dump_state(); //} - this.call_interrupt_vector(interrupt_nr, false, false); + this.call_interrupt_vector(interrupt_nr, false, false, 0); throw MAGIC_CPU_EXCEPTION; }; @@ -3163,49 +3223,49 @@ CPU.prototype.raise_exception_with_code = function(interrupt_nr, error_code) // this.debug.dump_regs(); //} - this.call_interrupt_vector(interrupt_nr, false, error_code); + this.call_interrupt_vector(interrupt_nr, false, true, error_code); throw MAGIC_CPU_EXCEPTION; }; CPU.prototype.trigger_de = function() { - this.instruction_pointer = this.previous_ip; + this.instruction_pointer[0] = this.previous_ip[0]; this.raise_exception(0); }; CPU.prototype.trigger_ud = function() { - this.instruction_pointer = this.previous_ip; + this.instruction_pointer[0] = this.previous_ip[0]; this.raise_exception(6); }; CPU.prototype.trigger_nm = function() { - this.instruction_pointer = this.previous_ip; + this.instruction_pointer[0] = this.previous_ip[0]; this.raise_exception(7); }; CPU.prototype.trigger_ts = function(code) { - this.instruction_pointer = this.previous_ip; + this.instruction_pointer[0] = this.previous_ip[0]; this.raise_exception_with_code(10, code); }; CPU.prototype.trigger_gp = function(code) { - this.instruction_pointer = this.previous_ip; + this.instruction_pointer[0] = this.previous_ip[0]; this.raise_exception_with_code(13, code); }; CPU.prototype.trigger_np = function(code) { - this.instruction_pointer = this.previous_ip; + this.instruction_pointer[0] = this.previous_ip[0]; this.raise_exception_with_code(11, code); }; CPU.prototype.trigger_ss = function(code) { - this.instruction_pointer = this.previous_ip; + this.instruction_pointer[0] = this.previous_ip[0]; this.raise_exception_with_code(12, code); }; @@ -3259,19 +3319,29 @@ CPU.prototype.unimplemented_sse = function() this.trigger_ud(); }; -CPU.prototype.get_seg_prefix_ds = function() +CPU.prototype.unimplemented_sse_wasm = function() { - return this.get_seg_prefix(reg_ds); + this.instruction_pointer[0] -= 1; + + this.table0F_32[this.read_op0F()](this); }; -CPU.prototype.get_seg_prefix_ss = function() +CPU.prototype.get_seg_prefix_ds = function(offset) { - return this.get_seg_prefix(reg_ss); + offset = offset || 0; + return this.get_seg_prefix(reg_ds) + offset | 0; }; -CPU.prototype.get_seg_prefix_cs = function() +CPU.prototype.get_seg_prefix_ss = function(offset) { - return this.get_seg_prefix(reg_cs); + offset = offset || 0; + return this.get_seg_prefix(reg_ss) + offset | 0; +}; + +CPU.prototype.get_seg_prefix_cs = function(offset) +{ + offset = offset || 0; + return this.get_seg_prefix(reg_cs) + offset | 0; }; /** @@ -3280,7 +3350,7 @@ CPU.prototype.get_seg_prefix_cs = function() */ CPU.prototype.get_seg_prefix = function(default_segment /*, offset*/) { - var prefix = this.prefixes & PREFIX_MASK_SEGMENT; + var prefix = this.prefixes[0] & PREFIX_MASK_SEGMENT; if(prefix) { @@ -3307,7 +3377,7 @@ CPU.prototype.get_seg = function(segment /*, offset*/) { dbg_assert(segment >= 0 && segment < 8); - if(this.protected_mode) + if(this.protected_mode[0]) { if(this.segment_is_null[segment]) { @@ -3328,10 +3398,11 @@ CPU.prototype.get_seg = function(segment /*, offset*/) CPU.prototype.read_e8 = function() { - if(this.modrm_byte < 0xC0) { - return this.safe_read8(this.modrm_resolve(this.modrm_byte)); + var modrm_byte = this.modrm_byte[0]; + if(modrm_byte < 0xC0) { + return this.safe_read8(this.modrm_resolve(modrm_byte)); } else { - return this.reg8[this.modrm_byte << 2 & 0xC | this.modrm_byte >> 2 & 1]; + return this.wm.funcs['_read_e8_partial_branch'](); } }; @@ -3342,10 +3413,11 @@ CPU.prototype.read_e8s = function() CPU.prototype.read_e16 = function() { - if(this.modrm_byte < 0xC0) { - return this.safe_read16(this.modrm_resolve(this.modrm_byte)); + var modrm_byte = this.modrm_byte[0]; + if(modrm_byte < 0xC0) { + return this.safe_read16(this.modrm_resolve(modrm_byte)); } else { - return this.reg16[this.modrm_byte << 1 & 14]; + return this.reg16[modrm_byte << 1 & 14]; } }; @@ -3356,10 +3428,11 @@ CPU.prototype.read_e16s = function() CPU.prototype.read_e32s = function() { - if(this.modrm_byte < 0xC0) { - return this.safe_read32s(this.modrm_resolve(this.modrm_byte)); + var modrm_byte = this.modrm_byte[0]; + if(modrm_byte < 0xC0) { + return this.safe_read32s(this.modrm_resolve(modrm_byte)); } else { - return this.reg32s[this.modrm_byte & 7]; + return this.reg32s[modrm_byte & 7]; } }; @@ -3435,31 +3508,34 @@ CPU.prototype.read_xmm_mem128s_unaligned = function() CPU.prototype.set_e8 = function(value) { - if(this.modrm_byte < 0xC0) { - var addr = this.modrm_resolve(this.modrm_byte); + var modrm_byte = this.modrm_byte[0]; + if(modrm_byte < 0xC0) { + var addr = this.modrm_resolve(modrm_byte); this.safe_write8(addr, value); } else { - this.reg8[this.modrm_byte << 2 & 0xC | this.modrm_byte >> 2 & 1] = value; + this.reg8[modrm_byte << 2 & 0xC | modrm_byte >> 2 & 1] = value; } }; CPU.prototype.set_e16 = function(value) { - if(this.modrm_byte < 0xC0) { - var addr = this.modrm_resolve(this.modrm_byte); + var modrm_byte = this.modrm_byte[0]; + if(modrm_byte < 0xC0) { + var addr = this.modrm_resolve(modrm_byte); this.safe_write16(addr, value); } else { - this.reg16[this.modrm_byte << 1 & 14] = value; + this.reg16[modrm_byte << 1 & 14] = value; } }; CPU.prototype.set_e32 = function(value) { - if(this.modrm_byte < 0xC0) { - var addr = this.modrm_resolve(this.modrm_byte); + var modrm_byte = this.modrm_byte[0]; + if(modrm_byte < 0xC0) { + var addr = this.modrm_resolve(modrm_byte); this.safe_write32(addr, value); } else { - this.reg32s[this.modrm_byte & 7] = value; + this.reg32s[modrm_byte & 7] = value; } }; @@ -3476,141 +3552,147 @@ CPU.prototype.set_mmx_mem64s = function(low, high) CPU.prototype.read_write_e8 = function() { - if(this.modrm_byte < 0xC0) { - var virt_addr = this.modrm_resolve(this.modrm_byte); - this.phys_addr = this.translate_address_write(virt_addr); - return this.read8(this.phys_addr); + var modrm_byte = this.modrm_byte[0]; + if(modrm_byte < 0xC0) { + var virt_addr = this.modrm_resolve(modrm_byte); + this.phys_addr[0] = this.translate_address_write(virt_addr); + return this.read8(this.phys_addr[0]); } else { - return this.reg8[this.modrm_byte << 2 & 0xC | this.modrm_byte >> 2 & 1]; + return this.reg8[modrm_byte << 2 & 0xC | modrm_byte >> 2 & 1]; } }; CPU.prototype.write_e8 = function(value) { - if(this.modrm_byte < 0xC0) { - this.write8(this.phys_addr, value); + var modrm_byte = this.modrm_byte[0]; + if(modrm_byte < 0xC0) { + this.write8(this.phys_addr[0], value); } else { - this.reg8[this.modrm_byte << 2 & 0xC | this.modrm_byte >> 2 & 1] = value; + this.reg8[modrm_byte << 2 & 0xC | modrm_byte >> 2 & 1] = value; } }; CPU.prototype.read_write_e16 = function() { - if(this.modrm_byte < 0xC0) { - var virt_addr = this.modrm_resolve(this.modrm_byte); - this.phys_addr = this.translate_address_write(virt_addr); - if(this.paging && (virt_addr & 0xFFF) === 0xFFF) { - this.phys_addr_high = this.translate_address_write(virt_addr + 1 | 0); - dbg_assert(this.phys_addr_high); - return this.virt_boundary_read16(this.phys_addr, this.phys_addr_high); + var modrm_byte = this.modrm_byte[0]; + if(modrm_byte < 0xC0) { + var virt_addr = this.modrm_resolve(modrm_byte); + this.phys_addr[0] = this.translate_address_write(virt_addr); + if(this.paging[0] && (virt_addr & 0xFFF) === 0xFFF) { + this.phys_addr_high[0] = this.translate_address_write(virt_addr + 1 | 0); + dbg_assert(this.phys_addr_high[0]); + return this.virt_boundary_read16(this.phys_addr[0], this.phys_addr_high[0]); } else { - this.phys_addr_high = 0; - return this.read16(this.phys_addr); + this.phys_addr_high[0] = 0; + return this.read16(this.phys_addr[0]); } } else { - return this.reg16[this.modrm_byte << 1 & 14]; + return this.reg16[modrm_byte << 1 & 14]; } }; CPU.prototype.write_e16 = function(value) { - if(this.modrm_byte < 0xC0) { - if(this.phys_addr_high) { - this.virt_boundary_write16(this.phys_addr, this.phys_addr_high, value); + var modrm_byte = this.modrm_byte[0]; + if(modrm_byte < 0xC0) { + if(this.phys_addr_high[0]) { + this.virt_boundary_write16(this.phys_addr[0], this.phys_addr_high[0], value); } else { - this.write16(this.phys_addr, value); + this.write16(this.phys_addr[0], value); } } else { - this.reg16[this.modrm_byte << 1 & 14] = value; + this.reg16[modrm_byte << 1 & 14] = value; } }; CPU.prototype.read_write_e32 = function() { - if(this.modrm_byte < 0xC0) { - var virt_addr = this.modrm_resolve(this.modrm_byte); - this.phys_addr = this.translate_address_write(virt_addr); - if(this.paging && (virt_addr & 0xFFF) >= 0xFFD) { - //this.phys_addr_high = this.translate_address_write(virt_addr + 3 | 0); - this.phys_addr_high = this.translate_address_write(virt_addr + 3 & ~3) | (virt_addr + 3) & 3; - dbg_assert(this.phys_addr_high); - return this.virt_boundary_read32s(this.phys_addr, this.phys_addr_high); + var modrm_byte = this.modrm_byte[0]; + if(modrm_byte < 0xC0) { + var virt_addr = this.modrm_resolve(modrm_byte); + this.phys_addr[0] = this.translate_address_write(virt_addr); + if(this.paging[0] && (virt_addr & 0xFFF) >= 0xFFD) { + //this.phys_addr_high[0] = this.translate_address_write(virt_addr + 3 | 0); + this.phys_addr_high[0] = this.translate_address_write(virt_addr + 3 & ~3) | (virt_addr + 3) & 3; + dbg_assert(this.phys_addr_high[0]); + return this.virt_boundary_read32s(this.phys_addr[0], this.phys_addr_high[0]); } else { - this.phys_addr_high = 0; - return this.read32s(this.phys_addr); + this.phys_addr_high[0] = 0; + return this.read32s(this.phys_addr[0]); } } else { - return this.reg32s[this.modrm_byte & 7]; + return this.reg32s[modrm_byte & 7]; } }; CPU.prototype.write_e32 = function(value) { - if(this.modrm_byte < 0xC0) { - if(this.phys_addr_high) { - this.virt_boundary_write32(this.phys_addr, this.phys_addr_high, value); + var modrm_byte = this.modrm_byte[0]; + if(modrm_byte < 0xC0) { + if(this.phys_addr_high[0]) { + this.virt_boundary_write32(this.phys_addr[0], this.phys_addr_high[0], value); } else { - this.write32(this.phys_addr, value); + this.write32(this.phys_addr[0], value); } } else { - this.reg32s[this.modrm_byte & 7] = value; + this.reg32s[modrm_byte & 7] = value; } }; CPU.prototype.read_reg_e16 = function() { - return this.reg16[this.modrm_byte << 1 & 14]; + return this.reg16[this.modrm_byte[0] << 1 & 14]; }; CPU.prototype.write_reg_e16 = function(value) { - this.reg16[this.modrm_byte << 1 & 14] = value; + this.reg16[this.modrm_byte[0] << 1 & 14] = value; }; CPU.prototype.read_reg_e32s = function() { - return this.reg32s[this.modrm_byte & 7]; + return this.reg32s[this.modrm_byte[0] & 7]; }; CPU.prototype.write_reg_e32 = function(value) { - this.reg32s[this.modrm_byte & 7] = value; + this.reg32s[this.modrm_byte[0] & 7] = value; }; CPU.prototype.read_g8 = function() { - return this.reg8[this.modrm_byte >> 1 & 0xC | this.modrm_byte >> 5 & 1]; + return this.reg8[this.modrm_byte[0] >> 1 & 0xC | this.modrm_byte[0] >> 5 & 1]; }; CPU.prototype.write_g8 = function(value) { - this.reg8[this.modrm_byte >> 1 & 0xC | this.modrm_byte >> 5 & 1] = value; + this.reg8[this.modrm_byte[0] >> 1 & 0xC | this.modrm_byte[0] >> 5 & 1] = value; }; CPU.prototype.read_g16 = function() { - return this.reg16[this.modrm_byte >> 2 & 14]; + return this.reg16[this.modrm_byte[0] >> 2 & 14]; }; CPU.prototype.read_g16s = function() { - return this.reg16s[this.modrm_byte >> 2 & 14]; + return this.reg16s[this.modrm_byte[0] >> 2 & 14]; }; CPU.prototype.write_g16 = function(value) { - this.reg16[this.modrm_byte >> 2 & 14] = value; + this.reg16[this.modrm_byte[0] >> 2 & 14] = value; }; CPU.prototype.read_g32s = function() { - return this.reg32s[this.modrm_byte >> 3 & 7]; + return this.reg32s[this.modrm_byte[0] >> 3 & 7]; }; CPU.prototype.write_g32 = function(value) { - this.reg32[this.modrm_byte >> 3 & 7] = value; + this.reg32[this.modrm_byte[0] >> 3 & 7] = value; }; CPU.prototype.read_xmm64s = function() @@ -3666,8 +3748,8 @@ CPU.prototype.pic_call_irq = function(int) { try { - this.previous_ip = this.instruction_pointer; - this.call_interrupt_vector(int, false, false); + this.previous_ip[0] = this.instruction_pointer[0]; + this.call_interrupt_vector(int, false, false, 0); } catch(e) { @@ -3681,7 +3763,7 @@ CPU.prototype.handle_irqs = function() this.diverged(); - if((this.flags & flag_interrupt) && !this.page_fault) + if((this.flags[0] & flag_interrupt) && !this.page_fault) { if(this.devices.pic) { @@ -3724,7 +3806,7 @@ CPU.prototype.device_lower_irq = function(i) CPU.prototype.test_privileges_for_io = function(port, size) { - if(this.protected_mode && (this.cpl > this.getiopl() || (this.flags & flag_vm))) + if(this.protected_mode[0] && (this.cpl[0] > this.getiopl() || (this.flags[0] & flag_vm))) { if(!this.tss_size_32) { @@ -3887,19 +3969,19 @@ CPU.prototype.cpuid = function() CPU.prototype.update_cs_size = function(new_size) { - dbg_assert(typeof new_size === "boolean"); + new_size = Boolean(new_size); - if(this.is_32 !== new_size) + if(Boolean(this.is_32[0]) !== new_size) { this.clear_instruction_cache(); - this.is_32 = new_size; + this.is_32[0] = +new_size; this.update_operand_size(); } }; CPU.prototype.update_operand_size = function() { - if(this.is_32) + if(this.is_32[0]) { this.table = this.table32; } @@ -3955,8 +4037,8 @@ CPU.prototype.lookup_segment_selector = function(selector) if(is_gdt) { - table_offset = this.gdtr_offset; - table_limit = this.gdtr_size; + table_offset = this.gdtr_offset[0]; + table_limit = this.gdtr_size[0]; } else { @@ -3981,7 +4063,7 @@ CPU.prototype.lookup_segment_selector = function(selector) table_offset = table_offset + selector_offset | 0; - if(this.paging) + if(this.paging[0]) { table_offset = this.translate_address_system_read(table_offset); } @@ -4041,7 +4123,7 @@ CPU.prototype.switch_seg = function(reg, selector) dbg_assert(reg >= 0 && reg <= 5); dbg_assert(typeof selector === "number" && selector < 0x10000 && selector >= 0); - if(!this.protected_mode || this.vm86_mode()) + if(!this.protected_mode[0] || this.vm86_mode()) { this.sreg[reg] = selector; this.segment_is_null[reg] = 0; @@ -4049,7 +4131,7 @@ CPU.prototype.switch_seg = function(reg, selector) if(reg === reg_ss) { - this.stack_size_32 = false; + this.stack_size_32[0] = +false; } return; } @@ -4067,9 +4149,9 @@ CPU.prototype.switch_seg = function(reg, selector) if(!info.is_valid || info.is_system || - info.rpl !== this.cpl || + info.rpl !== this.cpl[0] || !info.is_writable || - info.dpl !== this.cpl) + info.dpl !== this.cpl[0]) { dbg_log("#GP for loading invalid in SS sel=" + h(selector, 4), LOG_CPU); dbg_trace(LOG_CPU); @@ -4083,7 +4165,7 @@ CPU.prototype.switch_seg = function(reg, selector) this.trigger_ss(selector & ~3); } - this.stack_size_32 = info.size; + this.stack_size_32[0] = info.size; } else if(reg === reg_cs) { @@ -4106,7 +4188,7 @@ CPU.prototype.switch_seg = function(reg, selector) info.is_system || !info.is_readable || (!info.is_conforming_executable && - (info.rpl > info.dpl || this.cpl > info.dpl)) + (info.rpl > info.dpl || this.cpl[0] > info.dpl)) ) { dbg_log("#GP for loading invalid in seg " + reg + " sel=" + h(selector, 4), LOG_CPU); this.debug.dump_state(); @@ -4228,16 +4310,16 @@ CPU.prototype.load_ldt = function(selector) CPU.prototype.arpl = function(seg, r16) { - this.flags_changed &= ~flag_zero; + this.flags_changed[0] &= ~flag_zero; if((seg & 3) < (this.reg16[r16] & 3)) { - this.flags |= flag_zero; + this.flags[0] |= flag_zero; return seg & ~3 | this.reg16[r16] & 3; } else { - this.flags &= ~flag_zero; + this.flags[0] &= ~flag_zero; return seg; } }; @@ -4251,21 +4333,21 @@ CPU.prototype.lar = function(selector, original) 1 << 0xD | 1 << 0xE | 1 << 0xF; var info = this.lookup_segment_selector(selector); - this.flags_changed &= ~flag_zero; + this.flags_changed[0] &= ~flag_zero; - var dpl_bad = info.dpl < this.cpl || info.dpl < info.rpl; + var dpl_bad = info.dpl < this.cpl[0] || info.dpl < info.rpl; if(info.is_null || !info.is_valid || (info.is_system ? (LAR_INVALID_TYPE >> info.type & 1) || dpl_bad : !info.is_conforming_executable && dpl_bad) ) { - this.flags &= ~flag_zero; + this.flags[0] &= ~flag_zero; dbg_log("lar: invalid selector=" + h(selector, 4) + " is_null=" + info.is_null, LOG_CPU); return original; } else { - this.flags |= flag_zero; + this.flags[0] |= flag_zero; return info.raw1 & 0x00FFFF00; } }; @@ -4279,21 +4361,21 @@ CPU.prototype.lsl = function(selector, original) 1 << 0xA | 1 << 0xC | 1 << 0xD | 1 << 0xE | 1 << 0xF; var info = this.lookup_segment_selector(selector); - this.flags_changed &= ~flag_zero; + this.flags_changed[0] &= ~flag_zero; - var dpl_bad = info.dpl < this.cpl || info.dpl < info.rpl; + var dpl_bad = info.dpl < this.cpl[0] || info.dpl < info.rpl; if(info.is_null || !info.is_valid || (info.is_system ? (LSL_INVALID_TYPE >> info.type & 1) || dpl_bad : !info.is_conforming_executable && dpl_bad) ) { - this.flags &= ~flag_zero; + this.flags[0] &= ~flag_zero; dbg_log("lsl: invalid selector=" + h(selector, 4) + " is_null=" + info.is_null, LOG_CPU); return original; } else { - this.flags |= flag_zero; + this.flags[0] |= flag_zero; return info.effective_limit | 0; } @@ -4302,46 +4384,45 @@ CPU.prototype.lsl = function(selector, original) CPU.prototype.verr = function(selector) { var info = this.lookup_segment_selector(selector); - this.flags_changed &= ~flag_zero; + this.flags_changed[0] &= ~flag_zero; if(info.is_null || !info.is_valid || info.is_system || !info.is_readable || - (!info.is_conforming_executable && (info.dpl < this.cpl || info.dpl < info.rpl))) + (!info.is_conforming_executable && (info.dpl < this.cpl[0] || info.dpl < info.rpl))) { dbg_log("verr -> invalid. selector=" + h(selector, 4), LOG_CPU); - this.flags &= ~flag_zero; + this.flags[0] &= ~flag_zero; } else { dbg_log("verr -> valid. selector=" + h(selector, 4), LOG_CPU); - this.flags |= flag_zero; + this.flags[0] |= flag_zero; } }; CPU.prototype.verw = function(selector) { var info = this.lookup_segment_selector(selector); - this.flags_changed &= ~flag_zero; + this.flags_changed[0] &= ~flag_zero; if(info.is_null || !info.is_valid || info.is_system || !info.is_writable || - info.dpl < this.cpl || info.dpl < info.rpl) + info.dpl < this.cpl[0] || info.dpl < info.rpl) { dbg_log("verw invalid " + " " + h(selector) + " " + info.is_null + " " + !info.is_valid + " " + info.is_system + " " + !info.is_writable + " " + - (info.dpl < this.cpl) + " " + (info.dpl < info.rpl) + " " + LOG_CPU); - this.flags &= ~flag_zero; + (info.dpl < this.cpl[0]) + " " + (info.dpl < info.rpl) + " " + LOG_CPU); + this.flags[0] &= ~flag_zero; } else { - dbg_log("verw valid", LOG_CPU); - this.flags |= flag_zero; + this.flags[0] |= flag_zero; } }; CPU.prototype.clear_tlb = function() { // clear tlb excluding global pages - this.last_virt_eip = -1; - this.last_virt_esp = -1; + this.last_virt_eip[0] = -1; + this.last_virt_esp[0] = -1; this.tlb_info.set(this.tlb_info_global); @@ -4353,7 +4434,10 @@ CPU.prototype.full_clear_tlb = function() //dbg_log("TLB full clear", LOG_CPU); // clear tlb including global pages - var buf32 = new Int32Array(this.tlb_info_global.buffer); + var buf32 = new Int32Array( + this.tlb_info_global.buffer, + this.tlb_info_global.byteOffset, + this.tlb_info_global.length >>> 2); for(var i = 0; i < (1 << 18); ) { buf32[i++] = buf32[i++] = buf32[i++] = buf32[i++] = 0; @@ -4370,18 +4454,18 @@ CPU.prototype.invlpg = function(addr) this.tlb_info[page] = 0; this.tlb_info_global[page] = 0; - this.last_virt_eip = -1; - this.last_virt_esp = -1; + this.last_virt_eip[0] = -1; + this.last_virt_esp[0] = -1; }; CPU.prototype.translate_address_read = function(addr) { - if(!this.paging) + if(!this.paging[0]) { return addr; } - if(this.cpl === 3) + if(this.cpl[0] === 3) { return this.translate_address_user_read(addr); } @@ -4393,12 +4477,12 @@ CPU.prototype.translate_address_read = function(addr) CPU.prototype.translate_address_write = function(addr) { - if(!this.paging) + if(!this.paging[0]) { return addr; } - if(this.cpl === 3) + if(this.cpl[0] === 3) { return this.translate_address_user_write(addr); } @@ -4410,7 +4494,7 @@ CPU.prototype.translate_address_write = function(addr) CPU.prototype.translate_address_user_write = function(addr) { - if(!this.paging) + if(!this.paging[0]) { return addr; } @@ -4429,7 +4513,7 @@ CPU.prototype.translate_address_user_write = function(addr) CPU.prototype.translate_address_user_read = function(addr) { - if(!this.paging) + if(!this.paging[0]) { return addr; } @@ -4448,7 +4532,7 @@ CPU.prototype.translate_address_user_read = function(addr) CPU.prototype.translate_address_system_write = function(addr) { - if(!this.paging) + if(!this.paging[0]) { return addr; } @@ -4467,7 +4551,7 @@ CPU.prototype.translate_address_system_write = function(addr) CPU.prototype.translate_address_system_read = function(addr) { - if(!this.paging) + if(!this.paging[0]) { return addr; } @@ -4542,7 +4626,7 @@ CPU.prototype.do_page_translation = function(addr, for_writing, user) } } - if(page_dir_entry & this.page_size_extensions) + if(page_dir_entry & this.page_size_extensions[0]) { // size bit is set @@ -4642,12 +4726,12 @@ CPU.prototype.writable_or_pagefault = function(addr, size) dbg_assert(size < 0x1000, "not supported yet"); dbg_assert(size > 0); - if(!this.paging) + if(!this.paging[0]) { return; } - var user = this.cpl === 3 ? 1 : 0, + var user = this.cpl[0] === 3 ? 1 : 0, mask = user ? TLB_USER_WRITE : TLB_SYSTEM_WRITE, page = addr >>> 12; @@ -4686,21 +4770,21 @@ CPU.prototype.trigger_pagefault = function(write, user, present) this.tlb_info[page] = 0; this.tlb_info_global[page] = 0; - this.instruction_pointer = this.previous_ip; + this.instruction_pointer[0] = this.previous_ip[0]; this.page_fault = true; - this.call_interrupt_vector(14, false, user << 2 | write << 1 | present); + this.call_interrupt_vector(14, false, true, user << 2 | write << 1 | present); throw MAGIC_CPU_EXCEPTION; }; CPU.prototype.is_osize_32 = function() { - return this.is_32 !== ((this.prefixes & PREFIX_MASK_OPSIZE) === PREFIX_MASK_OPSIZE); + return Boolean(this.is_32[0]) !== ((this.prefixes[0] & PREFIX_MASK_OPSIZE) === PREFIX_MASK_OPSIZE); }; CPU.prototype.is_asize_32 = function() { - return this.is_32 !== ((this.prefixes & PREFIX_MASK_ADDRSIZE) === PREFIX_MASK_ADDRSIZE); + return Boolean(this.is_32[0]) !== ((this.prefixes[0] & PREFIX_MASK_ADDRSIZE) === PREFIX_MASK_ADDRSIZE); }; CPU.prototype.get_reg_asize = function(reg) diff --git a/src/debug.js b/src/debug.js index c7d5771f..97453d25 100644 --- a/src/debug.js +++ b/src/debug.js @@ -130,7 +130,7 @@ CPU.prototype.debug_init = function() cpu.running = false; var a = parseInt(prompt("input hex", ""), 16); - if(a) while(cpu.instruction_pointer != a) step(); + if(a) while(cpu.instruction_pointer[0] != a) step(); } // http://ref.x86asm.net/x86reference.xml @@ -215,15 +215,17 @@ CPU.prototype.debug_init = function() function get_state(where) { - var vm = (cpu.flags & flag_vm) ? 1 : 0; - var mode = cpu.protected_mode ? vm ? "vm86" : "prot" : "real"; + if(!DEBUG) return; + + var mode = cpu.protected_mode[0] ? "prot" : "real"; + var vm = (cpu.flags[0] & flag_vm) ? 1 : 0; var flags = cpu.get_eflags(); var iopl = cpu.getiopl(); - var cpl = cpu.cpl; + var cpl = cpu.cpl[0]; var cs_eip = h(cpu.sreg[reg_cs], 4) + ":" + h(cpu.get_real_eip() >>> 0, 8); var ss_esp = h(cpu.sreg[reg_ss], 4) + ":" + h(cpu.get_stack_reg() >>> 0, 8); - var op_size = cpu.is_32 ? "32" : "16"; - var if_ = (cpu.flags & flag_interrupt) ? 1 : 0; + var op_size = cpu.is_32[0] ? "32" : "16"; + var if_ = (cpu.flags[0] & flag_interrupt) ? 1 : 0; var flag_names = { [flag_carry]: "c", @@ -253,12 +255,12 @@ CPU.prototype.debug_init = function() } } - return ("mode=" + mode + "/" + op_size + " paging=" + (+cpu.paging) + + return ("mode=" + mode + "/" + op_size + " paging=" + (+cpu.paging[0]) + " iopl=" + iopl + " cpl=" + cpl + " if=" + if_ + " cs:eip=" + cs_eip + " cs_off=" + h(cpu.get_seg(reg_cs) >>> 0, 8) + " flgs=" + h(cpu.get_eflags() >>> 0, 6) + " (" + flag_string + ")" + " ss:esp=" + ss_esp + - " ssize=" + (+cpu.stack_size_32) + + " ssize=" + (+cpu.stack_size_32[0]) + (where ? " in " + where : "")); } @@ -357,8 +359,8 @@ CPU.prototype.debug_init = function() { if(!DEBUG) return; - dbg_log("gdt: (len = " + h(cpu.gdtr_size) + ")"); - dump_table(cpu.translate_address_system_read(cpu.gdtr_offset), cpu.gdtr_size); + dbg_log("gdt: (len = " + h(cpu.gdtr_size[0]) + ")"); + dump_table(cpu.translate_address_system_read(cpu.gdtr_offset[0]), cpu.gdtr_size[0]); dbg_log("\nldt: (len = " + h(cpu.segment_limits[reg_ldtr]) + ")"); dump_table(cpu.translate_address_system_read(cpu.segment_offsets[reg_ldtr]), cpu.segment_limits[reg_ldtr]); @@ -439,9 +441,9 @@ CPU.prototype.debug_init = function() { if(!DEBUG) return; - for(var i = 0; i < cpu.idtr_size; i += 8) + for(var i = 0; i < cpu.idtr_size[0]; i += 8) { - var addr = cpu.translate_address_system_read(cpu.idtr_offset + i), + var addr = cpu.translate_address_system_read(cpu.idtr_offset[0] + i), base = cpu.read16(addr) | cpu.read16(addr + 6) << 16, selector = cpu.read16(addr + 2), type = cpu.read8(addr + 5), @@ -583,7 +585,7 @@ CPU.prototype.debug_init = function() if(start === undefined) { start = 0; - count = cpu.memory_size; + count = cpu.memory_size[0]; } else if(count === undefined) { @@ -630,7 +632,7 @@ CPU.prototype.debug_init = function() var width = 0x80, height = 0x10, - block_size = cpu.memory_size / width / height | 0, + block_size = cpu.memory_size[0] / width / height | 0, row; for(var i = 0; i < height; i++) diff --git a/src/externs.js b/src/externs.js index a24e1730..cd914398 100644 --- a/src/externs.js +++ b/src/externs.js @@ -14,3 +14,4 @@ var exports = {}; var define = {}; var module = {}; +var WebAssembly = { Memory() {}, Table() {}, instantiate() {}, compile() {} }; diff --git a/src/fpu.js b/src/fpu.js index ba33a493..cb592ece 100644 --- a/src/fpu.js +++ b/src/fpu.js @@ -76,7 +76,8 @@ function FPU(cpu) // bitmap of which stack registers are empty - this.stack_empty = 0xff; + this.stack_empty = new Int32Array(cpu.wm.mem.buffer, 816, 1); + this.stack_empty[0] = 0xff; this.stack_ptr = 0; this.control_word = 0x37F; @@ -96,14 +97,20 @@ function FPU(cpu) Math.log(2) / Math.LN10, Math.LN2, 0 ]); + this.wasm_patch(); } +FPU.prototype.wasm_patch = function() +{ + this.set_tag_word = this.cpu.wm.funcs["_safe_tag_word"]; +}; + FPU.prototype.get_state = function() { var state = []; state[0] = this.st; - state[1] = this.stack_empty; + state[1] = this.stack_empty[0]; state[2] = this.stack_ptr; state[3] = this.control_word; state[4] = this.fpu_dp_selector; @@ -119,7 +126,7 @@ FPU.prototype.get_state = function() FPU.prototype.set_state = function(state) { this.st.set(state[0]); - this.stack_empty = state[1]; + this.stack_empty[0] = state[1]; this.stack_ptr = state[2]; this.control_word = state[3]; this.fpu_dp_selector = state[4]; @@ -182,23 +189,23 @@ FPU.prototype.fcomi = function(y) { var x = this.st[this.stack_ptr]; - this.cpu.flags_changed &= ~(1 | flag_parity | flag_zero); - this.cpu.flags &= ~(1 | flag_parity | flag_zero); + this.cpu.flags_changed[0] &= ~(1 | flag_parity | flag_zero); + this.cpu.flags[0] &= ~(1 | flag_parity | flag_zero); if(x > y) { } else if(y > x) { - this.cpu.flags |= 1; + this.cpu.flags[0] |= 1; } else if(x === y) { - this.cpu.flags |= flag_zero; + this.cpu.flags[0] |= flag_zero; } else { - this.cpu.flags |= 1 | flag_parity | flag_zero; + this.cpu.flags[0] |= 1 | flag_parity | flag_zero; } } @@ -233,7 +240,7 @@ FPU.prototype.fxam = function(x) this.status_word &= ~FPU_RESULT_FLAGS; this.status_word |= this.sign(0) << 9; - if(this.stack_empty >> this.stack_ptr & 1) + if(this.stack_empty[0] >> this.stack_ptr & 1) { this.status_word |= FPU_C3 | FPU_C0; } @@ -265,7 +272,7 @@ FPU.prototype.finit = function() this.fpu_dp = 0; this.fpu_opcode = 0; - this.stack_empty = 0xFF; + this.stack_empty[0] = 0xFF; this.stack_ptr = 0; } @@ -289,7 +296,7 @@ FPU.prototype.load_tag_word = function() { value = this.st[i]; - if(this.stack_empty >> i & 1) + if(this.stack_empty[0] >> i & 1) { tag_word |= 3 << (i << 1); } @@ -303,18 +310,18 @@ FPU.prototype.load_tag_word = function() } } - //dbg_log("load tw=" + h(tag_word) + " se=" + h(this.stack_empty) + " sp=" + this.stack_ptr, LOG_FPU); + //dbg_log("load tw=" + h(tag_word) + " se=" + h(this.stack_empty[0]) + " sp=" + this.stack_ptr, LOG_FPU); return tag_word; } FPU.prototype.set_tag_word = function(tag_word) { - this.stack_empty = 0; + this.stack_empty[0] = 0; for(var i = 0; i < 8; i++) { - this.stack_empty |= (tag_word >> i) & (tag_word >> i + 1) & 1 << i; + this.stack_empty[0] |= (tag_word >> i) & (tag_word >> i + 1) & 1 << i; } //dbg_log("set_tag_word tw=" + h(tag_word) + " se=" + h(this.stack_empty), LOG_FPU); @@ -447,10 +454,10 @@ FPU.prototype.push = function(x) { this.stack_ptr = this.stack_ptr - 1 & 7; - if(this.stack_empty >> this.stack_ptr & 1) + if(this.stack_empty[0] >> this.stack_ptr & 1) { this.status_word &= ~FPU_C1; - this.stack_empty &= ~(1 << this.stack_ptr); + this.stack_empty[0] &= ~(1 << this.stack_ptr); this.st[this.stack_ptr] = x; } else @@ -463,7 +470,7 @@ FPU.prototype.push = function(x) FPU.prototype.pop = function() { - this.stack_empty |= 1 << this.stack_ptr; + this.stack_empty[0] |= 1 << this.stack_ptr; this.stack_ptr = this.stack_ptr + 1 & 7; } @@ -473,7 +480,7 @@ FPU.prototype.get_sti = function(i) i = i + this.stack_ptr & 7; - if(this.stack_empty >> i & 1) + if(this.stack_empty[0] >> i & 1) { this.status_word &= ~FPU_C1; this.stack_fault(); @@ -487,7 +494,7 @@ FPU.prototype.get_sti = function(i) FPU.prototype.get_st0 = function() { - if(this.stack_empty >> this.stack_ptr & 1) + if(this.stack_empty[0] >> this.stack_ptr & 1) { this.status_word &= ~FPU_C1; this.stack_fault(); @@ -646,12 +653,12 @@ FPU.prototype.dbg_log_fpu_op = function(op, imm8) if(imm8 >= 0xC0) { dbg_log(h(op, 2) + " " + h(imm8, 2) + "/" + (imm8 >> 3 & 7) + "/" + (imm8 & 7) + - " @" + h(this.cpu.instruction_pointer >>> 0, 8) + " sp=" + this.stack_ptr + " st=" + h(this.stack_empty, 2), LOG_FPU); + " @" + h(this.cpu.instruction_pointer[0] >>> 0, 8) + " sp=" + this.stack_ptr + " st=" + h(this.stack_empty[0], 2), LOG_FPU); } else { dbg_log(h(op, 2) + " /" + (imm8 >> 3 & 7) + - " @" + h(this.cpu.instruction_pointer >>> 0, 8) + " sp=" + this.stack_ptr + " st=" + h(this.stack_empty, 2), LOG_FPU); + " @" + h(this.cpu.instruction_pointer[0] >>> 0, 8) + " sp=" + this.stack_ptr + " st=" + h(this.stack_empty[0], 2), LOG_FPU); } } @@ -987,7 +994,7 @@ FPU.prototype.op_DA_reg = function(imm8) if(this.cpu.test_b()) { this.st[this.stack_ptr] = this.get_sti(low); - this.stack_empty &= ~(1 << this.stack_ptr); + this.stack_empty[0] &= ~(1 << this.stack_ptr); } break; case 1: @@ -995,7 +1002,7 @@ FPU.prototype.op_DA_reg = function(imm8) if(this.cpu.test_z()) { this.st[this.stack_ptr] = this.get_sti(low); - this.stack_empty &= ~(1 << this.stack_ptr); + this.stack_empty[0] &= ~(1 << this.stack_ptr); } break; case 2: @@ -1003,7 +1010,7 @@ FPU.prototype.op_DA_reg = function(imm8) if(this.cpu.test_be()) { this.st[this.stack_ptr] = this.get_sti(low); - this.stack_empty &= ~(1 << this.stack_ptr); + this.stack_empty[0] &= ~(1 << this.stack_ptr); } break; case 3: @@ -1011,7 +1018,7 @@ FPU.prototype.op_DA_reg = function(imm8) if(this.cpu.test_p()) { this.st[this.stack_ptr] = this.get_sti(low); - this.stack_empty &= ~(1 << this.stack_ptr); + this.stack_empty[0] &= ~(1 << this.stack_ptr); } break; case 5: @@ -1096,7 +1103,7 @@ FPU.prototype.op_DB_reg = function(imm8) if(!this.cpu.test_b()) { this.st[this.stack_ptr] = this.get_sti(low); - this.stack_empty &= ~(1 << this.stack_ptr); + this.stack_empty[0] &= ~(1 << this.stack_ptr); } break; case 1: @@ -1104,7 +1111,7 @@ FPU.prototype.op_DB_reg = function(imm8) if(!this.cpu.test_z()) { this.st[this.stack_ptr] = this.get_sti(low); - this.stack_empty &= ~(1 << this.stack_ptr); + this.stack_empty[0] &= ~(1 << this.stack_ptr); } break; case 2: @@ -1112,7 +1119,7 @@ FPU.prototype.op_DB_reg = function(imm8) if(!this.cpu.test_be()) { this.st[this.stack_ptr] = this.get_sti(low); - this.stack_empty &= ~(1 << this.stack_ptr); + this.stack_empty[0] &= ~(1 << this.stack_ptr); } break; case 3: @@ -1120,7 +1127,7 @@ FPU.prototype.op_DB_reg = function(imm8) if(!this.cpu.test_p()) { this.st[this.stack_ptr] = this.get_sti(low); - this.stack_empty &= ~(1 << this.stack_ptr); + this.stack_empty[0] &= ~(1 << this.stack_ptr); } break; case 4: @@ -1329,7 +1336,7 @@ FPU.prototype.op_DD_reg = function(imm8) { case 0: // ffree - this.stack_empty |= 1 << (this.stack_ptr + low & 7); + this.stack_empty[0] |= 1 << (this.stack_ptr + low & 7); break; case 2: // fst diff --git a/src/instructions.js b/src/instructions.js index 59b483bb..53558a3d 100644 --- a/src/instructions.js +++ b/src/instructions.js @@ -230,9 +230,9 @@ t[0x62] = cpu => { t[0x63] = cpu => { cpu.read_modrm_byte(); // arpl //dbg_log("arpl", LOG_CPU); - if(cpu.protected_mode && !cpu.vm86_mode()) + if(cpu.protected_mode[0] && !cpu.vm86_mode()) { - cpu.write_e16(cpu.arpl(cpu.read_write_e16(), cpu.modrm_byte >> 2 & 14)); + cpu.write_e16(cpu.arpl(cpu.read_write_e16(), cpu.modrm_byte[0] >> 2 & 14)); } else { @@ -246,18 +246,18 @@ t[0x65] = cpu => { cpu.segment_prefix_op(reg_gs); }; t[0x66] = cpu => { // Operand-size override prefix - cpu.prefixes |= PREFIX_MASK_OPSIZE; + cpu.prefixes[0] |= PREFIX_MASK_OPSIZE; cpu.run_prefix_instruction(); - cpu.prefixes = 0; + cpu.prefixes[0] = 0; }; t[0x67] = cpu => { // Address-size override prefix - dbg_assert(cpu.is_asize_32() === cpu.is_32); + dbg_assert(cpu.is_asize_32() === Boolean(cpu.is_32[0])); - cpu.prefixes |= PREFIX_MASK_ADDRSIZE; + cpu.prefixes[0] |= PREFIX_MASK_ADDRSIZE; cpu.run_prefix_instruction(); - cpu.prefixes = 0; + cpu.prefixes[0] = 0; }; t16[0x68] = cpu => { cpu.push16(cpu.read_op16()); }; @@ -305,7 +305,7 @@ t[0x7E] = cpu => { cpu.jmpcc8( cpu.test_le()); }; t[0x7F] = cpu => { cpu.jmpcc8(!cpu.test_le()); }; t[0x80] = cpu => { cpu.read_modrm_byte(); - switch(cpu.modrm_byte >> 3 & 7) + switch(cpu.modrm_byte[0] >> 3 & 7) { case 0: cpu.write_e8(cpu.add8(cpu.read_write_e8(), cpu.read_op8())); break; case 1: cpu.write_e8(cpu. or8(cpu.read_write_e8(), cpu.read_op8())); break; @@ -318,7 +318,7 @@ t[0x80] = cpu => { cpu.read_modrm_byte(); } }; t16[0x81] = cpu => { cpu.read_modrm_byte(); - switch(cpu.modrm_byte >> 3 & 7) + switch(cpu.modrm_byte[0] >> 3 & 7) { case 0: cpu.write_e16(cpu.add16(cpu.read_write_e16(), cpu.read_op16())); break; case 1: cpu.write_e16(cpu. or16(cpu.read_write_e16(), cpu.read_op16())); break; @@ -331,7 +331,7 @@ t16[0x81] = cpu => { cpu.read_modrm_byte(); } }; t32[0x81] = cpu => { cpu.read_modrm_byte(); - switch(cpu.modrm_byte >> 3 & 7) + switch(cpu.modrm_byte[0] >> 3 & 7) { case 0: cpu.write_e32(cpu.add32(cpu.read_write_e32(), cpu.read_op32s())); break; case 1: cpu.write_e32(cpu. or32(cpu.read_write_e32(), cpu.read_op32s())); break; @@ -345,7 +345,7 @@ t32[0x81] = cpu => { cpu.read_modrm_byte(); }; t[0x82] = t[0x80]; // alias t16[0x83] = cpu => { cpu.read_modrm_byte(); - switch(cpu.modrm_byte >> 3 & 7) + switch(cpu.modrm_byte[0] >> 3 & 7) { case 0: cpu.write_e16(cpu.add16(cpu.read_write_e16(), cpu.read_op8s())); break; case 1: cpu.write_e16(cpu. or16(cpu.read_write_e16(), cpu.read_op8s())); break; @@ -358,7 +358,7 @@ t16[0x83] = cpu => { cpu.read_modrm_byte(); } }; t32[0x83] = cpu => { cpu.read_modrm_byte(); - switch(cpu.modrm_byte >> 3 & 7) + switch(cpu.modrm_byte[0] >> 3 & 7) { case 0: cpu.write_e32(cpu.add32(cpu.read_write_e32(), cpu.read_op8s())); break; case 1: cpu.write_e32(cpu. or32(cpu.read_write_e32(), cpu.read_op8s())); break; @@ -376,12 +376,12 @@ t16[0x85] = cpu => { cpu.read_modrm_byte(); var data = cpu.read_e16(); cpu.test1 t32[0x85] = cpu => { cpu.read_modrm_byte(); var data = cpu.read_e32s(); cpu.test32(data, cpu.read_g32s()); } -t[0x86] = cpu => { cpu.read_modrm_byte(); var data = cpu.read_write_e8(); cpu.write_e8(cpu.xchg8(data, cpu.modrm_byte)); }; +t[0x86] = cpu => { cpu.read_modrm_byte(); var data = cpu.read_write_e8(); cpu.write_e8(cpu.xchg8(data, cpu.modrm_byte[0])); }; t16[0x87] = cpu => { cpu.read_modrm_byte(); - var data = cpu.read_write_e16(); cpu.write_e16(cpu.xchg16(data, cpu.modrm_byte)); + var data = cpu.read_write_e16(); cpu.write_e16(cpu.xchg16(data, cpu.modrm_byte[0])); }; t32[0x87] = cpu => { cpu.read_modrm_byte(); - var data = cpu.read_write_e32(); cpu.write_e32(cpu.xchg32(data, cpu.modrm_byte)); + var data = cpu.read_write_e32(); cpu.write_e32(cpu.xchg32(data, cpu.modrm_byte[0])); }; t[0x88] = cpu => { cpu.read_modrm_byte(); cpu.set_e8(cpu.read_g8()); }; @@ -402,41 +402,41 @@ t32[0x8B] = cpu => { cpu.read_modrm_byte(); }; t16[0x8C] = cpu => { cpu.read_modrm_byte(); - cpu.set_e16(cpu.sreg[cpu.modrm_byte >> 3 & 7]); + cpu.set_e16(cpu.sreg[cpu.modrm_byte[0] >> 3 & 7]); }; t32[0x8C] = cpu => { cpu.read_modrm_byte(); - cpu.set_e32(cpu.sreg[cpu.modrm_byte >> 3 & 7]); + cpu.set_e32(cpu.sreg[cpu.modrm_byte[0] >> 3 & 7]); }; t16[0x8D] = cpu => { cpu.read_modrm_byte(); // lea - if(cpu.modrm_byte >= 0xC0) + if(cpu.modrm_byte[0] >= 0xC0) { dbg_log("lea #ud", LOG_CPU); cpu.trigger_ud(); } - var mod = cpu.modrm_byte >> 3 & 7; + var mod = cpu.modrm_byte[0] >> 3 & 7; // override prefix, so modrm_resolve does not return the segment part - cpu.prefixes |= SEG_PREFIX_ZERO; - cpu.reg16[mod << 1] = cpu.modrm_resolve(cpu.modrm_byte); - cpu.prefixes = 0; + cpu.prefixes[0] |= SEG_PREFIX_ZERO; + cpu.reg16[mod << 1] = cpu.modrm_resolve(cpu.modrm_byte[0]); + cpu.prefixes[0] = 0; }; t32[0x8D] = cpu => { cpu.read_modrm_byte(); - if(cpu.modrm_byte >= 0xC0) + if(cpu.modrm_byte[0] >= 0xC0) { dbg_log("lea #ud", LOG_CPU); cpu.trigger_ud(); } - var mod = cpu.modrm_byte >> 3 & 7; + var mod = cpu.modrm_byte[0] >> 3 & 7; - cpu.prefixes |= SEG_PREFIX_ZERO; - cpu.reg32s[mod] = cpu.modrm_resolve(cpu.modrm_byte); - cpu.prefixes = 0; + cpu.prefixes[0] |= SEG_PREFIX_ZERO; + cpu.reg32s[mod] = cpu.modrm_resolve(cpu.modrm_byte[0]); + cpu.prefixes[0] = 0; }; t[0x8E] = cpu => { cpu.read_modrm_byte(); - var mod = cpu.modrm_byte >> 3 & 7; + var mod = cpu.modrm_byte[0] >> 3 & 7; var data = cpu.read_e16(); cpu.switch_seg(mod, data); @@ -454,8 +454,8 @@ t16[0x8F] = cpu => { cpu.read_modrm_byte(); cpu.adjust_stack_reg(2); - if(cpu.modrm_byte < 0xC0) { - var addr = cpu.modrm_resolve(cpu.modrm_byte); + if(cpu.modrm_byte[0] < 0xC0) { + var addr = cpu.modrm_resolve(cpu.modrm_byte[0]); cpu.adjust_stack_reg(-2); cpu.safe_write16(addr, sp); cpu.adjust_stack_reg(2); @@ -469,8 +469,8 @@ t32[0x8F] = cpu => { cpu.read_modrm_byte(); // change esp first, then resolve modrm address cpu.adjust_stack_reg(4); - if(cpu.modrm_byte < 0xC0) { - var addr = cpu.modrm_resolve(cpu.modrm_byte); + if(cpu.modrm_byte[0] < 0xC0) { + var addr = cpu.modrm_resolve(cpu.modrm_byte[0]); // Before attempting a write that might cause a page fault, // we must set esp to the old value. Fuck Intel. @@ -516,7 +516,7 @@ t32[0x9A] = cpu => { var new_ip = cpu.read_op32s(); var new_cs = cpu.read_disp16(); - if(!cpu.protected_mode || cpu.vm86_mode()) + if(!cpu.protected_mode[0] || cpu.vm86_mode()) { if(new_ip & 0xFFFF0000) { @@ -551,9 +551,9 @@ t[0x9B] = cpu => { }; t16[0x9C] = cpu => { // pushf - if((cpu.flags & flag_vm) && cpu.getiopl() < 3) + if((cpu.flags[0] & flag_vm) && cpu.getiopl() < 3) { - dbg_assert(cpu.protected_mode); + dbg_assert(cpu.protected_mode[0]); dbg_log("pushf #gp", LOG_CPU); cpu.trigger_gp(0); } @@ -564,10 +564,10 @@ t16[0x9C] = cpu => { }; t32[0x9C] = cpu => { // pushf - if((cpu.flags & flag_vm) && cpu.getiopl() < 3) + if((cpu.flags[0] & flag_vm) && cpu.getiopl() < 3) { // trap to virtual 8086 monitor - dbg_assert(cpu.protected_mode); + dbg_assert(cpu.protected_mode[0]); dbg_log("pushf #gp", LOG_CPU); cpu.trigger_gp(0); } @@ -579,20 +579,20 @@ t32[0x9C] = cpu => { }; t16[0x9D] = cpu => { // popf - if((cpu.flags & flag_vm) && cpu.getiopl() < 3) + if((cpu.flags[0] & flag_vm) && cpu.getiopl() < 3) { dbg_log("popf #gp", LOG_CPU); cpu.trigger_gp(0); } - cpu.update_eflags((cpu.flags & ~0xFFFF) | cpu.pop16()); + cpu.update_eflags((cpu.flags[0] & ~0xFFFF) | cpu.pop16()); - if(cpu.flags & flag_trap) + if(cpu.flags[0] & flag_trap) { // XXX: Problems with fdgame //cpu.clear_prefixes(); //cpu.cycle_internal(); - cpu.flags &= ~flag_trap; + cpu.flags[0] &= ~flag_trap; //cpu.instruction_pointer = cpu.previous_ip; //cpu.raise_exception(1); } @@ -603,7 +603,7 @@ t16[0x9D] = cpu => { }; t32[0x9D] = cpu => { // popf - if((cpu.flags & flag_vm) && cpu.getiopl() < 3) + if((cpu.flags[0] & flag_vm) && cpu.getiopl() < 3) { dbg_log("popf #gp", LOG_CPU); cpu.trigger_gp(0); @@ -614,9 +614,9 @@ t32[0x9D] = cpu => { }; t[0x9E] = cpu => { // sahf - cpu.flags = (cpu.flags & ~0xFF) | cpu.reg8[reg_ah]; - cpu.flags = (cpu.flags & flags_mask) | flags_default; - cpu.flags_changed = 0; + cpu.flags[0] = (cpu.flags[0] & ~0xFF) | cpu.reg8[reg_ah]; + cpu.flags[0] = (cpu.flags[0] & flags_mask) | flags_default; + cpu.flags_changed[0] = 0; }; t[0x9F] = cpu => { // lahf @@ -708,7 +708,7 @@ t[0xC0] = cpu => { cpu.read_modrm_byte(); var op1 = cpu.read_write_e8(); var op2 = cpu.read_op8() & 31; var result = 0; - switch(cpu.modrm_byte >> 3 & 7) + switch(cpu.modrm_byte[0] >> 3 & 7) { case 0: result = cpu.rol8(op1, op2); break; case 1: result = cpu.ror8(op1, op2); break; @@ -725,7 +725,7 @@ t16[0xC1] = cpu => { cpu.read_modrm_byte(); var op1 = cpu.read_write_e16(); var op2 = cpu.read_op8() & 31; var result = 0; - switch(cpu.modrm_byte >> 3 & 7) + switch(cpu.modrm_byte[0] >> 3 & 7) { case 0: result = cpu.rol16(op1, op2); break; case 1: result = cpu.ror16(op1, op2); break; @@ -742,7 +742,7 @@ t32[0xC1] = cpu => { cpu.read_modrm_byte(); var op1 = cpu.read_write_e32(); var op2 = cpu.read_op8() & 31; var result = 0; - switch(cpu.modrm_byte >> 3 & 7) + switch(cpu.modrm_byte[0] >> 3 & 7) { case 0: result = cpu.rol32(op1, op2); break; case 1: result = cpu.ror32(op1, op2); break; @@ -760,7 +760,7 @@ t16[0xC2] = cpu => { // retn var imm16 = cpu.read_op16(); - cpu.instruction_pointer = cpu.get_seg(reg_cs) + cpu.pop16() | 0; + cpu.instruction_pointer[0] = cpu.get_seg(reg_cs) + cpu.pop16() | 0; dbg_assert(cpu.is_asize_32() || cpu.get_real_eip() < 0x10000); cpu.adjust_stack_reg(imm16); cpu.diverged(); @@ -771,20 +771,20 @@ t32[0xC2] = cpu => { var ip = cpu.pop32s(); dbg_assert(cpu.is_asize_32() || ip < 0x10000); - cpu.instruction_pointer = cpu.get_seg(reg_cs) + ip | 0; + cpu.instruction_pointer[0] = cpu.get_seg(reg_cs) + ip | 0; cpu.adjust_stack_reg(imm16); cpu.diverged(); }; t16[0xC3] = cpu => { // retn - cpu.instruction_pointer = cpu.get_seg(reg_cs) + cpu.pop16() | 0; + cpu.instruction_pointer[0] = cpu.get_seg(reg_cs) + cpu.pop16() | 0; cpu.diverged(); }; t32[0xC3] = cpu => { // retn var ip = cpu.pop32s(); dbg_assert(cpu.is_asize_32() || ip < 0x10000); - cpu.instruction_pointer = cpu.get_seg(reg_cs) + ip | 0; + cpu.instruction_pointer[0] = cpu.get_seg(reg_cs) + ip | 0; cpu.diverged(); }; @@ -802,24 +802,24 @@ t32[0xC5] = cpu => { cpu.read_modrm_byte(); }; t[0xC6] = cpu => { cpu.read_modrm_byte(); - if(cpu.modrm_byte < 0xC0) { - cpu.safe_write8(cpu.modrm_resolve(cpu.modrm_byte), cpu.read_op8()); + if(cpu.modrm_byte[0] < 0xC0) { + cpu.safe_write8(cpu.modrm_resolve(cpu.modrm_byte[0]), cpu.read_op8()); } else { - cpu.reg8[cpu.modrm_byte << 2 & 0xC | cpu.modrm_byte >> 2 & 1] = cpu.read_op8(); + cpu.reg8[cpu.modrm_byte[0] << 2 & 0xC | cpu.modrm_byte[0] >> 2 & 1] = cpu.read_op8(); } } t16[0xC7] = cpu => { cpu.read_modrm_byte(); - if(cpu.modrm_byte < 0xC0) { - cpu.safe_write16(cpu.modrm_resolve(cpu.modrm_byte), cpu.read_op16()); + if(cpu.modrm_byte[0] < 0xC0) { + cpu.safe_write16(cpu.modrm_resolve(cpu.modrm_byte[0]), cpu.read_op16()); } else { - cpu.reg16[cpu.modrm_byte << 1 & 14] = cpu.read_op16(); + cpu.reg16[cpu.modrm_byte[0] << 1 & 14] = cpu.read_op16(); } }; t32[0xC7] = cpu => { cpu.read_modrm_byte(); - if(cpu.modrm_byte < 0xC0) { - cpu.safe_write32(cpu.modrm_resolve(cpu.modrm_byte), cpu.read_op32s()); + if(cpu.modrm_byte[0] < 0xC0) { + cpu.safe_write32(cpu.modrm_resolve(cpu.modrm_byte[0]), cpu.read_op32s()); } else { - cpu.reg32s[cpu.modrm_byte & 7] = cpu.read_op32s(); + cpu.reg32s[cpu.modrm_byte[0] & 7] = cpu.read_op32s(); } } @@ -827,13 +827,13 @@ t16[0xC8] = cpu => { cpu.enter16(cpu.read_op16(), cpu.read_disp8()); }; t32[0xC8] = cpu => { cpu.enter32(cpu.read_op16(), cpu.read_disp8()); }; t16[0xC9] = cpu => { // leave - var old_vbp = cpu.stack_size_32 ? cpu.reg32s[reg_ebp] : cpu.reg16[reg_bp]; + var old_vbp = cpu.stack_size_32[0] ? cpu.reg32s[reg_ebp] : cpu.reg16[reg_bp]; var new_bp = cpu.safe_read16(cpu.get_seg(reg_ss) + old_vbp | 0); cpu.set_stack_reg(old_vbp + 2 | 0); cpu.reg16[reg_bp] = new_bp; }; t32[0xC9] = cpu => { - var old_vbp = cpu.stack_size_32 ? cpu.reg32s[reg_ebp] : cpu.reg16[reg_bp]; + var old_vbp = cpu.stack_size_32[0] ? cpu.reg32s[reg_ebp] : cpu.reg16[reg_bp]; var new_ebp = cpu.safe_read32s(cpu.get_seg(reg_ss) + old_vbp | 0); cpu.set_stack_reg(old_vbp + 4 | 0); cpu.reg32s[reg_ebp] = new_ebp; @@ -880,13 +880,13 @@ t[0xCC] = cpu => { // INT3 // TODO: inhibit iopl checks dbg_log("INT3", LOG_CPU); - cpu.call_interrupt_vector(3, true, false); + cpu.call_interrupt_vector(3, true, false, 0); cpu.diverged(); }; t[0xCD] = cpu => { // INT var imm8 = cpu.read_op8(); - cpu.call_interrupt_vector(imm8, true, false); + cpu.call_interrupt_vector(imm8, true, false, 0); cpu.diverged(); }; t[0xCE] = cpu => { @@ -895,7 +895,7 @@ t[0xCE] = cpu => { if(cpu.getof()) { // TODO: inhibit iopl checks - cpu.call_interrupt_vector(4, true, false); + cpu.call_interrupt_vector(4, true, false, 0); } cpu.diverged(); }; @@ -913,7 +913,7 @@ t32[0xCF] = cpu => { t[0xD0] = cpu => { cpu.read_modrm_byte(); var op1 = cpu.read_write_e8(); var result = 0; - switch(cpu.modrm_byte >> 3 & 7) + switch(cpu.modrm_byte[0] >> 3 & 7) { case 0: result = cpu.rol8(op1, 1); break; case 1: result = cpu.ror8(op1, 1); break; @@ -929,7 +929,7 @@ t[0xD0] = cpu => { cpu.read_modrm_byte(); t16[0xD1] = cpu => { cpu.read_modrm_byte(); var op1 = cpu.read_write_e16(); var result = 0; - switch(cpu.modrm_byte >> 3 & 7) + switch(cpu.modrm_byte[0] >> 3 & 7) { case 0: result = cpu.rol16(op1, 1); break; case 1: result = cpu.ror16(op1, 1); break; @@ -945,7 +945,7 @@ t16[0xD1] = cpu => { cpu.read_modrm_byte(); t32[0xD1] = cpu => { cpu.read_modrm_byte(); var op1 = cpu.read_write_e32(); var result = 0; - switch(cpu.modrm_byte >> 3 & 7) + switch(cpu.modrm_byte[0] >> 3 & 7) { case 0: result = cpu.rol32(op1, 1); break; case 1: result = cpu.ror32(op1, 1); break; @@ -963,7 +963,7 @@ t[0xD2] = cpu => { cpu.read_modrm_byte(); var op1 = cpu.read_write_e8(); var op2 = cpu.reg8[reg_cl] & 31; var result = 0; - switch(cpu.modrm_byte >> 3 & 7) + switch(cpu.modrm_byte[0] >> 3 & 7) { case 0: result = cpu.rol8(op1, op2); break; case 1: result = cpu.ror8(op1, op2); break; @@ -980,7 +980,7 @@ t16[0xD3] = cpu => { cpu.read_modrm_byte(); var op1 = cpu.read_write_e16(); var op2 = cpu.reg8[reg_cl] & 31; var result = 0; - switch(cpu.modrm_byte >> 3 & 7) + switch(cpu.modrm_byte[0] >> 3 & 7) { case 0: result = cpu.rol16(op1, op2); break; case 1: result = cpu.ror16(op1, op2); break; @@ -997,7 +997,7 @@ t32[0xD3] = cpu => { cpu.read_modrm_byte(); var op1 = cpu.read_write_e32(); var op2 = cpu.reg8[reg_cl] & 31; var result = 0; - switch(cpu.modrm_byte >> 3 & 7) + switch(cpu.modrm_byte[0] >> 3 & 7) { case 0: result = cpu.rol32(op1, op2); break; case 1: result = cpu.ror32(op1, op2); break; @@ -1036,59 +1036,59 @@ t[0xD7] = cpu => { t[0xD8] = cpu => { cpu.read_modrm_byte(); cpu.task_switch_test(); - if(cpu.modrm_byte < 0xC0) - cpu.fpu.op_D8_mem(cpu.modrm_byte, cpu.modrm_resolve(cpu.modrm_byte)); + if(cpu.modrm_byte[0] < 0xC0) + cpu.fpu.op_D8_mem(cpu.modrm_byte[0], cpu.modrm_resolve(cpu.modrm_byte[0])); else - cpu.fpu.op_D8_reg(cpu.modrm_byte); + cpu.fpu.op_D8_reg(cpu.modrm_byte[0]); }; t[0xD9] = cpu => { cpu.read_modrm_byte(); cpu.task_switch_test(); - if(cpu.modrm_byte < 0xC0) - cpu.fpu.op_D9_mem(cpu.modrm_byte, cpu.modrm_resolve(cpu.modrm_byte)); + if(cpu.modrm_byte[0] < 0xC0) + cpu.fpu.op_D9_mem(cpu.modrm_byte[0], cpu.modrm_resolve(cpu.modrm_byte[0])); else - cpu.fpu.op_D9_reg(cpu.modrm_byte); + cpu.fpu.op_D9_reg(cpu.modrm_byte[0]); }; t[0xDA] = cpu => { cpu.read_modrm_byte(); cpu.task_switch_test(); - if(cpu.modrm_byte < 0xC0) - cpu.fpu.op_DA_mem(cpu.modrm_byte, cpu.modrm_resolve(cpu.modrm_byte)); + if(cpu.modrm_byte[0] < 0xC0) + cpu.fpu.op_DA_mem(cpu.modrm_byte[0], cpu.modrm_resolve(cpu.modrm_byte[0])); else - cpu.fpu.op_DA_reg(cpu.modrm_byte); + cpu.fpu.op_DA_reg(cpu.modrm_byte[0]); }; t[0xDB] = cpu => { cpu.read_modrm_byte(); cpu.task_switch_test(); - if(cpu.modrm_byte < 0xC0) - cpu.fpu.op_DB_mem(cpu.modrm_byte, cpu.modrm_resolve(cpu.modrm_byte)); + if(cpu.modrm_byte[0] < 0xC0) + cpu.fpu.op_DB_mem(cpu.modrm_byte[0], cpu.modrm_resolve(cpu.modrm_byte[0])); else - cpu.fpu.op_DB_reg(cpu.modrm_byte); + cpu.fpu.op_DB_reg(cpu.modrm_byte[0]); }; t[0xDC] = cpu => { cpu.read_modrm_byte(); cpu.task_switch_test(); - if(cpu.modrm_byte < 0xC0) - cpu.fpu.op_DC_mem(cpu.modrm_byte, cpu.modrm_resolve(cpu.modrm_byte)); + if(cpu.modrm_byte[0] < 0xC0) + cpu.fpu.op_DC_mem(cpu.modrm_byte[0], cpu.modrm_resolve(cpu.modrm_byte[0])); else - cpu.fpu.op_DC_reg(cpu.modrm_byte); + cpu.fpu.op_DC_reg(cpu.modrm_byte[0]); }; t[0xDD] = cpu => { cpu.read_modrm_byte(); cpu.task_switch_test(); - if(cpu.modrm_byte < 0xC0) - cpu.fpu.op_DD_mem(cpu.modrm_byte, cpu.modrm_resolve(cpu.modrm_byte)); + if(cpu.modrm_byte[0] < 0xC0) + cpu.fpu.op_DD_mem(cpu.modrm_byte[0], cpu.modrm_resolve(cpu.modrm_byte[0])); else - cpu.fpu.op_DD_reg(cpu.modrm_byte); + cpu.fpu.op_DD_reg(cpu.modrm_byte[0]); }; t[0xDE] = cpu => { cpu.read_modrm_byte(); cpu.task_switch_test(); - if(cpu.modrm_byte < 0xC0) - cpu.fpu.op_DE_mem(cpu.modrm_byte, cpu.modrm_resolve(cpu.modrm_byte)); + if(cpu.modrm_byte[0] < 0xC0) + cpu.fpu.op_DE_mem(cpu.modrm_byte[0], cpu.modrm_resolve(cpu.modrm_byte[0])); else - cpu.fpu.op_DE_reg(cpu.modrm_byte); + cpu.fpu.op_DE_reg(cpu.modrm_byte[0]); }; t[0xDF] = cpu => { cpu.read_modrm_byte(); cpu.task_switch_test(); - if(cpu.modrm_byte < 0xC0) - cpu.fpu.op_DF_mem(cpu.modrm_byte, cpu.modrm_resolve(cpu.modrm_byte)); + if(cpu.modrm_byte[0] < 0xC0) + cpu.fpu.op_DF_mem(cpu.modrm_byte[0], cpu.modrm_resolve(cpu.modrm_byte[0])); else - cpu.fpu.op_DF_reg(cpu.modrm_byte); + cpu.fpu.op_DF_reg(cpu.modrm_byte[0]); }; t[0xE0] = cpu => { cpu.loopne(cpu.read_op8s()); }; @@ -1146,7 +1146,7 @@ t32[0xE8] = cpu => { var imm32s = cpu.read_op32s(); cpu.push32(cpu.get_real_eip()); - cpu.instruction_pointer = cpu.instruction_pointer + imm32s | 0; + cpu.instruction_pointer[0] = cpu.instruction_pointer[0] + imm32s | 0; dbg_assert(cpu.is_asize_32() || cpu.get_real_eip() < 0x10000); cpu.diverged(); }; @@ -1159,7 +1159,7 @@ t16[0xE9] = cpu => { t32[0xE9] = cpu => { // jmp var imm32s = cpu.read_op32s(); - cpu.instruction_pointer = cpu.instruction_pointer + imm32s | 0; + cpu.instruction_pointer[0] = cpu.instruction_pointer[0] + imm32s | 0; dbg_assert(cpu.is_asize_32() || cpu.get_real_eip() < 0x10000); cpu.diverged(); }; @@ -1182,7 +1182,7 @@ t32[0xEA] = cpu => { t[0xEB] = cpu => { // jmp near var imm8 = cpu.read_op8s(); - cpu.instruction_pointer = cpu.instruction_pointer + imm8 | 0; + cpu.instruction_pointer[0] = cpu.instruction_pointer[0] + imm8 | 0; dbg_assert(cpu.is_asize_32() || cpu.get_real_eip() < 0x10000); cpu.diverged(); }; @@ -1241,17 +1241,17 @@ t[0xF1] = cpu => { t[0xF2] = cpu => { // repnz - dbg_assert((cpu.prefixes & PREFIX_MASK_REP) === 0); - cpu.prefixes |= PREFIX_REPNZ; + dbg_assert((cpu.prefixes[0] & PREFIX_MASK_REP) === 0); + cpu.prefixes[0] |= PREFIX_REPNZ; cpu.run_prefix_instruction(); - cpu.prefixes = 0; + cpu.prefixes[0] = 0; }; t[0xF3] = cpu => { // repz - dbg_assert((cpu.prefixes & PREFIX_MASK_REP) === 0); - cpu.prefixes |= PREFIX_REPZ; + dbg_assert((cpu.prefixes[0] & PREFIX_MASK_REP) === 0); + cpu.prefixes[0] |= PREFIX_REPZ; cpu.run_prefix_instruction(); - cpu.prefixes = 0; + cpu.prefixes[0] = 0; }; t[0xF4] = cpu => { @@ -1260,12 +1260,12 @@ t[0xF4] = cpu => { t[0xF5] = cpu => { // cmc - cpu.flags = (cpu.flags | 1) ^ cpu.getcf(); - cpu.flags_changed &= ~1; + cpu.flags[0] = (cpu.flags[0] | 1) ^ cpu.getcf(); + cpu.flags_changed[0] &= ~1; }; t[0xF6] = cpu => { cpu.read_modrm_byte(); - switch(cpu.modrm_byte >> 3 & 7) + switch(cpu.modrm_byte[0] >> 3 & 7) { case 0: var data = cpu.read_e8(); cpu.test8(data, cpu.read_op8()); @@ -1295,7 +1295,7 @@ t[0xF6] = cpu => { cpu.read_modrm_byte(); }; t16[0xF7] = cpu => { cpu.read_modrm_byte(); - switch(cpu.modrm_byte >> 3 & 7) + switch(cpu.modrm_byte[0] >> 3 & 7) { case 0: var data = cpu.read_e16(); cpu.test16(data, cpu.read_op16()); @@ -1324,7 +1324,7 @@ t16[0xF7] = cpu => { cpu.read_modrm_byte(); } }; t32[0xF7] = cpu => { cpu.read_modrm_byte(); - switch(cpu.modrm_byte >> 3 & 7) + switch(cpu.modrm_byte[0] >> 3 & 7) { case 0: var data = cpu.read_e32s(); cpu.test32(data, cpu.read_op32s()); @@ -1355,31 +1355,31 @@ t32[0xF7] = cpu => { cpu.read_modrm_byte(); t[0xF8] = cpu => { // clc - cpu.flags &= ~flag_carry; - cpu.flags_changed &= ~1; + cpu.flags[0] &= ~flag_carry; + cpu.flags_changed[0] &= ~1; }; t[0xF9] = cpu => { // stc - cpu.flags |= flag_carry; - cpu.flags_changed &= ~1; + cpu.flags[0] |= flag_carry; + cpu.flags_changed[0] &= ~1; }; t[0xFA] = cpu => { // cli //dbg_log("interrupts off"); - if(!cpu.protected_mode || ((cpu.flags & flag_vm) ? - cpu.getiopl() === 3 : cpu.getiopl() >= cpu.cpl)) + if(!cpu.protected_mode[0] || ((cpu.flags[0] & flag_vm) ? + cpu.getiopl() === 3 : cpu.getiopl() >= cpu.cpl[0])) { - cpu.flags &= ~flag_interrupt; + cpu.flags[0] &= ~flag_interrupt; } else { - //if(cpu.getiopl() < 3 && ((cpu.flags & flag_vm) ? + //if(cpu.getiopl() < 3 && ((cpu.flags[0] & flag_vm) ? // (cpu.cr[4] & CR4_VME) : - // (cpu.cpl === 3 && (cpu.cr[4] & CR4_PVI)))) + // (cpu.cpl[0] === 3 && (cpu.cr[4] & CR4_PVI)))) //{ - // cpu.flags &= ~flag_vif; + // cpu.flags[0] &= ~flag_vif; //} //else { @@ -1392,10 +1392,10 @@ t[0xFB] = cpu => { // sti //dbg_log("interrupts on"); - if(!cpu.protected_mode || ((cpu.flags & flag_vm) ? - cpu.getiopl() === 3 : cpu.getiopl() >= cpu.cpl)) + if(!cpu.protected_mode[0] || ((cpu.flags[0] & flag_vm) ? + cpu.getiopl() === 3 : cpu.getiopl() >= cpu.cpl[0])) { - cpu.flags |= flag_interrupt; + cpu.flags[0] |= flag_interrupt; cpu.clear_prefixes(); cpu.cycle_internal(); @@ -1404,11 +1404,11 @@ t[0xFB] = cpu => { } else { - //if(cpu.getiopl() < 3 && (cpu.flags & flag_vip) === 0 && ((cpu.flags & flag_vm) ? + //if(cpu.getiopl() < 3 && (cpu.flags[0] & flag_vip) === 0 && ((cpu.flags[0] & flag_vm) ? // (cpu.cr[4] & CR4_VME) : - // (cpu.cpl === 3 && (cpu.cr[4] & CR4_PVI)))) + // (cpu.cpl[0] === 3 && (cpu.cr[4] & CR4_PVI)))) //{ - // cpu.flags |= flag_vif; + // cpu.flags[0] |= flag_vif; //} //else { @@ -1421,15 +1421,15 @@ t[0xFB] = cpu => { t[0xFC] = cpu => { // cld - cpu.flags &= ~flag_direction; + cpu.flags[0] &= ~flag_direction; }; t[0xFD] = cpu => { // std - cpu.flags |= flag_direction; + cpu.flags[0] |= flag_direction; }; t[0xFE] = cpu => { cpu.read_modrm_byte(); - var mod = cpu.modrm_byte & 56; + var mod = cpu.modrm_byte[0] & 56; if(mod === 0) { @@ -1445,7 +1445,7 @@ t[0xFE] = cpu => { cpu.read_modrm_byte(); } }; t16[0xFF] = cpu => { cpu.read_modrm_byte(); - switch(cpu.modrm_byte >> 3 & 7) + switch(cpu.modrm_byte[0] >> 3 & 7) { case 0: var data = cpu.read_write_e16(); cpu.write_e16(cpu.inc16(data)); @@ -1457,20 +1457,20 @@ t16[0xFF] = cpu => { cpu.read_modrm_byte(); // 2, call near var data = cpu.read_e16(); cpu.push16(cpu.get_real_eip()); - cpu.instruction_pointer = cpu.get_seg(reg_cs) + data | 0; + cpu.instruction_pointer[0] = cpu.get_seg(reg_cs) + data | 0; dbg_assert(cpu.is_asize_32() || cpu.get_real_eip() < 0x10000); cpu.diverged(); break; case 3: // 3, callf - if(cpu.modrm_byte >= 0xC0) + if(cpu.modrm_byte[0] >= 0xC0) { dbg_log("callf #ud", LOG_CPU); cpu.trigger_ud(); dbg_assert(false, "unreachable"); } - var virt_addr = cpu.modrm_resolve(cpu.modrm_byte); + var virt_addr = cpu.modrm_resolve(cpu.modrm_byte[0]); var new_ip = cpu.safe_read16(virt_addr); var new_cs = cpu.safe_read16(virt_addr + 2 | 0); @@ -1481,20 +1481,20 @@ t16[0xFF] = cpu => { cpu.read_modrm_byte(); case 4: // 4, jmp near var data = cpu.read_e16(); - cpu.instruction_pointer = cpu.get_seg(reg_cs) + data | 0; + cpu.instruction_pointer[0] = cpu.get_seg(reg_cs) + data | 0; dbg_assert(cpu.is_asize_32() || cpu.get_real_eip() < 0x10000); cpu.diverged(); break; case 5: // 5, jmpf - if(cpu.modrm_byte >= 0xC0) + if(cpu.modrm_byte[0] >= 0xC0) { dbg_log("jmpf #ud", LOG_CPU); cpu.trigger_ud(); dbg_assert(false, "unreachable"); } - var virt_addr = cpu.modrm_resolve(cpu.modrm_byte); + var virt_addr = cpu.modrm_resolve(cpu.modrm_byte[0]); var new_ip = cpu.safe_read16(virt_addr); var new_cs = cpu.safe_read16(virt_addr + 2 | 0); @@ -1512,7 +1512,7 @@ t16[0xFF] = cpu => { cpu.read_modrm_byte(); } }; t32[0xFF] = cpu => { cpu.read_modrm_byte(); - switch(cpu.modrm_byte >> 3 & 7) + switch(cpu.modrm_byte[0] >> 3 & 7) { case 0: var data = cpu.read_write_e32(); cpu.write_e32(cpu.inc32(data)); @@ -1526,23 +1526,23 @@ t32[0xFF] = cpu => { cpu.read_modrm_byte(); cpu.push32(cpu.get_real_eip()); dbg_assert(cpu.is_asize_32() || data < 0x10000); - cpu.instruction_pointer = cpu.get_seg(reg_cs) + data | 0; + cpu.instruction_pointer[0] = cpu.get_seg(reg_cs) + data | 0; cpu.diverged(); break; case 3: // 3, callf - if(cpu.modrm_byte >= 0xC0) + if(cpu.modrm_byte[0] >= 0xC0) { dbg_log("callf #ud", LOG_CPU); cpu.trigger_ud(); dbg_assert(false, "unreachable"); } - var virt_addr = cpu.modrm_resolve(cpu.modrm_byte); + var virt_addr = cpu.modrm_resolve(cpu.modrm_byte[0]); var new_ip = cpu.safe_read32s(virt_addr); var new_cs = cpu.safe_read16(virt_addr + 4 | 0); - if(!cpu.protected_mode || cpu.vm86_mode()) + if(!cpu.protected_mode[0] || cpu.vm86_mode()) { if(new_ip & 0xFFFF0000) { @@ -1558,23 +1558,23 @@ t32[0xFF] = cpu => { cpu.read_modrm_byte(); // 4, jmp near var data = cpu.read_e32s(); dbg_assert(cpu.is_asize_32() || data < 0x10000); - cpu.instruction_pointer = cpu.get_seg(reg_cs) + data | 0; + cpu.instruction_pointer[0] = cpu.get_seg(reg_cs) + data | 0; cpu.diverged(); break; case 5: // 5, jmpf - if(cpu.modrm_byte >= 0xC0) + if(cpu.modrm_byte[0] >= 0xC0) { dbg_log("jmpf #ud", LOG_CPU); cpu.trigger_ud(); dbg_assert(false, "unreachable"); } - var virt_addr = cpu.modrm_resolve(cpu.modrm_byte); + var virt_addr = cpu.modrm_resolve(cpu.modrm_byte[0]); var new_ip = cpu.safe_read32s(virt_addr); var new_cs = cpu.safe_read16(virt_addr + 4 | 0); - if(!cpu.protected_mode || cpu.vm86_mode()) + if(!cpu.protected_mode[0] || cpu.vm86_mode()) { if(new_ip & 0xFFFF0000) { @@ -1625,34 +1625,34 @@ t32 = []; // 0F ops start here t[0x00] = cpu => { cpu.read_modrm_byte(); - if(!cpu.protected_mode || cpu.vm86_mode()) + if(!cpu.protected_mode[0] || cpu.vm86_mode()) { // No GP, UD is correct here dbg_log("0f 00 #ud", LOG_CPU); cpu.trigger_ud(); } - switch(cpu.modrm_byte >> 3 & 7) + switch(cpu.modrm_byte[0] >> 3 & 7) { case 0: // sldt cpu.set_e16(cpu.sreg[reg_ldtr]); - if(cpu.is_osize_32() && cpu.modrm_byte >= 0xC0) + if(cpu.is_osize_32() && cpu.modrm_byte[0] >= 0xC0) { - cpu.reg32s[cpu.modrm_byte & 7] &= 0xFFFF; + cpu.reg32s[cpu.modrm_byte[0] & 7] &= 0xFFFF; } break; case 1: // str cpu.set_e16(cpu.sreg[reg_tr]); - if(cpu.is_osize_32() && cpu.modrm_byte >= 0xC0) + if(cpu.is_osize_32() && cpu.modrm_byte[0] >= 0xC0) { - cpu.reg32s[cpu.modrm_byte & 7] &= 0xFFFF; + cpu.reg32s[cpu.modrm_byte[0] & 7] &= 0xFFFF; } break; case 2: // lldt - if(cpu.cpl) + if(cpu.cpl[0]) { cpu.trigger_gp(0); } @@ -1662,7 +1662,7 @@ t[0x00] = cpu => { cpu.read_modrm_byte(); break; case 3: // ltr - if(cpu.cpl) + if(cpu.cpl[0]) { cpu.trigger_gp(0); } @@ -1678,18 +1678,18 @@ t[0x00] = cpu => { cpu.read_modrm_byte(); break; default: - dbg_log(cpu.modrm_byte >> 3 & 7, LOG_CPU); + dbg_log(cpu.modrm_byte[0] >> 3 & 7, LOG_CPU); cpu.todo(); } }; t[0x01] = cpu => { cpu.read_modrm_byte(); - var mod = cpu.modrm_byte >> 3 & 7; + var mod = cpu.modrm_byte[0] >> 3 & 7; if(mod === 4) { // smsw - if(cpu.modrm_byte >= 0xC0 && cpu.is_osize_32()) + if(cpu.modrm_byte[0] >= 0xC0 && cpu.is_osize_32()) { cpu.set_e32(cpu.cr[0]); } @@ -1702,7 +1702,7 @@ t[0x01] = cpu => { cpu.read_modrm_byte(); else if(mod === 6) { // lmsw - if(cpu.cpl) + if(cpu.cpl[0]) { cpu.trigger_gp(0); } @@ -1711,7 +1711,7 @@ t[0x01] = cpu => { cpu.read_modrm_byte(); cr0 = (cpu.cr[0] & ~0xF) | (cr0 & 0xF); - if(cpu.protected_mode) + if(cpu.protected_mode[0]) { // lmsw cannot be used to switch back cr0 |= CR0_PE; @@ -1721,34 +1721,34 @@ t[0x01] = cpu => { cpu.read_modrm_byte(); return; } - if(cpu.modrm_byte >= 0xC0) + if(cpu.modrm_byte[0] >= 0xC0) { // only memory dbg_log("0f 01 #ud", LOG_CPU); cpu.trigger_ud(); } - var addr = cpu.modrm_resolve(cpu.modrm_byte); + var addr = cpu.modrm_resolve(cpu.modrm_byte[0]); switch(mod) { case 0: // sgdt cpu.writable_or_pagefault(addr, 6); - cpu.safe_write16(addr, cpu.gdtr_size); + cpu.safe_write16(addr, cpu.gdtr_size[0]); var mask = cpu.is_osize_32() ? -1 : 0x00FFFFFF; - cpu.safe_write32(addr + 2, cpu.gdtr_offset & mask); + cpu.safe_write32(addr + 2, cpu.gdtr_offset[0] & mask); break; case 1: // sidt cpu.writable_or_pagefault(addr, 6); - cpu.safe_write16(addr, cpu.idtr_size); + cpu.safe_write16(addr, cpu.idtr_size[0]); var mask = cpu.is_osize_32() ? -1 : 0x00FFFFFF; - cpu.safe_write32(addr + 2, cpu.idtr_offset & mask); + cpu.safe_write32(addr + 2, cpu.idtr_offset[0] & mask); break; case 2: // lgdt - if(cpu.cpl) + if(cpu.cpl[0]) { cpu.trigger_gp(0); } @@ -1756,22 +1756,22 @@ t[0x01] = cpu => { cpu.read_modrm_byte(); var size = cpu.safe_read16(addr); var offset = cpu.safe_read32s(addr + 2); - cpu.gdtr_size = size; - cpu.gdtr_offset = offset; + cpu.gdtr_size[0] = size; + cpu.gdtr_offset[0] = offset; if(!cpu.is_osize_32()) { - cpu.gdtr_offset &= 0xFFFFFF; + cpu.gdtr_offset[0] &= 0xFFFFFF; } - //dbg_log("gdt at " + h(cpu.gdtr_offset) + ", " + cpu.gdtr_size + " bytes", LOG_CPU); + //dbg_log("gdt at " + h(cpu.gdtr_offset[0]) + ", " + cpu.gdtr_size[0] + " bytes", LOG_CPU); //cpu.debug.dump_state(); //cpu.debug.dump_regs_short(); //cpu.debug.dump_gdt_ldt(); break; case 3: // lidt - if(cpu.cpl) + if(cpu.cpl[0]) { cpu.trigger_gp(0); } @@ -1779,20 +1779,20 @@ t[0x01] = cpu => { cpu.read_modrm_byte(); var size = cpu.safe_read16(addr); var offset = cpu.safe_read32s(addr + 2); - cpu.idtr_size = size; - cpu.idtr_offset = offset; + cpu.idtr_size[0] = size; + cpu.idtr_offset[0] = offset; if(!cpu.is_osize_32()) { - cpu.idtr_offset &= 0xFFFFFF; + cpu.idtr_offset[0] &= 0xFFFFFF; } //dbg_log("[" + h(cpu.instruction_pointer) + "] idt at " + - // h(idtr_offset) + ", " + cpu.idtr_size + " bytes " + h(addr), LOG_CPU); + // h(idtr_offset) + ", " + cpu.idtr_size[0] + " bytes " + h(addr), LOG_CPU); break; case 7: // flush translation lookaside buffer - if(cpu.cpl) + if(cpu.cpl[0]) { cpu.trigger_gp(0); } @@ -1807,7 +1807,7 @@ t[0x01] = cpu => { cpu.read_modrm_byte(); t16[0x02] = cpu => { cpu.read_modrm_byte(); // lar - if(!cpu.protected_mode || cpu.vm86_mode()) + if(!cpu.protected_mode[0] || cpu.vm86_mode()) { dbg_log("lar #ud", LOG_CPU); cpu.trigger_ud(); @@ -1816,7 +1816,7 @@ t16[0x02] = cpu => { cpu.read_modrm_byte(); cpu.write_g16(cpu.lar(data, cpu.read_g16())); }; t32[0x02] = cpu => { cpu.read_modrm_byte(); - if(!cpu.protected_mode || cpu.vm86_mode()) + if(!cpu.protected_mode[0] || cpu.vm86_mode()) { dbg_log("lar #ud", LOG_CPU); cpu.trigger_ud(); @@ -1827,7 +1827,7 @@ t32[0x02] = cpu => { cpu.read_modrm_byte(); t16[0x03] = cpu => { cpu.read_modrm_byte(); // lsl - if(!cpu.protected_mode || cpu.vm86_mode()) + if(!cpu.protected_mode[0] || cpu.vm86_mode()) { dbg_log("lsl #ud", LOG_CPU); cpu.trigger_ud(); @@ -1836,7 +1836,7 @@ t16[0x03] = cpu => { cpu.read_modrm_byte(); cpu.write_g16(cpu.lsl(data, cpu.read_g16())); }; t32[0x03] = cpu => { cpu.read_modrm_byte(); - if(!cpu.protected_mode || cpu.vm86_mode()) + if(!cpu.protected_mode[0] || cpu.vm86_mode()) { dbg_log("lsl #ud", LOG_CPU); cpu.trigger_ud(); @@ -1850,7 +1850,7 @@ t[0x05] = cpu => { cpu.undefined_instruction(); }; t[0x06] = cpu => { // clts - if(cpu.cpl) + if(cpu.cpl[0]) { dbg_log("clts #gp", LOG_CPU); cpu.trigger_gp(0); @@ -1869,7 +1869,7 @@ t[0x08] = cpu => { }; t[0x09] = cpu => { - if(cpu.cpl) + if(cpu.cpl[0]) { dbg_log("wbinvd #gp", LOG_CPU); cpu.trigger_gp(0); @@ -1913,7 +1913,21 @@ t[0x13] = cpu => { var addr = cpu.modrm_resolve(cpu.modrm_byte); cpu.safe_write64(addr, data[0], data[1]); }; -t[0x14] = cpu => { cpu.unimplemented_sse(); }; +t[0x14] = cpu => { + // unpcklpd xmm, xmm/m128 + dbg_assert((cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) === PREFIX_66); + cpu.task_switch_test_mmx(); + cpu.read_modrm_byte(); + let source = cpu.read_xmm_mem64s(); + let destination = cpu.read_xmm64s(); + + cpu.write_xmm128s( + destination[0], + destination[1], + source[0], + source[1] + ); +}; t[0x15] = cpu => { cpu.unimplemented_sse(); }; t[0x16] = cpu => { cpu.unimplemented_sse(); }; t[0x17] = cpu => { cpu.unimplemented_sse(); }; @@ -1921,8 +1935,8 @@ t[0x17] = cpu => { cpu.unimplemented_sse(); }; t[0x18] = cpu => { cpu.read_modrm_byte(); // prefetch // nop for us - if(cpu.modrm_byte < 0xC0) - cpu.modrm_resolve(cpu.modrm_byte); + if(cpu.modrm_byte[0] < 0xC0) + cpu.modrm_resolve(cpu.modrm_byte[0]); }; t[0x19] = cpu => { cpu.unimplemented_sse(); }; @@ -1933,22 +1947,22 @@ t[0x1D] = cpu => { cpu.unimplemented_sse(); }; t[0x1E] = cpu => { cpu.unimplemented_sse(); }; t[0x1F] = cpu => { cpu.read_modrm_byte() // multi-byte nop - if(cpu.modrm_byte < 0xC0) - cpu.modrm_resolve(cpu.modrm_byte); + if(cpu.modrm_byte[0] < 0xC0) + cpu.modrm_resolve(cpu.modrm_byte[0]); }; t[0x20] = cpu => { cpu.read_modrm_byte(); - if(cpu.cpl) + if(cpu.cpl[0]) { cpu.trigger_gp(0); } - //dbg_log("cr" + (cpu.modrm_byte >> 3 & 7) + " read", LOG_CPU); + //dbg_log("cr" + (cpu.modrm_byte[0] >> 3 & 7) + " read", LOG_CPU); // mov addr, cr // mod = which control register - switch(cpu.modrm_byte >> 3 & 7) + switch(cpu.modrm_byte[0] >> 3 & 7) { case 0: cpu.write_reg_e32(cpu.cr[0]); @@ -1972,12 +1986,12 @@ t[0x20] = cpu => { cpu.read_modrm_byte(); }; t[0x21] = cpu => { cpu.read_modrm_byte(); - if(cpu.cpl) + if(cpu.cpl[0]) { cpu.trigger_gp(0); } - var dreg = cpu.modrm_byte >> 3 & 7; + var dreg = cpu.modrm_byte[0] >> 3 & 7; if((cpu.cr[4] & CR4_DE) && (dreg === 4 || dreg === 5)) { dbg_log("#ud mov dreg 4/5 with cr4.DE set", LOG_CPU); @@ -1985,24 +1999,24 @@ t[0x21] = cpu => { cpu.read_modrm_byte(); } // high two bits of modrm are ignored - cpu.reg32s[cpu.modrm_byte & 7] = cpu.dreg[dreg]; + cpu.reg32s[cpu.modrm_byte[0] & 7] = cpu.dreg[dreg]; //dbg_log("read dr" + dreg + ": " + h(cpu.dreg[dreg] >>> 0), LOG_CPU); }; t[0x22] = cpu => { cpu.read_modrm_byte(); - if(cpu.cpl) + if(cpu.cpl[0]) { cpu.trigger_gp(0); } var data = cpu.read_reg_e32s(); - //dbg_log("cr" + (cpu.modrm_byte >> 3 & 7) + " written: " + h(data >>> 0, 8), LOG_CPU); + //dbg_log("cr" + (cpu.modrm_byte[0] >> 3 & 7) + " written: " + h(data >>> 0, 8), LOG_CPU); // mov cr, addr // mod = which control register - switch(cpu.modrm_byte >> 3 & 7) + switch(cpu.modrm_byte[0] >> 3 & 7) { case 0: cpu.set_cr0(data); @@ -2036,12 +2050,12 @@ t[0x22] = cpu => { cpu.read_modrm_byte(); } }; t[0x23] = cpu => { cpu.read_modrm_byte(); - if(cpu.cpl) + if(cpu.cpl[0]) { cpu.trigger_gp(0); } - var dreg = cpu.modrm_byte >> 3 & 7; + var dreg = cpu.modrm_byte[0] >> 3 & 7; if((cpu.cr[4] & CR4_DE) && (dreg === 4 || dreg === 5)) { dbg_log("#ud mov dreg 4/5 with cr4.DE set", LOG_CPU); @@ -2060,10 +2074,20 @@ t[0x26] = cpu => { cpu.undefined_instruction(); }; t[0x27] = cpu => { cpu.undefined_instruction(); }; t[0x28] = cpu => { - // movaps xmm, xmm/m128 - dbg_assert((cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) === 0); cpu.task_switch_test_mmx(); cpu.read_modrm_byte(); + + if((cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) === PREFIX_66) + { + // movapd xmm, xmm/m128 + // (note: same as movaps, see google.com/?q=MOVAPD+vs+MOVAPS) + } + else + { + dbg_assert((cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) === 0); + // movaps xmm, xmm/m128 + } + let data = cpu.read_xmm_mem128s(); cpu.write_xmm128s(data[0], data[1], data[2], data[3]); }; @@ -2073,25 +2097,60 @@ t[0x29] = cpu => { if((cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) === PREFIX_66) { // movapd xmm/m128, xmm - // (note: same as below, see google.com/?q=MOVAPD+vs+MOVAPS) - let data = cpu.read_xmm128s(); - dbg_assert(cpu.modrm_byte < 0xC0); - let addr = cpu.modrm_resolve(cpu.modrm_byte); - cpu.safe_write128(addr, data[0], data[1], data[2], data[3]); + // (note: same as movaps, see google.com/?q=MOVAPD+vs+MOVAPS) } else { // movaps xmm/m128, xmm dbg_assert((cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) === 0); - let data = cpu.read_xmm128s(); - dbg_assert(cpu.modrm_byte < 0xC0); - let addr = cpu.modrm_resolve(cpu.modrm_byte); - cpu.safe_write128(addr, data[0], data[1], data[2], data[3]); } + + let data = cpu.read_xmm128s(); + dbg_assert(cpu.modrm_byte < 0xC0); + let addr = cpu.modrm_resolve(cpu.modrm_byte); + cpu.safe_write128(addr, data[0], data[1], data[2], data[3]); }; t[0x2A] = cpu => { cpu.unimplemented_sse(); }; -t[0x2B] = cpu => { cpu.unimplemented_sse(); }; -t[0x2C] = cpu => { cpu.unimplemented_sse(); }; +t[0x2B] = cpu => { + cpu.task_switch_test_mmx(); + cpu.read_modrm_byte(); + dbg_assert((cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) == 0 || + (cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) === PREFIX_66); + + if(cpu.modrm_byte >= 0xC0) + { + cpu.trigger_ud(); + } + + // movntps m128, xmm + // movntpd m128, xmm + + let data = cpu.read_xmm128s(); + let addr = cpu.modrm_resolve(cpu.modrm_byte); + cpu.safe_write128(addr, data[0], data[1], data[2], data[3]); +}; +t[0x2C] = cpu => { + cpu.task_switch_test_mmx(); + cpu.read_modrm_byte(); + if((cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) === PREFIX_F2) + { + // cvttsd2si r32, xmm/m64 + let source = cpu.read_xmm_mem64s(); + let source_f64 = new Float64Array(source.buffer); + let f = source_f64[0]; + + if(!(f <= 0x7FFFFFFF && f >= -0x80000000)) + { + f = 0x80000000 | 0; + } + + cpu.write_g32(f); + } + else + { + dbg_assert(false); + } +}; t[0x2D] = cpu => { cpu.unimplemented_sse(); }; t[0x2E] = cpu => { cpu.unimplemented_sse(); }; t[0x2F] = cpu => { cpu.unimplemented_sse(); }; @@ -2100,7 +2159,7 @@ t[0x2F] = cpu => { cpu.unimplemented_sse(); }; t[0x30] = cpu => { // wrmsr - write maschine specific register - if(cpu.cpl) + if(cpu.cpl[0]) { // cpl > 0 or vm86 mode (vm86 mode is always runs with cpl=3) cpu.trigger_gp(0); @@ -2119,15 +2178,15 @@ t[0x30] = cpu => { switch(index) { case IA32_SYSENTER_CS: - cpu.sysenter_cs = low & 0xFFFF; + cpu.sysenter_cs[0] = low & 0xFFFF; break; case IA32_SYSENTER_EIP: - cpu.sysenter_eip = low; + cpu.sysenter_eip[0] = low; break; case IA32_SYSENTER_ESP: - cpu.sysenter_esp = low; + cpu.sysenter_esp[0] = low; break; case IA32_APIC_BASE_MSR: @@ -2140,7 +2199,7 @@ t[0x30] = cpu => { case IA32_TIME_STAMP_COUNTER: var new_tick = (low >>> 0) + 0x100000000 * (high >>> 0); - cpu.tsc_offset = v86.microtick() - new_tick / TSC_RATE; + cpu.tsc_offset[0] = v86.microtick() - new_tick / TSC_RATE; break; case IA32_BIOS_SIGN_ID: @@ -2167,9 +2226,9 @@ t[0x30] = cpu => { t[0x31] = cpu => { // rdtsc - read timestamp counter - if(!cpu.cpl || !(cpu.cr[4] & CR4_TSD)) + if(!cpu.cpl[0] || !(cpu.cr[4] & CR4_TSD)) { - var n = v86.microtick() - cpu.tsc_offset; + var n = v86.microtick() - cpu.tsc_offset[0]; dbg_assert(isFinite(n), "non-finite tsc: " + n); cpu.reg32s[reg_eax] = n * TSC_RATE; @@ -2185,7 +2244,7 @@ t[0x31] = cpu => { t[0x32] = cpu => { // rdmsr - read maschine specific register - if(cpu.cpl) + if(cpu.cpl[0]) { cpu.trigger_gp(0); } @@ -2200,19 +2259,19 @@ t[0x32] = cpu => { switch(index) { case IA32_SYSENTER_CS: - low = cpu.sysenter_cs; + low = cpu.sysenter_cs[0]; break; case IA32_SYSENTER_EIP: - low = cpu.sysenter_eip; + low = cpu.sysenter_eip[0]; break; case IA32_SYSENTER_ESP: - low = cpu.sysenter_esp; + low = cpu.sysenter_esp[0]; break; case IA32_TIME_STAMP_COUNTER: - var n = v86.microtick() - cpu.tsc_offset; + var n = v86.microtick() - cpu.tsc_offset[0]; low = n * TSC_RATE; high = n * (TSC_RATE / 0x100000000); break; @@ -2271,20 +2330,23 @@ t[0x33] = cpu => { t[0x34] = cpu => { // sysenter - var seg = cpu.sysenter_cs & 0xFFFC; + var seg = cpu.sysenter_cs[0] & 0xFFFC; - if(!cpu.protected_mode || seg === 0) + if(!cpu.protected_mode[0] || seg === 0) { cpu.trigger_gp(0); } - //dbg_log("sysenter cs:eip=" + h(seg , 4) + ":" + h(cpu.sysenter_eip >>> 0, 8) + - // " ss:esp=" + h(seg + 8, 4) + ":" + h(cpu.sysenter_esp >>> 0, 8), LOG_CPU); + if(CPU_LOG_VERBOSE) + { + dbg_log("sysenter cs:eip=" + h(seg , 4) + ":" + h(cpu.sysenter_eip[0] >>> 0, 8) + + " ss:esp=" + h(seg + 8, 4) + ":" + h(cpu.sysenter_esp[0] >>> 0, 8), LOG_CPU); + } - cpu.flags &= ~flag_vm & ~flag_interrupt; + cpu.flags[0] &= ~flag_vm & ~flag_interrupt; - cpu.instruction_pointer = cpu.sysenter_eip; - cpu.reg32s[reg_esp] = cpu.sysenter_esp; + cpu.instruction_pointer[0] = cpu.sysenter_eip[0]; + cpu.reg32s[reg_esp] = cpu.sysenter_esp[0]; cpu.sreg[reg_cs] = seg; cpu.segment_is_null[reg_cs] = 0; @@ -2293,7 +2355,7 @@ t[0x34] = cpu => { cpu.update_cs_size(true); - cpu.cpl = 0; + cpu.cpl[0] = 0; cpu.cpl_changed(); cpu.sreg[reg_ss] = seg + 8; @@ -2301,23 +2363,26 @@ t[0x34] = cpu => { cpu.segment_limits[reg_ss] = -1; cpu.segment_offsets[reg_ss] = 0; - cpu.stack_size_32 = true; + cpu.stack_size_32[0] = true; cpu.diverged(); }; t[0x35] = cpu => { // sysexit - var seg = cpu.sysenter_cs & 0xFFFC; + var seg = cpu.sysenter_cs[0] & 0xFFFC; - if(!cpu.protected_mode || cpu.cpl || seg === 0) + if(!cpu.protected_mode[0] || cpu.cpl[0] || seg === 0) { cpu.trigger_gp(0); } - //dbg_log("sysexit cs:eip=" + h(seg + 16, 4) + ":" + h(cpu.reg32s[reg_edx] >>> 0, 8) + - // " ss:esp=" + h(seg + 24, 4) + ":" + h(cpu.reg32s[reg_ecx] >>> 0, 8), LOG_CPU); + if(CPU_LOG_VERBOSE) + { + dbg_log("sysexit cs:eip=" + h(seg + 16, 4) + ":" + h(cpu.reg32s[reg_edx] >>> 0, 8) + + " ss:esp=" + h(seg + 24, 4) + ":" + h(cpu.reg32s[reg_ecx] >>> 0, 8), LOG_CPU); + } - cpu.instruction_pointer = cpu.reg32s[reg_edx]; + cpu.instruction_pointer[0] = cpu.reg32s[reg_edx]; cpu.reg32s[reg_esp] = cpu.reg32s[reg_ecx]; cpu.sreg[reg_cs] = seg + 16 | 3; @@ -2328,7 +2393,7 @@ t[0x35] = cpu => { cpu.update_cs_size(true); - cpu.cpl = 3; + cpu.cpl[0] = 3; cpu.cpl_changed(); cpu.sreg[reg_ss] = seg + 24 | 3; @@ -2336,7 +2401,7 @@ t[0x35] = cpu => { cpu.segment_limits[reg_ss] = -1; cpu.segment_offsets[reg_ss] = 0; - cpu.stack_size_32 = true; + cpu.stack_size_32[0] = true; cpu.diverged(); }; @@ -2396,7 +2461,23 @@ t[0x50] = cpu => { cpu.unimplemented_sse(); }; t[0x51] = cpu => { cpu.unimplemented_sse(); }; t[0x52] = cpu => { cpu.unimplemented_sse(); }; t[0x53] = cpu => { cpu.unimplemented_sse(); }; -t[0x54] = cpu => { cpu.unimplemented_sse(); }; +t[0x54] = cpu => { + // andps xmm, xmm/mem128 + // andpd xmm, xmm/mem128 + // Note: Same code as pand + cpu.task_switch_test_mmx(); + cpu.read_modrm_byte(); + + let source = cpu.read_xmm_mem128s(); + let destination = cpu.read_xmm128s(); + + cpu.write_xmm128s( + source[0] & destination[0], + source[1] & destination[1], + source[2] & destination[2], + source[3] & destination[3] + ); +}; t[0x55] = cpu => { cpu.unimplemented_sse(); }; t[0x56] = cpu => { cpu.unimplemented_sse(); }; t[0x57] = cpu => { @@ -3053,7 +3134,6 @@ t[0x72] = cpu => { t[0x73] = cpu => { cpu.read_modrm_byte(); - dbg_assert((cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) == 0); cpu.task_switch_test_mmx(); if(cpu.modrm_byte < 0xC0) @@ -3066,32 +3146,65 @@ t[0x73] = cpu => { switch(cpu.modrm_byte >> 3 & 7) { case 2: - // psrlq mm, imm8 - var source = cpu.read_op8(); - var destination = cpu.modrm_byte & 7; + if((cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) == PREFIX_66) + { + // psrlq xmm, imm8 + var shift = cpu.read_op8(); - var destination_low = cpu.reg_mmxs[2 * destination]; - var destination_high = cpu.reg_mmxs[2 * destination + 1]; + if(shift === 0) + { + return; + } - var shift = source; - var low = 0; - var high = 0; + let destination = cpu.read_xmm128s(); + let result = cpu.create_atom128s(0, 0, 0, 0); - if (shift <= 31) { - low = destination_low >>> shift | (destination_high << (32 - shift)); - high = destination_high >>> shift; + if (shift <= 31) + { + result[0] = destination[0] >>> shift | destination[1] << (32 - shift); + result[1] = destination[1] >>> shift; + + result[2] = destination[2] >>> shift | destination[3] << (32 - shift); + result[3] = destination[3] >>> shift; + } + else if (shift <= 63) + { + result[0] = destination[1] >>> shift; + result[2] = destination[3] >>> shift; + } + + cpu.write_xmm128s(result[0], result[1], result[2], result[3]); } - else if (shift <= 63) { - low = destination_high >>> (shift & 0x1F); - high = 0; + else + { + // psrlq mm, imm8 + dbg_assert((cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) == 0); + var source = cpu.read_op8(); + var destination = cpu.modrm_byte & 7; + + var destination_low = cpu.reg_mmxs[2 * destination]; + var destination_high = cpu.reg_mmxs[2 * destination + 1]; + + var shift = source; + var low = 0; + var high = 0; + + if (shift <= 31) { + low = destination_low >>> shift | (destination_high << (32 - shift)); + high = destination_high >>> shift; + } + else if (shift <= 63) { + low = destination_high >>> (shift & 0x1F); + high = 0; + } + + cpu.reg_mmxs[2 * destination] = low; + cpu.reg_mmxs[2 * destination + 1] = high; } - - cpu.reg_mmxs[2 * destination] = low; - cpu.reg_mmxs[2 * destination + 1] = high; - break; case 6: // psllq mm, imm8 + dbg_assert((cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) == 0); var source = cpu.read_op8(); var destination = cpu.modrm_byte & 7; @@ -3115,6 +3228,7 @@ t[0x73] = cpu => { cpu.reg_mmxs[2 * destination + 1] = high; break; + default: cpu.unimplemented_sse(); break; @@ -3171,24 +3285,47 @@ t[0x74] = cpu => { }; t[0x75] = cpu => { - // pcmpeqw mm, mm/m64 - dbg_assert((cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) == 0); cpu.task_switch_test_mmx(); cpu.read_modrm_byte(); - let source = cpu.read_mmx_mem64s(); - let destination_low = cpu.reg_mmxs[2 * (cpu.modrm_byte >> 3 & 7)]; - let destination_high = cpu.reg_mmxs[2 * (cpu.modrm_byte >> 3 & 7) + 1]; + if((cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) == PREFIX_66) + { + // pcmpeqw xmm, xmm/m128 + let source64s = cpu.read_xmm_mem128s(); + let source16 = new Uint16Array(source64s.buffer); - let word0 = (destination_low & 0xFFFF) === (source[0] & 0xFFFF) ? 0xFFFF : 0; - let word1 = (destination_low & 0xFFFF0000) === (source[0] & 0xFFFF0000) ? 0xFFFF : 0; - let word2 = (destination_high & 0xFFFF) === (source[1] & 0xFFFF) ? 0xFFFF : 0; - let word3 = (destination_high & 0xFFFF0000) === (source[1] & 0xFFFF0000) ? 0xFFFF : 0; + let destination128 = cpu.read_xmm128s(); + let destination16 = new Uint16Array(destination128.buffer); - let low = word0 | word1 << 16; - let high = word2 | word3 << 16; + let result = cpu.create_atom128s(0, 0, 0, 0); + let result16 = new Uint16Array(result.buffer); - cpu.write_mmx64s(low, high); + for(let i = 0; i < 8; i++) + { + result16[i] = source16[i] === destination16[i] ? 0xFFFF : 0; + } + + cpu.write_xmm128s(result[0], result[1], result[2], result[3]) + } + else + { + // pcmpeqw mm, mm/m64 + dbg_assert((cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) == 0); + + let source = cpu.read_mmx_mem64s(); + let destination_low = cpu.reg_mmxs[2 * (cpu.modrm_byte >> 3 & 7)]; + let destination_high = cpu.reg_mmxs[2 * (cpu.modrm_byte >> 3 & 7) + 1]; + + let word0 = (destination_low & 0xFFFF) === (source[0] & 0xFFFF) ? 0xFFFF : 0; + let word1 = (destination_low & 0xFFFF0000) === (source[0] & 0xFFFF0000) ? 0xFFFF : 0; + let word2 = (destination_high & 0xFFFF) === (source[1] & 0xFFFF) ? 0xFFFF : 0; + let word3 = (destination_high & 0xFFFF0000) === (source[1] & 0xFFFF0000) ? 0xFFFF : 0; + + let low = word0 | word1 << 16; + let high = word2 | word3 << 16; + + cpu.write_mmx64s(low, high); + } }; t[0x76] = cpu => { @@ -3228,7 +3365,7 @@ t[0x77] = cpu => { // emms dbg_assert((cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) == 0); cpu.task_switch_test_mmx(); - cpu.fpu.stack_empty = 0xFF; + cpu.fpu.stack_empty[0] = 0xFF; }; t[0x78] = cpu => { cpu.unimplemented_sse(); }; @@ -3835,7 +3972,21 @@ t[0xC3] = cpu => { cpu.set_e32(cpu.read_g32s()); }; t[0xC4] = cpu => { cpu.unimplemented_sse(); }; -t[0xC5] = cpu => { cpu.unimplemented_sse(); }; +t[0xC5] = cpu => { + dbg_assert((cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) === PREFIX_66); + // pextrw r32/m16, xmm, imm8 + cpu.task_switch_test_mmx(); + cpu.read_modrm_byte(); + + if(cpu.modrm_byte < 0xC0) cpu.trigger_ud(); + + let data = cpu.read_xmm_mem128s(); + let data16 = new Uint16Array(data.buffer); + let index = cpu.read_imm8() & 7; + let result = data16[index]; + + cpu.write_g32(result); +}; t[0xC6] = cpu => { cpu.unimplemented_sse(); }; t[0xC7] = cpu => { @@ -3859,14 +4010,14 @@ t[0xC7] = cpu => { if(cpu.reg32s[reg_eax] === m64_low && cpu.reg32s[reg_edx] === m64_high) { - cpu.flags |= flag_zero; + cpu.flags[0] |= flag_zero; cpu.safe_write32(addr, cpu.reg32s[reg_ebx]); cpu.safe_write32(addr + 4 | 0, cpu.reg32s[reg_ecx]); } else { - cpu.flags &= ~flag_zero; + cpu.flags[0] &= ~flag_zero; cpu.reg32s[reg_eax] = m64_low; cpu.reg32s[reg_edx] = m64_high; @@ -3875,7 +4026,7 @@ t[0xC7] = cpu => { cpu.safe_write32(addr + 4 | 0, m64_high); } - cpu.flags_changed &= ~flag_zero; + cpu.flags_changed[0] &= ~flag_zero; break; case 6: @@ -3900,9 +4051,9 @@ t[0xC7] = cpu => { cpu.set_e16(rand); } - cpu.flags &= ~flags_all; - cpu.flags |= has_rand; - cpu.flags_changed = 0; + cpu.flags[0] &= ~flags_all; + cpu.flags[0] |= has_rand; + cpu.flags_changed[0] = 0; break; default: @@ -3972,35 +4123,69 @@ t[0xD2] = cpu => { }; t[0xD3] = cpu => { - // psrlq mm, mm/m64 - dbg_assert((cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) == 0); cpu.task_switch_test_mmx(); cpu.read_modrm_byte(); - let source = cpu.read_mmx_mem64s(); - let destination_low = cpu.reg_mmxs[2 * (cpu.modrm_byte >> 3 & 7)]; - let destination_high = cpu.reg_mmxs[2 * (cpu.modrm_byte >> 3 & 7) + 1]; - - let shift = source[0] >>> 0; - - if(shift === 0) + if((cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) === PREFIX_66) { - return; - } + // psrlq xmm, mm/m64 + let source = cpu.read_xmm_mem64s(); + var shift = source[0] >>> 0; - let low = 0; - let high = 0; + if(shift === 0) + { + return; + } - if (shift <= 31) { - low = destination_low >>> shift | (destination_high << (32 - shift)); - high = destination_high >>> shift; - } - else if (shift <= 63) { - low = destination_high >>> (shift & 0x1F); - high = 0; - } + let destination = cpu.read_xmm128s(); + let result = cpu.create_atom128s(0, 0, 0, 0); - cpu.write_mmx64s(low, high); + if (shift <= 31) + { + result[0] = destination[0] >>> shift | destination[1] << (32 - shift); + result[1] = destination[1] >>> shift; + + result[2] = destination[2] >>> shift | destination[3] << (32 - shift); + result[3] = destination[3] >>> shift; + } + else if (shift <= 63) + { + result[0] = destination[1] >>> shift; + result[2] = destination[3] >>> shift; + } + + cpu.write_xmm128s(result[0], result[1], result[2], result[3]); + } + else + { + // psrlq mm, mm/m64 + dbg_assert((cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) == 0); + + let source = cpu.read_mmx_mem64s(); + let destination_low = cpu.reg_mmxs[2 * (cpu.modrm_byte >> 3 & 7)]; + let destination_high = cpu.reg_mmxs[2 * (cpu.modrm_byte >> 3 & 7) + 1]; + + let shift = source[0] >>> 0; + + if(shift === 0) + { + return; + } + + let low = 0; + let high = 0; + + if (shift <= 31) { + low = destination_low >>> shift | (destination_high << (32 - shift)); + high = destination_high >>> shift; + } + else if (shift <= 63) { + low = destination_high >>> (shift & 0x1F); + high = 0; + } + + cpu.write_mmx64s(low, high); + } }; t[0xD4] = cpu => { cpu.unimplemented_sse(); }; @@ -4740,19 +4925,36 @@ t[0xF9] = cpu => { }; t[0xFA] = cpu => { - // psubd mm, mm/m64 - dbg_assert((cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) == 0); cpu.task_switch_test_mmx(); cpu.read_modrm_byte(); - let source = cpu.read_mmx_mem64s(); - let destination_low = cpu.reg_mmxs[2 * (cpu.modrm_byte >> 3 & 7)]; - let destination_high = cpu.reg_mmxs[2 * (cpu.modrm_byte >> 3 & 7) + 1]; + if((cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) == PREFIX_66) + { + // psubd xmm, xmm/m128 + let source = cpu.read_xmm_mem128s(); + let destination = cpu.read_xmm128s(); - let low = destination_low - source[0]; - let high = destination_high - source[1]; + cpu.write_xmm128s( + destination[0] - source[0], + destination[1] - source[1], + destination[2] - source[2], + destination[3] - source[3] + ); + } + else + { + // psubd mm, mm/m64 + dbg_assert((cpu.prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) == 0); - cpu.write_mmx64s(low, high); + let source = cpu.read_mmx_mem64s(); + let destination_low = cpu.reg_mmxs[2 * (cpu.modrm_byte >> 3 & 7)]; + let destination_high = cpu.reg_mmxs[2 * (cpu.modrm_byte >> 3 & 7) + 1]; + + cpu.write_mmx64s( + destination_low - source[0], + destination_high - source[1] + ); + } }; t[0xFB] = cpu => { cpu.unimplemented_sse(); }; diff --git a/src/io.js b/src/io.js index 5d2d1ccb..b8a93451 100644 --- a/src/io.js +++ b/src/io.js @@ -20,7 +20,7 @@ function IO(cpu) this.ports[i] = this.create_empty_entry(); } - var memory_size = cpu.memory_size; + var memory_size = cpu.memory_size[0]; for(var i = 0; (i << MMAP_BLOCK_BITS) < memory_size; i++) { @@ -253,7 +253,7 @@ IO.prototype.in_mmap_range = function(start, count) var end = start + count; - if(end >= this.cpu.memory_size) + if(end >= this.cpu.memory_size[0]) { return true; } diff --git a/src/ioapic.js b/src/ioapic.js index 811cbea6..77a1fcc3 100644 --- a/src/ioapic.js +++ b/src/ioapic.js @@ -120,7 +120,7 @@ function IOAPIC(cpu) dbg_assert(false); } }); -} +}; IOAPIC.prototype.remote_eoi = function(vector) { diff --git a/src/log.js b/src/log.js index 1e740950..881b095f 100644 --- a/src/log.js +++ b/src/log.js @@ -87,6 +87,27 @@ var dbg_log = (function() return dbg_log_; })(); +function dbg_log_wasm(memory, offset, args) +{ + if(!(LOG_LEVEL & LOG_CPU)) + { + return; + } + + let s = new Uint8Array(memory, offset); + let length = s.indexOf(0); + if(length !== -1) + { + s = new Uint8Array(memory, offset, length); + } + + let format_string = "[CPU ] " + String.fromCharCode.apply(String, s); + let format_args = [format_string]; + format_args.push.apply(format_args, args); + + console.log.apply(console, format_args); +} + /** * @param {number=} level */ diff --git a/src/main.js b/src/main.js index 46e6cf3a..fd163347 100644 --- a/src/main.js +++ b/src/main.js @@ -1,7 +1,10 @@ "use strict"; -/** @constructor */ -function v86(bus) +/** + * @constructor + * @param {Object=} wm + */ +function v86(bus, wm) { /** @type {boolean} */ this.running = false; @@ -10,7 +13,7 @@ function v86(bus) this.stopped = false; /** @type {CPU} */ - this.cpu = new CPU(bus); + this.cpu = new CPU(bus, wm); this.bus = bus; bus.register("cpu-init", this.init, this); diff --git a/src/memory.js b/src/memory.js index 9db53240..3f4ca06d 100644 --- a/src/memory.js +++ b/src/memory.js @@ -81,7 +81,7 @@ CPU.prototype.mmap_write32 = function(addr, value) CPU.prototype.in_mapped_range = function(addr) { - return (addr | 0) >= 0xA0000 && (addr | 0) < 0xC0000 || (addr >>> 0) >= (this.memory_size >>> 0); + return (addr | 0) >= 0xA0000 && (addr | 0) < 0xC0000 || (addr >>> 0) >= (this.memory_size[0] >>> 0); }; /** @@ -90,7 +90,7 @@ CPU.prototype.in_mapped_range = function(addr) CPU.prototype.read8 = function(addr) { this.debug_read(addr, 1); - if(USE_A20 && !this.a20_enabled) addr &= A20_MASK; + if(USE_A20 && !this.a20_enabled[0]) addr &= A20_MASK; if(this.in_mapped_range(addr)) { @@ -108,7 +108,7 @@ CPU.prototype.read8 = function(addr) CPU.prototype.read16 = function(addr) { this.debug_read(addr, 2); - if(USE_A20 && !this.a20_enabled) addr &= A20_MASK; + if(USE_A20 && !this.a20_enabled[0]) addr &= A20_MASK; if(this.in_mapped_range(addr)) { @@ -127,7 +127,7 @@ CPU.prototype.read_aligned16 = function(addr) { dbg_assert(addr >= 0 && addr < 0x80000000); this.debug_read(addr << 1, 2); - if(USE_A20 && !this.a20_enabled) addr &= A20_MASK16; + if(USE_A20 && !this.a20_enabled[0]) addr &= A20_MASK16; if(this.in_mapped_range(addr << 1)) { @@ -145,7 +145,7 @@ CPU.prototype.read_aligned16 = function(addr) CPU.prototype.read32s = function(addr) { this.debug_read(addr, 4); - if(USE_A20 && !this.a20_enabled) addr &= A20_MASK; + if(USE_A20 && !this.a20_enabled[0]) addr &= A20_MASK; if(this.in_mapped_range(addr)) { @@ -165,7 +165,7 @@ CPU.prototype.read_aligned32 = function(addr) { dbg_assert(addr >= 0 && addr < 0x40000000); this.debug_read(addr << 2, 4); - if(USE_A20 && !this.a20_enabled) addr &= A20_MASK32; + if(USE_A20 && !this.a20_enabled[0]) addr &= A20_MASK32; if(this.in_mapped_range(addr << 2)) { @@ -184,7 +184,7 @@ CPU.prototype.read_aligned32 = function(addr) CPU.prototype.write8 = function(addr, value) { this.debug_write(addr, 1, value); - if(USE_A20 && !this.a20_enabled) addr &= A20_MASK; + if(USE_A20 && !this.a20_enabled[0]) addr &= A20_MASK; if(this.in_mapped_range(addr)) { @@ -203,7 +203,7 @@ CPU.prototype.write8 = function(addr, value) CPU.prototype.write16 = function(addr, value) { this.debug_write(addr, 2, value); - if(USE_A20 && !this.a20_enabled) addr &= A20_MASK; + if(USE_A20 && !this.a20_enabled[0]) addr &= A20_MASK; if(this.in_mapped_range(addr)) { @@ -224,7 +224,7 @@ CPU.prototype.write_aligned16 = function(addr, value) { dbg_assert(addr >= 0 && addr < 0x80000000); this.debug_write(addr << 1, 2, value); - if(USE_A20 && !this.a20_enabled) addr &= A20_MASK16; + if(USE_A20 && !this.a20_enabled[0]) addr &= A20_MASK16; if(this.in_mapped_range(addr << 1)) { @@ -243,7 +243,7 @@ CPU.prototype.write_aligned16 = function(addr, value) CPU.prototype.write32 = function(addr, value) { this.debug_write(addr, 4, value); - if(USE_A20 && !this.a20_enabled) addr &= A20_MASK; + if(USE_A20 && !this.a20_enabled[0]) addr &= A20_MASK; if(this.in_mapped_range(addr)) { @@ -262,7 +262,7 @@ CPU.prototype.write_aligned32 = function(addr, value) { dbg_assert(addr >= 0 && addr < 0x40000000); this.debug_write(addr << 2, 4, value); - if(USE_A20 && !this.a20_enabled) addr &= A20_MASK32; + if(USE_A20 && !this.a20_enabled[0]) addr &= A20_MASK32; if(this.in_mapped_range(addr << 2)) { diff --git a/src/misc_instr.js b/src/misc_instr.js index 37003121..48f83226 100644 --- a/src/misc_instr.js +++ b/src/misc_instr.js @@ -20,7 +20,7 @@ CPU.prototype.jmpcc8 = function(condition) var imm8 = this.read_op8s(); if(condition) { - this.instruction_pointer = this.instruction_pointer + imm8 | 0; + this.instruction_pointer[0] = this.instruction_pointer[0] + imm8 | 0; this.branch_taken(); } else @@ -35,9 +35,9 @@ CPU.prototype.jmp_rel16 = function(rel16) // limit ip to 16 bit // ugly - this.instruction_pointer -= current_cs; - this.instruction_pointer = (this.instruction_pointer + rel16) & 0xFFFF; - this.instruction_pointer = this.instruction_pointer + current_cs | 0; + this.instruction_pointer[0] -= current_cs; + this.instruction_pointer[0] = (this.instruction_pointer[0] + rel16) & 0xFFFF; + this.instruction_pointer[0] = this.instruction_pointer[0] + current_cs | 0; }; CPU.prototype.jmpcc16 = function(condition) @@ -54,7 +54,6 @@ CPU.prototype.jmpcc16 = function(condition) } } - CPU.prototype.jmpcc32 = function(condition) { var imm32s = this.read_op32s(); @@ -63,7 +62,7 @@ CPU.prototype.jmpcc32 = function(condition) // don't change to `this.instruction_pointer += this.read_op32s()`, // since read_op32s modifies instruction_pointer - this.instruction_pointer = this.instruction_pointer + imm32s | 0; + this.instruction_pointer[0] = this.instruction_pointer[0] + imm32s | 0; this.branch_taken(); } else @@ -99,7 +98,7 @@ CPU.prototype.loopne = function(imm8s) { if(this.decr_ecx_asize() && !this.getzf()) { - this.instruction_pointer = this.instruction_pointer + imm8s | 0; + this.instruction_pointer[0] = this.instruction_pointer[0] + imm8s | 0; this.branch_taken(); } else @@ -112,7 +111,7 @@ CPU.prototype.loope = function(imm8s) { if(this.decr_ecx_asize() && this.getzf()) { - this.instruction_pointer = this.instruction_pointer + imm8s | 0; + this.instruction_pointer[0] = this.instruction_pointer[0] + imm8s | 0; this.branch_taken(); } else @@ -125,7 +124,7 @@ CPU.prototype.loop = function(imm8s) { if(this.decr_ecx_asize()) { - this.instruction_pointer = this.instruction_pointer + imm8s | 0; + this.instruction_pointer[0] = this.instruction_pointer[0] + imm8s | 0; this.branch_taken(); } else @@ -138,7 +137,7 @@ CPU.prototype.jcxz = function(imm8s) { if(this.get_reg_asize(reg_ecx) === 0) { - this.instruction_pointer = this.instruction_pointer + imm8s | 0; + this.instruction_pointer[0] = this.instruction_pointer[0] + imm8s | 0; this.branch_taken(); } else @@ -149,83 +148,82 @@ CPU.prototype.jcxz = function(imm8s) /** * @return {number} - * @const */ CPU.prototype.getcf = function() { - if(this.flags_changed & 1) + if(this.flags_changed[0] & 1) { - return (this.last_op1 ^ (this.last_op1 ^ this.last_op2) & (this.last_op2 ^ this.last_add_result)) >>> this.last_op_size & 1; + return (this.last_op1[0] ^ (this.last_op1[0] ^ this.last_op2[0]) & (this.last_op2[0] ^ this.last_add_result[0])) >>> this.last_op_size[0] & 1; } else { - return this.flags & 1; + return this.flags[0] & 1; } }; /** @return {number} */ CPU.prototype.getpf = function() { - if(this.flags_changed & flag_parity) + if(this.flags_changed[0] & flag_parity) { // inverted lookup table - return 0x9669 << 2 >> ((this.last_result ^ this.last_result >> 4) & 0xF) & flag_parity; + return 0x9669 << 2 >> ((this.last_result[0] ^ this.last_result[0] >> 4) & 0xF) & flag_parity; } else { - return this.flags & flag_parity; + return this.flags[0] & flag_parity; } }; /** @return {number} */ CPU.prototype.getaf = function() { - if(this.flags_changed & flag_adjust) + if(this.flags_changed[0] & flag_adjust) { - return (this.last_op1 ^ this.last_op2 ^ this.last_add_result) & flag_adjust; + return (this.last_op1[0] ^ this.last_op2[0] ^ this.last_add_result[0]) & flag_adjust; } else { - return this.flags & flag_adjust; + return this.flags[0] & flag_adjust; } }; /** @return {number} */ CPU.prototype.getzf = function() { - if(this.flags_changed & flag_zero) + if(this.flags_changed[0] & flag_zero) { - return (~this.last_result & this.last_result - 1) >>> this.last_op_size & 1; + return (~this.last_result[0] & this.last_result[0] - 1) >>> this.last_op_size[0] & 1; } else { - return this.flags & flag_zero; + return this.flags[0] & flag_zero; } }; /** @return {number} */ CPU.prototype.getsf = function() { - if(this.flags_changed & flag_sign) + if(this.flags_changed[0] & flag_sign) { - return this.last_result >>> this.last_op_size & 1; + return this.last_result[0] >>> this.last_op_size[0] & 1; } else { - return this.flags & flag_sign; + return this.flags[0] & flag_sign; } }; /** @return {number} */ CPU.prototype.getof = function() { - if(this.flags_changed & flag_overflow) + if(this.flags_changed[0] & flag_overflow) { - return ((this.last_op1 ^ this.last_add_result) & (this.last_op2 ^ this.last_add_result)) >>> this.last_op_size & 1; + return ((this.last_op1[0] ^ this.last_add_result[0]) & (this.last_op2[0] ^ this.last_add_result[0])) >>> this.last_op_size[0] & 1; } else { - return this.flags & flag_overflow; + return this.flags[0] & flag_overflow; } }; @@ -402,44 +400,44 @@ CPU.prototype.xchg32r = function(operand) CPU.prototype.lss16 = function(seg) { - if(this.modrm_byte >= 0xC0) + if(this.modrm_byte[0] >= 0xC0) { // 0xc4c4 #ud (EMULATOR_BOP) is used by reactos and windows to exit vm86 mode this.trigger_ud(); } - var addr = this.modrm_resolve(this.modrm_byte); + var addr = this.modrm_resolve(this.modrm_byte[0]); var new_reg = this.safe_read16(addr), new_seg = this.safe_read16(addr + 2 | 0); this.switch_seg(seg, new_seg); - this.reg16[this.modrm_byte >> 2 & 14] = new_reg; + this.reg16[this.modrm_byte[0] >> 2 & 14] = new_reg; } CPU.prototype.lss32 = function(seg) { - if(this.modrm_byte >= 0xC0) + if(this.modrm_byte[0] >= 0xC0) { this.trigger_ud(); } - var addr = this.modrm_resolve(this.modrm_byte); + var addr = this.modrm_resolve(this.modrm_byte[0]); var new_reg = this.safe_read32s(addr), new_seg = this.safe_read16(addr + 4 | 0); this.switch_seg(seg, new_seg); - this.reg32s[this.modrm_byte >> 3 & 7] = new_reg; + this.reg32s[this.modrm_byte[0] >> 3 & 7] = new_reg; } CPU.prototype.enter16 = function(size, nesting_level) { nesting_level &= 31; - if(nesting_level) dbg_log("enter16 stack=" + (this.stack_size_32 ? 32 : 16) + " size=" + size + " nest=" + nesting_level, LOG_CPU); + if(nesting_level) dbg_log("enter16 stack=" + (this.stack_size_32[0] ? 32 : 16) + " size=" + size + " nest=" + nesting_level, LOG_CPU); this.push16(this.reg16[reg_bp]); var frame_temp = this.reg16[reg_sp]; @@ -461,7 +459,7 @@ CPU.prototype.enter32 = function(size, nesting_level) { nesting_level &= 31; - if(nesting_level) dbg_log("enter32 stack=" + (this.stack_size_32 ? 32 : 16) + " size=" + size + " nest=" + nesting_level, LOG_CPU); + if(nesting_level) dbg_log("enter32 stack=" + (this.stack_size_32[0] ? 32 : 16) + " size=" + size + " nest=" + nesting_level, LOG_CPU); this.push32(this.reg32s[reg_ebp]); var frame_temp = this.reg32s[reg_esp]; @@ -492,7 +490,7 @@ CPU.prototype.fxsave = function(addr) this.safe_write16(addr + 0 | 0, this.fpu.control_word); this.safe_write16(addr + 2 | 0, this.fpu.load_status_word()); - this.safe_write8( addr + 4 | 0, ~this.fpu.stack_empty & 0xFF); + this.safe_write8( addr + 4 | 0, ~this.fpu.stack_empty[0] & 0xFF); this.safe_write16(addr + 6 | 0, this.fpu.fpu_opcode); this.safe_write32(addr + 8 | 0, this.fpu.fpu_ip); this.safe_write16(addr + 12 | 0, this.fpu.fpu_ip_selector); @@ -534,7 +532,7 @@ CPU.prototype.fxrstor = function(addr) this.fpu.control_word = this.safe_read16(addr + 0 | 0); this.fpu.set_status_word(this.safe_read16(addr + 2 | 0)); - this.fpu.stack_empty = ~this.safe_read8(addr + 4 | 0) & 0xFF; + this.fpu.stack_empty[0] = ~this.safe_read8(addr + 4 | 0) & 0xFF; this.fpu.fpu_opcode = this.safe_read16(addr + 6 | 0); this.fpu.fpu_ip = this.safe_read32s(addr + 8 | 0); this.fpu.fpu_ip = this.safe_read16(addr + 12 | 0); diff --git a/src/native/all.c b/src/native/all.c new file mode 100644 index 00000000..b208ed84 --- /dev/null +++ b/src/native/all.c @@ -0,0 +1,19 @@ +#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); +extern void throw_cpu_exception(void); + +#include "const.h" +#include "global_pointers.h" +#include "log.c" +#include "cpu.c" +#include "memory.c" +#include "modrm.c" +#include "misc_instr.c" +#include "arith.c" +#include "fpu.c" +#include "instructions.c" +#include "instructions_0f.c" diff --git a/src/native/arith.c b/src/native/arith.c new file mode 100644 index 00000000..e9cc853f --- /dev/null +++ b/src/native/arith.c @@ -0,0 +1,825 @@ +#include +#include +#include +#include + +#include + +#include "const.h" +#include "global_pointers.h" + +int32_t add(int32_t dest_operand, int32_t source_operand, int32_t op_size) +{ + *last_op1 = dest_operand; + *last_op2 = source_operand; + int32_t res = dest_operand + source_operand; + *last_add_result = *last_result = res; + + *last_op_size = op_size; + *flags_changed = FLAGS_ALL; + + return res; +} + +int32_t adc(int32_t dest_operand, int32_t source_operand, int32_t op_size) +{ + int32_t cf = getcf(); + *last_op1 = dest_operand; + *last_op2 = source_operand; + + int32_t res = dest_operand + source_operand + cf; + + *last_add_result = *last_result = res; + + *last_op_size = op_size; + *flags_changed = FLAGS_ALL; + + return res; +} + +int32_t sub(int32_t dest_operand, int32_t source_operand, int32_t op_size) +{ + *last_add_result = dest_operand; + *last_op2 = source_operand; + + int32_t res = dest_operand - source_operand; + + *last_op1 = *last_result = res; + + *last_op_size = op_size; + *flags_changed = FLAGS_ALL; + + return res; +} + +int32_t sbb(int32_t dest_operand, int32_t source_operand, int32_t op_size) +{ + int32_t cf = getcf(); + *last_add_result = dest_operand; + *last_op2 = source_operand; + + int32_t res = dest_operand - source_operand - cf; + + *last_op1 = *last_result = res; + + *last_op_size = op_size; + *flags_changed = FLAGS_ALL; + + return res; +} + +int32_t add8(int32_t x, int32_t y) { return add(x, y, OPSIZE_8); } +int32_t add16(int32_t x, int32_t y) { return add(x, y, OPSIZE_16); } +int32_t add32(int32_t x, int32_t y) { return add(x, y, OPSIZE_32); } + +int32_t sub8(int32_t x, int32_t y) { return sub(x, y, OPSIZE_8); } +int32_t sub16(int32_t x, int32_t y) { return sub(x, y, OPSIZE_16); } +int32_t sub32(int32_t x, int32_t y) { return sub(x, y, OPSIZE_32); } + +int32_t adc8(int32_t x, int32_t y) { return adc(x, y, OPSIZE_8); } +int32_t adc16(int32_t x, int32_t y) { return adc(x, y, OPSIZE_16); } +int32_t adc32(int32_t x, int32_t y) { return adc(x, y, OPSIZE_32); } + +int32_t sbb8(int32_t x, int32_t y) { return sbb(x, y, OPSIZE_8); } +int32_t sbb16(int32_t x, int32_t y) { return sbb(x, y, OPSIZE_16); } +int32_t sbb32(int32_t x, int32_t y) { return sbb(x, y, OPSIZE_32); } + +void cmp8(int32_t x, int32_t y) { sub(x, y, OPSIZE_8); } +void cmp16(int32_t x, int32_t y) { sub(x, y, OPSIZE_16); } +void cmp32(int32_t x, int32_t y) { sub(x, y, OPSIZE_32); } + +int32_t inc(int32_t dest_operand, int32_t op_size) +{ + *flags = (*flags & ~1) | getcf(); + *last_op1 = dest_operand; + *last_op2 = 1; + + int32_t res = dest_operand + 1; + + *last_add_result = *last_result = res; + *last_op_size = op_size; + *flags_changed = FLAGS_ALL & ~1; + + return res; +} + +int32_t dec(int32_t dest_operand, int32_t op_size) +{ + *flags = (*flags & ~1) | getcf(); + *last_add_result = dest_operand; + *last_op2 = 1; + + int32_t res = dest_operand - 1; + + *last_op1 = *last_result = res; + *last_op_size = op_size; + *flags_changed = FLAGS_ALL & ~1; + + return res; +} + +int32_t inc8(int32_t x) { return inc(x, OPSIZE_8); } +int32_t inc16(int32_t x) { return inc(x, OPSIZE_16); } +int32_t inc32(int32_t x) { return inc(x, OPSIZE_32); } + +int32_t dec8(int32_t x) { return dec(x, OPSIZE_8); } +int32_t dec16(int32_t x) { return dec(x, OPSIZE_16); } +int32_t dec32(int32_t x) { return dec(x, OPSIZE_32); } + +int32_t neg(int32_t dest_operand, int32_t op_size) +{ + int32_t res = -dest_operand; + *last_op1 = *last_result = res; + *flags_changed = FLAGS_ALL; + *last_add_result = 0; + *last_op2 = dest_operand; + *last_op_size = op_size; + + return res; +} + +int32_t neg8(int32_t x) { return neg(x, OPSIZE_8); } +int32_t neg16(int32_t x) { return neg(x, OPSIZE_16); } +int32_t neg32(int32_t x) { return neg(x, OPSIZE_32); } + +void mul8(int32_t source_operand) +{ + int32_t result = source_operand * reg8[AL]; + + reg16[AX] = result; + *last_result = result & 0xFF; + *last_op_size = OPSIZE_8; + + if(result < 0x100) + { + *flags = *flags & ~1 & ~FLAG_OVERFLOW; + } + else + { + *flags = *flags | 1 | FLAG_OVERFLOW; + } + + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; +} + +void imul8(int32_t source_operand) +{ + int32_t result = source_operand * reg8s[AL]; + + reg16[AX] = result; + *last_result = result & 0xFF; + *last_op_size = OPSIZE_8; + + if(result > 0x7F || result < -0x80) + { + *flags = *flags | 1 | FLAG_OVERFLOW; + } + else + { + *flags = *flags & ~1 & ~FLAG_OVERFLOW; + } + + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; +} + +void mul16(uint32_t source_operand) +{ + uint32_t result = source_operand * reg16[AX]; + uint32_t high_result = result >> 16; + + + reg16[AX] = result; + reg16[DX] = high_result; + + *last_result = result & 0xFFFF; + *last_op_size = OPSIZE_16; + + if(high_result == 0) + { + *flags &= ~1 & ~FLAG_OVERFLOW; + } + else + { + *flags |= *flags | 1 | FLAG_OVERFLOW; + } + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; +} + +void imul16(int32_t source_operand) +{ + int32_t result = source_operand * reg16s[AX]; + + reg16[AX] = result; + reg16[DX] = result >> 16; + + *last_result = result & 0xFFFF; + *last_op_size = OPSIZE_16; + + if(result > 0x7FFF || result < -0x8000) + { + *flags |= 1 | FLAG_OVERFLOW; + } + else + { + *flags &= ~1 & ~FLAG_OVERFLOW; + } + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; +} + +int32_t imul_reg16(int32_t operand1, int32_t operand2) +{ + assert(operand1 < 0x8000 && operand1 >= -0x8000); + assert(operand2 < 0x8000 && operand2 >= -0x8000); + + int32_t result = operand1 * operand2; + + *last_result = result & 0xFFFF; + *last_op_size = OPSIZE_16; + + if(result > 0x7FFF || result < -0x8000) + { + *flags |= 1 | FLAG_OVERFLOW; + } + else + { + *flags &= ~1 & ~FLAG_OVERFLOW; + } + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; + + 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); + + reg32s[EAX] = mul32_result[0]; + reg32s[EDX] = mul32_result[1]; + + *last_result = mul32_result[0]; + *last_op_size = OPSIZE_32; + + if(mul32_result[1] == 0) + { + *flags &= ~1 & ~FLAG_OVERFLOW; + } + else + { + *flags |= 1 | FLAG_OVERFLOW; + } + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; +} + +void imul32(int32_t source_operand) +{ + //XXX: this assert fails since the limits here are out of bounds for int32 + //but the assert is present in the original JS source :| + //assert(source_operand < 0x80000000 && source_operand >= -0x80000000); + + int32_t dest_operand = reg32s[EAX]; + + do_imul32(dest_operand, source_operand); + + reg32s[EAX] = mul32_result[0]; + reg32s[EDX] = mul32_result[1]; + + *last_result = mul32_result[0]; + *last_op_size = OPSIZE_32; + + if(mul32_result[1] == (mul32_result[0] >> 31)) + { + *flags &= ~1 & ~FLAG_OVERFLOW; + } + else + { + *flags |= 1 | FLAG_OVERFLOW; + } + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; +} + +int32_t imul_reg32(int32_t operand1, int32_t operand2) +{ + //XXX: assert limits OOB for int32 + //dbg_assert(operand1 < 0x80000000 && operand1 >= -0x80000000); + //dbg_assert(operand2 < 0x80000000 && operand2 >= -0x80000000); + + do_imul32(operand1, operand2); + + *last_result = mul32_result[0]; + *last_op_size = OPSIZE_32; + + if(mul32_result[1] == (mul32_result[0] >> 31)) + { + *flags &= ~1 & ~FLAG_OVERFLOW; + } + else + { + *flags |= 1 | FLAG_OVERFLOW; + } + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; + + return mul32_result[0]; +} + +int32_t xadd8(int32_t source_operand, int32_t reg) +{ + int32_t tmp = reg8[reg]; + + reg8[reg] = source_operand; + + return add(source_operand, tmp, OPSIZE_8); +} + +int32_t xadd16(int32_t source_operand, int32_t reg) +{ + int32_t tmp = reg16[reg]; + + reg16[reg] = source_operand; + + return add(source_operand, tmp, OPSIZE_16); +} + +int32_t xadd32(int32_t source_operand, int32_t reg) +{ + int32_t tmp = reg32s[reg]; + + reg32s[reg] = source_operand; + + return add(source_operand, tmp, OPSIZE_32); +} + +void bcd_daa() +{ + int32_t old_al = reg8[AL]; + int32_t old_cf = getcf(); + int32_t old_af = getaf(); + + *flags &= ~1 & ~FLAG_ADJUST; + + if((old_al & 0xF) > 9 || old_af) + { + reg8[AL] += 6; + *flags |= FLAG_ADJUST; + } + if(old_al > 0x99 || old_cf) + { + reg8[AL] += 0x60; + *flags |= 1; + } + + *last_result = reg8[AL]; + *last_op_size = OPSIZE_8; + *last_op1 = *last_op2 = 0; + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_ADJUST & ~FLAG_OVERFLOW; +} + +void bcd_das() +{ + int32_t old_al = reg8[AL]; + int32_t old_cf = getcf(); + + *flags &= ~1; + + if((old_al & 0xF) > 9 || getaf()) + { + reg8[AL] -= 6; + *flags |= FLAG_ADJUST; + *flags = *flags & ~1 | old_cf | (old_al < 6); + } + else + { + *flags &= ~FLAG_ADJUST; + } + + if(old_al > 0x99 || old_cf) + { + reg8[AL] -= 0x60; + *flags |= 1; + } + + *last_result = reg8[AL]; + *last_op_size = OPSIZE_8; + *last_op1 = *last_op2 = 0; + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_ADJUST & ~FLAG_OVERFLOW; +} + +void bcd_aad(int32_t imm8) +{ + int32_t result = reg8[AL] + reg8[AH] * imm8; + *last_result = result & 0xFF; + reg16[AX] = *last_result; + *last_op_size = OPSIZE_8; + + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_ADJUST & ~FLAG_OVERFLOW; + *flags &= ~1 & ~FLAG_ADJUST & ~FLAG_OVERFLOW; + + if(result > 0xFFFF) + { + *flags |= 1; + } +} + +void bcd_aaa() +{ + if((reg8[AL] & 0xF) > 9 || getaf()) + { + reg16[AX] += 6; + reg8[AH] += 1; + *flags |= FLAG_ADJUST | 1; + } + else + { + *flags &= ~FLAG_ADJUST & ~1; + } + reg8[AL] &= 0xF; + + *flags_changed &= ~FLAG_ADJUST & ~1; +} + +void bcd_aas() +{ + if((reg8[AL] & 0xF) > 9 || getaf()) + { + reg16[AX] -= 6; + reg8[AH] -= 1; + *flags |= FLAG_ADJUST | 1; + } + else + { + *flags &= ~FLAG_ADJUST & ~1; + } + reg8[AL] &= 0xF; + + *flags_changed &= ~FLAG_ADJUST & ~1; +} + +int32_t and(int32_t dest_operand, int32_t source_operand, int32_t op_size) +{ + *last_result = dest_operand & source_operand; + + *last_op_size = op_size; + *flags &= ~1 & ~FLAG_OVERFLOW & ~FLAG_ADJUST; + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW & ~FLAG_ADJUST; + + return *last_result; +} + +int32_t or(int32_t dest_operand, int32_t source_operand, int32_t op_size) +{ + *last_result = dest_operand | source_operand; + + *last_op_size = op_size; + *flags &= ~1 & ~FLAG_OVERFLOW & ~FLAG_ADJUST; + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW & ~FLAG_ADJUST; + + return *last_result; +} + +int32_t xor(int32_t dest_operand, int32_t source_operand, int32_t op_size) +{ + *last_result = dest_operand ^ source_operand; + + *last_op_size = op_size; + *flags &= ~1 & ~FLAG_OVERFLOW & ~FLAG_ADJUST; + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW & ~FLAG_ADJUST; + + return *last_result; +} + +int32_t and8(int32_t x, int32_t y) { return and(x, y, OPSIZE_8); } +int32_t and16(int32_t x, int32_t y) { return and(x, y, OPSIZE_16); } +int32_t and32(int32_t x, int32_t y) { return and(x, y, OPSIZE_32); } + +void test8(int32_t x, int32_t y) { and(x, y, OPSIZE_8); } +void test16(int32_t x, int32_t y) { and(x, y, OPSIZE_16); } +void test32(int32_t x, int32_t y) { and(x, y, OPSIZE_32); } + +int32_t or8(int32_t x, int32_t y) { return or(x, y, OPSIZE_8); } +int32_t or16(int32_t x, int32_t y) { return or(x, y, OPSIZE_16); } +int32_t or32(int32_t x, int32_t y) { return or(x, y, OPSIZE_32); } + +int32_t xor8(int32_t x, int32_t y) { return xor(x, y, OPSIZE_8); } +int32_t xor16(int32_t x, int32_t y) { return xor(x, y, OPSIZE_16); } +int32_t xor32(int32_t x, int32_t y) { return xor(x, y, OPSIZE_32); } + +int32_t rol8(int32_t dest_operand, int32_t count) +{ + if(!count) + { + return dest_operand; + } + count &= 7; + + int32_t result = dest_operand << count | dest_operand >> (8 - count); + + *flags_changed &= ~1 & ~FLAG_OVERFLOW; + *flags = (*flags & ~1 & ~FLAG_OVERFLOW) + | (result & 1) + | (result << 11 ^ result << 4) & FLAG_OVERFLOW; + + return result; +} + +int32_t rol16(int32_t dest_operand, int32_t count) +{ + if(!count) + { + return dest_operand; + } + count &= 15; + + int32_t result = dest_operand << count | dest_operand >> (16 - count); + + *flags_changed &= ~1 & ~FLAG_OVERFLOW; + *flags = (*flags & ~1 & ~FLAG_OVERFLOW) + | (result & 1) + | (result << 11 ^ result >> 4) & FLAG_OVERFLOW; + + return result; +} + +int32_t rol32(int32_t dest_operand, int32_t count) +{ + if(!count) + { + return dest_operand; + } + + int32_t result = dest_operand << count | ((uint32_t) dest_operand) >> (32 - count); + + *flags_changed &= ~1 & ~FLAG_OVERFLOW; + *flags = (*flags & ~1 & ~FLAG_OVERFLOW) + | (result & 1) + | (result << 11 ^ result >> 20) & FLAG_OVERFLOW; + + return result; +} + +int32_t rcl8(int32_t dest_operand, int32_t count) +{ + count %= 9; + if(!count) + { + return dest_operand; + } + + int32_t result = dest_operand << count | getcf() << (count - 1) | dest_operand >> (9 - count); + + *flags_changed &= ~1 & ~FLAG_OVERFLOW; + *flags = (*flags & ~1 & ~FLAG_OVERFLOW) + | (result >> 8 & 1) + | (result << 3 ^ result << 4) & FLAG_OVERFLOW; + + return result; +} + +int32_t rcl16(int32_t dest_operand, int32_t count) +{ + count %= 17; + if(!count) + { + return dest_operand; + } + + int32_t result = dest_operand << count | getcf() << (count - 1) | dest_operand >> (17 - count); + + *flags_changed &= ~1 & ~FLAG_OVERFLOW; + *flags = (*flags & ~1 & ~FLAG_OVERFLOW) + | (result >> 16 & 1) + | (result >> 5 ^ result >> 4) & FLAG_OVERFLOW; + + return result; +} + +int32_t rcl32(int32_t dest_operand, int32_t count) +{ + if(!count) + { + return dest_operand; + } + + int32_t result = dest_operand << count | getcf() << (count - 1); + + if(count > 1) + { + result |= ((uint32_t) dest_operand) >> (33 - count); + } + + *flags_changed &= ~1 & ~FLAG_OVERFLOW; + *flags = (*flags & ~1 & ~FLAG_OVERFLOW) | (((uint32_t) dest_operand) >> (32 - count) & 1); + *flags |= (*flags << 11 ^ result >> 20) & FLAG_OVERFLOW; + + return result; +} + +int32_t ror8(int32_t dest_operand, int32_t count) +{ + if(!count) + { + return dest_operand; + } + + count &= 7; + int32_t result = dest_operand >> count | dest_operand << (8 - count); + + *flags_changed &= ~1 & ~FLAG_OVERFLOW; + *flags = (*flags & ~1 & ~FLAG_OVERFLOW) + | (result >> 7 & 1) + | (result << 4 ^ result << 5) & FLAG_OVERFLOW; + + return result; +} + +int32_t ror16(int32_t dest_operand, int32_t count) +{ + if(!count) + { + return dest_operand; + } + + count &= 15; + int32_t result = dest_operand >> count | dest_operand << (16 - count); + + *flags_changed &= ~1 & ~FLAG_OVERFLOW; + *flags = (*flags & ~1 & ~FLAG_OVERFLOW) + | (result >> 15 & 1) + | (result >> 4 ^ result >> 3) & FLAG_OVERFLOW; + + return result; +} + +int32_t ror32(int32_t dest_operand, int32_t count) +{ + if(!count) + { + return dest_operand; + } + + int32_t result = ((uint32_t) dest_operand) >> count | dest_operand << (32 - count); + + *flags_changed &= ~1 & ~FLAG_OVERFLOW; + *flags = (*flags & ~1 & ~FLAG_OVERFLOW) + | (result >> 31 & 1) + | (result >> 20 ^ result >> 19) & FLAG_OVERFLOW; + + return result; +} + +int32_t rcr8(int32_t dest_operand, int32_t count) +{ + count %= 9; + if(!count) + { + return dest_operand; + } + + int32_t result = dest_operand >> count | getcf() << (8 - count) | dest_operand << (9 - count); + + *flags_changed &= ~1 & ~FLAG_OVERFLOW; + *flags = (*flags & ~1 & ~FLAG_OVERFLOW) + | (result >> 8 & 1) + | (result << 4 ^ result << 5) & FLAG_OVERFLOW; + + return result; +} + +int32_t rcr16(int32_t dest_operand, int32_t count) +{ + count %= 17; + if(!count) + { + return dest_operand; + } + + int32_t result = dest_operand >> count | getcf() << (16 - count) | dest_operand << (17 - count); + + *flags_changed &= ~1 & ~FLAG_OVERFLOW; + *flags = (*flags & ~1 & ~FLAG_OVERFLOW) + | (result >> 16 & 1) + | (result >> 4 ^ result >> 3) & FLAG_OVERFLOW; + + return result; +} + +int32_t rcr32(int32_t dest_operand, int32_t count) +{ + if(!count) + { + return dest_operand; + } + + int32_t result = ((uint32_t) dest_operand) >> count | getcf() << (32 - count); + + if(count > 1) + { + result |= dest_operand << (33 - count); + } + + *flags_changed &= ~1 & ~FLAG_OVERFLOW; + *flags = (*flags & ~1 & ~FLAG_OVERFLOW) + | (dest_operand >> (count - 1) & 1) + | (result >> 20 ^ result >> 19) & FLAG_OVERFLOW; + + return result; +} + +void div8(uint32_t source_operand) +{ + if(source_operand == 0) + { + trigger_de(); + return; + } + + uint16_t target_operand = reg16[AX]; + uint16_t result = target_operand / source_operand; + + if(result >= 0x100) + { + trigger_de(); + } + else + { + reg8[AL] = result; + reg8[AH] = target_operand % source_operand; + } +} + +void idiv8(int32_t source_operand) +{ + if(source_operand == 0) + { + trigger_de(); + return; + } + + int32_t target_operand = reg16s[AX]; + int32_t result = target_operand / source_operand; + + if(result >= 0x80 || result <= -0x81) + { + trigger_de(); + } + else + { + reg8[AL] = result; + reg8[AH] = target_operand % source_operand; + } +} + +void div16(uint32_t source_operand) +{ + if(source_operand == 0) + { + trigger_de(); + return; + } + + uint32_t target_operand = reg16[AX] | reg16[DX] << 16; + uint32_t result = target_operand / source_operand; + + if(result >= 0x10000) + { + trigger_de(); + } + else + { + reg16[AX] = result; + reg16[DX] = target_operand % source_operand; + } +} + diff --git a/src/native/const.h b/src/native/const.h new file mode 100644 index 00000000..b5f8e10f --- /dev/null +++ b/src/native/const.h @@ -0,0 +1,159 @@ +#ifndef DEBUG +#define DEBUG true +#endif + +#define FLAG_CARRY 1 +#define FLAG_PARITY 4 +#define FLAG_ADJUST 16 +#define FLAG_ZERO 64 +#define FLAG_SIGN 128 +#define FLAG_TRAP 256 +#define FLAG_INTERRUPT 512 +#define FLAG_DIRECTION 1024 +#define FLAG_OVERFLOW 2048 +#define FLAG_IOPL (1 << 12 | 1 << 13) +#define FLAG_NT (1 << 14) +#define FLAG_RF (1 << 16) +#define FLAG_VM (1 << 17) +#define FLAG_AC (1 << 18) +#define FLAG_VIF (1 << 19) +#define FLAG_VIP (1 << 20) +#define FLAG_ID (1 << 21) +#define FLAGS_DEFAULT (1 << 1) + +#define FLAGS_MASK ( \ + FLAG_CARRY | FLAG_PARITY | FLAG_ADJUST | FLAG_ZERO | FLAG_SIGN | FLAG_TRAP | FLAG_INTERRUPT | \ + FLAG_DIRECTION | FLAG_OVERFLOW | FLAG_IOPL | FLAG_NT | FLAG_RF | FLAG_VM | FLAG_AC | \ + FLAG_VIF | FLAG_VIP | FLAG_ID) + +#define FLAGS_ALL (FLAG_CARRY | FLAG_PARITY | FLAG_ADJUST | FLAG_ZERO | FLAG_SIGN | FLAG_OVERFLOW) + +#define OPSIZE_8 7 +#define OPSIZE_16 15 +#define OPSIZE_32 31 + +#define EAX 0 +#define ECX 1 +#define EDX 2 +#define EBX 3 +#define ESP 4 +#define EBP 5 +#define ESI 6 +#define EDI 7 + +#define AX 0 +#define CX 2 +#define DX 4 +#define BX 6 +#define SP 8 +#define BP 10 +#define SI 12 +#define DI 14 + +#define AL 0 +#define CL 4 +#define DL 8 +#define BL 12 +#define AH 1 +#define CH 5 +#define DH 9 +#define BH 13 + +#define ES 0 +#define CS 1 +#define SS 2 +#define DS 3 +#define FS 4 +#define GS 5 + +#define TR 6 +#define LDTR 7 + + +#define TLB_SYSTEM_READ 1 +#define TLB_SYSTEM_WRITE 2 +#define TLB_USER_READ 4 +#define TLB_USER_WRITE 8 + + +#define PSE_ENABLED 128 + +#define MMAP_BLOCK_BITS 17 +#define MMAP_BLOCK_SIZE = (1 << MMAP_BLOCK_BITS) + +#define CR0_PE 1 +#define CR0_MP (1 << 1) +#define CR0_EM (1 << 2) +#define CR0_TS (1 << 3) +#define CR0_ET (1 << 4) +#define CR0_WP (1 << 16) +#define CR0_NW (1 << 29) +#define CR0_CD (1 << 30) +#define CR0_PG (1 << 31) + +#define CR4_VME (1) +#define CR4_PVI (1 << 1) +#define CR4_TSD (1 << 2) +#define CR4_PSE (1 << 4) +#define CR4_DE (1 << 3) +#define CR4_PAE (1 << 5) +#define CR4_PGE (1 << 7) + + +#define IA32_SYSENTER_CS 0x174 +#define IA32_SYSENTER_ESP 0x175 +#define IA32_SYSENTER_EIP 0x176 + +#define IA32_TIME_STAMP_COUNTER 0x10 +#define IA32_PLATFORM_ID 0x17 +#define IA32_APIC_BASE_MSR 0x1B +#define IA32_BIOS_SIGN_ID 0x8B +#define IA32_MISC_ENABLE 0x1A0 +#define IA32_RTIT_CTL 0x570 +#define MSR_SMI_COUNT 0x34 +#define IA32_MCG_CAP 0x179 +#define IA32_KERNEL_GS_BASE 0xC0000101 +#define MSR_PKG_C2_RESIDENCY 0x60D + +#define IA32_APIC_BASE_BSP (1 << 8) +#define IA32_APIC_BASE_EXTD (1 << 10) +#define IA32_APIC_BASE_EN (1 << 11) + + +// Note: Duplicated in apic.js +#define APIC_ADDRESS ((int32_t)0xFEE00000) + + +// Segment prefixes must not collide with reg_*s variables +// _ZERO is a special zero offset segment +#define SEG_PREFIX_NONE (-1) +#define SEG_PREFIX_ZERO 7 + +#define PREFIX_MASK_REP 0b11000 +#define PREFIX_REPZ 0b01000 +#define PREFIX_REPNZ 0b10000 + +#define PREFIX_MASK_SEGMENT 0b111 +#define PREFIX_MASK_OPSIZE 0b100000 +#define PREFIX_MASK_ADDRSIZE 0b1000000 + + + +/** + * How many cycles the CPU does at a time before running hardware timers + */ +#define LOOP_COUNTER 11001 + +#define TSC_RATE (8 * 1024) + +#define LOG_CPU 0x000002 +#define CPU_LOG_VERBOSE false +#define ENABLE_ACPI false + +#define A20_MASK (~(1 << 20)) +#define A20_MASK16 (~(1 << (20 - 1))) +#define A20_MASK32 (~(1 << (20 - 2))) + +#define USE_A20 false + +#define MXCSR_MASK (0xFFFF & ~(1 << 6)) diff --git a/src/native/cpu.c b/src/native/cpu.c new file mode 100644 index 00000000..46b45a7e --- /dev/null +++ b/src/native/cpu.c @@ -0,0 +1,572 @@ +#include +#include +#include +#include +#include + +#include "const.h" +#include "global_pointers.h" + +int32_t read_e8_partial_branch() { + return reg8[*modrm_byte << 2 & 0xC | *modrm_byte >> 2 & 1]; +} + +int32_t translate_address_read(int32_t); +int32_t translate_address_write(int32_t); +int32_t read8(uint32_t); +int32_t read16(uint32_t); +int32_t read32s(uint32_t); +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 write32(uint32_t, int32_t); +void virt_boundary_write16(int32_t, int32_t, int32_t); +void virt_boundary_write32(int32_t, int32_t, int32_t); + +void trigger_gp(int32_t); + +int32_t safe_read8(int32_t); +int32_t safe_read16(int32_t); +int32_t safe_read32s(int32_t); + +void safe_write8(int32_t, int32_t); +void safe_write16(int32_t, int32_t); +void safe_write32(int32_t, int32_t); + +void fxsave(int32_t); +void fxrstor(int32_t); + +int32_t do_page_translation(int32_t, bool, bool); + +void diverged() {} +void branch_taken() {} +void branch_not_taken() {} + +int32_t getcf(void); +int32_t getpf(void); +int32_t getaf(void); +int32_t getzf(void); +int32_t getsf(void); +int32_t getof(void); + + +int32_t get_eflags() +{ + return (*flags & ~FLAGS_ALL) | !!getcf() | !!getpf() << 2 | !!getaf() << 4 | + !!getzf() << 6 | !!getsf() << 7 | !!getof() << 11; +} + +int32_t translate_address_read(int32_t address) +{ + if(!*paging) return address; + + int32_t base = (uint32_t)address >> 12; + if(tlb_info[base] & (*cpl == 3 ? TLB_USER_READ : TLB_SYSTEM_READ)) + { + return tlb_data[base] ^ address; + } + else + { + return do_page_translation(address, 0, *cpl == 3) | address & 0xFFF; + } +} + +int32_t translate_address_write(int32_t address) +{ + if(!*paging) return address; + + int32_t base = (uint32_t)address >> 12; + if(tlb_info[base] & (*cpl == 3 ? TLB_USER_WRITE : TLB_SYSTEM_WRITE)) + { + return tlb_data[base] ^ address; + } + else + { + return do_page_translation(address, 1, *cpl == 3) | address & 0xFFF; + } +} + +int32_t read_imm8() +{ + int32_t eip = *instruction_pointer; + + if((eip & ~0xFFF) ^ *last_virt_eip) + { + *eip_phys = translate_address_read(eip) ^ eip; + *last_virt_eip = eip & ~0xFFF; + } + + int32_t data8 = read8(*eip_phys ^ eip); + *instruction_pointer = eip + 1; + + return data8; +} + +int32_t read_imm8s() +{ + return read_imm8() << 24 >> 24; +} + +int32_t read_imm16() +{ + // Two checks in one comparison: + // 1. Did the high 20 bits of eip change + // or 2. Are the low 12 bits of eip 0xFFF (and this read crosses a page boundary) + if((uint32_t)(*instruction_pointer ^ *last_virt_eip) > 0xFFE) + { + return read_imm8() | read_imm8() << 8; + } + + int32_t data16 = read16(*eip_phys ^ *instruction_pointer); + *instruction_pointer = *instruction_pointer + 2; + + return data16; +} + +int32_t read_imm32s() +{ + // Analogue to the above comment + if((uint32_t)(*instruction_pointer ^ *last_virt_eip) > 0xFFC) + { + return read_imm16() | read_imm16() << 16; + } + + int32_t data32 = read32s(*eip_phys ^ *instruction_pointer); + *instruction_pointer = *instruction_pointer + 4; + + 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); +} + +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); + + // TODO: Remove protected_mode check + if(*protected_mode) + { + if(segment_is_null[segment]) + { + assert(segment != CS && segment != SS); + trigger_gp(0); + } + } + + return segment_offsets[segment]; +} + +int32_t get_seg_prefix(int32_t default_segment) +{ + int32_t prefix = *prefixes & PREFIX_MASK_SEGMENT; + + if(prefix) + { + if(prefix == SEG_PREFIX_ZERO) + { + return 0; // TODO: Remove this special case + } + else + { + return get_seg(prefix - 1); + } + } + else + { + return get_seg(default_segment); + } +} + +int32_t get_seg_prefix_ds(int32_t offset) { return get_seg_prefix(DS) + offset; } +int32_t get_seg_prefix_ss(int32_t offset) { return get_seg_prefix(SS) + offset; } +int32_t get_seg_prefix_cs(int32_t offset) { return get_seg_prefix(CS) + offset; } + +static void run_instruction(int32_t); +static int32_t resolve_modrm16(int32_t); +static int32_t resolve_modrm32(int32_t); + +static int32_t modrm_resolve(int32_t modrm_byte) +{ + if(is_asize_32()) + { + return resolve_modrm32(modrm_byte); + } + else + { + return resolve_modrm16(modrm_byte); + } +} + +void set_e8(int32_t value) +{ + 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]; + } +} + +void cycle_internal() +{ + previous_ip[0] = instruction_pointer[0]; + + (*timestamp_counter)++; + + int32_t opcode = read_imm8(); + + run_instruction(opcode); +} + +static void run_prefix_instruction() +{ + run_instruction(read_imm8()); +} + +void clear_prefixes() +{ + *prefixes = 0; +} + +void segment_prefix_op(int32_t seg) +{ + assert(seg <= 5); + *prefixes |= seg + 1; + run_prefix_instruction(); + *prefixes = 0; +} + +void do_many_cycles_unsafe() +{ + for(int32_t k = 0; k < LOOP_COUNTER; k++) + { + cycle_internal(); + } +} + +void raise_exception(int32_t interrupt_nr) +{ + call_interrupt_vector(interrupt_nr, false, false, 0); + throw_cpu_exception(); +} + +void raise_exception_with_code(int32_t interrupt_nr, int32_t error_code) +{ + call_interrupt_vector(interrupt_nr, false, true, error_code); + throw_cpu_exception(); +} + +void trigger_de() +{ + *instruction_pointer = *previous_ip; + raise_exception(0); +} + +void trigger_gp(int32_t code) +{ + *instruction_pointer = *previous_ip; + raise_exception_with_code(13, code); +} + +int32_t safe_read8(int32_t addr) +{ + return read8(translate_address_read(addr)); +} + +int32_t safe_read16(int32_t addr) +{ + if((addr & 0xFFF) == 0xFFF) + { + return safe_read8(addr) | safe_read8(addr + 1) << 8; + } + else + { + return read16(translate_address_read(addr)); + } +} + +int32_t safe_read32s(int32_t addr) +{ + if((addr & 0xFFF) >= 0xFFD) + { + return safe_read16(addr) | safe_read16(addr + 2) << 16; + } + else + { + return read32s(translate_address_read(addr)); + } +} + +void safe_write8(int32_t addr, int32_t value) +{ + write8(translate_address_write(addr), value); +} + +void safe_write16(int32_t addr, int32_t value) +{ + int32_t phys_low = translate_address_write(addr); + + if((addr & 0xFFF) == 0xFFF) + { + virt_boundary_write16(phys_low, translate_address_write(addr + 1), value); + } + else + { + write16(phys_low, value); + } +} + +void safe_write32(int32_t addr, int32_t value) +{ + int32_t phys_low = translate_address_write(addr); + + if((addr & 0xFFF) >= 0xFFD) + { + virt_boundary_write32(phys_low, translate_address_write(addr + 3 & ~3) | (addr + 3) & 3, value); + } + else + { + write32(phys_low, value); + } +} + +int32_t read_write_e8() +{ + if(*modrm_byte < 0xC0) + { + int32_t virt_addr = modrm_resolve(*modrm_byte); + *phys_addr = translate_address_write(virt_addr); + return read8(*phys_addr); + } + else + { + return reg8[*modrm_byte << 2 & 0xC | *modrm_byte >> 2 & 1]; + } +} + +void write_e8(int32_t value) +{ + if(*modrm_byte < 0xC0) + { + write8(*phys_addr, value); + } + else + { + reg8[*modrm_byte << 2 & 0xC | *modrm_byte >> 2 & 1] = value; + } +} + +int32_t read_write_e16() +{ + if(*modrm_byte < 0xC0) + { + 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); + } + } + else + { + return reg16[*modrm_byte << 1 & 14]; + } +} + +void write_e16(int32_t value) +{ + 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; + } +} + +int32_t read_write_e32() +{ + 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]; + } +} + +void write_e32(int32_t value) +{ + 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; + } +} diff --git a/src/native/fpu.c b/src/native/fpu.c new file mode 100644 index 00000000..aab2b889 --- /dev/null +++ b/src/native/fpu.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include + +#include + +#include "const.h" +#include "global_pointers.h" + +void safe_tag_word(int32_t tag_word) { + *stack_empty = 0; + + for(int i = 0; i < 8; i++) + { + *stack_empty |= (tag_word >> i) & (tag_word >> (i + 1)) & 1 << i; + } + + //dbg_log("safe tw=" + h(tag_word) + " se=" + h(this.stack_empty[0]), LOG_FPU); +} diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h new file mode 100644 index 00000000..5651a416 --- /dev/null +++ b/src/native/global_pointers.h @@ -0,0 +1,69 @@ +#ifndef _GLOBAL_POINTERS_H +#define _GLOBAL_POINTERS_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; +int16_t* const reg16s = (int16_t* const) 4; +int32_t* const reg32s = (int32_t* const) 4; + +int32_t* const last_op1 = (int32_t* const) 512; +int32_t* const last_op2 = (int32_t* const) 516; +int32_t* const last_op_size = (int32_t* const) 520; +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 2 + +bool* const a20_enabled = (bool* const) 552; +int32_t* const instruction_pointer = (int32_t* const) 556; +int32_t* const previous_ip = (int32_t* const) 560; + +int32_t* const idtr_size = (int32_t* const) 564; +int32_t* const idtr_offset = (int32_t* const) 568; +int32_t* const gdtr_size = (int32_t* const) 572; +int32_t* const gdtr_offset = (int32_t* const) 576; +int32_t* const cr = (int32_t* const) 580; // length 8 + +int32_t* const cpl = (int32_t* const) 612; +int32_t* const page_size_extensions = (int32_t* const) 616; +int32_t* const last_virt_eip = (int32_t* const) 620; +int32_t* const eip_phys = (int32_t* const) 624; +int32_t* const last_virt_esp = (int32_t* const) 628; +int32_t* const esp_phys = (int32_t* const) 632; +int32_t* const sysenter_cs = (int32_t* const) 636; +int32_t* const sysenter_esp = (int32_t* const) 640; +int32_t* const sysenter_eip = (int32_t* const) 644; +int32_t* const prefixes = (int32_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; + +uint16_t* const sreg = (uint16_t* const) 668; +int32_t* const dreg = (int32_t* const) 684; // length 8 +int32_t* const fw_value = (int32_t* const) 720; +uint8_t* const segment_is_null = (uint8_t* const) 724; // length 8 +int32_t* const segment_offsets = (int32_t* const) 736; // length 8 +uint32_t* const segment_limits = (uint32_t* const) 768; // length 8 + +bool* const protected_mode = (bool* const) 800; +bool* const is_32 = (bool* const) 804; +bool* const stack_size_32 = (bool* const) 808; +uint32_t* const memory_size = (uint32_t* const) 812; +int32_t* const stack_empty = (int32_t* const) 816; + +bool* const paging = (bool* const) 820; + +bool* const mxcsr = (bool* const) 824; + +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); + +#endif diff --git a/src/native/instructions.c b/src/native/instructions.c new file mode 100644 index 00000000..9280ec74 --- /dev/null +++ b/src/native/instructions.c @@ -0,0 +1,3171 @@ +#include +#include +#include +#include + +#include + +#include "const.h" +#include "global_pointers.h" + +int32_t translate_address_write(int32_t); +int32_t resolve_modrm(int32_t); + +/* +int32_t phys_read8(int32_t); +int32_t phys_write8(int32_t, int32_t); + + +#define RE8 reg8[modrm_byte << 2 & 0xC | modrm_byte >> 2 & 1] +#define E8 e8 +#define G8 reg8[modrm_byte >> 1 & 0xC | modrm_byte >> 5 & 1] + +#define IDX_E8 (modrm_byte << 2 & 0xC | modrm_byte >> 2 & 1) +#define IDX_G8 (modrm_byte >> 1 & 0xC | modrm_byte >> 5 & 1) + +#define READ_WRITE_E8_(f)\ +{\ + int32_t modrm_byte = read_modrm_byte();\ + if(modrm_byte < 0xC0) {\ + int32_t phys_addr = translate_address_write(resolve_modrm(modrm_byte));\ + int32_t e8 = phys_read8(phys_addr);\ + phys_write8(phys_addr, f);\ + }\ + else {\ + int32_t e8 = RE8;\ + RE8 = f;\ + }\ +} + +#define READ_WRITE_E8(f)\ +{\ + int32_t modrm_byte = read_modrm_byte();\ + if(modrm_byte < 0xC0) {\ + int32_t virt_addr = resolve_modrm(modrm_byte);\ + f ## _rm(virt_addr, IDX_G8);\ + }\ + else {\ + f ## _rr(IDX_E8, IDX_G8);\ + }\ +} +*/ + + +// 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_e32(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); + +void pusha16(void); +void pusha32(void); +void popa16(void); +void popa32(void); +int32_t arpl(int32_t, int32_t); + +void trigger_ud(void); +void trigger_nm(void); +static void run_prefix_instruction(void); + +int32_t pop16(void); +int32_t pop32s(void); + +int32_t safe_read8(int32_t); +int32_t safe_read16(int32_t); +int32_t safe_read32s(int32_t); + +void safe_write8(int32_t, int32_t); +void safe_write16(int32_t, int32_t); +void safe_write32(int32_t, int32_t); + +void push32(int32_t); +int32_t get_stack_pointer(int32_t); +void adjust_stack_reg(int32_t); +void set_stack_reg(int32_t); + +int32_t getiopl(void); +int32_t get_eflags(void); +int32_t getof(void); +int32_t getzf(void); + +void switch_seg(int32_t, int32_t); + +bool vm86_mode(void); + +int32_t shl8(int32_t, int32_t); +int32_t shr8(int32_t, int32_t); +int32_t sar8(int32_t, int32_t); +int32_t ror8(int32_t, int32_t); +int32_t rol8(int32_t, int32_t); +int32_t rcr8(int32_t, int32_t); +int32_t rcl8(int32_t, int32_t); + +int32_t shl16(int32_t, int32_t); +int32_t shr16(int32_t, int32_t); +int32_t sar16(int32_t, int32_t); +int32_t ror16(int32_t, int32_t); +int32_t rol16(int32_t, int32_t); +int32_t rcr16(int32_t, int32_t); +int32_t rcl16(int32_t, int32_t); + +int32_t shl32(int32_t, int32_t); +int32_t shr32(int32_t, int32_t); +int32_t sar32(int32_t, int32_t); +int32_t ror32(int32_t, int32_t); +int32_t rol32(int32_t, int32_t); +int32_t rcr32(int32_t, int32_t); +int32_t rcl32(int32_t, int32_t); + +int32_t idiv16(int32_t); +int32_t div32(int32_t); +int32_t idiv32(int32_t); + + +void insb(void); +void insw(void); +void insd(void); +void outsb(void); +void outsw(void); +void outsd(void); +void movsb(void); +void movsw(void); +void movsd(void); +void cmpsb(void); +void cmpsw(void); +void cmpsd(void); +void stosb(void); +void stosw(void); +void stosd(void); +void lodsb(void); +void lodsw(void); +void lodsd(void); +void scasb(void); +void scasw(void); +void scasd(void); + +void fpu_op_D8_mem(int32_t, int32_t); +void fpu_op_D8_reg(int32_t); +void fpu_op_D9_mem(int32_t, int32_t); +void fpu_op_D9_reg(int32_t); +void fpu_op_DA_mem(int32_t, int32_t); +void fpu_op_DA_reg(int32_t); +void fpu_op_DB_mem(int32_t, int32_t); +void fpu_op_DB_reg(int32_t); +void fpu_op_DC_mem(int32_t, int32_t); +void fpu_op_DC_reg(int32_t); +void fpu_op_DD_mem(int32_t, int32_t); +void fpu_op_DD_reg(int32_t); +void fpu_op_DE_mem(int32_t, int32_t); +void fpu_op_DE_reg(int32_t); +void fpu_op_DF_mem(int32_t, int32_t); +void fpu_op_DF_reg(int32_t); + +int32_t test_o(void); +int32_t test_b(void); +int32_t test_z(void); +int32_t test_s(void); +int32_t test_p(void); +int32_t test_be(void); +int32_t test_l(void); +int32_t test_le(void); + +void jmpcc8(bool); + +void far_jump(int32_t, int32_t, int32_t); +void far_return(int32_t, int32_t, int32_t); + +void iret16(); +void iret32(); + +void lss16(int32_t); +void lss32(int32_t); + +void enter16(int32_t, int32_t); +void enter32(int32_t, int32_t); + +int32_t get_seg(int32_t); +int32_t get_seg_prefix(int32_t); +void update_eflags(int32_t); +void handle_irqs(void); +int32_t get_real_eip(void); +void diverged(void); + +int32_t xchg8(int32_t, int32_t); +int32_t xchg16(int32_t, int32_t); +int32_t xchg16r(int32_t); +int32_t xchg32(int32_t, int32_t); +int32_t xchg32r(int32_t); + +int32_t loop(int32_t); +int32_t loope(int32_t); +int32_t loopne(int32_t); + +void bcd_aam(int32_t); +void task_switch_test(void); +void jcxz(int32_t); +void test_privileges_for_io(int32_t, int32_t); +int32_t io_port_read8(int32_t); +int32_t io_port_read16(int32_t); +int32_t io_port_read32(int32_t); +void jmp_rel16(int32_t); +void hlt_op(void); + +void io_port_write8(int32_t, int32_t); +void io_port_write16(int32_t, int32_t); +void io_port_write32(int32_t, int32_t); + +int32_t modrm_resolve(int32_t); + +static void run_instruction0f_16(int32_t); +static void run_instruction0f_32(int32_t); + +void clear_prefixes(void); +void cycle_internal(void); + + +void fwait(void); + + +static void instr_00() { read_modrm_byte(); write_e8(add8(read_write_e8(), read_g8())); } +static void instr16_01() { read_modrm_byte(); write_e16(add16(read_write_e16(), read_g16())); } +static void instr32_01() { read_modrm_byte(); write_e32(add32(read_write_e32(), read_g32s())); } +static void instr_02() { read_modrm_byte(); write_g8(add8(read_g8(), read_e8())); } +static void instr16_03() { read_modrm_byte(); write_g16(add16(read_g16(), read_e16())); } +static void instr32_03() { read_modrm_byte(); write_g32(add32(read_g32s(), read_e32s())); } +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 instr16_06() { push16(sreg[ES]); } +static void instr32_06() { push32(sreg[ES]); } +static void instr16_07() { + switch_seg(ES, safe_read16(get_stack_pointer(0))); + adjust_stack_reg(2); +} +static void instr32_07() { + switch_seg(ES, safe_read32s(get_stack_pointer(0)) & 0xFFFF); + adjust_stack_reg(4); +} + +static void instr_08() { read_modrm_byte(); write_e8(or8(read_write_e8(), read_g8())); } +static void instr16_09() { read_modrm_byte(); write_e16(or16(read_write_e16(), read_g16())); } +static void instr32_09() { read_modrm_byte(); write_e32(or32(read_write_e32(), read_g32s())); } +static void instr_0A() { read_modrm_byte(); write_g8(or8(read_g8(), read_e8())); } +static void instr16_0B() { read_modrm_byte(); write_g16(or16(read_g16(), read_e16())); } +static void instr32_0B() { read_modrm_byte(); write_g32(or32(read_g32s(), read_e32s())); } +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 instr16_0E() { push16(sreg[CS]); } +static void instr32_0E() { push32(sreg[CS]); } +static void instr16_0F() { + run_instruction0f_16(read_imm8()); +} +static void instr32_0F() { + run_instruction0f_32(read_imm8()); +} + +static void instr_10() { read_modrm_byte(); write_e8(adc8(read_write_e8(), read_g8())); } +static void instr16_11() { read_modrm_byte(); write_e16(adc16(read_write_e16(), read_g16())); } +static void instr32_11() { read_modrm_byte(); write_e32(adc32(read_write_e32(), read_g32s())); } +static void instr_12() { read_modrm_byte(); write_g8(adc8(read_g8(), read_e8())); } +static void instr16_13() { read_modrm_byte(); write_g16(adc16(read_g16(), read_e16())); } +static void instr32_13() { read_modrm_byte(); write_g32(adc32(read_g32s(), read_e32s())); } +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 instr16_16() { push16(sreg[SS]); } +static void instr32_16() { push32(sreg[SS]); } +static void instr16_17() { + switch_seg(SS, safe_read16(get_stack_pointer(0))); + adjust_stack_reg(2); + clear_prefixes(); + cycle_internal(); +} +static void instr32_17() { + switch_seg(SS, safe_read32s(get_stack_pointer(0)) & 0xFFFF); + adjust_stack_reg(4); + clear_prefixes(); + cycle_internal(); +} + +static void instr_18() { read_modrm_byte(); write_e8(sbb8(read_write_e8(), read_g8())); } +static void instr16_19() { read_modrm_byte(); write_e16(sbb16(read_write_e16(), read_g16())); } +static void instr32_19() { read_modrm_byte(); write_e32(sbb32(read_write_e32(), read_g32s())); } +static void instr_1A() { read_modrm_byte(); write_g8(sbb8(read_g8(), read_e8())); } +static void instr16_1B() { read_modrm_byte(); write_g16(sbb16(read_g16(), read_e16())); } +static void instr32_1B() { read_modrm_byte(); write_g32(sbb32(read_g32s(), read_e32s())); } +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 instr16_1E() { push16(sreg[DS]); } +static void instr32_1E() { push32(sreg[DS]); } +static void instr16_1F() { + switch_seg(DS, safe_read16(get_stack_pointer(0))); + adjust_stack_reg(2); +} +static void instr32_1F() { + switch_seg(DS, safe_read32s(get_stack_pointer(0)) & 0xFFFF); + adjust_stack_reg(4); +} + +static void instr_20() { read_modrm_byte(); write_e8(and8(read_write_e8(), read_g8())); } +static void instr16_21() { read_modrm_byte(); write_e16(and16(read_write_e16(), read_g16())); } +static void instr32_21() { read_modrm_byte(); write_e32(and32(read_write_e32(), read_g32s())); } +static void instr_22() { read_modrm_byte(); write_g8(and8(read_g8(), read_e8())); } +static void instr16_23() { read_modrm_byte(); write_g16(and16(read_g16(), read_e16())); } +static void instr32_23() { read_modrm_byte(); write_g32(and32(read_g32s(), read_e32s())); } +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_26() { segment_prefix_op(ES); } +static void instr_27() { bcd_daa(); } + +static void instr_28() { read_modrm_byte(); write_e8(sub8(read_write_e8(), read_g8())); } +static void instr16_29() { read_modrm_byte(); write_e16(sub16(read_write_e16(), read_g16())); } +static void instr32_29() { read_modrm_byte(); write_e32(sub32(read_write_e32(), read_g32s())); } +static void instr_2A() { read_modrm_byte(); write_g8(sub8(read_g8(), read_e8())); } +static void instr16_2B() { read_modrm_byte(); write_g16(sub16(read_g16(), read_e16())); } +static void instr32_2B() { read_modrm_byte(); write_g32(sub32(read_g32s(), read_e32s())); } +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_2E() { segment_prefix_op(CS); } +static void instr_2F() { bcd_das(); } + +static void instr_30() { read_modrm_byte(); write_e8(xor8(read_write_e8(), read_g8())); } +static void instr16_31() { read_modrm_byte(); write_e16(xor16(read_write_e16(), read_g16())); } +static void instr32_31() { read_modrm_byte(); write_e32(xor32(read_write_e32(), read_g32s())); } +static void instr_32() { read_modrm_byte(); write_g8(xor8(read_g8(), read_e8())); } +static void instr16_33() { read_modrm_byte(); write_g16(xor16(read_g16(), read_e16())); } +static void instr32_33() { read_modrm_byte(); write_g32(xor32(read_g32s(), read_e32s())); } +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_36() { segment_prefix_op(SS); } +static void instr_37() { bcd_aaa(); } + +static void instr_38() { read_modrm_byte(); cmp8(read_e8(), read_g8()); } +static void instr16_39() { read_modrm_byte(); cmp16(read_e16(), read_g16()); } +static void instr32_39() { read_modrm_byte(); cmp32(read_e32s(), read_g32s()); } +static void instr_3A() { read_modrm_byte(); cmp8(read_g8(), read_e8()); } +static void instr16_3B() { read_modrm_byte(); cmp16(read_g16(), read_e16()); } +static void instr32_3B() { read_modrm_byte(); cmp32(read_g32s(), read_e32s()); } +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_3E() { segment_prefix_op(DS); } +static void instr_3F() { bcd_aas(); } + + +static void instr16_40() { reg16[AX] = inc16(reg16[AX]); } +static void instr32_40() { reg32s[EAX] = inc32(reg32s[EAX]); } +static void instr16_41() { reg16[CX] = inc16(reg16[CX]); } +static void instr32_41() { reg32s[ECX] = inc32(reg32s[ECX]); } +static void instr16_42() { reg16[DX] = inc16(reg16[DX]); } +static void instr32_42() { reg32s[EDX] = inc32(reg32s[EDX]); } +static void instr16_43() { reg16[BX] = inc16(reg16[BX]); } +static void instr32_43() { reg32s[EBX] = inc32(reg32s[EBX]); } +static void instr16_44() { reg16[SP] = inc16(reg16[SP]); } +static void instr32_44() { reg32s[ESP] = inc32(reg32s[ESP]); } +static void instr16_45() { reg16[BP] = inc16(reg16[BP]); } +static void instr32_45() { reg32s[EBP] = inc32(reg32s[EBP]); } +static void instr16_46() { reg16[SI] = inc16(reg16[SI]); } +static void instr32_46() { reg32s[ESI] = inc32(reg32s[ESI]); } +static void instr16_47() { reg16[DI] = inc16(reg16[DI]); } +static void instr32_47() { reg32s[EDI] = inc32(reg32s[EDI]); } + + +static void instr16_48() { reg16[AX] = dec16(reg16[AX]); } +static void instr32_48() { reg32s[EAX] = dec32(reg32s[EAX]); } +static void instr16_49() { reg16[CX] = dec16(reg16[CX]); } +static void instr32_49() { reg32s[ECX] = dec32(reg32s[ECX]); } +static void instr16_4A() { reg16[DX] = dec16(reg16[DX]); } +static void instr32_4A() { reg32s[EDX] = dec32(reg32s[EDX]); } +static void instr16_4B() { reg16[BX] = dec16(reg16[BX]); } +static void instr32_4B() { reg32s[EBX] = dec32(reg32s[EBX]); } +static void instr16_4C() { reg16[SP] = dec16(reg16[SP]); } +static void instr32_4C() { reg32s[ESP] = dec32(reg32s[ESP]); } +static void instr16_4D() { reg16[BP] = dec16(reg16[BP]); } +static void instr32_4D() { reg32s[EBP] = dec32(reg32s[EBP]); } +static void instr16_4E() { reg16[SI] = dec16(reg16[SI]); } +static void instr32_4E() { reg32s[ESI] = dec32(reg32s[ESI]); } +static void instr16_4F() { reg16[DI] = dec16(reg16[DI]); } +static void instr32_4F() { reg32s[EDI] = dec32(reg32s[EDI]); } + + +static void instr16_50() { push16(reg16[AX]); } +static void instr32_50() { push32(reg32s[EAX]); } +static void instr16_51() { push16(reg16[CX]); } +static void instr32_51() { push32(reg32s[ECX]); } +static void instr16_52() { push16(reg16[DX]); } +static void instr32_52() { push32(reg32s[EDX]); } +static void instr16_53() { push16(reg16[BX]); } +static void instr32_53() { push32(reg32s[EBX]); } +static void instr16_54() { push16(reg16[SP]); } +static void instr32_54() { push32(reg32s[ESP]); } +static void instr16_55() { push16(reg16[BP]); } +static void instr32_55() { push32(reg32s[EBP]); } +static void instr16_56() { push16(reg16[SI]); } +static void instr32_56() { push32(reg32s[ESI]); } +static void instr16_57() { push16(reg16[DI]); } +static void instr32_57() { push32(reg32s[EDI]); } + +static void instr16_58() { reg16[AX] = pop16(); } +static void instr32_58() { reg32s[EAX] = pop32s(); } +static void instr16_59() { reg16[CX] = pop16(); } +static void instr32_59() { reg32s[ECX] = pop32s(); } +static void instr16_5A() { reg16[DX] = pop16(); } +static void instr32_5A() { reg32s[EDX] = pop32s(); } +static void instr16_5B() { reg16[BX] = pop16(); } +static void instr32_5B() { reg32s[EBX] = pop32s(); } +static void instr16_5C() { reg16[SP] = pop16(); } +static void instr32_5C() { reg32s[ESP] = pop32s(); } +static void instr16_5D() { reg16[BP] = pop16(); } +static void instr32_5D() { reg32s[EBP] = pop32s(); } +static void instr16_5E() { reg16[SI] = pop16(); } +static void instr32_5E() { reg32s[ESI] = pop32s(); } +static void instr16_5F() { reg16[DI] = pop16(); } +static void instr32_5F() { reg32s[EDI] = pop32s(); } + + +static void instr16_60() { pusha16(); } +static void instr32_60() { pusha32(); } +static void instr16_61() { popa16(); } +static void instr32_61() { popa32(); } + +static void instr_62() { + // bound + dbg_log("Unimplemented BOUND instruction"); + dbg_assert(false); +} +static void instr_63() { read_modrm_byte(); + // arpl + //dbg_log("arpl"); + if(*protected_mode && !vm86_mode()) + { + write_e16(arpl(read_write_e16(), modrm_byte[0] >> 2 & 14)); + } + else + { + dbg_log("arpl #ud"); + trigger_ud(); + } +} + +static void instr_64() { segment_prefix_op(FS); } +static void instr_65() { segment_prefix_op(GS); } + +static void instr_66() { + // Operand-size override prefix + *prefixes |= PREFIX_MASK_OPSIZE; + run_prefix_instruction(); + *prefixes = 0; +} + +static void instr_67() { + // Address-size override prefix + dbg_assert(is_asize_32() == *is_32); + + *prefixes |= PREFIX_MASK_ADDRSIZE; + run_prefix_instruction(); + *prefixes = 0; +} + +static void instr16_68() { push16(read_op16()); } +static void instr32_68() { push32(read_op32s()); } + +static void instr16_69() { read_modrm_byte(); + write_g16(imul_reg16(read_e16s(), read_op16() << 16 >> 16)); +} +static void instr32_69() { read_modrm_byte(); + write_g32(imul_reg32(read_e32s(), read_op32s())); +} + +static void instr16_6A() { push16(read_op8s()); } +static void instr32_6A() { push32(read_op8s()); } + +static void instr16_6B() { read_modrm_byte(); + write_g16(imul_reg16(read_e16s(), read_op8s())); +} +static void instr32_6B() { read_modrm_byte(); + write_g32(imul_reg32(read_e32s(), read_op8s())); +} + +static void instr_6C() { insb(); } +static void instr16_6D() { insw(); } +static void instr32_6D() { insd(); } +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_80() { read_modrm_byte(); + switch(modrm_byte[0] >> 3 & 7) + { + case 0: write_e8(add8(read_write_e8(), read_op8())); break; + case 1: write_e8( or8(read_write_e8(), read_op8())); break; + case 2: write_e8(adc8(read_write_e8(), read_op8())); break; + case 3: write_e8(sbb8(read_write_e8(), read_op8())); break; + case 4: write_e8(and8(read_write_e8(), read_op8())); break; + case 5: write_e8(sub8(read_write_e8(), read_op8())); break; + case 6: write_e8(xor8(read_write_e8(), read_op8())); break; + case 7: cmp8(read_e8(), read_op8()); break; + } +} +static void instr16_81() { read_modrm_byte(); + switch(modrm_byte[0] >> 3 & 7) + { + case 0: write_e16(add16(read_write_e16(), read_op16())); break; + case 1: write_e16( or16(read_write_e16(), read_op16())); break; + case 2: write_e16(adc16(read_write_e16(), read_op16())); break; + case 3: write_e16(sbb16(read_write_e16(), read_op16())); break; + case 4: write_e16(and16(read_write_e16(), read_op16())); break; + case 5: write_e16(sub16(read_write_e16(), read_op16())); break; + case 6: write_e16(xor16(read_write_e16(), read_op16())); break; + case 7: cmp16(read_e16(), read_op16()); break; + } +} +static void instr32_81() { read_modrm_byte(); + switch(modrm_byte[0] >> 3 & 7) + { + case 0: write_e32(add32(read_write_e32(), read_op32s())); break; + case 1: write_e32( or32(read_write_e32(), read_op32s())); break; + case 2: write_e32(adc32(read_write_e32(), read_op32s())); break; + case 3: write_e32(sbb32(read_write_e32(), read_op32s())); break; + case 4: write_e32(and32(read_write_e32(), read_op32s())); break; + case 5: write_e32(sub32(read_write_e32(), read_op32s())); break; + case 6: write_e32(xor32(read_write_e32(), read_op32s())); break; + case 7: cmp32(read_e32s(), read_op32s()); break; + } +} +static void instr_82() { instr_80(); } // alias +static void instr16_83() { read_modrm_byte(); + switch(modrm_byte[0] >> 3 & 7) + { + case 0: write_e16(add16(read_write_e16(), read_op8s())); break; + case 1: write_e16( or16(read_write_e16(), read_op8s())); break; + case 2: write_e16(adc16(read_write_e16(), read_op8s())); break; + case 3: write_e16(sbb16(read_write_e16(), read_op8s())); break; + case 4: write_e16(and16(read_write_e16(), read_op8s())); break; + case 5: write_e16(sub16(read_write_e16(), read_op8s())); break; + case 6: write_e16(xor16(read_write_e16(), read_op8s())); break; + case 7: cmp16(read_e16(), read_op8s()); break; + } +} +static void instr32_83() { read_modrm_byte(); + switch(modrm_byte[0] >> 3 & 7) + { + case 0: write_e32(add32(read_write_e32(), read_op8s())); break; + case 1: write_e32( or32(read_write_e32(), read_op8s())); break; + case 2: write_e32(adc32(read_write_e32(), read_op8s())); break; + case 3: write_e32(sbb32(read_write_e32(), read_op8s())); break; + case 4: write_e32(and32(read_write_e32(), read_op8s())); break; + case 5: write_e32(sub32(read_write_e32(), read_op8s())); break; + case 6: write_e32(xor32(read_write_e32(), read_op8s())); break; + case 7: cmp32(read_e32s(), read_op8s()); break; + } +} + +static void instr_84() { read_modrm_byte(); int32_t data = read_e8(); test8(data, read_g8()); } +static void instr16_85() { read_modrm_byte(); int32_t data = read_e16(); test16(data, read_g16()); } +static void instr32_85() { read_modrm_byte(); int32_t data = read_e32s(); test32(data, read_g32s()); } + + +static void instr_86() { read_modrm_byte(); int32_t data = read_write_e8(); write_e8(xchg8(data, modrm_byte[0])); } +static void instr16_87() { read_modrm_byte(); + int32_t data = read_write_e16(); write_e16(xchg16(data, modrm_byte[0])); +} +static void instr32_87() { read_modrm_byte(); + int32_t data = read_write_e32(); write_e32(xchg32(data, modrm_byte[0])); +} + +static void instr_88() { read_modrm_byte(); set_e8(read_g8()); } +static void instr16_89() { read_modrm_byte(); set_e16(read_g16()); } +static void instr32_89() { read_modrm_byte(); set_e32(read_g32s()); } + +static void instr_8A() { read_modrm_byte(); + int32_t data = read_e8(); + write_g8(data); +} +static void instr16_8B() { read_modrm_byte(); + int32_t data = read_e16(); + write_g16(data); +} +static void instr32_8B() { read_modrm_byte(); + int32_t data = read_e32s(); + write_g32(data); +} + +static void instr16_8C() { read_modrm_byte(); + set_e16(sreg[modrm_byte[0] >> 3 & 7]); +} +static void instr32_8C() { read_modrm_byte(); + set_e32(sreg[modrm_byte[0] >> 3 & 7]); +} + +static void instr16_8D() { read_modrm_byte(); + // lea + if(modrm_byte[0] >= 0xC0) + { + dbg_log("lea #ud"); + trigger_ud(); + } + int32_t mod = modrm_byte[0] >> 3 & 7; + + // override prefix, so modrm_resolve does not return the segment part + *prefixes |= SEG_PREFIX_ZERO; + reg16[mod << 1] = modrm_resolve(modrm_byte[0]); + *prefixes = 0; +} +static void instr32_8D() { read_modrm_byte(); + if(modrm_byte[0] >= 0xC0) + { + dbg_log("lea #ud"); + trigger_ud(); + } + int32_t mod = modrm_byte[0] >> 3 & 7; + + *prefixes |= SEG_PREFIX_ZERO; + reg32s[mod] = modrm_resolve(modrm_byte[0]); + *prefixes = 0; +} + +static void instr_8E() { read_modrm_byte(); + int32_t mod = modrm_byte[0] >> 3 & 7; + int32_t data = read_e16(); + switch_seg(mod, data); + + if(mod == SS) + { + // run next instruction, so no interrupts are handled + clear_prefixes(); + cycle_internal(); + } +} + +static void instr16_8F() { read_modrm_byte(); + // pop + int32_t sp = safe_read16(get_stack_pointer(0)); + + adjust_stack_reg(2); + + if(modrm_byte[0] < 0xC0) { + int32_t addr = modrm_resolve(modrm_byte[0]); + adjust_stack_reg(-2); + safe_write16(addr, sp); + adjust_stack_reg(2); + } else { + write_reg_e16(sp); + } +} +static void instr32_8F() { read_modrm_byte(); + int32_t sp = safe_read32s(get_stack_pointer(0)); + + // change esp first, then resolve modrm address + adjust_stack_reg(4); + + if(modrm_byte[0] < 0xC0) { + int32_t addr = modrm_resolve(modrm_byte[0]); + + // Before attempting a write that might cause a page fault, + // we must set esp to the old value. Fuck Intel. + adjust_stack_reg(-4); + safe_write32(addr, sp); + adjust_stack_reg(4); + } else { + write_reg_e32(sp); + } +} + +static void instr_90() { } +static void instr16_91() { xchg16r(CX); } +static void instr32_91() { xchg32r(ECX); } +static void instr16_92() { xchg16r(DX); } +static void instr32_92() { xchg32r(EDX); } +static void instr16_93() { xchg16r(BX); } +static void instr32_93() { xchg32r(EBX); } +static void instr16_94() { xchg16r(SP); } +static void instr32_94() { xchg32r(ESP); } +static void instr16_95() { xchg16r(BP); } +static void instr32_95() { xchg32r(EBP); } +static void instr16_96() { xchg16r(SI); } +static void instr32_96() { xchg32r(ESI); } +static void instr16_97() { xchg16r(DI); } +static void instr32_97() { xchg32r(EDI); } + +static void instr16_98() { /* cbw */ reg16[AX] = reg8s[AL]; } +static void instr32_98() { /* cwde */ reg32s[EAX] = reg16s[AX]; } +static void instr16_99() { /* cwd */ reg16[DX] = reg16s[AX] >> 15; } +static void instr32_99() { /* cdq */ reg32s[EDX] = reg32s[EAX] >> 31; } + +static void instr16_9A() { + // callf + int32_t new_ip = read_op16(); + int32_t new_cs = read_disp16(); + + far_jump(new_ip, new_cs, true); + dbg_assert(is_asize_32() || get_real_eip() < 0x10000); + diverged(); +} +static void instr32_9A() { + int32_t new_ip = read_op32s(); + int32_t new_cs = read_disp16(); + + if(!*protected_mode || vm86_mode()) + { + if(new_ip & 0xFFFF0000) + { + assert(false); + //throw debug.unimpl("#GP handler"); + } + } + + far_jump(new_ip, new_cs, true); + dbg_assert(is_asize_32() || get_real_eip() < 0x10000); + diverged(); +} + +static void instr_9B() { + // fwait: check for pending fpu exceptions + if((cr[0] & (CR0_MP | CR0_TS)) == (CR0_MP | CR0_TS)) + { + // task switched and MP bit is set + trigger_nm(); + } + else + { + //if(fpu) + { + fwait(); + } + //else + //{ + // // EM bit isn't checked + // // If there's no FPU, do nothing + //} + } +} +static void instr16_9C() { + // pushf + if((flags[0] & FLAG_VM) && getiopl() < 3) + { + dbg_assert(*protected_mode); + dbg_log("pushf #gp"); + trigger_gp(0); + } + else + { + push16(get_eflags()); + } +} +static void instr32_9C() { + // pushf + if((flags[0] & FLAG_VM) && getiopl() < 3) + { + // trap to virtual 8086 monitor + dbg_assert(*protected_mode); + dbg_log("pushf #gp"); + trigger_gp(0); + } + else + { + // vm and rf flag are cleared in image stored on the stack + push32(get_eflags() & 0x00FCFFFF); + } +} +static void instr16_9D() { + // popf + if((flags[0] & FLAG_VM) && getiopl() < 3) + { + dbg_log("popf #gp"); + trigger_gp(0); + } + + update_eflags((flags[0] & ~0xFFFF) | pop16()); + + if(flags[0] & FLAG_TRAP) + { + // XXX: Problems with fdgame + //clear_prefixes(); + //cycle_internal(); + flags[0] &= ~FLAG_TRAP; + //instruction_pointer = previous_ip; + //raise_exception(1); + } + else + { + handle_irqs(); + } +} +static void instr32_9D() { + // popf + if((flags[0] & FLAG_VM) && getiopl() < 3) + { + dbg_log("popf #gp"); + trigger_gp(0); + } + + update_eflags(pop32s()); + handle_irqs(); +} +static void instr_9E() { + // sahf + flags[0] = (flags[0] & ~0xFF) | reg8[AH]; + flags[0] = (flags[0] & FLAGS_MASK) | FLAGS_DEFAULT; + flags_changed[0] = 0; +} +static void instr_9F() { + // lahf + reg8[AH] = get_eflags(); +} + +static void instr_A0() { + // mov + int32_t data = safe_read8(read_moffs()); + reg8[AL] = data; +} +static void instr16_A1() { + // mov + int32_t data = safe_read16(read_moffs()); + reg16[AX] = data; +} +static void instr32_A1() { + int32_t data = safe_read32s(read_moffs()); + reg32s[EAX] = data; +} +static void instr_A2() { + // mov + safe_write8(read_moffs(), reg8[AL]); +} +static void instr16_A3() { + // mov + safe_write16(read_moffs(), reg16[AX]); +} +static void instr32_A3() { + safe_write32(read_moffs(), reg32s[EAX]); +} + +static void instr_A4() { movsb(); } +static void instr16_A5() { movsw(); } +static void instr32_A5() { movsd(); } +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 instr16_A9() { + test16(reg16[AX], read_op16()); +} +static void instr32_A9() { + test32(reg32s[EAX], read_op32s()); +} + +static void instr_AA() { stosb(); } +static void instr16_AB() { stosw(); } +static void instr32_AB() { stosd(); } +static void instr_AC() { lodsb(); } +static void instr16_AD() { lodsw(); } +static void instr32_AD() { lodsd(); } +static void instr_AE() { scasb(); } +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 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 instr_C0() { read_modrm_byte(); + int32_t op1 = read_write_e8(); + int32_t op2 = read_op8() & 31; + int32_t result = 0; + switch(modrm_byte[0] >> 3 & 7) + { + case 0: result = rol8(op1, op2); break; + case 1: result = ror8(op1, op2); break; + case 2: result = rcl8(op1, op2); break; + case 3: result = rcr8(op1, op2); break; + case 4: result = shl8(op1, op2); break; + case 5: result = shr8(op1, op2); break; + case 6: result = shl8(op1, op2); break; + case 7: result = sar8(op1, op2); break; + } + write_e8(result); +} +static void instr16_C1() { read_modrm_byte(); + int32_t op1 = read_write_e16(); + int32_t op2 = read_op8() & 31; + int32_t result = 0; + switch(modrm_byte[0] >> 3 & 7) + { + case 0: result = rol16(op1, op2); break; + case 1: result = ror16(op1, op2); break; + case 2: result = rcl16(op1, op2); break; + case 3: result = rcr16(op1, op2); break; + case 4: result = shl16(op1, op2); break; + case 5: result = shr16(op1, op2); break; + case 6: result = shl16(op1, op2); break; + case 7: result = sar16(op1, op2); break; + } + write_e16(result); +} +static void instr32_C1() { read_modrm_byte(); + int32_t op1 = read_write_e32(); + int32_t op2 = read_op8() & 31; + int32_t result = 0; + switch(modrm_byte[0] >> 3 & 7) + { + case 0: result = rol32(op1, op2); break; + case 1: result = ror32(op1, op2); break; + case 2: result = rcl32(op1, op2); break; + case 3: result = rcr32(op1, op2); break; + case 4: result = shl32(op1, op2); break; + case 5: result = shr32(op1, op2); break; + case 6: result = shl32(op1, op2); break; + case 7: result = sar32(op1, op2); break; + } + write_e32(result); +} + +static void instr16_C2() { + // retn + int32_t imm16 = read_op16(); + + instruction_pointer[0] = get_seg(CS) + pop16(); + dbg_assert(is_asize_32() || get_real_eip() < 0x10000); + adjust_stack_reg(imm16); + diverged(); +} +static void instr32_C2() { + // retn + int32_t imm16 = read_op16(); + int32_t ip = pop32s(); + + dbg_assert(is_asize_32() || ip < 0x10000); + instruction_pointer[0] = get_seg(CS) + ip; + adjust_stack_reg(imm16); + diverged(); +} +static void instr16_C3() { + // retn + instruction_pointer[0] = get_seg(CS) + pop16(); + diverged(); +} +static void instr32_C3() { + // retn + int32_t ip = pop32s(); + dbg_assert(is_asize_32() || ip < 0x10000); + instruction_pointer[0] = get_seg(CS) + ip; + diverged(); +} + +static void instr16_C4() { read_modrm_byte(); + lss16(ES); +} +static void instr32_C4() { read_modrm_byte(); + lss32(ES); +} +static void instr16_C5() { read_modrm_byte(); + lss16(DS); +} +static void instr32_C5() { read_modrm_byte(); + lss32(DS); +} + +static void instr_C6() { read_modrm_byte(); + if(modrm_byte[0] < 0xC0) { + safe_write8(modrm_resolve(modrm_byte[0]), read_op8()); + } else { + reg8[modrm_byte[0] << 2 & 0xC | modrm_byte[0] >> 2 & 1] = read_op8(); + } +} +static void instr16_C7() { read_modrm_byte(); + if(modrm_byte[0] < 0xC0) { + safe_write16(modrm_resolve(modrm_byte[0]), read_op16()); + } else { + reg16[modrm_byte[0] << 1 & 14] = read_op16(); + } +} +static void instr32_C7() { read_modrm_byte(); + if(modrm_byte[0] < 0xC0) { + safe_write32(modrm_resolve(modrm_byte[0]), read_op32s()); + } else { + reg32s[modrm_byte[0] & 7] = read_op32s(); + } +} + +static void instr16_C8() { enter16(read_op16(), read_disp8()); } +static void instr32_C8() { enter32(read_op16(), read_disp8()); } +static void instr16_C9() { + // leave + int32_t old_vbp = *stack_size_32 ? reg32s[EBP] : reg16[BP]; + int32_t new_bp = safe_read16(get_seg(SS) + old_vbp); + set_stack_reg(old_vbp + 2); + reg16[BP] = new_bp; +} +static void instr32_C9() { + int32_t old_vbp = *stack_size_32 ? reg32s[EBP] : reg16[BP]; + int32_t new_ebp = safe_read32s(get_seg(SS) + old_vbp); + set_stack_reg(old_vbp + 4); + reg32s[EBP] = new_ebp; +} +static void instr16_CA() { + // 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() { + // 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; + + far_return(ip, cs, imm16); + dbg_assert(is_asize_32() || get_real_eip() < 0x10000); + diverged(); +} +static void instr16_CB() { + // retf + int32_t ip = safe_read16(get_stack_pointer(0)); + int32_t cs = safe_read16(get_stack_pointer(2)); + + far_return(ip, cs, 0); + dbg_assert(is_asize_32() || get_real_eip() < 0x10000); + diverged(); +} +static void instr32_CB() { + // retf + int32_t ip = safe_read32s(get_stack_pointer(0)); + int32_t cs = safe_read32s(get_stack_pointer(4)) & 0xFFFF; + + far_return(ip, cs, 0); + dbg_assert(is_asize_32() || get_real_eip() < 0x10000); + diverged(); +} + +static void instr_CC() { + // INT3 + // TODO: inhibit iopl checks + dbg_log("INT3"); + call_interrupt_vector(3, true, false, 0); + diverged(); +} +static void instr_CD() { + // INT + int32_t imm8 = read_op8(); + call_interrupt_vector(imm8, true, false, 0); + diverged(); +} +static void instr_CE() { + // INTO + dbg_log("INTO"); + if(getof()) + { + // TODO: inhibit iopl checks + call_interrupt_vector(4, true, false, 0); + } + diverged(); +} + +static void instr16_CF() { + // iret + iret16(); + diverged(); +} +static void instr32_CF() { + iret32(); + diverged(); +} + +static void instr_D0() { read_modrm_byte(); + int32_t op1 = read_write_e8(); + int32_t result = 0; + switch(modrm_byte[0] >> 3 & 7) + { + case 0: result = rol8(op1, 1); break; + case 1: result = ror8(op1, 1); break; + case 2: result = rcl8(op1, 1); break; + case 3: result = rcr8(op1, 1); break; + case 4: result = shl8(op1, 1); break; + case 5: result = shr8(op1, 1); break; + case 6: result = shl8(op1, 1); break; + case 7: result = sar8(op1, 1); break; + } + write_e8(result); +} +static void instr16_D1() { read_modrm_byte(); + int32_t op1 = read_write_e16(); + int32_t result = 0; + switch(modrm_byte[0] >> 3 & 7) + { + case 0: result = rol16(op1, 1); break; + case 1: result = ror16(op1, 1); break; + case 2: result = rcl16(op1, 1); break; + case 3: result = rcr16(op1, 1); break; + case 4: result = shl16(op1, 1); break; + case 5: result = shr16(op1, 1); break; + case 6: result = shl16(op1, 1); break; + case 7: result = sar16(op1, 1); break; + } + write_e16(result); +} +static void instr32_D1() { read_modrm_byte(); + int32_t op1 = read_write_e32(); + int32_t result = 0; + switch(modrm_byte[0] >> 3 & 7) + { + case 0: result = rol32(op1, 1); break; + case 1: result = ror32(op1, 1); break; + case 2: result = rcl32(op1, 1); break; + case 3: result = rcr32(op1, 1); break; + case 4: result = shl32(op1, 1); break; + case 5: result = shr32(op1, 1); break; + case 6: result = shl32(op1, 1); break; + case 7: result = sar32(op1, 1); break; + } + write_e32(result); +} + +static void instr_D2() { read_modrm_byte(); + int32_t op1 = read_write_e8(); + int32_t op2 = reg8[CL] & 31; + int32_t result = 0; + switch(modrm_byte[0] >> 3 & 7) + { + case 0: result = rol8(op1, op2); break; + case 1: result = ror8(op1, op2); break; + case 2: result = rcl8(op1, op2); break; + case 3: result = rcr8(op1, op2); break; + case 4: result = shl8(op1, op2); break; + case 5: result = shr8(op1, op2); break; + case 6: result = shl8(op1, op2); break; + case 7: result = sar8(op1, op2); break; + } + write_e8(result); +} +static void instr16_D3() { read_modrm_byte(); + int32_t op1 = read_write_e16(); + int32_t op2 = reg8[CL] & 31; + int32_t result = 0; + switch(modrm_byte[0] >> 3 & 7) + { + case 0: result = rol16(op1, op2); break; + case 1: result = ror16(op1, op2); break; + case 2: result = rcl16(op1, op2); break; + case 3: result = rcr16(op1, op2); break; + case 4: result = shl16(op1, op2); break; + case 5: result = shr16(op1, op2); break; + case 6: result = shl16(op1, op2); break; + case 7: result = sar16(op1, op2); break; + } + write_e16(result); +} +static void instr32_D3() { read_modrm_byte(); + int32_t op1 = read_write_e32(); + int32_t op2 = reg8[CL] & 31; + int32_t result = 0; + switch(modrm_byte[0] >> 3 & 7) + { + case 0: result = rol32(op1, op2); break; + case 1: result = ror32(op1, op2); break; + case 2: result = rcl32(op1, op2); break; + case 3: result = rcr32(op1, op2); break; + case 4: result = shl32(op1, op2); break; + case 5: result = shr32(op1, op2); break; + case 6: result = shl32(op1, op2); break; + case 7: result = sar32(op1, op2); break; + } + write_e32(result); +} + +static void instr_D4() { + bcd_aam(read_op8()); +} +static void instr_D5() { + bcd_aad(read_op8()); +} + +static void instr_D6() { + // salc + reg8[AL] = -getcf(); +} +static void instr_D7() { + // xlat + if(is_asize_32()) + { + reg8[AL] = safe_read8(get_seg_prefix(DS) + reg32s[EBX] + reg8[AL]); + } + else + { + reg8[AL] = safe_read8(get_seg_prefix(DS) + (reg16[BX] + reg8[AL] & 0xFFFF)); + } +} + +static void instr_D8() { read_modrm_byte(); + task_switch_test(); + if(modrm_byte[0] < 0xC0) + fpu_op_D8_mem(modrm_byte[0], modrm_resolve(modrm_byte[0])); + else + fpu_op_D8_reg(modrm_byte[0]); +} +static void instr_D9() { read_modrm_byte(); + task_switch_test(); + if(modrm_byte[0] < 0xC0) + fpu_op_D9_mem(modrm_byte[0], modrm_resolve(modrm_byte[0])); + else + fpu_op_D9_reg(modrm_byte[0]); +} +static void instr_DA() { read_modrm_byte(); + task_switch_test(); + if(modrm_byte[0] < 0xC0) + fpu_op_DA_mem(modrm_byte[0], modrm_resolve(modrm_byte[0])); + else + fpu_op_DA_reg(modrm_byte[0]); +} +static void instr_DB() { read_modrm_byte(); + task_switch_test(); + if(modrm_byte[0] < 0xC0) + fpu_op_DB_mem(modrm_byte[0], modrm_resolve(modrm_byte[0])); + else + fpu_op_DB_reg(modrm_byte[0]); +} +static void instr_DC() { read_modrm_byte(); + task_switch_test(); + if(modrm_byte[0] < 0xC0) + fpu_op_DC_mem(modrm_byte[0], modrm_resolve(modrm_byte[0])); + else + fpu_op_DC_reg(modrm_byte[0]); +} +static void instr_DD() { read_modrm_byte(); + task_switch_test(); + if(modrm_byte[0] < 0xC0) + fpu_op_DD_mem(modrm_byte[0], modrm_resolve(modrm_byte[0])); + else + fpu_op_DD_reg(modrm_byte[0]); +} +static void instr_DE() { read_modrm_byte(); + task_switch_test(); + if(modrm_byte[0] < 0xC0) + fpu_op_DE_mem(modrm_byte[0], modrm_resolve(modrm_byte[0])); + else + fpu_op_DE_reg(modrm_byte[0]); +} +static void instr_DF() { read_modrm_byte(); + task_switch_test(); + if(modrm_byte[0] < 0xC0) + fpu_op_DF_mem(modrm_byte[0], modrm_resolve(modrm_byte[0])); + else + fpu_op_DF_reg(modrm_byte[0]); +} + +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_E4() { + int32_t port = read_op8(); + test_privileges_for_io(port, 1); + reg8[AL] = io_port_read8(port); + diverged(); +} +static void instr16_E5() { + int32_t port = read_op8(); + test_privileges_for_io(port, 2); + reg16[AX] = io_port_read16(port); + diverged(); +} +static void instr32_E5() { + int32_t port = read_op8(); + test_privileges_for_io(port, 4); + reg32s[EAX] = io_port_read32(port); + diverged(); +} +static void instr_E6() { + int32_t port = read_op8(); + test_privileges_for_io(port, 1); + io_port_write8(port, reg8[AL]); + diverged(); +} +static void instr16_E7() { + int32_t port = read_op8(); + test_privileges_for_io(port, 2); + io_port_write16(port, reg16[AX]); + diverged(); +} +static void instr32_E7() { + int32_t port = read_op8(); + test_privileges_for_io(port, 4); + io_port_write32(port, reg32s[EAX]); + diverged(); +} + +static void instr16_E8() { + // call + int32_t imm16 = read_op16(); + push16(get_real_eip()); + + jmp_rel16(imm16); + diverged(); +} +static void instr32_E8() { + // 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() { + // jmp + int32_t imm16 = read_op16(); + jmp_rel16(imm16); + diverged(); +} +static void instr32_E9() { + // jmp + int32_t imm32s = read_op32s(); + instruction_pointer[0] = instruction_pointer[0] + imm32s; + dbg_assert(is_asize_32() || get_real_eip() < 0x10000); + diverged(); +} +static void instr16_EA() { + // jmpf + int32_t ip = read_op16(); + int32_t cs = read_disp16(); + far_jump(ip, cs, false); + dbg_assert(is_asize_32() || get_real_eip() < 0x10000); + diverged(); +} +static void instr32_EA() { + // jmpf + int32_t new_ip = read_op32s(); + int32_t cs = read_disp16(); + far_jump(new_ip, cs, false); + dbg_assert(is_asize_32() || get_real_eip() < 0x10000); + diverged(); +} +static void instr_EB() { + // jmp near + int32_t imm8 = read_op8s(); + instruction_pointer[0] = instruction_pointer[0] + imm8; + dbg_assert(is_asize_32() || get_real_eip() < 0x10000); + diverged(); +} + +static void instr_EC() { + int32_t port = reg16[DX]; + test_privileges_for_io(port, 1); + reg8[AL] = io_port_read8(port); + diverged(); +} +static void instr16_ED() { + int32_t port = reg16[DX]; + test_privileges_for_io(port, 2); + reg16[AX] = io_port_read16(port); + diverged(); +} +static void instr32_ED() { + int32_t port = reg16[DX]; + test_privileges_for_io(port, 4); + reg32s[EAX] = io_port_read32(port); + diverged(); +} +static void instr_EE() { + int32_t port = reg16[DX]; + test_privileges_for_io(port, 1); + io_port_write8(port, reg8[AL]); + diverged(); +} +static void instr16_EF() { + int32_t port = reg16[DX]; + test_privileges_for_io(port, 2); + io_port_write16(port, reg16[AX]); + diverged(); +} +static void instr32_EF() { + int32_t port = reg16[DX]; + test_privileges_for_io(port, 4); + io_port_write32(port, reg32s[EAX]); + diverged(); +} + +static void instr_F0() { + // lock + //dbg_log("lock"); + + // TODO + // This triggers UD when used with + // some instructions that don't write to memory + run_prefix_instruction(); +} +static void instr_F1() { + // INT1 + // https://code.google.com/p/corkami/wiki/x86oddities#IceBP + //throw debug.unimpl("int1 instruction"); + assert(false); +} + +static void instr_F2() { + // repnz + dbg_assert((*prefixes & PREFIX_MASK_REP) == 0); + *prefixes |= PREFIX_REPNZ; + run_prefix_instruction(); + *prefixes = 0; +} +static void instr_F3() { + // repz + dbg_assert((*prefixes & PREFIX_MASK_REP) == 0); + *prefixes |= PREFIX_REPZ; + run_prefix_instruction(); + *prefixes = 0; +} + +static void instr_F4() { + hlt_op(); +} + +static void instr_F5() { + // cmc + flags[0] = (flags[0] | 1) ^ getcf(); + flags_changed[0] &= ~1; +} + +static void instr_F6() { read_modrm_byte(); + switch(modrm_byte[0] >> 3 & 7) + { + case 0: + test8(read_e8(), read_op8()); + break; + case 1: + test8(read_e8(), read_op8()); + break; + case 2: + write_e8(~(read_write_e8())); + break; + case 3: + write_e8(neg8(read_write_e8())); + break; + case 4: + mul8(read_e8()); + break; + case 5: + imul8(read_e8s()); + break; + case 6: + div8(read_e8()); + break; + case 7: + idiv8(read_e8s()); + break; + } +} + +static void instr16_F7() { read_modrm_byte(); + switch(modrm_byte[0] >> 3 & 7) + { + case 0: + test16(read_e16(), read_op16()); + break; + case 1: + test16(read_e16(), read_op16()); + break; + case 2: + write_e16(~(read_write_e16())); + break; + case 3: + write_e16(neg16(read_write_e16())); + break; + case 4: + mul16(read_e16()); + break; + case 5: + imul16(read_e16s()); + break; + case 6: + div16(read_e16()); + break; + case 7: + idiv16(read_e16s()); + break; + } +} +static void instr32_F7() { read_modrm_byte(); + switch(modrm_byte[0] >> 3 & 7) + { + case 0: + test32(read_e32s(), read_op32s()); + break; + case 1: + test32(read_e32s(), read_op32s()); + break; + case 2: + write_e32(~(read_write_e32())); + break; + case 3: + write_e32(neg32(read_write_e32())); + break; + case 4: + mul32(read_e32s()); + break; + case 5: + imul32(read_e32s()); + break; + case 6: + div32(read_e32s()); + break; + case 7: + idiv32(read_e32s()); + break; + } +} + +static void instr_F8() { + // clc + flags[0] &= ~FLAG_CARRY; + flags_changed[0] &= ~1; +} +static void instr_F9() { + // stc + flags[0] |= FLAG_CARRY; + flags_changed[0] &= ~1; +} + +static void instr_FA() { + // cli + //dbg_log("interrupts off"); + + if(!*protected_mode || ((flags[0] & FLAG_VM) ? + getiopl() == 3 : getiopl() >= *cpl)) + { + flags[0] &= ~FLAG_INTERRUPT; + } + else + { + //if(getiopl() < 3 && ((flags & FLAG_VM) ? + // (cr[4] & CR4_VME) : + // (*cpl == 3 && (cr[4] & CR4_PVI)))) + //{ + // flags &= ~flag_vif; + //} + //else + { + dbg_log("cli #gp"); + trigger_gp(0); + } + } +} +static void instr_FB() { + // sti + //dbg_log("interrupts on"); + + if(!*protected_mode || ((flags[0] & FLAG_VM) ? + getiopl() == 3 : getiopl() >= *cpl)) + { + flags[0] |= FLAG_INTERRUPT; + + clear_prefixes(); + cycle_internal(); + + handle_irqs(); + } + else + { + //if(getiopl() < 3 && (flags & flag_vip) == 0 && ((flags & FLAG_VM) ? + // (cr[4] & CR4_VME) : + // (cpl == 3 && (cr[4] & CR4_PVI)))) + //{ + // flags |= flag_vif; + //} + //else + { + dbg_log("sti #gp"); + trigger_gp(0); + } + } + +} + +static void instr_FC() { + // cld + flags[0] &= ~FLAG_DIRECTION; +} +static void instr_FD() { + // std + flags[0] |= FLAG_DIRECTION; +} + +static void instr_FE() { read_modrm_byte(); + int32_t mod = modrm_byte[0] & 56; + + if(mod == 0) + { + int32_t data = read_write_e8(); write_e8(inc8(data)); + } + else if(mod == 8) + { + int32_t data = read_write_e8(); write_e8(dec8(data)); + } + else + { + assert(false); + } +} +static void instr16_FF() { read_modrm_byte(); + switch(modrm_byte[0] >> 3 & 7) + { + case 0: + write_e16(inc16(read_write_e16())); + break; + case 1: + write_e16(dec16(read_write_e16())); + break; + case 2: + // 2, call near + { + int32_t data = read_e16(); + push16(get_real_eip()); + instruction_pointer[0] = get_seg(CS) + data; + dbg_assert(is_asize_32() || get_real_eip() < 0x10000); + diverged(); + } + break; + case 3: + // 3, callf + { + if(modrm_byte[0] >= 0xC0) + { + dbg_log("callf #ud"); + trigger_ud(); + dbg_assert_message(false, "unreachable"); + } + + int32_t virt_addr = modrm_resolve(modrm_byte[0]); + int32_t new_ip = safe_read16(virt_addr); + int32_t new_cs = safe_read16(virt_addr + 2); + + far_jump(new_ip, new_cs, true); + dbg_assert(is_asize_32() || get_real_eip() < 0x10000); + diverged(); + } + break; + case 4: + // 4, jmp near + { + int32_t data = read_e16(); + instruction_pointer[0] = get_seg(CS) + data; + dbg_assert(is_asize_32() || get_real_eip() < 0x10000); + diverged(); + } + break; + case 5: + // 5, jmpf + { + if(modrm_byte[0] >= 0xC0) + { + dbg_log("jmpf #ud"); + trigger_ud(); + dbg_assert_message(false, "unreachable"); + } + + int32_t virt_addr = modrm_resolve(modrm_byte[0]); + int32_t new_ip = safe_read16(virt_addr); + int32_t new_cs = safe_read16(virt_addr + 2); + + far_jump(new_ip, new_cs, false); + dbg_assert(is_asize_32() || get_real_eip() < 0x10000); + diverged(); + } + break; + case 6: + // 6, push + push16(read_e16()); + break; + case 7: + assert(false); + } +} +static void instr32_FF() { read_modrm_byte(); + switch(modrm_byte[0] >> 3 & 7) + { + case 0: + write_e32(inc32(read_write_e32())); + break; + case 1: + write_e32(dec32(read_write_e32())); + break; + case 2: + // 2, call near + { + int32_t data = read_e32s(); + push32(get_real_eip()); + + dbg_assert(is_asize_32() || data < 0x10000); + instruction_pointer[0] = get_seg(CS) + data; + diverged(); + } + break; + case 3: + // 3, callf + { + if(modrm_byte[0] >= 0xC0) + { + dbg_log("callf #ud"); + trigger_ud(); + dbg_assert_message(false, "unreachable"); + } + + int32_t virt_addr = modrm_resolve(modrm_byte[0]); + int32_t new_ip = safe_read32s(virt_addr); + int32_t new_cs = safe_read16(virt_addr + 4); + + if(!*protected_mode || vm86_mode()) + { + if(new_ip & 0xFFFF0000) + { + //throw debug.unimpl("#GP handler"); + assert(false); + } + } + + far_jump(new_ip, new_cs, true); + dbg_assert(is_asize_32() || new_ip < 0x10000); + diverged(); + } + break; + case 4: + // 4, jmp near + { + int32_t data = read_e32s(); + dbg_assert(is_asize_32() || data < 0x10000); + instruction_pointer[0] = get_seg(CS) + data; + diverged(); + } + break; + case 5: + // 5, jmpf + { + if(modrm_byte[0] >= 0xC0) + { + dbg_log("jmpf #ud"); + trigger_ud(); + dbg_assert_message(false, "unreachable"); + } + + int32_t virt_addr = modrm_resolve(modrm_byte[0]); + int32_t new_ip = safe_read32s(virt_addr); + int32_t new_cs = safe_read16(virt_addr + 4); + + if(!*protected_mode || vm86_mode()) + { + if(new_ip & 0xFFFF0000) + { + //throw debug.unimpl("#GP handler"); + assert(false); + } + } + + far_jump(new_ip, new_cs, false); + dbg_assert(is_asize_32() || new_ip < 0x10000); + diverged(); + } + break; + case 6: + // push + push32(read_e32s()); + break; + case 7: + assert(false); + } +} + +static void run_instruction(int32_t opcode) +{ + //dbg_log(opcode); + // XXX: This table is generated. Don't modify + switch(opcode | is_osize_32() << 8) + { +case 0x00: +case 0x00|0x100: + instr_00(); + break; +case 0x01: + instr16_01(); + break; +case 0x01|0x100: + instr32_01(); + break; +case 0x02: +case 0x02|0x100: + instr_02(); + break; +case 0x03: + instr16_03(); + break; +case 0x03|0x100: + instr32_03(); + 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: + instr_08(); + break; +case 0x09: + instr16_09(); + break; +case 0x09|0x100: + instr32_09(); + break; +case 0x0A: +case 0x0A|0x100: + instr_0A(); + break; +case 0x0B: + instr16_0B(); + break; +case 0x0B|0x100: + instr32_0B(); + 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: + instr_10(); + break; +case 0x11: + instr16_11(); + break; +case 0x11|0x100: + instr32_11(); + break; +case 0x12: +case 0x12|0x100: + instr_12(); + break; +case 0x13: + instr16_13(); + break; +case 0x13|0x100: + instr32_13(); + 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: + instr_18(); + break; +case 0x19: + instr16_19(); + break; +case 0x19|0x100: + instr32_19(); + break; +case 0x1A: +case 0x1A|0x100: + instr_1A(); + break; +case 0x1B: + instr16_1B(); + break; +case 0x1B|0x100: + instr32_1B(); + 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: + instr_20(); + break; +case 0x21: + instr16_21(); + break; +case 0x21|0x100: + instr32_21(); + break; +case 0x22: +case 0x22|0x100: + instr_22(); + break; +case 0x23: + instr16_23(); + break; +case 0x23|0x100: + instr32_23(); + 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: + instr_28(); + break; +case 0x29: + instr16_29(); + break; +case 0x29|0x100: + instr32_29(); + break; +case 0x2A: +case 0x2A|0x100: + instr_2A(); + break; +case 0x2B: + instr16_2B(); + break; +case 0x2B|0x100: + instr32_2B(); + 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: + instr_30(); + break; +case 0x31: + instr16_31(); + break; +case 0x31|0x100: + instr32_31(); + break; +case 0x32: +case 0x32|0x100: + instr_32(); + break; +case 0x33: + instr16_33(); + break; +case 0x33|0x100: + instr32_33(); + 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: + instr_38(); + break; +case 0x39: + instr16_39(); + break; +case 0x39|0x100: + instr32_39(); + break; +case 0x3A: +case 0x3A|0x100: + instr_3A(); + break; +case 0x3B: + instr16_3B(); + break; +case 0x3B|0x100: + instr32_3B(); + 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: + instr_62(); + break; +case 0x63: +case 0x63|0x100: + instr_63(); + 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: + instr16_69(); + break; +case 0x69|0x100: + instr32_69(); + break; +case 0x6A: + instr16_6A(); + break; +case 0x6A|0x100: + instr32_6A(); + break; +case 0x6B: + instr16_6B(); + break; +case 0x6B|0x100: + instr32_6B(); + 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: + instr_80(); + break; +case 0x81: + instr16_81(); + break; +case 0x81|0x100: + instr32_81(); + break; +case 0x82: +case 0x82|0x100: + instr_82(); + break; +case 0x83: + instr16_83(); + break; +case 0x83|0x100: + instr32_83(); + break; +case 0x84: +case 0x84|0x100: + instr_84(); + break; +case 0x85: + instr16_85(); + break; +case 0x85|0x100: + instr32_85(); + break; +case 0x86: +case 0x86|0x100: + instr_86(); + break; +case 0x87: + instr16_87(); + break; +case 0x87|0x100: + instr32_87(); + break; +case 0x88: +case 0x88|0x100: + instr_88(); + break; +case 0x89: + instr16_89(); + break; +case 0x89|0x100: + instr32_89(); + break; +case 0x8A: +case 0x8A|0x100: + instr_8A(); + break; +case 0x8B: + instr16_8B(); + break; +case 0x8B|0x100: + instr32_8B(); + break; +case 0x8C: + instr16_8C(); + break; +case 0x8C|0x100: + instr32_8C(); + break; +case 0x8D: + instr16_8D(); + break; +case 0x8D|0x100: + instr32_8D(); + break; +case 0x8E: +case 0x8E|0x100: + instr_8E(); + break; +case 0x8F: + instr16_8F(); + break; +case 0x8F|0x100: + instr32_8F(); + 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(); + break; +case 0x9A|0x100: + instr32_9A(); + 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: + instr_C0(); + break; +case 0xC1: + instr16_C1(); + break; +case 0xC1|0x100: + instr32_C1(); + 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: + instr16_C4(); + break; +case 0xC4|0x100: + instr32_C4(); + break; +case 0xC5: + instr16_C5(); + break; +case 0xC5|0x100: + instr32_C5(); + break; +case 0xC6: +case 0xC6|0x100: + instr_C6(); + break; +case 0xC7: + instr16_C7(); + break; +case 0xC7|0x100: + instr32_C7(); + break; +case 0xC8: + instr16_C8(); + break; +case 0xC8|0x100: + instr32_C8(); + 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: + instr_D0(); + break; +case 0xD1: + instr16_D1(); + break; +case 0xD1|0x100: + instr32_D1(); + break; +case 0xD2: +case 0xD2|0x100: + instr_D2(); + break; +case 0xD3: + instr16_D3(); + break; +case 0xD3|0x100: + instr32_D3(); + 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: + instr_D8(); + break; +case 0xD9: +case 0xD9|0x100: + instr_D9(); + break; +case 0xDA: +case 0xDA|0x100: + instr_DA(); + break; +case 0xDB: +case 0xDB|0x100: + instr_DB(); + break; +case 0xDC: +case 0xDC|0x100: + instr_DC(); + break; +case 0xDD: +case 0xDD|0x100: + instr_DD(); + break; +case 0xDE: +case 0xDE|0x100: + instr_DE(); + break; +case 0xDF: +case 0xDF|0x100: + instr_DF(); + 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(); + break; +case 0xEA|0x100: + instr32_EA(); + 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: + instr_F6(); + break; +case 0xF7: + instr16_F7(); + break; +case 0xF7|0x100: + instr32_F7(); + 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: + instr_FE(); + break; +case 0xFF: + instr16_FF(); + break; +case 0xFF|0x100: + instr32_FF(); + break; +default: + assert(false); + } +} diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c new file mode 100644 index 00000000..ceb70a3a --- /dev/null +++ b/src/native/instructions_0f.c @@ -0,0 +1,3155 @@ +#include +#include +#include +#include + +#include "const.h" +#include "global_pointers.h" + +// XXX: Remove these declarations when they are implemented in C +void cmovcc16(bool); +void cmovcc32(bool); +void jmpcc16(bool); +void jmpcc32(bool); +void setcc(bool); +void cpuid(); + +int32_t bt_mem(int32_t, int32_t); +int32_t bt_reg(int32_t, int32_t); +int32_t bts_mem(int32_t, int32_t); +int32_t bts_reg(int32_t, int32_t); +int32_t btc_mem(int32_t, int32_t); +int32_t btc_reg(int32_t, int32_t); +int32_t btr_mem(int32_t, int32_t); +int32_t btr_reg(int32_t, int32_t); +int32_t bsf16(int32_t, int32_t); +int32_t bsf32(int32_t, int32_t); +int32_t bsr16(int32_t, int32_t); +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); + +int32_t shld16(int32_t, int32_t, int32_t); +int32_t shld32(int32_t, int32_t, int32_t); +int32_t shrd16(int32_t, int32_t, int32_t); +int32_t shrd32(int32_t, int32_t, int32_t); + +bool has_rand_int(void); +int32_t get_rand_int(void); + +void todo(); +void undefined_instruction(); + +void clear_tlb(); +void full_clear_tlb(); + +int32_t microtick(); + +int32_t lsl(int32_t, int32_t); +int32_t lar(int32_t, int32_t); +int32_t verw(int32_t); +int32_t verr(int32_t); + +void invlpg(int32_t); +void load_tr(int32_t); +void load_ldt(int32_t); + +int32_t set_cr0(int32_t); +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(); + } + + 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); + } + + int32_t data = read_e16(); + load_tr(data); + break; + case 4: + verr(read_e16()); + break; + case 5: + verw(read_e16()); + break; + + default: + dbg_log("%d", modrm_byte[0] >> 3 & 7); + todo(); + } +} + +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 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 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 instr16_0F03() { read_modrm_byte(); + // lsl + if(!protected_mode[0] || vm86_mode()) + { + dbg_log("lsl #ud"); + trigger_ud(); + } + int32_t data = read_e16(); + write_g16(lsl(data, read_g16())); +} +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_0F04() { undefined_instruction(); } +static void instr_0F05() { undefined_instruction(); } + +static void instr_0F06() { + // clts + if(cpl[0]) + { + dbg_log("clts #gp"); + trigger_gp(0); + } + else + { + //dbg_log("clts"); + cr[0] &= ~CR0_TS; + } +} + +static void instr_0F07() { undefined_instruction(); } +static void instr_0F08() { + // invd + todo(); +} + +static void instr_0F09() { + if(cpl[0]) + { + dbg_log("wbinvd #gp"); + trigger_gp(0); + } + // wbinvd +} + + +static void instr_0F0A() { undefined_instruction(); } +static void instr_0F0B() { + // UD2 + trigger_ud(); +} +static void instr_0F0C() { undefined_instruction(); } + +static void instr_0F0D() { + // nop + todo(); +} + +static void instr_0F0E() { undefined_instruction(); } +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_0F13() { unimplemented_sse(); } +static void instr_0F14() { unimplemented_sse(); } +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(); + // prefetch + // nop for us + if(modrm_byte[0] < 0xC0) + modrm_resolve(modrm_byte[0]); +} + +static void instr_0F19() { unimplemented_sse(); } +static void instr_0F1A() { unimplemented_sse(); } +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(); + // multi-byte nop + if(modrm_byte[0] < 0xC0) + modrm_resolve(modrm_byte[0]); +} + + +static void instr_0F20() { read_modrm_byte(); + + 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) + { + case 0: + write_reg_e32(cr[0]); + break; + case 2: + //dbg_log("read cr2 at " + h(instruction_pointer, 8)); + write_reg_e32(cr[2]); + break; + case 3: + //dbg_log("read cr3 (" + h(cr[3], 8) + ")"); + write_reg_e32(cr[3]); + break; + case 4: + write_reg_e32(cr[4]); + break; + default: + dbg_log("%d", modrm_byte[0] >> 3 & 7); + todo(); + } +} + +static void instr_0F21() { read_modrm_byte(); + 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)) + { + dbg_log("#ud mov dreg 4/5 with cr4.DE set"); + trigger_ud(); + } + + // high two bits of modrm are ignored + reg32s[modrm_byte[0] & 7] = dreg[dreg_index]; + + //dbg_log("read dr" + dreg + ": " + h(dreg[dreg_index])); +} + +static void instr_0F22() { read_modrm_byte(); + + if(cpl[0]) + { + trigger_gp(0); + } + + int32_t data = read_reg_e32s(); + //dbg_log("cr" + (modrm_byte[0] >> 3 & 7) + " written: " + h(data, 8)); + + // mov cr, addr + // mod = which control register + switch(modrm_byte[0] >> 3 & 7) + { + case 0: + set_cr0(data); + //dbg_log("cr0=" + h(data)); + break; + + case 2: + cr[2] = data; + //dbg_log("cr2=" + h(data)); + break; + + case 3: + //dbg_log("cr3=" + h(data)); + data &= ~0b111111100111; + dbg_assert_message((data & 0xFFF) == 0, "TODO"); + cr[3] = data; + clear_tlb(); + + //dump_page_directory(); + //dbg_log("page directory loaded at " + h(cr[3], 8)); + break; + + case 4: + if(data & (1 << 11 | 1 << 12 | 1 << 15 | 1 << 16 | 1 << 19 | 0xFFC00000)) + { + trigger_gp(0); + } + + if((cr[4] ^ data) & CR4_PGE) + { + if(data & CR4_PGE) + { + // The PGE bit has been enabled. The global TLB is + // still empty, so we only have to copy it over + clear_tlb(); + } + else + { + // Clear the global TLB + full_clear_tlb(); + } + } + + cr[4] = data; + page_size_extensions[0] = (cr[4] & CR4_PSE) ? PSE_ENABLED : 0; + + if(cr[4] & CR4_PAE) + { + //throw debug.unimpl("PAE"); + assert(false); + } + + //dbg_log("cr4=" + h(cr[4])); + break; + + default: + dbg_log("%d", modrm_byte[0] >> 3 & 7); + todo(); + } +} +static void instr_0F23() { read_modrm_byte(); + 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)) + { + dbg_log("#ud mov dreg 4/5 with cr4.DE set"); + trigger_ud(); + } + + // high two bits of modrm are ignored + dreg[dreg_index] = read_reg_e32s(); + + //dbg_log("write dr" + dreg + ": " + h(dreg[dreg_index])); +} + +static void instr_0F24() { undefined_instruction(); } +static void instr_0F25() { undefined_instruction(); } +static void instr_0F26() { undefined_instruction(); } +static void instr_0F27() { undefined_instruction(); } + +static void instr_0F28() { unimplemented_sse(); } +static void instr_0F29() { unimplemented_sse(); } +static void instr_0F2A() { unimplemented_sse(); } +static void instr_0F2B() { unimplemented_sse(); } +static void instr_0F2C() { unimplemented_sse(); } +static void instr_0F2D() { unimplemented_sse(); } +static void instr_0F2E() { unimplemented_sse(); } +static void instr_0F2F() { unimplemented_sse(); } + +// wrmsr +static void instr_0F30() { + // wrmsr - write maschine specific register + + if(cpl[0]) + { + // cpl > 0 or vm86 mode (vm86 mode is always runs with cpl=3) + trigger_gp(0); + } + + int32_t index = reg32s[ECX]; + int32_t low = reg32s[EAX]; + int32_t high = reg32s[EDX]; + + if(index != IA32_SYSENTER_ESP) + { + //dbg_log("wrmsr ecx=" + h(index, 8) + + // " data=" + h(high, 8) + ":" + h(low, 8)); + } + + switch(index) + { + case IA32_SYSENTER_CS: + sysenter_cs[0] = low & 0xFFFF; + break; + + case IA32_SYSENTER_EIP: + sysenter_eip[0] = low; + break; + + case IA32_SYSENTER_ESP: + sysenter_esp[0] = low; + break; + + case IA32_APIC_BASE_MSR: + { + dbg_assert_message(high == 0, "Changing APIC address (high 32 bits) not supported"); + int32_t address = low & ~(IA32_APIC_BASE_BSP | IA32_APIC_BASE_EXTD | IA32_APIC_BASE_EN); + dbg_assert_message(address == APIC_ADDRESS, "Changing APIC address not supported"); + dbg_assert_message((low & IA32_APIC_BASE_EXTD) == 0, "x2apic not supported"); + *apic_enabled = (low & IA32_APIC_BASE_EN) == IA32_APIC_BASE_EN; + } + break; + + case IA32_TIME_STAMP_COUNTER: + { + int32_t new_tick = (low) + 0x100000000 * (high); + tsc_offset[0] = microtick() - new_tick / TSC_RATE; // XXX: float + } + break; + + case IA32_BIOS_SIGN_ID: + break; + + case IA32_MISC_ENABLE: // Enable Misc. Processor Features + break; + + case IA32_MCG_CAP: + // netbsd + break; + + case IA32_KERNEL_GS_BASE: + // Only used in 64 bit mode (by SWAPGS), but set by kvm-unit-test + dbg_log("GS Base written"); + break; + + default: + assert(false); + //dbg_assert(false, "Unknown msr: " + h(index, 8)); + } +} + +static void instr_0F31() { + // rdtsc - read timestamp counter + + if(!cpl[0] || !(cr[4] & CR4_TSD)) + { + int32_t n = microtick() - tsc_offset[0]; // XXX: float + //dbg_assert(isFinite(n), "non-finite tsc: " + n); + + reg32s[EAX] = n * TSC_RATE; + reg32s[EDX] = n * (TSC_RATE / 0x100000000); + + //dbg_log("rdtsc edx:eax=" + h(reg32[EDX], 8) + ":" + h(reg32[EAX], 8)); + } + else + { + trigger_gp(0); + } +} + +static void instr_0F32() { + // rdmsr - read maschine specific register + if(cpl[0]) + { + trigger_gp(0); + } + + int32_t index = reg32s[ECX]; + + //dbg_log("rdmsr ecx=" + h(index, 8)); + + int32_t low = 0; + int32_t high = 0; + + switch(index) + { + case IA32_SYSENTER_CS: + low = sysenter_cs[0]; + break; + + case IA32_SYSENTER_EIP: + low = sysenter_eip[0]; + break; + + case IA32_SYSENTER_ESP: + low = sysenter_esp[0]; + break; + + case IA32_TIME_STAMP_COUNTER: + { + int32_t n = microtick() - tsc_offset[0]; // XXX: float + low = n * TSC_RATE; + high = n * (TSC_RATE / 0x100000000); + } + break; + + case IA32_PLATFORM_ID: + break; + + case IA32_APIC_BASE_MSR: + if(ENABLE_ACPI) + { + low = APIC_ADDRESS; + + if(*apic_enabled) + { + low |= IA32_APIC_BASE_EN; + } + } + break; + + case IA32_BIOS_SIGN_ID: + break; + + case IA32_MISC_ENABLE: // Enable Misc. Processor Features + break; + + case IA32_RTIT_CTL: + // linux4 + break; + + case MSR_SMI_COUNT: + break; + + case IA32_MCG_CAP: + // netbsd + break; + + case MSR_PKG_C2_RESIDENCY: + break; + + default: + assert(false); + //dbg_assert(false, "Unknown msr: " + h(index, 8)); + } + + reg32s[EAX] = low; + reg32s[EDX] = high; +} + +static void instr_0F33() { + // rdpmc + todo(); +} + +static void instr_0F34() { + // sysenter + int32_t seg = sysenter_cs[0] & 0xFFFC; + + if(!protected_mode[0] || seg == 0) + { + trigger_gp(0); + } + + if(CPU_LOG_VERBOSE) + { + //dbg_log("sysenter cs:eip=" + h(seg , 4) + ":" + h(sysenter_eip[0], 8) + + // " ss:esp=" + h(seg + 8, 4) + ":" + h(sysenter_esp[0], 8)); + } + + flags[0] &= ~FLAG_VM & ~FLAG_INTERRUPT; + + instruction_pointer[0] = sysenter_eip[0]; + reg32s[ESP] = sysenter_esp[0]; + + sreg[CS] = seg; + segment_is_null[CS] = 0; + segment_limits[CS] = -1; + segment_offsets[CS] = 0; + + update_cs_size(true); + + cpl[0] = 0; + cpl_changed(); + + sreg[SS] = seg + 8; + segment_is_null[SS] = 0; + segment_limits[SS] = -1; + segment_offsets[SS] = 0; + + stack_size_32[0] = true; + diverged(); +} + +static void instr_0F35() { + // sysexit + int32_t seg = sysenter_cs[0] & 0xFFFC; + + if(!protected_mode[0] || cpl[0] || seg == 0) + { + trigger_gp(0); + } + + if(CPU_LOG_VERBOSE) + { + //dbg_log("sysexit cs:eip=" + h(seg + 16, 4) + ":" + h(reg32s[EDX], 8) + + // " ss:esp=" + h(seg + 24, 4) + ":" + h(reg32s[ECX], 8)); + } + + instruction_pointer[0] = reg32s[EDX]; + reg32s[ESP] = reg32s[ECX]; + + sreg[CS] = seg + 16 | 3; + + segment_is_null[CS] = 0; + segment_limits[CS] = -1; + segment_offsets[CS] = 0; + + update_cs_size(true); + + cpl[0] = 3; + cpl_changed(); + + sreg[SS] = seg + 24 | 3; + segment_is_null[SS] = 0; + segment_limits[SS] = -1; + segment_offsets[SS] = 0; + + stack_size_32[0] = true; + diverged(); +} + +static void instr_0F36() { undefined_instruction(); } + +static void instr_0F37() { + // getsec + todo(); +} + +static void instr_0F38() { unimplemented_sse(); } +static void instr_0F39() { unimplemented_sse(); } +static void instr_0F3A() { unimplemented_sse(); } +static void instr_0F3B() { unimplemented_sse(); } +static void instr_0F3C() { unimplemented_sse(); } +static void instr_0F3D() { unimplemented_sse(); } +static void instr_0F3E() { unimplemented_sse(); } +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()); } + + +static void instr_0F50() { unimplemented_sse(); } +static void instr_0F51() { unimplemented_sse(); } +static void instr_0F52() { unimplemented_sse(); } +static void instr_0F53() { unimplemented_sse(); } +static void instr_0F54() { unimplemented_sse(); } +static void instr_0F55() { unimplemented_sse(); } +static void instr_0F56() { unimplemented_sse(); } +static void instr_0F57() { unimplemented_sse(); } + +static void instr_0F58() { unimplemented_sse(); } +static void instr_0F59() { unimplemented_sse(); } +static void instr_0F5A() { unimplemented_sse(); } +static void instr_0F5B() { unimplemented_sse(); } +static void instr_0F5C() { unimplemented_sse(); } +static void instr_0F5D() { unimplemented_sse(); } +static void instr_0F5E() { unimplemented_sse(); } +static void instr_0F5F() { unimplemented_sse(); } + +static void instr_0F60() { unimplemented_sse(); } +static void instr_0F61() { unimplemented_sse(); } +static void instr_0F62() { unimplemented_sse(); } +static void instr_0F63() { unimplemented_sse(); } +static void instr_0F64() { unimplemented_sse(); } +static void instr_0F65() { unimplemented_sse(); } +static void instr_0F66() { unimplemented_sse(); } +static void instr_0F67() { unimplemented_sse(); } + +static void instr_0F68() { unimplemented_sse(); } +static void instr_0F69() { unimplemented_sse(); } +static void instr_0F6A() { unimplemented_sse(); } +static void instr_0F6B() { unimplemented_sse(); } +static void instr_0F6C() { unimplemented_sse(); } +static void instr_0F6D() { unimplemented_sse(); } +static void instr_0F6E() { unimplemented_sse(); } +static void instr_0F6F() { unimplemented_sse(); } + +static void instr_0F70() { unimplemented_sse(); } +static void instr_0F71() { unimplemented_sse(); } +static void instr_0F72() { unimplemented_sse(); } +static void instr_0F73() { unimplemented_sse(); } +static void instr_0F74() { unimplemented_sse(); } +static void instr_0F75() { unimplemented_sse(); } +static void instr_0F76() { unimplemented_sse(); } +static void instr_0F77() { + // emms + dbg_assert((*prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) == 0); + + if(cr[0] & (CR0_EM | CR0_TS)) { + if(cr[0] & CR0_TS) { + trigger_nm(); + } + else { + trigger_ud(); + } + } + + safe_tag_word(0xFFFF); +} + +static void instr_0F78() { unimplemented_sse(); } +static void instr_0F79() { unimplemented_sse(); } +static void instr_0F7A() { unimplemented_sse(); } +static void instr_0F7B() { unimplemented_sse(); } +static void instr_0F7C() { unimplemented_sse(); } +static void instr_0F7D() { unimplemented_sse(); } +static void instr_0F7E() { unimplemented_sse(); } +static void instr_0F7F() { unimplemented_sse(); } + +// 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()); } + +// 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 instr16_0FA0() { push16(sreg[FS]); } +static void instr32_0FA0() { push32(sreg[FS]); } +static void instr16_0FA1() { + switch_seg(FS, safe_read16(get_stack_pointer(0))); + adjust_stack_reg(2); +} +static void instr32_0FA1() { + switch_seg(FS, safe_read32s(get_stack_pointer(0)) & 0xFFFF); + adjust_stack_reg(4); +} + +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_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)); +} + +static void instr_0FA6() { + // obsolete cmpxchg (os/2) + trigger_ud(); +} +static void instr_0FA7() { undefined_instruction(); } + +static void instr16_0FA8() { push16(sreg[GS]); } +static void instr32_0FA8() { push32(sreg[GS]); } +static void instr16_0FA9() { + switch_seg(GS, safe_read16(get_stack_pointer(0))); + adjust_stack_reg(2); +} +static void instr32_0FA9() { + switch_seg(GS, safe_read32s(get_stack_pointer(0)) & 0xFFFF); + adjust_stack_reg(4); +} + + +static void instr_0FAA() { + // rsm + 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_0FAC() { read_modrm_byte(); + int32_t data = read_write_e16(); write_e16(shrd16(data, read_g16(), read_op8() & 31)); +} +static void instr32_0FAC() { read_modrm_byte(); + int32_t data = read_write_e32(); write_e32(shrd32(data, read_g32s(), read_op8() & 31)); +} +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) + { + 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(); + } +} + +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)); +} + + +static void instr_0FB0() { read_modrm_byte(); + // 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]; + + + 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(); + } + 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); + + data = safe_read16(virt_addr); + } + else + data = read_reg_e16(); + + cmp16(reg16[AX], data); + + if(getzf()) + { + if(modrm_byte[0] < 0xC0) + safe_write16(virt_addr, read_g16()); + else + write_reg_e16(read_g16()); + } + 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); + + data = safe_read32s(virt_addr); + } + else + { + data = read_reg_e32s(); + } + + cmp32(reg32s[EAX], data); + + if(getzf()) + { + if(modrm_byte[0] < 0xC0) + safe_write32(virt_addr, read_g32s()); + else + write_reg_e32(read_g32s()); + } + else + { + if(modrm_byte[0] < 0xC0) + safe_write32(virt_addr, data); + + reg32s[EAX] = data; + } +} + +// lss +static void instr16_0FB2() { read_modrm_byte(); + lss16(SS); +} +static void instr32_0FB2() { read_modrm_byte(); + lss32(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)); + } +} + +// lfs, lgs +static void instr16_0FB4() { read_modrm_byte(); + lss16(FS); +} +static void instr32_0FB4() { read_modrm_byte(); + lss32(FS); +} +static void instr16_0FB5() { read_modrm_byte(); + lss16(GS); +} +static void instr32_0FB5() { read_modrm_byte(); + lss32(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); +} + +static void instr16_0FB7() { read_modrm_byte(); + // movzx + dbg_assert_message(false, "Possibly invalid encoding"); + 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() { 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 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 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_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_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 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_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)); +} + +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 + dbg_assert_message(false, "Possibly invalid encoding"); + 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)); +} + + +static void instr_0FC2() { unimplemented_sse(); } +static void instr_0FC3() { unimplemented_sse(); } +static void instr_0FC4() { unimplemented_sse(); } +static void instr_0FC5() { unimplemented_sse(); } +static void instr_0FC6() { unimplemented_sse(); } + +static void instr_0FC7() { + read_modrm_byte(); + + switch(modrm_byte[0] >> 3 & 7) + { + case 1: + // cmpxchg8b + if(modrm_byte[0] >= 0xC0) + { + trigger_ud(); + } + + 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(); + } +} + +static void instr_0FC8() { bswap(EAX); } +static void instr_0FC9() { bswap(ECX); } +static void instr_0FCA() { bswap(EDX); } +static void instr_0FCB() { bswap(EBX); } +static void instr_0FCC() { bswap(ESP); } +static void instr_0FCD() { bswap(EBP); } +static void instr_0FCE() { bswap(ESI); } +static void instr_0FCF() { bswap(EDI); } + +static void instr_0FD0() { unimplemented_sse(); } +static void instr_0FD1() { unimplemented_sse(); } +static void instr_0FD2() { unimplemented_sse(); } +static void instr_0FD3() { unimplemented_sse(); } +static void instr_0FD4() { unimplemented_sse(); } +static void instr_0FD5() { unimplemented_sse(); } +static void instr_0FD6() { unimplemented_sse(); } +static void instr_0FD7() { unimplemented_sse(); } + +static void instr_0FD8() { unimplemented_sse(); } +static void instr_0FD9() { unimplemented_sse(); } +static void instr_0FDA() { unimplemented_sse(); } +static void instr_0FDB() { unimplemented_sse(); } +static void instr_0FDC() { unimplemented_sse(); } +static void instr_0FDD() { unimplemented_sse(); } +static void instr_0FDE() { unimplemented_sse(); } +static void instr_0FDF() { unimplemented_sse(); } + +static void instr_0FE0() { unimplemented_sse(); } +static void instr_0FE1() { unimplemented_sse(); } +static void instr_0FE2() { unimplemented_sse(); } +static void instr_0FE3() { unimplemented_sse(); } +static void instr_0FE4() { unimplemented_sse(); } +static void instr_0FE5() { unimplemented_sse(); } +static void instr_0FE6() { unimplemented_sse(); } +static void instr_0FE7() { unimplemented_sse(); } + +static void instr_0FE8() { unimplemented_sse(); } +static void instr_0FE9() { unimplemented_sse(); } +static void instr_0FEA() { unimplemented_sse(); } +static void instr_0FEB() { unimplemented_sse(); } +static void instr_0FEC() { unimplemented_sse(); } +static void instr_0FED() { unimplemented_sse(); } +static void instr_0FEE() { unimplemented_sse(); } +static void instr_0FEF() { unimplemented_sse(); } + +static void instr_0FF0() { unimplemented_sse(); } +static void instr_0FF1() { unimplemented_sse(); } +static void instr_0FF2() { unimplemented_sse(); } +static void instr_0FF3() { unimplemented_sse(); } +static void instr_0FF4() { unimplemented_sse(); } +static void instr_0FF5() { unimplemented_sse(); } +static void instr_0FF6() { unimplemented_sse(); } +static void instr_0FF7() { unimplemented_sse(); } + +static void instr_0FF8() { unimplemented_sse(); } +static void instr_0FF9() { unimplemented_sse(); } +static void instr_0FFA() { unimplemented_sse(); } +static void instr_0FFB() { unimplemented_sse(); } +static void instr_0FFC() { unimplemented_sse(); } +static void instr_0FFD() { unimplemented_sse(); } +static void instr_0FFE() { unimplemented_sse(); } + +static void instr_0FFF() { + // Windows 98 + dbg_log("#ud: 0F FF"); + trigger_ud(); +} + + +static void run_instruction0f_16(int32_t opcode) +{ + // XXX: This table is generated. Don't modify + switch(opcode) + { +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: + instr_0F12(); + break; +case 0x13: + instr_0F13(); + break; +case 0x14: + 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: + instr_0F28(); + break; +case 0x29: + instr_0F29(); + break; +case 0x2A: + instr_0F2A(); + break; +case 0x2B: + instr_0F2B(); + break; +case 0x2C: + 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: + instr_0F54(); + break; +case 0x55: + instr_0F55(); + break; +case 0x56: + instr_0F56(); + break; +case 0x57: + 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: + instr_0F60(); + break; +case 0x61: + 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: + instr_0F67(); + break; +case 0x68: + 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: + instr_0F6E(); + break; +case 0x6F: + instr_0F6F(); + break; +case 0x70: + instr_0F70(); + break; +case 0x71: + instr_0F71(); + break; +case 0x72: + instr_0F72(); + break; +case 0x73: + instr_0F73(); + break; +case 0x74: + instr_0F74(); + break; +case 0x75: + instr_0F75(); + break; +case 0x76: + 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: + instr_0F7E(); + break; +case 0x7F: + 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: + 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: + instr_0FD3(); + break; +case 0xD4: + instr_0FD4(); + break; +case 0xD5: + instr_0FD5(); + break; +case 0xD6: + instr_0FD6(); + break; +case 0xD7: + instr_0FD7(); + break; +case 0xD8: + instr_0FD8(); + break; +case 0xD9: + instr_0FD9(); + break; +case 0xDA: + instr_0FDA(); + break; +case 0xDB: + instr_0FDB(); + break; +case 0xDC: + instr_0FDC(); + break; +case 0xDD: + instr_0FDD(); + break; +case 0xDE: + 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: + instr_0FE4(); + break; +case 0xE5: + instr_0FE5(); + break; +case 0xE6: + instr_0FE6(); + break; +case 0xE7: + instr_0FE7(); + break; +case 0xE8: + instr_0FE8(); + break; +case 0xE9: + instr_0FE9(); + break; +case 0xEA: + instr_0FEA(); + break; +case 0xEB: + instr_0FEB(); + break; +case 0xEC: + instr_0FEC(); + break; +case 0xED: + instr_0FED(); + break; +case 0xEE: + instr_0FEE(); + break; +case 0xEF: + 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: + 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); + } +} + +static void run_instruction0f_32(int32_t opcode) +{ + // XXX: This table is generated. Don't modify + switch(opcode) + { +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: + instr_0F12(); + break; +case 0x13: + instr_0F13(); + break; +case 0x14: + 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: + instr_0F28(); + break; +case 0x29: + instr_0F29(); + break; +case 0x2A: + instr_0F2A(); + break; +case 0x2B: + instr_0F2B(); + break; +case 0x2C: + 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: + instr_0F54(); + break; +case 0x55: + instr_0F55(); + break; +case 0x56: + instr_0F56(); + break; +case 0x57: + 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: + instr_0F60(); + break; +case 0x61: + 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: + instr_0F67(); + break; +case 0x68: + 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: + instr_0F6E(); + break; +case 0x6F: + instr_0F6F(); + break; +case 0x70: + instr_0F70(); + break; +case 0x71: + instr_0F71(); + break; +case 0x72: + instr_0F72(); + break; +case 0x73: + instr_0F73(); + break; +case 0x74: + instr_0F74(); + break; +case 0x75: + instr_0F75(); + break; +case 0x76: + 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: + instr_0F7E(); + break; +case 0x7F: + 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: + 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: + instr_0FD3(); + break; +case 0xD4: + instr_0FD4(); + break; +case 0xD5: + instr_0FD5(); + break; +case 0xD6: + instr_0FD6(); + break; +case 0xD7: + instr_0FD7(); + break; +case 0xD8: + instr_0FD8(); + break; +case 0xD9: + instr_0FD9(); + break; +case 0xDA: + instr_0FDA(); + break; +case 0xDB: + instr_0FDB(); + break; +case 0xDC: + instr_0FDC(); + break; +case 0xDD: + instr_0FDD(); + break; +case 0xDE: + 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: + instr_0FE4(); + break; +case 0xE5: + instr_0FE5(); + break; +case 0xE6: + instr_0FE6(); + break; +case 0xE7: + instr_0FE7(); + break; +case 0xE8: + instr_0FE8(); + break; +case 0xE9: + instr_0FE9(); + break; +case 0xEA: + instr_0FEA(); + break; +case 0xEB: + instr_0FEB(); + break; +case 0xEC: + instr_0FEC(); + break; +case 0xED: + instr_0FED(); + break; +case 0xEE: + instr_0FEE(); + break; +case 0xEF: + 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: + 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); + } +} diff --git a/src/native/log.c b/src/native/log.c new file mode 100644 index 00000000..24a673bb --- /dev/null +++ b/src/native/log.c @@ -0,0 +1,13 @@ +#include +#include +#include +#include + +#include + +#include "const.h" +#include "global_pointers.h" + +#define dbg_log(...) { if(DEBUG) { printf(__VA_ARGS__); } } +#define dbg_assert(condition) { if(DEBUG) { 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 new file mode 100644 index 00000000..1f049f08 --- /dev/null +++ b/src/native/memory.c @@ -0,0 +1,112 @@ +#include + +bool in_mapped_range(uint32_t addr) +{ + return (addr >= 0xA0000 && addr < 0xC0000) || addr >= *memory_size; +} + +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); + +int32_t read8(uint32_t addr) +{ + if(USE_A20 && *a20_enabled) addr &= A20_MASK; + + if(in_mapped_range(addr)) + { + return mmap_read8(addr); + } + else + { + return mem8[addr]; + } +} + +int32_t read16(uint32_t addr) +{ + if(USE_A20 && !*a20_enabled) addr &= A20_MASK; + + if(in_mapped_range(addr)) + { + return mmap_read16(addr); + } + else + { + return *(uint16_t*)(mem8 + addr); + } +} + +uint16_t read_aligned16(uint32_t addr) +{ + dbg_assert(addr >= 0 && addr < 0x80000000); + if(USE_A20 && !*a20_enabled) addr &= A20_MASK16; + + if(in_mapped_range(addr << 1)) + { + return mmap_read16(addr << 1); + } + else + { + return mem16[addr]; + } +} + +int32_t read32s(uint32_t addr) +{ + if(USE_A20 && *a20_enabled) addr &= A20_MASK; + + if(in_mapped_range(addr)) + { + return mmap_read32(addr); + } + else + { + return *(int32_t*)(mem8 + addr); + } +} + +void write8(uint32_t addr, uint8_t value) +{ + if(USE_A20 && !*a20_enabled) addr &= A20_MASK; + + if(in_mapped_range(addr)) + { + mmap_write8(addr, value); + } + else + { + mem8[addr] = value; + } +} + +void write16(uint32_t addr, uint16_t value) +{ + if(USE_A20 && !*a20_enabled) addr &= A20_MASK; + + if(in_mapped_range(addr)) + { + mmap_write16(addr, value); + } + else + { + *(uint16_t*)(mem8 + addr) = value; + } +} + +void write32(uint32_t addr, int32_t value) +{ + if(USE_A20 && !*a20_enabled) addr &= A20_MASK; + + if(in_mapped_range(addr)) + { + mmap_write32(addr, value); + } + else + { + *(int32_t*)(mem8 + addr) = value; + } +} diff --git a/src/native/misc_instr.c b/src/native/misc_instr.c new file mode 100644 index 00000000..5d4f9ee4 --- /dev/null +++ b/src/native/misc_instr.c @@ -0,0 +1,232 @@ +#include +#include +#include +#include + +#include + +#include "const.h" +#include "global_pointers.h" + +static int32_t get_stack_pointer(int32_t); +static void adjust_stack_reg(int32_t); +void branch_taken(); +void branch_not_taken(); +void writable_or_pagefault(int32_t, int32_t); + + +int32_t getcf() +{ + if(*flags_changed & 1) + { + return (*last_op1 ^ (*last_op1 ^ *last_op2) & (*last_op2 ^ *last_add_result)) >> *last_op_size & 1; + } + else + { + return *flags & 1; + } +} + +int32_t getpf() +{ + if(*flags_changed & FLAG_PARITY) + { + // inverted lookup table + return 0x9669 << 2 >> ((*last_result ^ *last_result >> 4) & 0xF) & FLAG_PARITY; + } + else + { + return *flags & FLAG_PARITY; + } +} + +int32_t getaf() +{ + if(*flags_changed & FLAG_ADJUST) + { + return (*last_op1 ^ *last_op2 ^ *last_add_result) & FLAG_ADJUST; + } + else + { + return *flags & FLAG_ADJUST; + } +} + +int32_t getzf() +{ + if(*flags_changed & FLAG_ZERO) + { + return (~*last_result & *last_result - 1) >> *last_op_size & 1; + } + else + { + return *flags & FLAG_ZERO; + } +} + +int32_t getsf() +{ + if(*flags_changed & FLAG_SIGN) + { + return *last_result >> *last_op_size & 1; + } + else + { + return *flags & FLAG_SIGN; + } +} + +int32_t getof() +{ + if(*flags_changed & FLAG_OVERFLOW) + { + return ((*last_op1 ^ *last_add_result) & (*last_op2 ^ *last_add_result)) >> *last_op_size & 1; + } + else + { + return *flags & FLAG_OVERFLOW; + } +} + +int32_t test_o() { return getof(); } +int32_t test_b() { return getcf(); } +int32_t test_z() { return getzf(); } +int32_t test_s() { return getsf(); } +int32_t test_p() { return getpf(); } +int32_t test_be() { return getcf() || getzf(); } +int32_t test_l() { return !getsf() != !getof(); } +int32_t test_le() { return getzf() || !getsf() != !getof(); } + +void jmp_rel16(int32_t rel16) +{ + int32_t cs_offset = get_seg(CS); + + // limit ip to 16 bit + *instruction_pointer = cs_offset + ((*instruction_pointer - cs_offset + rel16) & 0xFFFF); +} + +void jmpcc8(bool condition) +{ + int32_t imm8 = read_imm8s(); + if(condition) + { + *instruction_pointer += imm8; + branch_taken(); + } + else + { + branch_not_taken(); + } +} + +void jmpcc16(bool condition) +{ + int32_t imm16 = read_imm16(); + + if(condition) + { + jmp_rel16(imm16); + branch_taken(); + } + else + { + branch_not_taken(); + } +} + +void jmpcc32(bool condition) +{ + int32_t op = read_imm32s(); + + if(condition) + { + *instruction_pointer += op; + branch_taken(); + } + else + { + branch_not_taken(); + } +} + +static int32_t get_stack_pointer(int32_t offset) +{ + if(*stack_size_32) + { + return get_seg(SS) + reg32s[ESP] + offset; + } + else + { + return get_seg(SS) + (reg16[SP] + offset & 0xFFFF); + } +} + +static void adjust_stack_reg(int32_t adjustment) +{ + if(*stack_size_32) + { + reg32s[ESP] += adjustment; + } + else + { + reg16[SP] += adjustment; + } +} + +void push16(int32_t imm16) +{ + int32_t sp = get_stack_pointer(-2); + + safe_write16(sp, imm16); + adjust_stack_reg(-2); +} + +void push32(int32_t imm32) +{ + int32_t sp = get_stack_pointer(-4); + + safe_write32(sp, imm32); + adjust_stack_reg(-4); +} + +void pusha16() +{ + uint16_t temp = reg16[SP]; + + // make sure we don't get a pagefault after having + // pushed several registers already + writable_or_pagefault(get_stack_pointer(-16), 16); + + push16(reg16[AX]); + push16(reg16[CX]); + push16(reg16[DX]); + push16(reg16[BX]); + push16(temp); + push16(reg16[BP]); + push16(reg16[SI]); + push16(reg16[DI]); +} + +void pusha32() +{ + int32_t temp = reg32s[ESP]; + + writable_or_pagefault(get_stack_pointer(-32), 32); + + push32(reg32s[EAX]); + push32(reg32s[ECX]); + push32(reg32s[EDX]); + push32(reg32s[EBX]); + push32(temp); + push32(reg32s[EBP]); + push32(reg32s[ESI]); + push32(reg32s[EDI]); +} + +int32_t pop32s() +{ + int32_t sp = get_stack_pointer(0); + int32_t result = safe_read32s(sp); + adjust_stack_reg(4); + return result; +} diff --git a/src/native/modrm.c b/src/native/modrm.c new file mode 100644 index 00000000..42794ac5 --- /dev/null +++ b/src/native/modrm.c @@ -0,0 +1,230 @@ +#include +#include +#include +#include + +#include + +#include "const.h" +#include "global_pointers.h" + +// XXX: Remove these declarations when they are implemented in C +static int32_t resolve_sib(bool); + + +#define ds get_seg_prefix_ds +#define ss get_seg_prefix_ss + +#define MODRM_ENTRY(n, offset)\ + 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:\ + return offset; + +#define MODRM_ENTRY16(row, seg, value)\ + MODRM_ENTRY(0x00 | row, seg(((value) & 0xFFFF)))\ + MODRM_ENTRY(0x40 | row, seg(((value) + read_imm8s() & 0xFFFF)))\ + MODRM_ENTRY(0x80 | row, seg(((value) + read_imm16() & 0xFFFF)))\ + + +static int32_t resolve_modrm16(int32_t modrm_byte) +{ + switch(modrm_byte) + { + MODRM_ENTRY16(0, ds, reg16[BX] + reg16[SI]) + MODRM_ENTRY16(1, ds, reg16[BX] + reg16[DI]) + MODRM_ENTRY16(2, ss, reg16[BP] + reg16[SI]) + MODRM_ENTRY16(3, ss, reg16[BP] + reg16[DI]) + MODRM_ENTRY16(4, ds, reg16[SI]) + MODRM_ENTRY16(5, ds, reg16[DI]) + + // special case + MODRM_ENTRY(0x00 | 6, ds(read_imm16())) + MODRM_ENTRY(0x40 | 6, ss(reg16[BP] + read_imm8s() & 0xFFFF)) + MODRM_ENTRY(0x80 | 6, ss(reg16[BP] + read_imm16() & 0xFFFF)) + + MODRM_ENTRY16(7, ds, reg16[BX]) + + default: + assert(false); + } + + return 0; +} + +#undef MODRM_ENTRY16 + +#define MODRM_ENTRY32(row, seg, value)\ + MODRM_ENTRY(0x00 | row, seg((value)))\ + MODRM_ENTRY(0x40 | row, seg((value) + read_imm8s()))\ + MODRM_ENTRY(0x80 | row, seg((value) + read_imm32s()))\ + +static int32_t resolve_modrm32(int32_t modrm_byte) +{ + switch(modrm_byte) + { + MODRM_ENTRY32(0, ds, reg32s[EAX]) + MODRM_ENTRY32(1, ds, reg32s[ECX]) + MODRM_ENTRY32(2, ds, reg32s[EDX]) + MODRM_ENTRY32(3, ds, reg32s[EBX]) + + // special cases + MODRM_ENTRY(0x00 | 4, resolve_sib(false)) + MODRM_ENTRY(0x40 | 4, resolve_sib(true) + read_imm8s()) + MODRM_ENTRY(0x80 | 4, resolve_sib(true) + read_imm32s()) + MODRM_ENTRY(0x00 | 5, ds(read_imm32s())) + MODRM_ENTRY(0x40 | 5, ss(reg32s[EBP] + read_imm8s())) + MODRM_ENTRY(0x80 | 5, ss(reg32s[EBP] + read_imm32s())) + + MODRM_ENTRY32(6, ds, reg32s[ESI]) + MODRM_ENTRY32(7, ds, reg32s[EDI]) + + default: + assert(false); + } + + return 0; +} + +#undef MODRM_ENTRY32 +#undef MODRM_ENTRY + + +#define SIB_ENTRY_LEVEL3(n, offset)\ + case n: return offset; + +#define SIB_ENTRY_LEVEL2(n, offset)\ + SIB_ENTRY_LEVEL3(n | 0, ds((offset) + reg32s[EAX]))\ + SIB_ENTRY_LEVEL3(n | 1, ds((offset) + reg32s[ECX]))\ + SIB_ENTRY_LEVEL3(n | 2, ds((offset) + reg32s[EDX]))\ + SIB_ENTRY_LEVEL3(n | 3, ds((offset) + reg32s[EBX]))\ + SIB_ENTRY_LEVEL3(n | 4, ss((offset) + reg32s[ESP]))\ + SIB_ENTRY_LEVEL3(n | 5, (mod ? ss((offset) + reg32s[EBP]) : ds((offset) + read_imm32s())))\ + SIB_ENTRY_LEVEL3(n | 6, ds((offset) + reg32s[ESI]))\ + SIB_ENTRY_LEVEL3(n | 7, ds((offset) + reg32s[EDI])) + +#define SIB_ENTRY_LEVEL1(n, reg1)\ + SIB_ENTRY_LEVEL2(0x00 | (n) << 3, (reg1))\ + SIB_ENTRY_LEVEL2(0x40 | (n) << 3, (reg1) << 1)\ + SIB_ENTRY_LEVEL2(0x80 | (n) << 3, (reg1) << 2)\ + SIB_ENTRY_LEVEL2(0xC0 | (n) << 3, (reg1) << 3) + +static int32_t resolve_sib_(bool mod) +{ + switch(read_imm8()) + { + SIB_ENTRY_LEVEL1(0, reg32s[EAX]); + SIB_ENTRY_LEVEL1(1, reg32s[ECX]); + SIB_ENTRY_LEVEL1(2, reg32s[EDX]); + SIB_ENTRY_LEVEL1(3, reg32s[EBX]); + SIB_ENTRY_LEVEL1(4, 0 ); + SIB_ENTRY_LEVEL1(5, reg32s[EBP]); + SIB_ENTRY_LEVEL1(6, reg32s[ESI]); + SIB_ENTRY_LEVEL1(7, reg32s[EDI]); + + default: + assert(false); + } + + return 0; +} + +#undef SIB_ENTRY_LEVEL3 +#undef SIB_ENTRY_LEVEL2 +#undef SIB_ENTRY_LEVEL1 + +#undef ds +#undef ss + + +static int32_t 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; + int32_t seg; + + if(r == 4) + { + base = reg32s[ESP]; + seg = SS; + } + else if(r == 5) + { + if(mod) + { + base = reg32s[EBP]; + seg = SS; + } + else + { + base = read_imm32s(); + seg = DS; + } + } + else + { + base = reg32s[r]; + seg = DS; + } + + int32_t offset; + if(m == 4) + { + offset = 0; + } + else + { + uint8_t s = sib_byte >> 6 & 3; + offset = reg32s[m] << s; + } + + return get_seg_prefix(seg) + base + offset; +} + +static int32_t resolve_modrm32_(int32_t modrm_byte) +{ + uint8_t r = modrm_byte & 7; + assert(modrm_byte < 0xC0); + + if(r == 4) + { + if(modrm_byte < 0x40) + { + return resolve_sib(false); + } + else + { + return resolve_sib(true) + (modrm_byte < 0x80 ? read_imm8s() : read_imm32s()); + } + } + else if(r == 5) + { + if(modrm_byte < 0x40) + { + return get_seg_prefix_ds(read_imm32s()); + } + else + { + return get_seg_prefix_ss(reg32s[EBP] + (modrm_byte < 0x80 ? read_imm8s() : read_imm32s())); + } + } + else + { + if(modrm_byte < 0x40) + { + return get_seg_prefix_ds(reg32s[r]); + } + else + { + return get_seg_prefix_ds(reg32s[r] + (modrm_byte < 0x80 ? read_imm8s() : read_imm32s())); + } + } +} diff --git a/src/pci.js b/src/pci.js index c79405fa..dca6e2e2 100644 --- a/src/pci.js +++ b/src/pci.js @@ -446,6 +446,11 @@ PCI.prototype.pci_write32 = function(address, written) space[addr >> 2] = 0; } } + else if(addr === 0x04) + { + dbg_log("PCI write dev=" + h(bdf >> 3, 2) + " (" + device.name + ") addr=" + h(addr, 4) + + " value=" + h(written >>> 0, 8), LOG_PCI); + } else { dbg_log("PCI write dev=" + h(bdf >> 3, 2) + " (" + device.name + ") addr=" + h(addr, 4) + diff --git a/src/string.js b/src/string.js index cf1b934e..b38a20ce 100644 --- a/src/string.js +++ b/src/string.js @@ -46,9 +46,9 @@ CPU.prototype.movsb = function() var cpu = this; var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0; var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0; - var size = cpu.flags & flag_direction ? -1 : 1; + var size = cpu.flags[0] & flag_direction ? -1 : 1; - if(cpu.prefixes & PREFIX_MASK_REP) + if(cpu.prefixes[0] & PREFIX_MASK_REP) { var count = cpu.get_reg_asize(reg_ecx) >>> 0; if(count === 0) return; @@ -57,7 +57,7 @@ CPU.prototype.movsb = function() var cycle_counter = MAX_COUNT_PER_CYCLE; var phys_src = cpu.translate_address_read(src); var phys_dest = cpu.translate_address_write(dest); - if(cpu.paging) + if(cpu.paging[0]) { cycle_counter = string_get_cycle_count2(size, src, dest); } @@ -73,10 +73,10 @@ CPU.prototype.movsb = function() cpu.add_reg_asize(reg_edi, diff); cpu.add_reg_asize(reg_esi, diff); cpu.set_ecx_asize(count); - cpu.timestamp_counter += start_count - count; + cpu.timestamp_counter[0] += start_count - count; if(cont) { - cpu.instruction_pointer = cpu.previous_ip; + cpu.instruction_pointer[0] = cpu.previous_ip[0]; } } else @@ -93,9 +93,9 @@ CPU.prototype.movsw = function() var cpu = this; var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0; var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0; - var size = cpu.flags & flag_direction ? -2 : 2; + var size = cpu.flags[0] & flag_direction ? -2 : 2; - if(cpu.prefixes & PREFIX_MASK_REP) + if(cpu.prefixes[0] & PREFIX_MASK_REP) { var count = cpu.get_reg_asize(reg_ecx) >>> 0; if(count === 0) return; @@ -107,7 +107,7 @@ CPU.prototype.movsw = function() var single_size = size < 0 ? -1 : 1; var phys_src = cpu.translate_address_read(src) >>> 1; var phys_dest = cpu.translate_address_write(dest) >>> 1; - if(cpu.paging) + if(cpu.paging[0]) { cycle_counter = string_get_cycle_count2(size, src, dest); } @@ -123,7 +123,7 @@ CPU.prototype.movsw = function() cpu.add_reg_asize(reg_edi, diff); cpu.add_reg_asize(reg_esi, diff); cpu.set_ecx_asize(count); - cpu.timestamp_counter += start_count - count; + cpu.timestamp_counter[0] += start_count - count; } else { @@ -140,7 +140,7 @@ CPU.prototype.movsw = function() } if(cont) { - cpu.instruction_pointer = cpu.previous_ip; + cpu.instruction_pointer[0] = cpu.previous_ip[0]; } } else @@ -156,7 +156,7 @@ CPU.prototype.movsd = function() { var cpu = this; - if(cpu.prefixes & PREFIX_MASK_REP) + if(cpu.prefixes[0] & PREFIX_MASK_REP) { // often used by memcpy, well worth optimizing // using cpu.mem32s.set @@ -173,16 +173,16 @@ CPU.prototype.movsd = function() // must be page-aligned if cpu.paging is enabled // and dword-aligned in general - var align_mask = cpu.paging ? 0xFFF : 3; + var align_mask = cpu.paging[0] ? 0xFFF : 3; if((dest & align_mask) === 0 && (src & align_mask) === 0 && // If df is set, alignment works a different // This should be unlikely - (cpu.flags & flag_direction) === 0) + (cpu.flags[0] & flag_direction) === 0) { var cont = false; - if(cpu.paging) + if(cpu.paging[0]) { src = cpu.translate_address_read(src); dest = cpu.translate_address_write(dest); @@ -208,7 +208,7 @@ CPU.prototype.movsd = function() if(cont) { - cpu.instruction_pointer = cpu.previous_ip; + cpu.instruction_pointer[0] = cpu.previous_ip[0]; } return; @@ -218,9 +218,9 @@ CPU.prototype.movsd = function() var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0; var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0; - var size = cpu.flags & flag_direction ? -4 : 4; + var size = cpu.flags[0] & flag_direction ? -4 : 4; - if(cpu.prefixes & PREFIX_MASK_REP) + if(cpu.prefixes[0] & PREFIX_MASK_REP) { var count = cpu.get_reg_asize(reg_ecx) >>> 0; if(count === 0) return; @@ -232,7 +232,7 @@ CPU.prototype.movsd = function() var single_size = size < 0 ? -1 : 1; var phys_src = cpu.translate_address_read(src) >>> 2; var phys_dest = cpu.translate_address_write(dest) >>> 2; - if(cpu.paging) + if(cpu.paging[0]) { cycle_counter = string_get_cycle_count2(size, src, dest); } @@ -248,7 +248,7 @@ CPU.prototype.movsd = function() cpu.add_reg_asize(reg_edi, diff); cpu.add_reg_asize(reg_esi, diff); cpu.set_ecx_asize(count); - cpu.timestamp_counter += start_count - count; + cpu.timestamp_counter[0] += start_count - count; } else { @@ -265,7 +265,7 @@ CPU.prototype.movsd = function() } if(cont) { - this.instruction_pointer = this.previous_ip; + this.instruction_pointer[0] = this.previous_ip[0]; } } else @@ -282,19 +282,19 @@ function cmpsb(cpu) var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0; var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0; var data_src, data_dest; - var size = cpu.flags & flag_direction ? -1 : 1; + var size = cpu.flags[0] & flag_direction ? -1 : 1; - if(cpu.prefixes & PREFIX_MASK_REP) + if(cpu.prefixes[0] & PREFIX_MASK_REP) { var count = cpu.get_reg_asize(reg_ecx) >>> 0; if(count === 0) return; var cont = false; var start_count = count; - var is_repz = (cpu.prefixes & PREFIX_MASK_REP) === PREFIX_REPZ; + var is_repz = (cpu.prefixes[0] & PREFIX_MASK_REP) === PREFIX_REPZ; var cycle_counter = MAX_COUNT_PER_CYCLE; var phys_src = cpu.translate_address_read(src); var phys_dest = cpu.translate_address_read(dest); - if(cpu.paging) + if(cpu.paging[0]) { cycle_counter = string_get_cycle_count2(size, src, dest); } @@ -311,10 +311,10 @@ function cmpsb(cpu) cpu.add_reg_asize(reg_edi, diff); cpu.add_reg_asize(reg_esi, diff); cpu.set_ecx_asize(count); - cpu.timestamp_counter += start_count - count; + cpu.timestamp_counter[0] += start_count - count; if(cont) { - cpu.instruction_pointer = cpu.previous_ip; + cpu.instruction_pointer[0] = cpu.previous_ip[0]; } } else @@ -334,22 +334,22 @@ function cmpsw(cpu) var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0; var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0; var data_src, data_dest; - var size = cpu.flags & flag_direction ? -2 : 2; + var size = cpu.flags[0] & flag_direction ? -2 : 2; - if(cpu.prefixes & PREFIX_MASK_REP) + if(cpu.prefixes[0] & PREFIX_MASK_REP) { var count = cpu.get_reg_asize(reg_ecx) >>> 0; if(count === 0) return; var cont = false; var start_count = count; - var is_repz = (cpu.prefixes & PREFIX_MASK_REP) === PREFIX_REPZ; + var is_repz = (cpu.prefixes[0] & PREFIX_MASK_REP) === PREFIX_REPZ; var cycle_counter = MAX_COUNT_PER_CYCLE; if(!(dest & 1) && !(src & 1)) { var single_size = size < 0 ? -1 : 1; var phys_src = cpu.translate_address_read(src) >>> 1; var phys_dest = cpu.translate_address_read(dest) >>> 1; - if(cpu.paging) + if(cpu.paging[0]) { cycle_counter = string_get_cycle_count2(size, src, dest); } @@ -366,7 +366,7 @@ function cmpsw(cpu) cpu.add_reg_asize(reg_edi, diff); cpu.add_reg_asize(reg_esi, diff); cpu.set_ecx_asize(count); - cpu.timestamp_counter += start_count - count; + cpu.timestamp_counter[0] += start_count - count; } else { @@ -384,7 +384,7 @@ function cmpsw(cpu) } if(cont) { - cpu.instruction_pointer = cpu.previous_ip; + cpu.instruction_pointer[0] = cpu.previous_ip[0]; } } else @@ -404,22 +404,22 @@ function cmpsd(cpu) var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0; var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0; var data_src, data_dest; - var size = cpu.flags & flag_direction ? -4 : 4; + var size = cpu.flags[0] & flag_direction ? -4 : 4; - if(cpu.prefixes & PREFIX_MASK_REP) + if(cpu.prefixes[0] & PREFIX_MASK_REP) { var count = cpu.get_reg_asize(reg_ecx) >>> 0; if(count === 0) return; var cont = false; var start_count = count; - var is_repz = (cpu.prefixes & PREFIX_MASK_REP) === PREFIX_REPZ; + var is_repz = (cpu.prefixes[0] & PREFIX_MASK_REP) === PREFIX_REPZ; var cycle_counter = MAX_COUNT_PER_CYCLE; if(!(dest & 3) && !(src & 3)) { var single_size = size < 0 ? -1 : 1; var phys_src = cpu.translate_address_read(src) >>> 2; var phys_dest = cpu.translate_address_read(dest) >>> 2; - if(cpu.paging) + if(cpu.paging[0]) { cycle_counter = string_get_cycle_count2(size, src, dest); } @@ -436,7 +436,7 @@ function cmpsd(cpu) cpu.add_reg_asize(reg_edi, diff); cpu.add_reg_asize(reg_esi, diff); cpu.set_ecx_asize(count); - cpu.timestamp_counter += start_count - count; + cpu.timestamp_counter[0] += start_count - count; } else { @@ -454,7 +454,7 @@ function cmpsd(cpu) } if(cont) { - cpu.instruction_pointer = cpu.previous_ip; + cpu.instruction_pointer[0] = cpu.previous_ip[0]; } } else @@ -473,9 +473,9 @@ function stosb(cpu) { var data = cpu.reg8[reg_al]; var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0; - var size = cpu.flags & flag_direction ? -1 : 1; + var size = cpu.flags[0] & flag_direction ? -1 : 1; - if(cpu.prefixes & PREFIX_MASK_REP) + if(cpu.prefixes[0] & PREFIX_MASK_REP) { var count = cpu.get_reg_asize(reg_ecx) >>> 0; if(count === 0) return; @@ -483,7 +483,7 @@ function stosb(cpu) var start_count = count; var cycle_counter = MAX_COUNT_PER_CYCLE; var phys_dest = cpu.translate_address_write(dest); - if(cpu.paging) + if(cpu.paging[0]) { cycle_counter = string_get_cycle_count(size, dest); } @@ -497,10 +497,10 @@ function stosb(cpu) var diff = size * (start_count - count) | 0; cpu.add_reg_asize(reg_edi, diff); cpu.set_ecx_asize(count); - cpu.timestamp_counter += start_count - count; + cpu.timestamp_counter[0] += start_count - count; if(cont) { - cpu.instruction_pointer = cpu.previous_ip; + cpu.instruction_pointer[0] = cpu.previous_ip[0]; } } else @@ -515,9 +515,9 @@ function stosw(cpu) { var data = cpu.reg16[reg_ax]; var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0; - var size = cpu.flags & flag_direction ? -2 : 2; + var size = cpu.flags[0] & flag_direction ? -2 : 2; - if(cpu.prefixes & PREFIX_MASK_REP) + if(cpu.prefixes[0] & PREFIX_MASK_REP) { var count = cpu.get_reg_asize(reg_ecx) >>> 0; if(count === 0) return; @@ -528,7 +528,7 @@ function stosw(cpu) { var single_size = size < 0 ? -1 : 1; var phys_dest = cpu.translate_address_write(dest) >>> 1; - if(cpu.paging) + if(cpu.paging[0]) { cycle_counter = string_get_cycle_count(size, dest); } @@ -542,7 +542,7 @@ function stosw(cpu) var diff = size * (start_count - count) | 0; cpu.add_reg_asize(reg_edi, diff); cpu.set_ecx_asize(count); - cpu.timestamp_counter += start_count - count; + cpu.timestamp_counter[0] += start_count - count; } else { @@ -557,7 +557,7 @@ function stosw(cpu) } if(cont) { - cpu.instruction_pointer = cpu.previous_ip; + cpu.instruction_pointer[0] = cpu.previous_ip[0]; } } else @@ -572,9 +572,9 @@ function stosd(cpu) { var data = cpu.reg32s[reg_eax]; var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0; - var size = cpu.flags & flag_direction ? -4 : 4; + var size = cpu.flags[0] & flag_direction ? -4 : 4; - if(cpu.prefixes & PREFIX_MASK_REP) + if(cpu.prefixes[0] & PREFIX_MASK_REP) { var count = cpu.get_reg_asize(reg_ecx) >>> 0; if(count === 0) return; @@ -585,7 +585,7 @@ function stosd(cpu) { var single_size = size < 0 ? -1 : 1; var phys_dest = cpu.translate_address_write(dest) >>> 2; - if(cpu.paging) + if(cpu.paging[0]) { cycle_counter = string_get_cycle_count(size, dest); } @@ -599,7 +599,7 @@ function stosd(cpu) var diff = size * (start_count - count) | 0; cpu.add_reg_asize(reg_edi, diff); cpu.set_ecx_asize(count); - cpu.timestamp_counter += start_count - count; + cpu.timestamp_counter[0] += start_count - count; } else { @@ -614,7 +614,7 @@ function stosd(cpu) } if(cont) { - cpu.instruction_pointer = cpu.previous_ip; + cpu.instruction_pointer[0] = cpu.previous_ip[0]; } } else @@ -628,9 +628,9 @@ function stosd(cpu) function lodsb(cpu) { var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0; - var size = cpu.flags & flag_direction ? -1 : 1; + var size = cpu.flags[0] & flag_direction ? -1 : 1; - if(cpu.prefixes & PREFIX_MASK_REP) + if(cpu.prefixes[0] & PREFIX_MASK_REP) { var count = cpu.get_reg_asize(reg_ecx) >>> 0; if(count === 0) return; @@ -638,7 +638,7 @@ function lodsb(cpu) var start_count = count; var cycle_counter = MAX_COUNT_PER_CYCLE; var phys_src = cpu.translate_address_read(src); - if(cpu.paging) + if(cpu.paging[0]) { cycle_counter = string_get_cycle_count(size, src); } @@ -652,10 +652,10 @@ function lodsb(cpu) var diff = size * (start_count - count) | 0; cpu.add_reg_asize(reg_esi, diff); cpu.set_ecx_asize(count); - cpu.timestamp_counter += start_count - count; + cpu.timestamp_counter[0] += start_count - count; if(cont) { - cpu.instruction_pointer = cpu.previous_ip; + cpu.instruction_pointer[0] = cpu.previous_ip[0]; } } else @@ -669,9 +669,9 @@ function lodsb(cpu) function lodsw(cpu) { var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0; - var size = cpu.flags & flag_direction ? -2 : 2; + var size = cpu.flags[0] & flag_direction ? -2 : 2; - if(cpu.prefixes & PREFIX_MASK_REP) + if(cpu.prefixes[0] & PREFIX_MASK_REP) { var count = cpu.get_reg_asize(reg_ecx) >>> 0; if(count === 0) return; @@ -687,7 +687,7 @@ function lodsw(cpu) while(cont && cycle_counter--); if(cont) { - cpu.instruction_pointer = cpu.previous_ip; + cpu.instruction_pointer[0] = cpu.previous_ip[0]; } } else @@ -701,9 +701,9 @@ function lodsw(cpu) function lodsd(cpu) { var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0; - var size = cpu.flags & flag_direction ? -4 : 4; + var size = cpu.flags[0] & flag_direction ? -4 : 4; - if(cpu.prefixes & PREFIX_MASK_REP) + if(cpu.prefixes[0] & PREFIX_MASK_REP) { var count = cpu.get_reg_asize(reg_ecx) >>> 0; if(count === 0) return; @@ -719,7 +719,7 @@ function lodsd(cpu) while(cont && cycle_counter--); if(cont) { - cpu.instruction_pointer = cpu.previous_ip; + cpu.instruction_pointer[0] = cpu.previous_ip[0]; } } else @@ -733,20 +733,20 @@ function lodsd(cpu) function scasb(cpu) { var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0; - var size = cpu.flags & flag_direction ? -1 : 1; + var size = cpu.flags[0] & flag_direction ? -1 : 1; var data_dest; var data_src = cpu.reg8[reg_al]; - if(cpu.prefixes & PREFIX_MASK_REP) + if(cpu.prefixes[0] & PREFIX_MASK_REP) { var count = cpu.get_reg_asize(reg_ecx) >>> 0; if(count === 0) return; var cont = false; var start_count = count; - var is_repz = (cpu.prefixes & PREFIX_MASK_REP) === PREFIX_REPZ; + var is_repz = (cpu.prefixes[0] & PREFIX_MASK_REP) === PREFIX_REPZ; var cycle_counter = MAX_COUNT_PER_CYCLE; var phys_dest = cpu.translate_address_read(dest); - if(cpu.paging) + if(cpu.paging[0]) { cycle_counter = string_get_cycle_count(size, dest); } @@ -760,10 +760,10 @@ function scasb(cpu) var diff = size * (start_count - count) | 0; cpu.add_reg_asize(reg_edi, diff); cpu.set_ecx_asize(count); - cpu.timestamp_counter += start_count - count; + cpu.timestamp_counter[0] += start_count - count; if(cont) { - cpu.instruction_pointer = cpu.previous_ip; + cpu.instruction_pointer[0] = cpu.previous_ip[0]; } } else @@ -779,23 +779,23 @@ function scasb(cpu) function scasw(cpu) { var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0; - var size = cpu.flags & flag_direction ? -2 : 2; + var size = cpu.flags[0] & flag_direction ? -2 : 2; var data_dest; var data_src = cpu.reg16[reg_al]; - if(cpu.prefixes & PREFIX_MASK_REP) + if(cpu.prefixes[0] & PREFIX_MASK_REP) { var count = cpu.get_reg_asize(reg_ecx) >>> 0; if(count === 0) return; var cont = false; var start_count = count; - var is_repz = (cpu.prefixes & PREFIX_MASK_REP) === PREFIX_REPZ; + var is_repz = (cpu.prefixes[0] & PREFIX_MASK_REP) === PREFIX_REPZ; var cycle_counter = MAX_COUNT_PER_CYCLE; if(!(dest & 1)) { var single_size = size < 0 ? -1 : 1; var phys_dest = cpu.translate_address_read(dest) >>> 1; - if(cpu.paging) + if(cpu.paging[0]) { cycle_counter = string_get_cycle_count(size, dest); } @@ -809,7 +809,7 @@ function scasw(cpu) var diff = size * (start_count - count) | 0; cpu.add_reg_asize(reg_edi, diff); cpu.set_ecx_asize(count); - cpu.timestamp_counter += start_count - count; + cpu.timestamp_counter[0] += start_count - count; } else { @@ -824,7 +824,7 @@ function scasw(cpu) } if(cont) { - cpu.instruction_pointer = cpu.previous_ip; + cpu.instruction_pointer[0] = cpu.previous_ip[0]; } } else @@ -840,23 +840,23 @@ function scasw(cpu) function scasd(cpu) { var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0; - var size = cpu.flags & flag_direction ? -4 : 4; + var size = cpu.flags[0] & flag_direction ? -4 : 4; var data_dest; var data_src = cpu.reg32s[reg_eax]; - if(cpu.prefixes & PREFIX_MASK_REP) + if(cpu.prefixes[0] & PREFIX_MASK_REP) { var count = cpu.get_reg_asize(reg_ecx) >>> 0; if(count === 0) return; var cont = false; var start_count = count; - var is_repz = (cpu.prefixes & PREFIX_MASK_REP) === PREFIX_REPZ; + var is_repz = (cpu.prefixes[0] & PREFIX_MASK_REP) === PREFIX_REPZ; var cycle_counter = MAX_COUNT_PER_CYCLE; if(!(dest & 3)) { var single_size = size < 0 ? -1 : 1; var phys_dest = cpu.translate_address_read(dest) >>> 2; - if(cpu.paging) + if(cpu.paging[0]) { cycle_counter = string_get_cycle_count(size, dest); } @@ -870,7 +870,7 @@ function scasd(cpu) var diff = size * (start_count - count) | 0; cpu.add_reg_asize(reg_edi, diff); cpu.set_ecx_asize(count); - cpu.timestamp_counter += start_count - count; + cpu.timestamp_counter[0] += start_count - count; } else { @@ -885,7 +885,7 @@ function scasd(cpu) } if(cont) { - cpu.instruction_pointer = cpu.previous_ip; + cpu.instruction_pointer[0] = cpu.previous_ip[0]; } } else @@ -904,9 +904,9 @@ function insb(cpu) cpu.test_privileges_for_io(port, 1); var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0; - var size = cpu.flags & flag_direction ? -1 : 1; + var size = cpu.flags[0] & flag_direction ? -1 : 1; - if(cpu.prefixes & PREFIX_MASK_REP) + if(cpu.prefixes[0] & PREFIX_MASK_REP) { var count = cpu.get_reg_asize(reg_ecx) >>> 0; if(count === 0) return; @@ -914,7 +914,7 @@ function insb(cpu) var start_count = count; var cycle_counter = MAX_COUNT_PER_CYCLE; var phys_dest = cpu.translate_address_write(dest); - if(cpu.paging) + if(cpu.paging[0]) { cycle_counter = string_get_cycle_count(size, dest); } @@ -928,10 +928,10 @@ function insb(cpu) var diff = size * (start_count - count) | 0; cpu.add_reg_asize(reg_edi, diff); cpu.set_ecx_asize(count); - cpu.timestamp_counter += start_count - count; + cpu.timestamp_counter[0] += start_count - count; if(cont) { - cpu.instruction_pointer = cpu.previous_ip; + cpu.instruction_pointer[0] = cpu.previous_ip[0]; } } else @@ -949,9 +949,9 @@ function insw(cpu) cpu.test_privileges_for_io(port, 2); var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0; - var size = cpu.flags & flag_direction ? -2 : 2; + var size = cpu.flags[0] & flag_direction ? -2 : 2; - if(cpu.prefixes & PREFIX_MASK_REP) + if(cpu.prefixes[0] & PREFIX_MASK_REP) { var count = cpu.get_reg_asize(reg_ecx) >>> 0; if(count === 0) return; @@ -962,7 +962,7 @@ function insw(cpu) { var single_size = size < 0 ? -1 : 1; var phys_dest = cpu.translate_address_write(dest) >>> 1; - if(cpu.paging) + if(cpu.paging[0]) { cycle_counter = string_get_cycle_count(size, dest); } @@ -976,7 +976,7 @@ function insw(cpu) var diff = size * (start_count - count) | 0; cpu.add_reg_asize(reg_edi, diff); cpu.set_ecx_asize(count); - cpu.timestamp_counter += start_count - count; + cpu.timestamp_counter[0] += start_count - count; } else { @@ -991,7 +991,7 @@ function insw(cpu) } if(cont) { - cpu.instruction_pointer = cpu.previous_ip; + cpu.instruction_pointer[0] = cpu.previous_ip[0]; } } else @@ -1009,9 +1009,9 @@ function insd(cpu) cpu.test_privileges_for_io(port, 4); var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0; - var size = cpu.flags & flag_direction ? -4 : 4; + var size = cpu.flags[0] & flag_direction ? -4 : 4; - if(cpu.prefixes & PREFIX_MASK_REP) + if(cpu.prefixes[0] & PREFIX_MASK_REP) { var count = cpu.get_reg_asize(reg_ecx) >>> 0; if(count === 0) return; @@ -1022,7 +1022,7 @@ function insd(cpu) { var single_size = size < 0 ? -1 : 1; var phys_dest = cpu.translate_address_write(dest) >>> 2; - if(cpu.paging) + if(cpu.paging[0]) { cycle_counter = string_get_cycle_count(size, dest); } @@ -1036,7 +1036,7 @@ function insd(cpu) var diff = size * (start_count - count) | 0; cpu.add_reg_asize(reg_edi, diff); cpu.set_ecx_asize(count); - cpu.timestamp_counter += start_count - count; + cpu.timestamp_counter[0] += start_count - count; } else { @@ -1051,7 +1051,7 @@ function insd(cpu) } if(cont) { - cpu.instruction_pointer = cpu.previous_ip; + cpu.instruction_pointer[0] = cpu.previous_ip[0]; } } else @@ -1069,9 +1069,9 @@ function outsb(cpu) cpu.test_privileges_for_io(port, 1); var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0; - var size = cpu.flags & flag_direction ? -1 : 1; + var size = cpu.flags[0] & flag_direction ? -1 : 1; - if(cpu.prefixes & PREFIX_MASK_REP) + if(cpu.prefixes[0] & PREFIX_MASK_REP) { var count = cpu.get_reg_asize(reg_ecx) >>> 0; if(count === 0) return; @@ -1079,7 +1079,7 @@ function outsb(cpu) var start_count = count; var cycle_counter = MAX_COUNT_PER_CYCLE; var phys_src = cpu.translate_address_read(src); - if(cpu.paging) + if(cpu.paging[0]) { cycle_counter = string_get_cycle_count(size, src); } @@ -1093,10 +1093,10 @@ function outsb(cpu) var diff = size * (start_count - count) | 0; cpu.add_reg_asize(reg_esi, diff); cpu.set_ecx_asize(count); - cpu.timestamp_counter += start_count - count; + cpu.timestamp_counter[0] += start_count - count; if(cont) { - cpu.instruction_pointer = cpu.previous_ip; + cpu.instruction_pointer[0] = cpu.previous_ip[0]; } } else @@ -1113,9 +1113,9 @@ function outsw(cpu) cpu.test_privileges_for_io(port, 2); var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0; - var size = cpu.flags & flag_direction ? -2 : 2; + var size = cpu.flags[0] & flag_direction ? -2 : 2; - if(cpu.prefixes & PREFIX_MASK_REP) + if(cpu.prefixes[0] & PREFIX_MASK_REP) { var count = cpu.get_reg_asize(reg_ecx) >>> 0; if(count === 0) return; @@ -1126,7 +1126,7 @@ function outsw(cpu) { var single_size = size < 0 ? -1 : 1; var phys_src = cpu.translate_address_read(src) >>> 1; - if(cpu.paging) + if(cpu.paging[0]) { cycle_counter = string_get_cycle_count(size, src); } @@ -1140,7 +1140,7 @@ function outsw(cpu) var diff = size * (start_count - count) | 0; cpu.add_reg_asize(reg_esi, diff); cpu.set_ecx_asize(count); - cpu.timestamp_counter += start_count - count; + cpu.timestamp_counter[0] += start_count - count; } else { @@ -1155,7 +1155,7 @@ function outsw(cpu) } if(cont) { - cpu.instruction_pointer = cpu.previous_ip; + cpu.instruction_pointer[0] = cpu.previous_ip[0]; } } else @@ -1172,9 +1172,9 @@ function outsd(cpu) cpu.test_privileges_for_io(port, 4); var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0; - var size = cpu.flags & flag_direction ? -4 : 4; + var size = cpu.flags[0] & flag_direction ? -4 : 4; - if(cpu.prefixes & PREFIX_MASK_REP) + if(cpu.prefixes[0] & PREFIX_MASK_REP) { var count = cpu.get_reg_asize(reg_ecx) >>> 0; if(count === 0) return; @@ -1185,7 +1185,7 @@ function outsd(cpu) { var single_size = size < 0 ? -1 : 1; var phys_src = cpu.translate_address_read(src) >>> 2; - if(cpu.paging) + if(cpu.paging[0]) { cycle_counter = string_get_cycle_count(size, src); } @@ -1199,7 +1199,7 @@ function outsd(cpu) var diff = size * (start_count - count) | 0; cpu.add_reg_asize(reg_esi, diff); cpu.set_ecx_asize(count); - cpu.timestamp_counter += start_count - count; + cpu.timestamp_counter[0] += start_count - count; } else { @@ -1214,7 +1214,7 @@ function outsd(cpu) } if(cont) { - cpu.instruction_pointer = cpu.previous_ip; + cpu.instruction_pointer[0] = cpu.previous_ip[0]; } } else @@ -1224,3 +1224,27 @@ function outsd(cpu) } cpu.diverged(); } + +CPU.prototype.stosb = function() { stosb(this); } +CPU.prototype.stosw = function() { stosw(this); } +CPU.prototype.stosd = function() { stosd(this); } + +CPU.prototype.lodsb = function() { lodsb(this); } +CPU.prototype.lodsw = function() { lodsw(this); } +CPU.prototype.lodsd = function() { lodsd(this); } + +CPU.prototype.cmpsb = function() { cmpsb(this); } +CPU.prototype.cmpsw = function() { cmpsw(this); } +CPU.prototype.cmpsd = function() { cmpsd(this); } + +CPU.prototype.scasb = function() { scasb(this); } +CPU.prototype.scasw = function() { scasw(this); } +CPU.prototype.scasd = function() { scasd(this); } + +CPU.prototype.insb = function() { insb(this); } +CPU.prototype.insw = function() { insw(this); } +CPU.prototype.insd = function() { insd(this); } + +CPU.prototype.outsb = function() { outsb(this); } +CPU.prototype.outsw = function() { outsw(this); } +CPU.prototype.outsd = function() { outsd(this); } diff --git a/src/virtio.js b/src/virtio.js index ef3cb202..cc63e9db 100644 --- a/src/virtio.js +++ b/src/virtio.js @@ -11,6 +11,8 @@ function VirtIO(cpu, bus, filesystem) { // http://ozlabs.org/~rusty/virtio-spec/virtio-0.9.5.pdf + this.irq = 10; + this.pci_space = [ 0xf4, 0x1a, 0x09, 0x10, 0x07, 0x05, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xa8, 0x00, 0x00, 0x00, 0x10, 0xbf, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/tests/kvm-unit-tests/run.js b/tests/kvm-unit-tests/run.js index 9ac5b93f..7f9e27b5 100755 --- a/tests/kvm-unit-tests/run.js +++ b/tests/kvm-unit-tests/run.js @@ -33,7 +33,7 @@ var emulator = new V86({ emulator.bus.register("emulator-started", function() { - emulator.v86.cpu.io.register_write_consecutive(0xF4, this, + emulator.v86.cpu.io.register_write_consecutive(0xF4, {}, function(value) { console.log("Test exited with code " + value); From 1dcb5a6f5876e202a3659cd902975dd0ec751a78 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 6 Jul 2017 14:52:22 -0500 Subject: [PATCH 0002/2137] Port cmovcc --- src/browser/starter.js | 2 -- src/native/instructions_0f.c | 4 ++-- src/native/misc_instr.c | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 7aa17b9e..42df0d32 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -202,8 +202,6 @@ function V86Starter(options) "_bswap": function() { return cpu.bswap.apply(cpu, arguments); }, "_setcc": function() { return cpu.setcc.apply(cpu, arguments); }, - "_cmovcc16": function() { return cpu.cmovcc16.apply(cpu, arguments); }, - "_cmovcc32": function() { return cpu.cmovcc32.apply(cpu, arguments); }, "_lar": function() { return cpu.lar.apply(cpu, arguments); }, "_lsl": function() { return cpu.lsl.apply(cpu, arguments); }, diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index ceb70a3a..327f2e0b 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -7,8 +7,8 @@ #include "global_pointers.h" // XXX: Remove these declarations when they are implemented in C -void cmovcc16(bool); -void cmovcc32(bool); +static void cmovcc16(bool); +static void cmovcc32(bool); void jmpcc16(bool); void jmpcc32(bool); void setcc(bool); diff --git a/src/native/misc_instr.c b/src/native/misc_instr.c index 5d4f9ee4..e0f901be 100644 --- a/src/native/misc_instr.c +++ b/src/native/misc_instr.c @@ -149,6 +149,24 @@ void jmpcc32(bool condition) } } +static void cmovcc16(bool condition) +{ + int32_t data = read_e16(); + if(condition) + { + write_g16(data); + } +} + +static void cmovcc32(bool condition) +{ + int32_t data = read_e32s(); + if(condition) + { + write_g32(data); + } +} + static int32_t get_stack_pointer(int32_t offset) { if(*stack_size_32) From cefd1c4978d0da7b40c7541b1385959021d6ffb2 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 6 Jul 2017 15:15:57 -0500 Subject: [PATCH 0003/2137] Port reg_xmm32s --- src/cpu.js | 2 +- src/native/global_pointers.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cpu.js b/src/cpu.js index ee350f91..f93cacb0 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -198,7 +198,7 @@ function CPU(bus, wm) this.reg_mmx8s = new Int8Array(this.reg_mmxs.buffer); this.reg_mmx8 = new Uint8Array(this.reg_mmxs.buffer); - this.reg_xmm32s = new Int32Array(8 * 4); + this.reg_xmm32s = new Int32Array(wm.mem.buffer, 828, 8 * 4); this.mxcsr = new Int32Array(wm.mem.buffer, 824, 1); // segment registers, tr and ldtr diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index 5651a416..5f203c99 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -59,6 +59,8 @@ bool* const paging = (bool* const) 820; bool* const mxcsr = (bool* const) 824; +int32_t* const reg_xmm32s = (int32_t* 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 From 2beb1ae1774efb4ccf3be8a6aabd4934b9b2f83a Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 6 Jul 2017 15:16:50 -0500 Subject: [PATCH 0004/2137] Improve speed of run_instruction --- src/native/cpu.c | 4 ++-- src/native/instructions.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/native/cpu.c b/src/native/cpu.c index 46b45a7e..10e77112 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -344,12 +344,12 @@ void cycle_internal() int32_t opcode = read_imm8(); - run_instruction(opcode); + run_instruction(opcode | !!*is_32 << 8); } static void run_prefix_instruction() { - run_instruction(read_imm8()); + run_instruction(read_imm8() | is_osize_32() << 8); } void clear_prefixes() diff --git a/src/native/instructions.c b/src/native/instructions.c index 9280ec74..46ed09c1 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -1877,7 +1877,7 @@ static void run_instruction(int32_t opcode) { //dbg_log(opcode); // XXX: This table is generated. Don't modify - switch(opcode | is_osize_32() << 8) + switch(opcode) { case 0x00: case 0x00|0x100: From 80abbd87af910154c4537c2840723b6eb05a7bf2 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 6 Jul 2017 15:28:49 -0500 Subject: [PATCH 0005/2137] Fix sizes of some pointers --- src/native/global_pointers.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index 5f203c99..c0ff07e4 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -27,7 +27,7 @@ int32_t* const gdtr_size = (int32_t* const) 572; int32_t* const gdtr_offset = (int32_t* const) 576; int32_t* const cr = (int32_t* const) 580; // length 8 -int32_t* const cpl = (int32_t* const) 612; +uint8_t* const cpl = (uint8_t* const) 612; int32_t* const page_size_extensions = (int32_t* const) 616; int32_t* const last_virt_eip = (int32_t* const) 620; int32_t* const eip_phys = (int32_t* const) 624; @@ -36,7 +36,7 @@ int32_t* const esp_phys = (int32_t* const) 632; int32_t* const sysenter_cs = (int32_t* const) 636; int32_t* const sysenter_esp = (int32_t* const) 640; int32_t* const sysenter_eip = (int32_t* const) 644; -int32_t* const prefixes = (int32_t* const) 648; +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; @@ -45,7 +45,7 @@ int32_t* const timestamp_counter = (int32_t* const) 664; uint16_t* const sreg = (uint16_t* const) 668; int32_t* const dreg = (int32_t* const) 684; // length 8 int32_t* const fw_value = (int32_t* const) 720; -uint8_t* const segment_is_null = (uint8_t* const) 724; // length 8 +bool* const segment_is_null = (bool* const) 724; // length 8 int32_t* const segment_offsets = (int32_t* const) 736; // length 8 uint32_t* const segment_limits = (uint32_t* const) 768; // length 8 @@ -57,7 +57,7 @@ int32_t* const stack_empty = (int32_t* const) 816; bool* const paging = (bool* const) 820; -bool* const mxcsr = (bool* const) 824; +int32_t* const mxcsr = (int32_t* const) 824; int32_t* const reg_xmm32s = (int32_t* const) 828; // length 128 From 02941fd98d8eda36486f2c6c30de3fa72c445398 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 6 Jul 2017 15:49:55 -0500 Subject: [PATCH 0006/2137] Add prefix constants for SSE instructions --- src/native/const.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/native/const.h b/src/native/const.h index b5f8e10f..2b1cc86d 100644 --- a/src/native/const.h +++ b/src/native/const.h @@ -137,6 +137,10 @@ #define PREFIX_MASK_OPSIZE 0b100000 #define PREFIX_MASK_ADDRSIZE 0b1000000 +// aliases +#define PREFIX_F2 PREFIX_REPNZ +#define PREFIX_F3 PREFIX_REPZ +#define PREFIX_66 PREFIX_MASK_OPSIZE /** From dcde1db73ab3ddf48271940520f357130bba25c3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 6 Jul 2017 15:59:45 -0500 Subject: [PATCH 0007/2137] Add stubs for prefixed SSE instructions --- src/native/instructions_0f.c | 123 +++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 327f2e0b..f4e0cc16 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -351,8 +351,11 @@ 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_660F12() { unimplemented_sse(); } static void instr_0F13() { unimplemented_sse(); } +static void instr_660F13() { unimplemented_sse(); } static void instr_0F14() { unimplemented_sse(); } +static void instr_660F14() { unimplemented_sse(); } static void instr_0F15() { unimplemented_sse(); } static void instr_0F16() { unimplemented_sse(); } static void instr_0F17() { unimplemented_sse(); } @@ -526,10 +529,14 @@ static void instr_0F26() { undefined_instruction(); } static void instr_0F27() { undefined_instruction(); } static void instr_0F28() { unimplemented_sse(); } +static void instr_660F28() { unimplemented_sse(); } static void instr_0F29() { unimplemented_sse(); } +static void instr_660F29() { unimplemented_sse(); } static void instr_0F2A() { unimplemented_sse(); } static void instr_0F2B() { unimplemented_sse(); } +static void instr_660F2B() { unimplemented_sse(); } static void instr_0F2C() { unimplemented_sse(); } +static void instr_F20F2C() { unimplemented_sse(); } static void instr_0F2D() { unimplemented_sse(); } static void instr_0F2E() { unimplemented_sse(); } static void instr_0F2F() { unimplemented_sse(); } @@ -844,9 +851,11 @@ static void instr_0F51() { unimplemented_sse(); } static void instr_0F52() { unimplemented_sse(); } static void instr_0F53() { unimplemented_sse(); } static void instr_0F54() { unimplemented_sse(); } +static void instr_660F54() { unimplemented_sse(); } static void instr_0F55() { unimplemented_sse(); } static void instr_0F56() { unimplemented_sse(); } static void instr_0F57() { unimplemented_sse(); } +static void instr_660F57() { unimplemented_sse(); } static void instr_0F58() { unimplemented_sse(); } static void instr_0F59() { unimplemented_sse(); } @@ -858,30 +867,44 @@ static void instr_0F5E() { unimplemented_sse(); } static void instr_0F5F() { unimplemented_sse(); } static void instr_0F60() { unimplemented_sse(); } +static void instr_660F60() { unimplemented_sse(); } static void instr_0F61() { unimplemented_sse(); } +static void instr_660F61() { unimplemented_sse(); } static void instr_0F62() { unimplemented_sse(); } static void instr_0F63() { unimplemented_sse(); } static void instr_0F64() { unimplemented_sse(); } static void instr_0F65() { unimplemented_sse(); } static void instr_0F66() { unimplemented_sse(); } static void instr_0F67() { unimplemented_sse(); } +static void instr_660F67() { unimplemented_sse(); } static void instr_0F68() { unimplemented_sse(); } +static void instr_660F68() { unimplemented_sse(); } static void instr_0F69() { unimplemented_sse(); } static void instr_0F6A() { unimplemented_sse(); } static void instr_0F6B() { unimplemented_sse(); } static void instr_0F6C() { unimplemented_sse(); } static void instr_0F6D() { unimplemented_sse(); } static void instr_0F6E() { unimplemented_sse(); } +static void instr_660F6E() { unimplemented_sse(); } static void instr_0F6F() { unimplemented_sse(); } +static void instr_660F6F() { unimplemented_sse(); } +static void instr_F30F6F() { unimplemented_sse(); } static void instr_0F70() { unimplemented_sse(); } +static void instr_660F70() { unimplemented_sse(); } +static void instr_F20F70() { unimplemented_sse(); } +static void instr_F30F70() { unimplemented_sse(); } static void instr_0F71() { unimplemented_sse(); } static void instr_0F72() { unimplemented_sse(); } static void instr_0F73() { unimplemented_sse(); } +static void instr_660F73() { unimplemented_sse(); } static void instr_0F74() { unimplemented_sse(); } +static void instr_660F74() { unimplemented_sse(); } static void instr_0F75() { unimplemented_sse(); } +static void instr_660F75() { unimplemented_sse(); } static void instr_0F76() { unimplemented_sse(); } +static void instr_660F76() { unimplemented_sse(); } static void instr_0F77() { // emms dbg_assert((*prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) == 0); @@ -905,7 +928,11 @@ static void instr_0F7B() { unimplemented_sse(); } static void instr_0F7C() { unimplemented_sse(); } static void instr_0F7D() { unimplemented_sse(); } static void instr_0F7E() { unimplemented_sse(); } +static void instr_660F7E() { unimplemented_sse(); } +static void instr_F30F7E() { unimplemented_sse(); } static void instr_0F7F() { unimplemented_sse(); } +static void instr_660F7F() { unimplemented_sse(); } +static void instr_F30F7F() { unimplemented_sse(); } // jmpcc static void instr16_0F80() { jmpcc16( test_o()); } @@ -1457,6 +1484,7 @@ static void instr_0FC2() { unimplemented_sse(); } static void instr_0FC3() { unimplemented_sse(); } static void instr_0FC4() { unimplemented_sse(); } static void instr_0FC5() { unimplemented_sse(); } +static void instr_660FC5() { unimplemented_sse(); } static void instr_0FC6() { unimplemented_sse(); } static void instr_0FC7() { @@ -1544,18 +1572,26 @@ static void instr_0FD0() { unimplemented_sse(); } static void instr_0FD1() { unimplemented_sse(); } static void instr_0FD2() { unimplemented_sse(); } static void instr_0FD3() { unimplemented_sse(); } +static void instr_660FD3() { unimplemented_sse(); } static void instr_0FD4() { unimplemented_sse(); } static void instr_0FD5() { unimplemented_sse(); } +static void instr_660FD5() { unimplemented_sse(); } static void instr_0FD6() { unimplemented_sse(); } +static void instr_660FD6() { unimplemented_sse(); } static void instr_0FD7() { unimplemented_sse(); } +static void instr_660FD7() { unimplemented_sse(); } static void instr_0FD8() { unimplemented_sse(); } static void instr_0FD9() { unimplemented_sse(); } static void instr_0FDA() { unimplemented_sse(); } +static void instr_660FDA() { unimplemented_sse(); } static void instr_0FDB() { unimplemented_sse(); } static void instr_0FDC() { unimplemented_sse(); } +static void instr_660FDC() { unimplemented_sse(); } static void instr_0FDD() { unimplemented_sse(); } +static void instr_660FDD() { unimplemented_sse(); } static void instr_0FDE() { unimplemented_sse(); } +static void instr_660FDE() { unimplemented_sse(); } static void instr_0FDF() { unimplemented_sse(); } static void instr_0FE0() { unimplemented_sse(); } @@ -1563,18 +1599,22 @@ static void instr_0FE1() { unimplemented_sse(); } static void instr_0FE2() { unimplemented_sse(); } static void instr_0FE3() { unimplemented_sse(); } static void instr_0FE4() { unimplemented_sse(); } +static void instr_660FE4() { unimplemented_sse(); } static void instr_0FE5() { unimplemented_sse(); } static void instr_0FE6() { unimplemented_sse(); } static void instr_0FE7() { unimplemented_sse(); } +static void instr_660FE7() { unimplemented_sse(); } static void instr_0FE8() { unimplemented_sse(); } static void instr_0FE9() { unimplemented_sse(); } static void instr_0FEA() { unimplemented_sse(); } static void instr_0FEB() { unimplemented_sse(); } +static void instr_660FEB() { unimplemented_sse(); } static void instr_0FEC() { unimplemented_sse(); } static void instr_0FED() { unimplemented_sse(); } static void instr_0FEE() { unimplemented_sse(); } static void instr_0FEF() { unimplemented_sse(); } +static void instr_660FEF() { unimplemented_sse(); } static void instr_0FF0() { unimplemented_sse(); } static void instr_0FF1() { unimplemented_sse(); } @@ -1588,6 +1628,7 @@ static void instr_0FF7() { unimplemented_sse(); } static void instr_0FF8() { unimplemented_sse(); } static void instr_0FF9() { unimplemented_sse(); } static void instr_0FFA() { unimplemented_sse(); } +static void instr_660FFA() { unimplemented_sse(); } static void instr_0FFB() { unimplemented_sse(); } static void instr_0FFC() { unimplemented_sse(); } static void instr_0FFD() { unimplemented_sse(); } @@ -1660,12 +1701,15 @@ 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: @@ -1726,18 +1770,22 @@ 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: @@ -1858,6 +1906,7 @@ case 0x53: instr_0F53(); break; case 0x54: + (*prefixes & PREFIX_66) ? instr_660F54() : instr_0F54(); break; case 0x55: @@ -1867,6 +1916,7 @@ case 0x56: instr_0F56(); break; case 0x57: + (*prefixes & PREFIX_66) ? instr_660F57() : instr_0F57(); break; case 0x58: @@ -1894,9 +1944,11 @@ 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: @@ -1915,9 +1967,11 @@ 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: @@ -1936,12 +1990,18 @@ 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: @@ -1951,15 +2011,19 @@ 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: @@ -1984,9 +2048,13 @@ 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: @@ -2197,6 +2265,7 @@ case 0xC4: instr_0FC4(); break; case 0xC5: + (*prefixes & PREFIX_66) ? instr_660FC5() : instr_0FC5(); break; case 0xC6: @@ -2239,18 +2308,22 @@ 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: @@ -2260,18 +2333,22 @@ 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: @@ -2290,6 +2367,7 @@ case 0xE3: instr_0FE3(); break; case 0xE4: + (*prefixes & PREFIX_66) ? instr_660FE4() : instr_0FE4(); break; case 0xE5: @@ -2299,6 +2377,7 @@ case 0xE6: instr_0FE6(); break; case 0xE7: + (*prefixes & PREFIX_66) ? instr_660FE7() : instr_0FE7(); break; case 0xE8: @@ -2311,6 +2390,7 @@ case 0xEA: instr_0FEA(); break; case 0xEB: + (*prefixes & PREFIX_66) ? instr_660FEB() : instr_0FEB(); break; case 0xEC: @@ -2323,6 +2403,7 @@ case 0xEE: instr_0FEE(); break; case 0xEF: + (*prefixes & PREFIX_66) ? instr_660FEF() : instr_0FEF(); break; case 0xF0: @@ -2356,6 +2437,7 @@ case 0xF9: instr_0FF9(); break; case 0xFA: + (*prefixes & PREFIX_66) ? instr_660FFA() : instr_0FFA(); break; case 0xFB: @@ -2437,12 +2519,15 @@ 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: @@ -2503,18 +2588,22 @@ 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: @@ -2635,6 +2724,7 @@ case 0x53: instr_0F53(); break; case 0x54: + (*prefixes & PREFIX_66) ? instr_660F54() : instr_0F54(); break; case 0x55: @@ -2644,6 +2734,7 @@ case 0x56: instr_0F56(); break; case 0x57: + (*prefixes & PREFIX_66) ? instr_660F57() : instr_0F57(); break; case 0x58: @@ -2671,9 +2762,11 @@ 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: @@ -2692,9 +2785,11 @@ 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: @@ -2713,12 +2808,18 @@ 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: @@ -2728,15 +2829,19 @@ 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: @@ -2761,9 +2866,13 @@ 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: @@ -2974,6 +3083,7 @@ case 0xC4: instr_0FC4(); break; case 0xC5: + (*prefixes & PREFIX_66) ? instr_660FC5() : instr_0FC5(); break; case 0xC6: @@ -3016,18 +3126,22 @@ 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: @@ -3037,18 +3151,22 @@ 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: @@ -3067,6 +3185,7 @@ case 0xE3: instr_0FE3(); break; case 0xE4: + (*prefixes & PREFIX_66) ? instr_660FE4() : instr_0FE4(); break; case 0xE5: @@ -3076,6 +3195,7 @@ case 0xE6: instr_0FE6(); break; case 0xE7: + (*prefixes & PREFIX_66) ? instr_660FE7() : instr_0FE7(); break; case 0xE8: @@ -3088,6 +3208,7 @@ case 0xEA: instr_0FEA(); break; case 0xEB: + (*prefixes & PREFIX_66) ? instr_660FEB() : instr_0FEB(); break; case 0xEC: @@ -3100,6 +3221,7 @@ case 0xEE: instr_0FEE(); break; case 0xEF: + (*prefixes & PREFIX_66) ? instr_660FEF() : instr_0FEF(); break; case 0xF0: @@ -3133,6 +3255,7 @@ case 0xF9: instr_0FF9(); break; case 0xFA: + (*prefixes & PREFIX_66) ? instr_660FFA() : instr_0FFA(); break; case 0xFB: From 42351c527a5c5b4373ec6c443d1457b0f98e2c54 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 6 Jul 2017 17:13:25 -0500 Subject: [PATCH 0008/2137] Port clear_tlb --- src/browser/starter.js | 1 - src/native/cpu.c | 8 ++++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 42df0d32..1879b7c6 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -215,7 +215,6 @@ function V86Starter(options) "_cpl_changed": function() { return cpu.cpl_changed.apply(cpu, arguments); }, "_set_cr0": function() { return cpu.set_cr0.apply(cpu, arguments); }, "_update_cs_size": function() { return cpu.update_cs_size.apply(cpu, arguments); }, - "_clear_tlb": function() { return cpu.clear_tlb.apply(cpu, arguments); }, "_cpuid": function() { return cpu.cpuid.apply(cpu, arguments); }, "_load_ldt": function() { return cpu.load_ldt.apply(cpu, arguments); }, diff --git a/src/native/cpu.c b/src/native/cpu.c index 10e77112..ccee51d8 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -570,3 +570,11 @@ void write_e32(int32_t value) reg32s[*modrm_byte & 7] = value; } } + +void clear_tlb() +{ + for(int32_t i = 0; i < 0x100000; i += 4) + { + *(int32_t*)(tlb_info + i) = *(int32_t*)(tlb_info_global + i); + } +} From b881360e8af9d6c7792e52df1ef6e37446215de6 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 7 Jul 2017 17:11:19 -0500 Subject: [PATCH 0009/2137] Increase wasm memory size and reserve more space for static memory --- src/browser/lib.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/browser/lib.js b/src/browser/lib.js index 14c08b03..6a368a73 100644 --- a/src/browser/lib.js +++ b/src/browser/lib.js @@ -22,7 +22,11 @@ var ASYNC_SAFE = false; if (!imports) { imports = {}; } - const STATIC_MEMORY_BASE = 64 * 1024 * 1024; // XXX + + // XXX: These should not be fixed + // in M + const STATIC_MEMORY_BASE = 256 - 32; + const WASM_MEMORY_SIZE = 256; v86util.load_file(filename, { done: function(buffer) { @@ -35,9 +39,9 @@ var ASYNC_SAFE = false; console.error('Assertion Failed', a, b, c, d); dbg_assert(false); }; - imports['env']['memoryBase'] = STATIC_MEMORY_BASE; + imports['env']['memoryBase'] = STATIC_MEMORY_BASE * 1024 * 1024; imports['env']['tableBase'] = 0; - imports['env']['memory'] = new WebAssembly.Memory({ ['initial']: 4096, }); + 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 })); }) From 54d52ed908fea33ae537d0c50a512d7a65cb1ca1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 7 Jul 2017 17:11:39 -0500 Subject: [PATCH 0010/2137] Call __post_instantiate --- src/browser/starter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/browser/starter.js b/src/browser/starter.js index 1879b7c6..4fe12275 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -270,6 +270,7 @@ function V86Starter(options) let wasm_file = DEBUG ? "v86-debug.wasm" : "v86.wasm"; v86util.load_wasm("build/" + wasm_file, { 'env': wasm_shared_funcs }, wm => { + wm.instance.exports["__post_instantiate"](); emulator = this.v86 = new v86(this.emulator_bus, wm); cpu = emulator.cpu; mem = wm.mem.buffer; From b4f2faf795919481d499d6d6cfff3864590923c1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 7 Jul 2017 17:12:27 -0500 Subject: [PATCH 0011/2137] Port task_switch_test_mmx --- src/native/cpu.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/native/cpu.c b/src/native/cpu.c index ccee51d8..1d48cb3b 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -25,6 +25,8 @@ void virt_boundary_write16(int32_t, int32_t, int32_t); void virt_boundary_write32(int32_t, int32_t, int32_t); void trigger_gp(int32_t); +void trigger_ud(); +void trigger_nm(); int32_t safe_read8(int32_t); int32_t safe_read16(int32_t); @@ -578,3 +580,18 @@ void clear_tlb() *(int32_t*)(tlb_info + i) = *(int32_t*)(tlb_info_global + i); } } + +void task_switch_test_mmx() +{ + if(*cr & (CR0_EM | CR0_TS)) + { + if(*cr & CR0_TS) + { + trigger_nm(); + } + else + { + trigger_ud(); + } + } +} From 0cbdaa12024940f37be627beb95f48071aea6515 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 7 Jul 2017 17:17:03 -0500 Subject: [PATCH 0012/2137] Add reg64 and reg128 types --- src/native/global_pointers.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index c0ff07e4..9e424fe5 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -59,7 +59,20 @@ 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 { + uint8_t u8[8]; + uint16_t u16[4]; + uint32_t u32[2]; +}; + 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 From 2330b8d1a8bfcc78946453d12edd60aa0f2707f7 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 7 Jul 2017 17:17:59 -0500 Subject: [PATCH 0013/2137] Port helper functions for SSE instructions --- src/native/cpu.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/src/native/cpu.c b/src/native/cpu.c index 1d48cb3b..5fc7e8c0 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -11,6 +11,7 @@ int32_t read_e8_partial_branch() { return reg8[*modrm_byte << 2 & 0xC | *modrm_byte >> 2 & 1]; } +void writable_or_pagefault(int32_t, int32_t); int32_t translate_address_read(int32_t); int32_t translate_address_write(int32_t); int32_t read8(uint32_t); @@ -428,6 +429,54 @@ int32_t safe_read32s(int32_t addr) } } +union reg64 safe_read64s(int32_t addr) +{ + union reg64 x; + if((addr & 0xFFF) >= 0xFF9) + { + x.u32[0] = safe_read32s(addr); + x.u32[1] = safe_read32s(addr + 4); + } + else + { + int32_t addr_phys = translate_address_read(addr); + x.u32[0] = read32s(addr_phys); + x.u32[1] = read32s(addr_phys + 4); + } + return x; +} + +union reg128 safe_read128s(int32_t addr) +{ + union reg128 x; + if((addr & 0xFFF) >= 0xFF1) + { + x.u32[0] = safe_read32s(addr); + x.u32[1] = safe_read32s(addr + 4); + x.u32[2] = safe_read32s(addr + 8); + x.u32[3] = safe_read32s(addr + 12); + } + 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); + } + return x; +} + +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); @@ -573,6 +622,69 @@ void write_e32(int32_t value) } } +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_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; +} + void clear_tlb() { for(int32_t i = 0; i < 0x100000; i += 4) From afba8c9f171468088879b69384751c788779cbfd Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 7 Jul 2017 17:18:32 -0500 Subject: [PATCH 0014/2137] Port a few SSE instructions --- src/native/instructions_0f.c | 135 ++++++++++++++++++++++++++++++++--- 1 file changed, 124 insertions(+), 11 deletions(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index f4e0cc16..53caf530 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -530,7 +530,16 @@ static void instr_0F27() { undefined_instruction(); } static void instr_0F28() { unimplemented_sse(); } static void instr_660F28() { unimplemented_sse(); } -static void instr_0F29() { unimplemented_sse(); } +static void instr_0F29() { + // movaps 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); +} static void instr_660F29() { unimplemented_sse(); } static void instr_0F2A() { unimplemented_sse(); } static void instr_0F2B() { unimplemented_sse(); } @@ -867,7 +876,19 @@ static void instr_0F5E() { unimplemented_sse(); } static void instr_0F5F() { unimplemented_sse(); } static void instr_0F60() { unimplemented_sse(); } -static void instr_660F60() { unimplemented_sse(); } +void instr_660F60() { + // punpcklbw xmm, xmm/m128 + task_switch_test_mmx(); + read_modrm_byte(); + union reg64 source = read_xmm_mem64s(); + union reg64 destination = read_xmm64s(); + write_xmm128s( + 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 + ); +} static void instr_0F61() { unimplemented_sse(); } static void instr_660F61() { unimplemented_sse(); } static void instr_0F62() { unimplemented_sse(); } @@ -886,13 +907,44 @@ static void instr_0F6B() { unimplemented_sse(); } static void instr_0F6C() { unimplemented_sse(); } static void instr_0F6D() { unimplemented_sse(); } static void instr_0F6E() { unimplemented_sse(); } -static void instr_660F6E() { unimplemented_sse(); } +static void instr_660F6E() { + // movd mm, r/m32 + task_switch_test_mmx(); + read_modrm_byte(); + int32_t data = read_e32s(); + write_xmm128s(data, 0, 0, 0); +} static void instr_0F6F() { unimplemented_sse(); } -static void instr_660F6F() { unimplemented_sse(); } -static void instr_F30F6F() { unimplemented_sse(); } +static void instr_660F6F() { + // movdqa xmm, xmm/mem128 + 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]); +} +static void instr_F30F6F() { + // 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]); +} static void instr_0F70() { unimplemented_sse(); } -static void instr_660F70() { unimplemented_sse(); } +static void instr_660F70() { + // 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] + ); +} static void instr_F20F70() { unimplemented_sse(); } static void instr_F30F70() { unimplemented_sse(); } static void instr_0F71() { unimplemented_sse(); } @@ -900,7 +952,23 @@ static void instr_0F72() { unimplemented_sse(); } static void instr_0F73() { unimplemented_sse(); } static void instr_660F73() { unimplemented_sse(); } static void instr_0F74() { unimplemented_sse(); } -static void instr_660F74() { unimplemented_sse(); } +static void instr_660F74() { + // pcmpeqb xmm, xmm/m128 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg128 source = read_xmm_mem128s(); + union reg128 destination = read_xmm128s(); + + union reg128 result; + + for(int32_t i = 0; i < 16; i++) + { + 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]); +} static void instr_0F75() { unimplemented_sse(); } static void instr_660F75() { unimplemented_sse(); } static void instr_0F76() { unimplemented_sse(); } @@ -931,7 +999,15 @@ static void instr_0F7E() { unimplemented_sse(); } static void instr_660F7E() { unimplemented_sse(); } static void instr_F30F7E() { unimplemented_sse(); } static void instr_0F7F() { unimplemented_sse(); } -static void instr_660F7F() { unimplemented_sse(); } +static void instr_660F7F() { + // 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); +} static void instr_F30F7F() { unimplemented_sse(); } // jmpcc @@ -1579,7 +1655,20 @@ static void instr_660FD5() { unimplemented_sse(); } static void instr_0FD6() { unimplemented_sse(); } static void instr_660FD6() { unimplemented_sse(); } static void instr_0FD7() { unimplemented_sse(); } -static void instr_660FD7() { unimplemented_sse(); } +static void instr_660FD7() { + // pmovmskb reg, xmm + task_switch_test_mmx(); + read_modrm_byte(); + if(*modrm_byte < 0xC0) trigger_ud(); + + union reg128 x = read_xmm_mem128s(); + 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); +} static void instr_0FD8() { unimplemented_sse(); } static void instr_0FD9() { unimplemented_sse(); } @@ -1603,7 +1692,17 @@ static void instr_660FE4() { unimplemented_sse(); } static void instr_0FE5() { unimplemented_sse(); } static void instr_0FE6() { unimplemented_sse(); } static void instr_0FE7() { unimplemented_sse(); } -static void instr_660FE7() { unimplemented_sse(); } +static void instr_660FE7() { + // 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); + safe_write128(addr, data); +} static void instr_0FE8() { unimplemented_sse(); } static void instr_0FE9() { unimplemented_sse(); } @@ -1614,7 +1713,21 @@ static void instr_0FEC() { unimplemented_sse(); } static void instr_0FED() { unimplemented_sse(); } static void instr_0FEE() { unimplemented_sse(); } static void instr_0FEF() { unimplemented_sse(); } -static void instr_660FEF() { unimplemented_sse(); } +static void instr_660FEF() { + // pxor xmm, xmm/m128 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg128 source = read_xmm_mem128s(); + union reg128 destination = read_xmm128s(); + + write_xmm128s( + source.u32[0] ^ destination.u32[0], + source.u32[1] ^ destination.u32[1], + source.u32[2] ^ destination.u32[2], + source.u32[3] ^ destination.u32[3] + ); +} static void instr_0FF0() { unimplemented_sse(); } static void instr_0FF1() { unimplemented_sse(); } From 403ff43c25a59098677f6807f022a00b88397d01 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 7 Jul 2017 17:21:01 -0500 Subject: [PATCH 0015/2137] Fix nasm tests, add support for testing general purpose registers, eflags and xmm registers --- tests/nasm/gdbauto | 74 ++++++++++++++++++++++++++++++++----- tests/nasm/header.inc | 17 +++++++++ tests/nasm/run.js | 86 +++++++++++++++++++++++++++++++++++++------ 3 files changed, 155 insertions(+), 22 deletions(-) diff --git a/tests/nasm/gdbauto b/tests/nasm/gdbauto index 3b663b60..d7fec0e6 100644 --- a/tests/nasm/gdbauto +++ b/tests/nasm/gdbauto @@ -1,9 +1,20 @@ # Invocation: gdb -x gdbauto xyz.bin -start -until loop + +break loop +run printf "---BEGIN JSON---\n" printf "[\n" +printf " %d,\n", $eax +printf " %d,\n", $ecx +printf " %d,\n", $edx +printf " %d,\n", $ebx +printf " %d,\n", $esp +printf " %d,\n", $ebp +printf " %d,\n", $esi +printf " %d,\n", $edi +printf " \n" + printf " %d,\n", $mm0.v2_int32[0] printf " %d,\n", $mm0.v2_int32[1] printf " %d,\n", $mm1.v2_int32[0] @@ -14,14 +25,57 @@ printf " %d,\n", $mm3.v2_int32[0] printf " %d,\n", $mm3.v2_int32[1] printf " %d,\n", $mm4.v2_int32[0] printf " %d,\n", $mm4.v2_int32[1] -printf " %d,\n", $mm5.v2_int32[0] -printf " %d,\n", $mm5.v2_int32[1] -printf " %d,\n", $mm6.v2_int32[0] -printf " %d,\n", $mm6.v2_int32[1] -printf " %d,\n", $mm7.v2_int32[0] -printf " %d\n", $mm7.v2_int32[1] +printf " %d,\n", $mm5.v2_int32[0] +printf " %d,\n", $mm5.v2_int32[1] +printf " %d,\n", $mm6.v2_int32[0] +printf " %d,\n", $mm6.v2_int32[1] +printf " %d,\n", $mm7.v2_int32[0] +printf " %d,\n", $mm7.v2_int32[1] +printf " \n" + +printf " %d,\n", $xmm0.v4_int32[0] +printf " %d,\n", $xmm0.v4_int32[1] +printf " %d,\n", $xmm0.v4_int32[2] +printf " %d,\n", $xmm0.v4_int32[3] +printf " %d,\n", $xmm1.v4_int32[0] +printf " %d,\n", $xmm1.v4_int32[1] +printf " %d,\n", $xmm1.v4_int32[2] +printf " %d,\n", $xmm1.v4_int32[3] +printf " %d,\n", $xmm2.v4_int32[0] +printf " %d,\n", $xmm2.v4_int32[1] +printf " %d,\n", $xmm2.v4_int32[2] +printf " %d,\n", $xmm2.v4_int32[3] +printf " %d,\n", $xmm3.v4_int32[0] +printf " %d,\n", $xmm3.v4_int32[1] +printf " %d,\n", $xmm3.v4_int32[2] +printf " %d,\n", $xmm3.v4_int32[3] +printf " %d,\n", $xmm4.v4_int32[0] +printf " %d,\n", $xmm4.v4_int32[1] +printf " %d,\n", $xmm4.v4_int32[2] +printf " %d,\n", $xmm4.v4_int32[3] +printf " %d,\n", $xmm5.v4_int32[0] +printf " %d,\n", $xmm5.v4_int32[1] +printf " %d,\n", $xmm5.v4_int32[2] +printf " %d,\n", $xmm5.v4_int32[3] +printf " %d,\n", $xmm6.v4_int32[0] +printf " %d,\n", $xmm6.v4_int32[1] +printf " %d,\n", $xmm6.v4_int32[2] +printf " %d,\n", $xmm6.v4_int32[3] +printf " %d,\n", $xmm7.v4_int32[0] +printf " %d,\n", $xmm7.v4_int32[1] +printf " %d,\n", $xmm7.v4_int32[2] +printf " %d,\n", $xmm7.v4_int32[3] +printf " \n" + +printf " %d,\n", *(int*)($esp+0) +printf " %d,\n", *(int*)($esp+4) +printf " %d,\n", *(int*)($esp+8) +printf " %d,\n", *(int*)($esp+12) +printf " \n" + +printf " %d\n", $eflags + printf "]\n" printf "---END JSON---\n" -continue -quit \ No newline at end of file +quit diff --git a/tests/nasm/header.inc b/tests/nasm/header.inc index 303dd74f..ea8aa302 100644 --- a/tests/nasm/header.inc +++ b/tests/nasm/header.inc @@ -13,3 +13,20 @@ section .text _start: main: + xor eax, eax + xor ecx, ecx + xor edx, edx + xor ebx, ebx + ; xor esp, esp + xor ebp, ebp + xor esi, esi + xor edi, edi + + ; make space for memory operations + %rep 8 + sub esp, 4 + mov dword [esp], 0 + %endrep + + push 0 + popf diff --git a/tests/nasm/run.js b/tests/nasm/run.js index 00e10f5c..1249e582 100755 --- a/tests/nasm/run.js +++ b/tests/nasm/run.js @@ -50,11 +50,16 @@ function h(n, len) if (cluster.isMaster) { - function extract_json(fixture_text) { + function extract_json(name, fixture_text) { + if(fixture_text.includes("Program received signal") || fixture_text.includes("SIGILL")) + { + throw new Error("Test was killed during execution by gdb: " + name); + } + const json_regex = /---BEGIN JSON---([\s\[\]\w":\-,]*)---END JSON---/; const regex_match = json_regex.exec(fixture_text); if (!regex_match || regex_match.length < 2) { - throw new Error('Could not find JSON in fixture text: ' + fixture_text); + throw new Error('Could not find JSON in fixture text: ' + fixture_text + "\nTest: " + name); } try { @@ -72,7 +77,7 @@ if (cluster.isMaster) { let fixture_name = name + ".fixture"; let img_name = name + ".img"; let fixture_text = fs.readFileSync(TEST_DIR + fixture_name); - let fixture_array = extract_json(fixture_text); + let fixture_array = extract_json(name, fixture_text); worker.send({ img_name: img_name, @@ -146,10 +151,13 @@ if (cluster.isMaster) { if (failed_tests.length > 0) { console.log('[-] Failed %d test(s).', failed_tests.length); failed_tests.forEach(function(test_failure) { + console.error('\n[-] %s:', test_failure.img_name); test_failure.failures.forEach(function(individual_failure) { - console.error(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)); }); }); process.exit(1); @@ -167,23 +175,77 @@ else { autostart: false }); - emulator.v86.cpu.debug.show = () => {}; + //emulator.v86.cpu.debug.show = () => {}; emulator.bus.register('cpu-event-halt', function() { + var cpu = emulator.v86.cpu; + const filename = TEST_DIR + test.img_name; - const evaluated_mmxs = this.cpu.reg_mmxs; + const evaluated_mmxs = cpu.reg_mmxs; + const evaluated_xmms = cpu.reg_xmm32s; + const esp = cpu.reg32s[4]; + const evaluated_memory = cpu.mem32s.slice(esp >> 2, esp + 16 >> 2); let individual_failures = []; - for (let i = 0; i < evaluated_mmxs.length; i++) { - if (evaluated_mmxs[i] !== test.fixture_array[i]) { + let offset = 0; + const expected_reg32s = test.fixture_array.slice(offset, offset += 8); + const expected_mmx_registers = test.fixture_array.slice(offset, offset += 16); + const expected_xmm_registers = test.fixture_array.slice(offset, offset += 32); + const expected_memory = test.fixture_array.slice(offset, offset += 4); + const expected_eflags = test.fixture_array[offset] & MASK_ARITH; + + for (let i = 0; i < cpu.reg32s.length; i++) { + if(i === 4) continue; // TODO: Same stack for elf and multiboot + let reg = cpu.reg32s[i]; + if (reg !== expected_reg32s[i]) { individual_failures.push({ - index: i, - actual: evaluated_mmxs[i], - expected: test.fixture_array[i] + name: "cpu.reg32s[" + i + "]", + expected: expected_reg32s[i], + actual: reg, }); } } + for (let i = 0; i < evaluated_mmxs.length; i++) { + if (evaluated_mmxs[i] !== expected_mmx_registers[i]) { + individual_failures.push({ + name: "mm" + (i >> 1) + ".int32[" + (i & 1) + "] (cpu.reg_mmx[" + i + "])", + expected: expected_mmx_registers[i], + actual: evaluated_mmxs[i], + }); + } + } + + for (let i = 0; i < evaluated_xmms.length; i++) { + if (evaluated_xmms[i] !== expected_xmm_registers[i]) { + individual_failures.push({ + name: "xmm" + (i >> 2) + ".int32[" + (i & 3) + "] (cpu.reg_xmm[" + i + "])", + expected: expected_xmm_registers[i], + actual: evaluated_xmms[i], + }); + } + } + + for (let i = 0; i < evaluated_memory.length; i++) { + if (evaluated_memory[i] !== expected_memory[i]) { + individual_failures.push({ + name: "mem[" + i + "]", + expected: expected_memory[i], + actual: evaluated_memory[i], + }); + } + } + + const seen_eflags = cpu.get_eflags() & MASK_ARITH; + if(seen_eflags !== expected_eflags) + { + individual_failures.push({ + name: "eflags", + expected: expected_eflags, + actual: seen_eflags, + }); + } + if (individual_failures.length > 0) { done({ failures: individual_failures, @@ -194,7 +256,7 @@ else { done(); } - }, emulator.v86); + }); emulator.bus.register('emulator-ready', function() { try { From 5b8296b0fd589c0537931c1bf7c12143574dc8bc Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 7 Jul 2017 17:30:58 -0500 Subject: [PATCH 0016/2137] Add nasm test generation script --- tests/nasm/Makefile | 2 +- tests/nasm/create_tests.js | 914 +++++++++++++++++++++++++++++++++++++ 2 files changed, 915 insertions(+), 1 deletion(-) create mode 100755 tests/nasm/create_tests.js diff --git a/tests/nasm/Makefile b/tests/nasm/Makefile index b8a1f20e..11171dda 100644 --- a/tests/nasm/Makefile +++ b/tests/nasm/Makefile @@ -19,4 +19,4 @@ all: $(host_executables) $(v86_executables) $(host_fixtures) nasm -felf32 -o $@.o $<; ld -g $@.o -m elf_i386 --section-start=.text=0x8000 -o $@ clean: - rm -f *.o *.bin *.img *.fixture + rm -f *.o *.bin *.img *.fixture gen_*.asm diff --git a/tests/nasm/create_tests.js b/tests/nasm/create_tests.js new file mode 100755 index 00000000..6aaee8d1 --- /dev/null +++ b/tests/nasm/create_tests.js @@ -0,0 +1,914 @@ +#!/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) +// - memory tests +// - multiple random tests +// - 16 bit +// - describe which registers are written and read + +const fs = require("fs"); + +const zf = 1 << 6; +const of = 1 << 11; +const cf = 1 << 0; +const af = 1 << 4; + + +// 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, skip: 1, }, + { opcode: 0x3E, prefix: 1, }, + { opcode: 0x3F, skip: 1, }, + + { opcode: 0x40, os: 1, }, + { opcode: 0x41, os: 1, }, + { opcode: 0x42, os: 1, }, + { opcode: 0x43, os: 1, }, + { opcode: 0x44, os: 1, skip: 1, }, // inc esp + { 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, skip: 1, }, // dec esp + { 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, skip: 1, }, // push esp + { 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, skip: 1, }, // pop esp + { opcode: 0x5D, os: 1, }, + { opcode: 0x5E, os: 1, }, + { opcode: 0x5F, os: 1, }, + + { opcode: 0x60, os: 1, skip: 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: 0, }, // zf? + { opcode: 0x6A, os: 1, imm8: 1, }, + { opcode: 0x6B, os: 1, e: 1, g: 1, imm8: 1, mask_flags: 0, }, // 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, skip: 1, }, // lea + { opcode: 0x8E, e: 1, g: 1, skip: 1, }, + { opcode: 0x8F, os: 1, e: 1, g: 1, }, + + { opcode: 0x90, }, + { opcode: 0x91, os: 1, }, + { opcode: 0x92, os: 1, }, + { opcode: 0x93, os: 1, }, + { opcode: 0x94, os: 1, skip: 1, }, // xchg eax, esp + { opcode: 0x95, os: 1, }, + { opcode: 0x96, os: 1, }, + { opcode: 0x97, os: 1, }, + + { opcode: 0x98, os: 1, }, + { opcode: 0x99, os: 1, }, + { opcode: 0x9A, os: 1, imm3248: 1, skip: 1, }, + { opcode: 0x9B, skip: 1, }, + { opcode: 0x9C, os: 1, skip: 1, }, + { opcode: 0x9D, os: 1, skip: 1, }, + { opcode: 0x9E, }, + { opcode: 0x9F, }, + + { opcode: 0xA0, immaddr: 1, skip: 1, }, + { opcode: 0xA1, os: 1, immaddr: 1, skip: 1, }, + { opcode: 0xA2, immaddr: 1, skip: 1, }, + { opcode: 0xA3, os: 1, immaddr: 1, skip: 1, }, + + { opcode: 0xA4, skip: 1, }, + { opcode: 0xA5, os: 1, skip: 1, }, + { opcode: 0xA6, skip: 1, }, + { opcode: 0xA7, os: 1, skip: 1, }, + + { opcode: 0xA8, imm: 1, }, + { opcode: 0xA9, os: 1, imm: 1, }, + + { opcode: 0xAA, skip: 1, }, + { opcode: 0xAB, os: 1, skip: 1, }, + { opcode: 0xAC, skip: 1, }, + { opcode: 0xAD, os: 1, skip: 1, }, + { opcode: 0xAE, skip: 1, }, + { opcode: 0xAF, os: 1, skip: 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, g: 1, imm: 1, }, + { opcode: 0xC7, os: 1, e: 1, g: 1, imm: 1, }, + + { opcode: 0xC8, os: 1, imm24: 1, skip: 1, }, // enter + { opcode: 0xC9, os: 1, skip: 1, }, + { 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, }, + { 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, imm: 1, skip: 1, }, + { opcode: 0xE9, os: 1, imm: 1, skip: 1, }, + { opcode: 0xEA, os: 1, imm: 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: zf, }, + { opcode: 0xF6, fixed_g: 5, mask_flags: zf, }, + //{ opcode: 0xF6, fixed_g: 6, }, // zero divide + //{ opcode: 0xF6, fixed_g: 7, }, + + { 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, }, + { opcode: 0xF7, os: 1, fixed_g: 5, mask_flags: zf, }, + //{ opcode: 0xF7, os: 1, fixed_g: 6, }, // zero divide + //{ 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, 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, is_32: 1, e: 1, g: 1, }, // bsf + { opcode: 0x0FBD, os: 1, is_32: 1, e: 1, g: 1, }, + + // note: overflow flag only undefined if shift is > 1 + { opcode: 0x0FA4, os: 1, is_32: 1, e: 1, g: 1, imm8: 1, mask_flags: of, }, // shld + { opcode: 0x0FA5, os: 1, is_32: 1, e: 1, g: 1, mask_flags: of, }, + { opcode: 0x0FAC, os: 1, is_32: 1, e: 1, g: 1, imm8: 1, mask_flags: of, }, + { opcode: 0x0FAD, os: 1, is_32: 1, e: 1, g: 1, mask_flags: of, }, + + { opcode: 0x0FAE, e: 1, g: 1, skip: 1, }, + + { opcode: 0x0FAF, os: 1, e: 1, g: 1, mask_flags: 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, is_32: 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, skip: 1, }, // bswap esp + { opcode: 0x0FCD, }, + { opcode: 0x0FCE, }, + { opcode: 0x0FCF, }, + + + // mmx, sse + // - Commented out are not implemented + // - Missing are sse3+, and floating point + + { opcode: 0x660F12, e: 1, g: 1 }, + { opcode: 0x660F13, e: 1, g: 1 }, + { opcode: 0x660F14, e: 1, g: 1 }, + + { opcode: 0x0F28, e: 1, g: 1 }, + { opcode: 0x660F28, e: 1, g: 1 }, + { opcode: 0x0F29, e: 1, g: 1 }, + { opcode: 0x660F29, e: 1, g: 1 }, + { opcode: 0x0F2B, e: 1, g: 1 }, + { opcode: 0x660F2B, e: 1, g: 1 }, + + { opcode: 0xF20F2C, e: 1, g: 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, e: 1, g: 1 }, + { opcode: 0xF30F7F, e: 1, g: 1 }, + + { 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, e: 1, g: 1 }, + //{ 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++) +{ + 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, }, + + { 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, skip: 1, }, + { opcode: 0xB8 | i, os: 1, imm1632: 1, skip: 1, }, + + // note: overflow flag only undefined if shift is > 1 + { opcode: 0xC0, e: 1, fixed_g: i, imm8: 1, mask_flags: of, }, + { opcode: 0xC1, os: 1, e: 1, fixed_g: i, imm8: 1, mask_flags: of, }, + { opcode: 0xD0, e: 1, fixed_g: i, mask_flags: of, }, + { opcode: 0xD1, os: 1, e: 1, fixed_g: i, mask_flags: of, }, + { opcode: 0xD2, e: 1, fixed_g: i, mask_flags: of, }, + { opcode: 0xD3, os: 1, e: 1, fixed_g: i, mask_flags: of, }, + ]); +} + +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 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 = opcode.toString(16).toUpperCase(); + if(opcode_hex.length === 1) opcode_hex = "0" + opcode_hex; + + if(encoding[0].os) + { + t += `case 0x${opcode_hex}:\n`; + t += ` instr16_${opcode_hex}();\n`; + t += ` break;\n`; + t += `case 0x${opcode_hex}|0x100:\n`; + t += ` instr32_${opcode_hex}();\n`; + t += ` break;\n`; + } + else + { + t += `case 0x${opcode_hex}:\n`; + t += `case 0x${opcode_hex}|0x100:\n`; + t += ` instr_${opcode_hex}();\n`; + t += ` break;\n`; + } + } + t += `default: assert(false);\n`; + fs.writeFileSync("/tmp/table", t); + + 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(); + +for(const op of encodings) +{ + let i = 0; + for(const code of create_nasm(op)) + { + const filename = "gen_" + format_opcode(op.opcode) + "_" + (op.fixed_g || 0) + "_" + i + ".asm"; + console.log("Creating %s", filename); + fs.writeFileSync(__dirname + "/" + filename, code); + i++; + } +} + +function format_opcode(n) +{ + let x = n.toString(16); + return (x.length === 1 || x.length === 3) ? "0" + x : x; +} + +function random_int32() +{ + return Math.random() * 0x100000000 | 0; +} + +function create_nasm(op) +{ + if(op.prefix || op.skip) + { + return []; + } + + var size = (op.is_32 || op.opcode % 2 === 0) ? 8 : 32; + var is_modrm = op.e || op.g || op.fixed_g !== undefined; + + var codes = []; + + for(let reg of ["eax", "ecx", "edx", "ebx", "ebp", "esi", "edi"]) + { + let rand = random_int32(); + codes.push("mov " + reg + ", " + rand); + } + + if(true) // generate random mmx registers + { + 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("movq mm" + i + ", [esp]"); + } + codes.push("add esp, 8"); + } + + if(true) // generate random xmm registers + { + 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("movdqu xmm" + i + ", [esp]"); + } + codes.push("add esp, 16"); + } + + if(true) // generate random stack memory + { + for(let i = 0; i < 8; i++) + { + codes.push("sub esp, 4"); + codes.push("mov dword [esp], " + random_int32()); + } + } + + codes.push("push dword " + (random_int32() & ~(1 << 8 | 1 << 9))); + codes.push("popf"); + + if(size === 32) + { + //codes.push(["", "db 66h ; 16 bit"]); + } + + let opcode = op.opcode; + console.assert(opcode < 0x1000000); + if(opcode >= 0x10000) + { + let c = opcode >> 16; + console.assert(c === 0x66 || c === 0xF3 || c === 0xF2); + codes.push("db " + c); + opcode &= ~0xFF0000; + } + if(opcode >= 0x100) + { + 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 = 0; + + if(op.fixed_g !== undefined) + { + g = op.fixed_g; + } + + let e; + let sib; + + if(op.only_reg) + //if(!op.only_mem) + { + e = 0xc2; // edx + sib = ""; + } + else // op.only_mem + { + e = 0x04; // [esp] + sib = 0x24; + } + + codes.push("db " + (e | g << 3)); + if(e < 0xC0) + { + codes.push("db " + sib); + } + } + + if(op.imm || op.imm8 || op.imm1632 || op.immaddr) + { + if(op.imm8 || (op.imm && size === 8)) + { + codes.push("db 12h"); + } + else + { + // immaddr: depends on address size + console.assert(op.imm1632 || (op.imm && size === 32) || op.immaddr); + codes.push("dd 1234abcdh"); + } + } + + if(op.mask_flags) + { + codes.push( + "pushf", + "and dword [esp], ~" + op.mask_flags, + "popf" + ); + } + + return all_combinations(codes).map(c => { + return ( + "global _start\n" + + '%include "header.inc"\n\n' + + c.join("\n") + "\n" + + '%include "footer.inc"\n' + ); + }); +} + +function all_combinations(xs) +{ + var result = [xs]; + + for(let i = 0; i < xs.length; i++) + { + let x = xs[i]; + + if(x instanceof Array) + { + let new_result = []; + + for(let r of result) + { + for(let x_ of x) + { + r = r.slice(); + r[i] = x_; + new_result.push(r); + } + } + + result = new_result; + } + } + + return result; +} From c46a6f310a1505d2af065a9c348dd6bdec25b5b3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 8 Jul 2017 13:54:14 -0500 Subject: [PATCH 0017/2137] Add LEGALIZE_JS_FFI and BINARYEN_TRAP_MODE for efficient 64-bit operations --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index f22d696e..a361c209 100644 --- a/Makefile +++ b/Makefile @@ -140,6 +140,8 @@ build/v86.wasm: src/native/*.c src/native/*.h --llvm-opts 3 \ -O3 \ -g4 \ + -s LEGALIZE_JS_FFI=0 \ + -s "BINARYEN_TRAP_MODE='allow'" \ -s WASM=1 -s SIDE_MODULE=1 -o build/v86.wasm ls -lh build/v86.wasm @@ -151,6 +153,8 @@ build/v86-debug.wasm: src/native/*.c src/native/*.h -fwrapv \ -Os \ -g4 \ + -s LEGALIZE_JS_FFI=0 \ + -s "BINARYEN_TRAP_MODE='allow'" \ -s WASM=1 -s SIDE_MODULE=1 -o build/v86-debug.wasm ls -lh build/v86-debug.wasm From 593ce966d0c9e380bed2f16467e082d4e7ca2f89 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 8 Jul 2017 13:55:14 -0500 Subject: [PATCH 0018/2137] Optimise clear_tlb --- src/browser/starter.js | 6 ++++++ src/native/cpu.c | 9 +++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 4fe12275..358835f3 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -95,6 +95,7 @@ function V86Starter(options) var emulator; var cpu; var mem; + var mem8; var wasm_shared_funcs = { "_throw_cpu_exception": () => { throw MAGIC_CPU_EXCEPTION; }, "_hlt_op": function() { return cpu.hlt_op(); }, @@ -108,6 +109,10 @@ function V86Starter(options) "_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)); }, + "_memcpy_large": function(dest, source, length) { + mem8.set(mem8.subarray(source, source + length), dest); + return dest; + }, "_call_interrupt_vector": function(interrupt_nr, is_software_int, has_error_code, error_code) { cpu.call_interrupt_vector(interrupt_nr, is_software_int, !!has_error_code, error_code); @@ -274,6 +279,7 @@ function V86Starter(options) emulator = this.v86 = new v86(this.emulator_bus, wm); cpu = emulator.cpu; mem = wm.mem.buffer; + mem8 = new Uint8Array(mem); this.bus.register("emulator-stopped", function() { diff --git a/src/native/cpu.c b/src/native/cpu.c index 5fc7e8c0..34d8a2ef 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -11,6 +11,10 @@ int32_t read_e8_partial_branch() { return reg8[*modrm_byte << 2 & 0xC | *modrm_byte >> 2 & 1]; } +// like memcpy, but only efficient for large (approximately 10k) sizes +// See memcpy in https://github.com/kripken/emscripten/blob/master/src/library.js +void* memcpy_large(void* dest, const void* src, size_t n); + void writable_or_pagefault(int32_t, int32_t); int32_t translate_address_read(int32_t); int32_t translate_address_write(int32_t); @@ -687,10 +691,7 @@ void write_xmm128s(int32_t d0, int32_t d1, int32_t d2, int32_t d3) void clear_tlb() { - for(int32_t i = 0; i < 0x100000; i += 4) - { - *(int32_t*)(tlb_info + i) = *(int32_t*)(tlb_info_global + i); - } + memcpy_large(tlb_info, tlb_info_global, 0x100000); } void task_switch_test_mmx() From 77c43a938a7cdd2085de46f16dbe5d3865660f97 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 8 Jul 2017 14:00:45 -0500 Subject: [PATCH 0019/2137] Port read_moffs --- src/browser/starter.js | 1 - src/native/cpu.c | 13 +++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 358835f3..dc1a3d2f 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -161,7 +161,6 @@ function V86Starter(options) "_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); }, - "_read_moffs": function() { return cpu.read_moffs.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); }, diff --git a/src/native/cpu.c b/src/native/cpu.c index 34d8a2ef..5426eac2 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -708,3 +708,16 @@ void task_switch_test_mmx() } } } + +// read 2 or 4 byte from ip, depending on address size attribute +int32_t read_moffs() +{ + if(is_asize_32()) + { + return get_seg_prefix(DS) + read_op32s(); + } + else + { + return get_seg_prefix(DS) + read_op16(); + } +} From ad06ea7bf418630884dd89d30fe12f473184ce45 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 8 Jul 2017 14:11:19 -0500 Subject: [PATCH 0020/2137] Port get_real_eip --- src/browser/starter.js | 1 - src/native/cpu.c | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index dc1a3d2f..7c12097d 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -254,7 +254,6 @@ function V86Starter(options) "_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); }, - "_get_real_eip": function() { return cpu.get_real_eip.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); }, diff --git a/src/native/cpu.c b/src/native/cpu.c index 5426eac2..7e37190a 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -721,3 +721,9 @@ int32_t read_moffs() return get_seg_prefix(DS) + read_op16(); } } + +// Returns the "real" instruction pointer, without segment offset +int32_t get_real_eip() +{ + return *instruction_pointer - get_seg(CS); +} From cfdc438a17345094a5059502f47ba71fddf67474 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 8 Jul 2017 14:19:15 -0500 Subject: [PATCH 0021/2137] Port a few sse instructions --- src/native/instructions_0f.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 53caf530..a721f196 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -996,8 +996,20 @@ static void instr_0F7B() { unimplemented_sse(); } static void instr_0F7C() { unimplemented_sse(); } static void instr_0F7D() { unimplemented_sse(); } static void instr_0F7E() { unimplemented_sse(); } -static void instr_660F7E() { unimplemented_sse(); } -static void instr_F30F7E() { unimplemented_sse(); } +static void instr_660F7E() { + // movd r/m32, xmm + task_switch_test_mmx(); + read_modrm_byte(); + union reg64 data = read_xmm64s(); + set_e32(data.u32[0]); +} +static void instr_F30F7E() { + // 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); +} static void instr_0F7F() { unimplemented_sse(); } static void instr_660F7F() { // movdqa xmm/m128, xmm @@ -1008,7 +1020,15 @@ static void instr_660F7F() { int32_t addr = modrm_resolve(*modrm_byte); safe_write128(addr, data); } -static void instr_F30F7F() { unimplemented_sse(); } +static void instr_F30F7F() { + // 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); + safe_write128(addr, data); +} // jmpcc static void instr16_0F80() { jmpcc16( test_o()); } From 41879ba7517a20b9ec5fbe2a6b655af3c37443f6 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 8 Jul 2017 14:23:07 -0500 Subject: [PATCH 0022/2137] Silence unused warning --- src/native/modrm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/native/modrm.c b/src/native/modrm.c index 42794ac5..2f5d6090 100644 --- a/src/native/modrm.c +++ b/src/native/modrm.c @@ -114,7 +114,7 @@ static int32_t resolve_modrm32(int32_t modrm_byte) SIB_ENTRY_LEVEL2(0x80 | (n) << 3, (reg1) << 2)\ SIB_ENTRY_LEVEL2(0xC0 | (n) << 3, (reg1) << 3) -static int32_t resolve_sib_(bool mod) +static inline int32_t resolve_sib_(bool mod) { switch(read_imm8()) { @@ -189,7 +189,7 @@ static int32_t resolve_sib(bool mod) return get_seg_prefix(seg) + base + offset; } -static int32_t resolve_modrm32_(int32_t modrm_byte) +static inline int32_t resolve_modrm32_(int32_t modrm_byte) { uint8_t r = modrm_byte & 7; assert(modrm_byte < 0xC0); From fa65e9cef9913cf452b3315eefd1e1d37136105f Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 9 Jul 2017 18:04:41 -0500 Subject: [PATCH 0023/2137] Fix output wrapper (fixes loading libv86.js in browsers) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a361c209..41f569db 100644 --- a/Makefile +++ b/Makefile @@ -117,7 +117,7 @@ build/libv86.js: $(CLOSURE) src/*.js lib/*.js src/browser/*.js $(CLOSURE_FLAGS)\ --compilation_level SIMPLE\ $(TRANSPILE_ES6_FLAGS)\ - --output_wrapper ';(function(){%output%})();'\ + --output_wrapper ';(function(){%output%}).call(this);'\ --js $(CORE_FILES)\ --js $(BROWSER_FILES)\ --js $(LIB_FILES) From b4bffa6b8a8ace13e5f0fba095672f188f4971b3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 9 Jul 2017 18:05:19 -0500 Subject: [PATCH 0024/2137] Add missing branch_taken() --- src/native/misc_instr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/native/misc_instr.c b/src/native/misc_instr.c index e0f901be..d0495f7c 100644 --- a/src/native/misc_instr.c +++ b/src/native/misc_instr.c @@ -103,6 +103,7 @@ void jmp_rel16(int32_t rel16) // limit ip to 16 bit *instruction_pointer = cs_offset + ((*instruction_pointer - cs_offset + rel16) & 0xFFFF); + branch_taken(); } void jmpcc8(bool condition) From 5da7185d302b25d4145f491cfd0a59a4bfa6e11c Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 9 Jul 2017 18:09:07 -0500 Subject: [PATCH 0025/2137] Fix state restoring --- src/cpu.js | 83 +++++++++++++++++++++--------------------------------- 1 file changed, 32 insertions(+), 51 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index f93cacb0..b78386f4 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -199,6 +199,7 @@ function CPU(bus, wm) this.reg_mmx8 = new Uint8Array(this.reg_mmxs.buffer); this.reg_xmm32s = new Int32Array(wm.mem.buffer, 828, 8 * 4); + this.mxcsr = new Int32Array(wm.mem.buffer, 824, 1); // segment registers, tr and ldtr @@ -328,17 +329,17 @@ CPU.prototype.get_state = function() state[23] = this.sysenter_eip[0]; state[24] = this.sysenter_esp[0]; state[25] = this.prefixes[0]; - state[26] = this.flags; - state[27] = this.flags_changed; - state[28] = this.last_op1; - state[29] = this.last_op2; - state[30] = this.last_op_size; - state[31] = this.last_add_result; + state[26] = this.flags[0]; + state[27] = this.flags_changed[0]; + state[28] = this.last_op1[0]; + state[29] = this.last_op2[0]; + state[30] = this.last_op_size[0]; + state[31] = this.last_add_result[0]; state[32] = this.modrm_byte[0]; state[36] = this.paging[0]; - state[37] = this.instruction_pointer; - state[38] = this.previous_ip; + state[37] = this.instruction_pointer[0]; + state[38] = this.previous_ip[0]; state[39] = this.reg32s; state[40] = this.sreg; state[41] = this.dreg; @@ -369,11 +370,8 @@ CPU.prototype.get_state = function() state[64] = this.tss_size_32; - state[63] = this.devices.ioapic; - - state[64] = this.tss_size_32; - state[65] = this.reg_mmxs; + state[66] = this.reg_xmm32s; return state; }; @@ -381,16 +379,16 @@ CPU.prototype.get_state = function() CPU.prototype.set_state = function(state) { this.memory_size[0] = state[0]; - this.segment_is_null = state[1]; - this.segment_offsets = state[2]; - this.segment_limits = state[3]; + this.segment_is_null.set(state[1]); + this.segment_offsets.set(state[2]); + this.segment_limits.set(state[3]); this.protected_mode[0] = state[4]; this.idtr_offset[0] = state[5]; this.idtr_size[0] = state[6]; this.gdtr_offset[0] = state[7]; this.gdtr_size[0] = state[8]; this.page_fault = state[9]; - this.cr = state[10]; + this.cr.set(state[10]); this.cpl[0] = state[11]; this.page_size_extensions[0] = state[12]; this.is_32[0] = state[13]; @@ -407,21 +405,21 @@ CPU.prototype.set_state = function(state) this.sysenter_esp[0] = state[24]; this.prefixes[0] = state[25]; - this.flags = state[26]; - this.flags_changed = state[27]; - this.last_op1 = state[28]; - this.last_op2 = state[29]; - this.last_op_size = state[30]; - this.last_add_result = state[31]; - this.modrm_byte = state[32]; + this.flags[0] = state[26]; + this.flags_changed[0] = state[27]; + this.last_op1[0] = state[28]; + this.last_op2[0] = state[29]; + this.last_op_size[0] = state[30]; + this.last_add_result[0] = state[31]; + this.modrm_byte[0] = state[32]; this.paging[0] = state[36]; - this.instruction_pointer = state[37]; - this.previous_ip = state[38]; - this.reg32s = state[39]; - this.sreg = state[40]; - this.dreg = state[41]; - this.mem8 = state[42]; + this.instruction_pointer[0] = state[37]; + this.previous_ip[0] = state[38]; + this.reg32s.set(state[39]); + this.sreg.set(state[40]); + this.dreg.set(state[41]); + this.mem8.set(state[42]); this.fpu = state[43]; this.devices.virtio = state[45]; @@ -448,28 +446,12 @@ CPU.prototype.set_state = function(state) this.tss_size_32 = state[64]; - this.devices.ioapic = state[63]; - - this.tss_size_32 = state[64]; - - this.reg_mmxs = state[65]; - - this.mem16 = new Uint16Array(this.mem8.buffer, this.mem8.byteOffset, this.mem8.length >> 1); - this.mem32s = new Int32Array(this.mem8.buffer, this.mem8.byteOffset, this.mem8.length >> 2); - + this.reg_mmxs.set(state[65]); + this.reg_xmm32s.set(state[66]); this.full_clear_tlb(); // tsc_offset? - this.reg32 = new Uint32Array(this.reg32s.buffer); - this.reg16s = new Int16Array(this.reg32s.buffer); - this.reg16 = new Uint16Array(this.reg32s.buffer); - this.reg8s = new Int8Array(this.reg32s.buffer); - this.reg8 = new Uint8Array(this.reg32s.buffer); - - this.reg_mmx = new Uint32Array(this.reg_mmxs.buffer); - this.reg_mmx8s = new Int8Array(this.reg_mmxs.buffer); - this.reg_mmx8 = new Uint8Array(this.reg_mmxs.buffer); this.update_operand_size(); }; @@ -641,9 +623,9 @@ CPU.prototype.create_memory = function(size) var buffer = this.wm.mem.buffer; - this.mem8 = new Uint8Array(buffer, 2048 + 0x100000 * 6); - this.mem16 = new Uint16Array(buffer, 2048 + 0x100000 * 6); - this.mem32s = new Int32Array(buffer, 2048 + 0x100000 * 6); + this.mem8 = new Uint8Array(buffer, 2048 + 0x100000 * 6, size); + this.mem16 = new Uint16Array(buffer, 2048 + 0x100000 * 6, size); + this.mem32s = new Int32Array(buffer, 2048 + 0x100000 * 6, size); }; CPU.prototype.init = function(settings, device_bus) @@ -3292,7 +3274,6 @@ CPU.prototype.task_switch_test_mmx = function() this.trigger_ud(); } } - }; CPU.prototype.todo = function() From e995f2b3e5b6dc2bfa8f223e30d3e2f609432252 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 9 Jul 2017 18:09:28 -0500 Subject: [PATCH 0026/2137] Fix failing assertion during state restoring --- src/pci.js | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/pci.js b/src/pci.js index dca6e2e2..2acbd3f8 100644 --- a/src/pci.js +++ b/src/pci.js @@ -534,7 +534,7 @@ PCI.prototype.set_io_bars = function(bar, from, to) old_entry.write16 === this.io.empty_port_write && old_entry.write32 === this.io.empty_port_write) { - dbg_log("Move IO bar: Source not mapped, port=" + h(from + i, 4), LOG_PCI); + dbg_log("Warning: Bad IO bar: Source not mapped, port=" + h(from + i, 4), LOG_PCI); } var entry = bar.entries[i]; @@ -543,13 +543,17 @@ PCI.prototype.set_io_bars = function(bar, from, to) ports[to + i] = entry; - // these can fail if the os maps an io port in multiple bars (indicating a bug) - dbg_assert(empty_entry.read8 === this.io.empty_port_read8, "Bad IO bar: Target already mapped"); - dbg_assert(empty_entry.read16 === this.io.empty_port_read16, "Bad IO bar: Target already mapped"); - dbg_assert(empty_entry.read32 === this.io.empty_port_read32, "Bad IO bar: Target already mapped"); - dbg_assert(empty_entry.write8 === this.io.empty_port_write, "Bad IO bar: Target already mapped"); - dbg_assert(empty_entry.write16 === this.io.empty_port_write, "Bad IO bar: Target already mapped"); - dbg_assert(empty_entry.write32 === this.io.empty_port_write, "Bad IO bar: Target already mapped"); + if(empty_entry.read8 === this.io.empty_port_read8 || + empty_entry.read16 === this.io.empty_port_read16 || + empty_entry.read32 === this.io.empty_port_read32 || + empty_entry.write8 === this.io.empty_port_write || + empty_entry.write16 === this.io.empty_port_write || + empty_entry.write32 === this.io.empty_port_write) + { + // These can fail if the os maps an io port in multiple bars (indicating a bug) + // XXX: Fails during restore_state + dbg_log("Warning: Bad IO bar: Target already mapped, port=" + h(to + i, 4), LOG_PCI); + } } }; From 83f7e03090683c1f47a1edd757ee3d4092bb4dc6 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 9 Jul 2017 18:11:39 -0500 Subject: [PATCH 0027/2137] Fix compilation with latest Closure Compiler --- src/cpu.js | 60 +++++++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index b78386f4..8d05509c 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -3424,32 +3424,32 @@ CPU.prototype.read_e32 = function() CPU.prototype.read_mmx_mem32s = function() { - if(this.modrm_byte < 0xC0) { - return this.safe_read32s(this.modrm_resolve(this.modrm_byte)); + if(this.modrm_byte[0] < 0xC0) { + return this.safe_read32s(this.modrm_resolve(this.modrm_byte[0])); } else { // Returning lower dword of qword - return this.reg_mmxs[2 * (this.modrm_byte & 7)]; + return this.reg_mmxs[2 * (this.modrm_byte[0] & 7)]; } }; CPU.prototype.read_mmx_mem64s = function() { - if(this.modrm_byte < 0xC0) { - return this.safe_read64s(this.modrm_resolve(this.modrm_byte)); + if(this.modrm_byte[0] < 0xC0) { + return this.safe_read64s(this.modrm_resolve(this.modrm_byte[0])); } else { return this.create_atom64s( - this.reg_mmxs[2 * (this.modrm_byte & 7)], - this.reg_mmxs[2 * (this.modrm_byte & 7) + 1] + this.reg_mmxs[2 * (this.modrm_byte[0] & 7)], + this.reg_mmxs[2 * (this.modrm_byte[0] & 7) + 1] ); } }; CPU.prototype.read_xmm_mem64s = function() { - if(this.modrm_byte < 0xC0) { - return this.safe_read64s(this.modrm_resolve(this.modrm_byte)); + if(this.modrm_byte[0] < 0xC0) { + return this.safe_read64s(this.modrm_resolve(this.modrm_byte[0])); } else { - let i = (this.modrm_byte & 7) << 2; + let i = (this.modrm_byte[0] & 7) << 2; return this.create_atom64s( this.reg_xmm32s[i], this.reg_xmm32s[i | 1] @@ -3459,10 +3459,10 @@ CPU.prototype.read_xmm_mem64s = function() CPU.prototype.read_xmm_mem128s = function() { - if(this.modrm_byte < 0xC0) { - return this.safe_read128s_aligned(this.modrm_resolve(this.modrm_byte)); + if(this.modrm_byte[0] < 0xC0) { + return this.safe_read128s_aligned(this.modrm_resolve(this.modrm_byte[0])); } else { - let i = (this.modrm_byte & 7) << 2; + let i = (this.modrm_byte[0] & 7) << 2; return this.create_atom128s( this.reg_xmm32s[i], this.reg_xmm32s[i | 1], @@ -3474,10 +3474,10 @@ CPU.prototype.read_xmm_mem128s = function() CPU.prototype.read_xmm_mem128s_unaligned = function() { - if(this.modrm_byte < 0xC0) { - return this.safe_read128s_unaligned(this.modrm_resolve(this.modrm_byte)); + if(this.modrm_byte[0] < 0xC0) { + return this.safe_read128s_unaligned(this.modrm_resolve(this.modrm_byte[0])); } else { - let i = (this.modrm_byte & 7) << 2; + let i = (this.modrm_byte[0] & 7) << 2; return this.create_atom128s( this.reg_xmm32s[i], this.reg_xmm32s[i | 1], @@ -3522,12 +3522,12 @@ CPU.prototype.set_e32 = function(value) CPU.prototype.set_mmx_mem64s = function(low, high) { - if(this.modrm_byte < 0xC0) { - var addr = this.modrm_resolve(this.modrm_byte); + if(this.modrm_byte[0] < 0xC0) { + var addr = this.modrm_resolve(this.modrm_byte[0]); this.safe_write64(addr, low, high); } else { - this.reg_mmxs[2 * (this.modrm_byte & 7)] = low; - this.reg_mmxs[2 * (this.modrm_byte & 7) + 1] = high; + this.reg_mmxs[2 * (this.modrm_byte[0] & 7)] = low; + this.reg_mmxs[2 * (this.modrm_byte[0] & 7) + 1] = high; } }; @@ -3679,14 +3679,14 @@ CPU.prototype.write_g32 = function(value) CPU.prototype.read_xmm64s = function() { return this.create_atom64s( - this.reg_xmm32s[(this.modrm_byte >> 3 & 7) << 2], - this.reg_xmm32s[(this.modrm_byte >> 3 & 7) << 2 | 1] + this.reg_xmm32s[(this.modrm_byte[0] >> 3 & 7) << 2], + this.reg_xmm32s[(this.modrm_byte[0] >> 3 & 7) << 2 | 1] ); }; CPU.prototype.read_xmm128s = function() { - let i = (this.modrm_byte >> 3 & 7) << 2; + let i = (this.modrm_byte[0] >> 3 & 7) << 2; return this.create_atom128s( this.reg_xmm32s[i | 0], this.reg_xmm32s[i | 1], @@ -3698,27 +3698,27 @@ CPU.prototype.read_xmm128s = function() CPU.prototype.read_mmx64s = function() { return this.create_atom64s( - this.reg_mmxs[2 * (this.modrm_byte >> 3 & 7)], - this.reg_mmxs[2 * (this.modrm_byte >> 3 & 7) + 1] + this.reg_mmxs[2 * (this.modrm_byte[0] >> 3 & 7)], + this.reg_mmxs[2 * (this.modrm_byte[0] >> 3 & 7) + 1] ); }; CPU.prototype.write_mmx64s = function(low, high) { - this.reg_mmxs[2 * (this.modrm_byte >> 3 & 7)] = low; - this.reg_mmxs[2 * (this.modrm_byte >> 3 & 7) + 1] = high; + this.reg_mmxs[2 * (this.modrm_byte[0] >> 3 & 7)] = low; + this.reg_mmxs[2 * (this.modrm_byte[0] >> 3 & 7) + 1] = high; }; CPU.prototype.write_xmm64 = function(low, high) { - let i = (this.modrm_byte >> 3 & 7) << 2; + let i = (this.modrm_byte[0] >> 3 & 7) << 2; this.reg_xmm32s[i] = low; this.reg_xmm32s[i + 1] = high; }; CPU.prototype.write_xmm128s = function(d0, d1, d2, d3) { - let i = (this.modrm_byte >> 3 & 7) << 2; + let i = (this.modrm_byte[0] >> 3 & 7) << 2; this.reg_xmm32s[i] = d0; this.reg_xmm32s[i + 1] = d1; this.reg_xmm32s[i + 2] = d2; @@ -4735,7 +4735,7 @@ CPU.prototype.trigger_pagefault = function(write, user, present) if(LOG_PAGE_FAULTS) { dbg_log("page fault w=" + write + " u=" + user + " p=" + present + - " eip=" + h(this.previous_ip >>> 0, 8) + + " eip=" + h(this.previous_ip[0] >>> 0, 8) + " cr2=" + h(this.cr[2] >>> 0, 8), LOG_CPU); dbg_trace(LOG_CPU); } From e835729bfa164703edd219f4bdd49457ac687a48 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 9 Jul 2017 18:46:40 -0500 Subject: [PATCH 0028/2137] Optimise push16, push32 and pop32s --- src/native/misc_instr.c | 56 ++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/src/native/misc_instr.c b/src/native/misc_instr.c index d0495f7c..40d1b8ad 100644 --- a/src/native/misc_instr.c +++ b/src/native/misc_instr.c @@ -194,18 +194,52 @@ static void adjust_stack_reg(int32_t adjustment) void push16(int32_t imm16) { - int32_t sp = get_stack_pointer(-2); - - safe_write16(sp, imm16); - adjust_stack_reg(-2); + if(*stack_size_32) + { + int32_t sp = get_seg(SS) + reg32s[ESP] - 2; + safe_write16(sp, imm16); + reg32s[ESP] += -2; + } + else + { + int32_t sp = get_seg(SS) + (reg16[SP] - 2 & 0xFFFF); + safe_write16(sp, imm16); + reg16[SP] += -2; + } } void push32(int32_t imm32) { - int32_t sp = get_stack_pointer(-4); + if(*stack_size_32) + { + int32_t sp = get_seg(SS) + reg32s[ESP] - 4; + safe_write32(sp, imm32); + reg32s[ESP] += -4; + } + else + { + int32_t sp = get_seg(SS) + (reg16[SP] - 4 & 0xFFFF); + safe_write32(sp, imm32); + reg16[SP] += -4; + } +} - safe_write32(sp, imm32); - adjust_stack_reg(-4); +int32_t pop32s() +{ + if(*stack_size_32) + { + int32_t sp = get_seg(SS) + reg32s[ESP]; + int32_t result = safe_read32s(sp); + reg32s[ESP] += 4; + return result; + } + else + { + int32_t sp = get_seg(SS) + reg16[SP]; + int32_t result = safe_read32s(sp); + reg16[SP] += 4; + return result; + } } void pusha16() @@ -241,11 +275,3 @@ void pusha32() push32(reg32s[ESI]); push32(reg32s[EDI]); } - -int32_t pop32s() -{ - int32_t sp = get_stack_pointer(0); - int32_t result = safe_read32s(sp); - adjust_stack_reg(4); - return result; -} From 8ede7ccbed0949428ed6027405e3503c57efe287 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 9 Jul 2017 18:55:30 -0500 Subject: [PATCH 0029/2137] Port MOVQ --- src/native/cpu.c | 8 ++++++++ src/native/instructions_0f.c | 10 +++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/native/cpu.c b/src/native/cpu.c index 7e37190a..acde925e 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -471,6 +471,14 @@ union reg128 safe_read128s(int32_t addr) 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 diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index a721f196..aec6485f 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1673,7 +1673,15 @@ static void instr_0FD4() { unimplemented_sse(); } static void instr_0FD5() { unimplemented_sse(); } static void instr_660FD5() { unimplemented_sse(); } static void instr_0FD6() { unimplemented_sse(); } -static void instr_660FD6() { unimplemented_sse(); } +static void instr_660FD6() { + // 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]); +} static void instr_0FD7() { unimplemented_sse(); } static void instr_660FD7() { // pmovmskb reg, xmm From 645991b30f90851470a2763270d6e57c8fb0d683 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 9 Jul 2017 19:32:13 -0500 Subject: [PATCH 0030/2137] Makefile: Use $(MAKE) --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 41f569db..36c45b8c 100644 --- a/Makefile +++ b/Makefile @@ -195,12 +195,12 @@ nasmtests: build/libv86.js $(NASM_TEST_DIR)/run.js qemutests: build/libv86.js - make -C tests/qemu test-i386 + $(MAKE) -C tests/qemu test-i386 ./tests/qemu/run.js > result ./tests/qemu/test-i386 > reference diff result reference kvm-unit-test: build/libv86.js (cd tests/kvm-unit-tests && ./configure) - make -C tests/kvm-unit-tests + $(MAKE) -C tests/kvm-unit-tests tests/kvm-unit-tests/run.js tests/kvm-unit-tests/x86/realmode.flat From 6c702c7340e7da891215c6c553bd5855eac4c54b Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 9 Jul 2017 20:00:56 -0500 Subject: [PATCH 0031/2137] nasm tests: Test both memory and register, skip failing register tests --- tests/nasm/create_tests.js | 67 ++++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/tests/nasm/create_tests.js b/tests/nasm/create_tests.js index 6aaee8d1..178631dd 100755 --- a/tests/nasm/create_tests.js +++ b/tests/nasm/create_tests.js @@ -384,16 +384,16 @@ const encodings = [ // - Commented out are not implemented // - Missing are sse3+, and floating point - { opcode: 0x660F12, e: 1, g: 1 }, - { opcode: 0x660F13, e: 1, g: 1 }, + { 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, e: 1, g: 1 }, - { opcode: 0x660F29, e: 1, g: 1 }, - { opcode: 0x0F2B, e: 1, g: 1 }, - { opcode: 0x660F2B, 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 }, { opcode: 0xF20F2C, e: 1, g: 1 }, @@ -473,8 +473,8 @@ const encodings = [ { opcode: 0x660F7E, e: 1, g: 1 }, { opcode: 0xF30F7E, e: 1, g: 1 }, { opcode: 0x0F7F, e: 1, g: 1 }, - { opcode: 0x660F7F, e: 1, g: 1 }, - { opcode: 0xF30F7F, 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, }, @@ -492,7 +492,7 @@ const encodings = [ { opcode: 0x0FD5, e: 1, g: 1 }, { opcode: 0x660FD5, e: 1, g: 1 }, - { opcode: 0x660FD6, 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 }, @@ -721,12 +721,35 @@ gen_table(); for(const op of encodings) { let i = 0; - for(const code of create_nasm(op)) + for(const config of [{ mem: 0 }, { mem: 1 }]) { - const filename = "gen_" + format_opcode(op.opcode) + "_" + (op.fixed_g || 0) + "_" + i + ".asm"; - console.log("Creating %s", filename); - fs.writeFileSync(__dirname + "/" + filename, code); - i++; + for(const code of create_nasm(op, config)) + { + const filename = "gen_" + format_opcode(op.opcode) + "_" + (op.fixed_g || 0) + "_" + i + ".asm"; + const dirname = __dirname + "/" + 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++; + } } } @@ -741,7 +764,7 @@ function random_int32() return Math.random() * 0x100000000 | 0; } -function create_nasm(op) +function create_nasm(op, config) { if(op.prefix || op.skip) { @@ -832,17 +855,21 @@ function create_nasm(op) let e; let sib; - if(op.only_reg) - //if(!op.only_mem) + if(config.mem ? op.only_reg : op.only_mem) { - e = 0xc2; // edx - sib = ""; + return []; } - else // op.only_mem + + 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) From a1a10d75a8ea2f189792e0eab58f2f0d48732d1c Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 9 Jul 2017 20:45:51 -0500 Subject: [PATCH 0032/2137] Fix unaligned stack check during nasm tests --- tests/nasm/run.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/nasm/run.js b/tests/nasm/run.js index 1249e582..ce5788bd 100755 --- a/tests/nasm/run.js +++ b/tests/nasm/run.js @@ -184,7 +184,7 @@ else { const evaluated_mmxs = cpu.reg_mmxs; const evaluated_xmms = cpu.reg_xmm32s; const esp = cpu.reg32s[4]; - const evaluated_memory = cpu.mem32s.slice(esp >> 2, esp + 16 >> 2); + const evaluated_memory = new Int32Array(cpu.mem8.slice(esp, esp + 16).buffer); let individual_failures = []; let offset = 0; From 95cd31bb49244805dad3cb89dcdd4687b3489553 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 9 Jul 2017 20:51:33 -0500 Subject: [PATCH 0033/2137] nasm tests: Test 16-bit instructions --- tests/nasm/create_tests.js | 80 +++++++++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 19 deletions(-) diff --git a/tests/nasm/create_tests.js b/tests/nasm/create_tests.js index 178631dd..4d328247 100755 --- a/tests/nasm/create_tests.js +++ b/tests/nasm/create_tests.js @@ -338,14 +338,14 @@ const encodings = [ { 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, is_32: 1, e: 1, g: 1, }, // bsf - { opcode: 0x0FBD, os: 1, is_32: 1, e: 1, g: 1, }, + { opcode: 0x0FBC, os: 1, e: 1, g: 1, }, // bsf + { opcode: 0x0FBD, os: 1, e: 1, g: 1, }, // note: overflow flag only undefined if shift is > 1 - { opcode: 0x0FA4, os: 1, is_32: 1, e: 1, g: 1, imm8: 1, mask_flags: of, }, // shld - { opcode: 0x0FA5, os: 1, is_32: 1, e: 1, g: 1, mask_flags: of, }, - { opcode: 0x0FAC, os: 1, is_32: 1, e: 1, g: 1, imm8: 1, mask_flags: of, }, - { opcode: 0x0FAD, os: 1, is_32: 1, e: 1, g: 1, mask_flags: of, }, + { opcode: 0x0FA4, os: 1, e: 1, g: 1, imm8: 1, mask_flags: of, }, // shld + { opcode: 0x0FA5, os: 1, e: 1, g: 1, mask_flags: of, }, + { opcode: 0x0FAC, os: 1, e: 1, g: 1, imm8: 1, mask_flags: of, }, + { opcode: 0x0FAD, os: 1, e: 1, g: 1, mask_flags: of, }, { opcode: 0x0FAE, e: 1, g: 1, skip: 1, }, @@ -362,7 +362,7 @@ const encodings = [ { opcode: 0x0FB6, os: 1, e: 1, g: 1, }, // movzx { opcode: 0x0FB7, os: 1, e: 1, g: 1, }, - { opcode: 0xF30FB8, os: 1, is_32: 1, e: 1, g: 1 }, // popcnt + { 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, }, @@ -720,8 +720,16 @@ gen_table(); 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 [{ mem: 0 }, { mem: 1 }]) + + for(const config of configurations) { for(const code of create_nasm(op, config)) { @@ -771,7 +779,31 @@ function create_nasm(op, config) return []; } - var size = (op.is_32 || op.opcode % 2 === 0) ? 8 : 32; + if(config.mem ? op.only_reg : op.only_mem) + { + // illegal opcode + return []; + } + + if(!op.e) + { + if(config.mem) + { + // doesn't use memory, don't test both + return []; + } + } + + if(!op.os) + { + if(config.size === 16) + { + // equivalent to 32-bit version, don't test both + return []; + } + } + + var size = (op.os || op.opcode % 2 === 1) ? config.size : 8; var is_modrm = op.e || op.g || op.fixed_g !== undefined; var codes = []; @@ -820,9 +852,9 @@ function create_nasm(op, config) codes.push("push dword " + (random_int32() & ~(1 << 8 | 1 << 9))); codes.push("popf"); - if(size === 32) + if(size === 16) { - //codes.push(["", "db 66h ; 16 bit"]); + codes.push("db 66h ; 16 bit"); } let opcode = op.opcode; @@ -855,11 +887,6 @@ function create_nasm(op, config) let e; let sib; - if(config.mem ? op.only_reg : op.only_mem) - { - return []; - } - if(config.mem) { e = 0x04; // [esp] @@ -886,9 +913,24 @@ function create_nasm(op, config) } else { - // immaddr: depends on address size - console.assert(op.imm1632 || (op.imm && size === 32) || op.immaddr); - codes.push("dd 1234abcdh"); + if(op.immaddr) + { + // immaddr: depends on address size + codes.push("dd 1234abcdh"); + } + else + { + console.assert(op.imm1632 || (op.imm && (size === 16 || size === 32))); + + if(size === 16) + { + codes.push("dw 34cdh"); + } + else + { + codes.push("dd 1234abcdh"); + } + } } } From 654235ec16de9c323f3e25e3fce3c9911ad53d04 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 9 Jul 2017 21:42:34 -0500 Subject: [PATCH 0034/2137] Fix .wasm loading in nodejs --- src/browser/starter.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 7c12097d..2851a932 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -272,7 +272,17 @@ function V86Starter(options) }; let wasm_file = DEBUG ? "v86-debug.wasm" : "v86.wasm"; - v86util.load_wasm("build/" + wasm_file, { 'env': wasm_shared_funcs }, wm => { + + if(typeof window === "undefined" && typeof __dirname === "string") + { + wasm_file = __dirname + "/" + wasm_file; + } + else + { + wasm_file = "build/" + wasm_file; + } + + v86util.load_wasm(wasm_file, { 'env': wasm_shared_funcs }, wm => { wm.instance.exports["__post_instantiate"](); emulator = this.v86 = new v86(this.emulator_bus, wm); cpu = emulator.cpu; From b55c5119c7af366c26473d91ec3c0769a12f9978 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 9 Jul 2017 21:48:39 -0500 Subject: [PATCH 0035/2137] Nasm tests: Write to build folder --- tests/nasm/Makefile | 23 +++++++++++++++++------ tests/nasm/create_tests.js | 2 +- tests/nasm/run.js | 2 +- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/tests/nasm/Makefile b/tests/nasm/Makefile index 11171dda..1f5bf0ea 100644 --- a/tests/nasm/Makefile +++ b/tests/nasm/Makefile @@ -1,22 +1,33 @@ -source_files := $(wildcard *.asm) +source_files := $(wildcard build/*.asm) +source_files += $(addprefix build/,$(wildcard *.asm)) + host_executables := $(patsubst %.asm,%.bin,$(source_files)) v86_executables := $(patsubst %.asm,%.img,$(source_files)) host_fixtures := $(patsubst %.asm,%.fixture,$(source_files)) -all: $(host_executables) $(v86_executables) $(host_fixtures) +inc_files := $(addprefix build/,$(wildcard *.inc)) + +all: $(source_files) $(host_executables) $(v86_executables) $(host_fixtures) .PHONY: all # To run / debug locally -%.bin: %.asm *.inc +build/%.bin: build/%.asm $(inc_files) nasm -felf32 -o $@.o $<; ld -g $@.o -m elf_i386 -o $@ # To generate a fixture using gdb -%.fixture: %.bin +build/%.fixture: build/%.bin gdb -quiet -batch -x gdbauto $< > $@ # To use as a multiboot kernel image for v86 -%.img: %.asm *.inc +build/%.img: build/%.asm $(inc_files) nasm -felf32 -o $@.o $<; ld -g $@.o -m elf_i386 --section-start=.text=0x8000 -o $@ +build/%.asm: %.asm + mkdir -p build; cp $< $@ + +build/%.inc: %.inc + mkdir -p build; cp $< $@ + clean: - rm -f *.o *.bin *.img *.fixture gen_*.asm + 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 4d328247..1f7130f6 100755 --- a/tests/nasm/create_tests.js +++ b/tests/nasm/create_tests.js @@ -734,7 +734,7 @@ for(const op of encodings) for(const code of create_nasm(op, config)) { const filename = "gen_" + format_opcode(op.opcode) + "_" + (op.fixed_g || 0) + "_" + i + ".asm"; - const dirname = __dirname + "/" + filename; + const dirname = __dirname + "/build/" + filename; let old_code = undefined; diff --git a/tests/nasm/run.js b/tests/nasm/run.js index ce5788bd..629eac20 100755 --- a/tests/nasm/run.js +++ b/tests/nasm/run.js @@ -7,7 +7,7 @@ const os = require('os'); const cluster = require('cluster'); const MAX_PARALLEL_TESTS = +process.env.MAX_PARALLEL_TESTS || 99; -const TEST_DIR = __dirname + "/"; +const TEST_DIR = __dirname + "/build/"; const DONE_MSG = 'DONE'; const MASK_ARITH = 1 | 1 << 2 | 1 << 4 | 1 << 6 | 1 << 7 | 1 << 11; From 425654304aaf226c080c6f4442ff351c3139a328 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 11 Jul 2017 12:48:17 -0500 Subject: [PATCH 0036/2137] Skip divide instruction tests instead of out-commenting them --- tests/nasm/create_tests.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/nasm/create_tests.js b/tests/nasm/create_tests.js index 1f7130f6..9a9774ed 100755 --- a/tests/nasm/create_tests.js +++ b/tests/nasm/create_tests.js @@ -211,8 +211,8 @@ const encodings = [ { opcode: 0xF6, fixed_g: 3, }, { opcode: 0xF6, fixed_g: 4, mask_flags: zf, }, { opcode: 0xF6, fixed_g: 5, mask_flags: zf, }, - //{ opcode: 0xF6, fixed_g: 6, }, // zero divide - //{ opcode: 0xF6, fixed_g: 7, }, + { 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, }, @@ -220,8 +220,8 @@ const encodings = [ { opcode: 0xF7, os: 1, fixed_g: 3, }, { opcode: 0xF7, os: 1, fixed_g: 4, mask_flags: zf, }, { opcode: 0xF7, os: 1, fixed_g: 5, mask_flags: zf, }, - //{ opcode: 0xF7, os: 1, fixed_g: 6, }, // zero divide - //{ opcode: 0xF7, os: 1, fixed_g: 7, }, + { opcode: 0xF7, os: 1, fixed_g: 6, skip: 1, }, // zero divide + { opcode: 0xF7, os: 1, fixed_g: 7, skip: 1, }, { opcode: 0xF8, }, { opcode: 0xF9, }, From 6d9e8580ef305ba8037a57664837d3fdcaa4f8ca Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 11 Jul 2017 13:47:17 -0500 Subject: [PATCH 0037/2137] Generate instruction calls when modrm/reg decides instructions --- src/native/instructions.c | 3248 ++++++++++++++++++++++++++---------- tests/nasm/create_tests.js | 145 +- 2 files changed, 2499 insertions(+), 894 deletions(-) diff --git a/src/native/instructions.c b/src/native/instructions.c index 46ed09c1..da3473a1 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -563,72 +563,59 @@ static void instr_7D() { jmpcc8(!test_l()); } static void instr_7E() { jmpcc8( test_le()); } static void instr_7F() { jmpcc8(!test_le()); } -static void instr_80() { read_modrm_byte(); - switch(modrm_byte[0] >> 3 & 7) - { - case 0: write_e8(add8(read_write_e8(), read_op8())); break; - case 1: write_e8( or8(read_write_e8(), read_op8())); break; - case 2: write_e8(adc8(read_write_e8(), read_op8())); break; - case 3: write_e8(sbb8(read_write_e8(), read_op8())); break; - case 4: write_e8(and8(read_write_e8(), read_op8())); break; - case 5: write_e8(sub8(read_write_e8(), read_op8())); break; - case 6: write_e8(xor8(read_write_e8(), read_op8())); break; - case 7: cmp8(read_e8(), read_op8()); break; - } -} -static void instr16_81() { read_modrm_byte(); - switch(modrm_byte[0] >> 3 & 7) - { - case 0: write_e16(add16(read_write_e16(), read_op16())); break; - case 1: write_e16( or16(read_write_e16(), read_op16())); break; - case 2: write_e16(adc16(read_write_e16(), read_op16())); break; - case 3: write_e16(sbb16(read_write_e16(), read_op16())); break; - case 4: write_e16(and16(read_write_e16(), read_op16())); break; - case 5: write_e16(sub16(read_write_e16(), read_op16())); break; - case 6: write_e16(xor16(read_write_e16(), read_op16())); break; - case 7: cmp16(read_e16(), read_op16()); break; - } -} -static void instr32_81() { read_modrm_byte(); - switch(modrm_byte[0] >> 3 & 7) - { - case 0: write_e32(add32(read_write_e32(), read_op32s())); break; - case 1: write_e32( or32(read_write_e32(), read_op32s())); break; - case 2: write_e32(adc32(read_write_e32(), read_op32s())); break; - case 3: write_e32(sbb32(read_write_e32(), read_op32s())); break; - case 4: write_e32(and32(read_write_e32(), read_op32s())); break; - case 5: write_e32(sub32(read_write_e32(), read_op32s())); break; - case 6: write_e32(xor32(read_write_e32(), read_op32s())); break; - case 7: cmp32(read_e32s(), read_op32s()); break; - } -} -static void instr_82() { instr_80(); } // alias -static void instr16_83() { read_modrm_byte(); - switch(modrm_byte[0] >> 3 & 7) - { - case 0: write_e16(add16(read_write_e16(), read_op8s())); break; - case 1: write_e16( or16(read_write_e16(), read_op8s())); break; - case 2: write_e16(adc16(read_write_e16(), read_op8s())); break; - case 3: write_e16(sbb16(read_write_e16(), read_op8s())); break; - case 4: write_e16(and16(read_write_e16(), read_op8s())); break; - case 5: write_e16(sub16(read_write_e16(), read_op8s())); break; - case 6: write_e16(xor16(read_write_e16(), read_op8s())); break; - case 7: cmp16(read_e16(), read_op8s()); break; - } -} -static void instr32_83() { read_modrm_byte(); - switch(modrm_byte[0] >> 3 & 7) - { - case 0: write_e32(add32(read_write_e32(), read_op8s())); break; - case 1: write_e32( or32(read_write_e32(), read_op8s())); break; - case 2: write_e32(adc32(read_write_e32(), read_op8s())); break; - case 3: write_e32(sbb32(read_write_e32(), read_op8s())); break; - case 4: write_e32(and32(read_write_e32(), read_op8s())); break; - case 5: write_e32(sub32(read_write_e32(), read_op8s())); break; - case 6: write_e32(xor32(read_write_e32(), read_op8s())); break; - case 7: cmp32(read_e32s(), read_op8s()); break; - } -} +static void instr_80_0() { write_e8(add8(read_write_e8(), read_op8())); } +static void instr_80_1() { write_e8( or8(read_write_e8(), read_op8())); } +static void instr_80_2() { write_e8(adc8(read_write_e8(), read_op8())); } +static void instr_80_3() { write_e8(sbb8(read_write_e8(), read_op8())); } +static void instr_80_4() { write_e8(and8(read_write_e8(), read_op8())); } +static void instr_80_5() { write_e8(sub8(read_write_e8(), read_op8())); } +static void instr_80_6() { write_e8(xor8(read_write_e8(), read_op8())); } +static void instr_80_7() { cmp8(read_e8(), read_op8()); } + +static void instr16_81_0() { write_e16(add16(read_write_e16(), read_op16())); } +static void instr16_81_1() { write_e16( or16(read_write_e16(), read_op16())); } +static void instr16_81_2() { write_e16(adc16(read_write_e16(), read_op16())); } +static void instr16_81_3() { write_e16(sbb16(read_write_e16(), read_op16())); } +static void instr16_81_4() { write_e16(and16(read_write_e16(), read_op16())); } +static void instr16_81_5() { write_e16(sub16(read_write_e16(), read_op16())); } +static void instr16_81_6() { write_e16(xor16(read_write_e16(), read_op16())); } +static void instr16_81_7() { cmp16(read_e16(), read_op16()); } + +static void instr32_81_0() { write_e32(add32(read_write_e32(), read_op32s())); } +static void instr32_81_1() { write_e32( or32(read_write_e32(), read_op32s())); } +static void instr32_81_2() { write_e32(adc32(read_write_e32(), read_op32s())); } +static void instr32_81_3() { write_e32(sbb32(read_write_e32(), read_op32s())); } +static void instr32_81_4() { write_e32(and32(read_write_e32(), read_op32s())); } +static void instr32_81_5() { write_e32(sub32(read_write_e32(), read_op32s())); } +static void instr32_81_6() { write_e32(xor32(read_write_e32(), read_op32s())); } +static void instr32_81_7() { cmp32(read_e32s(), read_op32s()); } + +static void instr_82_0() { write_e8(add8(read_write_e8(), read_op8())); } +static void instr_82_1() { write_e8( or8(read_write_e8(), read_op8())); } +static void instr_82_2() { write_e8(adc8(read_write_e8(), read_op8())); } +static void instr_82_3() { write_e8(sbb8(read_write_e8(), read_op8())); } +static void instr_82_4() { write_e8(and8(read_write_e8(), read_op8())); } +static void instr_82_5() { write_e8(sub8(read_write_e8(), read_op8())); } +static void instr_82_6() { write_e8(xor8(read_write_e8(), read_op8())); } +static void instr_82_7() { cmp8(read_e8(), read_op8()); } + +static void instr16_83_0() { write_e16(add16(read_write_e16(), read_op8s())); } +static void instr16_83_1() { write_e16( or16(read_write_e16(), read_op8s())); } +static void instr16_83_2() { write_e16(adc16(read_write_e16(), read_op8s())); } +static void instr16_83_3() { write_e16(sbb16(read_write_e16(), read_op8s())); } +static void instr16_83_4() { write_e16(and16(read_write_e16(), read_op8s())); } +static void instr16_83_5() { write_e16(sub16(read_write_e16(), read_op8s())); } +static void instr16_83_6() { write_e16(xor16(read_write_e16(), read_op8s())); } +static void instr16_83_7() { cmp16(read_e16s(), read_op8s()); } + +static void instr32_83_0() { write_e32(add32(read_write_e32(), read_op8s())); } +static void instr32_83_1() { write_e32( or32(read_write_e32(), read_op8s())); } +static void instr32_83_2() { write_e32(adc32(read_write_e32(), read_op8s())); } +static void instr32_83_3() { write_e32(sbb32(read_write_e32(), read_op8s())); } +static void instr32_83_4() { write_e32(and32(read_write_e32(), read_op8s())); } +static void instr32_83_5() { write_e32(sub32(read_write_e32(), read_op8s())); } +static void instr32_83_6() { write_e32(xor32(read_write_e32(), read_op8s())); } +static void instr32_83_7() { cmp32(read_e32s(), read_op8s()); } static void instr_84() { read_modrm_byte(); int32_t data = read_e8(); test8(data, read_g8()); } static void instr16_85() { read_modrm_byte(); int32_t data = read_e16(); test16(data, read_g16()); } @@ -964,57 +951,32 @@ static void instr16_BF() { reg16[DI] = read_op16(); } static void instr32_BF() { reg32s[EDI] = read_op32s(); } -static void instr_C0() { read_modrm_byte(); - int32_t op1 = read_write_e8(); - int32_t op2 = read_op8() & 31; - int32_t result = 0; - switch(modrm_byte[0] >> 3 & 7) - { - case 0: result = rol8(op1, op2); break; - case 1: result = ror8(op1, op2); break; - case 2: result = rcl8(op1, op2); break; - case 3: result = rcr8(op1, op2); break; - case 4: result = shl8(op1, op2); break; - case 5: result = shr8(op1, op2); break; - case 6: result = shl8(op1, op2); break; - case 7: result = sar8(op1, op2); break; - } - write_e8(result); -} -static void instr16_C1() { read_modrm_byte(); - int32_t op1 = read_write_e16(); - int32_t op2 = read_op8() & 31; - int32_t result = 0; - switch(modrm_byte[0] >> 3 & 7) - { - case 0: result = rol16(op1, op2); break; - case 1: result = ror16(op1, op2); break; - case 2: result = rcl16(op1, op2); break; - case 3: result = rcr16(op1, op2); break; - case 4: result = shl16(op1, op2); break; - case 5: result = shr16(op1, op2); break; - case 6: result = shl16(op1, op2); break; - case 7: result = sar16(op1, op2); break; - } - write_e16(result); -} -static void instr32_C1() { read_modrm_byte(); - int32_t op1 = read_write_e32(); - int32_t op2 = read_op8() & 31; - int32_t result = 0; - switch(modrm_byte[0] >> 3 & 7) - { - case 0: result = rol32(op1, op2); break; - case 1: result = ror32(op1, op2); break; - case 2: result = rcl32(op1, op2); break; - case 3: result = rcr32(op1, op2); break; - case 4: result = shl32(op1, op2); break; - case 5: result = shr32(op1, op2); break; - case 6: result = shl32(op1, op2); break; - case 7: result = sar32(op1, op2); break; - } - write_e32(result); -} +static void instr_C0_0() { write_e8(rol8(read_write_e8(), read_op8() & 31)); } +static void instr_C0_1() { write_e8(ror8(read_write_e8(), read_op8() & 31)); } +static void instr_C0_2() { write_e8(rcl8(read_write_e8(), read_op8() & 31)); } +static void instr_C0_3() { write_e8(rcr8(read_write_e8(), read_op8() & 31)); } +static void instr_C0_4() { write_e8(shl8(read_write_e8(), read_op8() & 31)); } +static void instr_C0_5() { write_e8(shr8(read_write_e8(), read_op8() & 31)); } +static void instr_C0_6() { write_e8(shl8(read_write_e8(), read_op8() & 31)); } +static void instr_C0_7() { write_e8(sar8(read_write_e8(), read_op8() & 31)); } + +static void instr16_C1_0() { write_e16(rol16(read_write_e16(), read_op8() & 31)); } +static void instr16_C1_1() { write_e16(ror16(read_write_e16(), read_op8() & 31)); } +static void instr16_C1_2() { write_e16(rcl16(read_write_e16(), read_op8() & 31)); } +static void instr16_C1_3() { write_e16(rcr16(read_write_e16(), read_op8() & 31)); } +static void instr16_C1_4() { write_e16(shl16(read_write_e16(), read_op8() & 31)); } +static void instr16_C1_5() { write_e16(shr16(read_write_e16(), read_op8() & 31)); } +static void instr16_C1_6() { write_e16(shl16(read_write_e16(), read_op8() & 31)); } +static void instr16_C1_7() { write_e16(sar16(read_write_e16(), read_op8() & 31)); } + +static void instr32_C1_0() { write_e32(rol32(read_write_e32(), read_op8() & 31)); } +static void instr32_C1_1() { write_e32(ror32(read_write_e32(), read_op8() & 31)); } +static void instr32_C1_2() { write_e32(rcl32(read_write_e32(), read_op8() & 31)); } +static void instr32_C1_3() { write_e32(rcr32(read_write_e32(), read_op8() & 31)); } +static void instr32_C1_4() { write_e32(shl32(read_write_e32(), read_op8() & 31)); } +static void instr32_C1_5() { write_e32(shr32(read_write_e32(), read_op8() & 31)); } +static void instr32_C1_6() { write_e32(shl32(read_write_e32(), read_op8() & 31)); } +static void instr32_C1_7() { write_e32(sar32(read_write_e32(), read_op8() & 31)); } static void instr16_C2() { // retn @@ -1170,106 +1132,60 @@ static void instr32_CF() { diverged(); } -static void instr_D0() { read_modrm_byte(); - int32_t op1 = read_write_e8(); - int32_t result = 0; - switch(modrm_byte[0] >> 3 & 7) - { - case 0: result = rol8(op1, 1); break; - case 1: result = ror8(op1, 1); break; - case 2: result = rcl8(op1, 1); break; - case 3: result = rcr8(op1, 1); break; - case 4: result = shl8(op1, 1); break; - case 5: result = shr8(op1, 1); break; - case 6: result = shl8(op1, 1); break; - case 7: result = sar8(op1, 1); break; - } - write_e8(result); -} -static void instr16_D1() { read_modrm_byte(); - int32_t op1 = read_write_e16(); - int32_t result = 0; - switch(modrm_byte[0] >> 3 & 7) - { - case 0: result = rol16(op1, 1); break; - case 1: result = ror16(op1, 1); break; - case 2: result = rcl16(op1, 1); break; - case 3: result = rcr16(op1, 1); break; - case 4: result = shl16(op1, 1); break; - case 5: result = shr16(op1, 1); break; - case 6: result = shl16(op1, 1); break; - case 7: result = sar16(op1, 1); break; - } - write_e16(result); -} -static void instr32_D1() { read_modrm_byte(); - int32_t op1 = read_write_e32(); - int32_t result = 0; - switch(modrm_byte[0] >> 3 & 7) - { - case 0: result = rol32(op1, 1); break; - case 1: result = ror32(op1, 1); break; - case 2: result = rcl32(op1, 1); break; - case 3: result = rcr32(op1, 1); break; - case 4: result = shl32(op1, 1); break; - case 5: result = shr32(op1, 1); break; - case 6: result = shl32(op1, 1); break; - case 7: result = sar32(op1, 1); break; - } - write_e32(result); -} -static void instr_D2() { read_modrm_byte(); - int32_t op1 = read_write_e8(); - int32_t op2 = reg8[CL] & 31; - int32_t result = 0; - switch(modrm_byte[0] >> 3 & 7) - { - case 0: result = rol8(op1, op2); break; - case 1: result = ror8(op1, op2); break; - case 2: result = rcl8(op1, op2); break; - case 3: result = rcr8(op1, op2); break; - case 4: result = shl8(op1, op2); break; - case 5: result = shr8(op1, op2); break; - case 6: result = shl8(op1, op2); break; - case 7: result = sar8(op1, op2); break; - } - write_e8(result); -} -static void instr16_D3() { read_modrm_byte(); - int32_t op1 = read_write_e16(); - int32_t op2 = reg8[CL] & 31; - int32_t result = 0; - switch(modrm_byte[0] >> 3 & 7) - { - case 0: result = rol16(op1, op2); break; - case 1: result = ror16(op1, op2); break; - case 2: result = rcl16(op1, op2); break; - case 3: result = rcr16(op1, op2); break; - case 4: result = shl16(op1, op2); break; - case 5: result = shr16(op1, op2); break; - case 6: result = shl16(op1, op2); break; - case 7: result = sar16(op1, op2); break; - } - write_e16(result); -} -static void instr32_D3() { read_modrm_byte(); - int32_t op1 = read_write_e32(); - int32_t op2 = reg8[CL] & 31; - int32_t result = 0; - switch(modrm_byte[0] >> 3 & 7) - { - case 0: result = rol32(op1, op2); break; - case 1: result = ror32(op1, op2); break; - case 2: result = rcl32(op1, op2); break; - case 3: result = rcr32(op1, op2); break; - case 4: result = shl32(op1, op2); break; - case 5: result = shr32(op1, op2); break; - case 6: result = shl32(op1, op2); break; - case 7: result = sar32(op1, op2); break; - } - write_e32(result); -} +static void instr_D0_0() { write_e8(rol8(read_write_e8(), 1)); } +static void instr_D0_1() { write_e8(ror8(read_write_e8(), 1)); } +static void instr_D0_2() { write_e8(rcl8(read_write_e8(), 1)); } +static void instr_D0_3() { write_e8(rcr8(read_write_e8(), 1)); } +static void instr_D0_4() { write_e8(shl8(read_write_e8(), 1)); } +static void instr_D0_5() { write_e8(shr8(read_write_e8(), 1)); } +static void instr_D0_6() { write_e8(shl8(read_write_e8(), 1)); } +static void instr_D0_7() { write_e8(sar8(read_write_e8(), 1)); } + +static void instr16_D1_0() { write_e16(rol16(read_write_e16(), 1)); } +static void instr16_D1_1() { write_e16(ror16(read_write_e16(), 1)); } +static void instr16_D1_2() { write_e16(rcl16(read_write_e16(), 1)); } +static void instr16_D1_3() { write_e16(rcr16(read_write_e16(), 1)); } +static void instr16_D1_4() { write_e16(shl16(read_write_e16(), 1)); } +static void instr16_D1_5() { write_e16(shr16(read_write_e16(), 1)); } +static void instr16_D1_6() { write_e16(shl16(read_write_e16(), 1)); } +static void instr16_D1_7() { write_e16(sar16(read_write_e16(), 1)); } + +static void instr32_D1_0() { write_e32(rol32(read_write_e32(), 1)); } +static void instr32_D1_1() { write_e32(ror32(read_write_e32(), 1)); } +static void instr32_D1_2() { write_e32(rcl32(read_write_e32(), 1)); } +static void instr32_D1_3() { write_e32(rcr32(read_write_e32(), 1)); } +static void instr32_D1_4() { write_e32(shl32(read_write_e32(), 1)); } +static void instr32_D1_5() { write_e32(shr32(read_write_e32(), 1)); } +static void instr32_D1_6() { write_e32(shl32(read_write_e32(), 1)); } +static void instr32_D1_7() { write_e32(sar32(read_write_e32(), 1)); } + +static void instr_D2_0() { write_e8(rol8(read_write_e8(), reg8[CL] & 31)); } +static void instr_D2_1() { write_e8(ror8(read_write_e8(), reg8[CL] & 31)); } +static void instr_D2_2() { write_e8(rcl8(read_write_e8(), reg8[CL] & 31)); } +static void instr_D2_3() { write_e8(rcr8(read_write_e8(), reg8[CL] & 31)); } +static void instr_D2_4() { write_e8(shl8(read_write_e8(), reg8[CL] & 31)); } +static void instr_D2_5() { write_e8(shr8(read_write_e8(), reg8[CL] & 31)); } +static void instr_D2_6() { write_e8(shl8(read_write_e8(), reg8[CL] & 31)); } +static void instr_D2_7() { write_e8(sar8(read_write_e8(), reg8[CL] & 31)); } + +static void instr16_D3_0() { write_e16(rol16(read_write_e16(), reg8[CL] & 31)); } +static void instr16_D3_1() { write_e16(ror16(read_write_e16(), reg8[CL] & 31)); } +static void instr16_D3_2() { write_e16(rcl16(read_write_e16(), reg8[CL] & 31)); } +static void instr16_D3_3() { write_e16(rcr16(read_write_e16(), reg8[CL] & 31)); } +static void instr16_D3_4() { write_e16(shl16(read_write_e16(), reg8[CL] & 31)); } +static void instr16_D3_5() { write_e16(shr16(read_write_e16(), reg8[CL] & 31)); } +static void instr16_D3_6() { write_e16(shl16(read_write_e16(), reg8[CL] & 31)); } +static void instr16_D3_7() { write_e16(sar16(read_write_e16(), reg8[CL] & 31)); } + +static void instr32_D3_0() { write_e32(rol32(read_write_e32(), reg8[CL] & 31)); } +static void instr32_D3_1() { write_e32(ror32(read_write_e32(), reg8[CL] & 31)); } +static void instr32_D3_2() { write_e32(rcl32(read_write_e32(), reg8[CL] & 31)); } +static void instr32_D3_3() { write_e32(rcr32(read_write_e32(), reg8[CL] & 31)); } +static void instr32_D3_4() { write_e32(shl32(read_write_e32(), reg8[CL] & 31)); } +static void instr32_D3_5() { write_e32(shr32(read_write_e32(), reg8[CL] & 31)); } +static void instr32_D3_6() { write_e32(shl32(read_write_e32(), reg8[CL] & 31)); } +static void instr32_D3_7() { write_e32(sar32(read_write_e32(), reg8[CL] & 31)); } static void instr_D4() { bcd_aam(read_op8()); @@ -1525,94 +1441,32 @@ static void instr_F5() { flags_changed[0] &= ~1; } -static void instr_F6() { read_modrm_byte(); - switch(modrm_byte[0] >> 3 & 7) - { - case 0: - test8(read_e8(), read_op8()); - break; - case 1: - test8(read_e8(), read_op8()); - break; - case 2: - write_e8(~(read_write_e8())); - break; - case 3: - write_e8(neg8(read_write_e8())); - break; - case 4: - mul8(read_e8()); - break; - case 5: - imul8(read_e8s()); - break; - case 6: - div8(read_e8()); - break; - case 7: - idiv8(read_e8s()); - break; - } -} +static void instr_F6_0() { test8(read_e8(), read_op8()); } +static void instr_F6_1() { test8(read_e8(), read_op8()); } +static void instr_F6_2() { write_e8(~read_write_e8()); } +static void instr_F6_3() { write_e8(neg8(read_write_e8())); } +static void instr_F6_4() { mul8(read_e8()); } +static void instr_F6_5() { imul8(read_e8s()); } +static void instr_F6_6() { div8(read_e8()); } +static void instr_F6_7() { idiv8(read_e8s()); } -static void instr16_F7() { read_modrm_byte(); - switch(modrm_byte[0] >> 3 & 7) - { - case 0: - test16(read_e16(), read_op16()); - break; - case 1: - test16(read_e16(), read_op16()); - break; - case 2: - write_e16(~(read_write_e16())); - break; - case 3: - write_e16(neg16(read_write_e16())); - break; - case 4: - mul16(read_e16()); - break; - case 5: - imul16(read_e16s()); - break; - case 6: - div16(read_e16()); - break; - case 7: - idiv16(read_e16s()); - break; - } -} -static void instr32_F7() { read_modrm_byte(); - switch(modrm_byte[0] >> 3 & 7) - { - case 0: - test32(read_e32s(), read_op32s()); - break; - case 1: - test32(read_e32s(), read_op32s()); - break; - case 2: - write_e32(~(read_write_e32())); - break; - case 3: - write_e32(neg32(read_write_e32())); - break; - case 4: - mul32(read_e32s()); - break; - case 5: - imul32(read_e32s()); - break; - case 6: - div32(read_e32s()); - break; - case 7: - idiv32(read_e32s()); - break; - } -} +static void instr16_F7_0() { test16(read_e16(), read_op16()); } +static void instr16_F7_1() { test16(read_e16(), read_op16()); } +static void instr16_F7_2() { write_e16(~read_write_e16()); } +static void instr16_F7_3() { write_e16(neg16(read_write_e16())); } +static void instr16_F7_4() { mul16(read_e16()); } +static void instr16_F7_5() { imul16(read_e16s()); } +static void instr16_F7_6() { div16(read_e16()); } +static void instr16_F7_7() { idiv16(read_e16s()); } + +static void instr32_F7_0() { test32(read_e32s(), read_op32s()); } +static void instr32_F7_1() { test32(read_e32s(), read_op32s()); } +static void instr32_F7_2() { write_e32(~read_write_e32()); } +static void instr32_F7_3() { write_e32(neg32(read_write_e32())); } +static void instr32_F7_4() { mul32(read_e32s()); } +static void instr32_F7_5() { imul32(read_e32s()); } +static void instr32_F7_6() { div32(read_e32s()); } +static void instr32_F7_7() { idiv32(read_e32s()); } static void instr_F8() { // clc @@ -1689,189 +1543,142 @@ static void instr_FD() { flags[0] |= FLAG_DIRECTION; } -static void instr_FE() { read_modrm_byte(); - int32_t mod = modrm_byte[0] & 56; +static void instr_FE_0() { int32_t data = read_write_e8(); write_e8(inc8(data)); } +static void instr_FE_1() { int32_t data = read_write_e8(); write_e8(dec8(data)); } - if(mod == 0) - { - int32_t data = read_write_e8(); write_e8(inc8(data)); - } - else if(mod == 8) - { - int32_t data = read_write_e8(); write_e8(dec8(data)); - } - else - { - assert(false); - } +static void instr16_FF_0() { write_e16(inc16(read_write_e16())); } +static void instr16_FF_1() { write_e16(dec16(read_write_e16())); } +static void instr16_FF_2() +{ + // call near + int32_t data = read_e16(); + push16(get_real_eip()); + instruction_pointer[0] = get_seg(CS) + data; + dbg_assert(is_asize_32() || get_real_eip() < 0x10000); + diverged(); } -static void instr16_FF() { read_modrm_byte(); - switch(modrm_byte[0] >> 3 & 7) +static void instr16_FF_3() +{ + // callf + if(modrm_byte[0] >= 0xC0) { - case 0: - write_e16(inc16(read_write_e16())); - break; - case 1: - write_e16(dec16(read_write_e16())); - break; - case 2: - // 2, call near - { - int32_t data = read_e16(); - push16(get_real_eip()); - instruction_pointer[0] = get_seg(CS) + data; - dbg_assert(is_asize_32() || get_real_eip() < 0x10000); - diverged(); - } - break; - case 3: - // 3, callf - { - if(modrm_byte[0] >= 0xC0) - { - dbg_log("callf #ud"); - trigger_ud(); - dbg_assert_message(false, "unreachable"); - } + dbg_log("callf #ud"); + trigger_ud(); + dbg_assert_message(false, "unreachable"); + } - int32_t virt_addr = modrm_resolve(modrm_byte[0]); - int32_t new_ip = safe_read16(virt_addr); - int32_t new_cs = safe_read16(virt_addr + 2); + int32_t virt_addr = modrm_resolve(modrm_byte[0]); + int32_t new_ip = safe_read16(virt_addr); + int32_t new_cs = safe_read16(virt_addr + 2); - far_jump(new_ip, new_cs, true); - dbg_assert(is_asize_32() || get_real_eip() < 0x10000); - diverged(); - } - break; - case 4: - // 4, jmp near - { - int32_t data = read_e16(); - instruction_pointer[0] = get_seg(CS) + data; - dbg_assert(is_asize_32() || get_real_eip() < 0x10000); - diverged(); - } - break; - case 5: - // 5, jmpf - { - if(modrm_byte[0] >= 0xC0) - { - dbg_log("jmpf #ud"); - trigger_ud(); - dbg_assert_message(false, "unreachable"); - } + far_jump(new_ip, new_cs, true); + dbg_assert(is_asize_32() || get_real_eip() < 0x10000); + diverged(); +} +static void instr16_FF_4() +{ + // jmp near + int32_t data = read_e16(); + instruction_pointer[0] = get_seg(CS) + data; + dbg_assert(is_asize_32() || get_real_eip() < 0x10000); + diverged(); +} +static void instr16_FF_5() +{ + // jmpf + if(modrm_byte[0] >= 0xC0) + { + dbg_log("jmpf #ud"); + trigger_ud(); + dbg_assert_message(false, "unreachable"); + } - int32_t virt_addr = modrm_resolve(modrm_byte[0]); - int32_t new_ip = safe_read16(virt_addr); - int32_t new_cs = safe_read16(virt_addr + 2); + int32_t virt_addr = modrm_resolve(modrm_byte[0]); + int32_t new_ip = safe_read16(virt_addr); + int32_t new_cs = safe_read16(virt_addr + 2); - far_jump(new_ip, new_cs, false); - dbg_assert(is_asize_32() || get_real_eip() < 0x10000); - diverged(); - } - break; - case 6: - // 6, push - push16(read_e16()); - break; - case 7: + far_jump(new_ip, new_cs, false); + dbg_assert(is_asize_32() || get_real_eip() < 0x10000); + diverged(); +} +static void instr16_FF_6() { push16(read_e16()); } + +static void instr32_FF_0() { write_e32(inc32(read_write_e32())); } +static void instr32_FF_1() { write_e32(dec32(read_write_e32())); } +static void instr32_FF_2() +{ + // call near + int32_t data = read_e32s(); + push32(get_real_eip()); + dbg_assert(is_asize_32() || data < 0x10000); + instruction_pointer[0] = get_seg(CS) + data; + diverged(); +} +static void instr32_FF_3() +{ + // callf + if(modrm_byte[0] >= 0xC0) + { + dbg_log("callf #ud"); + trigger_ud(); + dbg_assert_message(false, "unreachable"); + } + + int32_t virt_addr = modrm_resolve(modrm_byte[0]); + int32_t new_ip = safe_read32s(virt_addr); + int32_t new_cs = safe_read16(virt_addr + 4); + + if(!*protected_mode || vm86_mode()) + { + if(new_ip & 0xFFFF0000) + { + //throw debug.unimpl("#GP handler"); assert(false); + } } + + far_jump(new_ip, new_cs, true); + dbg_assert(is_asize_32() || new_ip < 0x10000); + diverged(); } -static void instr32_FF() { read_modrm_byte(); - switch(modrm_byte[0] >> 3 & 7) +static void instr32_FF_4() +{ + // jmp near + int32_t data = read_e32s(); + dbg_assert(is_asize_32() || data < 0x10000); + instruction_pointer[0] = get_seg(CS) + data; + diverged(); +} +static void instr32_FF_5() +{ + // jmpf + if(modrm_byte[0] >= 0xC0) { - case 0: - write_e32(inc32(read_write_e32())); - break; - case 1: - write_e32(dec32(read_write_e32())); - break; - case 2: - // 2, call near - { - int32_t data = read_e32s(); - push32(get_real_eip()); - - dbg_assert(is_asize_32() || data < 0x10000); - instruction_pointer[0] = get_seg(CS) + data; - diverged(); - } - break; - case 3: - // 3, callf - { - if(modrm_byte[0] >= 0xC0) - { - dbg_log("callf #ud"); - trigger_ud(); - dbg_assert_message(false, "unreachable"); - } - - int32_t virt_addr = modrm_resolve(modrm_byte[0]); - int32_t new_ip = safe_read32s(virt_addr); - int32_t new_cs = safe_read16(virt_addr + 4); - - if(!*protected_mode || vm86_mode()) - { - if(new_ip & 0xFFFF0000) - { - //throw debug.unimpl("#GP handler"); - assert(false); - } - } - - far_jump(new_ip, new_cs, true); - dbg_assert(is_asize_32() || new_ip < 0x10000); - diverged(); - } - break; - case 4: - // 4, jmp near - { - int32_t data = read_e32s(); - dbg_assert(is_asize_32() || data < 0x10000); - instruction_pointer[0] = get_seg(CS) + data; - diverged(); - } - break; - case 5: - // 5, jmpf - { - if(modrm_byte[0] >= 0xC0) - { - dbg_log("jmpf #ud"); - trigger_ud(); - dbg_assert_message(false, "unreachable"); - } - - int32_t virt_addr = modrm_resolve(modrm_byte[0]); - int32_t new_ip = safe_read32s(virt_addr); - int32_t new_cs = safe_read16(virt_addr + 4); - - if(!*protected_mode || vm86_mode()) - { - if(new_ip & 0xFFFF0000) - { - //throw debug.unimpl("#GP handler"); - assert(false); - } - } - - far_jump(new_ip, new_cs, false); - dbg_assert(is_asize_32() || new_ip < 0x10000); - diverged(); - } - break; - case 6: - // push - push32(read_e32s()); - break; - case 7: - assert(false); + dbg_log("jmpf #ud"); + trigger_ud(); + dbg_assert_message(false, "unreachable"); } + + int32_t virt_addr = modrm_resolve(modrm_byte[0]); + int32_t new_ip = safe_read32s(virt_addr); + int32_t new_cs = safe_read16(virt_addr + 4); + + if(!*protected_mode || vm86_mode()) + { + if(new_ip & 0xFFFF0000) + { + //throw debug.unimpl("#GP handler"); + assert(false); + } + } + + far_jump(new_ip, new_cs, false); + dbg_assert(is_asize_32() || new_ip < 0x10000); + diverged(); } +static void instr32_FF_6() { push32(read_e32s()); } + + static void run_instruction(int32_t opcode) { @@ -1881,1290 +1688,2969 @@ static void run_instruction(int32_t opcode) { case 0x00: case 0x00|0x100: +{ instr_00(); - break; +} +break; case 0x01: +{ instr16_01(); - break; +} +break; case 0x01|0x100: +{ instr32_01(); - break; +} +break; case 0x02: case 0x02|0x100: +{ instr_02(); - break; +} +break; case 0x03: +{ instr16_03(); - break; +} +break; case 0x03|0x100: +{ instr32_03(); - break; +} +break; case 0x04: case 0x04|0x100: +{ instr_04(); - break; +} +break; case 0x05: +{ instr16_05(); - break; +} +break; case 0x05|0x100: +{ instr32_05(); - break; +} +break; case 0x06: +{ instr16_06(); - break; +} +break; case 0x06|0x100: +{ instr32_06(); - break; +} +break; case 0x07: +{ instr16_07(); - break; +} +break; case 0x07|0x100: +{ instr32_07(); - break; +} +break; case 0x08: case 0x08|0x100: +{ instr_08(); - break; +} +break; case 0x09: +{ instr16_09(); - break; +} +break; case 0x09|0x100: +{ instr32_09(); - break; +} +break; case 0x0A: case 0x0A|0x100: +{ instr_0A(); - break; +} +break; case 0x0B: +{ instr16_0B(); - break; +} +break; case 0x0B|0x100: +{ instr32_0B(); - break; +} +break; case 0x0C: case 0x0C|0x100: +{ instr_0C(); - break; +} +break; case 0x0D: +{ instr16_0D(); - break; +} +break; case 0x0D|0x100: +{ instr32_0D(); - break; +} +break; case 0x0E: +{ instr16_0E(); - break; +} +break; case 0x0E|0x100: +{ instr32_0E(); - break; +} +break; case 0x0F: +{ instr16_0F(); - break; +} +break; case 0x0F|0x100: +{ instr32_0F(); - break; +} +break; case 0x10: case 0x10|0x100: +{ instr_10(); - break; +} +break; case 0x11: +{ instr16_11(); - break; +} +break; case 0x11|0x100: +{ instr32_11(); - break; +} +break; case 0x12: case 0x12|0x100: +{ instr_12(); - break; +} +break; case 0x13: +{ instr16_13(); - break; +} +break; case 0x13|0x100: +{ instr32_13(); - break; +} +break; case 0x14: case 0x14|0x100: +{ instr_14(); - break; +} +break; case 0x15: +{ instr16_15(); - break; +} +break; case 0x15|0x100: +{ instr32_15(); - break; +} +break; case 0x16: +{ instr16_16(); - break; +} +break; case 0x16|0x100: +{ instr32_16(); - break; +} +break; case 0x17: +{ instr16_17(); - break; +} +break; case 0x17|0x100: +{ instr32_17(); - break; +} +break; case 0x18: case 0x18|0x100: +{ instr_18(); - break; +} +break; case 0x19: +{ instr16_19(); - break; +} +break; case 0x19|0x100: +{ instr32_19(); - break; +} +break; case 0x1A: case 0x1A|0x100: +{ instr_1A(); - break; +} +break; case 0x1B: +{ instr16_1B(); - break; +} +break; case 0x1B|0x100: +{ instr32_1B(); - break; +} +break; case 0x1C: case 0x1C|0x100: +{ instr_1C(); - break; +} +break; case 0x1D: +{ instr16_1D(); - break; +} +break; case 0x1D|0x100: +{ instr32_1D(); - break; +} +break; case 0x1E: +{ instr16_1E(); - break; +} +break; case 0x1E|0x100: +{ instr32_1E(); - break; +} +break; case 0x1F: +{ instr16_1F(); - break; +} +break; case 0x1F|0x100: +{ instr32_1F(); - break; +} +break; case 0x20: case 0x20|0x100: +{ instr_20(); - break; +} +break; case 0x21: +{ instr16_21(); - break; +} +break; case 0x21|0x100: +{ instr32_21(); - break; +} +break; case 0x22: case 0x22|0x100: +{ instr_22(); - break; +} +break; case 0x23: +{ instr16_23(); - break; +} +break; case 0x23|0x100: +{ instr32_23(); - break; +} +break; case 0x24: case 0x24|0x100: +{ instr_24(); - break; +} +break; case 0x25: +{ instr16_25(); - break; +} +break; case 0x25|0x100: +{ instr32_25(); - break; +} +break; case 0x26: case 0x26|0x100: +{ instr_26(); - break; +} +break; case 0x27: case 0x27|0x100: +{ instr_27(); - break; +} +break; case 0x28: case 0x28|0x100: +{ instr_28(); - break; +} +break; case 0x29: +{ instr16_29(); - break; +} +break; case 0x29|0x100: +{ instr32_29(); - break; +} +break; case 0x2A: case 0x2A|0x100: +{ instr_2A(); - break; +} +break; case 0x2B: +{ instr16_2B(); - break; +} +break; case 0x2B|0x100: +{ instr32_2B(); - break; +} +break; case 0x2C: case 0x2C|0x100: +{ instr_2C(); - break; +} +break; case 0x2D: +{ instr16_2D(); - break; +} +break; case 0x2D|0x100: +{ instr32_2D(); - break; +} +break; case 0x2E: case 0x2E|0x100: +{ instr_2E(); - break; +} +break; case 0x2F: case 0x2F|0x100: +{ instr_2F(); - break; +} +break; case 0x30: case 0x30|0x100: +{ instr_30(); - break; +} +break; case 0x31: +{ instr16_31(); - break; +} +break; case 0x31|0x100: +{ instr32_31(); - break; +} +break; case 0x32: case 0x32|0x100: +{ instr_32(); - break; +} +break; case 0x33: +{ instr16_33(); - break; +} +break; case 0x33|0x100: +{ instr32_33(); - break; +} +break; case 0x34: case 0x34|0x100: +{ instr_34(); - break; +} +break; case 0x35: +{ instr16_35(); - break; +} +break; case 0x35|0x100: +{ instr32_35(); - break; +} +break; case 0x36: case 0x36|0x100: +{ instr_36(); - break; +} +break; case 0x37: case 0x37|0x100: +{ instr_37(); - break; +} +break; case 0x38: case 0x38|0x100: +{ instr_38(); - break; +} +break; case 0x39: +{ instr16_39(); - break; +} +break; case 0x39|0x100: +{ instr32_39(); - break; +} +break; case 0x3A: case 0x3A|0x100: +{ instr_3A(); - break; +} +break; case 0x3B: +{ instr16_3B(); - break; +} +break; case 0x3B|0x100: +{ instr32_3B(); - break; +} +break; case 0x3C: case 0x3C|0x100: +{ instr_3C(); - break; +} +break; case 0x3D: +{ instr16_3D(); - break; +} +break; case 0x3D|0x100: +{ instr32_3D(); - break; +} +break; case 0x3E: case 0x3E|0x100: +{ instr_3E(); - break; +} +break; case 0x3F: case 0x3F|0x100: +{ instr_3F(); - break; +} +break; case 0x40: +{ instr16_40(); - break; +} +break; case 0x40|0x100: +{ instr32_40(); - break; +} +break; case 0x41: +{ instr16_41(); - break; +} +break; case 0x41|0x100: +{ instr32_41(); - break; +} +break; case 0x42: +{ instr16_42(); - break; +} +break; case 0x42|0x100: +{ instr32_42(); - break; +} +break; case 0x43: +{ instr16_43(); - break; +} +break; case 0x43|0x100: +{ instr32_43(); - break; +} +break; case 0x44: +{ instr16_44(); - break; +} +break; case 0x44|0x100: +{ instr32_44(); - break; +} +break; case 0x45: +{ instr16_45(); - break; +} +break; case 0x45|0x100: +{ instr32_45(); - break; +} +break; case 0x46: +{ instr16_46(); - break; +} +break; case 0x46|0x100: +{ instr32_46(); - break; +} +break; case 0x47: +{ instr16_47(); - break; +} +break; case 0x47|0x100: +{ instr32_47(); - break; +} +break; case 0x48: +{ instr16_48(); - break; +} +break; case 0x48|0x100: +{ instr32_48(); - break; +} +break; case 0x49: +{ instr16_49(); - break; +} +break; case 0x49|0x100: +{ instr32_49(); - break; +} +break; case 0x4A: +{ instr16_4A(); - break; +} +break; case 0x4A|0x100: +{ instr32_4A(); - break; +} +break; case 0x4B: +{ instr16_4B(); - break; +} +break; case 0x4B|0x100: +{ instr32_4B(); - break; +} +break; case 0x4C: +{ instr16_4C(); - break; +} +break; case 0x4C|0x100: +{ instr32_4C(); - break; +} +break; case 0x4D: +{ instr16_4D(); - break; +} +break; case 0x4D|0x100: +{ instr32_4D(); - break; +} +break; case 0x4E: +{ instr16_4E(); - break; +} +break; case 0x4E|0x100: +{ instr32_4E(); - break; +} +break; case 0x4F: +{ instr16_4F(); - break; +} +break; case 0x4F|0x100: +{ instr32_4F(); - break; +} +break; case 0x50: +{ instr16_50(); - break; +} +break; case 0x50|0x100: +{ instr32_50(); - break; +} +break; case 0x51: +{ instr16_51(); - break; +} +break; case 0x51|0x100: +{ instr32_51(); - break; +} +break; case 0x52: +{ instr16_52(); - break; +} +break; case 0x52|0x100: +{ instr32_52(); - break; +} +break; case 0x53: +{ instr16_53(); - break; +} +break; case 0x53|0x100: +{ instr32_53(); - break; +} +break; case 0x54: +{ instr16_54(); - break; +} +break; case 0x54|0x100: +{ instr32_54(); - break; +} +break; case 0x55: +{ instr16_55(); - break; +} +break; case 0x55|0x100: +{ instr32_55(); - break; +} +break; case 0x56: +{ instr16_56(); - break; +} +break; case 0x56|0x100: +{ instr32_56(); - break; +} +break; case 0x57: +{ instr16_57(); - break; +} +break; case 0x57|0x100: +{ instr32_57(); - break; +} +break; case 0x58: +{ instr16_58(); - break; +} +break; case 0x58|0x100: +{ instr32_58(); - break; +} +break; case 0x59: +{ instr16_59(); - break; +} +break; case 0x59|0x100: +{ instr32_59(); - break; +} +break; case 0x5A: +{ instr16_5A(); - break; +} +break; case 0x5A|0x100: +{ instr32_5A(); - break; +} +break; case 0x5B: +{ instr16_5B(); - break; +} +break; case 0x5B|0x100: +{ instr32_5B(); - break; +} +break; case 0x5C: +{ instr16_5C(); - break; +} +break; case 0x5C|0x100: +{ instr32_5C(); - break; +} +break; case 0x5D: +{ instr16_5D(); - break; +} +break; case 0x5D|0x100: +{ instr32_5D(); - break; +} +break; case 0x5E: +{ instr16_5E(); - break; +} +break; case 0x5E|0x100: +{ instr32_5E(); - break; +} +break; case 0x5F: +{ instr16_5F(); - break; +} +break; case 0x5F|0x100: +{ instr32_5F(); - break; +} +break; case 0x60: +{ instr16_60(); - break; +} +break; case 0x60|0x100: +{ instr32_60(); - break; +} +break; case 0x61: +{ instr16_61(); - break; +} +break; case 0x61|0x100: +{ instr32_61(); - break; +} +break; case 0x62: case 0x62|0x100: +{ instr_62(); - break; +} +break; case 0x63: case 0x63|0x100: +{ instr_63(); - break; +} +break; case 0x64: case 0x64|0x100: +{ instr_64(); - break; +} +break; case 0x65: case 0x65|0x100: +{ instr_65(); - break; +} +break; case 0x66: case 0x66|0x100: +{ instr_66(); - break; +} +break; case 0x67: case 0x67|0x100: +{ instr_67(); - break; +} +break; case 0x68: +{ instr16_68(); - break; +} +break; case 0x68|0x100: +{ instr32_68(); - break; +} +break; case 0x69: +{ instr16_69(); - break; +} +break; case 0x69|0x100: +{ instr32_69(); - break; +} +break; case 0x6A: +{ instr16_6A(); - break; +} +break; case 0x6A|0x100: +{ instr32_6A(); - break; +} +break; case 0x6B: +{ instr16_6B(); - break; +} +break; case 0x6B|0x100: +{ instr32_6B(); - break; +} +break; case 0x6C: case 0x6C|0x100: +{ instr_6C(); - break; +} +break; case 0x6D: +{ instr16_6D(); - break; +} +break; case 0x6D|0x100: +{ instr32_6D(); - break; +} +break; case 0x6E: case 0x6E|0x100: +{ instr_6E(); - break; +} +break; case 0x6F: +{ instr16_6F(); - break; +} +break; case 0x6F|0x100: +{ instr32_6F(); - break; +} +break; case 0x70: case 0x70|0x100: +{ instr_70(); - break; +} +break; case 0x71: case 0x71|0x100: +{ instr_71(); - break; +} +break; case 0x72: case 0x72|0x100: +{ instr_72(); - break; +} +break; case 0x73: case 0x73|0x100: +{ instr_73(); - break; +} +break; case 0x74: case 0x74|0x100: +{ instr_74(); - break; +} +break; case 0x75: case 0x75|0x100: +{ instr_75(); - break; +} +break; case 0x76: case 0x76|0x100: +{ instr_76(); - break; +} +break; case 0x77: case 0x77|0x100: +{ instr_77(); - break; +} +break; case 0x78: case 0x78|0x100: +{ instr_78(); - break; +} +break; case 0x79: case 0x79|0x100: +{ instr_79(); - break; +} +break; case 0x7A: case 0x7A|0x100: +{ instr_7A(); - break; +} +break; case 0x7B: case 0x7B|0x100: +{ instr_7B(); - break; +} +break; case 0x7C: case 0x7C|0x100: +{ instr_7C(); - break; +} +break; case 0x7D: case 0x7D|0x100: +{ instr_7D(); - break; +} +break; case 0x7E: case 0x7E|0x100: +{ instr_7E(); - break; +} +break; case 0x7F: case 0x7F|0x100: +{ instr_7F(); - break; +} +break; case 0x80: case 0x80|0x100: - instr_80(); - break; +{ + read_modrm_byte(); + switch(*modrm_byte >> 3 & 7) + { + case 0: + { + instr_80_0(); + } + break; + case 1: + { + instr_80_1(); + } + break; + case 2: + { + instr_80_2(); + } + break; + case 3: + { + instr_80_3(); + } + break; + case 4: + { + instr_80_4(); + } + break; + case 5: + { + instr_80_5(); + } + break; + case 6: + { + instr_80_6(); + } + break; + case 7: + { + instr_80_7(); + } + break; + default: + assert(false); + } +} +break; case 0x81: - instr16_81(); - break; +{ + read_modrm_byte(); + switch(*modrm_byte >> 3 & 7) + { + case 0: + { + instr16_81_0(); + } + break; + case 1: + { + instr16_81_1(); + } + break; + case 2: + { + instr16_81_2(); + } + break; + case 3: + { + instr16_81_3(); + } + break; + case 4: + { + instr16_81_4(); + } + break; + case 5: + { + instr16_81_5(); + } + break; + case 6: + { + instr16_81_6(); + } + break; + case 7: + { + instr16_81_7(); + } + break; + default: + assert(false); + } +} +break; case 0x81|0x100: - instr32_81(); - break; +{ + read_modrm_byte(); + switch(*modrm_byte >> 3 & 7) + { + case 0: + { + instr32_81_0(); + } + break; + case 1: + { + instr32_81_1(); + } + break; + case 2: + { + instr32_81_2(); + } + break; + case 3: + { + instr32_81_3(); + } + break; + case 4: + { + instr32_81_4(); + } + break; + case 5: + { + instr32_81_5(); + } + break; + case 6: + { + instr32_81_6(); + } + break; + case 7: + { + instr32_81_7(); + } + break; + default: + assert(false); + } +} +break; case 0x82: case 0x82|0x100: - instr_82(); - break; +{ + read_modrm_byte(); + switch(*modrm_byte >> 3 & 7) + { + case 0: + { + instr_82_0(); + } + break; + case 1: + { + instr_82_1(); + } + break; + case 2: + { + instr_82_2(); + } + break; + case 3: + { + instr_82_3(); + } + break; + case 4: + { + instr_82_4(); + } + break; + case 5: + { + instr_82_5(); + } + break; + case 6: + { + instr_82_6(); + } + break; + case 7: + { + instr_82_7(); + } + break; + default: + assert(false); + } +} +break; case 0x83: - instr16_83(); - break; +{ + read_modrm_byte(); + switch(*modrm_byte >> 3 & 7) + { + case 0: + { + instr16_83_0(); + } + break; + case 1: + { + instr16_83_1(); + } + break; + case 2: + { + instr16_83_2(); + } + break; + case 3: + { + instr16_83_3(); + } + break; + case 4: + { + instr16_83_4(); + } + break; + case 5: + { + instr16_83_5(); + } + break; + case 6: + { + instr16_83_6(); + } + break; + case 7: + { + instr16_83_7(); + } + break; + default: + assert(false); + } +} +break; case 0x83|0x100: - instr32_83(); - break; +{ + read_modrm_byte(); + switch(*modrm_byte >> 3 & 7) + { + case 0: + { + instr32_83_0(); + } + break; + case 1: + { + instr32_83_1(); + } + break; + case 2: + { + instr32_83_2(); + } + break; + case 3: + { + instr32_83_3(); + } + break; + case 4: + { + instr32_83_4(); + } + break; + case 5: + { + instr32_83_5(); + } + break; + case 6: + { + instr32_83_6(); + } + break; + case 7: + { + instr32_83_7(); + } + break; + default: + assert(false); + } +} +break; case 0x84: case 0x84|0x100: +{ instr_84(); - break; +} +break; case 0x85: +{ instr16_85(); - break; +} +break; case 0x85|0x100: +{ instr32_85(); - break; +} +break; case 0x86: case 0x86|0x100: +{ instr_86(); - break; +} +break; case 0x87: +{ instr16_87(); - break; +} +break; case 0x87|0x100: +{ instr32_87(); - break; +} +break; case 0x88: case 0x88|0x100: +{ instr_88(); - break; +} +break; case 0x89: +{ instr16_89(); - break; +} +break; case 0x89|0x100: +{ instr32_89(); - break; +} +break; case 0x8A: case 0x8A|0x100: +{ instr_8A(); - break; +} +break; case 0x8B: +{ instr16_8B(); - break; +} +break; case 0x8B|0x100: +{ instr32_8B(); - break; +} +break; case 0x8C: +{ instr16_8C(); - break; +} +break; case 0x8C|0x100: +{ instr32_8C(); - break; +} +break; case 0x8D: +{ instr16_8D(); - break; +} +break; case 0x8D|0x100: +{ instr32_8D(); - break; +} +break; case 0x8E: case 0x8E|0x100: +{ instr_8E(); - break; +} +break; case 0x8F: +{ instr16_8F(); - break; +} +break; case 0x8F|0x100: +{ instr32_8F(); - break; +} +break; case 0x90: case 0x90|0x100: +{ instr_90(); - break; +} +break; case 0x91: +{ instr16_91(); - break; +} +break; case 0x91|0x100: +{ instr32_91(); - break; +} +break; case 0x92: +{ instr16_92(); - break; +} +break; case 0x92|0x100: +{ instr32_92(); - break; +} +break; case 0x93: +{ instr16_93(); - break; +} +break; case 0x93|0x100: +{ instr32_93(); - break; +} +break; case 0x94: +{ instr16_94(); - break; +} +break; case 0x94|0x100: +{ instr32_94(); - break; +} +break; case 0x95: +{ instr16_95(); - break; +} +break; case 0x95|0x100: +{ instr32_95(); - break; +} +break; case 0x96: +{ instr16_96(); - break; +} +break; case 0x96|0x100: +{ instr32_96(); - break; +} +break; case 0x97: +{ instr16_97(); - break; +} +break; case 0x97|0x100: +{ instr32_97(); - break; +} +break; case 0x98: +{ instr16_98(); - break; +} +break; case 0x98|0x100: +{ instr32_98(); - break; +} +break; case 0x99: +{ instr16_99(); - break; +} +break; case 0x99|0x100: +{ instr32_99(); - break; +} +break; case 0x9A: +{ instr16_9A(); - break; +} +break; case 0x9A|0x100: +{ instr32_9A(); - break; +} +break; case 0x9B: case 0x9B|0x100: +{ instr_9B(); - break; +} +break; case 0x9C: +{ instr16_9C(); - break; +} +break; case 0x9C|0x100: +{ instr32_9C(); - break; +} +break; case 0x9D: +{ instr16_9D(); - break; +} +break; case 0x9D|0x100: +{ instr32_9D(); - break; +} +break; case 0x9E: case 0x9E|0x100: +{ instr_9E(); - break; +} +break; case 0x9F: case 0x9F|0x100: +{ instr_9F(); - break; +} +break; case 0xA0: case 0xA0|0x100: +{ instr_A0(); - break; +} +break; case 0xA1: +{ instr16_A1(); - break; +} +break; case 0xA1|0x100: +{ instr32_A1(); - break; +} +break; case 0xA2: case 0xA2|0x100: +{ instr_A2(); - break; +} +break; case 0xA3: +{ instr16_A3(); - break; +} +break; case 0xA3|0x100: +{ instr32_A3(); - break; +} +break; case 0xA4: case 0xA4|0x100: +{ instr_A4(); - break; +} +break; case 0xA5: +{ instr16_A5(); - break; +} +break; case 0xA5|0x100: +{ instr32_A5(); - break; +} +break; case 0xA6: case 0xA6|0x100: +{ instr_A6(); - break; +} +break; case 0xA7: +{ instr16_A7(); - break; +} +break; case 0xA7|0x100: +{ instr32_A7(); - break; +} +break; case 0xA8: case 0xA8|0x100: +{ instr_A8(); - break; +} +break; case 0xA9: +{ instr16_A9(); - break; +} +break; case 0xA9|0x100: +{ instr32_A9(); - break; +} +break; case 0xAA: case 0xAA|0x100: +{ instr_AA(); - break; +} +break; case 0xAB: +{ instr16_AB(); - break; +} +break; case 0xAB|0x100: +{ instr32_AB(); - break; +} +break; case 0xAC: case 0xAC|0x100: +{ instr_AC(); - break; +} +break; case 0xAD: +{ instr16_AD(); - break; +} +break; case 0xAD|0x100: +{ instr32_AD(); - break; +} +break; case 0xAE: case 0xAE|0x100: +{ instr_AE(); - break; +} +break; case 0xAF: +{ instr16_AF(); - break; +} +break; case 0xAF|0x100: +{ instr32_AF(); - break; +} +break; case 0xB0: case 0xB0|0x100: +{ instr_B0(); - break; +} +break; case 0xB1: case 0xB1|0x100: +{ instr_B1(); - break; +} +break; case 0xB2: case 0xB2|0x100: +{ instr_B2(); - break; +} +break; case 0xB3: case 0xB3|0x100: +{ instr_B3(); - break; +} +break; case 0xB4: case 0xB4|0x100: +{ instr_B4(); - break; +} +break; case 0xB5: case 0xB5|0x100: +{ instr_B5(); - break; +} +break; case 0xB6: case 0xB6|0x100: +{ instr_B6(); - break; +} +break; case 0xB7: case 0xB7|0x100: +{ instr_B7(); - break; +} +break; case 0xB8: +{ instr16_B8(); - break; +} +break; case 0xB8|0x100: +{ instr32_B8(); - break; +} +break; case 0xB9: +{ instr16_B9(); - break; +} +break; case 0xB9|0x100: +{ instr32_B9(); - break; +} +break; case 0xBA: +{ instr16_BA(); - break; +} +break; case 0xBA|0x100: +{ instr32_BA(); - break; +} +break; case 0xBB: +{ instr16_BB(); - break; +} +break; case 0xBB|0x100: +{ instr32_BB(); - break; +} +break; case 0xBC: +{ instr16_BC(); - break; +} +break; case 0xBC|0x100: +{ instr32_BC(); - break; +} +break; case 0xBD: +{ instr16_BD(); - break; +} +break; case 0xBD|0x100: +{ instr32_BD(); - break; +} +break; case 0xBE: +{ instr16_BE(); - break; +} +break; case 0xBE|0x100: +{ instr32_BE(); - break; +} +break; case 0xBF: +{ instr16_BF(); - break; +} +break; case 0xBF|0x100: +{ instr32_BF(); - break; +} +break; case 0xC0: case 0xC0|0x100: - instr_C0(); - break; +{ + read_modrm_byte(); + switch(*modrm_byte >> 3 & 7) + { + case 0: + { + instr_C0_0(); + } + break; + case 1: + { + instr_C0_1(); + } + break; + case 2: + { + instr_C0_2(); + } + break; + case 3: + { + instr_C0_3(); + } + break; + case 4: + { + instr_C0_4(); + } + break; + case 5: + { + instr_C0_5(); + } + break; + case 6: + { + instr_C0_6(); + } + break; + case 7: + { + instr_C0_7(); + } + break; + default: + assert(false); + } +} +break; case 0xC1: - instr16_C1(); - break; +{ + read_modrm_byte(); + switch(*modrm_byte >> 3 & 7) + { + case 0: + { + instr16_C1_0(); + } + break; + case 1: + { + instr16_C1_1(); + } + break; + case 2: + { + instr16_C1_2(); + } + break; + case 3: + { + instr16_C1_3(); + } + break; + case 4: + { + instr16_C1_4(); + } + break; + case 5: + { + instr16_C1_5(); + } + break; + case 6: + { + instr16_C1_6(); + } + break; + case 7: + { + instr16_C1_7(); + } + break; + default: + assert(false); + } +} +break; case 0xC1|0x100: - instr32_C1(); - break; +{ + read_modrm_byte(); + switch(*modrm_byte >> 3 & 7) + { + case 0: + { + instr32_C1_0(); + } + break; + case 1: + { + instr32_C1_1(); + } + break; + case 2: + { + instr32_C1_2(); + } + break; + case 3: + { + instr32_C1_3(); + } + break; + case 4: + { + instr32_C1_4(); + } + break; + case 5: + { + instr32_C1_5(); + } + break; + case 6: + { + instr32_C1_6(); + } + break; + case 7: + { + instr32_C1_7(); + } + break; + default: + assert(false); + } +} +break; case 0xC2: +{ instr16_C2(); - break; +} +break; case 0xC2|0x100: +{ instr32_C2(); - break; +} +break; case 0xC3: +{ instr16_C3(); - break; +} +break; case 0xC3|0x100: +{ instr32_C3(); - break; +} +break; case 0xC4: +{ instr16_C4(); - break; +} +break; case 0xC4|0x100: +{ instr32_C4(); - break; +} +break; case 0xC5: +{ instr16_C5(); - break; +} +break; case 0xC5|0x100: +{ instr32_C5(); - break; +} +break; case 0xC6: case 0xC6|0x100: +{ instr_C6(); - break; +} +break; case 0xC7: +{ instr16_C7(); - break; +} +break; case 0xC7|0x100: +{ instr32_C7(); - break; +} +break; case 0xC8: +{ instr16_C8(); - break; +} +break; case 0xC8|0x100: +{ instr32_C8(); - break; +} +break; case 0xC9: +{ instr16_C9(); - break; +} +break; case 0xC9|0x100: +{ instr32_C9(); - break; +} +break; case 0xCA: +{ instr16_CA(); - break; +} +break; case 0xCA|0x100: +{ instr32_CA(); - break; +} +break; case 0xCB: +{ instr16_CB(); - break; +} +break; case 0xCB|0x100: +{ instr32_CB(); - break; +} +break; case 0xCC: case 0xCC|0x100: +{ instr_CC(); - break; +} +break; case 0xCD: case 0xCD|0x100: +{ instr_CD(); - break; +} +break; case 0xCE: case 0xCE|0x100: +{ instr_CE(); - break; +} +break; case 0xCF: +{ instr16_CF(); - break; +} +break; case 0xCF|0x100: +{ instr32_CF(); - break; +} +break; case 0xD0: case 0xD0|0x100: - instr_D0(); - break; +{ + read_modrm_byte(); + switch(*modrm_byte >> 3 & 7) + { + case 0: + { + instr_D0_0(); + } + break; + case 1: + { + instr_D0_1(); + } + break; + case 2: + { + instr_D0_2(); + } + break; + case 3: + { + instr_D0_3(); + } + break; + case 4: + { + instr_D0_4(); + } + break; + case 5: + { + instr_D0_5(); + } + break; + case 6: + { + instr_D0_6(); + } + break; + case 7: + { + instr_D0_7(); + } + break; + default: + assert(false); + } +} +break; case 0xD1: - instr16_D1(); - break; +{ + read_modrm_byte(); + switch(*modrm_byte >> 3 & 7) + { + case 0: + { + instr16_D1_0(); + } + break; + case 1: + { + instr16_D1_1(); + } + break; + case 2: + { + instr16_D1_2(); + } + break; + case 3: + { + instr16_D1_3(); + } + break; + case 4: + { + instr16_D1_4(); + } + break; + case 5: + { + instr16_D1_5(); + } + break; + case 6: + { + instr16_D1_6(); + } + break; + case 7: + { + instr16_D1_7(); + } + break; + default: + assert(false); + } +} +break; case 0xD1|0x100: - instr32_D1(); - break; +{ + read_modrm_byte(); + switch(*modrm_byte >> 3 & 7) + { + case 0: + { + instr32_D1_0(); + } + break; + case 1: + { + instr32_D1_1(); + } + break; + case 2: + { + instr32_D1_2(); + } + break; + case 3: + { + instr32_D1_3(); + } + break; + case 4: + { + instr32_D1_4(); + } + break; + case 5: + { + instr32_D1_5(); + } + break; + case 6: + { + instr32_D1_6(); + } + break; + case 7: + { + instr32_D1_7(); + } + break; + default: + assert(false); + } +} +break; case 0xD2: case 0xD2|0x100: - instr_D2(); - break; +{ + read_modrm_byte(); + switch(*modrm_byte >> 3 & 7) + { + case 0: + { + instr_D2_0(); + } + break; + case 1: + { + instr_D2_1(); + } + break; + case 2: + { + instr_D2_2(); + } + break; + case 3: + { + instr_D2_3(); + } + break; + case 4: + { + instr_D2_4(); + } + break; + case 5: + { + instr_D2_5(); + } + break; + case 6: + { + instr_D2_6(); + } + break; + case 7: + { + instr_D2_7(); + } + break; + default: + assert(false); + } +} +break; case 0xD3: - instr16_D3(); - break; +{ + read_modrm_byte(); + switch(*modrm_byte >> 3 & 7) + { + case 0: + { + instr16_D3_0(); + } + break; + case 1: + { + instr16_D3_1(); + } + break; + case 2: + { + instr16_D3_2(); + } + break; + case 3: + { + instr16_D3_3(); + } + break; + case 4: + { + instr16_D3_4(); + } + break; + case 5: + { + instr16_D3_5(); + } + break; + case 6: + { + instr16_D3_6(); + } + break; + case 7: + { + instr16_D3_7(); + } + break; + default: + assert(false); + } +} +break; case 0xD3|0x100: - instr32_D3(); - break; +{ + read_modrm_byte(); + switch(*modrm_byte >> 3 & 7) + { + case 0: + { + instr32_D3_0(); + } + break; + case 1: + { + instr32_D3_1(); + } + break; + case 2: + { + instr32_D3_2(); + } + break; + case 3: + { + instr32_D3_3(); + } + break; + case 4: + { + instr32_D3_4(); + } + break; + case 5: + { + instr32_D3_5(); + } + break; + case 6: + { + instr32_D3_6(); + } + break; + case 7: + { + instr32_D3_7(); + } + break; + default: + assert(false); + } +} +break; case 0xD4: case 0xD4|0x100: +{ instr_D4(); - break; +} +break; case 0xD5: case 0xD5|0x100: +{ instr_D5(); - break; +} +break; case 0xD6: case 0xD6|0x100: +{ instr_D6(); - break; +} +break; case 0xD7: case 0xD7|0x100: +{ instr_D7(); - break; +} +break; case 0xD8: case 0xD8|0x100: +{ instr_D8(); - break; +} +break; case 0xD9: case 0xD9|0x100: +{ instr_D9(); - break; +} +break; case 0xDA: case 0xDA|0x100: +{ instr_DA(); - break; +} +break; case 0xDB: case 0xDB|0x100: +{ instr_DB(); - break; +} +break; case 0xDC: case 0xDC|0x100: +{ instr_DC(); - break; +} +break; case 0xDD: case 0xDD|0x100: +{ instr_DD(); - break; +} +break; case 0xDE: case 0xDE|0x100: +{ instr_DE(); - break; +} +break; case 0xDF: case 0xDF|0x100: +{ instr_DF(); - break; +} +break; case 0xE0: case 0xE0|0x100: +{ instr_E0(); - break; +} +break; case 0xE1: case 0xE1|0x100: +{ instr_E1(); - break; +} +break; case 0xE2: case 0xE2|0x100: +{ instr_E2(); - break; +} +break; case 0xE3: case 0xE3|0x100: +{ instr_E3(); - break; +} +break; case 0xE4: case 0xE4|0x100: +{ instr_E4(); - break; +} +break; case 0xE5: +{ instr16_E5(); - break; +} +break; case 0xE5|0x100: +{ instr32_E5(); - break; +} +break; case 0xE6: case 0xE6|0x100: +{ instr_E6(); - break; +} +break; case 0xE7: +{ instr16_E7(); - break; +} +break; case 0xE7|0x100: +{ instr32_E7(); - break; +} +break; case 0xE8: +{ instr16_E8(); - break; +} +break; case 0xE8|0x100: +{ instr32_E8(); - break; +} +break; case 0xE9: +{ instr16_E9(); - break; +} +break; case 0xE9|0x100: +{ instr32_E9(); - break; +} +break; case 0xEA: +{ instr16_EA(); - break; +} +break; case 0xEA|0x100: +{ instr32_EA(); - break; +} +break; case 0xEB: case 0xEB|0x100: +{ instr_EB(); - break; +} +break; case 0xEC: case 0xEC|0x100: +{ instr_EC(); - break; +} +break; case 0xED: +{ instr16_ED(); - break; +} +break; case 0xED|0x100: +{ instr32_ED(); - break; +} +break; case 0xEE: case 0xEE|0x100: +{ instr_EE(); - break; +} +break; case 0xEF: +{ instr16_EF(); - break; +} +break; case 0xEF|0x100: +{ instr32_EF(); - break; +} +break; case 0xF0: case 0xF0|0x100: +{ instr_F0(); - break; +} +break; case 0xF1: case 0xF1|0x100: +{ instr_F1(); - break; +} +break; case 0xF2: case 0xF2|0x100: +{ instr_F2(); - break; +} +break; case 0xF3: case 0xF3|0x100: +{ instr_F3(); - break; +} +break; case 0xF4: case 0xF4|0x100: +{ instr_F4(); - break; +} +break; case 0xF5: case 0xF5|0x100: +{ instr_F5(); - break; +} +break; case 0xF6: case 0xF6|0x100: - instr_F6(); - break; +{ + read_modrm_byte(); + switch(*modrm_byte >> 3 & 7) + { + case 0: + { + instr_F6_0(); + } + break; + case 1: + { + instr_F6_1(); + } + break; + case 2: + { + instr_F6_2(); + } + break; + case 3: + { + instr_F6_3(); + } + break; + case 4: + { + instr_F6_4(); + } + break; + case 5: + { + instr_F6_5(); + } + break; + case 6: + { + instr_F6_6(); + } + break; + case 7: + { + instr_F6_7(); + } + break; + default: + assert(false); + } +} +break; case 0xF7: - instr16_F7(); - break; +{ + read_modrm_byte(); + switch(*modrm_byte >> 3 & 7) + { + case 0: + { + instr16_F7_0(); + } + break; + case 1: + { + instr16_F7_1(); + } + break; + case 2: + { + instr16_F7_2(); + } + break; + case 3: + { + instr16_F7_3(); + } + break; + case 4: + { + instr16_F7_4(); + } + break; + case 5: + { + instr16_F7_5(); + } + break; + case 6: + { + instr16_F7_6(); + } + break; + case 7: + { + instr16_F7_7(); + } + break; + default: + assert(false); + } +} +break; case 0xF7|0x100: - instr32_F7(); - break; +{ + read_modrm_byte(); + switch(*modrm_byte >> 3 & 7) + { + case 0: + { + instr32_F7_0(); + } + break; + case 1: + { + instr32_F7_1(); + } + break; + case 2: + { + instr32_F7_2(); + } + break; + case 3: + { + instr32_F7_3(); + } + break; + case 4: + { + instr32_F7_4(); + } + break; + case 5: + { + instr32_F7_5(); + } + break; + case 6: + { + instr32_F7_6(); + } + break; + case 7: + { + instr32_F7_7(); + } + break; + default: + assert(false); + } +} +break; case 0xF8: case 0xF8|0x100: +{ instr_F8(); - break; +} +break; case 0xF9: case 0xF9|0x100: +{ instr_F9(); - break; +} +break; case 0xFA: case 0xFA|0x100: +{ instr_FA(); - break; +} +break; case 0xFB: case 0xFB|0x100: +{ instr_FB(); - break; +} +break; case 0xFC: case 0xFC|0x100: +{ instr_FC(); - break; +} +break; case 0xFD: case 0xFD|0x100: +{ instr_FD(); - break; +} +break; case 0xFE: case 0xFE|0x100: - instr_FE(); - break; +{ + read_modrm_byte(); + switch(*modrm_byte >> 3 & 7) + { + case 0: + { + instr_FE_0(); + } + break; + case 1: + { + instr_FE_1(); + } + break; + default: + assert(false); + } +} +break; case 0xFF: - instr16_FF(); - break; +{ + read_modrm_byte(); + switch(*modrm_byte >> 3 & 7) + { + case 0: + { + instr16_FF_0(); + } + break; + case 1: + { + instr16_FF_1(); + } + break; + case 2: + { + instr16_FF_2(); + } + break; + case 3: + { + instr16_FF_3(); + } + break; + case 4: + { + instr16_FF_4(); + } + break; + case 5: + { + instr16_FF_5(); + } + break; + case 6: + { + instr16_FF_6(); + } + break; + default: + assert(false); + } +} +break; case 0xFF|0x100: - instr32_FF(); - break; +{ + read_modrm_byte(); + switch(*modrm_byte >> 3 & 7) + { + case 0: + { + instr32_FF_0(); + } + break; + case 1: + { + instr32_FF_1(); + } + break; + case 2: + { + instr32_FF_2(); + } + break; + case 3: + { + instr32_FF_3(); + } + break; + case 4: + { + instr32_FF_4(); + } + break; + case 5: + { + instr32_FF_5(); + } + break; + case 6: + { + instr32_FF_6(); + } + break; + default: + assert(false); + } +} +break; default: assert(false); } diff --git a/tests/nasm/create_tests.js b/tests/nasm/create_tests.js index 9a9774ed..558db507 100755 --- a/tests/nasm/create_tests.js +++ b/tests/nasm/create_tests.js @@ -618,6 +618,117 @@ encodings.sort((e1, e2) => { 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 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); + 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); + } + } + + return code; +} + +function gen_instruction_body(encoding, variant) +{ + let suffix = encoding[0].os ? `${variant}` : ""; + let opcode = encoding[0].opcode & 0xFF; + + let opcode_hex = opcode.toString(16).toUpperCase(); + if(opcode_hex.length === 1) opcode_hex = "0" + opcode_hex; + + //if(opcode === 0 || opcode === 1 || opcode === 2 || opcode === 3) + //{ + // return [ + // `int32_t modrm_byte = read_imm8();`, + // `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.length > 1) + { + 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 [ + "read_modrm_byte();", + { + type: "switch", + condition: "*modrm_byte >> 3 & 7", + body: cases.map(case_ => { + return { + type: "case", + cases: [case_.fixed_g], + body: [`instr${suffix}_${opcode_hex}_${case_.fixed_g}();`] + }; + }).concat([ + { + type: "default-case", + body: ["assert(false);"], + } + ]), + } + ]; + } + else + { + return [`instr${suffix}_${opcode_hex}();`]; + } +} + function gen_table() { let by_opcode = Object.create(null); @@ -643,7 +754,7 @@ function gen_table() } } - let t = ``; + let t = []; for(let opcode = 0; opcode < 0x100; opcode++) { let encoding = by_opcode[opcode]; @@ -654,23 +765,31 @@ function gen_table() if(encoding[0].os) { - t += `case 0x${opcode_hex}:\n`; - t += ` instr16_${opcode_hex}();\n`; - t += ` break;\n`; - t += `case 0x${opcode_hex}|0x100:\n`; - t += ` instr32_${opcode_hex}();\n`; - t += ` break;\n`; + 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 += `case 0x${opcode_hex}:\n`; - t += `case 0x${opcode_hex}|0x100:\n`; - t += ` instr_${opcode_hex}();\n`; - t += ` break;\n`; + t.push({ + type: "case", + cases: [`0x${opcode_hex}`, `0x${opcode_hex}|0x100`], + body: gen_instruction_body(encoding, undefined), + }); } } - t += `default: assert(false);\n`; - fs.writeFileSync("/tmp/table", t); + t.push({ + type: "default-case", + body: ["assert(false);"], + }); + fs.writeFileSync("/tmp/table", print_syntax_tree(t).join("\n")); let t0f_16 = ``; let t0f_32 = ``; From 0ef4508b22a54f512e0566f113a71fb95e2767d0 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 11 Jul 2017 13:57:38 -0500 Subject: [PATCH 0038/2137] Add v86.wasm to test targets --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 36c45b8c..eeefb8f1 100644 --- a/Makefile +++ b/Makefile @@ -187,20 +187,20 @@ $(CLOSURE): mv $(CLOSURE_DIR)/*.jar $(CLOSURE) rm $(CLOSURE_DIR)/compiler-latest.zip -tests: build/libv86.js +tests: build/libv86.js build/v86.wasm ./tests/full/run.js -nasmtests: build/libv86.js +nasmtests: build/libv86.js build/v86.wasm $(MAKE) -C $(NASM_TEST_DIR) all $(NASM_TEST_DIR)/run.js -qemutests: build/libv86.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 -kvm-unit-test: build/libv86.js +kvm-unit-test: build/libv86.js build/v86.wasm (cd tests/kvm-unit-tests && ./configure) $(MAKE) -C tests/kvm-unit-tests tests/kvm-unit-tests/run.js tests/kvm-unit-tests/x86/realmode.flat From 14875dafb279577d0ddb3fc06f9cbd308faf8f02 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 11 Jul 2017 13:58:06 -0500 Subject: [PATCH 0039/2137] Move code into hex_byte --- tests/nasm/create_tests.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tests/nasm/create_tests.js b/tests/nasm/create_tests.js index 558db507..bdef3ce8 100755 --- a/tests/nasm/create_tests.js +++ b/tests/nasm/create_tests.js @@ -630,6 +630,13 @@ 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 = []; @@ -679,10 +686,9 @@ function print_syntax_tree(statements) function gen_instruction_body(encoding, variant) { let suffix = encoding[0].os ? `${variant}` : ""; - let opcode = encoding[0].opcode & 0xFF; - let opcode_hex = opcode.toString(16).toUpperCase(); - if(opcode_hex.length === 1) opcode_hex = "0" + opcode_hex; + let opcode = encoding[0].opcode & 0xFF; + let opcode_hex = hex_byte(opcode); //if(opcode === 0 || opcode === 1 || opcode === 2 || opcode === 3) //{ @@ -760,8 +766,7 @@ function gen_table() let encoding = by_opcode[opcode]; console.assert(encoding && encoding.length); - let opcode_hex = opcode.toString(16).toUpperCase(); - if(opcode_hex.length === 1) opcode_hex = "0" + opcode_hex; + let opcode_hex = hex_byte(opcode); if(encoding[0].os) { From a29221a6b2daac302915d029b69aaeb9f5d38f8b Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 11 Jul 2017 15:18:31 -0500 Subject: [PATCH 0040/2137] Prepare for catching exceptions in nasm test --- tests/nasm/run.js | 149 ++++++++++++++++++++++++++++------------------ 1 file changed, 90 insertions(+), 59 deletions(-) diff --git a/tests/nasm/run.js b/tests/nasm/run.js index 629eac20..7eae4e22 100755 --- a/tests/nasm/run.js +++ b/tests/nasm/run.js @@ -1,6 +1,18 @@ #!/usr/bin/env node 'use strict'; +// Mapping between signals and x86 exceptions: +// "Program received signal SIGILL, Illegal instruction." -> #UD +// "Program received signal SIGFPE, Arithmetic exception." -> #GP +// to be determined -> #GP +// to be determined -> #NM +// to be determined -> #TS +// to be determined -> #NP +// to be determined -> #SS +// to be determined -> #PF + +// A #UD might indicate a bug in the test generation + const fs = require('fs'); const path = require('path'); const os = require('os'); @@ -51,6 +63,16 @@ function h(n, len) if (cluster.isMaster) { function extract_json(name, fixture_text) { + if(fixture_text.includes("SIGFPE, Arithmetic exception")) + { + return { exception: "DE", }; + } + + if(fixture_text.includes("SIGILL, Illegal instruction")) + { + return { exception: "UD", }; + } + if(fixture_text.includes("Program received signal") || fixture_text.includes("SIGILL")) { throw new Error("Test was killed during execution by gdb: " + name); @@ -63,7 +85,8 @@ if (cluster.isMaster) { } try { - return JSON.parse(regex_match[1]); + let array = JSON.parse(regex_match[1]); + return { array: array }; } catch (e) { throw e; @@ -77,11 +100,11 @@ if (cluster.isMaster) { let fixture_name = name + ".fixture"; let img_name = name + ".img"; let fixture_text = fs.readFileSync(TEST_DIR + fixture_name); - let fixture_array = extract_json(name, fixture_text); + let fixture = extract_json(name, fixture_text); worker.send({ img_name: img_name, - fixture_array: fixture_array + fixture: fixture, }); current_test++; @@ -187,63 +210,71 @@ else { const evaluated_memory = new Int32Array(cpu.mem8.slice(esp, esp + 16).buffer); let individual_failures = []; - let offset = 0; - const expected_reg32s = test.fixture_array.slice(offset, offset += 8); - const expected_mmx_registers = test.fixture_array.slice(offset, offset += 16); - const expected_xmm_registers = test.fixture_array.slice(offset, offset += 32); - const expected_memory = test.fixture_array.slice(offset, offset += 4); - const expected_eflags = test.fixture_array[offset] & MASK_ARITH; - - for (let i = 0; i < cpu.reg32s.length; i++) { - if(i === 4) continue; // TODO: Same stack for elf and multiboot - let reg = cpu.reg32s[i]; - if (reg !== expected_reg32s[i]) { - individual_failures.push({ - name: "cpu.reg32s[" + i + "]", - expected: expected_reg32s[i], - actual: reg, - }); - } - } - - for (let i = 0; i < evaluated_mmxs.length; i++) { - if (evaluated_mmxs[i] !== expected_mmx_registers[i]) { - individual_failures.push({ - name: "mm" + (i >> 1) + ".int32[" + (i & 1) + "] (cpu.reg_mmx[" + i + "])", - expected: expected_mmx_registers[i], - actual: evaluated_mmxs[i], - }); - } - } - - for (let i = 0; i < evaluated_xmms.length; i++) { - if (evaluated_xmms[i] !== expected_xmm_registers[i]) { - individual_failures.push({ - name: "xmm" + (i >> 2) + ".int32[" + (i & 3) + "] (cpu.reg_xmm[" + i + "])", - expected: expected_xmm_registers[i], - actual: evaluated_xmms[i], - }); - } - } - - for (let i = 0; i < evaluated_memory.length; i++) { - if (evaluated_memory[i] !== expected_memory[i]) { - individual_failures.push({ - name: "mem[" + i + "]", - expected: expected_memory[i], - actual: evaluated_memory[i], - }); - } - } - - const seen_eflags = cpu.get_eflags() & MASK_ARITH; - if(seen_eflags !== expected_eflags) + if(test.exception) { - individual_failures.push({ - name: "eflags", - expected: expected_eflags, - actual: seen_eflags, - }); + throw "TODO: Handle exceptions"; + } + + if(test.fixture.array) + { + let offset = 0; + const expected_reg32s = test.fixture.array.slice(offset, offset += 8); + const expected_mmx_registers = test.fixture.array.slice(offset, offset += 16); + const expected_xmm_registers = test.fixture.array.slice(offset, offset += 32); + const expected_memory = test.fixture.array.slice(offset, offset += 4); + const expected_eflags = test.fixture.array[offset] & MASK_ARITH; + + for (let i = 0; i < cpu.reg32s.length; i++) { + if(i === 4) continue; // TODO: Same stack for elf and multiboot + let reg = cpu.reg32s[i]; + if (reg !== expected_reg32s[i]) { + individual_failures.push({ + name: "cpu.reg32s[" + i + "]", + expected: expected_reg32s[i], + actual: reg, + }); + } + } + + for (let i = 0; i < evaluated_mmxs.length; i++) { + if (evaluated_mmxs[i] !== expected_mmx_registers[i]) { + individual_failures.push({ + name: "mm" + (i >> 1) + ".int32[" + (i & 1) + "] (cpu.reg_mmx[" + i + "])", + expected: expected_mmx_registers[i], + actual: evaluated_mmxs[i], + }); + } + } + + for (let i = 0; i < evaluated_xmms.length; i++) { + if (evaluated_xmms[i] !== expected_xmm_registers[i]) { + individual_failures.push({ + name: "xmm" + (i >> 2) + ".int32[" + (i & 3) + "] (cpu.reg_xmm[" + i + "])", + expected: expected_xmm_registers[i], + actual: evaluated_xmms[i], + }); + } + } + + for (let i = 0; i < evaluated_memory.length; i++) { + if (evaluated_memory[i] !== expected_memory[i]) { + individual_failures.push({ + name: "mem[" + i + "]", + expected: expected_memory[i], + actual: evaluated_memory[i], + }); + } + } + + const seen_eflags = cpu.get_eflags() & MASK_ARITH; + if(seen_eflags !== expected_eflags) + { + individual_failures.push({ + name: "eflags", + expected: expected_eflags, + actual: seen_eflags, + }); + } } if (individual_failures.length > 0) { From fc0e438348966ec2a174039c3c1182278bb6784e Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 11 Jul 2017 17:36:56 -0500 Subject: [PATCH 0041/2137] nasm test: Test with different register than eax --- tests/nasm/create_tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/nasm/create_tests.js b/tests/nasm/create_tests.js index bdef3ce8..3477ab25 100755 --- a/tests/nasm/create_tests.js +++ b/tests/nasm/create_tests.js @@ -1001,7 +1001,7 @@ function create_nasm(op, config) if(is_modrm) { - let g = 0; + let g = 7; // edi / di / bh if(op.fixed_g !== undefined) { From 809fc6638b4395506230c6a888ca19cb5519b8da Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 17 Jul 2017 14:50:20 -0500 Subject: [PATCH 0042/2137] Fix LSL: segment types considered invalid --- src/cpu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpu.js b/src/cpu.js index 8d05509c..f3cc1c56 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -4338,7 +4338,7 @@ CPU.prototype.lsl = function(selector, original) dbg_log("lsl sel=" + h(selector, 4), LOG_CPU); /** @const */ - var LSL_INVALID_TYPE = 1 << 0 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 8 | + 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; var info = this.lookup_segment_selector(selector); From 2ad9406d62532dc892e03eebfb4357d8be850eee Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 17 Jul 2017 14:51:04 -0500 Subject: [PATCH 0043/2137] Bump LOOP_COUNTER for native execution --- src/native/const.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/const.h b/src/native/const.h index 2b1cc86d..97dbd3bc 100644 --- a/src/native/const.h +++ b/src/native/const.h @@ -146,7 +146,7 @@ /** * How many cycles the CPU does at a time before running hardware timers */ -#define LOOP_COUNTER 11001 +#define LOOP_COUNTER 20011 #define TSC_RATE (8 * 1024) From 5253f810d6d62047a4a6fe3d2b53447c8ce41d8c Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 17 Jul 2017 14:56:05 -0500 Subject: [PATCH 0044/2137] Warn on cr0.am --- src/const.js | 2 ++ src/cpu.js | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/src/const.js b/src/const.js index fc0fb66f..5d3f5642 100644 --- a/src/const.js +++ b/src/const.js @@ -205,6 +205,8 @@ var /** @const */ CR0_WP = 1 << 16, /** @const */ + CR0_AM = 1 << 18, + /** @const */ CR0_NW = 1 << 29, /** @const */ CR0_CD = 1 << 30, diff --git a/src/cpu.js b/src/cpu.js index f3cc1c56..b2f2750e 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -1302,6 +1302,11 @@ CPU.prototype.set_cr0 = function(cr0) { //dbg_log("cr0 = " + h(this.cr[0] >>> 0), LOG_CPU); + if(cr0 & CR0_AM) + { + dbg_log("Warning: Unimplemented: cr0 alignment mask", LOG_CPU); + } + if((cr0 & (CR0_PE | CR0_PG)) === CR0_PG) { // cannot load PG without PE From c61e668f617dc634c6ecb879f4d40f56ad5ef01d Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 17 Jul 2017 14:58:42 -0500 Subject: [PATCH 0045/2137] Log esp, even in 16-bit mode --- src/debug.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/debug.js b/src/debug.js index 97453d25..21d5cbab 100644 --- a/src/debug.js +++ b/src/debug.js @@ -223,7 +223,7 @@ CPU.prototype.debug_init = function() var iopl = cpu.getiopl(); var cpl = cpu.cpl[0]; var cs_eip = h(cpu.sreg[reg_cs], 4) + ":" + h(cpu.get_real_eip() >>> 0, 8); - var ss_esp = h(cpu.sreg[reg_ss], 4) + ":" + h(cpu.get_stack_reg() >>> 0, 8); + var ss_esp = h(cpu.sreg[reg_ss], 4) + ":" + h(cpu.reg32s[reg_es] >>> 0, 8); var op_size = cpu.is_32[0] ? "32" : "16"; var if_ = (cpu.flags[0] & flag_interrupt) ? 1 : 0; From 75ae9fe42053358b0da3cfd2d9ab6e796daa5e09 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 18 Jul 2017 15:17:56 -0500 Subject: [PATCH 0046/2137] Split modrm functions by reg/mem --- src/cpu.js | 9 +- src/fpu.js | 58 +- src/misc_instr.js | 38 +- src/native/instructions.c | 2181 ++++++++++++++++++++++------------ src/native/instructions_0f.c | 20 +- tests/nasm/create_tests.js | 54 +- 6 files changed, 1497 insertions(+), 863 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index b2f2750e..ded5739b 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -4296,12 +4296,17 @@ CPU.prototype.load_ldt = function(selector) CPU.prototype.arpl = function(seg, r16) { + if(!this.protected_mode[0] || this.vm86_mode()) + { + this.trigger_ud(); + } + this.flags_changed[0] &= ~flag_zero; - if((seg & 3) < (this.reg16[r16] & 3)) + if((seg & 3) < (r16 & 3)) { this.flags[0] |= flag_zero; - return seg & ~3 | this.reg16[r16] & 3; + return seg & ~3 | r16 & 3; } else { diff --git a/src/fpu.js b/src/fpu.js index cb592ece..cb371a69 100644 --- a/src/fpu.js +++ b/src/fpu.js @@ -657,7 +657,7 @@ FPU.prototype.dbg_log_fpu_op = function(op, imm8) } else { - dbg_log(h(op, 2) + " /" + (imm8 >> 3 & 7) + + dbg_log(h(op, 2) + " /" + imm8 + " @" + h(this.cpu.instruction_pointer[0] >>> 0, 8) + " sp=" + this.stack_ptr + " st=" + h(this.stack_empty[0], 2), LOG_FPU); } } @@ -718,13 +718,11 @@ FPU.prototype.op_D8_reg = function(imm8) } }; -FPU.prototype.op_D8_mem = function(imm8, addr) +FPU.prototype.op_D8_mem = function(mod, addr) { - this.dbg_log_fpu_op(0xD8, imm8); - - var mod = imm8 >> 3 & 7, - m32 = this.load_m32(addr); + this.dbg_log_fpu_op(0xD8, mod); + var m32 = this.load_m32(addr); var st0 = this.get_st0(); switch(mod) @@ -934,11 +932,9 @@ FPU.prototype.op_D9_reg = function(imm8) } }; -FPU.prototype.op_D9_mem = function(imm8, addr) +FPU.prototype.op_D9_mem = function(mod, addr) { - this.dbg_log_fpu_op(0xD9, imm8); - - var mod = imm8 >> 3 & 7; + this.dbg_log_fpu_op(0xD9, mod); switch(mod) { @@ -1040,13 +1036,11 @@ FPU.prototype.op_DA_reg = function(imm8) } }; -FPU.prototype.op_DA_mem = function(imm8, addr) +FPU.prototype.op_DA_mem = function(mod, addr) { - this.dbg_log_fpu_op(0xDA, imm8); - - var mod = imm8 >> 3 & 7, - m32 = this.cpu.safe_read32s(addr); + this.dbg_log_fpu_op(0xDA, mod); + var m32 = this.cpu.safe_read32s(addr); var st0 = this.get_st0(); switch(mod) @@ -1168,11 +1162,9 @@ FPU.prototype.op_DB_reg = function(imm8) } }; -FPU.prototype.op_DB_mem = function(imm8, addr) +FPU.prototype.op_DB_mem = function(mod, addr) { - this.dbg_log_fpu_op(0xDB, imm8); - - var mod = imm8 >> 3 & 7; + this.dbg_log_fpu_op(0xDB, mod); switch(mod) { @@ -1275,13 +1267,11 @@ FPU.prototype.op_DC_reg = function(imm8) } }; -FPU.prototype.op_DC_mem = function(imm8, addr) +FPU.prototype.op_DC_mem = function(mod, addr) { - this.dbg_log_fpu_op(0xDC, imm8); + this.dbg_log_fpu_op(0xDC, mod); - var - mod = imm8 >> 3 & 7, - m64 = this.load_m64(addr); + var m64 = this.load_m64(addr); var st0 = this.get_st0(); @@ -1368,11 +1358,9 @@ FPU.prototype.op_DD_reg = function(imm8) } }; -FPU.prototype.op_DD_mem = function(imm8, addr) +FPU.prototype.op_DD_mem = function(mod, addr) { - this.dbg_log_fpu_op(0xDD, imm8); - - var mod = imm8 >> 3 & 7; + this.dbg_log_fpu_op(0xDD, mod); switch(mod) { @@ -1476,13 +1464,11 @@ FPU.prototype.op_DE_reg = function(imm8) this.pop(); }; -FPU.prototype.op_DE_mem = function(imm8, addr) +FPU.prototype.op_DE_mem = function(mod, addr) { - this.dbg_log_fpu_op(0xDE, imm8); - - var mod = imm8 >> 3 & 7, - m16 = this.cpu.safe_read16(addr) << 16 >> 16; + this.dbg_log_fpu_op(0xDE, mod); + var m16 = this.cpu.safe_read16(addr) << 16 >> 16; var st0 = this.get_st0(); switch(mod) @@ -1562,11 +1548,9 @@ FPU.prototype.op_DF_reg = function(imm8) } }; -FPU.prototype.op_DF_mem = function(imm8, addr) +FPU.prototype.op_DF_mem = function(mod, addr) { - this.dbg_log_fpu_op(0xDF, imm8); - - var mod = imm8 >> 3 & 7; + this.dbg_log_fpu_op(0xDF, mod); switch(mod) { diff --git a/src/misc_instr.js b/src/misc_instr.js index 48f83226..3b255a35 100644 --- a/src/misc_instr.js +++ b/src/misc_instr.js @@ -354,20 +354,18 @@ CPU.prototype.popa32 = function() this.reg32s[reg_eax] = this.pop32s(); } -CPU.prototype.xchg8 = function(memory_data, modrm_byte) +CPU.prototype.xchg8 = function(memory_data, mod) { - var mod = modrm_byte >> 1 & 0xC | modrm_byte >> 5 & 1, - tmp = this.reg8[mod]; + var tmp = this.reg8[mod]; this.reg8[mod] = memory_data; return tmp; } -CPU.prototype.xchg16 = function(memory_data, modrm_byte) +CPU.prototype.xchg16 = function(memory_data, mod) { - var mod = modrm_byte >> 2 & 14, - tmp = this.reg16[mod]; + var tmp = this.reg16[mod]; this.reg16[mod] = memory_data; @@ -381,10 +379,9 @@ CPU.prototype.xchg16r = function(operand) this.reg16[operand] = temp; } -CPU.prototype.xchg32 = function(memory_data, modrm_byte) +CPU.prototype.xchg32 = function(memory_data, mod) { - var mod = modrm_byte >> 3 & 7, - tmp = this.reg32s[mod]; + var tmp = this.reg32s[mod]; this.reg32s[mod] = memory_data; @@ -398,39 +395,24 @@ CPU.prototype.xchg32r = function(operand) this.reg32s[operand] = temp; } -CPU.prototype.lss16 = function(seg) +CPU.prototype.lss16 = function(addr, reg, seg) { - if(this.modrm_byte[0] >= 0xC0) - { - // 0xc4c4 #ud (EMULATOR_BOP) is used by reactos and windows to exit vm86 mode - this.trigger_ud(); - } - - var addr = this.modrm_resolve(this.modrm_byte[0]); - var new_reg = this.safe_read16(addr), new_seg = this.safe_read16(addr + 2 | 0); this.switch_seg(seg, new_seg); - this.reg16[this.modrm_byte[0] >> 2 & 14] = new_reg; + this.reg16[reg] = new_reg; } -CPU.prototype.lss32 = function(seg) +CPU.prototype.lss32 = function(addr, reg, seg) { - if(this.modrm_byte[0] >= 0xC0) - { - this.trigger_ud(); - } - - var addr = this.modrm_resolve(this.modrm_byte[0]); - var new_reg = this.safe_read32s(addr), new_seg = this.safe_read16(addr + 4 | 0); this.switch_seg(seg, new_seg); - this.reg32s[this.modrm_byte[0] >> 3 & 7] = new_reg; + this.reg32s[reg] = new_reg; } CPU.prototype.enter16 = function(size, nesting_level) diff --git a/src/native/instructions.c b/src/native/instructions.c index da3473a1..81635fea 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -11,44 +11,74 @@ int32_t translate_address_write(int32_t); int32_t resolve_modrm(int32_t); -/* -int32_t phys_read8(int32_t); -int32_t phys_write8(int32_t, int32_t); +#define SAFE_READ_WRITE8(addr, fun) \ + int32_t phys_addr = translate_address_write(addr); \ + int32_t ___ = read8(phys_addr); \ + write8(phys_addr, fun); -#define RE8 reg8[modrm_byte << 2 & 0xC | modrm_byte >> 2 & 1] -#define E8 e8 -#define G8 reg8[modrm_byte >> 1 & 0xC | modrm_byte >> 5 & 1] +#define SAFE_READ_WRITE16(addr, fun) \ + int32_t phys_addr = translate_address_write(addr); \ + if((phys_addr & 0xFFF) == 0xFFF) \ + { \ + int32_t phys_addr_high = translate_address_write(addr + 1); \ + int32_t ___ = virt_boundary_read16(phys_addr, phys_addr_high); \ + virt_boundary_write16(phys_addr, phys_addr_high, fun); \ + } \ + else \ + { \ + int32_t ___ = read16(phys_addr); \ + write16(phys_addr, fun); \ + } -#define IDX_E8 (modrm_byte << 2 & 0xC | modrm_byte >> 2 & 1) -#define IDX_G8 (modrm_byte >> 1 & 0xC | modrm_byte >> 5 & 1) +#define SAFE_READ_WRITE32(addr, fun) \ + int32_t phys_addr = translate_address_write(addr); \ + if((phys_addr & 0xFFF) >= 0xFFD) \ + { \ + int32_t phys_addr_high = translate_address_write(addr + 3 & ~3) | (addr + 3) & 3; \ + int32_t ___ = virt_boundary_read32s(phys_addr, phys_addr_high); \ + virt_boundary_write32(phys_addr, phys_addr_high, fun); \ + } \ + else \ + { \ + int32_t ___ = read32s(phys_addr); \ + write32(phys_addr, fun); \ + } -#define READ_WRITE_E8_(f)\ -{\ - int32_t modrm_byte = read_modrm_byte();\ - if(modrm_byte < 0xC0) {\ - int32_t phys_addr = translate_address_write(resolve_modrm(modrm_byte));\ - int32_t e8 = phys_read8(phys_addr);\ - phys_write8(phys_addr, f);\ - }\ - else {\ - int32_t e8 = RE8;\ - RE8 = f;\ - }\ +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)]; } -#define READ_WRITE_E8(f)\ -{\ - int32_t modrm_byte = read_modrm_byte();\ - if(modrm_byte < 0xC0) {\ - int32_t virt_addr = resolve_modrm(modrm_byte);\ - f ## _rm(virt_addr, IDX_G8);\ - }\ - else {\ - f ## _rr(IDX_E8, IDX_G8);\ - }\ +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 @@ -63,7 +93,6 @@ int32_t read_e8(void); int32_t read_e8s(void); int32_t read_e16(void); int32_t read_e16s(void); -int32_t read_e32(void); int32_t read_e32s(void); void write_e8(int32_t); @@ -214,8 +243,8 @@ void far_return(int32_t, int32_t, int32_t); void iret16(); void iret32(); -void lss16(int32_t); -void lss32(int32_t); +void lss16(int32_t, int32_t, int32_t); +void lss32(int32_t, int32_t, int32_t); void enter16(int32_t, int32_t); void enter32(int32_t, int32_t); @@ -259,16 +288,67 @@ static void run_instruction0f_32(int32_t); void clear_prefixes(void); void cycle_internal(void); - void fwait(void); -static void instr_00() { read_modrm_byte(); write_e8(add8(read_write_e8(), read_g8())); } -static void instr16_01() { read_modrm_byte(); write_e16(add16(read_write_e16(), read_g16())); } -static void instr32_01() { read_modrm_byte(); write_e32(add32(read_write_e32(), read_g32s())); } -static void instr_02() { read_modrm_byte(); write_g8(add8(read_g8(), read_e8())); } -static void instr16_03() { read_modrm_byte(); write_g16(add16(read_g16(), read_e16())); } -static void instr32_03() { read_modrm_byte(); write_g32(add32(read_g32s(), read_e32s())); } +#define DEFINE_MODRM_INSTR1_READ_WRITE_8(name, fun) \ + static void name ## _mem(int32_t addr) { SAFE_READ_WRITE8(addr, fun) } \ + static void name ## _reg(int32_t r1) { int32_t ___ = read_reg8(r1); write_reg8(r1, fun); } + +#define DEFINE_MODRM_INSTR1_READ_WRITE_16(name, fun) \ + static void name ## _mem(int32_t addr) { SAFE_READ_WRITE16(addr, fun) } \ + static void name ## _reg(int32_t r1) { int32_t ___ = read_reg16(r1); write_reg16(r1, fun); } + +#define DEFINE_MODRM_INSTR1_READ_WRITE_32(name, fun) \ + static void name ## _mem(int32_t addr) { SAFE_READ_WRITE32(addr, fun) } \ + static void name ## _reg(int32_t r1) { 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_MODRM_INSTR1_READ8(name, fun) \ + static void name ## _mem(int32_t addr) { int32_t ___ = safe_read8(addr); fun; } \ + static void name ## _reg(int32_t r1) { int32_t ___ = read_reg8(r1); fun; } + +#define DEFINE_MODRM_INSTR1_READ16(name, fun) \ + static void name ## _mem(int32_t addr) { int32_t ___ = safe_read16(addr); fun; } \ + static void name ## _reg(int32_t r1) { int32_t ___ = read_reg16(r1); fun; } + +#define DEFINE_MODRM_INSTR1_READ32(name, fun) \ + static void name ## _mem(int32_t addr) { int32_t ___ = safe_read32s(addr); fun; } \ + static void name ## _reg(int32_t r1) { 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; } + +#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; } + +#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; } + + +DEFINE_MODRM_INSTR_READ_WRITE_8(instr_00, add8(___, read_reg8(r))) +DEFINE_MODRM_INSTR_READ_WRITE_16(instr16_01, add16(___, read_reg16(r))) +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()); } @@ -284,12 +364,12 @@ static void instr32_07() { adjust_stack_reg(4); } -static void instr_08() { read_modrm_byte(); write_e8(or8(read_write_e8(), read_g8())); } -static void instr16_09() { read_modrm_byte(); write_e16(or16(read_write_e16(), read_g16())); } -static void instr32_09() { read_modrm_byte(); write_e32(or32(read_write_e32(), read_g32s())); } -static void instr_0A() { read_modrm_byte(); write_g8(or8(read_g8(), read_e8())); } -static void instr16_0B() { read_modrm_byte(); write_g16(or16(read_g16(), read_e16())); } -static void instr32_0B() { read_modrm_byte(); write_g32(or32(read_g32s(), read_e32s())); } +DEFINE_MODRM_INSTR_READ_WRITE_8(instr_08, or8(___, read_reg8(r))) +DEFINE_MODRM_INSTR_READ_WRITE_16(instr16_09, or16(___, read_reg16(r))) +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()); } @@ -304,12 +384,13 @@ static void instr32_0F() { run_instruction0f_32(read_imm8()); } -static void instr_10() { read_modrm_byte(); write_e8(adc8(read_write_e8(), read_g8())); } -static void instr16_11() { read_modrm_byte(); write_e16(adc16(read_write_e16(), read_g16())); } -static void instr32_11() { read_modrm_byte(); write_e32(adc32(read_write_e32(), read_g32s())); } -static void instr_12() { read_modrm_byte(); write_g8(adc8(read_g8(), read_e8())); } -static void instr16_13() { read_modrm_byte(); write_g16(adc16(read_g16(), read_e16())); } -static void instr32_13() { read_modrm_byte(); write_g32(adc32(read_g32s(), read_e32s())); } + +DEFINE_MODRM_INSTR_READ_WRITE_8(instr_10, adc8(___, read_reg8(r))) +DEFINE_MODRM_INSTR_READ_WRITE_16(instr16_11, adc16(___, read_reg16(r))) +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()); } @@ -329,12 +410,12 @@ static void instr32_17() { cycle_internal(); } -static void instr_18() { read_modrm_byte(); write_e8(sbb8(read_write_e8(), read_g8())); } -static void instr16_19() { read_modrm_byte(); write_e16(sbb16(read_write_e16(), read_g16())); } -static void instr32_19() { read_modrm_byte(); write_e32(sbb32(read_write_e32(), read_g32s())); } -static void instr_1A() { read_modrm_byte(); write_g8(sbb8(read_g8(), read_e8())); } -static void instr16_1B() { read_modrm_byte(); write_g16(sbb16(read_g16(), read_e16())); } -static void instr32_1B() { read_modrm_byte(); write_g32(sbb32(read_g32s(), read_e32s())); } +DEFINE_MODRM_INSTR_READ_WRITE_8(instr_18, sbb8(___, read_reg8(r))) +DEFINE_MODRM_INSTR_READ_WRITE_16(instr16_19, sbb16(___, read_reg16(r))) +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()); } @@ -351,12 +432,12 @@ static void instr32_1F() { adjust_stack_reg(4); } -static void instr_20() { read_modrm_byte(); write_e8(and8(read_write_e8(), read_g8())); } -static void instr16_21() { read_modrm_byte(); write_e16(and16(read_write_e16(), read_g16())); } -static void instr32_21() { read_modrm_byte(); write_e32(and32(read_write_e32(), read_g32s())); } -static void instr_22() { read_modrm_byte(); write_g8(and8(read_g8(), read_e8())); } -static void instr16_23() { read_modrm_byte(); write_g16(and16(read_g16(), read_e16())); } -static void instr32_23() { read_modrm_byte(); write_g32(and32(read_g32s(), read_e32s())); } +DEFINE_MODRM_INSTR_READ_WRITE_8(instr_20, and8(___, read_reg8(r))) +DEFINE_MODRM_INSTR_READ_WRITE_16(instr16_21, and16(___, read_reg16(r))) +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()); } @@ -365,12 +446,12 @@ static void instr32_25() { reg32s[EAX] = and32(reg32s[EAX], read_op32s()); } static void instr_26() { segment_prefix_op(ES); } static void instr_27() { bcd_daa(); } -static void instr_28() { read_modrm_byte(); write_e8(sub8(read_write_e8(), read_g8())); } -static void instr16_29() { read_modrm_byte(); write_e16(sub16(read_write_e16(), read_g16())); } -static void instr32_29() { read_modrm_byte(); write_e32(sub32(read_write_e32(), read_g32s())); } -static void instr_2A() { read_modrm_byte(); write_g8(sub8(read_g8(), read_e8())); } -static void instr16_2B() { read_modrm_byte(); write_g16(sub16(read_g16(), read_e16())); } -static void instr32_2B() { read_modrm_byte(); write_g32(sub32(read_g32s(), read_e32s())); } +DEFINE_MODRM_INSTR_READ_WRITE_8(instr_28, sub8(___, read_reg8(r))) +DEFINE_MODRM_INSTR_READ_WRITE_16(instr16_29, sub16(___, read_reg16(r))) +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()); } @@ -378,12 +459,12 @@ static void instr32_2D() { reg32s[EAX] = sub32(reg32s[EAX], read_op32s()); } static void instr_2E() { segment_prefix_op(CS); } static void instr_2F() { bcd_das(); } -static void instr_30() { read_modrm_byte(); write_e8(xor8(read_write_e8(), read_g8())); } -static void instr16_31() { read_modrm_byte(); write_e16(xor16(read_write_e16(), read_g16())); } -static void instr32_31() { read_modrm_byte(); write_e32(xor32(read_write_e32(), read_g32s())); } -static void instr_32() { read_modrm_byte(); write_g8(xor8(read_g8(), read_e8())); } -static void instr16_33() { read_modrm_byte(); write_g16(xor16(read_g16(), read_e16())); } -static void instr32_33() { read_modrm_byte(); write_g32(xor32(read_g32s(), read_e32s())); } +DEFINE_MODRM_INSTR_READ_WRITE_8(instr_30, xor8(___, read_reg8(r))) +DEFINE_MODRM_INSTR_READ_WRITE_16(instr16_31, xor16(___, read_reg16(r))) +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()); } @@ -391,12 +472,12 @@ static void instr32_35() { reg32s[EAX] = xor32(reg32s[EAX], read_op32s()); } static void instr_36() { segment_prefix_op(SS); } static void instr_37() { bcd_aaa(); } -static void instr_38() { read_modrm_byte(); cmp8(read_e8(), read_g8()); } -static void instr16_39() { read_modrm_byte(); cmp16(read_e16(), read_g16()); } -static void instr32_39() { read_modrm_byte(); cmp32(read_e32s(), read_g32s()); } -static void instr_3A() { read_modrm_byte(); cmp8(read_g8(), read_e8()); } -static void instr16_3B() { read_modrm_byte(); cmp16(read_g16(), read_e16()); } -static void instr32_3B() { read_modrm_byte(); cmp32(read_g32s(), read_e32s()); } +DEFINE_MODRM_INSTR_READ8(instr_38, cmp8(___, read_reg8(r))) +DEFINE_MODRM_INSTR_READ16(instr16_39, cmp16(___, read_reg16(r))) +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()); } @@ -481,25 +562,18 @@ static void instr32_60() { pusha32(); } static void instr16_61() { popa16(); } static void instr32_61() { popa32(); } -static void instr_62() { +static void instr_62_reg(int32_t r2, int32_t r) { // bound dbg_log("Unimplemented BOUND instruction"); dbg_assert(false); } -static void instr_63() { read_modrm_byte(); - // arpl - //dbg_log("arpl"); - if(*protected_mode && !vm86_mode()) - { - write_e16(arpl(read_write_e16(), modrm_byte[0] >> 2 & 14)); - } - else - { - dbg_log("arpl #ud"); - trigger_ud(); - } +static void instr_62_mem(int32_t addr, int32_t r) { + dbg_log("Unimplemented BOUND instruction"); + dbg_assert(false); } +DEFINE_MODRM_INSTR_READ_WRITE_16(instr_63, arpl(___, read_reg16(r))) + static void instr_64() { segment_prefix_op(FS); } static void instr_65() { segment_prefix_op(GS); } @@ -522,22 +596,14 @@ static void instr_67() { static void instr16_68() { push16(read_op16()); } static void instr32_68() { push32(read_op32s()); } -static void instr16_69() { read_modrm_byte(); - write_g16(imul_reg16(read_e16s(), read_op16() << 16 >> 16)); -} -static void instr32_69() { read_modrm_byte(); - write_g32(imul_reg32(read_e32s(), read_op32s())); -} +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_6A() { push16(read_op8s()); } static void instr32_6A() { push32(read_op8s()); } -static void instr16_6B() { read_modrm_byte(); - write_g16(imul_reg16(read_e16s(), read_op8s())); -} -static void instr32_6B() { read_modrm_byte(); - write_g32(imul_reg32(read_e32s(), read_op8s())); -} +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 instr_6C() { insb(); } static void instr16_6D() { insw(); } @@ -563,127 +629,124 @@ static void instr_7D() { jmpcc8(!test_l()); } static void instr_7E() { jmpcc8( test_le()); } static void instr_7F() { jmpcc8(!test_le()); } -static void instr_80_0() { write_e8(add8(read_write_e8(), read_op8())); } -static void instr_80_1() { write_e8( or8(read_write_e8(), read_op8())); } -static void instr_80_2() { write_e8(adc8(read_write_e8(), read_op8())); } -static void instr_80_3() { write_e8(sbb8(read_write_e8(), read_op8())); } -static void instr_80_4() { write_e8(and8(read_write_e8(), read_op8())); } -static void instr_80_5() { write_e8(sub8(read_write_e8(), read_op8())); } -static void instr_80_6() { write_e8(xor8(read_write_e8(), read_op8())); } -static void instr_80_7() { cmp8(read_e8(), read_op8()); } +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()); } -static void instr16_81_0() { write_e16(add16(read_write_e16(), read_op16())); } -static void instr16_81_1() { write_e16( or16(read_write_e16(), read_op16())); } -static void instr16_81_2() { write_e16(adc16(read_write_e16(), read_op16())); } -static void instr16_81_3() { write_e16(sbb16(read_write_e16(), read_op16())); } -static void instr16_81_4() { write_e16(and16(read_write_e16(), read_op16())); } -static void instr16_81_5() { write_e16(sub16(read_write_e16(), read_op16())); } -static void instr16_81_6() { write_e16(xor16(read_write_e16(), read_op16())); } -static void instr16_81_7() { cmp16(read_e16(), read_op16()); } +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()); } -static void instr32_81_0() { write_e32(add32(read_write_e32(), read_op32s())); } -static void instr32_81_1() { write_e32( or32(read_write_e32(), read_op32s())); } -static void instr32_81_2() { write_e32(adc32(read_write_e32(), read_op32s())); } -static void instr32_81_3() { write_e32(sbb32(read_write_e32(), read_op32s())); } -static void instr32_81_4() { write_e32(and32(read_write_e32(), read_op32s())); } -static void instr32_81_5() { write_e32(sub32(read_write_e32(), read_op32s())); } -static void instr32_81_6() { write_e32(xor32(read_write_e32(), read_op32s())); } -static void instr32_81_7() { cmp32(read_e32s(), read_op32s()); } +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()); } -static void instr_82_0() { write_e8(add8(read_write_e8(), read_op8())); } -static void instr_82_1() { write_e8( or8(read_write_e8(), read_op8())); } -static void instr_82_2() { write_e8(adc8(read_write_e8(), read_op8())); } -static void instr_82_3() { write_e8(sbb8(read_write_e8(), read_op8())); } -static void instr_82_4() { write_e8(and8(read_write_e8(), read_op8())); } -static void instr_82_5() { write_e8(sub8(read_write_e8(), read_op8())); } -static void instr_82_6() { write_e8(xor8(read_write_e8(), read_op8())); } -static void instr_82_7() { cmp8(read_e8(), read_op8()); } +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()); } -static void instr16_83_0() { write_e16(add16(read_write_e16(), read_op8s())); } -static void instr16_83_1() { write_e16( or16(read_write_e16(), read_op8s())); } -static void instr16_83_2() { write_e16(adc16(read_write_e16(), read_op8s())); } -static void instr16_83_3() { write_e16(sbb16(read_write_e16(), read_op8s())); } -static void instr16_83_4() { write_e16(and16(read_write_e16(), read_op8s())); } -static void instr16_83_5() { write_e16(sub16(read_write_e16(), read_op8s())); } -static void instr16_83_6() { write_e16(xor16(read_write_e16(), read_op8s())); } -static void instr16_83_7() { cmp16(read_e16s(), read_op8s()); } +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()); } -static void instr32_83_0() { write_e32(add32(read_write_e32(), read_op8s())); } -static void instr32_83_1() { write_e32( or32(read_write_e32(), read_op8s())); } -static void instr32_83_2() { write_e32(adc32(read_write_e32(), read_op8s())); } -static void instr32_83_3() { write_e32(sbb32(read_write_e32(), read_op8s())); } -static void instr32_83_4() { write_e32(and32(read_write_e32(), read_op8s())); } -static void instr32_83_5() { write_e32(sub32(read_write_e32(), read_op8s())); } -static void instr32_83_6() { write_e32(xor32(read_write_e32(), read_op8s())); } -static void instr32_83_7() { cmp32(read_e32s(), read_op8s()); } +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()); } -static void instr_84() { read_modrm_byte(); int32_t data = read_e8(); test8(data, read_g8()); } -static void instr16_85() { read_modrm_byte(); int32_t data = read_e16(); test16(data, read_g16()); } -static void instr32_85() { read_modrm_byte(); int32_t data = read_e32s(); test32(data, read_g32s()); } +DEFINE_MODRM_INSTR_READ8(instr_84, test8(___, read_reg8(r))) +DEFINE_MODRM_INSTR_READ16(instr16_85, test16(___, read_reg16(r))) +DEFINE_MODRM_INSTR_READ32(instr32_85, test32(___, read_reg32(r))) +DEFINE_MODRM_INSTR_READ_WRITE_8(instr_86, xchg8(___, get_reg8_index(r))) +DEFINE_MODRM_INSTR_READ_WRITE_16(instr16_87, xchg16(___, get_reg16_index(r))) +DEFINE_MODRM_INSTR_READ_WRITE_32(instr32_87, xchg32(___, r)) -static void instr_86() { read_modrm_byte(); int32_t data = read_write_e8(); write_e8(xchg8(data, modrm_byte[0])); } -static void instr16_87() { read_modrm_byte(); - int32_t data = read_write_e16(); write_e16(xchg16(data, modrm_byte[0])); +static void instr_88_reg(int32_t r2, int32_t r) { write_reg8(r2, read_reg8(r)); } +static void instr_88_mem(int32_t addr, int32_t r) { safe_write8(addr, read_reg8(r)); } +static void instr16_89_reg(int32_t r2, int32_t r) { write_reg16(r2, read_reg16(r)); } +static void instr16_89_mem(int32_t addr, int32_t r) { safe_write16(addr, read_reg16(r)); } +static void instr32_89_reg(int32_t r2, int32_t r) { write_reg32(r2, read_reg32(r)); } +static void instr32_89_mem(int32_t addr, int32_t r) { safe_write32(addr, read_reg32(r)); } + +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]); } + +static void instr16_8D_reg(int32_t r, int32_t r2) +{ + dbg_log("lea #ud"); + trigger_ud(); } -static void instr32_87() { read_modrm_byte(); - int32_t data = read_write_e32(); write_e32(xchg32(data, modrm_byte[0])); -} - -static void instr_88() { read_modrm_byte(); set_e8(read_g8()); } -static void instr16_89() { read_modrm_byte(); set_e16(read_g16()); } -static void instr32_89() { read_modrm_byte(); set_e32(read_g32s()); } - -static void instr_8A() { read_modrm_byte(); - int32_t data = read_e8(); - write_g8(data); -} -static void instr16_8B() { read_modrm_byte(); - int32_t data = read_e16(); - write_g16(data); -} -static void instr32_8B() { read_modrm_byte(); - int32_t data = read_e32s(); - write_g32(data); -} - -static void instr16_8C() { read_modrm_byte(); - set_e16(sreg[modrm_byte[0] >> 3 & 7]); -} -static void instr32_8C() { read_modrm_byte(); - set_e32(sreg[modrm_byte[0] >> 3 & 7]); -} - -static void instr16_8D() { read_modrm_byte(); - // lea - if(modrm_byte[0] >= 0xC0) - { - dbg_log("lea #ud"); - trigger_ud(); - } - int32_t mod = modrm_byte[0] >> 3 & 7; - +static void instr16_8D_mem_pre() +{ // override prefix, so modrm_resolve does not return the segment part *prefixes |= SEG_PREFIX_ZERO; - reg16[mod << 1] = modrm_resolve(modrm_byte[0]); +} +static void instr16_8D_mem(int32_t addr, int32_t mod) +{ + // lea + reg16[mod << 1] = addr; *prefixes = 0; } -static void instr32_8D() { read_modrm_byte(); - if(modrm_byte[0] >= 0xC0) - { - dbg_log("lea #ud"); - trigger_ud(); - } - int32_t mod = modrm_byte[0] >> 3 & 7; - +static void instr32_8D_reg(int32_t r, int32_t r2) +{ + dbg_log("lea #ud"); + trigger_ud(); +} +static void instr32_8D_mem_pre() +{ + // override prefix, so modrm_resolve does not return the segment part *prefixes |= SEG_PREFIX_ZERO; - reg32s[mod] = modrm_resolve(modrm_byte[0]); +} +static void instr32_8D_mem(int32_t addr, int32_t mod) { + // lea + reg32s[mod] = addr; *prefixes = 0; } -static void instr_8E() { read_modrm_byte(); - int32_t mod = modrm_byte[0] >> 3 & 7; - int32_t data = read_e16(); +static void instr_8E_helper(int32_t data, int32_t mod) +{ switch_seg(mod, data); if(mod == SS) @@ -693,39 +756,43 @@ static void instr_8E() { read_modrm_byte(); cycle_internal(); } } +DEFINE_MODRM_INSTR_READ16(instr_8E, instr_8E_helper(___, r)) -static void instr16_8F() { read_modrm_byte(); - // pop - int32_t sp = safe_read16(get_stack_pointer(0)); - +static void instr16_8F_0_mem_pre() +{ + for(int32_t i = 0; i < 8; i++) { translate_address_read(*instruction_pointer + i); }; // XXX adjust_stack_reg(2); - - if(modrm_byte[0] < 0xC0) { - int32_t addr = modrm_resolve(modrm_byte[0]); - adjust_stack_reg(-2); - safe_write16(addr, sp); - adjust_stack_reg(2); - } else { - write_reg_e16(sp); - } } -static void instr32_8F() { read_modrm_byte(); +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); +} +static void instr16_8F_0_reg(int32_t r) +{ + write_reg16(r, pop16()); +} +static void instr32_8F_0_mem_pre() +{ + for(int32_t i = 0; i < 8; i++) { translate_address_read(*instruction_pointer + i); }; // XXX + adjust_stack_reg(4); +} +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)); - // change esp first, then resolve modrm address + safe_write32(addr, sp); adjust_stack_reg(4); - - if(modrm_byte[0] < 0xC0) { - int32_t addr = modrm_resolve(modrm_byte[0]); - - // Before attempting a write that might cause a page fault, - // we must set esp to the old value. Fuck Intel. - adjust_stack_reg(-4); - safe_write32(addr, sp); - adjust_stack_reg(4); - } else { - write_reg_e32(sp); - } +} +static void instr32_8F_0_reg(int32_t r) +{ + write_reg32(r, pop32s()); } static void instr_90() { } @@ -950,33 +1017,32 @@ static void instr32_BE() { reg32s[ESI] = read_op32s(); } static void instr16_BF() { reg16[DI] = read_op16(); } static void instr32_BF() { reg32s[EDI] = read_op32s(); } +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)) -static void instr_C0_0() { write_e8(rol8(read_write_e8(), read_op8() & 31)); } -static void instr_C0_1() { write_e8(ror8(read_write_e8(), read_op8() & 31)); } -static void instr_C0_2() { write_e8(rcl8(read_write_e8(), read_op8() & 31)); } -static void instr_C0_3() { write_e8(rcr8(read_write_e8(), read_op8() & 31)); } -static void instr_C0_4() { write_e8(shl8(read_write_e8(), read_op8() & 31)); } -static void instr_C0_5() { write_e8(shr8(read_write_e8(), read_op8() & 31)); } -static void instr_C0_6() { write_e8(shl8(read_write_e8(), read_op8() & 31)); } -static void instr_C0_7() { write_e8(sar8(read_write_e8(), read_op8() & 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)) -static void instr16_C1_0() { write_e16(rol16(read_write_e16(), read_op8() & 31)); } -static void instr16_C1_1() { write_e16(ror16(read_write_e16(), read_op8() & 31)); } -static void instr16_C1_2() { write_e16(rcl16(read_write_e16(), read_op8() & 31)); } -static void instr16_C1_3() { write_e16(rcr16(read_write_e16(), read_op8() & 31)); } -static void instr16_C1_4() { write_e16(shl16(read_write_e16(), read_op8() & 31)); } -static void instr16_C1_5() { write_e16(shr16(read_write_e16(), read_op8() & 31)); } -static void instr16_C1_6() { write_e16(shl16(read_write_e16(), read_op8() & 31)); } -static void instr16_C1_7() { write_e16(sar16(read_write_e16(), read_op8() & 31)); } - -static void instr32_C1_0() { write_e32(rol32(read_write_e32(), read_op8() & 31)); } -static void instr32_C1_1() { write_e32(ror32(read_write_e32(), read_op8() & 31)); } -static void instr32_C1_2() { write_e32(rcl32(read_write_e32(), read_op8() & 31)); } -static void instr32_C1_3() { write_e32(rcr32(read_write_e32(), read_op8() & 31)); } -static void instr32_C1_4() { write_e32(shl32(read_write_e32(), read_op8() & 31)); } -static void instr32_C1_5() { write_e32(shr32(read_write_e32(), read_op8() & 31)); } -static void instr32_C1_6() { write_e32(shl32(read_write_e32(), read_op8() & 31)); } -static void instr32_C1_7() { write_e32(sar32(read_write_e32(), read_op8() & 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)) static void instr16_C2() { // retn @@ -1010,40 +1076,29 @@ static void instr32_C3() { diverged(); } -static void instr16_C4() { read_modrm_byte(); - lss16(ES); +static void instr16_C4_reg(int32_t _unused1, int32_t _unused2) { trigger_ud(); } +static void instr16_C4_mem(int32_t addr, int32_t r) { + lss16(addr, get_reg16_index(r), ES); } -static void instr32_C4() { read_modrm_byte(); - lss32(ES); +static void instr32_C4_reg(int32_t _unused1, int32_t _unused2) { trigger_ud(); } +static void instr32_C4_mem(int32_t addr, int32_t r) { + lss32(addr, r, ES); } -static void instr16_C5() { read_modrm_byte(); - lss16(DS); +static void instr16_C5_reg(int32_t _unused1, int32_t _unused2) { trigger_ud(); } +static void instr16_C5_mem(int32_t addr, int32_t r) { + lss16(addr, get_reg16_index(r), DS); } -static void instr32_C5() { read_modrm_byte(); - lss32(DS); +static void instr32_C5_reg(int32_t _unused1, int32_t _unused2) { trigger_ud(); } +static void instr32_C5_mem(int32_t addr, int32_t r) { + lss32(addr, r, DS); } -static void instr_C6() { read_modrm_byte(); - if(modrm_byte[0] < 0xC0) { - safe_write8(modrm_resolve(modrm_byte[0]), read_op8()); - } else { - reg8[modrm_byte[0] << 2 & 0xC | modrm_byte[0] >> 2 & 1] = read_op8(); - } -} -static void instr16_C7() { read_modrm_byte(); - if(modrm_byte[0] < 0xC0) { - safe_write16(modrm_resolve(modrm_byte[0]), read_op16()); - } else { - reg16[modrm_byte[0] << 1 & 14] = read_op16(); - } -} -static void instr32_C7() { read_modrm_byte(); - if(modrm_byte[0] < 0xC0) { - safe_write32(modrm_resolve(modrm_byte[0]), read_op32s()); - } else { - reg32s[modrm_byte[0] & 7] = read_op32s(); - } -} +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 instr16_C8() { enter16(read_op16(), read_disp8()); } static void instr32_C8() { enter32(read_op16(), read_disp8()); } @@ -1132,60 +1187,59 @@ static void instr32_CF() { diverged(); } +DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D0_0, rol8(___, 1)) +DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D0_1, ror8(___, 1)) +DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D0_2, rcl8(___, 1)) +DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D0_3, rcr8(___, 1)) +DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D0_4, shl8(___, 1)) +DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D0_5, shr8(___, 1)) +DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D0_6, shl8(___, 1)) +DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D0_7, sar8(___, 1)) -static void instr_D0_0() { write_e8(rol8(read_write_e8(), 1)); } -static void instr_D0_1() { write_e8(ror8(read_write_e8(), 1)); } -static void instr_D0_2() { write_e8(rcl8(read_write_e8(), 1)); } -static void instr_D0_3() { write_e8(rcr8(read_write_e8(), 1)); } -static void instr_D0_4() { write_e8(shl8(read_write_e8(), 1)); } -static void instr_D0_5() { write_e8(shr8(read_write_e8(), 1)); } -static void instr_D0_6() { write_e8(shl8(read_write_e8(), 1)); } -static void instr_D0_7() { write_e8(sar8(read_write_e8(), 1)); } +DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D1_0, rol16(___, 1)) +DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D1_1, ror16(___, 1)) +DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D1_2, rcl16(___, 1)) +DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D1_3, rcr16(___, 1)) +DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D1_4, shl16(___, 1)) +DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D1_5, shr16(___, 1)) +DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D1_6, shl16(___, 1)) +DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D1_7, sar16(___, 1)) -static void instr16_D1_0() { write_e16(rol16(read_write_e16(), 1)); } -static void instr16_D1_1() { write_e16(ror16(read_write_e16(), 1)); } -static void instr16_D1_2() { write_e16(rcl16(read_write_e16(), 1)); } -static void instr16_D1_3() { write_e16(rcr16(read_write_e16(), 1)); } -static void instr16_D1_4() { write_e16(shl16(read_write_e16(), 1)); } -static void instr16_D1_5() { write_e16(shr16(read_write_e16(), 1)); } -static void instr16_D1_6() { write_e16(shl16(read_write_e16(), 1)); } -static void instr16_D1_7() { write_e16(sar16(read_write_e16(), 1)); } +DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D1_0, rol32(___, 1)) +DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D1_1, ror32(___, 1)) +DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D1_2, rcl32(___, 1)) +DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D1_3, rcr32(___, 1)) +DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D1_4, shl32(___, 1)) +DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D1_5, shr32(___, 1)) +DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D1_6, shl32(___, 1)) +DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D1_7, sar32(___, 1)) -static void instr32_D1_0() { write_e32(rol32(read_write_e32(), 1)); } -static void instr32_D1_1() { write_e32(ror32(read_write_e32(), 1)); } -static void instr32_D1_2() { write_e32(rcl32(read_write_e32(), 1)); } -static void instr32_D1_3() { write_e32(rcr32(read_write_e32(), 1)); } -static void instr32_D1_4() { write_e32(shl32(read_write_e32(), 1)); } -static void instr32_D1_5() { write_e32(shr32(read_write_e32(), 1)); } -static void instr32_D1_6() { write_e32(shl32(read_write_e32(), 1)); } -static void instr32_D1_7() { write_e32(sar32(read_write_e32(), 1)); } +DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D2_0, rol8(___, reg8[CL] & 31)) +DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D2_1, ror8(___, reg8[CL] & 31)) +DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D2_2, rcl8(___, reg8[CL] & 31)) +DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D2_3, rcr8(___, reg8[CL] & 31)) +DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D2_4, shl8(___, reg8[CL] & 31)) +DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D2_5, shr8(___, reg8[CL] & 31)) +DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D2_6, shl8(___, reg8[CL] & 31)) +DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D2_7, sar8(___, reg8[CL] & 31)) -static void instr_D2_0() { write_e8(rol8(read_write_e8(), reg8[CL] & 31)); } -static void instr_D2_1() { write_e8(ror8(read_write_e8(), reg8[CL] & 31)); } -static void instr_D2_2() { write_e8(rcl8(read_write_e8(), reg8[CL] & 31)); } -static void instr_D2_3() { write_e8(rcr8(read_write_e8(), reg8[CL] & 31)); } -static void instr_D2_4() { write_e8(shl8(read_write_e8(), reg8[CL] & 31)); } -static void instr_D2_5() { write_e8(shr8(read_write_e8(), reg8[CL] & 31)); } -static void instr_D2_6() { write_e8(shl8(read_write_e8(), reg8[CL] & 31)); } -static void instr_D2_7() { write_e8(sar8(read_write_e8(), reg8[CL] & 31)); } +DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D3_0, rol16(___, reg8[CL] & 31)) +DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D3_1, ror16(___, reg8[CL] & 31)) +DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D3_2, rcl16(___, reg8[CL] & 31)) +DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D3_3, rcr16(___, reg8[CL] & 31)) +DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D3_4, shl16(___, reg8[CL] & 31)) +DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D3_5, shr16(___, reg8[CL] & 31)) +DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D3_6, shl16(___, reg8[CL] & 31)) +DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D3_7, sar16(___, reg8[CL] & 31)) -static void instr16_D3_0() { write_e16(rol16(read_write_e16(), reg8[CL] & 31)); } -static void instr16_D3_1() { write_e16(ror16(read_write_e16(), reg8[CL] & 31)); } -static void instr16_D3_2() { write_e16(rcl16(read_write_e16(), reg8[CL] & 31)); } -static void instr16_D3_3() { write_e16(rcr16(read_write_e16(), reg8[CL] & 31)); } -static void instr16_D3_4() { write_e16(shl16(read_write_e16(), reg8[CL] & 31)); } -static void instr16_D3_5() { write_e16(shr16(read_write_e16(), reg8[CL] & 31)); } -static void instr16_D3_6() { write_e16(shl16(read_write_e16(), reg8[CL] & 31)); } -static void instr16_D3_7() { write_e16(sar16(read_write_e16(), reg8[CL] & 31)); } - -static void instr32_D3_0() { write_e32(rol32(read_write_e32(), reg8[CL] & 31)); } -static void instr32_D3_1() { write_e32(ror32(read_write_e32(), reg8[CL] & 31)); } -static void instr32_D3_2() { write_e32(rcl32(read_write_e32(), reg8[CL] & 31)); } -static void instr32_D3_3() { write_e32(rcr32(read_write_e32(), reg8[CL] & 31)); } -static void instr32_D3_4() { write_e32(shl32(read_write_e32(), reg8[CL] & 31)); } -static void instr32_D3_5() { write_e32(shr32(read_write_e32(), reg8[CL] & 31)); } -static void instr32_D3_6() { write_e32(shl32(read_write_e32(), reg8[CL] & 31)); } -static void instr32_D3_7() { write_e32(sar32(read_write_e32(), reg8[CL] & 31)); } +DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D3_0, rol32(___, reg8[CL] & 31)) +DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D3_1, ror32(___, reg8[CL] & 31)) +DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D3_2, rcl32(___, reg8[CL] & 31)) +DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D3_3, rcr32(___, reg8[CL] & 31)) +DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D3_4, shl32(___, reg8[CL] & 31)) +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()); @@ -1210,62 +1264,23 @@ static void instr_D7() { } } -static void instr_D8() { read_modrm_byte(); - task_switch_test(); - if(modrm_byte[0] < 0xC0) - fpu_op_D8_mem(modrm_byte[0], modrm_resolve(modrm_byte[0])); - else - fpu_op_D8_reg(modrm_byte[0]); -} -static void instr_D9() { read_modrm_byte(); - task_switch_test(); - if(modrm_byte[0] < 0xC0) - fpu_op_D9_mem(modrm_byte[0], modrm_resolve(modrm_byte[0])); - else - fpu_op_D9_reg(modrm_byte[0]); -} -static void instr_DA() { read_modrm_byte(); - task_switch_test(); - if(modrm_byte[0] < 0xC0) - fpu_op_DA_mem(modrm_byte[0], modrm_resolve(modrm_byte[0])); - else - fpu_op_DA_reg(modrm_byte[0]); -} -static void instr_DB() { read_modrm_byte(); - task_switch_test(); - if(modrm_byte[0] < 0xC0) - fpu_op_DB_mem(modrm_byte[0], modrm_resolve(modrm_byte[0])); - else - fpu_op_DB_reg(modrm_byte[0]); -} -static void instr_DC() { read_modrm_byte(); - task_switch_test(); - if(modrm_byte[0] < 0xC0) - fpu_op_DC_mem(modrm_byte[0], modrm_resolve(modrm_byte[0])); - else - fpu_op_DC_reg(modrm_byte[0]); -} -static void instr_DD() { read_modrm_byte(); - task_switch_test(); - if(modrm_byte[0] < 0xC0) - fpu_op_DD_mem(modrm_byte[0], modrm_resolve(modrm_byte[0])); - else - fpu_op_DD_reg(modrm_byte[0]); -} -static void instr_DE() { read_modrm_byte(); - task_switch_test(); - if(modrm_byte[0] < 0xC0) - fpu_op_DE_mem(modrm_byte[0], modrm_resolve(modrm_byte[0])); - else - fpu_op_DE_reg(modrm_byte[0]); -} -static void instr_DF() { read_modrm_byte(); - task_switch_test(); - if(modrm_byte[0] < 0xC0) - fpu_op_DF_mem(modrm_byte[0], modrm_resolve(modrm_byte[0])); - else - fpu_op_DF_reg(modrm_byte[0]); -} +static void instr_D8_mem(int32_t addr, int32_t r) { task_switch_test(); fpu_op_D8_mem(r, addr); } +static void instr_D8_reg(int32_t r2, int32_t r) { task_switch_test(); fpu_op_D8_reg(0xC0 | r2 | r << 3); } +static void instr_D9_mem(int32_t addr, int32_t r) { task_switch_test(); fpu_op_D9_mem(r, addr); } +static void instr_D9_reg(int32_t r2, int32_t r) { task_switch_test(); fpu_op_D9_reg(0xC0 | r2 | r << 3); } +static void instr_DA_mem(int32_t addr, int32_t r) { task_switch_test(); fpu_op_DA_mem(r, addr); } +static void instr_DA_reg(int32_t r2, int32_t r) { task_switch_test(); fpu_op_DA_reg(0xC0 | r2 | r << 3); } +static void instr_DB_mem(int32_t addr, int32_t r) { task_switch_test(); fpu_op_DB_mem(r, addr); } +static void instr_DB_reg(int32_t r2, int32_t r) { task_switch_test(); fpu_op_DB_reg(0xC0 | r2 | r << 3); } +static void instr_DC_mem(int32_t addr, int32_t r) { task_switch_test(); fpu_op_DC_mem(r, addr); } +static void instr_DC_reg(int32_t r2, int32_t r) { task_switch_test(); fpu_op_DC_reg(0xC0 | r2 | r << 3); } +static void instr_DD_mem(int32_t addr, int32_t r) { task_switch_test(); fpu_op_DD_mem(r, addr); } +static void instr_DD_reg(int32_t r2, int32_t r) { task_switch_test(); fpu_op_DD_reg(0xC0 | r2 | r << 3); } +static void instr_DE_mem(int32_t addr, int32_t r) { task_switch_test(); fpu_op_DE_mem(r, addr); } +static void instr_DE_reg(int32_t r2, int32_t r) { task_switch_test(); fpu_op_DE_reg(0xC0 | r2 | r << 3); } +static void instr_DF_mem(int32_t addr, int32_t r) { task_switch_test(); fpu_op_DF_mem(r, addr); } +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()); } @@ -1441,32 +1456,32 @@ static void instr_F5() { flags_changed[0] &= ~1; } -static void instr_F6_0() { test8(read_e8(), read_op8()); } -static void instr_F6_1() { test8(read_e8(), read_op8()); } -static void instr_F6_2() { write_e8(~read_write_e8()); } -static void instr_F6_3() { write_e8(neg8(read_write_e8())); } -static void instr_F6_4() { mul8(read_e8()); } -static void instr_F6_5() { imul8(read_e8s()); } -static void instr_F6_6() { div8(read_e8()); } -static void instr_F6_7() { idiv8(read_e8s()); } +DEFINE_MODRM_INSTR1_READ8(instr_F6_0, test8(___, read_op8())) +DEFINE_MODRM_INSTR1_READ8(instr_F6_1, test8(___, read_op8())) +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(___)) +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)) -static void instr16_F7_0() { test16(read_e16(), read_op16()); } -static void instr16_F7_1() { test16(read_e16(), read_op16()); } -static void instr16_F7_2() { write_e16(~read_write_e16()); } -static void instr16_F7_3() { write_e16(neg16(read_write_e16())); } -static void instr16_F7_4() { mul16(read_e16()); } -static void instr16_F7_5() { imul16(read_e16s()); } -static void instr16_F7_6() { div16(read_e16()); } -static void instr16_F7_7() { idiv16(read_e16s()); } +DEFINE_MODRM_INSTR1_READ16(instr16_F7_0, test16(___, read_op16())) +DEFINE_MODRM_INSTR1_READ16(instr16_F7_1, test16(___, read_op16())) +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(___)) +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)) -static void instr32_F7_0() { test32(read_e32s(), read_op32s()); } -static void instr32_F7_1() { test32(read_e32s(), read_op32s()); } -static void instr32_F7_2() { write_e32(~read_write_e32()); } -static void instr32_F7_3() { write_e32(neg32(read_write_e32())); } -static void instr32_F7_4() { mul32(read_e32s()); } -static void instr32_F7_5() { imul32(read_e32s()); } -static void instr32_F7_6() { div32(read_e32s()); } -static void instr32_F7_7() { idiv32(read_e32s()); } +DEFINE_MODRM_INSTR1_READ32(instr32_F7_0, test32(___, read_op32s())) +DEFINE_MODRM_INSTR1_READ32(instr32_F7_1, test32(___, read_op32s())) +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(___)) +DEFINE_MODRM_INSTR1_READ32(instr32_F7_5, imul32(___)) +DEFINE_MODRM_INSTR1_READ32(instr32_F7_6, div32(___)) +DEFINE_MODRM_INSTR1_READ32(instr32_F7_7, idiv32(___)) static void instr_F8() { // clc @@ -1543,90 +1558,82 @@ static void instr_FD() { flags[0] |= FLAG_DIRECTION; } -static void instr_FE_0() { int32_t data = read_write_e8(); write_e8(inc8(data)); } -static void instr_FE_1() { int32_t data = read_write_e8(); write_e8(dec8(data)); } +DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_FE_0, inc8(___)) +DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_FE_1, dec8(___)) -static void instr16_FF_0() { write_e16(inc16(read_write_e16())); } -static void instr16_FF_1() { write_e16(dec16(read_write_e16())); } -static void instr16_FF_2() + +DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_FF_0, inc16(___)) +DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_FF_1, dec16(___)) +static void instr16_FF_2_helper(int32_t data) { // call near - int32_t data = read_e16(); push16(get_real_eip()); instruction_pointer[0] = get_seg(CS) + data; dbg_assert(is_asize_32() || get_real_eip() < 0x10000); diverged(); } -static void instr16_FF_3() +DEFINE_MODRM_INSTR1_READ16(instr16_FF_2, instr16_FF_2_helper(___)) +static void instr16_FF_3_reg(int32_t r) +{ + dbg_log("callf #ud"); + trigger_ud(); +} +static void instr16_FF_3_mem(int32_t addr) { // callf - if(modrm_byte[0] >= 0xC0) - { - dbg_log("callf #ud"); - trigger_ud(); - dbg_assert_message(false, "unreachable"); - } - - int32_t virt_addr = modrm_resolve(modrm_byte[0]); - int32_t new_ip = safe_read16(virt_addr); - int32_t new_cs = safe_read16(virt_addr + 2); + int32_t new_ip = safe_read16(addr); + int32_t new_cs = safe_read16(addr + 2); far_jump(new_ip, new_cs, true); dbg_assert(is_asize_32() || get_real_eip() < 0x10000); diverged(); } -static void instr16_FF_4() +static void instr16_FF_4_helper(int32_t data) { // jmp near - int32_t data = read_e16(); instruction_pointer[0] = get_seg(CS) + data; dbg_assert(is_asize_32() || get_real_eip() < 0x10000); diverged(); } -static void instr16_FF_5() +DEFINE_MODRM_INSTR1_READ16(instr16_FF_4, instr16_FF_4_helper(___)) +static void instr16_FF_5_reg(int32_t r) +{ + dbg_log("jmpf #ud"); + trigger_ud(); +} +static void instr16_FF_5_mem(int32_t addr) { // jmpf - if(modrm_byte[0] >= 0xC0) - { - dbg_log("jmpf #ud"); - trigger_ud(); - dbg_assert_message(false, "unreachable"); - } - - int32_t virt_addr = modrm_resolve(modrm_byte[0]); - int32_t new_ip = safe_read16(virt_addr); - int32_t new_cs = safe_read16(virt_addr + 2); + int32_t new_ip = safe_read16(addr); + int32_t new_cs = safe_read16(addr + 2); far_jump(new_ip, new_cs, false); dbg_assert(is_asize_32() || get_real_eip() < 0x10000); diverged(); } -static void instr16_FF_6() { push16(read_e16()); } +DEFINE_MODRM_INSTR1_READ16(instr16_FF_6, push16(___)) -static void instr32_FF_0() { write_e32(inc32(read_write_e32())); } -static void instr32_FF_1() { write_e32(dec32(read_write_e32())); } -static void instr32_FF_2() +DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_FF_0, inc32(___)) +DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_FF_1, dec32(___)) +static void instr32_FF_2_helper(int32_t data) { // call near - int32_t data = read_e32s(); push32(get_real_eip()); dbg_assert(is_asize_32() || data < 0x10000); instruction_pointer[0] = get_seg(CS) + data; diverged(); } -static void instr32_FF_3() +DEFINE_MODRM_INSTR1_READ32(instr32_FF_2, instr32_FF_2_helper(___)) +static void instr32_FF_3_reg(int32_t r) +{ + dbg_log("callf #ud"); + trigger_ud(); +} +static void instr32_FF_3_mem(int32_t addr) { // callf - if(modrm_byte[0] >= 0xC0) - { - dbg_log("callf #ud"); - trigger_ud(); - dbg_assert_message(false, "unreachable"); - } - - int32_t virt_addr = modrm_resolve(modrm_byte[0]); - int32_t new_ip = safe_read32s(virt_addr); - int32_t new_cs = safe_read16(virt_addr + 4); + int32_t new_ip = safe_read32s(addr); + int32_t new_cs = safe_read16(addr + 4); if(!*protected_mode || vm86_mode()) { @@ -1641,27 +1648,24 @@ static void instr32_FF_3() dbg_assert(is_asize_32() || new_ip < 0x10000); diverged(); } -static void instr32_FF_4() +static void instr32_FF_4_helper(int32_t data) { // jmp near - int32_t data = read_e32s(); dbg_assert(is_asize_32() || data < 0x10000); instruction_pointer[0] = get_seg(CS) + data; diverged(); } -static void instr32_FF_5() +DEFINE_MODRM_INSTR1_READ32(instr32_FF_4, instr32_FF_4_helper(___)) +static void instr32_FF_5_reg(int32_t r) +{ + dbg_log("jmpf #ud"); + trigger_ud(); +} +static void instr32_FF_5_mem(int32_t addr) { // jmpf - if(modrm_byte[0] >= 0xC0) - { - dbg_log("jmpf #ud"); - trigger_ud(); - dbg_assert_message(false, "unreachable"); - } - - int32_t virt_addr = modrm_resolve(modrm_byte[0]); - int32_t new_ip = safe_read32s(virt_addr); - int32_t new_cs = safe_read16(virt_addr + 4); + int32_t new_ip = safe_read32s(addr); + int32_t new_cs = safe_read16(addr + 4); if(!*protected_mode || vm86_mode()) { @@ -1676,7 +1680,7 @@ static void instr32_FF_5() dbg_assert(is_asize_32() || new_ip < 0x10000); diverged(); } -static void instr32_FF_6() { push32(read_e32s()); } +DEFINE_MODRM_INSTR1_READ32(instr32_FF_6, push32(___)) @@ -1689,33 +1693,51 @@ static void run_instruction(int32_t opcode) case 0x00: case 0x00|0x100: { - instr_00(); + 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: { - instr16_01(); + 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: { - instr32_01(); + 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: { - instr_02(); + 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: { - instr16_03(); + 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: { - instr32_03(); + 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: @@ -1757,33 +1779,51 @@ break; case 0x08: case 0x08|0x100: { - instr_08(); + 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: { - instr16_09(); + 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: { - instr32_09(); + 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: { - instr_0A(); + 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: { - instr16_0B(); + 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: { - instr32_0B(); + 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: @@ -1825,33 +1865,51 @@ break; case 0x10: case 0x10|0x100: { - instr_10(); + 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: { - instr16_11(); + 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: { - instr32_11(); + 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: { - instr_12(); + 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: { - instr16_13(); + 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: { - instr32_13(); + 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: @@ -1893,33 +1951,51 @@ break; case 0x18: case 0x18|0x100: { - instr_18(); + 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: { - instr16_19(); + 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: { - instr32_19(); + 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: { - instr_1A(); + 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: { - instr16_1B(); + 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: { - instr32_1B(); + 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: @@ -1961,33 +2037,51 @@ break; case 0x20: case 0x20|0x100: { - instr_20(); + 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: { - instr16_21(); + 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: { - instr32_21(); + 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: { - instr_22(); + 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: { - instr16_23(); + 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: { - instr32_23(); + 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: @@ -2021,33 +2115,51 @@ break; case 0x28: case 0x28|0x100: { - instr_28(); + 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: { - instr16_29(); + 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: { - instr32_29(); + 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: { - instr_2A(); + 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: { - instr16_2B(); + 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: { - instr32_2B(); + 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: @@ -2081,33 +2193,51 @@ break; case 0x30: case 0x30|0x100: { - instr_30(); + 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: { - instr16_31(); + 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: { - instr32_31(); + 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: { - instr_32(); + 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: { - instr16_33(); + 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: { - instr32_33(); + 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: @@ -2141,33 +2271,51 @@ break; case 0x38: case 0x38|0x100: { - instr_38(); + 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: { - instr16_39(); + 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: { - instr32_39(); + 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: { - instr_3A(); + 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: { - instr16_3B(); + 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: { - instr32_3B(); + 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: @@ -2541,13 +2689,19 @@ break; case 0x62: case 0x62|0x100: { - instr_62(); + 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: { - instr_63(); + 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: @@ -2586,12 +2740,18 @@ case 0x68|0x100: break; case 0x69: { - instr16_69(); + 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: { - instr32_69(); + 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: @@ -2606,12 +2766,18 @@ case 0x6A|0x100: break; case 0x6B: { - instr16_6B(); + 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: { - instr32_6B(); + 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: @@ -2745,47 +2911,63 @@ break; case 0x80: case 0x80|0x100: { - read_modrm_byte(); - switch(*modrm_byte >> 3 & 7) + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) { case 0: { - instr_80_0(); + modrm_byte < 0xC0 ? + instr_80_0_mem(modrm_resolve(modrm_byte)) : + instr_80_0_reg(modrm_byte & 7); } break; case 1: { - instr_80_1(); + modrm_byte < 0xC0 ? + instr_80_1_mem(modrm_resolve(modrm_byte)) : + instr_80_1_reg(modrm_byte & 7); } break; case 2: { - instr_80_2(); + modrm_byte < 0xC0 ? + instr_80_2_mem(modrm_resolve(modrm_byte)) : + instr_80_2_reg(modrm_byte & 7); } break; case 3: { - instr_80_3(); + modrm_byte < 0xC0 ? + instr_80_3_mem(modrm_resolve(modrm_byte)) : + instr_80_3_reg(modrm_byte & 7); } break; case 4: { - instr_80_4(); + modrm_byte < 0xC0 ? + instr_80_4_mem(modrm_resolve(modrm_byte)) : + instr_80_4_reg(modrm_byte & 7); } break; case 5: { - instr_80_5(); + modrm_byte < 0xC0 ? + instr_80_5_mem(modrm_resolve(modrm_byte)) : + instr_80_5_reg(modrm_byte & 7); } break; case 6: { - instr_80_6(); + modrm_byte < 0xC0 ? + instr_80_6_mem(modrm_resolve(modrm_byte)) : + instr_80_6_reg(modrm_byte & 7); } break; case 7: { - instr_80_7(); + modrm_byte < 0xC0 ? + instr_80_7_mem(modrm_resolve(modrm_byte)) : + instr_80_7_reg(modrm_byte & 7); } break; default: @@ -2795,47 +2977,63 @@ case 0x80|0x100: break; case 0x81: { - read_modrm_byte(); - switch(*modrm_byte >> 3 & 7) + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) { case 0: { - instr16_81_0(); + modrm_byte < 0xC0 ? + instr16_81_0_mem(modrm_resolve(modrm_byte)) : + instr16_81_0_reg(modrm_byte & 7); } break; case 1: { - instr16_81_1(); + modrm_byte < 0xC0 ? + instr16_81_1_mem(modrm_resolve(modrm_byte)) : + instr16_81_1_reg(modrm_byte & 7); } break; case 2: { - instr16_81_2(); + modrm_byte < 0xC0 ? + instr16_81_2_mem(modrm_resolve(modrm_byte)) : + instr16_81_2_reg(modrm_byte & 7); } break; case 3: { - instr16_81_3(); + modrm_byte < 0xC0 ? + instr16_81_3_mem(modrm_resolve(modrm_byte)) : + instr16_81_3_reg(modrm_byte & 7); } break; case 4: { - instr16_81_4(); + modrm_byte < 0xC0 ? + instr16_81_4_mem(modrm_resolve(modrm_byte)) : + instr16_81_4_reg(modrm_byte & 7); } break; case 5: { - instr16_81_5(); + modrm_byte < 0xC0 ? + instr16_81_5_mem(modrm_resolve(modrm_byte)) : + instr16_81_5_reg(modrm_byte & 7); } break; case 6: { - instr16_81_6(); + modrm_byte < 0xC0 ? + instr16_81_6_mem(modrm_resolve(modrm_byte)) : + instr16_81_6_reg(modrm_byte & 7); } break; case 7: { - instr16_81_7(); + modrm_byte < 0xC0 ? + instr16_81_7_mem(modrm_resolve(modrm_byte)) : + instr16_81_7_reg(modrm_byte & 7); } break; default: @@ -2845,47 +3043,63 @@ case 0x81: break; case 0x81|0x100: { - read_modrm_byte(); - switch(*modrm_byte >> 3 & 7) + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) { case 0: { - instr32_81_0(); + modrm_byte < 0xC0 ? + instr32_81_0_mem(modrm_resolve(modrm_byte)) : + instr32_81_0_reg(modrm_byte & 7); } break; case 1: { - instr32_81_1(); + modrm_byte < 0xC0 ? + instr32_81_1_mem(modrm_resolve(modrm_byte)) : + instr32_81_1_reg(modrm_byte & 7); } break; case 2: { - instr32_81_2(); + modrm_byte < 0xC0 ? + instr32_81_2_mem(modrm_resolve(modrm_byte)) : + instr32_81_2_reg(modrm_byte & 7); } break; case 3: { - instr32_81_3(); + modrm_byte < 0xC0 ? + instr32_81_3_mem(modrm_resolve(modrm_byte)) : + instr32_81_3_reg(modrm_byte & 7); } break; case 4: { - instr32_81_4(); + modrm_byte < 0xC0 ? + instr32_81_4_mem(modrm_resolve(modrm_byte)) : + instr32_81_4_reg(modrm_byte & 7); } break; case 5: { - instr32_81_5(); + modrm_byte < 0xC0 ? + instr32_81_5_mem(modrm_resolve(modrm_byte)) : + instr32_81_5_reg(modrm_byte & 7); } break; case 6: { - instr32_81_6(); + modrm_byte < 0xC0 ? + instr32_81_6_mem(modrm_resolve(modrm_byte)) : + instr32_81_6_reg(modrm_byte & 7); } break; case 7: { - instr32_81_7(); + modrm_byte < 0xC0 ? + instr32_81_7_mem(modrm_resolve(modrm_byte)) : + instr32_81_7_reg(modrm_byte & 7); } break; default: @@ -2896,47 +3110,63 @@ break; case 0x82: case 0x82|0x100: { - read_modrm_byte(); - switch(*modrm_byte >> 3 & 7) + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) { case 0: { - instr_82_0(); + modrm_byte < 0xC0 ? + instr_82_0_mem(modrm_resolve(modrm_byte)) : + instr_82_0_reg(modrm_byte & 7); } break; case 1: { - instr_82_1(); + modrm_byte < 0xC0 ? + instr_82_1_mem(modrm_resolve(modrm_byte)) : + instr_82_1_reg(modrm_byte & 7); } break; case 2: { - instr_82_2(); + modrm_byte < 0xC0 ? + instr_82_2_mem(modrm_resolve(modrm_byte)) : + instr_82_2_reg(modrm_byte & 7); } break; case 3: { - instr_82_3(); + modrm_byte < 0xC0 ? + instr_82_3_mem(modrm_resolve(modrm_byte)) : + instr_82_3_reg(modrm_byte & 7); } break; case 4: { - instr_82_4(); + modrm_byte < 0xC0 ? + instr_82_4_mem(modrm_resolve(modrm_byte)) : + instr_82_4_reg(modrm_byte & 7); } break; case 5: { - instr_82_5(); + modrm_byte < 0xC0 ? + instr_82_5_mem(modrm_resolve(modrm_byte)) : + instr_82_5_reg(modrm_byte & 7); } break; case 6: { - instr_82_6(); + modrm_byte < 0xC0 ? + instr_82_6_mem(modrm_resolve(modrm_byte)) : + instr_82_6_reg(modrm_byte & 7); } break; case 7: { - instr_82_7(); + modrm_byte < 0xC0 ? + instr_82_7_mem(modrm_resolve(modrm_byte)) : + instr_82_7_reg(modrm_byte & 7); } break; default: @@ -2946,47 +3176,63 @@ case 0x82|0x100: break; case 0x83: { - read_modrm_byte(); - switch(*modrm_byte >> 3 & 7) + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) { case 0: { - instr16_83_0(); + modrm_byte < 0xC0 ? + instr16_83_0_mem(modrm_resolve(modrm_byte)) : + instr16_83_0_reg(modrm_byte & 7); } break; case 1: { - instr16_83_1(); + modrm_byte < 0xC0 ? + instr16_83_1_mem(modrm_resolve(modrm_byte)) : + instr16_83_1_reg(modrm_byte & 7); } break; case 2: { - instr16_83_2(); + modrm_byte < 0xC0 ? + instr16_83_2_mem(modrm_resolve(modrm_byte)) : + instr16_83_2_reg(modrm_byte & 7); } break; case 3: { - instr16_83_3(); + modrm_byte < 0xC0 ? + instr16_83_3_mem(modrm_resolve(modrm_byte)) : + instr16_83_3_reg(modrm_byte & 7); } break; case 4: { - instr16_83_4(); + modrm_byte < 0xC0 ? + instr16_83_4_mem(modrm_resolve(modrm_byte)) : + instr16_83_4_reg(modrm_byte & 7); } break; case 5: { - instr16_83_5(); + modrm_byte < 0xC0 ? + instr16_83_5_mem(modrm_resolve(modrm_byte)) : + instr16_83_5_reg(modrm_byte & 7); } break; case 6: { - instr16_83_6(); + modrm_byte < 0xC0 ? + instr16_83_6_mem(modrm_resolve(modrm_byte)) : + instr16_83_6_reg(modrm_byte & 7); } break; case 7: { - instr16_83_7(); + modrm_byte < 0xC0 ? + instr16_83_7_mem(modrm_resolve(modrm_byte)) : + instr16_83_7_reg(modrm_byte & 7); } break; default: @@ -2996,47 +3242,63 @@ case 0x83: break; case 0x83|0x100: { - read_modrm_byte(); - switch(*modrm_byte >> 3 & 7) + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) { case 0: { - instr32_83_0(); + modrm_byte < 0xC0 ? + instr32_83_0_mem(modrm_resolve(modrm_byte)) : + instr32_83_0_reg(modrm_byte & 7); } break; case 1: { - instr32_83_1(); + modrm_byte < 0xC0 ? + instr32_83_1_mem(modrm_resolve(modrm_byte)) : + instr32_83_1_reg(modrm_byte & 7); } break; case 2: { - instr32_83_2(); + modrm_byte < 0xC0 ? + instr32_83_2_mem(modrm_resolve(modrm_byte)) : + instr32_83_2_reg(modrm_byte & 7); } break; case 3: { - instr32_83_3(); + modrm_byte < 0xC0 ? + instr32_83_3_mem(modrm_resolve(modrm_byte)) : + instr32_83_3_reg(modrm_byte & 7); } break; case 4: { - instr32_83_4(); + modrm_byte < 0xC0 ? + instr32_83_4_mem(modrm_resolve(modrm_byte)) : + instr32_83_4_reg(modrm_byte & 7); } break; case 5: { - instr32_83_5(); + modrm_byte < 0xC0 ? + instr32_83_5_mem(modrm_resolve(modrm_byte)) : + instr32_83_5_reg(modrm_byte & 7); } break; case 6: { - instr32_83_6(); + modrm_byte < 0xC0 ? + instr32_83_6_mem(modrm_resolve(modrm_byte)) : + instr32_83_6_reg(modrm_byte & 7); } break; case 7: { - instr32_83_7(); + modrm_byte < 0xC0 ? + instr32_83_7_mem(modrm_resolve(modrm_byte)) : + instr32_83_7_reg(modrm_byte & 7); } break; default: @@ -3047,101 +3309,180 @@ break; case 0x84: case 0x84|0x100: { - instr_84(); + 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: { - instr16_85(); + 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: { - instr32_85(); + 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: { - instr_86(); + 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: { - instr16_87(); + 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: { - instr32_87(); + 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: { - instr_88(); + 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: { - instr16_89(); + 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: { - instr32_89(); + 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: { - instr_8A(); + 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: { - instr16_8B(); + 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: { - instr32_8B(); + 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: { - instr16_8C(); + 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: { - instr32_8C(); + 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: { - instr16_8D(); + 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: { - instr32_8D(); + 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: { - instr_8E(); + 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: { - instr16_8F(); + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) + { + 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); + } } break; case 0x8F|0x100: { - instr32_8F(); + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) + { + 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); + } } break; case 0x90: @@ -3547,47 +3888,63 @@ break; case 0xC0: case 0xC0|0x100: { - read_modrm_byte(); - switch(*modrm_byte >> 3 & 7) + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) { case 0: { - instr_C0_0(); + modrm_byte < 0xC0 ? + instr_C0_0_mem(modrm_resolve(modrm_byte)) : + instr_C0_0_reg(modrm_byte & 7); } break; case 1: { - instr_C0_1(); + modrm_byte < 0xC0 ? + instr_C0_1_mem(modrm_resolve(modrm_byte)) : + instr_C0_1_reg(modrm_byte & 7); } break; case 2: { - instr_C0_2(); + modrm_byte < 0xC0 ? + instr_C0_2_mem(modrm_resolve(modrm_byte)) : + instr_C0_2_reg(modrm_byte & 7); } break; case 3: { - instr_C0_3(); + modrm_byte < 0xC0 ? + instr_C0_3_mem(modrm_resolve(modrm_byte)) : + instr_C0_3_reg(modrm_byte & 7); } break; case 4: { - instr_C0_4(); + modrm_byte < 0xC0 ? + instr_C0_4_mem(modrm_resolve(modrm_byte)) : + instr_C0_4_reg(modrm_byte & 7); } break; case 5: { - instr_C0_5(); + modrm_byte < 0xC0 ? + instr_C0_5_mem(modrm_resolve(modrm_byte)) : + instr_C0_5_reg(modrm_byte & 7); } break; case 6: { - instr_C0_6(); + modrm_byte < 0xC0 ? + instr_C0_6_mem(modrm_resolve(modrm_byte)) : + instr_C0_6_reg(modrm_byte & 7); } break; case 7: { - instr_C0_7(); + modrm_byte < 0xC0 ? + instr_C0_7_mem(modrm_resolve(modrm_byte)) : + instr_C0_7_reg(modrm_byte & 7); } break; default: @@ -3597,47 +3954,63 @@ case 0xC0|0x100: break; case 0xC1: { - read_modrm_byte(); - switch(*modrm_byte >> 3 & 7) + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) { case 0: { - instr16_C1_0(); + modrm_byte < 0xC0 ? + instr16_C1_0_mem(modrm_resolve(modrm_byte)) : + instr16_C1_0_reg(modrm_byte & 7); } break; case 1: { - instr16_C1_1(); + modrm_byte < 0xC0 ? + instr16_C1_1_mem(modrm_resolve(modrm_byte)) : + instr16_C1_1_reg(modrm_byte & 7); } break; case 2: { - instr16_C1_2(); + modrm_byte < 0xC0 ? + instr16_C1_2_mem(modrm_resolve(modrm_byte)) : + instr16_C1_2_reg(modrm_byte & 7); } break; case 3: { - instr16_C1_3(); + modrm_byte < 0xC0 ? + instr16_C1_3_mem(modrm_resolve(modrm_byte)) : + instr16_C1_3_reg(modrm_byte & 7); } break; case 4: { - instr16_C1_4(); + modrm_byte < 0xC0 ? + instr16_C1_4_mem(modrm_resolve(modrm_byte)) : + instr16_C1_4_reg(modrm_byte & 7); } break; case 5: { - instr16_C1_5(); + modrm_byte < 0xC0 ? + instr16_C1_5_mem(modrm_resolve(modrm_byte)) : + instr16_C1_5_reg(modrm_byte & 7); } break; case 6: { - instr16_C1_6(); + modrm_byte < 0xC0 ? + instr16_C1_6_mem(modrm_resolve(modrm_byte)) : + instr16_C1_6_reg(modrm_byte & 7); } break; case 7: { - instr16_C1_7(); + modrm_byte < 0xC0 ? + instr16_C1_7_mem(modrm_resolve(modrm_byte)) : + instr16_C1_7_reg(modrm_byte & 7); } break; default: @@ -3647,47 +4020,63 @@ case 0xC1: break; case 0xC1|0x100: { - read_modrm_byte(); - switch(*modrm_byte >> 3 & 7) + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) { case 0: { - instr32_C1_0(); + modrm_byte < 0xC0 ? + instr32_C1_0_mem(modrm_resolve(modrm_byte)) : + instr32_C1_0_reg(modrm_byte & 7); } break; case 1: { - instr32_C1_1(); + modrm_byte < 0xC0 ? + instr32_C1_1_mem(modrm_resolve(modrm_byte)) : + instr32_C1_1_reg(modrm_byte & 7); } break; case 2: { - instr32_C1_2(); + modrm_byte < 0xC0 ? + instr32_C1_2_mem(modrm_resolve(modrm_byte)) : + instr32_C1_2_reg(modrm_byte & 7); } break; case 3: { - instr32_C1_3(); + modrm_byte < 0xC0 ? + instr32_C1_3_mem(modrm_resolve(modrm_byte)) : + instr32_C1_3_reg(modrm_byte & 7); } break; case 4: { - instr32_C1_4(); + modrm_byte < 0xC0 ? + instr32_C1_4_mem(modrm_resolve(modrm_byte)) : + instr32_C1_4_reg(modrm_byte & 7); } break; case 5: { - instr32_C1_5(); + modrm_byte < 0xC0 ? + instr32_C1_5_mem(modrm_resolve(modrm_byte)) : + instr32_C1_5_reg(modrm_byte & 7); } break; case 6: { - instr32_C1_6(); + modrm_byte < 0xC0 ? + instr32_C1_6_mem(modrm_resolve(modrm_byte)) : + instr32_C1_6_reg(modrm_byte & 7); } break; case 7: { - instr32_C1_7(); + modrm_byte < 0xC0 ? + instr32_C1_7_mem(modrm_resolve(modrm_byte)) : + instr32_C1_7_reg(modrm_byte & 7); } break; default: @@ -3717,38 +4106,86 @@ case 0xC3|0x100: break; case 0xC4: { - instr16_C4(); + 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: { - instr32_C4(); + 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: { - instr16_C5(); + 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: { - instr32_C5(); + 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: { - instr_C6(); + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) + { + case 0: + { + modrm_byte < 0xC0 ? + instr_C6_0_mem(modrm_resolve(modrm_byte)) : + instr_C6_0_reg(modrm_byte & 7); + } + break; + default: + assert(false); + } } break; case 0xC7: { - instr16_C7(); + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) + { + case 0: + { + modrm_byte < 0xC0 ? + instr16_C7_0_mem(modrm_resolve(modrm_byte)) : + instr16_C7_0_reg(modrm_byte & 7); + } + break; + default: + assert(false); + } } break; case 0xC7|0x100: { - instr32_C7(); + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) + { + case 0: + { + modrm_byte < 0xC0 ? + instr32_C7_0_mem(modrm_resolve(modrm_byte)) : + instr32_C7_0_reg(modrm_byte & 7); + } + break; + default: + assert(false); + } } break; case 0xC8: @@ -3822,47 +4259,63 @@ break; case 0xD0: case 0xD0|0x100: { - read_modrm_byte(); - switch(*modrm_byte >> 3 & 7) + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) { case 0: { - instr_D0_0(); + modrm_byte < 0xC0 ? + instr_D0_0_mem(modrm_resolve(modrm_byte)) : + instr_D0_0_reg(modrm_byte & 7); } break; case 1: { - instr_D0_1(); + modrm_byte < 0xC0 ? + instr_D0_1_mem(modrm_resolve(modrm_byte)) : + instr_D0_1_reg(modrm_byte & 7); } break; case 2: { - instr_D0_2(); + modrm_byte < 0xC0 ? + instr_D0_2_mem(modrm_resolve(modrm_byte)) : + instr_D0_2_reg(modrm_byte & 7); } break; case 3: { - instr_D0_3(); + modrm_byte < 0xC0 ? + instr_D0_3_mem(modrm_resolve(modrm_byte)) : + instr_D0_3_reg(modrm_byte & 7); } break; case 4: { - instr_D0_4(); + modrm_byte < 0xC0 ? + instr_D0_4_mem(modrm_resolve(modrm_byte)) : + instr_D0_4_reg(modrm_byte & 7); } break; case 5: { - instr_D0_5(); + modrm_byte < 0xC0 ? + instr_D0_5_mem(modrm_resolve(modrm_byte)) : + instr_D0_5_reg(modrm_byte & 7); } break; case 6: { - instr_D0_6(); + modrm_byte < 0xC0 ? + instr_D0_6_mem(modrm_resolve(modrm_byte)) : + instr_D0_6_reg(modrm_byte & 7); } break; case 7: { - instr_D0_7(); + modrm_byte < 0xC0 ? + instr_D0_7_mem(modrm_resolve(modrm_byte)) : + instr_D0_7_reg(modrm_byte & 7); } break; default: @@ -3872,47 +4325,63 @@ case 0xD0|0x100: break; case 0xD1: { - read_modrm_byte(); - switch(*modrm_byte >> 3 & 7) + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) { case 0: { - instr16_D1_0(); + modrm_byte < 0xC0 ? + instr16_D1_0_mem(modrm_resolve(modrm_byte)) : + instr16_D1_0_reg(modrm_byte & 7); } break; case 1: { - instr16_D1_1(); + modrm_byte < 0xC0 ? + instr16_D1_1_mem(modrm_resolve(modrm_byte)) : + instr16_D1_1_reg(modrm_byte & 7); } break; case 2: { - instr16_D1_2(); + modrm_byte < 0xC0 ? + instr16_D1_2_mem(modrm_resolve(modrm_byte)) : + instr16_D1_2_reg(modrm_byte & 7); } break; case 3: { - instr16_D1_3(); + modrm_byte < 0xC0 ? + instr16_D1_3_mem(modrm_resolve(modrm_byte)) : + instr16_D1_3_reg(modrm_byte & 7); } break; case 4: { - instr16_D1_4(); + modrm_byte < 0xC0 ? + instr16_D1_4_mem(modrm_resolve(modrm_byte)) : + instr16_D1_4_reg(modrm_byte & 7); } break; case 5: { - instr16_D1_5(); + modrm_byte < 0xC0 ? + instr16_D1_5_mem(modrm_resolve(modrm_byte)) : + instr16_D1_5_reg(modrm_byte & 7); } break; case 6: { - instr16_D1_6(); + modrm_byte < 0xC0 ? + instr16_D1_6_mem(modrm_resolve(modrm_byte)) : + instr16_D1_6_reg(modrm_byte & 7); } break; case 7: { - instr16_D1_7(); + modrm_byte < 0xC0 ? + instr16_D1_7_mem(modrm_resolve(modrm_byte)) : + instr16_D1_7_reg(modrm_byte & 7); } break; default: @@ -3922,47 +4391,63 @@ case 0xD1: break; case 0xD1|0x100: { - read_modrm_byte(); - switch(*modrm_byte >> 3 & 7) + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) { case 0: { - instr32_D1_0(); + modrm_byte < 0xC0 ? + instr32_D1_0_mem(modrm_resolve(modrm_byte)) : + instr32_D1_0_reg(modrm_byte & 7); } break; case 1: { - instr32_D1_1(); + modrm_byte < 0xC0 ? + instr32_D1_1_mem(modrm_resolve(modrm_byte)) : + instr32_D1_1_reg(modrm_byte & 7); } break; case 2: { - instr32_D1_2(); + modrm_byte < 0xC0 ? + instr32_D1_2_mem(modrm_resolve(modrm_byte)) : + instr32_D1_2_reg(modrm_byte & 7); } break; case 3: { - instr32_D1_3(); + modrm_byte < 0xC0 ? + instr32_D1_3_mem(modrm_resolve(modrm_byte)) : + instr32_D1_3_reg(modrm_byte & 7); } break; case 4: { - instr32_D1_4(); + modrm_byte < 0xC0 ? + instr32_D1_4_mem(modrm_resolve(modrm_byte)) : + instr32_D1_4_reg(modrm_byte & 7); } break; case 5: { - instr32_D1_5(); + modrm_byte < 0xC0 ? + instr32_D1_5_mem(modrm_resolve(modrm_byte)) : + instr32_D1_5_reg(modrm_byte & 7); } break; case 6: { - instr32_D1_6(); + modrm_byte < 0xC0 ? + instr32_D1_6_mem(modrm_resolve(modrm_byte)) : + instr32_D1_6_reg(modrm_byte & 7); } break; case 7: { - instr32_D1_7(); + modrm_byte < 0xC0 ? + instr32_D1_7_mem(modrm_resolve(modrm_byte)) : + instr32_D1_7_reg(modrm_byte & 7); } break; default: @@ -3973,47 +4458,63 @@ break; case 0xD2: case 0xD2|0x100: { - read_modrm_byte(); - switch(*modrm_byte >> 3 & 7) + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) { case 0: { - instr_D2_0(); + modrm_byte < 0xC0 ? + instr_D2_0_mem(modrm_resolve(modrm_byte)) : + instr_D2_0_reg(modrm_byte & 7); } break; case 1: { - instr_D2_1(); + modrm_byte < 0xC0 ? + instr_D2_1_mem(modrm_resolve(modrm_byte)) : + instr_D2_1_reg(modrm_byte & 7); } break; case 2: { - instr_D2_2(); + modrm_byte < 0xC0 ? + instr_D2_2_mem(modrm_resolve(modrm_byte)) : + instr_D2_2_reg(modrm_byte & 7); } break; case 3: { - instr_D2_3(); + modrm_byte < 0xC0 ? + instr_D2_3_mem(modrm_resolve(modrm_byte)) : + instr_D2_3_reg(modrm_byte & 7); } break; case 4: { - instr_D2_4(); + modrm_byte < 0xC0 ? + instr_D2_4_mem(modrm_resolve(modrm_byte)) : + instr_D2_4_reg(modrm_byte & 7); } break; case 5: { - instr_D2_5(); + modrm_byte < 0xC0 ? + instr_D2_5_mem(modrm_resolve(modrm_byte)) : + instr_D2_5_reg(modrm_byte & 7); } break; case 6: { - instr_D2_6(); + modrm_byte < 0xC0 ? + instr_D2_6_mem(modrm_resolve(modrm_byte)) : + instr_D2_6_reg(modrm_byte & 7); } break; case 7: { - instr_D2_7(); + modrm_byte < 0xC0 ? + instr_D2_7_mem(modrm_resolve(modrm_byte)) : + instr_D2_7_reg(modrm_byte & 7); } break; default: @@ -4023,47 +4524,63 @@ case 0xD2|0x100: break; case 0xD3: { - read_modrm_byte(); - switch(*modrm_byte >> 3 & 7) + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) { case 0: { - instr16_D3_0(); + modrm_byte < 0xC0 ? + instr16_D3_0_mem(modrm_resolve(modrm_byte)) : + instr16_D3_0_reg(modrm_byte & 7); } break; case 1: { - instr16_D3_1(); + modrm_byte < 0xC0 ? + instr16_D3_1_mem(modrm_resolve(modrm_byte)) : + instr16_D3_1_reg(modrm_byte & 7); } break; case 2: { - instr16_D3_2(); + modrm_byte < 0xC0 ? + instr16_D3_2_mem(modrm_resolve(modrm_byte)) : + instr16_D3_2_reg(modrm_byte & 7); } break; case 3: { - instr16_D3_3(); + modrm_byte < 0xC0 ? + instr16_D3_3_mem(modrm_resolve(modrm_byte)) : + instr16_D3_3_reg(modrm_byte & 7); } break; case 4: { - instr16_D3_4(); + modrm_byte < 0xC0 ? + instr16_D3_4_mem(modrm_resolve(modrm_byte)) : + instr16_D3_4_reg(modrm_byte & 7); } break; case 5: { - instr16_D3_5(); + modrm_byte < 0xC0 ? + instr16_D3_5_mem(modrm_resolve(modrm_byte)) : + instr16_D3_5_reg(modrm_byte & 7); } break; case 6: { - instr16_D3_6(); + modrm_byte < 0xC0 ? + instr16_D3_6_mem(modrm_resolve(modrm_byte)) : + instr16_D3_6_reg(modrm_byte & 7); } break; case 7: { - instr16_D3_7(); + modrm_byte < 0xC0 ? + instr16_D3_7_mem(modrm_resolve(modrm_byte)) : + instr16_D3_7_reg(modrm_byte & 7); } break; default: @@ -4073,47 +4590,63 @@ case 0xD3: break; case 0xD3|0x100: { - read_modrm_byte(); - switch(*modrm_byte >> 3 & 7) + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) { case 0: { - instr32_D3_0(); + modrm_byte < 0xC0 ? + instr32_D3_0_mem(modrm_resolve(modrm_byte)) : + instr32_D3_0_reg(modrm_byte & 7); } break; case 1: { - instr32_D3_1(); + modrm_byte < 0xC0 ? + instr32_D3_1_mem(modrm_resolve(modrm_byte)) : + instr32_D3_1_reg(modrm_byte & 7); } break; case 2: { - instr32_D3_2(); + modrm_byte < 0xC0 ? + instr32_D3_2_mem(modrm_resolve(modrm_byte)) : + instr32_D3_2_reg(modrm_byte & 7); } break; case 3: { - instr32_D3_3(); + modrm_byte < 0xC0 ? + instr32_D3_3_mem(modrm_resolve(modrm_byte)) : + instr32_D3_3_reg(modrm_byte & 7); } break; case 4: { - instr32_D3_4(); + modrm_byte < 0xC0 ? + instr32_D3_4_mem(modrm_resolve(modrm_byte)) : + instr32_D3_4_reg(modrm_byte & 7); } break; case 5: { - instr32_D3_5(); + modrm_byte < 0xC0 ? + instr32_D3_5_mem(modrm_resolve(modrm_byte)) : + instr32_D3_5_reg(modrm_byte & 7); } break; case 6: { - instr32_D3_6(); + modrm_byte < 0xC0 ? + instr32_D3_6_mem(modrm_resolve(modrm_byte)) : + instr32_D3_6_reg(modrm_byte & 7); } break; case 7: { - instr32_D3_7(); + modrm_byte < 0xC0 ? + instr32_D3_7_mem(modrm_resolve(modrm_byte)) : + instr32_D3_7_reg(modrm_byte & 7); } break; default: @@ -4148,49 +4681,73 @@ break; case 0xD8: case 0xD8|0x100: { - instr_D8(); + 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: { - instr_D9(); + 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: { - instr_DA(); + 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: { - instr_DB(); + 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: { - instr_DC(); + 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: { - instr_DD(); + 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: { - instr_DE(); + 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: { - instr_DF(); + 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: @@ -4356,47 +4913,63 @@ break; case 0xF6: case 0xF6|0x100: { - read_modrm_byte(); - switch(*modrm_byte >> 3 & 7) + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) { case 0: { - instr_F6_0(); + modrm_byte < 0xC0 ? + instr_F6_0_mem(modrm_resolve(modrm_byte)) : + instr_F6_0_reg(modrm_byte & 7); } break; case 1: { - instr_F6_1(); + modrm_byte < 0xC0 ? + instr_F6_1_mem(modrm_resolve(modrm_byte)) : + instr_F6_1_reg(modrm_byte & 7); } break; case 2: { - instr_F6_2(); + modrm_byte < 0xC0 ? + instr_F6_2_mem(modrm_resolve(modrm_byte)) : + instr_F6_2_reg(modrm_byte & 7); } break; case 3: { - instr_F6_3(); + modrm_byte < 0xC0 ? + instr_F6_3_mem(modrm_resolve(modrm_byte)) : + instr_F6_3_reg(modrm_byte & 7); } break; case 4: { - instr_F6_4(); + modrm_byte < 0xC0 ? + instr_F6_4_mem(modrm_resolve(modrm_byte)) : + instr_F6_4_reg(modrm_byte & 7); } break; case 5: { - instr_F6_5(); + modrm_byte < 0xC0 ? + instr_F6_5_mem(modrm_resolve(modrm_byte)) : + instr_F6_5_reg(modrm_byte & 7); } break; case 6: { - instr_F6_6(); + modrm_byte < 0xC0 ? + instr_F6_6_mem(modrm_resolve(modrm_byte)) : + instr_F6_6_reg(modrm_byte & 7); } break; case 7: { - instr_F6_7(); + modrm_byte < 0xC0 ? + instr_F6_7_mem(modrm_resolve(modrm_byte)) : + instr_F6_7_reg(modrm_byte & 7); } break; default: @@ -4406,47 +4979,63 @@ case 0xF6|0x100: break; case 0xF7: { - read_modrm_byte(); - switch(*modrm_byte >> 3 & 7) + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) { case 0: { - instr16_F7_0(); + modrm_byte < 0xC0 ? + instr16_F7_0_mem(modrm_resolve(modrm_byte)) : + instr16_F7_0_reg(modrm_byte & 7); } break; case 1: { - instr16_F7_1(); + modrm_byte < 0xC0 ? + instr16_F7_1_mem(modrm_resolve(modrm_byte)) : + instr16_F7_1_reg(modrm_byte & 7); } break; case 2: { - instr16_F7_2(); + modrm_byte < 0xC0 ? + instr16_F7_2_mem(modrm_resolve(modrm_byte)) : + instr16_F7_2_reg(modrm_byte & 7); } break; case 3: { - instr16_F7_3(); + modrm_byte < 0xC0 ? + instr16_F7_3_mem(modrm_resolve(modrm_byte)) : + instr16_F7_3_reg(modrm_byte & 7); } break; case 4: { - instr16_F7_4(); + modrm_byte < 0xC0 ? + instr16_F7_4_mem(modrm_resolve(modrm_byte)) : + instr16_F7_4_reg(modrm_byte & 7); } break; case 5: { - instr16_F7_5(); + modrm_byte < 0xC0 ? + instr16_F7_5_mem(modrm_resolve(modrm_byte)) : + instr16_F7_5_reg(modrm_byte & 7); } break; case 6: { - instr16_F7_6(); + modrm_byte < 0xC0 ? + instr16_F7_6_mem(modrm_resolve(modrm_byte)) : + instr16_F7_6_reg(modrm_byte & 7); } break; case 7: { - instr16_F7_7(); + modrm_byte < 0xC0 ? + instr16_F7_7_mem(modrm_resolve(modrm_byte)) : + instr16_F7_7_reg(modrm_byte & 7); } break; default: @@ -4456,47 +5045,63 @@ case 0xF7: break; case 0xF7|0x100: { - read_modrm_byte(); - switch(*modrm_byte >> 3 & 7) + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) { case 0: { - instr32_F7_0(); + modrm_byte < 0xC0 ? + instr32_F7_0_mem(modrm_resolve(modrm_byte)) : + instr32_F7_0_reg(modrm_byte & 7); } break; case 1: { - instr32_F7_1(); + modrm_byte < 0xC0 ? + instr32_F7_1_mem(modrm_resolve(modrm_byte)) : + instr32_F7_1_reg(modrm_byte & 7); } break; case 2: { - instr32_F7_2(); + modrm_byte < 0xC0 ? + instr32_F7_2_mem(modrm_resolve(modrm_byte)) : + instr32_F7_2_reg(modrm_byte & 7); } break; case 3: { - instr32_F7_3(); + modrm_byte < 0xC0 ? + instr32_F7_3_mem(modrm_resolve(modrm_byte)) : + instr32_F7_3_reg(modrm_byte & 7); } break; case 4: { - instr32_F7_4(); + modrm_byte < 0xC0 ? + instr32_F7_4_mem(modrm_resolve(modrm_byte)) : + instr32_F7_4_reg(modrm_byte & 7); } break; case 5: { - instr32_F7_5(); + modrm_byte < 0xC0 ? + instr32_F7_5_mem(modrm_resolve(modrm_byte)) : + instr32_F7_5_reg(modrm_byte & 7); } break; case 6: { - instr32_F7_6(); + modrm_byte < 0xC0 ? + instr32_F7_6_mem(modrm_resolve(modrm_byte)) : + instr32_F7_6_reg(modrm_byte & 7); } break; case 7: { - instr32_F7_7(); + modrm_byte < 0xC0 ? + instr32_F7_7_mem(modrm_resolve(modrm_byte)) : + instr32_F7_7_reg(modrm_byte & 7); } break; default: @@ -4543,17 +5148,21 @@ break; case 0xFE: case 0xFE|0x100: { - read_modrm_byte(); - switch(*modrm_byte >> 3 & 7) + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) { case 0: { - instr_FE_0(); + modrm_byte < 0xC0 ? + instr_FE_0_mem(modrm_resolve(modrm_byte)) : + instr_FE_0_reg(modrm_byte & 7); } break; case 1: { - instr_FE_1(); + modrm_byte < 0xC0 ? + instr_FE_1_mem(modrm_resolve(modrm_byte)) : + instr_FE_1_reg(modrm_byte & 7); } break; default: @@ -4563,42 +5172,56 @@ case 0xFE|0x100: break; case 0xFF: { - read_modrm_byte(); - switch(*modrm_byte >> 3 & 7) + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) { case 0: { - instr16_FF_0(); + modrm_byte < 0xC0 ? + instr16_FF_0_mem(modrm_resolve(modrm_byte)) : + instr16_FF_0_reg(modrm_byte & 7); } break; case 1: { - instr16_FF_1(); + modrm_byte < 0xC0 ? + instr16_FF_1_mem(modrm_resolve(modrm_byte)) : + instr16_FF_1_reg(modrm_byte & 7); } break; case 2: { - instr16_FF_2(); + modrm_byte < 0xC0 ? + instr16_FF_2_mem(modrm_resolve(modrm_byte)) : + instr16_FF_2_reg(modrm_byte & 7); } break; case 3: { - instr16_FF_3(); + modrm_byte < 0xC0 ? + instr16_FF_3_mem(modrm_resolve(modrm_byte)) : + instr16_FF_3_reg(modrm_byte & 7); } break; case 4: { - instr16_FF_4(); + modrm_byte < 0xC0 ? + instr16_FF_4_mem(modrm_resolve(modrm_byte)) : + instr16_FF_4_reg(modrm_byte & 7); } break; case 5: { - instr16_FF_5(); + modrm_byte < 0xC0 ? + instr16_FF_5_mem(modrm_resolve(modrm_byte)) : + instr16_FF_5_reg(modrm_byte & 7); } break; case 6: { - instr16_FF_6(); + modrm_byte < 0xC0 ? + instr16_FF_6_mem(modrm_resolve(modrm_byte)) : + instr16_FF_6_reg(modrm_byte & 7); } break; default: @@ -4608,42 +5231,56 @@ case 0xFF: break; case 0xFF|0x100: { - read_modrm_byte(); - switch(*modrm_byte >> 3 & 7) + int32_t modrm_byte = read_imm8(); + switch(modrm_byte >> 3 & 7) { case 0: { - instr32_FF_0(); + modrm_byte < 0xC0 ? + instr32_FF_0_mem(modrm_resolve(modrm_byte)) : + instr32_FF_0_reg(modrm_byte & 7); } break; case 1: { - instr32_FF_1(); + modrm_byte < 0xC0 ? + instr32_FF_1_mem(modrm_resolve(modrm_byte)) : + instr32_FF_1_reg(modrm_byte & 7); } break; case 2: { - instr32_FF_2(); + modrm_byte < 0xC0 ? + instr32_FF_2_mem(modrm_resolve(modrm_byte)) : + instr32_FF_2_reg(modrm_byte & 7); } break; case 3: { - instr32_FF_3(); + modrm_byte < 0xC0 ? + instr32_FF_3_mem(modrm_resolve(modrm_byte)) : + instr32_FF_3_reg(modrm_byte & 7); } break; case 4: { - instr32_FF_4(); + modrm_byte < 0xC0 ? + instr32_FF_4_mem(modrm_resolve(modrm_byte)) : + instr32_FF_4_reg(modrm_byte & 7); } break; case 5: { - instr32_FF_5(); + modrm_byte < 0xC0 ? + instr32_FF_5_mem(modrm_resolve(modrm_byte)) : + instr32_FF_5_reg(modrm_byte & 7); } break; case 6: { - instr32_FF_6(); + modrm_byte < 0xC0 ? + instr32_FF_6_mem(modrm_resolve(modrm_byte)) : + instr32_FF_6_reg(modrm_byte & 7); } break; default: diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index aec6485f..39de15b5 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -496,7 +496,7 @@ static void instr_0F22() { read_modrm_byte(); assert(false); } - //dbg_log("cr4=" + h(cr[4])); + //dbg_log("cr4=%d", cr[4]); break; default: @@ -1357,10 +1357,12 @@ static void instr32_0FB1() { read_modrm_byte(); // lss static void instr16_0FB2() { read_modrm_byte(); - lss16(SS); + if(modrm_byte[0] >= 0xC0) trigger_ud(); + lss16(modrm_resolve(*modrm_byte), *modrm_byte >> 2 & 14, SS); } static void instr32_0FB2() { read_modrm_byte(); - lss32(SS); + if(modrm_byte[0] >= 0xC0) trigger_ud(); + lss32(modrm_resolve(*modrm_byte), *modrm_byte >> 3 & 7, SS); } static void instr16_0FB3() { read_modrm_byte(); @@ -1380,16 +1382,20 @@ static void instr32_0FB3() { read_modrm_byte(); // lfs, lgs static void instr16_0FB4() { read_modrm_byte(); - lss16(FS); + if(modrm_byte[0] >= 0xC0) trigger_ud(); + lss16(modrm_resolve(*modrm_byte), *modrm_byte >> 2 & 14, FS); } static void instr32_0FB4() { read_modrm_byte(); - lss32(FS); + if(modrm_byte[0] >= 0xC0) trigger_ud(); + lss32(modrm_resolve(*modrm_byte), *modrm_byte >> 3 & 7, FS); } static void instr16_0FB5() { read_modrm_byte(); - lss16(GS); + if(modrm_byte[0] >= 0xC0) trigger_ud(); + lss16(modrm_resolve(*modrm_byte), *modrm_byte >> 2 & 14, GS); } static void instr32_0FB5() { read_modrm_byte(); - lss32(GS); + if(modrm_byte[0] >= 0xC0) trigger_ud(); + lss32(modrm_resolve(*modrm_byte), *modrm_byte >> 3 & 7, GS); } static void instr16_0FB6() { read_modrm_byte(); diff --git a/tests/nasm/create_tests.js b/tests/nasm/create_tests.js index 3477ab25..2de3645d 100755 --- a/tests/nasm/create_tests.js +++ b/tests/nasm/create_tests.js @@ -106,7 +106,7 @@ const encodings = [ { opcode: 0x8C, os: 1, e: 1, g: 1, skip: 1, }, { opcode: 0x8D, os: 1, e: 1, g: 1, skip: 1, }, // lea { opcode: 0x8E, e: 1, g: 1, skip: 1, }, - { opcode: 0x8F, os: 1, e: 1, g: 1, }, + { opcode: 0x8F, os: 1, e: 1, fixed_g: 0, }, { opcode: 0x90, }, { opcode: 0x91, os: 1, }, @@ -152,8 +152,8 @@ const encodings = [ { opcode: 0xC4, os: 1, e: 1, g: 1, skip: 1, }, { opcode: 0xC5, os: 1, e: 1, g: 1, skip: 1, }, - { opcode: 0xC6, e: 1, g: 1, imm: 1, }, - { opcode: 0xC7, os: 1, e: 1, g: 1, imm: 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, imm24: 1, skip: 1, }, // enter { opcode: 0xC9, os: 1, skip: 1, }, @@ -690,17 +690,25 @@ function gen_instruction_body(encoding, variant) let opcode = encoding[0].opcode & 0xFF; let opcode_hex = hex_byte(opcode); - //if(opcode === 0 || opcode === 1 || opcode === 2 || opcode === 3) - //{ - // return [ - // `int32_t modrm_byte = read_imm8();`, - // `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.length > 1) + if(encoding[0].fixed_g === undefined && encoding[0].e) + { + let prefix_call = []; + + if(opcode === 0x8D) + { + // special case + 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); @@ -710,15 +718,27 @@ function gen_instruction_body(encoding, variant) } return [ - "read_modrm_byte();", + "int32_t modrm_byte = read_imm8();", { type: "switch", - condition: "*modrm_byte >> 3 & 7", + condition: "modrm_byte >> 3 & 7", body: cases.map(case_ => { + let prefix_call = []; + + if(opcode === 0x8F) + { + // special case + prefix_call = [`if(modrm_byte < 0xC0) { instr${suffix}_${opcode_hex}_${case_.fixed_g}_mem_pre(); };`]; + } + return { type: "case", cases: [case_.fixed_g], - body: [`instr${suffix}_${opcode_hex}_${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([ { From 9fa0d18ee8caf17c9c390be470ad4b0b13d03b60 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 18 Jul 2017 15:20:36 -0500 Subject: [PATCH 0047/2137] Disable initial state memory optimisation (breaks with wasm) --- src/browser/starter.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 2851a932..5a5e0943 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -589,11 +589,11 @@ function V86Starter(options) function done() { - if(settings.initial_state) - { - // avoid large allocation now, memory will be restored later anyway - settings.memory_size = 0; - } + //if(settings.initial_state) + //{ + // // avoid large allocation now, memory will be restored later anyway + // settings.memory_size = 0; + //} this.bus.send("cpu-init", settings); From 9b463626fe858f6dc3559270df2dd5777b295cd7 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Jul 2017 09:52:26 +0200 Subject: [PATCH 0048/2137] Do side-effects after get_seg --- src/native/instructions.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/native/instructions.c b/src/native/instructions.c index 81635fea..441b71cf 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -1047,8 +1047,9 @@ DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_C1_7, sar32(___, read_op8() & 31)) static void instr16_C2() { // retn int32_t imm16 = read_op16(); + int32_t cs = get_seg(CS); - instruction_pointer[0] = get_seg(CS) + pop16(); + instruction_pointer[0] = cs + pop16(); dbg_assert(is_asize_32() || get_real_eip() < 0x10000); adjust_stack_reg(imm16); diverged(); @@ -1056,23 +1057,26 @@ static void instr16_C2() { static void instr32_C2() { // retn int32_t imm16 = read_op16(); + int32_t cs = get_seg(CS); int32_t ip = pop32s(); dbg_assert(is_asize_32() || ip < 0x10000); - instruction_pointer[0] = get_seg(CS) + ip; + instruction_pointer[0] = cs + ip; adjust_stack_reg(imm16); diverged(); } static void instr16_C3() { // retn - instruction_pointer[0] = get_seg(CS) + pop16(); + int32_t cs = get_seg(CS); + instruction_pointer[0] = cs + pop16(); diverged(); } static void instr32_C3() { // retn + int32_t cs = get_seg(CS); int32_t ip = pop32s(); dbg_assert(is_asize_32() || ip < 0x10000); - instruction_pointer[0] = get_seg(CS) + ip; + instruction_pointer[0] = cs + ip; diverged(); } @@ -1567,8 +1571,9 @@ DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_FF_1, dec16(___)) static void instr16_FF_2_helper(int32_t data) { // call near + int32_t cs = get_seg(CS); push16(get_real_eip()); - instruction_pointer[0] = get_seg(CS) + data; + instruction_pointer[0] = cs + data; dbg_assert(is_asize_32() || get_real_eip() < 0x10000); diverged(); } @@ -1618,9 +1623,10 @@ DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_FF_1, dec32(___)) static void instr32_FF_2_helper(int32_t data) { // call near + int32_t cs = get_seg(CS); push32(get_real_eip()); dbg_assert(is_asize_32() || data < 0x10000); - instruction_pointer[0] = get_seg(CS) + data; + instruction_pointer[0] = cs + data; diverged(); } DEFINE_MODRM_INSTR1_READ32(instr32_FF_2, instr32_FF_2_helper(___)) From 7c9cdc75d3d39984b5016126e0ddf49380e0e959 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Jul 2017 11:21:28 +0200 Subject: [PATCH 0049/2137] Multiboot loader: Allow bss section, add sanity check against memory size --- src/cpu.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index ded5739b..f2ef8594 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -904,9 +904,13 @@ CPU.prototype.load_multiboot = function(buffer) // virtual and physical address must be equal dbg_assert(program.paddr === program.vaddr); dbg_assert(program.filesz <= program.memsz); + dbg_assert(program.paddr + program.memsz < this.memory_size[0]); - let blob = new Uint8Array(buffer, program.offset, program.filesz); - this.write_blob(blob, program.paddr); + if(program.filesz) // offset mighty be outside of buffer if filesz is 0 + { + let blob = new Uint8Array(buffer, program.offset, program.filesz); + this.write_blob(blob, program.paddr); + } } else if(program.type === 4 || program.type === 0x6474e550 || From d6f856207cbfe3c30fb6bc38d43c2118f52985a5 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Jul 2017 11:51:49 +0200 Subject: [PATCH 0050/2137] Protect against call from C --- src/lib.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib.js b/src/lib.js index c32e123d..3120a8fd 100644 --- a/src/lib.js +++ b/src/lib.js @@ -161,6 +161,7 @@ SyncBuffer.prototype.get_buffer = function(fn) */ v86util.int_log2 = function(x) { + x >>>= 0; dbg_assert(x > 0); // http://jsperf.com/integer-log2/6 From 4332444dfe30fa9e0a287ea5f20ed9470d351bfd Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Jul 2017 12:31:49 +0200 Subject: [PATCH 0051/2137] Use same esp in orace and test --- tests/nasm/Makefile | 4 ++-- tests/nasm/create_tests.js | 46 ++++++++++++++++++++------------------ tests/nasm/gdbauto | 20 +++++++++++++---- tests/nasm/header.inc | 9 ++++++-- tests/nasm/run.js | 5 +++-- 5 files changed, 52 insertions(+), 32 deletions(-) diff --git a/tests/nasm/Makefile b/tests/nasm/Makefile index 1f5bf0ea..c9e2ed99 100644 --- a/tests/nasm/Makefile +++ b/tests/nasm/Makefile @@ -12,7 +12,7 @@ all: $(source_files) $(host_executables) $(v86_executables) $(host_fixtures) # To run / debug locally build/%.bin: build/%.asm $(inc_files) - nasm -felf32 -o $@.o $<; ld -g $@.o -m elf_i386 -o $@ + nasm -felf32 -o $@.o $<; ld -g $@.o -m elf_i386 --section-start=.bss=0x100000 -o $@ # To generate a fixture using gdb build/%.fixture: build/%.bin @@ -20,7 +20,7 @@ build/%.fixture: build/%.bin # To use as a multiboot kernel image for v86 build/%.img: build/%.asm $(inc_files) - nasm -felf32 -o $@.o $<; ld -g $@.o -m elf_i386 --section-start=.text=0x8000 -o $@ + nasm -felf32 -o $@.o $<; ld -g $@.o -m elf_i386 --section-start=.bss=0x100000 --section-start=.text=0x8000 -o $@ build/%.asm: %.asm mkdir -p build; cp $< $@ diff --git a/tests/nasm/create_tests.js b/tests/nasm/create_tests.js index 2de3645d..4e1396c2 100755 --- a/tests/nasm/create_tests.js +++ b/tests/nasm/create_tests.js @@ -6,10 +6,10 @@ // TODO // - lea (and all modrm/sib addressing modes) // - fix style (single quote, brace position) -// - memory tests // - multiple random tests // - 16 bit // - describe which registers are written and read +// - string instructions (initialise ds, esi, es, edi) const fs = require("fs"); @@ -17,6 +17,8 @@ const zf = 1 << 6; const of = 1 << 11; const cf = 1 << 0; const af = 1 << 4; +const pf = 1 << 2; +const sf = 1 << 7; // os: the instruction behaves differently depending on the operand size @@ -35,15 +37,15 @@ const encodings = [ { opcode: 0x2E, prefix: 1, }, { opcode: 0x2F, mask_flags: of, }, { opcode: 0x36, prefix: 1, }, - { opcode: 0x37, skip: 1, }, + { opcode: 0x37, mask_flags: of | sf | pf | zf, }, { opcode: 0x3E, prefix: 1, }, - { opcode: 0x3F, skip: 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, skip: 1, }, // inc esp + { opcode: 0x44, os: 1, }, { opcode: 0x45, os: 1, }, { opcode: 0x46, os: 1, }, { opcode: 0x47, os: 1, }, @@ -52,7 +54,7 @@ const encodings = [ { opcode: 0x49, os: 1, }, { opcode: 0x4A, os: 1, }, { opcode: 0x4B, os: 1, }, - { opcode: 0x4C, os: 1, skip: 1, }, // dec esp + { opcode: 0x4C, os: 1, }, { opcode: 0x4D, os: 1, }, { opcode: 0x4E, os: 1, }, { opcode: 0x4F, os: 1, }, @@ -61,7 +63,7 @@ const encodings = [ { opcode: 0x51, os: 1, }, { opcode: 0x52, os: 1, }, { opcode: 0x53, os: 1, }, - { opcode: 0x54, os: 1, skip: 1, }, // push esp + { opcode: 0x54, os: 1, }, { opcode: 0x55, os: 1, }, { opcode: 0x56, os: 1, }, { opcode: 0x57, os: 1, }, @@ -70,12 +72,12 @@ const encodings = [ { opcode: 0x59, os: 1, }, { opcode: 0x5A, os: 1, }, { opcode: 0x5B, os: 1, }, - { opcode: 0x5C, os: 1, skip: 1, }, // pop esp + { opcode: 0x5C, os: 1, }, { opcode: 0x5D, os: 1, }, { opcode: 0x5E, os: 1, }, { opcode: 0x5F, os: 1, }, - { opcode: 0x60, os: 1, skip: 1, }, + { opcode: 0x60, os: 1, }, { opcode: 0x61, os: 1, }, { opcode: 0x62, e: 1, g: 1, skip: 1, }, { opcode: 0x63, e: 1, g: 1, }, @@ -104,7 +106,7 @@ const encodings = [ { 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, skip: 1, }, // lea + { 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, }, @@ -112,21 +114,21 @@ const encodings = [ { opcode: 0x91, os: 1, }, { opcode: 0x92, os: 1, }, { opcode: 0x93, os: 1, }, - { opcode: 0x94, os: 1, skip: 1, }, // xchg eax, esp + { 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, imm3248: 1, skip: 1, }, + { opcode: 0x9A, os: 1, imm1632: 1, skip: 1, }, { opcode: 0x9B, skip: 1, }, - { opcode: 0x9C, os: 1, skip: 1, }, - { opcode: 0x9D, os: 1, skip: 1, }, + { opcode: 0x9C, os: 1, }, + { opcode: 0x9D, os: 1, skip: 1, }, // popf { opcode: 0x9E, }, { opcode: 0x9F, }, - { opcode: 0xA0, immaddr: 1, skip: 1, }, + { opcode: 0xA0, immaddr: 1, skip: 1, }, // skip: requires code generation for immediate pointer { opcode: 0xA1, os: 1, immaddr: 1, skip: 1, }, { opcode: 0xA2, immaddr: 1, skip: 1, }, { opcode: 0xA3, os: 1, immaddr: 1, skip: 1, }, @@ -164,7 +166,7 @@ const encodings = [ { opcode: 0xCE, skip: 1, }, { opcode: 0xCF, os: 1, skip: 1, }, - { opcode: 0xD4, imm8: 1, }, + { opcode: 0xD4, imm8: 1, }, // aam, may trigger #de { opcode: 0xD5, imm8: 1, mask_flags: of | cf | af, }, { opcode: 0xD6, }, { opcode: 0xD7, skip: 1, }, @@ -188,9 +190,9 @@ const encodings = [ { opcode: 0xE6, imm8: 1, skip: 1, }, { opcode: 0xE7, os: 1, imm8: 1, skip: 1, }, - { opcode: 0xE8, os: 1, imm: 1, skip: 1, }, - { opcode: 0xE9, os: 1, imm: 1, skip: 1, }, - { opcode: 0xEA, os: 1, imm: 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, }, @@ -374,7 +376,7 @@ const encodings = [ { opcode: 0x0FC9, }, { opcode: 0x0FCA, }, { opcode: 0x0FCB, }, - { opcode: 0x0FCC, skip: 1, }, // bswap esp + { opcode: 0x0FCC, }, { opcode: 0x0FCD, }, { opcode: 0x0FCE, }, { opcode: 0x0FCF, }, @@ -1049,7 +1051,7 @@ function create_nasm(op, config) } } - if(op.imm || op.imm8 || op.imm1632 || op.immaddr) + if(op.imm || op.imm8 || op.imm16 || op.imm1632 || op.immaddr) { if(op.imm8 || (op.imm && size === 8)) { @@ -1064,9 +1066,9 @@ function create_nasm(op, config) } else { - console.assert(op.imm1632 || (op.imm && (size === 16 || size === 32))); + console.assert(op.imm1632 || op.imm16 || (op.imm && (size === 16 || size === 32))); - if(size === 16) + if(size === 16 || op.imm16) { codes.push("dw 34cdh"); } diff --git a/tests/nasm/gdbauto b/tests/nasm/gdbauto index d7fec0e6..352bcb3b 100644 --- a/tests/nasm/gdbauto +++ b/tests/nasm/gdbauto @@ -67,10 +67,22 @@ printf " %d,\n", $xmm7.v4_int32[2] printf " %d,\n", $xmm7.v4_int32[3] printf " \n" -printf " %d,\n", *(int*)($esp+0) -printf " %d,\n", *(int*)($esp+4) -printf " %d,\n", *(int*)($esp+8) -printf " %d,\n", *(int*)($esp+12) +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 " \n" printf " %d\n", $eflags diff --git a/tests/nasm/header.inc b/tests/nasm/header.inc index ea8aa302..afedb1cc 100644 --- a/tests/nasm/header.inc +++ b/tests/nasm/header.inc @@ -9,6 +9,11 @@ align 4 dd FLAGS dd CHECKSUM +section .bss + resb 128*1024 + +stack_top: + section .text _start: @@ -18,14 +23,14 @@ main: xor edx, edx xor ebx, ebx ; xor esp, esp + mov esp, stack_top xor ebp, ebp xor esi, esi xor edi, edi ; make space for memory operations %rep 8 - sub esp, 4 - mov dword [esp], 0 + push 0 %endrep push 0 diff --git a/tests/nasm/run.js b/tests/nasm/run.js index 7eae4e22..a3cb02b3 100755 --- a/tests/nasm/run.js +++ b/tests/nasm/run.js @@ -207,7 +207,7 @@ else { const evaluated_mmxs = cpu.reg_mmxs; const evaluated_xmms = cpu.reg_xmm32s; const esp = cpu.reg32s[4]; - const evaluated_memory = new Int32Array(cpu.mem8.slice(esp, esp + 16).buffer); + const evaluated_memory = new Int32Array(cpu.mem8.slice(0x120000 - 16 * 4, 0x120000).buffer); let individual_failures = []; if(test.exception) @@ -215,13 +215,14 @@ else { throw "TODO: Handle exceptions"; } + console.assert(test.fixture.array); if(test.fixture.array) { let offset = 0; const expected_reg32s = test.fixture.array.slice(offset, offset += 8); const expected_mmx_registers = test.fixture.array.slice(offset, offset += 16); const expected_xmm_registers = test.fixture.array.slice(offset, offset += 32); - const expected_memory = test.fixture.array.slice(offset, offset += 4); + const expected_memory = test.fixture.array.slice(offset, offset += 16); const expected_eflags = test.fixture.array[offset] & MASK_ARITH; for (let i = 0; i < cpu.reg32s.length; i++) { From c414ac5c1fe024eda2eb3738f32a27e22273c3f5 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Jul 2017 13:53:37 +0200 Subject: [PATCH 0052/2137] Improve enter instructios --- src/misc_instr.js | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/misc_instr.js b/src/misc_instr.js index 3b255a35..83d8918f 100644 --- a/src/misc_instr.js +++ b/src/misc_instr.js @@ -420,21 +420,27 @@ CPU.prototype.enter16 = function(size, nesting_level) nesting_level &= 31; if(nesting_level) dbg_log("enter16 stack=" + (this.stack_size_32[0] ? 32 : 16) + " size=" + size + " nest=" + nesting_level, LOG_CPU); - this.push16(this.reg16[reg_bp]); - var frame_temp = this.reg16[reg_sp]; + + var ss_mask = this.stack_size_32[0] ? -1 : 0xFFFF; + var ss = this.get_seg(reg_ss); + var frame_temp = this.reg32s[reg_esp] - 2; if(nesting_level > 0) { - var tmp_ebp = this.reg16[reg_ebp]; + var tmp_ebp = this.reg32s[reg_ebp]; for(var i = 1; i < nesting_level; i++) { tmp_ebp -= 2; - this.push16(this.safe_read16(this.get_seg(reg_ss) + tmp_ebp | 0)); + this.push16(this.safe_read16(ss + (tmp_ebp & ss_mask) | 0)); } this.push16(frame_temp); } + + // check if write to final stack pointer would case a page fault + this.writable_or_pagefault(ss + (frame_temp - size & ss_mask), 2); + this.safe_write16(ss + (frame_temp & ss_mask) | 0, this.reg16[reg_bp]); this.reg16[reg_bp] = frame_temp; - this.adjust_stack_reg(-size); + this.adjust_stack_reg(-size - 2); }; CPU.prototype.enter32 = function(size, nesting_level) @@ -442,8 +448,10 @@ CPU.prototype.enter32 = function(size, nesting_level) nesting_level &= 31; if(nesting_level) dbg_log("enter32 stack=" + (this.stack_size_32[0] ? 32 : 16) + " size=" + size + " nest=" + nesting_level, LOG_CPU); - this.push32(this.reg32s[reg_ebp]); - var frame_temp = this.reg32s[reg_esp]; + + var ss_mask = this.stack_size_32[0] ? -1 : 0xFFFF; + var ss = this.get_seg(reg_ss); + var frame_temp = this.reg32s[reg_esp] - 4; if(nesting_level > 0) { @@ -451,12 +459,16 @@ CPU.prototype.enter32 = function(size, nesting_level) for(var i = 1; i < nesting_level; i++) { tmp_ebp -= 4; - this.push32(this.safe_read32s(this.get_seg(reg_ss) + tmp_ebp | 0)); + this.push32(this.safe_read32s(ss + (tmp_ebp & ss_mask) | 0)); } this.push32(frame_temp); } + + // check if write to final stack pointer would case a page fault + this.writable_or_pagefault(ss + (frame_temp - size & ss_mask), 4); + this.safe_write32(ss + (frame_temp & ss_mask) | 0, this.reg32s[reg_ebp]); this.reg32s[reg_ebp] = frame_temp; - this.adjust_stack_reg(-size); + this.adjust_stack_reg(-size - 4); }; CPU.prototype.bswap = function(reg) From c004dac4d55994945d526b805f3008a39800f96a Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Jul 2017 13:56:42 +0200 Subject: [PATCH 0053/2137] Generate immediate byte reads for callf/jmpf/enter --- src/native/instructions.c | 36 +++++++------------ tests/nasm/create_tests.js | 74 ++++++++++++++++++++++++++++++++++---- 2 files changed, 81 insertions(+), 29 deletions(-) diff --git a/src/native/instructions.c b/src/native/instructions.c index 441b71cf..1c45035b 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -816,19 +816,13 @@ static void instr32_98() { /* cwde */ reg32s[EAX] = reg16s[AX]; } static void instr16_99() { /* cwd */ reg16[DX] = reg16s[AX] >> 15; } static void instr32_99() { /* cdq */ reg32s[EDX] = reg32s[EAX] >> 31; } -static void instr16_9A() { +static void instr16_9A(int32_t new_ip, int32_t new_cs) { // callf - int32_t new_ip = read_op16(); - int32_t new_cs = read_disp16(); - far_jump(new_ip, new_cs, true); dbg_assert(is_asize_32() || get_real_eip() < 0x10000); diverged(); } -static void instr32_9A() { - int32_t new_ip = read_op32s(); - int32_t new_cs = read_disp16(); - +static void instr32_9A(int32_t new_ip, int32_t new_cs) { if(!*protected_mode || vm86_mode()) { if(new_ip & 0xFFFF0000) @@ -1104,8 +1098,8 @@ 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 instr16_C8() { enter16(read_op16(), read_disp8()); } -static void instr32_C8() { enter32(read_op16(), read_disp8()); } +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); } static void instr16_C9() { // leave int32_t old_vbp = *stack_size_32 ? reg32s[EBP] : reg16[BP]; @@ -1358,18 +1352,14 @@ static void instr32_E9() { dbg_assert(is_asize_32() || get_real_eip() < 0x10000); diverged(); } -static void instr16_EA() { +static void instr16_EA(int32_t new_ip, int32_t cs) { // jmpf - int32_t ip = read_op16(); - int32_t cs = read_disp16(); - far_jump(ip, cs, false); + far_jump(new_ip, cs, false); dbg_assert(is_asize_32() || get_real_eip() < 0x10000); diverged(); } -static void instr32_EA() { +static void instr32_EA(int32_t new_ip, int32_t cs) { // jmpf - int32_t new_ip = read_op32s(); - int32_t cs = read_disp16(); far_jump(new_ip, cs, false); dbg_assert(is_asize_32() || get_real_eip() < 0x10000); diverged(); @@ -3589,12 +3579,12 @@ case 0x99|0x100: break; case 0x9A: { - instr16_9A(); + instr16_9A(read_imm16(), read_imm16()); } break; case 0x9A|0x100: { - instr32_9A(); + instr32_9A(read_imm32s(), read_imm16()); } break; case 0x9B: @@ -4196,12 +4186,12 @@ case 0xC7|0x100: break; case 0xC8: { - instr16_C8(); + instr16_C8(read_imm16(), read_imm8()); } break; case 0xC8|0x100: { - instr32_C8(); + instr32_C8(read_imm16(), read_imm8()); } break; case 0xC9: @@ -4834,12 +4824,12 @@ case 0xE9|0x100: break; case 0xEA: { - instr16_EA(); + instr16_EA(read_imm16(), read_imm16()); } break; case 0xEA|0x100: { - instr32_EA(); + instr32_EA(read_imm32s(), read_imm16()); } break; case 0xEB: diff --git a/tests/nasm/create_tests.js b/tests/nasm/create_tests.js index 4e1396c2..6bca588e 100755 --- a/tests/nasm/create_tests.js +++ b/tests/nasm/create_tests.js @@ -22,6 +22,9 @@ const sf = 1 << 7; // 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, }, @@ -157,7 +160,7 @@ const encodings = [ { opcode: 0xC6, e: 1, fixed_g: 0, imm: 1, }, { opcode: 0xC7, os: 1, e: 1, fixed_g: 0, imm: 1, }, - { opcode: 0xC8, os: 1, imm24: 1, skip: 1, }, // enter + { opcode: 0xC8, os: 1, imm16: 1, }, // enter { opcode: 0xC9, os: 1, skip: 1, }, { opcode: 0xCA, os: 1, imm16: 1, skip: 1, }, { opcode: 0xCB, os: 1, skip: 1, }, @@ -685,9 +688,47 @@ function print_syntax_tree(statements) return code; } -function gen_instruction_body(encoding, variant) +function gen_read_imm_call(op, size_variant) { - let suffix = encoding[0].os ? `${variant}` : ""; + let size = (op.os || op.opcode % 2 === 1) ? size_variant : 8; + + if(op.imm || op.imm8 || op.imm16 || op.imm1632 || op.immaddr) + { + 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))); + + if(size === 16 || op.imm16) + { + return "read_imm16()"; + } + else + { + return "read_imm32s()"; + } + } + } + } + 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); @@ -698,7 +739,7 @@ function gen_instruction_body(encoding, variant) if(opcode === 0x8D) { - // special case + // special case: requires call before modrm_resolve prefix_call = [`if(modrm_byte < 0xC0) { instr${suffix}_${opcode_hex}_mem_pre(); };`]; } @@ -729,7 +770,7 @@ function gen_instruction_body(encoding, variant) if(opcode === 0x8F) { - // special case + // special case: requires call before modrm_resolve prefix_call = [`if(modrm_byte < 0xC0) { instr${suffix}_${opcode_hex}_${case_.fixed_g}_mem_pre(); };`]; } @@ -753,7 +794,22 @@ function gen_instruction_body(encoding, variant) } else { - return [`instr${suffix}_${opcode_hex}();`]; + 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}();`]; + } } } @@ -1051,6 +1107,12 @@ function create_nasm(op, config) } } + if(op.opcode === 0xC8) // special case: enter + { + codes.push("dw 8h"); + codes.push("db 0h"); + } + else if(op.imm || op.imm8 || op.imm16 || op.imm1632 || op.immaddr) { if(op.imm8 || (op.imm && size === 8)) From 243a452850aba3e7c384b6a9be262ad606555ab6 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Jul 2017 14:28:08 +0200 Subject: [PATCH 0054/2137] Fix sahf --- src/native/instructions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/instructions.c b/src/native/instructions.c index 1c45035b..e4e2683d 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -924,7 +924,7 @@ static void instr_9E() { // sahf flags[0] = (flags[0] & ~0xFF) | reg8[AH]; flags[0] = (flags[0] & FLAGS_MASK) | FLAGS_DEFAULT; - flags_changed[0] = 0; + flags_changed[0] &= ~0xFF; } static void instr_9F() { // lahf From 5ad6e1e67adb17d782f0d10ada210b9d84fdb2e2 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Jul 2017 14:51:06 +0200 Subject: [PATCH 0055/2137] Nasm tests: Test for lazy flags, fix flags mask for several instructions --- tests/nasm/create_tests.js | 55 +++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/tests/nasm/create_tests.js b/tests/nasm/create_tests.js index 6bca588e..8b59e416 100755 --- a/tests/nasm/create_tests.js +++ b/tests/nasm/create_tests.js @@ -90,9 +90,9 @@ const encodings = [ { opcode: 0x67, prefix: 1, }, { opcode: 0x68, os: 1, imm1632: 1, }, - { opcode: 0x69, os: 1, e: 1, g: 1, imm: 1, mask_flags: 0, }, // zf? + { 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: 0, }, // zf? + { opcode: 0x6B, os: 1, e: 1, g: 1, imm8: 1, mask_flags: af, }, // zf? { opcode: 0x6C, skip: 1, }, { opcode: 0x6D, os: 1, skip: 1, }, @@ -214,8 +214,8 @@ const encodings = [ { opcode: 0xF6, fixed_g: 1, imm: 1, }, { opcode: 0xF6, fixed_g: 2, }, { opcode: 0xF6, fixed_g: 3, }, - { opcode: 0xF6, fixed_g: 4, mask_flags: zf, }, - { opcode: 0xF6, fixed_g: 5, mask_flags: zf, }, + { 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, }, @@ -223,8 +223,8 @@ const encodings = [ { 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, }, - { opcode: 0xF7, os: 1, fixed_g: 5, mask_flags: zf, }, + { 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, }, @@ -343,18 +343,18 @@ const encodings = [ { 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, }, // bsf - { opcode: 0x0FBD, os: 1, e: 1, g: 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: of, }, // shld - { opcode: 0x0FA5, os: 1, e: 1, g: 1, mask_flags: of, }, - { opcode: 0x0FAC, os: 1, e: 1, g: 1, imm8: 1, mask_flags: of, }, - { opcode: 0x0FAD, os: 1, e: 1, g: 1, mask_flags: of, }, + { 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, g: 1, skip: 1, }, - { opcode: 0x0FAF, os: 1, e: 1, g: 1, mask_flags: zf }, // imul + { 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 }, @@ -608,12 +608,13 @@ for(var i = 0; i < 8; i++) { opcode: 0xB8 | i, os: 1, imm1632: 1, skip: 1, }, // note: overflow flag only undefined if shift is > 1 - { opcode: 0xC0, e: 1, fixed_g: i, imm8: 1, mask_flags: of, }, - { opcode: 0xC1, os: 1, e: 1, fixed_g: i, imm8: 1, mask_flags: of, }, - { opcode: 0xD0, e: 1, fixed_g: i, mask_flags: of, }, - { opcode: 0xD1, os: 1, e: 1, fixed_g: i, mask_flags: of, }, - { opcode: 0xD2, e: 1, fixed_g: i, mask_flags: of, }, - { opcode: 0xD3, os: 1, e: 1, fixed_g: i, mask_flags: of, }, + // 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, }, ]); } @@ -1054,6 +1055,22 @@ function create_nasm(op, config) codes.push("push dword " + (random_int32() & ~(1 << 8 | 1 << 9))); codes.push("popf"); + if(true) + { + // generate random flags using arithmatic instruction + // not well-distributed, but can trigger bugs in lazy flag calculation + if(true) + { + // rarely sets zero flag, other flags mostly well-distributed + codes.push("add al, ah"); + } + else + { + // always sets zero flag + codes.push("sub al, al"); + } + } + if(size === 16) { codes.push("db 66h ; 16 bit"); From 3cd91a5064c905efc807eb87ec726e8c2e182eb9 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Jul 2017 14:51:45 +0200 Subject: [PATCH 0056/2137] Temporarily disable QEMU tests that don't compiler on newer GCC --- tests/qemu/test-i386.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/qemu/test-i386.c b/tests/qemu/test-i386.c index b15f0fac..f304426b 100644 --- a/tests/qemu/test-i386.c +++ b/tests/qemu/test-i386.c @@ -1541,6 +1541,8 @@ void test_code16(void) modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ /* call the first function */ + // XXX: Temporarily disabled: Fails to compile on newer gcc, wait for upstream fix +#if 0 asm volatile ("lcall %1, %2" : "=a" (res) : "i" (MK_SEL(1)), "i" (&code16_func1): "memory", "cc"); @@ -1553,6 +1555,7 @@ void test_code16(void) : "=a" (res) : "i" (MK_SEL(1)), "i" (&code16_func3): "memory", "cc"); printf("func3() = 0x%08x\n", res); +#endif } #endif @@ -1628,6 +1631,9 @@ void test_misc(void) } #endif #else + + // XXX: Temporarily disabled: Fails to compile on newer gcc, wait for upstream fix +#if 0 asm volatile ("push %%cs ; call %1" : "=a" (res) : "m" (func_lret): "memory", "cc"); @@ -1638,6 +1644,7 @@ void test_misc(void) : "m" (func_iret): "memory", "cc"); printf("func_iret=" FMTLX "\n", res); #endif +#endif #if defined(__x86_64__) /* specific popl test */ From 649099851cb3882f1681844afa5487d9405e866c Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Jul 2017 15:00:15 +0200 Subject: [PATCH 0057/2137] Host bridge: Mark bios mapped in low memory --- src/pci.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/pci.js b/src/pci.js index 2acbd3f8..b67ca9df 100644 --- a/src/pci.js +++ b/src/pci.js @@ -145,14 +145,22 @@ function PCI(cpu) // pci_bars: [], //}; + // This needs to be set in order for seabios to not execute code outside of + // mapped memory. While we map the BIOS into high memory, we don't allow + // executing code there, which enables optimisations in read_imm8. + // See [make_bios_writable_intel] in src/fw/shadow.c in seabios for details + const PAM0 = 0x10; + var host_bridge = { pci_id: 0, pci_space: [ // 00:00.0 Host bridge: Intel Corporation 440FX - 82441FX PMC [Natoma] (rev 02) - 0x86, 0x80, 0x37, 0x12, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x86, 0x80, 0x37, 0x12, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, PAM0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], pci_bars: [], name: "82441FX PMC", From 08a51f7b0c3347f821634df13de2fcbc237e2d28 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Jul 2017 15:10:00 +0200 Subject: [PATCH 0058/2137] Add libv86-debug.js target --- Makefile | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index eeefb8f1..88cea35c 100644 --- a/Makefile +++ b/Makefile @@ -121,15 +121,29 @@ build/libv86.js: $(CLOSURE) src/*.js lib/*.js src/browser/*.js --js $(CORE_FILES)\ --js $(BROWSER_FILES)\ --js $(LIB_FILES) - ls -lh build/libv86.js +build/libv86-debug.js: $(CLOSURE) src/*.js lib/*.js src/browser/*.js + mkdir -p build + java -jar $(CLOSURE) \ + --js_output_file build/libv86-debug.js\ + --define=DEBUG=true\ + $(CLOSURE_FLAGS)\ + $(CLOSURE_READABLE)\ + --compilation_level SIMPLE\ + $(TRANSPILE_ES6_FLAGS)\ + --output_wrapper ';(function(){%output%}).call(this);'\ + --js $(CORE_FILES)\ + --js $(BROWSER_FILES)\ + --js $(LIB_FILES) + build/v86.wasm: src/native/*.c src/native/*.h mkdir -p build -ls -lh build/v86.wasm # --llvm-opts 3 # -Wno-extra-semi - # EMCC_WASM_BACKEND=1 + # EMCC_DEBUG=1 EMCC_WASM_BACKEND=1 + # -fno-inline emcc src/native/all.c \ -Wall -Wpedantic -Wextra \ -DDEBUG=false \ From 15899c843b2e5f6671e8feae35cb7d0c9cab8144 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Jul 2017 15:11:31 +0200 Subject: [PATCH 0059/2137] Remove warnings, code is tested --- src/native/instructions_0f.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 39de15b5..fbdcdda3 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1410,7 +1410,6 @@ static void instr32_0FB6() { read_modrm_byte(); static void instr16_0FB7() { read_modrm_byte(); // movzx - dbg_assert_message(false, "Possibly invalid encoding"); int32_t data = read_e16(); write_g16(data); } @@ -1558,7 +1557,6 @@ static void instr32_0FBE() { read_modrm_byte(); static void instr16_0FBF() { read_modrm_byte(); // movsx - dbg_assert_message(false, "Possibly invalid encoding"); int32_t data = read_e16(); write_g16(data); } From d6ee01dc7a0e3a4cf551e30a302871647cca4c69 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Jul 2017 15:56:26 +0200 Subject: [PATCH 0060/2137] Optimise read_imm8 by not checking for mapped range --- src/native/cpu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/native/cpu.c b/src/native/cpu.c index acde925e..be0f91c2 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -29,6 +29,8 @@ void write32(uint32_t, int32_t); void virt_boundary_write16(int32_t, int32_t, int32_t); void virt_boundary_write32(int32_t, int32_t, int32_t); +bool in_mapped_range(uint32_t); + void trigger_gp(int32_t); void trigger_ud(); void trigger_nm(); @@ -104,7 +106,8 @@ int32_t read_imm8() *last_virt_eip = eip & ~0xFFF; } - int32_t data8 = read8(*eip_phys ^ eip); + assert(!in_mapped_range(*eip_phys ^ eip)); + int32_t data8 = mem8[*eip_phys ^ eip]; *instruction_pointer = eip + 1; return data8; From 3079fe8f8db9eac529a76c2f0ec1b445316079d4 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Jul 2017 15:56:53 +0200 Subject: [PATCH 0061/2137] Disable Windows 98 test --- tests/full/run.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/full/run.js b/tests/full/run.js index 21410c4c..e404228a 100755 --- a/tests/full/run.js +++ b/tests/full/run.js @@ -126,15 +126,15 @@ if(cluster.isMaster) }, ], }, - { - name: "Windows 98", - hda: root_path + "/images/windows98.img", - timeout: 60, - expect_graphical_mode: true, - expect_graphical_size: [800, 600], - expect_mouse_registered: true, - skip_if_disk_image_missing: true, - }, + //{ + // name: "Windows 98", + // hda: root_path + "/images/windows98.img", + // timeout: 60, + // expect_graphical_mode: true, + // expect_graphical_size: [800, 600], + // expect_mouse_registered: true, + // skip_if_disk_image_missing: true, + //}, //{ // name: "Oberon", // hda: root_path + "/images/oberon.dsk", From db376f3b637c3e7c7b5cbcb24880b603e796eaf4 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Jul 2017 16:09:01 +0200 Subject: [PATCH 0062/2137] Add tests for fixed address in instructions --- tests/nasm/create_tests.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/nasm/create_tests.js b/tests/nasm/create_tests.js index 8b59e416..7e2cbc89 100755 --- a/tests/nasm/create_tests.js +++ b/tests/nasm/create_tests.js @@ -131,10 +131,10 @@ const encodings = [ { opcode: 0x9E, }, { opcode: 0x9F, }, - { opcode: 0xA0, immaddr: 1, skip: 1, }, // skip: requires code generation for immediate pointer - { opcode: 0xA1, os: 1, immaddr: 1, skip: 1, }, - { opcode: 0xA2, immaddr: 1, skip: 1, }, - { opcode: 0xA3, os: 1, immaddr: 1, skip: 1, }, + { opcode: 0xA0, immaddr: 1, }, + { opcode: 0xA1, os: 1, immaddr: 1, }, + { opcode: 0xA2, immaddr: 1, }, + { opcode: 0xA3, os: 1, immaddr: 1, }, { opcode: 0xA4, skip: 1, }, { opcode: 0xA5, os: 1, skip: 1, }, @@ -1141,7 +1141,8 @@ function create_nasm(op, config) if(op.immaddr) { // immaddr: depends on address size - codes.push("dd 1234abcdh"); + // generate valid pointer into bss section + codes.push("dd (120000h-16)"); } else { From 0b0d5394efbfdf02da8a1cd5e651d8e1c289ced5 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Jul 2017 16:22:05 +0200 Subject: [PATCH 0063/2137] Check fixtures before starting to run tests --- tests/nasm/run.js | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/tests/nasm/run.js b/tests/nasm/run.js index a3cb02b3..7e1959dc 100755 --- a/tests/nasm/run.js +++ b/tests/nasm/run.js @@ -95,18 +95,9 @@ if (cluster.isMaster) { function send_work_to_worker(worker, message) { - if(current_test < files.length) { - let name = files[current_test]; - let fixture_name = name + ".fixture"; - let img_name = name + ".img"; - let fixture_text = fs.readFileSync(TEST_DIR + fixture_name); - let fixture = extract_json(name, fixture_text); - - worker.send({ - img_name: img_name, - fixture: fixture, - }); - + if(current_test < tests.length) { + const test = tests[current_test]; + worker.send(test); current_test++; } else { @@ -127,9 +118,21 @@ if (cluster.isMaster) { return name.slice(0, -4); }); + const tests = files.map(name => { + let fixture_name = name + ".fixture"; + let img_name = name + ".img"; + let fixture_text = fs.readFileSync(TEST_DIR + fixture_name); + let fixture = extract_json(name, fixture_text); + + return { + img_name: img_name, + fixture: fixture, + }; + }); + const nr_of_cpus = Math.min( os.cpus().length || 1, - files.length, + tests.length, MAX_PARALLEL_TESTS ); console.log('Using %d cpus', nr_of_cpus); @@ -168,8 +171,8 @@ if (cluster.isMaster) { { console.log( '\n[+] Passed %d/%d tests.', - files.length - failed_tests.length, - files.length + tests.length - failed_tests.length, + tests.length ); if (failed_tests.length > 0) { console.log('[-] Failed %d test(s).', failed_tests.length); From 3cea7aacde714a32f7b779341859b2e6bb00d71f Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Jul 2017 16:39:06 +0200 Subject: [PATCH 0064/2137] Nasm test: Also check final ESP --- tests/nasm/run.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/nasm/run.js b/tests/nasm/run.js index 7e1959dc..697c6138 100755 --- a/tests/nasm/run.js +++ b/tests/nasm/run.js @@ -229,7 +229,6 @@ else { const expected_eflags = test.fixture.array[offset] & MASK_ARITH; for (let i = 0; i < cpu.reg32s.length; i++) { - if(i === 4) continue; // TODO: Same stack for elf and multiboot let reg = cpu.reg32s[i]; if (reg !== expected_reg32s[i]) { individual_failures.push({ From 4871e5a28888f65635c86cc2008d46a284c80e2d Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Jul 2017 16:39:49 +0200 Subject: [PATCH 0065/2137] Nasm tests: Create more tests, improve instruction table --- tests/nasm/create_tests.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tests/nasm/create_tests.js b/tests/nasm/create_tests.js index 7e2cbc89..51e611e8 100755 --- a/tests/nasm/create_tests.js +++ b/tests/nasm/create_tests.js @@ -161,7 +161,7 @@ const encodings = [ { opcode: 0xC7, os: 1, e: 1, fixed_g: 0, imm: 1, }, { opcode: 0xC8, os: 1, imm16: 1, }, // enter - { opcode: 0xC9, os: 1, skip: 1, }, + { 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, }, @@ -352,7 +352,14 @@ const encodings = [ { 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, g: 1, skip: 1, }, + { 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 @@ -604,8 +611,8 @@ for(var i = 0; i < 8; i++) { 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, skip: 1, }, - { opcode: 0xB8 | i, os: 1, imm1632: 1, skip: 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 From 3014f95359cb6b753cc9d297c94072494dc0de04 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 27 Jul 2017 12:25:36 +0200 Subject: [PATCH 0066/2137] Significantly improve speed of nasm tests - Reuse v86 instances (in particular, memory allocation and wasm loading) - Reduce memory size from default (64M) to 2M --- src/browser/starter.js | 2 + src/bus.js | 4 +- src/cpu.js | 57 +++++----- src/main.js | 2 + tests/nasm/run.js | 240 ++++++++++++++++++++++------------------- 5 files changed, 166 insertions(+), 139 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 5a5e0943..0e74960f 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -615,6 +615,8 @@ function V86Starter(options) { this.bus.send("cpu-run"); } + + this.emulator_bus.send("emulator-loaded"); }.bind(this), 0); }.bind(this), 0); } diff --git a/src/bus.js b/src/bus.js index 4976aa34..38abc96b 100644 --- a/src/bus.js +++ b/src/bus.js @@ -7,7 +7,7 @@ function BusConnector() { this.listeners = {}; this.pair = undefined; -}; +} /** * @param {string} name @@ -46,7 +46,7 @@ BusConnector.prototype.unregister = function(name, fn) this.listeners[name] = listeners.filter(function(l) { - return l.fn !== fn + return l.fn !== fn; }); }; diff --git a/src/cpu.js b/src/cpu.js index f2ef8594..057f74e0 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -603,6 +603,11 @@ CPU.prototype.reset = function() this.fw_value[0] = 0; }; +CPU.prototype.reset_memory = function() +{ + this.mem8.fill(0); +}; + /** @export */ CPU.prototype.create_memory = function(size) { @@ -1267,13 +1272,19 @@ CPU.prototype.run_prefix_instruction = function() CPU.prototype.hlt_loop = function() { - dbg_assert(this.flags[0] & flag_interrupt); - //dbg_log("In HLT loop", LOG_CPU); + if(this.flags[0] & flag_interrupt) + { + //dbg_log("In HLT loop", LOG_CPU); - this.run_hardware_timers(v86.microtick()); - this.handle_irqs(); + this.run_hardware_timers(v86.microtick()); + this.handle_irqs(); - return 0; + return 0; + } + else + { + return 100; + } }; CPU.prototype.run_hardware_timers = function(now) @@ -3161,29 +3172,25 @@ CPU.prototype.hlt_op = function() if((this.flags[0] & flag_interrupt) === 0) { - this.debug.show("cpu halted"); + // execution can never resume (until NMIs are supported) this.bus.send("cpu-event-halt"); - if(DEBUG) this.debug.dump_regs(); - throw "HALT"; } - else - { - // get out of here and into hlt_loop - this.in_hlt = true; - //if(false) // possibly unsafe, test in safari - //{ - // this.hlt_loop(); - // this.diverged(); - // if(this.in_hlt) - // { - // throw MAGIC_CPU_EXCEPTION; - // } - //} - //else - { - throw MAGIC_CPU_EXCEPTION; - } + // get out of here and into hlt_loop + this.in_hlt = true; + + //if(false) // possibly unsafe, test in safari + //{ + // this.hlt_loop(); + // this.diverged(); + // if(this.in_hlt) + // { + // throw MAGIC_CPU_EXCEPTION; + // } + //} + //else + { + throw MAGIC_CPU_EXCEPTION; } }; diff --git a/src/main.js b/src/main.js index fd163347..b8efd8cb 100644 --- a/src/main.js +++ b/src/main.js @@ -26,6 +26,8 @@ function v86(bus, wm) v86.prototype.run = function() { + this.stopped = false; + if(!this.running) { this.bus.send("emulator-started"); diff --git a/tests/nasm/run.js b/tests/nasm/run.js index 697c6138..40c853e5 100755 --- a/tests/nasm/run.js +++ b/tests/nasm/run.js @@ -21,6 +21,7 @@ const cluster = require('cluster'); const MAX_PARALLEL_TESTS = +process.env.MAX_PARALLEL_TESTS || 99; const TEST_DIR = __dirname + "/build/"; const DONE_MSG = 'DONE'; +const TERMINATE_MSG = 'DONE'; const MASK_ARITH = 1 | 1 << 2 | 1 << 4 | 1 << 6 | 1 << 7 | 1 << 11; @@ -101,8 +102,15 @@ if (cluster.isMaster) { current_test++; } else { + worker.send(TERMINATE_MSG); worker.disconnect(); + setTimeout(() => { + // The emulator currently doesn't cleanly exit, so this is necessary + console.log("Worker killed"); + worker.kill(); + }, 100); + finished_workers++; if(finished_workers === nr_of_cpus) { @@ -155,7 +163,7 @@ if (cluster.isMaster) { worker.on('online', send_work_to_worker.bind(null, worker)); worker.on('exit', function(code, signal) { - if(code !== 0) { + if(code !== 0 && code !== null) { console.log('Worker error code:', code); process.exit(code); } @@ -191,135 +199,143 @@ if (cluster.isMaster) { } } else { - function run_test(test, done) { + function run_test(test) + { + if(!loaded) + { + first_test = test; + return; + } + + current_test = test; console.info('Testing', test.img_name); - let emulator = new V86({ - multiboot: { - url: TEST_DIR + test.img_name - }, - autostart: false + var cpu = emulator.v86.cpu; + + cpu.reset(); + cpu.reset_memory(); + cpu.load_multiboot(new Uint8Array(fs.readFileSync(TEST_DIR + current_test.img_name)).buffer); + + emulator.run(); + } + + let loaded = false; + let current_test = undefined; + let first_test = undefined; + + let emulator = new V86({ + autostart: false, + memory_size: 2 * 1024 * 1024, + }); + + emulator.add_listener("emulator-loaded", function() + { + loaded = true; + + if(first_test) + { + run_test(first_test); + } }); - //emulator.v86.cpu.debug.show = () => {}; + emulator.bus.register('cpu-event-halt', function() { + emulator.stop(); + var cpu = emulator.v86.cpu; - emulator.bus.register('cpu-event-halt', function() { - var cpu = emulator.v86.cpu; + const filename = TEST_DIR + current_test.img_name; + const evaluated_mmxs = cpu.reg_mmxs; + const evaluated_xmms = cpu.reg_xmm32s; + const esp = cpu.reg32s[4]; + const evaluated_memory = new Int32Array(cpu.mem8.slice(0x120000 - 16 * 4, 0x120000).buffer); + let individual_failures = []; - const filename = TEST_DIR + test.img_name; - const evaluated_mmxs = cpu.reg_mmxs; - const evaluated_xmms = cpu.reg_xmm32s; - const esp = cpu.reg32s[4]; - const evaluated_memory = new Int32Array(cpu.mem8.slice(0x120000 - 16 * 4, 0x120000).buffer); - let individual_failures = []; + if(current_test.exception) + { + throw "TODO: Handle exceptions"; + } - if(test.exception) - { - throw "TODO: Handle exceptions"; - } + console.assert(current_test.fixture.array); + if(current_test.fixture.array) + { + let offset = 0; + const expected_reg32s = current_test.fixture.array.slice(offset, offset += 8); + const expected_mmx_registers = current_test.fixture.array.slice(offset, offset += 16); + const expected_xmm_registers = current_test.fixture.array.slice(offset, offset += 32); + const expected_memory = current_test.fixture.array.slice(offset, offset += 16); + const expected_eflags = current_test.fixture.array[offset] & MASK_ARITH; - console.assert(test.fixture.array); - if(test.fixture.array) - { - let offset = 0; - const expected_reg32s = test.fixture.array.slice(offset, offset += 8); - const expected_mmx_registers = test.fixture.array.slice(offset, offset += 16); - const expected_xmm_registers = test.fixture.array.slice(offset, offset += 32); - const expected_memory = test.fixture.array.slice(offset, offset += 16); - const expected_eflags = test.fixture.array[offset] & MASK_ARITH; - - for (let i = 0; i < cpu.reg32s.length; i++) { - let reg = cpu.reg32s[i]; - if (reg !== expected_reg32s[i]) { - individual_failures.push({ - name: "cpu.reg32s[" + i + "]", - expected: expected_reg32s[i], - actual: reg, - }); - } - } - - for (let i = 0; i < evaluated_mmxs.length; i++) { - if (evaluated_mmxs[i] !== expected_mmx_registers[i]) { - individual_failures.push({ - name: "mm" + (i >> 1) + ".int32[" + (i & 1) + "] (cpu.reg_mmx[" + i + "])", - expected: expected_mmx_registers[i], - actual: evaluated_mmxs[i], - }); - } - } - - for (let i = 0; i < evaluated_xmms.length; i++) { - if (evaluated_xmms[i] !== expected_xmm_registers[i]) { - individual_failures.push({ - name: "xmm" + (i >> 2) + ".int32[" + (i & 3) + "] (cpu.reg_xmm[" + i + "])", - expected: expected_xmm_registers[i], - actual: evaluated_xmms[i], - }); - } - } - - for (let i = 0; i < evaluated_memory.length; i++) { - if (evaluated_memory[i] !== expected_memory[i]) { - individual_failures.push({ - name: "mem[" + i + "]", - expected: expected_memory[i], - actual: evaluated_memory[i], - }); - } - } - - const seen_eflags = cpu.get_eflags() & MASK_ARITH; - if(seen_eflags !== expected_eflags) - { + for (let i = 0; i < cpu.reg32s.length; i++) { + let reg = cpu.reg32s[i]; + if (reg !== expected_reg32s[i]) { individual_failures.push({ - name: "eflags", - expected: expected_eflags, - actual: seen_eflags, + name: "cpu.reg32s[" + i + "]", + expected: expected_reg32s[i], + actual: reg, }); } } - if (individual_failures.length > 0) { - done({ - failures: individual_failures, - img_name: test.img_name + for (let i = 0; i < evaluated_mmxs.length; i++) { + if (evaluated_mmxs[i] !== expected_mmx_registers[i]) { + individual_failures.push({ + name: "mm" + (i >> 1) + ".int32[" + (i & 1) + "] (cpu.reg_mmx[" + i + "])", + expected: expected_mmx_registers[i], + actual: evaluated_mmxs[i], + }); + } + } + + for (let i = 0; i < evaluated_xmms.length; i++) { + if (evaluated_xmms[i] !== expected_xmm_registers[i]) { + individual_failures.push({ + name: "xmm" + (i >> 2) + ".int32[" + (i & 3) + "] (cpu.reg_xmm[" + i + "])", + expected: expected_xmm_registers[i], + actual: evaluated_xmms[i], + }); + } + } + + for (let i = 0; i < evaluated_memory.length; i++) { + if (evaluated_memory[i] !== expected_memory[i]) { + individual_failures.push({ + name: "mem[" + i + "]", + expected: expected_memory[i], + actual: evaluated_memory[i], + }); + } + } + + const seen_eflags = cpu.get_eflags() & MASK_ARITH; + if(seen_eflags !== expected_eflags) + { + individual_failures.push({ + name: "eflags", + expected: expected_eflags, + actual: seen_eflags, }); } - else { - done(); - } + } - }); - - emulator.bus.register('emulator-ready', function() { - try { - emulator.run(); - } - catch(e) { - console.log(e); - } - }); - } - - // To silence logs from emulator in the worker - console.log = () => {}; - - process.on('uncaughtException', (err) => { - if (err !== 'HALT') { - console.error(err); - throw err; + if (individual_failures.length > 0) { + process.send({ + failures: individual_failures, + img_name: current_test.img_name + }); + } + else { + process.send(DONE_MSG); } }); - cluster.worker.on('message', function(test) { - run_test(test, function(test_failure) { - if (test_failure) { - process.send(test_failure); - } - else { - process.send(DONE_MSG); - } - }); + cluster.worker.on('message', function(message) { + if(message === TERMINATE_MSG) + { + emulator.stop(); + emulator = null; + } + else + { + run_test(message); + } }); } From 6e9fb16ac59a104769036fcf1716783c235c4da1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 27 Jul 2017 12:32:32 +0200 Subject: [PATCH 0067/2137] Nasm: Separate .o generation in makefile --- tests/nasm/Makefile | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/nasm/Makefile b/tests/nasm/Makefile index c9e2ed99..87577c0b 100644 --- a/tests/nasm/Makefile +++ b/tests/nasm/Makefile @@ -10,17 +10,20 @@ inc_files := $(addprefix build/,$(wildcard *.inc)) all: $(source_files) $(host_executables) $(v86_executables) $(host_fixtures) .PHONY: all +build/%.o: build/%.asm $(inc_files) + nasm -felf32 -o $@ $< + # To run / debug locally -build/%.bin: build/%.asm $(inc_files) - nasm -felf32 -o $@.o $<; ld -g $@.o -m elf_i386 --section-start=.bss=0x100000 -o $@ +build/%.bin: build/%.o + ld -g $< -m elf_i386 --section-start=.bss=0x100000 -o $@ # To generate a fixture using gdb build/%.fixture: build/%.bin gdb -quiet -batch -x gdbauto $< > $@ # To use as a multiboot kernel image for v86 -build/%.img: build/%.asm $(inc_files) - nasm -felf32 -o $@.o $<; ld -g $@.o -m elf_i386 --section-start=.bss=0x100000 --section-start=.text=0x8000 -o $@ +build/%.img: build/%.o + ld -g $< -m elf_i386 --section-start=.bss=0x100000 --section-start=.text=0x8000 -o $@ build/%.asm: %.asm mkdir -p build; cp $< $@ From 0a8899d3b6c646225de02addda791ad736134035 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 27 Jul 2017 15:11:27 +0200 Subject: [PATCH 0068/2137] Fix memory view size --- src/cpu.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index 057f74e0..68454499 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -629,8 +629,8 @@ 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); - this.mem32s = new Int32Array(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); }; CPU.prototype.init = function(settings, device_bus) From cda9398da5dca7753c53054d2c9686015b297587 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 27 Jul 2017 15:33:24 +0200 Subject: [PATCH 0069/2137] Nasm tests: Ensure build folder exists --- tests/nasm/create_tests.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/nasm/create_tests.js b/tests/nasm/create_tests.js index 51e611e8..6d779e79 100755 --- a/tests/nasm/create_tests.js +++ b/tests/nasm/create_tests.js @@ -928,6 +928,18 @@ function gen_table() } gen_table(); +try +{ + fs.mkdirSync(__dirname + "/build/"); +} +catch(e) +{ + if(e.code !== 'EEXIST') + { + throw e; + } +} + for(const op of encodings) { const configurations = [ From 1b6c1091cea553873de8badece3d916cdc5f3483 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 27 Jul 2017 16:05:06 +0200 Subject: [PATCH 0070/2137] Update kvm-unit-test from upstream --- tests/kvm-unit-tests/.gitignore | 3 + tests/kvm-unit-tests/COPYRIGHT | 10 +- tests/kvm-unit-tests/MAINTAINERS | 7 + tests/kvm-unit-tests/Makefile | 48 +- tests/kvm-unit-tests/configure | 82 +- tests/kvm-unit-tests/lib/alloc.c | 10 +- tests/kvm-unit-tests/lib/argv.c | 23 +- tests/kvm-unit-tests/lib/asm-generic/io.h | 4 +- tests/kvm-unit-tests/lib/asm-generic/page.h | 4 +- .../kvm-unit-tests/lib/asm-generic/spinlock.h | 16 +- tests/kvm-unit-tests/lib/auxinfo.h | 4 + tests/kvm-unit-tests/lib/bitops.h | 6 +- tests/kvm-unit-tests/lib/errata.h | 27 +- tests/kvm-unit-tests/lib/libcflat.h | 37 +- tests/kvm-unit-tests/lib/pci-edu.c | 2 +- tests/kvm-unit-tests/lib/pci-testdev.c | 4 +- tests/kvm-unit-tests/lib/pci.c | 20 +- tests/kvm-unit-tests/lib/pci.h | 3 + tests/kvm-unit-tests/lib/printf.c | 75 +- tests/kvm-unit-tests/lib/report.c | 51 +- tests/kvm-unit-tests/lib/setjmp.h | 6 + tests/kvm-unit-tests/lib/stack.c | 7 + tests/kvm-unit-tests/lib/stack.h | 6 + tests/kvm-unit-tests/lib/string.c | 48 + tests/kvm-unit-tests/lib/string.h | 6 + tests/kvm-unit-tests/lib/util.c | 1 + tests/kvm-unit-tests/lib/virtio-mmio.c | 4 +- tests/kvm-unit-tests/lib/virtio-mmio.h | 4 +- tests/kvm-unit-tests/lib/virtio.c | 4 +- tests/kvm-unit-tests/lib/virtio.h | 4 +- tests/kvm-unit-tests/lib/x86/asm/page.h | 2 + tests/kvm-unit-tests/lib/x86/asm/spinlock.h | 7 +- tests/kvm-unit-tests/lib/x86/desc.c | 32 +- tests/kvm-unit-tests/lib/x86/desc.h | 63 +- tests/kvm-unit-tests/lib/x86/fwcfg.c | 2 +- tests/kvm-unit-tests/lib/x86/intel-iommu.c | 16 +- tests/kvm-unit-tests/lib/x86/processor.h | 24 +- tests/kvm-unit-tests/lib/x86/smp.c | 37 +- tests/kvm-unit-tests/lib/x86/smp.h | 2 + tests/kvm-unit-tests/lib/x86/vm.c | 183 +- tests/kvm-unit-tests/lib/x86/vm.h | 28 + tests/kvm-unit-tests/x86/Makefile | 2 +- tests/kvm-unit-tests/x86/Makefile.common | 44 +- tests/kvm-unit-tests/x86/Makefile.i386 | 2 +- tests/kvm-unit-tests/x86/Makefile.x86_64 | 5 +- tests/kvm-unit-tests/x86/asyncpf.c | 6 +- tests/kvm-unit-tests/x86/cstart.S | 14 +- tests/kvm-unit-tests/x86/cstart64.S | 12 +- tests/kvm-unit-tests/x86/eventinj.c | 2 +- tests/kvm-unit-tests/x86/hyperv.c | 65 +- tests/kvm-unit-tests/x86/hyperv.h | 40 +- tests/kvm-unit-tests/x86/hyperv_clock.c | 29 +- tests/kvm-unit-tests/x86/hyperv_stimer.c | 83 +- tests/kvm-unit-tests/x86/hyperv_synic.c | 46 +- tests/kvm-unit-tests/x86/kvmclock_test.c | 33 +- tests/kvm-unit-tests/x86/msr.c | 29 +- tests/kvm-unit-tests/x86/pmu.c | 2 +- tests/kvm-unit-tests/x86/run | 51 - tests/kvm-unit-tests/x86/tsc.c | 2 +- tests/kvm-unit-tests/x86/unittests.cfg | 226 --- tests/kvm-unit-tests/x86/vmexit.c | 42 +- tests/kvm-unit-tests/x86/vmx.c | 990 ++++++++-- tests/kvm-unit-tests/x86/vmx.h | 217 +- tests/kvm-unit-tests/x86/vmx_tests.c | 1741 ++++++++++++++++- tests/kvm-unit-tests/x86/xsave.c | 2 +- 65 files changed, 3718 insertions(+), 889 deletions(-) delete mode 100755 tests/kvm-unit-tests/x86/run delete mode 100644 tests/kvm-unit-tests/x86/unittests.cfg diff --git a/tests/kvm-unit-tests/.gitignore b/tests/kvm-unit-tests/.gitignore index 2213b9b1..2405a808 100644 --- a/tests/kvm-unit-tests/.gitignore +++ b/tests/kvm-unit-tests/.gitignore @@ -17,3 +17,6 @@ cscope.* /build-head /logs/ /logs.old/ +/api/api-sample +/api/dirty-log +/api/dirty-log-perf diff --git a/tests/kvm-unit-tests/COPYRIGHT b/tests/kvm-unit-tests/COPYRIGHT index d35649cb..b9d975fc 100644 --- a/tests/kvm-unit-tests/COPYRIGHT +++ b/tests/kvm-unit-tests/COPYRIGHT @@ -1,4 +1,10 @@ Copyright (C) 2006 Qumranet. +Copyright (C) 2007-2017 by various contributors (see source files for details) -The files in this directory and its subdirectories are licensed under the -GNU LGPL, version 2. +The kvm-unit-tests are free software; the whole package can be redistributed +and/or modified under the terms of the GNU General Public License version 2 +as published by the Free Software Foundation. + +Many files in this directory and its subdirectories are also licensed under +the less restrictive GNU LGPL, version 2, or other compatible licenses. See +the individual files for details. diff --git a/tests/kvm-unit-tests/MAINTAINERS b/tests/kvm-unit-tests/MAINTAINERS index b86dea73..d07a4cfa 100644 --- a/tests/kvm-unit-tests/MAINTAINERS +++ b/tests/kvm-unit-tests/MAINTAINERS @@ -76,6 +76,13 @@ F: powerpc/* F: lib/powerpc/* F: lib/ppc64/* +S390X +M: Thomas Huth +M: David Hildenbrand +L: kvm@vger.kernel.org +F: s390x/* +F: lib/s390x/* + X86 M: Paolo Bonzini M: Radim Krčmář diff --git a/tests/kvm-unit-tests/Makefile b/tests/kvm-unit-tests/Makefile index 16ce2970..72313347 100644 --- a/tests/kvm-unit-tests/Makefile +++ b/tests/kvm-unit-tests/Makefile @@ -1,5 +1,5 @@ -SHELL := /bin/bash +SHELL := /usr/bin/env bash ifeq ($(wildcard config.mak),) $(error run ./configure first. See ./configure -h) @@ -7,8 +7,12 @@ endif include config.mak +# Set search path for all sources +VPATH = $(SRCDIR) + libdirs-get = $(shell [ -d "lib/$(1)" ] && echo "lib/$(1) lib/$(1)/asm") ARCH_LIBDIRS := $(call libdirs-get,$(ARCH)) $(call libdirs-get,$(TEST_DIR)) +OBJDIRS := $(ARCH_LIBDIRS) DESTDIR := $(PREFIX)/share/kvm-unit-tests/ @@ -30,13 +34,15 @@ cflatobjs := \ # libfdt paths LIBFDT_objdir = lib/libfdt -LIBFDT_srcdir = lib/libfdt +LIBFDT_srcdir = $(SRCDIR)/lib/libfdt LIBFDT_archive = $(LIBFDT_objdir)/libfdt.a LIBFDT_include = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_INCLUDES)) LIBFDT_version = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_VERSION)) -#include architecure specific make rules -include $(TEST_DIR)/Makefile +OBJDIRS += $(LIBFDT_objdir) + +#include architecture specific make rules +include $(SRCDIR)/$(TEST_DIR)/Makefile # cc-option # Usage: OP_CFLAGS+=$(call cc-option, -falign-functions=0, -malign-functions=0) @@ -44,8 +50,10 @@ include $(TEST_DIR)/Makefile cc-option = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null \ > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;) -CFLAGS += -g -CFLAGS += $(autodepend-flags) -Wall -Werror +COMMON_CFLAGS += -g $(autodepend-flags) +COMMON_CFLAGS += -Wall -Wwrite-strings -Wclobbered -Wempty-body -Wuninitialized +COMMON_CFLAGS += -Wignored-qualifiers -Wunused-but-set-parameter +COMMON_CFLAGS += -Werror frame-pointer-flag=-f$(if $(KEEP_FRAME_POINTER),no-,)omit-frame-pointer fomit_frame_pointer := $(call cc-option, $(frame-pointer-flag), "") fnostack_protector := $(call cc-option, -fno-stack-protector, "") @@ -53,34 +61,42 @@ fnostack_protector_all := $(call cc-option, -fno-stack-protector-all, "") wno_frame_address := $(call cc-option, -Wno-frame-address, "") fno_pic := $(call cc-option, -fno-pic, "") no_pie := $(call cc-option, -no-pie, "") -CFLAGS += $(fomit_frame_pointer) -CFLAGS += $(fno_stack_protector) -CFLAGS += $(fno_stack_protector_all) -CFLAGS += $(wno_frame_address) -CFLAGS += $(if $(U32_LONG_FMT),-D__U32_LONG_FMT__,) -CFLAGS += $(fno_pic) $(no_pie) +COMMON_CFLAGS += $(fomit_frame_pointer) +COMMON_CFLAGS += $(fno_stack_protector) +COMMON_CFLAGS += $(fno_stack_protector_all) +COMMON_CFLAGS += $(wno_frame_address) +COMMON_CFLAGS += $(if $(U32_LONG_FMT),-D__U32_LONG_FMT__,) +COMMON_CFLAGS += $(fno_pic) $(no_pie) -CXXFLAGS += $(CFLAGS) +CFLAGS += $(COMMON_CFLAGS) +CFLAGS += -Wmissing-parameter-type -Wold-style-declaration -Woverride-init + +CXXFLAGS += $(COMMON_CFLAGS) autodepend-flags = -MMD -MF $(dir $*).$(notdir $*).d LDFLAGS += $(CFLAGS) -LDFLAGS += -pthread -lrt $(libcflat): $(cflatobjs) $(AR) rcs $@ $^ include $(LIBFDT_srcdir)/Makefile.libfdt -$(LIBFDT_archive): CFLAGS += -ffreestanding -I lib -I lib/libfdt -Wno-sign-compare +$(LIBFDT_archive): CFLAGS += -ffreestanding -I $(SRCDIR)/lib -I $(SRCDIR)/lib/libfdt -Wno-sign-compare $(LIBFDT_archive): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS)) $(AR) rcs $@ $^ + +# Build directory target +.PHONY: directories +directories: + @mkdir -p $(OBJDIRS) + %.o: %.S $(CC) $(CFLAGS) -c -nostdlib -o $@ $< -include */.*.d */*/.*.d -all: $(shell git rev-parse --verify --short=8 HEAD >build-head 2>/dev/null) +all: directories $(shell cd $(SRCDIR) && git rev-parse --verify --short=8 HEAD >$(PWD)/build-head 2>/dev/null) standalone: all @scripts/mkstandalone.sh diff --git a/tests/kvm-unit-tests/configure b/tests/kvm-unit-tests/configure index b653b65f..e1efb3ca 100755 --- a/tests/kvm-unit-tests/configure +++ b/tests/kvm-unit-tests/configure @@ -1,17 +1,20 @@ -#!/bin/bash +#!/usr/bin/env bash +srcdir=$(cd "$(dirname "$0")"; pwd) prefix=/usr/local cc=gcc +cxx=g++ ld=ld objcopy=objcopy objdump=objdump ar=ar addr2line=addr2line -arch=i386 +arch=`uname -m | sed -e 's/i.86/i386/;s/arm.*/arm/;s/ppc64.*/ppc64/'` host=$arch cross_prefix= endian="" pretty_print_stacks=yes +environ_default=yes u32_long= usage() { @@ -23,11 +26,15 @@ usage() { --processor=PROCESSOR processor to compile for ($arch) --cross-prefix=PREFIX cross compiler prefix --cc=CC c compiler to use ($cc) + --cxx=CXX c++ compiler to use ($cxx) --ld=LD ld linker to use ($ld) --prefix=PREFIX where to install things ($prefix) --endian=ENDIAN endianness to compile for (little or big, ppc64 only) --[enable|disable]-pretty-print-stacks enable or disable pretty stack printing (enabled by default) + --[enable|disable]-default-environ + enable or disable the generation of a default environ when + no environ is provided by the user (enabled by default) EOF exit 1 } @@ -58,6 +65,9 @@ while [[ "$1" = -* ]]; do --cc) cc="$arg" ;; + --cxx) + cxx="$arg" + ;; --ld) ld="$arg" ;; @@ -67,6 +77,12 @@ while [[ "$1" = -* ]]; do --disable-pretty-print-stacks) pretty_print_stacks=no ;; + --enable-default-environ) + environ_default=yes + ;; + --disable-default-environ) + environ_default=no + ;; --help) usage ;; @@ -102,12 +118,12 @@ elif [ "$arch" = "ppc64" ]; then else testdir=$arch fi -if [ ! -d $testdir ]; then +if [ ! -d "$srcdir/$testdir" ]; then echo "$testdir does not exist!" exit 1 fi -if [ -f $testdir/run ]; then - ln -fs $testdir/run $testdir-run +if [ -f "$srcdir/$testdir/run" ]; then + ln -fs "$srcdir/$testdir/run" $testdir-run fi # check if uint32_t needs a long format modifier @@ -117,42 +133,56 @@ EOF u32_long=$($cross_prefix$cc -E lib-test.c | grep -v '^#' | grep -q long && echo yes) rm -f lib-test.c -# check for dependent 32 bit libraries -if [ "$arch" != "arm" ]; then -cat << EOF > lib_test.c -#include -#include -#include - -int main () -{} -EOF -$cc -m32 -o /dev/null lib_test.c &> /dev/null -exit=$? -if [ $exit -eq 0 ]; then - api=true +# api/: check for dependent 32 bit libraries and gnu++11 support +if [ "$testdir" = "x86" ]; then + echo 'int main () {}' > lib-test.c + $cc -m32 -o /dev/null -lstdc++ -lpthread -lrt lib-test.c &> /dev/null + exit=$? + $cxx -m32 -o /dev/null -std=gnu++11 lib-test.c &> /dev/null + if [ $? -eq 0 -a $exit -eq 0 ]; then + api=true + fi + rm -f lib-test.c fi -rm -f lib_test.c + +# Are we in a separate build tree? If so, link the Makefile +# and shared stuff so that 'make' and run_tests.sh work. +if test ! -e Makefile; then + echo "linking Makefile..." + ln -s "$srcdir/Makefile" . + + echo "linking tests..." + mkdir -p $testdir + ln -sf "$srcdir/$testdir/run" $testdir/ + ln -sf "$srcdir/$testdir/unittests.cfg" $testdir/ + ln -sf "$srcdir/run_tests.sh" + + echo "linking scripts..." + ln -sf "$srcdir/scripts" fi # link lib/asm for the architecture rm -f lib/asm asm=asm-generic -if [ -d lib/$arch/asm ]; then - asm=$arch/asm -elif [ -d lib/$testdir/asm ]; then - asm=$testdir/asm +if [ -d "$srcdir/lib/$arch/asm" ]; then + asm="$srcdir/lib/$arch/asm" +elif [ -d "$srcdir/lib/$testdir/asm" ]; then + asm="$srcdir/lib/$testdir/asm" fi -ln -s $asm lib/asm +mkdir -p lib +ln -sf "$asm" lib/asm + # create the config cat < config.mak +SRCDIR=$srcdir PREFIX=$prefix HOST=$host ARCH=$arch ARCH_NAME=$arch_name PROCESSOR=$processor CC=$cross_prefix$cc +CXX=$cross_prefix$cxx LD=$cross_prefix$ld OBJCOPY=$cross_prefix$objcopy OBJDUMP=$cross_prefix$objdump @@ -163,5 +193,7 @@ TEST_DIR=$testdir FIRMWARE=$firmware ENDIAN=$endian PRETTY_PRINT_STACKS=$pretty_print_stacks +ENVIRON_DEFAULT=$environ_default +ERRATATXT=errata.txt U32_LONG_FMT=$u32_long EOF diff --git a/tests/kvm-unit-tests/lib/alloc.c b/tests/kvm-unit-tests/lib/alloc.c index 58af52b3..d553a7ec 100644 --- a/tests/kvm-unit-tests/lib/alloc.c +++ b/tests/kvm-unit-tests/lib/alloc.c @@ -25,7 +25,7 @@ void phys_alloc_show(void) int i; spin_lock(&lock); - printf("phys_alloc minimum alignment: 0x%" PRIx64 "\n", + printf("phys_alloc minimum alignment: %#" PRIx64 "\n", (u64)align_min); for (i = 0; i < nr_regions; ++i) printf("%016" PRIx64 "-%016" PRIx64 " [%s]\n", @@ -75,10 +75,10 @@ static phys_addr_t phys_alloc_aligned_safe(phys_addr_t size, size += addr - base; if ((top_safe - base) < size) { - printf("phys_alloc: requested=0x%" PRIx64 - " (align=0x%" PRIx64 "), " - "need=0x%" PRIx64 ", but free=0x%" PRIx64 ". " - "top=0x%" PRIx64 ", top_safe=0x%" PRIx64 "\n", + printf("phys_alloc: requested=%#" PRIx64 + " (align=%#" PRIx64 "), " + "need=%#" PRIx64 ", but free=%#" PRIx64 ". " + "top=%#" PRIx64 ", top_safe=%#" PRIx64 "\n", (u64)size_orig, (u64)align, (u64)size, top_safe - base, (u64)top, top_safe); spin_unlock(&lock); diff --git a/tests/kvm-unit-tests/lib/argv.c b/tests/kvm-unit-tests/lib/argv.c index a37fc879..f0e183a8 100644 --- a/tests/kvm-unit-tests/lib/argv.c +++ b/tests/kvm-unit-tests/lib/argv.c @@ -1,8 +1,16 @@ +/* + * Set up arguments for main() and prepare environment variables + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License version 2. + */ + #include "libcflat.h" +#include "argv.h" #include "auxinfo.h" int __argc; -char *__args; +const char *__args; char *__argv[100]; char *__environ[200]; @@ -15,7 +23,7 @@ static char *copy_ptr = args_copy; #define isalpha(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z') || (c) == '_') #define isalnum(c) (isalpha(c) || ((c) >= '0' && (c) <= '9')) -static char *skip_blanks(char *p) +static const char *skip_blanks(const char *p) { while (isblank(*p)) ++p; @@ -24,7 +32,7 @@ static char *skip_blanks(char *p) void __setup_args(void) { - char *args = __args; + const char *args = __args; char **argv = __argv + __argc; while (*(args = skip_blanks(args)) != '\0') { @@ -36,7 +44,7 @@ void __setup_args(void) __argc = argv - __argv; } -void setup_args(char *args) +static void setup_args(const char *args) { if (!args) return; @@ -45,16 +53,13 @@ void setup_args(char *args) __setup_args(); } -void setup_args_progname(char *args) +void setup_args_progname(const char *args) { __argv[0] = copy_ptr; strcpy(__argv[0], auxinfo.progname); copy_ptr += strlen(auxinfo.progname) + 1; ++__argc; - if (args) { - __args = args; - __setup_args(); - } + setup_args(args); } static char *env_eol(char *env) diff --git a/tests/kvm-unit-tests/lib/asm-generic/io.h b/tests/kvm-unit-tests/lib/asm-generic/io.h index 91a2d799..88972f3b 100644 --- a/tests/kvm-unit-tests/lib/asm-generic/io.h +++ b/tests/kvm-unit-tests/lib/asm-generic/io.h @@ -5,9 +5,9 @@ * adapted from the Linux kernel's include/asm-generic/io.h * and arch/arm/include/asm/io.h * - * Copyright (C) 2014, Red Hat Inc, Andrew Jones + * Copyright (C) 2017, Red Hat Inc, Andrew Jones * - * This work is licensed under the terms of the GNU LGPL, version 2. + * This work is licensed under the terms of the GNU GPL, version 2. */ #include "libcflat.h" #include "asm/page.h" diff --git a/tests/kvm-unit-tests/lib/asm-generic/page.h b/tests/kvm-unit-tests/lib/asm-generic/page.h index 7b8a08bf..5ed08612 100644 --- a/tests/kvm-unit-tests/lib/asm-generic/page.h +++ b/tests/kvm-unit-tests/lib/asm-generic/page.h @@ -4,9 +4,9 @@ * asm-generic/page.h * adapted from the Linux kernel's include/asm-generic/page.h * - * Copyright (C) 2014, Red Hat Inc, Andrew Jones + * Copyright (C) 2017, Red Hat Inc, Andrew Jones * - * This work is licensed under the terms of the GNU LGPL, version 2. + * This work is licensed under the terms of the GNU GPL, version 2. */ #include diff --git a/tests/kvm-unit-tests/lib/asm-generic/spinlock.h b/tests/kvm-unit-tests/lib/asm-generic/spinlock.h index 31417442..31fa510e 100644 --- a/tests/kvm-unit-tests/lib/asm-generic/spinlock.h +++ b/tests/kvm-unit-tests/lib/asm-generic/spinlock.h @@ -1,4 +1,18 @@ #ifndef _ASM_GENERIC_SPINLOCK_H_ #define _ASM_GENERIC_SPINLOCK_H_ -#error need architecture specific asm/spinlock.h + +struct spinlock { + unsigned int v; +}; + +static inline void spin_lock(struct spinlock *lock) +{ + while (__sync_lock_test_and_set(&lock->v, 1)); +} + +static inline void spin_unlock(struct spinlock *lock) +{ + __sync_lock_release(&lock->v); +} + #endif diff --git a/tests/kvm-unit-tests/lib/auxinfo.h b/tests/kvm-unit-tests/lib/auxinfo.h index ef2376b4..669ba5da 100644 --- a/tests/kvm-unit-tests/lib/auxinfo.h +++ b/tests/kvm-unit-tests/lib/auxinfo.h @@ -1,3 +1,7 @@ +/* + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License version 2. + */ #ifndef _AUXINFO_H_ #define _AUXINFO_H_ struct auxinfo { diff --git a/tests/kvm-unit-tests/lib/bitops.h b/tests/kvm-unit-tests/lib/bitops.h index 9aa847e1..185c5d36 100644 --- a/tests/kvm-unit-tests/lib/bitops.h +++ b/tests/kvm-unit-tests/lib/bitops.h @@ -2,12 +2,12 @@ #define _BITOPS_H_ /* - * Adapated from + * Adapted from * include/linux/bitops.h * - * Copyright (C) 2015, Red Hat Inc, Andrew Jones + * Copyright (C) 2017, Red Hat Inc, Andrew Jones * - * This work is licensed under the terms of the GNU LGPL, version 2. + * This work is licensed under the terms of the GNU GPL, version 2. */ #define BITS_PER_LONG_LONG 64 diff --git a/tests/kvm-unit-tests/lib/errata.h b/tests/kvm-unit-tests/lib/errata.h index 5e63f73b..f3ebca2d 100644 --- a/tests/kvm-unit-tests/lib/errata.h +++ b/tests/kvm-unit-tests/lib/errata.h @@ -1,3 +1,9 @@ +/* + * errata functions + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License version 2. + */ #ifndef _ERRATA_H_ #define _ERRATA_H_ @@ -7,16 +13,33 @@ #define _ERRATA_RELAXED(erratum) errata_relaxed("ERRATA_" # erratum) #define ERRATA_RELAXED(erratum) _ERRATA_RELAXED(erratum) +static inline bool errata_force(void) +{ + char *s = getenv("ERRATA_FORCE"); + + return s && (*s == '1' || *s == 'y' || *s == 'Y'); +} + static inline bool errata(const char *erratum) { - char *s = getenv(erratum); + char *s; + + if (errata_force()) + return true; + + s = getenv(erratum); return s && (*s == '1' || *s == 'y' || *s == 'Y'); } static inline bool errata_relaxed(const char *erratum) { - char *s = getenv(erratum); + char *s; + + if (errata_force()) + return true; + + s = getenv(erratum); return !(s && (*s == '0' || *s == 'n' || *s == 'N')); } diff --git a/tests/kvm-unit-tests/lib/libcflat.h b/tests/kvm-unit-tests/lib/libcflat.h index 96a37926..a5c42903 100644 --- a/tests/kvm-unit-tests/lib/libcflat.h +++ b/tests/kvm-unit-tests/lib/libcflat.h @@ -96,15 +96,25 @@ extern int vsnprintf(char *buf, int size, const char *fmt, va_list va) extern int vprintf(const char *fmt, va_list va) __attribute__((format(printf, 1, 0))); +void report_prefix_pushf(const char *prefix_fmt, ...) + __attribute__((format(printf, 1, 2))); extern void report_prefix_push(const char *prefix); extern void report_prefix_pop(void); -extern void report(const char *msg_fmt, bool pass, ...); -extern void report_xfail(const char *msg_fmt, bool xfail, bool pass, ...); -extern void report_abort(const char *msg_fmt, ...); -extern void report_skip(const char *msg_fmt, ...); -extern void report_info(const char *msg_fmt, ...); +extern void report(const char *msg_fmt, bool pass, ...) + __attribute__((format(printf, 1, 3))); +extern void report_xfail(const char *msg_fmt, bool xfail, bool pass, ...) + __attribute__((format(printf, 1, 4))); +extern void report_abort(const char *msg_fmt, ...) + __attribute__((format(printf, 1, 2))); +extern void report_skip(const char *msg_fmt, ...) + __attribute__((format(printf, 1, 2))); +extern void report_info(const char *msg_fmt, ...) + __attribute__((format(printf, 1, 2))); +extern void report_pass(void); extern int report_summary(void); +bool simple_glob(const char *text, const char *pattern); + extern void dump_stack(void); extern void dump_frame_stack(const void *instruction, const void *frame); @@ -124,9 +134,26 @@ do { \ } \ } while (0) +#define assert_msg(cond, fmt, args...) \ +do { \ + if (!(cond)) { \ + printf("%s:%d: assert failed: %s: " fmt "\n", \ + __FILE__, __LINE__, #cond, ## args); \ + dump_stack(); \ + abort(); \ + } \ +} while (0) + static inline bool is_power_of_2(unsigned long n) { return n && !(n & (n - 1)); } +/* + * One byte per bit, a ' between each group of 4 bits, and a null terminator. + */ +#define BINSTR_SZ (sizeof(unsigned long) * 8 + sizeof(unsigned long) * 2) +void binstr(unsigned long x, char out[BINSTR_SZ]); +void print_binstr(unsigned long x); + #endif diff --git a/tests/kvm-unit-tests/lib/pci-edu.c b/tests/kvm-unit-tests/lib/pci-edu.c index f94962f0..0e031054 100644 --- a/tests/kvm-unit-tests/lib/pci-edu.c +++ b/tests/kvm-unit-tests/lib/pci-edu.c @@ -48,7 +48,7 @@ void edu_dma(struct pci_edu_dev *dev, iova_t iova, assert(size <= EDU_DMA_SIZE_MAX); assert(dev_offset < EDU_DMA_SIZE_MAX); - printf("edu device DMA start %s addr 0x%" PRIx64 " size 0x%lu off 0x%x\n", + printf("edu device DMA start %s addr %#" PRIx64 " size %lu off %#x\n", from_device ? "FROM" : "TO", iova, (ulong)size, dev_offset); diff --git a/tests/kvm-unit-tests/lib/pci-testdev.c b/tests/kvm-unit-tests/lib/pci-testdev.c index 7d298e69..039bb447 100644 --- a/tests/kvm-unit-tests/lib/pci-testdev.c +++ b/tests/kvm-unit-tests/lib/pci-testdev.c @@ -131,8 +131,8 @@ static bool pci_testdev_one(struct pci_test_dev_hdr *test, return (int)count == nr_writes; } -void pci_testdev_print(struct pci_test_dev_hdr *test, - struct pci_testdev_ops *ops) +static void pci_testdev_print(struct pci_test_dev_hdr *test, + struct pci_testdev_ops *ops) { bool io = (ops == &pci_testdev_io_ops); int i; diff --git a/tests/kvm-unit-tests/lib/pci.c b/tests/kvm-unit-tests/lib/pci.c index daf39810..daa33e1f 100644 --- a/tests/kvm-unit-tests/lib/pci.c +++ b/tests/kvm-unit-tests/lib/pci.c @@ -49,7 +49,7 @@ bool pci_setup_msi(struct pci_dev *dev, uint64_t msi_addr, uint32_t msi_data) assert(dev); if (!dev->msi_offset) { - printf("MSI: dev 0x%x does not support MSI.\n", dev->bdf); + printf("MSI: dev %#x does not support MSI.\n", dev->bdf); return false; } @@ -112,6 +112,8 @@ uint32_t pci_bar_mask(uint32_t bar) uint32_t pci_bar_get(struct pci_dev *dev, int bar_num) { + ASSERT_BAR_NUM(bar_num); + return pci_config_readl(dev->bdf, PCI_BASE_ADDRESS_0 + bar_num * 4); } @@ -134,6 +136,8 @@ static phys_addr_t __pci_bar_get_addr(struct pci_dev *dev, int bar_num) phys_addr_t pci_bar_get_addr(struct pci_dev *dev, int bar_num) { + ASSERT_BAR_NUM(bar_num); + return dev->resource[bar_num]; } @@ -141,11 +145,19 @@ void pci_bar_set_addr(struct pci_dev *dev, int bar_num, phys_addr_t addr) { int off = PCI_BASE_ADDRESS_0 + bar_num * 4; + assert(addr != INVALID_PHYS_ADDR); + assert(dev->resource[bar_num] != INVALID_PHYS_ADDR); + + ASSERT_BAR_NUM(bar_num); + if (pci_bar_is64(dev, bar_num)) + ASSERT_BAR_NUM(bar_num + 1); + else + assert((addr >> 32) == 0); + pci_config_writel(dev->bdf, off, (uint32_t)addr); dev->resource[bar_num] = addr; if (pci_bar_is64(dev, bar_num)) { - assert(bar_num + 1 < PCI_BAR_NUM); pci_config_writel(dev->bdf, off + 4, (uint32_t)(addr >> 32)); dev->resource[bar_num + 1] = dev->resource[bar_num]; } @@ -283,10 +295,10 @@ static void pci_cap_print(struct pci_dev *dev, int cap_offset, int cap_id) break; } default: - printf("\tcapability 0x%02x ", cap_id); + printf("\tcapability %#04x ", cap_id); break; } - printf("at offset 0x%02x\n", cap_offset); + printf("at offset %#04x\n", cap_offset); } void pci_dev_print(struct pci_dev *dev) diff --git a/tests/kvm-unit-tests/lib/pci.h b/tests/kvm-unit-tests/lib/pci.h index 03cc0a72..689f03ca 100644 --- a/tests/kvm-unit-tests/lib/pci.h +++ b/tests/kvm-unit-tests/lib/pci.h @@ -18,6 +18,9 @@ enum { #define PCI_BAR_NUM 6 #define PCI_DEVFN_MAX 256 +#define ASSERT_BAR_NUM(bar_num) \ + do { assert(bar_num >= 0 && bar_num < PCI_BAR_NUM); } while (0) + #define PCI_BDF_GET_DEVFN(x) ((x) & 0xff) #define PCI_BDF_GET_BUS(x) (((x) >> 8) & 0xff) diff --git a/tests/kvm-unit-tests/lib/printf.c b/tests/kvm-unit-tests/lib/printf.c index 2aec59aa..1269723e 100644 --- a/tests/kvm-unit-tests/lib/printf.c +++ b/tests/kvm-unit-tests/lib/printf.c @@ -1,3 +1,10 @@ +/* + * libc printf and friends + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License version 2. + */ + #include "libcflat.h" #define BUFSZ 2000 @@ -11,6 +18,7 @@ typedef struct pstream { typedef struct strprops { char pad; int npad; + bool alternate; } strprops_t; static void addchar(pstream_t *p, char c) @@ -22,7 +30,7 @@ static void addchar(pstream_t *p, char c) ++p->added; } -void print_str(pstream_t *p, const char *s, strprops_t props) +static void print_str(pstream_t *p, const char *s, strprops_t props) { const char *s_orig = s; int npad = props.npad; @@ -50,7 +58,7 @@ void print_str(pstream_t *p, const char *s, strprops_t props) static char digits[16] = "0123456789abcdef"; -void print_int(pstream_t *ps, long long n, int base, strprops_t props) +static void print_int(pstream_t *ps, long long n, int base, strprops_t props) { char buf[sizeof(long) * 3 + 2], *p = buf; int s = 0, i; @@ -84,10 +92,10 @@ void print_int(pstream_t *ps, long long n, int base, strprops_t props) print_str(ps, buf, props); } -void print_unsigned(pstream_t *ps, unsigned long long n, int base, - strprops_t props) +static void print_unsigned(pstream_t *ps, unsigned long long n, int base, + strprops_t props) { - char buf[sizeof(long) * 3 + 1], *p = buf; + char buf[sizeof(long) * 3 + 3], *p = buf; int i; while (n) { @@ -97,6 +105,18 @@ void print_unsigned(pstream_t *ps, unsigned long long n, int base, if (p == buf) *p++ = '0'; + else if (props.alternate && base == 16) { + if (props.pad == '0') { + addchar(ps, '0'); + addchar(ps, 'x'); + + if (props.npad > 0) + props.npad = MAX(props.npad - 2, 0); + } else { + *p++ = 'x'; + *p++ = '0'; + } + } for (i = 0; i < (p - buf) / 2; ++i) { char tmp; @@ -157,6 +177,9 @@ int vsnprintf(char *buf, int size, const char *fmt, va_list va) case '\0': --fmt; break; + case '#': + props.alternate = true; + goto morefmt; case '0': props.pad = '0'; ++fmt; @@ -169,6 +192,15 @@ int vsnprintf(char *buf, int size, const char *fmt, va_list va) case 'l': ++nlong; goto morefmt; + case 't': + case 'z': + /* Here we only care that sizeof(size_t) == sizeof(long). + * On a 32-bit platform it doesn't matter that size_t is + * typedef'ed to int or long; va_arg will work either way. + * Same for ptrdiff_t (%td). + */ + nlong = 1; + goto morefmt; case 'd': switch (nlong) { case 0: @@ -209,7 +241,7 @@ int vsnprintf(char *buf, int size, const char *fmt, va_list va) } break; case 'p': - print_str(&s, "0x", props); + props.alternate = true; print_unsigned(&s, (unsigned long)va_arg(va, void *), 16, props); break; case 's': @@ -221,7 +253,6 @@ int vsnprintf(char *buf, int size, const char *fmt, va_list va) } } *s.buffer = 0; - ++s.added; return s.added; } @@ -259,3 +290,33 @@ int printf(const char *fmt, ...) puts(buf); return r; } + +void binstr(unsigned long x, char out[BINSTR_SZ]) +{ + int i; + char *c; + int n; + + n = sizeof(unsigned long) * 8; + i = 0; + c = &out[0]; + for (;;) { + *c++ = (x & (1ul << (n - i - 1))) ? '1' : '0'; + i++; + + if (i == n) { + *c = '\0'; + break; + } + if (i % 4 == 0) + *c++ = '\''; + } + assert(c + 1 - &out[0] == BINSTR_SZ); +} + +void print_binstr(unsigned long x) +{ + char out[BINSTR_SZ]; + binstr(x, out); + printf("%s", out); +} diff --git a/tests/kvm-unit-tests/lib/report.c b/tests/kvm-unit-tests/lib/report.c index e24e8138..5da27ab3 100644 --- a/tests/kvm-unit-tests/lib/report.c +++ b/tests/kvm-unit-tests/lib/report.c @@ -17,14 +17,49 @@ static unsigned int tests, failures, xfailures, skipped; static char prefixes[256]; static struct spinlock lock; -void report_prefix_push(const char *prefix) +#define PREFIX_DELIMITER ": " + +void report_pass(void) { spin_lock(&lock); - strcat(prefixes, prefix); - strcat(prefixes, ": "); + tests++; spin_unlock(&lock); } +void report_prefix_pushf(const char *prefix_fmt, ...) +{ + va_list va; + unsigned int len; + int start; + + spin_lock(&lock); + + len = strlen(prefixes); + assert_msg(len < sizeof(prefixes), "%d >= %zu", len, sizeof(prefixes)); + start = len; + + va_start(va, prefix_fmt); + len += vsnprintf(&prefixes[len], sizeof(prefixes) - len, prefix_fmt, + va); + va_end(va); + assert_msg(len < sizeof(prefixes), "%d >= %zu", len, sizeof(prefixes)); + + assert_msg(!strstr(&prefixes[start], PREFIX_DELIMITER), + "Prefix \"%s\" contains delimiter \"" PREFIX_DELIMITER "\"", + &prefixes[start]); + + len += snprintf(&prefixes[len], sizeof(prefixes) - len, + PREFIX_DELIMITER); + assert_msg(len < sizeof(prefixes), "%d >= %zu", len, sizeof(prefixes)); + + spin_unlock(&lock); +} + +void report_prefix_push(const char *prefix) +{ + report_prefix_pushf("%s", prefix); +} + void report_prefix_pop(void) { char *p, *q; @@ -34,9 +69,9 @@ void report_prefix_pop(void) if (!*prefixes) return; - for (p = prefixes, q = strstr(p, ": ") + 2; + for (p = prefixes, q = strstr(p, PREFIX_DELIMITER) + 2; *q; - p = q, q = strstr(p, ": ") + 2) + p = q, q = strstr(p, PREFIX_DELIMITER) + 2) ; *p = '\0'; @@ -46,9 +81,9 @@ void report_prefix_pop(void) static void va_report(const char *msg_fmt, bool pass, bool xfail, bool skip, va_list va) { - char *prefix = skip ? "SKIP" - : xfail ? (pass ? "XPASS" : "XFAIL") - : (pass ? "PASS" : "FAIL"); + const char *prefix = skip ? "SKIP" + : xfail ? (pass ? "XPASS" : "XFAIL") + : (pass ? "PASS" : "FAIL"); spin_lock(&lock); diff --git a/tests/kvm-unit-tests/lib/setjmp.h b/tests/kvm-unit-tests/lib/setjmp.h index 334f466f..2c56b4c6 100644 --- a/tests/kvm-unit-tests/lib/setjmp.h +++ b/tests/kvm-unit-tests/lib/setjmp.h @@ -1,3 +1,9 @@ +/* + * setjmp/longjmp prototypes + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License version 2. + */ #ifndef LIBCFLAT_SETJMP_H #define LIBCFLAT_SETJMP_H 1 diff --git a/tests/kvm-unit-tests/lib/stack.c b/tests/kvm-unit-tests/lib/stack.c index b0a02950..bdb23fde 100644 --- a/tests/kvm-unit-tests/lib/stack.c +++ b/tests/kvm-unit-tests/lib/stack.c @@ -1,3 +1,10 @@ +/* + * stack related functions + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License version 2. + */ + #include #include diff --git a/tests/kvm-unit-tests/lib/stack.h b/tests/kvm-unit-tests/lib/stack.h index cfc66f44..10fc2f79 100644 --- a/tests/kvm-unit-tests/lib/stack.h +++ b/tests/kvm-unit-tests/lib/stack.h @@ -1,3 +1,9 @@ +/* + * Header for stack related functions + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License version 2. + */ #ifndef _STACK_H_ #define _STACK_H_ diff --git a/tests/kvm-unit-tests/lib/string.c b/tests/kvm-unit-tests/lib/string.c index 833f22be..018dcc87 100644 --- a/tests/kvm-unit-tests/lib/string.c +++ b/tests/kvm-unit-tests/lib/string.c @@ -1,3 +1,10 @@ +/* + * libc string functions + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License version 2. + */ + #include "libcflat.h" unsigned long strlen(const char *buf) @@ -173,3 +180,44 @@ char *getenv(const char *name) } return NULL; } + +/* Very simple glob matching. Allows '*' at beginning and end of pattern. */ +bool simple_glob(const char *text, const char *pattern) +{ + bool star_start = false; + bool star_end = false; + size_t n = strlen(pattern); + char copy[n + 1]; + + if (pattern[0] == '*') { + pattern += 1; + n -= 1; + star_start = true; + } + + strcpy(copy, pattern); + + if (n > 0 && pattern[n - 1] == '*') { + n -= 1; + copy[n] = '\0'; + star_end = true; + } + + if (star_start && star_end) + return strstr(text, copy); + + if (star_end) + return strstr(text, copy) == text; + + if (star_start) { + size_t text_len = strlen(text); + const char *suffix; + + if (n > text_len) + return false; + suffix = text + text_len - n; + return !strcmp(suffix, copy); + } + + return !strcmp(text, copy); +} diff --git a/tests/kvm-unit-tests/lib/string.h b/tests/kvm-unit-tests/lib/string.h index 2391013a..493d51ba 100644 --- a/tests/kvm-unit-tests/lib/string.h +++ b/tests/kvm-unit-tests/lib/string.h @@ -1,3 +1,9 @@ +/* + * Header for libc string functions + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License version 2. + */ #ifndef __STRING_H #define __STRING_H diff --git a/tests/kvm-unit-tests/lib/util.c b/tests/kvm-unit-tests/lib/util.c index 69b18100..a9055413 100644 --- a/tests/kvm-unit-tests/lib/util.c +++ b/tests/kvm-unit-tests/lib/util.c @@ -4,6 +4,7 @@ * This work is licensed under the terms of the GNU LGPL, version 2. */ #include +#include "util.h" int parse_keyval(char *s, long *val) { diff --git a/tests/kvm-unit-tests/lib/virtio-mmio.c b/tests/kvm-unit-tests/lib/virtio-mmio.c index fa8dd5b8..e4a92f19 100644 --- a/tests/kvm-unit-tests/lib/virtio-mmio.c +++ b/tests/kvm-unit-tests/lib/virtio-mmio.c @@ -1,9 +1,9 @@ /* * virtqueue support adapted from the Linux kernel. * - * Copyright (C) 2014, Red Hat Inc, Andrew Jones + * Copyright (C) 2017, Red Hat Inc, Andrew Jones * - * This work is licensed under the terms of the GNU LGPL, version 2. + * This work is licensed under the terms of the GNU GPL, version 2. */ #include "libcflat.h" #include "devicetree.h" diff --git a/tests/kvm-unit-tests/lib/virtio-mmio.h b/tests/kvm-unit-tests/lib/virtio-mmio.h index 8046a474..250f28a0 100644 --- a/tests/kvm-unit-tests/lib/virtio-mmio.h +++ b/tests/kvm-unit-tests/lib/virtio-mmio.h @@ -3,9 +3,9 @@ /* * A minimal implementation of virtio-mmio. Adapted from the Linux Kernel. * - * Copyright (C) 2014, Red Hat Inc, Andrew Jones + * Copyright (C) 2017, Red Hat Inc, Andrew Jones * - * This work is licensed under the terms of the GNU LGPL, version 2. + * This work is licensed under the terms of the GNU GPL, version 2. */ #include "libcflat.h" #include "asm/page.h" diff --git a/tests/kvm-unit-tests/lib/virtio.c b/tests/kvm-unit-tests/lib/virtio.c index 9532d1ae..69054757 100644 --- a/tests/kvm-unit-tests/lib/virtio.c +++ b/tests/kvm-unit-tests/lib/virtio.c @@ -1,9 +1,9 @@ /* * virtqueue support adapted from the Linux kernel. * - * Copyright (C) 2014, Red Hat Inc, Andrew Jones + * Copyright (C) 2017, Red Hat Inc, Andrew Jones * - * This work is licensed under the terms of the GNU LGPL, version 2. + * This work is licensed under the terms of the GNU GPL, version 2. */ #include "libcflat.h" #include "asm/io.h" diff --git a/tests/kvm-unit-tests/lib/virtio.h b/tests/kvm-unit-tests/lib/virtio.h index 4801e204..2c31fdc7 100644 --- a/tests/kvm-unit-tests/lib/virtio.h +++ b/tests/kvm-unit-tests/lib/virtio.h @@ -4,9 +4,9 @@ * A minimal implementation of virtio. * Structures adapted from the Linux Kernel. * - * Copyright (C) 2014, Red Hat Inc, Andrew Jones + * Copyright (C) 2017, Red Hat Inc, Andrew Jones * - * This work is licensed under the terms of the GNU LGPL, version 2. + * This work is licensed under the terms of the GNU GPL, version 2. */ #include "libcflat.h" diff --git a/tests/kvm-unit-tests/lib/x86/asm/page.h b/tests/kvm-unit-tests/lib/x86/asm/page.h index c43bab28..562594df 100644 --- a/tests/kvm-unit-tests/lib/x86/asm/page.h +++ b/tests/kvm-unit-tests/lib/x86/asm/page.h @@ -31,6 +31,8 @@ #define PT64_NX_MASK (1ull << 63) #define PT_ADDR_MASK GENMASK_ULL(51, 12) +#define PT_AD_MASK (PT_ACCESSED_MASK | PT_DIRTY_MASK) + #ifdef __x86_64__ #define PAGE_LEVEL 4 #define PGDIR_WIDTH 9 diff --git a/tests/kvm-unit-tests/lib/x86/asm/spinlock.h b/tests/kvm-unit-tests/lib/x86/asm/spinlock.h index 4b0cb331..692020c5 100644 --- a/tests/kvm-unit-tests/lib/x86/asm/spinlock.h +++ b/tests/kvm-unit-tests/lib/x86/asm/spinlock.h @@ -1,11 +1,6 @@ #ifndef __ASM_SPINLOCK_H #define __ASM_SPINLOCK_H -struct spinlock { - int v; -}; - -void spin_lock(struct spinlock *lock); -void spin_unlock(struct spinlock *lock); +#include #endif diff --git a/tests/kvm-unit-tests/lib/x86/desc.c b/tests/kvm-unit-tests/lib/x86/desc.c index 402204dd..a5272916 100644 --- a/tests/kvm-unit-tests/lib/x86/desc.c +++ b/tests/kvm-unit-tests/lib/x86/desc.c @@ -69,7 +69,7 @@ static void unhandled_exception(struct ex_regs *regs, bool cpu) cpu ? "cpu " : "", regs->vector, exception_mnemonic(regs->vector), regs->rip); if (regs->vector == 14) - printf("PF at 0x%lx addr 0x%lx\n", regs->rip, read_cr2()); + printf("PF at %#lx addr %#lx\n", regs->rip, read_cr2()); printf("error_code=%04lx rflags=%08lx cs=%08lx\n" "rax=%016lx rcx=%016lx rdx=%016lx rbx=%016lx\n" @@ -117,13 +117,16 @@ static void check_exception_table(struct ex_regs *regs) unhandled_exception(regs, false); } -static void (*exception_handlers[32])(struct ex_regs *regs); +static handler exception_handlers[32]; - -void handle_exception(u8 v, void (*func)(struct ex_regs *regs)) +handler handle_exception(u8 v, handler fn) { + handler old; + + old = exception_handlers[v]; if (v < 32) - exception_handlers[v] = func; + exception_handlers[v] = fn; + return old; } #ifndef __x86_64__ @@ -262,19 +265,6 @@ bool exception_rflags_rf(void) static char intr_alt_stack[4096]; #ifndef __x86_64__ -/* - * GDT, with 6 entries: - * 0x00 - NULL descriptor - * 0x08 - Code segment (ring 0) - * 0x10 - Data segment (ring 0) - * 0x18 - Not present code segment (ring 0) - * 0x20 - Code segment (ring 3) - * 0x28 - Data segment (ring 3) - * 0x30 - Interrupt task - * 0x38 to 0x78 - Free to use for test cases - * 0x80 - Primary task (CPU 0) - */ - void set_gdt_entry(int sel, u32 base, u32 limit, u8 access, u8 gran) { int num = sel >> 3; @@ -385,19 +375,21 @@ static void exception_handler(struct ex_regs *regs) /* longjmp must happen after iret, so do not do it now. */ exception = true; regs->rip = (unsigned long)&exception_handler_longjmp; + regs->cs = read_cs(); } bool test_for_exception(unsigned int ex, void (*trigger_func)(void *data), void *data) { + handler old; jmp_buf jmpbuf; int ret; - handle_exception(ex, exception_handler); + old = handle_exception(ex, exception_handler); ret = set_exception_jmpbuf(jmpbuf); if (ret == 0) trigger_func(data); - handle_exception(ex, NULL); + handle_exception(ex, old); return ret; } diff --git a/tests/kvm-unit-tests/lib/x86/desc.h b/tests/kvm-unit-tests/lib/x86/desc.h index be52fd4e..3bf8fbe5 100644 --- a/tests/kvm-unit-tests/lib/x86/desc.h +++ b/tests/kvm-unit-tests/lib/x86/desc.h @@ -20,6 +20,8 @@ struct ex_regs { unsigned long rflags; }; +typedef void (*handler)(struct ex_regs *regs); + typedef struct { u16 prev; u16 res1; @@ -85,24 +87,59 @@ typedef struct __attribute__((packed)) { #define UD_VECTOR 6 #define GP_VECTOR 13 -#define KERNEL_CS 0x08 -#define KERNEL_DS 0x10 -#define NP_SEL 0x18 -#define USER_CS 0x23 -#define USER_DS 0x2b +/* + * selector 32-bit 64-bit + * 0x00 NULL descriptor NULL descriptor + * 0x08 ring-0 code segment (32-bit) ring-0 code segment (64-bit) + * 0x10 ring-0 data segment (32-bit) ring-0 data segment (32/64-bit) + * 0x18 ring-0 code segment (P=0) ring-0 code segment (64-bit, P=0) + * 0x20 intr_alt_stack TSS ring-0 code segment (32-bit) + * 0x28 ring-0 code segment (16-bit) same + * 0x30 ring-0 data segment (16-bit) same + * 0x38 (0x3b) ring-3 code segment (32-bit) same + * 0x40 (0x43) ring-3 data segment (32-bit) ring-3 data segment (32/64-bit) + * 0x48 (0x4b) **unused** ring-3 code segment (64-bit) + * 0x50--0x78 free to use for test cases same + * 0x80 primary TSS (CPU 0) same + * + * Note that the same segment can be used for 32-bit and 64-bit data segments + * (the L bit is only defined for code segments) + * + * Selectors 0x08-0x10 and 0x3b-0x4b are set up for use with the SYSCALL + * and SYSRET instructions. + */ + +#define KERNEL_CS 0x08 +#define KERNEL_DS 0x10 +#define NP_SEL 0x18 +#ifdef __x86_64__ +#define KERNEL_CS32 0x20 +#else +#define TSS_INTR 0x20 +#endif +#define KERNEL_CS16 0x28 +#define KERNEL_DS16 0x30 +#define USER_CS32 0x3b +#define USER_DS 0x43 +#ifdef __x86_64__ +#define USER_CS64 0x4b +#endif + +/* Synonyms */ +#define KERNEL_DS32 KERNEL_DS +#define USER_DS32 USER_DS + #ifdef __x86_64__ #define KERNEL_CS64 KERNEL_CS +#define USER_CS USER_CS64 #define KERNEL_DS64 KERNEL_DS -#define KERNEL_CS32 0x30 -#define KERNEL_DS32 0x38 -#define KERNEL_CS16 0x40 -#define KERNEL_DS16 0x48 +#define USER_DS64 USER_DS #else #define KERNEL_CS32 KERNEL_CS -#define KERNEL_DS32 KERNEL_DS +#define USER_CS USER_CS32 #endif -#define TSS_INTR 0x50 -#define FIRST_SPARE_SEL 0x58 + +#define FIRST_SPARE_SEL 0x50 #define TSS_MAIN 0x80 typedef struct { @@ -153,7 +190,7 @@ void set_idt_dpl(int vec, u16 dpl); void set_gdt_entry(int sel, u32 base, u32 limit, u8 access, u8 gran); void set_intr_alt_stack(int e, void *fn); void print_current_tss_info(void); -void handle_exception(u8 v, void (*func)(struct ex_regs *regs)); +handler handle_exception(u8 v, handler fn); bool test_for_exception(unsigned int ex, void (*trigger_func)(void *data), void *data); diff --git a/tests/kvm-unit-tests/lib/x86/fwcfg.c b/tests/kvm-unit-tests/lib/x86/fwcfg.c index e2cdd157..c52b4452 100644 --- a/tests/kvm-unit-tests/lib/x86/fwcfg.c +++ b/tests/kvm-unit-tests/lib/x86/fwcfg.c @@ -3,7 +3,7 @@ static struct spinlock lock; -uint64_t fwcfg_get_u(uint16_t index, int bytes) +static uint64_t fwcfg_get_u(uint16_t index, int bytes) { uint64_t r = 0; uint8_t b; diff --git a/tests/kvm-unit-tests/lib/x86/intel-iommu.c b/tests/kvm-unit-tests/lib/x86/intel-iommu.c index 7cc5a702..9fdbd3ba 100644 --- a/tests/kvm-unit-tests/lib/x86/intel-iommu.c +++ b/tests/kvm-unit-tests/lib/x86/intel-iommu.c @@ -115,9 +115,9 @@ static void vtd_dump_init_info(void) /* Major version >= 1 */ assert(((version >> 3) & 0xf) >= 1); - printf("VT-d version: 0x%x\n", version); - printf(" cap: 0x%016lx\n", vtd_readq(DMAR_CAP_REG)); - printf(" ecap: 0x%016lx\n", vtd_readq(DMAR_ECAP_REG)); + printf("VT-d version: %#x\n", version); + printf(" cap: %#018lx\n", vtd_readq(DMAR_CAP_REG)); + printf(" ecap: %#018lx\n", vtd_readq(DMAR_ECAP_REG)); } static void vtd_setup_root_table(void) @@ -127,7 +127,7 @@ static void vtd_setup_root_table(void) memset(root, 0, PAGE_SIZE); vtd_writeq(DMAR_RTADDR_REG, virt_to_phys(root)); vtd_gcmd_or(VTD_GCMD_ROOT); - printf("DMAR table address: 0x%016lx\n", vtd_root_table()); + printf("DMAR table address: %#018lx\n", vtd_root_table()); } static void vtd_setup_ir_table(void) @@ -138,7 +138,7 @@ static void vtd_setup_ir_table(void) /* 0xf stands for table size (2^(0xf+1) == 65536) */ vtd_writeq(DMAR_IRTA_REG, virt_to_phys(root) | 0xf); vtd_gcmd_or(VTD_GCMD_IR_TABLE); - printf("IR table address: 0x%016lx\n", vtd_ir_table()); + printf("IR table address: %#018lx\n", vtd_ir_table()); } static void vtd_install_pte(vtd_pte_t *root, iova_t iova, @@ -219,14 +219,14 @@ void vtd_map_range(uint16_t sid, iova_t iova, phys_addr_t pa, size_t size) ce->present = 1; /* No error reporting yet */ ce->disable_fault_report = 1; - printf("allocated vt-d context entry for devfn 0x%x\n", + printf("allocated vt-d context entry for devfn %#x\n", devfn); } else slptptr = phys_to_virt(ce->slptptr << VTD_PAGE_SHIFT); while (size) { /* TODO: currently we only map 4K pages (level = 1) */ - printf("map 4K page IOVA 0x%lx to 0x%lx (sid=0x%04x)\n", + printf("map 4K page IOVA %#lx to %#lx (sid=%#06x)\n", iova, pa, sid); vtd_install_pte(slptptr, iova, pa, 1); size -= VTD_PAGE_SIZE; @@ -324,7 +324,7 @@ bool vtd_setup_msi(struct pci_dev *dev, int vector, int dest_id) msi_addr.head = 0xfee; msi_data.subhandle = 0; - printf("%s: msi_addr=0x%" PRIx64 ", msi_data=0x%x\n", __func__, + printf("%s: msi_addr=%#" PRIx64 ", msi_data=%#x\n", __func__, *(uint64_t *)&msi_addr, *(uint32_t *)&msi_data); return pci_setup_msi(dev, *(uint64_t *)&msi_addr, diff --git a/tests/kvm-unit-tests/lib/x86/processor.h b/tests/kvm-unit-tests/lib/x86/processor.h index 895d992a..e658d83a 100644 --- a/tests/kvm-unit-tests/lib/x86/processor.h +++ b/tests/kvm-unit-tests/lib/x86/processor.h @@ -30,13 +30,18 @@ #define X86_CR4_SMAP 0x00200000 #define X86_CR4_PKE 0x00400000 -#define X86_EFLAGS_CF 0x00000001 -#define X86_EFLAGS_PF 0x00000004 -#define X86_EFLAGS_AF 0x00000010 -#define X86_EFLAGS_ZF 0x00000040 -#define X86_EFLAGS_SF 0x00000080 -#define X86_EFLAGS_OF 0x00000800 -#define X86_EFLAGS_AC 0x00040000 +#define X86_EFLAGS_CF 0x00000001 +#define X86_EFLAGS_FIXED 0x00000002 +#define X86_EFLAGS_PF 0x00000004 +#define X86_EFLAGS_AF 0x00000010 +#define X86_EFLAGS_ZF 0x00000040 +#define X86_EFLAGS_SF 0x00000080 +#define X86_EFLAGS_TF 0x00000100 +#define X86_EFLAGS_IF 0x00000200 +#define X86_EFLAGS_DF 0x00000400 +#define X86_EFLAGS_OF 0x00000800 +#define X86_EFLAGS_NT 0x00004000 +#define X86_EFLAGS_AC 0x00040000 #define X86_IA32_EFER 0xc0000080 #define X86_EFER_LMA (1UL << 8) @@ -430,4 +435,9 @@ static inline void write_pkru(u32 pkru) : : "a" (eax), "c" (ecx), "d" (edx)); } +static inline bool is_canonical(u64 addr) +{ + return (s64)(addr << 16) >> 16 == addr; +} + #endif diff --git a/tests/kvm-unit-tests/lib/x86/smp.c b/tests/kvm-unit-tests/lib/x86/smp.c index 1eb49f24..bffb6dec 100644 --- a/tests/kvm-unit-tests/lib/x86/smp.c +++ b/tests/kvm-unit-tests/lib/x86/smp.c @@ -1,5 +1,7 @@ #include +#include "processor.h" +#include "atomic.h" #include "smp.h" #include "apic.h" #include "fwcfg.h" @@ -15,6 +17,7 @@ static void *volatile ipi_data; static volatile int ipi_done; static volatile bool ipi_wait; static int _cpu_count; +static atomic_t active_cpus; static __attribute__((used)) void ipi() { @@ -27,6 +30,7 @@ static __attribute__((used)) void ipi() apic_write(APIC_EOI, 0); } function(data); + atomic_dec(&active_cpus); if (wait) { ipi_done = 1; apic_write(APIC_EOI, 0); @@ -43,22 +47,6 @@ asm ( #endif ); -void spin_lock(struct spinlock *lock) -{ - int v = 1; - - do { - asm volatile ("xchg %1, %0" : "+m"(lock->v), "+r"(v)); - } while (v); - asm volatile ("" : : : "memory"); -} - -void spin_unlock(struct spinlock *lock) -{ - asm volatile ("" : : : "memory"); - lock->v = 0; -} - int cpu_count(void) { return _cpu_count; @@ -84,6 +72,7 @@ static void __on_cpu(int cpu, void (*function)(void *data), void *data, if (cpu == smp_id()) function(data); else { + atomic_inc(&active_cpus); ipi_done = 0; ipi_function = function; ipi_data = data; @@ -107,6 +96,21 @@ void on_cpu_async(int cpu, void (*function)(void *data), void *data) __on_cpu(cpu, function, data, 0); } +void on_cpus(void (*function)(void *data), void *data) +{ + int cpu; + + for (cpu = cpu_count() - 1; cpu >= 0; --cpu) + on_cpu_async(cpu, function, data); + + while (cpus_active() > 1) + pause(); +} + +int cpus_active(void) +{ + return atomic_read(&active_cpus); +} void smp_init(void) { @@ -122,4 +126,5 @@ void smp_init(void) for (i = 1; i < cpu_count(); ++i) on_cpu(i, setup_smp_id, 0); + atomic_inc(&active_cpus); } diff --git a/tests/kvm-unit-tests/lib/x86/smp.h b/tests/kvm-unit-tests/lib/x86/smp.h index afabac84..1453bb5e 100644 --- a/tests/kvm-unit-tests/lib/x86/smp.h +++ b/tests/kvm-unit-tests/lib/x86/smp.h @@ -6,7 +6,9 @@ void smp_init(void); int cpu_count(void); int smp_id(void); +int cpus_active(void); void on_cpu(int cpu, void (*function)(void *data), void *data); void on_cpu_async(int cpu, void (*function)(void *data), void *data); +void on_cpus(void (*function)(void *data), void *data); #endif diff --git a/tests/kvm-unit-tests/lib/x86/vm.c b/tests/kvm-unit-tests/lib/x86/vm.c index cda4c5f4..9b5f9220 100644 --- a/tests/kvm-unit-tests/lib/x86/vm.c +++ b/tests/kvm-unit-tests/lib/x86/vm.c @@ -7,12 +7,29 @@ static void *vfree_top = 0; static void free_memory(void *mem, unsigned long size) { - while (size >= PAGE_SIZE) { - *(void **)mem = free; + void *end; + + assert_msg((unsigned long) mem % PAGE_SIZE == 0, + "mem not page aligned: %p", mem); + + assert_msg(size % PAGE_SIZE == 0, "size not page aligned: %#lx", size); + + assert_msg(size == 0 || mem + size > mem, + "mem + size overflow: %p + %#lx", mem, size); + + if (size == 0) { + free = NULL; + return; + } + free = mem; - mem += PAGE_SIZE; - size -= PAGE_SIZE; - } + end = mem + size; + while (mem + PAGE_SIZE != end) { + *(void **)mem = (mem + PAGE_SIZE); + mem += PAGE_SIZE; + } + + *(void **)mem = NULL; } void *alloc_page() @@ -28,6 +45,63 @@ void *alloc_page() return p; } +/* + * Allocates (1 << order) physically contiguous and naturally aligned pages. + * Returns NULL if there's no memory left. + */ +void *alloc_pages(unsigned long order) +{ + /* Generic list traversal. */ + void *prev; + void *curr = NULL; + void *next = free; + + /* Looking for a run of length (1 << order). */ + unsigned long run = 0; + const unsigned long n = 1ul << order; + const unsigned long align_mask = (n << PAGE_SHIFT) - 1; + void *run_start = NULL; + void *run_prev = NULL; + unsigned long run_next_pa = 0; + unsigned long pa; + + assert(order < sizeof(unsigned long) * 8); + + for (;;) { + prev = curr; + curr = next; + next = curr ? *((void **) curr) : NULL; + + if (!curr) + return 0; + + pa = virt_to_phys(curr); + + if (run == 0) { + if (!(pa & align_mask)) { + run_start = curr; + run_prev = prev; + run_next_pa = pa + PAGE_SIZE; + run = 1; + } + } else if (pa == run_next_pa) { + run_next_pa += PAGE_SIZE; + run += 1; + } else { + run = 0; + } + + if (run == n) { + if (run_prev) + *((void **) run_prev) = next; + else + free = next; + return run_start; + } + } +} + + void free_page(void *page) { *(void **)page = free; @@ -65,23 +139,62 @@ unsigned long *install_pte(unsigned long *cr3, return &pt[offset]; } +/* + * Finds last PTE in the mapping of @virt that's at or above @lowest_level. The + * returned PTE isn't necessarily present, but its parent is. + */ +struct pte_search find_pte_level(unsigned long *cr3, void *virt, + int lowest_level) +{ + unsigned long *pt = cr3, pte; + unsigned offset; + unsigned long shift; + struct pte_search r; + + assert(lowest_level >= 1 && lowest_level <= PAGE_LEVEL); + + for (r.level = PAGE_LEVEL;; --r.level) { + shift = (r.level - 1) * PGDIR_WIDTH + 12; + offset = ((unsigned long)virt >> shift) & PGDIR_MASK; + r.pte = &pt[offset]; + pte = *r.pte; + + if (!(pte & PT_PRESENT_MASK)) + return r; + + if ((r.level == 2 || r.level == 3) && (pte & PT_PAGE_SIZE_MASK)) + return r; + + if (r.level == lowest_level) + return r; + + pt = phys_to_virt(pte & 0xffffffffff000ull); + } +} + +/* + * Returns the leaf PTE in the mapping of @virt (i.e., 4K PTE or a present huge + * PTE). Returns NULL if no leaf PTE exists. + */ unsigned long *get_pte(unsigned long *cr3, void *virt) { - int level; - unsigned long *pt = cr3, pte; - unsigned offset; + struct pte_search search; - for (level = PAGE_LEVEL; level > 1; --level) { - offset = ((unsigned long)virt >> (((level-1) * PGDIR_WIDTH) + 12)) & PGDIR_MASK; - pte = pt[offset]; - if (!(pte & PT_PRESENT_MASK)) - return NULL; - if (level == 2 && (pte & PT_PAGE_SIZE_MASK)) - return &pt[offset]; - pt = phys_to_virt(pte & PT_ADDR_MASK); - } - offset = ((unsigned long)virt >> (((level-1) * PGDIR_WIDTH) + 12)) & PGDIR_MASK; - return &pt[offset]; + search = find_pte_level(cr3, virt, 1); + return found_leaf_pte(search) ? search.pte : NULL; +} + +/* + * Returns the PTE in the mapping of @virt at the given level @pte_level. + * Returns NULL if the PT at @pte_level isn't present (i.e., the mapping at + * @pte_level - 1 isn't present). + */ +unsigned long *get_pte_level(unsigned long *cr3, void *virt, int pte_level) +{ + struct pte_search search; + + search = find_pte_level(cr3, virt, pte_level); + return search.level == pte_level ? search.pte : NULL; } unsigned long *install_large_page(unsigned long *cr3, @@ -99,6 +212,33 @@ unsigned long *install_page(unsigned long *cr3, return install_pte(cr3, 1, virt, phys | PT_PRESENT_MASK | PT_WRITABLE_MASK | PT_USER_MASK, 0); } +void install_pages(unsigned long *cr3, unsigned long phys, unsigned long len, + void *virt) +{ + unsigned long max = (u64)len + (u64)phys; + assert(phys % PAGE_SIZE == 0); + assert((unsigned long) virt % PAGE_SIZE == 0); + assert(len % PAGE_SIZE == 0); + + while (phys + PAGE_SIZE <= max) { + install_page(cr3, phys, virt); + phys += PAGE_SIZE; + virt = (char *) virt + PAGE_SIZE; + } +} + +bool any_present_pages(unsigned long *cr3, void *virt, unsigned long len) +{ + unsigned long max = (unsigned long) virt + len; + unsigned long curr; + + for (curr = (unsigned long) virt; curr < max; curr += PAGE_SIZE) { + unsigned long *ptep = get_pte(cr3, (void *) curr); + if (ptep && (*ptep & PT_PRESENT_MASK)) + return true; + } + return false; +} static void setup_mmu_range(unsigned long *cr3, unsigned long start, unsigned long len) @@ -110,10 +250,7 @@ static void setup_mmu_range(unsigned long *cr3, unsigned long start, install_large_page(cr3, phys, (void *)(ulong)phys); phys += LARGE_PAGE_SIZE; } - while (phys + PAGE_SIZE <= max) { - install_page(cr3, phys, (void *)(ulong)phys); - phys += PAGE_SIZE; - } + install_pages(cr3, phys, max - phys, (void *)(ulong)phys); } static void setup_mmu(unsigned long len) diff --git a/tests/kvm-unit-tests/lib/x86/vm.h b/tests/kvm-unit-tests/lib/x86/vm.h index 6a4384f5..3522ba8b 100644 --- a/tests/kvm-unit-tests/lib/x86/vm.h +++ b/tests/kvm-unit-tests/lib/x86/vm.h @@ -14,7 +14,27 @@ void *alloc_vpage(void); void *alloc_vpages(ulong nr); uint64_t virt_to_phys_cr3(void *mem); +struct pte_search { + int level; + unsigned long *pte; +}; + +static inline bool found_huge_pte(struct pte_search search) +{ + return (search.level == 2 || search.level == 3) && + (*search.pte & PT_PRESENT_MASK) && + (*search.pte & PT_PAGE_SIZE_MASK); +} + +static inline bool found_leaf_pte(struct pte_search search) +{ + return search.level == 1 || found_huge_pte(search); +} + +struct pte_search find_pte_level(unsigned long *cr3, void *virt, + int lowest_level); unsigned long *get_pte(unsigned long *cr3, void *virt); +unsigned long *get_pte_level(unsigned long *cr3, void *virt, int pte_level); unsigned long *install_pte(unsigned long *cr3, int pte_level, void *virt, @@ -22,10 +42,18 @@ unsigned long *install_pte(unsigned long *cr3, unsigned long *pt_page); void *alloc_page(); +void *alloc_pages(unsigned long order); void free_page(void *page); unsigned long *install_large_page(unsigned long *cr3,unsigned long phys, void *virt); unsigned long *install_page(unsigned long *cr3, unsigned long phys, void *virt); +void install_pages(unsigned long *cr3, unsigned long phys, unsigned long len, + void *virt); +bool any_present_pages(unsigned long *cr3, void *virt, unsigned long len); +static inline void *current_page_table(void) +{ + return phys_to_virt(read_cr3()); +} #endif diff --git a/tests/kvm-unit-tests/x86/Makefile b/tests/kvm-unit-tests/x86/Makefile index 369a38b2..8a007ab5 100644 --- a/tests/kvm-unit-tests/x86/Makefile +++ b/tests/kvm-unit-tests/x86/Makefile @@ -1 +1 @@ -include $(TEST_DIR)/Makefile.$(ARCH) +include $(SRCDIR)/$(TEST_DIR)/Makefile.$(ARCH) diff --git a/tests/kvm-unit-tests/x86/Makefile.common b/tests/kvm-unit-tests/x86/Makefile.common index fbab82c8..e96812bf 100644 --- a/tests/kvm-unit-tests/x86/Makefile.common +++ b/tests/kvm-unit-tests/x86/Makefile.common @@ -1,6 +1,6 @@ #This is a make file with common rules for both x86 & x86-64 -all: test_cases +all: directories test_cases cflatobjs += lib/pci.o cflatobjs += lib/pci-edu.o @@ -16,11 +16,13 @@ cflatobjs += lib/x86/isr.o cflatobjs += lib/x86/acpi.o cflatobjs += lib/x86/stack.o -$(libcflat): LDFLAGS += -nostdlib -$(libcflat): CFLAGS += -ffreestanding -I lib +OBJDIRS += lib/x86 -CFLAGS += -m$(bits) -CFLAGS += -O1 +$(libcflat): LDFLAGS += -nostdlib +$(libcflat): CFLAGS += -ffreestanding -I $(SRCDIR)/lib -I lib + +COMMON_CFLAGS += -m$(bits) +COMMON_CFLAGS += -O1 # stack.o relies on frame pointers. KEEP_FRAME_POINTER := y @@ -31,8 +33,8 @@ libgcc := $(shell $(CC) -m$(bits) --print-libgcc-file-name) .PRECIOUS: %.elf %.o FLATLIBS = lib/libcflat.a $(libgcc) -%.elf: %.o $(FLATLIBS) x86/flat.lds $(cstart.o) - $(CC) $(CFLAGS) -nostdlib -o $@ -Wl,-T,x86/flat.lds \ +%.elf: %.o $(FLATLIBS) $(SRCDIR)/x86/flat.lds $(cstart.o) + $(CC) $(CFLAGS) -nostdlib -o $@ -Wl,-T,$(SRCDIR)/x86/flat.lds \ $(filter %.o, $^) $(FLATLIBS) %.flat: %.elf @@ -47,19 +49,20 @@ tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \ $(TEST_DIR)/tsc_adjust.flat $(TEST_DIR)/asyncpf.flat \ $(TEST_DIR)/init.flat $(TEST_DIR)/smap.flat \ $(TEST_DIR)/hyperv_synic.flat $(TEST_DIR)/hyperv_stimer.flat \ + $(TEST_DIR)/hyperv_connections.flat \ ifdef API -tests-common += api/api-sample -tests-common += api/dirty-log -tests-common += api/dirty-log-perf +tests-api = api/api-sample api/dirty-log api/dirty-log-perf + +OBJDIRS += api endif -test_cases: $(tests-common) $(tests) +test_cases: $(tests-common) $(tests) $(tests-api) -$(TEST_DIR)/%.o: CFLAGS += -std=gnu99 -ffreestanding -I lib -I lib/x86 +$(TEST_DIR)/%.o: CFLAGS += -std=gnu99 -ffreestanding -I $(SRCDIR)/lib -I $(SRCDIR)/lib/x86 -I lib $(TEST_DIR)/realmode.elf: $(TEST_DIR)/realmode.o - $(CC) -m32 -nostdlib -o $@ -Wl,-T,$(TEST_DIR)/realmode.lds $^ + $(CC) -m32 -nostdlib -o $@ -Wl,-T,$(SRCDIR)/$(TEST_DIR)/realmode.lds $^ $(TEST_DIR)/realmode.o: bits = 32 @@ -69,20 +72,19 @@ $(TEST_DIR)/hyperv_synic.elf: $(TEST_DIR)/hyperv.o $(TEST_DIR)/hyperv_stimer.elf: $(TEST_DIR)/hyperv.o +$(TEST_DIR)/hyperv_connections.elf: $(TEST_DIR)/hyperv.o + arch_clean: $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \ - $(TEST_DIR)/.*.d lib/x86/.*.d + $(TEST_DIR)/.*.d lib/x86/.*.d \ + $(tests-api) api/*.o api/*.a api/.*.d -api/%.o: CFLAGS += -m32 +api/%.o: CXXFLAGS += -m32 -std=gnu++11 -api/%: LDLIBS += -lstdc++ -lboost_thread -lpthread -lrt +api/%: LDLIBS += -lstdc++ -lpthread -lrt api/%: LDFLAGS += -m32 api/libapi.a: api/kvmxx.o api/identity.o api/exception.o api/memmap.o $(AR) rcs $@ $^ -api/api-sample: api/api-sample.o api/libapi.a - -api/dirty-log: api/dirty-log.o api/libapi.a - -api/dirty-log-perf: api/dirty-log-perf.o api/libapi.a +$(tests-api) : % : %.o api/libapi.a diff --git a/tests/kvm-unit-tests/x86/Makefile.i386 b/tests/kvm-unit-tests/x86/Makefile.i386 index 5f89e3e5..c105cac6 100644 --- a/tests/kvm-unit-tests/x86/Makefile.i386 +++ b/tests/kvm-unit-tests/x86/Makefile.i386 @@ -30,4 +30,4 @@ tests += $(TEST_DIR)/tscdeadline_latency.flat #tests += $(TEST_DIR)/intel-iommu.flat -include $(TEST_DIR)/Makefile.common +include $(SRCDIR)/$(TEST_DIR)/Makefile.common diff --git a/tests/kvm-unit-tests/x86/Makefile.x86_64 b/tests/kvm-unit-tests/x86/Makefile.x86_64 index 3e2821ea..623fc5b3 100644 --- a/tests/kvm-unit-tests/x86/Makefile.x86_64 +++ b/tests/kvm-unit-tests/x86/Makefile.x86_64 @@ -1,7 +1,7 @@ cstart.o = $(TEST_DIR)/cstart64.o bits = 64 ldarch = elf64-x86-64 -CFLAGS += -mno-red-zone +COMMON_CFLAGS += -mno-red-zone cflatobjs += lib/x86/setjmp64.o cflatobjs += lib/x86/intel-iommu.o @@ -12,12 +12,13 @@ tests = $(TEST_DIR)/access.flat $(TEST_DIR)/apic.flat \ $(TEST_DIR)/pcid.flat $(TEST_DIR)/debug.flat \ $(TEST_DIR)/ioapic.flat $(TEST_DIR)/memory.flat \ $(TEST_DIR)/pku.flat $(TEST_DIR)/hyperv_clock.flat +tests += $(TEST_DIR)/syscall.flat tests += $(TEST_DIR)/svm.flat tests += $(TEST_DIR)/vmx.flat tests += $(TEST_DIR)/tscdeadline_latency.flat tests += $(TEST_DIR)/intel-iommu.flat -include $(TEST_DIR)/Makefile.common +include $(SRCDIR)/$(TEST_DIR)/Makefile.common $(TEST_DIR)/hyperv_clock.elf: $(TEST_DIR)/hyperv_clock.o diff --git a/tests/kvm-unit-tests/x86/asyncpf.c b/tests/kvm-unit-tests/x86/asyncpf.c index e29e07c5..f04d7cb5 100644 --- a/tests/kvm-unit-tests/x86/asyncpf.c +++ b/tests/kvm-unit-tests/x86/asyncpf.c @@ -52,13 +52,13 @@ static void pf_isr(struct ex_regs *r) switch (reason) { case 0: - report("unexpected #PF at %p", false, read_cr2()); + report("unexpected #PF at %#lx", false, read_cr2()); break; case KVM_PV_REASON_PAGE_NOT_PRESENT: phys = virt_to_phys_cr3(virt); install_pte(phys_to_virt(read_cr3()), 1, virt, phys, 0); write_cr3(read_cr3()); - report("Got not present #PF token %x virt addr %p phys addr %p", + report("Got not present #PF token %lx virt addr %p phys addr %#" PRIx64, true, read_cr2(), virt, phys); while(phys) { safe_halt(); /* enables irq */ @@ -66,7 +66,7 @@ static void pf_isr(struct ex_regs *r) } break; case KVM_PV_REASON_PAGE_READY: - report("Got present #PF token %x", true, read_cr2()); + report("Got present #PF token %lx", true, read_cr2()); if ((uint32_t)read_cr2() == ~0) break; install_pte(phys_to_virt(read_cr3()), 1, virt, phys | PT_PRESENT_MASK | PT_WRITABLE_MASK, 0); diff --git a/tests/kvm-unit-tests/x86/cstart.S b/tests/kvm-unit-tests/x86/cstart.S index 69b5c332..a3c26a41 100644 --- a/tests/kvm-unit-tests/x86/cstart.S +++ b/tests/kvm-unit-tests/x86/cstart.S @@ -34,14 +34,14 @@ gdt32: .quad 0x00cf9b000000ffff // flat 32-bit code segment .quad 0x00cf93000000ffff // flat 32-bit data segment .quad 0x00cf1b000000ffff // flat 32-bit code segment, not present - .quad 0x00cffb000000ffff // 64-bit code segment (user) - .quad 0x00cff3000000ffff // 64-bit data segment (user) + .quad 0 // TSS for task gates + .quad 0x008f9b000000FFFF // 16-bit code segment + .quad 0x008f93000000FFFF // 16-bit data segment + .quad 0x00cffb000000ffff // 32-bit code segment (user) + .quad 0x00cff3000000ffff // 32-bit data segment (user) + .quad 0 // unused - .quad 0 // 10 spare selectors - .quad 0 - .quad 0 - .quad 0 - .quad 0 + .quad 0 // 6 spare selectors .quad 0 .quad 0 .quad 0 diff --git a/tests/kvm-unit-tests/x86/cstart64.S b/tests/kvm-unit-tests/x86/cstart64.S index 004c014b..4c26fb25 100644 --- a/tests/kvm-unit-tests/x86/cstart64.S +++ b/tests/kvm-unit-tests/x86/cstart64.S @@ -53,14 +53,14 @@ gdt64_desc: gdt64: .quad 0 .quad 0x00af9b000000ffff // 64-bit code segment - .quad 0x00cf93000000ffff // 64-bit data segment + .quad 0x00cf93000000ffff // 32/64-bit data segment .quad 0x00af1b000000ffff // 64-bit code segment, not present - .quad 0x00affb000000ffff // 64-bit code segment (user) - .quad 0x00cff3000000ffff // 64-bit data segment (user) .quad 0x00cf9b000000ffff // 32-bit code segment - .quad 0x00cf92000000ffff // 32-bit data segment - .quad 0x008F9A000000FFFF // 16-bit code segment - .quad 0x008F92000000FFFF // 16-bit data segment + .quad 0x008f9b000000FFFF // 16-bit code segment + .quad 0x008f93000000FFFF // 16-bit data segment + .quad 0x00cffb000000ffff // 32-bit code segment (user) + .quad 0x00cff3000000ffff // 32/64-bit data segment (user) + .quad 0x00affb000000ffff // 64-bit code segment (user) .quad 0 // 6 spare selectors .quad 0 diff --git a/tests/kvm-unit-tests/x86/eventinj.c b/tests/kvm-unit-tests/x86/eventinj.c index 9ee557b8..665eb618 100644 --- a/tests/kvm-unit-tests/x86/eventinj.c +++ b/tests/kvm-unit-tests/x86/eventinj.c @@ -171,7 +171,7 @@ static void nmi_iret_isr(struct ex_regs *r) static void tirq0(isr_regs_t *r) { printf("irq0 running\n"); - if (test_count != 0) + if (test_count == 1) test_count++; eoi(); } diff --git a/tests/kvm-unit-tests/x86/hyperv.c b/tests/kvm-unit-tests/x86/hyperv.c index 2511aa2e..60f76455 100644 --- a/tests/kvm-unit-tests/x86/hyperv.c +++ b/tests/kvm-unit-tests/x86/hyperv.c @@ -1,25 +1,70 @@ #include "hyperv.h" #include "asm/io.h" +#include "smp.h" -static void synic_ctl(u8 ctl, u8 vcpu_id, u8 sint) +enum { + HV_TEST_DEV_SINT_ROUTE_CREATE = 1, + HV_TEST_DEV_SINT_ROUTE_DESTROY, + HV_TEST_DEV_SINT_ROUTE_SET_SINT, + HV_TEST_DEV_MSG_CONN_CREATE, + HV_TEST_DEV_MSG_CONN_DESTROY, + HV_TEST_DEV_EVT_CONN_CREATE, + HV_TEST_DEV_EVT_CONN_DESTROY, +}; + +static void synic_ctl(u32 ctl, u32 vcpu_id, u32 sint, u32 conn_id) { - outl((ctl << 16)|((vcpu_id) << 8)|sint, 0x3000); + outl((conn_id << 24) | (ctl << 16) | (vcpu_id << 8) | sint, 0x3000); } -void synic_sint_create(int vcpu, int sint, int vec, bool auto_eoi) +static void sint_enable(u8 sint, u8 vec, bool auto_eoi) { wrmsr(HV_X64_MSR_SINT0 + sint, - (u64)vec | ((auto_eoi) ? HV_SYNIC_SINT_AUTO_EOI : 0)); - synic_ctl(HV_TEST_DEV_SINT_ROUTE_CREATE, vcpu, sint); + (u64)vec | (auto_eoi ? HV_SYNIC_SINT_AUTO_EOI : 0)); } -void synic_sint_set(int vcpu, int sint) +static void sint_disable(u8 sint) { - synic_ctl(HV_TEST_DEV_SINT_ROUTE_SET_SINT, vcpu, sint); + wrmsr(HV_X64_MSR_SINT0 + sint, 0xff | HV_SYNIC_SINT_MASKED); } -void synic_sint_destroy(int vcpu, int sint) +void synic_sint_create(u8 sint, u8 vec, bool auto_eoi) { - wrmsr(HV_X64_MSR_SINT0 + sint, 0xFF|HV_SYNIC_SINT_MASKED); - synic_ctl(HV_TEST_DEV_SINT_ROUTE_DESTROY, vcpu, sint); + synic_ctl(HV_TEST_DEV_SINT_ROUTE_CREATE, smp_id(), sint, 0); + sint_enable(sint, vec, auto_eoi); +} + +void synic_sint_set(u8 vcpu, u8 sint) +{ + synic_ctl(HV_TEST_DEV_SINT_ROUTE_SET_SINT, vcpu, sint, 0); +} + +void synic_sint_destroy(u8 sint) +{ + sint_disable(sint); + synic_ctl(HV_TEST_DEV_SINT_ROUTE_DESTROY, smp_id(), sint, 0); +} + +void msg_conn_create(u8 sint, u8 vec, u8 conn_id) +{ + synic_ctl(HV_TEST_DEV_MSG_CONN_CREATE, smp_id(), sint, conn_id); + sint_enable(sint, vec, true); +} + +void msg_conn_destroy(u8 sint, u8 conn_id) +{ + sint_disable(sint); + synic_ctl(HV_TEST_DEV_MSG_CONN_DESTROY, 0, 0, conn_id); +} + +void evt_conn_create(u8 sint, u8 vec, u8 conn_id) +{ + synic_ctl(HV_TEST_DEV_EVT_CONN_CREATE, smp_id(), sint, conn_id); + sint_enable(sint, vec, true); +} + +void evt_conn_destroy(u8 sint, u8 conn_id) +{ + sint_disable(sint); + synic_ctl(HV_TEST_DEV_EVT_CONN_DESTROY, 0, 0, conn_id); } diff --git a/tests/kvm-unit-tests/x86/hyperv.h b/tests/kvm-unit-tests/x86/hyperv.h index bef03177..e135221f 100644 --- a/tests/kvm-unit-tests/x86/hyperv.h +++ b/tests/kvm-unit-tests/x86/hyperv.h @@ -10,6 +10,9 @@ #define HV_X64_MSR_SYNIC_AVAILABLE (1 << 2) #define HV_X64_MSR_SYNTIMER_AVAILABLE (1 << 3) +#define HV_X64_MSR_GUEST_OS_ID 0x40000000 +#define HV_X64_MSR_HYPERCALL 0x40000001 + #define HV_X64_MSR_TIME_REF_COUNT 0x40000020 #define HV_X64_MSR_REFERENCE_TSC 0x40000021 @@ -155,10 +158,29 @@ struct hv_message_page { struct hv_message sint_message[HV_SYNIC_SINT_COUNT]; }; -enum { - HV_TEST_DEV_SINT_ROUTE_CREATE = 1, - HV_TEST_DEV_SINT_ROUTE_DESTROY, - HV_TEST_DEV_SINT_ROUTE_SET_SINT +#define HV_EVENT_FLAGS_COUNT (256 * 8) + +struct hv_event_flags { + ulong flags[HV_EVENT_FLAGS_COUNT / (8 * sizeof(ulong))]; +}; + +struct hv_event_flags_page { + struct hv_event_flags slot[HV_SYNIC_SINT_COUNT]; +}; + +#define HV_X64_MSR_HYPERCALL_ENABLE 0x1 + +#define HV_HYPERCALL_FAST (1u << 16) + +#define HVCALL_POST_MESSAGE 0x5c +#define HVCALL_SIGNAL_EVENT 0x5d + +struct hv_input_post_message { + u32 connectionid; + u32 reserved; + u32 message_type; + u32 payload_size; + u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT]; }; static inline bool synic_supported(void) @@ -176,9 +198,13 @@ static inline bool hv_time_ref_counter_supported(void) return cpuid(HYPERV_CPUID_FEATURES).a & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE; } -void synic_sint_create(int vcpu, int sint, int vec, bool auto_eoi); -void synic_sint_set(int vcpu, int sint); -void synic_sint_destroy(int vcpu, int sint); +void synic_sint_create(u8 sint, u8 vec, bool auto_eoi); +void synic_sint_set(u8 vcpu, u8 sint); +void synic_sint_destroy(u8 sint); +void msg_conn_create(u8 sint, u8 vec, u8 conn_id); +void msg_conn_destroy(u8 sint, u8 conn_id); +void evt_conn_create(u8 sint, u8 vec, u8 conn_id); +void evt_conn_destroy(u8 sint, u8 conn_id); struct hv_reference_tsc_page { uint32_t tsc_sequence; diff --git a/tests/kvm-unit-tests/x86/hyperv_clock.c b/tests/kvm-unit-tests/x86/hyperv_clock.c index 8b1deba6..94972697 100644 --- a/tests/kvm-unit-tests/x86/hyperv_clock.c +++ b/tests/kvm-unit-tests/x86/hyperv_clock.c @@ -19,7 +19,7 @@ static inline u64 scale_delta(u64 delta, u64 mul_frac) u64 product, unused; __asm__ ( - "mul %3" + "mulq %3" : "=d" (product), "=a" (unused) : "1" (delta), "rm" ((u64)mul_frac) ); return product; @@ -55,7 +55,6 @@ uint64_t hv_clock_read(void) return hvclock_tsc_to_ticks(&shadow, rdtsc()); } -atomic_t cpus_left; bool ok[MAX_CPU]; uint64_t loops[MAX_CPU]; @@ -99,7 +98,6 @@ static void hv_clock_test(void *data) if (!got_drift) printf("delta on CPU %d was %d...%d\n", smp_id(), min_delta, max_delta); barrier(); - atomic_dec(&cpus_left); } static void check_test(int ncpus) @@ -107,13 +105,7 @@ static void check_test(int ncpus) int i; bool pass; - atomic_set(&cpus_left, ncpus); - for (i = ncpus - 1; i >= 0; i--) - on_cpu_async(i, hv_clock_test, NULL); - - /* Wait for the end of other vcpu */ - while(atomic_read(&cpus_left)) - ; + on_cpus(hv_clock_test, NULL); pass = true; for (i = ncpus - 1; i >= 0; i--) @@ -134,7 +126,6 @@ static void hv_perf_test(void *data) } while(t < end); loops[smp_id()] = local_loops; - atomic_dec(&cpus_left); } static void perf_test(int ncpus) @@ -142,13 +133,7 @@ static void perf_test(int ncpus) int i; uint64_t total_loops; - atomic_set(&cpus_left, ncpus); - for (i = ncpus - 1; i >= 0; i--) - on_cpu_async(i, hv_perf_test, NULL); - - /* Wait for the end of other vcpu */ - while(atomic_read(&cpus_left)) - ; + on_cpus(hv_perf_test, NULL); total_loops = 0; for (i = ncpus - 1; i >= 0; i--) @@ -167,6 +152,10 @@ int main(int ac, char **av) setup_vm(); smp_init(); + ncpus = cpu_count(); + if (ncpus > MAX_CPU) + report_abort("number cpus exceeds %d", MAX_CPU); + hv_clock = alloc_page(); wrmsr(HV_X64_MSR_REFERENCE_TSC, (u64)(uintptr_t)hv_clock | 1); report("MSR value after enabling", @@ -195,10 +184,6 @@ int main(int ac, char **av) "TSC reference %" PRId64" (delta %" PRId64")\n", ref2, ref2 - ref1, tsc2, t2, t2 - t1); - ncpus = cpu_count(); - if (ncpus > MAX_CPU) - ncpus = MAX_CPU; - check_test(ncpus); perf_test(ncpus); diff --git a/tests/kvm-unit-tests/x86/hyperv_stimer.c b/tests/kvm-unit-tests/x86/hyperv_stimer.c index 52925237..bd7f9663 100644 --- a/tests/kvm-unit-tests/x86/hyperv_stimer.c +++ b/tests/kvm-unit-tests/x86/hyperv_stimer.c @@ -19,8 +19,6 @@ #define SINT2_NUM 3 #define ONE_MS_IN_100NS 10000 -static atomic_t g_cpus_comp_count; -static int g_cpus_count; static struct spinlock g_synic_alloc_lock; struct stimer { @@ -216,20 +214,13 @@ static void synic_disable(void) synic_free_page(svcpu->msg_page); } -static void cpu_comp(void) -{ - atomic_inc(&g_cpus_comp_count); -} static void stimer_test_prepare(void *ctx) { - int vcpu = smp_id(); - write_cr3((ulong)ctx); synic_enable(); - synic_sint_create(vcpu, SINT1_NUM, SINT1_VEC, false); - synic_sint_create(vcpu, SINT2_NUM, SINT2_VEC, true); - cpu_comp(); + synic_sint_create(SINT1_NUM, SINT1_VEC, false); + synic_sint_create(SINT2_NUM, SINT2_VEC, true); } static void stimer_test_periodic(int vcpu, struct stimer *timer1, @@ -280,6 +271,35 @@ static void stimer_test_auto_enable_periodic(int vcpu, struct stimer *timer) stimer_shutdown(timer); } +static void stimer_test_one_shot_busy(int vcpu, struct stimer *timer) +{ + struct hv_message_page *msg_page = g_synic_vcpu[vcpu].msg_page; + struct hv_message *msg = &msg_page->sint_message[timer->sint]; + + msg->header.message_type = HVMSG_TIMER_EXPIRED; + wmb(); + + stimer_start(timer, false, false, ONE_MS_IN_100NS, SINT1_NUM); + + do + rmb(); + while (!msg->header.message_flags.msg_pending); + + report("no timer fired while msg slot busy: vcpu %d", + !atomic_read(&timer->fire_count), vcpu); + + msg->header.message_type = HVMSG_NONE; + wmb(); + wrmsr(HV_X64_MSR_EOM, 0); + + while (atomic_read(&timer->fire_count) < 1) { + pause(); + } + report("timer resumed when msg slot released: vcpu %d", true, vcpu); + + stimer_shutdown(timer); +} + static void stimer_test(void *ctx) { int vcpu = smp_id(); @@ -295,33 +315,17 @@ static void stimer_test(void *ctx) stimer_test_one_shot(vcpu, timer1); stimer_test_auto_enable_one_shot(vcpu, timer2); stimer_test_auto_enable_periodic(vcpu, timer1); + stimer_test_one_shot_busy(vcpu, timer1); irq_disable(); - cpu_comp(); } static void stimer_test_cleanup(void *ctx) { - int vcpu = smp_id(); - stimers_shutdown(); - synic_sint_destroy(vcpu, SINT1_NUM); - synic_sint_destroy(vcpu, SINT2_NUM); + synic_sint_destroy(SINT1_NUM); + synic_sint_destroy(SINT2_NUM); synic_disable(); - cpu_comp(); -} - -static void on_each_cpu_async_wait(void (*func)(void *ctx), void *ctx) -{ - int i; - - atomic_set(&g_cpus_comp_count, 0); - for (i = 0; i < g_cpus_count; i++) { - on_cpu_async(i, func, ctx); - } - while (atomic_read(&g_cpus_comp_count) != g_cpus_count) { - pause(); - } } static void stimer_test_all(void) @@ -332,20 +336,17 @@ static void stimer_test_all(void) smp_init(); enable_apic(); + ncpus = cpu_count(); + if (ncpus > MAX_CPUS) + report_abort("number cpus exceeds %d", MAX_CPUS); + printf("cpus = %d\n", ncpus); + handle_irq(SINT1_VEC, stimer_isr); handle_irq(SINT2_VEC, stimer_isr_auto_eoi); - ncpus = cpu_count(); - if (ncpus > MAX_CPUS) { - ncpus = MAX_CPUS; - } - - printf("cpus = %d\n", ncpus); - g_cpus_count = ncpus; - - on_each_cpu_async_wait(stimer_test_prepare, (void *)read_cr3()); - on_each_cpu_async_wait(stimer_test, NULL); - on_each_cpu_async_wait(stimer_test_cleanup, NULL); + on_cpus(stimer_test_prepare, (void *)read_cr3()); + on_cpus(stimer_test, NULL); + on_cpus(stimer_test_cleanup, NULL); } int main(int ac, char **av) diff --git a/tests/kvm-unit-tests/x86/hyperv_synic.c b/tests/kvm-unit-tests/x86/hyperv_synic.c index 74bbd58e..1ccf1a06 100644 --- a/tests/kvm-unit-tests/x86/hyperv_synic.c +++ b/tests/kvm-unit-tests/x86/hyperv_synic.c @@ -12,7 +12,6 @@ #define MAX_CPUS 4 static atomic_t isr_enter_count[MAX_CPUS]; -static atomic_t cpus_comp_count; static void synic_sint_auto_eoi_isr(isr_regs_t *regs) { @@ -69,7 +68,7 @@ static void synic_sints_prepare(int vcpu) for (i = 0; i < HV_SYNIC_SINT_COUNT; i++) { vec = sint_vecs[i].vec; auto_eoi = sint_vecs[i].auto_eoi; - synic_sint_create(vcpu, i, vec, auto_eoi); + synic_sint_create(i, vec, auto_eoi); } } @@ -90,8 +89,8 @@ static void synic_test_prepare(void *ctx) } r = rdmsr(HV_X64_MSR_EOM); if (r != 0) { - report("Hyper-V SynIC test, EOM read 0x%llx", false, r); - goto ret; + report("Hyper-V SynIC test, EOM read %#" PRIx64, false, r); + return; } wrmsr(HV_X64_MSR_SIMP, (u64)virt_to_phys(alloc_page()) | @@ -101,8 +100,6 @@ static void synic_test_prepare(void *ctx) wrmsr(HV_X64_MSR_SCONTROL, HV_SYNIC_CONTROL_ENABLE); synic_sints_prepare(smp_id()); -ret: - atomic_inc(&cpus_comp_count); } static void synic_sints_test(int dst_vcpu) @@ -125,24 +122,20 @@ static void synic_test(void *ctx) irq_enable(); synic_sints_test(dst_vcpu); - atomic_inc(&cpus_comp_count); } static void synic_test_cleanup(void *ctx) { - int vcpu = smp_id(); int i; irq_enable(); for (i = 0; i < HV_SYNIC_SINT_COUNT; i++) { - synic_sint_destroy(vcpu, i); - wrmsr(HV_X64_MSR_SINT0 + i, 0xFF|HV_SYNIC_SINT_MASKED); + synic_sint_destroy(i); } wrmsr(HV_X64_MSR_SCONTROL, 0); wrmsr(HV_X64_MSR_SIMP, 0); wrmsr(HV_X64_MSR_SIEFP, 0); - atomic_inc(&cpus_comp_count); } int main(int ac, char **av) @@ -156,40 +149,25 @@ int main(int ac, char **av) smp_init(); enable_apic(); - synic_prepare_sint_vecs(); - ncpus = cpu_count(); - if (ncpus > MAX_CPUS) { - ncpus = MAX_CPUS; - } + if (ncpus > MAX_CPUS) + report_abort("number cpus exceeds %d", MAX_CPUS); printf("ncpus = %d\n", ncpus); - atomic_set(&cpus_comp_count, 0); - for (i = 0; i < ncpus; i++) { - on_cpu_async(i, synic_test_prepare, (void *)read_cr3()); - } - printf("prepare\n"); - while (atomic_read(&cpus_comp_count) != ncpus) { - pause(); - } + synic_prepare_sint_vecs(); + + printf("prepare\n"); + on_cpus(synic_test_prepare, (void *)read_cr3()); - atomic_set(&cpus_comp_count, 0); for (i = 0; i < ncpus; i++) { printf("test %d -> %d\n", i, ncpus - 1 - i); on_cpu_async(i, synic_test, (void *)(ulong)(ncpus - 1 - i)); } - while (atomic_read(&cpus_comp_count) != ncpus) { + while (cpus_active() > 1) pause(); - } - atomic_set(&cpus_comp_count, 0); - for (i = 0; i < ncpus; i++) { - on_cpu_async(i, synic_test_cleanup, NULL); - } printf("cleanup\n"); - while (atomic_read(&cpus_comp_count) != ncpus) { - pause(); - } + on_cpus(synic_test_cleanup, NULL); ok = true; for (i = 0; i < ncpus; ++i) { diff --git a/tests/kvm-unit-tests/x86/kvmclock_test.c b/tests/kvm-unit-tests/x86/kvmclock_test.c index b90203e0..48a7cdb2 100644 --- a/tests/kvm-unit-tests/x86/kvmclock_test.c +++ b/tests/kvm-unit-tests/x86/kvmclock_test.c @@ -17,7 +17,6 @@ struct test_info { u64 stalls; /* stall count */ long long worst; /* worst warp */ volatile cycle_t last; /* last cycle seen by test */ - atomic_t ncpus; /* number of cpu in the test*/ int check; /* check cycle ? */ }; @@ -78,29 +77,20 @@ static void kvm_clock_test(void *data) if (!((unsigned long)i & 31)) asm volatile("rep; nop"); } - - atomic_dec(&hv_test_info->ncpus); } -static int cycle_test(int ncpus, int check, struct test_info *ti) +static int cycle_test(int check, struct test_info *ti) { - int i; unsigned long long begin, end; begin = rdtsc(); - atomic_set(&ti->ncpus, ncpus); ti->check = check; - for (i = ncpus - 1; i >= 0; i--) - on_cpu_async(i, kvm_clock_test, (void *)ti); - - /* Wait for the end of other vcpu */ - while(atomic_read(&ti->ncpus)) - ; + on_cpus(kvm_clock_test, ti); end = rdtsc(); - printf("Total vcpus: %d\n", ncpus); + printf("Total vcpus: %d\n", cpu_count()); printf("Test loops: %ld\n", loops); if (check == 1) { printf("Total warps: %" PRId64 "\n", ti->warps); @@ -129,9 +119,9 @@ int main(int ac, char **av) ncpus = cpu_count(); if (ncpus > MAX_CPU) - ncpus = MAX_CPU; - for (i = 0; i < ncpus; ++i) - on_cpu(i, kvm_clock_init, (void *)0); + report_abort("number cpus exceeds %d", MAX_CPU); + + on_cpus(kvm_clock_init, NULL); if (ac > 2) { printf("Wallclock test, threshold %ld\n", threshold); @@ -143,26 +133,25 @@ int main(int ac, char **av) printf("Check the stability of raw cycle ...\n"); pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT | PVCLOCK_RAW_CYCLE_BIT); - if (cycle_test(ncpus, 1, &ti[0])) + if (cycle_test(1, &ti[0])) printf("Raw cycle is not stable\n"); else printf("Raw cycle is stable\n"); pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT); printf("Monotonic cycle test:\n"); - nerr += cycle_test(ncpus, 1, &ti[1]); + nerr += cycle_test(1, &ti[1]); printf("Measure the performance of raw cycle ...\n"); pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT | PVCLOCK_RAW_CYCLE_BIT); - cycle_test(ncpus, 0, &ti[2]); + cycle_test(0, &ti[2]); printf("Measure the performance of adjusted cycle ...\n"); pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT); - cycle_test(ncpus, 0, &ti[3]); + cycle_test(0, &ti[3]); - for (i = 0; i < ncpus; ++i) - on_cpu(i, kvm_clock_clear, (void *)0); + on_cpus(kvm_clock_clear, NULL); return nerr > 0 ? 1 : 0; } diff --git a/tests/kvm-unit-tests/x86/msr.c b/tests/kvm-unit-tests/x86/msr.c index ded94249..ffc24b1e 100644 --- a/tests/kvm-unit-tests/x86/msr.c +++ b/tests/kvm-unit-tests/x86/msr.c @@ -6,7 +6,7 @@ struct msr_info { int index; - char *name; + const char *name; struct tc { int valid; unsigned long long value; @@ -78,37 +78,20 @@ static void test_msr_rw(int msr_index, unsigned long long input, unsigned long l { unsigned long long r = 0; int index; - char *sptr; + const char *sptr; if ((index = find_msr_info(msr_index)) != -1) { sptr = msr_info[index].name; } else { - printf("couldn't find name for msr # 0x%x, skipping\n", msr_index); + printf("couldn't find name for msr # %#x, skipping\n", msr_index); return; } wrmsr(msr_index, input); r = rdmsr(msr_index); if (expected != r) { - printf("testing %s: output = 0x%x:0x%x expected = 0x%x:0x%x\n", sptr, + printf("testing %s: output = %#x:%#x expected = %#x:%#x\n", sptr, (u32)(r >> 32), (u32)r, (u32)(expected >> 32), (u32)expected); } - report(sptr, expected == r); -} - -static void test_syscall_lazy_load(void) -{ -#ifdef __x86_64__ - extern void syscall_target(); - u16 cs = read_cs(), ss = read_ss(); - ulong tmp; - - wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_SCE); - wrmsr(MSR_LSTAR, (ulong)syscall_target); - wrmsr(MSR_STAR, (uint64_t)cs << 32); - asm volatile("pushf; syscall; syscall_target: popf" : "=c"(tmp) : : "r11"); - write_ss(ss); - // will crash horribly if broken - report("MSR_*STAR eager loading", true); -#endif + report("%s", expected == r, sptr); } int main(int ac, char **av) @@ -124,8 +107,6 @@ int main(int ac, char **av) } } - test_syscall_lazy_load(); - return report_summary(); } diff --git a/tests/kvm-unit-tests/x86/pmu.c b/tests/kvm-unit-tests/x86/pmu.c index c6898004..a0238dcd 100644 --- a/tests/kvm-unit-tests/x86/pmu.c +++ b/tests/kvm-unit-tests/x86/pmu.c @@ -73,7 +73,7 @@ union cpuid10_edx { } edx; struct pmu_event { - char *name; + const char *name; uint32_t unit_sel; int min; int max; diff --git a/tests/kvm-unit-tests/x86/run b/tests/kvm-unit-tests/x86/run deleted file mode 100755 index 867a1ccc..00000000 --- a/tests/kvm-unit-tests/x86/run +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/bash - -[ -z "$STANDALONE" ] && source scripts/arch-run.bash - -qemubinarysearch="${QEMU:-qemu-kvm qemu-system-x86_64}" - -for qemucmd in ${qemubinarysearch} -do - unset QEMUFOUND - unset qemu - if ! [ -z "${QEMUFOUND=$(${qemucmd} --help 2>/dev/null | grep "QEMU")}" ] && - ${qemucmd} -device '?' 2>&1 | grep -F -e \"testdev\" -e \"pc-testdev\" > /dev/null; - then - qemu="${qemucmd}" - break - fi -done - -if [ -z "${QEMUFOUND}" ] -then - echo "A QEMU binary was not found, You can set a custom location by using the QEMU= environment variable " - exit 2 -elif [ -z "${qemu}" ] -then - echo "No Qemu test device support found" - exit 2 -fi - -if - ${qemu} -device '?' 2>&1 | grep -F "pci-testdev" > /dev/null; -then - pci_testdev="-device pci-testdev" -else - pci_testdev="" -fi - -if - ${qemu} -device '?' 2>&1 | grep -F "pc-testdev" > /dev/null; -then - pc_testdev="-device pc-testdev -device isa-debug-exit,iobase=0xf4,iosize=0x4" -else - pc_testdev="-device testdev,chardev=testlog -chardev file,id=testlog,path=msr.out" -fi - -command="${qemu} -nodefaults -enable-kvm $pc_testdev -vnc none -serial stdio $pci_testdev $hyperv_testdev" -[ -f "$ENV" ] && command+=" -initrd $ENV" -command+=" -kernel" -command="$(timeout_cmd) $command" -echo ${command} "$@" - -run_qemu ${command} "$@" diff --git a/tests/kvm-unit-tests/x86/tsc.c b/tests/kvm-unit-tests/x86/tsc.c index 62450e71..6dc05af2 100644 --- a/tests/kvm-unit-tests/x86/tsc.c +++ b/tests/kvm-unit-tests/x86/tsc.c @@ -23,7 +23,7 @@ void test_rdtscp(u64 aux) wrmsr(MSR_TSC_AUX, aux); rdtscp(&ecx); - report("Test RDTSCP %d", ecx == aux, aux); + report("Test RDTSCP %" PRIu64, ecx == aux, aux); } int main() diff --git a/tests/kvm-unit-tests/x86/unittests.cfg b/tests/kvm-unit-tests/x86/unittests.cfg deleted file mode 100644 index 54138388..00000000 --- a/tests/kvm-unit-tests/x86/unittests.cfg +++ /dev/null @@ -1,226 +0,0 @@ -############################################################################## -# unittest configuration -# -# [unittest_name] -# file = .flat # Name of the flat file to be used. -# smp = # Number of processors the VM will use -# # during this test. Use $MAX_SMP to use -# # the maximum the host supports. Defaults -# # to one. -# extra_params = -append # Additional parameters used. -# arch = i386|x86_64 # Select one if the test case is -# # specific to only one. -# groups = ... # Used to identify test cases -# # with run_tests -g ... -# # Specify group_name=nodefault -# # to have test not run by -# # default -# accel = kvm|tcg # Optionally specify if test must run with -# # kvm or tcg. If not specified, then kvm will -# # be used when available. -# timeout = # Optionally specify a timeout. -# check = = # check a file for a particular value before running -# # a test. The check line can contain multiple files -# # to check separated by a space but each check -# # parameter needs to be of the form = -############################################################################## - -[apic-split] -file = apic.flat -smp = 2 -extra_params = -cpu qemu64,+x2apic,+tsc-deadline -machine kernel_irqchip=split -arch = x86_64 - -[ioapic-split] -file = ioapic.flat -extra_params = -cpu qemu64 -machine kernel_irqchip=split -arch = x86_64 - -[apic] -file = apic.flat -smp = 2 -extra_params = -cpu qemu64,+x2apic,+tsc-deadline -arch = x86_64 -timeout = 30 - -[ioapic] -file = ioapic.flat -extra_params = -cpu qemu64 -arch = x86_64 - -[smptest] -file = smptest.flat -smp = 2 - -[smptest3] -file = smptest.flat -smp = 3 - -[vmexit_cpuid] -file = vmexit.flat -extra_params = -append 'cpuid' -groups = vmexit - -[vmexit_vmcall] -file = vmexit.flat -extra_params = -append 'vmcall' -groups = vmexit - -[vmexit_mov_from_cr8] -file = vmexit.flat -extra_params = -append 'mov_from_cr8' -groups = vmexit - -[vmexit_mov_to_cr8] -file = vmexit.flat -extra_params = -append 'mov_to_cr8' -groups = vmexit - -[vmexit_inl_pmtimer] -file = vmexit.flat -extra_params = -append 'inl_from_pmtimer' -groups = vmexit - -[vmexit_ipi] -file = vmexit.flat -smp = 2 -extra_params = -append 'ipi' -groups = vmexit - -[vmexit_ipi_halt] -file = vmexit.flat -smp = 2 -extra_params = -append 'ipi_halt' -groups = vmexit - -[vmexit_ple_round_robin] -file = vmexit.flat -extra_params = -append 'ple_round_robin' -groups = vmexit - -[access] -file = access.flat -arch = x86_64 - -[smap] -file = smap.flat -extra_params = -cpu host - -[pku] -file = pku.flat -arch = x86_64 -extra_params = -cpu host - -#[asyncpf] -#file = asyncpf.flat - -[emulator] -file = emulator.flat -arch = x86_64 - -[eventinj] -file = eventinj.flat - -[hypercall] -file = hypercall.flat - -[idt_test] -file = idt_test.flat -arch = x86_64 - -#[init] -#file = init.flat - -[msr] -file = msr.flat - -[pmu] -file = pmu.flat -extra_params = -cpu host -check = /proc/sys/kernel/nmi_watchdog=0 - -[port80] -file = port80.flat - -[realmode] -file = realmode.flat - -[s3] -file = s3.flat - -[sieve] -file = sieve.flat - -[tsc] -file = tsc.flat -extra_params = -cpu kvm64,+rdtscp - -[tsc_adjust] -file = tsc_adjust.flat -extra_params = -cpu host - -[xsave] -file = xsave.flat -arch = x86_64 -extra_params = -cpu host - -[rmap_chain] -file = rmap_chain.flat -arch = x86_64 - -[svm] -file = svm.flat -smp = 2 -extra_params = -cpu qemu64,+svm -arch = x86_64 - -[taskswitch] -file = taskswitch.flat -arch = i386 -groups = tasks - -[taskswitch2] -file = taskswitch2.flat -arch = i386 -groups = tasks - -[kvmclock_test] -file = kvmclock_test.flat -smp = 2 -extra_params = --append "10000000 `date +%s`" - -[pcid] -file = pcid.flat -extra_params = -cpu qemu64,+pcid -arch = x86_64 - -[vmx] -file = vmx.flat -extra_params = -cpu host,+vmx -arch = x86_64 - -[debug] -file = debug.flat -arch = x86_64 - -[hyperv_synic] -file = hyperv_synic.flat -smp = 2 -extra_params = -cpu kvm64,hv_synic -device hyperv-testdev - -[hyperv_stimer] -file = hyperv_stimer.flat -smp = 2 -extra_params = -cpu kvm64,hv_time,hv_synic,hv_stimer -device hyperv-testdev - -[hyperv_clock] -file = hyperv_clock.flat -smp = 2 -extra_params = -cpu kvm64,hv_time - -[intel_iommu] -file = intel-iommu.flat -arch = x86_64 -timeout = 30 -smp = 4 -extra_params = -M q35,kernel-irqchip=split -device intel-iommu,intremap=on,eim=off -device edu diff --git a/tests/kvm-unit-tests/x86/vmexit.c b/tests/kvm-unit-tests/x86/vmexit.c index 5b821b5e..42ab7dbf 100644 --- a/tests/kvm-unit-tests/x86/vmexit.c +++ b/tests/kvm-unit-tests/x86/vmexit.c @@ -387,6 +387,32 @@ static bool pci_io_next(struct test *test) return ret; } +static int has_tscdeadline(void) +{ + uint32_t lvtt; + + if (cpuid(1).c & (1 << 24)) { + lvtt = APIC_LVT_TIMER_TSCDEADLINE | IPI_TEST_VECTOR; + apic_write(APIC_LVTT, lvtt); + return 1; + } else { + return 0; + } +} + +static void tscdeadline_immed(void) +{ + wrmsr(MSR_IA32_TSCDEADLINE, rdtsc()); + asm volatile("nop"); +} + +static void tscdeadline(void) +{ + x = 0; + wrmsr(MSR_IA32_TSCDEADLINE, rdtsc()+3000); + while (x == 0) barrier(); +} + static struct test tests[] = { { cpuid_test, "cpuid", .parallel = 1, }, { vmcall, "vmcall", .parallel = 1, }, @@ -399,6 +425,8 @@ static struct test tests[] = { { inl_nop_kernel, "inl_from_kernel", .parallel = 1 }, { outl_elcr_kernel, "outl_to_kernel", .parallel = 1 }, { mov_dr, "mov_dr", .parallel = 1 }, + { tscdeadline_immed, "tscdeadline_immed", has_tscdeadline, .parallel = 1, }, + { tscdeadline, "tscdeadline", has_tscdeadline, .parallel = 1, }, { self_ipi_sti_nop, "self_ipi_sti_nop", .parallel = 0, }, { self_ipi_sti_hlt, "self_ipi_sti_hlt", .parallel = 0, }, { self_ipi_tpr, "self_ipi_tpr", .parallel = 0, }, @@ -419,7 +447,6 @@ static struct test tests[] = { }; unsigned iterations; -static atomic_t nr_cpus_done; static void run_test(void *_func) { @@ -428,8 +455,6 @@ static void run_test(void *_func) for (i = 0; i < iterations; ++i) func(); - - atomic_inc(&nr_cpus_done); } static bool do_test(struct test *test) @@ -463,11 +488,7 @@ static bool do_test(struct test *test) for (i = 0; i < iterations; ++i) func(); } else { - atomic_set(&nr_cpus_done, 0); - for (i = cpu_count(); i > 0; i--) - on_cpu_async(i-1, run_test, func); - while (atomic_read(&nr_cpus_done) < cpu_count()) - ; + on_cpus(run_test, func); } t2 = rdtsc(); } while ((t2 - t1) < GOAL); @@ -509,8 +530,7 @@ int main(int ac, char **av) nr_cpus = cpu_count(); irq_enable(); - for (i = cpu_count(); i > 0; i--) - on_cpu(i-1, enable_nx, 0); + on_cpus(enable_nx, NULL); fadt = find_acpi_table_addr(FACP_SIGNATURE); pm_tmr_blk = fadt->pm_tmr_blk; @@ -524,7 +544,7 @@ int main(int ac, char **av) membar = pcidev.resource[PCI_TESTDEV_BAR_MEM]; pci_test.memaddr = ioremap(membar, PAGE_SIZE); pci_test.iobar = pcidev.resource[PCI_TESTDEV_BAR_IO]; - printf("pci-testdev at 0x%x membar %lx iobar %x\n", + printf("pci-testdev at %#x membar %lx iobar %x\n", pcidev.bdf, membar, pci_test.iobar); } diff --git a/tests/kvm-unit-tests/x86/vmx.c b/tests/kvm-unit-tests/x86/vmx.c index da5daa86..889df372 100644 --- a/tests/kvm-unit-tests/x86/vmx.c +++ b/tests/kvm-unit-tests/x86/vmx.c @@ -42,9 +42,26 @@ u32 vpid_cnt; void *guest_stack, *guest_syscall_stack; u32 ctrl_pin, ctrl_enter, ctrl_exit, ctrl_cpu[2]; struct regs regs; + struct vmx_test *current; + +#define MAX_TEST_TEARDOWN_STEPS 10 + +struct test_teardown_step { + test_teardown_func func; + void *data; +}; + +static int teardown_count; +static struct test_teardown_step teardown_steps[MAX_TEST_TEARDOWN_STEPS]; + +static test_guest_func v2_guest_main; + u64 hypercall_field; bool launched; +static int matched; +static int guest_finished; +static int in_guest; union vmx_basic basic; union vmx_ctrl_msr ctrl_pin_rev; @@ -62,6 +79,308 @@ extern void *guest_entry; static volatile u32 stage; +static jmp_buf abort_target; + +struct vmcs_field { + u64 mask; + u64 encoding; +}; + +#define MASK(_bits) GENMASK_ULL((_bits) - 1, 0) +#define MASK_NATURAL MASK(sizeof(unsigned long) * 8) + +static struct vmcs_field vmcs_fields[] = { + { MASK(16), VPID }, + { MASK(16), PINV }, + { MASK(16), EPTP_IDX }, + + { MASK(16), GUEST_SEL_ES }, + { MASK(16), GUEST_SEL_CS }, + { MASK(16), GUEST_SEL_SS }, + { MASK(16), GUEST_SEL_DS }, + { MASK(16), GUEST_SEL_FS }, + { MASK(16), GUEST_SEL_GS }, + { MASK(16), GUEST_SEL_LDTR }, + { MASK(16), GUEST_SEL_TR }, + { MASK(16), GUEST_INT_STATUS }, + + { MASK(16), HOST_SEL_ES }, + { MASK(16), HOST_SEL_CS }, + { MASK(16), HOST_SEL_SS }, + { MASK(16), HOST_SEL_DS }, + { MASK(16), HOST_SEL_FS }, + { MASK(16), HOST_SEL_GS }, + { MASK(16), HOST_SEL_TR }, + + { MASK(64), IO_BITMAP_A }, + { MASK(64), IO_BITMAP_B }, + { MASK(64), MSR_BITMAP }, + { MASK(64), EXIT_MSR_ST_ADDR }, + { MASK(64), EXIT_MSR_LD_ADDR }, + { MASK(64), ENTER_MSR_LD_ADDR }, + { MASK(64), VMCS_EXEC_PTR }, + { MASK(64), TSC_OFFSET }, + { MASK(64), APIC_VIRT_ADDR }, + { MASK(64), APIC_ACCS_ADDR }, + { MASK(64), EPTP }, + + { 0 /* read-only */, INFO_PHYS_ADDR }, + + { MASK(64), VMCS_LINK_PTR }, + { MASK(64), GUEST_DEBUGCTL }, + { MASK(64), GUEST_EFER }, + { MASK(64), GUEST_PAT }, + { MASK(64), GUEST_PERF_GLOBAL_CTRL }, + { MASK(64), GUEST_PDPTE }, + + { MASK(64), HOST_PAT }, + { MASK(64), HOST_EFER }, + { MASK(64), HOST_PERF_GLOBAL_CTRL }, + + { MASK(32), PIN_CONTROLS }, + { MASK(32), CPU_EXEC_CTRL0 }, + { MASK(32), EXC_BITMAP }, + { MASK(32), PF_ERROR_MASK }, + { MASK(32), PF_ERROR_MATCH }, + { MASK(32), CR3_TARGET_COUNT }, + { MASK(32), EXI_CONTROLS }, + { MASK(32), EXI_MSR_ST_CNT }, + { MASK(32), EXI_MSR_LD_CNT }, + { MASK(32), ENT_CONTROLS }, + { MASK(32), ENT_MSR_LD_CNT }, + { MASK(32), ENT_INTR_INFO }, + { MASK(32), ENT_INTR_ERROR }, + { MASK(32), ENT_INST_LEN }, + { MASK(32), TPR_THRESHOLD }, + { MASK(32), CPU_EXEC_CTRL1 }, + + { 0 /* read-only */, VMX_INST_ERROR }, + { 0 /* read-only */, EXI_REASON }, + { 0 /* read-only */, EXI_INTR_INFO }, + { 0 /* read-only */, EXI_INTR_ERROR }, + { 0 /* read-only */, IDT_VECT_INFO }, + { 0 /* read-only */, IDT_VECT_ERROR }, + { 0 /* read-only */, EXI_INST_LEN }, + { 0 /* read-only */, EXI_INST_INFO }, + + { MASK(32), GUEST_LIMIT_ES }, + { MASK(32), GUEST_LIMIT_CS }, + { MASK(32), GUEST_LIMIT_SS }, + { MASK(32), GUEST_LIMIT_DS }, + { MASK(32), GUEST_LIMIT_FS }, + { MASK(32), GUEST_LIMIT_GS }, + { MASK(32), GUEST_LIMIT_LDTR }, + { MASK(32), GUEST_LIMIT_TR }, + { MASK(32), GUEST_LIMIT_GDTR }, + { MASK(32), GUEST_LIMIT_IDTR }, + { 0x1d0ff, GUEST_AR_ES }, + { 0x1f0ff, GUEST_AR_CS }, + { 0x1d0ff, GUEST_AR_SS }, + { 0x1d0ff, GUEST_AR_DS }, + { 0x1d0ff, GUEST_AR_FS }, + { 0x1d0ff, GUEST_AR_GS }, + { 0x1d0ff, GUEST_AR_LDTR }, + { 0x1d0ff, GUEST_AR_TR }, + { MASK(32), GUEST_INTR_STATE }, + { MASK(32), GUEST_ACTV_STATE }, + { MASK(32), GUEST_SMBASE }, + { MASK(32), GUEST_SYSENTER_CS }, + { MASK(32), PREEMPT_TIMER_VALUE }, + + { MASK(32), HOST_SYSENTER_CS }, + + { MASK_NATURAL, CR0_MASK }, + { MASK_NATURAL, CR4_MASK }, + { MASK_NATURAL, CR0_READ_SHADOW }, + { MASK_NATURAL, CR4_READ_SHADOW }, + { MASK_NATURAL, CR3_TARGET_0 }, + { MASK_NATURAL, CR3_TARGET_1 }, + { MASK_NATURAL, CR3_TARGET_2 }, + { MASK_NATURAL, CR3_TARGET_3 }, + + { 0 /* read-only */, EXI_QUALIFICATION }, + { 0 /* read-only */, IO_RCX }, + { 0 /* read-only */, IO_RSI }, + { 0 /* read-only */, IO_RDI }, + { 0 /* read-only */, IO_RIP }, + { 0 /* read-only */, GUEST_LINEAR_ADDRESS }, + + { MASK_NATURAL, GUEST_CR0 }, + { MASK_NATURAL, GUEST_CR3 }, + { MASK_NATURAL, GUEST_CR4 }, + { MASK_NATURAL, GUEST_BASE_ES }, + { MASK_NATURAL, GUEST_BASE_CS }, + { MASK_NATURAL, GUEST_BASE_SS }, + { MASK_NATURAL, GUEST_BASE_DS }, + { MASK_NATURAL, GUEST_BASE_FS }, + { MASK_NATURAL, GUEST_BASE_GS }, + { MASK_NATURAL, GUEST_BASE_LDTR }, + { MASK_NATURAL, GUEST_BASE_TR }, + { MASK_NATURAL, GUEST_BASE_GDTR }, + { MASK_NATURAL, GUEST_BASE_IDTR }, + { MASK_NATURAL, GUEST_DR7 }, + { MASK_NATURAL, GUEST_RSP }, + { MASK_NATURAL, GUEST_RIP }, + { MASK_NATURAL, GUEST_RFLAGS }, + { MASK_NATURAL, GUEST_PENDING_DEBUG }, + { MASK_NATURAL, GUEST_SYSENTER_ESP }, + { MASK_NATURAL, GUEST_SYSENTER_EIP }, + + { MASK_NATURAL, HOST_CR0 }, + { MASK_NATURAL, HOST_CR3 }, + { MASK_NATURAL, HOST_CR4 }, + { MASK_NATURAL, HOST_BASE_FS }, + { MASK_NATURAL, HOST_BASE_GS }, + { MASK_NATURAL, HOST_BASE_TR }, + { MASK_NATURAL, HOST_BASE_GDTR }, + { MASK_NATURAL, HOST_BASE_IDTR }, + { MASK_NATURAL, HOST_SYSENTER_ESP }, + { MASK_NATURAL, HOST_SYSENTER_EIP }, + { MASK_NATURAL, HOST_RSP }, + { MASK_NATURAL, HOST_RIP }, +}; + +static inline u64 vmcs_field_value(struct vmcs_field *f, u8 cookie) +{ + u64 value; + + /* Incorporate the cookie and the field encoding into the value. */ + value = cookie; + value |= (f->encoding << 8); + value |= 0xdeadbeefull << 32; + + return value & f->mask; +} + +static void set_vmcs_field(struct vmcs_field *f, u8 cookie) +{ + vmcs_write(f->encoding, vmcs_field_value(f, cookie)); +} + +static bool check_vmcs_field(struct vmcs_field *f, u8 cookie) +{ + u64 expected; + u64 actual; + int ret; + + ret = vmcs_read_checking(f->encoding, &actual); + assert(!(ret & X86_EFLAGS_CF)); + /* Skip VMCS fields that aren't recognized by the CPU */ + if (ret & X86_EFLAGS_ZF) + return true; + + expected = vmcs_field_value(f, cookie); + actual &= f->mask; + + if (expected == actual) + return true; + + printf("FAIL: VMWRITE/VMREAD %lx (expected: %lx, actual: %lx)\n", + f->encoding, (unsigned long) expected, (unsigned long) actual); + + return false; +} + +static void set_all_vmcs_fields(u8 cookie) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(vmcs_fields); i++) + set_vmcs_field(&vmcs_fields[i], cookie); +} + +static bool check_all_vmcs_fields(u8 cookie) +{ + bool pass = true; + int i; + + for (i = 0; i < ARRAY_SIZE(vmcs_fields); i++) { + if (!check_vmcs_field(&vmcs_fields[i], cookie)) + pass = false; + } + + return pass; +} + +void test_vmwrite_vmread(void) +{ + struct vmcs *vmcs = alloc_page(); + + memset(vmcs, 0, PAGE_SIZE); + vmcs->revision_id = basic.revision; + assert(!vmcs_clear(vmcs)); + assert(!make_vmcs_current(vmcs)); + + set_all_vmcs_fields(0x42); + report("VMWRITE/VMREAD", check_all_vmcs_fields(0x42)); + + assert(!vmcs_clear(vmcs)); + free_page(vmcs); +} + +void test_vmcs_lifecycle(void) +{ + struct vmcs *vmcs[2] = {}; + int i; + + for (i = 0; i < ARRAY_SIZE(vmcs); i++) { + vmcs[i] = alloc_page(); + memset(vmcs[i], 0, PAGE_SIZE); + vmcs[i]->revision_id = basic.revision; + } + +#define VMPTRLD(_i) do { \ + assert(_i < ARRAY_SIZE(vmcs)); \ + assert(!make_vmcs_current(vmcs[_i])); \ + printf("VMPTRLD VMCS%d\n", (_i)); \ +} while (0) + +#define VMCLEAR(_i) do { \ + assert(_i < ARRAY_SIZE(vmcs)); \ + assert(!vmcs_clear(vmcs[_i])); \ + printf("VMCLEAR VMCS%d\n", (_i)); \ +} while (0) + + VMCLEAR(0); + VMPTRLD(0); + set_all_vmcs_fields(0); + report("current:VMCS0 active:[VMCS0]", check_all_vmcs_fields(0)); + + VMCLEAR(0); + VMPTRLD(0); + report("current:VMCS0 active:[VMCS0]", check_all_vmcs_fields(0)); + + VMCLEAR(1); + report("current:VMCS0 active:[VMCS0]", check_all_vmcs_fields(0)); + + VMPTRLD(1); + set_all_vmcs_fields(1); + report("current:VMCS1 active:[VMCS0,VCMS1]", check_all_vmcs_fields(1)); + + VMPTRLD(0); + report("current:VMCS0 active:[VMCS0,VCMS1]", check_all_vmcs_fields(0)); + VMPTRLD(1); + report("current:VMCS1 active:[VMCS0,VCMS1]", check_all_vmcs_fields(1)); + VMPTRLD(1); + report("current:VMCS1 active:[VMCS0,VCMS1]", check_all_vmcs_fields(1)); + + VMCLEAR(0); + report("current:VMCS1 active:[VCMS1]", check_all_vmcs_fields(1)); + + /* VMPTRLD should not erase VMWRITEs to the current VMCS */ + set_all_vmcs_fields(2); + VMPTRLD(1); + report("current:VMCS1 active:[VCMS1]", check_all_vmcs_fields(2)); + + for (i = 0; i < ARRAY_SIZE(vmcs); i++) { + VMCLEAR(i); + free_page(vmcs[i]); + } + +#undef VMPTRLD +#undef VMCLEAR +} + void vmx_set_test_stage(u32 s) { barrier(); @@ -86,16 +405,6 @@ void vmx_inc_test_stage(void) barrier(); } -static int make_vmcs_current(struct vmcs *vmcs) -{ - bool ret; - u64 rflags = read_rflags() | X86_EFLAGS_CF | X86_EFLAGS_ZF; - - asm volatile ("push %1; popf; vmptrld %2; setbe %0" - : "=q" (ret) : "q" (rflags), "m" (vmcs) : "cc"); - return ret; -} - /* entry_sysenter */ asm( ".align 4, 0x90\n\t" @@ -115,23 +424,73 @@ static void __attribute__((__used__)) syscall_handler(u64 syscall_no) current->syscall_handler(syscall_no); } -static inline int vmx_on() -{ - bool ret; - u64 rflags = read_rflags() | X86_EFLAGS_CF | X86_EFLAGS_ZF; - asm volatile ("push %1; popf; vmxon %2; setbe %0\n\t" - : "=q" (ret) : "q" (rflags), "m" (vmxon_region) : "cc"); - return ret; -} +static const char * const exit_reason_descriptions[] = { + [VMX_EXC_NMI] = "VMX_EXC_NMI", + [VMX_EXTINT] = "VMX_EXTINT", + [VMX_TRIPLE_FAULT] = "VMX_TRIPLE_FAULT", + [VMX_INIT] = "VMX_INIT", + [VMX_SIPI] = "VMX_SIPI", + [VMX_SMI_IO] = "VMX_SMI_IO", + [VMX_SMI_OTHER] = "VMX_SMI_OTHER", + [VMX_INTR_WINDOW] = "VMX_INTR_WINDOW", + [VMX_NMI_WINDOW] = "VMX_NMI_WINDOW", + [VMX_TASK_SWITCH] = "VMX_TASK_SWITCH", + [VMX_CPUID] = "VMX_CPUID", + [VMX_GETSEC] = "VMX_GETSEC", + [VMX_HLT] = "VMX_HLT", + [VMX_INVD] = "VMX_INVD", + [VMX_INVLPG] = "VMX_INVLPG", + [VMX_RDPMC] = "VMX_RDPMC", + [VMX_RDTSC] = "VMX_RDTSC", + [VMX_RSM] = "VMX_RSM", + [VMX_VMCALL] = "VMX_VMCALL", + [VMX_VMCLEAR] = "VMX_VMCLEAR", + [VMX_VMLAUNCH] = "VMX_VMLAUNCH", + [VMX_VMPTRLD] = "VMX_VMPTRLD", + [VMX_VMPTRST] = "VMX_VMPTRST", + [VMX_VMREAD] = "VMX_VMREAD", + [VMX_VMRESUME] = "VMX_VMRESUME", + [VMX_VMWRITE] = "VMX_VMWRITE", + [VMX_VMXOFF] = "VMX_VMXOFF", + [VMX_VMXON] = "VMX_VMXON", + [VMX_CR] = "VMX_CR", + [VMX_DR] = "VMX_DR", + [VMX_IO] = "VMX_IO", + [VMX_RDMSR] = "VMX_RDMSR", + [VMX_WRMSR] = "VMX_WRMSR", + [VMX_FAIL_STATE] = "VMX_FAIL_STATE", + [VMX_FAIL_MSR] = "VMX_FAIL_MSR", + [VMX_MWAIT] = "VMX_MWAIT", + [VMX_MTF] = "VMX_MTF", + [VMX_MONITOR] = "VMX_MONITOR", + [VMX_PAUSE] = "VMX_PAUSE", + [VMX_FAIL_MCHECK] = "VMX_FAIL_MCHECK", + [VMX_TPR_THRESHOLD] = "VMX_TPR_THRESHOLD", + [VMX_APIC_ACCESS] = "VMX_APIC_ACCESS", + [VMX_GDTR_IDTR] = "VMX_GDTR_IDTR", + [VMX_LDTR_TR] = "VMX_LDTR_TR", + [VMX_EPT_VIOLATION] = "VMX_EPT_VIOLATION", + [VMX_EPT_MISCONFIG] = "VMX_EPT_MISCONFIG", + [VMX_INVEPT] = "VMX_INVEPT", + [VMX_PREEMPT] = "VMX_PREEMPT", + [VMX_INVVPID] = "VMX_INVVPID", + [VMX_WBINVD] = "VMX_WBINVD", + [VMX_XSETBV] = "VMX_XSETBV", + [VMX_APIC_WRITE] = "VMX_APIC_WRITE", + [VMX_RDRAND] = "VMX_RDRAND", + [VMX_INVPCID] = "VMX_INVPCID", + [VMX_VMFUNC] = "VMX_VMFUNC", + [VMX_RDSEED] = "VMX_RDSEED", + [VMX_PML_FULL] = "VMX_PML_FULL", + [VMX_XSAVES] = "VMX_XSAVES", + [VMX_XRSTORS] = "VMX_XRSTORS", +}; -static inline int vmx_off() +const char *exit_reason_description(u64 reason) { - bool ret; - u64 rflags = read_rflags() | X86_EFLAGS_CF | X86_EFLAGS_ZF; - - asm volatile("push %1; popf; vmxoff; setbe %0\n\t" - : "=q"(ret) : "q" (rflags) : "cc"); - return ret; + if (reason >= ARRAY_SIZE(exit_reason_descriptions)) + return "(unknown)"; + return exit_reason_descriptions[reason] ? : "(unused)"; } void print_vmexit_info() @@ -143,16 +502,16 @@ void print_vmexit_info() guest_rsp = vmcs_read(GUEST_RSP); printf("VMEXIT info:\n"); printf("\tvmexit reason = %ld\n", reason); - printf("\texit qualification = 0x%lx\n", exit_qual); + printf("\texit qualification = %#lx\n", exit_qual); printf("\tBit 31 of reason = %lx\n", (vmcs_read(EXI_REASON) >> 31) & 1); - printf("\tguest_rip = 0x%lx\n", guest_rip); - printf("\tRAX=0x%lx RBX=0x%lx RCX=0x%lx RDX=0x%lx\n", + printf("\tguest_rip = %#lx\n", guest_rip); + printf("\tRAX=%#lx RBX=%#lx RCX=%#lx RDX=%#lx\n", regs.rax, regs.rbx, regs.rcx, regs.rdx); - printf("\tRSP=0x%lx RBP=0x%lx RSI=0x%lx RDI=0x%lx\n", + printf("\tRSP=%#lx RBP=%#lx RSI=%#lx RDI=%#lx\n", guest_rsp, regs.rbp, regs.rsi, regs.rdi); - printf("\tR8 =0x%lx R9 =0x%lx R10=0x%lx R11=0x%lx\n", + printf("\tR8 =%#lx R9 =%#lx R10=%#lx R11=%#lx\n", regs.r8, regs.r9, regs.r10, regs.r11); - printf("\tR12=0x%lx R13=0x%lx R14=0x%lx R15=0x%lx\n", + printf("\tR12=%#lx R13=%#lx R14=%#lx R15=%#lx\n", regs.r12, regs.r13, regs.r14, regs.r15); } @@ -175,7 +534,7 @@ print_vmentry_failure_info(struct vmentry_failure *failure) { u64 reason = vmcs_read(EXI_REASON); u64 qual = vmcs_read(EXI_QUALIFICATION); - printf("Non-early %s failure (reason=0x%lx, qual=0x%lx): ", + printf("Non-early %s failure (reason=%#lx, qual=%#lx): ", failure->instr, reason, qual); switch (reason & 0xff) { @@ -201,6 +560,42 @@ print_vmentry_failure_info(struct vmentry_failure *failure) { } } +/* + * VMCLEAR should ensures all VMCS state is flushed to the VMCS + * region in memory. + */ +static void test_vmclear_flushing(void) +{ + struct vmcs *vmcs[3] = {}; + int i; + + for (i = 0; i < ARRAY_SIZE(vmcs); i++) { + vmcs[i] = alloc_page(); + memset(vmcs[i], 0, PAGE_SIZE); + } + + vmcs[0]->revision_id = basic.revision; + assert(!vmcs_clear(vmcs[0])); + assert(!make_vmcs_current(vmcs[0])); + set_all_vmcs_fields(0x86); + + assert(!vmcs_clear(vmcs[0])); + memcpy(vmcs[1], vmcs[0], basic.size); + assert(!make_vmcs_current(vmcs[1])); + report("test vmclear flush (current VMCS)", check_all_vmcs_fields(0x86)); + + set_all_vmcs_fields(0x87); + assert(!make_vmcs_current(vmcs[0])); + assert(!vmcs_clear(vmcs[1])); + memcpy(vmcs[2], vmcs[1], basic.size); + assert(!make_vmcs_current(vmcs[2])); + report("test vmclear flush (!current VMCS)", check_all_vmcs_fields(0x87)); + + for (i = 0; i < ARRAY_SIZE(vmcs); i++) { + assert(!vmcs_clear(vmcs[i])); + free_page(vmcs[i]); + } +} static void test_vmclear(void) { @@ -233,19 +628,15 @@ static void test_vmclear(void) /* Valid VMCS */ report("test vmclear with valid vmcs region", vmcs_clear(vmcs_root) == 0); -} - -static void test_vmxoff(void) -{ - int ret; - - ret = vmx_off(); - report("test vmxoff", !ret); + test_vmclear_flushing(); } static void __attribute__((__used__)) guest_main(void) { - current->guest_main(); + if (current->v2) + v2_guest_main(); + else + current->guest_main(); } /* guest_entry */ @@ -314,6 +705,9 @@ void install_ept_entry(unsigned long *pml4, unsigned long *pt = pml4; unsigned offset; + /* EPT only uses 48 bits of GPA. */ + assert(guest_addr < (1ul << 48)); + for (level = EPT_PAGE_LEVEL; level > pte_level; --level) { offset = (guest_addr >> EPT_LEVEL_SHIFT(level)) & EPT_PGDIR_MASK; @@ -396,31 +790,135 @@ void setup_ept_range(unsigned long *pml4, unsigned long start, /* get_ept_pte : Get the PTE of a given level in EPT, @level == 1 means get the latest level*/ -unsigned long get_ept_pte(unsigned long *pml4, - unsigned long guest_addr, int level) +bool get_ept_pte(unsigned long *pml4, unsigned long guest_addr, int level, + unsigned long *pte) { int l; - unsigned long *pt = pml4, pte; + unsigned long *pt = pml4, iter_pte; unsigned offset; - if (level < 1 || level > 3) - return -1; + assert(level >= 1 && level <= 4); + for (l = EPT_PAGE_LEVEL; ; --l) { offset = (guest_addr >> EPT_LEVEL_SHIFT(l)) & EPT_PGDIR_MASK; - pte = pt[offset]; - if (!(pte & (EPT_PRESENT))) - return 0; + iter_pte = pt[offset]; if (l == level) break; - if (l < 4 && (pte & EPT_LARGE_PAGE)) - return pte; - pt = (unsigned long *)(pte & EPT_ADDR_MASK); + if (l < 4 && (iter_pte & EPT_LARGE_PAGE)) + return false; + if (!(iter_pte & (EPT_PRESENT))) + return false; + pt = (unsigned long *)(iter_pte & EPT_ADDR_MASK); } offset = (guest_addr >> EPT_LEVEL_SHIFT(l)) & EPT_PGDIR_MASK; - pte = pt[offset]; - return pte; + if (pte) + *pte = pt[offset]; + return true; } +static void clear_ept_ad_pte(unsigned long *pml4, unsigned long guest_addr) +{ + int l; + unsigned long *pt = pml4; + u64 pte; + unsigned offset; + + for (l = EPT_PAGE_LEVEL; ; --l) { + offset = (guest_addr >> EPT_LEVEL_SHIFT(l)) & EPT_PGDIR_MASK; + pt[offset] &= ~(EPT_ACCESS_FLAG|EPT_DIRTY_FLAG); + pte = pt[offset]; + if (l == 1 || (l < 4 && (pte & EPT_LARGE_PAGE))) + break; + pt = (unsigned long *)(pte & EPT_ADDR_MASK); + } +} + +/* clear_ept_ad : Clear EPT A/D bits for the page table walk and the + final GPA of a guest address. */ +void clear_ept_ad(unsigned long *pml4, u64 guest_cr3, + unsigned long guest_addr) +{ + int l; + unsigned long *pt = (unsigned long *)guest_cr3, gpa; + u64 pte, offset_in_page; + unsigned offset; + + for (l = EPT_PAGE_LEVEL; ; --l) { + offset = (guest_addr >> EPT_LEVEL_SHIFT(l)) & EPT_PGDIR_MASK; + + clear_ept_ad_pte(pml4, (u64) &pt[offset]); + pte = pt[offset]; + if (l == 1 || (l < 4 && (pte & PT_PAGE_SIZE_MASK))) + break; + if (!(pte & PT_PRESENT_MASK)) + return; + pt = (unsigned long *)(pte & PT_ADDR_MASK); + } + + offset = (guest_addr >> EPT_LEVEL_SHIFT(l)) & EPT_PGDIR_MASK; + offset_in_page = guest_addr & ((1 << EPT_LEVEL_SHIFT(l)) - 1); + gpa = (pt[offset] & PT_ADDR_MASK) | (guest_addr & offset_in_page); + clear_ept_ad_pte(pml4, gpa); +} + +/* check_ept_ad : Check the content of EPT A/D bits for the page table + walk and the final GPA of a guest address. */ +void check_ept_ad(unsigned long *pml4, u64 guest_cr3, + unsigned long guest_addr, int expected_gpa_ad, + int expected_pt_ad) +{ + int l; + unsigned long *pt = (unsigned long *)guest_cr3, gpa; + u64 ept_pte, pte, offset_in_page; + unsigned offset; + bool bad_pt_ad = false; + + for (l = EPT_PAGE_LEVEL; ; --l) { + offset = (guest_addr >> EPT_LEVEL_SHIFT(l)) & EPT_PGDIR_MASK; + + if (!get_ept_pte(pml4, (u64) &pt[offset], 1, &ept_pte)) { + printf("EPT - guest level %d page table is not mapped.\n", l); + return; + } + + if (!bad_pt_ad) { + bad_pt_ad |= (ept_pte & (EPT_ACCESS_FLAG|EPT_DIRTY_FLAG)) != expected_pt_ad; + if (bad_pt_ad) + report("EPT - guest level %d page table A=%d/D=%d", + false, l, + !!(expected_pt_ad & EPT_ACCESS_FLAG), + !!(expected_pt_ad & EPT_DIRTY_FLAG)); + } + + pte = pt[offset]; + if (l == 1 || (l < 4 && (pte & PT_PAGE_SIZE_MASK))) + break; + if (!(pte & PT_PRESENT_MASK)) + return; + pt = (unsigned long *)(pte & PT_ADDR_MASK); + } + + if (!bad_pt_ad) + report("EPT - guest page table structures A=%d/D=%d", + true, + !!(expected_pt_ad & EPT_ACCESS_FLAG), + !!(expected_pt_ad & EPT_DIRTY_FLAG)); + + offset = (guest_addr >> EPT_LEVEL_SHIFT(l)) & EPT_PGDIR_MASK; + offset_in_page = guest_addr & ((1 << EPT_LEVEL_SHIFT(l)) - 1); + gpa = (pt[offset] & PT_ADDR_MASK) | (guest_addr & offset_in_page); + + if (!get_ept_pte(pml4, gpa, 1, &ept_pte)) { + report("EPT - guest physical address is not mapped", false); + return; + } + report("EPT - guest physical address A=%d/D=%d", + (ept_pte & (EPT_ACCESS_FLAG|EPT_DIRTY_FLAG)) == expected_gpa_ad, + !!(expected_gpa_ad & EPT_ACCESS_FLAG), + !!(expected_gpa_ad & EPT_DIRTY_FLAG)); +} + + void ept_sync(int type, u64 eptp) { switch (type) { @@ -441,34 +939,62 @@ void ept_sync(int type, u64 eptp) } } -int set_ept_pte(unsigned long *pml4, unsigned long guest_addr, - int level, u64 pte_val) +void set_ept_pte(unsigned long *pml4, unsigned long guest_addr, + int level, u64 pte_val) { int l; unsigned long *pt = pml4; unsigned offset; - if (level < 1 || level > 3) - return -1; + assert(level >= 1 && level <= 4); + for (l = EPT_PAGE_LEVEL; ; --l) { offset = (guest_addr >> EPT_LEVEL_SHIFT(l)) & EPT_PGDIR_MASK; if (l == level) break; - if (!(pt[offset] & (EPT_PRESENT))) - return -1; + assert(pt[offset] & EPT_PRESENT); pt = (unsigned long *)(pt[offset] & EPT_ADDR_MASK); } offset = (guest_addr >> EPT_LEVEL_SHIFT(l)) & EPT_PGDIR_MASK; pt[offset] = pte_val; - return 0; +} + +bool ept_2m_supported(void) +{ + return ept_vpid.val & EPT_CAP_2M_PAGE; +} + +bool ept_1g_supported(void) +{ + return ept_vpid.val & EPT_CAP_1G_PAGE; +} + +bool ept_huge_pages_supported(int level) +{ + if (level == 2) + return ept_2m_supported(); + else if (level == 3) + return ept_1g_supported(); + else + return false; +} + +bool ept_execute_only_supported(void) +{ + return ept_vpid.val & EPT_CAP_WT; +} + +bool ept_ad_bits_supported(void) +{ + return ept_vpid.val & EPT_CAP_AD_FLAG; } void vpid_sync(int type, u16 vpid) { switch(type) { - case INVVPID_SINGLE: - if (ept_vpid.val & VPID_CAP_INVVPID_SINGLE) { - invvpid(INVVPID_SINGLE, vpid, 0); + case INVVPID_CONTEXT_GLOBAL: + if (ept_vpid.val & VPID_CAP_INVVPID_CXTGLB) { + invvpid(INVVPID_CONTEXT_GLOBAL, vpid, 0); break; } case INVVPID_ALL: @@ -799,9 +1325,12 @@ static void test_vmptrld(void) make_vmcs_current(tmp_root) == 1); /* Pass VMXON region */ + make_vmcs_current(vmcs); tmp_root = (struct vmcs *)vmxon_region; report("test vmptrld with vmxon region", make_vmcs_current(tmp_root) == 1); + report("test vmptrld with vmxon region vm-instruction error", + vmcs_read(VMX_INST_ERROR) == VMXERR_VMPTRLD_VMXON_POINTER); report("test vmptrld with valid vmcs region", make_vmcs_current(vmcs) == 0); } @@ -866,7 +1395,7 @@ static void test_vmx_caps(void) ok = ctrl.clr == true_ctrl.clr; ok = ok && ctrl.set == (true_ctrl.set | default1); } - report(vmx_ctl_msr[n].name, ok); + report("%s", ok, vmx_ctl_msr[n].name); } fixed0 = rdmsr(MSR_IA32_VMX_CR0_FIXED0); @@ -886,7 +1415,7 @@ static void test_vmx_caps(void) val = rdmsr(MSR_IA32_VMX_EPT_VPID_CAP); report("MSR_IA32_VMX_EPT_VPID_CAP", - (val & 0xfffff07ef9eebebeUll) == 0); + (val & 0xfffff07ef98cbebeUll) == 0); } /* This function can only be called in guest */ @@ -918,12 +1447,51 @@ static int handle_hypercall() switch (hypercall_no) { case HYPERCALL_VMEXIT: return VMX_TEST_VMEXIT; + case HYPERCALL_VMABORT: + return VMX_TEST_VMABORT; + case HYPERCALL_VMSKIP: + return VMX_TEST_VMSKIP; default: printf("ERROR : Invalid hypercall number : %ld\n", hypercall_no); } return VMX_TEST_EXIT; } +static void continue_abort(void) +{ + assert(!in_guest); + printf("Host was here when guest aborted:\n"); + dump_stack(); + longjmp(abort_target, 1); + abort(); +} + +void __abort_test(void) +{ + if (in_guest) + hypercall(HYPERCALL_VMABORT); + else + longjmp(abort_target, 1); + abort(); +} + +static void continue_skip(void) +{ + assert(!in_guest); + longjmp(abort_target, 1); + abort(); +} + +void test_skip(const char *msg) +{ + printf("%s skipping test: %s\n", in_guest ? "Guest" : "Host", msg); + if (in_guest) + hypercall(HYPERCALL_VMABORT); + else + longjmp(abort_target, 1); + abort(); +} + static int exit_handler() { int ret; @@ -954,43 +1522,56 @@ entry_failure_handler(struct vmentry_failure *failure) return VMX_TEST_EXIT; } +/* + * Tries to enter the guest. Returns true iff entry succeeded. Otherwise, + * populates @failure. + */ +static bool vmx_enter_guest(struct vmentry_failure *failure) +{ + failure->early = 0; + + in_guest = 1; + asm volatile ( + "mov %[HOST_RSP], %%rdi\n\t" + "vmwrite %%rsp, %%rdi\n\t" + LOAD_GPR_C + "cmpb $0, %[launched]\n\t" + "jne 1f\n\t" + "vmlaunch\n\t" + "jmp 2f\n\t" + "1: " + "vmresume\n\t" + "2: " + SAVE_GPR_C + "pushf\n\t" + "pop %%rdi\n\t" + "mov %%rdi, %[failure_flags]\n\t" + "movl $1, %[failure_flags]\n\t" + "jmp 3f\n\t" + "vmx_return:\n\t" + SAVE_GPR_C + "3: \n\t" + : [failure_early]"+m"(failure->early), + [failure_flags]"=m"(failure->flags) + : [launched]"m"(launched), [HOST_RSP]"i"(HOST_RSP) + : "rdi", "memory", "cc" + ); + in_guest = 0; + + failure->vmlaunch = !launched; + failure->instr = launched ? "vmresume" : "vmlaunch"; + + return !failure->early && !(vmcs_read(EXI_REASON) & VMX_ENTRY_FAILURE); +} + static int vmx_run() { - unsigned long host_rflags; - while (1) { u32 ret; - u32 fail = 0; bool entered; struct vmentry_failure failure; - asm volatile ( - "mov %[HOST_RSP], %%rdi\n\t" - "vmwrite %%rsp, %%rdi\n\t" - LOAD_GPR_C - "cmpb $0, %[launched]\n\t" - "jne 1f\n\t" - "vmlaunch\n\t" - "jmp 2f\n\t" - "1: " - "vmresume\n\t" - "2: " - SAVE_GPR_C - "pushf\n\t" - "pop %%rdi\n\t" - "mov %%rdi, %[host_rflags]\n\t" - "movl $1, %[fail]\n\t" - "jmp 3f\n\t" - "vmx_return:\n\t" - SAVE_GPR_C - "3: \n\t" - : [fail]"+m"(fail), [host_rflags]"=m"(host_rflags) - : [launched]"m"(launched), [HOST_RSP]"i"(HOST_RSP) - : "rdi", "memory", "cc" - - ); - - entered = !fail && !(vmcs_read(EXI_REASON) & VMX_ENTRY_FAILURE); + entered = vmx_enter_guest(&failure); if (entered) { /* @@ -1000,10 +1581,6 @@ static int vmx_run() launched = 1; ret = exit_handler(); } else { - failure.flags = host_rflags; - failure.vmlaunch = !launched; - failure.instr = launched ? "vmresume" : "vmlaunch"; - failure.early = fail; ret = entry_failure_handler(&failure); } @@ -1011,6 +1588,7 @@ static int vmx_run() case VMX_TEST_RESUME: continue; case VMX_TEST_VMEXIT: + guest_finished = 1; return 0; case VMX_TEST_EXIT: break; @@ -1029,26 +1607,67 @@ static int vmx_run() } } +static void run_teardown_step(struct test_teardown_step *step) +{ + step->func(step->data); +} + static int test_run(struct vmx_test *test) { + int r; + + /* Validate V2 interface. */ + if (test->v2) { + int ret = 0; + if (test->init || test->guest_main || test->exit_handler || + test->syscall_handler) { + report("V2 test cannot specify V1 callbacks.", 0); + ret = 1; + } + if (ret) + return ret; + } + if (test->name == NULL) test->name = "(no name)"; if (vmx_on()) { printf("%s : vmxon failed.\n", __func__); return 1; } + init_vmcs(&(test->vmcs)); /* Directly call test->init is ok here, init_vmcs has done vmcs init, vmclear and vmptrld*/ if (test->init && test->init(test->vmcs) != VMX_TEST_START) goto out; + teardown_count = 0; + v2_guest_main = NULL; test->exits = 0; current = test; regs = test->guest_regs; vmcs_write(GUEST_RFLAGS, regs.rflags | 0x2); launched = 0; + guest_finished = 0; printf("\nTest suite: %s\n", test->name); - vmx_run(); + + r = setjmp(abort_target); + if (r) { + assert(!in_guest); + goto out; + } + + + if (test->v2) + test->v2(); + else + vmx_run(); + + while (teardown_count > 0) + run_teardown_step(&teardown_steps[--teardown_count]); + + if (launched && !guest_finished) + report("Guest didn't run to completion.", 0); + out: if (vmx_off()) { printf("%s : vmxoff failed.\n", __func__); @@ -1057,9 +1676,116 @@ out: return 0; } +/* + * Add a teardown step. Executed after the test's main function returns. + * Teardown steps executed in reverse order. + */ +void test_add_teardown(test_teardown_func func, void *data) +{ + struct test_teardown_step *step; + + TEST_ASSERT_MSG(teardown_count < MAX_TEST_TEARDOWN_STEPS, + "There are already %d teardown steps.", + teardown_count); + step = &teardown_steps[teardown_count++]; + step->func = func; + step->data = data; +} + +/* + * Set the target of the first enter_guest call. Can only be called once per + * test. Must be called before first enter_guest call. + */ +void test_set_guest(test_guest_func func) +{ + assert(current->v2); + TEST_ASSERT_MSG(!v2_guest_main, "Already set guest func."); + v2_guest_main = func; +} + +/* + * Enters the guest (or launches it for the first time). Error to call once the + * guest has returned (i.e., run past the end of its guest() function). Also + * aborts if guest entry fails. + */ +void enter_guest(void) +{ + struct vmentry_failure failure; + + TEST_ASSERT_MSG(v2_guest_main, + "Never called test_set_guest_func!"); + + TEST_ASSERT_MSG(!guest_finished, + "Called enter_guest() after guest returned."); + + if (!vmx_enter_guest(&failure)) { + print_vmentry_failure_info(&failure); + abort(); + } + + launched = 1; + + if (is_hypercall()) { + int ret; + + ret = handle_hypercall(); + switch (ret) { + case VMX_TEST_VMEXIT: + guest_finished = 1; + break; + case VMX_TEST_VMABORT: + continue_abort(); + break; + case VMX_TEST_VMSKIP: + continue_skip(); + break; + default: + printf("ERROR : Invalid handle_hypercall return %d.\n", + ret); + abort(); + } + } +} + extern struct vmx_test vmx_tests[]; -int main(void) +static bool +test_wanted(const char *name, const char *filters[], int filter_count) +{ + int i; + bool positive = false; + bool match = false; + char clean_name[strlen(name) + 1]; + char *c; + const char *n; + + /* Replace spaces with underscores. */ + n = name; + c = &clean_name[0]; + do *c++ = (*n == ' ') ? '_' : *n; + while (*n++); + + for (i = 0; i < filter_count; i++) { + const char *filter = filters[i]; + + if (filter[0] == '-') { + if (simple_glob(clean_name, filter + 1)) + return false; + } else { + positive = true; + match |= simple_glob(clean_name, filter); + } + } + + if (!positive || match) { + matched++; + return true; + } else { + return false; + } +} + +int main(int argc, const char *argv[]) { int i = 0; @@ -1067,31 +1793,59 @@ int main(void) setup_idt(); hypercall_field = 0; + argv++; + argc--; + if (!(cpuid(1).c & (1 << 5))) { printf("WARNING: vmx not supported, add '-cpu host'\n"); goto exit; } init_vmx(); - if (test_vmx_feature_control() != 0) - goto exit; - /* Set basic test ctxt the same as "null" */ - current = &vmx_tests[0]; - if (test_vmxon() != 0) - goto exit; - test_vmptrld(); - test_vmclear(); - test_vmptrst(); - init_vmcs(&vmcs_root); - if (vmx_run()) { - report("test vmlaunch", 0); - goto exit; + if (test_wanted("test_vmx_feature_control", argv, argc)) { + /* Sets MSR_IA32_FEATURE_CONTROL to 0x5 */ + if (test_vmx_feature_control() != 0) + goto exit; + } else { + if ((rdmsr(MSR_IA32_FEATURE_CONTROL) & 0x5) != 0x5) + wrmsr(MSR_IA32_FEATURE_CONTROL, 0x5); } - test_vmxoff(); - test_vmx_caps(); - while (vmx_tests[++i].name != NULL) + if (test_wanted("test_vmxon", argv, argc)) { + /* Enables VMX */ + if (test_vmxon() != 0) + goto exit; + } else { + if (vmx_on()) { + report("vmxon", 0); + goto exit; + } + } + + if (test_wanted("test_vmptrld", argv, argc)) + test_vmptrld(); + if (test_wanted("test_vmclear", argv, argc)) + test_vmclear(); + if (test_wanted("test_vmptrst", argv, argc)) + test_vmptrst(); + if (test_wanted("test_vmwrite_vmread", argv, argc)) + test_vmwrite_vmread(); + if (test_wanted("test_vmcs_lifecycle", argv, argc)) + test_vmcs_lifecycle(); + if (test_wanted("test_vmx_caps", argv, argc)) + test_vmx_caps(); + + /* Balance vmxon from test_vmxon. */ + vmx_off(); + + for (; vmx_tests[i].name != NULL; i++) { + if (!test_wanted(vmx_tests[i].name, argv, argc)) + continue; if (test_run(&vmx_tests[i])) goto exit; + } + + if (!matched) + report("command line didn't match any tests!", matched); exit: return report_summary(); diff --git a/tests/kvm-unit-tests/x86/vmx.h b/tests/kvm-unit-tests/x86/vmx.h index a2bacd34..f32dffe1 100644 --- a/tests/kvm-unit-tests/x86/vmx.h +++ b/tests/kvm-unit-tests/x86/vmx.h @@ -5,6 +5,7 @@ #include "processor.h" #include "bitops.h" #include "asm/page.h" +#include "asm/io.h" struct vmcs { u32 revision_id; /* vmcs revision identifier */ @@ -13,6 +14,11 @@ struct vmcs { char data[0]; }; +struct invvpid_operand { + u64 vpid; + u64 gla; +}; + struct regs { u64 rax; u64 rcx; @@ -54,6 +60,8 @@ struct vmx_test { int (*entry_failure_handler)(struct vmentry_failure *failure); struct vmcs *vmcs; int exits; + /* Alternative test interface. */ + void (*v2)(void); }; union vmx_basic { @@ -108,6 +116,7 @@ enum Encoding { GUEST_SEL_LDTR = 0x080cul, GUEST_SEL_TR = 0x080eul, GUEST_INT_STATUS = 0x0810ul, + GUEST_PML_INDEX = 0x0812ul, /* 16-Bit Host State Fields */ HOST_SEL_ES = 0x0c00ul, @@ -132,6 +141,9 @@ enum Encoding { APIC_ACCS_ADDR = 0x2014ul, EPTP = 0x201aul, EPTP_HI = 0x201bul, + PMLADDR = 0x200eul, + PMLADDR_HI = 0x200ful, + /* 64-Bit Readonly Data Field */ INFO_PHYS_ADDR = 0x2400ul, @@ -317,7 +329,15 @@ enum Reason { VMX_PREEMPT = 52, VMX_INVVPID = 53, VMX_WBINVD = 54, - VMX_XSETBV = 55 + VMX_XSETBV = 55, + VMX_APIC_WRITE = 56, + VMX_RDRAND = 57, + VMX_INVPCID = 58, + VMX_VMFUNC = 59, + VMX_RDSEED = 61, + VMX_PML_FULL = 62, + VMX_XSAVES = 63, + VMX_XRSTORS = 64, }; enum Ctrl_exi { @@ -375,6 +395,7 @@ enum Ctrl1 { CPU_URG = 1ul << 7, CPU_WBINVD = 1ul << 6, CPU_RDRAND = 1ul << 11, + CPU_PML = 1ul << 17, }; enum Intr_type { @@ -396,6 +417,37 @@ enum Intr_type { #define INTR_INFO_INTR_TYPE_SHIFT 8 +/* + * VM-instruction error numbers + */ +enum vm_instruction_error_number { + VMXERR_VMCALL_IN_VMX_ROOT_OPERATION = 1, + VMXERR_VMCLEAR_INVALID_ADDRESS = 2, + VMXERR_VMCLEAR_VMXON_POINTER = 3, + VMXERR_VMLAUNCH_NONCLEAR_VMCS = 4, + VMXERR_VMRESUME_NONLAUNCHED_VMCS = 5, + VMXERR_VMRESUME_AFTER_VMXOFF = 6, + VMXERR_ENTRY_INVALID_CONTROL_FIELD = 7, + VMXERR_ENTRY_INVALID_HOST_STATE_FIELD = 8, + VMXERR_VMPTRLD_INVALID_ADDRESS = 9, + VMXERR_VMPTRLD_VMXON_POINTER = 10, + VMXERR_VMPTRLD_INCORRECT_VMCS_REVISION_ID = 11, + VMXERR_UNSUPPORTED_VMCS_COMPONENT = 12, + VMXERR_VMWRITE_READ_ONLY_VMCS_COMPONENT = 13, + VMXERR_VMXON_IN_VMX_ROOT_OPERATION = 15, + VMXERR_ENTRY_INVALID_EXECUTIVE_VMCS_POINTER = 16, + VMXERR_ENTRY_NONLAUNCHED_EXECUTIVE_VMCS = 17, + VMXERR_ENTRY_EXECUTIVE_VMCS_POINTER_NOT_VMXON_POINTER = 18, + VMXERR_VMCALL_NONCLEAR_VMCS = 19, + VMXERR_VMCALL_INVALID_VM_EXIT_CONTROL_FIELDS = 20, + VMXERR_VMCALL_INCORRECT_MSEG_REVISION_ID = 22, + VMXERR_VMXOFF_UNDER_DUAL_MONITOR_TREATMENT_OF_SMIS_AND_SMM = 23, + VMXERR_VMCALL_INVALID_SMM_MONITOR_FEATURES = 24, + VMXERR_ENTRY_INVALID_VM_EXECUTION_CONTROL_FIELDS_IN_EXECUTIVE_VMCS = 25, + VMXERR_ENTRY_EVENTS_BLOCKED_BY_MOV_SS = 26, + VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID = 28, +}; + #define SAVE_GPR \ "xchg %rax, regs\n\t" \ "xchg %rbx, regs+0x8\n\t" \ @@ -451,10 +503,14 @@ enum Intr_type { #define VMX_TEST_VMEXIT 1 #define VMX_TEST_EXIT 2 #define VMX_TEST_RESUME 3 +#define VMX_TEST_VMABORT 4 +#define VMX_TEST_VMSKIP 5 #define HYPERCALL_BIT (1ul << 12) #define HYPERCALL_MASK 0xFFF #define HYPERCALL_VMEXIT 0x1 +#define HYPERCALL_VMABORT 0x2 +#define HYPERCALL_VMSKIP 0x3 #define EPTP_PG_WALK_LEN_SHIFT 3ul #define EPTP_AD_FLAG (1ul << 6) @@ -487,8 +543,10 @@ enum Intr_type { #define EPT_CAP_INVEPT_ALL (1ull << 26) #define EPT_CAP_AD_FLAG (1ull << 21) #define VPID_CAP_INVVPID (1ull << 32) -#define VPID_CAP_INVVPID_SINGLE (1ull << 41) -#define VPID_CAP_INVVPID_ALL (1ull << 42) +#define VPID_CAP_INVVPID_ADDR (1ull << 40) +#define VPID_CAP_INVVPID_CXTGLB (1ull << 41) +#define VPID_CAP_INVVPID_ALL (1ull << 42) +#define VPID_CAP_INVVPID_CXTLOC (1ull << 43) #define PAGE_SIZE_2M (512 * PAGE_SIZE) #define PAGE_SIZE_1G (512 * PAGE_SIZE_2M) @@ -506,19 +564,23 @@ enum Intr_type { #define EPT_VLT_PERM_RD (1 << 3) #define EPT_VLT_PERM_WR (1 << 4) #define EPT_VLT_PERM_EX (1 << 5) +#define EPT_VLT_PERMS (EPT_VLT_PERM_RD | EPT_VLT_PERM_WR | \ + EPT_VLT_PERM_EX) #define EPT_VLT_LADDR_VLD (1 << 7) #define EPT_VLT_PADDR (1 << 8) #define MAGIC_VAL_1 0x12345678ul #define MAGIC_VAL_2 0x87654321ul #define MAGIC_VAL_3 0xfffffffful +#define MAGIC_VAL_4 0xdeadbeeful #define INVEPT_SINGLE 1 #define INVEPT_GLOBAL 2 -#define INVVPID_SINGLE_ADDRESS 0 -#define INVVPID_SINGLE 1 +#define INVVPID_ADDR 0 +#define INVVPID_CONTEXT_GLOBAL 1 #define INVVPID_ALL 2 +#define INVVPID_CONTEXT_LOCAL 3 #define ACTV_ACTIVE 0 #define ACTV_HLT 1 @@ -532,10 +594,41 @@ extern union vmx_ctrl_msr ctrl_exit_rev; extern union vmx_ctrl_msr ctrl_enter_rev; extern union vmx_ept_vpid ept_vpid; +extern u64 *vmxon_region; + void vmx_set_test_stage(u32 s); u32 vmx_get_test_stage(void); void vmx_inc_test_stage(void); +static int vmx_on(void) +{ + bool ret; + u64 rflags = read_rflags() | X86_EFLAGS_CF | X86_EFLAGS_ZF; + asm volatile ("push %1; popf; vmxon %2; setbe %0\n\t" + : "=q" (ret) : "q" (rflags), "m" (vmxon_region) : "cc"); + return ret; +} + +static int vmx_off(void) +{ + bool ret; + u64 rflags = read_rflags() | X86_EFLAGS_CF | X86_EFLAGS_ZF; + + asm volatile("push %1; popf; vmxoff; setbe %0\n\t" + : "=q"(ret) : "q" (rflags) : "cc"); + return ret; +} + +static inline int make_vmcs_current(struct vmcs *vmcs) +{ + bool ret; + u64 rflags = read_rflags() | X86_EFLAGS_CF | X86_EFLAGS_ZF; + + asm volatile ("push %1; popf; vmptrld %2; setbe %0" + : "=q" (ret) : "q" (rflags), "m" (vmcs) : "cc"); + return ret; +} + static inline int vmcs_clear(struct vmcs *vmcs) { bool ret; @@ -553,6 +646,25 @@ static inline u64 vmcs_read(enum Encoding enc) return val; } +static inline int vmcs_read_checking(enum Encoding enc, u64 *value) +{ + u64 rflags = read_rflags() | X86_EFLAGS_CF | X86_EFLAGS_ZF; + u64 encoding = enc; + u64 val; + + asm volatile ("shl $8, %%rax;" + "sahf;" + "vmread %[encoding], %[val];" + "lahf;" + "shr $8, %%rax" + : /* output */ [val]"=rm"(val), "+a"(rflags) + : /* input */ [encoding]"r"(encoding) + : /* clobber */ "cc"); + + *value = val; + return rflags & (X86_EFLAGS_CF | X86_EFLAGS_ZF); +} + static inline int vmcs_write(enum Encoding enc, u64 val) { bool ret; @@ -564,10 +676,12 @@ static inline int vmcs_write(enum Encoding enc, u64 val) static inline int vmcs_save(struct vmcs **vmcs) { bool ret; + unsigned long pa; u64 rflags = read_rflags() | X86_EFLAGS_CF | X86_EFLAGS_ZF; - asm volatile ("push %1; popf; vmptrst %2; setbe %0" - : "=q" (ret) : "q" (rflags), "m" (*vmcs) : "cc"); + asm volatile ("push %2; popf; vmptrst %1; setbe %0" + : "=q" (ret), "=m" (pa) : "r" (rflags) : "cc"); + *vmcs = (pa == -1ull) ? NULL : phys_to_virt(pa); return ret; } @@ -584,21 +698,18 @@ static inline bool invept(unsigned long type, u64 eptp) return ret; } -static inline bool invvpid(unsigned long type, u16 vpid, u64 gva) +static inline bool invvpid(unsigned long type, u64 vpid, u64 gla) { bool ret; u64 rflags = read_rflags() | X86_EFLAGS_CF | X86_EFLAGS_ZF; - struct { - u64 vpid : 16; - u64 rsvd : 48; - u64 gva; - } operand = {vpid, 0, gva}; + struct invvpid_operand operand = {vpid, gla}; asm volatile("push %1; popf; invvpid %2, %3; setbe %0" : "=q" (ret) : "r" (rflags), "m"(operand),"r"(type) : "cc"); return ret; } +const char *exit_reason_description(u64 reason); void print_vmexit_info(); void print_vmentry_failure_info(struct vmentry_failure *failure); void ept_sync(int type, u64 eptp); @@ -614,9 +725,83 @@ void install_ept(unsigned long *pml4, unsigned long phys, unsigned long guest_addr, u64 perm); void setup_ept_range(unsigned long *pml4, unsigned long start, unsigned long len, int map_1g, int map_2m, u64 perm); -unsigned long get_ept_pte(unsigned long *pml4, - unsigned long guest_addr, int level); -int set_ept_pte(unsigned long *pml4, unsigned long guest_addr, +bool get_ept_pte(unsigned long *pml4, unsigned long guest_addr, int level, + unsigned long *pte); +void set_ept_pte(unsigned long *pml4, unsigned long guest_addr, int level, u64 pte_val); +void check_ept_ad(unsigned long *pml4, u64 guest_cr3, + unsigned long guest_addr, int expected_gpa_ad, + int expected_pt_ad); +void clear_ept_ad(unsigned long *pml4, u64 guest_cr3, + unsigned long guest_addr); + +bool ept_2m_supported(void); +bool ept_1g_supported(void); +bool ept_huge_pages_supported(int level); +bool ept_execute_only_supported(void); +bool ept_ad_bits_supported(void); + +void enter_guest(void); + +typedef void (*test_guest_func)(void); +typedef void (*test_teardown_func)(void *data); +void test_set_guest(test_guest_func func); +void test_add_teardown(test_teardown_func func, void *data); +void test_skip(const char *msg); + +void __abort_test(void); + +#define TEST_ASSERT(cond) \ +do { \ + if (!(cond)) { \ + report("%s:%d: Assertion failed: %s", 0, \ + __FILE__, __LINE__, #cond); \ + dump_stack(); \ + __abort_test(); \ + } \ + report_pass(); \ +} while (0) + +#define TEST_ASSERT_MSG(cond, fmt, args...) \ +do { \ + if (!(cond)) { \ + report("%s:%d: Assertion failed: %s\n" fmt, 0, \ + __FILE__, __LINE__, #cond, ##args); \ + dump_stack(); \ + __abort_test(); \ + } \ + report_pass(); \ +} while (0) + +#define __TEST_EQ(a, b, a_str, b_str, assertion, fmt, args...) \ +do { \ + typeof(a) _a = a; \ + typeof(b) _b = b; \ + if (_a != _b) { \ + char _bin_a[BINSTR_SZ]; \ + char _bin_b[BINSTR_SZ]; \ + binstr(_a, _bin_a); \ + binstr(_b, _bin_b); \ + report("%s:%d: %s failed: (%s) == (%s)\n" \ + "\tLHS: %#018lx - %s - %lu\n" \ + "\tRHS: %#018lx - %s - %lu%s" fmt, 0, \ + __FILE__, __LINE__, \ + assertion ? "Assertion" : "Expectation", a_str, b_str, \ + (unsigned long) _a, _bin_a, (unsigned long) _a, \ + (unsigned long) _b, _bin_b, (unsigned long) _b, \ + fmt[0] == '\0' ? "" : "\n", ## args); \ + dump_stack(); \ + if (assertion) \ + __abort_test(); \ + } \ + report_pass(); \ +} while (0) + +#define TEST_ASSERT_EQ(a, b) __TEST_EQ(a, b, #a, #b, 1, "") +#define TEST_ASSERT_EQ_MSG(a, b, fmt, args...) \ + __TEST_EQ(a, b, #a, #b, 1, fmt, ## args) +#define TEST_EXPECT_EQ(a, b) __TEST_EQ(a, b, #a, #b, 0, "") +#define TEST_EXPECT_EQ_MSG(a, b, fmt, args...) \ + __TEST_EQ(a, b, #a, #b, 0, fmt, ## args) #endif diff --git a/tests/kvm-unit-tests/x86/vmx_tests.c b/tests/kvm-unit-tests/x86/vmx_tests.c index fff12141..0ccc7e77 100644 --- a/tests/kvm-unit-tests/x86/vmx_tests.c +++ b/tests/kvm-unit-tests/x86/vmx_tests.c @@ -13,6 +13,10 @@ #include "apic.h" #include "types.h" +#define NONCANONICAL 0xaaaaaaaaaaaaaaaaull + +#define VPID_CAP_INVVPID_TYPES_SHIFT 40 + u64 ia32_pat; u64 ia32_efer; void *io_bitmap_a, *io_bitmap_b; @@ -22,6 +26,18 @@ unsigned long *pml4; u64 eptp; void *data_page1, *data_page2; +void *pml_log; +#define PML_INDEX 512 + +static inline unsigned ffs(unsigned x) +{ + int pos = -1; + + __asm__ __volatile__("bsf %1, %%eax; cmovnz %%eax, %0" + : "+r"(pos) : "rm"(x) : "eax"); + return pos + 1; +} + static inline void vmcall() { asm volatile("vmcall"); @@ -29,6 +45,7 @@ static inline void vmcall() void basic_guest_main() { + report("Basic VMX test", 1); } int basic_exit_handler() @@ -163,7 +180,7 @@ int preemption_timer_exit_handler() saved_rip == guest_rip); break; default: - printf("Invalid stage.\n"); + report("Invalid stage.", false); print_vmexit_info(); break; } @@ -204,14 +221,14 @@ int preemption_timer_exit_handler() break; default: // Should not reach here - printf("ERROR : unexpected stage, %d\n", + report("unexpected stage, %d", false, vmx_get_test_stage()); print_vmexit_info(); return VMX_TEST_VMEXIT; } break; default: - printf("Unknown exit reason, %ld\n", reason); + report("Unknown exit reason, %ld", false, reason); print_vmexit_info(); } vmcs_write(PIN_CONTROLS, vmcs_read(PIN_CONTROLS) & ~PIN_PREEMPT); @@ -508,7 +525,7 @@ static int cr_shadowing_exit_handler() break; default: // Should not reach here - printf("ERROR : unexpected stage, %d\n", + report("unexpected stage, %d", false, vmx_get_test_stage()); print_vmexit_info(); return VMX_TEST_VMEXIT; @@ -547,7 +564,7 @@ static int cr_shadowing_exit_handler() break; default: // Should not reach here - printf("ERROR : unexpected stage, %d\n", + report("unexpected stage, %d", false, vmx_get_test_stage()); print_vmexit_info(); return VMX_TEST_VMEXIT; @@ -555,7 +572,7 @@ static int cr_shadowing_exit_handler() vmcs_write(GUEST_RIP, guest_rip + insn_len); return VMX_TEST_RESUME; default: - printf("Unknown exit reason, %ld\n", reason); + report("Unknown exit reason, %ld", false, reason); print_vmexit_info(); } return VMX_TEST_VMEXIT; @@ -686,7 +703,7 @@ static int iobmp_exit_handler() break; default: // Should not reach here - printf("ERROR : unexpected stage, %d\n", + report("unexpected stage, %d", false, vmx_get_test_stage()); print_vmexit_info(); return VMX_TEST_VMEXIT; @@ -707,7 +724,7 @@ static int iobmp_exit_handler() break; default: // Should not reach here - printf("ERROR : unexpected stage, %d\n", + report("unexpected stage, %d", false, vmx_get_test_stage()); print_vmexit_info(); return VMX_TEST_VMEXIT; @@ -715,7 +732,7 @@ static int iobmp_exit_handler() vmcs_write(GUEST_RIP, guest_rip + insn_len); return VMX_TEST_RESUME; default: - printf("guest_rip = 0x%lx\n", guest_rip); + printf("guest_rip = %#lx\n", guest_rip); printf("\tERROR : Undefined exit reason, reason = %ld.\n", reason); break; } @@ -732,7 +749,7 @@ static int iobmp_exit_handler() asm( "insn_hlt: hlt;ret\n\t" "insn_invlpg: invlpg 0x12345678;ret\n\t" - "insn_mwait: mwait;ret\n\t" + "insn_mwait: xor %eax, %eax; xor %ecx, %ecx; mwait;ret\n\t" "insn_rdpmc: xor %ecx, %ecx; rdpmc;ret\n\t" "insn_rdtsc: rdtsc;ret\n\t" "insn_cr3_load: mov cr3,%rax; mov %rax,%cr3;ret\n\t" @@ -741,7 +758,7 @@ asm( "insn_cr8_load: mov %rax,%cr8;ret\n\t" "insn_cr8_store: mov %cr8,%rax;ret\n\t" #endif - "insn_monitor: monitor;ret\n\t" + "insn_monitor: xor %eax, %eax; xor %ecx, %ecx; xor %edx, %edx; monitor;ret\n\t" "insn_pause: pause;ret\n\t" "insn_wbinvd: wbinvd;ret\n\t" "insn_cpuid: mov $10, %eax; cpuid;ret\n\t" @@ -939,10 +956,18 @@ static int insn_intercept_exit_handler() } -static int setup_ept() +/* Enables EPT and sets up the identity map. */ +static int setup_ept(bool enable_ad) { - int support_2m; unsigned long end_of_memory; + u32 ctrl_cpu[2]; + + if (!(ctrl_cpu_rev[0].clr & CPU_SECONDARY) || + !(ctrl_cpu_rev[1].clr & CPU_EPT)) { + printf("\tEPT is not supported"); + return 1; + } + if (!(ept_vpid.val & EPT_CAP_UC) && !(ept_vpid.val & EPT_CAP_WB)) { @@ -958,32 +983,6 @@ static int setup_ept() printf("\tPWL4 is not supported\n"); return 1; } - eptp |= (3 << EPTP_PG_WALK_LEN_SHIFT); - pml4 = alloc_page(); - memset(pml4, 0, PAGE_SIZE); - eptp |= virt_to_phys(pml4); - vmcs_write(EPTP, eptp); - support_2m = !!(ept_vpid.val & EPT_CAP_2M_PAGE); - end_of_memory = fwcfg_get_u64(FW_CFG_RAM_SIZE); - if (end_of_memory < (1ul << 32)) - end_of_memory = (1ul << 32); - setup_ept_range(pml4, 0, end_of_memory, 0, support_2m, - EPT_WA | EPT_RA | EPT_EA); - return 0; -} - -static int apic_version; - -static int ept_init() -{ - u32 ctrl_cpu[2]; - - if (!(ctrl_cpu_rev[0].clr & CPU_SECONDARY) || - !(ctrl_cpu_rev[1].clr & CPU_EPT)) { - printf("\tEPT is not supported"); - return VMX_TEST_EXIT; - } - ctrl_cpu[0] = vmcs_read(CPU_EXEC_CTRL0); ctrl_cpu[1] = vmcs_read(CPU_EXEC_CTRL1); ctrl_cpu[0] = (ctrl_cpu[0] | CPU_SECONDARY) @@ -992,7 +991,49 @@ static int ept_init() & ctrl_cpu_rev[1].clr; vmcs_write(CPU_EXEC_CTRL0, ctrl_cpu[0]); vmcs_write(CPU_EXEC_CTRL1, ctrl_cpu[1]); - if (setup_ept()) + eptp |= (3 << EPTP_PG_WALK_LEN_SHIFT); + pml4 = alloc_page(); + memset(pml4, 0, PAGE_SIZE); + eptp |= virt_to_phys(pml4); + if (enable_ad) + eptp |= EPTP_AD_FLAG; + vmcs_write(EPTP, eptp); + end_of_memory = fwcfg_get_u64(FW_CFG_RAM_SIZE); + if (end_of_memory < (1ul << 32)) + end_of_memory = (1ul << 32); + /* Cannot use large EPT pages if we need to track EPT + * accessed/dirty bits at 4K granularity. + */ + setup_ept_range(pml4, 0, end_of_memory, 0, + !enable_ad && ept_2m_supported(), + EPT_WA | EPT_RA | EPT_EA); + return 0; +} + +static void ept_enable_ad_bits(void) +{ + eptp |= EPTP_AD_FLAG; + vmcs_write(EPTP, eptp); +} + +static void ept_disable_ad_bits(void) +{ + eptp &= ~EPTP_AD_FLAG; + vmcs_write(EPTP, eptp); +} + +static void ept_enable_ad_bits_or_skip_test(void) +{ + if (!ept_ad_bits_supported()) + test_skip("EPT AD bits not supported."); + ept_enable_ad_bits(); +} + +static int apic_version; + +static int ept_init_common(bool have_ad) +{ + if (setup_ept(have_ad)) return VMX_TEST_EXIT; data_page1 = alloc_page(); data_page2 = alloc_page(); @@ -1003,11 +1044,16 @@ static int ept_init() install_ept(pml4, (unsigned long)data_page1, (unsigned long)data_page2, EPT_RA | EPT_WA | EPT_EA); - apic_version = *((u32 *)0xfee00030UL); + apic_version = apic_read(APIC_LVR); return VMX_TEST_START; } -static void ept_main() +static int ept_init() +{ + return ept_init_common(false); +} + +static void ept_common() { vmx_set_test_stage(0); if (*((u32 *)data_page2) != MAGIC_VAL_1 || @@ -1047,6 +1093,11 @@ t1: vmcall(); *((u32 *)data_page1) = MAGIC_VAL_2; report("EPT violation - paging structure", vmx_get_test_stage() == 5); +} + +static void ept_main() +{ + ept_common(); // Test EPT access to L1 MMIO vmx_set_test_stage(6); @@ -1075,15 +1126,63 @@ bool invept_test(int type, u64 eptp) return true; } -static int ept_exit_handler() +static int pml_exit_handler(void) +{ + u16 index, count; + ulong reason = vmcs_read(EXI_REASON) & 0xff; + u64 *pmlbuf = pml_log; + u64 guest_rip = vmcs_read(GUEST_RIP);; + u64 guest_cr3 = vmcs_read(GUEST_CR3); + u32 insn_len = vmcs_read(EXI_INST_LEN); + + switch (reason) { + case VMX_VMCALL: + switch (vmx_get_test_stage()) { + case 0: + index = vmcs_read(GUEST_PML_INDEX); + for (count = index + 1; count < PML_INDEX; count++) { + if (pmlbuf[count] == (u64)data_page2) { + vmx_inc_test_stage(); + clear_ept_ad(pml4, guest_cr3, (unsigned long)data_page2); + break; + } + } + break; + case 1: + index = vmcs_read(GUEST_PML_INDEX); + /* Keep clearing the dirty bit till a overflow */ + clear_ept_ad(pml4, guest_cr3, (unsigned long)data_page2); + break; + default: + report("unexpected stage, %d.", false, + vmx_get_test_stage()); + print_vmexit_info(); + return VMX_TEST_VMEXIT; + } + vmcs_write(GUEST_RIP, guest_rip + insn_len); + return VMX_TEST_RESUME; + case VMX_PML_FULL: + vmx_inc_test_stage(); + vmcs_write(GUEST_PML_INDEX, PML_INDEX - 1); + return VMX_TEST_RESUME; + default: + report("Unknown exit reason, %ld", false, reason); + print_vmexit_info(); + } + return VMX_TEST_VMEXIT; +} + +static int ept_exit_handler_common(bool have_ad) { u64 guest_rip; + u64 guest_cr3; ulong reason; u32 insn_len; u32 exit_qual; static unsigned long data_page1_pte, data_page1_pte_pte; guest_rip = vmcs_read(GUEST_RIP); + guest_cr3 = vmcs_read(GUEST_CR3); reason = vmcs_read(EXI_REASON) & 0xff; insn_len = vmcs_read(EXI_INST_LEN); exit_qual = vmcs_read(EXI_QUALIFICATION); @@ -1091,6 +1190,18 @@ static int ept_exit_handler() case VMX_VMCALL: switch (vmx_get_test_stage()) { case 0: + check_ept_ad(pml4, guest_cr3, + (unsigned long)data_page1, + have_ad ? EPT_ACCESS_FLAG : 0, + have_ad ? EPT_ACCESS_FLAG | EPT_DIRTY_FLAG : 0); + check_ept_ad(pml4, guest_cr3, + (unsigned long)data_page2, + have_ad ? EPT_ACCESS_FLAG | EPT_DIRTY_FLAG : 0, + have_ad ? EPT_ACCESS_FLAG | EPT_DIRTY_FLAG : 0); + clear_ept_ad(pml4, guest_cr3, (unsigned long)data_page1); + clear_ept_ad(pml4, guest_cr3, (unsigned long)data_page2); + if (have_ad) + ept_sync(INVEPT_SINGLE, eptp);; if (*((u32 *)data_page1) == MAGIC_VAL_3 && *((u32 *)data_page2) == MAGIC_VAL_2) { vmx_inc_test_stage(); @@ -1113,19 +1224,21 @@ static int ept_exit_handler() ept_sync(INVEPT_SINGLE, eptp); break; case 3: - data_page1_pte = get_ept_pte(pml4, - (unsigned long)data_page1, 1); + clear_ept_ad(pml4, guest_cr3, (unsigned long)data_page1); + TEST_ASSERT(get_ept_pte(pml4, (unsigned long)data_page1, + 1, &data_page1_pte)); set_ept_pte(pml4, (unsigned long)data_page1, - 1, data_page1_pte & (~EPT_PRESENT)); + 1, data_page1_pte & ~EPT_PRESENT); ept_sync(INVEPT_SINGLE, eptp); break; case 4: - data_page1_pte = get_ept_pte(pml4, - (unsigned long)data_page1, 2); + TEST_ASSERT(get_ept_pte(pml4, (unsigned long)data_page1, + 2, &data_page1_pte)); data_page1_pte &= PAGE_MASK; - data_page1_pte_pte = get_ept_pte(pml4, data_page1_pte, 2); + TEST_ASSERT(get_ept_pte(pml4, data_page1_pte, + 2, &data_page1_pte_pte)); set_ept_pte(pml4, data_page1_pte, 2, - data_page1_pte_pte & (~EPT_PRESENT)); + data_page1_pte_pte & ~EPT_PRESENT); ept_sync(INVEPT_SINGLE, eptp); break; case 6: @@ -1134,7 +1247,7 @@ static int ept_exit_handler() break; // Should not reach here default: - printf("ERROR - unexpected stage, %d.\n", + report("ERROR - unexpected stage, %d.", false, vmx_get_test_stage()); print_vmexit_info(); return VMX_TEST_VMEXIT; @@ -1153,7 +1266,7 @@ static int ept_exit_handler() break; // Should not reach here default: - printf("ERROR - unexpected stage, %d.\n", + report("ERROR - unexpected stage, %d.", false, vmx_get_test_stage()); print_vmexit_info(); return VMX_TEST_VMEXIT; @@ -1162,15 +1275,23 @@ static int ept_exit_handler() case VMX_EPT_VIOLATION: switch(vmx_get_test_stage()) { case 3: + check_ept_ad(pml4, guest_cr3, (unsigned long)data_page1, 0, + have_ad ? EPT_ACCESS_FLAG | EPT_DIRTY_FLAG : 0); + clear_ept_ad(pml4, guest_cr3, (unsigned long)data_page1); if (exit_qual == (EPT_VLT_WR | EPT_VLT_LADDR_VLD | EPT_VLT_PADDR)) vmx_inc_test_stage(); - set_ept_pte(pml4, (unsigned long)data_page1, + set_ept_pte(pml4, (unsigned long)data_page1, 1, data_page1_pte | (EPT_PRESENT)); ept_sync(INVEPT_SINGLE, eptp); break; case 4: - if (exit_qual == (EPT_VLT_RD | EPT_VLT_LADDR_VLD)) + check_ept_ad(pml4, guest_cr3, (unsigned long)data_page1, 0, + have_ad ? EPT_ACCESS_FLAG | EPT_DIRTY_FLAG : 0); + clear_ept_ad(pml4, guest_cr3, (unsigned long)data_page1); + if (exit_qual == (EPT_VLT_RD | + (have_ad ? EPT_VLT_WR : 0) | + EPT_VLT_LADDR_VLD)) vmx_inc_test_stage(); set_ept_pte(pml4, data_page1_pte, 2, data_page1_pte_pte | (EPT_PRESENT)); @@ -1178,24 +1299,98 @@ static int ept_exit_handler() break; default: // Should not reach here - printf("ERROR : unexpected stage, %d\n", + report("ERROR : unexpected stage, %d", false, vmx_get_test_stage()); print_vmexit_info(); return VMX_TEST_VMEXIT; } return VMX_TEST_RESUME; default: - printf("Unknown exit reason, %ld\n", reason); + report("Unknown exit reason, %ld", false, reason); print_vmexit_info(); } return VMX_TEST_VMEXIT; } +static int ept_exit_handler() +{ + return ept_exit_handler_common(false); +} + +static int eptad_init() +{ + int r = ept_init_common(true); + + if (r == VMX_TEST_EXIT) + return r; + + if ((rdmsr(MSR_IA32_VMX_EPT_VPID_CAP) & EPT_CAP_AD_FLAG) == 0) { + printf("\tEPT A/D bits are not supported"); + return VMX_TEST_EXIT; + } + + return r; +} + +static int pml_init() +{ + u32 ctrl_cpu; + int r = eptad_init(); + + if (r == VMX_TEST_EXIT) + return r; + + if (!(ctrl_cpu_rev[0].clr & CPU_SECONDARY) || + !(ctrl_cpu_rev[1].clr & CPU_PML)) { + printf("\tPML is not supported"); + return VMX_TEST_EXIT; + } + + pml_log = alloc_page(); + memset(pml_log, 0x0, PAGE_SIZE); + vmcs_write(PMLADDR, (u64)pml_log); + vmcs_write(GUEST_PML_INDEX, PML_INDEX - 1); + + ctrl_cpu = vmcs_read(CPU_EXEC_CTRL1) | CPU_PML; + vmcs_write(CPU_EXEC_CTRL1, ctrl_cpu); + + return VMX_TEST_START; +} + +static void pml_main() +{ + int count = 0; + + vmx_set_test_stage(0); + *((u32 *)data_page2) = 0x1; + vmcall(); + report("PML - Dirty GPA Logging", vmx_get_test_stage() == 1); + + while (vmx_get_test_stage() == 1) { + vmcall(); + *((u32 *)data_page2) = 0x1; + if (count++ > PML_INDEX) + break; + } + report("PML Full Event", vmx_get_test_stage() == 2); +} + +static void eptad_main() +{ + ept_common(); +} + +static int eptad_exit_handler() +{ + return ept_exit_handler_common(true); +} + bool invvpid_test(int type, u16 vpid) { bool ret, supported; - supported = ept_vpid.val & (VPID_CAP_INVVPID_SINGLE >> INVVPID_SINGLE << type); + supported = ept_vpid.val & + (VPID_CAP_INVVPID_ADDR >> INVVPID_ADDR << type); ret = invvpid(type, vpid, 0); if (ret == !supported) @@ -1252,11 +1447,11 @@ static int vpid_exit_handler() case VMX_VMCALL: switch(vmx_get_test_stage()) { case 0: - if (!invvpid_test(INVVPID_SINGLE_ADDRESS, 1)) + if (!invvpid_test(INVVPID_ADDR, 1)) vmx_inc_test_stage(); break; case 2: - if (!invvpid_test(INVVPID_SINGLE, 1)) + if (!invvpid_test(INVVPID_CONTEXT_GLOBAL, 1)) vmx_inc_test_stage(); break; case 4: @@ -1264,7 +1459,7 @@ static int vpid_exit_handler() vmx_inc_test_stage(); break; default: - printf("ERROR: unexpected stage, %d\n", + report("ERROR: unexpected stage, %d", false, vmx_get_test_stage()); print_vmexit_info(); return VMX_TEST_VMEXIT; @@ -1272,7 +1467,7 @@ static int vpid_exit_handler() vmcs_write(GUEST_RIP, guest_rip + insn_len); return VMX_TEST_RESUME; default: - printf("Unknown exit reason, %ld\n", reason); + report("Unknown exit reason, %ld", false, reason); print_vmexit_info(); } return VMX_TEST_VMEXIT; @@ -1429,7 +1624,7 @@ static int interrupt_exit_handler(void) vmcs_write(GUEST_ACTV_STATE, ACTV_ACTIVE); return VMX_TEST_RESUME; default: - printf("Unknown exit reason, %ld\n", reason); + report("Unknown exit reason, %ld", false, reason); print_vmexit_info(); } @@ -1542,7 +1737,7 @@ static int dbgctls_exit_handler(void) vmcs_write(GUEST_RIP, guest_rip + insn_len); return VMX_TEST_RESUME; default: - printf("Unknown exit reason, %d\n", reason); + report("Unknown exit reason, %d", false, reason); print_vmexit_info(); } return VMX_TEST_VMEXIT; @@ -1664,7 +1859,7 @@ static int vmmcall_exit_handler() (vmcs_read(EXI_INTR_INFO) & 0xff) == UD_VECTOR); break; default: - printf("Unknown exit reason, %ld\n", reason); + report("Unknown exit reason, %ld", false, reason); print_vmexit_info(); } @@ -1736,7 +1931,7 @@ static int disable_rdtscp_exit_handler(void) break; default: - printf("Unknown exit reason, %d\n", reason); + report("Unknown exit reason, %d", false, reason); print_vmexit_info(); } return VMX_TEST_VMEXIT; @@ -1816,6 +2011,1385 @@ int into_exit_handler() return VMX_TEST_VMEXIT; } +static void exit_monitor_from_l2_main(void) +{ + printf("Calling exit(0) from l2...\n"); + exit(0); +} + +static int exit_monitor_from_l2_handler(void) +{ + report("The guest should have killed the VMM", false); + return VMX_TEST_EXIT; +} + +static void assert_exit_reason(u64 expected) +{ + u64 actual = vmcs_read(EXI_REASON); + + TEST_ASSERT_EQ_MSG(expected, actual, "Expected %s, got %s.", + exit_reason_description(expected), + exit_reason_description(actual)); +} + +static void skip_exit_vmcall() +{ + u64 guest_rip = vmcs_read(GUEST_RIP); + u32 insn_len = vmcs_read(EXI_INST_LEN); + + assert_exit_reason(VMX_VMCALL); + vmcs_write(GUEST_RIP, guest_rip + insn_len); +} + +static void v2_null_test_guest(void) +{ +} + +static void v2_null_test(void) +{ + test_set_guest(v2_null_test_guest); + enter_guest(); + report(__func__, 1); +} + +static void v2_multiple_entries_test_guest(void) +{ + vmx_set_test_stage(1); + vmcall(); + vmx_set_test_stage(2); +} + +static void v2_multiple_entries_test(void) +{ + test_set_guest(v2_multiple_entries_test_guest); + enter_guest(); + TEST_ASSERT_EQ(vmx_get_test_stage(), 1); + skip_exit_vmcall(); + enter_guest(); + TEST_ASSERT_EQ(vmx_get_test_stage(), 2); + report(__func__, 1); +} + +static int fixture_test_data = 1; + +static void fixture_test_teardown(void *data) +{ + *((int *) data) = 1; +} + +static void fixture_test_guest(void) +{ + fixture_test_data++; +} + + +static void fixture_test_setup(void) +{ + TEST_ASSERT_EQ_MSG(1, fixture_test_data, + "fixture_test_teardown didn't run?!"); + fixture_test_data = 2; + test_add_teardown(fixture_test_teardown, &fixture_test_data); + test_set_guest(fixture_test_guest); +} + +static void fixture_test_case1(void) +{ + fixture_test_setup(); + TEST_ASSERT_EQ(2, fixture_test_data); + enter_guest(); + TEST_ASSERT_EQ(3, fixture_test_data); + report(__func__, 1); +} + +static void fixture_test_case2(void) +{ + fixture_test_setup(); + TEST_ASSERT_EQ(2, fixture_test_data); + enter_guest(); + TEST_ASSERT_EQ(3, fixture_test_data); + report(__func__, 1); +} + +enum ept_access_op { + OP_READ, + OP_WRITE, + OP_EXEC, + OP_FLUSH_TLB, + OP_EXIT, +}; + +static struct ept_access_test_data { + unsigned long gpa; + unsigned long *gva; + unsigned long hpa; + unsigned long *hva; + enum ept_access_op op; +} ept_access_test_data; + +extern unsigned char ret42_start; +extern unsigned char ret42_end; + +/* Returns 42. */ +asm( + ".align 64\n" + "ret42_start:\n" + "mov $42, %eax\n" + "ret\n" + "ret42_end:\n" +); + +static void +diagnose_ept_violation_qual(u64 expected, u64 actual) +{ + +#define DIAGNOSE(flag) \ +do { \ + if ((expected & flag) != (actual & flag)) \ + printf(#flag " %sexpected\n", \ + (expected & flag) ? "" : "un"); \ +} while (0) + + DIAGNOSE(EPT_VLT_RD); + DIAGNOSE(EPT_VLT_WR); + DIAGNOSE(EPT_VLT_FETCH); + DIAGNOSE(EPT_VLT_PERM_RD); + DIAGNOSE(EPT_VLT_PERM_WR); + DIAGNOSE(EPT_VLT_PERM_EX); + DIAGNOSE(EPT_VLT_LADDR_VLD); + DIAGNOSE(EPT_VLT_PADDR); + +#undef DIAGNOSE +} + +static void do_ept_access_op(enum ept_access_op op) +{ + ept_access_test_data.op = op; + enter_guest(); +} + +/* + * Force the guest to flush its TLB (i.e., flush gva -> gpa mappings). Only + * needed by tests that modify guest PTEs. + */ +static void ept_access_test_guest_flush_tlb(void) +{ + do_ept_access_op(OP_FLUSH_TLB); + skip_exit_vmcall(); +} + +/* + * Modifies the EPT entry at @level in the mapping of @gpa. First clears the + * bits in @clear then sets the bits in @set. @mkhuge transforms the entry into + * a huge page. + */ +static unsigned long ept_twiddle(unsigned long gpa, bool mkhuge, int level, + unsigned long clear, unsigned long set) +{ + struct ept_access_test_data *data = &ept_access_test_data; + unsigned long orig_pte; + unsigned long pte; + + /* Screw with the mapping at the requested level. */ + TEST_ASSERT(get_ept_pte(pml4, gpa, level, &orig_pte)); + pte = orig_pte; + if (mkhuge) + pte = (orig_pte & ~EPT_ADDR_MASK) | data->hpa | EPT_LARGE_PAGE; + else + pte = orig_pte; + pte = (pte & ~clear) | set; + set_ept_pte(pml4, gpa, level, pte); + ept_sync(INVEPT_SINGLE, eptp); + + return orig_pte; +} + +static void ept_untwiddle(unsigned long gpa, int level, unsigned long orig_pte) +{ + set_ept_pte(pml4, gpa, level, orig_pte); +} + +static void do_ept_violation(bool leaf, enum ept_access_op op, + u64 expected_qual, u64 expected_paddr) +{ + u64 qual; + + /* Try the access and observe the violation. */ + do_ept_access_op(op); + + assert_exit_reason(VMX_EPT_VIOLATION); + + qual = vmcs_read(EXI_QUALIFICATION); + + diagnose_ept_violation_qual(expected_qual, qual); + TEST_EXPECT_EQ(expected_qual, qual); + + #if 0 + /* Disable for now otherwise every test will fail */ + TEST_EXPECT_EQ(vmcs_read(GUEST_LINEAR_ADDRESS), + (unsigned long) ( + op == OP_EXEC ? data->gva + 1 : data->gva)); + #endif + /* + * TODO: tests that probe expected_paddr in pages other than the one at + * the beginning of the 1g region. + */ + TEST_EXPECT_EQ(vmcs_read(INFO_PHYS_ADDR), expected_paddr); +} + +static void +ept_violation_at_level_mkhuge(bool mkhuge, int level, unsigned long clear, + unsigned long set, enum ept_access_op op, + u64 expected_qual) +{ + struct ept_access_test_data *data = &ept_access_test_data; + unsigned long orig_pte; + + orig_pte = ept_twiddle(data->gpa, mkhuge, level, clear, set); + + do_ept_violation(level == 1 || mkhuge, op, expected_qual, + op == OP_EXEC ? data->gpa + sizeof(unsigned long) : + data->gpa); + + /* Fix the violation and resume the op loop. */ + ept_untwiddle(data->gpa, level, orig_pte); + enter_guest(); + skip_exit_vmcall(); +} + +static void +ept_violation_at_level(int level, unsigned long clear, unsigned long set, + enum ept_access_op op, u64 expected_qual) +{ + ept_violation_at_level_mkhuge(false, level, clear, set, op, + expected_qual); + if (ept_huge_pages_supported(level)) + ept_violation_at_level_mkhuge(true, level, clear, set, op, + expected_qual); +} + +static void ept_violation(unsigned long clear, unsigned long set, + enum ept_access_op op, u64 expected_qual) +{ + ept_violation_at_level(1, clear, set, op, expected_qual); + ept_violation_at_level(2, clear, set, op, expected_qual); + ept_violation_at_level(3, clear, set, op, expected_qual); + ept_violation_at_level(4, clear, set, op, expected_qual); +} + +static void ept_access_violation(unsigned long access, enum ept_access_op op, + u64 expected_qual) +{ + ept_violation(EPT_PRESENT, access, op, + expected_qual | EPT_VLT_LADDR_VLD | EPT_VLT_PADDR); +} + +/* + * For translations that don't involve a GVA, that is physical address (paddr) + * accesses, EPT violations don't set the flag EPT_VLT_PADDR. For a typical + * guest memory access, the hardware does GVA -> GPA -> HPA. However, certain + * translations don't involve GVAs, such as when the hardware does the guest + * page table walk. For example, in translating GVA_1 -> GPA_1, the guest MMU + * might try to set an A bit on a guest PTE. If the GPA_2 that the PTE resides + * on isn't present in the EPT, then the EPT violation will be for GPA_2 and + * the EPT_VLT_PADDR bit will be clear in the exit qualification. + * + * Note that paddr violations can also be triggered by loading PAE page tables + * with wonky addresses. We don't test that yet. + * + * This function modifies the EPT entry that maps the GPA that the guest page + * table entry mapping ept_access_data.gva resides on. + * + * @ept_access EPT permissions to set. Other permissions are cleared. + * + * @pte_ad Set the A/D bits on the guest PTE accordingly. + * + * @op Guest operation to perform with ept_access_data.gva. + * + * @expect_violation + * Is a violation expected during the paddr access? + * + * @expected_qual Expected qualification for the EPT violation. + * EPT_VLT_PADDR should be clear. + */ +static void ept_access_paddr(unsigned long ept_access, unsigned long pte_ad, + enum ept_access_op op, bool expect_violation, + u64 expected_qual) +{ + struct ept_access_test_data *data = &ept_access_test_data; + unsigned long *ptep; + unsigned long gpa; + unsigned long orig_epte; + + /* Modify the guest PTE mapping data->gva according to @pte_ad. */ + ptep = get_pte_level(current_page_table(), data->gva, /*level=*/1); + TEST_ASSERT(ptep); + TEST_ASSERT_EQ(*ptep & PT_ADDR_MASK, data->gpa); + *ptep = (*ptep & ~PT_AD_MASK) | pte_ad; + ept_access_test_guest_flush_tlb(); + + /* + * Now modify the access bits on the EPT entry for the GPA that the + * guest PTE resides on. Note that by modifying a single EPT entry, + * we're potentially affecting 512 guest PTEs. However, we've carefully + * constructed our test such that those other 511 PTEs aren't used by + * the guest: data->gva is at the beginning of a 1G huge page, thus the + * PTE we're modifying is at the beginning of a 4K page and the + * following 511 entires are also under our control (and not touched by + * the guest). + */ + gpa = virt_to_phys(ptep); + TEST_ASSERT_EQ(gpa & ~PAGE_MASK, 0); + /* + * Make sure the guest page table page is mapped with a 4K EPT entry, + * otherwise our level=1 twiddling below will fail. We use the + * identity map (gpa = gpa) since page tables are shared with the host. + */ + install_ept(pml4, gpa, gpa, EPT_PRESENT); + orig_epte = ept_twiddle(gpa, /*mkhuge=*/0, /*level=*/1, + /*clear=*/EPT_PRESENT, /*set=*/ept_access); + + if (expect_violation) { + do_ept_violation(/*leaf=*/true, op, + expected_qual | EPT_VLT_LADDR_VLD, gpa); + ept_untwiddle(gpa, /*level=*/1, orig_epte); + do_ept_access_op(op); + } else { + do_ept_access_op(op); + ept_untwiddle(gpa, /*level=*/1, orig_epte); + } + + TEST_ASSERT(*ptep & PT_ACCESSED_MASK); + if ((pte_ad & PT_DIRTY_MASK) || op == OP_WRITE) + TEST_ASSERT(*ptep & PT_DIRTY_MASK); + + skip_exit_vmcall(); +} + +static void ept_access_allowed_paddr(unsigned long ept_access, + unsigned long pte_ad, + enum ept_access_op op) +{ + ept_access_paddr(ept_access, pte_ad, op, /*expect_violation=*/false, + /*expected_qual=*/-1); +} + +static void ept_access_violation_paddr(unsigned long ept_access, + unsigned long pte_ad, + enum ept_access_op op, + u64 expected_qual) +{ + ept_access_paddr(ept_access, pte_ad, op, /*expect_violation=*/true, + expected_qual); +} + + +static void ept_allowed_at_level_mkhuge(bool mkhuge, int level, + unsigned long clear, + unsigned long set, + enum ept_access_op op) +{ + struct ept_access_test_data *data = &ept_access_test_data; + unsigned long orig_pte; + + orig_pte = ept_twiddle(data->gpa, mkhuge, level, clear, set); + + /* No violation. Should proceed to vmcall. */ + do_ept_access_op(op); + skip_exit_vmcall(); + + ept_untwiddle(data->gpa, level, orig_pte); +} + +static void ept_allowed_at_level(int level, unsigned long clear, + unsigned long set, enum ept_access_op op) +{ + ept_allowed_at_level_mkhuge(false, level, clear, set, op); + if (ept_huge_pages_supported(level)) + ept_allowed_at_level_mkhuge(true, level, clear, set, op); +} + +static void ept_allowed(unsigned long clear, unsigned long set, + enum ept_access_op op) +{ + ept_allowed_at_level(1, clear, set, op); + ept_allowed_at_level(2, clear, set, op); + ept_allowed_at_level(3, clear, set, op); + ept_allowed_at_level(4, clear, set, op); +} + +static void ept_ignored_bit(int bit) +{ + /* Set the bit. */ + ept_allowed(0, 1ul << bit, OP_READ); + ept_allowed(0, 1ul << bit, OP_WRITE); + ept_allowed(0, 1ul << bit, OP_EXEC); + + /* Clear the bit. */ + ept_allowed(1ul << bit, 0, OP_READ); + ept_allowed(1ul << bit, 0, OP_WRITE); + ept_allowed(1ul << bit, 0, OP_EXEC); +} + +static void ept_access_allowed(unsigned long access, enum ept_access_op op) +{ + ept_allowed(EPT_PRESENT, access, op); +} + + +static void ept_misconfig_at_level_mkhuge_op(bool mkhuge, int level, + unsigned long clear, + unsigned long set, + enum ept_access_op op) +{ + struct ept_access_test_data *data = &ept_access_test_data; + unsigned long orig_pte; + + orig_pte = ept_twiddle(data->gpa, mkhuge, level, clear, set); + + do_ept_access_op(op); + assert_exit_reason(VMX_EPT_MISCONFIG); + + /* Intel 27.2.1, "For all other VM exits, this field is cleared." */ + #if 0 + /* broken: */ + TEST_EXPECT_EQ_MSG(vmcs_read(EXI_QUALIFICATION), 0); + #endif + #if 0 + /* + * broken: + * According to description of exit qual for EPT violation, + * EPT_VLT_LADDR_VLD indicates if GUEST_LINEAR_ADDRESS is valid. + * However, I can't find anything that says GUEST_LINEAR_ADDRESS ought + * to be set for msiconfig. + */ + TEST_EXPECT_EQ(vmcs_read(GUEST_LINEAR_ADDRESS), + (unsigned long) ( + op == OP_EXEC ? data->gva + 1 : data->gva)); + #endif + + /* Fix the violation and resume the op loop. */ + ept_untwiddle(data->gpa, level, orig_pte); + enter_guest(); + skip_exit_vmcall(); +} + +static void ept_misconfig_at_level_mkhuge(bool mkhuge, int level, + unsigned long clear, + unsigned long set) +{ + /* The op shouldn't matter (read, write, exec), so try them all! */ + ept_misconfig_at_level_mkhuge_op(mkhuge, level, clear, set, OP_READ); + ept_misconfig_at_level_mkhuge_op(mkhuge, level, clear, set, OP_WRITE); + ept_misconfig_at_level_mkhuge_op(mkhuge, level, clear, set, OP_EXEC); +} + +static void ept_misconfig_at_level(int level, unsigned long clear, + unsigned long set) +{ + ept_misconfig_at_level_mkhuge(false, level, clear, set); + if (ept_huge_pages_supported(level)) + ept_misconfig_at_level_mkhuge(true, level, clear, set); +} + +static void ept_misconfig(unsigned long clear, unsigned long set) +{ + ept_misconfig_at_level(1, clear, set); + ept_misconfig_at_level(2, clear, set); + ept_misconfig_at_level(3, clear, set); + ept_misconfig_at_level(4, clear, set); +} + +static void ept_access_misconfig(unsigned long access) +{ + ept_misconfig(EPT_PRESENT, access); +} + +static void ept_reserved_bit_at_level_nohuge(int level, int bit) +{ + /* Setting the bit causes a misconfig. */ + ept_misconfig_at_level_mkhuge(false, level, 0, 1ul << bit); + + /* Making the entry non-present turns reserved bits into ignored. */ + ept_violation_at_level(level, EPT_PRESENT, 1ul << bit, OP_READ, + EPT_VLT_RD | EPT_VLT_LADDR_VLD | EPT_VLT_PADDR); +} + +static void ept_reserved_bit_at_level_huge(int level, int bit) +{ + /* Setting the bit causes a misconfig. */ + ept_misconfig_at_level_mkhuge(true, level, 0, 1ul << bit); + + /* Making the entry non-present turns reserved bits into ignored. */ + ept_violation_at_level(level, EPT_PRESENT, 1ul << bit, OP_READ, + EPT_VLT_RD | EPT_VLT_LADDR_VLD | EPT_VLT_PADDR); +} + +static void ept_reserved_bit_at_level(int level, int bit) +{ + /* Setting the bit causes a misconfig. */ + ept_misconfig_at_level(level, 0, 1ul << bit); + + /* Making the entry non-present turns reserved bits into ignored. */ + ept_violation_at_level(level, EPT_PRESENT, 1ul << bit, OP_READ, + EPT_VLT_RD | EPT_VLT_LADDR_VLD | EPT_VLT_PADDR); +} + +static void ept_reserved_bit(int bit) +{ + ept_reserved_bit_at_level(1, bit); + ept_reserved_bit_at_level(2, bit); + ept_reserved_bit_at_level(3, bit); + ept_reserved_bit_at_level(4, bit); +} + +#define PAGE_2M_ORDER 9 +#define PAGE_1G_ORDER 18 + +static void *get_1g_page(void) +{ + static void *alloc; + + if (!alloc) + alloc = alloc_pages(PAGE_1G_ORDER); + return alloc; +} + +static void ept_access_test_teardown(void *unused) +{ + /* Exit the guest cleanly. */ + do_ept_access_op(OP_EXIT); +} + +static void ept_access_test_guest(void) +{ + struct ept_access_test_data *data = &ept_access_test_data; + int (*code)(void) = (int (*)(void)) &data->gva[1]; + + while (true) { + switch (data->op) { + case OP_READ: + TEST_ASSERT_EQ(*data->gva, MAGIC_VAL_1); + break; + case OP_WRITE: + *data->gva = MAGIC_VAL_2; + TEST_ASSERT_EQ(*data->gva, MAGIC_VAL_2); + *data->gva = MAGIC_VAL_1; + break; + case OP_EXEC: + TEST_ASSERT_EQ(42, code()); + break; + case OP_FLUSH_TLB: + write_cr3(read_cr3()); + break; + case OP_EXIT: + return; + default: + TEST_ASSERT_MSG(false, "Unknown op %d", data->op); + } + vmcall(); + } +} + +static void ept_access_test_setup(void) +{ + struct ept_access_test_data *data = &ept_access_test_data; + unsigned long npages = 1ul << PAGE_1G_ORDER; + unsigned long size = npages * PAGE_SIZE; + unsigned long *page_table = current_page_table(); + unsigned long pte; + + if (setup_ept(false)) + test_skip("EPT not supported"); + + test_set_guest(ept_access_test_guest); + test_add_teardown(ept_access_test_teardown, NULL); + + data->hva = get_1g_page(); + TEST_ASSERT(data->hva); + data->hpa = virt_to_phys(data->hva); + + data->gpa = 1ul << 40; + data->gva = (void *) ALIGN((unsigned long) alloc_vpages(npages * 2), + size); + TEST_ASSERT(!any_present_pages(page_table, data->gva, size)); + install_pages(page_table, data->gpa, size, data->gva); + + /* + * Make sure nothing's mapped here so the tests that screw with the + * pml4 entry don't inadvertently break something. + */ + TEST_ASSERT(get_ept_pte(pml4, data->gpa, 4, &pte) && pte == 0); + TEST_ASSERT(get_ept_pte(pml4, data->gpa + size - 1, 4, &pte) && pte == 0); + install_ept(pml4, data->hpa, data->gpa, EPT_PRESENT); + + data->hva[0] = MAGIC_VAL_1; + memcpy(&data->hva[1], &ret42_start, &ret42_end - &ret42_start); +} + +static void ept_access_test_not_present(void) +{ + ept_access_test_setup(); + /* --- */ + ept_access_violation(0, OP_READ, EPT_VLT_RD); + ept_access_violation(0, OP_WRITE, EPT_VLT_WR); + ept_access_violation(0, OP_EXEC, EPT_VLT_FETCH); +} + +static void ept_access_test_read_only(void) +{ + ept_access_test_setup(); + + /* r-- */ + ept_access_allowed(EPT_RA, OP_READ); + ept_access_violation(EPT_RA, OP_WRITE, EPT_VLT_WR | EPT_VLT_PERM_RD); + ept_access_violation(EPT_RA, OP_EXEC, EPT_VLT_FETCH | EPT_VLT_PERM_RD); +} + +static void ept_access_test_write_only(void) +{ + ept_access_test_setup(); + /* -w- */ + ept_access_misconfig(EPT_WA); +} + +static void ept_access_test_read_write(void) +{ + ept_access_test_setup(); + /* rw- */ + ept_access_allowed(EPT_RA | EPT_WA, OP_READ); + ept_access_allowed(EPT_RA | EPT_WA, OP_WRITE); + ept_access_violation(EPT_RA | EPT_WA, OP_EXEC, + EPT_VLT_FETCH | EPT_VLT_PERM_RD | EPT_VLT_PERM_WR); +} + + +static void ept_access_test_execute_only(void) +{ + ept_access_test_setup(); + /* --x */ + if (ept_execute_only_supported()) { + ept_access_violation(EPT_EA, OP_READ, + EPT_VLT_RD | EPT_VLT_PERM_EX); + ept_access_violation(EPT_EA, OP_WRITE, + EPT_VLT_WR | EPT_VLT_PERM_EX); + ept_access_allowed(EPT_EA, OP_EXEC); + } else { + ept_access_misconfig(EPT_EA); + } +} + +static void ept_access_test_read_execute(void) +{ + ept_access_test_setup(); + /* r-x */ + ept_access_allowed(EPT_RA | EPT_EA, OP_READ); + ept_access_violation(EPT_RA | EPT_EA, OP_WRITE, + EPT_VLT_WR | EPT_VLT_PERM_RD | EPT_VLT_PERM_EX); + ept_access_allowed(EPT_RA | EPT_EA, OP_EXEC); +} + +static void ept_access_test_write_execute(void) +{ + ept_access_test_setup(); + /* -wx */ + ept_access_misconfig(EPT_WA | EPT_EA); +} + +static void ept_access_test_read_write_execute(void) +{ + ept_access_test_setup(); + /* rwx */ + ept_access_allowed(EPT_RA | EPT_WA | EPT_EA, OP_READ); + ept_access_allowed(EPT_RA | EPT_WA | EPT_EA, OP_WRITE); + ept_access_allowed(EPT_RA | EPT_WA | EPT_EA, OP_EXEC); +} + +static void ept_access_test_reserved_bits(void) +{ + int i; + int maxphyaddr; + + ept_access_test_setup(); + + /* Reserved bits above maxphyaddr. */ + maxphyaddr = cpuid_maxphyaddr(); + for (i = maxphyaddr; i <= 51; i++) { + report_prefix_pushf("reserved_bit=%d", i); + ept_reserved_bit(i); + report_prefix_pop(); + } + + /* Level-specific reserved bits. */ + ept_reserved_bit_at_level_nohuge(2, 3); + ept_reserved_bit_at_level_nohuge(2, 4); + ept_reserved_bit_at_level_nohuge(2, 5); + ept_reserved_bit_at_level_nohuge(2, 6); + /* 2M alignment. */ + for (i = 12; i < 20; i++) { + report_prefix_pushf("reserved_bit=%d", i); + ept_reserved_bit_at_level_huge(2, i); + report_prefix_pop(); + } + ept_reserved_bit_at_level_nohuge(3, 3); + ept_reserved_bit_at_level_nohuge(3, 4); + ept_reserved_bit_at_level_nohuge(3, 5); + ept_reserved_bit_at_level_nohuge(3, 6); + /* 1G alignment. */ + for (i = 12; i < 29; i++) { + report_prefix_pushf("reserved_bit=%d", i); + ept_reserved_bit_at_level_huge(3, i); + report_prefix_pop(); + } + ept_reserved_bit_at_level(4, 3); + ept_reserved_bit_at_level(4, 4); + ept_reserved_bit_at_level(4, 5); + ept_reserved_bit_at_level(4, 6); + ept_reserved_bit_at_level(4, 7); +} + +static void ept_access_test_ignored_bits(void) +{ + ept_access_test_setup(); + /* + * Bits ignored at every level. Bits 8 and 9 (A and D) are ignored as + * far as translation is concerned even if AD bits are enabled in the + * EPTP. Bit 63 is ignored because "EPT-violation #VE" VM-execution + * control is 0. + */ + ept_ignored_bit(8); + ept_ignored_bit(9); + ept_ignored_bit(10); + ept_ignored_bit(11); + ept_ignored_bit(52); + ept_ignored_bit(53); + ept_ignored_bit(54); + ept_ignored_bit(55); + ept_ignored_bit(56); + ept_ignored_bit(57); + ept_ignored_bit(58); + ept_ignored_bit(59); + ept_ignored_bit(60); + ept_ignored_bit(61); + ept_ignored_bit(62); + ept_ignored_bit(63); +} + +static void ept_access_test_paddr_not_present_ad_disabled(void) +{ + ept_access_test_setup(); + ept_disable_ad_bits(); + + ept_access_violation_paddr(0, PT_AD_MASK, OP_READ, EPT_VLT_RD); + ept_access_violation_paddr(0, PT_AD_MASK, OP_WRITE, EPT_VLT_RD); + ept_access_violation_paddr(0, PT_AD_MASK, OP_EXEC, EPT_VLT_RD); +} + +static void ept_access_test_paddr_not_present_ad_enabled(void) +{ + u64 qual = EPT_VLT_RD | EPT_VLT_WR; + + ept_access_test_setup(); + ept_enable_ad_bits_or_skip_test(); + + ept_access_violation_paddr(0, PT_AD_MASK, OP_READ, qual); + ept_access_violation_paddr(0, PT_AD_MASK, OP_WRITE, qual); + ept_access_violation_paddr(0, PT_AD_MASK, OP_EXEC, qual); +} + +static void ept_access_test_paddr_read_only_ad_disabled(void) +{ + /* + * When EPT AD bits are disabled, all accesses to guest paging + * structures are reported separately as a read and (after + * translation of the GPA to host physical address) a read+write + * if the A/D bits have to be set. + */ + u64 qual = EPT_VLT_WR | EPT_VLT_RD | EPT_VLT_PERM_RD; + + ept_access_test_setup(); + ept_disable_ad_bits(); + + /* Can't update A bit, so all accesses fail. */ + ept_access_violation_paddr(EPT_RA, 0, OP_READ, qual); + ept_access_violation_paddr(EPT_RA, 0, OP_WRITE, qual); + ept_access_violation_paddr(EPT_RA, 0, OP_EXEC, qual); + /* AD bits disabled, so only writes try to update the D bit. */ + ept_access_allowed_paddr(EPT_RA, PT_ACCESSED_MASK, OP_READ); + ept_access_violation_paddr(EPT_RA, PT_ACCESSED_MASK, OP_WRITE, qual); + ept_access_allowed_paddr(EPT_RA, PT_ACCESSED_MASK, OP_EXEC); + /* Both A and D already set, so read-only is OK. */ + ept_access_allowed_paddr(EPT_RA, PT_AD_MASK, OP_READ); + ept_access_allowed_paddr(EPT_RA, PT_AD_MASK, OP_WRITE); + ept_access_allowed_paddr(EPT_RA, PT_AD_MASK, OP_EXEC); +} + +static void ept_access_test_paddr_read_only_ad_enabled(void) +{ + /* + * When EPT AD bits are enabled, all accesses to guest paging + * structures are considered writes as far as EPT translation + * is concerned. + */ + u64 qual = EPT_VLT_WR | EPT_VLT_RD | EPT_VLT_PERM_RD; + + ept_access_test_setup(); + ept_enable_ad_bits_or_skip_test(); + + ept_access_violation_paddr(EPT_RA, 0, OP_READ, qual); + ept_access_violation_paddr(EPT_RA, 0, OP_WRITE, qual); + ept_access_violation_paddr(EPT_RA, 0, OP_EXEC, qual); + ept_access_violation_paddr(EPT_RA, PT_ACCESSED_MASK, OP_READ, qual); + ept_access_violation_paddr(EPT_RA, PT_ACCESSED_MASK, OP_WRITE, qual); + ept_access_violation_paddr(EPT_RA, PT_ACCESSED_MASK, OP_EXEC, qual); + ept_access_violation_paddr(EPT_RA, PT_AD_MASK, OP_READ, qual); + ept_access_violation_paddr(EPT_RA, PT_AD_MASK, OP_WRITE, qual); + ept_access_violation_paddr(EPT_RA, PT_AD_MASK, OP_EXEC, qual); +} + +static void ept_access_test_paddr_read_write(void) +{ + ept_access_test_setup(); + /* Read-write access to paging structure. */ + ept_access_allowed_paddr(EPT_RA | EPT_WA, 0, OP_READ); + ept_access_allowed_paddr(EPT_RA | EPT_WA, 0, OP_WRITE); + ept_access_allowed_paddr(EPT_RA | EPT_WA, 0, OP_EXEC); +} + +static void ept_access_test_paddr_read_write_execute(void) +{ + ept_access_test_setup(); + /* RWX access to paging structure. */ + ept_access_allowed_paddr(EPT_PRESENT, 0, OP_READ); + ept_access_allowed_paddr(EPT_PRESENT, 0, OP_WRITE); + ept_access_allowed_paddr(EPT_PRESENT, 0, OP_EXEC); +} + +static void ept_access_test_paddr_read_execute_ad_disabled(void) +{ + /* + * When EPT AD bits are disabled, all accesses to guest paging + * structures are reported separately as a read and (after + * translation of the GPA to host physical address) a read+write + * if the A/D bits have to be set. + */ + u64 qual = EPT_VLT_WR | EPT_VLT_RD | EPT_VLT_PERM_RD | EPT_VLT_PERM_EX; + + ept_access_test_setup(); + ept_disable_ad_bits(); + + /* Can't update A bit, so all accesses fail. */ + ept_access_violation_paddr(EPT_RA | EPT_EA, 0, OP_READ, qual); + ept_access_violation_paddr(EPT_RA | EPT_EA, 0, OP_WRITE, qual); + ept_access_violation_paddr(EPT_RA | EPT_EA, 0, OP_EXEC, qual); + /* AD bits disabled, so only writes try to update the D bit. */ + ept_access_allowed_paddr(EPT_RA | EPT_EA, PT_ACCESSED_MASK, OP_READ); + ept_access_violation_paddr(EPT_RA | EPT_EA, PT_ACCESSED_MASK, OP_WRITE, qual); + ept_access_allowed_paddr(EPT_RA | EPT_EA, PT_ACCESSED_MASK, OP_EXEC); + /* Both A and D already set, so read-only is OK. */ + ept_access_allowed_paddr(EPT_RA | EPT_EA, PT_AD_MASK, OP_READ); + ept_access_allowed_paddr(EPT_RA | EPT_EA, PT_AD_MASK, OP_WRITE); + ept_access_allowed_paddr(EPT_RA | EPT_EA, PT_AD_MASK, OP_EXEC); +} + +static void ept_access_test_paddr_read_execute_ad_enabled(void) +{ + /* + * When EPT AD bits are enabled, all accesses to guest paging + * structures are considered writes as far as EPT translation + * is concerned. + */ + u64 qual = EPT_VLT_WR | EPT_VLT_RD | EPT_VLT_PERM_RD | EPT_VLT_PERM_EX; + + ept_access_test_setup(); + ept_enable_ad_bits_or_skip_test(); + + ept_access_violation_paddr(EPT_RA | EPT_EA, 0, OP_READ, qual); + ept_access_violation_paddr(EPT_RA | EPT_EA, 0, OP_WRITE, qual); + ept_access_violation_paddr(EPT_RA | EPT_EA, 0, OP_EXEC, qual); + ept_access_violation_paddr(EPT_RA | EPT_EA, PT_ACCESSED_MASK, OP_READ, qual); + ept_access_violation_paddr(EPT_RA | EPT_EA, PT_ACCESSED_MASK, OP_WRITE, qual); + ept_access_violation_paddr(EPT_RA | EPT_EA, PT_ACCESSED_MASK, OP_EXEC, qual); + ept_access_violation_paddr(EPT_RA | EPT_EA, PT_AD_MASK, OP_READ, qual); + ept_access_violation_paddr(EPT_RA | EPT_EA, PT_AD_MASK, OP_WRITE, qual); + ept_access_violation_paddr(EPT_RA | EPT_EA, PT_AD_MASK, OP_EXEC, qual); +} + +static void ept_access_test_paddr_not_present_page_fault(void) +{ + ept_access_test_setup(); + /* + * TODO: test no EPT violation as long as guest PF occurs. e.g., GPA is + * page is read-only in EPT but GVA is also mapped read only in PT. + * Thus guest page fault before host takes EPT violation for trying to + * update A bit. + */ +} + +static void ept_access_test_force_2m_page(void) +{ + ept_access_test_setup(); + + TEST_ASSERT_EQ(ept_2m_supported(), true); + ept_allowed_at_level_mkhuge(true, 2, 0, 0, OP_READ); + ept_violation_at_level_mkhuge(true, 2, EPT_PRESENT, EPT_RA, OP_WRITE, + EPT_VLT_WR | EPT_VLT_PERM_RD | + EPT_VLT_LADDR_VLD | EPT_VLT_PADDR); + ept_misconfig_at_level_mkhuge(true, 2, EPT_PRESENT, EPT_WA); +} + +static bool invvpid_valid(u64 type, u64 vpid, u64 gla) +{ + u64 msr = rdmsr(MSR_IA32_VMX_EPT_VPID_CAP); + + TEST_ASSERT(msr & VPID_CAP_INVVPID); + + if (type < INVVPID_ADDR || type > INVVPID_CONTEXT_LOCAL) + return false; + + if (!(msr & (1ull << (type + VPID_CAP_INVVPID_TYPES_SHIFT)))) + return false; + + if (vpid >> 16) + return false; + + if (type != INVVPID_ALL && !vpid) + return false; + + if (type == INVVPID_ADDR && !is_canonical(gla)) + return false; + + return true; +} + +static void try_invvpid(u64 type, u64 vpid, u64 gla) +{ + int rc; + bool valid = invvpid_valid(type, vpid, gla); + u64 expected = valid ? VMXERR_UNSUPPORTED_VMCS_COMPONENT + : VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID; + /* + * Set VMX_INST_ERROR to VMXERR_UNVALID_VMCS_COMPONENT, so + * that we can tell if it is updated by INVVPID. + */ + vmcs_read(~0); + rc = invvpid(type, vpid, gla); + report("INVVPID type %ld VPID %lx GLA %lx %s", + !rc == valid, type, vpid, gla, + valid ? "passes" : "fails"); + report("After %s INVVPID, VMX_INST_ERR is %ld (actual %ld)", + vmcs_read(VMX_INST_ERROR) == expected, + rc ? "failed" : "successful", + expected, vmcs_read(VMX_INST_ERROR)); +} + +static void ds_invvpid(void *data) +{ + u64 msr = rdmsr(MSR_IA32_VMX_EPT_VPID_CAP); + u64 type = ffs(msr >> VPID_CAP_INVVPID_TYPES_SHIFT) - 1; + + TEST_ASSERT(type >= INVVPID_ADDR && type <= INVVPID_CONTEXT_LOCAL); + asm volatile("invvpid %0, %1" + : + : "m"(*(struct invvpid_operand *)data), + "r"(type)); +} + +/* + * The SS override is ignored in 64-bit mode, so we use an addressing + * mode with %rsp as the base register to generate an implicit SS + * reference. + */ +static void ss_invvpid(void *data) +{ + u64 msr = rdmsr(MSR_IA32_VMX_EPT_VPID_CAP); + u64 type = ffs(msr >> VPID_CAP_INVVPID_TYPES_SHIFT) - 1; + + TEST_ASSERT(type >= INVVPID_ADDR && type <= INVVPID_CONTEXT_LOCAL); + asm volatile("sub %%rsp,%0; invvpid (%%rsp,%0,1), %1" + : "+r"(data) + : "r"(type)); +} + +static void invvpid_test_gp(void) +{ + bool fault; + + fault = test_for_exception(GP_VECTOR, &ds_invvpid, + (void *)NONCANONICAL); + report("INVVPID with non-canonical DS operand raises #GP", fault); +} + +static void invvpid_test_ss(void) +{ + bool fault; + + fault = test_for_exception(SS_VECTOR, &ss_invvpid, + (void *)NONCANONICAL); + report("INVVPID with non-canonical SS operand raises #SS", fault); +} + +static void invvpid_test_pf(void) +{ + void *vpage = alloc_vpage(); + bool fault; + + fault = test_for_exception(PF_VECTOR, &ds_invvpid, vpage); + report("INVVPID with unmapped operand raises #PF", fault); +} + +static void try_compat_invvpid(void *unused) +{ + struct far_pointer32 fp = { + .offset = (uintptr_t)&&invvpid, + .selector = KERNEL_CS32, + }; + register uintptr_t rsp asm("rsp"); + + TEST_ASSERT_MSG(fp.offset == (uintptr_t)&&invvpid, + "Code address too high."); + TEST_ASSERT_MSG(rsp == (u32)rsp, "Stack address too high."); + + asm goto ("lcall *%0" : : "m" (fp) : "rax" : invvpid); + return; +invvpid: + asm volatile (".code32;" + "invvpid (%eax), %eax;" + "lret;" + ".code64"); + __builtin_unreachable(); +} + +static void invvpid_test_compatibility_mode(void) +{ + bool fault; + + fault = test_for_exception(UD_VECTOR, &try_compat_invvpid, NULL); + report("Compatibility mode INVVPID raises #UD", fault); +} + +static void invvpid_test_not_in_vmx_operation(void) +{ + bool fault; + + TEST_ASSERT(!vmx_off()); + fault = test_for_exception(UD_VECTOR, &ds_invvpid, NULL); + report("INVVPID outside of VMX operation raises #UD", fault); + TEST_ASSERT(!vmx_on()); +} + +/* + * This does not test real-address mode, virtual-8086 mode, protected mode, + * or CPL > 0. + */ +static void invvpid_test_v2(void) +{ + u64 msr; + int i; + unsigned types = 0; + unsigned type; + + if (!(ctrl_cpu_rev[0].clr & CPU_SECONDARY) || + !(ctrl_cpu_rev[1].clr & CPU_VPID)) + test_skip("VPID not supported"); + + msr = rdmsr(MSR_IA32_VMX_EPT_VPID_CAP); + + if (!(msr & VPID_CAP_INVVPID)) + test_skip("INVVPID not supported.\n"); + + if (msr & VPID_CAP_INVVPID_ADDR) + types |= 1u << INVVPID_ADDR; + if (msr & VPID_CAP_INVVPID_CXTGLB) + types |= 1u << INVVPID_CONTEXT_GLOBAL; + if (msr & VPID_CAP_INVVPID_ALL) + types |= 1u << INVVPID_ALL; + if (msr & VPID_CAP_INVVPID_CXTLOC) + types |= 1u << INVVPID_CONTEXT_LOCAL; + + if (!types) + test_skip("No INVVPID types supported.\n"); + + for (i = -127; i < 128; i++) + try_invvpid(i, 0xffff, 0); + + /* + * VPID must not be more than 16 bits. + */ + for (i = 0; i < 64; i++) + for (type = 0; type < 4; type++) + if (types & (1u << type)) + try_invvpid(type, 1ul << i, 0); + + /* + * VPID must not be zero, except for "all contexts." + */ + for (type = 0; type < 4; type++) + if (types & (1u << type)) + try_invvpid(type, 0, 0); + + /* + * The gla operand is only validated for single-address INVVPID. + */ + if (types & (1u << INVVPID_ADDR)) + try_invvpid(INVVPID_ADDR, 0xffff, NONCANONICAL); + + invvpid_test_gp(); + invvpid_test_ss(); + invvpid_test_pf(); + invvpid_test_compatibility_mode(); + invvpid_test_not_in_vmx_operation(); +} + +/* + * Test for early VMLAUNCH failure. Returns true if VMLAUNCH makes it + * at least as far as the guest-state checks. Returns false if the + * VMLAUNCH fails early and execution falls through to the next + * instruction. + */ +static bool vmlaunch_succeeds(void) +{ + /* + * Indirectly set VMX_INST_ERR to 12 ("VMREAD/VMWRITE from/to + * unsupported VMCS component"). The caller can then check + * to see if a failed VM-entry sets VMX_INST_ERR as expected. + */ + vmcs_write(~0u, 0); + + vmcs_write(HOST_RIP, (uintptr_t)&&success); + __asm__ __volatile__ goto ("vmwrite %%rsp, %0; vmlaunch" + : + : "r" ((u64)HOST_RSP) + : "cc", "memory" + : success); + return false; +success: + TEST_ASSERT(vmcs_read(EXI_REASON) == + (VMX_FAIL_STATE | VMX_ENTRY_FAILURE)); + return true; +} + +/* + * Try to launch the current VMCS. + */ +static void test_vmx_controls(bool controls_valid) +{ + bool success = vmlaunch_succeeds(); + u32 vmx_inst_err; + + report("vmlaunch %s", success == controls_valid, + controls_valid ? "succeeds" : "fails"); + if (!controls_valid) { + vmx_inst_err = vmcs_read(VMX_INST_ERROR); + report("VMX inst error is %d (actual %d)", + vmx_inst_err == VMXERR_ENTRY_INVALID_CONTROL_FIELD, + VMXERR_ENTRY_INVALID_CONTROL_FIELD, vmx_inst_err); + } +} + +/* + * Test a particular address setting for a physical page reference in + * the VMCS. + */ +static void test_vmcs_page_addr(const char *name, + enum Encoding encoding, + bool ignored, + u64 addr) +{ + report_prefix_pushf("%s = %lx", name, addr); + vmcs_write(encoding, addr); + test_vmx_controls(ignored || (IS_ALIGNED(addr, PAGE_SIZE) && + addr < (1ul << cpuid_maxphyaddr()))); + report_prefix_pop(); +} + +/* + * Test interesting values for a physical page reference in the VMCS. + */ +static void test_vmcs_page_values(const char *name, + enum Encoding encoding, + bool ignored) +{ + unsigned i; + u64 orig_val = vmcs_read(encoding); + + for (i = 0; i < 64; i++) + test_vmcs_page_addr(name, encoding, ignored, 1ul << i); + + test_vmcs_page_addr(name, encoding, ignored, PAGE_SIZE - 1); + test_vmcs_page_addr(name, encoding, ignored, PAGE_SIZE); + test_vmcs_page_addr(name, encoding, ignored, + (1ul << cpuid_maxphyaddr()) - PAGE_SIZE); + test_vmcs_page_addr(name, encoding, ignored, -1ul); + + vmcs_write(encoding, orig_val); +} + +/* + * Test a physical page reference in the VMCS, when the corresponding + * feature is enabled and when the corresponding feature is disabled. + */ +static void test_vmcs_page_reference(u32 control_bit, enum Encoding field, + const char *field_name, + const char *control_name) +{ + u32 primary = vmcs_read(CPU_EXEC_CTRL0); + u64 page_addr; + + if (!(ctrl_cpu_rev[0].clr & control_bit)) + return; + + page_addr = vmcs_read(field); + + report_prefix_pushf("%s enabled", control_name); + vmcs_write(CPU_EXEC_CTRL0, primary | control_bit); + test_vmcs_page_values(field_name, field, false); + report_prefix_pop(); + + report_prefix_pushf("%s disabled", control_name); + vmcs_write(CPU_EXEC_CTRL0, primary & ~control_bit); + test_vmcs_page_values(field_name, field, true); + report_prefix_pop(); + + vmcs_write(field, page_addr); + vmcs_write(CPU_EXEC_CTRL0, primary); +} + +/* + * If the "use I/O bitmaps" VM-execution control is 1, bits 11:0 of + * each I/O-bitmap address must be 0. Neither address should set any + * bits beyond the processor's physical-address width. + * [Intel SDM] + */ +static void test_io_bitmaps(void) +{ + test_vmcs_page_reference(CPU_IO_BITMAP, IO_BITMAP_A, + "I/O bitmap A", "Use I/O bitmaps"); + test_vmcs_page_reference(CPU_IO_BITMAP, IO_BITMAP_B, + "I/O bitmap B", "Use I/O bitmaps"); +} + +/* + * If the "use MSR bitmaps" VM-execution control is 1, bits 11:0 of + * the MSR-bitmap address must be 0. The address should not set any + * bits beyond the processor's physical-address width. + * [Intel SDM] + */ +static void test_msr_bitmap(void) +{ + test_vmcs_page_reference(CPU_MSR_BITMAP, MSR_BITMAP, + "MSR bitmap", "Use MSR bitmaps"); +} + +static void vmx_controls_test(void) +{ + /* + * Bit 1 of the guest's RFLAGS must be 1, or VM-entry will + * fail due to invalid guest state, should we make it that + * far. + */ + vmcs_write(GUEST_RFLAGS, 0); + + test_io_bitmaps(); + test_msr_bitmap(); +} + +static bool valid_vmcs_for_vmentry(void) +{ + struct vmcs *current_vmcs = NULL; + + if (vmcs_save(¤t_vmcs)) + return false; + + return current_vmcs && !(current_vmcs->revision_id >> 31); +} + +static void try_vmentry_in_movss_shadow(void) +{ + u32 vm_inst_err; + u32 flags; + bool early_failure = false; + u32 expected_flags = X86_EFLAGS_FIXED; + bool valid_vmcs = valid_vmcs_for_vmentry(); + + expected_flags |= valid_vmcs ? X86_EFLAGS_ZF : X86_EFLAGS_CF; + + /* + * Indirectly set VM_INST_ERR to 12 ("VMREAD/VMWRITE from/to + * unsupported VMCS component"). + */ + vmcs_write(~0u, 0); + + __asm__ __volatile__ ("mov %[host_rsp], %%edx;" + "vmwrite %%rsp, %%rdx;" + "mov 0f, %%rax;" + "mov %[host_rip], %%edx;" + "vmwrite %%rax, %%rdx;" + "mov $-1, %%ah;" + "sahf;" + "mov %%ss, %%ax;" + "mov %%ax, %%ss;" + "vmlaunch;" + "mov $1, %[early_failure];" + "0: lahf;" + "movzbl %%ah, %[flags]" + : [early_failure] "+r" (early_failure), + [flags] "=&a" (flags) + : [host_rsp] "i" (HOST_RSP), + [host_rip] "i" (HOST_RIP) + : "rdx", "cc", "memory"); + vm_inst_err = vmcs_read(VMX_INST_ERROR); + + report("Early VM-entry failure", early_failure); + report("RFLAGS[8:0] is %x (actual %x)", flags == expected_flags, + expected_flags, flags); + if (valid_vmcs) + report("VM-instruction error is %d (actual %d)", + vm_inst_err == VMXERR_ENTRY_EVENTS_BLOCKED_BY_MOV_SS, + VMXERR_ENTRY_EVENTS_BLOCKED_BY_MOV_SS, vm_inst_err); +} + +static void vmentry_movss_shadow_test(void) +{ + struct vmcs *orig_vmcs; + + TEST_ASSERT(!vmcs_save(&orig_vmcs)); + + /* + * Set the launched flag on the current VMCS to verify the correct + * error priority, below. + */ + test_set_guest(v2_null_test_guest); + enter_guest(); + + /* + * With bit 1 of the guest's RFLAGS clear, VM-entry should + * fail due to invalid guest state (if we make it that far). + */ + vmcs_write(GUEST_RFLAGS, 0); + + /* + * "VM entry with events blocked by MOV SS" takes precedence over + * "VMLAUNCH with non-clear VMCS." + */ + report_prefix_push("valid current-VMCS"); + try_vmentry_in_movss_shadow(); + report_prefix_pop(); + + /* + * VMfailInvalid takes precedence over "VM entry with events + * blocked by MOV SS." + */ + TEST_ASSERT(!vmcs_clear(orig_vmcs)); + report_prefix_push("no current-VMCS"); + try_vmentry_in_movss_shadow(); + report_prefix_pop(); + + TEST_ASSERT(!make_vmcs_current(orig_vmcs)); + vmcs_write(GUEST_RFLAGS, X86_EFLAGS_FIXED); +} + +#define TEST(name) { #name, .v2 = name } + /* name/init/guest_main/exit_handler/syscall_handler/guest_regs */ struct vmx_test vmx_tests[] = { { "null", NULL, basic_guest_main, basic_exit_handler, NULL, {0} }, @@ -1832,7 +3406,9 @@ struct vmx_test vmx_tests[] = { NULL, {0} }, { "instruction intercept", insn_intercept_init, insn_intercept_main, insn_intercept_exit_handler, NULL, {0} }, - { "EPT framework", ept_init, ept_main, ept_exit_handler, NULL, {0} }, + { "EPT A/D disabled", ept_init, ept_main, ept_exit_handler, NULL, {0} }, + { "EPT A/D enabled", eptad_init, eptad_main, eptad_exit_handler, NULL, {0} }, + { "PML", pml_init, pml_main, pml_exit_handler, NULL, {0} }, { "VPID", vpid_init, vpid_main, vpid_exit_handler, NULL, {0} }, { "interrupt", interrupt_init, interrupt_main, interrupt_exit_handler, NULL, {0} }, @@ -1845,5 +3421,38 @@ struct vmx_test vmx_tests[] = { disable_rdtscp_exit_handler, NULL, {0} }, { "int3", int3_init, int3_guest_main, int3_exit_handler, NULL, {0} }, { "into", into_init, into_guest_main, into_exit_handler, NULL, {0} }, + { "exit_monitor_from_l2_test", NULL, exit_monitor_from_l2_main, + exit_monitor_from_l2_handler, NULL, {0} }, + /* Basic V2 tests. */ + TEST(v2_null_test), + TEST(v2_multiple_entries_test), + TEST(fixture_test_case1), + TEST(fixture_test_case2), + /* EPT access tests. */ + TEST(ept_access_test_not_present), + TEST(ept_access_test_read_only), + TEST(ept_access_test_write_only), + TEST(ept_access_test_read_write), + TEST(ept_access_test_execute_only), + TEST(ept_access_test_read_execute), + TEST(ept_access_test_write_execute), + TEST(ept_access_test_read_write_execute), + TEST(ept_access_test_reserved_bits), + TEST(ept_access_test_ignored_bits), + TEST(ept_access_test_paddr_not_present_ad_disabled), + TEST(ept_access_test_paddr_not_present_ad_enabled), + TEST(ept_access_test_paddr_read_only_ad_disabled), + TEST(ept_access_test_paddr_read_only_ad_enabled), + TEST(ept_access_test_paddr_read_write), + TEST(ept_access_test_paddr_read_write_execute), + TEST(ept_access_test_paddr_read_execute_ad_disabled), + TEST(ept_access_test_paddr_read_execute_ad_enabled), + TEST(ept_access_test_paddr_not_present_page_fault), + TEST(ept_access_test_force_2m_page), + /* Opcode tests. */ + TEST(invvpid_test_v2), + /* VM-entry tests */ + TEST(vmx_controls_test), + TEST(vmentry_movss_shadow_test), { NULL, NULL, NULL, NULL, NULL, {0} }, }; diff --git a/tests/kvm-unit-tests/x86/xsave.c b/tests/kvm-unit-tests/x86/xsave.c index 52142d2c..2d8ca7c2 100644 --- a/tests/kvm-unit-tests/x86/xsave.c +++ b/tests/kvm-unit-tests/x86/xsave.c @@ -75,7 +75,7 @@ void test_xsave(void) printf("Legal instruction testing:\n"); supported_xcr0 = get_supported_xcr0(); - printf("Supported XCR0 bits: 0x%lx\n", supported_xcr0); + printf("Supported XCR0 bits: %#lx\n", supported_xcr0); test_bits = XSTATE_FP | XSTATE_SSE; report("Check minimal XSAVE required bits", From befddacccf5ec3755b78e920403c9fbfdc5424f9 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 27 Jul 2017 16:07:17 +0200 Subject: [PATCH 0071/2137] Fix kvm-unit-test: undefined reference to __stack_chk_fail --- tests/kvm-unit-tests/x86/Makefile.common | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/kvm-unit-tests/x86/Makefile.common b/tests/kvm-unit-tests/x86/Makefile.common index e96812bf..73069d86 100644 --- a/tests/kvm-unit-tests/x86/Makefile.common +++ b/tests/kvm-unit-tests/x86/Makefile.common @@ -23,6 +23,7 @@ $(libcflat): CFLAGS += -ffreestanding -I $(SRCDIR)/lib -I lib COMMON_CFLAGS += -m$(bits) COMMON_CFLAGS += -O1 +COMMON_CFLAGS += -fno-stack-protector # stack.o relies on frame pointers. KEEP_FRAME_POINTER := y From dbe71128e65a580edf1d67c2879dadff4c421d54 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 27 Jul 2017 16:34:05 +0200 Subject: [PATCH 0072/2137] Temporarily disable fxsave test --- tests/qemu/test-i386.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/qemu/test-i386.c b/tests/qemu/test-i386.c index f304426b..ef5a1d20 100644 --- a/tests/qemu/test-i386.c +++ b/tests/qemu/test-i386.c @@ -2999,7 +2999,7 @@ int main(int argc, char **argv) test_conv(); #ifdef TEST_SSE test_sse(); - test_fxsave(); + //test_fxsave(); #endif test_exceptions(); //test_single_step(); From 3a78beeb78aa4945e5ec8ca14dca563b9ae12db2 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 28 Jul 2017 20:59:17 +0200 Subject: [PATCH 0073/2137] kvm-unit-test: Add missing files --- tests/kvm-unit-tests/api/api-sample.cc | 30 ++ tests/kvm-unit-tests/api/dirty-log-perf.cc | 146 ++++++++ tests/kvm-unit-tests/api/dirty-log.cc | 84 +++++ tests/kvm-unit-tests/api/exception.cc | 33 ++ tests/kvm-unit-tests/api/exception.hh | 19 + tests/kvm-unit-tests/api/identity.cc | 120 +++++++ tests/kvm-unit-tests/api/identity.hh | 45 +++ tests/kvm-unit-tests/api/kvmxx.cc | 199 +++++++++++ tests/kvm-unit-tests/api/kvmxx.hh | 86 +++++ tests/kvm-unit-tests/api/memmap.cc | 96 +++++ tests/kvm-unit-tests/api/memmap.hh | 43 +++ tests/kvm-unit-tests/lib/argv.h | 10 + tests/kvm-unit-tests/x86/hyperv_connections.c | 336 ++++++++++++++++++ tests/kvm-unit-tests/x86/syscall.c | 108 ++++++ 14 files changed, 1355 insertions(+) create mode 100644 tests/kvm-unit-tests/api/api-sample.cc create mode 100644 tests/kvm-unit-tests/api/dirty-log-perf.cc create mode 100644 tests/kvm-unit-tests/api/dirty-log.cc create mode 100644 tests/kvm-unit-tests/api/exception.cc create mode 100644 tests/kvm-unit-tests/api/exception.hh create mode 100644 tests/kvm-unit-tests/api/identity.cc create mode 100644 tests/kvm-unit-tests/api/identity.hh create mode 100644 tests/kvm-unit-tests/api/kvmxx.cc create mode 100644 tests/kvm-unit-tests/api/kvmxx.hh create mode 100644 tests/kvm-unit-tests/api/memmap.cc create mode 100644 tests/kvm-unit-tests/api/memmap.hh create mode 100644 tests/kvm-unit-tests/lib/argv.h create mode 100644 tests/kvm-unit-tests/x86/hyperv_connections.c create mode 100644 tests/kvm-unit-tests/x86/syscall.c diff --git a/tests/kvm-unit-tests/api/api-sample.cc b/tests/kvm-unit-tests/api/api-sample.cc new file mode 100644 index 00000000..f523e470 --- /dev/null +++ b/tests/kvm-unit-tests/api/api-sample.cc @@ -0,0 +1,30 @@ + +#include "kvmxx.hh" +#include "identity.hh" +#include "exception.hh" +#include + +static int global = 0; + +static void set_global() +{ + global = 1; +} + +int test_main(int ac, char** av) +{ + kvm::system system; + kvm::vm vm(system); + mem_map memmap(vm); + identity::vm ident_vm(vm, memmap); + kvm::vcpu vcpu(vm, 0); + identity::vcpu thread(vcpu, set_global); + vcpu.run(); + printf("global %d\n", global); + return global == 1 ? 0 : 1; +} + +int main(int ac, char** av) +{ + return try_main(test_main, ac, av); +} diff --git a/tests/kvm-unit-tests/api/dirty-log-perf.cc b/tests/kvm-unit-tests/api/dirty-log-perf.cc new file mode 100644 index 00000000..f87b4b4d --- /dev/null +++ b/tests/kvm-unit-tests/api/dirty-log-perf.cc @@ -0,0 +1,146 @@ +#include "kvmxx.hh" +#include "exception.hh" +#include "memmap.hh" +#include "identity.hh" +#include +#include +#include + +namespace { + +const int page_size = 4096; +int64_t nr_total_pages = 256 * 1024; +int64_t nr_slot_pages = 256 * 1024; + +// Return the current time in nanoseconds. +uint64_t time_ns() +{ + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts.tv_sec * (uint64_t)1000000000 + ts.tv_nsec; +} + +// Update nr_to_write pages selected from nr_pages pages. +void write_mem(void* slot_head, int64_t nr_to_write, int64_t nr_pages) +{ + char* var = static_cast(slot_head); + int64_t interval = nr_pages / nr_to_write; + + for (int64_t i = 0; i < nr_to_write; ++i) { + ++(*var); + var += interval * page_size; + } +} + +// Let the guest update nr_to_write pages selected from nr_pages pages. +void do_guest_write(kvm::vcpu& vcpu, void* slot_head, + int64_t nr_to_write, int64_t nr_pages) +{ + identity::vcpu guest_write_thread(vcpu, std::bind(write_mem, slot_head, + nr_to_write, nr_pages)); + vcpu.run(); +} + +// Check how long it takes to update dirty log. +void check_dirty_log(kvm::vcpu& vcpu, mem_slot& slot, void* slot_head) +{ + slot.set_dirty_logging(true); + slot.update_dirty_log(); + + for (int64_t i = 1; i <= nr_slot_pages; i *= 2) { + do_guest_write(vcpu, slot_head, i, nr_slot_pages); + + uint64_t start_ns = time_ns(); + int n = slot.update_dirty_log(); + uint64_t end_ns = time_ns(); + + printf("get dirty log: %10lld ns for %10d dirty pages (expected %lld)\n", + end_ns - start_ns, n, i); + } + + slot.set_dirty_logging(false); +} + +} + +void parse_options(int ac, char **av) +{ + int opt; + char *endptr; + + while ((opt = getopt(ac, av, "n:m:")) != -1) { + switch (opt) { + case 'n': + errno = 0; + nr_slot_pages = strtol(optarg, &endptr, 10); + if (errno || endptr == optarg) { + printf("dirty-log-perf: Invalid number: -n %s\n", optarg); + exit(1); + } + if (*endptr == 'k' || *endptr == 'K') { + nr_slot_pages *= 1024; + } + break; + case 'm': + errno = 0; + nr_total_pages = strtol(optarg, &endptr, 10); + if (errno || endptr == optarg) { + printf("dirty-log-perf: Invalid number: -m %s\n", optarg); + exit(1); + } + if (*endptr == 'k' || *endptr == 'K') { + nr_total_pages *= 1024; + } + break; + default: + printf("dirty-log-perf: Invalid option\n"); + exit(1); + } + } + + if (nr_slot_pages > nr_total_pages) { + printf("dirty-log-perf: Invalid setting: slot %lld > mem %lld\n", + nr_slot_pages, nr_total_pages); + exit(1); + } + printf("dirty-log-perf: %lld slot pages / %lld mem pages\n", + nr_slot_pages, nr_total_pages); +} + +int test_main(int ac, char **av) +{ + kvm::system sys; + kvm::vm vm(sys); + mem_map memmap(vm); + + parse_options(ac, av); + + void* mem_head; + int64_t mem_size = nr_total_pages * page_size; + if (posix_memalign(&mem_head, page_size, mem_size)) { + printf("dirty-log-perf: Could not allocate guest memory.\n"); + exit(1); + } + uint64_t mem_addr = reinterpret_cast(mem_head); + + identity::hole hole(mem_head, mem_size); + identity::vm ident_vm(vm, memmap, hole); + kvm::vcpu vcpu(vm, 0); + + uint64_t slot_size = nr_slot_pages * page_size; + uint64_t next_size = mem_size - slot_size; + uint64_t next_addr = mem_addr + slot_size; + mem_slot slot(memmap, mem_addr, slot_size, mem_head); + mem_slot other_slot(memmap, next_addr, next_size, (void *)next_addr); + + // pre-allocate shadow pages + do_guest_write(vcpu, mem_head, nr_total_pages, nr_total_pages); + check_dirty_log(vcpu, slot, mem_head); + return 0; +} + +int main(int ac, char** av) +{ + return try_main(test_main, ac, av); +} diff --git a/tests/kvm-unit-tests/api/dirty-log.cc b/tests/kvm-unit-tests/api/dirty-log.cc new file mode 100644 index 00000000..9891e98f --- /dev/null +++ b/tests/kvm-unit-tests/api/dirty-log.cc @@ -0,0 +1,84 @@ +#include "kvmxx.hh" +#include "exception.hh" +#include "memmap.hh" +#include "identity.hh" +#include +#include +#include + +namespace { + +void delay_loop(unsigned n) +{ + for (unsigned i = 0; i < n; ++i) { + asm volatile("pause"); + } + } + +void write_mem(volatile bool& running, volatile int* shared_var) +{ + while (running) { + ++*shared_var; + delay_loop(1000); + } +} + +void check_dirty_log(mem_slot& slot, + volatile bool& running, + volatile int* shared_var, + int& nr_fail) +{ + uint64_t shared_var_gpa = reinterpret_cast(shared_var); + slot.set_dirty_logging(true); + slot.update_dirty_log(); + for (int i = 0; i < 10000000; ++i) { + int sample1 = *shared_var; + delay_loop(600); + int sample2 = *shared_var; + slot.update_dirty_log(); + if (!slot.is_dirty(shared_var_gpa) && sample1 != sample2) { + ++nr_fail; + } + } + running = false; + slot.set_dirty_logging(false); +} + +} + +int test_main(int ac, char **av) +{ + kvm::system sys; + kvm::vm vm(sys); + mem_map memmap(vm); + void* logged_slot_virt; + int ret = posix_memalign(&logged_slot_virt, 4096, 4096); + if (ret) { + throw errno_exception(ret); + } + volatile int* shared_var = static_cast(logged_slot_virt); + identity::hole hole(logged_slot_virt, 4096); + identity::vm ident_vm(vm, memmap, hole); + kvm::vcpu vcpu(vm, 0); + bool running = true; + int nr_fail = 0; + mem_slot logged_slot(memmap, + reinterpret_cast(logged_slot_virt), + 4096, logged_slot_virt); + std::thread host_poll_thread(check_dirty_log, std::ref(logged_slot), + std::ref(running), + shared_var, std::ref(nr_fail)); + identity::vcpu guest_write_thread(vcpu, + std::bind(write_mem, + std::ref(running), + shared_var)); + vcpu.run(); + host_poll_thread.join(); + printf("Dirty bitmap failures: %d\n", nr_fail); + return nr_fail == 0 ? 0 : 1; +} + +int main(int ac, char** av) +{ + return try_main(test_main, ac, av); +} diff --git a/tests/kvm-unit-tests/api/exception.cc b/tests/kvm-unit-tests/api/exception.cc new file mode 100644 index 00000000..910bdffb --- /dev/null +++ b/tests/kvm-unit-tests/api/exception.cc @@ -0,0 +1,33 @@ +#include "exception.hh" +#include +#include + +errno_exception::errno_exception(int errno) + : _errno(errno) +{ +} + +int errno_exception::errno() const +{ + return _errno; +} + +const char *errno_exception::what() +{ + std::snprintf(_buf, sizeof _buf, "error: %s (%d)", + std::strerror(_errno), _errno); + return _buf; +} + +int try_main(int (*main)(int argc, char** argv), int argc, char** argv, + int ret_on_exception) +{ + try { + return main(argc, argv); + } catch (std::exception& e) { + std::fprintf(stderr, "exception: %s\n", e.what()); + } catch (...) { + std::fprintf(stderr, "unknown exception\n"); + } + return ret_on_exception; +} diff --git a/tests/kvm-unit-tests/api/exception.hh b/tests/kvm-unit-tests/api/exception.hh new file mode 100644 index 00000000..f78d9a16 --- /dev/null +++ b/tests/kvm-unit-tests/api/exception.hh @@ -0,0 +1,19 @@ +#ifndef EXCEPTION_HH +#define EXCEPTION_HH + +#include + +class errno_exception : public std::exception { +public: + explicit errno_exception(int err_no); + int errno() const; + virtual const char *what(); +private: + int _errno; + char _buf[1000]; +}; + +int try_main(int (*main)(int argc, char** argv), int argc, char** argv, + int ret_on_exception = 127); + +#endif diff --git a/tests/kvm-unit-tests/api/identity.cc b/tests/kvm-unit-tests/api/identity.cc new file mode 100644 index 00000000..24609ef9 --- /dev/null +++ b/tests/kvm-unit-tests/api/identity.cc @@ -0,0 +1,120 @@ + +#include "identity.hh" +#include "exception.hh" +#include +#include + +namespace identity { + +typedef unsigned long ulong; + +hole::hole() + : address(), size() +{ +} + +hole::hole(void* address, size_t size) + : address(address), size(size) +{ +} + +vm::vm(kvm::vm& vm, mem_map& mmap, hole h) +{ + int ret = posix_memalign(&tss, 4096, 4 * 4096); + if (ret) { + throw errno_exception(ret); + } + + uint64_t hole_gpa = reinterpret_cast(h.address); + char* hole_hva = static_cast(h.address); + uint64_t tss_addr = reinterpret_cast(tss); + uint64_t tss_end = tss_addr + 4 * 4096; + uint64_t hole_end = hole_gpa + h.size; + + if (hole_gpa < tss_addr) { + if (hole_gpa) { + _slots.push_back(mem_slot_ptr(new mem_slot(mmap, 0, hole_gpa, NULL))); + } + _slots.push_back(mem_slot_ptr(new mem_slot(mmap, hole_end, tss_addr - hole_end, + hole_hva + h.size))); + _slots.push_back(mem_slot_ptr(new mem_slot(mmap, tss_end, (uint32_t)-tss_end, + (char*)tss + 4 * 4096))); + } else { + _slots.push_back(mem_slot_ptr(new mem_slot(mmap, 0, tss_addr, NULL))); + _slots.push_back(mem_slot_ptr(new mem_slot(mmap, tss_end, hole_gpa - tss_end, + (char*)tss + 4 * 4096))); + _slots.push_back(mem_slot_ptr(new mem_slot(mmap, hole_end, (uint32_t)-hole_end, + hole_hva + h.size))); + } + + vm.set_tss_addr(tss_addr); + vm.set_ept_identity_map_addr(tss_addr + 3 * 4096); +} + +vm::~vm() +{ + free(tss); +} + +void vcpu::setup_sregs() +{ + kvm_sregs sregs = { }; + kvm_segment dseg = { }; + dseg.base = 0; dseg.limit = -1U; dseg.type = 3; dseg.present = 1; + dseg.dpl = 3; dseg.db = 1; dseg.s = 1; dseg.l = 0; dseg.g = 1; + kvm_segment cseg = dseg; + cseg.type = 11; + + sregs.cs = cseg; asm ("mov %%cs, %0" : "=rm"(sregs.cs.selector)); + sregs.ds = dseg; asm ("mov %%ds, %0" : "=rm"(sregs.ds.selector)); + sregs.es = dseg; asm ("mov %%es, %0" : "=rm"(sregs.es.selector)); + sregs.fs = dseg; asm ("mov %%fs, %0" : "=rm"(sregs.fs.selector)); + sregs.gs = dseg; asm ("mov %%gs, %0" : "=rm"(sregs.gs.selector)); + sregs.ss = dseg; asm ("mov %%ss, %0" : "=rm"(sregs.ss.selector)); + + uint32_t gsbase; + asm ("mov %%gs:0, %0" : "=r"(gsbase)); + sregs.gs.base = gsbase; + + sregs.tr.base = reinterpret_cast(&*_stack.begin()); + sregs.tr.type = 11; + sregs.tr.s = 0; + sregs.tr.present = 1; + + sregs.cr0 = 0x11; /* PE, ET, !PG */ + sregs.cr4 = 0; + sregs.efer = 0; + sregs.apic_base = 0xfee00000; + _vcpu.set_sregs(sregs); +} + +void vcpu::thunk(vcpu* zis) +{ + zis->_guest_func(); + asm volatile("outb %%al, %%dx" : : "a"(0), "d"(0)); +} + +void vcpu::setup_regs() +{ + kvm_regs regs = {}; + regs.rflags = 0x3202; + regs.rsp = reinterpret_cast(&*_stack.end()); + regs.rsp &= ~15UL; + ulong* sp = reinterpret_cast(regs.rsp); + *--sp = reinterpret_cast((char*)this); + *--sp = 0; + regs.rsp = reinterpret_cast(sp); + regs.rip = reinterpret_cast(&vcpu::thunk); + printf("rip %llx\n", regs.rip); + _vcpu.set_regs(regs); +} + +vcpu::vcpu(kvm::vcpu& vcpu, std::function guest_func, + unsigned long stack_size) + : _vcpu(vcpu), _guest_func(guest_func), _stack(stack_size) +{ + setup_sregs(); + setup_regs(); +} + +} diff --git a/tests/kvm-unit-tests/api/identity.hh b/tests/kvm-unit-tests/api/identity.hh new file mode 100644 index 00000000..b95cb15f --- /dev/null +++ b/tests/kvm-unit-tests/api/identity.hh @@ -0,0 +1,45 @@ +#ifndef API_IDENTITY_HH +#define API_IDENTITY_HH + +#include "kvmxx.hh" +#include "memmap.hh" +#include +#include +#include + +namespace identity { + +struct hole { + hole(); + hole(void* address, size_t size); + void* address; + size_t size; +}; + +class vm { +public: + vm(kvm::vm& vm, mem_map& mmap, hole address_space_hole = hole()); + ~vm(); +private: + void *tss; + typedef std::shared_ptr mem_slot_ptr; + std::vector _slots; +}; + +class vcpu { +public: + vcpu(kvm::vcpu& vcpu, std::function guest_func, + unsigned long stack_size = 256 * 1024); +private: + static void thunk(vcpu* vcpu); + void setup_regs(); + void setup_sregs(); +private: + kvm::vcpu& _vcpu; + std::function _guest_func; + std::vector _stack; +}; + +} + +#endif diff --git a/tests/kvm-unit-tests/api/kvmxx.cc b/tests/kvm-unit-tests/api/kvmxx.cc new file mode 100644 index 00000000..313902e7 --- /dev/null +++ b/tests/kvm-unit-tests/api/kvmxx.cc @@ -0,0 +1,199 @@ +#include "kvmxx.hh" +#include "exception.hh" +#include +#include +#include +#include +#include +#include + +namespace kvm { + +static long check_error(long r) +{ + if (r == -1) { + throw errno_exception(errno); + } + return r; +} + +fd::fd(int fd) + : _fd(fd) +{ +} + +fd::fd(const fd& other) + : _fd(::dup(other._fd)) +{ + check_error(_fd); +} + +fd::fd(std::string device_node, int flags) + : _fd(::open(device_node.c_str(), flags)) +{ + check_error(_fd); +} + +long fd::ioctl(unsigned nr, long arg) +{ + return check_error(::ioctl(_fd, nr, arg)); +} + +vcpu::vcpu(vm& vm, int id) + : _vm(vm), _fd(vm._fd.ioctl(KVM_CREATE_VCPU, id)), _shared(NULL) + , _mmap_size(_vm._system._fd.ioctl(KVM_GET_VCPU_MMAP_SIZE, 0)) + +{ + kvm_run *shared = static_cast(::mmap(NULL, _mmap_size, + PROT_READ | PROT_WRITE, + MAP_SHARED, + _fd.get(), 0)); + if (shared == MAP_FAILED) { + throw errno_exception(errno); + } + _shared = shared; +} + +vcpu::~vcpu() +{ + munmap(_shared, _mmap_size); +} + +void vcpu::run() +{ + _fd.ioctl(KVM_RUN, 0); +} + +kvm_regs vcpu::regs() +{ + kvm_regs regs; + _fd.ioctlp(KVM_GET_REGS, ®s); + return regs; +} + +void vcpu::set_regs(const kvm_regs& regs) +{ + _fd.ioctlp(KVM_SET_REGS, const_cast(®s)); +} + +kvm_sregs vcpu::sregs() +{ + kvm_sregs sregs; + _fd.ioctlp(KVM_GET_SREGS, &sregs); + return sregs; +} + +void vcpu::set_sregs(const kvm_sregs& sregs) +{ + _fd.ioctlp(KVM_SET_SREGS, const_cast(&sregs)); +} + +class vcpu::kvm_msrs_ptr { +public: + explicit kvm_msrs_ptr(size_t nmsrs); + ~kvm_msrs_ptr() { ::free(_kvm_msrs); } + kvm_msrs* operator->() { return _kvm_msrs; } + kvm_msrs* get() { return _kvm_msrs; } +private: + kvm_msrs* _kvm_msrs; +}; + +vcpu::kvm_msrs_ptr::kvm_msrs_ptr(size_t nmsrs) + : _kvm_msrs(0) +{ + size_t size = sizeof(kvm_msrs) + sizeof(kvm_msr_entry) * nmsrs; + _kvm_msrs = static_cast(::malloc(size)); + if (!_kvm_msrs) { + throw std::bad_alloc(); + } +} + +std::vector vcpu::msrs(std::vector indices) +{ + kvm_msrs_ptr msrs(indices.size()); + msrs->nmsrs = indices.size(); + for (unsigned i = 0; i < msrs->nmsrs; ++i) { + msrs->entries[i].index = indices[i]; + } + _fd.ioctlp(KVM_GET_MSRS, msrs.get()); + return std::vector(msrs->entries, + msrs->entries + msrs->nmsrs); +} + +void vcpu::set_msrs(const std::vector& msrs) +{ + kvm_msrs_ptr _msrs(msrs.size()); + _msrs->nmsrs = msrs.size(); + std::copy(msrs.begin(), msrs.end(), _msrs->entries); + _fd.ioctlp(KVM_SET_MSRS, _msrs.get()); +} + +void vcpu::set_debug(uint64_t dr[8], bool enabled, bool singlestep) +{ + kvm_guest_debug gd; + + gd.control = 0; + if (enabled) { + gd.control |= KVM_GUESTDBG_ENABLE; + } + if (singlestep) { + gd.control |= KVM_GUESTDBG_SINGLESTEP; + } + for (int i = 0; i < 8; ++i) { + gd.arch.debugreg[i] = dr[i]; + } + _fd.ioctlp(KVM_SET_GUEST_DEBUG, &gd); +} + +vm::vm(system& system) + : _system(system), _fd(system._fd.ioctl(KVM_CREATE_VM, 0)) +{ +} + +void vm::set_memory_region(int slot, void *addr, uint64_t gpa, size_t len, + uint32_t flags) +{ + struct kvm_userspace_memory_region umr; + + umr.slot = slot; + umr.flags = flags; + umr.guest_phys_addr = gpa; + umr.memory_size = len; + umr.userspace_addr = reinterpret_cast(addr); + _fd.ioctlp(KVM_SET_USER_MEMORY_REGION, &umr); +} + +void vm::get_dirty_log(int slot, void *log) +{ + struct kvm_dirty_log kdl; + kdl.slot = slot; + kdl.dirty_bitmap = log; + _fd.ioctlp(KVM_GET_DIRTY_LOG, &kdl); +} + +void vm::set_tss_addr(uint32_t addr) +{ + _fd.ioctl(KVM_SET_TSS_ADDR, addr); +} + +void vm::set_ept_identity_map_addr(uint64_t addr) +{ + _fd.ioctlp(KVM_SET_IDENTITY_MAP_ADDR, &addr); +} + +system::system(std::string device_node) + : _fd(device_node, O_RDWR) +{ +} + +bool system::check_extension(int extension) +{ + return _fd.ioctl(KVM_CHECK_EXTENSION, extension); +} + +int system::get_extension_int(int extension) +{ + return _fd.ioctl(KVM_CHECK_EXTENSION, extension); +} + +}; diff --git a/tests/kvm-unit-tests/api/kvmxx.hh b/tests/kvm-unit-tests/api/kvmxx.hh new file mode 100644 index 00000000..e39bd5b2 --- /dev/null +++ b/tests/kvm-unit-tests/api/kvmxx.hh @@ -0,0 +1,86 @@ +#ifndef KVMXX_H +#define KVMXX_H + +#include +#include +#include +#include +#include +#include +#include + +namespace kvm { + +class system; +class vm; +class vcpu; +class fd; + +class fd { +public: + explicit fd(int n); + explicit fd(std::string path, int flags); + fd(const fd& other); + ~fd() { ::close(_fd); } + int get() { return _fd; } + long ioctl(unsigned nr, long arg); + long ioctlp(unsigned nr, void *arg) { + return ioctl(nr, reinterpret_cast(arg)); + } +private: + int _fd; +}; + +class vcpu { +public: + vcpu(vm& vm, int fd); + ~vcpu(); + void run(); + kvm_run *shared(); + kvm_regs regs(); + void set_regs(const kvm_regs& regs); + kvm_sregs sregs(); + void set_sregs(const kvm_sregs& sregs); + std::vector msrs(std::vector indices); + void set_msrs(const std::vector& msrs); + void set_debug(uint64_t dr[8], bool enabled, bool singlestep); +private: + class kvm_msrs_ptr; +private: + vm& _vm; + fd _fd; + kvm_run *_shared; + unsigned _mmap_size; + friend class vm; +}; + +class vm { +public: + explicit vm(system& system); + void set_memory_region(int slot, void *addr, uint64_t gpa, size_t len, + uint32_t flags = 0); + void get_dirty_log(int slot, void *log); + void set_tss_addr(uint32_t addr); + void set_ept_identity_map_addr(uint64_t addr); + system& sys() { return _system; } +private: + system& _system; + fd _fd; + friend class system; + friend class vcpu; +}; + +class system { +public: + explicit system(std::string device_node = "/dev/kvm"); + bool check_extension(int extension); + int get_extension_int(int extension); +private: + fd _fd; + friend class vcpu; + friend class vm; +}; + +}; + +#endif diff --git a/tests/kvm-unit-tests/api/memmap.cc b/tests/kvm-unit-tests/api/memmap.cc new file mode 100644 index 00000000..cf44824f --- /dev/null +++ b/tests/kvm-unit-tests/api/memmap.cc @@ -0,0 +1,96 @@ + +#include "memmap.hh" +#include + +mem_slot::mem_slot(mem_map& map, uint64_t gpa, uint64_t size, void* hva) + : _map(map) + , _slot(map._free_slots.top()) + , _gpa(gpa) + , _size(size) + , _hva(hva) + , _dirty_log_enabled(false) + , _log() +{ + map._free_slots.pop(); + if (_size) { + update(); + } +} + +mem_slot::~mem_slot() +{ + if (!_size) { + return; + } + _size = 0; + try { + update(); + _map._free_slots.push(_slot); + } catch (...) { + // can't do much if we can't undo slot registration - leak the slot + } +} + +void mem_slot::set_dirty_logging(bool enabled) +{ + if (_dirty_log_enabled != enabled) { + _dirty_log_enabled = enabled; + if (enabled) { + int logsize = ((_size >> 12) + bits_per_word - 1) / bits_per_word; + _log.resize(logsize); + } else { + _log.resize(0); + } + if (_size) { + update(); + } + } +} + +void mem_slot::update() +{ + uint32_t flags = 0; + if (_dirty_log_enabled) { + flags |= KVM_MEM_LOG_DIRTY_PAGES; + } + _map._vm.set_memory_region(_slot, _hva, _gpa, _size, flags); +} + +bool mem_slot::dirty_logging() const +{ + return _dirty_log_enabled; +} + +static inline int hweight(uint64_t w) +{ + w -= (w >> 1) & 0x5555555555555555; + w = (w & 0x3333333333333333) + ((w >> 2) & 0x3333333333333333); + w = (w + (w >> 4)) & 0x0f0f0f0f0f0f0f0f; + return (w * 0x0101010101010101) >> 56; +} + +int mem_slot::update_dirty_log() +{ + _map._vm.get_dirty_log(_slot, &_log[0]); + return std::accumulate(_log.begin(), _log.end(), 0, + [] (int prev, ulong elem) -> int { + return prev + hweight(elem); + }); +} + +bool mem_slot::is_dirty(uint64_t gpa) const +{ + uint64_t pagenr = (gpa - _gpa) >> 12; + ulong wordnr = pagenr / bits_per_word; + ulong bit = 1ULL << (pagenr % bits_per_word); + return _log[wordnr] & bit; +} + +mem_map::mem_map(kvm::vm& vm) + : _vm(vm) +{ + int nr_slots = vm.sys().get_extension_int(KVM_CAP_NR_MEMSLOTS); + for (int i = 0; i < nr_slots; ++i) { + _free_slots.push(i); + } +} diff --git a/tests/kvm-unit-tests/api/memmap.hh b/tests/kvm-unit-tests/api/memmap.hh new file mode 100644 index 00000000..48711ae2 --- /dev/null +++ b/tests/kvm-unit-tests/api/memmap.hh @@ -0,0 +1,43 @@ +#ifndef MEMMAP_HH +#define MEMMAP_HH + +#include "kvmxx.hh" +#include +#include +#include + +class mem_map; +class mem_slot; + +class mem_slot { +public: + mem_slot(mem_map& map, uint64_t gpa, uint64_t size, void *hva); + ~mem_slot(); + void set_dirty_logging(bool enabled); + bool dirty_logging() const; + int update_dirty_log(); + bool is_dirty(uint64_t gpa) const; +private: + void update(); +private: + typedef unsigned long ulong; + static const int bits_per_word = sizeof(ulong) * 8; + mem_map& _map; + int _slot; + uint64_t _gpa; + uint64_t _size; + void *_hva; + bool _dirty_log_enabled; + std::vector _log; +}; + +class mem_map { +public: + mem_map(kvm::vm& vm); +private: + kvm::vm& _vm; + std::stack _free_slots; + friend class mem_slot; +}; + +#endif diff --git a/tests/kvm-unit-tests/lib/argv.h b/tests/kvm-unit-tests/lib/argv.h new file mode 100644 index 00000000..2104dd42 --- /dev/null +++ b/tests/kvm-unit-tests/lib/argv.h @@ -0,0 +1,10 @@ +/* + * Set up arguments for main() and prepare environment variables + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License version 2. + */ + +extern void __setup_args(void); +extern void setup_args_progname(const char *args); +extern void setup_env(char *env, int size); diff --git a/tests/kvm-unit-tests/x86/hyperv_connections.c b/tests/kvm-unit-tests/x86/hyperv_connections.c new file mode 100644 index 00000000..b061048d --- /dev/null +++ b/tests/kvm-unit-tests/x86/hyperv_connections.c @@ -0,0 +1,336 @@ +#include "libcflat.h" +#include "vm.h" +#include "smp.h" +#include "isr.h" +#include "atomic.h" +#include "hyperv.h" +#include "bitops.h" + +#define MAX_CPUS 64 + +#define MSG_VEC 0xb0 +#define EVT_VEC 0xb1 +#define MSG_SINT 0x8 +#define EVT_SINT 0x9 +#define MSG_CONN_BASE 0x10 +#define EVT_CONN_BASE 0x20 +#define MSG_TYPE 0x12345678 + +#define WAIT_CYCLES 10000000 + +static atomic_t ncpus_done; + +struct hv_vcpu { + struct hv_message_page *msg_page; + struct hv_event_flags_page *evt_page; + struct hv_input_post_message *post_msg; + u8 msg_conn; + u8 evt_conn; + u64 hvcall_status; + atomic_t sint_received; +}; + +static struct hv_vcpu hv_vcpus[MAX_CPUS]; + +static void sint_isr(isr_regs_t *regs) +{ + atomic_inc(&hv_vcpus[smp_id()].sint_received); +} + +static void *hypercall_page; + +static void setup_hypercall(void) +{ + u64 guestid = (0x8f00ull << 48); + + hypercall_page = alloc_page(); + if (!hypercall_page) + report_abort("failed to allocate hypercall page"); + memset(hypercall_page, 0, PAGE_SIZE); + + wrmsr(HV_X64_MSR_GUEST_OS_ID, guestid); + + wrmsr(HV_X64_MSR_HYPERCALL, + (u64)virt_to_phys(hypercall_page) | HV_X64_MSR_HYPERCALL_ENABLE); +} + +static void teardown_hypercall(void) +{ + wrmsr(HV_X64_MSR_HYPERCALL, 0); + wrmsr(HV_X64_MSR_GUEST_OS_ID, 0); + free_page(hypercall_page); +} + +static u64 do_hypercall(u16 code, u64 arg, bool fast) +{ + u64 ret; + u64 ctl = code; + if (fast) + ctl |= HV_HYPERCALL_FAST; + + asm volatile ("call *%[hcall_page]" +#ifdef __x86_64__ + "\n mov $0,%%r8" + : "=a"(ret) + : "c"(ctl), "d"(arg), +#else + : "=A"(ret) + : "A"(ctl), + "b" ((u32)(arg >> 32)), "c" ((u32)arg), + "D"(0), "S"(0), +#endif + [hcall_page] "m" (hypercall_page) +#ifdef __x86_64__ + : "r8" +#endif + ); + + return ret; +} + +static void setup_cpu(void *ctx) +{ + int vcpu; + struct hv_vcpu *hv; + + write_cr3((ulong)ctx); + irq_enable(); + + vcpu = smp_id(); + hv = &hv_vcpus[vcpu]; + + hv->msg_page = alloc_page(); + hv->evt_page = alloc_page(); + hv->post_msg = alloc_page(); + if (!hv->msg_page || !hv->evt_page || !hv->post_msg) + report_abort("failed to allocate synic pages for vcpu"); + memset(hv->msg_page, 0, sizeof(*hv->msg_page)); + memset(hv->evt_page, 0, sizeof(*hv->evt_page)); + memset(hv->post_msg, 0, sizeof(*hv->post_msg)); + hv->msg_conn = MSG_CONN_BASE + vcpu; + hv->evt_conn = EVT_CONN_BASE + vcpu; + + wrmsr(HV_X64_MSR_SIMP, + (u64)virt_to_phys(hv->msg_page) | HV_SYNIC_SIMP_ENABLE); + wrmsr(HV_X64_MSR_SIEFP, + (u64)virt_to_phys(hv->evt_page) | HV_SYNIC_SIEFP_ENABLE); + wrmsr(HV_X64_MSR_SCONTROL, HV_SYNIC_CONTROL_ENABLE); + + msg_conn_create(MSG_SINT, MSG_VEC, hv->msg_conn); + evt_conn_create(EVT_SINT, EVT_VEC, hv->evt_conn); + + hv->post_msg->connectionid = hv->msg_conn; + hv->post_msg->message_type = MSG_TYPE; + hv->post_msg->payload_size = 8; + hv->post_msg->payload[0] = (u64)vcpu << 16; +} + +static void teardown_cpu(void *ctx) +{ + int vcpu = smp_id(); + struct hv_vcpu *hv = &hv_vcpus[vcpu]; + + evt_conn_destroy(EVT_SINT, hv->evt_conn); + msg_conn_destroy(MSG_SINT, hv->msg_conn); + + wrmsr(HV_X64_MSR_SCONTROL, 0); + wrmsr(HV_X64_MSR_SIEFP, 0); + wrmsr(HV_X64_MSR_SIMP, 0); + + free_page(hv->post_msg); + free_page(hv->evt_page); + free_page(hv->msg_page); +} + +static void do_msg(void *ctx) +{ + int vcpu = (ulong)ctx; + struct hv_vcpu *hv = &hv_vcpus[vcpu]; + struct hv_input_post_message *msg = hv->post_msg; + + msg->payload[0]++; + atomic_set(&hv->sint_received, 0); + hv->hvcall_status = do_hypercall(HVCALL_POST_MESSAGE, + virt_to_phys(msg), 0); + atomic_inc(&ncpus_done); +} + +static void clear_msg(void *ctx) +{ + /* should only be done on the current vcpu */ + int vcpu = smp_id(); + struct hv_vcpu *hv = &hv_vcpus[vcpu]; + struct hv_message *msg = &hv->msg_page->sint_message[MSG_SINT]; + + atomic_set(&hv->sint_received, 0); + msg->header.message_type = 0; + barrier(); + wrmsr(HV_X64_MSR_EOM, 0); + atomic_inc(&ncpus_done); +} + +static bool msg_ok(int vcpu) +{ + struct hv_vcpu *hv = &hv_vcpus[vcpu]; + struct hv_input_post_message *post_msg = hv->post_msg; + struct hv_message *msg = &hv->msg_page->sint_message[MSG_SINT]; + + return msg->header.message_type == post_msg->message_type && + msg->header.payload_size == post_msg->payload_size && + msg->header.message_flags.msg_pending == 0 && + msg->u.payload[0] == post_msg->payload[0] && + hv->hvcall_status == 0 && + atomic_read(&hv->sint_received) == 1; +} + +static bool msg_busy(int vcpu) +{ + struct hv_vcpu *hv = &hv_vcpus[vcpu]; + struct hv_input_post_message *post_msg = hv->post_msg; + struct hv_message *msg = &hv->msg_page->sint_message[MSG_SINT]; + + return msg->header.message_type == post_msg->message_type && + msg->header.payload_size == post_msg->payload_size && + msg->header.message_flags.msg_pending == 1 && + msg->u.payload[0] == post_msg->payload[0] - 1 && + hv->hvcall_status == 0 && + atomic_read(&hv->sint_received) == 0; +} + +static void do_evt(void *ctx) +{ + int vcpu = (ulong)ctx; + struct hv_vcpu *hv = &hv_vcpus[vcpu]; + + atomic_set(&hv->sint_received, 0); + hv->hvcall_status = do_hypercall(HVCALL_SIGNAL_EVENT, + hv->evt_conn, 1); + atomic_inc(&ncpus_done); +} + +static void clear_evt(void *ctx) +{ + /* should only be done on the current vcpu */ + int vcpu = smp_id(); + struct hv_vcpu *hv = &hv_vcpus[vcpu]; + ulong *flags = hv->evt_page->slot[EVT_SINT].flags; + + atomic_set(&hv->sint_received, 0); + flags[BIT_WORD(hv->evt_conn)] &= ~BIT_MASK(hv->evt_conn); + barrier(); + atomic_inc(&ncpus_done); +} + +static bool evt_ok(int vcpu) +{ + struct hv_vcpu *hv = &hv_vcpus[vcpu]; + ulong *flags = hv->evt_page->slot[EVT_SINT].flags; + + return flags[BIT_WORD(hv->evt_conn)] == BIT_MASK(hv->evt_conn) && + hv->hvcall_status == 0 && + atomic_read(&hv->sint_received) == 1; +} + +static bool evt_busy(int vcpu) +{ + struct hv_vcpu *hv = &hv_vcpus[vcpu]; + ulong *flags = hv->evt_page->slot[EVT_SINT].flags; + + return flags[BIT_WORD(hv->evt_conn)] == BIT_MASK(hv->evt_conn) && + hv->hvcall_status == 0 && + atomic_read(&hv->sint_received) == 0; +} + +static int run_test(int ncpus, int dst_add, ulong wait_cycles, + void (*func)(void *), bool (*is_ok)(int)) +{ + int i, ret = 0; + + atomic_set(&ncpus_done, 0); + for (i = 0; i < ncpus; i++) { + ulong dst = (i + dst_add) % ncpus; + on_cpu_async(i, func, (void *)dst); + } + while (atomic_read(&ncpus_done) != ncpus) + pause(); + + while (wait_cycles--) + pause(); + + if (is_ok) + for (i = 0; i < ncpus; i++) + ret += is_ok(i); + return ret; +} + +#define HV_STATUS_INVALID_HYPERCALL_CODE 2 + +int main(int ac, char **av) +{ + int ncpus, ncpus_ok, i; + + if (!synic_supported()) { + report_skip("Hyper-V SynIC is not supported"); + goto summary; + } + + setup_vm(); + smp_init(); + ncpus = cpu_count(); + if (ncpus > MAX_CPUS) + report_abort("# cpus: %d > %d", ncpus, MAX_CPUS); + + handle_irq(MSG_VEC, sint_isr); + handle_irq(EVT_VEC, sint_isr); + + setup_hypercall(); + + if (do_hypercall(HVCALL_SIGNAL_EVENT, 0x1234, 1) == + HV_STATUS_INVALID_HYPERCALL_CODE) { + report_skip("Hyper-V SynIC connections are not supported"); + goto summary; + } + + for (i = 0; i < ncpus; i++) + on_cpu(i, setup_cpu, (void *)read_cr3()); + + ncpus_ok = run_test(ncpus, 0, WAIT_CYCLES, do_msg, msg_ok); + report("send message to self: %d/%d", + ncpus_ok == ncpus, ncpus_ok, ncpus); + + run_test(ncpus, 0, 0, clear_msg, NULL); + + ncpus_ok = run_test(ncpus, 1, WAIT_CYCLES, do_msg, msg_ok); + report("send message to another cpu: %d/%d", + ncpus_ok == ncpus, ncpus_ok, ncpus); + + ncpus_ok = run_test(ncpus, 1, WAIT_CYCLES, do_msg, msg_busy); + report("send message to busy slot: %d/%d", + ncpus_ok == ncpus, ncpus_ok, ncpus); + + ncpus_ok = run_test(ncpus, 0, WAIT_CYCLES, clear_msg, msg_ok); + report("receive pending message: %d/%d", + ncpus_ok == ncpus, ncpus_ok, ncpus); + + ncpus_ok = run_test(ncpus, 0, WAIT_CYCLES, do_evt, evt_ok); + report("signal event on self: %d/%d", + ncpus_ok == ncpus, ncpus_ok, ncpus); + + run_test(ncpus, 0, 0, clear_evt, NULL); + + ncpus_ok = run_test(ncpus, 1, WAIT_CYCLES, do_evt, evt_ok); + report("signal event on another cpu: %d/%d", + ncpus_ok == ncpus, ncpus_ok, ncpus); + + ncpus_ok = run_test(ncpus, 1, WAIT_CYCLES, do_evt, evt_busy); + report("signal event already set: %d/%d", + ncpus_ok == ncpus, ncpus_ok, ncpus); + + for (i = 0; i < ncpus; i++) + on_cpu(i, teardown_cpu, NULL); + + teardown_hypercall(); + +summary: + return report_summary(); +} diff --git a/tests/kvm-unit-tests/x86/syscall.c b/tests/kvm-unit-tests/x86/syscall.c new file mode 100644 index 00000000..8c3992d3 --- /dev/null +++ b/tests/kvm-unit-tests/x86/syscall.c @@ -0,0 +1,108 @@ +/* msr tests */ + +#include "libcflat.h" +#include "processor.h" +#include "msr.h" +#include "desc.h" + +static void test_syscall_lazy_load(void) +{ + extern void syscall_target(); + u16 cs = read_cs(), ss = read_ss(); + ulong tmp; + + wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_SCE); + wrmsr(MSR_LSTAR, (ulong)syscall_target); + wrmsr(MSR_STAR, (uint64_t)cs << 32); + asm volatile("pushf; syscall; syscall_target: popf" : "=c"(tmp) : : "r11"); + write_ss(ss); + // will crash horribly if broken + report("MSR_*STAR eager loading", true); +} + +/* + * test handling of TF in syscall/sysret: #DB is raised if TF + * is 1 at the *end* of syscall/sysret. + * + * This uses 32-bit syscall/sysret because KVM emulates it on Intel processors. + * However, the same bug happens with 64-bit syscall/sysret if two vCPUs + * "race" to force the emulation of syscall/sysret. + */ + +static uint16_t code_segment_upon_db; +static void handle_db(struct ex_regs *regs) +{ + code_segment_upon_db = regs->cs; + regs->rflags &= ~(1 << 8); +} + +/* expects desired ring 3 flags in rax */ +asm("syscall32_target:\n" + " cmp $0, code_segment_upon_db(%rip)\n" + " jne back_to_test\n" + " mov %eax,%r11d\n" + " sysretl\n"); + +/* 32-bit, ring-3 part of test_syscall_tf */ +asm(" .code32\n" + "syscall_tf_user32:\n" + " pushf\n" + " pop %eax\n" + " or $(1<<8),%eax\n" + " push %eax\n" + " popf\n" + " syscall\n" /* singlestep trap taken after syscall */ + " syscall\n" /* jumps back to test_syscall_tf's body */ + " .code64\n"); + +static void test_syscall_tf(void) +{ + extern void syscall32_target(); + extern void syscall_tf_user32(); + ulong rcx; + + wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_SCE); + wrmsr(MSR_CSTAR, (ulong)syscall32_target); + wrmsr(MSR_STAR, ((uint64_t)USER_CS32 << 48) | ((uint64_t)KERNEL_CS64 << 32)); + wrmsr(MSR_SYSCALL_MASK, X86_EFLAGS_TF|X86_EFLAGS_DF|X86_EFLAGS_IF|X86_EFLAGS_NT); + handle_exception(DB_VECTOR, handle_db); + + /* good: + * sysret to syscall_tf_user32 + * popf sets TF (singlestep starts on the next instruction) + * syscall to syscall32_target -> TF cleared and no singlestep + * sysretl sets TF + * handle_db sets code_segment_upon_db to USER_CS32 and clears TF + * syscall to syscall32_target + * syscall32_target jumps to back_to_test + * + * bad: + * sysret to syscall_tf_user32 + * popf sets TF (singlestep starts on the next instruction) + * syscall to syscall32_target, TF cleared and wrong singlestep exception + * handle_db sets code_segment_upon_db to KERNEL_CS64 + * syscall32_target jumps to back_to_test + */ + rcx = (ulong)syscall_tf_user32; + asm volatile(" push %%rbp\n" + " pushf; pop %%rax\n" // expected by syscall32_target + " sysret\n" + "back_to_test:\n" + " pop %%rbp" + : "+c"(rcx) : + : "rax", "rbx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "r15"); + if (code_segment_upon_db != USER_CS32) { + printf("wrong CS (%#04x)!\n", code_segment_upon_db); + } + report("syscall TF handling", code_segment_upon_db == USER_CS32); +} + +int main(int ac, char **av) +{ + setup_idt(); + test_syscall_lazy_load(); + test_syscall_tf(); + + return report_summary(); +} From 725edc451fb99cbf7ed179e6e912779372f66979 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Thu, 27 Jul 2017 16:46:24 +0530 Subject: [PATCH 0074/2137] port pop16 and get_stack_reg --- src/browser/starter.js | 1 - src/cpu.js | 2 ++ src/native/cpu.c | 13 +++++++++++++ src/native/misc_instr.c | 9 +++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 0e74960f..c3495d06 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -166,7 +166,6 @@ function V86Starter(options) "_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); }, - "_pop16": function() { return cpu.pop16.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); }, diff --git a/src/cpu.js b/src/cpu.js index 68454499..596e525f 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -298,6 +298,8 @@ CPU.prototype.wasm_patch = function(wm) this.push32 = this.wm.funcs['_push32']; this.pusha16 = this.wm.funcs['_pusha16']; this.pusha32 = this.wm.funcs['_pusha32']; + this.pop16 = this.wm.funcs['_pop16']; + this.get_stack_reg = this.wm.funcs['_get_stack_reg']; }; CPU.prototype.get_state = function() diff --git a/src/native/cpu.c b/src/native/cpu.c index be0f91c2..eb2ad005 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -738,3 +738,16 @@ int32_t get_real_eip() { return *instruction_pointer - get_seg(CS); } + +int32_t get_stack_reg() +{ + if(*stack_size_32) + { + return reg32s[ESP]; + } + else + { + return reg16[SP]; + } +} + diff --git a/src/native/misc_instr.c b/src/native/misc_instr.c index 40d1b8ad..da9391c8 100644 --- a/src/native/misc_instr.c +++ b/src/native/misc_instr.c @@ -224,6 +224,15 @@ void push32(int32_t imm32) } } +int32_t pop16() +{ + int32_t sp = get_seg(SS) + get_stack_reg(); + int32_t result = safe_read16(sp); + + adjust_stack_reg(2); + return result; +} + int32_t pop32s() { if(*stack_size_32) From cd4d4491592021d535f873a877833fc1838741a3 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Thu, 27 Jul 2017 16:46:24 +0530 Subject: [PATCH 0075/2137] port setcc --- src/browser/starter.js | 2 -- src/cpu.js | 1 + src/native/misc_instr.c | 4 ++++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index c3495d06..57318419 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -204,8 +204,6 @@ function V86Starter(options) "_popcnt": function() { return cpu.popcnt.apply(cpu, arguments); }, "_bswap": function() { return cpu.bswap.apply(cpu, arguments); }, - "_setcc": function() { return cpu.setcc.apply(cpu, arguments); }, - "_lar": function() { return cpu.lar.apply(cpu, arguments); }, "_lsl": function() { return cpu.lsl.apply(cpu, arguments); }, "_verw": function() { return cpu.verw.apply(cpu, arguments); }, diff --git a/src/cpu.js b/src/cpu.js index 596e525f..05592b14 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -300,6 +300,7 @@ CPU.prototype.wasm_patch = function(wm) this.pusha32 = this.wm.funcs['_pusha32']; this.pop16 = this.wm.funcs['_pop16']; this.get_stack_reg = this.wm.funcs['_get_stack_reg']; + this.setcc = this.wm.funcs['_setcc']; }; CPU.prototype.get_state = function() diff --git a/src/native/misc_instr.c b/src/native/misc_instr.c index da9391c8..54953c07 100644 --- a/src/native/misc_instr.c +++ b/src/native/misc_instr.c @@ -284,3 +284,7 @@ void pusha32() push32(reg32s[ESI]); push32(reg32s[EDI]); } + +void setcc(bool condition) { + set_e8(condition); +} From c866462bd60c09fe0403f201558cb4b17b031e67 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Thu, 27 Jul 2017 16:46:24 +0530 Subject: [PATCH 0076/2137] port set_stack_reg --- src/browser/starter.js | 1 - src/cpu.js | 1 + src/native/cpu.c | 12 ++++++++++++ src/native/misc_instr.c | 2 +- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 57318419..d9c28652 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -170,7 +170,6 @@ function V86Starter(options) "_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); }, - "_set_stack_reg": function() { return cpu.set_stack_reg.apply(cpu, arguments); }, "_getiopl": function() { return cpu.getiopl.apply(cpu, arguments); }, "_vm86_mode": function() { return cpu.vm86_mode.apply(cpu, arguments); }, "_shl8": function() { return cpu.shl8.apply(cpu, arguments); }, diff --git a/src/cpu.js b/src/cpu.js index 05592b14..364ac4c9 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -301,6 +301,7 @@ CPU.prototype.wasm_patch = function(wm) this.pop16 = this.wm.funcs['_pop16']; this.get_stack_reg = this.wm.funcs['_get_stack_reg']; this.setcc = this.wm.funcs['_setcc']; + this.set_stack_reg = this.wm.funcs['_set_stack_reg']; }; CPU.prototype.get_state = function() diff --git a/src/native/cpu.c b/src/native/cpu.c index eb2ad005..9b3114b5 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -751,3 +751,15 @@ int32_t get_stack_reg() } } +void set_stack_reg(int32_t value) +{ + if(*stack_size_32) + { + reg32s[ESP] = value; + } + else + { + reg16[SP] = value; + } +} + diff --git a/src/native/misc_instr.c b/src/native/misc_instr.c index 54953c07..2f063233 100644 --- a/src/native/misc_instr.c +++ b/src/native/misc_instr.c @@ -286,5 +286,5 @@ void pusha32() } void setcc(bool condition) { - set_e8(condition); + set_e8(condition); } From 3140cce77f4163692a055f1ffe011d873f0aba7a Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Thu, 27 Jul 2017 16:46:24 +0530 Subject: [PATCH 0077/2137] port shift functions etc. from arith.js --- src/browser/starter.js | 16 +-- src/cpu.js | 14 +++ src/native/arith.c | 265 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 280 insertions(+), 15 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index d9c28652..a667cb0e 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -172,21 +172,7 @@ function V86Starter(options) "_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); }, - "_shl8": function() { return cpu.shl8.apply(cpu, arguments); }, - "_shr8": function() { return cpu.shr8.apply(cpu, arguments); }, - "_sar8": function() { return cpu.sar8.apply(cpu, arguments); }, - "_shl16": function() { return cpu.shl16.apply(cpu, arguments); }, - "_shr16": function() { return cpu.shr16.apply(cpu, arguments); }, - "_sar16": function() { return cpu.sar16.apply(cpu, arguments); }, - "_shl32": function() { return cpu.shl32.apply(cpu, arguments); }, - "_shr32": function() { return cpu.shr32.apply(cpu, arguments); }, - "_sar32": function() { return cpu.sar32.apply(cpu, arguments); }, - - "_shrd16": function() { return cpu.shrd16.apply(cpu, arguments); }, - "_shrd32": function() { return cpu.shrd32.apply(cpu, arguments); }, - "_shld16": function() { return cpu.shld16.apply(cpu, arguments); }, - "_shld32": function() { return cpu.shld32.apply(cpu, arguments); }, - + "_bt_reg": function() { return cpu.bt_reg.apply(cpu, arguments); }, "_bt_mem": function() { return cpu.bt_mem.apply(cpu, arguments); }, "_btr_reg": function() { return cpu.btr_reg.apply(cpu, arguments); }, diff --git a/src/cpu.js b/src/cpu.js index 364ac4c9..345d8384 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -279,6 +279,20 @@ CPU.prototype.wasm_patch = function(wm) this.trigger_de = this.wm.funcs['_trigger_de']; this.trigger_gp = this.wm.funcs['_trigger_gp']; + this.shl8 = this.wm.funcs['_shl8']; + this.shl16 = this.wm.funcs['_shl16']; + this.shl32 = this.wm.funcs['_shl32']; + this.shr8 = this.wm.funcs['_shr8']; + this.shr16 = this.wm.funcs['_shr16']; + this.shr32 = this.wm.funcs['_shr32']; + this.sar8 = this.wm.funcs['_sar8']; + this.sar16 = this.wm.funcs['_sar16']; + this.sar32 = this.wm.funcs['_sar32']; + this.shrd16 = this.wm.funcs['_shrd16']; + this.shrd32 = this.wm.funcs['_shrd32']; + this.shld16 = this.wm.funcs['_shld16']; + this.shld32 = this.wm.funcs['_shld32']; + this.do_many_cycles_unsafe = this.wm.funcs['_do_many_cycles_unsafe']; this.read_imm8 = this.wm.funcs['_read_imm8']; diff --git a/src/native/arith.c b/src/native/arith.c index e9cc853f..91321c0f 100644 --- a/src/native/arith.c +++ b/src/native/arith.c @@ -823,3 +823,268 @@ void div16(uint32_t source_operand) } } +int32_t shl8(int32_t dest_operand, int32_t count) +{ + if(count == 0) + { + return dest_operand; + } + + *last_result = dest_operand << count; + + *last_op_size = OPSIZE_8; + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; + *flags = (*flags & ~1 & ~FLAG_OVERFLOW) + | (*last_result >> 8 & 1) + | (*last_result << 3 ^ *last_result << 4) & FLAG_OVERFLOW; + + return *last_result; +} + +int32_t shl16(int32_t dest_operand, int32_t count) +{ + if(count == 0) + { + return dest_operand; + } + + *last_result = dest_operand << count; + + *last_op_size = OPSIZE_16; + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; + *flags = (*flags & ~1 & ~FLAG_OVERFLOW) + | (*last_result >> 16 & 1) + | (*last_result >> 5 ^ *last_result >> 4) & FLAG_OVERFLOW; + + return *last_result; +} + +int32_t shl32(int32_t dest_operand, int32_t count) +{ + if(count == 0) + { + return dest_operand; + } + + *last_result = dest_operand << count; + + *last_op_size = OPSIZE_32; + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; + // test this + *flags = (*flags & ~1 & ~FLAG_OVERFLOW) | (dest_operand >> (32 - count) & 1); + *flags |= ((*flags & 1) ^ (*last_result >> 31 & 1)) << 11 & FLAG_OVERFLOW; + + return *last_result; +} + +int32_t shr8(int32_t dest_operand, int32_t count) +{ + if(count == 0) + { + return dest_operand; + } + + *last_result = dest_operand >> count; + + *last_op_size = OPSIZE_8; + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; + *flags = (*flags & ~1 & ~FLAG_OVERFLOW) + | (dest_operand >> (count - 1) & 1) + | (dest_operand >> 7 & 1) << 11 & FLAG_OVERFLOW; + + return *last_result; +} + +int32_t shr16(int32_t dest_operand, int32_t count) +{ + if(count == 0) + { + return dest_operand; + } + + *last_result = dest_operand >> count; + + *last_op_size = OPSIZE_16; + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; + *flags = (*flags & ~1 & ~FLAG_OVERFLOW) + | (dest_operand >> (count - 1) & 1) + | (dest_operand >> 4) & FLAG_OVERFLOW; + + return *last_result; +} + +int32_t shr32(int32_t dest_operand, int32_t count) +{ + if(count == 0) + { + return dest_operand; + } + + *last_result = ((uint32_t) dest_operand) >> count; + + *last_op_size = OPSIZE_32; + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; + *flags = (*flags & ~1 & ~FLAG_OVERFLOW) + | (((uint32_t) dest_operand) >> (count - 1) & 1) + | (dest_operand >> 20) & FLAG_OVERFLOW; + + return *last_result; +} + +int32_t sar8(int32_t dest_operand, int32_t count) +{ + if(count == 0) + { + return dest_operand; + } + + if(count < 8) + { + *last_result = dest_operand << 24 >> count + 24; + // of is zero + *flags = (*flags & ~1 & ~FLAG_OVERFLOW) | (dest_operand >> (count - 1) & 1); + } + else + { + *last_result = dest_operand << 24 >> 31; + *flags = (*flags & ~1 & ~FLAG_OVERFLOW) | (*last_result & 1); + } + + *last_op_size = OPSIZE_8; + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; + + return *last_result; +} + +int32_t sar16(int32_t dest_operand, int32_t count) +{ + if(count == 0) + { + return dest_operand; + } + + if(count < 16) + { + *last_result = dest_operand << 16 >> count + 16; + *flags = (*flags & ~1 & ~FLAG_OVERFLOW) | (dest_operand >> (count - 1) & 1); + } + else + { + *last_result = dest_operand << 16 >> 31; + *flags = (*flags & ~1 & ~FLAG_OVERFLOW) | (*last_result & 1); + } + + *last_op_size = OPSIZE_16; + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; + + return *last_result; +} + +int32_t sar32(int32_t dest_operand, int32_t count) +{ + if(count == 0) + { + return dest_operand; + } + + *last_result = dest_operand >> count; + + *last_op_size = OPSIZE_32; + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; + *flags = (*flags & ~1 & ~FLAG_OVERFLOW) | (((uint32_t) dest_operand) >> (count - 1) & 1); + + return *last_result; +} + +int32_t shrd16(int32_t dest_operand, int32_t source_operand, int32_t count) +{ + if(count == 0) + { + return dest_operand; + } + + if(count <= 16) + { + *last_result = dest_operand >> count | source_operand << (16 - count); + *flags = (*flags & ~1) | (dest_operand >> (count - 1) & 1); + } + else + { + *last_result = dest_operand << (32 - count) | source_operand >> (count - 16); + *flags = (*flags & ~1) | (source_operand >> (count - 17) & 1); + } + + *last_op_size = OPSIZE_16; + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; + *flags = (*flags & ~FLAG_OVERFLOW) | ((*last_result ^ dest_operand) >> 4 & FLAG_OVERFLOW); + + return *last_result; +} + +int32_t shrd32(int32_t dest_operand, int32_t source_operand, int32_t count) +{ + if(count == 0) + { + return dest_operand; + } + + *last_result = ((uint32_t) dest_operand) >> count | source_operand << (32 - count); + + *last_op_size = OPSIZE_32; + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; + *flags = (*flags & ~1) | (((uint32_t) dest_operand) >> (count - 1) & 1); + *flags = (*flags & ~FLAG_OVERFLOW) | ((*last_result ^ dest_operand) >> 20 & FLAG_OVERFLOW); + + return *last_result; +} + +int32_t shld16(int32_t dest_operand, int32_t source_operand, int32_t count) +{ + if(count == 0) + { + return dest_operand; + } + + if(count <= 16) + { + *last_result = dest_operand << count | ((uint32_t) source_operand) >> (16 - count); + *flags = (*flags & ~1) | (((uint32_t) dest_operand) >> (16 - count) & 1); + } + else + { + *last_result = dest_operand >> (32 - count) | source_operand << (count - 16); + *flags = (*flags & ~1) | (((uint32_t) source_operand) >> (32 - count) & 1); + } + + *last_op_size = OPSIZE_16; + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; + *flags = (*flags & ~FLAG_OVERFLOW) | ((*flags & 1) ^ (*last_result >> 15 & 1)) << 11; + + return *last_result; +} + +int32_t shld32(int32_t dest_operand, int32_t source_operand, int32_t count) +{ + if(count == 0) + { + return dest_operand; + } + + *last_result = dest_operand << count | ((uint32_t) source_operand) >> (32 - count); + + *last_op_size = OPSIZE_32; + *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; + *flags = (*flags & ~1) | (((uint32_t) dest_operand) >> (32 - count) & 1); + + if(count == 1) + { + *flags = (*flags & ~FLAG_OVERFLOW) | ((*flags & 1) ^ (*last_result >> 31 & 1)) << 11; + } + else + { + *flags &= ~FLAG_OVERFLOW; + } + + return *last_result; +} + From 6d8b0862311fb272317794a855abb5a068439e41 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Thu, 27 Jul 2017 16:46:24 +0530 Subject: [PATCH 0078/2137] port bt*,bs*,popcnt,saturate* --- src/browser/starter.js | 16 +- src/cpu.js | 21 +++ src/native/arith.c | 282 +++++++++++++++++++++++++++++++++++ src/native/instructions_0f.c | 10 +- 4 files changed, 310 insertions(+), 19 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index a667cb0e..02e92b54 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -156,6 +156,8 @@ function V86Starter(options) "_fpu_op_DF_mem": function() { return cpu.fpu.op_DF_mem.apply(cpu.fpu, arguments); }, "_fwait": function() { return cpu.fpu.fwait(); }, + "_int_log2": function(val) { return v86util.int_log2(val); }, + "_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); }, @@ -173,20 +175,6 @@ function V86Starter(options) "_getiopl": function() { return cpu.getiopl.apply(cpu, arguments); }, "_vm86_mode": function() { return cpu.vm86_mode.apply(cpu, arguments); }, - "_bt_reg": function() { return cpu.bt_reg.apply(cpu, arguments); }, - "_bt_mem": function() { return cpu.bt_mem.apply(cpu, arguments); }, - "_btr_reg": function() { return cpu.btr_reg.apply(cpu, arguments); }, - "_btr_mem": function() { return cpu.btr_mem.apply(cpu, arguments); }, - "_btc_reg": function() { return cpu.btc_reg.apply(cpu, arguments); }, - "_btc_mem": function() { return cpu.btc_mem.apply(cpu, arguments); }, - "_bts_reg": function() { return cpu.bts_reg.apply(cpu, arguments); }, - "_bts_mem": function() { return cpu.bts_mem.apply(cpu, arguments); }, - - "_bsf16": function() { return cpu.bsf16.apply(cpu, arguments); }, - "_bsf32": function() { return cpu.bsf32.apply(cpu, arguments); }, - "_bsr16": function() { return cpu.bsr16.apply(cpu, arguments); }, - "_bsr32": function() { return cpu.bsr32.apply(cpu, arguments); }, - "_popcnt": function() { return cpu.popcnt.apply(cpu, arguments); }, "_bswap": function() { return cpu.bswap.apply(cpu, arguments); }, "_lar": function() { return cpu.lar.apply(cpu, arguments); }, diff --git a/src/cpu.js b/src/cpu.js index 345d8384..ff775be4 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -293,6 +293,27 @@ CPU.prototype.wasm_patch = function(wm) this.shld16 = this.wm.funcs['_shld16']; this.shld32 = this.wm.funcs['_shld32']; + this.bt_reg = this.wm.funcs['_bt_reg']; + this.btc_reg = this.wm.funcs['_btc_reg']; + this.bts_reg = this.wm.funcs['_bts_reg']; + this.btr_reg = this.wm.funcs['_btr_reg']; + this.bt_mem = this.wm.funcs['_bt_mem']; + this.btc_mem = this.wm.funcs['_btc_mem']; + this.btr_mem = this.wm.funcs['_btr_mem']; + this.bts_mem = this.wm.funcs['_bts_mem']; + this.bsf16 = this.wm.funcs['_bsf16']; + this.bsf32 = this.wm.funcs['_bsf32']; + this.bsr16 = this.wm.funcs['_bsr16']; + this.bsr32 = this.wm.funcs['_bsr32']; + this.popcnt = this.wm.funcs['_popcnt']; + this.saturate_sw_to_ub = this.wm.funcs['_saturate_sw_to_ub']; + this.saturate_sw_to_sb = this.wm.funcs['_saturate_sw_to_sb']; + this.saturate_sd_to_sw = this.wm.funcs['_saturate_sd_to_sw']; + this.saturate_sd_to_sb = this.wm.funcs['_saturate_sd_to_sb']; + this.saturate_sd_to_ub = this.wm.funcs['_saturate_sd_to_ub']; + this.saturate_ud_to_ub = this.wm.funcs['_saturate_ud_to_ub']; + this.saturate_uw = this.wm.funcs['_saturate_uw']; + this.do_many_cycles_unsafe = this.wm.funcs['_do_many_cycles_unsafe']; this.read_imm8 = this.wm.funcs['_read_imm8']; diff --git a/src/native/arith.c b/src/native/arith.c index 91321c0f..55ff91f0 100644 --- a/src/native/arith.c +++ b/src/native/arith.c @@ -1088,3 +1088,285 @@ int32_t shld32(int32_t dest_operand, int32_t source_operand, int32_t count) return *last_result; } +int32_t int_log2(int32_t); + +void bt_reg(int32_t bit_base, int32_t bit_offset) +{ + *flags = (*flags & ~1) | (bit_base >> bit_offset & 1); + *flags_changed &= ~1; +} + +int32_t btc_reg(int32_t bit_base, int32_t bit_offset) +{ + *flags = (*flags & ~1) | (bit_base >> bit_offset & 1); + *flags_changed &= ~1; + + return bit_base ^ 1 << bit_offset; +} + +int32_t bts_reg(int32_t bit_base, int32_t bit_offset) +{ + *flags = (*flags & ~1) | (bit_base >> bit_offset & 1); + *flags_changed &= ~1; + + return bit_base | 1 << bit_offset; +} + +int32_t btr_reg(int32_t bit_base, int32_t bit_offset) +{ + *flags = (*flags & ~1) | (bit_base >> bit_offset & 1); + *flags_changed &= ~1; + + return bit_base & ~(1 << 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); + bit_offset &= 7; + + *flags = (*flags & ~1) | (bit_base >> bit_offset & 1); + *flags_changed &= ~1; +} + +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 bit_base = read8(phys_addr); + + bit_offset &= 7; + + *flags = (*flags & ~1) | (bit_base >> bit_offset & 1); + *flags_changed &= ~1; + + write8(phys_addr, bit_base ^ 1 << 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 bit_base = read8(phys_addr); + + bit_offset &= 7; + + *flags = (*flags & ~1) | (bit_base >> bit_offset & 1); + *flags_changed &= ~1; + + write8(phys_addr, bit_base & ~(1 << 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 bit_base = read8(phys_addr); + + bit_offset &= 7; + + *flags = (*flags & ~1) | (bit_base >> bit_offset & 1); + *flags_changed &= ~1; + + write8(phys_addr, bit_base | 1 << bit_offset); +} + +int32_t bsf16(int32_t old, int32_t bit_base) +{ + *flags_changed = FLAGS_ALL & ~FLAG_ZERO; + *last_op_size = OPSIZE_16; + + if(bit_base == 0) + { + *flags |= FLAG_ZERO; + *last_result = bit_base; + + // not defined in the docs, but value doesn't change on my intel machine + return old; + } + else + { + *flags &= ~FLAG_ZERO; + + // http://jsperf.com/lowest-bit-index + return *last_result = int_log2(-bit_base & bit_base); + } +} + +int32_t bsf32(int32_t old, int32_t bit_base) +{ + *flags_changed = FLAGS_ALL & ~FLAG_ZERO; + *last_op_size = OPSIZE_32; + + if(bit_base == 0) + { + *flags |= FLAG_ZERO; + *last_result = bit_base; + + return old; + } + else + { + *flags &= ~FLAG_ZERO; + + return *last_result = int_log2(((uint32_t) (-bit_base & bit_base)) >> 0); + } +} + +int32_t bsr16(int32_t old, int32_t bit_base) +{ + *flags_changed = FLAGS_ALL & ~FLAG_ZERO; + *last_op_size = OPSIZE_16; + + if(bit_base == 0) + { + *flags |= FLAG_ZERO; + *last_result = bit_base; + + return old; + } + else + { + *flags &= ~FLAG_ZERO; + + return *last_result = int_log2(bit_base); + } +} + +int32_t bsr32(int32_t old, int32_t bit_base) +{ + *flags_changed = FLAGS_ALL & ~FLAG_ZERO; + *last_op_size = OPSIZE_32; + + if(bit_base == 0) + { + *flags |= FLAG_ZERO; + *last_result = bit_base; + + return old; + } + else + { + *flags &= ~FLAG_ZERO; + return *last_result = int_log2(((uint32_t) bit_base) >> 0); + } +} + +int32_t popcnt(int32_t v) +{ + *flags_changed = 0; + *flags &= ~FLAGS_ALL; + + if(v) + { + // http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel + v = v - ((v >> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >> 2) & 0x33333333); + return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; + } + else + { + *flags |= FLAG_ZERO; + return 0; + } +} + +uint32_t saturate_sw_to_ub(uint32_t v) +{ + dbg_assert((v & 0xFFFF0000) == 0); + + uint32_t ret = v >> 0; + if (ret >= 0x8000) { + ret = 0; + } + else if (ret > 0xFF) { + ret = 0xFF; + } + + dbg_assert((ret & 0xFFFFFF00) == 0); + return ret; +} + +int32_t saturate_sw_to_sb(int32_t v) +{ + dbg_assert((v & 0xFFFF0000) == 0); + + int32_t ret = v; + + if (ret > 0xFF80) { + ret = ret & 0xFF; + } + else if (ret > 0x7FFF) { + ret = 0x80; + } + else if (ret > 0x7F) { + ret = 0x7F; + } + + dbg_assert((ret & 0xFFFFFF00) == 0); + return ret; +} + +uint32_t saturate_sd_to_sw(uint32_t v) +{ + uint32_t ret = v >> 0; + + if (ret > 0xFFFF8000) { + ret = ret & 0xFFFF; + } + else if (ret > 0x7FFFFFFF) { + ret = 0x8000; + } + else if (ret > 0x7FFF) { + ret = 0x7FFF; + } + + dbg_assert((ret & 0xFFFF0000) == 0); + return ret; +} + +uint32_t saturate_sd_to_sb(uint32_t v) +{ + uint32_t ret = v >> 0; + + if (ret > 0xFFFFFF80) { + ret = ret & 0xFF; + } + else if (ret > 0x7FFFFFFF) { + ret = 0x80; + } + else if (ret > 0x7F) { + ret = 0x7F; + } + + dbg_assert((ret & 0xFFFFFF00) == 0); + return ret; +} + +int32_t saturate_sd_to_ub(int32_t v) +{ + int32_t ret = v | 0; + + if (ret < 0) { + ret = 0; + } + + dbg_assert((ret & 0xFFFFFF00) == 0); + return ret; +} + +uint32_t saturate_ud_to_ub(uint32_t v) +{ + uint32_t ret = v >> 0; + + if (ret > 0xFF) { + ret = 0xFF; + } + + dbg_assert((ret & 0xFFFFFF00) == 0); + return ret; +} + +int32_t saturate_uw(int32_t v) +{ + dbg_assert(v >= 0); + return v > 0xFFFF ? 0xFFFF : v; +} + diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index fbdcdda3..48b13cee 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -14,13 +14,13 @@ void jmpcc32(bool); void setcc(bool); void cpuid(); -int32_t bt_mem(int32_t, int32_t); -int32_t bt_reg(int32_t, int32_t); -int32_t bts_mem(int32_t, int32_t); +void bt_mem(int32_t, int32_t); +void bt_reg(int32_t, int32_t); +void bts_mem(int32_t, int32_t); int32_t bts_reg(int32_t, int32_t); -int32_t btc_mem(int32_t, int32_t); +void btc_mem(int32_t, int32_t); int32_t btc_reg(int32_t, int32_t); -int32_t btr_mem(int32_t, int32_t); +void btr_mem(int32_t, int32_t); int32_t btr_reg(int32_t, int32_t); int32_t bsf16(int32_t, int32_t); int32_t bsf32(int32_t, int32_t); From 30dae42b520fc3dd709fded3b9c1e2a06eeb7fe3 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Thu, 27 Jul 2017 16:46:24 +0530 Subject: [PATCH 0079/2137] remove obsolete stuff --- src/arith.js | 14 -------------- src/native/arith.c | 8 -------- 2 files changed, 22 deletions(-) diff --git a/src/arith.js b/src/arith.js index 5334af8a..2a6372f9 100644 --- a/src/arith.js +++ b/src/arith.js @@ -289,14 +289,6 @@ CPU.prototype.do_mul32 = function(a, b) return this.mul32_result; }; -//XXX: do_mul32 returns a typedarray object which we can't do from a wasm -//function, so we rewrite it here differently from other ports. Would -//change this when callers of do_mul32 are rewritten in wasm. -CPU.prototype.do_mul32 = function(a, b) { - this.wm.funcs['_do_mul32'](a, b); - return this.mul32_result; -}; - CPU.prototype.do_imul32 = function(a, b) { var is_neg = false; @@ -316,12 +308,6 @@ CPU.prototype.do_imul32 = function(a, b) return result; } -//XXX: same issue as do_mul32. rewrite after callers are ported to wasm -CPU.prototype.do_imul32 = function(a, b) { - this.wm.funcs['_do_imul32'](a, b); - return this.mul32_result; -}; - CPU.prototype.mul32 = function(source_operand) { var dest_operand = this.reg32s[reg_eax]; diff --git a/src/native/arith.c b/src/native/arith.c index 55ff91f0..8a463635 100644 --- a/src/native/arith.c +++ b/src/native/arith.c @@ -306,10 +306,6 @@ void mul32(int32_t source_operand) void imul32(int32_t source_operand) { - //XXX: this assert fails since the limits here are out of bounds for int32 - //but the assert is present in the original JS source :| - //assert(source_operand < 0x80000000 && source_operand >= -0x80000000); - int32_t dest_operand = reg32s[EAX]; do_imul32(dest_operand, source_operand); @@ -333,10 +329,6 @@ void imul32(int32_t source_operand) int32_t imul_reg32(int32_t operand1, int32_t operand2) { - //XXX: assert limits OOB for int32 - //dbg_assert(operand1 < 0x80000000 && operand1 >= -0x80000000); - //dbg_assert(operand2 < 0x80000000 && operand2 >= -0x80000000); - do_imul32(operand1, operand2); *last_result = mul32_result[0]; From 18b8ebf4baa696eebd70565687da9e06405cc7df Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Thu, 27 Jul 2017 16:46:24 +0530 Subject: [PATCH 0080/2137] port div32 --- src/browser/starter.js | 1 - src/cpu.js | 1 + src/native/arith.c | 25 +++++++++++++++++++++++++ src/native/instructions.c | 2 +- 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 02e92b54..9ae35489 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -195,7 +195,6 @@ function V86Starter(options) "_load_tr": function() { return cpu.load_tr.apply(cpu, arguments); }, "_idiv16": function() { return cpu.idiv16.apply(cpu, arguments); }, - "_div32": function() { return cpu.div32.apply(cpu, arguments); }, "_idiv32": function() { return cpu.idiv32.apply(cpu, arguments); }, "_insb": function() { return cpu.insb.apply(cpu, arguments); }, "_insw": function() { return cpu.insw.apply(cpu, arguments); }, diff --git a/src/cpu.js b/src/cpu.js index ff775be4..75b7535a 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -278,6 +278,7 @@ CPU.prototype.wasm_patch = function(wm) this.raise_exception_with_code = this.wm.funcs['_raise_exception_with_code']; this.trigger_de = this.wm.funcs['_trigger_de']; this.trigger_gp = this.wm.funcs['_trigger_gp']; + this.div32 = this.wm.funcs['_div32']; this.shl8 = this.wm.funcs['_shl8']; this.shl16 = this.wm.funcs['_shl16']; diff --git a/src/native/arith.c b/src/native/arith.c index 8a463635..895458c9 100644 --- a/src/native/arith.c +++ b/src/native/arith.c @@ -815,6 +815,31 @@ void div16(uint32_t source_operand) } } +void div32(uint32_t source_operand) +{ + if(source_operand == 0) + { + trigger_de(); + return; + } + + uint32_t target_low = reg32s[EAX]; + uint32_t target_high = reg32s[EDX]; + + uint64_t target_operand = (((uint64_t) target_high) << 32) | ((uint64_t) target_low); + uint64_t result = target_operand / source_operand; + if(result > UINT32_MAX) + { + trigger_de(); + return; + } + + int32_t mod = target_operand % source_operand; + + reg32s[EAX] = result; + reg32s[EDX] = mod; +} + int32_t shl8(int32_t dest_operand, int32_t count) { if(count == 0) diff --git a/src/native/instructions.c b/src/native/instructions.c index e4e2683d..67f45012 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -183,7 +183,7 @@ int32_t rcr32(int32_t, int32_t); int32_t rcl32(int32_t, int32_t); int32_t idiv16(int32_t); -int32_t div32(int32_t); +void div32(uint32_t); int32_t idiv32(int32_t); From f9d99ac4deea71fda0eedfd45085955e68de2303 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Thu, 27 Jul 2017 16:46:24 +0530 Subject: [PATCH 0081/2137] port idiv32 --- src/browser/starter.js | 1 - src/cpu.js | 1 + src/native/arith.c | 32 ++++++++++++++++++++++++++++++++ src/native/instructions.c | 2 +- 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 9ae35489..b0fb0198 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -195,7 +195,6 @@ function V86Starter(options) "_load_tr": function() { return cpu.load_tr.apply(cpu, arguments); }, "_idiv16": function() { return cpu.idiv16.apply(cpu, arguments); }, - "_idiv32": function() { return cpu.idiv32.apply(cpu, arguments); }, "_insb": function() { return cpu.insb.apply(cpu, arguments); }, "_insw": function() { return cpu.insw.apply(cpu, arguments); }, "_insd": function() { return cpu.insd.apply(cpu, arguments); }, diff --git a/src/cpu.js b/src/cpu.js index 75b7535a..f189a8d3 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -279,6 +279,7 @@ CPU.prototype.wasm_patch = function(wm) this.trigger_de = this.wm.funcs['_trigger_de']; this.trigger_gp = this.wm.funcs['_trigger_gp']; this.div32 = this.wm.funcs['_div32']; + this.idiv32 = this.wm.funcs['_idiv32']; this.shl8 = this.wm.funcs['_shl8']; this.shl16 = this.wm.funcs['_shl16']; diff --git a/src/native/arith.c b/src/native/arith.c index 895458c9..16180818 100644 --- a/src/native/arith.c +++ b/src/native/arith.c @@ -840,6 +840,38 @@ void div32(uint32_t source_operand) reg32s[EDX] = mod; } +void idiv32(int32_t source_operand) +{ + if(source_operand == 0) + { + trigger_de(); + return; + } + + uint32_t target_low = reg32s[EAX]; + uint32_t target_high = reg32s[EDX]; + + int64_t target_operand = (((uint64_t) target_high) << 32) | ((uint64_t) target_low); + + if(source_operand == -1 && target_operand == INT64_MIN) + { + trigger_de(); + return; + } + + int64_t result = target_operand / source_operand; + if(result < INT32_MIN || result > INT32_MAX) + { + trigger_de(); + return; + } + + int32_t mod = target_operand % source_operand; + + reg32s[EAX] = result; + reg32s[EDX] = mod; +} + int32_t shl8(int32_t dest_operand, int32_t count) { if(count == 0) diff --git a/src/native/instructions.c b/src/native/instructions.c index 67f45012..c55d2172 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -184,7 +184,7 @@ int32_t rcl32(int32_t, int32_t); int32_t idiv16(int32_t); void div32(uint32_t); -int32_t idiv32(int32_t); +void idiv32(int32_t); void insb(void); From 8cc574af222216fbf8e24a045a0d0fbe1b0ca46f Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Fri, 28 Jul 2017 23:19:11 +0530 Subject: [PATCH 0082/2137] port idiv16 --- src/browser/starter.js | 1 - src/cpu.js | 1 + src/native/arith.c | 22 ++++++++++++++++++++++ src/native/instructions.c | 2 +- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index b0fb0198..475482bb 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -194,7 +194,6 @@ function V86Starter(options) "_load_ldt": function() { return cpu.load_ldt.apply(cpu, arguments); }, "_load_tr": function() { return cpu.load_tr.apply(cpu, arguments); }, - "_idiv16": function() { return cpu.idiv16.apply(cpu, arguments); }, "_insb": function() { return cpu.insb.apply(cpu, arguments); }, "_insw": function() { return cpu.insw.apply(cpu, arguments); }, "_insd": function() { return cpu.insd.apply(cpu, arguments); }, diff --git a/src/cpu.js b/src/cpu.js index f189a8d3..6081b1d0 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -280,6 +280,7 @@ CPU.prototype.wasm_patch = function(wm) this.trigger_gp = this.wm.funcs['_trigger_gp']; this.div32 = this.wm.funcs['_div32']; this.idiv32 = this.wm.funcs['_idiv32']; + this.idiv16 = this.wm.funcs['_idiv16']; this.shl8 = this.wm.funcs['_shl8']; this.shl16 = this.wm.funcs['_shl16']; diff --git a/src/native/arith.c b/src/native/arith.c index 16180818..1b066740 100644 --- a/src/native/arith.c +++ b/src/native/arith.c @@ -815,6 +815,28 @@ void div16(uint32_t source_operand) } } +void idiv16(int32_t source_operand) +{ + if(source_operand == 0) + { + trigger_de(); + return; + } + + int32_t target_operand = reg16[AX] | (reg16[DX] << 16); + int32_t result = target_operand / source_operand; + + if(result >= 0x8000 || result <= -0x8001) + { + trigger_de(); + } + else + { + reg16[AX] = result; + reg16[DX] = target_operand % source_operand; + } +} + void div32(uint32_t source_operand) { if(source_operand == 0) diff --git a/src/native/instructions.c b/src/native/instructions.c index c55d2172..7a7be636 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -182,7 +182,7 @@ int32_t rol32(int32_t, int32_t); int32_t rcr32(int32_t, int32_t); int32_t rcl32(int32_t, int32_t); -int32_t idiv16(int32_t); +void idiv16(int32_t); void div32(uint32_t); void idiv32(int32_t); From 1ba669fa61ef5dc1e3c4eaae73d5f685a20c4db0 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sat, 29 Jul 2017 22:58:23 +0530 Subject: [PATCH 0083/2137] enable tests for mov* string instructions --- tests/nasm/create_tests.js | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/tests/nasm/create_tests.js b/tests/nasm/create_tests.js index 6d779e79..bb913d2a 100755 --- a/tests/nasm/create_tests.js +++ b/tests/nasm/create_tests.js @@ -136,10 +136,10 @@ const encodings = [ { opcode: 0xA2, immaddr: 1, }, { opcode: 0xA3, os: 1, immaddr: 1, }, - { opcode: 0xA4, skip: 1, }, - { opcode: 0xA5, os: 1, skip: 1, }, - { opcode: 0xA6, skip: 1, }, - { opcode: 0xA7, os: 1, skip: 1, }, + { opcode: 0xA4, }, + { opcode: 0xA5, os: 1, }, + { opcode: 0xA6, }, + { opcode: 0xA7, os: 1, }, { opcode: 0xA8, imm: 1, }, { opcode: 0xA9, os: 1, imm: 1, }, @@ -994,6 +994,11 @@ function random_int32() return Math.random() * 0x100000000 | 0; } +function is_string_instruction(op) +{ + return (op.opcode >= 0x6C && op.opcode <= 0x6F) || (op.opcode >= 0xA4 && op.opcode <= 0xA7); +} + function create_nasm(op, config) { if(op.prefix || op.skip) @@ -1090,6 +1095,14 @@ function create_nasm(op, config) } } + if(is_string_instruction(op)) + { + codes.push("mov ecx, 3"); + codes.push("mov edi, (120000h-16)"); + codes.push("mov esi, (120000h-20)"); + codes.push(["", "db 0f2h", "db 0f3h"]); + } + if(size === 16) { codes.push("db 66h ; 16 bit"); From 520f644eea2161cb2e5dd7d0f2b878566357c0e4 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sun, 30 Jul 2017 12:45:33 +0530 Subject: [PATCH 0084/2137] start porting string instructions --- src/native/all.c | 1 + src/native/string.c | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 src/native/string.c diff --git a/src/native/all.c b/src/native/all.c index b208ed84..6f932700 100644 --- a/src/native/all.c +++ b/src/native/all.c @@ -17,3 +17,4 @@ extern void throw_cpu_exception(void); #include "fpu.c" #include "instructions.c" #include "instructions_0f.c" +#include "string.c" diff --git a/src/native/string.c b/src/native/string.c new file mode 100644 index 00000000..3dc570ec --- /dev/null +++ b/src/native/string.c @@ -0,0 +1,25 @@ +#define MAX_COUNT_PER_CYCLE 0x1000 +#define MIN(x, y) (x < y ? x : y) + +int32_t string_get_cycle_count(int32_t size, int32_t address) +{ + dbg_assert(size && size <= 4 && size >= -4); + + if(size < 0) + { + return (address & 0xFFF) >> (-size >> 1); + } + else + { + return (~address & 0xFFF) >> size; + } +} + +int32_t string_get_cycle_count2(int32_t size, int32_t addr1, int32_t addr2) +{ + int32_t c1 = string_get_cycle_count(size, addr1); + int32_t c2 = string_get_cycle_count(size, addr2); + + return MIN(c1, c2); +} + From b3c16638fc1a1325eb5beac6e1a4464512eab7db Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sun, 30 Jul 2017 18:02:17 +0530 Subject: [PATCH 0085/2137] port {get,add}_reg_asize and set_ecx_asize --- src/cpu.js | 3 +++ src/native/cpu.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/cpu.js b/src/cpu.js index 6081b1d0..62f0ca09 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -340,6 +340,9 @@ CPU.prototype.wasm_patch = function(wm) this.get_stack_reg = this.wm.funcs['_get_stack_reg']; this.setcc = this.wm.funcs['_setcc']; this.set_stack_reg = this.wm.funcs['_set_stack_reg']; + this.get_reg_asize = this.wm.funcs['_get_reg_asize']; + this.set_ecx_asize = this.wm.funcs['_set_ecx_asize']; + this.add_reg_asize = this.wm.funcs['_add_reg_asize']; }; CPU.prototype.get_state = function() diff --git a/src/native/cpu.c b/src/native/cpu.c index 9b3114b5..de921fd5 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -763,3 +763,43 @@ void set_stack_reg(int32_t value) } } +int32_t get_reg_asize(int32_t reg) +{ + dbg_assert(reg == ECX || reg == ESI || reg == EDI); + int32_t r = reg32s[reg]; + + if(is_asize_32()) + { + return r; + } + else + { + return r & 0xFFFF; + } +} + +void set_ecx_asize(int32_t value) +{ + if(is_asize_32()) + { + reg32s[ECX] = value; + } + else + { + reg16[CX] = value; + } +} + +void add_reg_asize(int32_t reg, int32_t value) +{ + dbg_assert(reg == ECX || reg == ESI || reg == EDI); + if(is_asize_32()) + { + reg32s[reg] += value; + } + else + { + reg16[reg << 1] += value; + } +} + From f64fc5103620c7a512eb22f9c7de6fa98db47637 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sun, 30 Jul 2017 18:04:09 +0530 Subject: [PATCH 0086/2137] port movsb --- src/browser/starter.js | 1 - src/cpu.js | 1 + src/native/string.c | 61 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 475482bb..abb3e16b 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -200,7 +200,6 @@ function V86Starter(options) "_outsb": function() { return cpu.outsb.apply(cpu, arguments); }, "_outsw": function() { return cpu.outsw.apply(cpu, arguments); }, "_outsd": function() { return cpu.outsd.apply(cpu, arguments); }, - "_movsb": function() { return cpu.movsb.apply(cpu, arguments); }, "_movsw": function() { return cpu.movsw.apply(cpu, arguments); }, "_movsd": function() { return cpu.movsd.apply(cpu, arguments); }, "_cmpsb": function() { return cpu.cmpsb.apply(cpu, arguments); }, diff --git a/src/cpu.js b/src/cpu.js index 62f0ca09..558ec7fb 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -343,6 +343,7 @@ CPU.prototype.wasm_patch = function(wm) this.get_reg_asize = this.wm.funcs['_get_reg_asize']; this.set_ecx_asize = this.wm.funcs['_set_ecx_asize']; this.add_reg_asize = this.wm.funcs['_add_reg_asize']; + this.movsb = this.wm.funcs['_movsb']; }; CPU.prototype.get_state = function() diff --git a/src/native/string.c b/src/native/string.c index 3dc570ec..be3fd318 100644 --- a/src/native/string.c +++ b/src/native/string.c @@ -23,3 +23,64 @@ int32_t string_get_cycle_count2(int32_t size, int32_t addr1, int32_t addr2) return MIN(c1, c2); } +void movsb_rep() +{ + int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); + 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; + if(count == 0) return; + int32_t cont = false; + int32_t start_count = count; + int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + int32_t phys_src = translate_address_read(src); + int32_t phys_dest = translate_address_write(dest); + if(*paging) + { + cycle_counter = string_get_cycle_count2(size, src, dest); + } + do + { + write8(phys_dest, read8(phys_src)); + phys_dest += size; + phys_src += size; + cont = --count != 0; + } + while(cont && cycle_counter--); + int32_t diff = size * (start_count - count) | 0; + add_reg_asize(EDI, diff); + add_reg_asize(ESI, diff); + set_ecx_asize(count); + *timestamp_counter += start_count - count; + if(cont) + { + *instruction_pointer = *previous_ip; + } + diverged(); +} + +void movsb_no_rep() +{ + int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); + int32_t dest = get_seg(ES) + get_reg_asize(EDI); + int32_t size = *flags & FLAG_DIRECTION ? -1 : 1; + + safe_write8(dest, safe_read8(src)); + add_reg_asize(EDI, size); + add_reg_asize(ESI, size); + diverged(); +} + +void movsb() +{ + if(*prefixes & PREFIX_MASK_REP) + { + movsb_rep(); + } + else + { + movsb_no_rep(); + } +} + From f6c2e4ca971201e2a4f02cde54f8fa5c76d8499b Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sun, 30 Jul 2017 18:13:50 +0530 Subject: [PATCH 0087/2137] port dependencies of movsw --- src/cpu.js | 2 ++ src/native/cpu.c | 5 +++++ src/native/memory.c | 15 +++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/src/cpu.js b/src/cpu.js index 558ec7fb..236c6774 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -331,6 +331,7 @@ CPU.prototype.wasm_patch = function(wm) this.read32s = this.wm.funcs['_read32s']; this.write8 = this.wm.funcs['_write8']; this.write16 = this.wm.funcs['_write16']; + this.write_aligned16 = this.wm.funcs['_write_aligned16']; this.write32 = this.wm.funcs['_write32']; this.push16 = this.wm.funcs['_push16']; this.push32 = this.wm.funcs['_push32']; @@ -343,6 +344,7 @@ CPU.prototype.wasm_patch = function(wm) this.get_reg_asize = this.wm.funcs['_get_reg_asize']; this.set_ecx_asize = this.wm.funcs['_set_ecx_asize']; this.add_reg_asize = this.wm.funcs['_add_reg_asize']; + this.decr_ecx_asize = this.wm.funcs['_decr_ecx_asize']; this.movsb = this.wm.funcs['_movsb']; }; diff --git a/src/native/cpu.c b/src/native/cpu.c index de921fd5..9d6595c5 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -803,3 +803,8 @@ void add_reg_asize(int32_t reg, int32_t value) } } +int32_t decr_ecx_asize() +{ + return is_asize_32() ? --reg32s[ECX] : --reg16[CX]; +} + diff --git a/src/native/memory.c b/src/native/memory.c index 1f049f08..ba97101c 100644 --- a/src/native/memory.c +++ b/src/native/memory.c @@ -97,6 +97,21 @@ void write16(uint32_t addr, uint16_t value) } } +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)) + { + mmap_write16(addr << 1, value); + } + else + { + *(uint16_t*)(mem16 + addr) = value; + } +} + void write32(uint32_t addr, int32_t value) { if(USE_A20 && !*a20_enabled) addr &= A20_MASK; From a9edccebc74e3214673c01014d4733ab5c75dc44 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sun, 30 Jul 2017 18:14:16 +0530 Subject: [PATCH 0088/2137] port movsw --- src/browser/starter.js | 1 - src/cpu.js | 1 + src/native/string.c | 78 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index abb3e16b..e7f19b34 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -200,7 +200,6 @@ function V86Starter(options) "_outsb": function() { return cpu.outsb.apply(cpu, arguments); }, "_outsw": function() { return cpu.outsw.apply(cpu, arguments); }, "_outsd": function() { return cpu.outsd.apply(cpu, arguments); }, - "_movsw": function() { return cpu.movsw.apply(cpu, arguments); }, "_movsd": function() { return cpu.movsd.apply(cpu, arguments); }, "_cmpsb": function() { return cpu.cmpsb.apply(cpu, arguments); }, "_cmpsw": function() { return cpu.cmpsw.apply(cpu, arguments); }, diff --git a/src/cpu.js b/src/cpu.js index 236c6774..99f66763 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -346,6 +346,7 @@ CPU.prototype.wasm_patch = function(wm) this.add_reg_asize = this.wm.funcs['_add_reg_asize']; this.decr_ecx_asize = this.wm.funcs['_decr_ecx_asize']; this.movsb = this.wm.funcs['_movsb']; + this.movsw = this.wm.funcs['_movsw']; }; CPU.prototype.get_state = function() diff --git a/src/native/string.c b/src/native/string.c index be3fd318..0a1c0e9c 100644 --- a/src/native/string.c +++ b/src/native/string.c @@ -84,3 +84,81 @@ void movsb() } } +void movsw_rep() +{ + int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); + 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; + if(count == 0) return; + int32_t cont = false; + int32_t start_count = count; + int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + if(!(dest & 1) && !(src & 1)) + { + int32_t single_size = size < 0 ? -1 : 1; + int32_t phys_src = translate_address_read(src) >> 1; + int32_t phys_dest = translate_address_write(dest) >> 1; + if(*paging) + { + cycle_counter = string_get_cycle_count2(size, src, dest); + } + do + { + write_aligned16(phys_dest, read_aligned16(phys_src)); + phys_dest += single_size; + phys_src += single_size; + cont = --count != 0; + } + while(cont && cycle_counter--); + int32_t diff = size * (start_count - count) | 0; + add_reg_asize(EDI, diff); + add_reg_asize(ESI, diff); + set_ecx_asize(count); + *timestamp_counter += start_count - count; + } + else + { + do + { + safe_write16(dest, safe_read16(src)); + dest += size; + add_reg_asize(EDI, size); + src += size; + add_reg_asize(ESI, size); + cont = decr_ecx_asize() != 0; + } + while(cont && cycle_counter--); + } + if(cont) + { + *instruction_pointer = *previous_ip; + } + diverged(); +} + +void movsw_no_rep() +{ + int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); + int32_t dest = get_seg(ES) + get_reg_asize(EDI); + int32_t size = *flags & FLAG_DIRECTION ? -2 : 2; + + safe_write16(dest, safe_read16(src)); + add_reg_asize(EDI, size); + add_reg_asize(ESI, size); + diverged(); +} + +void movsw() +{ + if(*prefixes & PREFIX_MASK_REP) + { + movsw_rep(); + } + else + { + movsw_no_rep(); + } +} + From f6215a378e910a1e483505759e8c28bc402bea58 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sun, 30 Jul 2017 18:20:53 +0530 Subject: [PATCH 0089/2137] port dependencies of movsd --- src/cpu.js | 2 ++ src/native/global_pointers.h | 1 + src/native/memory.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/src/cpu.js b/src/cpu.js index 99f66763..974f610a 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -329,10 +329,12 @@ CPU.prototype.wasm_patch = function(wm) this.read16 = this.wm.funcs['_read16']; this.read_aligned16 = this.wm.funcs['_read_aligned16']; this.read32s = this.wm.funcs['_read32s']; + this.read_aligned32 = this.wm.funcs['_read_aligned32']; this.write8 = this.wm.funcs['_write8']; this.write16 = this.wm.funcs['_write16']; this.write_aligned16 = this.wm.funcs['_write_aligned16']; this.write32 = this.wm.funcs['_write32']; + this.write_aligned32 = this.wm.funcs['_write_aligned32']; this.push16 = this.wm.funcs['_push16']; this.push32 = this.wm.funcs['_push32']; this.pusha16 = this.wm.funcs['_pusha16']; diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index 9e424fe5..b61e8d01 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -80,5 +80,6 @@ int32_t* const tlb_data = (int32_t* const) (2048 + 0x100000 + 0x100000); // leng 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); #endif diff --git a/src/native/memory.c b/src/native/memory.c index ba97101c..353792ad 100644 --- a/src/native/memory.c +++ b/src/native/memory.c @@ -69,6 +69,20 @@ int32_t read32s(uint32_t addr) } } +int32_t read_aligned32(uint32_t addr) +{ + if(USE_A20 && !*a20_enabled) addr &= A20_MASK32; + + if(in_mapped_range(addr << 2)) + { + return mmap_read32(addr << 2); + } + else + { + return mem32s[addr]; + } +} + void write8(uint32_t addr, uint8_t value) { if(USE_A20 && !*a20_enabled) addr &= A20_MASK; @@ -125,3 +139,18 @@ void write32(uint32_t addr, int32_t value) *(int32_t*)(mem8 + addr) = value; } } + +void write_aligned32(int32_t addr, int32_t value) +{ + if(USE_A20 && !*a20_enabled) addr &= A20_MASK32; + + if(in_mapped_range(addr << 2)) + { + mmap_write32(addr << 2, value); + } + else + { + mem32s[addr] = value; + } +} + From 9a8c91e1a1b909e947af23c998f2ac15dbbf4a01 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sun, 30 Jul 2017 18:21:52 +0530 Subject: [PATCH 0090/2137] port movsd --- src/browser/starter.js | 1 - src/cpu.js | 1 + src/native/string.c | 78 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index e7f19b34..9ea36dbe 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -200,7 +200,6 @@ function V86Starter(options) "_outsb": function() { return cpu.outsb.apply(cpu, arguments); }, "_outsw": function() { return cpu.outsw.apply(cpu, arguments); }, "_outsd": function() { return cpu.outsd.apply(cpu, arguments); }, - "_movsd": function() { return cpu.movsd.apply(cpu, arguments); }, "_cmpsb": function() { return cpu.cmpsb.apply(cpu, arguments); }, "_cmpsw": function() { return cpu.cmpsw.apply(cpu, arguments); }, "_cmpsd": function() { return cpu.cmpsd.apply(cpu, arguments); }, diff --git a/src/cpu.js b/src/cpu.js index 974f610a..9fbb6cf3 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -349,6 +349,7 @@ CPU.prototype.wasm_patch = function(wm) this.decr_ecx_asize = this.wm.funcs['_decr_ecx_asize']; this.movsb = this.wm.funcs['_movsb']; this.movsw = this.wm.funcs['_movsw']; + this.movsd = this.wm.funcs['_movsd']; }; CPU.prototype.get_state = function() diff --git a/src/native/string.c b/src/native/string.c index 0a1c0e9c..a10363f6 100644 --- a/src/native/string.c +++ b/src/native/string.c @@ -162,3 +162,81 @@ void movsw() } } +void movsd_rep() +{ + int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); + 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; + if(count == 0) return; + int32_t cont = false; + int32_t start_count = count; + int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + if(!(dest & 3) && !(src & 3)) + { + int32_t single_size = size < 0 ? -1 : 1; + int32_t phys_src = translate_address_read(src) >> 2; + int32_t phys_dest = translate_address_write(dest) >> 2; + if(*paging) + { + cycle_counter = string_get_cycle_count2(size, src, dest); + } + do + { + write_aligned32(phys_dest, read_aligned32(phys_src)); + phys_dest += single_size; + phys_src += single_size; + cont = --count != 0; + } + while(cont && cycle_counter--); + int32_t diff = size * (start_count - count) | 0; + add_reg_asize(EDI, diff); + add_reg_asize(ESI, diff); + set_ecx_asize(count); + *timestamp_counter += start_count - count; + } + else + { + do + { + safe_write32(dest, safe_read32s(src)); + dest += size; + add_reg_asize(EDI, size); + src += size; + add_reg_asize(ESI, size); + cont = decr_ecx_asize() != 0; + } + while(cont && cycle_counter--); + } + if(cont) + { + *instruction_pointer = *previous_ip; + } + diverged(); +} + +void movsd_no_rep() +{ + int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); + int32_t dest = get_seg(ES) + get_reg_asize(EDI); + int32_t size = *flags & FLAG_DIRECTION ? -4 : 4; + + safe_write32(dest, safe_read32s(src)); + add_reg_asize(EDI, size); + add_reg_asize(ESI, size); + diverged(); +} + +void movsd() +{ + if(*prefixes & PREFIX_MASK_REP) + { + movsd_rep(); + } + else + { + movsd_no_rep(); + } +} + From c68e68a04f7d3b57a24bb624a941d5e8ccc99375 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sun, 30 Jul 2017 18:32:11 +0530 Subject: [PATCH 0091/2137] port cmpsb --- src/browser/starter.js | 1 - src/cpu.js | 1 + src/native/string.c | 70 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 9ea36dbe..5bd07a6d 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -200,7 +200,6 @@ function V86Starter(options) "_outsb": function() { return cpu.outsb.apply(cpu, arguments); }, "_outsw": function() { return cpu.outsw.apply(cpu, arguments); }, "_outsd": function() { return cpu.outsd.apply(cpu, arguments); }, - "_cmpsb": function() { return cpu.cmpsb.apply(cpu, arguments); }, "_cmpsw": function() { return cpu.cmpsw.apply(cpu, arguments); }, "_cmpsd": function() { return cpu.cmpsd.apply(cpu, arguments); }, "_stosb": function() { return cpu.stosb.apply(cpu, arguments); }, diff --git a/src/cpu.js b/src/cpu.js index 9fbb6cf3..7198f57a 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -350,6 +350,7 @@ CPU.prototype.wasm_patch = function(wm) this.movsb = this.wm.funcs['_movsb']; this.movsw = this.wm.funcs['_movsw']; this.movsd = this.wm.funcs['_movsd']; + this.cmpsb = this.wm.funcs['_cmpsb']; }; CPU.prototype.get_state = function() diff --git a/src/native/string.c b/src/native/string.c index a10363f6..544a546b 100644 --- a/src/native/string.c +++ b/src/native/string.c @@ -240,3 +240,73 @@ void movsd() } } +void cmpsb_rep() +{ + int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); + int32_t dest = get_seg(ES) + get_reg_asize(EDI); + int32_t data_src, data_dest; + int32_t size = *flags & FLAG_DIRECTION ? -1 : 1; + + int32_t count = get_reg_asize(ECX) >> 0; + if(count == 0) return; + int32_t cont = false; + int32_t start_count = count; + int32_t is_repz = (*prefixes & PREFIX_MASK_REP) == PREFIX_REPZ; + int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + int32_t phys_src = translate_address_read(src); + int32_t phys_dest = translate_address_read(dest); + if(*paging) + { + cycle_counter = string_get_cycle_count2(size, src, dest); + } + do + { + data_dest = read8(phys_dest); + data_src = read8(phys_src); + phys_dest += size; + phys_src += size; + cont = --count != 0 && (data_src == data_dest) == is_repz; + } + while(cont && cycle_counter--); + int32_t diff = size * (start_count - count); + add_reg_asize(EDI, diff); + add_reg_asize(ESI, diff); + set_ecx_asize(count); + *timestamp_counter += start_count - count; + if(cont) + { + *instruction_pointer = *previous_ip; + } + + cmp8(data_src, data_dest); + diverged(); +} + +void cmpsb_no_rep() +{ + int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); + int32_t dest = get_seg(ES) + get_reg_asize(EDI); + int32_t data_src, data_dest; + int32_t size = *flags & FLAG_DIRECTION ? -1 : 1; + + data_src = safe_read8(src); + data_dest = safe_read8(dest); + add_reg_asize(EDI, size); + add_reg_asize(ESI, size); + + cmp8(data_src, data_dest); + diverged(); +} + +void cmpsb() +{ + if(*prefixes & PREFIX_MASK_REP) + { + cmpsb_rep(); + } + else + { + cmpsb_no_rep(); + } +} + From 39ede470ed90e47a614f411cf55126d65dbd7d6d Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sun, 30 Jul 2017 18:32:54 +0530 Subject: [PATCH 0092/2137] port cmpsw --- src/browser/starter.js | 1 - src/cpu.js | 1 + src/native/string.c | 88 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 1 deletion(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 5bd07a6d..625f3127 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -200,7 +200,6 @@ function V86Starter(options) "_outsb": function() { return cpu.outsb.apply(cpu, arguments); }, "_outsw": function() { return cpu.outsw.apply(cpu, arguments); }, "_outsd": function() { return cpu.outsd.apply(cpu, arguments); }, - "_cmpsw": function() { return cpu.cmpsw.apply(cpu, arguments); }, "_cmpsd": function() { return cpu.cmpsd.apply(cpu, arguments); }, "_stosb": function() { return cpu.stosb.apply(cpu, arguments); }, "_stosw": function() { return cpu.stosw.apply(cpu, arguments); }, diff --git a/src/cpu.js b/src/cpu.js index 7198f57a..5a3f2831 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -351,6 +351,7 @@ CPU.prototype.wasm_patch = function(wm) this.movsw = this.wm.funcs['_movsw']; this.movsd = this.wm.funcs['_movsd']; this.cmpsb = this.wm.funcs['_cmpsb']; + this.cmpsw = this.wm.funcs['_cmpsw']; }; CPU.prototype.get_state = function() diff --git a/src/native/string.c b/src/native/string.c index 544a546b..d1254f9a 100644 --- a/src/native/string.c +++ b/src/native/string.c @@ -310,3 +310,91 @@ void cmpsb() } } +void cmpsw_rep() +{ + int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); + int32_t dest = get_seg(ES) + get_reg_asize(EDI); + int32_t data_src, data_dest; + int32_t size = *flags & FLAG_DIRECTION ? -2 : 2; + + int32_t count = get_reg_asize(ECX) >> 0; + if(count == 0) return; + int32_t cont = false; + int32_t start_count = count; + int32_t is_repz = (*prefixes & PREFIX_MASK_REP) == PREFIX_REPZ; + int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + if(!(dest & 1) && !(src & 1)) + { + int32_t single_size = size < 0 ? -1 : 1; + int32_t phys_src = translate_address_read(src) >> 1; + int32_t phys_dest = translate_address_read(dest) >> 1; + if(*paging) + { + cycle_counter = string_get_cycle_count2(size, src, dest); + } + do + { + data_dest = read_aligned16(phys_dest); + data_src = read_aligned16(phys_src); + phys_dest += single_size; + phys_src += single_size; + cont = --count != 0 && (data_src == data_dest) == is_repz; + } + while(cont && cycle_counter--); + int32_t diff = size * (start_count - count) | 0; + add_reg_asize(EDI, diff); + add_reg_asize(ESI, diff); + set_ecx_asize(count); + *timestamp_counter += start_count - count; + } + else + { + do + { + data_dest = safe_read16(dest); + data_src = safe_read16(src); + dest += size; + add_reg_asize(EDI, size); + src += size; + add_reg_asize(ESI, size); + cont = decr_ecx_asize() != 0 && (data_src == data_dest) == is_repz; + } + while(cont && cycle_counter--); + } + if(cont) + { + *instruction_pointer = *previous_ip; + } + + cmp16(data_src, data_dest); + diverged(); +} + +void cmpsw_no_rep() +{ + int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); + int32_t dest = get_seg(ES) + get_reg_asize(EDI); + int32_t data_src, data_dest; + int32_t size = *flags & FLAG_DIRECTION ? -2 : 2; + + data_dest = safe_read16(dest); + data_src = safe_read16(src); + add_reg_asize(EDI, size); + add_reg_asize(ESI, size); + + cmp16(data_src, data_dest); + diverged(); +} + +void cmpsw() +{ + if(*prefixes & PREFIX_MASK_REP) + { + cmpsw_rep(); + } + else + { + cmpsw_no_rep(); + } +} + From 59f7bc4ec10d618057817b1ba76947b27ec15e74 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sun, 30 Jul 2017 18:37:32 +0530 Subject: [PATCH 0093/2137] port cmpsd --- src/browser/starter.js | 1 - src/cpu.js | 1 + src/native/string.c | 88 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 1 deletion(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 625f3127..bde131ba 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -200,7 +200,6 @@ function V86Starter(options) "_outsb": function() { return cpu.outsb.apply(cpu, arguments); }, "_outsw": function() { return cpu.outsw.apply(cpu, arguments); }, "_outsd": function() { return cpu.outsd.apply(cpu, arguments); }, - "_cmpsd": function() { return cpu.cmpsd.apply(cpu, arguments); }, "_stosb": function() { return cpu.stosb.apply(cpu, arguments); }, "_stosw": function() { return cpu.stosw.apply(cpu, arguments); }, "_stosd": function() { return cpu.stosd.apply(cpu, arguments); }, diff --git a/src/cpu.js b/src/cpu.js index 5a3f2831..a00120b6 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -352,6 +352,7 @@ CPU.prototype.wasm_patch = function(wm) this.movsd = this.wm.funcs['_movsd']; this.cmpsb = this.wm.funcs['_cmpsb']; this.cmpsw = this.wm.funcs['_cmpsw']; + this.cmpsd = this.wm.funcs['_cmpsd']; }; CPU.prototype.get_state = function() diff --git a/src/native/string.c b/src/native/string.c index d1254f9a..e61a8749 100644 --- a/src/native/string.c +++ b/src/native/string.c @@ -398,3 +398,91 @@ void cmpsw() } } +void cmpsd_rep() +{ + int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); + int32_t dest = get_seg(ES) + get_reg_asize(EDI); + int32_t data_src, data_dest; + int32_t size = *flags & FLAG_DIRECTION ? -4 : 4; + + int32_t count = get_reg_asize(ECX) >> 0; + if(count == 0) return; + int32_t cont = false; + int32_t start_count = count; + int32_t is_repz = (*prefixes & PREFIX_MASK_REP) == PREFIX_REPZ; + int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + if(!(dest & 3) && !(src & 3)) + { + int32_t single_size = size < 0 ? -1 : 1; + int32_t phys_src = translate_address_read(src) >> 2; + int32_t phys_dest = translate_address_read(dest) >> 2; + if(*paging) + { + cycle_counter = string_get_cycle_count2(size, src, dest); + } + do + { + data_dest = read_aligned32(phys_dest); + data_src = read_aligned32(phys_src); + phys_dest += single_size; + phys_src += single_size; + cont = --count != 0 && (data_src == data_dest) == is_repz; + } + while(cont && cycle_counter--); + int32_t diff = size * (start_count - count) | 0; + add_reg_asize(EDI, diff); + add_reg_asize(ESI, diff); + set_ecx_asize(count); + *timestamp_counter += start_count - count; + } + else + { + do + { + data_dest = safe_read32s(dest); + data_src = safe_read32s(src); + dest += size; + add_reg_asize(EDI, size); + src += size; + add_reg_asize(ESI, size); + cont = decr_ecx_asize() != 0 && (data_src == data_dest) == is_repz; + } + while(cont && cycle_counter--); + } + if(cont) + { + *instruction_pointer = *previous_ip; + } + + cmp32(data_src, data_dest); + diverged(); +} + +void cmpsd_no_rep() +{ + int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); + int32_t dest = get_seg(ES) + get_reg_asize(EDI); + int32_t data_src, data_dest; + int32_t size = *flags & FLAG_DIRECTION ? -4 : 4; + + data_dest = safe_read32s(dest); + data_src = safe_read32s(src); + add_reg_asize(EDI, size); + add_reg_asize(ESI, size); + + cmp32(data_src, data_dest); + diverged(); +} + +void cmpsd() +{ + if(*prefixes & PREFIX_MASK_REP) + { + cmpsd_rep(); + } + else + { + cmpsd_no_rep(); + } +} + From e35ad8425dd46fc122025839f01cae9909370076 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sun, 30 Jul 2017 18:58:55 +0530 Subject: [PATCH 0094/2137] port stos* --- src/browser/starter.js | 3 - src/cpu.js | 3 + src/native/string.c | 201 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 204 insertions(+), 3 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index bde131ba..5119e518 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -200,9 +200,6 @@ function V86Starter(options) "_outsb": function() { return cpu.outsb.apply(cpu, arguments); }, "_outsw": function() { return cpu.outsw.apply(cpu, arguments); }, "_outsd": function() { return cpu.outsd.apply(cpu, arguments); }, - "_stosb": function() { return cpu.stosb.apply(cpu, arguments); }, - "_stosw": function() { return cpu.stosw.apply(cpu, arguments); }, - "_stosd": function() { return cpu.stosd.apply(cpu, arguments); }, "_lodsb": function() { return cpu.lodsb.apply(cpu, arguments); }, "_lodsw": function() { return cpu.lodsw.apply(cpu, arguments); }, "_lodsd": function() { return cpu.lodsd.apply(cpu, arguments); }, diff --git a/src/cpu.js b/src/cpu.js index a00120b6..61ca1df1 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -353,6 +353,9 @@ CPU.prototype.wasm_patch = function(wm) this.cmpsb = this.wm.funcs['_cmpsb']; this.cmpsw = this.wm.funcs['_cmpsw']; this.cmpsd = this.wm.funcs['_cmpsd']; + this.stosb = this.wm.funcs['_stosb']; + this.stosw = this.wm.funcs['_stosw']; + this.stosd = this.wm.funcs['_stosd']; }; CPU.prototype.get_state = function() diff --git a/src/native/string.c b/src/native/string.c index e61a8749..cd274adf 100644 --- a/src/native/string.c +++ b/src/native/string.c @@ -486,3 +486,204 @@ void cmpsd() } } +void stosb_rep() +{ + int32_t data = reg8[AL]; + 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; + if(count == 0) return; + int32_t cont = false; + int32_t start_count = count; + int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + int32_t phys_dest = translate_address_write(dest); + if(*paging) + { + cycle_counter = string_get_cycle_count(size, dest); + } + do + { + write8(phys_dest, data); + phys_dest += size; + cont = --count != 0; + } + while(cont && cycle_counter--); + int32_t diff = size * (start_count - count); + add_reg_asize(EDI, diff); + set_ecx_asize(count); + *timestamp_counter += start_count - count; + if(cont) + { + *instruction_pointer = *previous_ip; + } + diverged(); +} + +void stosb_no_rep() +{ + int32_t data = reg8[AL]; + int32_t dest = get_seg(ES) + get_reg_asize(EDI); + int32_t size = *flags & FLAG_DIRECTION ? -1 : 1; + + safe_write8(dest, data); + add_reg_asize(EDI, size); + diverged(); +} + +void stosb() +{ + if(*prefixes & PREFIX_MASK_REP) + { + stosb_rep(); + } + else + { + stosb_no_rep(); + } +} + +void stosw_rep() +{ + int32_t data = reg16[AX]; + 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; + if(count == 0) return; + int32_t cont = false; + int32_t start_count = count; + int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + if(!(dest & 1)) + { + int32_t single_size = size < 0 ? -1 : 1; + int32_t phys_dest = translate_address_write(dest) >> 1; + if(*paging) + { + cycle_counter = string_get_cycle_count(size, dest); + } + do + { + write_aligned16(phys_dest, data); + phys_dest += single_size; + cont = --count != 0; + } + while(cont && cycle_counter--); + int32_t diff = size * (start_count - count); + add_reg_asize(EDI, diff); + set_ecx_asize(count); + *timestamp_counter += start_count - count; + } + else + { + do + { + safe_write16(dest, data); + dest += size; + add_reg_asize(EDI, size); + cont = decr_ecx_asize() != 0; + } + while(cont && cycle_counter--); + } + if(cont) + { + *instruction_pointer = *previous_ip; + } + diverged(); +} + +void stosw_no_rep() +{ + int32_t data = reg16[AX]; + int32_t dest = get_seg(ES) + get_reg_asize(EDI); + int32_t size = *flags & FLAG_DIRECTION ? -2 : 2; + + safe_write16(dest, data); + add_reg_asize(EDI, size); + diverged(); +} + +void stosw() +{ + if(*prefixes & PREFIX_MASK_REP) + { + stosw_rep(); + } + else + { + stosw_no_rep(); + } +} + +void stosd_rep() +{ + int32_t data = reg32s[EAX]; + 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; + if(count == 0) return; + int32_t cont = false; + int32_t start_count = count; + int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + if(!(dest & 3)) + { + int32_t single_size = size < 0 ? -1 : 1; + int32_t phys_dest = translate_address_write(dest) >> 2; + if(*paging) + { + cycle_counter = string_get_cycle_count(size, dest); + } + do + { + write_aligned32(phys_dest, data); + phys_dest += single_size; + cont = --count != 0; + } + while(cont && cycle_counter--); + int32_t diff = size * (start_count - count); + add_reg_asize(EDI, diff); + set_ecx_asize(count); + *timestamp_counter += start_count - count; + } + else + { + do + { + safe_write32(dest, data); + dest += size; + add_reg_asize(EDI, size); + cont = decr_ecx_asize() != 0; + } + while(cont && cycle_counter--); + } + if(cont) + { + *instruction_pointer = *previous_ip; + } + diverged(); +} + +void stosd_no_rep() +{ + int32_t data = reg32s[EAX]; + int32_t dest = get_seg(ES) + get_reg_asize(EDI); + int32_t size = *flags & FLAG_DIRECTION ? -4 : 4; + + safe_write32(dest, data); + add_reg_asize(EDI, size); + diverged(); +} + +void stosd() +{ + if(*prefixes & PREFIX_MASK_REP) + { + stosd_rep(); + } + else + { + stosd_no_rep(); + } +} + From 6274f909392689b17d3b60cedee572be49f7939f Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 1 Aug 2017 16:46:12 +0530 Subject: [PATCH 0095/2137] enable more string instructions in nasm tests --- tests/nasm/create_tests.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tests/nasm/create_tests.js b/tests/nasm/create_tests.js index bb913d2a..c28ff1fa 100755 --- a/tests/nasm/create_tests.js +++ b/tests/nasm/create_tests.js @@ -144,12 +144,12 @@ const encodings = [ { opcode: 0xA8, imm: 1, }, { opcode: 0xA9, os: 1, imm: 1, }, - { opcode: 0xAA, skip: 1, }, - { opcode: 0xAB, os: 1, skip: 1, }, - { opcode: 0xAC, skip: 1, }, - { opcode: 0xAD, os: 1, skip: 1, }, - { opcode: 0xAE, skip: 1, }, - { opcode: 0xAF, os: 1, skip: 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, }, @@ -996,7 +996,9 @@ function random_int32() function is_string_instruction(op) { - return (op.opcode >= 0x6C && op.opcode <= 0x6F) || (op.opcode >= 0xA4 && op.opcode <= 0xA7); + return (op.opcode >= 0x6C && op.opcode <= 0x6F) + || (op.opcode >= 0xA4 && op.opcode <= 0xA7) + || (op.opcode >= 0xAA && op.opcode <= 0xAF); } function create_nasm(op, config) From 96dfe623a20511e2df0567c0cf5649face6a35f2 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Wed, 2 Aug 2017 18:57:15 +0530 Subject: [PATCH 0096/2137] port lods* --- src/browser/starter.js | 3 - src/cpu.js | 3 + src/native/string.c | 147 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+), 3 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 5119e518..003e2e7d 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -200,9 +200,6 @@ function V86Starter(options) "_outsb": function() { return cpu.outsb.apply(cpu, arguments); }, "_outsw": function() { return cpu.outsw.apply(cpu, arguments); }, "_outsd": function() { return cpu.outsd.apply(cpu, arguments); }, - "_lodsb": function() { return cpu.lodsb.apply(cpu, arguments); }, - "_lodsw": function() { return cpu.lodsw.apply(cpu, arguments); }, - "_lodsd": function() { return cpu.lodsd.apply(cpu, arguments); }, "_scasb": function() { return cpu.scasb.apply(cpu, arguments); }, "_scasw": function() { return cpu.scasw.apply(cpu, arguments); }, "_scasd": function() { return cpu.scasd.apply(cpu, arguments); }, diff --git a/src/cpu.js b/src/cpu.js index 61ca1df1..4408f400 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -356,6 +356,9 @@ CPU.prototype.wasm_patch = function(wm) this.stosb = this.wm.funcs['_stosb']; this.stosw = this.wm.funcs['_stosw']; this.stosd = this.wm.funcs['_stosd']; + this.lodsb = this.wm.funcs['_lodsb']; + this.lodsw = this.wm.funcs['_lodsw']; + this.lodsd = this.wm.funcs['_lodsd']; }; CPU.prototype.get_state = function() diff --git a/src/native/string.c b/src/native/string.c index cd274adf..faf56130 100644 --- a/src/native/string.c +++ b/src/native/string.c @@ -687,3 +687,150 @@ void stosd() } } +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; + if(count == 0) return; + int32_t cont = false; + int32_t start_count = count; + int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + int32_t phys_src = translate_address_read(src); + if(*paging) + { + cycle_counter = string_get_cycle_count(size, src); + } + do + { + reg8[AL] = read8(phys_src); + phys_src += size; + cont = --count != 0; + } + while(cont && cycle_counter--); + int32_t diff = size * (start_count - count); + add_reg_asize(ESI, diff); + set_ecx_asize(count); + *timestamp_counter += start_count - count; + if(cont) + { + *instruction_pointer = *previous_ip; + } + diverged(); +} + +void lodsb_no_rep() +{ + int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); + int32_t size = *flags & FLAG_DIRECTION ? -1 : 1; + reg8[AL] = safe_read8(src); + add_reg_asize(ESI, size); + diverged(); +} + + +void lodsb() +{ + if(*prefixes & PREFIX_MASK_REP) + { + lodsb_rep(); + } + else + { + lodsb_no_rep(); + } +} + +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; + if(count == 0) return; + bool cont = false; + uint32_t cycle_counter = MAX_COUNT_PER_CYCLE; + do + { + reg16[AX] = safe_read16(src); + src += size; + add_reg_asize(ESI, size); + cont = decr_ecx_asize() != 0; + } + while(cont && cycle_counter--); + if(cont) + { + *instruction_pointer = *previous_ip; + } + diverged(); +} + +void lodsw_no_rep() +{ + int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); + int32_t size = *flags & FLAG_DIRECTION ? -2 : 2; + + reg16[AX] = safe_read16(src); + add_reg_asize(ESI, size); + + diverged(); +} + +void lodsw() +{ + if(*prefixes & PREFIX_MASK_REP) + { + lodsw_rep(); + } + else + { + lodsw_no_rep(); + } +} + +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; + if(count == 0) return; + int32_t cont = false; + int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + do + { + reg32s[EAX] = safe_read32s(src); + src += size; + add_reg_asize(ESI, size); + cont = decr_ecx_asize() != 0; + } + while(cont && cycle_counter--); + if(cont) + { + *instruction_pointer = *previous_ip; + } + diverged(); +} + +void lodsd_no_rep() +{ + int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); + int32_t size = *flags & FLAG_DIRECTION ? -4 : 4; + + reg32s[EAX] = safe_read32s(src); + add_reg_asize(ESI, size); + diverged(); +} + +void lodsd() +{ + if(*prefixes & PREFIX_MASK_REP) + { + lodsd_rep(); + } + else + { + lodsd_no_rep(); + } +} + From c8b7c1edf43997ac95df7412b1946857233065db Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Wed, 2 Aug 2017 19:09:03 +0530 Subject: [PATCH 0097/2137] port scas* --- src/browser/starter.js | 3 - src/cpu.js | 3 + src/native/string.c | 217 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 220 insertions(+), 3 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 003e2e7d..3d01d597 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -200,9 +200,6 @@ function V86Starter(options) "_outsb": function() { return cpu.outsb.apply(cpu, arguments); }, "_outsw": function() { return cpu.outsw.apply(cpu, arguments); }, "_outsd": function() { return cpu.outsd.apply(cpu, arguments); }, - "_scasb": function() { return cpu.scasb.apply(cpu, arguments); }, - "_scasw": function() { return cpu.scasw.apply(cpu, arguments); }, - "_scasd": function() { return cpu.scasd.apply(cpu, arguments); }, "_lss16": function() { return cpu.lss16.apply(cpu, arguments); }, "_lss32": function() { return cpu.lss32.apply(cpu, arguments); }, "_enter16": function() { return cpu.enter16.apply(cpu, arguments); }, diff --git a/src/cpu.js b/src/cpu.js index 4408f400..fc95a927 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -359,6 +359,9 @@ CPU.prototype.wasm_patch = function(wm) this.lodsb = this.wm.funcs['_lodsb']; this.lodsw = this.wm.funcs['_lodsw']; this.lodsd = this.wm.funcs['_lodsd']; + this.scasb = this.wm.funcs['_scasb']; + this.scasw = this.wm.funcs['_scasw']; + this.scasd = this.wm.funcs['_scasd']; }; CPU.prototype.get_state = function() diff --git a/src/native/string.c b/src/native/string.c index faf56130..6dad7026 100644 --- a/src/native/string.c +++ b/src/native/string.c @@ -834,3 +834,220 @@ void lodsd() } } +void scasb_rep() +{ + int32_t dest = get_seg(ES) + get_reg_asize(EDI); + int32_t size = *flags & FLAG_DIRECTION ? -1 : 1; + int32_t data_dest; + int32_t data_src = reg8[AL]; + + int32_t count = get_reg_asize(ECX) >> 0; + if(count == 0) return; + int32_t cont = false; + int32_t start_count = count; + int32_t is_repz = (*prefixes & PREFIX_MASK_REP) == PREFIX_REPZ; + int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + int32_t phys_dest = translate_address_read(dest); + if(*paging) + { + cycle_counter = string_get_cycle_count(size, dest); + } + do + { + data_dest = read8(phys_dest); + phys_dest += size; + cont = --count != 0 && (data_src == data_dest) == is_repz; + } + while(cont && cycle_counter--); + int32_t diff = size * (start_count - count); + add_reg_asize(EDI, diff); + set_ecx_asize(count); + *timestamp_counter += start_count - count; + if(cont) + { + *instruction_pointer = *previous_ip; + } + cmp8(data_src, data_dest); + diverged(); +} + +void scasb_no_rep() +{ + int32_t dest = get_seg(ES) + get_reg_asize(EDI); + int32_t size = *flags & FLAG_DIRECTION ? -1 : 1; + int32_t data_dest; + int32_t data_src = reg8[AL]; + + data_dest = safe_read8(dest); + add_reg_asize(EDI, size); + cmp8(data_src, data_dest); + diverged(); +} + +void scasb() +{ + if(*prefixes & PREFIX_MASK_REP) + { + scasb_rep(); + } + else + { + scasb_no_rep(); + } +} + +void scasw_rep() +{ + int32_t dest = get_seg(ES) + get_reg_asize(EDI); + int32_t size = *flags & FLAG_DIRECTION ? -2 : 2; + int32_t data_dest; + int32_t data_src = reg16[AL]; + + int32_t count = get_reg_asize(ECX) >> 0; + if(count == 0) return; + int32_t cont = false; + int32_t start_count = count; + int32_t is_repz = (*prefixes & PREFIX_MASK_REP) == PREFIX_REPZ; + int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + if(!(dest & 1)) + { + int32_t single_size = size < 0 ? -1 : 1; + int32_t phys_dest = translate_address_read(dest) >> 1; + if(*paging) + { + cycle_counter = string_get_cycle_count(size, dest); + } + do + { + data_dest = read_aligned16(phys_dest); + phys_dest += single_size; + cont = --count != 0 && (data_src == data_dest) == is_repz; + } + while(cont && cycle_counter--); + int32_t diff = size * (start_count - count); + add_reg_asize(EDI, diff); + set_ecx_asize(count); + *timestamp_counter += start_count - count; + } + else + { + do + { + data_dest = safe_read16(dest); + dest += size; + add_reg_asize(EDI, size); + cont = decr_ecx_asize() != 0 && (data_src == data_dest) == is_repz; + } + while(cont && cycle_counter--); + } + if(cont) + { + *instruction_pointer = *previous_ip; + } + cmp16(data_src, data_dest); + diverged(); +} + +void scasw_no_rep() +{ + int32_t dest = get_seg(ES) + get_reg_asize(EDI); + int32_t size = *flags & FLAG_DIRECTION ? -2 : 2; + int32_t data_dest; + int32_t data_src = reg16[AL]; + + data_dest = safe_read16(dest); + add_reg_asize(EDI, size); + cmp16(data_src, data_dest); + diverged(); +} + +void scasw() +{ + if(*prefixes & PREFIX_MASK_REP) + { + scasw_rep(); + } + else + { + scasw_no_rep(); + } +} + +void scasd_rep() +{ + int32_t dest = get_seg(ES) + get_reg_asize(EDI); + int32_t size = *flags & FLAG_DIRECTION ? -4 : 4; + int32_t data_dest; + int32_t data_src = reg32s[EAX]; + + int32_t count = get_reg_asize(ECX) >> 0; + if(count == 0) return; + int32_t cont = false; + int32_t start_count = count; + int32_t is_repz = (*prefixes & PREFIX_MASK_REP) == PREFIX_REPZ; + int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + if(!(dest & 3)) + { + int32_t single_size = size < 0 ? -1 : 1; + int32_t phys_dest = translate_address_read(dest) >> 2; + if(*paging) + { + cycle_counter = string_get_cycle_count(size, dest); + } + do + { + data_dest = read_aligned32(phys_dest); + phys_dest += single_size; + cont = --count != 0 && (data_src == data_dest) == is_repz; + } + while(cont && cycle_counter--); + int32_t diff = size * (start_count - count); + add_reg_asize(EDI, diff); + set_ecx_asize(count); + *timestamp_counter += start_count - count; + } + else + { + do + { + data_dest = safe_read32s(dest); + dest += size; + add_reg_asize(EDI, size); + cont = decr_ecx_asize() != 0 && (data_src == data_dest) == is_repz; + } + while(cont && cycle_counter--); + } + if(cont) + { + *instruction_pointer = *previous_ip; + } + cmp32(data_src, data_dest); + diverged(); +} + +void scasd_no_rep() +{ + int32_t dest = get_seg(ES) + get_reg_asize(EDI); + int32_t size = *flags & FLAG_DIRECTION ? -4 : 4; + int32_t data_dest; + int32_t data_src = reg32s[EAX]; + + data_dest = safe_read32s(dest); + add_reg_asize(EDI, size); + cmp32(data_src, data_dest); + diverged(); +} + + +void scasd() +{ + if(*prefixes & PREFIX_MASK_REP) + { + scasd_rep(); + } + else + { + scasd_no_rep(); + } +} + From d96cbd5f7fe1882a8d633efd23fc4c17f9e53cbb Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Wed, 2 Aug 2017 19:22:23 +0530 Subject: [PATCH 0098/2137] port ins* --- src/browser/starter.js | 3 - src/cpu.js | 3 + src/native/string.c | 216 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 219 insertions(+), 3 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 3d01d597..258a9ec5 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -194,9 +194,6 @@ function V86Starter(options) "_load_ldt": function() { return cpu.load_ldt.apply(cpu, arguments); }, "_load_tr": function() { return cpu.load_tr.apply(cpu, arguments); }, - "_insb": function() { return cpu.insb.apply(cpu, arguments); }, - "_insw": function() { return cpu.insw.apply(cpu, arguments); }, - "_insd": function() { return cpu.insd.apply(cpu, arguments); }, "_outsb": function() { return cpu.outsb.apply(cpu, arguments); }, "_outsw": function() { return cpu.outsw.apply(cpu, arguments); }, "_outsd": function() { return cpu.outsd.apply(cpu, arguments); }, diff --git a/src/cpu.js b/src/cpu.js index fc95a927..85f06a0c 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -362,6 +362,9 @@ CPU.prototype.wasm_patch = function(wm) this.scasb = this.wm.funcs['_scasb']; this.scasw = this.wm.funcs['_scasw']; this.scasd = this.wm.funcs['_scasd']; + this.insb = this.wm.funcs['_insb']; + this.insw = this.wm.funcs['_insw']; + this.insd = this.wm.funcs['_insd']; }; CPU.prototype.get_state = function() diff --git a/src/native/string.c b/src/native/string.c index 6dad7026..d19fcb24 100644 --- a/src/native/string.c +++ b/src/native/string.c @@ -1051,3 +1051,219 @@ void scasd() } } +void insb_rep() +{ + int32_t port = reg16[DX]; + test_privileges_for_io(port, 1); + + 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; + if(count == 0) return; + int32_t cont = false; + int32_t start_count = count; + int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + int32_t phys_dest = translate_address_write(dest); + if(*paging) + { + cycle_counter = string_get_cycle_count(size, dest); + } + do + { + write8(phys_dest, io_port_read8(port)); + phys_dest += size; + cont = --count != 0; + } + while(cont && cycle_counter--); + int32_t diff = size * (start_count - count); + add_reg_asize(EDI, diff); + set_ecx_asize(count); + *timestamp_counter += start_count - count; + if(cont) + { + *instruction_pointer = *previous_ip; + } + diverged(); +} + +void insb_no_rep() +{ + int32_t port = reg16[DX]; + test_privileges_for_io(port, 1); + + int32_t dest = get_seg(ES) + get_reg_asize(EDI); + int32_t size = *flags & FLAG_DIRECTION ? -1 : 1; + + writable_or_pagefault(dest, 1); + safe_write8(dest, io_port_read8(port)); + add_reg_asize(EDI, size); + diverged(); +} + +void insb() +{ + if(*prefixes & PREFIX_MASK_REP) + { + insb_rep(); + } + else + { + insb_no_rep(); + } +} + +void insw_rep() +{ + int32_t port = reg16[DX]; + test_privileges_for_io(port, 2); + + 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; + if(count == 0) return; + int32_t cont = false; + int32_t start_count = count; + int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + if(!(dest & 1)) + { + int32_t single_size = size < 0 ? -1 : 1; + int32_t phys_dest = translate_address_write(dest) >> 1; + if(*paging) + { + cycle_counter = string_get_cycle_count(size, dest); + } + do + { + write_aligned16(phys_dest, io_port_read16(port)); + phys_dest += single_size; + cont = --count != 0; + } + while(cont && cycle_counter--); + int32_t diff = size * (start_count - count); + add_reg_asize(EDI, diff); + set_ecx_asize(count); + *timestamp_counter += start_count - count; + } + else + { + do + { + safe_write16(dest, io_port_read16(port)); + dest += size; + add_reg_asize(EDI, size); + cont = decr_ecx_asize() != 0; + } + while(cont && cycle_counter--); + } + if(cont) + { + *instruction_pointer = *previous_ip; + } + diverged(); +} + +void insw_no_rep() +{ + int32_t port = reg16[DX]; + test_privileges_for_io(port, 2); + + int32_t dest = get_seg(ES) + get_reg_asize(EDI); + int32_t size = *flags & FLAG_DIRECTION ? -2 : 2; + + writable_or_pagefault(dest, 2); + safe_write16(dest, io_port_read16(port)); + add_reg_asize(EDI, size); + diverged(); +} + +void insw() +{ + if(*prefixes & PREFIX_MASK_REP) + { + insw_rep(); + } + else + { + insw_no_rep(); + } +} + +void insd_rep() +{ + int32_t port = reg16[DX]; + test_privileges_for_io(port, 4); + + 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; + if(count == 0) return; + int32_t cont = false; + int32_t start_count = count; + int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + if(!(dest & 3)) + { + int32_t single_size = size < 0 ? -1 : 1; + int32_t phys_dest = translate_address_write(dest) >> 2; + if(*paging) + { + cycle_counter = string_get_cycle_count(size, dest); + } + do + { + write_aligned32(phys_dest, io_port_read32(port)); + phys_dest += single_size; + cont = --count != 0; + } + while(cont && cycle_counter--); + int32_t diff = size * (start_count - count); + add_reg_asize(EDI, diff); + set_ecx_asize(count); + *timestamp_counter += start_count - count; + } + else + { + do + { + safe_write32(dest, io_port_read32(port)); + dest += size; + add_reg_asize(EDI, size); + cont = decr_ecx_asize() != 0; + } + while(cont && cycle_counter--); + } + if(cont) + { + *instruction_pointer = *previous_ip; + } + diverged(); +} + +void insd_no_rep() +{ + int32_t port = reg16[DX]; + test_privileges_for_io(port, 4); + + int32_t dest = get_seg(ES) + get_reg_asize(EDI); + int32_t size = *flags & FLAG_DIRECTION ? -4 : 4; + + writable_or_pagefault(dest, 4); + safe_write32(dest, io_port_read32(port)); + add_reg_asize(EDI, size); + diverged(); +} + +void insd() +{ + if(*prefixes & PREFIX_MASK_REP) + { + insd_rep(); + } + else + { + insd_no_rep(); + } +} + From b17e5e16727eb696aaa0c578c9220433171b64a0 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Wed, 2 Aug 2017 19:29:46 +0530 Subject: [PATCH 0099/2137] port outs* --- src/browser/starter.js | 3 - src/cpu.js | 3 + src/native/string.c | 213 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 216 insertions(+), 3 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 258a9ec5..57cfbd28 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -194,9 +194,6 @@ function V86Starter(options) "_load_ldt": function() { return cpu.load_ldt.apply(cpu, arguments); }, "_load_tr": function() { return cpu.load_tr.apply(cpu, arguments); }, - "_outsb": function() { return cpu.outsb.apply(cpu, arguments); }, - "_outsw": function() { return cpu.outsw.apply(cpu, arguments); }, - "_outsd": function() { return cpu.outsd.apply(cpu, arguments); }, "_lss16": function() { return cpu.lss16.apply(cpu, arguments); }, "_lss32": function() { return cpu.lss32.apply(cpu, arguments); }, "_enter16": function() { return cpu.enter16.apply(cpu, arguments); }, diff --git a/src/cpu.js b/src/cpu.js index 85f06a0c..c6c4a6e4 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -365,6 +365,9 @@ CPU.prototype.wasm_patch = function(wm) this.insb = this.wm.funcs['_insb']; this.insw = this.wm.funcs['_insw']; this.insd = this.wm.funcs['_insd']; + this.outsb = this.wm.funcs['_outsb']; + this.outsw = this.wm.funcs['_outsw']; + this.outsd = this.wm.funcs['_outsd']; }; CPU.prototype.get_state = function() diff --git a/src/native/string.c b/src/native/string.c index d19fcb24..550c89ee 100644 --- a/src/native/string.c +++ b/src/native/string.c @@ -1267,3 +1267,216 @@ void insd() } } +void outsb_rep() + { + int32_t port = reg16[DX]; + test_privileges_for_io(port, 1); + + 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; + if(count == 0) return; + int32_t cont = false; + int32_t start_count = count; + int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + int32_t phys_src = translate_address_read(src); + if(*paging) + { + cycle_counter = string_get_cycle_count(size, src); + } + do + { + io_port_write8(port, read8(phys_src)); + phys_src += size; + cont = --count != 0; + } + while(cont && cycle_counter--); + int32_t diff = size * (start_count - count); + add_reg_asize(ESI, diff); + set_ecx_asize(count); + *timestamp_counter += start_count - count; + if(cont) + { + *instruction_pointer = *previous_ip; + } + diverged(); + } + +void outsb_no_rep() +{ + int32_t port = reg16[DX]; + test_privileges_for_io(port, 1); + + int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); + int32_t size = *flags & FLAG_DIRECTION ? -1 : 1; + + io_port_write8(port, safe_read8(src)); + add_reg_asize(ESI, size); + diverged(); +} + +void outsb() +{ + if(*prefixes & PREFIX_MASK_REP) + { + outsb_rep(); + } + else + { + outsb_no_rep(); + } +} + +void outsw_rep() +{ + int32_t port = reg16[DX]; + test_privileges_for_io(port, 2); + + 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; + if(count == 0) return; + int32_t cont = false; + int32_t start_count = count; + int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + if(!(src & 1)) + { + int32_t single_size = size < 0 ? -1 : 1; + int32_t phys_src = translate_address_read(src) >> 1; + if(*paging) + { + cycle_counter = string_get_cycle_count(size, src); + } + do + { + io_port_write16(port, read_aligned16(phys_src)); + phys_src += single_size; + cont = --count != 0; + } + while(cont && cycle_counter--); + int32_t diff = size * (start_count - count); + add_reg_asize(ESI, diff); + set_ecx_asize(count); + *timestamp_counter += start_count - count; + } + else + { + do + { + io_port_write16(port, safe_read16(src)); + src += size; + add_reg_asize(ESI, size); + cont = decr_ecx_asize() != 0; + } + while(cont && cycle_counter--); + } + if(cont) + { + *instruction_pointer = *previous_ip; + } + diverged(); +} + +void outsw_no_rep() +{ + int32_t port = reg16[DX]; + test_privileges_for_io(port, 2); + + int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); + int32_t size = *flags & FLAG_DIRECTION ? -2 : 2; + + io_port_write16(port, safe_read16(src)); + add_reg_asize(ESI, size); + diverged(); +} + +void outsw() +{ + if(*prefixes & PREFIX_MASK_REP) + { + outsw_rep(); + } + else + { + outsw_no_rep(); + } +} + +void outsd_rep() +{ + int32_t port = reg16[DX]; + test_privileges_for_io(port, 4); + + 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; + if(count == 0) return; + int32_t cont = false; + int32_t start_count = count; + int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + if(!(src & 3)) + { + int32_t single_size = size < 0 ? -1 : 1; + int32_t phys_src = translate_address_read(src) >> 2; + if(*paging) + { + cycle_counter = string_get_cycle_count(size, src); + } + do + { + io_port_write32(port, read_aligned32(phys_src)); + phys_src += single_size; + cont = --count != 0; + } + while(cont && cycle_counter--); + int32_t diff = size * (start_count - count); + add_reg_asize(ESI, diff); + set_ecx_asize(count); + *timestamp_counter += start_count - count; + } + else + { + do + { + io_port_write32(port, safe_read32s(src)); + src += size; + add_reg_asize(ESI, size); + cont = decr_ecx_asize() != 0; + } + while(cont && cycle_counter--); + } + if(cont) + { + *instruction_pointer = *previous_ip; + } + diverged(); +} + +void outsd_no_rep() +{ + int32_t port = reg16[DX]; + test_privileges_for_io(port, 4); + + int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); + int32_t size = *flags & FLAG_DIRECTION ? -4 : 4; + + io_port_write32(port, safe_read32s(src)); + add_reg_asize(ESI, size); + diverged(); +} + +void outsd() +{ + if(*prefixes & PREFIX_MASK_REP) + { + outsd_rep(); + } + else + { + outsd_no_rep(); + } +} + From 72da71330e1b0f383912c47380949ed5ab168901 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Wed, 2 Aug 2017 21:29:51 +0530 Subject: [PATCH 0100/2137] fpu style fixes --- src/fpu.js | 6 +++--- src/native/fpu.c | 9 ++++----- src/native/global_pointers.h | 2 +- src/native/instructions_0f.c | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/fpu.js b/src/fpu.js index cb371a69..b7cc5259 100644 --- a/src/fpu.js +++ b/src/fpu.js @@ -97,12 +97,12 @@ function FPU(cpu) Math.log(2) / Math.LN10, Math.LN2, 0 ]); - this.wasm_patch(); + this.wasm_patch(cpu.wm); } -FPU.prototype.wasm_patch = function() +FPU.prototype.wasm_patch = function(wm) { - this.set_tag_word = this.cpu.wm.funcs["_safe_tag_word"]; + this.set_tag_word = wm.funcs["_fpu_set_tag_word"]; }; FPU.prototype.get_state = function() diff --git a/src/native/fpu.c b/src/native/fpu.c index aab2b889..08997671 100644 --- a/src/native/fpu.c +++ b/src/native/fpu.c @@ -8,13 +8,12 @@ #include "const.h" #include "global_pointers.h" -void safe_tag_word(int32_t tag_word) { - *stack_empty = 0; +void fpu_set_tag_word(int32_t tag_word) +{ + *fpu_stack_empty = 0; for(int i = 0; i < 8; i++) { - *stack_empty |= (tag_word >> i) & (tag_word >> (i + 1)) & 1 << i; + *fpu_stack_empty |= (tag_word >> i) & (tag_word >> (i + 1)) & 1 << i; } - - //dbg_log("safe tw=" + h(tag_word) + " se=" + h(this.stack_empty[0]), LOG_FPU); } diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index b61e8d01..36f4c9a2 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -53,7 +53,7 @@ bool* const protected_mode = (bool* const) 800; bool* const is_32 = (bool* const) 804; bool* const stack_size_32 = (bool* const) 808; uint32_t* const memory_size = (uint32_t* const) 812; -int32_t* const stack_empty = (int32_t* const) 816; +int32_t* const fpu_stack_empty = (int32_t* const) 816; bool* const paging = (bool* const) 820; diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 48b13cee..94f7380d 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -986,7 +986,7 @@ static void instr_0F77() { } } - safe_tag_word(0xFFFF); + fpu_set_tag_word(0xFFFF); } static void instr_0F78() { unimplemented_sse(); } From 3525ae3cbc91bfc6c5eb047a530a4df3b84386db Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Thu, 3 Aug 2017 13:43:12 +0530 Subject: [PATCH 0101/2137] relocate fpu floats to wasm memory --- src/fpu.js | 18 +++++++++--------- src/native/global_pointers.h | 12 ++++++++++++ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/fpu.js b/src/fpu.js index b7cc5259..aefd1153 100644 --- a/src/fpu.js +++ b/src/fpu.js @@ -61,18 +61,18 @@ function FPU(cpu) this.cpu = cpu; // Why no Float80Array :-( - this.st = new Float64Array(8); + this.st = new Float64Array(cpu.wm.mem.buffer, 968, 8); // used for conversion - /** @const */ this.float32 = new Float32Array(1); - /** @const */ this.float32_byte = new Uint8Array(this.float32.buffer); - /** @const */ this.float32_int = new Int32Array(this.float32.buffer); - /** @const */ this.float64 = new Float64Array(1); - /** @const */ this.float64_byte = new Uint8Array(this.float64.buffer); - /** @const */ this.float64_int = new Int32Array(this.float64.buffer); + /** @const */ this.float32 = new Float32Array(cpu.wm.mem.buffer, 956, 1); + /** @const */ this.float32_byte = new Uint8Array(this.float32.buffer, 956, 4); + /** @const */ this.float32_int = new Int32Array(this.float32.buffer, 956, 1); + /** @const */ this.float64 = new Float64Array(cpu.wm.mem.buffer, 960, 1); + /** @const */ this.float64_byte = new Uint8Array(this.float64.buffer, 960, 8); + /** @const */ this.float64_int = new Int32Array(this.float64.buffer, 960, 2); - /** @const */ this.st8 = new Uint8Array(this.st.buffer); - /** @const */ this.st32 = new Int32Array(this.st.buffer); + /** @const */ this.st8 = new Uint8Array(this.st.buffer, 968, 8 << 3); + /** @const */ this.st32 = new Int32Array(this.st.buffer, 968, 8 << 1); // bitmap of which stack registers are empty diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index 36f4c9a2..6c2ca05a 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -82,4 +82,16 @@ 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); +float_t* const fpu_float32 = (float_t* const) 956; +uint8_t* const fpu_float32_byte = (uint8_t* const) 956; +int32_t* const fpu_float32_int = (int32_t* const) 956; + +double_t* const fpu_float64 = (double_t* const) 960; +uint8_t* const fpu_float64_byte = (uint8_t* const) 960; +int32_t* const fpu_float64_int = (int32_t* const) 960; + +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; + #endif From 0a9928545391df143b9dc90988b3c260ee9773a2 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Thu, 3 Aug 2017 13:46:27 +0530 Subject: [PATCH 0102/2137] move fpu.stack_ptr to wasm mem (offset 1032) --- src/fpu.js | 195 ++++++++++++++++++----------------- src/misc_instr.js | 4 +- src/native/global_pointers.h | 2 + 3 files changed, 102 insertions(+), 99 deletions(-) diff --git a/src/fpu.js b/src/fpu.js index aefd1153..195c754f 100644 --- a/src/fpu.js +++ b/src/fpu.js @@ -78,7 +78,8 @@ function FPU(cpu) // bitmap of which stack registers are empty this.stack_empty = new Int32Array(cpu.wm.mem.buffer, 816, 1); this.stack_empty[0] = 0xff; - this.stack_ptr = 0; + this.stack_ptr = new Uint32Array(cpu.wm.mem.buffer, 1032, 1); + this.stack_ptr[0] = 0; this.control_word = 0x37F; this.status_word = 0; @@ -111,7 +112,7 @@ FPU.prototype.get_state = function() state[0] = this.st; state[1] = this.stack_empty[0]; - state[2] = this.stack_ptr; + state[2] = this.stack_ptr[0]; state[3] = this.control_word; state[4] = this.fpu_dp_selector; state[5] = this.fpu_ip; @@ -127,7 +128,7 @@ FPU.prototype.set_state = function(state) { this.st.set(state[0]); this.stack_empty[0] = state[1]; - this.stack_ptr = state[2]; + this.stack_ptr[0] = state[2]; this.control_word = state[3]; this.fpu_dp_selector = state[4]; this.fpu_ip = state[5]; @@ -187,7 +188,7 @@ FPU.prototype.fucom = function(y) FPU.prototype.fcomi = function(y) { - var x = this.st[this.stack_ptr]; + var x = this.st[this.stack_ptr[0]]; this.cpu.flags_changed[0] &= ~(1 | flag_parity | flag_zero); this.cpu.flags[0] &= ~(1 | flag_parity | flag_zero); @@ -240,7 +241,7 @@ FPU.prototype.fxam = function(x) this.status_word &= ~FPU_RESULT_FLAGS; this.status_word |= this.sign(0) << 9; - if(this.stack_empty[0] >> this.stack_ptr & 1) + if(this.stack_empty[0] >> this.stack_ptr[0] & 1) { this.status_word |= FPU_C3 | FPU_C0; } @@ -273,18 +274,18 @@ FPU.prototype.finit = function() this.fpu_opcode = 0; this.stack_empty[0] = 0xFF; - this.stack_ptr = 0; + this.stack_ptr[0] = 0; } FPU.prototype.load_status_word = function() { - return this.status_word & ~(7 << 11) | this.stack_ptr << 11; + return this.status_word & ~(7 << 11) | this.stack_ptr[0] << 11; } FPU.prototype.set_status_word = function(sw) { this.status_word = sw & ~(7 << 11); - this.stack_ptr = sw >> 11 & 7; + this.stack_ptr[0] = sw >> 11 & 7; } FPU.prototype.load_tag_word = function() @@ -310,7 +311,7 @@ FPU.prototype.load_tag_word = function() } } - //dbg_log("load tw=" + h(tag_word) + " se=" + h(this.stack_empty[0]) + " sp=" + this.stack_ptr, LOG_FPU); + //dbg_log("load tw=" + h(tag_word) + " se=" + h(this.stack_empty[0]) + " sp=" + this.stack_ptr[0], LOG_FPU); return tag_word; } @@ -380,11 +381,11 @@ FPU.prototype.fsave = function(addr) for(var i = 0; i < 8; i++) { - this.store_m80(addr, this.st[this.stack_ptr + i & 7]); + this.store_m80(addr, this.st[this.stack_ptr[0] + i & 7]); addr += 10; } - //dbg_log("save st=" + this.stack_ptr + " " + [].slice.call(this.st), LOG_FPU); + //dbg_log("save st=" + this.stack_ptr[0] + " " + [].slice.call(this.st), LOG_FPU); this.finit(); } @@ -396,11 +397,11 @@ FPU.prototype.frstor = function(addr) for(var i = 0; i < 8; i++) { - this.st[(i + this.stack_ptr) & 7] = this.load_m80(addr); + this.st[(i + this.stack_ptr[0]) & 7] = this.load_m80(addr); addr += 10; } - //dbg_log("rstor st=" + this.stack_ptr + " " + [].slice.call(this.st), LOG_FPU); + //dbg_log("rstor st=" + this.stack_ptr[0] + " " + [].slice.call(this.st), LOG_FPU); } FPU.prototype.fxtract = function() @@ -412,7 +413,7 @@ FPU.prototype.fxtract = function() this.float64_byte[7] = 0x3F | (this.float64_byte[7] & 0x80); this.float64_byte[6] |= 0xF0; - this.st[this.stack_ptr] = exponent; + this.st[this.stack_ptr[0]] = exponent; this.push(this.float64[0]); }; @@ -452,33 +453,33 @@ FPU.prototype.truncate = function(x) FPU.prototype.push = function(x) { - this.stack_ptr = this.stack_ptr - 1 & 7; + this.stack_ptr[0] = this.stack_ptr[0] - 1 & 7; - if(this.stack_empty[0] >> this.stack_ptr & 1) + if(this.stack_empty[0] >> this.stack_ptr[0] & 1) { this.status_word &= ~FPU_C1; - this.stack_empty[0] &= ~(1 << this.stack_ptr); - this.st[this.stack_ptr] = x; + this.stack_empty[0] &= ~(1 << this.stack_ptr[0]); + this.st[this.stack_ptr[0]] = x; } else { this.status_word |= FPU_C1; this.stack_fault(); - this.st[this.stack_ptr] = this.indefinite_nan; + this.st[this.stack_ptr[0]] = this.indefinite_nan; } } FPU.prototype.pop = function() { - this.stack_empty[0] |= 1 << this.stack_ptr; - this.stack_ptr = this.stack_ptr + 1 & 7; + this.stack_empty[0] |= 1 << this.stack_ptr[0]; + this.stack_ptr[0] = this.stack_ptr[0] + 1 & 7; } FPU.prototype.get_sti = function(i) { dbg_assert(typeof i === "number" && i >= 0 && i < 8); - i = i + this.stack_ptr & 7; + i = i + this.stack_ptr[0] & 7; if(this.stack_empty[0] >> i & 1) { @@ -494,7 +495,7 @@ FPU.prototype.get_sti = function(i) FPU.prototype.get_st0 = function() { - if(this.stack_empty[0] >> this.stack_ptr & 1) + if(this.stack_empty[0] >> this.stack_ptr[0] & 1) { this.status_word &= ~FPU_C1; this.stack_fault(); @@ -502,7 +503,7 @@ FPU.prototype.get_st0 = function() } else { - return this.st[this.stack_ptr]; + return this.st[this.stack_ptr[0]]; } } @@ -639,7 +640,7 @@ FPU.prototype.store_m32 = function(addr, x) // sign of a number on the stack FPU.prototype.sign = function(i) { - return this.st8[(this.stack_ptr + i & 7) << 3 | 7] >> 7; + return this.st8[(this.stack_ptr[0] + i & 7) << 3 | 7] >> 7; }; @@ -653,12 +654,12 @@ FPU.prototype.dbg_log_fpu_op = function(op, imm8) if(imm8 >= 0xC0) { dbg_log(h(op, 2) + " " + h(imm8, 2) + "/" + (imm8 >> 3 & 7) + "/" + (imm8 & 7) + - " @" + h(this.cpu.instruction_pointer[0] >>> 0, 8) + " sp=" + this.stack_ptr + " st=" + h(this.stack_empty[0], 2), LOG_FPU); + " @" + h(this.cpu.instruction_pointer[0] >>> 0, 8) + " sp=" + this.stack_ptr[0] + " st=" + h(this.stack_empty[0], 2), LOG_FPU); } else { dbg_log(h(op, 2) + " /" + imm8 + - " @" + h(this.cpu.instruction_pointer[0] >>> 0, 8) + " sp=" + this.stack_ptr + " st=" + h(this.stack_empty[0], 2), LOG_FPU); + " @" + h(this.cpu.instruction_pointer[0] >>> 0, 8) + " sp=" + this.stack_ptr[0] + " st=" + h(this.stack_empty[0], 2), LOG_FPU); } } @@ -682,11 +683,11 @@ FPU.prototype.op_D8_reg = function(imm8) { case 0: // fadd - this.st[this.stack_ptr] = st0 + sti; + this.st[this.stack_ptr[0]] = st0 + sti; break; case 1: // fmul - this.st[this.stack_ptr] = st0 * sti; + this.st[this.stack_ptr[0]] = st0 * sti; break; case 2: // fcom @@ -699,19 +700,19 @@ FPU.prototype.op_D8_reg = function(imm8) break; case 4: // fsub - this.st[this.stack_ptr] = st0 - sti; + this.st[this.stack_ptr[0]] = st0 - sti; break; case 5: // fsubr - this.st[this.stack_ptr] = sti - st0; + this.st[this.stack_ptr[0]] = sti - st0; break; case 6: // fdiv - this.st[this.stack_ptr] = st0 / sti; + this.st[this.stack_ptr[0]] = st0 / sti; break; case 7: // fdivr - this.st[this.stack_ptr] = sti / st0; + this.st[this.stack_ptr[0]] = sti / st0; break; default: dbg_assert(false); @@ -729,11 +730,11 @@ FPU.prototype.op_D8_mem = function(mod, addr) { case 0: // fadd - this.st[this.stack_ptr] = st0 + m32; + this.st[this.stack_ptr[0]] = st0 + m32; break; case 1: // fmul - this.st[this.stack_ptr] = st0 * m32; + this.st[this.stack_ptr[0]] = st0 * m32; break; case 2: // fcom @@ -746,19 +747,19 @@ FPU.prototype.op_D8_mem = function(mod, addr) break; case 4: // fsub - this.st[this.stack_ptr] = st0 - m32; + this.st[this.stack_ptr[0]] = st0 - m32; break; case 5: // fsubr - this.st[this.stack_ptr] = m32 - st0; + this.st[this.stack_ptr[0]] = m32 - st0; break; case 6: // fdiv - this.st[this.stack_ptr] = st0 / m32; + this.st[this.stack_ptr[0]] = st0 / m32; break; case 7: // fdivr - this.st[this.stack_ptr] = m32 / st0; + this.st[this.stack_ptr[0]] = m32 / st0; break; default: dbg_assert(false); @@ -783,8 +784,8 @@ FPU.prototype.op_D9_reg = function(imm8) // fxch var sti = this.get_sti(low); - this.st[this.stack_ptr + low & 7] = this.get_st0(); - this.st[this.stack_ptr] = sti; + this.st[this.stack_ptr[0] + low & 7] = this.get_st0(); + this.st[this.stack_ptr[0]] = sti; break; case 2: switch(low) @@ -808,11 +809,11 @@ FPU.prototype.op_D9_reg = function(imm8) { case 0: // fchs - this.st[this.stack_ptr] = -st0; + this.st[this.stack_ptr[0]] = -st0; break; case 1: // fabs - this.st[this.stack_ptr] = Math.abs(st0); + this.st[this.stack_ptr[0]] = Math.abs(st0); break; case 4: this.ftst(st0); @@ -835,21 +836,21 @@ FPU.prototype.op_D9_reg = function(imm8) { case 0: // f2xm1 - this.st[this.stack_ptr] = Math.pow(2, st0) - 1; + this.st[this.stack_ptr[0]] = Math.pow(2, st0) - 1; break; case 1: // fyl2x - this.st[this.stack_ptr + 1 & 7] = this.get_sti(1) * Math.log(st0) / Math.LN2; + this.st[this.stack_ptr[0] + 1 & 7] = this.get_sti(1) * Math.log(st0) / Math.LN2; this.pop(); break; case 2: // fptan - this.st[this.stack_ptr] = Math.tan(st0); + this.st[this.stack_ptr[0]] = Math.tan(st0); this.push(1); // no bug: push constant 1 break; case 3: // fpatan - this.st[this.stack_ptr + 1 & 7] = Math.atan2(this.get_sti(1), st0); + this.st[this.stack_ptr[0] + 1 & 7] = Math.atan2(this.get_sti(1), st0); this.pop(); break; case 4: @@ -857,16 +858,16 @@ FPU.prototype.op_D9_reg = function(imm8) break; case 5: // fprem1 - this.st[this.stack_ptr] = st0 % this.get_sti(1); + this.st[this.stack_ptr[0]] = st0 % this.get_sti(1); break; case 6: // fdecstp - this.stack_ptr = this.stack_ptr - 1 & 7; + this.stack_ptr[0] = this.stack_ptr[0] - 1 & 7; this.status_word &= ~FPU_C1; break; case 7: // fincstp - this.stack_ptr = this.stack_ptr + 1 & 7; + this.stack_ptr[0] = this.stack_ptr[0] + 1 & 7; this.status_word &= ~FPU_C1; break; default: @@ -882,7 +883,7 @@ FPU.prototype.op_D9_reg = function(imm8) // fprem var st1 = this.get_sti(1); var fprem_quotient = Math.trunc(st0 / st1); - this.st[this.stack_ptr] = st0 % st1; + this.st[this.stack_ptr[0]] = st0 % st1; this.status_word &= ~(FPU_C0 | FPU_C1 | FPU_C3); if (fprem_quotient & 1) { @@ -899,29 +900,29 @@ FPU.prototype.op_D9_reg = function(imm8) break; case 1: // fyl2xp1: y * log2(x+1) and pop - this.st[this.stack_ptr + 1 & 7] = this.get_sti(1) * Math.log(st0 + 1) / Math.LN2; + this.st[this.stack_ptr[0] + 1 & 7] = this.get_sti(1) * Math.log(st0 + 1) / Math.LN2; this.pop(); break; case 2: - this.st[this.stack_ptr] = Math.sqrt(st0); + this.st[this.stack_ptr[0]] = Math.sqrt(st0); break; case 3: - this.st[this.stack_ptr] = Math.sin(st0); + this.st[this.stack_ptr[0]] = Math.sin(st0); this.push(Math.cos(st0)); break; case 4: // frndint - this.st[this.stack_ptr] = this.integer_round(st0); + this.st[this.stack_ptr[0]] = this.integer_round(st0); break; case 5: // fscale - this.st[this.stack_ptr] = st0 * Math.pow(2, this.truncate(this.get_sti(1))); + this.st[this.stack_ptr[0]] = st0 * Math.pow(2, this.truncate(this.get_sti(1))); break; case 6: - this.st[this.stack_ptr] = Math.sin(st0); + this.st[this.stack_ptr[0]] = Math.sin(st0); break; case 7: - this.st[this.stack_ptr] = Math.cos(st0); + this.st[this.stack_ptr[0]] = Math.cos(st0); break; default: dbg_assert(false); @@ -989,32 +990,32 @@ FPU.prototype.op_DA_reg = function(imm8) // fcmovb if(this.cpu.test_b()) { - this.st[this.stack_ptr] = this.get_sti(low); - this.stack_empty[0] &= ~(1 << this.stack_ptr); + this.st[this.stack_ptr[0]] = this.get_sti(low); + this.stack_empty[0] &= ~(1 << this.stack_ptr[0]); } break; case 1: // fcmove if(this.cpu.test_z()) { - this.st[this.stack_ptr] = this.get_sti(low); - this.stack_empty[0] &= ~(1 << this.stack_ptr); + this.st[this.stack_ptr[0]] = this.get_sti(low); + this.stack_empty[0] &= ~(1 << this.stack_ptr[0]); } break; case 2: // fcmovbe if(this.cpu.test_be()) { - this.st[this.stack_ptr] = this.get_sti(low); - this.stack_empty[0] &= ~(1 << this.stack_ptr); + this.st[this.stack_ptr[0]] = this.get_sti(low); + this.stack_empty[0] &= ~(1 << this.stack_ptr[0]); } break; case 3: // fcmovu if(this.cpu.test_p()) { - this.st[this.stack_ptr] = this.get_sti(low); - this.stack_empty[0] &= ~(1 << this.stack_ptr); + this.st[this.stack_ptr[0]] = this.get_sti(low); + this.stack_empty[0] &= ~(1 << this.stack_ptr[0]); } break; case 5: @@ -1047,11 +1048,11 @@ FPU.prototype.op_DA_mem = function(mod, addr) { case 0: // fadd - this.st[this.stack_ptr] = st0 + m32; + this.st[this.stack_ptr[0]] = st0 + m32; break; case 1: // fmul - this.st[this.stack_ptr] = st0 * m32; + this.st[this.stack_ptr[0]] = st0 * m32; break; case 2: // fcom @@ -1064,19 +1065,19 @@ FPU.prototype.op_DA_mem = function(mod, addr) break; case 4: // fsub - this.st[this.stack_ptr] = st0 - m32; + this.st[this.stack_ptr[0]] = st0 - m32; break; case 5: // fsubr - this.st[this.stack_ptr] = m32 - st0; + this.st[this.stack_ptr[0]] = m32 - st0; break; case 6: // fdiv - this.st[this.stack_ptr] = st0 / m32; + this.st[this.stack_ptr[0]] = st0 / m32; break; case 7: // fdivr - this.st[this.stack_ptr] = m32 / st0; + this.st[this.stack_ptr[0]] = m32 / st0; break; default: dbg_assert(false); @@ -1096,32 +1097,32 @@ FPU.prototype.op_DB_reg = function(imm8) // fcmovnb if(!this.cpu.test_b()) { - this.st[this.stack_ptr] = this.get_sti(low); - this.stack_empty[0] &= ~(1 << this.stack_ptr); + this.st[this.stack_ptr[0]] = this.get_sti(low); + this.stack_empty[0] &= ~(1 << this.stack_ptr[0]); } break; case 1: // fcmovne if(!this.cpu.test_z()) { - this.st[this.stack_ptr] = this.get_sti(low); - this.stack_empty[0] &= ~(1 << this.stack_ptr); + this.st[this.stack_ptr[0]] = this.get_sti(low); + this.stack_empty[0] &= ~(1 << this.stack_ptr[0]); } break; case 2: // fcmovnbe if(!this.cpu.test_be()) { - this.st[this.stack_ptr] = this.get_sti(low); - this.stack_empty[0] &= ~(1 << this.stack_ptr); + this.st[this.stack_ptr[0]] = this.get_sti(low); + this.stack_empty[0] &= ~(1 << this.stack_ptr[0]); } break; case 3: // fcmovnu if(!this.cpu.test_p()) { - this.st[this.stack_ptr] = this.get_sti(low); - this.stack_empty[0] &= ~(1 << this.stack_ptr); + this.st[this.stack_ptr[0]] = this.get_sti(low); + this.stack_empty[0] &= ~(1 << this.stack_ptr[0]); } break; case 4: @@ -1223,7 +1224,7 @@ FPU.prototype.op_DC_reg = function(imm8) var mod = imm8 >> 3 & 7, low = imm8 & 7, - low_ptr = this.stack_ptr + low & 7, + low_ptr = this.stack_ptr[0] + low & 7, sti = this.get_sti(low), st0 = this.get_st0(); @@ -1279,11 +1280,11 @@ FPU.prototype.op_DC_mem = function(mod, addr) { case 0: // fadd - this.st[this.stack_ptr] = st0 + m64; + this.st[this.stack_ptr[0]] = st0 + m64; break; case 1: // fmul - this.st[this.stack_ptr] = st0 * m64; + this.st[this.stack_ptr[0]] = st0 * m64; break; case 2: // fcom @@ -1296,19 +1297,19 @@ FPU.prototype.op_DC_mem = function(mod, addr) break; case 4: // fsub - this.st[this.stack_ptr] = st0 - m64; + this.st[this.stack_ptr[0]] = st0 - m64; break; case 5: // fsubr - this.st[this.stack_ptr] = m64 - st0; + this.st[this.stack_ptr[0]] = m64 - st0; break; case 6: // fdiv - this.st[this.stack_ptr] = st0 / m64; + this.st[this.stack_ptr[0]] = st0 / m64; break; case 7: // fdivr - this.st[this.stack_ptr] = m64 / st0; + this.st[this.stack_ptr[0]] = m64 / st0; break; default: dbg_assert(false); @@ -1326,11 +1327,11 @@ FPU.prototype.op_DD_reg = function(imm8) { case 0: // ffree - this.stack_empty[0] |= 1 << (this.stack_ptr + low & 7); + this.stack_empty[0] |= 1 << (this.stack_ptr[0] + low & 7); break; case 2: // fst - this.st[this.stack_ptr + low & 7] = this.get_st0(); + this.st[this.stack_ptr[0] + low & 7] = this.get_st0(); break; case 3: // fstp @@ -1340,7 +1341,7 @@ FPU.prototype.op_DD_reg = function(imm8) } else { - this.st[this.stack_ptr + low & 7] = this.get_st0(); + this.st[this.stack_ptr[0] + low & 7] = this.get_st0(); this.pop(); } break; @@ -1409,7 +1410,7 @@ FPU.prototype.op_DE_reg = function(imm8) var mod = imm8 >> 3 & 7, low = imm8 & 7, - low_ptr = this.stack_ptr + low & 7, + low_ptr = this.stack_ptr[0] + low & 7, sti = this.get_sti(low), st0 = this.get_st0(); @@ -1475,11 +1476,11 @@ FPU.prototype.op_DE_mem = function(mod, addr) { case 0: // fadd - this.st[this.stack_ptr] = st0 + m16; + this.st[this.stack_ptr[0]] = st0 + m16; break; case 1: // fmul - this.st[this.stack_ptr] = st0 * m16; + this.st[this.stack_ptr[0]] = st0 * m16; break; case 2: // fcom @@ -1492,19 +1493,19 @@ FPU.prototype.op_DE_mem = function(mod, addr) break; case 4: // fsub - this.st[this.stack_ptr] = st0 - m16; + this.st[this.stack_ptr[0]] = st0 - m16; break; case 5: // fsubr - this.st[this.stack_ptr] = m16 - st0; + this.st[this.stack_ptr[0]] = m16 - st0; break; case 6: // fdiv - this.st[this.stack_ptr] = st0 / m16; + this.st[this.stack_ptr[0]] = st0 / m16; break; case 7: // fdivr - this.st[this.stack_ptr] = m16 / st0; + this.st[this.stack_ptr[0]] = m16 / st0; break; default: dbg_assert(false); diff --git a/src/misc_instr.js b/src/misc_instr.js index 83d8918f..3f7e5baa 100644 --- a/src/misc_instr.js +++ b/src/misc_instr.js @@ -496,7 +496,7 @@ CPU.prototype.fxsave = function(addr) for(let i = 0; i < 8; i++) { - this.fpu.store_m80(addr + 32 + (i << 4) | 0, this.fpu.st[this.fpu.stack_ptr + i & 7]); + this.fpu.store_m80(addr + 32 + (i << 4) | 0, this.fpu.st[this.fpu.stack_ptr[0] + i & 7]); } // If the OSFXSR bit in control register CR4 is not set, the FXSAVE @@ -537,7 +537,7 @@ CPU.prototype.fxrstor = function(addr) for(let i = 0; i < 8; i++) { - this.fpu.st[this.fpu.stack_ptr + i & 7] = this.fpu.load_m80(addr + 32 + (i << 4) | 0); + this.fpu.st[this.fpu.stack_ptr[0] + i & 7] = this.fpu.load_m80(addr + 32 + (i << 4) | 0); } for(let i = 0; i < 8; i++) diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index 6c2ca05a..833f108c 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -90,6 +90,8 @@ double_t* const fpu_float64 = (double_t* const) 960; uint8_t* const fpu_float64_byte = (uint8_t* const) 960; int32_t* const fpu_float64_int = (int32_t* const) 960; +uint32_t* const fpu_stack_ptr = (uint32_t* const) 1032; + 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; From 251588d601ba7623b49c2c621d26053355532546 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Thu, 3 Aug 2017 13:46:49 +0530 Subject: [PATCH 0103/2137] port fpu_fcomi mostly as a test to see if doubles are reflecting correctly on the wasm side --- src/fpu.js | 1 + src/native/fpu.c | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/fpu.js b/src/fpu.js index 195c754f..a4fb6465 100644 --- a/src/fpu.js +++ b/src/fpu.js @@ -104,6 +104,7 @@ function FPU(cpu) FPU.prototype.wasm_patch = function(wm) { this.set_tag_word = wm.funcs["_fpu_set_tag_word"]; + this.fcomi = wm.funcs["_fpu_fcomi"]; }; FPU.prototype.get_state = function() diff --git a/src/native/fpu.c b/src/native/fpu.c index 08997671..4f1b53aa 100644 --- a/src/native/fpu.c +++ b/src/native/fpu.c @@ -17,3 +17,27 @@ void fpu_set_tag_word(int32_t tag_word) *fpu_stack_empty |= (tag_word >> i) & (tag_word >> (i + 1)) & 1 << i; } } + +void fpu_fcomi(double_t y) +{ + double_t x = fpu_st[*fpu_stack_ptr]; + *flags_changed &= ~(1 | FLAG_PARITY | FLAG_ZERO); + *flags &= ~(1 | FLAG_PARITY | FLAG_ZERO); + + if(x > y) + { + } + else if(y > x) + { + *flags |= 1; + } + else if(x == y) + { + *flags |= FLAG_ZERO; + } + else + { + *flags |= 1 | FLAG_PARITY | FLAG_ZERO; + } +} + From 11a25e4049b30df740e70dfadaa05428a2955923 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Fri, 4 Aug 2017 18:11:14 +0530 Subject: [PATCH 0104/2137] move fpu.control_word,status_word,opcode to wasm mem (till offset 1036) --- src/fpu.js | 99 +++++++++++++++++++----------------- src/misc_instr.js | 8 +-- src/native/global_pointers.h | 3 ++ 3 files changed, 58 insertions(+), 52 deletions(-) diff --git a/src/fpu.js b/src/fpu.js index a4fb6465..ccfb2af8 100644 --- a/src/fpu.js +++ b/src/fpu.js @@ -81,11 +81,14 @@ function FPU(cpu) this.stack_ptr = new Uint32Array(cpu.wm.mem.buffer, 1032, 1); this.stack_ptr[0] = 0; - this.control_word = 0x37F; - this.status_word = 0; + this.control_word = new Int32Array(cpu.wm.mem.buffer, 1036, 1); + this.control_word[0] = 0x37F; + this.status_word = new Int32Array(cpu.wm.mem.buffer, 1040, 1); + this.status_word[0] = 0; this.fpu_ip = 0; this.fpu_ip_selector = 0; - this.fpu_opcode = 0; + this.fpu_opcode = new Int32Array(cpu.wm.mem.buffer, 1044, 1); + this.fpu_opcode[0] = 0; this.fpu_dp = 0; this.fpu_dp_selector = 0; @@ -114,13 +117,13 @@ FPU.prototype.get_state = function() state[0] = this.st; state[1] = this.stack_empty[0]; state[2] = this.stack_ptr[0]; - state[3] = this.control_word; + state[3] = this.control_word[0]; state[4] = this.fpu_dp_selector; state[5] = this.fpu_ip; state[6] = this.fpu_ip_selector; state[7] = this.fpu_dp; state[8] = this.fpu_dp_selector; - state[9] = this.fpu_opcode; + state[9] = this.fpu_opcode[0]; return state; }; @@ -130,13 +133,13 @@ FPU.prototype.set_state = function(state) this.st.set(state[0]); this.stack_empty[0] = state[1]; this.stack_ptr[0] = state[2]; - this.control_word = state[3]; + this.control_word[0] = state[3]; this.fpu_dp_selector = state[4]; this.fpu_ip = state[5]; this.fpu_ip_selector = state[6]; this.fpu_dp = state[7]; this.fpu_dp_selector = state[8]; - this.fpu_opcode = state[9]; + this.fpu_opcode[0] = state[9]; }; FPU.prototype.fpu_unimpl = function() @@ -149,34 +152,34 @@ FPU.prototype.fpu_unimpl = function() FPU.prototype.stack_fault = function() { // TODO: Interrupt - this.status_word |= FPU_EX_SF | FPU_EX_I; + this.status_word[0] |= FPU_EX_SF | FPU_EX_I; } FPU.prototype.invalid_arithmatic = function() { - this.status_word |= FPU_EX_I; + this.status_word[0] |= FPU_EX_I; } FPU.prototype.fcom = function(y) { var x = this.get_st0(); - this.status_word &= ~FPU_RESULT_FLAGS; + this.status_word[0] &= ~FPU_RESULT_FLAGS; if(x > y) { } else if(y > x) { - this.status_word |= FPU_C0; + this.status_word[0] |= FPU_C0; } else if(x === y) { - this.status_word |= FPU_C3; + this.status_word[0] |= FPU_C3; } else { - this.status_word |= FPU_C0 | FPU_C2 | FPU_C3; + this.status_word[0] |= FPU_C0 | FPU_C2 | FPU_C3; } } @@ -219,19 +222,19 @@ FPU.prototype.fucomi = function(y) FPU.prototype.ftst = function(x) { - this.status_word &= ~FPU_RESULT_FLAGS; + this.status_word[0] &= ~FPU_RESULT_FLAGS; if(isNaN(x)) { - this.status_word |= FPU_C3 | FPU_C2 | FPU_C0; + this.status_word[0] |= FPU_C3 | FPU_C2 | FPU_C0; } else if(x === 0) { - this.status_word |= FPU_C3; + this.status_word[0] |= FPU_C3; } else if(x < 0) { - this.status_word |= FPU_C0; + this.status_word[0] |= FPU_C0; } // TODO: unordered (x is nan, etc) @@ -239,28 +242,28 @@ FPU.prototype.ftst = function(x) FPU.prototype.fxam = function(x) { - this.status_word &= ~FPU_RESULT_FLAGS; - this.status_word |= this.sign(0) << 9; + this.status_word[0] &= ~FPU_RESULT_FLAGS; + this.status_word[0] |= this.sign(0) << 9; if(this.stack_empty[0] >> this.stack_ptr[0] & 1) { - this.status_word |= FPU_C3 | FPU_C0; + this.status_word[0] |= FPU_C3 | FPU_C0; } else if(isNaN(x)) { - this.status_word |= FPU_C0; + this.status_word[0] |= FPU_C0; } else if(x === 0) { - this.status_word |= FPU_C3; + this.status_word[0] |= FPU_C3; } else if(x === Infinity || x === -Infinity) { - this.status_word |= FPU_C2 | FPU_C0; + this.status_word[0] |= FPU_C2 | FPU_C0; } else { - this.status_word |= FPU_C2; + this.status_word[0] |= FPU_C2; } // TODO: // Unsupported, Denormal @@ -268,11 +271,11 @@ FPU.prototype.fxam = function(x) FPU.prototype.finit = function() { - this.control_word = 0x37F; - this.status_word = 0; + this.control_word[0] = 0x37F; + this.status_word[0] = 0; this.fpu_ip = 0; this.fpu_dp = 0; - this.fpu_opcode = 0; + this.fpu_opcode[0] = 0; this.stack_empty[0] = 0xFF; this.stack_ptr[0] = 0; @@ -280,12 +283,12 @@ FPU.prototype.finit = function() FPU.prototype.load_status_word = function() { - return this.status_word & ~(7 << 11) | this.stack_ptr[0] << 11; + return this.status_word[0] & ~(7 << 11) | this.stack_ptr[0] << 11; } FPU.prototype.set_status_word = function(sw) { - this.status_word = sw & ~(7 << 11); + this.status_word[0] = sw & ~(7 << 11); this.stack_ptr[0] = sw >> 11 & 7; } @@ -335,14 +338,14 @@ FPU.prototype.fstenv = function(addr) { this.cpu.writable_or_pagefault(addr, 26); - this.cpu.safe_write16(addr, this.control_word); + this.cpu.safe_write16(addr, this.control_word[0]); this.cpu.safe_write16(addr + 4, this.load_status_word()); this.cpu.safe_write16(addr + 8, this.load_tag_word()); this.cpu.safe_write32(addr + 12, this.fpu_ip); this.cpu.safe_write16(addr + 16, this.fpu_ip_selector); - this.cpu.safe_write16(addr + 18, this.fpu_opcode); + this.cpu.safe_write16(addr + 18, this.fpu_opcode[0]); this.cpu.safe_write32(addr + 20, this.fpu_dp); this.cpu.safe_write16(addr + 24, this.fpu_dp_selector); } @@ -356,14 +359,14 @@ FPU.prototype.fldenv = function(addr) { if(this.cpu.is_osize_32()) { - this.control_word = this.cpu.safe_read16(addr); + this.control_word[0] = this.cpu.safe_read16(addr); this.set_status_word(this.cpu.safe_read16(addr + 4)); this.set_tag_word(this.cpu.safe_read16(addr + 8)); this.fpu_ip = this.cpu.safe_read32s(addr + 12); this.fpu_ip_selector = this.cpu.safe_read16(addr + 16); - this.fpu_opcode = this.cpu.safe_read16(addr + 18); + this.fpu_opcode[0] = this.cpu.safe_read16(addr + 18); this.fpu_dp = this.cpu.safe_read32s(addr + 20); this.fpu_dp_selector = this.cpu.safe_read16(addr + 24); } @@ -420,7 +423,7 @@ FPU.prototype.fxtract = function() FPU.prototype.integer_round = function(f) { - var rc = this.control_word >> 10 & 3; + var rc = this.control_word[0] >> 10 & 3; if(rc === 0) { @@ -458,13 +461,13 @@ FPU.prototype.push = function(x) if(this.stack_empty[0] >> this.stack_ptr[0] & 1) { - this.status_word &= ~FPU_C1; + this.status_word[0] &= ~FPU_C1; this.stack_empty[0] &= ~(1 << this.stack_ptr[0]); this.st[this.stack_ptr[0]] = x; } else { - this.status_word |= FPU_C1; + this.status_word[0] |= FPU_C1; this.stack_fault(); this.st[this.stack_ptr[0]] = this.indefinite_nan; } @@ -484,7 +487,7 @@ FPU.prototype.get_sti = function(i) if(this.stack_empty[0] >> i & 1) { - this.status_word &= ~FPU_C1; + this.status_word[0] &= ~FPU_C1; this.stack_fault(); return this.indefinite_nan; } @@ -498,7 +501,7 @@ FPU.prototype.get_st0 = function() { if(this.stack_empty[0] >> this.stack_ptr[0] & 1) { - this.status_word &= ~FPU_C1; + this.status_word[0] &= ~FPU_C1; this.stack_fault(); return this.indefinite_nan; } @@ -864,12 +867,12 @@ FPU.prototype.op_D9_reg = function(imm8) case 6: // fdecstp this.stack_ptr[0] = this.stack_ptr[0] - 1 & 7; - this.status_word &= ~FPU_C1; + this.status_word[0] &= ~FPU_C1; break; case 7: // fincstp this.stack_ptr[0] = this.stack_ptr[0] + 1 & 7; - this.status_word &= ~FPU_C1; + this.status_word[0] &= ~FPU_C1; break; default: dbg_assert(false); @@ -886,18 +889,18 @@ FPU.prototype.op_D9_reg = function(imm8) var fprem_quotient = Math.trunc(st0 / st1); this.st[this.stack_ptr[0]] = st0 % st1; - this.status_word &= ~(FPU_C0 | FPU_C1 | FPU_C3); + this.status_word[0] &= ~(FPU_C0 | FPU_C1 | FPU_C3); if (fprem_quotient & 1) { - this.status_word |= FPU_C1; + this.status_word[0] |= FPU_C1; } if (fprem_quotient & (1 << 1)) { - this.status_word |= FPU_C3; + this.status_word[0] |= FPU_C3; } if (fprem_quotient & (1 << 2)) { - this.status_word |= FPU_C0; + this.status_word[0] |= FPU_C0; } - this.status_word &= ~FPU_C2; + this.status_word[0] &= ~FPU_C2; break; case 1: // fyl2xp1: y * log2(x+1) and pop @@ -964,14 +967,14 @@ FPU.prototype.op_D9_mem = function(mod, addr) case 5: // fldcw var word = this.cpu.safe_read16(addr); - this.control_word = word; + this.control_word[0] = word; break; case 6: this.fstenv(addr); break; case 7: // fstcw - this.cpu.safe_write16(addr, this.control_word); + this.cpu.safe_write16(addr, this.control_word[0]); break; default: dbg_assert(false); @@ -1144,7 +1147,7 @@ FPU.prototype.op_DB_reg = function(imm8) else if(imm8 === 0xE2) { // fclex - this.status_word = 0; + this.status_word[0] = 0; } else { diff --git a/src/misc_instr.js b/src/misc_instr.js index 3f7e5baa..b85706f7 100644 --- a/src/misc_instr.js +++ b/src/misc_instr.js @@ -482,10 +482,10 @@ CPU.prototype.fxsave = function(addr) { this.writable_or_pagefault(addr, 512); - this.safe_write16(addr + 0 | 0, this.fpu.control_word); + this.safe_write16(addr + 0 | 0, this.fpu.control_word[0]); this.safe_write16(addr + 2 | 0, this.fpu.load_status_word()); this.safe_write8( addr + 4 | 0, ~this.fpu.stack_empty[0] & 0xFF); - this.safe_write16(addr + 6 | 0, this.fpu.fpu_opcode); + this.safe_write16(addr + 6 | 0, this.fpu.fpu_opcode[0]); this.safe_write32(addr + 8 | 0, this.fpu.fpu_ip); this.safe_write16(addr + 12 | 0, this.fpu.fpu_ip_selector); this.safe_write32(addr + 16 | 0, this.fpu.fpu_dp); @@ -524,10 +524,10 @@ CPU.prototype.fxrstor = function(addr) this.trigger_gp(0); } - this.fpu.control_word = this.safe_read16(addr + 0 | 0); + this.fpu.control_word[0] = this.safe_read16(addr + 0 | 0); this.fpu.set_status_word(this.safe_read16(addr + 2 | 0)); this.fpu.stack_empty[0] = ~this.safe_read8(addr + 4 | 0) & 0xFF; - this.fpu.fpu_opcode = this.safe_read16(addr + 6 | 0); + this.fpu.fpu_opcode[0] = this.safe_read16(addr + 6 | 0); this.fpu.fpu_ip = this.safe_read32s(addr + 8 | 0); this.fpu.fpu_ip = this.safe_read16(addr + 12 | 0); this.fpu.fpu_dp = this.safe_read32s(addr + 16 | 0); diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index 833f108c..ef46e8dd 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -91,6 +91,9 @@ uint8_t* const fpu_float64_byte = (uint8_t* const) 960; int32_t* const fpu_float64_int = (int32_t* const) 960; uint32_t* const fpu_stack_ptr = (uint32_t* const) 1032; +int32_t* const fpu_control_word = (int32_t* const) 1036; +int32_t* const fpu_status_word = (int32_t* const) 1040; +int32_t* const fpu_opcode = (int32_t* const) 1044; double_t* const fpu_st = (double_t* const) 968; uint8_t* const fpu_st8 = (uint8_t* const) 968; From 7e2ec4c6f2e3133829bce17412ed656268ec683e Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Fri, 4 Aug 2017 18:34:22 +0530 Subject: [PATCH 0105/2137] move fpu.ip,ip_selector to wasm mem (offsets 1048 and 1052) --- src/fpu.js | 24 +++++++++++++----------- src/misc_instr.js | 8 ++++---- src/native/global_pointers.h | 2 ++ 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/fpu.js b/src/fpu.js index ccfb2af8..1fe6af64 100644 --- a/src/fpu.js +++ b/src/fpu.js @@ -85,8 +85,10 @@ function FPU(cpu) this.control_word[0] = 0x37F; this.status_word = new Int32Array(cpu.wm.mem.buffer, 1040, 1); this.status_word[0] = 0; - this.fpu_ip = 0; - this.fpu_ip_selector = 0; + this.fpu_ip = new Int32Array(cpu.wm.mem.buffer, 1048, 1); + this.fpu_ip[0] = 0; + this.fpu_ip_selector = new Int32Array(cpu.wm.mem.buffer, 1052, 1); + this.fpu_ip_selector[0] = 0; this.fpu_opcode = new Int32Array(cpu.wm.mem.buffer, 1044, 1); this.fpu_opcode[0] = 0; this.fpu_dp = 0; @@ -119,8 +121,8 @@ FPU.prototype.get_state = function() state[2] = this.stack_ptr[0]; state[3] = this.control_word[0]; state[4] = this.fpu_dp_selector; - state[5] = this.fpu_ip; - state[6] = this.fpu_ip_selector; + state[5] = this.fpu_ip[0]; + state[6] = this.fpu_ip_selector[0]; state[7] = this.fpu_dp; state[8] = this.fpu_dp_selector; state[9] = this.fpu_opcode[0]; @@ -135,8 +137,8 @@ FPU.prototype.set_state = function(state) this.stack_ptr[0] = state[2]; this.control_word[0] = state[3]; this.fpu_dp_selector = state[4]; - this.fpu_ip = state[5]; - this.fpu_ip_selector = state[6]; + this.fpu_ip[0] = state[5]; + this.fpu_ip_selector[0] = state[6]; this.fpu_dp = state[7]; this.fpu_dp_selector = state[8]; this.fpu_opcode[0] = state[9]; @@ -273,7 +275,7 @@ FPU.prototype.finit = function() { this.control_word[0] = 0x37F; this.status_word[0] = 0; - this.fpu_ip = 0; + this.fpu_ip[0] = 0; this.fpu_dp = 0; this.fpu_opcode[0] = 0; @@ -343,8 +345,8 @@ FPU.prototype.fstenv = function(addr) this.cpu.safe_write16(addr + 4, this.load_status_word()); this.cpu.safe_write16(addr + 8, this.load_tag_word()); - this.cpu.safe_write32(addr + 12, this.fpu_ip); - this.cpu.safe_write16(addr + 16, this.fpu_ip_selector); + this.cpu.safe_write32(addr + 12, this.fpu_ip[0]); + this.cpu.safe_write16(addr + 16, this.fpu_ip_selector[0]); this.cpu.safe_write16(addr + 18, this.fpu_opcode[0]); this.cpu.safe_write32(addr + 20, this.fpu_dp); this.cpu.safe_write16(addr + 24, this.fpu_dp_selector); @@ -364,8 +366,8 @@ FPU.prototype.fldenv = function(addr) this.set_status_word(this.cpu.safe_read16(addr + 4)); this.set_tag_word(this.cpu.safe_read16(addr + 8)); - this.fpu_ip = this.cpu.safe_read32s(addr + 12); - this.fpu_ip_selector = this.cpu.safe_read16(addr + 16); + this.fpu_ip[0] = this.cpu.safe_read32s(addr + 12); + this.fpu_ip_selector[0] = this.cpu.safe_read16(addr + 16); this.fpu_opcode[0] = this.cpu.safe_read16(addr + 18); this.fpu_dp = this.cpu.safe_read32s(addr + 20); this.fpu_dp_selector = this.cpu.safe_read16(addr + 24); diff --git a/src/misc_instr.js b/src/misc_instr.js index b85706f7..de4f3f06 100644 --- a/src/misc_instr.js +++ b/src/misc_instr.js @@ -486,8 +486,8 @@ CPU.prototype.fxsave = function(addr) this.safe_write16(addr + 2 | 0, this.fpu.load_status_word()); this.safe_write8( addr + 4 | 0, ~this.fpu.stack_empty[0] & 0xFF); this.safe_write16(addr + 6 | 0, this.fpu.fpu_opcode[0]); - this.safe_write32(addr + 8 | 0, this.fpu.fpu_ip); - this.safe_write16(addr + 12 | 0, this.fpu.fpu_ip_selector); + this.safe_write32(addr + 8 | 0, this.fpu.fpu_ip[0]); + this.safe_write16(addr + 12 | 0, this.fpu.fpu_ip_selector[0]); this.safe_write32(addr + 16 | 0, this.fpu.fpu_dp); this.safe_write16(addr + 20 | 0, this.fpu.fpu_dp_selector); @@ -528,8 +528,8 @@ CPU.prototype.fxrstor = function(addr) this.fpu.set_status_word(this.safe_read16(addr + 2 | 0)); this.fpu.stack_empty[0] = ~this.safe_read8(addr + 4 | 0) & 0xFF; this.fpu.fpu_opcode[0] = this.safe_read16(addr + 6 | 0); - this.fpu.fpu_ip = this.safe_read32s(addr + 8 | 0); - this.fpu.fpu_ip = this.safe_read16(addr + 12 | 0); + this.fpu.fpu_ip[0] = this.safe_read32s(addr + 8 | 0); + this.fpu.fpu_ip[0] = this.safe_read16(addr + 12 | 0); this.fpu.fpu_dp = this.safe_read32s(addr + 16 | 0); this.fpu.fpu_dp_selector = this.safe_read16(addr + 20 | 0); diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index ef46e8dd..a4d0b9e0 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -94,6 +94,8 @@ uint32_t* const fpu_stack_ptr = (uint32_t* const) 1032; int32_t* const fpu_control_word = (int32_t* const) 1036; int32_t* const fpu_status_word = (int32_t* const) 1040; int32_t* const fpu_opcode = (int32_t* const) 1044; +int32_t* const fpu_ip = (int32_t* const) 1048; +int32_t* const fpu_ip_selector = (int32_t* const) 1052; double_t* const fpu_st = (double_t* const) 968; uint8_t* const fpu_st8 = (uint8_t* const) 968; From c06899f99112167e80c46ac58ba24be5796a8994 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Fri, 4 Aug 2017 19:03:04 +0530 Subject: [PATCH 0106/2137] move fpu.dp,dp_selector to wasm mem (offsets 1056 and 1060) --- src/fpu.js | 28 +++++++++++++++------------- src/misc_instr.js | 8 ++++---- src/native/global_pointers.h | 2 ++ 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/fpu.js b/src/fpu.js index 1fe6af64..20df0d60 100644 --- a/src/fpu.js +++ b/src/fpu.js @@ -91,8 +91,10 @@ function FPU(cpu) this.fpu_ip_selector[0] = 0; this.fpu_opcode = new Int32Array(cpu.wm.mem.buffer, 1044, 1); this.fpu_opcode[0] = 0; - this.fpu_dp = 0; - this.fpu_dp_selector = 0; + this.fpu_dp = new Int32Array(cpu.wm.mem.buffer, 1056, 1); + this.fpu_dp[0] = 0; + this.fpu_dp_selector = new Int32Array(cpu.wm.mem.buffer, 1060, 1); + this.fpu_dp_selector[0] = 0; /** @const */ this.indefinite_nan = NaN; @@ -120,11 +122,11 @@ FPU.prototype.get_state = function() state[1] = this.stack_empty[0]; state[2] = this.stack_ptr[0]; state[3] = this.control_word[0]; - state[4] = this.fpu_dp_selector; + state[4] = this.fpu_dp_selector[0]; state[5] = this.fpu_ip[0]; state[6] = this.fpu_ip_selector[0]; - state[7] = this.fpu_dp; - state[8] = this.fpu_dp_selector; + state[7] = this.fpu_dp[0]; + state[8] = this.fpu_dp_selector[0]; state[9] = this.fpu_opcode[0]; return state; @@ -136,11 +138,11 @@ FPU.prototype.set_state = function(state) this.stack_empty[0] = state[1]; this.stack_ptr[0] = state[2]; this.control_word[0] = state[3]; - this.fpu_dp_selector = state[4]; + this.fpu_dp_selector[0] = state[4]; this.fpu_ip[0] = state[5]; this.fpu_ip_selector[0] = state[6]; - this.fpu_dp = state[7]; - this.fpu_dp_selector = state[8]; + this.fpu_dp[0] = state[7]; + this.fpu_dp_selector[0] = state[8]; this.fpu_opcode[0] = state[9]; }; @@ -276,7 +278,7 @@ FPU.prototype.finit = function() this.control_word[0] = 0x37F; this.status_word[0] = 0; this.fpu_ip[0] = 0; - this.fpu_dp = 0; + this.fpu_dp[0] = 0; this.fpu_opcode[0] = 0; this.stack_empty[0] = 0xFF; @@ -348,8 +350,8 @@ FPU.prototype.fstenv = function(addr) this.cpu.safe_write32(addr + 12, this.fpu_ip[0]); this.cpu.safe_write16(addr + 16, this.fpu_ip_selector[0]); this.cpu.safe_write16(addr + 18, this.fpu_opcode[0]); - this.cpu.safe_write32(addr + 20, this.fpu_dp); - this.cpu.safe_write16(addr + 24, this.fpu_dp_selector); + this.cpu.safe_write32(addr + 20, this.fpu_dp[0]); + this.cpu.safe_write16(addr + 24, this.fpu_dp_selector[0]); } else { @@ -369,8 +371,8 @@ FPU.prototype.fldenv = function(addr) this.fpu_ip[0] = this.cpu.safe_read32s(addr + 12); this.fpu_ip_selector[0] = this.cpu.safe_read16(addr + 16); this.fpu_opcode[0] = this.cpu.safe_read16(addr + 18); - this.fpu_dp = this.cpu.safe_read32s(addr + 20); - this.fpu_dp_selector = this.cpu.safe_read16(addr + 24); + this.fpu_dp[0] = this.cpu.safe_read32s(addr + 20); + this.fpu_dp_selector[0] = this.cpu.safe_read16(addr + 24); } else { diff --git a/src/misc_instr.js b/src/misc_instr.js index de4f3f06..a07da414 100644 --- a/src/misc_instr.js +++ b/src/misc_instr.js @@ -488,8 +488,8 @@ CPU.prototype.fxsave = function(addr) this.safe_write16(addr + 6 | 0, this.fpu.fpu_opcode[0]); this.safe_write32(addr + 8 | 0, this.fpu.fpu_ip[0]); this.safe_write16(addr + 12 | 0, this.fpu.fpu_ip_selector[0]); - this.safe_write32(addr + 16 | 0, this.fpu.fpu_dp); - this.safe_write16(addr + 20 | 0, this.fpu.fpu_dp_selector); + this.safe_write32(addr + 16 | 0, this.fpu.fpu_dp[0]); + this.safe_write16(addr + 20 | 0, this.fpu.fpu_dp_selector[0]); this.safe_write32(addr + 24 | 0, this.mxcsr); this.safe_write32(addr + 28 | 0, MXCSR_MASK); @@ -530,8 +530,8 @@ CPU.prototype.fxrstor = function(addr) this.fpu.fpu_opcode[0] = this.safe_read16(addr + 6 | 0); this.fpu.fpu_ip[0] = this.safe_read32s(addr + 8 | 0); this.fpu.fpu_ip[0] = this.safe_read16(addr + 12 | 0); - this.fpu.fpu_dp = this.safe_read32s(addr + 16 | 0); - this.fpu.fpu_dp_selector = this.safe_read16(addr + 20 | 0); + this.fpu.fpu_dp[0] = this.safe_read32s(addr + 16 | 0); + this.fpu.fpu_dp_selector[0] = this.safe_read16(addr + 20 | 0); this.mxcsr = new_mxcsr; diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index a4d0b9e0..d96fa5c1 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -96,6 +96,8 @@ int32_t* const fpu_status_word = (int32_t* const) 1040; int32_t* const fpu_opcode = (int32_t* const) 1044; int32_t* const fpu_ip = (int32_t* const) 1048; int32_t* const fpu_ip_selector = (int32_t* const) 1052; +int32_t* const fpu_dp = (int32_t* const) 1056; +int32_t* const fpu_dp_selector = (int32_t* const) 1060; double_t* const fpu_st = (double_t* const) 968; uint8_t* const fpu_st8 = (uint8_t* const) 968; From 35be607cd3810057f6132f47551ac415c961afc9 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Fri, 4 Aug 2017 19:04:31 +0530 Subject: [PATCH 0107/2137] fix usage of mxcsr --- src/instructions.js | 4 ++-- src/misc_instr.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/instructions.js b/src/instructions.js index 53558a3d..d2cf9f9a 100644 --- a/src/instructions.js +++ b/src/instructions.js @@ -3606,13 +3606,13 @@ t[0xAE] = cpu => { cpu.read_modrm_byte(); dbg_log("Invalid mxcsr bits: " + h((new_mxcsr & ~MXCSR_MASK) >>> 0, 8)); cpu.trigger_gp(0); } - cpu.mxcsr = new_mxcsr; + cpu.mxcsr[0] = new_mxcsr; break; case 3: // stmxcsr if(cpu.modrm_byte >= 0xC0) cpu.trigger_ud(); var addr = cpu.modrm_resolve(cpu.modrm_byte); - cpu.safe_write32(addr, cpu.mxcsr); + cpu.safe_write32(addr, cpu.mxcsr[0]); break; case 5: diff --git a/src/misc_instr.js b/src/misc_instr.js index a07da414..8394a378 100644 --- a/src/misc_instr.js +++ b/src/misc_instr.js @@ -491,7 +491,7 @@ CPU.prototype.fxsave = function(addr) this.safe_write32(addr + 16 | 0, this.fpu.fpu_dp[0]); this.safe_write16(addr + 20 | 0, this.fpu.fpu_dp_selector[0]); - this.safe_write32(addr + 24 | 0, this.mxcsr); + this.safe_write32(addr + 24 | 0, this.mxcsr[0]); this.safe_write32(addr + 28 | 0, MXCSR_MASK); for(let i = 0; i < 8; i++) @@ -533,7 +533,7 @@ CPU.prototype.fxrstor = function(addr) this.fpu.fpu_dp[0] = this.safe_read32s(addr + 16 | 0); this.fpu.fpu_dp_selector[0] = this.safe_read16(addr + 20 | 0); - this.mxcsr = new_mxcsr; + this.mxcsr[0] = new_mxcsr; for(let i = 0; i < 8; i++) { From 30b8b40d56319538c909d6f47440cfed51210b68 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Fri, 4 Aug 2017 19:13:09 +0530 Subject: [PATCH 0108/2137] port fpu_load_status_word --- src/fpu.js | 1 + src/native/fpu.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/fpu.js b/src/fpu.js index 20df0d60..c31014a5 100644 --- a/src/fpu.js +++ b/src/fpu.js @@ -112,6 +112,7 @@ FPU.prototype.wasm_patch = function(wm) { this.set_tag_word = wm.funcs["_fpu_set_tag_word"]; this.fcomi = wm.funcs["_fpu_fcomi"]; + this.load_status_word = wm.funcs["_fpu_load_status_word"]; }; FPU.prototype.get_state = function() diff --git a/src/native/fpu.c b/src/native/fpu.c index 4f1b53aa..73b50fe6 100644 --- a/src/native/fpu.c +++ b/src/native/fpu.c @@ -41,3 +41,8 @@ void fpu_fcomi(double_t y) } } +int32_t fpu_load_status_word() +{ + return *fpu_status_word & ~(7 << 11) | *fpu_stack_ptr << 11; +} + From da48e747a91844edf016be73d46cb5f62e1faf6b Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Fri, 4 Aug 2017 20:34:29 +0530 Subject: [PATCH 0109/2137] port fpu_store_m80 --- src/fpu.js | 1 + src/native/fpu.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/fpu.js b/src/fpu.js index c31014a5..84c143ab 100644 --- a/src/fpu.js +++ b/src/fpu.js @@ -113,6 +113,7 @@ FPU.prototype.wasm_patch = function(wm) this.set_tag_word = wm.funcs["_fpu_set_tag_word"]; this.fcomi = wm.funcs["_fpu_fcomi"]; this.load_status_word = wm.funcs["_fpu_load_status_word"]; + this.store_m80 = wm.funcs["_fpu_store_m80"]; }; FPU.prototype.get_state = function() diff --git a/src/native/fpu.c b/src/native/fpu.c index 73b50fe6..12f76ac3 100644 --- a/src/native/fpu.c +++ b/src/native/fpu.c @@ -46,3 +46,42 @@ int32_t fpu_load_status_word() return *fpu_status_word & ~(7 << 11) | *fpu_stack_ptr << 11; } +void fpu_store_m80(uint32_t addr, double_t n) +{ + *fpu_float64 = n; + + uint8_t sign = fpu_float64_byte[7] & 0x80; + int32_t exponent = (fpu_float64_byte[7] & 0x7f) << 4 | fpu_float64_byte[6] >> 4; + int32_t low, high; + + if(exponent == 0x7FF) + { + // all bits set (NaN and infinity) + exponent = 0x7FFF; + low = 0; + high = 0x80000000 | (fpu_float64_int[1] & 0x80000) << 11; + } + else if(exponent == 0) + { + // zero and denormal numbers + // Just assume zero for now + low = 0; + high = 0; + } + else + { + exponent += 0x3FFF - 0x3FF; + + // does the mantissa need to be adjusted? + low = fpu_float64_int[0] << 11; + high = 0x80000000 | (fpu_float64_int[1] & 0xFFFFF) << 11 | (((uint32_t)(fpu_float64_int[0])) >> 21); + } + + dbg_assert(exponent >= 0 && exponent < 0x8000); + + safe_write32(addr, low); + safe_write32(addr + 4, high); + + safe_write16(addr + 8, sign << 8 | exponent); +} + From 4f7a6c6ef86050d55366ef57815684a1588c8c8f Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Fri, 4 Aug 2017 20:48:27 +0530 Subject: [PATCH 0110/2137] port fxsave --- src/cpu.js | 2 ++ src/native/cpu.c | 2 +- src/native/misc_instr.c | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/cpu.js b/src/cpu.js index c6c4a6e4..f6c54f0c 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -368,6 +368,8 @@ CPU.prototype.wasm_patch = function(wm) this.outsb = this.wm.funcs['_outsb']; this.outsw = this.wm.funcs['_outsw']; this.outsd = this.wm.funcs['_outsd']; + + this.fxsave = this.wm.funcs['_fxsave']; }; CPU.prototype.get_state = function() diff --git a/src/native/cpu.c b/src/native/cpu.c index 9d6595c5..b6b474eb 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -43,7 +43,7 @@ void safe_write8(int32_t, int32_t); void safe_write16(int32_t, int32_t); void safe_write32(int32_t, int32_t); -void fxsave(int32_t); +void fxsave(uint32_t); void fxrstor(int32_t); int32_t do_page_translation(int32_t, bool, bool); diff --git a/src/native/misc_instr.c b/src/native/misc_instr.c index 2f063233..8baa40e2 100644 --- a/src/native/misc_instr.c +++ b/src/native/misc_instr.c @@ -288,3 +288,40 @@ void pusha32() void setcc(bool condition) { set_e8(condition); } + +int32_t fpu_load_status_word(); +void fpu_store_m80(uint32_t, double_t); + +void fxsave(uint32_t addr) +{ + writable_or_pagefault(addr, 512); + + safe_write16(addr + 0, *fpu_control_word); + safe_write16(addr + 2, fpu_load_status_word()); + safe_write8( addr + 4, ~*fpu_stack_empty & 0xFF); + safe_write16(addr + 6, *fpu_opcode); + safe_write32(addr + 8, *fpu_ip); + safe_write16(addr + 12, *fpu_ip_selector); + safe_write32(addr + 16, *fpu_dp); + safe_write16(addr + 20, *fpu_dp_selector); + + safe_write32(addr + 24, *mxcsr); + safe_write32(addr + 28, MXCSR_MASK); + + for(int32_t i = 0; i < 8; i++) + { + fpu_store_m80(addr + 32 + (i << 4), fpu_st[*fpu_stack_ptr + i & 7]); + } + + // If the OSFXSR bit in control register CR4 is not set, the FXSAVE + // instruction may not save these registers. This behavior is + // 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]); + } +} + From 27c14b19c26ed48638e66368ecf8559767b16dc1 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Fri, 4 Aug 2017 20:51:13 +0530 Subject: [PATCH 0111/2137] port fpu_set_status_word --- src/fpu.js | 1 + src/native/fpu.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/fpu.js b/src/fpu.js index 84c143ab..8142f2ac 100644 --- a/src/fpu.js +++ b/src/fpu.js @@ -114,6 +114,7 @@ FPU.prototype.wasm_patch = function(wm) this.fcomi = wm.funcs["_fpu_fcomi"]; this.load_status_word = wm.funcs["_fpu_load_status_word"]; this.store_m80 = wm.funcs["_fpu_store_m80"]; + this.set_status_word = wm.funcs["_fpu_set_status_word"]; }; FPU.prototype.get_state = function() diff --git a/src/native/fpu.c b/src/native/fpu.c index 12f76ac3..c53fe550 100644 --- a/src/native/fpu.c +++ b/src/native/fpu.c @@ -46,6 +46,12 @@ int32_t fpu_load_status_word() return *fpu_status_word & ~(7 << 11) | *fpu_stack_ptr << 11; } +void fpu_set_status_word(int32_t sw) +{ + *fpu_status_word = sw & ~(7 << 11); + *fpu_stack_ptr = sw >> 11 & 7; +} + void fpu_store_m80(uint32_t addr, double_t n) { *fpu_float64 = n; From d7b81d5bb9c34ec9eb0bc1cf6f2d426ecec564b0 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sat, 5 Aug 2017 02:37:56 +0530 Subject: [PATCH 0112/2137] port load_m80 --- src/browser/starter.js | 1 + src/fpu.js | 1 + src/native/all.c | 1 + src/native/fpu.c | 49 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+) diff --git a/src/browser/starter.js b/src/browser/starter.js index 57cfbd28..6cd6fd3c 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -157,6 +157,7 @@ function V86Starter(options) "_fwait": function() { return cpu.fpu.fwait(); }, "_int_log2": function(val) { return v86util.int_log2(val); }, + "_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); }, diff --git a/src/fpu.js b/src/fpu.js index 8142f2ac..77ec647d 100644 --- a/src/fpu.js +++ b/src/fpu.js @@ -115,6 +115,7 @@ FPU.prototype.wasm_patch = function(wm) this.load_status_word = wm.funcs["_fpu_load_status_word"]; this.store_m80 = wm.funcs["_fpu_store_m80"]; this.set_status_word = wm.funcs["_fpu_set_status_word"]; + this.load_m80 = wm.funcs["_fpu_load_m80"]; }; FPU.prototype.get_state = function() diff --git a/src/native/all.c b/src/native/all.c index 6f932700..14a70831 100644 --- a/src/native/all.c +++ b/src/native/all.c @@ -5,6 +5,7 @@ extern void call_interrupt_vector(int32_t interrupt_nr, bool is_software_int, bool has_error_code, int32_t error_code); extern void throw_cpu_exception(void); +extern double_t math_pow(double_t, double_t); #include "const.h" #include "global_pointers.h" diff --git a/src/native/fpu.c b/src/native/fpu.c index c53fe550..12f1824b 100644 --- a/src/native/fpu.c +++ b/src/native/fpu.c @@ -91,3 +91,52 @@ void fpu_store_m80(uint32_t addr, double_t n) safe_write16(addr + 8, sign << 8 | exponent); } +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; + + int32_t sign = exponent >> 15; + exponent &= ~0x8000; + + if(exponent == 0) + { + // TODO: denormal numbers + return 0; + } + + if(exponent < 0x7FFF) + { + exponent -= 0x3FFF; + } + else + { + // TODO: NaN, Infinity + //dbg_log("Load m80 TODO", LOG_FPU); + fpu_float64_byte[7] = 0x7F | sign << 7; + fpu_float64_byte[6] = 0xF0 | high >> 30 << 3 & 0x08; + + fpu_float64_byte[5] = 0; + fpu_float64_byte[4] = 0; + + fpu_float64_int[0] = 0; + + return *fpu_float64; + } + + // Note: some bits might be lost at this point + double_t mantissa = ((double_t)(low)) + 0x100000000 * ((double_t)(high)); + + if(sign) + { + mantissa = -mantissa; + } + + // Simply compute the 64 bit floating point number. + // An alternative write the mantissa, sign and exponent in the + // float64_byte and return float64[0] + + return mantissa * math_pow(2, exponent - 63); +} + From 7c8294230d504e9f9b4725bc385d2fe76ad159c7 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sat, 5 Aug 2017 02:45:21 +0530 Subject: [PATCH 0113/2137] port fxrstor --- src/browser/starter.js | 2 -- src/cpu.js | 1 + src/native/cpu.c | 2 +- src/native/misc_instr.c | 40 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 6cd6fd3c..777c57be 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -214,8 +214,6 @@ 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); }, - "_fxsave": function() { return cpu.fxsave.apply(cpu, arguments); }, - "_fxrstor": function() { return cpu.fxrstor.apply(cpu, arguments); }, }; let wasm_file = DEBUG ? "v86-debug.wasm" : "v86.wasm"; diff --git a/src/cpu.js b/src/cpu.js index f6c54f0c..34cab609 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -370,6 +370,7 @@ CPU.prototype.wasm_patch = function(wm) this.outsd = this.wm.funcs['_outsd']; this.fxsave = this.wm.funcs['_fxsave']; + this.fxrstor = this.wm.funcs['_fxrstor']; }; CPU.prototype.get_state = function() diff --git a/src/native/cpu.c b/src/native/cpu.c index b6b474eb..d7129329 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -44,7 +44,7 @@ void safe_write16(int32_t, int32_t); void safe_write32(int32_t, int32_t); void fxsave(uint32_t); -void fxrstor(int32_t); +void fxrstor(uint32_t); int32_t do_page_translation(int32_t, bool, bool); diff --git a/src/native/misc_instr.c b/src/native/misc_instr.c index 8baa40e2..aa6f24b6 100644 --- a/src/native/misc_instr.c +++ b/src/native/misc_instr.c @@ -290,7 +290,9 @@ void setcc(bool condition) { } int32_t fpu_load_status_word(); +void fpu_set_status_word(int32_t); void fpu_store_m80(uint32_t, double_t); +double_t fpu_load_m80(uint32_t); void fxsave(uint32_t addr) { @@ -325,3 +327,41 @@ void fxsave(uint32_t addr) } } +void fxrstor(uint32_t addr) +{ + translate_address_read(addr); + translate_address_read(addr + 511); + + int32_t new_mxcsr = safe_read32s(addr + 24); + + if(new_mxcsr & ~MXCSR_MASK) + { + //dbg_log("Invalid mxcsr bits: " + h((new_mxcsr & ~MXCSR_MASK) >>> 0, 8)); + trigger_gp(0); + } + + *fpu_control_word = safe_read16(addr + 0); + fpu_set_status_word(safe_read16(addr + 2)); + *fpu_stack_empty = ~safe_read8(addr + 4) & 0xFF; + *fpu_opcode = safe_read16(addr + 6); + *fpu_ip = safe_read32s(addr + 8); + *fpu_ip = safe_read16(addr + 12); + *fpu_dp = safe_read32s(addr + 16); + *fpu_dp_selector = safe_read16(addr + 20); + + *mxcsr = new_mxcsr; + + for(int32_t i = 0; i < 8; i++) + { + fpu_st[*fpu_stack_ptr + i & 7] = fpu_load_m80(addr + 32 + (i << 4)); + } + + 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); + } +} + From 8ed632c0bcae7da2580653ae5104789c5b46f881 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 15 Aug 2017 11:58:31 +0530 Subject: [PATCH 0114/2137] Port reg_mmx to wasm (offset 1064, length 64 bytes) --- src/cpu.js | 8 ++++---- src/native/global_pointers.h | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index 34cab609..351e3ead 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -193,10 +193,10 @@ function CPU(bus, wm) this.reg8 = new Uint8Array(this.reg32s.buffer, 4, 32); // mm0-mm7 split up into 32 bit pairs - this.reg_mmxs = new Int32Array(16); - this.reg_mmx = new Uint32Array(this.reg_mmxs.buffer); - this.reg_mmx8s = new Int8Array(this.reg_mmxs.buffer); - this.reg_mmx8 = new Uint8Array(this.reg_mmxs.buffer); + this.reg_mmxs = new Int32Array(wm.mem.buffer, 1064, 16); + this.reg_mmx = new Uint32Array(this.reg_mmxs.buffer, 1064, 16); + this.reg_mmx8s = new Int8Array(this.reg_mmxs.buffer, 1064, 64); + this.reg_mmx8 = new Uint8Array(this.reg_mmxs.buffer, 1064, 64); this.reg_xmm32s = new Int32Array(wm.mem.buffer, 828, 8 * 4); diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index d96fa5c1..3c508829 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -103,4 +103,7 @@ 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 + #endif From c1336a90397b16ae3c94f9ae1a1253ca14be5f9d Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 15 Aug 2017 12:03:32 +0530 Subject: [PATCH 0115/2137] Clean up length comments to always use bytes in global_pointers --- src/native/global_pointers.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index 3c508829..9695110c 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -15,7 +15,7 @@ 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 2 +int32_t* const mul32_result = (int32_t* const) 544; // length 8 bool* const a20_enabled = (bool* const) 552; int32_t* const instruction_pointer = (int32_t* const) 556; @@ -25,7 +25,7 @@ int32_t* const idtr_size = (int32_t* const) 564; int32_t* const idtr_offset = (int32_t* const) 568; int32_t* const gdtr_size = (int32_t* const) 572; int32_t* const gdtr_offset = (int32_t* const) 576; -int32_t* const cr = (int32_t* const) 580; // length 8 +int32_t* const cr = (int32_t* const) 580; // length 32 uint8_t* const cpl = (uint8_t* const) 612; int32_t* const page_size_extensions = (int32_t* const) 616; @@ -43,11 +43,11 @@ int32_t* const phys_addr_high = (int32_t* const) 660; int32_t* const timestamp_counter = (int32_t* const) 664; uint16_t* const sreg = (uint16_t* const) 668; -int32_t* const dreg = (int32_t* const) 684; // length 8 +int32_t* const dreg = (int32_t* const) 684; // length 32 int32_t* const fw_value = (int32_t* const) 720; bool* const segment_is_null = (bool* const) 724; // length 8 -int32_t* const segment_offsets = (int32_t* const) 736; // length 8 -uint32_t* const segment_limits = (uint32_t* const) 768; // length 8 +int32_t* const segment_offsets = (int32_t* const) 736; // length 32 +uint32_t* const segment_limits = (uint32_t* const) 768; // length 32 bool* const protected_mode = (bool* const) 800; bool* const is_32 = (bool* const) 804; From e4c7f5df7b3cc7cf2d9846618b0bd56fafd4011b Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 15 Aug 2017 16:18:00 +0530 Subject: [PATCH 0116/2137] Port read_mmx_mem64s --- src/native/cpu.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/native/cpu.c b/src/native/cpu.c index d7129329..6a78348c 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -637,6 +637,22 @@ void write_e32(int32_t value) } } +union reg64 read_mmx_mem64s() +{ + 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; + } +}; union reg64 read_xmm64s() { union reg64 x; From ca7f31bd32698435d27b454c0ff289af69d1c3d1 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 15 Aug 2017 16:18:21 +0530 Subject: [PATCH 0117/2137] Port write_mmx64s --- src/native/cpu.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/native/cpu.c b/src/native/cpu.c index 6a78348c..b184b890 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -653,6 +653,14 @@ union reg64 read_mmx_mem64s() return x; } }; + +void write_mmx64s(int32_t low, int32_t high) +{ + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + reg_mmx32s[offset] = low; + reg_mmx32s[offset + 1] = high; +}; + union reg64 read_xmm64s() { union reg64 x; From 693335f31003de642877ed7e4380fce5a220a1f8 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 15 Aug 2017 16:18:50 +0530 Subject: [PATCH 0118/2137] Port packssdw mm, mm/m64 --- src/native/instructions_0f.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 94f7380d..dea24811 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -903,7 +903,28 @@ static void instr_0F68() { unimplemented_sse(); } static void instr_660F68() { unimplemented_sse(); } static void instr_0F69() { unimplemented_sse(); } static void instr_0F6A() { unimplemented_sse(); } -static void instr_0F6B() { unimplemented_sse(); } + +static void instr_0F6B() { + // packssdw mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + int32_t destination_low = reg_mmx32s[offset]; + int32_t destination_high = reg_mmx32s[offset + 1]; + + int32_t low = 0; + low |= saturate_sd_to_sw(destination_low); + low |= saturate_sd_to_sw(destination_high) << 16; + + int32_t high = 0; + high |= saturate_sd_to_sw(source.u32[0]); + high |= saturate_sd_to_sw(source.u32[1]) << 16; + + write_mmx64s(low, high); +} + static void instr_0F6C() { unimplemented_sse(); } static void instr_0F6D() { unimplemented_sse(); } static void instr_0F6E() { unimplemented_sse(); } From 972ed07b61d6c44cf7d3284623183f61683cbf3a Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 15 Aug 2017 17:05:25 +0530 Subject: [PATCH 0119/2137] Port packsswb mm, mm/m64 --- src/native/instructions_0f.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index dea24811..bfce8ba2 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -892,7 +892,32 @@ void instr_660F60() { static void instr_0F61() { unimplemented_sse(); } static void instr_660F61() { unimplemented_sse(); } static void instr_0F62() { unimplemented_sse(); } -static void instr_0F63() { unimplemented_sse(); } + +static void instr_0F63() { + // packsswb mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + uint32_t destination_low = reg_mmx32s[offset]; + uint32_t destination_high = reg_mmx32s[offset + 1]; + + int32_t low = 0; + low |= (saturate_sw_to_sb((destination_low) & 0xFFFF)); + low |= (saturate_sw_to_sb(destination_low >> 16)) << 8; + low |= (saturate_sw_to_sb((destination_high) & 0xFFFF)) << 16; + low |= (saturate_sw_to_sb(destination_high >> 16)) << 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; + + write_mmx64s(low, high); +} + static void instr_0F64() { unimplemented_sse(); } static void instr_0F65() { unimplemented_sse(); } static void instr_0F66() { unimplemented_sse(); } @@ -904,7 +929,8 @@ static void instr_660F68() { unimplemented_sse(); } static void instr_0F69() { unimplemented_sse(); } static void instr_0F6A() { unimplemented_sse(); } -static void instr_0F6B() { +static void instr_0F6B() +{ // packssdw mm, mm/m64 task_switch_test_mmx(); read_modrm_byte(); From 5254cf4691230cf7ed14484054af9876132eec4a Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 15 Aug 2017 17:24:48 +0530 Subject: [PATCH 0120/2137] Port packuswb mm, mm/m64 --- src/native/instructions_0f.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index bfce8ba2..0d1ce5a8 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -921,7 +921,33 @@ static void instr_0F63() { static void instr_0F64() { unimplemented_sse(); } static void instr_0F65() { unimplemented_sse(); } static void instr_0F66() { unimplemented_sse(); } -static void instr_0F67() { unimplemented_sse(); } + +static void instr_0F67() +{ + // packuswb mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + uint32_t destination_low = reg_mmx32s[offset]; + uint32_t destination_high = reg_mmx32s[offset + 1]; + + uint32_t low = 0; + low |= (saturate_sw_to_ub((destination_low) & 0xFFFF)); + low |= (saturate_sw_to_ub(destination_low >> 16)) << 8; + low |= (saturate_sw_to_ub((destination_high) & 0xFFFF)) << 16; + low |= (saturate_sw_to_ub(destination_high >> 16)) << 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; + + write_mmx64s(low, high); +} + static void instr_660F67() { unimplemented_sse(); } static void instr_0F68() { unimplemented_sse(); } From 07a317d9808ea3cf355d3b43751d57a15d582504 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 15 Aug 2017 17:38:59 +0530 Subject: [PATCH 0121/2137] Port paddb mm, mm/m64 --- src/native/instructions_0f.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 0d1ce5a8..10cfc330 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1848,7 +1848,32 @@ static void instr_0FF9() { unimplemented_sse(); } static void instr_0FFA() { unimplemented_sse(); } static void instr_660FFA() { unimplemented_sse(); } static void instr_0FFB() { unimplemented_sse(); } -static void instr_0FFC() { unimplemented_sse(); } + +static void instr_0FFC() +{ + // paddb mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + + uint32_t reg_offset = 8 * (*modrm_byte >> 3 & 7); + + uint8_t byte0 = (reg_mmx->u8[reg_offset] + source.u8[0]) & 0xFF; + uint8_t byte1 = (reg_mmx->u8[reg_offset + 1] + source.u8[1]) & 0xFF; + uint8_t byte2 = (reg_mmx->u8[reg_offset + 2] + source.u8[2]) & 0xFF; + uint8_t byte3 = (reg_mmx->u8[reg_offset + 3] + source.u8[3]) & 0xFF; + uint8_t byte4 = (reg_mmx->u8[reg_offset + 4] + source.u8[4]) & 0xFF; + uint8_t byte5 = (reg_mmx->u8[reg_offset + 5] + source.u8[5]) & 0xFF; + uint8_t byte6 = (reg_mmx->u8[reg_offset + 6] + source.u8[6]) & 0xFF; + uint8_t byte7 = (reg_mmx->u8[reg_offset + 7] + source.u8[7]) & 0xFF; + + uint32_t low = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24; + uint32_t high = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24; + + write_mmx64s(low, high); +} + static void instr_0FFD() { unimplemented_sse(); } static void instr_0FFE() { unimplemented_sse(); } From ad629e1a7b03538930162e622d5e0c1c6bb85d4d Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 16 Aug 2017 21:39:32 +0530 Subject: [PATCH 0122/2137] Remove unsupported Closure Compiler flags --- Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/Makefile b/Makefile index 88cea35c..3da75efe 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,6 @@ CLOSURE_FLAGS=\ --jscomp_error externsValidation\ --jscomp_error fileoverviewTags\ --jscomp_error globalThis\ - --jscomp_error inferredConstCheck\ --jscomp_error internetExplorerChecks\ --jscomp_error invalidCasts\ --jscomp_error misplacedTypeAnnotation\ @@ -63,7 +62,6 @@ CLOSURE_FLAGS=\ --jscomp_error undefinedNames\ --jscomp_error undefinedVars\ --jscomp_error unknownDefines\ - --jscomp_error unnecessaryCasts\ --jscomp_error visibility\ --use_types_for_optimization\ --summary_detail_level 3\ From 89f6e3f2985e082927428255fd6a52c81ee68007 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 11:04:19 +0530 Subject: [PATCH 0123/2137] Port paddd --- src/native/instructions_0f.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 10cfc330..e13945eb 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1875,7 +1875,22 @@ static void instr_0FFC() } static void instr_0FFD() { unimplemented_sse(); } -static void instr_0FFE() { unimplemented_sse(); } +static void instr_0FFE() +{ + // paddd mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + int32_t destination_low = reg_mmx32s[offset]; + int32_t destination_high = reg_mmx32s[offset + 1]; + + int32_t low = destination_low + source.u32[0] | 0; + int32_t high = destination_high + source.u32[1] | 0; + + write_mmx64s(low, high); +} static void instr_0FFF() { // Windows 98 From aa9d5764e99a16ed4ae9ad38a89f1367c83272dd Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 11:18:41 +0530 Subject: [PATCH 0124/2137] Add s8 to reg64 union (int8_t) --- src/native/global_pointers.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index 9695110c..e3abd29f 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -66,6 +66,7 @@ union reg128 { }; union reg64 { + int8_t s8[8]; uint8_t u8[8]; uint16_t u16[4]; uint32_t u32[2]; From e895c2e735d065b349f4c5863bc265f32e44438d Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 11:19:55 +0530 Subject: [PATCH 0125/2137] Port paddsb --- src/native/instructions_0f.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index e13945eb..5f02d084 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1814,7 +1814,32 @@ static void instr_0FE9() { unimplemented_sse(); } static void instr_0FEA() { unimplemented_sse(); } static void instr_0FEB() { unimplemented_sse(); } static void instr_660FEB() { unimplemented_sse(); } -static void instr_0FEC() { unimplemented_sse(); } + +static void instr_0FEC() +{ + // paddsb mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + + int32_t reg_offset = (*modrm_byte >> 3 & 7) << 3; + + uint32_t byte0 = saturate_sd_to_sb(reg_mmx->s8[reg_offset] + source.s8[0]); + uint32_t byte1 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 1] + source.s8[1]); + uint32_t byte2 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 2] + source.s8[2]); + uint32_t byte3 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 3] + source.s8[3]); + uint32_t byte4 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 4] + source.s8[4]); + uint32_t byte5 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 5] + source.s8[5]); + uint32_t byte6 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 6] + source.s8[6]); + uint32_t byte7 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 7] + source.s8[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); +} + static void instr_0FED() { unimplemented_sse(); } static void instr_0FEE() { unimplemented_sse(); } static void instr_0FEF() { unimplemented_sse(); } From c1caba17ec07831efb30e7835c88c955afa62e44 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 11:27:54 +0530 Subject: [PATCH 0126/2137] Add s32 to reg64 union (int32_t) --- src/native/global_pointers.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index e3abd29f..a8f406c3 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -67,6 +67,7 @@ union reg128 { union reg64 { int8_t s8[8]; + int32_t s32[2]; uint8_t u8[8]; uint16_t u16[4]; uint32_t u32[2]; From b1aee95bd9765092323030e2eb18f773229d1966 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 11:28:21 +0530 Subject: [PATCH 0127/2137] Port paddsw --- src/native/instructions_0f.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 5f02d084..86c5b832 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1840,7 +1840,27 @@ static void instr_0FEC() write_mmx64s(low, high); } -static void instr_0FED() { unimplemented_sse(); } +static void instr_0FED() { + // paddsw mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + int32_t destination_low = reg_mmx32s[offset]; + int32_t destination_high = reg_mmx32s[offset + 1]; + + int32_t word0 = saturate_sd_to_sw((destination_low << 16 >> 16) + (source.s32[0] << 16 >> 16)); + int32_t word1 = saturate_sd_to_sw((destination_low >> 16) + (source.s32[0] >> 16)); + int32_t word2 = saturate_sd_to_sw((destination_high << 16 >> 16) + (source.s32[1] << 16 >> 16)); + int32_t word3 = saturate_sd_to_sw((destination_high >> 16) + (source.s32[1] >> 16)); + + int32_t low = word0 | word1 << 16; + int32_t high = word2 | word3 << 16; + + write_mmx64s(low, high); +} + static void instr_0FEE() { unimplemented_sse(); } static void instr_0FEF() { unimplemented_sse(); } static void instr_660FEF() { From 43dbb718ed73c361b705ce08bf7dba5d8f20739b Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 11:36:29 +0530 Subject: [PATCH 0128/2137] Port paddusb mm, mm/m64 --- src/native/instructions_0f.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 86c5b832..385c7771 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1780,7 +1780,31 @@ static void instr_0FD9() { unimplemented_sse(); } static void instr_0FDA() { unimplemented_sse(); } static void instr_660FDA() { unimplemented_sse(); } static void instr_0FDB() { unimplemented_sse(); } -static void instr_0FDC() { unimplemented_sse(); } + +static void instr_0FDC() +{ + // paddusb mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + union reg64 source = read_mmx_mem64s(); + + int32_t reg_offset = (*modrm_byte >> 3 & 7) << 3; + + uint32_t byte0 = saturate_ud_to_ub(reg_mmx->u8[reg_offset] + source.u8[0]); + uint32_t byte1 = saturate_ud_to_ub(reg_mmx->u8[reg_offset + 1] + source.u8[1]); + uint32_t byte2 = saturate_ud_to_ub(reg_mmx->u8[reg_offset + 2] + source.u8[2]); + uint32_t byte3 = saturate_ud_to_ub(reg_mmx->u8[reg_offset + 3] + source.u8[3]); + uint32_t byte4 = saturate_ud_to_ub(reg_mmx->u8[reg_offset + 4] + source.u8[4]); + uint32_t byte5 = saturate_ud_to_ub(reg_mmx->u8[reg_offset + 5] + source.u8[5]); + uint32_t byte6 = saturate_ud_to_ub(reg_mmx->u8[reg_offset + 6] + source.u8[6]); + uint32_t byte7 = saturate_ud_to_ub(reg_mmx->u8[reg_offset + 7] + 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); +} + static void instr_660FDC() { unimplemented_sse(); } static void instr_0FDD() { unimplemented_sse(); } static void instr_660FDD() { unimplemented_sse(); } From f049636e73846c60e41d90d409c8fabe1cf76c40 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 11:42:46 +0530 Subject: [PATCH 0129/2137] Port paddusw mm, mm/m64 --- src/native/instructions_0f.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 385c7771..f2e04419 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1806,7 +1806,29 @@ static void instr_0FDC() } static void instr_660FDC() { unimplemented_sse(); } -static void instr_0FDD() { unimplemented_sse(); } + +static void instr_0FDD() +{ + // paddusw mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + uint32_t destination_low = reg_mmx32s[offset]; + uint32_t destination_high = reg_mmx32s[offset + 1]; + + int32_t word0 = saturate_uw((destination_low & 0xFFFF) + (source.u32[0] & 0xFFFF)); + int32_t word1 = saturate_uw((destination_low >> 16) + (source.u32[0] >> 16)); + int32_t word2 = saturate_uw((destination_high & 0xFFFF) + (source.u32[1] & 0xFFFF)); + int32_t word3 = saturate_uw((destination_high >> 16) + (source.u32[1] >> 16)); + + int32_t low = word0 | word1 << 16; + int32_t high = word2 | word3 << 16; + + write_mmx64s(low, high); +} + static void instr_660FDD() { unimplemented_sse(); } static void instr_0FDE() { unimplemented_sse(); } static void instr_660FDE() { unimplemented_sse(); } From f91b1e2599ff75235075ab756149d1b9225924ee Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 11:46:24 +0530 Subject: [PATCH 0130/2137] Port paddw --- src/native/instructions_0f.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index f2e04419..45c39437 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1965,7 +1965,29 @@ static void instr_0FFC() write_mmx64s(low, high); } -static void instr_0FFD() { unimplemented_sse(); } +static void instr_0FFD() +{ + // paddw mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + uint32_t destination_low = reg_mmx32s[offset]; + uint32_t destination_high = reg_mmx32s[offset + 1]; + + int32_t word0 = (destination_low + source.u32[0]) & 0xFFFF; + int32_t word1 = ((destination_low >> 16) + (source.u32[0] >> 16)) & 0xFFFF; + int32_t low = word0 | word1 << 16; + + int32_t word2 = (destination_high + source.u32[1]) & 0xFFFF; + int32_t word3 = ((destination_high >> 16) + (source.u32[1] >> 16)) & 0xFFFF; + int32_t high = word2 | word3 << 16; + + write_mmx64s(low, high); + +} + static void instr_0FFE() { // paddd mm, mm/m64 From 5bdf91b70daa3edaae4440c363a8956a7740ccfc Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 11:54:18 +0530 Subject: [PATCH 0131/2137] Port pandn --- src/native/instructions_0f.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 45c39437..bba4dfbf 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1832,7 +1832,23 @@ static void instr_0FDD() static void instr_660FDD() { unimplemented_sse(); } static void instr_0FDE() { unimplemented_sse(); } static void instr_660FDE() { unimplemented_sse(); } -static void instr_0FDF() { unimplemented_sse(); } + +static void instr_0FDF() +{ + // pandn mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + int32_t destination_low = reg_mmx32s[offset]; + int32_t destination_high = reg_mmx32s[offset + 1]; + + int32_t low = source.u32[0] & ~destination_low; + int32_t high = source.u32[1] & ~destination_high; + + write_mmx64s(low, high); +} static void instr_0FE0() { unimplemented_sse(); } static void instr_0FE1() { unimplemented_sse(); } From 7806a58f292b5cbd35185197a8f567888c5ff025 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 12:07:36 +0530 Subject: [PATCH 0132/2137] Port pand --- src/native/instructions_0f.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index bba4dfbf..baffef49 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1779,7 +1779,23 @@ static void instr_0FD8() { unimplemented_sse(); } static void instr_0FD9() { unimplemented_sse(); } static void instr_0FDA() { unimplemented_sse(); } static void instr_660FDA() { unimplemented_sse(); } -static void instr_0FDB() { unimplemented_sse(); } + +static void instr_0FDB() +{ + // pand mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + int32_t destination_low = reg_mmx32s[offset]; + int32_t destination_high = reg_mmx32s[offset + 1]; + + int32_t low = source.u32[0] & destination_low; + int32_t high = source.u32[1] & destination_high; + + write_mmx64s(low, high); +} static void instr_0FDC() { From 3a1623b4f6b819d08c47d3da0f7c71b8f72e252c Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 12:08:38 +0530 Subject: [PATCH 0133/2137] Port pcmpeqb mm, mm/m64 --- src/native/instructions_0f.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index baffef49..2fbc0db9 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1024,7 +1024,32 @@ static void instr_0F71() { unimplemented_sse(); } static void instr_0F72() { unimplemented_sse(); } static void instr_0F73() { unimplemented_sse(); } static void instr_660F73() { unimplemented_sse(); } -static void instr_0F74() { unimplemented_sse(); } + +static void instr_0F74() +{ + // pcmpeqb mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + + int32_t reg_offset = (*modrm_byte >> 3 & 7) << 3; + + int32_t byte0 = reg_mmx->s8[reg_offset] == source.s8[0] ? 0xFF : 0; + int32_t byte1 = reg_mmx->s8[reg_offset + 1] == source.s8[1] ? 0xFF : 0; + int32_t byte2 = reg_mmx->s8[reg_offset + 2] == source.s8[2] ? 0xFF : 0; + int32_t byte3 = reg_mmx->s8[reg_offset + 3] == source.s8[3] ? 0xFF : 0; + int32_t byte4 = reg_mmx->s8[reg_offset + 4] == source.s8[4] ? 0xFF : 0; + int32_t byte5 = reg_mmx->s8[reg_offset + 5] == source.s8[5] ? 0xFF : 0; + int32_t byte6 = reg_mmx->s8[reg_offset + 6] == source.s8[6] ? 0xFF : 0; + int32_t byte7 = reg_mmx->s8[reg_offset + 7] == source.s8[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); +} + static void instr_660F74() { // pcmpeqb xmm, xmm/m128 task_switch_test_mmx(); From 35ebcce64a342059ae33638017edad79b6d9b933 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 12:43:25 +0530 Subject: [PATCH 0134/2137] Port pcmpeqd --- src/native/instructions_0f.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 2fbc0db9..53274038 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1069,7 +1069,24 @@ static void instr_660F74() { } static void instr_0F75() { unimplemented_sse(); } static void instr_660F75() { unimplemented_sse(); } -static void instr_0F76() { unimplemented_sse(); } + +static void instr_0F76() +{ + // pcmpeqd mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + uint32_t destination_low = reg_mmx32s[offset]; + uint32_t destination_high = reg_mmx32s[offset + 1]; + + int32_t low = destination_low == source.u32[0] ? -1 : 0; + int32_t high = destination_high == source.u32[1] ? -1 : 0; + + write_mmx64s(low, high); +} + static void instr_660F76() { unimplemented_sse(); } static void instr_0F77() { // emms From 32d69483bd83f17e712514e0b64aaf7f54b93f53 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 12:46:13 +0530 Subject: [PATCH 0135/2137] Port pcmpeqw mm, mm/m64 --- src/native/instructions_0f.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 53274038..41ce4bcb 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1067,7 +1067,29 @@ static void instr_660F74() { write_xmm128s(result.u32[0], result.u32[1], result.u32[2], result.u32[3]); } -static void instr_0F75() { unimplemented_sse(); } + +static void instr_0F75() +{ + // pcmpeqw mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = 2 * (*modrm_byte >> 3 & 7); + int32_t destination_low = reg_mmx32s[offset]; + int32_t destination_high = reg_mmx32s[offset + 1]; + + int32_t word0 = (destination_low & 0xFFFF) == (source.u32[0] & 0xFFFF) ? 0xFFFF : 0; + int32_t word1 = (destination_low & 0xFFFF0000) == (source.u32[0] & 0xFFFF0000) ? 0xFFFF : 0; + int32_t word2 = (destination_high & 0xFFFF) == (source.u32[1] & 0xFFFF) ? 0xFFFF : 0; + int32_t word3 = (destination_high & 0xFFFF0000) == (source.u32[1] & 0xFFFF0000) ? 0xFFFF : 0; + + int32_t low = word0 | word1 << 16; + int32_t high = word2 | word3 << 16; + + write_mmx64s(low, high); +} + static void instr_660F75() { unimplemented_sse(); } static void instr_0F76() From bd066bbe28fec7eedb67ffda0ca36f783c612ad1 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 12:49:43 +0530 Subject: [PATCH 0136/2137] Port pcmpgtb mm, mm/m64 --- src/native/instructions_0f.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 41ce4bcb..6b155e2a 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -918,7 +918,32 @@ static void instr_0F63() { write_mmx64s(low, high); } -static void instr_0F64() { unimplemented_sse(); } + +static void instr_0F64() +{ + // pcmpgtb mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + + int32_t reg_offset = (*modrm_byte >> 3 & 7) << 3; + + int32_t byte0 = reg_mmx->s8[reg_offset] > source.s8[0] ? 0xFF : 0; + int32_t byte1 = reg_mmx->s8[reg_offset + 1] > source.s8[1] ? 0xFF : 0; + int32_t byte2 = reg_mmx->s8[reg_offset + 2] > source.s8[2] ? 0xFF : 0; + int32_t byte3 = reg_mmx->s8[reg_offset + 3] > source.s8[3] ? 0xFF : 0; + int32_t byte4 = reg_mmx->s8[reg_offset + 4] > source.s8[4] ? 0xFF : 0; + int32_t byte5 = reg_mmx->s8[reg_offset + 5] > source.s8[5] ? 0xFF : 0; + int32_t byte6 = reg_mmx->s8[reg_offset + 6] > source.s8[6] ? 0xFF : 0; + int32_t byte7 = reg_mmx->s8[reg_offset + 7] > source.s8[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); +} + static void instr_0F65() { unimplemented_sse(); } static void instr_0F66() { unimplemented_sse(); } From 9cdce8230050d248b27c730e3dfa9d1145c506ea Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 12:53:12 +0530 Subject: [PATCH 0137/2137] Port pcmpgtd mm, mm/m64 --- src/native/instructions_0f.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 6b155e2a..3f8d5f2c 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -945,7 +945,23 @@ static void instr_0F64() } static void instr_0F65() { unimplemented_sse(); } -static void instr_0F66() { unimplemented_sse(); } + +static void instr_0F66() +{ + // pcmpgtd mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + int32_t destination_low = reg_mmx32s[offset]; + int32_t destination_high = reg_mmx32s[offset + 1]; + + int32_t low = destination_low > source.s32[0] ? -1 : 0; + int32_t high = destination_high > source.s32[1] ? -1 : 0; + + write_mmx64s(low, high); +} static void instr_0F67() { From 85c9fb7c8c8462f9258ba82b38c55711e919cd06 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 12:59:35 +0530 Subject: [PATCH 0138/2137] Add s16 to reg64 union (int16_t) --- src/native/global_pointers.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index a8f406c3..4da53321 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -67,6 +67,7 @@ union reg128 { union reg64 { int8_t s8[8]; + int16_t s16[4]; int32_t s32[2]; uint8_t u8[8]; uint16_t u16[4]; From 65b02866c838bfb1e3d25f1667319e3998342a66 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 12:59:50 +0530 Subject: [PATCH 0139/2137] Port pcmpgtw --- src/native/instructions_0f.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 3f8d5f2c..3b4499d4 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -944,7 +944,26 @@ static void instr_0F64() write_mmx64s(low, high); } -static void instr_0F65() { unimplemented_sse(); } + +static void instr_0F65() +{ + // pcmpgtw mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 2; + + int32_t word0 = (reg_mmx->s16[offset]) > (source.s16[0]) ? 0xFFFF : 0; + int32_t word1 = (reg_mmx->s16[offset + 1]) > (source.s16[1]) ? 0xFFFF : 0; + int32_t word2 = (reg_mmx->s16[offset + 2]) > (source.s16[2]) ? 0xFFFF : 0; + int32_t word3 = (reg_mmx->s16[offset + 3]) > (source.s16[3]) ? 0xFFFF : 0; + + int32_t low = word0 | word1 << 16; + int32_t high = word2 | word3 << 16; + + write_mmx64s(low, high); +} static void instr_0F66() { From 1efe7cf06982787600045564904193030df0fe77 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 13:03:14 +0530 Subject: [PATCH 0140/2137] Refactor to simplify paddsw by using s16 instead of bit shifts --- src/native/instructions_0f.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 3b4499d4..12e347e9 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2048,14 +2048,12 @@ static void instr_0FED() { read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 1; - int32_t destination_low = reg_mmx32s[offset]; - int32_t destination_high = reg_mmx32s[offset + 1]; + int32_t offset = (*modrm_byte >> 3 & 7) << 2; - int32_t word0 = saturate_sd_to_sw((destination_low << 16 >> 16) + (source.s32[0] << 16 >> 16)); - int32_t word1 = saturate_sd_to_sw((destination_low >> 16) + (source.s32[0] >> 16)); - int32_t word2 = saturate_sd_to_sw((destination_high << 16 >> 16) + (source.s32[1] << 16 >> 16)); - int32_t word3 = saturate_sd_to_sw((destination_high >> 16) + (source.s32[1] >> 16)); + int32_t word0 = saturate_sd_to_sw((reg_mmx->s16[offset]) + (source.s16[0])); + int32_t word1 = saturate_sd_to_sw((reg_mmx->s16[offset + 1]) + (source.s16[1])); + int32_t word2 = saturate_sd_to_sw((reg_mmx->s16[offset + 2]) + (source.s16[2])); + int32_t word3 = saturate_sd_to_sw((reg_mmx->s16[offset + 3]) + (source.s16[3])); int32_t low = word0 | word1 << 16; int32_t high = word2 | word3 << 16; From 08c736a8196e3e7d1cad4c9696fa6f21b2f1c45b Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 13:06:26 +0530 Subject: [PATCH 0141/2137] Port pmaddwd --- src/native/instructions_0f.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 12e347e9..969d7ba4 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2084,7 +2084,27 @@ static void instr_0FF1() { unimplemented_sse(); } static void instr_0FF2() { unimplemented_sse(); } static void instr_0FF3() { unimplemented_sse(); } static void instr_0FF4() { unimplemented_sse(); } -static void instr_0FF5() { unimplemented_sse(); } + +static void instr_0FF5() +{ + // pmaddwd mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 2; + + int32_t mul0 = (reg_mmx->s16[offset] * (source.s16[0])); + int32_t mul1 = (reg_mmx->s16[offset + 1] * (source.s16[1])); + int32_t mul2 = (reg_mmx->s16[offset + 2] * (source.s16[2])); + int32_t mul3 = (reg_mmx->s16[offset + 3] * (source.s16[3])); + + int32_t low = mul0 + mul1 | 0; + int32_t high = mul2 + mul3 | 0; + + write_mmx64s(low, high); +} + static void instr_0FF6() { unimplemented_sse(); } static void instr_0FF7() { unimplemented_sse(); } From f5fbd73ad9426cb4f9d94fd86c08074f5ac26037 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 15:05:08 +0530 Subject: [PATCH 0142/2137] Port pmulhw --- src/native/instructions_0f.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 969d7ba4..d2627f22 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1996,7 +1996,27 @@ static void instr_0FE2() { unimplemented_sse(); } static void instr_0FE3() { unimplemented_sse(); } static void instr_0FE4() { unimplemented_sse(); } static void instr_660FE4() { unimplemented_sse(); } -static void instr_0FE5() { unimplemented_sse(); } + +static void instr_0FE5() +{ + // pmulhw mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 2; + + uint32_t word0 = ((reg_mmx->s16[offset] * source.s16[0]) >> 16) & 0xFFFF; + uint32_t word1 = ((reg_mmx->s16[offset + 1] * source.s16[1]) >> 16) & 0xFFFF; + uint32_t word2 = ((reg_mmx->s16[offset + 2] * source.s16[2]) >> 16) & 0xFFFF; + uint32_t word3 = ((reg_mmx->s16[offset + 3] * source.s16[3]) >> 16) & 0xFFFF; + + int32_t low = word0 | (word1 << 16); + int32_t high = word2 | (word3 << 16); + + write_mmx64s(low, high); +} + static void instr_0FE6() { unimplemented_sse(); } static void instr_0FE7() { unimplemented_sse(); } static void instr_660FE7() { From a3703ca5b72121769e7f95382dccef6723d5f7e5 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 16:25:52 +0530 Subject: [PATCH 0143/2137] Port pmullw --- src/native/instructions_0f.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index d2627f22..818365ae 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1871,7 +1871,27 @@ static void instr_0FD2() { unimplemented_sse(); } static void instr_0FD3() { unimplemented_sse(); } static void instr_660FD3() { unimplemented_sse(); } static void instr_0FD4() { unimplemented_sse(); } -static void instr_0FD5() { unimplemented_sse(); } + +static void instr_0FD5() +{ + // pmullw mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 2; + + int32_t word0 = ((reg_mmx->u16[offset]) * (source.u16[0])) & 0xFFFF; + int32_t word1 = ((reg_mmx->u16[offset + 1]) * (source.u16[1])) & 0xFFFF; + int32_t word2 = ((reg_mmx->u16[offset + 2]) * (source.u16[2])) & 0xFFFF; + int32_t word3 = ((reg_mmx->u16[offset + 3]) * (source.u16[3])) & 0xFFFF; + + int32_t low = word0 | word1 << 16; + int32_t high = word2 | word3 << 16; + + write_mmx64s(low, high); +} + static void instr_660FD5() { unimplemented_sse(); } static void instr_0FD6() { unimplemented_sse(); } static void instr_660FD6() { From 0737491025f95659bca9c570be7d764a32fee8fe Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 16:30:03 +0530 Subject: [PATCH 0144/2137] Port pshufw --- src/native/instructions_0f.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 818365ae..51d659ed 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1063,7 +1063,31 @@ static void instr_F30F6F() { write_xmm128s(data.u32[0], data.u32[1], data.u32[2], data.u32[3]); } -static void instr_0F70() { unimplemented_sse(); } + +static void instr_0F70() +{ + // 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; + uint32_t word0 = source.u32[word0_shift >> 1] >> ((word0_shift & 1) << 4) & 0xFFFF; + int32_t word1_shift = (order >> 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; + uint32_t word2 = source.u32[word2_shift >> 1] >> ((word2_shift & 1) << 4) & 0xFFFF; + uint32_t word3_shift = (order >> 6); + uint32_t word3 = source.u32[word3_shift >> 1] >> ((word3_shift & 1) << 4); + int32_t high = word2 | word3 << 16; + + write_mmx64s(low, high); +} + static void instr_660F70() { // pshufd xmm, xmm/mem128 task_switch_test_mmx(); From 4823528abd8a542fff36937ef02b12c4c62f515e Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 16:35:00 +0530 Subject: [PATCH 0145/2137] Port por mm, mm/m64 --- src/native/instructions_0f.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 51d659ed..383b4ae3 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2078,7 +2078,24 @@ static void instr_660FE7() { static void instr_0FE8() { unimplemented_sse(); } static void instr_0FE9() { unimplemented_sse(); } static void instr_0FEA() { unimplemented_sse(); } -static void instr_0FEB() { unimplemented_sse(); } + +static void instr_0FEB() +{ + // por mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + int32_t destination_low = reg_mmx32s[offset]; + int32_t destination_high = reg_mmx32s[offset + 1]; + + int32_t low = source.u32[0] | destination_low; + int32_t high = source.u32[1] | destination_high; + + write_mmx64s(low, high); +} + static void instr_660FEB() { unimplemented_sse(); } static void instr_0FEC() From 4b58f75690e1c08d93d85ed31ea3e049b7787ab1 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 17 Aug 2017 16:37:39 +0530 Subject: [PATCH 0146/2137] Port pslld mm, mm/m64 --- src/native/instructions_0f.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 383b4ae3..82da7606 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2162,7 +2162,30 @@ static void instr_660FEF() { static void instr_0FF0() { unimplemented_sse(); } static void instr_0FF1() { unimplemented_sse(); } -static void instr_0FF2() { unimplemented_sse(); } + +static void instr_0FF2() +{ + // pslld mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + int32_t destination_low = reg_mmx32s[offset]; + int32_t destination_high = reg_mmx32s[offset + 1]; + + uint32_t shift = source.u32[0]; + int32_t low = 0; + int32_t high = 0; + + if (shift <= 31) { + low = destination_low << shift; + high = destination_high << shift; + } + + write_mmx64s(low, high); +} + static void instr_0FF3() { unimplemented_sse(); } static void instr_0FF4() { unimplemented_sse(); } From 76fc5599ac402f8e6f6fb19072994c23b693de34 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 18 Aug 2017 12:02:56 +0530 Subject: [PATCH 0147/2137] Port psrld, psrad, pslld mm, imm8 --- src/native/instructions_0f.c | 75 +++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 82da7606..9e781afb 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1105,7 +1105,80 @@ static void instr_660F70() { static void instr_F20F70() { unimplemented_sse(); } static void instr_F30F70() { unimplemented_sse(); } static void instr_0F71() { unimplemented_sse(); } -static void instr_0F72() { unimplemented_sse(); } + +static void instr_0F72() +{ + task_switch_test_mmx(); + read_modrm_byte(); + + if(*modrm_byte < 0xC0) + { + trigger_ud(); + } + + uint32_t source = read_op8(); + uint32_t destination = (*modrm_byte & 7) << 1; + + uint32_t low = 0; + uint32_t high = 0; + int32_t shift = source; + + 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; + } +} + static void instr_0F73() { unimplemented_sse(); } static void instr_660F73() { unimplemented_sse(); } From bf6d2fe9aabce0ecbd28c9aac917da67382092c3 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 18 Aug 2017 12:32:52 +0530 Subject: [PATCH 0148/2137] Port psrad mm, mm/m64 --- src/native/instructions_0f.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 9e781afb..060f4f15 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2109,7 +2109,29 @@ static void instr_0FDF() static void instr_0FE0() { unimplemented_sse(); } static void instr_0FE1() { unimplemented_sse(); } -static void instr_0FE2() { unimplemented_sse(); } + +static void instr_0FE2() +{ + // psrad mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + int32_t destination_low = reg_mmx32s[offset]; + int32_t destination_high = reg_mmx32s[offset + 1]; + + uint32_t shift = source.u32[0]; + if (shift > 31) { + shift = 31; + } + + int32_t low = destination_low >> shift; + int32_t high = destination_high >> shift; + + write_mmx64s(low, high); +} + static void instr_0FE3() { unimplemented_sse(); } static void instr_0FE4() { unimplemented_sse(); } static void instr_660FE4() { unimplemented_sse(); } From 24eef010bb3169fb13dcf40817baa33599d2e858 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 18 Aug 2017 12:37:42 +0530 Subject: [PATCH 0149/2137] Port psllq --- src/native/instructions_0f.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 060f4f15..258e0d55 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2281,7 +2281,40 @@ static void instr_0FF2() write_mmx64s(low, high); } -static void instr_0FF3() { unimplemented_sse(); } + +static void instr_0FF3() +{ + // psllq mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + int32_t destination_low = reg_mmx32s[offset]; + int32_t destination_high = reg_mmx32s[offset + 1]; + + uint32_t shift = source.u32[0]; + + if(shift == 0) + { + return; + } + + int32_t low = 0; + int32_t high = 0; + + 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; + } + + write_mmx64s(low, high); +} + static void instr_0FF4() { unimplemented_sse(); } static void instr_0FF5() From b8b6208a589afc10cd219c2af1552117651effb2 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 18 Aug 2017 13:12:35 +0530 Subject: [PATCH 0150/2137] Port psllw --- src/native/instructions_0f.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 258e0d55..7024d084 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2256,7 +2256,35 @@ static void instr_660FEF() { } static void instr_0FF0() { unimplemented_sse(); } -static void instr_0FF1() { unimplemented_sse(); } + +static void instr_0FF1() +{ + // psllw mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + int32_t destination_low = reg_mmx32s[offset]; + int32_t destination_high = reg_mmx32s[offset + 1]; + + + uint32_t shift = source.u32[0]; + int32_t low = 0; + int32_t high = 0; + + if (shift <= 15) { + int32_t word0 = ((destination_low & 0xFFFF) << shift) & 0xFFFF; + int32_t word1 = (((uint32_t) destination_low) >> 16) << shift; + low = word0 | word1 << 16; + + int32_t word2 = ((destination_high & 0xFFFF) << shift) & 0xFFFF; + int32_t word3 = (((uint32_t) destination_high) >> 16) << shift; + high = word2 | word3 << 16; + } + + write_mmx64s(low, high); +} static void instr_0FF2() { From dee9469f7391075deb4ebeafa1c97ac0fe823182 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 18 Aug 2017 13:52:26 +0530 Subject: [PATCH 0151/2137] Port psraw --- src/native/instructions_0f.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 7024d084..8163d878 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2108,7 +2108,31 @@ static void instr_0FDF() } static void instr_0FE0() { unimplemented_sse(); } -static void instr_0FE1() { unimplemented_sse(); } + +static void instr_0FE1() +{ + // psraw mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 2; + + uint32_t shift = source.u32[0]; + if (shift > 15) { + shift = 16; + } + + int32_t word0 = (reg_mmx->s16[offset] >> shift) & 0xFFFF; + int32_t word1 = (reg_mmx->s16[offset + 1] >> shift) & 0xFFFF; + int32_t low = word0 | word1 << 16; + + int32_t word2 = (reg_mmx->s16[offset + 2] >> shift) & 0xFFFF; + int32_t word3 = (reg_mmx->s16[offset + 3] >> shift) & 0xFFFF; + int32_t high = word2 | word3 << 16; + + write_mmx64s(low, high); +} static void instr_0FE2() { From 737530a956bbb2e584076a5f2b75e64c76d40658 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 18 Aug 2017 13:55:29 +0530 Subject: [PATCH 0152/2137] Port psrld --- src/native/instructions_0f.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 8163d878..c25ea031 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1964,7 +1964,30 @@ static void instr_0FCF() { bswap(EDI); } static void instr_0FD0() { unimplemented_sse(); } static void instr_0FD1() { unimplemented_sse(); } -static void instr_0FD2() { unimplemented_sse(); } + +static void instr_0FD2() +{ + // psrld mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + int32_t destination_low = reg_mmx32s[offset]; + int32_t destination_high = reg_mmx32s[offset + 1]; + + uint32_t shift = source.u32[0]; + int32_t low = 0; + int32_t high = 0; + + if (shift <= 31) { + low = (uint32_t) destination_low >> shift; + high = (uint32_t) destination_high >> shift; + } + + write_mmx64s(low, high); +} + static void instr_0FD3() { unimplemented_sse(); } static void instr_660FD3() { unimplemented_sse(); } static void instr_0FD4() { unimplemented_sse(); } From 892402b358f827d0408592688213b464122f325b Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 18 Aug 2017 14:12:37 +0530 Subject: [PATCH 0153/2137] Port psrlw, psraw, psllw mm, imm8 --- src/native/instructions_0f.c | 82 +++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index c25ea031..3a8da83f 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1104,7 +1104,87 @@ static void instr_660F70() { } static void instr_F20F70() { unimplemented_sse(); } static void instr_F30F70() { unimplemented_sse(); } -static void instr_0F71() { unimplemented_sse(); } + +static void instr_0F71() +{ + read_modrm_byte(); + 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]; + + 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; + low = word0 | word1 << 16; + + word2 = ((destination_high << 16 >> 16) >> shift) & 0xFFFF; + word3 = ((destination_high >> 16) >> shift) & 0xFFFF; + 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; + } +} static void instr_0F72() { From 245a8d97c25c41d6a7ed198da0bc8094836d19c4 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 18 Aug 2017 14:27:12 +0530 Subject: [PATCH 0154/2137] Port psrlq, psllq mm, imm8 --- src/native/instructions_0f.c | 61 +++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 3a8da83f..b544d9f2 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1259,7 +1259,66 @@ static void instr_0F72() } } -static void instr_0F73() { unimplemented_sse(); } + +static void instr_0F73() +{ + read_modrm_byte(); + 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]; + + 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; + } + + 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; + } +} + static void instr_660F73() { unimplemented_sse(); } static void instr_0F74() From 0b5f304145470ae561504bd5ef6842c8d7365729 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 18 Aug 2017 15:25:58 +0530 Subject: [PATCH 0155/2137] Port psrlq xmm, imm8 --- src/native/instructions_0f.c | 49 +++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index b544d9f2..513a81dd 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1319,7 +1319,54 @@ static void instr_0F73() } } -static void instr_660F73() { unimplemented_sse(); } +static void instr_660F73() +{ + + read_modrm_byte(); + task_switch_test_mmx(); + + if(*modrm_byte < 0xC0) + { + trigger_ud(); + } + + 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; + } +} static void instr_0F74() { From f8f685cbc2ccceeee3f29a31a96487a0121a1ce4 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 18 Aug 2017 15:31:41 +0530 Subject: [PATCH 0156/2137] Port psrlq xmm, mm/m64 --- src/native/instructions_0f.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 513a81dd..a593e643 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2175,7 +2175,41 @@ static void instr_0FD2() } static void instr_0FD3() { unimplemented_sse(); } -static void instr_660FD3() { unimplemented_sse(); } + +static void instr_660FD3() +{ + // 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) + { + return; + } + + union reg128 destination = read_xmm128s(); + union reg128 result; + + if (shift <= 31) + { + result.u32[0] = destination.u32[0] >> shift | destination.u32[1] << (32 - shift); + result.u32[1] = destination.u32[1] >> shift; + + result.u32[2] = destination.u32[2] >> shift | destination.u32[3] << (32 - shift); + result.u32[3] = destination.u32[3] >> shift; + } + else if (shift <= 63) + { + result.u32[0] = destination.u32[1] >> shift; + result.u32[2] = destination.u32[3] >> shift; + } + + write_xmm128s(result.u32[0], result.u32[1], result.u32[2], result.u32[3]); +} + static void instr_0FD4() { unimplemented_sse(); } static void instr_0FD5() From 65fb37b432ac7c1a4af9cf57613e8c61a242c78c Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 18 Aug 2017 15:41:30 +0530 Subject: [PATCH 0157/2137] Port psrlq mm, mm/m64 --- src/native/instructions_0f.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index a593e643..5dfa800c 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2174,7 +2174,41 @@ static void instr_0FD2() write_mmx64s(low, high); } -static void instr_0FD3() { unimplemented_sse(); } + +static void instr_0FD3() +{ + // psrlq mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + int32_t destination_low = reg_mmx32s[offset]; + int32_t destination_high = reg_mmx32s[offset + 1]; + + uint32_t shift = source.u32[0]; + + if(shift == 0) + { + return; + } + + int32_t low = 0; + int32_t high = 0; + + 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; + } + + write_mmx64s(low, high); +} static void instr_660FD3() { From d760663bdd567ce68e414f1773787101b5d1c094 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 18 Aug 2017 15:45:03 +0530 Subject: [PATCH 0158/2137] Port psrlw mm, mm/m64 --- src/native/instructions_0f.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 5dfa800c..b4ebe0ec 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2149,7 +2149,34 @@ static void instr_0FCE() { bswap(ESI); } static void instr_0FCF() { bswap(EDI); } static void instr_0FD0() { unimplemented_sse(); } -static void instr_0FD1() { unimplemented_sse(); } + +static void instr_0FD1() +{ + // psrlw mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + int32_t destination_low = reg_mmx32s[offset]; + int32_t destination_high = reg_mmx32s[offset + 1]; + + uint32_t shift = source.u32[0]; + int32_t low = 0; + int32_t high = 0; + + if (shift <= 15) { + uint32_t word0 = (destination_low & 0xFFFF) >> shift; + uint32_t word1 = ((uint32_t) destination_low >> 16) >> shift; + low = word0 | word1 << 16; + + uint32_t word2 = ((uint32_t) destination_high & 0xFFFF) >> shift; + uint32_t word3 = ((uint32_t) destination_high >> 16) >> shift; + high = word2 | word3 << 16; + } + + write_mmx64s(low, high); +} static void instr_0FD2() { From 2110fdef09f0c180ab5591b7b86e69c999152afe Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 18 Aug 2017 15:47:20 +0530 Subject: [PATCH 0159/2137] Port psubb --- src/native/instructions_0f.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index b4ebe0ec..72532a64 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2696,7 +2696,32 @@ static void instr_0FF5() static void instr_0FF6() { unimplemented_sse(); } static void instr_0FF7() { unimplemented_sse(); } -static void instr_0FF8() { unimplemented_sse(); } + +static void instr_0FF8() +{ + // psubb mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + + int32_t reg_offset = (*modrm_byte >> 3 & 7) << 3; + + int32_t byte0 = (reg_mmx->s8[reg_offset] - source.s8[0]) & 0xFF; + int32_t byte1 = (reg_mmx->s8[reg_offset + 1] - source.s8[1]) & 0xFF; + int32_t byte2 = (reg_mmx->s8[reg_offset + 2] - source.s8[2]) & 0xFF; + int32_t byte3 = (reg_mmx->s8[reg_offset + 3] - source.s8[3]) & 0xFF; + int32_t byte4 = (reg_mmx->s8[reg_offset + 4] - source.s8[4]) & 0xFF; + int32_t byte5 = (reg_mmx->s8[reg_offset + 5] - source.s8[5]) & 0xFF; + int32_t byte6 = (reg_mmx->s8[reg_offset + 6] - source.s8[6]) & 0xFF; + int32_t byte7 = (reg_mmx->s8[reg_offset + 7] - source.s8[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); +} + static void instr_0FF9() { unimplemented_sse(); } static void instr_0FFA() { unimplemented_sse(); } static void instr_660FFA() { unimplemented_sse(); } From 738c7d88ac96918fea306ea4fc2aad5cbf0a91ac Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 18 Aug 2017 15:49:57 +0530 Subject: [PATCH 0160/2137] Port psubd xmm, xmm/m128 --- src/native/instructions_0f.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 72532a64..295566f2 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2724,7 +2724,24 @@ static void instr_0FF8() static void instr_0FF9() { unimplemented_sse(); } static void instr_0FFA() { unimplemented_sse(); } -static void instr_660FFA() { unimplemented_sse(); } + +static void instr_660FFA() +{ + // psubd xmm, xmm/m128 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg128 source = read_xmm_mem128s(); + union reg128 destination = read_xmm128s(); + + write_xmm128s( + destination.u32[0] - source.u32[0], + destination.u32[1] - source.u32[1], + destination.u32[2] - source.u32[2], + destination.u32[3] - source.u32[3] + ); +} + static void instr_0FFB() { unimplemented_sse(); } static void instr_0FFC() From db08ce5699e17ba7fb2b3dae0f603c02e96ea47f Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 18 Aug 2017 15:51:40 +0530 Subject: [PATCH 0161/2137] Port psubd mm, mm/m64 --- src/native/instructions_0f.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 295566f2..50e7032a 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2723,7 +2723,23 @@ static void instr_0FF8() } static void instr_0FF9() { unimplemented_sse(); } -static void instr_0FFA() { unimplemented_sse(); } + +static void instr_0FFA() +{ + // psubd mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + int32_t destination_low = reg_mmx32s[offset]; + int32_t destination_high = reg_mmx32s[offset + 1]; + + write_mmx64s( + destination_low - source.u32[0], + destination_high - source.u32[1] + ); +} static void instr_660FFA() { From 707215d415475500a694cf3ec433878578987f37 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 18 Aug 2017 15:53:47 +0530 Subject: [PATCH 0162/2137] Port psubsb --- src/native/instructions_0f.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 50e7032a..45dd1ebc 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2498,7 +2498,32 @@ static void instr_660FE7() { safe_write128(addr, data); } -static void instr_0FE8() { unimplemented_sse(); } + +static void instr_0FE8() +{ + // psubsb mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + + int32_t reg_offset = (*modrm_byte >> 3 & 7) << 3; + + int32_t byte0 = saturate_sd_to_sb(reg_mmx->s8[reg_offset] - source.s8[0]); + int32_t byte1 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 1] - source.s8[1]); + int32_t byte2 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 2] - source.s8[2]); + int32_t byte3 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 3] - source.s8[3]); + int32_t byte4 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 4] - source.s8[4]); + int32_t byte5 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 5] - source.s8[5]); + int32_t byte6 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 6] - source.s8[6]); + int32_t byte7 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 7] - source.s8[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); +} + static void instr_0FE9() { unimplemented_sse(); } static void instr_0FEA() { unimplemented_sse(); } From 3f1d028f9b0a08c44b2197e6b6b3257efd9eb817 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 18 Aug 2017 16:00:52 +0530 Subject: [PATCH 0163/2137] Port psubsw --- src/native/instructions_0f.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 45dd1ebc..0b356435 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2524,7 +2524,27 @@ static void instr_0FE8() write_mmx64s(low, high); } -static void instr_0FE9() { unimplemented_sse(); } + +static void instr_0FE9() +{ + // psubsw mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 2; + + int32_t word0 = saturate_sd_to_sw(reg_mmx->s16[offset] - source.s16[0]); + int32_t word1 = saturate_sd_to_sw(reg_mmx->s16[offset + 1] - source.s16[1]); + int32_t word2 = saturate_sd_to_sw(reg_mmx->s16[offset + 2] - source.s16[2]); + int32_t word3 = saturate_sd_to_sw(reg_mmx->s16[offset + 3] - source.s16[3]); + + int32_t low = word0 | word1 << 16; + int32_t high = word2 | word3 << 16; + + write_mmx64s(low, high); +} + static void instr_0FEA() { unimplemented_sse(); } static void instr_0FEB() From be8328741002839384cae43398262dac178c22c7 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 18 Aug 2017 16:03:21 +0530 Subject: [PATCH 0164/2137] Port psubusb --- src/native/instructions_0f.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 0b356435..34af2591 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2320,7 +2320,32 @@ static void instr_660FD7() { write_g32(result); } -static void instr_0FD8() { unimplemented_sse(); } + +static void instr_0FD8() +{ + // psubusb mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + + int32_t reg_offset = (*modrm_byte >> 3 & 7) << 3; + + int32_t byte0 = saturate_sd_to_ub(reg_mmx->u8[reg_offset] - source.u8[0]); + int32_t byte1 = saturate_sd_to_ub(reg_mmx->u8[reg_offset + 1] - source.u8[1]); + int32_t byte2 = saturate_sd_to_ub(reg_mmx->u8[reg_offset + 2] - source.u8[2]); + int32_t byte3 = saturate_sd_to_ub(reg_mmx->u8[reg_offset + 3] - source.u8[3]); + int32_t byte4 = saturate_sd_to_ub(reg_mmx->u8[reg_offset + 4] - source.u8[4]); + int32_t byte5 = saturate_sd_to_ub(reg_mmx->u8[reg_offset + 5] - source.u8[5]); + int32_t byte6 = saturate_sd_to_ub(reg_mmx->u8[reg_offset + 6] - source.u8[6]); + int32_t byte7 = saturate_sd_to_ub(reg_mmx->u8[reg_offset + 7] - 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); +} + static void instr_0FD9() { unimplemented_sse(); } static void instr_0FDA() { unimplemented_sse(); } static void instr_660FDA() { unimplemented_sse(); } From b217d91acc56b4a9b36d40fea0186c0437308f55 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 18 Aug 2017 16:08:19 +0530 Subject: [PATCH 0165/2137] Port psubusw --- src/native/instructions_0f.c | 37 +++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 34af2591..4237f76f 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2346,7 +2346,42 @@ static void instr_0FD8() write_mmx64s(low, high); } -static void instr_0FD9() { unimplemented_sse(); } + +static void instr_0FD9() +{ + // psubusw mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + int32_t destination_low = reg_mmx32s[offset]; + int32_t destination_high = reg_mmx32s[offset + 1]; + + int32_t word0 = (destination_low & 0xFFFF) - (source.u32[0] & 0xFFFF); + int32_t word1 = ((uint32_t) destination_low >> 16) - (source.u32[0] >> 16); + if (word0 < 0) { + word0 = 0; + } + if (word1 < 0) { + word1 = 0; + } + + int32_t word2 = (destination_high & 0xFFFF) - (source.u32[1] & 0xFFFF); + int32_t word3 = ((uint32_t) destination_high >> 16) - (source.u32[1] >> 16); + if (word2 < 0) { + word2 = 0; + } + if (word3 < 0) { + word3 = 0; + } + + int32_t low = word0 | word1 << 16; + int32_t high = word2 | word3 << 16; + + write_mmx64s(low, high); +} + static void instr_0FDA() { unimplemented_sse(); } static void instr_660FDA() { unimplemented_sse(); } From 6ce221a697a5787c93a9fa7a9511de3802086366 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 18 Aug 2017 16:08:29 +0530 Subject: [PATCH 0166/2137] Port psubw --- src/native/instructions_0f.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 4237f76f..34de4247 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2827,7 +2827,28 @@ static void instr_0FF8() write_mmx64s(low, high); } -static void instr_0FF9() { unimplemented_sse(); } + +static void instr_0FF9() +{ + // psubw mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + int32_t destination_low = reg_mmx32s[offset]; + int32_t destination_high = reg_mmx32s[offset + 1]; + + int32_t word0 = (destination_low - source.u32[0]) & 0xFFFF; + int32_t word1 = (((uint32_t) destination_low >> 16) - (source.u32[0] >> 16)) & 0xFFFF; + int32_t low = word0 | word1 << 16; + + int32_t word2 = (destination_high - source.u32[1]) & 0xFFFF; + int32_t word3 = (((uint32_t) destination_high >> 16) - (source.u32[1] >> 16)) & 0xFFFF; + int32_t high = word2 | word3 << 16; + + write_mmx64s(low, high); +} static void instr_0FFA() { From 06842dd25f5df9eaa7f06cb5ec61d0eb0f43fb47 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 18 Aug 2017 16:11:35 +0530 Subject: [PATCH 0167/2137] Port punpckhbw --- src/native/instructions_0f.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 34de4247..e4894411 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1010,7 +1010,32 @@ static void instr_0F67() static void instr_660F67() { unimplemented_sse(); } -static void instr_0F68() { unimplemented_sse(); } + +static void instr_0F68() +{ + // punpckhbw mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_mmx_mem64s(); + int32_t offset = (*modrm_byte >> 3 & 7) << 1; + uint32_t destination_high = reg_mmx32s[offset + 1]; + + int32_t byte0 = destination_high & 0xFF; + int32_t byte1 = source.u32[1] & 0xFF; + int32_t byte2 = (destination_high >> 8) & 0xFF; + int32_t byte3 = (source.u32[1] >> 8) & 0xFF; + int32_t byte4 = (destination_high >> 16) & 0xFF; + int32_t byte5 = (source.u32[1] >> 16) & 0xFF; + int32_t byte6 = destination_high >> 24; + int32_t byte7 = source.u32[1] >> 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); +} + static void instr_660F68() { unimplemented_sse(); } static void instr_0F69() { unimplemented_sse(); } static void instr_0F6A() { unimplemented_sse(); } From 0bc4ba79f148dbb6cd2e38f8b55e6d99550409de Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 18 Aug 2017 16:15:11 +0530 Subject: [PATCH 0168/2137] Port punpckhbw xmm, xmm/m128 --- src/native/instructions_0f.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index e4894411..a03c41a0 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1036,7 +1036,24 @@ static void instr_0F68() write_mmx64s(low, high); } -static void instr_660F68() { unimplemented_sse(); } + +static void instr_660F68() +{ + // punpckhbw xmm, xmm/m128 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg128 source = read_xmm_mem128s(); + union reg128 destination = read_xmm128s(); + + write_xmm128s( + 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 + ); +} + static void instr_0F69() { unimplemented_sse(); } static void instr_0F6A() { unimplemented_sse(); } From 641f9905d80b781474c5ab2aed11e2728a129f38 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Mon, 28 Aug 2017 11:04:21 +0530 Subject: [PATCH 0169/2137] Use bitwise OR instead of addition in read_mmx_mem64s --- src/native/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/cpu.c b/src/native/cpu.c index b184b890..a7479055 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -648,7 +648,7 @@ union reg64 read_mmx_mem64s() union reg64 x; int32_t i = (*modrm_byte & 7) << 1; x.u32[0] = reg_mmx32s[i]; - x.u32[1] = reg_mmx32s[i + 1]; + x.u32[1] = reg_mmx32s[i | 1]; return x; } From 787d115f499144719ce804f312550b2ea210487e Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Mon, 28 Aug 2017 11:05:05 +0530 Subject: [PATCH 0170/2137] Implement read_mmx64s to prevent code duplication --- src/native/cpu.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/native/cpu.c b/src/native/cpu.c index a7479055..fc581757 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -637,6 +637,15 @@ void write_e32(int32_t value) } } +union reg64 read_mmx64s() +{ + union reg64 x; + int32_t i = (*modrm_byte >> 3 & 7) << 1; + x.u32[0] = reg_mmx32s[i]; + x.u32[1] = reg_mmx32s[i | 1]; + return x; +} + union reg64 read_mmx_mem64s() { if(*modrm_byte < 0xC0) From 82f9d8ec11444133055d8b9f23bef16f80c1efff Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Mon, 28 Aug 2017 11:05:20 +0530 Subject: [PATCH 0171/2137] Port punpckhdq mm, mm/m64 --- src/native/instructions_0f.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index a03c41a0..ace61903 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1055,7 +1055,18 @@ static void instr_660F68() } static void instr_0F69() { unimplemented_sse(); } -static void instr_0F6A() { unimplemented_sse(); } + +static void instr_0F6A() +{ + // 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]); +} static void instr_0F6B() { From 58b14ed59b83f222318e0ac8faa407707f68d9cb Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Mon, 28 Aug 2017 11:35:50 +0530 Subject: [PATCH 0172/2137] Use union reg64 destination pattern instead of duplicated offset calculation in all instructions. --- src/native/instructions_0f.c | 227 ++++++++++++++--------------------- 1 file changed, 91 insertions(+), 136 deletions(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index ace61903..e16f9aa1 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -899,15 +899,13 @@ static void instr_0F63() { read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 1; - uint32_t destination_low = reg_mmx32s[offset]; - uint32_t destination_high = reg_mmx32s[offset + 1]; + union reg64 destination = read_mmx64s(); int32_t low = 0; - low |= (saturate_sw_to_sb((destination_low) & 0xFFFF)); - low |= (saturate_sw_to_sb(destination_low >> 16)) << 8; - low |= (saturate_sw_to_sb((destination_high) & 0xFFFF)) << 16; - low |= (saturate_sw_to_sb(destination_high >> 16)) << 24; + 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; int32_t high = 0; high |= (saturate_sw_to_sb((source.u32[0]) & 0xFFFF)); @@ -972,12 +970,10 @@ static void instr_0F66() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 1; - int32_t destination_low = reg_mmx32s[offset]; - int32_t destination_high = reg_mmx32s[offset + 1]; + union reg64 destination = read_mmx64s(); - int32_t low = destination_low > source.s32[0] ? -1 : 0; - int32_t high = destination_high > source.s32[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); } @@ -989,15 +985,13 @@ static void instr_0F67() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 1; - uint32_t destination_low = reg_mmx32s[offset]; - uint32_t destination_high = reg_mmx32s[offset + 1]; + union reg64 destination = read_mmx64s(); uint32_t low = 0; - low |= (saturate_sw_to_ub((destination_low) & 0xFFFF)); - low |= (saturate_sw_to_ub(destination_low >> 16)) << 8; - low |= (saturate_sw_to_ub((destination_high) & 0xFFFF)) << 16; - low |= (saturate_sw_to_ub(destination_high >> 16)) << 24; + 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; uint32_t high = 0; high |= (saturate_sw_to_ub((source.u32[0]) & 0xFFFF)); @@ -1018,16 +1012,15 @@ static void instr_0F68() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 1; - uint32_t destination_high = reg_mmx32s[offset + 1]; + union reg64 destination = read_mmx64s(); - int32_t byte0 = destination_high & 0xFF; + int32_t byte0 = destination.u32[1] & 0xFF; int32_t byte1 = source.u32[1] & 0xFF; - int32_t byte2 = (destination_high >> 8) & 0xFF; + int32_t byte2 = (destination.u32[1] >> 8) & 0xFF; int32_t byte3 = (source.u32[1] >> 8) & 0xFF; - int32_t byte4 = (destination_high >> 16) & 0xFF; + int32_t byte4 = (destination.u32[1] >> 16) & 0xFF; int32_t byte5 = (source.u32[1] >> 16) & 0xFF; - int32_t byte6 = destination_high >> 24; + int32_t byte6 = destination.u32[1] >> 24; int32_t byte7 = source.u32[1] >> 24; int32_t low = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24; @@ -1075,13 +1068,11 @@ static void instr_0F6B() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 1; - int32_t destination_low = reg_mmx32s[offset]; - int32_t destination_high = reg_mmx32s[offset + 1]; + union reg64 destination = read_mmx64s(); int32_t low = 0; - low |= saturate_sd_to_sw(destination_low); - low |= saturate_sd_to_sw(destination_high) << 16; + low |= saturate_sd_to_sw(destination.u32[0]); + low |= saturate_sd_to_sw(destination.u32[1]) << 16; int32_t high = 0; high |= saturate_sd_to_sw(source.u32[0]); @@ -1471,14 +1462,12 @@ static void instr_0F75() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = 2 * (*modrm_byte >> 3 & 7); - int32_t destination_low = reg_mmx32s[offset]; - int32_t destination_high = reg_mmx32s[offset + 1]; + union reg64 destination = read_mmx64s(); - int32_t word0 = (destination_low & 0xFFFF) == (source.u32[0] & 0xFFFF) ? 0xFFFF : 0; - int32_t word1 = (destination_low & 0xFFFF0000) == (source.u32[0] & 0xFFFF0000) ? 0xFFFF : 0; - int32_t word2 = (destination_high & 0xFFFF) == (source.u32[1] & 0xFFFF) ? 0xFFFF : 0; - int32_t word3 = (destination_high & 0xFFFF0000) == (source.u32[1] & 0xFFFF0000) ? 0xFFFF : 0; + 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 low = word0 | word1 << 16; int32_t high = word2 | word3 << 16; @@ -1495,12 +1484,10 @@ static void instr_0F76() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 1; - uint32_t destination_low = reg_mmx32s[offset]; - uint32_t destination_high = reg_mmx32s[offset + 1]; + union reg64 destination = read_mmx64s(); - int32_t low = destination_low == source.u32[0] ? -1 : 0; - int32_t high = destination_high == source.u32[1] ? -1 : 0; + 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); } @@ -2210,21 +2197,19 @@ static void instr_0FD1() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 1; - int32_t destination_low = reg_mmx32s[offset]; - int32_t destination_high = reg_mmx32s[offset + 1]; + union reg64 destination = read_mmx64s(); uint32_t shift = source.u32[0]; int32_t low = 0; int32_t high = 0; if (shift <= 15) { - uint32_t word0 = (destination_low & 0xFFFF) >> shift; - uint32_t word1 = ((uint32_t) destination_low >> 16) >> shift; + uint32_t word0 = (destination.u32[0] & 0xFFFF) >> shift; + uint32_t word1 = ((uint32_t) destination.u32[0] >> 16) >> shift; low = word0 | word1 << 16; - uint32_t word2 = ((uint32_t) destination_high & 0xFFFF) >> shift; - uint32_t word3 = ((uint32_t) destination_high >> 16) >> shift; + uint32_t word2 = ((uint32_t) destination.u32[1] & 0xFFFF) >> shift; + uint32_t word3 = ((uint32_t) destination.u32[1] >> 16) >> shift; high = word2 | word3 << 16; } @@ -2238,17 +2223,15 @@ static void instr_0FD2() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 1; - int32_t destination_low = reg_mmx32s[offset]; - int32_t destination_high = reg_mmx32s[offset + 1]; + union reg64 destination = read_mmx64s(); uint32_t shift = source.u32[0]; int32_t low = 0; int32_t high = 0; if (shift <= 31) { - low = (uint32_t) destination_low >> shift; - high = (uint32_t) destination_high >> shift; + low = (uint32_t) destination.u32[0] >> shift; + high = (uint32_t) destination.u32[1] >> shift; } write_mmx64s(low, high); @@ -2262,9 +2245,7 @@ static void instr_0FD3() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 1; - int32_t destination_low = reg_mmx32s[offset]; - int32_t destination_high = reg_mmx32s[offset + 1]; + union reg64 destination = read_mmx64s(); uint32_t shift = source.u32[0]; @@ -2278,12 +2259,12 @@ static void instr_0FD3() if(shift <= 31) { - low = (uint32_t) destination_low >> shift | (destination_high << (32 - shift)); - high = (uint32_t) destination_high >> shift; + low = (uint32_t) destination.u32[0] >> shift | (destination.u32[1] << (32 - shift)); + high = (uint32_t) destination.u32[1] >> shift; } else if(shift <= 63) { - low = (uint32_t) destination_high >> (shift & 0x1F); + low = (uint32_t) destination.u32[1] >> (shift & 0x1F); high = 0; } @@ -2407,12 +2388,10 @@ static void instr_0FD9() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 1; - int32_t destination_low = reg_mmx32s[offset]; - int32_t destination_high = reg_mmx32s[offset + 1]; + union reg64 destination = read_mmx64s(); - int32_t word0 = (destination_low & 0xFFFF) - (source.u32[0] & 0xFFFF); - int32_t word1 = ((uint32_t) destination_low >> 16) - (source.u32[0] >> 16); + int32_t word0 = (destination.u32[0] & 0xFFFF) - (source.u32[0] & 0xFFFF); + int32_t word1 = ((uint32_t) destination.u32[0] >> 16) - (source.u32[0] >> 16); if (word0 < 0) { word0 = 0; } @@ -2420,8 +2399,8 @@ static void instr_0FD9() word1 = 0; } - int32_t word2 = (destination_high & 0xFFFF) - (source.u32[1] & 0xFFFF); - int32_t word3 = ((uint32_t) destination_high >> 16) - (source.u32[1] >> 16); + int32_t word2 = (destination.u32[1] & 0xFFFF) - (source.u32[1] & 0xFFFF); + int32_t word3 = ((uint32_t) destination.u32[1] >> 16) - (source.u32[1] >> 16); if (word2 < 0) { word2 = 0; } @@ -2445,12 +2424,10 @@ static void instr_0FDB() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 1; - int32_t destination_low = reg_mmx32s[offset]; - int32_t destination_high = reg_mmx32s[offset + 1]; + union reg64 destination = read_mmx64s(); - int32_t low = source.u32[0] & destination_low; - int32_t high = source.u32[1] & destination_high; + int32_t low = source.u32[0] & destination.u32[0]; + int32_t high = source.u32[1] & destination.u32[1]; write_mmx64s(low, high); } @@ -2488,14 +2465,12 @@ static void instr_0FDD() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 1; - uint32_t destination_low = reg_mmx32s[offset]; - uint32_t destination_high = reg_mmx32s[offset + 1]; + union reg64 destination = read_mmx64s(); - int32_t word0 = saturate_uw((destination_low & 0xFFFF) + (source.u32[0] & 0xFFFF)); - int32_t word1 = saturate_uw((destination_low >> 16) + (source.u32[0] >> 16)); - int32_t word2 = saturate_uw((destination_high & 0xFFFF) + (source.u32[1] & 0xFFFF)); - int32_t word3 = saturate_uw((destination_high >> 16) + (source.u32[1] >> 16)); + 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 low = word0 | word1 << 16; int32_t high = word2 | word3 << 16; @@ -2514,12 +2489,10 @@ static void instr_0FDF() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 1; - int32_t destination_low = reg_mmx32s[offset]; - int32_t destination_high = reg_mmx32s[offset + 1]; + union reg64 destination = read_mmx64s(); - int32_t low = source.u32[0] & ~destination_low; - int32_t high = source.u32[1] & ~destination_high; + int32_t low = source.u32[0] & ~destination.u32[0]; + int32_t high = source.u32[1] & ~destination.u32[1]; write_mmx64s(low, high); } @@ -2558,17 +2531,15 @@ static void instr_0FE2() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 1; - int32_t destination_low = reg_mmx32s[offset]; - int32_t destination_high = reg_mmx32s[offset + 1]; + union reg64 destination = read_mmx64s(); uint32_t shift = source.u32[0]; if (shift > 31) { shift = 31; } - int32_t low = destination_low >> shift; - int32_t high = destination_high >> shift; + int32_t low = destination.s32[0] >> shift; + int32_t high = destination.s32[1] >> shift; write_mmx64s(low, high); } @@ -2667,12 +2638,10 @@ static void instr_0FEB() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 1; - int32_t destination_low = reg_mmx32s[offset]; - int32_t destination_high = reg_mmx32s[offset + 1]; + union reg64 destination = read_mmx64s(); - int32_t low = source.u32[0] | destination_low; - int32_t high = source.u32[1] | destination_high; + int32_t low = source.u32[0] | destination.u32[0]; + int32_t high = source.u32[1] | destination.u32[1]; write_mmx64s(low, high); } @@ -2750,9 +2719,7 @@ static void instr_0FF1() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 1; - int32_t destination_low = reg_mmx32s[offset]; - int32_t destination_high = reg_mmx32s[offset + 1]; + union reg64 destination = read_mmx64s(); uint32_t shift = source.u32[0]; @@ -2760,12 +2727,12 @@ static void instr_0FF1() int32_t high = 0; if (shift <= 15) { - int32_t word0 = ((destination_low & 0xFFFF) << shift) & 0xFFFF; - int32_t word1 = (((uint32_t) destination_low) >> 16) << shift; + int32_t word0 = ((destination.u32[0] & 0xFFFF) << shift) & 0xFFFF; + int32_t word1 = (((uint32_t) destination.u32[0]) >> 16) << shift; low = word0 | word1 << 16; - int32_t word2 = ((destination_high & 0xFFFF) << shift) & 0xFFFF; - int32_t word3 = (((uint32_t) destination_high) >> 16) << shift; + int32_t word2 = ((destination.u32[1] & 0xFFFF) << shift) & 0xFFFF; + int32_t word3 = (((uint32_t) destination.u32[1]) >> 16) << shift; high = word2 | word3 << 16; } @@ -2779,17 +2746,15 @@ static void instr_0FF2() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 1; - int32_t destination_low = reg_mmx32s[offset]; - int32_t destination_high = reg_mmx32s[offset + 1]; + union reg64 destination = read_mmx64s(); uint32_t shift = source.u32[0]; int32_t low = 0; int32_t high = 0; if (shift <= 31) { - low = destination_low << shift; - high = destination_high << shift; + low = destination.u32[0] << shift; + high = destination.u32[1] << shift; } write_mmx64s(low, high); @@ -2803,9 +2768,7 @@ static void instr_0FF3() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 1; - int32_t destination_low = reg_mmx32s[offset]; - int32_t destination_high = reg_mmx32s[offset + 1]; + union reg64 destination = read_mmx64s(); uint32_t shift = source.u32[0]; @@ -2818,11 +2781,11 @@ static void instr_0FF3() int32_t high = 0; if (shift <= 31) { - low = destination_low << shift; - high = destination_high << shift | (((uint32_t) destination_low) >> (32 - shift)); + low = destination.u32[0] << shift; + high = destination.u32[1] << shift | (((uint32_t) destination.u32[0]) >> (32 - shift)); } else if (shift <= 63) { - high = destination_low << (shift & 0x1F); + high = destination.u32[0] << (shift & 0x1F); low = 0; } @@ -2888,16 +2851,14 @@ static void instr_0FF9() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 1; - int32_t destination_low = reg_mmx32s[offset]; - int32_t destination_high = reg_mmx32s[offset + 1]; + union reg64 destination = read_mmx64s(); - int32_t word0 = (destination_low - source.u32[0]) & 0xFFFF; - int32_t word1 = (((uint32_t) destination_low >> 16) - (source.u32[0] >> 16)) & 0xFFFF; + 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 low = word0 | word1 << 16; - int32_t word2 = (destination_high - source.u32[1]) & 0xFFFF; - int32_t word3 = (((uint32_t) destination_high >> 16) - (source.u32[1] >> 16)) & 0xFFFF; + 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 high = word2 | word3 << 16; write_mmx64s(low, high); @@ -2910,13 +2871,11 @@ static void instr_0FFA() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 1; - int32_t destination_low = reg_mmx32s[offset]; - int32_t destination_high = reg_mmx32s[offset + 1]; + union reg64 destination = read_mmx64s(); write_mmx64s( - destination_low - source.u32[0], - destination_high - source.u32[1] + destination.u32[0] - source.u32[0], + destination.u32[1] - source.u32[1] ); } @@ -2971,16 +2930,14 @@ static void instr_0FFD() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 1; - uint32_t destination_low = reg_mmx32s[offset]; - uint32_t destination_high = reg_mmx32s[offset + 1]; + union reg64 destination = read_mmx64s(); - int32_t word0 = (destination_low + source.u32[0]) & 0xFFFF; - int32_t word1 = ((destination_low >> 16) + (source.u32[0] >> 16)) & 0xFFFF; + int32_t word0 = (destination.u32[0] + source.u32[0]) & 0xFFFF; + int32_t word1 = ((destination.u32[0] >> 16) + (source.u32[0] >> 16)) & 0xFFFF; int32_t low = word0 | word1 << 16; - int32_t word2 = (destination_high + source.u32[1]) & 0xFFFF; - int32_t word3 = ((destination_high >> 16) + (source.u32[1] >> 16)) & 0xFFFF; + int32_t word2 = (destination.u32[1] + source.u32[1]) & 0xFFFF; + int32_t word3 = ((destination.u32[1] >> 16) + (source.u32[1] >> 16)) & 0xFFFF; int32_t high = word2 | word3 << 16; write_mmx64s(low, high); @@ -2994,12 +2951,10 @@ static void instr_0FFE() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 1; - int32_t destination_low = reg_mmx32s[offset]; - int32_t destination_high = reg_mmx32s[offset + 1]; + union reg64 destination = read_mmx64s(); - int32_t low = destination_low + source.u32[0] | 0; - int32_t high = destination_high + source.u32[1] | 0; + int32_t low = destination.u32[0] + source.u32[0] | 0; + int32_t high = destination.u32[1] + source.u32[1] | 0; write_mmx64s(low, high); } From 257afe7ec358ff1ac469e8e04958a793c224a7da Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Mon, 28 Aug 2017 11:52:36 +0530 Subject: [PATCH 0173/2137] Port punpckhwd mm, mm/m64 --- src/native/instructions_0f.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index e16f9aa1..27608de9 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1047,7 +1047,26 @@ static void instr_660F68() ); } -static void instr_0F69() { unimplemented_sse(); } + +static void instr_0F69() +{ + // punpckhwd mm, mm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + + 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 low = word0 | word1 << 16; + int32_t high = word2 | word3 << 16; + + write_mmx64s(low, high); +} static void instr_0F6A() { From ec333182c15515409b662b40551e016bea518eac Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Mon, 28 Aug 2017 12:00:42 +0530 Subject: [PATCH 0174/2137] Port read_mmx_mem32s --- src/native/cpu.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/native/cpu.c b/src/native/cpu.c index fc581757..376689e2 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -646,6 +646,20 @@ union reg64 read_mmx64s() return x; } + +int32_t read_mmx_mem32s() +{ + if(*modrm_byte < 0xC0) + { + return safe_read32s(modrm_resolve(*modrm_byte)); + } + else + { + // Returning lower dword of qword + return reg_mmx32s[(*modrm_byte & 7) << 1]; + } +} + union reg64 read_mmx_mem64s() { if(*modrm_byte < 0xC0) From 4bd3eb8501544c1a0af891162a1ab399c6527809 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Mon, 28 Aug 2017 12:01:00 +0530 Subject: [PATCH 0175/2137] Port punpcklbw mm, mm/m32 --- src/native/instructions_0f.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 27608de9..55b4849e 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -875,7 +875,31 @@ static void instr_0F5D() { unimplemented_sse(); } static void instr_0F5E() { unimplemented_sse(); } static void instr_0F5F() { unimplemented_sse(); } -static void instr_0F60() { unimplemented_sse(); } + +static void instr_0F60() +{ + // punpcklbw mm, mm/m32 + task_switch_test_mmx(); + read_modrm_byte(); + + int32_t source = read_mmx_mem32s(); + union reg64 destination = read_mmx64s(); + + int32_t byte0 = destination.u32[0] & 0xFF; + int32_t byte1 = source & 0xFF; + int32_t byte2 = (destination.u32[0] >> 8) & 0xFF; + int32_t byte3 = (source >> 8) & 0xFF; + int32_t byte4 = (destination.u32[0] >> 16) & 0xFF; + int32_t byte5 = (source >> 16) & 0xFF; + int32_t byte6 = destination.u32[0] >> 24; + 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); +} + void instr_660F60() { // punpcklbw xmm, xmm/m128 task_switch_test_mmx(); From e8152bb6d2c350f0a86065b3395a0af3d7303dab Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Mon, 28 Aug 2017 12:03:36 +0530 Subject: [PATCH 0176/2137] Port punpckldq mm, mm/m32 --- src/native/instructions_0f.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 55b4849e..c04389e8 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -915,7 +915,18 @@ void instr_660F60() { } static void instr_0F61() { unimplemented_sse(); } static void instr_660F61() { unimplemented_sse(); } -static void instr_0F62() { unimplemented_sse(); } + +static void instr_0F62() +{ + // 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); +} static void instr_0F63() { // packsswb mm, mm/m64 From 87fc62e0fd536722911311d58f9277398aef5073 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Mon, 28 Aug 2017 12:07:27 +0530 Subject: [PATCH 0177/2137] Port punpcklwd mm, mm/m32 --- src/native/instructions_0f.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index c04389e8..b3bc278b 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -913,7 +913,27 @@ void instr_660F60() { destination.u8[6] | source.u8[6] << 8 | destination.u8[7] << 16 | source.u8[7] << 24 ); } -static void instr_0F61() { unimplemented_sse(); } + +static void instr_0F61() +{ + // punpcklwd mm, mm/m32 + task_switch_test_mmx(); + read_modrm_byte(); + + int32_t source = read_mmx_mem32s(); + union reg64 destination = read_mmx64s(); + + int32_t word0 = destination.u32[0] & 0xFFFF; + int32_t word1 = source & 0xFFFF; + int32_t word2 = destination.u32[0] >> 16; + int32_t word3 = source >> 16; + + int32_t low = word0 | word1 << 16; + int32_t high = word2 | word3 << 16; + + write_mmx64s(low, high); +} + static void instr_660F61() { unimplemented_sse(); } static void instr_0F62() From 64c49eee03585bc0bc3312406c603d41d3b2d004 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Mon, 28 Aug 2017 12:10:48 +0530 Subject: [PATCH 0178/2137] Port punpcklwd xmm, xmm/m128 --- src/native/instructions_0f.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index b3bc278b..f367534d 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -934,7 +934,23 @@ static void instr_0F61() write_mmx64s(low, high); } -static void instr_660F61() { unimplemented_sse(); } + +static void instr_660F61() +{ + // punpcklwd xmm, xmm/m128 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg64 source = read_xmm_mem64s(); + union reg64 destination = read_xmm64s(); + + write_xmm128s( + 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 + ); +} static void instr_0F62() { @@ -1569,7 +1585,6 @@ static void instr_0F76() static void instr_660F76() { unimplemented_sse(); } static void instr_0F77() { // emms - dbg_assert((*prefixes & (PREFIX_MASK_REP | PREFIX_MASK_OPSIZE)) == 0); if(cr[0] & (CR0_EM | CR0_TS)) { if(cr[0] & CR0_TS) { From 9184a87b1895616b531a662ff27bd22f2a18e484 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Mon, 28 Aug 2017 12:15:07 +0530 Subject: [PATCH 0179/2137] Port write_xmm64 --- src/native/cpu.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/native/cpu.c b/src/native/cpu.c index 376689e2..f612fc3f 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -738,6 +738,13 @@ union reg128 read_xmm_mem128s() } } +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; From 202033cbb57edb5a05bda8a3736fc98171826606 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Mon, 28 Aug 2017 12:56:14 +0530 Subject: [PATCH 0180/2137] Port movlpd --- src/native/instructions_0f.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index f367534d..4c74dab3 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -351,9 +351,27 @@ 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_660F12() { unimplemented_sse(); } + +static void instr_660F12() { + // movlpd xmm, xmm/m64 + task_switch_test_mmx(); + read_modrm_byte(); + union reg64 data = read_xmm_mem64s(); + write_xmm64(data.u32[0], data.u32[1]); +} + static void instr_0F13() { unimplemented_sse(); } -static void instr_660F13() { unimplemented_sse(); } + +static void instr_660F13() +{ + // 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]); +} + static void instr_0F14() { unimplemented_sse(); } static void instr_660F14() { unimplemented_sse(); } static void instr_0F15() { unimplemented_sse(); } From 2d6cfa9ede261817413fc9d661ee92323b139bff Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Mon, 28 Aug 2017 13:01:22 +0530 Subject: [PATCH 0181/2137] Port unpckpld --- src/native/instructions_0f.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 4c74dab3..34d6e209 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -373,7 +373,23 @@ static void instr_660F13() } static void instr_0F14() { unimplemented_sse(); } -static void instr_660F14() { unimplemented_sse(); } + +static void instr_660F14() +{ + // unpcklpd xmm, xmm/m128 + task_switch_test_mmx(); + read_modrm_byte(); + union reg64 source = read_xmm_mem64s(); + union reg64 destination = read_xmm64s(); + + write_xmm128s( + destination.u32[0], + destination.u32[1], + source.u32[0], + source.u32[1] + ); +} + static void instr_0F15() { unimplemented_sse(); } static void instr_0F16() { unimplemented_sse(); } static void instr_0F17() { unimplemented_sse(); } From 12ec029cebc328e96160f4ff6d3f964ea83464c8 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Mon, 28 Aug 2017 13:07:54 +0530 Subject: [PATCH 0182/2137] Port movaps --- src/native/instructions_0f.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 34d6e209..3eb916fd 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -562,8 +562,16 @@ static void instr_0F25() { undefined_instruction(); } static void instr_0F26() { undefined_instruction(); } static void instr_0F27() { undefined_instruction(); } -static void instr_0F28() { unimplemented_sse(); } static void instr_660F28() { unimplemented_sse(); } +static void instr_0F28() +{ + // movaps 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]); +} + static void instr_0F29() { // movaps xmm/m128, xmm task_switch_test_mmx(); From 90d9e838eba275eba824af353c13dd39e7092dd1 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Mon, 28 Aug 2017 13:08:15 +0530 Subject: [PATCH 0183/2137] Port movapd --- src/native/instructions_0f.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 3eb916fd..55b8e3eb 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -562,7 +562,6 @@ static void instr_0F25() { undefined_instruction(); } static void instr_0F26() { undefined_instruction(); } static void instr_0F27() { undefined_instruction(); } -static void instr_660F28() { unimplemented_sse(); } static void instr_0F28() { // movaps xmm, xmm/m128 @@ -572,6 +571,14 @@ static void instr_0F28() write_xmm128s(data.u32[0], data.u32[1], data.u32[2], data.u32[3]); } +static void instr_660F28() { + // movapd 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]); +} + static void instr_0F29() { // movaps xmm/m128, xmm task_switch_test_mmx(); From f6aaf38dba9c68a129cbe6e0a210a0ec5ba9b2d2 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Mon, 28 Aug 2017 13:11:22 +0530 Subject: [PATCH 0184/2137] Port movapd xmm/m128, xmm --- src/native/instructions_0f.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 55b8e3eb..c706cb13 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -589,7 +589,18 @@ static void instr_0F29() { int32_t addr = modrm_resolve(*modrm_byte); safe_write128(addr, data); } -static void instr_660F29() { unimplemented_sse(); } +static void instr_660F29() +{ + // movapd 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); +} + static void instr_0F2A() { unimplemented_sse(); } static void instr_0F2B() { unimplemented_sse(); } static void instr_660F2B() { unimplemented_sse(); } From edcc43189258771d709ac5b40352438cf081ff7e Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Mon, 28 Aug 2017 17:05:20 +0530 Subject: [PATCH 0185/2137] Port movntps and movntpd --- src/native/instructions_0f.c | 41 ++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index c706cb13..479f30b2 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -602,8 +602,45 @@ static void instr_660F29() } static void instr_0F2A() { unimplemented_sse(); } -static void instr_0F2B() { unimplemented_sse(); } -static void instr_660F2B() { unimplemented_sse(); } + +static void instr_0F2B() +{ + + task_switch_test_mmx(); + read_modrm_byte(); + + if(*modrm_byte >= 0xC0) + { + trigger_ud(); + } + + // movntps m128, xmm + // movntpd m128, xmm + + union reg128 data = read_xmm128s(); + int32_t addr = modrm_resolve(*modrm_byte); + safe_write128(addr, data); +} + +static void instr_660F2B() +{ + + task_switch_test_mmx(); + read_modrm_byte(); + + if(*modrm_byte >= 0xC0) + { + trigger_ud(); + } + + // movntps m128, xmm + // movntpd m128, xmm + + union reg128 data = read_xmm128s(); + int32_t addr = modrm_resolve(*modrm_byte); + safe_write128(addr, data); +} + static void instr_0F2C() { unimplemented_sse(); } static void instr_F20F2C() { unimplemented_sse(); } static void instr_0F2D() { unimplemented_sse(); } From 57566a7e8d1452387d47265d51587632a43e6fce Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 29 Aug 2017 16:48:43 +0530 Subject: [PATCH 0186/2137] Comment mentioning group of SSE instructions --- src/native/instructions_0f.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 479f30b2..1810863f 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -907,6 +907,7 @@ static void instr_0F37() { todo(); } +// sse3+ static void instr_0F38() { unimplemented_sse(); } static void instr_0F39() { unimplemented_sse(); } static void instr_0F3A() { unimplemented_sse(); } From cc4f9094753f2134c95cf9c594d7971ab2745053 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 29 Aug 2017 16:49:11 +0530 Subject: [PATCH 0187/2137] Port andps/andpd xmm, xmm/mem128 --- src/native/instructions_0f.c | 40 ++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 1810863f..5706d989 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -957,8 +957,44 @@ static void instr_0F50() { unimplemented_sse(); } static void instr_0F51() { unimplemented_sse(); } static void instr_0F52() { unimplemented_sse(); } static void instr_0F53() { unimplemented_sse(); } -static void instr_0F54() { unimplemented_sse(); } -static void instr_660F54() { unimplemented_sse(); } + +static void instr_0F54() +{ + // 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( + source.u32[0] & destination.u32[0], + source.u32[1] & destination.u32[1], + source.u32[2] & destination.u32[2], + source.u32[3] & destination.u32[3] + ); +} + +static void instr_660F54() { + // 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( + source.u32[0] & destination.u32[0], + source.u32[1] & destination.u32[1], + source.u32[2] & destination.u32[2], + source.u32[3] & destination.u32[3] + ); +} + static void instr_0F55() { unimplemented_sse(); } static void instr_0F56() { unimplemented_sse(); } static void instr_0F57() { unimplemented_sse(); } From 9e7fef8362fc0b5fa342ad00323e391610fef347 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 30 Aug 2017 08:43:29 +0530 Subject: [PATCH 0188/2137] Port xorps/xorpd xmm, xmm/mem128 --- src/native/instructions_0f.c | 39 ++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 5706d989..968d36b6 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -997,8 +997,43 @@ static void instr_660F54() { static void instr_0F55() { unimplemented_sse(); } static void instr_0F56() { unimplemented_sse(); } -static void instr_0F57() { unimplemented_sse(); } -static void instr_660F57() { unimplemented_sse(); } + +static void instr_0F57() +{ + // 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( + source.u32[0] ^ destination.u32[0], + source.u32[1] ^ destination.u32[1], + source.u32[2] ^ destination.u32[2], + source.u32[3] ^ destination.u32[3] + ); +} + +static void instr_660F57() { + // 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( + source.u32[0] ^ destination.u32[0], + source.u32[1] ^ destination.u32[1], + source.u32[2] ^ destination.u32[2], + source.u32[3] ^ destination.u32[3] + ); +} static void instr_0F58() { unimplemented_sse(); } static void instr_0F59() { unimplemented_sse(); } From 6d831a6840cb445b8e9dad516a31f2e9cc48767c Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 30 Aug 2017 08:55:53 +0530 Subject: [PATCH 0189/2137] Port packuswb xmm, xmm/m128 --- src/native/instructions_0f.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 968d36b6..9e8a30bc 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1242,7 +1242,24 @@ static void instr_0F67() write_mmx64s(low, high); } -static void instr_660F67() { unimplemented_sse(); } +static void instr_660F67() +{ + // packuswb xmm, xmm/m128 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg128 source = read_xmm_mem128s(); + union reg128 destination = read_xmm128s(); + union reg128 result; + + for(int32_t i = 0; i < 8; i++) + { + result.u8[i] = saturate_sw_to_ub(destination.u16[i]); + 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]); +} static void instr_0F68() From d7e5cfbfcff1f2b841a2c5edc2c0a84f4f797c43 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 30 Aug 2017 08:59:05 +0530 Subject: [PATCH 0190/2137] Port movd mm, r/m32 --- src/native/instructions_0f.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 9e8a30bc..377ac4e6 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1359,7 +1359,16 @@ static void instr_0F6B() static void instr_0F6C() { unimplemented_sse(); } static void instr_0F6D() { unimplemented_sse(); } -static void instr_0F6E() { unimplemented_sse(); } + +static void instr_0F6E() +{ + // movd mm, r/m32 + task_switch_test_mmx(); + read_modrm_byte(); + int32_t data = read_e32s(); + write_mmx64s(data, 0); +} + static void instr_660F6E() { // movd mm, r/m32 task_switch_test_mmx(); From 129eef6efa93a212a85f54c0e01a4989a69adf2b Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 30 Aug 2017 09:01:31 +0530 Subject: [PATCH 0191/2137] Port movq mm, mm/m64 --- src/native/instructions_0f.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 377ac4e6..dfe3124d 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1376,7 +1376,16 @@ static void instr_660F6E() { int32_t data = read_e32s(); write_xmm128s(data, 0, 0, 0); } -static void instr_0F6F() { unimplemented_sse(); } + +static void instr_0F6F() +{ + // 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]); +} + static void instr_660F6F() { // movdqa xmm, xmm/mem128 task_switch_test_mmx(); From 3014f009f9bad01c9a616d92f940dc89b60d5e76 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 30 Aug 2017 09:06:09 +0530 Subject: [PATCH 0192/2137] Port pshuflw xmm, xmm/m128, imm8 --- src/native/instructions_0f.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index dfe3124d..eb2cdbdb 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1440,7 +1440,23 @@ static void instr_660F70() { source.u32[order >> 6 & 3] ); } -static void instr_F20F70() { unimplemented_sse(); } + +static void instr_F20F70() +{ + // 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, + source.u32[2], + source.u32[3] + ); +} + static void instr_F30F70() { unimplemented_sse(); } static void instr_0F71() From 9ef5d853a97d7f46abc007bd5683140371b95a1a Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 30 Aug 2017 09:11:03 +0530 Subject: [PATCH 0193/2137] Port pshufhw xmm, xmm/m128, imm8 --- src/native/instructions_0f.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index eb2cdbdb..071ab9f4 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1457,7 +1457,22 @@ static void instr_F20F70() ); } -static void instr_F30F70() { unimplemented_sse(); } + +static void instr_F30F70() +{ + // 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( + 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 + ); +} static void instr_0F71() { From 1530bbddb935294256279d68a0fa7339545e14c8 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 30 Aug 2017 09:17:13 +0530 Subject: [PATCH 0194/2137] Port pcmpeqw xmm, xmm/m128 --- src/native/instructions_0f.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 071ab9f4..e8f1cd0b 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1800,7 +1800,22 @@ static void instr_0F75() write_mmx64s(low, high); } -static void instr_660F75() { unimplemented_sse(); } +static void instr_660F75() +{ + // pcmpeqw xmm, xmm/m128 + task_switch_test_mmx(); + read_modrm_byte(); + union reg128 source = read_xmm_mem128s(); + union reg128 destination = read_xmm128s(); + union reg128 result; + + for(int32_t i = 0; i < 8; i++) + { + 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]); +} static void instr_0F76() { From 2314d9586ca5c9e86e2d5242c3c62d2026d76dd1 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 30 Aug 2017 09:31:47 +0530 Subject: [PATCH 0195/2137] Port pcmpeqd xmm, xmm/m128 --- src/native/instructions_0f.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index e8f1cd0b..6bc9f848 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1832,7 +1832,22 @@ static void instr_0F76() write_mmx64s(low, high); } -static void instr_660F76() { unimplemented_sse(); } +static void instr_660F76() +{ + // pcmpeqd xmm, xmm/m128 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg128 source = read_xmm_mem128s(); + union reg128 destination = read_xmm128s(); + + write_xmm128s( + 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 + ); +} static void instr_0F77() { // emms From 33b359d29d73c60aca8667589611b4adddf19160 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 30 Aug 2017 09:35:00 +0530 Subject: [PATCH 0196/2137] Port movd r/m32, mm --- src/native/instructions_0f.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 6bc9f848..a4e03264 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1869,7 +1869,16 @@ static void instr_0F7A() { unimplemented_sse(); } static void instr_0F7B() { unimplemented_sse(); } static void instr_0F7C() { unimplemented_sse(); } static void instr_0F7D() { unimplemented_sse(); } -static void instr_0F7E() { unimplemented_sse(); } + +static void instr_0F7E() +{ + // movd r/m32, mm + task_switch_test_mmx(); + read_modrm_byte(); + union reg64 data = read_mmx64s(); + set_e32(data.u32[0]); +} + static void instr_660F7E() { // movd r/m32, xmm task_switch_test_mmx(); From 90551151fe62aa926e929ca6e9fc0eec4d39c5b4 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 30 Aug 2017 09:53:51 +0530 Subject: [PATCH 0197/2137] Fix warnings about semicolons after function definitions in cpu.c --- src/native/cpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/native/cpu.c b/src/native/cpu.c index f612fc3f..0a0b42a1 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -675,14 +675,14 @@ union reg64 read_mmx_mem64s() return x; } -}; +} void write_mmx64s(int32_t low, int32_t high) { int32_t offset = (*modrm_byte >> 3 & 7) << 1; reg_mmx32s[offset] = low; reg_mmx32s[offset + 1] = high; -}; +} union reg64 read_xmm64s() { From bd56185d4501ebbe3d34a1905b642eb16c3cf92b Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 30 Aug 2017 09:54:45 +0530 Subject: [PATCH 0198/2137] Port write_mmx_mem64s --- src/native/cpu.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/native/cpu.c b/src/native/cpu.c index 0a0b42a1..b2b5e555 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -684,6 +684,18 @@ void write_mmx64s(int32_t low, int32_t high) reg_mmx32s[offset + 1] = high; } +void write_mmx_mem64s(int32_t low, int32_t high) +{ + 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; From 41509abc49fe4530b4cc1a65a5058bb01ad066bf Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 30 Aug 2017 09:55:01 +0530 Subject: [PATCH 0199/2137] Port movq mm/m64, mm --- src/native/instructions_0f.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index a4e03264..9d40195b 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1893,7 +1893,16 @@ static void instr_F30F7E() { union reg64 data = read_xmm_mem64s(); write_xmm128s(data.u32[0], data.u32[1], 0, 0); } -static void instr_0F7F() { unimplemented_sse(); } + +static void instr_0F7F() +{ + // 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]); +} + static void instr_660F7F() { // movdqa xmm/m128, xmm task_switch_test_mmx(); From 120a63c26a1ac886e96861fdde2fc97f578ddf4d Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 30 Aug 2017 09:57:30 +0530 Subject: [PATCH 0200/2137] Port movnti --- src/native/instructions_0f.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 9d40195b..f26993c2 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2473,7 +2473,15 @@ static void instr32_0FC1() { read_modrm_byte(); static void instr_0FC2() { unimplemented_sse(); } -static void instr_0FC3() { unimplemented_sse(); } + +static void instr_0FC3() +{ + // movnti + read_modrm_byte(); + if(*modrm_byte >= 0xC0) trigger_ud(); + set_e32(read_g32s()); +} + static void instr_0FC4() { unimplemented_sse(); } static void instr_0FC5() { unimplemented_sse(); } static void instr_660FC5() { unimplemented_sse(); } From 57a0ae7c6ea662011e86b23e97c7d6c7e9905a95 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 30 Aug 2017 09:58:56 +0530 Subject: [PATCH 0201/2137] Port pextrw r32/m16, xmm, imm8 --- src/native/instructions_0f.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index f26993c2..737b5f64 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2484,7 +2484,21 @@ static void instr_0FC3() static void instr_0FC4() { unimplemented_sse(); } static void instr_0FC5() { unimplemented_sse(); } -static void instr_660FC5() { unimplemented_sse(); } + +static void instr_660FC5() { + // pextrw r32/m16, 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; + uint32_t result = data.u16[index]; + + write_g32(result); +} + static void instr_0FC6() { unimplemented_sse(); } static void instr_0FC7() { From 6bca04e227e512317ef76aca5d84db5f74cb95a9 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 30 Aug 2017 10:10:45 +0530 Subject: [PATCH 0202/2137] Port pmullw xmm, xmm/m128 --- src/native/instructions_0f.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 737b5f64..1155d45c 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2721,7 +2721,23 @@ static void instr_0FD5() write_mmx64s(low, high); } -static void instr_660FD5() { unimplemented_sse(); } + +static void instr_660FD5() +{ + // pmullw xmm, xmm/m128 + task_switch_test_mmx(); + read_modrm_byte(); + union reg128 source = read_xmm_mem128s(); + union reg128 destination = read_xmm128s(); + + write_xmm128s( + 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 + ); +} + static void instr_0FD6() { unimplemented_sse(); } static void instr_660FD6() { // movq xmm/m64, xmm From 09b3ab74470863e9817f8cbb077ff9edd9eb11c5 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 5 Sep 2017 13:58:58 +0530 Subject: [PATCH 0203/2137] Port pminub xmm, xmm/m128 --- src/native/instructions_0f.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 1155d45c..58ef520f 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2825,7 +2825,24 @@ static void instr_0FD9() } static void instr_0FDA() { unimplemented_sse(); } -static void instr_660FDA() { unimplemented_sse(); } + +static void instr_660FDA() +{ + // pminub xmm, xmm/m128 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg128 source = read_xmm_mem128s(); + union reg128 destination = read_xmm128s(); + union reg128 result; + + for(uint32_t i = 0; i < 16; i++) + { + 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]); +} static void instr_0FDB() { From d15762cdc1944c11ff4f2fe13e0c2096bcf9d0ea Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 5 Sep 2017 14:03:08 +0530 Subject: [PATCH 0204/2137] Port paddusb xmm, xmm/m128 --- src/native/instructions_0f.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 58ef520f..85dedecc 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2883,7 +2883,24 @@ static void instr_0FDC() write_mmx64s(low, high); } -static void instr_660FDC() { unimplemented_sse(); } + +static void instr_660FDC() +{ + // paddusb xmm, xmm/m128 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg128 source = read_xmm_mem128s(); + union reg128 destination = read_xmm128s(); + union reg128 result; + + for(uint32_t i = 0; i < 16; i++) + { + 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]); +} static void instr_0FDD() { From 5d61f965f0613c8767aa02e78821eabedab5d8ce Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 5 Sep 2017 14:06:33 +0530 Subject: [PATCH 0205/2137] Port paddusw xmm, xmm/m128 --- src/native/instructions_0f.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 85dedecc..93d7770e 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2922,7 +2922,24 @@ static void instr_0FDD() write_mmx64s(low, high); } -static void instr_660FDD() { unimplemented_sse(); } + +static void instr_660FDD() +{ + // paddusw xmm, xmm/m128 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg128 source = read_xmm_mem128s(); + union reg128 destination = read_xmm128s(); + + write_xmm128s( + 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 + ); +} + static void instr_0FDE() { unimplemented_sse(); } static void instr_660FDE() { unimplemented_sse(); } From d164284e6e7484618aa44399544f4c05afc0df51 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 5 Sep 2017 14:13:59 +0530 Subject: [PATCH 0206/2137] Port pmaxub xmm, xmm/m128 --- src/native/instructions_0f.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 93d7770e..90199dd7 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2941,7 +2941,24 @@ static void instr_660FDD() } static void instr_0FDE() { unimplemented_sse(); } -static void instr_660FDE() { unimplemented_sse(); } + +static void instr_660FDE() +{ + // pmaxub xmm, xmm/m128 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg128 source = read_xmm_mem128s(); + union reg128 destination = read_xmm128s(); + union reg128 result; + + for(uint32_t i = 0; i < 16; i++) + { + 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]); +} static void instr_0FDF() { From 91b6f27e634223be87fdb0320ac6cae84ea1a4cc Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 5 Sep 2017 14:57:14 +0530 Subject: [PATCH 0207/2137] Port pmulhuw --- src/native/instructions_0f.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 90199dd7..59310cc1 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -3024,7 +3024,23 @@ static void instr_0FE2() static void instr_0FE3() { unimplemented_sse(); } static void instr_0FE4() { unimplemented_sse(); } -static void instr_660FE4() { unimplemented_sse(); } + +static void instr_660FE4() +{ + // pmulhuw xmm, xmm/m128 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg128 source = read_xmm_mem128s(); + union reg128 destination = read_xmm128s(); + + write_xmm128s( + (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 + ); +} static void instr_0FE5() { From decc784f443dcc9827405027618da9dc209b39ea Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 5 Sep 2017 15:01:07 +0530 Subject: [PATCH 0208/2137] Mass refactor to use read_mmx64s instead of offset --- src/native/instructions_0f.c | 216 +++++++++++++++++------------------ 1 file changed, 107 insertions(+), 109 deletions(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 59310cc1..f3a7b1e3 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1164,17 +1164,16 @@ static void instr_0F64() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); + union reg64 destination = read_mmx64s(); - int32_t reg_offset = (*modrm_byte >> 3 & 7) << 3; - - int32_t byte0 = reg_mmx->s8[reg_offset] > source.s8[0] ? 0xFF : 0; - int32_t byte1 = reg_mmx->s8[reg_offset + 1] > source.s8[1] ? 0xFF : 0; - int32_t byte2 = reg_mmx->s8[reg_offset + 2] > source.s8[2] ? 0xFF : 0; - int32_t byte3 = reg_mmx->s8[reg_offset + 3] > source.s8[3] ? 0xFF : 0; - int32_t byte4 = reg_mmx->s8[reg_offset + 4] > source.s8[4] ? 0xFF : 0; - int32_t byte5 = reg_mmx->s8[reg_offset + 5] > source.s8[5] ? 0xFF : 0; - int32_t byte6 = reg_mmx->s8[reg_offset + 6] > source.s8[6] ? 0xFF : 0; - int32_t byte7 = reg_mmx->s8[reg_offset + 7] > source.s8[7] ? 0xFF : 0; + 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 low = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24; int32_t high = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24; @@ -1190,12 +1189,12 @@ static void instr_0F65() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 2; + union reg64 destination = read_mmx64s(); - int32_t word0 = (reg_mmx->s16[offset]) > (source.s16[0]) ? 0xFFFF : 0; - int32_t word1 = (reg_mmx->s16[offset + 1]) > (source.s16[1]) ? 0xFFFF : 0; - int32_t word2 = (reg_mmx->s16[offset + 2]) > (source.s16[2]) ? 0xFFFF : 0; - int32_t word3 = (reg_mmx->s16[offset + 3]) > (source.s16[3]) ? 0xFFFF : 0; + 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 low = word0 | word1 << 16; int32_t high = word2 | word3 << 16; @@ -1745,16 +1744,16 @@ static void instr_0F74() union reg64 source = read_mmx_mem64s(); - int32_t reg_offset = (*modrm_byte >> 3 & 7) << 3; + union reg64 destination = read_mmx64s(); - int32_t byte0 = reg_mmx->s8[reg_offset] == source.s8[0] ? 0xFF : 0; - int32_t byte1 = reg_mmx->s8[reg_offset + 1] == source.s8[1] ? 0xFF : 0; - int32_t byte2 = reg_mmx->s8[reg_offset + 2] == source.s8[2] ? 0xFF : 0; - int32_t byte3 = reg_mmx->s8[reg_offset + 3] == source.s8[3] ? 0xFF : 0; - int32_t byte4 = reg_mmx->s8[reg_offset + 4] == source.s8[4] ? 0xFF : 0; - int32_t byte5 = reg_mmx->s8[reg_offset + 5] == source.s8[5] ? 0xFF : 0; - int32_t byte6 = reg_mmx->s8[reg_offset + 6] == source.s8[6] ? 0xFF : 0; - int32_t byte7 = reg_mmx->s8[reg_offset + 7] == source.s8[7] ? 0xFF : 0; + 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 low = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24; int32_t high = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24; @@ -2708,12 +2707,12 @@ static void instr_0FD5() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 2; + union reg64 destination = read_mmx64s(); - int32_t word0 = ((reg_mmx->u16[offset]) * (source.u16[0])) & 0xFFFF; - int32_t word1 = ((reg_mmx->u16[offset + 1]) * (source.u16[1])) & 0xFFFF; - int32_t word2 = ((reg_mmx->u16[offset + 2]) * (source.u16[2])) & 0xFFFF; - int32_t word3 = ((reg_mmx->u16[offset + 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; @@ -2773,16 +2772,16 @@ static void instr_0FD8() union reg64 source = read_mmx_mem64s(); - int32_t reg_offset = (*modrm_byte >> 3 & 7) << 3; + union reg64 destination = read_mmx64s(); - int32_t byte0 = saturate_sd_to_ub(reg_mmx->u8[reg_offset] - source.u8[0]); - int32_t byte1 = saturate_sd_to_ub(reg_mmx->u8[reg_offset + 1] - source.u8[1]); - int32_t byte2 = saturate_sd_to_ub(reg_mmx->u8[reg_offset + 2] - source.u8[2]); - int32_t byte3 = saturate_sd_to_ub(reg_mmx->u8[reg_offset + 3] - source.u8[3]); - int32_t byte4 = saturate_sd_to_ub(reg_mmx->u8[reg_offset + 4] - source.u8[4]); - int32_t byte5 = saturate_sd_to_ub(reg_mmx->u8[reg_offset + 5] - source.u8[5]); - int32_t byte6 = saturate_sd_to_ub(reg_mmx->u8[reg_offset + 6] - source.u8[6]); - int32_t byte7 = saturate_sd_to_ub(reg_mmx->u8[reg_offset + 7] - source.u8[7]); + 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]); + int32_t byte2 = saturate_sd_to_ub(destination.u8[2] - source.u8[2]); + int32_t byte3 = saturate_sd_to_ub(destination.u8[3] - source.u8[3]); + int32_t byte4 = saturate_sd_to_ub(destination.u8[4] - source.u8[4]); + int32_t byte5 = saturate_sd_to_ub(destination.u8[5] - source.u8[5]); + int32_t byte6 = saturate_sd_to_ub(destination.u8[6] - source.u8[6]); + int32_t byte7 = saturate_sd_to_ub(destination.u8[7] - source.u8[7]); int32_t low = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24; int32_t high = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24; @@ -2866,16 +2865,16 @@ static void instr_0FDC() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t reg_offset = (*modrm_byte >> 3 & 7) << 3; + union reg64 destination = read_mmx64s(); - uint32_t byte0 = saturate_ud_to_ub(reg_mmx->u8[reg_offset] + source.u8[0]); - uint32_t byte1 = saturate_ud_to_ub(reg_mmx->u8[reg_offset + 1] + source.u8[1]); - uint32_t byte2 = saturate_ud_to_ub(reg_mmx->u8[reg_offset + 2] + source.u8[2]); - uint32_t byte3 = saturate_ud_to_ub(reg_mmx->u8[reg_offset + 3] + source.u8[3]); - uint32_t byte4 = saturate_ud_to_ub(reg_mmx->u8[reg_offset + 4] + source.u8[4]); - uint32_t byte5 = saturate_ud_to_ub(reg_mmx->u8[reg_offset + 5] + source.u8[5]); - uint32_t byte6 = saturate_ud_to_ub(reg_mmx->u8[reg_offset + 6] + source.u8[6]); - uint32_t byte7 = saturate_ud_to_ub(reg_mmx->u8[reg_offset + 7] + source.u8[7]); + 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]); + uint32_t byte2 = saturate_ud_to_ub(destination.u8[2] + source.u8[2]); + uint32_t byte3 = saturate_ud_to_ub(destination.u8[3] + source.u8[3]); + uint32_t byte4 = saturate_ud_to_ub(destination.u8[4] + source.u8[4]); + uint32_t byte5 = saturate_ud_to_ub(destination.u8[5] + source.u8[5]); + uint32_t byte6 = saturate_ud_to_ub(destination.u8[6] + source.u8[6]); + uint32_t byte7 = saturate_ud_to_ub(destination.u8[7] + source.u8[7]); int32_t low = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24; int32_t high = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24; @@ -2984,19 +2983,19 @@ static void instr_0FE1() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 2; + union reg64 destination = read_mmx64s(); uint32_t shift = source.u32[0]; if (shift > 15) { shift = 16; } - int32_t word0 = (reg_mmx->s16[offset] >> shift) & 0xFFFF; - int32_t word1 = (reg_mmx->s16[offset + 1] >> shift) & 0xFFFF; + int32_t word0 = (destination.s16[0] >> shift) & 0xFFFF; + int32_t word1 = (destination.s16[1] >> shift) & 0xFFFF; int32_t low = word0 | word1 << 16; - int32_t word2 = (reg_mmx->s16[offset + 2] >> shift) & 0xFFFF; - int32_t word3 = (reg_mmx->s16[offset + 3] >> shift) & 0xFFFF; + int32_t word2 = (destination.s16[2] >> shift) & 0xFFFF; + int32_t word3 = (destination.s16[3] >> shift) & 0xFFFF; int32_t high = word2 | word3 << 16; write_mmx64s(low, high); @@ -3049,12 +3048,12 @@ static void instr_0FE5() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 2; + union reg64 destination = read_mmx64s(); - uint32_t word0 = ((reg_mmx->s16[offset] * source.s16[0]) >> 16) & 0xFFFF; - uint32_t word1 = ((reg_mmx->s16[offset + 1] * source.s16[1]) >> 16) & 0xFFFF; - uint32_t word2 = ((reg_mmx->s16[offset + 2] * source.s16[2]) >> 16) & 0xFFFF; - uint32_t word3 = ((reg_mmx->s16[offset + 3] * source.s16[3]) >> 16) & 0xFFFF; + 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; int32_t low = word0 | (word1 << 16); int32_t high = word2 | (word3 << 16); @@ -3085,16 +3084,16 @@ static void instr_0FE8() union reg64 source = read_mmx_mem64s(); - int32_t reg_offset = (*modrm_byte >> 3 & 7) << 3; + union reg64 destination = read_mmx64s(); - int32_t byte0 = saturate_sd_to_sb(reg_mmx->s8[reg_offset] - source.s8[0]); - int32_t byte1 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 1] - source.s8[1]); - int32_t byte2 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 2] - source.s8[2]); - int32_t byte3 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 3] - source.s8[3]); - int32_t byte4 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 4] - source.s8[4]); - int32_t byte5 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 5] - source.s8[5]); - int32_t byte6 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 6] - source.s8[6]); - int32_t byte7 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 7] - source.s8[7]); + 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 low = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24; int32_t high = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24; @@ -3110,12 +3109,12 @@ static void instr_0FE9() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 2; + union reg64 destination = read_mmx64s(); - int32_t word0 = saturate_sd_to_sw(reg_mmx->s16[offset] - source.s16[0]); - int32_t word1 = saturate_sd_to_sw(reg_mmx->s16[offset + 1] - source.s16[1]); - int32_t word2 = saturate_sd_to_sw(reg_mmx->s16[offset + 2] - source.s16[2]); - int32_t word3 = saturate_sd_to_sw(reg_mmx->s16[offset + 3] - source.s16[3]); + 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 low = word0 | word1 << 16; int32_t high = word2 | word3 << 16; @@ -3150,16 +3149,16 @@ static void instr_0FEC() union reg64 source = read_mmx_mem64s(); - int32_t reg_offset = (*modrm_byte >> 3 & 7) << 3; + union reg64 destination = read_mmx64s(); - uint32_t byte0 = saturate_sd_to_sb(reg_mmx->s8[reg_offset] + source.s8[0]); - uint32_t byte1 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 1] + source.s8[1]); - uint32_t byte2 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 2] + source.s8[2]); - uint32_t byte3 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 3] + source.s8[3]); - uint32_t byte4 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 4] + source.s8[4]); - uint32_t byte5 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 5] + source.s8[5]); - uint32_t byte6 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 6] + source.s8[6]); - uint32_t byte7 = saturate_sd_to_sb(reg_mmx->s8[reg_offset + 7] + source.s8[7]); + 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]); int32_t low = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24; int32_t high = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24; @@ -3173,12 +3172,12 @@ static void instr_0FED() { read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 2; + union reg64 destination = read_mmx64s(); - int32_t word0 = saturate_sd_to_sw((reg_mmx->s16[offset]) + (source.s16[0])); - int32_t word1 = saturate_sd_to_sw((reg_mmx->s16[offset + 1]) + (source.s16[1])); - int32_t word2 = saturate_sd_to_sw((reg_mmx->s16[offset + 2]) + (source.s16[2])); - int32_t word3 = saturate_sd_to_sw((reg_mmx->s16[offset + 3]) + (source.s16[3])); + 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 low = word0 | word1 << 16; int32_t high = word2 | word3 << 16; @@ -3295,12 +3294,12 @@ static void instr_0FF5() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); - int32_t offset = (*modrm_byte >> 3 & 7) << 2; + union reg64 destination = read_mmx64s(); - int32_t mul0 = (reg_mmx->s16[offset] * (source.s16[0])); - int32_t mul1 = (reg_mmx->s16[offset + 1] * (source.s16[1])); - int32_t mul2 = (reg_mmx->s16[offset + 2] * (source.s16[2])); - int32_t mul3 = (reg_mmx->s16[offset + 3] * (source.s16[3])); + 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 low = mul0 + mul1 | 0; int32_t high = mul2 + mul3 | 0; @@ -3320,16 +3319,16 @@ static void instr_0FF8() union reg64 source = read_mmx_mem64s(); - int32_t reg_offset = (*modrm_byte >> 3 & 7) << 3; + union reg64 destination = read_mmx64s(); - int32_t byte0 = (reg_mmx->s8[reg_offset] - source.s8[0]) & 0xFF; - int32_t byte1 = (reg_mmx->s8[reg_offset + 1] - source.s8[1]) & 0xFF; - int32_t byte2 = (reg_mmx->s8[reg_offset + 2] - source.s8[2]) & 0xFF; - int32_t byte3 = (reg_mmx->s8[reg_offset + 3] - source.s8[3]) & 0xFF; - int32_t byte4 = (reg_mmx->s8[reg_offset + 4] - source.s8[4]) & 0xFF; - int32_t byte5 = (reg_mmx->s8[reg_offset + 5] - source.s8[5]) & 0xFF; - int32_t byte6 = (reg_mmx->s8[reg_offset + 6] - source.s8[6]) & 0xFF; - int32_t byte7 = (reg_mmx->s8[reg_offset + 7] - source.s8[7]) & 0xFF; + 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 low = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24; int32_t high = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24; @@ -3399,17 +3398,16 @@ static void instr_0FFC() read_modrm_byte(); union reg64 source = read_mmx_mem64s(); + union reg64 destination = read_mmx64s(); - uint32_t reg_offset = 8 * (*modrm_byte >> 3 & 7); - - uint8_t byte0 = (reg_mmx->u8[reg_offset] + source.u8[0]) & 0xFF; - uint8_t byte1 = (reg_mmx->u8[reg_offset + 1] + source.u8[1]) & 0xFF; - uint8_t byte2 = (reg_mmx->u8[reg_offset + 2] + source.u8[2]) & 0xFF; - uint8_t byte3 = (reg_mmx->u8[reg_offset + 3] + source.u8[3]) & 0xFF; - uint8_t byte4 = (reg_mmx->u8[reg_offset + 4] + source.u8[4]) & 0xFF; - uint8_t byte5 = (reg_mmx->u8[reg_offset + 5] + source.u8[5]) & 0xFF; - uint8_t byte6 = (reg_mmx->u8[reg_offset + 6] + source.u8[6]) & 0xFF; - uint8_t byte7 = (reg_mmx->u8[reg_offset + 7] + source.u8[7]) & 0xFF; + uint8_t byte0 = (destination.u8[0] + source.u8[0]) & 0xFF; + uint8_t byte1 = (destination.u8[1] + source.u8[1]) & 0xFF; + uint8_t byte2 = (destination.u8[2] + source.u8[2]) & 0xFF; + uint8_t byte3 = (destination.u8[3] + source.u8[3]) & 0xFF; + uint8_t byte4 = (destination.u8[4] + source.u8[4]) & 0xFF; + uint8_t byte5 = (destination.u8[5] + source.u8[5]) & 0xFF; + uint8_t byte6 = (destination.u8[6] + source.u8[6]) & 0xFF; + uint8_t byte7 = (destination.u8[7] + source.u8[7]) & 0xFF; uint32_t low = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24; uint32_t high = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24; From ee8a2b484e2994b73d0e0e376d291e5cc0cf1253 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 5 Sep 2017 15:19:33 +0530 Subject: [PATCH 0209/2137] Port por xmm, xmm/m128 --- src/native/instructions_0f.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index f3a7b1e3..b54f681b 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -3139,7 +3139,23 @@ static void instr_0FEB() write_mmx64s(low, high); } -static void instr_660FEB() { unimplemented_sse(); } + +static void instr_660FEB() +{ + // por xmm, xmm/m128 + task_switch_test_mmx(); + read_modrm_byte(); + + union reg128 source = read_xmm_mem128s(); + union reg128 destination = read_xmm128s(); + + write_xmm128s( + source.u32[0] | destination.u32[0], + source.u32[1] | destination.u32[1], + source.u32[2] | destination.u32[2], + source.u32[3] | destination.u32[3] + ); +} static void instr_0FEC() { From ba2abe2123e760097cd91c051af3dd5d8e0d3243 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 5 Sep 2017 15:24:20 +0530 Subject: [PATCH 0210/2137] Port pxor mm, mm/m64 --- src/native/instructions_0f.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index b54f681b..7e85f6a2 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -3202,7 +3202,19 @@ static void instr_0FED() { } static void instr_0FEE() { unimplemented_sse(); } -static void instr_0FEF() { unimplemented_sse(); } + +static void instr_0FEF() +{ + // 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]); +} + static void instr_660FEF() { // pxor xmm, xmm/m128 task_switch_test_mmx(); From 650de5d7d782ae4ac9ff1fc2ed892aded385dae1 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 7 Sep 2017 18:41:06 +0530 Subject: [PATCH 0211/2137] Skip cvttsd2si test (due to emscripten bug) --- tests/nasm/create_tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/nasm/create_tests.js b/tests/nasm/create_tests.js index c28ff1fa..168d1fb1 100755 --- a/tests/nasm/create_tests.js +++ b/tests/nasm/create_tests.js @@ -407,7 +407,7 @@ const encodings = [ { opcode: 0x0F2B, only_mem: 1, e: 1, g: 1 }, { opcode: 0x660F2B, only_mem: 1, e: 1, g: 1 }, - { opcode: 0xF20F2C, e: 1, g: 1 }, + { opcode: 0xF20F2C, e: 1, g: 1, skip: 1 }, { opcode: 0x0F54, e: 1, g: 1 }, { opcode: 0x660F54, e: 1, g: 1 }, From d8a63a88d049353ae4d9adb46556f162dd1daae2 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 7 Sep 2017 18:43:32 +0530 Subject: [PATCH 0212/2137] Port cvttsd2si (may throw "integer result unrepresentable") --- src/native/global_pointers.h | 1 + src/native/instructions_0f.c | 23 ++++++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index 4da53321..3287136b 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -72,6 +72,7 @@ union reg64 { uint8_t u8[8]; uint16_t u16[4]; uint32_t u32[2]; + double d64[1]; }; int32_t* const reg_xmm32s = (int32_t* const) 828; // length 128 diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 7e85f6a2..fe9289f9 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -642,7 +642,28 @@ static void instr_660F2B() } static void instr_0F2C() { unimplemented_sse(); } -static void instr_F20F2C() { unimplemented_sse(); } + +static void instr_F20F2C() +{ + // 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(); + union reg64 source = read_xmm_mem64s(); + double f = source.d64[0]; + + if(f <= 0x7FFFFFFF && f >= -0x80000000) + { + int32_t si = (int32_t) f; + write_g32(si); + } + else + { + write_g32(0x80000000); + } +} + static void instr_0F2D() { unimplemented_sse(); } static void instr_0F2E() { unimplemented_sse(); } static void instr_0F2F() { unimplemented_sse(); } From 966f61616cbdbab7f07e7980b7440a61b0e294a5 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 22 Sep 2017 21:25:45 +0530 Subject: [PATCH 0213/2137] Minor refactor based on feedback --- src/native/cpu.c | 10 +++++----- src/native/global_pointers.h | 2 +- src/native/instructions_0f.c | 16 +++++++--------- tests/nasm/create_tests.js | 2 ++ 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/native/cpu.c b/src/native/cpu.c index b2b5e555..16009e26 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -681,7 +681,7 @@ void write_mmx64s(int32_t low, int32_t high) { int32_t offset = (*modrm_byte >> 3 & 7) << 1; reg_mmx32s[offset] = low; - reg_mmx32s[offset + 1] = high; + reg_mmx32s[offset | 1] = high; } void write_mmx_mem64s(int32_t low, int32_t high) @@ -692,7 +692,7 @@ void write_mmx_mem64s(int32_t low, int32_t high) } else { int32_t offset = (*modrm_byte & 7) << 1; reg_mmx32s[offset] = low; - reg_mmx32s[offset + 1] = high; + reg_mmx32s[offset | 1] = high; } } @@ -761,9 +761,9 @@ 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_xmm32s[i | 1] = d1; + reg_xmm32s[i | 2] = d2; + reg_xmm32s[i | 3] = d3; } void clear_tlb() diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index 3287136b..731f21da 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -72,7 +72,7 @@ union reg64 { uint8_t u8[8]; uint16_t u16[4]; uint32_t u32[2]; - double d64[1]; + double f64[1]; }; int32_t* const reg_xmm32s = (int32_t* const) 828; // length 128 diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index fe9289f9..72b4168b 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -605,7 +605,8 @@ static void instr_0F2A() { unimplemented_sse(); } static void instr_0F2B() { - + // movntps m128, xmm + // movntpd m128, xmm task_switch_test_mmx(); read_modrm_byte(); @@ -614,9 +615,6 @@ static void instr_0F2B() trigger_ud(); } - // movntps m128, xmm - // movntpd m128, xmm - union reg128 data = read_xmm128s(); int32_t addr = modrm_resolve(*modrm_byte); safe_write128(addr, data); @@ -651,7 +649,7 @@ static void instr_F20F2C() task_switch_test_mmx(); read_modrm_byte(); union reg64 source = read_xmm_mem64s(); - double f = source.d64[0]; + double f = source.f64[0]; if(f <= 0x7FFFFFFF && f >= -0x80000000) { @@ -3350,8 +3348,8 @@ static void instr_0FF5() int32_t mul2 = (destination.s16[2] * (source.s16[2])); int32_t mul3 = (destination.s16[3] * (source.s16[3])); - int32_t low = mul0 + mul1 | 0; - int32_t high = mul2 + mul3 | 0; + int32_t low = mul0 + mul1; + int32_t high = mul2 + mul3; write_mmx64s(low, high); } @@ -3494,8 +3492,8 @@ static void instr_0FFE() union reg64 source = read_mmx_mem64s(); union reg64 destination = read_mmx64s(); - int32_t low = destination.u32[0] + source.u32[0] | 0; - int32_t high = destination.u32[1] + source.u32[1] | 0; + int32_t low = destination.u32[0] + source.u32[0]; + int32_t high = destination.u32[1] + source.u32[1]; write_mmx64s(low, high); } diff --git a/tests/nasm/create_tests.js b/tests/nasm/create_tests.js index 168d1fb1..3df06f53 100755 --- a/tests/nasm/create_tests.js +++ b/tests/nasm/create_tests.js @@ -407,6 +407,8 @@ const encodings = [ { 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 }, From 975a06269e406c47702b15c5a28520a779568842 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 8 May 2020 23:39:42 +0200 Subject: [PATCH 0214/2137] Squash 2e469796 Minor fab422ef Improve generation of 0f instructions 08ad7fe9 Improved if-else generation 3f81014d Minor: Align test output 4a3a84ef Generate modrm tests 61aa1875 Simplify a6e47954 Generate decoding of immediate operands 435b2c10 Fix warnings e4933042 Add missing immediate operand 3f3810c7 Generate immediate operands for instructions with modrm byte a0aa7b1f Make memory layout in nasm tests clearer 6b8ef212 Remove 'g' property from instruction table (implied by 'e') bf15c58c Remove unused declarations 1e543035 Remove useless `| 0` and `>>> 0` javascriptisms 1ccc5d53 Fix headers 8b40c532 Update qemu tests with changes from qemu ec9b0fb5 Port xchg instructions to C c73613e7 Port virt_boundary_* to C d61d1241 Add headers fd19f22c Make written value in write8 and write16 int32_t 497dcaec Generate read_imm for instructions with a modrm byte 8b7003d6 Generate read_imm8s 0cc75498 Remove read_op 9d716086 Trigger unimplemented_sse for partial sse instructions with prefix 8d5edd03 Remove unimplmented sse c-to-js hack 585d3565 Remove | 0 308124b2 Use int32_t as return value f193f8e1 Use JS version of cvttsd2si for now 12747b97 Generate trigger_ud for missing modrm branches 770f674e Split 0f00 and 0f01 into multiple instructions depending on modrm bits 1cb372a3 Generate decoder for some 0f-prefix instructions cec7bc63 Disable unused parameter warnings in instruction functions 807665b1 Generate read_imm for 0f/jmpcc cdf6eccc Generate modrm decoding for shld 04528429 Create temporary files in /tmp/, not cwd d8f3fbd8 Generate modrm/imm decoding for shld 00ef0942 Generate modrm decoding for bts f531984b Generate modrm decoding for shrd and imul 07569c53 Generate modrm decoding cmpxchg 535ff190 Generate modrm decoding for lfs/lgs/lss 2f8ced8d Generate modrm decoding for btr and btc 95de6c66 Generate modrm decoding for movzx c4d07e7e Generate modrm decoding for bsf and bsr f0985d26 Generate modrm decoding for movsx 4b30937a Generate modrm decoding for xadd a422eb27 Generate modrm decoding for movnti e5501d3c Generate modrm decoding for mov to/from control/debug registers bce11ec5 Generate modrm decoding for lar/lsl 5729a23c Fix access to DR4 and DR5 when cr4.DE is clear 44269a81 Specify immediate size explicitly instead of inferring it 82b2867a Fix STR instruction 98a9cc89 Log failing assertion 6d2f9964 Fix rdtsc 00260694 Log GP exceptions 7916883d Port trigger_ud and trigger_nm to C 36fedae9 Remove unused code e08fabd0 Generate modrm decoding for 0f00 and 0f01 8ae8174d Generate modrm decoding for 0fae and 0fc7 (fxsave, cmpxchg8, etc.) 26168164 Generate modrm+immediate decoding for 0fba (bit test with immediate operand) 6adf7fa7 Simplify create_tests.js (unused prefix call) c77cbdd8 Add comments about the implementation of pop [addr] 4640b4fe Simplify prefix call a81a5497 Don't use var 3ca5d13d Separate call name and arguments in code generator 3191a543 Simplify other prefix call (8D/lea) 5185080e Update generated code (stylistic changes and #ud generation) 93b51d41 Remove unused wasm externals e4af0a7f Avoid hardcoding special cases in code generator (lea, pop r/m) 654a2b49 Avoid hardcoding special cases in code generator (enter/jumpf/callf) fd1a1e86 Commit generated code (only stylistic changes) 7310fd1a Simplify code generator by merging code for with and without 0f prefix e7eae4af Simplify code generator by merging code for immediate operands 00fafd8a Improve assertions db084e49 Simplify code generator (modrm if-else) 0a0e4c9e Improve code generation of switch-case ce292795 Clarify some comments 37cf33fa Generate code in if/else blocks cbcc33fc Document naming scheme e30b97eb Generate modrm decoding for 0f12 (sse) instruction 24b72c2f movlpd cannot be used for register-to-register moves 72d72995 Generate modrm decoding for 0f13 (sse) instruction and disable register-to-register moving 75d76fbb Generate modrm decoding for 0f14 (sse) instruction ac8965a7 Generate modrm decoding for 0f28-0f2b (movap, movntp) e919d33e Generate modrm decoding for cvttsd2si 5f2ca2b4 Generate modrm decoding for andp and xorp c8d1c6de Generate modrm decoding for 0f60-0f70 (sse instructions) ae4ed46d Add multi-byte nop and prefetch to nasm test, generate modrm decoding 718a1acf Print qemu test error message more useful d1ecc37e Generate modrm decoding for 0f70-0f80 (sse instructions) 6a7219a5 Generate modrm decoding for popcnt 25278217 Generate modrm decoding for 0f71-0f73 (sse shift with immediate byte) ed1ec81b Generate modrm decoding for the remaining sse instructions (0fc0-0fff) 42bc5a6f Use 64-bit multiplication for native code dda3fb39 Remove old modrm-decoding functions 717975ef Move register access functions to cpu.c aee8138f Remove read_op, read_sib, read_op0F, read_disp f31317f2 Rename xmm/mmx register access functions a525e70b Remove 32-bit access to reg_xmm and reg_mmx c803eabc Rename s8/s16/s32 to i8/i16/i32 9fbd2ddf Don't use uninitialised structs 942eb4f7 Use 64-bit load for mmx registers and assert reg64 and reg128 size f94ec612 Use 64-bit writes for write_xmm64 08022de9 Use more efficient method for some 128-bit stores 9d5b084c Make timestamp counter unsigned 2ef388b3 Pass 64-bit value to safe_write64 4cb2b1be Optimise safe_write64 and safe_write128 b0ab09fb Implement psllq (660ff3) 9935e5d4 Optimise safe_read64s and safe_read128s af9ea1cc Log cl in cpuid only if relevant be5fe23e Add multi-op cache (disabled by default through ENABLE_JIT macro) and JIT paging test (similar to QEMU test). aa2f286e Don't initialise group_dirtiness with 1 as it increases the binary size significantly b8e14ed9 Remove unused reg_xmm32s bc726e03 Implement dbg_log for native code with format characters 'd' and 'x' 454039d6 Fix store task register 63a4b349 Remove unnecessary parens and clean up some log statements 4cc96814 Add logop and dbg_trace imports 7940655d Only inhibit interrupts if the interrupt flag was 0 in STI 876c68a7 Split create_tests into create_tests and generate_interpreter aa82499f Move detection of string instructions to x86_table f3840ec2 Move C ast to separate file 90400703 Skip tests for lfence/mfence/sfence, clarify their encoding 4a9d8204 elf: Hide log messages when log level is zero a601c526 Allow setting log level via settings 8a624453 Add cpu_exception_hook to debug builds f9e335bf Nasm: Test exceptions 599ad088 logop: Format instruction pointer as unsigned f95cf22b Don't skip zero dividing tests 2a655a0e Remove get_seg_prefix_ds from read_moffs (preparation for calling read_moffs from the code generator) bc580b71 Remove obsolete comment e556cee0 Fix nasmtest dependencies in makefile and clean dcb1e72b Use all cores on travis 86efa737 Replace all instances of u32 & 0xFFFF with the respective u16 accesses 98b9f439 Use u8 instead of bit-shifts and masks from u32 b43f6569 Replace all instances of u32 >> 16 with the respective u16 accesses 9bfa72c7 Remove unnecessary parens 9cf93734 Clean up remaining instance of u32 with a mask instead of u16 22d4117f Correct order of writes in virt_boundary_write32 6734c7c1 Fix keyboard on ios, fixes #105 858a4506 Add missing file, c_ast.js 1d62e39e Move instruction naming scheme into function f4816852 Reorder some code 69d49788 Minor improvements 0493e05f Add util.js af9000c1 Improve full test e5feba31 Add missing export c7c42065 Replace prefix_call with custom_resolve_modrm 3186e6ad Add support for "%%" format string to dbg_log_wasm for printf import efe54fad Add barebones instrumentation profiler (disabled by default). c9f0d462 Implement movlps m64, xmm and enable its test 42869a12 Add tests for cross-page reads/writes confirmed with byte reads/writes d68976ea Mask word values in port byte reads 9758d51e Add PS2_LOG_VERBOSE 5f52f037 Update NASM Makefile to include all dependencies to prevent unnecessary recompilation 2c71f927 Have NASM test generator use a seedable PRNG to allow for faster incremental tests e4aa45bb Add chunk{16,32}_rw paging tests; instructions that read and write to memory bdf538a2 add codegen to cpu constructor aa76ce8e add resolve_modrm16 14d7ecf1 refactor codegen b710319f [rebased] Merge branch codegen 0565ea42 minor refactoring 071dff3f temporary fix for automatic cast warnings 57c504f2 fix modrm16 issue c2db5d9e jit modrm32 85c04245 reinstate modrm_fn0 and modrm_fn1 be65dafd add ip and previous ip manipulating functions ae00ef89 update codegen js interface 530a74fa squashed commit for refactor 2c692199 add codegen-test to build c15afe68 prefix gen to codegen api c9611533 codegen tests fixes --- .gitignore | 1 + .travis-run-nasm.sh | 3 +- Makefile | 44 +- debug.html | 6 +- gen/c_ast.js | 97 + gen/generate_interpreter.js | 439 + gen/util.js | 14 + gen/x86_table.js | 648 ++ index.html | 5 +- loader.js | 2 +- src/browser/lib.js | 44 + src/browser/main.js | 15 +- src/browser/screen.js | 2 +- src/browser/starter.js | 56 +- src/codegen.js | 91 + src/const.js | 5 + src/cpu.js | 168 +- src/debug.js | 2 + src/elf.js | 6 +- src/externs.js | 2 +- src/ide.js | 4 +- src/log.js | 43 +- src/main.js | 5 +- src/memory.js | 27 +- src/native/all.c | 6 +- src/native/arith.c | 93 +- src/native/codegen/api.c | 332 + src/native/codegen/codegen.h | 331 + src/native/codegen/cstring.h | 132 + src/native/codegen/util.h | 135 + src/native/codegen/wasm_opcodes.h | 212 + src/native/const.h | 14 + src/native/cpu.c | 679 +- src/native/fpu.c | 4 +- src/native/global_pointers.h | 39 +- src/native/instructions.c | 8892 ++++++++++-------- src/native/instructions_0f.c | 13649 +++++++++++++++++++++------- src/native/log.c | 5 +- src/native/memory.c | 111 +- src/native/misc_instr.c | 90 +- src/native/modrm.c | 7 + src/native/profiler/profiler.c | 67 + src/native/profiler/profiler.h | 29 + src/native/shared.h | 49 + src/native/string.c | 97 +- src/ps2.js | 14 +- tests/codegen.js | 144 + tests/full/run.js | 16 +- tests/jit-paging/Makefile | 11 + tests/jit-paging/README.md | 11 + tests/jit-paging/run.js | 75 + tests/jit-paging/test-jit.c | 84 + tests/nasm/Makefile | 4 +- tests/nasm/create_tests.js | 1195 +-- tests/nasm/gdbauto | 34 +- tests/nasm/header.inc | 2 +- tests/nasm/prand.js | 21 + tests/nasm/run.js | 77 +- tests/qemu/Makefile | 2 +- tests/qemu/compiler.h | 78 +- tests/qemu/run.js | 6 +- tests/qemu/test-i386.c | 264 +- v86.css | 8 +- 63 files changed, 19774 insertions(+), 8974 deletions(-) create mode 100644 gen/c_ast.js create mode 100755 gen/generate_interpreter.js create mode 100644 gen/util.js create mode 100644 gen/x86_table.js create mode 100644 src/codegen.js create mode 100644 src/native/codegen/api.c create mode 100644 src/native/codegen/codegen.h create mode 100644 src/native/codegen/cstring.h create mode 100644 src/native/codegen/util.h create mode 100644 src/native/codegen/wasm_opcodes.h create mode 100644 src/native/profiler/profiler.c create mode 100644 src/native/profiler/profiler.h create mode 100644 src/native/shared.h create mode 100644 tests/codegen.js create mode 100644 tests/jit-paging/Makefile create mode 100644 tests/jit-paging/README.md create mode 100755 tests/jit-paging/run.js create mode 100644 tests/jit-paging/test-jit.c create mode 100644 tests/nasm/prand.js 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 @@ - +
+ +
+ From 4512fee4879633f9762f46291700e1ed7e6d690d Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 11 Jun 2018 13:11:40 -0500 Subject: [PATCH 0922/2137] Fix string_get_cycle_count and make it more readable --- src/native/string.c | 80 ++++++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 38 deletions(-) diff --git a/src/native/string.c b/src/native/string.c index f881e302..c0748844 100644 --- a/src/native/string.c +++ b/src/native/string.c @@ -18,12 +18,16 @@ int32_t string_get_cycle_count(int32_t size, int32_t address) if(size < 0) { - return (address & 0xFFF) >> (-size >> 1); - } - else - { - return (~address & 0xFFF) >> size; + size = -size; + address = 0x1000 - address - size; } + + assert((address & (size - 1)) == 0); + + // 1 -> 0; 2 -> 1; 4 -> 2 + int32_t shift = size >> 1; + + return (0x1000 - (address & 0xFFF)) >> shift; } int32_t string_get_cycle_count2(int32_t size, int32_t addr1, int32_t addr2) @@ -58,7 +62,7 @@ void movsb_rep() phys_src += size; cont = --count != 0; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); int32_t diff = size * (start_count - count); add_reg_asize(EDI, diff); add_reg_asize(ESI, diff); @@ -120,7 +124,7 @@ void movsw_rep() phys_src += single_size; cont = --count != 0; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); int32_t diff = size * (start_count - count); add_reg_asize(EDI, diff); add_reg_asize(ESI, diff); @@ -138,7 +142,7 @@ void movsw_rep() add_reg_asize(ESI, size); cont = decr_ecx_asize() != 0; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); } if(cont) { @@ -196,7 +200,7 @@ void movsd_rep() phys_src += single_size; cont = --count != 0; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); int32_t diff = size * (start_count - count); add_reg_asize(EDI, diff); add_reg_asize(ESI, diff); @@ -214,7 +218,7 @@ void movsd_rep() add_reg_asize(ESI, size); cont = decr_ecx_asize() != 0; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); } if(cont) { @@ -272,7 +276,7 @@ void cmpsb_rep() phys_src += size; cont = --count != 0 && (data_src == data_dest) == is_repz; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); int32_t diff = size * (start_count - count); add_reg_asize(EDI, diff); add_reg_asize(ESI, diff); @@ -343,7 +347,7 @@ void cmpsw_rep() phys_src += single_size; cont = --count != 0 && (data_src == data_dest) == is_repz; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); int32_t diff = size * (start_count - count); add_reg_asize(EDI, diff); add_reg_asize(ESI, diff); @@ -362,7 +366,7 @@ void cmpsw_rep() add_reg_asize(ESI, size); cont = decr_ecx_asize() != 0 && (data_src == data_dest) == is_repz; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); } if(cont) { @@ -429,7 +433,7 @@ void cmpsd_rep() phys_src += single_size; cont = --count != 0 && (data_src == data_dest) == is_repz; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); int32_t diff = size * (start_count - count); add_reg_asize(EDI, diff); add_reg_asize(ESI, diff); @@ -448,7 +452,7 @@ void cmpsd_rep() add_reg_asize(ESI, size); cont = decr_ecx_asize() != 0 && (data_src == data_dest) == is_repz; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); } if(cont) { @@ -507,7 +511,7 @@ void stosb_rep() phys_dest += size; cont = --count != 0; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); int32_t diff = size * (start_count - count); add_reg_asize(EDI, diff); set_ecx_asize(count); @@ -565,7 +569,7 @@ void stosw_rep() phys_dest += single_size; cont = --count != 0; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); int32_t diff = size * (start_count - count); add_reg_asize(EDI, diff); set_ecx_asize(count); @@ -580,7 +584,7 @@ void stosw_rep() add_reg_asize(EDI, size); cont = decr_ecx_asize() != 0; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); } if(cont) { @@ -635,7 +639,7 @@ void stosd_rep() phys_dest += single_size; cont = --count != 0; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); int32_t diff = size * (start_count - count); add_reg_asize(EDI, diff); set_ecx_asize(count); @@ -650,7 +654,7 @@ void stosd_rep() add_reg_asize(EDI, size); cont = decr_ecx_asize() != 0; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); } if(cont) { @@ -700,7 +704,7 @@ void lodsb_rep() phys_src += size; cont = --count != 0; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); int32_t diff = size * (start_count - count); add_reg_asize(ESI, diff); set_ecx_asize(count); @@ -748,7 +752,7 @@ void lodsw_rep() add_reg_asize(ESI, size); cont = decr_ecx_asize() != 0; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); if(cont) { *instruction_pointer = *previous_ip; @@ -793,7 +797,7 @@ void lodsd_rep() add_reg_asize(ESI, size); cont = decr_ecx_asize() != 0; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); if(cont) { *instruction_pointer = *previous_ip; @@ -845,7 +849,7 @@ void scasb_rep() phys_dest += size; cont = --count != 0 && (data_src == data_dest) == is_repz; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); int32_t diff = size * (start_count - count); add_reg_asize(EDI, diff); set_ecx_asize(count); @@ -908,7 +912,7 @@ void scasw_rep() phys_dest += single_size; cont = --count != 0 && (data_src == data_dest) == is_repz; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); int32_t diff = size * (start_count - count); add_reg_asize(EDI, diff); set_ecx_asize(count); @@ -923,7 +927,7 @@ void scasw_rep() add_reg_asize(EDI, size); cont = decr_ecx_asize() != 0 && (data_src == data_dest) == is_repz; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); } if(cont) { @@ -983,7 +987,7 @@ void scasd_rep() phys_dest += single_size; cont = --count != 0 && (data_src == data_dest) == is_repz; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); int32_t diff = size * (start_count - count); add_reg_asize(EDI, diff); set_ecx_asize(count); @@ -998,7 +1002,7 @@ void scasd_rep() add_reg_asize(EDI, size); cont = decr_ecx_asize() != 0 && (data_src == data_dest) == is_repz; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); } if(cont) { @@ -1056,7 +1060,7 @@ void insb_rep() phys_dest += size; cont = --count != 0; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); int32_t diff = size * (start_count - count); add_reg_asize(EDI, diff); set_ecx_asize(count); @@ -1119,7 +1123,7 @@ void insw_rep() phys_dest += single_size; cont = --count != 0; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); int32_t diff = size * (start_count - count); add_reg_asize(EDI, diff); set_ecx_asize(count); @@ -1134,7 +1138,7 @@ void insw_rep() add_reg_asize(EDI, size); cont = decr_ecx_asize() != 0; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); } if(cont) { @@ -1194,7 +1198,7 @@ void insd_rep() phys_dest += single_size; cont = --count != 0; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); int32_t diff = size * (start_count - count); add_reg_asize(EDI, diff); set_ecx_asize(count); @@ -1209,7 +1213,7 @@ void insd_rep() add_reg_asize(EDI, size); cont = decr_ecx_asize() != 0; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); } if(cont) { @@ -1266,7 +1270,7 @@ void outsb_rep() phys_src += size; cont = --count != 0; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); int32_t diff = size * (start_count - count); add_reg_asize(ESI, diff); set_ecx_asize(count); @@ -1328,7 +1332,7 @@ void outsw_rep() phys_src += single_size; cont = --count != 0; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); int32_t diff = size * (start_count - count); add_reg_asize(ESI, diff); set_ecx_asize(count); @@ -1343,7 +1347,7 @@ void outsw_rep() add_reg_asize(ESI, size); cont = decr_ecx_asize() != 0; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); } if(cont) { @@ -1402,7 +1406,7 @@ void outsd_rep() phys_src += single_size; cont = --count != 0; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); int32_t diff = size * (start_count - count); add_reg_asize(ESI, diff); set_ecx_asize(count); @@ -1417,7 +1421,7 @@ void outsd_rep() add_reg_asize(ESI, size); cont = decr_ecx_asize() != 0; } - while(cont && cycle_counter--); + while(cont && --cycle_counter); } if(cont) { From 2fcbfdaf1960713ec22cbcbc0acd30974f63c52f Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 11 Jun 2018 13:13:25 -0500 Subject: [PATCH 0923/2137] Full test: Add extra time for more stability --- tests/full/run.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/full/run.js b/tests/full/run.js index f9864fca..76a90a48 100755 --- a/tests/full/run.js +++ b/tests/full/run.js @@ -155,7 +155,8 @@ if(cluster.isMaster) actions: [ { on_text: "~%", - run: "head -c 10000 /dev/urandom > rand; echo test pas''sed\n" + run: "head -c 10000 /dev/urandom > rand; echo test pas''sed\n", + after: 1000, }, ], }, @@ -191,7 +192,7 @@ if(cluster.isMaster) { name: "Windows 3.0", skip_if_disk_image_missing: true, - timeout: 120, + timeout: 5 * 60, cdrom: root_path + "/../v86-images/os/Win30.iso", expected_texts: [ "Press any key to continue", From f10dd50be6f3cb92a086c5e9e3d4e528ed3e86e0 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 11 Jun 2018 13:13:46 -0500 Subject: [PATCH 0924/2137] Full test: Verbose mode --- tests/full/run.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/full/run.js b/tests/full/run.js index 76a90a48..c6347b46 100755 --- a/tests/full/run.js +++ b/tests/full/run.js @@ -7,6 +7,8 @@ var TIMEOUT_EXTRA_FACTOR = +process.env.TIMEOUT_EXTRA_FACTOR || 1; var MAX_PARALLEL_TESTS = +process.env.MAX_PARALLEL_TESTS || 4; var TEST_NAME = process.env.TEST_NAME; +const VERBOSE = false; + try { var V86 = require("../../build/libv86.js").V86; @@ -537,6 +539,7 @@ function run_test(test, done) } else { + if(VERBOSE) console.error("Sending '%s'", action.run); emulator.keyboard_send_text(action.run); } } From fe1536cf90bce138331585ef73961bb5b5ac9c7e Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 11 Jun 2018 13:14:54 -0500 Subject: [PATCH 0925/2137] PCI: Log address when unexpected size is written --- src/pci.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pci.js b/src/pci.js index b67ca9df..d4b83ee2 100644 --- a/src/pci.js +++ b/src/pci.js @@ -324,7 +324,7 @@ PCI.prototype.pci_write8 = function(address, written) } dbg_assert(!(addr >= 0x10 && addr < 0x2C || addr >= 0x30 && addr < 0x34), - "PCI: Expected 32-bit write"); + "PCI: Expected 32-bit write, got 8-bit (addr: " + h(addr) + ")"); dbg_log("PCI write8 dev=" + h(bdf >> 3, 2) + " (" + device.name + ") addr=" + h(addr, 4) + " value=" + h(written, 2), LOG_PCI); @@ -348,7 +348,7 @@ PCI.prototype.pci_write16 = function(address, written) } dbg_assert(!(addr >= 0x10 && addr < 0x2C || addr >= 0x30 && addr < 0x34), - "PCI: Expected 32-bit write"); + "PCI: Expected 32-bit write, got 16-bit (addr: " + h(addr) + ")"); dbg_log("PCI writ16 dev=" + h(bdf >> 3, 2) + " (" + device.name + ") addr=" + h(addr, 4) + " value=" + h(written, 4), LOG_PCI); From e750b64d58e2dceb80794cd7e9061d5dfc58f93b Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 11 Jun 2018 13:24:39 -0500 Subject: [PATCH 0926/2137] Record interpreted/cached steps using timestamp_counter --- src/native/cpu.c | 8 ++++++++ src/native/profiler/profiler.c | 8 +++++++- src/native/profiler/profiler.h | 4 ++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/native/cpu.c b/src/native/cpu.c index 470fe2d5..38276039 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -1623,6 +1623,8 @@ void cycle_internal() profiler_start(P_RUN_FROM_CACHE); profiler_stat_increment(S_RUN_FROM_CACHE); + int32_t initial_tsc = *timestamp_counter; + assert(entry->opcode[0] == read8(phys_addr)); uint32_t old_start_address = entry->start_addr; @@ -1636,6 +1638,8 @@ void cycle_internal() UNUSED(old_start_address); + profiler_stat_increment_by(S_RUN_FROM_CACHE_STEPS, *timestamp_counter - initial_tsc); + profiler_end(P_RUN_FROM_CACHE); } else @@ -1683,7 +1687,11 @@ void cycle_internal() profiler_stat_increment(S_RUN_INTERPRETED_NOT_HOT); } + int32_t initial_tsc = *timestamp_counter; + jit_run_interpreted(phys_addr); + + profiler_stat_increment_by(S_RUN_INTERPRETED_STEPS, *timestamp_counter - initial_tsc); } } diff --git a/src/native/profiler/profiler.c b/src/native/profiler/profiler.c index 6d74518d..8763bf0d 100644 --- a/src/native/profiler/profiler.c +++ b/src/native/profiler/profiler.c @@ -98,7 +98,12 @@ int32_t profiler_get_total(void) void profiler_stat_increment(enum stat_name stat) { - profiler_stat_arr[stat].count++; + profiler_stat_increment_by(stat, 1); +} + +void profiler_stat_increment_by(enum stat_name stat, int32_t by) +{ + profiler_stat_arr[stat].count += by; } // to be called from JS @@ -122,6 +127,7 @@ void profiler_print(void) {} int32_t profiler_get_time(enum profile_name name) { UNUSED(name); return 0; } int32_t profiler_get_total(void) { return 0; } void profiler_stat_increment(enum stat_name stat) { UNUSED(stat); } +void profiler_stat_increment_by(enum stat_name stat, int32_t by) { UNUSED(stat); UNUSED(by); } void profiler_stat_increment_do_run() {} int32_t profiler_stat_get(enum stat_name stat) { UNUSED(stat); return 0; } diff --git a/src/native/profiler/profiler.h b/src/native/profiler/profiler.h index 4d402625..d960f611 100644 --- a/src/native/profiler/profiler.h +++ b/src/native/profiler/profiler.h @@ -35,7 +35,10 @@ enum stat_name { S_RUN_INTERPRETED_NO_BLOCK_BOUNDARY, S_RUN_INTERPRETED_NOT_HOT, + S_RUN_INTERPRETED_STEPS, + S_RUN_FROM_CACHE, + S_RUN_FROM_CACHE_STEPS, S_CACHE_MISMATCH, S_DO_RUN, @@ -66,6 +69,7 @@ void profiler_end(enum profile_name name); void profiler_print(void); void profiler_stat_increment(enum stat_name stat); +void profiler_stat_increment_by(enum stat_name stat, int32_t by); int32_t profiler_stat_get(enum stat_name stat); // JS import From e98e78a7c2f1ed8335ace1f3d5dcc1eba0ec47ca Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 12 Jun 2018 20:24:22 -0500 Subject: [PATCH 0927/2137] Don't manage jit caches in memory mapped area We don't allow any execution in memory mapped areas for efficiency, but jit execution is particularly unsafe, as bytes can change any time --- src/native/memory.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/native/memory.c b/src/native/memory.c index c903c649..d4a97f13 100644 --- a/src/native/memory.c +++ b/src/native/memory.c @@ -126,14 +126,13 @@ void write8(uint32_t addr, int32_t value) { if(USE_A20 && !*a20_enabled) addr &= A20_MASK; - jit_dirty_cache_single(addr); - if(in_mapped_range(addr)) { mmap_write8(addr, value); } else { + jit_dirty_cache_single(addr); mem8[addr] = value; } } @@ -142,14 +141,13 @@ void write16(uint32_t addr, int32_t value) { if(USE_A20 && !*a20_enabled) addr &= A20_MASK; - jit_dirty_cache_small(addr, addr + 2); - if(in_mapped_range(addr)) { mmap_write16(addr, value); } else { + jit_dirty_cache_small(addr, addr + 2); *(uint16_t*)(mem8 + addr) = value; } } @@ -160,7 +158,6 @@ void write_aligned16(uint32_t addr, uint32_t value) if(USE_A20 && !*a20_enabled) addr &= A20_MASK16; uint32_t phys_addr = addr << 1; - jit_dirty_cache_small(phys_addr, phys_addr + 2); if(in_mapped_range(phys_addr)) { @@ -168,6 +165,7 @@ void write_aligned16(uint32_t addr, uint32_t value) } else { + jit_dirty_cache_small(phys_addr, phys_addr + 2); mem16[addr] = value; } } @@ -176,14 +174,13 @@ void write32(uint32_t addr, int32_t value) { if(USE_A20 && !*a20_enabled) addr &= A20_MASK; - jit_dirty_cache_small(addr, addr + 4); - if(in_mapped_range(addr)) { mmap_write32(addr, value); } else { + jit_dirty_cache_small(addr, addr + 4); *(int32_t*)(mem8 + addr) = value; } } @@ -194,7 +191,6 @@ void write_aligned32(uint32_t addr, int32_t value) if(USE_A20 && !*a20_enabled) addr &= A20_MASK32; uint32_t phys_addr = addr << 2; - jit_dirty_cache_small(phys_addr, phys_addr + 4); if(in_mapped_range(phys_addr)) { @@ -202,6 +198,7 @@ void write_aligned32(uint32_t addr, int32_t value) } else { + jit_dirty_cache_small(phys_addr, phys_addr + 4); mem32s[addr] = value; } } @@ -210,8 +207,6 @@ void write64(uint32_t addr, int64_t value) { if(USE_A20 && !*a20_enabled) addr &= A20_MASK; - jit_dirty_cache_small(addr, addr + 8); - if(in_mapped_range(addr)) { mmap_write32(addr + 0, value & 0xFFFFFFFF); @@ -219,6 +214,7 @@ void write64(uint32_t addr, int64_t value) } else { + jit_dirty_cache_small(addr, addr + 8); *(int64_t*)(mem8 + addr) = value; } } @@ -227,14 +223,13 @@ void write128(uint32_t addr, union reg128 value) { if(USE_A20 && !*a20_enabled) addr &= A20_MASK; - jit_dirty_cache_small(addr, addr + 16); - if(in_mapped_range(addr)) { mmap_write128(addr, value.i32[0], value.i32[1], value.i32[2], value.i32[3]); } else { + jit_dirty_cache_small(addr, addr + 16); *(int64_t*)(mem8 + addr) = value.i64[0]; *(int64_t*)(mem8 + addr + 8) = value.i64[1]; } From dc86ade56091ceae2891f4d892b64ec0e0483632 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 12 Jun 2018 20:28:39 -0500 Subject: [PATCH 0928/2137] Make clang-tidy happy --- src/native/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/cpu.c b/src/native/cpu.c index 38276039..feb95864 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -9,6 +9,7 @@ #include "cpu.h" #include "global_pointers.h" #include "instructions.h" +#include "jit.h" #include "js_imports.h" #include "log.h" #include "memory.h" @@ -17,7 +18,6 @@ #include "profiler/opstats.h" #include "profiler/profiler.h" #include "shared.h" -#include "jit.h" struct code_cache jit_cache_arr[JIT_CACHE_ARRAY_SIZE] = { { From 24c9f14459068c127f7b9a4c88df59ace5b30da6 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 12 Jun 2018 20:32:32 -0500 Subject: [PATCH 0929/2137] Check that there are no page faults while generating code --- src/native/cpu.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/native/cpu.c b/src/native/cpu.c index feb95864..bb1e6d60 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -19,6 +19,10 @@ #include "profiler/profiler.h" #include "shared.h" +#if DEBUG +bool must_not_fault = false; +#endif + struct code_cache jit_cache_arr[JIT_CACHE_ARRAY_SIZE] = { { .start_addr = 0, @@ -130,6 +134,15 @@ void trigger_pagefault(bool write, bool user, bool present) dbg_trace(); } +#if DEBUG + if(must_not_fault) + { + dbg_log("Unexpected page fault"); + dbg_trace(); + assert(false); + } +#endif + if(*page_fault) { dbg_log("double fault"); @@ -1661,11 +1674,17 @@ void cycle_internal() ) ) { +#if DEBUG + assert(!must_not_fault); must_not_fault = true; +#endif // don't immediately retry to compile hot_code_addresses[address_hash] = 0; jit_block_boundary = false; jit_generate(phys_addr); +#if DEBUG + assert(must_not_fault); must_not_fault = false; +#endif } else { From 27b83df6b14eb9bb226884d803c2033210e5b60e Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 13 Jun 2018 13:01:50 -0500 Subject: [PATCH 0930/2137] Don't set previous_ip during code generation Setting previous_ip is incorrect, as page faults are not allowed during code generation --- src/native/cpu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/native/cpu.c b/src/native/cpu.c index bb1e6d60..66ac84da 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -808,7 +808,6 @@ static void jit_generate_basic_block(int32_t start_addr, int32_t stop_addr) do { - *previous_ip = *instruction_pointer; #if ENABLE_PROFILER_OPSTATS gen_opstats(safe_read32s(*instruction_pointer)); #endif From 62673c09905143db4d5be7ac99ddae071b372686 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 14 Jun 2018 16:51:33 -0500 Subject: [PATCH 0931/2137] Optimise away max iteration limit in jit code --- src/browser/print_stats.js | 1 + src/native/config.h | 1 + src/native/cpu.c | 41 +++++++++++++++++++++++----------- src/native/profiler/profiler.h | 1 + 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index b89b40e0..3890b5f9 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -24,6 +24,7 @@ const print_stats = { "COMPILE", "COMPILE_SUCCESS", "COMPILE_CUT_OFF_AT_END_OF_PAGE", + "COMPILE_WITH_LOOP_SAFETY", "COMPILE_BASIC_BLOCK", "COMPILE_ENTRY_POINT", "RUN_INTERPRETED", diff --git a/src/native/config.h b/src/native/config.h index 85781e69..f0fefe85 100644 --- a/src/native/config.h +++ b/src/native/config.h @@ -31,6 +31,7 @@ #define ENABLE_JIT 1 #define ENABLE_JIT_NONFAULTING_OPTIMZATION 1 +#define JIT_ALWAYS_USE_LOOP_SAFETY 0 #ifndef ENABLE_JIT_ALWAYS #define ENABLE_JIT_ALWAYS 0 diff --git a/src/native/cpu.c b/src/native/cpu.c index 66ac84da..d798de5f 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -1189,8 +1189,9 @@ int32_t to_visit_stack[1000]; int32_t marked_as_entry[1000]; // populates the basic_blocks global variable -static void jit_find_basic_blocks() +static void jit_find_basic_blocks(bool* requires_loop_limit) { + *requires_loop_limit = false; int32_t start = *instruction_pointer; basic_blocks.length = 0; @@ -1300,6 +1301,14 @@ static void jit_find_basic_blocks() assert(jump_target); current_block->next_block_branch_taken_addr = jump_target; + + // Very simple heuristic for "infinite loops": This + // detects Linux's "calibrating delay loop" + if(jump_target == current_block->addr) + { + dbg_log("Basic block looping back to front"); + *requires_loop_limit = true; + } } else { @@ -1391,8 +1400,10 @@ static void jit_generate(uint32_t phys_addr) int32_t first_opcode = read8(get_phys_eip()); + bool requires_loop_limit = false; + // populate basic_blocks - jit_find_basic_blocks(); + jit_find_basic_blocks(&requires_loop_limit); // Code generation starts here gen_reset(); @@ -1408,19 +1419,23 @@ static void jit_generate(uint32_t phys_addr) // main state machine loop gen_loop_void(); - // decrement max_iterations - gen_get_local(GEN_LOCAL_ITERATION_COUNTER); - gen_const_i32(-1); - gen_add_i32(); - gen_set_local(GEN_LOCAL_ITERATION_COUNTER); + if(JIT_ALWAYS_USE_LOOP_SAFETY || requires_loop_limit) + { + profiler_stat_increment(S_COMPILE_WITH_LOOP_SAFETY); + // decrement max_iterations + gen_get_local(GEN_LOCAL_ITERATION_COUNTER); + gen_const_i32(-1); + gen_add_i32(); + gen_set_local(GEN_LOCAL_ITERATION_COUNTER); - // if max_iterations == 0: return - gen_get_local(GEN_LOCAL_ITERATION_COUNTER); - gen_eqz_i32(); - gen_if_void(); - gen_return(); - gen_block_end(); + // if max_iterations == 0: return + gen_get_local(GEN_LOCAL_ITERATION_COUNTER); + gen_eqz_i32(); + gen_if_void(); + gen_return(); + gen_block_end(); + } gen_block_void(); // for the default case diff --git a/src/native/profiler/profiler.h b/src/native/profiler/profiler.h index d960f611..efff267a 100644 --- a/src/native/profiler/profiler.h +++ b/src/native/profiler/profiler.h @@ -26,6 +26,7 @@ enum stat_name { S_COMPILE, S_COMPILE_SUCCESS, S_COMPILE_CUT_OFF_AT_END_OF_PAGE, + S_COMPILE_WITH_LOOP_SAFETY, S_COMPILE_BASIC_BLOCK, S_COMPILE_ENTRY_POINT, From 9d74407efa91ee5e98af40aaa37802c51870ff6c Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 16 Jun 2018 16:07:51 -0600 Subject: [PATCH 0932/2137] Also check other faults when must_not_fault is set --- src/native/cpu.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/native/cpu.c b/src/native/cpu.c index d798de5f..2f01abc8 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -1798,6 +1798,13 @@ void do_many_cycles_unsafe() void raise_exception(int32_t interrupt_nr) { #if DEBUG + if(must_not_fault) + { + dbg_log("Unexpected fault: 0x%x", interrupt_nr); + dbg_trace(); + assert(false); + } + if(cpu_exception_hook(interrupt_nr)) { throw_cpu_exception(); @@ -1811,6 +1818,13 @@ void raise_exception(int32_t interrupt_nr) void raise_exception_with_code(int32_t interrupt_nr, int32_t error_code) { #if DEBUG + if(must_not_fault) + { + dbg_log("Unexpected fault: 0x%x with code 0x%x", interrupt_nr, error_code); + dbg_trace(); + assert(false); + } + if(cpu_exception_hook(interrupt_nr)) { throw_cpu_exception(); From ad7fa728b500777fdb2359e1829b017d968c9465 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 16 Jun 2018 19:12:05 -0600 Subject: [PATCH 0933/2137] Annotate some instructions --- gen/x86_table.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 8c4da080..15a575dc 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -21,9 +21,9 @@ const encodings = [ { opcode: 0x0E, os: 1, skip: 1, }, { opcode: 0x0F, os: 1, prefix: 1, }, { opcode: 0x16, os: 1, skip: 1, }, - { opcode: 0x17, block_boundary: 1, os: 1, skip: 1, }, + { opcode: 0x17, block_boundary: 1, os: 1, skip: 1, }, // pop ss { opcode: 0x1E, os: 1, skip: 1, }, - { opcode: 0x1F, block_boundary: 1, os: 1, skip: 1, }, + { opcode: 0x1F, block_boundary: 1, os: 1, skip: 1, }, // pop ds { opcode: 0x26, prefix: 1, }, { opcode: 0x27, nonfaulting: 1, mask_flags: of, }, { opcode: 0x2E, prefix: 1, }, @@ -99,7 +99,7 @@ const encodings = [ { opcode: 0x8C, os: 1, e: 1, skip: 1, }, { opcode: 0x8D, nonfaulting: 1, os: 1, e: 1, only_mem: 1, requires_prefix_call: 1, custom: 1, }, // lea - { opcode: 0x8E, block_boundary: 1, e: 1, skip: 1, }, + { opcode: 0x8E, block_boundary: 1, e: 1, skip: 1, }, // mov sreg { opcode: 0x8F, os: 1, e: 1, fixed_g: 0, requires_prefix_call: 1, custom: 1, }, // pop r/m { opcode: 0x90, nonfaulting: 1, }, @@ -146,7 +146,7 @@ const encodings = [ { opcode: 0xC3, block_boundary: 1, no_next_instruction: 1, os: 1, skip: 1, }, { opcode: 0xC4, os: 1, e: 1, skip: 1, }, - { opcode: 0xC5, block_boundary: 1, os: 1, e: 1, skip: 1, }, + { opcode: 0xC5, block_boundary: 1, os: 1, e: 1, skip: 1, }, // lds { opcode: 0xC6, e: 1, fixed_g: 0, nonfaulting: 1, imm8: 1, }, { opcode: 0xC7, os: 1, e: 1, fixed_g: 0, nonfaulting: 1, imm1632: 1, }, From 55126509ad86032e53660e85110836255c71cae3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 18 Jun 2018 10:08:19 -0600 Subject: [PATCH 0934/2137] Increase size of jit_cache_array --- src/const.js | 2 +- src/native/config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/const.js b/src/const.js index d7da4a91..a71d1d4e 100644 --- a/src/const.js +++ b/src/const.js @@ -366,7 +366,7 @@ const P_RUN_INTERPRETED = 4; var WASM_TABLE_SIZE = 0x10000; /** @const */ -var JIT_CACHE_ARRAY_SIZE = 0x10000; +var JIT_CACHE_ARRAY_SIZE = 0x40000; /** @const */ diff --git a/src/native/config.h b/src/native/config.h index f0fefe85..fe6d24db 100644 --- a/src/native/config.h +++ b/src/native/config.h @@ -17,7 +17,7 @@ #define USE_A20 false // Mask used to map physical address to index in cache array -#define JIT_CACHE_ARRAY_SIZE 0x10000 +#define JIT_CACHE_ARRAY_SIZE 0x40000 #define JIT_CACHE_ARRAY_MASK (JIT_CACHE_ARRAY_SIZE - 1) #define HASH_PRIME 6151 From 2f890c71665c7cbcea3b37916837c9f0d5c0e933 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 18 Jun 2018 10:59:40 -0600 Subject: [PATCH 0935/2137] Track virtual address where code entry was created in debug mode --- src/native/cpu.c | 1 + src/native/cpu.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/native/cpu.c b/src/native/cpu.c index 2f01abc8..111125ee 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -1598,6 +1598,7 @@ static void jit_generate(uint32_t phys_addr) entry->opcode[0] = read8(phys_addr); entry->end_addr = block->end_addr; entry->len = block->end_addr - block->addr; + entry->virt_addr = *instruction_pointer & ~0xFFF | phys_addr & 0xFFF; #endif entry_point_count++; diff --git a/src/native/cpu.h b/src/native/cpu.h index f3de6838..b486ac73 100644 --- a/src/native/cpu.h +++ b/src/native/cpu.h @@ -45,6 +45,7 @@ struct code_cache { uint32_t end_addr; int32_t opcode[1]; int32_t len; + int32_t virt_addr; #endif // an index into jit_cache_arr for the next code_cache entry within the same physical page From e0b67557e9a0b5d19f7824aebf4cbca8be17f880 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 18 Jun 2018 11:18:36 -0600 Subject: [PATCH 0936/2137] Profiler: Track cpu exceptions --- src/browser/print_stats.js | 5 ++++- src/native/cpu.c | 3 +++ src/native/profiler/profiler.h | 5 +++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index 3890b5f9..81747886 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -27,13 +27,16 @@ const print_stats = { "COMPILE_WITH_LOOP_SAFETY", "COMPILE_BASIC_BLOCK", "COMPILE_ENTRY_POINT", + "CACHE_MISMATCH", "RUN_INTERPRETED", "RUN_INTERPRETED_PENDING", "RUN_INTERPRETED_NEAR_END_OF_PAGE", "RUN_INTERPRETED_NO_BLOCK_BOUNDARY", "RUN_INTERPRETED_NOT_HOT", + "RUN_INTERPRETED_STEPS", "RUN_FROM_CACHE", - "CACHE_MISMATCH", + "RUN_FROM_CACHE_STEPS", + "TRIGGER_CPU_EXCEPTION", "DO_RUN", "DO_MANY_CYCLES", "CYCLE_INTERNAL", diff --git a/src/native/cpu.c b/src/native/cpu.c index 111125ee..4a0b70da 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -158,6 +158,7 @@ void trigger_pagefault(bool write, bool user, bool present) *page_fault = true; call_interrupt_vector(14, false, true, user << 2 | write << 1 | present); + profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); throw_cpu_exception(); } @@ -1812,6 +1813,7 @@ void raise_exception(int32_t interrupt_nr) return; } #endif + profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); call_interrupt_vector(interrupt_nr, false, false, 0); throw_cpu_exception(); } @@ -1832,6 +1834,7 @@ void raise_exception_with_code(int32_t interrupt_nr, int32_t error_code) return; } #endif + profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); call_interrupt_vector(interrupt_nr, false, true, error_code); throw_cpu_exception(); } diff --git a/src/native/profiler/profiler.h b/src/native/profiler/profiler.h index efff267a..c9b7ec79 100644 --- a/src/native/profiler/profiler.h +++ b/src/native/profiler/profiler.h @@ -29,18 +29,19 @@ enum stat_name { S_COMPILE_WITH_LOOP_SAFETY, S_COMPILE_BASIC_BLOCK, S_COMPILE_ENTRY_POINT, + S_CACHE_MISMATCH, S_RUN_INTERPRETED, S_RUN_INTERPRETED_PENDING, S_RUN_INTERPRETED_NEAR_END_OF_PAGE, S_RUN_INTERPRETED_NO_BLOCK_BOUNDARY, S_RUN_INTERPRETED_NOT_HOT, - S_RUN_INTERPRETED_STEPS, S_RUN_FROM_CACHE, S_RUN_FROM_CACHE_STEPS, - S_CACHE_MISMATCH, + + S_TRIGGER_CPU_EXCEPTION, S_DO_RUN, S_DO_MANY_CYCLES, From 822f640a7120b51ee3ca3791eb016e521e95d671 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 18 Jun 2018 11:19:37 -0600 Subject: [PATCH 0937/2137] Use const pointer where possible --- src/native/jit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/jit.c b/src/native/jit.c index 30871d4a..a7c5d792 100644 --- a/src/native/jit.c +++ b/src/native/jit.c @@ -104,7 +104,7 @@ void remove_jit_cache_wasm_index(int32_t page, uint16_t wasm_table_index) } } -bool find_u16(uint16_t* array, uint16_t value, int32_t length) +bool find_u16(const uint16_t* array, uint16_t value, int32_t length) { for(int32_t i = 0; i < length; i++) { From 82e0cc00dfad1581dc7a670736d90091bc739085 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 18 Jun 2018 11:51:00 -0600 Subject: [PATCH 0938/2137] Check that do_page_translation isn't called without paging --- src/native/cpu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/native/cpu.c b/src/native/cpu.c index 4a0b70da..7f75700f 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -164,6 +164,8 @@ void trigger_pagefault(bool write, bool user, bool present) int32_t do_page_translation(int32_t addr, bool for_writing, bool user) { + assert(*paging); + int32_t page = (uint32_t)addr >> 12; int32_t page_dir_addr = ((uint32_t)cr[3] >> 2) + (page >> 10); int32_t page_dir_entry = read_aligned32(page_dir_addr); From 38a36d2e32dcc5bed542d52a50fc30908110461c Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 18 Jun 2018 12:01:44 -0600 Subject: [PATCH 0939/2137] Minor --- src/browser/main.js | 21 ++++++++++++--------- src/browser/print_stats.js | 5 +++++ src/config.js | 2 +- src/debug.js | 1 + 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/browser/main.js b/src/browser/main.js index 4d91fc3d..3f7a8120 100644 --- a/src/browser/main.js +++ b/src/browser/main.js @@ -762,18 +762,21 @@ var panel = document.createElement("pre"); document.body.appendChild(panel); - setInterval(function() - { - if(!emulator.is_running()) + if(ENABLE_PROFILER) + { + setInterval(function() { - return; - } + if(!emulator.is_running()) + { + return; + } - const text = print_stats.stats_to_string(emulator.v86.cpu); - panel.textContent = text; + const text = print_stats.stats_to_string(emulator.v86.cpu); + panel.textContent = text; - CLEAR_STATS && emulator.v86.cpu.wm.exports["_profiler_init"](); - }, CLEAR_STATS ? 5000 : 1000); + CLEAR_STATS && emulator.v86.cpu.wm.exports["_profiler_init"](); + }, CLEAR_STATS ? 5000 : 1000); + } init_ui(settings, emulator); diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index 81747886..c3028579 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -185,6 +185,11 @@ const print_stats = { } text += "Total: " + total + "\n"; + if(total === 0) + { + return ""; + } + for(let [i, count] of counts) { if((i & 0xFF00) === 0) diff --git a/src/config.js b/src/config.js index bc183765..15e3928f 100644 --- a/src/config.js +++ b/src/config.js @@ -10,7 +10,7 @@ var DEBUG = true; /** @const - * Also needs to be set in const.h + * Also needs to be set in config.h */ var ENABLE_PROFILER = true; diff --git a/src/debug.js b/src/debug.js index f127d87e..900d1b7e 100644 --- a/src/debug.js +++ b/src/debug.js @@ -533,6 +533,7 @@ CPU.prototype.debug_init = function() if(!entry) { + dbg_log("Not present: " + h((i << 22) >>> 0, 8)); continue; } From ede7b705b58cafbc16a80b8568ef1ac2d6125801 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 18 Jun 2018 11:49:19 -0600 Subject: [PATCH 0940/2137] JIT: Record entry points before compilation This changes the strategy of finding basic blocks. Instead of starting at a single address (the current instruction pointer, which was found to be hot), we record all entries of control flow per page while interpreting code; we also determine hotness per page. Once a page is hot, all entries that were recorded in this page are compiled into a single wasm module. The code generator didn't need much changes, as it already supported multiple entry points. --- src/browser/print_stats.js | 1 - src/native/codegen/codegen.c | 16 ++- src/native/codegen/wasm_util.h | 7 + src/native/cpu.c | 248 ++++++++++++++++++++------------- src/native/cpu.h | 10 +- src/native/jit.c | 37 +++++ src/native/profiler/profiler.h | 1 - 7 files changed, 223 insertions(+), 97 deletions(-) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index c3028579..36a66fb5 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -31,7 +31,6 @@ const print_stats = { "RUN_INTERPRETED", "RUN_INTERPRETED_PENDING", "RUN_INTERPRETED_NEAR_END_OF_PAGE", - "RUN_INTERPRETED_NO_BLOCK_BOUNDARY", "RUN_INTERPRETED_NOT_HOT", "RUN_INTERPRETED_STEPS", "RUN_FROM_CACHE", diff --git a/src/native/codegen/codegen.c b/src/native/codegen/codegen.c index 01c9f159..2b455c19 100644 --- a/src/native/codegen/codegen.c +++ b/src/native/codegen/codegen.c @@ -430,7 +430,8 @@ void gen_safe_write32(int32_t local_for_address, int32_t local_for_value) // Only call jit_dirty_cache_single if absolutely necessary // Pseudo: // /* continued within can_use_fast_path branch */ - // if(page_first_jit_cache_entry[phys_address >> 12] != JIT_CACHE_ARRAY_NO_NEXT_ENTRY) + // if(page_first_jit_cache_entry[phys_address >> 12] != JIT_CACHE_ARRAY_NO_NEXT_ENTRY || + // page_entry_points[phys_address >> 12] != ENTRY_POINT_END) // { // jit_dirty_cache_single(phys_address); // } @@ -445,6 +446,19 @@ void gen_safe_write32(int32_t local_for_address, int32_t local_for_value) gen_const_i32(JIT_CACHE_ARRAY_NO_NEXT_ENTRY); gen_ne_i32(); + + gen_get_local(phys_addr_local); + gen_const_i32(12); + shr_u32(&instruction_body); + gen_const_i32(1); + shl_i32(&instruction_body); + load_aligned_u16_from_stack(&instruction_body, (uint32_t) page_entry_points); + + gen_const_i32(ENTRY_POINT_END); + gen_ne_i32(); + + or_i32(&instruction_body); + gen_if_void(); gen_get_local(phys_addr_local); gen_call_fn1("jit_dirty_cache_single", 22); diff --git a/src/native/codegen/wasm_util.h b/src/native/codegen/wasm_util.h index 4c73a4ee..5c4b73c8 100644 --- a/src/native/codegen/wasm_util.h +++ b/src/native/codegen/wasm_util.h @@ -30,6 +30,13 @@ static void inline load_aligned_u16(Buffer* buf, uint32_t addr) write_raw_u8(buf, 0); } +static void inline load_aligned_u16_from_stack(Buffer* buf, uint32_t byte_offset) +{ + write_raw_u8(buf, OP_I32LOAD16U); + write_raw_u8(buf, MEM_ALIGN16); + write_leb_u32(buf, byte_offset); +} + static void inline load_unaligned_i32_from_stack(Buffer* buf, uint32_t byte_offset) { write_raw_u8(buf, OP_I32LOAD); diff --git a/src/native/cpu.c b/src/native/cpu.c index 7f75700f..6835e50f 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -19,6 +19,9 @@ #include "profiler/profiler.h" #include "shared.h" +// TODO: Use sparse structure +uint16_t page_entry_points[MAX_PHYSICAL_PAGES][MAX_ENTRIES_PER_PAGE] = { { 0 } }; + #if DEBUG bool must_not_fault = false; #endif @@ -57,6 +60,47 @@ int32_t wasm_table_index_pending_free_count = 0; int32_t valid_tlb_entries[VALID_TLB_ENTRY_MAX] = {0}; int32_t valid_tlb_entries_count = 0; +static bool is_near_end_of_page(uint32_t addr); + +void record_page_entry(uint32_t phys_addr) +{ + if(is_near_end_of_page(phys_addr)) + { + return; + } + + uint32_t page = phys_addr >> 12; + + assert(page < MAX_PHYSICAL_PAGES); + uint16_t* entry_points = page_entry_points[page]; + + uint16_t entry_point = phys_addr & 0xFFF; + assert(entry_point != ENTRY_POINT_END); + + bool did_insert_or_find = false; + + for(int32_t i = 0; i < MAX_ENTRIES_PER_PAGE; i++) + { + if(entry_points[i] == ENTRY_POINT_END) + { + entry_points[i] = entry_point; + did_insert_or_find = true; + break; + } + else if(entry_points[i] == entry_point) + { + did_insert_or_find = true; + break; + } + } + + if(!did_insert_or_find) + { + // page entry list full :( + //assert(false); + } +} + int32_t get_wasm_table_index_free_list_count(void) { return wasm_table_index_free_list_count; @@ -571,9 +615,9 @@ void modrm_skip(int32_t modrm_byte) modrm_resolve(modrm_byte); } -uint32_t jit_hot_hash(uint32_t addr) +uint32_t jit_hot_hash_page(uint32_t page) { - return addr % HASH_PRIME; + return page % HASH_PRIME; } static void jit_run_interpreted(int32_t phys_addr) @@ -583,31 +627,14 @@ static void jit_run_interpreted(int32_t phys_addr) jit_block_boundary = false; -#if DUMP_UNCOMPILED_ASSEMBLY - int32_t start_eip = phys_addr; - int32_t end_eip = start_eip; -#endif - assert(!in_mapped_range(phys_addr)); int32_t opcode = mem8[phys_addr]; (*instruction_pointer)++; (*timestamp_counter)++; -#if DEBUG - logop(previous_ip[0], opcode); -#endif - run_instruction(opcode | !!*is_32 << 8); -#if DUMP_UNCOMPILED_ASSEMBLY - if(!jit_block_boundary) - { - *previous_ip = *instruction_pointer; - end_eip = get_phys_eip(); - } -#endif - - while(!jit_block_boundary) + while(!jit_block_boundary && same_page(*previous_ip, *instruction_pointer)) { previous_ip[0] = instruction_pointer[0]; (*timestamp_counter)++; @@ -618,19 +645,8 @@ static void jit_run_interpreted(int32_t phys_addr) logop(previous_ip[0], opcode); #endif run_instruction(opcode | !!*is_32 << 8); - -#if DUMP_UNCOMPILED_ASSEMBLY - if(!jit_block_boundary) - { - *previous_ip = *instruction_pointer; - end_eip = get_phys_eip(); - } -#endif } -#if DUMP_UNCOMPILED_ASSEMBLY - log_uncompiled_code(start_eip, end_eip); -#endif profiler_end(P_RUN_INTERPRETED); } @@ -876,7 +892,17 @@ static void jit_generate_basic_block(int32_t start_addr, int32_t stop_addr) } while(!was_block_boundary && !is_near_end_of_page(*instruction_pointer) && - *instruction_pointer != stop_addr); + *instruction_pointer < stop_addr); + + if(*instruction_pointer != stop_addr) + { + // Overlapping basic blocks: This can happen as we only track basic + // blocks, not individual instructions, and basic blocks sometimes need + // to be split. + // Happens for example when a jump is performed into the middle of an instruction + dbg_log("Overlapping basic blocks: start %x eip %x stop %x", + start_addr, *instruction_pointer, stop_addr); + } #if ENABLE_JIT_NONFAULTING_OPTIMZATION // When the block ends in a non-jump instruction, we may have uncommitted updates still @@ -1143,6 +1169,8 @@ struct basic_block* add_basic_block_start(struct basic_block_list* basic_blocks, // Split the previous block as it would overlap otherwise; change // it to continue at this block + // XXX: May do invalid split here. For example, a jump into the middle of an instruction + // jit_generate_basic_block handles this correctly previous_block->end_addr = addr; previous_block->next_block_addr = addr; previous_block->condition_index = -1; @@ -1192,20 +1220,47 @@ int32_t to_visit_stack[1000]; int32_t marked_as_entry[1000]; // populates the basic_blocks global variable -static void jit_find_basic_blocks(bool* requires_loop_limit) +static bool jit_find_basic_blocks(uint32_t phys_addr, bool* requires_loop_limit) { *requires_loop_limit = false; - int32_t start = *instruction_pointer; - basic_blocks.length = 0; // keep a stack of locations to visit that are part of the current control flow int32_t to_visit_stack_count = 0; - to_visit_stack[to_visit_stack_count++] = *instruction_pointer; - int32_t marked_as_entry_count = 0; - marked_as_entry[marked_as_entry_count++] = *instruction_pointer; + + uint32_t page = phys_addr >> 12; + int32_t base_address = *instruction_pointer & ~0xFFF; + uint16_t* entry_points = page_entry_points[page]; + + for(int32_t i = 0; i < MAX_ENTRIES_PER_PAGE; i++) + { + if(entry_points[i] == ENTRY_POINT_END) + { + if(i == 0) + { + return false; + } + + break; + } + + assert((entry_points[i] & ~0xFFF) == 0); + + int32_t address = base_address | entry_points[i]; + + assert(!is_near_end_of_page(address)); + + assert(to_visit_stack_count < 1000); + to_visit_stack[to_visit_stack_count++] = address; + assert(marked_as_entry_count < 1000); + marked_as_entry[marked_as_entry_count++] = address; + + entry_points[i] = ENTRY_POINT_END; + } + + assert(to_visit_stack_count >= 1); while(to_visit_stack_count) { @@ -1379,18 +1434,24 @@ static void jit_find_basic_blocks(bool* requires_loop_limit) if(DEBUG) { + int32_t start = basic_blocks.blocks[0].addr; int32_t end = basic_blocks.blocks[basic_blocks.length - 1].end_addr; - dbg_log("Function with %d basic blocks, start at %x end at %x", - basic_blocks.length, start, end); + if(true) + { + dbg_log("Function with %d basic blocks, start at %x end at %x", + basic_blocks.length, start, end); + } //for(int32_t i = 0; i < basic_blocks.length; i++) //{ - // dbg_log("%x", basic_blocks.blocks[i].addr); + // dbg_log("- addr=%x end_addr=%x", basic_blocks.blocks[i].addr, basic_blocks.blocks[i].end_addr); //} dump_function_code(basic_blocks.blocks, basic_blocks.length, end); } + + return true; } __attribute__((noinline)) @@ -1399,6 +1460,9 @@ static void jit_generate(uint32_t phys_addr) profiler_stat_increment(S_COMPILE); profiler_start(P_GEN_INSTR); + // don't immediately retry to compile + hot_code_addresses[jit_hot_hash_page(phys_addr >> 12)] = 0; + int32_t start = *instruction_pointer; int32_t first_opcode = read8(get_phys_eip()); @@ -1406,7 +1470,13 @@ static void jit_generate(uint32_t phys_addr) bool requires_loop_limit = false; // populate basic_blocks - jit_find_basic_blocks(&requires_loop_limit); + if(!jit_find_basic_blocks(phys_addr, &requires_loop_limit)) + { + profiler_end(P_GEN_INSTR); + dbg_log("No basic blocks, not generating code"); + *instruction_pointer = start; + return; + } // Code generation starts here gen_reset(); @@ -1476,7 +1546,9 @@ static void jit_generate(uint32_t phys_addr) gen_commit_instruction_body_to_cs(); } - if(block.next_block_addr) + bool invalid_connection_to_next_block = next_block_start != *instruction_pointer; + + if(!invalid_connection_to_next_block && block.next_block_addr) { if(block.condition_index == -1) { @@ -1633,6 +1705,7 @@ static void jit_generate(uint32_t phys_addr) void jit_force_generate_unsafe(uint32_t phys_addr) { *instruction_pointer = phys_addr; + record_page_entry(phys_addr); jit_generate(phys_addr); } #endif @@ -1647,8 +1720,6 @@ void cycle_internal() struct code_cache* entry = find_cache_entry(phys_addr); - const bool JIT_COMPILE_ONLY_AFTER_BLOCK_BOUNDARY = true; - if(entry && !entry->pending) { profiler_start(P_RUN_FROM_CACHE); @@ -1670,66 +1741,57 @@ void cycle_internal() UNUSED(old_start_address); profiler_stat_increment_by(S_RUN_FROM_CACHE_STEPS, *timestamp_counter - initial_tsc); - profiler_end(P_RUN_FROM_CACHE); } else { - bool did_block_boundary = !JIT_COMPILE_ONLY_AFTER_BLOCK_BOUNDARY || jit_block_boundary; - const int32_t address_hash = jit_hot_hash(phys_addr); - - // exists | pending -> should generate - // -------+---------++--------------------- - // 0 | x -> yes - // 1 | 0 -> impossible (handled above) - // 1 | 1 -> no - - if( - !entry && - !is_near_end_of_page(phys_addr) && ( - ENABLE_JIT_ALWAYS || - (did_block_boundary && ++hot_code_addresses[address_hash] > JIT_THRESHOLD) - ) - ) + if(!entry) // not pending { -#if DEBUG - assert(!must_not_fault); must_not_fault = true; -#endif - // don't immediately retry to compile - hot_code_addresses[address_hash] = 0; - jit_block_boundary = false; + const int32_t address_hash = jit_hot_hash_page(phys_addr >> 12); - jit_generate(phys_addr); + hot_code_addresses[address_hash]++; + + record_page_entry(phys_addr); + + if(ENABLE_JIT_ALWAYS || hot_code_addresses[address_hash] >= JIT_THRESHOLD) + { #if DEBUG - assert(must_not_fault); must_not_fault = false; + assert(!must_not_fault); must_not_fault = true; #endif + + int32_t old_previous_ip = *previous_ip; + int32_t old_instruction_pointer = *instruction_pointer; + + jit_generate(phys_addr); + + // jit_generate must not change previous_ip or instruction_pointer + assert(*previous_ip == old_previous_ip); + assert(*instruction_pointer == old_instruction_pointer); +#if DEBUG + assert(must_not_fault); must_not_fault = false; +#endif + } + } + + if(entry) + { + assert(entry->pending); + profiler_stat_increment(S_RUN_INTERPRETED_PENDING); + } + else if(is_near_end_of_page(phys_addr)) + { + profiler_stat_increment(S_RUN_INTERPRETED_NEAR_END_OF_PAGE); } else { - if(entry) - { - assert(entry->pending); - profiler_stat_increment(S_RUN_INTERPRETED_PENDING); - } - else if(is_near_end_of_page(phys_addr)) - { - profiler_stat_increment(S_RUN_INTERPRETED_NEAR_END_OF_PAGE); - } - else if(!did_block_boundary) - { - profiler_stat_increment(S_RUN_INTERPRETED_NO_BLOCK_BOUNDARY); - } - else - { - profiler_stat_increment(S_RUN_INTERPRETED_NOT_HOT); - } - - int32_t initial_tsc = *timestamp_counter; - - jit_run_interpreted(phys_addr); - - profiler_stat_increment_by(S_RUN_INTERPRETED_STEPS, *timestamp_counter - initial_tsc); + profiler_stat_increment(S_RUN_INTERPRETED_NOT_HOT); } + + int32_t initial_tsc = *timestamp_counter; + + jit_run_interpreted(phys_addr); + + profiler_stat_increment_by(S_RUN_INTERPRETED_STEPS, *timestamp_counter - initial_tsc); } #else diff --git a/src/native/cpu.h b/src/native/cpu.h index b486ac73..06cf2f5c 100644 --- a/src/native/cpu.h +++ b/src/native/cpu.h @@ -62,6 +62,14 @@ _Static_assert(sizeof(struct code_cache) == 16, "code_cache uses 16 bytes"); #endif struct code_cache jit_cache_arr[JIT_CACHE_ARRAY_SIZE]; +// XXX: Remove this limitation when page_entry_points is sparse +#define MAX_PHYSICAL_PAGES (512 << 20 >> 12) + +#define MAX_ENTRIES_PER_PAGE 128 +#define ENTRY_POINT_END 0xFFFF + +uint16_t page_entry_points[MAX_PHYSICAL_PAGES][MAX_ENTRIES_PER_PAGE]; + // Flag indicating whether the instruction that just ran was at a block's boundary (jump, // state-altering, etc.) extern uint32_t jit_block_boundary; @@ -167,7 +175,7 @@ void modrm_skip(int32_t modrm_byte); void check_jit_cache_array_invariants(); -uint32_t jit_hot_hash(uint32_t addr); +uint32_t jit_hot_hash_page(uint32_t page); void jit_link_block(int32_t target); void jit_link_block_conditional(int32_t offset, const char* condition); void cycle_internal(void); diff --git a/src/native/jit.c b/src/native/jit.c index a7c5d792..94319edc 100644 --- a/src/native/jit.c +++ b/src/native/jit.c @@ -120,6 +120,7 @@ bool find_u16(const uint16_t* array, uint16_t value, int32_t length) __attribute__((noinline)) void jit_clear_page(uint32_t index) { + assert(index < MAX_PHYSICAL_PAGES); int32_t cache_array_index = page_first_jit_cache_entry[index]; assert(cache_array_index != JIT_CACHE_ARRAY_NO_NEXT_ENTRY); @@ -187,12 +188,38 @@ void jit_clear_page(uint32_t index) void jit_dirty_index(uint32_t index) { + assert(index < MAX_PHYSICAL_PAGES); int32_t cache_array_index = page_first_jit_cache_entry[index]; if(cache_array_index != JIT_CACHE_ARRAY_NO_NEXT_ENTRY) { jit_clear_page(index); } + + uint16_t* entry_points = page_entry_points[index]; + + if(entry_points[0] != ENTRY_POINT_END) + { + // don't try to compile code in this page anymore until it's hot again + hot_code_addresses[jit_hot_hash_page(index)] = 0; + + for(int32_t i = 0; i < MAX_ENTRIES_PER_PAGE; i++) + { + if(entry_points[i] == ENTRY_POINT_END) + { + break; + } + + entry_points[i] = ENTRY_POINT_END; + } + +#if DEBUG + for(int32_t i = 0; i < MAX_ENTRIES_PER_PAGE; i++) + { + assert(entry_points[i] == ENTRY_POINT_END); + } +#endif + } } /* @@ -262,6 +289,16 @@ void jit_empty_cache() page_first_jit_cache_entry[i] = JIT_CACHE_ARRAY_NO_NEXT_ENTRY; } + for(int32_t i = 0; i < MAX_PHYSICAL_PAGES; i++) + { + uint16_t* entry_points = page_entry_points[i]; + + for(int32_t j = 0; j < MAX_ENTRIES_PER_PAGE; j++) + { + entry_points[j] = ENTRY_POINT_END; + } + } + for(int32_t i = 0; i < 0xFFFF; i++) { // don't assign 0 (XXX: Check) diff --git a/src/native/profiler/profiler.h b/src/native/profiler/profiler.h index c9b7ec79..4944b23c 100644 --- a/src/native/profiler/profiler.h +++ b/src/native/profiler/profiler.h @@ -34,7 +34,6 @@ enum stat_name { S_RUN_INTERPRETED, S_RUN_INTERPRETED_PENDING, S_RUN_INTERPRETED_NEAR_END_OF_PAGE, - S_RUN_INTERPRETED_NO_BLOCK_BOUNDARY, S_RUN_INTERPRETED_NOT_HOT, S_RUN_INTERPRETED_STEPS, From 5995414f8736c03274dc1f69a46df8d3e6411380 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 18 Jun 2018 11:58:05 -0600 Subject: [PATCH 0941/2137] JIT: Follow call instructions --- gen/x86_table.js | 4 +--- src/native/cpu.c | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 15a575dc..2e9fda95 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -179,9 +179,7 @@ const encodings = [ { opcode: 0xE6, block_boundary: 1, imm8: 1, skip: 1, }, // out { opcode: 0xE7, block_boundary: 1, os: 1, imm8: 1, skip: 1, }, - // E8 call: Has immediate jump offset, but we don't really want to follow - // into other functions while generating code - { opcode: 0xE8, block_boundary: 1, /* jump_offset_imm: 1, */ os: 1, imm1632: 1, custom: 1, skip: 1, }, + { opcode: 0xE8, block_boundary: 1, jump_offset_imm: 1, os: 1, imm1632: 1, custom: 1, skip: 1, }, // call { opcode: 0xE9, block_boundary: 1, jump_offset_imm: 1, no_next_instruction: 1, os: 1, imm1632: 1, custom: 1, skip: 1, }, { opcode: 0xEA, block_boundary: 1, no_next_instruction: 1, os: 1, imm1632: 1, extra_imm16: 1, skip: 1, }, // jmpf { opcode: 0xEB, block_boundary: 1, jump_offset_imm: 1, no_next_instruction: 1, imm8s: 1, custom: 1, skip: 1, }, diff --git a/src/native/cpu.c b/src/native/cpu.c index 6835e50f..a41199c5 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -1301,10 +1301,13 @@ static bool jit_find_basic_blocks(uint32_t phys_addr, bool* requires_loop_limit) int32_t instruction_end = *instruction_pointer; + bool has_next_instruction = (analysis.flags & JIT_INSTR_NO_NEXT_INSTRUCTION_FLAG) == 0; + if((analysis.flags & JIT_INSTR_BLOCK_BOUNDARY_FLAG) == 0) { // ordinary instruction, continue at next assert(!has_jump_target); + assert(has_next_instruction); if(find_basic_block_index(&basic_blocks, *instruction_pointer) != -1) { @@ -1326,6 +1329,17 @@ static bool jit_find_basic_blocks(uint32_t phys_addr, bool* requires_loop_limit) { // non-conditional jump: continue at jump target + if(has_next_instruction) + { + // Execution will eventually come back to the next instruction (CALL) + + assert(marked_as_entry_count < 1000); + marked_as_entry[marked_as_entry_count++] = *instruction_pointer; + + assert(to_visit_stack_count < 1000); + to_visit_stack[to_visit_stack_count++] = *instruction_pointer; + } + if(same_page(jump_target, *instruction_pointer)) { assert(jump_target); @@ -1348,6 +1362,7 @@ static bool jit_find_basic_blocks(uint32_t phys_addr, bool* requires_loop_limit) else { // conditional jump: continue at next and continue at jump target + assert(has_next_instruction); assert(to_visit_stack_count < 1000); to_visit_stack[to_visit_stack_count++] = *instruction_pointer; @@ -1392,8 +1407,6 @@ static bool jit_find_basic_blocks(uint32_t phys_addr, bool* requires_loop_limit) assert((analysis.flags & JIT_INSTR_BLOCK_BOUNDARY_FLAG) && !has_jump_target); - bool has_next_instruction = (analysis.flags & JIT_INSTR_NO_NEXT_INSTRUCTION_FLAG) == 0; - if(has_next_instruction) { // block boundary, but execution will eventually come back From 5778076c2b7e6d825b60abc1c2fa07515c49c7e4 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 23 Jun 2018 22:41:00 +1200 Subject: [PATCH 0942/2137] 9P read(dir) handle case when offset exceeds available Previously: (1) The number of bytes to read (aka count) is readjusted to become negative. Driver reports bogus count value. (2) However, when sending the data through virtio, the payload buffer was incorrectly subarrayed with the negative end-offset, so wrong data was still sent through. Now: (1) 9P read(dir) now clamps the count value to non-negative numbers. (2) Add asserts for negative replybuffersize and payloadsize as those should not happen in the first place. --- lib/9p.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/9p.js b/lib/9p.js index 0c8dedf1..dfd5836c 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -199,6 +199,7 @@ Virtio9p.prototype.Reset = function() { Virtio9p.prototype.BuildReply = function(id, tag, payloadsize) { + dbg_assert(payloadsize >= 0, "9P: Negative payload size"); marshall.Marshall(["w", "b", "h"], [payloadsize+7, id+1, tag], this.replybuffer, 0); if ((payloadsize+7) >= this.replybuffer.length) { message.Debug("Error in 9p: payloadsize exceeds maximum length"); @@ -216,6 +217,7 @@ Virtio9p.prototype.SendError = function (tag, errormsg, errorcode) { } Virtio9p.prototype.SendReply = function (bufchain) { + dbg_assert(this.replybuffersize >= 0, "9P: Negative replybuffersize"); bufchain.set_next_blob(this.replybuffer.subarray(0, this.replybuffersize)); this.virtqueue.push_reply(bufchain); this.virtqueue.flush_replies(); @@ -538,6 +540,12 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { this.bus.send("9p-read-end", [file.name, count]); if (inode.size < offset+count) count = inode.size - offset; + if(offset > inode.size) + { + // offset can be greater than available - should return count of zero. + // See http://ericvh.github.io/9p-rfc/rfc9p2000.html#anchor30 + count = 0; + } var data = this.fs.inodedata[this.fids[fid].inodeid]; if(data) { this.replybuffer.set(data.subarray(offset, offset + count), 7 + 4); From 67af8f55e1974f0481464f4fdbb0381b05493f28 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 18 Jun 2018 15:43:31 -0600 Subject: [PATCH 0943/2137] nasmtests: Allow running specific test by name --- tests/nasm/run.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/nasm/run.js b/tests/nasm/run.js index a22c54a1..703da8c1 100755 --- a/tests/nasm/run.js +++ b/tests/nasm/run.js @@ -21,6 +21,8 @@ const os = require("os"); const cluster = require("cluster"); const MAX_PARALLEL_TESTS = +process.env.MAX_PARALLEL_TESTS || 99; +const TEST_NAME = process.env.TEST_NAME; + const TEST_DIR = __dirname + "/build/"; const DONE_MSG = "DONE"; const TERMINATE_MSG = "DONE"; @@ -103,6 +105,8 @@ if(cluster.isMaster) return name.endsWith(".asm"); }).map(name => { return name.slice(0, -4); + }).filter(name => { + return !TEST_NAME || name === TEST_NAME; }); const tests = files.map(name => { From 718f27114a9015d2873b0a0a17b537a6bd17225a Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 18 Jun 2018 16:20:11 -0600 Subject: [PATCH 0944/2137] Don't call get_seg from modrm_skip --- src/native/cpu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/native/cpu.c b/src/native/cpu.c index a41199c5..ea6cc793 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -612,7 +612,9 @@ int32_t modrm_resolve(int32_t modrm_byte) void modrm_skip(int32_t modrm_byte) { // TODO: More efficient implementation is possible + *prefixes |= SEG_PREFIX_ZERO; modrm_resolve(modrm_byte); + *prefixes &= ~SEG_PREFIX_ZERO; } uint32_t jit_hot_hash_page(uint32_t page) From c40a5ccf254af3d2fd5a627c7f08adaeebb7c967 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 18 Jun 2018 16:26:01 -0600 Subject: [PATCH 0945/2137] nasmtests: Put multiboot section early into binary --- tests/nasm/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/nasm/Makefile b/tests/nasm/Makefile index 0d48411e..30237a52 100644 --- a/tests/nasm/Makefile +++ b/tests/nasm/Makefile @@ -19,7 +19,7 @@ build/%.bin: build/%.o # To use as a multiboot kernel image for v86 build/%.img: build/%.o - ld -g $< -m elf_i386 --section-start=.bss=0x100000 --section-start=.text=0x8000 -o $@ + ld -g $< -m elf_i386 --section-start=.bss=0x100000 --section-start=.text=0x8000 --section-start=.multiboot=0x200 -o $@ build/%.asm: %.asm mkdir -p build; cp $< $@ From 9b2b3250df99e4bc50c605e3abbfe07ee712d786 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 19 Jun 2018 09:35:09 -0600 Subject: [PATCH 0946/2137] Fix 8-bit jumps in 16-bit mode --- gen/x86_table.js | 14 ++--- src/native/instructions.c | 125 ++++++++++++++++++++++++++------------ src/native/misc_instr.c | 47 +++----------- src/native/misc_instr.h | 14 +++-- 4 files changed, 110 insertions(+), 90 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 2e9fda95..2cb614f9 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -168,10 +168,10 @@ const encodings = [ // loop, jcxz, etc. // Conditional jumps, but condition code not supported by code generator // (these are never generated by modern compilers) - { opcode: 0xE0, imm8s: 1, skip: 1, block_boundary: 1, /* jump_offset_imm: 1, conditional_jump: 1, */ }, - { opcode: 0xE1, imm8s: 1, skip: 1, block_boundary: 1, /* jump_offset_imm: 1, conditional_jump: 1, */ }, - { opcode: 0xE2, imm8s: 1, skip: 1, block_boundary: 1, /* jump_offset_imm: 1, conditional_jump: 1, */ }, - { opcode: 0xE3, imm8s: 1, skip: 1, block_boundary: 1, /* jump_offset_imm: 1, conditional_jump: 1, */ }, + { opcode: 0xE0, os: 1, imm8s: 1, skip: 1, block_boundary: 1, /* jump_offset_imm: 1, conditional_jump: 1, */ }, + { opcode: 0xE1, os: 1, imm8s: 1, skip: 1, block_boundary: 1, /* jump_offset_imm: 1, conditional_jump: 1, */ }, + { opcode: 0xE2, os: 1, imm8s: 1, skip: 1, block_boundary: 1, /* jump_offset_imm: 1, conditional_jump: 1, */ }, + { opcode: 0xE3, os: 1, imm8s: 1, skip: 1, block_boundary: 1, /* jump_offset_imm: 1, conditional_jump: 1, */ }, // port functions aren't jumps, but they may modify eip due to how they are implemented { opcode: 0xE4, block_boundary: 1, imm8: 1, skip: 1, }, // in @@ -182,7 +182,7 @@ const encodings = [ { opcode: 0xE8, block_boundary: 1, jump_offset_imm: 1, os: 1, imm1632: 1, custom: 1, skip: 1, }, // call { opcode: 0xE9, block_boundary: 1, jump_offset_imm: 1, no_next_instruction: 1, os: 1, imm1632: 1, custom: 1, skip: 1, }, { opcode: 0xEA, block_boundary: 1, no_next_instruction: 1, os: 1, imm1632: 1, extra_imm16: 1, skip: 1, }, // jmpf - { opcode: 0xEB, block_boundary: 1, jump_offset_imm: 1, no_next_instruction: 1, imm8s: 1, custom: 1, skip: 1, }, + { opcode: 0xEB, block_boundary: 1, jump_offset_imm: 1, no_next_instruction: 1, os: 1, imm8s: 1, custom: 1, skip: 1, }, { opcode: 0xEC, block_boundary: 1, skip: 1, }, // in { opcode: 0xED, block_boundary: 1, os: 1, skip: 1, }, @@ -704,8 +704,8 @@ for(let i = 0; i < 8; i++) { opcode: 0x04 | i << 3, nonfaulting: 1, eax: 1, imm8: 1, }, { opcode: 0x05 | i << 3, nonfaulting: 1, os: 1, eax: 1, imm1632: 1, }, - { opcode: 0x70 | i, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm8s: 1, custom: 1, skip: 1, }, - { opcode: 0x78 | i, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm8s: 1, custom: 1, skip: 1, }, + { opcode: 0x70 | i, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, os: 1, imm8s: 1, custom: 1, skip: 1, }, + { opcode: 0x78 | i, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, os: 1, imm8s: 1, custom: 1, skip: 1, }, { opcode: 0x80, nonfaulting: 1, e: 1, fixed_g: i, imm8: 1, }, { opcode: 0x81, nonfaulting: 1, os: 1, e: 1, fixed_g: i, imm1632: 1, }, diff --git a/src/native/instructions.c b/src/native/instructions.c index 96ec4139..ff8967f8 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -371,39 +371,73 @@ void instr_6E() { outsb(); } void instr16_6F() { outsw(); } void instr32_6F() { outsd(); } -void instr_70(int32_t imm8) { jmpcc8( test_o(), imm8); } -void instr_71(int32_t imm8) { jmpcc8(!test_o(), imm8); } -void instr_72(int32_t imm8) { jmpcc8( test_b(), imm8); } -void instr_73(int32_t imm8) { jmpcc8(!test_b(), imm8); } -void instr_74(int32_t imm8) { jmpcc8( test_z(), imm8); } -void instr_75(int32_t imm8) { jmpcc8(!test_z(), imm8); } -void instr_76(int32_t imm8) { jmpcc8( test_be(), imm8); } -void instr_77(int32_t imm8) { jmpcc8(!test_be(), imm8); } -void instr_78(int32_t imm8) { jmpcc8( test_s(), imm8); } -void instr_79(int32_t imm8) { jmpcc8(!test_s(), imm8); } -void instr_7A(int32_t imm8) { jmpcc8( test_p(), imm8); } -void instr_7B(int32_t imm8) { jmpcc8(!test_p(), imm8); } -void instr_7C(int32_t imm8) { jmpcc8( test_l(), imm8); } -void instr_7D(int32_t imm8) { jmpcc8(!test_l(), imm8); } -void instr_7E(int32_t imm8) { jmpcc8( test_le(), imm8); } -void instr_7F(int32_t imm8) { jmpcc8(!test_le(), imm8); } +void instr16_70(int32_t imm8) { jmpcc16( test_o(), imm8); } +void instr16_71(int32_t imm8) { jmpcc16(!test_o(), imm8); } +void instr16_72(int32_t imm8) { jmpcc16( test_b(), imm8); } +void instr16_73(int32_t imm8) { jmpcc16(!test_b(), imm8); } +void instr16_74(int32_t imm8) { jmpcc16( test_z(), imm8); } +void instr16_75(int32_t imm8) { jmpcc16(!test_z(), imm8); } +void instr16_76(int32_t imm8) { jmpcc16( test_be(), imm8); } +void instr16_77(int32_t imm8) { jmpcc16(!test_be(), imm8); } +void instr16_78(int32_t imm8) { jmpcc16( test_s(), imm8); } +void instr16_79(int32_t imm8) { jmpcc16(!test_s(), imm8); } +void instr16_7A(int32_t imm8) { jmpcc16( test_p(), imm8); } +void instr16_7B(int32_t imm8) { jmpcc16(!test_p(), imm8); } +void instr16_7C(int32_t imm8) { jmpcc16( test_l(), imm8); } +void instr16_7D(int32_t imm8) { jmpcc16(!test_l(), imm8); } +void instr16_7E(int32_t imm8) { jmpcc16( test_le(), imm8); } +void instr16_7F(int32_t imm8) { jmpcc16(!test_le(), imm8); } -void instr_70_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_o"); } -void instr_71_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_no"); } -void instr_72_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_b"); } -void instr_73_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nb"); } -void instr_74_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_z"); } -void instr_75_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nz"); } -void instr_76_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_be"); } -void instr_77_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nbe"); } -void instr_78_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_s"); } -void instr_79_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_ns"); } -void instr_7A_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_p"); } -void instr_7B_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_np"); } -void instr_7C_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_l"); } -void instr_7D_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nl"); } -void instr_7E_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_le"); } -void instr_7F_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nle"); } +void instr32_70(int32_t imm8) { jmpcc32( test_o(), imm8); } +void instr32_71(int32_t imm8) { jmpcc32(!test_o(), imm8); } +void instr32_72(int32_t imm8) { jmpcc32( test_b(), imm8); } +void instr32_73(int32_t imm8) { jmpcc32(!test_b(), imm8); } +void instr32_74(int32_t imm8) { jmpcc32( test_z(), imm8); } +void instr32_75(int32_t imm8) { jmpcc32(!test_z(), imm8); } +void instr32_76(int32_t imm8) { jmpcc32( test_be(), imm8); } +void instr32_77(int32_t imm8) { jmpcc32(!test_be(), imm8); } +void instr32_78(int32_t imm8) { jmpcc32( test_s(), imm8); } +void instr32_79(int32_t imm8) { jmpcc32(!test_s(), imm8); } +void instr32_7A(int32_t imm8) { jmpcc32( test_p(), imm8); } +void instr32_7B(int32_t imm8) { jmpcc32(!test_p(), imm8); } +void instr32_7C(int32_t imm8) { jmpcc32( test_l(), imm8); } +void instr32_7D(int32_t imm8) { jmpcc32(!test_l(), imm8); } +void instr32_7E(int32_t imm8) { jmpcc32( test_le(), imm8); } +void instr32_7F(int32_t imm8) { jmpcc32(!test_le(), imm8); } + +void instr16_70_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_o"); } +void instr16_71_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_no"); } +void instr16_72_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_b"); } +void instr16_73_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nb"); } +void instr16_74_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_z"); } +void instr16_75_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nz"); } +void instr16_76_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_be"); } +void instr16_77_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nbe"); } +void instr16_78_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_s"); } +void instr16_79_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_ns"); } +void instr16_7A_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_p"); } +void instr16_7B_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_np"); } +void instr16_7C_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_l"); } +void instr16_7D_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nl"); } +void instr16_7E_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_le"); } +void instr16_7F_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nle"); } + +void instr32_70_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_o"); } +void instr32_71_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_no"); } +void instr32_72_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_b"); } +void instr32_73_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nb"); } +void instr32_74_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_z"); } +void instr32_75_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nz"); } +void instr32_76_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_be"); } +void instr32_77_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nbe"); } +void instr32_78_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_s"); } +void instr32_79_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_ns"); } +void instr32_7A_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_p"); } +void instr32_7B_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_np"); } +void instr32_7C_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_l"); } +void instr32_7D_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nl"); } +void instr32_7E_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_le"); } +void instr32_7F_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nle"); } DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_80_0, add8(___, imm)) DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_80_1, or8(___, imm)) @@ -1413,10 +1447,15 @@ void instr_DF_5_reg(int32_t r) { task_switch_test(); fpu_fucomip(r); } void instr_DF_6_reg(int32_t r) { task_switch_test(); fpu_fcomip(r); } void instr_DF_7_reg(int32_t r) { trigger_ud(); } -void instr_E0(int32_t off) { loopne(off); } -void instr_E1(int32_t off) { loope(off); } -void instr_E2(int32_t off) { loop(off); } -void instr_E3(int32_t off) { jcxz(off); } +void instr16_E0(int32_t imm8s) { loopne16(imm8s); } +void instr16_E1(int32_t imm8s) { loope16(imm8s); } +void instr16_E2(int32_t imm8s) { loop16(imm8s); } +void instr16_E3(int32_t imm8s) { jcxz16(imm8s); } + +void instr32_E0(int32_t imm8s) { loopne32(imm8s); } +void instr32_E1(int32_t imm8s) { loope32(imm8s); } +void instr32_E2(int32_t imm8s) { loop32(imm8s); } +void instr32_E3(int32_t imm8s) { jcxz32(imm8s); } void instr_E4(int32_t port) { test_privileges_for_io(port, 1); @@ -1491,14 +1530,22 @@ void instr32_EA(int32_t new_ip, int32_t cs) { dbg_assert(is_asize_32() || get_real_eip() < 0x10000); } -void instr_EB(int32_t imm8) { +void instr16_EB(int32_t imm8) { + // jmp near + jmp_rel16(imm8); + dbg_assert(is_asize_32() || get_real_eip() < 0x10000); +} +void instr32_EB(int32_t imm8) { // jmp near instruction_pointer[0] = instruction_pointer[0] + imm8; dbg_assert(is_asize_32() || get_real_eip() < 0x10000); } -void instr_EB_jit(int32_t imm8s) { - gen_fn1_const("instr_EB", 8, imm8s); +void instr16_EB_jit(int32_t imm8s) { + gen_fn1_const("instr16_EB", 10, imm8s); +} +void instr32_EB_jit(int32_t imm8s) { + gen_fn1_const("instr32_EB", 10, imm8s); } void instr_EC() { diff --git a/src/native/misc_instr.c b/src/native/misc_instr.c index 4fcd1614..88c5997e 100644 --- a/src/native/misc_instr.c +++ b/src/native/misc_instr.c @@ -112,14 +112,6 @@ void jmp_rel16(int32_t rel16) *instruction_pointer = cs_offset + ((*instruction_pointer - cs_offset + rel16) & 0xFFFF); } -void jmpcc8(bool condition, int32_t imm8) -{ - if(condition) - { - *instruction_pointer += imm8; - } -} - void jmpcc16(bool condition, int32_t imm16) { if(condition) @@ -136,38 +128,15 @@ void jmpcc32(bool condition, int32_t imm32) } } -void loopne(int32_t imm8s) -{ - if(decr_ecx_asize() && !getzf()) - { - instruction_pointer[0] = instruction_pointer[0] + imm8s; - } -} - -void loope(int32_t imm8s) -{ - if(decr_ecx_asize() && getzf()) - { - instruction_pointer[0] = instruction_pointer[0] + imm8s; - } -} - -void loop(int32_t imm8s) -{ - if(decr_ecx_asize()) - { - instruction_pointer[0] = instruction_pointer[0] + imm8s; - } -} - -void jcxz(int32_t imm8s) -{ - if(get_reg_asize(ECX) == 0) - { - instruction_pointer[0] = instruction_pointer[0] + imm8s; - } -} +void loopne16(int32_t imm8s) { jmpcc16(decr_ecx_asize() && !getzf(), imm8s); } +void loope16(int32_t imm8s) { jmpcc16(decr_ecx_asize() && getzf(), imm8s); } +void loop16(int32_t imm8s) { jmpcc16(decr_ecx_asize(), imm8s); } +void jcxz16(int32_t imm8s) { jmpcc16(get_reg_asize(ECX) == 0, imm8s); } +void loopne32(int32_t imm8s) { jmpcc32(decr_ecx_asize() && !getzf(), imm8s); } +void loope32(int32_t imm8s) { jmpcc32(decr_ecx_asize() && getzf(), imm8s); } +void loop32(int32_t imm8s) { jmpcc32(decr_ecx_asize(), imm8s); } +void jcxz32(int32_t imm8s) { jmpcc32(get_reg_asize(ECX) == 0, imm8s); } void cmovcc16(bool condition, int32_t value, int32_t r) { diff --git a/src/native/misc_instr.h b/src/native/misc_instr.h index 3eff6616..046c5343 100644 --- a/src/native/misc_instr.h +++ b/src/native/misc_instr.h @@ -29,13 +29,17 @@ bool test_nl(void); bool test_nle(void); void jmp_rel16(int32_t rel16); -void jmpcc8(bool condition, int32_t imm8); void jmpcc16(bool condition, int32_t imm16); void jmpcc32(bool condition, int32_t imm32); -void loope(int32_t imm8s); -void loopne(int32_t imm8s); -void loop(int32_t imm8s); -void jcxz(int32_t imm8s); + +void loope16(int32_t imm8s); +void loopne16(int32_t imm8s); +void loop16(int32_t imm8s); +void jcxz16(int32_t imm8s); +void loope32(int32_t imm8s); +void loopne32(int32_t imm8s); +void loop32(int32_t imm8s); +void jcxz32(int32_t imm8s); void cmovcc16(bool condition, int32_t value, int32_t r); void cmovcc32(bool condition, int32_t value, int32_t r); From c8986111961731478ad8eac3cc688dd7d875e80b Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 19 Jun 2018 10:30:38 -0600 Subject: [PATCH 0947/2137] Regression tests for 8-bit jumps --- tests/nasm/jcc8.asm | 33 +++++++++++++++++++++++++++++++++ tests/nasm/jmp_near.asm | 38 ++++++++++++++++++++++++++++++++++++++ tests/nasm/loop.asm | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 tests/nasm/jcc8.asm create mode 100644 tests/nasm/jmp_near.asm create mode 100644 tests/nasm/loop.asm diff --git a/tests/nasm/jcc8.asm b/tests/nasm/jcc8.asm new file mode 100644 index 00000000..26058f71 --- /dev/null +++ b/tests/nasm/jcc8.asm @@ -0,0 +1,33 @@ +global _start + +section .data +re_entered: + db 0 + +%include "header.inc" + +align 0x10000 + + cmp byte [re_entered], 0 + jz ok + + ; force a #gp if the code section is re-entered + mov eax, -1 + mov cr4, eax + +ok: + mov byte [re_entered], 1 + + ; NOPs until the beginning of the next page minus two bytes + times ($$-$) % 0x10000 - 2 nop + inc al + + ; Next page starts here + + ; should jump to absolute address 0xfffe and #gp, as 16-bit eip wraps around + db 0x66 + jnz ($-3) + + ; this should never be executed + +%include "footer.inc" diff --git a/tests/nasm/jmp_near.asm b/tests/nasm/jmp_near.asm new file mode 100644 index 00000000..46d1c8ff --- /dev/null +++ b/tests/nasm/jmp_near.asm @@ -0,0 +1,38 @@ +global _start + +section .data +re_entered: + db 0 + +%include "header.inc" + +align 0x10000 + + cmp byte [re_entered], 0 + jz ok + + ; force a #gp if the code section is re-entered + mov eax, -1 + mov cr4, eax + +ok: + mov byte [re_entered], 1 + + jmp page_start + + ; NOPs until the beginning of the next page minus two bytes + times ($$-$) % 0x10000 - 2 nop + jmp fail + + ; Next page starts here + +page_start: + ; should jump to absolute address 0xfffe and #gp, as 16-bit eip wraps around + ; jumps to "fail" if 32-bit eip is used + db 0x66 + jmp ($-3) + +fail: + ; this should never be executed + +%include "footer.inc" diff --git a/tests/nasm/loop.asm b/tests/nasm/loop.asm new file mode 100644 index 00000000..b24245ed --- /dev/null +++ b/tests/nasm/loop.asm @@ -0,0 +1,34 @@ +global _start + +section .data +re_entered: + db 0 + +%include "header.inc" + +align 0x10000 + + cmp byte [re_entered], 0 + jz ok + + ; force a #gp if the code section is re-entered + mov eax, -1 + mov cr4, eax + +ok: + mov byte [re_entered], 1 + + mov ecx, 2 ; loop counter variable + + ; NOPs until the beginning of the next page minus one byte + times ($$-$) % 0x10000 nop + + ; Next page starts here + + ; should jump to absolute address 0xfffe and #gp, as 16-bit eip wraps around + db 0x66 + loop ($-3) + + ; this should never be executed + +%include "footer.inc" From 2f9078040f90c9a32d2bb2a329114295c4c01e29 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 19 Jun 2018 11:00:04 -0600 Subject: [PATCH 0948/2137] The stack segment can't be null --- src/native/cpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/native/cpu.c b/src/native/cpu.c index ea6cc793..42e89f10 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -654,8 +654,8 @@ static void jit_run_interpreted(int32_t phys_addr) bool has_flat_segmentation(void) { - return !segment_is_null[SS] && segment_offsets[SS] == 0 && - !segment_is_null[DS] && segment_offsets[DS] == 0; + // ss can't be null + return segment_offsets[SS] == 0 && !segment_is_null[DS] && segment_offsets[DS] == 0; } static cached_state_flags pack_current_state_flags() From 8a682f40766ff71f5d074a7f10e8119dd7354d04 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 19 Jun 2018 14:58:35 -0600 Subject: [PATCH 0949/2137] jit_cache_array: Check more invariants --- src/native/cpu.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/native/cpu.c b/src/native/cpu.c index 42e89f10..8e82c3df 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -707,6 +707,30 @@ void check_jit_cache_array_invariants(void) wasm_table_index_to_jit_cache_index[entry->wasm_table_index] = i; } } + + if(entry->start_addr) + { + // valid entries can be reached from page_first_jit_cache_entry + bool reached = false; + + uint32_t index = entry->start_addr >> DIRTY_ARR_SHIFT; + int32_t cache_array_index = page_first_jit_cache_entry[index]; + + while(cache_array_index != JIT_CACHE_ARRAY_NO_NEXT_ENTRY) + { + struct code_cache* other_entry = &jit_cache_arr[cache_array_index]; + + if(entry == other_entry) + { + reached = true; + break; + } + + cache_array_index = other_entry->next_index_same_page; + } + + assert(reached); + } } // there are no loops in the linked lists From 7c666596feed945976bacfab2833d3f47a8cbca3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 19 Jun 2018 14:59:31 -0600 Subject: [PATCH 0950/2137] Remove superfluous invariants check (is checked by the caller) --- src/native/cpu.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/native/cpu.c b/src/native/cpu.c index 8e82c3df..e5770f33 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -780,8 +780,6 @@ static struct code_cache* create_cache_entry(uint32_t phys_addr) } } - check_jit_cache_array_invariants(); - if(found_entry_index == -1) { profiler_stat_increment(S_CACHE_MISMATCH); From 423cfbea652408a3ee585f2fbeea8fcfe0848267 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 19 Jun 2018 15:17:04 -0600 Subject: [PATCH 0951/2137] Check for potential faults before doing port io --- src/native/string.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/native/string.c b/src/native/string.c index c0748844..529bef17 100644 --- a/src/native/string.c +++ b/src/native/string.c @@ -1133,6 +1133,7 @@ void insw_rep() { do { + writable_or_pagefault(dest, 2); safe_write16(dest, io_port_read16(port)); dest += size; add_reg_asize(EDI, size); @@ -1208,6 +1209,7 @@ void insd_rep() { do { + writable_or_pagefault(dest, 4); safe_write32(dest, io_port_read32(port)); dest += size; add_reg_asize(EDI, size); From 0cc47d72d112ef6f795ae7e20b48658cad9b8091 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 21 Jun 2018 13:20:39 -0600 Subject: [PATCH 0952/2137] nasmtests: Catch general protection error / sigsegv --- tests/nasm/gen_fixtures.js | 1 + tests/nasm/run.js | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/tests/nasm/gen_fixtures.js b/tests/nasm/gen_fixtures.js index bf1344ac..50fc4e85 100755 --- a/tests/nasm/gen_fixtures.js +++ b/tests/nasm/gen_fixtures.js @@ -26,6 +26,7 @@ const GDB_DEFAULT_ARGS = [ "--eval-command=break loop", "--eval-command=catch signal SIGFPE", "--eval-command=catch signal SIGILL", + "--eval-command=catch signal SIGSEGV", ]; /* Split up an array into semi-evenly sized chunks */ diff --git a/tests/nasm/run.js b/tests/nasm/run.js index 703da8c1..8db192ad 100755 --- a/tests/nasm/run.js +++ b/tests/nasm/run.js @@ -55,6 +55,11 @@ if(cluster.isMaster) return { exception: "UD", }; } + if(fixture_text.includes("(signal SIGSEGV)")) + { + return { exception: "GP", }; + } + if(fixture_text.includes("Program received signal") || fixture_text.includes("SIGILL")) { throw new Error("Test was killed during execution by gdb: " + name + "\n" + fixture_text); @@ -263,6 +268,7 @@ else { const exceptions = { 0: "DE", 6: "UD", + 13: "GP", }; const exception = exceptions[n]; From 950ae53dde74ad44a516f866c0b49722b7ad44b1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 19 Jun 2018 15:19:24 -0600 Subject: [PATCH 0953/2137] Optimisation: Allow safe_{read,write} fast path for cpl<3 This also adds cpl==3 into the state flags, which might cause some code to be compiled twice (once for cpl<3 and once for cpl==3), but this is assumed to be an uncommon case compared to memory accesses for cpl<3. --- src/native/codegen/codegen.c | 8 ++++---- src/native/cpu.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/native/codegen/codegen.c b/src/native/codegen/codegen.c index 2b455c19..7c17d436 100644 --- a/src/native/codegen/codegen.c +++ b/src/native/codegen/codegen.c @@ -323,9 +323,9 @@ void gen_safe_read32(void) load_aligned_i32_from_stack(&instruction_body, (uint32_t) tlb_data); gen_tee_local(entry_local); - // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL == TLB_VALID && + // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && // (address & 0xFFF) <= (0x1000 - 4)); - gen_const_i32(0xFFF & ~TLB_READONLY & ~TLB_GLOBAL); + gen_const_i32(0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(*cpl == 3 ? 0 : TLB_NO_USER)); and_i32(&instruction_body); gen_const_i32(TLB_VALID); @@ -388,9 +388,9 @@ void gen_safe_write32(int32_t local_for_address, int32_t local_for_value) load_aligned_i32_from_stack(&instruction_body, (uint32_t) tlb_data); gen_tee_local(entry_local); - // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_GLOBAL == TLB_VALID && + // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && // (address & 0xFFF) <= (0x1000 - 4)); - gen_const_i32(0xFFF & ~TLB_GLOBAL); + gen_const_i32(0xFFF & ~TLB_GLOBAL & ~(*cpl == 3 ? 0 : TLB_NO_USER)); and_i32(&instruction_body); gen_const_i32(TLB_VALID); diff --git a/src/native/cpu.c b/src/native/cpu.c index e5770f33..be8feee5 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -660,7 +660,7 @@ bool has_flat_segmentation(void) static cached_state_flags pack_current_state_flags() { - return *is_32 << 0 | *stack_size_32 << 1 | has_flat_segmentation() << 2; + return *is_32 << 0 | *stack_size_32 << 1 | (*cpl == 3) << 2 | has_flat_segmentation() << 3; } void check_jit_cache_array_invariants(void) From 44642c6e30485222879a5199ac507a3a9825d8d0 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 19 Jun 2018 15:47:50 -0600 Subject: [PATCH 0954/2137] Add missing void to argument list --- src/native/cpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/cpu.h b/src/native/cpu.h index 06cf2f5c..6832689c 100644 --- a/src/native/cpu.h +++ b/src/native/cpu.h @@ -173,7 +173,7 @@ int32_t get_seg_prefix_cs(int32_t offset); int32_t modrm_resolve(int32_t modrm_byte); void modrm_skip(int32_t modrm_byte); -void check_jit_cache_array_invariants(); +void check_jit_cache_array_invariants(void); uint32_t jit_hot_hash_page(uint32_t page); void jit_link_block(int32_t target); From 94b0376186a9ade43bf6015c33ccc05e43b8ecfd Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 20 Jun 2018 10:39:57 -0600 Subject: [PATCH 0955/2137] Remove timing profiler --- src/browser/print_stats.js | 10 ----- src/cpu.js | 10 ----- src/native/config.h | 1 - src/native/cpu.c | 8 ---- src/native/profiler/profiler.c | 82 ---------------------------------- src/native/profiler/profiler.h | 22 --------- tests/benchmark/linux-boot.js | 21 --------- 7 files changed, 154 deletions(-) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index 36a66fb5..b5cd02bd 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -48,16 +48,6 @@ const print_stats = { "TLB_GLOBAL_FULL", ]; - const total = cpu.wm.exports["_profiler_get_total"](); - - for(let i = 0; i < names.length; i++) - { - let stat = cpu.wm.exports["_profiler_get_time"](i) / total; - text += names[i] + "=" + stat.toFixed(2) + " "; - } - - text += "\n"; - for(let i = 0; i < stat_names.length; i++) { let stat = cpu.wm.exports["_profiler_stat_get"](i); diff --git a/src/cpu.js b/src/cpu.js index 969864b6..3c071e4f 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -1122,9 +1122,6 @@ CPU.prototype.do_run = function() { this.wm.exports["_profiler_stat_increment_do_run"](); - // Idle time is when no instructions are being executed - this.wm.exports["_profiler_end"](P_IDLE); - /** @type {number} */ var start = v86.microtick(); @@ -1147,8 +1144,6 @@ CPU.prototype.do_run = function() now = v86.microtick(); } - - this.wm.exports["_profiler_start"](P_IDLE); }; let do_many_cycles_count = 0; @@ -1157,7 +1152,6 @@ let do_many_cycles_total = 0; CPU.prototype.do_many_cycles = function() { // Capture the total time we were executing instructions - this.wm.exports["_profiler_start"](P_DO_MANY_CYCLES); this.coverage_logger.log_start(); if(ENABLE_PROFILER) @@ -1180,10 +1174,6 @@ CPU.prototype.do_many_cycles = function() } this.coverage_logger.log_end(); - this.wm.exports["_profiler_end"](P_DO_MANY_CYCLES); - this.wm.exports["_profiler_end"](P_GEN_INSTR); - this.wm.exports["_profiler_end"](P_RUN_FROM_CACHE); - this.wm.exports["_profiler_end"](P_RUN_INTERPRETED); }; /** @export */ diff --git a/src/native/config.h b/src/native/config.h index fe6d24db..3f365b8d 100644 --- a/src/native/config.h +++ b/src/native/config.h @@ -38,7 +38,6 @@ #endif #define ENABLE_PROFILER 0 -#define ENABLE_PROFILER_TIMES 0 #define ENABLE_PROFILER_OPSTATS 0 // Note: needs to be enabled here and in config.js diff --git a/src/native/cpu.c b/src/native/cpu.c index be8feee5..50301b69 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -624,7 +624,6 @@ uint32_t jit_hot_hash_page(uint32_t page) static void jit_run_interpreted(int32_t phys_addr) { - profiler_start(P_RUN_INTERPRETED); profiler_stat_increment(S_RUN_INTERPRETED); jit_block_boundary = false; @@ -648,8 +647,6 @@ static void jit_run_interpreted(int32_t phys_addr) #endif run_instruction(opcode | !!*is_32 << 8); } - - profiler_end(P_RUN_INTERPRETED); } bool has_flat_segmentation(void) @@ -1495,7 +1492,6 @@ __attribute__((noinline)) static void jit_generate(uint32_t phys_addr) { profiler_stat_increment(S_COMPILE); - profiler_start(P_GEN_INSTR); // don't immediately retry to compile hot_code_addresses[jit_hot_hash_page(phys_addr >> 12)] = 0; @@ -1509,7 +1505,6 @@ static void jit_generate(uint32_t phys_addr) // populate basic_blocks if(!jit_find_basic_blocks(phys_addr, &requires_loop_limit)) { - profiler_end(P_GEN_INSTR); dbg_log("No basic blocks, not generating code"); *instruction_pointer = start; return; @@ -1732,7 +1727,6 @@ static void jit_generate(uint32_t phys_addr) first_opcode, state_flags); profiler_stat_increment(S_COMPILE_SUCCESS); - profiler_end(P_GEN_INSTR); *instruction_pointer = start; } @@ -1759,7 +1753,6 @@ void cycle_internal() if(entry && !entry->pending) { - profiler_start(P_RUN_FROM_CACHE); profiler_stat_increment(S_RUN_FROM_CACHE); int32_t initial_tsc = *timestamp_counter; @@ -1778,7 +1771,6 @@ void cycle_internal() UNUSED(old_start_address); profiler_stat_increment_by(S_RUN_FROM_CACHE_STEPS, *timestamp_counter - initial_tsc); - profiler_end(P_RUN_FROM_CACHE); } else { diff --git a/src/native/profiler/profiler.c b/src/native/profiler/profiler.c index 8763bf0d..4b68834f 100644 --- a/src/native/profiler/profiler.c +++ b/src/native/profiler/profiler.c @@ -9,93 +9,16 @@ #if ENABLE_PROFILER -struct profiler_data profiler_arr[PROFILER_NAME_COUNT] = {{0, 0, false}}; struct profiler_stat profiler_stat_arr[PROFILER_STAT_COUNT] = {{0}}; -double profiler_init_time = 0; void profiler_init(void) { - 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; - } - for(uint32_t i = 0; i < PROFILER_STAT_COUNT; i++) { profiler_stat_arr[i].count = 0; } } -void profiler_start(enum profile_name name) -{ -#if ENABLE_PROFILER_TIMES - struct profiler_data *entry = &profiler_arr[name]; - assert(!entry->capturing); - - entry->current_start = get_time(); - entry->capturing = true; -#endif - UNUSED(name); -} - -void profiler_end(enum profile_name name) -{ -#if ENABLE_PROFILER_TIMES - struct profiler_data *entry = &profiler_arr[name]; - if(entry->capturing) - { - entry->total += get_time() - entry->current_start; - entry->current_start = 0; - entry->capturing = false; - } -#endif - UNUSED(name); -} - -void profiler_print(void) -{ -#if ENABLE_PROFILER_TIMES - static const char *profiler_names[] = { - "IDLE", - "DO_MANY_CYCLES", - "GEN_INSTR", - "RUN_FROM_CACHE", - "RUN_INTERPRETED", - }; - - double init_elapsed = get_time() - profiler_init_time; - printf("\nElapsed: %d\n", (int32_t) init_elapsed); - for(int32_t i = 0; i < PROFILER_NAME_COUNT; i++) - { - double cur_total = profiler_arr[i].total; - printf(profiler_names[i]); - printf( - "\nIndex:\t%d" - "\nTotal:\t%d" - "\nPercentage:\t%d%%\n", - i, - (int32_t) cur_total, - (int32_t) (100 * cur_total / init_elapsed) - ); - } -#endif -} - -int32_t profiler_get_time(enum profile_name name) -{ - return profiler_arr[name].total; -} - -int32_t profiler_get_total(void) -{ - return get_time() - profiler_init_time; -} - void profiler_stat_increment(enum stat_name stat) { profiler_stat_increment_by(stat, 1); @@ -121,11 +44,6 @@ int32_t profiler_stat_get(enum stat_name stat) // Disable profiler void profiler_init(void) {} -void profiler_start(enum profile_name name) { UNUSED(name); } -void profiler_end(enum profile_name name) { UNUSED(name); } -void profiler_print(void) {} -int32_t profiler_get_time(enum profile_name name) { UNUSED(name); return 0; } -int32_t profiler_get_total(void) { return 0; } void profiler_stat_increment(enum stat_name stat) { UNUSED(stat); } void profiler_stat_increment_by(enum stat_name stat, int32_t by) { UNUSED(stat); UNUSED(by); } void profiler_stat_increment_do_run() {} diff --git a/src/native/profiler/profiler.h b/src/native/profiler/profiler.h index 4944b23c..6cdf7fd0 100644 --- a/src/native/profiler/profiler.h +++ b/src/native/profiler/profiler.h @@ -3,25 +3,6 @@ #include #include -#define PROFILER_NAME_COUNT 5 - -struct profiler_data { - double total; - double current_start; - bool capturing; -}; - -extern struct profiler_data profiler_arr[PROFILER_NAME_COUNT]; - -enum profile_name { - P_IDLE, - P_DO_MANY_CYCLES, - P_GEN_INSTR, - P_RUN_FROM_CACHE, - P_RUN_INTERPRETED, -}; - - enum stat_name { S_COMPILE, S_COMPILE_SUCCESS, @@ -65,9 +46,6 @@ struct profiler_stat { extern struct profiler_stat profiler_stat_arr[PROFILER_STAT_COUNT]; void profiler_init(void); -void profiler_start(enum profile_name name); -void profiler_end(enum profile_name name); -void profiler_print(void); void profiler_stat_increment(enum stat_name stat); void profiler_stat_increment_by(enum stat_name stat, int32_t by); diff --git a/tests/benchmark/linux-boot.js b/tests/benchmark/linux-boot.js index 12f14408..91178c32 100755 --- a/tests/benchmark/linux-boot.js +++ b/tests/benchmark/linux-boot.js @@ -47,13 +47,6 @@ emulator.add_listener("serial0-output-char", function(chr) emulator.stop(); const cpu = emulator.v86.cpu; - const names = [ - "IDLE", - "DO_MANY_CYCLES", - "GEN_INSTR", - "RUN_FROM_CACHE", - "RUN_INTERPRETED", - ]; const stat_names = [ "COMPILE", "COMPILE_SUCCESS", @@ -66,22 +59,8 @@ emulator.add_listener("serial0-output-char", function(chr) "TLB_FULL", "TLB_GLOBAL_FULL", ]; - const total = cpu.wm.exports["_profiler_get_total"](); let text = ""; - if(!total) - { - console.error("Warning: No elapsed time measured, did you set ENABLE_PROFILER?"); - } - - for(let i = 0; i < names.length; i++) - { - let stat = cpu.wm.exports["_profiler_get_time"](i) / total; - text += names[i] + "=" + stat.toFixed(2) + " "; - } - - text += "\n"; - for(let i = 0; i < stat_names.length; i++) { let stat = cpu.wm.exports["_profiler_stat_get"](i); From 5e1e3ea06dfa627673d4e2720a1a8a6e072632e5 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 25 Jun 2018 10:10:32 -0600 Subject: [PATCH 0956/2137] Remove unused constants --- src/const.js | 7 ------- src/native/const.h | 6 ------ 2 files changed, 13 deletions(-) diff --git a/src/const.js b/src/const.js index a71d1d4e..aa053e8b 100644 --- a/src/const.js +++ b/src/const.js @@ -59,13 +59,6 @@ var LOG_NAMES = [ [LOG_9P, "9P"], ]; -var -/** @const */ TLB_SYSTEM_READ = 1, -/** @const */ TLB_SYSTEM_WRITE = 2, -/** @const */ TLB_USER_READ = 4, -/** @const */ TLB_USER_WRITE = 8; - - var // flags register bitflags diff --git a/src/native/const.h b/src/native/const.h index 0c8c138e..4e7a601c 100644 --- a/src/native/const.h +++ b/src/native/const.h @@ -68,12 +68,6 @@ #define LDTR 7 -#define TLB_SYSTEM_READ 1 -#define TLB_SYSTEM_WRITE 2 -#define TLB_USER_READ 4 -#define TLB_USER_WRITE 8 - - #define PSE_ENABLED 128 #define PAGE_TABLE_PRESENT_MASK (1 << 0) From e5e827d9237b556e94a15aa543d9d83757aa8c8a Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Wed, 20 Jun 2018 02:31:03 +0530 Subject: [PATCH 0957/2137] import wasmgen from original oxidation branch --- .gitignore | 2 + docker/test-image/Dockerfile | 7 +- src/wasmgen/Cargo.toml | 19 ++ src/wasmgen/src/c_api.rs | 88 +++++++++ src/wasmgen/src/codegen.rs | 172 ++++++++++++++++ src/wasmgen/src/dbg.rs | 70 +++++++ src/wasmgen/src/lib.rs | 12 ++ src/wasmgen/src/module_init.rs | 337 ++++++++++++++++++++++++++++++++ src/wasmgen/src/util.rs | 96 +++++++++ src/wasmgen/src/wasm_opcodes.rs | 221 +++++++++++++++++++++ src/wasmgen/src/wasm_util.rs | 84 ++++++++ 11 files changed, 1107 insertions(+), 1 deletion(-) create mode 100644 src/wasmgen/Cargo.toml create mode 100644 src/wasmgen/src/c_api.rs create mode 100644 src/wasmgen/src/codegen.rs create mode 100644 src/wasmgen/src/dbg.rs create mode 100644 src/wasmgen/src/lib.rs create mode 100644 src/wasmgen/src/module_init.rs create mode 100644 src/wasmgen/src/util.rs create mode 100644 src/wasmgen/src/wasm_opcodes.rs create mode 100644 src/wasmgen/src/wasm_util.rs diff --git a/.gitignore b/.gitignore index 0e4bbcfb..1babd7d1 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,5 @@ images/ node_modules/ package-lock.json profile*.json +src/wasmgen/target +src/wasmgen/Cargo.lock diff --git a/docker/test-image/Dockerfile b/docker/test-image/Dockerfile index 40db73e8..ff166f1f 100644 --- a/docker/test-image/Dockerfile +++ b/docker/test-image/Dockerfile @@ -6,4 +6,9 @@ RUN \ apt-get install -y clang-tidy gcc-multilib nasm gdb unzip openjdk-8-jre wget python qemu-system-x86 && \ wget https://nodejs.org/dist/v8.9.4/node-v8.9.4-linux-x64.tar.xz && \ tar xfv node-v8.9.4-linux-x64.tar.xz && \ - rm node-v8.9.4-linux-x64.tar.xz + rm node-v8.9.4-linux-x64.tar.xz && \ + wget https://sh.rustup.rs -O rustup.sh && \ + sh ./rustup.sh && \ + rm ./rustup.sh && \ + rustup toolchain install nightly && \ + rustup target add wasm32-unknown-unknown --toolchain nightly diff --git a/src/wasmgen/Cargo.toml b/src/wasmgen/Cargo.toml new file mode 100644 index 00000000..e95b6bee --- /dev/null +++ b/src/wasmgen/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "wasmgen" +version = "0.1.0" +authors = ["Awal Garg "] +publish = false + +[dependencies] +lazy_static = "1.0" + +[lib] +crate-type = ["cdylib"] + +[profile.dev] +panic = "abort" + +[profile.release] +lto = true +incremental = false +panic = "abort" diff --git a/src/wasmgen/src/c_api.rs b/src/wasmgen/src/c_api.rs new file mode 100644 index 00000000..4a1bad22 --- /dev/null +++ b/src/wasmgen/src/c_api.rs @@ -0,0 +1,88 @@ +use ::util::PackedStr; + +pub use ::module_init::{ setup, get_module }; + +#[no_mangle] +pub fn new_buf() -> *mut Vec { + let b = Box::new(Vec::with_capacity(256)); + Box::into_raw(b) +} + +#[no_mangle] +pub fn reset() { + let m = get_module(); + m.reset(); +} + +#[no_mangle] +pub fn finish(no_of_locals_i32: u8) { + let m = get_module(); + m.finish(no_of_locals_i32); +} + +#[no_mangle] +pub fn get_fn_idx(fn_name: PackedStr, type_idx: u8) -> u8 { + let m = get_module(); + m.get_fn_index(fn_name, type_idx) +} + +#[no_mangle] +pub fn include_buffer(buf: *mut Vec) { + let m = get_module(); + m.include_buffer(buf); +} + +#[no_mangle] +pub fn get_op_ptr() -> *const u8 { + let m = get_module(); + m.get_op_ptr() +} + +#[no_mangle] +pub fn get_op_len() -> usize { + let m = get_module(); + m.get_op_len() +} + +#[cfg(test)] +mod tests { + use std::io::prelude::*; + use std::fs::File; + use ::codegen::*; + use ::c_api::*; + use ::util::*; + use ::wasm_util::*; + + #[test] + fn c_api_test() { + setup(); + let buf1 = unsafe { new_buf().as_mut().expect("get buf1") }; + let buf2 = unsafe { new_buf().as_mut().expect("get buf2") }; + + gen_fn0_const_ret(buf1, pack_str("foo")); + gen_fn0_const_ret(buf1, pack_str("bar")); + + include_buffer(buf1); + + finish(2); + reset(); + + push_i32(buf1, 2); + gen_call_fn1_ret(buf2, pack_str("baz")); + gen_drop(buf2); + + include_buffer(buf1); + include_buffer(buf2); + + finish(1); + + let op_ptr = get_op_ptr(); + let op_len = get_op_len(); + dbg_log!("op_ptr: {:?}, op_len: {:?}", op_ptr, op_len); + + // XXX: move file path + let mut f = File::create("c_api_test.wasm").expect("creating c_api_test.wasm"); + f.write_all(&get_module().op).expect("write c_api_test.wasm"); + } + +} diff --git a/src/wasmgen/src/codegen.rs b/src/wasmgen/src/codegen.rs new file mode 100644 index 00000000..fc97c0fd --- /dev/null +++ b/src/wasmgen/src/codegen.rs @@ -0,0 +1,172 @@ +use ::wasm_opcodes::*; +use ::util::*; +use ::wasm_util::*; +use ::module_init::*; + +#[no_mangle] +pub fn gen_fn0_const(buf: &mut Vec, fn_name: PackedStr) { + let m = get_module(); + let fn_idx = m.get_fn_index(fn_name, FN0_TYPE_INDEX); + call_fn(buf, fn_idx); +} + +#[no_mangle] +pub fn gen_fn0_const_ret(buf: &mut Vec, fn_name: PackedStr) { + let m = get_module(); + let fn_idx = m.get_fn_index(fn_name, FN0_RET_TYPE_INDEX); + call_fn(buf, fn_idx); +} + +#[no_mangle] +pub fn gen_fn1_const(buf: &mut Vec, fn_name: PackedStr, arg0: i32) { + let m = get_module(); + let fn_idx = m.get_fn_index(fn_name, FN1_TYPE_INDEX); + push_i32(buf, arg0); + call_fn(buf, fn_idx); +} + +#[no_mangle] +pub fn gen_fn1_const_ret(buf: &mut Vec, fn_name: PackedStr, arg0: i32) { + let m = get_module(); + let fn_idx = m.get_fn_index(fn_name, FN1_RET_TYPE_INDEX); + push_i32(buf, arg0); + call_fn(buf, fn_idx); +} + +#[no_mangle] +pub fn gen_fn2_const(buf: &mut Vec, fn_name: PackedStr, arg0: i32, arg1: i32) { + let m = get_module(); + let fn_idx = m.get_fn_index(fn_name, FN2_TYPE_INDEX); + push_i32(buf, arg0); + push_i32(buf, arg1); + call_fn(buf, fn_idx); +} + +#[no_mangle] +pub fn gen_fn3_const(buf: &mut Vec, fn_name: PackedStr, arg0: i32, arg1: i32, arg2: i32) { + let m = get_module(); + let fn_idx = m.get_fn_index(fn_name, FN3_TYPE_INDEX); + push_i32(buf, arg0); + push_i32(buf, arg1); + push_i32(buf, arg2); + call_fn(buf, fn_idx); +} + +#[no_mangle] +pub fn gen_call_fn1_ret(buf: &mut Vec, fn_name: PackedStr) { + // generates: fn( _ ) where _ must be left on the stack before calling this, and fn returns a value + let m = get_module(); + let fn_idx = m.get_fn_index(fn_name, FN1_RET_TYPE_INDEX); + call_fn(buf, fn_idx); +} + +#[no_mangle] +pub fn gen_call_fn2(buf: &mut Vec, fn_name: PackedStr) { + // generates: fn( _, _ ) where _, _ must be left on the stack before calling this + let m = get_module(); + let fn_idx = m.get_fn_index(fn_name, FN2_TYPE_INDEX); + call_fn(buf, fn_idx); +} + +#[no_mangle] +pub fn gen_eqz_i32(buf: &mut Vec) { + buf.push(OP_I32EQZ); +} + +#[no_mangle] +pub fn gen_if_void(buf: &mut Vec) { + buf.push(OP_IF); + buf.push(TYPE_VOID_BLOCK); +} + +#[no_mangle] +pub fn gen_else(buf: &mut Vec) { + buf.push(OP_ELSE); +} + +#[no_mangle] +pub fn gen_loop_void(buf: &mut Vec) { + buf.push(OP_LOOP); + buf.push(TYPE_VOID_BLOCK); +} + +#[no_mangle] +pub fn gen_block_void(buf: &mut Vec) { + buf.push(OP_BLOCK); + buf.push(TYPE_VOID_BLOCK); +} + +#[no_mangle] +pub fn gen_block_end(buf: &mut Vec) { + buf.push(OP_END); +} + +#[no_mangle] +pub fn gen_return(buf: &mut Vec) { + buf.push(OP_RETURN); +} + +#[no_mangle] +pub fn gen_drop(buf: &mut Vec) { + buf.push(OP_DROP); +} + +// Generate a br_table where an input of [i] will branch [i]th outer block, +// where [i] is passed on the wasm stack +#[no_mangle] +pub fn gen_brtable_and_cases(buf: &mut Vec, cases_count: i32) { + assert!(cases_count >= 0); + + buf.push(OP_BRTABLE); + write_leb_u32(buf, cases_count as u32); + + for i in 0..(cases_count + 1) { + write_leb_u32(buf, i as u32); + } +} + +#[no_mangle] +pub fn gen_br(buf: &mut Vec, depth: i32) { + buf.push(OP_BR); + write_leb_i32(buf, depth); +} + +#[no_mangle] +pub fn gen_get_local(buf: &mut Vec, idx: i32) { + buf.push(OP_GETLOCAL); + write_leb_i32(buf, idx); +} + +#[no_mangle] +pub fn gen_set_local(buf: &mut Vec, idx: i32) { + buf.push(OP_SETLOCAL); + write_leb_i32(buf, idx); +} + +#[no_mangle] +pub fn gen_const_i32(buf: &mut Vec, v: i32) { + push_i32(buf, v); +} + +#[no_mangle] +pub fn gen_unreachable(buf: &mut Vec) { + buf.push(OP_UNREACHABLE); +} + +#[no_mangle] +pub fn gen_increment_mem32(buf: &mut Vec, addr: u32) { + push_i32(buf, addr as i32); + load_aligned_i32(buf, addr); + push_i32(buf, 1); + add_i32(buf); + store_aligned_i32(buf); +} + +#[no_mangle] +pub fn gen_increment_variable(buf: &mut Vec, variable_address: u32, n: i32) { + push_i32(buf, variable_address as i32); + load_aligned_i32(buf, variable_address as u32); + push_i32(buf, n); + add_i32(buf); + store_aligned_i32(buf); +} diff --git a/src/wasmgen/src/dbg.rs b/src/wasmgen/src/dbg.rs new file mode 100644 index 00000000..7b10de90 --- /dev/null +++ b/src/wasmgen/src/dbg.rs @@ -0,0 +1,70 @@ +#[allow(dead_code)] +pub const DEBUG: bool = true; + +#[allow(unused_macros)] +macro_rules! dbg_log { + ($fmt:expr) => { + println!($fmt); + }; + ($fmt:expr, $($arg:tt)*) => { + println!($fmt, $($arg)*); + } +} + +#[allow(unused_macros)] +macro_rules! dbg_assert { + ($($arg:tt)*) => { + debug_assert!($($arg)*); + }; +} + +#[cfg(target_arch = "wasm32")] +extern "C" { + pub fn log_from_wasm(ptr: *const u8, len: usize); + pub fn abort(); +} + +#[cfg(target_arch = "wasm32")] +use std::string::ToString; + +#[cfg(target_arch = "wasm32")] +pub fn __log_to_js_console(s: T) { + let s: String = s.to_string(); + let len = s.len(); + unsafe { log_from_wasm(s.as_bytes().as_ptr(), len); } +} + +#[cfg(target_arch = "wasm32")] +macro_rules! dbg_log { + ($fmt:expr) => { + if DEBUG { __log_to_js_console($fmt); } + }; + ($fmt:expr, $($arg:tt)*) => { + if DEBUG { __log_to_js_console(format!($fmt, $($arg)*)); } + }; +} + +#[cfg(target_arch = "wasm32")] +macro_rules! dbg_assert { + ($cond:expr) => { + if DEBUG && !$cond { + __log_to_js_console(format!( + "Assertion failed at {}:{}:{}: '{}'", + file!(), line!(), column!(), + stringify!($cond), + )); + unsafe { abort(); } + } + }; + ($cond:expr, $desc:expr) => { + if DEBUG && !$cond { + __log_to_js_console(format!( + "Assertion failed at {}:{}:{}: '{}' - '{}'", + file!(), line!(), column!(), + stringify!($cond), + $desc, + )); + unsafe { abort(); } + } + }; +} diff --git a/src/wasmgen/src/lib.rs b/src/wasmgen/src/lib.rs new file mode 100644 index 00000000..b5faeb9e --- /dev/null +++ b/src/wasmgen/src/lib.rs @@ -0,0 +1,12 @@ +#[macro_use] +mod dbg; + +#[macro_use] +mod util; + +mod wasm_opcodes; +mod module_init; + +pub mod c_api; +pub mod codegen; +pub mod wasm_util; diff --git a/src/wasmgen/src/module_init.rs b/src/wasmgen/src/module_init.rs new file mode 100644 index 00000000..d384a831 --- /dev/null +++ b/src/wasmgen/src/module_init.rs @@ -0,0 +1,337 @@ +use std::ptr; + +use ::util::*; +use ::wasm_opcodes::*; + +pub const FN0_TYPE_INDEX: u8 = 0; +pub const FN1_TYPE_INDEX: u8 = 1; +pub const FN2_TYPE_INDEX: u8 = 2; +pub const FN3_TYPE_INDEX: u8 = 3; + +pub const FN0_RET_TYPE_INDEX: u8 = 4; +pub const FN1_RET_TYPE_INDEX: u8 = 5; + +#[allow(dead_code)] +pub const FN2_RET_TYPE_INDEX: u8 = 6; + +pub const NR_FN_TYPE_INDEXES: u8 = 7; + +static mut MODULE_PTR: *mut WasmBuilder = ptr::null_mut(); + +#[no_mangle] +pub fn setup() { + let wm = Box::new(WasmBuilder::new()); + unsafe { + MODULE_PTR = Box::into_raw(wm); + } + get_module().init(); +} + +#[no_mangle] +pub fn get_module<'a>() -> &'a mut WasmBuilder { + unsafe { + MODULE_PTR.as_mut().expect("getting module") + } +} + +pub struct WasmBuilder { + pub op: Vec, + pub buffers: Vec<*mut Vec>, + + idx_import_table_size: usize, // for rewriting once finished + idx_import_count: usize, // for rewriting once finished + idx_import_entries: usize, // for searching the imports + + import_table_size: usize, // the current import table size (to avoid reading 2 byte leb) + + initial_static_size: usize, // size of module after initialization, rest is drained on reset +} + +impl WasmBuilder { + pub fn new() -> Self { + WasmBuilder { + op: Vec::with_capacity(256), + buffers: Vec::with_capacity(64), + + idx_import_table_size: 0, + idx_import_count: 0, + idx_import_entries: 0, + + import_table_size: 1, + + initial_static_size: 0, + } + } + + pub fn init(&mut self) { + self.op.extend("\0asm".as_bytes()); + + // wasm version in leb128, 4 bytes + self.op.push(WASM_VERSION); self.op.push(0); self.op.push(0); self.op.push(0); + + self.write_type_section(); + self.write_import_section_preamble(); + + // store state of current pointers etc. so we can reset them later + self.initial_static_size = self.op.len(); + } + + pub fn reset(&mut self) { + self.op.drain(self.initial_static_size..); + self.set_import_table_size(1); + self.set_import_count(0); + self.buffers.drain(..); + } + + pub fn include_buffer(&mut self, buf: *mut Vec) { + self.buffers.push(buf); + } + + pub fn finish(&mut self, no_of_locals_i32: u8) -> usize { + self.write_memory_import(); + self.write_function_section(1); + self.write_export_section(); + + // write code section preamble + self.op.push(SC_CODE); + + let idx_code_section_size = self.op.len(); // we will write to this location later + self.op.push(0); self.op.push(0); // write temp val for now using 4 bytes + self.op.push(0); self.op.push(0); + + self.op.push(1); // number of function bodies: just 1 + + // same as above but for body size of the function + let idx_fn_body_size = self.op.len(); + self.op.push(0); self.op.push(0); + self.op.push(0); self.op.push(0); + + self.op.push(1); // count of local blocks + self.op.push(no_of_locals_i32); self.op.push(TYPE_I32); + + for buf_ptr in &mut self.buffers { + self.op.append(unsafe { buf_ptr.as_mut().expect("unloading buffer") }); + } + + self.op.push(OP_END); + + // write the actual sizes to the pointer locations stored above. We subtract 4 from the actual + // value because the ptr itself points to four bytes + let fn_body_size = (self.op.len() - idx_fn_body_size - 4) as u32; + write_fixed_leb32_to_buf(&mut self.op, idx_fn_body_size, fn_body_size); + + let code_section_size = (self.op.len() - idx_code_section_size - 4) as u32; + write_fixed_leb32_to_buf(&mut self.op, idx_code_section_size, code_section_size); + + self.op.len() + } + + pub fn write_type_section(&mut self) { + self.op.push(SC_TYPE); + + let idx_section_size = self.op.len(); + self.op.push(0); + + self.op.push(NR_FN_TYPE_INDEXES); // number of type descriptors + + // FN0 + self.op.push(TYPE_FUNC); + self.op.push(0); // no args + self.op.push(0); // no return val + + // FN1 + self.op.push(TYPE_FUNC); + self.op.push(1); + self.op.push(TYPE_I32); + self.op.push(0); + + // FN2 + self.op.push(TYPE_FUNC); + self.op.push(2); + self.op.push(TYPE_I32); + self.op.push(TYPE_I32); + self.op.push(0); + + // FN3 + self.op.push(TYPE_FUNC); + self.op.push(3); + self.op.push(TYPE_I32); + self.op.push(TYPE_I32); + self.op.push(TYPE_I32); + self.op.push(0); + + // FN0_RET + self.op.push(TYPE_FUNC); + self.op.push(0); + self.op.push(1); + self.op.push(TYPE_I32); + + // FN1_RET + self.op.push(TYPE_FUNC); + self.op.push(1); + self.op.push(TYPE_I32); + self.op.push(1); + self.op.push(TYPE_I32); + + // FN2_RET + self.op.push(TYPE_FUNC); + self.op.push(2); + self.op.push(TYPE_I32); + self.op.push(TYPE_I32); + self.op.push(1); + self.op.push(TYPE_I32); + + let new_len = self.op.len(); + let size = (new_len - 1) - idx_section_size; + self.op[idx_section_size] = size as u8; + } + + /// Goes over the import block to find index of an import entry by function name + pub fn get_import_index(&self, fn_name: PackedStr) -> Option { + let fn_name = unpack_str(fn_name); + let mut offset = self.idx_import_entries; + for i in 0..self.get_import_count() { + offset += 1; // skip length of module name + offset += 1; // skip module name itself + let len = self.op[offset]; + offset += 1; + let name = self.op.get(offset..(offset + len as usize)).expect("get function name"); + if name == fn_name.as_bytes() { + return Some(i); + } + offset += len as usize; // skip the string + offset += 1; // skip import kind + offset += 1; // skip type index + } + None + } + + pub fn get_import_count(&self) -> u8 { + dbg_assert!(self.idx_import_count < self.op.len()); + self.op[self.idx_import_count] + } + + pub fn set_import_count(&mut self, count: u8) { + self.op[self.idx_import_count] = count; + } + + pub fn set_import_table_size(&mut self, size: usize) { + self.import_table_size = size; + let idx_import_table_size = self.idx_import_table_size; + write_fixed_leb16_to_buf(&mut self.op, idx_import_table_size, size as u16); + } + + pub fn write_import_section_preamble(&mut self) { + self.op.push(SC_IMPORT); + + self.idx_import_table_size = self.op.len(); + self.op.push(1 | 0b10000000); self.op.push(0); // 1 in 2 byte leb + + self.idx_import_count = self.op.len(); + self.op.push(0); + + // here after starts the actual list of imports + self.idx_import_entries = self.op.len(); + } + + pub fn write_memory_import(&mut self) { + self.op.push(1); + self.op.push('e' as u8); + self.op.push(1); + self.op.push('m' as u8); + + self.op.push(EXT_MEMORY); + + self.op.push(0); // memory flag, 0 for no maximum memory limit present + write_leb_u32(&mut self.op, 256); // initial memory length of 256 pages, takes 2 bytes in leb128 + + let idx_import_count = self.idx_import_count; + self.op[idx_import_count] += 1; + + let new_table_size = self.import_table_size + 8; + self.set_import_table_size(new_table_size); + } + + pub fn write_import_entry(&mut self, fn_name: PackedStr, type_index: u8) -> u8 { + self.op.push(1); // length of module name + self.op.push('e' as u8); // module name + let fn_name = unpack_str(fn_name); + self.op.push(fn_name.len() as u8); + self.op.extend(fn_name.as_bytes()); + self.op.push(EXT_FUNCTION); + self.op.push(type_index); + + let idx_import_count = self.idx_import_count; + self.op[idx_import_count] += 1; + + let new_table_size = self.import_table_size + 1 + 1 + 1 + fn_name.len() + 1 + 1; + self.set_import_table_size(new_table_size); + + return self.op[idx_import_count] - 1; + } + + pub fn write_function_section(&mut self, count: u8) { + self.op.push(SC_FUNCTION); + self.op.push(1 + count); // length of this section + self.op.push(count); // count of signature indices + for _ in 0..count { + self.op.push(FN0_TYPE_INDEX); + } + } + + pub fn write_export_section(&mut self) { + self.op.push(SC_EXPORT); + self.op.push(1 + 1 + 1 + 1 + 1); // size of this section + self.op.push(1); // count of table: just one function exported + + self.op.push(1); // length of exported function name + self.op.push('f' as u8); // function name + self.op.push(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 + let import_count = self.get_import_count(); + self.op.push(import_count - 1); + } + + pub fn get_fn_index(&mut self, fn_name: PackedStr, type_index: u8) -> u8 { + dbg_log!("getting fn idx for '{}'", unpack_str(fn_name)); + match self.get_import_index(fn_name) { + Some(idx) => { + dbg_log!("found existing entry at idx {}", idx); + idx + }, + None => { + let idx = self.write_import_entry(fn_name, type_index); + dbg_log!("wrote new import entry at idx {}", idx); + idx + }, + } + } + + pub fn get_op_ptr(&self) -> *const u8 { + self.op.as_ptr() + } + + pub fn get_op_len(&self) -> usize { + self.op.len() + } + +} + +#[cfg(test)] +mod tests { + use ::module_init::*; + + #[test] + fn import_table_management() { + let mut w = WasmBuilder::new(); + w.init(); + assert_eq!(0, w.get_fn_index(pack_str("foo"), FN0_TYPE_INDEX)); + assert_eq!(1, w.get_fn_index(pack_str("bar"), FN1_TYPE_INDEX)); + assert_eq!(0, w.get_fn_index(pack_str("foo"), FN0_TYPE_INDEX)); + assert_eq!(2, w.get_fn_index(pack_str("baz"), FN2_TYPE_INDEX)); + } + +} diff --git a/src/wasmgen/src/util.rs b/src/wasmgen/src/util.rs new file mode 100644 index 00000000..75e18c40 --- /dev/null +++ b/src/wasmgen/src/util.rs @@ -0,0 +1,96 @@ +pub use ::dbg::*; + +pub fn write_leb_i32(buf: &mut Vec, mut v: i32) { + // Super complex stuff. See the following: + // https://en.wikipedia.org/wiki/LEB128#Encode_signed_integer + // http://llvm.org/doxygen/LEB128_8h_source.html#l00048 + + let mut more = true; + let negative = v < 0; + let size = 32; + while more { + let mut byte = (v & 0b1111111) as u8; // get last 7 bits + v >>= 7; // shift them away from the value + if negative { + v |= (!0 as i32) << (size - 7); // extend sign + } + let sign_bit = byte & (1 << 6); + if (v == 0 && sign_bit == 0) || (v == -1 && sign_bit != 0) { + more = false; + } + else { + byte |= 0b10000000; // turn on MSB + } + buf.push(byte); + } +} + +pub fn write_leb_u32(buf: &mut Vec, mut v: u32) { + loop { + let mut byte = v as u8 & 0b01111111; // get last 7 bits + v >>= 7; // shift them away from the value + if v != 0 { + byte |= 0b10000000; // turn on MSB + } + buf.push(byte); + if v == 0 { + break; + } + } +} + +#[inline] +pub fn write_fixed_leb16_to_buf(vec: &mut Vec, idx: usize, x: u16) { + dbg_assert!(x < (1 << 14)); // we have 14 bits of available space in 2 bytes for leb + vec[idx] = ((x & 0b1111111) | 0b10000000) as u8; + vec[idx + 1] = (x >> 7) as u8; +} + +#[inline] +pub fn write_fixed_leb32_to_buf(vec: &mut Vec, idx: usize, x: u32) { + dbg_assert!(x < (1 << 28)); // we have 28 bits of available space in 4 bytes for leb + vec[idx ] = (x & 0b1111111) as u8 | 0b10000000; + vec[idx + 1] = (x >> 7 & 0b1111111) as u8 | 0b10000000; + vec[idx + 2] = (x >> 14 & 0b1111111) as u8 | 0b10000000; + vec[idx + 3] = (x >> 21 & 0b1111111) as u8; +} + +pub type PackedStr = (u64, u64); + +#[allow(dead_code)] +pub fn pack_str(s: &str) -> PackedStr { + assert!(s.len() <= 16); + let mut a: [u8; 16] = [0; 16]; + for (i, ch) in s.char_indices() { + a[i] = ch as u8; + } + + unsafe { ::std::mem::transmute(a) } +} + +pub fn unpack_str(s: PackedStr) -> String { + let mut buf = String::with_capacity(16); + let bytes: [u8; 16] = unsafe { ::std::mem::transmute(s) }; + for i in 0..16 { + if bytes[i] == 0 { + break; + } + buf.push(bytes[i] as char); + } + buf +} + +#[cfg(test)] +mod tests { + use ::util::*; + + #[test] + fn packed_strs() { + let pstr = pack_str("foo"); + assert_eq!("foo", unpack_str(pstr)); + + let pstr = pack_str("abcdefghijkl"); + assert_eq!("abcdefghijkl", unpack_str(pstr)); + } + +} \ No newline at end of file diff --git a/src/wasmgen/src/wasm_opcodes.rs b/src/wasmgen/src/wasm_opcodes.rs new file mode 100644 index 00000000..7a10526b --- /dev/null +++ b/src/wasmgen/src/wasm_opcodes.rs @@ -0,0 +1,221 @@ +macro_rules! c { + ($x:ident, $y: expr) => { + #[allow(dead_code)] + pub const $x: u8 = $y; + } +} + +// https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md#high-level-structure +c!(WASM_VERSION, 0x1); + +// Section codes +c!(SC_TYPE, 1); +c!(SC_IMPORT, 2); +c!(SC_FUNCTION, 3); +c!(SC_TABLE, 4); +c!(SC_MEMORY, 5); +c!(SC_GLOBAL, 6); +c!(SC_EXPORT, 7); +c!(SC_START, 8); +c!(SC_ELEMENT, 9); +c!(SC_CODE, 10); +c!(SC_DATA, 11); + +// https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md#language-types +c!(TYPE_I32, 0x7f); +c!(TYPE_I64, 0x7e); +c!(TYPE_F32, 0x7d); +c!(TYPE_F64, 0x7c); +c!(TYPE_ANYFUNC, 0x70); +c!(TYPE_FUNC, 0x60); +c!(TYPE_VOID_BLOCK, 0x40); + +// https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md#external_kind +c!(EXT_FUNCTION, 0); +c!(EXT_TABLE, 1); +c!(EXT_MEMORY, 2); +c!(EXT_GLOBAL, 3); + +// Taken from wasm2ast's source code and modified with vim magic +c!(OP_UNREACHABLE, 0x00); +c!(OP_NOP, 0x01); +c!(OP_BLOCK, 0x02); +c!(OP_LOOP, 0x03); +c!(OP_IF, 0x04); +c!(OP_ELSE, 0x05); +c!(OP_TRY, 0x06); +c!(OP_CATCH, 0x07); +c!(OP_THROW, 0x08); +c!(OP_RETHROW, 0x09); +c!(OP_CATCHALL, 0x0a); +c!(OP_END, 0x0b); +c!(OP_BR, 0x0c); +c!(OP_BRIF, 0x0d); +c!(OP_BRTABLE, 0x0e); +c!(OP_RETURN, 0x0f); +c!(OP_CALL, 0x10); +c!(OP_CALLINDIRECT, 0x11); +c!(OP_DROP, 0x1a); +c!(OP_SELECT, 0x1b); +c!(OP_GETLOCAL, 0x20); +c!(OP_SETLOCAL, 0x21); +c!(OP_TEELOCAL, 0x22); +c!(OP_GETGLOBAL, 0x23); +c!(OP_SETGLOBAL, 0x24); +c!(OP_I32LOAD, 0x28); +c!(OP_I64LOAD, 0x29); +c!(OP_F32LOAD, 0x2a); +c!(OP_F64LOAD, 0x2b); +c!(OP_I32LOAD8S, 0x2c); +c!(OP_I32LOAD8U, 0x2d); +c!(OP_I32LOAD16S, 0x2e); +c!(OP_I32LOAD16U, 0x2f); +c!(OP_I64LOAD8S, 0x30); +c!(OP_I64LOAD8U, 0x31); +c!(OP_I64LOAD16S, 0x32); +c!(OP_I64LOAD16U, 0x33); +c!(OP_I64LOAD32S, 0x34); +c!(OP_I64LOAD32U, 0x35); +c!(OP_I32STORE, 0x36); +c!(OP_I64STORE, 0x37); +c!(OP_F32STORE, 0x38); +c!(OP_F64STORE, 0x39); +c!(OP_I32STORE8, 0x3a); +c!(OP_I32STORE16, 0x3b); +c!(OP_I64STORE8, 0x3c); +c!(OP_I64STORE16, 0x3d); +c!(OP_I64STORE32, 0x3e); +c!(OP_CURRENTMEMORY, 0x3f); +c!(OP_GROWMEMORY, 0x40); +c!(OP_I32CONST, 0x41); +c!(OP_I64CONST, 0x42); +c!(OP_F32CONST, 0x43); +c!(OP_F64CONST, 0x44); +c!(OP_I32EQZ, 0x45); +c!(OP_I32EQ, 0x46); +c!(OP_I32NE, 0x47); +c!(OP_I32LTS, 0x48); +c!(OP_I32LTU, 0x49); +c!(OP_I32GTS, 0x4a); +c!(OP_I32GTU, 0x4b); +c!(OP_I32LES, 0x4c); +c!(OP_I32LEU, 0x4d); +c!(OP_I32GES, 0x4e); +c!(OP_I32GEU, 0x4f); +c!(OP_I64EQZ, 0x50); +c!(OP_I64EQ, 0x51); +c!(OP_I64NE, 0x52); +c!(OP_I64LTS, 0x53); +c!(OP_I64LTU, 0x54); +c!(OP_I64GTS, 0x55); +c!(OP_I64GTU, 0x56); +c!(OP_I64LES, 0x57); +c!(OP_I64LEU, 0x58); +c!(OP_I64GES, 0x59); +c!(OP_I64GEU, 0x5a); +c!(OP_F32EQ, 0x5b); +c!(OP_F32NE, 0x5c); +c!(OP_F32LT, 0x5d); +c!(OP_F32GT, 0x5e); +c!(OP_F32LE, 0x5f); +c!(OP_F32GE, 0x60); +c!(OP_F64EQ, 0x61); +c!(OP_F64NE, 0x62); +c!(OP_F64LT, 0x63); +c!(OP_F64GT, 0x64); +c!(OP_F64LE, 0x65); +c!(OP_F64GE, 0x66); +c!(OP_I32CLZ, 0x67); +c!(OP_I32CTZ, 0x68); +c!(OP_I32POPCNT, 0x69); +c!(OP_I32ADD, 0x6a); +c!(OP_I32SUB, 0x6b); +c!(OP_I32MUL, 0x6c); +c!(OP_I32DIVS, 0x6d); +c!(OP_I32DIVU, 0x6e); +c!(OP_I32REMS, 0x6f); +c!(OP_I32REMU, 0x70); +c!(OP_I32AND, 0x71); +c!(OP_I32OR, 0x72); +c!(OP_I32XOR, 0x73); +c!(OP_I32SHL, 0x74); +c!(OP_I32SHRS, 0x75); +c!(OP_I32SHRU, 0x76); +c!(OP_I32ROTL, 0x77); +c!(OP_I32ROTR, 0x78); +c!(OP_I64CLZ, 0x79); +c!(OP_I64CTZ, 0x7a); +c!(OP_I64POPCNT, 0x7b); +c!(OP_I64ADD, 0x7c); +c!(OP_I64SUB, 0x7d); +c!(OP_I64MUL, 0x7e); +c!(OP_I64DIVS, 0x7f); +c!(OP_I64DIVU, 0x80); +c!(OP_I64REMS, 0x81); +c!(OP_I64REMU, 0x82); +c!(OP_I64AND, 0x83); +c!(OP_I64OR, 0x84); +c!(OP_I64XOR, 0x85); +c!(OP_I64SHL, 0x86); +c!(OP_I64SHRS, 0x87); +c!(OP_I64SHRU, 0x88); +c!(OP_I64ROTL, 0x89); +c!(OP_I64ROTR, 0x8a); +c!(OP_F32ABS, 0x8b); +c!(OP_F32NEG, 0x8c); +c!(OP_F32CEIL, 0x8d); +c!(OP_F32FLOOR, 0x8e); +c!(OP_F32TRUNC, 0x8f); +c!(OP_F32NEAREST, 0x90); +c!(OP_F32SQRT, 0x91); +c!(OP_F32ADD, 0x92); +c!(OP_F32SUB, 0x93); +c!(OP_F32MUL, 0x94); +c!(OP_F32DIV, 0x95); +c!(OP_F32MIN, 0x96); +c!(OP_F32MAX, 0x97); +c!(OP_F32COPYSIGN, 0x98); +c!(OP_F64ABS, 0x99); +c!(OP_F64NEG, 0x9a); +c!(OP_F64CEIL, 0x9b); +c!(OP_F64FLOOR, 0x9c); +c!(OP_F64TRUNC, 0x9d); +c!(OP_F64NEAREST, 0x9e); +c!(OP_F64SQRT, 0x9f); +c!(OP_F64ADD, 0xa0); +c!(OP_F64SUB, 0xa1); +c!(OP_F64MUL, 0xa2); +c!(OP_F64DIV, 0xa3); +c!(OP_F64MIN, 0xa4); +c!(OP_F64MAX, 0xa5); +c!(OP_F64COPYSIGN, 0xa6); +c!(OP_I32WRAPI64, 0xa7); +c!(OP_I32TRUNCSF32, 0xa8); +c!(OP_I32TRUNCUF32, 0xa9); +c!(OP_I32TRUNCSF64, 0xaa); +c!(OP_I32TRUNCUF64, 0xab); +c!(OP_I64EXTENDSI32, 0xac); +c!(OP_I64EXTENDUI32, 0xad); +c!(OP_I64TRUNCSF32, 0xae); +c!(OP_I64TRUNCUF32, 0xaf); +c!(OP_I64TRUNCSF64, 0xb0); +c!(OP_I64TRUNCUF64, 0xb1); +c!(OP_F32CONVERTSI32, 0xb2); +c!(OP_F32CONVERTUI32, 0xb3); +c!(OP_F32CONVERTSI64, 0xb4); +c!(OP_F32CONVERTUI64, 0xb5); +c!(OP_F32DEMOTEF64, 0xb6); +c!(OP_F64CONVERTSI32, 0xb7); +c!(OP_F64CONVERTUI32, 0xb8); +c!(OP_F64CONVERTSI64, 0xb9); +c!(OP_F64CONVERTUI64, 0xba); +c!(OP_F64PROMOTEF32, 0xbb); +c!(OP_I32REINTERPRETF32, 0xbc); +c!(OP_I64REINTERPRETF64, 0xbd); +c!(OP_F32REINTERPRETI32, 0xbe); +c!(OP_F64REINTERPRETI64, 0xbf); + +c!(MEM_NO_ALIGN, 0); +c!(MEM_ALIGN16, 1); +c!(MEM_ALIGN32, 2); +c!(MEM_IMM_OFFSET, 0); \ No newline at end of file diff --git a/src/wasmgen/src/wasm_util.rs b/src/wasmgen/src/wasm_util.rs new file mode 100644 index 00000000..cdbff4e8 --- /dev/null +++ b/src/wasmgen/src/wasm_util.rs @@ -0,0 +1,84 @@ +use ::wasm_opcodes::*; +use ::util::*; + +#[no_mangle] +pub fn push_i32(buf: &mut Vec, v: i32) { + buf.push(OP_I32CONST); + write_leb_i32(buf, v); +} + +#[no_mangle] +pub fn push_u32(buf: &mut Vec, v: u32) { + buf.push(OP_I32CONST); + write_leb_u32(buf, v); +} + +#[no_mangle] +pub fn load_aligned_u16(buf: &mut Vec, addr: u32) { + // doesn't cause a failure in the generated code, but it will be much slower + dbg_assert!((addr & 1) == 0); + + buf.push(OP_I32CONST); + write_leb_u32(buf, addr); + buf.push(OP_I32LOAD16U); + buf.push(MEM_ALIGN16); + buf.push(MEM_IMM_OFFSET); +} + +#[no_mangle] +pub fn load_aligned_i32(buf: &mut Vec, addr: u32) { + // doesn't cause a failure in the generated code, but it will be much slower + dbg_assert!((addr & 3) == 0); + + buf.push(OP_I32CONST); + write_leb_u32(buf, addr); + buf.push(OP_I32LOAD); + buf.push(MEM_ALIGN32); + buf.push(MEM_IMM_OFFSET); +} + +#[no_mangle] +pub fn store_aligned_u16(buf: &mut Vec) { + buf.push(OP_I32STORE16); + buf.push(MEM_ALIGN16); + buf.push(MEM_IMM_OFFSET); +} + +#[no_mangle] +pub fn store_aligned_i32(buf: &mut Vec) { + buf.push(OP_I32STORE); + buf.push(MEM_ALIGN32); + buf.push(MEM_IMM_OFFSET); +} + +#[no_mangle] +pub fn add_i32(buf: &mut Vec) { + buf.push(OP_I32ADD); +} + +#[no_mangle] +pub fn and_i32(buf: &mut Vec) { + buf.push(OP_I32AND); +} + +#[no_mangle] +pub fn or_i32(buf: &mut Vec) { + buf.push(OP_I32OR); +} + +#[no_mangle] +pub fn shl_i32(buf: &mut Vec) { + buf.push(OP_I32SHL); +} + +#[no_mangle] +pub fn call_fn(buf: &mut Vec, fn_idx: u8) { + buf.push(OP_CALL); + buf.push(fn_idx); +} + +#[no_mangle] +pub fn call_fn_with_arg(buf: &mut Vec, fn_idx: u8, arg0: i32) { + push_i32(buf, arg0); + call_fn(buf, fn_idx); +} From 6cb022e403a4ce5576150b294f36b1b9bd2d3cea Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Wed, 20 Jun 2018 02:33:14 +0530 Subject: [PATCH 0958/2137] add new wasm_util functions --- src/wasmgen/src/wasm_util.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/wasmgen/src/wasm_util.rs b/src/wasmgen/src/wasm_util.rs index cdbff4e8..8931990e 100644 --- a/src/wasmgen/src/wasm_util.rs +++ b/src/wasmgen/src/wasm_util.rs @@ -82,3 +82,33 @@ pub fn call_fn_with_arg(buf: &mut Vec, fn_idx: u8, arg0: i32) { push_i32(buf, arg0); call_fn(buf, fn_idx); } + +#[no_mangle] +pub fn eq_i32(buf: &mut Vec) { + buf.push(OP_I32EQ); +} + +#[no_mangle] +pub fn ne_i32(buf: &mut Vec) { + buf.push(OP_I32NE); +} + +#[no_mangle] +pub fn le_i32(buf: &mut Vec) { + buf.push(OP_I32LES); +} + +#[no_mangle] +pub fn lt_i32(buf: &mut Vec) { + buf.push(OP_I32LTS); +} + +#[no_mangle] +pub fn ge_i32(buf: &mut Vec) { + buf.push(OP_I32GES); +} + +#[no_mangle] +pub fn gt_i32(buf: &mut Vec) { + buf.push(OP_I32GTS); +} From d094bdf6ee5f381105d4bb755b150cf22fa50d7f Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Wed, 20 Jun 2018 21:47:42 +0530 Subject: [PATCH 0959/2137] add more wasm_util functions, use 2 bytes for storing import count --- src/wasmgen/src/c_api.rs | 2 +- src/wasmgen/src/module_init.rs | 54 ++++++++++++------------ src/wasmgen/src/util.rs | 8 ++-- src/wasmgen/src/wasm_util.rs | 77 +++++++++++++++++++++++++++++----- 4 files changed, 98 insertions(+), 43 deletions(-) diff --git a/src/wasmgen/src/c_api.rs b/src/wasmgen/src/c_api.rs index 4a1bad22..0f2d87a5 100644 --- a/src/wasmgen/src/c_api.rs +++ b/src/wasmgen/src/c_api.rs @@ -21,7 +21,7 @@ pub fn finish(no_of_locals_i32: u8) { } #[no_mangle] -pub fn get_fn_idx(fn_name: PackedStr, type_idx: u8) -> u8 { +pub fn get_fn_idx(fn_name: PackedStr, type_idx: u8) -> u16 { let m = get_module(); m.get_fn_index(fn_name, type_idx) } diff --git a/src/wasmgen/src/module_init.rs b/src/wasmgen/src/module_init.rs index d384a831..5eca7572 100644 --- a/src/wasmgen/src/module_init.rs +++ b/src/wasmgen/src/module_init.rs @@ -43,6 +43,7 @@ pub struct WasmBuilder { idx_import_entries: usize, // for searching the imports import_table_size: usize, // the current import table size (to avoid reading 2 byte leb) + import_count: u16, // same as above initial_static_size: usize, // size of module after initialization, rest is drained on reset } @@ -57,7 +58,8 @@ impl WasmBuilder { idx_import_count: 0, idx_import_entries: 0, - import_table_size: 1, + import_table_size: 2, + import_count: 0, initial_static_size: 0, } @@ -78,7 +80,7 @@ impl WasmBuilder { pub fn reset(&mut self) { self.op.drain(self.initial_static_size..); - self.set_import_table_size(1); + self.set_import_table_size(2); self.set_import_count(0); self.buffers.drain(..); } @@ -118,10 +120,10 @@ impl WasmBuilder { // write the actual sizes to the pointer locations stored above. We subtract 4 from the actual // value because the ptr itself points to four bytes let fn_body_size = (self.op.len() - idx_fn_body_size - 4) as u32; - write_fixed_leb32_to_buf(&mut self.op, idx_fn_body_size, fn_body_size); + write_fixed_leb32_at_idx(&mut self.op, idx_fn_body_size, fn_body_size); let code_section_size = (self.op.len() - idx_code_section_size - 4) as u32; - write_fixed_leb32_to_buf(&mut self.op, idx_code_section_size, code_section_size); + write_fixed_leb32_at_idx(&mut self.op, idx_code_section_size, code_section_size); self.op.len() } @@ -187,10 +189,10 @@ impl WasmBuilder { } /// Goes over the import block to find index of an import entry by function name - pub fn get_import_index(&self, fn_name: PackedStr) -> Option { + pub fn get_import_index(&self, fn_name: PackedStr) -> Option { let fn_name = unpack_str(fn_name); let mut offset = self.idx_import_entries; - for i in 0..self.get_import_count() { + for i in 0..self.import_count { offset += 1; // skip length of module name offset += 1; // skip module name itself let len = self.op[offset]; @@ -206,29 +208,28 @@ impl WasmBuilder { None } - pub fn get_import_count(&self) -> u8 { - dbg_assert!(self.idx_import_count < self.op.len()); - self.op[self.idx_import_count] - } - - pub fn set_import_count(&mut self, count: u8) { - self.op[self.idx_import_count] = count; + pub fn set_import_count(&mut self, count: u16) { + dbg_assert!(count < 0x4000); + self.import_count = count; + let idx_import_count = self.idx_import_count; + write_fixed_leb16_at_idx(&mut self.op, idx_import_count, count as u16); } pub fn set_import_table_size(&mut self, size: usize) { + dbg_assert!(size < 0x4000); self.import_table_size = size; let idx_import_table_size = self.idx_import_table_size; - write_fixed_leb16_to_buf(&mut self.op, idx_import_table_size, size as u16); + write_fixed_leb16_at_idx(&mut self.op, idx_import_table_size, size as u16); } pub fn write_import_section_preamble(&mut self) { self.op.push(SC_IMPORT); self.idx_import_table_size = self.op.len(); - self.op.push(1 | 0b10000000); self.op.push(0); // 1 in 2 byte leb + self.op.push(1 | 0b10000000); self.op.push(2); // 2 in 2 byte leb self.idx_import_count = self.op.len(); - self.op.push(0); + self.op.push(1 | 0b10000000); self.op.push(0); // 0 in 2 byte leb // here after starts the actual list of imports self.idx_import_entries = self.op.len(); @@ -245,14 +246,14 @@ impl WasmBuilder { self.op.push(0); // memory flag, 0 for no maximum memory limit present write_leb_u32(&mut self.op, 256); // initial memory length of 256 pages, takes 2 bytes in leb128 - let idx_import_count = self.idx_import_count; - self.op[idx_import_count] += 1; + let new_import_count = self.import_count + 1; + self.set_import_count(new_import_count); let new_table_size = self.import_table_size + 8; self.set_import_table_size(new_table_size); } - pub fn write_import_entry(&mut self, fn_name: PackedStr, type_index: u8) -> u8 { + pub fn write_import_entry(&mut self, fn_name: PackedStr, type_index: u8) -> u16 { self.op.push(1); // length of module name self.op.push('e' as u8); // module name let fn_name = unpack_str(fn_name); @@ -261,13 +262,13 @@ impl WasmBuilder { self.op.push(EXT_FUNCTION); self.op.push(type_index); - let idx_import_count = self.idx_import_count; - self.op[idx_import_count] += 1; + let new_import_count = self.import_count + 1; + self.set_import_count(new_import_count); let new_table_size = self.import_table_size + 1 + 1 + 1 + fn_name.len() + 1 + 1; self.set_import_table_size(new_table_size); - return self.op[idx_import_count] - 1; + self.import_count - 1 } pub fn write_function_section(&mut self, count: u8) { @@ -281,7 +282,7 @@ impl WasmBuilder { pub fn write_export_section(&mut self) { self.op.push(SC_EXPORT); - self.op.push(1 + 1 + 1 + 1 + 1); // size of this section + self.op.push(1 + 1 + 1 + 1 + 2); // size of this section self.op.push(1); // count of table: just one function exported self.op.push(1); // length of exported function name @@ -291,11 +292,12 @@ impl WasmBuilder { // 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 - let import_count = self.get_import_count(); - self.op.push(import_count - 1); + let next_op_idx = self.op.len(); + self.op.push(0); self.op.push(0); // add 2 bytes for writing 16 byte val + write_fixed_leb16_at_idx(&mut self.op, next_op_idx, self.import_count - 1); } - pub fn get_fn_index(&mut self, fn_name: PackedStr, type_index: u8) -> u8 { + pub fn get_fn_index(&mut self, fn_name: PackedStr, type_index: u8) -> u16 { dbg_log!("getting fn idx for '{}'", unpack_str(fn_name)); match self.get_import_index(fn_name) { Some(idx) => { diff --git a/src/wasmgen/src/util.rs b/src/wasmgen/src/util.rs index 75e18c40..0b259373 100644 --- a/src/wasmgen/src/util.rs +++ b/src/wasmgen/src/util.rs @@ -39,15 +39,13 @@ pub fn write_leb_u32(buf: &mut Vec, mut v: u32) { } } -#[inline] -pub fn write_fixed_leb16_to_buf(vec: &mut Vec, idx: usize, x: u16) { +pub fn write_fixed_leb16_at_idx(vec: &mut Vec, idx: usize, x: u16) { dbg_assert!(x < (1 << 14)); // we have 14 bits of available space in 2 bytes for leb - vec[idx] = ((x & 0b1111111) | 0b10000000) as u8; + vec[idx ] = ((x & 0b1111111) | 0b10000000) as u8; vec[idx + 1] = (x >> 7) as u8; } -#[inline] -pub fn write_fixed_leb32_to_buf(vec: &mut Vec, idx: usize, x: u32) { +pub fn write_fixed_leb32_at_idx(vec: &mut Vec, idx: usize, x: u32) { dbg_assert!(x < (1 << 28)); // we have 28 bits of available space in 4 bytes for leb vec[idx ] = (x & 0b1111111) as u8 | 0b10000000; vec[idx + 1] = (x >> 7 & 0b1111111) as u8 | 0b10000000; diff --git a/src/wasmgen/src/wasm_util.rs b/src/wasmgen/src/wasm_util.rs index 8931990e..297ba6a6 100644 --- a/src/wasmgen/src/wasm_util.rs +++ b/src/wasmgen/src/wasm_util.rs @@ -22,7 +22,7 @@ pub fn load_aligned_u16(buf: &mut Vec, addr: u32) { write_leb_u32(buf, addr); buf.push(OP_I32LOAD16U); buf.push(MEM_ALIGN16); - buf.push(MEM_IMM_OFFSET); + buf.push(0); // immediate offset } #[no_mangle] @@ -30,25 +30,22 @@ pub fn load_aligned_i32(buf: &mut Vec, addr: u32) { // doesn't cause a failure in the generated code, but it will be much slower dbg_assert!((addr & 3) == 0); - buf.push(OP_I32CONST); - write_leb_u32(buf, addr); - buf.push(OP_I32LOAD); - buf.push(MEM_ALIGN32); - buf.push(MEM_IMM_OFFSET); + push_i32(buf, addr as i32); + load_aligned_i32_from_stack(buf, 0); } #[no_mangle] pub fn store_aligned_u16(buf: &mut Vec) { buf.push(OP_I32STORE16); buf.push(MEM_ALIGN16); - buf.push(MEM_IMM_OFFSET); + buf.push(0); // immediate offset } #[no_mangle] pub fn store_aligned_i32(buf: &mut Vec) { buf.push(OP_I32STORE); buf.push(MEM_ALIGN32); - buf.push(MEM_IMM_OFFSET); + buf.push(0); // immediate offset } #[no_mangle] @@ -72,13 +69,15 @@ pub fn shl_i32(buf: &mut Vec) { } #[no_mangle] -pub fn call_fn(buf: &mut Vec, fn_idx: u8) { +pub fn call_fn(buf: &mut Vec, fn_idx: u16) { buf.push(OP_CALL); - buf.push(fn_idx); + let buf_len = buf.len(); + buf.push(0); buf.push(0); + write_fixed_leb16_at_idx(buf, buf_len, fn_idx); } #[no_mangle] -pub fn call_fn_with_arg(buf: &mut Vec, fn_idx: u8, arg0: i32) { +pub fn call_fn_with_arg(buf: &mut Vec, fn_idx: u16, arg0: i32) { push_i32(buf, arg0); call_fn(buf, fn_idx); } @@ -112,3 +111,59 @@ pub fn ge_i32(buf: &mut Vec) { pub fn gt_i32(buf: &mut Vec) { buf.push(OP_I32GTS); } + +#[no_mangle] +pub fn if_i32(buf: &mut Vec) { + buf.push(OP_IF); + buf.push(TYPE_I32); +} + +#[no_mangle] +pub fn block_i32(buf: &mut Vec) { + buf.push(OP_BLOCK); + buf.push(TYPE_I32); +} + +#[no_mangle] +pub fn tee_local(buf: &mut Vec, idx: i32) { + buf.push(OP_TEELOCAL); + write_leb_i32(buf, idx); +} + +#[no_mangle] +pub fn xor_i32(buf: &mut Vec) { + buf.push(OP_I32XOR); +} + +#[no_mangle] +pub fn load_unaligned_i32_from_stack(buf: &mut Vec, byte_offset: u32) { + buf.push(OP_I32LOAD); + buf.push(MEM_NO_ALIGN); + write_leb_u32(buf, byte_offset); +} + +#[no_mangle] +pub fn load_aligned_i32_from_stack(buf: &mut Vec, byte_offset: u32) { + buf.push(OP_I32LOAD); + buf.push(MEM_ALIGN32); + write_leb_u32(buf, byte_offset); +} + +// XXX: Function naming should be consistent regarding both alignment and accepting an +// offset. Leaving as-is for the Rust port to cleanup +#[no_mangle] +pub fn store_unaligned_i32(buf: &mut Vec, byte_offset: u32) { + buf.push(OP_I32STORE); + buf.push(MEM_NO_ALIGN); + write_leb_u32(buf, byte_offset); +} + +#[no_mangle] +pub fn shr_u32(buf: &mut Vec) { + buf.push(OP_I32SHRU); +} + +#[no_mangle] +pub fn shr_i32(buf: &mut Vec) { + buf.push(OP_I32SHRS); +} From 6251730fee3099d141dd42ab4b1e4da57db44d9f Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Thu, 21 Jun 2018 05:02:03 +0530 Subject: [PATCH 0960/2137] added wasmgen init changes --- loader.js | 2 +- src/browser/lib.js | 26 ++++++++++++ src/browser/starter.js | 96 +++++++++++++++++++++++++++++++++++++++++- src/codegen.js | 94 ----------------------------------------- src/cpu.js | 15 +++++-- 5 files changed, 134 insertions(+), 99 deletions(-) delete mode 100644 src/codegen.js diff --git a/loader.js b/loader.js index 740ca02b..d23465b6 100644 --- a/loader.js +++ b/loader.js @@ -5,7 +5,7 @@ "use strict"; var CORE_FILES = - "const.js config.js log.js lib.js coverage.js cpu.js debug.js codegen.js " + + "const.js config.js log.js lib.js coverage.js cpu.js debug.js " + "io.js main.js ide.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 44137627..c960c581 100644 --- a/src/browser/lib.js +++ b/src/browser/lib.js @@ -66,6 +66,32 @@ var ASYNC_SAFE = false; }; }; + // Reads len characters at offset from Memory object mem as a JS string + v86util.read_sized_string_from_mem = function read_sized_string_from_mem(mem, offset, len) + { + return String.fromCharCode(...new Uint8Array(mem.buffer, offset, len)); + }; + + //XXX: figure out a better way to handle dylink issue than duplicating above function + v86util.minimal_load_wasm = function minimal_load_wasm(filename, imports, cb) + { + function load_cb(bytes) + { + WebAssembly + .instantiate(bytes, imports) + .then(function({ instance }) { + cb({ + memory: imports["env"]["memory"], + exports: instance["exports"], + instance, + imports, + filename, + }); + }); + } + v86util.load_file(filename, { done: load_cb }); + }; + /** * Fetches, compiles, and instantiates a wasm file * @param {string} filename diff --git a/src/browser/starter.js b/src/browser/starter.js index d3cc31da..ecaf9731 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -259,18 +259,111 @@ function V86Starter(options) "Infinity": Infinity, "NaN": NaN, }; + + const wasmgen_mem = new WebAssembly.Memory({ initial: 10000 }); + const wasmgen_externs = { + "memory": wasmgen_mem, + "log_from_wasm": function(offset, len) { + const str = v86util.read_sized_string_from_mem(wasmgen_mem, offset, len); + dbg_log(str, LOG_CPU); + }, + "abort": function() { + dbg_assert(false); + }, + }; let wasm_file = DEBUG ? "v86-debug.wasm" : "v86.wasm"; + let wasmgen_bin = DEBUG ? "wasmgen-debug.wasm" : "wasmgen.wasm"; if(typeof window === "undefined" && typeof __dirname === "string") { wasm_file = __dirname + "/" + wasm_file; + wasmgen_bin = __dirname + "/" + wasmgen_bin; } else { wasm_file = "build/" + wasm_file; + wasmgen_bin = "build/" + wasmgen_bin; } + const wasmgen_exports = [ + // these are used by C as is + "gen_eqz_i32", + "gen_if_void", + "gen_else", + "gen_loop_void", + "gen_block_void", + "gen_block_end", + "gen_return", + "gen_brtable_and_cases", + "gen_br", + "gen_get_local", + "gen_set_local", + "gen_const_i32", + "gen_unreachable", + "gen_drop", + "gen_increment_mem32", + "gen_increment_variable", + + // these are wrapped around without the rs_ prefix by C + "rs_gen_fn0_const", + "rs_gen_fn0_const_ret", + "rs_gen_fn1_const", + "rs_gen_fn1_const_ret", + "rs_gen_fn2_const", + "rs_gen_fn3_const", + "rs_gen_call_fn1_ret", + "rs_gen_call_fn2", + "rs_get_fn_idx", + + // these are exported to C with the gen_ prefix attached via JS + "new_buf", + "reset", + "finish", + "get_op_ptr", + "get_op_len", + "include_buffer", + "push_i32", + "push_u32", + "load_aligned_u16", + "load_aligned_i32", + "store_aligned_u16", + "store_aligned_i32", + "add_i32", + "and_i32", + "or_i32", + "shl_i32", + "call_fn", + "call_fn_with_arg", + ]; + + function reexport_wasmgen_functions(wasmgen) { + for(const fn_name of wasmgen_exports) + { + if(fn_name.startsWith("gen_")) + { + // used as is via C + wasm_shared_funcs[`_${fn_name}`] = wasmgen.exports[fn_name]; + } + else if(fn_name.startsWith("rs_")) + { + // wrapped around by C + wasm_shared_funcs[`_${fn_name}`] = wasmgen.exports[fn_name.replace("rs_", "")]; + } + else + { + // prefix "gen_" attached by JS + wasm_shared_funcs[`_gen_${fn_name}`] = wasmgen.exports[fn_name]; + } + } + } + + v86util.minimal_load_wasm(wasmgen_bin, { "env": wasmgen_externs }, (wasmgen) => { + reexport_wasmgen_functions(wasmgen); + wasmgen.exports["setup"](); + + //XXX: fix indentation break + v86util.load_wasm( wasm_file, { "env": wasm_shared_funcs, "global" : wasm_globals }, @@ -281,7 +374,7 @@ function V86Starter(options) mem8 = new Uint8Array(mem); wm.instance.exports["__post_instantiate"](); coverage_logger.init(wm); - emulator = this.v86 = new v86(this.emulator_bus, wm, new Codegen(wm), coverage_logger); + emulator = this.v86 = new v86(this.emulator_bus, wm, wasmgen, coverage_logger); cpu = emulator.cpu; // XXX: Leaving unindented to minimize diff; still a part of the cb to load_wasm! @@ -629,6 +722,7 @@ function V86Starter(options) } }); + }); } /** diff --git a/src/codegen.js b/src/codegen.js deleted file mode 100644 index 3dd8797e..00000000 --- a/src/codegen.js +++ /dev/null @@ -1,94 +0,0 @@ -"use strict"; - -if(typeof module !== "undefined") -{ - module.exports = Codegen; -} - -/** @constructor */ -function Codegen(wm) -{ - this.wm = wm; - this.wm.exports["_gen_init"](); -} - -Codegen.prototype.reset = function() -{ - this.wm.exports["_gen_reset"](); -}; - -Codegen.OUTPUT_OFFSET = 0x1000; -Codegen.STR_INPUT_OFFSET = 0x301000; - -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.memory.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.exports["_gen_fn0_const"](Codegen.STR_INPUT_OFFSET, fn.length); -}; - -Codegen.prototype.fn1 = function(fn, arg0) -{ - this.str_input(fn); - this.wm.exports["_gen_fn1_const"](Codegen.STR_INPUT_OFFSET, fn.length, arg0); -}; - -Codegen.prototype.fn2 = function(fn, arg0, arg1) -{ - this.str_input(fn); - this.wm.exports["_gen_fn2_const"](Codegen.STR_INPUT_OFFSET, fn.length, arg0, arg1); -}; - -Codegen.prototype.modrm_fn1 = function(fn, modrm_byte, arg) -{ - this.str_input(fn); - this.wm.exports["_gen_modrm_resolve"](modrm_byte); - this.wm.exports["_gen_modrm_fn1"](Codegen.STR_INPUT_OFFSET, fn.length, arg); -}; - -Codegen.prototype.modrm_fn0 = function(fn, modrm_byte) -{ - this.str_input(fn); - this.wm.exports["_gen_modrm_resolve"](modrm_byte); - this.wm.exports["_gen_modrm_fn1"](Codegen.STR_INPUT_OFFSET, fn.length); -}; - -Codegen.prototype.increment_instruction_pointer = function(n) -{ - this.wm.exports["_gen_increment_instruction_pointer"](n); -}; - -Codegen.prototype.set_previous_eip = function() -{ - this.wm.exports["_gen_set_previous_eip"](); -}; - -Codegen.prototype.finish = function() -{ - return this.wm.exports["_gen_finish"](); -}; - -Codegen.prototype.commit_instruction_body_to_cs = function() -{ - return this.wm.exports["_gen_commit_instruction_body_to_cs"](); -}; - -Codegen.prototype.get_module_code = function() -{ - const end = this.wm.exports["_gen_get_final_offset"]() - Codegen.OUTPUT_OFFSET; - - // extract wasm module - const output_buffer_view = new Uint8Array(this.wm.memory.buffer, Codegen.OUTPUT_OFFSET, end); - return output_buffer_view; -}; diff --git a/src/cpu.js b/src/cpu.js index 3c071e4f..606c7105 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -11,10 +11,10 @@ var CPU_LOG_VERBOSE = false; /** @constructor */ -function CPU(bus, wm, codegen, coverage_logger) +function CPU(bus, wm, wasmgen, coverage_logger) { this.wm = wm; - this.codegen = codegen; + this.wasmgen = wasmgen; this.coverage_logger = coverage_logger; this.wasm_patch(wm); this.create_jit_imports(); @@ -215,6 +215,15 @@ function CPU(bus, wm, codegen, coverage_logger) //Object.seal(this); } +CPU.prototype.wasmgen_get_module_code = function() +{ + const ptr = this.wasmgen.exports["get_op_ptr"](); + const len = this.wasmgen.exports["get_op_len"](); + + const output_buffer_view = new Uint8Array(this.wasmgen.memory.buffer, ptr, len); + return output_buffer_view; +}; + CPU.prototype.create_jit_imports = function() { // Set this.jit_imports as generated WASM modules will expect @@ -1237,7 +1246,7 @@ CPU.prototype.codegen_finalize = function(wasm_table_index, start, end, first_op { dbg_assert(wasm_table_index >= 0 && wasm_table_index < WASM_TABLE_SIZE); //dbg_log("finalize"); - const code = this.codegen.get_module_code(); + const code = this.wasmgen_get_module_code(); if(DEBUG) { From 03f0da9525dd6ca3241c7eb9d2650c9128c4d54a Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Fri, 22 Jun 2018 18:30:25 +0530 Subject: [PATCH 0961/2137] use wg_ prefix for wasmgen, add tests to makefile --- .travis-run-codegen.sh | 2 +- Makefile | 14 + src/browser/starter.js | 110 ++--- src/native/codegen/codegen.c | 639 ++++++++++-------------------- src/native/codegen/codegen.h | 51 +-- src/native/codegen/cstring.h | 16 - src/native/codegen/module_init.h | 218 ---------- src/native/codegen/util.h | 100 ----- src/native/codegen/wasm_opcodes.h | 213 ---------- src/native/codegen/wasm_util.h | 135 ------- src/native/codegen/wasmgen.h | 72 ++++ src/native/cpu.c | 73 ++-- src/native/instructions.c | 22 +- src/native/profiler/opstats.c | 1 + src/wasmgen/src/c_api.rs | 10 +- src/wasmgen/src/codegen.rs | 152 ++----- src/wasmgen/src/wasm_opcodes.rs | 1 - src/wasmgen/src/wasm_util.rs | 163 ++++++-- 18 files changed, 579 insertions(+), 1413 deletions(-) delete mode 100644 src/native/codegen/cstring.h delete mode 100644 src/native/codegen/module_init.h delete mode 100644 src/native/codegen/util.h delete mode 100644 src/native/codegen/wasm_opcodes.h delete mode 100644 src/native/codegen/wasm_util.h create mode 100644 src/native/codegen/wasmgen.h diff --git a/.travis-run-codegen.sh b/.travis-run-codegen.sh index ffdffef2..6a17bdbe 100755 --- a/.travis-run-codegen.sh +++ b/.travis-run-codegen.sh @@ -1,3 +1,3 @@ #!/usr/bin/env bash set -e -make codegen-test +make wasmgen-test diff --git a/Makefile b/Makefile index b7b6d7a5..120247e4 100644 --- a/Makefile +++ b/Makefile @@ -223,6 +223,20 @@ build/v86-debug.wasm: src/native/*.c src/native/*.h src/native/codegen/*.c src/n -o build/v86-debug.wasm ls -lh build/v86-debug.wasm +build/wasmgen.wasm: src/wasmgen/src/*.rs src/wasmgen/Cargo.toml + mkdir -p build/ + -ls -lh build/wasmgen.wasm + (cd src/wasmgen && cargo +nightly rustc --release --target wasm32-unknown-unknown -- -Clink-args="--import-memory") + mv src/wasmgen/target/wasm32-unknown-unknown/release/wasmgen.wasm build/wasmgen.wasm + ls -lh build/wasmgen.wasm + +build/wasmgen-debug.wasm: src/wasmgen/src/*.rs src/wasmgen/Cargo.toml + mkdir -p build/ + -ls -lh build/wasmgen-debug.wasm + (cd src/wasmgen && cargo +nightly rustc --target wasm32-unknown-unknown -- -Clink-args="--import-memory") + mv src/wasmgen/target/wasm32-unknown-unknown/debug/wasmgen.wasm build/wasmgen-debug.wasm + ls -lh build/wasmgen-debug.wasm + build/codegen-test.wasm: src/native/*.c src/native/*.h src/native/codegen/*.c src/native/codegen/*.h mkdir -p build -ls -lh build/codegen-test.wasm diff --git a/src/browser/starter.js b/src/browser/starter.js index ecaf9731..229322fe 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -287,73 +287,77 @@ function V86Starter(options) } const wasmgen_exports = [ - // these are used by C as is - "gen_eqz_i32", - "gen_if_void", - "gen_else", - "gen_loop_void", - "gen_block_void", - "gen_block_end", - "gen_return", - "gen_brtable_and_cases", - "gen_br", - "gen_get_local", - "gen_set_local", - "gen_const_i32", - "gen_unreachable", - "gen_drop", - "gen_increment_mem32", - "gen_increment_variable", - - // these are wrapped around without the rs_ prefix by C - "rs_gen_fn0_const", - "rs_gen_fn0_const_ret", - "rs_gen_fn1_const", - "rs_gen_fn1_const_ret", - "rs_gen_fn2_const", - "rs_gen_fn3_const", - "rs_gen_call_fn1_ret", - "rs_gen_call_fn2", - "rs_get_fn_idx", - - // these are exported to C with the gen_ prefix attached via JS "new_buf", - "reset", "finish", - "get_op_ptr", - "get_op_len", + "reset", + "get_fn_idx", "include_buffer", - "push_i32", - "push_u32", - "load_aligned_u16", - "load_aligned_i32", - "store_aligned_u16", - "store_aligned_i32", - "add_i32", - "and_i32", - "or_i32", - "shl_i32", - "call_fn", - "call_fn_with_arg", + + "wg_push_i32", + "wg_push_u32", + "wg_load_aligned_u16", + "wg_load_aligned_i32", + "wg_store_aligned_u16", + "wg_store_aligned_i32", + "wg_add_i32", + "wg_and_i32", + "wg_or_i32", + "wg_shl_i32", + "wg_call_fn", + "wg_call_fn_with_arg", + "wg_eq_i32", + "wg_ne_i32", + "wg_le_i32", + "wg_lt_i32", + "wg_ge_i32", + "wg_gt_i32", + "wg_if_i32", + "wg_block_i32", + "wg_tee_local", + "wg_xor_i32", + "wg_load_unaligned_i32_from_stack", + "wg_load_aligned_i32_from_stack", + "wg_store_unaligned_i32", + "wg_shr_u32", + "wg_shr_i32", + "wg_eqz_i32", + "wg_if_void", + "wg_else", + "wg_loop_void", + "wg_block_void", + "wg_block_end", + "wg_return", + "wg_drop", + "wg_brtable_and_cases", + "wg_br", + "wg_get_local", + "wg_set_local", + "wg_unreachable", + "wg_increment_mem32", + "wg_increment_variable", + "wg_load_aligned_u16_from_stack", + "wg_fn0_const", + "wg_fn0_const_ret", + "wg_fn1_const", + "wg_fn1_const_ret", + "wg_fn2_const", + "wg_fn3_const", + "wg_call_fn1_ret", + "wg_call_fn2", ]; function reexport_wasmgen_functions(wasmgen) { for(const fn_name of wasmgen_exports) { - if(fn_name.startsWith("gen_")) + if(fn_name.startsWith("wg_")) { // used as is via C wasm_shared_funcs[`_${fn_name}`] = wasmgen.exports[fn_name]; } - else if(fn_name.startsWith("rs_")) - { - // wrapped around by C - wasm_shared_funcs[`_${fn_name}`] = wasmgen.exports[fn_name.replace("rs_", "")]; - } else { - // prefix "gen_" attached by JS - wasm_shared_funcs[`_gen_${fn_name}`] = wasmgen.exports[fn_name]; + // prefix "wg_" attached by JS + wasm_shared_funcs[`_wg_${fn_name}`] = wasmgen.exports[fn_name]; } } } diff --git a/src/native/codegen/codegen.c b/src/native/codegen/codegen.c index 7c17d436..e6a98086 100644 --- a/src/native/codegen/codegen.c +++ b/src/native/codegen/codegen.c @@ -5,145 +5,81 @@ #include "../const.h" #include "../cpu.h" #include "../global_pointers.h" +#include "wasmgen.h" #include "codegen.h" -#include "cstring.h" -#include "module_init.h" -#include "util.h" -#include "wasm_opcodes.h" -#include "wasm_util.h" - -static Buffer op = { .start = codegen_buffer_op, .ptr = codegen_buffer_op, .len = 0x100000 }; -static Buffer cs = { .start = codegen_buffer_cs, .ptr = codegen_buffer_cs, .len = 0x100000 }; -Buffer instruction_body = { - .start = codegen_buffer_instruction_body, - .ptr = codegen_buffer_instruction_body, - .len = 0x100000, -}; - -static uint8_t* op_ptr_reset_location; -static int32_t import_table_size_reset_value; -static int32_t import_table_count_reset_value; static void jit_add_seg_offset(int32_t default_segment); static void jit_resolve_modrm32_(int32_t modrm_byte); static void jit_resolve_modrm16_(int32_t modrm_byte); - -void gen_init(void) -{ - // wasm magic header - write_raw_u8(&op, 0); write_raw_u8(&op, 'a'); write_raw_u8(&op, 's'); write_raw_u8(&op, 'm'); - - // wasm version in leb128, 4 bytes - write_raw_u8(&op, WASM_VERSION); write_raw_u8(&op, 0); write_raw_u8(&op, 0); write_raw_u8(&op, 0); - - write_type_section(); - write_import_section_preamble(); - - // add initial imports - uint8_t _fn_get_seg_idx = write_import_entry("get_seg", 7, FN1_RET_TYPE_INDEX); - assert(_fn_get_seg_idx == fn_get_seg_idx); - UNUSED(_fn_get_seg_idx); - - // store state of current pointers etc. so we can reset them later - op_ptr_reset_location = op.ptr; - import_table_size_reset_value = import_table_size; - import_table_count_reset_value = import_table_count; -} +PackedStr pack_str(char const* fn_name, uint8_t fn_len); void gen_reset(void) { - op.ptr = op_ptr_reset_location; - cs.ptr = cs.start; - import_table_size = import_table_size_reset_value; - import_table_count = import_table_count_reset_value; + wg_reset(); + cs = wg_new_buf(); + instruction_body = wg_new_buf(); + add_get_seg_import(); } -uintptr_t gen_finish(int32_t no_of_locals_i32) +void add_get_seg_import(void) { - write_memory_import(); - write_function_section(1); - 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_raw_u8(&op, SC_CODE); - - ptr_code_section_size = op.ptr; // we will write to this location later - write_raw_u8(&op, 0); write_raw_u8(&op, 0); // write temp val for now using 4 bytes - write_raw_u8(&op, 0); write_raw_u8(&op, 0); - - write_raw_u8(&op, 1); // number of function bodies: just 1 - - // same as above but for body size of the function - ptr_fn_body_size = op.ptr; - write_raw_u8(&op, 0); write_raw_u8(&op, 0); - write_raw_u8(&op, 0); write_raw_u8(&op, 0); - - write_raw_u8(&op, 1); // count of local blocks - write_raw_u8(&op, no_of_locals_i32); write_raw_u8(&op, TYPE_I32); // locals of type i32 - - copy_code_section(); - - // write code section epilogue - write_raw_u8(&op, OP_END); - - // write the actual sizes to the pointer locations stored above. We subtract 4 from the actual - // value because the ptr itself points to four bytes - write_fixed_leb32_to_ptr(ptr_fn_body_size, op.ptr - ptr_fn_body_size - 4); - write_fixed_leb32_to_ptr(ptr_code_section_size, op.ptr - ptr_code_section_size - 4); - - return (uintptr_t) op.ptr; + uint16_t _fn_get_seg_idx = get_fn_idx("get_seg", 7, FN1_RET_TYPE_INDEX); + assert(_fn_get_seg_idx == fn_get_seg_idx); + UNUSED(_fn_get_seg_idx); } -uintptr_t gen_get_final_offset(void) +PackedStr pack_str(char const* fn_name, uint8_t fn_len) { - return (uintptr_t) op.ptr; + assert(fn_len <= 16); + + union { + PackedStr pstr; + uint8_t u8s[16]; + } ret = { { 0 } }; + + for(int i = 0; i < fn_len; i++) + { + ret.u8s[i] = fn_name[i]; + } + return ret.pstr; +} + +uint16_t get_fn_idx(char const* fn, uint8_t fn_len, uint8_t fn_type) +{ + PackedStr pstr = pack_str(fn, fn_len); + return wg_get_fn_idx(pstr.a, pstr.b, fn_type); } void gen_increment_mem32(int32_t addr) { - push_i32(&cs, addr); - - load_aligned_i32(&cs, addr); - push_i32(&cs, 1); - add_i32(&cs); - - store_aligned_i32(&cs); + wg_increment_mem32(cs, addr); } void gen_increment_variable(int32_t variable_address, int32_t n) { - push_i32(&cs, variable_address); - - load_aligned_i32(&cs, variable_address); - push_i32(&cs, n); - add_i32(&cs); - - store_aligned_i32(&cs); + wg_increment_variable(cs, variable_address, n); } void gen_increment_instruction_pointer(int32_t n) { - push_i32(&cs, (int32_t)instruction_pointer); // store address of ip + wg_push_i32(cs, (int32_t)instruction_pointer); // store address of ip - load_aligned_i32(&cs, (int32_t)instruction_pointer); // load ip + wg_load_aligned_i32(cs, (int32_t)instruction_pointer); // load ip - push_i32(&cs, n); + wg_push_i32(cs, n); - add_i32(&cs); - store_aligned_i32(&cs); // store it back in + wg_add_i32(cs); + wg_store_aligned_i32(cs); // store it back in } void gen_relative_jump(int32_t n) { // add n to instruction_pointer (without setting the offset as above) - push_i32(&instruction_body, (int32_t)instruction_pointer); - load_aligned_i32(&instruction_body, (int32_t)instruction_pointer); - push_i32(&instruction_body, n); - add_i32(&instruction_body); - store_aligned_i32(&instruction_body); + wg_push_i32(instruction_body, (int32_t)instruction_pointer); + wg_load_aligned_i32(instruction_body, (int32_t)instruction_pointer); + wg_push_i32(instruction_body, n); + wg_add_i32(instruction_body); + wg_store_aligned_i32(instruction_body); } void gen_increment_timestamp_counter(uint32_t n) @@ -153,156 +89,156 @@ void gen_increment_timestamp_counter(uint32_t n) void gen_set_previous_eip_offset_from_eip(int32_t n) { - push_i32(&cs, (int32_t)previous_ip); // store address of previous ip - load_aligned_i32(&cs, (int32_t)instruction_pointer); // load ip + wg_push_i32(cs, (int32_t)previous_ip); // store address of previous ip + wg_load_aligned_i32(cs, (int32_t)instruction_pointer); // load ip if(n != 0) { - push_i32(&cs, n); - add_i32(&cs); // add constant to ip value + wg_push_i32(cs, n); + wg_add_i32(cs); // add constant to ip value } - store_aligned_i32(&cs); // store it as previous ip + wg_store_aligned_i32(cs); // store it as previous ip } void gen_set_previous_eip(void) { - push_i32(&cs, (int32_t)previous_ip); // store address of previous ip - load_aligned_i32(&cs, (int32_t)instruction_pointer); // load ip - store_aligned_i32(&cs); // store it as previous ip + wg_push_i32(cs, (int32_t)previous_ip); // store address of previous ip + wg_load_aligned_i32(cs, (int32_t)instruction_pointer); // load ip + wg_store_aligned_i32(cs); // store it as previous ip } void gen_clear_prefixes(void) { - push_i32(&instruction_body, (int32_t)prefixes); // load address of prefixes - push_i32(&instruction_body, 0); - store_aligned_i32(&instruction_body); + wg_push_i32(instruction_body, (int32_t)prefixes); // load address of prefixes + wg_push_i32(instruction_body, 0); + wg_store_aligned_i32(instruction_body); } void gen_add_prefix_bits(int32_t mask) { assert(mask >= 0 && mask < 0x100); - push_i32(&instruction_body, (int32_t)prefixes); // load address of prefixes + wg_push_i32(instruction_body, (int32_t)prefixes); // load address of prefixes - load_aligned_i32(&instruction_body, (int32_t)prefixes); // load old value - push_i32(&instruction_body, mask); - or_i32(&instruction_body); + wg_load_aligned_i32(instruction_body, (int32_t)prefixes); // load old value + wg_push_i32(instruction_body, mask); + wg_or_i32(instruction_body); - store_aligned_i32(&instruction_body); + wg_store_aligned_i32(instruction_body); } void gen_fn0_const_ret(char const* fn, uint8_t fn_len) { - int32_t fn_idx = get_fn_index(fn, fn_len, FN0_RET_TYPE_INDEX); - call_fn(&instruction_body, fn_idx); + int32_t fn_idx = get_fn_idx(fn, fn_len, FN0_RET_TYPE_INDEX); + wg_call_fn(instruction_body, fn_idx); } void gen_fn0_const(char const* fn, uint8_t fn_len) { - int32_t fn_idx = get_fn_index(fn, fn_len, FN0_TYPE_INDEX); - call_fn(&instruction_body, fn_idx); + int32_t fn_idx = get_fn_idx(fn, fn_len, FN0_TYPE_INDEX); + wg_call_fn(instruction_body, fn_idx); } void gen_set_reg16_fn0(char const* fn, uint8_t fn_len, int32_t reg) { // generates: reg16[reg] = fn() - int32_t fn_idx = get_fn_index(fn, fn_len, FN0_RET_TYPE_INDEX); - push_i32(&instruction_body, (int32_t) ®16[reg]); - call_fn(&instruction_body, fn_idx); - store_aligned_u16(&instruction_body); + int32_t fn_idx = get_fn_idx(fn, fn_len, FN0_RET_TYPE_INDEX); + wg_push_i32(instruction_body, (int32_t) ®16[reg]); + wg_call_fn(instruction_body, fn_idx); + wg_store_aligned_u16(instruction_body); } void gen_set_reg32s_fn0(char const* fn, uint8_t fn_len, int32_t reg) { // generates: reg32s[reg] = fn() - int32_t fn_idx = get_fn_index(fn, fn_len, FN0_RET_TYPE_INDEX); - push_i32(&instruction_body, (int32_t) ®32s[reg]); - call_fn(&instruction_body, fn_idx); - store_aligned_i32(&instruction_body); + int32_t fn_idx = get_fn_idx(fn, fn_len, FN0_RET_TYPE_INDEX); + wg_push_i32(instruction_body, (int32_t) ®32s[reg]); + wg_call_fn(instruction_body, fn_idx); + wg_store_aligned_i32(instruction_body); } void gen_fn1_const_ret(char const* fn, uint8_t fn_len, int32_t arg0) { - int32_t fn_idx = get_fn_index(fn, fn_len, FN1_RET_TYPE_INDEX); - push_i32(&instruction_body, arg0); - call_fn(&instruction_body, fn_idx); + int32_t fn_idx = get_fn_idx(fn, fn_len, FN1_RET_TYPE_INDEX); + wg_push_i32(instruction_body, arg0); + wg_call_fn(instruction_body, fn_idx); } void gen_call_fn1_ret(char const* fn, uint8_t fn_len) { // generates: fn( _ ) where _ must be left on the stack before calling this, and fn returns a value - int32_t fn_idx = get_fn_index(fn, fn_len, FN1_RET_TYPE_INDEX); - call_fn(&instruction_body, fn_idx); + int32_t fn_idx = get_fn_idx(fn, fn_len, FN1_RET_TYPE_INDEX); + wg_call_fn(instruction_body, fn_idx); } void gen_call_fn1(char const* fn, uint8_t fn_len) { // generates: fn( _ ) where _ must be left on the stack before calling this - int32_t fn_idx = get_fn_index(fn, fn_len, FN1_TYPE_INDEX); - call_fn(&instruction_body, fn_idx); + int32_t fn_idx = get_fn_idx(fn, fn_len, FN1_TYPE_INDEX); + wg_call_fn(instruction_body, fn_idx); } void gen_fn1_const(char const* fn, uint8_t fn_len, int32_t arg0) { - int32_t fn_idx = get_fn_index(fn, fn_len, FN1_TYPE_INDEX); - push_i32(&instruction_body, arg0); - call_fn(&instruction_body, fn_idx); + int32_t fn_idx = get_fn_idx(fn, fn_len, FN1_TYPE_INDEX); + wg_push_i32(instruction_body, arg0); + wg_call_fn(instruction_body, fn_idx); } void gen_set_reg16_r(int32_t r_dest, int32_t r_src) { // generates: reg16[r_dest] = reg16[r_src] - push_i32(&instruction_body, (int32_t) ®16[r_dest]); - load_aligned_u16(&instruction_body, (int32_t) ®16[r_src]); - store_aligned_u16(&instruction_body); + wg_push_i32(instruction_body, (int32_t) ®16[r_dest]); + wg_load_aligned_u16(instruction_body, (int32_t) ®16[r_src]); + wg_store_aligned_u16(instruction_body); } void gen_set_reg32_r(int32_t r_dest, int32_t r_src) { // generates: reg32s[r_dest] = reg32s[r_src] - push_i32(&instruction_body, (int32_t) ®32s[r_dest]); - load_aligned_i32(&instruction_body, (int32_t) ®32s[r_src]); - store_aligned_i32(&instruction_body); + wg_push_i32(instruction_body, (int32_t) ®32s[r_dest]); + wg_load_aligned_i32(instruction_body, (int32_t) ®32s[r_src]); + wg_store_aligned_i32(instruction_body); } void gen_fn1_reg16(char const* fn, uint8_t fn_len, int32_t reg) { // generates: fn(reg16[reg]) - int32_t fn_idx = get_fn_index(fn, fn_len, FN1_TYPE_INDEX); - load_aligned_u16(&instruction_body, (int32_t) ®16[reg]); - call_fn(&instruction_body, fn_idx); + int32_t fn_idx = get_fn_idx(fn, fn_len, FN1_TYPE_INDEX); + wg_load_aligned_u16(instruction_body, (int32_t) ®16[reg]); + wg_call_fn(instruction_body, fn_idx); } void gen_fn1_reg32s(char const* fn, uint8_t fn_len, int32_t reg) { // generates: fn(reg32s[reg]) - int32_t fn_idx = get_fn_index(fn, fn_len, FN1_TYPE_INDEX); - load_aligned_i32(&instruction_body, (int32_t) ®32s[reg]); - call_fn(&instruction_body, fn_idx); + int32_t fn_idx = get_fn_idx(fn, fn_len, FN1_TYPE_INDEX); + wg_load_aligned_i32(instruction_body, (int32_t) ®32s[reg]); + wg_call_fn(instruction_body, fn_idx); } void gen_call_fn2(char const* fn, uint8_t fn_len) { // generates: fn( _, _ ) where _ must be left on the stack before calling this - int32_t fn_idx = get_fn_index(fn, fn_len, FN2_TYPE_INDEX); - call_fn(&instruction_body, fn_idx); + int32_t fn_idx = get_fn_idx(fn, fn_len, FN2_TYPE_INDEX); + wg_call_fn(instruction_body, fn_idx); } void gen_fn2_const(char const* 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(&instruction_body, arg0); - push_i32(&instruction_body, arg1); - call_fn(&instruction_body, fn_idx); + int32_t fn_idx = get_fn_idx(fn, fn_len, FN2_TYPE_INDEX); + wg_push_i32(instruction_body, arg0); + wg_push_i32(instruction_body, arg1); + wg_call_fn(instruction_body, fn_idx); } void gen_fn3_const(char const* fn, uint8_t fn_len, int32_t arg0, int32_t arg1, int32_t arg2) { - int32_t fn_idx = get_fn_index(fn, fn_len, FN3_TYPE_INDEX); - push_i32(&instruction_body, arg0); - push_i32(&instruction_body, arg1); - push_i32(&instruction_body, arg2); - call_fn(&instruction_body, fn_idx); + int32_t fn_idx = get_fn_idx(fn, fn_len, FN3_TYPE_INDEX); + wg_push_i32(instruction_body, arg0); + wg_push_i32(instruction_body, arg1); + wg_push_i32(instruction_body, arg2); + wg_call_fn(instruction_body, fn_idx); } void gen_safe_read32(void) @@ -311,51 +247,51 @@ void gen_safe_read32(void) // inline, bailing to safe_read32s_slow if necessary const int32_t address_local = GEN_LOCAL_SCRATCH0; - gen_tee_local(address_local); + wg_tee_local(instruction_body, address_local); // Pseudo: base_on_stack = (uint32_t)address >> 12; - gen_const_i32(12); - shr_u32(&instruction_body); + wg_push_i32(instruction_body, 12); + wg_shr_u32(instruction_body); SCALE_INDEX_FOR_ARRAY32(tlb_data); // Pseudo: entry = tlb_data[base_on_stack]; const int32_t entry_local = GEN_LOCAL_SCRATCH1; - load_aligned_i32_from_stack(&instruction_body, (uint32_t) tlb_data); - gen_tee_local(entry_local); + wg_load_aligned_i32_from_stack(instruction_body, (uint32_t) tlb_data); + wg_tee_local(instruction_body, entry_local); // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && // (address & 0xFFF) <= (0x1000 - 4)); - gen_const_i32(0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(*cpl == 3 ? 0 : TLB_NO_USER)); - and_i32(&instruction_body); + wg_push_i32(instruction_body, 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(*cpl == 3 ? 0 : TLB_NO_USER)); + wg_and_i32(instruction_body); - gen_const_i32(TLB_VALID); - gen_eq_i32(); + wg_push_i32(instruction_body, TLB_VALID); + wg_eq_i32(instruction_body); - gen_get_local(address_local); - gen_const_i32(0xFFF); - and_i32(&instruction_body); - gen_const_i32(0x1000 - 4); - gen_le_i32(); + wg_get_local(instruction_body, address_local); + wg_push_i32(instruction_body, 0xFFF); + wg_and_i32(instruction_body); + wg_push_i32(instruction_body, 0x1000 - 4); + wg_le_i32(instruction_body); - and_i32(&instruction_body); + wg_and_i32(instruction_body); // Pseudo: // if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]); - gen_if_i32(); - gen_get_local(entry_local); - gen_const_i32(~0xFFF); - and_i32(&instruction_body); - gen_get_local(address_local); - xor_i32(&instruction_body); + wg_if_i32(instruction_body); + wg_get_local(instruction_body, entry_local); + wg_push_i32(instruction_body, ~0xFFF); + wg_and_i32(instruction_body); + wg_get_local(instruction_body, address_local); + wg_xor_i32(instruction_body); - load_unaligned_i32_from_stack(&instruction_body, (uint32_t) mem8); + wg_load_unaligned_i32_from_stack(instruction_body, (uint32_t) mem8); // Pseudo: // else { leave_on_stack(safe_read32s_slow(address)); } - gen_else(); - gen_get_local(address_local); + wg_else(instruction_body); + wg_get_local(instruction_body, address_local); gen_call_fn1_ret("safe_read32s_slow", 17); - gen_block_end(); + wg_block_end(instruction_body); } void gen_safe_write32(int32_t local_for_address, int32_t local_for_value) @@ -374,47 +310,47 @@ void gen_safe_write32(int32_t local_for_address, int32_t local_for_value) assert(local_for_address == GEN_LOCAL_SCRATCH0); assert(local_for_value == GEN_LOCAL_SCRATCH1); - gen_get_local(local_for_address); + wg_get_local(instruction_body, local_for_address); // Pseudo: base_on_stack = (uint32_t)address >> 12; - gen_const_i32(12); - shr_u32(&instruction_body); + wg_push_i32(instruction_body, 12); + wg_shr_u32(instruction_body); SCALE_INDEX_FOR_ARRAY32(tlb_data); // entry_local is only used in the following block, so the scratch variable can be reused later { // Pseudo: entry = tlb_data[base_on_stack]; const int32_t entry_local = GEN_LOCAL_SCRATCH2; - load_aligned_i32_from_stack(&instruction_body, (uint32_t) tlb_data); - gen_tee_local(entry_local); + wg_load_aligned_i32_from_stack(instruction_body, (uint32_t) tlb_data); + wg_tee_local(instruction_body, entry_local); // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && // (address & 0xFFF) <= (0x1000 - 4)); - gen_const_i32(0xFFF & ~TLB_GLOBAL & ~(*cpl == 3 ? 0 : TLB_NO_USER)); - and_i32(&instruction_body); + wg_push_i32(instruction_body, 0xFFF & ~TLB_GLOBAL & ~(*cpl == 3 ? 0 : TLB_NO_USER)); + wg_and_i32(instruction_body); - gen_const_i32(TLB_VALID); - gen_eq_i32(); + wg_push_i32(instruction_body, TLB_VALID); + wg_eq_i32(instruction_body); - gen_get_local(local_for_address); - gen_const_i32(0xFFF); - and_i32(&instruction_body); - gen_const_i32(0x1000 - 4); - gen_le_i32(); + wg_get_local(instruction_body, local_for_address); + wg_push_i32(instruction_body, 0xFFF); + wg_and_i32(instruction_body); + wg_push_i32(instruction_body, 0x1000 - 4); + wg_le_i32(instruction_body); - and_i32(&instruction_body); + wg_and_i32(instruction_body); // Pseudo: // if(can_use_fast_path) // { // phys_addr = entry & ~0xFFF ^ address; - gen_if_void(); + wg_if_void(instruction_body); - gen_get_local(entry_local); - gen_const_i32(~0xFFF); - and_i32(&instruction_body); - gen_get_local(local_for_address); - xor_i32(&instruction_body); + wg_get_local(instruction_body, entry_local); + wg_push_i32(instruction_body, ~0xFFF); + wg_and_i32(instruction_body); + wg_get_local(instruction_body, local_for_address); + wg_xor_i32(instruction_body); } // entry_local isn't needed anymore, so we overwrite it @@ -423,9 +359,9 @@ void gen_safe_write32(int32_t local_for_address, int32_t local_for_value) // /* continued within can_use_fast_path branch */ // mem8[phys_addr] = value; - gen_tee_local(phys_addr_local); - gen_get_local(local_for_value); - store_unaligned_i32_with_offset(&instruction_body, (uint32_t) mem8); + wg_tee_local(instruction_body, phys_addr_local); + wg_get_local(instruction_body, local_for_value); + wg_store_unaligned_i32(instruction_body, (uint32_t) mem8); // Only call jit_dirty_cache_single if absolutely necessary // Pseudo: @@ -437,184 +373,40 @@ void gen_safe_write32(int32_t local_for_address, int32_t local_for_value) // } // } - gen_get_local(phys_addr_local); - gen_const_i32(12); - shr_u32(&instruction_body); + wg_get_local(instruction_body, phys_addr_local); + wg_push_i32(instruction_body, 12); + wg_shr_u32(instruction_body); SCALE_INDEX_FOR_ARRAY32(page_first_jit_cache_entry); - load_aligned_i32_from_stack(&instruction_body, (uint32_t) page_first_jit_cache_entry); + wg_load_aligned_i32_from_stack(instruction_body, (uint32_t) page_first_jit_cache_entry); - gen_const_i32(JIT_CACHE_ARRAY_NO_NEXT_ENTRY); - gen_ne_i32(); + wg_push_i32(instruction_body, JIT_CACHE_ARRAY_NO_NEXT_ENTRY); + wg_ne_i32(instruction_body); - gen_get_local(phys_addr_local); - gen_const_i32(12); - shr_u32(&instruction_body); - gen_const_i32(1); - shl_i32(&instruction_body); - load_aligned_u16_from_stack(&instruction_body, (uint32_t) page_entry_points); + wg_get_local(instruction_body, phys_addr_local); + wg_push_i32(instruction_body, 12); + wg_shr_u32(instruction_body); + wg_push_i32(instruction_body, 1); + wg_shl_i32(instruction_body); + wg_load_aligned_u16_from_stack(instruction_body, (uint32_t) page_entry_points); - gen_const_i32(ENTRY_POINT_END); - gen_ne_i32(); + wg_push_i32(instruction_body, ENTRY_POINT_END); + wg_ne_i32(instruction_body); - or_i32(&instruction_body); + wg_or_i32(instruction_body); - gen_if_void(); - gen_get_local(phys_addr_local); + wg_if_void(instruction_body); + wg_get_local(instruction_body, phys_addr_local); gen_call_fn1("jit_dirty_cache_single", 22); - gen_block_end(); + wg_block_end(instruction_body); // Pseudo: // else { safe_read32_slow(address, value); } - gen_else(); - gen_get_local(local_for_address); - gen_get_local(local_for_value); + wg_else(instruction_body); + wg_get_local(instruction_body, local_for_address); + wg_get_local(instruction_body, local_for_value); gen_call_fn2("safe_write32_slow", 17); - gen_block_end(); -} - -void gen_add_i32(void) -{ - add_i32(&instruction_body); -} - -void gen_eqz_i32(void) -{ - write_raw_u8(&instruction_body, OP_I32EQZ); -} - -void gen_eq_i32(void) -{ - write_raw_u8(&instruction_body, OP_I32EQ); -} - -void gen_ne_i32(void) -{ - write_raw_u8(&instruction_body, OP_I32NE); -} - -void gen_le_i32(void) -{ - write_raw_u8(&instruction_body, OP_I32LES); -} - -void gen_lt_i32(void) -{ - write_raw_u8(&instruction_body, OP_I32LTS); -} - -void gen_ge_i32(void) -{ - write_raw_u8(&instruction_body, OP_I32GES); -} - -void gen_gt_i32(void) -{ - write_raw_u8(&instruction_body, OP_I32GTS); -} - -void gen_if_void(void) -{ - write_raw_u8(&instruction_body, OP_IF); - write_raw_u8(&instruction_body, TYPE_VOID_BLOCK); -} - -void gen_if_i32(void) -{ - write_raw_u8(&instruction_body, OP_IF); - write_raw_u8(&instruction_body, TYPE_I32); -} - -void gen_else(void) -{ - write_raw_u8(&instruction_body, OP_ELSE); -} - -void gen_loop_void(void) -{ - write_raw_u8(&instruction_body, OP_LOOP); - write_raw_u8(&instruction_body, TYPE_VOID_BLOCK); -} - -void gen_block_void(void) -{ - write_raw_u8(&instruction_body, OP_BLOCK); - write_raw_u8(&instruction_body, TYPE_VOID_BLOCK); -} - -void gen_block_i32(void) -{ - write_raw_u8(&instruction_body, OP_BLOCK); - write_raw_u8(&instruction_body, TYPE_I32); -} - -void gen_block_end(void) -{ - write_raw_u8(&instruction_body, OP_END); -} - -void gen_return(void) -{ - write_raw_u8(&instruction_body, OP_RETURN); -} - -// Generate a br_table where an input of [i] will branch [i]th outer block, -// where [i] is passed on the wasm stack -void gen_brtable_and_cases(int32_t cases_count) -{ - assert(cases_count >= 0); - - write_raw_u8(&instruction_body, OP_BRTABLE); - write_leb_u32(&instruction_body, cases_count); - - for(int32_t i = 0; i < cases_count + 1; i++) - { - write_leb_u32(&instruction_body, i); - } -} - -void gen_br(int32_t depth) -{ - write_raw_u8(&instruction_body, OP_BR); - write_leb_i32(&instruction_body, depth); -} - -void gen_get_local(int32_t idx) -{ - write_raw_u8(&instruction_body, OP_GETLOCAL); - write_leb_i32(&instruction_body, idx); -} - -void gen_set_local(int32_t idx) -{ - write_raw_u8(&instruction_body, OP_SETLOCAL); - write_leb_i32(&instruction_body, idx); -} - -void gen_tee_local(int32_t idx) -{ - write_raw_u8(&instruction_body, OP_TEELOCAL); - write_leb_i32(&instruction_body, idx); -} - -void gen_const_i32(int32_t v) -{ - push_i32(&instruction_body, v); -} - -void gen_unreachable(void) -{ - write_raw_u8(&instruction_body, OP_UNREACHABLE); -} - -void gen_load_aligned_i32_from_stack(uint32_t byte_offset) -{ - load_aligned_i32_from_stack(&instruction_body, byte_offset); -} - -void gen_store_aligned_i32(void) -{ - store_aligned_i32(&instruction_body); + wg_block_end(instruction_body); } #define MODRM_ENTRY(n, work)\ @@ -641,18 +433,18 @@ void gen_store_aligned_i32(void) static void inline gen_modrm_entry_0(int32_t segment, int32_t reg16_idx_1, int32_t reg16_idx_2, int32_t imm) { // generates: fn( ( reg1 + reg2 + imm ) & 0xFFFF ) - load_aligned_u16(&instruction_body, reg16_idx_1); - load_aligned_u16(&instruction_body, reg16_idx_2); - add_i32(&instruction_body); + wg_load_aligned_u16(instruction_body, reg16_idx_1); + wg_load_aligned_u16(instruction_body, reg16_idx_2); + wg_add_i32(instruction_body); if(imm) { - push_i32(&instruction_body, imm); - add_i32(&instruction_body); + wg_push_i32(instruction_body, imm); + wg_add_i32(instruction_body); } - push_i32(&instruction_body, 0xFFFF); - and_i32(&instruction_body); + wg_push_i32(instruction_body, 0xFFFF); + wg_and_i32(instruction_body); jit_add_seg_offset(segment); } @@ -660,16 +452,16 @@ static void inline gen_modrm_entry_0(int32_t segment, int32_t reg16_idx_1, int32 static void gen_modrm_entry_1(int32_t segment, int32_t reg16_idx, int32_t imm) { // generates: fn ( ( reg + imm ) & 0xFFFF ) - load_aligned_u16(&instruction_body, reg16_idx); + wg_load_aligned_u16(instruction_body, reg16_idx); if(imm) { - push_i32(&instruction_body, imm); - add_i32(&instruction_body); + wg_push_i32(instruction_body, imm); + wg_add_i32(instruction_body); } - push_i32(&instruction_body, 0xFFFF); - and_i32(&instruction_body); + wg_push_i32(instruction_body, 0xFFFF); + wg_and_i32(instruction_body); jit_add_seg_offset(segment); } @@ -693,14 +485,14 @@ static void jit_add_seg_offset(int32_t default_segment) return; } - push_i32(&instruction_body, seg); - call_fn(&instruction_body, fn_get_seg_idx); - add_i32(&instruction_body); + wg_push_i32(instruction_body, seg); + wg_call_fn(instruction_body, fn_get_seg_idx); + wg_add_i32(instruction_body); } static void gen_modrm_entry_2() { - push_i32(&instruction_body, read_imm16()); + wg_push_i32(instruction_body, read_imm16()); jit_add_seg_offset(DS); } @@ -737,12 +529,12 @@ static void jit_resolve_modrm16_(int32_t modrm_byte) static void gen_modrm32_entry(int32_t segment, int32_t reg32s_idx, int32_t imm) { // generates: fn ( reg + imm ) - load_aligned_i32(&instruction_body, reg32s_idx); + wg_load_aligned_i32(instruction_body, reg32s_idx); if(imm) { - push_i32(&instruction_body, imm); - add_i32(&instruction_body); + wg_push_i32(instruction_body, imm); + wg_add_i32(instruction_body); } jit_add_seg_offset(segment); @@ -788,11 +580,11 @@ static void jit_resolve_sib(bool mod) // Where base is accessed from memory if base_is_mem_access or written as a constant otherwise if(base_is_mem_access) { - load_aligned_i32(&instruction_body, base_addr); + wg_load_aligned_i32(instruction_body, base_addr); } else { - push_i32(&instruction_body, base); + wg_push_i32(instruction_body, base); } jit_add_seg_offset(seg); @@ -809,13 +601,11 @@ static void jit_resolve_sib(bool mod) uint8_t s = sib_byte >> 6 & 3; - load_aligned_i32(&instruction_body, (int32_t)(reg32s + m)); - // We don't use push_u32 here either since s will fit in 1 byte - write_raw_u8(&instruction_body, OP_I32CONST); - write_raw_u8(&instruction_body, s); - shl_i32(&instruction_body); + wg_load_aligned_i32(instruction_body, (int32_t)(reg32s + m)); + wg_push_i32(instruction_body, s); + wg_shl_i32(instruction_body); - add_i32(&instruction_body); + wg_add_i32(instruction_body); } static void modrm32_special_case_1(void) @@ -826,8 +616,8 @@ static void modrm32_special_case_1(void) if(imm) { - push_i32(&instruction_body, imm); - add_i32(&instruction_body); + wg_push_i32(instruction_body, imm); + wg_add_i32(instruction_body); } } @@ -839,8 +629,8 @@ static void modrm32_special_case_2(void) if(imm) { - push_i32(&instruction_body, imm); - add_i32(&instruction_body); + wg_push_i32(instruction_body, imm); + wg_add_i32(instruction_body); } } @@ -848,7 +638,7 @@ static void gen_modrm32_entry_1() { int32_t imm = read_imm32s(); - push_i32(&instruction_body, imm); + wg_push_i32(instruction_body, imm); jit_add_seg_offset(DS); } @@ -897,33 +687,34 @@ void gen_modrm_fn2(char const* fn, uint8_t fn_len, int32_t arg0, int32_t arg1) { // generates: fn( _, arg0, arg1 ) - push_i32(&instruction_body, arg0); - push_i32(&instruction_body, arg1); + wg_push_i32(instruction_body, arg0); + wg_push_i32(instruction_body, arg1); - int32_t fn_idx = get_fn_index(fn, fn_len, FN3_TYPE_INDEX); - call_fn(&instruction_body, fn_idx); + int32_t fn_idx = get_fn_idx(fn, fn_len, FN3_TYPE_INDEX); + wg_call_fn(instruction_body, fn_idx); } void gen_modrm_fn1(char const* fn, uint8_t fn_len, int32_t arg0) { // generates: fn( _, arg0 ) - push_i32(&instruction_body, arg0); + wg_push_i32(instruction_body, arg0); - int32_t fn_idx = get_fn_index(fn, fn_len, FN2_TYPE_INDEX); - call_fn(&instruction_body, fn_idx); + int32_t fn_idx = get_fn_idx(fn, fn_len, FN2_TYPE_INDEX); + wg_call_fn(instruction_body, fn_idx); } void gen_modrm_fn0(char const* fn, uint8_t fn_len) { // generates: fn( _ ) - int32_t fn_idx = get_fn_index(fn, fn_len, FN1_TYPE_INDEX); - call_fn(&instruction_body, fn_idx); + int32_t fn_idx = get_fn_idx(fn, fn_len, FN1_TYPE_INDEX); + wg_call_fn(instruction_body, fn_idx); } void gen_commit_instruction_body_to_cs(void) { - append_buffer(&cs, &instruction_body); - instruction_body.ptr = instruction_body.start; + wg_include_buffer(cs); + wg_include_buffer(instruction_body); } + diff --git a/src/native/codegen/codegen.h b/src/native/codegen/codegen.h index 1bb0a948..19ef9256 100644 --- a/src/native/codegen/codegen.h +++ b/src/native/codegen/codegen.h @@ -2,7 +2,7 @@ #include -#include "util.h" +#include "wasmgen.h" #define FN0_TYPE_INDEX 0 #define FN1_TYPE_INDEX 1 @@ -24,19 +24,19 @@ "codegen: Elements assumed to be 4 bytes." \ ); \ /* Shift the index to make it byte-indexed, not array-indexed */ \ - gen_const_i32(2); \ - shl_i32(&instruction_body); + wg_push_i32(instruction_body, 2); \ + wg_shl_i32(instruction_body); -extern Buffer instruction_body; +uint8_t* cs; +uint8_t* instruction_body; -static uint8_t const fn_get_seg_idx = 0; +static uint16_t const fn_get_seg_idx = 0; -void gen_init(void); void gen_reset(void); -uintptr_t gen_finish(int32_t no_of_locals_i32); -uintptr_t gen_get_final_offset(void); +// uintptr_t gen_finish(int32_t no_of_locals_i32); +void add_get_seg_import(void); -int32_t get_fn_index(char const* fn, uint8_t fn_len, uint8_t type_index); +uint16_t get_fn_idx(char const* fn, uint8_t fn_len, uint8_t fn_type); // Generate function call with constant arguments void gen_fn0_const(char const* fn, uint8_t fn_len); @@ -68,39 +68,6 @@ void gen_call_fn2(char const* fn, uint8_t fn_len); void gen_safe_read32(void); void gen_safe_write32(int32_t local_for_address, int32_t local_for_value); -void gen_add_i32(void); -void gen_eqz_i32(void); -void gen_eq_i32(void); -void gen_ne_i32(void); -void gen_le_i32(void); -void gen_lt_i32(void); -void gen_ge_i32(void); -void gen_gt_i32(void); - -void gen_if_void(void); -void gen_if_i32(void); -void gen_else(void); -void gen_loop_void(void); -void gen_block_void(void); -void gen_block_i32(void); -void gen_block_end(void); -void gen_return(void); - -void gen_brtable_and_cases(int32_t); - -void gen_br(int32_t depth); - -void gen_const_i32(int32_t); - -void gen_get_local(int32_t); -void gen_set_local(int32_t); -void gen_tee_local(int32_t); - -void gen_unreachable(void); - -void gen_load_aligned_i32_from_stack(uint32_t byte_offset); -void gen_store_aligned_i32(void); - void gen_modrm_resolve(int32_t modrm_byte); void gen_modrm_fn0(char const* fn, uint8_t fn_len); void gen_modrm_fn1(char const* fn, uint8_t fn_len, int32_t arg0); diff --git a/src/native/codegen/cstring.h b/src/native/codegen/cstring.h deleted file mode 100644 index f0cdf0e0..00000000 --- a/src/native/codegen/cstring.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -// everything here is copied from musl - -#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; -} diff --git a/src/native/codegen/module_init.h b/src/native/codegen/module_init.h deleted file mode 100644 index f4b5ab0c..00000000 --- a/src/native/codegen/module_init.h +++ /dev/null @@ -1,218 +0,0 @@ -#pragma once - -#include - -#include "codegen.h" -#include "cstring.h" -#include "util.h" -#include "wasm_opcodes.h" - -static Buffer op; -static Buffer cs; - -static void write_type_section() -{ - write_raw_u8(&op, SC_TYPE); - - uint8_t* ptr_section_size = op.ptr; - write_raw_u8(&op, 0); - - write_raw_u8(&op, NR_FN_TYPE_INDEXES); // number of type descriptors - - // FN0 - write_raw_u8(&op, TYPE_FUNC); - write_raw_u8(&op, 0); // no args - write_raw_u8(&op, 0); // no return val - - // FN1 - write_raw_u8(&op, TYPE_FUNC); - write_raw_u8(&op, 1); - write_raw_u8(&op, TYPE_I32); - write_raw_u8(&op, 0); - - // FN2 - write_raw_u8(&op, TYPE_FUNC); - write_raw_u8(&op, 2); - write_raw_u8(&op, TYPE_I32); - write_raw_u8(&op, TYPE_I32); - write_raw_u8(&op, 0); - - // FN3 - write_raw_u8(&op, TYPE_FUNC); - write_raw_u8(&op, 3); - write_raw_u8(&op, TYPE_I32); - write_raw_u8(&op, TYPE_I32); - write_raw_u8(&op, TYPE_I32); - write_raw_u8(&op, 0); - - // FN0_RET - write_raw_u8(&op, TYPE_FUNC); - write_raw_u8(&op, 0); - write_raw_u8(&op, 1); - write_raw_u8(&op, TYPE_I32); - - // FN1_RET - write_raw_u8(&op, TYPE_FUNC); - write_raw_u8(&op, 1); - write_raw_u8(&op, TYPE_I32); - write_raw_u8(&op, 1); - write_raw_u8(&op, TYPE_I32); - - // FN2_RET - write_raw_u8(&op, TYPE_FUNC); - write_raw_u8(&op, 2); - write_raw_u8(&op, TYPE_I32); - write_raw_u8(&op, TYPE_I32); - write_raw_u8(&op, 1); - write_raw_u8(&op, 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 two as the section starts with containing two bytes for the import count -static int32_t import_table_size = 2; - -static int32_t import_table_count = 0; - -// 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 const* fn, uint8_t fn_len) -{ - uint8_t* offset = ptr_import_entries; - for(int32_t i = 0; i < import_table_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(int32_t size) -{ - assert(size < 0x4000); - import_table_size = size; - write_fixed_leb16_to_ptr(ptr_import_table_size, size); -} - -static void set_import_table_count(int32_t count) -{ - assert(count < 0x4000); - import_table_count = count; - write_fixed_leb16_to_ptr(ptr_import_count, import_table_count); -} - -static void write_import_section_preamble() -{ - write_raw_u8(&op, SC_IMPORT); - - ptr_import_table_size = op.ptr; // store current pointer location to write into later on - write_raw_u8(&op, 1 | 0b10000000); write_raw_u8(&op, 0); // 1 in 2 byte leb - - // same as above but for count of entries - ptr_import_count = op.ptr; - write_raw_u8(&op, 0); - write_raw_u8(&op, 0); - - // here after starts the actual list of imports - ptr_import_entries = op.ptr; -} - -static void write_memory_import() -{ - write_raw_u8(&op, 1); - write_raw_u8(&op, 'e'); - write_raw_u8(&op, 1); - write_raw_u8(&op, 'm'); - - write_raw_u8(&op, EXT_MEMORY); - - write_raw_u8(&op, 0); // memory flag, 0 for no maximum memory limit present - write_leb_u32(&op, 256); // initial memory length of 256 pages, takes 2 bytes in leb128 - - set_import_table_count(import_table_count + 1); - set_import_table_size(import_table_size + 1 + 1 + 1 + 1 + 1 + 1 + 2); -} - -static int32_t write_import_entry(char const* fn_name, uint8_t fn_name_len, uint8_t type_index) -{ - write_raw_u8(&op, 1); // length of module name - write_raw_u8(&op, 'e'); // module name - write_raw_u8(&op, fn_name_len); - assert(fn_name_len < 0x80); - for (uint8_t i = 0; i < fn_name_len; i++) - { - assert(fn_name[i] >= 0); - write_raw_u8(&op, fn_name[i]); - } - write_raw_u8(&op, EXT_FUNCTION); - assert(type_index < 0x80); - write_raw_u8(&op, type_index); - set_import_table_count(import_table_count + 1); - - set_import_table_size(import_table_size + 1 + 1 + 1 + fn_name_len + 1 + 1); - - return import_table_count - 1; -} - -static void write_function_section(int32_t count) -{ - write_raw_u8(&op, SC_FUNCTION); - assert(1 + count < 0x80 && count >= 0); - write_raw_u8(&op, 1 + count); // length of this section - write_raw_u8(&op, count); // count of signature indices - - for(int32_t i = 0; i < count; i++) - { - write_raw_u8(&op, FN1_TYPE_INDEX); - } -} - -static void write_export_section() -{ - write_raw_u8(&op, SC_EXPORT); - write_raw_u8(&op, 1 + 1 + 1 + 1 + 2); // size of this section - write_raw_u8(&op, 1); // count of table: just one function exported - - write_raw_u8(&op, 1); // length of exported function name - write_raw_u8(&op, 'f'); // function name - write_raw_u8(&op, 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 - assert(import_table_count - 1 < 0x4000 && import_table_count >= 1); - write_fixed_leb16(&op, import_table_count - 1); -} - -int32_t get_fn_index(char const* 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 void copy_code_section() -{ - append_buffer(&op, &cs); -} diff --git a/src/native/codegen/util.h b/src/native/codegen/util.h deleted file mode 100644 index f92a2250..00000000 --- a/src/native/codegen/util.h +++ /dev/null @@ -1,100 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include "../const.h" -#include "../log.h" - -typedef struct Buffer { - uint8_t* const start; - uint8_t* ptr; - int32_t const len; -} Buffer; - - -static void inline write_raw_u8(Buffer* buf, int32_t v) -{ - assert(v >= 0 && v < 0x100); - assert(buf->ptr < buf->start + buf->len); - *buf->ptr++ = v; -} - -static void write_leb_i32(Buffer* buf, 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; - const uint32_t SIZE = 32; - while (more) - { - uint8_t byte = v & 0b1111111; // get last 7 bits - v >>= 7; // shift them away from the value - if (negative) - { - v |= ((uint32_t)~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 - } - write_raw_u8(buf, byte); - } -} - -static void write_leb_u32(Buffer* buf, uint32_t v) -{ - do { - uint8_t byte = v & 0b1111111; // get last 7 bits - v >>= 7; // shift them away from the value - if (v != 0) - { - byte |= 0b10000000; // turn on MSB - } - write_raw_u8(buf, byte); - } while (v != 0); -} - -static void write_fixed_leb16(Buffer* buf, int32_t x) -{ - dbg_assert(x >= 0 && x < (1 << 14)); // we have 14 bits of available space in 2 bytes for leb - write_raw_u8(buf, (x & 0b1111111) | 0b10000000); - write_raw_u8(buf, x >> 7); -} - -static void inline write_fixed_leb16_to_ptr(uint8_t* ptr, int32_t x) -{ - dbg_assert(x >= 0 && x < (1 << 14)); // we have 14 bits of available space in 2 bytes for leb - *(ptr ) = (x & 0b1111111) | 0b10000000; - *(ptr + 1) = x >> 7; -} - -static void inline write_fixed_leb32_to_ptr(uint8_t* ptr, uint32_t x) -{ - dbg_assert(x < (1 << 28)); // we have 28 bits of available space in 4 bytes for leb - *(ptr ) = (x & 0b1111111) | 0b10000000; - *(ptr + 1) = (x >> 7 & 0b1111111) | 0b10000000; - *(ptr + 2) = (x >> 14 & 0b1111111) | 0b10000000; - *(ptr + 3) = (x >> 21 & 0b1111111); -} - -static void append_buffer(Buffer *dest, Buffer *src) -{ - assert(dest->len - (dest->ptr - dest->start) >= (src->ptr - src->start)); - - uint8_t* offset = src->start; - while (offset < src->ptr) - { - write_raw_u8(dest, *offset++); - } -} diff --git a/src/native/codegen/wasm_opcodes.h b/src/native/codegen/wasm_opcodes.h deleted file mode 100644 index be015a51..00000000 --- a/src/native/codegen/wasm_opcodes.h +++ /dev/null @@ -1,213 +0,0 @@ -// 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_VOID_BLOCK 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_NO_ALIGN 0 -#define MEM_ALIGN16 1 -#define MEM_ALIGN32 2 diff --git a/src/native/codegen/wasm_util.h b/src/native/codegen/wasm_util.h deleted file mode 100644 index 5c4b73c8..00000000 --- a/src/native/codegen/wasm_util.h +++ /dev/null @@ -1,135 +0,0 @@ -#pragma once - -#include - -#include "wasm_opcodes.h" -#include "util.h" - -static void inline push_i32(Buffer* buf, int32_t v) -{ - write_raw_u8(buf, OP_I32CONST); - write_leb_i32(buf, v); -} - -static void inline push_u32(Buffer* buf, uint32_t v) -{ - write_raw_u8(buf, OP_I32CONST); - write_leb_u32(buf, v); -} - -static void inline load_aligned_u16(Buffer* buf, uint32_t addr) -{ - // doesn't cause a failure in the generated code, but it will be much slower - assert((addr & 1) == 0); - - write_raw_u8(buf, OP_I32CONST); - write_leb_i32(buf, addr); - write_raw_u8(buf, OP_I32LOAD16U); - write_raw_u8(buf, MEM_ALIGN16); - // Immediate offset - write_raw_u8(buf, 0); -} - -static void inline load_aligned_u16_from_stack(Buffer* buf, uint32_t byte_offset) -{ - write_raw_u8(buf, OP_I32LOAD16U); - write_raw_u8(buf, MEM_ALIGN16); - write_leb_u32(buf, byte_offset); -} - -static void inline load_unaligned_i32_from_stack(Buffer* buf, uint32_t byte_offset) -{ - write_raw_u8(buf, OP_I32LOAD); - write_raw_u8(buf, MEM_NO_ALIGN); - write_leb_u32(buf, byte_offset); -} - -static void inline load_aligned_i32_from_stack(Buffer* buf, uint32_t byte_offset) -{ - write_raw_u8(buf, OP_I32LOAD); - write_raw_u8(buf, MEM_ALIGN32); - write_leb_u32(buf, byte_offset); -} - -static void inline load_aligned_i32(Buffer* buf, uint32_t addr) -{ - // doesn't cause a failure in the generated code, but it will be much slower - assert((addr & 3) == 0); - - push_i32(buf, addr); - load_aligned_i32_from_stack(buf, 0); -} - -static void inline store_aligned_u16(Buffer* buf) -{ - write_raw_u8(buf, OP_I32STORE16); - write_raw_u8(buf, MEM_ALIGN16); - // Immediate offset - write_raw_u8(buf, 0); -} - -static void inline store_aligned_i32(Buffer* buf) -{ - write_raw_u8(buf, OP_I32STORE); - write_raw_u8(buf, MEM_ALIGN32); - // Immediate offset - write_raw_u8(buf, 0); -} - -// XXX: Function naming should be consistent regarding both alignment and accepting an -// offset. Leaving as-is for the Rust port to cleanup -static void inline store_unaligned_i32_with_offset(Buffer* buf, uint32_t byte_offset) -{ - write_raw_u8(buf, OP_I32STORE); - write_raw_u8(buf, MEM_NO_ALIGN); - write_leb_u32(buf, byte_offset); -} - -static void inline add_i32(Buffer* buf) -{ - write_raw_u8(buf, OP_I32ADD); -} - -static void inline and_i32(Buffer* buf) -{ - write_raw_u8(buf, OP_I32AND); -} - -static void inline or_i32(Buffer* buf) -{ - write_raw_u8(buf, OP_I32OR); -} - -static void inline xor_i32(Buffer* buf) -{ - write_raw_u8(buf, OP_I32XOR); -} - -static void inline shl_i32(Buffer* buf) -{ - write_raw_u8(buf, OP_I32SHL); -} - -static void inline shr_u32(Buffer* buf) -{ - write_raw_u8(buf, OP_I32SHRU); -} - -static void inline shr_i32(Buffer* buf) -{ - write_raw_u8(buf, OP_I32SHRS); -} - -static void inline call_fn(Buffer* buf, int32_t fn_idx) -{ - write_raw_u8(buf, OP_CALL); - assert(fn_idx >= 0); - write_leb_u32(buf, fn_idx); -} - -static void inline call_fn_with_arg(Buffer* buf, int32_t fn_idx, int32_t arg0) -{ - push_i32(buf, arg0); - call_fn(buf, fn_idx); -} - diff --git a/src/native/codegen/wasmgen.h b/src/native/codegen/wasmgen.h new file mode 100644 index 00000000..f9668c2d --- /dev/null +++ b/src/native/codegen/wasmgen.h @@ -0,0 +1,72 @@ +#pragma once + +#include + +typedef struct PackedStr { + uint64_t a; + uint64_t b; +} PackedStr; + +#define PSTR_TY uint64_t, uint64_t + +extern uint8_t* wg_new_buf(void); +extern void wg_finish(uint8_t no_of_locals_i32); +extern void wg_reset(void); +extern uint16_t wg_get_fn_idx(PSTR_TY, uint8_t fn_type); +extern void wg_include_buffer(uint8_t* buf); + +extern void wg_push_i32(uint8_t* buf, int32_t v); +extern void wg_push_u32(uint8_t* buf, uint32_t v); +extern void wg_load_aligned_u16(uint8_t* buf, uint32_t addr); +extern void wg_load_aligned_i32(uint8_t* buf, uint32_t addr); +extern void wg_store_aligned_u16(uint8_t* buf); +extern void wg_store_aligned_i32(uint8_t* buf); +extern void wg_add_i32(uint8_t* buf); +extern void wg_and_i32(uint8_t* buf); +extern void wg_or_i32(uint8_t* buf); +extern void wg_shl_i32(uint8_t* buf); +extern void wg_call_fn(uint8_t* buf, uint16_t fn_idx); +extern void wg_call_fn_with_arg(uint8_t* buf, uint16_t fn_idx, int32_t arg0); +extern void wg_eq_i32(uint8_t* buf); +extern void wg_ne_i32(uint8_t* buf); +extern void wg_le_i32(uint8_t* buf); +extern void wg_lt_i32(uint8_t* buf); +extern void wg_ge_i32(uint8_t* buf); +extern void wg_gt_i32(uint8_t* buf); +extern void wg_if_i32(uint8_t* buf); +extern void wg_block_i32(uint8_t* buf); +extern void wg_tee_local(uint8_t* buf, int32_t idx); +extern void wg_xor_i32(uint8_t* buf); +extern void wg_load_unaligned_i32_from_stack(uint8_t* buf, uint32_t byte_offset); +extern void wg_load_aligned_i32_from_stack(uint8_t* buf, uint32_t byte_offset); +extern void wg_store_unaligned_i32(uint8_t* buf, uint32_t byte_offset); +extern void wg_shr_u32(uint8_t* buf); +extern void wg_shr_i32(uint8_t* buf); +extern void wg_eqz_i32(uint8_t* buf); +extern void wg_if_void(uint8_t* buf); +extern void wg_else(uint8_t* buf); +extern void wg_loop_void(uint8_t* buf); +extern void wg_block_void(uint8_t* buf); +extern void wg_block_end(uint8_t* buf); +extern void wg_return(uint8_t* buf); +extern void wg_drop(uint8_t* buf); +extern void wg_brtable_and_cases(uint8_t* buf, int32_t cases_count); +extern void wg_br(uint8_t* buf, int32_t depth); +extern void wg_get_local(uint8_t* buf, int32_t idx); +extern void wg_set_local(uint8_t* buf, int32_t idx); +extern void wg_unreachable(uint8_t* buf); +extern void wg_increment_mem32(uint8_t* buf, int32_t addr); +extern void wg_increment_variable(uint8_t* buf, int32_t addr, int32_t n); +extern void wg_load_aligned_u16_from_stack(uint8_t* buf, uint32_t byte_offset); + +extern void wg_fn0_const(uint8_t* buf, PSTR_TY); +extern void wg_fn0_const_ret(uint8_t* buf, PSTR_TY); +extern void wg_fn1_const(uint8_t* buf, PSTR_TY, int32_t arg0); +extern void wg_fn1_const_ret(uint8_t* buf, PSTR_TY, int32_t arg0); +extern void wg_fn2_const(uint8_t* buf, PSTR_TY, int32_t arg0, int32_t arg1); +extern void wg_fn3_const(uint8_t* buf, PSTR_TY, int32_t arg0, int32_t arg1, int32_t arg2); +extern void wg_call_fn1_ret(uint8_t* buf, PSTR_TY); +extern void wg_call_fn2(uint8_t* buf, PSTR_TY); + +#undef PSTR_TY + diff --git a/src/native/cpu.c b/src/native/cpu.c index 50301b69..8b988c8e 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -5,6 +5,7 @@ #include #include "codegen/codegen.h" +#include "codegen/wasmgen.h" #include "const.h" #include "cpu.h" #include "global_pointers.h" @@ -1514,52 +1515,52 @@ static void jit_generate(uint32_t phys_addr) gen_reset(); // set state local variable to the initial state passed as the first argument - gen_get_local(GEN_LOCAL_ARG_INITIAL_STATE); - gen_set_local(GEN_LOCAL_STATE); + wg_get_local(instruction_body, GEN_LOCAL_ARG_INITIAL_STATE); + wg_set_local(instruction_body, GEN_LOCAL_STATE); // initialise max_iterations - gen_const_i32(JIT_MAX_ITERATIONS_PER_FUNCTION); - gen_set_local(GEN_LOCAL_ITERATION_COUNTER); + wg_push_i32(instruction_body, JIT_MAX_ITERATIONS_PER_FUNCTION); + wg_set_local(instruction_body, GEN_LOCAL_ITERATION_COUNTER); // main state machine loop - gen_loop_void(); + wg_loop_void(instruction_body); if(JIT_ALWAYS_USE_LOOP_SAFETY || requires_loop_limit) { profiler_stat_increment(S_COMPILE_WITH_LOOP_SAFETY); // decrement max_iterations - gen_get_local(GEN_LOCAL_ITERATION_COUNTER); - gen_const_i32(-1); - gen_add_i32(); - gen_set_local(GEN_LOCAL_ITERATION_COUNTER); + wg_get_local(instruction_body, GEN_LOCAL_ITERATION_COUNTER); + wg_push_i32(instruction_body, -1); + wg_add_i32(instruction_body); + wg_set_local(instruction_body, GEN_LOCAL_ITERATION_COUNTER); // if max_iterations == 0: return - gen_get_local(GEN_LOCAL_ITERATION_COUNTER); - gen_eqz_i32(); - gen_if_void(); - gen_return(); - gen_block_end(); + wg_get_local(instruction_body, GEN_LOCAL_ITERATION_COUNTER); + wg_eqz_i32(instruction_body); + wg_if_void(instruction_body); + wg_return(instruction_body); + wg_block_end(instruction_body); } - gen_block_void(); // for the default case + wg_block_void(instruction_body); // for the default case // generate the opening blocks for the cases for(int32_t i = 0; i < basic_blocks.length; i++) { - gen_block_void(); + wg_block_void(instruction_body); } - gen_get_local(GEN_LOCAL_STATE); - gen_brtable_and_cases(basic_blocks.length); + wg_get_local(instruction_body, GEN_LOCAL_STATE); + wg_brtable_and_cases(instruction_body, basic_blocks.length); for(int32_t i = 0; i < basic_blocks.length; i++) { // Case [i] will jump after the [i]th block, so we first generate the // block end opcode and then the code for that block - gen_block_end(); + wg_block_end(instruction_body); struct basic_block block = basic_blocks.blocks[i]; @@ -1594,10 +1595,10 @@ static void jit_generate(uint32_t phys_addr) assert(next_bb_index != -1); // set state variable to next basic block - gen_const_i32(next_bb_index); - gen_set_local(GEN_LOCAL_STATE); + wg_push_i32(instruction_body, next_bb_index); + wg_set_local(instruction_body, GEN_LOCAL_STATE); - gen_br(basic_blocks.length - i); // to the loop + wg_br(instruction_body, basic_blocks.length - i); // to the loop } else { @@ -1608,7 +1609,7 @@ static void jit_generate(uint32_t phys_addr) const char* condition = condition_functions[block.condition_index]; gen_fn0_const_ret(condition, strlen(condition)); - gen_if_void(); + wg_if_void(instruction_body); // Branch taken @@ -1627,16 +1628,16 @@ static void jit_generate(uint32_t phys_addr) &basic_blocks, block.next_block_branch_taken_addr); assert(next_basic_block_branch_taken_index != -1); - gen_const_i32(next_basic_block_branch_taken_index); - gen_set_local(GEN_LOCAL_STATE); + wg_push_i32(instruction_body, next_basic_block_branch_taken_index); + wg_set_local(instruction_body, GEN_LOCAL_STATE); } else { // Jump to different page - gen_return(); + wg_return(instruction_body); } - gen_else(); + wg_else(instruction_body); { // Branch not taken @@ -1645,13 +1646,13 @@ static void jit_generate(uint32_t phys_addr) &basic_blocks, block.next_block_addr); assert(next_basic_block_index != -1); - gen_const_i32(next_basic_block_index); - gen_set_local(GEN_LOCAL_STATE); + wg_push_i32(instruction_body, next_basic_block_index); + wg_set_local(instruction_body, GEN_LOCAL_STATE); } - gen_block_end(); + wg_block_end(instruction_body); - gen_br(basic_blocks.length - i); // to the loop + wg_br(instruction_body, basic_blocks.length - i); // to the loop } } else @@ -1660,17 +1661,17 @@ static void jit_generate(uint32_t phys_addr) assert(block.condition_index == -1); // Exit this function - gen_return(); + wg_return(instruction_body); } } - gen_block_end(); // default case - gen_unreachable(); + wg_block_end(instruction_body); // default case + wg_unreachable(instruction_body); - gen_block_end(); // loop + wg_block_end(instruction_body); // loop gen_commit_instruction_body_to_cs(); - gen_finish(GEN_NO_OF_LOCALS); + wg_finish(GEN_NO_OF_LOCALS); cached_state_flags state_flags = pack_current_state_flags(); diff --git a/src/native/instructions.c b/src/native/instructions.c index ff8967f8..484a6374 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -5,7 +5,7 @@ #include "arith.h" #include "codegen/codegen.h" -#include "codegen/wasm_util.h" +#include "codegen/wasmgen.h" #include "const.h" #include "cpu.h" #include "fpu.h" @@ -535,11 +535,11 @@ void instr32_89_mem_jit(int32_t modrm_byte, int32_t r) const int32_t value_local = GEN_LOCAL_SCRATCH1; gen_modrm_resolve(modrm_byte); - gen_set_local(address_local); + wg_set_local(instruction_body, address_local); - gen_const_i32((uint32_t) ®32s[r]); - gen_load_aligned_i32_from_stack(0); - gen_set_local(value_local); + wg_push_i32(instruction_body, (uint32_t) ®32s[r]); + wg_load_aligned_i32_from_stack(instruction_body, 0); + wg_set_local(instruction_body, value_local); gen_safe_write32(address_local, value_local); } @@ -565,12 +565,12 @@ void instr16_8B_mem_jit(int32_t modrm_byte, int32_t r) void instr32_8B_mem_jit(int32_t modrm_byte, int32_t r) { // Pseudo: reg32s[r] = safe_read32s(modrm_resolve(modrm_byte)); - gen_const_i32((int32_t) ®32s[r]); + wg_push_i32(instruction_body, (int32_t) ®32s[r]); gen_modrm_resolve(modrm_byte); gen_safe_read32(); - gen_store_aligned_i32(); + wg_store_aligned_i32(instruction_body); } void instr_8C_check_sreg(int32_t sreg) { @@ -620,22 +620,22 @@ void instr32_8D_mem(int32_t addr, int32_t r) { void instr16_8D_mem_jit(int32_t modrm_byte) { int32_t loc = (int32_t) ®16[get_reg16_index(modrm_byte >> 3 & 7)]; - push_u32(&instruction_body, loc); + wg_push_u32(instruction_body, loc); // override prefix, so modrm_resolve does not return the segment part *prefixes |= SEG_PREFIX_ZERO; gen_modrm_resolve(modrm_byte); - store_aligned_u16(&instruction_body); + wg_store_aligned_u16(instruction_body); *prefixes = 0; } void instr32_8D_mem_jit(int32_t modrm_byte) { int32_t loc = (int32_t) ®32s[modrm_byte >> 3 & 7]; - push_u32(&instruction_body, loc); + wg_push_u32(instruction_body, loc); // override prefix, so modrm_resolve does not return the segment part *prefixes |= SEG_PREFIX_ZERO; gen_modrm_resolve(modrm_byte); - store_aligned_i32(&instruction_body); + wg_store_aligned_i32(instruction_body); *prefixes = 0; } diff --git a/src/native/profiler/opstats.c b/src/native/profiler/opstats.c index 8b35d86a..074d3c5c 100644 --- a/src/native/profiler/opstats.c +++ b/src/native/profiler/opstats.c @@ -1,5 +1,6 @@ #include #include +#include #include "../codegen/codegen.h" #include "../shared.h" diff --git a/src/wasmgen/src/c_api.rs b/src/wasmgen/src/c_api.rs index 0f2d87a5..01dc2a64 100644 --- a/src/wasmgen/src/c_api.rs +++ b/src/wasmgen/src/c_api.rs @@ -59,17 +59,17 @@ mod tests { let buf1 = unsafe { new_buf().as_mut().expect("get buf1") }; let buf2 = unsafe { new_buf().as_mut().expect("get buf2") }; - gen_fn0_const_ret(buf1, pack_str("foo")); - gen_fn0_const_ret(buf1, pack_str("bar")); + wg_fn0_const_ret(buf1, pack_str("foo")); + wg_fn0_const_ret(buf1, pack_str("bar")); include_buffer(buf1); finish(2); reset(); - push_i32(buf1, 2); - gen_call_fn1_ret(buf2, pack_str("baz")); - gen_drop(buf2); + wg_push_i32(buf1, 2); + wg_call_fn1_ret(buf2, pack_str("baz")); + wg_drop(buf2); include_buffer(buf1); include_buffer(buf2); diff --git a/src/wasmgen/src/codegen.rs b/src/wasmgen/src/codegen.rs index fc97c0fd..efacd442 100644 --- a/src/wasmgen/src/codegen.rs +++ b/src/wasmgen/src/codegen.rs @@ -1,172 +1,70 @@ -use ::wasm_opcodes::*; use ::util::*; use ::wasm_util::*; use ::module_init::*; +// for functions using the global module singleton + #[no_mangle] -pub fn gen_fn0_const(buf: &mut Vec, fn_name: PackedStr) { +pub fn wg_fn0_const(buf: &mut Vec, fn_name: PackedStr) { let m = get_module(); let fn_idx = m.get_fn_index(fn_name, FN0_TYPE_INDEX); - call_fn(buf, fn_idx); + wg_call_fn(buf, fn_idx); } #[no_mangle] -pub fn gen_fn0_const_ret(buf: &mut Vec, fn_name: PackedStr) { +pub fn wg_fn0_const_ret(buf: &mut Vec, fn_name: PackedStr) { let m = get_module(); let fn_idx = m.get_fn_index(fn_name, FN0_RET_TYPE_INDEX); - call_fn(buf, fn_idx); + wg_call_fn(buf, fn_idx); } #[no_mangle] -pub fn gen_fn1_const(buf: &mut Vec, fn_name: PackedStr, arg0: i32) { +pub fn wg_fn1_const(buf: &mut Vec, fn_name: PackedStr, arg0: i32) { let m = get_module(); let fn_idx = m.get_fn_index(fn_name, FN1_TYPE_INDEX); - push_i32(buf, arg0); - call_fn(buf, fn_idx); + wg_push_i32(buf, arg0); + wg_call_fn(buf, fn_idx); } #[no_mangle] -pub fn gen_fn1_const_ret(buf: &mut Vec, fn_name: PackedStr, arg0: i32) { +pub fn wg_fn1_const_ret(buf: &mut Vec, fn_name: PackedStr, arg0: i32) { let m = get_module(); let fn_idx = m.get_fn_index(fn_name, FN1_RET_TYPE_INDEX); - push_i32(buf, arg0); - call_fn(buf, fn_idx); + wg_push_i32(buf, arg0); + wg_call_fn(buf, fn_idx); } #[no_mangle] -pub fn gen_fn2_const(buf: &mut Vec, fn_name: PackedStr, arg0: i32, arg1: i32) { +pub fn wg_fn2_const(buf: &mut Vec, fn_name: PackedStr, arg0: i32, arg1: i32) { let m = get_module(); let fn_idx = m.get_fn_index(fn_name, FN2_TYPE_INDEX); - push_i32(buf, arg0); - push_i32(buf, arg1); - call_fn(buf, fn_idx); + wg_push_i32(buf, arg0); + wg_push_i32(buf, arg1); + wg_call_fn(buf, fn_idx); } #[no_mangle] -pub fn gen_fn3_const(buf: &mut Vec, fn_name: PackedStr, arg0: i32, arg1: i32, arg2: i32) { +pub fn wg_fn3_const(buf: &mut Vec, fn_name: PackedStr, arg0: i32, arg1: i32, arg2: i32) { let m = get_module(); let fn_idx = m.get_fn_index(fn_name, FN3_TYPE_INDEX); - push_i32(buf, arg0); - push_i32(buf, arg1); - push_i32(buf, arg2); - call_fn(buf, fn_idx); + wg_push_i32(buf, arg0); + wg_push_i32(buf, arg1); + wg_push_i32(buf, arg2); + wg_call_fn(buf, fn_idx); } #[no_mangle] -pub fn gen_call_fn1_ret(buf: &mut Vec, fn_name: PackedStr) { +pub fn wg_call_fn1_ret(buf: &mut Vec, fn_name: PackedStr) { // generates: fn( _ ) where _ must be left on the stack before calling this, and fn returns a value let m = get_module(); let fn_idx = m.get_fn_index(fn_name, FN1_RET_TYPE_INDEX); - call_fn(buf, fn_idx); + wg_call_fn(buf, fn_idx); } #[no_mangle] -pub fn gen_call_fn2(buf: &mut Vec, fn_name: PackedStr) { +pub fn wg_call_fn2(buf: &mut Vec, fn_name: PackedStr) { // generates: fn( _, _ ) where _, _ must be left on the stack before calling this let m = get_module(); let fn_idx = m.get_fn_index(fn_name, FN2_TYPE_INDEX); - call_fn(buf, fn_idx); -} - -#[no_mangle] -pub fn gen_eqz_i32(buf: &mut Vec) { - buf.push(OP_I32EQZ); -} - -#[no_mangle] -pub fn gen_if_void(buf: &mut Vec) { - buf.push(OP_IF); - buf.push(TYPE_VOID_BLOCK); -} - -#[no_mangle] -pub fn gen_else(buf: &mut Vec) { - buf.push(OP_ELSE); -} - -#[no_mangle] -pub fn gen_loop_void(buf: &mut Vec) { - buf.push(OP_LOOP); - buf.push(TYPE_VOID_BLOCK); -} - -#[no_mangle] -pub fn gen_block_void(buf: &mut Vec) { - buf.push(OP_BLOCK); - buf.push(TYPE_VOID_BLOCK); -} - -#[no_mangle] -pub fn gen_block_end(buf: &mut Vec) { - buf.push(OP_END); -} - -#[no_mangle] -pub fn gen_return(buf: &mut Vec) { - buf.push(OP_RETURN); -} - -#[no_mangle] -pub fn gen_drop(buf: &mut Vec) { - buf.push(OP_DROP); -} - -// Generate a br_table where an input of [i] will branch [i]th outer block, -// where [i] is passed on the wasm stack -#[no_mangle] -pub fn gen_brtable_and_cases(buf: &mut Vec, cases_count: i32) { - assert!(cases_count >= 0); - - buf.push(OP_BRTABLE); - write_leb_u32(buf, cases_count as u32); - - for i in 0..(cases_count + 1) { - write_leb_u32(buf, i as u32); - } -} - -#[no_mangle] -pub fn gen_br(buf: &mut Vec, depth: i32) { - buf.push(OP_BR); - write_leb_i32(buf, depth); -} - -#[no_mangle] -pub fn gen_get_local(buf: &mut Vec, idx: i32) { - buf.push(OP_GETLOCAL); - write_leb_i32(buf, idx); -} - -#[no_mangle] -pub fn gen_set_local(buf: &mut Vec, idx: i32) { - buf.push(OP_SETLOCAL); - write_leb_i32(buf, idx); -} - -#[no_mangle] -pub fn gen_const_i32(buf: &mut Vec, v: i32) { - push_i32(buf, v); -} - -#[no_mangle] -pub fn gen_unreachable(buf: &mut Vec) { - buf.push(OP_UNREACHABLE); -} - -#[no_mangle] -pub fn gen_increment_mem32(buf: &mut Vec, addr: u32) { - push_i32(buf, addr as i32); - load_aligned_i32(buf, addr); - push_i32(buf, 1); - add_i32(buf); - store_aligned_i32(buf); -} - -#[no_mangle] -pub fn gen_increment_variable(buf: &mut Vec, variable_address: u32, n: i32) { - push_i32(buf, variable_address as i32); - load_aligned_i32(buf, variable_address as u32); - push_i32(buf, n); - add_i32(buf); - store_aligned_i32(buf); + wg_call_fn(buf, fn_idx); } diff --git a/src/wasmgen/src/wasm_opcodes.rs b/src/wasmgen/src/wasm_opcodes.rs index 7a10526b..c5348084 100644 --- a/src/wasmgen/src/wasm_opcodes.rs +++ b/src/wasmgen/src/wasm_opcodes.rs @@ -218,4 +218,3 @@ c!(OP_F64REINTERPRETI64, 0xbf); c!(MEM_NO_ALIGN, 0); c!(MEM_ALIGN16, 1); c!(MEM_ALIGN32, 2); -c!(MEM_IMM_OFFSET, 0); \ No newline at end of file diff --git a/src/wasmgen/src/wasm_util.rs b/src/wasmgen/src/wasm_util.rs index 297ba6a6..ee120662 100644 --- a/src/wasmgen/src/wasm_util.rs +++ b/src/wasmgen/src/wasm_util.rs @@ -2,19 +2,19 @@ use ::wasm_opcodes::*; use ::util::*; #[no_mangle] -pub fn push_i32(buf: &mut Vec, v: i32) { +pub fn wg_push_i32(buf: &mut Vec, v: i32) { buf.push(OP_I32CONST); write_leb_i32(buf, v); } #[no_mangle] -pub fn push_u32(buf: &mut Vec, v: u32) { +pub fn wg_push_u32(buf: &mut Vec, v: u32) { buf.push(OP_I32CONST); write_leb_u32(buf, v); } #[no_mangle] -pub fn load_aligned_u16(buf: &mut Vec, addr: u32) { +pub fn wg_load_aligned_u16(buf: &mut Vec, addr: u32) { // doesn't cause a failure in the generated code, but it will be much slower dbg_assert!((addr & 1) == 0); @@ -26,50 +26,50 @@ pub fn load_aligned_u16(buf: &mut Vec, addr: u32) { } #[no_mangle] -pub fn load_aligned_i32(buf: &mut Vec, addr: u32) { +pub fn wg_load_aligned_i32(buf: &mut Vec, addr: u32) { // doesn't cause a failure in the generated code, but it will be much slower dbg_assert!((addr & 3) == 0); - push_i32(buf, addr as i32); - load_aligned_i32_from_stack(buf, 0); + wg_push_i32(buf, addr as i32); + wg_load_aligned_i32_from_stack(buf, 0); } #[no_mangle] -pub fn store_aligned_u16(buf: &mut Vec) { +pub fn wg_store_aligned_u16(buf: &mut Vec) { buf.push(OP_I32STORE16); buf.push(MEM_ALIGN16); buf.push(0); // immediate offset } #[no_mangle] -pub fn store_aligned_i32(buf: &mut Vec) { +pub fn wg_store_aligned_i32(buf: &mut Vec) { buf.push(OP_I32STORE); buf.push(MEM_ALIGN32); buf.push(0); // immediate offset } #[no_mangle] -pub fn add_i32(buf: &mut Vec) { +pub fn wg_add_i32(buf: &mut Vec) { buf.push(OP_I32ADD); } #[no_mangle] -pub fn and_i32(buf: &mut Vec) { +pub fn wg_and_i32(buf: &mut Vec) { buf.push(OP_I32AND); } #[no_mangle] -pub fn or_i32(buf: &mut Vec) { +pub fn wg_or_i32(buf: &mut Vec) { buf.push(OP_I32OR); } #[no_mangle] -pub fn shl_i32(buf: &mut Vec) { +pub fn wg_shl_i32(buf: &mut Vec) { buf.push(OP_I32SHL); } #[no_mangle] -pub fn call_fn(buf: &mut Vec, fn_idx: u16) { +pub fn wg_call_fn(buf: &mut Vec, fn_idx: u16) { buf.push(OP_CALL); let buf_len = buf.len(); buf.push(0); buf.push(0); @@ -77,73 +77,73 @@ pub fn call_fn(buf: &mut Vec, fn_idx: u16) { } #[no_mangle] -pub fn call_fn_with_arg(buf: &mut Vec, fn_idx: u16, arg0: i32) { - push_i32(buf, arg0); - call_fn(buf, fn_idx); +pub fn wg_call_fn_with_arg(buf: &mut Vec, fn_idx: u16, arg0: i32) { + wg_push_i32(buf, arg0); + wg_call_fn(buf, fn_idx); } #[no_mangle] -pub fn eq_i32(buf: &mut Vec) { +pub fn wg_eq_i32(buf: &mut Vec) { buf.push(OP_I32EQ); } #[no_mangle] -pub fn ne_i32(buf: &mut Vec) { +pub fn wg_ne_i32(buf: &mut Vec) { buf.push(OP_I32NE); } #[no_mangle] -pub fn le_i32(buf: &mut Vec) { +pub fn wg_le_i32(buf: &mut Vec) { buf.push(OP_I32LES); } #[no_mangle] -pub fn lt_i32(buf: &mut Vec) { +pub fn wg_lt_i32(buf: &mut Vec) { buf.push(OP_I32LTS); } #[no_mangle] -pub fn ge_i32(buf: &mut Vec) { +pub fn wg_ge_i32(buf: &mut Vec) { buf.push(OP_I32GES); } #[no_mangle] -pub fn gt_i32(buf: &mut Vec) { +pub fn wg_gt_i32(buf: &mut Vec) { buf.push(OP_I32GTS); } #[no_mangle] -pub fn if_i32(buf: &mut Vec) { +pub fn wg_if_i32(buf: &mut Vec) { buf.push(OP_IF); buf.push(TYPE_I32); } #[no_mangle] -pub fn block_i32(buf: &mut Vec) { +pub fn wg_block_i32(buf: &mut Vec) { buf.push(OP_BLOCK); buf.push(TYPE_I32); } #[no_mangle] -pub fn tee_local(buf: &mut Vec, idx: i32) { +pub fn wg_tee_local(buf: &mut Vec, idx: i32) { buf.push(OP_TEELOCAL); write_leb_i32(buf, idx); } #[no_mangle] -pub fn xor_i32(buf: &mut Vec) { +pub fn wg_xor_i32(buf: &mut Vec) { buf.push(OP_I32XOR); } #[no_mangle] -pub fn load_unaligned_i32_from_stack(buf: &mut Vec, byte_offset: u32) { +pub fn wg_load_unaligned_i32_from_stack(buf: &mut Vec, byte_offset: u32) { buf.push(OP_I32LOAD); buf.push(MEM_NO_ALIGN); write_leb_u32(buf, byte_offset); } #[no_mangle] -pub fn load_aligned_i32_from_stack(buf: &mut Vec, byte_offset: u32) { +pub fn wg_load_aligned_i32_from_stack(buf: &mut Vec, byte_offset: u32) { buf.push(OP_I32LOAD); buf.push(MEM_ALIGN32); write_leb_u32(buf, byte_offset); @@ -152,18 +152,119 @@ pub fn load_aligned_i32_from_stack(buf: &mut Vec, byte_offset: u32) { // XXX: Function naming should be consistent regarding both alignment and accepting an // offset. Leaving as-is for the Rust port to cleanup #[no_mangle] -pub fn store_unaligned_i32(buf: &mut Vec, byte_offset: u32) { +pub fn wg_store_unaligned_i32(buf: &mut Vec, byte_offset: u32) { buf.push(OP_I32STORE); buf.push(MEM_NO_ALIGN); write_leb_u32(buf, byte_offset); } #[no_mangle] -pub fn shr_u32(buf: &mut Vec) { +pub fn wg_shr_u32(buf: &mut Vec) { buf.push(OP_I32SHRU); } #[no_mangle] -pub fn shr_i32(buf: &mut Vec) { +pub fn wg_shr_i32(buf: &mut Vec) { buf.push(OP_I32SHRS); } + +#[no_mangle] +pub fn wg_eqz_i32(buf: &mut Vec) { + buf.push(OP_I32EQZ); +} + +#[no_mangle] +pub fn wg_if_void(buf: &mut Vec) { + buf.push(OP_IF); + buf.push(TYPE_VOID_BLOCK); +} + +#[no_mangle] +pub fn wg_else(buf: &mut Vec) { + buf.push(OP_ELSE); +} + +#[no_mangle] +pub fn wg_loop_void(buf: &mut Vec) { + buf.push(OP_LOOP); + buf.push(TYPE_VOID_BLOCK); +} + +#[no_mangle] +pub fn wg_block_void(buf: &mut Vec) { + buf.push(OP_BLOCK); + buf.push(TYPE_VOID_BLOCK); +} + +#[no_mangle] +pub fn wg_block_end(buf: &mut Vec) { + buf.push(OP_END); +} + +#[no_mangle] +pub fn wg_return(buf: &mut Vec) { + buf.push(OP_RETURN); +} + +#[no_mangle] +pub fn wg_drop(buf: &mut Vec) { + buf.push(OP_DROP); +} + +// Generate a br_table where an input of [i] will branch [i]th outer block, +// where [i] is passed on the wasm stack +#[no_mangle] +pub fn wg_brtable_and_cases(buf: &mut Vec, cases_count: i32) { + assert!(cases_count >= 0); + + buf.push(OP_BRTABLE); + write_leb_u32(buf, cases_count as u32); + + for i in 0..(cases_count + 1) { + write_leb_u32(buf, i as u32); + } +} + +#[no_mangle] +pub fn wg_br(buf: &mut Vec, depth: i32) { + buf.push(OP_BR); + write_leb_i32(buf, depth); +} + +#[no_mangle] +pub fn wg_get_local(buf: &mut Vec, idx: i32) { + buf.push(OP_GETLOCAL); + write_leb_i32(buf, idx); +} + +#[no_mangle] +pub fn wg_set_local(buf: &mut Vec, idx: i32) { + buf.push(OP_SETLOCAL); + write_leb_i32(buf, idx); +} + +#[no_mangle] +pub fn wg_unreachable(buf: &mut Vec) { + buf.push(OP_UNREACHABLE); +} + +#[no_mangle] +pub fn wg_increment_mem32(buf: &mut Vec, addr: i32) { + wg_increment_variable(buf, addr, 1) +} + +#[no_mangle] +pub fn wg_increment_variable(buf: &mut Vec, addr: i32, n: i32) { + wg_push_i32(buf, addr); + wg_load_aligned_i32(buf, addr as u32); + wg_push_i32(buf, n); + wg_add_i32(buf); + wg_store_aligned_i32(buf); +} + +#[no_mangle] +pub fn wg_load_aligned_u16_from_stack(buf: &mut Vec, byte_offset: u32) { + buf.push(OP_I32LOAD16U); + buf.push(MEM_ALIGN16); + write_leb_u32(buf, byte_offset); +} From 95a65153f423198739b986c1b68bb54ca3714e6f Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Fri, 22 Jun 2018 21:54:28 +0530 Subject: [PATCH 0962/2137] fix commit_instruction_body_to_cs --- Makefile | 2 +- src/browser/starter.js | 6 +++-- src/native/codegen/codegen.c | 11 +++------ src/native/codegen/codegen.h | 1 - src/native/codegen/wasmgen.h | 4 +++- src/native/cpu.c | 14 ++++++------ src/wasmgen/src/c_api.rs | 41 +++++++++++++++++----------------- src/wasmgen/src/module_init.rs | 21 ++++++++--------- 8 files changed, 50 insertions(+), 50 deletions(-) diff --git a/Makefile b/Makefile index 120247e4..3115259b 100644 --- a/Makefile +++ b/Makefile @@ -108,7 +108,7 @@ CORE_FILES=const.js config.js io.js main.js lib.js coverage.js ide.js pci.js flo memory.js 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 debug.js \ - elf.js codegen.js + elf.js LIB_FILES=9p.js filesystem.js jor1k.js marshall.js utf8.js BROWSER_FILES=screen.js \ keyboard.js mouse.js serial.js \ diff --git a/src/browser/starter.js b/src/browser/starter.js index 229322fe..c337fe6c 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -259,7 +259,7 @@ function V86Starter(options) "Infinity": Infinity, "NaN": NaN, }; - + const wasmgen_mem = new WebAssembly.Memory({ initial: 10000 }); const wasmgen_externs = { "memory": wasmgen_mem, @@ -287,7 +287,9 @@ function V86Starter(options) } const wasmgen_exports = [ - "new_buf", + "get_cs", + "get_instruction_body", + "commit_instruction_body_to_cs", "finish", "reset", "get_fn_idx", diff --git a/src/native/codegen/codegen.c b/src/native/codegen/codegen.c index e6a98086..0419786e 100644 --- a/src/native/codegen/codegen.c +++ b/src/native/codegen/codegen.c @@ -4,6 +4,7 @@ #include "../const.h" #include "../cpu.h" +#include "../log.h" #include "../global_pointers.h" #include "wasmgen.h" #include "codegen.h" @@ -16,8 +17,8 @@ PackedStr pack_str(char const* fn_name, uint8_t fn_len); void gen_reset(void) { wg_reset(); - cs = wg_new_buf(); - instruction_body = wg_new_buf(); + cs = wg_get_cs(); + instruction_body = wg_get_instruction_body(); add_get_seg_import(); } @@ -712,9 +713,3 @@ void gen_modrm_fn0(char const* fn, uint8_t fn_len) wg_call_fn(instruction_body, fn_idx); } -void gen_commit_instruction_body_to_cs(void) -{ - wg_include_buffer(cs); - wg_include_buffer(instruction_body); -} - diff --git a/src/native/codegen/codegen.h b/src/native/codegen/codegen.h index 19ef9256..ecba9a66 100644 --- a/src/native/codegen/codegen.h +++ b/src/native/codegen/codegen.h @@ -83,6 +83,5 @@ void gen_increment_instruction_pointer(int32_t); void gen_increment_timestamp_counter(uint32_t); -void gen_commit_instruction_body_to_cs(void); void gen_clear_prefixes(void); void gen_add_prefix_bits(int32_t); diff --git a/src/native/codegen/wasmgen.h b/src/native/codegen/wasmgen.h index f9668c2d..d7061024 100644 --- a/src/native/codegen/wasmgen.h +++ b/src/native/codegen/wasmgen.h @@ -9,7 +9,9 @@ typedef struct PackedStr { #define PSTR_TY uint64_t, uint64_t -extern uint8_t* wg_new_buf(void); +extern uint8_t* wg_get_cs(void); +extern uint8_t* wg_get_instruction_body(void); +extern void wg_commit_instruction_body_to_cs(void); extern void wg_finish(uint8_t no_of_locals_i32); extern void wg_reset(void); extern uint16_t wg_get_fn_idx(PSTR_TY, uint8_t fn_type); diff --git a/src/native/cpu.c b/src/native/cpu.c index 8b988c8e..ade2cd7e 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -881,7 +881,7 @@ static void jit_generate_basic_block(int32_t start_addr, int32_t stop_addr) // eip += eip_delta + len(jump) so instruction logic uses the correct eip gen_increment_instruction_pointer(eip_delta + instruction_length); - gen_commit_instruction_body_to_cs(); + wg_commit_instruction_body_to_cs(); eip_delta = 0; } @@ -891,7 +891,7 @@ static void jit_generate_basic_block(int32_t start_addr, int32_t stop_addr) // prev_ip = eip + eip_delta, so that previous_ip points to the start of this instruction gen_set_previous_eip_offset_from_eip(eip_delta); - gen_commit_instruction_body_to_cs(); + wg_commit_instruction_body_to_cs(); // Leave this instruction's length to be updated in the next batch, whatever it may be eip_delta += instruction_length; @@ -907,7 +907,7 @@ static void jit_generate_basic_block(int32_t start_addr, int32_t stop_addr) UNUSED(eip_delta); gen_set_previous_eip(); gen_increment_instruction_pointer(instruction_length); - gen_commit_instruction_body_to_cs(); + wg_commit_instruction_body_to_cs(); #endif end_addr = *instruction_pointer; len++; @@ -930,7 +930,7 @@ static void jit_generate_basic_block(int32_t start_addr, int32_t stop_addr) // When the block ends in a non-jump instruction, we may have uncommitted updates still if(eip_delta > 0) { - gen_commit_instruction_body_to_cs(); + wg_commit_instruction_body_to_cs(); gen_increment_instruction_pointer(eip_delta); } #endif @@ -1574,9 +1574,9 @@ static void jit_generate(uint32_t phys_addr) } else { - gen_commit_instruction_body_to_cs(); + wg_commit_instruction_body_to_cs(); jit_generate_basic_block(block.addr, next_block_start); - gen_commit_instruction_body_to_cs(); + wg_commit_instruction_body_to_cs(); } bool invalid_connection_to_next_block = next_block_start != *instruction_pointer; @@ -1670,7 +1670,7 @@ static void jit_generate(uint32_t phys_addr) wg_block_end(instruction_body); // loop - gen_commit_instruction_body_to_cs(); + wg_commit_instruction_body_to_cs(); wg_finish(GEN_NO_OF_LOCALS); cached_state_flags state_flags = pack_current_state_flags(); diff --git a/src/wasmgen/src/c_api.rs b/src/wasmgen/src/c_api.rs index 01dc2a64..f2c9ab4c 100644 --- a/src/wasmgen/src/c_api.rs +++ b/src/wasmgen/src/c_api.rs @@ -3,9 +3,13 @@ use ::util::PackedStr; pub use ::module_init::{ setup, get_module }; #[no_mangle] -pub fn new_buf() -> *mut Vec { - let b = Box::new(Vec::with_capacity(256)); - Box::into_raw(b) +pub fn get_cs() -> *mut Vec { + &mut get_module().cs +} + +#[no_mangle] +pub fn get_instruction_body() -> *mut Vec { + &mut get_module().instruction_body } #[no_mangle] @@ -26,12 +30,6 @@ pub fn get_fn_idx(fn_name: PackedStr, type_idx: u8) -> u16 { m.get_fn_index(fn_name, type_idx) } -#[no_mangle] -pub fn include_buffer(buf: *mut Vec) { - let m = get_module(); - m.include_buffer(buf); -} - #[no_mangle] pub fn get_op_ptr() -> *const u8 { let m = get_module(); @@ -44,6 +42,12 @@ pub fn get_op_len() -> usize { m.get_op_len() } +#[no_mangle] +pub fn commit_instruction_body_to_cs() { + let m = get_module(); + m.commit_instruction_body_cs(); +} + #[cfg(test)] mod tests { use std::io::prelude::*; @@ -56,23 +60,20 @@ mod tests { #[test] fn c_api_test() { setup(); - let buf1 = unsafe { new_buf().as_mut().expect("get buf1") }; - let buf2 = unsafe { new_buf().as_mut().expect("get buf2") }; + let cs = &mut get_module().cs; + let instruction_body = &mut get_module().instruction_body; - wg_fn0_const_ret(buf1, pack_str("foo")); - wg_fn0_const_ret(buf1, pack_str("bar")); - - include_buffer(buf1); + wg_fn0_const_ret(cs, pack_str("foo")); + wg_fn0_const_ret(cs, pack_str("bar")); finish(2); reset(); - wg_push_i32(buf1, 2); - wg_call_fn1_ret(buf2, pack_str("baz")); - wg_drop(buf2); + wg_push_i32(cs, 2); + wg_call_fn1_ret(instruction_body, pack_str("baz")); + wg_drop(instruction_body); - include_buffer(buf1); - include_buffer(buf2); + commit_instruction_body_to_cs(); finish(1); diff --git a/src/wasmgen/src/module_init.rs b/src/wasmgen/src/module_init.rs index 5eca7572..dd874eb7 100644 --- a/src/wasmgen/src/module_init.rs +++ b/src/wasmgen/src/module_init.rs @@ -36,7 +36,8 @@ pub fn get_module<'a>() -> &'a mut WasmBuilder { pub struct WasmBuilder { pub op: Vec, - pub buffers: Vec<*mut Vec>, + pub cs: Vec, + pub instruction_body: Vec, idx_import_table_size: usize, // for rewriting once finished idx_import_count: usize, // for rewriting once finished @@ -52,7 +53,8 @@ impl WasmBuilder { pub fn new() -> Self { WasmBuilder { op: Vec::with_capacity(256), - buffers: Vec::with_capacity(64), + cs: Vec::with_capacity(256), + instruction_body: Vec::with_capacity(256), idx_import_table_size: 0, idx_import_count: 0, @@ -82,11 +84,8 @@ impl WasmBuilder { self.op.drain(self.initial_static_size..); self.set_import_table_size(2); self.set_import_count(0); - self.buffers.drain(..); - } - - pub fn include_buffer(&mut self, buf: *mut Vec) { - self.buffers.push(buf); + self.cs.drain(..); + self.instruction_body.drain(..); } pub fn finish(&mut self, no_of_locals_i32: u8) -> usize { @@ -111,9 +110,7 @@ impl WasmBuilder { self.op.push(1); // count of local blocks self.op.push(no_of_locals_i32); self.op.push(TYPE_I32); - for buf_ptr in &mut self.buffers { - self.op.append(unsafe { buf_ptr.as_mut().expect("unloading buffer") }); - } + self.op.append(&mut self.cs); self.op.push(OP_END); @@ -320,6 +317,10 @@ impl WasmBuilder { self.op.len() } + pub fn commit_instruction_body_cs(&mut self) { + self.cs.append(&mut self.instruction_body); + } + } #[cfg(test)] From fc7f4b468c39898d47321b3b749beb2c43ef9117 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Fri, 22 Jun 2018 22:03:45 +0530 Subject: [PATCH 0963/2137] add wasmgen tests to makefile --- Makefile | 16 ++++------------ tests/codegen/codegen.js | 3 +++ 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 3115259b..20c3d252 100644 --- a/Makefile +++ b/Makefile @@ -237,14 +237,8 @@ build/wasmgen-debug.wasm: src/wasmgen/src/*.rs src/wasmgen/Cargo.toml mv src/wasmgen/target/wasm32-unknown-unknown/debug/wasmgen.wasm build/wasmgen-debug.wasm ls -lh build/wasmgen-debug.wasm -build/codegen-test.wasm: src/native/*.c src/native/*.h src/native/codegen/*.c src/native/codegen/*.h - mkdir -p build - -ls -lh build/codegen-test.wasm - emcc src/native/codegen/codegen.c \ - $(CC_FLAGS) \ - -Os \ - -o build/codegen-test.wasm - ls -lh build/codegen-test.wasm +wasmgen-test: + (cd src/wasmgen && env RUST_BACKTRACE=full RUST_TEST_THREADS=1 cargo test -- --nocapture) clean: -rm build/libv86.js @@ -252,7 +246,8 @@ clean: -rm build/v86_all.js -rm build/v86.wasm -rm build/v86-debug.wasm - -rm build/codegen-test.wasm + -rm build/wasmgen.wasm + -rm build/wasmgen-debug.wasm -rm $(INSTRUCTION_TABLES) -rm $(addsuffix .bak,$(INSTRUCTION_TABLES)) -rm $(addsuffix .diff,$(INSTRUCTION_TABLES)) @@ -312,9 +307,6 @@ kvm-unit-test: build/libv86-debug.js build/v86-debug.wasm $(MAKE) -C tests/kvm-unit-tests tests/kvm-unit-tests/run.js tests/kvm-unit-tests/x86/realmode.flat -codegen-test: build/codegen-test.wasm - ./tests/codegen/codegen.js - expect-tests: build/libv86-debug.js build/v86-debug.wasm build/libwabt.js make -C tests/expect/tests ./tests/expect/run.js diff --git a/tests/codegen/codegen.js b/tests/codegen/codegen.js index 0d14dec4..5bf51812 100755 --- a/tests/codegen/codegen.js +++ b/tests/codegen/codegen.js @@ -1,4 +1,7 @@ #!/usr/bin/env node + +//XXX: this file is currently unused, fold these tests into the wasmgen tests + "use strict"; process.on("unhandledRejection", exn => { throw exn; }); From e96792ca8438ce8f26321633515987007b68f48d Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Fri, 22 Jun 2018 22:30:49 +0530 Subject: [PATCH 0964/2137] increase fn name length limit to 24 --- src/native/codegen/codegen.c | 6 +++--- src/native/codegen/wasmgen.h | 3 ++- src/wasmgen/src/c_api.rs | 3 ++- src/wasmgen/src/util.rs | 10 +++++----- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/native/codegen/codegen.c b/src/native/codegen/codegen.c index 0419786e..f5c05693 100644 --- a/src/native/codegen/codegen.c +++ b/src/native/codegen/codegen.c @@ -31,11 +31,11 @@ void add_get_seg_import(void) PackedStr pack_str(char const* fn_name, uint8_t fn_len) { - assert(fn_len <= 16); + assert(fn_len <= 24); union { PackedStr pstr; - uint8_t u8s[16]; + uint8_t u8s[24]; } ret = { { 0 } }; for(int i = 0; i < fn_len; i++) @@ -48,7 +48,7 @@ PackedStr pack_str(char const* fn_name, uint8_t fn_len) uint16_t get_fn_idx(char const* fn, uint8_t fn_len, uint8_t fn_type) { PackedStr pstr = pack_str(fn, fn_len); - return wg_get_fn_idx(pstr.a, pstr.b, fn_type); + return wg_get_fn_idx(pstr.a, pstr.b, pstr.c, fn_type); } void gen_increment_mem32(int32_t addr) diff --git a/src/native/codegen/wasmgen.h b/src/native/codegen/wasmgen.h index d7061024..12960569 100644 --- a/src/native/codegen/wasmgen.h +++ b/src/native/codegen/wasmgen.h @@ -5,9 +5,10 @@ typedef struct PackedStr { uint64_t a; uint64_t b; + uint64_t c; } PackedStr; -#define PSTR_TY uint64_t, uint64_t +#define PSTR_TY uint64_t, uint64_t, uint64_t extern uint8_t* wg_get_cs(void); extern uint8_t* wg_get_instruction_body(void); diff --git a/src/wasmgen/src/c_api.rs b/src/wasmgen/src/c_api.rs index f2c9ab4c..117a7e8a 100644 --- a/src/wasmgen/src/c_api.rs +++ b/src/wasmgen/src/c_api.rs @@ -25,7 +25,8 @@ pub fn finish(no_of_locals_i32: u8) { } #[no_mangle] -pub fn get_fn_idx(fn_name: PackedStr, type_idx: u8) -> u16 { +pub fn get_fn_idx(fn_name_a: u64, fn_name_b: u64, fn_name_c: u64, type_idx: u8) -> u16 { + let fn_name: PackedStr = (fn_name_a, fn_name_b, fn_name_c); let m = get_module(); m.get_fn_index(fn_name, type_idx) } diff --git a/src/wasmgen/src/util.rs b/src/wasmgen/src/util.rs index 0b259373..7b2846f4 100644 --- a/src/wasmgen/src/util.rs +++ b/src/wasmgen/src/util.rs @@ -53,12 +53,12 @@ pub fn write_fixed_leb32_at_idx(vec: &mut Vec, idx: usize, x: u32) { vec[idx + 3] = (x >> 21 & 0b1111111) as u8; } -pub type PackedStr = (u64, u64); +pub type PackedStr = (u64, u64, u64); #[allow(dead_code)] pub fn pack_str(s: &str) -> PackedStr { assert!(s.len() <= 16); - let mut a: [u8; 16] = [0; 16]; + let mut a: [u8; 24] = [0; 24]; for (i, ch) in s.char_indices() { a[i] = ch as u8; } @@ -67,9 +67,9 @@ pub fn pack_str(s: &str) -> PackedStr { } pub fn unpack_str(s: PackedStr) -> String { - let mut buf = String::with_capacity(16); - let bytes: [u8; 16] = unsafe { ::std::mem::transmute(s) }; - for i in 0..16 { + let mut buf = String::with_capacity(24); + let bytes: [u8; 24] = unsafe { ::std::mem::transmute(s) }; + for i in 0..24 { if bytes[i] == 0 { break; } From 2aeb9960a3f9eed853d6171fa1fad4c9f5d46cc1 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Fri, 22 Jun 2018 23:00:22 +0530 Subject: [PATCH 0965/2137] fix fn type in rust --- src/debug.js | 14 ++++++++++++++ src/wasmgen/src/module_init.rs | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/debug.js b/src/debug.js index 900d1b7e..2e36c641 100644 --- a/src/debug.js +++ b/src/debug.js @@ -748,6 +748,19 @@ CPU.prototype.debug_init = function() } }; + function dump_file(ab, name) + { + var blob = new Blob([ab]); + + var a = document.createElement("a"); + a["download"] = name; + a.href = window.URL.createObjectURL(blob); + a.dataset["downloadurl"] = ["application/octet-stream", a["download"], a.href].join(":"); + + a.click(); + window.URL.revokeObjectURL(a.src); + } + debug.dump_wasm = function(buffer) { if(typeof wabt === "undefined") @@ -770,6 +783,7 @@ CPU.prototype.debug_init = function() } catch(e) { + dump_file(buffer, "failed.wasm"); console.log(e.toString()); } finally diff --git a/src/wasmgen/src/module_init.rs b/src/wasmgen/src/module_init.rs index dd874eb7..79658fc7 100644 --- a/src/wasmgen/src/module_init.rs +++ b/src/wasmgen/src/module_init.rs @@ -273,7 +273,7 @@ impl WasmBuilder { self.op.push(1 + count); // length of this section self.op.push(count); // count of signature indices for _ in 0..count { - self.op.push(FN0_TYPE_INDEX); + self.op.push(FN1_TYPE_INDEX); } } From 345f979287d328ac6fc71ea619cff5cc4d76624c Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 26 Jun 2018 00:18:27 +0530 Subject: [PATCH 0966/2137] use a sane number of pages in wasmgen memory --- src/browser/starter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index c337fe6c..6e2e7f8d 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -260,7 +260,7 @@ function V86Starter(options) "NaN": NaN, }; - const wasmgen_mem = new WebAssembly.Memory({ initial: 10000 }); + const wasmgen_mem = new WebAssembly.Memory({ "initial": 10 }); const wasmgen_externs = { "memory": wasmgen_mem, "log_from_wasm": function(offset, len) { From 863c0207856e63a365d5486a488567ea161edbda Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 26 Jun 2018 00:19:42 +0530 Subject: [PATCH 0967/2137] delete codegen test --- tests/codegen/codegen.js | 137 --------------------------------------- 1 file changed, 137 deletions(-) delete mode 100755 tests/codegen/codegen.js diff --git a/tests/codegen/codegen.js b/tests/codegen/codegen.js deleted file mode 100755 index 5bf51812..00000000 --- a/tests/codegen/codegen.js +++ /dev/null @@ -1,137 +0,0 @@ -#!/usr/bin/env node - -//XXX: this file is currently unused, fold these tests into the wasmgen tests - -"use strict"; - -process.on("unhandledRejection", exn => { throw exn; }); - -const fs = require("fs"); - -global.v86util = {}; - -// copied from const.js -global.WASM_TABLE_SIZE = 0x10000; -// The space we need for misc internal state before the beginning of mem8; see global_pointers.h -global.GUEST_MEMORY_START = 0x10000 + 0x100000 * 6; -global.WASM_PAGE_SIZE = 64 * 1024; - -global.dbg_assert = x => console.assert(x); - -require("../../src/browser/lib.js"); - -const Codegen = require("../../src/codegen.js"); - -const codegen_module_buffer = fs.readFileSync(__dirname + "/../../build/codegen-test.wasm"); - -const vals = { - imm8: 1, - imm8s: 1, - imm16: 2, - imm32s: 3, - asize_32: false, - reg16: 4, - reg32s: 4, - instruction_pointer: 556, - previous_ip: 560, - prefixes: 0, - timestamp_counter: 0, -}; - -const wasm_test_funcs = { - 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; }, - _has_flat_segmentation() { return false; }, - _printf(...args) { console.log(...args); }, - ___assert_fail(...args) { console.error(...args); console.assert(false); }, - abort() { console.assert(false); }, - }, -}; - -const memory_size = 256 * 1024 * 1024; - -v86util.load_wasm( - "build/codegen-test.wasm", - wasm_test_funcs, - memory_size + GUEST_MEMORY_START, - WASM_TABLE_SIZE, - wm => { - try { - test(new Codegen(wm)); - } catch(er) { - console.error(er); - process.exit(1); - } - } -); - -function test(gen) -{ - gen.reset(); - gen.fn0("fn0"); - gen.fn0("fn0_test_eip_order"); - gen.fn1("fn1", 0); - gen.fn2("fn2", 0, 1); - gen.increment_instruction_pointer(10); - gen.set_previous_eip(); - - gen.commit_instruction_body_to_cs(); - - gen.modrm_fn0("fn1r"); - gen.modrm_fn1("fn2r", 2); - vals.asize_32 = !vals.asize_32; - gen.modrm_fn0("fn1r"); - gen.modrm_fn1("fn2r", 2); - - gen.commit_instruction_body_to_cs(); - // Test instruction_body buffer separation by leaving the following uncomitted: - gen.fn0("fn0"); - gen.finish(); - - let buf = gen.get_module_code(); - fs.writeFileSync(__dirname + "/../../build/codegen-test-output.wasm", buf); - - const module = new WebAssembly.Module(buf); - - const expected = [ - ["fn0"], - ["fn0_test_eip_order"], - ["fn1", 0], - ["fn2", 0, 1], - ["fn1r", 0], - ["fn2r", 0, 0], - ["fn1r", 0], - ["fn2r", 0, 0], - ]; - - const store = []; - - const imports = { - e: { - fn0() { store.push(["fn0"]); }, - fn1(arg0) { store.push(["fn1", arg0]); }, - fn2(arg0, arg1) { store.push(["fn2", arg0, arg1]); }, - fn1r(arg0) { store.push(["fn1r", arg0]); }, - fn2r(arg0, arg1) { store.push(["fn2r", arg0, arg1]); }, - get_seg() {}, - m: new WebAssembly.Memory({ initial: memory_size / 64 / 1024 }), - }, - }; - const view = new Uint32Array(imports.e.m.buffer); - imports.e.fn0_test_eip_order = function() - { - store.push(["fn0_test_eip_order"]); - // Since fn0 was commited from the instruction_body buffer _after_ the instruction pointer updates - console.assert(view[vals.instruction_pointer >> 2] === 10); - console.assert(view[vals.previous_ip >> 2] === 10); - }; - - const o = new WebAssembly.Instance(module, imports); - o.exports.f(); - console.log(store); - console.assert(JSON.stringify(store) === JSON.stringify(expected)); -} From 75ed04e959e8af7dd7ab04578771db2c7f3ab7b2 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 26 Jun 2018 00:20:56 +0530 Subject: [PATCH 0968/2137] copy wasmgen bins instead of moving --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 20c3d252..885415b1 100644 --- a/Makefile +++ b/Makefile @@ -227,14 +227,14 @@ build/wasmgen.wasm: src/wasmgen/src/*.rs src/wasmgen/Cargo.toml mkdir -p build/ -ls -lh build/wasmgen.wasm (cd src/wasmgen && cargo +nightly rustc --release --target wasm32-unknown-unknown -- -Clink-args="--import-memory") - mv src/wasmgen/target/wasm32-unknown-unknown/release/wasmgen.wasm build/wasmgen.wasm + cp src/wasmgen/target/wasm32-unknown-unknown/release/wasmgen.wasm build/wasmgen.wasm ls -lh build/wasmgen.wasm build/wasmgen-debug.wasm: src/wasmgen/src/*.rs src/wasmgen/Cargo.toml mkdir -p build/ -ls -lh build/wasmgen-debug.wasm (cd src/wasmgen && cargo +nightly rustc --target wasm32-unknown-unknown -- -Clink-args="--import-memory") - mv src/wasmgen/target/wasm32-unknown-unknown/debug/wasmgen.wasm build/wasmgen-debug.wasm + cp src/wasmgen/target/wasm32-unknown-unknown/debug/wasmgen.wasm build/wasmgen-debug.wasm ls -lh build/wasmgen-debug.wasm wasmgen-test: From 7be3803590d28919bd32243a78c9a5997bd7e7e2 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 26 Jun 2018 00:28:24 +0530 Subject: [PATCH 0969/2137] add wg_ prefix to rust exports --- src/browser/starter.js | 33 ++++++++++----------------------- src/cpu.js | 4 ++-- src/wasmgen/src/c_api.rs | 28 ++++++++++++++-------------- 3 files changed, 26 insertions(+), 39 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 6e2e7f8d..04036f53 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -260,7 +260,7 @@ function V86Starter(options) "NaN": NaN, }; - const wasmgen_mem = new WebAssembly.Memory({ "initial": 10 }); + const wasmgen_mem = new WebAssembly.Memory({ "initial": 100 }); const wasmgen_externs = { "memory": wasmgen_mem, "log_from_wasm": function(offset, len) { @@ -287,13 +287,13 @@ function V86Starter(options) } const wasmgen_exports = [ - "get_cs", - "get_instruction_body", - "commit_instruction_body_to_cs", - "finish", - "reset", - "get_fn_idx", - "include_buffer", + "wg_get_cs", + "wg_get_instruction_body", + "wg_commit_instruction_body_to_cs", + "wg_finish", + "wg_reset", + "wg_get_fn_idx", + "wg_include_buffer", "wg_push_i32", "wg_push_u32", @@ -348,24 +348,11 @@ function V86Starter(options) "wg_call_fn2", ]; - function reexport_wasmgen_functions(wasmgen) { + v86util.minimal_load_wasm(wasmgen_bin, { "env": wasmgen_externs }, (wasmgen) => { for(const fn_name of wasmgen_exports) { - if(fn_name.startsWith("wg_")) - { - // used as is via C - wasm_shared_funcs[`_${fn_name}`] = wasmgen.exports[fn_name]; - } - else - { - // prefix "wg_" attached by JS - wasm_shared_funcs[`_wg_${fn_name}`] = wasmgen.exports[fn_name]; - } + wasm_shared_funcs[`_${fn_name}`] = wasmgen.exports[fn_name]; } - } - - v86util.minimal_load_wasm(wasmgen_bin, { "env": wasmgen_externs }, (wasmgen) => { - reexport_wasmgen_functions(wasmgen); wasmgen.exports["setup"](); //XXX: fix indentation break diff --git a/src/cpu.js b/src/cpu.js index 606c7105..639d7dbe 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -217,8 +217,8 @@ function CPU(bus, wm, wasmgen, coverage_logger) CPU.prototype.wasmgen_get_module_code = function() { - const ptr = this.wasmgen.exports["get_op_ptr"](); - const len = this.wasmgen.exports["get_op_len"](); + const ptr = this.wasmgen.exports["wg_get_op_ptr"](); + const len = this.wasmgen.exports["wg_get_op_len"](); const output_buffer_view = new Uint8Array(this.wasmgen.memory.buffer, ptr, len); return output_buffer_view; diff --git a/src/wasmgen/src/c_api.rs b/src/wasmgen/src/c_api.rs index 117a7e8a..a9358a67 100644 --- a/src/wasmgen/src/c_api.rs +++ b/src/wasmgen/src/c_api.rs @@ -3,48 +3,48 @@ use ::util::PackedStr; pub use ::module_init::{ setup, get_module }; #[no_mangle] -pub fn get_cs() -> *mut Vec { +pub fn wg_get_cs() -> *mut Vec { &mut get_module().cs } #[no_mangle] -pub fn get_instruction_body() -> *mut Vec { +pub fn wg_get_instruction_body() -> *mut Vec { &mut get_module().instruction_body } #[no_mangle] -pub fn reset() { +pub fn wg_reset() { let m = get_module(); m.reset(); } #[no_mangle] -pub fn finish(no_of_locals_i32: u8) { +pub fn wg_finish(no_of_locals_i32: u8) { let m = get_module(); m.finish(no_of_locals_i32); } #[no_mangle] -pub fn get_fn_idx(fn_name_a: u64, fn_name_b: u64, fn_name_c: u64, type_idx: u8) -> u16 { +pub fn wg_get_fn_idx(fn_name_a: u64, fn_name_b: u64, fn_name_c: u64, type_idx: u8) -> u16 { let fn_name: PackedStr = (fn_name_a, fn_name_b, fn_name_c); let m = get_module(); m.get_fn_index(fn_name, type_idx) } #[no_mangle] -pub fn get_op_ptr() -> *const u8 { +pub fn wg_get_op_ptr() -> *const u8 { let m = get_module(); m.get_op_ptr() } #[no_mangle] -pub fn get_op_len() -> usize { +pub fn wg_get_op_len() -> usize { let m = get_module(); m.get_op_len() } #[no_mangle] -pub fn commit_instruction_body_to_cs() { +pub fn wg_commit_instruction_body_to_cs() { let m = get_module(); m.commit_instruction_body_cs(); } @@ -67,19 +67,19 @@ mod tests { wg_fn0_const_ret(cs, pack_str("foo")); wg_fn0_const_ret(cs, pack_str("bar")); - finish(2); - reset(); + wg_finish(2); + wg_reset(); wg_push_i32(cs, 2); wg_call_fn1_ret(instruction_body, pack_str("baz")); wg_drop(instruction_body); - commit_instruction_body_to_cs(); + wg_commit_instruction_body_to_cs(); - finish(1); + wg_finish(1); - let op_ptr = get_op_ptr(); - let op_len = get_op_len(); + let op_ptr = wg_get_op_ptr(); + let op_len = wg_get_op_len(); dbg_log!("op_ptr: {:?}, op_len: {:?}", op_ptr, op_len); // XXX: move file path From 43832da9204e599da11f5aa37929318057e6083e Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 26 Jun 2018 00:29:52 +0530 Subject: [PATCH 0970/2137] remove unused binding --- src/browser/starter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 04036f53..772d4ca2 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -293,7 +293,6 @@ function V86Starter(options) "wg_finish", "wg_reset", "wg_get_fn_idx", - "wg_include_buffer", "wg_push_i32", "wg_push_u32", @@ -351,6 +350,7 @@ function V86Starter(options) v86util.minimal_load_wasm(wasmgen_bin, { "env": wasmgen_externs }, (wasmgen) => { for(const fn_name of wasmgen_exports) { + dbg_assert(typeof wasmgen.exports[fn_name] === "function"); wasm_shared_funcs[`_${fn_name}`] = wasmgen.exports[fn_name]; } wasmgen.exports["setup"](); From a62573fa013bbcdd0cdb20cef1852295d3ed338b Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 26 Jun 2018 00:37:00 +0530 Subject: [PATCH 0971/2137] minor rust fixes --- src/wasmgen/src/dbg.rs | 10 +++++----- src/wasmgen/src/module_init.rs | 13 +++++++------ src/wasmgen/src/util.rs | 2 +- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/wasmgen/src/dbg.rs b/src/wasmgen/src/dbg.rs index 7b10de90..d99937c1 100644 --- a/src/wasmgen/src/dbg.rs +++ b/src/wasmgen/src/dbg.rs @@ -28,7 +28,7 @@ extern "C" { use std::string::ToString; #[cfg(target_arch = "wasm32")] -pub fn __log_to_js_console(s: T) { +pub fn _log_to_js_console(s: T) { let s: String = s.to_string(); let len = s.len(); unsafe { log_from_wasm(s.as_bytes().as_ptr(), len); } @@ -37,10 +37,10 @@ pub fn __log_to_js_console(s: T) { #[cfg(target_arch = "wasm32")] macro_rules! dbg_log { ($fmt:expr) => { - if DEBUG { __log_to_js_console($fmt); } + if DEBUG { _log_to_js_console($fmt); } }; ($fmt:expr, $($arg:tt)*) => { - if DEBUG { __log_to_js_console(format!($fmt, $($arg)*)); } + if DEBUG { _log_to_js_console(format!($fmt, $($arg)*)); } }; } @@ -48,7 +48,7 @@ macro_rules! dbg_log { macro_rules! dbg_assert { ($cond:expr) => { if DEBUG && !$cond { - __log_to_js_console(format!( + _log_to_js_console(format!( "Assertion failed at {}:{}:{}: '{}'", file!(), line!(), column!(), stringify!($cond), @@ -58,7 +58,7 @@ macro_rules! dbg_assert { }; ($cond:expr, $desc:expr) => { if DEBUG && !$cond { - __log_to_js_console(format!( + _log_to_js_console(format!( "Assertion failed at {}:{}:{}: '{}' - '{}'", file!(), line!(), column!(), stringify!($cond), diff --git a/src/wasmgen/src/module_init.rs b/src/wasmgen/src/module_init.rs index 79658fc7..9a8ba846 100644 --- a/src/wasmgen/src/module_init.rs +++ b/src/wasmgen/src/module_init.rs @@ -84,8 +84,8 @@ impl WasmBuilder { self.op.drain(self.initial_static_size..); self.set_import_table_size(2); self.set_import_count(0); - self.cs.drain(..); - self.instruction_body.drain(..); + self.cs.clear(); + self.instruction_body.clear(); } pub fn finish(&mut self, no_of_locals_i32: u8) -> usize { @@ -108,6 +108,7 @@ impl WasmBuilder { self.op.push(0); self.op.push(0); self.op.push(1); // count of local blocks + dbg_assert!(no_of_locals_i32 < 128); self.op.push(no_of_locals_i32); self.op.push(TYPE_I32); self.op.append(&mut self.cs); @@ -192,13 +193,13 @@ impl WasmBuilder { for i in 0..self.import_count { offset += 1; // skip length of module name offset += 1; // skip module name itself - let len = self.op[offset]; + let len = self.op[offset] as usize; offset += 1; - let name = self.op.get(offset..(offset + len as usize)).expect("get function name"); + let name = self.op.get(offset..(offset + len)).expect("get function name"); if name == fn_name.as_bytes() { return Some(i); } - offset += len as usize; // skip the string + offset += len; // skip the string offset += 1; // skip import kind offset += 1; // skip type index } @@ -209,7 +210,7 @@ impl WasmBuilder { dbg_assert!(count < 0x4000); self.import_count = count; let idx_import_count = self.idx_import_count; - write_fixed_leb16_at_idx(&mut self.op, idx_import_count, count as u16); + write_fixed_leb16_at_idx(&mut self.op, idx_import_count, count); } pub fn set_import_table_size(&mut self, size: usize) { diff --git a/src/wasmgen/src/util.rs b/src/wasmgen/src/util.rs index 7b2846f4..91ce99d9 100644 --- a/src/wasmgen/src/util.rs +++ b/src/wasmgen/src/util.rs @@ -91,4 +91,4 @@ mod tests { assert_eq!("abcdefghijkl", unpack_str(pstr)); } -} \ No newline at end of file +} From 6841703e176233bcde96ff80076ee280e06d4425 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 26 Jun 2018 00:42:52 +0530 Subject: [PATCH 0972/2137] deglob imports --- src/wasmgen/src/codegen.rs | 6 +- src/wasmgen/src/module_init.rs | 64 +++++++++---------- src/wasmgen/src/wasm_util.rs | 108 ++++++++++++++++----------------- 3 files changed, 89 insertions(+), 89 deletions(-) diff --git a/src/wasmgen/src/codegen.rs b/src/wasmgen/src/codegen.rs index efacd442..1c92fae8 100644 --- a/src/wasmgen/src/codegen.rs +++ b/src/wasmgen/src/codegen.rs @@ -1,6 +1,6 @@ -use ::util::*; -use ::wasm_util::*; -use ::module_init::*; +use ::util::PackedStr; +use ::wasm_util::{wg_call_fn, wg_push_i32}; +use ::module_init::{FN0_RET_TYPE_INDEX, FN0_TYPE_INDEX, FN1_RET_TYPE_INDEX, FN1_TYPE_INDEX, FN2_TYPE_INDEX, FN3_TYPE_INDEX, get_module}; // for functions using the global module singleton diff --git a/src/wasmgen/src/module_init.rs b/src/wasmgen/src/module_init.rs index 9a8ba846..0aa735a0 100644 --- a/src/wasmgen/src/module_init.rs +++ b/src/wasmgen/src/module_init.rs @@ -1,7 +1,7 @@ use std::ptr; -use ::util::*; -use ::wasm_opcodes::*; +use ::util::{PackedStr, pack_str, unpack_str, write_fixed_leb16_at_idx, write_fixed_leb32_at_idx, write_leb_u32}; +use ::wasm_opcodes as op; pub const FN0_TYPE_INDEX: u8 = 0; pub const FN1_TYPE_INDEX: u8 = 1; @@ -71,7 +71,7 @@ impl WasmBuilder { self.op.extend("\0asm".as_bytes()); // wasm version in leb128, 4 bytes - self.op.push(WASM_VERSION); self.op.push(0); self.op.push(0); self.op.push(0); + self.op.push(op::WASM_VERSION); self.op.push(0); self.op.push(0); self.op.push(0); self.write_type_section(); self.write_import_section_preamble(); @@ -94,7 +94,7 @@ impl WasmBuilder { self.write_export_section(); // write code section preamble - self.op.push(SC_CODE); + self.op.push(op::SC_CODE); let idx_code_section_size = self.op.len(); // we will write to this location later self.op.push(0); self.op.push(0); // write temp val for now using 4 bytes @@ -109,11 +109,11 @@ impl WasmBuilder { self.op.push(1); // count of local blocks dbg_assert!(no_of_locals_i32 < 128); - self.op.push(no_of_locals_i32); self.op.push(TYPE_I32); + self.op.push(no_of_locals_i32); self.op.push(op::TYPE_I32); self.op.append(&mut self.cs); - self.op.push(OP_END); + self.op.push(op::OP_END); // write the actual sizes to the pointer locations stored above. We subtract 4 from the actual // value because the ptr itself points to four bytes @@ -127,7 +127,7 @@ impl WasmBuilder { } pub fn write_type_section(&mut self) { - self.op.push(SC_TYPE); + self.op.push(op::SC_TYPE); let idx_section_size = self.op.len(); self.op.push(0); @@ -135,51 +135,51 @@ impl WasmBuilder { self.op.push(NR_FN_TYPE_INDEXES); // number of type descriptors // FN0 - self.op.push(TYPE_FUNC); + self.op.push(op::TYPE_FUNC); self.op.push(0); // no args self.op.push(0); // no return val // FN1 - self.op.push(TYPE_FUNC); + self.op.push(op::TYPE_FUNC); self.op.push(1); - self.op.push(TYPE_I32); + self.op.push(op::TYPE_I32); self.op.push(0); // FN2 - self.op.push(TYPE_FUNC); + self.op.push(op::TYPE_FUNC); self.op.push(2); - self.op.push(TYPE_I32); - self.op.push(TYPE_I32); + self.op.push(op::TYPE_I32); + self.op.push(op::TYPE_I32); self.op.push(0); // FN3 - self.op.push(TYPE_FUNC); + self.op.push(op::TYPE_FUNC); self.op.push(3); - self.op.push(TYPE_I32); - self.op.push(TYPE_I32); - self.op.push(TYPE_I32); + self.op.push(op::TYPE_I32); + self.op.push(op::TYPE_I32); + self.op.push(op::TYPE_I32); self.op.push(0); // FN0_RET - self.op.push(TYPE_FUNC); + self.op.push(op::TYPE_FUNC); self.op.push(0); self.op.push(1); - self.op.push(TYPE_I32); + self.op.push(op::TYPE_I32); // FN1_RET - self.op.push(TYPE_FUNC); + self.op.push(op::TYPE_FUNC); self.op.push(1); - self.op.push(TYPE_I32); + self.op.push(op::TYPE_I32); self.op.push(1); - self.op.push(TYPE_I32); + self.op.push(op::TYPE_I32); // FN2_RET - self.op.push(TYPE_FUNC); + self.op.push(op::TYPE_FUNC); self.op.push(2); - self.op.push(TYPE_I32); - self.op.push(TYPE_I32); + self.op.push(op::TYPE_I32); + self.op.push(op::TYPE_I32); self.op.push(1); - self.op.push(TYPE_I32); + self.op.push(op::TYPE_I32); let new_len = self.op.len(); let size = (new_len - 1) - idx_section_size; @@ -221,7 +221,7 @@ impl WasmBuilder { } pub fn write_import_section_preamble(&mut self) { - self.op.push(SC_IMPORT); + self.op.push(op::SC_IMPORT); self.idx_import_table_size = self.op.len(); self.op.push(1 | 0b10000000); self.op.push(2); // 2 in 2 byte leb @@ -239,7 +239,7 @@ impl WasmBuilder { self.op.push(1); self.op.push('m' as u8); - self.op.push(EXT_MEMORY); + self.op.push(op::EXT_MEMORY); self.op.push(0); // memory flag, 0 for no maximum memory limit present write_leb_u32(&mut self.op, 256); // initial memory length of 256 pages, takes 2 bytes in leb128 @@ -257,7 +257,7 @@ impl WasmBuilder { let fn_name = unpack_str(fn_name); self.op.push(fn_name.len() as u8); self.op.extend(fn_name.as_bytes()); - self.op.push(EXT_FUNCTION); + self.op.push(op::EXT_FUNCTION); self.op.push(type_index); let new_import_count = self.import_count + 1; @@ -270,7 +270,7 @@ impl WasmBuilder { } pub fn write_function_section(&mut self, count: u8) { - self.op.push(SC_FUNCTION); + self.op.push(op::SC_FUNCTION); self.op.push(1 + count); // length of this section self.op.push(count); // count of signature indices for _ in 0..count { @@ -279,13 +279,13 @@ impl WasmBuilder { } pub fn write_export_section(&mut self) { - self.op.push(SC_EXPORT); + self.op.push(op::SC_EXPORT); self.op.push(1 + 1 + 1 + 1 + 2); // size of this section self.op.push(1); // count of table: just one function exported self.op.push(1); // length of exported function name self.op.push('f' as u8); // function name - self.op.push(EXT_FUNCTION); + self.op.push(op::EXT_FUNCTION); // index of the exported function // function space starts with imports. index of last import is import count - 1 diff --git a/src/wasmgen/src/wasm_util.rs b/src/wasmgen/src/wasm_util.rs index ee120662..fccd1400 100644 --- a/src/wasmgen/src/wasm_util.rs +++ b/src/wasmgen/src/wasm_util.rs @@ -1,15 +1,15 @@ -use ::wasm_opcodes::*; -use ::util::*; +use ::wasm_opcodes as op; +use ::util::{write_fixed_leb16_at_idx, write_leb_i32, write_leb_u32}; #[no_mangle] pub fn wg_push_i32(buf: &mut Vec, v: i32) { - buf.push(OP_I32CONST); + buf.push(op::OP_I32CONST); write_leb_i32(buf, v); } #[no_mangle] pub fn wg_push_u32(buf: &mut Vec, v: u32) { - buf.push(OP_I32CONST); + buf.push(op::OP_I32CONST); write_leb_u32(buf, v); } @@ -18,10 +18,10 @@ pub fn wg_load_aligned_u16(buf: &mut Vec, addr: u32) { // doesn't cause a failure in the generated code, but it will be much slower dbg_assert!((addr & 1) == 0); - buf.push(OP_I32CONST); + buf.push(op::OP_I32CONST); write_leb_u32(buf, addr); - buf.push(OP_I32LOAD16U); - buf.push(MEM_ALIGN16); + buf.push(op::OP_I32LOAD16U); + buf.push(op::MEM_ALIGN16); buf.push(0); // immediate offset } @@ -36,41 +36,41 @@ pub fn wg_load_aligned_i32(buf: &mut Vec, addr: u32) { #[no_mangle] pub fn wg_store_aligned_u16(buf: &mut Vec) { - buf.push(OP_I32STORE16); - buf.push(MEM_ALIGN16); + buf.push(op::OP_I32STORE16); + buf.push(op::MEM_ALIGN16); buf.push(0); // immediate offset } #[no_mangle] pub fn wg_store_aligned_i32(buf: &mut Vec) { - buf.push(OP_I32STORE); - buf.push(MEM_ALIGN32); + buf.push(op::OP_I32STORE); + buf.push(op::MEM_ALIGN32); buf.push(0); // immediate offset } #[no_mangle] pub fn wg_add_i32(buf: &mut Vec) { - buf.push(OP_I32ADD); + buf.push(op::OP_I32ADD); } #[no_mangle] pub fn wg_and_i32(buf: &mut Vec) { - buf.push(OP_I32AND); + buf.push(op::OP_I32AND); } #[no_mangle] pub fn wg_or_i32(buf: &mut Vec) { - buf.push(OP_I32OR); + buf.push(op::OP_I32OR); } #[no_mangle] pub fn wg_shl_i32(buf: &mut Vec) { - buf.push(OP_I32SHL); + buf.push(op::OP_I32SHL); } #[no_mangle] pub fn wg_call_fn(buf: &mut Vec, fn_idx: u16) { - buf.push(OP_CALL); + buf.push(op::OP_CALL); let buf_len = buf.len(); buf.push(0); buf.push(0); write_fixed_leb16_at_idx(buf, buf_len, fn_idx); @@ -84,68 +84,68 @@ pub fn wg_call_fn_with_arg(buf: &mut Vec, fn_idx: u16, arg0: i32) { #[no_mangle] pub fn wg_eq_i32(buf: &mut Vec) { - buf.push(OP_I32EQ); + buf.push(op::OP_I32EQ); } #[no_mangle] pub fn wg_ne_i32(buf: &mut Vec) { - buf.push(OP_I32NE); + buf.push(op::OP_I32NE); } #[no_mangle] pub fn wg_le_i32(buf: &mut Vec) { - buf.push(OP_I32LES); + buf.push(op::OP_I32LES); } #[no_mangle] pub fn wg_lt_i32(buf: &mut Vec) { - buf.push(OP_I32LTS); + buf.push(op::OP_I32LTS); } #[no_mangle] pub fn wg_ge_i32(buf: &mut Vec) { - buf.push(OP_I32GES); + buf.push(op::OP_I32GES); } #[no_mangle] pub fn wg_gt_i32(buf: &mut Vec) { - buf.push(OP_I32GTS); + buf.push(op::OP_I32GTS); } #[no_mangle] pub fn wg_if_i32(buf: &mut Vec) { - buf.push(OP_IF); - buf.push(TYPE_I32); + buf.push(op::OP_IF); + buf.push(op::TYPE_I32); } #[no_mangle] pub fn wg_block_i32(buf: &mut Vec) { - buf.push(OP_BLOCK); - buf.push(TYPE_I32); + buf.push(op::OP_BLOCK); + buf.push(op::TYPE_I32); } #[no_mangle] pub fn wg_tee_local(buf: &mut Vec, idx: i32) { - buf.push(OP_TEELOCAL); + buf.push(op::OP_TEELOCAL); write_leb_i32(buf, idx); } #[no_mangle] pub fn wg_xor_i32(buf: &mut Vec) { - buf.push(OP_I32XOR); + buf.push(op::OP_I32XOR); } #[no_mangle] pub fn wg_load_unaligned_i32_from_stack(buf: &mut Vec, byte_offset: u32) { - buf.push(OP_I32LOAD); - buf.push(MEM_NO_ALIGN); + buf.push(op::OP_I32LOAD); + buf.push(op::MEM_NO_ALIGN); write_leb_u32(buf, byte_offset); } #[no_mangle] pub fn wg_load_aligned_i32_from_stack(buf: &mut Vec, byte_offset: u32) { - buf.push(OP_I32LOAD); - buf.push(MEM_ALIGN32); + buf.push(op::OP_I32LOAD); + buf.push(op::MEM_ALIGN32); write_leb_u32(buf, byte_offset); } @@ -153,62 +153,62 @@ pub fn wg_load_aligned_i32_from_stack(buf: &mut Vec, byte_offset: u32) { // offset. Leaving as-is for the Rust port to cleanup #[no_mangle] pub fn wg_store_unaligned_i32(buf: &mut Vec, byte_offset: u32) { - buf.push(OP_I32STORE); - buf.push(MEM_NO_ALIGN); + buf.push(op::OP_I32STORE); + buf.push(op::MEM_NO_ALIGN); write_leb_u32(buf, byte_offset); } #[no_mangle] pub fn wg_shr_u32(buf: &mut Vec) { - buf.push(OP_I32SHRU); + buf.push(op::OP_I32SHRU); } #[no_mangle] pub fn wg_shr_i32(buf: &mut Vec) { - buf.push(OP_I32SHRS); + buf.push(op::OP_I32SHRS); } #[no_mangle] pub fn wg_eqz_i32(buf: &mut Vec) { - buf.push(OP_I32EQZ); + buf.push(op::OP_I32EQZ); } #[no_mangle] pub fn wg_if_void(buf: &mut Vec) { - buf.push(OP_IF); - buf.push(TYPE_VOID_BLOCK); + buf.push(op::OP_IF); + buf.push(op::TYPE_VOID_BLOCK); } #[no_mangle] pub fn wg_else(buf: &mut Vec) { - buf.push(OP_ELSE); + buf.push(op::OP_ELSE); } #[no_mangle] pub fn wg_loop_void(buf: &mut Vec) { - buf.push(OP_LOOP); - buf.push(TYPE_VOID_BLOCK); + buf.push(op::OP_LOOP); + buf.push(op::TYPE_VOID_BLOCK); } #[no_mangle] pub fn wg_block_void(buf: &mut Vec) { - buf.push(OP_BLOCK); - buf.push(TYPE_VOID_BLOCK); + buf.push(op::OP_BLOCK); + buf.push(op::TYPE_VOID_BLOCK); } #[no_mangle] pub fn wg_block_end(buf: &mut Vec) { - buf.push(OP_END); + buf.push(op::OP_END); } #[no_mangle] pub fn wg_return(buf: &mut Vec) { - buf.push(OP_RETURN); + buf.push(op::OP_RETURN); } #[no_mangle] pub fn wg_drop(buf: &mut Vec) { - buf.push(OP_DROP); + buf.push(op::OP_DROP); } // Generate a br_table where an input of [i] will branch [i]th outer block, @@ -217,7 +217,7 @@ pub fn wg_drop(buf: &mut Vec) { pub fn wg_brtable_and_cases(buf: &mut Vec, cases_count: i32) { assert!(cases_count >= 0); - buf.push(OP_BRTABLE); + buf.push(op::OP_BRTABLE); write_leb_u32(buf, cases_count as u32); for i in 0..(cases_count + 1) { @@ -227,25 +227,25 @@ pub fn wg_brtable_and_cases(buf: &mut Vec, cases_count: i32) { #[no_mangle] pub fn wg_br(buf: &mut Vec, depth: i32) { - buf.push(OP_BR); + buf.push(op::OP_BR); write_leb_i32(buf, depth); } #[no_mangle] pub fn wg_get_local(buf: &mut Vec, idx: i32) { - buf.push(OP_GETLOCAL); + buf.push(op::OP_GETLOCAL); write_leb_i32(buf, idx); } #[no_mangle] pub fn wg_set_local(buf: &mut Vec, idx: i32) { - buf.push(OP_SETLOCAL); + buf.push(op::OP_SETLOCAL); write_leb_i32(buf, idx); } #[no_mangle] pub fn wg_unreachable(buf: &mut Vec) { - buf.push(OP_UNREACHABLE); + buf.push(op::OP_UNREACHABLE); } #[no_mangle] @@ -264,7 +264,7 @@ pub fn wg_increment_variable(buf: &mut Vec, addr: i32, n: i32) { #[no_mangle] pub fn wg_load_aligned_u16_from_stack(buf: &mut Vec, byte_offset: u32) { - buf.push(OP_I32LOAD16U); - buf.push(MEM_ALIGN16); + buf.push(op::OP_I32LOAD16U); + buf.push(op::MEM_ALIGN16); write_leb_u32(buf, byte_offset); } From 2b9244aaef9398beb5e1b50726022aa0ed2310d3 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 26 Jun 2018 01:55:42 +0530 Subject: [PATCH 0973/2137] use NonNull instead of plain ptr::null_mut holy amazing black magic --- src/wasmgen/src/module_init.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/wasmgen/src/module_init.rs b/src/wasmgen/src/module_init.rs index 0aa735a0..0275b2f9 100644 --- a/src/wasmgen/src/module_init.rs +++ b/src/wasmgen/src/module_init.rs @@ -1,4 +1,4 @@ -use std::ptr; +use std::ptr::{NonNull, null_mut}; use ::util::{PackedStr, pack_str, unpack_str, write_fixed_leb16_at_idx, write_fixed_leb32_at_idx, write_leb_u32}; use ::wasm_opcodes as op; @@ -16,13 +16,13 @@ pub const FN2_RET_TYPE_INDEX: u8 = 6; pub const NR_FN_TYPE_INDEXES: u8 = 7; -static mut MODULE_PTR: *mut WasmBuilder = ptr::null_mut(); +static mut MODULE_PTR: NonNull = unsafe { NonNull::new_unchecked(null_mut()) }; #[no_mangle] pub fn setup() { let wm = Box::new(WasmBuilder::new()); unsafe { - MODULE_PTR = Box::into_raw(wm); + MODULE_PTR = NonNull::new(Box::into_raw(wm)).expect("assigning module ptr"); } get_module().init(); } @@ -30,7 +30,7 @@ pub fn setup() { #[no_mangle] pub fn get_module<'a>() -> &'a mut WasmBuilder { unsafe { - MODULE_PTR.as_mut().expect("getting module") + MODULE_PTR.as_mut() } } From eb322bcddf24e292ee768ebf9eae478f639ccded Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 26 Jun 2018 02:15:44 +0530 Subject: [PATCH 0974/2137] rename get_cs --- src/browser/starter.js | 2 +- src/native/codegen/codegen.c | 2 +- src/native/codegen/wasmgen.h | 3 +-- src/wasmgen/src/c_api.rs | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 772d4ca2..49267b5b 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -287,7 +287,7 @@ function V86Starter(options) } const wasmgen_exports = [ - "wg_get_cs", + "wg_get_code_section", "wg_get_instruction_body", "wg_commit_instruction_body_to_cs", "wg_finish", diff --git a/src/native/codegen/codegen.c b/src/native/codegen/codegen.c index f5c05693..b72c2aab 100644 --- a/src/native/codegen/codegen.c +++ b/src/native/codegen/codegen.c @@ -17,7 +17,7 @@ PackedStr pack_str(char const* fn_name, uint8_t fn_len); void gen_reset(void) { wg_reset(); - cs = wg_get_cs(); + cs = wg_get_code_section(); instruction_body = wg_get_instruction_body(); add_get_seg_import(); } diff --git a/src/native/codegen/wasmgen.h b/src/native/codegen/wasmgen.h index 12960569..0191b5f0 100644 --- a/src/native/codegen/wasmgen.h +++ b/src/native/codegen/wasmgen.h @@ -10,13 +10,12 @@ typedef struct PackedStr { #define PSTR_TY uint64_t, uint64_t, uint64_t -extern uint8_t* wg_get_cs(void); +extern uint8_t* wg_get_code_section(void); extern uint8_t* wg_get_instruction_body(void); extern void wg_commit_instruction_body_to_cs(void); extern void wg_finish(uint8_t no_of_locals_i32); extern void wg_reset(void); extern uint16_t wg_get_fn_idx(PSTR_TY, uint8_t fn_type); -extern void wg_include_buffer(uint8_t* buf); extern void wg_push_i32(uint8_t* buf, int32_t v); extern void wg_push_u32(uint8_t* buf, uint32_t v); diff --git a/src/wasmgen/src/c_api.rs b/src/wasmgen/src/c_api.rs index a9358a67..35c0027d 100644 --- a/src/wasmgen/src/c_api.rs +++ b/src/wasmgen/src/c_api.rs @@ -3,7 +3,7 @@ use ::util::PackedStr; pub use ::module_init::{ setup, get_module }; #[no_mangle] -pub fn wg_get_cs() -> *mut Vec { +pub fn wg_get_code_section() -> *mut Vec { &mut get_module().cs } From f3a6c988951b08c63c1a8858c8b83206e7f7caca Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 26 Jun 2018 02:25:44 +0530 Subject: [PATCH 0975/2137] refactoring dbg macros, remove codegen.rs --- src/wasmgen/src/c_api.rs | 11 +++--- src/wasmgen/src/codegen.rs | 70 ---------------------------------- src/wasmgen/src/dbg.rs | 23 ++--------- src/wasmgen/src/lib.rs | 1 - src/wasmgen/src/module_init.rs | 18 +++++---- src/wasmgen/src/util.rs | 21 +++++++++- src/wasmgen/src/wasm_util.rs | 2 +- 7 files changed, 40 insertions(+), 106 deletions(-) delete mode 100644 src/wasmgen/src/codegen.rs diff --git a/src/wasmgen/src/c_api.rs b/src/wasmgen/src/c_api.rs index 35c0027d..4dfc494c 100644 --- a/src/wasmgen/src/c_api.rs +++ b/src/wasmgen/src/c_api.rs @@ -28,7 +28,7 @@ pub fn wg_finish(no_of_locals_i32: u8) { pub fn wg_get_fn_idx(fn_name_a: u64, fn_name_b: u64, fn_name_c: u64, type_idx: u8) -> u16 { let fn_name: PackedStr = (fn_name_a, fn_name_b, fn_name_c); let m = get_module(); - m.get_fn_index(fn_name, type_idx) + m.get_fn_idx(fn_name, type_idx) } #[no_mangle] @@ -53,25 +53,26 @@ pub fn wg_commit_instruction_body_to_cs() { mod tests { use std::io::prelude::*; use std::fs::File; - use ::codegen::*; use ::c_api::*; use ::util::*; use ::wasm_util::*; + use ::module_init::*; #[test] fn c_api_test() { setup(); + let m = get_module(); let cs = &mut get_module().cs; let instruction_body = &mut get_module().instruction_body; - wg_fn0_const_ret(cs, pack_str("foo")); - wg_fn0_const_ret(cs, pack_str("bar")); + wg_call_fn(cs, m.get_fn_idx(pack_str("foo"), FN0_TYPE_INDEX)); + wg_call_fn(cs, m.get_fn_idx(pack_str("bar"), FN0_TYPE_INDEX)); wg_finish(2); wg_reset(); wg_push_i32(cs, 2); - wg_call_fn1_ret(instruction_body, pack_str("baz")); + wg_call_fn(instruction_body, m.get_fn_idx(pack_str("baz"), FN1_RET_TYPE_INDEX)); wg_drop(instruction_body); wg_commit_instruction_body_to_cs(); diff --git a/src/wasmgen/src/codegen.rs b/src/wasmgen/src/codegen.rs deleted file mode 100644 index 1c92fae8..00000000 --- a/src/wasmgen/src/codegen.rs +++ /dev/null @@ -1,70 +0,0 @@ -use ::util::PackedStr; -use ::wasm_util::{wg_call_fn, wg_push_i32}; -use ::module_init::{FN0_RET_TYPE_INDEX, FN0_TYPE_INDEX, FN1_RET_TYPE_INDEX, FN1_TYPE_INDEX, FN2_TYPE_INDEX, FN3_TYPE_INDEX, get_module}; - -// for functions using the global module singleton - -#[no_mangle] -pub fn wg_fn0_const(buf: &mut Vec, fn_name: PackedStr) { - let m = get_module(); - let fn_idx = m.get_fn_index(fn_name, FN0_TYPE_INDEX); - wg_call_fn(buf, fn_idx); -} - -#[no_mangle] -pub fn wg_fn0_const_ret(buf: &mut Vec, fn_name: PackedStr) { - let m = get_module(); - let fn_idx = m.get_fn_index(fn_name, FN0_RET_TYPE_INDEX); - wg_call_fn(buf, fn_idx); -} - -#[no_mangle] -pub fn wg_fn1_const(buf: &mut Vec, fn_name: PackedStr, arg0: i32) { - let m = get_module(); - let fn_idx = m.get_fn_index(fn_name, FN1_TYPE_INDEX); - wg_push_i32(buf, arg0); - wg_call_fn(buf, fn_idx); -} - -#[no_mangle] -pub fn wg_fn1_const_ret(buf: &mut Vec, fn_name: PackedStr, arg0: i32) { - let m = get_module(); - let fn_idx = m.get_fn_index(fn_name, FN1_RET_TYPE_INDEX); - wg_push_i32(buf, arg0); - wg_call_fn(buf, fn_idx); -} - -#[no_mangle] -pub fn wg_fn2_const(buf: &mut Vec, fn_name: PackedStr, arg0: i32, arg1: i32) { - let m = get_module(); - let fn_idx = m.get_fn_index(fn_name, FN2_TYPE_INDEX); - wg_push_i32(buf, arg0); - wg_push_i32(buf, arg1); - wg_call_fn(buf, fn_idx); -} - -#[no_mangle] -pub fn wg_fn3_const(buf: &mut Vec, fn_name: PackedStr, arg0: i32, arg1: i32, arg2: i32) { - let m = get_module(); - let fn_idx = m.get_fn_index(fn_name, FN3_TYPE_INDEX); - wg_push_i32(buf, arg0); - wg_push_i32(buf, arg1); - wg_push_i32(buf, arg2); - wg_call_fn(buf, fn_idx); -} - -#[no_mangle] -pub fn wg_call_fn1_ret(buf: &mut Vec, fn_name: PackedStr) { - // generates: fn( _ ) where _ must be left on the stack before calling this, and fn returns a value - let m = get_module(); - let fn_idx = m.get_fn_index(fn_name, FN1_RET_TYPE_INDEX); - wg_call_fn(buf, fn_idx); -} - -#[no_mangle] -pub fn wg_call_fn2(buf: &mut Vec, fn_name: PackedStr) { - // generates: fn( _, _ ) where _, _ must be left on the stack before calling this - let m = get_module(); - let fn_idx = m.get_fn_index(fn_name, FN2_TYPE_INDEX); - wg_call_fn(buf, fn_idx); -} diff --git a/src/wasmgen/src/dbg.rs b/src/wasmgen/src/dbg.rs index d99937c1..af330aa5 100644 --- a/src/wasmgen/src/dbg.rs +++ b/src/wasmgen/src/dbg.rs @@ -1,6 +1,3 @@ -#[allow(dead_code)] -pub const DEBUG: bool = true; - #[allow(unused_macros)] macro_rules! dbg_log { ($fmt:expr) => { @@ -18,28 +15,14 @@ macro_rules! dbg_assert { }; } -#[cfg(target_arch = "wasm32")] -extern "C" { - pub fn log_from_wasm(ptr: *const u8, len: usize); - pub fn abort(); -} - -#[cfg(target_arch = "wasm32")] -use std::string::ToString; - -#[cfg(target_arch = "wasm32")] -pub fn _log_to_js_console(s: T) { - let s: String = s.to_string(); - let len = s.len(); - unsafe { log_from_wasm(s.as_bytes().as_ptr(), len); } -} - #[cfg(target_arch = "wasm32")] macro_rules! dbg_log { ($fmt:expr) => { + use ::util::{ DEBUG, _log_to_js_console }; if DEBUG { _log_to_js_console($fmt); } }; ($fmt:expr, $($arg:tt)*) => { + use ::util::{ DEBUG, _log_to_js_console }; if DEBUG { _log_to_js_console(format!($fmt, $($arg)*)); } }; } @@ -47,6 +30,7 @@ macro_rules! dbg_log { #[cfg(target_arch = "wasm32")] macro_rules! dbg_assert { ($cond:expr) => { + use ::util::{ DEBUG, _log_to_js_console, abort }; if DEBUG && !$cond { _log_to_js_console(format!( "Assertion failed at {}:{}:{}: '{}'", @@ -57,6 +41,7 @@ macro_rules! dbg_assert { } }; ($cond:expr, $desc:expr) => { + use ::util::{ DEBUG, _log_to_js_console, abort }; if DEBUG && !$cond { _log_to_js_console(format!( "Assertion failed at {}:{}:{}: '{}' - '{}'", diff --git a/src/wasmgen/src/lib.rs b/src/wasmgen/src/lib.rs index b5faeb9e..0dea0d98 100644 --- a/src/wasmgen/src/lib.rs +++ b/src/wasmgen/src/lib.rs @@ -8,5 +8,4 @@ mod wasm_opcodes; mod module_init; pub mod c_api; -pub mod codegen; pub mod wasm_util; diff --git a/src/wasmgen/src/module_init.rs b/src/wasmgen/src/module_init.rs index 0275b2f9..e631ab71 100644 --- a/src/wasmgen/src/module_init.rs +++ b/src/wasmgen/src/module_init.rs @@ -1,6 +1,9 @@ use std::ptr::{NonNull, null_mut}; -use ::util::{PackedStr, pack_str, unpack_str, write_fixed_leb16_at_idx, write_fixed_leb32_at_idx, write_leb_u32}; +use ::util::{ + PackedStr, unpack_str, + write_fixed_leb16_at_idx, write_fixed_leb32_at_idx, write_leb_u32, +}; use ::wasm_opcodes as op; pub const FN0_TYPE_INDEX: u8 = 0; @@ -10,8 +13,6 @@ pub const FN3_TYPE_INDEX: u8 = 3; pub const FN0_RET_TYPE_INDEX: u8 = 4; pub const FN1_RET_TYPE_INDEX: u8 = 5; - -#[allow(dead_code)] pub const FN2_RET_TYPE_INDEX: u8 = 6; pub const NR_FN_TYPE_INDEXES: u8 = 7; @@ -295,7 +296,7 @@ impl WasmBuilder { write_fixed_leb16_at_idx(&mut self.op, next_op_idx, self.import_count - 1); } - pub fn get_fn_index(&mut self, fn_name: PackedStr, type_index: u8) -> u16 { + pub fn get_fn_idx(&mut self, fn_name: PackedStr, type_index: u8) -> u16 { dbg_log!("getting fn idx for '{}'", unpack_str(fn_name)); match self.get_import_index(fn_name) { Some(idx) => { @@ -327,15 +328,16 @@ impl WasmBuilder { #[cfg(test)] mod tests { use ::module_init::*; + use ::util::pack_str; #[test] fn import_table_management() { let mut w = WasmBuilder::new(); w.init(); - assert_eq!(0, w.get_fn_index(pack_str("foo"), FN0_TYPE_INDEX)); - assert_eq!(1, w.get_fn_index(pack_str("bar"), FN1_TYPE_INDEX)); - assert_eq!(0, w.get_fn_index(pack_str("foo"), FN0_TYPE_INDEX)); - assert_eq!(2, w.get_fn_index(pack_str("baz"), FN2_TYPE_INDEX)); + assert_eq!(0, w.get_fn_idx(pack_str("foo"), FN0_TYPE_INDEX)); + assert_eq!(1, w.get_fn_idx(pack_str("bar"), FN1_TYPE_INDEX)); + assert_eq!(0, w.get_fn_idx(pack_str("foo"), FN0_TYPE_INDEX)); + assert_eq!(2, w.get_fn_idx(pack_str("baz"), FN2_TYPE_INDEX)); } } diff --git a/src/wasmgen/src/util.rs b/src/wasmgen/src/util.rs index 91ce99d9..10e837ca 100644 --- a/src/wasmgen/src/util.rs +++ b/src/wasmgen/src/util.rs @@ -1,5 +1,3 @@ -pub use ::dbg::*; - pub fn write_leb_i32(buf: &mut Vec, mut v: i32) { // Super complex stuff. See the following: // https://en.wikipedia.org/wiki/LEB128#Encode_signed_integer @@ -78,6 +76,25 @@ pub fn unpack_str(s: PackedStr) -> String { buf } +#[allow(dead_code)] +pub const DEBUG: bool = true; + +#[cfg(target_arch = "wasm32")] +extern "C" { + pub fn log_from_wasm(ptr: *const u8, len: usize); + pub fn abort(); +} + +#[cfg(target_arch = "wasm32")] +use std::string::ToString; + +#[cfg(target_arch = "wasm32")] +pub fn _log_to_js_console(s: T) { + let s: String = s.to_string(); + let len = s.len(); + unsafe { log_from_wasm(s.as_bytes().as_ptr(), len); } +} + #[cfg(test)] mod tests { use ::util::*; diff --git a/src/wasmgen/src/wasm_util.rs b/src/wasmgen/src/wasm_util.rs index fccd1400..39b9d5b3 100644 --- a/src/wasmgen/src/wasm_util.rs +++ b/src/wasmgen/src/wasm_util.rs @@ -1,5 +1,5 @@ use ::wasm_opcodes as op; -use ::util::{write_fixed_leb16_at_idx, write_leb_i32, write_leb_u32}; +use ::util::{ write_fixed_leb16_at_idx, write_leb_i32, write_leb_u32 }; #[no_mangle] pub fn wg_push_i32(buf: &mut Vec, v: i32) { From bca32cb310e4f08705f47c6251109a27044b8b1d Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 26 Jun 2018 02:30:53 +0530 Subject: [PATCH 0976/2137] use align_of instead of null_mut more magic! --- src/wasmgen/src/module_init.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/wasmgen/src/module_init.rs b/src/wasmgen/src/module_init.rs index e631ab71..491e89c6 100644 --- a/src/wasmgen/src/module_init.rs +++ b/src/wasmgen/src/module_init.rs @@ -1,4 +1,5 @@ -use std::ptr::{NonNull, null_mut}; +use std::ptr::NonNull; +use std::mem; use ::util::{ PackedStr, unpack_str, @@ -17,7 +18,9 @@ pub const FN2_RET_TYPE_INDEX: u8 = 6; pub const NR_FN_TYPE_INDEXES: u8 = 7; -static mut MODULE_PTR: NonNull = unsafe { NonNull::new_unchecked(null_mut()) }; +static mut MODULE_PTR: NonNull = unsafe { + NonNull::new_unchecked(mem::align_of::() as *mut _) +}; #[no_mangle] pub fn setup() { From e654c761c46b6bff0cb33aee919ed8a3e540ec84 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 26 Jun 2018 02:48:22 +0530 Subject: [PATCH 0977/2137] safe numeric downcasts --- src/wasmgen/src/module_init.rs | 7 ++-- src/wasmgen/src/util.rs | 75 ++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/src/wasmgen/src/module_init.rs b/src/wasmgen/src/module_init.rs index 491e89c6..c05f0cb3 100644 --- a/src/wasmgen/src/module_init.rs +++ b/src/wasmgen/src/module_init.rs @@ -4,6 +4,7 @@ use std::mem; use ::util::{ PackedStr, unpack_str, write_fixed_leb16_at_idx, write_fixed_leb32_at_idx, write_leb_u32, + SafeToU8, SafeToU16, SafeToI32, }; use ::wasm_opcodes as op; @@ -187,7 +188,7 @@ impl WasmBuilder { let new_len = self.op.len(); let size = (new_len - 1) - idx_section_size; - self.op[idx_section_size] = size as u8; + self.op[idx_section_size] = size.safe_to_u8(); } /// Goes over the import block to find index of an import entry by function name @@ -221,7 +222,7 @@ impl WasmBuilder { dbg_assert!(size < 0x4000); self.import_table_size = size; let idx_import_table_size = self.idx_import_table_size; - write_fixed_leb16_at_idx(&mut self.op, idx_import_table_size, size as u16); + write_fixed_leb16_at_idx(&mut self.op, idx_import_table_size, size.safe_to_u16()); } pub fn write_import_section_preamble(&mut self) { @@ -259,7 +260,7 @@ impl WasmBuilder { self.op.push(1); // length of module name self.op.push('e' as u8); // module name let fn_name = unpack_str(fn_name); - self.op.push(fn_name.len() as u8); + self.op.push(fn_name.len().safe_to_u8()); self.op.extend(fn_name.as_bytes()); self.op.push(op::EXT_FUNCTION); self.op.push(type_index); diff --git a/src/wasmgen/src/util.rs b/src/wasmgen/src/util.rs index 10e837ca..24cb7222 100644 --- a/src/wasmgen/src/util.rs +++ b/src/wasmgen/src/util.rs @@ -1,3 +1,78 @@ +pub trait SafeToU8 { + fn safe_to_u8(self) -> u8; +} + +pub trait SafeToU16 { + fn safe_to_u16(self) -> u16; +} + +pub trait SafeToI32 { + fn safe_to_i32(self) -> i32; +} + +impl SafeToU8 for u16 { + fn safe_to_u8(self) -> u8 { + dbg_assert!(self < ::std::u8::MAX as u16); + self as u8 + } +} + +impl SafeToU8 for u32 { + fn safe_to_u8(self) -> u8 { + dbg_assert!(self < ::std::u8::MAX as u32); + self as u8 + } +} + +impl SafeToU8 for i32 { + fn safe_to_u8(self) -> u8 { + dbg_assert!(self < ::std::u8::MAX as i32); + self as u8 + } +} + +impl SafeToU8 for usize { + fn safe_to_u8(self) -> u8 { + dbg_assert!(self < ::std::u8::MAX as usize); + self as u8 + } +} + +impl SafeToU16 for u32 { + fn safe_to_u16(self) -> u16 { + dbg_assert!(self < ::std::u16::MAX as u32); + self as u16 + } +} + +impl SafeToU16 for i32 { + fn safe_to_u16(self) -> u16 { + dbg_assert!(self < ::std::u16::MAX as i32); + self as u16 + } +} + +impl SafeToU16 for usize { + fn safe_to_u16(self) -> u16 { + dbg_assert!(self < ::std::u16::MAX as usize); + self as u16 + } +} + +impl SafeToI32 for u32 { + fn safe_to_i32(self) -> i32 { + dbg_assert!(self < ::std::i32::MAX as u32); + self as i32 + } +} + +impl SafeToI32 for usize { + fn safe_to_i32(self) -> i32 { + dbg_assert!(self < ::std::i32::MAX as usize); + self as i32 + } +} + pub fn write_leb_i32(buf: &mut Vec, mut v: i32) { // Super complex stuff. See the following: // https://en.wikipedia.org/wiki/LEB128#Encode_signed_integer From 9177cab5db834e6cdd1a92190e1d3cc4d35b3cf8 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 26 Jun 2018 18:16:25 +0530 Subject: [PATCH 0978/2137] use cfg!(debug_assertions) to set DEBUG --- src/wasmgen/src/util.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wasmgen/src/util.rs b/src/wasmgen/src/util.rs index 24cb7222..668c887f 100644 --- a/src/wasmgen/src/util.rs +++ b/src/wasmgen/src/util.rs @@ -152,7 +152,7 @@ pub fn unpack_str(s: PackedStr) -> String { } #[allow(dead_code)] -pub const DEBUG: bool = true; +pub const DEBUG: bool = cfg!(debug_assertions); #[cfg(target_arch = "wasm32")] extern "C" { From 044b9553eb299f360ef40b073cc0ee3ce3735727 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 26 Jun 2018 18:19:08 +0530 Subject: [PATCH 0979/2137] fix bounds check in Safe* traits --- src/wasmgen/src/util.rs | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/src/wasmgen/src/util.rs b/src/wasmgen/src/util.rs index 668c887f..98adf145 100644 --- a/src/wasmgen/src/util.rs +++ b/src/wasmgen/src/util.rs @@ -1,74 +1,66 @@ -pub trait SafeToU8 { - fn safe_to_u8(self) -> u8; -} - -pub trait SafeToU16 { - fn safe_to_u16(self) -> u16; -} - -pub trait SafeToI32 { - fn safe_to_i32(self) -> i32; -} +pub trait SafeToU8 { fn safe_to_u8(self) -> u8; } +pub trait SafeToU16 { fn safe_to_u16(self) -> u16; } +pub trait SafeToI32 { fn safe_to_i32(self) -> i32; } impl SafeToU8 for u16 { fn safe_to_u8(self) -> u8 { - dbg_assert!(self < ::std::u8::MAX as u16); + dbg_assert!(self <= ::std::u8::MAX as u16); self as u8 } } impl SafeToU8 for u32 { fn safe_to_u8(self) -> u8 { - dbg_assert!(self < ::std::u8::MAX as u32); + dbg_assert!(self <= ::std::u8::MAX as u32); self as u8 } } impl SafeToU8 for i32 { fn safe_to_u8(self) -> u8 { - dbg_assert!(self < ::std::u8::MAX as i32); + dbg_assert!(self >= 0 && self <= ::std::u8::MAX as i32); self as u8 } } impl SafeToU8 for usize { fn safe_to_u8(self) -> u8 { - dbg_assert!(self < ::std::u8::MAX as usize); + dbg_assert!(self <= ::std::u8::MAX as usize); self as u8 } } impl SafeToU16 for u32 { fn safe_to_u16(self) -> u16 { - dbg_assert!(self < ::std::u16::MAX as u32); + dbg_assert!(self <= ::std::u16::MAX as u32); self as u16 } } impl SafeToU16 for i32 { fn safe_to_u16(self) -> u16 { - dbg_assert!(self < ::std::u16::MAX as i32); + dbg_assert!(self >= 0 && self <= ::std::u16::MAX as i32); self as u16 } } impl SafeToU16 for usize { fn safe_to_u16(self) -> u16 { - dbg_assert!(self < ::std::u16::MAX as usize); + dbg_assert!(self <= ::std::u16::MAX as usize); self as u16 } } impl SafeToI32 for u32 { fn safe_to_i32(self) -> i32 { - dbg_assert!(self < ::std::i32::MAX as u32); + dbg_assert!(self <= ::std::i32::MAX as u32); self as i32 } } impl SafeToI32 for usize { fn safe_to_i32(self) -> i32 { - dbg_assert!(self < ::std::i32::MAX as usize); + dbg_assert!(self <= ::std::i32::MAX as usize); self as i32 } } From c33cdbd04eb65ba5af4ef3d2b5aaa610479b34f4 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 26 Jun 2018 18:36:45 +0530 Subject: [PATCH 0980/2137] fix rustup commands in dockerfile --- docker/test-image/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker/test-image/Dockerfile b/docker/test-image/Dockerfile index ff166f1f..31c07759 100644 --- a/docker/test-image/Dockerfile +++ b/docker/test-image/Dockerfile @@ -8,7 +8,8 @@ RUN \ tar xfv node-v8.9.4-linux-x64.tar.xz && \ rm node-v8.9.4-linux-x64.tar.xz && \ wget https://sh.rustup.rs -O rustup.sh && \ - sh ./rustup.sh && \ + sh ./rustup.sh -y && \ rm ./rustup.sh && \ + export PATH="$HOME/.cargo/bin:$PATH" && \ rustup toolchain install nightly && \ rustup target add wasm32-unknown-unknown --toolchain nightly From bb60a99d9a1c860308001363ba6725e6d8c7d25c Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 26 Jun 2018 18:44:08 +0530 Subject: [PATCH 0981/2137] fix clang-tidy warnings --- src/native/codegen/codegen.c | 6 +++--- src/native/profiler/opstats.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/native/codegen/codegen.c b/src/native/codegen/codegen.c index b72c2aab..d14e7d00 100644 --- a/src/native/codegen/codegen.c +++ b/src/native/codegen/codegen.c @@ -4,10 +4,10 @@ #include "../const.h" #include "../cpu.h" -#include "../log.h" #include "../global_pointers.h" -#include "wasmgen.h" +#include "../log.h" #include "codegen.h" +#include "wasmgen.h" static void jit_add_seg_offset(int32_t default_segment); static void jit_resolve_modrm32_(int32_t modrm_byte); @@ -36,7 +36,7 @@ PackedStr pack_str(char const* fn_name, uint8_t fn_len) union { PackedStr pstr; uint8_t u8s[24]; - } ret = { { 0 } }; + } ret = { { 0, 0, 0 } }; for(int i = 0; i < fn_len; i++) { diff --git a/src/native/profiler/opstats.c b/src/native/profiler/opstats.c index 074d3c5c..bd881d98 100644 --- a/src/native/profiler/opstats.c +++ b/src/native/profiler/opstats.c @@ -1,6 +1,6 @@ +#include #include #include -#include #include "../codegen/codegen.h" #include "../shared.h" From 5d0d683bbcb4edfc54364f0797f8b1f3db3a7082 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 26 Jun 2018 21:18:24 +0530 Subject: [PATCH 0982/2137] fix deps and remove trailing space --- Makefile | 26 +++++++++++++------------- src/native/codegen/codegen.c | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 885415b1..c9bd5b1f 100644 --- a/Makefile +++ b/Makefile @@ -23,9 +23,9 @@ ifeq ($(JIT_ALWAYS),) JIT_ALWAYS=false endif -all: build/v86_all.js +all: build/v86_all.js build/v86.wasm build/wasmgen.wasm browser: build/v86_all.js -wasm: build/v86.wasm +wasm: build/v86.wasm build/wasmgen.wasm # Used for nodejs builds and in order to profile code. # `debug` gives identifiers a readable name, make sure it doesn't have any side effects. @@ -237,9 +237,6 @@ build/wasmgen-debug.wasm: src/wasmgen/src/*.rs src/wasmgen/Cargo.toml cp src/wasmgen/target/wasm32-unknown-unknown/debug/wasmgen.wasm build/wasmgen-debug.wasm ls -lh build/wasmgen-debug.wasm -wasmgen-test: - (cd src/wasmgen && env RUST_BACKTRACE=full RUST_TEST_THREADS=1 cargo test -- --nocapture) - clean: -rm build/libv86.js -rm build/libv86-debug.js @@ -278,42 +275,45 @@ $(CLOSURE): mv $(CLOSURE_DIR)/*.jar $(CLOSURE) rm $(CLOSURE_DIR)/compiler-latest.zip -tests: build/libv86.js build/v86.wasm +tests: build/libv86.js build/v86.wasm build/wasmgen.wasm ./tests/full/run.js -nasmtests: build/libv86-debug.js build/v86-debug.wasm +nasmtests: build/libv86-debug.js build/v86-debug.wasm build/wasmgen-debug.wasm $(MAKE) -C $(NASM_TEST_DIR) all $(NASM_TEST_DIR)/gen_fixtures.js $(NASM_TEST_DIR)/run.js -nasmtests-force-jit: build/libv86-debug.js build/v86-debug.wasm +nasmtests-force-jit: build/libv86-debug.js build/v86-debug.wasm build/wasmgen-debug.wasm $(MAKE) -C $(NASM_TEST_DIR) all $(NASM_TEST_DIR)/gen_fixtures.js $(NASM_TEST_DIR)/run.js --force-jit -jitpagingtests: build/libv86-debug.js build/v86-debug.wasm +jitpagingtests: build/libv86-debug.js build/v86-debug.wasm build/wasmgen-debug.wasm $(MAKE) -C tests/jit-paging test-jit ./tests/jit-paging/run.js -qemutests: build/libv86-debug.js build/v86-debug.wasm +qemutests: build/libv86-debug.js build/v86-debug.wasm build/wasmgen-debug.wasm $(MAKE) -C tests/qemu test-i386 ./tests/qemu/run.js > /tmp/v86-test-result #./tests/qemu/test-i386 > /tmp/v86-test-reference ./tests/qemu/run-qemu.js > /tmp/v86-test-reference diff /tmp/v86-test-result /tmp/v86-test-reference -kvm-unit-test: build/libv86-debug.js build/v86-debug.wasm +kvm-unit-test: build/libv86-debug.js build/v86-debug.wasm build/wasmgen-debug.wasm (cd tests/kvm-unit-tests && ./configure) $(MAKE) -C tests/kvm-unit-tests tests/kvm-unit-tests/run.js tests/kvm-unit-tests/x86/realmode.flat -expect-tests: build/libv86-debug.js build/v86-debug.wasm build/libwabt.js +expect-tests: build/libv86-debug.js build/v86-debug.wasm build/wasmgen-debug.wasm build/libwabt.js make -C tests/expect/tests ./tests/expect/run.js -devices-test: build/libv86-debug.js build/v86-debug.wasm +devices-test: build/libv86-debug.js build/v86-debug.wasm build/wasmgen-debug.wasm ./tests/devices/virtio_9p.js +wasmgen-test: + (cd src/wasmgen && env RUST_BACKTRACE=full RUST_TEST_THREADS=1 cargo test -- --nocapture) + covreport: mkdir -p $(COVERAGE_DIR)/build/ $(COVERAGE_DIR)/gen_report.js diff --git a/src/native/codegen/codegen.c b/src/native/codegen/codegen.c index d14e7d00..2ed55926 100644 --- a/src/native/codegen/codegen.c +++ b/src/native/codegen/codegen.c @@ -37,7 +37,7 @@ PackedStr pack_str(char const* fn_name, uint8_t fn_len) PackedStr pstr; uint8_t u8s[24]; } ret = { { 0, 0, 0 } }; - + for(int i = 0; i < fn_len; i++) { ret.u8s[i] = fn_name[i]; From ca2486391abe4bdbb2d0be0e12fe188069174dee Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 26 Jun 2018 21:42:48 +0530 Subject: [PATCH 0983/2137] remove unused bindings --- src/browser/starter.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 49267b5b..2633ac88 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -337,20 +337,12 @@ function V86Starter(options) "wg_increment_mem32", "wg_increment_variable", "wg_load_aligned_u16_from_stack", - "wg_fn0_const", - "wg_fn0_const_ret", - "wg_fn1_const", - "wg_fn1_const_ret", - "wg_fn2_const", - "wg_fn3_const", - "wg_call_fn1_ret", - "wg_call_fn2", ]; v86util.minimal_load_wasm(wasmgen_bin, { "env": wasmgen_externs }, (wasmgen) => { for(const fn_name of wasmgen_exports) { - dbg_assert(typeof wasmgen.exports[fn_name] === "function"); + dbg_assert(typeof wasmgen.exports[fn_name] === "function", `Function ${fn_name} not found in wasmgen exports`); wasm_shared_funcs[`_${fn_name}`] = wasmgen.exports[fn_name]; } wasmgen.exports["setup"](); From 9fa6ef5f63064803a41df04bcf3a85a64ab9aaae Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 26 Jun 2018 22:03:40 +0530 Subject: [PATCH 0984/2137] rename travis-run-codegen.sh --- .travis-run-codegen.sh => .travis-run-wasmgen.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .travis-run-codegen.sh => .travis-run-wasmgen.sh (100%) diff --git a/.travis-run-codegen.sh b/.travis-run-wasmgen.sh similarity index 100% rename from .travis-run-codegen.sh rename to .travis-run-wasmgen.sh From 65bb81f66f4a5da7893ea4247774c9309ceffb23 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 23 Jun 2018 20:42:53 -0600 Subject: [PATCH 0985/2137] Check invariants after remove_jit_cache_wasm_index --- src/native/jit.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/native/jit.c b/src/native/jit.c index 94319edc..c988be03 100644 --- a/src/native/jit.c +++ b/src/native/jit.c @@ -102,6 +102,17 @@ void remove_jit_cache_wasm_index(int32_t page, uint16_t wasm_table_index) { free_wasm_table_index(wasm_table_index); } + +#if CHECK_JIT_CACHE_ARRAY_INVARIANTS + // sanity check that the above iteration deleted all entries + + for(int32_t i = 0; i < JIT_CACHE_ARRAY_SIZE; i++) + { + struct code_cache* entry = &jit_cache_arr[i]; + + assert(entry->wasm_table_index != wasm_table_index); + } +#endif } bool find_u16(const uint16_t* array, uint16_t value, int32_t length) From 2a983fb83f9d4940f8e9fa552089bb58d76d2258 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 23 Jun 2018 20:43:23 -0600 Subject: [PATCH 0986/2137] Reorder invariant checking to avoid infinite loops --- src/native/cpu.c | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/native/cpu.c b/src/native/cpu.c index ade2cd7e..a3dc29b4 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -666,6 +666,29 @@ void check_jit_cache_array_invariants(void) #if CHECK_JIT_CACHE_ARRAY_INVARIANTS int32_t wasm_table_index_to_jit_cache_index[WASM_TABLE_SIZE] = { 0 }; + // there are no loops in the linked lists + // https://en.wikipedia.org/wiki/Cycle_detection#Floyd's_Tortoise_and_Hare + for(int32_t i = 0; i < GROUP_DIRTINESS_LENGTH; i++) + { + int32_t slow = page_first_jit_cache_entry[i]; + int32_t fast = page_first_jit_cache_entry[i]; + + while(fast != JIT_CACHE_ARRAY_NO_NEXT_ENTRY) + { + slow = jit_cache_arr[slow].next_index_same_page; + fast = jit_cache_arr[fast].next_index_same_page; + + if(fast == JIT_CACHE_ARRAY_NO_NEXT_ENTRY) + { + break; + } + + fast = jit_cache_arr[fast].next_index_same_page; + + assert(slow != fast); + } + } + for(int32_t i = 0; i < JIT_CACHE_ARRAY_SIZE; i++) { struct code_cache* entry = &jit_cache_arr[i]; @@ -730,29 +753,6 @@ void check_jit_cache_array_invariants(void) assert(reached); } } - - // there are no loops in the linked lists - // https://en.wikipedia.org/wiki/Cycle_detection#Floyd's_Tortoise_and_Hare - for(int32_t i = 0; i < GROUP_DIRTINESS_LENGTH; i++) - { - int32_t slow = page_first_jit_cache_entry[i]; - int32_t fast = page_first_jit_cache_entry[i]; - - while(fast != JIT_CACHE_ARRAY_NO_NEXT_ENTRY) - { - slow = jit_cache_arr[slow].next_index_same_page; - fast = jit_cache_arr[fast].next_index_same_page; - - if(fast == JIT_CACHE_ARRAY_NO_NEXT_ENTRY) - { - break; - } - - fast = jit_cache_arr[fast].next_index_same_page; - - assert(slow != fast); - } - } #endif } From f8d1c8f61b9a8b3093288aa9ec3d980f9fa7ca51 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 23 Jun 2018 20:51:09 -0600 Subject: [PATCH 0987/2137] JIT: Fix case when creating an entry overrides existing entry with the same table index --- src/native/cpu.c | 42 ++++++++++++++++++++++++++++++++---------- src/native/jit.c | 4 +++- src/native/jit.h | 1 + 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/native/cpu.c b/src/native/cpu.c index a3dc29b4..e13530f5 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -756,7 +756,7 @@ void check_jit_cache_array_invariants(void) #endif } -static struct code_cache* create_cache_entry(uint32_t phys_addr) +static struct code_cache* create_cache_entry(uint32_t phys_addr, uint16_t wasm_table_index) { int32_t found_entry_index = -1; @@ -791,17 +791,39 @@ static struct code_cache* create_cache_entry(uint32_t phys_addr) assert(entry->start_addr); assert(entry->wasm_table_index); - uint16_t wasm_table_index = entry->wasm_table_index; - uint32_t page = entry->start_addr >> DIRTY_ARR_SHIFT; + if(entry->wasm_table_index == wasm_table_index) + { + assert(entry->pending); + assert(same_page(entry->start_addr, phys_addr)); - remove_jit_cache_wasm_index(page, wasm_table_index); + // The entry belongs to the same wasm table index as this entry. + // *Don't* free the wasm table index, instead just delete the entry + // and use its slot for this entry. + // TODO: Optimally, we should pick another slot instead of dropping + // an entry has just been created. + uint32_t old_page = entry->start_addr >> DIRTY_ARR_SHIFT; + remove_jit_cache_entry(old_page, found_entry_index); - // entry should be removed after calling remove_jit_cache_wasm_index + assert(entry->next_index_same_page == JIT_CACHE_ARRAY_NO_NEXT_ENTRY); + entry->pending = false; + entry->start_addr = 0; + } + else + { + uint16_t old_wasm_table_index = entry->wasm_table_index; + uint32_t old_page = entry->start_addr >> DIRTY_ARR_SHIFT; - assert(!entry->pending); - assert(!entry->start_addr); - assert(!entry->wasm_table_index); - assert(entry->next_index_same_page == JIT_CACHE_ARRAY_NO_NEXT_ENTRY); + remove_jit_cache_wasm_index(old_page, old_wasm_table_index); + + check_jit_cache_array_invariants(); + + // entry should be removed after calling remove_jit_cache_wasm_index + + assert(!entry->pending); + assert(!entry->start_addr); + assert(!entry->wasm_table_index); + assert(entry->next_index_same_page == JIT_CACHE_ARRAY_NO_NEXT_ENTRY); + } } uint32_t page = phys_addr >> DIRTY_ARR_SHIFT; @@ -1693,7 +1715,7 @@ static void jit_generate(uint32_t phys_addr) { uint32_t phys_addr = translate_address_read(block->addr); - struct code_cache* entry = create_cache_entry(phys_addr); + struct code_cache* entry = create_cache_entry(phys_addr, wasm_table_index); assert(phys_addr); entry->start_addr = phys_addr; diff --git a/src/native/jit.c b/src/native/jit.c index c988be03..80e3a1c1 100644 --- a/src/native/jit.c +++ b/src/native/jit.c @@ -57,6 +57,8 @@ void remove_jit_cache_entry(uint32_t page, int32_t addr_index) } } + jit_cache_arr[addr_index].next_index_same_page = JIT_CACHE_ARRAY_NO_NEXT_ENTRY; + assert(did_remove); } @@ -83,7 +85,7 @@ void remove_jit_cache_wasm_index(int32_t page, uint16_t wasm_table_index) remove_jit_cache_entry(page, cache_array_index); - entry->next_index_same_page = JIT_CACHE_ARRAY_NO_NEXT_ENTRY; + assert(entry->next_index_same_page == JIT_CACHE_ARRAY_NO_NEXT_ENTRY); entry->wasm_table_index = 0; entry->start_addr = 0; entry->pending = false; diff --git a/src/native/jit.h b/src/native/jit.h index ec898108..7f26045f 100644 --- a/src/native/jit.h +++ b/src/native/jit.h @@ -5,6 +5,7 @@ void free_wasm_table_index(uint16_t wasm_table_index); void remove_jit_cache_wasm_index(int32_t page, uint16_t wasm_table_index); +void remove_jit_cache_entry(uint32_t page, int32_t addr_index); void jit_dirty_cache(uint32_t start_addr, uint32_t end_addr); void jit_dirty_cache_single(uint32_t addr); void jit_dirty_cache_small(uint32_t start_addr, uint32_t end_addr); From 81b8b27bc27d24a5bafb43a93525ecf253d077a3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 25 Jun 2018 14:45:41 -0600 Subject: [PATCH 0988/2137] Update .clang-tidy --- .clang-tidy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.clang-tidy b/.clang-tidy index fdb1f351..0dd220a6 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1 +1 @@ -Checks: '*,-llvm-header-guard,-readability-braces-around-statements,-readability-else-after-return,-google-readability-todo,-misc-unused-parameters,-*-function-size,-clang-diagnostic-unused-function' +Checks: '*,-llvm-header-guard,-readability-braces-around-statements,-readability-else-after-return,-google-readability-todo,-misc-unused-parameters,-*-function-size,-clang-diagnostic-unused-function,-hicpp-signed-bitwise,-hicpp-braces-around-statements' From 87c762414cc61d78079fa98b043954557090ca31 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 25 Jun 2018 20:39:07 -0600 Subject: [PATCH 0989/2137] clang-tidy: All warnings are errors --- .clang-tidy | 1 + 1 file changed, 1 insertion(+) diff --git a/.clang-tidy b/.clang-tidy index 0dd220a6..33243ca1 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1 +1,2 @@ Checks: '*,-llvm-header-guard,-readability-braces-around-statements,-readability-else-after-return,-google-readability-todo,-misc-unused-parameters,-*-function-size,-clang-diagnostic-unused-function,-hicpp-signed-bitwise,-hicpp-braces-around-statements' +WarningsAsErrors: '*' From b37a086cb2c7afd7bd447a818ef4e87d03b49491 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 25 Jun 2018 20:44:26 -0600 Subject: [PATCH 0990/2137] Delete dead code --- src/browser/print_stats.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index b5cd02bd..cbb24082 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -13,13 +13,6 @@ const print_stats = { { let text = ""; - const names = [ - "IDLE", - "DO_MANY_CYCLES", - "GEN_INSTR", - "RUN_FROM_CACHE", - "RUN_INTERPRETED", - ]; const stat_names = [ "COMPILE", "COMPILE_SUCCESS", From e33cc8f0722257bbc8d8b87f449aabe30b32a2a9 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sat, 30 Jun 2018 00:16:21 +0530 Subject: [PATCH 0991/2137] rust restructuring, some refactoring --- .gitignore | 3 +- .travis-run-lint.sh | 3 + .travis-run-jshint.sh => .travis-run-rust.sh | 2 +- .travis-run-wasmgen.sh | 3 - .travis.yml | 4 +- src/wasmgen/Cargo.toml => Cargo.toml | 6 +- Makefile | 59 +++++++++++-------- docker/test-image/Dockerfile | 4 +- src/browser/starter.js | 28 ++++----- src/cpu.js | 10 ++-- src/{wasmgen/src => rust}/dbg.rs | 0 src/rust/lib.rs | 8 +++ src/{wasmgen/src => rust}/util.rs | 0 src/{wasmgen/src => rust/wasmgen}/c_api.rs | 25 ++++---- .../src/lib.rs => rust/wasmgen/mod.rs} | 7 +-- .../src => rust/wasmgen}/module_init.rs | 23 ++++---- .../src => rust/wasmgen}/wasm_opcodes.rs | 0 .../src => rust/wasmgen}/wasm_util.rs | 4 +- tests/rust/verify-wasmgen-dummy-output.js | 34 +++++++++++ 19 files changed, 139 insertions(+), 84 deletions(-) create mode 100755 .travis-run-lint.sh rename .travis-run-jshint.sh => .travis-run-rust.sh (64%) delete mode 100755 .travis-run-wasmgen.sh rename src/wasmgen/Cargo.toml => Cargo.toml (77%) rename src/{wasmgen/src => rust}/dbg.rs (100%) create mode 100644 src/rust/lib.rs rename src/{wasmgen/src => rust}/util.rs (100%) rename src/{wasmgen/src => rust/wasmgen}/c_api.rs (76%) rename src/{wasmgen/src/lib.rs => rust/wasmgen/mod.rs} (60%) rename src/{wasmgen/src => rust/wasmgen}/module_init.rs (96%) rename src/{wasmgen/src => rust/wasmgen}/wasm_opcodes.rs (100%) rename src/{wasmgen/src => rust/wasmgen}/wasm_util.rs (98%) create mode 100755 tests/rust/verify-wasmgen-dummy-output.js diff --git a/.gitignore b/.gitignore index 1babd7d1..383679e8 100644 --- a/.gitignore +++ b/.gitignore @@ -19,5 +19,4 @@ images/ node_modules/ package-lock.json profile*.json -src/wasmgen/target -src/wasmgen/Cargo.lock +Cargo.lock diff --git a/.travis-run-lint.sh b/.travis-run-lint.sh new file mode 100755 index 00000000..17dd1e24 --- /dev/null +++ b/.travis-run-lint.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +set -e +make jshint rustfmt clang-tidy diff --git a/.travis-run-jshint.sh b/.travis-run-rust.sh similarity index 64% rename from .travis-run-jshint.sh rename to .travis-run-rust.sh index ce3c99be..50b98bee 100755 --- a/.travis-run-jshint.sh +++ b/.travis-run-rust.sh @@ -1,3 +1,3 @@ #!/usr/bin/env bash set -e -make jshint +make rust-test diff --git a/.travis-run-wasmgen.sh b/.travis-run-wasmgen.sh deleted file mode 100755 index 6a17bdbe..00000000 --- a/.travis-run-wasmgen.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash -set -e -make wasmgen-test diff --git a/.travis.yml b/.travis.yml index 6af91306..dace51de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,8 +14,8 @@ env: - TEST_SUITE=integration - TEST_SUITE=unit-qemu - TEST_SUITE=nasm - - TEST_SUITE=codegen - - TEST_SUITE=jshint + - TEST_SUITE=rust + - TEST_SUITE=lint - TEST_SUITE=jit-paging - TEST_SUITE=expect - TEST_SUITE=devices diff --git a/src/wasmgen/Cargo.toml b/Cargo.toml similarity index 77% rename from src/wasmgen/Cargo.toml rename to Cargo.toml index e95b6bee..f8191cc4 100644 --- a/src/wasmgen/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "wasmgen" +name = "v86oxide" version = "0.1.0" -authors = ["Awal Garg "] publish = false [dependencies] @@ -9,11 +8,14 @@ lazy_static = "1.0" [lib] crate-type = ["cdylib"] +path = "src/rust/lib.rs" [profile.dev] +lto = false panic = "abort" [profile.release] lto = true incremental = false panic = "abort" + diff --git a/Makefile b/Makefile index c9bd5b1f..43e25dc8 100644 --- a/Makefile +++ b/Makefile @@ -23,9 +23,9 @@ ifeq ($(JIT_ALWAYS),) JIT_ALWAYS=false endif -all: build/v86_all.js build/v86.wasm build/wasmgen.wasm +all: build/v86_all.js build/libv86.js build/v86.wasm build/v86oxide.wasm +all-debug: build/libv86-debug.js build/v86-debug.wasm build/v86oxide-debug.wasm browser: build/v86_all.js -wasm: build/v86.wasm build/wasmgen.wasm # Used for nodejs builds and in order to profile code. # `debug` gives identifiers a readable name, make sure it doesn't have any side effects. @@ -104,6 +104,11 @@ CC_FLAGS=\ -s WASM=1 \ -s SIDE_MODULE=1 +CARGO_FLAGS=\ + --target wasm32-unknown-unknown \ + --target-dir build/ \ + -- -Clink-args="--import-memory" + CORE_FILES=const.js config.js io.js main.js lib.js coverage.js ide.js pci.js floppy.js \ memory.js 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 \ @@ -114,6 +119,8 @@ BROWSER_FILES=screen.js \ keyboard.js mouse.js serial.js \ network.js lib.js starter.js worker_bus.js dummy_screen.js print_stats.js +RUST_FILES=$(shell find src/rust/ -name '*.rs') + CORE_FILES:=$(addprefix src/,$(CORE_FILES)) LIB_FILES:=$(addprefix lib/,$(LIB_FILES)) BROWSER_FILES:=$(addprefix src/browser/,$(BROWSER_FILES)) @@ -223,19 +230,19 @@ build/v86-debug.wasm: src/native/*.c src/native/*.h src/native/codegen/*.c src/n -o build/v86-debug.wasm ls -lh build/v86-debug.wasm -build/wasmgen.wasm: src/wasmgen/src/*.rs src/wasmgen/Cargo.toml +build/v86oxide.wasm: $(RUST_FILES) Cargo.toml mkdir -p build/ - -ls -lh build/wasmgen.wasm - (cd src/wasmgen && cargo +nightly rustc --release --target wasm32-unknown-unknown -- -Clink-args="--import-memory") - cp src/wasmgen/target/wasm32-unknown-unknown/release/wasmgen.wasm build/wasmgen.wasm - ls -lh build/wasmgen.wasm + -ls -lh build/v86oxide.wasm + cargo +nightly rustc --release $(CARGO_FLAGS) + cp build/wasm32-unknown-unknown/release/v86oxide.wasm build/v86oxide.wasm + ls -lh build/v86oxide.wasm -build/wasmgen-debug.wasm: src/wasmgen/src/*.rs src/wasmgen/Cargo.toml +build/v86oxide-debug.wasm: $(RUST_FILES) Cargo.toml mkdir -p build/ - -ls -lh build/wasmgen-debug.wasm - (cd src/wasmgen && cargo +nightly rustc --target wasm32-unknown-unknown -- -Clink-args="--import-memory") - cp src/wasmgen/target/wasm32-unknown-unknown/debug/wasmgen.wasm build/wasmgen-debug.wasm - ls -lh build/wasmgen-debug.wasm + -ls -lh build/v86oxide-debug.wasm + cargo +nightly rustc $(CARGO_FLAGS) + cp build/wasm32-unknown-unknown/debug/v86oxide.wasm build/v86oxide-debug.wasm + ls -lh build/v86oxide-debug.wasm clean: -rm build/libv86.js @@ -243,8 +250,8 @@ clean: -rm build/v86_all.js -rm build/v86.wasm -rm build/v86-debug.wasm - -rm build/wasmgen.wasm - -rm build/wasmgen-debug.wasm + -rm build/v86oxide.wasm + -rm build/v86oxide-debug.wasm -rm $(INSTRUCTION_TABLES) -rm $(addsuffix .bak,$(INSTRUCTION_TABLES)) -rm $(addsuffix .diff,$(INSTRUCTION_TABLES)) @@ -275,44 +282,45 @@ $(CLOSURE): mv $(CLOSURE_DIR)/*.jar $(CLOSURE) rm $(CLOSURE_DIR)/compiler-latest.zip -tests: build/libv86.js build/v86.wasm build/wasmgen.wasm +tests: build/libv86.js build/v86.wasm build/v86oxide.wasm ./tests/full/run.js -nasmtests: build/libv86-debug.js build/v86-debug.wasm build/wasmgen-debug.wasm +nasmtests: all-debug $(MAKE) -C $(NASM_TEST_DIR) all $(NASM_TEST_DIR)/gen_fixtures.js $(NASM_TEST_DIR)/run.js -nasmtests-force-jit: build/libv86-debug.js build/v86-debug.wasm build/wasmgen-debug.wasm +nasmtests-force-jit: all-debug $(MAKE) -C $(NASM_TEST_DIR) all $(NASM_TEST_DIR)/gen_fixtures.js $(NASM_TEST_DIR)/run.js --force-jit -jitpagingtests: build/libv86-debug.js build/v86-debug.wasm build/wasmgen-debug.wasm +jitpagingtests: all-debug $(MAKE) -C tests/jit-paging test-jit ./tests/jit-paging/run.js -qemutests: build/libv86-debug.js build/v86-debug.wasm build/wasmgen-debug.wasm +qemutests: all-debug $(MAKE) -C tests/qemu test-i386 ./tests/qemu/run.js > /tmp/v86-test-result #./tests/qemu/test-i386 > /tmp/v86-test-reference ./tests/qemu/run-qemu.js > /tmp/v86-test-reference diff /tmp/v86-test-result /tmp/v86-test-reference -kvm-unit-test: build/libv86-debug.js build/v86-debug.wasm build/wasmgen-debug.wasm +kvm-unit-test: all-debug (cd tests/kvm-unit-tests && ./configure) $(MAKE) -C tests/kvm-unit-tests tests/kvm-unit-tests/run.js tests/kvm-unit-tests/x86/realmode.flat -expect-tests: build/libv86-debug.js build/v86-debug.wasm build/wasmgen-debug.wasm build/libwabt.js +expect-tests: all-debug build/libwabt.js make -C tests/expect/tests ./tests/expect/run.js -devices-test: build/libv86-debug.js build/v86-debug.wasm build/wasmgen-debug.wasm +devices-test: all-debug ./tests/devices/virtio_9p.js -wasmgen-test: - (cd src/wasmgen && env RUST_BACKTRACE=full RUST_TEST_THREADS=1 cargo test -- --nocapture) +rust-test: + env RUST_BACKTRACE=full RUST_TEST_THREADS=1 cargo test --target-dir build -- --nocapture + ./tests/rust/verify-wasmgen-dummy-output.js covreport: mkdir -p $(COVERAGE_DIR)/build/ @@ -324,6 +332,9 @@ node_modules/.bin/jshint: jshint: node_modules/.bin/jshint ./node_modules/.bin/jshint --config=./.jshint.json src tests gen +rustfmt: $(RUST_FILES) + cargo fmt --all -- --write-mode check + build/capstone-x86.min.js: mkdir -p build wget -P build https://github.com/AlexAltea/capstone.js/releases/download/v3.0.5-rc1/capstone-x86.min.js diff --git a/docker/test-image/Dockerfile b/docker/test-image/Dockerfile index 31c07759..100e8a7e 100644 --- a/docker/test-image/Dockerfile +++ b/docker/test-image/Dockerfile @@ -12,4 +12,6 @@ RUN \ rm ./rustup.sh && \ export PATH="$HOME/.cargo/bin:$PATH" && \ rustup toolchain install nightly && \ - rustup target add wasm32-unknown-unknown --toolchain nightly + rustup target add wasm32-unknown-unknown --toolchain nightly && \ + rustup component add rustfmt-preview --toolchain nightly + diff --git a/src/browser/starter.js b/src/browser/starter.js index 2633ac88..004f9958 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -260,11 +260,11 @@ function V86Starter(options) "NaN": NaN, }; - const wasmgen_mem = new WebAssembly.Memory({ "initial": 100 }); - const wasmgen_externs = { - "memory": wasmgen_mem, + const v86oxide_mem = new WebAssembly.Memory({ "initial": 100 }); + const v86oxide_externs = { + "memory": v86oxide_mem, "log_from_wasm": function(offset, len) { - const str = v86util.read_sized_string_from_mem(wasmgen_mem, offset, len); + const str = v86util.read_sized_string_from_mem(v86oxide_mem, offset, len); dbg_log(str, LOG_CPU); }, "abort": function() { @@ -273,20 +273,20 @@ function V86Starter(options) }; let wasm_file = DEBUG ? "v86-debug.wasm" : "v86.wasm"; - let wasmgen_bin = DEBUG ? "wasmgen-debug.wasm" : "wasmgen.wasm"; + let v86oxide_bin = DEBUG ? "v86oxide-debug.wasm" : "v86oxide.wasm"; if(typeof window === "undefined" && typeof __dirname === "string") { wasm_file = __dirname + "/" + wasm_file; - wasmgen_bin = __dirname + "/" + wasmgen_bin; + v86oxide_bin = __dirname + "/" + v86oxide_bin; } else { wasm_file = "build/" + wasm_file; - wasmgen_bin = "build/" + wasmgen_bin; + v86oxide_bin = "build/" + v86oxide_bin; } - const wasmgen_exports = [ + const v86oxide_exports = [ "wg_get_code_section", "wg_get_instruction_body", "wg_commit_instruction_body_to_cs", @@ -339,13 +339,13 @@ function V86Starter(options) "wg_load_aligned_u16_from_stack", ]; - v86util.minimal_load_wasm(wasmgen_bin, { "env": wasmgen_externs }, (wasmgen) => { - for(const fn_name of wasmgen_exports) + v86util.minimal_load_wasm(v86oxide_bin, { "env": v86oxide_externs }, (v86oxide) => { + for(const fn_name of v86oxide_exports) { - dbg_assert(typeof wasmgen.exports[fn_name] === "function", `Function ${fn_name} not found in wasmgen exports`); - wasm_shared_funcs[`_${fn_name}`] = wasmgen.exports[fn_name]; + dbg_assert(typeof v86oxide.exports[fn_name] === "function", `Function ${fn_name} not found in v86oxide exports`); + wasm_shared_funcs[`_${fn_name}`] = v86oxide.exports[fn_name]; } - wasmgen.exports["setup"](); + v86oxide.exports["wg_setup"](); //XXX: fix indentation break @@ -359,7 +359,7 @@ function V86Starter(options) mem8 = new Uint8Array(mem); wm.instance.exports["__post_instantiate"](); coverage_logger.init(wm); - emulator = this.v86 = new v86(this.emulator_bus, wm, wasmgen, coverage_logger); + emulator = this.v86 = new v86(this.emulator_bus, wm, v86oxide, coverage_logger); cpu = emulator.cpu; // XXX: Leaving unindented to minimize diff; still a part of the cb to load_wasm! diff --git a/src/cpu.js b/src/cpu.js index 639d7dbe..333af17f 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -11,10 +11,10 @@ var CPU_LOG_VERBOSE = false; /** @constructor */ -function CPU(bus, wm, wasmgen, coverage_logger) +function CPU(bus, wm, v86oxide, coverage_logger) { this.wm = wm; - this.wasmgen = wasmgen; + this.v86oxide = v86oxide; this.coverage_logger = coverage_logger; this.wasm_patch(wm); this.create_jit_imports(); @@ -217,10 +217,10 @@ function CPU(bus, wm, wasmgen, coverage_logger) CPU.prototype.wasmgen_get_module_code = function() { - const ptr = this.wasmgen.exports["wg_get_op_ptr"](); - const len = this.wasmgen.exports["wg_get_op_len"](); + const ptr = this.v86oxide.exports["wg_get_op_ptr"](); + const len = this.v86oxide.exports["wg_get_op_len"](); - const output_buffer_view = new Uint8Array(this.wasmgen.memory.buffer, ptr, len); + const output_buffer_view = new Uint8Array(this.v86oxide.memory.buffer, ptr, len); return output_buffer_view; }; diff --git a/src/wasmgen/src/dbg.rs b/src/rust/dbg.rs similarity index 100% rename from src/wasmgen/src/dbg.rs rename to src/rust/dbg.rs diff --git a/src/rust/lib.rs b/src/rust/lib.rs new file mode 100644 index 00000000..eeaf2d4f --- /dev/null +++ b/src/rust/lib.rs @@ -0,0 +1,8 @@ +#[macro_use] +mod dbg; + +#[macro_use] +mod util; + +pub mod wasmgen; + diff --git a/src/wasmgen/src/util.rs b/src/rust/util.rs similarity index 100% rename from src/wasmgen/src/util.rs rename to src/rust/util.rs diff --git a/src/wasmgen/src/c_api.rs b/src/rust/wasmgen/c_api.rs similarity index 76% rename from src/wasmgen/src/c_api.rs rename to src/rust/wasmgen/c_api.rs index 4dfc494c..18e89eda 100644 --- a/src/wasmgen/src/c_api.rs +++ b/src/rust/wasmgen/c_api.rs @@ -1,6 +1,7 @@ -use ::util::PackedStr; +use util::PackedStr; -pub use ::module_init::{ setup, get_module }; +pub use wasmgen::module_init::wg_setup; +use wasmgen::module_init::get_module; #[no_mangle] pub fn wg_get_code_section() -> *mut Vec { @@ -53,14 +54,14 @@ pub fn wg_commit_instruction_body_to_cs() { mod tests { use std::io::prelude::*; use std::fs::File; - use ::c_api::*; - use ::util::*; - use ::wasm_util::*; - use ::module_init::*; + use util::*; + use wasmgen::c_api::*; + use wasmgen::wasm_util::*; + use wasmgen::module_init::*; #[test] fn c_api_test() { - setup(); + wg_setup(); let m = get_module(); let cs = &mut get_module().cs; let instruction_body = &mut get_module().instruction_body; @@ -73,19 +74,19 @@ mod tests { wg_push_i32(cs, 2); wg_call_fn(instruction_body, m.get_fn_idx(pack_str("baz"), FN1_RET_TYPE_INDEX)); - wg_drop(instruction_body); + wg_call_fn(instruction_body, m.get_fn_idx(pack_str("foo"), FN1_TYPE_INDEX)); wg_commit_instruction_body_to_cs(); - wg_finish(1); + wg_finish(0); let op_ptr = wg_get_op_ptr(); let op_len = wg_get_op_len(); dbg_log!("op_ptr: {:?}, op_len: {:?}", op_ptr, op_len); - // XXX: move file path - let mut f = File::create("c_api_test.wasm").expect("creating c_api_test.wasm"); - f.write_all(&get_module().op).expect("write c_api_test.wasm"); + let mut f = File::create("build/wg_dummy_output.wasm").expect("creating wg_dummy_output.wasm"); + f.write_all(&get_module().op).expect("write wg_dummy_output.wasm"); } } + diff --git a/src/wasmgen/src/lib.rs b/src/rust/wasmgen/mod.rs similarity index 60% rename from src/wasmgen/src/lib.rs rename to src/rust/wasmgen/mod.rs index 0dea0d98..62e52c09 100644 --- a/src/wasmgen/src/lib.rs +++ b/src/rust/wasmgen/mod.rs @@ -1,11 +1,6 @@ -#[macro_use] -mod dbg; - -#[macro_use] -mod util; - mod wasm_opcodes; mod module_init; pub mod c_api; pub mod wasm_util; + diff --git a/src/wasmgen/src/module_init.rs b/src/rust/wasmgen/module_init.rs similarity index 96% rename from src/wasmgen/src/module_init.rs rename to src/rust/wasmgen/module_init.rs index c05f0cb3..849cf2c0 100644 --- a/src/wasmgen/src/module_init.rs +++ b/src/rust/wasmgen/module_init.rs @@ -1,20 +1,27 @@ use std::ptr::NonNull; use std::mem; -use ::util::{ +use util::{ PackedStr, unpack_str, write_fixed_leb16_at_idx, write_fixed_leb32_at_idx, write_leb_u32, - SafeToU8, SafeToU16, SafeToI32, + SafeToU8, SafeToU16, }; -use ::wasm_opcodes as op; +use wasmgen::wasm_opcodes as op; +#[allow(dead_code)] pub const FN0_TYPE_INDEX: u8 = 0; +#[allow(dead_code)] pub const FN1_TYPE_INDEX: u8 = 1; +#[allow(dead_code)] pub const FN2_TYPE_INDEX: u8 = 2; +#[allow(dead_code)] pub const FN3_TYPE_INDEX: u8 = 3; +#[allow(dead_code)] pub const FN0_RET_TYPE_INDEX: u8 = 4; +#[allow(dead_code)] pub const FN1_RET_TYPE_INDEX: u8 = 5; +#[allow(dead_code)] pub const FN2_RET_TYPE_INDEX: u8 = 6; pub const NR_FN_TYPE_INDEXES: u8 = 7; @@ -24,7 +31,7 @@ static mut MODULE_PTR: NonNull = unsafe { }; #[no_mangle] -pub fn setup() { +pub fn wg_setup() { let wm = Box::new(WasmBuilder::new()); unsafe { MODULE_PTR = NonNull::new(Box::into_raw(wm)).expect("assigning module ptr"); @@ -32,7 +39,6 @@ pub fn setup() { get_module().init(); } -#[no_mangle] pub fn get_module<'a>() -> &'a mut WasmBuilder { unsafe { MODULE_PTR.as_mut() @@ -301,15 +307,12 @@ impl WasmBuilder { } pub fn get_fn_idx(&mut self, fn_name: PackedStr, type_index: u8) -> u16 { - dbg_log!("getting fn idx for '{}'", unpack_str(fn_name)); match self.get_import_index(fn_name) { Some(idx) => { - dbg_log!("found existing entry at idx {}", idx); idx }, None => { let idx = self.write_import_entry(fn_name, type_index); - dbg_log!("wrote new import entry at idx {}", idx); idx }, } @@ -331,8 +334,8 @@ impl WasmBuilder { #[cfg(test)] mod tests { - use ::module_init::*; - use ::util::pack_str; + use wasmgen::module_init::*; + use util::pack_str; #[test] fn import_table_management() { diff --git a/src/wasmgen/src/wasm_opcodes.rs b/src/rust/wasmgen/wasm_opcodes.rs similarity index 100% rename from src/wasmgen/src/wasm_opcodes.rs rename to src/rust/wasmgen/wasm_opcodes.rs diff --git a/src/wasmgen/src/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs similarity index 98% rename from src/wasmgen/src/wasm_util.rs rename to src/rust/wasmgen/wasm_util.rs index 39b9d5b3..4cb84ab3 100644 --- a/src/wasmgen/src/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -1,5 +1,5 @@ -use ::wasm_opcodes as op; -use ::util::{ write_fixed_leb16_at_idx, write_leb_i32, write_leb_u32 }; +use wasmgen::wasm_opcodes as op; +use util::{ write_fixed_leb16_at_idx, write_leb_i32, write_leb_u32 }; #[no_mangle] pub fn wg_push_i32(buf: &mut Vec, v: i32) { diff --git a/tests/rust/verify-wasmgen-dummy-output.js b/tests/rust/verify-wasmgen-dummy-output.js new file mode 100755 index 00000000..fd1408a0 --- /dev/null +++ b/tests/rust/verify-wasmgen-dummy-output.js @@ -0,0 +1,34 @@ +#!/usr/bin/env node +"use strict"; + +process.on("unhandledRejection", exn => { throw exn; }); + +const fs = require('fs'); +const path = require('path'); + +const DUMMY_MODULE_PATH = path.resolve(__dirname, '../../build/wg_dummy_output.wasm'); +const dummy_module = fs.readFileSync(DUMMY_MODULE_PATH); + +const wm = new WebAssembly.Module(dummy_module); +const mem = new WebAssembly.Memory({ initial: 256 }); + +// These tests have to be kept in sync with src/rust/wasmgen/module_init.rs' tests +// XXX: make the test more complex, involving locals, conditionals and stuff + +let baz_recd_arg; +function baz(arg) { + baz_recd_arg = arg; + return 456; +} + +let foo_recd_arg; +function foo(arg) { + foo_recd_arg = arg; +} + +const i = new WebAssembly.Instance(wm, { 'e': { m: mem, baz, foo } }); +i.exports.f(); + +console.assert(baz_recd_arg === 2, `baz returned: "${baz_recd_arg}"`); +console.assert(foo_recd_arg === 456, `foo returned: "${foo_recd_arg}"`); + From e462e0aaf10bfd7f61806a1ba865b4196f95b496 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sat, 30 Jun 2018 00:52:14 +0530 Subject: [PATCH 0992/2137] add quickcheck test for {un}pack_str --- Cargo.toml | 2 +- src/rust/lib.rs | 4 ++++ src/rust/util.rs | 10 +++++++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f8191cc4..1050d6c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" publish = false [dependencies] -lazy_static = "1.0" +quickcheck = "0.6.2" [lib] crate-type = ["cdylib"] diff --git a/src/rust/lib.rs b/src/rust/lib.rs index eeaf2d4f..787dcdad 100644 --- a/src/rust/lib.rs +++ b/src/rust/lib.rs @@ -1,3 +1,7 @@ +#[cfg(test)] +#[macro_use] +extern crate quickcheck; + #[macro_use] mod dbg; diff --git a/src/rust/util.rs b/src/rust/util.rs index 98adf145..ff7c7694 100644 --- a/src/rust/util.rs +++ b/src/rust/util.rs @@ -122,7 +122,7 @@ pub type PackedStr = (u64, u64, u64); #[allow(dead_code)] pub fn pack_str(s: &str) -> PackedStr { - assert!(s.len() <= 16); + assert!(s.len() <= 24); let mut a: [u8; 24] = [0; 24]; for (i, ch) in s.char_indices() { a[i] = ch as u8; @@ -175,4 +175,12 @@ mod tests { assert_eq!("abcdefghijkl", unpack_str(pstr)); } + quickcheck! { + fn prop(xs: Vec) -> bool { + if xs.len() > 24 || xs.contains(&0) { return true; } + let xs = String::from_utf8(xs).expect("get string"); + xs == unpack_str(pack_str(&xs)) + } + } + } From 853bf477ccc41d9d18df366be383eb562805e68c Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sat, 30 Jun 2018 07:09:28 +0530 Subject: [PATCH 0993/2137] minor fixes --- .cargo/config | 2 + .travis-run-jshint.sh | 3 + .travis-run-lint.sh | 3 - Cargo.toml | 3 +- Makefile | 3 +- docker/test-image/Dockerfile | 1 - src/rust/lib.rs | 1 - src/rust/util.rs | 12 +- src/rust/wasmgen/c_api.rs | 6 +- src/rust/wasmgen/module_init.rs | 208 +++++++++++----------- tests/rust/verify-wasmgen-dummy-output.js | 9 +- 11 files changed, 126 insertions(+), 125 deletions(-) create mode 100644 .cargo/config create mode 100755 .travis-run-jshint.sh delete mode 100755 .travis-run-lint.sh diff --git a/.cargo/config b/.cargo/config new file mode 100644 index 00000000..fcd33554 --- /dev/null +++ b/.cargo/config @@ -0,0 +1,2 @@ +[build] +target-dir = "build" diff --git a/.travis-run-jshint.sh b/.travis-run-jshint.sh new file mode 100755 index 00000000..ce3c99be --- /dev/null +++ b/.travis-run-jshint.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +set -e +make jshint diff --git a/.travis-run-lint.sh b/.travis-run-lint.sh deleted file mode 100755 index 17dd1e24..00000000 --- a/.travis-run-lint.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash -set -e -make jshint rustfmt clang-tidy diff --git a/Cargo.toml b/Cargo.toml index 1050d6c8..c15c5d91 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "v86oxide" version = "0.1.0" publish = false -[dependencies] +[dev-dependencies] quickcheck = "0.6.2" [lib] @@ -18,4 +18,3 @@ panic = "abort" lto = true incremental = false panic = "abort" - diff --git a/Makefile b/Makefile index 43e25dc8..90f4259d 100644 --- a/Makefile +++ b/Makefile @@ -106,7 +106,6 @@ CC_FLAGS=\ CARGO_FLAGS=\ --target wasm32-unknown-unknown \ - --target-dir build/ \ -- -Clink-args="--import-memory" CORE_FILES=const.js config.js io.js main.js lib.js coverage.js ide.js pci.js floppy.js \ @@ -319,7 +318,7 @@ devices-test: all-debug ./tests/devices/virtio_9p.js rust-test: - env RUST_BACKTRACE=full RUST_TEST_THREADS=1 cargo test --target-dir build -- --nocapture + env RUST_BACKTRACE=full RUST_TEST_THREADS=1 cargo test -- --nocapture ./tests/rust/verify-wasmgen-dummy-output.js covreport: diff --git a/docker/test-image/Dockerfile b/docker/test-image/Dockerfile index 100e8a7e..bb6ebfcb 100644 --- a/docker/test-image/Dockerfile +++ b/docker/test-image/Dockerfile @@ -14,4 +14,3 @@ RUN \ rustup toolchain install nightly && \ rustup target add wasm32-unknown-unknown --toolchain nightly && \ rustup component add rustfmt-preview --toolchain nightly - diff --git a/src/rust/lib.rs b/src/rust/lib.rs index 787dcdad..a1cf1068 100644 --- a/src/rust/lib.rs +++ b/src/rust/lib.rs @@ -9,4 +9,3 @@ mod dbg; mod util; pub mod wasmgen; - diff --git a/src/rust/util.rs b/src/rust/util.rs index ff7c7694..31202d38 100644 --- a/src/rust/util.rs +++ b/src/rust/util.rs @@ -165,6 +165,7 @@ pub fn _log_to_js_console(s: T) { #[cfg(test)] mod tests { use ::util::*; + use quickcheck::TestResult; #[test] fn packed_strs() { @@ -176,10 +177,13 @@ mod tests { } quickcheck! { - fn prop(xs: Vec) -> bool { - if xs.len() > 24 || xs.contains(&0) { return true; } - let xs = String::from_utf8(xs).expect("get string"); - xs == unpack_str(pack_str(&xs)) + fn prop(xs: Vec) -> TestResult { + if xs.len() > 24 || xs.contains(&0) { return TestResult::discard(); } + let xs = match String::from_utf8(xs) { + Ok(x) => x, + Err(_) => { return TestResult::discard(); }, + }; + TestResult::from_bool(xs == unpack_str(pack_str(&xs))) } } diff --git a/src/rust/wasmgen/c_api.rs b/src/rust/wasmgen/c_api.rs index 18e89eda..24e8ac04 100644 --- a/src/rust/wasmgen/c_api.rs +++ b/src/rust/wasmgen/c_api.rs @@ -5,7 +5,7 @@ use wasmgen::module_init::get_module; #[no_mangle] pub fn wg_get_code_section() -> *mut Vec { - &mut get_module().cs + &mut get_module().code_section } #[no_mangle] @@ -63,7 +63,7 @@ mod tests { fn c_api_test() { wg_setup(); let m = get_module(); - let cs = &mut get_module().cs; + let cs = &mut get_module().code_section; let instruction_body = &mut get_module().instruction_body; wg_call_fn(cs, m.get_fn_idx(pack_str("foo"), FN0_TYPE_INDEX)); @@ -85,7 +85,7 @@ mod tests { dbg_log!("op_ptr: {:?}, op_len: {:?}", op_ptr, op_len); let mut f = File::create("build/wg_dummy_output.wasm").expect("creating wg_dummy_output.wasm"); - f.write_all(&get_module().op).expect("write wg_dummy_output.wasm"); + f.write_all(&get_module().output).expect("write wg_dummy_output.wasm"); } } diff --git a/src/rust/wasmgen/module_init.rs b/src/rust/wasmgen/module_init.rs index 849cf2c0..4cd9e7d2 100644 --- a/src/rust/wasmgen/module_init.rs +++ b/src/rust/wasmgen/module_init.rs @@ -46,8 +46,8 @@ pub fn get_module<'a>() -> &'a mut WasmBuilder { } pub struct WasmBuilder { - pub op: Vec, - pub cs: Vec, + pub output: Vec, + pub code_section: Vec, pub instruction_body: Vec, idx_import_table_size: usize, // for rewriting once finished @@ -63,8 +63,8 @@ pub struct WasmBuilder { impl WasmBuilder { pub fn new() -> Self { WasmBuilder { - op: Vec::with_capacity(256), - cs: Vec::with_capacity(256), + output: Vec::with_capacity(256), + code_section: Vec::with_capacity(256), instruction_body: Vec::with_capacity(256), idx_import_table_size: 0, @@ -79,23 +79,23 @@ impl WasmBuilder { } pub fn init(&mut self) { - self.op.extend("\0asm".as_bytes()); + self.output.extend("\0asm".as_bytes()); // wasm version in leb128, 4 bytes - self.op.push(op::WASM_VERSION); self.op.push(0); self.op.push(0); self.op.push(0); + self.output.push(op::WASM_VERSION); self.output.push(0); self.output.push(0); self.output.push(0); self.write_type_section(); self.write_import_section_preamble(); // store state of current pointers etc. so we can reset them later - self.initial_static_size = self.op.len(); + self.initial_static_size = self.output.len(); } pub fn reset(&mut self) { - self.op.drain(self.initial_static_size..); + self.output.drain(self.initial_static_size..); self.set_import_table_size(2); self.set_import_count(0); - self.cs.clear(); + self.code_section.clear(); self.instruction_body.clear(); } @@ -105,96 +105,96 @@ impl WasmBuilder { self.write_export_section(); // write code section preamble - self.op.push(op::SC_CODE); + self.output.push(op::SC_CODE); - let idx_code_section_size = self.op.len(); // we will write to this location later - self.op.push(0); self.op.push(0); // write temp val for now using 4 bytes - self.op.push(0); self.op.push(0); + let idx_code_section_size = self.output.len(); // we will write to this location later + self.output.push(0); self.output.push(0); // write temp val for now using 4 bytes + self.output.push(0); self.output.push(0); - self.op.push(1); // number of function bodies: just 1 + self.output.push(1); // number of function bodies: just 1 // same as above but for body size of the function - let idx_fn_body_size = self.op.len(); - self.op.push(0); self.op.push(0); - self.op.push(0); self.op.push(0); + let idx_fn_body_size = self.output.len(); + self.output.push(0); self.output.push(0); + self.output.push(0); self.output.push(0); - self.op.push(1); // count of local blocks + self.output.push(1); // count of local blocks dbg_assert!(no_of_locals_i32 < 128); - self.op.push(no_of_locals_i32); self.op.push(op::TYPE_I32); + self.output.push(no_of_locals_i32); self.output.push(op::TYPE_I32); - self.op.append(&mut self.cs); + self.output.append(&mut self.code_section); - self.op.push(op::OP_END); + self.output.push(op::OP_END); // write the actual sizes to the pointer locations stored above. We subtract 4 from the actual // value because the ptr itself points to four bytes - let fn_body_size = (self.op.len() - idx_fn_body_size - 4) as u32; - write_fixed_leb32_at_idx(&mut self.op, idx_fn_body_size, fn_body_size); + let fn_body_size = (self.output.len() - idx_fn_body_size - 4) as u32; + write_fixed_leb32_at_idx(&mut self.output, idx_fn_body_size, fn_body_size); - let code_section_size = (self.op.len() - idx_code_section_size - 4) as u32; - write_fixed_leb32_at_idx(&mut self.op, idx_code_section_size, code_section_size); + let code_section_size = (self.output.len() - idx_code_section_size - 4) as u32; + write_fixed_leb32_at_idx(&mut self.output, idx_code_section_size, code_section_size); - self.op.len() + self.output.len() } pub fn write_type_section(&mut self) { - self.op.push(op::SC_TYPE); + self.output.push(op::SC_TYPE); - let idx_section_size = self.op.len(); - self.op.push(0); + let idx_section_size = self.output.len(); + self.output.push(0); - self.op.push(NR_FN_TYPE_INDEXES); // number of type descriptors + self.output.push(NR_FN_TYPE_INDEXES); // number of type descriptors // FN0 - self.op.push(op::TYPE_FUNC); - self.op.push(0); // no args - self.op.push(0); // no return val + self.output.push(op::TYPE_FUNC); + self.output.push(0); // no args + self.output.push(0); // no return val // FN1 - self.op.push(op::TYPE_FUNC); - self.op.push(1); - self.op.push(op::TYPE_I32); - self.op.push(0); + self.output.push(op::TYPE_FUNC); + self.output.push(1); + self.output.push(op::TYPE_I32); + self.output.push(0); // FN2 - self.op.push(op::TYPE_FUNC); - self.op.push(2); - self.op.push(op::TYPE_I32); - self.op.push(op::TYPE_I32); - self.op.push(0); + self.output.push(op::TYPE_FUNC); + self.output.push(2); + self.output.push(op::TYPE_I32); + self.output.push(op::TYPE_I32); + self.output.push(0); // FN3 - self.op.push(op::TYPE_FUNC); - self.op.push(3); - self.op.push(op::TYPE_I32); - self.op.push(op::TYPE_I32); - self.op.push(op::TYPE_I32); - self.op.push(0); + self.output.push(op::TYPE_FUNC); + self.output.push(3); + self.output.push(op::TYPE_I32); + self.output.push(op::TYPE_I32); + self.output.push(op::TYPE_I32); + self.output.push(0); // FN0_RET - self.op.push(op::TYPE_FUNC); - self.op.push(0); - self.op.push(1); - self.op.push(op::TYPE_I32); + self.output.push(op::TYPE_FUNC); + self.output.push(0); + self.output.push(1); + self.output.push(op::TYPE_I32); // FN1_RET - self.op.push(op::TYPE_FUNC); - self.op.push(1); - self.op.push(op::TYPE_I32); - self.op.push(1); - self.op.push(op::TYPE_I32); + self.output.push(op::TYPE_FUNC); + self.output.push(1); + self.output.push(op::TYPE_I32); + self.output.push(1); + self.output.push(op::TYPE_I32); // FN2_RET - self.op.push(op::TYPE_FUNC); - self.op.push(2); - self.op.push(op::TYPE_I32); - self.op.push(op::TYPE_I32); - self.op.push(1); - self.op.push(op::TYPE_I32); + self.output.push(op::TYPE_FUNC); + self.output.push(2); + self.output.push(op::TYPE_I32); + self.output.push(op::TYPE_I32); + self.output.push(1); + self.output.push(op::TYPE_I32); - let new_len = self.op.len(); + let new_len = self.output.len(); let size = (new_len - 1) - idx_section_size; - self.op[idx_section_size] = size.safe_to_u8(); + self.output[idx_section_size] = size.safe_to_u8(); } /// Goes over the import block to find index of an import entry by function name @@ -204,9 +204,9 @@ impl WasmBuilder { for i in 0..self.import_count { offset += 1; // skip length of module name offset += 1; // skip module name itself - let len = self.op[offset] as usize; + let len = self.output[offset] as usize; offset += 1; - let name = self.op.get(offset..(offset + len)).expect("get function name"); + let name = self.output.get(offset..(offset + len)).expect("get function name"); if name == fn_name.as_bytes() { return Some(i); } @@ -221,39 +221,39 @@ impl WasmBuilder { dbg_assert!(count < 0x4000); self.import_count = count; let idx_import_count = self.idx_import_count; - write_fixed_leb16_at_idx(&mut self.op, idx_import_count, count); + write_fixed_leb16_at_idx(&mut self.output, idx_import_count, count); } pub fn set_import_table_size(&mut self, size: usize) { dbg_assert!(size < 0x4000); self.import_table_size = size; let idx_import_table_size = self.idx_import_table_size; - write_fixed_leb16_at_idx(&mut self.op, idx_import_table_size, size.safe_to_u16()); + write_fixed_leb16_at_idx(&mut self.output, idx_import_table_size, size.safe_to_u16()); } pub fn write_import_section_preamble(&mut self) { - self.op.push(op::SC_IMPORT); + self.output.push(op::SC_IMPORT); - self.idx_import_table_size = self.op.len(); - self.op.push(1 | 0b10000000); self.op.push(2); // 2 in 2 byte leb + self.idx_import_table_size = self.output.len(); + self.output.push(1 | 0b10000000); self.output.push(2); // 2 in 2 byte leb - self.idx_import_count = self.op.len(); - self.op.push(1 | 0b10000000); self.op.push(0); // 0 in 2 byte leb + self.idx_import_count = self.output.len(); + self.output.push(1 | 0b10000000); self.output.push(0); // 0 in 2 byte leb // here after starts the actual list of imports - self.idx_import_entries = self.op.len(); + self.idx_import_entries = self.output.len(); } pub fn write_memory_import(&mut self) { - self.op.push(1); - self.op.push('e' as u8); - self.op.push(1); - self.op.push('m' as u8); + self.output.push(1); + self.output.push('e' as u8); + self.output.push(1); + self.output.push('m' as u8); - self.op.push(op::EXT_MEMORY); + self.output.push(op::EXT_MEMORY); - self.op.push(0); // memory flag, 0 for no maximum memory limit present - write_leb_u32(&mut self.op, 256); // initial memory length of 256 pages, takes 2 bytes in leb128 + self.output.push(0); // memory flag, 0 for no maximum memory limit present + write_leb_u32(&mut self.output, 256); // initial memory length of 256 pages, takes 2 bytes in leb128 let new_import_count = self.import_count + 1; self.set_import_count(new_import_count); @@ -263,13 +263,13 @@ impl WasmBuilder { } pub fn write_import_entry(&mut self, fn_name: PackedStr, type_index: u8) -> u16 { - self.op.push(1); // length of module name - self.op.push('e' as u8); // module name + self.output.push(1); // length of module name + self.output.push('e' as u8); // module name let fn_name = unpack_str(fn_name); - self.op.push(fn_name.len().safe_to_u8()); - self.op.extend(fn_name.as_bytes()); - self.op.push(op::EXT_FUNCTION); - self.op.push(type_index); + self.output.push(fn_name.len().safe_to_u8()); + self.output.extend(fn_name.as_bytes()); + self.output.push(op::EXT_FUNCTION); + self.output.push(type_index); let new_import_count = self.import_count + 1; self.set_import_count(new_import_count); @@ -281,29 +281,29 @@ impl WasmBuilder { } pub fn write_function_section(&mut self, count: u8) { - self.op.push(op::SC_FUNCTION); - self.op.push(1 + count); // length of this section - self.op.push(count); // count of signature indices + self.output.push(op::SC_FUNCTION); + self.output.push(1 + count); // length of this section + self.output.push(count); // count of signature indices for _ in 0..count { - self.op.push(FN1_TYPE_INDEX); + self.output.push(FN1_TYPE_INDEX); } } pub fn write_export_section(&mut self) { - self.op.push(op::SC_EXPORT); - self.op.push(1 + 1 + 1 + 1 + 2); // size of this section - self.op.push(1); // count of table: just one function exported + self.output.push(op::SC_EXPORT); + self.output.push(1 + 1 + 1 + 1 + 2); // size of this section + self.output.push(1); // count of table: just one function exported - self.op.push(1); // length of exported function name - self.op.push('f' as u8); // function name - self.op.push(op::EXT_FUNCTION); + self.output.push(1); // length of exported function name + self.output.push('f' as u8); // function name + self.output.push(op::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 - let next_op_idx = self.op.len(); - self.op.push(0); self.op.push(0); // add 2 bytes for writing 16 byte val - write_fixed_leb16_at_idx(&mut self.op, next_op_idx, self.import_count - 1); + let next_op_idx = self.output.len(); + self.output.push(0); self.output.push(0); // add 2 bytes for writing 16 byte val + write_fixed_leb16_at_idx(&mut self.output, next_op_idx, self.import_count - 1); } pub fn get_fn_idx(&mut self, fn_name: PackedStr, type_index: u8) -> u16 { @@ -319,15 +319,15 @@ impl WasmBuilder { } pub fn get_op_ptr(&self) -> *const u8 { - self.op.as_ptr() + self.output.as_ptr() } pub fn get_op_len(&self) -> usize { - self.op.len() + self.output.len() } pub fn commit_instruction_body_cs(&mut self) { - self.cs.append(&mut self.instruction_body); + self.code_section.append(&mut self.instruction_body); } } diff --git a/tests/rust/verify-wasmgen-dummy-output.js b/tests/rust/verify-wasmgen-dummy-output.js index fd1408a0..29b32157 100755 --- a/tests/rust/verify-wasmgen-dummy-output.js +++ b/tests/rust/verify-wasmgen-dummy-output.js @@ -3,10 +3,10 @@ process.on("unhandledRejection", exn => { throw exn; }); -const fs = require('fs'); -const path = require('path'); +const fs = require("fs"); +const path = require("path"); -const DUMMY_MODULE_PATH = path.resolve(__dirname, '../../build/wg_dummy_output.wasm'); +const DUMMY_MODULE_PATH = path.resolve(__dirname, "../../build/wg_dummy_output.wasm"); const dummy_module = fs.readFileSync(DUMMY_MODULE_PATH); const wm = new WebAssembly.Module(dummy_module); @@ -26,9 +26,8 @@ function foo(arg) { foo_recd_arg = arg; } -const i = new WebAssembly.Instance(wm, { 'e': { m: mem, baz, foo } }); +const i = new WebAssembly.Instance(wm, { "e": { m: mem, baz, foo } }); i.exports.f(); console.assert(baz_recd_arg === 2, `baz returned: "${baz_recd_arg}"`); console.assert(foo_recd_arg === 456, `foo returned: "${foo_recd_arg}"`); - From 892e589be5d5649f8406740a7d1f7b207c4ecc21 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sat, 30 Jun 2018 07:11:13 +0530 Subject: [PATCH 0994/2137] allow unused macros --- src/rust/dbg.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rust/dbg.rs b/src/rust/dbg.rs index af330aa5..18715440 100644 --- a/src/rust/dbg.rs +++ b/src/rust/dbg.rs @@ -16,6 +16,7 @@ macro_rules! dbg_assert { } #[cfg(target_arch = "wasm32")] +#[allow(unused_macros)] macro_rules! dbg_log { ($fmt:expr) => { use ::util::{ DEBUG, _log_to_js_console }; @@ -28,6 +29,7 @@ macro_rules! dbg_log { } #[cfg(target_arch = "wasm32")] +#[allow(unused_macros)] macro_rules! dbg_assert { ($cond:expr) => { use ::util::{ DEBUG, _log_to_js_console, abort }; From ba5b8b730cff2702139f3841ed30783759c5bda1 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sat, 30 Jun 2018 07:39:44 +0530 Subject: [PATCH 0995/2137] re-add jshint to .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index dace51de..9e37f6b1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ env: - TEST_SUITE=unit-qemu - TEST_SUITE=nasm - TEST_SUITE=rust - - TEST_SUITE=lint + - TEST_SUITE=jshint - TEST_SUITE=jit-paging - TEST_SUITE=expect - TEST_SUITE=devices From 2f1ff12f9153063dc3320215773ac2a0d90cf347 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sat, 30 Jun 2018 07:48:56 +0530 Subject: [PATCH 0996/2137] remove travis scripts --- .travis-run-devices.sh | 5 ----- .travis-run-expect.sh | 3 --- .travis-run-integration.sh | 6 ------ .travis-run-jit-paging.sh | 5 ----- .travis-run-jshint.sh | 3 --- .travis-run-nasm-jit-always.sh | 4 ---- .travis-run-nasm.sh | 4 ---- .travis-run-rust.sh | 3 --- .travis-run-unit-qemu.sh | 5 ----- .travis-run-unit.sh | 5 ----- .travis.yml | 21 --------------------- 11 files changed, 64 deletions(-) delete mode 100755 .travis-run-devices.sh delete mode 100755 .travis-run-expect.sh delete mode 100755 .travis-run-integration.sh delete mode 100755 .travis-run-jit-paging.sh delete mode 100755 .travis-run-jshint.sh delete mode 100755 .travis-run-nasm-jit-always.sh delete mode 100755 .travis-run-nasm.sh delete mode 100755 .travis-run-rust.sh delete mode 100755 .travis-run-unit-qemu.sh delete mode 100755 .travis-run-unit.sh delete mode 100644 .travis.yml diff --git a/.travis-run-devices.sh b/.travis-run-devices.sh deleted file mode 100755 index 55789618..00000000 --- a/.travis-run-devices.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -e -mkdir -p images -(cd images && curl --compressed -O https://copy.sh/v86/images/linux4.iso) -make devices-test diff --git a/.travis-run-expect.sh b/.travis-run-expect.sh deleted file mode 100755 index ff54b7e7..00000000 --- a/.travis-run-expect.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash -set -e -make expect-tests diff --git a/.travis-run-integration.sh b/.travis-run-integration.sh deleted file mode 100755 index 58ef8d36..00000000 --- a/.travis-run-integration.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash -set -e -mkdir -p images -(cd images && curl --compressed -OOOOOOOOOO https://copy.sh/v86/images/{linux.iso,linux3.iso,kolibri.img,windows101.img,os8.dsk,freedos722.img,openbsd.img,oberon.dsk,oberon-boot.dsk}) -make build/libv86.js -tests/full/run.js diff --git a/.travis-run-jit-paging.sh b/.travis-run-jit-paging.sh deleted file mode 100755 index cbfed9f0..00000000 --- a/.travis-run-jit-paging.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -e -mkdir -p images -(cd images && curl --compressed -O https://copy.sh/v86/images/linux4.iso) -make jitpagingtests diff --git a/.travis-run-jshint.sh b/.travis-run-jshint.sh deleted file mode 100755 index ce3c99be..00000000 --- a/.travis-run-jshint.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash -set -e -make jshint diff --git a/.travis-run-nasm-jit-always.sh b/.travis-run-nasm-jit-always.sh deleted file mode 100755 index 0ec3045d..00000000 --- a/.travis-run-nasm-jit-always.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -e -./tests/nasm/create_tests.js -make -j $(nproc --all) nasmtests-force-jit diff --git a/.travis-run-nasm.sh b/.travis-run-nasm.sh deleted file mode 100755 index e596f97c..00000000 --- a/.travis-run-nasm.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -e -./tests/nasm/create_tests.js -make -j $(nproc --all) nasmtests diff --git a/.travis-run-rust.sh b/.travis-run-rust.sh deleted file mode 100755 index 50b98bee..00000000 --- a/.travis-run-rust.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash -set -e -make rust-test diff --git a/.travis-run-unit-qemu.sh b/.travis-run-unit-qemu.sh deleted file mode 100755 index e7005730..00000000 --- a/.travis-run-unit-qemu.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -e -mkdir -p images -(cd images && curl --compressed -O https://copy.sh/v86/images/linux4.iso) -make qemutests diff --git a/.travis-run-unit.sh b/.travis-run-unit.sh deleted file mode 100755 index 3e60572a..00000000 --- a/.travis-run-unit.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -e -make build/libv86.js -(cd tests/kvm-unit-tests && ./configure && make) -tests/kvm-unit-tests/run.js tests/kvm-unit-tests/x86/realmode.flat diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 9e37f6b1..00000000 --- a/.travis.yml +++ /dev/null @@ -1,21 +0,0 @@ -language: node_js -node_js: - - "6.10.2" -dist: trusty -before_install: - - sudo dpkg --add-architecture i386 - - sudo apt-get update -qq -install: - - sudo apt-get install -y gcc-multilib nasm gdb -script: - - "./.travis-run-$TEST_SUITE.sh" -env: - - TEST_SUITE=unit - - TEST_SUITE=integration - - TEST_SUITE=unit-qemu - - TEST_SUITE=nasm - - TEST_SUITE=rust - - TEST_SUITE=jshint - - TEST_SUITE=jit-paging - - TEST_SUITE=expect - - TEST_SUITE=devices From f346fb2c7d0c4a63b216bf2a69aaed8b5037fc06 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sat, 30 Jun 2018 08:02:30 +0530 Subject: [PATCH 0997/2137] increase freedos tests time limit to 20 seconds --- tests/full/run.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/full/run.js b/tests/full/run.js index c6347b46..3fda72e3 100755 --- a/tests/full/run.js +++ b/tests/full/run.js @@ -81,7 +81,7 @@ if(cluster.isMaster) { name: "FreeDOS boot", fda: root_path + "/images/freedos722.img", - timeout: 10, + timeout: 20, expected_texts: [ "Welcome to FreeDOS", ], @@ -89,7 +89,7 @@ if(cluster.isMaster) { name: "FreeDOS boot with Bochs BIOS", fda: root_path + "/images/freedos722.img", - timeout: 10, + timeout: 20, alternative_bios: true, expected_texts: [ "Welcome to FreeDOS", From afbe240060a36b919ba630f4a6a716482b2270af Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 28 Jun 2018 20:34:23 -0600 Subject: [PATCH 0998/2137] Optimise gen_safe_write32: Remove jit cache check The jit cache check (whether a physical page contains code) has been integrated into the tlb: When code is created or deleted, the tlb is iterated to set or clear all "has_code" bits. When a new tlb entry is created, the mapped physical page is checked and the "has_code" bit is set correspondingly. The new invariant is: (page_entry_points[p] != empty || page_first_jit_cache_entry[p] != empty) implies (forall v: if(tlb_data[v] == p) tlb_data[v].has_code) --- src/native/codegen/codegen.c | 37 ------------------ src/native/cpu.c | 73 ++++++++++++++++++++++++++++++++++-- src/native/cpu.h | 3 ++ src/native/jit.c | 18 ++++++++- 4 files changed, 88 insertions(+), 43 deletions(-) diff --git a/src/native/codegen/codegen.c b/src/native/codegen/codegen.c index 2ed55926..6e17df6d 100644 --- a/src/native/codegen/codegen.c +++ b/src/native/codegen/codegen.c @@ -364,43 +364,6 @@ void gen_safe_write32(int32_t local_for_address, int32_t local_for_value) wg_get_local(instruction_body, local_for_value); wg_store_unaligned_i32(instruction_body, (uint32_t) mem8); - // Only call jit_dirty_cache_single if absolutely necessary - // Pseudo: - // /* continued within can_use_fast_path branch */ - // if(page_first_jit_cache_entry[phys_address >> 12] != JIT_CACHE_ARRAY_NO_NEXT_ENTRY || - // page_entry_points[phys_address >> 12] != ENTRY_POINT_END) - // { - // jit_dirty_cache_single(phys_address); - // } - // } - - wg_get_local(instruction_body, phys_addr_local); - wg_push_i32(instruction_body, 12); - wg_shr_u32(instruction_body); - - SCALE_INDEX_FOR_ARRAY32(page_first_jit_cache_entry); - wg_load_aligned_i32_from_stack(instruction_body, (uint32_t) page_first_jit_cache_entry); - - wg_push_i32(instruction_body, JIT_CACHE_ARRAY_NO_NEXT_ENTRY); - wg_ne_i32(instruction_body); - - wg_get_local(instruction_body, phys_addr_local); - wg_push_i32(instruction_body, 12); - wg_shr_u32(instruction_body); - wg_push_i32(instruction_body, 1); - wg_shl_i32(instruction_body); - wg_load_aligned_u16_from_stack(instruction_body, (uint32_t) page_entry_points); - - wg_push_i32(instruction_body, ENTRY_POINT_END); - wg_ne_i32(instruction_body); - - wg_or_i32(instruction_body); - - wg_if_void(instruction_body); - wg_get_local(instruction_body, phys_addr_local); - gen_call_fn1("jit_dirty_cache_single", 22); - wg_block_end(instruction_body); - // Pseudo: // else { safe_read32_slow(address, value); } wg_else(instruction_body); diff --git a/src/native/cpu.c b/src/native/cpu.c index e13530f5..4913e857 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -80,6 +80,12 @@ void record_page_entry(uint32_t phys_addr) bool did_insert_or_find = false; + if(entry_points[0] == ENTRY_POINT_END) + { + // first entry in this page + tlb_set_has_code(page, true); + } + for(int32_t i = 0; i < MAX_ENTRIES_PER_PAGE; i++) { if(entry_points[i] == ENTRY_POINT_END) @@ -359,12 +365,21 @@ int32_t do_page_translation(int32_t addr, bool for_writing, bool user) #endif } + bool is_in_mapped_range = in_mapped_range(high); + int32_t physical_page = (uint32_t)high >> 12; + + bool has_code = !is_in_mapped_range && ( + page_first_jit_cache_entry[physical_page] != JIT_CACHE_ARRAY_NO_NEXT_ENTRY || + page_entry_points[physical_page][0] != ENTRY_POINT_END + ); + int32_t info_bits = TLB_VALID | (can_write ? 0 : TLB_READONLY) | (allow_user ? 0 : TLB_NO_USER) | - (in_mapped_range(high) ? TLB_IN_MAPPED_RANGE : 0) | - (global && (cr[4] & CR4_PGE) ? TLB_GLOBAL : 0); + (is_in_mapped_range ? TLB_IN_MAPPED_RANGE : 0) | + (global && (cr[4] & CR4_PGE) ? TLB_GLOBAL : 0) | + (has_code ? TLB_HAS_CODE : 0); assert(((high ^ page << 12) & 0xFFF) == 0); tlb_data[page] = high ^ page << 12 | info_bits; @@ -372,6 +387,27 @@ int32_t do_page_translation(int32_t addr, bool for_writing, bool user) return high; } +void tlb_set_has_code(uint32_t physical_page, bool has_code) +{ + assert(physical_page < (1 << 20)); + + for(int32_t i = 0; i < valid_tlb_entries_count; i++) + { + int32_t page = valid_tlb_entries[i]; + int32_t entry = tlb_data[page]; + + if(entry) + { + uint32_t tlb_physical_page = (uint32_t)entry >> 12 ^ page; + + if(physical_page == tlb_physical_page) + { + tlb_data[page] = has_code ? entry | TLB_HAS_CODE : entry & ~TLB_HAS_CODE; + } + } + } +} + void writable_or_pagefault(int32_t addr, int32_t size) { dbg_assert(size < 0x1000); @@ -753,6 +789,33 @@ void check_jit_cache_array_invariants(void) assert(reached); } } + + for(int32_t i = 0; i < valid_tlb_entries_count; i++) + { + int32_t page = valid_tlb_entries[i]; + int32_t entry = tlb_data[page]; + + if(!entry || (entry & TLB_IN_MAPPED_RANGE)) // there's no code in mapped memory + { + continue; + } + + int32_t physical_page = (uint32_t)entry >> 12 ^ page; + assert(!in_mapped_range(physical_page << 12)); + + bool entry_has_code = entry & TLB_HAS_CODE; + bool has_code = + page_first_jit_cache_entry[physical_page] != JIT_CACHE_ARRAY_NO_NEXT_ENTRY || + page_entry_points[physical_page][0] != ENTRY_POINT_END; + + // If some code has been created in a page, the corresponding tlb entries must be marked + assert(!has_code || entry_has_code); + + // If a tlb entry is marked to have code, the physical page should + // contain code (the converse is not a bug, but indicates a cleanup + // problem when clearing code from a page) + assert(!entry_has_code || has_code); + } #endif } @@ -2113,7 +2176,7 @@ int32_t safe_read32s(int32_t address) #if 1 int32_t base = (uint32_t)address >> 12; int32_t entry = tlb_data[base]; - int32_t info_bits = entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL; + int32_t info_bits = entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~TLB_HAS_CODE; // XXX: Paging check @@ -2213,9 +2276,11 @@ void safe_write32(int32_t address, int32_t value) // - allowed to write in user-mode // - not in memory mapped area // - can be accessed from any cpl + // - does not contain code uint32_t phys_address = entry & ~0xFFF ^ address; - jit_dirty_cache_single(phys_address); + assert(page_first_jit_cache_entry[phys_address >> 12] == JIT_CACHE_ARRAY_NO_NEXT_ENTRY); + assert(page_entry_points[phys_address >> 12][0] == ENTRY_POINT_END); assert(!in_mapped_range(phys_address)); *(int32_t*)(mem8 + phys_address) = value; return; diff --git a/src/native/cpu.h b/src/native/cpu.h index 6832689c..0188f41f 100644 --- a/src/native/cpu.h +++ b/src/native/cpu.h @@ -126,6 +126,7 @@ int32_t valid_tlb_entries_count; #define TLB_NO_USER (1 << 2) #define TLB_IN_MAPPED_RANGE (1 << 3) #define TLB_GLOBAL (1 << 4) +#define TLB_HAS_CODE (1 << 5) // Indices for local variables and function arguments (which are accessed as local variables) for // the generated WASM function @@ -156,6 +157,8 @@ bool same_page(int32_t, int32_t); int32_t get_eflags(void); uint32_t translate_address_read(int32_t address); uint32_t translate_address_write(int32_t address); +void tlb_set_has_code(uint32_t physical_page, bool has_code); + void writable_or_pagefault(int32_t addr, int32_t size); int32_t read_imm8(void); int32_t read_imm8s(void); diff --git a/src/native/jit.c b/src/native/jit.c index 80e3a1c1..8da495db 100644 --- a/src/native/jit.c +++ b/src/native/jit.c @@ -105,6 +105,12 @@ void remove_jit_cache_wasm_index(int32_t page, uint16_t wasm_table_index) free_wasm_table_index(wasm_table_index); } + if(page_first_jit_cache_entry[page] == JIT_CACHE_ARRAY_NO_NEXT_ENTRY && + page_entry_points[page][0] == ENTRY_POINT_END) + { + tlb_set_has_code(page, false); + } + #if CHECK_JIT_CACHE_ARRAY_INVARIANTS // sanity check that the above iteration deleted all entries @@ -195,17 +201,18 @@ void jit_clear_page(uint32_t index) assert(wasm_table_index_pending_free_count < WASM_TABLE_SIZE); wasm_table_index_pending_free[wasm_table_index_pending_free_count++] = wasm_table_index; } - - check_jit_cache_array_invariants(); } void jit_dirty_index(uint32_t index) { assert(index < MAX_PHYSICAL_PAGES); + + bool did_have_code = false; int32_t cache_array_index = page_first_jit_cache_entry[index]; if(cache_array_index != JIT_CACHE_ARRAY_NO_NEXT_ENTRY) { + did_have_code = true; jit_clear_page(index); } @@ -213,6 +220,8 @@ void jit_dirty_index(uint32_t index) if(entry_points[0] != ENTRY_POINT_END) { + did_have_code = true; + // don't try to compile code in this page anymore until it's hot again hot_code_addresses[jit_hot_hash_page(index)] = 0; @@ -233,6 +242,11 @@ void jit_dirty_index(uint32_t index) } #endif } + + if(did_have_code) + { + tlb_set_has_code(index, false); + } } /* From bcefd54349786029cb55b3725371c630c77b5260 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Mon, 2 Jul 2018 06:57:48 +0530 Subject: [PATCH 0999/2137] fix rustfmt invocation --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 90f4259d..260f0464 100644 --- a/Makefile +++ b/Makefile @@ -332,7 +332,7 @@ jshint: node_modules/.bin/jshint ./node_modules/.bin/jshint --config=./.jshint.json src tests gen rustfmt: $(RUST_FILES) - cargo fmt --all -- --write-mode check + cargo +nightly fmt --all -- --check build/capstone-x86.min.js: mkdir -p build From 2e24cdf61e5db4c6636e1dddb068539cf9bee0ee Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 29 Jun 2018 10:21:10 -0600 Subject: [PATCH 1000/2137] Add comment regarding tlb_data --- src/native/cpu.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/native/cpu.c b/src/native/cpu.c index 4913e857..33f53c29 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -346,6 +346,10 @@ int32_t do_page_translation(int32_t addr, bool for_writing, bool user) assert(valid_tlb_entries_count < VALID_TLB_ENTRY_MAX); valid_tlb_entries[valid_tlb_entries_count++] = page; + + // TODO: Check that there are no duplicates in valid_tlb_entries + // XXX: There will probably be duplicates due to invlpg deleting + // entries from tlb_data but not from valid_tlb_entries } else { @@ -2483,6 +2487,10 @@ void invlpg(int32_t addr) //dbg_log("invlpg: addr=" + h(addr >>> 0), LOG_CPU); int32_t page = (uint32_t)addr >> 12; + // Note: Doesn't remove this page from valid_tlb_entries: This isn't + // necessary, because when valid_tlb_entries grows too large, it will be + // empties by calling clear_tlb, which removes this entry as it isn't global. + // This however means that valid_tlb_entries can contain some invalid entries tlb_data[page] = 0; *last_virt_eip = -1; From 0fde39d22b69760331f49b2943169648fa3de6ce Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 29 Jun 2018 10:38:26 -0600 Subject: [PATCH 1001/2137] Stats for safe_{read,write}32 fast/slow path --- src/browser/print_stats.js | 12 +++++++ src/native/config.h | 1 + src/native/cpu.c | 64 ++++++++++++++++++++++++++++++++++ src/native/profiler/profiler.h | 14 ++++++++ 4 files changed, 91 insertions(+) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index cbb24082..33a4442c 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -29,6 +29,18 @@ const print_stats = { "RUN_FROM_CACHE", "RUN_FROM_CACHE_STEPS", "TRIGGER_CPU_EXCEPTION", + "S_SAFE_READ32_FAST", + "S_SAFE_READ32_SLOW_PAGE_CROSSED", + "S_SAFE_READ32_SLOW_NOT_VALID", + "S_SAFE_READ32_SLOW_NOT_USER", + "S_SAFE_READ32_SLOW_IN_MAPPED_RANGE", + "S_SAFE_WRITE32_FAST", + "S_SAFE_WRITE32_SLOW_PAGE_CROSSED", + "S_SAFE_WRITE32_SLOW_NOT_VALID", + "S_SAFE_WRITE32_SLOW_NOT_USER", + "S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE", + "S_SAFE_WRITE32_SLOW_READ_ONLY", + "S_SAFE_WRITE32_SLOW_HAS_CODE", "DO_RUN", "DO_MANY_CYCLES", "CYCLE_INTERNAL", diff --git a/src/native/config.h b/src/native/config.h index 3f365b8d..6603c69f 100644 --- a/src/native/config.h +++ b/src/native/config.h @@ -39,6 +39,7 @@ #define ENABLE_PROFILER 0 #define ENABLE_PROFILER_OPSTATS 0 +#define ENABLE_PROFILER_SAFE_READ_WRITE 0 // Note: needs to be enabled here and in config.js #define DUMP_UNCOMPILED_ASSEMBLY 0 diff --git a/src/native/cpu.c b/src/native/cpu.c index 33f53c29..c7be55f7 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -2186,6 +2186,9 @@ int32_t safe_read32s(int32_t address) if(info_bits == TLB_VALID && (address & 0xFFF) <= (0x1000 - 4)) { +#if ENABLE_PROFILER_SAFE_READ_WRITE + profiler_stat_increment(S_SAFE_READ32_FAST); +#endif // - not in memory mapped area // - can be accessed from any cpl @@ -2193,6 +2196,31 @@ int32_t safe_read32s(int32_t address) assert(!in_mapped_range(phys_address)); return *(int32_t*)(mem8 + phys_address); } + else + { +#if ENABLE_PROFILER_SAFE_READ_WRITE + if((address & 0xFFF) > 0x1000 - 4) + { + profiler_stat_increment(S_SAFE_READ32_SLOW_PAGE_CROSSED); + } + else if((info_bits & TLB_VALID) == 0) + { + profiler_stat_increment(S_SAFE_READ32_SLOW_NOT_VALID); + } + else if(info_bits & TLB_NO_USER) + { + profiler_stat_increment(S_SAFE_READ32_SLOW_NOT_USER); + } + else if(info_bits & TLB_IN_MAPPED_RANGE) + { + profiler_stat_increment(S_SAFE_READ32_SLOW_IN_MAPPED_RANGE); + } + else + { + dbg_assert(false); + } +#endif + } #endif return safe_read32s_slow(address); @@ -2277,6 +2305,9 @@ void safe_write32(int32_t address, int32_t value) if(info_bits == TLB_VALID && (address & 0xFFF) <= (0x1000 - 4)) { +#if ENABLE_PROFILER_SAFE_READ_WRITE + profiler_stat_increment(S_SAFE_WRITE32_FAST); +#endif // - allowed to write in user-mode // - not in memory mapped area // - can be accessed from any cpl @@ -2289,6 +2320,39 @@ void safe_write32(int32_t address, int32_t value) *(int32_t*)(mem8 + phys_address) = value; return; } + else + { +#if ENABLE_PROFILER_SAFE_READ_WRITE + if((address & 0xFFF) > 0x1000 - 4) + { + profiler_stat_increment(S_SAFE_WRITE32_SLOW_PAGE_CROSSED); + } + else if((info_bits & TLB_VALID) == 0) + { + profiler_stat_increment(S_SAFE_WRITE32_SLOW_NOT_VALID); + } + else if(info_bits & TLB_NO_USER) + { + profiler_stat_increment(S_SAFE_WRITE32_SLOW_NOT_USER); + } + else if(info_bits & TLB_IN_MAPPED_RANGE) + { + profiler_stat_increment(S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE); + } + else if(info_bits & TLB_READONLY) + { + profiler_stat_increment(S_SAFE_WRITE32_SLOW_READ_ONLY); + } + else if(info_bits & TLB_HAS_CODE) + { + profiler_stat_increment(S_SAFE_WRITE32_SLOW_HAS_CODE); + } + else + { + dbg_assert(false); + } +#endif + } #endif safe_write32_slow(address, value); diff --git a/src/native/profiler/profiler.h b/src/native/profiler/profiler.h index 6cdf7fd0..4e568131 100644 --- a/src/native/profiler/profiler.h +++ b/src/native/profiler/profiler.h @@ -23,6 +23,20 @@ enum stat_name { S_TRIGGER_CPU_EXCEPTION, + S_SAFE_READ32_FAST, + S_SAFE_READ32_SLOW_PAGE_CROSSED, + S_SAFE_READ32_SLOW_NOT_VALID, + S_SAFE_READ32_SLOW_NOT_USER, + S_SAFE_READ32_SLOW_IN_MAPPED_RANGE, + + S_SAFE_WRITE32_FAST, + S_SAFE_WRITE32_SLOW_PAGE_CROSSED, + S_SAFE_WRITE32_SLOW_NOT_VALID, + S_SAFE_WRITE32_SLOW_NOT_USER, + S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE, + S_SAFE_WRITE32_SLOW_READ_ONLY, + S_SAFE_WRITE32_SLOW_HAS_CODE, + S_DO_RUN, S_DO_MANY_CYCLES, S_CYCLE_INTERNAL, From a35825b3628ed58f3ba2b81f2f6e1e4f869f21d9 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 29 Jun 2018 10:39:26 -0600 Subject: [PATCH 1002/2137] Stat for current tlb utilisation --- src/browser/print_stats.js | 1 + src/native/cpu.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index 33a4442c..c6617b11 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -67,6 +67,7 @@ const print_stats = { text += "\n"; + text += "TLB_ENTRIES=" + cpu.wm.exports["_get_valid_tlb_entries_count"]() + "\n"; text += "CACHE_UNUSED=" + cpu.wm.exports["_jit_unused_cache_stat"]() + "\n"; text += "WASM_TABLE_FREE=" + cpu.wm.exports["_get_wasm_table_index_free_list_count"]() + "\n"; diff --git a/src/native/cpu.c b/src/native/cpu.c index c7be55f7..32280df1 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -412,6 +412,11 @@ void tlb_set_has_code(uint32_t physical_page, bool has_code) } } +int32_t get_valid_tlb_entries_count(void) +{ + return valid_tlb_entries_count; +} + void writable_or_pagefault(int32_t addr, int32_t size) { dbg_assert(size < 0x1000); From 6807c2e77247f44fdc47174de599610a843f7a06 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 29 Jun 2018 10:39:51 -0600 Subject: [PATCH 1003/2137] Minor: Trailing comma --- src/browser/lib.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/lib.js b/src/browser/lib.js index c960c581..e757370c 100644 --- a/src/browser/lib.js +++ b/src/browser/lib.js @@ -142,7 +142,7 @@ var ASYNC_SAFE = false; imports["env"]["table"] = new WebAssembly.Table({ "initial": dylink.table_size + table_size + EXTRA_TABLE_SPACE_FOR_EMULATED_FP, - "element": "anyfunc" + "element": "anyfunc", }); imports["env"]["tableBase"] = table_size; From 21c57bc920fc2bfd497b899960925d2ac95c5f69 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 29 Jun 2018 10:42:07 -0600 Subject: [PATCH 1004/2137] Use constant for wasm table name --- src/browser/lib.js | 2 +- src/const.js | 3 +++ src/cpu.js | 6 +++--- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/browser/lib.js b/src/browser/lib.js index e757370c..1efc9ffb 100644 --- a/src/browser/lib.js +++ b/src/browser/lib.js @@ -140,7 +140,7 @@ var ASYNC_SAFE = false; // here const EXTRA_TABLE_SPACE_FOR_EMULATED_FP = 10000; - imports["env"]["table"] = new WebAssembly.Table({ + imports["env"][WASM_EXPORT_TABLE_NAME] = new WebAssembly.Table({ "initial": dylink.table_size + table_size + EXTRA_TABLE_SPACE_FOR_EMULATED_FP, "element": "anyfunc", }); diff --git a/src/const.js b/src/const.js index aa053e8b..08260a11 100644 --- a/src/const.js +++ b/src/const.js @@ -361,6 +361,9 @@ var WASM_TABLE_SIZE = 0x10000; /** @const */ var JIT_CACHE_ARRAY_SIZE = 0x40000; +/** @const */ +const WASM_EXPORT_TABLE_NAME = "table"; + /** @const */ // The space we need for misc internal state before the beginning of mem8; see global_pointers.h diff --git a/src/cpu.js b/src/cpu.js index 333af17f..c14f0432 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -306,7 +306,7 @@ CPU.prototype.wasm_patch = function(wm) CPU.prototype.jit_clear_func = function(index) { dbg_assert(index >= 0 && index < WASM_TABLE_SIZE); - this.wm.imports.env.table.set(index, null); + this.wm.imports.env[WASM_EXPORT_TABLE_NAME].set(index, null); }; CPU.prototype.get_state = function() @@ -1295,7 +1295,7 @@ CPU.prototype.codegen_finalize = function(wasm_table_index, start, end, first_op first_opcode, state_flags); // The following will throw if f isn't an exported function - this.wm.imports["env"].table.set(wasm_table_index, f); + this.wm.imports["env"][WASM_EXPORT_TABLE_NAME].set(wasm_table_index, f); if(this.test_hook_did_finalize_wasm) { @@ -1517,7 +1517,7 @@ CPU.prototype.jit_empty_cache = function() { this.wm.exports["_jit_empty_cache"](); - const table = this.wm.imports["env"].table; + const table = this.wm.imports["env"][WASM_EXPORT_TABLE_NAME]; for(let i = 0; i < WASM_TABLE_SIZE; i++) { From d13cf327626698b6809c3b49e25209e761c6b0ef Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 29 Jun 2018 10:42:56 -0600 Subject: [PATCH 1005/2137] Delete dead profiling code --- src/cpu.js | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index c14f0432..1db4fd85 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -1210,35 +1210,6 @@ if(typeof window !== "undefined") ]; } -/** @const */ -var PROFILING = false; - -if(PROFILING) -{ - var instruction_total = new Float64Array(256); - var instruction_count = new Float64Array(256); - - window["print_profiling"] = function print_profiling() - { - var prof_instructions = []; - for(var i = 0; i < 256; i++) prof_instructions[i] = { - n: h(i, 2), - total: instruction_total[i], - count: instruction_count[i], - per: (instruction_total[i] / instruction_count[i]) || 0, - }; - - console.log("count:"); - console.table(prof_instructions.sort((p0, p1) => p1.count - p0.count)); - - console.log("time:"); - console.table(prof_instructions.sort((p0, p1) => p1.total - p0.total)); - - console.log("time/count:"); - console.table(prof_instructions.sort((p0, p1) => p1.per - p0.per)); - }; -} - var seen_code = {}; var seen_code_uncompiled = {}; From c06d141ea6e8957542d1bdee91ce0269cbb18a68 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 29 Jun 2018 10:47:04 -0600 Subject: [PATCH 1006/2137] Run full tests in debug mode --- Makefile | 2 +- tests/full/run.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 260f0464..3105af95 100644 --- a/Makefile +++ b/Makefile @@ -281,7 +281,7 @@ $(CLOSURE): mv $(CLOSURE_DIR)/*.jar $(CLOSURE) rm $(CLOSURE_DIR)/compiler-latest.zip -tests: build/libv86.js build/v86.wasm build/v86oxide.wasm +tests: all-debug ./tests/full/run.js nasmtests: all-debug diff --git a/tests/full/run.js b/tests/full/run.js index 3fda72e3..e34db8f1 100755 --- a/tests/full/run.js +++ b/tests/full/run.js @@ -11,7 +11,7 @@ const VERBOSE = false; try { - var V86 = require("../../build/libv86.js").V86; + var V86 = require("../../build/libv86-debug.js").V86; } catch(e) { From b5de7a6d5301d3b3d6b15993a7b34be184568aef Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 1 Jul 2018 15:16:15 -0600 Subject: [PATCH 1007/2137] PCI: Change assertion into warning (bochs bios) --- src/pci.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/pci.js b/src/pci.js index d4b83ee2..f866a532 100644 --- a/src/pci.js +++ b/src/pci.js @@ -347,8 +347,14 @@ PCI.prototype.pci_write16 = function(address, written) return; } - dbg_assert(!(addr >= 0x10 && addr < 0x2C || addr >= 0x30 && addr < 0x34), - "PCI: Expected 32-bit write, got 16-bit (addr: " + h(addr) + ")"); + if(addr >= 0x10 && addr < 0x2C) + { + // Bochs bios + dbg_log("Warning: PCI: Expected 32-bit write, got 16-bit (addr: " + h(addr) + ")"); + } + + dbg_assert(!(addr >= 0x30 && addr < 0x34), + "PCI: Expected 32-bit write, got 16-bit (addr: " + h(addr) + ")"); dbg_log("PCI writ16 dev=" + h(bdf >> 3, 2) + " (" + device.name + ") addr=" + h(addr, 4) + " value=" + h(written, 4), LOG_PCI); From ba0c875254d543755215ae5fb3c11fca2aa1a433 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 1 Jul 2018 15:26:37 -0600 Subject: [PATCH 1008/2137] libwabt: Download stable release --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3105af95..b185dfda 100644 --- a/Makefile +++ b/Makefile @@ -340,7 +340,9 @@ build/capstone-x86.min.js: build/libwabt.js: mkdir -p build - wget -P build https://raw.githubusercontent.com/WebAssembly/wabt/master/demo/libwabt.js + wget -P build https://github.com/WebAssembly/wabt/archive/1.0.1.zip + unzip -j -d build/ build/1.0.1.zip wabt-1.0.1/demo/libwabt.js + rm build/1.0.1.zip clang-tidy: clang-tidy \ From f8dd22cf044bf4da6c01c43894399d90f0e0abad Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 1 Jul 2018 16:11:01 -0600 Subject: [PATCH 1009/2137] Expect test: Accept tests interactively (#15) --- tests/expect/run.js | 71 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 5 deletions(-) diff --git a/tests/expect/run.js b/tests/expect/run.js index a613f6ae..bb4477ae 100755 --- a/tests/expect/run.js +++ b/tests/expect/run.js @@ -3,6 +3,7 @@ const fs = require("fs"); const path = require("path"); +const process = require("process"); const { spawnSync } = require("child_process"); const libwabt = require("../../build/libwabt.js"); @@ -40,10 +41,39 @@ function run_all() }; }); - files.forEach(run_test); + next_test(0); + + function next_test(i) + { + if(files[i]) + { + run_test(files[i], () => next_test(i + 1)); + } + } } -function run_test({ name, executable_file, expect_file, actual_file, actual_wasm, asm_file }) +let stdin_data = ""; +let stdin_buffer = Buffer.alloc(100); +const stdin = fs.openSync("/dev/stdin", "r"); + +function readline() +{ + const bytesRead = fs.readSync(stdin, stdin_buffer, 0, stdin_buffer.length, null); + stdin_data += stdin_buffer.slice(0, bytesRead).toString(); + + const nl = stdin_data.indexOf("\n"); + + if(nl === -1) + { + return readline(); + } + + const line = stdin_data.slice(0, nl); + stdin_data = stdin_data.slice(nl + 1); + return line; +} + +function run_test({ name, executable_file, expect_file, actual_file, actual_wasm, asm_file }, onfinished) { const emulator = new V86({ autostart: false, @@ -101,18 +131,47 @@ function run_test({ name, executable_file, expect_file, actual_file, actual_wasm { console.log(result.stdout); console.log(result.stderr); - const failure_message = `${name}.asm failed: + + if(process.argv.includes("--interactive")) + { + while(true) + { + console.log("Pick: [y] Accept this change and overwrite, [n] Don't accept this change, [q] Quit"); + const choice = readline(); + + if(choice === "y") + { + console.log(`Running: cp ${actual_file} ${expect_file}`); + fs.copyFileSync(actual_file, expect_file); + break; + } + else if(choice === "n") + { + break; + } + else if(choice === "q") + { + process.exit(1); + } + } + } + else + { + const failure_message = `${name}.asm failed: The code generator produced different code. If you believe this change is intentional, verify the diff above and run the following command to accept the change: cp ${actual_file} ${expect_file} When done, re-run this test to confirm that all expect-tests pass. + +Hint: Use tests/expect/run.js --interactive to interactively accept changes. `; - console.log(failure_message); + console.log(failure_message); - process.exit(1); + process.exit(1); + } } else { @@ -120,6 +179,8 @@ When done, re-run this test to confirm that all expect-tests pass. console.assert(!result.stdout); console.assert(!result.stderr); } + + onfinished(); }; if(is_32) From 8ac1e2a995b5f83f4d82178aad7693d8fdae44b3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 1 Jul 2018 16:15:36 -0600 Subject: [PATCH 1010/2137] Update expect tests due to optimisation of loop iterations --- tests/expect/tests/if.wast | 21 ++++++--------------- tests/expect/tests/indirect-call.wast | 17 ++++------------- tests/expect/tests/mov16.wast | 15 +++------------ tests/expect/tests/mov32-mem.wast | 15 +++------------ tests/expect/tests/mov32-reg.wast | 15 +++------------ tests/expect/tests/pop.wast | 15 +++------------ tests/expect/tests/push.wast | 15 +++------------ tests/expect/tests/while-do.wast | 25 ++++++++----------------- 8 files changed, 33 insertions(+), 105 deletions(-) diff --git a/tests/expect/tests/if.wast b/tests/expect/tests/if.wast index 3a7e4c24..61a9475f 100644 --- a/tests/expect/tests/if.wast +++ b/tests/expect/tests/if.wast @@ -20,20 +20,11 @@ (set_local $l1 (i32.const 10000)) (loop $L0 - (set_local $l1 - (i32.add - (get_local $l1) - (i32.const -1))) - (if $I1 - (i32.eqz - (get_local $l1)) - (then - (return))) - (block $B2 - (block $B3 - (block $B4 - (block $B5 - (br_table $B5 $B4 $B3 $B2 + (block $B1 + (block $B2 + (block $B3 + (block $B4 + (br_table $B4 $B3 $B2 $B1 (get_local $l0))) (i32.store (i32.const 560) @@ -56,7 +47,7 @@ (i32.load (i32.const 664)) (i32.const 2))) - (if $I6 + (if $I5 (call $e.test_nle) (then (i32.store diff --git a/tests/expect/tests/indirect-call.wast b/tests/expect/tests/indirect-call.wast index fca91991..00b4a8b4 100644 --- a/tests/expect/tests/indirect-call.wast +++ b/tests/expect/tests/indirect-call.wast @@ -17,19 +17,10 @@ (set_local $l1 (i32.const 10000)) (loop $L0 - (set_local $l1 - (i32.add - (get_local $l1) - (i32.const -1))) - (if $I1 - (i32.eqz - (get_local $l1)) - (then - (return))) - (block $B2 - (block $B3 - (block $B4 - (br_table $B4 $B3 $B2 + (block $B1 + (block $B2 + (block $B3 + (br_table $B3 $B2 $B1 (get_local $l0))) (i32.store (i32.const 560) diff --git a/tests/expect/tests/mov16.wast b/tests/expect/tests/mov16.wast index 6f915065..31399bd6 100644 --- a/tests/expect/tests/mov16.wast +++ b/tests/expect/tests/mov16.wast @@ -19,18 +19,9 @@ (set_local $l1 (i32.const 10000)) (loop $L0 - (set_local $l1 - (i32.add - (get_local $l1) - (i32.const -1))) - (if $I1 - (i32.eqz - (get_local $l1)) - (then - (return))) - (block $B2 - (block $B3 - (br_table $B3 $B2 + (block $B1 + (block $B2 + (br_table $B2 $B1 (get_local $l0))) (i32.store (i32.const 560) diff --git a/tests/expect/tests/mov32-mem.wast b/tests/expect/tests/mov32-mem.wast index 071fe11a..383877e4 100644 --- a/tests/expect/tests/mov32-mem.wast +++ b/tests/expect/tests/mov32-mem.wast @@ -19,18 +19,9 @@ (set_local $l1 (i32.const 10000)) (loop $L0 - (set_local $l1 - (i32.add - (get_local $l1) - (i32.const -1))) - (if $I1 - (i32.eqz - (get_local $l1)) - (then - (return))) - (block $B2 - (block $B3 - (br_table $B3 $B2 + (block $B1 + (block $B2 + (br_table $B2 $B1 (get_local $l0))) (i32.store (i32.const 560) diff --git a/tests/expect/tests/mov32-reg.wast b/tests/expect/tests/mov32-reg.wast index 3d8c2fda..fd9618a9 100644 --- a/tests/expect/tests/mov32-reg.wast +++ b/tests/expect/tests/mov32-reg.wast @@ -20,18 +20,9 @@ (set_local $l1 (i32.const 10000)) (loop $L0 - (set_local $l1 - (i32.add - (get_local $l1) - (i32.const -1))) - (if $I1 - (i32.eqz - (get_local $l1)) - (then - (return))) - (block $B2 - (block $B3 - (br_table $B3 $B2 + (block $B1 + (block $B2 + (br_table $B2 $B1 (get_local $l0))) (i32.store (i32.const 560) diff --git a/tests/expect/tests/pop.wast b/tests/expect/tests/pop.wast index a15d1f71..7a9d6064 100644 --- a/tests/expect/tests/pop.wast +++ b/tests/expect/tests/pop.wast @@ -17,18 +17,9 @@ (set_local $l1 (i32.const 10000)) (loop $L0 - (set_local $l1 - (i32.add - (get_local $l1) - (i32.const -1))) - (if $I1 - (i32.eqz - (get_local $l1)) - (then - (return))) - (block $B2 - (block $B3 - (br_table $B3 $B2 + (block $B1 + (block $B2 + (br_table $B2 $B1 (get_local $l0))) (i32.store (i32.const 560) diff --git a/tests/expect/tests/push.wast b/tests/expect/tests/push.wast index 79775931..6882b723 100644 --- a/tests/expect/tests/push.wast +++ b/tests/expect/tests/push.wast @@ -17,18 +17,9 @@ (set_local $l1 (i32.const 10000)) (loop $L0 - (set_local $l1 - (i32.add - (get_local $l1) - (i32.const -1))) - (if $I1 - (i32.eqz - (get_local $l1)) - (then - (return))) - (block $B2 - (block $B3 - (br_table $B3 $B2 + (block $B1 + (block $B2 + (br_table $B2 $B1 (get_local $l0))) (i32.store (i32.const 560) diff --git a/tests/expect/tests/while-do.wast b/tests/expect/tests/while-do.wast index e98eec81..c51c1e63 100644 --- a/tests/expect/tests/while-do.wast +++ b/tests/expect/tests/while-do.wast @@ -10,7 +10,7 @@ (import "e" "instr32_83_7_reg" (func $e.instr32_83_7_reg (type $t2))) (import "e" "test_z" (func $e.test_z (type $t4))) (import "e" "instr32_43" (func $e.instr32_43 (type $t0))) - (import "e" "instr_EB" (func $e.instr_EB (type $t1))) + (import "e" "instr32_EB" (func $e.instr32_EB (type $t1))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) @@ -20,20 +20,11 @@ (set_local $l1 (i32.const 10000)) (loop $L0 - (set_local $l1 - (i32.add - (get_local $l1) - (i32.const -1))) - (if $I1 - (i32.eqz - (get_local $l1)) - (then - (return))) - (block $B2 - (block $B3 - (block $B4 - (block $B5 - (br_table $B5 $B4 $B3 $B2 + (block $B1 + (block $B2 + (block $B3 + (block $B4 + (br_table $B4 $B3 $B2 $B1 (get_local $l0))) (i32.store (i32.const 560) @@ -56,7 +47,7 @@ (i32.load (i32.const 664)) (i32.const 2))) - (if $I6 + (if $I5 (call $e.test_z) (then (i32.store @@ -84,7 +75,7 @@ (i32.const 556)) (i32.const 3))) (call $e.instr32_43) - (call $e.instr_EB + (call $e.instr32_EB (i32.const -8)) (i32.store (i32.const 664) From 793c68a5011534b16e76ea420f8bf850b2ed9771 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 1 Jul 2018 16:17:01 -0600 Subject: [PATCH 1011/2137] Update expect tests due to optimisation of memory writes --- tests/expect/tests/mov32-mem.wast | 61 +++++++++---------------------- 1 file changed, 18 insertions(+), 43 deletions(-) diff --git a/tests/expect/tests/mov32-mem.wast b/tests/expect/tests/mov32-mem.wast index 383877e4..9465335c 100644 --- a/tests/expect/tests/mov32-mem.wast +++ b/tests/expect/tests/mov32-mem.wast @@ -7,7 +7,6 @@ (type $t5 (func (param i32) (result i32))) (type $t6 (func (param i32 i32) (result i32))) (import "e" "get_seg" (func $e.get_seg (type $t5))) - (import "e" "jit_dirty_cache_single" (func $e.jit_dirty_cache_single (type $t1))) (import "e" "safe_write32_slow" (func $e.safe_write32_slow (type $t2))) (import "e" "safe_read32s_slow" (func $e.safe_read32s_slow (type $t5))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) @@ -38,18 +37,18 @@ (set_local $l3 (i32.load (i32.const 4))) - (if $I4 + (if $I3 (i32.and (i32.eq (i32.and (tee_local $l4 - (i32.load offset=262144 + (i32.load offset=4194304 (i32.shl (i32.shr_u (get_local $l2) (i32.const 12)) (i32.const 2)))) - (i32.const 4079)) + (i32.const 4075)) (i32.const 1)) (i32.le_s (i32.and @@ -57,26 +56,14 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.store offset=8650752 align=1 + (i32.store offset=12582912 align=1 (tee_local $l4 (i32.xor (i32.and (get_local $l4) (i32.const -4096)) (get_local $l2))) - (get_local $l3)) - (if $I5 - (i32.ne - (i32.load offset=4456448 - (i32.shl - (i32.shr_u - (get_local $l4) - (i32.const 12)) - (i32.const 2))) - (i32.const -1)) - (then - (call $e.jit_dirty_cache_single - (get_local $l4))))) + (get_local $l3))) (else (call $e.safe_write32_slow (get_local $l2) @@ -98,18 +85,18 @@ (set_local $l3 (i32.load (i32.const 8))) - (if $I6 + (if $I4 (i32.and (i32.eq (i32.and (tee_local $l4 - (i32.load offset=262144 + (i32.load offset=4194304 (i32.shl (i32.shr_u (get_local $l2) (i32.const 12)) (i32.const 2)))) - (i32.const 4079)) + (i32.const 4075)) (i32.const 1)) (i32.le_s (i32.and @@ -117,26 +104,14 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.store offset=8650752 align=1 + (i32.store offset=12582912 align=1 (tee_local $l4 (i32.xor (i32.and (get_local $l4) (i32.const -4096)) (get_local $l2))) - (get_local $l3)) - (if $I7 - (i32.ne - (i32.load offset=4456448 - (i32.shl - (i32.shr_u - (get_local $l4) - (i32.const 12)) - (i32.const 2))) - (i32.const -1)) - (then - (call $e.jit_dirty_cache_single - (get_local $l4))))) + (get_local $l3))) (else (call $e.safe_write32_slow (get_local $l2) @@ -149,12 +124,12 @@ (i32.const 12))) (i32.store (i32.const 28) - (if $I8 (result i32) + (if $I5 (result i32) (i32.and (i32.eq (i32.and (tee_local $l3 - (i32.load offset=262144 + (i32.load offset=4194304 (i32.shl (i32.shr_u (tee_local $l2 @@ -167,7 +142,7 @@ (i32.const 3)))) (i32.const 12)) (i32.const 2)))) - (i32.const 4077)) + (i32.const 4073)) (i32.const 1)) (i32.le_s (i32.and @@ -175,7 +150,7 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.load offset=8650752 align=1 + (i32.load offset=12582912 align=1 (i32.xor (i32.and (get_local $l3) @@ -192,12 +167,12 @@ (i32.const 18))) (i32.store (i32.const 32) - (if $I9 (result i32) + (if $I6 (result i32) (i32.and (i32.eq (i32.and (tee_local $l3 - (i32.load offset=262144 + (i32.load offset=4194304 (i32.shl (i32.shr_u (tee_local $l2 @@ -210,7 +185,7 @@ (i32.const 3)))) (i32.const 12)) (i32.const 2)))) - (i32.const 4077)) + (i32.const 4073)) (i32.const 1)) (i32.le_s (i32.and @@ -218,7 +193,7 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.load offset=8650752 align=1 + (i32.load offset=12582912 align=1 (i32.xor (i32.and (get_local $l3) From 3812cb548947544d2a86f482d9345734ed824949 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 1 Jul 2018 16:17:54 -0600 Subject: [PATCH 1012/2137] Update expect tests due to following of call instructions --- tests/expect/tests/call.wast | 61 +++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/tests/expect/tests/call.wast b/tests/expect/tests/call.wast index 3da96bc9..c4c12622 100644 --- a/tests/expect/tests/call.wast +++ b/tests/expect/tests/call.wast @@ -9,6 +9,8 @@ (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "instr32_E8" (func $e.instr32_E8 (type $t1))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) + (import "e" "instr32_40" (func $e.instr32_40 (type $t0))) + (import "e" "instr32_C3" (func $e.instr32_C3 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) @@ -17,20 +19,33 @@ (set_local $l1 (i32.const 10000)) (loop $L0 - (set_local $l1 - (i32.add - (get_local $l1) - (i32.const -1))) - (if $I1 - (i32.eqz - (get_local $l1)) - (then - (return))) - (block $B2 - (block $B3 - (block $B4 - (br_table $B4 $B3 $B2 - (get_local $l0))) + (block $B1 + (block $B2 + (block $B3 + (block $B4 + (br_table $B4 $B3 $B2 $B1 + (get_local $l0))) + (i32.store + (i32.const 560) + (i32.load + (i32.const 556))) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 5))) + (call $e.instr32_E8 + (i32.const 1)) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) + (set_local $l0 + (i32.const 2)) + (br $L0)) (i32.store (i32.const 560) (i32.load @@ -40,9 +55,8 @@ (i32.add (i32.load (i32.const 556)) - (i32.const 5))) - (call $e.instr32_E8 - (i32.const 1)) + (i32.const 1))) + (call $e.instr_F4) (i32.store (i32.const 664) (i32.add @@ -52,20 +66,23 @@ (return)) (i32.store (i32.const 560) - (i32.load - (i32.const 556))) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 1))) (i32.store (i32.const 556) (i32.add (i32.load (i32.const 556)) - (i32.const 1))) - (call $e.instr_F4) + (i32.const 2))) + (call $e.instr32_40) + (call $e.instr32_C3) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) - (i32.const 1))) + (i32.const 2))) (return)) (unreachable)))) From 70bc0b5ec45dfa827af74949e15376dace1fc1ea Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 1 Jul 2018 17:11:41 -0600 Subject: [PATCH 1013/2137] Remove unused declaration --- src/native/js_imports.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/native/js_imports.h b/src/native/js_imports.h index 7a653297..8e0aa634 100644 --- a/src/native/js_imports.h +++ b/src/native/js_imports.h @@ -65,7 +65,6 @@ extern void io_port_write16(int32_t, int32_t); extern void io_port_write32(int32_t, int32_t); extern int32_t convert_f64_to_i32(double_t); extern void jit_clear_func(int32_t index); -void set_jit_import(int32_t fn_index, int32_t wasm_table_index); extern void call_interrupt_vector(int32_t interrupt_nr, bool is_software_int, bool has_error_code, int32_t error_code); extern void throw_cpu_exception(void); extern double_t microtick(void); From c8b88354288c47ffdcdced5c482a5a80896a02df Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 4 Jul 2018 16:56:23 -0600 Subject: [PATCH 1014/2137] Apply rustfmt --- src/rust/dbg.rs | 20 +++++++--- src/rust/util.rs | 27 ++++++++----- src/rust/wasmgen/c_api.rs | 23 +++++++---- src/rust/wasmgen/mod.rs | 3 +- src/rust/wasmgen/module_init.rs | 65 ++++++++++++++++++-------------- src/rust/wasmgen/wasm_opcodes.rs | 4 +- src/rust/wasmgen/wasm_util.rs | 5 ++- 7 files changed, 88 insertions(+), 59 deletions(-) diff --git a/src/rust/dbg.rs b/src/rust/dbg.rs index 18715440..f42f790e 100644 --- a/src/rust/dbg.rs +++ b/src/rust/dbg.rs @@ -32,26 +32,34 @@ macro_rules! dbg_log { #[allow(unused_macros)] macro_rules! dbg_assert { ($cond:expr) => { - use ::util::{ DEBUG, _log_to_js_console, abort }; + use util::{_log_to_js_console, abort, DEBUG}; if DEBUG && !$cond { _log_to_js_console(format!( "Assertion failed at {}:{}:{}: '{}'", - file!(), line!(), column!(), + file!(), + line!(), + column!(), stringify!($cond), )); - unsafe { abort(); } + unsafe { + abort(); + } } }; ($cond:expr, $desc:expr) => { - use ::util::{ DEBUG, _log_to_js_console, abort }; + use util::{_log_to_js_console, abort, DEBUG}; if DEBUG && !$cond { _log_to_js_console(format!( "Assertion failed at {}:{}:{}: '{}' - '{}'", - file!(), line!(), column!(), + file!(), + line!(), + column!(), stringify!($cond), $desc, )); - unsafe { abort(); } + unsafe { + abort(); + } } }; } diff --git a/src/rust/util.rs b/src/rust/util.rs index 31202d38..2c0f92ef 100644 --- a/src/rust/util.rs +++ b/src/rust/util.rs @@ -1,6 +1,12 @@ -pub trait SafeToU8 { fn safe_to_u8(self) -> u8; } -pub trait SafeToU16 { fn safe_to_u16(self) -> u16; } -pub trait SafeToI32 { fn safe_to_i32(self) -> i32; } +pub trait SafeToU8 { + fn safe_to_u8(self) -> u8; +} +pub trait SafeToU16 { + fn safe_to_u16(self) -> u16; +} +pub trait SafeToI32 { + fn safe_to_i32(self) -> i32; +} impl SafeToU8 for u16 { fn safe_to_u8(self) -> u8 { @@ -82,8 +88,7 @@ pub fn write_leb_i32(buf: &mut Vec, mut v: i32) { let sign_bit = byte & (1 << 6); if (v == 0 && sign_bit == 0) || (v == -1 && sign_bit != 0) { more = false; - } - else { + } else { byte |= 0b10000000; // turn on MSB } buf.push(byte); @@ -106,14 +111,14 @@ pub fn write_leb_u32(buf: &mut Vec, mut v: u32) { pub fn write_fixed_leb16_at_idx(vec: &mut Vec, idx: usize, x: u16) { dbg_assert!(x < (1 << 14)); // we have 14 bits of available space in 2 bytes for leb - vec[idx ] = ((x & 0b1111111) | 0b10000000) as u8; + vec[idx] = ((x & 0b1111111) | 0b10000000) as u8; vec[idx + 1] = (x >> 7) as u8; } pub fn write_fixed_leb32_at_idx(vec: &mut Vec, idx: usize, x: u32) { dbg_assert!(x < (1 << 28)); // we have 28 bits of available space in 4 bytes for leb - vec[idx ] = (x & 0b1111111) as u8 | 0b10000000; - vec[idx + 1] = (x >> 7 & 0b1111111) as u8 | 0b10000000; + vec[idx] = (x & 0b1111111) as u8 | 0b10000000; + vec[idx + 1] = (x >> 7 & 0b1111111) as u8 | 0b10000000; vec[idx + 2] = (x >> 14 & 0b1111111) as u8 | 0b10000000; vec[idx + 3] = (x >> 21 & 0b1111111) as u8; } @@ -159,13 +164,15 @@ use std::string::ToString; pub fn _log_to_js_console(s: T) { let s: String = s.to_string(); let len = s.len(); - unsafe { log_from_wasm(s.as_bytes().as_ptr(), len); } + unsafe { + log_from_wasm(s.as_bytes().as_ptr(), len); + } } #[cfg(test)] mod tests { - use ::util::*; use quickcheck::TestResult; + use util::*; #[test] fn packed_strs() { diff --git a/src/rust/wasmgen/c_api.rs b/src/rust/wasmgen/c_api.rs index 24e8ac04..6e88662c 100644 --- a/src/rust/wasmgen/c_api.rs +++ b/src/rust/wasmgen/c_api.rs @@ -1,7 +1,7 @@ use util::PackedStr; -pub use wasmgen::module_init::wg_setup; use wasmgen::module_init::get_module; +pub use wasmgen::module_init::wg_setup; #[no_mangle] pub fn wg_get_code_section() -> *mut Vec { @@ -52,12 +52,12 @@ pub fn wg_commit_instruction_body_to_cs() { #[cfg(test)] mod tests { - use std::io::prelude::*; use std::fs::File; + use std::io::prelude::*; use util::*; use wasmgen::c_api::*; - use wasmgen::wasm_util::*; use wasmgen::module_init::*; + use wasmgen::wasm_util::*; #[test] fn c_api_test() { @@ -73,8 +73,14 @@ mod tests { wg_reset(); wg_push_i32(cs, 2); - wg_call_fn(instruction_body, m.get_fn_idx(pack_str("baz"), FN1_RET_TYPE_INDEX)); - wg_call_fn(instruction_body, m.get_fn_idx(pack_str("foo"), FN1_TYPE_INDEX)); + wg_call_fn( + instruction_body, + m.get_fn_idx(pack_str("baz"), FN1_RET_TYPE_INDEX), + ); + wg_call_fn( + instruction_body, + m.get_fn_idx(pack_str("foo"), FN1_TYPE_INDEX), + ); wg_commit_instruction_body_to_cs(); @@ -84,9 +90,10 @@ mod tests { let op_len = wg_get_op_len(); dbg_log!("op_ptr: {:?}, op_len: {:?}", op_ptr, op_len); - let mut f = File::create("build/wg_dummy_output.wasm").expect("creating wg_dummy_output.wasm"); - f.write_all(&get_module().output).expect("write wg_dummy_output.wasm"); + let mut f = + File::create("build/wg_dummy_output.wasm").expect("creating wg_dummy_output.wasm"); + f.write_all(&get_module().output) + .expect("write wg_dummy_output.wasm"); } } - diff --git a/src/rust/wasmgen/mod.rs b/src/rust/wasmgen/mod.rs index 62e52c09..d7ee2beb 100644 --- a/src/rust/wasmgen/mod.rs +++ b/src/rust/wasmgen/mod.rs @@ -1,6 +1,5 @@ -mod wasm_opcodes; mod module_init; +mod wasm_opcodes; pub mod c_api; pub mod wasm_util; - diff --git a/src/rust/wasmgen/module_init.rs b/src/rust/wasmgen/module_init.rs index 4cd9e7d2..e61a4ca4 100644 --- a/src/rust/wasmgen/module_init.rs +++ b/src/rust/wasmgen/module_init.rs @@ -1,10 +1,9 @@ -use std::ptr::NonNull; use std::mem; +use std::ptr::NonNull; use util::{ - PackedStr, unpack_str, - write_fixed_leb16_at_idx, write_fixed_leb32_at_idx, write_leb_u32, - SafeToU8, SafeToU16, + unpack_str, write_fixed_leb16_at_idx, write_fixed_leb32_at_idx, write_leb_u32, PackedStr, + SafeToU16, SafeToU8, }; use wasmgen::wasm_opcodes as op; @@ -26,9 +25,8 @@ pub const FN2_RET_TYPE_INDEX: u8 = 6; pub const NR_FN_TYPE_INDEXES: u8 = 7; -static mut MODULE_PTR: NonNull = unsafe { - NonNull::new_unchecked(mem::align_of::() as *mut _) -}; +static mut MODULE_PTR: NonNull = + unsafe { NonNull::new_unchecked(mem::align_of::() as *mut _) }; #[no_mangle] pub fn wg_setup() { @@ -40,9 +38,7 @@ pub fn wg_setup() { } pub fn get_module<'a>() -> &'a mut WasmBuilder { - unsafe { - MODULE_PTR.as_mut() - } + unsafe { MODULE_PTR.as_mut() } } pub struct WasmBuilder { @@ -51,11 +47,11 @@ pub struct WasmBuilder { pub instruction_body: Vec, idx_import_table_size: usize, // for rewriting once finished - idx_import_count: usize, // for rewriting once finished - idx_import_entries: usize, // for searching the imports + idx_import_count: usize, // for rewriting once finished + idx_import_entries: usize, // for searching the imports import_table_size: usize, // the current import table size (to avoid reading 2 byte leb) - import_count: u16, // same as above + import_count: u16, // same as above initial_static_size: usize, // size of module after initialization, rest is drained on reset } @@ -82,7 +78,10 @@ impl WasmBuilder { self.output.extend("\0asm".as_bytes()); // wasm version in leb128, 4 bytes - self.output.push(op::WASM_VERSION); self.output.push(0); self.output.push(0); self.output.push(0); + self.output.push(op::WASM_VERSION); + self.output.push(0); + self.output.push(0); + self.output.push(0); self.write_type_section(); self.write_import_section_preamble(); @@ -108,19 +107,24 @@ impl WasmBuilder { self.output.push(op::SC_CODE); let idx_code_section_size = self.output.len(); // we will write to this location later - self.output.push(0); self.output.push(0); // write temp val for now using 4 bytes - self.output.push(0); self.output.push(0); + self.output.push(0); + self.output.push(0); // write temp val for now using 4 bytes + self.output.push(0); + self.output.push(0); self.output.push(1); // number of function bodies: just 1 // same as above but for body size of the function let idx_fn_body_size = self.output.len(); - self.output.push(0); self.output.push(0); - self.output.push(0); self.output.push(0); + self.output.push(0); + self.output.push(0); + self.output.push(0); + self.output.push(0); self.output.push(1); // count of local blocks dbg_assert!(no_of_locals_i32 < 128); - self.output.push(no_of_locals_i32); self.output.push(op::TYPE_I32); + self.output.push(no_of_locals_i32); + self.output.push(op::TYPE_I32); self.output.append(&mut self.code_section); @@ -206,7 +210,10 @@ impl WasmBuilder { offset += 1; // skip module name itself let len = self.output[offset] as usize; offset += 1; - let name = self.output.get(offset..(offset + len)).expect("get function name"); + let name = self + .output + .get(offset..(offset + len)) + .expect("get function name"); if name == fn_name.as_bytes() { return Some(i); } @@ -235,10 +242,12 @@ impl WasmBuilder { self.output.push(op::SC_IMPORT); self.idx_import_table_size = self.output.len(); - self.output.push(1 | 0b10000000); self.output.push(2); // 2 in 2 byte leb + self.output.push(1 | 0b10000000); + self.output.push(2); // 2 in 2 byte leb self.idx_import_count = self.output.len(); - self.output.push(1 | 0b10000000); self.output.push(0); // 0 in 2 byte leb + self.output.push(1 | 0b10000000); + self.output.push(0); // 0 in 2 byte leb // here after starts the actual list of imports self.idx_import_entries = self.output.len(); @@ -302,19 +311,18 @@ impl WasmBuilder { // 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 let next_op_idx = self.output.len(); - self.output.push(0); self.output.push(0); // add 2 bytes for writing 16 byte val + self.output.push(0); + self.output.push(0); // add 2 bytes for writing 16 byte val write_fixed_leb16_at_idx(&mut self.output, next_op_idx, self.import_count - 1); } pub fn get_fn_idx(&mut self, fn_name: PackedStr, type_index: u8) -> u16 { match self.get_import_index(fn_name) { - Some(idx) => { - idx - }, + Some(idx) => idx, None => { let idx = self.write_import_entry(fn_name, type_index); idx - }, + } } } @@ -329,13 +337,12 @@ impl WasmBuilder { pub fn commit_instruction_body_cs(&mut self) { self.code_section.append(&mut self.instruction_body); } - } #[cfg(test)] mod tests { - use wasmgen::module_init::*; use util::pack_str; + use wasmgen::module_init::*; #[test] fn import_table_management() { diff --git a/src/rust/wasmgen/wasm_opcodes.rs b/src/rust/wasmgen/wasm_opcodes.rs index c5348084..cd26f2b5 100644 --- a/src/rust/wasmgen/wasm_opcodes.rs +++ b/src/rust/wasmgen/wasm_opcodes.rs @@ -1,8 +1,8 @@ macro_rules! c { - ($x:ident, $y: expr) => { + ($x:ident, $y:expr) => { #[allow(dead_code)] pub const $x: u8 = $y; - } + }; } // https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md#high-level-structure diff --git a/src/rust/wasmgen/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs index 4cb84ab3..e465d329 100644 --- a/src/rust/wasmgen/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -1,5 +1,5 @@ +use util::{write_fixed_leb16_at_idx, write_leb_i32, write_leb_u32}; use wasmgen::wasm_opcodes as op; -use util::{ write_fixed_leb16_at_idx, write_leb_i32, write_leb_u32 }; #[no_mangle] pub fn wg_push_i32(buf: &mut Vec, v: i32) { @@ -72,7 +72,8 @@ pub fn wg_shl_i32(buf: &mut Vec) { pub fn wg_call_fn(buf: &mut Vec, fn_idx: u16) { buf.push(op::OP_CALL); let buf_len = buf.len(); - buf.push(0); buf.push(0); + buf.push(0); + buf.push(0); write_fixed_leb16_at_idx(buf, buf_len, fn_idx); } From 9bf49105ec91819dd5ec140c14b67e74dd9dd102 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 5 Jul 2018 12:52:56 -0600 Subject: [PATCH 1015/2137] Add rustfmt.toml --- .rustfmt.toml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .rustfmt.toml diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 00000000..cd4d0ef4 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,6 @@ +normalize_comments = true +use_field_init_shorthand = true +match_block_trailing_comma = true +fn_single_line = true +imports_indent = "Block" +control_brace_style = "ClosingNextLine" From 3af405aca1880be810f14eb44380b97286aa3b7b Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 5 Jul 2018 12:53:11 -0600 Subject: [PATCH 1016/2137] Rustfmt with config --- src/rust/util.rs | 3 +- src/rust/wasmgen/c_api.rs | 8 +--- src/rust/wasmgen/module_init.rs | 14 ++---- src/rust/wasmgen/wasm_util.rs | 80 +++++++++------------------------ 4 files changed, 28 insertions(+), 77 deletions(-) diff --git a/src/rust/util.rs b/src/rust/util.rs index 2c0f92ef..ba88bae5 100644 --- a/src/rust/util.rs +++ b/src/rust/util.rs @@ -88,7 +88,8 @@ pub fn write_leb_i32(buf: &mut Vec, mut v: i32) { let sign_bit = byte & (1 << 6); if (v == 0 && sign_bit == 0) || (v == -1 && sign_bit != 0) { more = false; - } else { + } + else { byte |= 0b10000000; // turn on MSB } buf.push(byte); diff --git a/src/rust/wasmgen/c_api.rs b/src/rust/wasmgen/c_api.rs index 6e88662c..1dbc36ab 100644 --- a/src/rust/wasmgen/c_api.rs +++ b/src/rust/wasmgen/c_api.rs @@ -4,14 +4,10 @@ use wasmgen::module_init::get_module; pub use wasmgen::module_init::wg_setup; #[no_mangle] -pub fn wg_get_code_section() -> *mut Vec { - &mut get_module().code_section -} +pub fn wg_get_code_section() -> *mut Vec { &mut get_module().code_section } #[no_mangle] -pub fn wg_get_instruction_body() -> *mut Vec { - &mut get_module().instruction_body -} +pub fn wg_get_instruction_body() -> *mut Vec { &mut get_module().instruction_body } #[no_mangle] pub fn wg_reset() { diff --git a/src/rust/wasmgen/module_init.rs b/src/rust/wasmgen/module_init.rs index e61a4ca4..c6fabb0d 100644 --- a/src/rust/wasmgen/module_init.rs +++ b/src/rust/wasmgen/module_init.rs @@ -37,9 +37,7 @@ pub fn wg_setup() { get_module().init(); } -pub fn get_module<'a>() -> &'a mut WasmBuilder { - unsafe { MODULE_PTR.as_mut() } -} +pub fn get_module<'a>() -> &'a mut WasmBuilder { unsafe { MODULE_PTR.as_mut() } } pub struct WasmBuilder { pub output: Vec, @@ -322,17 +320,13 @@ impl WasmBuilder { None => { let idx = self.write_import_entry(fn_name, type_index); idx - } + }, } } - pub fn get_op_ptr(&self) -> *const u8 { - self.output.as_ptr() - } + pub fn get_op_ptr(&self) -> *const u8 { self.output.as_ptr() } - pub fn get_op_len(&self) -> usize { - self.output.len() - } + pub fn get_op_len(&self) -> usize { self.output.len() } pub fn commit_instruction_body_cs(&mut self) { self.code_section.append(&mut self.instruction_body); diff --git a/src/rust/wasmgen/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs index e465d329..0c456a43 100644 --- a/src/rust/wasmgen/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -49,24 +49,16 @@ pub fn wg_store_aligned_i32(buf: &mut Vec) { } #[no_mangle] -pub fn wg_add_i32(buf: &mut Vec) { - buf.push(op::OP_I32ADD); -} +pub fn wg_add_i32(buf: &mut Vec) { buf.push(op::OP_I32ADD); } #[no_mangle] -pub fn wg_and_i32(buf: &mut Vec) { - buf.push(op::OP_I32AND); -} +pub fn wg_and_i32(buf: &mut Vec) { buf.push(op::OP_I32AND); } #[no_mangle] -pub fn wg_or_i32(buf: &mut Vec) { - buf.push(op::OP_I32OR); -} +pub fn wg_or_i32(buf: &mut Vec) { buf.push(op::OP_I32OR); } #[no_mangle] -pub fn wg_shl_i32(buf: &mut Vec) { - buf.push(op::OP_I32SHL); -} +pub fn wg_shl_i32(buf: &mut Vec) { buf.push(op::OP_I32SHL); } #[no_mangle] pub fn wg_call_fn(buf: &mut Vec, fn_idx: u16) { @@ -84,34 +76,22 @@ pub fn wg_call_fn_with_arg(buf: &mut Vec, fn_idx: u16, arg0: i32) { } #[no_mangle] -pub fn wg_eq_i32(buf: &mut Vec) { - buf.push(op::OP_I32EQ); -} +pub fn wg_eq_i32(buf: &mut Vec) { buf.push(op::OP_I32EQ); } #[no_mangle] -pub fn wg_ne_i32(buf: &mut Vec) { - buf.push(op::OP_I32NE); -} +pub fn wg_ne_i32(buf: &mut Vec) { buf.push(op::OP_I32NE); } #[no_mangle] -pub fn wg_le_i32(buf: &mut Vec) { - buf.push(op::OP_I32LES); -} +pub fn wg_le_i32(buf: &mut Vec) { buf.push(op::OP_I32LES); } #[no_mangle] -pub fn wg_lt_i32(buf: &mut Vec) { - buf.push(op::OP_I32LTS); -} +pub fn wg_lt_i32(buf: &mut Vec) { buf.push(op::OP_I32LTS); } #[no_mangle] -pub fn wg_ge_i32(buf: &mut Vec) { - buf.push(op::OP_I32GES); -} +pub fn wg_ge_i32(buf: &mut Vec) { buf.push(op::OP_I32GES); } #[no_mangle] -pub fn wg_gt_i32(buf: &mut Vec) { - buf.push(op::OP_I32GTS); -} +pub fn wg_gt_i32(buf: &mut Vec) { buf.push(op::OP_I32GTS); } #[no_mangle] pub fn wg_if_i32(buf: &mut Vec) { @@ -132,9 +112,7 @@ pub fn wg_tee_local(buf: &mut Vec, idx: i32) { } #[no_mangle] -pub fn wg_xor_i32(buf: &mut Vec) { - buf.push(op::OP_I32XOR); -} +pub fn wg_xor_i32(buf: &mut Vec) { buf.push(op::OP_I32XOR); } #[no_mangle] pub fn wg_load_unaligned_i32_from_stack(buf: &mut Vec, byte_offset: u32) { @@ -160,19 +138,13 @@ pub fn wg_store_unaligned_i32(buf: &mut Vec, byte_offset: u32) { } #[no_mangle] -pub fn wg_shr_u32(buf: &mut Vec) { - buf.push(op::OP_I32SHRU); -} +pub fn wg_shr_u32(buf: &mut Vec) { buf.push(op::OP_I32SHRU); } #[no_mangle] -pub fn wg_shr_i32(buf: &mut Vec) { - buf.push(op::OP_I32SHRS); -} +pub fn wg_shr_i32(buf: &mut Vec) { buf.push(op::OP_I32SHRS); } #[no_mangle] -pub fn wg_eqz_i32(buf: &mut Vec) { - buf.push(op::OP_I32EQZ); -} +pub fn wg_eqz_i32(buf: &mut Vec) { buf.push(op::OP_I32EQZ); } #[no_mangle] pub fn wg_if_void(buf: &mut Vec) { @@ -181,9 +153,7 @@ pub fn wg_if_void(buf: &mut Vec) { } #[no_mangle] -pub fn wg_else(buf: &mut Vec) { - buf.push(op::OP_ELSE); -} +pub fn wg_else(buf: &mut Vec) { buf.push(op::OP_ELSE); } #[no_mangle] pub fn wg_loop_void(buf: &mut Vec) { @@ -198,19 +168,13 @@ pub fn wg_block_void(buf: &mut Vec) { } #[no_mangle] -pub fn wg_block_end(buf: &mut Vec) { - buf.push(op::OP_END); -} +pub fn wg_block_end(buf: &mut Vec) { buf.push(op::OP_END); } #[no_mangle] -pub fn wg_return(buf: &mut Vec) { - buf.push(op::OP_RETURN); -} +pub fn wg_return(buf: &mut Vec) { buf.push(op::OP_RETURN); } #[no_mangle] -pub fn wg_drop(buf: &mut Vec) { - buf.push(op::OP_DROP); -} +pub fn wg_drop(buf: &mut Vec) { buf.push(op::OP_DROP); } // Generate a br_table where an input of [i] will branch [i]th outer block, // where [i] is passed on the wasm stack @@ -245,14 +209,10 @@ pub fn wg_set_local(buf: &mut Vec, idx: i32) { } #[no_mangle] -pub fn wg_unreachable(buf: &mut Vec) { - buf.push(op::OP_UNREACHABLE); -} +pub fn wg_unreachable(buf: &mut Vec) { buf.push(op::OP_UNREACHABLE); } #[no_mangle] -pub fn wg_increment_mem32(buf: &mut Vec, addr: i32) { - wg_increment_variable(buf, addr, 1) -} +pub fn wg_increment_mem32(buf: &mut Vec, addr: i32) { wg_increment_variable(buf, addr, 1) } #[no_mangle] pub fn wg_increment_variable(buf: &mut Vec, addr: i32, n: i32) { From 42d21bde56f428c15bf2d6f6998eea1268de6497 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 8 Jul 2018 21:30:03 +1200 Subject: [PATCH 1017/2137] Extend 9p tests to cover most file system calls --- tests/devices/testfs.json | 1 + tests/devices/testfs/foo | 1 + tests/devices/virtio_9p.js | 953 ++++++++++++++++++++++++++++++++++--- 3 files changed, 895 insertions(+), 60 deletions(-) create mode 100644 tests/devices/testfs.json create mode 100644 tests/devices/testfs/foo diff --git a/tests/devices/testfs.json b/tests/devices/testfs.json new file mode 100644 index 00000000..12e7ce94 --- /dev/null +++ b/tests/devices/testfs.json @@ -0,0 +1 @@ +{"fsroot":[["foo",4,1531028318,33188,1000,1000]],"version":2,"size":4} \ No newline at end of file diff --git a/tests/devices/testfs/foo b/tests/devices/testfs/foo new file mode 100644 index 00000000..5716ca59 --- /dev/null +++ b/tests/devices/testfs/foo @@ -0,0 +1 @@ +bar diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index fc67a649..91a48c41 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -5,12 +5,45 @@ process.on("unhandledRejection", exn => { throw exn; }); const V86 = require("../../build/libv86-debug.js").V86; const fs = require("fs"); -// Random printable characters +const testfsjson = require('./testfs.json'); + +function log_pass(msg, ...args) +{ + console.log(`\x1b[92m[+] ${msg}\x1b[0m`, ...args); +} + +function log_warn(msg, ...args) +{ + console.error(`\x1b[93m[!] ${msg}\x1b[0m`, ...args); +} + +function log_fail(msg, ...args) +{ + console.error(`\x1b[91m[-] ${msg}\x1b[0m`, ...args); +} + +function assert_equal(actual, expected) +{ + if(actual !== expected) + { + log_warn("Failed assert equal (Test: %s)", tests[test_num].name); + log_warn("Expected:\n", expected); + log_warn("Actual:\n", actual); + test_fail(); + } +} + +// Random printable characters. const test_file = (new Uint8Array(512)).map(v => 0x20 + Math.random() * 0x5e); +const test_file_string = Buffer.from(test_file).toString().replace(/\n/g, ''); +const test_file_small = (new Uint8Array(16)).map(v => 0x20 + Math.random() * 0x5e); +const test_file_small_string = Buffer.from(test_file_small).toString().replace(/\n/g, ''); + const tests = [ { name: "Read Existing", + timeout: 10, start: () => { emulator.serial0_send("cp /etc/profile /mnt/read-existing\n"); @@ -18,81 +51,730 @@ const tests = }, capture_trigger: "start-capture", end_trigger: "done-read-existing", - end: capture => + end: (capture, done) => { emulator.read_file("read-existing", function(err, data) { if(err) { - console.log("Reading read-existing failed: " + err); - process.exit(1); - } - const expected = capture; - const actual = Buffer.from(data).toString().replace(/\n/g, ''); - if(actual !== expected) - { - console.log("Fail: Incorrect data"); - console.log("Expected:\n", expected); - console.log("Actual:\n", actual); - process.exit(1); + log_warn("Reading read-existing failed: %s", err); + test_fail(); + done(); + return; } + assert_equal(capture, Buffer.from(data).toString().replace(/\n/g, "")); + done(); }); }, }, { name: "Read New", + timeout: 10, start: () => { emulator.serial0_send("dd if=/dev/zero of=/mnt/read-new bs=1k count=512\n"); emulator.serial0_send("echo done-read-new\n"); }, end_trigger: "done-read-new", - end: () => + end: (capture, done) => { emulator.read_file("read-new", function(err, data) { if(err) { - console.log("Reading read-new failed: " + err); - process.exit(1); - } - if(data.length !== 512 * 1024) - { - console.log("Fail: Incorrect size"); - process.exit(1); + log_warn("Reading read-new failed: %s", err); + test_fail(); + done(); + return; } + assert_equal(data.length, 512 * 1024); if(data.find(v => v !== 0)) { - console.log("Fail: Incorrect data. Expected all zeros."); - process.exit(1); + log_warn("Fail: Incorrect data. Expected all zeros."); + test_fail(); } + done(); + }); + }, + }, + { + name: "Read Async", + use_fsjson: true, + timeout: 10, + start: () => + { + emulator.serial0_send("echo start-capture;"); + + // "foo" is from ./testfs/foo + emulator.serial0_send("cat /mnt/foo;"); + + emulator.serial0_send("echo done-read-async\n"); + }, + capture_trigger: "start-capture", + end_trigger: "done-read-async", + end: (capture, done) => + { + assert_equal(capture, "bar"); + emulator.read_file("foo", function(err, data) + { + if(err) + { + log_warn("Reading foo failed: %s", err); + test_fail(); + done(); + return; + } + assert_equal(Buffer.from(data).toString(), "bar\n"); + done(); }); }, }, { name: "Write New", + timeout: 10, + files: + [ + { + file: "write-new", + data: test_file, + }, + ], start: () => { emulator.serial0_send("echo start-capture; cat /mnt/write-new; echo; echo done-write-new\n"); }, capture_trigger: "start-capture", end_trigger: "done-write-new", - end: capture => + end: (capture, done) => + { + assert_equal(capture, test_file_string); + done(); + }, + }, + { + name: "Move", + timeout: 10, + files: + [ + { + file: "test-file", + data: test_file, + }, + ], + start: () => + { + emulator.serial0_send("echo start-capture;"); + emulator.serial0_send("cat /mnt/test-file;"); + emulator.serial0_send("find /mnt;"); + + // Rename. Verify updated directory. + emulator.serial0_send("mv /mnt/test-file /mnt/renamed;"); + emulator.serial0_send("cat /mnt/renamed;"); + emulator.serial0_send("find /mnt;"); + + // Move between folders. Verify directories. + emulator.serial0_send("mkdir /mnt/somedir;"); + emulator.serial0_send("mv /mnt/renamed /mnt/somedir/file;"); + emulator.serial0_send("cat /mnt/somedir/file;"); + emulator.serial0_send("find /mnt;"); + + // Rename folder. + emulator.serial0_send("mv /mnt/somedir /mnt/otherdir;"); + emulator.serial0_send("cat /mnt/otherdir/file;"); + emulator.serial0_send("find /mnt;"); + + // Move folder. + emulator.serial0_send("mkdir /mnt/thirddir;"); + emulator.serial0_send("mv /mnt/otherdir /mnt/thirddir;"); + emulator.serial0_send("cat /mnt/thirddir/otherdir/file;"); + emulator.serial0_send("find /mnt;"); + + // Move folder outside /mnt. Should be removed from 9p filesystem. + emulator.serial0_send("mv /mnt/thirddir/otherdir /root/movedoutside;"); + emulator.serial0_send("cat /root/movedoutside/file;"); + emulator.serial0_send("find /mnt;"); + + // Cleanup. + emulator.serial0_send("rm -rf /root/movedoutside;"); + emulator.serial0_send("echo done-move\n"); + }, + capture_trigger: "start-capture", + end_trigger: "done-move", + end: (capture, done) => + { + assert_equal(capture, + test_file_string + + "/mnt" + "/mnt/test-file" + + test_file_string + + "/mnt" + "/mnt/renamed" + + test_file_string + + "/mnt" + "/mnt/somedir" + "/mnt/somedir/file" + + test_file_string + + "/mnt" + "/mnt/otherdir" + "/mnt/otherdir/file" + + test_file_string + + "/mnt" + "/mnt/thirddir" + "/mnt/thirddir/otherdir" + "/mnt/thirddir/otherdir/file" + + test_file_string + + "/mnt" + "/mnt/thirddir"); + done(); + }, + }, + { + name: "Unlink", + timeout: 10, + files: + [ + { + file: "existing-file", + data: test_file, + }, + ], + start: () => + { + emulator.serial0_send("touch /mnt/new-file\n"); + emulator.serial0_send("mkdir /mnt/new-dir\n"); + emulator.serial0_send("touch /mnt/new-dir/file\n"); + + emulator.serial0_send("echo start-capture;"); + + emulator.serial0_send("rm /mnt/new-file;"); + emulator.serial0_send("cat /mnt/new-file 2>/dev/null || echo read-failed;"); + + emulator.serial0_send("rm /mnt/existing-file;"); + emulator.serial0_send("cat /mnt/existing-file 2>/dev/null || echo read-failed;"); + + emulator.serial0_send("rmdir /mnt/new-dir 2>/dev/null || echo rmdir-failed;"); + + emulator.serial0_send("rm /mnt/new-dir/file;"); + emulator.serial0_send("rmdir /mnt/new-dir;"); + emulator.serial0_send("ls /mnt/new-dir 2>/dev/null || echo read-failed;"); + + emulator.serial0_send("echo done-unlink\n"); + }, + capture_trigger: "start-capture", + end_trigger: "done-unlink", + end: (capture, done) => + { + assert_equal(capture, + "read-failed" + + "read-failed" + + "rmdir-failed" + + "read-failed"); + done(); + }, + }, + { + name: "Hard Links", + timeout: 10, + allow_failure: true, + files: + [ + { + file: "target", + data: test_file_small, + }, + ], + start: () => + { + emulator.serial0_send("ln /mnt/target /mnt/link\n"); + emulator.serial0_send("echo foo >> /mnt/link\n"); + + emulator.serial0_send("echo start-capture;"); + + // "foo" should be added to the target. + emulator.serial0_send("cat /mnt/target;"); + + // File should still exist after one is renamed. + emulator.serial0_send("mv /mnt/target /mnt/renamed;"); + emulator.serial0_send("echo bar >> /mnt/renamed\n"); + emulator.serial0_send("cat /mnt/link;"); + + // File should still exist after one of the names are unlinked. + emulator.serial0_send("rm /mnt/renamed;"); + emulator.serial0_send("cat /mnt/link;"); + + emulator.serial0_send("echo done-hard-links\n"); + }, + capture_trigger: "start-capture", + end_trigger: "done-hard-links", + end: (capture, done) => + { + assert_equal(capture, + test_file_small_string + "foo" + + test_file_small_string + "foobar" + + test_file_small_string + "foobar"); + done(); + }, + }, + { + name: "Symlinks", + timeout: 10, + files: + [ + { + file: "target", + data: test_file_small, + }, + ], + start: () => + { + emulator.serial0_send("echo otherdata > /mnt/target2\n"); + emulator.serial0_send("ln -s /mnt/target /mnt/symlink\n"); + emulator.serial0_send("echo appended >> /mnt/symlink\n"); + + emulator.serial0_send("echo start-capture;"); + + // Should output same file data. + emulator.serial0_send("cat /mnt/target;"); + emulator.serial0_send("cat /mnt/symlink;"); + + // Swap target with the other file. + emulator.serial0_send("rm /mnt/target;"); + emulator.serial0_send("mv /mnt/target2 /mnt/target;"); + + // Symlink should now read from that file. + emulator.serial0_send("cat /mnt/symlink;"); + + emulator.serial0_send("rm /mnt/target;"); + emulator.serial0_send("rm /mnt/symlink;"); + emulator.serial0_send("echo done-symlinks\n"); + }, + capture_trigger: "start-capture", + end_trigger: "done-symlinks", + end: (capture, done) => + { + assert_equal(capture, test_file_small_string + "appended" + + test_file_small_string + "appended" + "otherdata"); + done(); + }, + }, + { + name: "Mknod - fifo", + timeout: 10, + start: () => + { + emulator.serial0_send("mkfifo /mnt/testfifo\n"); + emulator.serial0_send('(cat /mnt/testfifo > /mnt/testfifo-output;echo "\ndone-fifo") &\n'); + emulator.serial0_send("echo fifomessage > /mnt/testfifo\n"); + }, + end_trigger: "done-fifo", + end: (capture, done) => + { + emulator.read_file("testfifo-output", function(err, data) + { + if(err) + { + log_warn("Reading testfifo-output failed: %s", err); + test_fail(); + done(); + return; + } + assert_equal(Buffer.from(data).toString(), "fifomessage\n"); + done(); + }); + }, + }, + { + name: "Readlink", + timeout: 10, + start: () => + { + emulator.serial0_send("touch /mnt/target\n"); + emulator.serial0_send("ln -s /mnt/target /mnt/link\n"); + emulator.serial0_send("echo start-capture;"); + emulator.serial0_send("readlink /mnt/link;"); + emulator.serial0_send("echo done-readlink\n"); + }, + capture_trigger: "start-capture", + end_trigger: "done-readlink", + end: (capture, done) => + { + assert_equal(capture, "/mnt/target"); + done(); + }, + }, + { + name: "Mkdir", + timeout: 10, + start: () => + { + emulator.serial0_send("echo notfoobar > /mnt/e-file\n"); + emulator.serial0_send("mkdir /mnt/a-dir\n"); + emulator.serial0_send("mkdir /mnt/a-dir/b-dir\n"); + emulator.serial0_send("mkdir /mnt/a-dir/c-dir\n"); + emulator.serial0_send("touch /mnt/a-dir/d-file\n"); + emulator.serial0_send("echo mkdirfoobar > /mnt/a-dir/e-file\n"); + emulator.serial0_send("echo done-mkdir\n"); + }, + end_trigger: "done-mkdir", + end: (capture, done) => + { + emulator.read_file("a-dir/e-file", function(err, data) + { + if(err) + { + log_warn("Reading a-dir/e-file failed: %s", err); + test_fail(); + done(); + return; + } + assert_equal(Buffer.from(data).toString(), "mkdirfoobar\n"); + done(); + }); + }, + }, + { + name: "Walk", + timeout: 10, + start: () => + { + emulator.serial0_send("mkdir -p /mnt/walk/a/aa/aaa/aaaa\n"); + emulator.serial0_send("mkdir -p /mnt/walk/a/aa/aaa/aaaa\n"); + emulator.serial0_send("mkdir -p /mnt/walk/b/ba\n"); + emulator.serial0_send("mkdir -p /mnt/walk/a/aa/aab\n"); + emulator.serial0_send("mkdir -p /mnt/walk/a/aa/aac\n"); + emulator.serial0_send("touch /mnt/walk/a/aa/aab/aabfile\n"); + emulator.serial0_send("touch /mnt/walk/b/bfile\n"); + emulator.serial0_send("echo start-capture;"); + emulator.serial0_send("find /mnt/walk | sort;"); // order agnostic + emulator.serial0_send("echo done-walk\n"); + }, + capture_trigger: "start-capture", + end_trigger: "done-walk", + end: (capture, done) => { const actual = capture; - const expected = Buffer.from(test_file).toString().replace(/\n/g, ''); - if(actual !== expected) + const expected = + "/mnt/walk" + + "/mnt/walk/a" + + "/mnt/walk/a/aa" + + "/mnt/walk/a/aa/aaa" + + "/mnt/walk/a/aa/aaa/aaaa" + + "/mnt/walk/a/aa/aab" + + "/mnt/walk/a/aa/aab/aabfile" + + "/mnt/walk/a/aa/aac" + + "/mnt/walk/b" + + "/mnt/walk/b/ba" + + "/mnt/walk/b/bfile"; + assert_equal(actual, expected); + done(); + }, + }, + { + name: "Statfs", + timeout: 10, + allow_failure: true, + start: () => + { + emulator.serial0_send("echo start-capture;"); + emulator.serial0_send("touch /mnt/file;"); + emulator.serial0_send("df -PTk /mnt | tail -n 1;"); + + // Grow file and verify space usage. + emulator.serial0_send("dd if=/dev/zero of=/mnt/file bs=1k count=4 status=none;"); + emulator.serial0_send("echo next;"); + emulator.serial0_send("df -PTk /mnt | tail -n 1;"); + + // Shrink file and verify space usage. + emulator.serial0_send("truncate -s 0 /mnt/file;"); + emulator.serial0_send("echo next;"); + emulator.serial0_send("df -PTk /mnt | tail -n 1;"); + + emulator.serial0_send("echo done-statfs\n"); + }, + capture_trigger: "start-capture", + end_trigger: "done-statfs", + end: (capture, done) => + { + const outputs = capture.split("next").map(output => output.split(/\s+/)); + if(outputs.length !== 3) { - console.log("Fail: Incorrect data"); - console.log("Expected:\n", expected); - console.log("Actual:\n", actual); - process.exit(1); + log_warn("Wrong format: %s", capture); + test_fail(); + done(); + return; } + + const before = outputs[0]; + const after_add = outputs[1]; + const after_rm = outputs[2]; + + // mount tag + assert_equal(before[0], "host9p"); + + // fs type + assert_equal(before[1], "9p"); + + // total size in 1024 blocks + assert_equal(after_add[2], before[2]); + assert_equal(after_rm[2], before[2]); + + // used size in 1024 blocks + assert_equal(+after_add[3], (+before[3]) + 4); + assert_equal(after_rm[3], before[3]); + + // free size in 1024 blocks + assert_equal(+after_add[4], (+before[4]) - 4); + assert_equal(after_rm[4], before[4]); + + // Entry [5] is percentage used. + + // mount path + assert_equal(before[6], "/mnt"); + + done(); + }, + }, + { + name: "File Attributes", + timeout: 10, + allow_failure: true, + start: () => + { + emulator.serial0_send("echo start-capture;"); + + emulator.serial0_send("dd if=/dev/zero of=/mnt/file bs=1 count=137 status=none;"); + emulator.serial0_send("touch -t 200002022222 /mnt/file;"); + emulator.serial0_send("chmod =rw /mnt/file;"); + emulator.serial0_send("ls -l --full-time /mnt/file;"); + + emulator.serial0_send("echo next;"); + + emulator.serial0_send("chmod +x /mnt/file;"); + emulator.serial0_send("chmod -w /mnt/file;"); + emulator.serial0_send("ls -l --full-time /mnt/file;"); + + emulator.serial0_send("echo next;"); + + emulator.serial0_send("chmod -x /mnt/file;"); + emulator.serial0_send("truncate -s 100 /mnt/file;"); + emulator.serial0_send("touch -t 201011220344 /mnt/file;"); + emulator.serial0_send("ln /mnt/file /mnt/file-link;"); + emulator.serial0_send("ls -l --full-time /mnt/file;"); + + emulator.serial0_send("echo done-file-attr\n"); + }, + capture_trigger: "start-capture", + end_trigger: "done-file-attr", + end: (capture, done) => + { + const outputs = capture.split("next").map(output => output.split(/\s+/)); + + if(outputs.length !== 3) + { + log_warn("Wrong format (expected 3 rows): %s", capture); + test_fail(); + return; + } + + // mode + assert_equal(outputs[0][0], "-rw-r--r--"); + // nlinks + assert_equal(outputs[0][1], "1"); + // user + assert_equal(outputs[0][2], "root"); + // group + assert_equal(outputs[0][3], "root"); + // size + assert_equal(outputs[0][4], "137"); + // atime + assert_equal(outputs[0][5], "2000-02-02"); + assert_equal(outputs[0][6], "22:22:00"); + assert_equal(outputs[0][7], "+0000"); + + // mode + assert_equal(outputs[1][0], "-r-xr-xr-x"); + // nlinks + assert_equal(outputs[1][1], "1"); + // user + assert_equal(outputs[1][2], "root"); + // group + assert_equal(outputs[1][3], "root"); + // size + assert_equal(outputs[1][4], "137"); + // atime + assert_equal(outputs[1][5], "2000-02-02"); + assert_equal(outputs[1][6], "22:22:00"); + assert_equal(outputs[1][7], "+0000"); + + // mode + assert_equal(outputs[2][0], "-r--r--r--"); + // nlinks + assert_equal(outputs[2][1], "2"); + // user + assert_equal(outputs[2][2], "root"); + // group + assert_equal(outputs[2][3], "root"); + // size + assert_equal(outputs[2][4], "100"); + // atime + assert_equal(outputs[2][5], "2010-11-22"); + assert_equal(outputs[2][6], "03:44:00"); + assert_equal(outputs[2][7], "+0000"); + + done(); + }, + }, + { + name: "Support for Full Security Capabilities", + timeout: 10, + allow_failure: true, + start: () => + { + emulator.serial0_send("touch /mnt/file\n"); + emulator.serial0_send("echo start-capture\n"); + emulator.serial0_send("getfattr /mnt/file\n"); + emulator.serial0_send("echo done-xattr\n"); + }, + capture_trigger: "start-capture", + end_trigger: "done-xattr", + end: (capture, done) => + { + log_warn("Security Capability test unimplemented"); + test_fail(); + done(); + }, + }, + { + name: "Stress Files", + timeout: 120, + start: () => + { + emulator.serial0_send("mkdir /mnt/stress-files\n"); + + emulator.serial0_send('cat << "EOF" | sh\n'); + + // Create files. + // Ensure directory inode data exceeds maximum message size for 9p. + emulator.serial0_send("for f in $(seq 0 999)\n"); + emulator.serial0_send("do\n"); + emulator.serial0_send(' echo "$f" > "/mnt/stress-files/file-$f"\n'); + emulator.serial0_send("done\n"); + + emulator.serial0_send("echo start-capture\n"); + + // Read some of them. + emulator.serial0_send("for f in $(seq 0 31 999)\n"); + emulator.serial0_send("do\n"); + emulator.serial0_send(' cat "/mnt/stress-files/file-$f"\n'); + emulator.serial0_send("done\n"); + + // Delete and verify. + // Using glob checks readdir. + emulator.serial0_send('rm /mnt/stress-files/file-*\n'); + emulator.serial0_send('test -z "$(ls /mnt/stress-files)" && echo delete-success\n'); + + emulator.serial0_send("echo done-stress-files\n"); + emulator.serial0_send("EOF\n"); + }, + capture_trigger: "start-capture", + end_trigger: "done-stress-files", + end: (capture, done) => + { + let expected = ""; + for(let i = 0; i < 1000; i += 31) + { + expected += i; + } + expected += "delete-success"; + assert_equal(capture, expected); + done(); + }, + }, + { + name: "Stress Directories", + timeout: 120, + start: () => + { + emulator.serial0_send('cat << "EOF" | sh\n'); + + emulator.serial0_send("p=/mnt/stress-dirs\n"); + emulator.serial0_send('mkdir "$p"\n'); + + // Create deep folder structure + emulator.serial0_send("for i in $(seq 0 99)\n"); + emulator.serial0_send("do\n"); + emulator.serial0_send(' p="$p/$i"\n'); + emulator.serial0_send(' mkdir "$p"\n'); + emulator.serial0_send(' echo "$i" > "$p/file"\n'); + emulator.serial0_send("done\n"); + + // Try accessing deep files + emulator.serial0_send("p=/mnt/stress-dirs\n"); + emulator.serial0_send("echo start-capture\n"); + // Skip first 80 - otherwise too slow + emulator.serial0_send("for i in $(seq 0 79)\n"); + emulator.serial0_send("do\n"); + emulator.serial0_send(' p="$p/$i"\n'); + emulator.serial0_send("done\n"); + emulator.serial0_send("for i in $(seq 80 99)\n"); + emulator.serial0_send("do\n"); + emulator.serial0_send(' p="$p/$i"\n'); + emulator.serial0_send(' cat "$p/file"\n'); + emulator.serial0_send("done\n"); + + // Delete and verify + emulator.serial0_send("rm -rf /mnt/stress-dirs/0\n"); + emulator.serial0_send('test -z "$(ls /mnt/stress-dirs)" && echo delete-success\n'); + + emulator.serial0_send("echo done-stress-dirs\n"); + emulator.serial0_send("EOF\n"); + }, + capture_trigger: "start-capture", + end_trigger: "done-stress-dirs", + end: (capture, done) => + { + let pos = 0; + for(let i = 80; i < 100; i++) + { + const str = "" + i; + assert_equal(capture.substr(pos, str.length), str); + pos += str.length; + } + assert_equal(capture.slice(pos), "delete-success"); + done(); + }, + }, + { + name: "Read Past Available", + timeout: 10, + start: () => + { + emulator.serial0_send("echo a > /mnt/small-file\n"); + emulator.serial0_send("echo start-capture;"); + + // Reading from offsets > size of file should not read anything. + emulator.serial0_send("dd if=/mnt/small-file bs=1 count=1 skip=10;"); + emulator.serial0_send("dd if=/mnt/small-file bs=1 count=1 skip=100;"); + emulator.serial0_send("dd if=/mnt/small-file bs=1 count=1 skip=1000;"); + + emulator.serial0_send("echo done-read-exceed\n"); + }, + capture_trigger: "start-capture", + end_trigger: "done-read-exceed", + end: (capture, done) => + { + assert_equal(capture, + "0+0 records in" + "0+0 records out" + + "0+0 records in" + "0+0 records out" + + "0+0 records in" + "0+0 records out"); + done(); }, }, ]; let test_num = 0; +let test_timeout = 0; +let test_has_failed = false; +const failed_tests = []; + +function test_fail() +{ + if(!test_has_failed) + { + test_has_failed = true; + failed_tests.push(test_num); + } +} const emulator = new V86({ bios: { url: __dirname + "/../../bios/seabios.bin" }, @@ -100,7 +782,9 @@ const emulator = new V86({ cdrom: { url: __dirname + "/../../images/linux4.iso" }, autostart: true, memory_size: 32 * 1024 * 1024, - filesystem: {}, + filesystem: { + "baseurl": __dirname + "/testfs/", + }, log_level: 0, }); @@ -108,11 +792,178 @@ let ran_command = false; let line = ""; let capturing = false; let capture = ""; +let next_trigger; +let next_trigger_handler; + +function nuke_fs() +{ + console.log("\nPreparing test #%d: %s", test_num, tests[test_num].name); + console.log(" Nuking /mnt"); + emulator.serial0_send("rm -rf /mnt/*\n"); + emulator.serial0_send("echo prep-nuke-done\n"); + + next_trigger = "prep-nuke-done"; + next_trigger_handler = tests[test_num].use_fsjson ? reload_fsjson : load_files; +} + +function reload_fsjson() +{ + console.log(" Reloading files from json"); + emulator.fs9p.OnJSONLoaded(JSON.stringify(testfsjson)); + emulator.fs9p.OnLoaded = () => + { + emulator.serial0_send("echo prep-fs-loaded\n"); + }; + + next_trigger = "prep-fs-loaded"; + next_trigger_handler = load_files; +} + +function load_files() +{ + if(tests[test_num].files) + { + let remaining = tests[test_num].files.length; + for(const f of tests[test_num].files) + { + emulator.create_file(f.file, f.data, function(err) + { + if(err) + { + log_warn("Failed to add file required for test %s: %s", + tests[test_num].name, err); + process.exit(1); + } + remaining--; + if(!remaining) + { + start_test(); + } + }); + } + } + else + { + start_test(); + } +} + +function start_test() +{ + console.log("Starting test #%d: %s", test_num, tests[test_num].name); + + if(tests[test_num].timeout) + { + test_timeout = setTimeout(() => + { + log_fail("Test #%d (%s) took longer than %s sec. Timing out and terminating.", test_num, tests[test_num].name, tests[test_num].timeout); + process.exit(1); + }, tests[test_num].timeout * 1000); + } + + capture = ""; + + tests[test_num].start(); + + if(tests[test_num].capture_trigger) + { + next_trigger = tests[test_num].capture_trigger; + next_trigger_handler = start_capture; + } + else + { + next_trigger = tests[test_num].end_trigger; + next_trigger_handler = end_test; + } +} + +function start_capture() +{ + console.log("Capturing..."); + capture = ""; + capturing = true; + + next_trigger = tests[test_num].end_trigger; + next_trigger_handler = end_test; +} + +function end_test() +{ + capturing = false; + + if(tests[test_num].timeout) + { + clearTimeout(test_timeout); + } + + tests[test_num].end(capture, () => + { + if(!test_has_failed) + { + log_pass("Test #%d passed: %s", test_num, tests[test_num].name); + } + else + { + if(tests[test_num].allow_failure) + { + log_warn("Test #%d failed: %s (failure allowed)", test_num, tests[test_num].name); + } + else + { + log_fail("Test #%d failed: %s", test_num, tests[test_num].name); + } + test_has_failed = false; + } + + test_num++; + + if(test_num < tests.length) + { + nuke_fs(); + } + else + { + finish_tests(); + } + }); +} + +function finish_tests() +{ + emulator.stop(); + + console.log("\nTests finished."); + if(failed_tests.length == 0) + { + console.log("All tests passed"); + } + else + { + let unallowed_failure = false; + + console.error("Failed %d out of %d tests:", failed_tests.length, tests.length); + for(const num of failed_tests) + { + if(tests[num].allow_failure) + { + log_warn("#%d %s (failure allowed)", num, tests[num].name); + } + else + { + unallowed_failure = true; + log_fail("#%d %s", num, tests[num].name); + } + } + if(unallowed_failure) + { + process.exit(1); + } + } +} emulator.bus.register("emulator-started", function() { - console.log("Booting now, please stand by"); - emulator.create_file("write-new", test_file); + console.error("Booting now, please stand by"); }); emulator.add_listener("serial0-output-char", function(chr) @@ -126,7 +977,6 @@ emulator.add_listener("serial0-output-char", function(chr) if(chr === "\n") { new_line = line; - console.log("Serial: %s", line); line = ""; } else @@ -137,36 +987,19 @@ emulator.add_listener("serial0-output-char", function(chr) if(!ran_command && line.endsWith("~% ")) { ran_command = true; - console.log("Starting: " + tests[0].name); - tests[0].start(); + nuke_fs(); } - else if(new_line === tests[test_num].capture_trigger) + else if(new_line === next_trigger) { - capture = ""; - capturing = true; + next_trigger_handler(); } - else if(new_line === tests[test_num].end_trigger) - { - tests[test_num].end(capture); - console.log("Passed: " + tests[test_num].name); - - test_num++; - capture = ""; - capturing = false; - - if(test_num < tests.length) - { - console.log("Starting: " + tests[test_num].name); - tests[test_num].start(); - } - else - { - console.log("Tests finished"); - emulator.stop(); - } - } - else if(capturing) + else if(new_line && capturing) { capture += new_line; + console.log(" Captured: %s", new_line); + } + else if(new_line) + { + console.log(" Serial: %s", new_line); } }); From 8c6bfdb6da0718b783233a21add68ac3b299648b Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 11 Jul 2018 10:42:29 +1200 Subject: [PATCH 1018/2137] Minor improvements to filesystem tests --- tests/devices/virtio_9p.js | 51 +++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index 91a48c41..0ef52c37 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -237,15 +237,20 @@ const tests = emulator.serial0_send("echo start-capture;"); emulator.serial0_send("rm /mnt/new-file;"); + emulator.serial0_send("test ! -e /mnt/new-file && echo new-file-unlinked;"); emulator.serial0_send("cat /mnt/new-file 2>/dev/null || echo read-failed;"); emulator.serial0_send("rm /mnt/existing-file;"); + emulator.serial0_send("test ! -e /mnt/existing-file && echo existing-file-unlinked;"); emulator.serial0_send("cat /mnt/existing-file 2>/dev/null || echo read-failed;"); emulator.serial0_send("rmdir /mnt/new-dir 2>/dev/null || echo rmdir-failed;"); + emulator.serial0_send("test -e /mnt/new-dir && echo new-dir-exist;"); emulator.serial0_send("rm /mnt/new-dir/file;"); emulator.serial0_send("rmdir /mnt/new-dir;"); + emulator.serial0_send("test ! -e /mnt/new-dir/file && echo new-dir-file-unlinked;"); + emulator.serial0_send("test ! -e /mnt/new-dir && echo new-dir-unlinked;"); emulator.serial0_send("ls /mnt/new-dir 2>/dev/null || echo read-failed;"); emulator.serial0_send("echo done-unlink\n"); @@ -255,9 +260,14 @@ const tests = end: (capture, done) => { assert_equal(capture, + "new-file-unlinked" + "read-failed" + + "existing-file-unlinked" + "read-failed" + "rmdir-failed" + + "new-dir-exist" + + "new-dir-file-unlinked" + + "new-dir-unlinked" + "read-failed"); done(); }, @@ -283,9 +293,12 @@ const tests = // "foo" should be added to the target. emulator.serial0_send("cat /mnt/target;"); + // Both should have the same inode number + emulator.serial0_send("test -ef /mnt/target /mnt/link && echo same-inode;"); + // File should still exist after one is renamed. emulator.serial0_send("mv /mnt/target /mnt/renamed;"); - emulator.serial0_send("echo bar >> /mnt/renamed\n"); + emulator.serial0_send("echo bar >> /mnt/renamed;"); emulator.serial0_send("cat /mnt/link;"); // File should still exist after one of the names are unlinked. @@ -300,6 +313,7 @@ const tests = { assert_equal(capture, test_file_small_string + "foo" + + "same-inode" + test_file_small_string + "foobar" + test_file_small_string + "foobar"); done(); @@ -618,19 +632,48 @@ const tests = name: "Support for Full Security Capabilities", timeout: 10, allow_failure: true, + // The following doesn't work with linux4.img yet. + // Host machine also requires package libcap-dev:i386 to compile this. + //files: + //[ + // { + // file: "test", + // data: new Uint8Array(child_process.execSync("gcc -xc -m32 -o /dev/stdout -static - -lcap", + // { + // input: ` + // #include + // #include + // int main(int argc, char *argv[]) + // { + // cap_t cap = cap_get_file(argv[1]); + // if(cap == NULL) + // { + // perror("Error accessing capabilities"); + // return 1; + // } + // char *text = cap_to_text(cap, NULL); + // puts(text); + // cap_free(cap); + // cap_free(text); + // return 0; + // } + // `, + // }).buffer), + // }, + //], start: () => { emulator.serial0_send("touch /mnt/file\n"); + emulator.serial0_send("chmod +x /mnt/test\n"); emulator.serial0_send("echo start-capture\n"); - emulator.serial0_send("getfattr /mnt/file\n"); + emulator.serial0_send("/mnt/test /mnt/file\n"); emulator.serial0_send("echo done-xattr\n"); }, capture_trigger: "start-capture", end_trigger: "done-xattr", end: (capture, done) => { - log_warn("Security Capability test unimplemented"); - test_fail(); + assert_equal(capture, "= cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap+ip"); done(); }, }, From 496e63f76e5d5285843e827e790e399d8dd82f88 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Thu, 12 Jul 2018 12:51:39 +1200 Subject: [PATCH 1019/2137] Add walk to filesystem stress test --- tests/devices/virtio_9p.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index 0ef52c37..a4280920 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -688,7 +688,7 @@ const tests = // Create files. // Ensure directory inode data exceeds maximum message size for 9p. - emulator.serial0_send("for f in $(seq 0 999)\n"); + emulator.serial0_send("for f in $(seq -w 0 999)\n"); emulator.serial0_send("do\n"); emulator.serial0_send(' echo "$f" > "/mnt/stress-files/file-$f"\n'); emulator.serial0_send("done\n"); @@ -696,11 +696,14 @@ const tests = emulator.serial0_send("echo start-capture\n"); // Read some of them. - emulator.serial0_send("for f in $(seq 0 31 999)\n"); + emulator.serial0_send("for f in $(seq -w 0 31 999)\n"); emulator.serial0_send("do\n"); emulator.serial0_send(' cat "/mnt/stress-files/file-$f"\n'); emulator.serial0_send("done\n"); + // Walk. + emulator.serial0_send("find /mnt/stress-files | sort\n"); + // Delete and verify. // Using glob checks readdir. emulator.serial0_send('rm /mnt/stress-files/file-*\n'); @@ -716,7 +719,12 @@ const tests = let expected = ""; for(let i = 0; i < 1000; i += 31) { - expected += i; + expected += i.toString().padStart(3, "0"); + } + expected += "/mnt/stress-files"; + for(let i = 0; i < 1000; i ++) + { + expected += "/mnt/stress-files/file-" + i.toString().padStart(3, "0"); } expected += "delete-success"; assert_equal(capture, expected); From 72a4dc64487c33ad5f4e52def831491423cab700 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Thu, 12 Jul 2018 12:59:32 +1200 Subject: [PATCH 1020/2137] Filesystem tests tidyup and ls --color=never --- tests/devices/virtio_9p.js | 66 ++++++++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index a4280920..0cea2218 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -34,9 +34,9 @@ function assert_equal(actual, expected) } // Random printable characters. -const test_file = (new Uint8Array(512)).map(v => 0x20 + Math.random() * 0x5e); +const test_file = new Uint8Array(512).map(v => 0x20 + Math.random() * 0x5e); const test_file_string = Buffer.from(test_file).toString().replace(/\n/g, ''); -const test_file_small = (new Uint8Array(16)).map(v => 0x20 + Math.random() * 0x5e); +const test_file_small = new Uint8Array(16).map(v => 0x20 + Math.random() * 0x5e); const test_file_small_string = Buffer.from(test_file_small).toString().replace(/\n/g, ''); const tests = @@ -549,13 +549,13 @@ const tests = emulator.serial0_send("dd if=/dev/zero of=/mnt/file bs=1 count=137 status=none;"); emulator.serial0_send("touch -t 200002022222 /mnt/file;"); emulator.serial0_send("chmod =rw /mnt/file;"); - emulator.serial0_send("ls -l --full-time /mnt/file;"); + emulator.serial0_send("ls -l --full-time --color=never /mnt/file;"); emulator.serial0_send("echo next;"); emulator.serial0_send("chmod +x /mnt/file;"); emulator.serial0_send("chmod -w /mnt/file;"); - emulator.serial0_send("ls -l --full-time /mnt/file;"); + emulator.serial0_send("ls -l --full-time --color=never /mnt/file;"); emulator.serial0_send("echo next;"); @@ -563,7 +563,7 @@ const tests = emulator.serial0_send("truncate -s 100 /mnt/file;"); emulator.serial0_send("touch -t 201011220344 /mnt/file;"); emulator.serial0_send("ln /mnt/file /mnt/file-link;"); - emulator.serial0_send("ls -l --full-time /mnt/file;"); + emulator.serial0_send("ls -l --full-time --color=never /mnt/file;"); emulator.serial0_send("echo done-file-attr\n"); }, @@ -594,6 +594,8 @@ const tests = assert_equal(outputs[0][5], "2000-02-02"); assert_equal(outputs[0][6], "22:22:00"); assert_equal(outputs[0][7], "+0000"); + // pathname + assert_equal(outputs[0][8], "/mnt/file"); // mode assert_equal(outputs[1][0], "-r-xr-xr-x"); @@ -609,6 +611,8 @@ const tests = assert_equal(outputs[1][5], "2000-02-02"); assert_equal(outputs[1][6], "22:22:00"); assert_equal(outputs[1][7], "+0000"); + // pathname + assert_equal(outputs[1][8], "/mnt/file"); // mode assert_equal(outputs[2][0], "-r--r--r--"); @@ -624,6 +628,8 @@ const tests = assert_equal(outputs[2][5], "2010-11-22"); assert_equal(outputs[2][6], "03:44:00"); assert_equal(outputs[2][7], "+0000"); + // pathname + assert_equal(outputs[2][8], "/mnt/file"); done(); }, @@ -632,6 +638,7 @@ const tests = name: "Support for Full Security Capabilities", timeout: 10, allow_failure: true, + // TODO: Delete the following. Better to use getfattr or getcap commands if available. // The following doesn't work with linux4.img yet. // Host machine also requires package libcap-dev:i386 to compile this. //files: @@ -673,7 +680,54 @@ const tests = end_trigger: "done-xattr", end: (capture, done) => { - assert_equal(capture, "= cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap+ip"); + const EXPECTED_CAPABILITIES = + [ + // In order of their values defined in linux/capability.h + "cap_chown", + "cap_dac_override", + "cap_dac_read_search", + "cap_fowner", + "cap_fsetid", + "cap_kill", + "cap_setgid", + "cap_setuid", + "cap_setcap", + "cap_linux_immutable", + "cap_net_bind_service", + "cap_net_broadcast", + "cap_net_admin", + "cap_net_raw", + "cap_ipc_lock", + "cap_ipc_owner", + "cap_sys_module", + "cap_sys_rawio", + "cap_sys_chroot", + "cap_sys_ptrace", + "cap_sys_pacct", + "cap_sys_admin", + "cap_sys_boot", + "cap_sys_nice", + "cap_sys_resource", + "cap_sys_time", + "cap_sys_tty_config", + "cap_mknod", + "cap_lease", + "cap_audit_write", + "cap_audit_control", + "cap_setfcap", + + // VFS_CAP_REVISION_1 can only set the first 32 capabilities + // The rest is accessible via VFS_CAP_REVISION_2 or 3 + + //"cap_mac_override", + //"cap_mac_admin", + //"cap_syslog", + //"cap_wake_alarm", + //"cap_block_suspend", + //"cap_audit_read", + ]; + const expected = "= " + EXPECTED_CAPABILITIES.join(",") + "+ip"; + assert_equal(capture, expected); done(); }, }, From 30a72e587438b9af83b6d7e08c513e4fb1668b82 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Thu, 12 Jul 2018 16:20:49 +1200 Subject: [PATCH 1021/2137] Filesystem tests: include newlines in capture - keep empty lines - handle word wraps - remove extra space in assert failure logging --- tests/devices/virtio_9p.js | 157 ++++++++++++++++++++----------------- 1 file changed, 87 insertions(+), 70 deletions(-) diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index 0cea2218..d646b736 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -27,17 +27,17 @@ function assert_equal(actual, expected) if(actual !== expected) { log_warn("Failed assert equal (Test: %s)", tests[test_num].name); - log_warn("Expected:\n", expected); - log_warn("Actual:\n", actual); + log_warn("Expected:\n" + expected); + log_warn("Actual:\n" + actual); test_fail(); } } // Random printable characters. const test_file = new Uint8Array(512).map(v => 0x20 + Math.random() * 0x5e); -const test_file_string = Buffer.from(test_file).toString().replace(/\n/g, ''); +const test_file_string = Buffer.from(test_file).toString(); const test_file_small = new Uint8Array(16).map(v => 0x20 + Math.random() * 0x5e); -const test_file_small_string = Buffer.from(test_file_small).toString().replace(/\n/g, ''); +const test_file_small_string = Buffer.from(test_file_small).toString(); const tests = [ @@ -62,7 +62,7 @@ const tests = done(); return; } - assert_equal(capture, Buffer.from(data).toString().replace(/\n/g, "")); + assert_equal(capture, Buffer.from(data).toString()); done(); }); }, @@ -114,7 +114,7 @@ const tests = end_trigger: "done-read-async", end: (capture, done) => { - assert_equal(capture, "bar"); + assert_equal(capture, "bar\n"); emulator.read_file("foo", function(err, data) { if(err) @@ -147,7 +147,14 @@ const tests = end_trigger: "done-write-new", end: (capture, done) => { - assert_equal(capture, test_file_string); + // Handle word wrapping. + const lines = capture.split("\n"); + let pos = 0; + for(const line of lines) + { + assert_equal(line, test_file_string.slice(pos, line.length)); + pos += line.length; + } done(); }, }, @@ -204,17 +211,27 @@ const tests = { assert_equal(capture, test_file_string + - "/mnt" + "/mnt/test-file" + + "/mnt\n" + + "/mnt/test-file\n" + test_file_string + - "/mnt" + "/mnt/renamed" + + "/mnt\n" + + "/mnt/renamed\n" + test_file_string + - "/mnt" + "/mnt/somedir" + "/mnt/somedir/file" + + "/mnt\n" + + "/mnt/somedir\n" + + "/mnt/somedir/file\n" + test_file_string + - "/mnt" + "/mnt/otherdir" + "/mnt/otherdir/file" + + "/mnt\n" + + "/mnt/otherdir\n" + + "/mnt/otherdir/file\n" + test_file_string + - "/mnt" + "/mnt/thirddir" + "/mnt/thirddir/otherdir" + "/mnt/thirddir/otherdir/file" + + "/mnt\n" + + "/mnt/thirddir\n" + + "/mnt/thirddir/otherdir\n" + + "/mnt/thirddir/otherdir/file\n" + test_file_string + - "/mnt" + "/mnt/thirddir"); + "/mnt\n" + + "/mnt/thirddir\n"); done(); }, }, @@ -260,15 +277,15 @@ const tests = end: (capture, done) => { assert_equal(capture, - "new-file-unlinked" + - "read-failed" + - "existing-file-unlinked" + - "read-failed" + - "rmdir-failed" + - "new-dir-exist" + - "new-dir-file-unlinked" + - "new-dir-unlinked" + - "read-failed"); + "new-file-unlinked\n" + + "read-failed\n" + + "existing-file-unlinked\n" + + "read-failed\n" + + "rmdir-failed\n" + + "new-dir-exist\n" + + "new-dir-file-unlinked\n" + + "new-dir-unlinked\n" + + "read-failed\n"); done(); }, }, @@ -294,7 +311,7 @@ const tests = emulator.serial0_send("cat /mnt/target;"); // Both should have the same inode number - emulator.serial0_send("test -ef /mnt/target /mnt/link && echo same-inode;"); + emulator.serial0_send("test /mnt/target -ef /mnt/link && echo same-inode;"); // File should still exist after one is renamed. emulator.serial0_send("mv /mnt/target /mnt/renamed;"); @@ -312,10 +329,10 @@ const tests = end: (capture, done) => { assert_equal(capture, - test_file_small_string + "foo" + - "same-inode" + - test_file_small_string + "foobar" + - test_file_small_string + "foobar"); + test_file_small_string + "foo\n" + + "same-inode\n" + + test_file_small_string + "foo\nbar\n" + + test_file_small_string + "foo\nbar\n"); done(); }, }, @@ -356,8 +373,10 @@ const tests = end_trigger: "done-symlinks", end: (capture, done) => { - assert_equal(capture, test_file_small_string + "appended" + - test_file_small_string + "appended" + "otherdata"); + assert_equal(capture, + test_file_small_string + "appended\n" + + test_file_small_string + "appended\n" + + "otherdata\n"); done(); }, }, @@ -402,7 +421,7 @@ const tests = end_trigger: "done-readlink", end: (capture, done) => { - assert_equal(capture, "/mnt/target"); + assert_equal(capture, "/mnt/target\n"); done(); }, }, @@ -458,17 +477,17 @@ const tests = { const actual = capture; const expected = - "/mnt/walk" + - "/mnt/walk/a" + - "/mnt/walk/a/aa" + - "/mnt/walk/a/aa/aaa" + - "/mnt/walk/a/aa/aaa/aaaa" + - "/mnt/walk/a/aa/aab" + - "/mnt/walk/a/aa/aab/aabfile" + - "/mnt/walk/a/aa/aac" + - "/mnt/walk/b" + - "/mnt/walk/b/ba" + - "/mnt/walk/b/bfile"; + "/mnt/walk\n" + + "/mnt/walk/a\n" + + "/mnt/walk/a/aa\n" + + "/mnt/walk/a/aa/aaa\n" + + "/mnt/walk/a/aa/aaa/aaaa\n" + + "/mnt/walk/a/aa/aab\n" + + "/mnt/walk/a/aa/aab/aabfile\n" + + "/mnt/walk/a/aa/aac\n" + + "/mnt/walk/b\n" + + "/mnt/walk/b/ba\n" + + "/mnt/walk/b/bfile\n"; assert_equal(actual, expected); done(); }, @@ -485,12 +504,10 @@ const tests = // Grow file and verify space usage. emulator.serial0_send("dd if=/dev/zero of=/mnt/file bs=1k count=4 status=none;"); - emulator.serial0_send("echo next;"); emulator.serial0_send("df -PTk /mnt | tail -n 1;"); // Shrink file and verify space usage. emulator.serial0_send("truncate -s 0 /mnt/file;"); - emulator.serial0_send("echo next;"); emulator.serial0_send("df -PTk /mnt | tail -n 1;"); emulator.serial0_send("echo done-statfs\n"); @@ -499,8 +516,8 @@ const tests = end_trigger: "done-statfs", end: (capture, done) => { - const outputs = capture.split("next").map(output => output.split(/\s+/)); - if(outputs.length !== 3) + const outputs = capture.split("\n").map(output => output.split(/\s+/)); + if(outputs.length < 3) { log_warn("Wrong format: %s", capture); test_fail(); @@ -551,14 +568,10 @@ const tests = emulator.serial0_send("chmod =rw /mnt/file;"); emulator.serial0_send("ls -l --full-time --color=never /mnt/file;"); - emulator.serial0_send("echo next;"); - emulator.serial0_send("chmod +x /mnt/file;"); emulator.serial0_send("chmod -w /mnt/file;"); emulator.serial0_send("ls -l --full-time --color=never /mnt/file;"); - emulator.serial0_send("echo next;"); - emulator.serial0_send("chmod -x /mnt/file;"); emulator.serial0_send("truncate -s 100 /mnt/file;"); emulator.serial0_send("touch -t 201011220344 /mnt/file;"); @@ -571,12 +584,13 @@ const tests = end_trigger: "done-file-attr", end: (capture, done) => { - const outputs = capture.split("next").map(output => output.split(/\s+/)); + const outputs = capture.split("\n").map(output => output.split(/\s+/)); - if(outputs.length !== 3) + if(outputs.length < 3) { log_warn("Wrong format (expected 3 rows): %s", capture); test_fail(); + done(); return; } @@ -672,8 +686,8 @@ const tests = { emulator.serial0_send("touch /mnt/file\n"); emulator.serial0_send("chmod +x /mnt/test\n"); - emulator.serial0_send("echo start-capture\n"); - emulator.serial0_send("/mnt/test /mnt/file\n"); + emulator.serial0_send("echo start-capture;"); + emulator.serial0_send("/mnt/test /mnt/file;"); emulator.serial0_send("echo done-xattr\n"); }, capture_trigger: "start-capture", @@ -773,14 +787,14 @@ const tests = let expected = ""; for(let i = 0; i < 1000; i += 31) { - expected += i.toString().padStart(3, "0"); + expected += i.toString().padStart(3, "0") + "\n"; } - expected += "/mnt/stress-files"; + expected += "/mnt/stress-files\n"; for(let i = 0; i < 1000; i ++) { - expected += "/mnt/stress-files/file-" + i.toString().padStart(3, "0"); + expected += "/mnt/stress-files/file-" + i.toString().padStart(3, "0") + "\n"; } - expected += "delete-success"; + expected += "delete-success\n"; assert_equal(capture, expected); done(); }, @@ -828,14 +842,12 @@ const tests = end_trigger: "done-stress-dirs", end: (capture, done) => { - let pos = 0; - for(let i = 80; i < 100; i++) + const outputs = capture.split("\n"); + for(let i = 0; i < 20; i++) { - const str = "" + i; - assert_equal(capture.substr(pos, str.length), str); - pos += str.length; + assert_equal(outputs[i], `${i + 80}`); } - assert_equal(capture.slice(pos), "delete-success"); + assert_equal(outputs[20], "delete-success"); done(); }, }, @@ -858,10 +870,13 @@ const tests = end_trigger: "done-read-exceed", end: (capture, done) => { - assert_equal(capture, - "0+0 records in" + "0+0 records out" + - "0+0 records in" + "0+0 records out" + - "0+0 records in" + "0+0 records out"); + const outputs = capture.split("\n"); + assert_equal(outputs[0], "0+0 records in"); + assert_equal(outputs[1], "0+0 records out"); + assert_equal(outputs[2], "0+0 records in"); + assert_equal(outputs[3], "0+0 records out"); + assert_equal(outputs[4], "0+0 records in"); + assert_equal(outputs[5], "0+0 records out"); done(); }, }, @@ -1079,8 +1094,10 @@ emulator.add_listener("serial0-output-char", function(chr) } let new_line = ""; + let is_new_line = false; if(chr === "\n") { + is_new_line = true; new_line = line; line = ""; } @@ -1098,12 +1115,12 @@ emulator.add_listener("serial0-output-char", function(chr) { next_trigger_handler(); } - else if(new_line && capturing) + else if(is_new_line && capturing) { - capture += new_line; + capture += new_line + "\n"; console.log(" Captured: %s", new_line); } - else if(new_line) + else if(is_new_line) { console.log(" Serial: %s", new_line); } From 3a8d644d7554f452617371866be7a2e492a76d3e Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 3 Jul 2018 09:28:33 -0600 Subject: [PATCH 1022/2137] Port jit to Rust The following files and functions were ported: - jit.c - codegen.c - _jit functions in instructions*.c and misc_instr.c - generate_{analyzer,jit}.js (produces Rust code) - jit_* from cpu.c And the following data structures: - hot_code_addresses - wasm_table_index_free_list - entry_points - jit_cache_array - page_first_jit_cache_entry Other miscellaneous changes: - Page is an abstract type - Addresses, locals and bitflags are unsigned - Make the number of entry points a growable type - Avoid use of global state wherever possible - Delete string packing - Make CachedStateFlags abstract - Make AnalysisType product type - Make BasicBlockType product type - Restore opcode assertion - Set opt-level=2 in debug mode (for test performance) - Delete JIT_ALWAYS instrumentation (now possible via api) - Refactor generate_analyzer.js - Refactor generate_jit.js --- .rustfmt.toml | 1 - Cargo.toml | 1 + Makefile | 43 +- gen/generate_analyzer.js | 468 +++---- gen/generate_jit.js | 627 +++++----- gen/rust_ast.js | 88 ++ gen/util.js | 10 + gen/x86_table.js | 39 +- src/browser/lib.js | 5 +- src/browser/print_stats.js | 38 +- src/browser/starter.js | 84 +- src/config.js | 2 +- src/const.js | 2 +- src/cpu.js | 45 +- src/memory.js | 2 +- src/native/codegen/codegen.c | 678 ---------- src/native/codegen/codegen.h | 87 -- src/native/codegen/wasmgen.h | 74 -- src/native/config.h | 17 - src/native/const.h | 4 - src/native/cpu.c | 1358 +------------------- src/native/cpu.h | 108 +- src/native/global_pointers.h | 16 +- src/native/instructions.c | 274 ----- src/native/instructions.h | 17 +- src/native/instructions_0f.c | 54 +- src/native/instructions_0f.h | 2 - src/native/jit.c | 377 ------ src/native/jit.h | 12 - src/native/js_imports.h | 4 - src/native/memory.c | 2 +- src/native/misc_instr.c | 101 -- src/native/misc_instr.h | 12 +- src/native/profiler/opstats.c | 82 -- src/native/profiler/opstats.h | 5 - src/native/profiler/profiler.h | 2 +- src/native/rust_imports.h | 17 + src/native/shared.h | 9 - src/rust/analysis.rs | 96 ++ src/rust/c_api.rs | 132 ++ src/rust/codegen.rs | 382 ++++++ src/rust/cpu.rs | 50 + src/rust/cpu_context.rs | 74 ++ src/rust/dbg.rs | 20 +- src/rust/gen/mod.rs | 7 + src/rust/global_pointers.rs | 18 + src/rust/jit.rs | 1360 +++++++++++++++++++++ src/rust/jit_instructions.rs | 396 ++++++ src/rust/leb.rs | 52 + src/rust/lib.rs | 23 +- src/rust/modrm.rs | 345 ++++++ src/rust/opstats.rs | 49 + src/rust/page.rs | 8 + src/rust/prefix.rs | 14 + src/rust/profiler.rs | 63 + src/rust/regs.rs | 25 + src/rust/state_flags.rs | 19 + src/rust/tlb.rs | 6 + src/rust/util.rs | 105 -- src/rust/wasmgen/c_api.rs | 95 -- src/rust/wasmgen/mod.rs | 4 +- src/rust/wasmgen/module_init.rs | 79 +- src/rust/wasmgen/wasm_util.rs | 175 +-- tests/expect/run.js | 2 +- tests/expect/tests/mov32-mem.wast | 8 +- tests/nasm/run.js | 2 +- tests/rust/verify-wasmgen-dummy-output.js | 2 +- 67 files changed, 4034 insertions(+), 4344 deletions(-) create mode 100644 gen/rust_ast.js delete mode 100644 src/native/codegen/codegen.c delete mode 100644 src/native/codegen/codegen.h delete mode 100644 src/native/codegen/wasmgen.h delete mode 100644 src/native/jit.c delete mode 100644 src/native/jit.h delete mode 100644 src/native/profiler/opstats.c delete mode 100644 src/native/profiler/opstats.h create mode 100644 src/native/rust_imports.h create mode 100644 src/rust/analysis.rs create mode 100644 src/rust/c_api.rs create mode 100644 src/rust/codegen.rs create mode 100644 src/rust/cpu.rs create mode 100644 src/rust/cpu_context.rs create mode 100644 src/rust/gen/mod.rs create mode 100644 src/rust/global_pointers.rs create mode 100644 src/rust/jit.rs create mode 100644 src/rust/jit_instructions.rs create mode 100644 src/rust/leb.rs create mode 100644 src/rust/modrm.rs create mode 100644 src/rust/opstats.rs create mode 100644 src/rust/page.rs create mode 100644 src/rust/prefix.rs create mode 100644 src/rust/profiler.rs create mode 100644 src/rust/regs.rs create mode 100644 src/rust/state_flags.rs create mode 100644 src/rust/tlb.rs delete mode 100644 src/rust/wasmgen/c_api.rs diff --git a/.rustfmt.toml b/.rustfmt.toml index cd4d0ef4..626802c6 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1,4 +1,3 @@ -normalize_comments = true use_field_init_shorthand = true match_block_trailing_comma = true fn_single_line = true diff --git a/Cargo.toml b/Cargo.toml index c15c5d91..0b45eeac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ path = "src/rust/lib.rs" [profile.dev] lto = false +opt-level=2 panic = "abort" [profile.release] diff --git a/Makefile b/Makefile index b185dfda..39f47003 100644 --- a/Makefile +++ b/Makefile @@ -4,9 +4,9 @@ BROWSER=chromium NASM_TEST_DIR=./tests/nasm COVERAGE_DIR=./tests/coverage -INSTRUCTION_TABLES=build/jit.c build/jit0f_16.c build/jit0f_32.c \ +INSTRUCTION_TABLES=src/rust/gen/jit.rs src/rust/gen/jit0f_16.rs src/rust/gen/jit0f_32.rs \ build/interpreter.c build/interpreter0f_16.c build/interpreter0f_32.c \ - build/analyzer.c build/analyzer0f_16.c build/analyzer0f_32.c \ + src/rust/gen/analyzer.rs src/rust/gen/analyzer0f_16.rs src/rust/gen/analyzer0f_32.rs \ # Only the dependencies common to both generate_{jit,interpreter}.js GEN_DEPENDENCIES=$(filter-out gen/generate_interpreter.js gen/generate_jit.js gen/generate_analyzer.js, $(wildcard gen/*.js)) @@ -19,10 +19,6 @@ ifeq ($(ENABLE_COV), 1) CC_COVERAGE_FLAGS=--coverage -fprofile-instr-generate endif -ifeq ($(JIT_ALWAYS),) -JIT_ALWAYS=false -endif - all: build/v86_all.js build/libv86.js build/v86.wasm build/v86oxide.wasm all-debug: build/libv86-debug.js build/v86-debug.wasm build/v86oxide-debug.wasm browser: build/v86_all.js @@ -118,7 +114,9 @@ BROWSER_FILES=screen.js \ keyboard.js mouse.js serial.js \ network.js lib.js starter.js worker_bus.js dummy_screen.js print_stats.js -RUST_FILES=$(shell find src/rust/ -name '*.rs') +RUST_FILES=$(shell find src/rust/ -name '*.rs') \ + src/rust/gen/jit.rs src/rust/gen/jit0f_16.rs src/rust/gen/jit0f_32.rs \ + src/rust/gen/analyzer.rs src/rust/gen/analyzer0f_16.rs src/rust/gen/analyzer0f_32.rs CORE_FILES:=$(addprefix src/,$(CORE_FILES)) LIB_FILES:=$(addprefix lib/,$(LIB_FILES)) @@ -177,11 +175,11 @@ build/libv86-debug.js: $(CLOSURE) src/*.js lib/*.js src/browser/*.js .PHONY: instruction_tables instruction_tables: $(INSTRUCTION_TABLES) -build/jit.c: $(JIT_DEPENDENCIES) +src/rust/gen/jit.rs: $(JIT_DEPENDENCIES) ./gen/generate_jit.js --output-dir build/ --table jit -build/jit0f_16.c: $(JIT_DEPENDENCIES) +src/rust/gen/jit0f_16.rs: $(JIT_DEPENDENCIES) ./gen/generate_jit.js --output-dir build/ --table jit0f_16 -build/jit0f_32.c: $(JIT_DEPENDENCIES) +src/rust/gen/jit0f_32.rs: $(JIT_DEPENDENCIES) ./gen/generate_jit.js --output-dir build/ --table jit0f_32 build/interpreter.c: $(INTERPRETER_DEPENDENCIES) @@ -191,40 +189,32 @@ build/interpreter0f_16.c: $(INTERPRETER_DEPENDENCIES) build/interpreter0f_32.c: $(INTERPRETER_DEPENDENCIES) ./gen/generate_interpreter.js --output-dir build/ --table interpreter0f_32 -build/analyzer.c: $(ANALYZER_DEPENDENCIES) +src/rust/gen/analyzer.rs: $(ANALYZER_DEPENDENCIES) ./gen/generate_analyzer.js --output-dir build/ --table analyzer -build/analyzer0f_16.c: $(ANALYZER_DEPENDENCIES) +src/rust/gen/analyzer0f_16.rs: $(ANALYZER_DEPENDENCIES) ./gen/generate_analyzer.js --output-dir build/ --table analyzer0f_16 -build/analyzer0f_32.c: $(ANALYZER_DEPENDENCIES) +src/rust/gen/analyzer0f_32.rs: $(ANALYZER_DEPENDENCIES) ./gen/generate_analyzer.js --output-dir build/ --table analyzer0f_32 -.PHONY: phony -build/JIT_ALWAYS: phony - @if [[ `cat build/JIT_ALWAYS 2>&1` != '$(JIT_ALWAYS)' ]]; then \ - echo -n $(JIT_ALWAYS) > build/JIT_ALWAYS ; \ - fi - -build/v86.wasm: src/native/*.c src/native/*.h src/native/codegen/*.c src/native/codegen/*.h src/native/profiler/* src/native/*.ll $(INSTRUCTION_TABLES) build/JIT_ALWAYS +build/v86.wasm: src/native/*.c src/native/*.h src/native/profiler/* src/native/*.ll $(INSTRUCTION_TABLES) mkdir -p build -ls -lh build/v86.wasm - emcc src/native/*.c src/native/profiler/*.c src/native/codegen/codegen.c src/native/*.ll \ + emcc src/native/*.c src/native/profiler/*.c src/native/*.ll \ $(CC_FLAGS) \ -DDEBUG=false \ -DNDEBUG \ - -D"ENABLE_JIT_ALWAYS=$(JIT_ALWAYS)" \ -O3 \ --llvm-opts 3 \ --llvm-lto 3 \ -o build/v86.wasm ls -lh build/v86.wasm -build/v86-debug.wasm: src/native/*.c src/native/*.h src/native/codegen/*.c src/native/codegen/*.h src/native/profiler/* src/native/*.ll $(INSTRUCTION_TABLES) build/JIT_ALWAYS +build/v86-debug.wasm: src/native/*.c src/native/*.h src/native/profiler/* src/native/*.ll $(INSTRUCTION_TABLES) mkdir -p build/coverage -ls -lh build/v86-debug.wasm - emcc src/native/*.c src/native/profiler/*.c src/native/codegen/codegen.c src/native/*.ll \ + emcc src/native/*.c src/native/profiler/*.c src/native/*.ll \ $(CC_FLAGS) \ $(CC_COVERAGE_FLAGS) \ - -D"ENABLE_JIT_ALWAYS=$(JIT_ALWAYS)" \ -Os \ -o build/v86-debug.wasm ls -lh build/v86-debug.wasm @@ -317,7 +307,7 @@ expect-tests: all-debug build/libwabt.js devices-test: all-debug ./tests/devices/virtio_9p.js -rust-test: +rust-test: $(RUST_FILES) env RUST_BACKTRACE=full RUST_TEST_THREADS=1 cargo test -- --nocapture ./tests/rust/verify-wasmgen-dummy-output.js @@ -348,5 +338,4 @@ clang-tidy: clang-tidy \ src/native/*.c src/native/*.h \ src/native/profiler/*.c src/native/profiler/*.h \ - src/native/codegen/*.c src/native/codegen/*.h \ -- -I src/native/ -Wall -Wno-bitwise-op-parentheses -Wno-gnu-binary-literal diff --git a/gen/generate_analyzer.js b/gen/generate_analyzer.js index f4801184..a8a7961b 100755 --- a/gen/generate_analyzer.js +++ b/gen/generate_analyzer.js @@ -3,13 +3,11 @@ const fs = require("fs"); const path = require("path"); -const encodings = require("./x86_table"); -const c_ast = require("./c_ast"); -const { hex, mkdirpSync, get_switch_value, get_switch_exist, finalize_table } = require("./util"); +const x86_table = require("./x86_table"); +const rust_ast = require("./rust_ast"); +const { hex, mkdirpSync, get_switch_value, get_switch_exist, finalize_table_rust } = require("./util"); -const APPEND_NONFAULTING_FLAG = "analysis.flags |= JIT_INSTR_NONFAULTING_FLAG;"; - -const OUT_DIR = get_switch_value("--output-dir") || path.join(__dirname, "..", "build"); +const OUT_DIR = path.join(__dirname, "..", "src/rust/gen/"); mkdirpSync(OUT_DIR); @@ -36,18 +34,18 @@ function gen_read_imm_call(op, size_variant) { if(op.imm8) { - return "read_imm8()"; + return "cpu.read_imm8()"; } else if(op.imm8s) { - return "read_imm8s()"; + return "cpu.read_imm8s()"; } else { if(op.immaddr) { // immaddr: depends on address size - return "read_moffs()"; + return "cpu.read_moffs()"; } else { @@ -55,12 +53,12 @@ function gen_read_imm_call(op, size_variant) if(op.imm1632 && size === 16 || op.imm16) { - return "read_imm16()"; + return "cpu.read_imm16()"; } else { console.assert(op.imm1632 && size === 32 || op.imm32); - return "read_imm32s()"; + return "cpu.read_imm32()"; } } } @@ -77,93 +75,97 @@ function gen_call(name, args) return `${name}(${args.join(", ")});`; } -function gen_codegen_call(args) -{ - return args.map(arg => arg + ";"); -} - -function gen_codegen_call_modrm(args) -{ - args = args.map(arg => arg + ";"); - return [].concat(gen_call("modrm_skip", ["modrm_byte"]), args); -} - -function gen_modrm_mem_reg_split(mem_args, reg_args, postfixes={}) -{ - const { mem_postfix=[], reg_postfix=[] } = postfixes; - - return { - type: "if-else", - if_blocks: [{ - condition: "modrm_byte < 0xC0", - body: [] - .concat(gen_codegen_call_modrm(mem_args)) - .concat(mem_postfix), - }], - else_block: { - body: gen_codegen_call(reg_args).concat(reg_postfix), - }, - }; -} - /* * 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) +function make_instruction_name(encoding, size) { 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 prefix = (encoding.opcode & 0xFF0000) === 0 ? "" : hex(encoding.opcode >> 16 & 0xFF, 2); const fixed_g_suffix = encoding.fixed_g === undefined ? "" : `_${encoding.fixed_g}`; return `instr${suffix}_${prefix}${prefix_0f}${opcode_hex}${fixed_g_suffix}`; } -function get_nonfaulting_mem_reg_postfix(encoding) -{ - const lea_special_case = encoding.opcode === 0x8D; - const mem_postfix = (encoding.nonfaulting && lea_special_case) ? [APPEND_NONFAULTING_FLAG] : []; - const reg_postfix = (encoding.nonfaulting && !lea_special_case) ? [APPEND_NONFAULTING_FLAG] : []; - - return { - mem_postfix, - reg_postfix, - }; -} - -function create_instruction_postfix(encoding) -{ - return [].concat( - encoding.block_boundary ? ["analysis.flags |= JIT_INSTR_BLOCK_BOUNDARY_FLAG;"] : [], - encoding.no_next_instruction ? ["analysis.flags |= JIT_INSTR_NO_NEXT_INSTRUCTION_FLAG;"] : [] - ); -} - function gen_instruction_body(encodings, size) { const encoding = encodings[0]; - let has_66 = false; - let has_F2 = false; - let has_F3 = false; + let has_66 = []; + let has_F2 = []; + let has_F3 = []; + let no_prefix = []; 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((e.opcode >>> 16) === 0x66) has_66.push(e); + else if((e.opcode >>> 16) === 0xF2) has_F2.push(e); + else if((e.opcode >>> 16) === 0xF3) has_F3.push(e); + else no_prefix.push(e); } - if(has_66 || has_F2 || has_F3) + if(has_66.length || has_F2.length || has_F3.length) { console.assert((encoding.opcode & 0xFF00) === 0x0F00); } + const code = []; + + if(encoding.e) + { + code.push("let modrm_byte = cpu.read_imm8();"); + } + + if(has_66.length || has_F2.length || has_F3.length) + { + const if_blocks = []; + + if(has_66.length) { + const body = gen_instruction_body_after_prefix(has_66, size); + if_blocks.push({ condition: "cpu.prefixes & ::prefix::PREFIX_66 != 0", body, }); + } + if(has_F2.length) { + const body = gen_instruction_body_after_prefix(has_F2, size); + if_blocks.push({ condition: "cpu.prefixes & ::prefix::PREFIX_F2 != 0", body, }); + } + if(has_F3.length) { + const body = gen_instruction_body_after_prefix(has_F3, size); + if_blocks.push({ condition: "cpu.prefixes & ::prefix::PREFIX_F3 != 0", body, }); + } + + const else_block = { + body: gen_instruction_body_after_prefix(no_prefix, size), + }; + + return [].concat( + code, + { + type: "if-else", + if_blocks, + else_block, + } + ); + } + else { + return [].concat( + code, + gen_instruction_body_after_prefix(encodings, size) + ); + } +} + +function gen_instruction_body_after_prefix(encodings, size) +{ + const encoding = encodings[0]; + if(encoding.fixed_g !== undefined) { + console.assert(encoding.e); + // instruction with modrm byte where the middle 3 bits encode the instruction // group by opcode without prefix plus middle bits of modrm byte @@ -175,158 +177,65 @@ function gen_instruction_body(encodings, size) 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_postfix = create_instruction_postfix(case_); + const body = gen_instruction_body_after_fixed_g(case_, size); - const mem_args = []; - const reg_args = []; - - 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(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(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(mem_args, reg_args, {})]; - if_blocks.push({ condition: "prefixes_ & PREFIX_F3", body, }); - } - - const else_block = { - body: [ - gen_modrm_mem_reg_split( - mem_args, - reg_args, - {} - ) - ], - }; - - return { - conditions: [fixed_g], - body: [ - "int32_t prefixes_ = *prefixes;", - { - type: "if-else", - if_blocks, - else_block, - }, - ].concat(instruction_postfix), - }; - } - else - { - const body = [ - gen_modrm_mem_reg_split( - mem_args, - reg_args, - get_nonfaulting_mem_reg_postfix(case_) - ) - ].concat(instruction_postfix); - - return { - conditions: [fixed_g], - body, - }; - } + return { + conditions: [fixed_g], + body, + }; }), default_case: { body: [ - "analysis.flags |= JIT_INSTR_BLOCK_BOUNDARY_FLAG;", - "analysis.flags |= JIT_INSTR_NO_NEXT_INSTRUCTION_FLAG;", + "analysis.ty = ::analysis::AnalysisType::BlockBoundary;", + "analysis.no_next_instruction = true;", ], } }, ]; } - else if(has_66 || has_F2 || has_F3) - { - // instruction without modrm byte but with prefix - - console.assert(encoding.e); - console.assert(!encoding.ignore_mod); - - const instruction_postfix = create_instruction_postfix(encoding); - - const imm_read = gen_read_imm_call(encoding, size); - - const mem_args = []; - const reg_args = []; - - if(imm_read) - { - mem_args.push(imm_read); - reg_args.push(imm_read); - } - - const if_blocks = []; - - if(has_66) { - const body = [gen_modrm_mem_reg_split(mem_args, reg_args, {})]; - if_blocks.push({ condition: "prefixes_ & PREFIX_66", body, }); - } - if(has_F2) { - const body = [gen_modrm_mem_reg_split(mem_args, reg_args, {})]; - if_blocks.push({ condition: "prefixes_ & PREFIX_F2", body, }); - } - if(has_F3) { - const body = [gen_modrm_mem_reg_split(mem_args, reg_args, {})]; - if_blocks.push({ condition: "prefixes_ & PREFIX_F3", body, }); - } - - const else_block = { - body: [ - gen_modrm_mem_reg_split( - mem_args, - reg_args, - {} - ) - ], - }; - - return [ - "int32_t modrm_byte = read_imm8();", - "int32_t prefixes_ = *prefixes;", - { - type: "if-else", - if_blocks, - else_block, - } - ].concat(instruction_postfix); + else { + console.assert(encodings.length === 1); + return gen_instruction_body_after_fixed_g(encodings[0], size); } - else if(encoding.fixed_g === undefined && encoding.e) +} + +function gen_instruction_body_after_fixed_g(encoding, size) +{ + const imm_read = gen_read_imm_call(encoding, size); + const instruction_postfix = []; + + if(encoding.block_boundary && !encoding.jump_offset_imm) + { + instruction_postfix.push("analysis.ty = ::analysis::AnalysisType::BlockBoundary;"); + } + + if(encoding.no_next_instruction) + { + instruction_postfix.push("analysis.no_next_instruction = true;"); + } + + if(encoding.prefix) + { + const instruction_name = "::analysis::" + make_instruction_name(encoding, size) + "_analyze"; + const args = ["cpu", "analysis"]; + + console.assert(!imm_read); + + return [].concat( + gen_call(instruction_name, args), + instruction_postfix + ); + } + else if(encoding.e) { // instruction with modrm byte where the middle 3 bits encode a register - console.assert(encodings.length === 1); - - const instruction_postfix = create_instruction_postfix(encoding); - - const imm_read = gen_read_imm_call(encoding, size); - if(encoding.ignore_mod) { console.assert(!imm_read, "Unexpected instruction (ignore mod with immediate value)"); @@ -334,102 +243,69 @@ function gen_instruction_body(encodings, size) // Has modrm byte, but the 2 mod bits are ignored and both // operands are always registers (0f20-0f24) - if(encoding.nonfaulting) - { - instruction_postfix.push(APPEND_NONFAULTING_FLAG); - } - - return ["int32_t modrm_byte = read_imm8();"] - .concat(gen_codegen_call([])) - .concat(instruction_postfix); + return instruction_postfix; } else { - const mem_args = []; - const reg_args = []; - - 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( - mem_args, - reg_args, - get_nonfaulting_mem_reg_postfix(encoding) - ), - ].concat(instruction_postfix); + return [].concat( + { + type: "if-else", + if_blocks: [{ + condition: "modrm_byte < 0xC0", + body: [ + gen_call("::analysis::modrm_analyze", ["cpu", "modrm_byte"]) + ], + }], + }, + imm_read ? [imm_read + ";"] : [], + instruction_postfix + ); } } - else if(encoding.prefix) - { - console.assert(!encoding.nonfaulting, "Prefix/custom instructions cannot be marked as nonfaulting."); - - const instruction_postfix = create_instruction_postfix(encoding); - - const instruction_name = make_instruction_name(encoding, size) + "_analyze"; - const imm_read = gen_read_imm_call(encoding, size); - const args = []; - - if(imm_read) - { - args.push(imm_read); - } - - const call_prefix = encoding.prefix ? "return " : ""; - // Prefix calls can add to the return flags - return [call_prefix + gen_call(instruction_name, args)].concat(instruction_postfix); - } else { // instruction without modrm byte or prefix - const instruction_postfix = create_instruction_postfix(encoding); - - const imm_read = gen_read_imm_call(encoding, size); - - const args = []; + const body = []; if(imm_read) { if(encoding.jump_offset_imm) { - args.push("int32_t jump_offset = " + imm_read + ";"); - args.push("analysis.jump_offset = jump_offset;"); - args.push("analysis.flags |= is_osize_32() ? JIT_INSTR_IMM_JUMP32_FLAG : JIT_INSTR_IMM_JUMP16_FLAG;"); + body.push("let jump_offset = " + imm_read + ";"); + + if(encoding.conditional_jump) + { + console.assert((encoding.opcode & ~0xF) === 0x70 || (encoding.opcode & ~0xF) === 0x0F80); + const condition_index = encoding.opcode & 0xF; + body.push(`analysis.ty = ::analysis::AnalysisType::Jump { offset: jump_offset as i32, condition: Some(${condition_index}), is_32: cpu.osize_32() };`); + } + else + { + body.push(`analysis.ty = ::analysis::AnalysisType::Jump { offset: jump_offset as i32, condition: None, is_32: cpu.osize_32() };`); + } } else { - args.push(imm_read + ";"); + body.push(imm_read + ";"); } } if(encoding.extra_imm16) { console.assert(imm_read); - args.push(gen_call("read_imm16")); + body.push(gen_call("cpu.read_imm16")); } else if(encoding.extra_imm8) { console.assert(imm_read); - args.push(gen_call("read_imm8")); + body.push(gen_call("cpu.read_imm8")); } - if(encoding.nonfaulting) - { - instruction_postfix.push(APPEND_NONFAULTING_FLAG); - } - - if(encoding.conditional_jump) - { - console.assert((encoding.opcode & ~0xF) === 0x70 || (encoding.opcode & ~0xF) === 0x0F80); - instruction_postfix.push("analysis.condition_index = " + (encoding.opcode & 0xF) + ";"); - } - - return args.concat(instruction_postfix); + return [].concat( + body, + instruction_postfix + ); } } @@ -438,7 +314,7 @@ function gen_table() let by_opcode = Object.create(null); let by_opcode0f = Object.create(null); - for(let o of encodings) + for(let o of x86_table) { let opcode = o.opcode; @@ -465,6 +341,7 @@ function gen_table() console.assert(encoding && encoding.length); let opcode_hex = hex(opcode, 2); + let opcode_high_hex = hex(opcode | 0x100, 2); if(encoding[0].os) { @@ -473,14 +350,14 @@ function gen_table() body: gen_instruction_body(encoding, 16), }); cases.push({ - conditions: [`0x${opcode_hex}|0x100`], + conditions: [`0x${opcode_high_hex}`], body: gen_instruction_body(encoding, 32), }); } else { cases.push({ - conditions: [`0x${opcode_hex}`, `0x${opcode_hex}|0x100`], + conditions: [`0x${opcode_hex}`, `0x${opcode_high_hex}`], body: gen_instruction_body(encoding, undefined), }); } @@ -490,16 +367,23 @@ function gen_table() condition: "opcode", cases, default_case: { - body: ["assert(false);"] + body: ["dbg_assert!(false);"] }, }; if(to_generate.analyzer) { - finalize_table( + const code = [ + "#[cfg_attr(rustfmt, rustfmt_skip)]", + "pub fn analyzer(opcode: u32, cpu: &mut ::cpu_context::CpuContext, analysis: &mut ::analysis::Analysis) {", + table, + "}", + ]; + + finalize_table_rust( OUT_DIR, - "analyzer", - c_ast.print_syntax_tree([table]).join("\n") + "\n" + "analyzer.rs", + rust_ast.print_syntax_tree([].concat(code)).join("\n") + "\n" ); } @@ -540,7 +424,7 @@ function gen_table() condition: "opcode", cases: cases0f_16, default_case: { - body: ["assert(false);"] + body: ["dbg_assert!(false);"] }, }; const table0f_32 = { @@ -548,25 +432,41 @@ function gen_table() condition: "opcode", cases: cases0f_32, default_case: { - body: ["assert(false);"] + body: ["dbg_assert!(false);"] }, }; if(to_generate.analyzer0f_16) { - finalize_table( + const code = [ + "#![allow(unused)]", + "#[cfg_attr(rustfmt, rustfmt_skip)]", + "pub fn analyzer(opcode: u8, cpu: &mut ::cpu_context::CpuContext, analysis: &mut ::analysis::Analysis) {", + table0f_16, + "}" + ]; + + finalize_table_rust( OUT_DIR, - "analyzer0f_16", - c_ast.print_syntax_tree([table0f_16]).join("\n") + "\n" + "analyzer0f_16.rs", + rust_ast.print_syntax_tree([].concat(code)).join("\n") + "\n" ); } if(to_generate.analyzer0f_32) { - finalize_table( + const code = [ + "#![allow(unused)]", + "#[cfg_attr(rustfmt, rustfmt_skip)]", + "pub fn analyzer(opcode: u8, cpu: &mut ::cpu_context::CpuContext, analysis: &mut ::analysis::Analysis) {", + table0f_32, + "}" + ]; + + finalize_table_rust( OUT_DIR, - "analyzer0f_32", - c_ast.print_syntax_tree([table0f_32]).join("\n") + "\n" + "analyzer0f_32.rs", + rust_ast.print_syntax_tree([].concat(code)).join("\n") + "\n" ); } } diff --git a/gen/generate_jit.js b/gen/generate_jit.js index 477dff83..f1a02aa7 100755 --- a/gen/generate_jit.js +++ b/gen/generate_jit.js @@ -3,14 +3,11 @@ const fs = require("fs"); const path = require("path"); -const encodings = require("./x86_table"); -const c_ast = require("./c_ast"); -const { hex, mkdirpSync, get_switch_value, get_switch_exist, finalize_table } = require("./util"); +const x86_table = require("./x86_table"); +const rust_ast = require("./rust_ast"); +const { hex, mkdirpSync, get_switch_value, get_switch_exist, finalize_table_rust } = require("./util"); -const APPEND_NONFAULTING_FLAG = "instr_flags |= JIT_INSTR_NONFAULTING_FLAG;"; - -const OUT_DIR = get_switch_value("--output-dir") || - path.join(__dirname, "..", "build"); +const OUT_DIR = path.join(__dirname, "..", "src/rust/gen/"); mkdirpSync(OUT_DIR); @@ -37,18 +34,18 @@ function gen_read_imm_call(op, size_variant) { if(op.imm8) { - return "read_imm8()"; + return "ctx.cpu.read_imm8()"; } else if(op.imm8s) { - return "read_imm8s()"; + return "ctx.cpu.read_imm8s()"; } else { if(op.immaddr) { // immaddr: depends on address size - return "read_moffs()"; + return "ctx.cpu.read_moffs()"; } else { @@ -56,12 +53,12 @@ function gen_read_imm_call(op, size_variant) if(op.imm1632 && size === 16 || op.imm16) { - return "read_imm16()"; + return "ctx.cpu.read_imm16()"; } else { console.assert(op.imm1632 && size === 32 || op.imm32); - return "read_imm32s()"; + return "ctx.cpu.read_imm32()"; } } } @@ -80,49 +77,27 @@ function gen_call(name, args) function gen_codegen_call(name, args) { - args = args || []; - const args_count = args.length; - args = [].concat([`"${name}"`, name.length], args); - return gen_call(`gen_fn${args_count}_const`, args); -} + const IMM_VAR_NAME = "imm"; + let imm_read; -function gen_codegen_call_modrm(name, args) -{ - args = (args || []).slice(); + args = (args || []).map(arg => { + if(arg.includes("read_imm")) + { + imm_read = arg; + return IMM_VAR_NAME; + } + else + { + return arg; + } + }); const args_count = args.length; - args = [].concat([`"${name}"`, name.length], args); - - return [ - gen_call(`gen_modrm_resolve`, ["modrm_byte"]), - gen_call(`gen_modrm_fn${args_count}`, args), - ].join(" "); -} - -function gen_custom_jit_call(name, args) -{ - return gen_call(`${name}_jit`, args); -} - -function gen_modrm_mem_reg_split(name, gen_call_fns, mem_args, reg_args, postfixes={}) -{ - const { mem_call_fn, reg_call_fn } = gen_call_fns; - const { mem_postfix=[], reg_postfix=[] } = postfixes; - - return { - type: "if-else", - if_blocks: [{ - condition: "modrm_byte < 0xC0", - body: [] - .concat([mem_call_fn(`${name}_mem`, mem_args)]) - .concat(mem_postfix), - }], - else_block: { - body: [ - reg_call_fn(`${name}_reg`, reg_args) - ].concat(reg_postfix), - }, - }; + args = [].concat(["ctx", `"${name}"`], args); + return [].concat( + imm_read ? `let ${IMM_VAR_NAME} = ${imm_read};` : [], + gen_call(`::codegen::gen_fn${args_count}_const`, args) + ); } /* @@ -130,69 +105,92 @@ function gen_modrm_mem_reg_split(name, gen_call_fns, mem_args, reg_args, postfix * instr(16|32|)_((66|F2|F3)?0F)?[0-9a-f]{2}(_[0-7])?(_mem|_reg|) */ -function make_instruction_name(encoding, size, prefix_variant) +function make_instruction_name(encoding, size) { 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 prefix = (encoding.opcode & 0xFF0000) === 0 ? "" : hex(encoding.opcode >> 16 & 0xFF, 2); const fixed_g_suffix = encoding.fixed_g === undefined ? "" : `_${encoding.fixed_g}`; return `instr${suffix}_${prefix}${prefix_0f}${opcode_hex}${fixed_g_suffix}`; } -function get_nonfaulting_mem_reg_postfix(encoding) -{ - const lea_special_case = encoding.opcode === 0x8D; - // In general only reg_postfixes will append the nonfaulting flag, except in the special case - // for LEA - it doesn't actually access memory, so the memory variant can be nonfaulting - const mem_postfix = (encoding.nonfaulting && lea_special_case) ? [APPEND_NONFAULTING_FLAG] : []; - const reg_postfix = (encoding.nonfaulting && !lea_special_case) ? [APPEND_NONFAULTING_FLAG] : []; - - return { - mem_postfix, - reg_postfix, - }; -} - function gen_instruction_body(encodings, size) { const encoding = encodings[0]; - let has_66 = false; - let has_F2 = false; - let has_F3 = false; + let has_66 = []; + let has_F2 = []; + let has_F3 = []; + let no_prefix = []; 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((e.opcode >>> 16) === 0x66) has_66.push(e); + else if((e.opcode >>> 16) === 0xF2) has_F2.push(e); + else if((e.opcode >>> 16) === 0xF3) has_F3.push(e); + else no_prefix.push(e); } - if(has_66 || has_F2 || has_F3) + if(has_66.length || has_F2.length || has_F3.length) { console.assert((encoding.opcode & 0xFF00) === 0x0F00); - // Leaving unsupported because: - // 1. Instructions that use these prefixes are usually faulting - // 2. It would need a refactor to allow us to pass the correct prefixed encoding object to - // where the nonfaulting flags are set - console.assert( - !encodings.some(e => e.nonfaulting), - "Unsupported: instruction with 66/f2/f3 prefix marked as nonfaulting. Opcode: 0x" + hex(encoding.opcode) - ); } - const instruction_postfix = encoding.block_boundary ? ["instr_flags |= JIT_INSTR_BLOCK_BOUNDARY_FLAG;"] : []; + const code = []; - // May be overridden for custom encodings - const gen_call_fns = { - mem_call_fn: gen_codegen_call_modrm, - reg_call_fn: gen_codegen_call, - }; + if(encoding.e) + { + code.push("let modrm_byte = ctx.cpu.read_imm8();"); + } + + if(has_66.length || has_F2.length || has_F3.length) + { + const if_blocks = []; + + if(has_66.length) { + const body = gen_instruction_body_after_prefix(has_66, size); + if_blocks.push({ condition: "ctx.cpu.prefixes & ::prefix::PREFIX_66 != 0", body, }); + } + if(has_F2.length) { + const body = gen_instruction_body_after_prefix(has_F2, size); + if_blocks.push({ condition: "ctx.cpu.prefixes & ::prefix::PREFIX_F2 != 0", body, }); + } + if(has_F3.length) { + const body = gen_instruction_body_after_prefix(has_F3, size); + if_blocks.push({ condition: "ctx.cpu.prefixes & ::prefix::PREFIX_F3 != 0", body, }); + } + + const else_block = { + body: gen_instruction_body_after_prefix(no_prefix, size), + }; + + return [].concat( + code, + { + type: "if-else", + if_blocks, + else_block, + } + ); + } + else { + return [].concat( + code, + gen_instruction_body_after_prefix(encodings, size) + ); + } +} + +function gen_instruction_body_after_prefix(encodings, size) +{ + const encoding = encodings[0]; if(encoding.fixed_g !== undefined) { + console.assert(encoding.e); + // instruction with modrm byte where the middle 3 bits encode the instruction // group by opcode without prefix plus middle bits of modrm byte @@ -204,171 +202,57 @@ function gen_instruction_body(encodings, size) 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; - let instruction_name = make_instruction_name(case_, size, undefined); - const instruction_postfix = case_.block_boundary ? ["instr_flags |= JIT_INSTR_BLOCK_BOUNDARY_FLAG;"] : []; + const body = gen_instruction_body_after_fixed_g(case_, size); - const mem_args = []; - 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(case_.custom) - { - console.assert(!case_.nonfaulting, "Unsupported: custom fixed_g instruction as nonfaulting"); - instruction_name += "_jit"; - mem_args.push("modrm_byte"); - gen_call_fns.mem_call_fn = gen_call; - gen_call_fns.reg_call_fn = gen_call; - } - - 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, gen_call_fns, 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, gen_call_fns, 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, gen_call_fns, mem_args, reg_args, {})]; - if_blocks.push({ condition: "prefixes_ & PREFIX_F3", body, }); - } - - const else_block = { - body: [ - gen_modrm_mem_reg_split( - instruction_name, - gen_call_fns, - mem_args, - reg_args, - {} - ) - ], - }; - - return { - conditions: [fixed_g], - body: [ - "int32_t prefixes_ = *prefixes;", - { - type: "if-else", - if_blocks, - else_block, - }, - ].concat(instruction_postfix), - }; - } - else - { - const body = [ - gen_modrm_mem_reg_split( - instruction_name, - gen_call_fns, - mem_args, - reg_args, - get_nonfaulting_mem_reg_postfix(case_) - ) - ].concat(instruction_postfix); - - return { - conditions: [fixed_g], - body, - }; - } + return { + conditions: [fixed_g], + body, + }; }), default_case: { - body: [ - gen_codegen_call("trigger_ud"), - ], + body: [].concat( + gen_call(`::codegen::gen_fn0_const`, ["ctx", '"trigger_ud"']) + ), } }, - ].concat(instruction_postfix); + ]; } - else if(has_66 || has_F2 || has_F3) - { - // instruction without modrm byte but with prefix - - console.assert(encoding.e); - console.assert(!encoding.ignore_mod); - - const imm_read = gen_read_imm_call(encoding, size); - - const mem_args = ["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, gen_call_fns, 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, gen_call_fns, 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, gen_call_fns, 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), - gen_call_fns, - mem_args, - reg_args, - {} - ) - ], - }; - - return [ - "int32_t modrm_byte = read_imm8();", - "int32_t prefixes_ = *prefixes;", - { - type: "if-else", - if_blocks, - else_block, - } - ].concat(instruction_postfix); - } - else if(encoding.fixed_g === undefined && encoding.e) - { - // instruction with modrm byte where the middle 3 bits encode a register - + else { console.assert(encodings.length === 1); + return gen_instruction_body_after_fixed_g(encodings[0], size); + } +} - const instruction_name = make_instruction_name(encoding, size); - const imm_read = gen_read_imm_call(encoding, size); +function gen_instruction_body_after_fixed_g(encoding, size) +{ + const instruction_postfix = []; + + if(encoding.block_boundary) + { + instruction_postfix.push("*instr_flags |= ::jit::JIT_INSTR_BLOCK_BOUNDARY_FLAG;"); + } + + const APPEND_NONFAULTING_FLAG = "*instr_flags |= ::jit::JIT_INSTR_NONFAULTING_FLAG;"; + + const imm_read = gen_read_imm_call(encoding, size); + const imm_read_bindings = []; + if(imm_read) + { + imm_read_bindings.push(`let imm = ${imm_read} as u32;`); + } + + const instruction_name = make_instruction_name(encoding, size); + + if(encoding.e) + { + const reg_postfix = encoding.nonfaulting ? [APPEND_NONFAULTING_FLAG] : []; + const mem_postfix = encoding.memory_nonfaulting ? [APPEND_NONFAULTING_FLAG] : []; if(encoding.ignore_mod) { @@ -376,105 +260,99 @@ function gen_instruction_body(encodings, size) // Has modrm byte, but the 2 mod bits are ignored and both // operands are always registers (0f20-0f24) + const args = ["ctx", `"${instruction_name}"`, "(modrm_byte & 7) as u32", "(modrm_byte >> 3 & 7) as u32"]; - if(encoding.nonfaulting) + return [].concat( + gen_call(`::codegen::gen_fn${args.length - 2}_const`, args), + reg_postfix, + instruction_postfix + ); + } + else if(encoding.custom) + { + const mem_args = ["ctx", "modrm_byte"]; + const reg_args = ["ctx", "(modrm_byte & 7) as u32"]; + + if(encoding.fixed_g === undefined) { - instruction_postfix.push(APPEND_NONFAULTING_FLAG); + mem_args.push("(modrm_byte >> 3 & 7) as u32"); + reg_args.push("(modrm_byte >> 3 & 7) as u32"); } - return [ - "int32_t modrm_byte = read_imm8();", - gen_codegen_call(instruction_name, ["modrm_byte & 7", "modrm_byte >> 3 & 7"]), - ].concat(instruction_postfix); - } - else if(encoding.opcode === 0x8D) // lea - { - const mem_args = ["modrm_byte"]; - const reg_args = ["0", "0"]; - gen_call_fns.mem_call_fn = gen_custom_jit_call; - return [ - "int32_t modrm_byte = read_imm8();", - gen_modrm_mem_reg_split( - instruction_name, - gen_call_fns, - mem_args, - reg_args, - get_nonfaulting_mem_reg_postfix(encoding) - ), - ].concat(instruction_postfix); - } - else - { - const mem_args = ["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); + mem_args.push("imm"); + reg_args.push("imm"); } - if(encoding.custom) + return [].concat( + imm_read_bindings, + { + type: "if-else", + if_blocks: [{ + condition: "modrm_byte < 0xC0", + body: [].concat( + gen_call(`::jit_instructions::${instruction_name}_mem_jit`, mem_args), + mem_postfix + ), + }], + else_block: { + body: [].concat( + gen_call(`::jit_instructions::${instruction_name}_reg_jit`, reg_args), + reg_postfix + ), + }, + } + ); + } + else + { + const mem_args = ["ctx", `"${instruction_name}_mem"`]; + const reg_args = ["ctx", `"${instruction_name}_reg"`, "(modrm_byte & 7) as u32"]; + + if(encoding.fixed_g === undefined) { - // The default mem_call_fn adds a modrm_resolve call, but since we override it, - // we also need to pass it in to our custom function to resolve it however it wishes - mem_args.unshift("modrm_byte"); - gen_call_fns.mem_call_fn = gen_custom_jit_call; - gen_call_fns.reg_call_fn = gen_custom_jit_call; + mem_args.push("(modrm_byte >> 3 & 7) as u32"); + reg_args.push("(modrm_byte >> 3 & 7) as u32"); } - return [ - "int32_t modrm_byte = read_imm8();", - gen_modrm_mem_reg_split( - instruction_name, - gen_call_fns, - mem_args, - reg_args, - get_nonfaulting_mem_reg_postfix(encoding) - ), - ].concat(instruction_postfix); + if(imm_read) + { + mem_args.push("imm"); + reg_args.push("imm"); + } + + return [].concat( + { + type: "if-else", + if_blocks: [{ + condition: "modrm_byte < 0xC0", + body: [].concat( + gen_call(`::codegen::gen_modrm_resolve`, ["ctx", "modrm_byte"]), + imm_read_bindings, + gen_call(`::codegen::gen_modrm_fn${mem_args.length - 2}`, mem_args), + mem_postfix + ), + }], + else_block: { + body: [].concat( + imm_read_bindings, + gen_call(`::codegen::gen_fn${reg_args.length - 2}_const`, reg_args), + reg_postfix + ), + }, + }, + instruction_postfix + ); } } else if(encoding.prefix || encoding.custom) { - console.assert(!encoding.nonfaulting, "Prefix/custom instructions cannot be marked as nonfaulting."); + // custom, but not modrm - const instruction_name = make_instruction_name(encoding, size) + "_jit"; - const imm_read = gen_read_imm_call(encoding, size); - const args = []; - - if(imm_read) + if(encoding.prefix) { - args.push(imm_read); - } - - const call_prefix = encoding.prefix ? "instr_flags |= " : ""; - // Prefix calls can add to the return flags - return [call_prefix + gen_call(instruction_name, args)].concat(instruction_postfix); - } - 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()"); + console.assert(!encoding.nonfaulting, "Prefix instructions cannot be marked as nonfaulting."); } if(encoding.nonfaulting) @@ -482,7 +360,58 @@ function gen_instruction_body(encodings, size) instruction_postfix.push(APPEND_NONFAULTING_FLAG); } - return [gen_codegen_call(instruction_name, args)].concat(instruction_postfix); + const args = ["ctx"]; + + if(imm_read) + { + args.push("imm"); + } + + if(encoding.prefix) + { + args.push("instr_flags"); + } + + return [].concat( + imm_read_bindings, + gen_call(`::jit_instructions::${instruction_name}_jit`, args), + instruction_postfix + ); + } + else + { + // instruction without modrm byte or prefix + + if(encoding.nonfaulting) + { + instruction_postfix.push(APPEND_NONFAULTING_FLAG); + } + + const args = ["ctx", `"${instruction_name}"`]; + + if(imm_read) + { + args.push("imm"); + } + + if(encoding.extra_imm16) + { + console.assert(imm_read); + imm_read_bindings.push(`let imm2 = ctx.cpu.read_imm16() as u32;`); + args.push("imm2"); + } + else if(encoding.extra_imm8) + { + console.assert(imm_read); + imm_read_bindings.push(`let imm2 = ctx.cpu.read_imm8() as u32;`); + args.push("imm2"); + } + + return [].concat( + imm_read_bindings, + gen_call(`::codegen::gen_fn${args.length - 2}_const`, args), + instruction_postfix + ); } } @@ -491,7 +420,7 @@ function gen_table() let by_opcode = Object.create(null); let by_opcode0f = Object.create(null); - for(let o of encodings) + for(let o of x86_table) { let opcode = o.opcode; @@ -518,6 +447,7 @@ function gen_table() console.assert(encoding && encoding.length); let opcode_hex = hex(opcode, 2); + let opcode_high_hex = hex(opcode | 0x100, 2); if(encoding[0].os) { @@ -526,14 +456,14 @@ function gen_table() body: gen_instruction_body(encoding, 16), }); cases.push({ - conditions: [`0x${opcode_hex}|0x100`], + conditions: [`0x${opcode_high_hex}`], body: gen_instruction_body(encoding, 32), }); } else { cases.push({ - conditions: [`0x${opcode_hex}`, `0x${opcode_hex}|0x100`], + conditions: [`0x${opcode_hex}`, `0x${opcode_high_hex}`], body: gen_instruction_body(encoding, undefined), }); } @@ -543,16 +473,23 @@ function gen_table() condition: "opcode", cases, default_case: { - body: ["assert(false);"] + body: ["assert!(false);"] }, }; if(to_generate.jit) { - finalize_table( + const code = [ + "#[cfg_attr(rustfmt, rustfmt_skip)]", + "pub fn jit(opcode: u32, ctx: &mut ::jit::JitContext, instr_flags: &mut u32) {", + table, + "}", + ]; + + finalize_table_rust( OUT_DIR, - "jit", - c_ast.print_syntax_tree([table]).join("\n") + "\n" + "jit.rs", + rust_ast.print_syntax_tree([].concat(code)).join("\n") + "\n" ); } @@ -593,7 +530,7 @@ function gen_table() condition: "opcode", cases: cases0f_16, default_case: { - body: ["assert(false);"] + body: ["assert!(false);"] }, }; const table0f_32 = { @@ -601,25 +538,39 @@ function gen_table() condition: "opcode", cases: cases0f_32, default_case: { - body: ["assert(false);"] + body: ["assert!(false);"] }, }; if(to_generate.jit0f_16) { - finalize_table( + const code = [ + "#[cfg_attr(rustfmt, rustfmt_skip)]", + "pub fn jit(opcode: u8, ctx: &mut ::jit::JitContext, instr_flags: &mut u32) {", + table0f_16, + "}", + ]; + + finalize_table_rust( OUT_DIR, - "jit0f_16", - c_ast.print_syntax_tree([table0f_16]).join("\n") + "\n" + "jit0f_16.rs", + rust_ast.print_syntax_tree([].concat(code)).join("\n") + "\n" ); } if(to_generate.jit0f_32) { - finalize_table( + const code = [ + "#[cfg_attr(rustfmt, rustfmt_skip)]", + "pub fn jit(opcode: u8, ctx: &mut ::jit::JitContext, instr_flags: &mut u32) {", + table0f_32, + "}", + ]; + + finalize_table_rust( OUT_DIR, - "jit0f_32", - c_ast.print_syntax_tree([table0f_32]).join("\n") + "\n" + "jit0f_32.rs", + rust_ast.print_syntax_tree([].concat(code)).join("\n") + "\n" ); } } diff --git a/gen/rust_ast.js b/gen/rust_ast.js new file mode 100644 index 00000000..bc4fa762 --- /dev/null +++ b/gen/rust_ast.js @@ -0,0 +1,88 @@ +"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); + + cases.push(case_.conditions.join(" | ") + " => {"); + cases.push.apply(cases, indent(print_syntax_tree(case_.body), 4)); + cases.push(`},`); + } + + if(statement.default_case) + { + cases.push(`_ => {`); + cases.push.apply(cases, indent(print_syntax_tree(statement.default_case.body), 4)); + cases.push(`}`); + } + + code.push(`match ${statement.condition} {`); + 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.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.apply(code, indent(print_syntax_tree(if_block.body), 4)); + code.push(`}`); + } + + if(statement.else_block) + { + code.push(`else {`); + code.push.apply(code, indent(print_syntax_tree(statement.else_block.body), 4)); + code.push(`}`); + } + } + else + { + console.assert(false, "Unexpected type: " + statement.type, "In:", statement); + } + } + + return code; +} + +module.exports = { + print_syntax_tree, +}; diff --git a/gen/util.js b/gen/util.js index f0309801..71a706df 100644 --- a/gen/util.js +++ b/gen/util.js @@ -74,10 +74,20 @@ function finalize_table(out_dir, name, contents) console.log(CYAN_FMT, `[+] Wrote table ${name}. Remember to check ${diff_file_path}`); } +function finalize_table_rust(out_dir, name, contents) +{ + const file_path = path.join(out_dir, name); + + fs.writeFileSync(file_path, contents); + + console.log(CYAN_FMT, `[+] Wrote table ${name}.`); +} + module.exports = { hex, mkdirpSync, get_switch_value, get_switch_exist, finalize_table, + finalize_table_rust, }; diff --git a/gen/x86_table.js b/gen/x86_table.js index 2cb614f9..f49a4dc8 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -98,7 +98,7 @@ const encodings = [ { opcode: 0x8B, custom: 1, nonfaulting: 1, os: 1, e: 1, }, { opcode: 0x8C, os: 1, e: 1, skip: 1, }, - { opcode: 0x8D, nonfaulting: 1, os: 1, e: 1, only_mem: 1, requires_prefix_call: 1, custom: 1, }, // lea + { opcode: 0x8D, memory_nonfaulting: 1, os: 1, e: 1, only_mem: 1, requires_prefix_call: 1, custom: 1, }, // lea { opcode: 0x8E, block_boundary: 1, e: 1, skip: 1, }, // mov sreg { opcode: 0x8F, os: 1, e: 1, fixed_g: 0, requires_prefix_call: 1, custom: 1, }, // pop r/m @@ -196,23 +196,23 @@ const encodings = [ { opcode: 0xF4, block_boundary: 1, no_next_instruction: 1, skip: 1, }, // hlt { opcode: 0xF5, nonfaulting: 1, }, - { opcode: 0xF6, fixed_g: 0, nonfaulting: 1, imm8: 1, }, - { opcode: 0xF6, fixed_g: 1, nonfaulting: 1, imm8: 1, }, - { opcode: 0xF6, fixed_g: 2, nonfaulting: 1, }, - { opcode: 0xF6, fixed_g: 3, nonfaulting: 1, }, - { opcode: 0xF6, fixed_g: 4, nonfaulting: 1, mask_flags: af | zf, }, - { opcode: 0xF6, fixed_g: 5, nonfaulting: 1, mask_flags: af | zf, }, - { opcode: 0xF6, fixed_g: 6, }, - { opcode: 0xF6, fixed_g: 7, }, + { opcode: 0xF6, e: 1, fixed_g: 0, nonfaulting: 1, imm8: 1, }, + { opcode: 0xF6, e: 1, fixed_g: 1, nonfaulting: 1, imm8: 1, }, + { opcode: 0xF6, e: 1, fixed_g: 2, nonfaulting: 1, }, + { opcode: 0xF6, e: 1, fixed_g: 3, nonfaulting: 1, }, + { opcode: 0xF6, e: 1, fixed_g: 4, nonfaulting: 1, mask_flags: af | zf, }, + { opcode: 0xF6, e: 1, fixed_g: 5, nonfaulting: 1, mask_flags: af | zf, }, + { opcode: 0xF6, e: 1, fixed_g: 6, }, + { opcode: 0xF6, e: 1, fixed_g: 7, }, - { opcode: 0xF7, os: 1, fixed_g: 0, nonfaulting: 1, imm1632: 1, }, - { opcode: 0xF7, os: 1, fixed_g: 1, nonfaulting: 1, imm1632: 1, }, - { opcode: 0xF7, os: 1, fixed_g: 2, nonfaulting: 1, }, - { opcode: 0xF7, os: 1, fixed_g: 3, nonfaulting: 1, }, - { opcode: 0xF7, os: 1, fixed_g: 4, nonfaulting: 1, mask_flags: zf | af, }, - { opcode: 0xF7, os: 1, fixed_g: 5, nonfaulting: 1, mask_flags: zf | af, }, - { opcode: 0xF7, os: 1, fixed_g: 6, }, - { opcode: 0xF7, os: 1, fixed_g: 7, }, + { opcode: 0xF7, os: 1, e: 1, fixed_g: 0, nonfaulting: 1, imm1632: 1, }, + { opcode: 0xF7, os: 1, e: 1, fixed_g: 1, nonfaulting: 1, imm1632: 1, }, + { opcode: 0xF7, os: 1, e: 1, fixed_g: 2, nonfaulting: 1, }, + { opcode: 0xF7, os: 1, e: 1, fixed_g: 3, nonfaulting: 1, }, + { opcode: 0xF7, os: 1, e: 1, fixed_g: 4, nonfaulting: 1, mask_flags: zf | af, }, + { opcode: 0xF7, os: 1, e: 1, fixed_g: 5, nonfaulting: 1, mask_flags: zf | af, }, + { opcode: 0xF7, os: 1, e: 1, fixed_g: 6, }, + { opcode: 0xF7, os: 1, e: 1, fixed_g: 7, }, { opcode: 0xF8, nonfaulting: 1, }, { opcode: 0xF9, nonfaulting: 1, }, @@ -408,6 +408,7 @@ const encodings = [ { opcode: 0x0FB7, nonfaulting: 1, os: 1, e: 1, }, { opcode: 0xF30FB8, os: 1, e: 1 }, // popcnt + { opcode: 0x0FB8, os: 1, e: 1, }, // ud { opcode: 0x0FB9, }, // ud2 @@ -519,7 +520,9 @@ const encodings = [ { opcode: 0x660F6B, e: 1 }, { opcode: 0x0F6B, e: 1 }, { opcode: 0x660F6C, e: 1 }, + { opcode: 0x0F6C, e: 1, }, // ud { opcode: 0x660F6D, e: 1 }, + { opcode: 0x0F6D, e: 1, }, // ud { opcode: 0x660F6E, e: 1 }, { opcode: 0x0F6E, e: 1 }, { opcode: 0xF30F6F, e: 1 }, @@ -601,6 +604,7 @@ const encodings = [ { opcode: 0x660FD6, e: 1 }, { opcode: 0xF20FD6, only_reg: 1, e: 1 }, { opcode: 0xF30FD6, only_reg: 1, e: 1 }, + { opcode: 0x0FD6, e: 1, }, // ud { opcode: 0x0FD7, e: 1, only_reg: 1 }, { opcode: 0x660FD7, e: 1, only_reg: 1, }, @@ -637,6 +641,7 @@ const encodings = [ { opcode: 0x660FE6, e: 1, skip: 1, }, { opcode: 0xF20FE6, e: 1, skip: 1, }, { opcode: 0xF30FE6, e: 1, skip: 1, }, + { opcode: 0x0FE6, e: 1, }, // ud { opcode: 0x0FE7, e: 1, only_mem: 1 }, { opcode: 0x660FE7, e: 1, only_mem: 1, }, diff --git a/src/browser/lib.js b/src/browser/lib.js index 1efc9ffb..518e528e 100644 --- a/src/browser/lib.js +++ b/src/browser/lib.js @@ -113,10 +113,13 @@ var ASYNC_SAFE = false; WebAssembly.compile(buffer) .then(module => { const dylink = v86util.decode_dylink(module); - const total_mem_pages = Math.ceil( + let total_mem_pages = Math.ceil( (dylink.memory_size + memory_size) / WASM_PAGE_SIZE ); + // emscripten seems to require a minimum of 256 pages (16 MB) + total_mem_pages = Math.max(256, total_mem_pages); + try { imports["env"]["memory"] = new WebAssembly.Memory({ diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index c6617b11..ca02adae 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -24,23 +24,23 @@ const print_stats = { "RUN_INTERPRETED", "RUN_INTERPRETED_PENDING", "RUN_INTERPRETED_NEAR_END_OF_PAGE", - "RUN_INTERPRETED_NOT_HOT", + "RUN_INTERPRETED_DIFFERENT_STATE", "RUN_INTERPRETED_STEPS", "RUN_FROM_CACHE", "RUN_FROM_CACHE_STEPS", "TRIGGER_CPU_EXCEPTION", - "S_SAFE_READ32_FAST", - "S_SAFE_READ32_SLOW_PAGE_CROSSED", - "S_SAFE_READ32_SLOW_NOT_VALID", - "S_SAFE_READ32_SLOW_NOT_USER", - "S_SAFE_READ32_SLOW_IN_MAPPED_RANGE", - "S_SAFE_WRITE32_FAST", - "S_SAFE_WRITE32_SLOW_PAGE_CROSSED", - "S_SAFE_WRITE32_SLOW_NOT_VALID", - "S_SAFE_WRITE32_SLOW_NOT_USER", - "S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE", - "S_SAFE_WRITE32_SLOW_READ_ONLY", - "S_SAFE_WRITE32_SLOW_HAS_CODE", + "SAFE_READ32_FAST", + "SAFE_READ32_SLOW_PAGE_CROSSED", + "SAFE_READ32_SLOW_NOT_VALID", + "SAFE_READ32_SLOW_NOT_USER", + "SAFE_READ32_SLOW_IN_MAPPED_RANGE", + "SAFE_WRITE32_FAST", + "SAFE_WRITE32_SLOW_PAGE_CROSSED", + "SAFE_WRITE32_SLOW_NOT_VALID", + "SAFE_WRITE32_SLOW_NOT_USER", + "SAFE_WRITE32_SLOW_IN_MAPPED_RANGE", + "SAFE_WRITE32_SLOW_READ_ONLY", + "SAFE_WRITE32_SLOW_HAS_CODE", "DO_RUN", "DO_MANY_CYCLES", "CYCLE_INTERNAL", @@ -68,8 +68,8 @@ const print_stats = { text += "\n"; text += "TLB_ENTRIES=" + cpu.wm.exports["_get_valid_tlb_entries_count"]() + "\n"; - text += "CACHE_UNUSED=" + cpu.wm.exports["_jit_unused_cache_stat"]() + "\n"; - text += "WASM_TABLE_FREE=" + cpu.wm.exports["_get_wasm_table_index_free_list_count"]() + "\n"; + text += "CACHE_UNUSED=" + cpu.v86oxide.exports["jit_unused_cache_stat"]() + "\n"; + text += "WASM_TABLE_FREE=" + cpu.v86oxide.exports["jit_get_wasm_table_index_free_list_count"]() + "\n"; text += "do_many_cycles avg: " + do_many_cycles_total / do_many_cycles_count + "\n"; @@ -86,7 +86,7 @@ const print_stats = { for(let i = 0; i < JIT_CACHE_ARRAY_SIZE; i++) { - const address = cpu.wm.exports["_jit_get_entry_address"](i); + const address = cpu.v86oxide.exports["jit_get_entry_address"](i); if(address !== 0) { @@ -117,10 +117,10 @@ const print_stats = { let pending_count = 0; const histogram = Object.create(null); - for(let i = 0; i < 0x10000; i++) + for(let i = 0; i < JIT_CACHE_ARRAY_SIZE; i++) { - const length = cpu.wm.exports["_jit_get_entry_length"](i); - pending_count += cpu.wm.exports["_jit_get_entry_pending"](i); + const length = cpu.v86oxide.exports["jit_get_entry_length"](i); + pending_count += cpu.v86oxide.exports["jit_get_entry_pending"](i); histogram[length] = (histogram[length] || 0) + 1; } diff --git a/src/browser/starter.js b/src/browser/starter.js index 004f9958..ee9befe9 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -136,7 +136,6 @@ function V86Starter(options) "_cpu_exception_hook": (n) => { return this["cpu_exception_hook"] && this["cpu_exception_hook"](n); }, - "_jit_clear_func": function(index) { return cpu.jit_clear_func(index); }, "_hlt_op": function() { return cpu.hlt_op(); }, "abort": function() { dbg_assert(false); }, "__dbg_trace": function() { return dbg_trace(); }, @@ -224,16 +223,9 @@ function V86Starter(options) }, "_get_time": Date.now, - "_codegen_finalize": (wasm_table_index, start, end, first_opcode, state_flags) => { - cpu.codegen_finalize(wasm_table_index, start, end, first_opcode, state_flags); - }, "_coverage_log": (fn_name_offset, num_blocks, visited_block) => { coverage_logger.log(fn_name_offset, num_blocks, visited_block); }, - "_log_uncompiled_code": (start, end) => cpu.log_uncompiled_code(start, end), - "_dump_function_code": (blocks_ptr, count, end) => { - cpu.dump_function_code(blocks_ptr, count, end); - }, // see https://github.com/kripken/emscripten/blob/incoming/src/library.js "_atan2": Math.atan2, @@ -260,7 +252,7 @@ function V86Starter(options) "NaN": NaN, }; - const v86oxide_mem = new WebAssembly.Memory({ "initial": 100 }); + const v86oxide_mem = new WebAssembly.Memory({ "initial": 250 }); const v86oxide_externs = { "memory": v86oxide_mem, "log_from_wasm": function(offset, len) { @@ -270,6 +262,14 @@ function V86Starter(options) "abort": function() { dbg_assert(false); }, + + "read8": addr => cpu.read8(addr), + "read16": addr => cpu.read16(addr), + "read32": addr => cpu.read32s(addr), + "tlb_set_has_code": (page, has_code) => cpu.wm.exports["_tlb_set_has_code"](page, has_code), + "check_tlb_invariants": () => cpu.wm.exports["_check_tlb_invariants"](), + "codegen_finalize": (wasm_table_index, start, end, first_opcode, state_flags) => cpu.codegen_finalize(wasm_table_index, start, end, first_opcode, state_flags), + "profiler_stat_increment": (name) => cpu.wm.exports["_profiler_stat_increment"](name), }; let wasm_file = DEBUG ? "v86-debug.wasm" : "v86.wasm"; @@ -287,56 +287,22 @@ function V86Starter(options) } const v86oxide_exports = [ - "wg_get_code_section", - "wg_get_instruction_body", - "wg_commit_instruction_body_to_cs", - "wg_finish", - "wg_reset", - "wg_get_fn_idx", + // For C: + "jit_get_entry_pending", + "jit_get_entry_address", + "jit_get_entry_length", + "jit_unused_cache_stat", + "jit_dirty_cache_single", + "jit_dirty_cache_small", + "jit_page_has_code", + "jit_increase_hotness_and_maybe_compile", + "jit_find_cache_entry", - "wg_push_i32", - "wg_push_u32", - "wg_load_aligned_u16", - "wg_load_aligned_i32", - "wg_store_aligned_u16", - "wg_store_aligned_i32", - "wg_add_i32", - "wg_and_i32", - "wg_or_i32", - "wg_shl_i32", - "wg_call_fn", - "wg_call_fn_with_arg", - "wg_eq_i32", - "wg_ne_i32", - "wg_le_i32", - "wg_lt_i32", - "wg_ge_i32", - "wg_gt_i32", - "wg_if_i32", - "wg_block_i32", - "wg_tee_local", - "wg_xor_i32", - "wg_load_unaligned_i32_from_stack", - "wg_load_aligned_i32_from_stack", - "wg_store_unaligned_i32", - "wg_shr_u32", - "wg_shr_i32", - "wg_eqz_i32", - "wg_if_void", - "wg_else", - "wg_loop_void", - "wg_block_void", - "wg_block_end", - "wg_return", - "wg_drop", - "wg_brtable_and_cases", - "wg_br", - "wg_get_local", - "wg_set_local", - "wg_unreachable", - "wg_increment_mem32", - "wg_increment_variable", - "wg_load_aligned_u16_from_stack", + // For JS: + "jit_empty_cache", + "codegen_finalize_finished", + "rust_setup", + "jit_dirty_cache", ]; v86util.minimal_load_wasm(v86oxide_bin, { "env": v86oxide_externs }, (v86oxide) => { @@ -345,7 +311,7 @@ function V86Starter(options) dbg_assert(typeof v86oxide.exports[fn_name] === "function", `Function ${fn_name} not found in v86oxide exports`); wasm_shared_funcs[`_${fn_name}`] = v86oxide.exports[fn_name]; } - v86oxide.exports["wg_setup"](); + v86oxide.exports["rust_setup"](); //XXX: fix indentation break diff --git a/src/config.js b/src/config.js index 15e3928f..96b8bafb 100644 --- a/src/config.js +++ b/src/config.js @@ -12,7 +12,7 @@ var DEBUG = true; /** @const * Also needs to be set in config.h */ -var ENABLE_PROFILER = true; +var ENABLE_PROFILER = false; /** @const */ var LOG_TO_FILE = false; diff --git a/src/const.js b/src/const.js index 08260a11..2e6cfda5 100644 --- a/src/const.js +++ b/src/const.js @@ -367,7 +367,7 @@ const WASM_EXPORT_TABLE_NAME = "table"; /** @const */ // The space we need for misc internal state before the beginning of mem8; see global_pointers.h -const GUEST_MEMORY_START = 0x400000 + 0x100000 * 8; +const GUEST_MEMORY_START = 0x800000; /** @const */ const WASM_PAGE_SIZE = 64 * 1024; diff --git a/src/cpu.js b/src/cpu.js index 1db4fd85..01b8d0eb 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -208,7 +208,7 @@ function CPU(bus, wm, v86oxide, coverage_logger) this.update_operand_size(); - wm.exports["_set_tsc"](0, 0); + this.set_tsc(0, 0); this.debug_init(); @@ -217,8 +217,8 @@ function CPU(bus, wm, v86oxide, coverage_logger) CPU.prototype.wasmgen_get_module_code = function() { - const ptr = this.v86oxide.exports["wg_get_op_ptr"](); - const len = this.v86oxide.exports["wg_get_op_len"](); + const ptr = this.jit_get_op_ptr(); + const len = this.jit_get_op_len(); const output_buffer_view = new Uint8Array(this.v86oxide.memory.buffer, ptr, len); return output_buffer_view; @@ -300,7 +300,25 @@ CPU.prototype.wasm_patch = function(wm) this.clear_tlb = this.wm.exports["_clear_tlb"]; this.full_clear_tlb = this.wm.exports["_full_clear_tlb"]; - this.jit_force_generate_unsafe = this.wm.exports["_jit_force_generate_unsafe"]; + this.set_tsc = this.wm.exports["_set_tsc"]; + this.store_current_tsc = this.wm.exports["_store_current_tsc"]; + + this.pack_current_state_flags = this.wm.exports["_pack_current_state_flags"]; + + this.jit_force_generate_unsafe = this.v86oxide.exports["jit_force_generate_unsafe"]; + this.jit_empty_cache = this.v86oxide.exports["jit_empty_cache"]; + this.jit_dirty_cache = this.v86oxide.exports["jit_dirty_cache"]; + this.codegen_finalize_finished = this.v86oxide.exports["codegen_finalize_finished"]; + + this.jit_get_op_ptr = this.v86oxide.exports["jit_get_op_ptr"]; + this.jit_get_op_len = this.v86oxide.exports["jit_get_op_len"]; +}; + +CPU.prototype.jit_force_generate = function(addr) +{ + const cs_offset = this.get_seg(reg_cs); + const state_flags = this.pack_current_state_flags(); + this.jit_force_generate_unsafe(addr, cs_offset, state_flags); }; CPU.prototype.jit_clear_func = function(index) @@ -353,7 +371,7 @@ CPU.prototype.get_state = function() state[41] = this.dreg; state[42] = this.mem8; - this.wm.exports["_store_current_tsc"](); + this.store_current_tsc(); state[43] = this.current_tsc; state[45] = this.devices.virtio_9p; @@ -440,7 +458,7 @@ CPU.prototype.set_state = function(state) this.dreg.set(state[41]); this.mem8.set(state[42]); - this.wm.exports["_set_tsc"](state[43][0], state[43][1]); + this.set_tsc(state[43][0], state[43][1]); this.devices.virtio_9p = state[45]; this.devices.apic = state[46]; @@ -616,7 +634,7 @@ CPU.prototype.reset = function() this.last_op2.fill(0); this.last_op_size.fill(0); - this.wm.exports["_set_tsc"](0, 0); + this.set_tsc(0, 0); this.instruction_pointer[0] = 0xFFFF0; this.switch_cs_real_mode(0xF000); @@ -631,7 +649,7 @@ CPU.prototype.reset = function() this.fw_value[0] = 0; - this.jit_empty_cache(); + this.jit_clear_cache(); }; CPU.prototype.reset_memory = function() @@ -1261,7 +1279,7 @@ CPU.prototype.codegen_finalize = function(wasm_table_index, start, end, first_op const result = WebAssembly.instantiate(code, { "e": jit_imports }).then(result => { const f = result.instance.exports["f"]; - this.wm.exports["_codegen_finalize_finished"]( + this.codegen_finalize_finished( wasm_table_index, start, end, first_opcode, state_flags); @@ -1434,8 +1452,6 @@ CPU.prototype.set_cr0 = function(cr0) } this.protected_mode[0] = +((this.cr[0] & CR0_PE) === CR0_PE); - - //this.jit_empty_cache(); }; CPU.prototype.set_cr4 = function(cr4) @@ -1484,9 +1500,9 @@ CPU.prototype.cpl_changed = function() this.last_virt_esp[0] = -1; }; -CPU.prototype.jit_empty_cache = function() +CPU.prototype.jit_clear_cache = function() { - this.wm.exports["_jit_empty_cache"](); + this.jit_empty_cache(); const table = this.wm.imports["env"][WASM_EXPORT_TABLE_NAME]; @@ -3145,9 +3161,6 @@ CPU.prototype.update_cs_size = function(new_size) if(Boolean(this.is_32[0]) !== new_size) { - //dbg_log("clear instruction cache", LOG_CPU); - //this.jit_empty_cache(); - this.is_32[0] = +new_size; this.update_operand_size(); } diff --git a/src/memory.js b/src/memory.js index 3605e605..7e05260b 100644 --- a/src/memory.js +++ b/src/memory.js @@ -63,7 +63,7 @@ CPU.prototype.write_blob = function(blob, offset) dbg_assert(!this.in_mapped_range(offset)); dbg_assert(!this.in_mapped_range(offset + blob.length)); - this.wm.exports["_jit_dirty_cache"](offset, offset + blob.length); + this.jit_dirty_cache(offset, offset + blob.length); this.mem8.set(blob, offset); }; diff --git a/src/native/codegen/codegen.c b/src/native/codegen/codegen.c deleted file mode 100644 index 6e17df6d..00000000 --- a/src/native/codegen/codegen.c +++ /dev/null @@ -1,678 +0,0 @@ -#include -#include -#include - -#include "../const.h" -#include "../cpu.h" -#include "../global_pointers.h" -#include "../log.h" -#include "codegen.h" -#include "wasmgen.h" - -static void jit_add_seg_offset(int32_t default_segment); -static void jit_resolve_modrm32_(int32_t modrm_byte); -static void jit_resolve_modrm16_(int32_t modrm_byte); -PackedStr pack_str(char const* fn_name, uint8_t fn_len); - -void gen_reset(void) -{ - wg_reset(); - cs = wg_get_code_section(); - instruction_body = wg_get_instruction_body(); - add_get_seg_import(); -} - -void add_get_seg_import(void) -{ - uint16_t _fn_get_seg_idx = get_fn_idx("get_seg", 7, FN1_RET_TYPE_INDEX); - assert(_fn_get_seg_idx == fn_get_seg_idx); - UNUSED(_fn_get_seg_idx); -} - -PackedStr pack_str(char const* fn_name, uint8_t fn_len) -{ - assert(fn_len <= 24); - - union { - PackedStr pstr; - uint8_t u8s[24]; - } ret = { { 0, 0, 0 } }; - - for(int i = 0; i < fn_len; i++) - { - ret.u8s[i] = fn_name[i]; - } - return ret.pstr; -} - -uint16_t get_fn_idx(char const* fn, uint8_t fn_len, uint8_t fn_type) -{ - PackedStr pstr = pack_str(fn, fn_len); - return wg_get_fn_idx(pstr.a, pstr.b, pstr.c, fn_type); -} - -void gen_increment_mem32(int32_t addr) -{ - wg_increment_mem32(cs, addr); -} - -void gen_increment_variable(int32_t variable_address, int32_t n) -{ - wg_increment_variable(cs, variable_address, n); -} - -void gen_increment_instruction_pointer(int32_t n) -{ - wg_push_i32(cs, (int32_t)instruction_pointer); // store address of ip - - wg_load_aligned_i32(cs, (int32_t)instruction_pointer); // load ip - - wg_push_i32(cs, n); - - wg_add_i32(cs); - wg_store_aligned_i32(cs); // store it back in -} - -void gen_relative_jump(int32_t n) -{ - // add n to instruction_pointer (without setting the offset as above) - wg_push_i32(instruction_body, (int32_t)instruction_pointer); - wg_load_aligned_i32(instruction_body, (int32_t)instruction_pointer); - wg_push_i32(instruction_body, n); - wg_add_i32(instruction_body); - wg_store_aligned_i32(instruction_body); -} - -void gen_increment_timestamp_counter(uint32_t n) -{ - gen_increment_variable((int32_t)timestamp_counter, n); -} - -void gen_set_previous_eip_offset_from_eip(int32_t n) -{ - wg_push_i32(cs, (int32_t)previous_ip); // store address of previous ip - wg_load_aligned_i32(cs, (int32_t)instruction_pointer); // load ip - if(n != 0) - { - wg_push_i32(cs, n); - wg_add_i32(cs); // add constant to ip value - } - wg_store_aligned_i32(cs); // store it as previous ip -} - -void gen_set_previous_eip(void) -{ - wg_push_i32(cs, (int32_t)previous_ip); // store address of previous ip - wg_load_aligned_i32(cs, (int32_t)instruction_pointer); // load ip - wg_store_aligned_i32(cs); // store it as previous ip -} - -void gen_clear_prefixes(void) -{ - wg_push_i32(instruction_body, (int32_t)prefixes); // load address of prefixes - wg_push_i32(instruction_body, 0); - wg_store_aligned_i32(instruction_body); -} - -void gen_add_prefix_bits(int32_t mask) -{ - assert(mask >= 0 && mask < 0x100); - - wg_push_i32(instruction_body, (int32_t)prefixes); // load address of prefixes - - wg_load_aligned_i32(instruction_body, (int32_t)prefixes); // load old value - wg_push_i32(instruction_body, mask); - wg_or_i32(instruction_body); - - wg_store_aligned_i32(instruction_body); -} - -void gen_fn0_const_ret(char const* fn, uint8_t fn_len) -{ - int32_t fn_idx = get_fn_idx(fn, fn_len, FN0_RET_TYPE_INDEX); - wg_call_fn(instruction_body, fn_idx); -} - -void gen_fn0_const(char const* fn, uint8_t fn_len) -{ - int32_t fn_idx = get_fn_idx(fn, fn_len, FN0_TYPE_INDEX); - wg_call_fn(instruction_body, fn_idx); -} - -void gen_set_reg16_fn0(char const* fn, uint8_t fn_len, int32_t reg) -{ - // generates: reg16[reg] = fn() - int32_t fn_idx = get_fn_idx(fn, fn_len, FN0_RET_TYPE_INDEX); - wg_push_i32(instruction_body, (int32_t) ®16[reg]); - wg_call_fn(instruction_body, fn_idx); - wg_store_aligned_u16(instruction_body); -} - -void gen_set_reg32s_fn0(char const* fn, uint8_t fn_len, int32_t reg) -{ - // generates: reg32s[reg] = fn() - int32_t fn_idx = get_fn_idx(fn, fn_len, FN0_RET_TYPE_INDEX); - wg_push_i32(instruction_body, (int32_t) ®32s[reg]); - wg_call_fn(instruction_body, fn_idx); - wg_store_aligned_i32(instruction_body); -} - -void gen_fn1_const_ret(char const* fn, uint8_t fn_len, int32_t arg0) -{ - int32_t fn_idx = get_fn_idx(fn, fn_len, FN1_RET_TYPE_INDEX); - wg_push_i32(instruction_body, arg0); - wg_call_fn(instruction_body, fn_idx); -} - -void gen_call_fn1_ret(char const* fn, uint8_t fn_len) -{ - // generates: fn( _ ) where _ must be left on the stack before calling this, and fn returns a value - int32_t fn_idx = get_fn_idx(fn, fn_len, FN1_RET_TYPE_INDEX); - wg_call_fn(instruction_body, fn_idx); -} - -void gen_call_fn1(char const* fn, uint8_t fn_len) -{ - // generates: fn( _ ) where _ must be left on the stack before calling this - int32_t fn_idx = get_fn_idx(fn, fn_len, FN1_TYPE_INDEX); - wg_call_fn(instruction_body, fn_idx); -} - -void gen_fn1_const(char const* fn, uint8_t fn_len, int32_t arg0) -{ - int32_t fn_idx = get_fn_idx(fn, fn_len, FN1_TYPE_INDEX); - wg_push_i32(instruction_body, arg0); - wg_call_fn(instruction_body, fn_idx); -} - -void gen_set_reg16_r(int32_t r_dest, int32_t r_src) -{ - // generates: reg16[r_dest] = reg16[r_src] - wg_push_i32(instruction_body, (int32_t) ®16[r_dest]); - wg_load_aligned_u16(instruction_body, (int32_t) ®16[r_src]); - wg_store_aligned_u16(instruction_body); -} - -void gen_set_reg32_r(int32_t r_dest, int32_t r_src) -{ - // generates: reg32s[r_dest] = reg32s[r_src] - wg_push_i32(instruction_body, (int32_t) ®32s[r_dest]); - wg_load_aligned_i32(instruction_body, (int32_t) ®32s[r_src]); - wg_store_aligned_i32(instruction_body); -} - -void gen_fn1_reg16(char const* fn, uint8_t fn_len, int32_t reg) -{ - // generates: fn(reg16[reg]) - int32_t fn_idx = get_fn_idx(fn, fn_len, FN1_TYPE_INDEX); - wg_load_aligned_u16(instruction_body, (int32_t) ®16[reg]); - wg_call_fn(instruction_body, fn_idx); -} - -void gen_fn1_reg32s(char const* fn, uint8_t fn_len, int32_t reg) -{ - // generates: fn(reg32s[reg]) - int32_t fn_idx = get_fn_idx(fn, fn_len, FN1_TYPE_INDEX); - wg_load_aligned_i32(instruction_body, (int32_t) ®32s[reg]); - wg_call_fn(instruction_body, fn_idx); -} - - -void gen_call_fn2(char const* fn, uint8_t fn_len) -{ - // generates: fn( _, _ ) where _ must be left on the stack before calling this - int32_t fn_idx = get_fn_idx(fn, fn_len, FN2_TYPE_INDEX); - wg_call_fn(instruction_body, fn_idx); -} - -void gen_fn2_const(char const* fn, uint8_t fn_len, int32_t arg0, int32_t arg1) -{ - int32_t fn_idx = get_fn_idx(fn, fn_len, FN2_TYPE_INDEX); - wg_push_i32(instruction_body, arg0); - wg_push_i32(instruction_body, arg1); - wg_call_fn(instruction_body, fn_idx); -} - -void gen_fn3_const(char const* fn, uint8_t fn_len, int32_t arg0, int32_t arg1, int32_t arg2) -{ - int32_t fn_idx = get_fn_idx(fn, fn_len, FN3_TYPE_INDEX); - wg_push_i32(instruction_body, arg0); - wg_push_i32(instruction_body, arg1); - wg_push_i32(instruction_body, arg2); - wg_call_fn(instruction_body, fn_idx); -} - -void gen_safe_read32(void) -{ - // Assumes virtual address has been pushed to the stack, and generates safe_read32s' fast-path - // inline, bailing to safe_read32s_slow if necessary - - const int32_t address_local = GEN_LOCAL_SCRATCH0; - wg_tee_local(instruction_body, address_local); - - // Pseudo: base_on_stack = (uint32_t)address >> 12; - wg_push_i32(instruction_body, 12); - wg_shr_u32(instruction_body); - SCALE_INDEX_FOR_ARRAY32(tlb_data); - - // Pseudo: entry = tlb_data[base_on_stack]; - const int32_t entry_local = GEN_LOCAL_SCRATCH1; - wg_load_aligned_i32_from_stack(instruction_body, (uint32_t) tlb_data); - wg_tee_local(instruction_body, entry_local); - - // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && - // (address & 0xFFF) <= (0x1000 - 4)); - wg_push_i32(instruction_body, 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(*cpl == 3 ? 0 : TLB_NO_USER)); - wg_and_i32(instruction_body); - - wg_push_i32(instruction_body, TLB_VALID); - wg_eq_i32(instruction_body); - - wg_get_local(instruction_body, address_local); - wg_push_i32(instruction_body, 0xFFF); - wg_and_i32(instruction_body); - wg_push_i32(instruction_body, 0x1000 - 4); - wg_le_i32(instruction_body); - - wg_and_i32(instruction_body); - - // Pseudo: - // if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]); - wg_if_i32(instruction_body); - wg_get_local(instruction_body, entry_local); - wg_push_i32(instruction_body, ~0xFFF); - wg_and_i32(instruction_body); - wg_get_local(instruction_body, address_local); - wg_xor_i32(instruction_body); - - wg_load_unaligned_i32_from_stack(instruction_body, (uint32_t) mem8); - - // Pseudo: - // else { leave_on_stack(safe_read32s_slow(address)); } - wg_else(instruction_body); - wg_get_local(instruction_body, address_local); - gen_call_fn1_ret("safe_read32s_slow", 17); - wg_block_end(instruction_body); -} - -void gen_safe_write32(int32_t local_for_address, int32_t local_for_value) -{ - // Generates safe_write32' fast-path inline, bailing to safe_write32_slow if necessary. - - // local_for_{address,value} are the numbers of the local variables which contain the virtual - // address and value for safe_write32 - // Usage: - // set_local(0, value); - // set_local(1, v_addr); - // gen_safe_write32(); - - // Since this function clobbers other variables, we confirm that the caller uses the local - // variables we expect them to - assert(local_for_address == GEN_LOCAL_SCRATCH0); - assert(local_for_value == GEN_LOCAL_SCRATCH1); - - wg_get_local(instruction_body, local_for_address); - - // Pseudo: base_on_stack = (uint32_t)address >> 12; - wg_push_i32(instruction_body, 12); - wg_shr_u32(instruction_body); - SCALE_INDEX_FOR_ARRAY32(tlb_data); - - // entry_local is only used in the following block, so the scratch variable can be reused later - { - // Pseudo: entry = tlb_data[base_on_stack]; - const int32_t entry_local = GEN_LOCAL_SCRATCH2; - wg_load_aligned_i32_from_stack(instruction_body, (uint32_t) tlb_data); - wg_tee_local(instruction_body, entry_local); - - // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && - // (address & 0xFFF) <= (0x1000 - 4)); - wg_push_i32(instruction_body, 0xFFF & ~TLB_GLOBAL & ~(*cpl == 3 ? 0 : TLB_NO_USER)); - wg_and_i32(instruction_body); - - wg_push_i32(instruction_body, TLB_VALID); - wg_eq_i32(instruction_body); - - wg_get_local(instruction_body, local_for_address); - wg_push_i32(instruction_body, 0xFFF); - wg_and_i32(instruction_body); - wg_push_i32(instruction_body, 0x1000 - 4); - wg_le_i32(instruction_body); - - wg_and_i32(instruction_body); - - // Pseudo: - // if(can_use_fast_path) - // { - // phys_addr = entry & ~0xFFF ^ address; - wg_if_void(instruction_body); - - wg_get_local(instruction_body, entry_local); - wg_push_i32(instruction_body, ~0xFFF); - wg_and_i32(instruction_body); - wg_get_local(instruction_body, local_for_address); - wg_xor_i32(instruction_body); - } - - // entry_local isn't needed anymore, so we overwrite it - const int32_t phys_addr_local = GEN_LOCAL_SCRATCH2; - // Pseudo: - // /* continued within can_use_fast_path branch */ - // mem8[phys_addr] = value; - - wg_tee_local(instruction_body, phys_addr_local); - wg_get_local(instruction_body, local_for_value); - wg_store_unaligned_i32(instruction_body, (uint32_t) mem8); - - // Pseudo: - // else { safe_read32_slow(address, value); } - wg_else(instruction_body); - wg_get_local(instruction_body, local_for_address); - wg_get_local(instruction_body, local_for_value); - gen_call_fn2("safe_write32_slow", 17); - wg_block_end(instruction_body); -} - -#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 segment, int32_t reg16_idx_1, int32_t reg16_idx_2, int32_t imm) -{ - // generates: fn( ( reg1 + reg2 + imm ) & 0xFFFF ) - wg_load_aligned_u16(instruction_body, reg16_idx_1); - wg_load_aligned_u16(instruction_body, reg16_idx_2); - wg_add_i32(instruction_body); - - if(imm) - { - wg_push_i32(instruction_body, imm); - wg_add_i32(instruction_body); - } - - wg_push_i32(instruction_body, 0xFFFF); - wg_and_i32(instruction_body); - - jit_add_seg_offset(segment); -} - -static void gen_modrm_entry_1(int32_t segment, int32_t reg16_idx, int32_t imm) -{ - // generates: fn ( ( reg + imm ) & 0xFFFF ) - wg_load_aligned_u16(instruction_body, reg16_idx); - - if(imm) - { - wg_push_i32(instruction_body, imm); - wg_add_i32(instruction_body); - } - - wg_push_i32(instruction_body, 0xFFFF); - wg_and_i32(instruction_body); - - jit_add_seg_offset(segment); -} - -static bool can_optimize_get_seg(int32_t segment) -{ - return (segment == DS || segment == SS) && has_flat_segmentation(); -} - -/* - * Note: Requires an existing value to be on the WASM stack! Based on optimization possibilities, - * the value will be consumed and added to get_seg(segment), or it'll be left as-is - */ -static void jit_add_seg_offset(int32_t default_segment) -{ - int32_t prefix = *prefixes & PREFIX_MASK_SEGMENT; - int32_t seg = prefix ? prefix - 1 : default_segment; - - if(can_optimize_get_seg(seg) || prefix == SEG_PREFIX_ZERO) - { - return; - } - - wg_push_i32(instruction_body, seg); - wg_call_fn(instruction_body, fn_get_seg_idx); - wg_add_i32(instruction_body); -} - -static void gen_modrm_entry_2() -{ - wg_push_i32(instruction_body, read_imm16()); - jit_add_seg_offset(DS); -} - -static void jit_resolve_modrm16_(int32_t modrm_byte) -{ - 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, gen_modrm_entry_2()) - 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); - } -} - -#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 segment, int32_t reg32s_idx, int32_t imm) -{ - // generates: fn ( reg + imm ) - wg_load_aligned_i32(instruction_body, reg32s_idx); - - if(imm) - { - wg_push_i32(instruction_body, imm); - wg_add_i32(instruction_body); - } - - jit_add_seg_offset(segment); -} - -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 - if(base_is_mem_access) - { - wg_load_aligned_i32(instruction_body, base_addr); - } - else - { - wg_push_i32(instruction_body, base); - } - - jit_add_seg_offset(seg); - - // 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; - - wg_load_aligned_i32(instruction_body, (int32_t)(reg32s + m)); - wg_push_i32(instruction_body, s); - wg_shl_i32(instruction_body); - - wg_add_i32(instruction_body); -} - -static void modrm32_special_case_1(void) -{ - jit_resolve_sib(true); - - int32_t imm = read_imm8s(); - - if(imm) - { - wg_push_i32(instruction_body, imm); - wg_add_i32(instruction_body); - } -} - -static void modrm32_special_case_2(void) -{ - jit_resolve_sib(true); - - int32_t imm = read_imm32s(); - - if(imm) - { - wg_push_i32(instruction_body, imm); - wg_add_i32(instruction_body); - } -} - -static void gen_modrm32_entry_1() -{ - int32_t imm = read_imm32s(); - - wg_push_i32(instruction_body, imm); - jit_add_seg_offset(DS); -} - -static void jit_resolve_modrm32_(int32_t modrm_byte) -{ - 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, gen_modrm32_entry_1()) - 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); - } -} - -#undef MODRM_ENTRY - -// This function leaves a value on the wasm stack, to be consumed by one of the -// gen_modrm_fn* functions below -void gen_modrm_resolve(int32_t modrm_byte) -{ - if(is_asize_32()) - { - jit_resolve_modrm32_(modrm_byte); - } - else - { - jit_resolve_modrm16_(modrm_byte); - } -} - -void gen_modrm_fn2(char const* fn, uint8_t fn_len, int32_t arg0, int32_t arg1) -{ - // generates: fn( _, arg0, arg1 ) - - wg_push_i32(instruction_body, arg0); - wg_push_i32(instruction_body, arg1); - - int32_t fn_idx = get_fn_idx(fn, fn_len, FN3_TYPE_INDEX); - wg_call_fn(instruction_body, fn_idx); -} - -void gen_modrm_fn1(char const* fn, uint8_t fn_len, int32_t arg0) -{ - // generates: fn( _, arg0 ) - - wg_push_i32(instruction_body, arg0); - - int32_t fn_idx = get_fn_idx(fn, fn_len, FN2_TYPE_INDEX); - wg_call_fn(instruction_body, fn_idx); -} - -void gen_modrm_fn0(char const* fn, uint8_t fn_len) -{ - // generates: fn( _ ) - - int32_t fn_idx = get_fn_idx(fn, fn_len, FN1_TYPE_INDEX); - wg_call_fn(instruction_body, fn_idx); -} - diff --git a/src/native/codegen/codegen.h b/src/native/codegen/codegen.h deleted file mode 100644 index ecba9a66..00000000 --- a/src/native/codegen/codegen.h +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once - -#include - -#include "wasmgen.h" - -#define FN0_TYPE_INDEX 0 -#define FN1_TYPE_INDEX 1 -#define FN2_TYPE_INDEX 2 -#define FN3_TYPE_INDEX 3 - -#define FN0_RET_TYPE_INDEX 4 -#define FN1_RET_TYPE_INDEX 5 -#define FN2_RET_TYPE_INDEX 6 - -#define NR_FN_TYPE_INDEXES 7 - -// We'll need to scale the index on the stack to access arr32[i] correctly, for eg. -// &array32[i]'s byte address is "array32 + i*4" -// This macro simply does the "i*4" part of the address calculation -#define SCALE_INDEX_FOR_ARRAY32(array) \ - _Static_assert( \ - sizeof((array)[0]) == 4, \ - "codegen: Elements assumed to be 4 bytes." \ - ); \ - /* Shift the index to make it byte-indexed, not array-indexed */ \ - wg_push_i32(instruction_body, 2); \ - wg_shl_i32(instruction_body); - -uint8_t* cs; -uint8_t* instruction_body; - -static uint16_t const fn_get_seg_idx = 0; - -void gen_reset(void); -// uintptr_t gen_finish(int32_t no_of_locals_i32); -void add_get_seg_import(void); - -uint16_t get_fn_idx(char const* fn, uint8_t fn_len, uint8_t fn_type); - -// Generate function call with constant arguments -void gen_fn0_const(char const* fn, uint8_t fn_len); -void gen_fn1_const(char const* fn, uint8_t fn_len, int32_t arg0); -void gen_fn2_const(char const* fn, uint8_t fn_len, int32_t arg0, int32_t arg1); -void gen_fn3_const(char const* fn, uint8_t fn_len, int32_t arg0, int32_t arg1, int32_t arg2); - -void gen_fn0_const_ret(char const* fn, uint8_t fn_len); -void gen_fn1_const_ret(char const* fn, uint8_t fn_len, int32_t arg0); - -// Generate code to set register value to result of function call -void gen_set_reg16_fn0(char const* fn, uint8_t fn_len, int32_t reg); -void gen_set_reg32s_fn0(char const* fn, uint8_t fn_len, int32_t reg); - -// Generate code for "mov reg, reg" -void gen_set_reg16_r(int32_t r_dest, int32_t r_src); -void gen_set_reg32_r(int32_t r_dest, int32_t r_src); - -// Generate function call with register value as argument (reg is index of register) -void gen_fn1_reg16(char const* fn, uint8_t fn_len, int32_t reg); -void gen_fn1_reg32s(char const* fn, uint8_t fn_len, int32_t reg); - -// Generate a function call with arguments pushed to the stack separately -void gen_call_fn1_ret(char const* fn, uint8_t fn_len); -void gen_call_fn1(char const* fn, uint8_t fn_len); -void gen_call_fn2(char const* fn, uint8_t fn_len); - -// Generate code for safe_read32s and safe_write32 inline -void gen_safe_read32(void); -void gen_safe_write32(int32_t local_for_address, int32_t local_for_value); - -void gen_modrm_resolve(int32_t modrm_byte); -void gen_modrm_fn0(char const* fn, uint8_t fn_len); -void gen_modrm_fn1(char const* fn, uint8_t fn_len, int32_t arg0); -void gen_modrm_fn2(char const* fn, uint8_t fn_len, int32_t arg0, int32_t arg1); - -void gen_increment_mem32(int32_t addr); - -void gen_relative_jump(int32_t n); - -void gen_set_previous_eip_offset_from_eip(int32_t n); -void gen_set_previous_eip(void); -void gen_increment_instruction_pointer(int32_t); - -void gen_increment_timestamp_counter(uint32_t); - -void gen_clear_prefixes(void); -void gen_add_prefix_bits(int32_t); diff --git a/src/native/codegen/wasmgen.h b/src/native/codegen/wasmgen.h deleted file mode 100644 index 0191b5f0..00000000 --- a/src/native/codegen/wasmgen.h +++ /dev/null @@ -1,74 +0,0 @@ -#pragma once - -#include - -typedef struct PackedStr { - uint64_t a; - uint64_t b; - uint64_t c; -} PackedStr; - -#define PSTR_TY uint64_t, uint64_t, uint64_t - -extern uint8_t* wg_get_code_section(void); -extern uint8_t* wg_get_instruction_body(void); -extern void wg_commit_instruction_body_to_cs(void); -extern void wg_finish(uint8_t no_of_locals_i32); -extern void wg_reset(void); -extern uint16_t wg_get_fn_idx(PSTR_TY, uint8_t fn_type); - -extern void wg_push_i32(uint8_t* buf, int32_t v); -extern void wg_push_u32(uint8_t* buf, uint32_t v); -extern void wg_load_aligned_u16(uint8_t* buf, uint32_t addr); -extern void wg_load_aligned_i32(uint8_t* buf, uint32_t addr); -extern void wg_store_aligned_u16(uint8_t* buf); -extern void wg_store_aligned_i32(uint8_t* buf); -extern void wg_add_i32(uint8_t* buf); -extern void wg_and_i32(uint8_t* buf); -extern void wg_or_i32(uint8_t* buf); -extern void wg_shl_i32(uint8_t* buf); -extern void wg_call_fn(uint8_t* buf, uint16_t fn_idx); -extern void wg_call_fn_with_arg(uint8_t* buf, uint16_t fn_idx, int32_t arg0); -extern void wg_eq_i32(uint8_t* buf); -extern void wg_ne_i32(uint8_t* buf); -extern void wg_le_i32(uint8_t* buf); -extern void wg_lt_i32(uint8_t* buf); -extern void wg_ge_i32(uint8_t* buf); -extern void wg_gt_i32(uint8_t* buf); -extern void wg_if_i32(uint8_t* buf); -extern void wg_block_i32(uint8_t* buf); -extern void wg_tee_local(uint8_t* buf, int32_t idx); -extern void wg_xor_i32(uint8_t* buf); -extern void wg_load_unaligned_i32_from_stack(uint8_t* buf, uint32_t byte_offset); -extern void wg_load_aligned_i32_from_stack(uint8_t* buf, uint32_t byte_offset); -extern void wg_store_unaligned_i32(uint8_t* buf, uint32_t byte_offset); -extern void wg_shr_u32(uint8_t* buf); -extern void wg_shr_i32(uint8_t* buf); -extern void wg_eqz_i32(uint8_t* buf); -extern void wg_if_void(uint8_t* buf); -extern void wg_else(uint8_t* buf); -extern void wg_loop_void(uint8_t* buf); -extern void wg_block_void(uint8_t* buf); -extern void wg_block_end(uint8_t* buf); -extern void wg_return(uint8_t* buf); -extern void wg_drop(uint8_t* buf); -extern void wg_brtable_and_cases(uint8_t* buf, int32_t cases_count); -extern void wg_br(uint8_t* buf, int32_t depth); -extern void wg_get_local(uint8_t* buf, int32_t idx); -extern void wg_set_local(uint8_t* buf, int32_t idx); -extern void wg_unreachable(uint8_t* buf); -extern void wg_increment_mem32(uint8_t* buf, int32_t addr); -extern void wg_increment_variable(uint8_t* buf, int32_t addr, int32_t n); -extern void wg_load_aligned_u16_from_stack(uint8_t* buf, uint32_t byte_offset); - -extern void wg_fn0_const(uint8_t* buf, PSTR_TY); -extern void wg_fn0_const_ret(uint8_t* buf, PSTR_TY); -extern void wg_fn1_const(uint8_t* buf, PSTR_TY, int32_t arg0); -extern void wg_fn1_const_ret(uint8_t* buf, PSTR_TY, int32_t arg0); -extern void wg_fn2_const(uint8_t* buf, PSTR_TY, int32_t arg0, int32_t arg1); -extern void wg_fn3_const(uint8_t* buf, PSTR_TY, int32_t arg0, int32_t arg1, int32_t arg2); -extern void wg_call_fn1_ret(uint8_t* buf, PSTR_TY); -extern void wg_call_fn2(uint8_t* buf, PSTR_TY); - -#undef PSTR_TY - diff --git a/src/native/config.h b/src/native/config.h index 6603c69f..014af9fc 100644 --- a/src/native/config.h +++ b/src/native/config.h @@ -16,26 +16,9 @@ #define USE_A20 false -// Mask used to map physical address to index in cache array -#define JIT_CACHE_ARRAY_SIZE 0x40000 -#define JIT_CACHE_ARRAY_MASK (JIT_CACHE_ARRAY_SIZE - 1) - -#define HASH_PRIME 6151 - -#define JIT_THRESHOLD 2500 - -#define CHECK_JIT_CACHE_ARRAY_INVARIANTS 0 #define CHECK_TLB_INVARIANTS 0 -#define JIT_MAX_ITERATIONS_PER_FUNCTION 10000 - #define ENABLE_JIT 1 -#define ENABLE_JIT_NONFAULTING_OPTIMZATION 1 -#define JIT_ALWAYS_USE_LOOP_SAFETY 0 - -#ifndef ENABLE_JIT_ALWAYS -#define ENABLE_JIT_ALWAYS 0 -#endif #define ENABLE_PROFILER 0 #define ENABLE_PROFILER_OPSTATS 0 diff --git a/src/native/const.h b/src/native/const.h index 4e7a601c..6bae9819 100644 --- a/src/native/const.h +++ b/src/native/const.h @@ -151,7 +151,3 @@ #define A20_MASK32 (~(1 << (20 - 2))) #define MXCSR_MASK (0xFFFF & ~(1 << 6)) - -#define WASM_TABLE_SIZE 0x10000 -#define DIRTY_ARR_SHIFT 12 -#define GROUP_DIRTINESS_LENGTH (1 << (32 - DIRTY_ARR_SHIFT)) diff --git a/src/native/cpu.c b/src/native/cpu.c index 32280df1..acb07ed6 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -4,115 +4,30 @@ #include #include -#include "codegen/codegen.h" -#include "codegen/wasmgen.h" #include "const.h" #include "cpu.h" #include "global_pointers.h" #include "instructions.h" -#include "jit.h" #include "js_imports.h" #include "log.h" #include "memory.h" #include "misc_instr.h" #include "modrm.h" -#include "profiler/opstats.h" #include "profiler/profiler.h" +#include "rust_imports.h" #include "shared.h" -// TODO: Use sparse structure -uint16_t page_entry_points[MAX_PHYSICAL_PAGES][MAX_ENTRIES_PER_PAGE] = { { 0 } }; - #if DEBUG bool must_not_fault = false; #endif -struct code_cache jit_cache_arr[JIT_CACHE_ARRAY_SIZE] = { - { - .start_addr = 0, -#if DEBUG - .end_addr = 0, - .opcode = {0}, - .len = 0, -#endif - .next_index_same_page = 0, - - .wasm_table_index = 0, - .initial_state = 0, - .state_flags = 0, - .pending = false, - } -}; - uint64_t tsc_offset = 0; uint32_t jit_block_boundary = 0; -int32_t hot_code_addresses[HASH_PRIME] = {0}; - -// indices to the wasm table that can be used -uint16_t wasm_table_index_free_list[WASM_TABLE_SIZE] = { 0 }; -int32_t wasm_table_index_free_list_count = 0; - -// indices to the wasm table that can be used but the compilation is still pending -// will be moved to the above table by codegen_finalize_finished -uint16_t wasm_table_index_pending_free[WASM_TABLE_SIZE] = { 0 }; -int32_t wasm_table_index_pending_free_count = 0; int32_t valid_tlb_entries[VALID_TLB_ENTRY_MAX] = {0}; int32_t valid_tlb_entries_count = 0; -static bool is_near_end_of_page(uint32_t addr); - -void record_page_entry(uint32_t phys_addr) -{ - if(is_near_end_of_page(phys_addr)) - { - return; - } - - uint32_t page = phys_addr >> 12; - - assert(page < MAX_PHYSICAL_PAGES); - uint16_t* entry_points = page_entry_points[page]; - - uint16_t entry_point = phys_addr & 0xFFF; - assert(entry_point != ENTRY_POINT_END); - - bool did_insert_or_find = false; - - if(entry_points[0] == ENTRY_POINT_END) - { - // first entry in this page - tlb_set_has_code(page, true); - } - - for(int32_t i = 0; i < MAX_ENTRIES_PER_PAGE; i++) - { - if(entry_points[i] == ENTRY_POINT_END) - { - entry_points[i] = entry_point; - did_insert_or_find = true; - break; - } - else if(entry_points[i] == entry_point) - { - did_insert_or_find = true; - break; - } - } - - if(!did_insert_or_find) - { - // page entry list full :( - //assert(false); - } -} - -int32_t get_wasm_table_index_free_list_count(void) -{ - return wasm_table_index_free_list_count; -} - void after_block_boundary() { jit_block_boundary = true; @@ -372,10 +287,7 @@ int32_t do_page_translation(int32_t addr, bool for_writing, bool user) bool is_in_mapped_range = in_mapped_range(high); int32_t physical_page = (uint32_t)high >> 12; - bool has_code = !is_in_mapped_range && ( - page_first_jit_cache_entry[physical_page] != JIT_CACHE_ARRAY_NO_NEXT_ENTRY || - page_entry_points[physical_page][0] != ENTRY_POINT_END - ); + bool has_code = !is_in_mapped_range && jit_page_has_code(physical_page); int32_t info_bits = TLB_VALID | @@ -410,6 +322,38 @@ void tlb_set_has_code(uint32_t physical_page, bool has_code) } } } + + check_tlb_invariants(); +} + +void check_tlb_invariants(void) +{ +#if CHECK_TLB_INVARIANTS + for(int32_t i = 0; i < valid_tlb_entries_count; i++) + { + int32_t page = valid_tlb_entries[i]; + int32_t entry = tlb_data[page]; + + if(!entry || (entry & TLB_IN_MAPPED_RANGE)) // there's no code in mapped memory + { + continue; + } + + uint32_t physical_page = (uint32_t)entry >> 12 ^ page; + dbg_assert(!in_mapped_range(physical_page << 12)); + + bool entry_has_code = entry & TLB_HAS_CODE; + bool has_code = jit_page_has_code(physical_page); + + // If some code has been created in a page, the corresponding tlb entries must be marked + dbg_assert(!has_code || entry_has_code); + + // If a tlb entry is marked to have code, the physical page should + // contain code (the converse is not a bug, but indicates a cleanup + // problem when clearing code from a page) + dbg_assert(!entry_has_code || has_code); + } +#endif } int32_t get_valid_tlb_entries_count(void) @@ -655,19 +599,6 @@ int32_t modrm_resolve(int32_t modrm_byte) } } -void modrm_skip(int32_t modrm_byte) -{ - // TODO: More efficient implementation is possible - *prefixes |= SEG_PREFIX_ZERO; - modrm_resolve(modrm_byte); - *prefixes &= ~SEG_PREFIX_ZERO; -} - -uint32_t jit_hot_hash_page(uint32_t page) -{ - return page % HASH_PRIME; -} - static void jit_run_interpreted(int32_t phys_addr) { profiler_stat_increment(S_RUN_INTERPRETED); @@ -701,1141 +632,16 @@ bool has_flat_segmentation(void) return segment_offsets[SS] == 0 && !segment_is_null[DS] && segment_offsets[DS] == 0; } -static cached_state_flags pack_current_state_flags() +cached_state_flags pack_current_state_flags() { return *is_32 << 0 | *stack_size_32 << 1 | (*cpl == 3) << 2 | has_flat_segmentation() << 3; } -void check_jit_cache_array_invariants(void) -{ -#if CHECK_JIT_CACHE_ARRAY_INVARIANTS - int32_t wasm_table_index_to_jit_cache_index[WASM_TABLE_SIZE] = { 0 }; - - // there are no loops in the linked lists - // https://en.wikipedia.org/wiki/Cycle_detection#Floyd's_Tortoise_and_Hare - for(int32_t i = 0; i < GROUP_DIRTINESS_LENGTH; i++) - { - int32_t slow = page_first_jit_cache_entry[i]; - int32_t fast = page_first_jit_cache_entry[i]; - - while(fast != JIT_CACHE_ARRAY_NO_NEXT_ENTRY) - { - slow = jit_cache_arr[slow].next_index_same_page; - fast = jit_cache_arr[fast].next_index_same_page; - - if(fast == JIT_CACHE_ARRAY_NO_NEXT_ENTRY) - { - break; - } - - fast = jit_cache_arr[fast].next_index_same_page; - - assert(slow != fast); - } - } - - for(int32_t i = 0; i < JIT_CACHE_ARRAY_SIZE; i++) - { - struct code_cache* entry = &jit_cache_arr[i]; - - assert(entry->next_index_same_page == JIT_CACHE_ARRAY_NO_NEXT_ENTRY || - entry->next_index_same_page >= 0 && entry->next_index_same_page < JIT_CACHE_ARRAY_SIZE); - - if(entry->pending) - { - assert(entry->start_addr); - assert(entry->wasm_table_index); - } - else - { - // an invalid entry has both its start_addr and wasm_table_index set to 0 - // neither start_addr nor wasm_table_index are 0 for any valid entry - - assert((entry->start_addr == 0) == (entry->wasm_table_index == 0)); - } - - // having a next entry implies validity - assert(entry->next_index_same_page == JIT_CACHE_ARRAY_NO_NEXT_ENTRY || entry->start_addr); - - // any valid wasm_table_index can only be used within a single page - if(entry->wasm_table_index) - { - int32_t j = wasm_table_index_to_jit_cache_index[entry->wasm_table_index]; - - if(j) - { - struct code_cache* other_entry = &jit_cache_arr[j]; - assert(other_entry->wasm_table_index == entry->wasm_table_index); - assert(same_page(other_entry->start_addr, entry->start_addr)); - } - else - { - wasm_table_index_to_jit_cache_index[entry->wasm_table_index] = i; - } - } - - if(entry->start_addr) - { - // valid entries can be reached from page_first_jit_cache_entry - bool reached = false; - - uint32_t index = entry->start_addr >> DIRTY_ARR_SHIFT; - int32_t cache_array_index = page_first_jit_cache_entry[index]; - - while(cache_array_index != JIT_CACHE_ARRAY_NO_NEXT_ENTRY) - { - struct code_cache* other_entry = &jit_cache_arr[cache_array_index]; - - if(entry == other_entry) - { - reached = true; - break; - } - - cache_array_index = other_entry->next_index_same_page; - } - - assert(reached); - } - } - - for(int32_t i = 0; i < valid_tlb_entries_count; i++) - { - int32_t page = valid_tlb_entries[i]; - int32_t entry = tlb_data[page]; - - if(!entry || (entry & TLB_IN_MAPPED_RANGE)) // there's no code in mapped memory - { - continue; - } - - int32_t physical_page = (uint32_t)entry >> 12 ^ page; - assert(!in_mapped_range(physical_page << 12)); - - bool entry_has_code = entry & TLB_HAS_CODE; - bool has_code = - page_first_jit_cache_entry[physical_page] != JIT_CACHE_ARRAY_NO_NEXT_ENTRY || - page_entry_points[physical_page][0] != ENTRY_POINT_END; - - // If some code has been created in a page, the corresponding tlb entries must be marked - assert(!has_code || entry_has_code); - - // If a tlb entry is marked to have code, the physical page should - // contain code (the converse is not a bug, but indicates a cleanup - // problem when clearing code from a page) - assert(!entry_has_code || has_code); - } -#endif -} - -static struct code_cache* create_cache_entry(uint32_t phys_addr, uint16_t wasm_table_index) -{ - int32_t found_entry_index = -1; - - for(int32_t i = 0; i < CODE_CACHE_SEARCH_SIZE; i++) - { - int32_t addr_index = (phys_addr + i) & JIT_CACHE_ARRAY_MASK; - struct code_cache* entry = &jit_cache_arr[addr_index]; - - if(!entry->start_addr) - { - if(i > 0) - { - dbg_log("Inserted cache entry at %d for addr %x | 0=%x", i, - phys_addr, jit_cache_arr[addr_index - 1].start_addr); - } - - found_entry_index = addr_index; - break; - } - } - - if(found_entry_index == -1) - { - profiler_stat_increment(S_CACHE_MISMATCH); - - // no free slots, overwrite the first one - found_entry_index = phys_addr & JIT_CACHE_ARRAY_MASK; - - struct code_cache* entry = &jit_cache_arr[found_entry_index]; - - // if we're here, we expect to overwrite a valid index - assert(entry->start_addr); - assert(entry->wasm_table_index); - - if(entry->wasm_table_index == wasm_table_index) - { - assert(entry->pending); - assert(same_page(entry->start_addr, phys_addr)); - - // The entry belongs to the same wasm table index as this entry. - // *Don't* free the wasm table index, instead just delete the entry - // and use its slot for this entry. - // TODO: Optimally, we should pick another slot instead of dropping - // an entry has just been created. - uint32_t old_page = entry->start_addr >> DIRTY_ARR_SHIFT; - remove_jit_cache_entry(old_page, found_entry_index); - - assert(entry->next_index_same_page == JIT_CACHE_ARRAY_NO_NEXT_ENTRY); - entry->pending = false; - entry->start_addr = 0; - } - else - { - uint16_t old_wasm_table_index = entry->wasm_table_index; - uint32_t old_page = entry->start_addr >> DIRTY_ARR_SHIFT; - - remove_jit_cache_wasm_index(old_page, old_wasm_table_index); - - check_jit_cache_array_invariants(); - - // entry should be removed after calling remove_jit_cache_wasm_index - - assert(!entry->pending); - assert(!entry->start_addr); - assert(!entry->wasm_table_index); - assert(entry->next_index_same_page == JIT_CACHE_ARRAY_NO_NEXT_ENTRY); - } - } - - uint32_t page = phys_addr >> DIRTY_ARR_SHIFT; - int32_t previous_entry_index = page_first_jit_cache_entry[page]; - - if(previous_entry_index != JIT_CACHE_ARRAY_NO_NEXT_ENTRY) - { - struct code_cache* previous_entry = &jit_cache_arr[previous_entry_index]; - - if(previous_entry->start_addr) - { - assert(same_page(previous_entry->start_addr, phys_addr)); - } - } - - page_first_jit_cache_entry[page] = found_entry_index; - struct code_cache* entry = &jit_cache_arr[found_entry_index]; - entry->next_index_same_page = previous_entry_index; - - return entry; -} - -static bool is_near_end_of_page(uint32_t addr) -{ - return (addr & 0xFFF) >= (0x1000 - 16); -} - bool same_page(int32_t addr1, int32_t addr2) { return (addr1 & ~0xFFF) == (addr2 & ~0xFFF); } -static void jit_generate_basic_block(int32_t start_addr, int32_t stop_addr) -{ - uint32_t len = 0; - - int32_t end_addr; - bool was_block_boundary = false; - int32_t eip_delta = 0; - - *instruction_pointer = start_addr; - - // First iteration of do-while assumes the caller confirms this condition - assert(!is_near_end_of_page(start_addr)); - - do - { -#if ENABLE_PROFILER_OPSTATS - gen_opstats(safe_read32s(*instruction_pointer)); -#endif - int32_t opcode = read_imm8(); - - int32_t start_eip = *instruction_pointer - 1; - jit_instr_flags jit_ret = jit_instruction(opcode | !!*is_32 << 8); - int32_t end_eip = *instruction_pointer; - - int32_t instruction_length = end_eip - start_eip; - // XXX: There may be more instructions that form a block boundary than just jumps, but the - // granularity isn't very important since jumps are the majority - was_block_boundary = (jit_ret & JIT_INSTR_BLOCK_BOUNDARY_FLAG) != 0; - - assert(instruction_length >= 0 && instruction_length < 16); - -#if ENABLE_JIT_NONFAULTING_OPTIMZATION - /* - * There are a few conditions to keep in mind to optimize the update of previous_ip and - * instruction_pointer: - * - previous_ip MUST be updated just before a faulting instruction - * - instruction_pointer MUST be updated before jump instructions (since they use the EIP - * value for instruction logic) - * - Nonfaulting instructions don't need either to be updated - */ - if(was_block_boundary) - { - // prev_ip = eip + eip_delta, so that previous_ip points to the start of this instruction - gen_set_previous_eip_offset_from_eip(eip_delta); - - // eip += eip_delta + len(jump) so instruction logic uses the correct eip - gen_increment_instruction_pointer(eip_delta + instruction_length); - wg_commit_instruction_body_to_cs(); - - eip_delta = 0; - } - else if((jit_ret & JIT_INSTR_NONFAULTING_FLAG) == 0) - { - // Faulting instruction - - // prev_ip = eip + eip_delta, so that previous_ip points to the start of this instruction - gen_set_previous_eip_offset_from_eip(eip_delta); - wg_commit_instruction_body_to_cs(); - - // Leave this instruction's length to be updated in the next batch, whatever it may be - eip_delta += instruction_length; - } - else - { - // Non-faulting, so we skip setting previous_ip and simply queue the instruction length - // for whenever eip is updated next - profiler_stat_increment(S_NONFAULTING_OPTIMIZATION); - eip_delta += instruction_length; - } -#else - UNUSED(eip_delta); - gen_set_previous_eip(); - gen_increment_instruction_pointer(instruction_length); - wg_commit_instruction_body_to_cs(); -#endif - end_addr = *instruction_pointer; - len++; - } - while(!was_block_boundary && - !is_near_end_of_page(*instruction_pointer) && - *instruction_pointer < stop_addr); - - if(*instruction_pointer != stop_addr) - { - // Overlapping basic blocks: This can happen as we only track basic - // blocks, not individual instructions, and basic blocks sometimes need - // to be split. - // Happens for example when a jump is performed into the middle of an instruction - dbg_log("Overlapping basic blocks: start %x eip %x stop %x", - start_addr, *instruction_pointer, stop_addr); - } - -#if ENABLE_JIT_NONFAULTING_OPTIMZATION - // When the block ends in a non-jump instruction, we may have uncommitted updates still - if(eip_delta > 0) - { - wg_commit_instruction_body_to_cs(); - gen_increment_instruction_pointer(eip_delta); - } -#endif - - gen_increment_timestamp_counter(len); - - // no page was crossed - assert(same_page(end_addr, start_addr)); - - assert(*prefixes == 0); -} - -void codegen_finalize_finished( - int32_t wasm_table_index, uint32_t phys_addr, uint32_t end_addr, - int32_t first_opcode, cached_state_flags state_flags) -{ - assert(wasm_table_index); - - bool was_already_invalid = false; - - for(int32_t i = 0; i < wasm_table_index_pending_free_count; i++) - { - uint16_t index = wasm_table_index_pending_free[i]; - - if(index == wasm_table_index) - { - if(i == wasm_table_index_pending_free_count - 1) - { - wasm_table_index_pending_free_count--; - wasm_table_index_pending_free[wasm_table_index_pending_free_count] = 0; - } - else - { - wasm_table_index_pending_free_count--; - wasm_table_index_pending_free[i] = - wasm_table_index_pending_free[wasm_table_index_pending_free_count]; - wasm_table_index_pending_free[wasm_table_index_pending_free_count] = 0; - } - - was_already_invalid = true; - free_wasm_table_index(wasm_table_index); - break; - } - } - - if(!was_already_invalid) - { - uint32_t index = phys_addr >> DIRTY_ARR_SHIFT; - int32_t cache_array_index = page_first_jit_cache_entry[index]; - - while(cache_array_index != JIT_CACHE_ARRAY_NO_NEXT_ENTRY) - { - struct code_cache* entry = &jit_cache_arr[cache_array_index]; - - if(entry->wasm_table_index == wasm_table_index) - { - assert(entry->pending); - entry->pending = false; - } - - cache_array_index = entry->next_index_same_page; - } - } - - check_jit_cache_array_invariants(); - -#if CHECK_JIT_CACHE_ARRAY_INVARIANTS - // sanity check that the above iteration marked all entries as not pending - - for(int32_t i = 0; i < JIT_CACHE_ARRAY_SIZE; i++) - { - struct code_cache* entry = &jit_cache_arr[i]; - - if(entry->wasm_table_index == wasm_table_index) - { - assert(!entry->pending); - } - } -#endif - -#if 0 - // XXX: May end up in this branch when entry is overwritten due to full - // cache, causing the assertions below to fail - - // sanity check that we're looking at the right entry - assert(entry->start_addr == phys_addr); - assert(entry->state_flags == state_flags); -#endif - UNUSED(phys_addr); - UNUSED(state_flags); - UNUSED(end_addr); - UNUSED(first_opcode); -} - -static struct code_cache* find_cache_entry(uint32_t phys_addr) -{ - cached_state_flags state_flags = pack_current_state_flags(); - -#pragma clang loop unroll_count(CODE_CACHE_SEARCH_SIZE) - for(int32_t i = 0; i < CODE_CACHE_SEARCH_SIZE; i++) - { - int32_t addr_index = (phys_addr + i) & JIT_CACHE_ARRAY_MASK; - struct code_cache* entry = &jit_cache_arr[addr_index]; - - if(entry->start_addr == phys_addr && entry->state_flags == state_flags) - { - return entry; - } - } - - return NULL; -} - -void jit_link_block_conditional(int32_t offset, const char* condition) -{ - // Note: block linking cannot rely on the absolute value of eip, as blocks - // are stored at their *physical* address, which can be executed from - // multiple *virtual* addresses. Due to this, we cannot insert the value of - // eip into generated code - - // This is currently unused, the jump is generated in after analysis - UNUSED(offset); - UNUSED(condition); -} - -struct analysis analyze_prefix_instruction() -{ - return analyze_step(read_imm8() | is_osize_32() << 8); -} - -struct analysis instr_26_analyze() { return analyze_prefix_instruction(); } -struct analysis instr_2E_analyze() { return analyze_prefix_instruction(); } -struct analysis instr_36_analyze() { return analyze_prefix_instruction(); } -struct analysis instr_3E_analyze() { return analyze_prefix_instruction(); } -struct analysis instr_64_analyze() { return analyze_prefix_instruction(); } -struct analysis instr_65_analyze() { return analyze_prefix_instruction(); } -struct analysis instr_66_analyze() { - *prefixes |= PREFIX_MASK_OPSIZE; - struct analysis result = analyze_prefix_instruction(); - *prefixes = 0; - return result; -} -struct analysis instr_67_analyze() { - *prefixes |= PREFIX_MASK_ADDRSIZE; - struct analysis result = analyze_prefix_instruction(); - *prefixes = 0; - return result; -} -struct analysis instr_F0_analyze() { return analyze_prefix_instruction(); } -struct analysis instr_F2_analyze() { - *prefixes |= PREFIX_F2; - struct analysis result = analyze_prefix_instruction(); - *prefixes = 0; - return result; -} -struct analysis instr_F3_analyze() { - *prefixes |= PREFIX_F3; - struct analysis result = analyze_prefix_instruction(); - *prefixes = 0; - return result; -} - -struct analysis instr16_0F_analyze() -{ - int32_t opcode = read_imm8(); - struct analysis analysis = { .flags = 0, .jump_offset = 0, .condition_index = -1 }; -#include "../../build/analyzer0f_16.c" - return analysis; -} -struct analysis instr32_0F_analyze() -{ - int32_t opcode = read_imm8(); - struct analysis analysis = { .flags = 0, .jump_offset = 0, .condition_index = -1 }; -#include "../../build/analyzer0f_32.c" - return analysis; -} - -struct analysis analyze_step(int32_t opcode) -{ - struct analysis analysis = { .flags = 0, .jump_offset = 0, .condition_index = -1 }; -#include "../../build/analyzer.c" - return analysis; -} - -int32_t find_basic_block_index(const struct basic_block_list* basic_blocks, int32_t addr) -{ - for(int32_t i = 0; i < basic_blocks->length; i++) - { - if(basic_blocks->blocks[i].addr == addr) - { - return i; - } - } - - return -1; -} - -bool is_sorted_and_unique(const struct basic_block_list* basic_blocks) -{ - for(int32_t i = 0; i < basic_blocks->length - 1; i++) - { - if(basic_blocks->blocks[i].addr >= basic_blocks->blocks[i + 1].addr) - { - return false; - } - } - - return true; -} - -struct basic_block* add_basic_block_start(struct basic_block_list* basic_blocks, int32_t addr) -{ - assert(basic_blocks->length < BASIC_BLOCK_LIST_MAX); - assert(find_basic_block_index(basic_blocks, addr) == -1); - - // sorted insert - int32_t index_to_insert = -1; - - for(int32_t i = 0; i < basic_blocks->length; i++) - { - assert(basic_blocks->blocks[i].addr != addr); - - if(basic_blocks->blocks[i].addr > addr) - { - // make space - for(int32_t j = basic_blocks->length - 1; j >= i; j--) - { - basic_blocks->blocks[j + 1] = basic_blocks->blocks[j]; - } - - assert(basic_blocks->blocks[i].addr == basic_blocks->blocks[i + 1].addr); - - index_to_insert = i; - break; - } - } - - if(index_to_insert == -1) - { - // if we're here addr is larger than all existing basic blocks or basic blocks is empty - assert(basic_blocks->length == 0 || - basic_blocks->blocks[basic_blocks->length - 1].addr < addr); - - index_to_insert = basic_blocks->length; - } - - basic_blocks->blocks[index_to_insert].addr = addr; - basic_blocks->length++; - - assert(is_sorted_and_unique(basic_blocks)); - - if(index_to_insert != 0) - { - struct basic_block* previous_block = &basic_blocks->blocks[index_to_insert - 1]; - - if(previous_block->end_addr > addr) - { - // Split the previous block as it would overlap otherwise; change - // it to continue at this block - - // XXX: May do invalid split here. For example, a jump into the middle of an instruction - // jit_generate_basic_block handles this correctly - previous_block->end_addr = addr; - previous_block->next_block_addr = addr; - previous_block->condition_index = -1; - previous_block->next_block_branch_taken_addr = 0; - } - } - - return &basic_blocks->blocks[index_to_insert]; -} - -static const char* condition_functions[] = { - "test_o", - "test_no", - "test_b", - "test_nb", - "test_z", - "test_nz", - "test_be", - "test_nbe", - "test_s", - "test_ns", - "test_p", - "test_np", - "test_l", - "test_nl", - "test_le", - "test_nle", -}; - -struct basic_block_list basic_blocks = { - .length = 0, - .blocks = { - { - .addr = 0, - .end_addr = 0, - .next_block_addr = 0, - .next_block_branch_taken_addr = 0, - .condition_index = 0, - .jump_offset_is_32 = false, - .is_entry_block = false, - } - } -}; - -// temporary variables used only by jit_find_basic_blocks -int32_t to_visit_stack[1000]; -int32_t marked_as_entry[1000]; - -// populates the basic_blocks global variable -static bool jit_find_basic_blocks(uint32_t phys_addr, bool* requires_loop_limit) -{ - *requires_loop_limit = false; - basic_blocks.length = 0; - - // keep a stack of locations to visit that are part of the current control flow - - int32_t to_visit_stack_count = 0; - int32_t marked_as_entry_count = 0; - - uint32_t page = phys_addr >> 12; - int32_t base_address = *instruction_pointer & ~0xFFF; - uint16_t* entry_points = page_entry_points[page]; - - for(int32_t i = 0; i < MAX_ENTRIES_PER_PAGE; i++) - { - if(entry_points[i] == ENTRY_POINT_END) - { - if(i == 0) - { - return false; - } - - break; - } - - assert((entry_points[i] & ~0xFFF) == 0); - - int32_t address = base_address | entry_points[i]; - - assert(!is_near_end_of_page(address)); - - assert(to_visit_stack_count < 1000); - to_visit_stack[to_visit_stack_count++] = address; - assert(marked_as_entry_count < 1000); - marked_as_entry[marked_as_entry_count++] = address; - - entry_points[i] = ENTRY_POINT_END; - } - - assert(to_visit_stack_count >= 1); - - while(to_visit_stack_count) - { - int32_t to_visit = to_visit_stack[--to_visit_stack_count]; - - assert(same_page(*instruction_pointer, to_visit)); - *instruction_pointer = *instruction_pointer & ~0xFFF | to_visit & 0xFFF; - - if(find_basic_block_index(&basic_blocks, *instruction_pointer) != -1) - { - // been here already, next - continue; - } - - struct basic_block* current_block = add_basic_block_start(&basic_blocks, *instruction_pointer); - - current_block->next_block_branch_taken_addr = 0; - current_block->is_entry_block = false; - - while(true) - { - if(is_near_end_of_page(*instruction_pointer)) - { - current_block->next_block_branch_taken_addr = 0; - current_block->next_block_addr = 0; - current_block->end_addr = *instruction_pointer; - current_block->condition_index = -1; - profiler_stat_increment(S_COMPILE_CUT_OFF_AT_END_OF_PAGE); - break; - } - - int32_t opcode = read_imm8(); - struct analysis analysis = analyze_step(opcode | is_osize_32() << 8); - - assert(*prefixes == 0); - - bool has_jump_target = analysis.flags & (JIT_INSTR_IMM_JUMP16_FLAG | JIT_INSTR_IMM_JUMP32_FLAG); - - int32_t instruction_end = *instruction_pointer; - - bool has_next_instruction = (analysis.flags & JIT_INSTR_NO_NEXT_INSTRUCTION_FLAG) == 0; - - if((analysis.flags & JIT_INSTR_BLOCK_BOUNDARY_FLAG) == 0) - { - // ordinary instruction, continue at next - assert(!has_jump_target); - assert(has_next_instruction); - - if(find_basic_block_index(&basic_blocks, *instruction_pointer) != -1) - { - current_block->next_block_branch_taken_addr = 0; - assert(*instruction_pointer); - current_block->next_block_addr = *instruction_pointer; - current_block->end_addr = *instruction_pointer; - current_block->condition_index = -1; - break; - } - } - else if(has_jump_target) - { - int32_t jump_target = analysis.flags & JIT_INSTR_IMM_JUMP32_FLAG ? - instruction_end + analysis.jump_offset : - get_seg_cs() + ((instruction_end - get_seg_cs() + analysis.jump_offset) & 0xFFFF); - - if(analysis.condition_index == -1) - { - // non-conditional jump: continue at jump target - - if(has_next_instruction) - { - // Execution will eventually come back to the next instruction (CALL) - - assert(marked_as_entry_count < 1000); - marked_as_entry[marked_as_entry_count++] = *instruction_pointer; - - assert(to_visit_stack_count < 1000); - to_visit_stack[to_visit_stack_count++] = *instruction_pointer; - } - - if(same_page(jump_target, *instruction_pointer)) - { - assert(jump_target); - current_block->next_block_addr = jump_target; - - assert(to_visit_stack_count < 1000); - to_visit_stack[to_visit_stack_count++] = jump_target; - } - else - { - current_block->next_block_addr = 0; - } - - current_block->next_block_branch_taken_addr = 0; - current_block->condition_index = -1; - current_block->end_addr = *instruction_pointer; - - break; - } - else - { - // conditional jump: continue at next and continue at jump target - assert(has_next_instruction); - - assert(to_visit_stack_count < 1000); - to_visit_stack[to_visit_stack_count++] = *instruction_pointer; - - if(same_page(jump_target, *instruction_pointer)) - { - assert(to_visit_stack_count < 1000); - to_visit_stack[to_visit_stack_count++] = jump_target; - - assert(jump_target); - current_block->next_block_branch_taken_addr = jump_target; - - // Very simple heuristic for "infinite loops": This - // detects Linux's "calibrating delay loop" - if(jump_target == current_block->addr) - { - dbg_log("Basic block looping back to front"); - *requires_loop_limit = true; - } - } - else - { - current_block->next_block_branch_taken_addr = 0; - } - - current_block->jump_offset = analysis.jump_offset; - current_block->jump_offset_is_32 = analysis.flags & JIT_INSTR_IMM_JUMP32_FLAG; - - assert(*instruction_pointer); - current_block->next_block_addr = *instruction_pointer; - current_block->end_addr = *instruction_pointer; - - assert(analysis.condition_index >= 0 && analysis.condition_index < 0x10); - current_block->condition_index = analysis.condition_index; - - break; - } - } - else - { - // a block boundary but not a jump, get out - - assert((analysis.flags & JIT_INSTR_BLOCK_BOUNDARY_FLAG) && !has_jump_target); - - if(has_next_instruction) - { - // block boundary, but execution will eventually come back - // to the next instruction. Create a new basic block - // starting at the next instruction and register it as an - // entry point - - assert(marked_as_entry_count < 1000); - marked_as_entry[marked_as_entry_count++] = *instruction_pointer; - - assert(to_visit_stack_count < 1000); - to_visit_stack[to_visit_stack_count++] = *instruction_pointer; - } - - current_block->next_block_branch_taken_addr = 0; - current_block->next_block_addr = 0; - current_block->condition_index = -1; - current_block->end_addr = *instruction_pointer; - break; - } - } - } - - // Note: O(no_of_basic_blocks * no_of_entry_blocks) - for(int32_t basic_block_index = 0; basic_block_index < basic_blocks.length; basic_block_index++) - { - struct basic_block* basic_block = &basic_blocks.blocks[basic_block_index]; - - for(int32_t i = 0; i < marked_as_entry_count; i++) - { - if(basic_block->addr == marked_as_entry[i]) - { - basic_block->is_entry_block = true; - break; - } - } - } - - if(DEBUG) - { - int32_t start = basic_blocks.blocks[0].addr; - int32_t end = basic_blocks.blocks[basic_blocks.length - 1].end_addr; - - if(true) - { - dbg_log("Function with %d basic blocks, start at %x end at %x", - basic_blocks.length, start, end); - } - - //for(int32_t i = 0; i < basic_blocks.length; i++) - //{ - // dbg_log("- addr=%x end_addr=%x", basic_blocks.blocks[i].addr, basic_blocks.blocks[i].end_addr); - //} - - dump_function_code(basic_blocks.blocks, basic_blocks.length, end); - } - - return true; -} - -__attribute__((noinline)) -static void jit_generate(uint32_t phys_addr) -{ - profiler_stat_increment(S_COMPILE); - - // don't immediately retry to compile - hot_code_addresses[jit_hot_hash_page(phys_addr >> 12)] = 0; - - int32_t start = *instruction_pointer; - - int32_t first_opcode = read8(get_phys_eip()); - - bool requires_loop_limit = false; - - // populate basic_blocks - if(!jit_find_basic_blocks(phys_addr, &requires_loop_limit)) - { - dbg_log("No basic blocks, not generating code"); - *instruction_pointer = start; - return; - } - - // Code generation starts here - gen_reset(); - - // set state local variable to the initial state passed as the first argument - wg_get_local(instruction_body, GEN_LOCAL_ARG_INITIAL_STATE); - wg_set_local(instruction_body, GEN_LOCAL_STATE); - - // initialise max_iterations - wg_push_i32(instruction_body, JIT_MAX_ITERATIONS_PER_FUNCTION); - wg_set_local(instruction_body, GEN_LOCAL_ITERATION_COUNTER); - - // main state machine loop - wg_loop_void(instruction_body); - - if(JIT_ALWAYS_USE_LOOP_SAFETY || requires_loop_limit) - { - profiler_stat_increment(S_COMPILE_WITH_LOOP_SAFETY); - - // decrement max_iterations - wg_get_local(instruction_body, GEN_LOCAL_ITERATION_COUNTER); - wg_push_i32(instruction_body, -1); - wg_add_i32(instruction_body); - wg_set_local(instruction_body, GEN_LOCAL_ITERATION_COUNTER); - - // if max_iterations == 0: return - wg_get_local(instruction_body, GEN_LOCAL_ITERATION_COUNTER); - wg_eqz_i32(instruction_body); - wg_if_void(instruction_body); - wg_return(instruction_body); - wg_block_end(instruction_body); - } - - wg_block_void(instruction_body); // for the default case - - // generate the opening blocks for the cases - - for(int32_t i = 0; i < basic_blocks.length; i++) - { - wg_block_void(instruction_body); - } - - wg_get_local(instruction_body, GEN_LOCAL_STATE); - wg_brtable_and_cases(instruction_body, basic_blocks.length); - - for(int32_t i = 0; i < basic_blocks.length; i++) - { - // Case [i] will jump after the [i]th block, so we first generate the - // block end opcode and then the code for that block - - wg_block_end(instruction_body); - - struct basic_block block = basic_blocks.blocks[i]; - - int32_t next_block_start = block.end_addr; - - if(block.addr == next_block_start) - { - // Empty basic block, generate no code (for example, jump to block - // that is near end of page) - assert(!block.next_block_addr); - } - else - { - wg_commit_instruction_body_to_cs(); - jit_generate_basic_block(block.addr, next_block_start); - wg_commit_instruction_body_to_cs(); - } - - bool invalid_connection_to_next_block = next_block_start != *instruction_pointer; - - if(!invalid_connection_to_next_block && block.next_block_addr) - { - if(block.condition_index == -1) - { - assert(!block.next_block_branch_taken_addr); - - // Unconditional jump to next basic block - // - All instructions that don't change eip - // - Unconditional jump - - int32_t next_bb_index = find_basic_block_index(&basic_blocks, block.next_block_addr); - assert(next_bb_index != -1); - - // set state variable to next basic block - wg_push_i32(instruction_body, next_bb_index); - wg_set_local(instruction_body, GEN_LOCAL_STATE); - - wg_br(instruction_body, basic_blocks.length - i); // to the loop - } - else - { - // Conditional jump to next basic block - // - jnz, jc, etc. - - assert(block.condition_index >= 0 && block.condition_index < 16); - const char* condition = condition_functions[block.condition_index]; - gen_fn0_const_ret(condition, strlen(condition)); - - wg_if_void(instruction_body); - - // Branch taken - - if(block.jump_offset_is_32) - { - gen_relative_jump(block.jump_offset); - } - else - { - gen_fn1_const("jmp_rel16", strlen("jmp_rel16"), block.jump_offset); - } - - if(block.next_block_branch_taken_addr) - { - int32_t next_basic_block_branch_taken_index = find_basic_block_index( - &basic_blocks, block.next_block_branch_taken_addr); - assert(next_basic_block_branch_taken_index != -1); - - wg_push_i32(instruction_body, next_basic_block_branch_taken_index); - wg_set_local(instruction_body, GEN_LOCAL_STATE); - } - else - { - // Jump to different page - wg_return(instruction_body); - } - - wg_else(instruction_body); - - { - // Branch not taken - // TODO: Could use fall-through here - int32_t next_basic_block_index = find_basic_block_index( - &basic_blocks, block.next_block_addr); - assert(next_basic_block_index != -1); - - wg_push_i32(instruction_body, next_basic_block_index); - wg_set_local(instruction_body, GEN_LOCAL_STATE); - } - - wg_block_end(instruction_body); - - wg_br(instruction_body, basic_blocks.length - i); // to the loop - } - } - else - { - assert(!block.next_block_branch_taken_addr); - assert(block.condition_index == -1); - - // Exit this function - wg_return(instruction_body); - } - } - - wg_block_end(instruction_body); // default case - wg_unreachable(instruction_body); - - wg_block_end(instruction_body); // loop - - wg_commit_instruction_body_to_cs(); - wg_finish(GEN_NO_OF_LOCALS); - - cached_state_flags state_flags = pack_current_state_flags(); - - // allocate an index in the wasm table - assert(wasm_table_index_free_list_count > 0); - uint32_t wasm_table_index = wasm_table_index_free_list[--wasm_table_index_free_list_count]; - assert(wasm_table_index); - - // create entries for each basic block that is marked as an entry point - int32_t entry_point_count = 0; - - for(int32_t i = 0; i < basic_blocks.length; i++) - { - struct basic_block* block = &basic_blocks.blocks[i]; - - profiler_stat_increment(S_COMPILE_BASIC_BLOCK); - - if(block->is_entry_block && block->addr != block->end_addr) - { - uint32_t phys_addr = translate_address_read(block->addr); - - struct code_cache* entry = create_cache_entry(phys_addr, wasm_table_index); - - assert(phys_addr); - entry->start_addr = phys_addr; - entry->state_flags = state_flags; - entry->pending = true; - entry->initial_state = i; - entry->wasm_table_index = wasm_table_index; - -#if DEBUG - entry->opcode[0] = read8(phys_addr); - entry->end_addr = block->end_addr; - entry->len = block->end_addr - block->addr; - entry->virt_addr = *instruction_pointer & ~0xFFF | phys_addr & 0xFFF; -#endif - - entry_point_count++; - profiler_stat_increment(S_COMPILE_ENTRY_POINT); - } - } - - check_jit_cache_array_invariants(); - - assert(entry_point_count > 0); - - UNUSED(first_opcode); - - int32_t end_addr = 0; - - // will call codegen_finalize_finished asynchronously when finished - codegen_finalize( - wasm_table_index, phys_addr, end_addr, - first_opcode, state_flags); - - profiler_stat_increment(S_COMPILE_SUCCESS); - - *instruction_pointer = start; -} - -#if DEBUG -// for testing -void jit_force_generate_unsafe(uint32_t phys_addr) -{ - *instruction_pointer = phys_addr; - record_page_entry(phys_addr); - jit_generate(phys_addr); -} -#endif - void cycle_internal() { profiler_stat_increment(S_CYCLE_INTERNAL); @@ -1844,72 +650,38 @@ void cycle_internal() *previous_ip = *instruction_pointer; uint32_t phys_addr = get_phys_eip(); - struct code_cache* entry = find_cache_entry(phys_addr); + cached_state_flags state_flags = pack_current_state_flags(); + uint32_t entry = jit_find_cache_entry(phys_addr, state_flags); - if(entry && !entry->pending) + if(entry) { profiler_stat_increment(S_RUN_FROM_CACHE); int32_t initial_tsc = *timestamp_counter; - assert(entry->opcode[0] == read8(phys_addr)); + //uint32_t old_start_address = entry->start_addr; - uint32_t old_start_address = entry->start_addr; - - uint16_t wasm_table_index = entry->wasm_table_index; - uint16_t initial_state = entry->initial_state; + uint16_t wasm_table_index = entry & 0xFFFF; + uint16_t initial_state = entry >> 16; call_indirect1(wasm_table_index, initial_state); // XXX: New clearing: This should fail on self-modifying code //assert(entry->start_addr == old_start_address); - UNUSED(old_start_address); + //UNUSED(old_start_address); profiler_stat_increment_by(S_RUN_FROM_CACHE_STEPS, *timestamp_counter - initial_tsc); } else { - if(!entry) // not pending - { - const int32_t address_hash = jit_hot_hash_page(phys_addr >> 12); - - hot_code_addresses[address_hash]++; - - record_page_entry(phys_addr); - - if(ENABLE_JIT_ALWAYS || hot_code_addresses[address_hash] >= JIT_THRESHOLD) - { #if DEBUG - assert(!must_not_fault); must_not_fault = true; + assert(!must_not_fault); must_not_fault = true; #endif + jit_increase_hotness_and_maybe_compile(phys_addr, get_seg_cs(), state_flags); - int32_t old_previous_ip = *previous_ip; - int32_t old_instruction_pointer = *instruction_pointer; - - jit_generate(phys_addr); - - // jit_generate must not change previous_ip or instruction_pointer - assert(*previous_ip == old_previous_ip); - assert(*instruction_pointer == old_instruction_pointer); #if DEBUG - assert(must_not_fault); must_not_fault = false; + assert(must_not_fault); must_not_fault = false; #endif - } - } - - if(entry) - { - assert(entry->pending); - profiler_stat_increment(S_RUN_INTERPRETED_PENDING); - } - else if(is_near_end_of_page(phys_addr)) - { - profiler_stat_increment(S_RUN_INTERPRETED_NEAR_END_OF_PAGE); - } - else - { - profiler_stat_increment(S_RUN_INTERPRETED_NOT_HOT); - } int32_t initial_tsc = *timestamp_counter; @@ -1939,12 +711,6 @@ void run_prefix_instruction() run_instruction(read_imm8() | is_osize_32() << 8); } -jit_instr_flags jit_prefix_instruction() -{ - //dbg_log("jit_prefix_instruction is32=%d", is_osize_32()); - return jit_instruction(read_imm8() | is_osize_32() << 8); -} - void clear_prefixes() { *prefixes = 0; @@ -1958,17 +724,6 @@ void segment_prefix_op(int32_t seg) *prefixes = 0; } -jit_instr_flags segment_prefix_op_jit(int32_t seg) -{ - assert(seg <= 5); - *prefixes |= seg + 1; - gen_add_prefix_bits(seg + 1); - jit_instr_flags instr_flags = jit_prefix_instruction(); - gen_clear_prefixes(); - *prefixes = 0; - return instr_flags; -} - void do_many_cycles_unsafe() { profiler_stat_increment(S_DO_MANY_CYCLES); @@ -2319,8 +1074,7 @@ void safe_write32(int32_t address, int32_t value) // - does not contain code uint32_t phys_address = entry & ~0xFFF ^ address; - assert(page_first_jit_cache_entry[phys_address >> 12] == JIT_CACHE_ARRAY_NO_NEXT_ENTRY); - assert(page_entry_points[phys_address >> 12][0] == ENTRY_POINT_END); + assert(!jit_page_has_code(phys_address >> 12)); assert(!in_mapped_range(phys_address)); *(int32_t*)(mem8 + phys_address) = value; return; @@ -2736,3 +1490,23 @@ void store_current_tsc() { *current_tsc = read_tsc(); } + + +int32_t get_opstats_buffer(int32_t index) +{ + assert(index >= 0 && index < 0x200); + +#if ENABLE_PROFILER_OPSTATS + if(index < 0x100) + { + return opstats_buffer[index]; + } + else + { + return opstats_buffer_0f[index - 0x100]; + } +#else + UNUSED(index); + return 0; +#endif +} diff --git a/src/native/cpu.h b/src/native/cpu.h index 0188f41f..53660202 100644 --- a/src/native/cpu.h +++ b/src/native/cpu.h @@ -8,8 +8,6 @@ #include "config.h" #include "shared.h" -#define CODE_CACHE_SEARCH_SIZE 8 - union reg128 { int8_t i8[16]; int16_t i16[8]; @@ -37,86 +35,10 @@ _Static_assert(sizeof(union reg64) == 8, "reg64 is 8 bytes"); typedef uint8_t cached_state_flags; -struct code_cache { - // Address of the start of the basic block - uint32_t start_addr; -#if DEBUG - // Address of the instruction immediately after the basic block ends - uint32_t end_addr; - int32_t opcode[1]; - int32_t len; - int32_t virt_addr; -#endif - - // an index into jit_cache_arr for the next code_cache entry within the same physical page - int32_t next_index_same_page; - - uint16_t wasm_table_index; - uint16_t initial_state; - cached_state_flags state_flags; - bool pending; -}; -#if DEBUG -#else -_Static_assert(sizeof(struct code_cache) == 16, "code_cache uses 16 bytes"); -#endif -struct code_cache jit_cache_arr[JIT_CACHE_ARRAY_SIZE]; - -// XXX: Remove this limitation when page_entry_points is sparse -#define MAX_PHYSICAL_PAGES (512 << 20 >> 12) - -#define MAX_ENTRIES_PER_PAGE 128 -#define ENTRY_POINT_END 0xFFFF - -uint16_t page_entry_points[MAX_PHYSICAL_PAGES][MAX_ENTRIES_PER_PAGE]; - // Flag indicating whether the instruction that just ran was at a block's boundary (jump, // state-altering, etc.) extern uint32_t jit_block_boundary; -typedef uint32_t jit_instr_flags; - -#define JIT_INSTR_BLOCK_BOUNDARY_FLAG (1 << 0) -#define JIT_INSTR_NO_NEXT_INSTRUCTION_FLAG (1 << 1) -#define JIT_INSTR_NONFAULTING_FLAG (1 << 2) -#define JIT_INSTR_IMM_JUMP16_FLAG (1 << 3) -#define JIT_INSTR_IMM_JUMP32_FLAG (1 << 4) - -struct analysis { - jit_instr_flags flags; - int32_t jump_offset; - int32_t condition_index; -}; - -struct basic_block { - int32_t addr; - int32_t end_addr; - int32_t next_block_addr; // if 0 this is an exit block - int32_t next_block_branch_taken_addr; - int32_t condition_index; // if not -1 this block ends with a conditional jump - int32_t jump_offset; - bool jump_offset_is_32; - bool is_entry_block; -}; - -#define BASIC_BLOCK_LIST_MAX 1000 - -struct basic_block_list { - int32_t length; - struct basic_block blocks[BASIC_BLOCK_LIST_MAX]; -}; - -// Count of how many times prime_hash(address) has been called through a jump -extern int32_t hot_code_addresses[HASH_PRIME]; - -#define JIT_CACHE_ARRAY_NO_NEXT_ENTRY (-1) - -uint16_t wasm_table_index_free_list[WASM_TABLE_SIZE]; -int32_t wasm_table_index_free_list_count; - -uint16_t wasm_table_index_pending_free[WASM_TABLE_SIZE]; -int32_t wasm_table_index_pending_free_count; - #define VALID_TLB_ENTRY_MAX 10000 int32_t valid_tlb_entries[VALID_TLB_ENTRY_MAX]; int32_t valid_tlb_entries_count; @@ -128,29 +50,11 @@ int32_t valid_tlb_entries_count; #define TLB_GLOBAL (1 << 4) #define TLB_HAS_CODE (1 << 5) -// Indices for local variables and function arguments (which are accessed as local variables) for -// the generated WASM function -#define GEN_LOCAL_ARG_INITIAL_STATE 0 -#define GEN_LOCAL_STATE 1 -#define GEN_LOCAL_ITERATION_COUNTER 2 -// local scratch variables for use wherever required -#define GEN_LOCAL_SCRATCH0 3 -#define GEN_LOCAL_SCRATCH1 4 -#define GEN_LOCAL_SCRATCH2 5 -// Function arguments are not included in the local variable count -#define GEN_NO_OF_LOCALS 5 - // defined in call-indirect.ll extern void call_indirect(int32_t index); extern void call_indirect1(int32_t index, int32_t arg); void after_block_boundary(void); -struct analysis analyze_step(int32_t); - -void after_jump(void); -void diverged(void); -void branch_taken(void); -void branch_not_taken(void); bool same_page(int32_t, int32_t); @@ -158,6 +62,7 @@ int32_t get_eflags(void); uint32_t translate_address_read(int32_t address); uint32_t translate_address_write(int32_t address); void tlb_set_has_code(uint32_t physical_page, bool has_code); +void check_tlb_invariants(void); void writable_or_pagefault(int32_t addr, int32_t size); int32_t read_imm8(void); @@ -174,19 +79,12 @@ int32_t get_seg_prefix_ds(int32_t offset); int32_t get_seg_prefix_ss(int32_t offset); int32_t get_seg_prefix_cs(int32_t offset); int32_t modrm_resolve(int32_t modrm_byte); -void modrm_skip(int32_t modrm_byte); -void check_jit_cache_array_invariants(void); - -uint32_t jit_hot_hash_page(uint32_t page); -void jit_link_block(int32_t target); -void jit_link_block_conditional(int32_t offset, const char* condition); void cycle_internal(void); void run_prefix_instruction(void); -jit_instr_flags jit_prefix_instruction(void); void clear_prefixes(void); void segment_prefix_op(int32_t seg); -jit_instr_flags segment_prefix_op_jit(int32_t seg); + bool has_flat_segmentation(void); void do_many_cycles_unsafe(void); void raise_exception(int32_t interrupt_nr); @@ -243,3 +141,5 @@ void set_tsc(uint32_t, uint32_t); uint64_t read_tsc(void); bool vm86_mode(void); int32_t getiopl(void); + +int32_t get_opstats_buffer(int32_t index); diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index 8f1e6c28..b0e548e0 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -86,17 +86,13 @@ static union reg64* const reg_mmx = (union reg64* const) 1064; // length 64 // gap -static uint8_t* const codegen_buffer_op = (uint8_t* const) 0x1000; // length 0x100000 -static uint8_t* const codegen_buffer_cs = (uint8_t* const) 0x101000; // length 0x100000 -static uint8_t* const codegen_buffer_instruction_body = (uint8_t* const) 0x201000; // length 0x100000 -static uint8_t* const codegen_string_input = (uint8_t* const) 0x301000; // length 32 +static uint32_t* const opstats_buffer = (uint32_t* const) 0x1000; // length 0x400 +static uint32_t* const opstats_buffer_0f = (uint32_t* const) 0x1400; // length 0x400 // gap -static int32_t* const tlb_data = (int32_t* const) (0x400000); // length 0x100000*4 -// A mapping from physical page to index into jit_cache_arr -static int32_t* const page_first_jit_cache_entry = (int32_t* const) (0x800000); // length 0x100000*4 +static int32_t* const tlb_data = (int32_t* const) 0x400000; // length 0x100000*4 -static uint8_t* const mem8 = (uint8_t* const) (0x400000 + 0x100000 * 8); -static uint16_t* const mem16 = (uint16_t* const) (0x400000 + 0x100000 * 8); -static int32_t* const mem32s = (int32_t* const) (0x400000 + 0x100000 * 8); +static uint8_t* const mem8 = (uint8_t* const) 0x800000; +static uint16_t* const mem16 = (uint16_t* const) 0x800000; +static int32_t* const mem32s = (int32_t* const) 0x800000; diff --git a/src/native/instructions.c b/src/native/instructions.c index 484a6374..c61978df 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -4,8 +4,6 @@ #include #include "arith.h" -#include "codegen/codegen.h" -#include "codegen/wasmgen.h" #include "const.h" #include "cpu.h" #include "fpu.h" @@ -64,13 +62,6 @@ void instr32_0F() { run_instruction0f_32(read_imm8()); } -jit_instr_flags instr16_0F_jit() { - return jit_instruction0f_16(read_imm8()); -} -jit_instr_flags instr32_0F_jit() { - return jit_instruction0f_32(read_imm8()); -} - DEFINE_MODRM_INSTR_READ_WRITE_8(instr_10, adc8(___, read_reg8(r))) DEFINE_MODRM_INSTR_READ_WRITE_16(instr16_11, adc16(___, read_reg16(r))) @@ -131,7 +122,6 @@ void instr32_25(int32_t imm32) { reg32s[EAX] = and32(reg32s[EAX], imm32); } void instr_26() { segment_prefix_op(ES); } -jit_instr_flags instr_26_jit() { return segment_prefix_op_jit(ES); } void instr_27() { bcd_daa(); } DEFINE_MODRM_INSTR_READ_WRITE_8(instr_28, sub8(___, read_reg8(r))) @@ -145,7 +135,6 @@ void instr16_2D(int32_t imm16) { reg16[AX] = sub16(reg16[AX], imm16); } void instr32_2D(int32_t imm32) { reg32s[EAX] = sub32(reg32s[EAX], imm32); } void instr_2E() { segment_prefix_op(CS); } -jit_instr_flags instr_2E_jit() { return segment_prefix_op_jit(CS); } void instr_2F() { bcd_das(); } DEFINE_MODRM_INSTR_READ_WRITE_8(instr_30, xor8(___, read_reg8(r))) @@ -159,7 +148,6 @@ void instr16_35(int32_t imm16) { reg16[AX] = xor16(reg16[AX], imm16); } void instr32_35(int32_t imm32) { reg32s[EAX] = xor32(reg32s[EAX], imm32); } void instr_36() { segment_prefix_op(SS); } -jit_instr_flags instr_36_jit() { return segment_prefix_op_jit(SS); } void instr_37() { bcd_aaa(); } DEFINE_MODRM_INSTR_READ8(instr_38, cmp8(___, read_reg8(r))) @@ -173,7 +161,6 @@ void instr16_3D(int32_t imm16) { cmp16(reg16[AX], imm16); } void instr32_3D(int32_t imm32) { cmp32(reg32s[EAX], imm32); } void instr_3E() { segment_prefix_op(DS); } -jit_instr_flags instr_3E_jit() { return segment_prefix_op_jit(DS); } void instr_3F() { bcd_aas(); } @@ -247,39 +234,6 @@ void instr32_5E() { reg32s[ESI] = pop32s(); } void instr16_5F() { reg16[DI] = pop16(); } void instr32_5F() { reg32s[EDI] = pop32s(); } -void instr16_50_jit() { push16_reg_jit(AX); } -void instr32_50_jit() { push32_reg_jit(EAX); } -void instr16_51_jit() { push16_reg_jit(CX); } -void instr32_51_jit() { push32_reg_jit(ECX); } -void instr16_52_jit() { push16_reg_jit(DX); } -void instr32_52_jit() { push32_reg_jit(EDX); } -void instr16_53_jit() { push16_reg_jit(BX); } -void instr32_53_jit() { push32_reg_jit(EBX); } -void instr16_54_jit() { push16_reg_jit(SP); } -void instr32_54_jit() { push32_reg_jit(ESP); } -void instr16_55_jit() { push16_reg_jit(BP); } -void instr32_55_jit() { push32_reg_jit(EBP); } -void instr16_56_jit() { push16_reg_jit(SI); } -void instr32_56_jit() { push32_reg_jit(ESI); } -void instr16_57_jit() { push16_reg_jit(DI); } -void instr32_57_jit() { push32_reg_jit(EDI); } - -void instr16_58_jit() { pop16_reg_jit(AX); } -void instr32_58_jit() { pop32s_reg_jit(EAX); } -void instr16_59_jit() { pop16_reg_jit(CX); } -void instr32_59_jit() { pop32s_reg_jit(ECX); } -void instr16_5A_jit() { pop16_reg_jit(DX); } -void instr32_5A_jit() { pop32s_reg_jit(EDX); } -void instr16_5B_jit() { pop16_reg_jit(BX); } -void instr32_5B_jit() { pop32s_reg_jit(EBX); } -void instr16_5D_jit() { pop16_reg_jit(BP); } -void instr32_5D_jit() { pop32s_reg_jit(EBP); } -void instr16_5E_jit() { pop16_reg_jit(SI); } -void instr32_5E_jit() { pop32s_reg_jit(ESI); } -void instr16_5F_jit() { pop16_reg_jit(DI); } -void instr32_5F_jit() { pop32s_reg_jit(EDI); } - - void instr16_60() { pusha16(); } void instr32_60() { pusha32(); } void instr16_61() { popa16(); } @@ -298,9 +252,7 @@ void instr_62_mem(int32_t addr, int32_t r) { DEFINE_MODRM_INSTR_READ_WRITE_16(instr_63, arpl(___, read_reg16(r))) void instr_64() { segment_prefix_op(FS); } -jit_instr_flags instr_64_jit() { return segment_prefix_op_jit(FS); } void instr_65() { segment_prefix_op(GS); } -jit_instr_flags instr_65_jit() { return segment_prefix_op_jit(GS); } void instr_66() { // Operand-size override prefix @@ -308,18 +260,6 @@ void instr_66() { run_prefix_instruction(); *prefixes = 0; } -jit_instr_flags instr_66_jit() { - // Operand-size override prefix - - // This affects both decoding and instructions at runtime, so we set - // prefixes directly *and* in the generated code - *prefixes |= PREFIX_MASK_OPSIZE; - gen_add_prefix_bits(PREFIX_MASK_OPSIZE); - jit_instr_flags instr_flags = jit_prefix_instruction(); - *prefixes = 0; - gen_clear_prefixes(); - return instr_flags; -} void instr_67() { // Address-size override prefix @@ -328,26 +268,10 @@ void instr_67() { run_prefix_instruction(); *prefixes = 0; } -jit_instr_flags instr_67_jit() { - // Address-size override prefix - - // This affects both decoding and instructions at runtime, so we set - // prefixes directly *and* in the generated code - dbg_assert(is_asize_32() == *is_32); - *prefixes |= PREFIX_MASK_ADDRSIZE; - gen_add_prefix_bits(PREFIX_MASK_ADDRSIZE); - jit_instr_flags instr_flags = jit_prefix_instruction(); - *prefixes = 0; - gen_clear_prefixes(); - return instr_flags; -} void instr16_68(int32_t imm16) { push16(imm16); } void instr32_68(int32_t imm32) { push32(imm32); } -void instr16_68_jit(int32_t imm16) { push16_imm_jit(imm16); } -void instr32_68_jit(int32_t imm32) { push32_imm_jit(imm32); } - 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)); } 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)); } void instr32_69_mem(int32_t addr, int32_t r, int32_t imm) { write_reg32(r, imul_reg32(safe_read32s(addr), imm)); } @@ -356,9 +280,6 @@ void instr32_69_reg(int32_t r1, int32_t r, int32_t imm) { write_reg32(r, imul_re void instr16_6A(int32_t imm8) { push16(imm8); } void instr32_6A(int32_t imm8) { push32(imm8); } -void instr16_6A_jit(int32_t imm8) { push16_imm_jit(imm8); } -void instr32_6A_jit(int32_t imm8) { push32_imm_jit(imm8); } - void instr16_6B_mem(int32_t addr, int32_t r, int32_t imm) { write_reg16(r, imul_reg16(safe_read16(addr) << 16 >> 16, imm)); } void instr16_6B_reg(int32_t r1, int32_t r, int32_t imm) { write_reg16(r, imul_reg16(read_reg16(r1) << 16 >> 16, imm)); } void instr32_6B_mem(int32_t addr, int32_t r, int32_t imm) { write_reg32(r, imul_reg32(safe_read32s(addr), imm)); } @@ -405,40 +326,6 @@ void instr32_7D(int32_t imm8) { jmpcc32(!test_l(), imm8); } void instr32_7E(int32_t imm8) { jmpcc32( test_le(), imm8); } void instr32_7F(int32_t imm8) { jmpcc32(!test_le(), imm8); } -void instr16_70_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_o"); } -void instr16_71_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_no"); } -void instr16_72_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_b"); } -void instr16_73_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nb"); } -void instr16_74_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_z"); } -void instr16_75_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nz"); } -void instr16_76_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_be"); } -void instr16_77_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nbe"); } -void instr16_78_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_s"); } -void instr16_79_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_ns"); } -void instr16_7A_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_p"); } -void instr16_7B_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_np"); } -void instr16_7C_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_l"); } -void instr16_7D_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nl"); } -void instr16_7E_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_le"); } -void instr16_7F_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nle"); } - -void instr32_70_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_o"); } -void instr32_71_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_no"); } -void instr32_72_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_b"); } -void instr32_73_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nb"); } -void instr32_74_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_z"); } -void instr32_75_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nz"); } -void instr32_76_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_be"); } -void instr32_77_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nbe"); } -void instr32_78_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_s"); } -void instr32_79_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_ns"); } -void instr32_7A_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_p"); } -void instr32_7B_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_np"); } -void instr32_7C_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_l"); } -void instr32_7D_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nl"); } -void instr32_7E_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_le"); } -void instr32_7F_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nle"); } - 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)) @@ -514,65 +401,10 @@ void instr16_89_mem(int32_t addr, int32_t r) { safe_write16(addr, read_reg16(r)) void instr32_89_reg(int32_t r2, int32_t r) { write_reg32(r2, read_reg32(r)); } void instr32_89_mem(int32_t addr, int32_t r) { safe_write32(addr, read_reg32(r)); } -void instr16_89_reg_jit(int32_t r_dest, int32_t r_src) -{ - gen_set_reg16_r(get_reg16_index(r_dest), get_reg16_index(r_src)); -} -void instr32_89_reg_jit(int32_t r_dest, int32_t r_src) -{ - gen_set_reg32_r(r_dest, r_src); -} - -void instr16_89_mem_jit(int32_t modrm_byte, int32_t r) -{ - // XXX - gen_modrm_resolve(modrm_byte); gen_modrm_fn1("instr16_89_mem", 14, modrm_byte >> 3 & 7); -} -void instr32_89_mem_jit(int32_t modrm_byte, int32_t r) -{ - // Pseudo: safe_write32(modrm_resolve(modrm_byte), reg32s[r]); - const int32_t address_local = GEN_LOCAL_SCRATCH0; - const int32_t value_local = GEN_LOCAL_SCRATCH1; - - gen_modrm_resolve(modrm_byte); - wg_set_local(instruction_body, address_local); - - wg_push_i32(instruction_body, (uint32_t) ®32s[r]); - wg_load_aligned_i32_from_stack(instruction_body, 0); - wg_set_local(instruction_body, value_local); - - gen_safe_write32(address_local, value_local); -} - 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, ___)) -void instr16_8B_reg_jit(int32_t r_src, int32_t r_dest) -{ - gen_set_reg16_r(get_reg16_index(r_dest), get_reg16_index(r_src)); -} -void instr32_8B_reg_jit(int32_t r_src, int32_t r_dest) -{ - gen_set_reg32_r(r_dest, r_src); -} - -void instr16_8B_mem_jit(int32_t modrm_byte, int32_t r) -{ - // XXX - gen_modrm_resolve(modrm_byte); gen_modrm_fn1("instr16_8B_mem", 14, modrm_byte >> 3 & 7); -} -void instr32_8B_mem_jit(int32_t modrm_byte, int32_t r) -{ - // Pseudo: reg32s[r] = safe_read32s(modrm_resolve(modrm_byte)); - wg_push_i32(instruction_body, (int32_t) ®32s[r]); - - gen_modrm_resolve(modrm_byte); - gen_safe_read32(); - - wg_store_aligned_i32(instruction_body); -} - void instr_8C_check_sreg(int32_t sreg) { if(sreg >= 6) { @@ -617,28 +449,6 @@ void instr32_8D_mem(int32_t addr, int32_t r) { *prefixes = 0; } -void instr16_8D_mem_jit(int32_t modrm_byte) -{ - int32_t loc = (int32_t) ®16[get_reg16_index(modrm_byte >> 3 & 7)]; - wg_push_u32(instruction_body, loc); - // override prefix, so modrm_resolve does not return the segment part - *prefixes |= SEG_PREFIX_ZERO; - gen_modrm_resolve(modrm_byte); - wg_store_aligned_u16(instruction_body); - *prefixes = 0; -} - -void instr32_8D_mem_jit(int32_t modrm_byte) -{ - int32_t loc = (int32_t) ®32s[modrm_byte >> 3 & 7]; - wg_push_u32(instruction_body, loc); - // override prefix, so modrm_resolve does not return the segment part - *prefixes |= SEG_PREFIX_ZERO; - gen_modrm_resolve(modrm_byte); - wg_store_aligned_i32(instruction_body); - *prefixes = 0; -} - void instr_8E_helper(int32_t data, int32_t mod) { if(mod == ES || mod == SS || mod == DS || mod == FS || mod == GS) @@ -700,30 +510,6 @@ void instr32_8F_0_reg(int32_t r) write_reg32(r, pop32s()); } -void instr16_8F_0_jit_mem(int32_t modrm_byte) -{ - gen_fn0_const("instr16_8F_0_mem_pre", 20); - gen_modrm_resolve(modrm_byte); - gen_modrm_fn0("instr16_8F_0_mem", 16); -} - -void instr16_8F_0_jit_reg(int32_t r) -{ - gen_fn1_const("instr16_8F_0_reg", 16, r); -} - -void instr32_8F_0_jit_mem(int32_t modrm_byte) -{ - gen_fn0_const("instr32_8F_0_mem_pre", 20); - gen_modrm_resolve(modrm_byte); - gen_modrm_fn0("instr32_8F_0_mem", 16); -} - -void instr32_8F_0_jit_reg(int32_t r) -{ - gen_fn1_const("instr32_8F_0_reg", 16, r); -} - void instr_90() { } void instr16_91() { xchg16r(CX); } void instr32_91() { xchg32r(ECX); } @@ -1495,13 +1281,6 @@ void instr32_E8(int32_t imm32s) { instruction_pointer[0] = instruction_pointer[0] + imm32s; //dbg_assert(is_asize_32() || get_real_eip() < 0x10000); } -void instr16_E8_jit(int32_t imm16) { - gen_fn1_const("instr16_E8", 10, imm16); -} - -void instr32_E8_jit(int32_t imm32s) { - gen_fn1_const("instr32_E8", 10, imm32s); -} void instr16_E9(int32_t imm16) { // jmp @@ -1512,12 +1291,6 @@ void instr32_E9(int32_t imm32s) { instruction_pointer[0] = instruction_pointer[0] + imm32s; dbg_assert(is_asize_32() || get_real_eip() < 0x10000); } -void instr16_E9_jit(int32_t imm16) { - gen_fn1_const("instr16_E9", 10, imm16); -} -void instr32_E9_jit(int32_t imm32s) { - gen_fn1_const("instr32_E9", 10, imm32s); -} void instr16_EA(int32_t new_ip, int32_t cs) { // jmpf @@ -1541,12 +1314,6 @@ void instr32_EB(int32_t imm8) { dbg_assert(is_asize_32() || get_real_eip() < 0x10000); } -void instr16_EB_jit(int32_t imm8s) { - gen_fn1_const("instr16_EB", 10, imm8s); -} -void instr32_EB_jit(int32_t imm8s) { - gen_fn1_const("instr32_EB", 10, imm8s); -} void instr_EC() { int32_t port = reg16[DX]; @@ -1588,15 +1355,6 @@ void instr_F0() { // some instructions that don't write to memory run_prefix_instruction(); } -jit_instr_flags instr_F0_jit() { - // lock - //dbg_log("lock"); - - // TODO - // This triggers UD when used with - // some instructions that don't write to memory - return jit_prefix_instruction(); -} void instr_F1() { // INT1 // https://code.google.com/p/corkami/wiki/x86oddities#IceBP @@ -1611,16 +1369,6 @@ void instr_F2() { run_prefix_instruction(); *prefixes = 0; } -jit_instr_flags instr_F2_jit() { - // repnz - dbg_assert((*prefixes & PREFIX_MASK_REP) == 0); - gen_add_prefix_bits(PREFIX_REPNZ); - *prefixes |= PREFIX_REPNZ; - jit_instr_flags instr_flags = jit_prefix_instruction(); - gen_clear_prefixes(); - *prefixes = 0; - return instr_flags; -} void instr_F3() { // repz @@ -1630,17 +1378,6 @@ void instr_F3() { *prefixes = 0; } -jit_instr_flags instr_F3_jit() { - // repz - dbg_assert((*prefixes & PREFIX_MASK_REP) == 0); - gen_add_prefix_bits(PREFIX_REPZ); - *prefixes |= PREFIX_REPZ; - jit_instr_flags instr_flags = jit_prefix_instruction(); - gen_clear_prefixes(); - *prefixes = 0; - return instr_flags; -} - void instr_F4() { hlt_op(); } @@ -1809,8 +1546,6 @@ void instr16_FF_5_mem(int32_t addr) dbg_assert(is_asize_32() || get_real_eip() < 0x10000); } DEFINE_MODRM_INSTR1_READ16(instr16_FF_6, push16(___)) -void instr16_FF_6_jit_reg(int32_t reg) { push16_reg_jit(reg); } -void instr16_FF_6_jit_mem(int32_t modrm_byte) { push16_mem_jit(modrm_byte); } DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_FF_0, inc32(___)) DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_FF_1, dec32(___)) @@ -1877,19 +1612,10 @@ void instr32_FF_5_mem(int32_t addr) dbg_assert(is_asize_32() || new_ip < 0x10000); } DEFINE_MODRM_INSTR1_READ32(instr32_FF_6, push32(___)) -void instr32_FF_6_jit_reg(int32_t reg) { push32_reg_jit(reg); } -void instr32_FF_6_jit_mem(int32_t modrm_byte) { push32_mem_jit(modrm_byte); } void run_instruction(int32_t opcode) { #include "../../build/interpreter.c" } -jit_instr_flags jit_instruction(int32_t opcode) -{ - jit_instr_flags instr_flags = 0; -#include "../../build/jit.c" - return instr_flags; -} - #pragma clang diagnostic pop diff --git a/src/native/instructions.h b/src/native/instructions.h index ad7960ce..b95aa250 100644 --- a/src/native/instructions.h +++ b/src/native/instructions.h @@ -155,8 +155,6 @@ void instr16_0E(void); void instr32_0E(void); void instr16_0F(void); void instr32_0F(void); -jit_instr_flags instr16_0F_jit(void); -jit_instr_flags instr32_0F_jit(void); void instr_10_mem(int32_t addr, int32_t r); void instr_10_reg(int32_t r1, int32_t r); void instr16_11_mem(int32_t addr, int32_t r); @@ -211,7 +209,6 @@ void instr_24(int32_t imm8); void instr16_25(int32_t imm16); void instr32_25(int32_t imm32); void instr_26(void); -jit_instr_flags instr_26_jit(void); void instr_27(void); void instr_28_mem(int32_t addr, int32_t r); void instr_28_reg(int32_t r1, int32_t r); @@ -229,7 +226,6 @@ void instr_2C(int32_t imm8); void instr16_2D(int32_t imm16); void instr32_2D(int32_t imm32); void instr_2E(void); -jit_instr_flags instr_2E_jit(void); void instr_2F(void); void instr_30_mem(int32_t addr, int32_t r); void instr_30_reg(int32_t r1, int32_t r); @@ -247,7 +243,6 @@ void instr_34(int32_t imm8); void instr16_35(int32_t imm16); void instr32_35(int32_t imm32); void instr_36(void); -jit_instr_flags instr_36_jit(void); void instr_37(void); void instr_38_mem(int32_t addr, int32_t r); void instr_38_reg(int32_t r1, int32_t r); @@ -265,7 +260,6 @@ void instr_3C(int32_t imm8); void instr16_3D(int32_t imm16); void instr32_3D(int32_t imm32); void instr_3E(void); -jit_instr_flags instr_3E_jit(void); void instr_3F(void); void instr16_40(void); void instr32_40(void); @@ -340,13 +334,9 @@ void instr_62_mem(int32_t addr, int32_t r); void instr_63_mem(int32_t addr, int32_t r); void instr_63_reg(int32_t r1, int32_t r); void instr_64(void); -jit_instr_flags instr_64_jit(void); void instr_65(void); -jit_instr_flags instr_65_jit(void); void instr_66(void); -jit_instr_flags instr_66_jit(void); void instr_67(void); -jit_instr_flags instr_67_jit(void); void instr16_68(int32_t imm16); void instr32_68(int32_t imm32); void instr16_69_mem(int32_t addr, int32_t r, int32_t imm); @@ -512,8 +502,6 @@ void instr16_8D_mem(int32_t addr, int32_t r); void instr32_8D_reg(int32_t r, int32_t r2); void instr32_8D_mem_pre(void); void instr32_8D_mem(int32_t addr, int32_t r); -void instr16_8D_mem_jit(int32_t modrm_byte); -void instr32_8D_mem_jit(int32_t modrm_byte); void instr_8E_helper(int32_t data, int32_t mod); void instr_8E_mem(int32_t addr, int32_t r); void instr_8E_reg(int32_t r1, int32_t r); @@ -803,12 +791,9 @@ void instr_EE(void); void instr16_EF(void); void instr32_EF(void); void instr_F0(void); -jit_instr_flags instr_F0_jit(void); void instr_F1(void); void instr_F2(void); -jit_instr_flags instr_F2_jit(void); void instr_F3(void); -jit_instr_flags instr_F3_jit(void); void instr_F4(void); void instr_F5(void); void instr_F6_0_mem(int32_t addr, int32_t imm); @@ -901,5 +886,5 @@ void instr32_FF_5_reg(int32_t r); void instr32_FF_5_mem(int32_t addr); void instr32_FF_6_mem(int32_t addr); void instr32_FF_6_reg(int32_t r1); + void run_instruction(int32_t opcode); -jit_instr_flags jit_instruction(int32_t opcode); diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 835de776..59b7302b 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -5,7 +5,6 @@ #include #include "arith.h" -#include "codegen/codegen.h" #include "const.h" #include "cpu.h" #include "fpu.h" @@ -1969,41 +1968,6 @@ void instr32_0F8E(int32_t imm) { jmpcc32( test_le(), imm); } void instr16_0F8F(int32_t imm) { jmpcc16(!test_le(), imm); } void instr32_0F8F(int32_t imm) { jmpcc32(!test_le(), imm); } -void instr16_0F80_jit(int32_t imm) { jit_link_block_conditional(imm, "test_o"); } -void instr16_0F81_jit(int32_t imm) { jit_link_block_conditional(imm, "test_no"); } -void instr16_0F82_jit(int32_t imm) { jit_link_block_conditional(imm, "test_b"); } -void instr16_0F83_jit(int32_t imm) { jit_link_block_conditional(imm, "test_nb"); } -void instr16_0F84_jit(int32_t imm) { jit_link_block_conditional(imm, "test_z"); } -void instr16_0F85_jit(int32_t imm) { jit_link_block_conditional(imm, "test_nz"); } -void instr16_0F86_jit(int32_t imm) { jit_link_block_conditional(imm, "test_be"); } -void instr16_0F87_jit(int32_t imm) { jit_link_block_conditional(imm, "test_nbe"); } -void instr16_0F88_jit(int32_t imm) { jit_link_block_conditional(imm, "test_s"); } -void instr16_0F89_jit(int32_t imm) { jit_link_block_conditional(imm, "test_ns"); } -void instr16_0F8A_jit(int32_t imm) { jit_link_block_conditional(imm, "test_p"); } -void instr16_0F8B_jit(int32_t imm) { jit_link_block_conditional(imm, "test_np"); } -void instr16_0F8C_jit(int32_t imm) { jit_link_block_conditional(imm, "test_l"); } -void instr16_0F8D_jit(int32_t imm) { jit_link_block_conditional(imm, "test_nl"); } -void instr16_0F8E_jit(int32_t imm) { jit_link_block_conditional(imm, "test_le"); } -void instr16_0F8F_jit(int32_t imm) { jit_link_block_conditional(imm, "test_nle"); } - - -void instr32_0F80_jit(int32_t imm) { jit_link_block_conditional(imm, "test_o"); } -void instr32_0F81_jit(int32_t imm) { jit_link_block_conditional(imm, "test_no"); } -void instr32_0F82_jit(int32_t imm) { jit_link_block_conditional(imm, "test_b"); } -void instr32_0F83_jit(int32_t imm) { jit_link_block_conditional(imm, "test_nb"); } -void instr32_0F84_jit(int32_t imm) { jit_link_block_conditional(imm, "test_z"); } -void instr32_0F85_jit(int32_t imm) { jit_link_block_conditional(imm, "test_nz"); } -void instr32_0F86_jit(int32_t imm) { jit_link_block_conditional(imm, "test_be"); } -void instr32_0F87_jit(int32_t imm) { jit_link_block_conditional(imm, "test_nbe"); } -void instr32_0F88_jit(int32_t imm) { jit_link_block_conditional(imm, "test_s"); } -void instr32_0F89_jit(int32_t imm) { jit_link_block_conditional(imm, "test_ns"); } -void instr32_0F8A_jit(int32_t imm) { jit_link_block_conditional(imm, "test_p"); } -void instr32_0F8B_jit(int32_t imm) { jit_link_block_conditional(imm, "test_np"); } -void instr32_0F8C_jit(int32_t imm) { jit_link_block_conditional(imm, "test_l"); } -void instr32_0F8D_jit(int32_t imm) { jit_link_block_conditional(imm, "test_nl"); } -void instr32_0F8E_jit(int32_t imm) { jit_link_block_conditional(imm, "test_le"); } -void instr32_0F8F_jit(int32_t imm) { jit_link_block_conditional(imm, "test_nle"); } - // setcc void instr_0F90_reg(int32_t r, int32_t unused) { setcc_reg( test_o(), r); } void instr_0F91_reg(int32_t r, int32_t unused) { setcc_reg(!test_o(), r); } @@ -3035,8 +2999,8 @@ void instr_660FE5(union reg128 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_660FE5, safe_read128s, read_xmm128s) -void instr_0FE6_mem(int32_t addr, int32_t r) { unimplemented_sse(); } -void instr_0FE6_reg(int32_t r1, int32_t r2) { unimplemented_sse(); } +void instr_0FE6_mem(int32_t addr, int32_t r) { trigger_ud(); } +void instr_0FE6_reg(int32_t r1, int32_t r2) { trigger_ud(); } void instr_660FE6_mem(int32_t addr, int32_t r) { unimplemented_sse(); } void instr_660FE6_reg(int32_t r1, int32_t r2) { unimplemented_sse(); } void instr_F20FE6_mem(int32_t addr, int32_t r) { unimplemented_sse(); } @@ -3708,18 +3672,4 @@ void run_instruction0f_32(int32_t opcode) #include "../../build/interpreter0f_32.c" } -jit_instr_flags jit_instruction0f_16(int32_t opcode) -{ - jit_instr_flags instr_flags = 0; -#include "../../build/jit0f_16.c" - return instr_flags; -} - -jit_instr_flags jit_instruction0f_32(int32_t opcode) -{ - jit_instr_flags instr_flags = 0; -#include "../../build/jit0f_32.c" - return instr_flags; -} - #pragma clang diagnostic pop diff --git a/src/native/instructions_0f.h b/src/native/instructions_0f.h index 00dceee3..38c88a0b 100644 --- a/src/native/instructions_0f.h +++ b/src/native/instructions_0f.h @@ -998,5 +998,3 @@ void instr_660FFE_mem(int32_t addr, int32_t r); void instr_0FFF(void); void run_instruction0f_16(int32_t opcode); void run_instruction0f_32(int32_t opcode); -jit_instr_flags jit_instruction0f_16(int32_t opcode); -jit_instr_flags jit_instruction0f_32(int32_t opcode); diff --git a/src/native/jit.c b/src/native/jit.c deleted file mode 100644 index 8da495db..00000000 --- a/src/native/jit.c +++ /dev/null @@ -1,377 +0,0 @@ -#include - -#include "const.h" -#include "cpu.h" -#include "global_pointers.h" -#include "jit.h" -#include "js_imports.h" -#include "log.h" -#include "profiler/profiler.h" - - -void free_wasm_table_index(uint16_t wasm_table_index) -{ -#if DEBUG - for(int32_t i = 0; i < wasm_table_index_free_list_count; i++) - { - assert(wasm_table_index_free_list[i] != wasm_table_index); - } -#endif - - assert(wasm_table_index_free_list_count < WASM_TABLE_SIZE); - wasm_table_index_free_list[wasm_table_index_free_list_count++] = wasm_table_index; - - // It is not strictly necessary to clear the function, but it will fail - // more predictably if we accidentally use the function - // XXX: This fails in Chromium: - // RangeError: WebAssembly.Table.set(): Modifying existing entry in table not supported. - //jit_clear_func(wasm_table_index); -} - -// remove the entry with the given index from the jit_cache_arr structure -void remove_jit_cache_entry(uint32_t page, int32_t addr_index) -{ - assert(addr_index != JIT_CACHE_ARRAY_NO_NEXT_ENTRY); - assert(page == (jit_cache_arr[addr_index].start_addr >> 12)); - - int32_t page_index = page_first_jit_cache_entry[page]; - bool did_remove = false; - - if(page_index == addr_index) - { - page_first_jit_cache_entry[page] = jit_cache_arr[addr_index].next_index_same_page; - did_remove = true; - } - else - { - while(page_index != JIT_CACHE_ARRAY_NO_NEXT_ENTRY) - { - int32_t next_index = jit_cache_arr[page_index].next_index_same_page; - if(next_index == addr_index) - { - jit_cache_arr[page_index].next_index_same_page = jit_cache_arr[addr_index].next_index_same_page; - did_remove = true; - break; - } - page_index = next_index; - } - } - - jit_cache_arr[addr_index].next_index_same_page = JIT_CACHE_ARRAY_NO_NEXT_ENTRY; - - assert(did_remove); -} - -// remove all entries with the given wasm_table_index from the jit_cache_arr structure -void remove_jit_cache_wasm_index(int32_t page, uint16_t wasm_table_index) -{ - int32_t cache_array_index = page_first_jit_cache_entry[page]; - - assert(cache_array_index != JIT_CACHE_ARRAY_NO_NEXT_ENTRY); - - bool pending = false; - - do - { - struct code_cache* entry = &jit_cache_arr[cache_array_index]; - int32_t next_cache_array_index = entry->next_index_same_page; - - if(entry->wasm_table_index == wasm_table_index) - { - // if one entry is pending, all must be pending - dbg_assert(!pending || entry->pending); - - pending = entry->pending; - - remove_jit_cache_entry(page, cache_array_index); - - assert(entry->next_index_same_page == JIT_CACHE_ARRAY_NO_NEXT_ENTRY); - entry->wasm_table_index = 0; - entry->start_addr = 0; - entry->pending = false; - } - - cache_array_index = next_cache_array_index; - } - while(cache_array_index != JIT_CACHE_ARRAY_NO_NEXT_ENTRY); - - if(pending) - { - assert(wasm_table_index_pending_free_count < WASM_TABLE_SIZE); - wasm_table_index_pending_free[wasm_table_index_pending_free_count++] = wasm_table_index; - } - else - { - free_wasm_table_index(wasm_table_index); - } - - if(page_first_jit_cache_entry[page] == JIT_CACHE_ARRAY_NO_NEXT_ENTRY && - page_entry_points[page][0] == ENTRY_POINT_END) - { - tlb_set_has_code(page, false); - } - -#if CHECK_JIT_CACHE_ARRAY_INVARIANTS - // sanity check that the above iteration deleted all entries - - for(int32_t i = 0; i < JIT_CACHE_ARRAY_SIZE; i++) - { - struct code_cache* entry = &jit_cache_arr[i]; - - assert(entry->wasm_table_index != wasm_table_index); - } -#endif -} - -bool find_u16(const uint16_t* array, uint16_t value, int32_t length) -{ - for(int32_t i = 0; i < length; i++) - { - if(array[i] == value) - { - return true; - } - } - - return false; -} - -__attribute__((noinline)) -void jit_clear_page(uint32_t index) -{ - assert(index < MAX_PHYSICAL_PAGES); - int32_t cache_array_index = page_first_jit_cache_entry[index]; - - assert(cache_array_index != JIT_CACHE_ARRAY_NO_NEXT_ENTRY); - - uint16_t index_to_free[100]; - int32_t index_to_free_length = 0; - - uint16_t index_to_pending_free[100]; - int32_t index_to_pending_free_length = 0; - - page_first_jit_cache_entry[index] = JIT_CACHE_ARRAY_NO_NEXT_ENTRY; - profiler_stat_increment(S_INVALIDATE_PAGE); - - do - { - profiler_stat_increment(S_INVALIDATE_CACHE_ENTRY); - struct code_cache* entry = &jit_cache_arr[cache_array_index]; - uint16_t wasm_table_index = entry->wasm_table_index; - - assert(same_page(index << DIRTY_ARR_SHIFT, entry->start_addr)); - - int32_t next_cache_array_index = entry->next_index_same_page; - - entry->next_index_same_page = JIT_CACHE_ARRAY_NO_NEXT_ENTRY; - entry->start_addr = 0; - entry->wasm_table_index = 0; - - if(entry->pending) - { - entry->pending = false; - - if(!find_u16(index_to_pending_free, wasm_table_index, index_to_pending_free_length)) - { - assert(index_to_pending_free_length < 100); - index_to_pending_free[index_to_pending_free_length++] = wasm_table_index; - } - } - else - { - if(!find_u16(index_to_free, wasm_table_index, index_to_free_length)) - { - assert(index_to_free_length < 100); - index_to_free[index_to_free_length++] = wasm_table_index; - } - } - - cache_array_index = next_cache_array_index; - } - while(cache_array_index != JIT_CACHE_ARRAY_NO_NEXT_ENTRY); - - for(int32_t i = 0; i < index_to_free_length; i++) - { - free_wasm_table_index(index_to_free[i]); - } - - for(int32_t i = 0; i < index_to_pending_free_length; i++) - { - uint16_t wasm_table_index = index_to_pending_free[i]; - assert(wasm_table_index_pending_free_count < WASM_TABLE_SIZE); - wasm_table_index_pending_free[wasm_table_index_pending_free_count++] = wasm_table_index; - } -} - -void jit_dirty_index(uint32_t index) -{ - assert(index < MAX_PHYSICAL_PAGES); - - bool did_have_code = false; - int32_t cache_array_index = page_first_jit_cache_entry[index]; - - if(cache_array_index != JIT_CACHE_ARRAY_NO_NEXT_ENTRY) - { - did_have_code = true; - jit_clear_page(index); - } - - uint16_t* entry_points = page_entry_points[index]; - - if(entry_points[0] != ENTRY_POINT_END) - { - did_have_code = true; - - // don't try to compile code in this page anymore until it's hot again - hot_code_addresses[jit_hot_hash_page(index)] = 0; - - for(int32_t i = 0; i < MAX_ENTRIES_PER_PAGE; i++) - { - if(entry_points[i] == ENTRY_POINT_END) - { - break; - } - - entry_points[i] = ENTRY_POINT_END; - } - -#if DEBUG - for(int32_t i = 0; i < MAX_ENTRIES_PER_PAGE; i++) - { - assert(entry_points[i] == ENTRY_POINT_END); - } -#endif - } - - if(did_have_code) - { - tlb_set_has_code(index, false); - } -} - -/* - * 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 index = i >> DIRTY_ARR_SHIFT; - // XXX: Should only call once per index - jit_dirty_index(index); - } -#endif -} - -void jit_dirty_cache_small(uint32_t start_addr, uint32_t end_addr) -{ -#if ENABLE_JIT - assert(start_addr <= end_addr); - - uint32_t start_index = start_addr >> DIRTY_ARR_SHIFT; - uint32_t end_index = (end_addr - 1) >> DIRTY_ARR_SHIFT; - - jit_dirty_index(start_index); - - // Note: This can't happen when paging is enabled, as writes across - // boundaries are split up on two pages - if(start_index != end_index) - { - assert(end_index == start_index + 1); - jit_dirty_index(end_index); - } -#endif -} - -void jit_dirty_cache_single(uint32_t addr) -{ -#if ENABLE_JIT - uint32_t index = addr >> DIRTY_ARR_SHIFT; - - jit_dirty_index(index); -#endif -} - -void jit_empty_cache() -{ - for(int32_t i = 0; i < JIT_CACHE_ARRAY_SIZE; i++) - { - jit_cache_arr[i].start_addr = 0; - jit_cache_arr[i].next_index_same_page = JIT_CACHE_ARRAY_NO_NEXT_ENTRY; - jit_cache_arr[i].wasm_table_index = 0; - jit_cache_arr[i].pending = false; - } - - for(int32_t i = 0; i < GROUP_DIRTINESS_LENGTH; i++) - { - page_first_jit_cache_entry[i] = JIT_CACHE_ARRAY_NO_NEXT_ENTRY; - } - - for(int32_t i = 0; i < MAX_PHYSICAL_PAGES; i++) - { - uint16_t* entry_points = page_entry_points[i]; - - for(int32_t j = 0; j < MAX_ENTRIES_PER_PAGE; j++) - { - entry_points[j] = ENTRY_POINT_END; - } - } - - for(int32_t i = 0; i < 0xFFFF; i++) - { - // don't assign 0 (XXX: Check) - wasm_table_index_free_list[i] = i + 1; - } - - wasm_table_index_free_list_count = 0xFFFF; -} - -int32_t jit_unused_cache_stat() -{ - int32_t count = 0; - - for(int32_t i = 0; i < JIT_CACHE_ARRAY_SIZE; i++) - { - struct code_cache* entry = &jit_cache_arr[i]; - int32_t phys_addr = entry->start_addr; - - if(phys_addr == 0) - { - count++; - } - } - - return count; -} - -int32_t jit_get_entry_length(int32_t i) -{ - assert(i >= 0 && i < JIT_CACHE_ARRAY_SIZE); -#if DEBUG - return jit_cache_arr[i].len; -#else - UNUSED(i); - return 0; -#endif -} - -int32_t jit_get_entry_address(int32_t i) -{ - assert(i >= 0 && i < JIT_CACHE_ARRAY_SIZE); - return jit_cache_arr[i].start_addr; -} - -int32_t jit_get_entry_pending(int32_t i) -{ - assert(i >= 0 && i < JIT_CACHE_ARRAY_SIZE); - return jit_cache_arr[i].pending; -} diff --git a/src/native/jit.h b/src/native/jit.h deleted file mode 100644 index 7f26045f..00000000 --- a/src/native/jit.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include - -void free_wasm_table_index(uint16_t wasm_table_index); -void remove_jit_cache_wasm_index(int32_t page, uint16_t wasm_table_index); - -void remove_jit_cache_entry(uint32_t page, int32_t addr_index); -void jit_dirty_cache(uint32_t start_addr, uint32_t end_addr); -void jit_dirty_cache_single(uint32_t addr); -void jit_dirty_cache_small(uint32_t start_addr, uint32_t end_addr); -void jit_empty_cache(void); diff --git a/src/native/js_imports.h b/src/native/js_imports.h index 8e0aa634..0d494eeb 100644 --- a/src/native/js_imports.h +++ b/src/native/js_imports.h @@ -25,10 +25,6 @@ extern int32_t set_cr0(int32_t); extern int32_t verr(int32_t); extern int32_t verw(int32_t); -extern void codegen_finalize(int32_t, int32_t, int32_t, int32_t, int32_t); -extern void log_uncompiled_code(int32_t, int32_t); -extern void dump_function_code(const struct basic_block* basic_block, int32_t basic_block_count, int32_t end); - extern void cpl_changed(void); extern void cpuid(void); extern void enter16(int32_t, int32_t); diff --git a/src/native/memory.c b/src/native/memory.c index d4a97f13..4cc7f325 100644 --- a/src/native/memory.c +++ b/src/native/memory.c @@ -5,11 +5,11 @@ #include "const.h" #include "global_pointers.h" -#include "jit.h" #include "js_imports.h" #include "log.h" #include "memory.h" #include "profiler/profiler.h" +#include "rust_imports.h" bool in_mapped_range(uint32_t addr) { diff --git a/src/native/misc_instr.c b/src/native/misc_instr.c index 88c5997e..2ae6cf47 100644 --- a/src/native/misc_instr.c +++ b/src/native/misc_instr.c @@ -4,7 +4,6 @@ #include #include -#include "codegen/codegen.h" #include "const.h" #include "cpu.h" #include "fpu.h" @@ -209,44 +208,6 @@ void push16(int32_t imm16) } } -void push16_reg_jit(int32_t reg) -{ - if(*stack_size_32) - { - gen_fn1_reg16("push16_ss32", 11, reg); - } - else - { - gen_fn1_reg16("push16_ss16", 11, reg); - } -} - -void push16_imm_jit(int32_t imm) -{ - if(*stack_size_32) - { - gen_fn1_const("push16_ss32", 11, imm); - } - else - { - gen_fn1_const("push16_ss16", 11, imm); - } -} - -void push16_mem_jit(int32_t modrm_byte) -{ - if(*stack_size_32) - { - gen_modrm_resolve(modrm_byte); - gen_modrm_fn0("push16_ss32_mem", 15); - } - else - { - gen_modrm_resolve(modrm_byte); - gen_modrm_fn0("push16_ss16_mem", 15); - } -} - __attribute__((always_inline)) void push32_ss16(int32_t imm32) { @@ -279,44 +240,6 @@ void push32(int32_t imm32) } } -void push32_reg_jit(int32_t reg) -{ - if(*stack_size_32) - { - gen_fn1_reg32s("push32_ss32", 11, reg); - } - else - { - gen_fn1_reg32s("push32_ss16", 11, reg); - } -} - -void push32_imm_jit(int32_t imm) -{ - if(*stack_size_32) - { - gen_fn1_const("push32_ss32", 11, imm); - } - else - { - gen_fn1_const("push32_ss16", 11, imm); - } -} - -void push32_mem_jit(int32_t modrm_byte) -{ - if(*stack_size_32) - { - gen_modrm_resolve(modrm_byte); - gen_modrm_fn0("push32_ss32_mem", 15); - } - else - { - gen_modrm_resolve(modrm_byte); - gen_modrm_fn0("push32_ss16_mem", 15); - } -} - __attribute__((always_inline)) int32_t pop16_ss16() { @@ -350,18 +273,6 @@ int32_t pop16() } } -void pop16_reg_jit(int32_t reg) -{ - if(*stack_size_32) - { - gen_set_reg16_fn0("pop16_ss32", 10, reg); - } - else - { - gen_set_reg16_fn0("pop16_ss16", 10, reg); - } -} - __attribute__((always_inline)) int32_t pop32s_ss16() { @@ -393,18 +304,6 @@ int32_t pop32s() } } -void pop32s_reg_jit(int32_t reg) -{ - if(*stack_size_32) - { - gen_set_reg32s_fn0("pop32s_ss32", 11, reg); - } - else - { - gen_set_reg32s_fn0("pop32s_ss16", 11, reg); - } -} - void pusha16() { uint16_t temp = reg16[SP]; diff --git a/src/native/misc_instr.h b/src/native/misc_instr.h index 046c5343..1e12adeb 100644 --- a/src/native/misc_instr.h +++ b/src/native/misc_instr.h @@ -45,28 +45,24 @@ void cmovcc16(bool condition, int32_t value, int32_t r); void cmovcc32(bool condition, int32_t value, int32_t r); int32_t get_stack_pointer(int32_t offset); void adjust_stack_reg(int32_t adjustment); + void push16_ss16(int32_t imm16); void push16_ss32(int32_t imm16); void push16_ss16_mem(int32_t addr); void push16_ss32_mem(int32_t addr); void push16(int32_t imm16); -void push16_reg_jit(int32_t reg); -void push16_imm_jit(int32_t imm); -void push16_mem_jit(int32_t modrm_byte); + void push32_ss16(int32_t imm32); void push32_ss32(int32_t imm32); void push32_ss16_mem(int32_t addr); void push32_ss32_mem(int32_t addr); void push32(int32_t imm32); -void push32_reg_jit(int32_t reg); -void push32_imm_jit(int32_t imm); -void push32_mem_jit(int32_t modrm_byte); + int32_t pop16(void); -void pop16_reg_jit(int32_t reg); int32_t pop32_ss16(void); int32_t pop32_ss32(void); int32_t pop32s(void); -void pop32s_reg_jit(int32_t reg); + void pusha16(void); void pusha32(void); void setcc_reg(bool condition, int32_t r); diff --git a/src/native/profiler/opstats.c b/src/native/profiler/opstats.c deleted file mode 100644 index bd881d98..00000000 --- a/src/native/profiler/opstats.c +++ /dev/null @@ -1,82 +0,0 @@ -#include -#include -#include - -#include "../codegen/codegen.h" -#include "../shared.h" - -#if ENABLE_PROFILER_OPSTATS - -static struct { - uint32_t opcode[0x100]; - uint32_t opcode_0f[0x100]; -} opstats_buffer = { - .opcode = { 0 }, - .opcode_0f = { 0 }, -}; - -#endif - -void gen_opstats(uint32_t instruction) -{ -#if ENABLE_PROFILER_OPSTATS - bool is_0f = false; - - for(int32_t i = 0; i < 4; i++) - { - int32_t opcode = instruction & 0xFF; - instruction >>= 8; - - // TODO: - // - If instruction depends on middle bits of modrm_byte, split - // - Split depending on memory or register variant - // - If the instruction uses 4 or more prefixes, only the prefixes will be counted - - if(is_0f) - { - gen_increment_mem32((int32_t)&opstats_buffer.opcode_0f[opcode]); - break; - } - else - { - gen_increment_mem32((int32_t)&opstats_buffer.opcode[opcode]); - - if(opcode == 0x0F) - { - is_0f = true; - } - else if(opcode == 0x26 || opcode == 0x2E || opcode == 0x36 || opcode == 0x3E || - opcode == 0x64 || opcode == 0x65 || opcode == 0x66 || opcode == 0x67 || - opcode == 0xF0 || opcode == 0xF2 || opcode == 0xF3) - { - // prefix - } - else - { - break; - } - } - } -#else - UNUSED(instruction); -#endif -} - -int32_t get_opstats_buffer(int32_t index) -{ - assert(index >= 0 && index < 0x200); - -#if ENABLE_PROFILER_OPSTATS - if(index < 0x100) - { - return opstats_buffer.opcode[index]; - } - else - { - return opstats_buffer.opcode_0f[index - 0x100]; - } -#else - UNUSED(index); - return 0; -#endif -} diff --git a/src/native/profiler/opstats.h b/src/native/profiler/opstats.h deleted file mode 100644 index e8086add..00000000 --- a/src/native/profiler/opstats.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once -#include - -void gen_opstats(uint32_t instruction); -int32_t get_opstats_buffer(int32_t index); diff --git a/src/native/profiler/profiler.h b/src/native/profiler/profiler.h index 4e568131..8a6fdb79 100644 --- a/src/native/profiler/profiler.h +++ b/src/native/profiler/profiler.h @@ -15,7 +15,7 @@ enum stat_name { S_RUN_INTERPRETED, S_RUN_INTERPRETED_PENDING, S_RUN_INTERPRETED_NEAR_END_OF_PAGE, - S_RUN_INTERPRETED_NOT_HOT, + S_RUN_INTERPRETED_DIFFERENT_STATE, S_RUN_INTERPRETED_STEPS, S_RUN_FROM_CACHE, diff --git a/src/native/rust_imports.h b/src/native/rust_imports.h new file mode 100644 index 00000000..61dd4529 --- /dev/null +++ b/src/native/rust_imports.h @@ -0,0 +1,17 @@ +#pragma once + +#include "cpu.h" +#include + +uint32_t jit_find_cache_entry(uint32_t phys_addr, cached_state_flags flags); +void jit_increase_hotness_and_maybe_compile(uint32_t phys_addr, uint32_t cs_offset, cached_state_flags flags); + +void jit_dirty_cache_single(uint32_t phys_addr); +void jit_dirty_cache_small(uint32_t phys_start_addr, uint32_t phys_end_addr); + +bool jit_page_has_code(uint32_t physical_page); + +uint32_t jit_unused_cache_stat(void); +uint32_t jit_get_entry_length(int32_t i); +uint32_t jit_get_entry_address(int32_t i); +bool jit_get_entry_pending(int32_t i); diff --git a/src/native/shared.h b/src/native/shared.h index fe4a243c..b64bb652 100644 --- a/src/native/shared.h +++ b/src/native/shared.h @@ -6,13 +6,4 @@ #define UNUSED(x) (void)(x) -static inline size_t strlen(const char *str) -{ - const char *s; - - for (s = str; *s; ++s) {} - - return (s - str); -} - void *memset(void *dest, int c, size_t n); diff --git a/src/rust/analysis.rs b/src/rust/analysis.rs new file mode 100644 index 00000000..38506dca --- /dev/null +++ b/src/rust/analysis.rs @@ -0,0 +1,96 @@ +#![allow(non_snake_case)] + +use cpu_context::CpuContext; +use prefix::{PREFIX_66, PREFIX_67, PREFIX_F2, PREFIX_F3}; +use regs::{CS, DS, ES, FS, GS, SS}; + +#[derive(PartialEq, Eq)] +pub enum AnalysisType { + Normal, + BlockBoundary, + Jump { + offset: i32, + is_32: bool, + condition: Option, + }, +} + +pub struct Analysis { + pub no_next_instruction: bool, + pub ty: AnalysisType, +} + +pub fn analyze_step(mut cpu: &mut CpuContext) -> Analysis { + let mut analysis = Analysis { + no_next_instruction: false, + ty: AnalysisType::Normal, + }; + cpu.prefixes = 0; + let opcode = cpu.read_imm8() as u32 | (cpu.osize_32() as u32) << 8; + ::gen::analyzer::analyzer(opcode, &mut cpu, &mut analysis); + analysis +} + +pub fn analyze_step_handle_prefix(cpu: &mut CpuContext, analysis: &mut Analysis) { + ::gen::analyzer::analyzer( + cpu.read_imm8() as u32 | (cpu.osize_32() as u32) << 8, + cpu, + analysis, + ) +} +pub fn analyze_step_handle_segment_prefix( + segment: u32, + cpu: &mut CpuContext, + analysis: &mut Analysis, +) { + assert!(segment <= 5); + cpu.prefixes |= segment + 1; + analyze_step_handle_prefix(cpu, analysis) +} + +pub fn instr16_0F_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) { + ::gen::analyzer0f_16::analyzer(cpu.read_imm8(), cpu, analysis) +} +pub fn instr32_0F_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) { + ::gen::analyzer0f_32::analyzer(cpu.read_imm8(), cpu, analysis) +} +pub fn instr_26_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) { + analyze_step_handle_segment_prefix(ES, cpu, analysis) +} +pub fn instr_2E_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) { + analyze_step_handle_segment_prefix(CS, cpu, analysis) +} +pub fn instr_36_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) { + analyze_step_handle_segment_prefix(SS, cpu, analysis) +} +pub fn instr_3E_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) { + analyze_step_handle_segment_prefix(DS, cpu, analysis) +} +pub fn instr_64_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) { + analyze_step_handle_segment_prefix(FS, cpu, analysis) +} +pub fn instr_65_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) { + analyze_step_handle_segment_prefix(GS, cpu, analysis) +} +pub fn instr_66_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) { + cpu.prefixes |= PREFIX_66; + analyze_step_handle_prefix(cpu, analysis) +} +pub fn instr_67_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) { + cpu.prefixes |= PREFIX_67; + analyze_step_handle_prefix(cpu, analysis) +} +pub fn instr_F0_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) { + // lock: Ignored + analyze_step_handle_prefix(cpu, analysis) +} +pub fn instr_F2_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) { + cpu.prefixes |= PREFIX_F2; + analyze_step_handle_prefix(cpu, analysis) +} +pub fn instr_F3_analyze(cpu: &mut CpuContext, analysis: &mut Analysis) { + cpu.prefixes |= PREFIX_F3; + analyze_step_handle_prefix(cpu, analysis) +} + +pub fn modrm_analyze(ctx: &mut CpuContext, modrm_byte: u8) { ::modrm::skip(ctx, modrm_byte); } diff --git a/src/rust/c_api.rs b/src/rust/c_api.rs new file mode 100644 index 00000000..d819a873 --- /dev/null +++ b/src/rust/c_api.rs @@ -0,0 +1,132 @@ +use std::mem; +use std::ptr::NonNull; + +use jit::{cached_code, JitState}; +use page::Page; +use state_flags::CachedStateFlags; + +static mut MODULE_PTR: NonNull = + unsafe { NonNull::new_unchecked(mem::align_of::() as *mut _) }; + +fn get_module<'a>() -> &'a mut JitState { unsafe { MODULE_PTR.as_mut() } } + +#[no_mangle] +/// Called from JS, not C +pub fn rust_setup() { + let x = Box::new(JitState::create_and_initialise()); + unsafe { + MODULE_PTR = NonNull::new(Box::into_raw(x)).expect("assigning module ptr"); + } + + use std::panic; + + panic::set_hook(Box::new(|panic_info| { + if let Some(location) = panic_info.location() { + dbg_log!( + "panic occurred in file '{}' at line {}", + location.file(), + location.line() + ); + } + else { + dbg_log!("panic occurred but can't get location information..."); + } + })); +} + +#[no_mangle] +pub fn jit_find_cache_entry(phys_address: u32, state_flags: u32) -> u32 { + let cached_code { + wasm_table_index, + initial_state, + } = ::jit::jit_find_cache_entry(phys_address, CachedStateFlags::of_u32(state_flags)); + wasm_table_index as u32 | (initial_state as u32) << 16 +} + +#[no_mangle] +/// Called from JS, not C +pub fn codegen_finalize_finished( + wasm_table_index: u16, + phys_addr: u32, + end_addr: u32, + first_opcode: u32, + state_flags: u32, +) { + ::jit::codegen_finalize_finished( + get_module(), + wasm_table_index, + phys_addr, + end_addr, + first_opcode, + CachedStateFlags::of_u32(state_flags), + ) +} + +#[no_mangle] +pub fn jit_increase_hotness_and_maybe_compile(phys_address: u32, cs_offset: u32, state_flags: u32) { + ::jit::jit_increase_hotness_and_maybe_compile( + get_module(), + phys_address, + cs_offset, + CachedStateFlags::of_u32(state_flags), + ) +} + +#[no_mangle] +#[cfg(debug_assertions)] +pub fn jit_force_generate_unsafe(phys_addr: u32, cs_offset: u32, state_flags: u32) { + ::jit::jit_force_generate_unsafe( + get_module(), + phys_addr, + cs_offset, + CachedStateFlags::of_u32(state_flags), + ) +} + +#[no_mangle] +pub fn jit_dirty_cache(start_addr: u32, end_addr: u32) { + ::jit::jit_dirty_cache(get_module(), start_addr, end_addr); +} + +#[no_mangle] +pub fn jit_dirty_cache_small(start_addr: u32, end_addr: u32) { + ::jit::jit_dirty_cache_small(get_module(), start_addr, end_addr); +} + +#[no_mangle] +pub fn jit_dirty_cache_single(addr: u32) { ::jit::jit_dirty_cache_single(get_module(), addr); } + +#[no_mangle] +pub fn jit_page_has_code(page: u32) -> bool { + ::jit::jit_page_has_code(get_module(), Page::page_of(page << 12)) +} + +#[no_mangle] +/// Called from JS, not C +pub fn jit_empty_cache() { ::jit::jit_empty_cache(get_module()) } + +#[no_mangle] +/// Called from JS, not C +pub fn jit_get_op_ptr() -> *const u8 { ::jit::jit_get_op_ptr(get_module()) } + +#[no_mangle] +/// Called from JS, not C +pub fn jit_get_op_len() -> u32 { ::jit::jit_get_op_len(get_module()) } + +#[no_mangle] +#[cfg(debug_assertions)] +pub fn jit_unused_cache_stat() -> u32 { ::jit::jit_unused_cache_stat() } +#[no_mangle] +#[cfg(debug_assertions)] +pub fn jit_get_entry_length(i: u32) -> u32 { ::jit::jit_get_entry_length(i) } +#[no_mangle] +#[cfg(debug_assertions)] +pub fn jit_get_entry_address(i: u32) -> u32 { ::jit::jit_get_entry_address(i) } +#[no_mangle] +#[cfg(debug_assertions)] +pub fn jit_get_entry_pending(i: u32) -> bool { ::jit::jit_get_entry_pending(i) } +#[no_mangle] +#[cfg(debug_assertions)] +pub fn jit_get_wasm_table_index_free_list_count() -> u32 { + ::jit::jit_get_wasm_table_index_free_list_count(get_module()) +} diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs new file mode 100644 index 00000000..4d4d1c40 --- /dev/null +++ b/src/rust/codegen.rs @@ -0,0 +1,382 @@ +use global_pointers; +use jit::JitContext; +use jit::{GEN_LOCAL_SCRATCH0, GEN_LOCAL_SCRATCH1, GEN_LOCAL_SCRATCH2}; +use modrm; +use tlb::{TLB_GLOBAL, TLB_NO_USER, TLB_READONLY, TLB_VALID}; +use wasmgen::module_init::WasmBuilder; +use wasmgen::{module_init, wasm_util}; + +pub fn gen_set_previous_eip_offset_from_eip(builder: &mut WasmBuilder, n: u32) { + let cs = &mut builder.code_section; + wasm_util::push_i32(cs, global_pointers::PREVIOUS_IP as i32); // store address of previous ip + wasm_util::load_aligned_i32(cs, global_pointers::INSTRUCTION_POINTER); // load ip + if n != 0 { + wasm_util::push_i32(cs, n as i32); + wasm_util::add_i32(cs); // add constant to ip value + } + wasm_util::store_aligned_i32(cs); // store it as previous ip +} + +pub fn gen_increment_instruction_pointer(builder: &mut WasmBuilder, n: u32) { + let cs = &mut builder.code_section; + wasm_util::push_i32(cs, global_pointers::INSTRUCTION_POINTER as i32); // store address of ip + + wasm_util::load_aligned_i32(cs, global_pointers::INSTRUCTION_POINTER); // load ip + + wasm_util::push_i32(cs, n as i32); + + wasm_util::add_i32(cs); + wasm_util::store_aligned_i32(cs); // store it back in +} + +pub fn gen_set_previous_eip(builder: &mut WasmBuilder) { + let cs = &mut builder.code_section; + wasm_util::push_i32(cs, global_pointers::PREVIOUS_IP as i32); // store address of previous ip + wasm_util::load_aligned_i32(cs, global_pointers::INSTRUCTION_POINTER); // load ip + wasm_util::store_aligned_i32(cs); // store it as previous ip +} + +pub fn gen_relative_jump(builder: &mut WasmBuilder, n: i32) { + // add n to instruction_pointer (without setting the offset as above) + let instruction_body = &mut builder.instruction_body; + wasm_util::push_i32( + instruction_body, + global_pointers::INSTRUCTION_POINTER as i32, + ); + wasm_util::load_aligned_i32(instruction_body, global_pointers::INSTRUCTION_POINTER); + wasm_util::push_i32(instruction_body, n); + wasm_util::add_i32(instruction_body); + wasm_util::store_aligned_i32(instruction_body); +} + +pub fn gen_increment_variable(builder: &mut WasmBuilder, variable_address: u32, n: i32) { + wasm_util::increment_variable(&mut builder.code_section, variable_address, n); +} + +pub fn gen_increment_timestamp_counter(builder: &mut WasmBuilder, n: i32) { + gen_increment_variable(builder, global_pointers::TIMESTAMP_COUNTER, n); +} + +pub fn gen_increment_mem32(builder: &mut WasmBuilder, addr: u32) { + wasm_util::increment_mem32(&mut builder.code_section, addr) +} + +pub fn gen_fn0_const(ctx: &mut JitContext, name: &str) { + let builder = &mut ctx.builder; + let fn_idx = builder.get_fn_idx(name, module_init::FN0_TYPE_INDEX); + wasm_util::call_fn(&mut builder.instruction_body, fn_idx); +} + +pub fn gen_fn0_const_ret(builder: &mut WasmBuilder, name: &str) { + let fn_idx = builder.get_fn_idx(name, module_init::FN0_RET_TYPE_INDEX); + wasm_util::call_fn(&mut builder.instruction_body, fn_idx); +} + +pub fn gen_fn1_const(ctx: &mut JitContext, name: &str, arg0: u32) { + let builder = &mut ctx.builder; + let fn_idx = builder.get_fn_idx(name, module_init::FN1_TYPE_INDEX); + wasm_util::push_i32(&mut builder.instruction_body, arg0 as i32); + wasm_util::call_fn(&mut builder.instruction_body, fn_idx); +} + +pub fn gen_call_fn1_ret(builder: &mut WasmBuilder, name: &str) { + // generates: fn( _ ) where _ must be left on the stack before calling this, and fn returns a value + let fn_idx = builder.get_fn_idx(name, module_init::FN1_RET_TYPE_INDEX); + wasm_util::call_fn(&mut builder.instruction_body, fn_idx); +} + +pub fn gen_fn2_const(ctx: &mut JitContext, name: &str, arg0: u32, arg1: u32) { + let builder = &mut ctx.builder; + let fn_idx = builder.get_fn_idx(name, module_init::FN2_TYPE_INDEX); + wasm_util::push_i32(&mut builder.instruction_body, arg0 as i32); + wasm_util::push_i32(&mut builder.instruction_body, arg1 as i32); + wasm_util::call_fn(&mut builder.instruction_body, fn_idx); +} + +pub fn gen_call_fn2(builder: &mut WasmBuilder, name: &str) { + // generates: fn( _, _ ) where _ must be left on the stack before calling this + let fn_idx = builder.get_fn_idx(name, module_init::FN2_TYPE_INDEX); + wasm_util::call_fn(&mut builder.instruction_body, fn_idx); +} + +pub fn gen_fn3_const(ctx: &mut JitContext, name: &str, arg0: u32, arg1: u32, arg2: u32) { + let builder = &mut ctx.builder; + let fn_idx = builder.get_fn_idx(name, module_init::FN3_TYPE_INDEX); + wasm_util::push_i32(&mut builder.instruction_body, arg0 as i32); + wasm_util::push_i32(&mut builder.instruction_body, arg1 as i32); + wasm_util::push_i32(&mut builder.instruction_body, arg2 as i32); + wasm_util::call_fn(&mut builder.instruction_body, fn_idx); +} + +pub fn gen_modrm_fn0(ctx: &mut JitContext, name: &str) { + // generates: fn( _ ) + let builder = &mut ctx.builder; + let fn_idx = builder.get_fn_idx(name, module_init::FN1_TYPE_INDEX); + wasm_util::call_fn(&mut builder.instruction_body, fn_idx); +} + +pub fn gen_modrm_fn1(ctx: &mut JitContext, name: &str, arg0: u32) { + // generates: fn( _, arg0 ) + let builder = &mut ctx.builder; + let fn_idx = builder.get_fn_idx(name, module_init::FN2_TYPE_INDEX); + wasm_util::push_i32(&mut builder.instruction_body, arg0 as i32); + wasm_util::call_fn(&mut builder.instruction_body, fn_idx); +} + +pub fn gen_modrm_fn2(ctx: &mut JitContext, name: &str, arg0: u32, arg1: u32) { + // generates: fn( _, arg0, arg1 ) + let builder = &mut ctx.builder; + let fn_idx = builder.get_fn_idx(name, module_init::FN3_TYPE_INDEX); + wasm_util::push_i32(&mut builder.instruction_body, arg0 as i32); + wasm_util::push_i32(&mut builder.instruction_body, arg1 as i32); + wasm_util::call_fn(&mut builder.instruction_body, fn_idx); +} + +pub fn gen_modrm_resolve(ctx: &mut JitContext, modrm_byte: u8) { modrm::gen(ctx, modrm_byte) } + +pub fn gen_set_reg16_r(ctx: &mut JitContext, dest: u32, src: u32) { + // generates: reg16[r_dest] = reg16[r_src] + let builder = &mut ctx.builder; + wasm_util::push_i32( + &mut builder.instruction_body, + global_pointers::get_reg16_offset(dest) as i32, + ); + wasm_util::load_aligned_u16( + &mut builder.instruction_body, + global_pointers::get_reg16_offset(src), + ); + wasm_util::store_aligned_u16(&mut builder.instruction_body); +} +pub fn gen_set_reg32_r(ctx: &mut JitContext, dest: u32, src: u32) { + // generates: reg32s[r_dest] = reg32s[r_src] + let builder = &mut ctx.builder; + wasm_util::push_i32( + &mut builder.instruction_body, + global_pointers::get_reg32_offset(dest) as i32, + ); + wasm_util::load_aligned_i32( + &mut builder.instruction_body, + global_pointers::get_reg32_offset(src), + ); + wasm_util::store_aligned_i32(&mut builder.instruction_body); +} + +pub fn gen_set_reg16_fn0(ctx: &mut JitContext, name: &str, reg: u32) { + // generates: reg16[reg] = fn() + let builder = &mut ctx.builder; + let fn_idx = builder.get_fn_idx(name, module_init::FN0_RET_TYPE_INDEX); + wasm_util::push_i32( + &mut builder.instruction_body, + global_pointers::get_reg16_offset(reg) as i32, + ); + wasm_util::call_fn(&mut builder.instruction_body, fn_idx); + wasm_util::store_aligned_u16(&mut builder.instruction_body); +} + +pub fn gen_set_reg32s_fn0(ctx: &mut JitContext, name: &str, reg: u32) { + // generates: reg32s[reg] = fn() + let builder = &mut ctx.builder; + let fn_idx = builder.get_fn_idx(name, module_init::FN0_RET_TYPE_INDEX); + wasm_util::push_i32( + &mut builder.instruction_body, + global_pointers::get_reg32_offset(reg) as i32, + ); + wasm_util::call_fn(&mut builder.instruction_body, fn_idx); + wasm_util::store_aligned_i32(&mut builder.instruction_body); +} + +pub fn gen_safe_read32(ctx: &mut JitContext) { + // Assumes virtual address has been pushed to the stack, and generates safe_read32s' fast-path + // inline, bailing to safe_read32s_slow if necessary + let builder = &mut ctx.builder; + //let instruction_body = &mut ctx.builder.instruction_body; + //let cpu = &mut ctx.cpu; + + let address_local = GEN_LOCAL_SCRATCH0; + wasm_util::tee_local(&mut builder.instruction_body, address_local); + + // Pseudo: base_on_stack = (uint32_t)address >> 12; + wasm_util::push_i32(&mut builder.instruction_body, 12); + wasm_util::shr_u32(&mut builder.instruction_body); + + // scale index + wasm_util::push_i32(&mut builder.instruction_body, 2); + wasm_util::shl_i32(&mut builder.instruction_body); + + // Pseudo: entry = tlb_data[base_on_stack]; + let entry_local = GEN_LOCAL_SCRATCH1; + wasm_util::load_aligned_i32_from_stack( + &mut builder.instruction_body, + global_pointers::TLB_DATA, + ); + wasm_util::tee_local(&mut builder.instruction_body, entry_local); + + // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && + // (address & 0xFFF) <= (0x1000 - 4)); + wasm_util::push_i32( + &mut builder.instruction_body, + (0xFFF & !TLB_READONLY & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) + as i32, + ); + wasm_util::and_i32(&mut builder.instruction_body); + + wasm_util::push_i32(&mut builder.instruction_body, TLB_VALID as i32); + wasm_util::eq_i32(&mut builder.instruction_body); + + wasm_util::get_local(&mut builder.instruction_body, address_local); + wasm_util::push_i32(&mut builder.instruction_body, 0xFFF); + wasm_util::and_i32(&mut builder.instruction_body); + wasm_util::push_i32(&mut builder.instruction_body, 0x1000 - 4); + wasm_util::le_i32(&mut builder.instruction_body); + + wasm_util::and_i32(&mut builder.instruction_body); + + // Pseudo: + // if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]); + wasm_util::if_i32(&mut builder.instruction_body); + wasm_util::get_local(&mut builder.instruction_body, entry_local); + wasm_util::push_i32(&mut builder.instruction_body, !0xFFF); + wasm_util::and_i32(&mut builder.instruction_body); + wasm_util::get_local(&mut builder.instruction_body, address_local); + wasm_util::xor_i32(&mut builder.instruction_body); + + wasm_util::load_unaligned_i32_from_stack( + &mut builder.instruction_body, + global_pointers::MEMORY, + ); + + // Pseudo: + // else { leave_on_stack(safe_read32s_slow(address)); } + wasm_util::else_(&mut builder.instruction_body); + wasm_util::get_local(&mut builder.instruction_body, address_local); + gen_call_fn1_ret(builder, "safe_read32s_slow"); + wasm_util::block_end(&mut builder.instruction_body); +} + +pub fn gen_safe_write32(ctx: &mut JitContext, local_for_address: u32, local_for_value: u32) { + // Generates safe_write32' fast-path inline, bailing to safe_write32_slow if necessary. + + // local_for_{address,value} are the numbers of the local variables which contain the virtual + // address and value for safe_write32 + // Usage: + // set_local(0, value); + // set_local(1, v_addr); + // gen_safe_write32(0, 1); + + // Since this function clobbers other variables, we confirm that the caller uses the local + // variables we expect them to + assert!(local_for_address == GEN_LOCAL_SCRATCH0); + assert!(local_for_value == GEN_LOCAL_SCRATCH1); + + let builder = &mut ctx.builder; + //let instruction_body = &mut ctx.builder.instruction_body; + //let cpu = &mut ctx.cpu; + + wasm_util::get_local(&mut builder.instruction_body, local_for_address); + + // Pseudo: base_on_stack = (uint32_t)address >> 12; + wasm_util::push_i32(&mut builder.instruction_body, 12); + wasm_util::shr_u32(&mut builder.instruction_body); + + // scale index + wasm_util::push_i32(&mut builder.instruction_body, 2); + wasm_util::shl_i32(&mut builder.instruction_body); + + // entry_local is only used in the following block, so the scratch variable can be reused later + { + // Pseudo: entry = tlb_data[base_on_stack]; + let entry_local = GEN_LOCAL_SCRATCH2; + wasm_util::load_aligned_i32_from_stack( + &mut builder.instruction_body, + global_pointers::TLB_DATA, + ); + wasm_util::tee_local(&mut builder.instruction_body, entry_local); + + // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && + // (address & 0xFFF) <= (0x1000 - 4)); + wasm_util::push_i32( + &mut builder.instruction_body, + (0xFFF & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32, + ); + wasm_util::and_i32(&mut builder.instruction_body); + + wasm_util::push_i32(&mut builder.instruction_body, TLB_VALID as i32); + wasm_util::eq_i32(&mut builder.instruction_body); + + wasm_util::get_local(&mut builder.instruction_body, local_for_address); + wasm_util::push_i32(&mut builder.instruction_body, 0xFFF); + wasm_util::and_i32(&mut builder.instruction_body); + wasm_util::push_i32(&mut builder.instruction_body, 0x1000 - 4); + wasm_util::le_i32(&mut builder.instruction_body); + + wasm_util::and_i32(&mut builder.instruction_body); + + // Pseudo: + // if(can_use_fast_path) + // { + // phys_addr = entry & ~0xFFF ^ address; + wasm_util::if_void(&mut builder.instruction_body); + + wasm_util::get_local(&mut builder.instruction_body, entry_local); + wasm_util::push_i32(&mut builder.instruction_body, !0xFFF); + wasm_util::and_i32(&mut builder.instruction_body); + wasm_util::get_local(&mut builder.instruction_body, local_for_address); + wasm_util::xor_i32(&mut builder.instruction_body); + } + + // entry_local isn't needed anymore, so we overwrite it + let phys_addr_local = GEN_LOCAL_SCRATCH2; + // Pseudo: + // /* continued within can_use_fast_path branch */ + // mem8[phys_addr] = value; + + wasm_util::tee_local(&mut builder.instruction_body, phys_addr_local); + wasm_util::get_local(&mut builder.instruction_body, local_for_value); + wasm_util::store_unaligned_i32(&mut builder.instruction_body, global_pointers::MEMORY); + + // Pseudo: + // else { safe_read32_slow(address, value); } + wasm_util::else_(&mut builder.instruction_body); + wasm_util::get_local(&mut builder.instruction_body, local_for_address); + wasm_util::get_local(&mut builder.instruction_body, local_for_value); + gen_call_fn2(builder, "safe_write32_slow"); + wasm_util::block_end(&mut builder.instruction_body); +} + +pub fn gen_fn1_reg16(ctx: &mut JitContext, name: &str, r: u32) { + let fn_idx = ctx.builder.get_fn_idx(name, module_init::FN1_TYPE_INDEX); + wasm_util::load_aligned_u16( + &mut ctx.builder.instruction_body, + global_pointers::get_reg16_offset(r), + ); + wasm_util::call_fn(&mut ctx.builder.instruction_body, fn_idx) +} + +pub fn gen_fn1_reg32(ctx: &mut JitContext, name: &str, r: u32) { + let fn_idx = ctx.builder.get_fn_idx(name, module_init::FN1_TYPE_INDEX); + wasm_util::load_aligned_i32( + &mut ctx.builder.instruction_body, + global_pointers::get_reg32_offset(r), + ); + wasm_util::call_fn(&mut ctx.builder.instruction_body, fn_idx) +} + +pub fn gen_clear_prefixes(ctx: &mut JitContext) { + let instruction_body = &mut ctx.builder.instruction_body; + wasm_util::push_i32(instruction_body, global_pointers::PREFIXES as i32); // load address of prefixes + wasm_util::push_i32(instruction_body, 0); + wasm_util::store_aligned_i32(instruction_body); +} + +pub fn gen_add_prefix_bits(ctx: &mut JitContext, mask: u32) { + assert!(mask < 0x100); + + let instruction_body = &mut ctx.builder.instruction_body; + wasm_util::push_i32(instruction_body, global_pointers::PREFIXES as i32); // load address of prefixes + + wasm_util::load_aligned_i32(instruction_body, global_pointers::PREFIXES); // load old value + wasm_util::push_i32(instruction_body, mask as i32); + wasm_util::or_i32(instruction_body); + + wasm_util::store_aligned_i32(instruction_body); +} diff --git a/src/rust/cpu.rs b/src/rust/cpu.rs new file mode 100644 index 00000000..03fc37b6 --- /dev/null +++ b/src/rust/cpu.rs @@ -0,0 +1,50 @@ +// TODO: Make this an instance, so we can plug in a fake cpu + +use page::Page; +use state_flags::CachedStateFlags; + +mod unsafe_cpu { + extern "C" { + pub fn tlb_set_has_code(physical_page: u32, has_code: bool); + pub fn read8(addr: u32) -> u8; + pub fn read16(addr: u32) -> u16; + pub fn read32(addr: u32) -> u32; + pub fn check_tlb_invariants(); + + pub fn codegen_finalize( + wasm_table_index: u16, + phys_addr: u32, + end_addr: u32, + first_opcode: u32, + state_flags: u32, + ); + } +} + +pub fn read8(addr: u32) -> u8 { unsafe { unsafe_cpu::read8(addr) } } +pub fn read16(addr: u32) -> u16 { unsafe { unsafe_cpu::read16(addr) } } +pub fn read32(addr: u32) -> u32 { unsafe { unsafe_cpu::read32(addr) } } + +pub fn tlb_set_has_code(physical_page: Page, has_code: bool) { + unsafe { unsafe_cpu::tlb_set_has_code(physical_page.to_u32(), has_code) } +} + +pub fn check_tlb_invariants() { unsafe { unsafe_cpu::check_tlb_invariants() } } + +pub fn codegen_finalize( + wasm_table_index: u16, + phys_addr: u32, + end_addr: u32, + first_opcode: u32, + state_flags: CachedStateFlags, +) { + unsafe { + unsafe_cpu::codegen_finalize( + wasm_table_index, + phys_addr, + end_addr, + first_opcode, + state_flags.to_u32(), + ) + } +} diff --git a/src/rust/cpu_context.rs b/src/rust/cpu_context.rs new file mode 100644 index 00000000..e0f7e1b7 --- /dev/null +++ b/src/rust/cpu_context.rs @@ -0,0 +1,74 @@ +use cpu; +use prefix::{PREFIX_MASK_ADDRSIZE, PREFIX_MASK_OPSIZE}; +use state_flags::CachedStateFlags; + +#[derive(Clone)] +pub struct CpuContext { + pub eip: u32, + pub prefixes: u32, + pub cs_offset: u32, + pub state_flags: CachedStateFlags, +} + +impl CpuContext { + pub fn advance8(&mut self) { + assert!(self.eip & 0xFFF < 0xFFF); + self.eip += 1; + } + pub fn advance16(&mut self) { + assert!(self.eip & 0xFFF < 0xFFE); + self.eip += 2; + } + pub fn advance32(&mut self) { + assert!(self.eip & 0xFFF < 0xFFC); + self.eip += 4; + } + #[allow(unused)] + pub fn advance_moffs(&mut self) { + if self.asize_32() { + self.advance32() + } + else { + self.advance16() + } + } + + pub fn read_imm8(&mut self) -> u8 { + assert!(self.eip & 0xFFF < 0xFFF); + let v = cpu::read8(self.eip); + self.eip += 1; + v + } + pub fn read_imm8s(&mut self) -> i8 { self.read_imm8() as i8 } + pub fn read_imm16(&mut self) -> u16 { + assert!(self.eip & 0xFFF < 0xFFE); + let v = cpu::read16(self.eip); + self.eip += 2; + v + } + pub fn read_imm16s(&mut self) -> i16 { self.read_imm16() as i16 } + pub fn read_imm32(&mut self) -> u32 { + assert!(self.eip & 0xFFF < 0xFFC); + let v = cpu::read32(self.eip); + self.eip += 4; + v + } + pub fn read_moffs(&mut self) -> u32 { + if self.asize_32() { + self.read_imm32() + } + else { + self.read_imm16() as u32 + } + } + + pub fn cpl3(&self) -> bool { self.state_flags.cpl3() } + pub fn has_flat_segmentation(&self) -> bool { self.state_flags.has_flat_segmentation() } + pub fn osize_32(&self) -> bool { + self.state_flags.is_32() != (self.prefixes & PREFIX_MASK_OPSIZE != 0) + } + pub fn asize_32(&self) -> bool { + self.state_flags.is_32() != (self.prefixes & PREFIX_MASK_ADDRSIZE != 0) + } + pub fn ssize_32(&self) -> bool { self.state_flags.ssize_32() } +} diff --git a/src/rust/dbg.rs b/src/rust/dbg.rs index f42f790e..f507b94d 100644 --- a/src/rust/dbg.rs +++ b/src/rust/dbg.rs @@ -19,19 +19,23 @@ macro_rules! dbg_assert { #[allow(unused_macros)] macro_rules! dbg_log { ($fmt:expr) => { - use ::util::{ DEBUG, _log_to_js_console }; - if DEBUG { _log_to_js_console($fmt); } + { + use ::util::{ DEBUG, _log_to_js_console }; + if DEBUG { _log_to_js_console($fmt); } + } }; ($fmt:expr, $($arg:tt)*) => { - use ::util::{ DEBUG, _log_to_js_console }; - if DEBUG { _log_to_js_console(format!($fmt, $($arg)*)); } + { + use ::util::{ DEBUG, _log_to_js_console }; + if DEBUG { _log_to_js_console(format!($fmt, $($arg)*)); } + } }; } #[cfg(target_arch = "wasm32")] #[allow(unused_macros)] macro_rules! dbg_assert { - ($cond:expr) => { + ($cond:expr) => {{ use util::{_log_to_js_console, abort, DEBUG}; if DEBUG && !$cond { _log_to_js_console(format!( @@ -45,8 +49,8 @@ macro_rules! dbg_assert { abort(); } } - }; - ($cond:expr, $desc:expr) => { + }}; + ($cond:expr, $desc:expr) => {{ use util::{_log_to_js_console, abort, DEBUG}; if DEBUG && !$cond { _log_to_js_console(format!( @@ -61,5 +65,5 @@ macro_rules! dbg_assert { abort(); } } - }; + }}; } diff --git a/src/rust/gen/mod.rs b/src/rust/gen/mod.rs new file mode 100644 index 00000000..e7a048ce --- /dev/null +++ b/src/rust/gen/mod.rs @@ -0,0 +1,7 @@ +pub mod jit; +pub mod jit0f_16; +pub mod jit0f_32; + +pub mod analyzer; +pub mod analyzer0f_16; +pub mod analyzer0f_32; diff --git a/src/rust/global_pointers.rs b/src/rust/global_pointers.rs new file mode 100644 index 00000000..f717bb6c --- /dev/null +++ b/src/rust/global_pointers.rs @@ -0,0 +1,18 @@ +pub const REG: u32 = 4; +pub const INSTRUCTION_POINTER: u32 = 556; +pub const PREVIOUS_IP: u32 = 560; +pub const PREFIXES: u32 = 648; +pub const TIMESTAMP_COUNTER: u32 = 664; +pub const OPSTATS_BUFFER: u32 = 0x1000; +pub const OPSTATS_BUFFER_0F: u32 = 0x1400; +pub const TLB_DATA: u32 = 0x400000; +pub const MEMORY: u32 = 0x800000; + +pub fn get_reg16_offset(r: u32) -> u32 { + assert!(r < 8); + REG + 4 * r +} +pub fn get_reg32_offset(r: u32) -> u32 { + assert!(r < 8); + REG + 4 * r +} diff --git a/src/rust/jit.rs b/src/rust/jit.rs new file mode 100644 index 00000000..c99869df --- /dev/null +++ b/src/rust/jit.rs @@ -0,0 +1,1360 @@ +use std::collections::{HashMap, HashSet}; + +use analysis::AnalysisType; +use codegen; +use cpu; +use cpu_context::CpuContext; +use jit_instructions; +use page::Page; +use profiler; +use profiler::stat; +use state_flags::CachedStateFlags; +use util::SafeToU16; +use wasmgen::module_init::WasmBuilder; +use wasmgen::{module_init, wasm_util}; + +pub const WASM_TABLE_SIZE: u32 = 0x10000; + +pub const HASH_PRIME: u32 = 6151; + +pub const CHECK_JIT_CACHE_ARRAY_INVARIANTS: bool = false; +pub const ENABLE_JIT_NONFAULTING_OPTIMZATION: bool = true; + +pub const JIT_MAX_ITERATIONS_PER_FUNCTION: u32 = 10000; + +pub const JIT_ALWAYS_USE_LOOP_SAFETY: bool = false; + +pub const JIT_THRESHOLD: u32 = 2500; + +const CONDITION_FUNCTIONS: [&str; 16] = [ + "test_o", "test_no", "test_b", "test_nb", "test_z", "test_nz", "test_be", "test_nbe", "test_s", + "test_ns", "test_p", "test_np", "test_l", "test_nl", "test_le", "test_nle", +]; + +const CODE_CACHE_SEARCH_SIZE: u32 = 8; +const MAX_INSTRUCTION_LENGTH: u32 = 16; + +mod jit_cache_array { + use page::Page; + use state_flags::CachedStateFlags; + + // Note: For performance reasons, this is global state. See jit_find_cache_entry + + const NO_NEXT_ENTRY: u32 = 0xffff_ffff; + + pub const SIZE: u32 = 0x40000; + pub const MASK: u32 = (SIZE - 1); + + #[derive(Copy, Clone)] + pub struct Entry { + pub start_addr: u32, + + #[cfg(debug_assertions)] + pub len: u32, + + #[cfg(debug_assertions)] + pub opcode: u32, + + // an index into jit_cache_array for the next code_cache entry within the same physical page + next_index_same_page: u32, + + pub initial_state: u16, + pub wasm_table_index: u16, + pub state_flags: CachedStateFlags, + pub pending: bool, + } + + impl Entry { + pub fn create( + start_addr: u32, + next_index_same_page: Option, + wasm_table_index: u16, + initial_state: u16, + state_flags: CachedStateFlags, + pending: bool, + ) -> Entry { + let next_index_same_page = next_index_same_page.unwrap_or(NO_NEXT_ENTRY); + Entry { + start_addr, + next_index_same_page, + wasm_table_index, + initial_state, + state_flags, + pending, + + #[cfg(debug_assertions)] + len: 0, + + #[cfg(debug_assertions)] + opcode: 0, + } + } + pub fn next_index_same_page(&self) -> Option { + if self.next_index_same_page == NO_NEXT_ENTRY { + None + } + else { + Some(self.next_index_same_page) + } + } + + pub fn set_next_index_same_page(&mut self, next_index: Option) { + if let Some(i) = next_index { + self.next_index_same_page = i + } + else { + self.next_index_same_page = NO_NEXT_ENTRY + } + } + } + + const DEFAULT_ENTRY: Entry = Entry { + start_addr: 0, + next_index_same_page: NO_NEXT_ENTRY, + wasm_table_index: 0, + initial_state: 0, + state_flags: CachedStateFlags::EMPTY, + pending: false, + + #[cfg(debug_assertions)] + len: 0, + #[cfg(debug_assertions)] + opcode: 0, + }; + + #[allow(non_upper_case_globals)] + static mut jit_cache_array: [Entry; SIZE as usize] = [Entry { + start_addr: 0, + next_index_same_page: 0, + wasm_table_index: 0, + initial_state: 0, + state_flags: CachedStateFlags::EMPTY, + pending: false, + + #[cfg(debug_assertions)] + len: 0, + #[cfg(debug_assertions)] + opcode: 0, + }; SIZE as usize]; + + #[allow(non_upper_case_globals)] + static mut page_first_entry: [u32; 0x100000] = [0; 0x100000]; + + pub fn get_page_index(page: Page) -> Option { + let index = unsafe { page_first_entry[page.to_u32() as usize] }; + if index == NO_NEXT_ENTRY { + None + } + else { + Some(index) + } + } + + pub fn set_page_index(page: Page, index: Option) { + let index = index.unwrap_or(NO_NEXT_ENTRY); + unsafe { page_first_entry[page.to_u32() as usize] = index } + } + + pub fn get(i: u32) -> &'static Entry { unsafe { &jit_cache_array[i as usize] } } + pub fn get_mut(i: u32) -> &'static mut Entry { unsafe { &mut jit_cache_array[i as usize] } } + + pub fn get_unchecked(i: u32) -> &'static Entry { + unsafe { jit_cache_array.get_unchecked(i as usize) } + } + + fn set(i: u32, entry: Entry) { unsafe { jit_cache_array[i as usize] = entry }; } + + pub fn insert(index: u32, mut entry: Entry) { + let page = Page::page_of(entry.start_addr); + + let previous_entry_index = get_page_index(page); + + if let Some(previous_entry_index) = previous_entry_index { + let previous_entry = get(previous_entry_index); + + if previous_entry.start_addr != 0 { + dbg_assert!( + Page::page_of(previous_entry.start_addr) == Page::page_of(entry.start_addr) + ); + } + } + + set_page_index(page, Some(index)); + entry.set_next_index_same_page(previous_entry_index); + + set(index, entry); + } + + pub fn remove(index: u32) { + let page = Page::page_of(get(index).start_addr); + + let mut page_index = get_page_index(page); + let mut did_remove = false; + + if page_index == Some(index) { + set_page_index(page, get(index).next_index_same_page()); + did_remove = true; + } + else { + while let Some(page_index_ok) = page_index { + let next_index = get(page_index_ok).next_index_same_page(); + if next_index == Some(index) { + get_mut(page_index_ok) + .set_next_index_same_page(get(index).next_index_same_page()); + did_remove = true; + break; + } + page_index = next_index; + } + } + + get_mut(index).set_next_index_same_page(None); + + dbg_assert!(did_remove); + } + + pub fn iter() -> ::std::slice::Iter<'static, Entry> { unsafe { jit_cache_array.iter() } } + + pub fn clear() { + unsafe { + for (i, _) in jit_cache_array.iter().enumerate() { + jit_cache_array[i] = DEFAULT_ENTRY; + } + + for (i, _) in page_first_entry.iter().enumerate() { + page_first_entry[i] = NO_NEXT_ENTRY; + } + } + } + + pub fn check_invariants() { + if !::jit::CHECK_JIT_CACHE_ARRAY_INVARIANTS { + return; + } + + // there are no loops in the linked lists + // https://en.wikipedia.org/wiki/Cycle_detection#Floyd's_Tortoise_and_Hare + for i in 0..(1 << 20) { + let mut slow = get_page_index(Page::page_of(i << 12)); + let mut fast = slow; + + while let Some(fast_ok) = fast { + fast = get(fast_ok).next_index_same_page(); + slow = get(slow.unwrap()).next_index_same_page(); + + if let Some(fast_ok) = fast { + fast = get(fast_ok).next_index_same_page(); + } + else { + break; + } + + dbg_assert!(slow != fast); + } + } + + let mut wasm_table_index_to_jit_cache_index = [0; ::jit::WASM_TABLE_SIZE as usize]; + + for (i, entry) in iter().enumerate() { + dbg_assert!(entry.next_index_same_page().map_or(true, |i| i < SIZE)); + + if entry.pending { + dbg_assert!(entry.start_addr != 0); + dbg_assert!(entry.wasm_table_index != 0); + } + else { + // an invalid entry has both its start_addr and wasm_table_index set to 0 + // neither start_addr nor wasm_table_index are 0 for any valid entry + + dbg_assert!((entry.start_addr == 0) == (entry.wasm_table_index == 0)); + } + + // having a next entry implies validity + dbg_assert!(entry.next_index_same_page() == None || entry.start_addr != 0); + + // any valid wasm_table_index can only be used within a single page + if entry.wasm_table_index != 0 { + let j = wasm_table_index_to_jit_cache_index[entry.wasm_table_index as usize]; + + if j != 0 { + let other_entry = get(j); + dbg_assert!(other_entry.wasm_table_index == entry.wasm_table_index); + dbg_assert!( + Page::page_of(other_entry.start_addr) == Page::page_of(entry.start_addr) + ); + } + else { + wasm_table_index_to_jit_cache_index[entry.wasm_table_index as usize] = i as u32; + } + } + + if entry.start_addr != 0 { + // valid entries can be reached from page_first_entry + let mut reached = false; + + let page = Page::page_of(entry.start_addr); + let mut cache_array_index = get_page_index(page); + + while let Some(index) = cache_array_index { + let other_entry = get(index); + + if i as u32 == index { + reached = true; + break; + } + + cache_array_index = other_entry.next_index_same_page(); + } + + dbg_assert!(reached); + } + } + } +} + +pub struct JitState { + // as an alternative to HashSet, we could use a bitmap of 4096 bits here + // (faster, but uses much more memory) + // or a compressed bitmap (likely faster) + hot_code_addresses: [u32; HASH_PRIME as usize], + wasm_table_index_free_list: Vec, + wasm_table_index_pending_free: Vec, + entry_points: HashMap>, + wasm_builder: WasmBuilder, +} + +impl JitState { + pub fn create_and_initialise() -> JitState { + let mut wasm_builder = WasmBuilder::new(); + wasm_builder.init(); + let mut c = JitState { + hot_code_addresses: [0; HASH_PRIME as usize], + wasm_table_index_free_list: vec![], + wasm_table_index_pending_free: vec![], + entry_points: HashMap::new(), + wasm_builder, + }; + jit_empty_cache(&mut c); + c + } +} + +#[derive(PartialEq, Eq)] +enum BasicBlockType { + Normal { + next_block_addr: u32, + }, + ConditionalJump { + next_block_addr: u32, + next_block_branch_taken_addr: Option, + condition: u8, + jump_offset: i32, + jump_offset_is_32: bool, + }, + Exit, +} + +struct BasicBlock { + addr: u32, + end_addr: u32, + is_entry_block: bool, + ty: BasicBlockType, +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct cached_code { + pub wasm_table_index: u16, + pub initial_state: u16, +} + +impl cached_code { + const NONE: cached_code = cached_code { + wasm_table_index: 0, + initial_state: 0, + }; +} + +pub struct JitContext<'a> { + pub cpu: &'a mut CpuContext, + pub builder: &'a mut WasmBuilder, +} + +pub const GEN_LOCAL_ARG_INITIAL_STATE: u32 = 0; +pub const GEN_LOCAL_STATE: u32 = 1; +pub const GEN_LOCAL_ITERATION_COUNTER: u32 = 2; +// local scratch variables for use wherever required +pub const GEN_LOCAL_SCRATCH0: u32 = 3; +pub const GEN_LOCAL_SCRATCH1: u32 = 4; +pub const GEN_LOCAL_SCRATCH2: u32 = 5; +// Function arguments are not included in the local variable count +pub const GEN_NO_OF_LOCALS: u32 = 5; + +pub const JIT_INSTR_BLOCK_BOUNDARY_FLAG: u32 = 1 << 0; +pub const JIT_INSTR_NONFAULTING_FLAG: u32 = 1 << 1; + +pub const FN_GET_SEG_IDX: u16 = 0; + +fn jit_hot_hash_page(page: Page) -> u32 { page.to_u32() % HASH_PRIME } + +fn is_near_end_of_page(address: u32) -> bool { address & 0xFFF >= 0x1000 - MAX_INSTRUCTION_LENGTH } + +pub fn jit_find_cache_entry(phys_address: u32, state_flags: CachedStateFlags) -> cached_code { + for i in 0..CODE_CACHE_SEARCH_SIZE { + let index = (phys_address + i) & jit_cache_array::MASK; + let entry = jit_cache_array::get_unchecked(index); + + #[cfg(debug_assertions)] + { + if entry.start_addr == phys_address { + if entry.pending { + profiler::stat_increment(stat::S_RUN_INTERPRETED_PENDING) + } + if entry.state_flags != state_flags { + profiler::stat_increment(stat::S_RUN_INTERPRETED_DIFFERENT_STATE) + } + } + + if is_near_end_of_page(phys_address) { + assert!(entry.start_addr != phys_address); + profiler::stat_increment(stat::S_RUN_INTERPRETED_NEAR_END_OF_PAGE); + } + } + + if !entry.pending && entry.start_addr == phys_address && entry.state_flags == state_flags { + #[cfg(debug_assertions)] + { + assert!(cpu::read32(entry.start_addr) == entry.opcode) + } + return cached_code { + wasm_table_index: entry.wasm_table_index, + initial_state: entry.initial_state, + }; + } + } + + cached_code::NONE +} + +fn record_entry_point(ctx: &mut JitState, phys_address: u32) { + if is_near_end_of_page(phys_address) { + return; + } + let page = Page::page_of(phys_address); + let offset_in_page = phys_address as u16 & 0xFFF; + let mut is_new = false; + ctx.entry_points + .entry(page) + .or_insert_with(|| { + is_new = true; + HashSet::new() + }) + .insert(offset_in_page); + + if is_new { + cpu::tlb_set_has_code(page, true); + } +} + +fn jit_find_basic_blocks( + page: Page, + entry_points: &HashSet, + cpu: CpuContext, +) -> (Vec, bool) { + let mut to_visit_stack: Vec = entry_points.iter().cloned().collect(); + let mut marked_as_entry: HashSet = entry_points.clone(); + let page_high_bits = page.to_address(); + let mut basic_blocks: HashMap = HashMap::new(); + let mut requires_loop_limit = false; + + while let Some(to_visit_offset) = to_visit_stack.pop() { + let to_visit = to_visit_offset as u32 | page_high_bits; + if basic_blocks.contains_key(&to_visit) { + continue; + } + let mut current_address = to_visit; + let mut current_block = BasicBlock { + addr: current_address, + end_addr: 0, + ty: BasicBlockType::Exit, + is_entry_block: false, + }; + loop { + if is_near_end_of_page(current_address) { + // TODO: Don't insert this block if empty + current_block.end_addr = current_address; + profiler::stat_increment(stat::S_COMPILE_CUT_OFF_AT_END_OF_PAGE); + break; + } + let mut ctx = &mut CpuContext { + eip: current_address, + ..cpu + }; + let analysis = ::analysis::analyze_step(&mut ctx); + let has_next_instruction = !analysis.no_next_instruction; + current_address = ctx.eip; + + match analysis.ty { + AnalysisType::Normal => { + dbg_assert!(has_next_instruction); + + if basic_blocks.contains_key(¤t_address) { + current_block.end_addr = current_address; + current_block.ty = BasicBlockType::Normal { + next_block_addr: current_address, + }; + } + }, + AnalysisType::Jump { + offset, + is_32, + condition, + } => { + let jump_target = if is_32 { + current_address.wrapping_add(offset as u32) + } + else { + ctx.cs_offset.wrapping_add( + (current_address + .wrapping_sub(ctx.cs_offset) + .wrapping_add(offset as u32)) & 0xFFFF, + ) + }; + + if let Some(condition) = condition { + // conditional jump: continue at next and continue at jump target + + dbg_assert!(has_next_instruction); + to_visit_stack.push(current_address as u16 & 0xFFF); + + let next_block_branch_taken_addr; + + if Page::page_of(jump_target) == page { + to_visit_stack.push(jump_target as u16 & 0xFFF); + + next_block_branch_taken_addr = Some(jump_target); + + // Very simple heuristic for "infinite loops": This + // detects Linux's "calibrating delay loop" + if jump_target == current_block.addr { + dbg_log!("Basic block looping back to front"); + requires_loop_limit = true; + } + } + else { + next_block_branch_taken_addr = None; + } + + current_block.ty = BasicBlockType::ConditionalJump { + next_block_addr: current_address, + next_block_branch_taken_addr, + condition, + jump_offset: offset, + jump_offset_is_32: is_32, + }; + + current_block.end_addr = current_address; + + break; + } + else { + // non-conditional jump: continue at jump target + + if has_next_instruction { + // Execution will eventually come back to the next instruction (CALL) + marked_as_entry.insert(current_address as u16 & 0xFFF); + to_visit_stack.push(current_address as u16 & 0xFFF); + } + + if Page::page_of(jump_target) == page { + current_block.ty = BasicBlockType::Normal { + next_block_addr: jump_target, + }; + to_visit_stack.push(jump_target as u16 & 0xFFF); + } + else { + current_block.ty = BasicBlockType::Exit; + } + + current_block.end_addr = current_address; + + break; + } + }, + AnalysisType::BlockBoundary => { + // a block boundary but not a jump, get out + + if has_next_instruction { + // block boundary, but execution will eventually come back + // to the next instruction. Create a new basic block + // starting at the next instruction and register it as an + // entry point + marked_as_entry.insert(current_address as u16 & 0xFFF); + to_visit_stack.push(current_address as u16 & 0xFFF); + } + + current_block.end_addr = current_address; + break; + }, + } + } + + basic_blocks.insert(to_visit, current_block); + } + + for block in basic_blocks.values_mut() { + if marked_as_entry.contains(&(block.addr as u16 & 0xFFF)) { + block.is_entry_block = true; + } + } + + let mut basic_blocks: Vec = + basic_blocks.into_iter().map(|(_, block)| block).collect(); + + basic_blocks.sort_by_key(|block| block.addr); + + for i in 0..basic_blocks.len() - 1 { + let next_block_addr = basic_blocks[i + 1].addr; + let block = &mut basic_blocks[i]; + if next_block_addr < block.end_addr { + block.ty = BasicBlockType::Normal { next_block_addr }; + block.end_addr = next_block_addr; + + // TODO: assert that the old type is equal to the type of the following block? + } + } + + (basic_blocks, requires_loop_limit) +} + +fn create_cache_entry(ctx: &mut JitState, entry: jit_cache_array::Entry) { + let mut found_entry_index = None; + let phys_addr = entry.start_addr; + + for i in 0..CODE_CACHE_SEARCH_SIZE { + let addr_index = (phys_addr + i) & jit_cache_array::MASK; + let entry = jit_cache_array::get(addr_index); + + if entry.start_addr == 0 { + found_entry_index = Some(addr_index); + break; + } + } + + let found_entry_index = match found_entry_index { + Some(i) => i, + None => { + profiler::stat_increment(stat::S_CACHE_MISMATCH); + + // no free slots, overwrite the first one + let found_entry_index = phys_addr & jit_cache_array::MASK; + + let old_entry = jit_cache_array::get_mut(found_entry_index); + + // if we're here, we expect to overwrite a valid index + dbg_assert!(old_entry.start_addr != 0); + dbg_assert!(old_entry.wasm_table_index != 0); + + if old_entry.wasm_table_index == entry.wasm_table_index { + dbg_assert!(old_entry.pending); + dbg_assert!(Page::page_of(old_entry.start_addr) == Page::page_of(phys_addr)); + + // The old entry belongs to the same wasm table index as this entry. + // *Don't* free the wasm table index, instead just delete the old entry + // and use its slot for this entry. + // TODO: Optimally, we should pick another slot instead of dropping + // an entry has just been created. + //let old_page = Page::page_of(old_entry.start_addr); + jit_cache_array::remove(found_entry_index); + + dbg_assert!(old_entry.next_index_same_page() == None); + old_entry.pending = false; + old_entry.start_addr = 0; + } + else { + let old_wasm_table_index = old_entry.wasm_table_index; + let old_page = Page::page_of(old_entry.start_addr); + + remove_jit_cache_wasm_index(ctx, old_page, old_wasm_table_index); + + //jit_cache_array::check_invariants(); + + // old entry should be removed after calling remove_jit_cache_wasm_index + + dbg_assert!(!old_entry.pending); + dbg_assert!(old_entry.start_addr == 0); + dbg_assert!(old_entry.wasm_table_index == 0); + dbg_assert!(old_entry.next_index_same_page() == None); + } + + found_entry_index + }, + }; + + jit_cache_array::insert(found_entry_index, entry); +} + +#[cfg(debug_assertions)] +pub fn jit_force_generate_unsafe( + ctx: &mut JitState, + phys_addr: u32, + cs_offset: u32, + state_flags: CachedStateFlags, +) { + record_entry_point(ctx, phys_addr); + jit_analyze_and_generate(ctx, Page::page_of(phys_addr), cs_offset, state_flags); +} + +fn jit_analyze_and_generate( + ctx: &mut JitState, + page: Page, + cs_offset: u32, + state_flags: CachedStateFlags, +) { + profiler::stat_increment(stat::S_COMPILE); + + let entry_points = ctx.entry_points.remove(&page); + let cpu = CpuContext { + eip: 0, + prefixes: 0, + cs_offset, + state_flags, + }; + + if let Some(entry_points) = entry_points { + let (mut basic_blocks, requires_loop_limit) = + jit_find_basic_blocks(page, &entry_points, cpu.clone()); + + //for b in basic_blocks.iter() { + // dbg_log!( + // "> Basic block from {:x} to {:x}, is_entry={}", + // b.addr, + // b.end_addr, + // b.is_entry_block + // ); + //} + + jit_generate_module( + &basic_blocks, + requires_loop_limit, + cpu.clone(), + &mut ctx.wasm_builder, + ); + + // allocate an index in the wasm table + let wasm_table_index = ctx + .wasm_table_index_free_list + .pop() + .expect("allocate wasm table index"); + dbg_assert!(wasm_table_index != 0); + + // create entries for each basic block that is marked as an entry point + let mut entry_point_count = 0; + + for (i, block) in basic_blocks.iter().enumerate() { + profiler::stat_increment(stat::S_COMPILE_BASIC_BLOCK); + + if block.is_entry_block && block.addr != block.end_addr { + dbg_assert!(block.addr != 0); + + let initial_state = i.safe_to_u16(); + + let mut entry = jit_cache_array::Entry::create( + block.addr, + None, // to be filled in by create_cache_entry + wasm_table_index, + initial_state, + state_flags, + true, + ); + + #[cfg(debug_assertions)] + { + entry.len = block.end_addr - block.addr; + entry.opcode = cpu::read32(block.addr); + } + + create_cache_entry(ctx, entry); + + entry_point_count += 1; + profiler::stat_increment(stat::S_COMPILE_ENTRY_POINT); + } + } + + dbg_assert!(entry_point_count > 0); + + cpu::tlb_set_has_code(page, true); + + jit_cache_array::check_invariants(); + cpu::check_tlb_invariants(); + + let end_addr = 0; + let first_opcode = 0; + let phys_addr = page.to_address(); + + // will call codegen_finalize_finished asynchronously when finished + cpu::codegen_finalize( + wasm_table_index, + phys_addr, + end_addr, + first_opcode, + state_flags, + ); + + profiler::stat_increment(stat::S_COMPILE_SUCCESS); + } + else { + //dbg_log("No basic blocks, not generating code"); + // Nothing to do + } +} + +pub fn codegen_finalize_finished( + ctx: &mut JitState, + wasm_table_index: u16, + phys_addr: u32, + _end_addr: u32, + _first_opcode: u32, + _state_flags: CachedStateFlags, +) { + assert!(wasm_table_index != 0); + + match ctx + .wasm_table_index_pending_free + .iter() + .position(|i| *i == wasm_table_index) + { + Some(i) => { + ctx.wasm_table_index_pending_free.swap_remove(i); + free_wasm_table_index(ctx, wasm_table_index); + }, + None => { + let page = Page::page_of(phys_addr); + let mut cache_array_index = jit_cache_array::get_page_index(page); + + while let Some(index) = cache_array_index { + let mut entry = jit_cache_array::get_mut(index); + + if entry.wasm_table_index == wasm_table_index { + dbg_assert!(entry.pending); + entry.pending = false; + } + + cache_array_index = entry.next_index_same_page(); + } + }, + } + + jit_cache_array::check_invariants(); + + if CHECK_JIT_CACHE_ARRAY_INVARIANTS { + // sanity check that the above iteration marked all entries as not pending + + for entry in jit_cache_array::iter() { + if entry.wasm_table_index == wasm_table_index { + assert!(!entry.pending); + } + } + } +} + +fn jit_generate_module( + basic_blocks: &Vec, + requires_loop_limit: bool, + mut cpu: CpuContext, + builder: &mut WasmBuilder, +) { + builder.reset(); + + let fn_get_seg_idx = builder.get_fn_idx("get_seg", module_init::FN1_RET_TYPE_INDEX); + dbg_assert!(fn_get_seg_idx == FN_GET_SEG_IDX); + + let basic_block_indices: HashMap = basic_blocks + .iter() + .enumerate() + .map(|(index, block)| (block.addr, index as u32)) + .collect(); + + // set state local variable to the initial state passed as the first argument + wasm_util::get_local(&mut builder.instruction_body, GEN_LOCAL_ARG_INITIAL_STATE); + wasm_util::set_local(&mut builder.instruction_body, GEN_LOCAL_STATE); + + // initialise max_iterations + // TODO: Remove if not requires_loop_limit + wasm_util::push_i32( + &mut builder.instruction_body, + JIT_MAX_ITERATIONS_PER_FUNCTION as i32, + ); + wasm_util::set_local(&mut builder.instruction_body, GEN_LOCAL_ITERATION_COUNTER); + + // main state machine loop + wasm_util::loop_void(&mut builder.instruction_body); + + if JIT_ALWAYS_USE_LOOP_SAFETY || requires_loop_limit { + profiler::stat_increment(stat::S_COMPILE_WITH_LOOP_SAFETY); + + // decrement max_iterations + wasm_util::get_local(&mut builder.instruction_body, GEN_LOCAL_ITERATION_COUNTER); + wasm_util::push_i32(&mut builder.instruction_body, -1); + wasm_util::add_i32(&mut builder.instruction_body); + wasm_util::set_local(&mut builder.instruction_body, GEN_LOCAL_ITERATION_COUNTER); + + // if max_iterations == 0: return + wasm_util::get_local(&mut builder.instruction_body, GEN_LOCAL_ITERATION_COUNTER); + wasm_util::eqz_i32(&mut builder.instruction_body); + wasm_util::if_void(&mut builder.instruction_body); + wasm_util::return_(&mut builder.instruction_body); + wasm_util::block_end(&mut builder.instruction_body); + } + + wasm_util::block_void(&mut builder.instruction_body); // for the default case + + // generate the opening blocks for the cases + + for _ in 0..basic_blocks.len() { + wasm_util::block_void(&mut builder.instruction_body); + } + + wasm_util::get_local(&mut builder.instruction_body, GEN_LOCAL_STATE); + wasm_util::brtable_and_cases(&mut builder.instruction_body, basic_blocks.len() as u32); + + for (i, block) in basic_blocks.iter().enumerate() { + // Case [i] will jump after the [i]th block, so we first generate the + // block end opcode and then the code for that block + wasm_util::block_end(&mut builder.instruction_body); + + if block.addr == block.end_addr { + // Empty basic block, generate no code (for example, jump to block + // that is near end of page) + dbg_assert!(block.ty == BasicBlockType::Exit); + } + else { + builder.commit_instruction_body_to_cs(); + jit_generate_basic_block(&mut cpu, builder, block.addr, block.end_addr); + builder.commit_instruction_body_to_cs(); + } + + let invalid_connection_to_next_block = block.end_addr != cpu.eip; + + match (&block.ty, invalid_connection_to_next_block) { + (_, true) | (BasicBlockType::Exit, _) => { + // Exit this function + wasm_util::return_(&mut builder.instruction_body); + }, + (BasicBlockType::Normal { next_block_addr }, _) => { + // Unconditional jump to next basic block + // - All instructions that don't change eip + // - Unconditional jump + + let next_bb_index = *basic_block_indices.get(&next_block_addr).expect(""); + //dbg_assert!(next_bb_index != -1); + + // set state variable to next basic block + wasm_util::push_i32(&mut builder.instruction_body, next_bb_index as i32); + wasm_util::set_local(&mut builder.instruction_body, GEN_LOCAL_STATE); + + wasm_util::br( + &mut builder.instruction_body, + basic_blocks.len() as u32 - i as u32, + ); // to the loop + }, + ( + &BasicBlockType::ConditionalJump { + next_block_addr, + next_block_branch_taken_addr, + condition, + jump_offset, + jump_offset_is_32, + }, + _, + ) => { + // Conditional jump to next basic block + // - jnz, jc, etc. + + dbg_assert!(condition < 16); + let condition = CONDITION_FUNCTIONS[condition as usize]; + + codegen::gen_fn0_const_ret(builder, condition); + + wasm_util::if_void(&mut builder.instruction_body); + + // Branch taken + + if jump_offset_is_32 { + codegen::gen_relative_jump(builder, jump_offset); + } + else { + // TODO: Is this necessary? + let ctx = &mut JitContext { + cpu: &mut cpu.clone(), + builder, + }; + codegen::gen_fn1_const(ctx, "jmp_rel16", jump_offset as u32); + } + + if let Some(next_block_branch_taken_addr) = next_block_branch_taken_addr { + let next_basic_block_branch_taken_index = *basic_block_indices + .get(&next_block_branch_taken_addr) + .expect(""); + + wasm_util::push_i32( + &mut builder.instruction_body, + next_basic_block_branch_taken_index as i32, + ); + wasm_util::set_local(&mut builder.instruction_body, GEN_LOCAL_STATE); + } + else { + // Jump to different page + wasm_util::return_(&mut builder.instruction_body); + } + + wasm_util::else_(&mut builder.instruction_body); + + { + // Branch not taken + // TODO: Could use fall-through here + let next_basic_block_index = + *basic_block_indices.get(&next_block_addr).expect(""); + + wasm_util::push_i32( + &mut builder.instruction_body, + next_basic_block_index as i32, + ); + wasm_util::set_local(&mut builder.instruction_body, GEN_LOCAL_STATE); + } + + wasm_util::block_end(&mut builder.instruction_body); + + wasm_util::br( + &mut builder.instruction_body, + basic_blocks.len() as u32 - i as u32, + ); // to the loop + }, + } + } + + wasm_util::block_end(&mut builder.instruction_body); // default case + wasm_util::unreachable(&mut builder.instruction_body); + + wasm_util::block_end(&mut builder.instruction_body); // loop + + builder.commit_instruction_body_to_cs(); + builder.finish(GEN_NO_OF_LOCALS as u8); +} + +fn jit_generate_basic_block( + mut cpu: &mut CpuContext, + builder: &mut WasmBuilder, + start_addr: u32, + stop_addr: u32, +) { + let mut len = 0; + + let mut end_addr; + let mut was_block_boundary; + let mut eip_delta = 0; + + //*instruction_pointer = start_addr; + + // First iteration of do-while assumes the caller confirms this condition + dbg_assert!(!is_near_end_of_page(start_addr)); + + cpu.eip = start_addr; + + loop { + if false { + ::opstats::gen_opstats(builder, cpu::read32(cpu.eip)); + } + let start_eip = cpu.eip; + let mut instruction_flags = 0; + jit_instructions::jit_instruction(&mut cpu, builder, &mut instruction_flags); + let end_eip = cpu.eip; + + let instruction_length = end_eip - start_eip; + was_block_boundary = instruction_flags & JIT_INSTR_BLOCK_BOUNDARY_FLAG != 0; + + dbg_assert!(instruction_length < MAX_INSTRUCTION_LENGTH); + + if ENABLE_JIT_NONFAULTING_OPTIMZATION { + // There are a few conditions to keep in mind to optimize the update of previous_ip and + // instruction_pointer: + // - previous_ip MUST be updated just before a faulting instruction + // - instruction_pointer MUST be updated before jump instructions (since they use the EIP + // value for instruction logic) + // - Nonfaulting instructions don't need either to be updated + if was_block_boundary { + // prev_ip = eip + eip_delta, so that previous_ip points to the start of this instruction + codegen::gen_set_previous_eip_offset_from_eip(builder, eip_delta); + + // eip += eip_delta + len(jump) so instruction logic uses the correct eip + codegen::gen_increment_instruction_pointer(builder, eip_delta + instruction_length); + builder.commit_instruction_body_to_cs(); + + eip_delta = 0; + } + else if instruction_flags & JIT_INSTR_NONFAULTING_FLAG == 0 { + // Faulting instruction + + // prev_ip = eip + eip_delta, so that previous_ip points to the start of this instruction + codegen::gen_set_previous_eip_offset_from_eip(builder, eip_delta); + builder.commit_instruction_body_to_cs(); + + // Leave this instruction's length to be updated in the next batch, whatever it may be + eip_delta += instruction_length; + } + else { + // Non-faulting, so we skip setting previous_ip and simply queue the instruction length + // for whenever eip is updated next + profiler::stat_increment(stat::S_NONFAULTING_OPTIMIZATION); + eip_delta += instruction_length; + } + } + else { + codegen::gen_set_previous_eip(builder); + codegen::gen_increment_instruction_pointer(builder, instruction_length); + builder.commit_instruction_body_to_cs(); + } + end_addr = cpu.eip; + len += 1; + + if end_addr == stop_addr { + break; + } + + if was_block_boundary || is_near_end_of_page(end_addr) || end_addr > stop_addr { + dbg_log!("Overlapping basic blocks start={:x} expected_end={:x} end={:x} was_block_boundary={} near_end_of_page={}", + start_addr, stop_addr, end_addr, was_block_boundary, is_near_end_of_page(end_addr)); + break; + } + } + + if ENABLE_JIT_NONFAULTING_OPTIMZATION { + // When the block ends in a non-jump instruction, we may have uncommitted updates still + if eip_delta > 0 { + builder.commit_instruction_body_to_cs(); + codegen::gen_increment_instruction_pointer(builder, eip_delta); + } + } + + codegen::gen_increment_timestamp_counter(builder, len); + + // no page was crossed + dbg_assert!(Page::page_of(end_addr) == Page::page_of(start_addr)); +} + +pub fn jit_increase_hotness_and_maybe_compile( + ctx: &mut JitState, + phys_address: u32, + cs_offset: u32, + state_flags: CachedStateFlags, +) { + record_entry_point(ctx, phys_address); + let page = Page::page_of(phys_address); + let address_hash = jit_hot_hash_page(page) as usize; + ctx.hot_code_addresses[address_hash] += 1; + if ctx.hot_code_addresses[address_hash] >= JIT_THRESHOLD { + ctx.hot_code_addresses[address_hash] = 0; + jit_analyze_and_generate(ctx, page, cs_offset, state_flags) + }; +} + +fn free_wasm_table_index(ctx: &mut JitState, wasm_table_index: u16) { + if CHECK_JIT_CACHE_ARRAY_INVARIANTS { + dbg_assert!(!ctx.wasm_table_index_free_list.contains(&wasm_table_index)); + } + ctx.wasm_table_index_free_list.push(wasm_table_index) + + // It is not strictly necessary to clear the function, but it will fail + // more predictably if we accidentally use the function + // XXX: This fails in Chromium: + // RangeError: WebAssembly.Table.set(): Modifying existing entry in table not supported. + //jit_clear_func(wasm_table_index); +} + +/// Remove all entries with the given wasm_table_index in page +fn remove_jit_cache_wasm_index(ctx: &mut JitState, page: Page, wasm_table_index: u16) { + let mut cache_array_index = jit_cache_array::get_page_index(page).unwrap(); + + let mut pending = false; + + loop { + let entry = jit_cache_array::get_mut(cache_array_index); + let next_cache_array_index = entry.next_index_same_page(); + + if entry.wasm_table_index == wasm_table_index { + // if one entry is pending, all must be pending + dbg_assert!(!pending || entry.pending); + + pending = entry.pending; + + jit_cache_array::remove(cache_array_index); + + dbg_assert!(entry.next_index_same_page() == None); + entry.wasm_table_index = 0; + entry.start_addr = 0; + entry.pending = false; + } + + if let Some(i) = next_cache_array_index { + cache_array_index = i; + } + else { + break; + } + } + + if pending { + ctx.wasm_table_index_pending_free.push(wasm_table_index); + } + else { + free_wasm_table_index(ctx, wasm_table_index); + } + + if !jit_page_has_code(ctx, page) { + cpu::tlb_set_has_code(page, false); + } + + if CHECK_JIT_CACHE_ARRAY_INVARIANTS { + // sanity check that the above iteration deleted all entries + + for entry in jit_cache_array::iter() { + dbg_assert!(entry.wasm_table_index != wasm_table_index); + } + } +} + +/// Register a write in this page: Delete all present code +pub fn jit_dirty_page(ctx: &mut JitState, page: Page) { + let mut did_have_code = false; + + if let Some(mut cache_array_index) = jit_cache_array::get_page_index(page) { + did_have_code = true; + + let mut index_to_free = HashSet::new(); + let mut index_to_pending_free = HashSet::new(); + + jit_cache_array::set_page_index(page, None); + profiler::stat_increment(stat::S_INVALIDATE_PAGE); + + loop { + profiler::stat_increment(stat::S_INVALIDATE_CACHE_ENTRY); + let entry = jit_cache_array::get_mut(cache_array_index); + let wasm_table_index = entry.wasm_table_index; + + assert!(page == Page::page_of(entry.start_addr)); + + let next_cache_array_index = entry.next_index_same_page(); + + entry.set_next_index_same_page(None); + entry.start_addr = 0; + entry.wasm_table_index = 0; + + if entry.pending { + entry.pending = false; + + index_to_pending_free.insert(wasm_table_index); + } + else { + index_to_free.insert(wasm_table_index); + } + + if let Some(i) = next_cache_array_index { + cache_array_index = i; + } + else { + break; + } + } + + for index in index_to_free.iter().cloned() { + free_wasm_table_index(ctx, index) + } + + for index in index_to_pending_free { + ctx.wasm_table_index_pending_free.push(index); + } + } + + match ctx.entry_points.remove(&page) { + None => {}, + Some(_entry_points) => { + did_have_code = true; + + // don't try to compile code in this page anymore until it's hot again + ctx.hot_code_addresses[jit_hot_hash_page(page) as usize] = 0; + }, + } + + if did_have_code { + cpu::tlb_set_has_code(page, false); + } +} + +pub fn jit_dirty_cache(ctx: &mut JitState, start_addr: u32, end_addr: u32) { + assert!(start_addr < end_addr); + + let start_page = Page::page_of(start_addr); + let end_page = Page::page_of(end_addr - 1); + + for page in start_page.to_u32()..end_page.to_u32() + 1 { + jit_dirty_page(ctx, Page::page_of(page << 12)); + } +} + +pub fn jit_dirty_cache_small(ctx: &mut JitState, start_addr: u32, end_addr: u32) { + assert!(start_addr < end_addr); + + let start_page = Page::page_of(start_addr); + let end_page = Page::page_of(end_addr - 1); + + jit_dirty_page(ctx, start_page); + + // Note: This can't happen when paging is enabled, as writes across + // boundaries are split up on two pages + if start_page != end_page { + assert!(start_page.to_u32() + 1 == end_page.to_u32()); + jit_dirty_page(ctx, end_page); + } +} + +pub fn jit_dirty_cache_single(ctx: &mut JitState, addr: u32) { + jit_dirty_page(ctx, Page::page_of(addr)); +} + +pub fn jit_empty_cache(ctx: &mut JitState) { + jit_cache_array::clear(); + + ctx.entry_points.clear(); + + ctx.wasm_table_index_pending_free.clear(); + ctx.wasm_table_index_free_list.clear(); + + for i in 0..0xFFFF { + // don't assign 0 (XXX: Check) + ctx.wasm_table_index_free_list.push(i as u16 + 1); + } +} + +pub fn jit_page_has_code(ctx: &JitState, page: Page) -> bool { + (jit_cache_array::get_page_index(page) != None || ctx.entry_points.contains_key(&page)) +} + +#[cfg(debug_assertions)] +pub fn jit_unused_cache_stat() -> u32 { + jit_cache_array::iter() + .filter(|e| e.start_addr == 0) + .count() as u32 +} +#[cfg(debug_assertions)] +pub fn jit_get_entry_length(i: u32) -> u32 { jit_cache_array::get(i).len } +#[cfg(debug_assertions)] +pub fn jit_get_entry_address(i: u32) -> u32 { jit_cache_array::get(i).start_addr } +#[cfg(debug_assertions)] +pub fn jit_get_entry_pending(i: u32) -> bool { jit_cache_array::get(i).pending } +#[cfg(debug_assertions)] +pub fn jit_get_wasm_table_index_free_list_count(ctx: &JitState) -> u32 { + ctx.wasm_table_index_free_list.len() as u32 +} + +pub fn jit_get_op_len(ctx: &JitState) -> u32 { ctx.wasm_builder.get_op_len() } +pub fn jit_get_op_ptr(ctx: &JitState) -> *const u8 { ctx.wasm_builder.get_op_ptr() } diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs new file mode 100644 index 00000000..08ecf525 --- /dev/null +++ b/src/rust/jit_instructions.rs @@ -0,0 +1,396 @@ +#![allow(non_snake_case)] + +use codegen; +use cpu_context::CpuContext; +use global_pointers; +use jit::JitContext; +use jit::{GEN_LOCAL_SCRATCH0, GEN_LOCAL_SCRATCH1}; +use prefix::SEG_PREFIX_ZERO; +use prefix::{PREFIX_66, PREFIX_67, PREFIX_F2, PREFIX_F3}; +use regs::{AX, BP, BX, CX, DI, DX, SI, SP}; +use regs::{CS, DS, ES, FS, GS, SS}; +use regs::{EAX, EBP, EBX, ECX, EDI, EDX, ESI, ESP}; +use wasmgen::module_init::WasmBuilder; +use wasmgen::wasm_util; + +pub fn jit_instruction(cpu: &mut CpuContext, builder: &mut WasmBuilder, instr_flags: &mut u32) { + cpu.prefixes = 0; + let ctx = &mut JitContext { cpu, builder }; + ::gen::jit::jit( + ctx.cpu.read_imm8() as u32 | (ctx.cpu.osize_32() as u32) << 8, + ctx, + instr_flags, + ); +} + +pub fn jit_handle_prefix(ctx: &mut JitContext, instr_flags: &mut u32) { + // TODO: Could avoid repeatedly generating prefix updates + let prefixes = ctx.cpu.prefixes; + codegen::gen_add_prefix_bits(ctx, prefixes); + ::gen::jit::jit( + ctx.cpu.read_imm8() as u32 | (ctx.cpu.osize_32() as u32) << 8, + ctx, + instr_flags, + ); + codegen::gen_clear_prefixes(ctx); +} + +pub fn jit_handle_segment_prefix(segment: u32, ctx: &mut JitContext, instr_flags: &mut u32) { + assert!(segment <= 5); + ctx.cpu.prefixes |= segment + 1; + jit_handle_prefix(ctx, instr_flags) +} + +pub fn instr16_0F_jit(ctx: &mut JitContext, instr_flags: &mut u32) { + ::gen::jit0f_16::jit(ctx.cpu.read_imm8(), ctx, instr_flags) +} +pub fn instr32_0F_jit(ctx: &mut JitContext, instr_flags: &mut u32) { + ::gen::jit0f_32::jit(ctx.cpu.read_imm8(), ctx, instr_flags) +} +pub fn instr_26_jit(ctx: &mut JitContext, instr_flags: &mut u32) { + jit_handle_segment_prefix(ES, ctx, instr_flags) +} +pub fn instr_2E_jit(ctx: &mut JitContext, instr_flags: &mut u32) { + jit_handle_segment_prefix(CS, ctx, instr_flags) +} +pub fn instr_36_jit(ctx: &mut JitContext, instr_flags: &mut u32) { + jit_handle_segment_prefix(SS, ctx, instr_flags) +} +pub fn instr_3E_jit(ctx: &mut JitContext, instr_flags: &mut u32) { + jit_handle_segment_prefix(DS, ctx, instr_flags) +} + +pub fn instr_64_jit(ctx: &mut JitContext, instr_flags: &mut u32) { + jit_handle_segment_prefix(FS, ctx, instr_flags) +} +pub fn instr_65_jit(ctx: &mut JitContext, instr_flags: &mut u32) { + jit_handle_segment_prefix(GS, ctx, instr_flags) +} + +pub fn instr_66_jit(ctx: &mut JitContext, instr_flags: &mut u32) { + ctx.cpu.prefixes |= PREFIX_66; + jit_handle_prefix(ctx, instr_flags) +} +pub fn instr_67_jit(ctx: &mut JitContext, instr_flags: &mut u32) { + ctx.cpu.prefixes |= PREFIX_67; + jit_handle_prefix(ctx, instr_flags) +} +pub fn instr_F0_jit(ctx: &mut JitContext, instr_flags: &mut u32) { + // lock: Ignore + jit_handle_prefix(ctx, instr_flags) +} +pub fn instr_F2_jit(ctx: &mut JitContext, instr_flags: &mut u32) { + ctx.cpu.prefixes |= PREFIX_F2; + jit_handle_prefix(ctx, instr_flags) +} +pub fn instr_F3_jit(ctx: &mut JitContext, instr_flags: &mut u32) { + ctx.cpu.prefixes |= PREFIX_F3; + jit_handle_prefix(ctx, instr_flags) +} + +fn push16_reg_jit(ctx: &mut JitContext, r: u32) { + let name = if ctx.cpu.ssize_32() { + "push16_ss32" + } + else { + "push16_ss16" + }; + codegen::gen_fn1_reg16(ctx, name, r); +} + +fn push32_reg_jit(ctx: &mut JitContext, r: u32) { + let name = if ctx.cpu.ssize_32() { + "push32_ss32" + } + else { + "push32_ss16" + }; + codegen::gen_fn1_reg32(ctx, name, r); +} + +fn push16_imm_jit(ctx: &mut JitContext, imm: u32) { + let name = if ctx.cpu.ssize_32() { + "push16_ss32" + } + else { + "push16_ss16" + }; + codegen::gen_fn1_const(ctx, name, imm) +} + +fn push32_imm_jit(ctx: &mut JitContext, imm: u32) { + let name = if ctx.cpu.ssize_32() { + "push32_ss32" + } + else { + "push32_ss16" + }; + codegen::gen_fn1_const(ctx, name, imm) +} + +fn push16_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let name = if ctx.cpu.ssize_32() { + "push16_ss32_mem" + } + else { + "push16_ss16_mem" + }; + codegen::gen_modrm_fn0(ctx, name) +} + +fn push32_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let name = if ctx.cpu.ssize_32() { + "push32_ss32_mem" + } + else { + "push32_ss16_mem" + }; + codegen::gen_modrm_fn0(ctx, name) +} + +fn pop16_reg_jit(ctx: &mut JitContext, reg: u32) { + if ctx.cpu.ssize_32() { + codegen::gen_set_reg16_fn0(ctx, "pop16_ss32", reg); + } + else { + codegen::gen_set_reg16_fn0(ctx, "pop16_ss16", reg); + } +} + +fn pop32_reg_jit(ctx: &mut JitContext, reg: u32) { + if ctx.cpu.ssize_32() { + codegen::gen_set_reg32s_fn0(ctx, "pop32s_ss32", reg); + } + else { + codegen::gen_set_reg32s_fn0(ctx, "pop32s_ss16", reg); + } +} + +pub fn instr16_50_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, AX); } +pub fn instr32_50_jit(ctx: &mut JitContext) { push32_reg_jit(ctx, EAX); } +pub fn instr16_51_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, CX); } +pub fn instr32_51_jit(ctx: &mut JitContext) { push32_reg_jit(ctx, ECX); } +pub fn instr16_52_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, DX); } +pub fn instr32_52_jit(ctx: &mut JitContext) { push32_reg_jit(ctx, EDX); } +pub fn instr16_53_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, BX); } +pub fn instr32_53_jit(ctx: &mut JitContext) { push32_reg_jit(ctx, EBX); } +pub fn instr16_54_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, SP); } +pub fn instr32_54_jit(ctx: &mut JitContext) { push32_reg_jit(ctx, ESP); } +pub fn instr16_55_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, BP); } +pub fn instr32_55_jit(ctx: &mut JitContext) { push32_reg_jit(ctx, EBP); } +pub fn instr16_56_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, SI); } +pub fn instr32_56_jit(ctx: &mut JitContext) { push32_reg_jit(ctx, ESI); } +pub fn instr16_57_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, DI); } +pub fn instr32_57_jit(ctx: &mut JitContext) { push32_reg_jit(ctx, EDI); } + +pub fn instr16_58_jit(ctx: &mut JitContext) { pop16_reg_jit(ctx, AX); } +pub fn instr32_58_jit(ctx: &mut JitContext) { pop32_reg_jit(ctx, EAX); } +pub fn instr16_59_jit(ctx: &mut JitContext) { pop16_reg_jit(ctx, CX); } +pub fn instr32_59_jit(ctx: &mut JitContext) { pop32_reg_jit(ctx, ECX); } +pub fn instr16_5A_jit(ctx: &mut JitContext) { pop16_reg_jit(ctx, DX); } +pub fn instr32_5A_jit(ctx: &mut JitContext) { pop32_reg_jit(ctx, EDX); } +pub fn instr16_5B_jit(ctx: &mut JitContext) { pop16_reg_jit(ctx, BX); } +pub fn instr32_5B_jit(ctx: &mut JitContext) { pop32_reg_jit(ctx, EBX); } +// hole for pop esp +pub fn instr16_5D_jit(ctx: &mut JitContext) { pop16_reg_jit(ctx, BP); } +pub fn instr32_5D_jit(ctx: &mut JitContext) { pop32_reg_jit(ctx, EBP); } +pub fn instr16_5E_jit(ctx: &mut JitContext) { pop16_reg_jit(ctx, SI); } +pub fn instr32_5E_jit(ctx: &mut JitContext) { pop32_reg_jit(ctx, ESI); } +pub fn instr16_5F_jit(ctx: &mut JitContext) { pop16_reg_jit(ctx, DI); } +pub fn instr32_5F_jit(ctx: &mut JitContext) { pop32_reg_jit(ctx, EDI); } + +pub fn instr16_68_jit(ctx: &mut JitContext, imm16: u32) { push16_imm_jit(ctx, imm16) } +pub fn instr32_68_jit(ctx: &mut JitContext, imm32: u32) { push32_imm_jit(ctx, imm32) } +pub fn instr16_6A_jit(ctx: &mut JitContext, imm16: u32) { push16_imm_jit(ctx, imm16) } +pub fn instr32_6A_jit(ctx: &mut JitContext, imm32: u32) { push32_imm_jit(ctx, imm32) } + +// Code for conditional jumps is generated automatically by the basic block codegen +pub fn instr16_70_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_70_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_71_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_71_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_72_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_72_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_73_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_73_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_74_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_74_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_75_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_75_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_76_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_76_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_77_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_77_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_78_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_78_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_79_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_79_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_7A_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_7A_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_7B_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_7B_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_7C_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_7C_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_7D_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_7D_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_7E_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_7E_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_7F_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_7F_jit(_ctx: &mut JitContext, _imm: u32) {} + +pub fn instr16_89_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + // TODO: Inlining + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_modrm_fn1(ctx, "instr16_89_mem", r); +} +pub fn instr16_89_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_set_reg16_r(ctx, r1, r2); +} +pub fn instr32_89_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + // Pseudo: safe_write32(modrm_resolve(modrm_byte), reg32s[r]); + let address_local = GEN_LOCAL_SCRATCH0; + let value_local = GEN_LOCAL_SCRATCH1; + + codegen::gen_modrm_resolve(ctx, modrm_byte); + wasm_util::set_local(&mut ctx.builder.instruction_body, address_local); + + wasm_util::push_i32( + &mut ctx.builder.instruction_body, + global_pointers::get_reg32_offset(r) as i32, + ); + wasm_util::load_aligned_i32_from_stack(&mut ctx.builder.instruction_body, 0); + wasm_util::set_local(&mut ctx.builder.instruction_body, value_local); + + codegen::gen_safe_write32(ctx, address_local, value_local); +} +pub fn instr32_89_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_set_reg32_r(ctx, r1, r2); +} + +pub fn instr16_8B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + // TODO: Inlining + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_modrm_fn1(ctx, "instr16_8B_mem", r); +} +pub fn instr16_8B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_set_reg16_r(ctx, r2, r1); +} +pub fn instr32_8B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + // Pseudo: reg32s[r] = safe_read32s(modrm_resolve(modrm_byte)); + wasm_util::push_i32( + &mut ctx.builder.instruction_body, + global_pointers::get_reg32_offset(r) as i32, + ); + + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read32(ctx); + + wasm_util::store_aligned_i32(&mut ctx.builder.instruction_body); +} +pub fn instr32_8B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_set_reg32_r(ctx, r2, r1); +} + +pub fn instr16_8D_mem_jit(ctx: &mut JitContext, modrm_byte: u8, reg: u32) { + let loc = global_pointers::get_reg16_offset(reg); + wasm_util::push_i32(&mut ctx.builder.instruction_body, loc as i32); + ctx.cpu.prefixes |= SEG_PREFIX_ZERO; + codegen::gen_modrm_resolve(ctx, modrm_byte); + wasm_util::store_aligned_u16(&mut ctx.builder.instruction_body); +} +pub fn instr32_8D_mem_jit(ctx: &mut JitContext, modrm_byte: u8, reg: u32) { + let loc = global_pointers::get_reg32_offset(reg); + wasm_util::push_i32(&mut ctx.builder.instruction_body, loc as i32); + ctx.cpu.prefixes |= SEG_PREFIX_ZERO; + codegen::gen_modrm_resolve(ctx, modrm_byte); + wasm_util::store_aligned_i32(&mut ctx.builder.instruction_body); +} + +pub fn instr16_8D_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_fn2_const(ctx, "instr16_8D_reg", r1, r2); +} + +pub fn instr32_8D_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_fn2_const(ctx, "instr32_8D_reg", r1, r2); +} + +pub fn instr16_8F_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_fn0_const(ctx, "instr16_8F_0_mem_pre"); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_modrm_fn0(ctx, "instr16_8F_0_mem"); +} +pub fn instr16_8F_0_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_fn1_const(ctx, "instr16_8F_0_reg", r); +} +pub fn instr32_8F_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_fn0_const(ctx, "instr32_8F_0_mem_pre"); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_modrm_fn0(ctx, "instr32_8F_0_mem"); +} +pub fn instr32_8F_0_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_fn1_const(ctx, "instr32_8F_0_reg", r); +} + +pub fn instr16_E8_jit(ctx: &mut JitContext, imm: u32) { + codegen::gen_fn1_const(ctx, "instr16_E8", imm); +} +pub fn instr32_E8_jit(ctx: &mut JitContext, imm: u32) { + codegen::gen_fn1_const(ctx, "instr32_E8", imm); +} +pub fn instr16_E9_jit(ctx: &mut JitContext, imm: u32) { + codegen::gen_fn1_const(ctx, "instr16_E9", imm); +} +pub fn instr32_E9_jit(ctx: &mut JitContext, imm: u32) { + codegen::gen_fn1_const(ctx, "instr32_E9", imm); +} +pub fn instr16_EB_jit(ctx: &mut JitContext, imm: u32) { + codegen::gen_fn1_const(ctx, "instr16_EB", imm); +} +pub fn instr32_EB_jit(ctx: &mut JitContext, imm: u32) { + codegen::gen_fn1_const(ctx, "instr32_EB", imm); +} + +pub fn instr16_FF_6_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + push16_mem_jit(ctx, modrm_byte) +} +pub fn instr16_FF_6_reg_jit(ctx: &mut JitContext, r: u32) { push16_reg_jit(ctx, r) } +pub fn instr32_FF_6_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + push32_mem_jit(ctx, modrm_byte) +} +pub fn instr32_FF_6_reg_jit(ctx: &mut JitContext, r: u32) { push32_reg_jit(ctx, r) } + +// Code for conditional jumps is generated automatically by the basic block codegen +pub fn instr16_0F80_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_0F81_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_0F82_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_0F83_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_0F84_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_0F85_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_0F86_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_0F87_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_0F88_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_0F89_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_0F8A_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_0F8B_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_0F8C_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_0F8D_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_0F8E_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr16_0F8F_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_0F80_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_0F81_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_0F82_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_0F83_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_0F84_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_0F85_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_0F86_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_0F87_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_0F88_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_0F89_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_0F8A_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_0F8B_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_0F8C_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_0F8D_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_0F8E_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr32_0F8F_jit(_ctx: &mut JitContext, _imm: u32) {} diff --git a/src/rust/leb.rs b/src/rust/leb.rs new file mode 100644 index 00000000..dad827d9 --- /dev/null +++ b/src/rust/leb.rs @@ -0,0 +1,52 @@ +pub fn write_leb_i32(buf: &mut Vec, mut v: i32) { + // Super complex stuff. See the following: + // https://en.wikipedia.org/wiki/LEB128#Encode_signed_integer + // http://llvm.org/doxygen/LEB128_8h_source.html#l00048 + + let mut more = true; + let negative = v < 0; + let size = 32; + while more { + let mut byte = (v & 0b1111111) as u8; // get last 7 bits + v >>= 7; // shift them away from the value + if negative { + v |= (!0 as i32) << (size - 7); // extend sign + } + let sign_bit = byte & (1 << 6); + if (v == 0 && sign_bit == 0) || (v == -1 && sign_bit != 0) { + more = false; + } + else { + byte |= 0b10000000; // turn on MSB + } + buf.push(byte); + } +} + +pub fn write_leb_u32(buf: &mut Vec, mut v: u32) { + loop { + let mut byte = v as u8 & 0b01111111; // get last 7 bits + v >>= 7; // shift them away from the value + if v != 0 { + byte |= 0b10000000; // turn on MSB + } + buf.push(byte); + if v == 0 { + break; + } + } +} + +pub fn write_fixed_leb16_at_idx(vec: &mut Vec, idx: usize, x: u16) { + dbg_assert!(x < (1 << 14)); // we have 14 bits of available space in 2 bytes for leb + vec[idx] = ((x & 0b1111111) | 0b10000000) as u8; + vec[idx + 1] = (x >> 7) as u8; +} + +pub fn write_fixed_leb32_at_idx(vec: &mut Vec, idx: usize, x: u32) { + dbg_assert!(x < (1 << 28)); // we have 28 bits of available space in 4 bytes for leb + vec[idx] = (x & 0b1111111) as u8 | 0b10000000; + vec[idx + 1] = (x >> 7 & 0b1111111) as u8 | 0b10000000; + vec[idx + 2] = (x >> 14 & 0b1111111) as u8 | 0b10000000; + vec[idx + 3] = (x >> 21 & 0b1111111) as u8; +} diff --git a/src/rust/lib.rs b/src/rust/lib.rs index a1cf1068..9db6ba0f 100644 --- a/src/rust/lib.rs +++ b/src/rust/lib.rs @@ -5,7 +5,24 @@ extern crate quickcheck; #[macro_use] mod dbg; -#[macro_use] -mod util; +pub mod c_api; -pub mod wasmgen; +mod analysis; +mod codegen; +mod cpu; +mod cpu_context; +mod gen; +mod global_pointers; +mod jit; +mod jit_instructions; +mod leb; +mod modrm; +mod opstats; +mod page; +mod prefix; +mod profiler; +mod regs; +mod state_flags; +mod tlb; +mod util; +mod wasmgen; diff --git a/src/rust/modrm.rs b/src/rust/modrm.rs new file mode 100644 index 00000000..416b1e6d --- /dev/null +++ b/src/rust/modrm.rs @@ -0,0 +1,345 @@ +use cpu_context::CpuContext; +use jit::JitContext; +use prefix::{PREFIX_MASK_SEGMENT, SEG_PREFIX_ZERO}; +use regs::{BP, BX, DI, SI}; +use regs::{DS, SS}; +use regs::{EAX, EBP, EBX, ECX, EDI, EDX, ESI, ESP}; +use wasmgen::wasm_util; + +pub fn skip(ctx: &mut CpuContext, modrm_byte: u8) { + if ctx.asize_32() { + skip32(ctx, modrm_byte) + } + else { + skip16(ctx, modrm_byte) + } +} + +fn skip16(ctx: &mut CpuContext, modrm_byte: u8) { + assert!(modrm_byte < 0xC0); + let r = modrm_byte & 7; + + if modrm_byte < 0x40 { + if r == 6 { + ctx.advance16() + } + } + else if modrm_byte < 0x80 { + ctx.advance8() + } + else { + ctx.advance16() + } +} + +fn skip32(ctx: &mut CpuContext, modrm_byte: u8) { + assert!(modrm_byte < 0xC0); + let r = modrm_byte & 7; + + if r == 4 { + let sib = ctx.read_imm8(); + if modrm_byte < 0x40 { + if sib & 7 == 5 { + ctx.advance32() + } + } + else if modrm_byte < 0x80 { + ctx.advance8() + } + else { + ctx.advance32() + } + } + else if r == 5 && modrm_byte < 0x40 { + ctx.advance32(); + } + else { + if modrm_byte < 0x40 { + // Nothing + } + else if modrm_byte < 0x80 { + ctx.advance8() + } + else { + ctx.advance32() + } + } +} + +pub fn gen(ctx: &mut JitContext, modrm_byte: u8) { + if ctx.cpu.asize_32() { + gen32(ctx, modrm_byte) + } + else { + gen16(ctx, modrm_byte) + } +} + +enum Imm16 { + None, + Imm8, + Imm16, +} + +enum Offset16 { + Zero, + One(u32), + Two(u32, u32), +} + +fn gen16_case(ctx: &mut JitContext, seg: u32, offset: Offset16, imm: Imm16) { + // Generates one of: + // - add_segment(reg) + // - add_segment(imm) + // - add_segment(reg1 + reg2 & 0xFFFF) + // - add_segment(reg1 + imm & 0xFFFF) + // - add_segment(reg1 + reg2 + imm & 0xFFFF) + + let immediate_value = match imm { + Imm16::None => 0, + Imm16::Imm8 => ctx.cpu.read_imm8s() as i32, + Imm16::Imm16 => ctx.cpu.read_imm16s() as i32, + }; + + match offset { + Offset16::Zero => { + wasm_util::push_i32(&mut ctx.builder.instruction_body, immediate_value & 0xFFFF); + }, + Offset16::One(r) => { + wasm_util::load_aligned_u16( + &mut ctx.builder.instruction_body, + ::global_pointers::get_reg16_offset(r), + ); + + if immediate_value != 0 { + wasm_util::push_i32(&mut ctx.builder.instruction_body, immediate_value); + wasm_util::add_i32(&mut ctx.builder.instruction_body); + + wasm_util::push_i32(&mut ctx.builder.instruction_body, 0xFFFF); + wasm_util::and_i32(&mut ctx.builder.instruction_body); + } + }, + Offset16::Two(r1, r2) => { + wasm_util::load_aligned_u16( + &mut ctx.builder.instruction_body, + ::global_pointers::get_reg16_offset(r1), + ); + wasm_util::load_aligned_u16( + &mut ctx.builder.instruction_body, + ::global_pointers::get_reg16_offset(r2), + ); + wasm_util::add_i32(&mut ctx.builder.instruction_body); + + if immediate_value != 0 { + wasm_util::push_i32(&mut ctx.builder.instruction_body, immediate_value); + wasm_util::add_i32(&mut ctx.builder.instruction_body); + } + + wasm_util::push_i32(&mut ctx.builder.instruction_body, 0xFFFF); + wasm_util::and_i32(&mut ctx.builder.instruction_body); + }, + } + + jit_add_seg_offset(ctx, seg); +} + +fn gen16(ctx: &mut JitContext, modrm_byte: u8) { + match modrm_byte & !0o070 { + 0o000 => gen16_case(ctx, DS, Offset16::Two(BX, SI), Imm16::None), + 0o001 => gen16_case(ctx, DS, Offset16::Two(BX, DI), Imm16::None), + 0o002 => gen16_case(ctx, SS, Offset16::Two(BP, SI), Imm16::None), + 0o003 => gen16_case(ctx, SS, Offset16::Two(BP, DI), Imm16::None), + 0o004 => gen16_case(ctx, DS, Offset16::One(SI), Imm16::None), + 0o005 => gen16_case(ctx, DS, Offset16::One(DI), Imm16::None), + 0o006 => gen16_case(ctx, DS, Offset16::Zero, Imm16::Imm16), + 0o007 => gen16_case(ctx, DS, Offset16::One(BX), Imm16::None), + + 0o100 => gen16_case(ctx, DS, Offset16::Two(BX, SI), Imm16::Imm8), + 0o101 => gen16_case(ctx, DS, Offset16::Two(BX, DI), Imm16::Imm8), + 0o102 => gen16_case(ctx, SS, Offset16::Two(BP, SI), Imm16::Imm8), + 0o103 => gen16_case(ctx, SS, Offset16::Two(BP, DI), Imm16::Imm8), + 0o104 => gen16_case(ctx, DS, Offset16::One(SI), Imm16::Imm8), + 0o105 => gen16_case(ctx, DS, Offset16::One(DI), Imm16::Imm8), + 0o106 => gen16_case(ctx, SS, Offset16::One(BP), Imm16::Imm8), + 0o107 => gen16_case(ctx, DS, Offset16::One(BX), Imm16::Imm8), + + 0o200 => gen16_case(ctx, DS, Offset16::Two(BX, SI), Imm16::Imm16), + 0o201 => gen16_case(ctx, DS, Offset16::Two(BX, DI), Imm16::Imm16), + 0o202 => gen16_case(ctx, SS, Offset16::Two(BP, SI), Imm16::Imm16), + 0o203 => gen16_case(ctx, SS, Offset16::Two(BP, DI), Imm16::Imm16), + 0o204 => gen16_case(ctx, DS, Offset16::One(SI), Imm16::Imm16), + 0o205 => gen16_case(ctx, DS, Offset16::One(DI), Imm16::Imm16), + 0o206 => gen16_case(ctx, SS, Offset16::One(BP), Imm16::Imm16), + 0o207 => gen16_case(ctx, DS, Offset16::One(BX), Imm16::Imm16), + + _ => assert!(false), + } +} + +#[derive(PartialEq)] +enum Imm32 { + None, + Imm8, + Imm32, +} + +enum Offset { + Reg(u32), + Sib, + None, +} + +fn gen32_case(ctx: &mut JitContext, seg: u32, offset: Offset, imm: Imm32) { + match offset { + Offset::Sib => { + gen_sib(ctx, imm != Imm32::None); + + let immediate_value = match imm { + Imm32::None => 0, + Imm32::Imm8 => ctx.cpu.read_imm8s() as i32, + Imm32::Imm32 => ctx.cpu.read_imm32() as i32, + }; + + if immediate_value != 0 { + wasm_util::push_i32(&mut ctx.builder.instruction_body, immediate_value); + wasm_util::add_i32(&mut ctx.builder.instruction_body); + } + }, + Offset::Reg(r) => { + let immediate_value = match imm { + Imm32::None => 0, + Imm32::Imm8 => ctx.cpu.read_imm8s() as i32, + Imm32::Imm32 => ctx.cpu.read_imm32() as i32, + }; + wasm_util::load_aligned_i32( + &mut ctx.builder.instruction_body, + ::global_pointers::get_reg32_offset(r), + ); + if immediate_value != 0 { + wasm_util::push_i32(&mut ctx.builder.instruction_body, immediate_value); + wasm_util::add_i32(&mut ctx.builder.instruction_body); + } + jit_add_seg_offset(ctx, seg); + }, + Offset::None => { + let immediate_value = match imm { + Imm32::None => 0, + Imm32::Imm8 => ctx.cpu.read_imm8s() as i32, + Imm32::Imm32 => ctx.cpu.read_imm32() as i32, + }; + wasm_util::push_i32(&mut ctx.builder.instruction_body, immediate_value); + jit_add_seg_offset(ctx, seg); + }, + } +} + +fn gen32(ctx: &mut JitContext, modrm_byte: u8) { + match modrm_byte & !0o070 { + 0o000 => gen32_case(ctx, DS, Offset::Reg(EAX), Imm32::None), + 0o001 => gen32_case(ctx, DS, Offset::Reg(ECX), Imm32::None), + 0o002 => gen32_case(ctx, DS, Offset::Reg(EDX), Imm32::None), + 0o003 => gen32_case(ctx, DS, Offset::Reg(EBX), Imm32::None), + 0o004 => gen32_case(ctx, DS, Offset::Sib, Imm32::None), + 0o005 => gen32_case(ctx, DS, Offset::None, Imm32::Imm32), + 0o006 => gen32_case(ctx, DS, Offset::Reg(ESI), Imm32::None), + 0o007 => gen32_case(ctx, DS, Offset::Reg(EDI), Imm32::None), + + 0o100 => gen32_case(ctx, DS, Offset::Reg(EAX), Imm32::Imm8), + 0o101 => gen32_case(ctx, DS, Offset::Reg(ECX), Imm32::Imm8), + 0o102 => gen32_case(ctx, DS, Offset::Reg(EDX), Imm32::Imm8), + 0o103 => gen32_case(ctx, DS, Offset::Reg(EBX), Imm32::Imm8), + 0o104 => gen32_case(ctx, DS, Offset::Sib, Imm32::Imm8), + 0o105 => gen32_case(ctx, SS, Offset::Reg(EBP), Imm32::Imm8), + 0o106 => gen32_case(ctx, DS, Offset::Reg(ESI), Imm32::Imm8), + 0o107 => gen32_case(ctx, DS, Offset::Reg(EDI), Imm32::Imm8), + + 0o200 => gen32_case(ctx, DS, Offset::Reg(EAX), Imm32::Imm32), + 0o201 => gen32_case(ctx, DS, Offset::Reg(ECX), Imm32::Imm32), + 0o202 => gen32_case(ctx, DS, Offset::Reg(EDX), Imm32::Imm32), + 0o203 => gen32_case(ctx, DS, Offset::Reg(EBX), Imm32::Imm32), + 0o204 => gen32_case(ctx, DS, Offset::Sib, Imm32::Imm32), + 0o205 => gen32_case(ctx, SS, Offset::Reg(EBP), Imm32::Imm32), + 0o206 => gen32_case(ctx, DS, Offset::Reg(ESI), Imm32::Imm32), + 0o207 => gen32_case(ctx, DS, Offset::Reg(EDI), Imm32::Imm32), + + _ => assert!(false), + } +} + +fn gen_sib(ctx: &mut JitContext, mod_is_nonzero: bool) { + let sib_byte = ctx.cpu.read_imm8(); + let r = sib_byte & 7; + let m = sib_byte >> 3 & 7; + + let seg; + + // Generates: get_seg_prefix(seg) + base + // Where base is a register or constant + + if r == 4 { + seg = SS; + let base_addr = ::global_pointers::get_reg32_offset(ESP); + wasm_util::load_aligned_i32(&mut ctx.builder.instruction_body, base_addr); + } + else if r == 5 { + if mod_is_nonzero { + seg = SS; + let base_addr = ::global_pointers::get_reg32_offset(EBP); + wasm_util::load_aligned_i32(&mut ctx.builder.instruction_body, base_addr); + } + else { + seg = DS; + let base = ctx.cpu.read_imm32(); + wasm_util::push_i32(&mut ctx.builder.instruction_body, base as i32); + } + } + else { + seg = DS; + let base_addr = ::global_pointers::get_reg32_offset(r as u32); + wasm_util::load_aligned_i32(&mut ctx.builder.instruction_body, base_addr); + } + + jit_add_seg_offset(ctx, seg); + + // 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: + + let s = sib_byte >> 6 & 3; + + wasm_util::load_aligned_i32( + &mut ctx.builder.instruction_body, + ::global_pointers::get_reg32_offset(m as u32), + ); + wasm_util::push_i32(&mut ctx.builder.instruction_body, s as i32); + wasm_util::shl_i32(&mut ctx.builder.instruction_body); + + wasm_util::add_i32(&mut ctx.builder.instruction_body); +} + +fn can_optimize_get_seg(ctx: &mut JitContext, segment: u32) -> bool { + (segment == DS || segment == SS) && ctx.cpu.has_flat_segmentation() +} + +fn jit_add_seg_offset(ctx: &mut JitContext, default_segment: u32) { + let prefix = ctx.cpu.prefixes & PREFIX_MASK_SEGMENT; + let seg = if prefix != 0 { + prefix - 1 + } + else { + default_segment + }; + + if can_optimize_get_seg(ctx, seg) || prefix == SEG_PREFIX_ZERO { + return; + } + + wasm_util::push_i32(&mut ctx.builder.instruction_body, seg as i32); + wasm_util::call_fn(&mut ctx.builder.instruction_body, ::jit::FN_GET_SEG_IDX); + wasm_util::add_i32(&mut ctx.builder.instruction_body); +} diff --git a/src/rust/opstats.rs b/src/rust/opstats.rs new file mode 100644 index 00000000..79f6e2aa --- /dev/null +++ b/src/rust/opstats.rs @@ -0,0 +1,49 @@ +use codegen::gen_increment_mem32; +use global_pointers; +use wasmgen::module_init::WasmBuilder; + +pub fn gen_opstats(builder: &mut WasmBuilder, mut instruction: u32) { + if !cfg!(debug_assertions) { + return; + } + let mut is_0f = false; + + for _ in 0..4 { + let opcode = instruction & 0xFF; + instruction >>= 8; + + // TODO: + // - If instruction depends on middle bits of modrm_byte, split + // - Split depending on memory or register variant + // - If the instruction uses 4 or more prefixes, only the prefixes will be counted + + if is_0f { + gen_increment_mem32(builder, global_pointers::OPSTATS_BUFFER_0F + 4 * opcode); + break; + } + else { + gen_increment_mem32(builder, global_pointers::OPSTATS_BUFFER + 4 * opcode); + + if opcode == 0x0F { + is_0f = true; + } + else if opcode == 0x26 + || opcode == 0x2E + || opcode == 0x36 + || opcode == 0x3E + || opcode == 0x64 + || opcode == 0x65 + || opcode == 0x66 + || opcode == 0x67 + || opcode == 0xF0 + || opcode == 0xF2 + || opcode == 0xF3 + { + // prefix + } + else { + break; + } + } + } +} diff --git a/src/rust/page.rs b/src/rust/page.rs new file mode 100644 index 00000000..17461284 --- /dev/null +++ b/src/rust/page.rs @@ -0,0 +1,8 @@ +#[derive(Copy, Clone, Eq, Hash, PartialEq)] +pub struct Page(u32); +impl Page { + pub fn page_of(address: u32) -> Page { Page(address >> 12) } + pub fn to_address(self) -> u32 { self.0 << 12 } + + pub fn to_u32(self) -> u32 { self.0 } +} diff --git a/src/rust/prefix.rs b/src/rust/prefix.rs new file mode 100644 index 00000000..ba8adaa6 --- /dev/null +++ b/src/rust/prefix.rs @@ -0,0 +1,14 @@ +pub const PREFIX_REPZ: u32 = 0b01000; +pub const PREFIX_REPNZ: u32 = 0b10000; + +pub const PREFIX_MASK_OPSIZE: u32 = 0b100000; +pub const PREFIX_MASK_ADDRSIZE: u32 = 0b1000000; + +pub const PREFIX_66: u32 = PREFIX_MASK_OPSIZE; +pub const PREFIX_67: u32 = PREFIX_MASK_ADDRSIZE; +pub const PREFIX_F2: u32 = PREFIX_REPNZ; +pub const PREFIX_F3: u32 = PREFIX_REPZ; + +pub const SEG_PREFIX_ZERO: u32 = 7; + +pub const PREFIX_MASK_SEGMENT: u32 = 0b111; diff --git a/src/rust/profiler.rs b/src/rust/profiler.rs new file mode 100644 index 00000000..80f6dd94 --- /dev/null +++ b/src/rust/profiler.rs @@ -0,0 +1,63 @@ +#[repr(C)] +#[allow(non_camel_case_types, dead_code)] +pub enum stat { + S_COMPILE, + S_COMPILE_SUCCESS, + S_COMPILE_CUT_OFF_AT_END_OF_PAGE, + S_COMPILE_WITH_LOOP_SAFETY, + S_COMPILE_BASIC_BLOCK, + S_COMPILE_ENTRY_POINT, + S_CACHE_MISMATCH, + + S_RUN_INTERPRETED, + S_RUN_INTERPRETED_PENDING, + S_RUN_INTERPRETED_NEAR_END_OF_PAGE, + S_RUN_INTERPRETED_DIFFERENT_STATE, + S_RUN_INTERPRETED_STEPS, + + S_RUN_FROM_CACHE, + S_RUN_FROM_CACHE_STEPS, + + S_TRIGGER_CPU_EXCEPTION, + + S_SAFE_READ32_FAST, + S_SAFE_READ32_SLOW_PAGE_CROSSED, + S_SAFE_READ32_SLOW_NOT_VALID, + S_SAFE_READ32_SLOW_NOT_USER, + S_SAFE_READ32_SLOW_IN_MAPPED_RANGE, + + S_SAFE_WRITE32_FAST, + S_SAFE_WRITE32_SLOW_PAGE_CROSSED, + S_SAFE_WRITE32_SLOW_NOT_VALID, + S_SAFE_WRITE32_SLOW_NOT_USER, + S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE, + S_SAFE_WRITE32_SLOW_READ_ONLY, + S_SAFE_WRITE32_SLOW_HAS_CODE, + + S_DO_RUN, + S_DO_MANY_CYCLES, + S_CYCLE_INTERNAL, + + S_INVALIDATE_PAGE, + S_INVALIDATE_CACHE_ENTRY, + + S_NONFAULTING_OPTIMIZATION, + + S_CLEAR_TLB, + S_FULL_CLEAR_TLB, + S_TLB_FULL, + S_TLB_GLOBAL_FULL, +} + +#[cfg(debug_assertions)] +mod unsafe_extern { + extern "C" { + pub fn profiler_stat_increment(stat: ::profiler::stat); + } +} + +#[cfg(debug_assertions)] +pub fn stat_increment(stat: stat) { unsafe { unsafe_extern::profiler_stat_increment(stat) } } + +#[cfg(not(debug_assertions))] +pub fn stat_increment(_stat: stat) {} diff --git a/src/rust/regs.rs b/src/rust/regs.rs new file mode 100644 index 00000000..25113828 --- /dev/null +++ b/src/rust/regs.rs @@ -0,0 +1,25 @@ +pub const ES: u32 = 0; +pub const CS: u32 = 1; +pub const SS: u32 = 2; +pub const DS: u32 = 3; +pub const FS: u32 = 4; +pub const GS: u32 = 5; + +pub const EAX: u32 = 0; +pub const ECX: u32 = 1; +pub const EDX: u32 = 2; +pub const EBX: u32 = 3; +pub const ESP: u32 = 4; +pub const EBP: u32 = 5; +pub const ESI: u32 = 6; +pub const EDI: u32 = 7; + +// Note: Different from C constants +pub const AX: u32 = 0; +pub const CX: u32 = 1; +pub const DX: u32 = 2; +pub const BX: u32 = 3; +pub const SP: u32 = 4; +pub const BP: u32 = 5; +pub const SI: u32 = 6; +pub const DI: u32 = 7; diff --git a/src/rust/state_flags.rs b/src/rust/state_flags.rs new file mode 100644 index 00000000..2e2e7553 --- /dev/null +++ b/src/rust/state_flags.rs @@ -0,0 +1,19 @@ +#[derive(Copy, Clone, PartialEq, Eq)] +pub struct CachedStateFlags(u32); + +impl CachedStateFlags { + const MASK_IS_32: u32 = 1 << 0; + const MASK_SS32: u32 = 1 << 1; + const MASK_CPL3: u32 = 1 << 2; + const MASK_FLAT_SEGS: u32 = 1 << 3; + + pub const EMPTY: CachedStateFlags = CachedStateFlags(0); + + pub fn of_u32(f: u32) -> CachedStateFlags { CachedStateFlags(f) } + pub fn to_u32(&self) -> u32 { self.0 } + + pub fn cpl3(&self) -> bool { self.0 & CachedStateFlags::MASK_CPL3 != 0 } + pub fn has_flat_segmentation(&self) -> bool { self.0 & CachedStateFlags::MASK_FLAT_SEGS != 0 } + pub fn is_32(&self) -> bool { self.0 & CachedStateFlags::MASK_IS_32 != 0 } + pub fn ssize_32(&self) -> bool { self.0 & CachedStateFlags::MASK_SS32 != 0 } +} diff --git a/src/rust/tlb.rs b/src/rust/tlb.rs new file mode 100644 index 00000000..c13856f8 --- /dev/null +++ b/src/rust/tlb.rs @@ -0,0 +1,6 @@ +pub const TLB_VALID: u32 = (1 << 0); +pub const TLB_READONLY: u32 = (1 << 1); +pub const TLB_NO_USER: u32 = (1 << 2); +//const TLB_IN_MAPPED_RANGE: u32 = (1 << 3); +pub const TLB_GLOBAL: u32 = (1 << 4); +//const TLB_HAS_CODE: u32 = (1 << 5); diff --git a/src/rust/util.rs b/src/rust/util.rs index ba88bae5..98af60f6 100644 --- a/src/rust/util.rs +++ b/src/rust/util.rs @@ -71,84 +71,6 @@ impl SafeToI32 for usize { } } -pub fn write_leb_i32(buf: &mut Vec, mut v: i32) { - // Super complex stuff. See the following: - // https://en.wikipedia.org/wiki/LEB128#Encode_signed_integer - // http://llvm.org/doxygen/LEB128_8h_source.html#l00048 - - let mut more = true; - let negative = v < 0; - let size = 32; - while more { - let mut byte = (v & 0b1111111) as u8; // get last 7 bits - v >>= 7; // shift them away from the value - if negative { - v |= (!0 as i32) << (size - 7); // extend sign - } - let sign_bit = byte & (1 << 6); - if (v == 0 && sign_bit == 0) || (v == -1 && sign_bit != 0) { - more = false; - } - else { - byte |= 0b10000000; // turn on MSB - } - buf.push(byte); - } -} - -pub fn write_leb_u32(buf: &mut Vec, mut v: u32) { - loop { - let mut byte = v as u8 & 0b01111111; // get last 7 bits - v >>= 7; // shift them away from the value - if v != 0 { - byte |= 0b10000000; // turn on MSB - } - buf.push(byte); - if v == 0 { - break; - } - } -} - -pub fn write_fixed_leb16_at_idx(vec: &mut Vec, idx: usize, x: u16) { - dbg_assert!(x < (1 << 14)); // we have 14 bits of available space in 2 bytes for leb - vec[idx] = ((x & 0b1111111) | 0b10000000) as u8; - vec[idx + 1] = (x >> 7) as u8; -} - -pub fn write_fixed_leb32_at_idx(vec: &mut Vec, idx: usize, x: u32) { - dbg_assert!(x < (1 << 28)); // we have 28 bits of available space in 4 bytes for leb - vec[idx] = (x & 0b1111111) as u8 | 0b10000000; - vec[idx + 1] = (x >> 7 & 0b1111111) as u8 | 0b10000000; - vec[idx + 2] = (x >> 14 & 0b1111111) as u8 | 0b10000000; - vec[idx + 3] = (x >> 21 & 0b1111111) as u8; -} - -pub type PackedStr = (u64, u64, u64); - -#[allow(dead_code)] -pub fn pack_str(s: &str) -> PackedStr { - assert!(s.len() <= 24); - let mut a: [u8; 24] = [0; 24]; - for (i, ch) in s.char_indices() { - a[i] = ch as u8; - } - - unsafe { ::std::mem::transmute(a) } -} - -pub fn unpack_str(s: PackedStr) -> String { - let mut buf = String::with_capacity(24); - let bytes: [u8; 24] = unsafe { ::std::mem::transmute(s) }; - for i in 0..24 { - if bytes[i] == 0 { - break; - } - buf.push(bytes[i] as char); - } - buf -} - #[allow(dead_code)] pub const DEBUG: bool = cfg!(debug_assertions); @@ -169,30 +91,3 @@ pub fn _log_to_js_console(s: T) { log_from_wasm(s.as_bytes().as_ptr(), len); } } - -#[cfg(test)] -mod tests { - use quickcheck::TestResult; - use util::*; - - #[test] - fn packed_strs() { - let pstr = pack_str("foo"); - assert_eq!("foo", unpack_str(pstr)); - - let pstr = pack_str("abcdefghijkl"); - assert_eq!("abcdefghijkl", unpack_str(pstr)); - } - - quickcheck! { - fn prop(xs: Vec) -> TestResult { - if xs.len() > 24 || xs.contains(&0) { return TestResult::discard(); } - let xs = match String::from_utf8(xs) { - Ok(x) => x, - Err(_) => { return TestResult::discard(); }, - }; - TestResult::from_bool(xs == unpack_str(pack_str(&xs))) - } - } - -} diff --git a/src/rust/wasmgen/c_api.rs b/src/rust/wasmgen/c_api.rs deleted file mode 100644 index 1dbc36ab..00000000 --- a/src/rust/wasmgen/c_api.rs +++ /dev/null @@ -1,95 +0,0 @@ -use util::PackedStr; - -use wasmgen::module_init::get_module; -pub use wasmgen::module_init::wg_setup; - -#[no_mangle] -pub fn wg_get_code_section() -> *mut Vec { &mut get_module().code_section } - -#[no_mangle] -pub fn wg_get_instruction_body() -> *mut Vec { &mut get_module().instruction_body } - -#[no_mangle] -pub fn wg_reset() { - let m = get_module(); - m.reset(); -} - -#[no_mangle] -pub fn wg_finish(no_of_locals_i32: u8) { - let m = get_module(); - m.finish(no_of_locals_i32); -} - -#[no_mangle] -pub fn wg_get_fn_idx(fn_name_a: u64, fn_name_b: u64, fn_name_c: u64, type_idx: u8) -> u16 { - let fn_name: PackedStr = (fn_name_a, fn_name_b, fn_name_c); - let m = get_module(); - m.get_fn_idx(fn_name, type_idx) -} - -#[no_mangle] -pub fn wg_get_op_ptr() -> *const u8 { - let m = get_module(); - m.get_op_ptr() -} - -#[no_mangle] -pub fn wg_get_op_len() -> usize { - let m = get_module(); - m.get_op_len() -} - -#[no_mangle] -pub fn wg_commit_instruction_body_to_cs() { - let m = get_module(); - m.commit_instruction_body_cs(); -} - -#[cfg(test)] -mod tests { - use std::fs::File; - use std::io::prelude::*; - use util::*; - use wasmgen::c_api::*; - use wasmgen::module_init::*; - use wasmgen::wasm_util::*; - - #[test] - fn c_api_test() { - wg_setup(); - let m = get_module(); - let cs = &mut get_module().code_section; - let instruction_body = &mut get_module().instruction_body; - - wg_call_fn(cs, m.get_fn_idx(pack_str("foo"), FN0_TYPE_INDEX)); - wg_call_fn(cs, m.get_fn_idx(pack_str("bar"), FN0_TYPE_INDEX)); - - wg_finish(2); - wg_reset(); - - wg_push_i32(cs, 2); - wg_call_fn( - instruction_body, - m.get_fn_idx(pack_str("baz"), FN1_RET_TYPE_INDEX), - ); - wg_call_fn( - instruction_body, - m.get_fn_idx(pack_str("foo"), FN1_TYPE_INDEX), - ); - - wg_commit_instruction_body_to_cs(); - - wg_finish(0); - - let op_ptr = wg_get_op_ptr(); - let op_len = wg_get_op_len(); - dbg_log!("op_ptr: {:?}, op_len: {:?}", op_ptr, op_len); - - let mut f = - File::create("build/wg_dummy_output.wasm").expect("creating wg_dummy_output.wasm"); - f.write_all(&get_module().output) - .expect("write wg_dummy_output.wasm"); - } - -} diff --git a/src/rust/wasmgen/mod.rs b/src/rust/wasmgen/mod.rs index d7ee2beb..6b2d429b 100644 --- a/src/rust/wasmgen/mod.rs +++ b/src/rust/wasmgen/mod.rs @@ -1,5 +1,3 @@ -mod module_init; +pub mod module_init; mod wasm_opcodes; - -pub mod c_api; pub mod wasm_util; diff --git a/src/rust/wasmgen/module_init.rs b/src/rust/wasmgen/module_init.rs index c6fabb0d..bc527054 100644 --- a/src/rust/wasmgen/module_init.rs +++ b/src/rust/wasmgen/module_init.rs @@ -1,10 +1,5 @@ -use std::mem; -use std::ptr::NonNull; - -use util::{ - unpack_str, write_fixed_leb16_at_idx, write_fixed_leb32_at_idx, write_leb_u32, PackedStr, - SafeToU16, SafeToU8, -}; +use leb::{write_fixed_leb16_at_idx, write_fixed_leb32_at_idx, write_leb_u32}; +use util::{SafeToU16, SafeToU8}; use wasmgen::wasm_opcodes as op; #[allow(dead_code)] @@ -25,20 +20,6 @@ pub const FN2_RET_TYPE_INDEX: u8 = 6; pub const NR_FN_TYPE_INDEXES: u8 = 7; -static mut MODULE_PTR: NonNull = - unsafe { NonNull::new_unchecked(mem::align_of::() as *mut _) }; - -#[no_mangle] -pub fn wg_setup() { - let wm = Box::new(WasmBuilder::new()); - unsafe { - MODULE_PTR = NonNull::new(Box::into_raw(wm)).expect("assigning module ptr"); - } - get_module().init(); -} - -pub fn get_module<'a>() -> &'a mut WasmBuilder { unsafe { MODULE_PTR.as_mut() } } - pub struct WasmBuilder { pub output: Vec, pub code_section: Vec, @@ -200,8 +181,7 @@ impl WasmBuilder { } /// Goes over the import block to find index of an import entry by function name - pub fn get_import_index(&self, fn_name: PackedStr) -> Option { - let fn_name = unpack_str(fn_name); + pub fn get_import_index(&self, fn_name: &str) -> Option { let mut offset = self.idx_import_entries; for i in 0..self.import_count { offset += 1; // skip length of module name @@ -269,10 +249,9 @@ impl WasmBuilder { self.set_import_table_size(new_table_size); } - pub fn write_import_entry(&mut self, fn_name: PackedStr, type_index: u8) -> u16 { + pub fn write_import_entry(&mut self, fn_name: &str, type_index: u8) -> u16 { self.output.push(1); // length of module name self.output.push('e' as u8); // module name - let fn_name = unpack_str(fn_name); self.output.push(fn_name.len().safe_to_u8()); self.output.extend(fn_name.as_bytes()); self.output.push(op::EXT_FUNCTION); @@ -314,7 +293,7 @@ impl WasmBuilder { write_fixed_leb16_at_idx(&mut self.output, next_op_idx, self.import_count - 1); } - pub fn get_fn_idx(&mut self, fn_name: PackedStr, type_index: u8) -> u16 { + pub fn get_fn_idx(&mut self, fn_name: &str, type_index: u8) -> u16 { match self.get_import_index(fn_name) { Some(idx) => idx, None => { @@ -326,26 +305,60 @@ impl WasmBuilder { pub fn get_op_ptr(&self) -> *const u8 { self.output.as_ptr() } - pub fn get_op_len(&self) -> usize { self.output.len() } + pub fn get_op_len(&self) -> u32 { self.output.len() as u32 } - pub fn commit_instruction_body_cs(&mut self) { + pub fn commit_instruction_body_to_cs(&mut self) { self.code_section.append(&mut self.instruction_body); } } #[cfg(test)] mod tests { - use util::pack_str; + use std::fs::File; + use std::io::prelude::*; use wasmgen::module_init::*; + use wasmgen::wasm_util::*; #[test] fn import_table_management() { let mut w = WasmBuilder::new(); w.init(); - assert_eq!(0, w.get_fn_idx(pack_str("foo"), FN0_TYPE_INDEX)); - assert_eq!(1, w.get_fn_idx(pack_str("bar"), FN1_TYPE_INDEX)); - assert_eq!(0, w.get_fn_idx(pack_str("foo"), FN0_TYPE_INDEX)); - assert_eq!(2, w.get_fn_idx(pack_str("baz"), FN2_TYPE_INDEX)); + assert_eq!(0, w.get_fn_idx("foo", FN0_TYPE_INDEX)); + assert_eq!(1, w.get_fn_idx("bar", FN1_TYPE_INDEX)); + assert_eq!(0, w.get_fn_idx("foo", FN0_TYPE_INDEX)); + assert_eq!(2, w.get_fn_idx("baz", FN2_TYPE_INDEX)); } + #[test] + fn builder_test() { + let mut m = WasmBuilder::new(); + m.init(); + + let mut foo_index = m.get_fn_idx("foo", FN0_TYPE_INDEX); + call_fn(&mut m.code_section, foo_index); + + let bar_index = m.get_fn_idx("bar", FN0_TYPE_INDEX); + call_fn(&mut m.code_section, bar_index); + + m.finish(2); + m.reset(); + + push_i32(&mut m.code_section, 2); + + let baz_index = m.get_fn_idx("baz", FN1_RET_TYPE_INDEX); + call_fn(&mut m.instruction_body, baz_index); + foo_index = m.get_fn_idx("foo", FN1_TYPE_INDEX); + call_fn(&mut m.instruction_body, foo_index); + + m.commit_instruction_body_to_cs(); + + m.finish(0); + + let op_ptr = m.get_op_ptr(); + let op_len = m.get_op_len(); + dbg_log!("op_ptr: {:?}, op_len: {:?}", op_ptr, op_len); + + let mut f = File::create("build/dummy_output.wasm").expect("creating dummy_output.wasm"); + f.write_all(&m.output).expect("write dummy_output.wasm"); + } } diff --git a/src/rust/wasmgen/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs index 0c456a43..74e30c2e 100644 --- a/src/rust/wasmgen/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -1,20 +1,12 @@ -use util::{write_fixed_leb16_at_idx, write_leb_i32, write_leb_u32}; +use leb::{write_fixed_leb16_at_idx, write_leb_i32, write_leb_u32}; use wasmgen::wasm_opcodes as op; -#[no_mangle] -pub fn wg_push_i32(buf: &mut Vec, v: i32) { +pub fn push_i32(buf: &mut Vec, v: i32) { buf.push(op::OP_I32CONST); write_leb_i32(buf, v); } -#[no_mangle] -pub fn wg_push_u32(buf: &mut Vec, v: u32) { - buf.push(op::OP_I32CONST); - write_leb_u32(buf, v); -} - -#[no_mangle] -pub fn wg_load_aligned_u16(buf: &mut Vec, addr: u32) { +pub fn load_aligned_u16(buf: &mut Vec, addr: u32) { // doesn't cause a failure in the generated code, but it will be much slower dbg_assert!((addr & 1) == 0); @@ -25,43 +17,35 @@ pub fn wg_load_aligned_u16(buf: &mut Vec, addr: u32) { buf.push(0); // immediate offset } -#[no_mangle] -pub fn wg_load_aligned_i32(buf: &mut Vec, addr: u32) { +pub fn load_aligned_i32(buf: &mut Vec, addr: u32) { // doesn't cause a failure in the generated code, but it will be much slower dbg_assert!((addr & 3) == 0); - wg_push_i32(buf, addr as i32); - wg_load_aligned_i32_from_stack(buf, 0); + push_i32(buf, addr as i32); + load_aligned_i32_from_stack(buf, 0); } -#[no_mangle] -pub fn wg_store_aligned_u16(buf: &mut Vec) { +pub fn store_aligned_u16(buf: &mut Vec) { buf.push(op::OP_I32STORE16); buf.push(op::MEM_ALIGN16); buf.push(0); // immediate offset } -#[no_mangle] -pub fn wg_store_aligned_i32(buf: &mut Vec) { +pub fn store_aligned_i32(buf: &mut Vec) { buf.push(op::OP_I32STORE); buf.push(op::MEM_ALIGN32); buf.push(0); // immediate offset } -#[no_mangle] -pub fn wg_add_i32(buf: &mut Vec) { buf.push(op::OP_I32ADD); } +pub fn add_i32(buf: &mut Vec) { buf.push(op::OP_I32ADD); } -#[no_mangle] -pub fn wg_and_i32(buf: &mut Vec) { buf.push(op::OP_I32AND); } +pub fn and_i32(buf: &mut Vec) { buf.push(op::OP_I32AND); } -#[no_mangle] -pub fn wg_or_i32(buf: &mut Vec) { buf.push(op::OP_I32OR); } +pub fn or_i32(buf: &mut Vec) { buf.push(op::OP_I32OR); } -#[no_mangle] -pub fn wg_shl_i32(buf: &mut Vec) { buf.push(op::OP_I32SHL); } +pub fn shl_i32(buf: &mut Vec) { buf.push(op::OP_I32SHL); } -#[no_mangle] -pub fn wg_call_fn(buf: &mut Vec, fn_idx: u16) { +pub fn call_fn(buf: &mut Vec, fn_idx: u16) { buf.push(op::OP_CALL); let buf_len = buf.len(); buf.push(0); @@ -69,60 +53,37 @@ pub fn wg_call_fn(buf: &mut Vec, fn_idx: u16) { write_fixed_leb16_at_idx(buf, buf_len, fn_idx); } -#[no_mangle] -pub fn wg_call_fn_with_arg(buf: &mut Vec, fn_idx: u16, arg0: i32) { - wg_push_i32(buf, arg0); - wg_call_fn(buf, fn_idx); -} +pub fn eq_i32(buf: &mut Vec) { buf.push(op::OP_I32EQ); } -#[no_mangle] -pub fn wg_eq_i32(buf: &mut Vec) { buf.push(op::OP_I32EQ); } +pub fn ne_i32(buf: &mut Vec) { buf.push(op::OP_I32NE); } -#[no_mangle] -pub fn wg_ne_i32(buf: &mut Vec) { buf.push(op::OP_I32NE); } +pub fn le_i32(buf: &mut Vec) { buf.push(op::OP_I32LES); } -#[no_mangle] -pub fn wg_le_i32(buf: &mut Vec) { buf.push(op::OP_I32LES); } +pub fn lt_i32(buf: &mut Vec) { buf.push(op::OP_I32LTS); } -#[no_mangle] -pub fn wg_lt_i32(buf: &mut Vec) { buf.push(op::OP_I32LTS); } +pub fn ge_i32(buf: &mut Vec) { buf.push(op::OP_I32GES); } -#[no_mangle] -pub fn wg_ge_i32(buf: &mut Vec) { buf.push(op::OP_I32GES); } +pub fn gt_i32(buf: &mut Vec) { buf.push(op::OP_I32GTS); } -#[no_mangle] -pub fn wg_gt_i32(buf: &mut Vec) { buf.push(op::OP_I32GTS); } - -#[no_mangle] -pub fn wg_if_i32(buf: &mut Vec) { +pub fn if_i32(buf: &mut Vec) { buf.push(op::OP_IF); buf.push(op::TYPE_I32); } -#[no_mangle] -pub fn wg_block_i32(buf: &mut Vec) { +pub fn block_i32(buf: &mut Vec) { buf.push(op::OP_BLOCK); buf.push(op::TYPE_I32); } -#[no_mangle] -pub fn wg_tee_local(buf: &mut Vec, idx: i32) { - buf.push(op::OP_TEELOCAL); - write_leb_i32(buf, idx); -} +pub fn xor_i32(buf: &mut Vec) { buf.push(op::OP_I32XOR); } -#[no_mangle] -pub fn wg_xor_i32(buf: &mut Vec) { buf.push(op::OP_I32XOR); } - -#[no_mangle] -pub fn wg_load_unaligned_i32_from_stack(buf: &mut Vec, byte_offset: u32) { +pub fn load_unaligned_i32_from_stack(buf: &mut Vec, byte_offset: u32) { buf.push(op::OP_I32LOAD); buf.push(op::MEM_NO_ALIGN); write_leb_u32(buf, byte_offset); } -#[no_mangle] -pub fn wg_load_aligned_i32_from_stack(buf: &mut Vec, byte_offset: u32) { +pub fn load_aligned_i32_from_stack(buf: &mut Vec, byte_offset: u32) { buf.push(op::OP_I32LOAD); buf.push(op::MEM_ALIGN32); write_leb_u32(buf, byte_offset); @@ -130,101 +91,85 @@ pub fn wg_load_aligned_i32_from_stack(buf: &mut Vec, byte_offset: u32) { // XXX: Function naming should be consistent regarding both alignment and accepting an // offset. Leaving as-is for the Rust port to cleanup -#[no_mangle] -pub fn wg_store_unaligned_i32(buf: &mut Vec, byte_offset: u32) { +pub fn store_unaligned_i32(buf: &mut Vec, byte_offset: u32) { buf.push(op::OP_I32STORE); buf.push(op::MEM_NO_ALIGN); write_leb_u32(buf, byte_offset); } -#[no_mangle] -pub fn wg_shr_u32(buf: &mut Vec) { buf.push(op::OP_I32SHRU); } +pub fn shr_u32(buf: &mut Vec) { buf.push(op::OP_I32SHRU); } -#[no_mangle] -pub fn wg_shr_i32(buf: &mut Vec) { buf.push(op::OP_I32SHRS); } +pub fn shr_i32(buf: &mut Vec) { buf.push(op::OP_I32SHRS); } -#[no_mangle] -pub fn wg_eqz_i32(buf: &mut Vec) { buf.push(op::OP_I32EQZ); } +pub fn eqz_i32(buf: &mut Vec) { buf.push(op::OP_I32EQZ); } -#[no_mangle] -pub fn wg_if_void(buf: &mut Vec) { +pub fn if_void(buf: &mut Vec) { buf.push(op::OP_IF); buf.push(op::TYPE_VOID_BLOCK); } -#[no_mangle] -pub fn wg_else(buf: &mut Vec) { buf.push(op::OP_ELSE); } +pub fn else_(buf: &mut Vec) { buf.push(op::OP_ELSE); } -#[no_mangle] -pub fn wg_loop_void(buf: &mut Vec) { +pub fn loop_void(buf: &mut Vec) { buf.push(op::OP_LOOP); buf.push(op::TYPE_VOID_BLOCK); } -#[no_mangle] -pub fn wg_block_void(buf: &mut Vec) { +pub fn block_void(buf: &mut Vec) { buf.push(op::OP_BLOCK); buf.push(op::TYPE_VOID_BLOCK); } -#[no_mangle] -pub fn wg_block_end(buf: &mut Vec) { buf.push(op::OP_END); } +pub fn block_end(buf: &mut Vec) { buf.push(op::OP_END); } -#[no_mangle] -pub fn wg_return(buf: &mut Vec) { buf.push(op::OP_RETURN); } +pub fn return_(buf: &mut Vec) { buf.push(op::OP_RETURN); } -#[no_mangle] -pub fn wg_drop(buf: &mut Vec) { buf.push(op::OP_DROP); } +pub fn drop(buf: &mut Vec) { buf.push(op::OP_DROP); } // Generate a br_table where an input of [i] will branch [i]th outer block, // where [i] is passed on the wasm stack -#[no_mangle] -pub fn wg_brtable_and_cases(buf: &mut Vec, cases_count: i32) { - assert!(cases_count >= 0); - +pub fn brtable_and_cases(buf: &mut Vec, cases_count: u32) { buf.push(op::OP_BRTABLE); - write_leb_u32(buf, cases_count as u32); + write_leb_u32(buf, cases_count); for i in 0..(cases_count + 1) { - write_leb_u32(buf, i as u32); + write_leb_u32(buf, i); } } -#[no_mangle] -pub fn wg_br(buf: &mut Vec, depth: i32) { +pub fn br(buf: &mut Vec, depth: u32) { buf.push(op::OP_BR); - write_leb_i32(buf, depth); + write_leb_u32(buf, depth); } -#[no_mangle] -pub fn wg_get_local(buf: &mut Vec, idx: i32) { +pub fn get_local(buf: &mut Vec, idx: u32) { buf.push(op::OP_GETLOCAL); - write_leb_i32(buf, idx); + write_leb_u32(buf, idx); } -#[no_mangle] -pub fn wg_set_local(buf: &mut Vec, idx: i32) { +pub fn set_local(buf: &mut Vec, idx: u32) { buf.push(op::OP_SETLOCAL); - write_leb_i32(buf, idx); + write_leb_u32(buf, idx); } -#[no_mangle] -pub fn wg_unreachable(buf: &mut Vec) { buf.push(op::OP_UNREACHABLE); } - -#[no_mangle] -pub fn wg_increment_mem32(buf: &mut Vec, addr: i32) { wg_increment_variable(buf, addr, 1) } - -#[no_mangle] -pub fn wg_increment_variable(buf: &mut Vec, addr: i32, n: i32) { - wg_push_i32(buf, addr); - wg_load_aligned_i32(buf, addr as u32); - wg_push_i32(buf, n); - wg_add_i32(buf); - wg_store_aligned_i32(buf); +pub fn tee_local(buf: &mut Vec, idx: u32) { + buf.push(op::OP_TEELOCAL); + write_leb_u32(buf, idx); } -#[no_mangle] -pub fn wg_load_aligned_u16_from_stack(buf: &mut Vec, byte_offset: u32) { +pub fn unreachable(buf: &mut Vec) { buf.push(op::OP_UNREACHABLE); } + +pub fn increment_mem32(buf: &mut Vec, addr: u32) { increment_variable(buf, addr, 1) } + +pub fn increment_variable(buf: &mut Vec, addr: u32, n: i32) { + push_i32(buf, addr as i32); + load_aligned_i32(buf, addr); + push_i32(buf, n); + add_i32(buf); + store_aligned_i32(buf); +} + +pub fn load_aligned_u16_from_stack(buf: &mut Vec, byte_offset: u32) { buf.push(op::OP_I32LOAD16U); buf.push(op::MEM_ALIGN16); write_leb_u32(buf, byte_offset); diff --git a/tests/expect/run.js b/tests/expect/run.js index bb4477ae..ba529dbb 100755 --- a/tests/expect/run.js +++ b/tests/expect/run.js @@ -192,7 +192,7 @@ Hint: Use tests/expect/run.js --interactive to interactively accept changes. const START_ADDRESS = 0x1000; cpu.mem8.set(executable, START_ADDRESS); - cpu.jit_force_generate_unsafe(START_ADDRESS); + cpu.jit_force_generate(START_ADDRESS); }); } diff --git a/tests/expect/tests/mov32-mem.wast b/tests/expect/tests/mov32-mem.wast index 9465335c..eaed0249 100644 --- a/tests/expect/tests/mov32-mem.wast +++ b/tests/expect/tests/mov32-mem.wast @@ -56,7 +56,7 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.store offset=12582912 align=1 + (i32.store offset=8388608 align=1 (tee_local $l4 (i32.xor (i32.and @@ -104,7 +104,7 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.store offset=12582912 align=1 + (i32.store offset=8388608 align=1 (tee_local $l4 (i32.xor (i32.and @@ -150,7 +150,7 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.load offset=12582912 align=1 + (i32.load offset=8388608 align=1 (i32.xor (i32.and (get_local $l3) @@ -193,7 +193,7 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.load offset=12582912 align=1 + (i32.load offset=8388608 align=1 (i32.xor (i32.and (get_local $l3) diff --git a/tests/nasm/run.js b/tests/nasm/run.js index 8db192ad..3f4d958c 100755 --- a/tests/nasm/run.js +++ b/tests/nasm/run.js @@ -216,7 +216,7 @@ else { if(FORCE_JIT) { - cpu.jit_force_generate_unsafe(cpu.instruction_pointer[0]); + cpu.jit_force_generate(cpu.instruction_pointer[0]); cpu.test_hook_did_finalize_wasm = function() { diff --git a/tests/rust/verify-wasmgen-dummy-output.js b/tests/rust/verify-wasmgen-dummy-output.js index 29b32157..74c0ead7 100755 --- a/tests/rust/verify-wasmgen-dummy-output.js +++ b/tests/rust/verify-wasmgen-dummy-output.js @@ -6,7 +6,7 @@ process.on("unhandledRejection", exn => { throw exn; }); const fs = require("fs"); const path = require("path"); -const DUMMY_MODULE_PATH = path.resolve(__dirname, "../../build/wg_dummy_output.wasm"); +const DUMMY_MODULE_PATH = path.resolve(__dirname, "../../build/dummy_output.wasm"); const dummy_module = fs.readFileSync(DUMMY_MODULE_PATH); const wm = new WebAssembly.Module(dummy_module); From e5fe9d278b2ce3bd7077fbbe537152592643606c Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Fri, 13 Jul 2018 10:04:45 +1200 Subject: [PATCH 1023/2137] 9P readdir should return whole number of dir-entries See issue #43 --- lib/9p.js | 9 ++++++++- lib/filesystem.js | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/9p.js b/lib/9p.js index dfd5836c..4cbb758e 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -539,14 +539,21 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { function() { this.bus.send("9p-read-end", [file.name, count]); + const inodeid = this.fids[fid].inodeid; + if (inode.size < offset+count) count = inode.size - offset; + else if(id == 40) + { + // for directories, return whole number of dir-entries. + count = this.fs.RoundToDirentry(inodeid, offset + count) - offset; + } if(offset > inode.size) { // offset can be greater than available - should return count of zero. // See http://ericvh.github.io/9p-rfc/rfc9p2000.html#anchor30 count = 0; } - var data = this.fs.inodedata[this.fids[fid].inodeid]; + var data = this.fs.inodedata[inodeid]; if(data) { this.replybuffer.set(data.subarray(offset, offset + count), 7 + 4); } diff --git a/lib/filesystem.js b/lib/filesystem.js index 24859397..256d4a03 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -333,6 +333,7 @@ function Inode(qidnumber) }; this.caps = undefined; this.nlinks = 1; + this.dirent_offsets = undefined; //this.qid_type = 0; //this.qid_version = 0; @@ -364,6 +365,7 @@ Inode.prototype.get_state = function() state[19] = this.qid.path; state[20] = this.caps; state[21] = this.nlinks; + state[22] = this.dirent_offsets; return state; }; @@ -391,6 +393,7 @@ Inode.prototype.set_state = function(state) this.qid.path = state[19]; this.caps = state[20]; this.nlinks = state[21]; + this.dirent_offsets = state[22]; }; FS.prototype.CreateInode = function() { @@ -822,6 +825,8 @@ FS.prototype.FillDirectory = function(dirid) { inode.size = size; var offset = 0x0; + inode.dirent_offsets = [offset]; + offset += marshall.Marshall( ["Q", "d", "b", "s"], [this.inodes[dirid].qid, @@ -829,6 +834,7 @@ FS.prototype.FillDirectory = function(dirid) { this.inodes[dirid].mode >> 12, "."], data, offset); + inode.dirent_offsets.push(offset); offset += marshall.Marshall( ["Q", "d", "b", "s"], @@ -837,6 +843,7 @@ FS.prototype.FillDirectory = function(dirid) { this.inodes[parentid].mode >> 12, ".."], data, offset); + inode.dirent_offsets.push(offset); id = this.inodes[dirid].firstid; while(id != -1) { @@ -847,11 +854,29 @@ FS.prototype.FillDirectory = function(dirid) { this.inodes[id].mode >> 12, this.inodes[id].name], data, offset); + this.inodes[dirid].dirent_offsets.push(offset); id = this.inodes[id].nextid; } inode.updatedir = false; } +FS.prototype.RoundToDirentry = function(dirid, offset_target) +{ + const offsets = this.GetInode(dirid).dirent_offsets; + + dbg_assert(offsets, "9P direntry offsets should be cached"); + dbg_assert(offsets[0] === 0, "9P first direntry offset should be zero"); + dbg_assert(offset_target >= 0, "9P RoundToDirentry target offset should be non-negative"); + + let i = 0; + while(offsets[i] <= offset_target) + { + i++; + } + + return offsets[i - 1]; +}; + // ----------------------------------------------------- From 46d48c407003e7b72deef35dc2a2506522f4e61c Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Fri, 13 Jul 2018 11:32:30 +1200 Subject: [PATCH 1024/2137] RoundToDirentry - Use existing directory data --- lib/filesystem.js | 31 ++++++++++++++----------------- lib/marshall.js | 10 ++++++++++ 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 256d4a03..f32d95c8 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -333,7 +333,6 @@ function Inode(qidnumber) }; this.caps = undefined; this.nlinks = 1; - this.dirent_offsets = undefined; //this.qid_type = 0; //this.qid_version = 0; @@ -365,7 +364,6 @@ Inode.prototype.get_state = function() state[19] = this.qid.path; state[20] = this.caps; state[21] = this.nlinks; - state[22] = this.dirent_offsets; return state; }; @@ -393,7 +391,6 @@ Inode.prototype.set_state = function(state) this.qid.path = state[19]; this.caps = state[20]; this.nlinks = state[21]; - this.dirent_offsets = state[22]; }; FS.prototype.CreateInode = function() { @@ -825,8 +822,6 @@ FS.prototype.FillDirectory = function(dirid) { inode.size = size; var offset = 0x0; - inode.dirent_offsets = [offset]; - offset += marshall.Marshall( ["Q", "d", "b", "s"], [this.inodes[dirid].qid, @@ -834,7 +829,6 @@ FS.prototype.FillDirectory = function(dirid) { this.inodes[dirid].mode >> 12, "."], data, offset); - inode.dirent_offsets.push(offset); offset += marshall.Marshall( ["Q", "d", "b", "s"], @@ -843,7 +837,6 @@ FS.prototype.FillDirectory = function(dirid) { this.inodes[parentid].mode >> 12, ".."], data, offset); - inode.dirent_offsets.push(offset); id = this.inodes[dirid].firstid; while(id != -1) { @@ -854,7 +847,6 @@ FS.prototype.FillDirectory = function(dirid) { this.inodes[id].mode >> 12, this.inodes[id].name], data, offset); - this.inodes[dirid].dirent_offsets.push(offset); id = this.inodes[id].nextid; } inode.updatedir = false; @@ -862,19 +854,24 @@ FS.prototype.FillDirectory = function(dirid) { FS.prototype.RoundToDirentry = function(dirid, offset_target) { - const offsets = this.GetInode(dirid).dirent_offsets; + const data = this.inodedata[dirid]; + dbg_assert(data, `FS directory data for dirid=${dirid} should be generated`); + dbg_assert(data.length, "FS directory should have at least an entry"); - dbg_assert(offsets, "9P direntry offsets should be cached"); - dbg_assert(offsets[0] === 0, "9P first direntry offset should be zero"); - dbg_assert(offset_target >= 0, "9P RoundToDirentry target offset should be non-negative"); - - let i = 0; - while(offsets[i] <= offset_target) + if(offset_target >= data.length) { - i++; + return data.length; } - return offsets[i - 1]; + let offset = 0; + while(true) + { + const next_offset = marshall.Unmarshall(["Q", "d"], data, { offset })[1]; + if(next_offset > offset_target) break; + offset = next_offset; + } + + return offset; }; diff --git a/lib/marshall.js b/lib/marshall.js index 1b3267d0..89a56681 100644 --- a/lib/marshall.js +++ b/lib/marshall.js @@ -111,6 +111,16 @@ marshall.Unmarshall = function(typelist, struct, state) { } output.push(str); break; + case "Q": + state.offset = offset; + const qid = marshall.Unmarshall(["b", "w", "d"], struct, state); + offset = state.offset; + output.push({ + type: qid[0], + version: qid[1], + path: qid[2], + }); + break; default: message.Debug("Error in Unmarshall: Unknown type=" + typelist[i]); break; From bda133ba4997565a8aab87e87de70eb3f9062e1d Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Fri, 13 Jul 2018 14:21:23 +1200 Subject: [PATCH 1025/2137] JSHint the lib directory --- Makefile | 2 +- lib/9p.js | 23 +++++++------ lib/filesystem.js | 82 +++++++++++++++++++++++------------------------ lib/jor1k.js | 8 ++--- lib/marshall.js | 8 +++-- lib/utf8.js | 6 ++-- 6 files changed, 67 insertions(+), 62 deletions(-) diff --git a/Makefile b/Makefile index 39f47003..fe89ba53 100644 --- a/Makefile +++ b/Makefile @@ -319,7 +319,7 @@ node_modules/.bin/jshint: npm install jshint: node_modules/.bin/jshint - ./node_modules/.bin/jshint --config=./.jshint.json src tests gen + ./node_modules/.bin/jshint --config=./.jshint.json src tests gen lib --exclude lib/closure-base.js rustfmt: $(RUST_FILES) cargo +nightly fmt --all -- --check diff --git a/lib/9p.js b/lib/9p.js index 4cbb758e..b8cacb1f 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -21,7 +21,7 @@ var ENOENT = 2; /* No such file or directory */ var EINVAL = 22; /* Invalid argument */ var ENOTSUPP = 524; /* Operation is not supported */ var ENOTEMPTY = 39; /* Directory not empty */ -var EPROTO = 71 /* Protocol error */ +var EPROTO = 71; /* Protocol error */ var P9_SETATTR_MODE = 0x00000001; var P9_SETATTR_UID = 0x00000002; @@ -185,17 +185,20 @@ Virtio9p.prototype.set_state = function(state) this.msize = state[5]; this.replybuffer = state[6]; this.replybuffersize = state[7]; - this.fids = state[8].map(function(f) { return { inodeid: f[0], type: f[1], uid: f[2] } }); + this.fids = state[8].map(function(f) + { + return { inodeid: f[0], type: f[1], uid: f[2] }; + }); this.fs = state[9]; }; Virtio9p.prototype.Createfid = function(inode, type, uid) { return {inodeid: inode, type: type, uid: uid}; -} +}; Virtio9p.prototype.Reset = function() { this.fids = []; -} +}; Virtio9p.prototype.BuildReply = function(id, tag, payloadsize) { @@ -208,20 +211,20 @@ Virtio9p.prototype.BuildReply = function(id, tag, payloadsize) { // this.replybuffer[7+i] = payload[i]; this.replybuffersize = payloadsize+7; return; -} +}; Virtio9p.prototype.SendError = function (tag, errormsg, errorcode) { //var size = marshall.Marshall(["s", "w"], [errormsg, errorcode], this.replybuffer, 7); var size = marshall.Marshall(["w"], [errorcode], this.replybuffer, 7); this.BuildReply(6, tag, size); -} +}; Virtio9p.prototype.SendReply = function (bufchain) { dbg_assert(this.replybuffersize >= 0, "9P: Negative replybuffersize"); bufchain.set_next_blob(this.replybuffer.subarray(0, this.replybuffersize)); this.virtqueue.push_reply(bufchain); this.virtqueue.flush_replies(); -} +}; Virtio9p.prototype.ReceiveRequest = function (bufchain) { // TODO: split into header + data blobs to avoid unnecessary copying. @@ -431,7 +434,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { req[6] = (inode.major<<8) | (inode.minor); // device id low req[7] = inode.size; // size low req[8] = this.BLOCKSIZE; - req[9] = Math.floor(inode.size/512+1);; // blk size low + req[9] = Math.floor(inode.size/512+1); // blk size low req[10] = inode.atime; // atime req[11] = 0x0; req[12] = inode.mtime; // mtime @@ -464,8 +467,8 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { "w", "w", // uid, gid "d", // size "d", "d", // atime - "d", "d"] // mtime - , buffer, state); + "d", "d", // mtime + ], buffer, state); var fid = req[0]; var inode = this.fs.GetInode(this.fids[fid].inodeid); message.Debug("[setattr]: fid=" + fid + " request mask=" + req[1] + " name=" +inode.name); diff --git a/lib/filesystem.js b/lib/filesystem.js index f32d95c8..4cd4b077 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -34,13 +34,13 @@ var STATUS_UNLINKED = 0x4; /** @const */ var JSONFS_VERSION = 2; -/** @const */ var JSONFS_IDX_NAME = 0 -/** @const */ var JSONFS_IDX_SIZE = 1 -/** @const */ var JSONFS_IDX_MTIME = 2 -/** @const */ var JSONFS_IDX_MODE = 3 -/** @const */ var JSONFS_IDX_UID = 4 -/** @const */ var JSONFS_IDX_GID = 5 -/** @const */ var JSONFS_IDX_TARGET = 6 +/** @const */ var JSONFS_IDX_NAME = 0; +/** @const */ var JSONFS_IDX_SIZE = 1; +/** @const */ var JSONFS_IDX_MTIME = 2; +/** @const */ var JSONFS_IDX_MODE = 3; +/** @const */ var JSONFS_IDX_UID = 4; +/** @const */ var JSONFS_IDX_GID = 5; +/** @const */ var JSONFS_IDX_TARGET = 6; /** @constructor */ @@ -119,13 +119,13 @@ FS.prototype.AddEvent = function(id, OnEvent) { return; } this.events.push({id: id, OnEvent: OnEvent}); -} +}; FS.prototype.HandleEvent = function(id) { if (this.filesinloadingqueue == 0) { this.OnLoaded(); - this.OnLoaded = function() {} + this.OnLoaded = function() {}; } //message.Debug("number of events: " + this.events.length); var newevents = []; @@ -137,7 +137,7 @@ FS.prototype.HandleEvent = function(id) { } } this.events = newevents; -} +}; FS.prototype.OnJSONLoaded = function(fs) { @@ -225,7 +225,7 @@ FS.prototype.LoadRecursive = function(data, parentid) { dbg_log("Unexpected ifmt: " + h(ifmt) + " (" + inode.name + ")"); } -} +}; FS.prototype.LoadDir = function(inode, children) { @@ -237,7 +237,7 @@ FS.prototype.LoadDir = function(inode, children) for(var i = 0; i < children.length; i++) { this.LoadRecursive(children[i], p); } -} +}; // Loads the data from a url for a specific inode FS.prototype.LoadFile = function(idx) { @@ -281,7 +281,7 @@ FS.prototype.LoadFile = function(idx) { // If baseurl is not set, we started with an empty filesystem. No files // can be loaded } -} +}; // ----------------------------------------------------- @@ -304,7 +304,7 @@ FS.prototype.PushInode = function(inode) { message.Debug("Error in Filesystem: Pushed inode with name = "+ inode.name + " has no parent"); message.Abort(); -} +}; /** @constructor */ function Inode(qidnumber) @@ -416,7 +416,7 @@ FS.prototype.CreateDirectory = function(name, parentid) { this.PushInode(x); this.NotifyListeners(this.inodes.length-1, 'newdir'); return this.inodes.length-1; -} +}; FS.prototype.CreateFile = function(filename, parentid) { var x = this.CreateInode(); @@ -430,7 +430,7 @@ FS.prototype.CreateFile = function(filename, parentid) { this.PushInode(x); this.NotifyListeners(this.inodes.length-1, 'newfile'); return this.inodes.length-1; -} +}; FS.prototype.CreateNode = function(filename, parentid, major, minor) { @@ -446,7 +446,7 @@ FS.prototype.CreateNode = function(filename, parentid, major, minor) { x.mode = (this.inodes[parentid].mode & 0x1B6); this.PushInode(x); return this.inodes.length-1; -} +}; FS.prototype.CreateSymlink = function(filename, parentid, symlink) { var x = this.CreateInode(); @@ -460,7 +460,7 @@ FS.prototype.CreateSymlink = function(filename, parentid, symlink) { x.mode = S_IFLNK; this.PushInode(x); return this.inodes.length-1; -} +}; FS.prototype.CreateTextFile = function(filename, parentid, str) { var id = this.CreateFile(filename, parentid); @@ -471,7 +471,7 @@ FS.prototype.CreateTextFile = function(filename, parentid, str) { data[j] = str.charCodeAt(j); } return id; -} +}; /** * @param {Uint8Array} buffer @@ -483,7 +483,7 @@ FS.prototype.CreateBinaryFile = function(filename, parentid, buffer) { data.set(buffer); x.size = buffer.length; return id; -} +}; FS.prototype.OpenInode = function(id, mode) { @@ -506,7 +506,7 @@ FS.prototype.OpenInode = function(id, mode) { return false; } return true; -} +}; FS.prototype.CloseInode = function(id) { //message.Debug("close: " + this.GetFullPath(id)); @@ -517,7 +517,7 @@ FS.prototype.CloseInode = function(id) { delete this.inodedata[id]; inode.size = 0; } -} +}; FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { // message.Debug("Rename " + oldname + " to " + newname); @@ -564,7 +564,7 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { this.NotifyListeners(idx, "rename", {oldpath: oldpath}); return true; -} +}; FS.prototype.Write = function(id, offset, count, buffer) { this.NotifyListeners(id, 'write'); @@ -580,7 +580,7 @@ FS.prototype.Write = function(id, offset, count, buffer) { inode.size = offset + count; } data.set(buffer.subarray(0, count), offset); -} +}; FS.prototype.Search = function(parentid, name) { var id = this.inodes[parentid].firstid; @@ -592,7 +592,7 @@ FS.prototype.Search = function(parentid, name) { id = this.inodes[id].nextid; } return -1; -} +}; FS.prototype.GetTotalSize = function() { return this.used_size; @@ -602,7 +602,7 @@ FS.prototype.GetTotalSize = function() { // size += d ? d.length : 0; //} //return size; -} +}; FS.prototype.GetSpace = function() { return this.total_size; @@ -616,7 +616,7 @@ FS.prototype.GetFullPath = function(idx) { idx = this.inodes[idx].parentid; } return path.substring(1); -} +}; // no double linked list. So, we need this FS.prototype.FindPreviousID = function(idx) { @@ -627,7 +627,7 @@ FS.prototype.FindPreviousID = function(idx) { id = this.inodes[id].nextid; } return id; -} +}; FS.prototype.Unlink = function(idx) { this.NotifyListeners(idx, 'delete'); @@ -660,7 +660,7 @@ FS.prototype.Unlink = function(idx) { inode.parentid = -1; inode.nlinks--; return true; -} +}; FS.prototype.GetInode = function(idx) { @@ -674,7 +674,7 @@ FS.prototype.GetInode = function(idx) return 0; } return this.inodes[idx]; -} +}; FS.prototype.ChangeSize = function(idx, newsize) { @@ -687,7 +687,7 @@ FS.prototype.ChangeSize = function(idx, newsize) if(!temp) return; var size = Math.min(temp.length, inode.size); data.set(temp.subarray(0, size), 0); -} +}; FS.prototype.SearchPath = function(path) { //path = path.replace(/\/\//g, "/"); @@ -709,7 +709,7 @@ FS.prototype.SearchPath = function(path) { parentid = id; } return {id: id, parentid: parentid, name: walk[i]}; -} +}; // ----------------------------------------------------- FS.prototype.GetRecursiveList = function(dirid, list) { @@ -721,10 +721,10 @@ FS.prototype.GetRecursiveList = function(dirid, list) { } id = this.inodes[id].nextid; } -} +}; FS.prototype.RecursiveDelete = function(path) { - var toDelete = [] + var toDelete = []; var ids = this.SearchPath(path); if (ids.parentid == -1 || ids.id == -1) return; @@ -733,7 +733,7 @@ FS.prototype.RecursiveDelete = function(path) { for(var i=toDelete.length-1; i>=0; i--) this.Unlink(toDelete[i]); -} +}; FS.prototype.DeleteNode = function(path) { var ids = this.SearchPath(path); @@ -744,14 +744,14 @@ FS.prototype.DeleteNode = function(path) { return; } if ((this.inodes[ids.id].mode&S_IFMT) == S_IFDIR){ - var toDelete = [] + var toDelete = []; this.GetRecursiveList(ids.id, toDelete); for(var i=toDelete.length-1; i>=0; i--) this.Unlink(toDelete[i]); this.Unlink(ids.id); return; } -} +}; /** @param {*=} info */ FS.prototype.NotifyListeners = function(id, action, info) { @@ -769,7 +769,7 @@ FS.prototype.NotifyListeners = function(id, action, info) { // message.Send("WatchDirectoryEvent", {path: path, event: action, info: info}); // } //} -} +}; FS.prototype.Check = function() { @@ -798,7 +798,7 @@ FS.prototype.Check = function() { } } -} +}; FS.prototype.FillDirectory = function(dirid) { @@ -850,7 +850,7 @@ FS.prototype.FillDirectory = function(dirid) { id = this.inodes[id].nextid; } inode.updatedir = false; -} +}; FS.prototype.RoundToDirentry = function(dirid, offset_target) { @@ -908,5 +908,5 @@ FS.prototype.PrepareCAPs = function(id) { inode.caps[11] = 0xFF; return inode.caps.length; -} +}; diff --git a/lib/jor1k.js b/lib/jor1k.js index 00964f2d..9ae656c9 100644 --- a/lib/jor1k.js +++ b/lib/jor1k.js @@ -40,7 +40,7 @@ var message = {}; message.Debug = function(log) { dbg_log([].slice.apply(arguments).join(" "), LOG_9P); -} +}; message.Abort = function() { @@ -48,7 +48,7 @@ message.Abort = function() { throw "abort"; } -} +}; // XXX: Should go through emulator interface @@ -85,7 +85,7 @@ if(typeof XMLHttpRequest !== "undefined") }; */ req.send(null); - } + }; } else { @@ -103,5 +103,5 @@ else OnSuccess(data.buffer); } }); - } + }; } diff --git a/lib/marshall.js b/lib/marshall.js index 89a56681..fc76dff7 100644 --- a/lib/marshall.js +++ b/lib/marshall.js @@ -3,6 +3,8 @@ // ------------------------------------------------- // helper functions for virtio and 9p. +"use strict"; + var marshall = {}; @@ -58,7 +60,7 @@ marshall.Marshall = function(typelist, input, struct, offset) { struct[lengthoffset+1] = (length >> 8) & 0xFF; break; case "Q": - marshall.Marshall(["b", "w", "d"], [item.type, item.version, item.path], struct, offset) + marshall.Marshall(["b", "w", "d"], [item.type, item.version, item.path], struct, offset); offset += 13; size += 13; break; @@ -105,7 +107,7 @@ marshall.Unmarshall = function(typelist, struct, state) { var str = ''; var utf8converter = new UTF8StreamToUnicode(); for (var j=0; j < len; j++) { - var c = utf8converter.Put(struct[offset++]) + var c = utf8converter.Put(struct[offset++]); if (c == -1) continue; str += String.fromCharCode(c); } @@ -164,7 +166,7 @@ marshall.Unmarshall2 = function(typelist, GetByte) { var str = ''; var utf8converter = new UTF8StreamToUnicode(); for (var j=0; j < len; j++) { - var c = utf8converter.Put(GetByte()) + var c = utf8converter.Put(GetByte()); if (c == -1) continue; str += String.fromCharCode(c); } diff --git a/lib/utf8.js b/lib/utf8.js index c7e8a3e6..48758348 100644 --- a/lib/utf8.js +++ b/lib/utf8.js @@ -4,7 +4,7 @@ "use strict"; -var UTF8 = {} +var UTF8 = {}; /** @constructor */ function UTF8StreamToUnicode() { @@ -43,7 +43,7 @@ function UTF8StreamToUnicode() { //break; } return -1; - } + }; } function UnicodeToUTF8Stream(key) @@ -60,4 +60,4 @@ UTF8.UTF8Length = function(s) length += c<128?1:2; } return length; -} +}; From dac9b4591b24ee98057764fddfb96d597c4a6144 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 12 Jul 2018 14:21:25 -0600 Subject: [PATCH 1026/2137] Simplify generate_interpreter.js --- gen/generate_interpreter.js | 278 +++++++++++++++--------------------- 1 file changed, 116 insertions(+), 162 deletions(-) diff --git a/gen/generate_interpreter.js b/gen/generate_interpreter.js index f7bfbef8..c7fd2bfb 100755 --- a/gen/generate_interpreter.js +++ b/gen/generate_interpreter.js @@ -76,31 +76,17 @@ function gen_call(name, args) return `${name}(${args.join(", ")});`; } -function gen_modrm_mem_reg_split(name, modrm_resolve_prefix, mem_args, reg_args) -{ - return { - type: "if-else", - if_blocks: [{ - condition: "modrm_byte < 0xC0", - body: (modrm_resolve_prefix ? [modrm_resolve_prefix] : []).concat(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) +function make_instruction_name(encoding, size) { 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 prefix = (encoding.opcode & 0xFF0000) === 0 ? "" : hex(encoding.opcode >> 16 & 0xFF, 2); const fixed_g_suffix = encoding.fixed_g === undefined ? "" : `_${encoding.fixed_g}`; return `instr${suffix}_${prefix}${prefix_0f}${opcode_hex}${fixed_g_suffix}`; @@ -110,26 +96,78 @@ function gen_instruction_body(encodings, size) { const encoding = encodings[0]; - let has_66 = false; - let has_F2 = false; - let has_F3 = false; + let has_66 = []; + let has_F2 = []; + let has_F3 = []; + let no_prefix = []; 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((e.opcode >>> 16) === 0x66) has_66.push(e); + else if((e.opcode >>> 16) === 0xF2) has_F2.push(e); + else if((e.opcode >>> 16) === 0xF3) has_F3.push(e); + else no_prefix.push(e); } - if(has_66 || has_F2 || has_F3) + if(has_66.length || has_F2.length || has_F3.length) { console.assert((encoding.opcode & 0xFF00) === 0x0F00); } - const instruction_postfix = encoding.block_boundary ? ["after_block_boundary();"] : []; + const code = []; + + if(encoding.e) + { + code.push("int32_t modrm_byte = read_imm8();"); + } + + if(has_66.length || has_F2.length || has_F3.length) + { + const if_blocks = []; + + if(has_66.length) { + const body = gen_instruction_body_after_prefix(has_66, size); + if_blocks.push({ condition: "prefixes_ & PREFIX_66", body, }); + } + if(has_F2.length) { + const body = gen_instruction_body_after_prefix(has_F2, size); + if_blocks.push({ condition: "prefixes_ & PREFIX_F2", body, }); + } + if(has_F3.length) { + const body = gen_instruction_body_after_prefix(has_F3, size); + if_blocks.push({ condition: "prefixes_ & PREFIX_F3", body, }); + } + + const else_block = { + body: gen_instruction_body_after_prefix(no_prefix, size), + }; + + return [].concat( + "int32_t prefixes_ = *prefixes;", + code, + { + type: "if-else", + if_blocks, + else_block, + } + ); + } + else { + return [].concat( + code, + gen_instruction_body_after_prefix(encodings, size) + ); + } +} + +function gen_instruction_body_after_prefix(encodings, size) +{ + const encoding = encodings[0]; if(encoding.fixed_g !== undefined) { + console.assert(encoding.e); + // instruction with modrm byte where the middle 3 bits encode the instruction // group by opcode without prefix plus middle bits of modrm byte @@ -141,77 +179,17 @@ function gen_instruction_body(encodings, size) 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 instruction_postfix = case_.block_boundary ? ["after_block_boundary();"] : []; + const body = gen_instruction_body_after_fixed_g(case_, size); - let modrm_resolve_prefix = undefined; - - if(case_.requires_prefix_call) - { - modrm_resolve_prefix = gen_call(instruction_name + "_mem_pre"); - } - - 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, modrm_resolve_prefix, 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, modrm_resolve_prefix, 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, modrm_resolve_prefix, mem_args, reg_args)]; - if_blocks.push({ condition: "prefixes_ & PREFIX_F3", body, }); - } - - const else_block = { - body: [gen_modrm_mem_reg_split(instruction_name, modrm_resolve_prefix, mem_args, reg_args)], - }; - - return { - conditions: [fixed_g], - body: [ - "int32_t prefixes_ = *prefixes;", - { - type: "if-else", - if_blocks, - else_block, - }, - ].concat(instruction_postfix), - }; - } - else - { - const body = [gen_modrm_mem_reg_split(instruction_name, modrm_resolve_prefix, mem_args, reg_args)].concat(instruction_postfix); - - return { - conditions: [fixed_g], - body, - }; - } + return { + conditions: [fixed_g], + body, + }; }), default_case: { @@ -220,66 +198,24 @@ function gen_instruction_body(encodings, size) "trigger_ud();", ], } - } - ].concat(instruction_postfix); + }, + ]; } - else if(has_66 || has_F2 || has_F3) - { - // instruction without 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 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 = []; - const modrm_resolve_prefix = undefined; - - if(has_66) { - const name = make_instruction_name(encoding, size, 0x66); - const body = [gen_modrm_mem_reg_split(name, modrm_resolve_prefix, 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, modrm_resolve_prefix, 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, modrm_resolve_prefix, 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), modrm_resolve_prefix, mem_args, reg_args)], - }; - - return [ - "int32_t modrm_byte = read_imm8();", - "int32_t prefixes_ = *prefixes;", - { - type: "if-else", - if_blocks, - else_block, - } - ].concat(instruction_postfix); - } - else if(encoding.fixed_g === undefined && encoding.e) - { - // instruction with modrm byte where the middle 3 bits encode a register - + else { console.assert(encodings.length === 1); + return gen_instruction_body_after_fixed_g(encodings[0], size); + } +} + +function gen_instruction_body_after_fixed_g(encoding, size) +{ + const instruction_postfix = encoding.block_boundary ? ["after_block_boundary();"] : []; + const imm_read = gen_read_imm_call(encoding, size); + const instruction_name = make_instruction_name(encoding, size); + + if(encoding.e) + { + // instruction with modrm byte const instruction_name = make_instruction_name(encoding, size); @@ -300,15 +236,21 @@ function gen_instruction_body(encodings, size) // 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();", + return [].concat( gen_call(instruction_name, ["modrm_byte & 7", "modrm_byte >> 3 & 7"]), - ].concat(instruction_postfix); + instruction_postfix + ); } else { - const mem_args = ["modrm_resolve(modrm_byte)", "modrm_byte >> 3 & 7"]; - const reg_args = ["modrm_byte & 7", "modrm_byte >> 3 & 7"]; + const mem_args = ["modrm_resolve(modrm_byte)"]; + const reg_args = ["modrm_byte & 7"]; + + if(encoding.fixed_g === undefined) + { + mem_args.push("modrm_byte >> 3 & 7"); + reg_args.push("modrm_byte >> 3 & 7"); + } if(imm_read) { @@ -316,19 +258,28 @@ function gen_instruction_body(encodings, size) reg_args.push(imm_read); } - return [ - "int32_t modrm_byte = read_imm8();", - gen_modrm_mem_reg_split(instruction_name, modrm_resolve_prefix, mem_args, reg_args), - ].concat(instruction_postfix); + return [].concat( + { + type: "if-else", + if_blocks: [ + { + condition: "modrm_byte < 0xC0", + body: [].concat( + modrm_resolve_prefix ? [modrm_resolve_prefix] : [], + gen_call(`${instruction_name}_mem`, mem_args) + ), + } + ], + else_block: { + body: [gen_call(`${instruction_name}_reg`, reg_args)], + }, + }, + instruction_postfix + ); } } 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) @@ -347,7 +298,10 @@ function gen_instruction_body(encodings, size) args.push("read_imm8()"); } - return [gen_call(instruction_name, args)].concat(instruction_postfix); + return [].concat( + gen_call(instruction_name, args), + instruction_postfix + ); } } From c6764859b94167d248ae81661c375fdca98bb9e4 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 12 Jul 2018 14:29:54 -0600 Subject: [PATCH 1027/2137] Add verbose to cargo builds --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index fe89ba53..237ade98 100644 --- a/Makefile +++ b/Makefile @@ -101,8 +101,9 @@ CC_FLAGS=\ -s SIDE_MODULE=1 CARGO_FLAGS=\ - --target wasm32-unknown-unknown \ - -- -Clink-args="--import-memory" + --target wasm32-unknown-unknown \ + -- -Clink-args="--import-memory" \ + --verbose CORE_FILES=const.js config.js io.js main.js lib.js coverage.js ide.js pci.js floppy.js \ memory.js dma.js pit.js vga.js ps2.js pic.js rtc.js uart.js hpet.js acpi.js apic.js ioapic.js \ From 1253b729062d95b1bfd32b14c40de4e743c8af49 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 12 Jul 2018 15:19:49 -0600 Subject: [PATCH 1028/2137] Generate prefix handling for string instructions --- gen/generate_analyzer.js | 35 +++-- gen/generate_interpreter.js | 39 ++--- gen/generate_jit.js | 60 +++----- gen/x86_table.js | 32 +++++ src/native/instructions.c | 88 +++++++++--- src/native/string.c | 276 ++---------------------------------- src/native/string.h | 40 ++---- tests/nasm/create_tests.js | 3 +- 8 files changed, 187 insertions(+), 386 deletions(-) diff --git a/gen/generate_analyzer.js b/gen/generate_analyzer.js index a8a7961b..dee08c82 100755 --- a/gen/generate_analyzer.js +++ b/gen/generate_analyzer.js @@ -77,18 +77,20 @@ function gen_call(name, args) /* * Current naming scheme: - * instr(16|32|)_((66|F2|F3)?0F)?[0-9a-f]{2}(_[0-7])?(_mem|_reg|) + * instr(16|32|)_(66|F2|F3)?0F?[0-9a-f]{2}(_[0-7])?(_mem|_reg|) */ - function make_instruction_name(encoding, size) { const suffix = encoding.os ? String(size) : ""; const opcode_hex = hex(encoding.opcode & 0xFF, 2); - const prefix_0f = (encoding.opcode & 0xFF00) === 0x0F00 ? "0F" : ""; - const prefix = (encoding.opcode & 0xFF0000) === 0 ? "" : hex(encoding.opcode >> 16 & 0xFF, 2); + const first_prefix = (encoding.opcode & 0xFF00) === 0 ? "" : hex(encoding.opcode >> 8 & 0xFF, 2); + const second_prefix = (encoding.opcode & 0xFF0000) === 0 ? "" : hex(encoding.opcode >> 16 & 0xFF, 2); const fixed_g_suffix = encoding.fixed_g === undefined ? "" : `_${encoding.fixed_g}`; - return `instr${suffix}_${prefix}${prefix_0f}${opcode_hex}${fixed_g_suffix}`; + console.assert(first_prefix === "" || first_prefix === "0F" || first_prefix === "F2" || first_prefix === "F3"); + console.assert(second_prefix === "" || second_prefix === "66" || second_prefix === "F2" || second_prefix === "F3"); + + return `instr${suffix}_${second_prefix}${first_prefix}${opcode_hex}${fixed_g_suffix}`; } function gen_instruction_body(encodings, size) @@ -103,12 +105,17 @@ function gen_instruction_body(encodings, size) for(let e of encodings) { if((e.opcode >>> 16) === 0x66) has_66.push(e); - else if((e.opcode >>> 16) === 0xF2) has_F2.push(e); - else if((e.opcode >>> 16) === 0xF3) has_F3.push(e); + else if((e.opcode >>> 8 & 0xFF) === 0xF2 || (e.opcode >>> 16) === 0xF2) has_F2.push(e); + else if((e.opcode >>> 8 & 0xFF) === 0xF3 || (e.opcode >>> 16) === 0xF3) has_F3.push(e); else no_prefix.push(e); } - if(has_66.length || has_F2.length || has_F3.length) + if(has_F2.length || has_F3.length) + { + console.assert((encoding.opcode & 0xFF0000) === 0 || (encoding.opcode & 0xFF00) === 0x0F00); + } + + if(has_66.length) { console.assert((encoding.opcode & 0xFF00) === 0x0F00); } @@ -318,17 +325,15 @@ function gen_table() { let opcode = o.opcode; - if(opcode >= 0x100) + if((opcode & 0xFF00) === 0x0F00) { - if((opcode & 0xFF00) === 0x0F00) - { - opcode &= 0xFF; - by_opcode0f[opcode] = by_opcode0f[opcode] || []; - by_opcode0f[opcode].push(o); - } + opcode &= 0xFF; + by_opcode0f[opcode] = by_opcode0f[opcode] || []; + by_opcode0f[opcode].push(o); } else { + opcode &= 0xFF; by_opcode[opcode] = by_opcode[opcode] || []; by_opcode[opcode].push(o); } diff --git a/gen/generate_interpreter.js b/gen/generate_interpreter.js index c7fd2bfb..224dc712 100755 --- a/gen/generate_interpreter.js +++ b/gen/generate_interpreter.js @@ -3,7 +3,7 @@ const fs = require("fs"); const path = require("path"); -const encodings = require("./x86_table"); +const x86_table = require("./x86_table"); const c_ast = require("./c_ast"); const { hex, mkdirpSync, get_switch_value, get_switch_exist, finalize_table } = require("./util"); @@ -78,18 +78,20 @@ function gen_call(name, args) /* * Current naming scheme: - * instr(16|32|)_((66|F2|F3)?0F)?[0-9a-f]{2}(_[0-7])?(_mem|_reg|) + * instr(16|32|)_(66|F2|F3)?0F?[0-9a-f]{2}(_[0-7])?(_mem|_reg|) */ - function make_instruction_name(encoding, size) { const suffix = encoding.os ? String(size) : ""; const opcode_hex = hex(encoding.opcode & 0xFF, 2); - const prefix_0f = (encoding.opcode & 0xFF00) === 0x0F00 ? "0F" : ""; - const prefix = (encoding.opcode & 0xFF0000) === 0 ? "" : hex(encoding.opcode >> 16 & 0xFF, 2); + const first_prefix = (encoding.opcode & 0xFF00) === 0 ? "" : hex(encoding.opcode >> 8 & 0xFF, 2); + const second_prefix = (encoding.opcode & 0xFF0000) === 0 ? "" : hex(encoding.opcode >> 16 & 0xFF, 2); const fixed_g_suffix = encoding.fixed_g === undefined ? "" : `_${encoding.fixed_g}`; - return `instr${suffix}_${prefix}${prefix_0f}${opcode_hex}${fixed_g_suffix}`; + console.assert(first_prefix === "" || first_prefix === "0F" || first_prefix === "F2" || first_prefix === "F3"); + console.assert(second_prefix === "" || second_prefix === "66" || second_prefix === "F2" || second_prefix === "F3"); + + return `instr${suffix}_${second_prefix}${first_prefix}${opcode_hex}${fixed_g_suffix}`; } function gen_instruction_body(encodings, size) @@ -104,12 +106,17 @@ function gen_instruction_body(encodings, size) for(let e of encodings) { if((e.opcode >>> 16) === 0x66) has_66.push(e); - else if((e.opcode >>> 16) === 0xF2) has_F2.push(e); - else if((e.opcode >>> 16) === 0xF3) has_F3.push(e); + else if((e.opcode >>> 8 & 0xFF) === 0xF2 || (e.opcode >>> 16) === 0xF2) has_F2.push(e); + else if((e.opcode >>> 8 & 0xFF) === 0xF3 || (e.opcode >>> 16) === 0xF3) has_F3.push(e); else no_prefix.push(e); } - if(has_66.length || has_F2.length || has_F3.length) + if(has_F2.length || has_F3.length) + { + console.assert((encoding.opcode & 0xFF0000) === 0 || (encoding.opcode & 0xFF00) === 0x0F00); + } + + if(has_66.length) { console.assert((encoding.opcode & 0xFF00) === 0x0F00); } @@ -310,21 +317,19 @@ function gen_table() let by_opcode = Object.create(null); let by_opcode0f = Object.create(null); - for(let o of encodings) + for(let o of x86_table) { let opcode = o.opcode; - if(opcode >= 0x100) + if((opcode & 0xFF00) === 0x0F00) { - if((opcode & 0xFF00) === 0x0F00) - { - opcode &= 0xFF; - by_opcode0f[opcode] = by_opcode0f[opcode] || []; - by_opcode0f[opcode].push(o); - } + opcode &= 0xFF; + by_opcode0f[opcode] = by_opcode0f[opcode] || []; + by_opcode0f[opcode].push(o); } else { + opcode &= 0xFF; by_opcode[opcode] = by_opcode[opcode] || []; by_opcode[opcode].push(o); } diff --git a/gen/generate_jit.js b/gen/generate_jit.js index f1a02aa7..a8674a2f 100755 --- a/gen/generate_jit.js +++ b/gen/generate_jit.js @@ -75,45 +75,22 @@ function gen_call(name, args) return `${name}(${args.join(", ")});`; } -function gen_codegen_call(name, args) -{ - const IMM_VAR_NAME = "imm"; - let imm_read; - - args = (args || []).map(arg => { - if(arg.includes("read_imm")) - { - imm_read = arg; - return IMM_VAR_NAME; - } - else - { - return arg; - } - }); - const args_count = args.length; - - args = [].concat(["ctx", `"${name}"`], args); - return [].concat( - imm_read ? `let ${IMM_VAR_NAME} = ${imm_read};` : [], - gen_call(`::codegen::gen_fn${args_count}_const`, args) - ); -} - /* * Current naming scheme: - * instr(16|32|)_((66|F2|F3)?0F)?[0-9a-f]{2}(_[0-7])?(_mem|_reg|) + * instr(16|32|)_(66|F2|F3)?0F?[0-9a-f]{2}(_[0-7])?(_mem|_reg|) */ - function make_instruction_name(encoding, size) { const suffix = encoding.os ? String(size) : ""; const opcode_hex = hex(encoding.opcode & 0xFF, 2); - const prefix_0f = (encoding.opcode & 0xFF00) === 0x0F00 ? "0F" : ""; - const prefix = (encoding.opcode & 0xFF0000) === 0 ? "" : hex(encoding.opcode >> 16 & 0xFF, 2); + const first_prefix = (encoding.opcode & 0xFF00) === 0 ? "" : hex(encoding.opcode >> 8 & 0xFF, 2); + const second_prefix = (encoding.opcode & 0xFF0000) === 0 ? "" : hex(encoding.opcode >> 16 & 0xFF, 2); const fixed_g_suffix = encoding.fixed_g === undefined ? "" : `_${encoding.fixed_g}`; - return `instr${suffix}_${prefix}${prefix_0f}${opcode_hex}${fixed_g_suffix}`; + console.assert(first_prefix === "" || first_prefix === "0F" || first_prefix === "F2" || first_prefix === "F3"); + console.assert(second_prefix === "" || second_prefix === "66" || second_prefix === "F2" || second_prefix === "F3"); + + return `instr${suffix}_${second_prefix}${first_prefix}${opcode_hex}${fixed_g_suffix}`; } function gen_instruction_body(encodings, size) @@ -128,12 +105,17 @@ function gen_instruction_body(encodings, size) for(let e of encodings) { if((e.opcode >>> 16) === 0x66) has_66.push(e); - else if((e.opcode >>> 16) === 0xF2) has_F2.push(e); - else if((e.opcode >>> 16) === 0xF3) has_F3.push(e); + else if((e.opcode >>> 8 & 0xFF) === 0xF2 || (e.opcode >>> 16) === 0xF2) has_F2.push(e); + else if((e.opcode >>> 8 & 0xFF) === 0xF3 || (e.opcode >>> 16) === 0xF3) has_F3.push(e); else no_prefix.push(e); } - if(has_66.length || has_F2.length || has_F3.length) + if(has_F2.length || has_F3.length) + { + console.assert((encoding.opcode & 0xFF0000) === 0 || (encoding.opcode & 0xFF00) === 0x0F00); + } + + if(has_66.length) { console.assert((encoding.opcode & 0xFF00) === 0x0F00); } @@ -424,17 +406,15 @@ function gen_table() { let opcode = o.opcode; - if(opcode >= 0x100) + if((opcode & 0xFF00) === 0x0F00) { - if((opcode & 0xFF00) === 0x0F00) - { - opcode &= 0xFF; - by_opcode0f[opcode] = by_opcode0f[opcode] || []; - by_opcode0f[opcode].push(o); - } + opcode &= 0xFF; + by_opcode0f[opcode] = by_opcode0f[opcode] || []; + by_opcode0f[opcode].push(o); } else { + opcode &= 0xFF; by_opcode[opcode] = by_opcode[opcode] || []; by_opcode[opcode].push(o); } diff --git a/gen/x86_table.js b/gen/x86_table.js index f49a4dc8..74f98cd0 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -84,9 +84,18 @@ const encodings = [ { opcode: 0x6B, nonfaulting: 1, os: 1, e: 1, imm8s: 1, mask_flags: af, }, // zf? { opcode: 0x6C, block_boundary: 1, is_string: 1, skip: 1, }, // ins + { opcode: 0xF26C, block_boundary: 1, is_string: 1, skip: 1, }, + { opcode: 0xF36C, block_boundary: 1, is_string: 1, skip: 1, }, { opcode: 0x6D, block_boundary: 1, is_string: 1, os: 1, skip: 1, }, + { opcode: 0xF26D, block_boundary: 1, is_string: 1, os: 1, skip: 1, }, + { opcode: 0xF36D, block_boundary: 1, is_string: 1, os: 1, skip: 1, }, + { opcode: 0x6E, block_boundary: 1, is_string: 1, skip: 1, }, // outs + { opcode: 0xF26E, block_boundary: 1, is_string: 1, skip: 1, }, + { opcode: 0xF36E, block_boundary: 1, is_string: 1, skip: 1, }, { opcode: 0x6F, block_boundary: 1, is_string: 1, os: 1, skip: 1, }, + { opcode: 0xF26F, block_boundary: 1, is_string: 1, os: 1, skip: 1, }, + { opcode: 0xF36F, block_boundary: 1, is_string: 1, os: 1, skip: 1, }, { opcode: 0x84, nonfaulting: 1, e: 1, }, { opcode: 0x85, nonfaulting: 1, os: 1, e: 1, }, @@ -128,19 +137,42 @@ const encodings = [ // string instructions aren't jumps, but they modify eip due to how they're implemented { opcode: 0xA4, block_boundary: 1, is_string: 1, }, + { opcode: 0xF2A4, block_boundary: 1, is_string: 1, }, + { opcode: 0xF3A4, block_boundary: 1, is_string: 1, }, { opcode: 0xA5, block_boundary: 1, is_string: 1, os: 1, }, + { opcode: 0xF2A5, block_boundary: 1, is_string: 1, os: 1, }, + { opcode: 0xF3A5, block_boundary: 1, is_string: 1, os: 1, }, + { opcode: 0xA6, block_boundary: 1, is_string: 1, }, + { opcode: 0xF2A6, block_boundary: 1, is_string: 1, }, + { opcode: 0xF3A6, block_boundary: 1, is_string: 1, }, { opcode: 0xA7, block_boundary: 1, is_string: 1, os: 1, }, + { opcode: 0xF2A7, block_boundary: 1, is_string: 1, os: 1, }, + { opcode: 0xF3A7, block_boundary: 1, is_string: 1, os: 1, }, { opcode: 0xA8, nonfaulting: 1, imm8: 1, }, { opcode: 0xA9, nonfaulting: 1, os: 1, imm1632: 1, }, { opcode: 0xAA, block_boundary: 1, is_string: 1, }, + { opcode: 0xF2AA, block_boundary: 1, is_string: 1, }, + { opcode: 0xF3AA, block_boundary: 1, is_string: 1, }, { opcode: 0xAB, block_boundary: 1, is_string: 1, os: 1, }, + { opcode: 0xF2AB, block_boundary: 1, is_string: 1, os: 1, }, + { opcode: 0xF3AB, block_boundary: 1, is_string: 1, os: 1, }, + { opcode: 0xAC, block_boundary: 1, is_string: 1, }, + { opcode: 0xF2AC, block_boundary: 1, is_string: 1, }, + { opcode: 0xF3AC, block_boundary: 1, is_string: 1, }, { opcode: 0xAD, block_boundary: 1, is_string: 1, os: 1, }, + { opcode: 0xF2AD, block_boundary: 1, is_string: 1, os: 1, }, + { opcode: 0xF3AD, block_boundary: 1, is_string: 1, os: 1, }, + { opcode: 0xAE, block_boundary: 1, is_string: 1, }, + { opcode: 0xF2AE, block_boundary: 1, is_string: 1, }, + { opcode: 0xF3AE, block_boundary: 1, is_string: 1, }, { opcode: 0xAF, block_boundary: 1, is_string: 1, os: 1, }, + { opcode: 0xF2AF, block_boundary: 1, is_string: 1, os: 1, }, + { opcode: 0xF3AF, block_boundary: 1, is_string: 1, os: 1, }, { opcode: 0xC2, block_boundary: 1, no_next_instruction: 1, os: 1, imm16: 1, skip: 1, }, // ret { opcode: 0xC3, block_boundary: 1, no_next_instruction: 1, os: 1, skip: 1, }, diff --git a/src/native/instructions.c b/src/native/instructions.c index c61978df..50d5ba6d 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -285,12 +285,25 @@ void instr16_6B_reg(int32_t r1, int32_t r, int32_t imm) { write_reg16(r, imul_re void instr32_6B_mem(int32_t addr, int32_t r, int32_t imm) { write_reg32(r, imul_reg32(safe_read32s(addr), imm)); } void instr32_6B_reg(int32_t r1, int32_t r, int32_t imm) { write_reg32(r, imul_reg32(read_reg32(r1), imm)); } -void instr_6C() { insb(); } -void instr16_6D() { insw(); } -void instr32_6D() { insd(); } -void instr_6E() { outsb(); } -void instr16_6F() { outsw(); } -void instr32_6F() { outsd(); } +void instr_6C() { insb_no_rep(); } +void instr_F26C() { insb_rep(); } +void instr_F36C() { insb_rep(); } +void instr16_6D() { insw_no_rep(); } +void instr16_F26D() { insw_rep(); } +void instr16_F36D() { insw_rep(); } +void instr32_6D() { insd_no_rep(); } +void instr32_F26D() { insd_rep(); } +void instr32_F36D() { insd_rep(); } + +void instr_6E() { outsb_no_rep(); } +void instr_F26E() { outsb_rep(); } +void instr_F36E() { outsb_rep(); } +void instr16_6F() { outsw_no_rep(); } +void instr16_F26F() { outsw_rep(); } +void instr16_F36F() { outsw_rep(); } +void instr32_6F() { outsd_no_rep(); } +void instr32_F26F() { outsd_rep(); } +void instr32_F36F() { outsd_rep(); } void instr16_70(int32_t imm8) { jmpcc16( test_o(), imm8); } void instr16_71(int32_t imm8) { jmpcc16(!test_o(), imm8); } @@ -670,12 +683,25 @@ void instr32_A3(int32_t moffs) { safe_write32(get_seg_prefix_ds(moffs), reg32s[EAX]); } -void instr_A4() { movsb(); } -void instr16_A5() { movsw(); } -void instr32_A5() { movsd(); } -void instr_A6() { cmpsb(); } -void instr16_A7() { cmpsw(); } -void instr32_A7() { cmpsd(); } +void instr_A4() { movsb_no_rep(); } +void instr_F2A4() { movsb_rep(); } +void instr_F3A4() { movsb_rep(); } +void instr16_A5() { movsw_no_rep(); } +void instr16_F2A5() { movsw_rep(); } +void instr16_F3A5() { movsw_rep(); } +void instr32_A5() { movsd_no_rep(); } +void instr32_F2A5() { movsd_rep(); } +void instr32_F3A5() { movsd_rep(); } + +void instr_A6() { cmpsb_no_rep(); } +void instr_F2A6() { cmpsb_rep(PREFIX_F2); } +void instr_F3A6() { cmpsb_rep(PREFIX_F3); } +void instr16_A7() { cmpsw_no_rep(); } +void instr16_F2A7() { cmpsw_rep(PREFIX_F2); } +void instr16_F3A7() { cmpsw_rep(PREFIX_F3); } +void instr32_A7() { cmpsd_no_rep(); } +void instr32_F2A7() { cmpsd_rep(PREFIX_F2); } +void instr32_F3A7() { cmpsd_rep(PREFIX_F3); } void instr_A8(int32_t imm8) { test8(reg8[AL], imm8); @@ -687,15 +713,35 @@ void instr32_A9(int32_t imm32) { test32(reg32s[EAX], imm32); } -void instr_AA() { stosb(); } -void instr16_AB() { stosw(); } -void instr32_AB() { stosd(); } -void instr_AC() { lodsb(); } -void instr16_AD() { lodsw(); } -void instr32_AD() { lodsd(); } -void instr_AE() { scasb(); } -void instr16_AF() { scasw(); } -void instr32_AF() { scasd(); } +void instr_AA() { stosb_no_rep(); } +void instr_F2AA() { stosb_rep(); } +void instr_F3AA() { stosb_rep(); } +void instr16_AB() { stosw_no_rep(); } +void instr16_F2AB() { stosw_rep(); } +void instr16_F3AB() { stosw_rep(); } +void instr32_AB() { stosd_no_rep(); } +void instr32_F2AB() { stosd_rep(); } +void instr32_F3AB() { stosd_rep(); } + +void instr_AC() { lodsb_no_rep(); } +void instr_F2AC() { lodsb_rep(); } +void instr_F3AC() { lodsb_rep(); } +void instr16_AD() { lodsw_no_rep(); } +void instr16_F2AD() { lodsw_rep(); } +void instr16_F3AD() { lodsw_rep(); } +void instr32_AD() { lodsd_no_rep(); } +void instr32_F2AD() { lodsd_rep(); } +void instr32_F3AD() { lodsd_rep(); } + +void instr_AE() { scasb_no_rep(); } +void instr_F2AE() { scasb_rep(PREFIX_F2); } +void instr_F3AE() { scasb_rep(PREFIX_F3); } +void instr16_AF() { scasw_no_rep(); } +void instr16_F2AF() { scasw_rep(PREFIX_F2); } +void instr16_F3AF() { scasw_rep(PREFIX_F3); } +void instr32_AF() { scasd_no_rep(); } +void instr32_F2AF() { scasd_rep(PREFIX_F2); } +void instr32_F3AF() { scasd_rep(PREFIX_F3); } void instr_B0(int32_t imm8) { reg8[AL] = imm8; } diff --git a/src/native/string.c b/src/native/string.c index 529bef17..134b9546 100644 --- a/src/native/string.c +++ b/src/native/string.c @@ -85,18 +85,6 @@ void movsb_no_rep() add_reg_asize(ESI, size); } -void movsb() -{ - if(*prefixes & PREFIX_MASK_REP) - { - movsb_rep(); - } - else - { - movsb_no_rep(); - } -} - void movsw_rep() { int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); @@ -161,18 +149,6 @@ void movsw_no_rep() add_reg_asize(ESI, size); } -void movsw() -{ - if(*prefixes & PREFIX_MASK_REP) - { - movsw_rep(); - } - else - { - movsw_no_rep(); - } -} - void movsd_rep() { int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); @@ -237,19 +213,7 @@ void movsd_no_rep() add_reg_asize(ESI, size); } -void movsd() -{ - if(*prefixes & PREFIX_MASK_REP) - { - movsd_rep(); - } - else - { - movsd_no_rep(); - } -} - -void cmpsb_rep() +void cmpsb_rep(int32_t prefix_flag) { int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); int32_t dest = get_seg(ES) + get_reg_asize(EDI); @@ -260,7 +224,7 @@ void cmpsb_rep() if(count == 0) return; int32_t cont = false; int32_t start_count = count; - int32_t is_repz = (*prefixes & PREFIX_MASK_REP) == PREFIX_REPZ; + int32_t is_repz = prefix_flag == PREFIX_REPZ; int32_t cycle_counter = MAX_COUNT_PER_CYCLE; int32_t phys_src = translate_address_read(src); int32_t phys_dest = translate_address_read(dest); @@ -305,19 +269,7 @@ void cmpsb_no_rep() cmp8(data_src, data_dest); } -void cmpsb() -{ - if(*prefixes & PREFIX_MASK_REP) - { - cmpsb_rep(); - } - else - { - cmpsb_no_rep(); - } -} - -void cmpsw_rep() +void cmpsw_rep(int32_t prefix_flag) { int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); int32_t dest = get_seg(ES) + get_reg_asize(EDI); @@ -328,7 +280,7 @@ void cmpsw_rep() if(count == 0) return; int32_t cont = false; int32_t start_count = count; - int32_t is_repz = (*prefixes & PREFIX_MASK_REP) == PREFIX_REPZ; + int32_t is_repz = prefix_flag == PREFIX_REPZ; int32_t cycle_counter = MAX_COUNT_PER_CYCLE; if(!(dest & 1) && !(src & 1)) { @@ -391,19 +343,7 @@ void cmpsw_no_rep() cmp16(data_src, data_dest); } -void cmpsw() -{ - if(*prefixes & PREFIX_MASK_REP) - { - cmpsw_rep(); - } - else - { - cmpsw_no_rep(); - } -} - -void cmpsd_rep() +void cmpsd_rep(int32_t prefix_flag) { int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); int32_t dest = get_seg(ES) + get_reg_asize(EDI); @@ -414,7 +354,7 @@ void cmpsd_rep() if(count == 0) return; int32_t cont = false; int32_t start_count = count; - int32_t is_repz = (*prefixes & PREFIX_MASK_REP) == PREFIX_REPZ; + int32_t is_repz = prefix_flag == PREFIX_REPZ; int32_t cycle_counter = MAX_COUNT_PER_CYCLE; if(!(dest & 3) && !(src & 3)) { @@ -477,18 +417,6 @@ void cmpsd_no_rep() cmp32(data_src, data_dest); } -void cmpsd() -{ - if(*prefixes & PREFIX_MASK_REP) - { - cmpsd_rep(); - } - else - { - cmpsd_no_rep(); - } -} - void stosb_rep() { int32_t data = reg8[AL]; @@ -532,18 +460,6 @@ void stosb_no_rep() add_reg_asize(EDI, size); } -void stosb() -{ - if(*prefixes & PREFIX_MASK_REP) - { - stosb_rep(); - } - else - { - stosb_no_rep(); - } -} - void stosw_rep() { int32_t data = reg16[AX]; @@ -602,18 +518,6 @@ void stosw_no_rep() add_reg_asize(EDI, size); } -void stosw() -{ - if(*prefixes & PREFIX_MASK_REP) - { - stosw_rep(); - } - else - { - stosw_no_rep(); - } -} - void stosd_rep() { int32_t data = reg32s[EAX]; @@ -672,18 +576,6 @@ void stosd_no_rep() add_reg_asize(EDI, size); } -void stosd() -{ - if(*prefixes & PREFIX_MASK_REP) - { - stosd_rep(); - } - else - { - stosd_no_rep(); - } -} - void lodsb_rep() { int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); @@ -723,19 +615,6 @@ void lodsb_no_rep() add_reg_asize(ESI, size); } - -void lodsb() -{ - if(*prefixes & PREFIX_MASK_REP) - { - lodsb_rep(); - } - else - { - lodsb_no_rep(); - } -} - void lodsw_rep() { int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); @@ -769,18 +648,6 @@ void lodsw_no_rep() } -void lodsw() -{ - if(*prefixes & PREFIX_MASK_REP) - { - lodsw_rep(); - } - else - { - lodsw_no_rep(); - } -} - void lodsd_rep() { int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); @@ -813,19 +680,7 @@ void lodsd_no_rep() add_reg_asize(ESI, size); } -void lodsd() -{ - if(*prefixes & PREFIX_MASK_REP) - { - lodsd_rep(); - } - else - { - lodsd_no_rep(); - } -} - -void scasb_rep() +void scasb_rep(int32_t prefix_flag) { int32_t dest = get_seg(ES) + get_reg_asize(EDI); int32_t size = *flags & FLAG_DIRECTION ? -1 : 1; @@ -836,7 +691,7 @@ void scasb_rep() if(count == 0) return; int32_t cont = false; int32_t start_count = count; - int32_t is_repz = (*prefixes & PREFIX_MASK_REP) == PREFIX_REPZ; + int32_t is_repz = prefix_flag == PREFIX_REPZ; int32_t cycle_counter = MAX_COUNT_PER_CYCLE; int32_t phys_dest = translate_address_read(dest); if(*paging) @@ -873,19 +728,7 @@ void scasb_no_rep() cmp8(data_src, data_dest); } -void scasb() -{ - if(*prefixes & PREFIX_MASK_REP) - { - scasb_rep(); - } - else - { - scasb_no_rep(); - } -} - -void scasw_rep() +void scasw_rep(int32_t prefix_flag) { int32_t dest = get_seg(ES) + get_reg_asize(EDI); int32_t size = *flags & FLAG_DIRECTION ? -2 : 2; @@ -896,7 +739,7 @@ void scasw_rep() if(count == 0) return; int32_t cont = false; int32_t start_count = count; - int32_t is_repz = (*prefixes & PREFIX_MASK_REP) == PREFIX_REPZ; + int32_t is_repz = prefix_flag == PREFIX_REPZ; int32_t cycle_counter = MAX_COUNT_PER_CYCLE; if(!(dest & 1)) { @@ -948,19 +791,7 @@ void scasw_no_rep() cmp16(data_src, data_dest); } -void scasw() -{ - if(*prefixes & PREFIX_MASK_REP) - { - scasw_rep(); - } - else - { - scasw_no_rep(); - } -} - -void scasd_rep() +void scasd_rep(int32_t prefix_flag) { int32_t dest = get_seg(ES) + get_reg_asize(EDI); int32_t size = *flags & FLAG_DIRECTION ? -4 : 4; @@ -971,7 +802,7 @@ void scasd_rep() if(count == 0) return; int32_t cont = false; int32_t start_count = count; - int32_t is_repz = (*prefixes & PREFIX_MASK_REP) == PREFIX_REPZ; + int32_t is_repz = prefix_flag == PREFIX_REPZ; int32_t cycle_counter = MAX_COUNT_PER_CYCLE; if(!(dest & 3)) { @@ -1024,18 +855,6 @@ void scasd_no_rep() } -void scasd() -{ - if(*prefixes & PREFIX_MASK_REP) - { - scasd_rep(); - } - else - { - scasd_no_rep(); - } -} - void insb_rep() { int32_t port = reg16[DX]; @@ -1084,18 +903,6 @@ void insb_no_rep() add_reg_asize(EDI, size); } -void insb() -{ - if(*prefixes & PREFIX_MASK_REP) - { - insb_rep(); - } - else - { - insb_no_rep(); - } -} - void insw_rep() { int32_t port = reg16[DX]; @@ -1160,18 +967,6 @@ void insw_no_rep() add_reg_asize(EDI, size); } -void insw() -{ - if(*prefixes & PREFIX_MASK_REP) - { - insw_rep(); - } - else - { - insw_no_rep(); - } -} - void insd_rep() { int32_t port = reg16[DX]; @@ -1236,18 +1031,6 @@ void insd_no_rep() add_reg_asize(EDI, size); } -void insd() -{ - if(*prefixes & PREFIX_MASK_REP) - { - insd_rep(); - } - else - { - insd_no_rep(); - } -} - void outsb_rep() { int32_t port = reg16[DX]; @@ -1295,17 +1078,6 @@ void outsb_no_rep() add_reg_asize(ESI, size); } -void outsb() -{ - if(*prefixes & PREFIX_MASK_REP) - { - outsb_rep(); - } - else - { - outsb_no_rep(); - } -} void outsw_rep() { @@ -1369,18 +1141,6 @@ void outsw_no_rep() add_reg_asize(ESI, size); } -void outsw() -{ - if(*prefixes & PREFIX_MASK_REP) - { - outsw_rep(); - } - else - { - outsw_no_rep(); - } -} - void outsd_rep() { int32_t port = reg16[DX]; @@ -1442,15 +1202,3 @@ void outsd_no_rep() io_port_write32(port, safe_read32s(src)); add_reg_asize(ESI, size); } - -void outsd() -{ - if(*prefixes & PREFIX_MASK_REP) - { - outsd_rep(); - } - else - { - outsd_no_rep(); - } -} diff --git a/src/native/string.h b/src/native/string.h index 55303279..94d92fd3 100644 --- a/src/native/string.h +++ b/src/native/string.h @@ -4,66 +4,52 @@ int32_t string_get_cycle_count(int32_t size, int32_t address); int32_t string_get_cycle_count2(int32_t size, int32_t addr1, int32_t addr2); + void movsb_rep(void); void movsb_no_rep(void); -void movsb(void); void movsw_rep(void); void movsw_no_rep(void); -void movsw(void); void movsd_rep(void); void movsd_no_rep(void); -void movsd(void); -void cmpsb_rep(void); + +void cmpsb_rep(int32_t); void cmpsb_no_rep(void); -void cmpsb(void); -void cmpsw_rep(void); +void cmpsw_rep(int32_t); void cmpsw_no_rep(void); -void cmpsw(void); -void cmpsd_rep(void); +void cmpsd_rep(int32_t); void cmpsd_no_rep(void); -void cmpsd(void); + void stosb_rep(void); void stosb_no_rep(void); -void stosb(void); void stosw_rep(void); void stosw_no_rep(void); -void stosw(void); void stosd_rep(void); void stosd_no_rep(void); -void stosd(void); + void lodsb_rep(void); void lodsb_no_rep(void); -void lodsb(void); void lodsw_rep(void); void lodsw_no_rep(void); -void lodsw(void); void lodsd_rep(void); void lodsd_no_rep(void); -void lodsd(void); -void scasb_rep(void); + +void scasb_rep(int32_t); void scasb_no_rep(void); -void scasb(void); -void scasw_rep(void); +void scasw_rep(int32_t); void scasw_no_rep(void); -void scasw(void); -void scasd_rep(void); +void scasd_rep(int32_t); void scasd_no_rep(void); -void scasd(void); + void insb_rep(void); void insb_no_rep(void); -void insb(void); void insw_rep(void); void insw_no_rep(void); -void insw(void); void insd_rep(void); void insd_no_rep(void); -void insd(void); + void outsb_rep(void); void outsb_no_rep(void); -void outsb(void); void outsw_rep(void); void outsw_no_rep(void); -void outsw(void); void outsd_rep(void); void outsd_no_rep(void); -void outsd(void); diff --git a/tests/nasm/create_tests.js b/tests/nasm/create_tests.js index a46833cb..ffc7221b 100755 --- a/tests/nasm/create_tests.js +++ b/tests/nasm/create_tests.js @@ -247,7 +247,6 @@ function create_nasm(op, config) codes.push("mov ecx, 3"); codes.push("mov edi, (120000h-16)"); codes.push("mov esi, (120000h-20)"); - codes.push(["", "db 0f2h", "db 0f3h"]); } if(size === 16) @@ -280,7 +279,7 @@ function create_nasm(op, config) if(opcode >= 0x100) { let c = opcode >> 8; - console.assert(c === 0x0F, "Expected 0f prefix, got " + c.toString(16)); + console.assert(c === 0x0F || c === 0xF2 || c === 0xF3, "Expected 0F, F2, or F3 prefix, got " + c.toString(16)); codes.push("db " + c); opcode &= ~0xFF00; } From bdcaa62f51c50b2980a54e4d66ed921011e1f3b3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 12 Jul 2018 15:20:58 -0600 Subject: [PATCH 1029/2137] Don't generate code for string prefixes --- src/rust/jit_instructions.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 08ecf525..738b94f2 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -24,9 +24,6 @@ pub fn jit_instruction(cpu: &mut CpuContext, builder: &mut WasmBuilder, instr_fl } pub fn jit_handle_prefix(ctx: &mut JitContext, instr_flags: &mut u32) { - // TODO: Could avoid repeatedly generating prefix updates - let prefixes = ctx.cpu.prefixes; - codegen::gen_add_prefix_bits(ctx, prefixes); ::gen::jit::jit( ctx.cpu.read_imm8() as u32 | (ctx.cpu.osize_32() as u32) << 8, ctx, @@ -38,6 +35,8 @@ pub fn jit_handle_prefix(ctx: &mut JitContext, instr_flags: &mut u32) { pub fn jit_handle_segment_prefix(segment: u32, ctx: &mut JitContext, instr_flags: &mut u32) { assert!(segment <= 5); ctx.cpu.prefixes |= segment + 1; + // TODO: Could merge multiple prefix updates into one + codegen::gen_add_prefix_bits(ctx, segment + 1); jit_handle_prefix(ctx, instr_flags) } @@ -69,10 +68,14 @@ pub fn instr_65_jit(ctx: &mut JitContext, instr_flags: &mut u32) { pub fn instr_66_jit(ctx: &mut JitContext, instr_flags: &mut u32) { ctx.cpu.prefixes |= PREFIX_66; + // TODO: Could merge multiple prefix updates into one + codegen::gen_add_prefix_bits(ctx, PREFIX_66); jit_handle_prefix(ctx, instr_flags) } pub fn instr_67_jit(ctx: &mut JitContext, instr_flags: &mut u32) { ctx.cpu.prefixes |= PREFIX_67; + // TODO: Could merge multiple prefix updates into one + codegen::gen_add_prefix_bits(ctx, PREFIX_67); jit_handle_prefix(ctx, instr_flags) } pub fn instr_F0_jit(ctx: &mut JitContext, instr_flags: &mut u32) { @@ -81,10 +84,14 @@ pub fn instr_F0_jit(ctx: &mut JitContext, instr_flags: &mut u32) { } pub fn instr_F2_jit(ctx: &mut JitContext, instr_flags: &mut u32) { ctx.cpu.prefixes |= PREFIX_F2; + // string/sse prefix: Don't generate code to update prefixes at runtime. This means runtime + // instructions can't inspect the prefixes for this flags jit_handle_prefix(ctx, instr_flags) } pub fn instr_F3_jit(ctx: &mut JitContext, instr_flags: &mut u32) { ctx.cpu.prefixes |= PREFIX_F3; + // string/sse prefix: Don't generate code to update prefixes at runtime. This means runtime + // instructions can't inspect the prefixes for this flags jit_handle_prefix(ctx, instr_flags) } From 8f246c24d602388de313491da64a302ffa247572 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 12 Jul 2018 16:22:51 -0600 Subject: [PATCH 1030/2137] Delete dead code: CPU.prototype.set_cr4 --- src/cpu.js | 40 ---------------------------------------- 1 file changed, 40 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index 01b8d0eb..c01a7089 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -1454,46 +1454,6 @@ CPU.prototype.set_cr0 = function(cr0) this.protected_mode[0] = +((this.cr[0] & CR0_PE) === CR0_PE); }; -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); - } - - if((this.cr[4] ^ cr4) & CR4_PGE) - { - if(cr4 & CR4_PGE) - { - // The PGE bit has been enabled. The global TLB is - // still empty, so we only have to copy it over - this.clear_tlb(); - } - else - { - // Clear the global TLB - this.full_clear_tlb(); - } - } - - this.cr[4] = cr4; - this.page_size_extensions[0] = (cr4 & CR4_PSE) ? PSE_ENABLED : 0; - - if(cr4 & CR4_PAE) - { - throw this.debug.unimpl("PAE"); - } - - if(cr4 & 0xFFFFF900) - { - dbg_assert(false, "Unimplemented CR4 bits: " + h(cr4)); - this.trigger_ud(); - } - - dbg_log("cr4=" + h(cr4 >>> 0), LOG_CPU); -}; - CPU.prototype.cpl_changed = function() { this.last_virt_eip[0] = -1; From 815ef2b0552b39b7fcb5bacf0d1acc62cbe00f6c Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 12 Jul 2018 16:24:53 -0600 Subject: [PATCH 1031/2137] Be more conservative about clearing the tlb on cr4 writes --- src/native/instructions_0f.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 59b7302b..a13d128b 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -536,22 +536,13 @@ void instr_0F22(int32_t r, int32_t creg) { if(data & (1 << 11 | 1 << 12 | 1 << 15 | 1 << 16 | 1 << 19 | 0xFFC00000)) { + dbg_log("trigger_gp: Invalid cr4 bit"); trigger_gp(0); } - if((cr[4] ^ data) & CR4_PGE) + if((cr[4] ^ data) & (CR4_PGE | CR4_PSE)) { - if(data & CR4_PGE) - { - // The PGE bit has been enabled. The global TLB is - // still empty, so we only have to copy it over - clear_tlb(); - } - else - { - // Clear the global TLB - full_clear_tlb(); - } + full_clear_tlb(); } cr[4] = data; From 832cf9544f5c5da0b7ecff27d03c3c34770cb590 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 12 Jul 2018 16:39:10 -0600 Subject: [PATCH 1032/2137] Use tlb cache even when paging is off Since the tlb is used to store jit-specific optimisation, it should also be used when paging is off. This also simplifes the general paging code a bit. --- src/native/cpu.c | 166 +++++++++++++++++++++++------------------------ 1 file changed, 82 insertions(+), 84 deletions(-) diff --git a/src/native/cpu.c b/src/native/cpu.c index acb07ed6..5031f694 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -130,118 +130,128 @@ void trigger_pagefault(bool write, bool user, bool present) int32_t do_page_translation(int32_t addr, bool for_writing, bool user) { - assert(*paging); - - int32_t page = (uint32_t)addr >> 12; - int32_t page_dir_addr = ((uint32_t)cr[3] >> 2) + (page >> 10); - int32_t page_dir_entry = read_aligned32(page_dir_addr); - int32_t high; bool can_write = true; bool global; bool allow_user = true; - const bool kernel_write_override = !user && !(cr[0] & CR0_WP); + int32_t page = (uint32_t)addr >> 12; + int32_t high; - if(!(page_dir_entry & PAGE_TABLE_PRESENT_MASK)) + if(!*paging) { - // to do at this place: - // - // - set cr2 = addr (which caused the page fault) - // - call_interrupt_vector with id 14, error code 0-7 (requires information if read or write) - // - prevent execution of the function that triggered this call - //dbg_log("#PF not present", LOG_CPU); - - cr[2] = addr; - trigger_pagefault(for_writing, user, 0); - - // never reached as trigger_pagefault throws - dbg_assert(false); - } - - if((page_dir_entry & PAGE_TABLE_RW_MASK) == 0 && !kernel_write_override) - { - can_write = false; - - if(for_writing) - { - cr[2] = addr; - trigger_pagefault(for_writing, user, 1); - dbg_assert(false); - } - } - - if((page_dir_entry & PAGE_TABLE_USER_MASK) == 0) - { - allow_user = false; - - if(user) - { - // "Page Fault: page table accessed by non-supervisor"; - //dbg_log("#PF supervisor", LOG_CPU); - cr[2] = addr; - trigger_pagefault(for_writing, user, 1); - dbg_assert(false); - } - } - - if(page_dir_entry & *page_size_extensions) - { - // size bit is set - - // set the accessed and dirty bits - write_aligned32(page_dir_addr, page_dir_entry | PAGE_TABLE_ACCESSED_MASK | - (for_writing ? PAGE_TABLE_DIRTY_MASK : 0)); - - high = (page_dir_entry & 0xFFC00000) | (addr & 0x3FF000); - global = (page_dir_entry & PAGE_TABLE_GLOBAL_MASK) == PAGE_TABLE_GLOBAL_MASK; + // paging disabled + high = addr & 0xFFFFF000; + global = false; } else { - int32_t page_table_addr = ((uint32_t)(page_dir_entry & 0xFFFFF000) >> 2) + (page & 0x3FF); - int32_t page_table_entry = read_aligned32(page_table_addr); + int32_t page_dir_addr = ((uint32_t)cr[3] >> 2) + (page >> 10); + int32_t page_dir_entry = read_aligned32(page_dir_addr); - if((page_table_entry & PAGE_TABLE_PRESENT_MASK) == 0) + // XXX + const bool kernel_write_override = !user && !(cr[0] & CR0_WP); + + if(!(page_dir_entry & PAGE_TABLE_PRESENT_MASK)) { - //dbg_log("#PF not present table", LOG_CPU); + // to do at this place: + // + // - set cr2 = addr (which caused the page fault) + // - call_interrupt_vector with id 14, error code 0-7 (requires information if read or write) + // - prevent execution of the function that triggered this call + //dbg_log("#PF not present", LOG_CPU); + cr[2] = addr; trigger_pagefault(for_writing, user, 0); + + // never reached as trigger_pagefault throws dbg_assert(false); } - if((page_table_entry & PAGE_TABLE_RW_MASK) == 0 && !kernel_write_override) + if((page_dir_entry & PAGE_TABLE_RW_MASK) == 0 && !kernel_write_override) { can_write = false; if(for_writing) { - //dbg_log("#PF not writable page", LOG_CPU); cr[2] = addr; trigger_pagefault(for_writing, user, 1); dbg_assert(false); } } - if((page_table_entry & PAGE_TABLE_USER_MASK) == 0) + if((page_dir_entry & PAGE_TABLE_USER_MASK) == 0) { allow_user = false; if(user) { - //dbg_log("#PF not supervisor page", LOG_CPU); + // "Page Fault: page table accessed by non-supervisor"; + //dbg_log("#PF supervisor", LOG_CPU); cr[2] = addr; trigger_pagefault(for_writing, user, 1); dbg_assert(false); } } - // set the accessed and dirty bits - write_aligned32(page_dir_addr, page_dir_entry | PAGE_TABLE_ACCESSED_MASK); - write_aligned32(page_table_addr, - page_table_entry | PAGE_TABLE_ACCESSED_MASK | + if(page_dir_entry & *page_size_extensions) + { + // size bit is set + + // set the accessed and dirty bits + write_aligned32(page_dir_addr, page_dir_entry | PAGE_TABLE_ACCESSED_MASK | (for_writing ? PAGE_TABLE_DIRTY_MASK : 0)); - high = page_table_entry & 0xFFFFF000; - global = (page_table_entry & PAGE_TABLE_GLOBAL_MASK) == PAGE_TABLE_GLOBAL_MASK; + high = (page_dir_entry & 0xFFC00000) | (addr & 0x3FF000); + global = (page_dir_entry & PAGE_TABLE_GLOBAL_MASK) == PAGE_TABLE_GLOBAL_MASK; + } + else + { + int32_t page_table_addr = ((uint32_t)(page_dir_entry & 0xFFFFF000) >> 2) + (page & 0x3FF); + int32_t page_table_entry = read_aligned32(page_table_addr); + + if((page_table_entry & PAGE_TABLE_PRESENT_MASK) == 0) + { + //dbg_log("#PF not present table", LOG_CPU); + cr[2] = addr; + trigger_pagefault(for_writing, user, 0); + dbg_assert(false); + } + + if((page_table_entry & PAGE_TABLE_RW_MASK) == 0 && !kernel_write_override) + { + can_write = false; + + if(for_writing) + { + //dbg_log("#PF not writable page", LOG_CPU); + cr[2] = addr; + trigger_pagefault(for_writing, user, 1); + dbg_assert(false); + } + } + + if((page_table_entry & PAGE_TABLE_USER_MASK) == 0) + { + allow_user = false; + + if(user) + { + //dbg_log("#PF not supervisor page", LOG_CPU); + cr[2] = addr; + trigger_pagefault(for_writing, user, 1); + dbg_assert(false); + } + } + + // set the accessed and dirty bits + write_aligned32(page_dir_addr, page_dir_entry | PAGE_TABLE_ACCESSED_MASK); + write_aligned32(page_table_addr, + page_table_entry | PAGE_TABLE_ACCESSED_MASK | + (for_writing ? PAGE_TABLE_DIRTY_MASK : 0)); + + high = page_table_entry & 0xFFFFF000; + global = (page_table_entry & PAGE_TABLE_GLOBAL_MASK) == PAGE_TABLE_GLOBAL_MASK; + } } if(tlb_data[page] == 0) @@ -393,8 +403,6 @@ void writable_or_pagefault(int32_t addr, int32_t size) uint32_t translate_address_read(int32_t address) { - if(!*paging) return address; - int32_t base = (uint32_t)address >> 12; int32_t entry = tlb_data[base]; bool user = cpl[0] == 3; @@ -410,8 +418,6 @@ uint32_t translate_address_read(int32_t address) uint32_t translate_address_write(int32_t address) { - if(!*paging) return address; - int32_t base = (uint32_t)address >> 12; int32_t entry = tlb_data[base]; bool user = cpl[0] == 3; @@ -427,8 +433,6 @@ uint32_t translate_address_write(int32_t address) uint32_t translate_address_system_read(int32_t address) { - if(!*paging) return address; - int32_t base = (uint32_t)address >> 12; int32_t entry = tlb_data[base]; if(entry & TLB_VALID) @@ -443,8 +447,6 @@ uint32_t translate_address_system_read(int32_t address) uint32_t translate_address_system_write(int32_t address) { - if(!*paging) return address; - int32_t base = (uint32_t)address >> 12; int32_t entry = tlb_data[base]; if((entry & (TLB_VALID | TLB_READONLY)) == TLB_VALID) @@ -942,8 +944,6 @@ int32_t safe_read32s(int32_t address) int32_t entry = tlb_data[base]; int32_t info_bits = entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~TLB_HAS_CODE; - // XXX: Paging check - if(info_bits == TLB_VALID && (address & 0xFFF) <= (0x1000 - 4)) { #if ENABLE_PROFILER_SAFE_READ_WRITE @@ -1061,8 +1061,6 @@ void safe_write32(int32_t address, int32_t value) int32_t entry = tlb_data[base]; int32_t info_bits = entry & 0xFFF & ~TLB_GLOBAL; - // XXX: Paging check - if(info_bits == TLB_VALID && (address & 0xFFF) <= (0x1000 - 4)) { #if ENABLE_PROFILER_SAFE_READ_WRITE From 0e28694837f1f47e916057bb1eba71592fa6306b Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 12 Jul 2018 17:15:53 -0600 Subject: [PATCH 1033/2137] FPU: Replace double-safe_{read,write}32 by safe_{read,write}64 --- src/native/fpu.c | 45 ++++++++++++++------------------------------- 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/src/native/fpu.c b/src/native/fpu.c index 883683c9..6f6666e9 100644 --- a/src/native/fpu.c +++ b/src/native/fpu.c @@ -32,6 +32,7 @@ const double_t INDEFINITE_NAN = NAN; union f64_int { uint8_t u8[8]; int32_t i32[2]; + uint64_t u64[1]; double_t f64; }; @@ -128,16 +129,16 @@ void fpu_store_m80(uint32_t addr, double_t n) dbg_assert(exponent >= 0 && exponent < 0x8000); // writable_or_pagefault must have checked called by the caller! - safe_write32(addr, low); - safe_write32(addr + 4, high); + safe_write64(addr, (uint64_t)low & 0xFFFFFFFF | (uint64_t)high << 32); safe_write16(addr + 8, sign << 8 | exponent); } double_t fpu_load_m80(uint32_t addr) { + uint64_t value = safe_read64s(addr).u64[0]; + uint32_t low = value; + uint32_t high = value >> 32; int32_t exponent = safe_read16(addr + 8); - uint32_t low = ((uint32_t)(safe_read32s(addr))); - uint32_t high = ((uint32_t)(safe_read32s(addr + 4))); int32_t sign = exponent >> 15; exponent &= ~0x8000; @@ -537,24 +538,18 @@ double_t fpu_integer_round(double_t f) double_t fpu_load_m64(int32_t addr) { - // XXX: Use safe_read64s - int32_t low = safe_read32s(addr); - int32_t high = safe_read32s(addr + 4); + uint64_t value = safe_read64s(addr).u64[0]; - union f64_int v = { .i32 = { low, high } }; + union f64_int v = { .u64 = { value } }; return v.f64; } void fpu_store_m64(int32_t addr, double_t x) { - // XXX: Use safe_write64 - writable_or_pagefault(addr, 8); - union f64_int v = { .f64 = x }; - safe_write32(addr, v.i32[0]); - safe_write32(addr + 4, v.i32[1]); + safe_write64(addr, v.u64[0]); } double_t fpu_load_m32(int32_t addr) @@ -760,44 +755,32 @@ void fpu_fstp(int32_t r) void fpu_fildm64(int32_t addr) { - // XXX: Use safe_read64s - uint32_t low = safe_read32s(addr); - int32_t high = safe_read32s(addr + 4); + int64_t value = safe_read64s(addr).i64[0]; - double_t m64 = (double_t)low + 0x100000000 * (double_t)high; + double_t m64 = (double_t)value; fpu_push(m64); } void fpu_fistm64p(int32_t addr) { - writable_or_pagefault(addr, 8); - double_t st0 = fpu_integer_round(fpu_get_st0()); - //union f64_int v = { .f64 = st0 }; //dbg_log("fistp %x %x", v.i32[0], v.i32[1]); - int32_t st0_low; - int32_t st0_high; + int64_t value; if(st0 < TWO_POW_63 && st0 >= -TWO_POW_63) { - int64_t st0_int = st0; - st0_low = st0_int; - st0_high = st0_int >> 32; + value = st0; } else { - // write 0x8000000000000000 - st0_low = 0; - st0_high = 0x80000000; + value = 0x8000000000000000; fpu_invalid_arithmetic(); } - // XXX: Use safe_write64 - safe_write32(addr, st0_low); - safe_write32(addr + 4, st0_high); + safe_write64(addr, value); fpu_pop(); } From e5fca784fc1507b76a9360ddc57b5198ec5c89b8 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 12 Jul 2018 17:44:35 -0600 Subject: [PATCH 1034/2137] Remove useless state: page_size_extensions --- src/cpu.js | 8 ++------ src/native/const.h | 2 -- src/native/cpu.c | 2 +- src/native/global_pointers.h | 2 +- src/native/instructions_0f.c | 1 - 5 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index c01a7089..b80e69c6 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -72,9 +72,6 @@ function CPU(bus, wm, v86oxide, coverage_logger) // current privilege level this.cpl = new Int32Array(wm.memory.buffer, 612, 1); - // if false, pages are 4 KiB, else 4 Mib - this.page_size_extensions = new Int32Array(wm.memory.buffer, 616, 1); - // current operand/address size this.is_32 = new Int32Array(wm.memory.buffer, 804, 1); @@ -343,7 +340,7 @@ CPU.prototype.get_state = function() state[9] = this.page_fault[0]; state[10] = this.cr; state[11] = this.cpl[0]; - state[12] = this.page_size_extensions[0]; + state[13] = this.is_32[0]; state[16] = this.stack_size_32[0]; @@ -428,7 +425,7 @@ CPU.prototype.set_state = function(state) this.page_fault[0] = state[9]; this.cr.set(state[10]); this.cpl[0] = state[11]; - this.page_size_extensions[0] = state[12]; + this.is_32[0] = state[13]; this.stack_size_32[0] = state[16]; @@ -607,7 +604,6 @@ CPU.prototype.reset = function() this.dreg[7] = 0x400; this.cpl[0] = 0; this.paging[0] = 0; - this.page_size_extensions[0] = 0; this.is_32[0] = +false; this.stack_size_32[0] = +false; this.prefixes[0] = 0; diff --git a/src/native/const.h b/src/native/const.h index 6bae9819..b9e65a12 100644 --- a/src/native/const.h +++ b/src/native/const.h @@ -68,8 +68,6 @@ #define LDTR 7 -#define PSE_ENABLED 128 - #define PAGE_TABLE_PRESENT_MASK (1 << 0) #define PAGE_TABLE_RW_MASK (1 << 1) #define PAGE_TABLE_USER_MASK (1 << 2) diff --git a/src/native/cpu.c b/src/native/cpu.c index 5031f694..bea1d6c1 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -193,7 +193,7 @@ int32_t do_page_translation(int32_t addr, bool for_writing, bool user) } } - if(page_dir_entry & *page_size_extensions) + if((page_dir_entry & PAGE_TABLE_PSE_MASK) && (cr[4] & CR4_PSE)) { // size bit is set diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index b0e548e0..61090eca 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -36,7 +36,7 @@ static int32_t* const gdtr_offset = (int32_t* const) 576; static int32_t* const cr = (int32_t* const) 580; // length 32 static uint8_t* const cpl = (uint8_t* const) 612; -static int32_t* const page_size_extensions = (int32_t* const) 616; +// gap static int32_t* const last_virt_eip = (int32_t* const) 620; static int32_t* const eip_phys = (int32_t* const) 624; static int32_t* const last_virt_esp = (int32_t* const) 628; diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index a13d128b..02f76259 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -546,7 +546,6 @@ void instr_0F22(int32_t r, int32_t creg) { } cr[4] = data; - page_size_extensions[0] = (cr[4] & CR4_PSE) ? PSE_ENABLED : 0; if(cr[4] & CR4_PAE) { From e6457a319f004bf01f28f8a982313c4a4871bdc1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 12 Jul 2018 17:58:01 -0600 Subject: [PATCH 1035/2137] Limit cycle_counter when paging is off This change simplifies the code, and we don't care about the lost performance when paging is off. --- src/native/string.c | 102 +++++++++----------------------------------- 1 file changed, 19 insertions(+), 83 deletions(-) diff --git a/src/native/string.c b/src/native/string.c index 134b9546..f428a393 100644 --- a/src/native/string.c +++ b/src/native/string.c @@ -48,13 +48,9 @@ void movsb_rep() if(count == 0) return; int32_t cont = false; int32_t start_count = count; - int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + int32_t cycle_counter = string_get_cycle_count2(size, src, dest); int32_t phys_src = translate_address_read(src); int32_t phys_dest = translate_address_write(dest); - if(*paging) - { - cycle_counter = string_get_cycle_count2(size, src, dest); - } do { write8(phys_dest, read8(phys_src)); @@ -101,10 +97,7 @@ void movsw_rep() int32_t single_size = size < 0 ? -1 : 1; int32_t phys_src = translate_address_read(src) >> 1; int32_t phys_dest = translate_address_write(dest) >> 1; - if(*paging) - { - cycle_counter = string_get_cycle_count2(size, src, dest); - } + cycle_counter = string_get_cycle_count2(size, src, dest); do { write_aligned16(phys_dest, read_aligned16(phys_src)); @@ -165,10 +158,7 @@ void movsd_rep() int32_t single_size = size < 0 ? -1 : 1; int32_t phys_src = translate_address_read(src) >> 2; int32_t phys_dest = translate_address_write(dest) >> 2; - if(*paging) - { - cycle_counter = string_get_cycle_count2(size, src, dest); - } + cycle_counter = string_get_cycle_count2(size, src, dest); do { write_aligned32(phys_dest, read_aligned32(phys_src)); @@ -225,13 +215,9 @@ void cmpsb_rep(int32_t prefix_flag) int32_t cont = false; int32_t start_count = count; int32_t is_repz = prefix_flag == PREFIX_REPZ; - int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + int32_t cycle_counter = string_get_cycle_count2(size, src, dest); int32_t phys_src = translate_address_read(src); int32_t phys_dest = translate_address_read(dest); - if(*paging) - { - cycle_counter = string_get_cycle_count2(size, src, dest); - } do { data_dest = read8(phys_dest); @@ -287,10 +273,7 @@ void cmpsw_rep(int32_t prefix_flag) int32_t single_size = size < 0 ? -1 : 1; int32_t phys_src = translate_address_read(src) >> 1; int32_t phys_dest = translate_address_read(dest) >> 1; - if(*paging) - { - cycle_counter = string_get_cycle_count2(size, src, dest); - } + cycle_counter = string_get_cycle_count2(size, src, dest); do { data_dest = read_aligned16(phys_dest); @@ -361,10 +344,7 @@ void cmpsd_rep(int32_t prefix_flag) int32_t single_size = size < 0 ? -1 : 1; int32_t phys_src = translate_address_read(src) >> 2; int32_t phys_dest = translate_address_read(dest) >> 2; - if(*paging) - { - cycle_counter = string_get_cycle_count2(size, src, dest); - } + cycle_counter = string_get_cycle_count2(size, src, dest); do { data_dest = read_aligned32(phys_dest); @@ -427,12 +407,8 @@ void stosb_rep() if(count == 0) return; int32_t cont = false; int32_t start_count = count; - int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + int32_t cycle_counter = string_get_cycle_count(size, dest); int32_t phys_dest = translate_address_write(dest); - if(*paging) - { - cycle_counter = string_get_cycle_count(size, dest); - } do { write8(phys_dest, data); @@ -475,10 +451,7 @@ void stosw_rep() { int32_t single_size = size < 0 ? -1 : 1; int32_t phys_dest = translate_address_write(dest) >> 1; - if(*paging) - { - cycle_counter = string_get_cycle_count(size, dest); - } + cycle_counter = string_get_cycle_count(size, dest); do { write_aligned16(phys_dest, data); @@ -533,10 +506,7 @@ void stosd_rep() { int32_t single_size = size < 0 ? -1 : 1; int32_t phys_dest = translate_address_write(dest) >> 2; - if(*paging) - { - cycle_counter = string_get_cycle_count(size, dest); - } + cycle_counter = string_get_cycle_count(size, dest); do { write_aligned32(phys_dest, data); @@ -584,12 +554,8 @@ void lodsb_rep() if(count == 0) return; int32_t cont = false; int32_t start_count = count; - int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + int32_t cycle_counter = string_get_cycle_count(size, src); int32_t phys_src = translate_address_read(src); - if(*paging) - { - cycle_counter = string_get_cycle_count(size, src); - } do { reg8[AL] = read8(phys_src); @@ -692,12 +658,8 @@ void scasb_rep(int32_t prefix_flag) int32_t cont = false; int32_t start_count = count; int32_t is_repz = prefix_flag == PREFIX_REPZ; - int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + int32_t cycle_counter = string_get_cycle_count(size, dest); int32_t phys_dest = translate_address_read(dest); - if(*paging) - { - cycle_counter = string_get_cycle_count(size, dest); - } do { data_dest = read8(phys_dest); @@ -745,10 +707,7 @@ void scasw_rep(int32_t prefix_flag) { int32_t single_size = size < 0 ? -1 : 1; int32_t phys_dest = translate_address_read(dest) >> 1; - if(*paging) - { - cycle_counter = string_get_cycle_count(size, dest); - } + cycle_counter = string_get_cycle_count(size, dest); do { data_dest = read_aligned16(phys_dest); @@ -808,10 +767,7 @@ void scasd_rep(int32_t prefix_flag) { int32_t single_size = size < 0 ? -1 : 1; int32_t phys_dest = translate_address_read(dest) >> 2; - if(*paging) - { - cycle_counter = string_get_cycle_count(size, dest); - } + cycle_counter = string_get_cycle_count(size, dest); do { data_dest = read_aligned32(phys_dest); @@ -867,12 +823,8 @@ void insb_rep() if(count == 0) return; int32_t cont = false; int32_t start_count = count; - int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + int32_t cycle_counter = string_get_cycle_count(size, dest); int32_t phys_dest = translate_address_write(dest); - if(*paging) - { - cycle_counter = string_get_cycle_count(size, dest); - } do { write8(phys_dest, io_port_read8(port)); @@ -920,10 +872,7 @@ void insw_rep() { int32_t single_size = size < 0 ? -1 : 1; int32_t phys_dest = translate_address_write(dest) >> 1; - if(*paging) - { - cycle_counter = string_get_cycle_count(size, dest); - } + cycle_counter = string_get_cycle_count(size, dest); do { write_aligned16(phys_dest, io_port_read16(port)); @@ -984,10 +933,7 @@ void insd_rep() { int32_t single_size = size < 0 ? -1 : 1; int32_t phys_dest = translate_address_write(dest) >> 2; - if(*paging) - { - cycle_counter = string_get_cycle_count(size, dest); - } + cycle_counter = string_get_cycle_count(size, dest); do { write_aligned32(phys_dest, io_port_read32(port)); @@ -1043,12 +989,8 @@ void outsb_rep() if(count == 0) return; int32_t cont = false; int32_t start_count = count; - int32_t cycle_counter = MAX_COUNT_PER_CYCLE; + int32_t cycle_counter = string_get_cycle_count(size, src); int32_t phys_src = translate_address_read(src); - if(*paging) - { - cycle_counter = string_get_cycle_count(size, src); - } do { io_port_write8(port, read8(phys_src)); @@ -1096,10 +1038,7 @@ void outsw_rep() { int32_t single_size = size < 0 ? -1 : 1; int32_t phys_src = translate_address_read(src) >> 1; - if(*paging) - { - cycle_counter = string_get_cycle_count(size, src); - } + cycle_counter = string_get_cycle_count(size, src); do { io_port_write16(port, read_aligned16(phys_src)); @@ -1158,10 +1097,7 @@ void outsd_rep() { int32_t single_size = size < 0 ? -1 : 1; int32_t phys_src = translate_address_read(src) >> 2; - if(*paging) - { - cycle_counter = string_get_cycle_count(size, src); - } + cycle_counter = string_get_cycle_count(size, src); do { io_port_write32(port, read_aligned32(phys_src)); From 8585af1f894afcf5e48a5fe9f9b5ce5aa892702a Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 12 Jul 2018 18:04:28 -0600 Subject: [PATCH 1036/2137] Use dbg_assert over assert --- src/rust/analysis.rs | 2 +- src/rust/codegen.rs | 6 +++--- src/rust/cpu_context.rs | 12 ++++++------ src/rust/global_pointers.rs | 4 ++-- src/rust/jit.rs | 16 ++++++++-------- src/rust/jit_instructions.rs | 2 +- src/rust/modrm.rs | 4 ++-- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/rust/analysis.rs b/src/rust/analysis.rs index 38506dca..d537b2ff 100644 --- a/src/rust/analysis.rs +++ b/src/rust/analysis.rs @@ -43,7 +43,7 @@ pub fn analyze_step_handle_segment_prefix( cpu: &mut CpuContext, analysis: &mut Analysis, ) { - assert!(segment <= 5); + dbg_assert!(segment <= 5); cpu.prefixes |= segment + 1; analyze_step_handle_prefix(cpu, analysis) } diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 4d4d1c40..589f03ee 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -265,8 +265,8 @@ pub fn gen_safe_write32(ctx: &mut JitContext, local_for_address: u32, local_for_ // Since this function clobbers other variables, we confirm that the caller uses the local // variables we expect them to - assert!(local_for_address == GEN_LOCAL_SCRATCH0); - assert!(local_for_value == GEN_LOCAL_SCRATCH1); + dbg_assert!(local_for_address == GEN_LOCAL_SCRATCH0); + dbg_assert!(local_for_value == GEN_LOCAL_SCRATCH1); let builder = &mut ctx.builder; //let instruction_body = &mut ctx.builder.instruction_body; @@ -369,7 +369,7 @@ pub fn gen_clear_prefixes(ctx: &mut JitContext) { } pub fn gen_add_prefix_bits(ctx: &mut JitContext, mask: u32) { - assert!(mask < 0x100); + dbg_assert!(mask < 0x100); let instruction_body = &mut ctx.builder.instruction_body; wasm_util::push_i32(instruction_body, global_pointers::PREFIXES as i32); // load address of prefixes diff --git a/src/rust/cpu_context.rs b/src/rust/cpu_context.rs index e0f7e1b7..75aed9c8 100644 --- a/src/rust/cpu_context.rs +++ b/src/rust/cpu_context.rs @@ -12,15 +12,15 @@ pub struct CpuContext { impl CpuContext { pub fn advance8(&mut self) { - assert!(self.eip & 0xFFF < 0xFFF); + dbg_assert!(self.eip & 0xFFF < 0xFFF); self.eip += 1; } pub fn advance16(&mut self) { - assert!(self.eip & 0xFFF < 0xFFE); + dbg_assert!(self.eip & 0xFFF < 0xFFE); self.eip += 2; } pub fn advance32(&mut self) { - assert!(self.eip & 0xFFF < 0xFFC); + dbg_assert!(self.eip & 0xFFF < 0xFFC); self.eip += 4; } #[allow(unused)] @@ -34,21 +34,21 @@ impl CpuContext { } pub fn read_imm8(&mut self) -> u8 { - assert!(self.eip & 0xFFF < 0xFFF); + dbg_assert!(self.eip & 0xFFF < 0xFFF); let v = cpu::read8(self.eip); self.eip += 1; v } pub fn read_imm8s(&mut self) -> i8 { self.read_imm8() as i8 } pub fn read_imm16(&mut self) -> u16 { - assert!(self.eip & 0xFFF < 0xFFE); + dbg_assert!(self.eip & 0xFFF < 0xFFE); let v = cpu::read16(self.eip); self.eip += 2; v } pub fn read_imm16s(&mut self) -> i16 { self.read_imm16() as i16 } pub fn read_imm32(&mut self) -> u32 { - assert!(self.eip & 0xFFF < 0xFFC); + dbg_assert!(self.eip & 0xFFF < 0xFFC); let v = cpu::read32(self.eip); self.eip += 4; v diff --git a/src/rust/global_pointers.rs b/src/rust/global_pointers.rs index f717bb6c..3e2656df 100644 --- a/src/rust/global_pointers.rs +++ b/src/rust/global_pointers.rs @@ -9,10 +9,10 @@ pub const TLB_DATA: u32 = 0x400000; pub const MEMORY: u32 = 0x800000; pub fn get_reg16_offset(r: u32) -> u32 { - assert!(r < 8); + dbg_assert!(r < 8); REG + 4 * r } pub fn get_reg32_offset(r: u32) -> u32 { - assert!(r < 8); + dbg_assert!(r < 8); REG + 4 * r } diff --git a/src/rust/jit.rs b/src/rust/jit.rs index c99869df..2d77d6c7 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -416,7 +416,7 @@ pub fn jit_find_cache_entry(phys_address: u32, state_flags: CachedStateFlags) -> } if is_near_end_of_page(phys_address) { - assert!(entry.start_addr != phys_address); + dbg_assert!(entry.start_addr != phys_address); profiler::stat_increment(stat::S_RUN_INTERPRETED_NEAR_END_OF_PAGE); } } @@ -424,7 +424,7 @@ pub fn jit_find_cache_entry(phys_address: u32, state_flags: CachedStateFlags) -> if !entry.pending && entry.start_addr == phys_address && entry.state_flags == state_flags { #[cfg(debug_assertions)] { - assert!(cpu::read32(entry.start_addr) == entry.opcode) + dbg_assert!(cpu::read32(entry.start_addr) == entry.opcode) } return cached_code { wasm_table_index: entry.wasm_table_index, @@ -817,7 +817,7 @@ pub fn codegen_finalize_finished( _first_opcode: u32, _state_flags: CachedStateFlags, ) { - assert!(wasm_table_index != 0); + dbg_assert!(wasm_table_index != 0); match ctx .wasm_table_index_pending_free @@ -852,7 +852,7 @@ pub fn codegen_finalize_finished( for entry in jit_cache_array::iter() { if entry.wasm_table_index == wasm_table_index { - assert!(!entry.pending); + dbg_assert!(!entry.pending); } } } @@ -1241,7 +1241,7 @@ pub fn jit_dirty_page(ctx: &mut JitState, page: Page) { let entry = jit_cache_array::get_mut(cache_array_index); let wasm_table_index = entry.wasm_table_index; - assert!(page == Page::page_of(entry.start_addr)); + dbg_assert!(page == Page::page_of(entry.start_addr)); let next_cache_array_index = entry.next_index_same_page(); @@ -1291,7 +1291,7 @@ pub fn jit_dirty_page(ctx: &mut JitState, page: Page) { } pub fn jit_dirty_cache(ctx: &mut JitState, start_addr: u32, end_addr: u32) { - assert!(start_addr < end_addr); + dbg_assert!(start_addr < end_addr); let start_page = Page::page_of(start_addr); let end_page = Page::page_of(end_addr - 1); @@ -1302,7 +1302,7 @@ pub fn jit_dirty_cache(ctx: &mut JitState, start_addr: u32, end_addr: u32) { } pub fn jit_dirty_cache_small(ctx: &mut JitState, start_addr: u32, end_addr: u32) { - assert!(start_addr < end_addr); + dbg_assert!(start_addr < end_addr); let start_page = Page::page_of(start_addr); let end_page = Page::page_of(end_addr - 1); @@ -1312,7 +1312,7 @@ pub fn jit_dirty_cache_small(ctx: &mut JitState, start_addr: u32, end_addr: u32) // Note: This can't happen when paging is enabled, as writes across // boundaries are split up on two pages if start_page != end_page { - assert!(start_page.to_u32() + 1 == end_page.to_u32()); + dbg_assert!(start_page.to_u32() + 1 == end_page.to_u32()); jit_dirty_page(ctx, end_page); } } diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 738b94f2..f6e532d7 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -33,7 +33,7 @@ pub fn jit_handle_prefix(ctx: &mut JitContext, instr_flags: &mut u32) { } pub fn jit_handle_segment_prefix(segment: u32, ctx: &mut JitContext, instr_flags: &mut u32) { - assert!(segment <= 5); + dbg_assert!(segment <= 5); ctx.cpu.prefixes |= segment + 1; // TODO: Could merge multiple prefix updates into one codegen::gen_add_prefix_bits(ctx, segment + 1); diff --git a/src/rust/modrm.rs b/src/rust/modrm.rs index 416b1e6d..397180fd 100644 --- a/src/rust/modrm.rs +++ b/src/rust/modrm.rs @@ -16,7 +16,7 @@ pub fn skip(ctx: &mut CpuContext, modrm_byte: u8) { } fn skip16(ctx: &mut CpuContext, modrm_byte: u8) { - assert!(modrm_byte < 0xC0); + dbg_assert!(modrm_byte < 0xC0); let r = modrm_byte & 7; if modrm_byte < 0x40 { @@ -33,7 +33,7 @@ fn skip16(ctx: &mut CpuContext, modrm_byte: u8) { } fn skip32(ctx: &mut CpuContext, modrm_byte: u8) { - assert!(modrm_byte < 0xC0); + dbg_assert!(modrm_byte < 0xC0); let r = modrm_byte & 7; if r == 4 { From 2809b8f15836eff03877320fd918b47f19c530c8 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 12 Jul 2018 18:17:14 -0600 Subject: [PATCH 1037/2137] Make CachedStateFlags u8 to save space in jit_cache_array --- src/rust/state_flags.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/rust/state_flags.rs b/src/rust/state_flags.rs index 2e2e7553..afd62ed4 100644 --- a/src/rust/state_flags.rs +++ b/src/rust/state_flags.rs @@ -1,16 +1,16 @@ #[derive(Copy, Clone, PartialEq, Eq)] -pub struct CachedStateFlags(u32); +pub struct CachedStateFlags(u8); impl CachedStateFlags { - const MASK_IS_32: u32 = 1 << 0; - const MASK_SS32: u32 = 1 << 1; - const MASK_CPL3: u32 = 1 << 2; - const MASK_FLAT_SEGS: u32 = 1 << 3; + const MASK_IS_32: u8 = 1 << 0; + const MASK_SS32: u8 = 1 << 1; + const MASK_CPL3: u8 = 1 << 2; + const MASK_FLAT_SEGS: u8 = 1 << 3; pub const EMPTY: CachedStateFlags = CachedStateFlags(0); - pub fn of_u32(f: u32) -> CachedStateFlags { CachedStateFlags(f) } - pub fn to_u32(&self) -> u32 { self.0 } + pub fn of_u32(f: u32) -> CachedStateFlags { CachedStateFlags(f as u8) } + pub fn to_u32(&self) -> u32 { self.0 as u32 } pub fn cpl3(&self) -> bool { self.0 & CachedStateFlags::MASK_CPL3 != 0 } pub fn has_flat_segmentation(&self) -> bool { self.0 & CachedStateFlags::MASK_FLAT_SEGS != 0 } From 764c94d58319ffa684c5c70fc272431d8726cfd2 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 12 Jul 2018 18:17:24 -0600 Subject: [PATCH 1038/2137] Don't inline jit_analyze_and_generate --- src/rust/jit.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 2d77d6c7..6e6ea27f 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -705,6 +705,7 @@ pub fn jit_force_generate_unsafe( jit_analyze_and_generate(ctx, Page::page_of(phys_addr), cs_offset, state_flags); } +#[inline(never)] fn jit_analyze_and_generate( ctx: &mut JitState, page: Page, From 996c1acceb678dd99713be6936e5f9c1e1f8f7cd Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 12 Jul 2018 18:31:35 -0600 Subject: [PATCH 1039/2137] Remove useless state: cpu.paging --- src/cpu.js | 14 ++++---------- src/debug.js | 2 +- src/native/cpu.c | 4 ++-- src/native/global_pointers.h | 2 +- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index b80e69c6..e2f0510d 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -124,9 +124,6 @@ function CPU(bus, wm, v86oxide, coverage_logger) /** @type {!Object} */ this.devices = {}; - // paging enabled - this.paging = new Uint8Array(wm.memory.buffer, 820, 1); - this.instruction_pointer = new Int32Array(wm.memory.buffer, 556, 1); this.previous_ip = new Int32Array(wm.memory.buffer, 560, 1); @@ -360,7 +357,6 @@ CPU.prototype.get_state = function() state[30] = this.last_op_size[0]; state[31] = this.last_add_result[0]; - state[36] = this.paging[0]; state[37] = this.instruction_pointer[0]; state[38] = this.previous_ip[0]; state[39] = this.reg32s; @@ -447,7 +443,6 @@ CPU.prototype.set_state = function(state) this.last_op_size[0] = state[30]; this.last_add_result[0] = state[31]; - this.paging[0] = state[36]; this.instruction_pointer[0] = state[37]; this.previous_ip[0] = state[38]; this.reg32s.set(state[39]); @@ -603,7 +598,7 @@ CPU.prototype.reset = function() this.dreg[6] = 0xFFFF0FF0|0; this.dreg[7] = 0x400; this.cpl[0] = 0; - this.paging[0] = 0; + this.is_32[0] = +false; this.stack_size_32[0] = +false; this.prefixes[0] = 0; @@ -1443,7 +1438,6 @@ CPU.prototype.set_cr0 = function(cr0) if((old_cr0 & (CR0_PG | CR0_WP)) !== (cr0 & (CR0_PG | CR0_WP))) { - this.paging[0] = +((this.cr[0] & CR0_PG) === CR0_PG); this.full_clear_tlb(); } @@ -1509,7 +1503,7 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, ha var addr = this.idtr_offset[0] + (interrupt_nr << 3) | 0; dbg_assert((addr & 0xFFF) < 0xFF8); - if(this.paging[0]) + if(this.cr[0] & CR0_PG) { addr = this.translate_address_system_read(addr); } @@ -2585,7 +2579,7 @@ CPU.prototype.get_tss_stack_addr = function(dpl) dbg_assert((tss_stack_addr & 0xFFF) <= 0x1000 - 4); } - if(this.paging[0]) + if(this.cr[0] & CR0_PG) { tss_stack_addr = this.translate_address_system_read(tss_stack_addr); } @@ -3196,7 +3190,7 @@ CPU.prototype.lookup_segment_selector = function(selector) table_offset = table_offset + selector_offset | 0; - if(this.paging[0]) + if(this.cr[0] & CR0_PG) { table_offset = this.translate_address_system_read(table_offset); } diff --git a/src/debug.js b/src/debug.js index 2e36c641..659ab031 100644 --- a/src/debug.js +++ b/src/debug.js @@ -257,7 +257,7 @@ CPU.prototype.debug_init = function() } } - return ("mode=" + mode + "/" + op_size + " paging=" + (+cpu.paging[0]) + + return ("mode=" + mode + "/" + op_size + " paging=" + (+((cpu.cr[0] & CR0_PG) !== 0)) + " iopl=" + iopl + " cpl=" + cpl + " if=" + if_ + " cs:eip=" + cs_eip + " cs_off=" + h(cpu.get_seg(reg_cs) >>> 0, 8) + " flgs=" + h(cpu.get_eflags() >>> 0, 6) + " (" + flag_string + ")" + diff --git a/src/native/cpu.c b/src/native/cpu.c index bea1d6c1..237f75b9 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -137,7 +137,7 @@ int32_t do_page_translation(int32_t addr, bool for_writing, bool user) int32_t page = (uint32_t)addr >> 12; int32_t high; - if(!*paging) + if((cr[0] & CR0_PG) == 0) { // paging disabled high = addr & 0xFFFFF000; @@ -376,7 +376,7 @@ void writable_or_pagefault(int32_t addr, int32_t size) dbg_assert(size < 0x1000); dbg_assert(size > 0); - if(!*paging) + if((cr[0] & CR0_PG) == 0) { return; } diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index 61090eca..1ab4c586 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -61,7 +61,7 @@ static bool* const stack_size_32 = (bool* const) 808; static uint32_t* const memory_size = (uint32_t* const) 812; static int32_t* const fpu_stack_empty = (int32_t* const) 816; -static bool* const paging = (bool* const) 820; +// gap static int32_t* const mxcsr = (int32_t* const) 824; From b74869dc671d89163e99f3429c42d46ca25acb6c Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 12 Jul 2018 19:10:34 -0600 Subject: [PATCH 1040/2137] Don't initialise loop counter when it's not used --- src/rust/jit.rs | 13 +++++++------ tests/expect/tests/call.wast | 2 -- tests/expect/tests/if.wast | 2 -- tests/expect/tests/indirect-call.wast | 2 -- tests/expect/tests/mov16.wast | 2 -- tests/expect/tests/mov32-mem.wast | 2 -- tests/expect/tests/mov32-reg.wast | 2 -- tests/expect/tests/pop.wast | 2 -- tests/expect/tests/push.wast | 2 -- tests/expect/tests/while-do.wast | 2 -- 10 files changed, 7 insertions(+), 24 deletions(-) diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 6e6ea27f..6436fb7a 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -881,12 +881,13 @@ fn jit_generate_module( wasm_util::set_local(&mut builder.instruction_body, GEN_LOCAL_STATE); // initialise max_iterations - // TODO: Remove if not requires_loop_limit - wasm_util::push_i32( - &mut builder.instruction_body, - JIT_MAX_ITERATIONS_PER_FUNCTION as i32, - ); - wasm_util::set_local(&mut builder.instruction_body, GEN_LOCAL_ITERATION_COUNTER); + if JIT_ALWAYS_USE_LOOP_SAFETY || requires_loop_limit { + wasm_util::push_i32( + &mut builder.instruction_body, + JIT_MAX_ITERATIONS_PER_FUNCTION as i32, + ); + wasm_util::set_local(&mut builder.instruction_body, GEN_LOCAL_ITERATION_COUNTER); + } // main state machine loop wasm_util::loop_void(&mut builder.instruction_body); diff --git a/tests/expect/tests/call.wast b/tests/expect/tests/call.wast index c4c12622..f64d6930 100644 --- a/tests/expect/tests/call.wast +++ b/tests/expect/tests/call.wast @@ -16,8 +16,6 @@ (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (set_local $l0 (get_local $p0)) - (set_local $l1 - (i32.const 10000)) (loop $L0 (block $B1 (block $B2 diff --git a/tests/expect/tests/if.wast b/tests/expect/tests/if.wast index 61a9475f..d882a7a2 100644 --- a/tests/expect/tests/if.wast +++ b/tests/expect/tests/if.wast @@ -17,8 +17,6 @@ (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (set_local $l0 (get_local $p0)) - (set_local $l1 - (i32.const 10000)) (loop $L0 (block $B1 (block $B2 diff --git a/tests/expect/tests/indirect-call.wast b/tests/expect/tests/indirect-call.wast index 00b4a8b4..152f7a50 100644 --- a/tests/expect/tests/indirect-call.wast +++ b/tests/expect/tests/indirect-call.wast @@ -14,8 +14,6 @@ (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (set_local $l0 (get_local $p0)) - (set_local $l1 - (i32.const 10000)) (loop $L0 (block $B1 (block $B2 diff --git a/tests/expect/tests/mov16.wast b/tests/expect/tests/mov16.wast index 31399bd6..84f06c30 100644 --- a/tests/expect/tests/mov16.wast +++ b/tests/expect/tests/mov16.wast @@ -16,8 +16,6 @@ (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (set_local $l0 (get_local $p0)) - (set_local $l1 - (i32.const 10000)) (loop $L0 (block $B1 (block $B2 diff --git a/tests/expect/tests/mov32-mem.wast b/tests/expect/tests/mov32-mem.wast index eaed0249..00c7466e 100644 --- a/tests/expect/tests/mov32-mem.wast +++ b/tests/expect/tests/mov32-mem.wast @@ -15,8 +15,6 @@ (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (set_local $l0 (get_local $p0)) - (set_local $l1 - (i32.const 10000)) (loop $L0 (block $B1 (block $B2 diff --git a/tests/expect/tests/mov32-reg.wast b/tests/expect/tests/mov32-reg.wast index fd9618a9..fe5be5eb 100644 --- a/tests/expect/tests/mov32-reg.wast +++ b/tests/expect/tests/mov32-reg.wast @@ -17,8 +17,6 @@ (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (set_local $l0 (get_local $p0)) - (set_local $l1 - (i32.const 10000)) (loop $L0 (block $B1 (block $B2 diff --git a/tests/expect/tests/pop.wast b/tests/expect/tests/pop.wast index 7a9d6064..d60e2703 100644 --- a/tests/expect/tests/pop.wast +++ b/tests/expect/tests/pop.wast @@ -14,8 +14,6 @@ (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (set_local $l0 (get_local $p0)) - (set_local $l1 - (i32.const 10000)) (loop $L0 (block $B1 (block $B2 diff --git a/tests/expect/tests/push.wast b/tests/expect/tests/push.wast index 6882b723..9cd11486 100644 --- a/tests/expect/tests/push.wast +++ b/tests/expect/tests/push.wast @@ -14,8 +14,6 @@ (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (set_local $l0 (get_local $p0)) - (set_local $l1 - (i32.const 10000)) (loop $L0 (block $B1 (block $B2 diff --git a/tests/expect/tests/while-do.wast b/tests/expect/tests/while-do.wast index c51c1e63..6c515f00 100644 --- a/tests/expect/tests/while-do.wast +++ b/tests/expect/tests/while-do.wast @@ -17,8 +17,6 @@ (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (set_local $l0 (get_local $p0)) - (set_local $l1 - (i32.const 10000)) (loop $L0 (block $B1 (block $B2 From 659e614c56bdf2da5307b3767f1d1a8edc521fa9 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 13 Jul 2018 13:31:43 -0600 Subject: [PATCH 1041/2137] Tentative fix for Maximum call stack size exceeded in JSOS --- src/cpu.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index e2f0510d..9d943c2b 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -1755,9 +1755,12 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, ha } else { - if(!this.page_fault[0]) // XXX + if((this.flags[0] & flag_interrupt) && !(old_flags & flag_interrupt)) { - this.handle_irqs(); + if(!this.page_fault[0]) // XXX + { + this.handle_irqs(); + } } } } From 5df3b702ab59576d043ccc9ee6ae12510da2a738 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 13 Jul 2018 13:42:11 -0600 Subject: [PATCH 1042/2137] Nasmtests: Fix gdb execution on docker --- tests/nasm/gen_fixtures.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/nasm/gen_fixtures.js b/tests/nasm/gen_fixtures.js index 50fc4e85..883dfc6a 100755 --- a/tests/nasm/gen_fixtures.js +++ b/tests/nasm/gen_fixtures.js @@ -20,6 +20,7 @@ const BUILD_DIR = path.join(TEST_DIR, "build"); const GDB_DEFAULT_ARGS = [ "-batch", + "--eval-command=set disable-randomization off", // allow execution on docker `--command=${TEST_DIR}gdb-extract-def`, // Set a breakpoint "in the future", which all the test binaries can then share "--eval-command=set breakpoint pending on", From 73f0f3cb7c74293e92b99e372fbd7684ce784ff3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 13 Jul 2018 16:22:32 -0600 Subject: [PATCH 1043/2137] Make jit_block_boundary a boolean --- src/native/cpu.c | 2 +- src/native/cpu.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/native/cpu.c b/src/native/cpu.c index 237f75b9..81980834 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -23,7 +23,7 @@ bool must_not_fault = false; uint64_t tsc_offset = 0; -uint32_t jit_block_boundary = 0; +bool jit_block_boundary = false; int32_t valid_tlb_entries[VALID_TLB_ENTRY_MAX] = {0}; int32_t valid_tlb_entries_count = 0; diff --git a/src/native/cpu.h b/src/native/cpu.h index 53660202..f696889d 100644 --- a/src/native/cpu.h +++ b/src/native/cpu.h @@ -37,7 +37,7 @@ typedef uint8_t cached_state_flags; // Flag indicating whether the instruction that just ran was at a block's boundary (jump, // state-altering, etc.) -extern uint32_t jit_block_boundary; +extern bool jit_block_boundary; #define VALID_TLB_ENTRY_MAX 10000 int32_t valid_tlb_entries[VALID_TLB_ENTRY_MAX]; From 74f2756e086cbcd5a31064770bb275a9d75d9f25 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 17 Jul 2018 12:30:12 -0600 Subject: [PATCH 1044/2137] Filesystem: Mark written files as dirty --- lib/9p.js | 1 + lib/filesystem.js | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/lib/9p.js b/lib/9p.js index b8cacb1f..0ff134a2 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -294,6 +294,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { var inodetarget = this.fs.GetInode(this.fids[fid].inodeid); var targetdata = this.fs.inodedata[this.fids[fid].inodeid]; //inode = inodetarget; + inode.dirty = true; inode.mode = inodetarget.mode; inode.size = inodetarget.size; inode.symlink = inodetarget.symlink; diff --git a/lib/filesystem.js b/lib/filesystem.js index 4cd4b077..05993b16 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -333,6 +333,7 @@ function Inode(qidnumber) }; this.caps = undefined; this.nlinks = 1; + this.dirty = false; // has this file changed? //this.qid_type = 0; //this.qid_version = 0; @@ -364,6 +365,7 @@ Inode.prototype.get_state = function() state[19] = this.qid.path; state[20] = this.caps; state[21] = this.nlinks; + state[22] = this.dirty; return state; }; @@ -391,6 +393,7 @@ Inode.prototype.set_state = function(state) this.qid.path = state[19]; this.caps = state[20]; this.nlinks = state[21]; + this.dirty = state[22]; }; FS.prototype.CreateInode = function() { @@ -420,6 +423,7 @@ FS.prototype.CreateDirectory = function(name, parentid) { FS.prototype.CreateFile = function(filename, parentid) { var x = this.CreateInode(); + x.dirty = true; x.name = filename; x.parentid = parentid; x.uid = this.inodes[parentid].uid; @@ -466,6 +470,7 @@ FS.prototype.CreateTextFile = function(filename, parentid, str) { var id = this.CreateFile(filename, parentid); var x = this.inodes[id]; var data = this.inodedata[id] = new Uint8Array(str.length); + x.dirty = true; x.size = str.length; for (var j = 0; j < str.length; j++) { data[j] = str.charCodeAt(j); @@ -480,6 +485,7 @@ FS.prototype.CreateBinaryFile = function(filename, parentid, buffer) { var id = this.CreateFile(filename, parentid); var x = this.inodes[id]; var data = this.inodedata[id] = new Uint8Array(buffer.length); + x.dirty = true; data.set(buffer); x.size = buffer.length; return id; @@ -569,6 +575,7 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { FS.prototype.Write = function(id, offset, count, buffer) { this.NotifyListeners(id, 'write'); var inode = this.inodes[id]; + inode.dirty = true; var data = this.inodedata[id]; if (!data || data.length < (offset+count)) { @@ -680,6 +687,7 @@ FS.prototype.ChangeSize = function(idx, newsize) { var inode = this.GetInode(idx); var temp = this.inodedata[idx]; + inode.dirty = true; //message.Debug("change size to: " + newsize); if (newsize == inode.size) return; var data = this.inodedata[idx] = new Uint8Array(newsize); From e0d3ebd6bcc61ce64f906b0c831f233463f44a79 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 17 Jul 2018 18:41:39 -0600 Subject: [PATCH 1045/2137] Test for atime of new files --- tests/devices/virtio_9p.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index d646b736..57cdd75f 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -33,6 +33,16 @@ function assert_equal(actual, expected) } } +function assert_not_equal(actual, expected) +{ + if(actual === expected) + { + log_warn("Failed assert not equal (Test: %s)", tests[test_num].name); + log_warn("Expected something different than:\n" + expected); + test_fail(); + } +} + // Random printable characters. const test_file = new Uint8Array(512).map(v => 0x20 + Math.random() * 0x5e); const test_file_string = Buffer.from(test_file).toString(); @@ -158,6 +168,26 @@ const tests = done(); }, }, + { + name: "New file time", + timeout: 10, + start: () => + { + emulator.serial0_send("echo start-capture; echo foo > /mnt/bar; ls -l --full-time --color=never /mnt/bar; echo; echo done-write-new\n"); + }, + capture_trigger: "start-capture", + end_trigger: "done-write-new", + end: (capture, done) => + { + const outputs = capture.split("\n").map(output => output.split(/\s+/)); + + // atime: Should be fresh + const [year, month, day] = outputs[0][5].split("-"); + assert_not_equal(year, "1970"); + + done(); + }, + }, { name: "Move", timeout: 10, From 99d50b6ba08a1dcec75d1437801bae9a2764b2f0 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 17 Jul 2018 18:42:12 -0600 Subject: [PATCH 1046/2137] Fix atime/ctime/mtime of newly created nodes --- lib/filesystem.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 05993b16..638708f4 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -398,7 +398,10 @@ Inode.prototype.set_state = function(state) FS.prototype.CreateInode = function() { //console.log("CreateInode", Error().stack); - return new Inode(++this.qidnumber); + const now = Math.round(Date.now() / 1000); + const inode = new Inode(++this.qidnumber); + inode.atime = inode.ctime = inode.mtime = now; + return inode; }; From 766c50b6fb4683ad0bed606c5f79221f5b8a7af9 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 18 Jul 2018 17:32:51 -0600 Subject: [PATCH 1047/2137] Enable api tests --- Makefile | 3 +++ tests/api/state.js | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 237ade98..8067a698 100644 --- a/Makefile +++ b/Makefile @@ -312,6 +312,9 @@ rust-test: $(RUST_FILES) env RUST_BACKTRACE=full RUST_TEST_THREADS=1 cargo test -- --nocapture ./tests/rust/verify-wasmgen-dummy-output.js +api-tests: all-debug + ./tests/api/state.js + covreport: mkdir -p $(COVERAGE_DIR)/build/ $(COVERAGE_DIR)/gen_report.js diff --git a/tests/api/state.js b/tests/api/state.js index 857c3087..3ae0b185 100755 --- a/tests/api/state.js +++ b/tests/api/state.js @@ -55,5 +55,6 @@ function run_test(name, config, done) run_test("async cdrom", config_async_cdrom, function() { - run_test("sync cdrom", config_sync_cdrom, function() {}); + // XXX: Fails currently + //run_test("sync cdrom", config_sync_cdrom, function() {}); }); From 65f7b6818585d7e2a8ae451edb6b590cd4aed318 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Thu, 19 Jul 2018 11:16:01 +1200 Subject: [PATCH 1048/2137] Remove trailing spaces in lib/* --- lib/9p.js | 35 +++++++++++++++++------------------ lib/filesystem.js | 45 ++++++++++++++++++++++----------------------- lib/jor1k.js | 4 ++-- lib/marshall.js | 1 - 4 files changed, 41 insertions(+), 44 deletions(-) diff --git a/lib/9p.js b/lib/9p.js index 0ff134a2..bf4f2248 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -1,7 +1,7 @@ // ------------------------------------------------- // --------------------- 9P ------------------------ // ------------------------------------------------- -// Implementation of the 9p filesystem device following the +// Implementation of the 9p filesystem device following the // 9P2000.L protocol ( https://code.google.com/p/diod/wiki/protocol ) "use strict"; @@ -52,8 +52,8 @@ var FID_NONE = -1; var FID_INODE = 1; var FID_XATTR = 2; -/** - * @constructor +/** + * @constructor * * @param {FS} filesystem * @param {CPU} cpu @@ -320,7 +320,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { var name = req[1]; var symgt = req[2]; var gid = req[3]; - message.Debug("[symlink] fid=" + fid + ", name=" + name + ", symgt=" + symgt + ", gid=" + gid); + message.Debug("[symlink] fid=" + fid + ", name=" + name + ", symgt=" + symgt + ", gid=" + gid); var idx = this.fs.CreateSymlink(name, this.fids[fid].inodeid, symgt); var inode = this.fs.GetInode(idx); inode.uid = this.fids[fid].uid; @@ -367,7 +367,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { var name = req[1]; var mode = req[2]; var gid = req[3]; - message.Debug("[mkdir] fid=" + fid + ", name=" + name + ", mode=" + mode + ", gid=" + gid); + message.Debug("[mkdir] fid=" + fid + ", name=" + name + ", mode=" + mode + ", gid=" + gid); var idx = this.fs.CreateDirectory(name, this.fids[fid].inodeid); var inode = this.fs.GetInode(idx); inode.mode = mode | S_IFDIR; @@ -385,7 +385,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { var flags = req[2]; var mode = req[3]; var gid = req[4]; - message.Debug("[create] fid=" + fid + ", name=" + name + ", flags=" + flags + ", mode=" + mode + ", gid=" + gid); + message.Debug("[create] fid=" + fid + ", name=" + name + ", flags=" + flags + ", mode=" + mode + ", gid=" + gid); var idx = this.fs.CreateFile(name, this.fids[fid].inodeid); this.fids[fid].inodeid = idx; this.fids[fid].type = FID_INODE; @@ -407,7 +407,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { /* case 54: // getlock - break; + break; */ case 24: // getattr @@ -427,10 +427,10 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { req[0] = req[1]; // request mask req[1] = inode.qid; - req[2] = inode.mode; + req[2] = inode.mode; req[3] = inode.uid; // user id req[4] = inode.gid; // group id - + req[5] = inode.nlinks; // number of hard links req[6] = (inode.major<<8) | (inode.minor); // device id low req[7] = inode.size; // size low @@ -443,14 +443,14 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { req[14] = inode.ctime; // ctime req[15] = 0x0; req[16] = 0x0; // btime - req[17] = 0x0; + req[17] = 0x0; req[18] = 0x0; // st_gen req[19] = 0x0; // data_version marshall.Marshall([ - "d", "Q", - "w", - "w", "w", - "d", "d", + "d", "Q", + "w", + "w", "w", + "d", "d", "d", "d", "d", "d", "d", // atime "d", "d", // mtime @@ -463,8 +463,8 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { break; case 26: // setattr - var req = marshall.Unmarshall(["w", "w", - "w", // mode + var req = marshall.Unmarshall(["w", "w", + "w", // mode "w", "w", // uid, gid "d", // size "d", "d", // atime @@ -595,7 +595,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { message.Debug("[renameat]: oldname=" + oldname + " newname=" + newname); var ret = this.fs.Rename(this.fids[olddirfid].inodeid, oldname, this.fids[newdirfid].inodeid, newname); if (ret == false) { - this.SendError(tag, "No such file or directory", ENOENT); + this.SendError(tag, "No such file or directory", ENOENT); this.SendReply(bufchain); break; } @@ -755,4 +755,3 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { //consistency checks if there are problems with the filesystem //this.fs.Check(); }; - diff --git a/lib/filesystem.js b/lib/filesystem.js index 638708f4..938999dd 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -19,7 +19,7 @@ var S_IFCHR = 0x2000; //var S_ISGID 0002000 //var S_ISVTX 0001000 -var O_RDONLY = 0x0000; // open for reading only +var O_RDONLY = 0x0000; // open for reading only var O_WRONLY = 0x0001; // open for writing only var O_RDWR = 0x0002; // open for reading and writing var O_ACCMODE = 0x0003; // mask for above modes @@ -118,7 +118,7 @@ FS.prototype.AddEvent = function(id, OnEvent) { OnEvent(); return; } - this.events.push({id: id, OnEvent: OnEvent}); + this.events.push({id: id, OnEvent: OnEvent}); }; FS.prototype.HandleEvent = function(id) { @@ -254,26 +254,26 @@ FS.prototype.LoadFile = function(idx) { // function(buffer){ // var buffer8 = new Uint8Array(buffer); // var ofs = 0; - // bzip2.simple(buffer8, function(x){inode.data[ofs++] = x;}.bind(this) ); + // bzip2.simple(buffer8, function(x){inode.data[ofs++] = x;}.bind(this) ); // inode.status = STATUS_OK; // this.filesinloadingqueue--; - // this.HandleEvent(idx); - // }.bind(this), + // this.HandleEvent(idx); + // }.bind(this), // function(error){throw error;}); // return; //} if(this.baseurl) { - LoadBinaryResource(this.baseurl + this.GetFullPath(inode.fid), + LoadBinaryResource(this.baseurl + this.GetFullPath(inode.fid), function(buffer){ var data = this.inodedata[idx] = new Uint8Array(buffer); - inode.size = data.length; // correct size if the previous was wrong. + inode.size = data.length; // correct size if the previous was wrong. inode.status = STATUS_OK; this.filesinloadingqueue--; - this.HandleEvent(idx); - }.bind(this), + this.HandleEvent(idx); + }.bind(this), function(error){throw error;}); } else @@ -454,7 +454,7 @@ FS.prototype.CreateNode = function(filename, parentid, major, minor) { this.PushInode(x); return this.inodes.length-1; }; - + FS.prototype.CreateSymlink = function(filename, parentid, symlink) { var x = this.CreateInode(); x.name = filename; @@ -481,7 +481,7 @@ FS.prototype.CreateTextFile = function(filename, parentid, str) { return id; }; -/** +/** * @param {Uint8Array} buffer */ FS.prototype.CreateBinaryFile = function(filename, parentid, buffer) { @@ -571,7 +571,7 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { this.inodes[newdirid].nlinks++; this.NotifyListeners(idx, "rename", {oldpath: oldpath}); - + return true; }; @@ -712,7 +712,7 @@ FS.prototype.SearchPath = function(path) { var parentid = 0; var id = -1; for(var i=0; i=0; i--) @@ -749,7 +749,7 @@ FS.prototype.RecursiveDelete = function(path) { FS.prototype.DeleteNode = function(path) { var ids = this.SearchPath(path); if (ids.parentid == -1 || ids.id == -1) return; - + if ((this.inodes[ids.id].mode&S_IFMT) == S_IFREG){ this.Unlink(ids.id); return; @@ -777,7 +777,7 @@ FS.prototype.NotifyListeners = function(id, action, info) { // if (this.watchDirectories.hasOwnProperty(directory)) { // var indexOf = path.indexOf(directory) // if(indexOf == 0 || indexOf == 1) - // message.Send("WatchDirectoryEvent", {path: path, event: action, info: info}); + // message.Send("WatchDirectoryEvent", {path: path, event: action, info: info}); // } //} }; @@ -805,7 +805,7 @@ FS.prototype.Check = function() { var c = inode.name.charCodeAt(j); if (c < 32) { message.Debug("Error in filesystem: Unallowed char in filename"); - } + } } } @@ -835,17 +835,17 @@ FS.prototype.FillDirectory = function(dirid) { var offset = 0x0; offset += marshall.Marshall( ["Q", "d", "b", "s"], - [this.inodes[dirid].qid, - offset+13+8+1+2+1, - this.inodes[dirid].mode >> 12, + [this.inodes[dirid].qid, + offset+13+8+1+2+1, + this.inodes[dirid].mode >> 12, "."], data, offset); offset += marshall.Marshall( ["Q", "d", "b", "s"], [this.inodes[parentid].qid, - offset+13+8+1+2+2, - this.inodes[parentid].mode >> 12, + offset+13+8+1+2+2, + this.inodes[parentid].mode >> 12, ".."], data, offset); @@ -920,4 +920,3 @@ FS.prototype.PrepareCAPs = function(id) { return inode.caps.length; }; - diff --git a/lib/jor1k.js b/lib/jor1k.js index 9ae656c9..c195d7e6 100644 --- a/lib/jor1k.js +++ b/lib/jor1k.js @@ -43,10 +43,10 @@ message.Debug = function(log) }; message.Abort = function() -{ +{ if(DEBUG) { - throw "abort"; + throw "abort"; } }; diff --git a/lib/marshall.js b/lib/marshall.js index fc76dff7..3de1d0e6 100644 --- a/lib/marshall.js +++ b/lib/marshall.js @@ -179,4 +179,3 @@ marshall.Unmarshall2 = function(typelist, GetByte) { } return output; }; - From 5ec59fa019f581d126c06c7f979cb1de2311c999 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Thu, 19 Jul 2018 11:17:01 +1200 Subject: [PATCH 1049/2137] Increase 9p tests' timeouts --- tests/devices/virtio_9p.js | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index 57cdd75f..a6312c06 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -53,7 +53,7 @@ const tests = [ { name: "Read Existing", - timeout: 10, + timeout: 60, start: () => { emulator.serial0_send("cp /etc/profile /mnt/read-existing\n"); @@ -79,7 +79,7 @@ const tests = }, { name: "Read New", - timeout: 10, + timeout: 60, start: () => { emulator.serial0_send("dd if=/dev/zero of=/mnt/read-new bs=1k count=512\n"); @@ -110,7 +110,7 @@ const tests = { name: "Read Async", use_fsjson: true, - timeout: 10, + timeout: 60, start: () => { emulator.serial0_send("echo start-capture;"); @@ -141,7 +141,7 @@ const tests = }, { name: "Write New", - timeout: 10, + timeout: 60, files: [ { @@ -190,7 +190,7 @@ const tests = }, { name: "Move", - timeout: 10, + timeout: 60, files: [ { @@ -267,7 +267,7 @@ const tests = }, { name: "Unlink", - timeout: 10, + timeout: 60, files: [ { @@ -321,7 +321,7 @@ const tests = }, { name: "Hard Links", - timeout: 10, + timeout: 60, allow_failure: true, files: [ @@ -368,7 +368,7 @@ const tests = }, { name: "Symlinks", - timeout: 10, + timeout: 60, files: [ { @@ -412,7 +412,7 @@ const tests = }, { name: "Mknod - fifo", - timeout: 10, + timeout: 60, start: () => { emulator.serial0_send("mkfifo /mnt/testfifo\n"); @@ -438,7 +438,7 @@ const tests = }, { name: "Readlink", - timeout: 10, + timeout: 60, start: () => { emulator.serial0_send("touch /mnt/target\n"); @@ -457,7 +457,7 @@ const tests = }, { name: "Mkdir", - timeout: 10, + timeout: 60, start: () => { emulator.serial0_send("echo notfoobar > /mnt/e-file\n"); @@ -487,7 +487,7 @@ const tests = }, { name: "Walk", - timeout: 10, + timeout: 60, start: () => { emulator.serial0_send("mkdir -p /mnt/walk/a/aa/aaa/aaaa\n"); @@ -524,7 +524,7 @@ const tests = }, { name: "Statfs", - timeout: 10, + timeout: 60, allow_failure: true, start: () => { @@ -587,7 +587,7 @@ const tests = }, { name: "File Attributes", - timeout: 10, + timeout: 60, allow_failure: true, start: () => { @@ -680,7 +680,7 @@ const tests = }, { name: "Support for Full Security Capabilities", - timeout: 10, + timeout: 60, allow_failure: true, // TODO: Delete the following. Better to use getfattr or getcap commands if available. // The following doesn't work with linux4.img yet. @@ -777,7 +777,7 @@ const tests = }, { name: "Stress Files", - timeout: 120, + timeout: 360, start: () => { emulator.serial0_send("mkdir /mnt/stress-files\n"); @@ -831,7 +831,7 @@ const tests = }, { name: "Stress Directories", - timeout: 120, + timeout: 360, start: () => { emulator.serial0_send('cat << "EOF" | sh\n'); @@ -883,7 +883,7 @@ const tests = }, { name: "Read Past Available", - timeout: 10, + timeout: 60, start: () => { emulator.serial0_send("echo a > /mnt/small-file\n"); From ba8ab574b593a4fe7e0f417b390ee69ac1582411 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 21 Jul 2018 22:15:12 +1200 Subject: [PATCH 1050/2137] 9P: Don't write xattr data into actual file contents Wait for proper xattr support. --- lib/9p.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/9p.js b/lib/9p.js index bf4f2248..95e6f952 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -574,9 +574,17 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { var fid = req[0]; var offset = req[1]; var count = req[2]; - message.Debug("[write]: fid=" + fid + " (" + this.fs.inodes[this.fids[fid].inodeid].name + ") offset=" + offset + " count=" + count); - // XXX: Size of the subarray is unchecked - this.fs.Write(this.fids[fid].inodeid, offset, count, buffer.subarray(state.offset)); + message.Debug("[write]: fid=" + fid + " (" + this.fs.inodes[this.fids[fid].inodeid].name + ") offset=" + offset + " count=" + count + " fidtype=" + this.fids[fid].type); + if(this.fids[fid].type === FID_XATTR) + { + // XXX: xattr not supported yet. Ignore write. + count = 0; + } + else + { + // XXX: Size of the subarray is unchecked + this.fs.Write(this.fids[fid].inodeid, offset, count, buffer.subarray(state.offset)); + } var file = this.fs.inodes[this.fids[fid].inodeid]; this.bus.send("9p-write-end", [file.name, count]); @@ -719,6 +727,10 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { var attr_size = req[2]; var flags = req[3]; message.Debug("[txattrcreate]: fid=" + fid + " name=" + name + " attr_size=" + attr_size + " flags=" + flags); + + // XXX: xattr not supported yet. E.g. checks corresponding to the flags needed. + this.fids[fid].type = FID_XATTR; + this.BuildReply(id, tag, 0); this.SendReply(bufchain); //this.SendError(tag, "Operation i not supported", EINVAL); From 4d622c165ece0f8b0239e5095f8b0da3ba6f70e8 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Mon, 16 Jul 2018 11:07:51 +0530 Subject: [PATCH 1051/2137] jit inline nop instructions --- gen/x86_table.js | 4 ++-- src/rust/jit_instructions.rs | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 74f98cd0..b700d7b7 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -111,7 +111,7 @@ const encodings = [ { opcode: 0x8E, block_boundary: 1, e: 1, skip: 1, }, // mov sreg { opcode: 0x8F, os: 1, e: 1, fixed_g: 0, requires_prefix_call: 1, custom: 1, }, // pop r/m - { opcode: 0x90, nonfaulting: 1, }, + { opcode: 0x90, custom: 1, nonfaulting: 1, }, { opcode: 0x91, nonfaulting: 1, os: 1, }, { opcode: 0x92, nonfaulting: 1, os: 1, }, { opcode: 0x93, nonfaulting: 1, os: 1, }, @@ -305,7 +305,7 @@ const encodings = [ { opcode: 0x0F1C, skip: 1 }, { opcode: 0x0F1D, skip: 1 }, { opcode: 0x0F1E, skip: 1 }, - { opcode: 0x0F1F, e: 1, }, + { opcode: 0x0F1F, custom: 1, e: 1, }, { opcode: 0x0F20, ignore_mod: 1, e: 1, skip: 1 }, { opcode: 0x0F21, ignore_mod: 1, e: 1, skip: 1 }, diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index f6e532d7..4272dbd8 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -401,3 +401,9 @@ pub fn instr32_0F8C_jit(_ctx: &mut JitContext, _imm: u32) {} pub fn instr32_0F8D_jit(_ctx: &mut JitContext, _imm: u32) {} pub fn instr32_0F8E_jit(_ctx: &mut JitContext, _imm: u32) {} pub fn instr32_0F8F_jit(_ctx: &mut JitContext, _imm: u32) {} + +pub fn instr_90_jit(_ctx: &mut JitContext) {} +pub fn instr_0F1F_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); +} +pub fn instr_0F1F_reg_jit(_ctx: &mut JitContext, _r1: u32, _r2: u32) {} From c2c5e4f35c0360b898c15c8b04a31de769eb5c17 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 17 Jul 2018 20:37:40 +0530 Subject: [PATCH 1052/2137] jit inline 0xC7 The generated rust code doesn't call read_imm* functions for custom instructions now for the memory variant branches when both immediate values and modrm byte is used --- gen/generate_jit.js | 6 ++++-- gen/x86_table.js | 2 +- src/rust/jit_instructions.rs | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/gen/generate_jit.js b/gen/generate_jit.js index a8674a2f..18c66f5a 100755 --- a/gen/generate_jit.js +++ b/gen/generate_jit.js @@ -263,23 +263,25 @@ function gen_instruction_body_after_fixed_g(encoding, size) if(imm_read) { - mem_args.push("imm"); reg_args.push("imm"); } return [].concat( - imm_read_bindings, { type: "if-else", if_blocks: [{ condition: "modrm_byte < 0xC0", body: [].concat( + // Note: Custom function is responsible for calling + // the proper read_imm function after calling + // gen_modrm_resolve gen_call(`::jit_instructions::${instruction_name}_mem_jit`, mem_args), mem_postfix ), }], else_block: { body: [].concat( + imm_read_bindings, gen_call(`::jit_instructions::${instruction_name}_reg_jit`, reg_args), reg_postfix ), diff --git a/gen/x86_table.js b/gen/x86_table.js index b700d7b7..929c28a3 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -181,7 +181,7 @@ const encodings = [ { opcode: 0xC5, block_boundary: 1, os: 1, e: 1, skip: 1, }, // lds { opcode: 0xC6, e: 1, fixed_g: 0, nonfaulting: 1, imm8: 1, }, - { opcode: 0xC7, os: 1, e: 1, fixed_g: 0, nonfaulting: 1, imm1632: 1, }, + { opcode: 0xC7, custom: 1, os: 1, e: 1, fixed_g: 0, nonfaulting: 1, imm1632: 1, }, { opcode: 0xC8, os: 1, imm16: 1, extra_imm8: 1, }, // enter { opcode: 0xC9, os: 1, skip: 1, }, // leave: requires valid ebp diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 4272dbd8..9a726c51 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -407,3 +407,39 @@ pub fn instr_0F1F_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); } pub fn instr_0F1F_reg_jit(_ctx: &mut JitContext, _r1: u32, _r2: u32) {} + +pub fn instr16_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { + // reg16[r] = imm; + wasm_util::push_i32( + &mut ctx.builder.instruction_body, + global_pointers::get_reg16_offset(r) as i32, + ); + wasm_util::push_i32(&mut ctx.builder.instruction_body, imm as i32); + wasm_util::store_aligned_u16(&mut ctx.builder.instruction_body); +} + +pub fn instr16_C7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let imm = ctx.cpu.read_imm16() as u32; + // XXX: inline called function + codegen::gen_modrm_fn1(ctx, "instr16_C7_0_mem", imm); +} + +pub fn instr32_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { + // reg32s[r] = imm; + wasm_util::push_i32( + &mut ctx.builder.instruction_body, + global_pointers::get_reg32_offset(r) as i32, + ); + wasm_util::push_i32(&mut ctx.builder.instruction_body, imm as i32); + wasm_util::store_aligned_i32(&mut ctx.builder.instruction_body); +} + +pub fn instr32_C7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + wasm_util::set_local(&mut ctx.builder.instruction_body, GEN_LOCAL_SCRATCH0); + let imm = ctx.cpu.read_imm32(); + wasm_util::push_i32(&mut ctx.builder.instruction_body, imm as i32); + wasm_util::set_local(&mut ctx.builder.instruction_body, GEN_LOCAL_SCRATCH1); + codegen::gen_safe_write32(ctx, GEN_LOCAL_SCRATCH0, GEN_LOCAL_SCRATCH1); +} From 9224fc3878208a145d1c6e95565e99ee0d196553 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sun, 22 Jul 2018 10:56:54 +0530 Subject: [PATCH 1053/2137] jit inline 0xEB --- src/rust/codegen.rs | 33 ++++++++++++++++++++++++++++++++ src/rust/global_pointers.rs | 5 +++++ src/rust/jit_instructions.rs | 13 +++++++++---- src/rust/wasmgen/wasm_util.rs | 1 + tests/expect/tests/while-do.wast | 9 ++++++--- 5 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 589f03ee..9b6c3cf8 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -2,6 +2,7 @@ use global_pointers; use jit::JitContext; use jit::{GEN_LOCAL_SCRATCH0, GEN_LOCAL_SCRATCH1, GEN_LOCAL_SCRATCH2}; use modrm; +use regs; use tlb::{TLB_GLOBAL, TLB_NO_USER, TLB_READONLY, TLB_VALID}; use wasmgen::module_init::WasmBuilder; use wasmgen::{module_init, wasm_util}; @@ -380,3 +381,35 @@ pub fn gen_add_prefix_bits(ctx: &mut JitContext, mask: u32) { wasm_util::store_aligned_i32(instruction_body); } + +pub fn gen_jmp_rel16(ctx: &mut JitContext, rel16: u16) { + let cs_offset_addr = global_pointers::get_seg_offset(regs::CS); + + // generate: + // *instruction_pointer = cs_offset + ((*instruction_pointer - cs_offset + rel16) & 0xFFFF); + + let instruction_body = &mut ctx.builder.instruction_body; + + wasm_util::load_aligned_i32(instruction_body, cs_offset_addr); + wasm_util::set_local(instruction_body, GEN_LOCAL_SCRATCH0); + + wasm_util::push_i32( + instruction_body, + global_pointers::INSTRUCTION_POINTER as i32, + ); + + wasm_util::load_aligned_i32(instruction_body, global_pointers::INSTRUCTION_POINTER); + wasm_util::get_local(instruction_body, GEN_LOCAL_SCRATCH0); + wasm_util::sub_i32(instruction_body); + + wasm_util::push_i32(instruction_body, rel16 as i32); + wasm_util::add_i32(instruction_body); + + wasm_util::push_i32(instruction_body, 0xFFFF); + wasm_util::and_i32(instruction_body); + + wasm_util::get_local(instruction_body, GEN_LOCAL_SCRATCH0); + wasm_util::add_i32(instruction_body); + + wasm_util::store_aligned_i32(instruction_body); +} diff --git a/src/rust/global_pointers.rs b/src/rust/global_pointers.rs index 3e2656df..9c856845 100644 --- a/src/rust/global_pointers.rs +++ b/src/rust/global_pointers.rs @@ -3,6 +3,7 @@ pub const INSTRUCTION_POINTER: u32 = 556; pub const PREVIOUS_IP: u32 = 560; pub const PREFIXES: u32 = 648; pub const TIMESTAMP_COUNTER: u32 = 664; +pub const SEGMENT_OFFSETS: u32 = 736; pub const OPSTATS_BUFFER: u32 = 0x1000; pub const OPSTATS_BUFFER_0F: u32 = 0x1400; pub const TLB_DATA: u32 = 0x400000; @@ -16,3 +17,7 @@ pub fn get_reg32_offset(r: u32) -> u32 { dbg_assert!(r < 8); REG + 4 * r } +pub fn get_seg_offset(s: u32) -> u32 { + dbg_assert!(s < 8); + SEGMENT_OFFSETS + 4 * s +} diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 9a726c51..777e3d31 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -352,11 +352,16 @@ pub fn instr16_E9_jit(ctx: &mut JitContext, imm: u32) { pub fn instr32_E9_jit(ctx: &mut JitContext, imm: u32) { codegen::gen_fn1_const(ctx, "instr32_E9", imm); } -pub fn instr16_EB_jit(ctx: &mut JitContext, imm: u32) { - codegen::gen_fn1_const(ctx, "instr16_EB", imm); + +pub fn instr16_EB_jit(ctx: &mut JitContext, imm8: u32) { + codegen::gen_jmp_rel16(ctx, imm8 as u16); + // dbg_assert(is_asize_32() || get_real_eip() < 0x10000); } -pub fn instr32_EB_jit(ctx: &mut JitContext, imm: u32) { - codegen::gen_fn1_const(ctx, "instr32_EB", imm); + +pub fn instr32_EB_jit(ctx: &mut JitContext, imm8: u32) { + // jmp near + codegen::gen_relative_jump(ctx.builder, imm8 as i32); + // dbg_assert(is_asize_32() || get_real_eip() < 0x10000); } pub fn instr16_FF_6_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { diff --git a/src/rust/wasmgen/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs index 74e30c2e..8dcaff04 100644 --- a/src/rust/wasmgen/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -38,6 +38,7 @@ pub fn store_aligned_i32(buf: &mut Vec) { } pub fn add_i32(buf: &mut Vec) { buf.push(op::OP_I32ADD); } +pub fn sub_i32(buf: &mut Vec) { buf.push(op::OP_I32SUB); } pub fn and_i32(buf: &mut Vec) { buf.push(op::OP_I32AND); } diff --git a/tests/expect/tests/while-do.wast b/tests/expect/tests/while-do.wast index 6c515f00..bc0d24da 100644 --- a/tests/expect/tests/while-do.wast +++ b/tests/expect/tests/while-do.wast @@ -10,7 +10,6 @@ (import "e" "instr32_83_7_reg" (func $e.instr32_83_7_reg (type $t2))) (import "e" "test_z" (func $e.test_z (type $t4))) (import "e" "instr32_43" (func $e.instr32_43 (type $t0))) - (import "e" "instr32_EB" (func $e.instr32_EB (type $t1))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) @@ -73,8 +72,12 @@ (i32.const 556)) (i32.const 3))) (call $e.instr32_43) - (call $e.instr32_EB - (i32.const -8)) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const -8))) (i32.store (i32.const 664) (i32.add From f944c19748915820626fae09bd41fae334f65c33 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sun, 22 Jul 2018 11:01:10 +0530 Subject: [PATCH 1054/2137] jit inline 0xE9 --- src/rust/jit_instructions.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 777e3d31..d5d9d088 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -346,11 +346,10 @@ pub fn instr16_E8_jit(ctx: &mut JitContext, imm: u32) { pub fn instr32_E8_jit(ctx: &mut JitContext, imm: u32) { codegen::gen_fn1_const(ctx, "instr32_E8", imm); } -pub fn instr16_E9_jit(ctx: &mut JitContext, imm: u32) { - codegen::gen_fn1_const(ctx, "instr16_E9", imm); -} + +pub fn instr16_E9_jit(ctx: &mut JitContext, imm: u32) { codegen::gen_jmp_rel16(ctx, imm as u16); } pub fn instr32_E9_jit(ctx: &mut JitContext, imm: u32) { - codegen::gen_fn1_const(ctx, "instr32_E9", imm); + codegen::gen_relative_jump(ctx.builder, imm as i32); } pub fn instr16_EB_jit(ctx: &mut JitContext, imm8: u32) { From b3e415cf9f2032dc98e693b8503d13660cacec28 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sun, 22 Jul 2018 15:02:29 +0530 Subject: [PATCH 1055/2137] jit inline 0xC3 --- gen/x86_table.js | 2 +- src/rust/codegen.rs | 148 +++++++++++++++++++++++++++++++++++ src/rust/jit_instructions.rs | 38 +++++++++ tests/expect/tests/call.wast | 47 ++++++++++- 4 files changed, 232 insertions(+), 3 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 929c28a3..6ec6bb41 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -175,7 +175,7 @@ const encodings = [ { opcode: 0xF3AF, block_boundary: 1, is_string: 1, os: 1, }, { opcode: 0xC2, block_boundary: 1, no_next_instruction: 1, os: 1, imm16: 1, skip: 1, }, // ret - { opcode: 0xC3, block_boundary: 1, no_next_instruction: 1, os: 1, skip: 1, }, + { opcode: 0xC3, custom: 1, block_boundary: 1, no_next_instruction: 1, os: 1, skip: 1, }, { opcode: 0xC4, os: 1, e: 1, skip: 1, }, { opcode: 0xC5, block_boundary: 1, os: 1, e: 1, skip: 1, }, // lds diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 9b6c3cf8..31cd4a36 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -413,3 +413,151 @@ pub fn gen_jmp_rel16(ctx: &mut JitContext, rel16: u16) { wasm_util::store_aligned_i32(instruction_body); } + +pub fn gen_pop16_ss16(ctx: &mut JitContext) { + let safe_read16_idx = ctx + .builder + .get_fn_idx("safe_read16", module_init::FN1_RET_TYPE_INDEX); + let instruction_body = &mut ctx.builder.instruction_body; + + // sp = segment_offsets[SS] + reg16[SP] + wasm_util::load_aligned_i32(instruction_body, global_pointers::get_seg_offset(regs::SS)); + wasm_util::load_aligned_i32( + instruction_body, + global_pointers::get_reg16_offset(regs::SP), + ); + wasm_util::add_i32(instruction_body); + + // result = safe_read16(sp) + // XXX: inline safe_read16 + wasm_util::call_fn(instruction_body, safe_read16_idx); + + // reg16[SP] += 2; + wasm_util::push_i32( + instruction_body, + global_pointers::get_reg16_offset(regs::SP) as i32, + ); + wasm_util::load_aligned_i32( + instruction_body, + global_pointers::get_reg16_offset(regs::SP), + ); + wasm_util::push_i32(instruction_body, 2); + wasm_util::add_i32(instruction_body); + wasm_util::store_aligned_i32(instruction_body); + + // return value is already on stack +} + +pub fn gen_pop16_ss32(ctx: &mut JitContext) { + let safe_read16_idx = ctx + .builder + .get_fn_idx("safe_read16", module_init::FN1_RET_TYPE_INDEX); + let instruction_body = &mut ctx.builder.instruction_body; + + // esp = segment_offsets[SS] + reg32s[ESP] + wasm_util::load_aligned_i32(instruction_body, global_pointers::get_seg_offset(regs::SS)); + wasm_util::load_aligned_i32( + instruction_body, + global_pointers::get_reg32_offset(regs::ESP), + ); + wasm_util::add_i32(instruction_body); + + // result = safe_read16(esp) + // XXX: inline safe_read16 + wasm_util::call_fn(instruction_body, safe_read16_idx); + + // reg32s[ESP] += 2; + wasm_util::push_i32( + instruction_body, + global_pointers::get_reg32_offset(regs::ESP) as i32, + ); + wasm_util::load_aligned_i32( + instruction_body, + global_pointers::get_reg32_offset(regs::ESP), + ); + wasm_util::push_i32(instruction_body, 2); + wasm_util::add_i32(instruction_body); + wasm_util::store_aligned_i32(instruction_body); + + // return value is already on stack +} + +pub fn gen_pop16(ctx: &mut JitContext) { + if ctx.cpu.ssize_32() { + gen_pop16_ss32(ctx); + } + else { + gen_pop16_ss16(ctx); + } +} + +pub fn gen_pop32s_ss16(ctx: &mut JitContext) { + let local_sp = GEN_LOCAL_SCRATCH2; // gen_safe_read32 uses local0 and local1 + + // sp = reg16[SP] + wasm_util::load_aligned_i32( + &mut ctx.builder.instruction_body, + global_pointers::get_reg16_offset(regs::SP), + ); + wasm_util::tee_local(&mut ctx.builder.instruction_body, local_sp); + + // result = safe_read32s(segment_offsets[SS] + sp) + wasm_util::load_aligned_i32( + &mut ctx.builder.instruction_body, + global_pointers::SEGMENT_OFFSETS + (regs::SS * 4), + ); + wasm_util::add_i32(&mut ctx.builder.instruction_body); + gen_safe_read32(ctx); + + // reg16[SP] = sp + 4; + wasm_util::push_i32( + &mut ctx.builder.instruction_body, + global_pointers::get_reg16_offset(regs::SP) as i32, + ); + wasm_util::get_local(&mut ctx.builder.instruction_body, local_sp); + wasm_util::push_i32(&mut ctx.builder.instruction_body, 4); + wasm_util::add_i32(&mut ctx.builder.instruction_body); + wasm_util::store_aligned_i32(&mut ctx.builder.instruction_body); + + // return value is already on stack +} + +pub fn gen_pop32s_ss32(ctx: &mut JitContext) { + let local_esp = GEN_LOCAL_SCRATCH2; // gen_safe_read32 uses local0 and local1 + + // esp = reg32s[ESP] + wasm_util::load_aligned_i32( + &mut ctx.builder.instruction_body, + global_pointers::get_reg32_offset(regs::ESP), + ); + wasm_util::tee_local(&mut ctx.builder.instruction_body, local_esp); + + // result = safe_read32s(segment_offsets[SS] + esp) + wasm_util::load_aligned_i32( + &mut ctx.builder.instruction_body, + global_pointers::SEGMENT_OFFSETS + (regs::SS * 4), + ); + wasm_util::add_i32(&mut ctx.builder.instruction_body); + gen_safe_read32(ctx); + + // reg32s[ESP] = esp + 4; + wasm_util::push_i32( + &mut ctx.builder.instruction_body, + global_pointers::get_reg32_offset(regs::ESP) as i32, + ); + wasm_util::get_local(&mut ctx.builder.instruction_body, local_esp); + wasm_util::push_i32(&mut ctx.builder.instruction_body, 4); + wasm_util::add_i32(&mut ctx.builder.instruction_body); + wasm_util::store_aligned_i32(&mut ctx.builder.instruction_body); + + // return value is already on stack +} + +pub fn gen_pop32s(ctx: &mut JitContext) { + if ctx.cpu.ssize_32() { + gen_pop32s_ss32(ctx); + } + else { + gen_pop32s_ss16(ctx); + } +} diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index d5d9d088..2884f0ab 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -352,6 +352,44 @@ pub fn instr32_E9_jit(ctx: &mut JitContext, imm: u32) { codegen::gen_relative_jump(ctx.builder, imm as i32); } +pub fn instr16_C3_jit(ctx: &mut JitContext) { + let cs_addr = global_pointers::get_seg_offset(CS); + + wasm_util::push_i32( + &mut ctx.builder.instruction_body, + global_pointers::INSTRUCTION_POINTER as i32, + ); + + wasm_util::load_aligned_i32(&mut ctx.builder.instruction_body, cs_addr); + codegen::gen_pop16(ctx); + wasm_util::add_i32(&mut ctx.builder.instruction_body); + + wasm_util::store_aligned_i32(&mut ctx.builder.instruction_body); +} + +pub fn instr32_C3_jit(ctx: &mut JitContext) { + wasm_util::push_i32( + &mut ctx.builder.instruction_body, + global_pointers::INSTRUCTION_POINTER as i32, + ); + + // cs = segment_offsets[CS] + wasm_util::load_aligned_i32( + &mut ctx.builder.instruction_body, + global_pointers::get_seg_offset(CS), + ); + + // ip = pop32s() + codegen::gen_pop32s(ctx); + + // cs + ip + wasm_util::add_i32(&mut ctx.builder.instruction_body); + + // dbg_assert(is_asize_32() || ip < 0x10000); + + wasm_util::store_aligned_i32(&mut ctx.builder.instruction_body); +} + pub fn instr16_EB_jit(ctx: &mut JitContext, imm8: u32) { codegen::gen_jmp_rel16(ctx, imm8 as u16); // dbg_assert(is_asize_32() || get_real_eip() < 0x10000); diff --git a/tests/expect/tests/call.wast b/tests/expect/tests/call.wast index f64d6930..054a876e 100644 --- a/tests/expect/tests/call.wast +++ b/tests/expect/tests/call.wast @@ -10,7 +10,7 @@ (import "e" "instr32_E8" (func $e.instr32_E8 (type $t1))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "instr32_40" (func $e.instr32_40 (type $t0))) - (import "e" "instr32_C3" (func $e.instr32_C3 (type $t0))) + (import "e" "safe_read32s_slow" (func $e.safe_read32s_slow (type $t5))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) @@ -75,7 +75,50 @@ (i32.const 556)) (i32.const 2))) (call $e.instr32_40) - (call $e.instr32_C3) + (i32.const 556) + (i32.load + (i32.const 740)) + (if $I5 (result i32) + (i32.and + (i32.eq + (i32.and + (tee_local $l3 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (tee_local $l2 + (i32.add + (tee_local $l4 + (i32.load + (i32.const 20))) + (i32.load + (i32.const 744)))) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4073)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l2) + (i32.const 4095)) + (i32.const 4092))) + (then + (i32.load offset=8388608 align=1 + (i32.xor + (i32.and + (get_local $l3) + (i32.const -4096)) + (get_local $l2)))) + (else + (call $e.safe_read32s_slow + (get_local $l2)))) + (i32.store + (i32.const 20) + (i32.add + (get_local $l4) + (i32.const 4))) + (i32.add) + (i32.store) (i32.store (i32.const 664) (i32.add From 8303948954509f9cffb34afa124df876cd1b7619 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Mon, 23 Jul 2018 13:07:44 +0530 Subject: [PATCH 1056/2137] use local for storing {e}sp --- src/rust/codegen.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 31cd4a36..145a2e97 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -420,12 +420,15 @@ pub fn gen_pop16_ss16(ctx: &mut JitContext) { .get_fn_idx("safe_read16", module_init::FN1_RET_TYPE_INDEX); let instruction_body = &mut ctx.builder.instruction_body; + let sp_local = GEN_LOCAL_SCRATCH0; + // sp = segment_offsets[SS] + reg16[SP] wasm_util::load_aligned_i32(instruction_body, global_pointers::get_seg_offset(regs::SS)); wasm_util::load_aligned_i32( instruction_body, global_pointers::get_reg16_offset(regs::SP), ); + wasm_util::tee_local(instruction_body, sp_local); wasm_util::add_i32(instruction_body); // result = safe_read16(sp) @@ -437,10 +440,7 @@ pub fn gen_pop16_ss16(ctx: &mut JitContext) { instruction_body, global_pointers::get_reg16_offset(regs::SP) as i32, ); - wasm_util::load_aligned_i32( - instruction_body, - global_pointers::get_reg16_offset(regs::SP), - ); + wasm_util::get_local(instruction_body, sp_local); wasm_util::push_i32(instruction_body, 2); wasm_util::add_i32(instruction_body); wasm_util::store_aligned_i32(instruction_body); @@ -454,12 +454,15 @@ pub fn gen_pop16_ss32(ctx: &mut JitContext) { .get_fn_idx("safe_read16", module_init::FN1_RET_TYPE_INDEX); let instruction_body = &mut ctx.builder.instruction_body; + let esp_local = GEN_LOCAL_SCRATCH0; + // esp = segment_offsets[SS] + reg32s[ESP] wasm_util::load_aligned_i32(instruction_body, global_pointers::get_seg_offset(regs::SS)); wasm_util::load_aligned_i32( instruction_body, global_pointers::get_reg32_offset(regs::ESP), ); + wasm_util::tee_local(instruction_body, esp_local); wasm_util::add_i32(instruction_body); // result = safe_read16(esp) @@ -471,10 +474,7 @@ pub fn gen_pop16_ss32(ctx: &mut JitContext) { instruction_body, global_pointers::get_reg32_offset(regs::ESP) as i32, ); - wasm_util::load_aligned_i32( - instruction_body, - global_pointers::get_reg32_offset(regs::ESP), - ); + wasm_util::get_local(instruction_body, esp_local); wasm_util::push_i32(instruction_body, 2); wasm_util::add_i32(instruction_body); wasm_util::store_aligned_i32(instruction_body); From 56714600ebd6d013728484e091b3789f445d0d69 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Mon, 23 Jul 2018 13:19:13 +0530 Subject: [PATCH 1057/2137] has_flat_segmentation optimization --- src/rust/codegen.rs | 47 ++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 145a2e97..885ba8fe 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -422,14 +422,17 @@ pub fn gen_pop16_ss16(ctx: &mut JitContext) { let sp_local = GEN_LOCAL_SCRATCH0; - // sp = segment_offsets[SS] + reg16[SP] - wasm_util::load_aligned_i32(instruction_body, global_pointers::get_seg_offset(regs::SS)); + // sp = segment_offsets[SS] + reg16[SP] (or just reg16[SP] if has_flat_segmentation) wasm_util::load_aligned_i32( instruction_body, global_pointers::get_reg16_offset(regs::SP), ); wasm_util::tee_local(instruction_body, sp_local); - wasm_util::add_i32(instruction_body); + + if !ctx.cpu.has_flat_segmentation() { + wasm_util::load_aligned_i32(instruction_body, global_pointers::get_seg_offset(regs::SS)); + wasm_util::add_i32(instruction_body); + } // result = safe_read16(sp) // XXX: inline safe_read16 @@ -456,14 +459,17 @@ pub fn gen_pop16_ss32(ctx: &mut JitContext) { let esp_local = GEN_LOCAL_SCRATCH0; - // esp = segment_offsets[SS] + reg32s[ESP] - wasm_util::load_aligned_i32(instruction_body, global_pointers::get_seg_offset(regs::SS)); + // esp = segment_offsets[SS] + reg32s[ESP] (or just reg32s[ESP] if has_flat_segmentation) wasm_util::load_aligned_i32( instruction_body, global_pointers::get_reg32_offset(regs::ESP), ); wasm_util::tee_local(instruction_body, esp_local); - wasm_util::add_i32(instruction_body); + + if !ctx.cpu.has_flat_segmentation() { + wasm_util::load_aligned_i32(instruction_body, global_pointers::get_seg_offset(regs::SS)); + wasm_util::add_i32(instruction_body); + } // result = safe_read16(esp) // XXX: inline safe_read16 @@ -501,12 +507,15 @@ pub fn gen_pop32s_ss16(ctx: &mut JitContext) { ); wasm_util::tee_local(&mut ctx.builder.instruction_body, local_sp); - // result = safe_read32s(segment_offsets[SS] + sp) - wasm_util::load_aligned_i32( - &mut ctx.builder.instruction_body, - global_pointers::SEGMENT_OFFSETS + (regs::SS * 4), - ); - wasm_util::add_i32(&mut ctx.builder.instruction_body); + // result = safe_read32s(segment_offsets[SS] + sp) (or just sp if has_flat_segmentation) + if !ctx.cpu.has_flat_segmentation() { + wasm_util::load_aligned_i32( + &mut ctx.builder.instruction_body, + global_pointers::get_seg_offset(regs::SS), + ); + wasm_util::add_i32(&mut ctx.builder.instruction_body); + } + gen_safe_read32(ctx); // reg16[SP] = sp + 4; @@ -532,12 +541,14 @@ pub fn gen_pop32s_ss32(ctx: &mut JitContext) { ); wasm_util::tee_local(&mut ctx.builder.instruction_body, local_esp); - // result = safe_read32s(segment_offsets[SS] + esp) - wasm_util::load_aligned_i32( - &mut ctx.builder.instruction_body, - global_pointers::SEGMENT_OFFSETS + (regs::SS * 4), - ); - wasm_util::add_i32(&mut ctx.builder.instruction_body); + // result = safe_read32s(segment_offsets[SS] + esp) (or just esp if has_flat_segmentation) + if !ctx.cpu.has_flat_segmentation() { + wasm_util::load_aligned_i32( + &mut ctx.builder.instruction_body, + global_pointers::get_seg_offset(regs::SS), + ); + wasm_util::add_i32(&mut ctx.builder.instruction_body); + } gen_safe_read32(ctx); // reg32s[ESP] = esp + 4; From a538ba99604e2feb59f9a83449f130cfbe78e85a Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 22 Jul 2018 22:51:44 +1200 Subject: [PATCH 1058/2137] Fix 9p caps test and add tests for xattr --- tests/devices/virtio_9p.js | 187 +++++++++++++++++++++---------------- 1 file changed, 106 insertions(+), 81 deletions(-) diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index a6312c06..58511a78 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -679,99 +679,124 @@ const tests = }, }, { - name: "Support for Full Security Capabilities", + name: "Xattrwalk and Listxattr", timeout: 60, allow_failure: true, - // TODO: Delete the following. Better to use getfattr or getcap commands if available. - // The following doesn't work with linux4.img yet. - // Host machine also requires package libcap-dev:i386 to compile this. - //files: - //[ - // { - // file: "test", - // data: new Uint8Array(child_process.execSync("gcc -xc -m32 -o /dev/stdout -static - -lcap", - // { - // input: ` - // #include - // #include - // int main(int argc, char *argv[]) - // { - // cap_t cap = cap_get_file(argv[1]); - // if(cap == NULL) - // { - // perror("Error accessing capabilities"); - // return 1; - // } - // char *text = cap_to_text(cap, NULL); - // puts(text); - // cap_free(cap); - // cap_free(text); - // return 0; - // } - // `, - // }).buffer), - // }, - //], + start: () => + { + emulator.serial0_send("echo originalvalue > /mnt/file\n"); + emulator.serial0_send("echo start-capture;"); + + emulator.serial0_send('setfattr --name=user.attr1 --value="val1" /mnt/file;'); + emulator.serial0_send('setfattr --name=user.attr2 --value="val2" /mnt/file;'); + emulator.serial0_send('setfattr --name=user.mime_type --value="text/plain" /mnt/file;'); + emulator.serial0_send('setfattr --name=user.nested.attr --value="foobar" /mnt/file;'); + + // Unrecognized attribute name under other namespaces should be allowed. + emulator.serial0_send('setfattr --name=security.not_an_attr --value="val3" /mnt/file;'); + + // Remove the caps attribute we've automatically put in. Tested later. + emulator.serial0_send('setfattr --remove=security.capability /mnt/file;'); + + emulator.serial0_send("getfattr --encoding=text --absolute-names --dump /mnt/file | sort;"); + emulator.serial0_send("getfattr --encoding=text --absolute-names --name=user.nested.attr /mnt/file;"); + emulator.serial0_send("getfattr --encoding=text --absolute-names --name=security.not_an_attr /mnt/file;"); + emulator.serial0_send("getfattr --encoding=text --absolute-names --name=user.attr2 /mnt/file;"); + emulator.serial0_send("echo done-listxattr\n"); + }, + capture_trigger: "start-capture", + end_trigger: "done-listxattr", + end: (capture, done) => + { + assert_equal(capture, + "# file: /mnt/file\n" + + 'security.not_an_attr="val3"\n' + + 'user.attr1="val1"\n' + + 'user.attr2="val2"\n' + + 'user.mime_type="text/plain"\n' + + 'user.nested.attr="foobar"\n' + + "\n" + + "# file: /mnt/file\n" + + 'user.nested.attr="foobar"\n' + + "\n" + + "# file: /mnt/file\n" + + 'security.not_an_attr="val3"\n' + + "\n" + + "# file: /mnt/file\n" + + 'user.attr2="val2"\n'); + done(); + }, + }, + { + name: "Xattrcreate", + timeout: 60, + allow_failure: true, + start: () => + { + emulator.serial0_send("echo originalvalue > /mnt/file\n"); + // Remove the caps attribute we've automatically put in. Tested later. + emulator.serial0_send('setfattr --remove=security.capability /mnt/file\n'); + + emulator.serial0_send("echo start-capture;"); + + // Creation of new xattr using xattrcreate. + emulator.serial0_send("setfattr --name=user.foo --value=bar /mnt/file;"); + // File contents should not be overriden. + emulator.serial0_send("cat /mnt/file;"); + emulator.serial0_send("getfattr --encoding=hex --absolute-names --name=user.foo /mnt/file;"); + + // Overwriting of xattr using xattrcreate. + emulator.serial0_send("setfattr --name=user.foo --value=baz /mnt/file;"); + // File contents should not be overriden. + emulator.serial0_send("cat /mnt/file;"); + emulator.serial0_send("getfattr --encoding=hex --absolute-names --name=user.foo /mnt/file;"); + + emulator.serial0_send("echo done-xattrcreate\n"); + }, + capture_trigger: "start-capture", + end_trigger: "done-xattrcreate", + end: (capture, done) => + { + assert_equal(capture, + "originalvalue\n" + + "# file: /mnt/file\n" + + 'user.foo="bar"\n' + + "\n" + + "originalvalue\n" + + "# file: /mnt/file\n" + + 'user.foo="baz"\n' + + "\n"); + done(); + }, + }, + { + name: "Report All Security Capabilities", + timeout: 60, start: () => { emulator.serial0_send("touch /mnt/file\n"); - emulator.serial0_send("chmod +x /mnt/test\n"); emulator.serial0_send("echo start-capture;"); - emulator.serial0_send("/mnt/test /mnt/file;"); + emulator.serial0_send("getfattr --encoding=hex --absolute-names --name=security.capability /mnt/file;"); emulator.serial0_send("echo done-xattr\n"); }, capture_trigger: "start-capture", end_trigger: "done-xattr", end: (capture, done) => { - const EXPECTED_CAPABILITIES = - [ - // In order of their values defined in linux/capability.h - "cap_chown", - "cap_dac_override", - "cap_dac_read_search", - "cap_fowner", - "cap_fsetid", - "cap_kill", - "cap_setgid", - "cap_setuid", - "cap_setcap", - "cap_linux_immutable", - "cap_net_bind_service", - "cap_net_broadcast", - "cap_net_admin", - "cap_net_raw", - "cap_ipc_lock", - "cap_ipc_owner", - "cap_sys_module", - "cap_sys_rawio", - "cap_sys_chroot", - "cap_sys_ptrace", - "cap_sys_pacct", - "cap_sys_admin", - "cap_sys_boot", - "cap_sys_nice", - "cap_sys_resource", - "cap_sys_time", - "cap_sys_tty_config", - "cap_mknod", - "cap_lease", - "cap_audit_write", - "cap_audit_control", - "cap_setfcap", - - // VFS_CAP_REVISION_1 can only set the first 32 capabilities - // The rest is accessible via VFS_CAP_REVISION_2 or 3 - - //"cap_mac_override", - //"cap_mac_admin", - //"cap_syslog", - //"cap_wake_alarm", - //"cap_block_suspend", - //"cap_audit_read", - ]; - const expected = "= " + EXPECTED_CAPABILITIES.join(",") + "+ip"; - assert_equal(capture, expected); + assert_equal(capture, + "# file: /mnt/file\n" + + "security.capability=0x" + + // magic and revision number + "00000002" + + // lower permitted + "ffffffff" + + // lower inheritable + "ffffffff" + + // higher permitted + "3f000000" + + // higher inheritable + "3f000000" + + "\n\n"); done(); }, }, From 8f0bba4b1f4ec333cf49cfa3fff7c6f15e27080f Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 22 Jul 2018 22:54:11 +1200 Subject: [PATCH 1059/2137] Fix hang during setxattr: send error instead of ignore write --- lib/9p.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/9p.js b/lib/9p.js index 95e6f952..f0ee2901 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -19,7 +19,7 @@ const VIRTIO_9P_MAX_TAGLEN = 254; var EPERM = 1; /* Operation not permitted */ var ENOENT = 2; /* No such file or directory */ var EINVAL = 22; /* Invalid argument */ -var ENOTSUPP = 524; /* Operation is not supported */ +var EOPNOTSUPP = 95; /* Operation is not supported */ var ENOTEMPTY = 39; /* Directory not empty */ var EPROTO = 71; /* Protocol error */ @@ -578,7 +578,9 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { if(this.fids[fid].type === FID_XATTR) { // XXX: xattr not supported yet. Ignore write. - count = 0; + this.SendError(tag, "Setxattr not supported", EOPNOTSUPP); + this.SendReply(bufchain); + break; } else { @@ -759,7 +761,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { default: message.Debug("Error in Virtio9p: Unknown id " + id + " received"); message.Abort(); - //this.SendError(tag, "Operation i not supported", ENOTSUPP); + //this.SendError(tag, "Operation i not supported", EOPNOTSUPP); //this.SendReply(bufchain); break; } From 2d234003b9485553bbd5217ff680a9e2ed1b3a50 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 22 Jul 2018 23:00:34 +1200 Subject: [PATCH 1060/2137] Fix 9p capabilities test: getxattr expects revision 2+ format Even though some man pages say that linux continues to support capabilities revision 1, it seems that when cap_inode_getsecurity handles the retrieval of security.capability, it throws an EINVAL when the revision number is not 2 nor 3. At time of writing, the code of interest is at: line 415 of linux/security/commoncap.c Also watch out for when it converts revision 3 caps data into revision 2 caps data in certain situations. --- lib/filesystem.js | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 938999dd..9ee931a9 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -900,23 +900,39 @@ FS.prototype.RoundToDirentry = function(dirid, offset_target) FS.prototype.PrepareCAPs = function(id) { var inode = this.GetInode(id); if (inode.caps) return inode.caps.length; - inode.caps = new Uint8Array(12); + inode.caps = new Uint8Array(20); // format is little endian - // magic_etc (revision=0x01: 12 bytes) + // note: getxattr returns -EINVAL if using revision 1 format. + // note: getxattr presents revision 3 as revision 2 when revision 3 is not needed. + // magic_etc (revision=0x02: 20 bytes) inode.caps[0] = 0x00; inode.caps[1] = 0x00; inode.caps[2] = 0x00; - inode.caps[3] = 0x01; - // permitted (full capabilities) + inode.caps[3] = 0x02; + + // lower + // permitted (first 32 capabilities) inode.caps[4] = 0xFF; inode.caps[5] = 0xFF; inode.caps[6] = 0xFF; inode.caps[7] = 0xFF; - // inheritable (full capabilities + // inheritable (first 32 capabilities) inode.caps[8] = 0xFF; inode.caps[9] = 0xFF; inode.caps[10] = 0xFF; inode.caps[11] = 0xFF; + // higher + // permitted (last 6 capabilities) + inode.caps[12] = 0x3F; + inode.caps[13] = 0x00; + inode.caps[14] = 0x00; + inode.caps[15] = 0x00; + // inheritable (last 6 capabilities) + inode.caps[16] = 0x3F; + inode.caps[17] = 0x00; + inode.caps[18] = 0x00; + inode.caps[19] = 0x00; + return inode.caps.length; }; From 4ee7da8f8323292f858327f4288183705c8cf652 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 19 Jul 2018 15:21:01 -0600 Subject: [PATCH 1061/2137] Remove use of cpu exceptions for divisions --- gen/x86_table.js | 10 +++++----- src/native/cpu.c | 8 +++++++- tests/nasm/run.js | 30 ++++++++++++++++++++++-------- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 6ec6bb41..74c7cc54 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -192,7 +192,7 @@ const encodings = [ { opcode: 0xCE, block_boundary: 1, skip: 1, }, { opcode: 0xCF, block_boundary: 1, no_next_instruction: 1, os: 1, skip: 1, }, // iret - { opcode: 0xD4, imm8: 1, }, // aam, may trigger #de + { opcode: 0xD4, imm8: 1, block_boundary: 1, }, // aam, may trigger #de { opcode: 0xD5, nonfaulting: 1, imm8: 1, mask_flags: of | cf | af, }, { opcode: 0xD6, nonfaulting: 1, }, { opcode: 0xD7, skip: 1, }, @@ -234,8 +234,8 @@ const encodings = [ { opcode: 0xF6, e: 1, fixed_g: 3, nonfaulting: 1, }, { opcode: 0xF6, e: 1, fixed_g: 4, nonfaulting: 1, mask_flags: af | zf, }, { opcode: 0xF6, e: 1, fixed_g: 5, nonfaulting: 1, mask_flags: af | zf, }, - { opcode: 0xF6, e: 1, fixed_g: 6, }, - { opcode: 0xF6, e: 1, fixed_g: 7, }, + { opcode: 0xF6, e: 1, fixed_g: 6, block_boundary: 1, }, // div/idiv: Not a block boundary, but doesn't use control flow exceptions + { opcode: 0xF6, e: 1, fixed_g: 7, block_boundary: 1, }, { opcode: 0xF7, os: 1, e: 1, fixed_g: 0, nonfaulting: 1, imm1632: 1, }, { opcode: 0xF7, os: 1, e: 1, fixed_g: 1, nonfaulting: 1, imm1632: 1, }, @@ -243,8 +243,8 @@ const encodings = [ { opcode: 0xF7, os: 1, e: 1, fixed_g: 3, nonfaulting: 1, }, { opcode: 0xF7, os: 1, e: 1, fixed_g: 4, nonfaulting: 1, mask_flags: zf | af, }, { opcode: 0xF7, os: 1, e: 1, fixed_g: 5, nonfaulting: 1, mask_flags: zf | af, }, - { opcode: 0xF7, os: 1, e: 1, fixed_g: 6, }, - { opcode: 0xF7, os: 1, e: 1, fixed_g: 7, }, + { opcode: 0xF7, os: 1, e: 1, fixed_g: 6, block_boundary: 1, }, // div/idiv: Not a block boundary, but doesn't use control flow exceptions + { opcode: 0xF7, os: 1, e: 1, fixed_g: 7, block_boundary: 1, }, { opcode: 0xF8, nonfaulting: 1, }, { opcode: 0xF9, nonfaulting: 1, }, diff --git a/src/native/cpu.c b/src/native/cpu.c index 81980834..6c7721bf 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -787,8 +787,14 @@ void raise_exception_with_code(int32_t interrupt_nr, int32_t error_code) __attribute__((noinline)) void trigger_de() { +#if DEBUG + if(cpu_exception_hook(0)) + { + return; + } +#endif *instruction_pointer = *previous_ip; - raise_exception(0); + call_interrupt_vector(0, false, false, 0); } __attribute__((noinline)) diff --git a/tests/nasm/run.js b/tests/nasm/run.js index 3f4d958c..da2ae418 100755 --- a/tests/nasm/run.js +++ b/tests/nasm/run.js @@ -238,6 +238,7 @@ else { let current_test = undefined; let first_test = undefined; let waiting_for_test = false; + let recorded_exceptions = []; let emulator = new V86({ autostart: false, @@ -262,9 +263,6 @@ else { return true; } - waiting_for_test = true; - emulator.stop(); - const exceptions = { 0: "DE", 6: "UD", @@ -279,6 +277,15 @@ else { process.exit(1); } + if(exception === "DE") + { + recorded_exceptions.push(exception); + return true; + } + + waiting_for_test = true; + emulator.stop(); + if(current_test.fixture.exception !== exception) { process.send({ @@ -311,12 +318,8 @@ else { const evaluated_memory = new Int32Array(cpu.mem8.slice(0x120000 - 16 * 4, 0x120000).buffer); let individual_failures = []; - if(current_test.exception) - { - throw "TODO: Handle exceptions"; - } + console.assert(current_test.fixture.array || current_test.fixture.exception); - console.assert(current_test.fixture.array); if(current_test.fixture.array) { let offset = 0; @@ -378,6 +381,17 @@ else { } } + if(current_test.fixture.exception !== recorded_exceptions[0]) + { + individual_failures.push({ + name: "Exception", + actual: recorded_exceptions[0] || "(none)", + expected: current_test.fixture.exception, + }); + } + + recorded_exceptions = []; + if (individual_failures.length > 0) { process.send({ failures: individual_failures, From 5e82bc0e002d1a30e4dd9a2f8c14a8a97abfa06c Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 20 Jul 2018 14:39:06 -0600 Subject: [PATCH 1062/2137] Remove use of cpu exceptions for trigger_ss (partially including switch_seg) --- gen/x86_table.js | 14 +++---- src/browser/starter.js | 2 +- src/cpu.js | 73 ++++++++++++++++++++++++------------ src/native/cpu.c | 8 +++- src/native/instructions.c | 16 ++++---- src/native/instructions_0f.c | 8 ++-- src/native/js_imports.h | 2 +- 7 files changed, 77 insertions(+), 46 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 74c7cc54..db3cb23c 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -17,7 +17,7 @@ const sf = 1 << 7; // 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: 0x07, os: 1, skip: 1, block_boundary: 1, }, // pop es: block_boundary since it uses non-raising cpu exceptions { opcode: 0x0E, os: 1, skip: 1, }, { opcode: 0x0F, os: 1, prefix: 1, }, { opcode: 0x16, os: 1, skip: 1, }, @@ -177,7 +177,7 @@ const encodings = [ { opcode: 0xC2, block_boundary: 1, no_next_instruction: 1, os: 1, imm16: 1, skip: 1, }, // ret { opcode: 0xC3, custom: 1, block_boundary: 1, no_next_instruction: 1, os: 1, skip: 1, }, - { opcode: 0xC4, os: 1, e: 1, skip: 1, }, + { opcode: 0xC4, block_boundary: 1, os: 1, e: 1, skip: 1, }, // les { opcode: 0xC5, block_boundary: 1, os: 1, e: 1, skip: 1, }, // lds { opcode: 0xC6, e: 1, fixed_g: 0, nonfaulting: 1, imm8: 1, }, @@ -385,11 +385,11 @@ const encodings = [ { opcode: 0x0F9F, nonfaulting: 1, e: 1, }, { opcode: 0x0FA0, os: 1, skip: 1, }, - { opcode: 0x0FA1, os: 1, skip: 1, }, + { opcode: 0x0FA1, os: 1, block_boundary: 1, skip: 1, }, // pop fs: block_boundary since it uses non-raising cpu exceptions { opcode: 0x0FA2, skip: 1, }, { opcode: 0x0FA8, os: 1, skip: 1, }, - { opcode: 0x0FA9, os: 1, skip: 1, }, + { opcode: 0x0FA9, os: 1, block_boundary: 1, skip: 1, }, // pop gs { 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, }, @@ -432,9 +432,9 @@ const encodings = [ { 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, block_boundary: 1, 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: 0x0FB2, block_boundary: 1, os: 1, e: 1, skip: 1, }, // lss + { opcode: 0x0FB4, block_boundary: 1, os: 1, e: 1, skip: 1, }, // lfs + { opcode: 0x0FB5, block_boundary: 1, os: 1, e: 1, skip: 1, }, // lgs { opcode: 0x0FB6, nonfaulting: 1, os: 1, e: 1, }, // movzx { opcode: 0x0FB7, nonfaulting: 1, os: 1, e: 1, }, diff --git a/src/browser/starter.js b/src/browser/starter.js index ee9befe9..9488618a 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -164,7 +164,7 @@ function V86Starter(options) }, "_far_jump": function(eip, selector, is_call) { return cpu.far_jump(eip, selector, !!is_call); }, "_far_return": function(eip, selector, stack_adjust) { return cpu.far_return(eip, selector, stack_adjust); }, - "_switch_seg": function(reg, selector) { cpu.switch_seg(reg, selector); }, + "_switch_seg": function(reg, selector) { return cpu.switch_seg(reg, selector); }, "_iret16": function() { return cpu.iret16(); }, "_iret32": function() { return cpu.iret32(); }, "_handle_irqs": function() { return cpu.handle_irqs(); }, diff --git a/src/cpu.js b/src/cpu.js index 9d943c2b..da599cff 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -630,7 +630,7 @@ CPU.prototype.reset = function() this.instruction_pointer[0] = 0xFFFF0; this.switch_cs_real_mode(0xF000); - this.switch_seg(reg_ss, 0x30); + if(this.switch_seg(reg_ss, 0x30)) dbg_assert(false); this.reg16[reg_sp] = 0x100; if(this.devices.virtio) @@ -1647,7 +1647,7 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, ha this.flags[0] &= ~flag_vm & ~flag_rf; - this.switch_seg(reg_ss, new_ss); + if(this.switch_seg(reg_ss, new_ss)) dbg_assert(false); // XXX this.set_stack_reg(new_esp); if(old_flags & flag_vm) @@ -1730,10 +1730,16 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, ha if(old_flags & flag_vm) { - this.switch_seg(reg_gs, 0); - this.switch_seg(reg_fs, 0); - this.switch_seg(reg_ds, 0); - this.switch_seg(reg_es, 0); + if( + this.switch_seg(reg_gs, 0) || + this.switch_seg(reg_fs, 0) || + this.switch_seg(reg_ds, 0) || + this.switch_seg(reg_es, 0) + ) + { + // can't fail + dbg_assert(false); + } } this.sreg[reg_cs] = selector & ~3 | this.cpl[0]; @@ -1891,15 +1897,21 @@ CPU.prototype.iret = function(is_16) this.switch_cs_real_mode(new_cs); this.instruction_pointer[0] = (new_eip & 0xFFFF) + this.get_seg(reg_cs) | 0; - this.switch_seg(reg_es, new_es); - this.switch_seg(reg_ds, new_ds); - this.switch_seg(reg_fs, new_fs); - this.switch_seg(reg_gs, new_gs); + if( + this.switch_seg(reg_es, new_es) || + this.switch_seg(reg_ds, new_ds) || + this.switch_seg(reg_fs, new_fs) || + this.switch_seg(reg_gs, new_gs) + ) + { + // XXX: Should be checked before side effects + dbg_assert(false); + } this.adjust_stack_reg(9 * 4); // 9 dwords: eip, cs, flags, esp, ss, es, ds, fs, gs this.reg32s[reg_esp] = temp_esp; - this.switch_seg(reg_ss, temp_ss); + if(this.switch_seg(reg_ss, temp_ss)) dbg_assert(false); // XXX this.cpl[0] = 3; this.cpl_changed(); @@ -1993,6 +2005,7 @@ CPU.prototype.iret = function(is_16) dbg_log("#SS for loading non-present in SS sel=" + h(temp_ss, 4), LOG_CPU); dbg_trace(LOG_CPU); this.trigger_ss(temp_ss & ~3); + return; } // no exceptions below @@ -2011,7 +2024,7 @@ CPU.prototype.iret = function(is_16) //dbg_log("outer privilege return: from=" + this.cpl[0] + " to=" + info.rpl + " ss:esp=" + h(temp_ss, 4) + ":" + h(temp_esp >>> 0, 8), LOG_CPU); - this.switch_seg(reg_ss, temp_ss); + if(this.switch_seg(reg_ss, temp_ss)) dbg_assert(false); // XXX this.set_stack_reg(temp_esp); @@ -2024,7 +2037,7 @@ CPU.prototype.iret = function(is_16) // XXX: Set segment to 0 if it's not usable in the new cpl // XXX: Use cached segment information //var ds_info = this.lookup_segment_selector(this.sreg[reg_ds]); - //if(this.cpl[0] > ds_info.dpl && (!ds_info.is_executable || !ds_info.dc_bit)) this.switch_seg(reg_ds, 0); + //if(this.cpl[0] > ds_info.dpl && (!ds_info.is_executable || !ds_info.dc_bit)) if(this.switch_seg(reg_ds, 0)) ...; // ... } else if(info.rpl === this.cpl[0]) @@ -2171,8 +2184,8 @@ CPU.prototype.far_return = function(eip, selector, stack_adjust) this.cpl[0] = info.rpl; this.cpl_changed(); - // XXX: Can raise, conditions should be checked before side effects - this.switch_seg(reg_ss, temp_ss); + // XXX: This failure should be checked before side effects + if(this.switch_seg(reg_ss, temp_ss)) dbg_assert(false); this.set_stack_reg(temp_esp + stack_adjust); //if(this.is_osize_32()) @@ -2389,7 +2402,8 @@ CPU.prototype.far_jump = function(eip, selector, is_call) this.update_cs_size(cs_info.size); - this.switch_seg(reg_ss, new_ss); + // XXX: Should be checked before side effects + if(this.switch_seg(reg_ss, new_ss)) dbg_assert(false); this.set_stack_reg(new_esp); //dbg_log("parameter_count=" + parameter_count); @@ -2769,11 +2783,17 @@ CPU.prototype.do_task_switch = function(selector, error_code) this.reg32s[reg_esi] = this.safe_read32s(new_tsr_offset + TSR_ESI); this.reg32s[reg_edi] = this.safe_read32s(new_tsr_offset + TSR_EDI); - this.switch_seg(reg_es, this.safe_read16(new_tsr_offset + TSR_ES)); - this.switch_seg(reg_ss, this.safe_read16(new_tsr_offset + TSR_SS)); - this.switch_seg(reg_ds, this.safe_read16(new_tsr_offset + TSR_DS)); - this.switch_seg(reg_fs, this.safe_read16(new_tsr_offset + TSR_FS)); - this.switch_seg(reg_gs, this.safe_read16(new_tsr_offset + TSR_GS)); + if( + this.switch_seg(reg_es, this.safe_read16(new_tsr_offset + TSR_ES)) || + this.switch_seg(reg_ss, this.safe_read16(new_tsr_offset + TSR_SS)) || + this.switch_seg(reg_ds, this.safe_read16(new_tsr_offset + TSR_DS)) || + this.switch_seg(reg_fs, this.safe_read16(new_tsr_offset + TSR_FS)) || + this.switch_seg(reg_gs, this.safe_read16(new_tsr_offset + TSR_GS)) + ) + { + // XXX: Should be checked before side effects + dbg_assert(false); + } this.instruction_pointer[0] = this.get_seg(reg_cs) + new_eip | 0; @@ -3245,6 +3265,8 @@ CPU.prototype.lookup_segment_selector = function(selector) }; /** + * Returns true if changing was aborted due to an exception + * * @param {number} reg * @param {number} selector */ @@ -3263,7 +3285,7 @@ CPU.prototype.switch_seg = function(reg, selector) { this.stack_size_32[0] = +false; } - return; + return false; } var info = this.lookup_segment_selector(selector); @@ -3293,6 +3315,7 @@ CPU.prototype.switch_seg = function(reg, selector) dbg_log("#SS for loading non-present in SS sel=" + h(selector, 4), LOG_CPU); dbg_trace(LOG_CPU); this.trigger_ss(selector & ~3); + return true; } this.stack_size_32[0] = info.size; @@ -3341,6 +3364,8 @@ CPU.prototype.switch_seg = function(reg, selector) this.segment_offsets[reg] = info.base; this.sreg[reg] = selector; + + return false; }; CPU.prototype.load_tr = function(selector) @@ -3616,7 +3641,7 @@ CPU.prototype.lss16 = function(addr, reg, seg) var new_reg = this.safe_read16(addr), new_seg = this.safe_read16(addr + 2 | 0); - this.switch_seg(seg, new_seg); + if(this.switch_seg(seg, new_seg)) return; this.reg16[reg] = new_reg; }; @@ -3626,7 +3651,7 @@ CPU.prototype.lss32 = function(addr, reg, seg) var new_reg = this.safe_read32s(addr), new_seg = this.safe_read16(addr + 4 | 0); - this.switch_seg(seg, new_seg); + if(this.switch_seg(seg, new_seg)) return; this.reg32s[reg] = new_reg; }; diff --git a/src/native/cpu.c b/src/native/cpu.c index 6c7721bf..8198c886 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -823,8 +823,14 @@ void trigger_np(int32_t code) __attribute__((noinline)) void trigger_ss(int32_t code) { +#if DEBUG + if(cpu_exception_hook(12)) + { + return; + } +#endif *instruction_pointer = *previous_ip; - raise_exception_with_code(12, code); + call_interrupt_vector(12, false, true, code); } __attribute__((noinline)) diff --git a/src/native/instructions.c b/src/native/instructions.c index 50d5ba6d..ed7bc9c2 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -34,11 +34,11 @@ void instr32_05(int32_t imm32) { reg32s[EAX] = add32(reg32s[EAX], imm32); } void instr16_06() { push16(sreg[ES]); } void instr32_06() { push32(sreg[ES]); } void instr16_07() { - switch_seg(ES, safe_read16(get_stack_pointer(0))); + if(switch_seg(ES, safe_read16(get_stack_pointer(0)))) return; adjust_stack_reg(2); } void instr32_07() { - switch_seg(ES, safe_read32s(get_stack_pointer(0)) & 0xFFFF); + if(switch_seg(ES, safe_read32s(get_stack_pointer(0)) & 0xFFFF)) return; adjust_stack_reg(4); } @@ -76,13 +76,13 @@ void instr32_15(int32_t imm32) { reg32s[EAX] = adc32(reg32s[EAX], imm32); } void instr16_16() { push16(sreg[SS]); } void instr32_16() { push32(sreg[SS]); } void instr16_17() { - switch_seg(SS, safe_read16(get_stack_pointer(0))); + if(switch_seg(SS, safe_read16(get_stack_pointer(0)))) return; adjust_stack_reg(2); //clear_prefixes(); //cycle_internal(); } void instr32_17() { - switch_seg(SS, safe_read32s(get_stack_pointer(0)) & 0xFFFF); + if(switch_seg(SS, safe_read32s(get_stack_pointer(0)) & 0xFFFF)) return; adjust_stack_reg(4); //clear_prefixes(); //cycle_internal(); @@ -102,11 +102,11 @@ void instr32_1D(int32_t imm32) { reg32s[EAX] = sbb32(reg32s[EAX], imm32); } void instr16_1E() { push16(sreg[DS]); } void instr32_1E() { push32(sreg[DS]); } void instr16_1F() { - switch_seg(DS, safe_read16(get_stack_pointer(0))); + if(switch_seg(DS, safe_read16(get_stack_pointer(0)))) return; adjust_stack_reg(2); } void instr32_1F() { - switch_seg(DS, safe_read32s(get_stack_pointer(0)) & 0xFFFF); + if(switch_seg(DS, safe_read32s(get_stack_pointer(0)) & 0xFFFF)) return; adjust_stack_reg(4); } @@ -466,12 +466,12 @@ void instr_8E_helper(int32_t data, int32_t mod) { if(mod == ES || mod == SS || mod == DS || mod == FS || mod == GS) { - switch_seg(mod, data); + if(switch_seg(mod, data)) return; if(mod == SS) { // run next instruction, so no interrupts are handled - clear_prefixes(); + //clear_prefixes(); //cycle_internal(); } } diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 02f76259..cb67a111 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1997,11 +1997,11 @@ void instr_0F9F_mem(int32_t addr, int32_t unused) { setcc_mem(!test_le(), addr); void instr16_0FA0() { push16(sreg[FS]); } void instr32_0FA0() { push32(sreg[FS]); } void instr16_0FA1() { - switch_seg(FS, safe_read16(get_stack_pointer(0))); + if(switch_seg(FS, safe_read16(get_stack_pointer(0)))) return; adjust_stack_reg(2); } void instr32_0FA1() { - switch_seg(FS, safe_read32s(get_stack_pointer(0)) & 0xFFFF); + if(switch_seg(FS, safe_read32s(get_stack_pointer(0)) & 0xFFFF)) return; adjust_stack_reg(4); } @@ -2026,11 +2026,11 @@ void instr_0FA7() { undefined_instruction(); } void instr16_0FA8() { push16(sreg[GS]); } void instr32_0FA8() { push32(sreg[GS]); } void instr16_0FA9() { - switch_seg(GS, safe_read16(get_stack_pointer(0))); + if(switch_seg(GS, safe_read16(get_stack_pointer(0)))) return; adjust_stack_reg(2); } void instr32_0FA9() { - switch_seg(GS, safe_read32s(get_stack_pointer(0)) & 0xFFFF); + if(switch_seg(GS, safe_read32s(get_stack_pointer(0)) & 0xFFFF)) return; adjust_stack_reg(4); } diff --git a/src/native/js_imports.h b/src/native/js_imports.h index 0d494eeb..50ca1ee3 100644 --- a/src/native/js_imports.h +++ b/src/native/js_imports.h @@ -49,7 +49,7 @@ extern void undefined_instruction(void); extern void unimplemented_sse(void); extern void update_cs_size(int32_t); extern void update_eflags(int32_t); -extern void switch_seg(int32_t, int32_t); +extern bool switch_seg(int32_t, int32_t); extern void lss16(int32_t, int32_t, int32_t); extern void lss32(int32_t, int32_t, int32_t); extern void test_privileges_for_io(int32_t, int32_t); From 1cf742eac39f0c095a21470a9889b75015552c89 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 20 Jul 2018 15:12:45 -0600 Subject: [PATCH 1063/2137] Use constant names for cpu exceptions --- src/native/cpu.c | 18 +++++++++--------- src/native/cpu.h | 20 ++++++++++++++++++++ src/native/instructions.c | 2 +- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/native/cpu.c b/src/native/cpu.c index 8198c886..d6e36b58 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -122,7 +122,7 @@ void trigger_pagefault(bool write, bool user, bool present) *instruction_pointer = *previous_ip; *page_fault = true; - call_interrupt_vector(14, false, true, user << 2 | write << 1 | present); + call_interrupt_vector(CPU_EXCEPTION_PF, false, true, user << 2 | write << 1 | present); profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); throw_cpu_exception(); @@ -788,13 +788,13 @@ __attribute__((noinline)) void trigger_de() { #if DEBUG - if(cpu_exception_hook(0)) + if(cpu_exception_hook(CPU_EXCEPTION_DE)) { return; } #endif *instruction_pointer = *previous_ip; - call_interrupt_vector(0, false, false, 0); + call_interrupt_vector(CPU_EXCEPTION_DE, false, false, 0); } __attribute__((noinline)) @@ -803,41 +803,41 @@ void trigger_ud() dbg_log("#ud"); dbg_trace(); *instruction_pointer = *previous_ip; - raise_exception(6); + raise_exception(CPU_EXCEPTION_UD); } __attribute__((noinline)) void trigger_nm() { *instruction_pointer = *previous_ip; - raise_exception(7); + raise_exception(CPU_EXCEPTION_NM); } __attribute__((noinline)) void trigger_np(int32_t code) { *instruction_pointer = *previous_ip; - raise_exception_with_code(11, code); + raise_exception_with_code(CPU_EXCEPTION_NP, code); } __attribute__((noinline)) void trigger_ss(int32_t code) { #if DEBUG - if(cpu_exception_hook(12)) + if(cpu_exception_hook(CPU_EXCEPTION_SS)) { return; } #endif *instruction_pointer = *previous_ip; - call_interrupt_vector(12, false, true, code); + call_interrupt_vector(CPU_EXCEPTION_SS, false, true, code); } __attribute__((noinline)) void trigger_gp(int32_t code) { *instruction_pointer = *previous_ip; - raise_exception_with_code(13, code); + raise_exception_with_code(CPU_EXCEPTION_GP, code); } int32_t virt_boundary_read16(int32_t low, int32_t high) diff --git a/src/native/cpu.h b/src/native/cpu.h index f696889d..edb653ca 100644 --- a/src/native/cpu.h +++ b/src/native/cpu.h @@ -50,6 +50,26 @@ int32_t valid_tlb_entries_count; #define TLB_GLOBAL (1 << 4) #define TLB_HAS_CODE (1 << 5) +static const int32_t CPU_EXCEPTION_DE = 0; // Divide Error +static const int32_t CPU_EXCEPTION_DB = 1; // Debug Exception +static const int32_t CPU_EXCEPTION_NMI = 2; // NMI Interrupt +static const int32_t CPU_EXCEPTION_BP = 3; // Breakpoint +static const int32_t CPU_EXCEPTION_OF = 4; // Overflow +static const int32_t CPU_EXCEPTION_BR = 5; // BOUND Range Exceeded +static const int32_t CPU_EXCEPTION_UD = 6; // Invalid Opcode +static const int32_t CPU_EXCEPTION_NM = 7; // Device Not Available +static const int32_t CPU_EXCEPTION_DF = 8; // Double Fault +static const int32_t CPU_EXCEPTION_TS = 10; // Invalid TSS +static const int32_t CPU_EXCEPTION_NP = 11; // Segment Not Present +static const int32_t CPU_EXCEPTION_SS = 12; // Stack-Segment Fault +static const int32_t CPU_EXCEPTION_GP = 13; // General Protection +static const int32_t CPU_EXCEPTION_PF = 14; // Page Fault +static const int32_t CPU_EXCEPTION_MF = 16; // x87 FPU Floating-Point Error +static const int32_t CPU_EXCEPTION_AC = 17; // Alignment Check +static const int32_t CPU_EXCEPTION_MC = 18; // Machine Check Abort +static const int32_t CPU_EXCEPTION_XM = 19; // SIMD Floating-Point Exception +static const int32_t CPU_EXCEPTION_VE = 20; // Virtualization Exception + // defined in call-indirect.ll extern void call_indirect(int32_t index); extern void call_indirect1(int32_t index, int32_t arg); diff --git a/src/native/instructions.c b/src/native/instructions.c index ed7bc9c2..b89783e3 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -914,7 +914,7 @@ void instr_CE() { if(getof()) { // TODO: inhibit iopl checks - call_interrupt_vector(4, true, false, 0); + call_interrupt_vector(CPU_EXCEPTION_OF, true, false, 0); } } From ee4dbf62c6e960234a7f84d5b65ae09d5d7c9edd Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 20 Jul 2018 17:10:59 -0600 Subject: [PATCH 1064/2137] mov sreg, reg: Add missing trigger_ud --- src/native/instructions.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/native/instructions.c b/src/native/instructions.c index b89783e3..fce40ca3 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -478,6 +478,7 @@ void instr_8E_helper(int32_t data, int32_t mod) else { dbg_log("mov sreg #ud"); + trigger_ud(); } } DEFINE_MODRM_INSTR_READ16(instr_8E, instr_8E_helper(___, r)) From e5240e13d73d43e71eccae136a79e551e4ce4d85 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 20 Jul 2018 18:22:57 -0600 Subject: [PATCH 1065/2137] Remove use of cpu exceptions for trigger_np --- src/cpu.js | 6 ++++++ src/native/cpu.c | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/cpu.js b/src/cpu.js index da599cff..a24d65ab 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -1570,6 +1570,7 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, ha // kvm-unit-test dbg_log("not present"); this.trigger_np(interrupt_nr << 3 | 2); + return; } var old_flags = this.get_eflags(); @@ -2160,6 +2161,7 @@ CPU.prototype.far_return = function(eip, selector, stack_adjust) dbg_log("#NP for loading not-present in cs sel=" + h(selector, 4), LOG_CPU); dbg_trace(LOG_CPU); this.trigger_np(selector & ~3); + return; } if(info.rpl > this.cpl[0]) @@ -2296,6 +2298,7 @@ CPU.prototype.far_jump = function(eip, selector, is_call) { dbg_log("#NP for loading not-present in gate cs sel=" + h(selector, 4), LOG_CPU); this.trigger_np(selector & ~3); + return; } var cs_selector = info.raw0 >>> 16; @@ -2329,6 +2332,7 @@ CPU.prototype.far_jump = function(eip, selector, is_call) { dbg_log("#NP for loading not-present in cs sel=" + h(cs_selector, 4), LOG_CPU); this.trigger_np(cs_selector & ~3); + return; } if(!cs_info.dc_bit && cs_info.dpl < this.cpl[0]) @@ -2532,6 +2536,7 @@ CPU.prototype.far_jump = function(eip, selector, is_call) dbg_log("#NP for loading not-present in cs sel=" + h(selector, 4), LOG_CPU); dbg_trace(LOG_CPU); this.trigger_np(selector & ~3); + return; } if(is_call) @@ -3355,6 +3360,7 @@ CPU.prototype.switch_seg = function(reg, selector) dbg_log("#NP for loading not-present in seg " + reg + " sel=" + h(selector, 4), LOG_CPU); dbg_trace(LOG_CPU); this.trigger_np(selector & ~3); + return true; } } diff --git a/src/native/cpu.c b/src/native/cpu.c index d6e36b58..2be9c0ae 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -816,8 +816,14 @@ void trigger_nm() __attribute__((noinline)) void trigger_np(int32_t code) { +#if DEBUG + if(cpu_exception_hook(CPU_EXCEPTION_NP)) + { + return; + } +#endif *instruction_pointer = *previous_ip; - raise_exception_with_code(CPU_EXCEPTION_NP, code); + call_interrupt_vector(CPU_EXCEPTION_NP, false, true, code); } __attribute__((noinline)) From 33912bee282c49b0d8cd8dccffbdc0b6a426c512 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 21 Jul 2018 15:04:38 -0600 Subject: [PATCH 1066/2137] Add trigger_gp_non_raising and use it in JS --- src/cpu.js | 94 +++++++++++++++++++++++++++++++----------------- src/native/cpu.c | 7 ++++ src/native/cpu.h | 1 + 3 files changed, 70 insertions(+), 32 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index a24d65ab..e187fdcb 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -253,7 +253,7 @@ CPU.prototype.wasm_patch = function(wm) this.get_eflags = this.wm.exports["_get_eflags"]; this.update_eflags = this.wm.exports["_update_eflags"]; - this.trigger_gp = this.wm.exports["_trigger_gp"]; + this.trigger_gp_non_raising = this.wm.exports["_trigger_gp_non_raising"]; this.trigger_ud = this.wm.exports["_trigger_ud"]; this.trigger_np = this.wm.exports["_trigger_np"]; this.trigger_ss = this.wm.exports["_trigger_ss"]; @@ -1490,7 +1490,8 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, ha { dbg_log("call_interrupt_vector #GP. vm86 && software int && iopl < 3", LOG_CPU); dbg_trace(LOG_CPU); - this.trigger_gp(0); + this.trigger_gp_non_raising(0); + return; } if((interrupt_nr << 3 | 7) > this.idtr_size[0]) @@ -1524,7 +1525,8 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, ha { dbg_log("#gp software interrupt (" + h(interrupt_nr, 2) + ") and dpl < cpl", LOG_CPU); dbg_trace(LOG_CPU); - this.trigger_gp(interrupt_nr << 3 | 2); + this.trigger_gp_non_raising(interrupt_nr << 3 | 2); + return; } if(type === 5) @@ -1689,7 +1691,8 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, ha if(this.flags[0] & flag_vm) { dbg_assert(false, "check error code"); - this.trigger_gp(selector & ~3); + this.trigger_gp_non_raising(selector & ~3); + return; } var stack_space = (is_16 ? 2 : 4) * (3 + (has_error_code === true)); @@ -1814,7 +1817,8 @@ CPU.prototype.iret = function(is_16) { // vm86 mode, iopl != 3 dbg_log("#gp iret vm86 mode, iopl != 3", LOG_CPU); - this.trigger_gp(0); + this.trigger_gp_non_raising(0); + return; } if(is_16) @@ -1863,7 +1867,8 @@ CPU.prototype.iret = function(is_16) if(this.flags[0] & flag_nt) { if(DEBUG) throw this.debug.unimpl("nt"); - this.trigger_gp(0); + this.trigger_gp_non_raising(0); + return; } if(new_flags & flag_vm) @@ -1963,7 +1968,8 @@ CPU.prototype.iret = function(is_16) if(!info.dc_bit && info.rpl !== info.dpl) { dbg_log("#gp iret: non-conforming cs and rpl != dpl, dpl=" + info.dpl + " rpl=" + info.rpl, LOG_CPU); - this.trigger_gp(new_cs & ~3); + this.trigger_gp_non_raising(new_cs & ~3); + return; } if(info.rpl > this.cpl[0]) @@ -1987,7 +1993,8 @@ CPU.prototype.iret = function(is_16) { dbg_log("#GP for loading 0 in SS sel=" + h(temp_ss, 4), LOG_CPU); dbg_trace(LOG_CPU); - this.trigger_gp(0); + this.trigger_gp_non_raising(0); + return; } if(!ss_info.is_valid || @@ -1998,7 +2005,8 @@ CPU.prototype.iret = function(is_16) { dbg_log("#GP for loading invalid in SS sel=" + h(temp_ss, 4), LOG_CPU); dbg_trace(LOG_CPU); - this.trigger_gp(temp_ss & ~3); + this.trigger_gp_non_raising(temp_ss & ~3); + return; } if(!ss_info.is_present) @@ -2117,43 +2125,50 @@ CPU.prototype.far_return = function(eip, selector, stack_adjust) if(info.is_null) { dbg_log("null cs", LOG_CPU); - this.trigger_gp(0); + this.trigger_gp_non_raising(0); + return; } if(!info.is_valid) { dbg_log("invalid cs: " + h(selector), LOG_CPU); - this.trigger_gp(selector & ~3); + this.trigger_gp_non_raising(selector & ~3); + return; } if(info.is_system) { dbg_assert(false, "is system in far return"); - this.trigger_gp(selector & ~3); + this.trigger_gp_non_raising(selector & ~3); + return; } if(!info.is_executable) { dbg_log("non-executable cs: " + h(selector), LOG_CPU); - this.trigger_gp(selector & ~3); + this.trigger_gp_non_raising(selector & ~3); + return; } if(info.rpl < this.cpl[0]) { dbg_log("cs rpl < cpl: " + h(selector), LOG_CPU); - this.trigger_gp(selector & ~3); + this.trigger_gp_non_raising(selector & ~3); + return; } if(info.dc_bit && info.dpl > info.rpl) { dbg_log("cs conforming and dpl > rpl: " + h(selector), LOG_CPU); - this.trigger_gp(selector & ~3); + this.trigger_gp_non_raising(selector & ~3); + return; } if(!info.dc_bit && info.dpl !== info.rpl) { dbg_log("cs non-conforming and dpl != rpl: " + h(selector), LOG_CPU); - this.trigger_gp(selector & ~3); + this.trigger_gp_non_raising(selector & ~3); + return; } if(!info.is_present) @@ -2268,13 +2283,15 @@ CPU.prototype.far_jump = function(eip, selector, is_call) if(info.is_null) { dbg_log("#gp null cs", LOG_CPU); - this.trigger_gp(0); + this.trigger_gp_non_raising(0); + return; } if(!info.is_valid) { dbg_log("#gp invalid cs: " + h(selector), LOG_CPU); - this.trigger_gp(selector & ~3); + this.trigger_gp_non_raising(selector & ~3); + return; } if(info.is_system) @@ -2291,7 +2308,8 @@ CPU.prototype.far_jump = function(eip, selector, is_call) if(info.dpl < this.cpl[0] || info.dpl < info.rpl) { dbg_log("#gp cs gate dpl < cpl or dpl < rpl: " + h(selector), LOG_CPU); - this.trigger_gp(selector & ~3); + this.trigger_gp_non_raising(selector & ~3); + return; } if(!info.is_present) @@ -2307,25 +2325,29 @@ CPU.prototype.far_jump = function(eip, selector, is_call) if(cs_info.is_null) { dbg_log("#gp null cs", LOG_CPU); - this.trigger_gp(0); + this.trigger_gp_non_raising(0); + return; } if(!cs_info.is_valid) { dbg_log("#gp invalid cs: " + h(cs_selector), LOG_CPU); - this.trigger_gp(cs_selector & ~3); + this.trigger_gp_non_raising(cs_selector & ~3); + return; } if(!cs_info.is_executable) { dbg_log("#gp non-executable cs: " + h(cs_selector), LOG_CPU); - this.trigger_gp(cs_selector & ~3); + this.trigger_gp_non_raising(cs_selector & ~3); + return; } if(cs_info.dpl > this.cpl[0]) { dbg_log("#gp dpl > cpl: " + h(cs_selector), LOG_CPU); - this.trigger_gp(cs_selector & ~3); + this.trigger_gp_non_raising(cs_selector & ~3); + return; } if(!cs_info.is_present) @@ -2508,7 +2530,8 @@ CPU.prototype.far_jump = function(eip, selector, is_call) if(!info.is_executable) { dbg_log("#gp non-executable cs: " + h(selector), LOG_CPU); - this.trigger_gp(selector & ~3); + this.trigger_gp_non_raising(selector & ~3); + return; } if(info.dc_bit) @@ -2517,7 +2540,8 @@ CPU.prototype.far_jump = function(eip, selector, is_call) if(info.dpl > this.cpl[0]) { dbg_log("#gp cs dpl > cpl: " + h(selector), LOG_CPU); - this.trigger_gp(selector & ~3); + this.trigger_gp_non_raising(selector & ~3); + return; } } else @@ -2527,7 +2551,8 @@ CPU.prototype.far_jump = function(eip, selector, is_call) if(info.rpl > this.cpl[0] || info.dpl !== this.cpl[0]) { dbg_log("#gp cs rpl > cpl or dpl != cpl: " + h(selector), LOG_CPU); - this.trigger_gp(selector & ~3); + this.trigger_gp_non_raising(selector & ~3); + return; } } @@ -2830,7 +2855,8 @@ CPU.prototype.hlt_op = function() if(this.cpl[0]) { dbg_log("#gp hlt with cpl != 0", LOG_CPU); - this.trigger_gp(0); + this.trigger_gp_non_raising(0); + return; } if((this.flags[0] & flag_interrupt) === 0) @@ -2950,7 +2976,8 @@ CPU.prototype.test_privileges_for_io = function(port, size) { dbg_log("#GP for port io, 16-bit TSS port=" + h(port) + " size=" + size, LOG_CPU); CPU_LOG_VERBOSE && this.debug.dump_state(); - this.trigger_gp(0); + this.trigger_gp_non_raising(0); + return; } var tsr_size = this.segment_limits[reg_tr]; @@ -2981,7 +3008,7 @@ CPU.prototype.test_privileges_for_io = function(port, size) dbg_log("#GP for port io port=" + h(port) + " size=" + size, LOG_CPU); CPU_LOG_VERBOSE && this.debug.dump_state(); - this.trigger_gp(0); + this.trigger_gp_non_raising(0); } }; @@ -3301,7 +3328,8 @@ CPU.prototype.switch_seg = function(reg, selector) { dbg_log("#GP for loading 0 in SS sel=" + h(selector, 4), LOG_CPU); dbg_trace(LOG_CPU); - this.trigger_gp(0); + this.trigger_gp_non_raising(0); + return; } if(!info.is_valid || @@ -3312,7 +3340,8 @@ CPU.prototype.switch_seg = function(reg, selector) { dbg_log("#GP for loading invalid in SS sel=" + h(selector, 4), LOG_CPU); dbg_trace(LOG_CPU); - this.trigger_gp(selector & ~3); + this.trigger_gp_non_raising(selector & ~3); + return; } if(!info.is_present) @@ -3352,7 +3381,8 @@ CPU.prototype.switch_seg = function(reg, selector) this.debug.dump_state(); this.debug.dump_regs(); dbg_trace(LOG_CPU); - this.trigger_gp(selector & ~3); + this.trigger_gp_non_raising(selector & ~3); + return; } if(!info.is_present) diff --git a/src/native/cpu.c b/src/native/cpu.c index 2be9c0ae..c38f563c 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -846,6 +846,13 @@ void trigger_gp(int32_t code) raise_exception_with_code(CPU_EXCEPTION_GP, code); } +__attribute__((noinline)) +void trigger_gp_non_raising(int32_t code) +{ + *instruction_pointer = *previous_ip; + raise_exception_with_code(CPU_EXCEPTION_GP, code); +} + int32_t virt_boundary_read16(int32_t low, int32_t high) { dbg_assert((low & 0xFFF) == 0xFFF); diff --git a/src/native/cpu.h b/src/native/cpu.h index edb653ca..8b50f2fc 100644 --- a/src/native/cpu.h +++ b/src/native/cpu.h @@ -113,6 +113,7 @@ void trigger_de(void); void trigger_ud(void); void trigger_nm(void); void trigger_gp(int32_t code); +void trigger_gp_non_raising(int32_t code); int32_t virt_boundary_read16(int32_t low, int32_t high); int32_t virt_boundary_read32s(int32_t low, int32_t high); void virt_boundary_write16(int32_t low, int32_t high, int32_t value); From f43ab3387abf1d1dcb3642406f146f18b936597f Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 21 Jul 2018 15:52:30 -0600 Subject: [PATCH 1067/2137] Remove use of cpu exceptions for trigger_gp for instructions --- gen/x86_table.js | 58 ++++++++++++++++++----------------- src/cpu.js | 8 ++--- src/native/cpu.c | 8 ++++- src/native/instructions.c | 14 +++++---- src/native/instructions_0f.c | 59 ++++++++++++++++++++++-------------- src/native/misc_instr.c | 3 +- tests/nasm/jmp_near.asm | 1 + tests/nasm/loop.asm | 1 + tests/nasm/run.js | 5 ++- 9 files changed, 93 insertions(+), 64 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index db3cb23c..f5946310 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -124,7 +124,8 @@ const encodings = [ { opcode: 0x99, nonfaulting: 1, os: 1, }, { opcode: 0x9A, os: 1, imm1632: 1, extra_imm16: 1, skip: 1, block_boundary: 1, }, // callf { opcode: 0x9B, skip: 1, }, - { opcode: 0x9C, os: 1, }, + // pushf: block_boundary since it uses non-raising cpu exceptions + { opcode: 0x9C, os: 1, block_boundary: 1, }, // popf: not a jump, but can cause an eip change due to updating the interrupt flag { opcode: 0x9D, os: 1, block_boundary: 1, skip: 1, }, { opcode: 0x9E, }, @@ -248,7 +249,8 @@ const encodings = [ { opcode: 0xF8, nonfaulting: 1, }, { opcode: 0xF9, nonfaulting: 1, }, - { opcode: 0xFA, skip: 1, }, + // cli: block_boundary since it uses non-raising cpu exceptions + { opcode: 0xFA, block_boundary: 1, skip: 1, }, // sti: not a jump, but can cause a change in eip { opcode: 0xFB, block_boundary: 1, skip: 1, }, { opcode: 0xFC, nonfaulting: 1, }, @@ -264,29 +266,29 @@ const encodings = [ { opcode: 0xFF, os: 1, e: 1, fixed_g: 5, block_boundary: 1, no_next_instruction: 1, skip: 1, }, { opcode: 0xFF, custom: 1, 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: 0x0F00, fixed_g: 0, e: 1, skip: 1, block_boundary: 1, }, // sldt, ... + { opcode: 0x0F00, fixed_g: 1, e: 1, skip: 1, block_boundary: 1, }, + { opcode: 0x0F00, fixed_g: 2, e: 1, skip: 1, block_boundary: 1, }, + { opcode: 0x0F00, fixed_g: 3, e: 1, skip: 1, block_boundary: 1, }, + { opcode: 0x0F00, fixed_g: 4, e: 1, skip: 1, block_boundary: 1, }, + { opcode: 0x0F00, fixed_g: 5, e: 1, skip: 1, block_boundary: 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: 0x0F01, fixed_g: 0, e: 1, skip: 1, block_boundary: 1, }, // sgdt, ... + { opcode: 0x0F01, fixed_g: 1, e: 1, skip: 1, block_boundary: 1, }, + { opcode: 0x0F01, fixed_g: 2, e: 1, skip: 1, block_boundary: 1, }, + { opcode: 0x0F01, fixed_g: 3, e: 1, skip: 1, block_boundary: 1, }, + { opcode: 0x0F01, fixed_g: 4, e: 1, skip: 1, block_boundary: 1, }, + { opcode: 0x0F01, fixed_g: 6, e: 1, skip: 1, block_boundary: 1, }, + { opcode: 0x0F01, fixed_g: 7, e: 1, skip: 1, block_boundary: 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: 0x0F06, skip: 1, block_boundary: 1, }, // clts { opcode: 0x0F07, skip: 1 }, { opcode: 0x0F08, skip: 1 }, - { opcode: 0x0F09, skip: 1 }, + { opcode: 0x0F09, skip: 1, block_boundary: 1, }, // wbinvd { opcode: 0x0F0A, skip: 1 }, // ud2 // Technically has a next instruction, but Linux uses this for assertions @@ -307,18 +309,18 @@ const encodings = [ { opcode: 0x0F1E, skip: 1 }, { opcode: 0x0F1F, custom: 1, 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: 0x0F20, ignore_mod: 1, e: 1, skip: 1, block_boundary: 1, }, // mov reg, creg + { opcode: 0x0F21, ignore_mod: 1, e: 1, skip: 1, block_boundary: 1, }, // mov reg, dreg + { opcode: 0x0F22, ignore_mod: 1, e: 1, skip: 1, block_boundary: 1, }, // mov creg, reg + { opcode: 0x0F23, ignore_mod: 1, e: 1, skip: 1, block_boundary: 1, }, // mov dreg, reg { opcode: 0x0F24, skip: 1 }, { opcode: 0x0F25, skip: 1 }, { opcode: 0x0F26, skip: 1 }, { opcode: 0x0F27, skip: 1 }, - { opcode: 0x0F30, skip: 1 }, - { opcode: 0x0F31, skip: 1 }, - { opcode: 0x0F32, skip: 1 }, + { opcode: 0x0F30, skip: 1, block_boundary: 1, }, // wrmsr + { opcode: 0x0F31, skip: 1, block_boundary: 1, }, // rdtsc + { opcode: 0x0F32, skip: 1, block_boundary: 1, }, // rdmsr { opcode: 0x0F33, skip: 1 }, { opcode: 0x0F34, skip: 1, block_boundary: 1, no_next_instruction: 1, }, // sysenter { opcode: 0x0F35, skip: 1, block_boundary: 1, no_next_instruction: 1, }, // sysexit @@ -415,10 +417,10 @@ const encodings = [ { opcode: 0x0FAA, skip: 1 }, - { 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: 0, only_mem: 1, skip: 1, }, // fxsave + { opcode: 0x0FAE, e: 1, fixed_g: 1, only_mem: 1, skip: 1, block_boundary: 1, }, // fxrstor: block_boundary since it uses non-raising cpu exceptions + { opcode: 0x0FAE, e: 1, fixed_g: 2, only_mem: 1, skip: 1, block_boundary: 1, }, // ldmxcsr + { opcode: 0x0FAE, e: 1, fixed_g: 3, only_mem: 1, skip: 1, block_boundary: 1, }, // stmxcsr { 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) diff --git a/src/cpu.js b/src/cpu.js index e187fdcb..4277bf49 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -3329,7 +3329,7 @@ CPU.prototype.switch_seg = function(reg, selector) dbg_log("#GP for loading 0 in SS sel=" + h(selector, 4), LOG_CPU); dbg_trace(LOG_CPU); this.trigger_gp_non_raising(0); - return; + return true; } if(!info.is_valid || @@ -3341,7 +3341,7 @@ CPU.prototype.switch_seg = function(reg, selector) dbg_log("#GP for loading invalid in SS sel=" + h(selector, 4), LOG_CPU); dbg_trace(LOG_CPU); this.trigger_gp_non_raising(selector & ~3); - return; + return true; } if(!info.is_present) @@ -3368,7 +3368,7 @@ CPU.prototype.switch_seg = function(reg, selector) //dbg_trace(LOG_CPU); this.sreg[reg] = selector; this.segment_is_null[reg] = 1; - return; + return false; } if(!info.is_valid || @@ -3382,7 +3382,7 @@ CPU.prototype.switch_seg = function(reg, selector) this.debug.dump_regs(); dbg_trace(LOG_CPU); this.trigger_gp_non_raising(selector & ~3); - return; + return true; } if(!info.is_present) diff --git a/src/native/cpu.c b/src/native/cpu.c index c38f563c..d8300a15 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -849,8 +849,14 @@ void trigger_gp(int32_t code) __attribute__((noinline)) void trigger_gp_non_raising(int32_t code) { +#if DEBUG + if(cpu_exception_hook(CPU_EXCEPTION_GP)) + { + return; + } +#endif *instruction_pointer = *previous_ip; - raise_exception_with_code(CPU_EXCEPTION_GP, code); + call_interrupt_vector(CPU_EXCEPTION_GP, false, true, code); } int32_t virt_boundary_read16(int32_t low, int32_t high) diff --git a/src/native/instructions.c b/src/native/instructions.c index fce40ca3..ed846cd6 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -590,7 +590,7 @@ void instr16_9C() { { dbg_assert(*protected_mode); dbg_log("pushf #gp"); - trigger_gp(0); + trigger_gp_non_raising(0); } else { @@ -604,7 +604,7 @@ void instr32_9C() { // trap to virtual 8086 monitor dbg_assert(*protected_mode); dbg_log("pushf #gp"); - trigger_gp(0); + trigger_gp_non_raising(0); } else { @@ -617,7 +617,8 @@ void instr16_9D() { if((flags[0] & FLAG_VM) && getiopl() < 3) { dbg_log("popf #gp"); - trigger_gp(0); + trigger_gp_non_raising(0); + return; } update_eflags((flags[0] & ~0xFFFF) | pop16()); @@ -641,7 +642,8 @@ void instr32_9D() { if((flags[0] & FLAG_VM) && getiopl() < 3) { dbg_log("popf #gp"); - trigger_gp(0); + trigger_gp_non_raising(0); + return; } update_eflags(pop32s()); @@ -1493,7 +1495,7 @@ void instr_FA() { //else { dbg_log("cli #gp"); - trigger_gp(0); + trigger_gp_non_raising(0); } } } @@ -1527,7 +1529,7 @@ void instr_FB() { //else { dbg_log("sti #gp"); - trigger_gp(0); + trigger_gp_non_raising(0); } } diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index cb67a111..db24c7b3 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -43,23 +43,23 @@ void instr_0F00_1_reg(int32_t r) { void instr_0F00_2_mem(int32_t addr) { // lldt if(!protected_mode[0] || vm86_mode()) trigger_ud(); - if(cpl[0]) trigger_gp(0); + if(cpl[0]) { trigger_gp_non_raising(0); return; } load_ldt(safe_read16(addr)); } void instr_0F00_2_reg(int32_t r) { if(!protected_mode[0] || vm86_mode()) trigger_ud(); - if(cpl[0]) trigger_gp(0); + if(cpl[0]) { trigger_gp_non_raising(0); return; } load_ldt(read_reg16(r)); } void instr_0F00_3_mem(int32_t addr) { // ltr if(!protected_mode[0] || vm86_mode()) trigger_ud(); - if(cpl[0]) trigger_gp(0); + if(cpl[0]) { trigger_gp_non_raising(0); return; } load_tr(safe_read16(addr)); } void instr_0F00_3_reg(int32_t r) { if(!protected_mode[0] || vm86_mode()) trigger_ud(); - if(cpl[0]) trigger_gp(0); + if(cpl[0]) { trigger_gp_non_raising(0); return; } load_tr(read_reg16(r)); } void instr_0F00_4_mem(int32_t addr) { @@ -99,7 +99,7 @@ void instr_0F01_1_mem(int32_t addr) { void instr_0F01_2_reg(int32_t r) { trigger_ud(); } void instr_0F01_2_mem(int32_t addr) { // lgdt - if(cpl[0]) trigger_gp(0); + if(cpl[0]) { trigger_gp_non_raising(0); return; } int32_t size = safe_read16(addr); int32_t offset = safe_read32s(addr + 2); int32_t mask = is_osize_32() ? -1 : 0x00FFFFFF; @@ -109,7 +109,7 @@ void instr_0F01_2_mem(int32_t addr) { void instr_0F01_3_reg(int32_t r) { trigger_ud(); } void instr_0F01_3_mem(int32_t addr) { // lidt - if(cpl[0]) trigger_gp(0); + if(cpl[0]) { trigger_gp_non_raising(0); return; } int32_t size = safe_read16(addr); int32_t offset = safe_read32s(addr + 2); int32_t mask = is_osize_32() ? -1 : 0x00FFFFFF; @@ -137,18 +137,18 @@ void lmsw(int32_t new_cr0) { set_cr0(new_cr0); } void instr_0F01_6_reg(int32_t r) { - if(cpl[0]) trigger_gp(0); + if(cpl[0]) { trigger_gp_non_raising(0); return; } lmsw(read_reg16(r)); } void instr_0F01_6_mem(int32_t addr) { - if(cpl[0]) trigger_gp(0); + if(cpl[0]) { trigger_gp_non_raising(0); return; } lmsw(safe_read16(addr)); } void instr_0F01_7_reg(int32_t r) { trigger_ud(); } void instr_0F01_7_mem(int32_t addr) { // invlpg - if(cpl[0]) trigger_gp(0); + if(cpl[0]) { trigger_gp_non_raising(0); return; } invlpg(addr); } @@ -166,7 +166,7 @@ void instr_0F06() { if(cpl[0]) { dbg_log("clts #gp"); - trigger_gp(0); + trigger_gp_non_raising(0); } else { @@ -185,9 +185,12 @@ void instr_0F09() { if(cpl[0]) { dbg_log("wbinvd #gp"); - trigger_gp(0); + trigger_gp_non_raising(0); + } + else + { + // wbinvd } - // wbinvd } @@ -450,7 +453,8 @@ void instr_0F20(int32_t r, int32_t creg) { if(cpl[0]) { - trigger_gp(0); + trigger_gp_non_raising(0); + return; } switch(creg) @@ -477,7 +481,8 @@ void instr_0F20(int32_t r, int32_t creg) { void instr_0F21(int32_t r, int32_t dreg_index) { if(cpl[0]) { - trigger_gp(0); + trigger_gp_non_raising(0); + return; } if(dreg_index == 4 || dreg_index == 5) @@ -503,7 +508,8 @@ void instr_0F22(int32_t r, int32_t creg) { if(cpl[0]) { - trigger_gp(0); + trigger_gp_non_raising(0); + return; } int32_t data = read_reg32(r); @@ -537,7 +543,8 @@ void instr_0F22(int32_t r, int32_t creg) { if(data & (1 << 11 | 1 << 12 | 1 << 15 | 1 << 16 | 1 << 19 | 0xFFC00000)) { dbg_log("trigger_gp: Invalid cr4 bit"); - trigger_gp(0); + trigger_gp_non_raising(0); + return; } if((cr[4] ^ data) & (CR4_PGE | CR4_PSE)) @@ -564,7 +571,8 @@ void instr_0F22(int32_t r, int32_t creg) { void instr_0F23(int32_t r, int32_t dreg_index) { if(cpl[0]) { - trigger_gp(0); + trigger_gp_non_raising(0); + return; } if(dreg_index == 4 || dreg_index == 5) @@ -687,7 +695,8 @@ void instr_0F30() { if(cpl[0]) { - trigger_gp(0); + trigger_gp_non_raising(0); + return; } int32_t index = reg32s[ECX]; @@ -766,7 +775,7 @@ void instr_0F31() { } else { - trigger_gp(0); + trigger_gp_non_raising(0); } } @@ -774,7 +783,8 @@ void instr_0F32() { // rdmsr - read maschine specific register if(cpl[0]) { - trigger_gp(0); + trigger_gp_non_raising(0); + return; } int32_t index = reg32s[ECX]; @@ -869,7 +879,8 @@ void instr_0F34() { if(!protected_mode[0] || seg == 0) { - trigger_gp(0); + trigger_gp_non_raising(0); + return; } if(CPU_LOG_VERBOSE) @@ -907,7 +918,8 @@ void instr_0F35() { if(!protected_mode[0] || cpl[0] || seg == 0) { - trigger_gp(0); + trigger_gp_non_raising(0); + return; } if(CPU_LOG_VERBOSE) @@ -2066,7 +2078,8 @@ void instr_0FAE_2_mem(int32_t addr) { { dbg_log("Invalid mxcsr bits: %x", (new_mxcsr & ~MXCSR_MASK)); assert(false); - trigger_gp(0); + trigger_gp_non_raising(0); + return; } *mxcsr = new_mxcsr; } diff --git a/src/native/misc_instr.c b/src/native/misc_instr.c index 2ae6cf47..8b551fb6 100644 --- a/src/native/misc_instr.c +++ b/src/native/misc_instr.c @@ -389,7 +389,8 @@ void fxrstor(uint32_t addr) if(new_mxcsr & ~MXCSR_MASK) { dbg_log("#gp Invalid mxcsr bits"); - trigger_gp(0); + trigger_gp_non_raising(0); + return; } *fpu_control_word = safe_read16(addr + 0); diff --git a/tests/nasm/jmp_near.asm b/tests/nasm/jmp_near.asm index 46d1c8ff..e1f7aca8 100644 --- a/tests/nasm/jmp_near.asm +++ b/tests/nasm/jmp_near.asm @@ -14,6 +14,7 @@ align 0x10000 ; force a #gp if the code section is re-entered mov eax, -1 mov cr4, eax + hlt ok: mov byte [re_entered], 1 diff --git a/tests/nasm/loop.asm b/tests/nasm/loop.asm index b24245ed..55dc5228 100644 --- a/tests/nasm/loop.asm +++ b/tests/nasm/loop.asm @@ -14,6 +14,7 @@ align 0x10000 ; force a #gp if the code section is re-entered mov eax, -1 mov cr4, eax + hlt ok: mov byte [re_entered], 1 diff --git a/tests/nasm/run.js b/tests/nasm/run.js index da2ae418..7e4f020d 100755 --- a/tests/nasm/run.js +++ b/tests/nasm/run.js @@ -277,8 +277,11 @@ else { process.exit(1); } - if(exception === "DE") + if(exception === "DE" || exception === "GP") { + // XXX: On gdb execution is stopped at this point. On v86 we + // currently don't have this ability, so we record the exception + // and continue execution recorded_exceptions.push(exception); return true; } From bbd67d71b188a8ff723520168cd471944bea7cb3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 23 Jul 2018 12:43:31 -0600 Subject: [PATCH 1068/2137] Flip the return value of switch_seg --- src/cpu.js | 62 ++++++++++++++++++------------------ src/native/instructions.c | 14 ++++---- src/native/instructions_0f.c | 8 ++--- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index 4277bf49..42fa2b39 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -630,7 +630,7 @@ CPU.prototype.reset = function() this.instruction_pointer[0] = 0xFFFF0; this.switch_cs_real_mode(0xF000); - if(this.switch_seg(reg_ss, 0x30)) dbg_assert(false); + if(!this.switch_seg(reg_ss, 0x30)) dbg_assert(false); this.reg16[reg_sp] = 0x100; if(this.devices.virtio) @@ -1650,7 +1650,7 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, ha this.flags[0] &= ~flag_vm & ~flag_rf; - if(this.switch_seg(reg_ss, new_ss)) dbg_assert(false); // XXX + if(!this.switch_seg(reg_ss, new_ss)) dbg_assert(false); // XXX this.set_stack_reg(new_esp); if(old_flags & flag_vm) @@ -1735,10 +1735,10 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, ha if(old_flags & flag_vm) { if( - this.switch_seg(reg_gs, 0) || - this.switch_seg(reg_fs, 0) || - this.switch_seg(reg_ds, 0) || - this.switch_seg(reg_es, 0) + !this.switch_seg(reg_gs, 0) || + !this.switch_seg(reg_fs, 0) || + !this.switch_seg(reg_ds, 0) || + !this.switch_seg(reg_es, 0) ) { // can't fail @@ -1904,10 +1904,10 @@ CPU.prototype.iret = function(is_16) this.instruction_pointer[0] = (new_eip & 0xFFFF) + this.get_seg(reg_cs) | 0; if( - this.switch_seg(reg_es, new_es) || - this.switch_seg(reg_ds, new_ds) || - this.switch_seg(reg_fs, new_fs) || - this.switch_seg(reg_gs, new_gs) + !this.switch_seg(reg_es, new_es) || + !this.switch_seg(reg_ds, new_ds) || + !this.switch_seg(reg_fs, new_fs) || + !this.switch_seg(reg_gs, new_gs) ) { // XXX: Should be checked before side effects @@ -1917,7 +1917,7 @@ CPU.prototype.iret = function(is_16) this.adjust_stack_reg(9 * 4); // 9 dwords: eip, cs, flags, esp, ss, es, ds, fs, gs this.reg32s[reg_esp] = temp_esp; - if(this.switch_seg(reg_ss, temp_ss)) dbg_assert(false); // XXX + if(!this.switch_seg(reg_ss, temp_ss)) dbg_assert(false); // XXX this.cpl[0] = 3; this.cpl_changed(); @@ -2033,7 +2033,7 @@ CPU.prototype.iret = function(is_16) //dbg_log("outer privilege return: from=" + this.cpl[0] + " to=" + info.rpl + " ss:esp=" + h(temp_ss, 4) + ":" + h(temp_esp >>> 0, 8), LOG_CPU); - if(this.switch_seg(reg_ss, temp_ss)) dbg_assert(false); // XXX + if(!this.switch_seg(reg_ss, temp_ss)) dbg_assert(false); // XXX this.set_stack_reg(temp_esp); @@ -2046,7 +2046,7 @@ CPU.prototype.iret = function(is_16) // XXX: Set segment to 0 if it's not usable in the new cpl // XXX: Use cached segment information //var ds_info = this.lookup_segment_selector(this.sreg[reg_ds]); - //if(this.cpl[0] > ds_info.dpl && (!ds_info.is_executable || !ds_info.dc_bit)) if(this.switch_seg(reg_ds, 0)) ...; + //if(this.cpl[0] > ds_info.dpl && (!ds_info.is_executable || !ds_info.dc_bit)) if(!this.switch_seg(reg_ds, 0)) ...; // ... } else if(info.rpl === this.cpl[0]) @@ -2202,7 +2202,7 @@ CPU.prototype.far_return = function(eip, selector, stack_adjust) this.cpl_changed(); // XXX: This failure should be checked before side effects - if(this.switch_seg(reg_ss, temp_ss)) dbg_assert(false); + if(!this.switch_seg(reg_ss, temp_ss)) dbg_assert(false); this.set_stack_reg(temp_esp + stack_adjust); //if(this.is_osize_32()) @@ -2429,7 +2429,7 @@ CPU.prototype.far_jump = function(eip, selector, is_call) this.update_cs_size(cs_info.size); // XXX: Should be checked before side effects - if(this.switch_seg(reg_ss, new_ss)) dbg_assert(false); + if(!this.switch_seg(reg_ss, new_ss)) dbg_assert(false); this.set_stack_reg(new_esp); //dbg_log("parameter_count=" + parameter_count); @@ -2814,11 +2814,11 @@ CPU.prototype.do_task_switch = function(selector, error_code) this.reg32s[reg_edi] = this.safe_read32s(new_tsr_offset + TSR_EDI); if( - this.switch_seg(reg_es, this.safe_read16(new_tsr_offset + TSR_ES)) || - this.switch_seg(reg_ss, this.safe_read16(new_tsr_offset + TSR_SS)) || - this.switch_seg(reg_ds, this.safe_read16(new_tsr_offset + TSR_DS)) || - this.switch_seg(reg_fs, this.safe_read16(new_tsr_offset + TSR_FS)) || - this.switch_seg(reg_gs, this.safe_read16(new_tsr_offset + TSR_GS)) + !this.switch_seg(reg_es, this.safe_read16(new_tsr_offset + TSR_ES)) || + !this.switch_seg(reg_ss, this.safe_read16(new_tsr_offset + TSR_SS)) || + !this.switch_seg(reg_ds, this.safe_read16(new_tsr_offset + TSR_DS)) || + !this.switch_seg(reg_fs, this.safe_read16(new_tsr_offset + TSR_FS)) || + !this.switch_seg(reg_gs, this.safe_read16(new_tsr_offset + TSR_GS)) ) { // XXX: Should be checked before side effects @@ -3297,7 +3297,7 @@ CPU.prototype.lookup_segment_selector = function(selector) }; /** - * Returns true if changing was aborted due to an exception + * Returns false if changing was aborted due to an exception * * @param {number} reg * @param {number} selector @@ -3317,7 +3317,7 @@ CPU.prototype.switch_seg = function(reg, selector) { this.stack_size_32[0] = +false; } - return false; + return true; } var info = this.lookup_segment_selector(selector); @@ -3329,7 +3329,7 @@ CPU.prototype.switch_seg = function(reg, selector) dbg_log("#GP for loading 0 in SS sel=" + h(selector, 4), LOG_CPU); dbg_trace(LOG_CPU); this.trigger_gp_non_raising(0); - return true; + return false; } if(!info.is_valid || @@ -3341,7 +3341,7 @@ CPU.prototype.switch_seg = function(reg, selector) dbg_log("#GP for loading invalid in SS sel=" + h(selector, 4), LOG_CPU); dbg_trace(LOG_CPU); this.trigger_gp_non_raising(selector & ~3); - return true; + return false; } if(!info.is_present) @@ -3349,7 +3349,7 @@ CPU.prototype.switch_seg = function(reg, selector) dbg_log("#SS for loading non-present in SS sel=" + h(selector, 4), LOG_CPU); dbg_trace(LOG_CPU); this.trigger_ss(selector & ~3); - return true; + return false; } this.stack_size_32[0] = info.size; @@ -3368,7 +3368,7 @@ CPU.prototype.switch_seg = function(reg, selector) //dbg_trace(LOG_CPU); this.sreg[reg] = selector; this.segment_is_null[reg] = 1; - return false; + return true; } if(!info.is_valid || @@ -3382,7 +3382,7 @@ CPU.prototype.switch_seg = function(reg, selector) this.debug.dump_regs(); dbg_trace(LOG_CPU); this.trigger_gp_non_raising(selector & ~3); - return true; + return false; } if(!info.is_present) @@ -3390,7 +3390,7 @@ CPU.prototype.switch_seg = function(reg, selector) dbg_log("#NP for loading not-present in seg " + reg + " sel=" + h(selector, 4), LOG_CPU); dbg_trace(LOG_CPU); this.trigger_np(selector & ~3); - return true; + return false; } } @@ -3401,7 +3401,7 @@ CPU.prototype.switch_seg = function(reg, selector) this.segment_offsets[reg] = info.base; this.sreg[reg] = selector; - return false; + return true; }; CPU.prototype.load_tr = function(selector) @@ -3677,7 +3677,7 @@ CPU.prototype.lss16 = function(addr, reg, seg) var new_reg = this.safe_read16(addr), new_seg = this.safe_read16(addr + 2 | 0); - if(this.switch_seg(seg, new_seg)) return; + if(!this.switch_seg(seg, new_seg)) return; this.reg16[reg] = new_reg; }; @@ -3687,7 +3687,7 @@ CPU.prototype.lss32 = function(addr, reg, seg) var new_reg = this.safe_read32s(addr), new_seg = this.safe_read16(addr + 4 | 0); - if(this.switch_seg(seg, new_seg)) return; + if(!this.switch_seg(seg, new_seg)) return; this.reg32s[reg] = new_reg; }; diff --git a/src/native/instructions.c b/src/native/instructions.c index ed846cd6..e6d90a3e 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -34,11 +34,11 @@ void instr32_05(int32_t imm32) { reg32s[EAX] = add32(reg32s[EAX], imm32); } void instr16_06() { push16(sreg[ES]); } void instr32_06() { push32(sreg[ES]); } void instr16_07() { - if(switch_seg(ES, safe_read16(get_stack_pointer(0)))) return; + if(!switch_seg(ES, safe_read16(get_stack_pointer(0)))) return; adjust_stack_reg(2); } void instr32_07() { - if(switch_seg(ES, safe_read32s(get_stack_pointer(0)) & 0xFFFF)) return; + if(!switch_seg(ES, safe_read32s(get_stack_pointer(0)) & 0xFFFF)) return; adjust_stack_reg(4); } @@ -76,13 +76,13 @@ void instr32_15(int32_t imm32) { reg32s[EAX] = adc32(reg32s[EAX], imm32); } void instr16_16() { push16(sreg[SS]); } void instr32_16() { push32(sreg[SS]); } void instr16_17() { - if(switch_seg(SS, safe_read16(get_stack_pointer(0)))) return; + if(!switch_seg(SS, safe_read16(get_stack_pointer(0)))) return; adjust_stack_reg(2); //clear_prefixes(); //cycle_internal(); } void instr32_17() { - if(switch_seg(SS, safe_read32s(get_stack_pointer(0)) & 0xFFFF)) return; + if(!switch_seg(SS, safe_read32s(get_stack_pointer(0)) & 0xFFFF)) return; adjust_stack_reg(4); //clear_prefixes(); //cycle_internal(); @@ -102,11 +102,11 @@ void instr32_1D(int32_t imm32) { reg32s[EAX] = sbb32(reg32s[EAX], imm32); } void instr16_1E() { push16(sreg[DS]); } void instr32_1E() { push32(sreg[DS]); } void instr16_1F() { - if(switch_seg(DS, safe_read16(get_stack_pointer(0)))) return; + if(!switch_seg(DS, safe_read16(get_stack_pointer(0)))) return; adjust_stack_reg(2); } void instr32_1F() { - if(switch_seg(DS, safe_read32s(get_stack_pointer(0)) & 0xFFFF)) return; + if(!switch_seg(DS, safe_read32s(get_stack_pointer(0)) & 0xFFFF)) return; adjust_stack_reg(4); } @@ -466,7 +466,7 @@ void instr_8E_helper(int32_t data, int32_t mod) { if(mod == ES || mod == SS || mod == DS || mod == FS || mod == GS) { - if(switch_seg(mod, data)) return; + if(!switch_seg(mod, data)) return; if(mod == SS) { diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index db24c7b3..d5a1d87f 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2009,11 +2009,11 @@ void instr_0F9F_mem(int32_t addr, int32_t unused) { setcc_mem(!test_le(), addr); void instr16_0FA0() { push16(sreg[FS]); } void instr32_0FA0() { push32(sreg[FS]); } void instr16_0FA1() { - if(switch_seg(FS, safe_read16(get_stack_pointer(0)))) return; + if(!switch_seg(FS, safe_read16(get_stack_pointer(0)))) return; adjust_stack_reg(2); } void instr32_0FA1() { - if(switch_seg(FS, safe_read32s(get_stack_pointer(0)) & 0xFFFF)) return; + if(!switch_seg(FS, safe_read32s(get_stack_pointer(0)) & 0xFFFF)) return; adjust_stack_reg(4); } @@ -2038,11 +2038,11 @@ void instr_0FA7() { undefined_instruction(); } void instr16_0FA8() { push16(sreg[GS]); } void instr32_0FA8() { push32(sreg[GS]); } void instr16_0FA9() { - if(switch_seg(GS, safe_read16(get_stack_pointer(0)))) return; + if(!switch_seg(GS, safe_read16(get_stack_pointer(0)))) return; adjust_stack_reg(2); } void instr32_0FA9() { - if(switch_seg(GS, safe_read32s(get_stack_pointer(0)) & 0xFFFF)) return; + if(!switch_seg(GS, safe_read32s(get_stack_pointer(0)) & 0xFFFF)) return; adjust_stack_reg(4); } From 1ee5895c44a7abca08e1ede50c0c71eb33e5c914 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 23 Jul 2018 13:32:38 -0600 Subject: [PATCH 1069/2137] api test: Print error --- tests/api/state.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/api/state.js b/tests/api/state.js index 3ae0b185..ecf9e9ea 100755 --- a/tests/api/state.js +++ b/tests/api/state.js @@ -35,7 +35,11 @@ function run_test(name, config, done) console.log("Saving: %s", name); emulator.save_state(function(error, state) { - console.assert(!error); + if(error) + { + console.error(error); + console.assert(false); + } setTimeout(function() { From a7c25c423ec4acf57a3d56dde154ecc0d6127c98 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 23 Jul 2018 14:07:09 -0600 Subject: [PATCH 1070/2137] nasmtests: Add timeout and clarify --- tests/nasm/run.js | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/tests/nasm/run.js b/tests/nasm/run.js index 7e4f020d..661e5db6 100755 --- a/tests/nasm/run.js +++ b/tests/nasm/run.js @@ -22,6 +22,7 @@ const cluster = require("cluster"); const MAX_PARALLEL_TESTS = +process.env.MAX_PARALLEL_TESTS || 99; const TEST_NAME = process.env.TEST_NAME; +const SINGLE_TEST_TIMEOUT = 10000; const TEST_DIR = __dirname + "/build/"; const DONE_MSG = "DONE"; @@ -202,7 +203,7 @@ else { return; } - waiting_for_test = false; + waiting_to_receive_next_test = false; current_test = test; console.info("Testing", test.img_name); @@ -214,6 +215,11 @@ else { cpu.reset_memory(); cpu.load_multiboot(fs.readFileSync(TEST_DIR + current_test.img_name).buffer); + test_timeout = setTimeout(() => { + console.error("Test " + test.img_name + " timed out after " + (SINGLE_TEST_TIMEOUT / 1000) + " seconds."); + process.exit(2); + }, SINGLE_TEST_TIMEOUT); + if(FORCE_JIT) { cpu.jit_force_generate(cpu.instruction_pointer[0]); @@ -237,8 +243,9 @@ else { let loaded = false; let current_test = undefined; let first_test = undefined; - let waiting_for_test = false; + let waiting_to_receive_next_test = false; let recorded_exceptions = []; + let test_timeout; let emulator = new V86({ autostart: false, @@ -258,7 +265,7 @@ else { emulator.cpu_exception_hook = function(n) { - if(waiting_for_test) + if(waiting_to_receive_next_test) { return true; } @@ -286,7 +293,9 @@ else { return true; } - waiting_for_test = true; + clearTimeout(test_timeout); + + waiting_to_receive_next_test = true; emulator.stop(); if(current_test.fixture.exception !== exception) @@ -309,8 +318,10 @@ else { }; emulator.bus.register("cpu-event-halt", function() { - console.assert(!waiting_for_test); - waiting_for_test = true; + console.assert(!waiting_to_receive_next_test); + waiting_to_receive_next_test = true; + clearTimeout(test_timeout); + emulator.stop(); var cpu = emulator.v86.cpu; From 9bd1e304399637dd91c2e99c2c99e75ad8745b7e Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 23 Jul 2018 17:53:49 -0600 Subject: [PATCH 1071/2137] qemu tests: Re-enable some sse tests and reduce diff between upstream version --- tests/qemu/test-i386.c | 71 +++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 43 deletions(-) diff --git a/tests/qemu/test-i386.c b/tests/qemu/test-i386.c index 422308ed..889e8c0b 100644 --- a/tests/qemu/test-i386.c +++ b/tests/qemu/test-i386.c @@ -2081,7 +2081,6 @@ void test_exceptions(void) #endif } - #if !defined(__x86_64__) /* specific precise single step test */ void sig_trap_handler(int sig, siginfo_t *info, void *puc) @@ -2281,8 +2280,8 @@ static void test_enter(void) #ifdef TEST_SSE -typedef int __m64 __attribute__ ((__mode__ (__V2SI__))); -typedef float __m128 __attribute__ ((__mode__(__V4SF__))); +typedef int __m64 __attribute__ ((vector_size(8))); +typedef float __m128 __attribute__ ((vector_size(16))); typedef union { double d[2]; @@ -2299,8 +2298,7 @@ static uint64_t __attribute__((aligned(16))) test_values[4][2] = { { 0x0f76255a085427f8, 0xc233e9e8c4c9439a }, }; -#define SSE_OP(op) {} -/* \ +#define SSE_OP(op)\ {\ asm volatile (#op " %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\ printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\ @@ -2309,10 +2307,8 @@ static uint64_t __attribute__((aligned(16))) test_values[4][2] = { b.q[1], b.q[0],\ r.q[1], r.q[0]);\ } -*/ -#define SSE_OP2(op) {} -/* \ +#define SSE_OP2(op)\ {\ int i;\ for(i=0;i<2;i++) {\ @@ -2323,7 +2319,6 @@ static uint64_t __attribute__((aligned(16))) test_values[4][2] = { SSE_OP(op);\ }\ } -*/ #define MMX_OP2(op)\ {\ @@ -2342,7 +2337,7 @@ static uint64_t __attribute__((aligned(16))) test_values[4][2] = { } -#define SHUF_OP(op, ib)\ +#define SHUF_OP_MMX(op, ib)\ {\ int i;\ for(i=0;i<2;i++) {\ @@ -2358,7 +2353,6 @@ static uint64_t __attribute__((aligned(16))) test_values[4][2] = { }\ } -/* #define SHUF_OP(op, ib)\ {\ a.q[0] = test_values[0][0];\ @@ -2373,7 +2367,6 @@ static uint64_t __attribute__((aligned(16))) test_values[4][2] = { ib,\ r.q[1], r.q[0]);\ } -*/ #define PSHUF_OP(op, ib)\ {\ @@ -2391,7 +2384,7 @@ static uint64_t __attribute__((aligned(16))) test_values[4][2] = { } // To use mm0-7 registers instead of xmm registers -#define SHIFT_IM(op, ib) \ +#define SHIFT_IM_MMX(op, ib) \ {\ int i;\ for(i=0;i<2;i++) {\ @@ -2405,7 +2398,6 @@ static uint64_t __attribute__((aligned(16))) test_values[4][2] = { }\ } -/* #define SHIFT_IM(op, ib)\ {\ int i;\ @@ -2420,13 +2412,12 @@ static uint64_t __attribute__((aligned(16))) test_values[4][2] = { r.q[1], r.q[0]);\ }\ } -*/ // To use mm0-7 registers instead of xmm registers -#define SHIFT_OP(op, ib)\ +#define SHIFT_OP_MMX(op, ib)\ {\ int i;\ - SHIFT_IM(op, ib);\ + SHIFT_IM_MMX(op, ib);\ for(i=0;i<2;i++) {\ a.q[0] = test_values[2*i][0];\ b.q[0] = ib;\ @@ -2440,8 +2431,8 @@ static uint64_t __attribute__((aligned(16))) test_values[4][2] = { }\ } -/* #define SHIFT_OP(op, ib)\ +SHIFT_OP_MMX(op, ib)\ {\ int i;\ SHIFT_IM(op, ib);\ @@ -2458,7 +2449,6 @@ static uint64_t __attribute__((aligned(16))) test_values[4][2] = { r.q[1], r.q[0]);\ }\ } -*/ #define MOVMSK(op)\ {\ @@ -2484,16 +2474,16 @@ SSE_OP(a ## sd); #define SSE_COMI(op, field)\ {\ - unsigned int eflags;\ + unsigned long eflags;\ XMMReg a, b;\ a.field[0] = a1;\ b.field[0] = b1;\ asm volatile (#op " %2, %1\n"\ "pushf\n"\ "pop %0\n"\ - : "=m" (eflags)\ + : "=rm" (eflags)\ : "x" (a.dq), "x" (b.dq));\ - printf("%-9s: a=%f b=%f cc=%04x\n",\ + printf("%-9s: a=%f b=%f cc=%04lx\n",\ #op, a1, b1,\ eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));\ } @@ -2648,41 +2638,40 @@ void test_sse(void) MMX_OP2(pcmpeqw); MMX_OP2(pcmpeqd); - // MMX_OP2(paddq); + MMX_OP2(paddq); MMX_OP2(pmullw); MMX_OP2(psubusb); MMX_OP2(psubusw); - // MMX_OP2(pminub); + MMX_OP2(pminub); MMX_OP2(pand); MMX_OP2(paddusb); MMX_OP2(paddusw); - // MMX_OP2(pmaxub); + MMX_OP2(pmaxub); MMX_OP2(pandn); - // MMX_OP2(pmulhuw); + MMX_OP2(pmulhuw); MMX_OP2(pmulhw); MMX_OP2(psubsb); MMX_OP2(psubsw); - // MMX_OP2(pminsw); + MMX_OP2(pminsw); MMX_OP2(por); MMX_OP2(paddsb); MMX_OP2(paddsw); - // MMX_OP2(pmaxsw); + MMX_OP2(pmaxsw); MMX_OP2(pxor); - // MMX_OP2(pmuludq); + MMX_OP2(pmuludq); MMX_OP2(pmaddwd); - // MMX_OP2(psadbw); + MMX_OP2(psadbw); MMX_OP2(psubb); MMX_OP2(psubw); MMX_OP2(psubd); - // MMX_OP2(psubq); + MMX_OP2(psubq); MMX_OP2(paddb); MMX_OP2(paddw); MMX_OP2(psrlw); MMX_OP2(paddd); - /* MMX_OP2(pavgb); MMX_OP2(pavgw); @@ -2750,17 +2739,15 @@ void test_sse(void) SSE_OP2(unpckhps); SSE_OP2(unpckhpd); - SHUF_OP(shufps, 0x78); - SHUF_OP(shufpd, 0x02); - */ - SHUF_OP(pshufw, 0x78); - SHUF_OP(pshufw, 0x02); - /* + // TODO: These instructions pull in some other unimplemented instructions on v86 + //SHUF_OP(shufps, 0x78); + //SHUF_OP(shufpd, 0x02); + SHUF_OP_MMX(pshufw, 0x78); + SHUF_OP_MMX(pshufw, 0x02); PSHUF_OP(pshufd, 0x78); PSHUF_OP(pshuflw, 0x78); PSHUF_OP(pshufhw, 0x78); - */ SHIFT_OP(psrlw, 7); SHIFT_OP(psrlw, 16); @@ -2781,7 +2768,6 @@ void test_sse(void) SHIFT_OP(psllq, 7); SHIFT_OP(psllq, 32); - /* SHIFT_IM(psrldq, 16); SHIFT_IM(psrldq, 7); SHIFT_IM(pslldq, 16); @@ -2789,7 +2775,6 @@ void test_sse(void) MOVMSK(movmskps); MOVMSK(movmskpd); - */ /* FPU specific ops */ /* @@ -2911,7 +2896,7 @@ void test_sse(void) */ /* XXX: test PNI insns */ #if 0 - // SSE_OP2(movshdup); + SSE_OP2(movshdup); #endif asm volatile ("emms"); } @@ -3216,7 +3201,7 @@ int main(int argc, char **argv) test_conv(); #ifdef TEST_SSE test_sse(); - //test_fxsave(); + test_fxsave(); #endif test_page_boundaries(); return 0; From 02a7bbb8f7e2703ccd6cf7ecfd68a244c4e09ab8 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 23 Jul 2018 17:58:03 -0600 Subject: [PATCH 1072/2137] Implement hintable nops --- gen/x86_table.js | 12 ++++++------ src/native/instructions_0f.c | 27 +++++++++++++++------------ src/rust/jit_instructions.rs | 28 +++++++++++++++++++++++++++- 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index f5946310..a3598932 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -301,12 +301,12 @@ const encodings = [ { opcode: 0x0F0F, skip: 1 }, { opcode: 0x0F18, only_mem: 1, e: 1, }, - { opcode: 0x0F19, skip: 1 }, - { opcode: 0x0F1A, skip: 1 }, - { opcode: 0x0F1B, skip: 1 }, - { opcode: 0x0F1C, skip: 1 }, - { opcode: 0x0F1D, skip: 1 }, - { opcode: 0x0F1E, skip: 1 }, + { opcode: 0x0F19, custom: 1, e: 1, }, + { opcode: 0x0F1A, custom: 1, e: 1, }, + { opcode: 0x0F1B, custom: 1, e: 1, }, + { opcode: 0x0F1C, custom: 1, e: 1, }, + { opcode: 0x0F1D, custom: 1, e: 1, }, + { opcode: 0x0F1E, custom: 1, e: 1, }, { opcode: 0x0F1F, custom: 1, e: 1, }, { opcode: 0x0F20, ignore_mod: 1, e: 1, skip: 1, block_boundary: 1, }, // mov reg, creg diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index d5a1d87f..5603e2d2 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -435,18 +435,21 @@ void instr_0F18_mem(int32_t addr, int32_t r) { // nop for us } -void instr_0F19() { unimplemented_sse(); } -void instr_0F1A() { unimplemented_sse(); } -void instr_0F1B() { unimplemented_sse(); } -void instr_0F1C() { unimplemented_sse(); } -void instr_0F1D() { unimplemented_sse(); } -void instr_0F1E() { unimplemented_sse(); } -void instr_0F1F_reg(int32_t r1, int32_t r2) { - // multi-byte nop -} -void instr_0F1F_mem(int32_t addr, int32_t r) { - // multi-byte nop -} +// hintable nops +void instr_0F19_reg(int32_t r1, int32_t r2) { } +void instr_0F19_mem(int32_t addr, int32_t r) { } +void instr_0F1A_reg(int32_t r1, int32_t r2) { } +void instr_0F1A_mem(int32_t addr, int32_t r) { } +void instr_0F1B_reg(int32_t r1, int32_t r2) { } +void instr_0F1B_mem(int32_t addr, int32_t r) { } +void instr_0F1C_reg(int32_t r1, int32_t r2) { } +void instr_0F1C_mem(int32_t addr, int32_t r) { } +void instr_0F1D_reg(int32_t r1, int32_t r2) { } +void instr_0F1D_mem(int32_t addr, int32_t r) { } +void instr_0F1E_reg(int32_t r1, int32_t r2) { } +void instr_0F1E_mem(int32_t addr, int32_t r) { } +void instr_0F1F_reg(int32_t r1, int32_t r2) { } +void instr_0F1F_mem(int32_t addr, int32_t r) { } void instr_0F20(int32_t r, int32_t creg) { diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 2884f0ab..322e6371 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -5,6 +5,7 @@ use cpu_context::CpuContext; use global_pointers; use jit::JitContext; use jit::{GEN_LOCAL_SCRATCH0, GEN_LOCAL_SCRATCH1}; +use modrm; use prefix::SEG_PREFIX_ZERO; use prefix::{PREFIX_66, PREFIX_67, PREFIX_F2, PREFIX_F3}; use regs::{AX, BP, BX, CX, DI, DX, SI, SP}; @@ -445,8 +446,33 @@ pub fn instr32_0F8E_jit(_ctx: &mut JitContext, _imm: u32) {} pub fn instr32_0F8F_jit(_ctx: &mut JitContext, _imm: u32) {} pub fn instr_90_jit(_ctx: &mut JitContext) {} + +pub fn instr_0F19_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) { + modrm::skip(ctx.cpu, modrm_byte); +} +pub fn instr_0F19_reg_jit(_ctx: &mut JitContext, _r1: u32, _r2: u32) {} +pub fn instr_0F1A_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) { + modrm::skip(ctx.cpu, modrm_byte); +} +pub fn instr_0F1A_reg_jit(_ctx: &mut JitContext, _r1: u32, _r2: u32) {} +pub fn instr_0F1B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) { + modrm::skip(ctx.cpu, modrm_byte); +} +pub fn instr_0F1B_reg_jit(_ctx: &mut JitContext, _r1: u32, _r2: u32) {} +pub fn instr_0F1C_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) { + modrm::skip(ctx.cpu, modrm_byte); +} +pub fn instr_0F1C_reg_jit(_ctx: &mut JitContext, _r1: u32, _r2: u32) {} +pub fn instr_0F1D_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) { + modrm::skip(ctx.cpu, modrm_byte); +} +pub fn instr_0F1D_reg_jit(_ctx: &mut JitContext, _r1: u32, _r2: u32) {} +pub fn instr_0F1E_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) { + modrm::skip(ctx.cpu, modrm_byte); +} +pub fn instr_0F1E_reg_jit(_ctx: &mut JitContext, _r1: u32, _r2: u32) {} pub fn instr_0F1F_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); + modrm::skip(ctx.cpu, modrm_byte); } pub fn instr_0F1F_reg_jit(_ctx: &mut JitContext, _r1: u32, _r2: u32) {} From 510c6c186b07693235c175e9cc82060fdb79a081 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 23 Jul 2018 18:33:53 -0600 Subject: [PATCH 1073/2137] qemu tests: More sse shift tests --- tests/qemu/test-i386.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/tests/qemu/test-i386.c b/tests/qemu/test-i386.c index 889e8c0b..79da1a15 100644 --- a/tests/qemu/test-i386.c +++ b/tests/qemu/test-i386.c @@ -2749,29 +2749,42 @@ void test_sse(void) PSHUF_OP(pshuflw, 0x78); PSHUF_OP(pshufhw, 0x78); + SHIFT_OP(psrlw, 0); SHIFT_OP(psrlw, 7); SHIFT_OP(psrlw, 16); + SHIFT_OP(psraw, 0); SHIFT_OP(psraw, 7); SHIFT_OP(psraw, 16); + SHIFT_OP(psllw, 0); SHIFT_OP(psllw, 7); SHIFT_OP(psllw, 16); + SHIFT_OP(psrld, 0); SHIFT_OP(psrld, 7); SHIFT_OP(psrld, 32); + SHIFT_OP(psrad, 0); SHIFT_OP(psrad, 7); SHIFT_OP(psrad, 32); + SHIFT_OP(pslld, 0); SHIFT_OP(pslld, 7); SHIFT_OP(pslld, 32); + SHIFT_OP(psrlq, 0); SHIFT_OP(psrlq, 7); SHIFT_OP(psrlq, 32); + SHIFT_OP(psllq, 0); SHIFT_OP(psllq, 7); SHIFT_OP(psllq, 32); - SHIFT_IM(psrldq, 16); + // byte-wise shifts + SHIFT_IM(psrldq, 0); SHIFT_IM(psrldq, 7); - SHIFT_IM(pslldq, 16); + SHIFT_IM(psrldq, 11); + SHIFT_IM(psrldq, 16); SHIFT_IM(pslldq, 7); + SHIFT_IM(pslldq, 0); + SHIFT_IM(pslldq, 11); + SHIFT_IM(pslldq, 16); MOVMSK(movmskps); MOVMSK(movmskpd); From e3af4f9232635b071274da16f3fda55af4bd07b9 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 23 Jul 2018 18:34:55 -0600 Subject: [PATCH 1074/2137] Fix psrldq --- src/native/instructions_0f.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 5603e2d2..22df2039 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1723,7 +1723,7 @@ void instr_660F73_3_reg(int32_t r, int32_t imm8) { if(shift <= 63) { - result.u64[0] = destination.u64[0] >> shift | destination.u64[1] >> (64 - shift); + result.u64[0] = destination.u64[0] >> shift | destination.u64[1] << (64 - shift); result.u64[1] = destination.u64[1] >> shift; } else if(shift <= 127) From c108aaaaddfe29469fa474756f125896b3b53c90 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 23 Jul 2018 21:08:33 -0600 Subject: [PATCH 1075/2137] Extend qemu paging tests with cross-page page faults --- tests/qemu/test-i386.c | 272 ++++++++++++++++++++++++++++++++--------- 1 file changed, 212 insertions(+), 60 deletions(-) diff --git a/tests/qemu/test-i386.c b/tests/qemu/test-i386.c index 79da1a15..18acc8e5 100644 --- a/tests/qemu/test-i386.c +++ b/tests/qemu/test-i386.c @@ -18,6 +18,7 @@ */ #define _GNU_SOURCE #include "compiler.h" +#include #include #include #include @@ -2976,14 +2977,33 @@ void fatal(char *msg) 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) + uint64_t v1 = 0; + for(size_t i = 0; i < num_bytes && i < 8; i++) { - i--; - printf("%02" PRIx8, buffer[offset + i]); + if(setjmp(jmp_env) == 0) + { + v1 |= (uint64_t)buffer[offset + i] << (i * 8); + } + } + + uint64_t v2 = 0; + for(size_t i = 8; i < num_bytes; i++) + { + if(setjmp(jmp_env) == 0) + { + v2 |= (uint64_t)buffer[offset + i] << ((i - 8) * 8); + } + + } + + if(num_bytes > 8) + { + printf("%-12s: offset=%x value=%08llx%08llx\n", "byte_r", offset, v2, v1); + } + else + { + printf("%-12s: offset=%x value=%llx\n", "byte_r", offset, v1); } - printf("\n"); } uint64_t seq_counter = 0x8070605040302010; @@ -2995,25 +3015,36 @@ uint64_t get_seq64() 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) + uint64_t v = get_seq64(); + if(num_bytes < 8) v &= (1LL << (num_bytes * 8)) - 1; + + for(size_t i = 0; i < num_bytes; i++) { - i--; - uint8_t byte = get_seq64(); - target[offset + i] = byte; - printf("%02" PRIx8, byte); + if(setjmp(jmp_env) == 0) + { + target[offset + i] = (v >> (i * 8 % 64)) & 0xFF; + } + } + + if(num_bytes > 8) + { + printf("%-12s: offset=%x value=%08llx%08llx\n", "byte_w", offset, v, v); + } + else + { + printf("%-12s: offset=%x value=%llx\n", "byte_w", offset, v); } - 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)); \ + if(setjmp(jmp_env) == 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, \ @@ -3024,9 +3055,11 @@ void byte_write_seq(uint8_t* target, uint16_t offset, size_t num_bytes) 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)); \ + if(setjmp(jmp_env) == 0) { \ + asm volatile(INSTR " %0, %1" : \ + "=" CONSTR (chunk) : \ + "m" (*(addr + offset)), "0" (chunk)); \ + } \ printf("%-12s: offset=%x value=%" PRIx ## BITS "\n", \ "chunk" #BITS "_w", \ offset, \ @@ -3042,13 +3075,16 @@ void byte_write_seq(uint8_t* target, uint16_t offset, size_t num_bytes) chunk_read ## BITS(ADDR, OFFSET); #define TEST_CHUNK_WRITE(BITS, ADDR, OFFSET) \ + byte_write_seq(ADDR, OFFSET, (BITS) >> 3); \ 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); \ +#define TEST_CHUNK_READ_WRITE(BITS, ADDR, OFFSET) \ + if(BITS <= 32) { \ + 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) \ @@ -3069,9 +3105,12 @@ 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)); + if(setjmp(jmp_env) == 0) + { + asm volatile("addw %0, %1" : + "=r" (chunk) : + "m" (*(addr + offset)), "0" (chunk)); + } printf("%-12s: offset=%x value=%" PRIx16 "\n", "chunk16_rw", offset, @@ -3081,9 +3120,12 @@ void chunk_read_write16(uint8_t* addr, uint16_t offset) 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)); + if(setjmp(jmp_env) == 0) + { + asm volatile("add %0, %1" : + "=r" (chunk) : + "m" (*(addr + offset)), "0" (chunk)); + } printf("%-12s: offset=%x value=%" PRIx32 "\n", "chunk32_rw", offset, @@ -3103,14 +3145,18 @@ void chunk_read_write128(uint8_t* addr, uint16_t offset) 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) - ); + if(setjmp(jmp_env) == 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, @@ -3123,10 +3169,13 @@ 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) - ); + if(setjmp(jmp_env) == 0) + { + 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, @@ -3135,38 +3184,141 @@ void chunk_write128(uint8_t* addr, uint16_t offset) } #endif -void test_page_boundaries() +void* const TEST_ADDRESS = (void *)0x70000000; +uint8_t* first_page = NULL; +uint8_t* second_page = NULL; +uint8_t* throwaway_page = NULL; + +void setup_pages(int first_page_type, int second_page_type) { - // mmap 2 consecutive pages - uint8_t *const page0 = mmap(NULL, 2 * PAGE_SIZE, - PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + const int prot = PROT_READ | PROT_WRITE; - // 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) + if(first_page_type) { - fatal("mmap"); + // mmap 2 consecutive pages + first_page = mmap(TEST_ADDRESS, 2 * PAGE_SIZE, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + assert(first_page == TEST_ADDRESS); + } + else + { + first_page = NULL; + } + + // throwaway mmap to reduce likelhood of first_page and second_page mapping to consecutive physical frames + throwaway_page = mmap(NULL, PAGE_SIZE, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + assert(throwaway_page != MAP_FAILED && throwaway_page != TEST_ADDRESS && throwaway_page != TEST_ADDRESS + PAGE_SIZE); + + if(second_page_type) + { + second_page = mmap(TEST_ADDRESS + PAGE_SIZE, PAGE_SIZE, prot, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); + assert(second_page == TEST_ADDRESS + PAGE_SIZE); + } + else + { + munmap(TEST_ADDRESS + PAGE_SIZE, PAGE_SIZE); + second_page = NULL; } // Trigger page-faults causing virtual pages to be allocated to physical frames - page0[0] = 0x42; - throwaway[0] = 0x42; - page1[0] = 0x42; + if(first_page != NULL) memset(first_page, 0x42, PAGE_SIZE); + memset(throwaway_page, 0x42, PAGE_SIZE); + if(second_page != NULL) memset(second_page, 0x42, PAGE_SIZE); - TEST_CROSS_PAGE(16, page0); - TEST_CROSS_PAGE(32, page0); + if(first_page_type == PROT_READ) + { + mprotect(first_page, PAGE_SIZE, PROT_READ); + } + + if(second_page_type == PROT_READ) + { + mprotect(second_page, PAGE_SIZE, PROT_READ); + } +} + +void free_pages() +{ + munmap(TEST_ADDRESS, PAGE_SIZE); + munmap(TEST_ADDRESS + PAGE_SIZE, PAGE_SIZE); + munmap(throwaway_page, PAGE_SIZE); +} + +void pagefault_handler(int sig, siginfo_t *info, void *puc) +{ + ucontext_t *uc = puc; + + printf("page fault: addr=0x%08lx err=0x%lx eip=0x%08lx\n", + (unsigned long)info->si_addr, + (long)uc->uc_mcontext.gregs[REG_ERR], + (long)uc->uc_mcontext.gregs[REG_EIP]); + + assert(info->si_addr >= TEST_ADDRESS && info->si_addr < TEST_ADDRESS + 2 * PAGE_SIZE); + + longjmp(jmp_env, 1); +} + +void test_page_boundaries() +{ + const int prot_rw = PROT_READ | PROT_WRITE; + const int prot_ronly = PROT_READ; + + setup_pages(prot_rw, prot_rw); + + TEST_CROSS_PAGE(16, TEST_ADDRESS); + TEST_CROSS_PAGE(32, TEST_ADDRESS); #ifdef TEST_SSE - TEST_CROSS_PAGE(64, page0); - TEST_CROSS_PAGE(128, page0); + TEST_CROSS_PAGE(64, TEST_ADDRESS); + TEST_CROSS_PAGE(128, TEST_ADDRESS); #endif - munmap(page0, PAGE_SIZE); - munmap(page1, PAGE_SIZE); + struct sigaction act; + act.sa_sigaction = pagefault_handler; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_SIGINFO | SA_NODEFER; + sigaction(SIGSEGV, &act, NULL); + + free_pages(); + printf("With non-present page faults in first page:\n"); + setup_pages(0, prot_rw); + + TEST_CROSS_PAGE(16, TEST_ADDRESS); + TEST_CROSS_PAGE(32, TEST_ADDRESS); +#ifdef TEST_SSE + TEST_CROSS_PAGE(64, TEST_ADDRESS); + TEST_CROSS_PAGE(128, TEST_ADDRESS); +#endif + + free_pages(); + printf("With read-only page faults in first page:\n"); + setup_pages(prot_ronly, prot_rw); + + TEST_CROSS_PAGE(16, TEST_ADDRESS); + TEST_CROSS_PAGE(32, TEST_ADDRESS); +#ifdef TEST_SSE + TEST_CROSS_PAGE(64, TEST_ADDRESS); + TEST_CROSS_PAGE(128, TEST_ADDRESS); +#endif + + free_pages(); + printf("With non-present page faults in second page:\n"); + setup_pages(prot_rw, 0); + + TEST_CROSS_PAGE(16, TEST_ADDRESS); + TEST_CROSS_PAGE(32, TEST_ADDRESS); +#ifdef TEST_SSE + TEST_CROSS_PAGE(64, TEST_ADDRESS); + TEST_CROSS_PAGE(128, TEST_ADDRESS); +#endif + + free_pages(); + printf("With read-only page faults in second page:\n"); + setup_pages(prot_rw, prot_ronly); + + TEST_CROSS_PAGE(16, TEST_ADDRESS); + TEST_CROSS_PAGE(32, TEST_ADDRESS); +#ifdef TEST_SSE + TEST_CROSS_PAGE(64, TEST_ADDRESS); + TEST_CROSS_PAGE(128, TEST_ADDRESS); +#endif } extern void *__start_initcall; From 4f03f3334a9237c23b186d3d695c34a8823043cc Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 23 Jul 2018 21:08:56 -0600 Subject: [PATCH 1076/2137] Fix writable_or_pagefault --- src/native/cpu.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/native/cpu.c b/src/native/cpu.c index d8300a15..ac5fbf1e 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -386,17 +386,21 @@ void writable_or_pagefault(int32_t addr, int32_t size) int32_t expect = TLB_VALID; int32_t page = (uint32_t)addr >> 12; - if((tlb_data[page] & mask) == expect) + if((tlb_data[page] & mask) != expect) { do_page_translation(addr, true, user); } - if((addr & 0xFFF) + size - 1 >= 0x1000) + int32_t next_page = (uint32_t)(addr + size - 1) >> 12; + + if(page != next_page) { + assert(next_page == page + 1); + // XXX: possibly out of bounds - if((tlb_data[page + 1] & mask) == expect) + if((tlb_data[next_page] & mask) != expect) { - do_page_translation(addr + size - 1, true, user); + do_page_translation(next_page << 12, true, user); } } } From 6ba82ee31ee5f5ded960c023cc805f80fe3402b0 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 23 Jul 2018 21:09:19 -0600 Subject: [PATCH 1077/2137] Fix safe_write{64,128} at page boundary --- src/native/cpu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/native/cpu.c b/src/native/cpu.c index ac5fbf1e..369098bf 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -1154,6 +1154,7 @@ void safe_write64(int32_t addr, int64_t value) { if((addr & 0xFFF) > (0x1000 - 8)) { + writable_or_pagefault(addr, 8); safe_write32(addr, value); safe_write32(addr + 4, value >> 32); } @@ -1169,6 +1170,7 @@ void safe_write128(int32_t addr, union reg128 value) { if((addr & 0xFFF) > (0x1000 - 16)) { + writable_or_pagefault(addr, 16); safe_write64(addr, value.u64[0]); safe_write64(addr + 8, value.u64[1]); } From ad4c2b72ff7efafc2eee607a90efe70447a8b451 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 23 Jul 2018 21:19:18 -0600 Subject: [PATCH 1078/2137] Use safe_write128 over multiple safe_write32 --- src/native/misc_instr.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/native/misc_instr.c b/src/native/misc_instr.c index 8b551fb6..c0595ec2 100644 --- a/src/native/misc_instr.c +++ b/src/native/misc_instr.c @@ -372,10 +372,7 @@ void fxsave(uint32_t addr) // implementation dependent. for(int32_t i = 0; i < 8; i++) { - 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]); + safe_write128(addr + 160 + (i << 4), reg_xmm[i]); } } From 7d627ac13ae1dd073ce6ab0761189e95508849e3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 24 Jul 2018 13:02:16 -0600 Subject: [PATCH 1079/2137] Make tests a bit more robust --- tests/api/state.js | 2 +- tests/qemu/run-qemu.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/api/state.js b/tests/api/state.js index ecf9e9ea..014648e4 100755 --- a/tests/api/state.js +++ b/tests/api/state.js @@ -54,7 +54,7 @@ function run_test(name, config, done) }, 1000); }, 1000); }); - }, 1000); + }, 5000); } run_test("async cdrom", config_async_cdrom, function() diff --git a/tests/qemu/run-qemu.js b/tests/qemu/run-qemu.js index 7fa26bf2..a18a6937 100755 --- a/tests/qemu/run-qemu.js +++ b/tests/qemu/run-qemu.js @@ -45,7 +45,7 @@ qemu.stdout.on("data", data => { qemu.stdin.write("echo test fini''shed\n"); } - if(ran_command && !finished && qemu_output.includes("test finished\n")) + if(ran_command && !finished && qemu_output.includes("test finished")) { const result_file = path.join(share_dir_9p, "result"); From 848b07a628083edc7b70452b237768107bf44df5 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 24 Jul 2018 13:58:21 -0600 Subject: [PATCH 1080/2137] Skip tests that fail due to qemu bugs --- tests/qemu/test-i386.c | 50 +++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/tests/qemu/test-i386.c b/tests/qemu/test-i386.c index 18acc8e5..3508213e 100644 --- a/tests/qemu/test-i386.c +++ b/tests/qemu/test-i386.c @@ -2968,13 +2968,6 @@ void test_conv(void) } -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) { uint64_t v1 = 0; @@ -3074,26 +3067,34 @@ void byte_write_seq(uint8_t* target, uint16_t offset, size_t num_bytes) byte_write_seq(ADDR, OFFSET, (BITS) >> 3); \ chunk_read ## BITS(ADDR, OFFSET); -#define TEST_CHUNK_WRITE(BITS, ADDR, OFFSET) \ - byte_write_seq(ADDR, OFFSET, (BITS) >> 3); \ - chunk_write ## BITS(ADDR, OFFSET); \ - byte_read(ADDR, OFFSET, (BITS) >> 3); +#define TEST_CHUNK_WRITE(BITS, ADDR, OFFSET) \ + if(!skip_write_test) { \ + byte_write_seq(ADDR, OFFSET, (BITS) >> 3); \ + mask_pf_address = 1; \ + chunk_write ## BITS(ADDR, OFFSET); \ + mask_pf_address = 0; \ + byte_read(ADDR, OFFSET, (BITS) >> 3); \ + } #define TEST_CHUNK_READ_WRITE(BITS, ADDR, OFFSET) \ if(BITS <= 32) { \ byte_write_seq(ADDR, OFFSET, (BITS) >> 3); \ + mask_pf_error = 1; \ + mask_pf_address = 1; \ chunk_read_write ## BITS(ADDR, OFFSET); \ + mask_pf_address = 0; \ + mask_pf_error = 0; \ 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); \ +#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"); @@ -3242,13 +3243,18 @@ void free_pages() munmap(throwaway_page, PAGE_SIZE); } +// XXX: Workarounds for qemu bugs: Can be removed when running tests in kvm mode +int mask_pf_error = 0; +int mask_pf_address = 0; +int skip_write_test = 0; + void pagefault_handler(int sig, siginfo_t *info, void *puc) { ucontext_t *uc = puc; printf("page fault: addr=0x%08lx err=0x%lx eip=0x%08lx\n", - (unsigned long)info->si_addr, - (long)uc->uc_mcontext.gregs[REG_ERR], + (unsigned long)info->si_addr & (mask_pf_address ? ~0xfff : ~0), + (long)uc->uc_mcontext.gregs[REG_ERR] & (mask_pf_error ? ~2 : ~0), (long)uc->uc_mcontext.gregs[REG_EIP]); assert(info->si_addr >= TEST_ADDRESS && info->si_addr < TEST_ADDRESS + 2 * PAGE_SIZE); @@ -3306,7 +3312,9 @@ void test_page_boundaries() TEST_CROSS_PAGE(32, TEST_ADDRESS); #ifdef TEST_SSE TEST_CROSS_PAGE(64, TEST_ADDRESS); + skip_write_test = 1; TEST_CROSS_PAGE(128, TEST_ADDRESS); + skip_write_test = 0; #endif free_pages(); @@ -3317,7 +3325,9 @@ void test_page_boundaries() TEST_CROSS_PAGE(32, TEST_ADDRESS); #ifdef TEST_SSE TEST_CROSS_PAGE(64, TEST_ADDRESS); + skip_write_test = 1; TEST_CROSS_PAGE(128, TEST_ADDRESS); + skip_write_test = 0; #endif } From bdef74eced777a5b1efbde180348f8d37c592317 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 24 Jul 2018 14:40:10 -0600 Subject: [PATCH 1081/2137] Generate code for task_switch_test{,_mmx}, use non-raising exceptions --- gen/generate_interpreter.js | 19 ++ gen/generate_jit.js | 14 + gen/x86_table.js | 494 +++++++++++++++++------------------ src/native/cpu.c | 59 +++-- src/native/cpu.h | 6 +- src/native/instructions.c | 188 +++++++------ src/native/instructions.h | 4 +- src/native/instructions_0f.c | 148 ----------- src/native/sse_instr.c | 27 -- src/rust/codegen.rs | 39 +++ src/rust/global_pointers.rs | 7 + src/rust/regs.rs | 3 + 12 files changed, 466 insertions(+), 542 deletions(-) diff --git a/gen/generate_interpreter.js b/gen/generate_interpreter.js index 224dc712..2a29acfb 100755 --- a/gen/generate_interpreter.js +++ b/gen/generate_interpreter.js @@ -216,7 +216,23 @@ function gen_instruction_body_after_prefix(encodings, size) function gen_instruction_body_after_fixed_g(encoding, size) { + const instruction_prefix = []; const instruction_postfix = encoding.block_boundary ? ["after_block_boundary();"] : []; + + if(encoding.task_switch_test || encoding.sse) + { + instruction_prefix.push( + { + type: "if-else", + if_blocks: [ + { + condition: encoding.sse ? "!task_switch_test_mmx()" : "!task_switch_test()", + body: ["return;"], + } + ], + }); + } + const imm_read = gen_read_imm_call(encoding, size); const instruction_name = make_instruction_name(encoding, size); @@ -244,6 +260,7 @@ function gen_instruction_body_after_fixed_g(encoding, size) // operands are always registers (0f20-0f24) return [].concat( + instruction_prefix, gen_call(instruction_name, ["modrm_byte & 7", "modrm_byte >> 3 & 7"]), instruction_postfix ); @@ -266,6 +283,7 @@ function gen_instruction_body_after_fixed_g(encoding, size) } return [].concat( + instruction_prefix, { type: "if-else", if_blocks: [ @@ -306,6 +324,7 @@ function gen_instruction_body_after_fixed_g(encoding, size) } return [].concat( + instruction_prefix, gen_call(instruction_name, args), instruction_postfix ); diff --git a/gen/generate_jit.js b/gen/generate_jit.js index 18c66f5a..fa62cd01 100755 --- a/gen/generate_jit.js +++ b/gen/generate_jit.js @@ -220,6 +220,15 @@ function gen_instruction_body_after_fixed_g(encoding, size) instruction_postfix.push("*instr_flags |= ::jit::JIT_INSTR_BLOCK_BOUNDARY_FLAG;"); } + const instruction_prefix = []; + + if(encoding.task_switch_test || encoding.sse) + { + instruction_prefix.push( + gen_call(encoding.sse ? "::codegen::gen_task_switch_test_mmx" : "::codegen::gen_task_switch_test", ["ctx"]) + ); + } + const APPEND_NONFAULTING_FLAG = "*instr_flags |= ::jit::JIT_INSTR_NONFAULTING_FLAG;"; const imm_read = gen_read_imm_call(encoding, size); @@ -245,6 +254,7 @@ function gen_instruction_body_after_fixed_g(encoding, size) const args = ["ctx", `"${instruction_name}"`, "(modrm_byte & 7) as u32", "(modrm_byte >> 3 & 7) as u32"]; return [].concat( + instruction_prefix, gen_call(`::codegen::gen_fn${args.length - 2}_const`, args), reg_postfix, instruction_postfix @@ -267,6 +277,7 @@ function gen_instruction_body_after_fixed_g(encoding, size) } return [].concat( + instruction_prefix, { type: "if-else", if_blocks: [{ @@ -307,6 +318,7 @@ function gen_instruction_body_after_fixed_g(encoding, size) } return [].concat( + instruction_prefix, { type: "if-else", if_blocks: [{ @@ -357,6 +369,7 @@ function gen_instruction_body_after_fixed_g(encoding, size) } return [].concat( + instruction_prefix, imm_read_bindings, gen_call(`::jit_instructions::${instruction_name}_jit`, args), instruction_postfix @@ -392,6 +405,7 @@ function gen_instruction_body_after_fixed_g(encoding, size) } return [].concat( + instruction_prefix, imm_read_bindings, gen_call(`::codegen::gen_fn${args.length - 2}_const`, args), instruction_postfix diff --git a/gen/x86_table.js b/gen/x86_table.js index a3598932..c2e1e7e1 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -123,7 +123,7 @@ const encodings = [ { opcode: 0x98, nonfaulting: 1, os: 1, }, { opcode: 0x99, nonfaulting: 1, os: 1, }, { opcode: 0x9A, os: 1, imm1632: 1, extra_imm16: 1, skip: 1, block_boundary: 1, }, // callf - { opcode: 0x9B, skip: 1, }, + { opcode: 0x9B, skip: 1, }, // fwait: block_boundary since it uses non-raising cpu exceptions // pushf: block_boundary since it uses non-raising cpu exceptions { opcode: 0x9C, os: 1, block_boundary: 1, }, // popf: not a jump, but can cause an eip change due to updating the interrupt flag @@ -417,10 +417,10 @@ const encodings = [ { opcode: 0x0FAA, skip: 1 }, - { 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, block_boundary: 1, }, // fxrstor: block_boundary since it uses non-raising cpu exceptions - { opcode: 0x0FAE, e: 1, fixed_g: 2, only_mem: 1, skip: 1, block_boundary: 1, }, // ldmxcsr - { opcode: 0x0FAE, e: 1, fixed_g: 3, only_mem: 1, skip: 1, block_boundary: 1, }, // stmxcsr + { opcode: 0x0FAE, e: 1, fixed_g: 0, only_mem: 1, task_switch_test: 1, skip: 1, block_boundary: 1, }, // fxsave + { opcode: 0x0FAE, e: 1, fixed_g: 1, only_mem: 1, task_switch_test: 1, skip: 1, block_boundary: 1, }, // fxrstor: block_boundary since it uses non-raising cpu exceptions + { opcode: 0x0FAE, e: 1, fixed_g: 2, only_mem: 1, sse: 1, skip: 1, block_boundary: 1, }, // ldmxcsr + { opcode: 0x0FAE, e: 1, fixed_g: 3, only_mem: 1, sse: 1, skip: 1, block_boundary: 1, }, // stmxcsr { 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) @@ -466,269 +466,269 @@ const encodings = [ // - Skipped are not implemented // - Missing are sse3+, and floating point - { opcode: 0x0F10, e: 1 }, - { opcode: 0xF30F10, e: 1 }, - { opcode: 0x660F10, e: 1 }, - { opcode: 0xF20F10, e: 1 }, - { opcode: 0x0F11, e: 1 }, - { opcode: 0xF30F11, e: 1 }, - { opcode: 0x660F11, e: 1 }, - { opcode: 0xF20F11, e: 1 }, - { opcode: 0x0F12, e: 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 }, - { opcode: 0x660F14, e: 1 }, - { opcode: 0x0F15, e: 1 }, - { opcode: 0x660F15, e: 1 }, - { opcode: 0x0F16, e: 1 }, - { opcode: 0x660F16, only_mem: 1, e: 1 }, - { opcode: 0x0F17, only_mem: 1, e: 1 }, - { opcode: 0x660F17, only_mem: 1, e: 1 }, + { sse: 1, opcode: 0x0F10, e: 1 }, + { sse: 1, opcode: 0xF30F10, e: 1 }, + { sse: 1, opcode: 0x660F10, e: 1 }, + { sse: 1, opcode: 0xF20F10, e: 1 }, + { sse: 1, opcode: 0x0F11, e: 1 }, + { sse: 1, opcode: 0xF30F11, e: 1 }, + { sse: 1, opcode: 0x660F11, e: 1 }, + { sse: 1, opcode: 0xF20F11, e: 1 }, + { sse: 1, opcode: 0x0F12, e: 1 }, + { sse: 1, opcode: 0x660F12, only_mem: 1, e: 1 }, + { sse: 1, opcode: 0xF20F12, e: 1, skip: 1, }, + { sse: 1, opcode: 0xF30F12, e: 1, skip: 1, }, + { sse: 1, opcode: 0x0F13, only_mem: 1, e: 1 }, + { sse: 1, opcode: 0x660F13, only_mem: 1, e: 1 }, + { sse: 1, opcode: 0x0F14, e: 1 }, + { sse: 1, opcode: 0x660F14, e: 1 }, + { sse: 1, opcode: 0x0F15, e: 1 }, + { sse: 1, opcode: 0x660F15, e: 1 }, + { sse: 1, opcode: 0x0F16, e: 1 }, + { sse: 1, opcode: 0x660F16, only_mem: 1, e: 1 }, + { sse: 1, opcode: 0x0F17, only_mem: 1, e: 1 }, + { sse: 1, opcode: 0x660F17, only_mem: 1, e: 1 }, - { opcode: 0x0F28, e: 1 }, - { opcode: 0x660F28, e: 1 }, - { opcode: 0x0F29, e: 1 }, - { opcode: 0x660F29, e: 1 }, - { opcode: 0x0F2A, skip: 1 }, - { opcode: 0x0F2B, only_mem: 1, e: 1 }, - { opcode: 0x660F2B, only_mem: 1, e: 1 }, + { sse: 1, opcode: 0x0F28, e: 1 }, + { sse: 1, opcode: 0x660F28, e: 1 }, + { sse: 1, opcode: 0x0F29, e: 1 }, + { sse: 1, opcode: 0x660F29, e: 1 }, + { sse: 1, opcode: 0x0F2A, skip: 1 }, + { sse: 1, opcode: 0x0F2B, only_mem: 1, e: 1 }, + { sse: 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: 0x0F2D, skip: 1 }, - { opcode: 0x0F2E, skip: 1 }, - { opcode: 0x0F2F, skip: 1 }, + { sse: 1, opcode: 0xF20F2C, e: 1, }, + { sse: 1, opcode: 0x0F2C, e: 1, skip: 1, }, + { sse: 1, opcode: 0xF30F2C, e: 1, skip: 1, }, + { sse: 1, opcode: 0x660F2C, e: 1, skip: 1, }, + { sse: 1, opcode: 0x0F2D, skip: 1 }, + { sse: 1, opcode: 0x0F2E, skip: 1 }, + { sse: 1, opcode: 0x0F2F, skip: 1 }, - { opcode: 0x0F50, only_reg: 1, e: 1 }, - { opcode: 0x660F50, only_reg: 1, e: 1 }, - { opcode: 0x0F51, skip: 1 }, - { opcode: 0x0F52, skip: 1 }, - { opcode: 0x0F53, skip: 1 }, - { opcode: 0x0F54, e: 1 }, - { opcode: 0x660F54, e: 1 }, - { opcode: 0x0F55, e: 1 }, - { opcode: 0x660F55, e: 1 }, - { opcode: 0x0F56, e: 1 }, - { opcode: 0x660F56, e: 1 }, - { opcode: 0x0F57, e: 1 }, - { opcode: 0x660F57, e: 1 }, + { sse: 1, opcode: 0x0F50, only_reg: 1, e: 1 }, + { sse: 1, opcode: 0x660F50, only_reg: 1, e: 1 }, + { sse: 1, opcode: 0x0F51, skip: 1 }, + { sse: 1, opcode: 0x0F52, skip: 1 }, + { sse: 1, opcode: 0x0F53, skip: 1 }, + { sse: 1, opcode: 0x0F54, e: 1 }, + { sse: 1, opcode: 0x660F54, e: 1 }, + { sse: 1, opcode: 0x0F55, e: 1 }, + { sse: 1, opcode: 0x660F55, e: 1 }, + { sse: 1, opcode: 0x0F56, e: 1 }, + { sse: 1, opcode: 0x660F56, e: 1 }, + { sse: 1, opcode: 0x0F57, e: 1 }, + { sse: 1, opcode: 0x660F57, e: 1 }, - { opcode: 0x0F58, skip: 1 }, - { opcode: 0x0F59, skip: 1 }, - { opcode: 0x0F5A, skip: 1 }, - { opcode: 0x0F5B, skip: 1 }, - { opcode: 0x0F5C, skip: 1 }, - { opcode: 0x0F5D, skip: 1 }, - { opcode: 0x0F5E, skip: 1 }, - { opcode: 0x0F5F, skip: 1 }, + { sse: 1, opcode: 0x0F58, skip: 1 }, + { sse: 1, opcode: 0x0F59, skip: 1 }, + { sse: 1, opcode: 0x0F5A, skip: 1 }, + { sse: 1, opcode: 0x0F5B, skip: 1 }, + { sse: 1, opcode: 0x0F5C, skip: 1 }, + { sse: 1, opcode: 0x0F5D, skip: 1 }, + { sse: 1, opcode: 0x0F5E, skip: 1 }, + { sse: 1, opcode: 0x0F5F, skip: 1 }, - { opcode: 0x660F60, e: 1 }, - { opcode: 0x0F60, e: 1 }, - { opcode: 0x660F61, e: 1 }, - { opcode: 0x0F61, e: 1 }, - { opcode: 0x660F62, e: 1 }, - { opcode: 0x0F62, e: 1 }, - { opcode: 0x660F63, e: 1 }, - { opcode: 0x0F63, e: 1 }, - { opcode: 0x660F64, e: 1 }, - { opcode: 0x0F64, e: 1 }, - { opcode: 0x660F65, e: 1 }, - { opcode: 0x0F65, e: 1 }, - { opcode: 0x660F66, e: 1 }, - { opcode: 0x0F66, e: 1 }, - { opcode: 0x660F67, e: 1 }, - { opcode: 0x0F67, e: 1 }, + { sse: 1, opcode: 0x660F60, e: 1 }, + { sse: 1, opcode: 0x0F60, e: 1 }, + { sse: 1, opcode: 0x660F61, e: 1 }, + { sse: 1, opcode: 0x0F61, e: 1 }, + { sse: 1, opcode: 0x660F62, e: 1 }, + { sse: 1, opcode: 0x0F62, e: 1 }, + { sse: 1, opcode: 0x660F63, e: 1 }, + { sse: 1, opcode: 0x0F63, e: 1 }, + { sse: 1, opcode: 0x660F64, e: 1 }, + { sse: 1, opcode: 0x0F64, e: 1 }, + { sse: 1, opcode: 0x660F65, e: 1 }, + { sse: 1, opcode: 0x0F65, e: 1 }, + { sse: 1, opcode: 0x660F66, e: 1 }, + { sse: 1, opcode: 0x0F66, e: 1 }, + { sse: 1, opcode: 0x660F67, e: 1 }, + { sse: 1, opcode: 0x0F67, e: 1 }, - { opcode: 0x660F68, e: 1 }, - { opcode: 0x0F68, e: 1 }, - { opcode: 0x660F69, e: 1 }, - { opcode: 0x0F69, e: 1 }, - { opcode: 0x660F6A, e: 1 }, - { opcode: 0x0F6A, e: 1 }, - { opcode: 0x660F6B, e: 1 }, - { opcode: 0x0F6B, e: 1 }, - { opcode: 0x660F6C, e: 1 }, - { opcode: 0x0F6C, e: 1, }, // ud - { opcode: 0x660F6D, e: 1 }, - { opcode: 0x0F6D, e: 1, }, // ud - { opcode: 0x660F6E, e: 1 }, - { opcode: 0x0F6E, e: 1 }, - { opcode: 0xF30F6F, e: 1 }, - { opcode: 0x660F6F, e: 1 }, - { opcode: 0x0F6F, e: 1 }, + { sse: 1, opcode: 0x660F68, e: 1 }, + { sse: 1, opcode: 0x0F68, e: 1 }, + { sse: 1, opcode: 0x660F69, e: 1 }, + { sse: 1, opcode: 0x0F69, e: 1 }, + { sse: 1, opcode: 0x660F6A, e: 1 }, + { sse: 1, opcode: 0x0F6A, e: 1 }, + { sse: 1, opcode: 0x660F6B, e: 1 }, + { sse: 1, opcode: 0x0F6B, e: 1 }, + { sse: 1, opcode: 0x660F6C, e: 1 }, + { sse: 1, opcode: 0x0F6C, e: 1, }, // ud + { sse: 1, opcode: 0x660F6D, e: 1 }, + { sse: 1, opcode: 0x0F6D, e: 1, }, // ud + { sse: 1, opcode: 0x660F6E, e: 1 }, + { sse: 1, opcode: 0x0F6E, e: 1 }, + { sse: 1, opcode: 0xF30F6F, e: 1 }, + { sse: 1, opcode: 0x660F6F, e: 1 }, + { sse: 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, }, + { sse: 1, opcode: 0x0F70, e: 1, imm8: 1, }, + { sse: 1, opcode: 0x660F70, e: 1, imm8: 1, }, + { sse: 1, opcode: 0xF20F70, e: 1, imm8: 1, }, + { sse: 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 }, - { 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 }, + { sse: 1, opcode: 0x0F71, e: 1, fixed_g: 2, imm8: 1, only_reg: 1, }, + { sse: 1, opcode: 0x660F71, e: 1, fixed_g: 2, imm8: 1, only_reg: 1 }, + { sse: 1, opcode: 0x0F71, e: 1, fixed_g: 4, imm8: 1, only_reg: 1, }, + { sse: 1, opcode: 0x660F71, e: 1, fixed_g: 4, imm8: 1, only_reg: 1 }, + { sse: 1, opcode: 0x0F71, e: 1, fixed_g: 6, imm8: 1, only_reg: 1, }, + { sse: 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 }, + { sse: 1, opcode: 0x0F72, e: 1, fixed_g: 2, imm8: 1, only_reg: 1, }, + { sse: 1, opcode: 0x660F72, e: 1, fixed_g: 2, imm8: 1, only_reg: 1 }, + { sse: 1, opcode: 0x0F72, e: 1, fixed_g: 4, imm8: 1, only_reg: 1, }, + { sse: 1, opcode: 0x660F72, e: 1, fixed_g: 4, imm8: 1, only_reg: 1 }, + { sse: 1, opcode: 0x0F72, e: 1, fixed_g: 6, imm8: 1, only_reg: 1, }, + { sse: 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 }, + { sse: 1, opcode: 0x0F73, e: 1, fixed_g: 2, imm8: 1, only_reg: 1, }, + { sse: 1, opcode: 0x660F73, e: 1, fixed_g: 2, imm8: 1, only_reg: 1, }, + { sse: 1, opcode: 0x660F73, e: 1, fixed_g: 3, imm8: 1, only_reg: 1 }, + { sse: 1, opcode: 0x0F73, e: 1, fixed_g: 6, imm8: 1, only_reg: 1, }, + { sse: 1, opcode: 0x660F73, e: 1, fixed_g: 6, imm8: 1, only_reg: 1 }, + { sse: 1, opcode: 0x660F73, e: 1, fixed_g: 7, imm8: 1, only_reg: 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 }, + { sse: 1, opcode: 0x0F74, e: 1, }, + { sse: 1, opcode: 0x660F74, e: 1, }, + { sse: 1, opcode: 0x0F75, e: 1, }, + { sse: 1, opcode: 0x660F75, e: 1, }, + { sse: 1, opcode: 0x0F76, e: 1, }, + { sse: 1, opcode: 0x660F76, e: 1, }, + { sse: 1, opcode: 0x0F77 }, - { opcode: 0x0F78, skip: 1 }, - { opcode: 0x0F79, skip: 1 }, - { opcode: 0x0F7A, skip: 1 }, - { opcode: 0x0F7B, skip: 1 }, - { opcode: 0x0F7C, skip: 1 }, - { opcode: 0x0F7D, skip: 1 }, + { sse: 1, opcode: 0x0F78, skip: 1 }, + { sse: 1, opcode: 0x0F79, skip: 1 }, + { sse: 1, opcode: 0x0F7A, skip: 1 }, + { sse: 1, opcode: 0x0F7B, skip: 1 }, + { sse: 1, opcode: 0x0F7C, skip: 1 }, + { sse: 1, opcode: 0x0F7D, skip: 1 }, - { opcode: 0x0F7E, e: 1 }, - { opcode: 0x660F7E, e: 1 }, - { opcode: 0xF30F7E, e: 1 }, - { opcode: 0x0F7F, e: 1 }, - { opcode: 0x660F7F, e: 1 }, - { opcode: 0xF30F7F, e: 1 }, + { sse: 1, opcode: 0x0F7E, e: 1 }, + { sse: 1, opcode: 0x660F7E, e: 1 }, + { sse: 1, opcode: 0xF30F7E, e: 1 }, + { sse: 1, opcode: 0x0F7F, e: 1 }, + { sse: 1, opcode: 0x660F7F, e: 1 }, + { sse: 1, opcode: 0xF30F7F, e: 1 }, - { opcode: 0x0FC2, skip: 1, }, + { sse: 1, opcode: 0x0FC2, skip: 1, }, - { opcode: 0x0FC3, e: 1, only_mem: 1, }, - { opcode: 0x0FC4, e: 1, imm8: 1 }, - { opcode: 0x660FC4, e: 1, imm8: 1 }, + { opcode: 0x0FC3, e: 1, only_mem: 1, }, // movnti: Uses normal registers, hence not marked as sse + { sse: 1, opcode: 0x0FC4, e: 1, imm8: 1 }, + { sse: 1, opcode: 0x660FC4, e: 1, imm8: 1 }, - { opcode: 0x0FC5, e: 1, only_reg: 1, imm8: 1 }, - { opcode: 0x660FC5, e: 1, only_reg: 1, imm8: 1, }, + { sse: 1, opcode: 0x0FC5, e: 1, only_reg: 1, imm8: 1 }, + { sse: 1, opcode: 0x660FC5, e: 1, only_reg: 1, imm8: 1, }, - { opcode: 0x0FC6, skip: 1, }, + { sse: 1, opcode: 0x0FC6, skip: 1, }, - { opcode: 0x0FD0, skip: 1, }, + { sse: 1, opcode: 0x0FD0, skip: 1, }, - { opcode: 0x0FD1, e: 1 }, - { opcode: 0x660FD1, e: 1 }, - { opcode: 0x0FD2, e: 1 }, - { opcode: 0x660FD2, e: 1 }, - { opcode: 0x0FD3, e: 1 }, - { opcode: 0x660FD3, e: 1 }, - { opcode: 0x0FD4, e: 1 }, - { opcode: 0x660FD4, e: 1 }, - { opcode: 0x0FD5, e: 1 }, - { opcode: 0x660FD5, e: 1 }, + { sse: 1, opcode: 0x0FD1, e: 1 }, + { sse: 1, opcode: 0x660FD1, e: 1 }, + { sse: 1, opcode: 0x0FD2, e: 1 }, + { sse: 1, opcode: 0x660FD2, e: 1 }, + { sse: 1, opcode: 0x0FD3, e: 1 }, + { sse: 1, opcode: 0x660FD3, e: 1 }, + { sse: 1, opcode: 0x0FD4, e: 1 }, + { sse: 1, opcode: 0x660FD4, e: 1 }, + { sse: 1, opcode: 0x0FD5, e: 1 }, + { sse: 1, opcode: 0x660FD5, e: 1 }, - { opcode: 0x660FD6, e: 1 }, - { opcode: 0xF20FD6, only_reg: 1, e: 1 }, - { opcode: 0xF30FD6, only_reg: 1, e: 1 }, - { opcode: 0x0FD6, e: 1, }, // ud - { opcode: 0x0FD7, e: 1, only_reg: 1 }, - { opcode: 0x660FD7, e: 1, only_reg: 1, }, + { sse: 1, opcode: 0x660FD6, e: 1 }, + { sse: 1, opcode: 0xF20FD6, only_reg: 1, e: 1 }, + { sse: 1, opcode: 0xF30FD6, only_reg: 1, e: 1 }, + { sse: 1, opcode: 0x0FD6, e: 1, }, // ud + { sse: 1, opcode: 0x0FD7, e: 1, only_reg: 1 }, + { sse: 1, opcode: 0x660FD7, e: 1, only_reg: 1, }, - { opcode: 0x0FD8, e: 1 }, - { opcode: 0x660FD8, e: 1 }, - { opcode: 0x0FD9, e: 1 }, - { opcode: 0x660FD9, e: 1 }, - { opcode: 0x0FDA, e: 1 }, - { opcode: 0x660FDA, e: 1 }, - { opcode: 0x0FDB, e: 1 }, - { opcode: 0x660FDB, e: 1 }, - { opcode: 0x0FDC, e: 1 }, - { opcode: 0x660FDC, e: 1 }, - { opcode: 0x0FDD, e: 1 }, - { opcode: 0x660FDD, e: 1 }, - { opcode: 0x0FDE, e: 1 }, - { opcode: 0x660FDE, e: 1 }, - { opcode: 0x0FDF, e: 1 }, - { opcode: 0x660FDF, e: 1 }, + { sse: 1, opcode: 0x0FD8, e: 1 }, + { sse: 1, opcode: 0x660FD8, e: 1 }, + { sse: 1, opcode: 0x0FD9, e: 1 }, + { sse: 1, opcode: 0x660FD9, e: 1 }, + { sse: 1, opcode: 0x0FDA, e: 1 }, + { sse: 1, opcode: 0x660FDA, e: 1 }, + { sse: 1, opcode: 0x0FDB, e: 1 }, + { sse: 1, opcode: 0x660FDB, e: 1 }, + { sse: 1, opcode: 0x0FDC, e: 1 }, + { sse: 1, opcode: 0x660FDC, e: 1 }, + { sse: 1, opcode: 0x0FDD, e: 1 }, + { sse: 1, opcode: 0x660FDD, e: 1 }, + { sse: 1, opcode: 0x0FDE, e: 1 }, + { sse: 1, opcode: 0x660FDE, e: 1 }, + { sse: 1, opcode: 0x0FDF, e: 1 }, + { sse: 1, opcode: 0x660FDF, e: 1 }, - { opcode: 0x0FE0, e: 1 }, - { opcode: 0x660FE0, e: 1 }, - { opcode: 0x0FE1, e: 1 }, - { opcode: 0x660FE1, e: 1 }, - { opcode: 0x0FE2, e: 1 }, - { opcode: 0x660FE2, e: 1 }, - { opcode: 0x0FE3, e: 1 }, - { opcode: 0x660FE3, e: 1 }, - { opcode: 0x0FE4, e: 1 }, - { opcode: 0x660FE4, e: 1 }, - { opcode: 0x0FE5, e: 1 }, - { opcode: 0x660FE5, e: 1 }, + { sse: 1, opcode: 0x0FE0, e: 1 }, + { sse: 1, opcode: 0x660FE0, e: 1 }, + { sse: 1, opcode: 0x0FE1, e: 1 }, + { sse: 1, opcode: 0x660FE1, e: 1 }, + { sse: 1, opcode: 0x0FE2, e: 1 }, + { sse: 1, opcode: 0x660FE2, e: 1 }, + { sse: 1, opcode: 0x0FE3, e: 1 }, + { sse: 1, opcode: 0x660FE3, e: 1 }, + { sse: 1, opcode: 0x0FE4, e: 1 }, + { sse: 1, opcode: 0x660FE4, e: 1 }, + { sse: 1, opcode: 0x0FE5, e: 1 }, + { sse: 1, opcode: 0x660FE5, e: 1 }, - { opcode: 0x660FE6, e: 1, skip: 1, }, - { opcode: 0xF20FE6, e: 1, skip: 1, }, - { opcode: 0xF30FE6, e: 1, skip: 1, }, - { opcode: 0x0FE6, e: 1, }, // ud - { opcode: 0x0FE7, e: 1, only_mem: 1 }, - { opcode: 0x660FE7, e: 1, only_mem: 1, }, + { sse: 1, opcode: 0x660FE6, e: 1, skip: 1, }, + { sse: 1, opcode: 0xF20FE6, e: 1, skip: 1, }, + { sse: 1, opcode: 0xF30FE6, e: 1, skip: 1, }, + { sse: 1, opcode: 0x0FE6, e: 1, }, // ud + { sse: 1, opcode: 0x0FE7, e: 1, only_mem: 1 }, + { sse: 1, opcode: 0x660FE7, e: 1, only_mem: 1, }, - { opcode: 0x0FE8, e: 1 }, - { opcode: 0x660FE8, e: 1 }, - { opcode: 0x0FE9, e: 1 }, - { opcode: 0x660FE9, e: 1 }, - { opcode: 0x0FEA, e: 1 }, - { opcode: 0x660FEA, e: 1 }, - { opcode: 0x0FEB, e: 1 }, - { opcode: 0x660FEB, e: 1 }, - { opcode: 0x0FEC, e: 1 }, - { opcode: 0x660FEC, e: 1 }, - { opcode: 0x0FED, e: 1 }, - { opcode: 0x660FED, e: 1 }, - { opcode: 0x0FEE, e: 1 }, - { opcode: 0x660FEE, e: 1 }, - { opcode: 0x0FEF, e: 1 }, - { opcode: 0x660FEF, e: 1 }, + { sse: 1, opcode: 0x0FE8, e: 1 }, + { sse: 1, opcode: 0x660FE8, e: 1 }, + { sse: 1, opcode: 0x0FE9, e: 1 }, + { sse: 1, opcode: 0x660FE9, e: 1 }, + { sse: 1, opcode: 0x0FEA, e: 1 }, + { sse: 1, opcode: 0x660FEA, e: 1 }, + { sse: 1, opcode: 0x0FEB, e: 1 }, + { sse: 1, opcode: 0x660FEB, e: 1 }, + { sse: 1, opcode: 0x0FEC, e: 1 }, + { sse: 1, opcode: 0x660FEC, e: 1 }, + { sse: 1, opcode: 0x0FED, e: 1 }, + { sse: 1, opcode: 0x660FED, e: 1 }, + { sse: 1, opcode: 0x0FEE, e: 1 }, + { sse: 1, opcode: 0x660FEE, e: 1 }, + { sse: 1, opcode: 0x0FEF, e: 1 }, + { sse: 1, opcode: 0x660FEF, e: 1 }, - { opcode: 0x0FF0, skip: 1, }, + { sse: 1, opcode: 0x0FF0, skip: 1, }, - { opcode: 0x0FF1, e: 1 }, - { opcode: 0x660FF1, e: 1 }, - { opcode: 0x0FF2, e: 1 }, - { opcode: 0x660FF2, e: 1 }, - { opcode: 0x0FF3, e: 1 }, - { opcode: 0x660FF3, e: 1, }, - { opcode: 0x0FF4, e: 1 }, - { opcode: 0x660FF4, e: 1 }, - { opcode: 0x0FF5, e: 1 }, - { opcode: 0x660FF5, e: 1 }, - { opcode: 0x0FF6, e: 1 }, - { opcode: 0x660FF6, e: 1 }, + { sse: 1, opcode: 0x0FF1, e: 1 }, + { sse: 1, opcode: 0x660FF1, e: 1 }, + { sse: 1, opcode: 0x0FF2, e: 1 }, + { sse: 1, opcode: 0x660FF2, e: 1 }, + { sse: 1, opcode: 0x0FF3, e: 1 }, + { sse: 1, opcode: 0x660FF3, e: 1, }, + { sse: 1, opcode: 0x0FF4, e: 1 }, + { sse: 1, opcode: 0x660FF4, e: 1 }, + { sse: 1, opcode: 0x0FF5, e: 1 }, + { sse: 1, opcode: 0x660FF5, e: 1 }, + { sse: 1, opcode: 0x0FF6, e: 1 }, + { sse: 1, opcode: 0x660FF6, e: 1 }, // maskmovq (0FF7), maskmovdqu (660FF7) tested manually // Generated tests don't setup EDI as required (yet) - { opcode: 0x0FF7, only_reg: 1, e: 1, skip: 1, }, - { opcode: 0x660FF7, only_reg: 1, e: 1, skip: 1, }, + { sse: 1, opcode: 0x0FF7, only_reg: 1, e: 1, skip: 1, }, + { sse: 1, opcode: 0x660FF7, only_reg: 1, e: 1, skip: 1, }, - { opcode: 0x0FF8, e: 1 }, - { opcode: 0x660FF8, e: 1 }, - { opcode: 0x0FF9, e: 1 }, - { opcode: 0x660FF9, e: 1 }, - { opcode: 0x0FFA, e: 1 }, - { opcode: 0x660FFA, e: 1 }, - { opcode: 0x0FFB, e: 1 }, - { opcode: 0x660FFB, e: 1 }, - { opcode: 0x0FFC, e: 1 }, - { opcode: 0x660FFC, e: 1 }, - { opcode: 0x0FFD, e: 1 }, - { opcode: 0x660FFD, e: 1 }, - { opcode: 0x0FFE, e: 1 }, - { opcode: 0x660FFE, e: 1 }, + { sse: 1, opcode: 0x0FF8, e: 1 }, + { sse: 1, opcode: 0x660FF8, e: 1 }, + { sse: 1, opcode: 0x0FF9, e: 1 }, + { sse: 1, opcode: 0x660FF9, e: 1 }, + { sse: 1, opcode: 0x0FFA, e: 1 }, + { sse: 1, opcode: 0x660FFA, e: 1 }, + { sse: 1, opcode: 0x0FFB, e: 1 }, + { sse: 1, opcode: 0x660FFB, e: 1 }, + { sse: 1, opcode: 0x0FFC, e: 1 }, + { sse: 1, opcode: 0x660FFC, e: 1 }, + { sse: 1, opcode: 0x0FFD, e: 1 }, + { sse: 1, opcode: 0x660FFD, e: 1 }, + { sse: 1, opcode: 0x0FFE, e: 1 }, + { sse: 1, opcode: 0x660FFE, e: 1 }, { opcode: 0x0FFF, }, ]; @@ -763,14 +763,14 @@ for(let i = 0; i < 8; i++) { opcode: 0xD2, nonfaulting: 1, e: 1, fixed_g: i, mask_flags: of | af, }, { opcode: 0xD3, nonfaulting: 1, os: 1, e: 1, fixed_g: i, mask_flags: of | af, }, - { opcode: 0xD8, e: 1, fixed_g: i, skip: 1, }, - { opcode: 0xD9, e: 1, fixed_g: i, skip: 1, }, - { opcode: 0xDA, e: 1, fixed_g: i, skip: 1, }, - { opcode: 0xDB, e: 1, fixed_g: i, skip: 1, }, - { opcode: 0xDC, e: 1, fixed_g: i, skip: 1, }, - { opcode: 0xDD, e: 1, fixed_g: i, skip: 1, }, - { opcode: 0xDE, e: 1, fixed_g: i, skip: 1, }, - { opcode: 0xDF, e: 1, fixed_g: i, skip: 1, }, + { opcode: 0xD8, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, }, + { opcode: 0xD9, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, }, + { opcode: 0xDA, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, }, + { opcode: 0xDB, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, }, + { opcode: 0xDC, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, }, + { opcode: 0xDD, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, }, + { opcode: 0xDE, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, }, + { opcode: 0xDF, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, }, ]); } diff --git a/src/native/cpu.c b/src/native/cpu.c index 369098bf..9512fe80 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -810,11 +810,32 @@ void trigger_ud() raise_exception(CPU_EXCEPTION_UD); } +__attribute__((noinline)) +void trigger_ud_non_raising() +{ + dbg_log("#ud"); + dbg_trace(); +#if DEBUG + if(cpu_exception_hook(CPU_EXCEPTION_UD)) + { + return; + } +#endif + *instruction_pointer = *previous_ip; + call_interrupt_vector(CPU_EXCEPTION_UD, false, false, 0); +} + __attribute__((noinline)) void trigger_nm() { +#if DEBUG + if(cpu_exception_hook(CPU_EXCEPTION_NM)) + { + return; + } +#endif *instruction_pointer = *previous_ip; - raise_exception(CPU_EXCEPTION_NM); + call_interrupt_vector(CPU_EXCEPTION_NM, false, false, 0); } __attribute__((noinline)) @@ -1355,28 +1376,34 @@ void invlpg(int32_t addr) *last_virt_esp = -1; } -void task_switch_test() +bool task_switch_test() { if(cr[0] & (CR0_EM | CR0_TS)) { trigger_nm(); + return false; } -} -void task_switch_test_mmx() -{ - if(*cr & (CR0_EM | CR0_TS)) - { - if(*cr & CR0_TS) - { - trigger_nm(); - } - else - { - trigger_ud(); - } - } + return true; } +void task_switch_test_void() { task_switch_test(); } + +bool task_switch_test_mmx() +{ + if(*cr & CR0_TS) + { + trigger_nm(); + return false; + } + else if(*cr & CR0_EM) + { + trigger_ud_non_raising(); + return false; + } + + return true; +} +void task_switch_test_mmx_void() { task_switch_test_mmx(); } // read 2 or 4 byte from ip, depending on address size attribute int32_t read_moffs() diff --git a/src/native/cpu.h b/src/native/cpu.h index 8b50f2fc..760f8b86 100644 --- a/src/native/cpu.h +++ b/src/native/cpu.h @@ -148,8 +148,10 @@ void write_xmm128(int32_t r, int32_t i0, int32_t i1, int32_t i2, int32_t i3); void write_xmm_reg128(int32_t r, union reg128 data); void clear_tlb(void); void full_clear_tlb(void); -void task_switch_test(void); -void task_switch_test_mmx(void); +bool task_switch_test(void); +void task_switch_test_void(void); +bool task_switch_test_mmx(void); +void task_switch_test_mmx_void(void); int32_t read_moffs(void); int32_t get_real_eip(void); int32_t get_stack_reg(void); diff --git a/src/native/instructions.c b/src/native/instructions.c index e6d90a3e..41f2a39b 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -568,20 +568,13 @@ void instr_9B() { // fwait: check for pending fpu exceptions if((cr[0] & (CR0_MP | CR0_TS)) == (CR0_MP | CR0_TS)) { - // task switched and MP bit is set + // Note: Different from task_switch_test + // Triggers when TS and MP bits are set (EM bit is ignored) trigger_nm(); } else { - //if(fpu) - { - fwait(); - } - //else - //{ - // // EM bit isn't checked - // // If there's no FPU, do nothing - //} + fwait(); } } void instr16_9C() { @@ -1016,16 +1009,15 @@ DEFINE_MODRM_INSTR_FPU_READ32(instr_D8_6, fpu_fdiv(0, ___)) DEFINE_MODRM_INSTR_FPU_READ32(instr_D8_7, fpu_fdivr(0, ___)) DEFINE_MODRM_INSTR_FPU_READ32(instr_D9_0, fpu_push(___)) -void instr_D9_1_mem(int32_t addr) { task_switch_test(); dbg_log("d9/1"); trigger_ud(); } -void instr_D9_1_reg(int32_t r) { task_switch_test(); fpu_fxch(r); } -void instr_D9_2_mem(int32_t addr) { task_switch_test(); fpu_fstm32(addr); } -void instr_D9_2_reg(int32_t r) { task_switch_test(); if(r != 0) { trigger_ud(); } } -void instr_D9_3_mem(int32_t addr) { task_switch_test(); fpu_fstm32p(addr); } -void instr_D9_3_reg(int32_t r) { task_switch_test(); dbg_log("fstp1"); trigger_ud(); } -void instr_D9_4_mem(int32_t addr) { task_switch_test(); fpu_fldenv(addr); } +void instr_D9_1_mem(int32_t addr) { dbg_log("d9/1"); trigger_ud(); } +void instr_D9_1_reg(int32_t r) { fpu_fxch(r); } +void instr_D9_2_mem(int32_t addr) { fpu_fstm32(addr); } +void instr_D9_2_reg(int32_t r) { if(r != 0) { trigger_ud(); } } +void instr_D9_3_mem(int32_t addr) { fpu_fstm32p(addr); } +void instr_D9_3_reg(int32_t r) { dbg_log("fstp1"); trigger_ud(); } +void instr_D9_4_mem(int32_t addr) { fpu_fldenv(addr); } void instr_D9_4_reg(int32_t r) { - task_switch_test(); double_t st0 = fpu_get_st0(); switch(r) { @@ -1048,11 +1040,10 @@ void instr_D9_4_reg(int32_t r) trigger_ud(); } } -void instr_D9_5_mem(int32_t addr) { task_switch_test(); fpu_fldcw(addr); } +void instr_D9_5_mem(int32_t addr) { fpu_fldcw(addr); } void instr_D9_5_reg(int32_t r) { // fld1/fldl2t/fldl2e/fldpi/fldlg2/fldln2/fldz - task_switch_test(); switch(r) { case 0: fpu_push(1); break; @@ -1065,10 +1056,9 @@ void instr_D9_5_reg(int32_t r) case 7: dbg_log("d9/5/7"); trigger_ud(); break; } } -void instr_D9_6_mem(int32_t addr) { task_switch_test(); fpu_fstenv(addr); } +void instr_D9_6_mem(int32_t addr) { fpu_fstenv(addr); } void instr_D9_6_reg(int32_t r) { - task_switch_test(); double_t st0 = fpu_get_st0(); switch(r) @@ -1113,10 +1103,9 @@ void instr_D9_6_reg(int32_t r) dbg_assert(false); } } -void instr_D9_7_mem(int32_t addr) { task_switch_test(); fpu_fstcw(addr); } +void instr_D9_7_mem(int32_t addr) { fpu_fstcw(addr); } void instr_D9_7_reg(int32_t r) { - task_switch_test(); double_t st0 = fpu_get_st0(); switch(r) @@ -1155,40 +1144,39 @@ void instr_D9_7_reg(int32_t r) } } -void instr_DA_0_mem(int32_t addr) { task_switch_test(); fpu_fadd(0, safe_read32s(addr)); } -void instr_DA_1_mem(int32_t addr) { task_switch_test(); fpu_fmul(0, safe_read32s(addr)); } -void instr_DA_2_mem(int32_t addr) { task_switch_test(); fpu_fcom(safe_read32s(addr)); } -void instr_DA_3_mem(int32_t addr) { task_switch_test(); fpu_fcomp(safe_read32s(addr)); } -void instr_DA_4_mem(int32_t addr) { task_switch_test(); fpu_fsub(0, safe_read32s(addr)); } -void instr_DA_5_mem(int32_t addr) { task_switch_test(); fpu_fsubr(0, safe_read32s(addr)); } -void instr_DA_6_mem(int32_t addr) { task_switch_test(); fpu_fdiv(0, safe_read32s(addr)); } -void instr_DA_7_mem(int32_t addr) { task_switch_test(); fpu_fdivr(0, safe_read32s(addr)); } +void instr_DA_0_mem(int32_t addr) { fpu_fadd(0, safe_read32s(addr)); } +void instr_DA_1_mem(int32_t addr) { fpu_fmul(0, safe_read32s(addr)); } +void instr_DA_2_mem(int32_t addr) { fpu_fcom(safe_read32s(addr)); } +void instr_DA_3_mem(int32_t addr) { fpu_fcomp(safe_read32s(addr)); } +void instr_DA_4_mem(int32_t addr) { fpu_fsub(0, safe_read32s(addr)); } +void instr_DA_5_mem(int32_t addr) { fpu_fsubr(0, safe_read32s(addr)); } +void instr_DA_6_mem(int32_t addr) { fpu_fdiv(0, safe_read32s(addr)); } +void instr_DA_7_mem(int32_t addr) { fpu_fdivr(0, safe_read32s(addr)); } -void instr_DA_0_reg(int32_t r) { task_switch_test(); fpu_fcmovcc(test_b(), r); } -void instr_DA_1_reg(int32_t r) { task_switch_test(); fpu_fcmovcc(test_z(), r); } -void instr_DA_2_reg(int32_t r) { task_switch_test(); fpu_fcmovcc(test_be(), r); } -void instr_DA_3_reg(int32_t r) { task_switch_test(); fpu_fcmovcc(test_p(), r); } +void instr_DA_0_reg(int32_t r) { fpu_fcmovcc(test_b(), r); } +void instr_DA_1_reg(int32_t r) { fpu_fcmovcc(test_z(), r); } +void instr_DA_2_reg(int32_t r) { fpu_fcmovcc(test_be(), r); } +void instr_DA_3_reg(int32_t r) { fpu_fcmovcc(test_p(), r); } void instr_DA_4_reg(int32_t r) { trigger_ud(); } -void instr_DA_5_reg(int32_t r) { task_switch_test(); if(r == 1) { fpu_fucompp(); } else { trigger_ud(); } } +void instr_DA_5_reg(int32_t r) { if(r == 1) { fpu_fucompp(); } else { trigger_ud(); } } void instr_DA_6_reg(int32_t r) { trigger_ud(); } void instr_DA_7_reg(int32_t r) { trigger_ud(); } -void instr_DB_0_mem(int32_t addr) { task_switch_test(); fpu_fldm32(addr); } +void instr_DB_0_mem(int32_t addr) { fpu_fldm32(addr); } void instr_DB_1_mem(int32_t addr) { trigger_ud(); } -void instr_DB_2_mem(int32_t addr) { task_switch_test(); fpu_fistm32(addr); } -void instr_DB_3_mem(int32_t addr) { task_switch_test(); fpu_fistm32p(addr); } +void instr_DB_2_mem(int32_t addr) { fpu_fistm32(addr); } +void instr_DB_3_mem(int32_t addr) { fpu_fistm32p(addr); } void instr_DB_4_mem(int32_t addr) { trigger_ud(); } -void instr_DB_5_mem(int32_t addr) { task_switch_test(); fpu_fldm80(addr); } +void instr_DB_5_mem(int32_t addr) { fpu_fldm80(addr); } void instr_DB_6_mem(int32_t addr) { trigger_ud(); } -void instr_DB_7_mem(int32_t addr) { task_switch_test(); fpu_fst80p(addr); } +void instr_DB_7_mem(int32_t addr) { fpu_fst80p(addr); } -void instr_DB_0_reg(int32_t r) { task_switch_test(); fpu_fcmovcc(!test_b(), r); } -void instr_DB_1_reg(int32_t r) { task_switch_test(); fpu_fcmovcc(!test_z(), r); } -void instr_DB_2_reg(int32_t r) { task_switch_test(); fpu_fcmovcc(!test_be(), r); } -void instr_DB_3_reg(int32_t r) { task_switch_test(); fpu_fcmovcc(!test_p(), r); } +void instr_DB_0_reg(int32_t r) { fpu_fcmovcc(!test_b(), r); } +void instr_DB_1_reg(int32_t r) { fpu_fcmovcc(!test_z(), r); } +void instr_DB_2_reg(int32_t r) { fpu_fcmovcc(!test_be(), r); } +void instr_DB_3_reg(int32_t r) { fpu_fcmovcc(!test_p(), r); } void instr_DB_4_reg(int32_t r) { - task_switch_test(); if(r == 3) { fpu_finit(); @@ -1206,80 +1194,80 @@ void instr_DB_4_reg(int32_t r) trigger_ud(); } } -void instr_DB_5_reg(int32_t r) { task_switch_test(); fpu_fucomi(r); } -void instr_DB_6_reg(int32_t r) { task_switch_test(); fpu_fcomi(r); } +void instr_DB_5_reg(int32_t r) { fpu_fucomi(r); } +void instr_DB_6_reg(int32_t r) { fpu_fcomi(r); } void instr_DB_7_reg(int32_t r) { trigger_ud(); } -void instr_DC_0_mem(int32_t addr) { task_switch_test(); fpu_fadd(0, fpu_load_m64(addr)); } -void instr_DC_1_mem(int32_t addr) { task_switch_test(); fpu_fmul(0, fpu_load_m64(addr)); } -void instr_DC_2_mem(int32_t addr) { task_switch_test(); fpu_fcom(fpu_load_m64(addr)); } -void instr_DC_3_mem(int32_t addr) { task_switch_test(); fpu_fcomp(fpu_load_m64(addr)); } -void instr_DC_4_mem(int32_t addr) { task_switch_test(); fpu_fsub(0, fpu_load_m64(addr)); } -void instr_DC_5_mem(int32_t addr) { task_switch_test(); fpu_fsubr(0, fpu_load_m64(addr)); } -void instr_DC_6_mem(int32_t addr) { task_switch_test(); fpu_fdiv(0, fpu_load_m64(addr)); } -void instr_DC_7_mem(int32_t addr) { task_switch_test(); fpu_fdivr(0, fpu_load_m64(addr)); } +void instr_DC_0_mem(int32_t addr) { fpu_fadd(0, fpu_load_m64(addr)); } +void instr_DC_1_mem(int32_t addr) { fpu_fmul(0, fpu_load_m64(addr)); } +void instr_DC_2_mem(int32_t addr) { fpu_fcom(fpu_load_m64(addr)); } +void instr_DC_3_mem(int32_t addr) { fpu_fcomp(fpu_load_m64(addr)); } +void instr_DC_4_mem(int32_t addr) { fpu_fsub(0, fpu_load_m64(addr)); } +void instr_DC_5_mem(int32_t addr) { fpu_fsubr(0, fpu_load_m64(addr)); } +void instr_DC_6_mem(int32_t addr) { fpu_fdiv(0, fpu_load_m64(addr)); } +void instr_DC_7_mem(int32_t addr) { fpu_fdivr(0, fpu_load_m64(addr)); } -void instr_DC_0_reg(int32_t r) { task_switch_test(); fpu_fadd(r, fpu_get_sti(r)); } -void instr_DC_1_reg(int32_t r) { task_switch_test(); fpu_fmul(r, fpu_get_sti(r)); } -void instr_DC_2_reg(int32_t r) { task_switch_test(); fpu_fcom(fpu_get_sti(r)); } -void instr_DC_3_reg(int32_t r) { task_switch_test(); fpu_fcomp(fpu_get_sti(r)); } -void instr_DC_4_reg(int32_t r) { task_switch_test(); fpu_fsub(r, fpu_get_sti(r)); } -void instr_DC_5_reg(int32_t r) { task_switch_test(); fpu_fsubr(r, fpu_get_sti(r)); } -void instr_DC_6_reg(int32_t r) { task_switch_test(); fpu_fdiv(r, fpu_get_sti(r)); } -void instr_DC_7_reg(int32_t r) { task_switch_test(); fpu_fdivr(r, fpu_get_sti(r)); } +void instr_DC_0_reg(int32_t r) { fpu_fadd(r, fpu_get_sti(r)); } +void instr_DC_1_reg(int32_t r) { fpu_fmul(r, fpu_get_sti(r)); } +void instr_DC_2_reg(int32_t r) { fpu_fcom(fpu_get_sti(r)); } +void instr_DC_3_reg(int32_t r) { fpu_fcomp(fpu_get_sti(r)); } +void instr_DC_4_reg(int32_t r) { fpu_fsub(r, fpu_get_sti(r)); } +void instr_DC_5_reg(int32_t r) { fpu_fsubr(r, fpu_get_sti(r)); } +void instr_DC_6_reg(int32_t r) { fpu_fdiv(r, fpu_get_sti(r)); } +void instr_DC_7_reg(int32_t r) { fpu_fdivr(r, fpu_get_sti(r)); } -void instr_DD_0_mem(int32_t addr) { task_switch_test(); fpu_fldm64(addr); } +void instr_DD_0_mem(int32_t addr) { fpu_fldm64(addr); } void instr_DD_1_mem(int32_t addr) { dbg_log("fisttp"); trigger_ud(); } -void instr_DD_2_mem(int32_t addr) { task_switch_test(); fpu_fstm64(addr); } -void instr_DD_3_mem(int32_t addr) { task_switch_test(); fpu_fstm64p(addr); } -void instr_DD_4_mem(int32_t addr) { task_switch_test(); fpu_frstor(addr); } +void instr_DD_2_mem(int32_t addr) { fpu_fstm64(addr); } +void instr_DD_3_mem(int32_t addr) { fpu_fstm64p(addr); } +void instr_DD_4_mem(int32_t addr) { fpu_frstor(addr); } void instr_DD_5_mem(int32_t addr) { dbg_log("dd/5"); trigger_ud(); } -void instr_DD_6_mem(int32_t addr) { task_switch_test(); fpu_fsave(addr); } -void instr_DD_7_mem(int32_t addr) { task_switch_test(); fpu_fnstsw_mem(addr); } +void instr_DD_6_mem(int32_t addr) { fpu_fsave(addr); } +void instr_DD_7_mem(int32_t addr) { fpu_fnstsw_mem(addr); } -void instr_DD_0_reg(int32_t r) { task_switch_test(); fpu_ffree(r); } +void instr_DD_0_reg(int32_t r) { fpu_ffree(r); } void instr_DD_1_reg(int32_t r) { trigger_ud(); } -void instr_DD_2_reg(int32_t r) { task_switch_test(); fpu_fst(r); } -void instr_DD_3_reg(int32_t r) { task_switch_test(); fpu_fstp(r); } -void instr_DD_4_reg(int32_t r) { task_switch_test(); fpu_fucom(r); } -void instr_DD_5_reg(int32_t r) { task_switch_test(); fpu_fucomp(r); } +void instr_DD_2_reg(int32_t r) { fpu_fst(r); } +void instr_DD_3_reg(int32_t r) { fpu_fstp(r); } +void instr_DD_4_reg(int32_t r) { fpu_fucom(r); } +void instr_DD_5_reg(int32_t r) { fpu_fucomp(r); } void instr_DD_6_reg(int32_t r) { trigger_ud(); } void instr_DD_7_reg(int32_t r) { trigger_ud(); } -void instr_DE_0_mem(int32_t addr) { task_switch_test(); fpu_fadd(0, (int16_t) safe_read16(addr)); } -void instr_DE_1_mem(int32_t addr) { task_switch_test(); fpu_fmul(0, (int16_t) safe_read16(addr)); } -void instr_DE_2_mem(int32_t addr) { task_switch_test(); fpu_fcom((int16_t) safe_read16(addr)); } -void instr_DE_3_mem(int32_t addr) { task_switch_test(); fpu_fcomp((int16_t) safe_read16(addr)); } -void instr_DE_4_mem(int32_t addr) { task_switch_test(); fpu_fsub(0, (int16_t) safe_read16(addr)); } -void instr_DE_5_mem(int32_t addr) { task_switch_test(); fpu_fsubr(0, (int16_t) safe_read16(addr)); } -void instr_DE_6_mem(int32_t addr) { task_switch_test(); fpu_fdiv(0, (int16_t) safe_read16(addr)); } -void instr_DE_7_mem(int32_t addr) { task_switch_test(); fpu_fdivr(0, (int16_t) safe_read16(addr)); } +void instr_DE_0_mem(int32_t addr) { fpu_fadd(0, (int16_t) safe_read16(addr)); } +void instr_DE_1_mem(int32_t addr) { fpu_fmul(0, (int16_t) safe_read16(addr)); } +void instr_DE_2_mem(int32_t addr) { fpu_fcom((int16_t) safe_read16(addr)); } +void instr_DE_3_mem(int32_t addr) { fpu_fcomp((int16_t) safe_read16(addr)); } +void instr_DE_4_mem(int32_t addr) { fpu_fsub(0, (int16_t) safe_read16(addr)); } +void instr_DE_5_mem(int32_t addr) { fpu_fsubr(0, (int16_t) safe_read16(addr)); } +void instr_DE_6_mem(int32_t addr) { fpu_fdiv(0, (int16_t) safe_read16(addr)); } +void instr_DE_7_mem(int32_t addr) { fpu_fdivr(0, (int16_t) safe_read16(addr)); } -void instr_DE_0_reg(int32_t r) { task_switch_test(); fpu_fadd(r, fpu_get_sti(r)); fpu_pop(); } -void instr_DE_1_reg(int32_t r) { task_switch_test(); fpu_fmul(r, fpu_get_sti(r)); fpu_pop(); } -void instr_DE_2_reg(int32_t r) { task_switch_test(); fpu_fcom(fpu_get_sti(r)); fpu_pop(); } -void instr_DE_3_reg(int32_t r) { task_switch_test(); fpu_fcomp(fpu_get_sti(r)); fpu_pop(); } -void instr_DE_4_reg(int32_t r) { task_switch_test(); fpu_fsub(r, fpu_get_sti(r)); fpu_pop(); } -void instr_DE_5_reg(int32_t r) { task_switch_test(); fpu_fsubr(r, fpu_get_sti(r)); fpu_pop(); } -void instr_DE_6_reg(int32_t r) { task_switch_test(); fpu_fdiv(r, fpu_get_sti(r)); fpu_pop(); } -void instr_DE_7_reg(int32_t r) { task_switch_test(); fpu_fdivr(r, fpu_get_sti(r)); fpu_pop(); } +void instr_DE_0_reg(int32_t r) { fpu_fadd(r, fpu_get_sti(r)); fpu_pop(); } +void instr_DE_1_reg(int32_t r) { fpu_fmul(r, fpu_get_sti(r)); fpu_pop(); } +void instr_DE_2_reg(int32_t r) { fpu_fcom(fpu_get_sti(r)); fpu_pop(); } +void instr_DE_3_reg(int32_t r) { fpu_fcomp(fpu_get_sti(r)); fpu_pop(); } +void instr_DE_4_reg(int32_t r) { fpu_fsub(r, fpu_get_sti(r)); fpu_pop(); } +void instr_DE_5_reg(int32_t r) { fpu_fsubr(r, fpu_get_sti(r)); fpu_pop(); } +void instr_DE_6_reg(int32_t r) { fpu_fdiv(r, fpu_get_sti(r)); fpu_pop(); } +void instr_DE_7_reg(int32_t r) { fpu_fdivr(r, fpu_get_sti(r)); fpu_pop(); } -void instr_DF_0_mem(int32_t addr) { task_switch_test(); fpu_push((int16_t) safe_read16(addr)); } +void instr_DF_0_mem(int32_t addr) { fpu_push((int16_t) safe_read16(addr)); } void instr_DF_1_mem(int32_t addr) { dbg_log("df/fisttp"); trigger_ud(); } -void instr_DF_2_mem(int32_t addr) { task_switch_test(); fpu_fistm16(addr); } -void instr_DF_3_mem(int32_t addr) { task_switch_test(); fpu_fistm16p(addr); } +void instr_DF_2_mem(int32_t addr) { fpu_fistm16(addr); } +void instr_DF_3_mem(int32_t addr) { fpu_fistm16p(addr); } void instr_DF_4_mem(int32_t addr) { dbg_log("fbld"); trigger_ud(); } -void instr_DF_5_mem(int32_t addr) { task_switch_test(); fpu_fildm64(addr); } +void instr_DF_5_mem(int32_t addr) { fpu_fildm64(addr); } void instr_DF_6_mem(int32_t addr) { dbg_log("fbstp"); trigger_ud(); } -void instr_DF_7_mem(int32_t addr) { task_switch_test(); fpu_fistm64p(addr); } +void instr_DF_7_mem(int32_t addr) { fpu_fistm64p(addr); } void instr_DF_0_reg(int32_t r) { trigger_ud(); } void instr_DF_1_reg(int32_t r) { trigger_ud(); } void instr_DF_2_reg(int32_t r) { trigger_ud(); } void instr_DF_3_reg(int32_t r) { trigger_ud(); } -void instr_DF_4_reg(int32_t r) { task_switch_test(); if(r == 0) { fpu_fnstsw_reg(); } else { trigger_ud(); } } -void instr_DF_5_reg(int32_t r) { task_switch_test(); fpu_fucomip(r); } -void instr_DF_6_reg(int32_t r) { task_switch_test(); fpu_fcomip(r); } +void instr_DF_4_reg(int32_t r) { if(r == 0) { fpu_fnstsw_reg(); } else { trigger_ud(); } } +void instr_DF_5_reg(int32_t r) { fpu_fucomip(r); } +void instr_DF_6_reg(int32_t r) { fpu_fcomip(r); } void instr_DF_7_reg(int32_t r) { trigger_ud(); } void instr16_E0(int32_t imm8s) { loopne16(imm8s); } diff --git a/src/native/instructions.h b/src/native/instructions.h index b95aa250..d711a224 100644 --- a/src/native/instructions.h +++ b/src/native/instructions.h @@ -114,8 +114,8 @@ void name ## _reg(int32_t r1, int32_t r) { int32_t ___ = read_reg32(r1); fun; } #define DEFINE_MODRM_INSTR_FPU_READ32(name, fun) \ - void name ## _mem(int32_t addr) { task_switch_test(); double_t ___ = fpu_load_m32(addr); fun; } \ - void name ## _reg(int32_t r) { task_switch_test(); double_t ___ = fpu_get_sti(r); fun; } + void name ## _mem(int32_t addr) { double_t ___ = fpu_load_m32(addr); fun; } \ + void name ## _reg(int32_t r) { double_t ___ = fpu_get_sti(r); fun; } void instr_00_mem(int32_t addr, int32_t r); void instr_00_reg(int32_t r1, int32_t r); diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 22df2039..49b2455c 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -217,14 +217,12 @@ DEFINE_SSE_SPLIT(instr_0F10, safe_read128s, read_xmm128s) void instr_F30F10_reg(int32_t r1, int32_t r2) { // movss xmm, xmm/m32 - task_switch_test_mmx(); union reg128 data = read_xmm128s(r1); union reg128 orig = read_xmm128s(r2); write_xmm128(r2, data.u32[0], orig.u32[1], orig.u32[2], orig.u32[3]); } void instr_F30F10_mem(int32_t addr, int32_t r) { // movss xmm, xmm/m32 - task_switch_test_mmx(); int32_t data = safe_read32s(addr); write_xmm128(r, data, 0, 0, 0); } @@ -237,14 +235,12 @@ DEFINE_SSE_SPLIT(instr_660F10, safe_read128s, read_xmm128s) void instr_F20F10_reg(int32_t r1, int32_t r2) { // movsd xmm, xmm/m64 - task_switch_test_mmx(); union reg128 data = read_xmm128s(r1); union reg128 orig = read_xmm128s(r2); write_xmm128(r2, data.u32[0], data.u32[1], orig.u32[2], orig.u32[3]); } void instr_F20F10_mem(int32_t addr, int32_t r) { // movsd xmm, xmm/m64 - task_switch_test_mmx(); union reg64 data = safe_read64s(addr); write_xmm128(r, data.u32[0], data.u32[1], 0, 0); } @@ -260,14 +256,12 @@ void instr_0F11_mem(int32_t addr, int32_t r) { void instr_F30F11_reg(int32_t rm_dest, int32_t reg_src) { // movss xmm/m32, xmm - task_switch_test_mmx(); union reg128 data = read_xmm128s(reg_src); union reg128 orig = read_xmm128s(rm_dest); write_xmm128(rm_dest, data.u32[0], orig.u32[1], orig.u32[2], orig.u32[3]); } void instr_F30F11_mem(int32_t addr, int32_t r) { // movss xmm/m32, xmm - task_switch_test_mmx(); union reg128 data = read_xmm128s(r); safe_write32(addr, data.u32[0]); } @@ -283,28 +277,24 @@ void instr_660F11_mem(int32_t addr, int32_t r) { void instr_F20F11_reg(int32_t r1, int32_t r2) { // movsd xmm/m64, xmm - task_switch_test_mmx(); union reg128 data = read_xmm128s(r2); union reg128 orig = read_xmm128s(r1); write_xmm128(r1, data.u32[0], data.u32[1], orig.u32[2], orig.u32[3]); } void instr_F20F11_mem(int32_t addr, int32_t r) { // movsd xmm/m64, xmm - task_switch_test_mmx(); union reg64 data = read_xmm64s(r); safe_write64(addr, data.u64[0]); } void instr_0F12_mem(int32_t addr, int32_t r) { // movlps xmm, m64 - task_switch_test_mmx(); union reg64 data = safe_read64s(addr); union reg128 orig = read_xmm128s(r); write_xmm128(r, data.u32[0], data.u32[1], orig.u32[2], orig.u32[3]); } void instr_0F12_reg(int32_t r1, int32_t r2) { // movhlps xmm, xmm - task_switch_test_mmx(); union reg128 data = read_xmm128s(r1); union reg128 orig = read_xmm128s(r2); write_xmm128(r2, data.u32[2], data.u32[3], orig.u32[2], orig.u32[3]); @@ -313,7 +303,6 @@ void instr_0F12_reg(int32_t r1, int32_t r2) { void instr_660F12_reg(int32_t r1, int32_t r) { trigger_ud(); } void instr_660F12_mem(int32_t addr, int32_t r) { // movlpd xmm, m64 - task_switch_test_mmx(); union reg64 data = safe_read64s(addr); write_xmm64(r, data); } @@ -338,7 +327,6 @@ void instr_660F13_mem(int32_t addr, int32_t r) { void instr_0F14(union reg64 source, int32_t r) { // unpcklps xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg64 destination = read_xmm64s(r); write_xmm128( @@ -354,7 +342,6 @@ DEFINE_SSE_SPLIT(instr_0F14, safe_read64s, read_xmm64s) void instr_660F14(union reg64 source, int32_t r) { // unpcklpd xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg64 destination = read_xmm64s(r); write_xmm128( @@ -370,7 +357,6 @@ DEFINE_SSE_SPLIT(instr_660F14, safe_read64s, read_xmm64s) void instr_0F15(union reg128 source, int32_t r) { // unpckhps xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); write_xmm128( @@ -386,7 +372,6 @@ DEFINE_SSE_SPLIT(instr_0F15, safe_read128s, read_xmm128s) void instr_660F15(union reg128 source, int32_t r) { // unpckhpd xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); write_xmm128( @@ -405,7 +390,6 @@ void instr_0F16_mem(int32_t addr, int32_t r) { } void instr_0F16_reg(int32_t r1, int32_t r2) { // movlhps xmm, xmm - task_switch_test_mmx(); union reg128 data = read_xmm128s(r1); union reg128 orig = read_xmm128s(r2); write_xmm128(r2, orig.u32[0], orig.u32[1], data.u32[0], data.u32[1]); @@ -619,7 +603,6 @@ DEFINE_SSE_SPLIT(instr_660F28, safe_read128s, read_xmm128s) void instr_0F29_mem(int32_t addr, int32_t r) { // movaps m128, xmm - task_switch_test_mmx(); union reg128 data = read_xmm128s(r); // XXX: Aligned write or #gp safe_write128(addr, data); @@ -630,7 +613,6 @@ void instr_0F29_reg(int32_t r1, int32_t r2) { } 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); @@ -665,7 +647,6 @@ 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(); #if 0 union reg64 source = read_xmm_mem64s(); double f = source.f64[0]; @@ -1008,7 +989,6 @@ DEFINE_MODRM_INSTR_READ32(instr32_0F4F, cmovcc32(!test_le(), ___, r)) void instr_0F50_reg(int32_t r1, int32_t r2) { // movmskps r, xmm - task_switch_test_mmx(); union reg128 source = read_xmm128s(r1); int32_t data = source.u32[0] >> 31 | (source.u32[1] >> 31) << 1 | (source.u32[2] >> 31) << 2 | (source.u32[3] >> 31) << 3; @@ -1018,7 +998,6 @@ void instr_0F50_mem(int32_t addr, int32_t r1) { trigger_ud(); } void instr_660F50_reg(int32_t r1, int32_t r2) { // movmskpd r, xmm - task_switch_test_mmx(); union reg128 source = read_xmm128s(r1); int32_t data = (source.u32[1] >> 31) | (source.u32[3] >> 31) << 1; write_reg32(r2, data); @@ -1097,7 +1076,6 @@ void instr_0F5F() { unimplemented_sse(); } void instr_0F60(int32_t source, int32_t r) { // punpcklbw mm, mm/m32 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); int32_t byte0 = destination.u8[0]; @@ -1119,7 +1097,6 @@ DEFINE_SSE_SPLIT(instr_0F60, safe_read32s, read_mmx32s) void instr_660F60(union reg64 source, int32_t r) { // punpcklbw xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg64 destination = read_xmm64s(r); write_xmm128( r, @@ -1133,7 +1110,6 @@ DEFINE_SSE_SPLIT(instr_660F60, safe_read64s, read_xmm64s) void instr_0F61(int32_t source, int32_t r) { // punpcklwd mm, mm/m32 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); int32_t word0 = destination.u16[0]; @@ -1151,7 +1127,6 @@ DEFINE_SSE_SPLIT(instr_0F61, safe_read32s, read_mmx32s) void instr_660F61(union reg64 source, int32_t r) { // punpcklwd xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg64 destination = read_xmm64s(r); write_xmm128( r, @@ -1165,7 +1140,6 @@ DEFINE_SSE_SPLIT(instr_660F61, safe_read64s, read_xmm64s) void instr_0F62(int32_t source, int32_t r) { // punpckldq mm, mm/m32 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); write_mmx64(r, destination.u32[0], source); } @@ -1174,7 +1148,6 @@ DEFINE_SSE_SPLIT(instr_0F62, safe_read32s, read_mmx32s) void instr_660F62(union reg128 source, int32_t r) { // punpckldq xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); write_xmm128( r, @@ -1188,7 +1161,6 @@ DEFINE_SSE_SPLIT(instr_660F62, safe_read128s, read_xmm128s) void instr_0F63(union reg64 source, int32_t r) { // packsswb mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); int32_t low = saturate_sw_to_sb(destination.u16[0]) | @@ -1208,7 +1180,6 @@ DEFINE_SSE_SPLIT(instr_0F63, safe_read64s, read_mmx64s) void instr_660F63(union reg128 source, int32_t r) { // packsswb xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); int32_t dword0 = saturate_sw_to_sb(destination.u16[0]) | @@ -1237,7 +1208,6 @@ DEFINE_SSE_SPLIT(instr_660F63, safe_read128s, read_xmm128s) void instr_0F64(union reg64 source, int32_t r) { // pcmpgtb mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -1253,7 +1223,6 @@ DEFINE_SSE_SPLIT(instr_0F64, safe_read64s, read_mmx64s) void instr_660F64(union reg128 source, int32_t r) { // pcmpgtb xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); union reg128 result = { { 0 } }; @@ -1268,7 +1237,6 @@ DEFINE_SSE_SPLIT(instr_660F64, safe_read128s, read_xmm128s) void instr_0F65(union reg64 source, int32_t r) { // pcmpgtw mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); int32_t word0 = destination.i16[0] > source.i16[0] ? 0xFFFF : 0; @@ -1286,7 +1254,6 @@ DEFINE_SSE_SPLIT(instr_0F65, safe_read64s, read_mmx64s) void instr_660F65(union reg128 source, int32_t r) { // pcmpgtw xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); union reg128 result = { { 0 } }; @@ -1301,7 +1268,6 @@ DEFINE_SSE_SPLIT(instr_660F65, safe_read128s, read_xmm128s) void instr_0F66(union reg64 source, int32_t r) { // pcmpgtd mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); int32_t low = destination.i32[0] > source.i32[0] ? -1 : 0; @@ -1314,7 +1280,6 @@ DEFINE_SSE_SPLIT(instr_0F66, safe_read64s, read_mmx64s) void instr_660F66(union reg128 source, int32_t r) { // pcmpgtd xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); write_xmm128( @@ -1329,7 +1294,6 @@ DEFINE_SSE_SPLIT(instr_660F66, safe_read128s, read_xmm128s) void instr_0F67(union reg64 source, int32_t r) { // packuswb mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); uint32_t low = saturate_sw_to_ub(destination.u16[0]) | @@ -1349,7 +1313,6 @@ DEFINE_SSE_SPLIT(instr_0F67, safe_read64s, read_mmx64s) void instr_660F67(union reg128 source, int32_t r) { // packuswb xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -1366,7 +1329,6 @@ DEFINE_SSE_SPLIT(instr_660F67, safe_read128s, read_xmm128s) void instr_0F68(union reg64 source, int32_t r) { // punpckhbw mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); int32_t byte0 = destination.u8[4]; @@ -1388,7 +1350,6 @@ DEFINE_SSE_SPLIT(instr_0F68, safe_read64s, read_mmx64s) void instr_660F68(union reg128 source, int32_t r) { // punpckhbw xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); write_xmm128( @@ -1403,7 +1364,6 @@ DEFINE_SSE_SPLIT(instr_660F68, safe_read128s, read_xmm128s) void instr_0F69(union reg64 source, int32_t r) { // punpckhwd mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); int32_t word0 = destination.u16[2]; @@ -1421,7 +1381,6 @@ DEFINE_SSE_SPLIT(instr_0F69, safe_read64s, read_mmx64s) void instr_660F69(union reg128 source, int32_t r) { // punpckhwd xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); int32_t dword0 = destination.u16[4] | source.u16[4] << 16; @@ -1435,7 +1394,6 @@ DEFINE_SSE_SPLIT(instr_660F69, safe_read128s, read_xmm128s) void instr_0F6A(union reg64 source, int32_t r) { // punpckhdq mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); write_mmx64(r, destination.u32[1], source.u32[1]); } @@ -1444,7 +1402,6 @@ DEFINE_SSE_SPLIT(instr_0F6A, safe_read64s, read_mmx64s) void instr_660F6A(union reg128 source, int32_t r) { // punpckhdq xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); write_xmm128(r, destination.u32[2], source.u32[2], destination.u32[3], source.u32[3]); } @@ -1452,7 +1409,6 @@ DEFINE_SSE_SPLIT(instr_660F6A, safe_read128s, read_xmm128s) void instr_0F6B(union reg64 source, int32_t r) { // packssdw mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); int32_t low = saturate_sd_to_sw(destination.u32[0]) | @@ -1467,7 +1423,6 @@ DEFINE_SSE_SPLIT(instr_0F6B, safe_read64s, read_mmx64s) void instr_660F6B(union reg128 source, int32_t r) { // packssdw xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); int32_t dword0 = saturate_sd_to_sw(destination.u32[0]) | @@ -1489,7 +1444,6 @@ void instr_0F6C_reg(int32_t r1, int32_t r2) { trigger_ud(); } void instr_660F6C(union reg128 source, int32_t r) { // punpcklqdq xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); write_xmm128(r, destination.u32[0], destination.u32[1], source.u32[0], source.u32[1]); @@ -1502,7 +1456,6 @@ void instr_0F6D_reg(int32_t r1, int32_t r2) { trigger_ud(); } void instr_660F6D(union reg128 source, int32_t r) { // punpckhqdq xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); write_xmm128(r, destination.u32[2], destination.u32[3], source.u32[2], source.u32[3]); @@ -1511,21 +1464,18 @@ DEFINE_SSE_SPLIT(instr_660F6D, safe_read128s, read_xmm128s) void instr_0F6E(int32_t source, int32_t r) { // movd mm, r/m32 - task_switch_test_mmx(); write_mmx64(r, source, 0); } DEFINE_SSE_SPLIT(instr_0F6E, safe_read32s, read_reg32) void instr_660F6E(int32_t source, int32_t r) { // movd mm, r/m32 - task_switch_test_mmx(); write_xmm128(r, source, 0, 0, 0); } DEFINE_SSE_SPLIT(instr_660F6E, safe_read32s, read_reg32) void instr_0F6F(union reg64 source, int32_t r) { // movq mm, mm/m64 - task_switch_test_mmx(); write_mmx64(r, source.u32[0], source.u32[1]); } DEFINE_SSE_SPLIT(instr_0F6F, safe_read64s, read_mmx64s) @@ -1545,7 +1495,6 @@ DEFINE_SSE_SPLIT(instr_F30F6F, safe_read128s, read_xmm128s) void instr_0F70(union reg64 source, int32_t r, int32_t imm8) { // pshufw mm1, mm2/m64, imm8 - task_switch_test_mmx(); int32_t word0_shift = imm8 & 0b11; uint32_t word0 = source.u32[word0_shift >> 1] >> ((word0_shift & 1) << 4) & 0xFFFF; @@ -1566,7 +1515,6 @@ DEFINE_SSE_SPLIT_IMM(instr_0F70, safe_read64s, read_mmx64s) void instr_660F70(union reg128 source, int32_t r, int32_t imm8) { // pshufd xmm, xmm/mem128 // XXX: Aligned access or #gp - task_switch_test_mmx(); write_xmm128( r, source.u32[imm8 & 3], @@ -1580,7 +1528,6 @@ DEFINE_SSE_SPLIT_IMM(instr_660F70, safe_read128s, read_xmm128s) void instr_F20F70(union reg128 source, int32_t r, int32_t imm8) { // pshuflw xmm, xmm/m128, imm8 // XXX: Aligned access or #gp - task_switch_test_mmx(); write_xmm128( r, source.u16[imm8 & 3] | source.u16[imm8 >> 2 & 3] << 16, @@ -1594,7 +1541,6 @@ DEFINE_SSE_SPLIT_IMM(instr_F20F70, safe_read128s, read_xmm128s) void instr_F30F70(union reg128 source, int32_t r, int32_t imm8) { // pshufhw xmm, xmm/m128, imm8 // XXX: Aligned access or #gp - task_switch_test_mmx(); write_xmm128( r, source.u32[0], @@ -1710,7 +1656,6 @@ void instr_660F73_2_reg(int32_t r, int32_t imm8) { void instr_660F73_3_reg(int32_t r, int32_t imm8) { // psrldq xmm, imm8 - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); if(imm8 == 0) @@ -1743,7 +1688,6 @@ void instr_660F73_6_reg(int32_t r, int32_t imm8) { void instr_660F73_7_reg(int32_t r, int32_t imm8) { // pslldq xmm, imm8 - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); if(imm8 == 0) @@ -1770,7 +1714,6 @@ void instr_660F73_7_reg(int32_t r, int32_t imm8) { void instr_0F74(union reg64 source, int32_t r) { // pcmpeqb mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -1786,7 +1729,6 @@ DEFINE_SSE_SPLIT(instr_0F74, safe_read64s, read_mmx64s) void instr_660F74(union reg128 source, int32_t r) { // pcmpeqb xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -1802,7 +1744,6 @@ DEFINE_SSE_SPLIT(instr_660F74, safe_read128s, read_xmm128s) void instr_0F75(union reg64 source, int32_t r) { // pcmpeqw mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); int32_t word0 = destination.u16[0] == source.u16[0] ? 0xFFFF : 0; @@ -1820,7 +1761,6 @@ DEFINE_SSE_SPLIT(instr_0F75, safe_read64s, read_mmx64s) void instr_660F75(union reg128 source, int32_t r) { // pcmpeqw xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -1835,7 +1775,6 @@ DEFINE_SSE_SPLIT(instr_660F75, safe_read128s, read_xmm128s) void instr_0F76(union reg64 source, int32_t r) { // pcmpeqd mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); int32_t low = destination.u32[0] == source.u32[0] ? -1 : 0; @@ -1848,7 +1787,6 @@ DEFINE_SSE_SPLIT(instr_0F76, safe_read64s, read_mmx64s) void instr_660F76(union reg128 source, int32_t r) { // pcmpeqd xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); write_xmm128( @@ -1863,16 +1801,6 @@ DEFINE_SSE_SPLIT(instr_660F76, safe_read128s, read_xmm128s) void instr_0F77() { // emms - - if(cr[0] & (CR0_EM | CR0_TS)) { - if(cr[0] & CR0_TS) { - trigger_nm(); - } - else { - trigger_ud(); - } - } - fpu_set_tag_word(0xFFFF); } @@ -1885,27 +1813,23 @@ void instr_0F7D() { unimplemented_sse(); } int32_t instr_0F7E(int32_t r) { // movd r/m32, mm - task_switch_test_mmx(); union reg64 data = read_mmx64s(r); return data.u32[0]; } DEFINE_SSE_SPLIT_WRITE(instr_0F7E, safe_write32, write_reg32) int32_t instr_660F7E(int32_t r) { // movd r/m32, xmm - task_switch_test_mmx(); union reg64 data = read_xmm64s(r); return data.u32[0]; } DEFINE_SSE_SPLIT_WRITE(instr_660F7E, safe_write32, write_reg32) void instr_F30F7E_mem(int32_t addr, int32_t r) { // movq xmm, xmm/mem64 - task_switch_test_mmx(); union reg64 data = safe_read64s(addr); write_xmm128(r, data.u32[0], data.u32[1], 0, 0); } 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); } @@ -1916,7 +1840,6 @@ void instr_0F7F_mem(int32_t addr, int32_t r) { } 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]); } @@ -2349,7 +2272,6 @@ void instr_0FC3_mem(int32_t addr, int32_t r) { void instr_0FC4(int32_t source, int32_t r, int32_t imm8) { // pinsrw mm, r32/m16, imm8 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); uint32_t index = imm8 & 3; @@ -2361,7 +2283,6 @@ DEFINE_SSE_SPLIT_IMM(instr_0FC4, read16, read_reg32) void instr_660FC4(int32_t source, int32_t r, int32_t imm8) { // pinsrw xmm, r32/m16, imm8 - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); uint32_t index = imm8 & 7; @@ -2374,7 +2295,6 @@ DEFINE_SSE_SPLIT_IMM(instr_660FC4, read16, read_reg32) void instr_0FC5_mem(int32_t addr, int32_t r, int32_t imm8) { trigger_ud(); } void instr_0FC5_reg(int32_t r1, int32_t r2, int32_t imm8) { // pextrw r32, mm, imm8 - task_switch_test_mmx(); union reg64 data = read_mmx64s(r1); uint32_t index = imm8 & 3; @@ -2386,7 +2306,6 @@ void instr_0FC5_reg(int32_t r1, int32_t r2, int32_t imm8) { void instr_660FC5_mem(int32_t addr, int32_t r, int32_t imm8) { trigger_ud(); } void instr_660FC5_reg(int32_t r1, int32_t r2, int32_t imm8) { // pextrw r32, xmm, imm8 - task_switch_test_mmx(); union reg128 data = read_xmm128s(r1); uint32_t index = imm8 & 7; @@ -2499,7 +2418,6 @@ DEFINE_SSE_SPLIT(instr_660FD3, safe_read128s, read_xmm128s) void instr_0FD4(union reg64 source, int32_t r) { // paddq mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); destination.u64[0] += source.u64[0]; write_mmx_reg64(r, destination); @@ -2509,7 +2427,6 @@ DEFINE_SSE_SPLIT(instr_0FD4, safe_read64s, read_mmx64s) void instr_660FD4(union reg128 source, int32_t r) { // paddq xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); destination.u64[0] += source.u64[0]; destination.u64[1] += source.u64[1]; @@ -2519,7 +2436,6 @@ DEFINE_SSE_SPLIT(instr_660FD4, safe_read128s, read_xmm128s) void instr_0FD5(union reg64 source, int32_t r) { // pmullw mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); @@ -2538,7 +2454,6 @@ DEFINE_SSE_SPLIT(instr_0FD5, safe_read64s, read_mmx64s) void instr_660FD5(union reg128 source, int32_t r) { // pmullw xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); write_xmm128( @@ -2560,7 +2475,6 @@ void instr_660FD6_mem(int32_t addr, int32_t r) { } 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); } @@ -2568,7 +2482,6 @@ void instr_660FD6_reg(int32_t r1, int32_t r2) { void instr_F20FD6_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_F20FD6_reg(int32_t r1, int32_t r2) { // movdq2q mm, xmm - task_switch_test_mmx(); union reg128 source = read_xmm128s(r1); write_mmx64(r2, source.u32[0], source.u32[1]); } @@ -2576,7 +2489,6 @@ void instr_F20FD6_reg(int32_t r1, int32_t r2) { void instr_F30FD6_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_F30FD6_reg(int32_t r1, int32_t r2) { // movq2dq xmm, mm - task_switch_test_mmx(); union reg64 source = read_mmx64s(r1); write_xmm128(r2, source.u32[0], source.u32[1], 0, 0); } @@ -2584,7 +2496,6 @@ void instr_F30FD6_reg(int32_t r1, int32_t r2) { void instr_0FD7_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_0FD7_reg(int32_t r1, int32_t r2) { // pmovmskb r, mm - task_switch_test_mmx(); union reg64 x = read_mmx64s(r1); uint32_t result = x.u8[0] >> 7 << 0 | x.u8[1] >> 7 << 1 | x.u8[2] >> 7 << 2 | x.u8[3] >> 7 << 3 | @@ -2595,7 +2506,6 @@ void instr_0FD7_reg(int32_t r1, int32_t r2) { void instr_660FD7_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_660FD7_reg(int32_t r1, int32_t r2) { // pmovmskb reg, xmm - task_switch_test_mmx(); union reg128 x = read_xmm128s(r1); int32_t result = @@ -2608,7 +2518,6 @@ void instr_660FD7_reg(int32_t r1, int32_t r2) { void instr_0FD8(union reg64 source, int32_t r) { // psubusb mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -2624,7 +2533,6 @@ DEFINE_SSE_SPLIT(instr_0FD8, safe_read64s, read_mmx64s) void instr_660FD8(union reg128 source, int32_t r) { // psubusb xmm, xmm/m128 - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -2640,7 +2548,6 @@ DEFINE_SSE_SPLIT(instr_660FD8, safe_read128s, read_xmm128s) void instr_0FD9(union reg64 source, int32_t r) { // psubusw mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); @@ -2658,7 +2565,6 @@ DEFINE_SSE_SPLIT(instr_0FD9, safe_read64s, read_mmx64s) void instr_660FD9(union reg128 source, int32_t r) { // psubusw xmm, xmm/m128 - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -2674,7 +2580,6 @@ DEFINE_SSE_SPLIT(instr_660FD9, safe_read128s, read_xmm128s) void instr_0FDA(union reg64 source, int32_t r) { // pminub mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); union reg64 result; @@ -2691,7 +2596,6 @@ DEFINE_SSE_SPLIT(instr_0FDA, safe_read64s, read_mmx64s) void instr_660FDA(union reg128 source, int32_t r) { // pminub xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -2707,7 +2611,6 @@ DEFINE_SSE_SPLIT(instr_660FDA, safe_read128s, read_xmm128s) void instr_0FDB(union reg64 source, int32_t r) { // pand mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -2727,7 +2630,6 @@ DEFINE_SSE_SPLIT(instr_660FDB, safe_read128s, read_xmm128s) void instr_0FDC(union reg64 source, int32_t r) { // paddusb mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -2744,7 +2646,6 @@ DEFINE_SSE_SPLIT(instr_0FDC, safe_read64s, read_mmx64s) void instr_660FDC(union reg128 source, int32_t r) { // paddusb xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -2760,7 +2661,6 @@ DEFINE_SSE_SPLIT(instr_660FDC, safe_read128s, read_xmm128s) void instr_0FDD(union reg64 source, int32_t r) { // paddusw mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); @@ -2779,7 +2679,6 @@ DEFINE_SSE_SPLIT(instr_0FDD, safe_read64s, read_mmx64s) void instr_660FDD(union reg128 source, int32_t r) { // paddusw xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); @@ -2795,7 +2694,6 @@ DEFINE_SSE_SPLIT(instr_660FDD, safe_read128s, read_xmm128s) void instr_0FDE(union reg64 source, int32_t r) { // pmaxub mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); union reg64 result; @@ -2812,7 +2710,6 @@ DEFINE_SSE_SPLIT(instr_0FDE, safe_read64s, read_mmx64s) void instr_660FDE(union reg128 source, int32_t r) { // pmaxub xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -2828,7 +2725,6 @@ DEFINE_SSE_SPLIT(instr_660FDE, safe_read128s, read_xmm128s) void instr_0FDF(union reg64 source, int32_t r) { // pandn mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -2848,7 +2744,6 @@ DEFINE_SSE_SPLIT(instr_660FDF, safe_read128s, read_xmm128s) void instr_0FE0(union reg64 source, int32_t r) { // pavgb mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -2864,7 +2759,6 @@ DEFINE_SSE_SPLIT(instr_0FE0, safe_read64s, read_mmx64s) void instr_660FE0(union reg128 source, int32_t r) { // pavgb xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -2905,7 +2799,6 @@ DEFINE_SSE_SPLIT(instr_660FE2, safe_read128s, read_xmm128s) void instr_0FE3(union reg64 source, int32_t r) { // pavgw mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); destination.u16[0] = (destination.u16[0] + source.u16[0] + 1) >> 1; @@ -2920,7 +2813,6 @@ DEFINE_SSE_SPLIT(instr_0FE3, safe_read64s, read_mmx64s) void instr_660FE3(union reg128 source, int32_t r) { // pavgw xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); destination.u16[0] = (destination.u16[0] + source.u16[0] + 1) >> 1; @@ -2938,7 +2830,6 @@ DEFINE_SSE_SPLIT(instr_660FE3, safe_read128s, read_xmm128s) void instr_0FE4(union reg64 source, int32_t r) { // pmulhuw mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); @@ -2953,7 +2844,6 @@ DEFINE_SSE_SPLIT(instr_0FE4, safe_read64s, read_mmx64s) void instr_660FE4(union reg128 source, int32_t r) { // pmulhuw xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); @@ -2969,7 +2859,6 @@ DEFINE_SSE_SPLIT(instr_660FE4, safe_read128s, read_xmm128s) void instr_0FE5(union reg64 source, int32_t r) { // pmulhw mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); @@ -2988,7 +2877,6 @@ DEFINE_SSE_SPLIT(instr_0FE5, safe_read64s, read_mmx64s) void instr_660FE5(union reg128 source, int32_t r) { // pmulhw xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); @@ -3028,7 +2916,6 @@ void instr_660FE7_mem(int32_t addr, int32_t r) { void instr_0FE8(union reg64 source, int32_t r) { // psubsb mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -3045,7 +2932,6 @@ DEFINE_SSE_SPLIT(instr_0FE8, safe_read64s, read_mmx64s) void instr_660FE8(union reg128 source, int32_t r) { // psubsb xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -3061,7 +2947,6 @@ DEFINE_SSE_SPLIT(instr_660FE8, safe_read128s, read_xmm128s) void instr_0FE9(union reg64 source, int32_t r) { // psubsw mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); @@ -3080,7 +2965,6 @@ DEFINE_SSE_SPLIT(instr_0FE9, safe_read64s, read_mmx64s) void instr_660FE9(union reg128 source, int32_t r) { // psubsw xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); @@ -3099,7 +2983,6 @@ DEFINE_SSE_SPLIT(instr_660FE9, safe_read128s, read_xmm128s) void instr_0FEA(union reg64 source, int32_t r) { // pminsw mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); union reg64 result; @@ -3116,7 +2999,6 @@ DEFINE_SSE_SPLIT(instr_0FEA, safe_read64s, read_mmx64s) void instr_660FEA(union reg128 source, int32_t r) { // pminsw xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -3132,7 +3014,6 @@ DEFINE_SSE_SPLIT(instr_660FEA, safe_read128s, read_xmm128s) void instr_0FEB(union reg64 source, int32_t r) { // por mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -3152,7 +3033,6 @@ DEFINE_SSE_SPLIT(instr_660FEB, safe_read128s, read_xmm128s) void instr_0FEC(union reg64 source, int32_t r) { // paddsb mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -3169,7 +3049,6 @@ DEFINE_SSE_SPLIT(instr_0FEC, safe_read64s, read_mmx64s) void instr_660FEC(union reg128 source, int32_t r) { // paddsb xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -3185,7 +3064,6 @@ DEFINE_SSE_SPLIT(instr_660FEC, safe_read128s, read_xmm128s) void instr_0FED(union reg64 source, int32_t r) { // paddsw mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); @@ -3204,7 +3082,6 @@ DEFINE_SSE_SPLIT(instr_0FED, safe_read64s, read_mmx64s) void instr_660FED(union reg128 source, int32_t r) { // paddsw xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); @@ -3223,7 +3100,6 @@ DEFINE_SSE_SPLIT(instr_660FED, safe_read128s, read_xmm128s) void instr_0FEE(union reg64 source, int32_t r) { // pmaxsw mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); union reg64 result; @@ -3240,7 +3116,6 @@ DEFINE_SSE_SPLIT(instr_0FEE, safe_read64s, read_mmx64s) void instr_660FEE(union reg128 source, int32_t r) { // pmaxsw xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -3256,7 +3131,6 @@ DEFINE_SSE_SPLIT(instr_660FEE, safe_read128s, read_xmm128s) void instr_0FEF(union reg64 source, int32_t r) { // pxor mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -3316,7 +3190,6 @@ DEFINE_SSE_SPLIT(instr_660FF3, safe_read128s, read_xmm128s) void instr_0FF4(union reg64 source, int32_t r) { // pmuludq mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); destination.u64[0] = (uint64_t) source.u32[0] * (uint64_t) destination.u32[0]; @@ -3327,7 +3200,6 @@ DEFINE_SSE_SPLIT(instr_0FF4, safe_read64s, read_mmx64s) void instr_660FF4(union reg128 source, int32_t r) { // pmuludq xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); destination.u64[0] = (uint64_t) source.u32[0] * (uint64_t) destination.u32[0]; @@ -3338,7 +3210,6 @@ DEFINE_SSE_SPLIT(instr_660FF4, safe_read128s, read_xmm128s) void instr_0FF5(union reg64 source, int32_t r) { // pmaddwd mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); @@ -3357,7 +3228,6 @@ DEFINE_SSE_SPLIT(instr_0FF5, safe_read64s, read_mmx64s) void instr_660FF5(union reg128 source, int32_t r) { // pmaddwd xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); @@ -3376,7 +3246,6 @@ DEFINE_SSE_SPLIT(instr_660FF5, safe_read128s, read_xmm128s) void instr_0FF6(union reg64 source, int32_t r) { // psadbw mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); uint32_t sum = 0; @@ -3392,7 +3261,6 @@ DEFINE_SSE_SPLIT(instr_0FF6, safe_read64s, read_mmx64s) void instr_660FF6(union reg128 source, int32_t r) { // psadbw xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); uint32_t sum0 = 0; uint32_t sum1 = 0; @@ -3410,7 +3278,6 @@ DEFINE_SSE_SPLIT(instr_660FF6, safe_read128s, read_xmm128s) void instr_0FF7_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_0FF7_reg(int32_t r1, int32_t r2) { // maskmovq mm, mm - task_switch_test_mmx(); union reg64 source = read_mmx64s(r2); union reg64 mask = read_mmx64s(r1); int32_t addr = get_seg_prefix(DS) + get_reg_asize(EDI); @@ -3428,7 +3295,6 @@ void instr_0FF7_reg(int32_t r1, int32_t r2) { void instr_660FF7_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_660FF7_reg(int32_t r1, int32_t r2) { // maskmovdqu xmm, xmm - task_switch_test_mmx(); union reg128 source = read_xmm128s(r2); union reg128 mask = read_xmm128s(r1); int32_t addr = get_seg_prefix(DS) + get_reg_asize(EDI); @@ -3445,7 +3311,6 @@ void instr_660FF7_reg(int32_t r1, int32_t r2) { void instr_0FF8(union reg64 source, int32_t r) { // psubb mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -3462,7 +3327,6 @@ DEFINE_SSE_SPLIT(instr_0FF8, safe_read64s, read_mmx64s) void instr_660FF8(union reg128 source, int32_t r) { // psubb xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); union reg128 result = { { 0 } }; @@ -3478,7 +3342,6 @@ DEFINE_SSE_SPLIT(instr_660FF8, safe_read128s, read_xmm128s) void instr_0FF9(union reg64 source, int32_t r) { // psubw mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); @@ -3497,7 +3360,6 @@ DEFINE_SSE_SPLIT(instr_0FF9, safe_read64s, read_mmx64s) void instr_660FF9(union reg128 source, int32_t r) { // psubw xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); union reg128 result = { { 0 } }; @@ -3513,7 +3375,6 @@ DEFINE_SSE_SPLIT(instr_660FF9, safe_read128s, read_xmm128s) void instr_0FFA(union reg64 source, int32_t r) { // psubd mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); @@ -3528,7 +3389,6 @@ DEFINE_SSE_SPLIT(instr_0FFA, safe_read64s, read_mmx64s) void instr_660FFA(union reg128 source, int32_t r) { // psubd xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); @@ -3544,7 +3404,6 @@ DEFINE_SSE_SPLIT(instr_660FFA, safe_read128s, read_xmm128s) void instr_0FFB(union reg64 source, int32_t r) { // psubq mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); destination.u64[0] = destination.u64[0] - source.u64[0]; @@ -3555,7 +3414,6 @@ DEFINE_SSE_SPLIT(instr_0FFB, safe_read64s, read_mmx64s) void instr_660FFB(union reg128 source, int32_t r) { // psubq xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); destination.u64[0] = destination.u64[0] - source.u64[0]; @@ -3567,7 +3425,6 @@ DEFINE_SSE_SPLIT(instr_660FFB, safe_read128s, read_xmm128s) void instr_0FFC(union reg64 source, int32_t r) { // paddb mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -3584,7 +3441,6 @@ DEFINE_SSE_SPLIT(instr_0FFC, safe_read64s, read_mmx64s) void instr_660FFC(union reg128 source, int32_t r) { // paddb xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); union reg128 result = { { 0 } }; @@ -3600,7 +3456,6 @@ DEFINE_SSE_SPLIT(instr_660FFC, safe_read128s, read_xmm128s) void instr_0FFD(union reg64 source, int32_t r) { // paddw mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); @@ -3619,7 +3474,6 @@ DEFINE_SSE_SPLIT(instr_0FFD, safe_read64s, read_mmx64s) void instr_660FFD(union reg128 source, int32_t r) { // paddw xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); union reg128 result = { { 0 } }; @@ -3635,7 +3489,6 @@ DEFINE_SSE_SPLIT(instr_660FFD, safe_read128s, read_xmm128s) void instr_0FFE(union reg64 source, int32_t r) { // paddd mm, mm/m64 - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); @@ -3649,7 +3502,6 @@ DEFINE_SSE_SPLIT(instr_0FFE, safe_read64s, read_mmx64s) void instr_660FFE(union reg128 source, int32_t r) { // paddd xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); diff --git a/src/native/sse_instr.c b/src/native/sse_instr.c index 7061f57e..058c05ee 100644 --- a/src/native/sse_instr.c +++ b/src/native/sse_instr.c @@ -7,7 +7,6 @@ void mov_r_m64(int32_t addr, int32_t r) { // mov* m64, mm - task_switch_test_mmx(); union reg64 data = read_mmx64s(r); safe_write64(addr, data.u64[0]); } @@ -15,7 +14,6 @@ void mov_r_m64(int32_t addr, int32_t r) void movl_r128_m64(int32_t addr, int32_t r) { // mov* m64, xmm - task_switch_test_mmx(); union reg64 data = read_xmm64s(r); safe_write64(addr, data.u64[0]); } @@ -23,7 +21,6 @@ void movl_r128_m64(int32_t addr, int32_t r) void mov_r_r128(int32_t r1, int32_t r2) { // mov* xmm, xmm - task_switch_test_mmx(); union reg128 data = read_xmm128s(r2); write_xmm_reg128(r1, data); } @@ -31,7 +28,6 @@ void mov_r_r128(int32_t r1, int32_t r2) void mov_r_m128(int32_t addr, int32_t r) { // mov* m128, xmm - task_switch_test_mmx(); union reg128 data = read_xmm128s(r); safe_write128(addr, data); } @@ -39,14 +35,12 @@ void mov_r_m128(int32_t addr, int32_t r) void mov_rm_r128(union reg128 source, int32_t r) { // mov* xmm, xmm/m128 - task_switch_test_mmx(); write_xmm_reg128(r, source); } void movh_m64_r128(int32_t addr, int32_t r) { // movhp* xmm, m64 - task_switch_test_mmx(); union reg64 data = safe_read64s(addr); union reg128 orig = read_xmm128s(r); write_xmm128(r, orig.u32[0], orig.u32[1], data.u32[0], data.u32[1]); @@ -55,7 +49,6 @@ void movh_m64_r128(int32_t addr, int32_t r) void movh_r128_m64(int32_t addr, int32_t r) { // movhp* m64, xmm - task_switch_test_mmx(); union reg128 data = read_xmm128s(r); safe_write64(addr, data.u64[1]); } @@ -64,7 +57,6 @@ void pand_r128(union reg128 source, int32_t r) { // pand xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); union reg128 result = { { 0 } }; @@ -79,7 +71,6 @@ void pandn_r128(union reg128 source, int32_t r) { // pandn xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); union reg128 result = { { 0 } }; @@ -94,7 +85,6 @@ void pxor_r128(union reg128 source, int32_t r) { // pxor xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); union reg128 result = { { 0 } }; @@ -109,7 +99,6 @@ void por_r128(union reg128 source, int32_t r) { // por xmm, xmm/m128 // XXX: Aligned access or #gp - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); union reg128 result = { { 0 } }; @@ -123,7 +112,6 @@ void por_r128(union reg128 source, int32_t r) void psrlw_r64(int32_t r, uint32_t shift) { // psrlw mm, {shift} - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); int32_t dword0 = 0; int32_t dword1 = 0; @@ -140,7 +128,6 @@ void psrlw_r64(int32_t r, uint32_t shift) void psraw_r64(int32_t r, uint32_t shift) { // psraw mm, {shift} - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); int32_t shift_clamped = shift > 15 ? 16 : shift; @@ -154,7 +141,6 @@ void psraw_r64(int32_t r, uint32_t shift) void psllw_r64(int32_t r, uint32_t shift) { // psllw mm, {shift} - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); int32_t dword0 = 0; @@ -174,7 +160,6 @@ void psllw_r64(int32_t r, uint32_t shift) void psrld_r64(int32_t r, uint32_t shift) { // psrld mm, {shift} - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); int32_t dword0 = 0; @@ -192,7 +177,6 @@ void psrld_r64(int32_t r, uint32_t shift) void psrad_r64(int32_t r, uint32_t shift) { // psrad mm, {shift} - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); int32_t shift_clamped = shift > 31 ? 31 : shift; @@ -205,7 +189,6 @@ void psrad_r64(int32_t r, uint32_t shift) void pslld_r64(int32_t r, uint32_t shift) { // pslld mm, {shift} - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); int32_t dword0 = 0; @@ -223,7 +206,6 @@ void pslld_r64(int32_t r, uint32_t shift) void psrlq_r64(int32_t r, uint32_t shift) { // psrlq mm, {shift} - task_switch_test_mmx(); if(shift == 0) { @@ -244,7 +226,6 @@ void psrlq_r64(int32_t r, uint32_t shift) void psllq_r64(int32_t r, uint32_t shift) { // psllq mm, {shift} - task_switch_test_mmx(); union reg64 destination = read_mmx64s(r); if(shift == 0) @@ -265,7 +246,6 @@ void psllq_r64(int32_t r, uint32_t shift) void psrlw_r128(int32_t r, uint32_t shift) { // psrlw xmm, {shift} - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); int32_t dword0 = 0; int32_t dword1 = 0; @@ -286,7 +266,6 @@ void psrlw_r128(int32_t r, uint32_t shift) void psraw_r128(int32_t r, uint32_t shift) { // psraw xmm, {shift} - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); int32_t shift_clamped = shift > 15 ? 16 : shift; @@ -304,7 +283,6 @@ void psraw_r128(int32_t r, uint32_t shift) void psllw_r128(int32_t r, uint32_t shift) { // psllw xmm, {shift} - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); int32_t dword0 = 0; @@ -326,7 +304,6 @@ void psllw_r128(int32_t r, uint32_t shift) void psrld_r128(int32_t r, uint32_t shift) { // psrld xmm, {shift} - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); int32_t dword0 = 0; @@ -348,7 +325,6 @@ void psrld_r128(int32_t r, uint32_t shift) void psrad_r128(int32_t r, uint32_t shift) { // psrad xmm, {shift} - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); int32_t shift_clamped = shift > 31 ? 31 : shift; @@ -363,7 +339,6 @@ void psrad_r128(int32_t r, uint32_t shift) void pslld_r128(int32_t r, uint32_t shift) { // pslld xmm, {shift} - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); int32_t dword0 = 0; @@ -385,7 +360,6 @@ void pslld_r128(int32_t r, uint32_t shift) void psrlq_r128(int32_t r, uint32_t shift) { // psrlq xmm, {shift} - task_switch_test_mmx(); if(shift == 0) { @@ -407,7 +381,6 @@ void psrlq_r128(int32_t r, uint32_t shift) void psllq_r128(int32_t r, uint32_t shift) { // psllq xmm, {shift} - task_switch_test_mmx(); union reg128 destination = read_xmm128s(r); if(shift == 0) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 885ba8fe..050c1e3f 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -572,3 +572,42 @@ pub fn gen_pop32s(ctx: &mut JitContext) { gen_pop32s_ss16(ctx); } } + +pub fn gen_task_switch_test(ctx: &mut JitContext) { + // generate if(cr[0] & (CR0_EM | CR0_TS)) { task_switch_test_void(); return; } + + let cr0_offset = global_pointers::get_creg_offset(0); + + wasm_util::load_aligned_i32(&mut ctx.builder.instruction_body, cr0_offset); + wasm_util::push_i32( + &mut ctx.builder.instruction_body, + (regs::CR0_EM | regs::CR0_TS) as i32, + ); + wasm_util::and_i32(&mut ctx.builder.instruction_body); + + wasm_util::if_void(&mut ctx.builder.instruction_body); + + gen_fn0_const(ctx, "task_switch_test_void"); + wasm_util::return_(&mut ctx.builder.instruction_body); + + wasm_util::block_end(&mut ctx.builder.instruction_body); +} + +pub fn gen_task_switch_test_mmx(ctx: &mut JitContext) { + // generate if(cr[0] & (CR0_EM | CR0_TS)) { task_switch_test_mmx_void(); return; } + let cr0_offset = global_pointers::get_creg_offset(0); + + wasm_util::load_aligned_i32(&mut ctx.builder.instruction_body, cr0_offset); + wasm_util::push_i32( + &mut ctx.builder.instruction_body, + (regs::CR0_EM | regs::CR0_TS) as i32, + ); + wasm_util::and_i32(&mut ctx.builder.instruction_body); + + wasm_util::if_void(&mut ctx.builder.instruction_body); + + gen_fn0_const(ctx, "task_switch_test_mmx_void"); + wasm_util::return_(&mut ctx.builder.instruction_body); + + wasm_util::block_end(&mut ctx.builder.instruction_body); +} diff --git a/src/rust/global_pointers.rs b/src/rust/global_pointers.rs index 9c856845..0ec1b60d 100644 --- a/src/rust/global_pointers.rs +++ b/src/rust/global_pointers.rs @@ -1,6 +1,7 @@ pub const REG: u32 = 4; pub const INSTRUCTION_POINTER: u32 = 556; pub const PREVIOUS_IP: u32 = 560; +pub const CR: u32 = 580; pub const PREFIXES: u32 = 648; pub const TIMESTAMP_COUNTER: u32 = 664; pub const SEGMENT_OFFSETS: u32 = 736; @@ -17,7 +18,13 @@ pub fn get_reg32_offset(r: u32) -> u32 { dbg_assert!(r < 8); REG + 4 * r } + pub fn get_seg_offset(s: u32) -> u32 { dbg_assert!(s < 8); SEGMENT_OFFSETS + 4 * s } + +pub fn get_creg_offset(cr: u32) -> u32 { + dbg_assert!(cr < 8); + CR + 4 * cr +} diff --git a/src/rust/regs.rs b/src/rust/regs.rs index 25113828..4f32dce2 100644 --- a/src/rust/regs.rs +++ b/src/rust/regs.rs @@ -23,3 +23,6 @@ pub const SP: u32 = 4; pub const BP: u32 = 5; pub const SI: u32 = 6; pub const DI: u32 = 7; + +pub const CR0_EM: u32 = 1 << 2; +pub const CR0_TS: u32 = 1 << 3; From e0aabb29373ae5fdda8d44cc996c0de77221c2f4 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 25 Jul 2018 11:21:47 -0600 Subject: [PATCH 1082/2137] Mark hintable nops as non-faulting --- gen/x86_table.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index c2e1e7e1..b356a158 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -301,13 +301,13 @@ const encodings = [ { opcode: 0x0F0F, skip: 1 }, { opcode: 0x0F18, only_mem: 1, e: 1, }, - { opcode: 0x0F19, custom: 1, e: 1, }, - { opcode: 0x0F1A, custom: 1, e: 1, }, - { opcode: 0x0F1B, custom: 1, e: 1, }, - { opcode: 0x0F1C, custom: 1, e: 1, }, - { opcode: 0x0F1D, custom: 1, e: 1, }, - { opcode: 0x0F1E, custom: 1, e: 1, }, - { opcode: 0x0F1F, custom: 1, e: 1, }, + { opcode: 0x0F19, non_faulting: 1, custom: 1, e: 1, }, + { opcode: 0x0F1A, non_faulting: 1, custom: 1, e: 1, }, + { opcode: 0x0F1B, non_faulting: 1, custom: 1, e: 1, }, + { opcode: 0x0F1C, non_faulting: 1, custom: 1, e: 1, }, + { opcode: 0x0F1D, non_faulting: 1, custom: 1, e: 1, }, + { opcode: 0x0F1E, non_faulting: 1, custom: 1, e: 1, }, + { opcode: 0x0F1F, non_faulting: 1, custom: 1, e: 1, }, { opcode: 0x0F20, ignore_mod: 1, e: 1, skip: 1, block_boundary: 1, }, // mov reg, creg { opcode: 0x0F21, ignore_mod: 1, e: 1, skip: 1, block_boundary: 1, }, // mov reg, dreg From 49961ade7cdfb87fb21327ec1bc7014ecf6dba6b Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 25 Jul 2018 15:23:03 -0600 Subject: [PATCH 1083/2137] Remove hintable nops that were refitted for mpx instructions --- gen/x86_table.js | 4 ++-- src/native/instructions_0f.c | 6 ++---- src/rust/jit_instructions.rs | 9 +-------- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index b356a158..582bb1e1 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -302,8 +302,8 @@ const encodings = [ { opcode: 0x0F18, only_mem: 1, e: 1, }, { opcode: 0x0F19, non_faulting: 1, custom: 1, e: 1, }, - { opcode: 0x0F1A, non_faulting: 1, custom: 1, e: 1, }, - { opcode: 0x0F1B, non_faulting: 1, custom: 1, e: 1, }, + { opcode: 0x0F1A, skip: 1, }, + { opcode: 0x0F1B, skip: 1, }, { opcode: 0x0F1C, non_faulting: 1, custom: 1, e: 1, }, { opcode: 0x0F1D, non_faulting: 1, custom: 1, e: 1, }, { opcode: 0x0F1E, non_faulting: 1, custom: 1, e: 1, }, diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 49b2455c..821597d1 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -422,10 +422,8 @@ void instr_0F18_mem(int32_t addr, int32_t r) { // hintable nops void instr_0F19_reg(int32_t r1, int32_t r2) { } void instr_0F19_mem(int32_t addr, int32_t r) { } -void instr_0F1A_reg(int32_t r1, int32_t r2) { } -void instr_0F1A_mem(int32_t addr, int32_t r) { } -void instr_0F1B_reg(int32_t r1, int32_t r2) { } -void instr_0F1B_mem(int32_t addr, int32_t r) { } +void instr_0F1A() { todo(); trigger_ud(); } +void instr_0F1B() { todo(); trigger_ud(); } void instr_0F1C_reg(int32_t r1, int32_t r2) { } void instr_0F1C_mem(int32_t addr, int32_t r) { } void instr_0F1D_reg(int32_t r1, int32_t r2) { } diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 322e6371..9f7b22b6 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -451,14 +451,7 @@ pub fn instr_0F19_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) { modrm::skip(ctx.cpu, modrm_byte); } pub fn instr_0F19_reg_jit(_ctx: &mut JitContext, _r1: u32, _r2: u32) {} -pub fn instr_0F1A_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) { - modrm::skip(ctx.cpu, modrm_byte); -} -pub fn instr_0F1A_reg_jit(_ctx: &mut JitContext, _r1: u32, _r2: u32) {} -pub fn instr_0F1B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) { - modrm::skip(ctx.cpu, modrm_byte); -} -pub fn instr_0F1B_reg_jit(_ctx: &mut JitContext, _r1: u32, _r2: u32) {} + pub fn instr_0F1C_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) { modrm::skip(ctx.cpu, modrm_byte); } From b3c14214a6478aaaa942c8adccc72a53df582e77 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 25 Jul 2018 15:28:59 -0600 Subject: [PATCH 1084/2137] Dynamically check cpu exceptions --- src/native/config.h | 2 ++ src/native/cpu.c | 49 ++++++++++++++++++++++++++++++++++++++++++++- src/rust/config.rs | 1 + src/rust/jit.rs | 12 +++++++++++ src/rust/lib.rs | 1 + 5 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 src/rust/config.rs diff --git a/src/native/config.h b/src/native/config.h index 014af9fc..e6892c81 100644 --- a/src/native/config.h +++ b/src/native/config.h @@ -20,6 +20,8 @@ #define ENABLE_JIT 1 +#define CHECK_CPU_EXCEPTIONS 0 + #define ENABLE_PROFILER 0 #define ENABLE_PROFILER_OPSTATS 0 #define ENABLE_PROFILER_SAFE_READ_WRITE 0 diff --git a/src/native/cpu.c b/src/native/cpu.c index 9512fe80..e3d7c307 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -21,6 +21,24 @@ bool must_not_fault = false; #endif +#if CHECK_CPU_EXCEPTIONS +int32_t current_cpu_exception = -1; +void assert_no_cpu_exception() { + if(current_cpu_exception != -1) + { + dbg_log("Expected no cpu exception, got %d", current_cpu_exception); + dbg_trace(); + assert(false); + } +} +void set_current_cpu_exception(int32_t n) { current_cpu_exception = n; } +void clear_current_cpu_exception() { current_cpu_exception = -1; } +#else +void assert_no_cpu_exception() {} +void set_current_cpu_exception(int32_t n) { UNUSED(n); } +void clear_current_cpu_exception() { } +#endif + uint64_t tsc_offset = 0; bool jit_block_boundary = false; @@ -618,6 +636,8 @@ static void jit_run_interpreted(int32_t phys_addr) run_instruction(opcode | !!*is_32 << 8); + clear_current_cpu_exception(); + while(!jit_block_boundary && same_page(*previous_ip, *instruction_pointer)) { previous_ip[0] = instruction_pointer[0]; @@ -626,9 +646,11 @@ static void jit_run_interpreted(int32_t phys_addr) int32_t opcode = read_imm8(); #if DEBUG - logop(previous_ip[0], opcode); + logop(previous_ip[0], opcode); #endif run_instruction(opcode | !!*is_32 << 8); + + clear_current_cpu_exception(); } } @@ -671,6 +693,8 @@ void cycle_internal() uint16_t initial_state = entry >> 16; call_indirect1(wasm_table_index, initial_state); + clear_current_cpu_exception(); + // XXX: New clearing: This should fail on self-modifying code //assert(entry->start_addr == old_start_address); @@ -799,6 +823,7 @@ void trigger_de() #endif *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_DE, false, false, 0); + set_current_cpu_exception(CPU_EXCEPTION_DE); } __attribute__((noinline)) @@ -823,6 +848,7 @@ void trigger_ud_non_raising() #endif *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_UD, false, false, 0); + set_current_cpu_exception(CPU_EXCEPTION_UD); } __attribute__((noinline)) @@ -836,6 +862,7 @@ void trigger_nm() #endif *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_NM, false, false, 0); + set_current_cpu_exception(CPU_EXCEPTION_NM); } __attribute__((noinline)) @@ -849,6 +876,7 @@ void trigger_np(int32_t code) #endif *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_NP, false, true, code); + set_current_cpu_exception(CPU_EXCEPTION_NP); } __attribute__((noinline)) @@ -862,6 +890,7 @@ void trigger_ss(int32_t code) #endif *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_SS, false, true, code); + set_current_cpu_exception(CPU_EXCEPTION_SS); } __attribute__((noinline)) @@ -882,6 +911,7 @@ void trigger_gp_non_raising(int32_t code) #endif *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_GP, false, true, code); + set_current_cpu_exception(CPU_EXCEPTION_GP); } int32_t virt_boundary_read16(int32_t low, int32_t high) @@ -964,11 +994,13 @@ void virt_boundary_write32(int32_t low, int32_t high, int32_t value) int32_t safe_read8(int32_t addr) { + assert_no_cpu_exception(); return read8(translate_address_read(addr)); } int32_t safe_read16(int32_t addr) { + assert_no_cpu_exception(); if((addr & 0xFFF) == 0xFFF) { return safe_read8(addr) | safe_read8(addr + 1) << 8; @@ -995,6 +1027,7 @@ int32_t safe_read32s_slow(int32_t addr) __attribute__((always_inline)) int32_t safe_read32s(int32_t address) { + assert_no_cpu_exception(); #if 1 int32_t base = (uint32_t)address >> 12; int32_t entry = tlb_data[base]; @@ -1044,6 +1077,8 @@ int32_t safe_read32s(int32_t address) union reg64 safe_read64s(int32_t addr) { + assert_no_cpu_exception(); + union reg64 x; if((addr & 0xFFF) > (0x1000 - 8)) { @@ -1061,6 +1096,8 @@ union reg64 safe_read64s(int32_t addr) __attribute__((always_inline)) union reg128 safe_read128s(int32_t addr) { + assert_no_cpu_exception(); + union reg128 x; if((addr & 0xFFF) > (0x1000 - 16)) { @@ -1077,11 +1114,15 @@ union reg128 safe_read128s(int32_t addr) void safe_write8(int32_t addr, int32_t value) { + assert_no_cpu_exception(); + write8(translate_address_write(addr), value); } void safe_write16(int32_t addr, int32_t value) { + assert_no_cpu_exception(); + int32_t phys_low = translate_address_write(addr); if((addr & 0xFFF) == 0xFFF) @@ -1112,6 +1153,8 @@ void safe_write32_slow(int32_t addr, int32_t value) __attribute__((always_inline)) void safe_write32(int32_t address, int32_t value) { + assert_no_cpu_exception(); + #if 1 int32_t base = (uint32_t)address >> 12; int32_t entry = tlb_data[base]; @@ -1173,6 +1216,8 @@ void safe_write32(int32_t address, int32_t value) void safe_write64(int32_t addr, int64_t value) { + assert_no_cpu_exception(); + if((addr & 0xFFF) > (0x1000 - 8)) { writable_or_pagefault(addr, 8); @@ -1189,6 +1234,8 @@ void safe_write64(int32_t addr, int64_t value) __attribute__((always_inline)) void safe_write128(int32_t addr, union reg128 value) { + assert_no_cpu_exception(); + if((addr & 0xFFF) > (0x1000 - 16)) { writable_or_pagefault(addr, 16); diff --git a/src/rust/config.rs b/src/rust/config.rs new file mode 100644 index 00000000..3c1b712c --- /dev/null +++ b/src/rust/config.rs @@ -0,0 +1 @@ +pub const CHECK_CPU_EXCEPTIONS: bool = false; diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 6436fb7a..1d47a4f6 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -1072,6 +1072,18 @@ fn jit_generate_basic_block( jit_instructions::jit_instruction(&mut cpu, builder, &mut instruction_flags); let end_eip = cpu.eip; + #[cfg(debug_assertions)] + { + if ::config::CHECK_CPU_EXCEPTIONS { + // only the last instruction in each basic block is allowed to raise + if end_eip < stop_addr { + let fn_idx = + builder.get_fn_idx("assert_no_cpu_exception", module_init::FN0_TYPE_INDEX); + wasm_util::call_fn(&mut builder.instruction_body, fn_idx); + } + } + } + let instruction_length = end_eip - start_eip; was_block_boundary = instruction_flags & JIT_INSTR_BLOCK_BOUNDARY_FLAG != 0; diff --git a/src/rust/lib.rs b/src/rust/lib.rs index 9db6ba0f..fae5ea9d 100644 --- a/src/rust/lib.rs +++ b/src/rust/lib.rs @@ -9,6 +9,7 @@ pub mod c_api; mod analysis; mod codegen; +mod config; mod cpu; mod cpu_context; mod gen; From db52f652e29d2df43557719543e85e2ac26de61c Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 25 Jul 2018 15:31:08 -0600 Subject: [PATCH 1085/2137] Fix cpu exceptions raised due to port IO --- src/cpu.js | 7 +++++-- src/native/instructions.c | 24 ++++++++++++------------ src/native/js_imports.h | 2 +- src/native/string.c | 24 ++++++++++++------------ 4 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index 42fa2b39..41c04209 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -2977,7 +2977,7 @@ CPU.prototype.test_privileges_for_io = function(port, size) dbg_log("#GP for port io, 16-bit TSS port=" + h(port) + " size=" + size, LOG_CPU); CPU_LOG_VERBOSE && this.debug.dump_state(); this.trigger_gp_non_raising(0); - return; + return false; } var tsr_size = this.segment_limits[reg_tr]; @@ -3001,7 +3001,7 @@ CPU.prototype.test_privileges_for_io = function(port, size) if(!(port_info & mask)) { - return; + return true; } } } @@ -3009,7 +3009,10 @@ CPU.prototype.test_privileges_for_io = function(port, size) dbg_log("#GP for port io port=" + h(port) + " size=" + size, LOG_CPU); CPU_LOG_VERBOSE && this.debug.dump_state(); this.trigger_gp_non_raising(0); + return false; } + + return true; }; CPU.prototype.cpuid = function() diff --git a/src/native/instructions.c b/src/native/instructions.c index 41f2a39b..b0b59ba6 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -1281,27 +1281,27 @@ void instr32_E2(int32_t imm8s) { loop32(imm8s); } void instr32_E3(int32_t imm8s) { jcxz32(imm8s); } void instr_E4(int32_t port) { - test_privileges_for_io(port, 1); + if(!test_privileges_for_io(port, 1)) return; reg8[AL] = io_port_read8(port); } void instr16_E5(int32_t port) { - test_privileges_for_io(port, 2); + if(!test_privileges_for_io(port, 2)) return; reg16[AX] = io_port_read16(port); } void instr32_E5(int32_t port) { - test_privileges_for_io(port, 4); + if(!test_privileges_for_io(port, 4)) return; reg32s[EAX] = io_port_read32(port); } void instr_E6(int32_t port) { - test_privileges_for_io(port, 1); + if(!test_privileges_for_io(port, 1)) return; io_port_write8(port, reg8[AL]); } void instr16_E7(int32_t port) { - test_privileges_for_io(port, 2); + if(!test_privileges_for_io(port, 2)) return; io_port_write16(port, reg16[AX]); } void instr32_E7(int32_t port) { - test_privileges_for_io(port, 4); + if(!test_privileges_for_io(port, 4)) return; io_port_write32(port, reg32s[EAX]); } @@ -1354,32 +1354,32 @@ void instr32_EB(int32_t imm8) { void instr_EC() { int32_t port = reg16[DX]; - test_privileges_for_io(port, 1); + if(!test_privileges_for_io(port, 1)) return; reg8[AL] = io_port_read8(port); } void instr16_ED() { int32_t port = reg16[DX]; - test_privileges_for_io(port, 2); + if(!test_privileges_for_io(port, 2)) return; reg16[AX] = io_port_read16(port); } void instr32_ED() { int32_t port = reg16[DX]; - test_privileges_for_io(port, 4); + if(!test_privileges_for_io(port, 4)) return; reg32s[EAX] = io_port_read32(port); } void instr_EE() { int32_t port = reg16[DX]; - test_privileges_for_io(port, 1); + if(!test_privileges_for_io(port, 1)) return; io_port_write8(port, reg8[AL]); } void instr16_EF() { int32_t port = reg16[DX]; - test_privileges_for_io(port, 2); + if(!test_privileges_for_io(port, 2)) return; io_port_write16(port, reg16[AX]); } void instr32_EF() { int32_t port = reg16[DX]; - test_privileges_for_io(port, 4); + if(!test_privileges_for_io(port, 4)) return; io_port_write32(port, reg32s[EAX]); } diff --git a/src/native/js_imports.h b/src/native/js_imports.h index 50ca1ee3..dd2c4184 100644 --- a/src/native/js_imports.h +++ b/src/native/js_imports.h @@ -52,7 +52,7 @@ extern void update_eflags(int32_t); extern bool switch_seg(int32_t, int32_t); extern void lss16(int32_t, int32_t, int32_t); extern void lss32(int32_t, int32_t, int32_t); -extern void test_privileges_for_io(int32_t, int32_t); +extern bool test_privileges_for_io(int32_t, int32_t); extern int32_t io_port_read8(int32_t); extern int32_t io_port_read16(int32_t); extern int32_t io_port_read32(int32_t); diff --git a/src/native/string.c b/src/native/string.c index f428a393..5b54a257 100644 --- a/src/native/string.c +++ b/src/native/string.c @@ -814,7 +814,7 @@ void scasd_no_rep() void insb_rep() { int32_t port = reg16[DX]; - test_privileges_for_io(port, 1); + if(!test_privileges_for_io(port, 1)) return; int32_t dest = get_seg(ES) + get_reg_asize(EDI); int32_t size = *flags & FLAG_DIRECTION ? -1 : 1; @@ -845,7 +845,7 @@ void insb_rep() void insb_no_rep() { int32_t port = reg16[DX]; - test_privileges_for_io(port, 1); + if(!test_privileges_for_io(port, 1)) return; int32_t dest = get_seg(ES) + get_reg_asize(EDI); int32_t size = *flags & FLAG_DIRECTION ? -1 : 1; @@ -858,7 +858,7 @@ void insb_no_rep() void insw_rep() { int32_t port = reg16[DX]; - test_privileges_for_io(port, 2); + if(!test_privileges_for_io(port, 2)) return; int32_t dest = get_seg(ES) + get_reg_asize(EDI); int32_t size = *flags & FLAG_DIRECTION ? -2 : 2; @@ -906,7 +906,7 @@ void insw_rep() void insw_no_rep() { int32_t port = reg16[DX]; - test_privileges_for_io(port, 2); + if(!test_privileges_for_io(port, 2)) return; int32_t dest = get_seg(ES) + get_reg_asize(EDI); int32_t size = *flags & FLAG_DIRECTION ? -2 : 2; @@ -919,7 +919,7 @@ void insw_no_rep() void insd_rep() { int32_t port = reg16[DX]; - test_privileges_for_io(port, 4); + if(!test_privileges_for_io(port, 4)) return; int32_t dest = get_seg(ES) + get_reg_asize(EDI); int32_t size = *flags & FLAG_DIRECTION ? -4 : 4; @@ -967,7 +967,7 @@ void insd_rep() void insd_no_rep() { int32_t port = reg16[DX]; - test_privileges_for_io(port, 4); + if(!test_privileges_for_io(port, 4)) return; int32_t dest = get_seg(ES) + get_reg_asize(EDI); int32_t size = *flags & FLAG_DIRECTION ? -4 : 4; @@ -980,7 +980,7 @@ void insd_no_rep() void outsb_rep() { int32_t port = reg16[DX]; - test_privileges_for_io(port, 1); + if(!test_privileges_for_io(port, 1)) return; int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); int32_t size = *flags & FLAG_DIRECTION ? -1 : 1; @@ -1011,7 +1011,7 @@ void outsb_rep() void outsb_no_rep() { int32_t port = reg16[DX]; - test_privileges_for_io(port, 1); + if(!test_privileges_for_io(port, 1)) return; int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); int32_t size = *flags & FLAG_DIRECTION ? -1 : 1; @@ -1024,7 +1024,7 @@ void outsb_no_rep() void outsw_rep() { int32_t port = reg16[DX]; - test_privileges_for_io(port, 2); + if(!test_privileges_for_io(port, 2)) return; int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); int32_t size = *flags & FLAG_DIRECTION ? -2 : 2; @@ -1071,7 +1071,7 @@ void outsw_rep() void outsw_no_rep() { int32_t port = reg16[DX]; - test_privileges_for_io(port, 2); + if(!test_privileges_for_io(port, 2)) return; int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); int32_t size = *flags & FLAG_DIRECTION ? -2 : 2; @@ -1083,7 +1083,7 @@ void outsw_no_rep() void outsd_rep() { int32_t port = reg16[DX]; - test_privileges_for_io(port, 4); + if(!test_privileges_for_io(port, 4)) return; int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); int32_t size = *flags & FLAG_DIRECTION ? -4 : 4; @@ -1130,7 +1130,7 @@ void outsd_rep() void outsd_no_rep() { int32_t port = reg16[DX]; - test_privileges_for_io(port, 4); + if(!test_privileges_for_io(port, 4)) return; int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); int32_t size = *flags & FLAG_DIRECTION ? -4 : 4; From 1a177b6a5d0947f4c6968ed76553e41931a09d8b Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 24 Jul 2018 09:30:46 +0530 Subject: [PATCH 1086/2137] .gitignore build-head and src/rust/gen files --- .gitignore | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitignore b/.gitignore index 383679e8..a63e1fea 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,10 @@ node_modules/ package-lock.json profile*.json Cargo.lock +build-head +src/rust/gen/analyzer.rs +src/rust/gen/analyzer0f_16.rs +src/rust/gen/analyzer0f_32.rs +src/rust/gen/jit.rs +src/rust/gen/jit0f_16.rs +src/rust/gen/jit0f_32.rs From 7a14a010a8eea0f040078d494e75ec31608ff38b Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 24 Jul 2018 16:38:01 +0530 Subject: [PATCH 1087/2137] Improve handling of locals and add tests - adds alloc_local and free_local - slightly better wasmgen tests - caller of gen_safe_write32 is responsible for allocating and freeing locals for address and value - updates expect-tests --- src/rust/codegen.rs | 280 +++++++++++++------------- src/rust/jit.rs | 49 +++-- src/rust/jit_instructions.rs | 23 ++- src/rust/lib.rs | 2 + src/rust/wasmgen/module_init.rs | 78 +++++-- src/rust/wasmgen/wasm_util.rs | 13 +- tests/expect/tests/call.wast | 24 +-- tests/expect/tests/do-while.wast | 18 +- tests/expect/tests/if.wast | 12 +- tests/expect/tests/indirect-call.wast | 6 +- tests/expect/tests/mov16.wast | 6 +- tests/expect/tests/mov32-mem.wast | 74 +++---- tests/expect/tests/mov32-reg.wast | 6 +- tests/expect/tests/pop.wast | 6 +- tests/expect/tests/push.wast | 6 +- tests/expect/tests/while-do.wast | 12 +- 16 files changed, 345 insertions(+), 270 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 050c1e3f..f78301e2 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -1,10 +1,9 @@ use global_pointers; use jit::JitContext; -use jit::{GEN_LOCAL_SCRATCH0, GEN_LOCAL_SCRATCH1, GEN_LOCAL_SCRATCH2}; use modrm; use regs; use tlb::{TLB_GLOBAL, TLB_NO_USER, TLB_READONLY, TLB_VALID}; -use wasmgen::module_init::WasmBuilder; +use wasmgen::module_init::{WasmBuilder, WasmLocal}; use wasmgen::{module_init, wasm_util}; pub fn gen_set_previous_eip_offset_from_eip(builder: &mut WasmBuilder, n: u32) { @@ -193,8 +192,8 @@ pub fn gen_safe_read32(ctx: &mut JitContext) { //let instruction_body = &mut ctx.builder.instruction_body; //let cpu = &mut ctx.cpu; - let address_local = GEN_LOCAL_SCRATCH0; - wasm_util::tee_local(&mut builder.instruction_body, address_local); + let address_local = builder.alloc_local(); + wasm_util::tee_local(&mut builder.instruction_body, &address_local); // Pseudo: base_on_stack = (uint32_t)address >> 12; wasm_util::push_i32(&mut builder.instruction_body, 12); @@ -205,12 +204,12 @@ pub fn gen_safe_read32(ctx: &mut JitContext) { wasm_util::shl_i32(&mut builder.instruction_body); // Pseudo: entry = tlb_data[base_on_stack]; - let entry_local = GEN_LOCAL_SCRATCH1; + let entry_local = builder.alloc_local(); wasm_util::load_aligned_i32_from_stack( &mut builder.instruction_body, global_pointers::TLB_DATA, ); - wasm_util::tee_local(&mut builder.instruction_body, entry_local); + wasm_util::tee_local(&mut builder.instruction_body, &entry_local); // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && // (address & 0xFFF) <= (0x1000 - 4)); @@ -224,7 +223,7 @@ pub fn gen_safe_read32(ctx: &mut JitContext) { wasm_util::push_i32(&mut builder.instruction_body, TLB_VALID as i32); wasm_util::eq_i32(&mut builder.instruction_body); - wasm_util::get_local(&mut builder.instruction_body, address_local); + wasm_util::get_local(&mut builder.instruction_body, &address_local); wasm_util::push_i32(&mut builder.instruction_body, 0xFFF); wasm_util::and_i32(&mut builder.instruction_body); wasm_util::push_i32(&mut builder.instruction_body, 0x1000 - 4); @@ -235,10 +234,10 @@ pub fn gen_safe_read32(ctx: &mut JitContext) { // Pseudo: // if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]); wasm_util::if_i32(&mut builder.instruction_body); - wasm_util::get_local(&mut builder.instruction_body, entry_local); + wasm_util::get_local(&mut builder.instruction_body, &entry_local); wasm_util::push_i32(&mut builder.instruction_body, !0xFFF); wasm_util::and_i32(&mut builder.instruction_body); - wasm_util::get_local(&mut builder.instruction_body, address_local); + wasm_util::get_local(&mut builder.instruction_body, &address_local); wasm_util::xor_i32(&mut builder.instruction_body); wasm_util::load_unaligned_i32_from_stack( @@ -249,31 +248,22 @@ pub fn gen_safe_read32(ctx: &mut JitContext) { // Pseudo: // else { leave_on_stack(safe_read32s_slow(address)); } wasm_util::else_(&mut builder.instruction_body); - wasm_util::get_local(&mut builder.instruction_body, address_local); + wasm_util::get_local(&mut builder.instruction_body, &address_local); gen_call_fn1_ret(builder, "safe_read32s_slow"); wasm_util::block_end(&mut builder.instruction_body); + + builder.free_local(address_local); + builder.free_local(entry_local); } -pub fn gen_safe_write32(ctx: &mut JitContext, local_for_address: u32, local_for_value: u32) { +pub fn gen_safe_write32(ctx: &mut JitContext, address_local: &WasmLocal, value_local: &WasmLocal) { // Generates safe_write32' fast-path inline, bailing to safe_write32_slow if necessary. - // local_for_{address,value} are the numbers of the local variables which contain the virtual - // address and value for safe_write32 - // Usage: - // set_local(0, value); - // set_local(1, v_addr); - // gen_safe_write32(0, 1); - - // Since this function clobbers other variables, we confirm that the caller uses the local - // variables we expect them to - dbg_assert!(local_for_address == GEN_LOCAL_SCRATCH0); - dbg_assert!(local_for_value == GEN_LOCAL_SCRATCH1); - let builder = &mut ctx.builder; //let instruction_body = &mut ctx.builder.instruction_body; //let cpu = &mut ctx.cpu; - wasm_util::get_local(&mut builder.instruction_body, local_for_address); + wasm_util::get_local(&mut builder.instruction_body, &address_local); // Pseudo: base_on_stack = (uint32_t)address >> 12; wasm_util::push_i32(&mut builder.instruction_body, 12); @@ -283,65 +273,65 @@ pub fn gen_safe_write32(ctx: &mut JitContext, local_for_address: u32, local_for_ wasm_util::push_i32(&mut builder.instruction_body, 2); wasm_util::shl_i32(&mut builder.instruction_body); - // entry_local is only used in the following block, so the scratch variable can be reused later - { - // Pseudo: entry = tlb_data[base_on_stack]; - let entry_local = GEN_LOCAL_SCRATCH2; - wasm_util::load_aligned_i32_from_stack( - &mut builder.instruction_body, - global_pointers::TLB_DATA, - ); - wasm_util::tee_local(&mut builder.instruction_body, entry_local); + // Pseudo: entry = tlb_data[base_on_stack]; + let entry_local = builder.alloc_local(); + wasm_util::load_aligned_i32_from_stack( + &mut builder.instruction_body, + global_pointers::TLB_DATA, + ); + wasm_util::tee_local(&mut builder.instruction_body, &entry_local); - // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && - // (address & 0xFFF) <= (0x1000 - 4)); - wasm_util::push_i32( - &mut builder.instruction_body, - (0xFFF & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32, - ); - wasm_util::and_i32(&mut builder.instruction_body); + // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && + // (address & 0xFFF) <= (0x1000 - 4)); + wasm_util::push_i32( + &mut builder.instruction_body, + (0xFFF & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32, + ); + wasm_util::and_i32(&mut builder.instruction_body); - wasm_util::push_i32(&mut builder.instruction_body, TLB_VALID as i32); - wasm_util::eq_i32(&mut builder.instruction_body); + wasm_util::push_i32(&mut builder.instruction_body, TLB_VALID as i32); + wasm_util::eq_i32(&mut builder.instruction_body); - wasm_util::get_local(&mut builder.instruction_body, local_for_address); - wasm_util::push_i32(&mut builder.instruction_body, 0xFFF); - wasm_util::and_i32(&mut builder.instruction_body); - wasm_util::push_i32(&mut builder.instruction_body, 0x1000 - 4); - wasm_util::le_i32(&mut builder.instruction_body); + wasm_util::get_local(&mut builder.instruction_body, &address_local); + wasm_util::push_i32(&mut builder.instruction_body, 0xFFF); + wasm_util::and_i32(&mut builder.instruction_body); + wasm_util::push_i32(&mut builder.instruction_body, 0x1000 - 4); + wasm_util::le_i32(&mut builder.instruction_body); - wasm_util::and_i32(&mut builder.instruction_body); + wasm_util::and_i32(&mut builder.instruction_body); - // Pseudo: - // if(can_use_fast_path) - // { - // phys_addr = entry & ~0xFFF ^ address; - wasm_util::if_void(&mut builder.instruction_body); + // Pseudo: + // if(can_use_fast_path) + // { + // phys_addr = entry & ~0xFFF ^ address; + wasm_util::if_void(&mut builder.instruction_body); - wasm_util::get_local(&mut builder.instruction_body, entry_local); - wasm_util::push_i32(&mut builder.instruction_body, !0xFFF); - wasm_util::and_i32(&mut builder.instruction_body); - wasm_util::get_local(&mut builder.instruction_body, local_for_address); - wasm_util::xor_i32(&mut builder.instruction_body); - } + wasm_util::get_local(&mut builder.instruction_body, &entry_local); + wasm_util::push_i32(&mut builder.instruction_body, !0xFFF); + wasm_util::and_i32(&mut builder.instruction_body); + wasm_util::get_local(&mut builder.instruction_body, &address_local); + wasm_util::xor_i32(&mut builder.instruction_body); - // entry_local isn't needed anymore, so we overwrite it - let phys_addr_local = GEN_LOCAL_SCRATCH2; + builder.free_local(entry_local); + + let phys_addr_local = builder.alloc_local(); // Pseudo: // /* continued within can_use_fast_path branch */ // mem8[phys_addr] = value; - wasm_util::tee_local(&mut builder.instruction_body, phys_addr_local); - wasm_util::get_local(&mut builder.instruction_body, local_for_value); + wasm_util::tee_local(&mut builder.instruction_body, &phys_addr_local); + wasm_util::get_local(&mut builder.instruction_body, &value_local); wasm_util::store_unaligned_i32(&mut builder.instruction_body, global_pointers::MEMORY); // Pseudo: // else { safe_read32_slow(address, value); } wasm_util::else_(&mut builder.instruction_body); - wasm_util::get_local(&mut builder.instruction_body, local_for_address); - wasm_util::get_local(&mut builder.instruction_body, local_for_value); + wasm_util::get_local(&mut builder.instruction_body, &address_local); + wasm_util::get_local(&mut builder.instruction_body, &value_local); gen_call_fn2(builder, "safe_write32_slow"); wasm_util::block_end(&mut builder.instruction_body); + + builder.free_local(phys_addr_local); } pub fn gen_fn1_reg16(ctx: &mut JitContext, name: &str, r: u32) { @@ -384,69 +374,77 @@ pub fn gen_add_prefix_bits(ctx: &mut JitContext, mask: u32) { pub fn gen_jmp_rel16(ctx: &mut JitContext, rel16: u16) { let cs_offset_addr = global_pointers::get_seg_offset(regs::CS); + let local = ctx.builder.alloc_local(); // generate: // *instruction_pointer = cs_offset + ((*instruction_pointer - cs_offset + rel16) & 0xFFFF); + { + let instruction_body = &mut ctx.builder.instruction_body; - let instruction_body = &mut ctx.builder.instruction_body; + wasm_util::load_aligned_i32(instruction_body, cs_offset_addr); + wasm_util::set_local(instruction_body, &local); - wasm_util::load_aligned_i32(instruction_body, cs_offset_addr); - wasm_util::set_local(instruction_body, GEN_LOCAL_SCRATCH0); + wasm_util::push_i32( + instruction_body, + global_pointers::INSTRUCTION_POINTER as i32, + ); - wasm_util::push_i32( - instruction_body, - global_pointers::INSTRUCTION_POINTER as i32, - ); + wasm_util::load_aligned_i32(instruction_body, global_pointers::INSTRUCTION_POINTER); + wasm_util::get_local(instruction_body, &local); + wasm_util::sub_i32(instruction_body); - wasm_util::load_aligned_i32(instruction_body, global_pointers::INSTRUCTION_POINTER); - wasm_util::get_local(instruction_body, GEN_LOCAL_SCRATCH0); - wasm_util::sub_i32(instruction_body); + wasm_util::push_i32(instruction_body, rel16 as i32); + wasm_util::add_i32(instruction_body); - wasm_util::push_i32(instruction_body, rel16 as i32); - wasm_util::add_i32(instruction_body); + wasm_util::push_i32(instruction_body, 0xFFFF); + wasm_util::and_i32(instruction_body); - wasm_util::push_i32(instruction_body, 0xFFFF); - wasm_util::and_i32(instruction_body); + wasm_util::get_local(instruction_body, &local); + wasm_util::add_i32(instruction_body); - wasm_util::get_local(instruction_body, GEN_LOCAL_SCRATCH0); - wasm_util::add_i32(instruction_body); - - wasm_util::store_aligned_i32(instruction_body); + wasm_util::store_aligned_i32(instruction_body); + } + ctx.builder.free_local(local); } pub fn gen_pop16_ss16(ctx: &mut JitContext) { let safe_read16_idx = ctx .builder .get_fn_idx("safe_read16", module_init::FN1_RET_TYPE_INDEX); - let instruction_body = &mut ctx.builder.instruction_body; + let sp_local = ctx.builder.alloc_local(); + { + let instruction_body = &mut ctx.builder.instruction_body; - let sp_local = GEN_LOCAL_SCRATCH0; + // sp = segment_offsets[SS] + reg16[SP] (or just reg16[SP] if has_flat_segmentation) + wasm_util::load_aligned_i32( + instruction_body, + global_pointers::get_reg16_offset(regs::SP), + ); + wasm_util::tee_local(instruction_body, &sp_local); - // sp = segment_offsets[SS] + reg16[SP] (or just reg16[SP] if has_flat_segmentation) - wasm_util::load_aligned_i32( - instruction_body, - global_pointers::get_reg16_offset(regs::SP), - ); - wasm_util::tee_local(instruction_body, sp_local); + if !ctx.cpu.has_flat_segmentation() { + wasm_util::load_aligned_i32( + instruction_body, + global_pointers::get_seg_offset(regs::SS), + ); + wasm_util::add_i32(instruction_body); + } - if !ctx.cpu.has_flat_segmentation() { - wasm_util::load_aligned_i32(instruction_body, global_pointers::get_seg_offset(regs::SS)); + // result = safe_read16(sp) + // XXX: inline safe_read16 + wasm_util::call_fn(instruction_body, safe_read16_idx); + + // reg16[SP] += 2; + wasm_util::push_i32( + instruction_body, + global_pointers::get_reg16_offset(regs::SP) as i32, + ); + wasm_util::get_local(instruction_body, &sp_local); + wasm_util::push_i32(instruction_body, 2); wasm_util::add_i32(instruction_body); + wasm_util::store_aligned_i32(instruction_body); } - - // result = safe_read16(sp) - // XXX: inline safe_read16 - wasm_util::call_fn(instruction_body, safe_read16_idx); - - // reg16[SP] += 2; - wasm_util::push_i32( - instruction_body, - global_pointers::get_reg16_offset(regs::SP) as i32, - ); - wasm_util::get_local(instruction_body, sp_local); - wasm_util::push_i32(instruction_body, 2); - wasm_util::add_i32(instruction_body); - wasm_util::store_aligned_i32(instruction_body); + ctx.builder.free_local(sp_local); // return value is already on stack } @@ -455,35 +453,39 @@ pub fn gen_pop16_ss32(ctx: &mut JitContext) { let safe_read16_idx = ctx .builder .get_fn_idx("safe_read16", module_init::FN1_RET_TYPE_INDEX); - let instruction_body = &mut ctx.builder.instruction_body; + let esp_local = ctx.builder.alloc_local(); + { + let instruction_body = &mut ctx.builder.instruction_body; + // esp = segment_offsets[SS] + reg32s[ESP] (or just reg32s[ESP] if has_flat_segmentation) + wasm_util::load_aligned_i32( + instruction_body, + global_pointers::get_reg32_offset(regs::ESP), + ); + wasm_util::tee_local(instruction_body, &esp_local); - let esp_local = GEN_LOCAL_SCRATCH0; + if !ctx.cpu.has_flat_segmentation() { + wasm_util::load_aligned_i32( + instruction_body, + global_pointers::get_seg_offset(regs::SS), + ); + wasm_util::add_i32(instruction_body); + } - // esp = segment_offsets[SS] + reg32s[ESP] (or just reg32s[ESP] if has_flat_segmentation) - wasm_util::load_aligned_i32( - instruction_body, - global_pointers::get_reg32_offset(regs::ESP), - ); - wasm_util::tee_local(instruction_body, esp_local); + // result = safe_read16(esp) + // XXX: inline safe_read16 + wasm_util::call_fn(instruction_body, safe_read16_idx); - if !ctx.cpu.has_flat_segmentation() { - wasm_util::load_aligned_i32(instruction_body, global_pointers::get_seg_offset(regs::SS)); + // reg32s[ESP] += 2; + wasm_util::push_i32( + instruction_body, + global_pointers::get_reg32_offset(regs::ESP) as i32, + ); + wasm_util::get_local(instruction_body, &esp_local); + wasm_util::push_i32(instruction_body, 2); wasm_util::add_i32(instruction_body); + wasm_util::store_aligned_i32(instruction_body); } - - // result = safe_read16(esp) - // XXX: inline safe_read16 - wasm_util::call_fn(instruction_body, safe_read16_idx); - - // reg32s[ESP] += 2; - wasm_util::push_i32( - instruction_body, - global_pointers::get_reg32_offset(regs::ESP) as i32, - ); - wasm_util::get_local(instruction_body, esp_local); - wasm_util::push_i32(instruction_body, 2); - wasm_util::add_i32(instruction_body); - wasm_util::store_aligned_i32(instruction_body); + ctx.builder.free_local(esp_local); // return value is already on stack } @@ -498,14 +500,14 @@ pub fn gen_pop16(ctx: &mut JitContext) { } pub fn gen_pop32s_ss16(ctx: &mut JitContext) { - let local_sp = GEN_LOCAL_SCRATCH2; // gen_safe_read32 uses local0 and local1 + let local_sp = ctx.builder.alloc_local(); // sp = reg16[SP] wasm_util::load_aligned_i32( &mut ctx.builder.instruction_body, global_pointers::get_reg16_offset(regs::SP), ); - wasm_util::tee_local(&mut ctx.builder.instruction_body, local_sp); + wasm_util::tee_local(&mut ctx.builder.instruction_body, &local_sp); // result = safe_read32s(segment_offsets[SS] + sp) (or just sp if has_flat_segmentation) if !ctx.cpu.has_flat_segmentation() { @@ -523,23 +525,25 @@ pub fn gen_pop32s_ss16(ctx: &mut JitContext) { &mut ctx.builder.instruction_body, global_pointers::get_reg16_offset(regs::SP) as i32, ); - wasm_util::get_local(&mut ctx.builder.instruction_body, local_sp); + wasm_util::get_local(&mut ctx.builder.instruction_body, &local_sp); wasm_util::push_i32(&mut ctx.builder.instruction_body, 4); wasm_util::add_i32(&mut ctx.builder.instruction_body); wasm_util::store_aligned_i32(&mut ctx.builder.instruction_body); + ctx.builder.free_local(local_sp); + // return value is already on stack } pub fn gen_pop32s_ss32(ctx: &mut JitContext) { - let local_esp = GEN_LOCAL_SCRATCH2; // gen_safe_read32 uses local0 and local1 + let local_esp = ctx.builder.alloc_local(); // esp = reg32s[ESP] wasm_util::load_aligned_i32( &mut ctx.builder.instruction_body, global_pointers::get_reg32_offset(regs::ESP), ); - wasm_util::tee_local(&mut ctx.builder.instruction_body, local_esp); + wasm_util::tee_local(&mut ctx.builder.instruction_body, &local_esp); // result = safe_read32s(segment_offsets[SS] + esp) (or just esp if has_flat_segmentation) if !ctx.cpu.has_flat_segmentation() { @@ -556,11 +560,13 @@ pub fn gen_pop32s_ss32(ctx: &mut JitContext) { &mut ctx.builder.instruction_body, global_pointers::get_reg32_offset(regs::ESP) as i32, ); - wasm_util::get_local(&mut ctx.builder.instruction_body, local_esp); + wasm_util::get_local(&mut ctx.builder.instruction_body, &local_esp); wasm_util::push_i32(&mut ctx.builder.instruction_body, 4); wasm_util::add_i32(&mut ctx.builder.instruction_body); wasm_util::store_aligned_i32(&mut ctx.builder.instruction_body); + ctx.builder.free_local(local_esp); + // return value is already on stack } diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 1d47a4f6..b2e2f129 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -380,16 +380,6 @@ pub struct JitContext<'a> { pub builder: &'a mut WasmBuilder, } -pub const GEN_LOCAL_ARG_INITIAL_STATE: u32 = 0; -pub const GEN_LOCAL_STATE: u32 = 1; -pub const GEN_LOCAL_ITERATION_COUNTER: u32 = 2; -// local scratch variables for use wherever required -pub const GEN_LOCAL_SCRATCH0: u32 = 3; -pub const GEN_LOCAL_SCRATCH1: u32 = 4; -pub const GEN_LOCAL_SCRATCH2: u32 = 5; -// Function arguments are not included in the local variable count -pub const GEN_NO_OF_LOCALS: u32 = 5; - pub const JIT_INSTR_BLOCK_BOUNDARY_FLAG: u32 = 1 << 0; pub const JIT_INSTR_NONFAULTING_FLAG: u32 = 1 << 1; @@ -870,6 +860,14 @@ fn jit_generate_module( let fn_get_seg_idx = builder.get_fn_idx("get_seg", module_init::FN1_RET_TYPE_INDEX); dbg_assert!(fn_get_seg_idx == FN_GET_SEG_IDX); + let gen_local_state = builder.alloc_local(); + let gen_local_iteration_counter = if JIT_ALWAYS_USE_LOOP_SAFETY || requires_loop_limit { + Some(builder.alloc_local()) + } + else { + None + }; + let basic_block_indices: HashMap = basic_blocks .iter() .enumerate() @@ -877,16 +875,22 @@ fn jit_generate_module( .collect(); // set state local variable to the initial state passed as the first argument - wasm_util::get_local(&mut builder.instruction_body, GEN_LOCAL_ARG_INITIAL_STATE); - wasm_util::set_local(&mut builder.instruction_body, GEN_LOCAL_STATE); + wasm_util::get_local( + &mut builder.instruction_body, + &builder.arg_local_initial_state, + ); + wasm_util::set_local(&mut builder.instruction_body, &gen_local_state); // initialise max_iterations if JIT_ALWAYS_USE_LOOP_SAFETY || requires_loop_limit { + let gen_local_iteration_counter = gen_local_iteration_counter + .as_ref() + .expect("iteration counter"); wasm_util::push_i32( &mut builder.instruction_body, JIT_MAX_ITERATIONS_PER_FUNCTION as i32, ); - wasm_util::set_local(&mut builder.instruction_body, GEN_LOCAL_ITERATION_COUNTER); + wasm_util::set_local(&mut builder.instruction_body, gen_local_iteration_counter); } // main state machine loop @@ -894,15 +898,18 @@ fn jit_generate_module( if JIT_ALWAYS_USE_LOOP_SAFETY || requires_loop_limit { profiler::stat_increment(stat::S_COMPILE_WITH_LOOP_SAFETY); + let gen_local_iteration_counter = gen_local_iteration_counter + .as_ref() + .expect("iteration counter"); // decrement max_iterations - wasm_util::get_local(&mut builder.instruction_body, GEN_LOCAL_ITERATION_COUNTER); + wasm_util::get_local(&mut builder.instruction_body, gen_local_iteration_counter); wasm_util::push_i32(&mut builder.instruction_body, -1); wasm_util::add_i32(&mut builder.instruction_body); - wasm_util::set_local(&mut builder.instruction_body, GEN_LOCAL_ITERATION_COUNTER); + wasm_util::set_local(&mut builder.instruction_body, gen_local_iteration_counter); // if max_iterations == 0: return - wasm_util::get_local(&mut builder.instruction_body, GEN_LOCAL_ITERATION_COUNTER); + wasm_util::get_local(&mut builder.instruction_body, gen_local_iteration_counter); wasm_util::eqz_i32(&mut builder.instruction_body); wasm_util::if_void(&mut builder.instruction_body); wasm_util::return_(&mut builder.instruction_body); @@ -917,7 +924,7 @@ fn jit_generate_module( wasm_util::block_void(&mut builder.instruction_body); } - wasm_util::get_local(&mut builder.instruction_body, GEN_LOCAL_STATE); + wasm_util::get_local(&mut builder.instruction_body, &gen_local_state); wasm_util::brtable_and_cases(&mut builder.instruction_body, basic_blocks.len() as u32); for (i, block) in basic_blocks.iter().enumerate() { @@ -953,7 +960,7 @@ fn jit_generate_module( // set state variable to next basic block wasm_util::push_i32(&mut builder.instruction_body, next_bb_index as i32); - wasm_util::set_local(&mut builder.instruction_body, GEN_LOCAL_STATE); + wasm_util::set_local(&mut builder.instruction_body, &gen_local_state); wasm_util::br( &mut builder.instruction_body, @@ -1003,7 +1010,7 @@ fn jit_generate_module( &mut builder.instruction_body, next_basic_block_branch_taken_index as i32, ); - wasm_util::set_local(&mut builder.instruction_body, GEN_LOCAL_STATE); + wasm_util::set_local(&mut builder.instruction_body, &gen_local_state); } else { // Jump to different page @@ -1022,7 +1029,7 @@ fn jit_generate_module( &mut builder.instruction_body, next_basic_block_index as i32, ); - wasm_util::set_local(&mut builder.instruction_body, GEN_LOCAL_STATE); + wasm_util::set_local(&mut builder.instruction_body, &gen_local_state); } wasm_util::block_end(&mut builder.instruction_body); @@ -1041,7 +1048,7 @@ fn jit_generate_module( wasm_util::block_end(&mut builder.instruction_body); // loop builder.commit_instruction_body_to_cs(); - builder.finish(GEN_NO_OF_LOCALS as u8); + builder.finish(); } fn jit_generate_basic_block( diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 9f7b22b6..ff9da8b3 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -4,7 +4,6 @@ use codegen; use cpu_context::CpuContext; use global_pointers; use jit::JitContext; -use jit::{GEN_LOCAL_SCRATCH0, GEN_LOCAL_SCRATCH1}; use modrm; use prefix::SEG_PREFIX_ZERO; use prefix::{PREFIX_66, PREFIX_67, PREFIX_F2, PREFIX_F3}; @@ -258,20 +257,22 @@ pub fn instr16_89_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { } pub fn instr32_89_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { // Pseudo: safe_write32(modrm_resolve(modrm_byte), reg32s[r]); - let address_local = GEN_LOCAL_SCRATCH0; - let value_local = GEN_LOCAL_SCRATCH1; + let address_local = ctx.builder.alloc_local(); + let value_local = ctx.builder.alloc_local(); codegen::gen_modrm_resolve(ctx, modrm_byte); - wasm_util::set_local(&mut ctx.builder.instruction_body, address_local); + wasm_util::set_local(&mut ctx.builder.instruction_body, &address_local); wasm_util::push_i32( &mut ctx.builder.instruction_body, global_pointers::get_reg32_offset(r) as i32, ); wasm_util::load_aligned_i32_from_stack(&mut ctx.builder.instruction_body, 0); - wasm_util::set_local(&mut ctx.builder.instruction_body, value_local); + wasm_util::set_local(&mut ctx.builder.instruction_body, &value_local); - codegen::gen_safe_write32(ctx, address_local, value_local); + codegen::gen_safe_write32(ctx, &address_local, &value_local); + ctx.builder.free_local(address_local); + ctx.builder.free_local(value_local); } pub fn instr32_89_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_set_reg32_r(ctx, r1, r2); @@ -497,10 +498,14 @@ pub fn instr32_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { } pub fn instr32_C7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + let address_local = ctx.builder.alloc_local(); + let value_local = ctx.builder.alloc_local(); codegen::gen_modrm_resolve(ctx, modrm_byte); - wasm_util::set_local(&mut ctx.builder.instruction_body, GEN_LOCAL_SCRATCH0); + wasm_util::set_local(&mut ctx.builder.instruction_body, &address_local); let imm = ctx.cpu.read_imm32(); wasm_util::push_i32(&mut ctx.builder.instruction_body, imm as i32); - wasm_util::set_local(&mut ctx.builder.instruction_body, GEN_LOCAL_SCRATCH1); - codegen::gen_safe_write32(ctx, GEN_LOCAL_SCRATCH0, GEN_LOCAL_SCRATCH1); + wasm_util::set_local(&mut ctx.builder.instruction_body, &value_local); + codegen::gen_safe_write32(ctx, &address_local, &value_local); + ctx.builder.free_local(address_local); + ctx.builder.free_local(value_local); } diff --git a/src/rust/lib.rs b/src/rust/lib.rs index fae5ea9d..759217f1 100644 --- a/src/rust/lib.rs +++ b/src/rust/lib.rs @@ -1,3 +1,5 @@ +#![feature(const_fn)] + #[cfg(test)] #[macro_use] extern crate quickcheck; diff --git a/src/rust/wasmgen/module_init.rs b/src/rust/wasmgen/module_init.rs index bc527054..c7573a0f 100644 --- a/src/rust/wasmgen/module_init.rs +++ b/src/rust/wasmgen/module_init.rs @@ -33,6 +33,15 @@ pub struct WasmBuilder { import_count: u16, // same as above initial_static_size: usize, // size of module after initialization, rest is drained on reset + + free_locals: Vec, + local_count: u8, + pub arg_local_initial_state: WasmLocal, +} + +pub struct WasmLocal(u8); +impl WasmLocal { + pub fn idx(&self) -> u8 { self.0 } } impl WasmBuilder { @@ -50,6 +59,10 @@ impl WasmBuilder { import_count: 0, initial_static_size: 0, + + free_locals: Vec::with_capacity(8), + local_count: 1, // for the argument + arg_local_initial_state: WasmLocal(0), } } @@ -75,11 +88,13 @@ impl WasmBuilder { self.set_import_count(0); self.code_section.clear(); self.instruction_body.clear(); + self.free_locals.clear(); + self.local_count = 0; } - pub fn finish(&mut self, no_of_locals_i32: u8) -> usize { + pub fn finish(&mut self) -> usize { self.write_memory_import(); - self.write_function_section(1); + self.write_function_section(); self.write_export_section(); // write code section preamble @@ -101,8 +116,8 @@ impl WasmBuilder { self.output.push(0); self.output.push(1); // count of local blocks - dbg_assert!(no_of_locals_i32 < 128); - self.output.push(no_of_locals_i32); + dbg_assert!(self.local_count < 128); + self.output.push(self.local_count); self.output.push(op::TYPE_I32); self.output.append(&mut self.code_section); @@ -266,13 +281,11 @@ impl WasmBuilder { self.import_count - 1 } - pub fn write_function_section(&mut self, count: u8) { + pub fn write_function_section(&mut self) { self.output.push(op::SC_FUNCTION); - self.output.push(1 + count); // length of this section - self.output.push(count); // count of signature indices - for _ in 0..count { - self.output.push(FN1_TYPE_INDEX); - } + self.output.push(2); // length of this section + self.output.push(1); // count of signature indices + self.output.push(FN1_TYPE_INDEX); } pub fn write_export_section(&mut self) { @@ -310,6 +323,22 @@ impl WasmBuilder { pub fn commit_instruction_body_to_cs(&mut self) { self.code_section.append(&mut self.instruction_body); } + + pub fn alloc_local(&mut self) -> WasmLocal { + match self.free_locals.pop() { + Some(local) => local, + None => { + let new_idx = self.local_count; + self.local_count += 1; + WasmLocal(new_idx) + }, + } + } + + pub fn free_local(&mut self, local: WasmLocal) { + dbg_assert!(local.0 < self.local_count); + self.free_locals.push(local) + } } #[cfg(test)] @@ -340,7 +369,9 @@ mod tests { let bar_index = m.get_fn_idx("bar", FN0_TYPE_INDEX); call_fn(&mut m.code_section, bar_index); - m.finish(2); + let _ = m.alloc_local(); // for ensuring that reset clears previous locals + + m.finish(); m.reset(); push_i32(&mut m.code_section, 2); @@ -350,9 +381,32 @@ mod tests { foo_index = m.get_fn_idx("foo", FN1_TYPE_INDEX); call_fn(&mut m.instruction_body, foo_index); + push_i32(&mut m.code_section, 10); + let local1 = m.alloc_local(); + tee_local(&mut m.code_section, &local1); // local1 = 10 + + push_i32(&mut m.code_section, 20); + add_i32(&mut m.code_section); + let local2 = m.alloc_local(); + tee_local(&mut m.code_section, &local2); // local2 = 30 + + m.free_local(local1); + + let local3 = m.alloc_local(); + assert_eq!(local3.idx(), 0); + + m.free_local(local2); + m.free_local(local3); + + push_i32(&mut m.code_section, 30); + ne_i32(&mut m.code_section); + if_void(&mut m.code_section); + unreachable(&mut m.code_section); + block_end(&mut m.code_section); + m.commit_instruction_body_to_cs(); - m.finish(0); + m.finish(); let op_ptr = m.get_op_ptr(); let op_len = m.get_op_len(); diff --git a/src/rust/wasmgen/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs index 8dcaff04..8ca25a74 100644 --- a/src/rust/wasmgen/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -1,4 +1,5 @@ use leb::{write_fixed_leb16_at_idx, write_leb_i32, write_leb_u32}; +use wasmgen::module_init::WasmLocal; use wasmgen::wasm_opcodes as op; pub fn push_i32(buf: &mut Vec, v: i32) { @@ -143,19 +144,19 @@ pub fn br(buf: &mut Vec, depth: u32) { write_leb_u32(buf, depth); } -pub fn get_local(buf: &mut Vec, idx: u32) { +pub fn get_local(buf: &mut Vec, local: &WasmLocal) { buf.push(op::OP_GETLOCAL); - write_leb_u32(buf, idx); + buf.push(local.idx()); } -pub fn set_local(buf: &mut Vec, idx: u32) { +pub fn set_local(buf: &mut Vec, local: &WasmLocal) { buf.push(op::OP_SETLOCAL); - write_leb_u32(buf, idx); + buf.push(local.idx()); } -pub fn tee_local(buf: &mut Vec, idx: u32) { +pub fn tee_local(buf: &mut Vec, local: &WasmLocal) { buf.push(op::OP_TEELOCAL); - write_leb_u32(buf, idx); + buf.push(local.idx()); } pub fn unreachable(buf: &mut Vec) { buf.push(op::OP_UNREACHABLE); } diff --git a/tests/expect/tests/call.wast b/tests/expect/tests/call.wast index 054a876e..ca3f0d95 100644 --- a/tests/expect/tests/call.wast +++ b/tests/expect/tests/call.wast @@ -13,8 +13,8 @@ (import "e" "safe_read32s_slow" (func $e.safe_read32s_slow (type $t5))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) - (set_local $l0 + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) + (set_local $p0 (get_local $p0)) (loop $L0 (block $B1 @@ -22,7 +22,7 @@ (block $B3 (block $B4 (br_table $B4 $B3 $B2 $B1 - (get_local $l0))) + (get_local $p0))) (i32.store (i32.const 560) (i32.load @@ -41,7 +41,7 @@ (i32.load (i32.const 664)) (i32.const 1))) - (set_local $l0 + (set_local $p0 (i32.const 2)) (br $L0)) (i32.store @@ -82,13 +82,13 @@ (i32.and (i32.eq (i32.and - (tee_local $l3 + (tee_local $l2 (i32.load offset=4194304 (i32.shl (i32.shr_u - (tee_local $l2 + (tee_local $l1 (i32.add - (tee_local $l4 + (tee_local $l0 (i32.load (i32.const 20))) (i32.load @@ -99,23 +99,23 @@ (i32.const 1)) (i32.le_s (i32.and - (get_local $l2) + (get_local $l1) (i32.const 4095)) (i32.const 4092))) (then (i32.load offset=8388608 align=1 (i32.xor (i32.and - (get_local $l3) + (get_local $l2) (i32.const -4096)) - (get_local $l2)))) + (get_local $l1)))) (else (call $e.safe_read32s_slow - (get_local $l2)))) + (get_local $l1)))) (i32.store (i32.const 20) (i32.add - (get_local $l4) + (get_local $l0) (i32.const 4))) (i32.add) (i32.store) diff --git a/tests/expect/tests/do-while.wast b/tests/expect/tests/do-while.wast index 1b541881..83287fce 100644 --- a/tests/expect/tests/do-while.wast +++ b/tests/expect/tests/do-while.wast @@ -13,26 +13,26 @@ (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) - (set_local $l0 + (local $l0 i32) (local $l1 i32) + (set_local $p0 (get_local $p0)) - (set_local $l1 + (set_local $l0 (i32.const 10000)) (loop $L0 - (set_local $l1 + (set_local $l0 (i32.add - (get_local $l1) + (get_local $l0) (i32.const -1))) (if $I1 (i32.eqz - (get_local $l1)) + (get_local $l0)) (then (return))) (block $B2 (block $B3 (block $B4 (br_table $B4 $B3 $B2 - (get_local $l0))) + (get_local $p0))) (i32.store (i32.const 560) (i32.add @@ -64,10 +64,10 @@ (i32.load (i32.const 556)) (i32.const -6))) - (set_local $l0 + (set_local $p0 (i32.const 0))) (else - (set_local $l0 + (set_local $p0 (i32.const 1)))) (br $L0)) (i32.store diff --git a/tests/expect/tests/if.wast b/tests/expect/tests/if.wast index d882a7a2..96279f0b 100644 --- a/tests/expect/tests/if.wast +++ b/tests/expect/tests/if.wast @@ -14,8 +14,8 @@ (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) - (set_local $l0 + (local $l0 i32) + (set_local $p0 (get_local $p0)) (loop $L0 (block $B1 @@ -23,7 +23,7 @@ (block $B3 (block $B4 (br_table $B4 $B3 $B2 $B1 - (get_local $l0))) + (get_local $p0))) (i32.store (i32.const 560) (i32.add @@ -54,10 +54,10 @@ (i32.load (i32.const 556)) (i32.const 1))) - (set_local $l0 + (set_local $p0 (i32.const 2))) (else - (set_local $l0 + (set_local $p0 (i32.const 1)))) (br $L0)) (call $e.instr32_41) @@ -73,7 +73,7 @@ (i32.load (i32.const 664)) (i32.const 1))) - (set_local $l0 + (set_local $p0 (i32.const 2)) (br $L0)) (i32.store diff --git a/tests/expect/tests/indirect-call.wast b/tests/expect/tests/indirect-call.wast index 152f7a50..04d08758 100644 --- a/tests/expect/tests/indirect-call.wast +++ b/tests/expect/tests/indirect-call.wast @@ -11,15 +11,15 @@ (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) - (set_local $l0 + (local $l0 i32) + (set_local $p0 (get_local $p0)) (loop $L0 (block $B1 (block $B2 (block $B3 (br_table $B3 $B2 $B1 - (get_local $l0))) + (get_local $p0))) (i32.store (i32.const 560) (i32.load diff --git a/tests/expect/tests/mov16.wast b/tests/expect/tests/mov16.wast index 84f06c30..f112a54c 100644 --- a/tests/expect/tests/mov16.wast +++ b/tests/expect/tests/mov16.wast @@ -13,14 +13,14 @@ (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) - (set_local $l0 + (local $l0 i32) + (set_local $p0 (get_local $p0)) (loop $L0 (block $B1 (block $B2 (br_table $B2 $B1 - (get_local $l0))) + (get_local $p0))) (i32.store (i32.const 560) (i32.add diff --git a/tests/expect/tests/mov32-mem.wast b/tests/expect/tests/mov32-mem.wast index 00c7466e..0f13849a 100644 --- a/tests/expect/tests/mov32-mem.wast +++ b/tests/expect/tests/mov32-mem.wast @@ -12,19 +12,19 @@ (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) - (set_local $l0 + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) + (set_local $p0 (get_local $p0)) (loop $L0 (block $B1 (block $B2 (br_table $B2 $B1 - (get_local $l0))) + (get_local $p0))) (i32.store (i32.const 560) (i32.load (i32.const 556))) - (set_local $l2 + (set_local $l0 (i32.add (i32.add (i32.load @@ -32,47 +32,47 @@ (i32.const 32)) (call $e.get_seg (i32.const 3)))) - (set_local $l3 + (set_local $l1 (i32.load (i32.const 4))) (if $I3 (i32.and (i32.eq (i32.and - (tee_local $l4 + (tee_local $l2 (i32.load offset=4194304 (i32.shl (i32.shr_u - (get_local $l2) + (get_local $l0) (i32.const 12)) (i32.const 2)))) (i32.const 4075)) (i32.const 1)) (i32.le_s (i32.and - (get_local $l2) + (get_local $l0) (i32.const 4095)) (i32.const 4092))) (then (i32.store offset=8388608 align=1 - (tee_local $l4 + (tee_local $l2 (i32.xor (i32.and - (get_local $l4) + (get_local $l2) (i32.const -4096)) - (get_local $l2))) - (get_local $l3))) + (get_local $l0))) + (get_local $l1))) (else (call $e.safe_write32_slow - (get_local $l2) - (get_local $l3)))) + (get_local $l0) + (get_local $l1)))) (i32.store (i32.const 560) (i32.add (i32.load (i32.const 556)) (i32.const 6))) - (set_local $l2 + (set_local $l1 (i32.add (i32.add (i32.load @@ -80,40 +80,40 @@ (i32.const 28)) (call $e.get_seg (i32.const 3)))) - (set_local $l3 + (set_local $l0 (i32.load (i32.const 8))) (if $I4 (i32.and (i32.eq (i32.and - (tee_local $l4 + (tee_local $l2 (i32.load offset=4194304 (i32.shl (i32.shr_u - (get_local $l2) + (get_local $l1) (i32.const 12)) (i32.const 2)))) (i32.const 4075)) (i32.const 1)) (i32.le_s (i32.and - (get_local $l2) + (get_local $l1) (i32.const 4095)) (i32.const 4092))) (then (i32.store offset=8388608 align=1 - (tee_local $l4 + (tee_local $l2 (i32.xor (i32.and - (get_local $l4) + (get_local $l2) (i32.const -4096)) - (get_local $l2))) - (get_local $l3))) + (get_local $l1))) + (get_local $l0))) (else (call $e.safe_write32_slow - (get_local $l2) - (get_local $l3)))) + (get_local $l1) + (get_local $l0)))) (i32.store (i32.const 560) (i32.add @@ -126,11 +126,11 @@ (i32.and (i32.eq (i32.and - (tee_local $l3 + (tee_local $l1 (i32.load offset=4194304 (i32.shl (i32.shr_u - (tee_local $l2 + (tee_local $l0 (i32.add (i32.add (i32.load @@ -144,19 +144,19 @@ (i32.const 1)) (i32.le_s (i32.and - (get_local $l2) + (get_local $l0) (i32.const 4095)) (i32.const 4092))) (then (i32.load offset=8388608 align=1 (i32.xor (i32.and - (get_local $l3) + (get_local $l1) (i32.const -4096)) - (get_local $l2)))) + (get_local $l0)))) (else (call $e.safe_read32s_slow - (get_local $l2))))) + (get_local $l0))))) (i32.store (i32.const 560) (i32.add @@ -169,11 +169,11 @@ (i32.and (i32.eq (i32.and - (tee_local $l3 + (tee_local $l0 (i32.load offset=4194304 (i32.shl (i32.shr_u - (tee_local $l2 + (tee_local $l1 (i32.add (i32.add (i32.load @@ -187,19 +187,19 @@ (i32.const 1)) (i32.le_s (i32.and - (get_local $l2) + (get_local $l1) (i32.const 4095)) (i32.const 4092))) (then (i32.load offset=8388608 align=1 (i32.xor (i32.and - (get_local $l3) + (get_local $l0) (i32.const -4096)) - (get_local $l2)))) + (get_local $l1)))) (else (call $e.safe_read32s_slow - (get_local $l2))))) + (get_local $l1))))) (i32.store (i32.const 560) (i32.add diff --git a/tests/expect/tests/mov32-reg.wast b/tests/expect/tests/mov32-reg.wast index fe5be5eb..789e9eaa 100644 --- a/tests/expect/tests/mov32-reg.wast +++ b/tests/expect/tests/mov32-reg.wast @@ -14,14 +14,14 @@ (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) - (set_local $l0 + (local $l0 i32) + (set_local $p0 (get_local $p0)) (loop $L0 (block $B1 (block $B2 (br_table $B2 $B1 - (get_local $l0))) + (get_local $p0))) (i32.store (i32.const 560) (i32.add diff --git a/tests/expect/tests/pop.wast b/tests/expect/tests/pop.wast index d60e2703..dfff0885 100644 --- a/tests/expect/tests/pop.wast +++ b/tests/expect/tests/pop.wast @@ -11,14 +11,14 @@ (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) - (set_local $l0 + (local $l0 i32) + (set_local $p0 (get_local $p0)) (loop $L0 (block $B1 (block $B2 (br_table $B2 $B1 - (get_local $l0))) + (get_local $p0))) (i32.store (i32.const 560) (i32.load diff --git a/tests/expect/tests/push.wast b/tests/expect/tests/push.wast index 9cd11486..5fb791f9 100644 --- a/tests/expect/tests/push.wast +++ b/tests/expect/tests/push.wast @@ -11,14 +11,14 @@ (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) - (set_local $l0 + (local $l0 i32) + (set_local $p0 (get_local $p0)) (loop $L0 (block $B1 (block $B2 (br_table $B2 $B1 - (get_local $l0))) + (get_local $p0))) (i32.store (i32.const 560) (i32.load diff --git a/tests/expect/tests/while-do.wast b/tests/expect/tests/while-do.wast index bc0d24da..a86ab341 100644 --- a/tests/expect/tests/while-do.wast +++ b/tests/expect/tests/while-do.wast @@ -13,8 +13,8 @@ (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) - (set_local $l0 + (local $l0 i32) + (set_local $p0 (get_local $p0)) (loop $L0 (block $B1 @@ -22,7 +22,7 @@ (block $B3 (block $B4 (br_table $B4 $B3 $B2 $B1 - (get_local $l0))) + (get_local $p0))) (i32.store (i32.const 560) (i32.add @@ -53,10 +53,10 @@ (i32.load (i32.const 556)) (i32.const 3))) - (set_local $l0 + (set_local $p0 (i32.const 2))) (else - (set_local $l0 + (set_local $p0 (i32.const 1)))) (br $L0)) (i32.store @@ -84,7 +84,7 @@ (i32.load (i32.const 664)) (i32.const 2))) - (set_local $l0 + (set_local $p0 (i32.const 0)) (br $L0)) (i32.store From dbd8c7b9fa166a5f6cf779a18b3cd852cc0dbeb5 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 24 Jul 2018 16:48:13 +0530 Subject: [PATCH 1088/2137] Add safe_write16 fast path (in C only) --- src/native/cpu.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/native/cpu.c b/src/native/cpu.c index e3d7c307..f2f5d70b 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -1119,7 +1119,8 @@ void safe_write8(int32_t addr, int32_t value) write8(translate_address_write(addr), value); } -void safe_write16(int32_t addr, int32_t value) +__attribute__((noinline)) +void safe_write16_slow(int32_t addr, int32_t value) { assert_no_cpu_exception(); @@ -1135,6 +1136,32 @@ void safe_write16(int32_t addr, int32_t value) } } +__attribute__((always_inline)) +void safe_write16(int32_t address, int32_t value) +{ +#if 1 + int32_t base = (uint32_t)address >> 12; + int32_t entry = tlb_data[base]; + int32_t info_bits = entry & 0xFFF & ~TLB_GLOBAL; + + if(info_bits == TLB_VALID && (address & 0xFFF) <= (0x1000 - 2)) + { + // - allowed to write in user-mode + // - not in memory mapped area + // - can be accessed from any cpl + // - does not contain code + + uint32_t phys_address = entry & ~0xFFF ^ address; + assert(!jit_page_has_code(phys_address >> 12)); + assert(!in_mapped_range(phys_address)); + *(uint16_t*)(mem8 + phys_address) = value; + return; + } +#endif + + safe_write16_slow(address, value); +} + __attribute__((noinline)) void safe_write32_slow(int32_t addr, int32_t value) { From 6f45d5f6edfe62cfc457a38a9614742bddfc3be6 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 24 Jul 2018 17:03:21 +0530 Subject: [PATCH 1089/2137] add gen_safe_write16, jit instr16_C7_0_mem --- src/rust/codegen.rs | 78 +++++++++++++++++++++++++++++++++++ src/rust/jit_instructions.rs | 12 ++++-- src/rust/wasmgen/wasm_util.rs | 6 +++ 3 files changed, 93 insertions(+), 3 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index f78301e2..55018212 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -334,6 +334,84 @@ pub fn gen_safe_write32(ctx: &mut JitContext, address_local: &WasmLocal, value_l builder.free_local(phys_addr_local); } +pub fn gen_safe_write16(ctx: &mut JitContext, address_local: &WasmLocal, value_local: &WasmLocal) { + // Generates safe_write16' fast-path inline, bailing to safe_write16_slow if necessary. + + let builder = &mut ctx.builder; + //let instruction_body = &mut ctx.builder.instruction_body; + //let cpu = &mut ctx.cpu; + + wasm_util::get_local(&mut builder.instruction_body, &address_local); + + // Pseudo: base_on_stack = (uint32_t)address >> 12; + wasm_util::push_i32(&mut builder.instruction_body, 12); + wasm_util::shr_u32(&mut builder.instruction_body); + + // scale index + wasm_util::push_i32(&mut builder.instruction_body, 2); + wasm_util::shl_i32(&mut builder.instruction_body); + + // Pseudo: entry = tlb_data[base_on_stack]; + let entry_local = builder.alloc_local(); + wasm_util::load_aligned_i32_from_stack( + &mut builder.instruction_body, + global_pointers::TLB_DATA, + ); + wasm_util::tee_local(&mut builder.instruction_body, &entry_local); + + // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && + // (address & 0xFFF) <= (0x1000 - 4)); + wasm_util::push_i32( + &mut builder.instruction_body, + (0xFFF & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32, + ); + wasm_util::and_i32(&mut builder.instruction_body); + + wasm_util::push_i32(&mut builder.instruction_body, TLB_VALID as i32); + wasm_util::eq_i32(&mut builder.instruction_body); + + wasm_util::get_local(&mut builder.instruction_body, &address_local); + wasm_util::push_i32(&mut builder.instruction_body, 0xFFF); + wasm_util::and_i32(&mut builder.instruction_body); + wasm_util::push_i32(&mut builder.instruction_body, 0x1000 - 2); + wasm_util::le_i32(&mut builder.instruction_body); + + wasm_util::and_i32(&mut builder.instruction_body); + + // Pseudo: + // if(can_use_fast_path) + // { + // phys_addr = entry & ~0xFFF ^ address; + wasm_util::if_void(&mut builder.instruction_body); + + wasm_util::get_local(&mut builder.instruction_body, &entry_local); + wasm_util::push_i32(&mut builder.instruction_body, !0xFFF); + wasm_util::and_i32(&mut builder.instruction_body); + wasm_util::get_local(&mut builder.instruction_body, &address_local); + wasm_util::xor_i32(&mut builder.instruction_body); + + builder.free_local(entry_local); + + let phys_addr_local = builder.alloc_local(); + // Pseudo: + // /* continued within can_use_fast_path branch */ + // mem8[phys_addr] = value; + + wasm_util::tee_local(&mut builder.instruction_body, &phys_addr_local); + wasm_util::get_local(&mut builder.instruction_body, &value_local); + wasm_util::store_unaligned_u16(&mut builder.instruction_body, global_pointers::MEMORY); + + // Pseudo: + // else { safe_read16_slow(address, value); } + wasm_util::else_(&mut builder.instruction_body); + wasm_util::get_local(&mut builder.instruction_body, &address_local); + wasm_util::get_local(&mut builder.instruction_body, &value_local); + gen_call_fn2(builder, "safe_write16_slow"); + wasm_util::block_end(&mut builder.instruction_body); + + builder.free_local(phys_addr_local); +} + pub fn gen_fn1_reg16(ctx: &mut JitContext, name: &str, r: u32) { let fn_idx = ctx.builder.get_fn_idx(name, module_init::FN1_TYPE_INDEX); wasm_util::load_aligned_u16( diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index ff9da8b3..99542201 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -481,10 +481,16 @@ pub fn instr16_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { } pub fn instr16_C7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + let address_local = ctx.builder.alloc_local(); + let value_local = ctx.builder.alloc_local(); codegen::gen_modrm_resolve(ctx, modrm_byte); - let imm = ctx.cpu.read_imm16() as u32; - // XXX: inline called function - codegen::gen_modrm_fn1(ctx, "instr16_C7_0_mem", imm); + wasm_util::set_local(&mut ctx.builder.instruction_body, &address_local); + let imm = ctx.cpu.read_imm16(); + wasm_util::push_i32(&mut ctx.builder.instruction_body, imm as i32); + wasm_util::set_local(&mut ctx.builder.instruction_body, &value_local); + codegen::gen_safe_write16(ctx, &address_local, &value_local); + ctx.builder.free_local(address_local); + ctx.builder.free_local(value_local); } pub fn instr32_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { diff --git a/src/rust/wasmgen/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs index 8ca25a74..052d1ffd 100644 --- a/src/rust/wasmgen/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -99,6 +99,12 @@ pub fn store_unaligned_i32(buf: &mut Vec, byte_offset: u32) { write_leb_u32(buf, byte_offset); } +pub fn store_unaligned_u16(buf: &mut Vec, byte_offset: u32) { + buf.push(op::OP_I32STORE16); + buf.push(op::MEM_NO_ALIGN); + write_leb_u32(buf, byte_offset); +} + pub fn shr_u32(buf: &mut Vec) { buf.push(op::OP_I32SHRU); } pub fn shr_i32(buf: &mut Vec) { buf.push(op::OP_I32SHRS); } From c69186b48137955e4bc4ca1c1796344f048246d9 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 24 Jul 2018 17:12:39 +0530 Subject: [PATCH 1090/2137] Add safe_read16 fast path (in C only) --- src/native/cpu.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/native/cpu.c b/src/native/cpu.c index f2f5d70b..fa95c1f9 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -998,7 +998,8 @@ int32_t safe_read8(int32_t addr) return read8(translate_address_read(addr)); } -int32_t safe_read16(int32_t addr) +__attribute__((noinline)) +int32_t safe_read16_slow(int32_t addr) { assert_no_cpu_exception(); if((addr & 0xFFF) == 0xFFF) @@ -1011,6 +1012,28 @@ int32_t safe_read16(int32_t addr) } } +__attribute__((always_inline)) +int32_t safe_read16(int32_t address) +{ +#if 1 + int32_t base = (uint32_t)address >> 12; + int32_t entry = tlb_data[base]; + int32_t info_bits = entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~TLB_HAS_CODE; + + if(info_bits == TLB_VALID && (address & 0xFFF) <= (0x1000 - 2)) + { + // - not in memory mapped area + // - can be accessed from any cpl + + uint32_t phys_address = entry & ~0xFFF ^ address; + assert(!in_mapped_range(phys_address)); + return *(uint16_t*)(mem8 + phys_address); + } +#endif + + return safe_read16_slow(address); +} + __attribute__((noinline)) int32_t safe_read32s_slow(int32_t addr) { From 5f22e393ffc830f04d62f2a9103c9e36400cf6a0 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 24 Jul 2018 17:24:08 +0530 Subject: [PATCH 1091/2137] jit safe_read16 --- src/rust/codegen.rs | 183 ++++++++++++++++++++++------------ src/rust/wasmgen/wasm_util.rs | 6 ++ 2 files changed, 126 insertions(+), 63 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 55018212..3f002712 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -334,6 +334,75 @@ pub fn gen_safe_write32(ctx: &mut JitContext, address_local: &WasmLocal, value_l builder.free_local(phys_addr_local); } +pub fn gen_safe_read16(ctx: &mut JitContext) { + // Assumes virtual address has been pushed to the stack, and generates safe_read16's fast-path + // inline, bailing to safe_read16_slow if necessary + let builder = &mut ctx.builder; + + let address_local = builder.alloc_local(); + wasm_util::tee_local(&mut builder.instruction_body, &address_local); + + // Pseudo: base_on_stack = (uint32_t)address >> 12; + wasm_util::push_i32(&mut builder.instruction_body, 12); + wasm_util::shr_u32(&mut builder.instruction_body); + + // scale index + wasm_util::push_i32(&mut builder.instruction_body, 2); + wasm_util::shl_i32(&mut builder.instruction_body); + + // Pseudo: entry = tlb_data[base_on_stack]; + let entry_local = builder.alloc_local(); + wasm_util::load_aligned_i32_from_stack( + &mut builder.instruction_body, + global_pointers::TLB_DATA, + ); + wasm_util::tee_local(&mut builder.instruction_body, &entry_local); + + // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && + // (address & 0xFFF) <= (0x1000 - 2)); + wasm_util::push_i32( + &mut builder.instruction_body, + (0xFFF & !TLB_READONLY & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) + as i32, + ); + wasm_util::and_i32(&mut builder.instruction_body); + + wasm_util::push_i32(&mut builder.instruction_body, TLB_VALID as i32); + wasm_util::eq_i32(&mut builder.instruction_body); + + wasm_util::get_local(&mut builder.instruction_body, &address_local); + wasm_util::push_i32(&mut builder.instruction_body, 0xFFF); + wasm_util::and_i32(&mut builder.instruction_body); + wasm_util::push_i32(&mut builder.instruction_body, 0x1000 - 2); + wasm_util::le_i32(&mut builder.instruction_body); + + wasm_util::and_i32(&mut builder.instruction_body); + + // Pseudo: + // if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]); + wasm_util::if_i32(&mut builder.instruction_body); + wasm_util::get_local(&mut builder.instruction_body, &entry_local); + wasm_util::push_i32(&mut builder.instruction_body, !0xFFF); + wasm_util::and_i32(&mut builder.instruction_body); + wasm_util::get_local(&mut builder.instruction_body, &address_local); + wasm_util::xor_i32(&mut builder.instruction_body); + + wasm_util::load_unaligned_u16_from_stack( + &mut builder.instruction_body, + global_pointers::MEMORY, + ); + + // Pseudo: + // else { leave_on_stack(safe_read16_slow(address)); } + wasm_util::else_(&mut builder.instruction_body); + wasm_util::get_local(&mut builder.instruction_body, &address_local); + gen_call_fn1_ret(builder, "safe_read16_slow"); + wasm_util::block_end(&mut builder.instruction_body); + + builder.free_local(address_local); + builder.free_local(entry_local); +} + pub fn gen_safe_write16(ctx: &mut JitContext, address_local: &WasmLocal, value_local: &WasmLocal) { // Generates safe_write16' fast-path inline, bailing to safe_write16_slow if necessary. @@ -360,7 +429,7 @@ pub fn gen_safe_write16(ctx: &mut JitContext, address_local: &WasmLocal, value_l wasm_util::tee_local(&mut builder.instruction_body, &entry_local); // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && - // (address & 0xFFF) <= (0x1000 - 4)); + // (address & 0xFFF) <= (0x1000 - 2)); wasm_util::push_i32( &mut builder.instruction_body, (0xFFF & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32, @@ -486,83 +555,71 @@ pub fn gen_jmp_rel16(ctx: &mut JitContext, rel16: u16) { } pub fn gen_pop16_ss16(ctx: &mut JitContext) { - let safe_read16_idx = ctx - .builder - .get_fn_idx("safe_read16", module_init::FN1_RET_TYPE_INDEX); let sp_local = ctx.builder.alloc_local(); - { - let instruction_body = &mut ctx.builder.instruction_body; - // sp = segment_offsets[SS] + reg16[SP] (or just reg16[SP] if has_flat_segmentation) + // sp = segment_offsets[SS] + reg16[SP] (or just reg16[SP] if has_flat_segmentation) + wasm_util::load_aligned_i32( + &mut ctx.builder.instruction_body, + global_pointers::get_reg16_offset(regs::SP), + ); + wasm_util::tee_local(&mut ctx.builder.instruction_body, &sp_local); + + if !ctx.cpu.has_flat_segmentation() { wasm_util::load_aligned_i32( - instruction_body, - global_pointers::get_reg16_offset(regs::SP), + &mut ctx.builder.instruction_body, + global_pointers::get_seg_offset(regs::SS), ); - wasm_util::tee_local(instruction_body, &sp_local); - - if !ctx.cpu.has_flat_segmentation() { - wasm_util::load_aligned_i32( - instruction_body, - global_pointers::get_seg_offset(regs::SS), - ); - wasm_util::add_i32(instruction_body); - } - - // result = safe_read16(sp) - // XXX: inline safe_read16 - wasm_util::call_fn(instruction_body, safe_read16_idx); - - // reg16[SP] += 2; - wasm_util::push_i32( - instruction_body, - global_pointers::get_reg16_offset(regs::SP) as i32, - ); - wasm_util::get_local(instruction_body, &sp_local); - wasm_util::push_i32(instruction_body, 2); - wasm_util::add_i32(instruction_body); - wasm_util::store_aligned_i32(instruction_body); + wasm_util::add_i32(&mut ctx.builder.instruction_body); } + + // result = safe_read16(sp) + gen_safe_read16(ctx); + + // reg16[SP] += 2; + wasm_util::push_i32( + &mut ctx.builder.instruction_body, + global_pointers::get_reg16_offset(regs::SP) as i32, + ); + wasm_util::get_local(&mut ctx.builder.instruction_body, &sp_local); + wasm_util::push_i32(&mut ctx.builder.instruction_body, 2); + wasm_util::add_i32(&mut ctx.builder.instruction_body); + wasm_util::store_aligned_i32(&mut ctx.builder.instruction_body); + ctx.builder.free_local(sp_local); // return value is already on stack } pub fn gen_pop16_ss32(ctx: &mut JitContext) { - let safe_read16_idx = ctx - .builder - .get_fn_idx("safe_read16", module_init::FN1_RET_TYPE_INDEX); let esp_local = ctx.builder.alloc_local(); - { - let instruction_body = &mut ctx.builder.instruction_body; - // esp = segment_offsets[SS] + reg32s[ESP] (or just reg32s[ESP] if has_flat_segmentation) + + // esp = segment_offsets[SS] + reg32s[ESP] (or just reg32s[ESP] if has_flat_segmentation) + wasm_util::load_aligned_i32( + &mut ctx.builder.instruction_body, + global_pointers::get_reg32_offset(regs::ESP), + ); + wasm_util::tee_local(&mut ctx.builder.instruction_body, &esp_local); + + if !ctx.cpu.has_flat_segmentation() { wasm_util::load_aligned_i32( - instruction_body, - global_pointers::get_reg32_offset(regs::ESP), + &mut ctx.builder.instruction_body, + global_pointers::get_seg_offset(regs::SS), ); - wasm_util::tee_local(instruction_body, &esp_local); - - if !ctx.cpu.has_flat_segmentation() { - wasm_util::load_aligned_i32( - instruction_body, - global_pointers::get_seg_offset(regs::SS), - ); - wasm_util::add_i32(instruction_body); - } - - // result = safe_read16(esp) - // XXX: inline safe_read16 - wasm_util::call_fn(instruction_body, safe_read16_idx); - - // reg32s[ESP] += 2; - wasm_util::push_i32( - instruction_body, - global_pointers::get_reg32_offset(regs::ESP) as i32, - ); - wasm_util::get_local(instruction_body, &esp_local); - wasm_util::push_i32(instruction_body, 2); - wasm_util::add_i32(instruction_body); - wasm_util::store_aligned_i32(instruction_body); + wasm_util::add_i32(&mut ctx.builder.instruction_body); } + + // result = safe_read16(esp) + gen_safe_read16(ctx); + + // reg32s[ESP] += 2; + wasm_util::push_i32( + &mut ctx.builder.instruction_body, + global_pointers::get_reg32_offset(regs::ESP) as i32, + ); + wasm_util::get_local(&mut ctx.builder.instruction_body, &esp_local); + wasm_util::push_i32(&mut ctx.builder.instruction_body, 2); + wasm_util::add_i32(&mut ctx.builder.instruction_body); + wasm_util::store_aligned_i32(&mut ctx.builder.instruction_body); ctx.builder.free_local(esp_local); // return value is already on stack diff --git a/src/rust/wasmgen/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs index 052d1ffd..80d49fb6 100644 --- a/src/rust/wasmgen/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -85,6 +85,12 @@ pub fn load_unaligned_i32_from_stack(buf: &mut Vec, byte_offset: u32) { write_leb_u32(buf, byte_offset); } +pub fn load_unaligned_u16_from_stack(buf: &mut Vec, byte_offset: u32) { + buf.push(op::OP_I32LOAD16U); + buf.push(op::MEM_NO_ALIGN); + write_leb_u32(buf, byte_offset); +} + pub fn load_aligned_i32_from_stack(buf: &mut Vec, byte_offset: u32) { buf.push(op::OP_I32LOAD); buf.push(op::MEM_ALIGN32); From 07630b3947ccde030ad58ae41577b6820397a459 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 24 Jul 2018 17:24:34 +0530 Subject: [PATCH 1092/2137] fix comment --- src/rust/codegen.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 3f002712..25fdcd92 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -471,7 +471,7 @@ pub fn gen_safe_write16(ctx: &mut JitContext, address_local: &WasmLocal, value_l wasm_util::store_unaligned_u16(&mut builder.instruction_body, global_pointers::MEMORY); // Pseudo: - // else { safe_read16_slow(address, value); } + // else { safe_write16_slow(address, value); } wasm_util::else_(&mut builder.instruction_body); wasm_util::get_local(&mut builder.instruction_body, &address_local); wasm_util::get_local(&mut builder.instruction_body, &value_local); From 2541789cccb54279a4e9d7fbe6fc51c69934eab4 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Tue, 24 Jul 2018 18:20:22 +0530 Subject: [PATCH 1093/2137] run rust tests with nightly toolchain --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 8067a698..e9809f6c 100644 --- a/Makefile +++ b/Makefile @@ -309,7 +309,7 @@ devices-test: all-debug ./tests/devices/virtio_9p.js rust-test: $(RUST_FILES) - env RUST_BACKTRACE=full RUST_TEST_THREADS=1 cargo test -- --nocapture + env RUST_BACKTRACE=full RUST_TEST_THREADS=1 cargo +nightly test -- --nocapture ./tests/rust/verify-wasmgen-dummy-output.js api-tests: all-debug From 57d79c256d45efc9c0b81d5d8ee14dafd163c8c9 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Fri, 27 Jul 2018 13:22:00 +0530 Subject: [PATCH 1094/2137] remove unused local --- src/rust/codegen.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 25fdcd92..edb8788b 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -314,12 +314,10 @@ pub fn gen_safe_write32(ctx: &mut JitContext, address_local: &WasmLocal, value_l builder.free_local(entry_local); - let phys_addr_local = builder.alloc_local(); // Pseudo: // /* continued within can_use_fast_path branch */ // mem8[phys_addr] = value; - wasm_util::tee_local(&mut builder.instruction_body, &phys_addr_local); wasm_util::get_local(&mut builder.instruction_body, &value_local); wasm_util::store_unaligned_i32(&mut builder.instruction_body, global_pointers::MEMORY); @@ -330,8 +328,6 @@ pub fn gen_safe_write32(ctx: &mut JitContext, address_local: &WasmLocal, value_l wasm_util::get_local(&mut builder.instruction_body, &value_local); gen_call_fn2(builder, "safe_write32_slow"); wasm_util::block_end(&mut builder.instruction_body); - - builder.free_local(phys_addr_local); } pub fn gen_safe_read16(ctx: &mut JitContext) { @@ -461,12 +457,10 @@ pub fn gen_safe_write16(ctx: &mut JitContext, address_local: &WasmLocal, value_l builder.free_local(entry_local); - let phys_addr_local = builder.alloc_local(); // Pseudo: // /* continued within can_use_fast_path branch */ // mem8[phys_addr] = value; - wasm_util::tee_local(&mut builder.instruction_body, &phys_addr_local); wasm_util::get_local(&mut builder.instruction_body, &value_local); wasm_util::store_unaligned_u16(&mut builder.instruction_body, global_pointers::MEMORY); @@ -477,8 +471,6 @@ pub fn gen_safe_write16(ctx: &mut JitContext, address_local: &WasmLocal, value_l wasm_util::get_local(&mut builder.instruction_body, &value_local); gen_call_fn2(builder, "safe_write16_slow"); wasm_util::block_end(&mut builder.instruction_body); - - builder.free_local(phys_addr_local); } pub fn gen_fn1_reg16(ctx: &mut JitContext, name: &str, r: u32) { From 9b0fdc50197f56e3ca0da4974e6824338b26ebce Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sat, 28 Jul 2018 20:07:39 +0530 Subject: [PATCH 1095/2137] Improve locals handling Issuing of locals should only happen with set_new_local and tee_new_local now --- src/rust/codegen.rs | 40 ++++++++++--------------------- src/rust/jit.rs | 15 +++--------- src/rust/jit_instructions.rs | 19 +++++---------- src/rust/wasmgen/module_init.rs | 16 +++++++++---- src/rust/wasmgen/wasm_util.rs | 16 ++++++++++++- tests/expect/tests/mov32-mem.wast | 22 ++++++++--------- 6 files changed, 57 insertions(+), 71 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index edb8788b..a53ef2f4 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -192,8 +192,7 @@ pub fn gen_safe_read32(ctx: &mut JitContext) { //let instruction_body = &mut ctx.builder.instruction_body; //let cpu = &mut ctx.cpu; - let address_local = builder.alloc_local(); - wasm_util::tee_local(&mut builder.instruction_body, &address_local); + let address_local = wasm_util::tee_new_local(builder); // Pseudo: base_on_stack = (uint32_t)address >> 12; wasm_util::push_i32(&mut builder.instruction_body, 12); @@ -204,12 +203,11 @@ pub fn gen_safe_read32(ctx: &mut JitContext) { wasm_util::shl_i32(&mut builder.instruction_body); // Pseudo: entry = tlb_data[base_on_stack]; - let entry_local = builder.alloc_local(); wasm_util::load_aligned_i32_from_stack( &mut builder.instruction_body, global_pointers::TLB_DATA, ); - wasm_util::tee_local(&mut builder.instruction_body, &entry_local); + let entry_local = wasm_util::tee_new_local(builder); // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && // (address & 0xFFF) <= (0x1000 - 4)); @@ -274,12 +272,11 @@ pub fn gen_safe_write32(ctx: &mut JitContext, address_local: &WasmLocal, value_l wasm_util::shl_i32(&mut builder.instruction_body); // Pseudo: entry = tlb_data[base_on_stack]; - let entry_local = builder.alloc_local(); wasm_util::load_aligned_i32_from_stack( &mut builder.instruction_body, global_pointers::TLB_DATA, ); - wasm_util::tee_local(&mut builder.instruction_body, &entry_local); + let entry_local = wasm_util::tee_new_local(builder); // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && // (address & 0xFFF) <= (0x1000 - 4)); @@ -335,8 +332,7 @@ pub fn gen_safe_read16(ctx: &mut JitContext) { // inline, bailing to safe_read16_slow if necessary let builder = &mut ctx.builder; - let address_local = builder.alloc_local(); - wasm_util::tee_local(&mut builder.instruction_body, &address_local); + let address_local = wasm_util::tee_new_local(builder); // Pseudo: base_on_stack = (uint32_t)address >> 12; wasm_util::push_i32(&mut builder.instruction_body, 12); @@ -347,12 +343,11 @@ pub fn gen_safe_read16(ctx: &mut JitContext) { wasm_util::shl_i32(&mut builder.instruction_body); // Pseudo: entry = tlb_data[base_on_stack]; - let entry_local = builder.alloc_local(); wasm_util::load_aligned_i32_from_stack( &mut builder.instruction_body, global_pointers::TLB_DATA, ); - wasm_util::tee_local(&mut builder.instruction_body, &entry_local); + let entry_local = wasm_util::tee_new_local(builder); // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && // (address & 0xFFF) <= (0x1000 - 2)); @@ -417,12 +412,11 @@ pub fn gen_safe_write16(ctx: &mut JitContext, address_local: &WasmLocal, value_l wasm_util::shl_i32(&mut builder.instruction_body); // Pseudo: entry = tlb_data[base_on_stack]; - let entry_local = builder.alloc_local(); wasm_util::load_aligned_i32_from_stack( &mut builder.instruction_body, global_pointers::TLB_DATA, ); - wasm_util::tee_local(&mut builder.instruction_body, &entry_local); + let entry_local = wasm_util::tee_new_local(builder); // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && // (address & 0xFFF) <= (0x1000 - 2)); @@ -513,16 +507,14 @@ pub fn gen_add_prefix_bits(ctx: &mut JitContext, mask: u32) { pub fn gen_jmp_rel16(ctx: &mut JitContext, rel16: u16) { let cs_offset_addr = global_pointers::get_seg_offset(regs::CS); - let local = ctx.builder.alloc_local(); + wasm_util::load_aligned_i32(&mut ctx.builder.instruction_body, cs_offset_addr); + let local = wasm_util::set_new_local(ctx.builder); // generate: // *instruction_pointer = cs_offset + ((*instruction_pointer - cs_offset + rel16) & 0xFFFF); { let instruction_body = &mut ctx.builder.instruction_body; - wasm_util::load_aligned_i32(instruction_body, cs_offset_addr); - wasm_util::set_local(instruction_body, &local); - wasm_util::push_i32( instruction_body, global_pointers::INSTRUCTION_POINTER as i32, @@ -547,14 +539,12 @@ pub fn gen_jmp_rel16(ctx: &mut JitContext, rel16: u16) { } pub fn gen_pop16_ss16(ctx: &mut JitContext) { - let sp_local = ctx.builder.alloc_local(); - // sp = segment_offsets[SS] + reg16[SP] (or just reg16[SP] if has_flat_segmentation) wasm_util::load_aligned_i32( &mut ctx.builder.instruction_body, global_pointers::get_reg16_offset(regs::SP), ); - wasm_util::tee_local(&mut ctx.builder.instruction_body, &sp_local); + let sp_local = wasm_util::tee_new_local(ctx.builder); if !ctx.cpu.has_flat_segmentation() { wasm_util::load_aligned_i32( @@ -583,14 +573,12 @@ pub fn gen_pop16_ss16(ctx: &mut JitContext) { } pub fn gen_pop16_ss32(ctx: &mut JitContext) { - let esp_local = ctx.builder.alloc_local(); - // esp = segment_offsets[SS] + reg32s[ESP] (or just reg32s[ESP] if has_flat_segmentation) wasm_util::load_aligned_i32( &mut ctx.builder.instruction_body, global_pointers::get_reg32_offset(regs::ESP), ); - wasm_util::tee_local(&mut ctx.builder.instruction_body, &esp_local); + let esp_local = wasm_util::tee_new_local(ctx.builder); if !ctx.cpu.has_flat_segmentation() { wasm_util::load_aligned_i32( @@ -627,14 +615,12 @@ pub fn gen_pop16(ctx: &mut JitContext) { } pub fn gen_pop32s_ss16(ctx: &mut JitContext) { - let local_sp = ctx.builder.alloc_local(); - // sp = reg16[SP] wasm_util::load_aligned_i32( &mut ctx.builder.instruction_body, global_pointers::get_reg16_offset(regs::SP), ); - wasm_util::tee_local(&mut ctx.builder.instruction_body, &local_sp); + let local_sp = wasm_util::tee_new_local(ctx.builder); // result = safe_read32s(segment_offsets[SS] + sp) (or just sp if has_flat_segmentation) if !ctx.cpu.has_flat_segmentation() { @@ -663,14 +649,12 @@ pub fn gen_pop32s_ss16(ctx: &mut JitContext) { } pub fn gen_pop32s_ss32(ctx: &mut JitContext) { - let local_esp = ctx.builder.alloc_local(); - // esp = reg32s[ESP] wasm_util::load_aligned_i32( &mut ctx.builder.instruction_body, global_pointers::get_reg32_offset(regs::ESP), ); - wasm_util::tee_local(&mut ctx.builder.instruction_body, &local_esp); + let local_esp = wasm_util::tee_new_local(ctx.builder); // result = safe_read32s(segment_offsets[SS] + esp) (or just esp if has_flat_segmentation) if !ctx.cpu.has_flat_segmentation() { diff --git a/src/rust/jit.rs b/src/rust/jit.rs index b2e2f129..ca712d66 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -860,13 +860,7 @@ fn jit_generate_module( let fn_get_seg_idx = builder.get_fn_idx("get_seg", module_init::FN1_RET_TYPE_INDEX); dbg_assert!(fn_get_seg_idx == FN_GET_SEG_IDX); - let gen_local_state = builder.alloc_local(); - let gen_local_iteration_counter = if JIT_ALWAYS_USE_LOOP_SAFETY || requires_loop_limit { - Some(builder.alloc_local()) - } - else { - None - }; + let mut gen_local_iteration_counter = None; let basic_block_indices: HashMap = basic_blocks .iter() @@ -879,18 +873,15 @@ fn jit_generate_module( &mut builder.instruction_body, &builder.arg_local_initial_state, ); - wasm_util::set_local(&mut builder.instruction_body, &gen_local_state); + let gen_local_state = wasm_util::set_new_local(builder); // initialise max_iterations if JIT_ALWAYS_USE_LOOP_SAFETY || requires_loop_limit { - let gen_local_iteration_counter = gen_local_iteration_counter - .as_ref() - .expect("iteration counter"); wasm_util::push_i32( &mut builder.instruction_body, JIT_MAX_ITERATIONS_PER_FUNCTION as i32, ); - wasm_util::set_local(&mut builder.instruction_body, gen_local_iteration_counter); + gen_local_iteration_counter = Some(wasm_util::set_new_local(builder)); } // main state machine loop diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 99542201..92b224ac 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -257,18 +257,15 @@ pub fn instr16_89_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { } pub fn instr32_89_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { // Pseudo: safe_write32(modrm_resolve(modrm_byte), reg32s[r]); - let address_local = ctx.builder.alloc_local(); - let value_local = ctx.builder.alloc_local(); - codegen::gen_modrm_resolve(ctx, modrm_byte); - wasm_util::set_local(&mut ctx.builder.instruction_body, &address_local); + let address_local = wasm_util::set_new_local(ctx.builder); wasm_util::push_i32( &mut ctx.builder.instruction_body, global_pointers::get_reg32_offset(r) as i32, ); wasm_util::load_aligned_i32_from_stack(&mut ctx.builder.instruction_body, 0); - wasm_util::set_local(&mut ctx.builder.instruction_body, &value_local); + let value_local = wasm_util::set_new_local(ctx.builder); codegen::gen_safe_write32(ctx, &address_local, &value_local); ctx.builder.free_local(address_local); @@ -481,13 +478,11 @@ pub fn instr16_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { } pub fn instr16_C7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - let address_local = ctx.builder.alloc_local(); - let value_local = ctx.builder.alloc_local(); codegen::gen_modrm_resolve(ctx, modrm_byte); - wasm_util::set_local(&mut ctx.builder.instruction_body, &address_local); + let address_local = wasm_util::set_new_local(ctx.builder); let imm = ctx.cpu.read_imm16(); wasm_util::push_i32(&mut ctx.builder.instruction_body, imm as i32); - wasm_util::set_local(&mut ctx.builder.instruction_body, &value_local); + let value_local = wasm_util::set_new_local(ctx.builder); codegen::gen_safe_write16(ctx, &address_local, &value_local); ctx.builder.free_local(address_local); ctx.builder.free_local(value_local); @@ -504,13 +499,11 @@ pub fn instr32_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { } pub fn instr32_C7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - let address_local = ctx.builder.alloc_local(); - let value_local = ctx.builder.alloc_local(); codegen::gen_modrm_resolve(ctx, modrm_byte); - wasm_util::set_local(&mut ctx.builder.instruction_body, &address_local); + let address_local = wasm_util::set_new_local(ctx.builder); let imm = ctx.cpu.read_imm32(); wasm_util::push_i32(&mut ctx.builder.instruction_body, imm as i32); - wasm_util::set_local(&mut ctx.builder.instruction_body, &value_local); + let value_local = wasm_util::set_new_local(ctx.builder); codegen::gen_safe_write32(ctx, &address_local, &value_local); ctx.builder.free_local(address_local); ctx.builder.free_local(value_local); diff --git a/src/rust/wasmgen/module_init.rs b/src/rust/wasmgen/module_init.rs index c7573a0f..3db5aab4 100644 --- a/src/rust/wasmgen/module_init.rs +++ b/src/rust/wasmgen/module_init.rs @@ -324,7 +324,13 @@ impl WasmBuilder { self.code_section.append(&mut self.instruction_body); } - pub fn alloc_local(&mut self) -> WasmLocal { + // XXX: This should not be marked pub and not be prefixed with "_", + // but we need to share it with wasm_util so it is pub for now + // Moving set_local and tee_local to builder further complicate + // things. We should be able to fix this by better structuring the + // builder methods and wasm methods in the future. + // Currently only wasm_utils and the tests of this module use it. + pub fn _alloc_local(&mut self) -> WasmLocal { match self.free_locals.pop() { Some(local) => local, None => { @@ -369,7 +375,7 @@ mod tests { let bar_index = m.get_fn_idx("bar", FN0_TYPE_INDEX); call_fn(&mut m.code_section, bar_index); - let _ = m.alloc_local(); // for ensuring that reset clears previous locals + let _ = m._alloc_local(); // for ensuring that reset clears previous locals m.finish(); m.reset(); @@ -382,17 +388,17 @@ mod tests { call_fn(&mut m.instruction_body, foo_index); push_i32(&mut m.code_section, 10); - let local1 = m.alloc_local(); + let local1 = m._alloc_local(); tee_local(&mut m.code_section, &local1); // local1 = 10 push_i32(&mut m.code_section, 20); add_i32(&mut m.code_section); - let local2 = m.alloc_local(); + let local2 = m._alloc_local(); tee_local(&mut m.code_section, &local2); // local2 = 30 m.free_local(local1); - let local3 = m.alloc_local(); + let local3 = m._alloc_local(); assert_eq!(local3.idx(), 0); m.free_local(local2); diff --git a/src/rust/wasmgen/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs index 80d49fb6..0c55968b 100644 --- a/src/rust/wasmgen/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -1,5 +1,5 @@ use leb::{write_fixed_leb16_at_idx, write_leb_i32, write_leb_u32}; -use wasmgen::module_init::WasmLocal; +use wasmgen::module_init::{WasmBuilder, WasmLocal}; use wasmgen::wasm_opcodes as op; pub fn push_i32(buf: &mut Vec, v: i32) { @@ -161,6 +161,20 @@ pub fn get_local(buf: &mut Vec, local: &WasmLocal) { buf.push(local.idx()); } +pub fn set_new_local(builder: &mut WasmBuilder) -> WasmLocal { + let local = builder._alloc_local(); + builder.instruction_body.push(op::OP_SETLOCAL); + builder.instruction_body.push(local.idx()); + local +} + +pub fn tee_new_local(builder: &mut WasmBuilder) -> WasmLocal { + let local = builder._alloc_local(); + builder.instruction_body.push(op::OP_TEELOCAL); + builder.instruction_body.push(local.idx()); + local +} + pub fn set_local(buf: &mut Vec, local: &WasmLocal) { buf.push(op::OP_SETLOCAL); buf.push(local.idx()); diff --git a/tests/expect/tests/mov32-mem.wast b/tests/expect/tests/mov32-mem.wast index 0f13849a..a1aa22cb 100644 --- a/tests/expect/tests/mov32-mem.wast +++ b/tests/expect/tests/mov32-mem.wast @@ -55,12 +55,11 @@ (i32.const 4092))) (then (i32.store offset=8388608 align=1 - (tee_local $l2 - (i32.xor - (i32.and - (get_local $l2) - (i32.const -4096)) - (get_local $l0))) + (i32.xor + (i32.and + (get_local $l2) + (i32.const -4096)) + (get_local $l0)) (get_local $l1))) (else (call $e.safe_write32_slow @@ -103,12 +102,11 @@ (i32.const 4092))) (then (i32.store offset=8388608 align=1 - (tee_local $l2 - (i32.xor - (i32.and - (get_local $l2) - (i32.const -4096)) - (get_local $l1))) + (i32.xor + (i32.and + (get_local $l2) + (i32.const -4096)) + (get_local $l1)) (get_local $l0))) (else (call $e.safe_write32_slow From 046e399b55bb6471aad357b0371ac39450da4f9c Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sun, 29 Jul 2018 00:03:40 +0530 Subject: [PATCH 1096/2137] extend Vec with wasm_util functions --- src/rust/codegen.rs | 615 +++++++++++++++----------------- src/rust/jit.rs | 107 +++--- src/rust/jit_instructions.rs | 84 ++--- src/rust/modrm.rs | 89 +++-- src/rust/wasmgen/module_init.rs | 50 +-- src/rust/wasmgen/wasm_util.rs | 423 ++++++++++++---------- 6 files changed, 700 insertions(+), 668 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index a53ef2f4..99fbded8 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -4,53 +4,51 @@ use modrm; use regs; use tlb::{TLB_GLOBAL, TLB_NO_USER, TLB_READONLY, TLB_VALID}; use wasmgen::module_init::{WasmBuilder, WasmLocal}; +use wasmgen::wasm_util::WasmBuf; use wasmgen::{module_init, wasm_util}; pub fn gen_set_previous_eip_offset_from_eip(builder: &mut WasmBuilder, n: u32) { let cs = &mut builder.code_section; - wasm_util::push_i32(cs, global_pointers::PREVIOUS_IP as i32); // store address of previous ip - wasm_util::load_aligned_i32(cs, global_pointers::INSTRUCTION_POINTER); // load ip + cs.push_i32(global_pointers::PREVIOUS_IP as i32); // store address of previous ip + cs.load_aligned_i32(global_pointers::INSTRUCTION_POINTER); // load ip if n != 0 { - wasm_util::push_i32(cs, n as i32); - wasm_util::add_i32(cs); // add constant to ip value + cs.push_i32(n as i32); + cs.add_i32(); // add constant to ip value } - wasm_util::store_aligned_i32(cs); // store it as previous ip + cs.store_aligned_i32(); // store it as previous ip } pub fn gen_increment_instruction_pointer(builder: &mut WasmBuilder, n: u32) { let cs = &mut builder.code_section; - wasm_util::push_i32(cs, global_pointers::INSTRUCTION_POINTER as i32); // store address of ip + cs.push_i32(global_pointers::INSTRUCTION_POINTER as i32); // store address of ip - wasm_util::load_aligned_i32(cs, global_pointers::INSTRUCTION_POINTER); // load ip + cs.load_aligned_i32(global_pointers::INSTRUCTION_POINTER); // load ip - wasm_util::push_i32(cs, n as i32); + cs.push_i32(n as i32); - wasm_util::add_i32(cs); - wasm_util::store_aligned_i32(cs); // store it back in + cs.add_i32(); + cs.store_aligned_i32(); // store it back in } pub fn gen_set_previous_eip(builder: &mut WasmBuilder) { let cs = &mut builder.code_section; - wasm_util::push_i32(cs, global_pointers::PREVIOUS_IP as i32); // store address of previous ip - wasm_util::load_aligned_i32(cs, global_pointers::INSTRUCTION_POINTER); // load ip - wasm_util::store_aligned_i32(cs); // store it as previous ip + cs.push_i32(global_pointers::PREVIOUS_IP as i32); // store address of previous ip + cs.load_aligned_i32(global_pointers::INSTRUCTION_POINTER); // load ip + cs.store_aligned_i32(); // store it as previous ip } pub fn gen_relative_jump(builder: &mut WasmBuilder, n: i32) { // add n to instruction_pointer (without setting the offset as above) let instruction_body = &mut builder.instruction_body; - wasm_util::push_i32( - instruction_body, - global_pointers::INSTRUCTION_POINTER as i32, - ); - wasm_util::load_aligned_i32(instruction_body, global_pointers::INSTRUCTION_POINTER); - wasm_util::push_i32(instruction_body, n); - wasm_util::add_i32(instruction_body); - wasm_util::store_aligned_i32(instruction_body); + instruction_body.push_i32(global_pointers::INSTRUCTION_POINTER as i32); + instruction_body.load_aligned_i32(global_pointers::INSTRUCTION_POINTER); + instruction_body.push_i32(n); + instruction_body.add_i32(); + instruction_body.store_aligned_i32(); } pub fn gen_increment_variable(builder: &mut WasmBuilder, variable_address: u32, n: i32) { - wasm_util::increment_variable(&mut builder.code_section, variable_address, n); + builder.code_section.increment_variable(variable_address, n); } pub fn gen_increment_timestamp_counter(builder: &mut WasmBuilder, n: i32) { @@ -58,78 +56,78 @@ pub fn gen_increment_timestamp_counter(builder: &mut WasmBuilder, n: i32) { } pub fn gen_increment_mem32(builder: &mut WasmBuilder, addr: u32) { - wasm_util::increment_mem32(&mut builder.code_section, addr) + builder.code_section.increment_mem32(addr) } pub fn gen_fn0_const(ctx: &mut JitContext, name: &str) { let builder = &mut ctx.builder; let fn_idx = builder.get_fn_idx(name, module_init::FN0_TYPE_INDEX); - wasm_util::call_fn(&mut builder.instruction_body, fn_idx); + builder.instruction_body.call_fn(fn_idx); } pub fn gen_fn0_const_ret(builder: &mut WasmBuilder, name: &str) { let fn_idx = builder.get_fn_idx(name, module_init::FN0_RET_TYPE_INDEX); - wasm_util::call_fn(&mut builder.instruction_body, fn_idx); + builder.instruction_body.call_fn(fn_idx); } pub fn gen_fn1_const(ctx: &mut JitContext, name: &str, arg0: u32) { let builder = &mut ctx.builder; let fn_idx = builder.get_fn_idx(name, module_init::FN1_TYPE_INDEX); - wasm_util::push_i32(&mut builder.instruction_body, arg0 as i32); - wasm_util::call_fn(&mut builder.instruction_body, fn_idx); + builder.instruction_body.push_i32(arg0 as i32); + builder.instruction_body.call_fn(fn_idx); } pub fn gen_call_fn1_ret(builder: &mut WasmBuilder, name: &str) { // generates: fn( _ ) where _ must be left on the stack before calling this, and fn returns a value let fn_idx = builder.get_fn_idx(name, module_init::FN1_RET_TYPE_INDEX); - wasm_util::call_fn(&mut builder.instruction_body, fn_idx); + builder.instruction_body.call_fn(fn_idx); } pub fn gen_fn2_const(ctx: &mut JitContext, name: &str, arg0: u32, arg1: u32) { let builder = &mut ctx.builder; let fn_idx = builder.get_fn_idx(name, module_init::FN2_TYPE_INDEX); - wasm_util::push_i32(&mut builder.instruction_body, arg0 as i32); - wasm_util::push_i32(&mut builder.instruction_body, arg1 as i32); - wasm_util::call_fn(&mut builder.instruction_body, fn_idx); + builder.instruction_body.push_i32(arg0 as i32); + builder.instruction_body.push_i32(arg1 as i32); + builder.instruction_body.call_fn(fn_idx); } pub fn gen_call_fn2(builder: &mut WasmBuilder, name: &str) { // generates: fn( _, _ ) where _ must be left on the stack before calling this let fn_idx = builder.get_fn_idx(name, module_init::FN2_TYPE_INDEX); - wasm_util::call_fn(&mut builder.instruction_body, fn_idx); + builder.instruction_body.call_fn(fn_idx); } pub fn gen_fn3_const(ctx: &mut JitContext, name: &str, arg0: u32, arg1: u32, arg2: u32) { let builder = &mut ctx.builder; let fn_idx = builder.get_fn_idx(name, module_init::FN3_TYPE_INDEX); - wasm_util::push_i32(&mut builder.instruction_body, arg0 as i32); - wasm_util::push_i32(&mut builder.instruction_body, arg1 as i32); - wasm_util::push_i32(&mut builder.instruction_body, arg2 as i32); - wasm_util::call_fn(&mut builder.instruction_body, fn_idx); + builder.instruction_body.push_i32(arg0 as i32); + builder.instruction_body.push_i32(arg1 as i32); + builder.instruction_body.push_i32(arg2 as i32); + builder.instruction_body.call_fn(fn_idx); } pub fn gen_modrm_fn0(ctx: &mut JitContext, name: &str) { // generates: fn( _ ) let builder = &mut ctx.builder; let fn_idx = builder.get_fn_idx(name, module_init::FN1_TYPE_INDEX); - wasm_util::call_fn(&mut builder.instruction_body, fn_idx); + builder.instruction_body.call_fn(fn_idx); } pub fn gen_modrm_fn1(ctx: &mut JitContext, name: &str, arg0: u32) { // generates: fn( _, arg0 ) let builder = &mut ctx.builder; let fn_idx = builder.get_fn_idx(name, module_init::FN2_TYPE_INDEX); - wasm_util::push_i32(&mut builder.instruction_body, arg0 as i32); - wasm_util::call_fn(&mut builder.instruction_body, fn_idx); + builder.instruction_body.push_i32(arg0 as i32); + builder.instruction_body.call_fn(fn_idx); } pub fn gen_modrm_fn2(ctx: &mut JitContext, name: &str, arg0: u32, arg1: u32) { // generates: fn( _, arg0, arg1 ) let builder = &mut ctx.builder; let fn_idx = builder.get_fn_idx(name, module_init::FN3_TYPE_INDEX); - wasm_util::push_i32(&mut builder.instruction_body, arg0 as i32); - wasm_util::push_i32(&mut builder.instruction_body, arg1 as i32); - wasm_util::call_fn(&mut builder.instruction_body, fn_idx); + builder.instruction_body.push_i32(arg0 as i32); + builder.instruction_body.push_i32(arg1 as i32); + builder.instruction_body.call_fn(fn_idx); } pub fn gen_modrm_resolve(ctx: &mut JitContext, modrm_byte: u8) { modrm::gen(ctx, modrm_byte) } @@ -137,52 +135,46 @@ pub fn gen_modrm_resolve(ctx: &mut JitContext, modrm_byte: u8) { modrm::gen(ctx, pub fn gen_set_reg16_r(ctx: &mut JitContext, dest: u32, src: u32) { // generates: reg16[r_dest] = reg16[r_src] let builder = &mut ctx.builder; - wasm_util::push_i32( - &mut builder.instruction_body, - global_pointers::get_reg16_offset(dest) as i32, - ); - wasm_util::load_aligned_u16( - &mut builder.instruction_body, - global_pointers::get_reg16_offset(src), - ); - wasm_util::store_aligned_u16(&mut builder.instruction_body); + builder + .instruction_body + .push_i32(global_pointers::get_reg16_offset(dest) as i32); + builder + .instruction_body + .load_aligned_u16(global_pointers::get_reg16_offset(src)); + builder.instruction_body.store_aligned_u16(); } pub fn gen_set_reg32_r(ctx: &mut JitContext, dest: u32, src: u32) { // generates: reg32s[r_dest] = reg32s[r_src] let builder = &mut ctx.builder; - wasm_util::push_i32( - &mut builder.instruction_body, - global_pointers::get_reg32_offset(dest) as i32, - ); - wasm_util::load_aligned_i32( - &mut builder.instruction_body, - global_pointers::get_reg32_offset(src), - ); - wasm_util::store_aligned_i32(&mut builder.instruction_body); + builder + .instruction_body + .push_i32(global_pointers::get_reg32_offset(dest) as i32); + builder + .instruction_body + .load_aligned_i32(global_pointers::get_reg32_offset(src)); + builder.instruction_body.store_aligned_i32(); } pub fn gen_set_reg16_fn0(ctx: &mut JitContext, name: &str, reg: u32) { // generates: reg16[reg] = fn() let builder = &mut ctx.builder; let fn_idx = builder.get_fn_idx(name, module_init::FN0_RET_TYPE_INDEX); - wasm_util::push_i32( - &mut builder.instruction_body, - global_pointers::get_reg16_offset(reg) as i32, - ); - wasm_util::call_fn(&mut builder.instruction_body, fn_idx); - wasm_util::store_aligned_u16(&mut builder.instruction_body); + builder + .instruction_body + .push_i32(global_pointers::get_reg16_offset(reg) as i32); + builder.instruction_body.call_fn(fn_idx); + builder.instruction_body.store_aligned_u16(); } pub fn gen_set_reg32s_fn0(ctx: &mut JitContext, name: &str, reg: u32) { // generates: reg32s[reg] = fn() let builder = &mut ctx.builder; let fn_idx = builder.get_fn_idx(name, module_init::FN0_RET_TYPE_INDEX); - wasm_util::push_i32( - &mut builder.instruction_body, - global_pointers::get_reg32_offset(reg) as i32, - ); - wasm_util::call_fn(&mut builder.instruction_body, fn_idx); - wasm_util::store_aligned_i32(&mut builder.instruction_body); + builder + .instruction_body + .push_i32(global_pointers::get_reg32_offset(reg) as i32); + builder.instruction_body.call_fn(fn_idx); + builder.instruction_body.store_aligned_i32(); } pub fn gen_safe_read32(ctx: &mut JitContext) { @@ -195,60 +187,57 @@ pub fn gen_safe_read32(ctx: &mut JitContext) { let address_local = wasm_util::tee_new_local(builder); // Pseudo: base_on_stack = (uint32_t)address >> 12; - wasm_util::push_i32(&mut builder.instruction_body, 12); - wasm_util::shr_u32(&mut builder.instruction_body); + builder.instruction_body.push_i32(12); + builder.instruction_body.shr_u32(); // scale index - wasm_util::push_i32(&mut builder.instruction_body, 2); - wasm_util::shl_i32(&mut builder.instruction_body); + builder.instruction_body.push_i32(2); + builder.instruction_body.shl_i32(); // Pseudo: entry = tlb_data[base_on_stack]; - wasm_util::load_aligned_i32_from_stack( - &mut builder.instruction_body, - global_pointers::TLB_DATA, - ); + builder + .instruction_body + .load_aligned_i32_from_stack(global_pointers::TLB_DATA); let entry_local = wasm_util::tee_new_local(builder); // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && // (address & 0xFFF) <= (0x1000 - 4)); - wasm_util::push_i32( - &mut builder.instruction_body, + builder.instruction_body.push_i32( (0xFFF & !TLB_READONLY & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32, ); - wasm_util::and_i32(&mut builder.instruction_body); + builder.instruction_body.and_i32(); - wasm_util::push_i32(&mut builder.instruction_body, TLB_VALID as i32); - wasm_util::eq_i32(&mut builder.instruction_body); + builder.instruction_body.push_i32(TLB_VALID as i32); + builder.instruction_body.eq_i32(); - wasm_util::get_local(&mut builder.instruction_body, &address_local); - wasm_util::push_i32(&mut builder.instruction_body, 0xFFF); - wasm_util::and_i32(&mut builder.instruction_body); - wasm_util::push_i32(&mut builder.instruction_body, 0x1000 - 4); - wasm_util::le_i32(&mut builder.instruction_body); + builder.instruction_body.get_local(&address_local); + builder.instruction_body.push_i32(0xFFF); + builder.instruction_body.and_i32(); + builder.instruction_body.push_i32(0x1000 - 4); + builder.instruction_body.le_i32(); - wasm_util::and_i32(&mut builder.instruction_body); + builder.instruction_body.and_i32(); // Pseudo: // if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]); - wasm_util::if_i32(&mut builder.instruction_body); - wasm_util::get_local(&mut builder.instruction_body, &entry_local); - wasm_util::push_i32(&mut builder.instruction_body, !0xFFF); - wasm_util::and_i32(&mut builder.instruction_body); - wasm_util::get_local(&mut builder.instruction_body, &address_local); - wasm_util::xor_i32(&mut builder.instruction_body); + builder.instruction_body.if_i32(); + builder.instruction_body.get_local(&entry_local); + builder.instruction_body.push_i32(!0xFFF); + builder.instruction_body.and_i32(); + builder.instruction_body.get_local(&address_local); + builder.instruction_body.xor_i32(); - wasm_util::load_unaligned_i32_from_stack( - &mut builder.instruction_body, - global_pointers::MEMORY, - ); + builder + .instruction_body + .load_unaligned_i32_from_stack(global_pointers::MEMORY); // Pseudo: // else { leave_on_stack(safe_read32s_slow(address)); } - wasm_util::else_(&mut builder.instruction_body); - wasm_util::get_local(&mut builder.instruction_body, &address_local); + builder.instruction_body.else_(); + builder.instruction_body.get_local(&address_local); gen_call_fn1_ret(builder, "safe_read32s_slow"); - wasm_util::block_end(&mut builder.instruction_body); + builder.instruction_body.block_end(); builder.free_local(address_local); builder.free_local(entry_local); @@ -261,53 +250,51 @@ pub fn gen_safe_write32(ctx: &mut JitContext, address_local: &WasmLocal, value_l //let instruction_body = &mut ctx.builder.instruction_body; //let cpu = &mut ctx.cpu; - wasm_util::get_local(&mut builder.instruction_body, &address_local); + builder.instruction_body.get_local(&address_local); // Pseudo: base_on_stack = (uint32_t)address >> 12; - wasm_util::push_i32(&mut builder.instruction_body, 12); - wasm_util::shr_u32(&mut builder.instruction_body); + builder.instruction_body.push_i32(12); + builder.instruction_body.shr_u32(); // scale index - wasm_util::push_i32(&mut builder.instruction_body, 2); - wasm_util::shl_i32(&mut builder.instruction_body); + builder.instruction_body.push_i32(2); + builder.instruction_body.shl_i32(); // Pseudo: entry = tlb_data[base_on_stack]; - wasm_util::load_aligned_i32_from_stack( - &mut builder.instruction_body, - global_pointers::TLB_DATA, - ); + builder + .instruction_body + .load_aligned_i32_from_stack(global_pointers::TLB_DATA); let entry_local = wasm_util::tee_new_local(builder); // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && // (address & 0xFFF) <= (0x1000 - 4)); - wasm_util::push_i32( - &mut builder.instruction_body, - (0xFFF & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32, - ); - wasm_util::and_i32(&mut builder.instruction_body); + builder + .instruction_body + .push_i32((0xFFF & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32); + builder.instruction_body.and_i32(); - wasm_util::push_i32(&mut builder.instruction_body, TLB_VALID as i32); - wasm_util::eq_i32(&mut builder.instruction_body); + builder.instruction_body.push_i32(TLB_VALID as i32); + builder.instruction_body.eq_i32(); - wasm_util::get_local(&mut builder.instruction_body, &address_local); - wasm_util::push_i32(&mut builder.instruction_body, 0xFFF); - wasm_util::and_i32(&mut builder.instruction_body); - wasm_util::push_i32(&mut builder.instruction_body, 0x1000 - 4); - wasm_util::le_i32(&mut builder.instruction_body); + builder.instruction_body.get_local(&address_local); + builder.instruction_body.push_i32(0xFFF); + builder.instruction_body.and_i32(); + builder.instruction_body.push_i32(0x1000 - 4); + builder.instruction_body.le_i32(); - wasm_util::and_i32(&mut builder.instruction_body); + builder.instruction_body.and_i32(); // Pseudo: // if(can_use_fast_path) // { // phys_addr = entry & ~0xFFF ^ address; - wasm_util::if_void(&mut builder.instruction_body); + builder.instruction_body.if_void(); - wasm_util::get_local(&mut builder.instruction_body, &entry_local); - wasm_util::push_i32(&mut builder.instruction_body, !0xFFF); - wasm_util::and_i32(&mut builder.instruction_body); - wasm_util::get_local(&mut builder.instruction_body, &address_local); - wasm_util::xor_i32(&mut builder.instruction_body); + builder.instruction_body.get_local(&entry_local); + builder.instruction_body.push_i32(!0xFFF); + builder.instruction_body.and_i32(); + builder.instruction_body.get_local(&address_local); + builder.instruction_body.xor_i32(); builder.free_local(entry_local); @@ -315,16 +302,18 @@ pub fn gen_safe_write32(ctx: &mut JitContext, address_local: &WasmLocal, value_l // /* continued within can_use_fast_path branch */ // mem8[phys_addr] = value; - wasm_util::get_local(&mut builder.instruction_body, &value_local); - wasm_util::store_unaligned_i32(&mut builder.instruction_body, global_pointers::MEMORY); + builder.instruction_body.get_local(&value_local); + builder + .instruction_body + .store_unaligned_i32(global_pointers::MEMORY); // Pseudo: // else { safe_read32_slow(address, value); } - wasm_util::else_(&mut builder.instruction_body); - wasm_util::get_local(&mut builder.instruction_body, &address_local); - wasm_util::get_local(&mut builder.instruction_body, &value_local); + builder.instruction_body.else_(); + builder.instruction_body.get_local(&address_local); + builder.instruction_body.get_local(&value_local); gen_call_fn2(builder, "safe_write32_slow"); - wasm_util::block_end(&mut builder.instruction_body); + builder.instruction_body.block_end(); } pub fn gen_safe_read16(ctx: &mut JitContext) { @@ -335,60 +324,57 @@ pub fn gen_safe_read16(ctx: &mut JitContext) { let address_local = wasm_util::tee_new_local(builder); // Pseudo: base_on_stack = (uint32_t)address >> 12; - wasm_util::push_i32(&mut builder.instruction_body, 12); - wasm_util::shr_u32(&mut builder.instruction_body); + builder.instruction_body.push_i32(12); + builder.instruction_body.shr_u32(); // scale index - wasm_util::push_i32(&mut builder.instruction_body, 2); - wasm_util::shl_i32(&mut builder.instruction_body); + builder.instruction_body.push_i32(2); + builder.instruction_body.shl_i32(); // Pseudo: entry = tlb_data[base_on_stack]; - wasm_util::load_aligned_i32_from_stack( - &mut builder.instruction_body, - global_pointers::TLB_DATA, - ); + builder + .instruction_body + .load_aligned_i32_from_stack(global_pointers::TLB_DATA); let entry_local = wasm_util::tee_new_local(builder); // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && // (address & 0xFFF) <= (0x1000 - 2)); - wasm_util::push_i32( - &mut builder.instruction_body, + builder.instruction_body.push_i32( (0xFFF & !TLB_READONLY & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32, ); - wasm_util::and_i32(&mut builder.instruction_body); + builder.instruction_body.and_i32(); - wasm_util::push_i32(&mut builder.instruction_body, TLB_VALID as i32); - wasm_util::eq_i32(&mut builder.instruction_body); + builder.instruction_body.push_i32(TLB_VALID as i32); + builder.instruction_body.eq_i32(); - wasm_util::get_local(&mut builder.instruction_body, &address_local); - wasm_util::push_i32(&mut builder.instruction_body, 0xFFF); - wasm_util::and_i32(&mut builder.instruction_body); - wasm_util::push_i32(&mut builder.instruction_body, 0x1000 - 2); - wasm_util::le_i32(&mut builder.instruction_body); + builder.instruction_body.get_local(&address_local); + builder.instruction_body.push_i32(0xFFF); + builder.instruction_body.and_i32(); + builder.instruction_body.push_i32(0x1000 - 2); + builder.instruction_body.le_i32(); - wasm_util::and_i32(&mut builder.instruction_body); + builder.instruction_body.and_i32(); // Pseudo: // if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]); - wasm_util::if_i32(&mut builder.instruction_body); - wasm_util::get_local(&mut builder.instruction_body, &entry_local); - wasm_util::push_i32(&mut builder.instruction_body, !0xFFF); - wasm_util::and_i32(&mut builder.instruction_body); - wasm_util::get_local(&mut builder.instruction_body, &address_local); - wasm_util::xor_i32(&mut builder.instruction_body); + builder.instruction_body.if_i32(); + builder.instruction_body.get_local(&entry_local); + builder.instruction_body.push_i32(!0xFFF); + builder.instruction_body.and_i32(); + builder.instruction_body.get_local(&address_local); + builder.instruction_body.xor_i32(); - wasm_util::load_unaligned_u16_from_stack( - &mut builder.instruction_body, - global_pointers::MEMORY, - ); + builder + .instruction_body + .load_unaligned_u16_from_stack(global_pointers::MEMORY); // Pseudo: // else { leave_on_stack(safe_read16_slow(address)); } - wasm_util::else_(&mut builder.instruction_body); - wasm_util::get_local(&mut builder.instruction_body, &address_local); + builder.instruction_body.else_(); + builder.instruction_body.get_local(&address_local); gen_call_fn1_ret(builder, "safe_read16_slow"); - wasm_util::block_end(&mut builder.instruction_body); + builder.instruction_body.block_end(); builder.free_local(address_local); builder.free_local(entry_local); @@ -401,53 +387,51 @@ pub fn gen_safe_write16(ctx: &mut JitContext, address_local: &WasmLocal, value_l //let instruction_body = &mut ctx.builder.instruction_body; //let cpu = &mut ctx.cpu; - wasm_util::get_local(&mut builder.instruction_body, &address_local); + builder.instruction_body.get_local(&address_local); // Pseudo: base_on_stack = (uint32_t)address >> 12; - wasm_util::push_i32(&mut builder.instruction_body, 12); - wasm_util::shr_u32(&mut builder.instruction_body); + builder.instruction_body.push_i32(12); + builder.instruction_body.shr_u32(); // scale index - wasm_util::push_i32(&mut builder.instruction_body, 2); - wasm_util::shl_i32(&mut builder.instruction_body); + builder.instruction_body.push_i32(2); + builder.instruction_body.shl_i32(); // Pseudo: entry = tlb_data[base_on_stack]; - wasm_util::load_aligned_i32_from_stack( - &mut builder.instruction_body, - global_pointers::TLB_DATA, - ); + builder + .instruction_body + .load_aligned_i32_from_stack(global_pointers::TLB_DATA); let entry_local = wasm_util::tee_new_local(builder); // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && // (address & 0xFFF) <= (0x1000 - 2)); - wasm_util::push_i32( - &mut builder.instruction_body, - (0xFFF & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32, - ); - wasm_util::and_i32(&mut builder.instruction_body); + builder + .instruction_body + .push_i32((0xFFF & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32); + builder.instruction_body.and_i32(); - wasm_util::push_i32(&mut builder.instruction_body, TLB_VALID as i32); - wasm_util::eq_i32(&mut builder.instruction_body); + builder.instruction_body.push_i32(TLB_VALID as i32); + builder.instruction_body.eq_i32(); - wasm_util::get_local(&mut builder.instruction_body, &address_local); - wasm_util::push_i32(&mut builder.instruction_body, 0xFFF); - wasm_util::and_i32(&mut builder.instruction_body); - wasm_util::push_i32(&mut builder.instruction_body, 0x1000 - 2); - wasm_util::le_i32(&mut builder.instruction_body); + builder.instruction_body.get_local(&address_local); + builder.instruction_body.push_i32(0xFFF); + builder.instruction_body.and_i32(); + builder.instruction_body.push_i32(0x1000 - 2); + builder.instruction_body.le_i32(); - wasm_util::and_i32(&mut builder.instruction_body); + builder.instruction_body.and_i32(); // Pseudo: // if(can_use_fast_path) // { // phys_addr = entry & ~0xFFF ^ address; - wasm_util::if_void(&mut builder.instruction_body); + builder.instruction_body.if_void(); - wasm_util::get_local(&mut builder.instruction_body, &entry_local); - wasm_util::push_i32(&mut builder.instruction_body, !0xFFF); - wasm_util::and_i32(&mut builder.instruction_body); - wasm_util::get_local(&mut builder.instruction_body, &address_local); - wasm_util::xor_i32(&mut builder.instruction_body); + builder.instruction_body.get_local(&entry_local); + builder.instruction_body.push_i32(!0xFFF); + builder.instruction_body.and_i32(); + builder.instruction_body.get_local(&address_local); + builder.instruction_body.xor_i32(); builder.free_local(entry_local); @@ -455,59 +439,61 @@ pub fn gen_safe_write16(ctx: &mut JitContext, address_local: &WasmLocal, value_l // /* continued within can_use_fast_path branch */ // mem8[phys_addr] = value; - wasm_util::get_local(&mut builder.instruction_body, &value_local); - wasm_util::store_unaligned_u16(&mut builder.instruction_body, global_pointers::MEMORY); + builder.instruction_body.get_local(&value_local); + builder + .instruction_body + .store_unaligned_u16(global_pointers::MEMORY); // Pseudo: // else { safe_write16_slow(address, value); } - wasm_util::else_(&mut builder.instruction_body); - wasm_util::get_local(&mut builder.instruction_body, &address_local); - wasm_util::get_local(&mut builder.instruction_body, &value_local); + builder.instruction_body.else_(); + builder.instruction_body.get_local(&address_local); + builder.instruction_body.get_local(&value_local); gen_call_fn2(builder, "safe_write16_slow"); - wasm_util::block_end(&mut builder.instruction_body); + builder.instruction_body.block_end(); } pub fn gen_fn1_reg16(ctx: &mut JitContext, name: &str, r: u32) { let fn_idx = ctx.builder.get_fn_idx(name, module_init::FN1_TYPE_INDEX); - wasm_util::load_aligned_u16( - &mut ctx.builder.instruction_body, - global_pointers::get_reg16_offset(r), - ); - wasm_util::call_fn(&mut ctx.builder.instruction_body, fn_idx) + ctx.builder + .instruction_body + .load_aligned_u16(global_pointers::get_reg16_offset(r)); + ctx.builder.instruction_body.call_fn(fn_idx) } pub fn gen_fn1_reg32(ctx: &mut JitContext, name: &str, r: u32) { let fn_idx = ctx.builder.get_fn_idx(name, module_init::FN1_TYPE_INDEX); - wasm_util::load_aligned_i32( - &mut ctx.builder.instruction_body, - global_pointers::get_reg32_offset(r), - ); - wasm_util::call_fn(&mut ctx.builder.instruction_body, fn_idx) + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_reg32_offset(r)); + ctx.builder.instruction_body.call_fn(fn_idx) } pub fn gen_clear_prefixes(ctx: &mut JitContext) { let instruction_body = &mut ctx.builder.instruction_body; - wasm_util::push_i32(instruction_body, global_pointers::PREFIXES as i32); // load address of prefixes - wasm_util::push_i32(instruction_body, 0); - wasm_util::store_aligned_i32(instruction_body); + instruction_body.push_i32(global_pointers::PREFIXES as i32); // load address of prefixes + instruction_body.push_i32(0); + instruction_body.store_aligned_i32(); } pub fn gen_add_prefix_bits(ctx: &mut JitContext, mask: u32) { dbg_assert!(mask < 0x100); let instruction_body = &mut ctx.builder.instruction_body; - wasm_util::push_i32(instruction_body, global_pointers::PREFIXES as i32); // load address of prefixes + instruction_body.push_i32(global_pointers::PREFIXES as i32); // load address of prefixes - wasm_util::load_aligned_i32(instruction_body, global_pointers::PREFIXES); // load old value - wasm_util::push_i32(instruction_body, mask as i32); - wasm_util::or_i32(instruction_body); + instruction_body.load_aligned_i32(global_pointers::PREFIXES); // load old value + instruction_body.push_i32(mask as i32); + instruction_body.or_i32(); - wasm_util::store_aligned_i32(instruction_body); + instruction_body.store_aligned_i32(); } pub fn gen_jmp_rel16(ctx: &mut JitContext, rel16: u16) { let cs_offset_addr = global_pointers::get_seg_offset(regs::CS); - wasm_util::load_aligned_i32(&mut ctx.builder.instruction_body, cs_offset_addr); + ctx.builder + .instruction_body + .load_aligned_i32(cs_offset_addr); let local = wasm_util::set_new_local(ctx.builder); // generate: @@ -515,57 +501,51 @@ pub fn gen_jmp_rel16(ctx: &mut JitContext, rel16: u16) { { let instruction_body = &mut ctx.builder.instruction_body; - wasm_util::push_i32( - instruction_body, - global_pointers::INSTRUCTION_POINTER as i32, - ); + instruction_body.push_i32(global_pointers::INSTRUCTION_POINTER as i32); - wasm_util::load_aligned_i32(instruction_body, global_pointers::INSTRUCTION_POINTER); - wasm_util::get_local(instruction_body, &local); - wasm_util::sub_i32(instruction_body); + instruction_body.load_aligned_i32(global_pointers::INSTRUCTION_POINTER); + instruction_body.get_local(&local); + instruction_body.sub_i32(); - wasm_util::push_i32(instruction_body, rel16 as i32); - wasm_util::add_i32(instruction_body); + instruction_body.push_i32(rel16 as i32); + instruction_body.add_i32(); - wasm_util::push_i32(instruction_body, 0xFFFF); - wasm_util::and_i32(instruction_body); + instruction_body.push_i32(0xFFFF); + instruction_body.and_i32(); - wasm_util::get_local(instruction_body, &local); - wasm_util::add_i32(instruction_body); + instruction_body.get_local(&local); + instruction_body.add_i32(); - wasm_util::store_aligned_i32(instruction_body); + instruction_body.store_aligned_i32(); } ctx.builder.free_local(local); } pub fn gen_pop16_ss16(ctx: &mut JitContext) { // sp = segment_offsets[SS] + reg16[SP] (or just reg16[SP] if has_flat_segmentation) - wasm_util::load_aligned_i32( - &mut ctx.builder.instruction_body, - global_pointers::get_reg16_offset(regs::SP), - ); + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_reg16_offset(regs::SP)); let sp_local = wasm_util::tee_new_local(ctx.builder); if !ctx.cpu.has_flat_segmentation() { - wasm_util::load_aligned_i32( - &mut ctx.builder.instruction_body, - global_pointers::get_seg_offset(regs::SS), - ); - wasm_util::add_i32(&mut ctx.builder.instruction_body); + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_seg_offset(regs::SS)); + ctx.builder.instruction_body.add_i32(); } // result = safe_read16(sp) gen_safe_read16(ctx); // reg16[SP] += 2; - wasm_util::push_i32( - &mut ctx.builder.instruction_body, - global_pointers::get_reg16_offset(regs::SP) as i32, - ); - wasm_util::get_local(&mut ctx.builder.instruction_body, &sp_local); - wasm_util::push_i32(&mut ctx.builder.instruction_body, 2); - wasm_util::add_i32(&mut ctx.builder.instruction_body); - wasm_util::store_aligned_i32(&mut ctx.builder.instruction_body); + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg16_offset(regs::SP) as i32); + ctx.builder.instruction_body.get_local(&sp_local); + ctx.builder.instruction_body.push_i32(2); + ctx.builder.instruction_body.add_i32(); + ctx.builder.instruction_body.store_aligned_i32(); ctx.builder.free_local(sp_local); @@ -574,32 +554,29 @@ pub fn gen_pop16_ss16(ctx: &mut JitContext) { pub fn gen_pop16_ss32(ctx: &mut JitContext) { // esp = segment_offsets[SS] + reg32s[ESP] (or just reg32s[ESP] if has_flat_segmentation) - wasm_util::load_aligned_i32( - &mut ctx.builder.instruction_body, - global_pointers::get_reg32_offset(regs::ESP), - ); + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_reg32_offset(regs::ESP)); let esp_local = wasm_util::tee_new_local(ctx.builder); if !ctx.cpu.has_flat_segmentation() { - wasm_util::load_aligned_i32( - &mut ctx.builder.instruction_body, - global_pointers::get_seg_offset(regs::SS), - ); - wasm_util::add_i32(&mut ctx.builder.instruction_body); + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_seg_offset(regs::SS)); + ctx.builder.instruction_body.add_i32(); } // result = safe_read16(esp) gen_safe_read16(ctx); // reg32s[ESP] += 2; - wasm_util::push_i32( - &mut ctx.builder.instruction_body, - global_pointers::get_reg32_offset(regs::ESP) as i32, - ); - wasm_util::get_local(&mut ctx.builder.instruction_body, &esp_local); - wasm_util::push_i32(&mut ctx.builder.instruction_body, 2); - wasm_util::add_i32(&mut ctx.builder.instruction_body); - wasm_util::store_aligned_i32(&mut ctx.builder.instruction_body); + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg32_offset(regs::ESP) as i32); + ctx.builder.instruction_body.get_local(&esp_local); + ctx.builder.instruction_body.push_i32(2); + ctx.builder.instruction_body.add_i32(); + ctx.builder.instruction_body.store_aligned_i32(); ctx.builder.free_local(esp_local); // return value is already on stack @@ -616,32 +593,29 @@ pub fn gen_pop16(ctx: &mut JitContext) { pub fn gen_pop32s_ss16(ctx: &mut JitContext) { // sp = reg16[SP] - wasm_util::load_aligned_i32( - &mut ctx.builder.instruction_body, - global_pointers::get_reg16_offset(regs::SP), - ); + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_reg16_offset(regs::SP)); let local_sp = wasm_util::tee_new_local(ctx.builder); // result = safe_read32s(segment_offsets[SS] + sp) (or just sp if has_flat_segmentation) if !ctx.cpu.has_flat_segmentation() { - wasm_util::load_aligned_i32( - &mut ctx.builder.instruction_body, - global_pointers::get_seg_offset(regs::SS), - ); - wasm_util::add_i32(&mut ctx.builder.instruction_body); + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_seg_offset(regs::SS)); + ctx.builder.instruction_body.add_i32(); } gen_safe_read32(ctx); // reg16[SP] = sp + 4; - wasm_util::push_i32( - &mut ctx.builder.instruction_body, - global_pointers::get_reg16_offset(regs::SP) as i32, - ); - wasm_util::get_local(&mut ctx.builder.instruction_body, &local_sp); - wasm_util::push_i32(&mut ctx.builder.instruction_body, 4); - wasm_util::add_i32(&mut ctx.builder.instruction_body); - wasm_util::store_aligned_i32(&mut ctx.builder.instruction_body); + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg16_offset(regs::SP) as i32); + ctx.builder.instruction_body.get_local(&local_sp); + ctx.builder.instruction_body.push_i32(4); + ctx.builder.instruction_body.add_i32(); + ctx.builder.instruction_body.store_aligned_i32(); ctx.builder.free_local(local_sp); @@ -650,31 +624,28 @@ pub fn gen_pop32s_ss16(ctx: &mut JitContext) { pub fn gen_pop32s_ss32(ctx: &mut JitContext) { // esp = reg32s[ESP] - wasm_util::load_aligned_i32( - &mut ctx.builder.instruction_body, - global_pointers::get_reg32_offset(regs::ESP), - ); + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_reg32_offset(regs::ESP)); let local_esp = wasm_util::tee_new_local(ctx.builder); // result = safe_read32s(segment_offsets[SS] + esp) (or just esp if has_flat_segmentation) if !ctx.cpu.has_flat_segmentation() { - wasm_util::load_aligned_i32( - &mut ctx.builder.instruction_body, - global_pointers::get_seg_offset(regs::SS), - ); - wasm_util::add_i32(&mut ctx.builder.instruction_body); + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_seg_offset(regs::SS)); + ctx.builder.instruction_body.add_i32(); } gen_safe_read32(ctx); // reg32s[ESP] = esp + 4; - wasm_util::push_i32( - &mut ctx.builder.instruction_body, - global_pointers::get_reg32_offset(regs::ESP) as i32, - ); - wasm_util::get_local(&mut ctx.builder.instruction_body, &local_esp); - wasm_util::push_i32(&mut ctx.builder.instruction_body, 4); - wasm_util::add_i32(&mut ctx.builder.instruction_body); - wasm_util::store_aligned_i32(&mut ctx.builder.instruction_body); + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg32_offset(regs::ESP) as i32); + ctx.builder.instruction_body.get_local(&local_esp); + ctx.builder.instruction_body.push_i32(4); + ctx.builder.instruction_body.add_i32(); + ctx.builder.instruction_body.store_aligned_i32(); ctx.builder.free_local(local_esp); @@ -695,36 +666,34 @@ pub fn gen_task_switch_test(ctx: &mut JitContext) { let cr0_offset = global_pointers::get_creg_offset(0); - wasm_util::load_aligned_i32(&mut ctx.builder.instruction_body, cr0_offset); - wasm_util::push_i32( - &mut ctx.builder.instruction_body, - (regs::CR0_EM | regs::CR0_TS) as i32, - ); - wasm_util::and_i32(&mut ctx.builder.instruction_body); + ctx.builder.instruction_body.load_aligned_i32(cr0_offset); + ctx.builder + .instruction_body + .push_i32((regs::CR0_EM | regs::CR0_TS) as i32); + ctx.builder.instruction_body.and_i32(); - wasm_util::if_void(&mut ctx.builder.instruction_body); + ctx.builder.instruction_body.if_void(); gen_fn0_const(ctx, "task_switch_test_void"); - wasm_util::return_(&mut ctx.builder.instruction_body); + ctx.builder.instruction_body.return_(); - wasm_util::block_end(&mut ctx.builder.instruction_body); + ctx.builder.instruction_body.block_end(); } pub fn gen_task_switch_test_mmx(ctx: &mut JitContext) { // generate if(cr[0] & (CR0_EM | CR0_TS)) { task_switch_test_mmx_void(); return; } let cr0_offset = global_pointers::get_creg_offset(0); - wasm_util::load_aligned_i32(&mut ctx.builder.instruction_body, cr0_offset); - wasm_util::push_i32( - &mut ctx.builder.instruction_body, - (regs::CR0_EM | regs::CR0_TS) as i32, - ); - wasm_util::and_i32(&mut ctx.builder.instruction_body); + ctx.builder.instruction_body.load_aligned_i32(cr0_offset); + ctx.builder + .instruction_body + .push_i32((regs::CR0_EM | regs::CR0_TS) as i32); + ctx.builder.instruction_body.and_i32(); - wasm_util::if_void(&mut ctx.builder.instruction_body); + ctx.builder.instruction_body.if_void(); gen_fn0_const(ctx, "task_switch_test_mmx_void"); - wasm_util::return_(&mut ctx.builder.instruction_body); + ctx.builder.instruction_body.return_(); - wasm_util::block_end(&mut ctx.builder.instruction_body); + ctx.builder.instruction_body.block_end(); } diff --git a/src/rust/jit.rs b/src/rust/jit.rs index ca712d66..c4cd0450 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -11,6 +11,7 @@ use profiler::stat; use state_flags::CachedStateFlags; use util::SafeToU16; use wasmgen::module_init::WasmBuilder; +use wasmgen::wasm_util::WasmBuf; use wasmgen::{module_init, wasm_util}; pub const WASM_TABLE_SIZE: u32 = 0x10000; @@ -869,23 +870,21 @@ fn jit_generate_module( .collect(); // set state local variable to the initial state passed as the first argument - wasm_util::get_local( - &mut builder.instruction_body, - &builder.arg_local_initial_state, - ); + builder + .instruction_body + .get_local(&builder.arg_local_initial_state); let gen_local_state = wasm_util::set_new_local(builder); // initialise max_iterations if JIT_ALWAYS_USE_LOOP_SAFETY || requires_loop_limit { - wasm_util::push_i32( - &mut builder.instruction_body, - JIT_MAX_ITERATIONS_PER_FUNCTION as i32, - ); + builder + .instruction_body + .push_i32(JIT_MAX_ITERATIONS_PER_FUNCTION as i32); gen_local_iteration_counter = Some(wasm_util::set_new_local(builder)); } // main state machine loop - wasm_util::loop_void(&mut builder.instruction_body); + builder.instruction_body.loop_void(); if JIT_ALWAYS_USE_LOOP_SAFETY || requires_loop_limit { profiler::stat_increment(stat::S_COMPILE_WITH_LOOP_SAFETY); @@ -894,34 +893,42 @@ fn jit_generate_module( .expect("iteration counter"); // decrement max_iterations - wasm_util::get_local(&mut builder.instruction_body, gen_local_iteration_counter); - wasm_util::push_i32(&mut builder.instruction_body, -1); - wasm_util::add_i32(&mut builder.instruction_body); - wasm_util::set_local(&mut builder.instruction_body, gen_local_iteration_counter); + builder + .instruction_body + .get_local(gen_local_iteration_counter); + builder.instruction_body.push_i32(-1); + builder.instruction_body.add_i32(); + builder + .instruction_body + .set_local(gen_local_iteration_counter); // if max_iterations == 0: return - wasm_util::get_local(&mut builder.instruction_body, gen_local_iteration_counter); - wasm_util::eqz_i32(&mut builder.instruction_body); - wasm_util::if_void(&mut builder.instruction_body); - wasm_util::return_(&mut builder.instruction_body); - wasm_util::block_end(&mut builder.instruction_body); + builder + .instruction_body + .get_local(gen_local_iteration_counter); + builder.instruction_body.eqz_i32(); + builder.instruction_body.if_void(); + builder.instruction_body.return_(); + builder.instruction_body.block_end(); } - wasm_util::block_void(&mut builder.instruction_body); // for the default case + builder.instruction_body.block_void(); // for the default case // generate the opening blocks for the cases for _ in 0..basic_blocks.len() { - wasm_util::block_void(&mut builder.instruction_body); + builder.instruction_body.block_void(); } - wasm_util::get_local(&mut builder.instruction_body, &gen_local_state); - wasm_util::brtable_and_cases(&mut builder.instruction_body, basic_blocks.len() as u32); + builder.instruction_body.get_local(&gen_local_state); + builder + .instruction_body + .brtable_and_cases(basic_blocks.len() as u32); for (i, block) in basic_blocks.iter().enumerate() { // Case [i] will jump after the [i]th block, so we first generate the // block end opcode and then the code for that block - wasm_util::block_end(&mut builder.instruction_body); + builder.instruction_body.block_end(); if block.addr == block.end_addr { // Empty basic block, generate no code (for example, jump to block @@ -939,7 +946,7 @@ fn jit_generate_module( match (&block.ty, invalid_connection_to_next_block) { (_, true) | (BasicBlockType::Exit, _) => { // Exit this function - wasm_util::return_(&mut builder.instruction_body); + builder.instruction_body.return_(); }, (BasicBlockType::Normal { next_block_addr }, _) => { // Unconditional jump to next basic block @@ -950,13 +957,12 @@ fn jit_generate_module( //dbg_assert!(next_bb_index != -1); // set state variable to next basic block - wasm_util::push_i32(&mut builder.instruction_body, next_bb_index as i32); - wasm_util::set_local(&mut builder.instruction_body, &gen_local_state); + builder.instruction_body.push_i32(next_bb_index as i32); + builder.instruction_body.set_local(&gen_local_state); - wasm_util::br( - &mut builder.instruction_body, - basic_blocks.len() as u32 - i as u32, - ); // to the loop + builder + .instruction_body + .br(basic_blocks.len() as u32 - i as u32); // to the loop }, ( &BasicBlockType::ConditionalJump { @@ -976,7 +982,7 @@ fn jit_generate_module( codegen::gen_fn0_const_ret(builder, condition); - wasm_util::if_void(&mut builder.instruction_body); + builder.instruction_body.if_void(); // Branch taken @@ -997,18 +1003,17 @@ fn jit_generate_module( .get(&next_block_branch_taken_addr) .expect(""); - wasm_util::push_i32( - &mut builder.instruction_body, - next_basic_block_branch_taken_index as i32, - ); - wasm_util::set_local(&mut builder.instruction_body, &gen_local_state); + builder + .instruction_body + .push_i32(next_basic_block_branch_taken_index as i32); + builder.instruction_body.set_local(&gen_local_state); } else { // Jump to different page - wasm_util::return_(&mut builder.instruction_body); + builder.instruction_body.return_(); } - wasm_util::else_(&mut builder.instruction_body); + builder.instruction_body.else_(); { // Branch not taken @@ -1016,27 +1021,25 @@ fn jit_generate_module( let next_basic_block_index = *basic_block_indices.get(&next_block_addr).expect(""); - wasm_util::push_i32( - &mut builder.instruction_body, - next_basic_block_index as i32, - ); - wasm_util::set_local(&mut builder.instruction_body, &gen_local_state); + builder + .instruction_body + .push_i32(next_basic_block_index as i32); + builder.instruction_body.set_local(&gen_local_state); } - wasm_util::block_end(&mut builder.instruction_body); + builder.instruction_body.block_end(); - wasm_util::br( - &mut builder.instruction_body, - basic_blocks.len() as u32 - i as u32, - ); // to the loop + builder + .instruction_body + .br(basic_blocks.len() as u32 - i as u32); // to the loop }, } } - wasm_util::block_end(&mut builder.instruction_body); // default case - wasm_util::unreachable(&mut builder.instruction_body); + builder.instruction_body.block_end(); // default case + builder.instruction_body.unreachable(); - wasm_util::block_end(&mut builder.instruction_body); // loop + builder.instruction_body.block_end(); // loop builder.commit_instruction_body_to_cs(); builder.finish(); @@ -1077,7 +1080,7 @@ fn jit_generate_basic_block( if end_eip < stop_addr { let fn_idx = builder.get_fn_idx("assert_no_cpu_exception", module_init::FN0_TYPE_INDEX); - wasm_util::call_fn(&mut builder.instruction_body, fn_idx); + builder.instruction_body.call_fn(fn_idx); } } } diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 92b224ac..dae958c3 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -12,6 +12,7 @@ use regs::{CS, DS, ES, FS, GS, SS}; use regs::{EAX, EBP, EBX, ECX, EDI, EDX, ESI, ESP}; use wasmgen::module_init::WasmBuilder; use wasmgen::wasm_util; +use wasmgen::wasm_util::WasmBuf; pub fn jit_instruction(cpu: &mut CpuContext, builder: &mut WasmBuilder, instr_flags: &mut u32) { cpu.prefixes = 0; @@ -260,11 +261,10 @@ pub fn instr32_89_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = wasm_util::set_new_local(ctx.builder); - wasm_util::push_i32( - &mut ctx.builder.instruction_body, - global_pointers::get_reg32_offset(r) as i32, - ); - wasm_util::load_aligned_i32_from_stack(&mut ctx.builder.instruction_body, 0); + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg32_offset(r) as i32); + ctx.builder.instruction_body.load_aligned_i32_from_stack(0); let value_local = wasm_util::set_new_local(ctx.builder); codegen::gen_safe_write32(ctx, &address_local, &value_local); @@ -285,15 +285,14 @@ pub fn instr16_8B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { } pub fn instr32_8B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { // Pseudo: reg32s[r] = safe_read32s(modrm_resolve(modrm_byte)); - wasm_util::push_i32( - &mut ctx.builder.instruction_body, - global_pointers::get_reg32_offset(r) as i32, - ); + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg32_offset(r) as i32); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); - wasm_util::store_aligned_i32(&mut ctx.builder.instruction_body); + ctx.builder.instruction_body.store_aligned_i32(); } pub fn instr32_8B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_set_reg32_r(ctx, r2, r1); @@ -301,17 +300,17 @@ pub fn instr32_8B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { pub fn instr16_8D_mem_jit(ctx: &mut JitContext, modrm_byte: u8, reg: u32) { let loc = global_pointers::get_reg16_offset(reg); - wasm_util::push_i32(&mut ctx.builder.instruction_body, loc as i32); + ctx.builder.instruction_body.push_i32(loc as i32); ctx.cpu.prefixes |= SEG_PREFIX_ZERO; codegen::gen_modrm_resolve(ctx, modrm_byte); - wasm_util::store_aligned_u16(&mut ctx.builder.instruction_body); + ctx.builder.instruction_body.store_aligned_u16(); } pub fn instr32_8D_mem_jit(ctx: &mut JitContext, modrm_byte: u8, reg: u32) { let loc = global_pointers::get_reg32_offset(reg); - wasm_util::push_i32(&mut ctx.builder.instruction_body, loc as i32); + ctx.builder.instruction_body.push_i32(loc as i32); ctx.cpu.prefixes |= SEG_PREFIX_ZERO; codegen::gen_modrm_resolve(ctx, modrm_byte); - wasm_util::store_aligned_i32(&mut ctx.builder.instruction_body); + ctx.builder.instruction_body.store_aligned_i32(); } pub fn instr16_8D_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { @@ -354,39 +353,36 @@ pub fn instr32_E9_jit(ctx: &mut JitContext, imm: u32) { pub fn instr16_C3_jit(ctx: &mut JitContext) { let cs_addr = global_pointers::get_seg_offset(CS); - wasm_util::push_i32( - &mut ctx.builder.instruction_body, - global_pointers::INSTRUCTION_POINTER as i32, - ); + ctx.builder + .instruction_body + .push_i32(global_pointers::INSTRUCTION_POINTER as i32); - wasm_util::load_aligned_i32(&mut ctx.builder.instruction_body, cs_addr); + ctx.builder.instruction_body.load_aligned_i32(cs_addr); codegen::gen_pop16(ctx); - wasm_util::add_i32(&mut ctx.builder.instruction_body); + ctx.builder.instruction_body.add_i32(); - wasm_util::store_aligned_i32(&mut ctx.builder.instruction_body); + ctx.builder.instruction_body.store_aligned_i32(); } pub fn instr32_C3_jit(ctx: &mut JitContext) { - wasm_util::push_i32( - &mut ctx.builder.instruction_body, - global_pointers::INSTRUCTION_POINTER as i32, - ); + ctx.builder + .instruction_body + .push_i32(global_pointers::INSTRUCTION_POINTER as i32); // cs = segment_offsets[CS] - wasm_util::load_aligned_i32( - &mut ctx.builder.instruction_body, - global_pointers::get_seg_offset(CS), - ); + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_seg_offset(CS)); // ip = pop32s() codegen::gen_pop32s(ctx); // cs + ip - wasm_util::add_i32(&mut ctx.builder.instruction_body); + ctx.builder.instruction_body.add_i32(); // dbg_assert(is_asize_32() || ip < 0x10000); - wasm_util::store_aligned_i32(&mut ctx.builder.instruction_body); + ctx.builder.instruction_body.store_aligned_i32(); } pub fn instr16_EB_jit(ctx: &mut JitContext, imm8: u32) { @@ -469,19 +465,18 @@ pub fn instr_0F1F_reg_jit(_ctx: &mut JitContext, _r1: u32, _r2: u32) {} pub fn instr16_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { // reg16[r] = imm; - wasm_util::push_i32( - &mut ctx.builder.instruction_body, - global_pointers::get_reg16_offset(r) as i32, - ); - wasm_util::push_i32(&mut ctx.builder.instruction_body, imm as i32); - wasm_util::store_aligned_u16(&mut ctx.builder.instruction_body); + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg16_offset(r) as i32); + ctx.builder.instruction_body.push_i32(imm as i32); + ctx.builder.instruction_body.store_aligned_u16(); } pub fn instr16_C7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = wasm_util::set_new_local(ctx.builder); let imm = ctx.cpu.read_imm16(); - wasm_util::push_i32(&mut ctx.builder.instruction_body, imm as i32); + ctx.builder.instruction_body.push_i32(imm as i32); let value_local = wasm_util::set_new_local(ctx.builder); codegen::gen_safe_write16(ctx, &address_local, &value_local); ctx.builder.free_local(address_local); @@ -490,19 +485,18 @@ pub fn instr16_C7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { pub fn instr32_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { // reg32s[r] = imm; - wasm_util::push_i32( - &mut ctx.builder.instruction_body, - global_pointers::get_reg32_offset(r) as i32, - ); - wasm_util::push_i32(&mut ctx.builder.instruction_body, imm as i32); - wasm_util::store_aligned_i32(&mut ctx.builder.instruction_body); + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg32_offset(r) as i32); + ctx.builder.instruction_body.push_i32(imm as i32); + ctx.builder.instruction_body.store_aligned_i32(); } pub fn instr32_C7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = wasm_util::set_new_local(ctx.builder); let imm = ctx.cpu.read_imm32(); - wasm_util::push_i32(&mut ctx.builder.instruction_body, imm as i32); + ctx.builder.instruction_body.push_i32(imm as i32); let value_local = wasm_util::set_new_local(ctx.builder); codegen::gen_safe_write32(ctx, &address_local, &value_local); ctx.builder.free_local(address_local); diff --git a/src/rust/modrm.rs b/src/rust/modrm.rs index 397180fd..83f2a6cf 100644 --- a/src/rust/modrm.rs +++ b/src/rust/modrm.rs @@ -4,7 +4,7 @@ use prefix::{PREFIX_MASK_SEGMENT, SEG_PREFIX_ZERO}; use regs::{BP, BX, DI, SI}; use regs::{DS, SS}; use regs::{EAX, EBP, EBX, ECX, EDI, EDX, ESI, ESP}; -use wasmgen::wasm_util; +use wasmgen::wasm_util::WasmBuf; pub fn skip(ctx: &mut CpuContext, modrm_byte: u8) { if ctx.asize_32() { @@ -103,40 +103,39 @@ fn gen16_case(ctx: &mut JitContext, seg: u32, offset: Offset16, imm: Imm16) { match offset { Offset16::Zero => { - wasm_util::push_i32(&mut ctx.builder.instruction_body, immediate_value & 0xFFFF); + ctx.builder + .instruction_body + .push_i32(immediate_value & 0xFFFF); }, Offset16::One(r) => { - wasm_util::load_aligned_u16( - &mut ctx.builder.instruction_body, - ::global_pointers::get_reg16_offset(r), - ); + ctx.builder + .instruction_body + .load_aligned_u16(::global_pointers::get_reg16_offset(r)); if immediate_value != 0 { - wasm_util::push_i32(&mut ctx.builder.instruction_body, immediate_value); - wasm_util::add_i32(&mut ctx.builder.instruction_body); + ctx.builder.instruction_body.push_i32(immediate_value); + ctx.builder.instruction_body.add_i32(); - wasm_util::push_i32(&mut ctx.builder.instruction_body, 0xFFFF); - wasm_util::and_i32(&mut ctx.builder.instruction_body); + ctx.builder.instruction_body.push_i32(0xFFFF); + ctx.builder.instruction_body.and_i32(); } }, Offset16::Two(r1, r2) => { - wasm_util::load_aligned_u16( - &mut ctx.builder.instruction_body, - ::global_pointers::get_reg16_offset(r1), - ); - wasm_util::load_aligned_u16( - &mut ctx.builder.instruction_body, - ::global_pointers::get_reg16_offset(r2), - ); - wasm_util::add_i32(&mut ctx.builder.instruction_body); + ctx.builder + .instruction_body + .load_aligned_u16(::global_pointers::get_reg16_offset(r1)); + ctx.builder + .instruction_body + .load_aligned_u16(::global_pointers::get_reg16_offset(r2)); + ctx.builder.instruction_body.add_i32(); if immediate_value != 0 { - wasm_util::push_i32(&mut ctx.builder.instruction_body, immediate_value); - wasm_util::add_i32(&mut ctx.builder.instruction_body); + ctx.builder.instruction_body.push_i32(immediate_value); + ctx.builder.instruction_body.add_i32(); } - wasm_util::push_i32(&mut ctx.builder.instruction_body, 0xFFFF); - wasm_util::and_i32(&mut ctx.builder.instruction_body); + ctx.builder.instruction_body.push_i32(0xFFFF); + ctx.builder.instruction_body.and_i32(); }, } @@ -201,8 +200,8 @@ fn gen32_case(ctx: &mut JitContext, seg: u32, offset: Offset, imm: Imm32) { }; if immediate_value != 0 { - wasm_util::push_i32(&mut ctx.builder.instruction_body, immediate_value); - wasm_util::add_i32(&mut ctx.builder.instruction_body); + ctx.builder.instruction_body.push_i32(immediate_value); + ctx.builder.instruction_body.add_i32(); } }, Offset::Reg(r) => { @@ -211,13 +210,12 @@ fn gen32_case(ctx: &mut JitContext, seg: u32, offset: Offset, imm: Imm32) { Imm32::Imm8 => ctx.cpu.read_imm8s() as i32, Imm32::Imm32 => ctx.cpu.read_imm32() as i32, }; - wasm_util::load_aligned_i32( - &mut ctx.builder.instruction_body, - ::global_pointers::get_reg32_offset(r), - ); + ctx.builder + .instruction_body + .load_aligned_i32(::global_pointers::get_reg32_offset(r)); if immediate_value != 0 { - wasm_util::push_i32(&mut ctx.builder.instruction_body, immediate_value); - wasm_util::add_i32(&mut ctx.builder.instruction_body); + ctx.builder.instruction_body.push_i32(immediate_value); + ctx.builder.instruction_body.add_i32(); } jit_add_seg_offset(ctx, seg); }, @@ -227,7 +225,7 @@ fn gen32_case(ctx: &mut JitContext, seg: u32, offset: Offset, imm: Imm32) { Imm32::Imm8 => ctx.cpu.read_imm8s() as i32, Imm32::Imm32 => ctx.cpu.read_imm32() as i32, }; - wasm_util::push_i32(&mut ctx.builder.instruction_body, immediate_value); + ctx.builder.instruction_body.push_i32(immediate_value); jit_add_seg_offset(ctx, seg); }, } @@ -279,24 +277,24 @@ fn gen_sib(ctx: &mut JitContext, mod_is_nonzero: bool) { if r == 4 { seg = SS; let base_addr = ::global_pointers::get_reg32_offset(ESP); - wasm_util::load_aligned_i32(&mut ctx.builder.instruction_body, base_addr); + ctx.builder.instruction_body.load_aligned_i32(base_addr); } else if r == 5 { if mod_is_nonzero { seg = SS; let base_addr = ::global_pointers::get_reg32_offset(EBP); - wasm_util::load_aligned_i32(&mut ctx.builder.instruction_body, base_addr); + ctx.builder.instruction_body.load_aligned_i32(base_addr); } else { seg = DS; let base = ctx.cpu.read_imm32(); - wasm_util::push_i32(&mut ctx.builder.instruction_body, base as i32); + ctx.builder.instruction_body.push_i32(base as i32); } } else { seg = DS; let base_addr = ::global_pointers::get_reg32_offset(r as u32); - wasm_util::load_aligned_i32(&mut ctx.builder.instruction_body, base_addr); + ctx.builder.instruction_body.load_aligned_i32(base_addr); } jit_add_seg_offset(ctx, seg); @@ -312,14 +310,13 @@ fn gen_sib(ctx: &mut JitContext, mod_is_nonzero: bool) { let s = sib_byte >> 6 & 3; - wasm_util::load_aligned_i32( - &mut ctx.builder.instruction_body, - ::global_pointers::get_reg32_offset(m as u32), - ); - wasm_util::push_i32(&mut ctx.builder.instruction_body, s as i32); - wasm_util::shl_i32(&mut ctx.builder.instruction_body); + ctx.builder + .instruction_body + .load_aligned_i32(::global_pointers::get_reg32_offset(m as u32)); + ctx.builder.instruction_body.push_i32(s as i32); + ctx.builder.instruction_body.shl_i32(); - wasm_util::add_i32(&mut ctx.builder.instruction_body); + ctx.builder.instruction_body.add_i32(); } fn can_optimize_get_seg(ctx: &mut JitContext, segment: u32) -> bool { @@ -339,7 +336,7 @@ fn jit_add_seg_offset(ctx: &mut JitContext, default_segment: u32) { return; } - wasm_util::push_i32(&mut ctx.builder.instruction_body, seg as i32); - wasm_util::call_fn(&mut ctx.builder.instruction_body, ::jit::FN_GET_SEG_IDX); - wasm_util::add_i32(&mut ctx.builder.instruction_body); + ctx.builder.instruction_body.push_i32(seg as i32); + ctx.builder.instruction_body.call_fn(::jit::FN_GET_SEG_IDX); + ctx.builder.instruction_body.add_i32(); } diff --git a/src/rust/wasmgen/module_init.rs b/src/rust/wasmgen/module_init.rs index 3db5aab4..82562a63 100644 --- a/src/rust/wasmgen/module_init.rs +++ b/src/rust/wasmgen/module_init.rs @@ -1,6 +1,6 @@ -use leb::{write_fixed_leb16_at_idx, write_fixed_leb32_at_idx, write_leb_u32}; use util::{SafeToU16, SafeToU8}; use wasmgen::wasm_opcodes as op; +use wasmgen::wasm_util::WasmBuf; #[allow(dead_code)] pub const FN0_TYPE_INDEX: u8 = 0; @@ -127,10 +127,12 @@ impl WasmBuilder { // write the actual sizes to the pointer locations stored above. We subtract 4 from the actual // value because the ptr itself points to four bytes let fn_body_size = (self.output.len() - idx_fn_body_size - 4) as u32; - write_fixed_leb32_at_idx(&mut self.output, idx_fn_body_size, fn_body_size); + self.output + .write_fixed_leb32_at_idx(idx_fn_body_size, fn_body_size); let code_section_size = (self.output.len() - idx_code_section_size - 4) as u32; - write_fixed_leb32_at_idx(&mut self.output, idx_code_section_size, code_section_size); + self.output + .write_fixed_leb32_at_idx(idx_code_section_size, code_section_size); self.output.len() } @@ -221,14 +223,16 @@ impl WasmBuilder { dbg_assert!(count < 0x4000); self.import_count = count; let idx_import_count = self.idx_import_count; - write_fixed_leb16_at_idx(&mut self.output, idx_import_count, count); + self.output + .write_fixed_leb16_at_idx(idx_import_count, count); } pub fn set_import_table_size(&mut self, size: usize) { dbg_assert!(size < 0x4000); self.import_table_size = size; let idx_import_table_size = self.idx_import_table_size; - write_fixed_leb16_at_idx(&mut self.output, idx_import_table_size, size.safe_to_u16()); + self.output + .write_fixed_leb16_at_idx(idx_import_table_size, size.safe_to_u16()); } pub fn write_import_section_preamble(&mut self) { @@ -255,7 +259,7 @@ impl WasmBuilder { self.output.push(op::EXT_MEMORY); self.output.push(0); // memory flag, 0 for no maximum memory limit present - write_leb_u32(&mut self.output, 256); // initial memory length of 256 pages, takes 2 bytes in leb128 + self.output.write_leb_u32(256); // initial memory length of 256 pages, takes 2 bytes in leb128 let new_import_count = self.import_count + 1; self.set_import_count(new_import_count); @@ -303,7 +307,8 @@ impl WasmBuilder { let next_op_idx = self.output.len(); self.output.push(0); self.output.push(0); // add 2 bytes for writing 16 byte val - write_fixed_leb16_at_idx(&mut self.output, next_op_idx, self.import_count - 1); + self.output + .write_fixed_leb16_at_idx(next_op_idx, self.import_count - 1); } pub fn get_fn_idx(&mut self, fn_name: &str, type_index: u8) -> u16 { @@ -352,7 +357,6 @@ mod tests { use std::fs::File; use std::io::prelude::*; use wasmgen::module_init::*; - use wasmgen::wasm_util::*; #[test] fn import_table_management() { @@ -370,31 +374,31 @@ mod tests { m.init(); let mut foo_index = m.get_fn_idx("foo", FN0_TYPE_INDEX); - call_fn(&mut m.code_section, foo_index); + m.code_section.call_fn(foo_index); let bar_index = m.get_fn_idx("bar", FN0_TYPE_INDEX); - call_fn(&mut m.code_section, bar_index); + m.code_section.call_fn(bar_index); let _ = m._alloc_local(); // for ensuring that reset clears previous locals m.finish(); m.reset(); - push_i32(&mut m.code_section, 2); + m.code_section.push_i32(2); let baz_index = m.get_fn_idx("baz", FN1_RET_TYPE_INDEX); - call_fn(&mut m.instruction_body, baz_index); + m.instruction_body.call_fn(baz_index); foo_index = m.get_fn_idx("foo", FN1_TYPE_INDEX); - call_fn(&mut m.instruction_body, foo_index); + m.instruction_body.call_fn(foo_index); - push_i32(&mut m.code_section, 10); + m.code_section.push_i32(10); let local1 = m._alloc_local(); - tee_local(&mut m.code_section, &local1); // local1 = 10 + m.code_section.tee_local(&local1); // local1 = 10 - push_i32(&mut m.code_section, 20); - add_i32(&mut m.code_section); + m.code_section.push_i32(20); + m.code_section.add_i32(); let local2 = m._alloc_local(); - tee_local(&mut m.code_section, &local2); // local2 = 30 + m.code_section.tee_local(&local2); // local2 = 30 m.free_local(local1); @@ -404,11 +408,11 @@ mod tests { m.free_local(local2); m.free_local(local3); - push_i32(&mut m.code_section, 30); - ne_i32(&mut m.code_section); - if_void(&mut m.code_section); - unreachable(&mut m.code_section); - block_end(&mut m.code_section); + m.code_section.push_i32(30); + m.code_section.ne_i32(); + m.code_section.if_void(); + m.code_section.unreachable(); + m.code_section.block_end(); m.commit_instruction_body_to_cs(); diff --git a/src/rust/wasmgen/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs index 0c55968b..71e80dd0 100644 --- a/src/rust/wasmgen/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -1,164 +1,257 @@ -use leb::{write_fixed_leb16_at_idx, write_leb_i32, write_leb_u32}; +use leb::{write_fixed_leb16_at_idx, write_fixed_leb32_at_idx, write_leb_i32, write_leb_u32}; use wasmgen::module_init::{WasmBuilder, WasmLocal}; use wasmgen::wasm_opcodes as op; -pub fn push_i32(buf: &mut Vec, v: i32) { - buf.push(op::OP_I32CONST); - write_leb_i32(buf, v); +pub trait WasmBuf { + fn write_leb_i32(&mut self, v: i32); + fn write_leb_u32(&mut self, v: u32); + fn write_fixed_leb16_at_idx(&mut self, idx: usize, x: u16); + fn write_fixed_leb32_at_idx(&mut self, idx: usize, x: u32); + fn push_i32(&mut self, v: i32); + fn load_aligned_u16(&mut self, addr: u32); + fn load_aligned_i32(&mut self, addr: u32); + fn store_aligned_u16(&mut self); + fn store_aligned_i32(&mut self); + fn add_i32(&mut self); + fn sub_i32(&mut self); + fn and_i32(&mut self); + fn or_i32(&mut self); + fn shl_i32(&mut self); + fn call_fn(&mut self, fn_idx: u16); + fn eq_i32(&mut self); + fn ne_i32(&mut self); + fn le_i32(&mut self); + fn lt_i32(&mut self); + fn ge_i32(&mut self); + fn gt_i32(&mut self); + fn if_i32(&mut self); + fn block_i32(&mut self); + fn xor_i32(&mut self); + fn load_unaligned_i32_from_stack(&mut self, byte_offset: u32); + fn load_unaligned_u16_from_stack(&mut self, byte_offset: u32); + fn load_aligned_i32_from_stack(&mut self, byte_offset: u32); + fn store_unaligned_i32(&mut self, byte_offset: u32); + fn store_unaligned_u16(&mut self, byte_offset: u32); + fn shr_u32(&mut self); + fn shr_i32(&mut self); + fn eqz_i32(&mut self); + fn if_void(&mut self); + fn else_(&mut self); + fn loop_void(&mut self); + fn block_void(&mut self); + fn block_end(&mut self); + fn return_(&mut self); + fn drop(&mut self); + fn brtable_and_cases(&mut self, cases_count: u32); + fn br(&mut self, depth: u32); + fn get_local(&mut self, local: &WasmLocal); + fn set_local(&mut self, local: &WasmLocal); + fn tee_local(&mut self, local: &WasmLocal); + fn unreachable(&mut self); + fn increment_mem32(&mut self, addr: u32); + fn increment_variable(&mut self, addr: u32, n: i32); + fn load_aligned_u16_from_stack(&mut self, byte_offset: u32); } -pub fn load_aligned_u16(buf: &mut Vec, addr: u32) { - // doesn't cause a failure in the generated code, but it will be much slower - dbg_assert!((addr & 1) == 0); +impl WasmBuf for Vec { + fn write_leb_i32(&mut self, v: i32) { write_leb_i32(self, v) } - buf.push(op::OP_I32CONST); - write_leb_u32(buf, addr); - buf.push(op::OP_I32LOAD16U); - buf.push(op::MEM_ALIGN16); - buf.push(0); // immediate offset -} + fn write_leb_u32(&mut self, v: u32) { write_leb_u32(self, v) } -pub fn load_aligned_i32(buf: &mut Vec, addr: u32) { - // doesn't cause a failure in the generated code, but it will be much slower - dbg_assert!((addr & 3) == 0); - - push_i32(buf, addr as i32); - load_aligned_i32_from_stack(buf, 0); -} - -pub fn store_aligned_u16(buf: &mut Vec) { - buf.push(op::OP_I32STORE16); - buf.push(op::MEM_ALIGN16); - buf.push(0); // immediate offset -} - -pub fn store_aligned_i32(buf: &mut Vec) { - buf.push(op::OP_I32STORE); - buf.push(op::MEM_ALIGN32); - buf.push(0); // immediate offset -} - -pub fn add_i32(buf: &mut Vec) { buf.push(op::OP_I32ADD); } -pub fn sub_i32(buf: &mut Vec) { buf.push(op::OP_I32SUB); } - -pub fn and_i32(buf: &mut Vec) { buf.push(op::OP_I32AND); } - -pub fn or_i32(buf: &mut Vec) { buf.push(op::OP_I32OR); } - -pub fn shl_i32(buf: &mut Vec) { buf.push(op::OP_I32SHL); } - -pub fn call_fn(buf: &mut Vec, fn_idx: u16) { - buf.push(op::OP_CALL); - let buf_len = buf.len(); - buf.push(0); - buf.push(0); - write_fixed_leb16_at_idx(buf, buf_len, fn_idx); -} - -pub fn eq_i32(buf: &mut Vec) { buf.push(op::OP_I32EQ); } - -pub fn ne_i32(buf: &mut Vec) { buf.push(op::OP_I32NE); } - -pub fn le_i32(buf: &mut Vec) { buf.push(op::OP_I32LES); } - -pub fn lt_i32(buf: &mut Vec) { buf.push(op::OP_I32LTS); } - -pub fn ge_i32(buf: &mut Vec) { buf.push(op::OP_I32GES); } - -pub fn gt_i32(buf: &mut Vec) { buf.push(op::OP_I32GTS); } - -pub fn if_i32(buf: &mut Vec) { - buf.push(op::OP_IF); - buf.push(op::TYPE_I32); -} - -pub fn block_i32(buf: &mut Vec) { - buf.push(op::OP_BLOCK); - buf.push(op::TYPE_I32); -} - -pub fn xor_i32(buf: &mut Vec) { buf.push(op::OP_I32XOR); } - -pub fn load_unaligned_i32_from_stack(buf: &mut Vec, byte_offset: u32) { - buf.push(op::OP_I32LOAD); - buf.push(op::MEM_NO_ALIGN); - write_leb_u32(buf, byte_offset); -} - -pub fn load_unaligned_u16_from_stack(buf: &mut Vec, byte_offset: u32) { - buf.push(op::OP_I32LOAD16U); - buf.push(op::MEM_NO_ALIGN); - write_leb_u32(buf, byte_offset); -} - -pub fn load_aligned_i32_from_stack(buf: &mut Vec, byte_offset: u32) { - buf.push(op::OP_I32LOAD); - buf.push(op::MEM_ALIGN32); - write_leb_u32(buf, byte_offset); -} - -// XXX: Function naming should be consistent regarding both alignment and accepting an -// offset. Leaving as-is for the Rust port to cleanup -pub fn store_unaligned_i32(buf: &mut Vec, byte_offset: u32) { - buf.push(op::OP_I32STORE); - buf.push(op::MEM_NO_ALIGN); - write_leb_u32(buf, byte_offset); -} - -pub fn store_unaligned_u16(buf: &mut Vec, byte_offset: u32) { - buf.push(op::OP_I32STORE16); - buf.push(op::MEM_NO_ALIGN); - write_leb_u32(buf, byte_offset); -} - -pub fn shr_u32(buf: &mut Vec) { buf.push(op::OP_I32SHRU); } - -pub fn shr_i32(buf: &mut Vec) { buf.push(op::OP_I32SHRS); } - -pub fn eqz_i32(buf: &mut Vec) { buf.push(op::OP_I32EQZ); } - -pub fn if_void(buf: &mut Vec) { - buf.push(op::OP_IF); - buf.push(op::TYPE_VOID_BLOCK); -} - -pub fn else_(buf: &mut Vec) { buf.push(op::OP_ELSE); } - -pub fn loop_void(buf: &mut Vec) { - buf.push(op::OP_LOOP); - buf.push(op::TYPE_VOID_BLOCK); -} - -pub fn block_void(buf: &mut Vec) { - buf.push(op::OP_BLOCK); - buf.push(op::TYPE_VOID_BLOCK); -} - -pub fn block_end(buf: &mut Vec) { buf.push(op::OP_END); } - -pub fn return_(buf: &mut Vec) { buf.push(op::OP_RETURN); } - -pub fn drop(buf: &mut Vec) { buf.push(op::OP_DROP); } - -// Generate a br_table where an input of [i] will branch [i]th outer block, -// where [i] is passed on the wasm stack -pub fn brtable_and_cases(buf: &mut Vec, cases_count: u32) { - buf.push(op::OP_BRTABLE); - write_leb_u32(buf, cases_count); - - for i in 0..(cases_count + 1) { - write_leb_u32(buf, i); + fn write_fixed_leb16_at_idx(&mut self, idx: usize, x: u16) { + write_fixed_leb16_at_idx(self, idx, x) } -} -pub fn br(buf: &mut Vec, depth: u32) { - buf.push(op::OP_BR); - write_leb_u32(buf, depth); -} + fn write_fixed_leb32_at_idx(&mut self, idx: usize, x: u32) { + write_fixed_leb32_at_idx(self, idx, x) + } -pub fn get_local(buf: &mut Vec, local: &WasmLocal) { - buf.push(op::OP_GETLOCAL); - buf.push(local.idx()); + fn push_i32(&mut self, v: i32) { + self.push(op::OP_I32CONST); + self.write_leb_i32(v); + } + + fn load_aligned_u16(&mut self, addr: u32) { + // doesn't cause a failure in the generated code, but it will be much slower + dbg_assert!((addr & 1) == 0); + + self.push(op::OP_I32CONST); + self.write_leb_u32(addr); + self.push(op::OP_I32LOAD16U); + self.push(op::MEM_ALIGN16); + self.push(0); // immediate offset + } + + fn load_aligned_i32(&mut self, addr: u32) { + // doesn't cause a failure in the generated code, but it will be much slower + dbg_assert!((addr & 3) == 0); + + self.push_i32(addr as i32); + self.load_aligned_i32_from_stack(0); + } + + fn store_aligned_u16(&mut self) { + self.push(op::OP_I32STORE16); + self.push(op::MEM_ALIGN16); + self.push(0); // immediate offset + } + + fn store_aligned_i32(&mut self) { + self.push(op::OP_I32STORE); + self.push(op::MEM_ALIGN32); + self.push(0); // immediate offset + } + + fn add_i32(&mut self) { self.push(op::OP_I32ADD); } + fn sub_i32(&mut self) { self.push(op::OP_I32SUB); } + + fn and_i32(&mut self) { self.push(op::OP_I32AND); } + + fn or_i32(&mut self) { self.push(op::OP_I32OR); } + + fn shl_i32(&mut self) { self.push(op::OP_I32SHL); } + + fn call_fn(&mut self, fn_idx: u16) { + self.push(op::OP_CALL); + let buf_len = self.len(); + self.push(0); + self.push(0); + self.write_fixed_leb16_at_idx(buf_len, fn_idx); + } + + fn eq_i32(&mut self) { self.push(op::OP_I32EQ); } + + fn ne_i32(&mut self) { self.push(op::OP_I32NE); } + + fn le_i32(&mut self) { self.push(op::OP_I32LES); } + + fn lt_i32(&mut self) { self.push(op::OP_I32LTS); } + + fn ge_i32(&mut self) { self.push(op::OP_I32GES); } + + fn gt_i32(&mut self) { self.push(op::OP_I32GTS); } + + fn if_i32(&mut self) { + self.push(op::OP_IF); + self.push(op::TYPE_I32); + } + + fn block_i32(&mut self) { + self.push(op::OP_BLOCK); + self.push(op::TYPE_I32); + } + + fn xor_i32(&mut self) { self.push(op::OP_I32XOR); } + + fn load_unaligned_i32_from_stack(&mut self, byte_offset: u32) { + self.push(op::OP_I32LOAD); + self.push(op::MEM_NO_ALIGN); + self.write_leb_u32(byte_offset); + } + + fn load_unaligned_u16_from_stack(&mut self, byte_offset: u32) { + self.push(op::OP_I32LOAD16U); + self.push(op::MEM_NO_ALIGN); + self.write_leb_u32(byte_offset); + } + + fn load_aligned_i32_from_stack(&mut self, byte_offset: u32) { + self.push(op::OP_I32LOAD); + self.push(op::MEM_ALIGN32); + self.write_leb_u32(byte_offset); + } + + // XXX: Function naming should be consistent regarding both alignment and accepting an + // offset. Leaving as-is for the Rust port to cleanup + fn store_unaligned_i32(&mut self, byte_offset: u32) { + self.push(op::OP_I32STORE); + self.push(op::MEM_NO_ALIGN); + self.write_leb_u32(byte_offset); + } + + fn store_unaligned_u16(&mut self, byte_offset: u32) { + self.push(op::OP_I32STORE16); + self.push(op::MEM_NO_ALIGN); + self.write_leb_u32(byte_offset); + } + + fn shr_u32(&mut self) { self.push(op::OP_I32SHRU); } + + fn shr_i32(&mut self) { self.push(op::OP_I32SHRS); } + + fn eqz_i32(&mut self) { self.push(op::OP_I32EQZ); } + + fn if_void(&mut self) { + self.push(op::OP_IF); + self.push(op::TYPE_VOID_BLOCK); + } + + fn else_(&mut self) { self.push(op::OP_ELSE); } + + fn loop_void(&mut self) { + self.push(op::OP_LOOP); + self.push(op::TYPE_VOID_BLOCK); + } + + fn block_void(&mut self) { + self.push(op::OP_BLOCK); + self.push(op::TYPE_VOID_BLOCK); + } + + fn block_end(&mut self) { self.push(op::OP_END); } + + fn return_(&mut self) { self.push(op::OP_RETURN); } + + fn drop(&mut self) { self.push(op::OP_DROP); } + + // Generate a br_table where an input of [i] will branch [i]th outer block, + // where [i] is passed on the wasm stack + fn brtable_and_cases(&mut self, cases_count: u32) { + self.push(op::OP_BRTABLE); + self.write_leb_u32(cases_count); + + for i in 0..(cases_count + 1) { + self.write_leb_u32(i); + } + } + + fn br(&mut self, depth: u32) { + self.push(op::OP_BR); + self.write_leb_u32(depth); + } + + fn get_local(&mut self, local: &WasmLocal) { + self.push(op::OP_GETLOCAL); + self.push(local.idx()); + } + + fn set_local(&mut self, local: &WasmLocal) { + self.push(op::OP_SETLOCAL); + self.push(local.idx()); + } + + fn tee_local(&mut self, local: &WasmLocal) { + self.push(op::OP_TEELOCAL); + self.push(local.idx()); + } + + fn unreachable(&mut self) { self.push(op::OP_UNREACHABLE); } + + fn increment_mem32(&mut self, addr: u32) { self.increment_variable(addr, 1) } + + fn increment_variable(&mut self, addr: u32, n: i32) { + self.push_i32(addr as i32); + self.load_aligned_i32(addr); + self.push_i32(n); + self.add_i32(); + self.store_aligned_i32(); + } + + fn load_aligned_u16_from_stack(&mut self, byte_offset: u32) { + self.push(op::OP_I32LOAD16U); + self.push(op::MEM_ALIGN16); + self.write_leb_u32(byte_offset); + } } pub fn set_new_local(builder: &mut WasmBuilder) -> WasmLocal { @@ -174,31 +267,3 @@ pub fn tee_new_local(builder: &mut WasmBuilder) -> WasmLocal { builder.instruction_body.push(local.idx()); local } - -pub fn set_local(buf: &mut Vec, local: &WasmLocal) { - buf.push(op::OP_SETLOCAL); - buf.push(local.idx()); -} - -pub fn tee_local(buf: &mut Vec, local: &WasmLocal) { - buf.push(op::OP_TEELOCAL); - buf.push(local.idx()); -} - -pub fn unreachable(buf: &mut Vec) { buf.push(op::OP_UNREACHABLE); } - -pub fn increment_mem32(buf: &mut Vec, addr: u32) { increment_variable(buf, addr, 1) } - -pub fn increment_variable(buf: &mut Vec, addr: u32, n: i32) { - push_i32(buf, addr as i32); - load_aligned_i32(buf, addr); - push_i32(buf, n); - add_i32(buf); - store_aligned_i32(buf); -} - -pub fn load_aligned_u16_from_stack(buf: &mut Vec, byte_offset: u32) { - buf.push(op::OP_I32LOAD16U); - buf.push(op::MEM_ALIGN16); - write_leb_u32(buf, byte_offset); -} From 1835ea38448cfb7127dc116de912d8a1b6a0b4b6 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sun, 29 Jul 2018 14:43:06 +0530 Subject: [PATCH 1097/2137] refactor initialization of gen_local_iteration_counter --- src/rust/jit.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/rust/jit.rs b/src/rust/jit.rs index c4cd0450..ffd645b6 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -861,8 +861,6 @@ fn jit_generate_module( let fn_get_seg_idx = builder.get_fn_idx("get_seg", module_init::FN1_RET_TYPE_INDEX); dbg_assert!(fn_get_seg_idx == FN_GET_SEG_IDX); - let mut gen_local_iteration_counter = None; - let basic_block_indices: HashMap = basic_blocks .iter() .enumerate() @@ -876,21 +874,21 @@ fn jit_generate_module( let gen_local_state = wasm_util::set_new_local(builder); // initialise max_iterations - if JIT_ALWAYS_USE_LOOP_SAFETY || requires_loop_limit { + let gen_local_iteration_counter = if JIT_ALWAYS_USE_LOOP_SAFETY || requires_loop_limit { builder .instruction_body .push_i32(JIT_MAX_ITERATIONS_PER_FUNCTION as i32); - gen_local_iteration_counter = Some(wasm_util::set_new_local(builder)); + Some(wasm_util::set_new_local(builder)) } + else { + None + }; // main state machine loop builder.instruction_body.loop_void(); - if JIT_ALWAYS_USE_LOOP_SAFETY || requires_loop_limit { + if let Some(gen_local_iteration_counter) = gen_local_iteration_counter.as_ref() { profiler::stat_increment(stat::S_COMPILE_WITH_LOOP_SAFETY); - let gen_local_iteration_counter = gen_local_iteration_counter - .as_ref() - .expect("iteration counter"); // decrement max_iterations builder From 470246651d36c1eb3272f13574da059007534e87 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Mon, 30 Jul 2018 12:35:33 +0530 Subject: [PATCH 1098/2137] move {set,tee}_new_local to builder --- src/rust/codegen.rs | 24 ++++++++++++------------ src/rust/jit.rs | 6 +++--- src/rust/jit_instructions.rs | 13 ++++++------- src/rust/wasmgen/module_init.rs | 33 ++++++++++++++++++++++----------- src/rust/wasmgen/wasm_util.rs | 16 +--------------- 5 files changed, 44 insertions(+), 48 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 99fbded8..6a2d8ee0 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -3,9 +3,9 @@ use jit::JitContext; use modrm; use regs; use tlb::{TLB_GLOBAL, TLB_NO_USER, TLB_READONLY, TLB_VALID}; +use wasmgen::module_init; use wasmgen::module_init::{WasmBuilder, WasmLocal}; use wasmgen::wasm_util::WasmBuf; -use wasmgen::{module_init, wasm_util}; pub fn gen_set_previous_eip_offset_from_eip(builder: &mut WasmBuilder, n: u32) { let cs = &mut builder.code_section; @@ -184,7 +184,7 @@ pub fn gen_safe_read32(ctx: &mut JitContext) { //let instruction_body = &mut ctx.builder.instruction_body; //let cpu = &mut ctx.cpu; - let address_local = wasm_util::tee_new_local(builder); + let address_local = builder.tee_new_local(); // Pseudo: base_on_stack = (uint32_t)address >> 12; builder.instruction_body.push_i32(12); @@ -198,7 +198,7 @@ pub fn gen_safe_read32(ctx: &mut JitContext) { builder .instruction_body .load_aligned_i32_from_stack(global_pointers::TLB_DATA); - let entry_local = wasm_util::tee_new_local(builder); + let entry_local = builder.tee_new_local(); // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && // (address & 0xFFF) <= (0x1000 - 4)); @@ -264,7 +264,7 @@ pub fn gen_safe_write32(ctx: &mut JitContext, address_local: &WasmLocal, value_l builder .instruction_body .load_aligned_i32_from_stack(global_pointers::TLB_DATA); - let entry_local = wasm_util::tee_new_local(builder); + let entry_local = builder.tee_new_local(); // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && // (address & 0xFFF) <= (0x1000 - 4)); @@ -321,7 +321,7 @@ pub fn gen_safe_read16(ctx: &mut JitContext) { // inline, bailing to safe_read16_slow if necessary let builder = &mut ctx.builder; - let address_local = wasm_util::tee_new_local(builder); + let address_local = builder.tee_new_local(); // Pseudo: base_on_stack = (uint32_t)address >> 12; builder.instruction_body.push_i32(12); @@ -335,7 +335,7 @@ pub fn gen_safe_read16(ctx: &mut JitContext) { builder .instruction_body .load_aligned_i32_from_stack(global_pointers::TLB_DATA); - let entry_local = wasm_util::tee_new_local(builder); + let entry_local = builder.tee_new_local(); // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && // (address & 0xFFF) <= (0x1000 - 2)); @@ -401,7 +401,7 @@ pub fn gen_safe_write16(ctx: &mut JitContext, address_local: &WasmLocal, value_l builder .instruction_body .load_aligned_i32_from_stack(global_pointers::TLB_DATA); - let entry_local = wasm_util::tee_new_local(builder); + let entry_local = builder.tee_new_local(); // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && // (address & 0xFFF) <= (0x1000 - 2)); @@ -494,7 +494,7 @@ pub fn gen_jmp_rel16(ctx: &mut JitContext, rel16: u16) { ctx.builder .instruction_body .load_aligned_i32(cs_offset_addr); - let local = wasm_util::set_new_local(ctx.builder); + let local = ctx.builder.set_new_local(); // generate: // *instruction_pointer = cs_offset + ((*instruction_pointer - cs_offset + rel16) & 0xFFFF); @@ -526,7 +526,7 @@ pub fn gen_pop16_ss16(ctx: &mut JitContext) { ctx.builder .instruction_body .load_aligned_i32(global_pointers::get_reg16_offset(regs::SP)); - let sp_local = wasm_util::tee_new_local(ctx.builder); + let sp_local = ctx.builder.tee_new_local(); if !ctx.cpu.has_flat_segmentation() { ctx.builder @@ -557,7 +557,7 @@ pub fn gen_pop16_ss32(ctx: &mut JitContext) { ctx.builder .instruction_body .load_aligned_i32(global_pointers::get_reg32_offset(regs::ESP)); - let esp_local = wasm_util::tee_new_local(ctx.builder); + let esp_local = ctx.builder.tee_new_local(); if !ctx.cpu.has_flat_segmentation() { ctx.builder @@ -596,7 +596,7 @@ pub fn gen_pop32s_ss16(ctx: &mut JitContext) { ctx.builder .instruction_body .load_aligned_i32(global_pointers::get_reg16_offset(regs::SP)); - let local_sp = wasm_util::tee_new_local(ctx.builder); + let local_sp = ctx.builder.tee_new_local(); // result = safe_read32s(segment_offsets[SS] + sp) (or just sp if has_flat_segmentation) if !ctx.cpu.has_flat_segmentation() { @@ -627,7 +627,7 @@ pub fn gen_pop32s_ss32(ctx: &mut JitContext) { ctx.builder .instruction_body .load_aligned_i32(global_pointers::get_reg32_offset(regs::ESP)); - let local_esp = wasm_util::tee_new_local(ctx.builder); + let local_esp = ctx.builder.tee_new_local(); // result = safe_read32s(segment_offsets[SS] + esp) (or just esp if has_flat_segmentation) if !ctx.cpu.has_flat_segmentation() { diff --git a/src/rust/jit.rs b/src/rust/jit.rs index ffd645b6..9b150550 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -10,9 +10,9 @@ use profiler; use profiler::stat; use state_flags::CachedStateFlags; use util::SafeToU16; +use wasmgen::module_init; use wasmgen::module_init::WasmBuilder; use wasmgen::wasm_util::WasmBuf; -use wasmgen::{module_init, wasm_util}; pub const WASM_TABLE_SIZE: u32 = 0x10000; @@ -871,14 +871,14 @@ fn jit_generate_module( builder .instruction_body .get_local(&builder.arg_local_initial_state); - let gen_local_state = wasm_util::set_new_local(builder); + let gen_local_state = builder.set_new_local(); // initialise max_iterations let gen_local_iteration_counter = if JIT_ALWAYS_USE_LOOP_SAFETY || requires_loop_limit { builder .instruction_body .push_i32(JIT_MAX_ITERATIONS_PER_FUNCTION as i32); - Some(wasm_util::set_new_local(builder)) + Some(builder.set_new_local()) } else { None diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index dae958c3..4c28b698 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -11,7 +11,6 @@ use regs::{AX, BP, BX, CX, DI, DX, SI, SP}; use regs::{CS, DS, ES, FS, GS, SS}; use regs::{EAX, EBP, EBX, ECX, EDI, EDX, ESI, ESP}; use wasmgen::module_init::WasmBuilder; -use wasmgen::wasm_util; use wasmgen::wasm_util::WasmBuf; pub fn jit_instruction(cpu: &mut CpuContext, builder: &mut WasmBuilder, instr_flags: &mut u32) { @@ -259,13 +258,13 @@ pub fn instr16_89_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { pub fn instr32_89_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { // Pseudo: safe_write32(modrm_resolve(modrm_byte), reg32s[r]); codegen::gen_modrm_resolve(ctx, modrm_byte); - let address_local = wasm_util::set_new_local(ctx.builder); + let address_local = ctx.builder.set_new_local(); ctx.builder .instruction_body .push_i32(global_pointers::get_reg32_offset(r) as i32); ctx.builder.instruction_body.load_aligned_i32_from_stack(0); - let value_local = wasm_util::set_new_local(ctx.builder); + let value_local = ctx.builder.set_new_local(); codegen::gen_safe_write32(ctx, &address_local, &value_local); ctx.builder.free_local(address_local); @@ -474,10 +473,10 @@ pub fn instr16_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { pub fn instr16_C7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); - let address_local = wasm_util::set_new_local(ctx.builder); + let address_local = ctx.builder.set_new_local(); let imm = ctx.cpu.read_imm16(); ctx.builder.instruction_body.push_i32(imm as i32); - let value_local = wasm_util::set_new_local(ctx.builder); + let value_local = ctx.builder.set_new_local(); codegen::gen_safe_write16(ctx, &address_local, &value_local); ctx.builder.free_local(address_local); ctx.builder.free_local(value_local); @@ -494,10 +493,10 @@ pub fn instr32_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { pub fn instr32_C7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); - let address_local = wasm_util::set_new_local(ctx.builder); + let address_local = ctx.builder.set_new_local(); let imm = ctx.cpu.read_imm32(); ctx.builder.instruction_body.push_i32(imm as i32); - let value_local = wasm_util::set_new_local(ctx.builder); + let value_local = ctx.builder.set_new_local(); codegen::gen_safe_write32(ctx, &address_local, &value_local); ctx.builder.free_local(address_local); ctx.builder.free_local(value_local); diff --git a/src/rust/wasmgen/module_init.rs b/src/rust/wasmgen/module_init.rs index 82562a63..bd54b742 100644 --- a/src/rust/wasmgen/module_init.rs +++ b/src/rust/wasmgen/module_init.rs @@ -329,13 +329,8 @@ impl WasmBuilder { self.code_section.append(&mut self.instruction_body); } - // XXX: This should not be marked pub and not be prefixed with "_", - // but we need to share it with wasm_util so it is pub for now - // Moving set_local and tee_local to builder further complicate - // things. We should be able to fix this by better structuring the - // builder methods and wasm methods in the future. - // Currently only wasm_utils and the tests of this module use it. - pub fn _alloc_local(&mut self) -> WasmLocal { + #[must_use = "local allocated but not used"] + fn alloc_local(&mut self) -> WasmLocal { match self.free_locals.pop() { Some(local) => local, None => { @@ -350,6 +345,22 @@ impl WasmBuilder { dbg_assert!(local.0 < self.local_count); self.free_locals.push(local) } + + #[must_use = "local allocated but not used"] + pub fn set_new_local(&mut self) -> WasmLocal { + let local = self.alloc_local(); + self.instruction_body.push(op::OP_SETLOCAL); + self.instruction_body.push(local.idx()); + local + } + + #[must_use = "local allocated but not used"] + pub fn tee_new_local(&mut self) -> WasmLocal { + let local = self.alloc_local(); + self.instruction_body.push(op::OP_TEELOCAL); + self.instruction_body.push(local.idx()); + local + } } #[cfg(test)] @@ -379,7 +390,7 @@ mod tests { let bar_index = m.get_fn_idx("bar", FN0_TYPE_INDEX); m.code_section.call_fn(bar_index); - let _ = m._alloc_local(); // for ensuring that reset clears previous locals + let _ = m.alloc_local(); // for ensuring that reset clears previous locals m.finish(); m.reset(); @@ -392,17 +403,17 @@ mod tests { m.instruction_body.call_fn(foo_index); m.code_section.push_i32(10); - let local1 = m._alloc_local(); + let local1 = m.alloc_local(); m.code_section.tee_local(&local1); // local1 = 10 m.code_section.push_i32(20); m.code_section.add_i32(); - let local2 = m._alloc_local(); + let local2 = m.alloc_local(); m.code_section.tee_local(&local2); // local2 = 30 m.free_local(local1); - let local3 = m._alloc_local(); + let local3 = m.alloc_local(); assert_eq!(local3.idx(), 0); m.free_local(local2); diff --git a/src/rust/wasmgen/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs index 71e80dd0..532c191f 100644 --- a/src/rust/wasmgen/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -1,5 +1,5 @@ use leb::{write_fixed_leb16_at_idx, write_fixed_leb32_at_idx, write_leb_i32, write_leb_u32}; -use wasmgen::module_init::{WasmBuilder, WasmLocal}; +use wasmgen::module_init::WasmLocal; use wasmgen::wasm_opcodes as op; pub trait WasmBuf { @@ -253,17 +253,3 @@ impl WasmBuf for Vec { self.write_leb_u32(byte_offset); } } - -pub fn set_new_local(builder: &mut WasmBuilder) -> WasmLocal { - let local = builder._alloc_local(); - builder.instruction_body.push(op::OP_SETLOCAL); - builder.instruction_body.push(local.idx()); - local -} - -pub fn tee_new_local(builder: &mut WasmBuilder) -> WasmLocal { - let local = builder._alloc_local(); - builder.instruction_body.push(op::OP_TEELOCAL); - builder.instruction_body.push(local.idx()); - local -} From 22e570e1eb3295ee25d7d2cda69197fc0d608852 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Mon, 30 Jul 2018 12:37:13 +0530 Subject: [PATCH 1099/2137] remove commented out code --- src/rust/codegen.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 6a2d8ee0..bfee8a12 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -181,8 +181,6 @@ pub fn gen_safe_read32(ctx: &mut JitContext) { // Assumes virtual address has been pushed to the stack, and generates safe_read32s' fast-path // inline, bailing to safe_read32s_slow if necessary let builder = &mut ctx.builder; - //let instruction_body = &mut ctx.builder.instruction_body; - //let cpu = &mut ctx.cpu; let address_local = builder.tee_new_local(); @@ -247,8 +245,6 @@ pub fn gen_safe_write32(ctx: &mut JitContext, address_local: &WasmLocal, value_l // Generates safe_write32' fast-path inline, bailing to safe_write32_slow if necessary. let builder = &mut ctx.builder; - //let instruction_body = &mut ctx.builder.instruction_body; - //let cpu = &mut ctx.cpu; builder.instruction_body.get_local(&address_local); @@ -384,8 +380,6 @@ pub fn gen_safe_write16(ctx: &mut JitContext, address_local: &WasmLocal, value_l // Generates safe_write16' fast-path inline, bailing to safe_write16_slow if necessary. let builder = &mut ctx.builder; - //let instruction_body = &mut ctx.builder.instruction_body; - //let cpu = &mut ctx.cpu; builder.instruction_body.get_local(&address_local); From bad796b9eb836299ae0b8f058e98c2a9f9335d93 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Mon, 30 Jul 2018 13:17:53 +0530 Subject: [PATCH 1100/2137] deduplicate safe_{read,write}* functions --- src/rust/codegen.rs | 211 ++++++++++++++------------------------------ src/rust/cpu.rs | 6 ++ 2 files changed, 70 insertions(+), 147 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index bfee8a12..db9686bc 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -1,3 +1,4 @@ +use cpu::BitSize; use global_pointers; use jit::JitContext; use modrm; @@ -177,144 +178,19 @@ pub fn gen_set_reg32s_fn0(ctx: &mut JitContext, name: &str, reg: u32) { builder.instruction_body.store_aligned_i32(); } -pub fn gen_safe_read32(ctx: &mut JitContext) { - // Assumes virtual address has been pushed to the stack, and generates safe_read32s' fast-path - // inline, bailing to safe_read32s_slow if necessary - let builder = &mut ctx.builder; +pub fn gen_safe_read16(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::WORD) } +pub fn gen_safe_read32(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::DWORD) } - let address_local = builder.tee_new_local(); - - // Pseudo: base_on_stack = (uint32_t)address >> 12; - builder.instruction_body.push_i32(12); - builder.instruction_body.shr_u32(); - - // scale index - builder.instruction_body.push_i32(2); - builder.instruction_body.shl_i32(); - - // Pseudo: entry = tlb_data[base_on_stack]; - builder - .instruction_body - .load_aligned_i32_from_stack(global_pointers::TLB_DATA); - let entry_local = builder.tee_new_local(); - - // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && - // (address & 0xFFF) <= (0x1000 - 4)); - builder.instruction_body.push_i32( - (0xFFF & !TLB_READONLY & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) - as i32, - ); - builder.instruction_body.and_i32(); - - builder.instruction_body.push_i32(TLB_VALID as i32); - builder.instruction_body.eq_i32(); - - builder.instruction_body.get_local(&address_local); - builder.instruction_body.push_i32(0xFFF); - builder.instruction_body.and_i32(); - builder.instruction_body.push_i32(0x1000 - 4); - builder.instruction_body.le_i32(); - - builder.instruction_body.and_i32(); - - // Pseudo: - // if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]); - builder.instruction_body.if_i32(); - builder.instruction_body.get_local(&entry_local); - builder.instruction_body.push_i32(!0xFFF); - builder.instruction_body.and_i32(); - builder.instruction_body.get_local(&address_local); - builder.instruction_body.xor_i32(); - - builder - .instruction_body - .load_unaligned_i32_from_stack(global_pointers::MEMORY); - - // Pseudo: - // else { leave_on_stack(safe_read32s_slow(address)); } - builder.instruction_body.else_(); - builder.instruction_body.get_local(&address_local); - gen_call_fn1_ret(builder, "safe_read32s_slow"); - builder.instruction_body.block_end(); - - builder.free_local(address_local); - builder.free_local(entry_local); +pub fn gen_safe_write16(ctx: &mut JitContext, address_local: &WasmLocal, value_local: &WasmLocal) { + gen_safe_write(ctx, BitSize::WORD, address_local, value_local) } - pub fn gen_safe_write32(ctx: &mut JitContext, address_local: &WasmLocal, value_local: &WasmLocal) { - // Generates safe_write32' fast-path inline, bailing to safe_write32_slow if necessary. - - let builder = &mut ctx.builder; - - builder.instruction_body.get_local(&address_local); - - // Pseudo: base_on_stack = (uint32_t)address >> 12; - builder.instruction_body.push_i32(12); - builder.instruction_body.shr_u32(); - - // scale index - builder.instruction_body.push_i32(2); - builder.instruction_body.shl_i32(); - - // Pseudo: entry = tlb_data[base_on_stack]; - builder - .instruction_body - .load_aligned_i32_from_stack(global_pointers::TLB_DATA); - let entry_local = builder.tee_new_local(); - - // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && - // (address & 0xFFF) <= (0x1000 - 4)); - builder - .instruction_body - .push_i32((0xFFF & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32); - builder.instruction_body.and_i32(); - - builder.instruction_body.push_i32(TLB_VALID as i32); - builder.instruction_body.eq_i32(); - - builder.instruction_body.get_local(&address_local); - builder.instruction_body.push_i32(0xFFF); - builder.instruction_body.and_i32(); - builder.instruction_body.push_i32(0x1000 - 4); - builder.instruction_body.le_i32(); - - builder.instruction_body.and_i32(); - - // Pseudo: - // if(can_use_fast_path) - // { - // phys_addr = entry & ~0xFFF ^ address; - builder.instruction_body.if_void(); - - builder.instruction_body.get_local(&entry_local); - builder.instruction_body.push_i32(!0xFFF); - builder.instruction_body.and_i32(); - builder.instruction_body.get_local(&address_local); - builder.instruction_body.xor_i32(); - - builder.free_local(entry_local); - - // Pseudo: - // /* continued within can_use_fast_path branch */ - // mem8[phys_addr] = value; - - builder.instruction_body.get_local(&value_local); - builder - .instruction_body - .store_unaligned_i32(global_pointers::MEMORY); - - // Pseudo: - // else { safe_read32_slow(address, value); } - builder.instruction_body.else_(); - builder.instruction_body.get_local(&address_local); - builder.instruction_body.get_local(&value_local); - gen_call_fn2(builder, "safe_write32_slow"); - builder.instruction_body.block_end(); + gen_safe_write(ctx, BitSize::DWORD, address_local, value_local) } -pub fn gen_safe_read16(ctx: &mut JitContext) { - // Assumes virtual address has been pushed to the stack, and generates safe_read16's fast-path - // inline, bailing to safe_read16_slow if necessary +fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { + // Assumes virtual address has been pushed to the stack, and generates safe_readXX's fast-path + // inline, bailing to safe_readXX_slow if necessary let builder = &mut ctx.builder; let address_local = builder.tee_new_local(); @@ -334,7 +210,7 @@ pub fn gen_safe_read16(ctx: &mut JitContext) { let entry_local = builder.tee_new_local(); // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && - // (address & 0xFFF) <= (0x1000 - 2)); + // (address & 0xFFF) <= (0x1000 - (bitsize / 8)); builder.instruction_body.push_i32( (0xFFF & !TLB_READONLY & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32, @@ -347,7 +223,9 @@ pub fn gen_safe_read16(ctx: &mut JitContext) { builder.instruction_body.get_local(&address_local); builder.instruction_body.push_i32(0xFFF); builder.instruction_body.and_i32(); - builder.instruction_body.push_i32(0x1000 - 2); + builder + .instruction_body + .push_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 }); builder.instruction_body.le_i32(); builder.instruction_body.and_i32(); @@ -361,23 +239,44 @@ pub fn gen_safe_read16(ctx: &mut JitContext) { builder.instruction_body.get_local(&address_local); builder.instruction_body.xor_i32(); - builder - .instruction_body - .load_unaligned_u16_from_stack(global_pointers::MEMORY); + match bits { + BitSize::WORD => { + builder + .instruction_body + .load_unaligned_u16_from_stack(global_pointers::MEMORY); + }, + BitSize::DWORD => { + builder + .instruction_body + .load_unaligned_i32_from_stack(global_pointers::MEMORY); + }, + } // Pseudo: // else { leave_on_stack(safe_read16_slow(address)); } builder.instruction_body.else_(); builder.instruction_body.get_local(&address_local); - gen_call_fn1_ret(builder, "safe_read16_slow"); + match bits { + BitSize::WORD => { + gen_call_fn1_ret(builder, "safe_read16_slow"); + }, + BitSize::DWORD => { + gen_call_fn1_ret(builder, "safe_read32s_slow"); + }, + } builder.instruction_body.block_end(); builder.free_local(address_local); builder.free_local(entry_local); } -pub fn gen_safe_write16(ctx: &mut JitContext, address_local: &WasmLocal, value_local: &WasmLocal) { - // Generates safe_write16' fast-path inline, bailing to safe_write16_slow if necessary. +fn gen_safe_write( + ctx: &mut JitContext, + bits: BitSize, + address_local: &WasmLocal, + value_local: &WasmLocal, +) { + // Generates safe_writeXX' fast-path inline, bailing to safe_writeXX_slow if necessary. let builder = &mut ctx.builder; @@ -398,7 +297,7 @@ pub fn gen_safe_write16(ctx: &mut JitContext, address_local: &WasmLocal, value_l let entry_local = builder.tee_new_local(); // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && - // (address & 0xFFF) <= (0x1000 - 2)); + // (address & 0xFFF) <= (0x1000 - bitsize / 8)); builder .instruction_body .push_i32((0xFFF & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32); @@ -410,7 +309,9 @@ pub fn gen_safe_write16(ctx: &mut JitContext, address_local: &WasmLocal, value_l builder.instruction_body.get_local(&address_local); builder.instruction_body.push_i32(0xFFF); builder.instruction_body.and_i32(); - builder.instruction_body.push_i32(0x1000 - 2); + builder + .instruction_body + .push_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 }); builder.instruction_body.le_i32(); builder.instruction_body.and_i32(); @@ -434,16 +335,32 @@ pub fn gen_safe_write16(ctx: &mut JitContext, address_local: &WasmLocal, value_l // mem8[phys_addr] = value; builder.instruction_body.get_local(&value_local); - builder - .instruction_body - .store_unaligned_u16(global_pointers::MEMORY); + match bits { + BitSize::WORD => { + builder + .instruction_body + .store_unaligned_u16(global_pointers::MEMORY); + }, + BitSize::DWORD => { + builder + .instruction_body + .store_unaligned_i32(global_pointers::MEMORY); + }, + } // Pseudo: // else { safe_write16_slow(address, value); } builder.instruction_body.else_(); builder.instruction_body.get_local(&address_local); builder.instruction_body.get_local(&value_local); - gen_call_fn2(builder, "safe_write16_slow"); + match bits { + BitSize::WORD => { + gen_call_fn2(builder, "safe_write16_slow"); + }, + BitSize::DWORD => { + gen_call_fn2(builder, "safe_write32_slow"); + }, + } builder.instruction_body.block_end(); } diff --git a/src/rust/cpu.rs b/src/rust/cpu.rs index 03fc37b6..ff45fdd9 100644 --- a/src/rust/cpu.rs +++ b/src/rust/cpu.rs @@ -21,6 +21,12 @@ mod unsafe_cpu { } } +#[derive(Copy, Clone, Eq, PartialEq)] +pub enum BitSize { + WORD, + DWORD, +} + pub fn read8(addr: u32) -> u8 { unsafe { unsafe_cpu::read8(addr) } } pub fn read16(addr: u32) -> u16 { unsafe { unsafe_cpu::read16(addr) } } pub fn read32(addr: u32) -> u32 { unsafe { unsafe_cpu::read32(addr) } } From 9f2c78efb4286cfe1ded97d04201934c45425110 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 26 Jul 2018 15:06:50 -0600 Subject: [PATCH 1101/2137] Add missing sse3 instruction and add note on others --- gen/x86_table.js | 25 ++++++++++++++----------- src/native/instructions_0f.c | 1 + 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 582bb1e1..f8204db6 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -476,8 +476,8 @@ const encodings = [ { sse: 1, opcode: 0xF20F11, e: 1 }, { sse: 1, opcode: 0x0F12, e: 1 }, { sse: 1, opcode: 0x660F12, only_mem: 1, e: 1 }, - { sse: 1, opcode: 0xF20F12, e: 1, skip: 1, }, - { sse: 1, opcode: 0xF30F12, e: 1, skip: 1, }, + { sse: 1, opcode: 0xF20F12, e: 1, skip: 1, }, // sse3 + { sse: 1, opcode: 0xF30F12, e: 1, skip: 1, }, // sse3 { sse: 1, opcode: 0x0F13, only_mem: 1, e: 1 }, { sse: 1, opcode: 0x660F13, only_mem: 1, e: 1 }, { sse: 1, opcode: 0x0F14, e: 1 }, @@ -486,6 +486,7 @@ const encodings = [ { sse: 1, opcode: 0x660F15, e: 1 }, { sse: 1, opcode: 0x0F16, e: 1 }, { sse: 1, opcode: 0x660F16, only_mem: 1, e: 1 }, + { sse: 1, opcode: 0xF30F16, skip: 1, }, // sse3 { sse: 1, opcode: 0x0F17, only_mem: 1, e: 1 }, { sse: 1, opcode: 0x660F17, only_mem: 1, e: 1 }, @@ -597,12 +598,14 @@ const encodings = [ { sse: 1, opcode: 0x660F76, e: 1, }, { sse: 1, opcode: 0x0F77 }, - { sse: 1, opcode: 0x0F78, skip: 1 }, - { sse: 1, opcode: 0x0F79, skip: 1 }, - { sse: 1, opcode: 0x0F7A, skip: 1 }, - { sse: 1, opcode: 0x0F7B, skip: 1 }, - { sse: 1, opcode: 0x0F7C, skip: 1 }, - { sse: 1, opcode: 0x0F7D, skip: 1 }, + // vmx instructions + { opcode: 0x0F78, skip: 1 }, + { opcode: 0x0F79, skip: 1 }, + + { opcode: 0x0F7A, skip: 1 }, // ud + { opcode: 0x0F7B, skip: 1 }, // ud + { sse: 1, opcode: 0x0F7C, skip: 1 }, // sse3 + { sse: 1, opcode: 0x0F7D, skip: 1 }, // sse3 { sse: 1, opcode: 0x0F7E, e: 1 }, { sse: 1, opcode: 0x660F7E, e: 1 }, @@ -614,15 +617,15 @@ const encodings = [ { sse: 1, opcode: 0x0FC2, skip: 1, }, { opcode: 0x0FC3, e: 1, only_mem: 1, }, // movnti: Uses normal registers, hence not marked as sse + { sse: 1, opcode: 0x0FC4, e: 1, imm8: 1 }, { sse: 1, opcode: 0x660FC4, e: 1, imm8: 1 }, - { sse: 1, opcode: 0x0FC5, e: 1, only_reg: 1, imm8: 1 }, { sse: 1, opcode: 0x660FC5, e: 1, only_reg: 1, imm8: 1, }, { sse: 1, opcode: 0x0FC6, skip: 1, }, - { sse: 1, opcode: 0x0FD0, skip: 1, }, + { sse: 1, opcode: 0x0FD0, skip: 1, }, // sse3 { sse: 1, opcode: 0x0FD1, e: 1 }, { sse: 1, opcode: 0x660FD1, e: 1 }, @@ -696,7 +699,7 @@ const encodings = [ { sse: 1, opcode: 0x0FEF, e: 1 }, { sse: 1, opcode: 0x660FEF, e: 1 }, - { sse: 1, opcode: 0x0FF0, skip: 1, }, + { sse: 1, opcode: 0x0FF0, skip: 1, }, // sse3 { sse: 1, opcode: 0x0FF1, e: 1 }, { sse: 1, opcode: 0x660FF1, e: 1 }, diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 821597d1..52773448 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -400,6 +400,7 @@ void instr_660F16_mem(int32_t addr, int32_t r) { movh_m64_r128(addr, r); } void instr_660F16_reg(int32_t r1, int32_t r2) { trigger_ud(); } +void instr_F30F16() { unimplemented_sse(); } void instr_0F17_mem(int32_t addr, int32_t r) { // movhps m64, xmm From 828177b37ffb1656b076553a4b4ce0444c656fa3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 26 Jul 2018 15:07:15 -0600 Subject: [PATCH 1102/2137] Fix uninitialised pointer: apic_enabled --- src/native/instructions_0f.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 52773448..756733f3 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -20,7 +20,7 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-parameter" -bool* const apic_enabled; +bool apic_enabled = false; void instr_0F00_0_mem(int32_t addr) { // sldt @@ -711,7 +711,7 @@ void instr_0F30() { int32_t address = low & ~(IA32_APIC_BASE_BSP | IA32_APIC_BASE_EXTD | IA32_APIC_BASE_EN); dbg_assert_message(address == APIC_ADDRESS, "Changing APIC address not supported"); dbg_assert_message((low & IA32_APIC_BASE_EXTD) == 0, "x2apic not supported"); - *apic_enabled = (low & IA32_APIC_BASE_EN) == IA32_APIC_BASE_EN; + apic_enabled = (low & IA32_APIC_BASE_EN) == IA32_APIC_BASE_EN; } break; @@ -807,7 +807,7 @@ void instr_0F32() { { low = APIC_ADDRESS; - if(*apic_enabled) + if(apic_enabled) { low |= IA32_APIC_BASE_EN; } From a1f0b3f12e9bbfb01464a908217766bd605d8ef6 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 26 Jul 2018 17:35:17 -0600 Subject: [PATCH 1103/2137] Export profiling methods outside of debug mode --- src/rust/c_api.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/rust/c_api.rs b/src/rust/c_api.rs index d819a873..5262d781 100644 --- a/src/rust/c_api.rs +++ b/src/rust/c_api.rs @@ -130,3 +130,19 @@ pub fn jit_get_entry_pending(i: u32) -> bool { ::jit::jit_get_entry_pending(i) } pub fn jit_get_wasm_table_index_free_list_count() -> u32 { ::jit::jit_get_wasm_table_index_free_list_count(get_module()) } + +#[no_mangle] +#[cfg(not(debug_assertions))] +pub fn jit_unused_cache_stat() -> u32 { 0 } +#[no_mangle] +#[cfg(not(debug_assertions))] +pub fn jit_get_entry_length(_: u32) -> u32 { 0 } +#[no_mangle] +#[cfg(not(debug_assertions))] +pub fn jit_get_entry_address(_: u32) -> u32 { 0 } +#[no_mangle] +#[cfg(not(debug_assertions))] +pub fn jit_get_entry_pending(_: u32) -> bool { false } +#[no_mangle] +#[cfg(not(debug_assertions))] +pub fn jit_get_wasm_table_index_free_list_count() -> u32 { 0 } From bca4e80bb6fc176326b97d9280e7ed220bec67ab Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 26 Jul 2018 17:36:32 -0600 Subject: [PATCH 1104/2137] Allow fast path for cpl>0 in safe_write32 --- src/native/cpu.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/native/cpu.c b/src/native/cpu.c index fa95c1f9..5540f6f3 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -1208,7 +1208,7 @@ void safe_write32(int32_t address, int32_t value) #if 1 int32_t base = (uint32_t)address >> 12; int32_t entry = tlb_data[base]; - int32_t info_bits = entry & 0xFFF & ~TLB_GLOBAL; + int32_t info_bits = entry & 0xFFF & ~TLB_GLOBAL & ~(*cpl == 3 ? 0 : TLB_NO_USER); if(info_bits == TLB_VALID && (address & 0xFFF) <= (0x1000 - 4)) { @@ -1217,7 +1217,6 @@ void safe_write32(int32_t address, int32_t value) #endif // - allowed to write in user-mode // - not in memory mapped area - // - can be accessed from any cpl // - does not contain code uint32_t phys_address = entry & ~0xFFF ^ address; From aef0732be2c4281a9e56590194b0bd521a1f3d20 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 26 Jul 2018 17:37:47 -0600 Subject: [PATCH 1105/2137] Allow running release build with DEBUG=1 --- src/browser/main.js | 96 +++++++++++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 42 deletions(-) diff --git a/src/browser/main.js b/src/browser/main.js index 3f7a8120..cbba6bb7 100644 --- a/src/browser/main.js +++ b/src/browser/main.js @@ -577,56 +577,62 @@ var log_levels = $("log_levels"); - for(var i = 0; i < LOG_NAMES.length; i++) + if(log_levels) { - var mask = LOG_NAMES[i][0]; - - if(mask === 1) - continue; - - var name = LOG_NAMES[i][1].toLowerCase(), - input = document.createElement("input"), - label = document.createElement("label"); - - input.type = "checkbox"; - - label.htmlFor = input.id = "log_" + name; - - if(LOG_LEVEL & mask) + for(var i = 0; i < LOG_NAMES.length; i++) { - input.checked = true; + var mask = LOG_NAMES[i][0]; + + if(mask === 1) + continue; + + var name = LOG_NAMES[i][1].toLowerCase(), + input = document.createElement("input"), + label = document.createElement("label"); + + input.type = "checkbox"; + + label.htmlFor = input.id = "log_" + name; + + if(LOG_LEVEL & mask) + { + input.checked = true; + } + input.mask = mask; + + label.appendChild(input); + label.appendChild(document.createTextNode(v86util.pads(name, 4) + " ")); + log_levels.appendChild(label); + + if(i === Math.floor(LOG_NAMES.length / 2)) + { + log_levels.appendChild(document.createTextNode("\n")); + } } - input.mask = mask; - label.appendChild(input); - label.appendChild(document.createTextNode(v86util.pads(name, 4) + " ")); - log_levels.appendChild(label); - - if(i === Math.floor(LOG_NAMES.length / 2)) + log_levels.onchange = function(e) { - log_levels.appendChild(document.createTextNode("\n")); - } + var target = e.target, + mask = target.mask; + + if(target.checked) + { + LOG_LEVEL |= mask; + } + else + { + LOG_LEVEL &= ~mask; + } + + target.blur(); + }; } - log_levels.onchange = function(e) - { - var target = e.target, - mask = target.mask; - - if(target.checked) - { - LOG_LEVEL |= mask; - } - else - { - LOG_LEVEL &= ~mask; - } - - target.blur(); - }; - var debug_infos = $("debug_infos"); - debug_infos.textContent = "ACPI: " + (ENABLE_ACPI ? "enabled" : "disabled"); + if(debug_infos) + { + debug_infos.textContent = "ACPI: " + (ENABLE_ACPI ? "enabled" : "disabled"); + } } window.addEventListener("load", onload, false); @@ -1323,6 +1329,12 @@ var debug = emulator.v86.cpu.debug; var debug_infos = $("debug_infos"); + if(!debug_infos) + { + dbg_log("Element debug_infos not found, disabling debug UI"); + return; + } + debug_infos.textContent += " | logging ops: " + (debug.step_mode || debug.trace_all ? "yes" : "no"); From 384b7f3f735031bd88af9b03f600150d27200021 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 26 Jul 2018 17:39:01 -0600 Subject: [PATCH 1106/2137] Add more full tests and skip slow tests by default --- tests/full/run.js | 118 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 2 deletions(-) diff --git a/tests/full/run.js b/tests/full/run.js index e34db8f1..9337a735 100755 --- a/tests/full/run.js +++ b/tests/full/run.js @@ -8,6 +8,7 @@ var MAX_PARALLEL_TESTS = +process.env.MAX_PARALLEL_TESTS || 4; var TEST_NAME = process.env.TEST_NAME; const VERBOSE = false; +const RUN_SLOW_TESTS = false; try { @@ -140,6 +141,15 @@ if(cluster.isMaster) // skip_if_disk_image_missing: true, //}, //{ + // name: "Windows 95", + // hda: root_path + "/images/windows95.img", + // timeout: 60, + // expect_graphical_mode: true, + // expect_graphical_size: [800, 600], + // expect_mouse_registered: true, + // skip_if_disk_image_missing: true, + //}, + //{ // name: "Oberon", // hda: root_path + "/images/oberon.dsk", // fda: root_path + "/images/oberon-boot.dsk", @@ -185,6 +195,27 @@ if(cluster.isMaster) }, ], }, + { + name: "MS-DOS", + skip_if_disk_image_missing: true, + hda: root_path + "/images/msdos.img", + timeout: 90, + expected_texts: [ + "C:\\>", + ], + }, + { + name: "Linux 4", + skip_if_disk_image_missing: true, + cdrom: root_path + "/images/linux4.iso", + timeout: 200, + // TODO: Check serial + expected_texts: [ + "~%", + "Files send via emulator appear in", + ], + expect_mouse_registered: true, + }, { name: "OpenBSD", fda: root_path + "/images/openbsd.img", @@ -223,7 +254,7 @@ if(cluster.isMaster) { name: "FreeBSD", skip_if_disk_image_missing: true, - timeout: 240, + timeout: 5 * 60, hda: root_path + "/../v86-images/os/freebsd.img", expected_texts: ["FreeBSD/i386 (nyu) (ttyv0)"], actions: [ @@ -233,6 +264,34 @@ if(cluster.isMaster) } ], }, + { + name: "FreeBSD cdrom", + skip_if_disk_image_missing: true, + slow: 1, + timeout: 10 * 60, + cdrom: root_path + "/../v86-images/os/FreeBSD-11.0-RELEASE-i386-bootonly.iso", + expected_texts: ["Welcome to FreeBSD!"], + actions: [ + { + on_text: " Autoboot in ", + run: "\n", + } + ], + }, + { + name: "FreeGEM", + skip_if_disk_image_missing: true, + timeout: 60, + hda: root_path + "/../v86-images/os/freegem.bin", + expect_graphical_mode: true, + expect_mouse_registered: true, + actions: [ + { + on_text: " Select from Menu", + run: "3", + } + ], + }, // TODO: Check serial text { name: "Haiku", @@ -246,7 +305,7 @@ if(cluster.isMaster) { name: "HelenOS", skip_if_disk_image_missing: true, - timeout: 2 * 60, + timeout: 3 * 60, cdrom: root_path + "/../v86-images/os/HelenOS-0.5.0-ia32.iso", expect_graphical_mode: true, expect_mouse_registered: true, @@ -281,6 +340,54 @@ if(cluster.isMaster) }, ], }, + { + name: "Core 9", + skip_if_disk_image_missing: 1, + timeout: 5 * 60, + cdrom: root_path + "/../v86-images/os/Core-9.0.iso", + expected_texts: ["tc@box"], + actions: [{ on_text: "boot:", run: "\n" }], + }, + { + name: "Core 8", + skip_if_disk_image_missing: 1, + timeout: 5 * 60, + cdrom: root_path + "/../v86-images/os/Core-8.0.iso", + expected_texts: ["tc@box"], + actions: [{ on_text: "boot:", run: "\n" }], + }, + { + name: "Core 7", + skip_if_disk_image_missing: 1, + timeout: 5 * 60, + cdrom: root_path + "/../v86-images/os/Core-7.2.iso", + expected_texts: ["tc@box"], + actions: [{ on_text: "boot:", run: "\n" }], + }, + { + name: "Core 6", + skip_if_disk_image_missing: 1, + timeout: 5 * 60, + cdrom: root_path + "/../v86-images/os/Core-6.4.1.iso", + expected_texts: ["tc@box"], + actions: [{ on_text: "boot:", run: "\n" }], + }, + { + name: "Core 5", + skip_if_disk_image_missing: 1, + timeout: 5 * 60, + cdrom: root_path + "/../v86-images/os/Core-5.4.iso", + expected_texts: ["tc@box"], + actions: [{ on_text: "boot:", run: "\n" }], + }, + { + name: "Core 4", + skip_if_disk_image_missing: 1, + timeout: 5 * 60, + cdrom: root_path + "/../v86-images/os/Core-4.7.7.iso", + expected_texts: ["tc@box"], + actions: [{ on_text: "boot:", run: "\n" }], + }, ]; if(TEST_NAME) @@ -362,6 +469,13 @@ function run_test(test, done) } } + if(test.slow && !RUN_SLOW_TESTS) + { + console.warn("Slow test: " + test.name + ", skipped"); + console.warn(); + done(); + return; + } if(test.alternative_bios) { From 9eab018e1f6b674aa28a38d7e11b73b3c6c99043 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 27 Jul 2018 12:32:19 -0600 Subject: [PATCH 1107/2137] Check unhandled sse prefixes at runtime --- gen/generate_interpreter.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gen/generate_interpreter.js b/gen/generate_interpreter.js index 2a29acfb..0924c0fa 100755 --- a/gen/generate_interpreter.js +++ b/gen/generate_interpreter.js @@ -145,8 +145,13 @@ function gen_instruction_body(encodings, size) if_blocks.push({ condition: "prefixes_ & PREFIX_F3", body, }); } + const check_prefixes = encoding.sse ? "(PREFIX_66 | PREFIX_F2 | PREFIX_F3)" : "(PREFIX_F2 | PREFIX_F3)"; + const else_block = { - body: gen_instruction_body_after_prefix(no_prefix, size), + body: [].concat( + "dbg_assert((prefixes_ & " + check_prefixes + ") == 0);", + gen_instruction_body_after_prefix(no_prefix, size) + ) }; return [].concat( From 67db676cec04ab6c4c0dc4dff7ffd9db22a37371 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 27 Jul 2018 14:37:05 -0600 Subject: [PATCH 1108/2137] Fix pinsrw: Use safe_read16 instead of read16 --- src/native/instructions_0f.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 756733f3..89509b71 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -2278,7 +2278,7 @@ void instr_0FC4(int32_t source, int32_t r, int32_t imm8) { write_mmx_reg64(r, destination); } -DEFINE_SSE_SPLIT_IMM(instr_0FC4, read16, read_reg32) +DEFINE_SSE_SPLIT_IMM(instr_0FC4, safe_read16, read_reg32) void instr_660FC4(int32_t source, int32_t r, int32_t imm8) { // pinsrw xmm, r32/m16, imm8 @@ -2289,7 +2289,7 @@ void instr_660FC4(int32_t source, int32_t r, int32_t imm8) { write_xmm_reg128(r, destination); } -DEFINE_SSE_SPLIT_IMM(instr_660FC4, read16, read_reg32) +DEFINE_SSE_SPLIT_IMM(instr_660FC4, safe_read16, read_reg32) void instr_0FC5_mem(int32_t addr, int32_t r, int32_t imm8) { trigger_ud(); } void instr_0FC5_reg(int32_t r1, int32_t r2, int32_t imm8) { From 6f28d8b9c97827be4438cd392b11a229ebb1f01c Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 27 Jul 2018 15:46:01 -0600 Subject: [PATCH 1109/2137] call_interrupt_vector can't raise anymore --- src/cpu.js | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index 41c04209..a2e7438e 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -2908,18 +2908,8 @@ CPU.prototype.unimplemented_sse = function() CPU.prototype.pic_call_irq = function(int) { - //dbg_log("pic_call_irq", LOG_CPU); - - try - { - this.previous_ip[0] = this.instruction_pointer[0]; - this.call_interrupt_vector(int, false, false, 0); - //dbg_log("to " + h(this.instruction_pointer[0] >>> 0), LOG_CPU); - } - catch(e) - { - this.exception_cleanup(e); - } + this.previous_ip[0] = this.instruction_pointer[0]; // XXX: What if called after instruction (port IO) + this.call_interrupt_vector(int, false, false, 0); }; CPU.prototype.handle_irqs = function() From 7e574dde521610429f9f12559fa9100f4b5baa22 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 27 Jul 2018 16:24:54 -0600 Subject: [PATCH 1110/2137] Implement some floating point sse1/sse2 instructions (#57) --- gen/x86_table.js | 40 ++++-- src/native/cpu.c | 20 +++ src/native/cpu.h | 8 ++ src/native/instructions_0f.c | 241 ++++++++++++++++++++++++++++++++++- src/native/instructions_0f.h | 14 +- src/native/sse_instr.c | 19 +++ src/native/sse_instr.h | 2 + tests/qemu/test-i386.c | 18 ++- 8 files changed, 324 insertions(+), 38 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index f8204db6..a23de44c 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -494,7 +494,10 @@ const encodings = [ { sse: 1, opcode: 0x660F28, e: 1 }, { sse: 1, opcode: 0x0F29, e: 1 }, { sse: 1, opcode: 0x660F29, e: 1 }, - { sse: 1, opcode: 0x0F2A, skip: 1 }, + { sse: 1, opcode: 0x0F2A, e: 1, }, + { sse: 1, opcode: 0x660F2A, e: 1, }, + { sse: 1, opcode: 0xF20F2A, e: 1, }, + { sse: 1, opcode: 0xF30F2A, e: 1, }, { sse: 1, opcode: 0x0F2B, only_mem: 1, e: 1 }, { sse: 1, opcode: 0x660F2B, only_mem: 1, e: 1 }, @@ -510,7 +513,11 @@ const encodings = [ { sse: 1, opcode: 0x660F50, only_reg: 1, e: 1 }, { sse: 1, opcode: 0x0F51, skip: 1 }, { sse: 1, opcode: 0x0F52, skip: 1 }, - { sse: 1, opcode: 0x0F53, skip: 1 }, + + // reciprocal: approximation of 1/x. Skipped because our approximation doesn't match intel's + { sse: 1, opcode: 0x0F53, e: 1, skip: 1, }, + { sse: 1, opcode: 0xF30F53, e: 1, skip: 1, }, + { sse: 1, opcode: 0x0F54, e: 1 }, { sse: 1, opcode: 0x660F54, e: 1 }, { sse: 1, opcode: 0x0F55, e: 1 }, @@ -520,14 +527,26 @@ const encodings = [ { sse: 1, opcode: 0x0F57, e: 1 }, { sse: 1, opcode: 0x660F57, e: 1 }, - { sse: 1, opcode: 0x0F58, skip: 1 }, - { sse: 1, opcode: 0x0F59, skip: 1 }, + { sse: 1, opcode: 0x0F58, e: 1, }, + { sse: 1, opcode: 0x660F58, e: 1, }, + { sse: 1, opcode: 0xF20F58, e: 1, }, + { sse: 1, opcode: 0xF30F58, e: 1, }, + + { sse: 1, opcode: 0x0F59, e: 1, }, + { sse: 1, opcode: 0x660F59, e: 1, }, + { sse: 1, opcode: 0xF20F59, e: 1, }, + { sse: 1, opcode: 0xF30F59, e: 1, }, + { sse: 1, opcode: 0x0F5A, skip: 1 }, { sse: 1, opcode: 0x0F5B, skip: 1 }, - { sse: 1, opcode: 0x0F5C, skip: 1 }, - { sse: 1, opcode: 0x0F5D, skip: 1 }, - { sse: 1, opcode: 0x0F5E, skip: 1 }, - { sse: 1, opcode: 0x0F5F, skip: 1 }, + + { sse: 1, opcode: 0x0F5C, e: 1, }, + { sse: 1, opcode: 0x660F5C, e: 1, }, + { sse: 1, opcode: 0xF20F5C, e: 1, }, + { sse: 1, opcode: 0xF30F5C, e: 1, }, + { sse: 1, opcode: 0x0F5D, skip: 1, }, + { sse: 1, opcode: 0x0F5E, skip: 1, }, + { sse: 1, opcode: 0x0F5F, skip: 1, }, { sse: 1, opcode: 0x660F60, e: 1 }, { sse: 1, opcode: 0x0F60, e: 1 }, @@ -614,7 +633,10 @@ const encodings = [ { sse: 1, opcode: 0x660F7F, e: 1 }, { sse: 1, opcode: 0xF30F7F, e: 1 }, - { sse: 1, opcode: 0x0FC2, skip: 1, }, + { sse: 1, opcode: 0x0FC2, e: 1, imm8: 1 }, + { sse: 1, opcode: 0x660FC2, e: 1, imm8: 1 }, + { sse: 1, opcode: 0xF20FC2, e: 1, imm8: 1 }, + { sse: 1, opcode: 0xF30FC2, e: 1, imm8: 1 }, { opcode: 0x0FC3, e: 1, only_mem: 1, }, // movnti: Uses normal registers, hence not marked as sse diff --git a/src/native/cpu.c b/src/native/cpu.c index 5540f6f3..9c54ed6a 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -1368,6 +1368,16 @@ void write_mmx_reg64(int32_t r, union reg64 data) reg_mmx[r].u64[0] = data.u64[0]; } +float_t read_xmm_f32(int32_t r) +{ + return reg_xmm[r].f32[0]; +} + +int32_t read_xmm32(int32_t r) +{ + return reg_xmm[r].u32[0]; +} + union reg64 read_xmm64s(int32_t r) { union reg64 x; @@ -1380,6 +1390,16 @@ union reg128 read_xmm128s(int32_t r) return reg_xmm[r]; } +void write_xmm_f32(int32_t r, float_t data) +{ + reg_xmm[r].f32[0] = data; +} + +void write_xmm32(int32_t r, int32_t data) +{ + reg_xmm[r].i32[0] = data; +} + void write_xmm64(int32_t r, union reg64 data) { reg_xmm[r].u64[0] = data.u64[0]; diff --git a/src/native/cpu.h b/src/native/cpu.h index 760f8b86..342326a0 100644 --- a/src/native/cpu.h +++ b/src/native/cpu.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -17,6 +18,8 @@ union reg128 { uint16_t u16[8]; uint32_t u32[4]; uint64_t u64[2]; + float_t f32[4]; + double_t f64[2]; }; _Static_assert(sizeof(union reg128) == 16, "reg128 is 16 bytes"); @@ -29,6 +32,7 @@ union reg64 { uint16_t u16[4]; uint32_t u32[2]; uint64_t u64[1]; + float_t f32[2]; double f64[1]; }; _Static_assert(sizeof(union reg64) == 8, "reg64 is 8 bytes"); @@ -141,8 +145,12 @@ int32_t read_mmx32s(int32_t r); union reg64 read_mmx64s(int32_t r); void write_mmx64(int32_t r, int32_t low, int32_t high); void write_mmx_reg64(int32_t r, union reg64 data); +float_t read_xmm_f32(int32_t r); +int32_t read_xmm32(int32_t r); union reg64 read_xmm64s(int32_t r); union reg128 read_xmm128s(int32_t r); +void write_xmm_f32(int32_t r, float_t data); +void write_xmm32(int32_t r, int32_t); void write_xmm64(int32_t r, union reg64 data); void write_xmm128(int32_t r, int32_t i0, int32_t i1, int32_t i2, int32_t i3); void write_xmm_reg128(int32_t r, union reg128 data); diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 89509b71..71b17601 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -621,7 +621,48 @@ void instr_660F29_reg(int32_t r1, int32_t r2) { mov_r_r128(r1, r2); } -void instr_0F2A() { unimplemented_sse(); } +void instr_0F2A(union reg64 source, int32_t r) { + // cvtpi2ps xmm, mm/m64 + // XXX: The non-memory variant causes a transition from x87 FPU to MMX technology operation + union reg64 result = { + .f32 = { + // Note: Casts here can fail + source.i32[0], + source.i32[1], + } + }; + write_xmm64(r, result); +} +DEFINE_SSE_SPLIT(instr_0F2A, safe_read64s, read_mmx64s) +void instr_660F2A(union reg64 source, int32_t r) { + // cvtpi2pd xmm, xmm/m64 + // XXX: The non-memory variant causes a transition from x87 FPU to MMX technology operation + union reg128 result = { + .f64 = { + // These casts can't fail + source.i32[0], + source.i32[1], + } + }; + write_xmm_reg128(r, result); +} +DEFINE_SSE_SPLIT(instr_660F2A, safe_read64s, read_mmx64s) +void instr_F20F2A(int32_t source, int32_t r) { + // cvtsi2sd xmm, r32/m32 + union reg64 result = { + // This cast can't fail + .f64 = { source } + }; + write_xmm64(r, result); +} +DEFINE_SSE_SPLIT(instr_F20F2A, safe_read32s, read_reg32) +void instr_F30F2A(int32_t source, int32_t r) { + // cvtsi2ss xmm, r/m32 + // Note: This cast can fail + float_t result = source; + write_xmm_f32(r, result); +} +DEFINE_SSE_SPLIT(instr_F30F2A, safe_read32s, read_reg32) void instr_0F2B_reg(int32_t r1, int32_t r2) { trigger_ud(); } void instr_0F2B_mem(int32_t addr, int32_t r) { @@ -1005,7 +1046,26 @@ void instr_660F50_mem(int32_t addr, int32_t r1) { trigger_ud(); } void instr_0F51() { unimplemented_sse(); } void instr_0F52() { unimplemented_sse(); } -void instr_0F53() { unimplemented_sse(); } + +void instr_0F53(union reg128 source, int32_t r) { + // rcpps xmm, xmm/m128 + union reg128 result = { + .f32 = { + 1 / source.f32[0], + 1 / source.f32[1], + 1 / source.f32[2], + 1 / source.f32[3], + } + }; + write_xmm_reg128(r, result); +} +DEFINE_SSE_SPLIT(instr_0F53, safe_read128s, read_xmm128s) + +void instr_F30F53(float_t source, int32_t r) { + // rcpss xmm, xmm/m32 + write_xmm_f32(r, 1 / source); +} +DEFINE_SSE_SPLIT(instr_F30F53, fpu_load_m32, read_xmm_f32) void instr_0F54(union reg128 source, int32_t r) { // andps xmm, xmm/mem128 @@ -1063,11 +1123,138 @@ void instr_660F57(union reg128 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_660F57, safe_read128s, read_xmm128s) -void instr_0F58() { unimplemented_sse(); } -void instr_0F59() { unimplemented_sse(); } +void instr_0F58(union reg128 source, int32_t r) { + // addps xmm, xmm/mem128 + union reg128 destination = read_xmm128s(r); + union reg128 result = { + .f32 = { + source.f32[0] + destination.f32[0], + source.f32[1] + destination.f32[1], + source.f32[2] + destination.f32[2], + source.f32[3] + destination.f32[3], + } + }; + write_xmm_reg128(r, result); +} +DEFINE_SSE_SPLIT(instr_0F58, safe_read128s, read_xmm128s) +void instr_660F58(union reg128 source, int32_t r) { + // addpd xmm, xmm/mem128 + union reg128 destination = read_xmm128s(r); + union reg128 result = { + .f64 = { + source.f64[0] + destination.f64[0], + source.f64[1] + destination.f64[1], + } + }; + write_xmm_reg128(r, result); +} +DEFINE_SSE_SPLIT(instr_660F58, safe_read128s, read_xmm128s) +void instr_F20F58(union reg64 source, int32_t r) { + // addsd xmm, xmm/mem64 + union reg64 destination = read_xmm64s(r); + union reg64 result = { + .f64 = { source.f64[0] + destination.f64[0], } + }; + write_xmm64(r, result); +} +DEFINE_SSE_SPLIT(instr_F20F58, safe_read64s, read_xmm64s) +void instr_F30F58(float_t source, int32_t r) { + // addss xmm, xmm/mem32 + float_t destination = read_xmm_f32(r); + float result = source + destination; + write_xmm_f32(r, result); +} +DEFINE_SSE_SPLIT(instr_F30F58, fpu_load_m32, read_xmm_f32) + +void instr_0F59(union reg128 source, int32_t r) { + // mulps xmm, xmm/mem128 + union reg128 destination = read_xmm128s(r); + union reg128 result = { + .f32 = { + source.f32[0] * destination.f32[0], + source.f32[1] * destination.f32[1], + source.f32[2] * destination.f32[2], + source.f32[3] * destination.f32[3], + } + }; + write_xmm_reg128(r, result); +} +DEFINE_SSE_SPLIT(instr_0F59, safe_read128s, read_xmm128s) +void instr_660F59(union reg128 source, int32_t r) { + // mulpd xmm, xmm/mem128 + union reg128 destination = read_xmm128s(r); + union reg128 result = { + .f64 = { + source.f64[0] * destination.f64[0], + source.f64[1] * destination.f64[1], + } + }; + write_xmm_reg128(r, result); +} +DEFINE_SSE_SPLIT(instr_660F59, safe_read128s, read_xmm128s) +void instr_F20F59(union reg64 source, int32_t r) { + // mulsd xmm, xmm/mem64 + union reg64 destination = read_xmm64s(r); + union reg64 result = { + .f64 = { source.f64[0] * destination.f64[0], } + }; + write_xmm64(r, result); +} +DEFINE_SSE_SPLIT(instr_F20F59, safe_read64s, read_xmm64s) +void instr_F30F59(float_t source, int32_t r) { + // mulss xmm, xmm/mem32 + float_t destination = read_xmm_f32(r); + float result = source * destination; + write_xmm_f32(r, result); +} +DEFINE_SSE_SPLIT(instr_F30F59, fpu_load_m32, read_xmm_f32) + void instr_0F5A() { unimplemented_sse(); } void instr_0F5B() { unimplemented_sse(); } -void instr_0F5C() { unimplemented_sse(); } + +void instr_0F5C(union reg128 source, int32_t r) { + // subps xmm, xmm/mem128 + union reg128 destination = read_xmm128s(r); + union reg128 result = { + .f32 = { + destination.f32[0] - source.f32[0], + destination.f32[1] - source.f32[1], + destination.f32[2] - source.f32[2], + destination.f32[3] - source.f32[3], + } + }; + write_xmm_reg128(r, result); +} +DEFINE_SSE_SPLIT(instr_0F5C, safe_read128s, read_xmm128s) +void instr_660F5C(union reg128 source, int32_t r) { + // subpd xmm, xmm/mem128 + union reg128 destination = read_xmm128s(r); + union reg128 result = { + .f64 = { + destination.f64[0] - source.f64[0], + destination.f64[1] - source.f64[1], + } + }; + write_xmm_reg128(r, result); +} +DEFINE_SSE_SPLIT(instr_660F5C, safe_read128s, read_xmm128s) +void instr_F20F5C(union reg64 source, int32_t r) { + // subsd xmm, xmm/mem64 + union reg64 destination = read_xmm64s(r); + union reg64 result = { + .f64 = { destination.f64[0] - source.f64[0], } + }; + write_xmm64(r, result); +} +DEFINE_SSE_SPLIT(instr_F20F5C, safe_read64s, read_xmm64s) +void instr_F30F5C(float_t source, int32_t r) { + // subss xmm, xmm/mem32 + float_t destination = read_xmm_f32(r); + float result = destination - source; + write_xmm_f32(r, result); +} +DEFINE_SSE_SPLIT(instr_F30F5C, fpu_load_m32, read_xmm_f32) + void instr_0F5D() { unimplemented_sse(); } void instr_0F5E() { unimplemented_sse(); } void instr_0F5F() { unimplemented_sse(); } @@ -2261,7 +2448,49 @@ 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)) -void instr_0FC2() { unimplemented_sse(); } +void instr_0FC2(union reg128 source, int32_t r, int32_t imm8) { + // cmpps xmm, xmm/m128 + union reg128 destination = read_xmm128s(r); + union reg128 result = { + .i32 = { + sse_comparison(imm8, destination.f32[0], source.f32[0]) ? -1 : 0, + sse_comparison(imm8, destination.f32[1], source.f32[1]) ? -1 : 0, + sse_comparison(imm8, destination.f32[2], source.f32[2]) ? -1 : 0, + sse_comparison(imm8, destination.f32[3], source.f32[3]) ? -1 : 0, + } + }; + write_xmm_reg128(r, result); +} +DEFINE_SSE_SPLIT_IMM(instr_0FC2, safe_read128s, read_xmm128s) + +void instr_660FC2(union reg128 source, int32_t r, int32_t imm8) { + // cmppd xmm, xmm/m128 + union reg128 destination = read_xmm128s(r); + union reg128 result = { + .i64 = { + sse_comparison(imm8, destination.f64[0], source.f64[0]) ? -1 : 0, + sse_comparison(imm8, destination.f64[1], source.f64[1]) ? -1 : 0, + } + }; + write_xmm_reg128(r, result); +} +DEFINE_SSE_SPLIT_IMM(instr_660FC2, safe_read128s, read_xmm128s) +void instr_F20FC2(union reg64 source, int32_t r, int32_t imm8) { + // cmpsd xmm, xmm/m64 + union reg64 destination = read_xmm64s(r); + union reg64 result = { + .i64 = { sse_comparison(imm8, destination.f64[0], source.f64[0]) ? -1 : 0, } + }; + write_xmm64(r, result); +} +DEFINE_SSE_SPLIT_IMM(instr_F20FC2, safe_read64s, read_xmm64s) +void instr_F30FC2(float_t source, int32_t r, int32_t imm8) { + // cmpss xmm, xmm/m32 + float_t destination = read_xmm_f32(r); + int32_t result = sse_comparison(imm8, destination, source) ? -1 : 0; + write_xmm32(r, result); +} +DEFINE_SSE_SPLIT_IMM(instr_F30FC2, fpu_load_m32, read_xmm_f32) void instr_0FC3_reg(int32_t r1, int32_t r2) { trigger_ud(); } void instr_0FC3_mem(int32_t addr, int32_t r) { diff --git a/src/native/instructions_0f.h b/src/native/instructions_0f.h index 38c88a0b..3250e04f 100644 --- a/src/native/instructions_0f.h +++ b/src/native/instructions_0f.h @@ -174,7 +174,6 @@ void instr_0F29_mem(int32_t addr, int32_t r); void instr_0F29_reg(int32_t r1, int32_t r2); void instr_660F29_mem(int32_t addr, int32_t r); void instr_660F29_reg(int32_t r1, int32_t r2); -void instr_0F2A(void); void instr_0F2B_reg(int32_t r1, int32_t r2); void instr_0F2B_mem(int32_t addr, int32_t r); void instr_660F2B_reg(int32_t r1, int32_t r2); @@ -275,9 +274,6 @@ void instr_0F50_reg(int32_t r1, int32_t r2); void instr_0F50_mem(int32_t addr, int32_t r1); void instr_660F50_reg(int32_t r1, int32_t r2); void instr_660F50_mem(int32_t addr, int32_t r1); -void instr_0F51(void); -void instr_0F52(void); -void instr_0F53(void); void instr_0F54(union reg128 source, int32_t r); void instr_0F54_reg(int32_t r1, int32_t r2); void instr_0F54_mem(int32_t addr, int32_t r); @@ -302,14 +298,7 @@ void instr_0F57_mem(int32_t addr, int32_t r); void instr_660F57(union reg128 source, int32_t r); void instr_660F57_reg(int32_t r1, int32_t r2); void instr_660F57_mem(int32_t addr, int32_t r); -void instr_0F58(void); -void instr_0F59(void); -void instr_0F5A(void); -void instr_0F5B(void); -void instr_0F5C(void); -void instr_0F5D(void); -void instr_0F5E(void); -void instr_0F5F(void); + void instr_0F60(int32_t source, int32_t r); void instr_0F60_reg(int32_t r1, int32_t r2); void instr_0F60_mem(int32_t addr, int32_t r); @@ -699,7 +688,6 @@ void instr16_0FC1_mem(int32_t addr, int32_t r); void instr16_0FC1_reg(int32_t r1, int32_t r); void instr32_0FC1_mem(int32_t addr, int32_t r); void instr32_0FC1_reg(int32_t r1, int32_t r); -void instr_0FC2(void); void instr_0FC3_reg(int32_t r1, int32_t r2); void instr_0FC3_mem(int32_t addr, int32_t r); void instr_0FC4(int32_t source, int32_t r, int32_t imm8); diff --git a/src/native/sse_instr.c b/src/native/sse_instr.c index 058c05ee..aa2bba5c 100644 --- a/src/native/sse_instr.c +++ b/src/native/sse_instr.c @@ -398,3 +398,22 @@ void psllq_r128(int32_t r, uint32_t shift) write_xmm_reg128(r, result); } + +bool sse_comparison(int32_t op, double_t x, double_t y) +{ + // TODO: Signaling + + switch(op & 7) + { + case 0: return x == y; + case 1: return x < y; + case 2: return x <= y; + case 3: return isnan(x) || isnan(y); + case 4: return x != y || isnan(x) || isnan(y); + case 5: return x >= y || isnan(x) || isnan(y); + case 6: return x > y || isnan(x) || isnan(y); + case 7: return !isnan(x) && !isnan(y); + } + + assert(false); +} diff --git a/src/native/sse_instr.h b/src/native/sse_instr.h index 874f027e..5ab65359 100644 --- a/src/native/sse_instr.h +++ b/src/native/sse_instr.h @@ -31,3 +31,5 @@ void psrad_r128(int32_t r, uint32_t shift); void pslld_r128(int32_t r, uint32_t shift); void psrlq_r128(int32_t r, uint32_t shift); void psllq_r128(int32_t r, uint32_t shift); + +bool sse_comparison(int32_t op, double_t x, double_t y); diff --git a/tests/qemu/test-i386.c b/tests/qemu/test-i386.c index 3508213e..2e08a0ed 100644 --- a/tests/qemu/test-i386.c +++ b/tests/qemu/test-i386.c @@ -2791,7 +2791,6 @@ void test_sse(void) MOVMSK(movmskpd); /* FPU specific ops */ - /* { uint32_t mxcsr; asm volatile("stmxcsr %0" : "=m" (mxcsr)); @@ -2822,10 +2821,10 @@ void test_sse(void) SSE_OPS(add); SSE_OPS(mul); SSE_OPS(sub); - SSE_OPS(min); - SSE_OPS(div); - SSE_OPS(max); - SSE_OPS(sqrt); + //SSE_OPS(min); + //SSE_OPS(div); + //SSE_OPS(max); + //SSE_OPS(sqrt); SSE_OPS(cmpeq); SSE_OPS(cmplt); SSE_OPS(cmple); @@ -2847,10 +2846,10 @@ void test_sse(void) SSE_OPD(add); SSE_OPD(mul); SSE_OPD(sub); - SSE_OPD(min); - SSE_OPD(div); - SSE_OPD(max); - SSE_OPD(sqrt); + //SSE_OPD(min); + //SSE_OPD(div); + //SSE_OPD(max); + //SSE_OPD(sqrt); SSE_OPD(cmpeq); SSE_OPD(cmplt); SSE_OPD(cmple); @@ -2860,7 +2859,6 @@ void test_sse(void) SSE_OPD(cmpnle); SSE_OPD(cmpord); } - */ /* float to float/int */ /* From ae241fac7b921f0aa28cdb3c3a3cb209c3135c9a Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 29 Jul 2018 18:19:20 -0600 Subject: [PATCH 1111/2137] Replace todo() by undefined_instruction() --- src/browser/starter.js | 1 - src/cpu.js | 11 ----------- src/native/instructions_0f.c | 29 +++++++++++++---------------- src/native/js_imports.h | 1 - 4 files changed, 13 insertions(+), 29 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 9488618a..834d2a45 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -140,7 +140,6 @@ function V86Starter(options) "abort": function() { dbg_assert(false); }, "__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(); }, "_microtick": v86.microtick, diff --git a/src/cpu.js b/src/cpu.js index a2e7438e..b045d60b 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -2882,17 +2882,6 @@ CPU.prototype.hlt_op = function() } }; -CPU.prototype.todo = function() -{ - if(DEBUG) - { - dbg_trace(); - throw "TODO"; - } - - this.trigger_ud(); -}; - CPU.prototype.undefined_instruction = function() { dbg_assert(false, "Possible fault: undefined instruction"); diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 71b17601..2c211791 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -178,7 +178,7 @@ void instr_0F06() { void instr_0F07() { undefined_instruction(); } void instr_0F08() { // invd - todo(); + undefined_instruction(); } void instr_0F09() { @@ -203,7 +203,7 @@ void instr_0F0C() { undefined_instruction(); } void instr_0F0D() { // nop - todo(); + undefined_instruction(); } void instr_0F0E() { undefined_instruction(); } @@ -423,8 +423,8 @@ void instr_0F18_mem(int32_t addr, int32_t r) { // hintable nops void instr_0F19_reg(int32_t r1, int32_t r2) { } void instr_0F19_mem(int32_t addr, int32_t r) { } -void instr_0F1A() { todo(); trigger_ud(); } -void instr_0F1B() { todo(); trigger_ud(); } +void instr_0F1A() { undefined_instruction(); } +void instr_0F1B() { undefined_instruction(); } void instr_0F1C_reg(int32_t r1, int32_t r2) { } void instr_0F1C_mem(int32_t addr, int32_t r) { } void instr_0F1D_reg(int32_t r1, int32_t r2) { } @@ -459,8 +459,7 @@ void instr_0F20(int32_t r, int32_t creg) { break; default: dbg_log("%d", creg); - todo(); - trigger_ud(); + undefined_instruction(); } } @@ -550,8 +549,7 @@ void instr_0F22(int32_t r, int32_t creg) { default: dbg_log("%d", creg); - todo(); - trigger_ud(); + undefined_instruction(); } } void instr_0F23(int32_t r, int32_t dreg_index) { @@ -894,7 +892,7 @@ void instr_0F32() { void instr_0F33() { // rdpmc - todo(); + undefined_instruction(); } void instr_0F34() { @@ -978,7 +976,7 @@ void instr_0F36() { undefined_instruction(); } void instr_0F37() { // getsec - todo(); + undefined_instruction(); } // sse3+ @@ -2161,7 +2159,7 @@ void instr32_0FA9() { void instr_0FAA() { // rsm - todo(); + undefined_instruction(); } void instr16_0FAB_reg(int32_t r1, int32_t r2) { write_reg16(r1, bts_reg(read_reg16(r1), read_reg16(r2) & 15)); } @@ -2203,7 +2201,7 @@ void instr_0FAE_3_mem(int32_t addr) { void instr_0FAE_4_reg(int32_t r) { trigger_ud(); } void instr_0FAE_4_mem(int32_t addr) { // xsave - todo(); + undefined_instruction(); } void instr_0FAE_5_reg(int32_t r) { // lfence @@ -2211,7 +2209,7 @@ void instr_0FAE_5_reg(int32_t r) { } void instr_0FAE_5_mem(int32_t addr) { // xrstor - todo(); + undefined_instruction(); } void instr_0FAE_6_reg(int32_t r) { // mfence @@ -2227,7 +2225,7 @@ void instr_0FAE_7_reg(int32_t r) { } void instr_0FAE_7_mem(int32_t addr) { // clflush - todo(); + undefined_instruction(); } DEFINE_MODRM_INSTR_READ16(instr16_0FAF, write_reg16(r, imul_reg16(read_reg16(r) << 16 >> 16, ___ << 16 >> 16))) @@ -2591,8 +2589,7 @@ void instr_0FC7_6_reg(int32_t r) { flags_changed[0] = 0; } void instr_0FC7_6_mem(int32_t addr) { - todo(); - trigger_ud(); + undefined_instruction(); } void instr_0FC8() { bswap(EAX); } diff --git a/src/native/js_imports.h b/src/native/js_imports.h index dd2c4184..1d30df0a 100644 --- a/src/native/js_imports.h +++ b/src/native/js_imports.h @@ -44,7 +44,6 @@ extern void mmap_write32(uint32_t, int32_t); extern void mmap_write8(uint32_t, int32_t); extern void popa16(void); extern void popa32(void); -extern void todo(void); extern void undefined_instruction(void); extern void unimplemented_sse(void); extern void update_cs_size(int32_t); From becbc9ecff998f3a741a56a94847b99910adfe77 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 30 Jul 2018 17:01:13 -0500 Subject: [PATCH 1112/2137] Minor: Delete commented-out code --- src/rust/jit.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 9b150550..fbe9ab75 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -655,7 +655,6 @@ fn create_cache_entry(ctx: &mut JitState, entry: jit_cache_array::Entry) { // and use its slot for this entry. // TODO: Optimally, we should pick another slot instead of dropping // an entry has just been created. - //let old_page = Page::page_of(old_entry.start_addr); jit_cache_array::remove(found_entry_index); dbg_assert!(old_entry.next_index_same_page() == None); @@ -952,7 +951,6 @@ fn jit_generate_module( // - Unconditional jump let next_bb_index = *basic_block_indices.get(&next_block_addr).expect(""); - //dbg_assert!(next_bb_index != -1); // set state variable to next basic block builder.instruction_body.push_i32(next_bb_index as i32); @@ -1055,8 +1053,6 @@ fn jit_generate_basic_block( let mut was_block_boundary; let mut eip_delta = 0; - //*instruction_pointer = start_addr; - // First iteration of do-while assumes the caller confirms this condition dbg_assert!(!is_near_end_of_page(start_addr)); From 77525ef4accc6922dba669846c417487add78cb7 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 30 Jul 2018 17:02:48 -0500 Subject: [PATCH 1113/2137] Delete unused instructions --- src/native/instructions_0f.c | 4 ---- src/native/instructions_0f.h | 4 ---- 2 files changed, 8 deletions(-) diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 2c211791..c7e40dca 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1812,11 +1812,7 @@ void instr_660F72_6_reg(int32_t r, int32_t imm8) { } void instr_0F73_2_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_0F73_3_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_0F73_3_reg(int32_t addr, int32_t r) { trigger_ud(); } void instr_0F73_6_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_0F73_7_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_0F73_7_reg(int32_t addr, int32_t r) { trigger_ud(); } void instr_0F73_2_reg(int32_t r, int32_t imm8) { // psrlq mm, imm8 diff --git a/src/native/instructions_0f.h b/src/native/instructions_0f.h index 3250e04f..93d64430 100644 --- a/src/native/instructions_0f.h +++ b/src/native/instructions_0f.h @@ -433,11 +433,7 @@ void instr_660F72_2_reg(int32_t r, int32_t imm8); void instr_660F72_4_reg(int32_t r, int32_t imm8); void instr_660F72_6_reg(int32_t r, int32_t imm8); void instr_0F73_2_mem(int32_t addr, int32_t r); -void instr_0F73_3_mem(int32_t addr, int32_t r); -void instr_0F73_3_reg(int32_t addr, int32_t r); void instr_0F73_6_mem(int32_t addr, int32_t r); -void instr_0F73_7_mem(int32_t addr, int32_t r); -void instr_0F73_7_reg(int32_t addr, int32_t r); void instr_0F73_2_reg(int32_t r, int32_t imm8); void instr_0F73_6_reg(int32_t r, int32_t imm8); void instr_660F73_2_mem(int32_t addr, int32_t r); From 70ae4b720a2ef1b4476c54b099f2d8ea119e95a1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 30 Jul 2018 17:12:56 -0500 Subject: [PATCH 1114/2137] Remove use of raising cpu exceptions for trigger_ud --- gen/generate_jit.js | 17 +++- gen/x86_table.js | 163 ++++++++++++++++++----------------- src/cpu.js | 3 + src/native/cpu.c | 11 +-- src/native/instructions.c | 13 +-- src/native/instructions.h | 2 +- src/native/instructions_0f.c | 40 +++++---- tests/nasm/run.js | 35 ++------ 8 files changed, 138 insertions(+), 146 deletions(-) diff --git a/gen/generate_jit.js b/gen/generate_jit.js index fa62cd01..36f7185c 100755 --- a/gen/generate_jit.js +++ b/gen/generate_jit.js @@ -199,7 +199,8 @@ function gen_instruction_body_after_prefix(encodings, size) default_case: { body: [].concat( - gen_call(`::codegen::gen_fn0_const`, ["ctx", '"trigger_ud"']) + gen_call(`::codegen::gen_fn0_const`, ["ctx", '"trigger_ud"']), + "*instr_flags |= ::jit::JIT_INSTR_BLOCK_BOUNDARY_FLAG;" ), } }, @@ -245,6 +246,20 @@ function gen_instruction_body_after_fixed_g(encoding, size) const reg_postfix = encoding.nonfaulting ? [APPEND_NONFAULTING_FLAG] : []; const mem_postfix = encoding.memory_nonfaulting ? [APPEND_NONFAULTING_FLAG] : []; + if(encoding.mem_ud) + { + mem_postfix.push( + "*instr_flags |= ::jit::JIT_INSTR_BLOCK_BOUNDARY_FLAG;" + ); + } + + if(encoding.reg_ud) + { + reg_postfix.push( + "*instr_flags |= ::jit::JIT_INSTR_BLOCK_BOUNDARY_FLAG;" + ); + } + if(encoding.ignore_mod) { console.assert(!imm_read, "Unexpected instruction (ignore mod with immediate value)"); diff --git a/gen/x86_table.js b/gen/x86_table.js index a23de44c..d7b87eeb 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -72,7 +72,7 @@ const encodings = [ { opcode: 0x60, os: 1, }, { opcode: 0x61, os: 1, }, { opcode: 0x62, e: 1, skip: 1, }, - { opcode: 0x63, e: 1, }, + { opcode: 0x63, e: 1, block_boundary: 1, }, // arpl { opcode: 0x64, prefix: 1, }, { opcode: 0x65, prefix: 1, }, { opcode: 0x66, prefix: 1, }, @@ -106,8 +106,8 @@ const encodings = [ { opcode: 0x8A, nonfaulting: 1, e: 1, }, { opcode: 0x8B, custom: 1, nonfaulting: 1, os: 1, e: 1, }, - { opcode: 0x8C, os: 1, e: 1, skip: 1, }, - { opcode: 0x8D, memory_nonfaulting: 1, os: 1, e: 1, only_mem: 1, requires_prefix_call: 1, custom: 1, }, // lea + { opcode: 0x8C, block_boundary: 1, os: 1, e: 1, skip: 1, }, // mov reg, sreg: block_boundary as it can trigger #ud + { opcode: 0x8D, reg_ud: 1, memory_nonfaulting: 1, os: 1, e: 1, requires_prefix_call: 1, custom: 1, }, // lea { opcode: 0x8E, block_boundary: 1, e: 1, skip: 1, }, // mov sreg { opcode: 0x8F, os: 1, e: 1, fixed_g: 0, requires_prefix_call: 1, custom: 1, }, // pop r/m @@ -281,29 +281,29 @@ const encodings = [ { opcode: 0x0F01, fixed_g: 6, e: 1, skip: 1, block_boundary: 1, }, { opcode: 0x0F01, fixed_g: 7, e: 1, skip: 1, block_boundary: 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: 0x0F02, os: 1, e: 1, skip: 1, block_boundary: 1, }, // lar + { opcode: 0x0F03, os: 1, e: 1, skip: 1, block_boundary: 1, }, // lsl + { opcode: 0x0F04, skip: 1, block_boundary: 1, }, + { opcode: 0x0F05, skip: 1, block_boundary: 1, }, { opcode: 0x0F06, skip: 1, block_boundary: 1, }, // clts - { opcode: 0x0F07, skip: 1 }, - { opcode: 0x0F08, skip: 1 }, + { opcode: 0x0F07, skip: 1, block_boundary: 1, }, + { opcode: 0x0F08, skip: 1, block_boundary: 1, }, { opcode: 0x0F09, skip: 1, block_boundary: 1, }, // wbinvd - { opcode: 0x0F0A, skip: 1 }, + { opcode: 0x0F0A, skip: 1, block_boundary: 1, }, // ud2 // Technically has a next instruction, but Linux uses this for assertions // and embeds the assertion message after this instruction, which is likely // the most common use case of ud2 { opcode: 0x0F0B, skip: 1, block_boundary: 1, no_next_instruction: 1, }, - { opcode: 0x0F0C, skip: 1 }, - { opcode: 0x0F0D, skip: 1 }, - { opcode: 0x0F0E, skip: 1 }, - { opcode: 0x0F0F, skip: 1 }, + { opcode: 0x0F0C, skip: 1, block_boundary: 1, }, + { opcode: 0x0F0D, skip: 1, block_boundary: 1, }, + { opcode: 0x0F0E, skip: 1, block_boundary: 1, }, + { opcode: 0x0F0F, skip: 1, block_boundary: 1, }, - { opcode: 0x0F18, only_mem: 1, e: 1, }, + { opcode: 0x0F18, e: 1, }, { opcode: 0x0F19, non_faulting: 1, custom: 1, e: 1, }, - { opcode: 0x0F1A, skip: 1, }, - { opcode: 0x0F1B, skip: 1, }, + { opcode: 0x0F1A, skip: 1, block_boundary: 1, }, + { opcode: 0x0F1B, skip: 1, block_boundary: 1, }, { opcode: 0x0F1C, non_faulting: 1, custom: 1, e: 1, }, { opcode: 0x0F1D, non_faulting: 1, custom: 1, e: 1, }, { opcode: 0x0F1E, non_faulting: 1, custom: 1, e: 1, }, @@ -313,18 +313,18 @@ const encodings = [ { opcode: 0x0F21, ignore_mod: 1, e: 1, skip: 1, block_boundary: 1, }, // mov reg, dreg { opcode: 0x0F22, ignore_mod: 1, e: 1, skip: 1, block_boundary: 1, }, // mov creg, reg { opcode: 0x0F23, ignore_mod: 1, e: 1, skip: 1, block_boundary: 1, }, // mov dreg, reg - { opcode: 0x0F24, skip: 1 }, - { opcode: 0x0F25, skip: 1 }, - { opcode: 0x0F26, skip: 1 }, - { opcode: 0x0F27, skip: 1 }, + { opcode: 0x0F24, skip: 1, block_boundary: 1, }, + { opcode: 0x0F25, skip: 1, block_boundary: 1, }, + { opcode: 0x0F26, skip: 1, block_boundary: 1, }, + { opcode: 0x0F27, skip: 1, block_boundary: 1, }, { opcode: 0x0F30, skip: 1, block_boundary: 1, }, // wrmsr { opcode: 0x0F31, skip: 1, block_boundary: 1, }, // rdtsc { opcode: 0x0F32, skip: 1, block_boundary: 1, }, // rdmsr - { opcode: 0x0F33, skip: 1 }, + { opcode: 0x0F33, skip: 1, }, // rdpmc { opcode: 0x0F34, skip: 1, block_boundary: 1, no_next_instruction: 1, }, // sysenter { opcode: 0x0F35, skip: 1, block_boundary: 1, no_next_instruction: 1, }, // sysexit - { opcode: 0x0F36, skip: 1 }, + { opcode: 0x0F36, skip: 1, block_boundary: 1, }, { opcode: 0x0F37, skip: 1 }, { opcode: 0x0F38, skip: 1 }, { opcode: 0x0F39, skip: 1 }, @@ -412,27 +412,27 @@ const encodings = [ { opcode: 0x0FAC, nonfaulting: 1, os: 1, e: 1, imm8: 1, mask_flags: af | of, }, { opcode: 0x0FAD, nonfaulting: 1, os: 1, e: 1, mask_flags: af | of, }, - { opcode: 0x0FA6, skip: 1 }, - { opcode: 0x0FA7, skip: 1 }, + { opcode: 0x0FA6, skip: 1, block_boundary: 1, }, // ud + { opcode: 0x0FA7, skip: 1, block_boundary: 1, }, // ud { opcode: 0x0FAA, skip: 1 }, - { opcode: 0x0FAE, e: 1, fixed_g: 0, only_mem: 1, task_switch_test: 1, skip: 1, block_boundary: 1, }, // fxsave - { opcode: 0x0FAE, e: 1, fixed_g: 1, only_mem: 1, task_switch_test: 1, skip: 1, block_boundary: 1, }, // fxrstor: block_boundary since it uses non-raising cpu exceptions - { opcode: 0x0FAE, e: 1, fixed_g: 2, only_mem: 1, sse: 1, skip: 1, block_boundary: 1, }, // ldmxcsr - { opcode: 0x0FAE, e: 1, fixed_g: 3, only_mem: 1, sse: 1, skip: 1, block_boundary: 1, }, // stmxcsr - { opcode: 0x0FAE, e: 1, fixed_g: 4, only_mem: 1, skip: 1, }, + { opcode: 0x0FAE, e: 1, fixed_g: 0, reg_ud: 1, task_switch_test: 1, skip: 1, block_boundary: 1, }, // fxsave + { opcode: 0x0FAE, e: 1, fixed_g: 1, reg_ud: 1, task_switch_test: 1, skip: 1, block_boundary: 1, }, // fxrstor + { opcode: 0x0FAE, e: 1, fixed_g: 2, reg_ud: 1, sse: 1, skip: 1, block_boundary: 1, }, // ldmxcsr + { opcode: 0x0FAE, e: 1, fixed_g: 3, reg_ud: 1, sse: 1, skip: 1, block_boundary: 1, }, // stmxcsr - { 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: 0x0FAE, e: 1, fixed_g: 4, reg_ud: 1, skip: 1, block_boundary: 1, }, // xsave (mem, not implemented) + { opcode: 0x0FAE, e: 1, fixed_g: 5, skip: 1, block_boundary: 1, }, // lfence (reg, only 0), xrstor (mem, not implemented) + { opcode: 0x0FAE, e: 1, fixed_g: 6, skip: 1, block_boundary: 1, }, // mfence (reg, only 0), xsaveopt (mem, not implemented) + { opcode: 0x0FAE, e: 1, fixed_g: 7, skip: 1, block_boundary: 1, }, // sfence (reg, only 0), clflush (mem) { opcode: 0x0FAF, nonfaulting: 1, os: 1, e: 1, mask_flags: af | zf }, // imul { opcode: 0x0FB0, nonfaulting: 1, e: 1 }, // cmxchg { opcode: 0x0FB1, nonfaulting: 1, 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: 0x0FC7, e: 1, fixed_g: 1, reg_ud: 1, }, // cmpxchg8b (memory) + { opcode: 0x0FC7, e: 1, fixed_g: 6, mem_ud: 1, skip: 1, }, // rdrand { opcode: 0x0FB2, block_boundary: 1, os: 1, e: 1, skip: 1, }, // lss { opcode: 0x0FB4, block_boundary: 1, os: 1, e: 1, skip: 1, }, // lfs @@ -442,9 +442,9 @@ const encodings = [ { opcode: 0x0FB7, nonfaulting: 1, os: 1, e: 1, }, { opcode: 0xF30FB8, os: 1, e: 1 }, // popcnt - { opcode: 0x0FB8, os: 1, e: 1, }, // ud + { opcode: 0x0FB8, os: 1, e: 1, block_boundary: 1, }, // ud - { opcode: 0x0FB9, }, // ud2 + { opcode: 0x0FB9, block_boundary: 1, }, // ud2 { opcode: 0x0FBE, nonfaulting: 1, os: 1, e: 1, }, // movsx { opcode: 0x0FBF, nonfaulting: 1, os: 1, e: 1, }, @@ -475,20 +475,20 @@ const encodings = [ { sse: 1, opcode: 0x660F11, e: 1 }, { sse: 1, opcode: 0xF20F11, e: 1 }, { sse: 1, opcode: 0x0F12, e: 1 }, - { sse: 1, opcode: 0x660F12, only_mem: 1, e: 1 }, + { sse: 1, opcode: 0x660F12, reg_ud: 1, e: 1 }, { sse: 1, opcode: 0xF20F12, e: 1, skip: 1, }, // sse3 { sse: 1, opcode: 0xF30F12, e: 1, skip: 1, }, // sse3 - { sse: 1, opcode: 0x0F13, only_mem: 1, e: 1 }, - { sse: 1, opcode: 0x660F13, only_mem: 1, e: 1 }, + { sse: 1, opcode: 0x0F13, reg_ud: 1, e: 1 }, + { sse: 1, opcode: 0x660F13, reg_ud: 1, e: 1 }, { sse: 1, opcode: 0x0F14, e: 1 }, { sse: 1, opcode: 0x660F14, e: 1 }, { sse: 1, opcode: 0x0F15, e: 1 }, { sse: 1, opcode: 0x660F15, e: 1 }, { sse: 1, opcode: 0x0F16, e: 1 }, - { sse: 1, opcode: 0x660F16, only_mem: 1, e: 1 }, + { sse: 1, opcode: 0x660F16, reg_ud: 1, e: 1 }, { sse: 1, opcode: 0xF30F16, skip: 1, }, // sse3 - { sse: 1, opcode: 0x0F17, only_mem: 1, e: 1 }, - { sse: 1, opcode: 0x660F17, only_mem: 1, e: 1 }, + { sse: 1, opcode: 0x0F17, reg_ud: 1, e: 1 }, + { sse: 1, opcode: 0x660F17, reg_ud: 1, e: 1 }, { sse: 1, opcode: 0x0F28, e: 1 }, { sse: 1, opcode: 0x660F28, e: 1 }, @@ -498,8 +498,8 @@ const encodings = [ { sse: 1, opcode: 0x660F2A, e: 1, }, { sse: 1, opcode: 0xF20F2A, e: 1, }, { sse: 1, opcode: 0xF30F2A, e: 1, }, - { sse: 1, opcode: 0x0F2B, only_mem: 1, e: 1 }, - { sse: 1, opcode: 0x660F2B, only_mem: 1, e: 1 }, + { sse: 1, opcode: 0x0F2B, reg_ud: 1, e: 1 }, + { sse: 1, opcode: 0x660F2B, reg_ud: 1, e: 1 }, { sse: 1, opcode: 0xF20F2C, e: 1, }, { sse: 1, opcode: 0x0F2C, e: 1, skip: 1, }, @@ -509,8 +509,8 @@ const encodings = [ { sse: 1, opcode: 0x0F2E, skip: 1 }, { sse: 1, opcode: 0x0F2F, skip: 1 }, - { sse: 1, opcode: 0x0F50, only_reg: 1, e: 1 }, - { sse: 1, opcode: 0x660F50, only_reg: 1, e: 1 }, + { sse: 1, opcode: 0x0F50, mem_ud: 1, e: 1 }, + { sse: 1, opcode: 0x660F50, mem_ud: 1, e: 1 }, { sse: 1, opcode: 0x0F51, skip: 1 }, { sse: 1, opcode: 0x0F52, skip: 1 }, @@ -574,9 +574,9 @@ const encodings = [ { sse: 1, opcode: 0x660F6B, e: 1 }, { sse: 1, opcode: 0x0F6B, e: 1 }, { sse: 1, opcode: 0x660F6C, e: 1 }, - { sse: 1, opcode: 0x0F6C, e: 1, }, // ud + { sse: 1, opcode: 0x0F6C, e: 1, block_boundary: 1, }, // ud { sse: 1, opcode: 0x660F6D, e: 1 }, - { sse: 1, opcode: 0x0F6D, e: 1, }, // ud + { sse: 1, opcode: 0x0F6D, e: 1, block_boundary: 1, }, // ud { sse: 1, opcode: 0x660F6E, e: 1 }, { sse: 1, opcode: 0x0F6E, e: 1 }, { sse: 1, opcode: 0xF30F6F, e: 1 }, @@ -588,26 +588,26 @@ const encodings = [ { sse: 1, opcode: 0xF20F70, e: 1, imm8: 1, }, { sse: 1, opcode: 0xF30F70, e: 1, imm8: 1, }, - { sse: 1, opcode: 0x0F71, e: 1, fixed_g: 2, imm8: 1, only_reg: 1, }, - { sse: 1, opcode: 0x660F71, e: 1, fixed_g: 2, imm8: 1, only_reg: 1 }, - { sse: 1, opcode: 0x0F71, e: 1, fixed_g: 4, imm8: 1, only_reg: 1, }, - { sse: 1, opcode: 0x660F71, e: 1, fixed_g: 4, imm8: 1, only_reg: 1 }, - { sse: 1, opcode: 0x0F71, e: 1, fixed_g: 6, imm8: 1, only_reg: 1, }, - { sse: 1, opcode: 0x660F71, e: 1, fixed_g: 6, imm8: 1, only_reg: 1 }, + { sse: 1, opcode: 0x0F71, e: 1, fixed_g: 2, imm8: 1, mem_ud: 1, }, + { sse: 1, opcode: 0x660F71, e: 1, fixed_g: 2, imm8: 1, mem_ud: 1 }, + { sse: 1, opcode: 0x0F71, e: 1, fixed_g: 4, imm8: 1, mem_ud: 1, }, + { sse: 1, opcode: 0x660F71, e: 1, fixed_g: 4, imm8: 1, mem_ud: 1 }, + { sse: 1, opcode: 0x0F71, e: 1, fixed_g: 6, imm8: 1, mem_ud: 1, }, + { sse: 1, opcode: 0x660F71, e: 1, fixed_g: 6, imm8: 1, mem_ud: 1 }, - { sse: 1, opcode: 0x0F72, e: 1, fixed_g: 2, imm8: 1, only_reg: 1, }, - { sse: 1, opcode: 0x660F72, e: 1, fixed_g: 2, imm8: 1, only_reg: 1 }, - { sse: 1, opcode: 0x0F72, e: 1, fixed_g: 4, imm8: 1, only_reg: 1, }, - { sse: 1, opcode: 0x660F72, e: 1, fixed_g: 4, imm8: 1, only_reg: 1 }, - { sse: 1, opcode: 0x0F72, e: 1, fixed_g: 6, imm8: 1, only_reg: 1, }, - { sse: 1, opcode: 0x660F72, e: 1, fixed_g: 6, imm8: 1, only_reg: 1 }, + { sse: 1, opcode: 0x0F72, e: 1, fixed_g: 2, imm8: 1, mem_ud: 1, }, + { sse: 1, opcode: 0x660F72, e: 1, fixed_g: 2, imm8: 1, mem_ud: 1 }, + { sse: 1, opcode: 0x0F72, e: 1, fixed_g: 4, imm8: 1, mem_ud: 1, }, + { sse: 1, opcode: 0x660F72, e: 1, fixed_g: 4, imm8: 1, mem_ud: 1 }, + { sse: 1, opcode: 0x0F72, e: 1, fixed_g: 6, imm8: 1, mem_ud: 1, }, + { sse: 1, opcode: 0x660F72, e: 1, fixed_g: 6, imm8: 1, mem_ud: 1 }, - { sse: 1, opcode: 0x0F73, e: 1, fixed_g: 2, imm8: 1, only_reg: 1, }, - { sse: 1, opcode: 0x660F73, e: 1, fixed_g: 2, imm8: 1, only_reg: 1, }, - { sse: 1, opcode: 0x660F73, e: 1, fixed_g: 3, imm8: 1, only_reg: 1 }, - { sse: 1, opcode: 0x0F73, e: 1, fixed_g: 6, imm8: 1, only_reg: 1, }, - { sse: 1, opcode: 0x660F73, e: 1, fixed_g: 6, imm8: 1, only_reg: 1 }, - { sse: 1, opcode: 0x660F73, e: 1, fixed_g: 7, imm8: 1, only_reg: 1 }, + { sse: 1, opcode: 0x0F73, e: 1, fixed_g: 2, imm8: 1, mem_ud: 1, }, + { sse: 1, opcode: 0x660F73, e: 1, fixed_g: 2, imm8: 1, mem_ud: 1, }, + { sse: 1, opcode: 0x660F73, e: 1, fixed_g: 3, imm8: 1, mem_ud: 1 }, + { sse: 1, opcode: 0x0F73, e: 1, fixed_g: 6, imm8: 1, mem_ud: 1, }, + { sse: 1, opcode: 0x660F73, e: 1, fixed_g: 6, imm8: 1, mem_ud: 1 }, + { sse: 1, opcode: 0x660F73, e: 1, fixed_g: 7, imm8: 1, mem_ud: 1 }, { sse: 1, opcode: 0x0F74, e: 1, }, { sse: 1, opcode: 0x660F74, e: 1, }, @@ -638,12 +638,12 @@ const encodings = [ { sse: 1, opcode: 0xF20FC2, e: 1, imm8: 1 }, { sse: 1, opcode: 0xF30FC2, e: 1, imm8: 1 }, - { opcode: 0x0FC3, e: 1, only_mem: 1, }, // movnti: Uses normal registers, hence not marked as sse + { opcode: 0x0FC3, e: 1, reg_ud: 1, }, // movnti: Uses normal registers, hence not marked as sse { sse: 1, opcode: 0x0FC4, e: 1, imm8: 1 }, { sse: 1, opcode: 0x660FC4, e: 1, imm8: 1 }, - { sse: 1, opcode: 0x0FC5, e: 1, only_reg: 1, imm8: 1 }, - { sse: 1, opcode: 0x660FC5, e: 1, only_reg: 1, imm8: 1, }, + { sse: 1, opcode: 0x0FC5, e: 1, mem_ud: 1, imm8: 1 }, + { sse: 1, opcode: 0x660FC5, e: 1, mem_ud: 1, imm8: 1, }, { sse: 1, opcode: 0x0FC6, skip: 1, }, @@ -661,11 +661,12 @@ const encodings = [ { sse: 1, opcode: 0x660FD5, e: 1 }, { sse: 1, opcode: 0x660FD6, e: 1 }, - { sse: 1, opcode: 0xF20FD6, only_reg: 1, e: 1 }, - { sse: 1, opcode: 0xF30FD6, only_reg: 1, e: 1 }, - { sse: 1, opcode: 0x0FD6, e: 1, }, // ud - { sse: 1, opcode: 0x0FD7, e: 1, only_reg: 1 }, - { sse: 1, opcode: 0x660FD7, e: 1, only_reg: 1, }, + { sse: 1, opcode: 0xF20FD6, mem_ud: 1, e: 1 }, + { sse: 1, opcode: 0xF30FD6, mem_ud: 1, e: 1 }, + { sse: 1, opcode: 0x0FD6, e: 1, block_boundary: 1, }, // ud + + { sse: 1, opcode: 0x0FD7, e: 1, mem_ud: 1 }, + { sse: 1, opcode: 0x660FD7, e: 1, mem_ud: 1, }, { sse: 1, opcode: 0x0FD8, e: 1 }, { sse: 1, opcode: 0x660FD8, e: 1 }, @@ -700,9 +701,9 @@ const encodings = [ { sse: 1, opcode: 0x660FE6, e: 1, skip: 1, }, { sse: 1, opcode: 0xF20FE6, e: 1, skip: 1, }, { sse: 1, opcode: 0xF30FE6, e: 1, skip: 1, }, - { sse: 1, opcode: 0x0FE6, e: 1, }, // ud - { sse: 1, opcode: 0x0FE7, e: 1, only_mem: 1 }, - { sse: 1, opcode: 0x660FE7, e: 1, only_mem: 1, }, + { sse: 1, opcode: 0x0FE6, e: 1, block_boundary: 1, }, // ud + { sse: 1, opcode: 0x0FE7, e: 1, reg_ud: 1 }, + { sse: 1, opcode: 0x660FE7, e: 1, reg_ud: 1, }, { sse: 1, opcode: 0x0FE8, e: 1 }, { sse: 1, opcode: 0x660FE8, e: 1 }, @@ -737,8 +738,8 @@ const encodings = [ { sse: 1, opcode: 0x660FF6, e: 1 }, // maskmovq (0FF7), maskmovdqu (660FF7) tested manually // Generated tests don't setup EDI as required (yet) - { sse: 1, opcode: 0x0FF7, only_reg: 1, e: 1, skip: 1, }, - { sse: 1, opcode: 0x660FF7, only_reg: 1, e: 1, skip: 1, }, + { sse: 1, opcode: 0x0FF7, mem_ud: 1, e: 1, skip: 1, }, + { sse: 1, opcode: 0x660FF7, mem_ud: 1, e: 1, skip: 1, }, { sse: 1, opcode: 0x0FF8, e: 1 }, { sse: 1, opcode: 0x660FF8, e: 1 }, @@ -755,7 +756,7 @@ const encodings = [ { sse: 1, opcode: 0x0FFE, e: 1 }, { sse: 1, opcode: 0x660FFE, e: 1 }, - { opcode: 0x0FFF, }, + { opcode: 0x0FFF, block_boundary: 1, }, // ud ]; for(let i = 0; i < 8; i++) diff --git a/src/cpu.js b/src/cpu.js index b045d60b..ec3f6fbf 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -3486,6 +3486,7 @@ CPU.prototype.arpl = function(seg, r16) if(!this.protected_mode[0] || this.vm86_mode()) { this.trigger_ud(); + return; } this.flags_changed[0] &= ~flag_zero; @@ -3513,6 +3514,7 @@ CPU.prototype.lar = function(selector, original) { dbg_log("lar #ud"); this.trigger_ud(); + return; } /** @const */ @@ -3550,6 +3552,7 @@ CPU.prototype.lsl = function(selector, original) { dbg_log("lsl #ud"); this.trigger_ud(); + return; } /** @const */ diff --git a/src/native/cpu.c b/src/native/cpu.c index 9c54ed6a..567b8eb9 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -828,15 +828,6 @@ void trigger_de() __attribute__((noinline)) void trigger_ud() -{ - dbg_log("#ud"); - dbg_trace(); - *instruction_pointer = *previous_ip; - raise_exception(CPU_EXCEPTION_UD); -} - -__attribute__((noinline)) -void trigger_ud_non_raising() { dbg_log("#ud"); dbg_trace(); @@ -1513,7 +1504,7 @@ bool task_switch_test_mmx() } else if(*cr & CR0_EM) { - trigger_ud_non_raising(); + trigger_ud(); return false; } diff --git a/src/native/instructions.c b/src/native/instructions.c index b0b59ba6..bbdbe069 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -418,17 +418,20 @@ 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, ___)) -void instr_8C_check_sreg(int32_t sreg) { +bool instr_8C_check_sreg(int32_t sreg) { if(sreg >= 6) { dbg_log("mov sreg #ud"); trigger_ud(); + return false; } + + return true; } -void instr16_8C_reg(int32_t r, int32_t seg) { instr_8C_check_sreg(seg); write_reg16(r, sreg[seg]); } -void instr16_8C_mem(int32_t addr, int32_t seg) { instr_8C_check_sreg(seg); safe_write16(addr, sreg[seg]); } -void instr32_8C_reg(int32_t r, int32_t seg) { instr_8C_check_sreg(seg); write_reg32(r, sreg[seg]); } -void instr32_8C_mem(int32_t addr, int32_t seg) { instr_8C_check_sreg(seg); safe_write32(addr, sreg[seg]); } +void instr16_8C_reg(int32_t r, int32_t seg) { if(instr_8C_check_sreg(seg)) write_reg16(r, sreg[seg]); } +void instr16_8C_mem(int32_t addr, int32_t seg) { if(instr_8C_check_sreg(seg)) safe_write16(addr, sreg[seg]); } +void instr32_8C_reg(int32_t r, int32_t seg) { if(instr_8C_check_sreg(seg)) write_reg32(r, sreg[seg]); } +void instr32_8C_mem(int32_t addr, int32_t seg) { if(instr_8C_check_sreg(seg)) safe_write32(addr, sreg[seg]); } void instr16_8D_reg(int32_t r, int32_t r2) { diff --git a/src/native/instructions.h b/src/native/instructions.h index d711a224..43c66a62 100644 --- a/src/native/instructions.h +++ b/src/native/instructions.h @@ -491,7 +491,7 @@ void instr16_8B_mem(int32_t addr, int32_t r); void instr16_8B_reg(int32_t r1, int32_t r); void instr32_8B_mem(int32_t addr, int32_t r); void instr32_8B_reg(int32_t r1, int32_t r); -void instr_8C_check_sreg(int32_t sreg); +bool instr_8C_check_sreg(int32_t sreg); void instr16_8C_reg(int32_t r, int32_t seg); void instr16_8C_mem(int32_t addr, int32_t seg); void instr32_8C_reg(int32_t r, int32_t seg); diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index c7e40dca..d0ce4e7c 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -24,58 +24,58 @@ bool apic_enabled = false; void instr_0F00_0_mem(int32_t addr) { // sldt - if(!protected_mode[0] || vm86_mode()) trigger_ud(); + if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } safe_write16(addr, sreg[LDTR]); } void instr_0F00_0_reg(int32_t r) { - if(!protected_mode[0] || vm86_mode()) trigger_ud(); + if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } write_reg_osize(r, sreg[LDTR]); } void instr_0F00_1_mem(int32_t addr) { // str - if(!protected_mode[0] || vm86_mode()) trigger_ud(); + if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } safe_write16(addr, sreg[TR]); } void instr_0F00_1_reg(int32_t r) { - if(!protected_mode[0] || vm86_mode()) trigger_ud(); + if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } write_reg_osize(r, sreg[TR]); } void instr_0F00_2_mem(int32_t addr) { // lldt - if(!protected_mode[0] || vm86_mode()) trigger_ud(); + if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } if(cpl[0]) { trigger_gp_non_raising(0); return; } load_ldt(safe_read16(addr)); } void instr_0F00_2_reg(int32_t r) { - if(!protected_mode[0] || vm86_mode()) trigger_ud(); + if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } if(cpl[0]) { trigger_gp_non_raising(0); return; } load_ldt(read_reg16(r)); } void instr_0F00_3_mem(int32_t addr) { // ltr - if(!protected_mode[0] || vm86_mode()) trigger_ud(); + if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } if(cpl[0]) { trigger_gp_non_raising(0); return; } load_tr(safe_read16(addr)); } void instr_0F00_3_reg(int32_t r) { - if(!protected_mode[0] || vm86_mode()) trigger_ud(); + if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } if(cpl[0]) { trigger_gp_non_raising(0); return; } load_tr(read_reg16(r)); } void instr_0F00_4_mem(int32_t addr) { - if(!protected_mode[0] || vm86_mode()) trigger_ud(); + if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } verr(safe_read16(addr)); } void instr_0F00_4_reg(int32_t r) { - if(!protected_mode[0] || vm86_mode()) trigger_ud(); + if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } verr(read_reg16(r)); } void instr_0F00_5_mem(int32_t addr) { - if(!protected_mode[0] || vm86_mode()) trigger_ud(); + if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } verw(safe_read16(addr)); } void instr_0F00_5_reg(int32_t r) { - if(!protected_mode[0] || vm86_mode()) trigger_ud(); + if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } verw(read_reg16(r)); } @@ -316,7 +316,7 @@ void instr_0F13_mem(int32_t addr, int32_t r) { movl_r128_m64(addr, r); } -void instr_0F13_reg(int32_t r1, int32_t r2) { unimplemented_sse(); } +void instr_0F13_reg(int32_t r1, int32_t r2) { trigger_ud(); } void instr_660F13_reg(int32_t r1, int32_t r) { trigger_ud(); } void instr_660F13_mem(int32_t addr, int32_t r) { @@ -414,7 +414,9 @@ void instr_660F17_mem(int32_t addr, int32_t r) { } void instr_660F17_reg(int32_t r1, int32_t r2) { trigger_ud(); } -void instr_0F18_reg(int32_t r1, int32_t r2) { trigger_ud(); } +void instr_0F18_reg(int32_t r1, int32_t r2) { + // reserved nop +} void instr_0F18_mem(int32_t addr, int32_t r) { // prefetch // nop for us @@ -476,6 +478,7 @@ void instr_0F21(int32_t r, int32_t dreg_index) { { dbg_log("#ud mov dreg 4/5 with cr4.DE set"); trigger_ud(); + return; } else { @@ -565,6 +568,7 @@ void instr_0F23(int32_t r, int32_t dreg_index) { { dbg_log("#ud mov dreg 4/5 with cr4.DE set"); trigger_ud(); + return; } else { @@ -2176,7 +2180,7 @@ void instr_0FAE_1_reg(int32_t r) { trigger_ud(); } void instr_0FAE_1_mem(int32_t addr) { fxrstor(addr); } -void instr_0FAE_2_reg(int32_t r) { trigger_ud(); } +void instr_0FAE_2_reg(int32_t r) { unimplemented_sse(); } void instr_0FAE_2_mem(int32_t addr) { // ldmxcsr int32_t new_mxcsr = safe_read32s(addr); @@ -2212,8 +2216,8 @@ void instr_0FAE_6_reg(int32_t r) { dbg_assert_message(r == 0, "Unexpected mfence encoding"); } void instr_0FAE_6_mem(int32_t addr) { - dbg_assert_message(false, "0fae/5 #ud"); - trigger_ud(); + // xsaveopt + undefined_instruction(); } void instr_0FAE_7_reg(int32_t r) { // sfence @@ -2585,7 +2589,7 @@ void instr_0FC7_6_reg(int32_t r) { flags_changed[0] = 0; } void instr_0FC7_6_mem(int32_t addr) { - undefined_instruction(); + trigger_ud(); } void instr_0FC8() { bswap(EAX); } diff --git a/tests/nasm/run.js b/tests/nasm/run.js index 661e5db6..56b75296 100755 --- a/tests/nasm/run.js +++ b/tests/nasm/run.js @@ -284,36 +284,11 @@ else { process.exit(1); } - if(exception === "DE" || exception === "GP") - { - // XXX: On gdb execution is stopped at this point. On v86 we - // currently don't have this ability, so we record the exception - // and continue execution - recorded_exceptions.push(exception); - return true; - } - - clearTimeout(test_timeout); - - waiting_to_receive_next_test = true; - emulator.stop(); - - 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); - } - + // XXX: On gdb execution is stopped at this point. On v86 we + // currently don't have this ability, so we record the exception + // and continue execution + console.log("recorded", exception); + recorded_exceptions.push(exception); return true; }; From c10bbca85eac313c7adcdb4d1325eb23945b05d4 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 30 Jul 2018 17:48:47 -0500 Subject: [PATCH 1115/2137] Add sqrt{p,s}{d,s} instructions (#57) --- gen/x86_table.js | 5 ++++- src/native/instructions_0f.c | 39 +++++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index d7b87eeb..46a2b403 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -511,7 +511,10 @@ const encodings = [ { sse: 1, opcode: 0x0F50, mem_ud: 1, e: 1 }, { sse: 1, opcode: 0x660F50, mem_ud: 1, e: 1 }, - { sse: 1, opcode: 0x0F51, skip: 1 }, + { sse: 1, opcode: 0x0F51, e: 1 }, + { sse: 1, opcode: 0x660F51, e: 1 }, + { sse: 1, opcode: 0xF20F51, e: 1 }, + { sse: 1, opcode: 0xF30F51, e: 1 }, { sse: 1, opcode: 0x0F52, skip: 1 }, // reciprocal: approximation of 1/x. Skipped because our approximation doesn't match intel's diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index d0ce4e7c..da5e1079 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1046,7 +1046,44 @@ void instr_660F50_reg(int32_t r1, int32_t r2) { } void instr_660F50_mem(int32_t addr, int32_t r1) { trigger_ud(); } -void instr_0F51() { unimplemented_sse(); } +void instr_0F51(union reg128 source, int32_t r) { + // sqrtps xmm, xmm/mem128 + union reg128 result = { + .f32 = { + sqrtf(source.f32[0]), + sqrtf(source.f32[1]), + sqrtf(source.f32[2]), + sqrtf(source.f32[3]), + } + }; + write_xmm_reg128(r, result); +} +DEFINE_SSE_SPLIT(instr_0F51, safe_read128s, read_xmm128s) +void instr_660F51(union reg128 source, int32_t r) { + // sqrtpd xmm, xmm/mem128 + union reg128 result = { + .f64 = { + sqrt(source.f64[0]), + sqrt(source.f64[1]), + } + }; + write_xmm_reg128(r, result); +} +DEFINE_SSE_SPLIT(instr_660F51, safe_read128s, read_xmm128s) +void instr_F20F51(union reg64 source, int32_t r) { + // sqrtsd xmm, xmm/mem64 + union reg64 result = { + .f64 = { sqrt(source.f64[0]), } + }; + write_xmm64(r, result); +} +DEFINE_SSE_SPLIT(instr_F20F51, safe_read64s, read_xmm64s) +void instr_F30F51(float_t source, int32_t r) { + // sqrtss xmm, xmm/mem32 + write_xmm_f32(r, sqrtf(source)); +} +DEFINE_SSE_SPLIT(instr_F30F51, fpu_load_m32, read_xmm_f32) + void instr_0F52() { unimplemented_sse(); } void instr_0F53(union reg128 source, int32_t r) { From 6fa702c8aa2e0ad477df98ce0bf7bcce679aedee Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 30 Jul 2018 18:00:34 -0500 Subject: [PATCH 1116/2137] Implement {min,max,div}{p,s}{s,d} sse instructions (#57) --- gen/x86_table.js | 27 +++++--- src/native/instructions_0f.c | 131 ++++++++++++++++++++++++++++++++++- src/native/sse_instr.c | 12 ++++ src/native/sse_instr.h | 2 + tests/qemu/test-i386.c | 16 ++--- 5 files changed, 168 insertions(+), 20 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 46a2b403..ae4b412c 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -531,25 +531,34 @@ const encodings = [ { sse: 1, opcode: 0x660F57, e: 1 }, { sse: 1, opcode: 0x0F58, e: 1, }, - { sse: 1, opcode: 0x660F58, e: 1, }, + { sse: 1, opcode: 0x660F58, e: 1, }, { sse: 1, opcode: 0xF20F58, e: 1, }, { sse: 1, opcode: 0xF30F58, e: 1, }, - { sse: 1, opcode: 0x0F59, e: 1, }, - { sse: 1, opcode: 0x660F59, e: 1, }, + { sse: 1, opcode: 0x660F59, e: 1, }, { sse: 1, opcode: 0xF20F59, e: 1, }, { sse: 1, opcode: 0xF30F59, e: 1, }, - { sse: 1, opcode: 0x0F5A, skip: 1 }, - { sse: 1, opcode: 0x0F5B, skip: 1 }, + { sse: 1, opcode: 0x0F5A, skip: 1, }, + { sse: 1, opcode: 0x0F5B, skip: 1, }, { sse: 1, opcode: 0x0F5C, e: 1, }, - { sse: 1, opcode: 0x660F5C, e: 1, }, + { sse: 1, opcode: 0x660F5C, e: 1, }, { sse: 1, opcode: 0xF20F5C, e: 1, }, { sse: 1, opcode: 0xF30F5C, e: 1, }, - { sse: 1, opcode: 0x0F5D, skip: 1, }, - { sse: 1, opcode: 0x0F5E, skip: 1, }, - { sse: 1, opcode: 0x0F5F, skip: 1, }, + { sse: 1, opcode: 0x0F5D, e: 1, }, + { sse: 1, opcode: 0x660F5D, e: 1, }, + { sse: 1, opcode: 0xF20F5D, e: 1, }, + { sse: 1, opcode: 0xF30F5D, e: 1, }, + + { sse: 1, opcode: 0x0F5E, e: 1, }, + { sse: 1, opcode: 0x660F5E, e: 1, }, + { sse: 1, opcode: 0xF20F5E, e: 1, }, + { sse: 1, opcode: 0xF30F5E, e: 1, }, + { sse: 1, opcode: 0x0F5F, e: 1, }, + { sse: 1, opcode: 0x660F5F, e: 1, }, + { sse: 1, opcode: 0xF20F5F, e: 1, }, + { sse: 1, opcode: 0xF30F5F, e: 1, }, { sse: 1, opcode: 0x660F60, e: 1 }, { sse: 1, opcode: 0x0F60, e: 1 }, diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index da5e1079..b2efafc1 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1294,9 +1294,134 @@ void instr_F30F5C(float_t source, int32_t r) { } DEFINE_SSE_SPLIT(instr_F30F5C, fpu_load_m32, read_xmm_f32) -void instr_0F5D() { unimplemented_sse(); } -void instr_0F5E() { unimplemented_sse(); } -void instr_0F5F() { unimplemented_sse(); } +void instr_0F5D(union reg128 source, int32_t r) { + // minps xmm, xmm/mem128 + union reg128 destination = read_xmm128s(r); + union reg128 result = { + .f32 = { + sse_min(destination.f32[0], source.f32[0]), + sse_min(destination.f32[1], source.f32[1]), + sse_min(destination.f32[2], source.f32[2]), + sse_min(destination.f32[3], source.f32[3]), + } + }; + write_xmm_reg128(r, result); +} +DEFINE_SSE_SPLIT(instr_0F5D, safe_read128s, read_xmm128s) +void instr_660F5D(union reg128 source, int32_t r) { + // minpd xmm, xmm/mem128 + union reg128 destination = read_xmm128s(r); + union reg128 result = { + .f64 = { + sse_min(destination.f64[0], source.f64[0]), + sse_min(destination.f64[1], source.f64[1]), + } + }; + write_xmm_reg128(r, result); +} +DEFINE_SSE_SPLIT(instr_660F5D, safe_read128s, read_xmm128s) +void instr_F20F5D(union reg64 source, int32_t r) { + // minsd xmm, xmm/mem64 + union reg64 destination = read_xmm64s(r); + union reg64 result = { + .f64 = { sse_min(destination.f64[0], source.f64[0]), } + }; + write_xmm64(r, result); +} +DEFINE_SSE_SPLIT(instr_F20F5D, safe_read64s, read_xmm64s) +void instr_F30F5D(float_t source, int32_t r) { + // minss xmm, xmm/mem32 + float_t destination = read_xmm_f32(r); + float result = sse_min(destination, source); + write_xmm_f32(r, result); +} +DEFINE_SSE_SPLIT(instr_F30F5D, fpu_load_m32, read_xmm_f32) + +void instr_0F5E(union reg128 source, int32_t r) { + // divps xmm, xmm/mem128 + union reg128 destination = read_xmm128s(r); + union reg128 result = { + .f32 = { + destination.f32[0] / source.f32[0], + destination.f32[1] / source.f32[1], + destination.f32[2] / source.f32[2], + destination.f32[3] / source.f32[3], + } + }; + write_xmm_reg128(r, result); +} +DEFINE_SSE_SPLIT(instr_0F5E, safe_read128s, read_xmm128s) +void instr_660F5E(union reg128 source, int32_t r) { + // divpd xmm, xmm/mem128 + union reg128 destination = read_xmm128s(r); + union reg128 result = { + .f64 = { + destination.f64[0] / source.f64[0], + destination.f64[1] / source.f64[1], + } + }; + write_xmm_reg128(r, result); +} +DEFINE_SSE_SPLIT(instr_660F5E, safe_read128s, read_xmm128s) +void instr_F20F5E(union reg64 source, int32_t r) { + // divsd xmm, xmm/mem64 + union reg64 destination = read_xmm64s(r); + union reg64 result = { + .f64 = { destination.f64[0] / source.f64[0], } + }; + write_xmm64(r, result); +} +DEFINE_SSE_SPLIT(instr_F20F5E, safe_read64s, read_xmm64s) +void instr_F30F5E(float_t source, int32_t r) { + // divss xmm, xmm/mem32 + float_t destination = read_xmm_f32(r); + float result = destination / source; + write_xmm_f32(r, result); +} +DEFINE_SSE_SPLIT(instr_F30F5E, fpu_load_m32, read_xmm_f32) + +void instr_0F5F(union reg128 source, int32_t r) { + // maxps xmm, xmm/mem128 + union reg128 destination = read_xmm128s(r); + union reg128 result = { + .f32 = { + sse_max(destination.f32[0], source.f32[0]), + sse_max(destination.f32[1], source.f32[1]), + sse_max(destination.f32[2], source.f32[2]), + sse_max(destination.f32[3], source.f32[3]), + } + }; + write_xmm_reg128(r, result); +} +DEFINE_SSE_SPLIT(instr_0F5F, safe_read128s, read_xmm128s) +void instr_660F5F(union reg128 source, int32_t r) { + // maxpd xmm, xmm/mem128 + union reg128 destination = read_xmm128s(r); + union reg128 result = { + .f64 = { + sse_max(destination.f64[0], source.f64[0]), + sse_max(destination.f64[1], source.f64[1]), + } + }; + write_xmm_reg128(r, result); +} +DEFINE_SSE_SPLIT(instr_660F5F, safe_read128s, read_xmm128s) +void instr_F20F5F(union reg64 source, int32_t r) { + // maxsd xmm, xmm/mem64 + union reg64 destination = read_xmm64s(r); + union reg64 result = { + .f64 = { sse_max(destination.f64[0], source.f64[0]), } + }; + write_xmm64(r, result); +} +DEFINE_SSE_SPLIT(instr_F20F5F, safe_read64s, read_xmm64s) +void instr_F30F5F(float_t source, int32_t r) { + // maxss xmm, xmm/mem32 + float_t destination = read_xmm_f32(r); + float result = sse_max(destination, source); + write_xmm_f32(r, result); +} +DEFINE_SSE_SPLIT(instr_F30F5F, fpu_load_m32, read_xmm_f32) void instr_0F60(int32_t source, int32_t r) { diff --git a/src/native/sse_instr.c b/src/native/sse_instr.c index aa2bba5c..82255ae9 100644 --- a/src/native/sse_instr.c +++ b/src/native/sse_instr.c @@ -417,3 +417,15 @@ bool sse_comparison(int32_t op, double_t x, double_t y) assert(false); } + +double_t sse_min(double_t x, double_t y) +{ + // if both x and y are 0 or x is nan, y is returned + return x < y ? x : y; +} + +double_t sse_max(double_t x, double_t y) +{ + // if both x and y are 0 or x is nan, y is returned + return x > y ? x : y; +} diff --git a/src/native/sse_instr.h b/src/native/sse_instr.h index 5ab65359..9c974caf 100644 --- a/src/native/sse_instr.h +++ b/src/native/sse_instr.h @@ -33,3 +33,5 @@ void psrlq_r128(int32_t r, uint32_t shift); void psllq_r128(int32_t r, uint32_t shift); bool sse_comparison(int32_t op, double_t x, double_t y); +double_t sse_min(double_t x, double_t y); +double_t sse_max(double_t x, double_t y); diff --git a/tests/qemu/test-i386.c b/tests/qemu/test-i386.c index 2e08a0ed..feb4c02e 100644 --- a/tests/qemu/test-i386.c +++ b/tests/qemu/test-i386.c @@ -2821,10 +2821,10 @@ void test_sse(void) SSE_OPS(add); SSE_OPS(mul); SSE_OPS(sub); - //SSE_OPS(min); - //SSE_OPS(div); - //SSE_OPS(max); - //SSE_OPS(sqrt); + SSE_OPS(min); + SSE_OPS(div); + SSE_OPS(max); + SSE_OPS(sqrt); SSE_OPS(cmpeq); SSE_OPS(cmplt); SSE_OPS(cmple); @@ -2846,10 +2846,10 @@ void test_sse(void) SSE_OPD(add); SSE_OPD(mul); SSE_OPD(sub); - //SSE_OPD(min); - //SSE_OPD(div); - //SSE_OPD(max); - //SSE_OPD(sqrt); + SSE_OPD(min); + SSE_OPD(div); + SSE_OPD(max); + SSE_OPD(sqrt); SSE_OPD(cmpeq); SSE_OPD(cmplt); SSE_OPD(cmple); From 21018b880ef9a5be352f1a4c3f0755ae80364675 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 1 Aug 2018 16:29:50 -0400 Subject: [PATCH 1117/2137] Enable a few more sse tests --- tests/qemu/test-i386.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/qemu/test-i386.c b/tests/qemu/test-i386.c index feb4c02e..2ffc093e 100644 --- a/tests/qemu/test-i386.c +++ b/tests/qemu/test-i386.c @@ -2888,10 +2888,8 @@ void test_sse(void) */ /* sse/mmx moves */ - /* CVT_OP_XMM2MMX(movdq2q); CVT_OP_MMX2XMM(movq2dq); - */ /* int to float */ /* From 33acb48fb98274dc41a79d8526e592b9d842631c Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 1 Aug 2018 16:37:22 -0400 Subject: [PATCH 1118/2137] Implement cvtsd2si (#57) --- gen/x86_table.js | 10 +++++++--- src/native/instructions_0f.c | 29 ++++++++++++++++++++++------- src/native/instructions_0f.h | 1 - src/native/sse_instr.c | 14 ++++++++++++++ src/native/sse_instr.h | 1 + 5 files changed, 44 insertions(+), 11 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index ae4b412c..b85d874e 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -501,11 +501,15 @@ const encodings = [ { sse: 1, opcode: 0x0F2B, reg_ud: 1, e: 1 }, { sse: 1, opcode: 0x660F2B, reg_ud: 1, e: 1 }, - { sse: 1, opcode: 0xF20F2C, e: 1, }, { sse: 1, opcode: 0x0F2C, e: 1, skip: 1, }, - { sse: 1, opcode: 0xF30F2C, e: 1, skip: 1, }, { sse: 1, opcode: 0x660F2C, e: 1, skip: 1, }, - { sse: 1, opcode: 0x0F2D, skip: 1 }, + { sse: 1, opcode: 0xF20F2C, e: 1, }, + { sse: 1, opcode: 0xF30F2C, e: 1, skip: 1, }, + { sse: 1, opcode: 0x0F2D, e: 1, skip: 1, }, + { sse: 1, opcode: 0x660F2D, e: 1, skip: 1, }, + { sse: 1, opcode: 0xF20F2D, e: 1, }, + { sse: 1, opcode: 0xF30F2D, e: 1, skip: 1, }, + { sse: 1, opcode: 0x0F2E, skip: 1 }, { sse: 1, opcode: 0x0F2F, skip: 1 }, diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index b2efafc1..c31a1a6d 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -680,10 +680,11 @@ void instr_660F2B_mem(int32_t addr, int32_t r) { mov_r_m128(addr, r); } -void instr_0F2C_mem(int32_t addr, int32_t r) { unimplemented_sse(); } -void instr_0F2C_reg(int32_t r1, int32_t r2) { unimplemented_sse(); } -void instr_660F2C_mem(int32_t addr, int32_t r) { unimplemented_sse(); } -void instr_660F2C_reg(int32_t r1, int32_t r2) { unimplemented_sse(); } +void instr_0F2C(union reg64 source, int32_t r) { unimplemented_sse(); } +DEFINE_SSE_SPLIT(instr_0F2C, safe_read64s, read_mmx64s) + +void instr_660F2C(union reg128 source, int32_t r) { unimplemented_sse(); } +DEFINE_SSE_SPLIT(instr_660F2C, safe_read128s, read_xmm128s) void instr_F20F2C(union reg64 source, int32_t r) { // cvttsd2si r32, xmm/m64 @@ -708,10 +709,24 @@ void instr_F20F2C(union reg64 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_F20F2C, safe_read64s, read_xmm64s) -void instr_F30F2C_mem(int32_t addr, int32_t r) { unimplemented_sse(); } -void instr_F30F2C_reg(int32_t r1, int32_t r2) { unimplemented_sse(); } +void instr_F30F2C(float_t source, int32_t r) { unimplemented_sse(); } +DEFINE_SSE_SPLIT(instr_F30F2C, fpu_load_m32, read_xmm_f32) + +void instr_0F2D(union reg64 source, int32_t r) { unimplemented_sse(); } +DEFINE_SSE_SPLIT(instr_0F2D, safe_read64s, read_mmx64s) + +void instr_660F2D(union reg128 source, int32_t r) { unimplemented_sse(); } +DEFINE_SSE_SPLIT(instr_660F2D, safe_read128s, read_xmm128s) + +void instr_F20F2D(union reg64 source, int32_t r) { + // cvtsd2si r32, xmm/m64 + write_reg32(r, sse_convert_f64_to_i32(source.f64[0])); +} +DEFINE_SSE_SPLIT(instr_F20F2D, safe_read64s, read_xmm64s) + +void instr_F30F2D(float_t source, int32_t r) { unimplemented_sse(); } +DEFINE_SSE_SPLIT(instr_F30F2D, fpu_load_m32, read_xmm_f32) -void instr_0F2D() { unimplemented_sse(); } void instr_0F2E() { unimplemented_sse(); } void instr_0F2F() { unimplemented_sse(); } diff --git a/src/native/instructions_0f.h b/src/native/instructions_0f.h index 93d64430..2bd07624 100644 --- a/src/native/instructions_0f.h +++ b/src/native/instructions_0f.h @@ -187,7 +187,6 @@ void instr_F20F2C_reg(int32_t r1, int32_t r2); void instr_F20F2C_mem(int32_t addr, int32_t r); void instr_F30F2C_mem(int32_t addr, int32_t r); void instr_F30F2C_reg(int32_t r1, int32_t r2); -void instr_0F2D(void); void instr_0F2E(void); void instr_0F2F(void); void instr_0F30(void); diff --git a/src/native/sse_instr.c b/src/native/sse_instr.c index 82255ae9..311e4a5e 100644 --- a/src/native/sse_instr.c +++ b/src/native/sse_instr.c @@ -429,3 +429,17 @@ double_t sse_max(double_t x, double_t y) // if both x and y are 0 or x is nan, y is returned return x > y ? x : y; } + +int32_t sse_convert_f64_to_i32(double_t x) +{ + // TODO: Rounding modes + if(x >= -0x80000000 && x < 0x80000000) + { + return (int64_t)x; + } + else + { + // TODO: Signal + return -0x80000000; + } +} diff --git a/src/native/sse_instr.h b/src/native/sse_instr.h index 9c974caf..0151e1ed 100644 --- a/src/native/sse_instr.h +++ b/src/native/sse_instr.h @@ -35,3 +35,4 @@ void psllq_r128(int32_t r, uint32_t shift); bool sse_comparison(int32_t op, double_t x, double_t y); double_t sse_min(double_t x, double_t y); double_t sse_max(double_t x, double_t y); +int32_t sse_convert_f64_to_i32(double_t x); From 33b0084aa547dfc7c3213769099e2ffabbec8a74 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 7 Aug 2018 12:06:27 -0500 Subject: [PATCH 1119/2137] Stats for global/non-global tlb entries --- src/browser/print_stats.js | 6 +++++- src/native/cpu.c | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index ca02adae..df8e53af 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -67,7 +67,11 @@ const print_stats = { text += "\n"; - text += "TLB_ENTRIES=" + cpu.wm.exports["_get_valid_tlb_entries_count"]() + "\n"; + const tlb_entries = cpu.wm.exports["_get_valid_tlb_entries_count"](); + const global_tlb_entries = cpu.wm.exports["_get_valid_global_tlb_entries_count"](); + const nonglobal_tlb_entries = tlb_entries - global_tlb_entries; + + text += "TLB_ENTRIES=" + tlb_entries + " (" + global_tlb_entries + " global, " + nonglobal_tlb_entries + " non-global)\n"; text += "CACHE_UNUSED=" + cpu.v86oxide.exports["jit_unused_cache_stat"]() + "\n"; text += "WASM_TABLE_FREE=" + cpu.v86oxide.exports["jit_get_wasm_table_index_free_list_count"]() + "\n"; diff --git a/src/native/cpu.c b/src/native/cpu.c index 567b8eb9..d0994c1e 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -386,7 +386,38 @@ void check_tlb_invariants(void) int32_t get_valid_tlb_entries_count(void) { - return valid_tlb_entries_count; + int32_t result = 0; + + for(int32_t i = 0; i < valid_tlb_entries_count; i++) + { + int32_t page = valid_tlb_entries[i]; + int32_t entry = tlb_data[page]; + + if(entry) + { + result++; + } + } + + return result; +} + +int32_t get_valid_global_tlb_entries_count(void) +{ + int32_t result = 0; + + for(int32_t i = 0; i < valid_tlb_entries_count; i++) + { + int32_t page = valid_tlb_entries[i]; + int32_t entry = tlb_data[page]; + + if(entry & TLB_GLOBAL) + { + result++; + } + } + + return result; } void writable_or_pagefault(int32_t addr, int32_t size) From 8998bab05ca866767c5d93ad67d86b139e0a2f53 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 7 Aug 2018 12:07:54 -0500 Subject: [PATCH 1120/2137] Lazy-load wabt/capstone on node --- src/debug.js | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/src/debug.js b/src/debug.js index 659ab031..9bd993af 100644 --- a/src/debug.js +++ b/src/debug.js @@ -713,16 +713,29 @@ CPU.prototype.debug_init = function() //} }; + let cs; let capstone_decoder; debug.dump_code = function(is_32, buffer, start) { if(!capstone_decoder) { - if(typeof cs === "undefined") + if(cs === undefined) { - dbg_log("Warning: Missing capstone library, disassembly not available"); - return; + if(typeof require === "function") + { + cs = require("./capstone-x86.min.js"); + } + else + { + cs = window.cs; + } + + if(cs === undefined) + { + dbg_log("Warning: Missing capstone library, disassembly not available"); + return; + } } capstone_decoder = [ @@ -761,12 +774,26 @@ CPU.prototype.debug_init = function() window.URL.revokeObjectURL(a.src); } + let wabt; + debug.dump_wasm = function(buffer) { - if(typeof wabt === "undefined") + if(wabt === undefined) { - dbg_log("Warning: Missing libwabt, wasm dump not available"); - return; + if(typeof require === "function") + { + wabt = require("./libwabt.js"); + } + else + { + wabt = window.wabt; + } + + if(wabt === undefined) + { + dbg_log("Warning: Missing libwabt, wasm dump not available"); + return; + } } // Need to make a small copy otherwise libwabt goes nuts trying to copy From a30b5b7eb3f90b43b2cc69bdaebd2216ba4c146f Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 7 Aug 2018 12:26:51 -0500 Subject: [PATCH 1121/2137] Filesystem: Make copy of restored files to avoid link to state buffer --- lib/filesystem.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/filesystem.js b/lib/filesystem.js index 9ee931a9..e9c8e9a5 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -103,6 +103,12 @@ FS.prototype.set_state = function(state) this.inodedata = {}; for(let [key, value] of state[2]) { + if(value.buffer.byteLength !== value.byteLength) + { + // make a copy if we didn't get one + value = value.slice(); + } + this.inodedata[key] = value; } this.total_size = state[3]; From 09072feee301ecba9623517668a22da70c3b3cf6 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 7 Aug 2018 12:32:44 -0500 Subject: [PATCH 1122/2137] Warn when restoring memory of incorrect size --- src/cpu.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cpu.js b/src/cpu.js index ec3f6fbf..f4ef6547 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -448,6 +448,11 @@ CPU.prototype.set_state = function(state) this.reg32s.set(state[39]); this.sreg.set(state[40]); this.dreg.set(state[41]); + + if(this.mem8.length !== state[42].length) + { + console.warn("Note: Memory size mismatch. we=" + this.mem8.length + " state=" + state[42].length); + } this.mem8.set(state[42]); this.set_tsc(state[43][0], state[43][1]); From ea6e7daee5f246d8ce9e43ea2d675499aa5fc0de Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 7 Aug 2018 12:51:26 -0500 Subject: [PATCH 1123/2137] Avoid use of raising cpu exceptoins for HLT --- src/cpu.js | 32 +++++++++----------------------- src/native/cpu.c | 2 +- src/native/global_pointers.h | 2 +- 3 files changed, 11 insertions(+), 25 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index f4ef6547..feaf7c86 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -79,9 +79,8 @@ function CPU(bus, wm, v86oxide, coverage_logger) /** * Was the last instruction a hlt? - * @type {boolean} */ - this.in_hlt = false; + this.in_hlt = new Uint8Array(wm.memory.buffer, 616, 1); this.last_virt_eip = new Int32Array(wm.memory.buffer, 620, 1); @@ -341,7 +340,7 @@ CPU.prototype.get_state = function() state[13] = this.is_32[0]; state[16] = this.stack_size_32[0]; - state[17] = this.in_hlt; + state[17] = this.in_hlt[0]; state[18] = this.last_virt_eip[0]; state[19] = this.eip_phys[0]; state[20] = this.last_virt_esp[0]; @@ -426,7 +425,7 @@ CPU.prototype.set_state = function(state) this.stack_size_32[0] = state[16]; - this.in_hlt = state[17]; + this.in_hlt[0] = state[17]; this.last_virt_eip[0] = state[18]; this.eip_phys[0] = state[19]; this.last_virt_esp[0] = state[20]; @@ -505,7 +504,7 @@ CPU.prototype.set_state = function(state) */ CPU.prototype.main_run = function() { - if(this.in_hlt) + if(this.in_hlt[0]) { //if(false) //{ @@ -517,7 +516,7 @@ CPU.prototype.main_run = function() var t = this.hlt_loop(); //} - if(this.in_hlt) + if(this.in_hlt[0]) { return t; } @@ -615,7 +614,7 @@ CPU.prototype.reset = function() this.timestamp_counter[0] = 0; this.previous_ip[0] = 0; - this.in_hlt = false; + this.in_hlt[0] = +false; this.sysenter_cs[0] = 0; this.sysenter_esp[0] = 0; @@ -1160,7 +1159,7 @@ CPU.prototype.do_run = function() this.do_many_cycles(); - if(this.in_hlt) + if(this.in_hlt[0]) { return; } @@ -1482,7 +1481,7 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, ha // we have to leave hlt_loop at some point, this is a // good place to do it //this.in_hlt && dbg_log("Leave HLT loop", LOG_CPU); - this.in_hlt = false; + this.in_hlt[0] = +false; if(this.protected_mode[0]) { @@ -2871,20 +2870,7 @@ CPU.prototype.hlt_op = function() } // get out of here and into hlt_loop - this.in_hlt = true; - - //if(false) // possibly unsafe, test in safari - //{ - // this.hlt_loop(); - // if(this.in_hlt) - // { - // throw MAGIC_CPU_EXCEPTION; - // } - //} - //else - { - throw MAGIC_CPU_EXCEPTION; - } + this.in_hlt[0] = +true; }; CPU.prototype.undefined_instruction = function() diff --git a/src/native/cpu.c b/src/native/cpu.c index d0994c1e..cbd94000 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -794,7 +794,7 @@ void do_many_cycles_unsafe() #else uint32_t initial_timestamp_counter = *timestamp_counter; - for(; *timestamp_counter - initial_timestamp_counter < LOOP_COUNTER; ) + for(; *timestamp_counter - initial_timestamp_counter < LOOP_COUNTER && !in_hlt[0]; ) #endif { cycle_internal(); diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index 1ab4c586..fb3bbdd6 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -36,7 +36,7 @@ static int32_t* const gdtr_offset = (int32_t* const) 576; static int32_t* const cr = (int32_t* const) 580; // length 32 static uint8_t* const cpl = (uint8_t* const) 612; -// gap +static bool* const in_hlt = (bool* const) 616; static int32_t* const last_virt_eip = (int32_t* const) 620; static int32_t* const eip_phys = (int32_t* const) 624; static int32_t* const last_virt_esp = (int32_t* const) 628; From 551f5d1a1f8fd8a9b54cafddc98675e43c309c5d Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 7 Aug 2018 12:55:14 -0500 Subject: [PATCH 1124/2137] When HLT is executed, check for new interrupts immediately and don't leave the main loop if execution can continue --- src/cpu.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/cpu.js b/src/cpu.js index feaf7c86..5db958b2 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -1161,7 +1161,12 @@ CPU.prototype.do_run = function() if(this.in_hlt[0]) { - return; + let t = this.hlt_loop(); + + if(this.in_hlt[0]) + { + return t; + } } now = v86.microtick(); From 5b5a36d2588f1e17543c3a424692ebed7ffd32b8 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 15 Aug 2018 19:05:44 -0500 Subject: [PATCH 1125/2137] Fix rustfmt after upgrade --- src/rust/jit.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rust/jit.rs b/src/rust/jit.rs index fbe9ab75..87469d8f 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -439,8 +439,7 @@ fn record_entry_point(ctx: &mut JitState, phys_address: u32) { .or_insert_with(|| { is_new = true; HashSet::new() - }) - .insert(offset_in_page); + }).insert(offset_in_page); if is_new { cpu::tlb_set_has_code(page, true); @@ -508,7 +507,8 @@ fn jit_find_basic_blocks( ctx.cs_offset.wrapping_add( (current_address .wrapping_sub(ctx.cs_offset) - .wrapping_add(offset as u32)) & 0xFFFF, + .wrapping_add(offset as u32)) + & 0xFFFF, ) }; From 9e592dbd84544f19da19a5806d10e6d849baea1a Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 18 Jul 2018 11:06:55 +1200 Subject: [PATCH 1126/2137] Decouple 9p and starter from fs's internal structure Part of changes to support fs mounting on the host side. Inode attributes are generally left untouched as field accesses. --- lib/9p.js | 47 ++++++++++++++---------------------------- lib/filesystem.js | 46 +++++++++++++++++++++++++++++++++++++++++ src/browser/starter.js | 5 +++-- 3 files changed, 64 insertions(+), 34 deletions(-) diff --git a/lib/9p.js b/lib/9p.js index f0ee2901..5e362724 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -249,8 +249,8 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { req[2] = Math.floor(space/req[1]); // free blocks, let's say 1GB req[3] = req[2] - Math.floor(size/req[1]); // free blocks in fs req[4] = req[2] - Math.floor(size/req[1]); // free blocks avail to non-superuser - req[5] = this.fs.inodes.length; // total number of inodes - req[6] = 1024*1024; + req[5] = this.fs.CountUsedInodes(); // total number of inodes + req[6] = this.fs.CountFreeInodes(); req[7] = 0; // file system id? req[8] = 256; // maximum length of filenames @@ -290,26 +290,9 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { var fid = req[1]; var name = req[2]; message.Debug("[link] dfid=" + dfid + ", name=" + name); - var inode = this.fs.CreateInode(); - var inodetarget = this.fs.GetInode(this.fids[fid].inodeid); - var targetdata = this.fs.inodedata[this.fids[fid].inodeid]; - //inode = inodetarget; - inode.dirty = true; - inode.mode = inodetarget.mode; - inode.size = inodetarget.size; - inode.symlink = inodetarget.symlink; - var data = this.fs.inodedata[this.fs.inodes.length] = new Uint8Array(inode.size); - if(targetdata) - { - data.set(targetdata.subarray(0, inode.size), 0); - } - inode.name = name; - inode.parentid = this.fids[dfid].inodeid; - this.fs.PushInode(inode); - - //inode.uid = inodetarget.uid; - //inode.gid = inodetarget.gid; - //inode.mode = inodetarget.mode | S_IFLNK; + + this.fs.Link(this.fids[fid].inodeid, name, this.fids[dfid].inodeid); + this.BuildReply(id, tag, 0); this.SendReply(bufchain); break; @@ -535,13 +518,12 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { this.BuildReply(id, tag, 4 + count); this.SendReply(bufchain); } else { - var file = this.fs.inodes[this.fids[fid].inodeid]; this.bus.send("9p-read-start"); this.fs.OpenInode(this.fids[fid].inodeid, undefined); this.fs.AddEvent(this.fids[fid].inodeid, function() { - this.bus.send("9p-read-end", [file.name, count]); + this.bus.send("9p-read-end", [inode.name, count]); const inodeid = this.fids[fid].inodeid; @@ -557,9 +539,9 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { // See http://ericvh.github.io/9p-rfc/rfc9p2000.html#anchor30 count = 0; } - var data = this.fs.inodedata[inodeid]; + const data = this.fs.Read(inodeid, offset, count); if(data) { - this.replybuffer.set(data.subarray(offset, offset + count), 7 + 4); + this.replybuffer.set(data, 7 + 4); } marshall.Marshall(["w"], [count], this.replybuffer, 7); this.BuildReply(id, tag, 4 + count); @@ -574,7 +556,9 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { var fid = req[0]; var offset = req[1]; var count = req[2]; - message.Debug("[write]: fid=" + fid + " (" + this.fs.inodes[this.fids[fid].inodeid].name + ") offset=" + offset + " count=" + count + " fidtype=" + this.fids[fid].type); + + const filename = this.fs.GetInode(this.fids[fid].inodeid).name; + message.Debug("[write]: fid=" + fid + " (" + filename + ") offset=" + offset + " count=" + count + " fidtype=" + this.fids[fid].type); if(this.fids[fid].type === FID_XATTR) { // XXX: xattr not supported yet. Ignore write. @@ -588,8 +572,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { this.fs.Write(this.fids[fid].inodeid, offset, count, buffer.subarray(state.offset)); } - var file = this.fs.inodes[this.fids[fid].inodeid]; - this.bus.send("9p-write-end", [file.name, count]); + this.bus.send("9p-write-end", [filename, count]); marshall.Marshall(["w"], [count], this.replybuffer, 7); this.BuildReply(id, tag, 4); @@ -689,8 +672,8 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { var idx = this.fids[fid].inodeid; var offset = 7+2; var nwidx = 0; - //console.log(idx, this.fs.inodes[idx]); - message.Debug("walk in dir " + this.fs.inodes[idx].name + " to: " + walk.toString()); + //console.log(idx, this.fs.GetInode(idx)); + message.Debug("walk in dir " + this.fs.GetInode(idx).name + " to: " + walk.toString()); for(var i=0; i Date: Thu, 9 Aug 2018 20:45:12 +1200 Subject: [PATCH 1127/2137] FS tests: add enable-logs switch, simplify basefs option --- tests/devices/virtio_9p.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index 58511a78..fc80a8f6 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -5,7 +5,8 @@ process.on("unhandledRejection", exn => { throw exn; }); const V86 = require("../../build/libv86-debug.js").V86; const fs = require("fs"); -const testfsjson = require('./testfs.json'); +const testfsjson = JSON.stringify(require('./testfs.json')); +const SHOW_LOGS = false; function log_pass(msg, ...args) { @@ -960,7 +961,7 @@ const emulator = new V86({ filesystem: { "baseurl": __dirname + "/testfs/", }, - log_level: 0, + log_level: SHOW_LOGS ? 0x400000 : 0, }); let ran_command = false; @@ -984,7 +985,7 @@ function nuke_fs() function reload_fsjson() { console.log(" Reloading files from json"); - emulator.fs9p.OnJSONLoaded(JSON.stringify(testfsjson)); + emulator.fs9p.OnJSONLoaded(testfsjson); emulator.fs9p.OnLoaded = () => { emulator.serial0_send("echo prep-fs-loaded\n"); From fa7ffd6ccc1185fbd3f0e657955af248012d36f4 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Thu, 9 Aug 2018 20:49:13 +1200 Subject: [PATCH 1128/2137] FS tests: include preparation steps in timeout Stop hangs caused by faults during mounting and file loading --- tests/devices/virtio_9p.js | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index fc80a8f6..60e4eb06 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -971,8 +971,22 @@ let capture = ""; let next_trigger; let next_trigger_handler; +function start_timeout() +{ + if(tests[test_num].timeout) + { + test_timeout = setTimeout(() => + { + log_fail("Test #%d (%s) took longer than %s sec. Timing out and terminating.", test_num, tests[test_num].name, tests[test_num].timeout); + process.exit(1); + }, tests[test_num].timeout * 1000); + } +} + function nuke_fs() { + start_timeout(); + console.log("\nPreparing test #%d: %s", test_num, tests[test_num].name); console.log(" Nuking /mnt"); emulator.serial0_send("rm -rf /mnt/*\n"); @@ -1028,15 +1042,6 @@ function start_test() { console.log("Starting test #%d: %s", test_num, tests[test_num].name); - if(tests[test_num].timeout) - { - test_timeout = setTimeout(() => - { - log_fail("Test #%d (%s) took longer than %s sec. Timing out and terminating.", test_num, tests[test_num].name, tests[test_num].timeout); - process.exit(1); - }, tests[test_num].timeout * 1000); - } - capture = ""; tests[test_num].start(); From 070c38c6a1624ef21375b422cc35d9525708e6a5 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Thu, 9 Aug 2018 22:46:34 +1200 Subject: [PATCH 1129/2137] Add tests for host-side fs mounting The testing "framework" code is slowly turning into spaghetti due to the asynchronous nature of the triggers. Using async functions will help clarify the program flow if we think we should address this issue. --- src/browser/starter.js | 39 ++++ tests/devices/testfs.json | 2 +- tests/devices/testfs/dir/bar | 1 + tests/devices/virtio_9p.js | 353 ++++++++++++++++++++++++++++++++--- 4 files changed, 366 insertions(+), 29 deletions(-) create mode 100644 tests/devices/testfs/dir/bar diff --git a/src/browser/starter.js b/src/browser/starter.js index 7693650f..6c0718ed 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -1071,6 +1071,45 @@ V86Starter.prototype.serial0_send = function(data) } }; +/** + * Mount another filesystem to the current filesystem. + * @param {string} path Path for the mount point + * @param {string|undefined} baseurl + * @param {string|undefined} basefs As a JSON string + * @param {function(Object)=} callback + * @export + */ +V86Starter.prototype.mount_fs = function(path, baseurl, basefs, callback) +{ + const newfs = new FS(baseurl); + const mount = () => + { + const idx = this.fs9p.Mount(path, newfs); + if(!callback) + { + return; + } + if(idx === -1) + { + callback(new FileNotFoundError()); + } + else + { + callback(null); + } + }; + if(baseurl) + { + dbg_assert(typeof basefs === "string", "Filesystem: basefs must be a JSON string"); + newfs.OnJSONLoaded(basefs); + newfs.OnLoaded = mount; + } + else + { + mount(); + } +}; + /** * Write to a file in the 9p filesystem. Nothing happens if no filesystem has * been initialized. First argument to the callback is an error object if diff --git a/tests/devices/testfs.json b/tests/devices/testfs.json index 12e7ce94..f0c50ce8 100644 --- a/tests/devices/testfs.json +++ b/tests/devices/testfs.json @@ -1 +1 @@ -{"fsroot":[["foo",4,1531028318,33188,1000,1000]],"version":2,"size":4} \ No newline at end of file +{"fsroot":[["foo",4,1531432001,33188,1000,1000],["dir",4096,1532940393,16877,1000,1000,[["bar",7,1532940393,33188,1000,1000]]]],"version":2,"size":4107} \ No newline at end of file diff --git a/tests/devices/testfs/dir/bar b/tests/devices/testfs/dir/bar new file mode 100644 index 00000000..9dabfec9 --- /dev/null +++ b/tests/devices/testfs/dir/bar @@ -0,0 +1 @@ +foobaz diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index 60e4eb06..d9b74c91 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -936,6 +936,245 @@ const tests = done(); }, }, + { + name: "Read Mounted", + timeout: 60, + mounts: + [ + { path: "/a/b/fs2", baseurl: __dirname + "/testfs/", basefs: testfsjson }, + ], + start: () => + { + emulator.serial0_send("echo start-capture;"); + emulator.serial0_send("cat /mnt/a/b/fs2/foo;"); + emulator.serial0_send("cat /mnt/a/b/fs2/dir/bar;"); + emulator.serial0_send("echo done-read-mounted\n"); + }, + capture_trigger: "start-capture", + end_trigger: "done-read-mounted", + end: (capture, done) => + { + assert_equal(capture, "bar\nfoobaz\n"); + emulator.read_file("/a/b/fs2/dir/bar", function(err, data) + { + if(err) + { + log_warn("Reading /a/b/fs2/dir/bar failed: %s", err); + test_fail(); + done(); + return; + } + assert_equal(Buffer.from(data).toString(), "foobaz\n"); + done(); + }); + }, + }, + { + name: "Write Mounted", + timeout: 60, + mounts: + [ + { path: "/a/b/fs2" }, + ], + files: + [ + { + file: "/a/b/fs2/write-new-host", + data: test_file, + }, + ], + start: () => + { + emulator.serial0_send("mkdir /mnt/a/b/fs2/c\n"); + emulator.serial0_send("echo foobar > /mnt/a/b/fs2/c/write-new-guest\n"); + + emulator.serial0_send("echo start-capture;"); + emulator.serial0_send("cat /mnt/a/b/fs2/c/write-new-guest;"); + emulator.serial0_send("cat /mnt/a/b/fs2/write-new-host; echo;"); + emulator.serial0_send("echo done-write-mounted\n"); + }, + capture_trigger: "start-capture", + end_trigger: "done-write-mounted", + end: (capture, done) => + { + const lines = capture.split("\n"); + assert_equal(lines.shift(), "foobar"); + let pos = 0; + for(const line of lines) + { + assert_equal(line, test_file_string.slice(pos, line.length)); + pos += line.length; + } + emulator.read_file("a/b/fs2/c/write-new-guest", function(err, data) + { + if(err) + { + log_warn("Reading a/b/fs2/c/write-new-guest failed: %s", err); + test_fail(); + done(); + return; + } + assert_equal(Buffer.from(data).toString(), "foobar\n"); + done(); + }); + }, + }, + { + name: "Walk Mounted", + timeout: 180, + mounts: + [ + { path: "/a/fs2" }, + { path: "/fs3" }, + { path: "/fs3/fs4" }, + ], + start: () => + { + emulator.serial0_send("echo start-capture;"); + emulator.serial0_send("mkdir -p /mnt/a/fs2/aa/aaa/aaaa;"); + emulator.serial0_send("mkdir -p /mnt/a/fs2/aa/aab;"); + emulator.serial0_send("mkdir -p /mnt/a/fs2/ab/aba;"); + emulator.serial0_send("touch /mnt/a/fs2/ab/aba/abafile;"); + emulator.serial0_send("mkdir -p /mnt/a/fs2/ab/abb;"); + emulator.serial0_send("mkdir -p /mnt/fs3/a/aa/aaa;"); + emulator.serial0_send("mkdir -p /mnt/fs3/a/ab/aba;"); + emulator.serial0_send("touch /mnt/fs3/a/afile;"); + emulator.serial0_send("mkdir -p /mnt/fs3/b;"); + emulator.serial0_send("mkdir -p /mnt/fs3/fs4/a/aa/aaa;"); + emulator.serial0_send("mkdir -p /mnt/fs3/fs4/a/ab/;"); + emulator.serial0_send("mkdir -p /mnt/fs3/fs4/a/ac/aca;"); + emulator.serial0_send("touch /mnt/fs3/fs4/a/ac/aca/acafile;"); + emulator.serial0_send("find /mnt | sort;"); // order agnostic + emulator.serial0_send("echo done-walk-mounted\n"); + }, + capture_trigger: "start-capture", + end_trigger: "done-walk-mounted", + end: (capture, done) => + { + const lines = capture.split("\n"); + const expected_lines = + [ + "/mnt", + "/mnt/a", + "/mnt/a/fs2", + "/mnt/a/fs2/aa", + "/mnt/a/fs2/aa/aaa", + "/mnt/a/fs2/aa/aaa/aaaa", + "/mnt/a/fs2/aa/aab", + "/mnt/a/fs2/ab", + "/mnt/a/fs2/ab/aba", + "/mnt/a/fs2/ab/aba/abafile", + "/mnt/a/fs2/ab/abb", + "/mnt/fs3", + "/mnt/fs3/a", + "/mnt/fs3/a/aa", + "/mnt/fs3/a/aa/aaa", + "/mnt/fs3/a/ab", + "/mnt/fs3/a/ab/aba", + "/mnt/fs3/a/afile", + "/mnt/fs3/b", + "/mnt/fs3/fs4", + "/mnt/fs3/fs4/a", + "/mnt/fs3/fs4/a/aa", + "/mnt/fs3/fs4/a/aa/aaa", + "/mnt/fs3/fs4/a/ab", + "/mnt/fs3/fs4/a/ac", + "/mnt/fs3/fs4/a/ac/aca", + "/mnt/fs3/fs4/a/ac/aca/acafile", + ]; + for(const expected of expected_lines) + { + assert_equal(lines.shift(), expected); + } + done(); + }, + }, + { + name: "Move Mounted", + timeout: 60, + mounts: + [ + { path: "/a/b/fs2" }, + { path: "/fs3" }, + { path: "/fs3/fs4" }, + { path: "/fs3/fs4/fs5" }, + ], + start: () => + { + emulator.serial0_send("echo foobar > /mnt/file\n"); + emulator.serial0_send("mkdir /mnt/a/b/fs2/dir\n"); + emulator.serial0_send("echo contents > /mnt/a/b/fs2/dir/child\n"); + + // Using tail -f to keep 'file' open for modification in bg while it is being moved. + // Using fifo to send data from fg job to bg job to write to file. + emulator.serial0_send("mkfifo /mnt/fs3/fifo\n"); + emulator.serial0_send("mkfifo /mnt/fs3/fifo_intermediate\n"); + emulator.serial0_send("tail -f /mnt/fs3/fifo > /mnt/fs3/fifo_intermediate &\n"); + emulator.serial0_send('echo "$!" > /mnt/tailpid\n'); + emulator.serial0_send('{ sed "/EOF/q" < /mnt/fs3/fifo_intermediate && kill "$(cat /mnt/tailpid)"; } >> /mnt/file &\n'); + + emulator.serial0_send("echo start-capture; \\\n"); + emulator.serial0_send("echo untouched > /mnt/fs3/fifo; \\\n"); + + emulator.serial0_send("{ mv /mnt/file /mnt/renamed && "); + emulator.serial0_send(" echo renamed > /mnt/fs3/fifo; }; \\\n"); + + emulator.serial0_send("{ mv /mnt/renamed /mnt/fs3/file &&"); + emulator.serial0_send(" echo file jump filesystems > /mnt/fs3/fifo; }; \\\n"); + + emulator.serial0_send("{ mv /mnt/fs3/file /mnt/a/b/fs2/dir/file && "); + emulator.serial0_send(" echo moved to dir > /mnt/fs3/fifo; }; \\\n"); + + emulator.serial0_send("{ mv /mnt/a/b/fs2/dir /mnt/fs3/fs4/fs5/dir && "); + emulator.serial0_send(" echo dir jump filesystems > /mnt/fs3/fifo; }; \\\n"); + + emulator.serial0_send("{ mv /mnt/fs3/fs4 /mnt/a/b/fs2/fs4 2>/dev/null || "); + emulator.serial0_send(" echo move mount point across - fails > /mnt/fs3/fifo; }; \\\n"); + + emulator.serial0_send("{ mv /mnt/fs3/fs4/fs5 /mnt/fs5 2>/dev/null || "); + emulator.serial0_send(" echo move mount point upwards - fails > /mnt/fs3/fifo; }; \\\n"); + + emulator.serial0_send("{ mv /mnt/fs3/fs4/fs5/dir /mnt/dir && "); + emulator.serial0_send(" echo jump to root > /mnt/fs3/fifo; }; \\\n"); + + emulator.serial0_send('printf "EOF\\n\\n" > /mnt/fs3/fifo & wait "$(cat /mnt/tailpid)" 2>/dev/null; \\\n'); + emulator.serial0_send("cat /mnt/dir/file; \\\n"); + emulator.serial0_send("cat /mnt/dir/child; \\\n"); + emulator.serial0_send("find /mnt | sort; \\\n"); + emulator.serial0_send("echo done-move-mounted\n"); + }, + capture_trigger: "start-capture", + end_trigger: "done-move-mounted", + end: (capture, done) => + { + assert_equal(capture, + "foobar\n" + + "untouched\n" + + "renamed\n" + + "file jump filesystems\n" + + "moved to dir\n" + + "dir jump filesystems\n" + + "move mount point across - fails\n" + + "move mount point upwards - fails\n" + + "jump to root\n" + + "EOF\n" + + "contents\n" + + "/mnt\n" + + "/mnt/a\n" + + "/mnt/a/b\n" + + "/mnt/a/b/fs2\n" + + "/mnt/dir\n" + + "/mnt/dir/child\n" + + "/mnt/dir/file\n" + + "/mnt/fs3\n" + + "/mnt/fs3/fifo\n" + + "/mnt/fs3/fifo_intermediate\n" + + "/mnt/fs3/fs4\n" + + "/mnt/fs3/fs4/fs5\n" + + "/mnt/tailpid\n"); + done(); + }, + }, ]; let test_num = 0; @@ -993,7 +1232,7 @@ function nuke_fs() emulator.serial0_send("echo prep-nuke-done\n"); next_trigger = "prep-nuke-done"; - next_trigger_handler = tests[test_num].use_fsjson ? reload_fsjson : load_files; + next_trigger_handler = tests[test_num].use_fsjson ? reload_fsjson : do_mounts; } function reload_fsjson() @@ -1002,15 +1241,64 @@ function reload_fsjson() emulator.fs9p.OnJSONLoaded(testfsjson); emulator.fs9p.OnLoaded = () => { - emulator.serial0_send("echo prep-fs-loaded\n"); + do_mounts(); }; +} - next_trigger = "prep-fs-loaded"; - next_trigger_handler = load_files; +function do_mounts() +{ + console.log(" Configuring mounts"); + if(tests[test_num].mounts && tests[test_num].mounts.length > 0) + { + premount(0); + + function premount(mount_num) + { + const path = tests[test_num].mounts[mount_num].path; + emulator.serial0_send("mkdir -p /mnt" + path + "\n"); + emulator.serial0_send("echo done-premount\n"); + next_trigger = "done-premount"; + next_trigger_handler = () => mount(mount_num); + } + + function mount(mount_num) + { + const { path, baseurl, basefs } = tests[test_num].mounts[mount_num]; + emulator.mount_fs(path, baseurl, basefs, err => + { + if(err) + { + log_warn("Failed to mount fs required for test %s: %s", + tests[test_num].name, err); + test_fail(); + } + if(mount_num + 1 < tests[test_num].mounts.length) + { + premount(mount_num + 1); + } + else + { + if(test_has_failed) + { + report_test(); + } + else + { + load_files(); + } + } + }); + } + } + else + { + load_files(); + } } function load_files() { + console.log(" Loading additional files"); if(tests[test_num].files) { let remaining = tests[test_num].files.length; @@ -1022,12 +1310,19 @@ function load_files() { log_warn("Failed to add file required for test %s: %s", tests[test_num].name, err); - process.exit(1); + test_fail(); } remaining--; if(!remaining) { - start_test(); + if(test_has_failed) + { + report_test(); + } + else + { + start_test(); + } } }); } @@ -1077,36 +1372,38 @@ function end_test() clearTimeout(test_timeout); } - tests[test_num].end(capture, () => + tests[test_num].end(capture, report_test); +} + +function report_test() +{ + if(!test_has_failed) { - if(!test_has_failed) + log_pass("Test #%d passed: %s", test_num, tests[test_num].name); + } + else + { + if(tests[test_num].allow_failure) { - log_pass("Test #%d passed: %s", test_num, tests[test_num].name); + log_warn("Test #%d failed: %s (failure allowed)", test_num, tests[test_num].name); } else { - if(tests[test_num].allow_failure) - { - log_warn("Test #%d failed: %s (failure allowed)", test_num, tests[test_num].name); - } - else - { - log_fail("Test #%d failed: %s", test_num, tests[test_num].name); - } - test_has_failed = false; + log_fail("Test #%d failed: %s", test_num, tests[test_num].name); } + test_has_failed = false; + } - test_num++; + test_num++; - if(test_num < tests.length) - { - nuke_fs(); - } - else - { - finish_tests(); - } - }); + if(test_num < tests.length) + { + nuke_fs(); + } + else + { + finish_tests(); + } } function finish_tests() From e6ef68b33450752068a6d894cb4e336178cb210f Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 11 Aug 2018 11:05:11 +1200 Subject: [PATCH 1130/2137] Introduce forwarding inodes. Implement fs.Mount Add forward_path info to fs.SearchPath. Handle forwarding for fs.Search. --- lib/filesystem.js | 223 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 216 insertions(+), 7 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index ad65ec93..8785dc38 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -29,6 +29,7 @@ var STATUS_OK = 0x0; var STATUS_ON_SERVER = 0x2; var STATUS_LOADING = 0x3; var STATUS_UNLINKED = 0x4; +var STATUS_FORWARDING = 0x5; /** @const */ var JSONFS_VERSION = 2; @@ -62,6 +63,9 @@ function FS(baseurl) { this.total_size = 256 * 1024 * 1024 * 1024; this.used_size = 0; + /** @type {!Array} */ + this.mounts = []; + //RegisterMessage("LoadFilesystem", this.LoadFilesystem.bind(this) ); //RegisterMessage("MergeFile", this.MergeFile.bind(this) ); //RegisterMessage("tar", @@ -92,6 +96,8 @@ FS.prototype.get_state = function() } state[3] = this.total_size; state[4] = this.used_size; + state[5] = this.baseurl; + state[6] = this.mounts.map(mnt => mnt.fs); return state; }; @@ -113,6 +119,14 @@ FS.prototype.set_state = function(state) } this.total_size = state[3]; this.used_size = state[4]; + this.baseurl = state[5]; + this.mounts = []; + for(const mount_state of state[6]) + { + const mount = new FSMountInfo(null); + mount.set_state(mount_state); + this.mounts.push(mount); + } }; @@ -341,6 +355,10 @@ function Inode(qidnumber) this.nlinks = 1; this.dirty = false; // has this file changed? + // For forwarders: + this.mount_id = -1; // which fs in this.mounts does this inode forward to? + this.foreign_id = -1; // which foreign inode id does it represent? + //this.qid_type = 0; //this.qid_version = 0; //this.qid_path = qidnumber; @@ -372,6 +390,8 @@ Inode.prototype.get_state = function() state[20] = this.caps; state[21] = this.nlinks; state[22] = this.dirty; + state[23] = this.mount_id; + state[24] = this.foreign_id; return state; }; @@ -400,6 +420,8 @@ Inode.prototype.set_state = function(state) this.caps = state[20]; this.nlinks = state[21]; this.dirty = state[22]; + this.mount_id = state[23]; + this.foreign_id = state[24]; }; FS.prototype.CreateInode = function() { @@ -611,11 +633,21 @@ FS.prototype.Read = function(inodeid, offset, count) }; FS.prototype.Search = function(parentid, name) { - var id = this.inodes[parentid].firstid; + const parent_inode = this.inodes[parentid]; + + if(this.is_forwarder(parent_inode)) + { + const foreign_parentid = parent_inode.foreign_id; + const foreign_id = this.follow_fs(parent_inode).Search(foreign_parentid, name); + if(foreign_id === -1) return -1; + return this.get_forwarder(parent_inode.mount_id, foreign_id); + } + + var id = parent_inode.firstid; while(id != -1) { - if (this.inodes[id].parentid != parentid) { // consistency check - message.Debug("Error in Filesystem: Found inode with wrong parent id"); - } + dbg_assert(this.GetParent(id) === parentid, + "Error in Filesystem: Found inode (" + this.inodes[id].name + ") with wrong parent id. " + + "Expected: " + parentid + ", Actual: " + this.GetParent(id)); if (this.inodes[id].name == name) return id; id = this.inodes[id].nextid; } @@ -763,15 +795,20 @@ FS.prototype.SearchPath = function(path) { var parentid = 0; var id = -1; + let forward_path = null; for(var i=0; i} */ + this.backtrack = new Map(); +} + +FSMountInfo.prototype.get_state = function() +{ + const state = []; + + state[0] = this.fs; + state[1] = []; + for(const entry of this.backtrack.entries()) + { + state[1].push(entry); + } + + return state; +}; + +FSMountInfo.prototype.set_state = function(state) +{ + this.fs = new FS(undefined); + fs.set_state(state[0]); + this.backtrack = new Map(state[1]); +}; + +/** + * @private + * @param {number} idx Local idx of inode. + * @param {number} mount_id Mount number of the destination fs. + * @param {number} foreign_id Foreign idx of destination inode. + */ +FS.prototype.set_forwarder = function(idx, mount_id, foreign_id) +{ + const inode = this.inodes[idx]; + + if(this.is_forwarder(inode)) + { + this.mounts[inode.mount_id].backtrack.delete(inode.foreign_id); + } + + inode.status = STATUS_FORWARDING; + inode.mount_id = mount_id; + inode.foreign_id = foreign_id; + + this.mounts[mount_id].backtrack.set(foreign_id, idx); +}; + +/** + * @private + * @param {number} mount_id Mount number of the destination fs. + * @param {number} foreign_id Foreign idx of destination inode. + * @return {number} Local idx of newly created forwarder. + */ +FS.prototype.create_forwarder = function(mount_id, foreign_id) +{ + dbg_assert(foreign_id !== 0, "Filesystem: root forwarder should not be created."); + + const inode = this.CreateInode(); + + const idx = this.inodes.length; + this.inodes.push(inode); + inode.fid = idx; + + this.set_forwarder(idx, mount_id, foreign_id); + return idx; +}; + +/** + * @private + * @param {Inode} inode + * @return {boolean} + */ +FS.prototype.is_forwarder = function(inode) +{ + return inode.status === STATUS_FORWARDING; +}; + +/** + * Ensures forwarder exists, and returns such forwarder, for the described foreign inode. + * @private + * @param {number} mount_id + * @param {number} foreign_id + * @return {number} Local idx of a forwarder to described inode. + */ +FS.prototype.get_forwarder = function(mount_id, foreign_id) +{ + const mount = this.mounts[mount_id]; + + dbg_assert(foreign_id >= 0, "Filesystem get_forwarder: invalid foreign_id: " + foreign_id); + dbg_assert(mount, "Filesystem get_forwarder: invalid mount number: " + mount_id); + + const result = mount.backtrack.get(foreign_id); + + if(result === undefined) + { + // Create if not already exists. + return this.create_forwarder(mount_id, foreign_id); + } + + return result; +}; + +/** + * @private + * @param {Inode} inode + */ +FS.prototype.delete_forwarder = function(inode) +{ + dbg_assert(this.is_forwarder(inode), "Filesystem delete_forwarder: expected forwarder"); + + inode.status = STATUS_INVALID; + this.mounts[inode.mount_id].backtrack.delete(inode.foreign_id); +}; + +/** + * @private + * @param {Inode} inode + * @return {FS} + */ +FS.prototype.follow_fs = function(inode) +{ + const mount = this.mounts[inode.mount_id]; + + dbg_assert(this.is_forwarder(inode), + "Filesystem follow_fs: inode should be a forwarding inode"); + dbg_assert(mount, "Filesystem follow_fs: inode should point to valid mounted FS"); + + return mount.fs; +}; + +/** + * Mount another filesystem onto an existing directory. + * @param {string} path Path to existing directrory relative to this filesystem. + * @param {FS} fs + */ +FS.prototype.Mount = function(path, fs) +{ + const path_infos = this.SearchPath(path); + + if(path_infos.id === -1) + { + dbg_log("Mount failed: path not found: " + path, LOG_9P); + return -1; + } + if(path_infos.forward_path) + { + const parent = this.inodes[path_infos.parentid]; + this.follow_fs(parent).Mount(path_infos.forward_path, fs); + return; + } + + const mount_id = this.mounts.length; + this.mounts.push(new FSMountInfo(fs)); + + // Existing inode is already linked. Just set forwarding information. + this.set_forwarder(path_infos.id, mount_id, 0); + + return path_infos.id; +}; From 1c6e5f2a515ea3a4dd05896f702aa92c11e8b5c9 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 11 Aug 2018 11:08:45 +1200 Subject: [PATCH 1131/2137] Add failing tests for fs.SearchPath Bugs in fs.SearchPath is causing problems with fs.Mount. --- tests/devices/virtio_9p.js | 84 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 4 deletions(-) diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index d9b74c91..dffbfd21 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -23,22 +23,22 @@ function log_fail(msg, ...args) console.error(`\x1b[91m[-] ${msg}\x1b[0m`, ...args); } -function assert_equal(actual, expected) +function assert_equal(actual, expected, message) { if(actual !== expected) { - log_warn("Failed assert equal (Test: %s)", tests[test_num].name); + log_warn("Failed assert equal (Test: %s). %s", tests[test_num].name, message || ""); log_warn("Expected:\n" + expected); log_warn("Actual:\n" + actual); test_fail(); } } -function assert_not_equal(actual, expected) +function assert_not_equal(actual, expected, message) { if(actual === expected) { - log_warn("Failed assert not equal (Test: %s)", tests[test_num].name); + log_warn("Failed assert not equal (Test: %s). %s", tests[test_num].name, message || ""); log_warn("Expected something different than:\n" + expected); test_fail(); } @@ -52,6 +52,82 @@ const test_file_small_string = Buffer.from(test_file_small).toString(); const tests = [ + { + name: "API SearchPath", + timeout: 60, + mounts: + [ + { path: "/x/fs2" }, + ], + start: () => + { + emulator.serial0_send("mkdir -p /mnt/a/b/c\n"); + emulator.serial0_send("touch /mnt/a/b/c/file1\n"); + emulator.serial0_send("touch /mnt/file2\n"); + emulator.serial0_send("mkdir -p /mnt/x/fs2/y/z\n"); + emulator.serial0_send("echo done-searchpath\n"); + }, + end_trigger: "done-searchpath", + end: (capture, done) => + { + const root1 = emulator.fs9p.SearchPath(""); + assert_equal(root1.id, 0, "root1 id"); + assert_equal(root1.parentid, -1, "root1 parentid"); + + const root2 = emulator.fs9p.SearchPath("/"); + assert_equal(root2.id, 0, "root2 / id"); + assert_equal(root2.parentid, -1, "root2 / parentid"); + + const notfound1 = emulator.fs9p.SearchPath("c"); + assert_equal(notfound1.id, -1, "notfound1 c id"); + assert_equal(notfound1.parentid, 0, "notfound1 c parentid"); + + const notfound2 = emulator.fs9p.SearchPath("c/d"); + assert_equal(notfound2.id, -1, "notfound2 c/d id"); + assert_equal(notfound2.parentid, -1, "notfound2 c/d parentid"); + + const notfound3 = emulator.fs9p.SearchPath("a/d"); + assert_equal(notfound3.id, -1, "notfound3 a/d id"); + assert_equal(emulator.fs9p.GetInode(notfound3.parentid).name, "a", "notfound3 a/d parent name"); + const idx_a = notfound3.parentid; + + const notfound4 = emulator.fs9p.SearchPath("a/d/e"); + assert_equal(notfound4.id, -1, "notfound4 a/d/e id"); + assert_equal(notfound4.parentid, -1, "notfound4 a/d/e parentid"); + + const dir1 = emulator.fs9p.SearchPath("a"); + assert_equal(dir1.id, idx_a, "dir1 a id"); + assert_equal(dir1.parentid, 0, "dir1 a parentid"); + + const dir2 = emulator.fs9p.SearchPath("a/b/c"); + assert_equal(emulator.fs9p.GetInode(dir2.id).name, "c", "dir2 a/b/c name"); + assert_equal(emulator.fs9p.GetInode(dir2.parentid).name, "b", "dir2 a/b/c parent name"); + const idx_b = dir2.parentid; + const idx_c = dir2.id; + + const file1 = emulator.fs9p.SearchPath("a/b/c/file1"); + assert_equal(emulator.fs9p.GetInode(file1.id).name, "file1", "file1 a/b/c/file1 name"); + assert_equal(file1.parentid, idx_c, "file1 a/b/c/file1 parentid"); + + const file2 = emulator.fs9p.SearchPath("file2"); + assert_equal(emulator.fs9p.GetInode(file2.id).name, "file2", "file2 name"); + assert_equal(file2.parentid, 0, "file2 parentid"); + + const fwdpath1 = emulator.fs9p.SearchPath("x/fs2"); + assert_equal(fwdpath1.forward_path, null, "fwdpath1 x/fs2"); + + const fwdpath2 = emulator.fs9p.SearchPath("x/fs2/y"); + assert_equal(fwdpath2.forward_path, "/y", "fwdpath2 x/fs2/y"); + + const fwdpath3 = emulator.fs9p.SearchPath("x/fs2/y/z"); + assert_equal(fwdpath3.forward_path, "/y/z", "fwdpath3 x/fs2/y/z"); + + const fwdpath4 = emulator.fs9p.SearchPath("x/fs2/nonexistent"); + assert_equal(fwdpath4.forward_path, "/nonexistent", "fwdpath4 x/fs2/nonexistent"); + + done(); + }, + }, { name: "Read Existing", timeout: 60, From d78f722a385120b07967a190256499a416a7d6fc Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 11 Aug 2018 11:10:35 +1200 Subject: [PATCH 1132/2137] Fix fs.SearchPath --- lib/filesystem.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 8785dc38..942d0ba7 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -788,15 +788,15 @@ FS.prototype.SearchPath = function(path) { //path = path.replace(/\/\//g, "/"); path = path.replace("//", "/"); var walk = path.split("/"); - var n = walk.length; - if (walk[n-1].length == 0) walk.pop(); - if (walk[0].length == 0) walk.shift(); - n = walk.length; + if (walk.length > 0 && walk[walk.length - 1].length === 0) walk.pop(); + if (walk.length > 0 && walk[0].length === 0) walk.shift(); + const n = walk.length; - var parentid = 0; - var id = -1; + var parentid = -1; + var id = 0; let forward_path = null; for(var i=0; i Date: Sat, 11 Aug 2018 11:13:48 +1200 Subject: [PATCH 1133/2137] Make inode qid numbers unique across filesystems Storing the same global qid counter into every filesystem state is not ideal, but not sure if there's a better place to store it for state saving and restoring. --- lib/filesystem.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 942d0ba7..2f236b9c 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -52,7 +52,6 @@ function FS(baseurl) { this.baseurl = baseurl; - this.qidnumber = 0x0; this.filesinloadingqueue = 0; this.OnLoaded = function() {}; @@ -83,12 +82,14 @@ function FS(baseurl) { this.CreateDirectory("", -1); } +FS.last_qidnumber = 0; + FS.prototype.get_state = function() { const state = []; state[0] = this.inodes; - state[1] = this.qidnumber; + state[1] = FS.last_qidnumber; state[2] = []; for(let entry of Object.entries(this.inodedata)) { @@ -105,7 +106,7 @@ FS.prototype.get_state = function() FS.prototype.set_state = function(state) { this.inodes = state[0].map(state => { const inode = new Inode(0); inode.set_state(state); return inode; }); - this.qidnumber = state[1]; + FS.last_qidnumber = state[1]; this.inodedata = {}; for(let [key, value] of state[2]) { @@ -427,7 +428,7 @@ Inode.prototype.set_state = function(state) FS.prototype.CreateInode = function() { //console.log("CreateInode", Error().stack); const now = Math.round(Date.now() / 1000); - const inode = new Inode(++this.qidnumber); + const inode = new Inode(++FS.last_qidnumber); inode.atime = inode.ctime = inode.mtime = now; return inode; }; From 4e4c62bb2b34f5da55a01e1428ca3106c3118fa1 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 11 Aug 2018 11:33:32 +1200 Subject: [PATCH 1134/2137] Mount-aware accessors: GetInode/Parent/Children --- lib/filesystem.js | 101 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 93 insertions(+), 8 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 2f236b9c..43adfaf8 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -306,6 +306,17 @@ FS.prototype.LoadFile = function(idx) { // ----------------------------------------------------- +/** + * Non-root forwarders are not linked locally, or else we need to synchronise with the + * corresponding mounted filesystems. + * @private + * @return {boolean} + */ +FS.prototype.should_be_linked = function(inode) +{ + return !this.is_forwarder(inode) || this.is_root_forwarder(inode); +}; + FS.prototype.PushInode = function(inode) { if (inode.parentid != -1) { this.inodes.push(inode); @@ -759,16 +770,16 @@ FS.prototype.Unlink = function(idx) { FS.prototype.GetInode = function(idx) { - if (isNaN(idx)) { - message.Debug("Error in filesystem: id is not a number "); - return 0; + dbg_assert(!isNaN(idx), "Filesystem GetInode: NaN idx"); + dbg_assert(idx >= 0 && idx < this.inodes.length, "Filesystem GetInode: out of range idx:" + idx); + + const inode = this.inodes[idx]; + if(this.is_forwarder(inode)) + { + return this.follow_fs(inode).GetInode(inode.foreign_id); } - if ((idx < 0) || (idx > this.inodes.length)) { - message.Debug("Error in filesystem: Attempt to get inode with id " + idx); - return 0; - } - return this.inodes[idx]; + return inode; }; FS.prototype.ChangeSize = function(idx, newsize) @@ -974,6 +985,68 @@ FS.prototype.RoundToDirentry = function(dirid, offset_target) return offset; }; +/** + * @param {number} idx + * @return {boolean} + */ +FS.prototype.IsDirectory = function(idx) +{ + const inode = this.inodes[idx]; + if(this.is_forwarder(inode)) + { + return this.follow_fs(inode).IsDirectory(inode.foreign_id); + } + return (inode.mode & S_IFMT) === S_IFDIR; +}; + +/** + * @param {number} idx + * @return {!Array} List of children names + */ +FS.prototype.GetChildren = function(idx) +{ + const inode = this.inodes[idx]; + const children = []; + + if(this.is_forwarder(inode)) + { + return this.follow_fs(inode).GetChildren(inode.foreign_id); + } + + let child_id = this.inodes[idx].firstid; + + while(child_id !== -1) + { + children.push(this.inodes[child_id].name); + child_id = this.inodes[child_id].nextid; + } + + return children; +}; + +/** + * @param {number} idx + * @return {number} Local idx of parent + */ +FS.prototype.GetParent = function(idx) +{ + const inode = this.inodes[idx]; + + if(this.should_be_linked(inode)) + { + return inode.parentid; + } + else + { + const foreign_dirid = this.follow_fs(inode).GetParent(inode.foreign_id); + if(foreign_dirid === -1) + { + return -1; + } + return this.get_forwarder(inode.mount_id, foreign_dirid); + } +}; + // ----------------------------------------------------- @@ -1114,6 +1187,18 @@ FS.prototype.is_forwarder = function(inode) return inode.status === STATUS_FORWARDING; }; +/** + * @private + * @param {Inode} inode + * @return {boolean} + */ +FS.prototype.is_root_forwarder = function(inode) +{ + // Note: Non-root forwarder inode could still have a non-forwarder parent, so don't use + // parent inode to check. + return this.is_forwarder(inode) && inode.foreign_id === 0; +}; + /** * Ensures forwarder exists, and returns such forwarder, for the described foreign inode. * @private From ce0bd6624f5564c7d723f49df437797989fee808 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 11 Aug 2018 11:44:33 +1200 Subject: [PATCH 1135/2137] Abstract away procedure for unlinking and linking an inode --- lib/filesystem.js | 82 +++++++++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 35 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 43adfaf8..3d7e3d81 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -317,14 +317,51 @@ FS.prototype.should_be_linked = function(inode) return !this.is_forwarder(inode) || this.is_root_forwarder(inode); }; +/** + * @private + * @param {number} idx + * @param {number} parentid + */ +FS.prototype.link_under_dir = function(idx, parentid) +{ + const inode = this.inodes[idx]; + const parent_inode = this.inodes[parentid]; + dbg_assert(!this.is_forwarder(parent_inode), "Filesystem: Shouldn't link non-root fowarders"); + inode.parentid = parentid; + inode.nextid = parent_inode.firstid; + parent_inode.firstid = idx; + parent_inode.updatedir = true; +}; + +/** + * @private + * @param {number} idx + */ +FS.prototype.unlink_from_dir = function(idx) +{ + const inode = this.inodes[idx]; + const parent_inode = this.inodes[inode.parentid]; + dbg_assert(!this.is_forwarder(parent_inode), "Filesystem: Can't unlink non-root fowarders"); + if(parent_inode.firstid === idx) + { + parent_inode.firstid = inode.nextid; + } + else + { + const id = this.FindPreviousID(idx); + dbg_assert(id !== -1, + "Filesystem: Could not find previous sibling of (" + this.GetInode(idx).name + + ") while unlinking from it's parent"); + this.inodes[id].nextid = inode.nextid; + } + parent_inode.updatedir = true; +}; + FS.prototype.PushInode = function(inode) { if (inode.parentid != -1) { this.inodes.push(inode); inode.fid = this.inodes.length - 1; - var parent_node = this.inodes[inode.parentid]; - parent_node.updatedir = true; - inode.nextid = parent_node.firstid; - parent_node.firstid = this.inodes.length-1; + this.link_under_dir(this.inodes.length - 1, inode.parentid); return; } else { if (this.inodes.length == 0) { // if root directory @@ -586,27 +623,11 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { var idx = oldid; // idx contains the id which we want to rename var inode = this.inodes[idx]; - // remove inode ids - if (this.inodes[inode.parentid].firstid == idx) { - this.inodes[inode.parentid].firstid = inode.nextid; - } else { - var id = this.FindPreviousID(idx); - if (id == -1) { - message.Debug("Error in Filesystem: Cannot find previous id of inode"); - message.Abort(); - } - this.inodes[id].nextid = inode.nextid; - } + this.unlink_from_dir(idx); + this.link_under_dir(idx, newdirid); - inode.parentid = newdirid; inode.name = newname; inode.qid.version++; - - inode.nextid = this.inodes[inode.parentid].firstid; - this.inodes[inode.parentid].firstid = idx; - - this.inodes[olddirid].updatedir = true; - this.inodes[newdirid].updatedir = true; this.inodes[olddirid].nlinks--; this.inodes[newdirid].nlinks++; @@ -739,6 +760,7 @@ FS.prototype.Unlink = function(idx) { this.NotifyListeners(idx, 'delete'); if (idx == 0) return false; // root node cannot be deleted var inode = this.GetInode(idx); + const parent_inode = this.inodes[this.GetParent(idx)]; //message.Debug("Unlink " + inode.name); // check if directory is not empty @@ -746,20 +768,10 @@ FS.prototype.Unlink = function(idx) { if (inode.firstid != -1) return false; } - // update ids - if (this.inodes[inode.parentid].firstid == idx) { - this.inodes[inode.parentid].firstid = inode.nextid; - } else { - var id = this.FindPreviousID(idx); - if (id == -1) { - message.Debug("Error in Filesystem: Cannot find previous id of inode"); - message.Abort(); - } - this.inodes[id].nextid = inode.nextid; - } + this.unlink_from_dir(idx); + // don't delete the content. The file is still accessible - this.inodes[inode.parentid].updatedir = true; - this.inodes[inode.parentid].nlinks--; + parent_inode.nlinks--; inode.status = STATUS_UNLINKED; inode.nextid = -1; inode.firstid = -1; From 3fcdf62eef6b506d3b4bebd0dff9f8bbffd216e3 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 11 Aug 2018 11:49:07 +1200 Subject: [PATCH 1136/2137] Fix fs.GetFullPath and fs.FindPreviousID forwarding Use this.GetInode(idx) to get metadata such as filename and size. Use this.inodes to navigate about the filesystem graph --- lib/filesystem.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 3d7e3d81..28e390ee 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -715,15 +715,16 @@ FS.prototype.GetFullPath = function(idx) { var path = ""; while(idx != 0) { - path = "/" + this.inodes[idx].name + path; - idx = this.inodes[idx].parentid; + path = "/" + this.GetInode(idx).name + path; + idx = this.GetParent(idx); } return path.substring(1); }; // no double linked list. So, we need this FS.prototype.FindPreviousID = function(idx) { - var inode = this.GetInode(idx); + var inode = this.inodes[idx]; + dbg_assert(this.should_be_linked(inode), "Filesystem FindPreviousID assumes linked inode"); var id = this.inodes[inode.parentid].firstid; while(id != -1) { if (this.inodes[id].nextid == idx) return id; From b080b075bda5756437052d77d705051402999f93 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 11 Aug 2018 11:53:14 +1200 Subject: [PATCH 1137/2137] Handle forwarding in fs.Unlink --- lib/filesystem.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 28e390ee..4c894838 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -760,10 +760,19 @@ FS.prototype.Link = function(targetid, name, parentid) FS.prototype.Unlink = function(idx) { this.NotifyListeners(idx, 'delete'); if (idx == 0) return false; // root node cannot be deleted - var inode = this.GetInode(idx); + var inode = this.inodes[idx]; const parent_inode = this.inodes[this.GetParent(idx)]; //message.Debug("Unlink " + inode.name); + // forward if necessary + if(!this.should_be_linked(inode)) + { + const foreign_id = inode.foreign_id; + const success = this.follow_fs(inode).Unlink(foreign_id); + this.delete_forwarder(inode); + return success; + } + // check if directory is not empty if ((inode.mode&S_IFMT) == S_IFDIR) { if (inode.firstid != -1) return false; From d218b76994bff114afe5865210bdb648815add04 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 11 Aug 2018 12:02:08 +1200 Subject: [PATCH 1138/2137] Handle forwarding for fs events and file loading --- lib/filesystem.js | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 4c894838..ddfd91ae 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -133,18 +133,40 @@ FS.prototype.set_state = function(state) // ----------------------------------------------------- +FS.prototype.IsLoading = function() +{ + if(this.filesinloadingqueue > 0) return true; + for(const mount of this.mounts) + { + if(mount.fs.IsLoading()) return true; + } + return false; +}; + FS.prototype.AddEvent = function(id, OnEvent) { - var inode = this.GetInode(id); + var inode = this.inodes[id]; if (inode.status == STATUS_OK) { OnEvent(); return; } - this.events.push({id: id, OnEvent: OnEvent}); + else if(this.is_forwarder(inode)) + { + this.follow_fs(inode).AddEvent(inode.foreign_id, OnEvent); + return; + } + else + { + this.events.push({id: id, OnEvent: OnEvent}); + } }; FS.prototype.HandleEvent = function(id) { - - if (this.filesinloadingqueue == 0) { + const inode = this.inodes[id]; + if(this.is_forwarder(inode)) + { + this.follow_fs(inode).HandleEvent(inode.foreign_id); + } + if (!this.IsLoading()) { this.OnLoaded(); this.OnLoaded = function() {}; } @@ -263,7 +285,14 @@ FS.prototype.LoadDir = function(inode, children) // Loads the data from a url for a specific inode FS.prototype.LoadFile = function(idx) { var inode = this.inodes[idx]; - if (inode.status != STATUS_ON_SERVER) { + if(this.is_forwarder(inode)) + { + // Events handled by child filesystem. + this.follow_fs(inode).LoadFile(inode.foreign_id); + return; + } + else if(inode.status != STATUS_ON_SERVER) + { return; } inode.status = STATUS_LOADING; From 004182adc8d202c3ec4071225e6cede4e82d8efe Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 11 Aug 2018 12:03:47 +1200 Subject: [PATCH 1139/2137] Handle forwarding for fs.Create* methods --- lib/filesystem.js | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/lib/filesystem.js b/lib/filesystem.js index ddfd91ae..611a6c85 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -511,7 +511,15 @@ FS.prototype.CreateInode = function() { }; +// Note: parentid = -1 for initial root directory. FS.prototype.CreateDirectory = function(name, parentid) { + const parent_inode = this.inodes[parentid]; + if(parentid >= 0 && this.is_forwarder(parent_inode)) + { + const foreign_parentid = parent_inode.foreign_id; + const foreign_id = this.follow_fs(parent_inode).CreateDirectory(name, foreign_parentid); + return this.create_forwarder(parent_inode.mount_id, foreign_id); + } var x = this.CreateInode(); x.name = name; x.parentid = parentid; @@ -531,6 +539,13 @@ FS.prototype.CreateDirectory = function(name, parentid) { }; FS.prototype.CreateFile = function(filename, parentid) { + const parent_inode = this.inodes[parentid]; + if(this.is_forwarder(parent_inode)) + { + const foreign_parentid = parent_inode.foreign_id; + const foreign_id = this.follow_fs(parent_inode).CreateFile(filename, foreign_parentid); + return this.create_forwarder(parent_inode.mount_id, foreign_id); + } var x = this.CreateInode(); x.dirty = true; x.name = filename; @@ -547,6 +562,14 @@ FS.prototype.CreateFile = function(filename, parentid) { FS.prototype.CreateNode = function(filename, parentid, major, minor) { + const parent_inode = this.inodes[parentid]; + if(this.is_forwarder(parent_inode)) + { + const foreign_parentid = parent_inode.foreign_id; + const foreign_id = + this.follow_fs(parent_inode).CreateNode(filename, foreign_parentid, major, minor); + return this.create_forwarder(parent_inode.mount_id, foreign_id); + } var x = this.CreateInode(); x.name = filename; x.parentid = parentid; @@ -562,6 +585,14 @@ FS.prototype.CreateNode = function(filename, parentid, major, minor) { }; FS.prototype.CreateSymlink = function(filename, parentid, symlink) { + const parent_inode = this.inodes[parentid]; + if(this.is_forwarder(parent_inode)) + { + const foreign_parentid = parent_inode.foreign_id; + const foreign_id = + this.follow_fs(parent_inode).CreateSymlink(filename, foreign_parentid, symlink); + return this.create_forwarder(parent_inode.mount_id, foreign_id); + } var x = this.CreateInode(); x.name = filename; x.parentid = parentid; @@ -576,6 +607,14 @@ FS.prototype.CreateSymlink = function(filename, parentid, symlink) { }; FS.prototype.CreateTextFile = function(filename, parentid, str) { + const parent_inode = this.inodes[parentid]; + if(this.is_forwarder(parent_inode)) + { + const foreign_parentid = parent_inode.foreign_id; + const foreign_id = + this.follow_fs(parent_inode).CreateTextFile(filename, foreign_parentid, str); + return this.create_forwarder(parent_inode.mount_id, foreign_id); + } var id = this.CreateFile(filename, parentid); var x = this.inodes[id]; var data = this.inodedata[id] = new Uint8Array(str.length); @@ -591,6 +630,14 @@ FS.prototype.CreateTextFile = function(filename, parentid, str) { * @param {Uint8Array} buffer */ FS.prototype.CreateBinaryFile = function(filename, parentid, buffer) { + const parent_inode = this.inodes[parentid]; + if(this.is_forwarder(parent_inode)) + { + const foreign_parentid = parent_inode.foreign_id; + const foreign_id = + this.follow_fs(parent_inode).CreateBinaryFile(filename, foreign_parentid, buffer); + return this.create_forwarder(parent_inode.mount_id, foreign_id); + } var id = this.CreateFile(filename, parentid); var x = this.inodes[id]; var data = this.inodedata[id] = new Uint8Array(buffer.length); From 687607569b3074e335d0a84040623998d5f2fd03 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 11 Aug 2018 12:06:29 +1200 Subject: [PATCH 1140/2137] Handle forwarding for open, close, read, and write --- lib/filesystem.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 611a6c85..0d729183 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -649,6 +649,7 @@ FS.prototype.CreateBinaryFile = function(filename, parentid, buffer) { FS.prototype.OpenInode = function(id, mode) { + // Fully resolve inode. var inode = this.GetInode(id); if ((inode.mode&S_IFMT) == S_IFDIR) { this.FillDirectory(id); @@ -672,6 +673,7 @@ FS.prototype.OpenInode = function(id, mode) { FS.prototype.CloseInode = function(id) { //message.Debug("close: " + this.GetFullPath(id)); + // Fully resolve inode. var inode = this.GetInode(id); if (inode.status == STATUS_UNLINKED) { //message.Debug("Filesystem: Delete unlinked file"); @@ -715,6 +717,14 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { FS.prototype.Write = function(id, offset, count, buffer) { this.NotifyListeners(id, 'write'); var inode = this.inodes[id]; + + if(this.is_forwarder(inode)) + { + const foreign_id = inode.foreign_id; + this.follow_fs(inode).Write(foreign_id, offset, count, buffer); + return; + } + inode.dirty = true; var data = this.inodedata[id]; @@ -731,7 +741,13 @@ FS.prototype.Write = function(id, offset, count, buffer) { FS.prototype.Read = function(inodeid, offset, count) { - if(!this.inodedata[inodeid]) + const inode = this.inodes[inodeid]; + if(this.is_forwarder(inode)) + { + const foreign_id = inode.foreign_id; + return this.follow_fs(inode).Read(foreign_id, offset, count); + } + else if(!this.inodedata[inodeid]) { return null; } From 71cb654502953d695a94a65e8a2e7b59c41bad73 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 11 Aug 2018 12:09:09 +1200 Subject: [PATCH 1141/2137] Partially handle forwarding for fs.FillDirectory Unresolved bug: Calling fs.FillDirectory on a mountpoint gives incorrect information. ".." entry should describe parent of mountpoint, but currently describes itself. --- lib/filesystem.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 0d729183..69eaeb79 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -1027,7 +1027,14 @@ FS.prototype.Check = function() { FS.prototype.FillDirectory = function(dirid) { - var inode = this.GetInode(dirid); + const inode = this.inodes[dirid]; + if(this.is_forwarder(inode)) + { + // XXX: The ".." of a mountpoint should point back to an inode in this fs. + // Otherwise, ".." gets the wrong qid and mode. + this.follow_fs(inode).FillDirectory(inode.foreign_id); + return; + } if (!inode.updatedir) return; var parentid = inode.parentid; if (parentid == -1) parentid = 0; // if root directory point to the root directory From d98ec5f37baaf4e9d6a672b8ee9d561ee9387ace Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 11 Aug 2018 12:10:51 +1200 Subject: [PATCH 1142/2137] Handle forwarding for our dummy fs.Link method --- lib/filesystem.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 69eaeb79..28aa7046 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -836,14 +836,26 @@ FS.prototype.Link = function(targetid, name, parentid) inode.mode = inodetarget.mode; inode.size = inodetarget.size; inode.symlink = inodetarget.symlink; + var data = this.inodedata[this.inodes.length] = new Uint8Array(inode.size); if(targetdata) { data.set(targetdata, 0); } inode.name = name; - inode.parentid = parentid; - this.PushInode(inode); + + if(this.is_forwarder(this.inodes[parentid])) + { + inode.parentid = 0; + const newid = this.inodes.length; + this.PushInode(inode); + this.Rename(0, name, parentid, name); + } + else + { + inode.parentid = parentid; + this.PushInode(inode); + } //inode.uid = inodetarget.uid; //inode.gid = inodetarget.gid; //inode.mode = inodetarget.mode | S_IFLNK; From b6b6b8cada35ef8a068a8790ebbd7652ddf00e0f Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 11 Aug 2018 12:13:50 +1200 Subject: [PATCH 1143/2137] Implement Rename - moving files between filesystems --- lib/filesystem.js | 165 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 155 insertions(+), 10 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 28aa7046..f0e8e80e 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -46,7 +46,7 @@ var STATUS_FORWARDING = 0x5; /** @constructor */ function FS(baseurl) { - /** @type {Array.} */ + /** @type {Array.} */ this.inodes = []; this.events = []; @@ -502,6 +502,46 @@ Inode.prototype.set_state = function(state) this.foreign_id = state[24]; }; +/** + * Clones given inode to new idx, effectively diverting the inode to new idx value. + * Hence, original idx value is now free to use without losing the original information. + * @private + * @param {number} old_idx Target to divert. + * @return {number} New idx of diversion. + */ +FS.prototype.divert = function(old_idx) +{ + dbg_assert(old_idx !== 0, "Filesystem: can't divert root inode"); + dbg_assert(old_idx > 0, "Filesystem: invalid inode idx: " + old_idx); + + const old_inode = this.inodes[old_idx]; + const new_inode = new Inode(-1); + + // Shallow copy is alright. + Object.assign(new_inode, old_inode); + + const idx = this.inodes.length; + this.inodes.push(new_inode); + new_inode.fid = idx; + + // Relink references + if(this.is_forwarder(old_inode)) + { + this.mounts[old_inode.mount_id].backtrack.set(old_inode.foreign_id, idx); + } + if(this.should_be_linked(old_inode)) + { + this.unlink_from_dir(old_idx); + this.link_under_dir(idx, old_inode.parentid); + } + + // Relocate local data if any. + this.inodedata[idx] = this.inodedata[old_idx]; + delete this.inodedata[old_idx]; + + return idx; +}; + FS.prototype.CreateInode = function() { //console.log("CreateInode", Error().stack); const now = Math.round(Date.now() / 1000); @@ -689,10 +729,12 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { return true; } var oldid = this.Search(olddirid, oldname); - var oldpath = this.GetFullPath(oldid); - if (oldid == -1) { + if(oldid === -1) + { return false; } + var oldpath = this.GetFullPath(oldid); + var newid = this.Search(newdirid, newname); if (newid != -1) { this.Unlink(newid); @@ -700,14 +742,102 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { var idx = oldid; // idx contains the id which we want to rename var inode = this.inodes[idx]; + const olddir = this.inodes[olddirid]; + const newdir = this.inodes[newdirid]; - this.unlink_from_dir(idx); - this.link_under_dir(idx, newdirid); + if(!this.is_forwarder(olddir) && !this.is_forwarder(newdir)) + { + // Move inode within current filesystem. - inode.name = newname; - inode.qid.version++; - this.inodes[olddirid].nlinks--; - this.inodes[newdirid].nlinks++; + this.unlink_from_dir(idx); + this.link_under_dir(idx, newdirid); + + inode.name = newname; + inode.qid.version++; + + this.inodes[olddirid].nlinks--; + this.inodes[newdirid].nlinks++; + } + else if(this.is_forwarder(olddir) && olddir.mount_id === newdir.mount_id) + { + // Move inode within the same child filesystem. + + const success = this.follow_fs(olddir) + .Rename(olddir.foreign_id, oldname, newdir.foreign_id, newname); + + if(!success) return false; + } + else if(this.GetInode(idx).parentid === -1) + { + // The actual inode is a root of some descendant filesystem. + // Moving mountpoint across fs not supported - needs to update all corresponding forwarders. + dbg_log("Attempted to move mountpoint: " + oldname, LOG_9P); + return false; + } + else + { + // Jump between filesystems. + + // Can't work with both old and new inode information without first diverting the old + // information into a new idx value. + const diverted_old_idx = this.divert(idx); + const old_real_inode = this.GetInode(idx); + + const data = this.Read(diverted_old_idx, 0, old_real_inode.size); + + if(this.is_forwarder(newdir)) + { + // Create new inode. + const foreign_fs = this.follow_fs(newdir); + const foreign_id = foreign_fs.CreateFile(newname, newdir.foreign_id); + const new_real_inode = foreign_fs.GetInode(foreign_id); + + // Copy over inode info. Reassign info we want to keep. + Object.assign(new_real_inode, old_real_inode, + { + fid: new_real_inode.fid, + parentid: new_real_inode.parentid, + nextid: new_real_inode.nextid, + firstid: -1, + name: newname, + }); + + // Point to this new location. + this.set_forwarder(idx, newdir.mount_id, foreign_id); + } + else + { + // Replace current forwarder with real inode. + this.delete_forwarder(inode); + Object.assign(inode, old_real_inode); + + // Link into new location in this filesystem. + inode.firstid = -1; + this.link_under_dir(idx, newdirid); + } + + // Rewrite data to newly created destination. + this.ChangeSize(idx, old_real_inode.size); + if(data && data.length) + { + this.Write(idx, 0, data.length, data); + } + + // Move children to newly created destination. + if(this.IsDirectory(idx)) + { + for(const child_filename of this.GetChildren(diverted_old_idx)) + { + const success = this.Rename(diverted_old_idx, child_filename, idx, child_filename); + if(!success) return false; + } + } + + // Perform destructive changes only after migration succeeded. + this.DeleteData(diverted_old_idx); + const success = this.Unlink(diverted_old_idx); + if(!success) return false; + } this.NotifyListeners(idx, "rename", {oldpath: oldpath}); @@ -736,7 +866,10 @@ FS.prototype.Write = function(id, offset, count, buffer) { if (inode.size < (offset+count)) { inode.size = offset + count; } - data.set(buffer.subarray(0, count), offset); + if(buffer) + { + data.set(buffer.subarray(0, count), offset); + } }; FS.prototype.Read = function(inodeid, offset, count) @@ -894,6 +1027,18 @@ FS.prototype.Unlink = function(idx) { return true; }; +FS.prototype.DeleteData = function(idx) +{ + const inode = this.inodes[idx]; + if(this.is_forwarder(inode)) + { + this.follow_fs(inode).DeleteData(inode.foreign_id); + return; + } + inode.size = 0; + delete this.inodedata[idx]; +}; + FS.prototype.GetInode = function(idx) { dbg_assert(!isNaN(idx), "Filesystem GetInode: NaN idx"); From 121b9c3b96262dc76df40922e67a05a9cae76ef0 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 11 Aug 2018 12:15:02 +1200 Subject: [PATCH 1144/2137] Incorperate mounted filesystems in statistics --- lib/filesystem.js | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index f0e8e80e..2aa46430 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -914,16 +914,34 @@ FS.prototype.Search = function(parentid, name) { FS.prototype.CountUsedInodes = function() { - return this.inodes.length; + let count = this.inodes.length; + for(const { fs, backtrack } of this.mounts) + { + count += fs.CountUsedInodes(); + + // Forwarder inodes don't count. + count -= backtrack.size; + } + return count; }; FS.prototype.CountFreeInodes = function() { - return 1024 * 1024; + let count = 1024 * 1024; + for(const { fs } of this.mounts) + { + count += fs.CountFreeInodes(); + } + return count; }; FS.prototype.GetTotalSize = function() { - return this.used_size; + let size = this.used_size; + for(const { fs } of this.mounts) + { + size += fs.GetTotalSize(); + } + return size; //var size = 0; //for(var i=0; i Date: Sat, 11 Aug 2018 12:18:25 +1200 Subject: [PATCH 1145/2137] Handle forwarding and root inode in other api methods Root inode dosn't have a parent. Methods should work fine with root inodes too. --- lib/filesystem.js | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 2aa46430..f56359d4 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -1118,6 +1118,18 @@ FS.prototype.SearchPath = function(path) { // ----------------------------------------------------- FS.prototype.GetRecursiveList = function(dirid, list) { + if(this.is_forwarder(this.inodes[dirid])) + { + const foreign_fs = this.follow_fs(this.inodes[dirid]); + const foreign_dirid = this.inodes[dirid].foreign_id; + const foreign_list = []; + foreign_fs.GetRecursiveList(foreign_dirid, foreign_list); + for(const foreign_id of foreign_list) + { + list.push(this.get_forwarder(this.inodes[dirid].mount_id, foreign_id)); + } + return; + } var id = this.inodes[dirid].firstid; while(id != -1) { list.push(id); @@ -1131,18 +1143,19 @@ FS.prototype.GetRecursiveList = function(dirid, list) { FS.prototype.RecursiveDelete = function(path) { var toDelete = []; var ids = this.SearchPath(path); - if (ids.parentid == -1 || ids.id == -1) return; + if(ids.id === -1) return; this.GetRecursiveList(ids.id, toDelete); for(var i=toDelete.length-1; i>=0; i--) - this.Unlink(toDelete[i]); + dbg_assert(this.Unlink(toDelete[i]), + "Filesystem RecursiveDelete failed at inode=" + toDelete[i]); }; FS.prototype.DeleteNode = function(path) { var ids = this.SearchPath(path); - if (ids.parentid == -1 || ids.id == -1) return; + if (ids.id == -1) return; if ((this.inodes[ids.id].mode&S_IFMT) == S_IFREG){ this.Unlink(ids.id); @@ -1187,7 +1200,7 @@ FS.prototype.Check = function() { } var inode = this.GetInode(i); - if (inode.parentid < 0) { + if (this.GetParent(i) < 0) { message.Debug("Error in filesystem: negative parent id " + i); } var n = inode.name.length; From 89592e8283e5a5b6d9f08bbd0fa70971c8d670c0 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 11 Aug 2018 12:20:51 +1200 Subject: [PATCH 1146/2137] Use fs.RecursiveDelete before each fs test Don't need to involve the guest os to delete everything. --- tests/devices/virtio_9p.js | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index dffbfd21..1f360bb7 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -1304,21 +1304,26 @@ function nuke_fs() console.log("\nPreparing test #%d: %s", test_num, tests[test_num].name); console.log(" Nuking /mnt"); - emulator.serial0_send("rm -rf /mnt/*\n"); - emulator.serial0_send("echo prep-nuke-done\n"); - next_trigger = "prep-nuke-done"; - next_trigger_handler = tests[test_num].use_fsjson ? reload_fsjson : do_mounts; + emulator.fs9p.RecursiveDelete(""); + reload_fsjson(); } function reload_fsjson() { - console.log(" Reloading files from json"); - emulator.fs9p.OnJSONLoaded(testfsjson); - emulator.fs9p.OnLoaded = () => + if(tests[test_num].use_fsjson) + { + console.log(" Reloading files from json"); + emulator.fs9p.OnJSONLoaded(testfsjson); + emulator.fs9p.OnLoaded = () => + { + do_mounts(); + }; + } + else { do_mounts(); - }; + } } function do_mounts() From ff11e9c00f7223dde6358a4eddffd277af2297f7 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Mon, 13 Aug 2018 20:52:07 +1200 Subject: [PATCH 1147/2137] Minor: better rename-failure logs, comments, & unnecessary return --- lib/filesystem.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index f56359d4..bda5c43e 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -147,12 +147,10 @@ FS.prototype.AddEvent = function(id, OnEvent) { var inode = this.inodes[id]; if (inode.status == STATUS_OK) { OnEvent(); - return; } else if(this.is_forwarder(inode)) { this.follow_fs(inode).AddEvent(inode.foreign_id, OnEvent); - return; } else { @@ -771,7 +769,7 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { { // The actual inode is a root of some descendant filesystem. // Moving mountpoint across fs not supported - needs to update all corresponding forwarders. - dbg_log("Attempted to move mountpoint: " + oldname, LOG_9P); + dbg_log("XXX: Attempted to move mountpoint (" + oldname + ") - skipped", LOG_9P); return false; } else @@ -1424,7 +1422,10 @@ function FSMountInfo(filesystem) /** @type {FS}*/ this.fs = filesystem; - /** @type {!Map} */ + /** + * Maps foreign inode id back to local inode id. + * @type {!Map} + */ this.backtrack = new Map(); } From 8cb6f2324899ed23b0ac94c0371b4fd13abc87c6 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Mon, 13 Aug 2018 21:12:38 +1200 Subject: [PATCH 1148/2137] Fix filesystem mount state saving --- lib/filesystem.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index bda5c43e..ce65e1ca 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -98,7 +98,7 @@ FS.prototype.get_state = function() state[3] = this.total_size; state[4] = this.used_size; state[5] = this.baseurl; - state[6] = this.mounts.map(mnt => mnt.fs); + state[6] = this.mounts; return state; }; @@ -1434,11 +1434,7 @@ FSMountInfo.prototype.get_state = function() const state = []; state[0] = this.fs; - state[1] = []; - for(const entry of this.backtrack.entries()) - { - state[1].push(entry); - } + state[1] = [...this.backtrack]; return state; }; @@ -1446,7 +1442,7 @@ FSMountInfo.prototype.get_state = function() FSMountInfo.prototype.set_state = function(state) { this.fs = new FS(undefined); - fs.set_state(state[0]); + this.fs.set_state(state[0]); this.backtrack = new Map(state[1]); }; From 23080e27310f72e444e8ad8387d6e6a8406f9f9f Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Mon, 13 Aug 2018 22:34:39 +1200 Subject: [PATCH 1149/2137] Isolate filesystem qid counting to each v86 instance --- lib/filesystem.js | 21 ++++++++++++++------- src/browser/starter.js | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index ce65e1ca..e530eb42 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -44,14 +44,19 @@ var STATUS_FORWARDING = 0x5; /** @const */ var JSONFS_IDX_TARGET = 6; -/** @constructor */ -function FS(baseurl) { +/** + * @constructor + * @param {string=} baseurl + * @param {{ last_qidnumber: number }=} qidcounter Another fs's qidcounter to synchronise with. + */ +function FS(baseurl, qidcounter) { /** @type {Array.} */ this.inodes = []; this.events = []; this.baseurl = baseurl; + this.qidcounter = qidcounter || { last_qidnumber: 0 }; this.filesinloadingqueue = 0; this.OnLoaded = function() {}; @@ -82,14 +87,12 @@ function FS(baseurl) { this.CreateDirectory("", -1); } -FS.last_qidnumber = 0; - FS.prototype.get_state = function() { const state = []; state[0] = this.inodes; - state[1] = FS.last_qidnumber; + state[1] = this.qidcounter.last_qidnumber; state[2] = []; for(let entry of Object.entries(this.inodedata)) { @@ -106,7 +109,7 @@ FS.prototype.get_state = function() FS.prototype.set_state = function(state) { this.inodes = state[0].map(state => { const inode = new Inode(0); inode.set_state(state); return inode; }); - FS.last_qidnumber = state[1]; + this.qidcounter.last_qidnumber = state[1]; this.inodedata = {}; for(let [key, value] of state[2]) { @@ -126,6 +129,7 @@ FS.prototype.set_state = function(state) { const mount = new FSMountInfo(null); mount.set_state(mount_state); + mount.fs.qidcounter = this.qidcounter; this.mounts.push(mount); } }; @@ -543,7 +547,7 @@ FS.prototype.divert = function(old_idx) FS.prototype.CreateInode = function() { //console.log("CreateInode", Error().stack); const now = Math.round(Date.now() / 1000); - const inode = new Inode(++FS.last_qidnumber); + const inode = new Inode(++this.qidcounter.last_qidnumber); inode.atime = inode.ctime = inode.mtime = now; return inode; }; @@ -1571,6 +1575,9 @@ FS.prototype.follow_fs = function(inode) */ FS.prototype.Mount = function(path, fs) { + dbg_assert(fs.qidcounter === this.qidcounter, + "Cannot mount filesystem whose qid numbers aren't synchronised with current filesystem."); + const path_infos = this.SearchPath(path); if(path_infos.id === -1) diff --git a/src/browser/starter.js b/src/browser/starter.js index 6c0718ed..a0f3a84d 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -1081,7 +1081,7 @@ V86Starter.prototype.serial0_send = function(data) */ V86Starter.prototype.mount_fs = function(path, baseurl, basefs, callback) { - const newfs = new FS(baseurl); + const newfs = new FS(baseurl, this.fs9p.qidcounter); const mount = () => { const idx = this.fs9p.Mount(path, newfs); From c66731d55d27f5900bfa06008f05e4b9986f70cd Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Mon, 13 Aug 2018 23:03:28 +1200 Subject: [PATCH 1150/2137] Properly forward fs.Open/CloseInode --- lib/filesystem.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index e530eb42..c1821052 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -691,8 +691,11 @@ FS.prototype.CreateBinaryFile = function(filename, parentid, buffer) { FS.prototype.OpenInode = function(id, mode) { - // Fully resolve inode. - var inode = this.GetInode(id); + var inode = this.inodes[id]; + if(this.is_forwarder(inode)) + { + return this.follow_fs(inode).OpenInode(inode.foreign_id, mode); + } if ((inode.mode&S_IFMT) == S_IFDIR) { this.FillDirectory(id); } @@ -715,8 +718,11 @@ FS.prototype.OpenInode = function(id, mode) { FS.prototype.CloseInode = function(id) { //message.Debug("close: " + this.GetFullPath(id)); - // Fully resolve inode. - var inode = this.GetInode(id); + var inode = this.inodes[id]; + if(this.is_forwarder(inode)) + { + return this.follow_fs(inode).CloseInode(inode.foreign_id); + } if (inode.status == STATUS_UNLINKED) { //message.Debug("Filesystem: Delete unlinked file"); inode.status = STATUS_INVALID; From 3fe75a913070665bdc947d9343a36544b7407b24 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Mon, 13 Aug 2018 23:06:52 +1200 Subject: [PATCH 1151/2137] Identify type of failure for fs.Rename using -errno convention --- lib/9p.js | 7 +++++-- lib/filesystem.js | 23 +++++++++++++---------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/lib/9p.js b/lib/9p.js index 5e362724..4248c299 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -587,8 +587,11 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { var newname = req[3]; message.Debug("[renameat]: oldname=" + oldname + " newname=" + newname); var ret = this.fs.Rename(this.fids[olddirfid].inodeid, oldname, this.fids[newdirfid].inodeid, newname); - if (ret == false) { - this.SendError(tag, "No such file or directory", ENOENT); + if (ret < 0) { + let error_message = ""; + if(ret === -ENOENT) error_message = "No such file or directory"; + else if(ret === -EPERM) error_message = "Operation not permitted"; + this.SendError(tag, error_message, -ret); this.SendReply(bufchain); break; } diff --git a/lib/filesystem.js b/lib/filesystem.js index c1821052..7070b4b4 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -731,15 +731,18 @@ FS.prototype.CloseInode = function(id) { } }; +/** + * @return {number} 0 if success, or -errno if failured. + */ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { // message.Debug("Rename " + oldname + " to " + newname); if ((olddirid == newdirid) && (oldname == newname)) { - return true; + return 0; } var oldid = this.Search(olddirid, oldname); if(oldid === -1) { - return false; + return -ENOENT; } var oldpath = this.GetFullPath(oldid); @@ -770,17 +773,17 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { { // Move inode within the same child filesystem. - const success = this.follow_fs(olddir) + const ret = this.follow_fs(olddir) .Rename(olddir.foreign_id, oldname, newdir.foreign_id, newname); - if(!success) return false; + if(ret < 0) return ret; } else if(this.GetInode(idx).parentid === -1) { // The actual inode is a root of some descendant filesystem. // Moving mountpoint across fs not supported - needs to update all corresponding forwarders. dbg_log("XXX: Attempted to move mountpoint (" + oldname + ") - skipped", LOG_9P); - return false; + return -EPERM; } else { @@ -836,20 +839,20 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { { for(const child_filename of this.GetChildren(diverted_old_idx)) { - const success = this.Rename(diverted_old_idx, child_filename, idx, child_filename); - if(!success) return false; + const ret = this.Rename(diverted_old_idx, child_filename, idx, child_filename); + if(ret < 0) return ret; } } // Perform destructive changes only after migration succeeded. this.DeleteData(diverted_old_idx); - const success = this.Unlink(diverted_old_idx); - if(!success) return false; + const ret = this.Unlink(diverted_old_idx); + if(ret < 0) return ret; } this.NotifyListeners(idx, "rename", {oldpath: oldpath}); - return true; + return 0; }; FS.prototype.Write = function(id, offset, count, buffer) { From e683e812fd25c6102a86adedf5ae4c908982eefe Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Tue, 14 Aug 2018 12:55:06 +1200 Subject: [PATCH 1152/2137] Mount only onto non-existent paths, existent parent If mountpoint already exists, then we're silently making its children inaccessible which may not be what we expected/intended. Create a new forwarder inode upon mounting. --- lib/9p.js | 1 + lib/filesystem.js | 30 ++++++++++++++++++------------ src/browser/starter.js | 22 +++++++++++++++++++++- tests/devices/virtio_9p.js | 1 + 4 files changed, 41 insertions(+), 13 deletions(-) diff --git a/lib/9p.js b/lib/9p.js index 4248c299..318380ab 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -18,6 +18,7 @@ const VIRTIO_9P_MAX_TAGLEN = 254; var EPERM = 1; /* Operation not permitted */ var ENOENT = 2; /* No such file or directory */ +var EEXIST = 17; /* File exists */ var EINVAL = 22; /* Invalid argument */ var EOPNOTSUPP = 95; /* Operation is not supported */ var ENOTEMPTY = 39; /* Directory not empty */ diff --git a/lib/filesystem.js b/lib/filesystem.js index 7070b4b4..dca731b2 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -1489,8 +1489,6 @@ FS.prototype.set_forwarder = function(idx, mount_id, foreign_id) */ FS.prototype.create_forwarder = function(mount_id, foreign_id) { - dbg_assert(foreign_id !== 0, "Filesystem: root forwarder should not be created."); - const inode = this.CreateInode(); const idx = this.inodes.length; @@ -1578,9 +1576,10 @@ FS.prototype.follow_fs = function(inode) }; /** - * Mount another filesystem onto an existing directory. - * @param {string} path Path to existing directrory relative to this filesystem. + * Mount another filesystem to given path. + * @param {string} path * @param {FS} fs + * @return {number} inode id of mount point if successful, or -errno if mounting failed. */ FS.prototype.Mount = function(path, fs) { @@ -1589,23 +1588,30 @@ FS.prototype.Mount = function(path, fs) const path_infos = this.SearchPath(path); - if(path_infos.id === -1) + if(path_infos.parentid === -1) { - dbg_log("Mount failed: path not found: " + path, LOG_9P); - return -1; + dbg_log("Mount failed: parent for path not found: " + path, LOG_9P); + return -ENOENT; + } + if(path_infos.id !== -1) + { + dbg_log("Mount failed: file already exists at path: " + path, LOG_9P); + return -EEXIST; } if(path_infos.forward_path) { const parent = this.inodes[path_infos.parentid]; - this.follow_fs(parent).Mount(path_infos.forward_path, fs); - return; + const ret = this.follow_fs(parent).Mount(path_infos.forward_path, fs); + if(ret < 0) return ret; + return this.get_forwarder(parent.mount_id, ret); } const mount_id = this.mounts.length; this.mounts.push(new FSMountInfo(fs)); - // Existing inode is already linked. Just set forwarding information. - this.set_forwarder(path_infos.id, mount_id, 0); + const idx = this.create_forwarder(mount_id, 0); + this.inodes[idx].name = path_infos.name; + this.link_under_dir(idx, path_infos.parentid); - return path_infos.id; + return idx; }; diff --git a/src/browser/starter.js b/src/browser/starter.js index a0f3a84d..1f78a272 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -1089,10 +1089,18 @@ V86Starter.prototype.mount_fs = function(path, baseurl, basefs, callback) { return; } - if(idx === -1) + if(idx === -ENOENT) { callback(new FileNotFoundError()); } + if(idx === -EEXIST) + { + callback(new FileExistsError()); + } + if(idx < 0) + { + callback(new Error("Failed to mount. Error number: " + (-idx))); + } else { callback(null); @@ -1204,6 +1212,18 @@ V86Starter.prototype.read_file = function(file, callback) } }; +/** + * @ignore + * @constructor + * + * @param {string=} message + */ +function FileExistsError(message) +{ + this.message = message || "File already exists"; +} +FileNotFoundError.prototype = Error.prototype; + /** * @ignore * @constructor diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index 1f360bb7..549d4658 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -1337,6 +1337,7 @@ function do_mounts() { const path = tests[test_num].mounts[mount_num].path; emulator.serial0_send("mkdir -p /mnt" + path + "\n"); + emulator.serial0_send("rmdir /mnt" + path + "\n"); emulator.serial0_send("echo done-premount\n"); next_trigger = "done-premount"; next_trigger_handler = () => mount(mount_num); From 0a4b6c838876beb773c312fb213fa52edea80269 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 15 Aug 2018 00:02:11 +1200 Subject: [PATCH 1153/2137] Add fs test for using .. across filesystems --- tests/devices/virtio_9p.js | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index 549d4658..84aa1e75 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -1251,6 +1251,45 @@ const tests = done(); }, }, + { + name: "Using '..' across filesystems", + timeout: 60, + mounts: + [ + { path: "/a/fs2" }, + ], + start: () => + { + emulator.serial0_send("mkdir /mnt/a/fs2/c\n"); + emulator.serial0_send("echo foobar > /mnt/a/fs2/../file\n"); + emulator.serial0_send("cd /mnt/a/fs2/c\n"); + emulator.serial0_send("echo baz >> ../../file\n"); + emulator.serial0_send("mv /mnt/a/file ../../renamed\n"); + emulator.serial0_send("cp /mnt/a/renamed ../../file\n"); + + emulator.serial0_send("echo start-capture;\\\n"); + + emulator.serial0_send("cat /mnt/a/file;\\\n"); + emulator.serial0_send("cat /mnt/a/renamed;\\\n"); + emulator.serial0_send("rm ../../renamed;\\\n"); + emulator.serial0_send("test ! -e /mnt/a/renamed && echo removed;\\\n"); + + emulator.serial0_send("cd /;\\\n"); + emulator.serial0_send("echo done-readdir-parent-mount\n"); + }, + capture_trigger: "start-capture", + end_trigger:"done-readdir-parent-mount", + end: (capture, done) => + { + assert_equal(capture, + "foobar\n" + + "baz\n" + + "foobar\n" + + "baz\n" + + "removed\n"); + done(); + }, + }, ]; let test_num = 0; From 4a76c66ff3d2d3f8d047ef94115600154b180889 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 15 Aug 2018 23:03:45 +1200 Subject: [PATCH 1154/2137] Improve tests for fs.Rename across mounts - Test both file and directory. - Test combinations of forwarder/non-forwarder source/destinations - Test different destination filenames - Test empty file Can't test early failure behaviour when destination can't be unlinked, since right now only non-empty directories and root directories can't be unlinked and busybox's mv program does not support mv --no-target-directory. --- tests/devices/virtio_9p.js | 68 +++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 19 deletions(-) diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index 84aa1e75..26bf7ddf 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -1177,8 +1177,9 @@ const tests = ], start: () => { - emulator.serial0_send("echo foobar > /mnt/file\n"); + emulator.serial0_send("echo foobar > /mnt/fs3/file\n"); emulator.serial0_send("mkdir /mnt/a/b/fs2/dir\n"); + emulator.serial0_send("mkdir /mnt/fs3/fs4/fs5/otherdir\n"); emulator.serial0_send("echo contents > /mnt/a/b/fs2/dir/child\n"); // Using tail -f to keep 'file' open for modification in bg while it is being moved. @@ -1187,35 +1188,58 @@ const tests = emulator.serial0_send("mkfifo /mnt/fs3/fifo_intermediate\n"); emulator.serial0_send("tail -f /mnt/fs3/fifo > /mnt/fs3/fifo_intermediate &\n"); emulator.serial0_send('echo "$!" > /mnt/tailpid\n'); - emulator.serial0_send('{ sed "/EOF/q" < /mnt/fs3/fifo_intermediate && kill "$(cat /mnt/tailpid)"; } >> /mnt/file &\n'); + emulator.serial0_send('{ sed "/EOF/q" < /mnt/fs3/fifo_intermediate && kill "$(cat /mnt/tailpid)"; } >> /mnt/fs3/file &\n'); emulator.serial0_send("echo start-capture; \\\n"); emulator.serial0_send("echo untouched > /mnt/fs3/fifo; \\\n"); - emulator.serial0_send("{ mv /mnt/file /mnt/renamed && "); - emulator.serial0_send(" echo renamed > /mnt/fs3/fifo; }; \\\n"); + // File from forwarder to non-forwarder. Divert forwarder file. + emulator.serial0_send("{ mv /mnt/fs3/file /mnt/file1 &&"); + emulator.serial0_send(" echo file jump to root > /mnt/fs3/fifo; }; \\\n"); - emulator.serial0_send("{ mv /mnt/renamed /mnt/fs3/file &&"); + // File from non-forwarder to forwarder. Divert non-forwarder file. + emulator.serial0_send("{ mv /mnt/file1 /mnt/fs3/file2 &&"); emulator.serial0_send(" echo file jump filesystems > /mnt/fs3/fifo; }; \\\n"); - emulator.serial0_send("{ mv /mnt/fs3/file /mnt/a/b/fs2/dir/file && "); - emulator.serial0_send(" echo moved to dir > /mnt/fs3/fifo; }; \\\n"); + // File rename within the same foreign filesystem. Divert non-forwarder file. + emulator.serial0_send("{ mv /mnt/fs3/file2 /mnt/fs3/file3 && "); + emulator.serial0_send(" echo file renamed > /mnt/fs3/fifo; }; \\\n"); - emulator.serial0_send("{ mv /mnt/a/b/fs2/dir /mnt/fs3/fs4/fs5/dir && "); + // File from forwarder to forwarder under directory. Divert forwarder file. + emulator.serial0_send("{ mv /mnt/fs3/file3 /mnt/a/b/fs2/dir/file4 && "); + emulator.serial0_send(" echo file move to dir > /mnt/fs3/fifo; }; \\\n"); + + // Directory from forwarder to forwarder. + emulator.serial0_send("{ mv /mnt/a/b/fs2/dir /mnt/fs3/fs4/fs5/dir1 && "); emulator.serial0_send(" echo dir jump filesystems > /mnt/fs3/fifo; }; \\\n"); + // Moving mountpoint across filesystems. emulator.serial0_send("{ mv /mnt/fs3/fs4 /mnt/a/b/fs2/fs4 2>/dev/null || "); emulator.serial0_send(" echo move mount point across - fails > /mnt/fs3/fifo; }; \\\n"); - emulator.serial0_send("{ mv /mnt/fs3/fs4/fs5 /mnt/fs5 2>/dev/null || "); emulator.serial0_send(" echo move mount point upwards - fails > /mnt/fs3/fifo; }; \\\n"); - emulator.serial0_send("{ mv /mnt/fs3/fs4/fs5/dir /mnt/dir && "); - emulator.serial0_send(" echo jump to root > /mnt/fs3/fifo; }; \\\n"); + // Directory move within the same foreign filesystem. + emulator.serial0_send("{ mv /mnt/fs3/fs4/fs5/dir1 /mnt/fs3/fs4/fs5/otherdir/dir2 && "); + emulator.serial0_send(" echo dir move > /mnt/fs3/fifo; }; \\\n"); + + // Directory from forwarder to non-forwarder. Divert forwarder directory. + emulator.serial0_send("{ mv /mnt/fs3/fs4/fs5/otherdir/dir2 /mnt/dir3 && "); + emulator.serial0_send(" echo dir jump to root > /mnt/fs3/fifo; }; \\\n"); + + // Directory from non-forwarder to forwarder. Divert non-forwarder directory. + emulator.serial0_send("{ mv /mnt/dir3 /mnt/fs3/fs4/dir4 && "); + emulator.serial0_send(" echo dir jump back > /mnt/fs3/fifo; }; \\\n"); + + // Moving empty file (treated differently when rewriting data. + emulator.serial0_send("touch /mnt/a/b/fs2/emptyfile; \\\n"); + emulator.serial0_send("{ mv /mnt/a/b/fs2/emptyfile /mnt/fs3/fs4/dir4/emptyfile && "); + emulator.serial0_send(" echo move empty file > /mnt/fs3/fifo; }; \\\n"); + emulator.serial0_send("cat /mnt/fs3/fs4/dir4/emptyfile; \\\n"); emulator.serial0_send('printf "EOF\\n\\n" > /mnt/fs3/fifo & wait "$(cat /mnt/tailpid)" 2>/dev/null; \\\n'); - emulator.serial0_send("cat /mnt/dir/file; \\\n"); - emulator.serial0_send("cat /mnt/dir/child; \\\n"); + emulator.serial0_send("cat /mnt/fs3/fs4/dir4/file4; \\\n"); + emulator.serial0_send("cat /mnt/fs3/fs4/dir4/child; \\\n"); emulator.serial0_send("find /mnt | sort; \\\n"); emulator.serial0_send("echo done-move-mounted\n"); }, @@ -1226,27 +1250,33 @@ const tests = assert_equal(capture, "foobar\n" + "untouched\n" + - "renamed\n" + + "file jump to root\n" + "file jump filesystems\n" + - "moved to dir\n" + + "file renamed\n" + + "file move to dir\n" + "dir jump filesystems\n" + "move mount point across - fails\n" + "move mount point upwards - fails\n" + - "jump to root\n" + + "dir move\n" + + "dir jump to root\n" + + "dir jump back\n" + + "move empty file\n" + "EOF\n" + "contents\n" + "/mnt\n" + "/mnt/a\n" + "/mnt/a/b\n" + "/mnt/a/b/fs2\n" + - "/mnt/dir\n" + - "/mnt/dir/child\n" + - "/mnt/dir/file\n" + "/mnt/fs3\n" + "/mnt/fs3/fifo\n" + "/mnt/fs3/fifo_intermediate\n" + "/mnt/fs3/fs4\n" + + "/mnt/fs3/fs4/dir4\n" + + "/mnt/fs3/fs4/dir4/child\n" + + "/mnt/fs3/fs4/dir4/emptyfile\n" + + "/mnt/fs3/fs4/dir4/file4\n" + "/mnt/fs3/fs4/fs5\n" + + "/mnt/fs3/fs4/fs5/otherdir\n" + "/mnt/tailpid\n"); done(); }, From 53edf989ea310a875f0f12328f76727ee14117a2 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 15 Aug 2018 21:58:01 +1200 Subject: [PATCH 1155/2137] Fix: fs.divert should update children parentids Otherwise, calling fs.divert leaves the filesystem in an invalid state. --- lib/filesystem.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/filesystem.js b/lib/filesystem.js index dca731b2..bc18ea8a 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -537,6 +537,17 @@ FS.prototype.divert = function(old_idx) this.link_under_dir(idx, old_inode.parentid); } + // Update children + if(this.IsDirectory(old_idx) && !this.is_forwarder(old_inode)) + { + let child_id = this.inodes[idx].firstid; + while(child_id !== -1) + { + this.inodes[child_id].parentid = idx; + child_id = this.inodes[child_id].nextid; + } + } + // Relocate local data if any. this.inodedata[idx] = this.inodedata[old_idx]; delete this.inodedata[old_idx]; From 3a2ff7c47e7d81e439577a97b04981bce688c035 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 15 Aug 2018 22:02:56 +1200 Subject: [PATCH 1156/2137] Fix: fs.Rename should configure the correct filename Specifically when moving a file from a mounted filesystem to the local filesystem. --- lib/filesystem.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/filesystem.js b/lib/filesystem.js index bc18ea8a..e4929c0f 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -834,6 +834,7 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { Object.assign(inode, old_real_inode); // Link into new location in this filesystem. + inode.name = newname; inode.firstid = -1; this.link_under_dir(idx, newdirid); } From fa3a96162886dbb656e8392203b327b6416ca291 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 15 Aug 2018 22:32:55 +1200 Subject: [PATCH 1157/2137] Handle unexpected error codes from filesystem --- lib/9p.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/9p.js b/lib/9p.js index 318380ab..fe7748cc 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -592,6 +592,11 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { let error_message = ""; if(ret === -ENOENT) error_message = "No such file or directory"; else if(ret === -EPERM) error_message = "Operation not permitted"; + else + { + error_message = "Unknown error: " + (-ret); + dbg_assert(false, "[renameat]: Unexpected error code: " + (-ret)); + } this.SendError(tag, error_message, -ret); this.SendReply(bufchain); break; From 7aa42c341885591034e8085da9ee120fcf408c07 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 15 Aug 2018 22:36:22 +1200 Subject: [PATCH 1158/2137] Identify type of failure for fs.Unlink using -errno convention --- lib/9p.js | 12 ++++++++++-- lib/filesystem.js | 30 ++++++++++++++++-------------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/lib/9p.js b/lib/9p.js index fe7748cc..a497d001 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -618,8 +618,16 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { break; } var ret = this.fs.Unlink(fid); - if (!ret) { - this.SendError(tag, "Directory not empty", ENOTEMPTY); + if (ret < 0) { + let error_message = ""; + if(ret === -ENOTEMPTY) error_message = "Directory not empty"; + else if(ret === -EPERM) error_message = "Operation not permitted"; + else + { + error_message = "Unknown error: " + (-ret); + dbg_assert(false, "[unlink]: Unexpected error code: " + (-ret)); + } + this.SendError(tag, error_message, ENOTEMPTY); this.SendReply(bufchain); break; } diff --git a/lib/filesystem.js b/lib/filesystem.js index e4929c0f..ade6c7ec 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -1042,7 +1042,7 @@ FS.prototype.Link = function(targetid, name, parentid) FS.prototype.Unlink = function(idx) { this.NotifyListeners(idx, 'delete'); - if (idx == 0) return false; // root node cannot be deleted + if (idx == 0) return -EPERM; // root node cannot be deleted var inode = this.inodes[idx]; const parent_inode = this.inodes[this.GetParent(idx)]; //message.Debug("Unlink " + inode.name); @@ -1051,14 +1051,14 @@ FS.prototype.Unlink = function(idx) { if(!this.should_be_linked(inode)) { const foreign_id = inode.foreign_id; - const success = this.follow_fs(inode).Unlink(foreign_id); - this.delete_forwarder(inode); - return success; + const ret = this.follow_fs(inode).Unlink(foreign_id); + if(ret === 0) this.delete_forwarder(inode); + return ret; } // check if directory is not empty if ((inode.mode&S_IFMT) == S_IFDIR) { - if (inode.firstid != -1) return false; + if (inode.firstid != -1) return -ENOTEMPTY; } this.unlink_from_dir(idx); @@ -1070,7 +1070,7 @@ FS.prototype.Unlink = function(idx) { inode.firstid = -1; inode.parentid = -1; inode.nlinks--; - return true; + return 0; }; FS.prototype.DeleteData = function(idx) @@ -1171,8 +1171,11 @@ FS.prototype.RecursiveDelete = function(path) { this.GetRecursiveList(ids.id, toDelete); for(var i=toDelete.length-1; i>=0; i--) - dbg_assert(this.Unlink(toDelete[i]), - "Filesystem RecursiveDelete failed at inode=" + toDelete[i]); + { + const ret = this.Unlink(toDelete[i]); + dbg_assert(ret === 0, "Filesystem RecursiveDelete failed at inode=" + toDelete[i] + + " with error code: " + (-ret)); + } }; @@ -1181,15 +1184,14 @@ FS.prototype.DeleteNode = function(path) { if (ids.id == -1) return; if ((this.inodes[ids.id].mode&S_IFMT) == S_IFREG){ - this.Unlink(ids.id); + const ret = this.Unlink(ids.id); + dbg_assert(ret === 0, "Filesystem DeleteNode failed with error code: " + (-ret)); return; } if ((this.inodes[ids.id].mode&S_IFMT) == S_IFDIR){ - var toDelete = []; - this.GetRecursiveList(ids.id, toDelete); - for(var i=toDelete.length-1; i>=0; i--) - this.Unlink(toDelete[i]); - this.Unlink(ids.id); + this.RecursiveDelete(path); + const ret = this.Unlink(ids.id); + dbg_assert(ret === 0, "Filesystem DeleteNode failed with error code: " + (-ret)); return; } }; From 6c55912a59c7c28aa8df91ce8377ed2dc90b5f8c Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 15 Aug 2018 22:37:48 +1200 Subject: [PATCH 1159/2137] Fail early if unlink of destination failed for fs.Rename --- lib/9p.js | 1 + lib/filesystem.js | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/9p.js b/lib/9p.js index a497d001..588969c7 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -592,6 +592,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { let error_message = ""; if(ret === -ENOENT) error_message = "No such file or directory"; else if(ret === -EPERM) error_message = "Operation not permitted"; + else if(ret === -ENOTEMPTY) error_message = "Directory not empty"; else { error_message = "Unknown error: " + (-ret); diff --git a/lib/filesystem.js b/lib/filesystem.js index ade6c7ec..93c6b3dc 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -759,7 +759,8 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { var newid = this.Search(newdirid, newname); if (newid != -1) { - this.Unlink(newid); + const ret = this.Unlink(newid); + if(ret < 0) return ret; } var idx = oldid; // idx contains the id which we want to rename From e29e1ef9f4127ac3b41931f68cadbe1f24740e15 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 15 Aug 2018 23:27:19 +1200 Subject: [PATCH 1160/2137] Handle unexpected errors from fs.Mount and fix V86Starter error handling. --- src/browser/starter.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 1f78a272..9cb866bb 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -1093,12 +1093,13 @@ V86Starter.prototype.mount_fs = function(path, baseurl, basefs, callback) { callback(new FileNotFoundError()); } - if(idx === -EEXIST) + else if(idx === -EEXIST) { callback(new FileExistsError()); } - if(idx < 0) + else if(idx < 0) { + dbg_assert(false, "Unexpected error code: " + (-idx)); callback(new Error("Failed to mount. Error number: " + (-idx))); } else @@ -1222,7 +1223,7 @@ function FileExistsError(message) { this.message = message || "File already exists"; } -FileNotFoundError.prototype = Error.prototype; +FileExistsError.prototype = Error.prototype; /** * @ignore From 28ac891dc3b9568c19010135d84c5b7a37a9c48d Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 16 Aug 2018 15:10:30 -0500 Subject: [PATCH 1161/2137] Filesystem: Load files via their sha256 --- lib/filesystem.js | 9 +++++++-- tests/devices/testfs.json | 2 +- ...3f4f1d5af4a5e8149b479c813ab4ceea0bcf8b01f78eac84fd25} | 0 ...66918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730} | 0 4 files changed, 8 insertions(+), 3 deletions(-) rename tests/devices/testfs/{dir/bar => 5d70f436aa013f4f1d5af4a5e8149b479c813ab4ceea0bcf8b01f78eac84fd25} (100%) rename tests/devices/testfs/{foo => 7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730} (100%) diff --git a/lib/filesystem.js b/lib/filesystem.js index 93c6b3dc..bcbca10a 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -32,7 +32,7 @@ var STATUS_UNLINKED = 0x4; var STATUS_FORWARDING = 0x5; -/** @const */ var JSONFS_VERSION = 2; +/** @const */ var JSONFS_VERSION = 3; /** @const */ var JSONFS_IDX_NAME = 0; @@ -42,6 +42,7 @@ var STATUS_FORWARDING = 0x5; /** @const */ var JSONFS_IDX_UID = 4; /** @const */ var JSONFS_IDX_GID = 5; /** @const */ var JSONFS_IDX_TARGET = 6; +/** @const */ var JSONFS_IDX_SHA256 = 6; /** @@ -255,6 +256,7 @@ FS.prototype.LoadRecursive = function(data, parentid) else if(ifmt === S_IFREG) { inode.status = STATUS_ON_SERVER; + inode.sha256sum = data[JSONFS_IDX_SHA256]; this.PushInode(inode); } else if(ifmt === S_IFLNK) @@ -317,7 +319,7 @@ FS.prototype.LoadFile = function(idx) { if(this.baseurl) { - LoadBinaryResource(this.baseurl + this.GetFullPath(inode.fid), + LoadBinaryResource(this.baseurl + inode.sha256sum, function(buffer){ var data = this.inodedata[idx] = new Uint8Array(buffer); inode.size = data.length; // correct size if the previous was wrong. @@ -434,6 +436,7 @@ function Inode(qidnumber) this.caps = undefined; this.nlinks = 1; this.dirty = false; // has this file changed? + this.sha256sum = ""; // For forwarders: this.mount_id = -1; // which fs in this.mounts does this inode forward to? @@ -472,6 +475,7 @@ Inode.prototype.get_state = function() state[22] = this.dirty; state[23] = this.mount_id; state[24] = this.foreign_id; + state[25] = this.sha256sum; return state; }; @@ -502,6 +506,7 @@ Inode.prototype.set_state = function(state) this.dirty = state[22]; this.mount_id = state[23]; this.foreign_id = state[24]; + this.sha256sum = state[25]; }; /** diff --git a/tests/devices/testfs.json b/tests/devices/testfs.json index f0c50ce8..b900bfd6 100644 --- a/tests/devices/testfs.json +++ b/tests/devices/testfs.json @@ -1 +1 @@ -{"fsroot":[["foo",4,1531432001,33188,1000,1000],["dir",4096,1532940393,16877,1000,1000,[["bar",7,1532940393,33188,1000,1000]]]],"version":2,"size":4107} \ No newline at end of file +{"fsroot":[["foo",4,1531432001,33188,1000,1000,"7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730"],["dir",4096,1532940393,16877,1000,1000,[["bar",7,1532940393,33188,1000,1000,"5d70f436aa013f4f1d5af4a5e8149b479c813ab4ceea0bcf8b01f78eac84fd25"]]]],"version":3,"size":4107} diff --git a/tests/devices/testfs/dir/bar b/tests/devices/testfs/5d70f436aa013f4f1d5af4a5e8149b479c813ab4ceea0bcf8b01f78eac84fd25 similarity index 100% rename from tests/devices/testfs/dir/bar rename to tests/devices/testfs/5d70f436aa013f4f1d5af4a5e8149b479c813ab4ceea0bcf8b01f78eac84fd25 diff --git a/tests/devices/testfs/foo b/tests/devices/testfs/7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730 similarity index 100% rename from tests/devices/testfs/foo rename to tests/devices/testfs/7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730 From 8da18d339e0f1bf47bdb0bceb733a0e7b1fe32a7 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 17 Aug 2018 11:31:38 -0500 Subject: [PATCH 1162/2137] Add tools to build v86 images from docker container --- docker/debian-full/Dockerfile | 57 ++++++ docker/debian-full/boot-9p | 33 ++++ docker/debian-full/build-container.sh | 6 + docker/debian-full/build-state.js | 97 ++++++++++ .../debian-full/create-9p-from-container.sh | 95 ++++++++++ docker/debian-full/fluxbox/apps | 4 + docker/debian-full/fluxbox/init | 82 +++++++++ docker/debian-full/fluxbox/keys | 137 ++++++++++++++ docker/debian-full/fluxbox/lastwallpaper | 0 docker/debian-full/fluxbox/menu | 61 +++++++ docker/debian-full/fluxbox/overlay | 2 + .../Clearlooks/pixmaps/bullet-active.xpm | 32 ++++ .../styles/Clearlooks/pixmaps/bullet.xpm | 22 +++ .../Clearlooks/pixmaps/close-active.xpm | 28 +++ .../Clearlooks/pixmaps/close-inactive.xpm | 25 +++ .../Clearlooks/pixmaps/close-pressed.xpm | 19 ++ .../styles/Clearlooks/pixmaps/label-focus.xpm | 28 +++ .../Clearlooks/pixmaps/label-unfocus.xpm | 28 +++ .../Clearlooks/pixmaps/maximize-active.xpm | 28 +++ .../Clearlooks/pixmaps/maximize-inactive.xpm | 25 +++ .../Clearlooks/pixmaps/maximize-pressed.xpm | 19 ++ .../styles/Clearlooks/pixmaps/menu-active.xpm | 28 +++ .../styles/Clearlooks/pixmaps/menu-hilite.xpm | 37 ++++ .../Clearlooks/pixmaps/menu-inactive.xpm | 25 +++ .../Clearlooks/pixmaps/menu-pressed.xpm | 19 ++ .../Clearlooks/pixmaps/minimize-active.xpm | 28 +++ .../Clearlooks/pixmaps/minimize-inactive.xpm | 25 +++ .../Clearlooks/pixmaps/minimize-pressed.xpm | 19 ++ .../Clearlooks/pixmaps/selected-active.xpm | 49 +++++ .../styles/Clearlooks/pixmaps/selected.xpm | 49 +++++ .../Clearlooks/pixmaps/shade-active.xpm | 28 +++ .../Clearlooks/pixmaps/shade-inactive.xpm | 25 +++ .../Clearlooks/pixmaps/shade-pressed.xpm | 19 ++ .../pixmaps/shade-toggled-active.xpm | 28 +++ .../pixmaps/shade-toggled-inactive.xpm | 25 +++ .../pixmaps/shade-toggled-pressed.xpm | 19 ++ .../Clearlooks/pixmaps/stick-active.xpm | 28 +++ .../Clearlooks/pixmaps/stick-inactive.xpm | 25 +++ .../Clearlooks/pixmaps/stick-pressed.xpm | 19 ++ .../pixmaps/stick-toggled-active.xpm | 28 +++ .../pixmaps/stick-toggled-inactive.xpm | 25 +++ .../styles/Clearlooks/pixmaps/title-focus.xpm | 40 +++++ .../Clearlooks/pixmaps/title-unfocus.xpm | 40 +++++ .../pixmaps/toolbar-iconbar-focus.xpm | 44 +++++ .../pixmaps/toolbar-iconbar-unfocus.xpm | 38 ++++ .../Clearlooks/pixmaps/unselected-active.xpm | 19 ++ .../styles/Clearlooks/pixmaps/unselected.xpm | 19 ++ .../fluxbox/styles/Clearlooks/theme.cfg | 129 +++++++++++++ docker/debian-full/fluxbox/windowmenu | 15 ++ .../debian-full/getty-autologin-serial.conf | 3 + docker/debian-full/getty-noclear.conf | 2 + docker/debian-full/getty-override.conf | 3 + docker/debian-full/logind.conf | 37 ++++ docker/debian-full/xorg.conf | 67 +++++++ tools/copy-to-sha256.py | 60 +++++++ tools/fs2json.py | 170 ++++++++++++++++++ 56 files changed, 2062 insertions(+) create mode 100644 docker/debian-full/Dockerfile create mode 100644 docker/debian-full/boot-9p create mode 100755 docker/debian-full/build-container.sh create mode 100755 docker/debian-full/build-state.js create mode 100755 docker/debian-full/create-9p-from-container.sh create mode 100644 docker/debian-full/fluxbox/apps create mode 100644 docker/debian-full/fluxbox/init create mode 100644 docker/debian-full/fluxbox/keys create mode 100644 docker/debian-full/fluxbox/lastwallpaper create mode 100644 docker/debian-full/fluxbox/menu create mode 100644 docker/debian-full/fluxbox/overlay create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/bullet-active.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/bullet.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-active.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-inactive.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-pressed.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/label-focus.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/label-unfocus.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-active.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-inactive.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-pressed.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-active.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-hilite.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-inactive.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-pressed.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-active.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-inactive.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-pressed.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/selected-active.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/selected.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-active.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-inactive.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-pressed.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-active.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-inactive.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-pressed.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-active.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-inactive.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-pressed.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-toggled-active.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-toggled-inactive.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/title-focus.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/title-unfocus.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/toolbar-iconbar-focus.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/toolbar-iconbar-unfocus.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/unselected-active.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/unselected.xpm create mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/theme.cfg create mode 100644 docker/debian-full/fluxbox/windowmenu create mode 100644 docker/debian-full/getty-autologin-serial.conf create mode 100644 docker/debian-full/getty-noclear.conf create mode 100644 docker/debian-full/getty-override.conf create mode 100644 docker/debian-full/logind.conf create mode 100644 docker/debian-full/xorg.conf create mode 100755 tools/copy-to-sha256.py create mode 100755 tools/fs2json.py diff --git a/docker/debian-full/Dockerfile b/docker/debian-full/Dockerfile new file mode 100644 index 00000000..046637fe --- /dev/null +++ b/docker/debian-full/Dockerfile @@ -0,0 +1,57 @@ +FROM i386/debian + +ENV DEBIAN_FRONTEND noninteractive + +RUN apt-get update && \ + apt-get --yes --no-install-recommends install \ + linux-image-4.9.0-6-686 grub2 systemd \ + libterm-readline-perl-perl \ + unzip bzip2 xz-utils \ + fluxbox \ + xserver-xorg-input-kbd xserver-xorg-input-mouse xserver-xorg-input-evdev \ + xserver-xorg-video-fbdev xserver-xorg-video-vesa \ + xserver-xorg x11-xserver-utils xinit dbus-x11 \ + libgdk-pixbuf2.0 libpango-1.0 libpangocairo-1.0 libgtk2.0-bin \ + libc-l10n locales \ + fonts-noto fonts-droid-fallback \ + strace file xterm vim apt-file \ + winbind cabextract \ + dhcpcd5 \ + wget curl \ + && \ + echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen \ + locale-gen \ + chsh -s /bin/bash && \ + echo "root:root" | chpasswd && \ + mkdir -p /etc/systemd/system/serial-getty@ttyS0.service.d/ && \ + systemctl enable serial-getty@ttyS0.service && \ + rm /lib/systemd/system/getty.target.wants/getty-static.service && \ + rm /etc/motd /etc/issue && \ + systemctl disable winbind.service && \ + systemctl disable systemd-timesyncd.service && \ + systemctl disable apt-daily.timer && \ + systemctl disable apt-daily-upgrade.timer && \ + echo "tmpfs /tmp tmpfs nodev,nosuid 0 0" >> /etc/fstab + +COPY getty-noclear.conf getty-override.conf /etc/systemd/system/getty@tty1.service.d/ +COPY getty-autologin-serial.conf /etc/systemd/system/serial-getty@ttyS0.service.d/ + +COPY logind.conf /etc/systemd/logind.conf + +#COPY xinitrc /root/.xinitrc +COPY xorg.conf /etc/X11/ +COPY fluxbox /root/.fluxbox + +COPY boot-9p /etc/initramfs-tools/scripts/boot-9p + +# this needs to be commented out in order to boot from hdd +RUN printf '%s\n' 9p 9pnet 9pnet_virtio virtio virtio_ring virtio_pci | tee -a /etc/initramfs-tools/modules && \ + echo 'BOOT=boot-9p' | tee -a /etc/initramfs-tools/initramfs.conf && \ + update-initramfs -u + +RUN apt-get --yes clean && \ + rm -r /var/lib/apt/lists/* && \ + rm -r /usr/share/doc/* && \ + rm -r /usr/share/man/* && \ + rm -r /usr/share/locale/?? && \ + rm /var/log/*.log /var/log/lastlog /var/log/wtmp /var/log/apt/*.log /var/log/apt/*.xz diff --git a/docker/debian-full/boot-9p b/docker/debian-full/boot-9p new file mode 100644 index 00000000..88e695f6 --- /dev/null +++ b/docker/debian-full/boot-9p @@ -0,0 +1,33 @@ +# 9p filesystem mounting -*- shell-script -*- + +mountroot() +{ + wait_for_udev 10 + + if [ ${readonly} = y ]; then + roflag="-o ro" + else + roflag="-o rw" + fi + + #echo "Running: mount -t 9p -o cache=mmap ${ROOT} ${rootmnt}" + #mount -t 9p -o cache=mmap ${ROOT} ${rootmnt} + echo "Running: mount -t 9p -o cache=fscache ${ROOT} ${rootmnt}" + mount -t 9p -o cache=fscache ${ROOT} ${rootmnt} + echo "mount finished with code $?" +} + +mount_top() +{ + echo top +} + +mount_premount() +{ + echo premount +} + +mount_bottom() +{ + echo bottom +} diff --git a/docker/debian-full/build-container.sh b/docker/debian-full/build-container.sh new file mode 100755 index 00000000..e157f14f --- /dev/null +++ b/docker/debian-full/build-container.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +set -e + +docker build . --rm --tag i386/debian-full +docker rm debian-full || true +docker create -t -i --name debian-full i386/debian-full bash diff --git a/docker/debian-full/build-state.js b/docker/debian-full/build-state.js new file mode 100755 index 00000000..25056c3d --- /dev/null +++ b/docker/debian-full/build-state.js @@ -0,0 +1,97 @@ +#!/usr/bin/env node +"use strict"; + +const path = require("path"); + +// TODO: +// - Timeout + +console.log("Don't forget to run make build/libv86.js before running this script"); + +var fs = require("fs"); +var V86 = require("./../../build/libv86.js").V86; + +const V86_ROOT = path.join(__dirname, "../.."); + +var OUTPUT_FILE = path.join(V86_ROOT, "images/debian-state-base.bin"); +var SCREEN_FILE = "/tmp/screen_debian_full.txt"; + +process.stdin.setRawMode(true); +process.stdin.resume(); +process.stdin.setEncoding("utf8"); + +var emulator = new V86({ + bios: { url: path.join(V86_ROOT, "/bios/seabios.bin") }, + vga_bios: { url: path.join(V86_ROOT, "/bios/vgabios.bin") }, + hda: { url: path.join(V86_ROOT, "/images/debian-9p-boot.img"), async: true, }, + autostart: true, + memory_size: 512 * 1024 * 1024, + vga_memory_size: 8 * 1024 * 1024, + network_relay_url: "", + filesystem: { + basefs: { + url: path.join(V86_ROOT, "/images/debian-base-fs.json"), + }, + baseurl: path.join(V86_ROOT, "/images/debian-9p-rootfs-flat/"), + //baseurl: path.join(V86_ROOT, "/images/debian-9p-rootfs/"), + }, + screen_dummy: true, +}); + +console.log("Now booting, please stand by ..."); + +var boot_start = Date.now(); +var serial_text = ""; + +process.stdin.on("data", function(c) +{ + if(c === "\u0003") + { + // ctrl c + process.exit(); + } + else + { + emulator.serial0_send(c); + } +}); + +emulator.add_listener("serial0-output-char", function(c) +{ + process.stdout.write(c); + + serial_text += c; + + if(serial_text.endsWith("root@localhost:~# ")) + { + console.error("\nBooted in %d", (Date.now() - boot_start) / 1000); + + // wait a few seconds as the serial console finishes faster than the screen terminal + + setTimeout(function () + { + emulator.save_state(function(err, s) + { + if(err) + { + throw err; + } + + fs.writeFile(OUTPUT_FILE, new Uint8Array(s), function(e) + { + if(e) throw e; + console.error("Saved as " + OUTPUT_FILE); + emulator.stop(); + }); + }); + }, 5000); + } +}); + +//function save_screen() +//{ +// var screen = emulator.screen_adapter.get_text_screen(); +// fs.writeFile(SCREEN_FILE, screen.join("\n"), function(e) { if(e) throw e; }); +//} +// +//setInterval(save_screen, 1000); diff --git a/docker/debian-full/create-9p-from-container.sh b/docker/debian-full/create-9p-from-container.sh new file mode 100755 index 00000000..1f599841 --- /dev/null +++ b/docker/debian-full/create-9p-from-container.sh @@ -0,0 +1,95 @@ +#!/usr/bin/env bash +set -veu + +if [ $(id -u) != "0" ] +then + echo "Please run as root" + exit 1 +fi + +OUTFILE=$(dirname "$0")/../../images/debian-9p-boot.img +OUT_ROOTFS=$(dirname "$0")/../../images/debian-9p-rootfs +OUT_ROOTFS_FLAT=$(dirname "$0")/../../images/debian-9p-rootfs-flat +OUT_FSJSON=$(dirname "$0")/../../images/debian-base-fs.json +CONTAINER_NAME=debian-full + +# vmlinuz, initrd.img and grub take about 25M as of time of this writing, be on +# the safe side with 64M +dd if=/dev/zero of=$OUTFILE bs=1k count=64k + +( +echo o # Create a new empty DOS partition table +echo n # Add a new partition +echo p # Primary partition +echo 1 # Partition number +echo 2048 # First sector +echo # Last sector (Accept default: varies) +echo a # make bootable +echo w # Write changes +echo q # quit +) | fdisk $OUTFILE + +# 1048576 is 2048 (first sector) * 512 (sector size) +mkfs.ext4 -F -E offset=1048576 $OUTFILE + +KPARTX_OUTPUT=$(kpartx -a -v $OUTFILE) +echo $KPARTX_OUTPUT +LOOP_PARTITION=$(echo $KPARTX_OUTPUT | grep -o 'loop[0-9]\+p[0-9]\+') +LOOP_DEV=$(echo $LOOP_PARTITION | grep -o 'loop[0-9]\+') +echo $LOOP_PARTITION +echo $LOOP_DEV + +function finish_kpartx { + kpartx -d $OUTFILE +} +trap finish_kpartx EXIT + +ls -lah /dev/mapper/$LOOP_PARTITION +mount /dev/mapper/$LOOP_PARTITION /mnt +function finish_mount { + umount /mnt + finish_kpartx +} +trap finish_mount EXIT + +rm -rf $OUT_ROOTFS/ && mkdir $OUT_ROOTFS/ +docker export $CONTAINER_NAME | tar -xvC $OUT_ROOTFS/ + +$(dirname "$0")/../../tools/fs2json.py --out $OUT_FSJSON $OUT_ROOTFS/ +chmod 644 $OUT_FSJSON + +# Note: Not deleting old files here +$(dirname "$0")/../../tools/copy-to-sha256.py $OUT_ROOTFS $OUT_ROOTFS_FLAT + +#find $OUT_ROOTFS/ -type d -exec chmod 755 {} ";" +#find $OUT_ROOTFS/ -type f -exec chmod 644 {} ";" + +cp -r -av $OUT_ROOTFS/boot/ /mnt/boot/ +cp -av $OUT_ROOTFS/{initrd*,vmlinuz*} /mnt/ + + +grub-install --recheck --target=i386-pc --locales= --themes= --fonts= --root-directory /mnt/ /dev/$LOOP_DEV + +cat > /mnt/boot/grub/grub.cfg << 'EOF' +set root='hd0' # XXX: I believe this has no significance, but is required to exist by grub + +set timeout_style=menu +set timeout=0 + +menuentry 'Linux' { + #insmod ext2 + #insmod gzio + #insmod fat + set root='hd0,msdos1' + + echo 'Loading Linux linux ...' + #linux /vmlinuz rw root=/dev/sda1 rootfstype=ext4 init=/bin/systemd + linux /vmlinuz rw init=/bin/systemd root=host9p console=ttyS0 + #linux /boot/vmlinuz debug verbose rw root=/dev/sda1 rootfstype=ext4 + + echo 'Loading initial ramdisk ...' + initrd /initrd.img +} +EOF + +echo $OUTFILE created. diff --git a/docker/debian-full/fluxbox/apps b/docker/debian-full/fluxbox/apps new file mode 100644 index 00000000..7b4aeadb --- /dev/null +++ b/docker/debian-full/fluxbox/apps @@ -0,0 +1,4 @@ +[app] (name=fbrun) + [Position] (WINCENTER) {0 0} + [Layer] {2} +[end] diff --git a/docker/debian-full/fluxbox/init b/docker/debian-full/fluxbox/init new file mode 100644 index 00000000..e4054272 --- /dev/null +++ b/docker/debian-full/fluxbox/init @@ -0,0 +1,82 @@ +! If you're looking for settings to configure, they won't be saved here until +! you change something in the fluxbox configuration menu. + +session.menuFile: ~/.fluxbox/menu +session.keyFile: ~/.fluxbox/keys +session.styleFile: ~/.fluxbox/styles/Clearlooks +session.screen0.rootCommand: fbsetroot -solid black + + +session.screen0.slit.layer: Dock +session.screen0.slit.onhead: 0 +session.screen0.slit.acceptKdeDockapps: true +session.screen0.slit.autoHide: false +session.screen0.slit.placement: RightBottom +session.screen0.slit.alpha: 255 +session.screen0.slit.maxOver: false +session.screen0.window.focus.alpha: 255 +session.screen0.window.unfocus.alpha: 255 +session.screen0.tabs.usePixmap: true +session.screen0.tabs.maxOver: false +session.screen0.tabs.intitlebar: true +session.screen0.titlebar.left: Stick +session.screen0.titlebar.right: Minimize Maximize Close +session.screen0.iconbar.usePixmap: true +session.screen0.iconbar.mode: {static groups} (workspace) +session.screen0.iconbar.alignment: Relative +session.screen0.iconbar.iconWidth: 128 +session.screen0.iconbar.iconTextPadding: 10 +session.screen0.clientMenu.usePixmap: true +session.screen0.menu.alpha: 255 +session.screen0.toolbar.placement: BottomCenter +session.screen0.toolbar.layer: Dock +session.screen0.toolbar.autoHide: false +session.screen0.toolbar.visible: false +session.screen0.toolbar.tools: prevworkspace, workspacename, nextworkspace, iconbar, systemtray, clock +session.screen0.toolbar.onhead: 1 +session.screen0.toolbar.widthPercent: 100 +session.screen0.toolbar.maxOver: false +session.screen0.toolbar.height: 0 +session.screen0.toolbar.alpha: 255 +session.screen0.tab.placement: TopLeft +session.screen0.tab.width: 64 +session.screen0.tabFocusModel: ClickToTabFocus +session.screen0.autoRaise: true +session.screen0.maxDisableMove: false +session.screen0.edgeSnapThreshold: 10 +session.screen0.tooltipDelay: 500 +session.screen0.colPlacementDirection: TopToBottom +session.screen0.opaqueMove: true +session.screen0.windowPlacement: RowMinOverlapPlacement +session.screen0.focusNewWindows: true +session.screen0.clickRaises: true +session.screen0.maxDisableResize: false +session.screen0.allowRemoteActions: false +session.screen0.windowMenu: /root/.fluxbox/windowmenu +session.screen0.fullMaximization: false +session.screen0.defaultDeco: NORMAL +session.screen0.noFocusWhileTypingDelay: 0 +session.screen0.menuDelay: 200 +session.screen0.workspacewarping: true +session.screen0.focusSameHead: false +session.screen0.workspaceNames: Workspace 1,Workspace 2,Workspace 3,Workspace 4, +session.screen0.workspaces: 4 +session.screen0.maxIgnoreIncrement: true +session.screen0.showwindowposition: false +session.screen0.focusModel: ClickFocus +session.screen0.rowPlacementDirection: LeftToRight +session.screen0.strftimeFormat: %k:%M +session.doubleClickInterval: 250 +session.slitlistFile: /root/.fluxbox/slitlist +session.cacheLife: 5 +session.tabPadding: 0 +session.cacheMax: 200 +session.appsFile: /root/.fluxbox/apps +session.ignoreBorder: false +session.styleOverlay: /root/.fluxbox/overlay +session.forcePseudoTransparency: false +session.tabsAttachArea: Window +session.autoRaiseDelay: 250 +session.configVersion: 13 +session.colorsPerChannel: 4 +session.menuSearch: itemstart diff --git a/docker/debian-full/fluxbox/keys b/docker/debian-full/fluxbox/keys new file mode 100644 index 00000000..0567d04e --- /dev/null +++ b/docker/debian-full/fluxbox/keys @@ -0,0 +1,137 @@ +# click on the desktop to get menus +OnDesktop Mouse1 :HideMenus +OnDesktop Mouse2 :WorkspaceMenu +OnDesktop Mouse3 :RootMenu + +# scroll on the desktop to change workspaces +OnDesktop Mouse4 :PrevWorkspace +OnDesktop Mouse5 :NextWorkspace + +# scroll on the toolbar to change current window +OnToolbar Mouse4 :PrevWindow {static groups} (iconhidden=no) +OnToolbar Mouse5 :NextWindow {static groups} (iconhidden=no) + +# alt + left/right click to move/resize a window +OnWindow Mod1 Mouse1 :MacroCmd {Raise} {Focus} {StartMoving} +OnWindowBorder Move1 :StartMoving + +OnWindow Mod1 Mouse3 :MacroCmd {Raise} {Focus} {StartResizing NearestCorner} +OnLeftGrip Move1 :StartResizing bottomleft +OnRightGrip Move1 :StartResizing bottomright + +# alt + middle click to lower the window +OnWindow Mod1 Mouse2 :Lower + +# control-click a window's titlebar and drag to attach windows +OnTitlebar Control Mouse1 :StartTabbing + +# double click on the titlebar to shade +OnTitlebar Double Mouse1 :Shade + +# left click on the titlebar to move the window +OnTitlebar Mouse1 :MacroCmd {Raise} {Focus} {ActivateTab} +OnTitlebar Move1 :StartMoving + +# middle click on the titlebar to lower +OnTitlebar Mouse2 :Lower + +# right click on the titlebar for a menu of options +OnTitlebar Mouse3 :WindowMenu + +# alt-tab +Mod1 Tab :NextWindow {groups} (workspace=[current]) +Mod1 Shift Tab :PrevWindow {groups} (workspace=[current]) + +# cycle through tabs in the current window +Mod4 Tab :NextTab +Mod4 Shift Tab :PrevTab + +# go to a specific tab in the current window +Mod4 1 :Tab 1 +Mod4 2 :Tab 2 +Mod4 3 :Tab 3 +Mod4 4 :Tab 4 +Mod4 5 :Tab 5 +Mod4 6 :Tab 6 +Mod4 7 :Tab 7 +Mod4 8 :Tab 8 +Mod4 9 :Tab 9 + +# open a terminal +Mod1 F1 :Exec xterm + +# open a dialog to run programs +Mod1 F2 :Exec fbrun + +# volume settings, using common keycodes +# if these don't work, use xev to find out your real keycodes +176 :Exec amixer sset Master,0 1+ +174 :Exec amixer sset Master,0 1- +160 :Exec amixer sset Master,0 toggle + +# current window commands +Mod1 F4 :Close +Mod1 F5 :Kill +Mod1 F9 :Minimize +Mod1 F10 :Maximize +Mod1 F11 :Fullscreen + +# open the window menu +Mod1 space :WindowMenu + +# exit fluxbox +Control Mod1 Delete :Exit + +# change to previous/next workspace +Control Mod1 Left :PrevWorkspace +Control Mod1 Right :NextWorkspace + +# send the current window to previous/next workspace +Mod4 Left :SendToPrevWorkspace +Mod4 Right :SendToNextWorkspace + +# send the current window and follow it to previous/next workspace +Control Mod4 Left :TakeToPrevWorkspace +Control Mod4 Right :TakeToNextWorkspace + +# change to a specific workspace +Control F1 :Workspace 1 +Control F2 :Workspace 2 +Control F3 :Workspace 3 +Control F4 :Workspace 4 +Control F5 :Workspace 5 +Control F6 :Workspace 6 +Control F7 :Workspace 7 +Control F8 :Workspace 8 +Control F9 :Workspace 9 +Control F10 :Workspace 10 +Control F11 :Workspace 11 +Control F12 :Workspace 12 + +# send the current window to a specific workspace +Mod4 F1 :SendToWorkspace 1 +Mod4 F2 :SendToWorkspace 2 +Mod4 F3 :SendToWorkspace 3 +Mod4 F4 :SendToWorkspace 4 +Mod4 F5 :SendToWorkspace 5 +Mod4 F6 :SendToWorkspace 6 +Mod4 F7 :SendToWorkspace 7 +Mod4 F8 :SendToWorkspace 8 +Mod4 F9 :SendToWorkspace 9 +Mod4 F10 :SendToWorkspace 10 +Mod4 F11 :SendToWorkspace 11 +Mod4 F12 :SendToWorkspace 12 + +# send the current window and change to a specific workspace +Control Mod4 F1 :TakeToWorkspace 1 +Control Mod4 F2 :TakeToWorkspace 2 +Control Mod4 F3 :TakeToWorkspace 3 +Control Mod4 F4 :TakeToWorkspace 4 +Control Mod4 F5 :TakeToWorkspace 5 +Control Mod4 F6 :TakeToWorkspace 6 +Control Mod4 F7 :TakeToWorkspace 7 +Control Mod4 F8 :TakeToWorkspace 8 +Control Mod4 F9 :TakeToWorkspace 9 +Control Mod4 F10 :TakeToWorkspace 10 +Control Mod4 F11 :TakeToWorkspace 11 +Control Mod4 F12 :TakeToWorkspace 12 diff --git a/docker/debian-full/fluxbox/lastwallpaper b/docker/debian-full/fluxbox/lastwallpaper new file mode 100644 index 00000000..e69de29b diff --git a/docker/debian-full/fluxbox/menu b/docker/debian-full/fluxbox/menu new file mode 100644 index 00000000..ad46078d --- /dev/null +++ b/docker/debian-full/fluxbox/menu @@ -0,0 +1,61 @@ +# Generated by fluxbox-generate_menu +# +# If you read this it means you want to edit this file manually, so here +# are some useful tips: +# +# - You can add your own menu-entries to ~/.fluxbox/usermenu +# +# - If you miss apps please let me know and I will add them for the next +# release. +# +# - The -r option prevents removing of empty menu entries and lines which +# makes things much more readable. +# +# - To prevent any other app from overwriting your menu +# you can change the menu name in ~/.fluxbox/init to: +# session.menuFile: ~/.fluxbox/my-menu +[begin] (Fluxbox) +[encoding] {UTF-8} + [exec] (xterm) {xterm} + [exec] (firefox) {} execname is NULL; cannot lookup + [exec] (Run) {fbrun} +[submenu] (Terminals) + [exec] (xterm) {xterm} +[end] +[submenu] (Editors) + [exec] (vim) {xterm -e vim} + [exec] (vi) {xterm -e vi} +[end] +[submenu] (Multimedia) +[submenu] (X-utils) + [exec] (Reload .Xdefaults) {xrdb -load $HOME/.Xdefaults} +[end] +[end] +[submenu] (Office) + [exec] (Open Office) {soffice} +[end] +[submenu] (System Tools) + [exec] (top) {xterm -e top} +[end] +[submenu] (Fluxbox menu) + [config] (Configure) +[submenu] (System Styles) {Choose a style...} + [stylesdir] (/usr/share/fluxbox/styles) +[end] +[submenu] (User Styles) {Choose a style...} + [stylesdir] (~/.fluxbox/styles) +[end] + [workspaces] (Workspace List) +[submenu] (Tools) + [exec] (Run) {fbrun} + [exec] (Regen Menu) {fluxbox-generate_menu} +[end] + [commanddialog] (Fluxbox Command) + [reconfig] (Reload config) + [restart] (Restart) + [exec] (About) {(fluxbox -v; fluxbox -info | sed 1d) | xmessage -file - -center} + [separator] + [exit] (Exit) +[end] +[endencoding] +[end] diff --git a/docker/debian-full/fluxbox/overlay b/docker/debian-full/fluxbox/overlay new file mode 100644 index 00000000..3431cfe0 --- /dev/null +++ b/docker/debian-full/fluxbox/overlay @@ -0,0 +1,2 @@ +! The following line will prevent styles from setting the background. +background: none diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/bullet-active.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/bullet-active.xpm new file mode 100644 index 00000000..ecff74f3 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/bullet-active.xpm @@ -0,0 +1,32 @@ +/* XPM */ +static char * bullet_active_xpm[] = { +"6 10 19 1", +" c None", +". c #CEDEF2", +"+ c #CFDFF2", +"@ c #CEDEF1", +"# c #FFFFFF", +"$ c #CDDDF1", +"% c #CDDDF2", +"& c #CFDEF2", +"* c #F7FAFD", +"= c #CCDCF1", +"- c #F7F9FD", +"; c #C9DAEF", +"> c #CBDBEF", +", c #C8D9EF", +"' c #C6D8EE", +") c #C7D8EE", +"! c #C6D7ED", +"~ c #C5D7ED", +"{ c #C5D7EE", +".+ ", +"@#. ", +" $#% ", +" &#$ ", +" *#=", +" -#;", +" >#, ", +" '#) ", +"!#' ", +"~{ "}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/bullet.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/bullet.xpm new file mode 100644 index 00000000..6515a9f7 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/bullet.xpm @@ -0,0 +1,22 @@ +/* XPM */ +static char * bullet_xpm[] = { +"12 12 7 1", +" c None", +". c #808080", +"+ c #7F7F7F", +"@ c #000000", +"# c #797979", +"$ c #131313", +"% c #787878", +" ", +" .+ ", +" .@+ ", +" .@+ ", +" #@+ ", +" $@+ ", +" $@+ ", +" %@+ ", +" .@+ ", +" .@+ ", +" .+ ", +" "}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-active.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-active.xpm new file mode 100644 index 00000000..9b5f38a1 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-active.xpm @@ -0,0 +1,28 @@ +/* XPM */ +static char * close_active_xpm[] = { +"12 12 13 1", +" c None", +". c #49678B", +"+ c #ADC7E9", +"@ c #A7C3E7", +"# c #A1BFE5", +"$ c #F4F5F6", +"% c #9BBAE2", +"& c #90B2DE", +"* c #86ABD9", +"= c #84AAD8", +"- c #82A8D6", +"; c #7FA6D5", +"> c #7CA4D3", +"............", +".++++++++++.", +".@@@@@@@@@@.", +".##$$##$$##.", +".%%$$$$$$%%.", +".&&&$$$$&&&.", +".***$$$$***.", +".==$$$$$$==.", +".--$$--$$--.", +".;;;;;;;;;;.", +".>>>>>>>>>>.", +"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-inactive.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-inactive.xpm new file mode 100644 index 00000000..0ce800e4 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-inactive.xpm @@ -0,0 +1,25 @@ +/* XPM */ +static char * close_inactive_xpm[] = { +"12 12 10 1", +" c None", +". c #928F8B", +"+ c #FFFFFF", +"@ c #6D6C6C", +"# c #FEFDFD", +"$ c #F9F8F8", +"% c #FAF9F9", +"& c #FBFAFA", +"* c #FCFBFB", +"= c #FDFDFD", +"............", +".++++++++++.", +".++++++++++.", +".++@@++@@++.", +".++@@@@@@++.", +".###@@@@###.", +".$$$@@@@$$$.", +".%%@@@@@@%%.", +".&&@@&&@@&&.", +".**********.", +".==========.", +"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-pressed.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-pressed.xpm new file mode 100644 index 00000000..5f39960c --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-pressed.xpm @@ -0,0 +1,19 @@ +/* XPM */ +static char * close_pressed_xpm[] = { +"12 12 4 1", +" c None", +". c #49678B", +"+ c #7AA1D2", +"@ c #F4F5F6", +"............", +".++++++++++.", +".++++++++++.", +".++@@++@@++.", +".++@@@@@@++.", +".+++@@@@+++.", +".+++@@@@+++.", +".++@@@@@@++.", +".++@@++@@++.", +".++++++++++.", +".++++++++++.", +"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/label-focus.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/label-focus.xpm new file mode 100644 index 00000000..f1424dab --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/label-focus.xpm @@ -0,0 +1,28 @@ +/* XPM */ +static char * label_focus_xpm[] = { +"1 12 13 1", +" c None", +". c #94B6E0", +"+ c #93B5DF", +"@ c #91B4DF", +"# c #90B3DE", +"$ c #8EB1DD", +"% c #8BAFDB", +"& c #86ABD9", +"* c #85AAD8", +"= c #84A9D7", +"- c #82A8D6", +"; c #81A7D5", +"> c #80A6D5", +".", +"+", +"@", +"#", +"$", +"%", +"&", +"*", +"=", +"-", +";", +">"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/label-unfocus.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/label-unfocus.xpm new file mode 100644 index 00000000..5dbc311d --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/label-unfocus.xpm @@ -0,0 +1,28 @@ +/* XPM */ +static char * label_unfocus_xpm[] = { +"1 12 13 1", +" c None", +". c #E8E7E6", +"+ c #E7E6E5", +"@ c #E6E5E3", +"# c #E5E4E2", +"$ c #E4E3E1", +"% c #E2E1DF", +"& c #DEDCDA", +"* c #DDDBD9", +"= c #DCDAD8", +"- c #DBD9D7", +"; c #DAD8D6", +"> c #D9D7D5", +".", +"+", +"@", +"#", +"$", +"%", +"&", +"*", +"=", +"-", +";", +">"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-active.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-active.xpm new file mode 100644 index 00000000..6ff48713 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-active.xpm @@ -0,0 +1,28 @@ +/* XPM */ +static char * maximize_active_xpm[] = { +"12 12 13 1", +" c None", +". c #49678B", +"+ c #ADC7E9", +"@ c #A7C3E7", +"# c #A1BFE5", +"$ c #F4F5F6", +"% c #9BBAE2", +"& c #90B2DE", +"* c #86ABD9", +"= c #84AAD8", +"- c #82A8D6", +"; c #7FA6D5", +"> c #7CA4D3", +"............", +".++++++++++.", +".@@@@@@@@@@.", +".##$$$$$$##.", +".%%$$$$$$%%.", +".&&$&&&&$&&.", +".**$****$**.", +".==$====$==.", +".--$$$$$$--.", +".;;;;;;;;;;.", +".>>>>>>>>>>.", +"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-inactive.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-inactive.xpm new file mode 100644 index 00000000..6e9e17ad --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-inactive.xpm @@ -0,0 +1,25 @@ +/* XPM */ +static char * maximize_inactive_xpm[] = { +"12 12 10 1", +" c None", +". c #928F8B", +"+ c #FFFFFF", +"@ c #6D6C6C", +"# c #FEFDFD", +"$ c #F9F8F8", +"% c #FAF9F9", +"& c #FBFAFA", +"* c #FCFBFB", +"= c #FDFDFD", +"............", +".++++++++++.", +".++++++++++.", +".++@@@@@@++.", +".++@@@@@@++.", +".##@####@##.", +".$$@$$$$@$$.", +".%%@%%%%@%%.", +".&&@@@@@@&&.", +".**********.", +".==========.", +"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-pressed.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-pressed.xpm new file mode 100644 index 00000000..f670fb28 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-pressed.xpm @@ -0,0 +1,19 @@ +/* XPM */ +static char * maximize_pressed_xpm[] = { +"12 12 4 1", +" c None", +". c #49678B", +"+ c #7AA1D2", +"@ c #F4F5F6", +"............", +".++++++++++.", +".++++++++++.", +".++@@@@@@++.", +".++@@@@@@++.", +".++@++++@++.", +".++@++++@++.", +".++@++++@++.", +".++@@@@@@++.", +".++++++++++.", +".++++++++++.", +"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-active.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-active.xpm new file mode 100644 index 00000000..f4eac268 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-active.xpm @@ -0,0 +1,28 @@ +/* XPM */ +static char * menu_active_xpm[] = { +"12 12 13 1", +" c None", +". c #49678B", +"+ c #ADC7E9", +"@ c #A7C3E7", +"# c #A1BFE5", +"$ c #F4F5F6", +"% c #9BBAE2", +"& c #90B2DE", +"* c #86ABD9", +"= c #84AAD8", +"- c #82A8D6", +"; c #7FA6D5", +"> c #7CA4D3", +"............", +".++++++++++.", +".@@@@@@@@@@.", +".####$$####.", +".%%%%$$%%%%.", +".&&$$$$$$&&.", +".**$$$$$$**.", +".====$$====.", +".----$$----.", +".;;;;;;;;;;.", +".>>>>>>>>>>.", +"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-hilite.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-hilite.xpm new file mode 100644 index 00000000..9f3bae85 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-hilite.xpm @@ -0,0 +1,37 @@ +/* XPM */ +static char * menu_hilite_xpm[] = { +"1 17 17 1", +" c None", +". c #4B6E99", +"+ c #A6C4E8", +"@ c #A4C2E7", +"# c #A2C0E6", +"$ c #A0BFE5", +"% c #9EBDE5", +"& c #9CBCE4", +"* c #9ABAE3", +"= c #96B7E1", +"- c #91B3DE", +"; c #8FB2DD", +"> c #8DB0DC", +", c #8BAFDB", +"' c #89ADDA", +") c #87ACD9", +"! c #85AAD8", +".", +"+", +"@", +"#", +"$", +"%", +"&", +"*", +"=", +"-", +";", +">", +",", +"'", +")", +"!", +"."}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-inactive.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-inactive.xpm new file mode 100644 index 00000000..f3b07db0 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-inactive.xpm @@ -0,0 +1,25 @@ +/* XPM */ +static char * menu_inactive_xpm[] = { +"12 12 10 1", +" c None", +". c #928F8B", +"+ c #FFFFFF", +"@ c #6D6C6C", +"# c #FEFDFD", +"$ c #F9F8F8", +"% c #FAF9F9", +"& c #FBFAFA", +"* c #FCFBFB", +"= c #FDFDFD", +"............", +".++++++++++.", +".++++++++++.", +".++++@@++++.", +".++++@@++++.", +".##@@@@@@##.", +".$$@@@@@@$$.", +".%%%%@@%%%%.", +".&&&&@@&&&&.", +".**********.", +".==========.", +"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-pressed.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-pressed.xpm new file mode 100644 index 00000000..0cab5b9e --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-pressed.xpm @@ -0,0 +1,19 @@ +/* XPM */ +static char * menu_pressed_xpm[] = { +"12 12 4 1", +" c None", +". c #49678B", +"+ c #7AA1D2", +"@ c #F4F5F6", +"............", +".++++++++++.", +".++++++++++.", +".++++@@++++.", +".++++@@++++.", +".++@@@@@@++.", +".++@@@@@@++.", +".++++@@++++.", +".++++@@++++.", +".++++++++++.", +".++++++++++.", +"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-active.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-active.xpm new file mode 100644 index 00000000..dc6c9ec7 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-active.xpm @@ -0,0 +1,28 @@ +/* XPM */ +static char * hide_active_xpm[] = { +"12 12 13 1", +" c None", +". c #49678B", +"+ c #ADC7E9", +"@ c #A7C3E7", +"# c #A1BFE5", +"$ c #9BBAE2", +"% c #90B2DE", +"& c #86ABD9", +"* c #84AAD8", +"= c #FFFFFF", +"- c #82A8D6", +"; c #7FA6D5", +"> c #7CA4D3", +"............", +".++++++++++.", +".@@@@@@@@@@.", +".##########.", +".$$$$$$$$$$.", +".%%%%%%%%%%.", +".&&&&&&&&&&.", +".**======**.", +".--======--.", +".;;;;;;;;;;.", +".>>>>>>>>>>.", +"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-inactive.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-inactive.xpm new file mode 100644 index 00000000..8551a432 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-inactive.xpm @@ -0,0 +1,25 @@ +/* XPM */ +static char * hide_inactive_xpm[] = { +"12 12 10 1", +" c None", +". c #928F8B", +"+ c #FFFFFF", +"@ c #FEFDFD", +"# c #F9F8F8", +"$ c #FAF9F9", +"% c #6D6C6C", +"& c #FBFAFA", +"* c #FCFBFB", +"= c #FDFDFD", +"............", +".++++++++++.", +".++++++++++.", +".++++++++++.", +".++++++++++.", +".@@@@@@@@@@.", +".##########.", +".$$%%%%%%$$.", +".&&%%%%%%&&.", +".**********.", +".==========.", +"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-pressed.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-pressed.xpm new file mode 100644 index 00000000..3474dac0 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-pressed.xpm @@ -0,0 +1,19 @@ +/* XPM */ +static char * hide_pressed_xpm[] = { +"12 12 4 1", +" c None", +". c #49678B", +"+ c #7AA1D2", +"@ c #F4F5F6", +"............", +".++++++++++.", +".++++++++++.", +".++++++++++.", +".++++++++++.", +".++++++++++.", +".++++++++++.", +".++@@@@@@++.", +".++@@@@@@++.", +".++++++++++.", +".++++++++++.", +"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/selected-active.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/selected-active.xpm new file mode 100644 index 00000000..e67ad166 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/selected-active.xpm @@ -0,0 +1,49 @@ +/* XPM */ +static char * selected_active_xpm[] = { +"13 13 33 1", +" c None", +". c #4B6E99", +"+ c #C9DAEF", +"@ c #BDCDE0", +"# c #53585F", +"$ c #AEBDCE", +"% c #BACADD", +"& c #36393C", +"* c #1A1A1A", +"= c #717A84", +"- c #C7D7EC", +"; c #414549", +"> c #767F8A", +", c #A9B7C8", +"' c #939EAD", +") c #7B8590", +"! c #606770", +"~ c #C6D7EB", +"{ c #373A3D", +"] c #1D1D1E", +"^ c #909BA9", +"/ c #B8C8DB", +"( c #222223", +"_ c #2E3032", +": c #C1D1E5", +"< c #292A2C", +"[ c #1E1E1F", +"} c #484C52", +"| c #8D98A6", +"1 c #2F3133", +"2 c #28292B", +"3 c #767F8B", +"4 c #B4C2D5", +".............", +".+++++++++++.", +".+++++++@#$+.", +".++++++%&*=+.", +".+++++-;*>++.", +".+,'++)*!+++.", +".~{]^/(_:+++.", +".+,<[}*|++++.", +".++,<*1~++++.", +".+++,23+++++.", +".++++,4+++++.", +".+++++++++++.", +"............."}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/selected.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/selected.xpm new file mode 100644 index 00000000..d22783f7 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/selected.xpm @@ -0,0 +1,49 @@ +/* XPM */ +static char * selected_xpm[] = { +"13 13 33 1", +" c None", +". c #797979", +"+ c #FFFFFF", +"@ c #EFEFEF", +"# c #646464", +"$ c #DCDCDC", +"% c #ECECEC", +"& c #3F3F3F", +"* c #1A1A1A", +"= c #8C8C8C", +"- c #FCFCFC", +"; c #4D4D4D", +"> c #929292", +", c #D5D5D5", +"' c #B8B8B8", +") c #999999", +"! c #767676", +"~ c #FBFBFB", +"{ c #404040", +"] c #1E1E1E", +"^ c #B4B4B4", +"/ c #E9E9E9", +"( c #242424", +"_ c #343434", +": c #F4F4F4", +"< c #2D2D2D", +"[ c #1F1F1F", +"} c #565656", +"| c #B0B0B0", +"1 c #353535", +"2 c #2C2C2C", +"3 c #939393", +"4 c #E3E3E3", +".............", +".+++++++++++.", +".+++++++@#$+.", +".++++++%&*=+.", +".+++++-;*>++.", +".+,'++)*!+++.", +".~{]^/(_:+++.", +".+,<[}*|++++.", +".++,<*1~++++.", +".+++,23+++++.", +".++++,4+++++.", +".+++++++++++.", +"............."}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-active.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-active.xpm new file mode 100644 index 00000000..07a3e607 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-active.xpm @@ -0,0 +1,28 @@ +/* XPM */ +static char * shade_active_xpm[] = { +"12 12 13 1", +" c None", +". c #49678B", +"+ c #ADC7E9", +"@ c #A7C3E7", +"# c #A1BFE5", +"$ c #F4F5F6", +"% c #9BBAE2", +"& c #90B2DE", +"* c #86ABD9", +"= c #84AAD8", +"- c #82A8D6", +"; c #7FA6D5", +"> c #7CA4D3", +"............", +".++++++++++.", +".@@@@@@@@@@.", +".##$$$$$$##.", +".%%$$$$$$%%.", +".&&&&&&&&&&.", +".**********.", +".==========.", +".----------.", +".;;;;;;;;;;.", +".>>>>>>>>>>.", +"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-inactive.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-inactive.xpm new file mode 100644 index 00000000..8c8e5ba8 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-inactive.xpm @@ -0,0 +1,25 @@ +/* XPM */ +static char * shade_inactive_xpm[] = { +"12 12 10 1", +" c None", +". c #928F8B", +"+ c #FFFFFF", +"@ c #6D6C6C", +"# c #FEFDFD", +"$ c #F9F8F8", +"% c #FAF9F9", +"& c #FBFAFA", +"* c #FCFBFB", +"= c #FDFDFD", +"............", +".++++++++++.", +".++++++++++.", +".++@@@@@@++.", +".++@@@@@@++.", +".##########.", +".$$$$$$$$$$.", +".%%%%%%%%%%.", +".&&&&&&&&&&.", +".**********.", +".==========.", +"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-pressed.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-pressed.xpm new file mode 100644 index 00000000..33d539fe --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-pressed.xpm @@ -0,0 +1,19 @@ +/* XPM */ +static char * shade_pressed_xpm[] = { +"12 12 4 1", +" c None", +". c #49678B", +"+ c #7AA1D2", +"@ c #F4F5F6", +"............", +".++++++++++.", +".++++++++++.", +".++@@@@@@++.", +".++@@@@@@++.", +".++++++++++.", +".++++++++++.", +".++++++++++.", +".++++++++++.", +".++++++++++.", +".++++++++++.", +"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-active.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-active.xpm new file mode 100644 index 00000000..675a0ba0 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-active.xpm @@ -0,0 +1,28 @@ +/* XPM */ +static char * shade_toggled_active_xpm[] = { +"12 12 13 1", +" c None", +". c #49678B", +"+ c #ADC7E9", +"@ c #A7C3E7", +"# c #A1BFE5", +"$ c #F4F5F6", +"% c #9BBAE2", +"& c #90B2DE", +"* c #86ABD9", +"= c #84AAD8", +"- c #82A8D6", +"; c #7FA6D5", +"> c #7CA4D3", +"............", +".++++++++++.", +".@@@@@@@@@@.", +".##$$$$$$##.", +".%%$$$$$$%%.", +".&&&&&&&&&&.", +".***$$$$***.", +".====$$====.", +".----------.", +".;;;;;;;;;;.", +".>>>>>>>>>>.", +"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-inactive.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-inactive.xpm new file mode 100644 index 00000000..14069b0f --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-inactive.xpm @@ -0,0 +1,25 @@ +/* XPM */ +static char * shade_toggled_inactive_xpm[] = { +"12 12 10 1", +" c None", +". c #928F8B", +"+ c #FFFFFF", +"@ c #6D6C6C", +"# c #FEFDFD", +"$ c #F9F8F8", +"% c #FAF9F9", +"& c #FBFAFA", +"* c #FCFBFB", +"= c #FDFDFD", +"............", +".++++++++++.", +".++++++++++.", +".++@@@@@@++.", +".++@@@@@@++.", +".##########.", +".$$$@@@@$$$.", +".%%%%@@%%%%.", +".&&&&&&&&&&.", +".**********.", +".==========.", +"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-pressed.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-pressed.xpm new file mode 100644 index 00000000..e97d62e0 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-pressed.xpm @@ -0,0 +1,19 @@ +/* XPM */ +static char * shade_toggled_pressed_xpm[] = { +"12 12 4 1", +" c None", +". c #49678B", +"+ c #7AA1D2", +"@ c #F4F5F6", +"............", +".++++++++++.", +".++++++++++.", +".++@@@@@@++.", +".++@@@@@@++.", +".++++++++++.", +".+++@@@@+++.", +".++++@@++++.", +".++++++++++.", +".++++++++++.", +".++++++++++.", +"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-active.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-active.xpm new file mode 100644 index 00000000..7b5c1147 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-active.xpm @@ -0,0 +1,28 @@ +/* XPM */ +static char * stick_active_xpm[] = { +"12 12 13 1", +" c None", +". c #49678B", +"+ c #ADC7E9", +"@ c #A7C3E7", +"# c #A1BFE5", +"$ c #F4F5F6", +"% c #9BBAE2", +"& c #90B2DE", +"* c #86ABD9", +"= c #84AAD8", +"- c #82A8D6", +"; c #7FA6D5", +"> c #7CA4D3", +"............", +".++++++++++.", +".@@@@@@@@@@.", +".##$$##$$##.", +".%%$$%%$$%%.", +".&&&&&&&&&&.", +".**********.", +".==$$==$$==.", +".--$$--$$--.", +".;;;;;;;;;;.", +".>>>>>>>>>>.", +"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-inactive.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-inactive.xpm new file mode 100644 index 00000000..7d63a5d7 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-inactive.xpm @@ -0,0 +1,25 @@ +/* XPM */ +static char * stick_inactive_xpm[] = { +"12 12 10 1", +" c None", +". c #928F8B", +"+ c #FFFFFF", +"@ c #6D6C6C", +"# c #FEFDFD", +"$ c #F9F8F8", +"% c #FAF9F9", +"& c #FBFAFA", +"* c #FCFBFB", +"= c #FDFDFD", +"............", +".++++++++++.", +".++++++++++.", +".++@@++@@++.", +".++@@++@@++.", +".##########.", +".$$$$$$$$$$.", +".%%@@%%@@%%.", +".&&@@&&@@&&.", +".**********.", +".==========.", +"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-pressed.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-pressed.xpm new file mode 100644 index 00000000..01af6c17 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-pressed.xpm @@ -0,0 +1,19 @@ +/* XPM */ +static char * stick_pressed_xpm[] = { +"12 12 4 1", +" c None", +". c #49678B", +"+ c #7AA1D2", +"@ c #F4F5F6", +"............", +".++++++++++.", +".++++++++++.", +".++@@++@@++.", +".++@@++@@++.", +".++++++++++.", +".++++++++++.", +".++@@++@@++.", +".++@@++@@++.", +".++++++++++.", +".++++++++++.", +"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-toggled-active.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-toggled-active.xpm new file mode 100644 index 00000000..745312e9 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-toggled-active.xpm @@ -0,0 +1,28 @@ +/* XPM */ +static char * stick_toggled_active_xpm[] = { +"12 12 13 1", +" c None", +". c #49678B", +"+ c #ADC7E9", +"@ c #A7C3E7", +"# c #A1BFE5", +"$ c #9BBAE2", +"% c #F4F5F6", +"& c #90B2DE", +"* c #86ABD9", +"= c #84AAD8", +"- c #82A8D6", +"; c #7FA6D5", +"> c #7CA4D3", +"............", +".++++++++++.", +".@@@@@@@@@@.", +".##########.", +".$$$%%%%$$$.", +".&&&%&%%&&&.", +".***%%*%***.", +".===%%%%===.", +".----------.", +".;;;;;;;;;;.", +".>>>>>>>>>>.", +"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-toggled-inactive.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-toggled-inactive.xpm new file mode 100644 index 00000000..e644facc --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-toggled-inactive.xpm @@ -0,0 +1,25 @@ +/* XPM */ +static char * stick_toggled_inactive_xpm[] = { +"12 12 10 1", +" c None", +". c #928F8B", +"+ c #FFFFFF", +"@ c #6D6C6C", +"# c #FEFDFD", +"$ c #F9F8F8", +"% c #FAF9F9", +"& c #FBFAFA", +"* c #FCFBFB", +"= c #FDFDFD", +"............", +".++++++++++.", +".++++++++++.", +".++++++++++.", +".+++@@@@+++.", +".###@#@@###.", +".$$$@@$@$$$.", +".%%%@@@@%%%.", +".&&&&&&&&&&.", +".**********.", +".==========.", +"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/title-focus.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/title-focus.xpm new file mode 100644 index 00000000..6371404a --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/title-focus.xpm @@ -0,0 +1,40 @@ +/* XPM */ +static char * title_focus_xpm[] = { +"1 18 19 1", +" c None", +". c #ADD3FF", +"+ c #98B9E2", +"@ c #96B8E1", +"# c #94B6E0", +"$ c #93B5DF", +"% c #91B4DF", +"& c #90B3DE", +"* c #8EB1DD", +"= c #8BAFDB", +"- c #86ABD9", +"; c #85AAD8", +"> c #84A9D7", +", c #82A8D6", +"' c #81A7D5", +") c #80A6D5", +"! c #7EA4D4", +"~ c #7DA3D3", +"{ c #7A9FCE", +".", +"+", +"@", +"#", +"$", +"%", +"&", +"*", +"=", +"-", +";", +">", +",", +"'", +")", +"!", +"~", +"{"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/title-unfocus.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/title-unfocus.xpm new file mode 100644 index 00000000..3fa23d1a --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/title-unfocus.xpm @@ -0,0 +1,40 @@ +/* XPM */ +static char * title_unfocus_xpm[] = { +"1 18 19 1", +" c None", +". c #FFFFFF", +"+ c #EAE9E8", +"@ c #E9E8E7", +"# c #E8E7E6", +"$ c #E7E6E5", +"% c #E6E5E3", +"& c #E5E4E2", +"* c #E4E3E1", +"= c #E2E1DF", +"- c #DEDCDA", +"; c #DDDBD9", +"> c #DCDAD8", +", c #DBD9D7", +"' c #DAD8D6", +") c #D9D7D5", +"! c #D8D6D4", +"~ c #D7D5D3", +"{ c #D2D0CE", +".", +"+", +"@", +"#", +"$", +"%", +"&", +"*", +"=", +"-", +";", +">", +",", +"'", +")", +"!", +"~", +"{"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/toolbar-iconbar-focus.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/toolbar-iconbar-focus.xpm new file mode 100644 index 00000000..9d1cf257 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/toolbar-iconbar-focus.xpm @@ -0,0 +1,44 @@ +/* XPM */ +static char * toolbar_iconbar_focus_xpm[] = { +"1 20 21 1", +" c None", +". c #CCC9C7", +"+ c #D1CFCC", +"@ c #D6D3D1", +"# c #D6D4D2", +"$ c #D5D3D1", +"% c #D4D2D0", +"& c #D3D1CF", +"* c #D2D0CE", +"= c #D0CECC", +"- c #CFCDCB", +"; c #CAC8C5", +"> c #C9C7C4", +", c #C8C6C3", +"' c #C7C4C1", +") c #C6C3C0", +"! c #C4C2BF", +"~ c #C3C1BE", +"{ c #C2C0BD", +"] c #C1BEBB", +"^ c #C0BDBA", +".", +"+", +"@", +"#", +"$", +"%", +"&", +"*", +"=", +"-", +";", +">", +",", +"'", +")", +"!", +"~", +"{", +"]", +"^"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/toolbar-iconbar-unfocus.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/toolbar-iconbar-unfocus.xpm new file mode 100644 index 00000000..9fc1446f --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/toolbar-iconbar-unfocus.xpm @@ -0,0 +1,38 @@ +/* XPM */ +static char * toolbar_iconbar_unfocus_xpm[] = { +"1 20 15 1", +" c None", +". c #FEFEFE", +"+ c #FDFDFD", +"@ c #FCFCFC", +"# c #FBFBFB", +"$ c #F5F5F4", +"% c #F3F3F2", +"& c #F2F2F1", +"* c #F1F0EF", +"= c #EFEFEE", +"- c #EEEDEC", +"; c #ECECEB", +"> c #EBEAE9", +", c #EAE9E8", +"' c #E8E7E6", +".", +".", +".", +"+", +"+", +"@", +"@", +"@", +"#", +"#", +"$", +"%", +"&", +"*", +"=", +"-", +";", +">", +",", +"'"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/unselected-active.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/unselected-active.xpm new file mode 100644 index 00000000..09d95cfc --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/unselected-active.xpm @@ -0,0 +1,19 @@ +/* XPM */ +static char * unselected_active_xpm[] = { +"13 13 3 1", +" c None", +". c #4B6E99", +"+ c #C9DAEF", +".............", +".+++++++++++.", +".+++++++++++.", +".+++++++++++.", +".+++++++++++.", +".+++++++++++.", +".+++++++++++.", +".+++++++++++.", +".+++++++++++.", +".+++++++++++.", +".+++++++++++.", +".+++++++++++.", +"............."}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/unselected.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/unselected.xpm new file mode 100644 index 00000000..f05df80b --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/unselected.xpm @@ -0,0 +1,19 @@ +/* XPM */ +static char * unselected_xpm[] = { +"13 13 3 1", +" c None", +". c #797979", +"+ c #FFFFFF", +".............", +".+++++++++++.", +".+++++++++++.", +".+++++++++++.", +".+++++++++++.", +".+++++++++++.", +".+++++++++++.", +".+++++++++++.", +".+++++++++++.", +".+++++++++++.", +".+++++++++++.", +".+++++++++++.", +"............."}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/theme.cfg b/docker/debian-full/fluxbox/styles/Clearlooks/theme.cfg new file mode 100644 index 00000000..4a936075 --- /dev/null +++ b/docker/debian-full/fluxbox/styles/Clearlooks/theme.cfg @@ -0,0 +1,129 @@ +! vim: set ft=xdefaults: +! Clearlooks theme, port from Openbox +! 29.04.2012 + +! Menu +menu.bevelWidth: 0 +menu.borderWidth: 1 +menu.borderColor: #AAAAAA +menu.bullet: empty +menu.submenu.pixmap: bullet.xpm +menu.hilite.submenu.pixmap: bullet-active.xpm +menu.selected.pixmap: selected.xpm +menu.hilite.selected.pixmap: selected-active.xpm +menu.unselected.pixmap: unselected.xpm +menu.hilite.unselected.pixmap: unselected-active.xpm +menu.bullet.position: right +menu.itemHeight: 17 +menu.title: flat +menu.title.justify: Center +menu.title.color: #E6E7E6 +menu.title.textColor: #111111 +menu.titleHeight: 17 +menu.frame: flat +menu.frame.justify: left +menu.frame.color: #FFFFFF +menu.frame.textColor: #111111 +menu.frame.disableColor: #AAAAAA +menu.hilite.pixmap: menu-hilite.xpm +menu.hilite.textColor: #FFFFFF + +! Window +window.bevelWidth: 3 +window.borderWidth: 1 +window.borderColor: #585A5D +window.title.height: 18 +window.justify: right +window.label.focus: ParentRelative +window.label.unfocus: ParentRelative +#window.label.focus.pixmap: label-focus.xpm +#window.label.unfocus.pixmap: label-unfocus.xpm +window.label.focus.textColor: #FFFFFF +window.label.unfocus.textColor: #70747D +window.title.focus.pixmap: title-focus.xpm +window.title.unfocus.pixmap: title-unfocus.xpm +window.handleWidth: 0 +window.handle.focus: flat +window.handle.focus.color: #EAEBEC +window.handle.unfocus: flat +window.handle.unfocus.color: #EAEBEC +window.grip.focus: flat +window.grip.focus.color: #EAEBEC +window.grip.unfocus: flat +window.grip.unfocus.color: #EAEBEC +window.close.pixmap: close-active.xpm +window.close.pressed.pixmap: close-pressed.xpm +window.close.unfocus.pixmap: close-inactive.xpm +window.iconify.pixmap: minimize-active.xpm +window.iconify.pressed.pixmap: minimize-pressed.xpm +window.iconify.unfocus.pixmap: minimize-inactive.xpm +window.maximize.pixmap: maximize-active.xpm +window.maximize.pressed.pixmap: maximize-pressed.xpm +window.maximize.unfocus.pixmap: maximize-inactive.xpm +window.menuicon.pixmap: menu-active.xpm +window.menuicon.pressed.pixmap: menu-pressed.xpm +window.menuicon.unfocus.pixmap: menu-inactive.xpm +window.shade.pixmap: shade-active.xpm +window.shade.unfocus.pixmap: shade-inactive.xpm +window.shade.pressed.pixmap: shade-pressed.xpm +window.unshade.pixmap: shade-toggled-active.xpm +window.unshade.unfocus.pixmap: shade-toggled-inactive.xpm +window.unshade.pressed.pixmap: shade-toggled-pressed.xpm +window.stick.pixmap: stick-active.xpm +window.stick.unfocus.pixmap: stick-inactive.xpm +window.stick.pressed.pixmap: stick-pressed.xpm +window.stuck.pixmap: stick-toggled-active.xpm +window.stuck.unfocus.pixmap: stick-toggled-inactive.xpm + +! Toolbar +toolbar.bevelWidth: 1 +toolbar.borderWidth: 1 +toolbar.borderColor: #585A5D +toolbar.height: 20 +toolbar: flat +toolbar.color: #EAEBEC +toolbar.clock: flat +toolbar.clock.borderWidth: 0 +toolbar.clock.borderColor: #A9A5A2 +toolbar.clock.justify: center +toolbar.clock.textColor: #111111 +toolbar.clock.color: #EDECEB +toolbar.systray: flat +toolbar.systray.borderWidth: 0 +toolbar.systray.borderColor: #A9A5A2 +toolbar.systray.color: #EDECEB +toolbar.workspace: flat +toolbar.workspace.borderWidth: 0 +toolbar.workspace.borderColor: #A9A5A2 +toolbar.workspace.justify: center +toolbar.workspace.textColor: #111111 +toolbar.workspace.color: #EDECEB +toolbar.button: flat +toolbar.button.borderWidth: 0 +toolbar.button.borderColor: #A9A5A2 +toolbar.button.picColor: #111111 +toolbar.button.color: #EDECEB +toolbar.button.pressed.picColor: #111111 +toolbar.button.pressed.color: #CFCDCB +toolbar.iconbar.empty: flat +toolbar.iconbar.empty.color: #EDECEB +toolbar.iconbar.focused.pixmap: toolbar-iconbar-focus.xpm +toolbar.iconbar.focused.borderWidth: 1 +toolbar.iconbar.focused.borderColor: #A9A5A2 +toolbar.iconbar.focused.justify: center +toolbar.iconbar.focused.textColor: #111111 +toolbar.iconbar.unfocused.pixmap: toolbar-iconbar-unfocus.xpm +toolbar.iconbar.unfocused.borderWidth: 1 +toolbar.iconbar.unfocused.borderColor: #A9A5A2 +toolbar.iconbar.unfocused.justify: center +toolbar.iconbar.unfocused.textColor: #111111 + +! Slit +slit: flat +slit.bevelWidth: 0 +slit.borderColor: #585A5D +slit.borderWidth: 1 +slit.color: #EDECEB + +! Font +*.font: Sans-8 diff --git a/docker/debian-full/fluxbox/windowmenu b/docker/debian-full/fluxbox/windowmenu new file mode 100644 index 00000000..d867b64c --- /dev/null +++ b/docker/debian-full/fluxbox/windowmenu @@ -0,0 +1,15 @@ +[begin] + [shade] + [stick] + [maximize] + [iconify] + [raise] + [lower] + [settitledialog] + [sendto] + [layer] + [alpha] + [extramenus] + [separator] + [close] +[end] diff --git a/docker/debian-full/getty-autologin-serial.conf b/docker/debian-full/getty-autologin-serial.conf new file mode 100644 index 00000000..ad9b2c09 --- /dev/null +++ b/docker/debian-full/getty-autologin-serial.conf @@ -0,0 +1,3 @@ +[Service] +ExecStart= +ExecStart=-/sbin/agetty --autologin root --noissue --noclear -s %I 115200,38400,9600 vt102 diff --git a/docker/debian-full/getty-noclear.conf b/docker/debian-full/getty-noclear.conf new file mode 100644 index 00000000..52671c75 --- /dev/null +++ b/docker/debian-full/getty-noclear.conf @@ -0,0 +1,2 @@ +[Service] +TTYVTDisallocate=no diff --git a/docker/debian-full/getty-override.conf b/docker/debian-full/getty-override.conf new file mode 100644 index 00000000..6ca2ac92 --- /dev/null +++ b/docker/debian-full/getty-override.conf @@ -0,0 +1,3 @@ +[Service] +ExecStart= +ExecStart=-/sbin/agetty --autologin root --noissue --noclear %I 38400 $TERM diff --git a/docker/debian-full/logind.conf b/docker/debian-full/logind.conf new file mode 100644 index 00000000..f6e5c21d --- /dev/null +++ b/docker/debian-full/logind.conf @@ -0,0 +1,37 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# Entries in this file show the compile time defaults. +# You can change settings by editing this file. +# Defaults can be restored by simply deleting this file. +# +# See logind.conf(5) for details. + +[Login] +NAutoVTs=0 +ReserveVT=0 +#KillUserProcesses=no +#KillOnlyUsers= +#KillExcludeUsers=root +#InhibitDelayMaxSec=5 +#HandlePowerKey=poweroff +#HandleSuspendKey=suspend +#HandleHibernateKey=hibernate +#HandleLidSwitch=suspend +#HandleLidSwitchDocked=ignore +#PowerKeyIgnoreInhibited=no +#SuspendKeyIgnoreInhibited=no +#HibernateKeyIgnoreInhibited=no +#LidSwitchIgnoreInhibited=yes +#HoldoffTimeoutSec=30s +#IdleAction=ignore +#IdleActionSec=30min +#RuntimeDirectorySize=10% +#RemoveIPC=yes +#InhibitorsMax=8192 +#SessionsMax=8192 +#UserTasksMax=33% diff --git a/docker/debian-full/xorg.conf b/docker/debian-full/xorg.conf new file mode 100644 index 00000000..9a018628 --- /dev/null +++ b/docker/debian-full/xorg.conf @@ -0,0 +1,67 @@ +Section "ServerLayout" + Identifier "X.org Configured" + Screen 0 "Screen0" 0 0 + InputDevice "Mouse0" "CorePointer" + InputDevice "Keyboard0" "CoreKeyboard" +EndSection + +Section "Files" + ModulePath "/usr/lib/xorg/modules" + FontPath "/usr/share/fonts/misc/" + FontPath "/usr/share/fonts/TTF/" + #FontPath "/usr/share/fonts/OTF/" + #FontPath "/usr/share/fonts/Type1/" + FontPath "/usr/share/fonts/100dpi/" + FontPath "/usr/share/fonts/75dpi/" +EndSection + +Section "Module" + Load "glx" +EndSection + +Section "InputDevice" + Identifier "Keyboard0" + Driver "kbd" +EndSection + +Section "InputDevice" + Identifier "Mouse0" + Driver "mouse" + Option "Protocol" "auto" + Option "Device" "/dev/input/mice" + Option "ZAxisMapping" "4 5 6 7" +EndSection + +Section "Monitor" + Identifier "Monitor0" + VendorName "Monitor Vendor" + ModelName "Monitor Model" +EndSection + +Section "Device" + ### Available Driver options are:- + ### Values: : integer, : float, : "True"/"False", + ### : "String", : " Hz/kHz/MHz", + ### : "%" + ### [arg]: arg optional + #Option "ShadowFB" # [] + #Option "Rotate" # + #Option "fbdev" # + #Option "debug" # [] + Identifier "Card0" + Driver "fbdev" + #BusID "PCI:0:2:0" + Driver "vesa" +EndSection + +Section "Screen" + Identifier "Screen0" + Device "Card0" + Monitor "Monitor0" + SubSection "Display" + #Viewport 0 0 + Depth 24 + Modes "1280x1024" + EndSubSection +EndSection + diff --git a/tools/copy-to-sha256.py b/tools/copy-to-sha256.py new file mode 100755 index 00000000..10fd1986 --- /dev/null +++ b/tools/copy-to-sha256.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python + +import os +import logging +import stat +import argparse +import hashlib +import shutil + +def hash_file(filename): + h = hashlib.sha256() + with open(filename, "rb", buffering=0) as f: + for b in iter(lambda: f.read(128 * 1024), b""): + h.update(b) + return h.hexdigest() + + +def main(): + logging.basicConfig(format="%(message)s") + logger = logging.getLogger("copy") + logger.setLevel(logging.DEBUG) + + args = argparse.ArgumentParser(description="...", + formatter_class=argparse.RawTextHelpFormatter) + args.add_argument("from_path", metavar="from", help="from") + args.add_argument("to_path", metavar="to", help="to") + + args = args.parse_args() + + from_path = os.path.normpath(args.from_path) + to_path = os.path.normpath(args.to_path) + + def onerror(oserror): + logger.warning(oserror) + + files = os.walk(from_path, onerror=onerror) + + for f in files: + dirpath, dirnames, filenames = f + + for filename in filenames: + absname = os.path.join(dirpath, filename) + st = os.lstat(absname) + mode = st.st_mode + + assert not stat.S_ISDIR(mode) + if stat.S_ISLNK(mode) or stat.S_ISCHR(mode) or stat.S_ISBLK(mode) or stat.S_ISFIFO(mode) or stat.S_ISSOCK(mode): + continue + + sha256 = hash_file(absname) + to_abs = os.path.join(to_path, sha256) + + if os.path.exists(to_abs): + logger.info("Exists, skipped {}".format(to_abs)) + else: + logger.info("cp {} {}".format(absname, to_abs)) + shutil.copyfile(absname, to_abs) + +if __name__ == "__main__": + main() diff --git a/tools/fs2json.py b/tools/fs2json.py new file mode 100755 index 00000000..9f087b6f --- /dev/null +++ b/tools/fs2json.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python + +import argparse +import json +import os +import stat +import sys +import itertools +import logging +import hashlib + +VERSION = 3 + +IDX_NAME = 0 +IDX_SIZE = 1 +IDX_MTIME = 2 +IDX_MODE = 3 +IDX_UID = 4 +IDX_GID = 5 + +# target for symbolic links +# child nodes for directories +# sha256 for files +IDX_TARGET = 6 +IDX_SHA256 = 6 + + +def hash_file(filename): + h = hashlib.sha256() + with open(filename, "rb", buffering=0) as f: + for b in iter(lambda : f.read(128*1024), b""): + h.update(b) + return h.hexdigest() + + +def main(): + logging.basicConfig(format="%(message)s") + logger = logging.getLogger("fs2json") + logger.setLevel(logging.DEBUG) + + args = argparse.ArgumentParser(description="Create filesystem JSON. Example:\n" + " ./fs2xml.py --exclude /boot/ --out fs.json /mnt/", + formatter_class=argparse.RawTextHelpFormatter + ) + args.add_argument("--exclude", + action="append", + metavar="path", + help="Path to exclude (relative to base path). Can be specified multiple times.") + args.add_argument("--out", + metavar="out", + nargs="?", + type=argparse.FileType("w"), + help="File to write to (defaults to stdout)", + default=sys.stdout) + args.add_argument("path", + metavar="path", + help="Base path to include in JSON") + + args = args.parse_args() + + path = os.path.normpath(args.path) + path = path + "/" + exclude = args.exclude or [] + exclude = [os.path.join("/", os.path.normpath(p)) for p in exclude] + exclude = set(exclude) + + def onerror(oserror): + logger.warning(oserror) + + rootdepth = path.count("/") + files = os.walk(path, onerror=onerror) + prevpath = [] + + mainroot = [] + result = { + "fsroot": mainroot, + "version": VERSION, + "size": 0, + } + rootstack = [mainroot] + + def make_node(st, name): + obj = [None] * 7 + + obj[IDX_NAME] = name + obj[IDX_SIZE] = st.st_size + obj[IDX_MTIME] = int(st.st_mtime) + obj[IDX_MODE] = int(st.st_mode) + + obj[IDX_UID] = st.st_uid + obj[IDX_GID] = st.st_gid + + result["size"] += st.st_size + + # Missing: + # int(st.st_atime), + # int(st.st_ctime), + + return obj + + logger.info("Creating file tree ...") + + for f in files: + dirpath, dirnames, filenames = f + pathparts = dirpath.split("/") + pathparts = pathparts[rootdepth:] + fullpath = os.path.join("/", *pathparts) + + if fullpath in exclude: + dirnames[:] = [] + continue + + depth = 0 + for this, prev in zip(pathparts, prevpath): + if this != prev: + break + depth += 1 + + for name in prevpath[depth:]: + rootstack.pop() + + oldroot = rootstack[-1] + + assert len(pathparts[depth:]) == 1 + openname = pathparts[-1] + + if openname == "": + root = mainroot + else: + root = [] + st = os.stat(dirpath) + rootobj = make_node(st, openname) + rootobj[IDX_TARGET] = root + oldroot.append(rootobj) + + rootstack.append(root) + + for filename in itertools.chain(filenames, dirnames): + absname = os.path.join(dirpath, filename) + + st = os.lstat(absname) + isdir = stat.S_ISDIR(st.st_mode) + islink = stat.S_ISLNK(st.st_mode) + + isfile = stat.S_ISREG(st.st_mode) + + if isdir and not islink: + continue + + obj = make_node(st, filename) + + if islink: + target = os.readlink(absname) + obj[IDX_TARGET] = target + elif isfile: + obj[IDX_SHA256] = hash_file(absname) + + while obj[-1] is None: + obj.pop() + + root.append(obj) + + prevpath = pathparts + + logger.info("Creating json ...") + + json.dump(result, args.out, check_circular=False, separators=(',', ':')) + +if __name__ == "__main__": + main() From 5c2ab56b3b7972b5fc903c22c522990af4c59f73 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Fri, 17 Aug 2018 20:58:44 +0530 Subject: [PATCH 1163/2137] add gen_push16_ss{16,32} This adds the ImmVal enum type too. --- src/rust/codegen.rs | 90 +++++++++++++++++++++++++++++++++++- src/rust/cpu.rs | 7 +++ src/rust/jit_instructions.rs | 28 ++++++----- 3 files changed, 109 insertions(+), 16 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index db9686bc..fee499d7 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -1,4 +1,4 @@ -use cpu::BitSize; +use cpu::{BitSize, ImmVal}; use global_pointers; use jit::JitContext; use modrm; @@ -608,3 +608,91 @@ pub fn gen_task_switch_test_mmx(ctx: &mut JitContext) { ctx.builder.instruction_body.block_end(); } + +pub fn gen_push16_ss16(ctx: &mut JitContext, imm: ImmVal) { + match imm { + ImmVal::REG(r) => { + ctx.builder + .instruction_body + .load_aligned_u16(global_pointers::get_reg16_offset(r)); + }, + ImmVal::CONST(imm) => { + ctx.builder.instruction_body.push_i32(imm as i32); + }, + ImmVal::MEM => { + // NOTE: It's important that this match stays atop so gen_safe_read16 gets called early enough + gen_safe_read16(ctx); + }, + }; + let value_local = ctx.builder.set_new_local(); + + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_reg16_offset(regs::SP)); + ctx.builder.instruction_body.push_i32(2); + ctx.builder.instruction_body.sub_i32(); + let reg16_updated_local = ctx.builder.tee_new_local(); + ctx.builder.instruction_body.push_i32(0xFFFF); + ctx.builder.instruction_body.and_i32(); + + if !ctx.cpu.has_flat_segmentation() { + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_seg_offset(regs::SS)); + ctx.builder.instruction_body.add_i32(); + } + + let sp_local = ctx.builder.set_new_local(); + gen_safe_write16(ctx, &sp_local, &value_local); + ctx.builder.free_local(sp_local); + ctx.builder.free_local(value_local); + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg16_offset(regs::SP) as i32); + ctx.builder.instruction_body.get_local(®16_updated_local); + ctx.builder.instruction_body.store_aligned_u16(); + ctx.builder.free_local(reg16_updated_local); +} + +pub fn gen_push16_ss32(ctx: &mut JitContext, imm: ImmVal) { + match imm { + ImmVal::REG(r) => { + ctx.builder + .instruction_body + .load_aligned_u16(global_pointers::get_reg16_offset(r)); + }, + ImmVal::CONST(imm) => { + ctx.builder.instruction_body.push_i32(imm as i32); + }, + ImmVal::MEM => { + // NOTE: It's important that this match stays atop so gen_safe_read16 gets called early enough + gen_safe_read16(ctx); + }, + }; + let value_local = ctx.builder.set_new_local(); + + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_reg32_offset(regs::ESP)); + ctx.builder.instruction_body.push_i32(2); + ctx.builder.instruction_body.sub_i32(); + let reg32_updated_local = ctx.builder.tee_new_local(); + + if !ctx.cpu.has_flat_segmentation() { + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_seg_offset(regs::SS)); + ctx.builder.instruction_body.add_i32(); + } + + let sp_local = ctx.builder.set_new_local(); + gen_safe_write16(ctx, &sp_local, &value_local); + ctx.builder.free_local(sp_local); + ctx.builder.free_local(value_local); + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg32_offset(regs::ESP) as i32); + ctx.builder.instruction_body.get_local(®32_updated_local); + ctx.builder.instruction_body.store_aligned_i32(); + ctx.builder.free_local(reg32_updated_local); +} diff --git a/src/rust/cpu.rs b/src/rust/cpu.rs index ff45fdd9..cf616cb5 100644 --- a/src/rust/cpu.rs +++ b/src/rust/cpu.rs @@ -27,6 +27,13 @@ pub enum BitSize { DWORD, } +#[derive(Copy, Clone, Eq, PartialEq)] +pub enum ImmVal { + REG(u32), + CONST(u32), + MEM, +} + pub fn read8(addr: u32) -> u8 { unsafe { unsafe_cpu::read8(addr) } } pub fn read16(addr: u32) -> u16 { unsafe { unsafe_cpu::read16(addr) } } pub fn read32(addr: u32) -> u32 { unsafe { unsafe_cpu::read32(addr) } } diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 4c28b698..5e79d557 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1,6 +1,7 @@ #![allow(non_snake_case)] use codegen; +use cpu::ImmVal; use cpu_context::CpuContext; use global_pointers; use jit::JitContext; @@ -96,13 +97,12 @@ pub fn instr_F3_jit(ctx: &mut JitContext, instr_flags: &mut u32) { } fn push16_reg_jit(ctx: &mut JitContext, r: u32) { - let name = if ctx.cpu.ssize_32() { - "push16_ss32" + if ctx.cpu.ssize_32() { + codegen::gen_push16_ss32(ctx, ImmVal::REG(r)); } else { - "push16_ss16" - }; - codegen::gen_fn1_reg16(ctx, name, r); + codegen::gen_push16_ss16(ctx, ImmVal::REG(r)); + } } fn push32_reg_jit(ctx: &mut JitContext, r: u32) { @@ -116,13 +116,12 @@ fn push32_reg_jit(ctx: &mut JitContext, r: u32) { } fn push16_imm_jit(ctx: &mut JitContext, imm: u32) { - let name = if ctx.cpu.ssize_32() { - "push16_ss32" + if ctx.cpu.ssize_32() { + codegen::gen_push16_ss32(ctx, ImmVal::CONST(imm)); } else { - "push16_ss16" - }; - codegen::gen_fn1_const(ctx, name, imm) + codegen::gen_push16_ss16(ctx, ImmVal::CONST(imm)); + } } fn push32_imm_jit(ctx: &mut JitContext, imm: u32) { @@ -137,13 +136,12 @@ fn push32_imm_jit(ctx: &mut JitContext, imm: u32) { fn push16_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); - let name = if ctx.cpu.ssize_32() { - "push16_ss32_mem" + if ctx.cpu.ssize_32() { + codegen::gen_push16_ss32(ctx, ImmVal::MEM); } else { - "push16_ss16_mem" - }; - codegen::gen_modrm_fn0(ctx, name) + codegen::gen_push16_ss16(ctx, ImmVal::MEM); + } } fn push32_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { From be7d21e79f967b1ea731b15b66d8addee7c95dcd Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Fri, 17 Aug 2018 21:23:02 +0530 Subject: [PATCH 1164/2137] add gen_push32_ss{16,32} --- src/rust/codegen.rs | 90 ++++++++++++++++++++++++++++++++++++ src/rust/jit_instructions.rs | 27 +++++------ 2 files changed, 102 insertions(+), 15 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index fee499d7..287d3c6c 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -696,3 +696,93 @@ pub fn gen_push16_ss32(ctx: &mut JitContext, imm: ImmVal) { ctx.builder.instruction_body.store_aligned_i32(); ctx.builder.free_local(reg32_updated_local); } + +pub fn gen_push32_ss16(ctx: &mut JitContext, imm: ImmVal) { + match imm { + ImmVal::REG(r) => { + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_reg32_offset(r)); + }, + ImmVal::CONST(imm) => { + ctx.builder.instruction_body.push_i32(imm as i32); + }, + ImmVal::MEM => { + gen_safe_read32(ctx); + }, + }; + let value_local = ctx.builder.set_new_local(); + + ctx.builder + .instruction_body + .load_aligned_u16(global_pointers::get_reg16_offset(regs::SP)); + ctx.builder.instruction_body.push_i32(4); + ctx.builder.instruction_body.sub_i32(); + ctx.builder.instruction_body.push_i32(0xFFFF); + ctx.builder.instruction_body.and_i32(); + let new_sp_local = ctx.builder.tee_new_local(); + + if !ctx.cpu.has_flat_segmentation() { + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_seg_offset(regs::SS)); + ctx.builder.instruction_body.add_i32(); + } + + let sp_local = ctx.builder.set_new_local(); + + gen_safe_write32(ctx, &sp_local, &value_local); + ctx.builder.free_local(value_local); + ctx.builder.free_local(sp_local); + + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg16_offset(regs::SP) as i32); + ctx.builder.instruction_body.get_local(&new_sp_local); + ctx.builder.instruction_body.store_aligned_u16(); + ctx.builder.free_local(new_sp_local); +} + +pub fn gen_push32_ss32(ctx: &mut JitContext, imm: ImmVal) { + match imm { + ImmVal::REG(r) => { + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_reg32_offset(r)); + }, + ImmVal::CONST(imm) => { + ctx.builder.instruction_body.push_i32(imm as i32); + }, + ImmVal::MEM => { + gen_safe_read32(ctx); + }, + }; + let value_local = ctx.builder.set_new_local(); + + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_reg32_offset(regs::ESP)); + ctx.builder.instruction_body.push_i32(4); + ctx.builder.instruction_body.sub_i32(); + let new_esp_local = ctx.builder.tee_new_local(); + + if !ctx.cpu.has_flat_segmentation() { + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_seg_offset(regs::SS)); + ctx.builder.instruction_body.add_i32(); + } + + let sp_local = ctx.builder.set_new_local(); + + gen_safe_write32(ctx, &sp_local, &value_local); + ctx.builder.free_local(value_local); + ctx.builder.free_local(sp_local); + + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg32_offset(regs::ESP) as i32); + ctx.builder.instruction_body.get_local(&new_esp_local); + ctx.builder.instruction_body.store_aligned_i32(); + ctx.builder.free_local(new_esp_local); +} diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 5e79d557..7f75f93e 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -106,13 +106,12 @@ fn push16_reg_jit(ctx: &mut JitContext, r: u32) { } fn push32_reg_jit(ctx: &mut JitContext, r: u32) { - let name = if ctx.cpu.ssize_32() { - "push32_ss32" + if ctx.cpu.ssize_32() { + codegen::gen_push32_ss32(ctx, ImmVal::REG(r)); } else { - "push32_ss16" - }; - codegen::gen_fn1_reg32(ctx, name, r); + codegen::gen_push32_ss16(ctx, ImmVal::REG(r)); + } } fn push16_imm_jit(ctx: &mut JitContext, imm: u32) { @@ -125,13 +124,12 @@ fn push16_imm_jit(ctx: &mut JitContext, imm: u32) { } fn push32_imm_jit(ctx: &mut JitContext, imm: u32) { - let name = if ctx.cpu.ssize_32() { - "push32_ss32" + if ctx.cpu.ssize_32() { + codegen::gen_push32_ss32(ctx, ImmVal::CONST(imm)); } else { - "push32_ss16" - }; - codegen::gen_fn1_const(ctx, name, imm) + codegen::gen_push32_ss16(ctx, ImmVal::CONST(imm)); + } } fn push16_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { @@ -146,13 +144,12 @@ fn push16_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { fn push32_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); - let name = if ctx.cpu.ssize_32() { - "push32_ss32_mem" + if ctx.cpu.ssize_32() { + codegen::gen_push32_ss32(ctx, ImmVal::MEM); } else { - "push32_ss16_mem" - }; - codegen::gen_modrm_fn0(ctx, name) + codegen::gen_push32_ss16(ctx, ImmVal::MEM); + } } fn pop16_reg_jit(ctx: &mut JitContext, reg: u32) { From 73cbea7d0fadad2a0c56b7f5001365ae05158ad4 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Fri, 17 Aug 2018 21:37:21 +0530 Subject: [PATCH 1165/2137] call gen_pop{16,32} instead of using interpreted variants, update expect tests --- src/rust/jit_instructions.rs | 22 ++++++++--------- tests/expect/tests/pop.wast | 46 +++++++++++++++++++++++++++++++--- tests/expect/tests/push.wast | 48 +++++++++++++++++++++++++++++++++--- 3 files changed, 97 insertions(+), 19 deletions(-) diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 7f75f93e..4a8340d3 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -153,21 +153,19 @@ fn push32_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { } fn pop16_reg_jit(ctx: &mut JitContext, reg: u32) { - if ctx.cpu.ssize_32() { - codegen::gen_set_reg16_fn0(ctx, "pop16_ss32", reg); - } - else { - codegen::gen_set_reg16_fn0(ctx, "pop16_ss16", reg); - } + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg16_offset(reg) as i32); + codegen::gen_pop16(ctx); + ctx.builder.instruction_body.store_aligned_u16(); } fn pop32_reg_jit(ctx: &mut JitContext, reg: u32) { - if ctx.cpu.ssize_32() { - codegen::gen_set_reg32s_fn0(ctx, "pop32s_ss32", reg); - } - else { - codegen::gen_set_reg32s_fn0(ctx, "pop32s_ss16", reg); - } + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg32_offset(reg) as i32); + codegen::gen_pop32s(ctx); + ctx.builder.instruction_body.store_aligned_i32(); } pub fn instr16_50_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, AX); } diff --git a/tests/expect/tests/pop.wast b/tests/expect/tests/pop.wast index dfff0885..eaef36ea 100644 --- a/tests/expect/tests/pop.wast +++ b/tests/expect/tests/pop.wast @@ -7,11 +7,11 @@ (type $t5 (func (param i32) (result i32))) (type $t6 (func (param i32 i32) (result i32))) (import "e" "get_seg" (func $e.get_seg (type $t5))) - (import "e" "pop32s_ss32" (func $e.pop32s_ss32 (type $t4))) + (import "e" "safe_read32s_slow" (func $e.safe_read32s_slow (type $t5))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (set_local $p0 (get_local $p0)) (loop $L0 @@ -23,9 +23,47 @@ (i32.const 560) (i32.load (i32.const 556))) + (i32.const 4) + (if $I3 (result i32) + (i32.and + (i32.eq + (i32.and + (tee_local $l2 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (tee_local $l1 + (i32.add + (tee_local $l0 + (i32.load + (i32.const 20))) + (i32.load + (i32.const 744)))) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4073)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l1) + (i32.const 4095)) + (i32.const 4092))) + (then + (i32.load offset=8388608 align=1 + (i32.xor + (i32.and + (get_local $l2) + (i32.const -4096)) + (get_local $l1)))) + (else + (call $e.safe_read32s_slow + (get_local $l1)))) (i32.store - (i32.const 4) - (call $e.pop32s_ss32)) + (i32.const 20) + (i32.add + (get_local $l0) + (i32.const 4))) + (i32.store) (i32.store (i32.const 560) (i32.add diff --git a/tests/expect/tests/push.wast b/tests/expect/tests/push.wast index 5fb791f9..21c64ff3 100644 --- a/tests/expect/tests/push.wast +++ b/tests/expect/tests/push.wast @@ -7,11 +7,11 @@ (type $t5 (func (param i32) (result i32))) (type $t6 (func (param i32 i32) (result i32))) (import "e" "get_seg" (func $e.get_seg (type $t5))) - (import "e" "push32_ss32" (func $e.push32_ss32 (type $t1))) + (import "e" "safe_write32_slow" (func $e.safe_write32_slow (type $t2))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (set_local $p0 (get_local $p0)) (loop $L0 @@ -23,9 +23,51 @@ (i32.const 560) (i32.load (i32.const 556))) - (call $e.push32_ss32 + (set_local $l0 (i32.load (i32.const 4))) + (set_local $l2 + (i32.add + (tee_local $l1 + (i32.sub + (i32.load + (i32.const 20)) + (i32.const 4))) + (i32.load + (i32.const 744)))) + (if $I3 + (i32.and + (i32.eq + (i32.and + (tee_local $l3 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (get_local $l2) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4075)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l2) + (i32.const 4095)) + (i32.const 4092))) + (then + (i32.store offset=8388608 align=1 + (i32.xor + (i32.and + (get_local $l3) + (i32.const -4096)) + (get_local $l2)) + (get_local $l0))) + (else + (call $e.safe_write32_slow + (get_local $l2) + (get_local $l0)))) + (i32.store + (i32.const 20) + (get_local $l1)) (i32.store (i32.const 560) (i32.add From fb9a6e714a1f0768f7028e20549be24187d3375c Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Fri, 17 Aug 2018 21:39:58 +0530 Subject: [PATCH 1166/2137] remove unused codegen functions (register related) --- src/rust/codegen.rs | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 287d3c6c..4c780f6a 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -156,28 +156,6 @@ pub fn gen_set_reg32_r(ctx: &mut JitContext, dest: u32, src: u32) { builder.instruction_body.store_aligned_i32(); } -pub fn gen_set_reg16_fn0(ctx: &mut JitContext, name: &str, reg: u32) { - // generates: reg16[reg] = fn() - let builder = &mut ctx.builder; - let fn_idx = builder.get_fn_idx(name, module_init::FN0_RET_TYPE_INDEX); - builder - .instruction_body - .push_i32(global_pointers::get_reg16_offset(reg) as i32); - builder.instruction_body.call_fn(fn_idx); - builder.instruction_body.store_aligned_u16(); -} - -pub fn gen_set_reg32s_fn0(ctx: &mut JitContext, name: &str, reg: u32) { - // generates: reg32s[reg] = fn() - let builder = &mut ctx.builder; - let fn_idx = builder.get_fn_idx(name, module_init::FN0_RET_TYPE_INDEX); - builder - .instruction_body - .push_i32(global_pointers::get_reg32_offset(reg) as i32); - builder.instruction_body.call_fn(fn_idx); - builder.instruction_body.store_aligned_i32(); -} - pub fn gen_safe_read16(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::WORD) } pub fn gen_safe_read32(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::DWORD) } @@ -364,22 +342,6 @@ fn gen_safe_write( builder.instruction_body.block_end(); } -pub fn gen_fn1_reg16(ctx: &mut JitContext, name: &str, r: u32) { - let fn_idx = ctx.builder.get_fn_idx(name, module_init::FN1_TYPE_INDEX); - ctx.builder - .instruction_body - .load_aligned_u16(global_pointers::get_reg16_offset(r)); - ctx.builder.instruction_body.call_fn(fn_idx) -} - -pub fn gen_fn1_reg32(ctx: &mut JitContext, name: &str, r: u32) { - let fn_idx = ctx.builder.get_fn_idx(name, module_init::FN1_TYPE_INDEX); - ctx.builder - .instruction_body - .load_aligned_i32(global_pointers::get_reg32_offset(r)); - ctx.builder.instruction_body.call_fn(fn_idx) -} - pub fn gen_clear_prefixes(ctx: &mut JitContext) { let instruction_body = &mut ctx.builder.instruction_body; instruction_body.push_i32(global_pointers::PREFIXES as i32); // load address of prefixes From 2f5b1311c6bb95e20d657efded0f063890a9cf26 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Fri, 17 Aug 2018 22:27:48 +0530 Subject: [PATCH 1167/2137] re-add gen_safe_read_write --- src/rust/codegen.rs | 117 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 4c780f6a..d34f7c4a 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -748,3 +748,120 @@ pub fn gen_push32_ss32(ctx: &mut JitContext, imm: ImmVal) { ctx.builder.instruction_body.store_aligned_i32(); ctx.builder.free_local(new_esp_local); } + +fn gen_safe_read_write( + ctx: &mut JitContext, + bits: BitSize, + address_local: &WasmLocal, + fn_idx: u16, +) { + let builder = &mut ctx.builder; + + builder.instruction_body.get_local(address_local); + + // Pseudo: base_on_stack = (uint32_t)address >> 12; + builder.instruction_body.push_i32(12); + builder.instruction_body.shr_u32(); + + // scale index + builder.instruction_body.push_i32(2); + builder.instruction_body.shl_i32(); + + // Pseudo: entry = tlb_data[base_on_stack]; + builder + .instruction_body + .load_aligned_i32_from_stack(global_pointers::TLB_DATA); + let entry_local = builder.tee_new_local(); + + // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && + // (address & 0xFFF) <= (0x1000 - (bitsize / 8)); + builder.instruction_body.push_i32( + (0xFFF & !TLB_READONLY & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) + as i32, + ); + builder.instruction_body.and_i32(); + + builder.instruction_body.push_i32(TLB_VALID as i32); + builder.instruction_body.eq_i32(); + + builder.instruction_body.get_local(&address_local); + builder.instruction_body.push_i32(0xFFF); + builder.instruction_body.and_i32(); + builder + .instruction_body + .push_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 }); + builder.instruction_body.le_i32(); + + builder.instruction_body.and_i32(); + + // Pseudo: + // if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]); + builder.instruction_body.if_i32(); + builder.instruction_body.get_local(&entry_local); + builder.instruction_body.push_i32(!0xFFF); + builder.instruction_body.and_i32(); + builder.instruction_body.get_local(&address_local); + builder.instruction_body.xor_i32(); + + let phys_addr_local = builder.tee_new_local(); + + match bits { + BitSize::WORD => { + builder + .instruction_body + .load_unaligned_u16_from_stack(global_pointers::MEMORY); + }, + BitSize::DWORD => { + builder + .instruction_body + .load_unaligned_i32_from_stack(global_pointers::MEMORY); + }, + } + + builder.free_local(entry_local); + + builder.instruction_body.call_fn(fn_idx); + + // now store the value on stack to phys_addr + builder.instruction_body.get_local(&phys_addr_local); + match bits { + BitSize::WORD => { + builder + .instruction_body + .store_unaligned_u16(global_pointers::MEMORY); + }, + BitSize::DWORD => { + builder + .instruction_body + .store_unaligned_i32(global_pointers::MEMORY); + }, + }; + builder.free_local(phys_addr_local); + + // Pseudo: + // else { safe_readXX_slow(address); fn(); safe_writeXX_slow(); } + builder.instruction_body.else_(); + builder.instruction_body.get_local(&address_local); + match bits { + BitSize::WORD => { + gen_call_fn1_ret(builder, "safe_read16_slow"); + builder.instruction_body.call_fn(fn_idx); + let new_val_local = builder.set_new_local(); + builder.instruction_body.get_local(&address_local); + builder.instruction_body.get_local(&new_val_local); + gen_call_fn2(builder, "safe_write16_slow"); + builder.free_local(new_val_local); + }, + BitSize::DWORD => { + gen_call_fn1_ret(builder, "safe_read32s_slow"); + builder.instruction_body.call_fn(fn_idx); + let new_val_local = builder.set_new_local(); + builder.instruction_body.get_local(&address_local); + builder.instruction_body.get_local(&new_val_local); + gen_call_fn2(builder, "safe_write32_slow"); + builder.free_local(new_val_local); + }, + } + + builder.instruction_body.block_end(); +} From b6aa8efc37d867185609d0bab8183cec26a688f9 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sat, 18 Aug 2018 11:10:31 +0530 Subject: [PATCH 1168/2137] merge push16_ss* and push32_ss* functions --- src/rust/codegen.rs | 159 +++++++++++------------------------ src/rust/jit_instructions.rs | 55 ++---------- 2 files changed, 57 insertions(+), 157 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index d34f7c4a..b806d108 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -571,7 +571,16 @@ pub fn gen_task_switch_test_mmx(ctx: &mut JitContext) { ctx.builder.instruction_body.block_end(); } -pub fn gen_push16_ss16(ctx: &mut JitContext, imm: ImmVal) { +pub fn gen_push16(ctx: &mut JitContext, imm: ImmVal) { + if ctx.cpu.ssize_32() { + gen_push16_ss(ctx, imm, BitSize::DWORD) + } + else { + gen_push16_ss(ctx, imm, BitSize::WORD) + } +} + +fn gen_push16_ss(ctx: &mut JitContext, imm: ImmVal, bits: BitSize) { match imm { ImmVal::REG(r) => { ctx.builder @@ -588,57 +597,19 @@ pub fn gen_push16_ss16(ctx: &mut JitContext, imm: ImmVal) { }; let value_local = ctx.builder.set_new_local(); - ctx.builder - .instruction_body - .load_aligned_i32(global_pointers::get_reg16_offset(regs::SP)); - ctx.builder.instruction_body.push_i32(2); - ctx.builder.instruction_body.sub_i32(); - let reg16_updated_local = ctx.builder.tee_new_local(); - ctx.builder.instruction_body.push_i32(0xFFFF); - ctx.builder.instruction_body.and_i32(); - - if !ctx.cpu.has_flat_segmentation() { - ctx.builder - .instruction_body - .load_aligned_i32(global_pointers::get_seg_offset(regs::SS)); - ctx.builder.instruction_body.add_i32(); - } - - let sp_local = ctx.builder.set_new_local(); - gen_safe_write16(ctx, &sp_local, &value_local); - ctx.builder.free_local(sp_local); - ctx.builder.free_local(value_local); - ctx.builder - .instruction_body - .push_i32(global_pointers::get_reg16_offset(regs::SP) as i32); - ctx.builder.instruction_body.get_local(®16_updated_local); - ctx.builder.instruction_body.store_aligned_u16(); - ctx.builder.free_local(reg16_updated_local); -} - -pub fn gen_push16_ss32(ctx: &mut JitContext, imm: ImmVal) { - match imm { - ImmVal::REG(r) => { - ctx.builder - .instruction_body - .load_aligned_u16(global_pointers::get_reg16_offset(r)); - }, - ImmVal::CONST(imm) => { - ctx.builder.instruction_body.push_i32(imm as i32); - }, - ImmVal::MEM => { - // NOTE: It's important that this match stays atop so gen_safe_read16 gets called early enough - gen_safe_read16(ctx); - }, + let sp_reg = match bits { + BitSize::WORD => global_pointers::get_reg16_offset(regs::SP), + BitSize::DWORD => global_pointers::get_reg32_offset(regs::ESP), }; - let value_local = ctx.builder.set_new_local(); - ctx.builder - .instruction_body - .load_aligned_i32(global_pointers::get_reg32_offset(regs::ESP)); + ctx.builder.instruction_body.load_aligned_i32(sp_reg); ctx.builder.instruction_body.push_i32(2); ctx.builder.instruction_body.sub_i32(); - let reg32_updated_local = ctx.builder.tee_new_local(); + let reg_updated_local = ctx.builder.tee_new_local(); + if bits == BitSize::WORD { + ctx.builder.instruction_body.push_i32(0xFFFF); + ctx.builder.instruction_body.and_i32(); + } if !ctx.cpu.has_flat_segmentation() { ctx.builder @@ -651,15 +622,25 @@ pub fn gen_push16_ss32(ctx: &mut JitContext, imm: ImmVal) { gen_safe_write16(ctx, &sp_local, &value_local); ctx.builder.free_local(sp_local); ctx.builder.free_local(value_local); - ctx.builder - .instruction_body - .push_i32(global_pointers::get_reg32_offset(regs::ESP) as i32); - ctx.builder.instruction_body.get_local(®32_updated_local); - ctx.builder.instruction_body.store_aligned_i32(); - ctx.builder.free_local(reg32_updated_local); + ctx.builder.instruction_body.push_i32(sp_reg as i32); + ctx.builder.instruction_body.get_local(®_updated_local); + match bits { + BitSize::WORD => ctx.builder.instruction_body.store_aligned_u16(), + BitSize::DWORD => ctx.builder.instruction_body.store_aligned_i32(), + }; + ctx.builder.free_local(reg_updated_local); } -pub fn gen_push32_ss16(ctx: &mut JitContext, imm: ImmVal) { +pub fn gen_push32(ctx: &mut JitContext, imm: ImmVal) { + if ctx.cpu.ssize_32() { + gen_push32_ss(ctx, imm, BitSize::DWORD) + } + else { + gen_push32_ss(ctx, imm, BitSize::WORD) + } +} + +fn gen_push32_ss(ctx: &mut JitContext, imm: ImmVal, bits: BitSize) { match imm { ImmVal::REG(r) => { ctx.builder @@ -675,13 +656,18 @@ pub fn gen_push32_ss16(ctx: &mut JitContext, imm: ImmVal) { }; let value_local = ctx.builder.set_new_local(); - ctx.builder - .instruction_body - .load_aligned_u16(global_pointers::get_reg16_offset(regs::SP)); + let sp_reg = match bits { + BitSize::WORD => global_pointers::get_reg16_offset(regs::SP), + BitSize::DWORD => global_pointers::get_reg32_offset(regs::ESP), + }; + + ctx.builder.instruction_body.load_aligned_i32(sp_reg); ctx.builder.instruction_body.push_i32(4); ctx.builder.instruction_body.sub_i32(); - ctx.builder.instruction_body.push_i32(0xFFFF); - ctx.builder.instruction_body.and_i32(); + if bits == BitSize::WORD { + ctx.builder.instruction_body.push_i32(0xFFFF); + ctx.builder.instruction_body.and_i32(); + } let new_sp_local = ctx.builder.tee_new_local(); if !ctx.cpu.has_flat_segmentation() { @@ -697,56 +683,13 @@ pub fn gen_push32_ss16(ctx: &mut JitContext, imm: ImmVal) { ctx.builder.free_local(value_local); ctx.builder.free_local(sp_local); - ctx.builder - .instruction_body - .push_i32(global_pointers::get_reg16_offset(regs::SP) as i32); + ctx.builder.instruction_body.push_i32(sp_reg as i32); ctx.builder.instruction_body.get_local(&new_sp_local); - ctx.builder.instruction_body.store_aligned_u16(); - ctx.builder.free_local(new_sp_local); -} - -pub fn gen_push32_ss32(ctx: &mut JitContext, imm: ImmVal) { - match imm { - ImmVal::REG(r) => { - ctx.builder - .instruction_body - .load_aligned_i32(global_pointers::get_reg32_offset(r)); - }, - ImmVal::CONST(imm) => { - ctx.builder.instruction_body.push_i32(imm as i32); - }, - ImmVal::MEM => { - gen_safe_read32(ctx); - }, + match bits { + BitSize::WORD => ctx.builder.instruction_body.store_aligned_u16(), + BitSize::DWORD => ctx.builder.instruction_body.store_aligned_i32(), }; - let value_local = ctx.builder.set_new_local(); - - ctx.builder - .instruction_body - .load_aligned_i32(global_pointers::get_reg32_offset(regs::ESP)); - ctx.builder.instruction_body.push_i32(4); - ctx.builder.instruction_body.sub_i32(); - let new_esp_local = ctx.builder.tee_new_local(); - - if !ctx.cpu.has_flat_segmentation() { - ctx.builder - .instruction_body - .load_aligned_i32(global_pointers::get_seg_offset(regs::SS)); - ctx.builder.instruction_body.add_i32(); - } - - let sp_local = ctx.builder.set_new_local(); - - gen_safe_write32(ctx, &sp_local, &value_local); - ctx.builder.free_local(value_local); - ctx.builder.free_local(sp_local); - - ctx.builder - .instruction_body - .push_i32(global_pointers::get_reg32_offset(regs::ESP) as i32); - ctx.builder.instruction_body.get_local(&new_esp_local); - ctx.builder.instruction_body.store_aligned_i32(); - ctx.builder.free_local(new_esp_local); + ctx.builder.free_local(new_sp_local); } fn gen_safe_read_write( diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 4a8340d3..7c64d89b 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -96,60 +96,17 @@ pub fn instr_F3_jit(ctx: &mut JitContext, instr_flags: &mut u32) { jit_handle_prefix(ctx, instr_flags) } -fn push16_reg_jit(ctx: &mut JitContext, r: u32) { - if ctx.cpu.ssize_32() { - codegen::gen_push16_ss32(ctx, ImmVal::REG(r)); - } - else { - codegen::gen_push16_ss16(ctx, ImmVal::REG(r)); - } -} - -fn push32_reg_jit(ctx: &mut JitContext, r: u32) { - if ctx.cpu.ssize_32() { - codegen::gen_push32_ss32(ctx, ImmVal::REG(r)); - } - else { - codegen::gen_push32_ss16(ctx, ImmVal::REG(r)); - } -} - -fn push16_imm_jit(ctx: &mut JitContext, imm: u32) { - if ctx.cpu.ssize_32() { - codegen::gen_push16_ss32(ctx, ImmVal::CONST(imm)); - } - else { - codegen::gen_push16_ss16(ctx, ImmVal::CONST(imm)); - } -} - -fn push32_imm_jit(ctx: &mut JitContext, imm: u32) { - if ctx.cpu.ssize_32() { - codegen::gen_push32_ss32(ctx, ImmVal::CONST(imm)); - } - else { - codegen::gen_push32_ss16(ctx, ImmVal::CONST(imm)); - } -} - +fn push16_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_push16(ctx, ImmVal::REG(r)); } +fn push32_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_push32(ctx, ImmVal::REG(r)); } +fn push16_imm_jit(ctx: &mut JitContext, imm: u32) { codegen::gen_push16(ctx, ImmVal::CONST(imm)); } +fn push32_imm_jit(ctx: &mut JitContext, imm: u32) { codegen::gen_push32(ctx, ImmVal::CONST(imm)); } fn push16_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); - if ctx.cpu.ssize_32() { - codegen::gen_push16_ss32(ctx, ImmVal::MEM); - } - else { - codegen::gen_push16_ss16(ctx, ImmVal::MEM); - } + codegen::gen_push16(ctx, ImmVal::MEM); } - fn push32_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); - if ctx.cpu.ssize_32() { - codegen::gen_push32_ss32(ctx, ImmVal::MEM); - } - else { - codegen::gen_push32_ss16(ctx, ImmVal::MEM); - } + codegen::gen_push32(ctx, ImmVal::MEM); } fn pop16_reg_jit(ctx: &mut JitContext, reg: u32) { From 4d7f87c5154b81357f9129a0b6618155f94ca4fa Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sat, 18 Aug 2018 11:20:28 +0530 Subject: [PATCH 1169/2137] avoid local in gen_safe_read_write --- src/rust/codegen.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index b806d108..2ec8d04d 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -784,25 +784,18 @@ fn gen_safe_read_write( // Pseudo: // else { safe_readXX_slow(address); fn(); safe_writeXX_slow(); } builder.instruction_body.else_(); - builder.instruction_body.get_local(&address_local); + builder.instruction_body.get_local(&address_local); // for writeXX's first arg + builder.instruction_body.get_local(&address_local); // for readXX's first arg match bits { BitSize::WORD => { gen_call_fn1_ret(builder, "safe_read16_slow"); builder.instruction_body.call_fn(fn_idx); - let new_val_local = builder.set_new_local(); - builder.instruction_body.get_local(&address_local); - builder.instruction_body.get_local(&new_val_local); gen_call_fn2(builder, "safe_write16_slow"); - builder.free_local(new_val_local); }, BitSize::DWORD => { gen_call_fn1_ret(builder, "safe_read32s_slow"); builder.instruction_body.call_fn(fn_idx); - let new_val_local = builder.set_new_local(); - builder.instruction_body.get_local(&address_local); - builder.instruction_body.get_local(&new_val_local); gen_call_fn2(builder, "safe_write32_slow"); - builder.free_local(new_val_local); }, } From bfc04b80fbbf507aa703ca888a4286d6bbd946c3 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Sat, 18 Aug 2018 13:03:14 +0530 Subject: [PATCH 1170/2137] jit E8 --- src/rust/codegen.rs | 9 +++++ src/rust/cpu.rs | 1 + src/rust/jit_instructions.rs | 16 +++++++- tests/expect/tests/call.wast | 78 ++++++++++++++++++++++++++++++------ 4 files changed, 89 insertions(+), 15 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 2ec8d04d..66328c7f 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -594,6 +594,7 @@ fn gen_push16_ss(ctx: &mut JitContext, imm: ImmVal, bits: BitSize) { // NOTE: It's important that this match stays atop so gen_safe_read16 gets called early enough gen_safe_read16(ctx); }, + ImmVal::STACK => { /* nothing to do */ }, }; let value_local = ctx.builder.set_new_local(); @@ -653,6 +654,7 @@ fn gen_push32_ss(ctx: &mut JitContext, imm: ImmVal, bits: BitSize) { ImmVal::MEM => { gen_safe_read32(ctx); }, + ImmVal::STACK => { /* nothing to do */ }, }; let value_local = ctx.builder.set_new_local(); @@ -692,6 +694,13 @@ fn gen_push32_ss(ctx: &mut JitContext, imm: ImmVal, bits: BitSize) { ctx.builder.free_local(new_sp_local); } +pub fn gen_get_real_eip(ctx: &mut JitContext) { + let instruction_body = &mut ctx.builder.instruction_body; + instruction_body.load_aligned_i32(global_pointers::INSTRUCTION_POINTER); + instruction_body.load_aligned_i32(global_pointers::get_seg_offset(regs::CS)); + instruction_body.sub_i32(); +} + fn gen_safe_read_write( ctx: &mut JitContext, bits: BitSize, diff --git a/src/rust/cpu.rs b/src/rust/cpu.rs index cf616cb5..b6bffaa5 100644 --- a/src/rust/cpu.rs +++ b/src/rust/cpu.rs @@ -32,6 +32,7 @@ pub enum ImmVal { REG(u32), CONST(u32), MEM, + STACK, } pub fn read8(addr: u32) -> u8 { unsafe { unsafe_cpu::read8(addr) } } diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 7c64d89b..fdab55f7 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -288,10 +288,22 @@ pub fn instr32_8F_0_reg_jit(ctx: &mut JitContext, r: u32) { } pub fn instr16_E8_jit(ctx: &mut JitContext, imm: u32) { - codegen::gen_fn1_const(ctx, "instr16_E8", imm); + codegen::gen_get_real_eip(ctx); + codegen::gen_push16(ctx, ImmVal::STACK); + codegen::gen_jmp_rel16(ctx, imm as u16); } pub fn instr32_E8_jit(ctx: &mut JitContext, imm: u32) { - codegen::gen_fn1_const(ctx, "instr32_E8", imm); + codegen::gen_get_real_eip(ctx); + codegen::gen_push32(ctx, ImmVal::STACK); + ctx.builder + .instruction_body + .push_i32(global_pointers::INSTRUCTION_POINTER as i32); + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::INSTRUCTION_POINTER); + ctx.builder.instruction_body.push_i32(imm as i32); + ctx.builder.instruction_body.add_i32(); + ctx.builder.instruction_body.store_aligned_i32(); } pub fn instr16_E9_jit(ctx: &mut JitContext, imm: u32) { codegen::gen_jmp_rel16(ctx, imm as u16); } diff --git a/tests/expect/tests/call.wast b/tests/expect/tests/call.wast index ca3f0d95..e6da9dcc 100644 --- a/tests/expect/tests/call.wast +++ b/tests/expect/tests/call.wast @@ -7,13 +7,13 @@ (type $t5 (func (param i32) (result i32))) (type $t6 (func (param i32 i32) (result i32))) (import "e" "get_seg" (func $e.get_seg (type $t5))) - (import "e" "instr32_E8" (func $e.instr32_E8 (type $t1))) + (import "e" "safe_write32_slow" (func $e.safe_write32_slow (type $t2))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "instr32_40" (func $e.instr32_40 (type $t0))) (import "e" "safe_read32s_slow" (func $e.safe_read32s_slow (type $t5))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (set_local $p0 (get_local $p0)) (loop $L0 @@ -33,8 +33,60 @@ (i32.load (i32.const 556)) (i32.const 5))) - (call $e.instr32_E8 - (i32.const 1)) + (set_local $l0 + (i32.sub + (i32.load + (i32.const 556)) + (i32.load + (i32.const 740)))) + (set_local $l2 + (i32.add + (tee_local $l1 + (i32.sub + (i32.load + (i32.const 20)) + (i32.const 4))) + (i32.load + (i32.const 744)))) + (if $I5 + (i32.and + (i32.eq + (i32.and + (tee_local $l3 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (get_local $l2) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4075)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l2) + (i32.const 4095)) + (i32.const 4092))) + (then + (i32.store offset=8388608 align=1 + (i32.xor + (i32.and + (get_local $l3) + (i32.const -4096)) + (get_local $l2)) + (get_local $l0))) + (else + (call $e.safe_write32_slow + (get_local $l2) + (get_local $l0)))) + (i32.store + (i32.const 20) + (get_local $l1)) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 1))) (i32.store (i32.const 664) (i32.add @@ -78,17 +130,17 @@ (i32.const 556) (i32.load (i32.const 740)) - (if $I5 (result i32) + (if $I6 (result i32) (i32.and (i32.eq (i32.and - (tee_local $l2 + (tee_local $l0 (i32.load offset=4194304 (i32.shl (i32.shr_u - (tee_local $l1 + (tee_local $l2 (i32.add - (tee_local $l0 + (tee_local $l1 (i32.load (i32.const 20))) (i32.load @@ -99,23 +151,23 @@ (i32.const 1)) (i32.le_s (i32.and - (get_local $l1) + (get_local $l2) (i32.const 4095)) (i32.const 4092))) (then (i32.load offset=8388608 align=1 (i32.xor (i32.and - (get_local $l2) + (get_local $l0) (i32.const -4096)) - (get_local $l1)))) + (get_local $l2)))) (else (call $e.safe_read32s_slow - (get_local $l1)))) + (get_local $l2)))) (i32.store (i32.const 20) (i32.add - (get_local $l0) + (get_local $l1) (i32.const 4))) (i32.add) (i32.store) From 26fc44a61fe35cf32aafb2e59a6906f54fe66f88 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Mon, 20 Aug 2018 22:48:17 +0530 Subject: [PATCH 1171/2137] simplify push16,32 --- src/rust/codegen.rs | 87 +++++++++--------------------------- src/rust/cpu.rs | 8 ---- src/rust/jit_instructions.rs | 51 +++++++++++++++++---- tests/expect/tests/call.wast | 16 +++---- 4 files changed, 71 insertions(+), 91 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 66328c7f..4247c908 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -1,4 +1,4 @@ -use cpu::{BitSize, ImmVal}; +use cpu::BitSize; use global_pointers; use jit::JitContext; use modrm; @@ -571,43 +571,19 @@ pub fn gen_task_switch_test_mmx(ctx: &mut JitContext) { ctx.builder.instruction_body.block_end(); } -pub fn gen_push16(ctx: &mut JitContext, imm: ImmVal) { - if ctx.cpu.ssize_32() { - gen_push16_ss(ctx, imm, BitSize::DWORD) +pub fn gen_push16(ctx: &mut JitContext, value_local: &WasmLocal) { + let sp_reg = if ctx.cpu.ssize_32() { + global_pointers::get_reg32_offset(regs::ESP) } else { - gen_push16_ss(ctx, imm, BitSize::WORD) - } -} - -fn gen_push16_ss(ctx: &mut JitContext, imm: ImmVal, bits: BitSize) { - match imm { - ImmVal::REG(r) => { - ctx.builder - .instruction_body - .load_aligned_u16(global_pointers::get_reg16_offset(r)); - }, - ImmVal::CONST(imm) => { - ctx.builder.instruction_body.push_i32(imm as i32); - }, - ImmVal::MEM => { - // NOTE: It's important that this match stays atop so gen_safe_read16 gets called early enough - gen_safe_read16(ctx); - }, - ImmVal::STACK => { /* nothing to do */ }, - }; - let value_local = ctx.builder.set_new_local(); - - let sp_reg = match bits { - BitSize::WORD => global_pointers::get_reg16_offset(regs::SP), - BitSize::DWORD => global_pointers::get_reg32_offset(regs::ESP), + global_pointers::get_reg16_offset(regs::SP) }; ctx.builder.instruction_body.load_aligned_i32(sp_reg); ctx.builder.instruction_body.push_i32(2); ctx.builder.instruction_body.sub_i32(); let reg_updated_local = ctx.builder.tee_new_local(); - if bits == BitSize::WORD { + if !ctx.cpu.ssize_32() { ctx.builder.instruction_body.push_i32(0xFFFF); ctx.builder.instruction_body.and_i32(); } @@ -622,51 +598,29 @@ fn gen_push16_ss(ctx: &mut JitContext, imm: ImmVal, bits: BitSize) { let sp_local = ctx.builder.set_new_local(); gen_safe_write16(ctx, &sp_local, &value_local); ctx.builder.free_local(sp_local); - ctx.builder.free_local(value_local); ctx.builder.instruction_body.push_i32(sp_reg as i32); ctx.builder.instruction_body.get_local(®_updated_local); - match bits { - BitSize::WORD => ctx.builder.instruction_body.store_aligned_u16(), - BitSize::DWORD => ctx.builder.instruction_body.store_aligned_i32(), + if ctx.cpu.ssize_32() { + ctx.builder.instruction_body.store_aligned_i32() + } + else { + ctx.builder.instruction_body.store_aligned_u16() }; ctx.builder.free_local(reg_updated_local); } -pub fn gen_push32(ctx: &mut JitContext, imm: ImmVal) { - if ctx.cpu.ssize_32() { - gen_push32_ss(ctx, imm, BitSize::DWORD) +pub fn gen_push32(ctx: &mut JitContext, value_local: &WasmLocal) { + let sp_reg = if ctx.cpu.ssize_32() { + global_pointers::get_reg32_offset(regs::ESP) } else { - gen_push32_ss(ctx, imm, BitSize::WORD) - } -} - -fn gen_push32_ss(ctx: &mut JitContext, imm: ImmVal, bits: BitSize) { - match imm { - ImmVal::REG(r) => { - ctx.builder - .instruction_body - .load_aligned_i32(global_pointers::get_reg32_offset(r)); - }, - ImmVal::CONST(imm) => { - ctx.builder.instruction_body.push_i32(imm as i32); - }, - ImmVal::MEM => { - gen_safe_read32(ctx); - }, - ImmVal::STACK => { /* nothing to do */ }, - }; - let value_local = ctx.builder.set_new_local(); - - let sp_reg = match bits { - BitSize::WORD => global_pointers::get_reg16_offset(regs::SP), - BitSize::DWORD => global_pointers::get_reg32_offset(regs::ESP), + global_pointers::get_reg16_offset(regs::SP) }; ctx.builder.instruction_body.load_aligned_i32(sp_reg); ctx.builder.instruction_body.push_i32(4); ctx.builder.instruction_body.sub_i32(); - if bits == BitSize::WORD { + if !ctx.cpu.ssize_32() { ctx.builder.instruction_body.push_i32(0xFFFF); ctx.builder.instruction_body.and_i32(); } @@ -682,14 +636,15 @@ fn gen_push32_ss(ctx: &mut JitContext, imm: ImmVal, bits: BitSize) { let sp_local = ctx.builder.set_new_local(); gen_safe_write32(ctx, &sp_local, &value_local); - ctx.builder.free_local(value_local); ctx.builder.free_local(sp_local); ctx.builder.instruction_body.push_i32(sp_reg as i32); ctx.builder.instruction_body.get_local(&new_sp_local); - match bits { - BitSize::WORD => ctx.builder.instruction_body.store_aligned_u16(), - BitSize::DWORD => ctx.builder.instruction_body.store_aligned_i32(), + if ctx.cpu.ssize_32() { + ctx.builder.instruction_body.store_aligned_i32() + } + else { + ctx.builder.instruction_body.store_aligned_u16() }; ctx.builder.free_local(new_sp_local); } diff --git a/src/rust/cpu.rs b/src/rust/cpu.rs index b6bffaa5..ff45fdd9 100644 --- a/src/rust/cpu.rs +++ b/src/rust/cpu.rs @@ -27,14 +27,6 @@ pub enum BitSize { DWORD, } -#[derive(Copy, Clone, Eq, PartialEq)] -pub enum ImmVal { - REG(u32), - CONST(u32), - MEM, - STACK, -} - pub fn read8(addr: u32) -> u8 { unsafe { unsafe_cpu::read8(addr) } } pub fn read16(addr: u32) -> u16 { unsafe { unsafe_cpu::read16(addr) } } pub fn read32(addr: u32) -> u32 { unsafe { unsafe_cpu::read32(addr) } } diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index fdab55f7..224f229e 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1,7 +1,6 @@ #![allow(non_snake_case)] use codegen; -use cpu::ImmVal; use cpu_context::CpuContext; use global_pointers; use jit::JitContext; @@ -96,17 +95,47 @@ pub fn instr_F3_jit(ctx: &mut JitContext, instr_flags: &mut u32) { jit_handle_prefix(ctx, instr_flags) } -fn push16_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_push16(ctx, ImmVal::REG(r)); } -fn push32_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_push32(ctx, ImmVal::REG(r)); } -fn push16_imm_jit(ctx: &mut JitContext, imm: u32) { codegen::gen_push16(ctx, ImmVal::CONST(imm)); } -fn push32_imm_jit(ctx: &mut JitContext, imm: u32) { codegen::gen_push32(ctx, ImmVal::CONST(imm)); } +fn push16_reg_jit(ctx: &mut JitContext, r: u32) { + ctx.builder + .instruction_body + .load_aligned_u16(global_pointers::get_reg16_offset(r)); + let value_local = ctx.builder.set_new_local(); + codegen::gen_push16(ctx, &value_local); + ctx.builder.free_local(value_local); +} +fn push32_reg_jit(ctx: &mut JitContext, r: u32) { + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_reg32_offset(r)); + let value_local = ctx.builder.set_new_local(); + codegen::gen_push32(ctx, &value_local); + ctx.builder.free_local(value_local); +} +fn push16_imm_jit(ctx: &mut JitContext, imm: u32) { + ctx.builder.instruction_body.push_i32(imm as i32); + let value_local = ctx.builder.set_new_local(); + codegen::gen_push16(ctx, &value_local); + ctx.builder.free_local(value_local); +} +fn push32_imm_jit(ctx: &mut JitContext, imm: u32) { + ctx.builder.instruction_body.push_i32(imm as i32); + let value_local = ctx.builder.set_new_local(); + codegen::gen_push32(ctx, &value_local); + ctx.builder.free_local(value_local); +} fn push16_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_push16(ctx, ImmVal::MEM); + codegen::gen_safe_read16(ctx); + let value_local = ctx.builder.set_new_local(); + codegen::gen_push16(ctx, &value_local); + ctx.builder.free_local(value_local); } fn push32_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_push32(ctx, ImmVal::MEM); + codegen::gen_safe_read32(ctx); + let value_local = ctx.builder.set_new_local(); + codegen::gen_push32(ctx, &value_local); + ctx.builder.free_local(value_local); } fn pop16_reg_jit(ctx: &mut JitContext, reg: u32) { @@ -289,12 +318,16 @@ pub fn instr32_8F_0_reg_jit(ctx: &mut JitContext, r: u32) { pub fn instr16_E8_jit(ctx: &mut JitContext, imm: u32) { codegen::gen_get_real_eip(ctx); - codegen::gen_push16(ctx, ImmVal::STACK); + let value_local = ctx.builder.set_new_local(); + codegen::gen_push16(ctx, &value_local); + ctx.builder.free_local(value_local); codegen::gen_jmp_rel16(ctx, imm as u16); } pub fn instr32_E8_jit(ctx: &mut JitContext, imm: u32) { codegen::gen_get_real_eip(ctx); - codegen::gen_push32(ctx, ImmVal::STACK); + let value_local = ctx.builder.set_new_local(); + codegen::gen_push32(ctx, &value_local); + ctx.builder.free_local(value_local); ctx.builder .instruction_body .push_i32(global_pointers::INSTRUCTION_POINTER as i32); diff --git a/tests/expect/tests/call.wast b/tests/expect/tests/call.wast index e6da9dcc..303fa6a4 100644 --- a/tests/expect/tests/call.wast +++ b/tests/expect/tests/call.wast @@ -134,13 +134,13 @@ (i32.and (i32.eq (i32.and - (tee_local $l0 + (tee_local $l2 (i32.load offset=4194304 (i32.shl (i32.shr_u - (tee_local $l2 + (tee_local $l1 (i32.add - (tee_local $l1 + (tee_local $l0 (i32.load (i32.const 20))) (i32.load @@ -151,23 +151,23 @@ (i32.const 1)) (i32.le_s (i32.and - (get_local $l2) + (get_local $l1) (i32.const 4095)) (i32.const 4092))) (then (i32.load offset=8388608 align=1 (i32.xor (i32.and - (get_local $l0) + (get_local $l2) (i32.const -4096)) - (get_local $l2)))) + (get_local $l1)))) (else (call $e.safe_read32s_slow - (get_local $l2)))) + (get_local $l1)))) (i32.store (i32.const 20) (i32.add - (get_local $l1) + (get_local $l0) (i32.const 4))) (i32.add) (i32.store) From 6de0bb374b4cee520741a8fe9b683a86f2ebcda3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 2 Aug 2018 13:31:15 -0400 Subject: [PATCH 1172/2137] Preparation C code for c2rust conversion --- src/native/all.c | 0 src/native/arith.c | 1 - src/native/config.h | 26 +--- src/native/const.h | 235 ++++++++++++++++---------------- src/native/cpu.c | 253 ++++++++++++++++++++++++++++++----- src/native/cpu.h | 61 +++++---- src/native/fpu.c | 29 +++- src/native/fpu.h | 36 ++--- src/native/global_pointers.c | 96 +++++++++++++ src/native/global_pointers.h | 128 +++++++++--------- src/native/instructions.c | 16 +-- src/native/instructions.h | 84 ++++++------ src/native/instructions_0f.c | 176 +++++++++++++----------- src/native/instructions_0f.h | 10 +- src/native/log.h | 9 +- src/native/memory.c | 3 +- src/native/misc_instr.c | 1 - src/native/modrm.c | 56 ++++---- src/native/shared.c | 180 +++++++++++++------------ src/native/shared.h | 14 +- src/native/sse_instr.c | 11 +- src/native/string.c | 3 +- src/rust/lib.rs | 2 + 23 files changed, 887 insertions(+), 543 deletions(-) create mode 100644 src/native/all.c create mode 100644 src/native/global_pointers.c diff --git a/src/native/all.c b/src/native/all.c new file mode 100644 index 00000000..e69de29b diff --git a/src/native/arith.c b/src/native/arith.c index 86c0d7af..b7b29819 100644 --- a/src/native/arith.c +++ b/src/native/arith.c @@ -1,4 +1,3 @@ -#include #include #include #include diff --git a/src/native/config.h b/src/native/config.h index e6892c81..1a60db6b 100644 --- a/src/native/config.h +++ b/src/native/config.h @@ -1,32 +1,18 @@ #pragma once -#ifndef DEBUG -#define DEBUG true -#endif - /** * How many cycles the CPU does at a time before running hardware timers */ -#define LOOP_COUNTER 20011 +//#define LOOP_COUNTER 20011 -#define TSC_RATE (50 * 1000) +//#define TSC_RATE (50 * 1000) -#define CPU_LOG_VERBOSE false -#define ENABLE_ACPI false -#define USE_A20 false - -#define CHECK_TLB_INVARIANTS 0 - -#define ENABLE_JIT 1 - -#define CHECK_CPU_EXCEPTIONS 0 - -#define ENABLE_PROFILER 0 -#define ENABLE_PROFILER_OPSTATS 0 -#define ENABLE_PROFILER_SAFE_READ_WRITE 0 +#define ENABLE_PROFILER 1 +#define ENABLE_PROFILER_OPSTATS 1 +#define ENABLE_PROFILER_SAFE_READ_WRITE 1 // Note: needs to be enabled here and in config.js #define DUMP_UNCOMPILED_ASSEMBLY 0 -#define LOG_PAGE_FAULTS 0 +//#define LOG_PAGE_FAULTS 0 diff --git a/src/native/const.h b/src/native/const.h index b9e65a12..b3e3432d 100644 --- a/src/native/const.h +++ b/src/native/const.h @@ -1,151 +1,150 @@ #pragma once -#define FLAG_CARRY 1 -#define FLAG_PARITY 4 -#define FLAG_ADJUST 16 -#define FLAG_ZERO 64 -#define FLAG_SIGN 128 -#define FLAG_TRAP 256 -#define FLAG_INTERRUPT 512 -#define FLAG_DIRECTION 1024 -#define FLAG_OVERFLOW 2048 -#define FLAG_IOPL (1 << 12 | 1 << 13) -#define FLAG_NT (1 << 14) -#define FLAG_RF (1 << 16) -#define FLAG_VM (1 << 17) -#define FLAG_AC (1 << 18) -#define FLAG_VIF (1 << 19) -#define FLAG_VIP (1 << 20) -#define FLAG_ID (1 << 21) -#define FLAGS_DEFAULT (1 << 1) +#include -#define FLAGS_MASK ( \ - FLAG_CARRY | FLAG_PARITY | FLAG_ADJUST | FLAG_ZERO | FLAG_SIGN | FLAG_TRAP | FLAG_INTERRUPT | \ - FLAG_DIRECTION | FLAG_OVERFLOW | FLAG_IOPL | FLAG_NT | FLAG_RF | FLAG_VM | FLAG_AC | \ - FLAG_VIF | FLAG_VIP | FLAG_ID) +extern const int32_t FLAG_CARRY; +extern const int32_t FLAG_PARITY; +extern const int32_t FLAG_ADJUST; +extern const int32_t FLAG_ZERO; +extern const int32_t FLAG_SIGN; +extern const int32_t FLAG_TRAP; +extern const int32_t FLAG_INTERRUPT; +extern const int32_t FLAG_DIRECTION; +extern const int32_t FLAG_OVERFLOW; +extern const int32_t FLAG_IOPL; +extern const int32_t FLAG_NT; +extern const int32_t FLAG_RF; +extern const int32_t FLAG_VM; +extern const int32_t FLAG_AC; +extern const int32_t FLAG_VIF; +extern const int32_t FLAG_VIP; +extern const int32_t FLAG_ID; +extern const int32_t FLAGS_DEFAULT; -#define FLAGS_ALL (FLAG_CARRY | FLAG_PARITY | FLAG_ADJUST | FLAG_ZERO | FLAG_SIGN | FLAG_OVERFLOW) +extern const int32_t FLAGS_MASK; -#define OPSIZE_8 7 -#define OPSIZE_16 15 -#define OPSIZE_32 31 +extern const int32_t FLAGS_ALL; -#define EAX 0 -#define ECX 1 -#define EDX 2 -#define EBX 3 -#define ESP 4 -#define EBP 5 -#define ESI 6 -#define EDI 7 +extern const int32_t OPSIZE_8; +extern const int32_t OPSIZE_16; +extern const int32_t OPSIZE_32; -#define AX 0 -#define CX 2 -#define DX 4 -#define BX 6 -#define SP 8 -#define BP 10 -#define SI 12 -#define DI 14 +extern const int32_t EAX; +extern const int32_t ECX; +extern const int32_t EDX; +extern const int32_t EBX; +extern const int32_t ESP; +extern const int32_t EBP; +extern const int32_t ESI; +extern const int32_t EDI; -#define AL 0 -#define CL 4 -#define DL 8 -#define BL 12 -#define AH 1 -#define CH 5 -#define DH 9 -#define BH 13 +extern const int32_t AX; +extern const int32_t CX; +extern const int32_t DX; +extern const int32_t BX; +extern const int32_t SP; +extern const int32_t BP; +extern const int32_t SI; +extern const int32_t DI; -#define ES 0 -#define CS 1 -#define SS 2 -#define DS 3 -#define FS 4 -#define GS 5 +extern const int32_t AL; +extern const int32_t CL; +extern const int32_t DL; +extern const int32_t BL; +extern const int32_t AH; +extern const int32_t CH; +extern const int32_t DH; +extern const int32_t BH; -#define TR 6 -#define LDTR 7 +extern const int32_t ES; +extern const int32_t CS; +extern const int32_t SS; +extern const int32_t DS; +extern const int32_t FS; +extern const int32_t GS; + +extern const int32_t TR; +extern const int32_t LDTR; -#define PAGE_TABLE_PRESENT_MASK (1 << 0) -#define PAGE_TABLE_RW_MASK (1 << 1) -#define PAGE_TABLE_USER_MASK (1 << 2) -#define PAGE_TABLE_ACCESSED_MASK (1 << 5) -#define PAGE_TABLE_DIRTY_MASK (1 << 6) -#define PAGE_TABLE_PSE_MASK (1 << 7) -#define PAGE_TABLE_GLOBAL_MASK (1 << 8) +extern const int32_t PAGE_TABLE_PRESENT_MASK; +extern const int32_t PAGE_TABLE_RW_MASK; +extern const int32_t PAGE_TABLE_USER_MASK; +extern const int32_t PAGE_TABLE_ACCESSED_MASK; +extern const int32_t PAGE_TABLE_DIRTY_MASK; +extern const int32_t PAGE_TABLE_PSE_MASK; +extern const int32_t PAGE_TABLE_GLOBAL_MASK; -#define MMAP_BLOCK_BITS 17 -#define MMAP_BLOCK_SIZE = (1 << MMAP_BLOCK_BITS) +extern const int32_t MMAP_BLOCK_BITS; +extern const int32_t MMAP_BLOCK_SIZE; -#define CR0_PE 1 -#define CR0_MP (1 << 1) -#define CR0_EM (1 << 2) -#define CR0_TS (1 << 3) -#define CR0_ET (1 << 4) -#define CR0_WP (1 << 16) -#define CR0_NW (1 << 29) -#define CR0_CD (1 << 30) -#define CR0_PG (1 << 31) +extern const int32_t CR0_PE; +extern const int32_t CR0_MP; +extern const int32_t CR0_EM; +extern const int32_t CR0_TS; +extern const int32_t CR0_ET; +extern const int32_t CR0_WP; +extern const int32_t CR0_NW; +extern const int32_t CR0_CD; +extern const int32_t CR0_PG; -#define CR4_VME (1) -#define CR4_PVI (1 << 1) -#define CR4_TSD (1 << 2) -#define CR4_PSE (1 << 4) -#define CR4_DE (1 << 3) -#define CR4_PAE (1 << 5) -#define CR4_PGE (1 << 7) +extern const int32_t CR4_VME; +extern const int32_t CR4_PVI; +extern const int32_t CR4_TSD; +extern const int32_t CR4_PSE; +extern const int32_t CR4_DE; +extern const int32_t CR4_PAE; +extern const int32_t CR4_PGE; -#define IA32_SYSENTER_CS 0x174 -#define IA32_SYSENTER_ESP 0x175 -#define IA32_SYSENTER_EIP 0x176 +extern const int32_t IA32_SYSENTER_CS; +extern const int32_t IA32_SYSENTER_ESP; +extern const int32_t IA32_SYSENTER_EIP; -#define IA32_TIME_STAMP_COUNTER 0x10 -#define IA32_PLATFORM_ID 0x17 -#define IA32_APIC_BASE_MSR 0x1B -#define IA32_BIOS_SIGN_ID 0x8B -#define MSR_PLATFORM_INFO 0xCE -#define MSR_MISC_FEATURE_ENABLES 0x140 -#define IA32_MISC_ENABLE 0x1A0 -#define IA32_RTIT_CTL 0x570 -#define MSR_SMI_COUNT 0x34 -#define IA32_MCG_CAP 0x179 -#define IA32_KERNEL_GS_BASE 0xC0000101 -#define MSR_PKG_C2_RESIDENCY 0x60D +extern const int32_t IA32_TIME_STAMP_COUNTER; +extern const int32_t IA32_PLATFORM_ID; +extern const int32_t IA32_APIC_BASE_MSR; +extern const int32_t IA32_BIOS_SIGN_ID; +extern const int32_t MSR_PLATFORM_INFO; +extern const int32_t MSR_MISC_FEATURE_ENABLES; +extern const int32_t IA32_MISC_ENABLE; +extern const int32_t IA32_RTIT_CTL; +extern const int32_t MSR_SMI_COUNT; +extern const int32_t IA32_MCG_CAP; +extern const int32_t IA32_KERNEL_GS_BASE; +extern const int32_t MSR_PKG_C2_RESIDENCY; -#define IA32_APIC_BASE_BSP (1 << 8) -#define IA32_APIC_BASE_EXTD (1 << 10) -#define IA32_APIC_BASE_EN (1 << 11) +extern const int32_t IA32_APIC_BASE_BSP; +extern const int32_t IA32_APIC_BASE_EXTD; +extern const int32_t IA32_APIC_BASE_EN; // Note: Duplicated in apic.js -#define APIC_ADDRESS ((int32_t)0xFEE00000) +extern const int32_t APIC_ADDRESS; // Segment prefixes must not collide with reg_*s variables // _ZERO is a special zero offset segment -#define SEG_PREFIX_NONE (-1) -#define SEG_PREFIX_ZERO 7 +extern const int32_t SEG_PREFIX_NONE; +extern const int32_t SEG_PREFIX_ZERO; -#define PREFIX_MASK_REP 0b11000 -#define PREFIX_REPZ 0b01000 -#define PREFIX_REPNZ 0b10000 +extern const int32_t PREFIX_MASK_REP; +extern const int32_t PREFIX_REPZ; +extern const int32_t PREFIX_REPNZ; -#define PREFIX_MASK_SEGMENT 0b111 -#define PREFIX_MASK_OPSIZE 0b100000 -#define PREFIX_MASK_ADDRSIZE 0b1000000 +extern const int32_t PREFIX_MASK_SEGMENT; +extern const int32_t PREFIX_MASK_OPSIZE; +extern const int32_t PREFIX_MASK_ADDRSIZE; // aliases -#define PREFIX_F2 PREFIX_REPNZ -#define PREFIX_F3 PREFIX_REPZ -#define PREFIX_66 PREFIX_MASK_OPSIZE +extern const int32_t PREFIX_F2; +extern const int32_t PREFIX_F3; +extern const int32_t PREFIX_66; -#define LOG_CPU 0x000002 +extern const int32_t LOG_CPU; -#define A20_MASK (~(1 << 20)) -#define A20_MASK16 (~(1 << (20 - 1))) -#define A20_MASK32 (~(1 << (20 - 2))) +extern const int32_t A20_MASK; +extern const int32_t A20_MASK16; +extern const int32_t A20_MASK32; -#define MXCSR_MASK (0xFFFF & ~(1 << 6)) +extern const int32_t MXCSR_MASK; diff --git a/src/native/cpu.c b/src/native/cpu.c index cbd94000..28c81f07 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -17,16 +16,198 @@ #include "rust_imports.h" #include "shared.h" +const int32_t FLAG_CARRY = 1; +const int32_t FLAG_PARITY = 4; +const int32_t FLAG_ADJUST = 16; +const int32_t FLAG_ZERO = 64; +const int32_t FLAG_SIGN = 128; +const int32_t FLAG_TRAP = 256; +const int32_t FLAG_INTERRUPT = 512; +const int32_t FLAG_DIRECTION = 1024; +const int32_t FLAG_OVERFLOW = 2048; +const int32_t FLAG_IOPL = (1 << 12 | 1 << 13); +const int32_t FLAG_NT = (1 << 14); +const int32_t FLAG_RF = (1 << 16); +const int32_t FLAG_VM = (1 << 17); +const int32_t FLAG_AC = (1 << 18); +const int32_t FLAG_VIF = (1 << 19); +const int32_t FLAG_VIP = (1 << 20); +const int32_t FLAG_ID = (1 << 21); +const int32_t FLAGS_DEFAULT = (1 << 1); + +const int32_t FLAGS_MASK = ( + FLAG_CARRY | FLAG_PARITY | FLAG_ADJUST | FLAG_ZERO | FLAG_SIGN | FLAG_TRAP | FLAG_INTERRUPT | + FLAG_DIRECTION | FLAG_OVERFLOW | FLAG_IOPL | FLAG_NT | FLAG_RF | FLAG_VM | FLAG_AC | + FLAG_VIF | FLAG_VIP | FLAG_ID); + +const int32_t FLAGS_ALL = (FLAG_CARRY | FLAG_PARITY | FLAG_ADJUST | FLAG_ZERO | FLAG_SIGN | FLAG_OVERFLOW); + +const int32_t OPSIZE_8 = 7; +const int32_t OPSIZE_16 = 15; +const int32_t OPSIZE_32 = 31; + +const int32_t EAX = 0; +const int32_t ECX = 1; +const int32_t EDX = 2; +const int32_t EBX = 3; +const int32_t ESP = 4; +const int32_t EBP = 5; +const int32_t ESI = 6; +const int32_t EDI = 7; + +const int32_t AX = 0; +const int32_t CX = 2; +const int32_t DX = 4; +const int32_t BX = 6; +const int32_t SP = 8; +const int32_t BP = 10; +const int32_t SI = 12; +const int32_t DI = 14; + +const int32_t AL = 0; +const int32_t CL = 4; +const int32_t DL = 8; +const int32_t BL = 12; +const int32_t AH = 1; +const int32_t CH = 5; +const int32_t DH = 9; +const int32_t BH = 13; + +const int32_t ES = 0; +const int32_t CS = 1; +const int32_t SS = 2; +const int32_t DS = 3; +const int32_t FS = 4; +const int32_t GS = 5; + +const int32_t TR = 6; +const int32_t LDTR = 7; + + +const int32_t PAGE_TABLE_PRESENT_MASK = (1 << 0); +const int32_t PAGE_TABLE_RW_MASK = (1 << 1); +const int32_t PAGE_TABLE_USER_MASK = (1 << 2); +const int32_t PAGE_TABLE_ACCESSED_MASK = (1 << 5); +const int32_t PAGE_TABLE_DIRTY_MASK = (1 << 6); +const int32_t PAGE_TABLE_PSE_MASK = (1 << 7); +const int32_t PAGE_TABLE_GLOBAL_MASK = (1 << 8); + +const int32_t MMAP_BLOCK_BITS = 17; +const int32_t MMAP_BLOCK_SIZE = (1 << MMAP_BLOCK_BITS); + +const int32_t CR0_PE = 1; +const int32_t CR0_MP = (1 << 1); +const int32_t CR0_EM = (1 << 2); +const int32_t CR0_TS = (1 << 3); +const int32_t CR0_ET = (1 << 4); +const int32_t CR0_WP = (1 << 16); +const int32_t CR0_NW = (1 << 29); +const int32_t CR0_CD = (1 << 30); +const int32_t CR0_PG = (1 << 31); + +const int32_t CR4_VME = (1); +const int32_t CR4_PVI = (1 << 1); +const int32_t CR4_TSD = (1 << 2); +const int32_t CR4_PSE = (1 << 4); +const int32_t CR4_DE = (1 << 3); +const int32_t CR4_PAE = (1 << 5); +const int32_t CR4_PGE = (1 << 7); + + +const int32_t IA32_SYSENTER_CS = 0x174; +const int32_t IA32_SYSENTER_ESP = 0x175; +const int32_t IA32_SYSENTER_EIP = 0x176; + +const int32_t IA32_TIME_STAMP_COUNTER = 0x10; +const int32_t IA32_PLATFORM_ID = 0x17; +const int32_t IA32_APIC_BASE_MSR = 0x1B; +const int32_t IA32_BIOS_SIGN_ID = 0x8B; +const int32_t MSR_PLATFORM_INFO = 0xCE; +const int32_t MSR_MISC_FEATURE_ENABLES = 0x140; +const int32_t IA32_MISC_ENABLE = 0x1A0; +const int32_t IA32_RTIT_CTL = 0x570; +const int32_t MSR_SMI_COUNT = 0x34; +const int32_t IA32_MCG_CAP = 0x179; +const int32_t IA32_KERNEL_GS_BASE = 0xC0000101; +const int32_t MSR_PKG_C2_RESIDENCY = 0x60D; + +const int32_t IA32_APIC_BASE_BSP = (1 << 8); +const int32_t IA32_APIC_BASE_EXTD = (1 << 10); +const int32_t IA32_APIC_BASE_EN = (1 << 11); + + +// Note: Duplicated in apic.js +const int32_t APIC_ADDRESS = ((int32_t)0xFEE00000); + + +// Segment prefixes must not collide with reg_*s variables +// _ZERO is a special zero offset segment +const int32_t SEG_PREFIX_NONE = (-1); +const int32_t SEG_PREFIX_ZERO = 7; + +const int32_t PREFIX_MASK_REP = 0b11000; +const int32_t PREFIX_REPZ = 0b01000; +const int32_t PREFIX_REPNZ = 0b10000; + +const int32_t PREFIX_MASK_SEGMENT = 0b111; +const int32_t PREFIX_MASK_OPSIZE = 0b100000; +const int32_t PREFIX_MASK_ADDRSIZE = 0b1000000; + +// aliases +const int32_t PREFIX_F2 = PREFIX_REPNZ; +const int32_t PREFIX_F3 = PREFIX_REPZ; +const int32_t PREFIX_66 = PREFIX_MASK_OPSIZE; + +const int32_t LOG_CPU = 0x000002; + +const int32_t A20_MASK = (~(1 << 20)); +const int32_t A20_MASK16 = (~(1 << (20 - 1))); +const int32_t A20_MASK32 = (~(1 << (20 - 2))); + +const int32_t MXCSR_MASK = (0xFFFF & ~(1 << 6)); + +const int32_t CPU_EXCEPTION_DE = 0; // Divide Error +const int32_t CPU_EXCEPTION_DB = 1; // Debug Exception +const int32_t CPU_EXCEPTION_NMI = 2; // NMI Interrupt +const int32_t CPU_EXCEPTION_BP = 3; // Breakpoint +const int32_t CPU_EXCEPTION_OF = 4; // Overflow +const int32_t CPU_EXCEPTION_BR = 5; // BOUND Range Exceeded +const int32_t CPU_EXCEPTION_UD = 6; // Invalid Opcode +const int32_t CPU_EXCEPTION_NM = 7; // Device Not Available +const int32_t CPU_EXCEPTION_DF = 8; // Double Fault +const int32_t CPU_EXCEPTION_TS = 10; // Invalid TSS +const int32_t CPU_EXCEPTION_NP = 11; // Segment Not Present +const int32_t CPU_EXCEPTION_SS = 12; // Stack-Segment Fault +const int32_t CPU_EXCEPTION_GP = 13; // General Protection +const int32_t CPU_EXCEPTION_PF = 14; // Page Fault +const int32_t CPU_EXCEPTION_MF = 16; // x87 FPU Floating-Point Error +const int32_t CPU_EXCEPTION_AC = 17; // Alignment Check +const int32_t CPU_EXCEPTION_MC = 18; // Machine Check Abort +const int32_t CPU_EXCEPTION_XM = 19; // SIMD Floating-Point Exception +const int32_t CPU_EXCEPTION_VE = 20; // Virtualization Exception + +const int32_t LOOP_COUNTER = 20011; +const double_t TSC_RATE = (50 * 1000); + +const bool CHECK_TLB_INVARIANTS = false; + +const int32_t TLB_VALID = (1 << 0); +const int32_t TLB_READONLY = (1 << 1); +const int32_t TLB_NO_USER = (1 << 2); +const int32_t TLB_IN_MAPPED_RANGE = (1 << 3); +const int32_t TLB_GLOBAL = (1 << 4); +const int32_t TLB_HAS_CODE = (1 << 5); + #if DEBUG bool must_not_fault = false; #endif -#if CHECK_CPU_EXCEPTIONS +#if 1 int32_t current_cpu_exception = -1; void assert_no_cpu_exception() { if(current_cpu_exception != -1) { - dbg_log("Expected no cpu exception, got %d", current_cpu_exception); + dbg_log1("Expected no cpu exception, got %d", current_cpu_exception); dbg_trace(); assert(false); } @@ -43,6 +224,7 @@ uint64_t tsc_offset = 0; bool jit_block_boundary = false; +const int32_t VALID_TLB_ENTRY_MAX = 10000; int32_t valid_tlb_entries[VALID_TLB_ENTRY_MAX] = {0}; int32_t valid_tlb_entries_count = 0; @@ -111,9 +293,9 @@ void update_eflags(int32_t new_flags) void trigger_pagefault(bool write, bool user, bool present) { - if(LOG_PAGE_FAULTS) + if(false) { - dbg_log("page fault w=%d u=%d p=%d eip=%x cr2=%x", + dbg_log5("page fault w=%d u=%d p=%d eip=%x cr2=%x", write, user, present, *previous_ip, cr[2]); dbg_trace(); } @@ -296,20 +478,21 @@ int32_t do_page_translation(int32_t addr, bool for_writing, bool user) } else { -#if CHECK_TLB_INVARIANTS - bool found = false; - - for(int32_t i = 0; i < valid_tlb_entries_count; i++) + if(CHECK_TLB_INVARIANTS) { - if(valid_tlb_entries[i] == page) - { - found = true; - break; - } - } + bool found = false; - assert(found); -#endif + for(int32_t i = 0; i < valid_tlb_entries_count; i++) + { + if(valid_tlb_entries[i] == page) + { + found = true; + break; + } + } + + assert(found); + } } bool is_in_mapped_range = in_mapped_range(high); @@ -356,7 +539,8 @@ void tlb_set_has_code(uint32_t physical_page, bool has_code) void check_tlb_invariants(void) { -#if CHECK_TLB_INVARIANTS + if(!CHECK_TLB_INVARIANTS) return; + for(int32_t i = 0; i < valid_tlb_entries_count; i++) { int32_t page = valid_tlb_entries[i]; @@ -381,7 +565,6 @@ void check_tlb_invariants(void) // problem when clearing code from a page) dbg_assert(!entry_has_code || has_code); } -#endif } int32_t get_valid_tlb_entries_count(void) @@ -704,7 +887,7 @@ bool same_page(int32_t addr1, int32_t addr2) void cycle_internal() { profiler_stat_increment(S_CYCLE_INTERNAL); -#if ENABLE_JIT + if(true) { *previous_ip = *instruction_pointer; uint32_t phys_addr = get_phys_eip(); @@ -722,7 +905,7 @@ void cycle_internal() uint16_t wasm_table_index = entry & 0xFFFF; uint16_t initial_state = entry >> 16; - call_indirect1(wasm_table_index, initial_state); + call_indirect1((uint32_t)wasm_table_index + 0x100, initial_state); clear_current_cpu_exception(); @@ -751,7 +934,9 @@ void cycle_internal() profiler_stat_increment_by(S_RUN_INTERPRETED_STEPS, *timestamp_counter - initial_tsc); } -#else + } + else + { /* Use non-JIT mode */ previous_ip[0] = instruction_pointer[0]; @@ -764,7 +949,7 @@ void cycle_internal() #endif run_instruction(opcode | !!*is_32 << 8); -#endif + } } void run_prefix_instruction() @@ -806,7 +991,7 @@ void raise_exception(int32_t interrupt_nr) #if DEBUG if(must_not_fault) { - dbg_log("Unexpected fault: 0x%x", interrupt_nr); + dbg_log1("Unexpected fault: 0x%x", interrupt_nr); dbg_trace(); assert(false); } @@ -827,7 +1012,7 @@ void raise_exception_with_code(int32_t interrupt_nr, int32_t error_code) #if DEBUG if(must_not_fault) { - dbg_log("Unexpected fault: 0x%x with code 0x%x", interrupt_nr, error_code); + dbg_log2("Unexpected fault: 0x%x with code 0x%x", interrupt_nr, error_code); dbg_trace(); assert(false); } @@ -1467,12 +1652,13 @@ void clear_tlb() valid_tlb_entries_count = global_page_offset; -#if CHECK_TLB_INVARIANTS - for(int32_t i = 0; i < 0x100000; i++) + if(CHECK_TLB_INVARIANTS) { - assert(tlb_data[i] == 0 || (tlb_data[i] & TLB_GLOBAL)); + for(int32_t i = 0; i < 0x100000; i++) + { + assert(tlb_data[i] == 0 || (tlb_data[i] & TLB_GLOBAL)); + } } -#endif } void full_clear_tlb() @@ -1491,12 +1677,13 @@ void full_clear_tlb() valid_tlb_entries_count = 0; -#if CHECK_TLB_INVARIANTS - for(int32_t i = 0; i < 0x100000; i++) + if(CHECK_TLB_INVARIANTS) { - assert(tlb_data[i] == 0); + for(int32_t i = 0; i < 0x100000; i++) + { + assert(tlb_data[i] == 0); + } } -#endif } void invlpg(int32_t addr) diff --git a/src/native/cpu.h b/src/native/cpu.h index 342326a0..36be9c85 100644 --- a/src/native/cpu.h +++ b/src/native/cpu.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include @@ -21,7 +20,7 @@ union reg128 { float_t f32[4]; double_t f64[2]; }; -_Static_assert(sizeof(union reg128) == 16, "reg128 is 16 bytes"); +//_Static_assert(sizeof(union reg128) == 16, "reg128 is 16 bytes"); union reg64 { int8_t i8[8]; @@ -35,7 +34,7 @@ union reg64 { float_t f32[2]; double f64[1]; }; -_Static_assert(sizeof(union reg64) == 8, "reg64 is 8 bytes"); +//_Static_assert(sizeof(union reg64) == 8, "reg64 is 8 bytes"); typedef uint8_t cached_state_flags; @@ -43,36 +42,36 @@ typedef uint8_t cached_state_flags; // state-altering, etc.) extern bool jit_block_boundary; -#define VALID_TLB_ENTRY_MAX 10000 -int32_t valid_tlb_entries[VALID_TLB_ENTRY_MAX]; -int32_t valid_tlb_entries_count; +extern const int32_t VALID_TLB_ENTRY_MAX; +extern int32_t valid_tlb_entries[10000]; +extern int32_t valid_tlb_entries_count; -#define TLB_VALID (1 << 0) -#define TLB_READONLY (1 << 1) -#define TLB_NO_USER (1 << 2) -#define TLB_IN_MAPPED_RANGE (1 << 3) -#define TLB_GLOBAL (1 << 4) -#define TLB_HAS_CODE (1 << 5) +extern const int32_t TLB_VALID; +extern const int32_t TLB_READONLY; +extern const int32_t TLB_NO_USER; +extern const int32_t TLB_IN_MAPPED_RANGE; +extern const int32_t TLB_GLOBAL; +extern const int32_t TLB_HAS_CODE; -static const int32_t CPU_EXCEPTION_DE = 0; // Divide Error -static const int32_t CPU_EXCEPTION_DB = 1; // Debug Exception -static const int32_t CPU_EXCEPTION_NMI = 2; // NMI Interrupt -static const int32_t CPU_EXCEPTION_BP = 3; // Breakpoint -static const int32_t CPU_EXCEPTION_OF = 4; // Overflow -static const int32_t CPU_EXCEPTION_BR = 5; // BOUND Range Exceeded -static const int32_t CPU_EXCEPTION_UD = 6; // Invalid Opcode -static const int32_t CPU_EXCEPTION_NM = 7; // Device Not Available -static const int32_t CPU_EXCEPTION_DF = 8; // Double Fault -static const int32_t CPU_EXCEPTION_TS = 10; // Invalid TSS -static const int32_t CPU_EXCEPTION_NP = 11; // Segment Not Present -static const int32_t CPU_EXCEPTION_SS = 12; // Stack-Segment Fault -static const int32_t CPU_EXCEPTION_GP = 13; // General Protection -static const int32_t CPU_EXCEPTION_PF = 14; // Page Fault -static const int32_t CPU_EXCEPTION_MF = 16; // x87 FPU Floating-Point Error -static const int32_t CPU_EXCEPTION_AC = 17; // Alignment Check -static const int32_t CPU_EXCEPTION_MC = 18; // Machine Check Abort -static const int32_t CPU_EXCEPTION_XM = 19; // SIMD Floating-Point Exception -static const int32_t CPU_EXCEPTION_VE = 20; // Virtualization Exception +extern const int32_t CPU_EXCEPTION_DE; // Divide Error +extern const int32_t CPU_EXCEPTION_DB; // Debug Exception +extern const int32_t CPU_EXCEPTION_NMI; // NMI Interrupt +extern const int32_t CPU_EXCEPTION_BP; // Breakpoint +extern const int32_t CPU_EXCEPTION_OF; // Overflow +extern const int32_t CPU_EXCEPTION_BR; // BOUND Range Exceeded +extern const int32_t CPU_EXCEPTION_UD; // Invalid Opcode +extern const int32_t CPU_EXCEPTION_NM; // Device Not Available +extern const int32_t CPU_EXCEPTION_DF; // Double Fault +extern const int32_t CPU_EXCEPTION_TS; // Invalid TSS +extern const int32_t CPU_EXCEPTION_NP; // Segment Not Present +extern const int32_t CPU_EXCEPTION_SS; // Stack-Segment Fault +extern const int32_t CPU_EXCEPTION_GP; // General Protection +extern const int32_t CPU_EXCEPTION_PF; // Page Fault +extern const int32_t CPU_EXCEPTION_MF; // x87 FPU Floating-Point Error +extern const int32_t CPU_EXCEPTION_AC; // Alignment Check +extern const int32_t CPU_EXCEPTION_MC; // Machine Check Abort +extern const int32_t CPU_EXCEPTION_XM; // SIMD Floating-Point Exception +extern const int32_t CPU_EXCEPTION_VE; // Virtualization Exception // defined in call-indirect.ll extern void call_indirect(int32_t index); diff --git a/src/native/fpu.c b/src/native/fpu.c index 6f6666e9..9eb986c5 100644 --- a/src/native/fpu.c +++ b/src/native/fpu.c @@ -10,6 +10,29 @@ #include "log.h" #include "misc_instr.h" +//#ifndef M_LOG2E +const double_t M_LOG2E = 1.44269504088896340736; +//#endif + +//#ifndef M_LN2 +const double_t M_LN2 = 0.693147180559945309417; +//#endif + +//#ifndef M_LN10 +const double_t M_LN10 = 2.30258509299404568402; +//#endif + +//#ifndef M_PI +const double_t M_PI = 3.14159265358979323846; +//#endif + +const int32_t FPU_C0 = 0x100; +const int32_t FPU_C1 = 0x200; +const int32_t FPU_C2 = 0x400; +const int32_t FPU_C3 = 0x4000; +const int32_t FPU_RESULT_FLAGS = (FPU_C0 | FPU_C1 | FPU_C2 | FPU_C3); +const int32_t FPU_STACK_TOP = 0x3800; + // precision, round & infinity control const int32_t FPU_PC = 3 << 8, @@ -253,7 +276,7 @@ void fpu_ftst(double_t x) { *fpu_status_word &= ~FPU_RESULT_FLAGS; - if(isnan(x)) + if(isnan_XXX(x)) { *fpu_status_word |= FPU_C3 | FPU_C2 | FPU_C0; } @@ -278,7 +301,7 @@ void fpu_fxam(double_t x) { *fpu_status_word |= FPU_C3 | FPU_C0; } - else if(isnan(x)) + else if(isnan_XXX(x)) { *fpu_status_word |= FPU_C0; } @@ -326,7 +349,7 @@ int32_t fpu_load_tag_word() { tag_word |= 1 << (i << 1); } - else if(!isfinite(value)) + else if(!isfinite_XXX(value)) { tag_word |= 2 << (i << 1); } diff --git a/src/native/fpu.h b/src/native/fpu.h index f257f6be..abea6e1c 100644 --- a/src/native/fpu.h +++ b/src/native/fpu.h @@ -4,28 +4,28 @@ #include #include -#ifndef M_LOG2E -#define M_LOG2E 1.44269504088896340736 -#endif +//#ifndef M_LOG2E +extern const double_t M_LOG2E; +//#endif -#ifndef M_LN2 -#define M_LN2 0.693147180559945309417 -#endif +//#ifndef M_LN2 +extern const double_t M_LN2; +//#endif -#ifndef M_LN10 -#define M_LN10 2.30258509299404568402 -#endif +//#ifndef M_LN10 +extern const double_t M_LN10; +//#endif -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif +//#ifndef M_PI +extern const double_t M_PI; +//#endif -#define FPU_C0 0x100 -#define FPU_C1 0x200 -#define FPU_C2 0x400 -#define FPU_C3 0x4000 -#define FPU_RESULT_FLAGS (FPU_C0 | FPU_C1 | FPU_C2 | FPU_C3) -#define FPU_STACK_TOP 0x3800 +extern const int32_t FPU_C0; +extern const int32_t FPU_C1; +extern const int32_t FPU_C2; +extern const int32_t FPU_C3; +extern const int32_t FPU_RESULT_FLAGS; +extern const int32_t FPU_STACK_TOP; double_t fpu_get_st0(void); double_t fpu_get_sti(int32_t i); diff --git a/src/native/global_pointers.c b/src/native/global_pointers.c new file mode 100644 index 00000000..53c37c40 --- /dev/null +++ b/src/native/global_pointers.c @@ -0,0 +1,96 @@ +#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; +int16_t* const reg16s = (int16_t* const) 4; +int32_t* const reg32s = (int32_t* const) 4; + +int32_t* const last_op1 = (int32_t* const) 512; +int32_t* const last_op2 = (int32_t* const) 516; +int32_t* const last_op_size = (int32_t* const) 520; +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; + +bool* const page_fault = (bool* const) 540; + +// gap + +bool* const a20_enabled = (bool* const) 552; +int32_t* const instruction_pointer = (int32_t* const) 556; +int32_t* const previous_ip = (int32_t* const) 560; + +int32_t* const idtr_size = (int32_t* const) 564; +int32_t* const idtr_offset = (int32_t* const) 568; +int32_t* const gdtr_size = (int32_t* const) 572; +int32_t* const gdtr_offset = (int32_t* const) 576; +int32_t* const cr = (int32_t* const) 580; // length 32 + +uint8_t* const cpl = (uint8_t* const) 612; +bool* const in_hlt = (bool* const) 616; +int32_t* const last_virt_eip = (int32_t* const) 620; +int32_t* const eip_phys = (int32_t* const) 624; +int32_t* const last_virt_esp = (int32_t* const) 628; +int32_t* const esp_phys = (int32_t* const) 632; +int32_t* const sysenter_cs = (int32_t* const) 636; +int32_t* const sysenter_esp = (int32_t* const) 640; +int32_t* const sysenter_eip = (int32_t* const) 644; +uint8_t* const prefixes = (uint8_t* const) 648; +// gap +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 +int32_t* const fw_value = (int32_t* const) 720; +bool* const segment_is_null = (bool* const) 724; // length 8 +int32_t* const segment_offsets = (int32_t* const) 736; // length 32 +uint32_t* const segment_limits = (uint32_t* const) 768; // length 32 + +bool* const protected_mode = (bool* const) 800; +bool* const is_32 = (bool* const) 804; +bool* const stack_size_32 = (bool* const) 808; +uint32_t* const memory_size = (uint32_t* const) 812; +int32_t* const fpu_stack_empty = (int32_t* const) 816; + +// gap + +int32_t* const mxcsr = (int32_t* const) 824; + +union reg128* const reg_xmm = (union reg128* const) 828; // length 128 + +uint64_t* const current_tsc = (uint64_t* const) 956; + +double_t* const fpu_st = (double_t* const) 968; // length 64 +uint8_t* const fpu_st8 = (uint8_t* const) 968; +int32_t* const fpu_st32 = (int32_t* const) 968; + +uint32_t* const fpu_stack_ptr = (uint32_t* const) 1032; +int32_t* const fpu_control_word = (int32_t* const) 1036; +int32_t* const fpu_status_word = (int32_t* const) 1040; +int32_t* const fpu_opcode = (int32_t* const) 1044; +int32_t* const fpu_ip = (int32_t* const) 1048; +int32_t* const fpu_ip_selector = (int32_t* const) 1052; +int32_t* const fpu_dp = (int32_t* const) 1056; +int32_t* const fpu_dp_selector = (int32_t* const) 1060; + +union reg64* const reg_mmx = (union reg64* const) 1064; // length 64 + +// gap + +uint32_t* const opstats_buffer = (uint32_t* const) 0x1000; // length 0x400 +uint32_t* const opstats_buffer_0f = (uint32_t* const) 0x1400; // length 0x400 + +// gap + +int32_t* const tlb_data = (int32_t* const) 0x400000; // length 0x100000*4 + +uint8_t* const mem8 = (uint8_t* const) 0x800000; +uint16_t* const mem16 = (uint16_t* const) 0x800000; +int32_t* const mem32s = (int32_t* const) 0x800000; diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index fb3bbdd6..a47e33fc 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -7,92 +7,92 @@ #include "const.h" #include "shared.h" -static uint8_t* const reg8 = (uint8_t* const) 4; -static uint16_t* const reg16 = (uint16_t* const) 4; -static int8_t* const reg8s = (int8_t* const) 4; -static int16_t* const reg16s = (int16_t* const) 4; -static int32_t* const reg32s = (int32_t* const) 4; +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 int32_t* const last_op1 = (int32_t* const) 512; -static int32_t* const last_op2 = (int32_t* const) 516; -static int32_t* const last_op_size = (int32_t* const) 520; -static int32_t* const last_add_result = (int32_t* const) 524; -static int32_t* const last_result = (int32_t* const) 528; -static int32_t* const flags_changed = (int32_t* const) 532; -static int32_t* const flags = (int32_t* const) 536; +extern int32_t* const last_op1; +extern int32_t* const last_op2; +extern int32_t* const last_op_size; +extern int32_t* const last_add_result; +extern int32_t* const last_result; +extern int32_t* const flags_changed; +extern int32_t* const flags; -static bool* const page_fault = (bool* const) 540; +extern bool* const page_fault; // gap -static bool* const a20_enabled = (bool* const) 552; -static int32_t* const instruction_pointer = (int32_t* const) 556; -static int32_t* const previous_ip = (int32_t* const) 560; +extern bool* const a20_enabled; +extern int32_t* const instruction_pointer; +extern int32_t* const previous_ip; -static int32_t* const idtr_size = (int32_t* const) 564; -static int32_t* const idtr_offset = (int32_t* const) 568; -static int32_t* const gdtr_size = (int32_t* const) 572; -static int32_t* const gdtr_offset = (int32_t* const) 576; -static int32_t* const cr = (int32_t* const) 580; // length 32 +extern int32_t* const idtr_size; +extern int32_t* const idtr_offset; +extern int32_t* const gdtr_size; +extern int32_t* const gdtr_offset; +extern int32_t* const cr; // length 32 -static uint8_t* const cpl = (uint8_t* const) 612; -static bool* const in_hlt = (bool* const) 616; -static int32_t* const last_virt_eip = (int32_t* const) 620; -static int32_t* const eip_phys = (int32_t* const) 624; -static int32_t* const last_virt_esp = (int32_t* const) 628; -static int32_t* const esp_phys = (int32_t* const) 632; -static int32_t* const sysenter_cs = (int32_t* const) 636; -static int32_t* const sysenter_esp = (int32_t* const) 640; -static int32_t* const sysenter_eip = (int32_t* const) 644; -static uint8_t* const prefixes = (uint8_t* const) 648; +extern uint8_t* const cpl; +extern bool* const in_hlt; +extern int32_t* const last_virt_eip; +extern int32_t* const eip_phys; +extern int32_t* const last_virt_esp; +extern int32_t* const esp_phys; +extern int32_t* const sysenter_cs; +extern int32_t* const sysenter_esp; +extern int32_t* const sysenter_eip; +extern uint8_t* const prefixes; // gap -static uint32_t* const timestamp_counter = (uint32_t* const) 664; +extern uint32_t* const timestamp_counter; -static uint16_t* const sreg = (uint16_t* const) 668; -static int32_t* const dreg = (int32_t* const) 684; // length 32 -static int32_t* const fw_value = (int32_t* const) 720; -static bool* const segment_is_null = (bool* const) 724; // length 8 -static int32_t* const segment_offsets = (int32_t* const) 736; // length 32 -static uint32_t* const segment_limits = (uint32_t* const) 768; // length 32 +extern uint16_t* const sreg; +extern int32_t* const dreg; // length 32 +extern int32_t* const fw_value; +extern bool* const segment_is_null; // length 8 +extern int32_t* const segment_offsets; // length 32 +extern uint32_t* const segment_limits; // length 32 -static bool* const protected_mode = (bool* const) 800; -static bool* const is_32 = (bool* const) 804; -static bool* const stack_size_32 = (bool* const) 808; -static uint32_t* const memory_size = (uint32_t* const) 812; -static int32_t* const fpu_stack_empty = (int32_t* const) 816; +extern bool* const protected_mode; +extern bool* const is_32; +extern bool* const stack_size_32; +extern uint32_t* const memory_size; +extern int32_t* const fpu_stack_empty; // gap -static int32_t* const mxcsr = (int32_t* const) 824; +extern int32_t* const mxcsr; -static union reg128* const reg_xmm = (union reg128* const) 828; // length 128 +extern union reg128* const reg_xmm; // length 128 -static uint64_t* const current_tsc = (uint64_t* const) 956; +extern uint64_t* const current_tsc; -static double_t* const fpu_st = (double_t* const) 968; // length 64 -static uint8_t* const fpu_st8 = (uint8_t* const) 968; -static int32_t* const fpu_st32 = (int32_t* const) 968; +extern double_t* const fpu_st; // length 64 +extern uint8_t* const fpu_st8; +extern int32_t* const fpu_st32; -static uint32_t* const fpu_stack_ptr = (uint32_t* const) 1032; -static int32_t* const fpu_control_word = (int32_t* const) 1036; -static int32_t* const fpu_status_word = (int32_t* const) 1040; -static int32_t* const fpu_opcode = (int32_t* const) 1044; -static int32_t* const fpu_ip = (int32_t* const) 1048; -static int32_t* const fpu_ip_selector = (int32_t* const) 1052; -static int32_t* const fpu_dp = (int32_t* const) 1056; -static int32_t* const fpu_dp_selector = (int32_t* const) 1060; +extern uint32_t* const fpu_stack_ptr; +extern int32_t* const fpu_control_word; +extern int32_t* const fpu_status_word; +extern int32_t* const fpu_opcode; +extern int32_t* const fpu_ip; +extern int32_t* const fpu_ip_selector; +extern int32_t* const fpu_dp; +extern int32_t* const fpu_dp_selector; -static union reg64* const reg_mmx = (union reg64* const) 1064; // length 64 +extern union reg64* const reg_mmx; // length 64 // gap -static uint32_t* const opstats_buffer = (uint32_t* const) 0x1000; // length 0x400 -static uint32_t* const opstats_buffer_0f = (uint32_t* const) 0x1400; // length 0x400 +extern uint32_t* const opstats_buffer; // length 0x400 +extern uint32_t* const opstats_buffer_0f; // length 0x400 // gap -static int32_t* const tlb_data = (int32_t* const) 0x400000; // length 0x100000*4 +extern int32_t* const tlb_data; // length 0x100000*4 -static uint8_t* const mem8 = (uint8_t* const) 0x800000; -static uint16_t* const mem16 = (uint16_t* const) 0x800000; -static int32_t* const mem32s = (int32_t* const) 0x800000; +extern uint8_t* const mem8; +extern uint16_t* const mem16; +extern int32_t* const mem32s; diff --git a/src/native/instructions.c b/src/native/instructions.c index bbdbe069..66977eac 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -1,5 +1,3 @@ -#include -#include #include #include @@ -418,8 +416,8 @@ 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, ___)) -bool instr_8C_check_sreg(int32_t sreg) { - if(sreg >= 6) +bool instr_8C_check_sreg(int32_t seg) { + if(seg >= 6) { dbg_log("mov sreg #ud"); trigger_ud(); @@ -1039,7 +1037,7 @@ void instr_D9_4_reg(int32_t r) fpu_fxam(st0); break; default: - dbg_log("%x", r); + dbg_log1("%x", r); trigger_ud(); } } @@ -1653,9 +1651,9 @@ void instr32_FF_5_mem(int32_t addr) } DEFINE_MODRM_INSTR1_READ32(instr32_FF_6, push32(___)) -void run_instruction(int32_t opcode) -{ -#include "../../build/interpreter.c" -} +//void run_instruction(int32_t opcode) +//{ +//#include "../../build/interpreter.c" +//} #pragma clang diagnostic pop diff --git a/src/native/instructions.h b/src/native/instructions.h index 43c66a62..680a2faa 100644 --- a/src/native/instructions.h +++ b/src/native/instructions.h @@ -3,75 +3,81 @@ #include "cpu.h" #include -#define SAFE_READ_WRITE8(addr, fun) \ - int32_t phys_addr = translate_address_write(addr); \ - int32_t ___ = read8(phys_addr); \ - write8(phys_addr, fun); +extern void SAFE_READ_WRITE8(); +extern void SAFE_READ_WRITE16(); +extern void SAFE_READ_WRITE32(); -#define SAFE_READ_WRITE16(addr, fun) \ - int32_t phys_addr = translate_address_write(addr); \ - if((phys_addr & 0xFFF) == 0xFFF) \ - { \ - int32_t phys_addr_high = translate_address_write((addr) + 1); \ - int32_t ___ = virt_boundary_read16(phys_addr, phys_addr_high); \ - virt_boundary_write16(phys_addr, phys_addr_high, fun); \ - } \ - else \ - { \ - int32_t ___ = read16(phys_addr); \ - write16(phys_addr, fun); \ - } +extern int32_t ___; -#define SAFE_READ_WRITE32(addr, fun) \ - int32_t phys_addr = translate_address_write(addr); \ - if((phys_addr & 0xFFF) >= 0xFFD) \ - { \ - int32_t phys_addr_high = translate_address_write((addr) + 3 & ~3) | ((addr) + 3) & 3; \ - int32_t ___ = virt_boundary_read32s(phys_addr, phys_addr_high); \ - virt_boundary_write32(phys_addr, phys_addr_high, fun); \ - } \ - else \ - { \ - int32_t ___ = read32s(phys_addr); \ - write32(phys_addr, fun); \ - } +//#define SAFE_READ_WRITE8(addr, fun) \ +// int32_t phys_addr = translate_address_write(addr); \ +// int32_t ___ = read8(phys_addr); \ +// write8(phys_addr, fun); +// +//#define SAFE_READ_WRITE16(addr, fun) \ +// int32_t phys_addr = translate_address_write(addr); \ +// if((phys_addr & 0xFFF) == 0xFFF) \ +// { \ +// int32_t phys_addr_high = translate_address_write((addr) + 1); \ +// int32_t ___ = virt_boundary_read16(phys_addr, phys_addr_high); \ +// virt_boundary_write16(phys_addr, phys_addr_high, fun); \ +// } \ +// else \ +// { \ +// int32_t ___ = read16(phys_addr); \ +// write16(phys_addr, fun); \ +// } +// +//#define SAFE_READ_WRITE32(addr, fun) \ +// int32_t phys_addr = translate_address_write(addr); \ +// if((phys_addr & 0xFFF) >= 0xFFD) \ +// { \ +// int32_t phys_addr_high = translate_address_write((addr) + 3 & ~3) | ((addr) + 3) & 3; \ +// int32_t ___ = virt_boundary_read32s(phys_addr, phys_addr_high); \ +// virt_boundary_write32(phys_addr, phys_addr_high, fun); \ +// } \ +// else \ +// { \ +// int32_t ___ = read32s(phys_addr); \ +// write32(phys_addr, fun); \ +// } #define DEFINE_MODRM_INSTR1_READ_WRITE_8(name, fun) \ - void name ## _mem(int32_t addr) { SAFE_READ_WRITE8(addr, fun) } \ + void name ## _mem(int32_t addr) { SAFE_READ_WRITE8(addr, fun); } \ void name ## _reg(int32_t r1) { int32_t ___ = read_reg8(r1); write_reg8(r1, fun); } #define DEFINE_MODRM_INSTR1_READ_WRITE_16(name, fun) \ - void name ## _mem(int32_t addr) { SAFE_READ_WRITE16(addr, fun) } \ + void name ## _mem(int32_t addr) { SAFE_READ_WRITE16(addr, fun); } \ void name ## _reg(int32_t r1) { int32_t ___ = read_reg16(r1); write_reg16(r1, fun); } #define DEFINE_MODRM_INSTR1_READ_WRITE_32(name, fun) \ - void name ## _mem(int32_t addr) { SAFE_READ_WRITE32(addr, fun) } \ + void name ## _mem(int32_t addr) { SAFE_READ_WRITE32(addr, fun); } \ void name ## _reg(int32_t r1) { int32_t ___ = read_reg32(r1); write_reg32(r1, fun); } #define DEFINE_MODRM_INSTR2_READ_WRITE_8(name, fun) \ - void name ## _mem(int32_t addr, int32_t imm) { SAFE_READ_WRITE8(addr, fun) } \ + void name ## _mem(int32_t addr, int32_t imm) { SAFE_READ_WRITE8(addr, fun); } \ 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) \ - void name ## _mem(int32_t addr, int32_t imm) { SAFE_READ_WRITE16(addr, fun) } \ + void name ## _mem(int32_t addr, int32_t imm) { SAFE_READ_WRITE16(addr, fun); } \ 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) \ - void name ## _mem(int32_t addr, int32_t imm) { SAFE_READ_WRITE32(addr, fun) } \ + void name ## _mem(int32_t addr, int32_t imm) { SAFE_READ_WRITE32(addr, fun); } \ 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) \ - void name ## _mem(int32_t addr, int32_t r) { SAFE_READ_WRITE8(addr, fun) } \ + void name ## _mem(int32_t addr, int32_t r) { SAFE_READ_WRITE8(addr, fun); } \ 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) \ - void name ## _mem(int32_t addr, int32_t r) { SAFE_READ_WRITE16(addr, fun) } \ + void name ## _mem(int32_t addr, int32_t r) { SAFE_READ_WRITE16(addr, fun); } \ 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) \ - void name ## _mem(int32_t addr, int32_t r) { SAFE_READ_WRITE32(addr, fun) } \ + void name ## _mem(int32_t addr, int32_t r) { SAFE_READ_WRITE32(addr, fun); } \ void name ## _reg(int32_t r1, int32_t r) { int32_t ___ = read_reg32(r1); write_reg32(r1, fun); } diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index c31a1a6d..fc6937f5 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -20,6 +19,9 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-parameter" +const bool CPU_LOG_VERBOSE = false; +const bool ENABLE_ACPI = true; + bool apic_enabled = false; void instr_0F00_0_mem(int32_t addr) { @@ -460,7 +462,7 @@ void instr_0F20(int32_t r, int32_t creg) { write_reg32(r, cr[4]); break; default: - dbg_log("%d", creg); + dbg_log1("%d", creg); undefined_instruction(); } } @@ -511,7 +513,7 @@ void instr_0F22(int32_t r, int32_t creg) { break; case 2: - dbg_log("cr2 <- %x", data); + dbg_log1("cr2 <- %x", data); cr[2] = data; break; @@ -526,7 +528,7 @@ void instr_0F22(int32_t r, int32_t creg) { break; case 4: - dbg_log("cr4 <- %d", cr[4]); + dbg_log1("cr4 <- %d", cr[4]); if(data & (1 << 11 | 1 << 12 | 1 << 15 | 1 << 16 | 1 << 19 | 0xFFC00000)) { @@ -551,7 +553,7 @@ void instr_0F22(int32_t r, int32_t creg) { break; default: - dbg_log("%d", creg); + dbg_log1("%d", creg); undefined_instruction(); } } @@ -746,24 +748,25 @@ void instr_0F30() { if(index != IA32_SYSENTER_ESP) { - dbg_log("wrmsr ecx=%x data=%x:%x", index, high, low); + dbg_log3("wrmsr ecx=%x data=%x:%x", index, high, low); } - switch(index) - { - case IA32_SYSENTER_CS: + if(index == IA32_SYSENTER_CS) + { sysenter_cs[0] = low & 0xFFFF; - break; - - case IA32_SYSENTER_EIP: + } + else if(index == IA32_SYSENTER_EIP) + { sysenter_eip[0] = low; - break; - case IA32_SYSENTER_ESP: + } + else if(index == IA32_SYSENTER_ESP) + { sysenter_esp[0] = low; - break; - case IA32_APIC_BASE_MSR: + } + else if(index == IA32_APIC_BASE_MSR) + { { dbg_assert_message(high == 0, "Changing APIC address (high 32 bits) not supported"); int32_t address = low & ~(IA32_APIC_BASE_BSP | IA32_APIC_BASE_EXTD | IA32_APIC_BASE_EN); @@ -771,35 +774,40 @@ void instr_0F30() { dbg_assert_message((low & IA32_APIC_BASE_EXTD) == 0, "x2apic not supported"); apic_enabled = (low & IA32_APIC_BASE_EN) == IA32_APIC_BASE_EN; } - break; - case IA32_TIME_STAMP_COUNTER: + } + else if(index == IA32_TIME_STAMP_COUNTER) + { set_tsc(low, high); - break; - case IA32_BIOS_SIGN_ID: - break; + } + else if(index == IA32_BIOS_SIGN_ID) + { - case MSR_MISC_FEATURE_ENABLES: + } + else if(index == MSR_MISC_FEATURE_ENABLES) + { // Linux 4, see: https://patchwork.kernel.org/patch/9528279/ - break; - case IA32_MISC_ENABLE: // Enable Misc. Processor Features - break; + } + else if(index == IA32_MISC_ENABLE) + { // Enable Misc. Processor Features - case IA32_MCG_CAP: + } + else if(index == IA32_MCG_CAP) + { // netbsd - break; - - case IA32_KERNEL_GS_BASE: + } + else if(index == IA32_KERNEL_GS_BASE) + { // Only used in 64 bit mode (by SWAPGS), but set by kvm-unit-test dbg_log("GS Base written"); - break; - - default: - dbg_log("Unknown msr: %x", index); + } + else + { + dbg_log1("Unknown msr: %x", index); assert(false); - } + } } void instr_0F31() { @@ -830,37 +838,41 @@ void instr_0F32() { int32_t index = reg32s[ECX]; - dbg_log("rdmsr ecx=%x", index); + dbg_log1("rdmsr ecx=%x", index); int32_t low = 0; int32_t high = 0; - switch(index) - { - case IA32_SYSENTER_CS: + if(index == IA32_SYSENTER_CS) + { low = sysenter_cs[0]; - break; - case IA32_SYSENTER_EIP: + } + else if(index == IA32_SYSENTER_EIP) + { low = sysenter_eip[0]; - break; - case IA32_SYSENTER_ESP: + } + else if(index == IA32_SYSENTER_ESP) + { low = sysenter_esp[0]; - break; - case IA32_TIME_STAMP_COUNTER: + } + else if(index == IA32_TIME_STAMP_COUNTER) + { { uint64_t tsc = read_tsc(); low = tsc; high = tsc >> 32; } - break; - case IA32_PLATFORM_ID: - break; + } + else if(index == IA32_PLATFORM_ID) + { - case IA32_APIC_BASE_MSR: + } + else if(index == IA32_APIC_BASE_MSR) + { if(ENABLE_ACPI) { low = APIC_ADDRESS; @@ -870,40 +882,48 @@ void instr_0F32() { low |= IA32_APIC_BASE_EN; } } - break; - case IA32_BIOS_SIGN_ID: - break; + } + else if(index == IA32_BIOS_SIGN_ID) + { - case MSR_PLATFORM_INFO: + } + else if(index == MSR_PLATFORM_INFO) + { low = 1 << 8; - break; - case MSR_MISC_FEATURE_ENABLES: - break; + } + else if(index == MSR_MISC_FEATURE_ENABLES) + { - case IA32_MISC_ENABLE: // Enable Misc. Processor Features + } + else if(index == IA32_MISC_ENABLE) + { // Enable Misc. Processor Features low = 1 << 0; // fast string - break; - case IA32_RTIT_CTL: + } + else if(index == IA32_RTIT_CTL) + { // linux4 - break; - case MSR_SMI_COUNT: - break; + } + else if(index == MSR_SMI_COUNT) + { - case IA32_MCG_CAP: + } + else if(index == IA32_MCG_CAP) + { // netbsd - break; - case MSR_PKG_C2_RESIDENCY: - break; - - default: - dbg_log("Unknown msr: %x", index); + } + else if(index == MSR_PKG_C2_RESIDENCY) + { + } + else + { + dbg_log1("Unknown msr: %x", index); assert(false); - } + } reg32s[EAX] = low; reg32s[EDX] = high; @@ -2363,7 +2383,7 @@ void instr_0FAE_2_mem(int32_t addr) { int32_t new_mxcsr = safe_read32s(addr); if(new_mxcsr & ~MXCSR_MASK) { - dbg_log("Invalid mxcsr bits: %x", (new_mxcsr & ~MXCSR_MASK)); + dbg_log1("Invalid mxcsr bits: %x", (new_mxcsr & ~MXCSR_MASK)); assert(false); trigger_gp_non_raising(0); return; @@ -3922,14 +3942,14 @@ void instr_0FFF() { trigger_ud(); } -void run_instruction0f_16(int32_t opcode) -{ -#include "../../build/interpreter0f_16.c" -} +//void run_instruction0f_16(int32_t opcode) +//{ +//#include "../../build/interpreter0f_16.c" +//} -void run_instruction0f_32(int32_t opcode) -{ -#include "../../build/interpreter0f_32.c" -} +//void run_instruction0f_32(int32_t opcode) +//{ +//#include "../../build/interpreter0f_32.c" +//} #pragma clang diagnostic pop diff --git a/src/native/instructions_0f.h b/src/native/instructions_0f.h index 2bd07624..0b2f4340 100644 --- a/src/native/instructions_0f.h +++ b/src/native/instructions_0f.h @@ -16,24 +16,24 @@ #define DEFINE_MODRM_INSTR_IMM_READ_WRITE_16(name, fun) \ - void name ## _mem(int32_t addr, int32_t r, int32_t imm) { SAFE_READ_WRITE16(addr, fun) } \ + void name ## _mem(int32_t addr, int32_t r, int32_t imm) { SAFE_READ_WRITE16(addr, fun); } \ 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) \ - void name ## _mem(int32_t addr, int32_t r, int32_t imm) { SAFE_READ_WRITE32(addr, fun) } \ + void name ## _mem(int32_t addr, int32_t r, int32_t imm) { SAFE_READ_WRITE32(addr, fun); } \ 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) \ - void name ## _mem(int32_t addr, int32_t r) { SAFE_READ_WRITE8(addr, fun) } \ + void name ## _mem(int32_t addr, int32_t r) { SAFE_READ_WRITE8(addr, fun); } \ 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) \ - void name ## _mem(int32_t addr, int32_t r) { SAFE_READ_WRITE16(addr, fun) } \ + void name ## _mem(int32_t addr, int32_t r) { SAFE_READ_WRITE16(addr, fun); } \ 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) \ - void name ## _mem(int32_t addr, int32_t r) { SAFE_READ_WRITE32(addr, fun) } \ + void name ## _mem(int32_t addr, int32_t r) { SAFE_READ_WRITE32(addr, fun); } \ void name ## _reg(int32_t r1, int32_t r) { int32_t ___ = read_reg32(r1); write_reg32(r1, fun); } diff --git a/src/native/log.h b/src/native/log.h index 3b6644e5..65d595f2 100644 --- a/src/native/log.h +++ b/src/native/log.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include @@ -10,7 +9,7 @@ extern void logop(int32_t, int32_t); extern void _dbg_trace(void); -#define dbg_log(...) { if(DEBUG) { printf(__VA_ARGS__); } } -#define dbg_trace(...) { if(DEBUG) { _dbg_trace(__VA_ARGS__); } } -#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); } } +//#define dbg_log(...) { if(DEBUG) { printf(__VA_ARGS__); } } +//#define dbg_trace(...) { if(DEBUG) { _dbg_trace(__VA_ARGS__); } } +//#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 4cc7f325..41dc72ea 100644 --- a/src/native/memory.c +++ b/src/native/memory.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -11,6 +10,8 @@ #include "profiler/profiler.h" #include "rust_imports.h" +const bool USE_A20 = false; + bool in_mapped_range(uint32_t addr) { return (addr >= 0xA0000 && addr < 0xC0000) || addr >= *memory_size; diff --git a/src/native/misc_instr.c b/src/native/misc_instr.c index c0595ec2..c2d8cdc0 100644 --- a/src/native/misc_instr.c +++ b/src/native/misc_instr.c @@ -1,4 +1,3 @@ -#include #include #include #include diff --git a/src/native/modrm.c b/src/native/modrm.c index 7435012f..54418da1 100644 --- a/src/native/modrm.c +++ b/src/native/modrm.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -15,6 +14,11 @@ static int32_t resolve_sib(bool mod); #define ds get_seg_prefix_ds #define ss get_seg_prefix_ss +int32_t MODRM_ENTRY() { return 0; } +int32_t MODRM_ENTRY16() { return 0; } +int32_t MODRM_ENTRY32() { return 0; } + + #define MODRM_ENTRY(n, offset)\ case (n) | 0 << 3:\ case (n) | 1 << 3:\ @@ -35,19 +39,19 @@ int32_t resolve_modrm16(int32_t modrm_byte) { switch(modrm_byte) { - MODRM_ENTRY16(0, ds, reg16[BX] + reg16[SI]) - MODRM_ENTRY16(1, ds, reg16[BX] + reg16[DI]) - MODRM_ENTRY16(2, ss, reg16[BP] + reg16[SI]) - MODRM_ENTRY16(3, ss, reg16[BP] + reg16[DI]) - MODRM_ENTRY16(4, ds, reg16[SI]) - MODRM_ENTRY16(5, ds, reg16[DI]) + MODRM_ENTRY16(0, ds, reg16[BX] + reg16[SI]); + MODRM_ENTRY16(1, ds, reg16[BX] + reg16[DI]); + MODRM_ENTRY16(2, ss, reg16[BP] + reg16[SI]); + MODRM_ENTRY16(3, ss, reg16[BP] + reg16[DI]); + MODRM_ENTRY16(4, ds, reg16[SI]); + MODRM_ENTRY16(5, ds, reg16[DI]); // special case - MODRM_ENTRY(0x00 | 6, ds(read_imm16())) - MODRM_ENTRY(0x40 | 6, ss(reg16[BP] + read_imm8s() & 0xFFFF)) - MODRM_ENTRY(0x80 | 6, ss(reg16[BP] + read_imm16() & 0xFFFF)) + MODRM_ENTRY(0x00 | 6, ds(read_imm16())); + MODRM_ENTRY(0x40 | 6, ss(reg16[BP] + read_imm8s() & 0xFFFF)); + MODRM_ENTRY(0x80 | 6, ss(reg16[BP] + read_imm16() & 0xFFFF)); - MODRM_ENTRY16(7, ds, reg16[BX]) + MODRM_ENTRY16(7, ds, reg16[BX]); default: assert(false); @@ -63,25 +67,25 @@ int32_t resolve_modrm16(int32_t modrm_byte) MODRM_ENTRY(0x40 | (row), seg((value) + read_imm8s()))\ MODRM_ENTRY(0x80 | (row), seg((value) + read_imm32s()))\ -int32_t resolve_modrm32(int32_t modrm_byte) +int32_t resolve_modrm32_(int32_t modrm_byte) { switch(modrm_byte) { - MODRM_ENTRY32(0, ds, reg32s[EAX]) - MODRM_ENTRY32(1, ds, reg32s[ECX]) - MODRM_ENTRY32(2, ds, reg32s[EDX]) - MODRM_ENTRY32(3, ds, reg32s[EBX]) + MODRM_ENTRY32(0, ds, reg32s[EAX]); + MODRM_ENTRY32(1, ds, reg32s[ECX]); + MODRM_ENTRY32(2, ds, reg32s[EDX]); + MODRM_ENTRY32(3, ds, reg32s[EBX]); // special cases - MODRM_ENTRY(0x00 | 4, resolve_sib(false)) - MODRM_ENTRY(0x40 | 4, resolve_sib(true) + read_imm8s()) - MODRM_ENTRY(0x80 | 4, resolve_sib(true) + read_imm32s()) - MODRM_ENTRY(0x00 | 5, ds(read_imm32s())) - MODRM_ENTRY(0x40 | 5, ss(reg32s[EBP] + read_imm8s())) - MODRM_ENTRY(0x80 | 5, ss(reg32s[EBP] + read_imm32s())) + MODRM_ENTRY(0x00 | 4, resolve_sib(false)); + MODRM_ENTRY(0x40 | 4, resolve_sib(true) + read_imm8s()); + MODRM_ENTRY(0x80 | 4, resolve_sib(true) + read_imm32s()); + MODRM_ENTRY(0x00 | 5, ds(read_imm32s())); + MODRM_ENTRY(0x40 | 5, ss(reg32s[EBP] + read_imm8s())); + MODRM_ENTRY(0x80 | 5, ss(reg32s[EBP] + read_imm32s())); - MODRM_ENTRY32(6, ds, reg32s[ESI]) - MODRM_ENTRY32(7, ds, reg32s[EDI]) + MODRM_ENTRY32(6, ds, reg32s[ESI]); + MODRM_ENTRY32(7, ds, reg32s[EDI]); default: assert(false); @@ -190,8 +194,7 @@ static int32_t resolve_sib(bool mod) return get_seg_prefix(seg) + base + offset; } -#if 0 -static inline int32_t resolve_modrm32_(int32_t modrm_byte) +int32_t resolve_modrm32(int32_t modrm_byte) { uint8_t r = modrm_byte & 7; assert(modrm_byte < 0xC0); @@ -230,4 +233,3 @@ static inline int32_t resolve_modrm32_(int32_t modrm_byte) } } } -#endif diff --git a/src/native/shared.c b/src/native/shared.c index de454d36..8e0f573d 100644 --- a/src/native/shared.c +++ b/src/native/shared.c @@ -1,89 +1,103 @@ #include +#include +#include #include #include +void assert(bool x) {} +void dbg_assert(bool x) {} +void dbg_assert_message(bool x, const char* msg) {} +//void dbg_log(const char* m) {} +//void dbg_log1(const char* m, int32_t x) {} +//void dbg_log2(const char* m, int32_t x, int32_t y) {} +//void dbg_log3(const char* m, int32_t x, int32_t y, int32_t z) {} +//void dbg_log5(const char* m, int32_t x, int32_t y, int32_t z, int32_t i, int32_t j) {} +//void dbg_trace() {} +bool isnan_XXX(double f) { return f != f; } +bool isfinite_XXX(double f) { return f == INFINITY || f == -INFINITY || !isnan_XXX(f); } + // via musl libc -void *memset(void *dest, int c, size_t n) -{ - unsigned char *s = (unsigned char *)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; -} +//void *memset(void *dest, int c, size_t n) +//{ +// unsigned char *s = (unsigned char *)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; +//} diff --git a/src/native/shared.h b/src/native/shared.h index b64bb652..eb4ef037 100644 --- a/src/native/shared.h +++ b/src/native/shared.h @@ -6,4 +6,16 @@ #define UNUSED(x) (void)(x) -void *memset(void *dest, int c, size_t n); +//void *memset(void *dest, int c, size_t n); + +void assert(bool x); +void dbg_assert(bool x); +void dbg_assert_message(bool x, const char* msg); +void dbg_log(const char* m); +void dbg_log1(const char* m, int32_t x); +void dbg_log2(const char* m, int32_t x, int32_t y); +void dbg_log3(const char* m, int32_t x, int32_t y, int32_t z); +void dbg_log5(const char* m, int32_t x, int32_t y, int32_t z, int32_t i, int32_t j); +void dbg_trace(); +bool isnan_XXX(double f); +bool isfinite_XXX(double f); diff --git a/src/native/sse_instr.c b/src/native/sse_instr.c index 311e4a5e..217b4298 100644 --- a/src/native/sse_instr.c +++ b/src/native/sse_instr.c @@ -408,14 +408,15 @@ bool sse_comparison(int32_t op, double_t x, double_t y) case 0: return x == y; case 1: return x < y; case 2: return x <= y; - case 3: return isnan(x) || isnan(y); - case 4: return x != y || isnan(x) || isnan(y); - case 5: return x >= y || isnan(x) || isnan(y); - case 6: return x > y || isnan(x) || isnan(y); - case 7: return !isnan(x) && !isnan(y); + case 3: return isnan_XXX(x) || isnan_XXX(y); + case 4: return x != y || isnan_XXX(x) || isnan_XXX(y); + case 5: return x >= y || isnan_XXX(x) || isnan_XXX(y); + case 6: return x > y || isnan_XXX(x) || isnan_XXX(y); + case 7: return !isnan_XXX(x) && !isnan_XXX(y); } assert(false); + return false; } double_t sse_min(double_t x, double_t y) diff --git a/src/native/string.c b/src/native/string.c index 5b54a257..f1bf9df8 100644 --- a/src/native/string.c +++ b/src/native/string.c @@ -8,8 +8,9 @@ #include "log.h" #include "memory.h" #include "string.h" +#include "shared.h" -#define MAX_COUNT_PER_CYCLE 0x1000 +const int32_t MAX_COUNT_PER_CYCLE = 0x1000; #define MIN(x, y) ((x) < (y) ? (x) : (y)) int32_t string_get_cycle_count(int32_t size, int32_t address) diff --git a/src/rust/lib.rs b/src/rust/lib.rs index 759217f1..d4461fba 100644 --- a/src/rust/lib.rs +++ b/src/rust/lib.rs @@ -7,6 +7,8 @@ extern crate quickcheck; #[macro_use] mod dbg; +mod cpu2; + pub mod c_api; mod analysis; From 01061dc4b692d7f91f8a7fe6ec42c4f1567bc7b9 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 8 Aug 2018 16:04:19 -0500 Subject: [PATCH 1173/2137] The final Rust porting This commit contains the final changes requires for porting all C code to Rust and from emscripten to llvm: - tools/wasm-patch-indirect-function-table.js: A script that rewrites the wasm generated by llvm to remove the table limit - tools/rust-lld-wrapper: A wrapper around rust-lld that removes arguments forced by rustc that break compilation for us - src/rust/cpu2/Makefile: A monstrosity to postprocess c2rust's output - gen/generate_interpreter.js: Ported to produce Rust instead of C - src/rust/*: A few functions and macros to connect the old Rust code and the new Rust code - src/*.js: Removes the loading of the old emscripten wasm module and adapts imports and exports from emscripten to llvm --- .gitignore | 3 + Cargo.toml | 5 +- Makefile | 45 +-- docker/test-image/Dockerfile | 3 +- gen/generate_interpreter.js | 89 ++++-- src/browser/serial.js | 2 +- src/browser/starter.js | 249 +++++++++-------- src/const.js | 2 +- src/cpu.js | 289 +++++++++++--------- src/rust/cpu.rs | 4 +- src/rust/cpu2/Makefile | 86 ++++++ src/rust/cpu2/imports.rs | 46 ++++ src/rust/cpu2/instruction_helpers.rs | 41 +++ src/rust/cpu2/mod.rs | 20 ++ src/rust/dbg.rs | 2 + src/rust/gen/mod.rs | 4 + src/rust/lib.rs | 3 +- tools/rust-lld-wrapper | 38 +++ tools/wasm-patch-indirect-function-table.js | 184 +++++++++++++ 19 files changed, 821 insertions(+), 294 deletions(-) create mode 100644 src/rust/cpu2/Makefile create mode 100644 src/rust/cpu2/imports.rs create mode 100644 src/rust/cpu2/instruction_helpers.rs create mode 100644 src/rust/cpu2/mod.rs create mode 100755 tools/rust-lld-wrapper create mode 100755 tools/wasm-patch-indirect-function-table.js diff --git a/.gitignore b/.gitignore index a63e1fea..d976ea74 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,9 @@ package-lock.json profile*.json Cargo.lock build-head +src/rust/gen/interpreter.rs +src/rust/gen/interpreter0f_16.rs +src/rust/gen/interpreter0f_32.rs src/rust/gen/analyzer.rs src/rust/gen/analyzer0f_16.rs src/rust/gen/analyzer0f_32.rs diff --git a/Cargo.toml b/Cargo.toml index 0b45eeac..2d0d9e5c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,8 +12,11 @@ path = "src/rust/lib.rs" [profile.dev] lto = false -opt-level=2 +# XXX: 2 -> removes debug information in later rust verions +# 0 -> requires more imports that are optimised away +opt-level = 2 panic = "abort" +overflow-checks = false [profile.release] lto = true diff --git a/Makefile b/Makefile index e9809f6c..58cf68c5 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ NASM_TEST_DIR=./tests/nasm COVERAGE_DIR=./tests/coverage INSTRUCTION_TABLES=src/rust/gen/jit.rs src/rust/gen/jit0f_16.rs src/rust/gen/jit0f_32.rs \ - build/interpreter.c build/interpreter0f_16.c build/interpreter0f_32.c \ + src/rust/gen/interpreter.rs src/rust/gen/interpreter0f_16.rs src/rust/gen/interpreter0f_32.rs \ src/rust/gen/analyzer.rs src/rust/gen/analyzer0f_16.rs src/rust/gen/analyzer0f_32.rs \ # Only the dependencies common to both generate_{jit,interpreter}.js @@ -102,7 +102,9 @@ CC_FLAGS=\ CARGO_FLAGS=\ --target wasm32-unknown-unknown \ - -- -Clink-args="--import-memory" \ + -- \ + -C linker=tools/rust-lld-wrapper \ + -C link-args="--import-table --global-base=142606336" \ --verbose CORE_FILES=const.js config.js io.js main.js lib.js coverage.js ide.js pci.js floppy.js \ @@ -116,6 +118,7 @@ BROWSER_FILES=screen.js \ network.js lib.js starter.js worker_bus.js dummy_screen.js print_stats.js RUST_FILES=$(shell find src/rust/ -name '*.rs') \ + src/rust/gen/interpreter.rs src/rust/gen/interpreter0f_16.rs src/rust/gen/interpreter0f_32.rs \ src/rust/gen/jit.rs src/rust/gen/jit0f_16.rs src/rust/gen/jit0f_32.rs \ src/rust/gen/analyzer.rs src/rust/gen/analyzer0f_16.rs src/rust/gen/analyzer0f_32.rs @@ -183,11 +186,11 @@ src/rust/gen/jit0f_16.rs: $(JIT_DEPENDENCIES) src/rust/gen/jit0f_32.rs: $(JIT_DEPENDENCIES) ./gen/generate_jit.js --output-dir build/ --table jit0f_32 -build/interpreter.c: $(INTERPRETER_DEPENDENCIES) +src/rust/gen/interpreter.rs: $(INTERPRETER_DEPENDENCIES) ./gen/generate_interpreter.js --output-dir build/ --table interpreter -build/interpreter0f_16.c: $(INTERPRETER_DEPENDENCIES) +src/rust/gen/interpreter0f_16.rs: $(INTERPRETER_DEPENDENCIES) ./gen/generate_interpreter.js --output-dir build/ --table interpreter0f_16 -build/interpreter0f_32.c: $(INTERPRETER_DEPENDENCIES) +src/rust/gen/interpreter0f_32.rs: $(INTERPRETER_DEPENDENCIES) ./gen/generate_interpreter.js --output-dir build/ --table interpreter0f_32 src/rust/gen/analyzer.rs: $(ANALYZER_DEPENDENCIES) @@ -200,38 +203,38 @@ src/rust/gen/analyzer0f_32.rs: $(ANALYZER_DEPENDENCIES) build/v86.wasm: src/native/*.c src/native/*.h src/native/profiler/* src/native/*.ll $(INSTRUCTION_TABLES) mkdir -p build -ls -lh build/v86.wasm - emcc src/native/*.c src/native/profiler/*.c src/native/*.ll \ - $(CC_FLAGS) \ - -DDEBUG=false \ - -DNDEBUG \ - -O3 \ - --llvm-opts 3 \ - --llvm-lto 3 \ - -o build/v86.wasm + #emcc src/native/*.c src/native/profiler/*.c src/native/*.ll \ + # $(CC_FLAGS) \ + # -DDEBUG=false \ + # -DNDEBUG \ + # -O3 \ + # --llvm-opts 3 \ + # --llvm-lto 3 \ + # -o build/v86.wasm ls -lh build/v86.wasm build/v86-debug.wasm: src/native/*.c src/native/*.h src/native/profiler/* src/native/*.ll $(INSTRUCTION_TABLES) mkdir -p build/coverage -ls -lh build/v86-debug.wasm - emcc src/native/*.c src/native/profiler/*.c src/native/*.ll \ - $(CC_FLAGS) \ - $(CC_COVERAGE_FLAGS) \ - -Os \ - -o build/v86-debug.wasm - ls -lh build/v86-debug.wasm + #emcc src/native/*.c src/native/profiler/*.c src/native/*.ll \ + # $(CC_FLAGS) \ + # $(CC_COVERAGE_FLAGS) \ + # -Os \ + # -o build/v86-debug.wasm + #ls -lh build/v86-debug.wasm build/v86oxide.wasm: $(RUST_FILES) Cargo.toml mkdir -p build/ -ls -lh build/v86oxide.wasm cargo +nightly rustc --release $(CARGO_FLAGS) - cp build/wasm32-unknown-unknown/release/v86oxide.wasm build/v86oxide.wasm + ./tools/wasm-patch-indirect-function-table.js < build/wasm32-unknown-unknown/release/v86oxide.wasm > build/v86oxide.wasm ls -lh build/v86oxide.wasm build/v86oxide-debug.wasm: $(RUST_FILES) Cargo.toml mkdir -p build/ -ls -lh build/v86oxide-debug.wasm cargo +nightly rustc $(CARGO_FLAGS) - cp build/wasm32-unknown-unknown/debug/v86oxide.wasm build/v86oxide-debug.wasm + ./tools/wasm-patch-indirect-function-table.js < build/wasm32-unknown-unknown/debug/v86oxide.wasm > build/v86oxide-debug.wasm ls -lh build/v86oxide-debug.wasm clean: diff --git a/docker/test-image/Dockerfile b/docker/test-image/Dockerfile index bb6ebfcb..02fbb8bc 100644 --- a/docker/test-image/Dockerfile +++ b/docker/test-image/Dockerfile @@ -3,7 +3,7 @@ FROM ttt43ttt/emscripten RUN \ dpkg --add-architecture i386 && \ apt-get update -qq && \ - apt-get install -y clang-tidy gcc-multilib nasm gdb unzip openjdk-8-jre wget python qemu-system-x86 && \ + apt-get install -y clang-tidy gcc-multilib nasm gdb unzip openjdk-8-jre wget python python3 qemu-system-x86 && \ wget https://nodejs.org/dist/v8.9.4/node-v8.9.4-linux-x64.tar.xz && \ tar xfv node-v8.9.4-linux-x64.tar.xz && \ rm node-v8.9.4-linux-x64.tar.xz && \ @@ -12,5 +12,6 @@ RUN \ rm ./rustup.sh && \ export PATH="$HOME/.cargo/bin:$PATH" && \ rustup toolchain install nightly && \ + rustup default nightly && \ rustup target add wasm32-unknown-unknown --toolchain nightly && \ rustup component add rustfmt-preview --toolchain nightly diff --git a/gen/generate_interpreter.js b/gen/generate_interpreter.js index 0924c0fa..9c317ac7 100755 --- a/gen/generate_interpreter.js +++ b/gen/generate_interpreter.js @@ -4,11 +4,10 @@ const fs = require("fs"); const path = require("path"); const x86_table = require("./x86_table"); -const c_ast = require("./c_ast"); -const { hex, mkdirpSync, get_switch_value, get_switch_exist, finalize_table } = require("./util"); +const rust_ast = require("./rust_ast"); +const { hex, mkdirpSync, get_switch_value, get_switch_exist, finalize_table_rust } = require("./util"); -const OUT_DIR = get_switch_value("--output-dir") || - path.join(__dirname, "..", "build"); +const OUT_DIR = path.join(__dirname, "..", "src/rust/gen/"); mkdirpSync(OUT_DIR); @@ -125,7 +124,7 @@ function gen_instruction_body(encodings, size) if(encoding.e) { - code.push("int32_t modrm_byte = read_imm8();"); + code.push("let modrm_byte = read_imm8();"); } if(has_66.length || has_F2.length || has_F3.length) @@ -134,28 +133,28 @@ function gen_instruction_body(encodings, size) if(has_66.length) { const body = gen_instruction_body_after_prefix(has_66, size); - if_blocks.push({ condition: "prefixes_ & PREFIX_66", body, }); + if_blocks.push({ condition: "prefixes_ & PREFIX_66 != 0", body, }); } if(has_F2.length) { const body = gen_instruction_body_after_prefix(has_F2, size); - if_blocks.push({ condition: "prefixes_ & PREFIX_F2", body, }); + if_blocks.push({ condition: "prefixes_ & PREFIX_F2 != 0", body, }); } if(has_F3.length) { const body = gen_instruction_body_after_prefix(has_F3, size); - if_blocks.push({ condition: "prefixes_ & PREFIX_F3", body, }); + if_blocks.push({ condition: "prefixes_ & PREFIX_F3 != 0", body, }); } const check_prefixes = encoding.sse ? "(PREFIX_66 | PREFIX_F2 | PREFIX_F3)" : "(PREFIX_F2 | PREFIX_F3)"; const else_block = { body: [].concat( - "dbg_assert((prefixes_ & " + check_prefixes + ") == 0);", + "dbg_assert!((prefixes_ & " + check_prefixes + ") == 0);", gen_instruction_body_after_prefix(no_prefix, size) ) }; return [].concat( - "int32_t prefixes_ = *prefixes;", + "let prefixes_ = *prefixes as i32;", code, { type: "if-else", @@ -206,7 +205,7 @@ function gen_instruction_body_after_prefix(encodings, size) default_case: { body: [ - "assert(false);", + "assert!(false);", "trigger_ud();", ], } @@ -366,6 +365,7 @@ function gen_table() console.assert(encoding && encoding.length); let opcode_hex = hex(opcode, 2); + let opcode_high_hex = hex(opcode | 0x100, 2); if(encoding[0].os) { @@ -374,14 +374,14 @@ function gen_table() body: gen_instruction_body(encoding, 16), }); cases.push({ - conditions: [`0x${opcode_hex}|0x100`], + conditions: [`0x${opcode_high_hex}`], body: gen_instruction_body(encoding, 32), }); } else { cases.push({ - conditions: [`0x${opcode_hex}`, `0x${opcode_hex}|0x100`], + conditions: [`0x${opcode_hex}`, `0x${opcode_high_hex}`], body: gen_instruction_body(encoding, undefined), }); } @@ -391,15 +391,28 @@ function gen_table() condition: "opcode", cases, default_case: { - body: ["assert(false);"] + body: ["assert!(false);"] }, }; if(to_generate.interpreter) { - finalize_table( + const code = [ + "use cpu2::cpu::*;", + "use cpu2::instructions::*;", + "use cpu2::instructions_0f::*;", + "use cpu2::modrm::*;", + "use cpu2::global_pointers::*;", + + "#[cfg_attr(rustfmt, rustfmt_skip)]", + "pub unsafe fn run(opcode: u32) {", + table, + "}", + ]; + + finalize_table_rust( OUT_DIR, - "interpreter", - c_ast.print_syntax_tree([table]).join("\n") + "\n" + "interpreter.rs", + rust_ast.print_syntax_tree([].concat(code)).join("\n") + "\n" ); } @@ -440,7 +453,7 @@ function gen_table() condition: "opcode", cases: cases0f_16, default_case: { - body: ["assert(false);"] + body: ["assert!(false);"] }, }; const table0f_32 = { @@ -448,25 +461,51 @@ function gen_table() condition: "opcode", cases: cases0f_32, default_case: { - body: ["assert(false);"] + body: ["assert!(false);"] }, }; if(to_generate.interpreter0f_16) { - finalize_table( + const code = [ + "use cpu2::cpu::*;", + "use cpu2::instructions::*;", + "use cpu2::instructions_0f::*;", + "use cpu2::modrm::*;", + "use cpu2::global_pointers::*;", + + "#[cfg_attr(rustfmt, rustfmt_skip)]", + "pub unsafe fn run(opcode: u8) {", + table0f_16, + "}", + ]; + + finalize_table_rust( OUT_DIR, - "interpreter0f_16", - c_ast.print_syntax_tree([table0f_16]).join("\n") + "\n" + "interpreter0f_16.rs", + rust_ast.print_syntax_tree([].concat(code)).join("\n") + "\n" ); } if(to_generate.interpreter0f_32) { - finalize_table( + const code = [ + "use cpu2::cpu::*;", + "use cpu2::instructions::*;", + "use cpu2::instructions_0f::*;", + "use cpu2::modrm::*;", + "use cpu2::global_pointers::*;", + + "#[cfg_attr(rustfmt, rustfmt_skip)]", + "pub unsafe fn run(opcode: u8) {", + table0f_32, + "}", + ]; + + finalize_table_rust( OUT_DIR, - "interpreter0f_32", - c_ast.print_syntax_tree([table0f_32]).join("\n") + "\n" + "interpreter0f_32.rs", + rust_ast.print_syntax_tree([].concat(code)).join("\n") + "\n" ); } } diff --git a/src/browser/serial.js b/src/browser/serial.js index 1ca3c17a..dd5af3b0 100644 --- a/src/browser/serial.js +++ b/src/browser/serial.js @@ -79,7 +79,7 @@ function SerialAdapter(element, bus) this.update_timer = setTimeout(() => { this.update_timer = undefined; var now = Date.now(); - dbg_assert(now - this.last_update >= 16); + dbg_assert(now - this.last_update >= 15); this.last_update = now; this.render(); }, 16 - delta); diff --git a/src/browser/starter.js b/src/browser/starter.js index 9cb866bb..4810f5ee 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -94,21 +94,22 @@ function V86Starter(options) this.emulator_bus = bus[1]; var emulator; var cpu; - var mem; - var mem8; + var v86oxide; const coverage_logger = new CoverageLogger(); - if(coverage_logger.ENABLED) - { - this.bus.register("emulator-stopped", function() - { - coverage_logger.dump_to_files(); - }, this); - } + //if(coverage_logger.ENABLED) + //{ + // this.bus.register("emulator-stopped", function() + // { + // coverage_logger.dump_to_files(); + // }, this); + //} + + const wasm_table = new WebAssembly.Table({ element: "anyfunc", initial: 0x10000 + 0x100 }); var wasm_shared_funcs = { - "___assert_fail": (condition, file, line, fun) => { - const memory = mem8; + "__assert_fail": (condition, file, line, fun) => { + const memory = new Uint8Array(v86oxide.exports.memory.buffer); function read_string(memory, offset) { @@ -130,88 +131,90 @@ function V86Starter(options) dbg_assert(false); }, - "_throw_cpu_exception": () => { + "throw_cpu_exception": () => { throw MAGIC_CPU_EXCEPTION; }, - "_cpu_exception_hook": (n) => { + "cpu_exception_hook": (n) => { return this["cpu_exception_hook"] && this["cpu_exception_hook"](n); }, - "_hlt_op": function() { return cpu.hlt_op(); }, + "hlt_op": function() { return cpu.hlt_op(); }, "abort": function() { dbg_assert(false); }, - "__dbg_trace": function() { return dbg_trace(); }, - "_logop": function(eip, op) { return cpu.debug.logop(eip, op); }, - "_undefined_instruction": function() { return cpu.undefined_instruction.apply(cpu, arguments); }, - "_unimplemented_sse": function() { return cpu.unimplemented_sse(); }, - "_microtick": v86.microtick, - "_get_rand_int": function() { return v86util.get_rand_int(); }, - "_has_rand_int": function() { return v86util.has_rand_int(); }, - "_printf": function(format_string_offset, stack_top) { + "_dbg_trace": function() { return dbg_trace(); }, + "logop": function(eip, op) { return cpu.debug.logop(eip, op); }, + "undefined_instruction": function() { return cpu.undefined_instruction.apply(cpu, arguments); }, + "unimplemented_sse": function() { return cpu.unimplemented_sse(); }, + "microtick": v86.microtick, + "get_rand_int": function() { return v86util.get_rand_int(); }, + "has_rand_int": function() { return v86util.has_rand_int(); }, + "printf": function(format_string_offset, stack_top) { dbg_assert(arguments.length === 2); - dbg_log_wasm(mem, format_string_offset, stack_top); + dbg_log_wasm(v86oxide.exports.memory.buffer, format_string_offset, stack_top); }, - "_memcpy_large": function(dest, source, length) { + "memcpy_large": function(dest, source, length) { + const mem8 = new Uint8Array(v86oxide.exports.memory.buffer); mem8.set(mem8.subarray(source, source + length), dest); return dest; }, - "_memcpy": function(dest, source, length) { + "memcpy": function(dest, source, length) { + const mem8 = new Uint8Array(v86oxide.exports.memory.buffer); mem8.set(mem8.subarray(source, source + length), dest); return dest; }, - "_call_interrupt_vector": function(interrupt_nr, is_software_int, has_error_code, error_code) { + "call_interrupt_vector": function(interrupt_nr, is_software_int, has_error_code, error_code) { cpu.call_interrupt_vector(interrupt_nr, is_software_int, !!has_error_code, error_code); }, - "_far_jump": function(eip, selector, is_call) { return cpu.far_jump(eip, selector, !!is_call); }, - "_far_return": function(eip, selector, stack_adjust) { return cpu.far_return(eip, selector, stack_adjust); }, - "_switch_seg": function(reg, selector) { return cpu.switch_seg(reg, selector); }, - "_iret16": function() { return cpu.iret16(); }, - "_iret32": function() { return cpu.iret32(); }, - "_handle_irqs": function() { return cpu.handle_irqs(); }, + "far_jump": function(eip, selector, is_call) { return cpu.far_jump(eip, selector, !!is_call); }, + "far_return": function(eip, selector, stack_adjust) { return cpu.far_return(eip, selector, stack_adjust); }, + "switch_seg": function(reg, selector) { return cpu.switch_seg(reg, selector); }, + "iret16": function() { return cpu.iret16(); }, + "iret32": function() { return cpu.iret32(); }, + "handle_irqs": function() { return cpu.handle_irqs(); }, - "_io_port_read8": function(addr) { return cpu.io.port_read8(addr); }, - "_io_port_read16": function(addr) { return cpu.io.port_read16(addr); }, - "_io_port_read32": function(addr) { return cpu.io.port_read32(addr); }, - "_io_port_write8": function(addr, value) { cpu.io.port_write8(addr, value); }, - "_io_port_write16": function(addr, value) { cpu.io.port_write16(addr, value); }, - "_io_port_write32": function(addr, value) { cpu.io.port_write32(addr, value); }, + "io_port_read8": function(addr) { return cpu.io.port_read8(addr); }, + "io_port_read16": function(addr) { return cpu.io.port_read16(addr); }, + "io_port_read32": function(addr) { return cpu.io.port_read32(addr); }, + "io_port_write8": function(addr, value) { cpu.io.port_write8(addr, value); }, + "io_port_write16": function(addr, value) { cpu.io.port_write16(addr, value); }, + "io_port_write32": function(addr, value) { cpu.io.port_write32(addr, value); }, - "_mmap_read8": function(addr) { return cpu.mmap_read8(addr); }, - "_mmap_read16": function(addr) { return cpu.mmap_read16(addr); }, - "_mmap_read32": function(addr) { return cpu.mmap_read32(addr); }, - "_mmap_write8": function(addr, value) { return cpu.mmap_write8(addr, value); }, - "_mmap_write16": function(addr, value) { return cpu.mmap_write16(addr, value); }, - "_mmap_write32": function(addr, value) { return cpu.mmap_write32(addr, value); }, - "_mmap_write128": function(addr, value0, value1, value2, value3) { return cpu.mmap_write128(addr, value0, value1, value2, value3); }, + "mmap_read8": function(addr) { return cpu.mmap_read8(addr); }, + "mmap_read16": function(addr) { return cpu.mmap_read16(addr); }, + "mmap_read32": function(addr) { return cpu.mmap_read32(addr); }, + "mmap_write8": function(addr, value) { return cpu.mmap_write8(addr, value); }, + "mmap_write16": function(addr, value) { return cpu.mmap_write16(addr, value); }, + "mmap_write32": function(addr, value) { return cpu.mmap_write32(addr, value); }, + "mmap_write128": function(addr, value0, value1, value2, value3) { return cpu.mmap_write128(addr, value0, value1, value2, value3); }, - "_int_log2": function(val) { return v86util.int_log2(val); }, + "int_log2": function(val) { return v86util.int_log2(val); }, - "_popa16": function() { return cpu.popa16.apply(cpu, arguments); }, - "_popa32": function() { return cpu.popa32.apply(cpu, arguments); }, - "_arpl": function() { return cpu.arpl.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); }, - "_bswap": function() { return cpu.bswap.apply(cpu, arguments); }, + "bswap": function() { return cpu.bswap.apply(cpu, arguments); }, - "_lar": function() { return cpu.lar.apply(cpu, arguments); }, - "_lsl": function() { return cpu.lsl.apply(cpu, arguments); }, - "_verw": function() { return cpu.verw.apply(cpu, arguments); }, - "_verr": function() { return cpu.verr.apply(cpu, arguments); }, + "lar": function() { return cpu.lar.apply(cpu, arguments); }, + "lsl": function() { return cpu.lsl.apply(cpu, arguments); }, + "verw": function() { return cpu.verw.apply(cpu, arguments); }, + "verr": function() { return cpu.verr.apply(cpu, arguments); }, - "_cpl_changed": function() { return cpu.cpl_changed.apply(cpu, arguments); }, - "_set_cr0": function() { return cpu.set_cr0.apply(cpu, arguments); }, - "_update_cs_size": function() { return cpu.update_cs_size.apply(cpu, arguments); }, - "_cpuid": function() { return cpu.cpuid.apply(cpu, arguments); }, + "cpl_changed": function() { return cpu.cpl_changed.apply(cpu, arguments); }, + "set_cr0": function() { return cpu.set_cr0.apply(cpu, arguments); }, + "update_cs_size": function() { return cpu.update_cs_size.apply(cpu, arguments); }, + "cpuid": function() { return cpu.cpuid.apply(cpu, arguments); }, - "_load_ldt": function() { return cpu.load_ldt.apply(cpu, arguments); }, - "_load_tr": function() { return cpu.load_tr.apply(cpu, arguments); }, + "load_ldt": function() { return cpu.load_ldt.apply(cpu, arguments); }, + "load_tr": function() { return cpu.load_tr.apply(cpu, arguments); }, - "_lss16": function() { return cpu.lss16.apply(cpu, arguments); }, - "_lss32": function() { return cpu.lss32.apply(cpu, arguments); }, - "_enter16": function() { return cpu.enter16.apply(cpu, arguments); }, - "_enter32": function() { return cpu.enter32.apply(cpu, arguments); }, + "lss16": function() { return cpu.lss16.apply(cpu, arguments); }, + "lss32": function() { return cpu.lss32.apply(cpu, arguments); }, + "enter16": function() { return cpu.enter16.apply(cpu, arguments); }, + "enter32": function() { return cpu.enter32.apply(cpu, arguments); }, - "_test_privileges_for_io": function() { return cpu.test_privileges_for_io.apply(cpu, arguments); }, + "test_privileges_for_io": function() { return cpu.test_privileges_for_io.apply(cpu, arguments); }, - "_convert_f64_to_i32": function(f) { + "convert_f64_to_i32": function(f) { // implemented here due to emscripten bug if(!(f <= 0x7FFFFFFF && f >= -0x80000000)) { @@ -220,30 +223,37 @@ function V86Starter(options) return f | 0; }, - "_get_time": Date.now, + "get_time": Date.now, - "_coverage_log": (fn_name_offset, num_blocks, visited_block) => { - coverage_logger.log(fn_name_offset, num_blocks, visited_block); + "coverage_log": (fn_name_offset, num_blocks, visited_block) => { + //coverage_logger.log(fn_name_offset, num_blocks, visited_block); }, // see https://github.com/kripken/emscripten/blob/incoming/src/library.js - "_atan2": Math.atan2, - "_sin": Math.sin, - "_cos": Math.cos, - "_tan": Math.tan, - "_trunc": Math.trunc, - "_fmod": (x, y) => x % y, - "_llvm_exp2_f64": (x) => Math.pow(2, x), - "_log": Math.log, - "_round": Math.round, - "_ldexp": function(x, exp) { + "atan2": Math.atan2, + "sin": Math.sin, + "cos": Math.cos, + "tan": Math.tan, + "trunc": Math.trunc, + "fmod": (x, y) => x % y, + "llvm_exp2_f64": (x) => Math.pow(2, x), + "log": Math.log, + "round": Math.round, + "ldexp": function(x, exp) { return x * Math.pow(2, exp); }, - "_llvm_round_f64": function(d) { + "llvm_round_f64": function(d) { d = +d; return d >= +0 ? +Math.floor(d + 0.5) : +Math.ceil(d - 0.5); }, - "_llvm_trunc_f64": Math.trunc, + "llvm_trunc_f64": Math.trunc, + + "log_from_wasm": function(offset, len) { + const str = v86util.read_sized_string_from_mem(v86oxide.exports.memory, offset, len); + dbg_log(str, LOG_CPU); + }, + "codegen_finalize": (wasm_table_index, start, end, first_opcode, state_flags) => cpu.codegen_finalize(wasm_table_index, start, end, first_opcode, state_flags), + "__indirect_function_table": wasm_table, }; const wasm_globals = { @@ -251,25 +261,16 @@ function V86Starter(options) "NaN": NaN, }; - const v86oxide_mem = new WebAssembly.Memory({ "initial": 250 }); - const v86oxide_externs = { - "memory": v86oxide_mem, - "log_from_wasm": function(offset, len) { - const str = v86util.read_sized_string_from_mem(v86oxide_mem, offset, len); - dbg_log(str, LOG_CPU); - }, - "abort": function() { - dbg_assert(false); - }, - - "read8": addr => cpu.read8(addr), - "read16": addr => cpu.read16(addr), - "read32": addr => cpu.read32s(addr), - "tlb_set_has_code": (page, has_code) => cpu.wm.exports["_tlb_set_has_code"](page, has_code), - "check_tlb_invariants": () => cpu.wm.exports["_check_tlb_invariants"](), - "codegen_finalize": (wasm_table_index, start, end, first_opcode, state_flags) => cpu.codegen_finalize(wasm_table_index, start, end, first_opcode, state_flags), - "profiler_stat_increment": (name) => cpu.wm.exports["_profiler_stat_increment"](name), - }; + //const v86oxide_mem = new WebAssembly.Memory({ "initial": 250 }); + //const v86oxide_externs = { + // "memory": v86oxide_mem, + // "read8": addr => cpu.read8(addr), + // "read16": addr => cpu.read16(addr), + // "read32": addr => cpu.read32s(addr), + // "tlb_set_has_code": (page, has_code) => cpu.wm.exports["_tlb_set_has_code"](page, has_code), + // "check_tlb_invariants": () => cpu.wm.exports["_check_tlb_invariants"](), + // "profiler_stat_increment": (name) => cpu.wm.exports["_profiler_stat_increment"](name), + //}; let wasm_file = DEBUG ? "v86-debug.wasm" : "v86.wasm"; let v86oxide_bin = DEBUG ? "v86oxide-debug.wasm" : "v86oxide.wasm"; @@ -304,28 +305,38 @@ function V86Starter(options) "jit_dirty_cache", ]; - v86util.minimal_load_wasm(v86oxide_bin, { "env": v86oxide_externs }, (v86oxide) => { - for(const fn_name of v86oxide_exports) - { - dbg_assert(typeof v86oxide.exports[fn_name] === "function", `Function ${fn_name} not found in v86oxide exports`); - wasm_shared_funcs[`_${fn_name}`] = v86oxide.exports[fn_name]; - } + v86util.minimal_load_wasm(v86oxide_bin, { "env": wasm_shared_funcs }, (v86oxide_) => { + v86oxide = v86oxide_; + //for(const fn_name of v86oxide_exports) + //{ + // dbg_assert(typeof v86oxide.exports[fn_name] === "function", `Function ${fn_name} not found in v86oxide exports`); + // wasm_shared_funcs[`_${fn_name}`] = v86oxide.exports[fn_name]; + //} v86oxide.exports["rust_setup"](); + //v86oxide.exports[WASM_EXPORT_TABLE_NAME].grow(WASM_TABLE_SIZE); + + const wm = v86oxide; + + //mem = v86oxide.exports.memory.buffer; + //mem8 = new Uint8Array(mem); + emulator = this.v86 = new v86(this.emulator_bus, wm, v86oxide, coverage_logger); + cpu = emulator.cpu; + //XXX: fix indentation break - v86util.load_wasm( - wasm_file, - { "env": wasm_shared_funcs, "global" : wasm_globals }, - options["memory_size"] + GUEST_MEMORY_START, - WASM_TABLE_SIZE, - wm => { - mem = wm.memory.buffer; - mem8 = new Uint8Array(mem); - wm.instance.exports["__post_instantiate"](); - coverage_logger.init(wm); - emulator = this.v86 = new v86(this.emulator_bus, wm, v86oxide, coverage_logger); - cpu = emulator.cpu; + //v86util.load_wasm( + // wasm_file, + // { "env": wasm_shared_funcs, "global" : wasm_globals }, + // options["memory_size"] + GUEST_MEMORY_START, + // WASM_TABLE_SIZE, + // wm => { + // mem = wm.memory.buffer; + // mem8 = new Uint8Array(mem); + // wm.instance.exports["__post_instantiate"](); + // coverage_logger.init(wm); + // emulator = this.v86 = new v86(this.emulator_bus, wm, v86oxide, coverage_logger); + // cpu = emulator.cpu; // XXX: Leaving unindented to minimize diff; still a part of the cb to load_wasm! this.bus.register("emulator-stopped", function() @@ -671,7 +682,7 @@ function V86Starter(options) }.bind(this), 0); } - }); + //}); }); } diff --git a/src/const.js b/src/const.js index 2e6cfda5..c300bc73 100644 --- a/src/const.js +++ b/src/const.js @@ -362,7 +362,7 @@ var WASM_TABLE_SIZE = 0x10000; var JIT_CACHE_ARRAY_SIZE = 0x40000; /** @const */ -const WASM_EXPORT_TABLE_NAME = "table"; +const WASM_EXPORT_TABLE_NAME = "__indirect_function_table"; /** @const */ diff --git a/src/cpu.js b/src/cpu.js index 5db958b2..39b12be5 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -19,46 +19,64 @@ function CPU(bus, wm, v86oxide, coverage_logger) this.wasm_patch(wm); this.create_jit_imports(); - this.memory_size = new Uint32Array(wm.memory.buffer, 812, 1); + const memory = v86oxide.instance.exports.memory; + + Object.defineProperty(this, "memory_size", { get: () => { return new Uint32Array(memory.buffer, 812, 1); } }); + if(false) this.memory_size = new Uint32Array(memory.buffer, 812, 1); // Note: Currently unused (degrades performance and not required by any OS // that we support) - this.a20_enabled = new Int32Array(wm.memory.buffer, 552, 1); + if(false) this.a20_enabled = new Int32Array(memory.buffer, 552, 1); + Object.defineProperty(this, "a20_enabled", { get: () => { return new Int32Array(memory.buffer, 552, 1); } }); this.a20_enabled[0] = +true; - this.mem_page_infos = undefined; + if(false) this.mem8 = new Uint8Array(0); + if(false) this.mem16 = new Uint16Array(this.mem8.buffer); + if(false) this.mem32s = new Int32Array(this.mem8.buffer); - this.mem8 = new Uint8Array(0); - this.mem16 = new Uint16Array(this.mem8.buffer); - this.mem32s = new Int32Array(this.mem8.buffer); + Object.defineProperty(this, "mem8", { get: () => { return new Uint8Array(memory.buffer, GUEST_MEMORY_START, this.memory_size[0]); } }); + Object.defineProperty(this, "mem16", { get: () => { return new Uint16Array(memory.buffer, GUEST_MEMORY_START, this.memory_size[0] >> 1); } }); + Object.defineProperty(this, "mem32s", { get: () => { return new Int32Array(memory.buffer, GUEST_MEMORY_START, this.memory_size[0] >> 2); } }); - this.segment_is_null = new Uint8Array(wm.memory.buffer, 724, 8); - this.segment_offsets = new Int32Array(wm.memory.buffer, 736, 8); - this.segment_limits = new Uint32Array(wm.memory.buffer, 768, 8); - //this.segment_infos = []; + if(false) this.segment_is_null = new Uint8Array(memory.buffer, 724, 8); + Object.defineProperty(this, "segment_is_null", { get: () => { return new Uint8Array(memory.buffer, 724, 8); } }); + + if(false) this.segment_offsets = new Int32Array(memory.buffer, 736, 8); + Object.defineProperty(this, "segment_offsets", { get: () => { return new Int32Array(memory.buffer, 736, 8); } }); + + if(false) this.segment_limits = new Uint32Array(memory.buffer, 768, 8); + Object.defineProperty(this, "segment_limits", { get: () => { return new Uint32Array(memory.buffer, 768, 8); } }); /** * Wheter or not in protected mode */ - this.protected_mode = new Int32Array(wm.memory.buffer, 800, 1); + if(false) this.protected_mode = new Int32Array(memory.buffer, 800, 1); + Object.defineProperty(this, "protected_mode", { get: () => { return new Int32Array(memory.buffer, 800, 1); } }); - this.idtr_size = new Int32Array(wm.memory.buffer, 564, 1); - this.idtr_offset = new Int32Array(wm.memory.buffer, 568, 1); + if(false) this.idtr_size = new Int32Array(memory.buffer, 564, 1); + if(false) this.idtr_offset = new Int32Array(memory.buffer, 568, 1); + Object.defineProperty(this, "idtr_size", { get: () => { return new Int32Array(memory.buffer, 564, 1); } }); + Object.defineProperty(this, "idtr_offset", { get: () => { return new Int32Array(memory.buffer, 568, 1); } }); /** * global descriptor table register */ - this.gdtr_size = new Int32Array(wm.memory.buffer, 572, 1); - this.gdtr_offset = new Int32Array(wm.memory.buffer, 576, 1); + if(false) this.gdtr_size = new Int32Array(memory.buffer, 572, 1); + if(false) this.gdtr_offset = new Int32Array(memory.buffer, 576, 1); + + Object.defineProperty(this, "gdtr_size", { get: () => { return new Int32Array(memory.buffer, 572, 1); } }); + Object.defineProperty(this, "gdtr_offset", { get: () => { return new Int32Array(memory.buffer, 576, 1); } }); this.tss_size_32 = false; /* * whether or not a page fault occured */ - this.page_fault = new Uint32Array(wm.memory.buffer, 540, 8); + if(false) this.page_fault = new Uint32Array(memory.buffer, 540, 8); + Object.defineProperty(this, "page_fault", { get: () => { return new Uint32Array(memory.buffer, 540, 8); } }); - this.cr = new Int32Array(wm.memory.buffer, 580, 8); + if(false) this.cr = new Int32Array(memory.buffer, 580, 8); + Object.defineProperty(this, "cr", { get: () => { return new Int32Array(memory.buffer, 580, 8); } }); /** @type {number} */ this.cr[0] = 0; @@ -70,62 +88,76 @@ function CPU(bus, wm, v86oxide, coverage_logger) this.cr[4] = 0; // current privilege level - this.cpl = new Int32Array(wm.memory.buffer, 612, 1); + if(false) this.cpl = new Int32Array(memory.buffer, 612, 1); + Object.defineProperty(this, "cpl", { get: () => { return new Int32Array(memory.buffer, 612, 1); } }); // current operand/address size - this.is_32 = new Int32Array(wm.memory.buffer, 804, 1); + if(false) this.is_32 = new Int32Array(memory.buffer, 804, 1); + Object.defineProperty(this, "is_32", { get: () => { return new Int32Array(memory.buffer, 804, 1); } }); - this.stack_size_32 = new Int32Array(wm.memory.buffer, 808, 1); + if(false) this.stack_size_32 = new Int32Array(memory.buffer, 808, 1); + Object.defineProperty(this, "stack_size_32", { get: () => { return new Int32Array(memory.buffer, 808, 1); } }); /** * Was the last instruction a hlt? */ - this.in_hlt = new Uint8Array(wm.memory.buffer, 616, 1); + if(false) this.in_hlt = new Uint8Array(memory.buffer, 616, 1); + Object.defineProperty(this, "in_hlt", { get: () => { return new Uint8Array(memory.buffer, 616, 1); } }); - this.last_virt_eip = new Int32Array(wm.memory.buffer, 620, 1); + this.last_virt_eip = new Int32Array(memory.buffer, 620, 1); - this.eip_phys = new Int32Array(wm.memory.buffer, 624, 1); + this.eip_phys = new Int32Array(memory.buffer, 624, 1); - this.last_virt_esp = new Int32Array(wm.memory.buffer, 628, 1); + this.last_virt_esp = new Int32Array(memory.buffer, 628, 1); - this.esp_phys = new Int32Array(wm.memory.buffer, 632, 1); + this.esp_phys = new Int32Array(memory.buffer, 632, 1); - this.sysenter_cs = new Int32Array(wm.memory.buffer, 636, 1); + this.sysenter_cs = new Int32Array(memory.buffer, 636, 1); - this.sysenter_esp = new Int32Array(wm.memory.buffer, 640, 1); + this.sysenter_esp = new Int32Array(memory.buffer, 640, 1); - this.sysenter_eip = new Int32Array(wm.memory.buffer, 644, 1); + this.sysenter_eip = new Int32Array(memory.buffer, 644, 1); - this.prefixes = new Int32Array(wm.memory.buffer, 648, 1); + if(false) this.prefixes = new Int32Array(memory.buffer, 648, 1); + Object.defineProperty(this, "prefixes", { get: () => { return new Int32Array(memory.buffer, 648, 1); } }); - this.flags = new Int32Array(wm.memory.buffer, 536, 1); + if(false) this.flags = new Int32Array(memory.buffer, 536, 1); + Object.defineProperty(this, "flags", { get: () => { return new Int32Array(memory.buffer, 536, 1); } }); /** * bitmap of flags which are not updated in the flags variable * changed by arithmetic instructions, so only relevant to arithmetic flags */ - this.flags_changed = new Int32Array(wm.memory.buffer, 532, 1); + if(false) this.flags_changed = new Int32Array(memory.buffer, 532, 1); + Object.defineProperty(this, "flags_changed", { get: () => { return new Int32Array(memory.buffer, 532, 1); } }); /** * the last 2 operators and the result and size of the last arithmetic operation */ - this.last_op1 = new Int32Array(wm.memory.buffer, 512, 1); - this.last_op2 = new Int32Array(wm.memory.buffer, 516, 1); - this.last_op_size = new Int32Array(wm.memory.buffer, 520, 1); + if(false) this.last_op1 = new Int32Array(memory.buffer, 512, 1); + Object.defineProperty(this, "last_op1", { get: () => { return new Int32Array(memory.buffer, 512, 1); } }); + if(false) this.last_op2 = new Int32Array(memory.buffer, 516, 1); + Object.defineProperty(this, "last_op2", { get: () => { return new Int32Array(memory.buffer, 516, 1); } }); + if(false) this.last_op_size = new Int32Array(memory.buffer, 520, 1); + Object.defineProperty(this, "last_op_size", { get: () => { return new Int32Array(memory.buffer, 520, 1); } }); - this.last_add_result = new Int32Array(wm.memory.buffer, 524, 1); + if(false) this.last_add_result = new Int32Array(memory.buffer, 524, 1); + Object.defineProperty(this, "last_add_result", { get: () => { return new Int32Array(memory.buffer, 524, 1); } }); - this.last_result = new Int32Array(wm.memory.buffer, 528, 1); + if(false) this.last_result = new Int32Array(memory.buffer, 528, 1); + Object.defineProperty(this, "last_result", { get: () => { return new Int32Array(memory.buffer, 528, 1); } }); - this.current_tsc = new Uint32Array(wm.memory.buffer, 956, 2); // 64 bit + this.current_tsc = new Uint32Array(memory.buffer, 956, 2); // 64 bit /** @type {!Object} */ this.devices = {}; - this.instruction_pointer = new Int32Array(wm.memory.buffer, 556, 1); + if(false) this.instruction_pointer = new Int32Array(memory.buffer, 556, 1); + Object.defineProperty(this, "instruction_pointer", { get: () => { return new Int32Array(memory.buffer, 556, 1); } }); - this.previous_ip = new Int32Array(wm.memory.buffer, 560, 1); + if(false) this.previous_ip = new Int32Array(memory.buffer, 560, 1); + Object.defineProperty(this, "previous_ip", { get: () => { return new Int32Array(memory.buffer, 560, 1); } }); this.apic_enabled = true; @@ -144,56 +176,64 @@ function CPU(bus, wm, v86oxide, coverage_logger) vga: null, }; - this.timestamp_counter = new Uint32Array(wm.memory.buffer, 664, 1); + Object.defineProperty(this, "timestamp_counter", { get: () => { return new Int32Array(memory.buffer, 664, 1); } }); + if(false) this.timestamp_counter = new Uint32Array(memory.buffer, 664, 1); // registers - this.reg32s = new Int32Array(wm.memory.buffer, 4, 8); - this.reg32 = new Uint32Array(this.reg32s.buffer, 4, 8); - this.reg16s = new Int16Array(this.reg32s.buffer, 4, 16); - this.reg16 = new Uint16Array(this.reg32s.buffer, 4, 16); - this.reg8s = new Int8Array(this.reg32s.buffer, 4, 32); - this.reg8 = new Uint8Array(this.reg32s.buffer, 4, 32); + if(false) this.reg32s = new Int32Array(memory.buffer, 4, 8); + if(false) this.reg32 = new Uint32Array(this.reg32s.buffer, 4, 8); + if(false) this.reg16s = new Int16Array(this.reg32s.buffer, 4, 16); + if(false) this.reg16 = new Uint16Array(this.reg32s.buffer, 4, 16); + if(false) this.reg8s = new Int8Array(this.reg32s.buffer, 4, 32); + if(false) this.reg8 = new Uint8Array(this.reg32s.buffer, 4, 32); + Object.defineProperty(this, "reg32s", { get: () => { return new Int32Array(memory.buffer, 4, 8); } }); + Object.defineProperty(this, "reg32", { get: () => { return new Uint32Array(memory.buffer, 4, 8); } }); + Object.defineProperty(this, "reg16s", { get: () => { return new Int16Array(memory.buffer, 4, 16); } }); + Object.defineProperty(this, "reg16", { get: () => { return new Uint16Array(memory.buffer, 4, 16); } }); + Object.defineProperty(this, "reg8s", { get: () => { return new Int8Array(memory.buffer, 4, 32); } }); + Object.defineProperty(this, "reg8", { get: () => { return new Uint8Array(memory.buffer, 4, 32); } }); // Why no Float80Array :-( - this.fpu_st = new Float64Array(wm.memory.buffer, 968, 8); + this.fpu_st = new Float64Array(memory.buffer, 968, 8); - this.fpu_stack_empty = new Int32Array(wm.memory.buffer, 816, 1); + this.fpu_stack_empty = new Int32Array(memory.buffer, 816, 1); this.fpu_stack_empty[0] = 0xff; - this.fpu_stack_ptr = new Uint32Array(wm.memory.buffer, 1032, 1); + this.fpu_stack_ptr = new Uint32Array(memory.buffer, 1032, 1); this.fpu_stack_ptr[0] = 0; - this.fpu_control_word = new Int32Array(wm.memory.buffer, 1036, 1); + this.fpu_control_word = new Int32Array(memory.buffer, 1036, 1); this.fpu_control_word[0] = 0x37F; - this.fpu_status_word = new Int32Array(wm.memory.buffer, 1040, 1); + this.fpu_status_word = new Int32Array(memory.buffer, 1040, 1); this.fpu_status_word[0] = 0; - this.fpu_ip = new Int32Array(wm.memory.buffer, 1048, 1); + this.fpu_ip = new Int32Array(memory.buffer, 1048, 1); this.fpu_ip[0] = 0; - this.fpu_ip_selector = new Int32Array(wm.memory.buffer, 1052, 1); + this.fpu_ip_selector = new Int32Array(memory.buffer, 1052, 1); this.fpu_ip_selector[0] = 0; - this.fpu_opcode = new Int32Array(wm.memory.buffer, 1044, 1); + this.fpu_opcode = new Int32Array(memory.buffer, 1044, 1); this.fpu_opcode[0] = 0; - this.fpu_dp = new Int32Array(wm.memory.buffer, 1056, 1); + this.fpu_dp = new Int32Array(memory.buffer, 1056, 1); this.fpu_dp[0] = 0; - this.fpu_dp_selector = new Int32Array(wm.memory.buffer, 1060, 1); + this.fpu_dp_selector = new Int32Array(memory.buffer, 1060, 1); this.fpu_dp_selector[0] = 0; // mm0-mm7 split up into 32 bit pairs - this.reg_mmxs = new Int32Array(wm.memory.buffer, 1064, 16); + this.reg_mmxs = new Int32Array(memory.buffer, 1064, 16); this.reg_mmx = new Uint32Array(this.reg_mmxs.buffer, 1064, 16); this.reg_mmx8s = new Int8Array(this.reg_mmxs.buffer, 1064, 64); this.reg_mmx8 = new Uint8Array(this.reg_mmxs.buffer, 1064, 64); - this.reg_xmm32s = new Int32Array(wm.memory.buffer, 828, 8 * 4); + this.reg_xmm32s = new Int32Array(memory.buffer, 828, 8 * 4); - this.mxcsr = new Int32Array(wm.memory.buffer, 824, 1); + this.mxcsr = new Int32Array(memory.buffer, 824, 1); // segment registers, tr and ldtr - this.sreg = new Uint16Array(wm.memory.buffer, 668, 8); + if(false) this.sreg = new Uint16Array(memory.buffer, 668, 8); + Object.defineProperty(this, "sreg", { get: () => { return new Uint16Array(memory.buffer, 668, 8); } }); // debug registers - this.dreg = new Int32Array(wm.memory.buffer, 684, 8); + this.dreg = new Int32Array(memory.buffer, 684, 8); - this.fw_value = new Int32Array(wm.memory.buffer, 720, 1); + this.fw_value = new Int32Array(memory.buffer, 720, 1); this.io = undefined; @@ -213,7 +253,7 @@ CPU.prototype.wasmgen_get_module_code = function() const ptr = this.jit_get_op_ptr(); const len = this.jit_get_op_len(); - const output_buffer_view = new Uint8Array(this.v86oxide.memory.buffer, ptr, len); + const output_buffer_view = new Uint8Array(this.v86oxide.instance.exports.memory.buffer, ptr, len); return output_buffer_view; }; @@ -228,18 +268,21 @@ CPU.prototype.create_jit_imports = function() } // put all imports that don't change on the prototype - JITImports.prototype["m"] = this.wm.memory; + JITImports.prototype["m"] = this.v86oxide.memory; - const exports = this.wm.instance.exports; + const exports = this.v86oxide.instance.exports; + + JITImports.prototype["m"] = exports["memory"]; for(let name of Object.keys(exports)) { - if(name[0] !== "_") - { - continue; - } + //if(name[0] !== "_") + //{ + // continue; + //} - JITImports.prototype[name.slice(1)] = exports[name]; + //JITImports.prototype[name.slice(1)] = exports[name]; + JITImports.prototype[name] = exports[name]; } this.jit_imports = new JITImports(); @@ -247,56 +290,57 @@ CPU.prototype.create_jit_imports = function() CPU.prototype.wasm_patch = function(wm) { - this.getiopl = this.wm.exports["_getiopl"]; - this.vm86_mode = this.wm.exports["_vm86_mode"]; - this.get_eflags = this.wm.exports["_get_eflags"]; - this.update_eflags = this.wm.exports["_update_eflags"]; + this.getiopl = this.v86oxide.exports["getiopl"]; + this.vm86_mode = this.v86oxide.exports["vm86_mode"]; + this.get_eflags = this.v86oxide.exports["get_eflags"]; + this.update_eflags = this.v86oxide.exports["update_eflags"]; - this.trigger_gp_non_raising = this.wm.exports["_trigger_gp_non_raising"]; - this.trigger_ud = this.wm.exports["_trigger_ud"]; - this.trigger_np = this.wm.exports["_trigger_np"]; - this.trigger_ss = this.wm.exports["_trigger_ss"]; + this.trigger_gp_non_raising = this.v86oxide.exports["trigger_gp_non_raising"]; + this.trigger_ud = this.v86oxide.exports["trigger_ud"]; + this.trigger_np = this.v86oxide.exports["trigger_np"]; + this.trigger_ss = this.v86oxide.exports["trigger_ss"]; - this.do_many_cycles_unsafe = this.wm.exports["_do_many_cycles_unsafe"]; - this.cycle_internal = this.wm.exports["_cycle_internal"]; + //this.do_many_cycles_unsafe = this.wm.exports["_do_many_cycles_unsafe"]; + this.do_many_cycles_unsafe = this.v86oxide.exports["do_many_cycles_unsafe"]; + this.cycle_internal = this.v86oxide.exports["cycle_internal"]; - this.read8 = this.wm.exports["_read8"]; - this.read16 = this.wm.exports["_read16"]; - this.read32s = this.wm.exports["_read32s"]; - this.write8 = this.wm.exports["_write8"]; - this.write16 = this.wm.exports["_write16"]; - this.write32 = this.wm.exports["_write32"]; - this.in_mapped_range = this.wm.exports["_in_mapped_range"]; + this.read8 = this.v86oxide.exports["read8"]; + this.read16 = this.v86oxide.exports["read16"]; + this.read32s = this.v86oxide.exports["read32s"]; + this.write8 = this.v86oxide.exports["write8"]; + this.write16 = this.v86oxide.exports["write16"]; + this.write32 = this.v86oxide.exports["write32"]; + this.in_mapped_range = this.v86oxide.exports["in_mapped_range"]; - this.push16 = this.wm.exports["_push16"]; - this.push32 = this.wm.exports["_push32"]; - this.pop16 = this.wm.exports["_pop16"]; - this.pop32s = this.wm.exports["_pop32s"]; + this.push16 = this.v86oxide.exports["push16"]; + this.push32 = this.v86oxide.exports["push32"]; + this.pop16 = this.v86oxide.exports["pop16"]; + this.pop32s = this.v86oxide.exports["pop32s"]; - this.set_stack_reg = this.wm.exports["_set_stack_reg"]; + this.set_stack_reg = this.v86oxide.exports["set_stack_reg"]; - this.translate_address_read = this.wm.exports["_translate_address_read"]; - this.translate_address_system_read = this.wm.exports["_translate_address_system_read"]; - this.translate_address_system_write = this.wm.exports["_translate_address_system_write"]; + this.translate_address_read = this.v86oxide.exports["translate_address_read"]; + this.translate_address_system_read = this.v86oxide.exports["translate_address_system_read"]; + this.translate_address_system_write = this.v86oxide.exports["translate_address_system_write"]; - this.get_seg = this.wm.exports["_get_seg"]; - this.adjust_stack_reg = this.wm.exports["_adjust_stack_reg"]; - this.get_real_eip = this.wm.exports["_get_real_eip"]; - this.get_stack_pointer = this.wm.exports["_get_stack_pointer"]; + this.get_seg = this.v86oxide.exports["get_seg"]; + this.adjust_stack_reg = this.v86oxide.exports["adjust_stack_reg"]; + this.get_real_eip = this.v86oxide.exports["get_real_eip"]; + this.get_stack_pointer = this.v86oxide.exports["get_stack_pointer"]; - this.writable_or_pagefault = this.wm.exports["_writable_or_pagefault"]; - this.safe_write32 = this.wm.exports["_safe_write32"]; - this.safe_read32s = this.wm.exports["_safe_read32s"]; - this.safe_write16 = this.wm.exports["_safe_write16"]; - this.safe_read16 = this.wm.exports["_safe_read16"]; + this.writable_or_pagefault = this.v86oxide.exports["writable_or_pagefault"]; + this.safe_write32 = this.v86oxide.exports["safe_write32"]; + this.safe_read32s = this.v86oxide.exports["safe_read32s"]; + this.safe_write16 = this.v86oxide.exports["safe_write16"]; + this.safe_read16 = this.v86oxide.exports["safe_read16"]; - this.clear_tlb = this.wm.exports["_clear_tlb"]; - this.full_clear_tlb = this.wm.exports["_full_clear_tlb"]; + this.clear_tlb = this.v86oxide.exports["clear_tlb"]; + this.full_clear_tlb = this.v86oxide.exports["full_clear_tlb"]; - this.set_tsc = this.wm.exports["_set_tsc"]; - this.store_current_tsc = this.wm.exports["_store_current_tsc"]; + this.set_tsc = this.v86oxide.exports["set_tsc"]; + this.store_current_tsc = this.v86oxide.exports["store_current_tsc"]; - this.pack_current_state_flags = this.wm.exports["_pack_current_state_flags"]; + this.pack_current_state_flags = this.v86oxide.exports["pack_current_state_flags"]; this.jit_force_generate_unsafe = this.v86oxide.exports["jit_force_generate_unsafe"]; this.jit_empty_cache = this.v86oxide.exports["jit_empty_cache"]; @@ -317,7 +361,7 @@ CPU.prototype.jit_force_generate = function(addr) CPU.prototype.jit_clear_func = function(index) { dbg_assert(index >= 0 && index < WASM_TABLE_SIZE); - this.wm.imports.env[WASM_EXPORT_TABLE_NAME].set(index, null); + this.wm.imports.env[WASM_EXPORT_TABLE_NAME + 0x100].set(index, null); }; CPU.prototype.get_state = function() @@ -670,11 +714,11 @@ CPU.prototype.create_memory = function(size) this.memory_size[0] = size; - var buffer = this.wm.memory.buffer; + //var buffer = this.wm.memory.buffer; - this.mem8 = new Uint8Array(buffer, GUEST_MEMORY_START, size); - this.mem16 = new Uint16Array(buffer, GUEST_MEMORY_START, size >> 1); - this.mem32s = new Int32Array(buffer, GUEST_MEMORY_START, size >> 2); + //this.mem8 = new Uint8Array(buffer, GUEST_MEMORY_START, size); + //this.mem16 = new Uint16Array(buffer, GUEST_MEMORY_START, size >> 1); + //this.mem32s = new Int32Array(buffer, GUEST_MEMORY_START, size >> 2); }; CPU.prototype.init = function(settings, device_bus) @@ -833,7 +877,7 @@ CPU.prototype.init = function(settings, device_bus) this.debug.init(); } - this.wm.exports["_profiler_init"](); + //this.wm.exports["_profiler_init"](); }; CPU.prototype.load_multiboot = function(buffer) @@ -1142,7 +1186,7 @@ CPU.prototype.load_bios = function() CPU.prototype.do_run = function() { - this.wm.exports["_profiler_stat_increment_do_run"](); + //this.wm.exports["_profiler_stat_increment_do_run"](); /** @type {number} */ var start = v86.microtick(); @@ -1179,7 +1223,7 @@ let do_many_cycles_total = 0; CPU.prototype.do_many_cycles = function() { // Capture the total time we were executing instructions - this.coverage_logger.log_start(); + //this.coverage_logger.log_start(); if(ENABLE_PROFILER) { @@ -1200,7 +1244,7 @@ CPU.prototype.do_many_cycles = function() do_many_cycles_count++; } - this.coverage_logger.log_end(); + //this.coverage_logger.log_end(); }; /** @export */ @@ -1284,7 +1328,7 @@ CPU.prototype.codegen_finalize = function(wasm_table_index, start, end, first_op first_opcode, state_flags); // The following will throw if f isn't an exported function - this.wm.imports["env"][WASM_EXPORT_TABLE_NAME].set(wasm_table_index, f); + this.wm.imports["env"][WASM_EXPORT_TABLE_NAME].set(wasm_table_index + 0x100, f); if(this.test_hook_did_finalize_wasm) { @@ -1346,7 +1390,7 @@ CPU.prototype.dump_function_code = function(block_ptr, count) const SIZEOF_BASIC_BLOCK_IN_DWORDS = 7; - const mem32 = new Int32Array(this.wm.memory.buffer); + const mem32 = new Int32Array(this.v86oxide.instance.exports.memory.buffer); dbg_assert((block_ptr & 3) === 0); @@ -1463,11 +1507,12 @@ CPU.prototype.jit_clear_cache = function() { this.jit_empty_cache(); - const table = this.wm.imports["env"][WASM_EXPORT_TABLE_NAME]; + const table = this.wm.exports[WASM_EXPORT_TABLE_NAME] || this.wm.imports["env"][WASM_EXPORT_TABLE_NAME]; + const offset = 0x100; for(let i = 0; i < WASM_TABLE_SIZE; i++) { - table.set(i, null); + table.set(offset + i, null); } }; diff --git a/src/rust/cpu.rs b/src/rust/cpu.rs index ff45fdd9..674751d3 100644 --- a/src/rust/cpu.rs +++ b/src/rust/cpu.rs @@ -8,7 +8,7 @@ mod unsafe_cpu { pub fn tlb_set_has_code(physical_page: u32, has_code: bool); pub fn read8(addr: u32) -> u8; pub fn read16(addr: u32) -> u16; - pub fn read32(addr: u32) -> u32; + pub fn read32s(addr: u32) -> u32; pub fn check_tlb_invariants(); pub fn codegen_finalize( @@ -29,7 +29,7 @@ pub enum BitSize { pub fn read8(addr: u32) -> u8 { unsafe { unsafe_cpu::read8(addr) } } pub fn read16(addr: u32) -> u16 { unsafe { unsafe_cpu::read16(addr) } } -pub fn read32(addr: u32) -> u32 { unsafe { unsafe_cpu::read32(addr) } } +pub fn read32(addr: u32) -> u32 { unsafe { unsafe_cpu::read32s(addr) } } pub fn tlb_set_has_code(physical_page: Page, has_code: bool) { unsafe { unsafe_cpu::tlb_set_has_code(physical_page.to_u32(), has_code) } diff --git a/src/rust/cpu2/Makefile b/src/rust/cpu2/Makefile new file mode 100644 index 00000000..592e3d8c --- /dev/null +++ b/src/rust/cpu2/Makefile @@ -0,0 +1,86 @@ +ALL:= arith.rs cpu.rs fpu.rs instructions_0f.rs instructions.rs \ + memory.rs misc_instr.rs modrm.rs shared.rs sse_instr.rs string.rs \ + global_pointers.rs profiler.rs + +all: $(ALL) + +profiler.rs: profiler/profiler.rs + cp profiler/profiler.rs profiler.rs + +%.rs: + #citrus --api=rust $< -I ../../native/ ../../native/profiler/ > $@.tmp + #cat import-prefix $@.tmp | grep -v cpu2::$(basename $@):: > $@ + #rm $@.tmp + #sed -i 's/assert(/assert!(/' $@ + #sed -i 's/dbg_assert(/dbg_assert!(/' $@ + #sed -i 's/dbg_log(/dbg_log!(/' $@ + #sed -i 's/%x/{:x}/g' $@ + #sed -i 's/%d/{}/g' $@ + #sed -i '/:.*= ()/d' $@ + #sed -i 's/!= 0 != 0//' $@ + #sed -i 's/fn(,/fn(i32,/' $@ + #sed -i 's/is_32 != 0/is_32/' $@ + #sed -i 's/SAFE_READ_WRITE8/SAFE_READ_WRITE8!/' $@ + #sed -i 's/SAFE_READ_WRITE16/SAFE_READ_WRITE16!/' $@ + #sed -i 's/SAFE_READ_WRITE32/SAFE_READ_WRITE32!/' $@ + #sed -i 's/pub fn SAFE_READ_WRITE8!();//' $@ + #sed -i 's/pub fn SAFE_READ_WRITE16!();//' $@ + #sed -i 's/pub fn SAFE_READ_WRITE32!();//' $@ + + cp ~/DL/c2rust/scripts/v86/src/native/$@ $@ + #cat import-prefix $@.tmp | grep -v cpu2::$(basename $@):: > $@ + #cat $@.tmp | grep -v cpu2::$(basename $@):: > $@ + -rm $@.tmp + sed -i 's/assert(/assert_c!(/' $@ + #sed -i 's/dbg_assert(/dbg_assert!(/' $@ + sed -i 's/dbg_log(/dbg_log_c!(/' $@ + #sed -i 's/pub unsafe extern "C" fn assert_c!() -> () { }//' $@ + #sed -i 's/pub unsafe extern "C" fn dbg_assert_c!() -> () { }//' $@ + #sed -i 's/pub unsafe extern "C" fn dbg_log_c!() -> () { }//' $@ + + sed -i 's/fn assert_c!() -> ();//' $@ + sed -i 's/fn dbg_assert_c!() -> ();//' $@ + sed -i 's/fn dbg_log_c!() -> ();//' $@ + + sed -i 's/fn assert_c!/fn assert_c/' $@ + sed -i 's/fn dbg_assert_c!/fn dbg_assert_c/' $@ + sed -i 's/fn dbg_log_c!/fn dbg_log_c/' $@ + + sed -i 's/libc::c_char/i8/g' $@ + sed -i 's/libc::c_double/f64/g' $@ + sed -i 's/libc::c_float/f32/g' $@ + sed -i 's/libc::c_int/i32/g' $@ + sed -i 's/libc::c_longlong/i64/g' $@ + sed -i 's/libc::c_long/i64/g' $@ + sed -i 's/libc::c_schar/i8/g' $@ + sed -i 's/libc::c_short/i16/g' $@ + sed -i 's/libc::c_uchar/u8/g' $@ + sed -i 's/libc::c_uint/u32/g' $@ + sed -i 's/libc::c_ulonglong/u64/g' $@ + sed -i 's/libc::c_ulong/u64/g' $@ + sed -i 's/libc::c_ushort/u16/g' $@ + + sed -i 's/SAFE_READ_WRITE8/SAFE_READ_WRITE8!/' $@ + sed -i 's/SAFE_READ_WRITE16/SAFE_READ_WRITE16!/' $@ + sed -i 's/SAFE_READ_WRITE32/SAFE_READ_WRITE32!/' $@ + sed -i 's/fn SAFE_READ_WRITE8!() -> ();//' $@ + sed -i 's/fn SAFE_READ_WRITE16!() -> ();//' $@ + sed -i 's/fn SAFE_READ_WRITE32!() -> ();//' $@ + + sed -i 's/pub type _IO_FILE;//' $@ + sed -i 's/pub type FILE = _IO_FILE;//' $@ + sed -i ':a;N;$$!ba;s/#\[no_mangle]\n static stdin: \*mut FILE;//' $@ + sed -i ':a;N;$$!ba;s/#\[no_mangle]\n static stdout: \*mut FILE;//' $@ + sed -i ':a;N;$$!ba;s/#\[no_mangle]\n static stderr: \*mut FILE;//' $@ + + sed -i ':a;N;$$!ba;s/#\[no_mangle]\n static mut ___: int32_t;//' $@ + + sed -i 's/SAFE_READ_WRITE8!(/SAFE_READ_WRITE8!(___, /' $@ + sed -i 's/SAFE_READ_WRITE16!(/SAFE_READ_WRITE16!(___, /' $@ + sed -i 's/SAFE_READ_WRITE32!(/SAFE_READ_WRITE32!(___, /' $@ + + sed -i 's/extern crate libc;//' $@ + +clean: + -rm $(ALL) + -rm profiler/profiler.rs diff --git a/src/rust/cpu2/imports.rs b/src/rust/cpu2/imports.rs new file mode 100644 index 00000000..982548f9 --- /dev/null +++ b/src/rust/cpu2/imports.rs @@ -0,0 +1,46 @@ +#[no_mangle] +pub unsafe extern "C" fn run_instruction(opcode: u32) { ::gen::interpreter::run(opcode) } +#[no_mangle] +pub unsafe extern "C" fn run_instruction0f_16(opcode: u32) { + ::gen::interpreter0f_16::run(opcode as u8) +} +#[no_mangle] +pub unsafe extern "C" fn run_instruction0f_32(opcode: u32) { + ::gen::interpreter0f_32::run(opcode as u8) +} + +#[no_mangle] +pub fn sqrt(x: f64) -> f64 { x.sqrt() } + +#[no_mangle] +pub fn sqrtf(x: f32) -> f32 { x.sqrt() } + +#[no_mangle] +pub fn profiler_stat_increment(stat: u32) {} + +#[no_mangle] +pub fn profiler_stat_increment_by(stat: u32, by: u32) {} + +#[no_mangle] +pub fn call_indirect1(f: fn(u16), x: u16) { f(x); } + +macro_rules! dbg_assert_c { + ($fmt:expr) => { + dbg_assert!($fmt != 0); + }; + ($fmt:expr, $($arg:tt)*) => { + dbg_assert!($fmt != 0, $arg); + }; +} +macro_rules! dbg_log_c { + ($fmt:expr) => {}; + ($fmt:expr, $($arg:tt)*) => {}; +} +macro_rules! assert_c { + ($fmt:expr) => { + assert!($fmt != 0); + }; + ($fmt:expr, $($arg:tt)*) => { + assert!($fmt != 0, $arg); + }; +} diff --git a/src/rust/cpu2/instruction_helpers.rs b/src/rust/cpu2/instruction_helpers.rs new file mode 100644 index 00000000..b435de7e --- /dev/null +++ b/src/rust/cpu2/instruction_helpers.rs @@ -0,0 +1,41 @@ +macro_rules! SAFE_READ_WRITE8 { + ($value:ident, $addr:expr, $instruction:expr) => {{ + use cpu2::cpu::translate_address_write; + use cpu2::memory::{read8, write8}; + let phys_addr = translate_address_write($addr); + let $value = read8(phys_addr); + write8(phys_addr, $instruction); + }}; +} +macro_rules! SAFE_READ_WRITE16 { + ($value:ident, $addr:expr, $instruction:expr) => {{ + use cpu2::cpu::{translate_address_write, virt_boundary_read16, virt_boundary_write16}; + use cpu2::memory::{read16, write16}; + let phys_addr = translate_address_write($addr) as i32; + if phys_addr & 0xFFF == 0xFFF { + let phys_addr_high = translate_address_write($addr + 1) as i32; + let $value = virt_boundary_read16(phys_addr, phys_addr_high); + virt_boundary_write16(phys_addr, phys_addr_high, $instruction); + } + else { + let $value = read16(phys_addr as u32); + write16(phys_addr as u32, $instruction); + } + }}; +} +macro_rules! SAFE_READ_WRITE32 { + ($value:ident, $addr:expr, $instruction:expr) => {{ + use cpu2::cpu::{translate_address_write, virt_boundary_read32s, virt_boundary_write32}; + use cpu2::memory::{read32s, write32}; + let phys_addr = translate_address_write($addr); + if phys_addr & 0xFFF >= 0xFFD { + let phys_addr_high = translate_address_write($addr + 3 & !3) as i32 | $addr + 3 & 3; + let $value = virt_boundary_read32s(phys_addr as i32, phys_addr_high); + virt_boundary_write32(phys_addr as i32, phys_addr_high as i32, $instruction); + } + else { + let $value = read32s(phys_addr); + write32(phys_addr, $instruction); + } + }}; +} diff --git a/src/rust/cpu2/mod.rs b/src/rust/cpu2/mod.rs new file mode 100644 index 00000000..f828660d --- /dev/null +++ b/src/rust/cpu2/mod.rs @@ -0,0 +1,20 @@ +#![allow(unused_assignments, unused_variables, unused_unsafe)] + +#[macro_use] +pub mod imports; + +#[macro_use] +mod instruction_helpers; + +pub mod arith; +pub mod cpu; +pub mod fpu; +pub mod global_pointers; +pub mod instructions; +pub mod instructions_0f; +pub mod memory; +pub mod misc_instr; +pub mod modrm; +pub mod shared; +pub mod sse_instr; +pub mod string; diff --git a/src/rust/dbg.rs b/src/rust/dbg.rs index f507b94d..d03dbb7f 100644 --- a/src/rust/dbg.rs +++ b/src/rust/dbg.rs @@ -45,6 +45,7 @@ macro_rules! dbg_assert { column!(), stringify!($cond), )); + #[allow(unused_unsafe)] unsafe { abort(); } @@ -61,6 +62,7 @@ macro_rules! dbg_assert { stringify!($cond), $desc, )); + #[allow(unused_unsafe)] unsafe { abort(); } diff --git a/src/rust/gen/mod.rs b/src/rust/gen/mod.rs index e7a048ce..b9e11b0e 100644 --- a/src/rust/gen/mod.rs +++ b/src/rust/gen/mod.rs @@ -1,3 +1,7 @@ +pub mod interpreter; +pub mod interpreter0f_16; +pub mod interpreter0f_32; + pub mod jit; pub mod jit0f_16; pub mod jit0f_32; diff --git a/src/rust/lib.rs b/src/rust/lib.rs index d4461fba..6ec12ce0 100644 --- a/src/rust/lib.rs +++ b/src/rust/lib.rs @@ -1,4 +1,5 @@ #![feature(const_fn)] +#![feature(extern_types)] #[cfg(test)] #[macro_use] @@ -7,7 +8,7 @@ extern crate quickcheck; #[macro_use] mod dbg; -mod cpu2; +pub mod cpu2; pub mod c_api; diff --git a/tools/rust-lld-wrapper b/tools/rust-lld-wrapper new file mode 100755 index 00000000..70826f65 --- /dev/null +++ b/tools/rust-lld-wrapper @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 + +# A wrapper for rust-lld that removes certain arguments inserted by rustc that +# we'd like to override + +import sys +import subprocess +from os import path + +def main(): + args = sys.argv[1:] + + # filter out args inserted by rustc + TO_REMOVE = {"--stack-first"} + args = list(filter(lambda arg: arg not in TO_REMOVE, args)) + + lld = find_rust_lld() + + result = subprocess.run([lld] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + result.check_returncode() + + print(result.stderr, file=sys.stderr) + print(result.stdout) + +def find_rust_lld(): + which = subprocess.run(["rustup", "which", "rustc"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + which.check_returncode() + + rustc_path = which.stdout.decode("utf8").strip() + assert path.basename(rustc_path) == "rustc" + + bin_path = path.dirname(rustc_path) + rust_lld_path = path.join(bin_path, "../lib/rustlib/x86_64-unknown-linux-gnu/bin/rust-lld") + + assert path.isfile(rust_lld_path) + return rust_lld_path + +main() diff --git a/tools/wasm-patch-indirect-function-table.js b/tools/wasm-patch-indirect-function-table.js new file mode 100755 index 00000000..e1026368 --- /dev/null +++ b/tools/wasm-patch-indirect-function-table.js @@ -0,0 +1,184 @@ +#!/usr/bin/env node +"use strict"; + +// Read a wasm module in binary format from stdin, find table import entries, i.e.: +// +// (import "env" "table" (table (;0;) anyfunc)) +// +// Remove the and write the patched wasm module to stdout. + +process.on("unhandledRejection", exn => { throw exn; }); + +const fs = require("fs"); + +const SECTION_IMPORT = 2; + +const IMPORT_KIND_FUNCTION = 0; +const IMPORT_KIND_TABLE = 1; +const IMPORT_KIND_MEMORY = 2; +const IMPORT_KIND_GLOBAL = 3; + +function main() +{ + const wasm = fs.readFileSync("/dev/stdin"); + const view = new DataView(wasm.buffer); + var ptr = 0; + + // magic + console.assert(view.getUint32(ptr, true) === 0x6d736100); + ptr += 4; + + // version + console.assert(view.getUint32(ptr, true) === 1); + ptr += 4; + + while(ptr < view.byteLength) + { + const section_id = view.getUint8(ptr); + ptr++; + var { ptr, value: size } = read_leb_u32(ptr, view); + const section_end = ptr + size; + + if(section_id === SECTION_IMPORT) + { + patch_import_section(ptr, view); + } + + ptr = section_end; + } + + // sanity check + const module = new WebAssembly.Module(view.buffer); + + process.stdout.write(wasm); +} + +function patch_import_section(ptr, view) +{ + var { ptr, value: section_entry_count } = read_leb_u32(ptr, view); + + for(let i = 0; i < section_entry_count; i++) + { + var { ptr, value: module_str_length } = read_leb_u32(ptr, view); + ptr += module_str_length; + var { ptr, value: field_str_length } = read_leb_u32(ptr, view); + ptr += field_str_length; + + const kind = view.getUint8(ptr); + ptr++; + + if(kind === IMPORT_KIND_FUNCTION) + { + var { ptr, value: function_signature_index } = read_leb_u32(ptr, view); + } + else if(kind === IMPORT_KIND_TABLE) + { + const table_offset = ptr; + var { ptr, value: table_element_type } = read_leb_u32(ptr, view); + console.assert(table_element_type === 0x70); + + const maximum_present = new Uint8Array(view.buffer, ptr, 1); + console.assert(maximum_present[0] === 0 || maximum_present[0] === 1); + ptr++; + + var { ptr, value: initial_table_size, leb_view: initial_table_size_view } = read_leb_u32(ptr, view); + + if(maximum_present[0]) + { + var { ptr, value: maximum_table_size, leb_view: maximum_table_size_view } = read_leb_u32(ptr, view); + } + else + { + maximum_table_size = -1; + } + + console.error(`Found table import at offset` + + ` ${table_offset}` + + ` maximum_present=${maximum_present[0]}` + + ` initial=${initial_table_size}` + + ` maximum=${maximum_table_size}`); + + if(maximum_present[0]) + { + patch_maximum_limit(maximum_present, initial_table_size_view, maximum_table_size_view); + console.error("Patched!"); + } + else + { + console.error("No maximum present, skipped"); + } + } + else if(kind === IMPORT_KIND_MEMORY) + { + const maximum_present = view.getUint8(ptr); + console.assert(maximum_present === 0 || maximum_present === 1); + ptr++; + + var { ptr, value: initial_memory_size } = read_leb_u32(ptr, view); + + if(maximum_present) + { + var { ptr, value: maximum_memory_size } = read_leb_u32(ptr, view); + } + } + else if(kind === IMPORT_KIND_GLOBAL) + { + const content_type = view.getUint8(ptr); + ptr++; + const mutability = view.getUint8(ptr); + console.assert(mutability === 0 || mutability === 1); + ptr++; + } + else + { + console.assert(false, `Unexpected import kind: 0x${kind.toString(16)} at offset ${ptr - 1}`); + } + } +} + +function patch_maximum_limit(maximum_present, initial_size, maximum_size) +{ + // clear the maximum present bit + maximum_present[0] = 0; + + // set the highest bit of the initial size, in order to use it to pad the existing maximum size bytes + const last_byte_initial_size = initial_size[initial_size.length - 1]; + console.assert((last_byte_initial_size & 0x80) === 0); + initial_size[initial_size.length - 1] = last_byte_initial_size | 0x80; + + for(let i = 0; i < maximum_size.length - 1; i++) + { + // pad maximum value with 0x80 bytes + maximum_size[i] = 0x80; + } + + // pad the last byte of the maximum value with 0x00 + maximum_size[maximum_size.length - 1] = 0x00; +} + +function read_leb_u32(ptr, view) +{ + let value = 0; + let byte_length = 0; + + while(true) + { + let byte = view.getUint8(ptr++); + + value |= (byte & 0x7f) << (byte_length * 7); + byte_length++; + + if((byte & 0x80) === 0) + { + break; + } + } + + console.assert(byte_length <= 4); + + const leb_view = new Uint8Array(view.buffer, ptr - byte_length, byte_length); + + return { ptr, value, leb_view }; +} + +main(); From e8eb5b9b458e6c5a6c98ce7991b49d61190ce08a Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 9 Aug 2018 16:05:33 -0500 Subject: [PATCH 1174/2137] Restore debug info --- Cargo.toml | 2 -- tools/rust-lld-wrapper | 5 ++++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2d0d9e5c..694fe8fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,8 +12,6 @@ path = "src/rust/lib.rs" [profile.dev] lto = false -# XXX: 2 -> removes debug information in later rust verions -# 0 -> requires more imports that are optimised away opt-level = 2 panic = "abort" overflow-checks = false diff --git a/tools/rust-lld-wrapper b/tools/rust-lld-wrapper index 70826f65..7e6aac30 100755 --- a/tools/rust-lld-wrapper +++ b/tools/rust-lld-wrapper @@ -11,7 +11,10 @@ def main(): args = sys.argv[1:] # filter out args inserted by rustc - TO_REMOVE = {"--stack-first"} + TO_REMOVE = { + "--stack-first", + "--strip-debug", # TODO: Make this configurable + } args = list(filter(lambda arg: arg not in TO_REMOVE, args)) lld = find_rust_lld() From 05d0079015a84adc0835b803b37f1e696594fa97 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 9 Aug 2018 16:06:51 -0500 Subject: [PATCH 1175/2137] Use Proxy over getters for memory views (works in compiled mode) --- src/cpu.js | 203 +++++++++++++++++++++++++++-------------------------- src/lib.js | 24 +++++++ 2 files changed, 127 insertions(+), 100 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index 39b12be5..d2a0abb8 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -21,62 +21,62 @@ function CPU(bus, wm, v86oxide, coverage_logger) const memory = v86oxide.instance.exports.memory; - Object.defineProperty(this, "memory_size", { get: () => { return new Uint32Array(memory.buffer, 812, 1); } }); - if(false) this.memory_size = new Uint32Array(memory.buffer, 812, 1); + if(false) Object.defineProperty(this, "memory_size", { get: () => { return new Uint32Array(memory.buffer, 812, 1); } }); + this.memory_size = v86util.view(Uint32Array, memory, 812, 1); // Note: Currently unused (degrades performance and not required by any OS // that we support) - if(false) this.a20_enabled = new Int32Array(memory.buffer, 552, 1); - Object.defineProperty(this, "a20_enabled", { get: () => { return new Int32Array(memory.buffer, 552, 1); } }); + this.a20_enabled = v86util.view(Int32Array, memory, 552, 1); + if(false) Object.defineProperty(this, "a20_enabled", { get: () => { return new Int32Array(memory.buffer, 552, 1); } }); this.a20_enabled[0] = +true; - if(false) this.mem8 = new Uint8Array(0); - if(false) this.mem16 = new Uint16Array(this.mem8.buffer); - if(false) this.mem32s = new Int32Array(this.mem8.buffer); + this.mem8 = new Uint8Array(0); + this.mem16 = new Uint16Array(this.mem8.buffer); + this.mem32s = new Int32Array(this.mem8.buffer); - Object.defineProperty(this, "mem8", { get: () => { return new Uint8Array(memory.buffer, GUEST_MEMORY_START, this.memory_size[0]); } }); - Object.defineProperty(this, "mem16", { get: () => { return new Uint16Array(memory.buffer, GUEST_MEMORY_START, this.memory_size[0] >> 1); } }); - Object.defineProperty(this, "mem32s", { get: () => { return new Int32Array(memory.buffer, GUEST_MEMORY_START, this.memory_size[0] >> 2); } }); + if(false) Object.defineProperty(this, "mem8", { get: () => { return new Uint8Array(memory.buffer, GUEST_MEMORY_START, this.memory_size[0]); } }); + if(false) Object.defineProperty(this, "mem16", { get: () => { return new Uint16Array(memory.buffer, GUEST_MEMORY_START, this.memory_size[0] >> 1); } }); + if(false) Object.defineProperty(this, "mem32s", { get: () => { return new Int32Array(memory.buffer, GUEST_MEMORY_START, this.memory_size[0] >> 2); } }); - if(false) this.segment_is_null = new Uint8Array(memory.buffer, 724, 8); - Object.defineProperty(this, "segment_is_null", { get: () => { return new Uint8Array(memory.buffer, 724, 8); } }); + this.segment_is_null = v86util.view(Uint8Array, memory, 724, 8); + if(false) Object.defineProperty(this, "segment_is_null", { get: () => { return new Uint8Array(memory.buffer, 724, 8); } }); - if(false) this.segment_offsets = new Int32Array(memory.buffer, 736, 8); - Object.defineProperty(this, "segment_offsets", { get: () => { return new Int32Array(memory.buffer, 736, 8); } }); + this.segment_offsets = v86util.view(Int32Array, memory, 736, 8); + if(false) Object.defineProperty(this, "segment_offsets", { get: () => { return new Int32Array(memory.buffer, 736, 8); } }); - if(false) this.segment_limits = new Uint32Array(memory.buffer, 768, 8); - Object.defineProperty(this, "segment_limits", { get: () => { return new Uint32Array(memory.buffer, 768, 8); } }); + this.segment_limits = v86util.view(Uint32Array, memory, 768, 8); + if(false) Object.defineProperty(this, "segment_limits", { get: () => { return new Uint32Array(memory.buffer, 768, 8); } }); /** * Wheter or not in protected mode */ - if(false) this.protected_mode = new Int32Array(memory.buffer, 800, 1); - Object.defineProperty(this, "protected_mode", { get: () => { return new Int32Array(memory.buffer, 800, 1); } }); + this.protected_mode = v86util.view(Int32Array, memory, 800, 1); + if(false) Object.defineProperty(this, "protected_mode", { get: () => { return new Int32Array(memory.buffer, 800, 1); } }); - if(false) this.idtr_size = new Int32Array(memory.buffer, 564, 1); - if(false) this.idtr_offset = new Int32Array(memory.buffer, 568, 1); - Object.defineProperty(this, "idtr_size", { get: () => { return new Int32Array(memory.buffer, 564, 1); } }); - Object.defineProperty(this, "idtr_offset", { get: () => { return new Int32Array(memory.buffer, 568, 1); } }); + this.idtr_size = v86util.view(Int32Array, memory, 564, 1); + this.idtr_offset = v86util.view(Int32Array, memory, 568, 1); + if(false) Object.defineProperty(this, "idtr_size", { get: () => { return new Int32Array(memory.buffer, 564, 1); } }); + if(false) Object.defineProperty(this, "idtr_offset", { get: () => { return new Int32Array(memory.buffer, 568, 1); } }); /** * global descriptor table register */ - if(false) this.gdtr_size = new Int32Array(memory.buffer, 572, 1); - if(false) this.gdtr_offset = new Int32Array(memory.buffer, 576, 1); + this.gdtr_size = v86util.view(Int32Array, memory, 572, 1); + this.gdtr_offset = v86util.view(Int32Array, memory, 576, 1); - Object.defineProperty(this, "gdtr_size", { get: () => { return new Int32Array(memory.buffer, 572, 1); } }); - Object.defineProperty(this, "gdtr_offset", { get: () => { return new Int32Array(memory.buffer, 576, 1); } }); + if(false) Object.defineProperty(this, "gdtr_size", { get: () => { return new Int32Array(memory.buffer, 572, 1); } }); + if(false) Object.defineProperty(this, "gdtr_offset", { get: () => { return new Int32Array(memory.buffer, 576, 1); } }); this.tss_size_32 = false; /* * whether or not a page fault occured */ - if(false) this.page_fault = new Uint32Array(memory.buffer, 540, 8); - Object.defineProperty(this, "page_fault", { get: () => { return new Uint32Array(memory.buffer, 540, 8); } }); + this.page_fault = v86util.view(Uint32Array, memory, 540, 8); + if(false) Object.defineProperty(this, "page_fault", { get: () => { return new Uint32Array(memory.buffer, 540, 8); } }); - if(false) this.cr = new Int32Array(memory.buffer, 580, 8); - Object.defineProperty(this, "cr", { get: () => { return new Int32Array(memory.buffer, 580, 8); } }); + this.cr = v86util.view(Int32Array, memory, 580, 8); + if(false) Object.defineProperty(this, "cr", { get: () => { return new Int32Array(memory.buffer, 580, 8); } }); /** @type {number} */ this.cr[0] = 0; @@ -88,76 +88,76 @@ function CPU(bus, wm, v86oxide, coverage_logger) this.cr[4] = 0; // current privilege level - if(false) this.cpl = new Int32Array(memory.buffer, 612, 1); - Object.defineProperty(this, "cpl", { get: () => { return new Int32Array(memory.buffer, 612, 1); } }); + this.cpl = v86util.view(Int32Array, memory, 612, 1); + if(false) Object.defineProperty(this, "cpl", { get: () => { return new Int32Array(memory.buffer, 612, 1); } }); // current operand/address size - if(false) this.is_32 = new Int32Array(memory.buffer, 804, 1); - Object.defineProperty(this, "is_32", { get: () => { return new Int32Array(memory.buffer, 804, 1); } }); + this.is_32 = v86util.view(Int32Array, memory, 804, 1); + if(false) Object.defineProperty(this, "is_32", { get: () => { return new Int32Array(memory.buffer, 804, 1); } }); - if(false) this.stack_size_32 = new Int32Array(memory.buffer, 808, 1); - Object.defineProperty(this, "stack_size_32", { get: () => { return new Int32Array(memory.buffer, 808, 1); } }); + this.stack_size_32 = v86util.view(Int32Array, memory, 808, 1); + if(false) Object.defineProperty(this, "stack_size_32", { get: () => { return new Int32Array(memory.buffer, 808, 1); } }); /** * Was the last instruction a hlt? */ - if(false) this.in_hlt = new Uint8Array(memory.buffer, 616, 1); - Object.defineProperty(this, "in_hlt", { get: () => { return new Uint8Array(memory.buffer, 616, 1); } }); + this.in_hlt = v86util.view(Uint8Array, memory, 616, 1); + if(false) Object.defineProperty(this, "in_hlt", { get: () => { return new Uint8Array(memory.buffer, 616, 1); } }); - this.last_virt_eip = new Int32Array(memory.buffer, 620, 1); + this.last_virt_eip = v86util.view(Int32Array, memory, 620, 1); - this.eip_phys = new Int32Array(memory.buffer, 624, 1); + this.eip_phys = v86util.view(Int32Array, memory, 624, 1); - this.last_virt_esp = new Int32Array(memory.buffer, 628, 1); + this.last_virt_esp = v86util.view(Int32Array, memory, 628, 1); - this.esp_phys = new Int32Array(memory.buffer, 632, 1); + this.esp_phys = v86util.view(Int32Array, memory, 632, 1); - this.sysenter_cs = new Int32Array(memory.buffer, 636, 1); + this.sysenter_cs = v86util.view(Int32Array, memory, 636, 1); - this.sysenter_esp = new Int32Array(memory.buffer, 640, 1); + this.sysenter_esp = v86util.view(Int32Array, memory, 640, 1); - this.sysenter_eip = new Int32Array(memory.buffer, 644, 1); + this.sysenter_eip = v86util.view(Int32Array, memory, 644, 1); - if(false) this.prefixes = new Int32Array(memory.buffer, 648, 1); - Object.defineProperty(this, "prefixes", { get: () => { return new Int32Array(memory.buffer, 648, 1); } }); + this.prefixes = v86util.view(Int32Array, memory, 648, 1); + if(false) Object.defineProperty(this, "prefixes", { get: () => { return new Int32Array(memory.buffer, 648, 1); } }); - if(false) this.flags = new Int32Array(memory.buffer, 536, 1); - Object.defineProperty(this, "flags", { get: () => { return new Int32Array(memory.buffer, 536, 1); } }); + this.flags = v86util.view(Int32Array, memory, 536, 1); + if(false) Object.defineProperty(this, "flags", { get: () => { return new Int32Array(memory.buffer, 536, 1); } }); /** * bitmap of flags which are not updated in the flags variable * changed by arithmetic instructions, so only relevant to arithmetic flags */ - if(false) this.flags_changed = new Int32Array(memory.buffer, 532, 1); - Object.defineProperty(this, "flags_changed", { get: () => { return new Int32Array(memory.buffer, 532, 1); } }); + this.flags_changed = v86util.view(Int32Array, memory, 532, 1); + if(false) Object.defineProperty(this, "flags_changed", { get: () => { return new Int32Array(memory.buffer, 532, 1); } }); /** * the last 2 operators and the result and size of the last arithmetic operation */ - if(false) this.last_op1 = new Int32Array(memory.buffer, 512, 1); - Object.defineProperty(this, "last_op1", { get: () => { return new Int32Array(memory.buffer, 512, 1); } }); - if(false) this.last_op2 = new Int32Array(memory.buffer, 516, 1); - Object.defineProperty(this, "last_op2", { get: () => { return new Int32Array(memory.buffer, 516, 1); } }); - if(false) this.last_op_size = new Int32Array(memory.buffer, 520, 1); - Object.defineProperty(this, "last_op_size", { get: () => { return new Int32Array(memory.buffer, 520, 1); } }); + this.last_op1 = v86util.view(Int32Array, memory, 512, 1); + if(false) Object.defineProperty(this, "last_op1", { get: () => { return new Int32Array(memory.buffer, 512, 1); } }); + this.last_op2 = v86util.view(Int32Array, memory, 516, 1); + if(false) Object.defineProperty(this, "last_op2", { get: () => { return new Int32Array(memory.buffer, 516, 1); } }); + this.last_op_size = v86util.view(Int32Array, memory, 520, 1); + if(false) Object.defineProperty(this, "last_op_size", { get: () => { return new Int32Array(memory.buffer, 520, 1); } }); - if(false) this.last_add_result = new Int32Array(memory.buffer, 524, 1); - Object.defineProperty(this, "last_add_result", { get: () => { return new Int32Array(memory.buffer, 524, 1); } }); + this.last_add_result = v86util.view(Int32Array, memory, 524, 1); + if(false) Object.defineProperty(this, "last_add_result", { get: () => { return new Int32Array(memory.buffer, 524, 1); } }); - if(false) this.last_result = new Int32Array(memory.buffer, 528, 1); - Object.defineProperty(this, "last_result", { get: () => { return new Int32Array(memory.buffer, 528, 1); } }); + this.last_result = v86util.view(Int32Array, memory, 528, 1); + if(false) Object.defineProperty(this, "last_result", { get: () => { return new Int32Array(memory.buffer, 528, 1); } }); - this.current_tsc = new Uint32Array(memory.buffer, 956, 2); // 64 bit + this.current_tsc = v86util.view(Uint32Array, memory, 956, 2); // 64 bit /** @type {!Object} */ this.devices = {}; - if(false) this.instruction_pointer = new Int32Array(memory.buffer, 556, 1); - Object.defineProperty(this, "instruction_pointer", { get: () => { return new Int32Array(memory.buffer, 556, 1); } }); + this.instruction_pointer = v86util.view(Int32Array, memory, 556, 1); + if(false) Object.defineProperty(this, "instruction_pointer", { get: () => { return new Int32Array(memory.buffer, 556, 1); } }); - if(false) this.previous_ip = new Int32Array(memory.buffer, 560, 1); - Object.defineProperty(this, "previous_ip", { get: () => { return new Int32Array(memory.buffer, 560, 1); } }); + this.previous_ip = v86util.view(Int32Array, memory, 560, 1); + if(false) Object.defineProperty(this, "previous_ip", { get: () => { return new Int32Array(memory.buffer, 560, 1); } }); this.apic_enabled = true; @@ -176,64 +176,64 @@ function CPU(bus, wm, v86oxide, coverage_logger) vga: null, }; - Object.defineProperty(this, "timestamp_counter", { get: () => { return new Int32Array(memory.buffer, 664, 1); } }); - if(false) this.timestamp_counter = new Uint32Array(memory.buffer, 664, 1); + if(false) Object.defineProperty(this, "timestamp_counter", { get: () => { return new Int32Array(memory.buffer, 664, 1); } }); + this.timestamp_counter = v86util.view(Uint32Array, memory, 664, 1); // registers - if(false) this.reg32s = new Int32Array(memory.buffer, 4, 8); - if(false) this.reg32 = new Uint32Array(this.reg32s.buffer, 4, 8); - if(false) this.reg16s = new Int16Array(this.reg32s.buffer, 4, 16); - if(false) this.reg16 = new Uint16Array(this.reg32s.buffer, 4, 16); - if(false) this.reg8s = new Int8Array(this.reg32s.buffer, 4, 32); - if(false) this.reg8 = new Uint8Array(this.reg32s.buffer, 4, 32); - Object.defineProperty(this, "reg32s", { get: () => { return new Int32Array(memory.buffer, 4, 8); } }); - Object.defineProperty(this, "reg32", { get: () => { return new Uint32Array(memory.buffer, 4, 8); } }); - Object.defineProperty(this, "reg16s", { get: () => { return new Int16Array(memory.buffer, 4, 16); } }); - Object.defineProperty(this, "reg16", { get: () => { return new Uint16Array(memory.buffer, 4, 16); } }); - Object.defineProperty(this, "reg8s", { get: () => { return new Int8Array(memory.buffer, 4, 32); } }); - Object.defineProperty(this, "reg8", { get: () => { return new Uint8Array(memory.buffer, 4, 32); } }); + this.reg32s = v86util.view(Int32Array, memory, 4, 8); + this.reg32 = v86util.view(Uint32Array, memory, 4, 8); + this.reg16s = v86util.view(Int16Array, memory, 4, 16); + this.reg16 = v86util.view(Uint16Array, memory, 4, 16); + this.reg8s = v86util.view(Int8Array, memory, 4, 32); + this.reg8 = v86util.view(Uint8Array, memory, 4, 32); + if(false) Object.defineProperty(this, "reg32s", { get: () => { return new Int32Array(memory.buffer, 4, 8); } }); + if(false) Object.defineProperty(this, "reg32", { get: () => { return new Uint32Array(memory.buffer, 4, 8); } }); + if(false) Object.defineProperty(this, "reg16s", { get: () => { return new Int16Array(memory.buffer, 4, 16); } }); + if(false) Object.defineProperty(this, "reg16", { get: () => { return new Uint16Array(memory.buffer, 4, 16); } }); + if(false) Object.defineProperty(this, "reg8s", { get: () => { return new Int8Array(memory.buffer, 4, 32); } }); + if(false) Object.defineProperty(this, "reg8", { get: () => { return new Uint8Array(memory.buffer, 4, 32); } }); // Why no Float80Array :-( - this.fpu_st = new Float64Array(memory.buffer, 968, 8); + this.fpu_st = v86util.view(Float64Array, memory, 968, 8); - this.fpu_stack_empty = new Int32Array(memory.buffer, 816, 1); + this.fpu_stack_empty = v86util.view(Int32Array, memory, 816, 1); this.fpu_stack_empty[0] = 0xff; - this.fpu_stack_ptr = new Uint32Array(memory.buffer, 1032, 1); + this.fpu_stack_ptr = v86util.view(Uint32Array, memory, 1032, 1); this.fpu_stack_ptr[0] = 0; - this.fpu_control_word = new Int32Array(memory.buffer, 1036, 1); + this.fpu_control_word = v86util.view(Int32Array, memory, 1036, 1); this.fpu_control_word[0] = 0x37F; - this.fpu_status_word = new Int32Array(memory.buffer, 1040, 1); + this.fpu_status_word = v86util.view(Int32Array, memory, 1040, 1); this.fpu_status_word[0] = 0; - this.fpu_ip = new Int32Array(memory.buffer, 1048, 1); + this.fpu_ip = v86util.view(Int32Array, memory, 1048, 1); this.fpu_ip[0] = 0; - this.fpu_ip_selector = new Int32Array(memory.buffer, 1052, 1); + this.fpu_ip_selector = v86util.view(Int32Array, memory, 1052, 1); this.fpu_ip_selector[0] = 0; - this.fpu_opcode = new Int32Array(memory.buffer, 1044, 1); + this.fpu_opcode = v86util.view(Int32Array, memory, 1044, 1); this.fpu_opcode[0] = 0; - this.fpu_dp = new Int32Array(memory.buffer, 1056, 1); + this.fpu_dp = v86util.view(Int32Array, memory, 1056, 1); this.fpu_dp[0] = 0; - this.fpu_dp_selector = new Int32Array(memory.buffer, 1060, 1); + this.fpu_dp_selector = v86util.view(Int32Array, memory, 1060, 1); this.fpu_dp_selector[0] = 0; // mm0-mm7 split up into 32 bit pairs - this.reg_mmxs = new Int32Array(memory.buffer, 1064, 16); - this.reg_mmx = new Uint32Array(this.reg_mmxs.buffer, 1064, 16); - this.reg_mmx8s = new Int8Array(this.reg_mmxs.buffer, 1064, 64); - this.reg_mmx8 = new Uint8Array(this.reg_mmxs.buffer, 1064, 64); + this.reg_mmxs = v86util.view(Int32Array, memory, 1064, 16); + this.reg_mmx = v86util.view(Uint32Array, this.reg_mmxs.buffer, 1064, 16); + this.reg_mmx8s = v86util.view(Int8Array, this.reg_mmxs.buffer, 1064, 64); + this.reg_mmx8 = v86util.view(Uint8Array, this.reg_mmxs.buffer, 1064, 64); - this.reg_xmm32s = new Int32Array(memory.buffer, 828, 8 * 4); + this.reg_xmm32s = v86util.view(Int32Array, memory, 828, 8 * 4); - this.mxcsr = new Int32Array(memory.buffer, 824, 1); + this.mxcsr = v86util.view(Int32Array, memory, 824, 1); // segment registers, tr and ldtr - if(false) this.sreg = new Uint16Array(memory.buffer, 668, 8); - Object.defineProperty(this, "sreg", { get: () => { return new Uint16Array(memory.buffer, 668, 8); } }); + this.sreg = v86util.view(Uint16Array, memory, 668, 8); + if(false) Object.defineProperty(this, "sreg", { get: () => { return new Uint16Array(memory.buffer, 668, 8); } }); // debug registers - this.dreg = new Int32Array(memory.buffer, 684, 8); + this.dreg = v86util.view(Int32Array, memory, 684, 8); - this.fw_value = new Int32Array(memory.buffer, 720, 1); + this.fw_value = v86util.view(Int32Array, memory, 720, 1); this.io = undefined; @@ -716,6 +716,9 @@ CPU.prototype.create_memory = function(size) //var buffer = this.wm.memory.buffer; + this.mem8 = v86util.view(Uint8Array, this.v86oxide.instance.exports.memory, GUEST_MEMORY_START, size); + this.mem16 = v86util.view(Uint16Array, this.v86oxide.instance.exports.memory, GUEST_MEMORY_START, size >> 1); + this.mem32s = v86util.view(Uint32Array, this.v86oxide.instance.exports.memory, GUEST_MEMORY_START, size >> 2); //this.mem8 = new Uint8Array(buffer, GUEST_MEMORY_START, size); //this.mem16 = new Uint16Array(buffer, GUEST_MEMORY_START, size >> 1); //this.mem32s = new Int32Array(buffer, GUEST_MEMORY_START, size >> 2); diff --git a/src/lib.js b/src/lib.js index 22779ce9..97f72af7 100644 --- a/src/lib.js +++ b/src/lib.js @@ -33,6 +33,30 @@ v86util.range = function(size) return Array.from(Array(size).keys()); }; +v86util.view = function(constructor, memory, offset, length) +{ + return new Proxy({}, + { + get: function(target, property, receiver) + { + const b = new constructor(memory.buffer, offset, length); + const x = b[property]; + if(typeof x === "function") + { + return x.bind(b); + } + dbg_assert(/^\d+$/.test(property) || property === "buffer" || property === "length"); + return x; + }, + set: function(target, property, value, receiver) + { + dbg_assert(/^\d+$/.test(property)); + new constructor(memory.buffer, offset, length)[property] = value; + return true; + }, + }); +}; + /** * number to hex * @param {number} n From 952b8cf7235f5fbc4d0204dd742c19f1aa564bd8 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 9 Aug 2018 18:10:16 -0500 Subject: [PATCH 1176/2137] Quote for Closure Compiler and add missing functions for non-optimised builds --- src/browser/starter.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 4810f5ee..4ab358c6 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -105,7 +105,7 @@ function V86Starter(options) // }, this); //} - const wasm_table = new WebAssembly.Table({ element: "anyfunc", initial: 0x10000 + 0x100 }); + const wasm_table = new WebAssembly.Table({ element: "anyfunc", "initial": 0x10000 + 0x100 }); var wasm_shared_funcs = { "__assert_fail": (condition, file, line, fun) => { @@ -254,6 +254,10 @@ function V86Starter(options) }, "codegen_finalize": (wasm_table_index, start, end, first_opcode, state_flags) => cpu.codegen_finalize(wasm_table_index, start, end, first_opcode, state_flags), "__indirect_function_table": wasm_table, + "floor": Math.floor, + "ceil": Math.ceil, + "fabs": Math.abs, + "abs": Math.abs, }; const wasm_globals = { From 1faf8ccc86ebae4bf76d9c2b2a816a86955033b2 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 9 Aug 2018 18:25:28 -0500 Subject: [PATCH 1177/2137] Allocate memory via Rust instead of ahead-of-time --- Makefile | 2 +- src/const.js | 5 ----- src/cpu.js | 19 ++++++++----------- src/native/cpu.c | 5 +++++ src/native/cpu.h | 4 ++++ src/native/global_pointers.c | 4 ---- src/native/global_pointers.h | 4 ---- src/rust/codegen.rs | 13 +++++++++---- src/rust/global_pointers.rs | 1 - tests/expect/run.js | 2 +- tests/expect/tests/call.wast | 2 +- tests/expect/tests/mov32-mem.wast | 8 ++++---- 12 files changed, 33 insertions(+), 36 deletions(-) diff --git a/Makefile b/Makefile index 58cf68c5..a3013628 100644 --- a/Makefile +++ b/Makefile @@ -104,7 +104,7 @@ CARGO_FLAGS=\ --target wasm32-unknown-unknown \ -- \ -C linker=tools/rust-lld-wrapper \ - -C link-args="--import-table --global-base=142606336" \ + -C link-args="--import-table --global-base=8388608" \ --verbose CORE_FILES=const.js config.js io.js main.js lib.js coverage.js ide.js pci.js floppy.js \ diff --git a/src/const.js b/src/const.js index c300bc73..d9865c51 100644 --- a/src/const.js +++ b/src/const.js @@ -364,11 +364,6 @@ var JIT_CACHE_ARRAY_SIZE = 0x40000; /** @const */ const WASM_EXPORT_TABLE_NAME = "__indirect_function_table"; - -/** @const */ -// The space we need for misc internal state before the beginning of mem8; see global_pointers.h -const GUEST_MEMORY_START = 0x800000; - /** @const */ const WASM_PAGE_SIZE = 64 * 1024; diff --git a/src/cpu.js b/src/cpu.js index d2a0abb8..ef2f1cd9 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -34,10 +34,6 @@ function CPU(bus, wm, v86oxide, coverage_logger) this.mem16 = new Uint16Array(this.mem8.buffer); this.mem32s = new Int32Array(this.mem8.buffer); - if(false) Object.defineProperty(this, "mem8", { get: () => { return new Uint8Array(memory.buffer, GUEST_MEMORY_START, this.memory_size[0]); } }); - if(false) Object.defineProperty(this, "mem16", { get: () => { return new Uint16Array(memory.buffer, GUEST_MEMORY_START, this.memory_size[0] >> 1); } }); - if(false) Object.defineProperty(this, "mem32s", { get: () => { return new Int32Array(memory.buffer, GUEST_MEMORY_START, this.memory_size[0] >> 2); } }); - this.segment_is_null = v86util.view(Uint8Array, memory, 724, 8); if(false) Object.defineProperty(this, "segment_is_null", { get: () => { return new Uint8Array(memory.buffer, 724, 8); } }); @@ -349,6 +345,8 @@ CPU.prototype.wasm_patch = function(wm) this.jit_get_op_ptr = this.v86oxide.exports["jit_get_op_ptr"]; this.jit_get_op_len = this.v86oxide.exports["jit_get_op_len"]; + + this.allocate_memory = this.v86oxide.exports["allocate_memory"]; }; CPU.prototype.jit_force_generate = function(addr) @@ -712,16 +710,15 @@ CPU.prototype.create_memory = function(size) dbg_assert((size | 0) > 0); dbg_assert((size & MMAP_BLOCK_SIZE - 1) === 0); + console.assert(this.memory_size[0] === 0); + this.memory_size[0] = size; - //var buffer = this.wm.memory.buffer; + const memory_offset = this.allocate_memory(size); - this.mem8 = v86util.view(Uint8Array, this.v86oxide.instance.exports.memory, GUEST_MEMORY_START, size); - this.mem16 = v86util.view(Uint16Array, this.v86oxide.instance.exports.memory, GUEST_MEMORY_START, size >> 1); - this.mem32s = v86util.view(Uint32Array, this.v86oxide.instance.exports.memory, GUEST_MEMORY_START, size >> 2); - //this.mem8 = new Uint8Array(buffer, GUEST_MEMORY_START, size); - //this.mem16 = new Uint16Array(buffer, GUEST_MEMORY_START, size >> 1); - //this.mem32s = new Int32Array(buffer, GUEST_MEMORY_START, size >> 2); + this.mem8 = v86util.view(Uint8Array, this.v86oxide.instance.exports.memory, memory_offset, size); + this.mem16 = v86util.view(Uint16Array, this.v86oxide.instance.exports.memory, memory_offset, size >> 1); + this.mem32s = v86util.view(Uint32Array, this.v86oxide.instance.exports.memory, memory_offset, size >> 2); }; CPU.prototype.init = function(settings, device_bus) diff --git a/src/native/cpu.c b/src/native/cpu.c index 28c81f07..82972214 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -198,6 +198,11 @@ const int32_t TLB_IN_MAPPED_RANGE = (1 << 3); const int32_t TLB_GLOBAL = (1 << 4); const int32_t TLB_HAS_CODE = (1 << 5); + +uint8_t* mem8 = NULL; +uint16_t* mem16 = NULL; +int32_t* mem32s = NULL; + #if DEBUG bool must_not_fault = false; #endif diff --git a/src/native/cpu.h b/src/native/cpu.h index 36be9c85..7e460f62 100644 --- a/src/native/cpu.h +++ b/src/native/cpu.h @@ -8,6 +8,10 @@ #include "config.h" #include "shared.h" +extern uint8_t* mem8; +extern uint16_t* mem16; +extern int32_t* mem32s; + union reg128 { int8_t i8[16]; int16_t i16[8]; diff --git a/src/native/global_pointers.c b/src/native/global_pointers.c index 53c37c40..fe90780d 100644 --- a/src/native/global_pointers.c +++ b/src/native/global_pointers.c @@ -90,7 +90,3 @@ uint32_t* const opstats_buffer_0f = (uint32_t* const) 0x1400; // length 0x400 // gap int32_t* const tlb_data = (int32_t* const) 0x400000; // length 0x100000*4 - -uint8_t* const mem8 = (uint8_t* const) 0x800000; -uint16_t* const mem16 = (uint16_t* const) 0x800000; -int32_t* const mem32s = (int32_t* const) 0x800000; diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index a47e33fc..44658ec4 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -92,7 +92,3 @@ extern uint32_t* const opstats_buffer_0f; // length 0x400 // gap extern int32_t* const tlb_data; // length 0x100000*4 - -extern uint8_t* const mem8; -extern uint16_t* const mem16; -extern int32_t* const mem32s; diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 4247c908..f747f337 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -8,6 +8,11 @@ use wasmgen::module_init; use wasmgen::module_init::{WasmBuilder, WasmLocal}; use wasmgen::wasm_util::WasmBuf; +extern "C" { + #[no_mangle] + static mut mem8: *mut u8; +} + pub fn gen_set_previous_eip_offset_from_eip(builder: &mut WasmBuilder, n: u32) { let cs = &mut builder.code_section; cs.push_i32(global_pointers::PREVIOUS_IP as i32); // store address of previous ip @@ -221,12 +226,12 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { BitSize::WORD => { builder .instruction_body - .load_unaligned_u16_from_stack(global_pointers::MEMORY); + .load_unaligned_u16_from_stack(unsafe { mem8 } as u32); }, BitSize::DWORD => { builder .instruction_body - .load_unaligned_i32_from_stack(global_pointers::MEMORY); + .load_unaligned_i32_from_stack(unsafe { mem8 } as u32); }, } @@ -317,12 +322,12 @@ fn gen_safe_write( BitSize::WORD => { builder .instruction_body - .store_unaligned_u16(global_pointers::MEMORY); + .store_unaligned_u16(unsafe { mem8 } as u32); }, BitSize::DWORD => { builder .instruction_body - .store_unaligned_i32(global_pointers::MEMORY); + .store_unaligned_i32(unsafe { mem8 } as u32); }, } diff --git a/src/rust/global_pointers.rs b/src/rust/global_pointers.rs index 0ec1b60d..b65fcc77 100644 --- a/src/rust/global_pointers.rs +++ b/src/rust/global_pointers.rs @@ -8,7 +8,6 @@ pub const SEGMENT_OFFSETS: u32 = 736; pub const OPSTATS_BUFFER: u32 = 0x1000; pub const OPSTATS_BUFFER_0F: u32 = 0x1400; pub const TLB_DATA: u32 = 0x400000; -pub const MEMORY: u32 = 0x800000; pub fn get_reg16_offset(r: u32) -> u32 { dbg_assert!(r < 8); diff --git a/tests/expect/run.js b/tests/expect/run.js index ba529dbb..ac3bca51 100755 --- a/tests/expect/run.js +++ b/tests/expect/run.js @@ -20,7 +20,7 @@ catch(e) { const LOG_LEVEL = 0; -const GIT_DIFF_FLAGS = [ "--no-index", "--patience", "--color=always"]; +const GIT_DIFF_FLAGS = ["--no-index", "--patience", "--color=always"]; const TEST_DIR = path.join(__dirname, "tests"); const BUILD_DIR = path.join(TEST_DIR, "build"); diff --git a/tests/expect/tests/call.wast b/tests/expect/tests/call.wast index 303fa6a4..be7ac1bb 100644 --- a/tests/expect/tests/call.wast +++ b/tests/expect/tests/call.wast @@ -155,7 +155,7 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.load offset=8388608 align=1 + (i32.load offset=20221952 align=1 (i32.xor (i32.and (get_local $l2) diff --git a/tests/expect/tests/mov32-mem.wast b/tests/expect/tests/mov32-mem.wast index a1aa22cb..498699bb 100644 --- a/tests/expect/tests/mov32-mem.wast +++ b/tests/expect/tests/mov32-mem.wast @@ -54,7 +54,7 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.store offset=8388608 align=1 + (i32.store offset=20221952 align=1 (i32.xor (i32.and (get_local $l2) @@ -101,7 +101,7 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.store offset=8388608 align=1 + (i32.store offset=20221952 align=1 (i32.xor (i32.and (get_local $l2) @@ -146,7 +146,7 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.load offset=8388608 align=1 + (i32.load offset=20221952 align=1 (i32.xor (i32.and (get_local $l1) @@ -189,7 +189,7 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.load offset=8388608 align=1 + (i32.load offset=20221952 align=1 (i32.xor (i32.and (get_local $l0) From d07cc4f7fa3f93ac49a8ebabec5f26a117dbe5c3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 9 Aug 2018 19:37:55 -0500 Subject: [PATCH 1178/2137] Fix state images --- src/lib.js | 3 ++- src/state.js | 29 ++++++++++++++++------------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/lib.js b/src/lib.js index 97f72af7..2e04fa9d 100644 --- a/src/lib.js +++ b/src/lib.js @@ -45,7 +45,8 @@ v86util.view = function(constructor, memory, offset, length) { return x.bind(b); } - dbg_assert(/^\d+$/.test(property) || property === "buffer" || property === "length"); + dbg_assert(/^\d+$/.test(property) || property === "buffer" || property === "length" || + property === "BYTES_PER_ELEMENT" || property === "byteOffset"); return x; }, set: function(target, property, value, receiver) diff --git a/src/state.js b/src/state.js index 80728165..b4ee2978 100644 --- a/src/state.js +++ b/src/state.js @@ -29,6 +29,16 @@ function StateLoadError(msg) } StateLoadError.prototype = new Error; +const CONSTRUCTOR_TABLE = { + "Uint8Array": Uint8Array, + "Int8Array": Int8Array, + "Uint16Array": Uint16Array, + "Int16Array": Int16Array, + "Uint32Array": Uint32Array, + "Int32Array": Int32Array, + "Float32Array": Float32Array, + "Float64Array": Float64Array, +}; function save_object(obj, saved_buffers) { @@ -50,8 +60,12 @@ function save_object(obj, saved_buffers) // Uint8Array, etc. var buffer = new Uint8Array(obj.buffer, obj.byteOffset, obj.length * obj.BYTES_PER_ELEMENT); + const constructor = obj.constructor.name.replace("bound ", ""); + + dbg_assert(CONSTRUCTOR_TABLE[constructor]); + return { - "__state_type__": obj.constructor.name, + "__state_type__": constructor, "buffer_id": saved_buffers.push(buffer) - 1, }; } @@ -123,18 +137,7 @@ function restore_object(base, obj, buffers) } else { - var table = { - "Uint8Array": Uint8Array, - "Int8Array": Int8Array, - "Uint16Array": Uint16Array, - "Int16Array": Int16Array, - "Uint32Array": Uint32Array, - "Int32Array": Int32Array, - "Float32Array": Float32Array, - "Float64Array": Float64Array, - }; - - var constructor = table[type]; + var constructor = CONSTRUCTOR_TABLE[type]; dbg_assert(constructor, "Unkown type: " + type); var info = buffers.infos[obj["buffer_id"]]; From a832a74a369d8669f362315ca96230fd62bfb77f Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 10 Aug 2018 18:17:50 -0500 Subject: [PATCH 1179/2137] Fix profiler --- src/browser/print_stats.js | 10 +++++----- src/rust/cpu2/imports.rs | 29 +++++++++++++++++++++++------ src/rust/cpu2/mod.rs | 1 + 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index df8e53af..a564c456 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -55,7 +55,7 @@ const print_stats = { for(let i = 0; i < stat_names.length; i++) { - let stat = cpu.wm.exports["_profiler_stat_get"](i); + let stat = cpu.v86oxide.exports["profiler_stat_get"](i); stat = stat >= 100e6 ? Math.round(stat / 1e6) + "m" : stat >= 100e3 ? Math.round(stat / 1e3) + "k" : stat; text += stat_names[i] + "=" + stat + " "; @@ -67,8 +67,8 @@ const print_stats = { text += "\n"; - const tlb_entries = cpu.wm.exports["_get_valid_tlb_entries_count"](); - const global_tlb_entries = cpu.wm.exports["_get_valid_global_tlb_entries_count"](); + const tlb_entries = cpu.v86oxide.exports["get_valid_tlb_entries_count"](); + const global_tlb_entries = cpu.v86oxide.exports["get_valid_global_tlb_entries_count"](); const nonglobal_tlb_entries = tlb_entries - global_tlb_entries; text += "TLB_ENTRIES=" + tlb_entries + " (" + global_tlb_entries + " global, " + nonglobal_tlb_entries + " non-global)\n"; @@ -159,10 +159,10 @@ const print_stats = { for(let i = 0; i < 0x100; i++) { - const count = cpu.wm.exports["_get_opstats_buffer"](i) / 1000 | 0; + const count = cpu.v86oxide.exports["get_opstats_buffer"](i) / 1000 | 0; counts.push([i, count]); - const count_0f = cpu.wm.exports["_get_opstats_buffer"](i + 0x100) / 1000 | 0; + const count_0f = cpu.v86oxide.exports["get_opstats_buffer"](i + 0x100) / 1000 | 0; counts.push([0x0f00 | i, count_0f]); } diff --git a/src/rust/cpu2/imports.rs b/src/rust/cpu2/imports.rs index 982548f9..b05d7bf0 100644 --- a/src/rust/cpu2/imports.rs +++ b/src/rust/cpu2/imports.rs @@ -1,3 +1,5 @@ +use std::alloc; + #[no_mangle] pub unsafe extern "C" fn run_instruction(opcode: u32) { ::gen::interpreter::run(opcode) } #[no_mangle] @@ -15,15 +17,30 @@ pub fn sqrt(x: f64) -> f64 { x.sqrt() } #[no_mangle] pub fn sqrtf(x: f32) -> f32 { x.sqrt() } -#[no_mangle] -pub fn profiler_stat_increment(stat: u32) {} - -#[no_mangle] -pub fn profiler_stat_increment_by(stat: u32, by: u32) {} - #[no_mangle] pub fn call_indirect1(f: fn(u16), x: u16) { f(x); } +extern "C" { + #[no_mangle] + static mut mem8: *mut u8; + #[no_mangle] + static mut mem16: *mut u16; + #[no_mangle] + static mut mem32s: *mut i32; +} + +#[no_mangle] +pub fn allocate_memory(size: u32) -> u32 { + let layout = alloc::Layout::from_size_align(size as usize, 0x1000).unwrap(); + let ptr = unsafe { alloc::alloc(layout) as u32 }; + unsafe { + mem8 = ptr as *mut u8; + mem16 = ptr as *mut u16; + mem32s = ptr as *mut i32; + }; + ptr +} + macro_rules! dbg_assert_c { ($fmt:expr) => { dbg_assert!($fmt != 0); diff --git a/src/rust/cpu2/mod.rs b/src/rust/cpu2/mod.rs index f828660d..16c5437e 100644 --- a/src/rust/cpu2/mod.rs +++ b/src/rust/cpu2/mod.rs @@ -15,6 +15,7 @@ pub mod instructions_0f; pub mod memory; pub mod misc_instr; pub mod modrm; +pub mod profiler; pub mod shared; pub mod sse_instr; pub mod string; From 5a874933dfa525ebc7ac10ee4fb2ef0222b6e216 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 10 Aug 2018 18:24:00 -0500 Subject: [PATCH 1180/2137] Clean up integer/float types --- src/rust/cpu2/Makefile | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/rust/cpu2/Makefile b/src/rust/cpu2/Makefile index 592e3d8c..53b5c302 100644 --- a/src/rust/cpu2/Makefile +++ b/src/rust/cpu2/Makefile @@ -60,6 +60,28 @@ profiler.rs: profiler/profiler.rs sed -i 's/libc::c_ulong/u64/g' $@ sed -i 's/libc::c_ushort/u16/g' $@ + sed -i 's/pub type double_t = f64;//' $@ + sed -i 's/pub type float_t = f32;//' $@ + sed -i 's/pub type uint64_t = u64;//' $@ + sed -i 's/pub type int64_t = i64;//' $@ + sed -i 's/pub type int32_t = i32;//' $@ + sed -i 's/pub type uint32_t = u32;//' $@ + sed -i 's/pub type int16_t = i16;//' $@ + sed -i 's/pub type uint16_t = u16;//' $@ + sed -i 's/pub type int8_t = i8;//' $@ + sed -i 's/pub type uint8_t = u8;//' $@ + + sed -i 's/double_t/f64/g' $@ + sed -i 's/float_t/f32/g' $@ + sed -i 's/uint64_t/u64/g' $@ + sed -i 's/int64_t/i64/g' $@ + sed -i 's/uint32_t/u32/g' $@ + sed -i 's/int32_t/i32/g' $@ + sed -i 's/uint16_t/u16/g' $@ + sed -i 's/int16_t/i16/g' $@ + sed -i 's/uint8_t/u8/g' $@ + sed -i 's/int8_t/i8/g' $@ + sed -i 's/SAFE_READ_WRITE8/SAFE_READ_WRITE8!/' $@ sed -i 's/SAFE_READ_WRITE16/SAFE_READ_WRITE16!/' $@ sed -i 's/SAFE_READ_WRITE32/SAFE_READ_WRITE32!/' $@ @@ -73,7 +95,7 @@ profiler.rs: profiler/profiler.rs sed -i ':a;N;$$!ba;s/#\[no_mangle]\n static stdout: \*mut FILE;//' $@ sed -i ':a;N;$$!ba;s/#\[no_mangle]\n static stderr: \*mut FILE;//' $@ - sed -i ':a;N;$$!ba;s/#\[no_mangle]\n static mut ___: int32_t;//' $@ + sed -i ':a;N;$$!ba;s/#\[no_mangle]\n static mut ___: i32;//' $@ sed -i 's/SAFE_READ_WRITE8!(/SAFE_READ_WRITE8!(___, /' $@ sed -i 's/SAFE_READ_WRITE16!(/SAFE_READ_WRITE16!(___, /' $@ From 67247ec907bcd1c785eff90b9f2a5b4ec8d87576 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 10 Aug 2018 19:29:06 -0500 Subject: [PATCH 1181/2137] (partially) fix variadic dbg_log --- src/browser/starter.js | 25 ++++++++++++++++++++++--- src/rust/cpu2/Makefile | 25 +++++++++++++------------ src/rust/cpu2/imports.rs | 21 --------------------- 3 files changed, 35 insertions(+), 36 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 4ab358c6..0e4082d0 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -146,10 +146,29 @@ function V86Starter(options) "microtick": v86.microtick, "get_rand_int": function() { return v86util.get_rand_int(); }, "has_rand_int": function() { return v86util.has_rand_int(); }, - "printf": function(format_string_offset, stack_top) { - dbg_assert(arguments.length === 2); - dbg_log_wasm(v86oxide.exports.memory.buffer, format_string_offset, stack_top); + "dbg_log": function(string_offset) + { }, + "dbg_log1": function(string_offset) + { + }, + "dbg_log2": function(string_offset) + { + }, + "dbg_log3": function(string_offset) + { + }, + "dbg_log5": function(string_offset) + { + }, + "dbg_trace": function() + { + dbg_trace(); + }, + //"printf": function(format_string_offset, stack_top) { + // dbg_assert(arguments.length === 2); + // dbg_log_wasm(v86oxide.exports.memory.buffer, format_string_offset, stack_top); + //}, "memcpy_large": function(dest, source, length) { const mem8 = new Uint8Array(v86oxide.exports.memory.buffer); mem8.set(mem8.subarray(source, source + length), dest); diff --git a/src/rust/cpu2/Makefile b/src/rust/cpu2/Makefile index 53b5c302..f9ab9b94 100644 --- a/src/rust/cpu2/Makefile +++ b/src/rust/cpu2/Makefile @@ -31,20 +31,21 @@ profiler.rs: profiler/profiler.rs #cat import-prefix $@.tmp | grep -v cpu2::$(basename $@):: > $@ #cat $@.tmp | grep -v cpu2::$(basename $@):: > $@ -rm $@.tmp - sed -i 's/assert(/assert_c!(/' $@ - #sed -i 's/dbg_assert(/dbg_assert!(/' $@ - sed -i 's/dbg_log(/dbg_log_c!(/' $@ - #sed -i 's/pub unsafe extern "C" fn assert_c!() -> () { }//' $@ - #sed -i 's/pub unsafe extern "C" fn dbg_assert_c!() -> () { }//' $@ - #sed -i 's/pub unsafe extern "C" fn dbg_log_c!() -> () { }//' $@ - sed -i 's/fn assert_c!() -> ();//' $@ - sed -i 's/fn dbg_assert_c!() -> ();//' $@ - sed -i 's/fn dbg_log_c!() -> ();//' $@ + #sed -i 's/assert(/assert_c!(/' $@ + ##sed -i 's/dbg_assert(/dbg_assert!(/' $@ + #sed -i 's/dbg_log(/dbg_log_c!(/' $@ + ##sed -i 's/pub unsafe extern "C" fn assert_c!() -> () { }//' $@ + ##sed -i 's/pub unsafe extern "C" fn dbg_assert_c!() -> () { }//' $@ + ##sed -i 's/pub unsafe extern "C" fn dbg_log_c!() -> () { }//' $@ - sed -i 's/fn assert_c!/fn assert_c/' $@ - sed -i 's/fn dbg_assert_c!/fn dbg_assert_c/' $@ - sed -i 's/fn dbg_log_c!/fn dbg_log_c/' $@ + #sed -i 's/fn assert_c!() -> ();//' $@ + #sed -i 's/fn dbg_assert_c!() -> ();//' $@ + #sed -i 's/fn dbg_log_c!() -> ();//' $@ + + #sed -i 's/fn assert_c!/fn assert_c/' $@ + #sed -i 's/fn dbg_assert_c!/fn dbg_assert_c/' $@ + #sed -i 's/fn dbg_log_c!/fn dbg_log_c/' $@ sed -i 's/libc::c_char/i8/g' $@ sed -i 's/libc::c_double/f64/g' $@ diff --git a/src/rust/cpu2/imports.rs b/src/rust/cpu2/imports.rs index b05d7bf0..3340b939 100644 --- a/src/rust/cpu2/imports.rs +++ b/src/rust/cpu2/imports.rs @@ -40,24 +40,3 @@ pub fn allocate_memory(size: u32) -> u32 { }; ptr } - -macro_rules! dbg_assert_c { - ($fmt:expr) => { - dbg_assert!($fmt != 0); - }; - ($fmt:expr, $($arg:tt)*) => { - dbg_assert!($fmt != 0, $arg); - }; -} -macro_rules! dbg_log_c { - ($fmt:expr) => {}; - ($fmt:expr, $($arg:tt)*) => {}; -} -macro_rules! assert_c { - ($fmt:expr) => { - assert!($fmt != 0); - }; - ($fmt:expr, $($arg:tt)*) => { - assert!($fmt != 0, $arg); - }; -} From 4255d6634ac24b4c8e6e4980d25c75b4fd93f76a Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 10 Aug 2018 21:54:47 -0500 Subject: [PATCH 1182/2137] generate_interpreter: Remove useless imports --- gen/generate_interpreter.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/gen/generate_interpreter.js b/gen/generate_interpreter.js index 9c317ac7..0786e614 100755 --- a/gen/generate_interpreter.js +++ b/gen/generate_interpreter.js @@ -399,8 +399,6 @@ function gen_table() const code = [ "use cpu2::cpu::*;", "use cpu2::instructions::*;", - "use cpu2::instructions_0f::*;", - "use cpu2::modrm::*;", "use cpu2::global_pointers::*;", "#[cfg_attr(rustfmt, rustfmt_skip)]", @@ -469,9 +467,7 @@ function gen_table() { const code = [ "use cpu2::cpu::*;", - "use cpu2::instructions::*;", "use cpu2::instructions_0f::*;", - "use cpu2::modrm::*;", "use cpu2::global_pointers::*;", "#[cfg_attr(rustfmt, rustfmt_skip)]", @@ -491,9 +487,7 @@ function gen_table() { const code = [ "use cpu2::cpu::*;", - "use cpu2::instructions::*;", "use cpu2::instructions_0f::*;", - "use cpu2::modrm::*;", "use cpu2::global_pointers::*;", "#[cfg_attr(rustfmt, rustfmt_skip)]", From 32322e5dc5e65544e5f3d010db72d311c455ec96 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 10 Aug 2018 21:57:20 -0500 Subject: [PATCH 1183/2137] Restore code that was lost by c2rust --- src/native/cpu.c | 96 +++++++++++++++++------------------- src/native/fpu.c | 12 ++--- src/native/instructions.c | 30 +++++------ src/native/instructions_0f.c | 51 +++++++------------ src/native/shared.h | 1 + 5 files changed, 84 insertions(+), 106 deletions(-) diff --git a/src/native/cpu.c b/src/native/cpu.c index 82972214..70dd0208 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -191,6 +191,8 @@ const double_t TSC_RATE = (50 * 1000); const bool CHECK_TLB_INVARIANTS = false; +const bool DEBUG = true; + const int32_t TLB_VALID = (1 << 0); const int32_t TLB_READONLY = (1 << 1); const int32_t TLB_NO_USER = (1 << 2); @@ -203,9 +205,7 @@ uint8_t* mem8 = NULL; uint16_t* mem16 = NULL; int32_t* mem32s = NULL; -#if DEBUG bool must_not_fault = false; -#endif #if 1 int32_t current_cpu_exception = -1; @@ -298,21 +298,21 @@ void update_eflags(int32_t new_flags) void trigger_pagefault(bool write, bool user, bool present) { - if(false) + if(0 * 0) { dbg_log5("page fault w=%d u=%d p=%d eip=%x cr2=%x", write, user, present, *previous_ip, cr[2]); dbg_trace(); } -#if DEBUG +if( DEBUG) { if(must_not_fault) { dbg_log("Unexpected page fault"); dbg_trace(); assert(false); } -#endif +} if(*page_fault) { @@ -864,9 +864,9 @@ static void jit_run_interpreted(int32_t phys_addr) int32_t opcode = read_imm8(); -#if DEBUG - logop(previous_ip[0], opcode); -#endif + if(DEBUG) + logop(previous_ip[0], opcode); + run_instruction(opcode | !!*is_32 << 8); clear_current_cpu_exception(); @@ -923,14 +923,14 @@ void cycle_internal() } else { -#if DEBUG + if(DEBUG) { assert(!must_not_fault); must_not_fault = true; -#endif + } jit_increase_hotness_and_maybe_compile(phys_addr, get_seg_cs(), state_flags); -#if DEBUG + if(DEBUG) { assert(must_not_fault); must_not_fault = false; -#endif + } int32_t initial_tsc = *timestamp_counter; @@ -949,9 +949,9 @@ void cycle_internal() int32_t opcode = read_imm8(); -#if DEBUG - logop(previous_ip[0], opcode); -#endif + if(DEBUG) + logop(previous_ip[0], opcode); + run_instruction(opcode | !!*is_32 << 8); } @@ -979,13 +979,9 @@ void do_many_cycles_unsafe() { profiler_stat_increment(S_DO_MANY_CYCLES); -#if 0 - for(int32_t k = 0; k < LOOP_COUNTER; k++) -#else uint32_t initial_timestamp_counter = *timestamp_counter; for(; *timestamp_counter - initial_timestamp_counter < LOOP_COUNTER && !in_hlt[0]; ) -#endif { cycle_internal(); } @@ -993,7 +989,7 @@ void do_many_cycles_unsafe() void raise_exception(int32_t interrupt_nr) { -#if DEBUG + if(DEBUG) { if(must_not_fault) { dbg_log1("Unexpected fault: 0x%x", interrupt_nr); @@ -1006,7 +1002,7 @@ void raise_exception(int32_t interrupt_nr) throw_cpu_exception(); return; } -#endif + } profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); call_interrupt_vector(interrupt_nr, false, false, 0); throw_cpu_exception(); @@ -1014,7 +1010,7 @@ void raise_exception(int32_t interrupt_nr) void raise_exception_with_code(int32_t interrupt_nr, int32_t error_code) { -#if DEBUG + if(DEBUG) { if(must_not_fault) { dbg_log2("Unexpected fault: 0x%x with code 0x%x", interrupt_nr, error_code); @@ -1027,7 +1023,7 @@ void raise_exception_with_code(int32_t interrupt_nr, int32_t error_code) throw_cpu_exception(); return; } -#endif + } profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); call_interrupt_vector(interrupt_nr, false, true, error_code); throw_cpu_exception(); @@ -1036,12 +1032,12 @@ void raise_exception_with_code(int32_t interrupt_nr, int32_t error_code) __attribute__((noinline)) void trigger_de() { -#if DEBUG + if(DEBUG) { if(cpu_exception_hook(CPU_EXCEPTION_DE)) { return; } -#endif + } *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_DE, false, false, 0); set_current_cpu_exception(CPU_EXCEPTION_DE); @@ -1052,12 +1048,12 @@ void trigger_ud() { dbg_log("#ud"); dbg_trace(); -#if DEBUG + if(DEBUG) { if(cpu_exception_hook(CPU_EXCEPTION_UD)) { return; } -#endif + } *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_UD, false, false, 0); set_current_cpu_exception(CPU_EXCEPTION_UD); @@ -1066,12 +1062,12 @@ void trigger_ud() __attribute__((noinline)) void trigger_nm() { -#if DEBUG + if(DEBUG) { if(cpu_exception_hook(CPU_EXCEPTION_NM)) { return; } -#endif + } *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_NM, false, false, 0); set_current_cpu_exception(CPU_EXCEPTION_NM); @@ -1080,12 +1076,12 @@ void trigger_nm() __attribute__((noinline)) void trigger_np(int32_t code) { -#if DEBUG + if(DEBUG) { if(cpu_exception_hook(CPU_EXCEPTION_NP)) { return; } -#endif + } *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_NP, false, true, code); set_current_cpu_exception(CPU_EXCEPTION_NP); @@ -1094,12 +1090,12 @@ void trigger_np(int32_t code) __attribute__((noinline)) void trigger_ss(int32_t code) { -#if DEBUG + if(DEBUG) { if(cpu_exception_hook(CPU_EXCEPTION_SS)) { return; } -#endif + } *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_SS, false, true, code); set_current_cpu_exception(CPU_EXCEPTION_SS); @@ -1115,12 +1111,12 @@ void trigger_gp(int32_t code) __attribute__((noinline)) void trigger_gp_non_raising(int32_t code) { -#if DEBUG + if(DEBUG) { if(cpu_exception_hook(CPU_EXCEPTION_GP)) { return; } -#endif + } *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_GP, false, true, code); set_current_cpu_exception(CPU_EXCEPTION_GP); @@ -1270,9 +1266,9 @@ int32_t safe_read32s(int32_t address) if(info_bits == TLB_VALID && (address & 0xFFF) <= (0x1000 - 4)) { -#if ENABLE_PROFILER_SAFE_READ_WRITE +if( ENABLE_PROFILER_SAFE_READ_WRITE) profiler_stat_increment(S_SAFE_READ32_FAST); -#endif + // - not in memory mapped area // - can be accessed from any cpl @@ -1282,7 +1278,7 @@ int32_t safe_read32s(int32_t address) } else { -#if ENABLE_PROFILER_SAFE_READ_WRITE +if( ENABLE_PROFILER_SAFE_READ_WRITE) { if((address & 0xFFF) > 0x1000 - 4) { profiler_stat_increment(S_SAFE_READ32_SLOW_PAGE_CROSSED); @@ -1303,7 +1299,7 @@ int32_t safe_read32s(int32_t address) { dbg_assert(false); } -#endif + } } #endif @@ -1424,9 +1420,8 @@ void safe_write32(int32_t address, int32_t value) if(info_bits == TLB_VALID && (address & 0xFFF) <= (0x1000 - 4)) { -#if ENABLE_PROFILER_SAFE_READ_WRITE +if( ENABLE_PROFILER_SAFE_READ_WRITE) profiler_stat_increment(S_SAFE_WRITE32_FAST); -#endif // - allowed to write in user-mode // - not in memory mapped area // - does not contain code @@ -1439,7 +1434,7 @@ void safe_write32(int32_t address, int32_t value) } else { -#if ENABLE_PROFILER_SAFE_READ_WRITE +if( ENABLE_PROFILER_SAFE_READ_WRITE) { if((address & 0xFFF) > 0x1000 - 4) { profiler_stat_increment(S_SAFE_WRITE32_SLOW_PAGE_CROSSED); @@ -1468,7 +1463,7 @@ void safe_write32(int32_t address, int32_t value) { dbg_assert(false); } -#endif +} } #endif @@ -1839,9 +1834,10 @@ uint64_t read_tsc() double_t n = microtick() * TSC_RATE; uint64_t value = (uint64_t)n - tsc_offset; -#if 1 + if(1 + 1) { return value; -#else + } + else { if(value == rdtsc_last_value) { @@ -1863,7 +1859,7 @@ uint64_t read_tsc() } else { - dbg_log("XXX: Overshot tsc prev=%x:%x offset=%x:%x curr=%x:%x", + dbg_log6("XXX: Overshot tsc prev=%x:%x offset=%x:%x curr=%x:%x", (uint32_t)(rdtsc_last_value >> 32), (uint32_t)rdtsc_last_value, (uint32_t)(rdtsc_imprecision_offset >> 32), (uint32_t)rdtsc_imprecision_offset, (uint32_t)(value >> 32), (uint32_t)value @@ -1875,7 +1871,7 @@ uint64_t read_tsc() } return rdtsc_last_value + rdtsc_imprecision_offset; -#endif + } } void store_current_tsc() @@ -1888,7 +1884,7 @@ int32_t get_opstats_buffer(int32_t index) { assert(index >= 0 && index < 0x200); -#if ENABLE_PROFILER_OPSTATS +if( ENABLE_PROFILER_OPSTATS) { if(index < 0x100) { return opstats_buffer[index]; @@ -1897,8 +1893,8 @@ int32_t get_opstats_buffer(int32_t index) { return opstats_buffer_0f[index - 0x100]; } -#else +} + UNUSED(index); return 0; -#endif } diff --git a/src/native/fpu.c b/src/native/fpu.c index 9eb986c5..9758b527 100644 --- a/src/native/fpu.c +++ b/src/native/fpu.c @@ -10,6 +10,8 @@ #include "log.h" #include "misc_instr.h" +extern const bool DEBUG; + //#ifndef M_LOG2E const double_t M_LOG2E = 1.44269504088896340736; //#endif @@ -179,7 +181,7 @@ double_t fpu_load_m80(uint32_t addr) else { // TODO: NaN, Infinity - //dbg_log("Load m80 TODO", LOG_FPU); + if(0 * 0) dbg_log("Load m80 TODO"); union f64_int double_int_view; @@ -355,8 +357,6 @@ int32_t fpu_load_tag_word() } } - //dbg_log("load tw=" + h(tag_word) + " se=" + h(*fpu_stack_empty) + " sp=" + *fpu_stack_ptr, LOG_FPU); - return tag_word; } @@ -431,8 +431,6 @@ void fpu_fsave(int32_t addr) addr += 10; } - //dbg_log("save st=" + *fpu_stack_ptr + " " + [].slice.call(this.st), LOG_FPU); - fpu_finit(); } @@ -446,8 +444,6 @@ void fpu_frstor(int32_t addr) fpu_st[(i + *fpu_stack_ptr) & 7] = fpu_load_m80(addr); addr += 10; } - - //dbg_log("rstor st=" + *fpu_stack_ptr + " " + [].slice.call(this.st), LOG_FPU); } void fpu_push(double_t x) @@ -789,8 +785,6 @@ void fpu_fistm64p(int32_t addr) { double_t st0 = fpu_integer_round(fpu_get_st0()); - //dbg_log("fistp %x %x", v.i32[0], v.i32[1]); - int64_t value; if(st0 < TWO_POW_63 && st0 >= -TWO_POW_63) diff --git a/src/native/instructions.c b/src/native/instructions.c index 66977eac..46cb93a4 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -1386,7 +1386,7 @@ void instr32_EF() { void instr_F0() { // lock - //dbg_log("lock"); + if(0 * 0) dbg_log("lock"); // TODO // This triggers UD when used with @@ -1475,13 +1475,13 @@ void instr_FA() { } else { - //if(getiopl() < 3 && ((flags & FLAG_VM) ? - // (cr[4] & CR4_VME) : - // (*cpl == 3 && (cr[4] & CR4_PVI)))) - //{ - // flags &= ~flag_vif; - //} - //else + if(0 * 0 && getiopl() < 3 && ((*flags & FLAG_VM) ? + (cr[4] & CR4_VME) : + (*cpl == 3 && (cr[4] & CR4_PVI)))) + { + *flags &= ~FLAG_VIF; + } + else { dbg_log("cli #gp"); trigger_gp_non_raising(0); @@ -1509,13 +1509,13 @@ void instr_FB() { } else { - //if(getiopl() < 3 && (flags & flag_vip) == 0 && ((flags & FLAG_VM) ? - // (cr[4] & CR4_VME) : - // (cpl == 3 && (cr[4] & CR4_PVI)))) - //{ - // flags |= flag_vif; - //} - //else + if(0 * 0 && getiopl() < 3 && (*flags & FLAG_VIP) == 0 && ((*flags & FLAG_VM) ? + (cr[4] & CR4_VME) : + (*cpl == 3 && (cr[4] & CR4_PVI)))) + { + *flags |= FLAG_VIF; + } + else { dbg_log("sti #gp"); trigger_gp_non_raising(0); diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index fc6937f5..84670b90 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -172,7 +172,7 @@ void instr_0F06() { } else { - //dbg_log("clts"); + if(0 * 0) dbg_log("clts"); cr[0] &= ~CR0_TS; } } @@ -491,7 +491,7 @@ void instr_0F21(int32_t r, int32_t dreg_index) { write_reg32(r, dreg[dreg_index]); - //dbg_log("read dr%d: %x", dreg_index, dreg[dreg_index]); + if(0 * 0) dbg_log2("read dr%d: %x", dreg_index, dreg[dreg_index]); } void instr_0F22(int32_t r, int32_t creg) { @@ -508,7 +508,7 @@ void instr_0F22(int32_t r, int32_t creg) { switch(creg) { case 0: - //dbg_log("cr0 <- %x", data); + if(0 * 0) dbg_log1("cr0 <- %x", data); set_cr0(data); break; @@ -518,13 +518,11 @@ void instr_0F22(int32_t r, int32_t creg) { break; case 3: - //dbg_log("cr3 <- %x", data); + if(0 * 0) dbg_log1("cr3 <- %x", data); data &= ~0b111111100111; dbg_assert_message((data & 0xFFF) == 0, "TODO"); cr[3] = data; clear_tlb(); - - //dump_page_directory(); break; case 4: @@ -546,7 +544,6 @@ void instr_0F22(int32_t r, int32_t creg) { if(cr[4] & CR4_PAE) { - //throw debug.unimpl("PAE"); assert(false); } @@ -581,7 +578,7 @@ void instr_0F23(int32_t r, int32_t dreg_index) { dreg[dreg_index] = read_reg32(r); - //dbg_log("write dr%d: %x", dreg_index, dreg[dreg_index]); + if(0 * 0) dbg_log2("write dr%d: %x", dreg_index, dreg[dreg_index]); } void instr_0F24() { undefined_instruction(); } @@ -692,22 +689,24 @@ 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 -#if 0 - union reg64 source = read_xmm_mem64s(); - double f = source.f64[0]; - - if(f <= 0x7FFFFFFF && f >= -0x80000000) + if(0 * 0) { - int32_t si = (int32_t) f; - write_g32(si); + double f = source.f64[0]; + + if(f <= 0x7FFFFFFF && f >= -0x80000000) + { + int32_t si = (int32_t) f; + write_reg32(r, si); + } + else + { + write_reg32(r, 0x80000000); + } } else { - write_g32(0x80000000); + write_reg32(r, convert_f64_to_i32(source.f64[0])); } -#else - write_reg32(r, convert_f64_to_i32(source.f64[0])); -#endif } DEFINE_SSE_SPLIT(instr_F20F2C, safe_read64s, read_xmm64s) @@ -820,7 +819,7 @@ void instr_0F31() { reg32s[EAX] = tsc; reg32s[EDX] = tsc >> 32; - //dbg_log("rdtsc edx:eax=%x:%x", reg32s[EDX], reg32s[EAX]); + if(0 * 0) dbg_log2("rdtsc edx:eax=%x:%x", reg32s[EDX], reg32s[EAX]); } else { @@ -944,12 +943,6 @@ void instr_0F34() { return; } - if(CPU_LOG_VERBOSE) - { - //dbg_log("sysenter cs:eip=" + h(seg , 4) + ":" + h(sysenter_eip[0], 8) + - // " ss:esp=" + h(seg + 8, 4) + ":" + h(sysenter_esp[0], 8)); - } - flags[0] &= ~FLAG_VM & ~FLAG_INTERRUPT; instruction_pointer[0] = sysenter_eip[0]; @@ -983,12 +976,6 @@ void instr_0F35() { return; } - if(CPU_LOG_VERBOSE) - { - //dbg_log("sysexit cs:eip=" + h(seg + 16, 4) + ":" + h(reg32s[EDX], 8) + - // " ss:esp=" + h(seg + 24, 4) + ":" + h(reg32s[ECX], 8)); - } - instruction_pointer[0] = reg32s[EDX]; reg32s[ESP] = reg32s[ECX]; diff --git a/src/native/shared.h b/src/native/shared.h index eb4ef037..cb870ef8 100644 --- a/src/native/shared.h +++ b/src/native/shared.h @@ -16,6 +16,7 @@ void dbg_log1(const char* m, int32_t x); void dbg_log2(const char* m, int32_t x, int32_t y); void dbg_log3(const char* m, int32_t x, int32_t y, int32_t z); void dbg_log5(const char* m, int32_t x, int32_t y, int32_t z, int32_t i, int32_t j); +void dbg_log6(const char* m, int32_t x, int32_t y, int32_t z, int32_t i, int32_t j, int32_t k); void dbg_trace(); bool isnan_XXX(double f); bool isfinite_XXX(double f); From 07851e90abe98f4eff166c7c9a826825e92a778c Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 10 Aug 2018 22:57:20 -0500 Subject: [PATCH 1184/2137] Clean up strings --- src/rust/cpu2/Makefile | 8 ++++++++ src/rust/cpu2/imports.rs | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/rust/cpu2/Makefile b/src/rust/cpu2/Makefile index f9ab9b94..749fd855 100644 --- a/src/rust/cpu2/Makefile +++ b/src/rust/cpu2/Makefile @@ -104,6 +104,14 @@ profiler.rs: profiler/profiler.rs sed -i 's/extern crate libc;//' $@ + sed -i 's/.as_mut_ptr()//' $@ + sed -i ':a;N;$$!ba;s/\*::std::mem::transmute::<&\[u8; [0-9]\+],[ \n]\+&mut \[i8; [0-9]\+]>//g' $@ + sed -i 's/\\x00//' $@ + + sed -i 's/dbg_log[0-9]\?((/dbg_log_c!((/' $@ + sed -i 's/ dbg_assert_message(/ dbg_assert_message!(/' $@ + + clean: -rm $(ALL) -rm profiler/profiler.rs diff --git a/src/rust/cpu2/imports.rs b/src/rust/cpu2/imports.rs index 3340b939..f2118a3a 100644 --- a/src/rust/cpu2/imports.rs +++ b/src/rust/cpu2/imports.rs @@ -40,3 +40,21 @@ pub fn allocate_memory(size: u32) -> u32 { }; ptr } + +macro_rules! dbg_log_c { + ($fmt:expr) => {{ + // TODO + }}; + ($fmt:expr, $($arg:tt)*) => {{ + // TODO + }}; +} + +macro_rules! dbg_assert_message { + ($fmt:expr) => {{ + // TODO + }}; + ($fmt:expr, $($arg:tt)*) => {{ + // TODO + }}; +} From 46f30ea7bca946cf29436fe6f24ea9c11ed656b5 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 10 Aug 2018 23:32:35 -0500 Subject: [PATCH 1185/2137] Preserve most comments --- src/native/arith.c | 11 +- src/native/cpu.c | 128 +++--- src/native/fpu.c | 50 +-- src/native/instructions.c | 192 +++++---- src/native/instructions_0f.c | 796 +++++++++++++++++------------------ src/native/misc_instr.c | 14 +- src/native/shared.h | 1 + src/native/sse_instr.c | 72 ++-- src/native/string.c | 2 +- src/rust/cpu2/Makefile | 1 + src/rust/cpu2/imports.rs | 4 + 11 files changed, 636 insertions(+), 635 deletions(-) diff --git a/src/native/arith.c b/src/native/arith.c index b7b29819..c1789bcc 100644 --- a/src/native/arith.c +++ b/src/native/arith.c @@ -440,7 +440,7 @@ void bcd_aaa() void bcd_aam(int32_t imm8) { - // ascii adjust after multiplication + c_comment("ascii adjust after multiplication"); if(imm8 == 0) { @@ -938,7 +938,7 @@ int32_t shl32(int32_t dest_operand, int32_t count) *last_op_size = OPSIZE_32; *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; - // test this + c_comment("test this"); *flags = (*flags & ~1 & ~FLAG_OVERFLOW) | (dest_operand >> (32 - count) & 1); *flags |= ((*flags & 1) ^ (*last_result >> 31 & 1)) << 11 & FLAG_OVERFLOW; @@ -1009,7 +1009,7 @@ int32_t sar8(int32_t dest_operand, int32_t count) if(count < 8) { *last_result = dest_operand << 24 >> (count + 24); - // of is zero + c_comment("of is zero"); *flags = (*flags & ~1 & ~FLAG_OVERFLOW) | (dest_operand >> (count - 1) & 1); } else @@ -1244,14 +1244,13 @@ int32_t bsf16(int32_t old, int32_t bit_base) *flags |= FLAG_ZERO; *last_result = bit_base; - // not defined in the docs, but value doesn't change on my intel machine + c_comment("not defined in the docs, but value doesn't change on my intel machine"); return old; } else { *flags &= ~FLAG_ZERO; - // http://jsperf.com/lowest-bit-index return *last_result = int_log2(-bit_base & bit_base); } } @@ -1322,7 +1321,7 @@ int32_t popcnt(int32_t v) if(v) { - // http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel + c_comment("http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel"); v = v - ((v >> 1) & 0x55555555); v = (v & 0x33333333) + ((v >> 2) & 0x33333333); return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; diff --git a/src/native/cpu.c b/src/native/cpu.c index 70dd0208..25f811e8 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -264,12 +264,12 @@ void update_eflags(int32_t new_flags) if(*flags & FLAG_VM) { - // other case needs to be handled in popf or iret + c_comment("other case needs to be handled in popf or iret"); dbg_assert(getiopl() == 3); dont_update |= FLAG_IOPL; - // don't clear vip or vif + c_comment("don't clear vip or vif"); clear |= FLAG_VIP | FLAG_VIF; } else @@ -278,14 +278,14 @@ void update_eflags(int32_t new_flags) if(*cpl) { - // cpl > 0 - // cannot update iopl + c_comment("cpl > 0"); + c_comment("cannot update iopl"); dont_update |= FLAG_IOPL; if(*cpl > getiopl()) { - // cpl > iopl - // cannot update interrupt flag + c_comment("cpl > iopl"); + c_comment("cannot update interrupt flag"); dont_update |= FLAG_INTERRUPT; } } @@ -321,7 +321,7 @@ if( DEBUG) { assert(false); } - // invalidate tlb entry + c_comment("invalidate tlb entry"); int32_t page = (uint32_t)cr[2] >> 12; tlb_data[page] = 0; @@ -344,7 +344,7 @@ int32_t do_page_translation(int32_t addr, bool for_writing, bool user) if((cr[0] & CR0_PG) == 0) { - // paging disabled + c_comment("paging disabled"); high = addr & 0xFFFFF000; global = false; } @@ -353,22 +353,22 @@ int32_t do_page_translation(int32_t addr, bool for_writing, bool user) int32_t page_dir_addr = ((uint32_t)cr[3] >> 2) + (page >> 10); int32_t page_dir_entry = read_aligned32(page_dir_addr); - // XXX + c_comment("XXX"); const bool kernel_write_override = !user && !(cr[0] & CR0_WP); if(!(page_dir_entry & PAGE_TABLE_PRESENT_MASK)) { - // to do at this place: - // - // - set cr2 = addr (which caused the page fault) - // - call_interrupt_vector with id 14, error code 0-7 (requires information if read or write) - // - prevent execution of the function that triggered this call + c_comment("to do at this place:"); + c_comment(""); + c_comment("- set cr2 = addr (which caused the page fault)"); + c_comment("- call_interrupt_vector with id 14, error code 0-7 (requires information if read or write)"); + c_comment("- prevent execution of the function that triggered this call"); //dbg_log("#PF not present", LOG_CPU); cr[2] = addr; trigger_pagefault(for_writing, user, 0); - // never reached as trigger_pagefault throws + c_comment("never reached as trigger_pagefault throws"); dbg_assert(false); } @@ -390,7 +390,7 @@ int32_t do_page_translation(int32_t addr, bool for_writing, bool user) if(user) { - // "Page Fault: page table accessed by non-supervisor"; + c_comment("Page Fault: page table accessed by non-supervisor"); //dbg_log("#PF supervisor", LOG_CPU); cr[2] = addr; trigger_pagefault(for_writing, user, 1); @@ -400,9 +400,9 @@ int32_t do_page_translation(int32_t addr, bool for_writing, bool user) if((page_dir_entry & PAGE_TABLE_PSE_MASK) && (cr[4] & CR4_PSE)) { - // size bit is set + c_comment("size bit is set"); - // set the accessed and dirty bits + c_comment("set the accessed and dirty bits"); write_aligned32(page_dir_addr, page_dir_entry | PAGE_TABLE_ACCESSED_MASK | (for_writing ? PAGE_TABLE_DIRTY_MASK : 0)); @@ -448,7 +448,7 @@ int32_t do_page_translation(int32_t addr, bool for_writing, bool user) } } - // set the accessed and dirty bits + c_comment("set the accessed and dirty bits"); write_aligned32(page_dir_addr, page_dir_entry | PAGE_TABLE_ACCESSED_MASK); write_aligned32(page_table_addr, page_table_entry | PAGE_TABLE_ACCESSED_MASK | @@ -466,7 +466,7 @@ int32_t do_page_translation(int32_t addr, bool for_writing, bool user) profiler_stat_increment(S_TLB_FULL); clear_tlb(); - // also clear global entries if tlb is almost full after clearing non-global pages + c_comment("also clear global entries if tlb is almost full after clearing non-global pages"); if(valid_tlb_entries_count > VALID_TLB_ENTRY_MAX * 3 / 4) { profiler_stat_increment(S_TLB_GLOBAL_FULL); @@ -477,9 +477,9 @@ int32_t do_page_translation(int32_t addr, bool for_writing, bool user) assert(valid_tlb_entries_count < VALID_TLB_ENTRY_MAX); valid_tlb_entries[valid_tlb_entries_count++] = page; - // TODO: Check that there are no duplicates in valid_tlb_entries - // XXX: There will probably be duplicates due to invlpg deleting - // entries from tlb_data but not from valid_tlb_entries + c_comment("TODO: Check that there are no duplicates in valid_tlb_entries"); + c_comment("XXX: There will probably be duplicates due to invlpg deleting"); + c_comment("entries from tlb_data but not from valid_tlb_entries"); } else { @@ -551,7 +551,7 @@ void check_tlb_invariants(void) int32_t page = valid_tlb_entries[i]; int32_t entry = tlb_data[page]; - if(!entry || (entry & TLB_IN_MAPPED_RANGE)) // there's no code in mapped memory + if(!entry || (entry & TLB_IN_MAPPED_RANGE)) c_comment("there's no code in mapped memory"); { continue; } @@ -562,12 +562,12 @@ void check_tlb_invariants(void) bool entry_has_code = entry & TLB_HAS_CODE; bool has_code = jit_page_has_code(physical_page); - // If some code has been created in a page, the corresponding tlb entries must be marked + c_comment("If some code has been created in a page, the corresponding tlb entries must be marked"); dbg_assert(!has_code || entry_has_code); - // If a tlb entry is marked to have code, the physical page should - // contain code (the converse is not a bug, but indicates a cleanup - // problem when clearing code from a page) + c_comment("If a tlb entry is marked to have code, the physical page should"); + c_comment("contain code (the converse is not a bug, but indicates a cleanup"); + c_comment("problem when clearing code from a page)"); dbg_assert(!entry_has_code || has_code); } } @@ -634,7 +634,7 @@ void writable_or_pagefault(int32_t addr, int32_t size) { assert(next_page == page + 1); - // XXX: possibly out of bounds + c_comment("XXX: possibly out of bounds"); if((tlb_data[next_page] & mask) != expect) { do_page_translation(next_page << 12, true, user); @@ -739,9 +739,9 @@ int32_t read_imm8s() int32_t read_imm16() { - // Two checks in one comparison: - // 1. Did the high 20 bits of eip change - // or 2. Are the low 12 bits of eip 0xFFF (and this read crosses a page boundary) + c_comment("Two checks in one comparison:"); + c_comment("1. Did the high 20 bits of eip change"); + c_comment("or 2. Are the low 12 bits of eip 0xFFF (and this read crosses a page boundary)"); if((uint32_t)(*instruction_pointer ^ *last_virt_eip) > 0xFFE) { return read_imm8() | read_imm8() << 8; @@ -755,7 +755,7 @@ int32_t read_imm16() int32_t read_imm32s() { - // Analogue to the above comment + c_comment("Analogue to the above comment"); if((uint32_t)(*instruction_pointer ^ *last_virt_eip) > 0xFFC) { return read_imm16() | read_imm16() << 16; @@ -781,7 +781,7 @@ int32_t get_seg(int32_t segment) { assert(segment >= 0 && segment < 8); - // TODO: Remove protected_mode check + c_comment("TODO: Remove protected_mode check"); if(*protected_mode) { if(segment_is_null[segment]) @@ -813,7 +813,7 @@ int32_t get_seg_prefix(int32_t default_segment) { if(prefix == SEG_PREFIX_ZERO) { - return 0; // TODO: Remove this special case + return 0; c_comment("TODO: Remove this special case"); } else { @@ -875,7 +875,7 @@ static void jit_run_interpreted(int32_t phys_addr) bool has_flat_segmentation(void) { - // ss can't be null + c_comment("ss can't be null"); return segment_offsets[SS] == 0 && !segment_is_null[DS] && segment_offsets[DS] == 0; } @@ -1141,18 +1141,18 @@ int32_t virt_boundary_read32s(int32_t low, int32_t high) { if(low & 2) { - // 0xFFF + c_comment("0xFFF"); mid = read_aligned16((high - 2) >> 1); } else { - // 0xFFD + c_comment("0xFFD"); mid = read_aligned16((low + 1) >> 1); } } else { - // 0xFFE + c_comment("0xFFE"); mid = virt_boundary_read16(low + 1, high - 1); } @@ -1179,20 +1179,20 @@ void virt_boundary_write32(int32_t low, int32_t high, int32_t value) { if(low & 2) { - // 0xFFF + c_comment("0xFFF"); write8(high - 2, value >> 8); write8(high - 1, value >> 16); } else { - // 0xFFD + c_comment("0xFFD"); write8(low + 1, value >> 8); write8(low + 2, value >> 16); } } else { - // 0xFFE + c_comment("0xFFE"); write8(low + 1, value >> 8); write8(high - 1, value >> 16); } @@ -1230,8 +1230,8 @@ int32_t safe_read16(int32_t address) if(info_bits == TLB_VALID && (address & 0xFFF) <= (0x1000 - 2)) { - // - not in memory mapped area - // - can be accessed from any cpl + c_comment("- not in memory mapped area"); + c_comment("- can be accessed from any cpl"); uint32_t phys_address = entry & ~0xFFF ^ address; assert(!in_mapped_range(phys_address)); @@ -1269,8 +1269,8 @@ int32_t safe_read32s(int32_t address) if( ENABLE_PROFILER_SAFE_READ_WRITE) profiler_stat_increment(S_SAFE_READ32_FAST); - // - not in memory mapped area - // - can be accessed from any cpl + c_comment("- not in memory mapped area"); + c_comment("- can be accessed from any cpl"); uint32_t phys_address = entry & ~0xFFF ^ address; assert(!in_mapped_range(phys_address)); @@ -1377,10 +1377,10 @@ void safe_write16(int32_t address, int32_t value) if(info_bits == TLB_VALID && (address & 0xFFF) <= (0x1000 - 2)) { - // - allowed to write in user-mode - // - not in memory mapped area - // - can be accessed from any cpl - // - does not contain code + c_comment("- allowed to write in user-mode"); + c_comment("- not in memory mapped area"); + c_comment("- can be accessed from any cpl"); + c_comment("- does not contain code"); uint32_t phys_address = entry & ~0xFFF ^ address; assert(!jit_page_has_code(phys_address >> 12)); @@ -1422,9 +1422,9 @@ void safe_write32(int32_t address, int32_t value) { if( ENABLE_PROFILER_SAFE_READ_WRITE) profiler_stat_increment(S_SAFE_WRITE32_FAST); - // - allowed to write in user-mode - // - not in memory mapped area - // - does not contain code + c_comment("- allowed to write in user-mode"); + c_comment("- not in memory mapped area"); + c_comment("- does not contain code"); uint32_t phys_address = entry & ~0xFFF ^ address; assert(!jit_page_has_code(phys_address >> 12)); @@ -1627,7 +1627,7 @@ void write_xmm_reg128(int32_t r, union reg128 data) void clear_tlb() { profiler_stat_increment(S_CLEAR_TLB); - // clear tlb excluding global pages + c_comment("clear tlb excluding global pages"); *last_virt_eip = -1; *last_virt_esp = -1; @@ -1641,7 +1641,7 @@ void clear_tlb() if(entry & TLB_GLOBAL) { - // reinsert at the front + c_comment("reinsert at the front"); valid_tlb_entries[global_page_offset++] = page; } else @@ -1664,7 +1664,7 @@ void clear_tlb() void full_clear_tlb() { profiler_stat_increment(S_FULL_CLEAR_TLB); - // clear tlb including global pages + c_comment("clear tlb including global pages"); *last_virt_eip = -1; *last_virt_esp = -1; @@ -1691,10 +1691,10 @@ void invlpg(int32_t addr) //dbg_log("invlpg: addr=" + h(addr >>> 0), LOG_CPU); int32_t page = (uint32_t)addr >> 12; - // Note: Doesn't remove this page from valid_tlb_entries: This isn't - // necessary, because when valid_tlb_entries grows too large, it will be - // empties by calling clear_tlb, which removes this entry as it isn't global. - // This however means that valid_tlb_entries can contain some invalid entries + c_comment("Note: Doesn't remove this page from valid_tlb_entries: This isn't"); + c_comment("necessary, because when valid_tlb_entries grows too large, it will be"); + c_comment("empties by calling clear_tlb, which removes this entry as it isn't global."); + c_comment("This however means that valid_tlb_entries can contain some invalid entries"); tlb_data[page] = 0; *last_virt_eip = -1; @@ -1730,9 +1730,9 @@ bool task_switch_test_mmx() } void task_switch_test_mmx_void() { task_switch_test_mmx(); } -// read 2 or 4 byte from ip, depending on address size attribute int32_t read_moffs() { + c_comment("read 2 or 4 byte from ip, depending on address size attribute"); if(is_asize_32()) { return read_imm32s(); @@ -1743,9 +1743,9 @@ int32_t read_moffs() } } -// Returns the "real" instruction pointer, without segment offset int32_t get_real_eip() { + c_comment("Returns the 'real' instruction pointer, without segment offset"); return *instruction_pointer - get_seg_cs(); } @@ -1841,7 +1841,7 @@ uint64_t read_tsc() if(value == rdtsc_last_value) { - // don't go past 1ms + c_comment("don't go past 1ms"); if(rdtsc_imprecision_offset < TSC_RATE) { @@ -1866,7 +1866,7 @@ uint64_t read_tsc() ); dbg_assert(false); - // Keep current value until time catches up + c_comment("Keep current value until time catches up"); } } diff --git a/src/native/fpu.c b/src/native/fpu.c index 9758b527..53a8be5d 100644 --- a/src/native/fpu.c +++ b/src/native/fpu.c @@ -114,9 +114,9 @@ void fpu_set_status_word(int32_t sw) *fpu_stack_ptr = sw >> 11 & 7; } -// sign of a number on the stack int32_t fpu_sign(int32_t i) { + c_comment("sign of a number on the stack"); return fpu_st8[(*fpu_stack_ptr + i & 7) << 3 | 7] >> 7; } @@ -130,15 +130,15 @@ void fpu_store_m80(uint32_t addr, double_t n) if(exponent == 0x7FF) { - // all bits set (NaN and infinity) + c_comment("all bits set (NaN and infinity)"); exponent = 0x7FFF; low = 0; high = 0x80000000 | (double_int_view.i32[1] & 0x80000) << 11; } else if(exponent == 0) { - // zero and denormal numbers - // Just assume zero for now + c_comment("zero and denormal numbers"); + c_comment("Just assume zero for now"); low = 0; high = 0; } @@ -146,14 +146,14 @@ void fpu_store_m80(uint32_t addr, double_t n) { exponent += 0x3FFF - 0x3FF; - // does the mantissa need to be adjusted? + c_comment("does the mantissa need to be adjusted?"); low = double_int_view.i32[0] << 11; high = 0x80000000 | (double_int_view.i32[1] & 0xFFFFF) << 11 | (((uint32_t)(double_int_view.i32[0])) >> 21); } dbg_assert(exponent >= 0 && exponent < 0x8000); - // writable_or_pagefault must have checked called by the caller! + c_comment("writable_or_pagefault must have checked called by the caller!"); safe_write64(addr, (uint64_t)low & 0xFFFFFFFF | (uint64_t)high << 32); safe_write16(addr + 8, sign << 8 | exponent); } @@ -170,7 +170,7 @@ double_t fpu_load_m80(uint32_t addr) if(exponent == 0) { - // TODO: denormal numbers + c_comment("TODO: denormal numbers"); return 0; } @@ -180,7 +180,7 @@ double_t fpu_load_m80(uint32_t addr) } else { - // TODO: NaN, Infinity + c_comment("TODO: NaN, Infinity"); if(0 * 0) dbg_log("Load m80 TODO"); union f64_int double_int_view; @@ -196,7 +196,7 @@ double_t fpu_load_m80(uint32_t addr) return double_int_view.f64; } - // Note: some bits might be lost at this point + c_comment("Note: some bits might be lost at this point"); double_t mantissa = ((double_t)(low)) + 0x100000000 * ((double_t)(high)); if(sign) @@ -204,16 +204,16 @@ double_t fpu_load_m80(uint32_t addr) mantissa = -mantissa; } - // Simply compute the 64 bit floating point number. - // An alternative write the mantissa, sign and exponent in the - // float64_byte and return float64[0] + c_comment("Simply compute the 64 bit floating point number."); + c_comment("An alternative write the mantissa, sign and exponent in the"); + c_comment("float64_byte and return float64[0]"); return mantissa * pow(2, exponent - 63); } void fpu_stack_fault() { - // TODO: Interrupt + c_comment("TODO: Interrupt"); *fpu_status_word |= FPU_EX_SF | FPU_EX_I; } @@ -261,14 +261,14 @@ void fpu_fcom(double_t y) void fpu_fucom(int32_t r) { - // TODO + c_comment("TODO"); fpu_fcom(fpu_get_sti(r)); } void fpu_fucomi(int32_t r) { - // TODO + c_comment("TODO"); fpu_fcomi(r); } @@ -291,7 +291,7 @@ void fpu_ftst(double_t x) *fpu_status_word |= FPU_C0; } - // TODO: unordered (x is nan, etc) + c_comment("TODO: unordered (x is nan, etc)"); } void fpu_fxam(double_t x) @@ -319,8 +319,8 @@ void fpu_fxam(double_t x) { *fpu_status_word |= FPU_C2; } - // TODO: - // Unsupported, Denormal + c_comment("TODO:"); + c_comment("Unsupported, Denormal"); } void fpu_finit(void) @@ -503,7 +503,7 @@ void fpu_fxtract(void) void fpu_fprem(void) { - // XXX: This implementation differs from the description in Intel's manuals + c_comment("XXX: This implementation differs from the description in Intel's manuals"); double_t st0 = fpu_get_st0(); double_t st1 = fpu_get_sti(1); @@ -528,11 +528,11 @@ double_t fpu_integer_round(double_t f) { int32_t rc = *fpu_control_word >> 10 & 3; - // XXX: See https://en.wikipedia.org/wiki/C_mathematical_functions + c_comment("XXX: See https://en.wikipedia.org/wiki/C_mathematical_functions"); if(rc == 0) { - // Round to nearest, or even if equidistant + c_comment("Round to nearest, or even if equidistant"); double_t rounded = round(f); double_t diff = rounded - f; @@ -544,9 +544,9 @@ double_t fpu_integer_round(double_t f) return rounded; } - // rc=3 is truncate -> floor for positive numbers else if(rc == 1 || (rc == 3 && f > 0)) { + c_comment("rc=3 is truncate -> floor for positive numbers"); return floor(f); } else @@ -585,7 +585,7 @@ void fpu_store_m32(int32_t addr, double_t x) void fwait(void) { - // NOP unless FPU instructions run in parallel with CPU instructions + c_comment("NOP unless FPU instructions run in parallel with CPU instructions"); } void fpu_fadd(int32_t target_index, double_t val) @@ -735,8 +735,8 @@ void fpu_fistm32(int32_t addr) int32_t i = convert_f64_to_i32(st0); if(i == (int32_t)0x80000000) { - // XXX: Probably not correct if st0 == 0x80000000 - // (input fits, but same value as error value) + c_comment("XXX: Probably not correct if st0 == 0x80000000"); + c_comment("(input fits, but same value as error value)"); fpu_invalid_arithmetic(); } safe_write32(addr, i); diff --git a/src/native/instructions.c b/src/native/instructions.c index 46cb93a4..20f9cdcf 100644 --- a/src/native/instructions.c +++ b/src/native/instructions.c @@ -238,7 +238,7 @@ void instr16_61() { popa16(); } void instr32_61() { popa32(); } void instr_62_reg(int32_t r2, int32_t r) { - // bound + c_comment("bound"); dbg_log("Unimplemented BOUND instruction"); dbg_assert(false); } @@ -253,14 +253,14 @@ void instr_64() { segment_prefix_op(FS); } void instr_65() { segment_prefix_op(GS); } void instr_66() { - // Operand-size override prefix + c_comment("Operand-size override prefix"); *prefixes |= PREFIX_MASK_OPSIZE; run_prefix_instruction(); *prefixes = 0; } void instr_67() { - // Address-size override prefix + c_comment("Address-size override prefix"); dbg_assert(is_asize_32() == *is_32); *prefixes |= PREFIX_MASK_ADDRSIZE; run_prefix_instruction(); @@ -438,12 +438,12 @@ void instr16_8D_reg(int32_t r, int32_t r2) } void instr16_8D_mem_pre() { - // override prefix, so modrm_resolve does not return the segment part + c_comment("override prefix, so modrm_resolve does not return the segment part"); *prefixes |= SEG_PREFIX_ZERO; } void instr16_8D_mem(int32_t addr, int32_t r) { - // lea + c_comment("lea"); write_reg16(r, addr); *prefixes = 0; } @@ -454,11 +454,11 @@ void instr32_8D_reg(int32_t r, int32_t r2) } void instr32_8D_mem_pre() { - // override prefix, so modrm_resolve does not return the segment part + c_comment("override prefix, so modrm_resolve does not return the segment part"); *prefixes |= SEG_PREFIX_ZERO; } void instr32_8D_mem(int32_t addr, int32_t r) { - // lea + c_comment("lea"); write_reg32(r, addr); *prefixes = 0; } @@ -486,12 +486,12 @@ DEFINE_MODRM_INSTR_READ16(instr_8E, instr_8E_helper(___, r)) void instr16_8F_0_mem_pre() { - for(int32_t i = 0; i < 8; i++) { translate_address_read(*instruction_pointer + i); }; // XXX + for(int32_t i = 0; i < 8; i++) { translate_address_read(*instruction_pointer + i); }; c_comment("XXX"); adjust_stack_reg(2); } void instr16_8F_0_mem(int32_t addr) { - // pop + c_comment("pop"); adjust_stack_reg(-2); int32_t sp = safe_read16(get_stack_pointer(0)); safe_write16(addr, sp); @@ -503,17 +503,17 @@ void instr16_8F_0_reg(int32_t r) } void instr32_8F_0_mem_pre() { - // prevent page faults during modrm_resolve - for(int32_t i = 0; i < 8; i++) { translate_address_read(*instruction_pointer + i); }; // XXX + c_comment("prevent page faults during modrm_resolve"); + for(int32_t i = 0; i < 8; i++) { translate_address_read(*instruction_pointer + i); }; c_comment("XXX"); - // esp must be adjusted before calling modrm_resolve - // The order of calls is: instr32_8F_0_mem_pre -> modrm_resolve -> instr32_8F_0_mem + c_comment("esp must be adjusted before calling modrm_resolve"); + c_comment("The order of calls is: instr32_8F_0_mem_pre -> modrm_resolve -> instr32_8F_0_mem"); adjust_stack_reg(4); } 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. + c_comment("Before attempting a write that might cause a page fault,"); + c_comment("we must set esp to the old value. Fuck Intel."); adjust_stack_reg(-4); int32_t sp = safe_read32s(get_stack_pointer(0)); @@ -547,7 +547,7 @@ void instr16_99() { /* cwd */ reg16[DX] = reg16s[AX] >> 15; } void instr32_99() { /* cdq */ reg32s[EDX] = reg32s[EAX] >> 31; } void instr16_9A(int32_t new_ip, int32_t new_cs) { - // callf + c_comment("callf"); far_jump(new_ip, new_cs, true); dbg_assert(is_asize_32() || get_real_eip() < 0x10000); } @@ -557,7 +557,6 @@ void instr32_9A(int32_t new_ip, int32_t new_cs) { if(new_ip & 0xFFFF0000) { assert(false); - //throw debug.unimpl("#GP handler"); } } @@ -566,11 +565,11 @@ void instr32_9A(int32_t new_ip, int32_t new_cs) { } void instr_9B() { - // fwait: check for pending fpu exceptions + c_comment("fwait: check for pending fpu exceptions"); if((cr[0] & (CR0_MP | CR0_TS)) == (CR0_MP | CR0_TS)) { - // Note: Different from task_switch_test - // Triggers when TS and MP bits are set (EM bit is ignored) + c_comment("Note: Different from task_switch_test"); + c_comment("Triggers when TS and MP bits are set (EM bit is ignored)"); trigger_nm(); } else @@ -579,7 +578,7 @@ void instr_9B() { } } void instr16_9C() { - // pushf + c_comment("pushf"); if((flags[0] & FLAG_VM) && getiopl() < 3) { dbg_assert(*protected_mode); @@ -592,22 +591,22 @@ void instr16_9C() { } } void instr32_9C() { - // pushf + c_comment("pushf"); if((flags[0] & FLAG_VM) && getiopl() < 3) { - // trap to virtual 8086 monitor + c_comment("trap to virtual 8086 monitor"); dbg_assert(*protected_mode); dbg_log("pushf #gp"); trigger_gp_non_raising(0); } else { - // vm and rf flag are cleared in image stored on the stack + c_comment("vm and rf flag are cleared in image stored on the stack"); push32(get_eflags() & 0x00FCFFFF); } } void instr16_9D() { - // popf + c_comment("popf"); if((flags[0] & FLAG_VM) && getiopl() < 3) { dbg_log("popf #gp"); @@ -632,7 +631,7 @@ void instr16_9D() { } } void instr32_9D() { - // popf + c_comment("popf"); if((flags[0] & FLAG_VM) && getiopl() < 3) { dbg_log("popf #gp"); @@ -644,23 +643,23 @@ void instr32_9D() { handle_irqs(); } void instr_9E() { - // sahf + c_comment("sahf"); flags[0] = (flags[0] & ~0xFF) | reg8[AH]; flags[0] = (flags[0] & FLAGS_MASK) | FLAGS_DEFAULT; flags_changed[0] &= ~0xFF; } void instr_9F() { - // lahf + c_comment("lahf"); reg8[AH] = get_eflags(); } void instr_A0(int32_t moffs) { - // mov + c_comment("mov"); int32_t data = safe_read8(get_seg_prefix_ds(moffs)); reg8[AL] = data; } void instr16_A1(int32_t moffs) { - // mov + c_comment("mov"); int32_t data = safe_read16(get_seg_prefix_ds(moffs)); reg16[AX] = data; } @@ -669,11 +668,11 @@ void instr32_A1(int32_t moffs) { reg32s[EAX] = data; } void instr_A2(int32_t moffs) { - // mov + c_comment("mov"); safe_write8(get_seg_prefix_ds(moffs), reg8[AL]); } void instr16_A3(int32_t moffs) { - // mov + c_comment("mov"); safe_write16(get_seg_prefix_ds(moffs), reg16[AX]); } void instr32_A3(int32_t moffs) { @@ -795,7 +794,7 @@ DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_C1_6, shl32(___, imm & 31)) DEFINE_MODRM_INSTR2_READ_WRITE_32(instr32_C1_7, sar32(___, imm & 31)) void instr16_C2(int32_t imm16) { - // retn + c_comment("retn"); int32_t cs = get_seg_cs(); instruction_pointer[0] = cs + pop16(); @@ -803,7 +802,7 @@ void instr16_C2(int32_t imm16) { adjust_stack_reg(imm16); } void instr32_C2(int32_t imm16) { - // retn + c_comment("retn"); int32_t cs = get_seg_cs(); int32_t ip = pop32s(); @@ -812,12 +811,12 @@ void instr32_C2(int32_t imm16) { adjust_stack_reg(imm16); } void instr16_C3() { - // retn + c_comment("retn"); int32_t cs = get_seg_cs(); instruction_pointer[0] = cs + pop16(); } void instr32_C3() { - // retn + c_comment("retn"); int32_t cs = get_seg_cs(); int32_t ip = pop32s(); dbg_assert(is_asize_32() || ip < 0x10000); @@ -851,7 +850,7 @@ void instr32_C7_0_mem(int32_t addr, int32_t imm) { safe_write32(addr, imm); } void instr16_C8(int32_t size, int32_t nesting) { enter16(size, nesting); } void instr32_C8(int32_t size, int32_t nesting) { enter32(size, nesting); } void instr16_C9() { - // leave + c_comment("leave"); int32_t old_vbp = *stack_size_32 ? reg32s[EBP] : reg16[BP]; int32_t new_bp = safe_read16(get_seg_ss() + old_vbp); set_stack_reg(old_vbp + 2); @@ -864,14 +863,14 @@ void instr32_C9() { reg32s[EBP] = new_ebp; } void instr16_CA(int32_t imm16) { - // retf + c_comment("retf"); int32_t ip = safe_read16(get_stack_pointer(0)); int32_t cs = safe_read16(get_stack_pointer(2)); far_return(ip, cs, imm16); } void instr32_CA(int32_t imm16) { - // retf + c_comment("retf"); int32_t ip = safe_read32s(get_stack_pointer(0)); int32_t cs = safe_read32s(get_stack_pointer(4)) & 0xFFFF; @@ -879,7 +878,7 @@ void instr32_CA(int32_t imm16) { dbg_assert(is_asize_32() || get_real_eip() < 0x10000); } void instr16_CB() { - // retf + c_comment("retf"); int32_t ip = safe_read16(get_stack_pointer(0)); int32_t cs = safe_read16(get_stack_pointer(2)); @@ -887,7 +886,7 @@ void instr16_CB() { dbg_assert(is_asize_32() || get_real_eip() < 0x10000); } void instr32_CB() { - // retf + c_comment("retf"); int32_t ip = safe_read32s(get_stack_pointer(0)); int32_t cs = safe_read32s(get_stack_pointer(4)) & 0xFFFF; @@ -896,27 +895,27 @@ void instr32_CB() { } void instr_CC() { - // INT3 - // TODO: inhibit iopl checks + c_comment("INT3"); + c_comment("TODO: inhibit iopl checks"); dbg_log("INT3"); call_interrupt_vector(3, true, false, 0); } void instr_CD(int32_t imm8) { - // INT + c_comment("INT"); call_interrupt_vector(imm8, true, false, 0); } void instr_CE() { - // INTO + c_comment("INTO"); dbg_log("INTO"); if(getof()) { - // TODO: inhibit iopl checks + c_comment("TODO: inhibit iopl checks"); call_interrupt_vector(CPU_EXCEPTION_OF, true, false, 0); } } void instr16_CF() { - // iret + c_comment("iret"); iret16(); } void instr32_CF() { @@ -985,11 +984,11 @@ void instr_D5(int32_t arg) { } void instr_D6() { - // salc + c_comment("salc"); reg8[AL] = -getcf(); } void instr_D7() { - // xlat + c_comment("xlat"); if(is_asize_32()) { reg8[AL] = safe_read8(get_seg_prefix(DS) + reg32s[EBX] + reg8[AL]); @@ -1023,11 +1022,11 @@ void instr_D9_4_reg(int32_t r) switch(r) { case 0: - // fchs + c_comment("fchs"); fpu_st[*fpu_stack_ptr] = -st0; break; case 1: - // fabs + c_comment("fabs"); fpu_st[*fpu_stack_ptr] = fabs(st0); break; case 4: @@ -1044,7 +1043,7 @@ void instr_D9_4_reg(int32_t r) void instr_D9_5_mem(int32_t addr) { fpu_fldcw(addr); } void instr_D9_5_reg(int32_t r) { - // fld1/fldl2t/fldl2e/fldpi/fldlg2/fldln2/fldz + c_comment("fld1/fldl2t/fldl2e/fldpi/fldlg2/fldln2/fldz"); switch(r) { case 0: fpu_push(1); break; @@ -1065,21 +1064,21 @@ void instr_D9_6_reg(int32_t r) switch(r) { case 0: - // f2xm1 + c_comment("f2xm1"); fpu_st[*fpu_stack_ptr] = pow(2, st0) - 1; break; case 1: - // fyl2x + c_comment("fyl2x"); fpu_st[*fpu_stack_ptr + 1 & 7] = fpu_get_sti(1) * log(st0) / M_LN2; fpu_pop(); break; case 2: - // fptan + c_comment("fptan"); fpu_st[*fpu_stack_ptr] = tan(st0); - fpu_push(1); // no bug: push constant 1 + fpu_push(1); c_comment("no bug: push constant 1"); break; case 3: - // fpatan + c_comment("fpatan"); fpu_st[*fpu_stack_ptr + 1 & 7] = atan2(fpu_get_sti(1), st0); fpu_pop(); break; @@ -1087,16 +1086,16 @@ void instr_D9_6_reg(int32_t r) fpu_fxtract(); break; case 5: - // fprem1 + c_comment("fprem1"); fpu_st[*fpu_stack_ptr] = fmod(st0, fpu_get_sti(1)); break; case 6: - // fdecstp + c_comment("fdecstp"); *fpu_stack_ptr = *fpu_stack_ptr - 1 & 7; *fpu_status_word &= ~FPU_C1; break; case 7: - // fincstp + c_comment("fincstp"); *fpu_stack_ptr = *fpu_stack_ptr + 1 & 7; *fpu_status_word &= ~FPU_C1; break; @@ -1115,7 +1114,7 @@ void instr_D9_7_reg(int32_t r) fpu_fprem(); break; case 1: - // fyl2xp1: y * log2(x+1) and pop + c_comment("fyl2xp1: y * log2(x+1) and pop"); fpu_st[*fpu_stack_ptr + 1 & 7] = fpu_get_sti(1) * log(st0 + 1) / M_LN2; fpu_pop(); break; @@ -1127,11 +1126,11 @@ void instr_D9_7_reg(int32_t r) fpu_push(cos(st0)); break; case 4: - // frndint + c_comment("frndint"); fpu_st[*fpu_stack_ptr] = fpu_integer_round(st0); break; case 5: - // fscale + c_comment("fscale"); fpu_st[*fpu_stack_ptr] = st0 * pow(2, trunc(fpu_get_sti(1))); break; case 6: @@ -1184,7 +1183,7 @@ void instr_DB_4_reg(int32_t r) } else if(r == 4 || r == 1) { - // fsetpm and fdisi; treated as nop + c_comment("fsetpm and fdisi; treated as nop"); } else if(r == 2) { @@ -1307,47 +1306,47 @@ void instr32_E7(int32_t port) { } void instr16_E8(int32_t imm16) { - // call + c_comment("call"); push16(get_real_eip()); jmp_rel16(imm16); } void instr32_E8(int32_t imm32s) { - // call + c_comment("call"); push32(get_real_eip()); instruction_pointer[0] = instruction_pointer[0] + imm32s; - //dbg_assert(is_asize_32() || get_real_eip() < 0x10000); + c_comment("dbg_assert(is_asize_32() || get_real_eip() < 0x10000);"); } void instr16_E9(int32_t imm16) { - // jmp + c_comment("jmp"); jmp_rel16(imm16); } void instr32_E9(int32_t imm32s) { - // jmp + c_comment("jmp"); instruction_pointer[0] = instruction_pointer[0] + imm32s; dbg_assert(is_asize_32() || get_real_eip() < 0x10000); } void instr16_EA(int32_t new_ip, int32_t cs) { - // jmpf + c_comment("jmpf"); far_jump(new_ip, cs, false); dbg_assert(is_asize_32() || get_real_eip() < 0x10000); } void instr32_EA(int32_t new_ip, int32_t cs) { - // jmpf + c_comment("jmpf"); far_jump(new_ip, cs, false); dbg_assert(is_asize_32() || get_real_eip() < 0x10000); } void instr16_EB(int32_t imm8) { - // jmp near + c_comment("jmp near"); jmp_rel16(imm8); dbg_assert(is_asize_32() || get_real_eip() < 0x10000); } void instr32_EB(int32_t imm8) { - // jmp near + c_comment("jmp near"); instruction_pointer[0] = instruction_pointer[0] + imm8; dbg_assert(is_asize_32() || get_real_eip() < 0x10000); } @@ -1385,23 +1384,22 @@ void instr32_EF() { } void instr_F0() { - // lock + c_comment("lock"); if(0 * 0) dbg_log("lock"); - // TODO - // This triggers UD when used with - // some instructions that don't write to memory + c_comment("TODO"); + c_comment("This triggers UD when used with"); + c_comment("some instructions that don't write to memory"); run_prefix_instruction(); } void instr_F1() { - // INT1 - // https://code.google.com/p/corkami/wiki/x86oddities#IceBP - //throw debug.unimpl("int1 instruction"); + c_comment("INT1"); + c_comment("https://code.google.com/p/corkami/wiki/x86oddities#IceBP"); assert(false); } void instr_F2() { - // repnz + c_comment("repnz"); dbg_assert((*prefixes & PREFIX_MASK_REP) == 0); *prefixes |= PREFIX_REPNZ; run_prefix_instruction(); @@ -1409,7 +1407,7 @@ void instr_F2() { } void instr_F3() { - // repz + c_comment("repz"); dbg_assert((*prefixes & PREFIX_MASK_REP) == 0); *prefixes |= PREFIX_REPZ; run_prefix_instruction(); @@ -1421,7 +1419,7 @@ void instr_F4() { } void instr_F5() { - // cmc + c_comment("cmc"); flags[0] = (flags[0] | 1) ^ getcf(); flags_changed[0] &= ~1; } @@ -1454,18 +1452,18 @@ DEFINE_MODRM_INSTR1_READ32(instr32_F7_6, div32(___)) DEFINE_MODRM_INSTR1_READ32(instr32_F7_7, idiv32(___)) void instr_F8() { - // clc + c_comment("clc"); flags[0] &= ~FLAG_CARRY; flags_changed[0] &= ~1; } void instr_F9() { - // stc + c_comment("stc"); flags[0] |= FLAG_CARRY; flags_changed[0] &= ~1; } void instr_FA() { - // cli + c_comment("cli"); //dbg_log("interrupts off"); if(!*protected_mode || ((flags[0] & FLAG_VM) ? @@ -1489,7 +1487,7 @@ void instr_FA() { } } void instr_FB() { - // sti + c_comment("sti"); //dbg_log("interrupts on"); int32_t old_if = flags[0] & FLAG_INTERRUPT; @@ -1525,11 +1523,11 @@ void instr_FB() { } void instr_FC() { - // cld + c_comment("cld"); flags[0] &= ~FLAG_DIRECTION; } void instr_FD() { - // std + c_comment("std"); flags[0] |= FLAG_DIRECTION; } @@ -1541,7 +1539,7 @@ DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_FF_0, inc16(___)) DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_FF_1, dec16(___)) void instr16_FF_2_helper(int32_t data) { - // call near + c_comment("call near"); int32_t cs = get_seg_cs(); push16(get_real_eip()); instruction_pointer[0] = cs + data; @@ -1555,7 +1553,7 @@ void instr16_FF_3_reg(int32_t r) } void instr16_FF_3_mem(int32_t addr) { - // callf + c_comment("callf"); int32_t new_ip = safe_read16(addr); int32_t new_cs = safe_read16(addr + 2); @@ -1564,7 +1562,7 @@ void instr16_FF_3_mem(int32_t addr) } void instr16_FF_4_helper(int32_t data) { - // jmp near + c_comment("jmp near"); instruction_pointer[0] = get_seg_cs() + data; dbg_assert(is_asize_32() || get_real_eip() < 0x10000); } @@ -1576,7 +1574,7 @@ void instr16_FF_5_reg(int32_t r) } void instr16_FF_5_mem(int32_t addr) { - // jmpf + c_comment("jmpf"); int32_t new_ip = safe_read16(addr); int32_t new_cs = safe_read16(addr + 2); @@ -1589,7 +1587,7 @@ DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_FF_0, inc32(___)) DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_FF_1, dec32(___)) void instr32_FF_2_helper(int32_t data) { - // call near + c_comment("call near"); int32_t cs = get_seg_cs(); push32(get_real_eip()); dbg_assert(is_asize_32() || data < 0x10000); @@ -1603,7 +1601,7 @@ void instr32_FF_3_reg(int32_t r) } void instr32_FF_3_mem(int32_t addr) { - // callf + c_comment("callf"); int32_t new_ip = safe_read32s(addr); int32_t new_cs = safe_read16(addr + 4); @@ -1621,7 +1619,7 @@ void instr32_FF_3_mem(int32_t addr) } void instr32_FF_4_helper(int32_t data) { - // jmp near + c_comment("jmp near"); dbg_assert(is_asize_32() || data < 0x10000); instruction_pointer[0] = get_seg_cs() + data; } @@ -1633,7 +1631,7 @@ void instr32_FF_5_reg(int32_t r) } void instr32_FF_5_mem(int32_t addr) { - // jmpf + c_comment("jmpf"); int32_t new_ip = safe_read32s(addr); int32_t new_cs = safe_read16(addr + 4); diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 84670b90..4dd7def0 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -25,7 +25,7 @@ const bool ENABLE_ACPI = true; bool apic_enabled = false; void instr_0F00_0_mem(int32_t addr) { - // sldt + c_comment("sldt"); if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } safe_write16(addr, sreg[LDTR]); } @@ -34,7 +34,7 @@ void instr_0F00_0_reg(int32_t r) { write_reg_osize(r, sreg[LDTR]); } void instr_0F00_1_mem(int32_t addr) { - // str + c_comment("str"); if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } safe_write16(addr, sreg[TR]); } @@ -43,7 +43,7 @@ void instr_0F00_1_reg(int32_t r) { write_reg_osize(r, sreg[TR]); } void instr_0F00_2_mem(int32_t addr) { - // lldt + c_comment("lldt"); if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } if(cpl[0]) { trigger_gp_non_raising(0); return; } load_ldt(safe_read16(addr)); @@ -54,7 +54,7 @@ void instr_0F00_2_reg(int32_t r) { load_ldt(read_reg16(r)); } void instr_0F00_3_mem(int32_t addr) { - // ltr + c_comment("ltr"); if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } if(cpl[0]) { trigger_gp_non_raising(0); return; } load_tr(safe_read16(addr)); @@ -84,7 +84,7 @@ void instr_0F00_5_reg(int32_t r) { void instr_0F01_0_reg(int32_t r) { trigger_ud(); } void instr_0F01_0_mem(int32_t addr) { - // sgdt + c_comment("sgdt"); writable_or_pagefault(addr, 6); int32_t mask = is_osize_32() ? -1 : 0x00FFFFFF; safe_write16(addr, gdtr_size[0]); @@ -92,7 +92,7 @@ void instr_0F01_0_mem(int32_t addr) { } void instr_0F01_1_reg(int32_t r) { trigger_ud(); } void instr_0F01_1_mem(int32_t addr) { - // sidt + c_comment("sidt"); writable_or_pagefault(addr, 6); int32_t mask = is_osize_32() ? -1 : 0x00FFFFFF; safe_write16(addr, idtr_size[0]); @@ -100,7 +100,7 @@ void instr_0F01_1_mem(int32_t addr) { } void instr_0F01_2_reg(int32_t r) { trigger_ud(); } void instr_0F01_2_mem(int32_t addr) { - // lgdt + c_comment("lgdt"); if(cpl[0]) { trigger_gp_non_raising(0); return; } int32_t size = safe_read16(addr); int32_t offset = safe_read32s(addr + 2); @@ -110,7 +110,7 @@ void instr_0F01_2_mem(int32_t addr) { } void instr_0F01_3_reg(int32_t r) { trigger_ud(); } void instr_0F01_3_mem(int32_t addr) { - // lidt + c_comment("lidt"); if(cpl[0]) { trigger_gp_non_raising(0); return; } int32_t size = safe_read16(addr); int32_t offset = safe_read32s(addr + 2); @@ -120,7 +120,7 @@ void instr_0F01_3_mem(int32_t addr) { } void instr_0F01_4_reg(int32_t r) { - // smsw + c_comment("smsw"); write_reg_osize(r, cr[0]); } void instr_0F01_4_mem(int32_t addr) { @@ -132,7 +132,7 @@ void lmsw(int32_t new_cr0) { if(protected_mode[0]) { - // lmsw cannot be used to switch back + c_comment("lmsw cannot be used to switch back"); new_cr0 |= CR0_PE; } @@ -149,7 +149,7 @@ void instr_0F01_6_mem(int32_t addr) { void instr_0F01_7_reg(int32_t r) { trigger_ud(); } void instr_0F01_7_mem(int32_t addr) { - // invlpg + c_comment("invlpg"); if(cpl[0]) { trigger_gp_non_raising(0); return; } invlpg(addr); } @@ -164,7 +164,7 @@ void instr_0F04() { undefined_instruction(); } void instr_0F05() { undefined_instruction(); } void instr_0F06() { - // clts + c_comment("clts"); if(cpl[0]) { dbg_log("clts #gp"); @@ -179,7 +179,7 @@ void instr_0F06() { void instr_0F07() { undefined_instruction(); } void instr_0F08() { - // invd + c_comment("invd"); undefined_instruction(); } @@ -191,20 +191,20 @@ void instr_0F09() { } else { - // wbinvd + c_comment("wbinvd"); } } void instr_0F0A() { undefined_instruction(); } void instr_0F0B() { - // UD2 + c_comment("UD2"); trigger_ud(); } void instr_0F0C() { undefined_instruction(); } void instr_0F0D() { - // nop + c_comment("nop"); undefined_instruction(); } @@ -212,91 +212,91 @@ void instr_0F0E() { undefined_instruction(); } void instr_0F0F() { undefined_instruction(); } void instr_0F10(union reg128 source, int32_t r) { - // movups xmm, xmm/m128 + c_comment("movups xmm, xmm/m128"); mov_rm_r128(source, r); } DEFINE_SSE_SPLIT(instr_0F10, safe_read128s, read_xmm128s) void instr_F30F10_reg(int32_t r1, int32_t r2) { - // movss xmm, xmm/m32 + c_comment("movss xmm, xmm/m32"); union reg128 data = read_xmm128s(r1); union reg128 orig = read_xmm128s(r2); write_xmm128(r2, data.u32[0], orig.u32[1], orig.u32[2], orig.u32[3]); } void instr_F30F10_mem(int32_t addr, int32_t r) { - // movss xmm, xmm/m32 + c_comment("movss xmm, xmm/m32"); int32_t data = safe_read32s(addr); write_xmm128(r, data, 0, 0, 0); } void instr_660F10(union reg128 source, int32_t r) { - // movupd xmm, xmm/m128 + c_comment("movupd xmm, xmm/m128"); mov_rm_r128(source, r); } DEFINE_SSE_SPLIT(instr_660F10, safe_read128s, read_xmm128s) void instr_F20F10_reg(int32_t r1, int32_t r2) { - // movsd xmm, xmm/m64 + c_comment("movsd xmm, xmm/m64"); union reg128 data = read_xmm128s(r1); union reg128 orig = read_xmm128s(r2); write_xmm128(r2, data.u32[0], data.u32[1], orig.u32[2], orig.u32[3]); } void instr_F20F10_mem(int32_t addr, int32_t r) { - // movsd xmm, xmm/m64 + c_comment("movsd xmm, xmm/m64"); union reg64 data = safe_read64s(addr); write_xmm128(r, data.u32[0], data.u32[1], 0, 0); } void instr_0F11_reg(int32_t r1, int32_t r2) { - // movups xmm/m128, xmm + c_comment("movups xmm/m128, xmm"); mov_r_r128(r1, r2); } void instr_0F11_mem(int32_t addr, int32_t r) { - // movups xmm/m128, xmm + c_comment("movups xmm/m128, xmm"); mov_r_m128(addr, r); } void instr_F30F11_reg(int32_t rm_dest, int32_t reg_src) { - // movss xmm/m32, xmm + c_comment("movss xmm/m32, xmm"); union reg128 data = read_xmm128s(reg_src); union reg128 orig = read_xmm128s(rm_dest); write_xmm128(rm_dest, data.u32[0], orig.u32[1], orig.u32[2], orig.u32[3]); } void instr_F30F11_mem(int32_t addr, int32_t r) { - // movss xmm/m32, xmm + c_comment("movss xmm/m32, xmm"); union reg128 data = read_xmm128s(r); safe_write32(addr, data.u32[0]); } void instr_660F11_reg(int32_t r1, int32_t r2) { - // movupd xmm/m128, xmm + c_comment("movupd xmm/m128, xmm"); mov_r_r128(r1, r2); } void instr_660F11_mem(int32_t addr, int32_t r) { - // movupd xmm/m128, xmm + c_comment("movupd xmm/m128, xmm"); mov_r_m128(addr, r); } void instr_F20F11_reg(int32_t r1, int32_t r2) { - // movsd xmm/m64, xmm + c_comment("movsd xmm/m64, xmm"); union reg128 data = read_xmm128s(r2); union reg128 orig = read_xmm128s(r1); write_xmm128(r1, data.u32[0], data.u32[1], orig.u32[2], orig.u32[3]); } void instr_F20F11_mem(int32_t addr, int32_t r) { - // movsd xmm/m64, xmm + c_comment("movsd xmm/m64, xmm"); union reg64 data = read_xmm64s(r); safe_write64(addr, data.u64[0]); } void instr_0F12_mem(int32_t addr, int32_t r) { - // movlps xmm, m64 + c_comment("movlps xmm, m64"); union reg64 data = safe_read64s(addr); union reg128 orig = read_xmm128s(r); write_xmm128(r, data.u32[0], data.u32[1], orig.u32[2], orig.u32[3]); } void instr_0F12_reg(int32_t r1, int32_t r2) { - // movhlps xmm, xmm + c_comment("movhlps xmm, xmm"); union reg128 data = read_xmm128s(r1); union reg128 orig = read_xmm128s(r2); write_xmm128(r2, data.u32[2], data.u32[3], orig.u32[2], orig.u32[3]); @@ -304,7 +304,7 @@ void instr_0F12_reg(int32_t r1, int32_t r2) { void instr_660F12_reg(int32_t r1, int32_t r) { trigger_ud(); } void instr_660F12_mem(int32_t addr, int32_t r) { - // movlpd xmm, m64 + c_comment("movlpd xmm, m64"); union reg64 data = safe_read64s(addr); write_xmm64(r, data); } @@ -314,7 +314,7 @@ void instr_F30F12_mem(int32_t addr, int32_t r) { unimplemented_sse(); } void instr_F30F12_reg(int32_t r1, int32_t r2) { unimplemented_sse(); } void instr_0F13_mem(int32_t addr, int32_t r) { - // movlps m64, xmm + c_comment("movlps m64, xmm"); movl_r128_m64(addr, r); } @@ -322,13 +322,13 @@ void instr_0F13_reg(int32_t r1, int32_t r2) { trigger_ud(); } void instr_660F13_reg(int32_t r1, int32_t r) { trigger_ud(); } void instr_660F13_mem(int32_t addr, int32_t r) { - // movlpd xmm/m64, xmm + c_comment("movlpd xmm/m64, xmm"); movl_r128_m64(addr, r); } void instr_0F14(union reg64 source, int32_t r) { - // unpcklps xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("unpcklps xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg64 destination = read_xmm64s(r); write_xmm128( @@ -342,8 +342,8 @@ void instr_0F14(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0F14, safe_read64s, read_xmm64s) void instr_660F14(union reg64 source, int32_t r) { - // unpcklpd xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("unpcklpd xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg64 destination = read_xmm64s(r); write_xmm128( @@ -357,8 +357,8 @@ void instr_660F14(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660F14, safe_read64s, read_xmm64s) void instr_0F15(union reg128 source, int32_t r) { - // unpckhps xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("unpckhps xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); write_xmm128( @@ -372,8 +372,8 @@ void instr_0F15(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0F15, safe_read128s, read_xmm128s) void instr_660F15(union reg128 source, int32_t r) { - // unpckhpd xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("unpckhpd xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); write_xmm128( @@ -387,44 +387,43 @@ void instr_660F15(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660F15, safe_read128s, read_xmm128s) void instr_0F16_mem(int32_t addr, int32_t r) { - // movhps xmm, m64 + c_comment("movhps xmm, m64"); movh_m64_r128(addr, r); } void instr_0F16_reg(int32_t r1, int32_t r2) { - // movlhps xmm, xmm + c_comment("movlhps xmm, xmm"); union reg128 data = read_xmm128s(r1); union reg128 orig = read_xmm128s(r2); write_xmm128(r2, orig.u32[0], orig.u32[1], data.u32[0], data.u32[1]); } void instr_660F16_mem(int32_t addr, int32_t r) { - // movhpd xmm, m64 + c_comment("movhpd xmm, m64"); movh_m64_r128(addr, r); } void instr_660F16_reg(int32_t r1, int32_t r2) { trigger_ud(); } void instr_F30F16() { unimplemented_sse(); } void instr_0F17_mem(int32_t addr, int32_t r) { - // movhps m64, xmm + c_comment("movhps m64, xmm"); movh_r128_m64(addr, r); } void instr_0F17_reg(int32_t r1, int32_t r2) { trigger_ud(); } void instr_660F17_mem(int32_t addr, int32_t r) { - // movhpd m64, xmm + c_comment("movhpd m64, xmm"); movh_r128_m64(addr, r); } void instr_660F17_reg(int32_t r1, int32_t r2) { trigger_ud(); } void instr_0F18_reg(int32_t r1, int32_t r2) { - // reserved nop + c_comment("reserved nop"); } void instr_0F18_mem(int32_t addr, int32_t r) { - // prefetch - // nop for us + c_comment("prefetch"); + c_comment("nop for us"); } -// hintable nops void instr_0F19_reg(int32_t r1, int32_t r2) { } void instr_0F19_mem(int32_t addr, int32_t r) { } void instr_0F1A() { undefined_instruction(); } @@ -484,7 +483,7 @@ void instr_0F21(int32_t r, int32_t dreg_index) { } else { - // DR4 and DR5 refer to DR6 and DR7 respectively + c_comment("DR4 and DR5 refer to DR6 and DR7 respectively"); dreg_index += 2; } } @@ -504,7 +503,7 @@ void instr_0F22(int32_t r, int32_t creg) { int32_t data = read_reg32(r); - // mov cr, addr + c_comment("mov cr, addr"); switch(creg) { case 0: @@ -571,7 +570,7 @@ void instr_0F23(int32_t r, int32_t dreg_index) { } else { - // DR4 and DR5 refer to DR6 and DR7 respectively + c_comment("DR4 and DR5 refer to DR6 and DR7 respectively"); dreg_index += 2; } } @@ -587,47 +586,47 @@ void instr_0F26() { undefined_instruction(); } void instr_0F27() { undefined_instruction(); } void instr_0F28(union reg128 source, int32_t r) { - // movaps xmm, xmm/m128 - // XXX: Aligned read or #gp + c_comment("movaps xmm, xmm/m128"); + c_comment("XXX: Aligned read or #gp"); mov_rm_r128(source, r); } DEFINE_SSE_SPLIT(instr_0F28, safe_read128s, read_xmm128s) void instr_660F28(union reg128 source, int32_t r) { - // movapd xmm, xmm/m128 - // XXX: Aligned read or #gp - // Note: Same as movdqa (660F6F) + c_comment("movapd xmm, xmm/m128"); + c_comment("XXX: Aligned read or #gp"); + c_comment("Note: Same as movdqa (660F6F)"); mov_rm_r128(source, r); } DEFINE_SSE_SPLIT(instr_660F28, safe_read128s, read_xmm128s) void instr_0F29_mem(int32_t addr, int32_t r) { - // movaps m128, xmm + c_comment("movaps m128, xmm"); union reg128 data = read_xmm128s(r); - // XXX: Aligned write or #gp + c_comment("XXX: Aligned write or #gp"); safe_write128(addr, data); } void instr_0F29_reg(int32_t r1, int32_t r2) { - // movaps xmm, xmm + c_comment("movaps xmm, xmm"); mov_r_r128(r1, r2); } void instr_660F29_mem(int32_t addr, int32_t r) { - // movapd m128, xmm + c_comment("movapd m128, xmm"); union reg128 data = read_xmm128s(r); - // XXX: Aligned write or #gp + c_comment("XXX: Aligned write or #gp"); safe_write128(addr, data); } void instr_660F29_reg(int32_t r1, int32_t r2) { - // movapd xmm, xmm + c_comment("movapd xmm, xmm"); mov_r_r128(r1, r2); } void instr_0F2A(union reg64 source, int32_t r) { - // cvtpi2ps xmm, mm/m64 - // XXX: The non-memory variant causes a transition from x87 FPU to MMX technology operation + c_comment("cvtpi2ps xmm, mm/m64"); + c_comment("XXX: The non-memory variant causes a transition from x87 FPU to MMX technology operation"); + c_comment("Note: Casts here can fail"); union reg64 result = { .f32 = { - // Note: Casts here can fail source.i32[0], source.i32[1], } @@ -636,11 +635,11 @@ void instr_0F2A(union reg64 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_0F2A, safe_read64s, read_mmx64s) void instr_660F2A(union reg64 source, int32_t r) { - // cvtpi2pd xmm, xmm/m64 - // XXX: The non-memory variant causes a transition from x87 FPU to MMX technology operation + c_comment("cvtpi2pd xmm, xmm/m64"); + c_comment("XXX: The non-memory variant causes a transition from x87 FPU to MMX technology operation"); + c_comment("These casts can't fail"); union reg128 result = { .f64 = { - // These casts can't fail source.i32[0], source.i32[1], } @@ -649,17 +648,17 @@ void instr_660F2A(union reg64 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_660F2A, safe_read64s, read_mmx64s) void instr_F20F2A(int32_t source, int32_t r) { - // cvtsi2sd xmm, r32/m32 + c_comment("cvtsi2sd xmm, r32/m32"); + c_comment("This cast can't fail"); union reg64 result = { - // This cast can't fail .f64 = { source } }; write_xmm64(r, result); } DEFINE_SSE_SPLIT(instr_F20F2A, safe_read32s, read_reg32) void instr_F30F2A(int32_t source, int32_t r) { - // cvtsi2ss xmm, r/m32 - // Note: This cast can fail + c_comment("cvtsi2ss xmm, r/m32"); + c_comment("Note: This cast can fail"); float_t result = source; write_xmm_f32(r, result); } @@ -667,15 +666,15 @@ DEFINE_SSE_SPLIT(instr_F30F2A, safe_read32s, read_reg32) void instr_0F2B_reg(int32_t r1, int32_t r2) { trigger_ud(); } void instr_0F2B_mem(int32_t addr, int32_t r) { - // movntps m128, xmm - // XXX: Aligned write or #gp + c_comment("movntps m128, xmm"); + c_comment("XXX: Aligned write or #gp"); mov_r_m128(addr, r); } void instr_660F2B_reg(int32_t r1, int32_t r2) { trigger_ud(); } void instr_660F2B_mem(int32_t addr, int32_t r) { - // movntpd m128, xmm - // XXX: Aligned write or #gp + c_comment("movntpd m128, xmm"); + c_comment("XXX: Aligned write or #gp"); mov_r_m128(addr, r); } @@ -686,9 +685,9 @@ void instr_660F2C(union reg128 source, int32_t r) { unimplemented_sse(); } DEFINE_SSE_SPLIT(instr_660F2C, safe_read128s, read_xmm128s) 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 + c_comment("cvttsd2si r32, xmm/m64"); + c_comment("emscripten bug causes this ported instruction to throw 'integer result unpresentable'"); + c_comment("https://github.com/kripken/emscripten/issues/5433"); if(0 * 0) { double f = source.f64[0]; @@ -720,7 +719,7 @@ void instr_660F2D(union reg128 source, int32_t r) { unimplemented_sse(); } DEFINE_SSE_SPLIT(instr_660F2D, safe_read128s, read_xmm128s) void instr_F20F2D(union reg64 source, int32_t r) { - // cvtsd2si r32, xmm/m64 + c_comment("cvtsd2si r32, xmm/m64"); write_reg32(r, sse_convert_f64_to_i32(source.f64[0])); } DEFINE_SSE_SPLIT(instr_F20F2D, safe_read64s, read_xmm64s) @@ -731,9 +730,8 @@ DEFINE_SSE_SPLIT(instr_F30F2D, fpu_load_m32, read_xmm_f32) void instr_0F2E() { unimplemented_sse(); } void instr_0F2F() { unimplemented_sse(); } -// wrmsr void instr_0F30() { - // wrmsr - write maschine specific register + c_comment("wrmsr - write maschine specific register"); if(cpl[0]) { @@ -786,20 +784,20 @@ void instr_0F30() { } else if(index == MSR_MISC_FEATURE_ENABLES) { - // Linux 4, see: https://patchwork.kernel.org/patch/9528279/ + c_comment("Linux 4, see: https://patchwork.kernel.org/patch/9528279/"); } else if(index == IA32_MISC_ENABLE) - { // Enable Misc. Processor Features + { c_comment("Enable Misc. Processor Features"); } else if(index == IA32_MCG_CAP) { - // netbsd + c_comment("netbsd"); } else if(index == IA32_KERNEL_GS_BASE) { - // Only used in 64 bit mode (by SWAPGS), but set by kvm-unit-test + c_comment("Only used in 64 bit mode (by SWAPGS), but set by kvm-unit-test"); dbg_log("GS Base written"); } else @@ -810,7 +808,7 @@ void instr_0F30() { } void instr_0F31() { - // rdtsc - read timestamp counter + c_comment("rdtsc - read timestamp counter"); if(!cpl[0] || !(cr[4] & CR4_TSD)) { @@ -828,7 +826,7 @@ void instr_0F31() { } void instr_0F32() { - // rdmsr - read maschine specific register + c_comment("rdmsr - read maschine specific register"); if(cpl[0]) { trigger_gp_non_raising(0); @@ -897,13 +895,13 @@ void instr_0F32() { } else if(index == IA32_MISC_ENABLE) - { // Enable Misc. Processor Features - low = 1 << 0; // fast string + { c_comment("Enable Misc. Processor Features"); + low = 1 << 0; c_comment("fast string"); } else if(index == IA32_RTIT_CTL) { - // linux4 + c_comment("linux4"); } else if(index == MSR_SMI_COUNT) @@ -912,7 +910,7 @@ void instr_0F32() { } else if(index == IA32_MCG_CAP) { - // netbsd + c_comment("netbsd"); } else if(index == MSR_PKG_C2_RESIDENCY) @@ -929,12 +927,12 @@ void instr_0F32() { } void instr_0F33() { - // rdpmc + c_comment("rdpmc"); undefined_instruction(); } void instr_0F34() { - // sysenter + c_comment("sysenter"); int32_t seg = sysenter_cs[0] & 0xFFFC; if(!protected_mode[0] || seg == 0) @@ -967,7 +965,7 @@ void instr_0F34() { } void instr_0F35() { - // sysexit + c_comment("sysexit"); int32_t seg = sysenter_cs[0] & 0xFFFC; if(!protected_mode[0] || cpl[0] || seg == 0) @@ -1001,7 +999,7 @@ void instr_0F35() { void instr_0F36() { undefined_instruction(); } void instr_0F37() { - // getsec + c_comment("getsec"); undefined_instruction(); } @@ -1052,7 +1050,7 @@ DEFINE_MODRM_INSTR_READ32(instr32_0F4F, cmovcc32(!test_le(), ___, r)) void instr_0F50_reg(int32_t r1, int32_t r2) { - // movmskps r, xmm + c_comment("movmskps r, xmm"); union reg128 source = read_xmm128s(r1); int32_t data = source.u32[0] >> 31 | (source.u32[1] >> 31) << 1 | (source.u32[2] >> 31) << 2 | (source.u32[3] >> 31) << 3; @@ -1061,7 +1059,7 @@ void instr_0F50_reg(int32_t r1, int32_t r2) { void instr_0F50_mem(int32_t addr, int32_t r1) { trigger_ud(); } void instr_660F50_reg(int32_t r1, int32_t r2) { - // movmskpd r, xmm + c_comment("movmskpd r, xmm"); union reg128 source = read_xmm128s(r1); int32_t data = (source.u32[1] >> 31) | (source.u32[3] >> 31) << 1; write_reg32(r2, data); @@ -1069,7 +1067,7 @@ void instr_660F50_reg(int32_t r1, int32_t r2) { void instr_660F50_mem(int32_t addr, int32_t r1) { trigger_ud(); } void instr_0F51(union reg128 source, int32_t r) { - // sqrtps xmm, xmm/mem128 + c_comment("sqrtps xmm, xmm/mem128"); union reg128 result = { .f32 = { sqrtf(source.f32[0]), @@ -1082,7 +1080,7 @@ void instr_0F51(union reg128 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_0F51, safe_read128s, read_xmm128s) void instr_660F51(union reg128 source, int32_t r) { - // sqrtpd xmm, xmm/mem128 + c_comment("sqrtpd xmm, xmm/mem128"); union reg128 result = { .f64 = { sqrt(source.f64[0]), @@ -1093,7 +1091,7 @@ void instr_660F51(union reg128 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_660F51, safe_read128s, read_xmm128s) void instr_F20F51(union reg64 source, int32_t r) { - // sqrtsd xmm, xmm/mem64 + c_comment("sqrtsd xmm, xmm/mem64"); union reg64 result = { .f64 = { sqrt(source.f64[0]), } }; @@ -1101,7 +1099,7 @@ void instr_F20F51(union reg64 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_F20F51, safe_read64s, read_xmm64s) void instr_F30F51(float_t source, int32_t r) { - // sqrtss xmm, xmm/mem32 + c_comment("sqrtss xmm, xmm/mem32"); write_xmm_f32(r, sqrtf(source)); } DEFINE_SSE_SPLIT(instr_F30F51, fpu_load_m32, read_xmm_f32) @@ -1109,7 +1107,7 @@ DEFINE_SSE_SPLIT(instr_F30F51, fpu_load_m32, read_xmm_f32) void instr_0F52() { unimplemented_sse(); } void instr_0F53(union reg128 source, int32_t r) { - // rcpps xmm, xmm/m128 + c_comment("rcpps xmm, xmm/m128"); union reg128 result = { .f32 = { 1 / source.f32[0], @@ -1123,69 +1121,69 @@ void instr_0F53(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0F53, safe_read128s, read_xmm128s) void instr_F30F53(float_t source, int32_t r) { - // rcpss xmm, xmm/m32 + c_comment("rcpss xmm, xmm/m32"); write_xmm_f32(r, 1 / source); } DEFINE_SSE_SPLIT(instr_F30F53, fpu_load_m32, read_xmm_f32) void instr_0F54(union reg128 source, int32_t r) { - // andps xmm, xmm/mem128 - // XXX: Aligned access or #gp + c_comment("andps xmm, xmm/mem128"); + c_comment("XXX: Aligned access or #gp"); pand_r128(source, r); } DEFINE_SSE_SPLIT(instr_0F54, safe_read128s, read_xmm128s) void instr_660F54(union reg128 source, int32_t r) { - // andpd xmm, xmm/mem128 - // XXX: Aligned access or #gp + c_comment("andpd xmm, xmm/mem128"); + c_comment("XXX: Aligned access or #gp"); pand_r128(source, r); } DEFINE_SSE_SPLIT(instr_660F54, safe_read128s, read_xmm128s) void instr_0F55(union reg128 source, int32_t r) { - // andnps xmm, xmm/mem128 - // XXX: Aligned access or #gp + c_comment("andnps xmm, xmm/mem128"); + c_comment("XXX: Aligned access or #gp"); pandn_r128(source, r); } DEFINE_SSE_SPLIT(instr_0F55, safe_read128s, read_xmm128s) void instr_660F55(union reg128 source, int32_t r) { - // andnpd xmm, xmm/mem128 - // XXX: Aligned access or #gp + c_comment("andnpd xmm, xmm/mem128"); + c_comment("XXX: Aligned access or #gp"); pandn_r128(source, r); } DEFINE_SSE_SPLIT(instr_660F55, safe_read128s, read_xmm128s) void instr_0F56(union reg128 source, int32_t r) { - // orps xmm, xmm/mem128 - // XXX: Aligned access or #gp + c_comment("orps xmm, xmm/mem128"); + c_comment("XXX: Aligned access or #gp"); por_r128(source, r); } DEFINE_SSE_SPLIT(instr_0F56, safe_read128s, read_xmm128s) void instr_660F56(union reg128 source, int32_t r) { - // orpd xmm, xmm/mem128 - // XXX: Aligned access or #gp + c_comment("orpd xmm, xmm/mem128"); + c_comment("XXX: Aligned access or #gp"); por_r128(source, r); } DEFINE_SSE_SPLIT(instr_660F56, safe_read128s, read_xmm128s) void instr_0F57(union reg128 source, int32_t r) { - // xorps xmm, xmm/mem128 - // XXX: Aligned access or #gp + c_comment("xorps xmm, xmm/mem128"); + c_comment("XXX: Aligned access or #gp"); pxor_r128(source, r); } DEFINE_SSE_SPLIT(instr_0F57, safe_read128s, read_xmm128s) void instr_660F57(union reg128 source, int32_t r) { - // xorpd xmm, xmm/mem128 - // XXX: Aligned access or #gp + c_comment("xorpd xmm, xmm/mem128"); + c_comment("XXX: Aligned access or #gp"); pxor_r128(source, r); } DEFINE_SSE_SPLIT(instr_660F57, safe_read128s, read_xmm128s) void instr_0F58(union reg128 source, int32_t r) { - // addps xmm, xmm/mem128 + c_comment("addps xmm, xmm/mem128"); union reg128 destination = read_xmm128s(r); union reg128 result = { .f32 = { @@ -1199,7 +1197,7 @@ void instr_0F58(union reg128 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_0F58, safe_read128s, read_xmm128s) void instr_660F58(union reg128 source, int32_t r) { - // addpd xmm, xmm/mem128 + c_comment("addpd xmm, xmm/mem128"); union reg128 destination = read_xmm128s(r); union reg128 result = { .f64 = { @@ -1211,7 +1209,7 @@ void instr_660F58(union reg128 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_660F58, safe_read128s, read_xmm128s) void instr_F20F58(union reg64 source, int32_t r) { - // addsd xmm, xmm/mem64 + c_comment("addsd xmm, xmm/mem64"); union reg64 destination = read_xmm64s(r); union reg64 result = { .f64 = { source.f64[0] + destination.f64[0], } @@ -1220,7 +1218,7 @@ void instr_F20F58(union reg64 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_F20F58, safe_read64s, read_xmm64s) void instr_F30F58(float_t source, int32_t r) { - // addss xmm, xmm/mem32 + c_comment("addss xmm, xmm/mem32"); float_t destination = read_xmm_f32(r); float result = source + destination; write_xmm_f32(r, result); @@ -1228,7 +1226,7 @@ void instr_F30F58(float_t source, int32_t r) { DEFINE_SSE_SPLIT(instr_F30F58, fpu_load_m32, read_xmm_f32) void instr_0F59(union reg128 source, int32_t r) { - // mulps xmm, xmm/mem128 + c_comment("mulps xmm, xmm/mem128"); union reg128 destination = read_xmm128s(r); union reg128 result = { .f32 = { @@ -1242,7 +1240,7 @@ void instr_0F59(union reg128 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_0F59, safe_read128s, read_xmm128s) void instr_660F59(union reg128 source, int32_t r) { - // mulpd xmm, xmm/mem128 + c_comment("mulpd xmm, xmm/mem128"); union reg128 destination = read_xmm128s(r); union reg128 result = { .f64 = { @@ -1254,7 +1252,7 @@ void instr_660F59(union reg128 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_660F59, safe_read128s, read_xmm128s) void instr_F20F59(union reg64 source, int32_t r) { - // mulsd xmm, xmm/mem64 + c_comment("mulsd xmm, xmm/mem64"); union reg64 destination = read_xmm64s(r); union reg64 result = { .f64 = { source.f64[0] * destination.f64[0], } @@ -1263,7 +1261,7 @@ void instr_F20F59(union reg64 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_F20F59, safe_read64s, read_xmm64s) void instr_F30F59(float_t source, int32_t r) { - // mulss xmm, xmm/mem32 + c_comment("mulss xmm, xmm/mem32"); float_t destination = read_xmm_f32(r); float result = source * destination; write_xmm_f32(r, result); @@ -1274,7 +1272,7 @@ void instr_0F5A() { unimplemented_sse(); } void instr_0F5B() { unimplemented_sse(); } void instr_0F5C(union reg128 source, int32_t r) { - // subps xmm, xmm/mem128 + c_comment("subps xmm, xmm/mem128"); union reg128 destination = read_xmm128s(r); union reg128 result = { .f32 = { @@ -1288,7 +1286,7 @@ void instr_0F5C(union reg128 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_0F5C, safe_read128s, read_xmm128s) void instr_660F5C(union reg128 source, int32_t r) { - // subpd xmm, xmm/mem128 + c_comment("subpd xmm, xmm/mem128"); union reg128 destination = read_xmm128s(r); union reg128 result = { .f64 = { @@ -1300,7 +1298,7 @@ void instr_660F5C(union reg128 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_660F5C, safe_read128s, read_xmm128s) void instr_F20F5C(union reg64 source, int32_t r) { - // subsd xmm, xmm/mem64 + c_comment("subsd xmm, xmm/mem64"); union reg64 destination = read_xmm64s(r); union reg64 result = { .f64 = { destination.f64[0] - source.f64[0], } @@ -1309,7 +1307,7 @@ void instr_F20F5C(union reg64 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_F20F5C, safe_read64s, read_xmm64s) void instr_F30F5C(float_t source, int32_t r) { - // subss xmm, xmm/mem32 + c_comment("subss xmm, xmm/mem32"); float_t destination = read_xmm_f32(r); float result = destination - source; write_xmm_f32(r, result); @@ -1317,7 +1315,7 @@ void instr_F30F5C(float_t source, int32_t r) { DEFINE_SSE_SPLIT(instr_F30F5C, fpu_load_m32, read_xmm_f32) void instr_0F5D(union reg128 source, int32_t r) { - // minps xmm, xmm/mem128 + c_comment("minps xmm, xmm/mem128"); union reg128 destination = read_xmm128s(r); union reg128 result = { .f32 = { @@ -1331,7 +1329,7 @@ void instr_0F5D(union reg128 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_0F5D, safe_read128s, read_xmm128s) void instr_660F5D(union reg128 source, int32_t r) { - // minpd xmm, xmm/mem128 + c_comment("minpd xmm, xmm/mem128"); union reg128 destination = read_xmm128s(r); union reg128 result = { .f64 = { @@ -1343,7 +1341,7 @@ void instr_660F5D(union reg128 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_660F5D, safe_read128s, read_xmm128s) void instr_F20F5D(union reg64 source, int32_t r) { - // minsd xmm, xmm/mem64 + c_comment("minsd xmm, xmm/mem64"); union reg64 destination = read_xmm64s(r); union reg64 result = { .f64 = { sse_min(destination.f64[0], source.f64[0]), } @@ -1352,7 +1350,7 @@ void instr_F20F5D(union reg64 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_F20F5D, safe_read64s, read_xmm64s) void instr_F30F5D(float_t source, int32_t r) { - // minss xmm, xmm/mem32 + c_comment("minss xmm, xmm/mem32"); float_t destination = read_xmm_f32(r); float result = sse_min(destination, source); write_xmm_f32(r, result); @@ -1360,7 +1358,7 @@ void instr_F30F5D(float_t source, int32_t r) { DEFINE_SSE_SPLIT(instr_F30F5D, fpu_load_m32, read_xmm_f32) void instr_0F5E(union reg128 source, int32_t r) { - // divps xmm, xmm/mem128 + c_comment("divps xmm, xmm/mem128"); union reg128 destination = read_xmm128s(r); union reg128 result = { .f32 = { @@ -1374,7 +1372,7 @@ void instr_0F5E(union reg128 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_0F5E, safe_read128s, read_xmm128s) void instr_660F5E(union reg128 source, int32_t r) { - // divpd xmm, xmm/mem128 + c_comment("divpd xmm, xmm/mem128"); union reg128 destination = read_xmm128s(r); union reg128 result = { .f64 = { @@ -1386,7 +1384,7 @@ void instr_660F5E(union reg128 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_660F5E, safe_read128s, read_xmm128s) void instr_F20F5E(union reg64 source, int32_t r) { - // divsd xmm, xmm/mem64 + c_comment("divsd xmm, xmm/mem64"); union reg64 destination = read_xmm64s(r); union reg64 result = { .f64 = { destination.f64[0] / source.f64[0], } @@ -1395,7 +1393,7 @@ void instr_F20F5E(union reg64 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_F20F5E, safe_read64s, read_xmm64s) void instr_F30F5E(float_t source, int32_t r) { - // divss xmm, xmm/mem32 + c_comment("divss xmm, xmm/mem32"); float_t destination = read_xmm_f32(r); float result = destination / source; write_xmm_f32(r, result); @@ -1403,7 +1401,7 @@ void instr_F30F5E(float_t source, int32_t r) { DEFINE_SSE_SPLIT(instr_F30F5E, fpu_load_m32, read_xmm_f32) void instr_0F5F(union reg128 source, int32_t r) { - // maxps xmm, xmm/mem128 + c_comment("maxps xmm, xmm/mem128"); union reg128 destination = read_xmm128s(r); union reg128 result = { .f32 = { @@ -1417,7 +1415,7 @@ void instr_0F5F(union reg128 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_0F5F, safe_read128s, read_xmm128s) void instr_660F5F(union reg128 source, int32_t r) { - // maxpd xmm, xmm/mem128 + c_comment("maxpd xmm, xmm/mem128"); union reg128 destination = read_xmm128s(r); union reg128 result = { .f64 = { @@ -1429,7 +1427,7 @@ void instr_660F5F(union reg128 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_660F5F, safe_read128s, read_xmm128s) void instr_F20F5F(union reg64 source, int32_t r) { - // maxsd xmm, xmm/mem64 + c_comment("maxsd xmm, xmm/mem64"); union reg64 destination = read_xmm64s(r); union reg64 result = { .f64 = { sse_max(destination.f64[0], source.f64[0]), } @@ -1438,7 +1436,7 @@ void instr_F20F5F(union reg64 source, int32_t r) { } DEFINE_SSE_SPLIT(instr_F20F5F, safe_read64s, read_xmm64s) void instr_F30F5F(float_t source, int32_t r) { - // maxss xmm, xmm/mem32 + c_comment("maxss xmm, xmm/mem32"); float_t destination = read_xmm_f32(r); float result = sse_max(destination, source); write_xmm_f32(r, result); @@ -1447,7 +1445,7 @@ DEFINE_SSE_SPLIT(instr_F30F5F, fpu_load_m32, read_xmm_f32) void instr_0F60(int32_t source, int32_t r) { - // punpcklbw mm, mm/m32 + c_comment("punpcklbw mm, mm/m32"); union reg64 destination = read_mmx64s(r); int32_t byte0 = destination.u8[0]; @@ -1467,8 +1465,8 @@ void instr_0F60(int32_t source, int32_t r) { DEFINE_SSE_SPLIT(instr_0F60, safe_read32s, read_mmx32s) void instr_660F60(union reg64 source, int32_t r) { - // punpcklbw xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("punpcklbw xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg64 destination = read_xmm64s(r); write_xmm128( r, @@ -1481,7 +1479,7 @@ void instr_660F60(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660F60, safe_read64s, read_xmm64s) void instr_0F61(int32_t source, int32_t r) { - // punpcklwd mm, mm/m32 + c_comment("punpcklwd mm, mm/m32"); union reg64 destination = read_mmx64s(r); int32_t word0 = destination.u16[0]; @@ -1497,8 +1495,8 @@ void instr_0F61(int32_t source, int32_t r) { DEFINE_SSE_SPLIT(instr_0F61, safe_read32s, read_mmx32s) void instr_660F61(union reg64 source, int32_t r) { - // punpcklwd xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("punpcklwd xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg64 destination = read_xmm64s(r); write_xmm128( r, @@ -1511,15 +1509,15 @@ void instr_660F61(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660F61, safe_read64s, read_xmm64s) void instr_0F62(int32_t source, int32_t r) { - // punpckldq mm, mm/m32 + c_comment("punpckldq mm, mm/m32"); union reg64 destination = read_mmx64s(r); write_mmx64(r, destination.u32[0], source); } DEFINE_SSE_SPLIT(instr_0F62, safe_read32s, read_mmx32s) void instr_660F62(union reg128 source, int32_t r) { - // punpckldq xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("punpckldq xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); write_xmm128( r, @@ -1532,7 +1530,7 @@ void instr_660F62(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660F62, safe_read128s, read_xmm128s) void instr_0F63(union reg64 source, int32_t r) { - // packsswb mm, mm/m64 + c_comment("packsswb mm, mm/m64"); union reg64 destination = read_mmx64s(r); int32_t low = saturate_sw_to_sb(destination.u16[0]) | @@ -1550,8 +1548,8 @@ void instr_0F63(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0F63, safe_read64s, read_mmx64s) void instr_660F63(union reg128 source, int32_t r) { - // packsswb xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("packsswb xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); int32_t dword0 = saturate_sw_to_sb(destination.u16[0]) | @@ -1579,7 +1577,7 @@ void instr_660F63(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660F63, safe_read128s, read_xmm128s) void instr_0F64(union reg64 source, int32_t r) { - // pcmpgtb mm, mm/m64 + c_comment("pcmpgtb mm, mm/m64"); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -1593,8 +1591,8 @@ void instr_0F64(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0F64, safe_read64s, read_mmx64s) void instr_660F64(union reg128 source, int32_t r) { - // pcmpgtb xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pcmpgtb xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); union reg128 result = { { 0 } }; @@ -1608,7 +1606,7 @@ void instr_660F64(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660F64, safe_read128s, read_xmm128s) void instr_0F65(union reg64 source, int32_t r) { - // pcmpgtw mm, mm/m64 + c_comment("pcmpgtw mm, mm/m64"); union reg64 destination = read_mmx64s(r); int32_t word0 = destination.i16[0] > source.i16[0] ? 0xFFFF : 0; @@ -1624,8 +1622,8 @@ void instr_0F65(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0F65, safe_read64s, read_mmx64s) void instr_660F65(union reg128 source, int32_t r) { - // pcmpgtw xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pcmpgtw xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); union reg128 result = { { 0 } }; @@ -1639,7 +1637,7 @@ void instr_660F65(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660F65, safe_read128s, read_xmm128s) void instr_0F66(union reg64 source, int32_t r) { - // pcmpgtd mm, mm/m64 + c_comment("pcmpgtd mm, mm/m64"); union reg64 destination = read_mmx64s(r); int32_t low = destination.i32[0] > source.i32[0] ? -1 : 0; @@ -1650,8 +1648,8 @@ void instr_0F66(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0F66, safe_read64s, read_mmx64s) void instr_660F66(union reg128 source, int32_t r) { - // pcmpgtd xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pcmpgtd xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); write_xmm128( @@ -1665,7 +1663,7 @@ void instr_660F66(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660F66, safe_read128s, read_xmm128s) void instr_0F67(union reg64 source, int32_t r) { - // packuswb mm, mm/m64 + c_comment("packuswb mm, mm/m64"); union reg64 destination = read_mmx64s(r); uint32_t low = saturate_sw_to_ub(destination.u16[0]) | @@ -1683,8 +1681,8 @@ void instr_0F67(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0F67, safe_read64s, read_mmx64s) void instr_660F67(union reg128 source, int32_t r) { - // packuswb xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("packuswb xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -1700,7 +1698,7 @@ DEFINE_SSE_SPLIT(instr_660F67, safe_read128s, read_xmm128s) void instr_0F68(union reg64 source, int32_t r) { - // punpckhbw mm, mm/m64 + c_comment("punpckhbw mm, mm/m64"); union reg64 destination = read_mmx64s(r); int32_t byte0 = destination.u8[4]; @@ -1720,8 +1718,8 @@ void instr_0F68(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0F68, safe_read64s, read_mmx64s) void instr_660F68(union reg128 source, int32_t r) { - // punpckhbw xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("punpckhbw xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); write_xmm128( @@ -1735,7 +1733,7 @@ void instr_660F68(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660F68, safe_read128s, read_xmm128s) void instr_0F69(union reg64 source, int32_t r) { - // punpckhwd mm, mm/m64 + c_comment("punpckhwd mm, mm/m64"); union reg64 destination = read_mmx64s(r); int32_t word0 = destination.u16[2]; @@ -1751,8 +1749,8 @@ void instr_0F69(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0F69, safe_read64s, read_mmx64s) void instr_660F69(union reg128 source, int32_t r) { - // punpckhwd xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("punpckhwd xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); int32_t dword0 = destination.u16[4] | source.u16[4] << 16; @@ -1765,22 +1763,22 @@ void instr_660F69(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660F69, safe_read128s, read_xmm128s) void instr_0F6A(union reg64 source, int32_t r) { - // punpckhdq mm, mm/m64 + c_comment("punpckhdq mm, mm/m64"); union reg64 destination = read_mmx64s(r); write_mmx64(r, destination.u32[1], source.u32[1]); } DEFINE_SSE_SPLIT(instr_0F6A, safe_read64s, read_mmx64s) void instr_660F6A(union reg128 source, int32_t r) { - // punpckhdq xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("punpckhdq xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); write_xmm128(r, destination.u32[2], source.u32[2], destination.u32[3], source.u32[3]); } DEFINE_SSE_SPLIT(instr_660F6A, safe_read128s, read_xmm128s) void instr_0F6B(union reg64 source, int32_t r) { - // packssdw mm, mm/m64 + c_comment("packssdw mm, mm/m64"); union reg64 destination = read_mmx64s(r); int32_t low = saturate_sd_to_sw(destination.u32[0]) | @@ -1793,8 +1791,8 @@ void instr_0F6B(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0F6B, safe_read64s, read_mmx64s) void instr_660F6B(union reg128 source, int32_t r) { - // packssdw xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("packssdw xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); int32_t dword0 = saturate_sd_to_sw(destination.u32[0]) | @@ -1814,8 +1812,8 @@ void instr_0F6C_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_0F6C_reg(int32_t r1, int32_t r2) { trigger_ud(); } void instr_660F6C(union reg128 source, int32_t r) { - // punpcklqdq xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("punpcklqdq xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); write_xmm128(r, destination.u32[0], destination.u32[1], source.u32[0], source.u32[1]); @@ -1826,8 +1824,8 @@ void instr_0F6D_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_0F6D_reg(int32_t r1, int32_t r2) { trigger_ud(); } void instr_660F6D(union reg128 source, int32_t r) { - // punpckhqdq xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("punpckhqdq xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); write_xmm128(r, destination.u32[2], destination.u32[3], source.u32[2], source.u32[3]); @@ -1835,38 +1833,38 @@ void instr_660F6D(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660F6D, safe_read128s, read_xmm128s) void instr_0F6E(int32_t source, int32_t r) { - // movd mm, r/m32 + c_comment("movd mm, r/m32"); write_mmx64(r, source, 0); } DEFINE_SSE_SPLIT(instr_0F6E, safe_read32s, read_reg32) void instr_660F6E(int32_t source, int32_t r) { - // movd mm, r/m32 + c_comment("movd mm, r/m32"); write_xmm128(r, source, 0, 0, 0); } DEFINE_SSE_SPLIT(instr_660F6E, safe_read32s, read_reg32) void instr_0F6F(union reg64 source, int32_t r) { - // movq mm, mm/m64 + c_comment("movq mm, mm/m64"); write_mmx64(r, source.u32[0], source.u32[1]); } DEFINE_SSE_SPLIT(instr_0F6F, safe_read64s, read_mmx64s) void instr_660F6F(union reg128 source, int32_t r) { - // movdqa xmm, xmm/mem128 - // XXX: Aligned access or #gp - // XXX: Aligned read or #gp + c_comment("movdqa xmm, xmm/mem128"); + c_comment("XXX: Aligned access or #gp"); + c_comment("XXX: Aligned read or #gp"); mov_rm_r128(source, r); } DEFINE_SSE_SPLIT(instr_660F6F, safe_read128s, read_xmm128s) void instr_F30F6F(union reg128 source, int32_t r) { - // movdqu xmm, xmm/m128 + c_comment("movdqu xmm, xmm/m128"); mov_rm_r128(source, r); } DEFINE_SSE_SPLIT(instr_F30F6F, safe_read128s, read_xmm128s) void instr_0F70(union reg64 source, int32_t r, int32_t imm8) { - // pshufw mm1, mm2/m64, imm8 + c_comment("pshufw mm1, mm2/m64, imm8"); int32_t word0_shift = imm8 & 0b11; uint32_t word0 = source.u32[word0_shift >> 1] >> ((word0_shift & 1) << 4) & 0xFFFF; @@ -1885,8 +1883,8 @@ void instr_0F70(union reg64 source, int32_t r, int32_t imm8) { DEFINE_SSE_SPLIT_IMM(instr_0F70, safe_read64s, read_mmx64s) void instr_660F70(union reg128 source, int32_t r, int32_t imm8) { - // pshufd xmm, xmm/mem128 - // XXX: Aligned access or #gp + c_comment("pshufd xmm, xmm/mem128"); + c_comment("XXX: Aligned access or #gp"); write_xmm128( r, source.u32[imm8 & 3], @@ -1898,8 +1896,8 @@ void instr_660F70(union reg128 source, int32_t r, int32_t imm8) { DEFINE_SSE_SPLIT_IMM(instr_660F70, safe_read128s, read_xmm128s) void instr_F20F70(union reg128 source, int32_t r, int32_t imm8) { - // pshuflw xmm, xmm/m128, imm8 - // XXX: Aligned access or #gp + c_comment("pshuflw xmm, xmm/m128, imm8"); + c_comment("XXX: Aligned access or #gp"); write_xmm128( r, source.u16[imm8 & 3] | source.u16[imm8 >> 2 & 3] << 16, @@ -1911,8 +1909,8 @@ void instr_F20F70(union reg128 source, int32_t r, int32_t imm8) { DEFINE_SSE_SPLIT_IMM(instr_F20F70, safe_read128s, read_xmm128s) void instr_F30F70(union reg128 source, int32_t r, int32_t imm8) { - // pshufhw xmm, xmm/m128, imm8 - // XXX: Aligned access or #gp + c_comment("pshufhw xmm, xmm/m128, imm8"); + c_comment("XXX: Aligned access or #gp"); write_xmm128( r, source.u32[0], @@ -1928,17 +1926,17 @@ void instr_0F71_4_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_0F71_6_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_0F71_2_reg(int32_t r, int32_t imm8) { - // psrlw mm, imm8 + c_comment("psrlw mm, imm8"); psrlw_r64(r, imm8); } void instr_0F71_4_reg(int32_t r, int32_t imm8) { - // psraw mm, imm8 + c_comment("psraw mm, imm8"); psraw_r64(r, imm8); } void instr_0F71_6_reg(int32_t r, int32_t imm8) { - // psllw mm, imm8 + c_comment("psllw mm, imm8"); psllw_r64(r, imm8); } @@ -1947,17 +1945,17 @@ void instr_660F71_4_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_660F71_6_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_660F71_2_reg(int32_t r, int32_t imm8) { - // psrlw xmm, imm8 + c_comment("psrlw xmm, imm8"); psrlw_r128(r, imm8); } void instr_660F71_4_reg(int32_t r, int32_t imm8) { - // psraw xmm, imm8 + c_comment("psraw xmm, imm8"); psraw_r128(r, imm8); } void instr_660F71_6_reg(int32_t r, int32_t imm8) { - // psllw xmm, imm8 + c_comment("psllw xmm, imm8"); psllw_r128(r, imm8); } @@ -1966,17 +1964,17 @@ void instr_0F72_4_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_0F72_6_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_0F72_2_reg(int32_t r, int32_t imm8) { - // psrld mm, imm8 + c_comment("psrld mm, imm8"); psrld_r64(r, imm8); } void instr_0F72_4_reg(int32_t r, int32_t imm8) { - // psrad mm, imm8 + c_comment("psrad mm, imm8"); psrad_r64(r, imm8); } void instr_0F72_6_reg(int32_t r, int32_t imm8) { - // pslld mm, imm8 + c_comment("pslld mm, imm8"); pslld_r64(r, imm8); } @@ -1985,17 +1983,17 @@ void instr_660F72_4_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_660F72_6_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_660F72_2_reg(int32_t r, int32_t imm8) { - // psrld xmm, imm8 + c_comment("psrld xmm, imm8"); psrld_r128(r, imm8); } void instr_660F72_4_reg(int32_t r, int32_t imm8) { - // psrad xmm, imm8 + c_comment("psrad xmm, imm8"); psrad_r128(r, imm8); } void instr_660F72_6_reg(int32_t r, int32_t imm8) { - // pslld xmm, imm8 + c_comment("pslld xmm, imm8"); pslld_r128(r, imm8); } @@ -2003,12 +2001,12 @@ void instr_0F73_2_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_0F73_6_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_0F73_2_reg(int32_t r, int32_t imm8) { - // psrlq mm, imm8 + c_comment("psrlq mm, imm8"); psrlq_r64(r, imm8); } void instr_0F73_6_reg(int32_t r, int32_t imm8) { - // psllq mm, imm8 + c_comment("psllq mm, imm8"); psllq_r64(r, imm8); } @@ -2018,12 +2016,12 @@ void instr_660F73_6_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_660F73_7_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_660F73_2_reg(int32_t r, int32_t imm8) { - // psrlq xmm, imm8 + c_comment("psrlq xmm, imm8"); psrlq_r128(r, imm8); } void instr_660F73_3_reg(int32_t r, int32_t imm8) { - // psrldq xmm, imm8 + c_comment("psrldq xmm, imm8"); union reg128 destination = read_xmm128s(r); if(imm8 == 0) @@ -2049,13 +2047,13 @@ void instr_660F73_3_reg(int32_t r, int32_t imm8) { } void instr_660F73_6_reg(int32_t r, int32_t imm8) { - // psllq xmm, imm8 + c_comment("psllq xmm, imm8"); psllq_r128(r, imm8); } void instr_660F73_7_reg(int32_t r, int32_t imm8) { - // pslldq xmm, imm8 + c_comment("pslldq xmm, imm8"); union reg128 destination = read_xmm128s(r); if(imm8 == 0) @@ -2081,7 +2079,7 @@ void instr_660F73_7_reg(int32_t r, int32_t imm8) { } void instr_0F74(union reg64 source, int32_t r) { - // pcmpeqb mm, mm/m64 + c_comment("pcmpeqb mm, mm/m64"); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -2095,8 +2093,8 @@ void instr_0F74(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0F74, safe_read64s, read_mmx64s) void instr_660F74(union reg128 source, int32_t r) { - // pcmpeqb xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pcmpeqb xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -2111,7 +2109,7 @@ void instr_660F74(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660F74, safe_read128s, read_xmm128s) void instr_0F75(union reg64 source, int32_t r) { - // pcmpeqw mm, mm/m64 + c_comment("pcmpeqw mm, mm/m64"); union reg64 destination = read_mmx64s(r); int32_t word0 = destination.u16[0] == source.u16[0] ? 0xFFFF : 0; @@ -2127,8 +2125,8 @@ void instr_0F75(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0F75, safe_read64s, read_mmx64s) void instr_660F75(union reg128 source, int32_t r) { - // pcmpeqw xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pcmpeqw xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -2142,7 +2140,7 @@ void instr_660F75(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660F75, safe_read128s, read_xmm128s) void instr_0F76(union reg64 source, int32_t r) { - // pcmpeqd mm, mm/m64 + c_comment("pcmpeqd mm, mm/m64"); union reg64 destination = read_mmx64s(r); int32_t low = destination.u32[0] == source.u32[0] ? -1 : 0; @@ -2153,8 +2151,8 @@ void instr_0F76(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0F76, safe_read64s, read_mmx64s) void instr_660F76(union reg128 source, int32_t r) { - // pcmpeqd xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pcmpeqd xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); write_xmm128( @@ -2168,7 +2166,7 @@ void instr_660F76(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660F76, safe_read128s, read_xmm128s) void instr_0F77() { - // emms + c_comment("emms"); fpu_set_tag_word(0xFFFF); } @@ -2180,53 +2178,53 @@ void instr_0F7C() { unimplemented_sse(); } void instr_0F7D() { unimplemented_sse(); } int32_t instr_0F7E(int32_t r) { - // movd r/m32, mm + c_comment("movd r/m32, mm"); union reg64 data = read_mmx64s(r); return data.u32[0]; } DEFINE_SSE_SPLIT_WRITE(instr_0F7E, safe_write32, write_reg32) int32_t instr_660F7E(int32_t r) { - // movd r/m32, xmm + c_comment("movd r/m32, xmm"); union reg64 data = read_xmm64s(r); return data.u32[0]; } DEFINE_SSE_SPLIT_WRITE(instr_660F7E, safe_write32, write_reg32) void instr_F30F7E_mem(int32_t addr, int32_t r) { - // movq xmm, xmm/mem64 + c_comment("movq xmm, xmm/mem64"); union reg64 data = safe_read64s(addr); write_xmm128(r, data.u32[0], data.u32[1], 0, 0); } void instr_F30F7E_reg(int32_t r1, int32_t r2) { - // movq xmm, xmm/mem64 + c_comment("movq xmm, xmm/mem64"); union reg64 data = read_xmm64s(r1); write_xmm128(r2, data.u32[0], data.u32[1], 0, 0); } void instr_0F7F_mem(int32_t addr, int32_t r) { - // movq mm/m64, mm + c_comment("movq mm/m64, mm"); mov_r_m64(addr, r); } void instr_0F7F_reg(int32_t r1, int32_t r2) { - // movq mm/m64, mm + c_comment("movq mm/m64, mm"); union reg64 data = read_mmx64s(r2); write_mmx64(r1, data.u32[0], data.u32[1]); } void instr_660F7F_mem(int32_t addr, int32_t r) { - // movdqa xmm/m128, xmm - // XXX: Aligned write or #gp + c_comment("movdqa xmm/m128, xmm"); + c_comment("XXX: Aligned write or #gp"); mov_r_m128(addr, r); } void instr_660F7F_reg(int32_t r1, int32_t r2) { - // movdqa xmm/m128, xmm - // XXX: Aligned access or #gp + c_comment("movdqa xmm/m128, xmm"); + c_comment("XXX: Aligned access or #gp"); mov_r_r128(r1, r2); } void instr_F30F7F_mem(int32_t addr, int32_t r) { - // movdqu xmm/m128, xmm + c_comment("movdqu xmm/m128, xmm"); mov_r_m128(addr, r); } void instr_F30F7F_reg(int32_t r1, int32_t r2) { - // movdqu xmm/m128, xmm + c_comment("movdqu xmm/m128, xmm"); mov_r_r128(r1, r2); } @@ -2324,7 +2322,7 @@ DEFINE_MODRM_INSTR_READ_WRITE_16(instr16_0FA5, shld16(___, read_reg16(r), reg8[C DEFINE_MODRM_INSTR_READ_WRITE_32(instr32_0FA5, shld32(___, read_reg32(r), reg8[CL] & 31)) void instr_0FA6() { - // obsolete cmpxchg (os/2) + c_comment("obsolete cmpxchg (os/2)"); trigger_ud(); } void instr_0FA7() { undefined_instruction(); } @@ -2342,7 +2340,7 @@ void instr32_0FA9() { void instr_0FAA() { - // rsm + c_comment("rsm"); undefined_instruction(); } @@ -2366,7 +2364,7 @@ void instr_0FAE_1_mem(int32_t addr) { } void instr_0FAE_2_reg(int32_t r) { unimplemented_sse(); } void instr_0FAE_2_mem(int32_t addr) { - // ldmxcsr + c_comment("ldmxcsr"); int32_t new_mxcsr = safe_read32s(addr); if(new_mxcsr & ~MXCSR_MASK) { @@ -2379,36 +2377,36 @@ void instr_0FAE_2_mem(int32_t addr) { } void instr_0FAE_3_reg(int32_t r) { trigger_ud(); } void instr_0FAE_3_mem(int32_t addr) { - // stmxcsr + c_comment("stmxcsr"); safe_write32(addr, *mxcsr); } void instr_0FAE_4_reg(int32_t r) { trigger_ud(); } void instr_0FAE_4_mem(int32_t addr) { - // xsave + c_comment("xsave"); undefined_instruction(); } void instr_0FAE_5_reg(int32_t r) { - // lfence + c_comment("lfence"); dbg_assert_message(r == 0, "Unexpected lfence encoding"); } void instr_0FAE_5_mem(int32_t addr) { - // xrstor + c_comment("xrstor"); undefined_instruction(); } void instr_0FAE_6_reg(int32_t r) { - // mfence + c_comment("mfence"); dbg_assert_message(r == 0, "Unexpected mfence encoding"); } void instr_0FAE_6_mem(int32_t addr) { - // xsaveopt + c_comment("xsaveopt"); undefined_instruction(); } void instr_0FAE_7_reg(int32_t r) { - // sfence + c_comment("sfence"); dbg_assert_message(r == 0, "Unexpected sfence encoding"); } void instr_0FAE_7_mem(int32_t addr) { - // clflush + c_comment("clflush"); undefined_instruction(); } @@ -2416,7 +2414,7 @@ DEFINE_MODRM_INSTR_READ16(instr16_0FAF, write_reg16(r, imul_reg16(read_reg16(r) DEFINE_MODRM_INSTR_READ32(instr32_0FAF, write_reg32(r, imul_reg32(read_reg32(r), ___))) void instr_0FB0_reg(int32_t r1, int32_t r2) { - // cmpxchg8 + c_comment("cmpxchg8"); int32_t data = read_reg8(r1); cmp8(reg8[AL], data); @@ -2430,7 +2428,7 @@ void instr_0FB0_reg(int32_t r1, int32_t r2) { } } void instr_0FB0_mem(int32_t addr, int32_t r) { - // cmpxchg8 + c_comment("cmpxchg8"); writable_or_pagefault(addr, 1); int32_t data = safe_read8(addr); cmp8(reg8[AL], data); @@ -2447,7 +2445,7 @@ void instr_0FB0_mem(int32_t addr, int32_t r) { } void instr16_0FB1_reg(int32_t r1, int32_t r2) { - // cmpxchg16 + c_comment("cmpxchg16"); int32_t data = read_reg16(r1); cmp16(reg16[AX], data); @@ -2461,7 +2459,7 @@ void instr16_0FB1_reg(int32_t r1, int32_t r2) { } } void instr16_0FB1_mem(int32_t addr, int32_t r) { - // cmpxchg16 + c_comment("cmpxchg16"); writable_or_pagefault(addr, 2); int32_t data = safe_read16(addr); cmp16(reg16[AX], data); @@ -2478,7 +2476,7 @@ void instr16_0FB1_mem(int32_t addr, int32_t r) { } void instr32_0FB1_reg(int32_t r1, int32_t r2) { - // cmpxchg32 + c_comment("cmpxchg32"); int32_t data = read_reg32(r1); cmp32(reg32s[EAX], data); @@ -2492,7 +2490,7 @@ void instr32_0FB1_reg(int32_t r1, int32_t r2) { } } void instr32_0FB1_mem(int32_t addr, int32_t r) { - // cmpxchg32 + c_comment("cmpxchg32"); writable_or_pagefault(addr, 4); int32_t data = safe_read32s(addr); cmp32(reg32s[EAX], data); @@ -2556,7 +2554,7 @@ void instr32_0FB8_mem(int32_t addr, int32_t r) { trigger_ud(); } DEFINE_MODRM_INSTR_READ32(instr32_F30FB8, write_reg32(r, popcnt(___))) void instr_0FB9() { - // UD2 + c_comment("UD2"); trigger_ud(); } @@ -2631,7 +2629,7 @@ DEFINE_MODRM_INSTR_READ_WRITE_16(instr16_0FC1, xadd16(___, get_reg16_index(r))) DEFINE_MODRM_INSTR_READ_WRITE_32(instr32_0FC1, xadd32(___, r)) void instr_0FC2(union reg128 source, int32_t r, int32_t imm8) { - // cmpps xmm, xmm/m128 + c_comment("cmpps xmm, xmm/m128"); union reg128 destination = read_xmm128s(r); union reg128 result = { .i32 = { @@ -2646,7 +2644,7 @@ void instr_0FC2(union reg128 source, int32_t r, int32_t imm8) { DEFINE_SSE_SPLIT_IMM(instr_0FC2, safe_read128s, read_xmm128s) void instr_660FC2(union reg128 source, int32_t r, int32_t imm8) { - // cmppd xmm, xmm/m128 + c_comment("cmppd xmm, xmm/m128"); union reg128 destination = read_xmm128s(r); union reg128 result = { .i64 = { @@ -2658,7 +2656,7 @@ void instr_660FC2(union reg128 source, int32_t r, int32_t imm8) { } DEFINE_SSE_SPLIT_IMM(instr_660FC2, safe_read128s, read_xmm128s) void instr_F20FC2(union reg64 source, int32_t r, int32_t imm8) { - // cmpsd xmm, xmm/m64 + c_comment("cmpsd xmm, xmm/m64"); union reg64 destination = read_xmm64s(r); union reg64 result = { .i64 = { sse_comparison(imm8, destination.f64[0], source.f64[0]) ? -1 : 0, } @@ -2667,7 +2665,7 @@ void instr_F20FC2(union reg64 source, int32_t r, int32_t imm8) { } DEFINE_SSE_SPLIT_IMM(instr_F20FC2, safe_read64s, read_xmm64s) void instr_F30FC2(float_t source, int32_t r, int32_t imm8) { - // cmpss xmm, xmm/m32 + c_comment("cmpss xmm, xmm/m32"); float_t destination = read_xmm_f32(r); int32_t result = sse_comparison(imm8, destination, source) ? -1 : 0; write_xmm32(r, result); @@ -2676,12 +2674,12 @@ DEFINE_SSE_SPLIT_IMM(instr_F30FC2, fpu_load_m32, read_xmm_f32) void instr_0FC3_reg(int32_t r1, int32_t r2) { trigger_ud(); } void instr_0FC3_mem(int32_t addr, int32_t r) { - // movnti + c_comment("movnti"); safe_write32(addr, read_reg32(r)); } void instr_0FC4(int32_t source, int32_t r, int32_t imm8) { - // pinsrw mm, r32/m16, imm8 + c_comment("pinsrw mm, r32/m16, imm8"); union reg64 destination = read_mmx64s(r); uint32_t index = imm8 & 3; @@ -2692,7 +2690,7 @@ void instr_0FC4(int32_t source, int32_t r, int32_t imm8) { DEFINE_SSE_SPLIT_IMM(instr_0FC4, safe_read16, read_reg32) void instr_660FC4(int32_t source, int32_t r, int32_t imm8) { - // pinsrw xmm, r32/m16, imm8 + c_comment("pinsrw xmm, r32/m16, imm8"); union reg128 destination = read_xmm128s(r); uint32_t index = imm8 & 7; @@ -2704,7 +2702,7 @@ DEFINE_SSE_SPLIT_IMM(instr_660FC4, safe_read16, read_reg32) void instr_0FC5_mem(int32_t addr, int32_t r, int32_t imm8) { trigger_ud(); } void instr_0FC5_reg(int32_t r1, int32_t r2, int32_t imm8) { - // pextrw r32, mm, imm8 + c_comment("pextrw r32, mm, imm8"); union reg64 data = read_mmx64s(r1); uint32_t index = imm8 & 3; @@ -2715,7 +2713,7 @@ void instr_0FC5_reg(int32_t r1, int32_t r2, int32_t imm8) { void instr_660FC5_mem(int32_t addr, int32_t r, int32_t imm8) { trigger_ud(); } void instr_660FC5_reg(int32_t r1, int32_t r2, int32_t imm8) { - // pextrw r32, xmm, imm8 + c_comment("pextrw r32, xmm, imm8"); union reg128 data = read_xmm128s(r1); uint32_t index = imm8 & 7; @@ -2728,7 +2726,7 @@ void instr_0FC6() { unimplemented_sse(); } void instr_0FC7_1_reg(int32_t r) { trigger_ud(); } void instr_0FC7_1_mem(int32_t addr) { - // cmpxchg8b + c_comment("cmpxchg8b"); writable_or_pagefault(addr, 8); int32_t m64_low = safe_read32s(addr); @@ -2757,7 +2755,7 @@ void instr_0FC7_1_mem(int32_t addr) { } void instr_0FC7_6_reg(int32_t r) { - // rdrand + c_comment("rdrand"); int32_t has_rand = has_rand_int(); int32_t rand = 0; @@ -2788,45 +2786,45 @@ void instr_0FCF() { bswap(EDI); } void instr_0FD0() { unimplemented_sse(); } void instr_0FD1(union reg64 source, int32_t r) { - // psrlw mm, mm/m64 + c_comment("psrlw mm, mm/m64"); psrlw_r64(r, source.u32[0]); } DEFINE_SSE_SPLIT(instr_0FD1, safe_read64s, read_mmx64s) void instr_660FD1(union reg128 source, int32_t r) { - // psrlw xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("psrlw xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); psrlw_r128(r, source.u32[0]); } DEFINE_SSE_SPLIT(instr_660FD1, safe_read128s, read_xmm128s) void instr_0FD2(union reg64 source, int32_t r) { - // psrld mm, mm/m64 + c_comment("psrld mm, mm/m64"); psrld_r64(r, source.u32[0]); } DEFINE_SSE_SPLIT(instr_0FD2, safe_read64s, read_mmx64s) void instr_660FD2(union reg128 source, int32_t r) { - // psrld xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("psrld xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); psrld_r128(r, source.u32[0]); } DEFINE_SSE_SPLIT(instr_660FD2, safe_read128s, read_xmm128s) void instr_0FD3(union reg64 source, int32_t r) { - // psrlq mm, mm/m64 + c_comment("psrlq mm, mm/m64"); psrlq_r64(r, source.u32[0]); } DEFINE_SSE_SPLIT(instr_0FD3, safe_read64s, read_mmx64s) void instr_660FD3(union reg128 source, int32_t r) { - // psrlq xmm, mm/m64 + c_comment("psrlq xmm, mm/m64"); psrlq_r128(r, source.u32[0]); } DEFINE_SSE_SPLIT(instr_660FD3, safe_read128s, read_xmm128s) void instr_0FD4(union reg64 source, int32_t r) { - // paddq mm, mm/m64 + c_comment("paddq mm, mm/m64"); union reg64 destination = read_mmx64s(r); destination.u64[0] += source.u64[0]; write_mmx_reg64(r, destination); @@ -2834,8 +2832,8 @@ void instr_0FD4(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FD4, safe_read64s, read_mmx64s) void instr_660FD4(union reg128 source, int32_t r) { - // paddq xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("paddq xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); destination.u64[0] += source.u64[0]; destination.u64[1] += source.u64[1]; @@ -2844,7 +2842,7 @@ void instr_660FD4(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FD4, safe_read128s, read_xmm128s) void instr_0FD5(union reg64 source, int32_t r) { - // pmullw mm, mm/m64 + c_comment("pmullw mm, mm/m64"); union reg64 destination = read_mmx64s(r); @@ -2861,8 +2859,8 @@ void instr_0FD5(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FD5, safe_read64s, read_mmx64s) void instr_660FD5(union reg128 source, int32_t r) { - // pmullw xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pmullw xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); write_xmm128( @@ -2879,32 +2877,32 @@ void instr_0FD6_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_0FD6_reg(int32_t r1, int32_t r2) { trigger_ud(); } void instr_660FD6_mem(int32_t addr, int32_t r) { - // movq xmm/m64, xmm + c_comment("movq xmm/m64, xmm"); movl_r128_m64(addr, r); } void instr_660FD6_reg(int32_t r1, int32_t r2) { - // movq xmm/m64, xmm + c_comment("movq xmm/m64, xmm"); union reg64 data = read_xmm64s(r2); write_xmm128(r1, data.u32[0], data.u32[1], 0, 0); } void instr_F20FD6_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_F20FD6_reg(int32_t r1, int32_t r2) { - // movdq2q mm, xmm + c_comment("movdq2q mm, xmm"); union reg128 source = read_xmm128s(r1); write_mmx64(r2, source.u32[0], source.u32[1]); } void instr_F30FD6_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_F30FD6_reg(int32_t r1, int32_t r2) { - // movq2dq xmm, mm + c_comment("movq2dq xmm, mm"); union reg64 source = read_mmx64s(r1); write_xmm128(r2, source.u32[0], source.u32[1], 0, 0); } void instr_0FD7_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_0FD7_reg(int32_t r1, int32_t r2) { - // pmovmskb r, mm + c_comment("pmovmskb r, mm"); union reg64 x = read_mmx64s(r1); uint32_t result = x.u8[0] >> 7 << 0 | x.u8[1] >> 7 << 1 | x.u8[2] >> 7 << 2 | x.u8[3] >> 7 << 3 | @@ -2914,7 +2912,7 @@ void instr_0FD7_reg(int32_t r1, int32_t r2) { void instr_660FD7_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_660FD7_reg(int32_t r1, int32_t r2) { - // pmovmskb reg, xmm + c_comment("pmovmskb reg, xmm"); union reg128 x = read_xmm128s(r1); int32_t result = @@ -2926,7 +2924,7 @@ void instr_660FD7_reg(int32_t r1, int32_t r2) { } void instr_0FD8(union reg64 source, int32_t r) { - // psubusb mm, mm/m64 + c_comment("psubusb mm, mm/m64"); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -2941,7 +2939,7 @@ void instr_0FD8(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FD8, safe_read64s, read_mmx64s) void instr_660FD8(union reg128 source, int32_t r) { - // psubusb xmm, xmm/m128 + c_comment("psubusb xmm, xmm/m128"); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -2956,7 +2954,7 @@ void instr_660FD8(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FD8, safe_read128s, read_xmm128s) void instr_0FD9(union reg64 source, int32_t r) { - // psubusw mm, mm/m64 + c_comment("psubusw mm, mm/m64"); union reg64 destination = read_mmx64s(r); @@ -2973,7 +2971,7 @@ void instr_0FD9(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FD9, safe_read64s, read_mmx64s) void instr_660FD9(union reg128 source, int32_t r) { - // psubusw xmm, xmm/m128 + c_comment("psubusw xmm, xmm/m128"); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -2988,7 +2986,7 @@ void instr_660FD9(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FD9, safe_read128s, read_xmm128s) void instr_0FDA(union reg64 source, int32_t r) { - // pminub mm, mm/m64 + c_comment("pminub mm, mm/m64"); union reg64 destination = read_mmx64s(r); union reg64 result; @@ -3003,8 +3001,8 @@ void instr_0FDA(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FDA, safe_read64s, read_mmx64s) void instr_660FDA(union reg128 source, int32_t r) { - // pminub xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pminub xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -3019,7 +3017,7 @@ void instr_660FDA(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FDA, safe_read128s, read_xmm128s) void instr_0FDB(union reg64 source, int32_t r) { - // pand mm, mm/m64 + c_comment("pand mm, mm/m64"); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -3031,14 +3029,14 @@ void instr_0FDB(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FDB, safe_read64s, read_mmx64s) void instr_660FDB(union reg128 source, int32_t r) { - // pand xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pand xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); pand_r128(source, r); } DEFINE_SSE_SPLIT(instr_660FDB, safe_read128s, read_xmm128s) void instr_0FDC(union reg64 source, int32_t r) { - // paddusb mm, mm/m64 + c_comment("paddusb mm, mm/m64"); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -3053,8 +3051,8 @@ void instr_0FDC(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FDC, safe_read64s, read_mmx64s) void instr_660FDC(union reg128 source, int32_t r) { - // paddusb xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("paddusb xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -3069,7 +3067,7 @@ void instr_660FDC(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FDC, safe_read128s, read_xmm128s) void instr_0FDD(union reg64 source, int32_t r) { - // paddusw mm, mm/m64 + c_comment("paddusw mm, mm/m64"); union reg64 destination = read_mmx64s(r); @@ -3086,8 +3084,8 @@ void instr_0FDD(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FDD, safe_read64s, read_mmx64s) void instr_660FDD(union reg128 source, int32_t r) { - // paddusw xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("paddusw xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); @@ -3102,7 +3100,7 @@ void instr_660FDD(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FDD, safe_read128s, read_xmm128s) void instr_0FDE(union reg64 source, int32_t r) { - // pmaxub mm, mm/m64 + c_comment("pmaxub mm, mm/m64"); union reg64 destination = read_mmx64s(r); union reg64 result; @@ -3117,8 +3115,8 @@ void instr_0FDE(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FDE, safe_read64s, read_mmx64s) void instr_660FDE(union reg128 source, int32_t r) { - // pmaxub xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pmaxub xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -3133,7 +3131,7 @@ void instr_660FDE(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FDE, safe_read128s, read_xmm128s) void instr_0FDF(union reg64 source, int32_t r) { - // pandn mm, mm/m64 + c_comment("pandn mm, mm/m64"); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -3145,14 +3143,14 @@ void instr_0FDF(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FDF, safe_read64s, read_mmx64s) void instr_660FDF(union reg128 source, int32_t r) { - // pandn xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pandn xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); pandn_r128(source, r); } DEFINE_SSE_SPLIT(instr_660FDF, safe_read128s, read_xmm128s) void instr_0FE0(union reg64 source, int32_t r) { - // pavgb mm, mm/m64 + c_comment("pavgb mm, mm/m64"); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -3166,8 +3164,8 @@ void instr_0FE0(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FE0, safe_read64s, read_mmx64s) void instr_660FE0(union reg128 source, int32_t r) { - // pavgb xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pavgb xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -3181,33 +3179,33 @@ void instr_660FE0(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FE0, safe_read128s, read_xmm128s) void instr_0FE1(union reg64 source, int32_t r) { - // psraw mm, mm/m64 + c_comment("psraw mm, mm/m64"); psraw_r64(r, source.u32[0]); } DEFINE_SSE_SPLIT(instr_0FE1, safe_read64s, read_mmx64s) void instr_660FE1(union reg128 source, int32_t r) { - // psraw xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("psraw xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); psraw_r128(r, source.u32[0]); } DEFINE_SSE_SPLIT(instr_660FE1, safe_read128s, read_xmm128s) void instr_0FE2(union reg64 source, int32_t r) { - // psrad mm, mm/m64 + c_comment("psrad mm, mm/m64"); psrad_r64(r, source.u32[0]); } DEFINE_SSE_SPLIT(instr_0FE2, safe_read64s, read_mmx64s) void instr_660FE2(union reg128 source, int32_t r) { - // psrad xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("psrad xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); psrad_r128(r, source.u32[0]); } DEFINE_SSE_SPLIT(instr_660FE2, safe_read128s, read_xmm128s) void instr_0FE3(union reg64 source, int32_t r) { - // pavgw mm, mm/m64 + c_comment("pavgw mm, mm/m64"); union reg64 destination = read_mmx64s(r); destination.u16[0] = (destination.u16[0] + source.u16[0] + 1) >> 1; @@ -3220,8 +3218,8 @@ void instr_0FE3(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FE3, safe_read64s, read_mmx64s) void instr_660FE3(union reg128 source, int32_t r) { - // pavgw xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pavgw xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); destination.u16[0] = (destination.u16[0] + source.u16[0] + 1) >> 1; @@ -3238,7 +3236,7 @@ void instr_660FE3(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FE3, safe_read128s, read_xmm128s) void instr_0FE4(union reg64 source, int32_t r) { - // pmulhuw mm, mm/m64 + c_comment("pmulhuw mm, mm/m64"); union reg64 destination = read_mmx64s(r); @@ -3251,8 +3249,8 @@ void instr_0FE4(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FE4, safe_read64s, read_mmx64s) void instr_660FE4(union reg128 source, int32_t r) { - // pmulhuw xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pmulhuw xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); @@ -3267,7 +3265,7 @@ void instr_660FE4(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FE4, safe_read128s, read_xmm128s) void instr_0FE5(union reg64 source, int32_t r) { - // pmulhw mm, mm/m64 + c_comment("pmulhw mm, mm/m64"); union reg64 destination = read_mmx64s(r); @@ -3284,8 +3282,8 @@ void instr_0FE5(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FE5, safe_read64s, read_mmx64s) void instr_660FE5(union reg128 source, int32_t r) { - // pmulhw xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pmulhw xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); @@ -3312,19 +3310,19 @@ void instr_F30FE6_mem(int32_t addr, int32_t r) { unimplemented_sse(); } void instr_F30FE6_reg(int32_t r1, int32_t r2) { unimplemented_sse(); } void instr_0FE7_mem(int32_t addr, int32_t r) { - // movntq m64, mm + c_comment("movntq m64, mm"); mov_r_m64(addr, r); } void instr_0FE7_reg(int32_t r1, int32_t r2) { trigger_ud(); } void instr_660FE7_reg(int32_t r1, int32_t r2) { trigger_ud(); } void instr_660FE7_mem(int32_t addr, int32_t r) { - // movntdq m128, xmm + c_comment("movntdq m128, xmm"); mov_r_m128(addr, r); } void instr_0FE8(union reg64 source, int32_t r) { - // psubsb mm, mm/m64 + c_comment("psubsb mm, mm/m64"); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -3339,8 +3337,8 @@ void instr_0FE8(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FE8, safe_read64s, read_mmx64s) void instr_660FE8(union reg128 source, int32_t r) { - // psubsb xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("psubsb xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -3355,7 +3353,7 @@ void instr_660FE8(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FE8, safe_read128s, read_xmm128s) void instr_0FE9(union reg64 source, int32_t r) { - // psubsw mm, mm/m64 + c_comment("psubsw mm, mm/m64"); union reg64 destination = read_mmx64s(r); @@ -3372,8 +3370,8 @@ void instr_0FE9(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FE9, safe_read64s, read_mmx64s) void instr_660FE9(union reg128 source, int32_t r) { - // psubsw xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("psubsw xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); @@ -3391,7 +3389,7 @@ void instr_660FE9(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FE9, safe_read128s, read_xmm128s) void instr_0FEA(union reg64 source, int32_t r) { - // pminsw mm, mm/m64 + c_comment("pminsw mm, mm/m64"); union reg64 destination = read_mmx64s(r); union reg64 result; @@ -3406,8 +3404,8 @@ void instr_0FEA(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FEA, safe_read64s, read_mmx64s) void instr_660FEA(union reg128 source, int32_t r) { - // pminsw xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pminsw xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -3422,7 +3420,7 @@ void instr_660FEA(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FEA, safe_read128s, read_xmm128s) void instr_0FEB(union reg64 source, int32_t r) { - // por mm, mm/m64 + c_comment("por mm, mm/m64"); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -3434,14 +3432,14 @@ void instr_0FEB(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FEB, safe_read64s, read_mmx64s) void instr_660FEB(union reg128 source, int32_t r) { - // por xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("por xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); por_r128(source, r); } DEFINE_SSE_SPLIT(instr_660FEB, safe_read128s, read_xmm128s) void instr_0FEC(union reg64 source, int32_t r) { - // paddsb mm, mm/m64 + c_comment("paddsb mm, mm/m64"); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -3456,8 +3454,8 @@ void instr_0FEC(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FEC, safe_read64s, read_mmx64s) void instr_660FEC(union reg128 source, int32_t r) { - // paddsb xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("paddsb xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -3472,7 +3470,7 @@ void instr_660FEC(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FEC, safe_read128s, read_xmm128s) void instr_0FED(union reg64 source, int32_t r) { - // paddsw mm, mm/m64 + c_comment("paddsw mm, mm/m64"); union reg64 destination = read_mmx64s(r); @@ -3489,8 +3487,8 @@ void instr_0FED(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FED, safe_read64s, read_mmx64s) void instr_660FED(union reg128 source, int32_t r) { - // paddsw xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("paddsw xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); @@ -3508,7 +3506,7 @@ void instr_660FED(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FED, safe_read128s, read_xmm128s) void instr_0FEE(union reg64 source, int32_t r) { - // pmaxsw mm, mm/m64 + c_comment("pmaxsw mm, mm/m64"); union reg64 destination = read_mmx64s(r); union reg64 result; @@ -3523,8 +3521,8 @@ void instr_0FEE(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FEE, safe_read64s, read_mmx64s) void instr_660FEE(union reg128 source, int32_t r) { - // pmaxsw xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pmaxsw xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); union reg128 result; @@ -3539,7 +3537,7 @@ void instr_660FEE(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FEE, safe_read128s, read_xmm128s) void instr_0FEF(union reg64 source, int32_t r) { - // pxor mm, mm/m64 + c_comment("pxor mm, mm/m64"); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -3550,8 +3548,8 @@ void instr_0FEF(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FEF, safe_read64s, read_mmx64s) void instr_660FEF(union reg128 source, int32_t r) { - // pxor xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pxor xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); pxor_r128(source, r); } DEFINE_SSE_SPLIT(instr_660FEF, safe_read128s, read_xmm128s) @@ -3559,46 +3557,46 @@ DEFINE_SSE_SPLIT(instr_660FEF, safe_read128s, read_xmm128s) void instr_0FF0() { unimplemented_sse(); } void instr_0FF1(union reg64 source, int32_t r) { - // psllw mm, mm/m64 + c_comment("psllw mm, mm/m64"); psllw_r64(r, source.u32[0]); } DEFINE_SSE_SPLIT(instr_0FF1, safe_read64s, read_mmx64s) void instr_660FF1(union reg128 source, int32_t r) { - // psllw xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("psllw xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); psllw_r128(r, source.u32[0]); } DEFINE_SSE_SPLIT(instr_660FF1, safe_read128s, read_xmm128s) void instr_0FF2(union reg64 source, int32_t r) { - // pslld mm, mm/m64 + c_comment("pslld mm, mm/m64"); pslld_r64(r, source.u32[0]); } DEFINE_SSE_SPLIT(instr_0FF2, safe_read64s, read_mmx64s) void instr_660FF2(union reg128 source, int32_t r) { - // pslld xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pslld xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); pslld_r128(r, source.u32[0]); } DEFINE_SSE_SPLIT(instr_660FF2, safe_read128s, read_xmm128s) void instr_0FF3(union reg64 source, int32_t r) { - // psllq mm, mm/m64 + c_comment("psllq mm, mm/m64"); psllq_r64(r, source.u32[0]); } DEFINE_SSE_SPLIT(instr_0FF3, safe_read64s, read_mmx64s) void instr_660FF3(union reg128 source, int32_t r) { - // psllq xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("psllq xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); psllq_r128(r, source.u32[0]); } DEFINE_SSE_SPLIT(instr_660FF3, safe_read128s, read_xmm128s) void instr_0FF4(union reg64 source, int32_t r) { - // pmuludq mm, mm/m64 + c_comment("pmuludq mm, mm/m64"); union reg64 destination = read_mmx64s(r); destination.u64[0] = (uint64_t) source.u32[0] * (uint64_t) destination.u32[0]; @@ -3607,8 +3605,8 @@ void instr_0FF4(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FF4, safe_read64s, read_mmx64s) void instr_660FF4(union reg128 source, int32_t r) { - // pmuludq xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pmuludq xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); destination.u64[0] = (uint64_t) source.u32[0] * (uint64_t) destination.u32[0]; @@ -3618,7 +3616,7 @@ void instr_660FF4(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FF4, safe_read128s, read_xmm128s) void instr_0FF5(union reg64 source, int32_t r) { - // pmaddwd mm, mm/m64 + c_comment("pmaddwd mm, mm/m64"); union reg64 destination = read_mmx64s(r); @@ -3635,8 +3633,8 @@ void instr_0FF5(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FF5, safe_read64s, read_mmx64s) void instr_660FF5(union reg128 source, int32_t r) { - // pmaddwd xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pmaddwd xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); @@ -3654,7 +3652,7 @@ void instr_660FF5(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FF5, safe_read128s, read_xmm128s) void instr_0FF6(union reg64 source, int32_t r) { - // psadbw mm, mm/m64 + c_comment("psadbw mm, mm/m64"); union reg64 destination = read_mmx64s(r); uint32_t sum = 0; @@ -3668,8 +3666,8 @@ void instr_0FF6(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FF6, safe_read64s, read_mmx64s) void instr_660FF6(union reg128 source, int32_t r) { - // psadbw xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("psadbw xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); uint32_t sum0 = 0; uint32_t sum1 = 0; @@ -3686,7 +3684,7 @@ DEFINE_SSE_SPLIT(instr_660FF6, safe_read128s, read_xmm128s) void instr_0FF7_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_0FF7_reg(int32_t r1, int32_t r2) { - // maskmovq mm, mm + c_comment("maskmovq mm, mm"); union reg64 source = read_mmx64s(r2); union reg64 mask = read_mmx64s(r1); int32_t addr = get_seg_prefix(DS) + get_reg_asize(EDI); @@ -3703,7 +3701,7 @@ void instr_0FF7_reg(int32_t r1, int32_t r2) { void instr_660FF7_mem(int32_t addr, int32_t r) { trigger_ud(); } void instr_660FF7_reg(int32_t r1, int32_t r2) { - // maskmovdqu xmm, xmm + c_comment("maskmovdqu xmm, xmm"); union reg128 source = read_xmm128s(r2); union reg128 mask = read_xmm128s(r1); int32_t addr = get_seg_prefix(DS) + get_reg_asize(EDI); @@ -3719,7 +3717,7 @@ void instr_660FF7_reg(int32_t r1, int32_t r2) { } void instr_0FF8(union reg64 source, int32_t r) { - // psubb mm, mm/m64 + c_comment("psubb mm, mm/m64"); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -3734,8 +3732,8 @@ void instr_0FF8(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FF8, safe_read64s, read_mmx64s) void instr_660FF8(union reg128 source, int32_t r) { - // psubb xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("psubb xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); union reg128 result = { { 0 } }; @@ -3750,7 +3748,7 @@ void instr_660FF8(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FF8, safe_read128s, read_xmm128s) void instr_0FF9(union reg64 source, int32_t r) { - // psubw mm, mm/m64 + c_comment("psubw mm, mm/m64"); union reg64 destination = read_mmx64s(r); @@ -3767,8 +3765,8 @@ void instr_0FF9(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FF9, safe_read64s, read_mmx64s) void instr_660FF9(union reg128 source, int32_t r) { - // psubw xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("psubw xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); union reg128 result = { { 0 } }; @@ -3783,7 +3781,7 @@ void instr_660FF9(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FF9, safe_read128s, read_xmm128s) void instr_0FFA(union reg64 source, int32_t r) { - // psubd mm, mm/m64 + c_comment("psubd mm, mm/m64"); union reg64 destination = read_mmx64s(r); @@ -3796,8 +3794,8 @@ void instr_0FFA(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FFA, safe_read64s, read_mmx64s) void instr_660FFA(union reg128 source, int32_t r) { - // psubd xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("psubd xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); @@ -3812,7 +3810,7 @@ void instr_660FFA(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FFA, safe_read128s, read_xmm128s) void instr_0FFB(union reg64 source, int32_t r) { - // psubq mm, mm/m64 + c_comment("psubq mm, mm/m64"); union reg64 destination = read_mmx64s(r); destination.u64[0] = destination.u64[0] - source.u64[0]; @@ -3821,8 +3819,8 @@ void instr_0FFB(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FFB, safe_read64s, read_mmx64s) void instr_660FFB(union reg128 source, int32_t r) { - // psubq xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("psubq xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); destination.u64[0] = destination.u64[0] - source.u64[0]; @@ -3833,7 +3831,7 @@ void instr_660FFB(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FFB, safe_read128s, read_xmm128s) void instr_0FFC(union reg64 source, int32_t r) { - // paddb mm, mm/m64 + c_comment("paddb mm, mm/m64"); union reg64 destination = read_mmx64s(r); union reg64 result = { { 0 } }; @@ -3848,8 +3846,8 @@ void instr_0FFC(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FFC, safe_read64s, read_mmx64s) void instr_660FFC(union reg128 source, int32_t r) { - // paddb xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("paddb xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); union reg128 result = { { 0 } }; @@ -3864,7 +3862,7 @@ void instr_660FFC(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FFC, safe_read128s, read_xmm128s) void instr_0FFD(union reg64 source, int32_t r) { - // paddw mm, mm/m64 + c_comment("paddw mm, mm/m64"); union reg64 destination = read_mmx64s(r); @@ -3881,8 +3879,8 @@ void instr_0FFD(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FFD, safe_read64s, read_mmx64s) void instr_660FFD(union reg128 source, int32_t r) { - // paddw xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("paddw xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); union reg128 result = { { 0 } }; @@ -3897,7 +3895,7 @@ void instr_660FFD(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FFD, safe_read128s, read_xmm128s) void instr_0FFE(union reg64 source, int32_t r) { - // paddd mm, mm/m64 + c_comment("paddd mm, mm/m64"); union reg64 destination = read_mmx64s(r); @@ -3909,8 +3907,8 @@ void instr_0FFE(union reg64 source, int32_t r) { DEFINE_SSE_SPLIT(instr_0FFE, safe_read64s, read_mmx64s) void instr_660FFE(union reg128 source, int32_t r) { - // paddd xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("paddd xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); @@ -3924,7 +3922,7 @@ void instr_660FFE(union reg128 source, int32_t r) { DEFINE_SSE_SPLIT(instr_660FFE, safe_read128s, read_xmm128s) void instr_0FFF() { - // Windows 98 + c_comment("Windows 98"); dbg_log("#ud: 0F FF"); trigger_ud(); } diff --git a/src/native/misc_instr.c b/src/native/misc_instr.c index c2d8cdc0..bd2c12ff 100644 --- a/src/native/misc_instr.c +++ b/src/native/misc_instr.c @@ -27,7 +27,7 @@ bool getpf() { if(*flags_changed & FLAG_PARITY) { - // inverted lookup table + c_comment("inverted lookup table"); return 0x9669 << 2 >> ((*last_result ^ *last_result >> 4) & 0xF) & FLAG_PARITY; } else @@ -106,7 +106,7 @@ void jmp_rel16(int32_t rel16) { int32_t cs_offset = get_seg_cs(); - // limit ip to 16 bit + c_comment("limit ip to 16 bit"); *instruction_pointer = cs_offset + ((*instruction_pointer - cs_offset + rel16) & 0xFFFF); } @@ -307,8 +307,8 @@ void pusha16() { uint16_t temp = reg16[SP]; - // make sure we don't get a pagefault after having - // pushed several registers already + c_comment("make sure we don't get a pagefault after having"); + c_comment("pushed several registers already"); writable_or_pagefault(get_stack_pointer(-16), 16); push16(reg16[AX]); @@ -366,9 +366,9 @@ void fxsave(uint32_t addr) fpu_store_m80(addr + 32 + (i << 4), fpu_st[*fpu_stack_ptr + i & 7]); } - // If the OSFXSR bit in control register CR4 is not set, the FXSAVE - // instruction may not save these registers. This behavior is - // implementation dependent. + c_comment("If the OSFXSR bit in control register CR4 is not set, the FXSAVE"); + c_comment("instruction may not save these registers. This behavior is"); + c_comment("implementation dependent."); for(int32_t i = 0; i < 8; i++) { safe_write128(addr + 160 + (i << 4), reg_xmm[i]); diff --git a/src/native/shared.h b/src/native/shared.h index cb870ef8..e7528281 100644 --- a/src/native/shared.h +++ b/src/native/shared.h @@ -18,5 +18,6 @@ void dbg_log3(const char* m, int32_t x, int32_t y, int32_t z); void dbg_log5(const char* m, int32_t x, int32_t y, int32_t z, int32_t i, int32_t j); void dbg_log6(const char* m, int32_t x, int32_t y, int32_t z, int32_t i, int32_t j, int32_t k); void dbg_trace(); +void c_comment(const char* m); bool isnan_XXX(double f); bool isfinite_XXX(double f); diff --git a/src/native/sse_instr.c b/src/native/sse_instr.c index 217b4298..2c8c374b 100644 --- a/src/native/sse_instr.c +++ b/src/native/sse_instr.c @@ -6,41 +6,41 @@ void mov_r_m64(int32_t addr, int32_t r) { - // mov* m64, mm + c_comment("mov* m64, mm"); union reg64 data = read_mmx64s(r); safe_write64(addr, data.u64[0]); } void movl_r128_m64(int32_t addr, int32_t r) { - // mov* m64, xmm + c_comment("mov* m64, xmm"); union reg64 data = read_xmm64s(r); safe_write64(addr, data.u64[0]); } void mov_r_r128(int32_t r1, int32_t r2) { - // mov* xmm, xmm + c_comment("mov* xmm, xmm"); union reg128 data = read_xmm128s(r2); write_xmm_reg128(r1, data); } void mov_r_m128(int32_t addr, int32_t r) { - // mov* m128, xmm + c_comment("mov* m128, xmm"); union reg128 data = read_xmm128s(r); safe_write128(addr, data); } void mov_rm_r128(union reg128 source, int32_t r) { - // mov* xmm, xmm/m128 + c_comment("mov* xmm, xmm/m128"); write_xmm_reg128(r, source); } void movh_m64_r128(int32_t addr, int32_t r) { - // movhp* xmm, m64 + c_comment("movhp* xmm, m64"); union reg64 data = safe_read64s(addr); union reg128 orig = read_xmm128s(r); write_xmm128(r, orig.u32[0], orig.u32[1], data.u32[0], data.u32[1]); @@ -48,15 +48,15 @@ void movh_m64_r128(int32_t addr, int32_t r) void movh_r128_m64(int32_t addr, int32_t r) { - // movhp* m64, xmm + c_comment("movhp* m64, xmm"); union reg128 data = read_xmm128s(r); safe_write64(addr, data.u64[1]); } void pand_r128(union reg128 source, int32_t r) { - // pand xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pand xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); union reg128 result = { { 0 } }; @@ -69,8 +69,8 @@ void pand_r128(union reg128 source, int32_t r) void pandn_r128(union reg128 source, int32_t r) { - // pandn xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pandn xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); union reg128 result = { { 0 } }; @@ -83,8 +83,8 @@ void pandn_r128(union reg128 source, int32_t r) void pxor_r128(union reg128 source, int32_t r) { - // pxor xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("pxor xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); union reg128 result = { { 0 } }; @@ -97,8 +97,8 @@ void pxor_r128(union reg128 source, int32_t r) void por_r128(union reg128 source, int32_t r) { - // por xmm, xmm/m128 - // XXX: Aligned access or #gp + c_comment("por xmm, xmm/m128"); + c_comment("XXX: Aligned access or #gp"); union reg128 destination = read_xmm128s(r); union reg128 result = { { 0 } }; @@ -111,7 +111,7 @@ void por_r128(union reg128 source, int32_t r) void psrlw_r64(int32_t r, uint32_t shift) { - // psrlw mm, {shift} + c_comment("psrlw mm, {shift}"); union reg64 destination = read_mmx64s(r); int32_t dword0 = 0; int32_t dword1 = 0; @@ -127,7 +127,7 @@ void psrlw_r64(int32_t r, uint32_t shift) void psraw_r64(int32_t r, uint32_t shift) { - // psraw mm, {shift} + c_comment("psraw mm, {shift}"); union reg64 destination = read_mmx64s(r); int32_t shift_clamped = shift > 15 ? 16 : shift; @@ -140,7 +140,7 @@ void psraw_r64(int32_t r, uint32_t shift) void psllw_r64(int32_t r, uint32_t shift) { - // psllw mm, {shift} + c_comment("psllw mm, {shift}"); union reg64 destination = read_mmx64s(r); int32_t dword0 = 0; @@ -159,7 +159,7 @@ void psllw_r64(int32_t r, uint32_t shift) void psrld_r64(int32_t r, uint32_t shift) { - // psrld mm, {shift} + c_comment("psrld mm, {shift}"); union reg64 destination = read_mmx64s(r); int32_t dword0 = 0; @@ -176,7 +176,7 @@ void psrld_r64(int32_t r, uint32_t shift) void psrad_r64(int32_t r, uint32_t shift) { - // psrad mm, {shift} + c_comment("psrad mm, {shift}"); union reg64 destination = read_mmx64s(r); int32_t shift_clamped = shift > 31 ? 31 : shift; @@ -188,7 +188,7 @@ void psrad_r64(int32_t r, uint32_t shift) void pslld_r64(int32_t r, uint32_t shift) { - // pslld mm, {shift} + c_comment("pslld mm, {shift}"); union reg64 destination = read_mmx64s(r); int32_t dword0 = 0; @@ -205,7 +205,7 @@ void pslld_r64(int32_t r, uint32_t shift) void psrlq_r64(int32_t r, uint32_t shift) { - // psrlq mm, {shift} + c_comment("psrlq mm, {shift}"); if(shift == 0) { @@ -225,7 +225,7 @@ void psrlq_r64(int32_t r, uint32_t shift) void psllq_r64(int32_t r, uint32_t shift) { - // psllq mm, {shift} + c_comment("psllq mm, {shift}"); union reg64 destination = read_mmx64s(r); if(shift == 0) @@ -245,7 +245,7 @@ void psllq_r64(int32_t r, uint32_t shift) void psrlw_r128(int32_t r, uint32_t shift) { - // psrlw xmm, {shift} + c_comment("psrlw xmm, {shift}"); union reg128 destination = read_xmm128s(r); int32_t dword0 = 0; int32_t dword1 = 0; @@ -265,7 +265,7 @@ void psrlw_r128(int32_t r, uint32_t shift) void psraw_r128(int32_t r, uint32_t shift) { - // psraw xmm, {shift} + c_comment("psraw xmm, {shift}"); union reg128 destination = read_xmm128s(r); int32_t shift_clamped = shift > 15 ? 16 : shift; @@ -282,7 +282,7 @@ void psraw_r128(int32_t r, uint32_t shift) void psllw_r128(int32_t r, uint32_t shift) { - // psllw xmm, {shift} + c_comment("psllw xmm, {shift}"); union reg128 destination = read_xmm128s(r); int32_t dword0 = 0; @@ -303,7 +303,7 @@ void psllw_r128(int32_t r, uint32_t shift) void psrld_r128(int32_t r, uint32_t shift) { - // psrld xmm, {shift} + c_comment("psrld xmm, {shift}"); union reg128 destination = read_xmm128s(r); int32_t dword0 = 0; @@ -324,7 +324,7 @@ void psrld_r128(int32_t r, uint32_t shift) void psrad_r128(int32_t r, uint32_t shift) { - // psrad xmm, {shift} + c_comment("psrad xmm, {shift}"); union reg128 destination = read_xmm128s(r); int32_t shift_clamped = shift > 31 ? 31 : shift; @@ -338,7 +338,7 @@ void psrad_r128(int32_t r, uint32_t shift) void pslld_r128(int32_t r, uint32_t shift) { - // pslld xmm, {shift} + c_comment("pslld xmm, {shift}"); union reg128 destination = read_xmm128s(r); int32_t dword0 = 0; @@ -359,7 +359,7 @@ void pslld_r128(int32_t r, uint32_t shift) void psrlq_r128(int32_t r, uint32_t shift) { - // psrlq xmm, {shift} + c_comment("psrlq xmm, {shift}"); if(shift == 0) { @@ -380,7 +380,7 @@ void psrlq_r128(int32_t r, uint32_t shift) void psllq_r128(int32_t r, uint32_t shift) { - // psllq xmm, {shift} + c_comment("psllq xmm, {shift}"); union reg128 destination = read_xmm128s(r); if(shift == 0) @@ -401,7 +401,7 @@ void psllq_r128(int32_t r, uint32_t shift) bool sse_comparison(int32_t op, double_t x, double_t y) { - // TODO: Signaling + c_comment("TODO: Signaling"); switch(op & 7) { @@ -421,26 +421,26 @@ bool sse_comparison(int32_t op, double_t x, double_t y) double_t sse_min(double_t x, double_t y) { - // if both x and y are 0 or x is nan, y is returned + c_comment("if both x and y are 0 or x is nan, y is returned"); return x < y ? x : y; } double_t sse_max(double_t x, double_t y) { - // if both x and y are 0 or x is nan, y is returned + c_comment("if both x and y are 0 or x is nan, y is returned"); return x > y ? x : y; } int32_t sse_convert_f64_to_i32(double_t x) { - // TODO: Rounding modes + c_comment("TODO: Rounding modes"); if(x >= -0x80000000 && x < 0x80000000) { return (int64_t)x; } else { - // TODO: Signal + c_comment("TODO: Signal"); return -0x80000000; } } diff --git a/src/native/string.c b/src/native/string.c index f1bf9df8..efa24f2d 100644 --- a/src/native/string.c +++ b/src/native/string.c @@ -25,7 +25,7 @@ int32_t string_get_cycle_count(int32_t size, int32_t address) assert((address & (size - 1)) == 0); - // 1 -> 0; 2 -> 1; 4 -> 2 + c_comment("1 -> 0; 2 -> 1; 4 -> 2"); int32_t shift = size >> 1; return (0x1000 - (address & 0xFFF)) >> shift; diff --git a/src/rust/cpu2/Makefile b/src/rust/cpu2/Makefile index 749fd855..77dfe44b 100644 --- a/src/rust/cpu2/Makefile +++ b/src/rust/cpu2/Makefile @@ -110,6 +110,7 @@ profiler.rs: profiler/profiler.rs sed -i 's/dbg_log[0-9]\?((/dbg_log_c!((/' $@ sed -i 's/ dbg_assert_message(/ dbg_assert_message!(/' $@ + sed -i 's/ c_comment(/ c_comment!(/' $@ clean: diff --git a/src/rust/cpu2/imports.rs b/src/rust/cpu2/imports.rs index f2118a3a..b0dffd80 100644 --- a/src/rust/cpu2/imports.rs +++ b/src/rust/cpu2/imports.rs @@ -58,3 +58,7 @@ macro_rules! dbg_assert_message { // TODO }}; } + +macro_rules! c_comment { + ($fmt:expr) => {{}}; +} From 48a8b74f20e684c7eb24ccb1e4987d8f673bc865 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 11 Aug 2018 17:53:48 -0500 Subject: [PATCH 1186/2137] Restore assertions --- src/native/shared.c | 6 +++--- src/native/shared.h | 2 +- src/rust/cpu2/Makefile | 13 ++++++++++++- src/rust/cpu2/imports.rs | 14 +++----------- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/native/shared.c b/src/native/shared.c index 8e0f573d..ea215992 100644 --- a/src/native/shared.c +++ b/src/native/shared.c @@ -4,9 +4,9 @@ #include #include -void assert(bool x) {} -void dbg_assert(bool x) {} -void dbg_assert_message(bool x, const char* msg) {} +//void assert(bool x) {} +//void dbg_assert(bool x) {} +//void dbg_assert_message(bool x, const char* msg) {} //void dbg_log(const char* m) {} //void dbg_log1(const char* m, int32_t x) {} //void dbg_log2(const char* m, int32_t x, int32_t y) {} diff --git a/src/native/shared.h b/src/native/shared.h index e7528281..32ac6721 100644 --- a/src/native/shared.h +++ b/src/native/shared.h @@ -17,7 +17,7 @@ void dbg_log2(const char* m, int32_t x, int32_t y); void dbg_log3(const char* m, int32_t x, int32_t y, int32_t z); void dbg_log5(const char* m, int32_t x, int32_t y, int32_t z, int32_t i, int32_t j); void dbg_log6(const char* m, int32_t x, int32_t y, int32_t z, int32_t i, int32_t j, int32_t k); -void dbg_trace(); +void dbg_trace(void); void c_comment(const char* m); bool isnan_XXX(double f); bool isfinite_XXX(double f); diff --git a/src/rust/cpu2/Makefile b/src/rust/cpu2/Makefile index 77dfe44b..93aa5b7f 100644 --- a/src/rust/cpu2/Makefile +++ b/src/rust/cpu2/Makefile @@ -107,11 +107,22 @@ profiler.rs: profiler/profiler.rs sed -i 's/.as_mut_ptr()//' $@ sed -i ':a;N;$$!ba;s/\*::std::mem::transmute::<&\[u8; [0-9]\+],[ \n]\+&mut \[i8; [0-9]\+]>//g' $@ sed -i 's/\\x00//' $@ + sed -i 's/b"/"/' $@ sed -i 's/dbg_log[0-9]\?((/dbg_log_c!((/' $@ - sed -i 's/ dbg_assert_message(/ dbg_assert_message!(/' $@ + + sed -i ':a;N;$$!ba;s/#\[no_mangle]\n fn dbg_assert[^\n]*//' $@ + sed -i ':a;N;$$!ba;s/#\[no_mangle]\n fn assert[^\n]*//' $@ + + sed -i 's/dbg_assert_message(/dbg_assert!(/' $@ + sed -i 's/dbg_assert(/dbg_assert!(/' $@ + sed -i 's/assert(/dbg_assert!(/' $@ + sed -i 's/ c_comment(/ c_comment!(/' $@ + # This works, but requires manual cleanup afterwards + #sed -i 's/\([0-9]\)[i]32/\1/' $@ + clean: -rm $(ALL) diff --git a/src/rust/cpu2/imports.rs b/src/rust/cpu2/imports.rs index b0dffd80..59c24654 100644 --- a/src/rust/cpu2/imports.rs +++ b/src/rust/cpu2/imports.rs @@ -43,19 +43,11 @@ pub fn allocate_memory(size: u32) -> u32 { macro_rules! dbg_log_c { ($fmt:expr) => {{ - // TODO + dbg_log!($fmt); }}; ($fmt:expr, $($arg:tt)*) => {{ - // TODO - }}; -} - -macro_rules! dbg_assert_message { - ($fmt:expr) => {{ - // TODO - }}; - ($fmt:expr, $($arg:tt)*) => {{ - // TODO + // TODO: Arguments + dbg_log!($fmt); }}; } From 0a68bc939365afce2e00868d4d7c8cf51f16e310 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 11 Aug 2018 16:40:14 -0500 Subject: [PATCH 1187/2137] Check in generated Rust files --- src/rust/cpu2/arith.rs | 2109 ++++++++ src/rust/cpu2/cpu.rs | 2736 +++++++++++ src/rust/cpu2/fpu.rs | 1541 ++++++ src/rust/cpu2/global_pointers.rs | 749 +++ src/rust/cpu2/instructions.rs | 5718 ++++++++++++++++++++++ src/rust/cpu2/instructions_0f.rs | 7810 ++++++++++++++++++++++++++++++ src/rust/cpu2/memory.rs | 1072 ++++ src/rust/cpu2/misc_instr.rs | 1343 +++++ src/rust/cpu2/modrm.rs | 1143 +++++ src/rust/cpu2/profiler.rs | 350 ++ src/rust/cpu2/shared.rs | 399 ++ src/rust/cpu2/sse_instr.rs | 1141 +++++ src/rust/cpu2/string.rs | 2448 ++++++++++ 13 files changed, 28559 insertions(+) create mode 100644 src/rust/cpu2/arith.rs create mode 100644 src/rust/cpu2/cpu.rs create mode 100644 src/rust/cpu2/fpu.rs create mode 100644 src/rust/cpu2/global_pointers.rs create mode 100644 src/rust/cpu2/instructions.rs create mode 100644 src/rust/cpu2/instructions_0f.rs create mode 100644 src/rust/cpu2/memory.rs create mode 100644 src/rust/cpu2/misc_instr.rs create mode 100644 src/rust/cpu2/modrm.rs create mode 100644 src/rust/cpu2/profiler.rs create mode 100644 src/rust/cpu2/shared.rs create mode 100644 src/rust/cpu2/sse_instr.rs create mode 100644 src/rust/cpu2/string.rs diff --git a/src/rust/cpu2/arith.rs b/src/rust/cpu2/arith.rs new file mode 100644 index 00000000..0eba1166 --- /dev/null +++ b/src/rust/cpu2/arith.rs @@ -0,0 +1,2109 @@ +#![allow( + dead_code, + mutable_transmutes, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_mut +)] +#![feature(extern_types, libc)] + +extern "C" { + + #[no_mangle] + fn __fpclassifyl(_: f64) -> i32; + #[no_mangle] + static FLAGS_ALL: i32; + #[no_mangle] + static flags_changed: *mut i32; + #[no_mangle] + static last_op_size: *mut i32; + #[no_mangle] + static last_result: *mut i32; + #[no_mangle] + static last_add_result: *mut i32; + #[no_mangle] + static last_op2: *mut i32; + #[no_mangle] + static last_op1: *mut i32; + #[no_mangle] + fn getcf() -> bool; + #[no_mangle] + static OPSIZE_8: i32; + #[no_mangle] + static OPSIZE_16: i32; + #[no_mangle] + static OPSIZE_32: i32; + #[no_mangle] + static flags: *mut i32; + #[no_mangle] + static FLAG_OVERFLOW: i32; + #[no_mangle] + static AL: i32; + #[no_mangle] + static reg8: *mut u8; + #[no_mangle] + static AX: i32; + #[no_mangle] + static reg16: *mut u16; + #[no_mangle] + static reg8s: *mut i8; + #[no_mangle] + static DX: i32; + #[no_mangle] + static reg16s: *mut i16; + + #[no_mangle] + static EAX: i32; + #[no_mangle] + static reg32s: *mut i32; + #[no_mangle] + static EDX: i32; + #[no_mangle] + static FLAG_ADJUST: i32; + #[no_mangle] + fn getaf() -> bool; + #[no_mangle] + static AH: i32; + #[no_mangle] + fn trigger_de() -> (); + #[no_mangle] + fn c_comment(m: *const i8) -> (); + #[no_mangle] + fn safe_read8(addr: i32) -> i32; + #[no_mangle] + fn translate_address_write(address: i32) -> u32; + #[no_mangle] + fn read8(addr: u32) -> i32; + #[no_mangle] + fn write8(addr: u32, value: i32) -> (); + #[no_mangle] + fn int_log2(_: i32) -> i32; + #[no_mangle] + static FLAG_ZERO: i32; + + #[no_mangle] + static FLAG_CARRY: i32; + #[no_mangle] + static FLAG_PARITY: i32; + #[no_mangle] + static FLAG_SIGN: i32; + #[no_mangle] + static FLAG_TRAP: i32; + #[no_mangle] + static FLAG_INTERRUPT: i32; + #[no_mangle] + static FLAG_DIRECTION: i32; + #[no_mangle] + static FLAG_IOPL: i32; + #[no_mangle] + static FLAG_NT: i32; + #[no_mangle] + static FLAG_RF: i32; + #[no_mangle] + static FLAG_VM: i32; + #[no_mangle] + static FLAG_AC: i32; + #[no_mangle] + static FLAG_VIF: i32; + #[no_mangle] + static FLAG_VIP: i32; + #[no_mangle] + static FLAG_ID: i32; + #[no_mangle] + static FLAGS_DEFAULT: i32; + #[no_mangle] + static FLAGS_MASK: i32; + #[no_mangle] + static ECX: i32; + #[no_mangle] + static EBX: i32; + #[no_mangle] + static ESP: i32; + #[no_mangle] + static EBP: i32; + #[no_mangle] + static ESI: i32; + #[no_mangle] + static EDI: i32; + #[no_mangle] + static CX: i32; + #[no_mangle] + static BX: i32; + #[no_mangle] + static SP: i32; + #[no_mangle] + static BP: i32; + #[no_mangle] + static SI: i32; + #[no_mangle] + static DI: i32; + #[no_mangle] + static CL: i32; + #[no_mangle] + static DL: i32; + #[no_mangle] + static BL: i32; + #[no_mangle] + static CH: i32; + #[no_mangle] + static DH: i32; + #[no_mangle] + static BH: i32; + #[no_mangle] + static ES: i32; + #[no_mangle] + static CS: i32; + #[no_mangle] + static SS: i32; + #[no_mangle] + static DS: i32; + #[no_mangle] + static FS: i32; + #[no_mangle] + static GS: i32; + #[no_mangle] + static TR: i32; + #[no_mangle] + static LDTR: i32; + #[no_mangle] + static PAGE_TABLE_PRESENT_MASK: i32; + #[no_mangle] + static PAGE_TABLE_RW_MASK: i32; + #[no_mangle] + static PAGE_TABLE_USER_MASK: i32; + #[no_mangle] + static PAGE_TABLE_ACCESSED_MASK: i32; + #[no_mangle] + static PAGE_TABLE_DIRTY_MASK: i32; + #[no_mangle] + static PAGE_TABLE_PSE_MASK: i32; + #[no_mangle] + static PAGE_TABLE_GLOBAL_MASK: i32; + #[no_mangle] + static MMAP_BLOCK_BITS: i32; + #[no_mangle] + static MMAP_BLOCK_SIZE: i32; + #[no_mangle] + static CR0_PE: i32; + #[no_mangle] + static CR0_MP: i32; + #[no_mangle] + static CR0_EM: i32; + #[no_mangle] + static CR0_TS: i32; + #[no_mangle] + static CR0_ET: i32; + #[no_mangle] + static CR0_WP: i32; + #[no_mangle] + static CR0_NW: i32; + #[no_mangle] + static CR0_CD: i32; + #[no_mangle] + static CR0_PG: i32; + #[no_mangle] + static CR4_VME: i32; + #[no_mangle] + static CR4_PVI: i32; + #[no_mangle] + static CR4_TSD: i32; + #[no_mangle] + static CR4_PSE: i32; + #[no_mangle] + static CR4_DE: i32; + #[no_mangle] + static CR4_PAE: i32; + #[no_mangle] + static CR4_PGE: i32; + #[no_mangle] + static IA32_SYSENTER_CS: i32; + #[no_mangle] + static IA32_SYSENTER_ESP: i32; + #[no_mangle] + static IA32_SYSENTER_EIP: i32; + #[no_mangle] + static IA32_TIME_STAMP_COUNTER: i32; + #[no_mangle] + static IA32_PLATFORM_ID: i32; + #[no_mangle] + static IA32_APIC_BASE_MSR: i32; + #[no_mangle] + static IA32_BIOS_SIGN_ID: i32; + #[no_mangle] + static MSR_PLATFORM_INFO: i32; + #[no_mangle] + static MSR_MISC_FEATURE_ENABLES: i32; + #[no_mangle] + static IA32_MISC_ENABLE: i32; + #[no_mangle] + static IA32_RTIT_CTL: i32; + #[no_mangle] + static MSR_SMI_COUNT: i32; + #[no_mangle] + static IA32_MCG_CAP: i32; + #[no_mangle] + static IA32_KERNEL_GS_BASE: i32; + #[no_mangle] + static MSR_PKG_C2_RESIDENCY: i32; + #[no_mangle] + static IA32_APIC_BASE_BSP: i32; + #[no_mangle] + static IA32_APIC_BASE_EXTD: i32; + #[no_mangle] + static IA32_APIC_BASE_EN: i32; + #[no_mangle] + static APIC_ADDRESS: i32; + #[no_mangle] + static SEG_PREFIX_NONE: i32; + #[no_mangle] + static SEG_PREFIX_ZERO: i32; + #[no_mangle] + static PREFIX_MASK_REP: i32; + #[no_mangle] + static PREFIX_REPZ: i32; + #[no_mangle] + static PREFIX_REPNZ: i32; + #[no_mangle] + static PREFIX_MASK_SEGMENT: i32; + #[no_mangle] + static PREFIX_MASK_OPSIZE: i32; + #[no_mangle] + static PREFIX_MASK_ADDRSIZE: i32; + #[no_mangle] + static PREFIX_F2: i32; + #[no_mangle] + static PREFIX_F3: i32; + #[no_mangle] + static PREFIX_66: i32; + #[no_mangle] + static LOG_CPU: i32; + #[no_mangle] + static A20_MASK: i32; + #[no_mangle] + static A20_MASK16: i32; + #[no_mangle] + static A20_MASK32: i32; + #[no_mangle] + static MXCSR_MASK: i32; + + #[no_mangle] + static mut mem8: *mut u8; + #[no_mangle] + static mut mem16: *mut u16; + #[no_mangle] + static mut mem32s: *mut i32; + #[no_mangle] + static mut jit_block_boundary: bool; + #[no_mangle] + static VALID_TLB_ENTRY_MAX: i32; + #[no_mangle] + static mut valid_tlb_entries: [i32; 10000]; + #[no_mangle] + static mut valid_tlb_entries_count: i32; + #[no_mangle] + static TLB_VALID: i32; + #[no_mangle] + static TLB_READONLY: i32; + #[no_mangle] + static TLB_NO_USER: i32; + #[no_mangle] + static TLB_IN_MAPPED_RANGE: i32; + #[no_mangle] + static TLB_GLOBAL: i32; + #[no_mangle] + static TLB_HAS_CODE: i32; + #[no_mangle] + static CPU_EXCEPTION_DE: i32; + #[no_mangle] + static CPU_EXCEPTION_DB: i32; + #[no_mangle] + static CPU_EXCEPTION_NMI: i32; + #[no_mangle] + static CPU_EXCEPTION_BP: i32; + #[no_mangle] + static CPU_EXCEPTION_OF: i32; + #[no_mangle] + static CPU_EXCEPTION_BR: i32; + #[no_mangle] + static CPU_EXCEPTION_UD: i32; + #[no_mangle] + static CPU_EXCEPTION_NM: i32; + #[no_mangle] + static CPU_EXCEPTION_DF: i32; + #[no_mangle] + static CPU_EXCEPTION_TS: i32; + #[no_mangle] + static CPU_EXCEPTION_NP: i32; + #[no_mangle] + static CPU_EXCEPTION_SS: i32; + #[no_mangle] + static CPU_EXCEPTION_GP: i32; + #[no_mangle] + static CPU_EXCEPTION_PF: i32; + #[no_mangle] + static CPU_EXCEPTION_MF: i32; + #[no_mangle] + static CPU_EXCEPTION_AC: i32; + #[no_mangle] + static CPU_EXCEPTION_MC: i32; + #[no_mangle] + static CPU_EXCEPTION_XM: i32; + #[no_mangle] + static CPU_EXCEPTION_VE: i32; + #[no_mangle] + static page_fault: *mut bool; + #[no_mangle] + static a20_enabled: *mut bool; + #[no_mangle] + static instruction_pointer: *mut i32; + #[no_mangle] + static previous_ip: *mut i32; + #[no_mangle] + static idtr_size: *mut i32; + #[no_mangle] + static idtr_offset: *mut i32; + #[no_mangle] + static gdtr_size: *mut i32; + #[no_mangle] + static gdtr_offset: *mut i32; + #[no_mangle] + static cr: *mut i32; + #[no_mangle] + static cpl: *mut u8; + #[no_mangle] + static in_hlt: *mut bool; + #[no_mangle] + static last_virt_eip: *mut i32; + #[no_mangle] + static eip_phys: *mut i32; + #[no_mangle] + static last_virt_esp: *mut i32; + #[no_mangle] + static esp_phys: *mut i32; + #[no_mangle] + static sysenter_cs: *mut i32; + #[no_mangle] + static sysenter_esp: *mut i32; + #[no_mangle] + static sysenter_eip: *mut i32; + #[no_mangle] + static prefixes: *mut u8; + #[no_mangle] + static timestamp_counter: *mut u32; + #[no_mangle] + static sreg: *mut u16; + #[no_mangle] + static dreg: *mut i32; + #[no_mangle] + static fw_value: *mut i32; + #[no_mangle] + static segment_is_null: *mut bool; + #[no_mangle] + static segment_offsets: *mut i32; + #[no_mangle] + static segment_limits: *mut u32; + #[no_mangle] + static protected_mode: *mut bool; + #[no_mangle] + static is_32: *mut bool; + #[no_mangle] + static stack_size_32: *mut bool; + #[no_mangle] + static memory_size: *mut u32; + #[no_mangle] + static fpu_stack_empty: *mut i32; + #[no_mangle] + static mxcsr: *mut i32; + #[no_mangle] + static reg_xmm: *mut reg128; + #[no_mangle] + static current_tsc: *mut u64; + #[no_mangle] + static fpu_st: *mut f64; + #[no_mangle] + static fpu_st8: *mut u8; + #[no_mangle] + static fpu_st32: *mut i32; + #[no_mangle] + static fpu_stack_ptr: *mut u32; + #[no_mangle] + static fpu_control_word: *mut i32; + #[no_mangle] + static fpu_status_word: *mut i32; + #[no_mangle] + static fpu_opcode: *mut i32; + #[no_mangle] + static fpu_ip: *mut i32; + #[no_mangle] + static fpu_ip_selector: *mut i32; + #[no_mangle] + static fpu_dp: *mut i32; + #[no_mangle] + static fpu_dp_selector: *mut i32; + #[no_mangle] + static reg_mmx: *mut reg64; + #[no_mangle] + static opstats_buffer: *mut u32; + #[no_mangle] + static opstats_buffer_0f: *mut u32; + #[no_mangle] + static tlb_data: *mut i32; +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union reg64 { + i8_0: [i8; 8], + i16_0: [i16; 4], + i32_0: [i32; 2], + i64_0: [i64; 1], + u8_0: [u8; 8], + u16_0: [u16; 4], + u32_0: [u32; 2], + u64_0: [u64; 1], + f32_0: [f32; 2], + f64_0: [f64; 1], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed { + __f: f32, + __i: u32, +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union reg128 { + i8_0: [i8; 16], + i16_0: [i16; 8], + i32_0: [i32; 4], + i64_0: [i64; 2], + u8_0: [u8; 16], + u16_0: [u16; 8], + u32_0: [u32; 4], + u64_0: [u64; 2], + f32_0: [f32; 4], + f64_0: [f64; 2], +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_0 { + __f: f64, + __i: u64, +} + +unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { + let mut __u: unnamed = unnamed { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { + let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x >= __y) as i32; +} +#[no_mangle] +pub unsafe extern "C" fn add( + mut dest_operand: i32, + mut source_operand: i32, + mut op_size: i32, +) -> i32 { + *last_op1 = dest_operand; + *last_op2 = source_operand; + let mut res: i32 = dest_operand + source_operand; + *last_result = res; + *last_add_result = *last_result; + *last_op_size = op_size; + *flags_changed = FLAGS_ALL; + return res; +} +#[no_mangle] +pub unsafe extern "C" fn adc( + mut dest_operand: i32, + mut source_operand: i32, + mut op_size: i32, +) -> i32 { + let mut cf: i32 = getcf() as i32; + *last_op1 = dest_operand; + *last_op2 = source_operand; + let mut res: i32 = dest_operand + source_operand + cf; + *last_result = res; + *last_add_result = *last_result; + *last_op_size = op_size; + *flags_changed = FLAGS_ALL; + return res; +} +#[no_mangle] +pub unsafe extern "C" fn sub( + mut dest_operand: i32, + mut source_operand: i32, + mut op_size: i32, +) -> i32 { + *last_add_result = dest_operand; + *last_op2 = source_operand; + let mut res: i32 = dest_operand - source_operand; + *last_result = res; + *last_op1 = *last_result; + *last_op_size = op_size; + *flags_changed = FLAGS_ALL; + return res; +} +#[no_mangle] +pub unsafe extern "C" fn sbb( + mut dest_operand: i32, + mut source_operand: i32, + mut op_size: i32, +) -> i32 { + let mut cf: i32 = getcf() as i32; + *last_add_result = dest_operand; + *last_op2 = source_operand; + let mut res: i32 = dest_operand - source_operand - cf; + *last_result = res; + *last_op1 = *last_result; + *last_op_size = op_size; + *flags_changed = FLAGS_ALL; + return res; +} +#[no_mangle] +pub unsafe extern "C" fn add8(mut x: i32, mut y: i32) -> i32 { return add(x, y, OPSIZE_8); } +#[no_mangle] +pub unsafe extern "C" fn add16(mut x: i32, mut y: i32) -> i32 { return add(x, y, OPSIZE_16); } +#[no_mangle] +pub unsafe extern "C" fn add32(mut x: i32, mut y: i32) -> i32 { return add(x, y, OPSIZE_32); } +#[no_mangle] +pub unsafe extern "C" fn sub8(mut x: i32, mut y: i32) -> i32 { return sub(x, y, OPSIZE_8); } +#[no_mangle] +pub unsafe extern "C" fn sub16(mut x: i32, mut y: i32) -> i32 { return sub(x, y, OPSIZE_16); } +#[no_mangle] +pub unsafe extern "C" fn sub32(mut x: i32, mut y: i32) -> i32 { return sub(x, y, OPSIZE_32); } +#[no_mangle] +pub unsafe extern "C" fn adc8(mut x: i32, mut y: i32) -> i32 { return adc(x, y, OPSIZE_8); } +#[no_mangle] +pub unsafe extern "C" fn adc16(mut x: i32, mut y: i32) -> i32 { return adc(x, y, OPSIZE_16); } +#[no_mangle] +pub unsafe extern "C" fn adc32(mut x: i32, mut y: i32) -> i32 { return adc(x, y, OPSIZE_32); } +#[no_mangle] +pub unsafe extern "C" fn sbb8(mut x: i32, mut y: i32) -> i32 { return sbb(x, y, OPSIZE_8); } +#[no_mangle] +pub unsafe extern "C" fn sbb16(mut x: i32, mut y: i32) -> i32 { return sbb(x, y, OPSIZE_16); } +#[no_mangle] +pub unsafe extern "C" fn sbb32(mut x: i32, mut y: i32) -> i32 { return sbb(x, y, OPSIZE_32); } +#[no_mangle] +pub unsafe extern "C" fn cmp8(mut x: i32, mut y: i32) -> () { sub(x, y, OPSIZE_8); } +#[no_mangle] +pub unsafe extern "C" fn cmp16(mut x: i32, mut y: i32) -> () { sub(x, y, OPSIZE_16); } +#[no_mangle] +pub unsafe extern "C" fn cmp32(mut x: i32, mut y: i32) -> () { sub(x, y, OPSIZE_32); } +#[no_mangle] +pub unsafe extern "C" fn inc(mut dest_operand: i32, mut op_size: i32) -> i32 { + *flags = *flags & !1i32 | getcf() as i32; + *last_op1 = dest_operand; + *last_op2 = 1i32; + let mut res: i32 = dest_operand + 1i32; + *last_result = res; + *last_add_result = *last_result; + *last_op_size = op_size; + *flags_changed = FLAGS_ALL & !1i32; + return res; +} +#[no_mangle] +pub unsafe extern "C" fn dec(mut dest_operand: i32, mut op_size: i32) -> i32 { + *flags = *flags & !1i32 | getcf() as i32; + *last_add_result = dest_operand; + *last_op2 = 1i32; + let mut res: i32 = dest_operand - 1i32; + *last_result = res; + *last_op1 = *last_result; + *last_op_size = op_size; + *flags_changed = FLAGS_ALL & !1i32; + return res; +} +#[no_mangle] +pub unsafe extern "C" fn inc8(mut x: i32) -> i32 { return inc(x, OPSIZE_8); } +#[no_mangle] +pub unsafe extern "C" fn inc16(mut x: i32) -> i32 { return inc(x, OPSIZE_16); } +#[no_mangle] +pub unsafe extern "C" fn inc32(mut x: i32) -> i32 { return inc(x, OPSIZE_32); } +#[no_mangle] +pub unsafe extern "C" fn dec8(mut x: i32) -> i32 { return dec(x, OPSIZE_8); } +#[no_mangle] +pub unsafe extern "C" fn dec16(mut x: i32) -> i32 { return dec(x, OPSIZE_16); } +#[no_mangle] +pub unsafe extern "C" fn dec32(mut x: i32) -> i32 { return dec(x, OPSIZE_32); } +#[no_mangle] +pub unsafe extern "C" fn neg(mut dest_operand: i32, mut op_size: i32) -> i32 { + let mut res: i32 = -dest_operand; + *last_result = res; + *last_op1 = *last_result; + *flags_changed = FLAGS_ALL; + *last_add_result = 0i32; + *last_op2 = dest_operand; + *last_op_size = op_size; + return res; +} +#[no_mangle] +pub unsafe extern "C" fn neg8(mut x: i32) -> i32 { return neg(x, OPSIZE_8); } +#[no_mangle] +pub unsafe extern "C" fn neg16(mut x: i32) -> i32 { return neg(x, OPSIZE_16); } +#[no_mangle] +pub unsafe extern "C" fn neg32(mut x: i32) -> i32 { return neg(x, OPSIZE_32); } +#[no_mangle] +pub unsafe extern "C" fn mul8(mut source_operand: i32) -> () { + let mut result: i32 = source_operand * *reg8.offset(AL as isize) as i32; + *reg16.offset(AX as isize) = result as u16; + *last_result = result & 255i32; + *last_op_size = OPSIZE_8; + if result < 256i32 { + *flags = *flags & !1i32 & !FLAG_OVERFLOW + } + else { + *flags = *flags | 1i32 | FLAG_OVERFLOW + } + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; +} +#[no_mangle] +pub unsafe extern "C" fn imul8(mut source_operand: i32) -> () { + let mut result: i32 = source_operand * *reg8s.offset(AL as isize) as i32; + *reg16.offset(AX as isize) = result as u16; + *last_result = result & 255i32; + *last_op_size = OPSIZE_8; + if result > 127i32 || result < -128i32 { + *flags = *flags | 1i32 | FLAG_OVERFLOW + } + else { + *flags = *flags & !1i32 & !FLAG_OVERFLOW + } + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; +} +#[no_mangle] +pub unsafe extern "C" fn mul16(mut source_operand: u32) -> () { + let mut result: u32 = source_operand.wrapping_mul(*reg16.offset(AX as isize) as u32); + let mut high_result: u32 = result >> 16i32; + *reg16.offset(AX as isize) = result as u16; + *reg16.offset(DX as isize) = high_result as u16; + *last_result = (result & 65535i32 as u32) as i32; + *last_op_size = OPSIZE_16; + if high_result == 0i32 as u32 { + *flags &= !1i32 & !FLAG_OVERFLOW + } + else { + *flags |= *flags | 1i32 | FLAG_OVERFLOW + } + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; +} +#[no_mangle] +pub unsafe extern "C" fn imul16(mut source_operand: i32) -> () { + let mut result: i32 = source_operand * *reg16s.offset(AX as isize) as i32; + *reg16.offset(AX as isize) = result as u16; + *reg16.offset(DX as isize) = (result >> 16i32) as u16; + *last_result = result & 65535i32; + *last_op_size = OPSIZE_16; + if result > 32767i32 || result < -32768i32 { + *flags |= 1i32 | FLAG_OVERFLOW + } + else { + *flags &= !1i32 & !FLAG_OVERFLOW + } + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; +} +#[no_mangle] +pub unsafe extern "C" fn imul_reg16(mut operand1: i32, mut operand2: i32) -> i32 { + dbg_assert!(operand1 < 32768i32 && operand1 >= -32768i32); + dbg_assert!(operand2 < 32768i32 && operand2 >= -32768i32); + let mut result: i32 = operand1 * operand2; + *last_result = result & 65535i32; + *last_op_size = OPSIZE_16; + if result > 32767i32 || result < -32768i32 { + *flags |= 1i32 | FLAG_OVERFLOW + } + else { + *flags &= !1i32 & !FLAG_OVERFLOW + } + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + return result; +} +#[no_mangle] +pub unsafe extern "C" fn mul32(mut source_operand: i32) -> () { + let mut dest_operand: i32 = *reg32s.offset(EAX as isize); + let mut result: u64 = (dest_operand as u32 as u64).wrapping_mul(source_operand as u32 as u64); + let mut result_low: i32 = result as i32; + let mut result_high: i32 = (result >> 32i32) as i32; + *reg32s.offset(EAX as isize) = result_low; + *reg32s.offset(EDX as isize) = result_high; + *last_result = result_low; + *last_op_size = OPSIZE_32; + if result_high == 0i32 { + *flags &= !1i32 & !FLAG_OVERFLOW + } + else { + *flags |= 1i32 | FLAG_OVERFLOW + } + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; +} +#[no_mangle] +pub unsafe extern "C" fn imul32(mut source_operand: i32) -> () { + let mut dest_operand: i32 = *reg32s.offset(EAX as isize); + let mut result: i64 = dest_operand as i64 * source_operand as i64; + let mut result_low: i32 = result as i32; + let mut result_high: i32 = (result >> 32i32) as i32; + *reg32s.offset(EAX as isize) = result_low; + *reg32s.offset(EDX as isize) = result_high; + *last_result = result_low; + *last_op_size = OPSIZE_32; + if result_high == result_low >> 31i32 { + *flags &= !1i32 & !FLAG_OVERFLOW + } + else { + *flags |= 1i32 | FLAG_OVERFLOW + } + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; +} +#[no_mangle] +pub unsafe extern "C" fn imul_reg32(mut operand1: i32, mut operand2: i32) -> i32 { + let mut result: i64 = operand1 as i64 * operand2 as i64; + let mut result_low: i32 = result as i32; + let mut result_high: i32 = (result >> 32i32) as i32; + *last_result = result_low; + *last_op_size = OPSIZE_32; + if result_high == result_low >> 31i32 { + *flags &= !1i32 & !FLAG_OVERFLOW + } + else { + *flags |= 1i32 | FLAG_OVERFLOW + } + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + return result_low; +} +#[no_mangle] +pub unsafe extern "C" fn xadd8(mut source_operand: i32, mut reg: i32) -> i32 { + let mut tmp: i32 = *reg8.offset(reg as isize) as i32; + *reg8.offset(reg as isize) = source_operand as u8; + return add(source_operand, tmp, OPSIZE_8); +} +#[no_mangle] +pub unsafe extern "C" fn xadd16(mut source_operand: i32, mut reg: i32) -> i32 { + let mut tmp: i32 = *reg16.offset(reg as isize) as i32; + *reg16.offset(reg as isize) = source_operand as u16; + return add(source_operand, tmp, OPSIZE_16); +} +#[no_mangle] +pub unsafe extern "C" fn xadd32(mut source_operand: i32, mut reg: i32) -> i32 { + let mut tmp: i32 = *reg32s.offset(reg as isize); + *reg32s.offset(reg as isize) = source_operand; + return add(source_operand, tmp, OPSIZE_32); +} +#[no_mangle] +pub unsafe extern "C" fn bcd_daa() -> () { + let mut old_al: i32 = *reg8.offset(AL as isize) as i32; + let mut old_cf: i32 = getcf() as i32; + let mut old_af: i32 = getaf() as i32; + *flags &= !1i32 & !FLAG_ADJUST; + if old_al & 15i32 > 9i32 || 0 != old_af { + let ref mut fresh0 = *reg8.offset(AL as isize); + *fresh0 = (*fresh0 as i32 + 6i32) as u8; + *flags |= FLAG_ADJUST + } + if old_al > 153i32 || 0 != old_cf { + let ref mut fresh1 = *reg8.offset(AL as isize); + *fresh1 = (*fresh1 as i32 + 96i32) as u8; + *flags |= 1i32 + } + *last_result = *reg8.offset(AL as isize) as i32; + *last_op_size = OPSIZE_8; + *last_op2 = 0i32; + *last_op1 = *last_op2; + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_ADJUST & !FLAG_OVERFLOW; +} +#[no_mangle] +pub unsafe extern "C" fn bcd_das() -> () { + let mut old_al: i32 = *reg8.offset(AL as isize) as i32; + let mut old_cf: i32 = getcf() as i32; + *flags &= !1i32; + if old_al & 15i32 > 9i32 || 0 != getaf() as i32 { + let ref mut fresh2 = *reg8.offset(AL as isize); + *fresh2 = (*fresh2 as i32 - 6i32) as u8; + *flags |= FLAG_ADJUST; + *flags = *flags & !1i32 | old_cf | (old_al < 6i32) as i32 + } + else { + *flags &= !FLAG_ADJUST + } + if old_al > 153i32 || 0 != old_cf { + let ref mut fresh3 = *reg8.offset(AL as isize); + *fresh3 = (*fresh3 as i32 - 96i32) as u8; + *flags |= 1i32 + } + *last_result = *reg8.offset(AL as isize) as i32; + *last_op_size = OPSIZE_8; + *last_op2 = 0i32; + *last_op1 = *last_op2; + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_ADJUST & !FLAG_OVERFLOW; +} +#[no_mangle] +pub unsafe extern "C" fn bcd_aad(mut imm8: i32) -> () { + let mut result: i32 = + *reg8.offset(AL as isize) as i32 + *reg8.offset(AH as isize) as i32 * imm8; + *last_result = result & 255i32; + *reg16.offset(AX as isize) = *last_result as u16; + *last_op_size = OPSIZE_8; + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_ADJUST & !FLAG_OVERFLOW; + *flags &= !1i32 & !FLAG_ADJUST & !FLAG_OVERFLOW; + if result > 65535i32 { + *flags |= 1i32 + }; +} +#[no_mangle] +pub unsafe extern "C" fn bcd_aam(mut imm8: i32) -> () { + c_comment!(("ascii adjust after multiplication")); + if imm8 == 0i32 { + trigger_de(); + } + else { + let mut temp: u8 = *reg8.offset(AL as isize); + *reg8.offset(AH as isize) = (temp as i32 / imm8) as u8; + *reg8.offset(AL as isize) = (temp as i32 % imm8) as u8; + *last_result = *reg8.offset(AL as isize) as i32; + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_ADJUST & !FLAG_OVERFLOW; + *flags &= !1i32 & !FLAG_ADJUST & !FLAG_OVERFLOW + }; +} +#[no_mangle] +pub unsafe extern "C" fn bcd_aaa() -> () { + if *reg8.offset(AL as isize) as i32 & 15i32 > 9i32 || 0 != getaf() as i32 { + let ref mut fresh4 = *reg16.offset(AX as isize); + *fresh4 = (*fresh4 as i32 + 6i32) as u16; + let ref mut fresh5 = *reg8.offset(AH as isize); + *fresh5 = (*fresh5 as i32 + 1i32) as u8; + *flags |= FLAG_ADJUST | 1i32 + } + else { + *flags &= !FLAG_ADJUST & !1i32 + } + let ref mut fresh6 = *reg8.offset(AL as isize); + *fresh6 = (*fresh6 as i32 & 15i32) as u8; + *flags_changed &= !FLAG_ADJUST & !1i32; +} +#[no_mangle] +pub unsafe extern "C" fn bcd_aas() -> () { + if *reg8.offset(AL as isize) as i32 & 15i32 > 9i32 || 0 != getaf() as i32 { + let ref mut fresh7 = *reg16.offset(AX as isize); + *fresh7 = (*fresh7 as i32 - 6i32) as u16; + let ref mut fresh8 = *reg8.offset(AH as isize); + *fresh8 = (*fresh8 as i32 - 1i32) as u8; + *flags |= FLAG_ADJUST | 1i32 + } + else { + *flags &= !FLAG_ADJUST & !1i32 + } + let ref mut fresh9 = *reg8.offset(AL as isize); + *fresh9 = (*fresh9 as i32 & 15i32) as u8; + *flags_changed &= !FLAG_ADJUST & !1i32; +} +#[no_mangle] +pub unsafe extern "C" fn and( + mut dest_operand: i32, + mut source_operand: i32, + mut op_size: i32, +) -> i32 { + *last_result = dest_operand & source_operand; + *last_op_size = op_size; + *flags &= !1i32 & !FLAG_OVERFLOW & !FLAG_ADJUST; + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW & !FLAG_ADJUST; + return *last_result; +} +#[no_mangle] +pub unsafe extern "C" fn or( + mut dest_operand: i32, + mut source_operand: i32, + mut op_size: i32, +) -> i32 { + *last_result = dest_operand | source_operand; + *last_op_size = op_size; + *flags &= !1i32 & !FLAG_OVERFLOW & !FLAG_ADJUST; + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW & !FLAG_ADJUST; + return *last_result; +} +#[no_mangle] +pub unsafe extern "C" fn xor( + mut dest_operand: i32, + mut source_operand: i32, + mut op_size: i32, +) -> i32 { + *last_result = dest_operand ^ source_operand; + *last_op_size = op_size; + *flags &= !1i32 & !FLAG_OVERFLOW & !FLAG_ADJUST; + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW & !FLAG_ADJUST; + return *last_result; +} +#[no_mangle] +pub unsafe extern "C" fn and8(mut x: i32, mut y: i32) -> i32 { return and(x, y, OPSIZE_8); } +#[no_mangle] +pub unsafe extern "C" fn and16(mut x: i32, mut y: i32) -> i32 { return and(x, y, OPSIZE_16); } +#[no_mangle] +pub unsafe extern "C" fn and32(mut x: i32, mut y: i32) -> i32 { return and(x, y, OPSIZE_32); } +#[no_mangle] +pub unsafe extern "C" fn test8(mut x: i32, mut y: i32) -> () { and(x, y, OPSIZE_8); } +#[no_mangle] +pub unsafe extern "C" fn test16(mut x: i32, mut y: i32) -> () { and(x, y, OPSIZE_16); } +#[no_mangle] +pub unsafe extern "C" fn test32(mut x: i32, mut y: i32) -> () { and(x, y, OPSIZE_32); } +#[no_mangle] +pub unsafe extern "C" fn or8(mut x: i32, mut y: i32) -> i32 { return or(x, y, OPSIZE_8); } +#[no_mangle] +pub unsafe extern "C" fn or16(mut x: i32, mut y: i32) -> i32 { return or(x, y, OPSIZE_16); } +#[no_mangle] +pub unsafe extern "C" fn or32(mut x: i32, mut y: i32) -> i32 { return or(x, y, OPSIZE_32); } +#[no_mangle] +pub unsafe extern "C" fn xor8(mut x: i32, mut y: i32) -> i32 { return xor(x, y, OPSIZE_8); } +#[no_mangle] +pub unsafe extern "C" fn xor16(mut x: i32, mut y: i32) -> i32 { return xor(x, y, OPSIZE_16); } +#[no_mangle] +pub unsafe extern "C" fn xor32(mut x: i32, mut y: i32) -> i32 { return xor(x, y, OPSIZE_32); } +#[no_mangle] +pub unsafe extern "C" fn rol8(mut dest_operand: i32, mut count: i32) -> i32 { + if 0 == count { + return dest_operand; + } + else { + count &= 7i32; + let mut result: i32 = dest_operand << count | dest_operand >> 8i32 - count; + *flags_changed &= !1i32 & !FLAG_OVERFLOW; + *flags = *flags & !1i32 & !FLAG_OVERFLOW + | result & 1i32 + | (result << 11i32 ^ result << 4i32) & FLAG_OVERFLOW; + return result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn rol16(mut dest_operand: i32, mut count: i32) -> i32 { + if 0 == count { + return dest_operand; + } + else { + count &= 15i32; + let mut result: i32 = dest_operand << count | dest_operand >> 16i32 - count; + *flags_changed &= !1i32 & !FLAG_OVERFLOW; + *flags = *flags & !1i32 & !FLAG_OVERFLOW + | result & 1i32 + | (result << 11i32 ^ result >> 4i32) & FLAG_OVERFLOW; + return result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn rol32(mut dest_operand: i32, mut count: i32) -> i32 { + if 0 == count { + return dest_operand; + } + else { + let mut result: i32 = + ((dest_operand << count) as u32 | dest_operand as u32 >> 32i32 - count) as i32; + *flags_changed &= !1i32 & !FLAG_OVERFLOW; + *flags = *flags & !1i32 & !FLAG_OVERFLOW + | result & 1i32 + | (result << 11i32 ^ result >> 20i32) & FLAG_OVERFLOW; + return result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn rcl8(mut dest_operand: i32, mut count: i32) -> i32 { + count %= 9i32; + if 0 == count { + return dest_operand; + } + else { + let mut result: i32 = + dest_operand << count | (getcf() as i32) << count - 1i32 | dest_operand >> 9i32 - count; + *flags_changed &= !1i32 & !FLAG_OVERFLOW; + *flags = *flags & !1i32 & !FLAG_OVERFLOW + | result >> 8i32 & 1i32 + | (result << 3i32 ^ result << 4i32) & FLAG_OVERFLOW; + return result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn rcl16(mut dest_operand: i32, mut count: i32) -> i32 { + count %= 17i32; + if 0 == count { + return dest_operand; + } + else { + let mut result: i32 = dest_operand << count + | (getcf() as i32) << count - 1i32 + | dest_operand >> 17i32 - count; + *flags_changed &= !1i32 & !FLAG_OVERFLOW; + *flags = *flags & !1i32 & !FLAG_OVERFLOW + | result >> 16i32 & 1i32 + | (result >> 5i32 ^ result >> 4i32) & FLAG_OVERFLOW; + return result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn rcl32(mut dest_operand: i32, mut count: i32) -> i32 { + if 0 == count { + return dest_operand; + } + else { + let mut result: i32 = dest_operand << count | (getcf() as i32) << count - 1i32; + if count > 1i32 { + result = (result as u32 | dest_operand as u32 >> 33i32 - count) as i32 + } + *flags_changed &= !1i32 & !FLAG_OVERFLOW; + *flags = ((*flags & !1i32 & !FLAG_OVERFLOW) as u32 + | dest_operand as u32 >> 32i32 - count & 1i32 as u32) as i32; + *flags |= (*flags << 11i32 ^ result >> 20i32) & FLAG_OVERFLOW; + return result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn ror8(mut dest_operand: i32, mut count: i32) -> i32 { + if 0 == count { + return dest_operand; + } + else { + count &= 7i32; + let mut result: i32 = dest_operand >> count | dest_operand << 8i32 - count; + *flags_changed &= !1i32 & !FLAG_OVERFLOW; + *flags = *flags & !1i32 & !FLAG_OVERFLOW + | result >> 7i32 & 1i32 + | (result << 4i32 ^ result << 5i32) & FLAG_OVERFLOW; + return result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn ror16(mut dest_operand: i32, mut count: i32) -> i32 { + if 0 == count { + return dest_operand; + } + else { + count &= 15i32; + let mut result: i32 = dest_operand >> count | dest_operand << 16i32 - count; + *flags_changed &= !1i32 & !FLAG_OVERFLOW; + *flags = *flags & !1i32 & !FLAG_OVERFLOW + | result >> 15i32 & 1i32 + | (result >> 4i32 ^ result >> 3i32) & FLAG_OVERFLOW; + return result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn ror32(mut dest_operand: i32, mut count: i32) -> i32 { + if 0 == count { + return dest_operand; + } + else { + let mut result: i32 = + (dest_operand as u32 >> count | (dest_operand << 32i32 - count) as u32) as i32; + *flags_changed &= !1i32 & !FLAG_OVERFLOW; + *flags = *flags & !1i32 & !FLAG_OVERFLOW + | result >> 31i32 & 1i32 + | (result >> 20i32 ^ result >> 19i32) & FLAG_OVERFLOW; + return result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn rcr8(mut dest_operand: i32, mut count: i32) -> i32 { + count %= 9i32; + if 0 == count { + return dest_operand; + } + else { + let mut result: i32 = + dest_operand >> count | (getcf() as i32) << 8i32 - count | dest_operand << 9i32 - count; + *flags_changed &= !1i32 & !FLAG_OVERFLOW; + *flags = *flags & !1i32 & !FLAG_OVERFLOW + | result >> 8i32 & 1i32 + | (result << 4i32 ^ result << 5i32) & FLAG_OVERFLOW; + return result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn rcr16(mut dest_operand: i32, mut count: i32) -> i32 { + count %= 17i32; + if 0 == count { + return dest_operand; + } + else { + let mut result: i32 = dest_operand >> count + | (getcf() as i32) << 16i32 - count + | dest_operand << 17i32 - count; + *flags_changed &= !1i32 & !FLAG_OVERFLOW; + *flags = *flags & !1i32 & !FLAG_OVERFLOW + | result >> 16i32 & 1i32 + | (result >> 4i32 ^ result >> 3i32) & FLAG_OVERFLOW; + return result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn rcr32(mut dest_operand: i32, mut count: i32) -> i32 { + if 0 == count { + return dest_operand; + } + else { + let mut result: i32 = + (dest_operand as u32 >> count | ((getcf() as i32) << 32i32 - count) as u32) as i32; + if count > 1i32 { + result |= dest_operand << 33i32 - count + } + *flags_changed &= !1i32 & !FLAG_OVERFLOW; + *flags = *flags & !1i32 & !FLAG_OVERFLOW + | dest_operand >> count - 1i32 & 1i32 + | (result >> 20i32 ^ result >> 19i32) & FLAG_OVERFLOW; + return result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn div8(mut source_operand: u32) -> () { + if source_operand == 0i32 as u32 { + trigger_de(); + return; + } + else { + let mut target_operand: u16 = *reg16.offset(AX as isize); + let mut result: u16 = (target_operand as u32).wrapping_div(source_operand) as u16; + if result as i32 >= 256i32 { + trigger_de(); + } + else { + *reg8.offset(AL as isize) = result as u8; + *reg8.offset(AH as isize) = (target_operand as u32).wrapping_rem(source_operand) as u8 + } + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn idiv8(mut source_operand: i32) -> () { + if source_operand == 0i32 { + trigger_de(); + return; + } + else { + let mut target_operand: i32 = *reg16s.offset(AX as isize) as i32; + let mut result: i32 = target_operand / source_operand; + if result >= 128i32 || result <= -129i32 { + trigger_de(); + } + else { + *reg8.offset(AL as isize) = result as u8; + *reg8.offset(AH as isize) = (target_operand % source_operand) as u8 + } + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn div16(mut source_operand: u32) -> () { + if source_operand == 0i32 as u32 { + trigger_de(); + return; + } + else { + let mut target_operand: u32 = (*reg16.offset(AX as isize) as i32 + | (*reg16.offset(DX as isize) as i32) << 16i32) + as u32; + let mut result: u32 = target_operand.wrapping_div(source_operand); + if result >= 65536i32 as u32 { + trigger_de(); + } + else { + *reg16.offset(AX as isize) = result as u16; + *reg16.offset(DX as isize) = target_operand.wrapping_rem(source_operand) as u16 + } + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn idiv16(mut source_operand: i32) -> () { + if source_operand == 0i32 { + trigger_de(); + return; + } + else { + let mut target_operand: i32 = + *reg16.offset(AX as isize) as i32 | (*reg16.offset(DX as isize) as i32) << 16i32; + let mut result: i32 = target_operand / source_operand; + if result >= 32768i32 || result <= -32769i32 { + trigger_de(); + } + else { + *reg16.offset(AX as isize) = result as u16; + *reg16.offset(DX as isize) = (target_operand % source_operand) as u16 + } + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn div32(mut source_operand: u32) -> () { + if source_operand == 0i32 as u32 { + trigger_de(); + return; + } + else { + let mut target_low: u32 = *reg32s.offset(EAX as isize) as u32; + let mut target_high: u32 = *reg32s.offset(EDX as isize) as u32; + let mut target_operand: u64 = (target_high as u64) << 32i32 | target_low as u64; + let mut result: u64 = target_operand.wrapping_div(source_operand as u64); + if result > 4294967295u32 as u64 { + trigger_de(); + return; + } + else { + let mut mod_0: i32 = target_operand.wrapping_rem(source_operand as u64) as i32; + *reg32s.offset(EAX as isize) = result as i32; + *reg32s.offset(EDX as isize) = mod_0; + return; + } + }; +} +#[no_mangle] +pub unsafe extern "C" fn idiv32(mut source_operand: i32) -> () { + if source_operand == 0i32 { + trigger_de(); + return; + } + else { + let mut target_low: u32 = *reg32s.offset(EAX as isize) as u32; + let mut target_high: u32 = *reg32s.offset(EDX as isize) as u32; + let mut target_operand: i64 = ((target_high as u64) << 32i32 | target_low as u64) as i64; + if source_operand == -1i32 + && target_operand == (-1i32 as i64 - 9223372036854775807i64) as i64 + { + trigger_de(); + return; + } + else { + let mut result: i64 = target_operand / source_operand as i64; + if result < (-1i32 - 2147483647i32) as i64 || result > 2147483647i32 as i64 { + trigger_de(); + return; + } + else { + let mut mod_0: i32 = (target_operand % source_operand as i64) as i32; + *reg32s.offset(EAX as isize) = result as i32; + *reg32s.offset(EDX as isize) = mod_0; + return; + } + } + }; +} +#[no_mangle] +pub unsafe extern "C" fn shl8(mut dest_operand: i32, mut count: i32) -> i32 { + if count == 0i32 { + return dest_operand; + } + else { + *last_result = dest_operand << count; + *last_op_size = OPSIZE_8; + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + *flags = *flags & !1i32 & !FLAG_OVERFLOW + | *last_result >> 8i32 & 1i32 + | (*last_result << 3i32 ^ *last_result << 4i32) & FLAG_OVERFLOW; + return *last_result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn shl16(mut dest_operand: i32, mut count: i32) -> i32 { + if count == 0i32 { + return dest_operand; + } + else { + *last_result = dest_operand << count; + *last_op_size = OPSIZE_16; + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + *flags = *flags & !1i32 & !FLAG_OVERFLOW + | *last_result >> 16i32 & 1i32 + | (*last_result >> 5i32 ^ *last_result >> 4i32) & FLAG_OVERFLOW; + return *last_result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn shl32(mut dest_operand: i32, mut count: i32) -> i32 { + if count == 0i32 { + return dest_operand; + } + else { + *last_result = dest_operand << count; + *last_op_size = OPSIZE_32; + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + c_comment!(("test this")); + *flags = *flags & !1i32 & !FLAG_OVERFLOW | dest_operand >> 32i32 - count & 1i32; + *flags |= (*flags & 1i32 ^ *last_result >> 31i32 & 1i32) << 11i32 & FLAG_OVERFLOW; + return *last_result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn shr8(mut dest_operand: i32, mut count: i32) -> i32 { + if count == 0i32 { + return dest_operand; + } + else { + *last_result = dest_operand >> count; + *last_op_size = OPSIZE_8; + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + *flags = *flags & !1i32 & !FLAG_OVERFLOW + | dest_operand >> count - 1i32 & 1i32 + | (dest_operand >> 7i32 & 1i32) << 11i32 & FLAG_OVERFLOW; + return *last_result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn shr16(mut dest_operand: i32, mut count: i32) -> i32 { + if count == 0i32 { + return dest_operand; + } + else { + *last_result = dest_operand >> count; + *last_op_size = OPSIZE_16; + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + *flags = *flags & !1i32 & !FLAG_OVERFLOW + | dest_operand >> count - 1i32 & 1i32 + | dest_operand >> 4i32 & FLAG_OVERFLOW; + return *last_result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn shr32(mut dest_operand: i32, mut count: i32) -> i32 { + if count == 0i32 { + return dest_operand; + } + else { + *last_result = (dest_operand as u32 >> count) as i32; + *last_op_size = OPSIZE_32; + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + *flags = ((*flags & !1i32 & !FLAG_OVERFLOW) as u32 + | dest_operand as u32 >> count - 1i32 & 1i32 as u32 + | (dest_operand >> 20i32 & FLAG_OVERFLOW) as u32) as i32; + return *last_result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn sar8(mut dest_operand: i32, mut count: i32) -> i32 { + if count == 0i32 { + return dest_operand; + } + else { + if count < 8i32 { + *last_result = dest_operand << 24i32 >> count + 24i32; + c_comment!(("of is zero")); + *flags = *flags & !1i32 & !FLAG_OVERFLOW | dest_operand >> count - 1i32 & 1i32 + } + else { + *last_result = dest_operand << 24i32 >> 31i32; + *flags = *flags & !1i32 & !FLAG_OVERFLOW | *last_result & 1i32 + } + *last_op_size = OPSIZE_8; + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + return *last_result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn sar16(mut dest_operand: i32, mut count: i32) -> i32 { + if count == 0i32 { + return dest_operand; + } + else { + if count < 16i32 { + *last_result = dest_operand << 16i32 >> count + 16i32; + *flags = *flags & !1i32 & !FLAG_OVERFLOW | dest_operand >> count - 1i32 & 1i32 + } + else { + *last_result = dest_operand << 16i32 >> 31i32; + *flags = *flags & !1i32 & !FLAG_OVERFLOW | *last_result & 1i32 + } + *last_op_size = OPSIZE_16; + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + return *last_result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn sar32(mut dest_operand: i32, mut count: i32) -> i32 { + if count == 0i32 { + return dest_operand; + } + else { + *last_result = dest_operand >> count; + *last_op_size = OPSIZE_32; + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + *flags = ((*flags & !1i32 & !FLAG_OVERFLOW) as u32 + | dest_operand as u32 >> count - 1i32 & 1i32 as u32) as i32; + return *last_result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn shrd16( + mut dest_operand: i32, + mut source_operand: i32, + mut count: i32, +) -> i32 { + if count == 0i32 { + return dest_operand; + } + else { + if count <= 16i32 { + *last_result = dest_operand >> count | source_operand << 16i32 - count; + *flags = *flags & !1i32 | dest_operand >> count - 1i32 & 1i32 + } + else { + *last_result = dest_operand << 32i32 - count | source_operand >> count - 16i32; + *flags = *flags & !1i32 | source_operand >> count - 17i32 & 1i32 + } + *last_op_size = OPSIZE_16; + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + *flags = *flags & !FLAG_OVERFLOW | (*last_result ^ dest_operand) >> 4i32 & FLAG_OVERFLOW; + return *last_result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn shrd32( + mut dest_operand: i32, + mut source_operand: i32, + mut count: i32, +) -> i32 { + if count == 0i32 { + return dest_operand; + } + else { + *last_result = + (dest_operand as u32 >> count | (source_operand << 32i32 - count) as u32) as i32; + *last_op_size = OPSIZE_32; + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + *flags = + ((*flags & !1i32) as u32 | dest_operand as u32 >> count - 1i32 & 1i32 as u32) as i32; + *flags = *flags & !FLAG_OVERFLOW | (*last_result ^ dest_operand) >> 20i32 & FLAG_OVERFLOW; + return *last_result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn shld16( + mut dest_operand: i32, + mut source_operand: i32, + mut count: i32, +) -> i32 { + if count == 0i32 { + return dest_operand; + } + else { + if count <= 16i32 { + *last_result = + ((dest_operand << count) as u32 | source_operand as u32 >> 16i32 - count) as i32; + *flags = ((*flags & !1i32) as u32 | dest_operand as u32 >> 16i32 - count & 1i32 as u32) + as i32 + } + else { + *last_result = dest_operand >> 32i32 - count | source_operand << count - 16i32; + *flags = ((*flags & !1i32) as u32 + | source_operand as u32 >> 32i32 - count & 1i32 as u32) as i32 + } + *last_op_size = OPSIZE_16; + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + *flags = *flags & !FLAG_OVERFLOW | (*flags & 1i32 ^ *last_result >> 15i32 & 1i32) << 11i32; + return *last_result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn shld32( + mut dest_operand: i32, + mut source_operand: i32, + mut count: i32, +) -> i32 { + if count == 0i32 { + return dest_operand; + } + else { + *last_result = + ((dest_operand << count) as u32 | source_operand as u32 >> 32i32 - count) as i32; + *last_op_size = OPSIZE_32; + *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + *flags = + ((*flags & !1i32) as u32 | dest_operand as u32 >> 32i32 - count & 1i32 as u32) as i32; + if count == 1i32 { + *flags = + *flags & !FLAG_OVERFLOW | (*flags & 1i32 ^ *last_result >> 31i32 & 1i32) << 11i32 + } + else { + *flags &= !FLAG_OVERFLOW + } + return *last_result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn bt_reg(mut bit_base: i32, mut bit_offset: i32) -> () { + *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; + *flags_changed &= !1i32; +} +#[no_mangle] +pub unsafe extern "C" fn btc_reg(mut bit_base: i32, mut bit_offset: i32) -> i32 { + *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; + *flags_changed &= !1i32; + return bit_base ^ 1i32 << bit_offset; +} +#[no_mangle] +pub unsafe extern "C" fn bts_reg(mut bit_base: i32, mut bit_offset: i32) -> i32 { + *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; + *flags_changed &= !1i32; + return bit_base | 1i32 << bit_offset; +} +#[no_mangle] +pub unsafe extern "C" fn btr_reg(mut bit_base: i32, mut bit_offset: i32) -> i32 { + *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; + *flags_changed &= !1i32; + return bit_base & !(1i32 << bit_offset); +} +#[no_mangle] +pub unsafe extern "C" fn bt_mem(mut virt_addr: i32, mut bit_offset: i32) -> () { + let mut bit_base: i32 = safe_read8(virt_addr + (bit_offset >> 3i32)); + bit_offset &= 7i32; + *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; + *flags_changed &= !1i32; +} +#[no_mangle] +pub unsafe extern "C" fn btc_mem(mut virt_addr: i32, mut bit_offset: i32) -> () { + let mut phys_addr: i32 = translate_address_write(virt_addr + (bit_offset >> 3i32)) as i32; + let mut bit_base: i32 = read8(phys_addr as u32); + bit_offset &= 7i32; + *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; + *flags_changed &= !1i32; + write8(phys_addr as u32, bit_base ^ 1i32 << bit_offset); +} +#[no_mangle] +pub unsafe extern "C" fn btr_mem(mut virt_addr: i32, mut bit_offset: i32) -> () { + let mut phys_addr: i32 = translate_address_write(virt_addr + (bit_offset >> 3i32)) as i32; + let mut bit_base: i32 = read8(phys_addr as u32); + bit_offset &= 7i32; + *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; + *flags_changed &= !1i32; + write8(phys_addr as u32, bit_base & !(1i32 << bit_offset)); +} +#[no_mangle] +pub unsafe extern "C" fn bts_mem(mut virt_addr: i32, mut bit_offset: i32) -> () { + let mut phys_addr: i32 = translate_address_write(virt_addr + (bit_offset >> 3i32)) as i32; + let mut bit_base: i32 = read8(phys_addr as u32); + bit_offset &= 7i32; + *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; + *flags_changed &= !1i32; + write8(phys_addr as u32, bit_base | 1i32 << bit_offset); +} +#[no_mangle] +pub unsafe extern "C" fn bsf16(mut old: i32, mut bit_base: i32) -> i32 { + *flags_changed = FLAGS_ALL & !FLAG_ZERO; + *last_op_size = OPSIZE_16; + if bit_base == 0i32 { + *flags |= FLAG_ZERO; + *last_result = bit_base; + c_comment!(("not defined in the docs, but value doesn\'t change on my intel machine")); + return old; + } + else { + *flags &= !FLAG_ZERO; + *last_result = int_log2(-bit_base & bit_base); + return *last_result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn bsf32(mut old: i32, mut bit_base: i32) -> i32 { + *flags_changed = FLAGS_ALL & !FLAG_ZERO; + *last_op_size = OPSIZE_32; + if bit_base == 0i32 { + *flags |= FLAG_ZERO; + *last_result = bit_base; + return old; + } + else { + *flags &= !FLAG_ZERO; + *last_result = int_log2((-bit_base & bit_base) as u32 as i32); + return *last_result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn bsr16(mut old: i32, mut bit_base: i32) -> i32 { + *flags_changed = FLAGS_ALL & !FLAG_ZERO; + *last_op_size = OPSIZE_16; + if bit_base == 0i32 { + *flags |= FLAG_ZERO; + *last_result = bit_base; + return old; + } + else { + *flags &= !FLAG_ZERO; + *last_result = int_log2(bit_base); + return *last_result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn bsr32(mut old: i32, mut bit_base: i32) -> i32 { + *flags_changed = FLAGS_ALL & !FLAG_ZERO; + *last_op_size = OPSIZE_32; + if bit_base == 0i32 { + *flags |= FLAG_ZERO; + *last_result = bit_base; + return old; + } + else { + *flags &= !FLAG_ZERO; + *last_result = int_log2(bit_base as u32 as i32); + return *last_result; + }; +} +#[no_mangle] +pub unsafe extern "C" fn popcnt(mut v: i32) -> i32 { + *flags_changed = 0i32; + *flags &= !FLAGS_ALL; + if 0 != v { + c_comment!(("http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel")); + v = v - (v >> 1i32 & 1431655765i32); + v = (v & 858993459i32) + (v >> 2i32 & 858993459i32); + return (v + (v >> 4i32) & 252645135i32) * 16843009i32 >> 24i32; + } + else { + *flags |= FLAG_ZERO; + return 0i32; + }; +} +#[no_mangle] +pub unsafe extern "C" fn saturate_sw_to_ub(mut v: u32) -> u32 { + dbg_assert!(v & 4294901760u32 == 0i32 as u32); + let mut ret: u32 = v; + if ret >= 32768i32 as u32 { + ret = 0i32 as u32 + } + else if ret > 255i32 as u32 { + ret = 255i32 as u32 + } + dbg_assert!(ret & 4294967040u32 == 0i32 as u32); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn saturate_sw_to_sb(mut v: i32) -> i32 { + dbg_assert!(v as u32 & 4294901760u32 == 0i32 as u32); + let mut ret: i32 = v; + if ret > 65408i32 { + ret = ret & 255i32 + } + else if ret > 32767i32 { + ret = 128i32 + } + else if ret > 127i32 { + ret = 127i32 + } + dbg_assert!(ret as u32 & 4294967040u32 == 0i32 as u32); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn saturate_sd_to_sw(mut v: u32) -> u32 { + let mut ret: u32 = v; + if ret > 4294934528u32 { + ret = ret & 65535i32 as u32 + } + else if ret > 2147483647i32 as u32 { + ret = 32768i32 as u32 + } + else if ret > 32767i32 as u32 { + ret = 32767i32 as u32 + } + dbg_assert!(ret & 4294901760u32 == 0i32 as u32); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn saturate_sd_to_sb(mut v: u32) -> u32 { + let mut ret: u32 = v; + if ret > 4294967168u32 { + ret = ret & 255i32 as u32 + } + else if ret > 2147483647i32 as u32 { + ret = 128i32 as u32 + } + else if ret > 127i32 as u32 { + ret = 127i32 as u32 + } + dbg_assert!(ret & 4294967040u32 == 0i32 as u32); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn saturate_sd_to_ub(mut v: i32) -> i32 { + let mut ret: i32 = v; + if ret < 0i32 { + ret = 0i32 + } + dbg_assert!(ret as u32 & 4294967040u32 == 0i32 as u32); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn saturate_ud_to_ub(mut v: u32) -> u32 { + let mut ret: u32 = v; + if ret > 255i32 as u32 { + ret = 255i32 as u32 + } + dbg_assert!(ret & 4294967040u32 == 0i32 as u32); + return ret; +} +#[no_mangle] +pub unsafe extern "C" fn saturate_uw(mut v: u32) -> i32 { + let mut ret: u32 = v; + if ret > 2147483647i32 as u32 { + ret = 0i32 as u32 + } + else if ret > 65535i32 as u32 { + ret = 65535i32 as u32 + } + dbg_assert!(ret & 4294901760u32 == 0i32 as u32); + return ret as i32; +} diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs new file mode 100644 index 00000000..f5dc700a --- /dev/null +++ b/src/rust/cpu2/cpu.rs @@ -0,0 +1,2736 @@ +#![allow( + dead_code, + mutable_transmutes, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_mut +)] +#![feature(extern_types, libc)] + +extern "C" { + + #[no_mangle] + fn __fpclassifyl(_: f64) -> i32; + + #[no_mangle] + fn dbg_log(m: *const i8) -> (); + #[no_mangle] + fn dbg_log1(m: *const i8, x: i32) -> (); + #[no_mangle] + fn dbg_log2(m: *const i8, x: i32, y: i32) -> (); + #[no_mangle] + fn dbg_log5(m: *const i8, x: i32, y: i32, z: i32, i: i32, j: i32) -> (); + #[no_mangle] + fn dbg_log6(m: *const i8, x: i32, y: i32, z: i32, i: i32, j: i32, k: i32) -> (); + #[no_mangle] + fn dbg_trace() -> (); + #[no_mangle] + fn c_comment(m: *const i8) -> (); + #[no_mangle] + fn call_indirect1(index: i32, arg: i32) -> (); + #[no_mangle] + fn getof() -> bool; + #[no_mangle] + fn getsf() -> bool; + #[no_mangle] + fn getzf() -> bool; + #[no_mangle] + fn getaf() -> bool; + #[no_mangle] + fn getpf() -> bool; + #[no_mangle] + fn getcf() -> bool; + #[no_mangle] + static flags: *mut i32; + #[no_mangle] + static cpl: *mut u8; + #[no_mangle] + fn jit_page_has_code(physical_page: u32) -> bool; + #[no_mangle] + fn in_mapped_range(addr: u32) -> bool; + #[no_mangle] + static cr: *mut i32; + #[no_mangle] + static tlb_data: *mut i32; + #[no_mangle] + static last_virt_esp: *mut i32; + #[no_mangle] + static last_virt_eip: *mut i32; + #[no_mangle] + fn profiler_stat_increment(stat: stat_name) -> (); + #[no_mangle] + fn read_aligned32(addr: u32) -> i32; + #[no_mangle] + fn write_aligned32(addr: u32, value: i32) -> (); + #[no_mangle] + fn throw_cpu_exception() -> (); + #[no_mangle] + fn call_interrupt_vector( + interrupt_nr: i32, + is_software_int: bool, + has_error_code: bool, + error_code: i32, + ) -> (); + #[no_mangle] + static page_fault: *mut bool; + #[no_mangle] + static previous_ip: *mut i32; + #[no_mangle] + static instruction_pointer: *mut i32; + #[no_mangle] + static eip_phys: *mut i32; + #[no_mangle] + fn read16(addr: u32) -> i32; + #[no_mangle] + fn read32s(addr: u32) -> i32; + #[no_mangle] + static prefixes: *mut u8; + #[no_mangle] + static is_32: *mut bool; + #[no_mangle] + static segment_offsets: *mut i32; + #[no_mangle] + fn cpu_exception_hook(_: i32) -> bool; + #[no_mangle] + static segment_is_null: *mut bool; + #[no_mangle] + static protected_mode: *mut bool; + #[no_mangle] + fn resolve_modrm16(modrm_byte: i32) -> i32; + #[no_mangle] + fn resolve_modrm32(modrm_byte: i32) -> i32; + #[no_mangle] + fn run_instruction(opcode: i32) -> (); + #[no_mangle] + fn logop(_: i32, _: i32) -> (); + #[no_mangle] + static timestamp_counter: *mut u32; + #[no_mangle] + fn profiler_stat_increment_by(stat: stat_name, by: i32) -> (); + #[no_mangle] + static stack_size_32: *mut bool; + #[no_mangle] + fn jit_increase_hotness_and_maybe_compile( + phys_addr: u32, + cs_offset: u32, + flags_0: cached_state_flags, + ) -> (); + #[no_mangle] + fn jit_find_cache_entry(phys_addr: u32, flags_0: cached_state_flags) -> u32; + #[no_mangle] + static in_hlt: *mut bool; + #[no_mangle] + fn read8(addr: u32) -> i32; + #[no_mangle] + fn read_aligned16(addr: u32) -> i32; + #[no_mangle] + fn write8(addr: u32, value: i32) -> (); + #[no_mangle] + fn read64s(addr: u32) -> i64; + #[no_mangle] + fn read128(addr: u32) -> reg128; + #[no_mangle] + fn write16(addr: u32, value: i32) -> (); + #[no_mangle] + fn write32(addr: u32, value: i32) -> (); + #[no_mangle] + fn write64(addr: u32, value: i64) -> (); + #[no_mangle] + fn write128(addr: u32, value: reg128) -> (); + #[no_mangle] + static reg8: *mut u8; + #[no_mangle] + static reg16: *mut u16; + #[no_mangle] + static reg32s: *mut i32; + #[no_mangle] + static reg_mmx: *mut reg64; + #[no_mangle] + static reg_xmm: *mut reg128; + #[no_mangle] + fn microtick() -> f64; + #[no_mangle] + static opstats_buffer_0f: *mut u32; + #[no_mangle] + static opstats_buffer: *mut u32; + #[no_mangle] + static reg8s: *mut i8; + #[no_mangle] + static reg16s: *mut i16; + #[no_mangle] + static last_op1: *mut i32; + #[no_mangle] + static last_op2: *mut i32; + #[no_mangle] + static last_op_size: *mut i32; + #[no_mangle] + static last_add_result: *mut i32; + #[no_mangle] + static last_result: *mut i32; + #[no_mangle] + static flags_changed: *mut i32; + #[no_mangle] + static a20_enabled: *mut bool; + #[no_mangle] + static idtr_size: *mut i32; + #[no_mangle] + static idtr_offset: *mut i32; + #[no_mangle] + static gdtr_size: *mut i32; + #[no_mangle] + static gdtr_offset: *mut i32; + #[no_mangle] + static esp_phys: *mut i32; + #[no_mangle] + static sysenter_cs: *mut i32; + #[no_mangle] + static sysenter_esp: *mut i32; + #[no_mangle] + static sysenter_eip: *mut i32; + #[no_mangle] + static sreg: *mut u16; + #[no_mangle] + static dreg: *mut i32; + #[no_mangle] + static fw_value: *mut i32; + #[no_mangle] + static segment_limits: *mut u32; + #[no_mangle] + static memory_size: *mut u32; + #[no_mangle] + static fpu_stack_empty: *mut i32; + #[no_mangle] + static mxcsr: *mut i32; + #[no_mangle] + static current_tsc: *mut u64; + #[no_mangle] + static fpu_st: *mut f64; + #[no_mangle] + static fpu_st8: *mut u8; + #[no_mangle] + static fpu_st32: *mut i32; + #[no_mangle] + static fpu_stack_ptr: *mut u32; + #[no_mangle] + static fpu_control_word: *mut i32; + #[no_mangle] + static fpu_status_word: *mut i32; + #[no_mangle] + static fpu_opcode: *mut i32; + #[no_mangle] + static fpu_ip: *mut i32; + #[no_mangle] + static fpu_ip_selector: *mut i32; + #[no_mangle] + static fpu_dp: *mut i32; + #[no_mangle] + static fpu_dp_selector: *mut i32; + + #[no_mangle] + static mut profiler_stat_arr: [profiler_stat; 37]; +} +pub const S_TRIGGER_CPU_EXCEPTION: stat_name = 14; + +pub const S_CACHE_MISMATCH: stat_name = 6; +pub const S_RUN_FROM_CACHE_STEPS: stat_name = 13; +pub type stat_name = u32; + +pub const S_COMPILE_SUCCESS: stat_name = 1; +pub const S_TLB_GLOBAL_FULL: stat_name = 36; +pub const S_COMPILE: stat_name = 0; +pub const S_DO_MANY_CYCLES: stat_name = 28; +pub const S_CYCLE_INTERNAL: stat_name = 29; +pub const S_COMPILE_BASIC_BLOCK: stat_name = 4; +pub const S_SAFE_WRITE32_SLOW_PAGE_CROSSED: stat_name = 21; +pub const S_SAFE_READ32_SLOW_NOT_USER: stat_name = 18; + +#[derive(Copy, Clone)] +#[repr(C)] +pub union reg64 { + i8_0: [i8; 8], + i16_0: [i16; 4], + i32_0: [i32; 2], + i64_0: [i64; 1], + u8_0: [u8; 8], + u16_0: [u16; 4], + u32_0: [u32; 2], + u64_0: [u64; 1], + f32_0: [f32; 2], + f64_0: [f64; 1], +} +pub const S_SAFE_READ32_SLOW_IN_MAPPED_RANGE: stat_name = 19; + +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed { + __f: f64, + __i: u64, +} +pub const S_RUN_INTERPRETED_STEPS: stat_name = 11; +pub const S_RUN_FROM_CACHE: stat_name = 12; + +pub const S_TLB_FULL: stat_name = 35; +pub type cached_state_flags = u8; +pub const S_SAFE_WRITE32_SLOW_HAS_CODE: stat_name = 26; + +pub const S_DO_RUN: stat_name = 27; +pub const S_FULL_CLEAR_TLB: stat_name = 34; +pub const S_RUN_INTERPRETED_PENDING: stat_name = 8; +pub const S_NONFAULTING_OPTIMIZATION: stat_name = 32; + +pub const S_SAFE_WRITE32_FAST: stat_name = 20; +pub const S_SAFE_WRITE32_SLOW_NOT_USER: stat_name = 23; +#[derive(Copy, Clone)] +#[repr(C)] +pub union reg128 { + i8_0: [i8; 16], + i16_0: [i16; 8], + i32_0: [i32; 4], + i64_0: [i64; 2], + u8_0: [u8; 16], + u16_0: [u16; 8], + u32_0: [u32; 4], + u64_0: [u64; 2], + f32_0: [f32; 4], + f64_0: [f64; 2], +} +pub const S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE: stat_name = 24; +pub const S_SAFE_WRITE32_SLOW_NOT_VALID: stat_name = 22; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct profiler_stat { + pub count: i32, +} +pub const S_COMPILE_CUT_OFF_AT_END_OF_PAGE: stat_name = 2; +pub const S_RUN_INTERPRETED_DIFFERENT_STATE: stat_name = 10; +pub const S_COMPILE_ENTRY_POINT: stat_name = 5; +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_0 { + __f: f32, + __i: u32, +} +pub const S_CLEAR_TLB: stat_name = 33; +pub const S_RUN_INTERPRETED_NEAR_END_OF_PAGE: stat_name = 9; +pub const S_COMPILE_WITH_LOOP_SAFETY: stat_name = 3; +pub const S_INVALIDATE_CACHE_ENTRY: stat_name = 31; +pub const S_SAFE_WRITE32_SLOW_READ_ONLY: stat_name = 25; + +pub const S_SAFE_READ32_SLOW_NOT_VALID: stat_name = 17; +pub const S_RUN_INTERPRETED: stat_name = 7; +pub const S_INVALIDATE_PAGE: stat_name = 30; +pub const S_SAFE_READ32_FAST: stat_name = 15; + +pub const S_SAFE_READ32_SLOW_PAGE_CROSSED: stat_name = 16; +unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { + let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { + let mut __u: unnamed = unnamed { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x >= __y) as i32; +} +#[no_mangle] +pub static mut FLAG_CARRY: i32 = unsafe { 1i32 }; +#[no_mangle] +pub static mut FLAG_PARITY: i32 = unsafe { 4i32 }; +#[no_mangle] +pub static mut FLAG_ADJUST: i32 = unsafe { 16i32 }; +#[no_mangle] +pub static mut FLAG_ZERO: i32 = unsafe { 64i32 }; +#[no_mangle] +pub static mut FLAG_SIGN: i32 = unsafe { 128i32 }; +#[no_mangle] +pub static mut FLAG_TRAP: i32 = unsafe { 256i32 }; +#[no_mangle] +pub static mut FLAG_INTERRUPT: i32 = unsafe { 512i32 }; +#[no_mangle] +pub static mut FLAG_DIRECTION: i32 = unsafe { 1024i32 }; +#[no_mangle] +pub static mut FLAG_OVERFLOW: i32 = unsafe { 2048i32 }; +#[no_mangle] +pub static mut FLAG_IOPL: i32 = unsafe { 1i32 << 12i32 | 1i32 << 13i32 }; +#[no_mangle] +pub static mut FLAG_NT: i32 = unsafe { 1i32 << 14i32 }; +#[no_mangle] +pub static mut FLAG_RF: i32 = unsafe { 1i32 << 16i32 }; +#[no_mangle] +pub static mut FLAG_VM: i32 = unsafe { 1i32 << 17i32 }; +#[no_mangle] +pub static mut FLAG_AC: i32 = unsafe { 1i32 << 18i32 }; +#[no_mangle] +pub static mut FLAG_VIF: i32 = unsafe { 1i32 << 19i32 }; +#[no_mangle] +pub static mut FLAG_VIP: i32 = unsafe { 1i32 << 20i32 }; +#[no_mangle] +pub static mut FLAG_ID: i32 = unsafe { 1i32 << 21i32 }; +#[no_mangle] +pub static mut FLAGS_DEFAULT: i32 = unsafe { 1i32 << 1i32 }; +#[no_mangle] +pub static mut FLAGS_MASK: i32 = unsafe { + FLAG_CARRY + | FLAG_PARITY + | FLAG_ADJUST + | FLAG_ZERO + | FLAG_SIGN + | FLAG_TRAP + | FLAG_INTERRUPT + | FLAG_DIRECTION + | FLAG_OVERFLOW + | FLAG_IOPL + | FLAG_NT + | FLAG_RF + | FLAG_VM + | FLAG_AC + | FLAG_VIF + | FLAG_VIP + | FLAG_ID +}; +#[no_mangle] +pub static mut FLAGS_ALL: i32 = + unsafe { FLAG_CARRY | FLAG_PARITY | FLAG_ADJUST | FLAG_ZERO | FLAG_SIGN | FLAG_OVERFLOW }; +#[no_mangle] +pub static mut OPSIZE_8: i32 = unsafe { 7i32 }; +#[no_mangle] +pub static mut OPSIZE_16: i32 = unsafe { 15i32 }; +#[no_mangle] +pub static mut OPSIZE_32: i32 = unsafe { 31i32 }; +#[no_mangle] +pub static mut EAX: i32 = unsafe { 0i32 }; +#[no_mangle] +pub static mut ECX: i32 = unsafe { 1i32 }; +#[no_mangle] +pub static mut EDX: i32 = unsafe { 2i32 }; +#[no_mangle] +pub static mut EBX: i32 = unsafe { 3i32 }; +#[no_mangle] +pub static mut ESP: i32 = unsafe { 4i32 }; +#[no_mangle] +pub static mut EBP: i32 = unsafe { 5i32 }; +#[no_mangle] +pub static mut ESI: i32 = unsafe { 6i32 }; +#[no_mangle] +pub static mut EDI: i32 = unsafe { 7i32 }; +#[no_mangle] +pub static mut AX: i32 = unsafe { 0i32 }; +#[no_mangle] +pub static mut CX: i32 = unsafe { 2i32 }; +#[no_mangle] +pub static mut DX: i32 = unsafe { 4i32 }; +#[no_mangle] +pub static mut BX: i32 = unsafe { 6i32 }; +#[no_mangle] +pub static mut SP: i32 = unsafe { 8i32 }; +#[no_mangle] +pub static mut BP: i32 = unsafe { 10i32 }; +#[no_mangle] +pub static mut SI: i32 = unsafe { 12i32 }; +#[no_mangle] +pub static mut DI: i32 = unsafe { 14i32 }; +#[no_mangle] +pub static mut AL: i32 = unsafe { 0i32 }; +#[no_mangle] +pub static mut CL: i32 = unsafe { 4i32 }; +#[no_mangle] +pub static mut DL: i32 = unsafe { 8i32 }; +#[no_mangle] +pub static mut BL: i32 = unsafe { 12i32 }; +#[no_mangle] +pub static mut AH: i32 = unsafe { 1i32 }; +#[no_mangle] +pub static mut CH: i32 = unsafe { 5i32 }; +#[no_mangle] +pub static mut DH: i32 = unsafe { 9i32 }; +#[no_mangle] +pub static mut BH: i32 = unsafe { 13i32 }; +#[no_mangle] +pub static mut ES: i32 = unsafe { 0i32 }; +#[no_mangle] +pub static mut CS: i32 = unsafe { 1i32 }; +#[no_mangle] +pub static mut SS: i32 = unsafe { 2i32 }; +#[no_mangle] +pub static mut DS: i32 = unsafe { 3i32 }; +#[no_mangle] +pub static mut FS: i32 = unsafe { 4i32 }; +#[no_mangle] +pub static mut GS: i32 = unsafe { 5i32 }; +#[no_mangle] +pub static mut TR: i32 = unsafe { 6i32 }; +#[no_mangle] +pub static mut LDTR: i32 = unsafe { 7i32 }; +#[no_mangle] +pub static mut PAGE_TABLE_PRESENT_MASK: i32 = unsafe { 1i32 << 0i32 }; +#[no_mangle] +pub static mut PAGE_TABLE_RW_MASK: i32 = unsafe { 1i32 << 1i32 }; +#[no_mangle] +pub static mut PAGE_TABLE_USER_MASK: i32 = unsafe { 1i32 << 2i32 }; +#[no_mangle] +pub static mut PAGE_TABLE_ACCESSED_MASK: i32 = unsafe { 1i32 << 5i32 }; +#[no_mangle] +pub static mut PAGE_TABLE_DIRTY_MASK: i32 = unsafe { 1i32 << 6i32 }; +#[no_mangle] +pub static mut PAGE_TABLE_PSE_MASK: i32 = unsafe { 1i32 << 7i32 }; +#[no_mangle] +pub static mut PAGE_TABLE_GLOBAL_MASK: i32 = unsafe { 1i32 << 8i32 }; +#[no_mangle] +pub static mut MMAP_BLOCK_BITS: i32 = unsafe { 17i32 }; +#[no_mangle] +pub static mut MMAP_BLOCK_SIZE: i32 = unsafe { 1i32 << MMAP_BLOCK_BITS }; +#[no_mangle] +pub static mut CR0_PE: i32 = unsafe { 1i32 }; +#[no_mangle] +pub static mut CR0_MP: i32 = unsafe { 1i32 << 1i32 }; +#[no_mangle] +pub static mut CR0_EM: i32 = unsafe { 1i32 << 2i32 }; +#[no_mangle] +pub static mut CR0_TS: i32 = unsafe { 1i32 << 3i32 }; +#[no_mangle] +pub static mut CR0_ET: i32 = unsafe { 1i32 << 4i32 }; +#[no_mangle] +pub static mut CR0_WP: i32 = unsafe { 1i32 << 16i32 }; +#[no_mangle] +pub static mut CR0_NW: i32 = unsafe { 1i32 << 29i32 }; +#[no_mangle] +pub static mut CR0_CD: i32 = unsafe { 1i32 << 30i32 }; +#[no_mangle] +pub static mut CR0_PG: i32 = unsafe { 1i32 << 31i32 }; +#[no_mangle] +pub static mut CR4_VME: i32 = unsafe { 1i32 }; +#[no_mangle] +pub static mut CR4_PVI: i32 = unsafe { 1i32 << 1i32 }; +#[no_mangle] +pub static mut CR4_TSD: i32 = unsafe { 1i32 << 2i32 }; +#[no_mangle] +pub static mut CR4_PSE: i32 = unsafe { 1i32 << 4i32 }; +#[no_mangle] +pub static mut CR4_DE: i32 = unsafe { 1i32 << 3i32 }; +#[no_mangle] +pub static mut CR4_PAE: i32 = unsafe { 1i32 << 5i32 }; +#[no_mangle] +pub static mut CR4_PGE: i32 = unsafe { 1i32 << 7i32 }; +#[no_mangle] +pub static mut IA32_SYSENTER_CS: i32 = unsafe { 372i32 }; +#[no_mangle] +pub static mut IA32_SYSENTER_ESP: i32 = unsafe { 373i32 }; +#[no_mangle] +pub static mut IA32_SYSENTER_EIP: i32 = unsafe { 374i32 }; +#[no_mangle] +pub static mut IA32_TIME_STAMP_COUNTER: i32 = unsafe { 16i32 }; +#[no_mangle] +pub static mut IA32_PLATFORM_ID: i32 = unsafe { 23i32 }; +#[no_mangle] +pub static mut IA32_APIC_BASE_MSR: i32 = unsafe { 27i32 }; +#[no_mangle] +pub static mut IA32_BIOS_SIGN_ID: i32 = unsafe { 139i32 }; +#[no_mangle] +pub static mut MSR_PLATFORM_INFO: i32 = unsafe { 206i32 }; +#[no_mangle] +pub static mut MSR_MISC_FEATURE_ENABLES: i32 = unsafe { 320i32 }; +#[no_mangle] +pub static mut IA32_MISC_ENABLE: i32 = unsafe { 416i32 }; +#[no_mangle] +pub static mut IA32_RTIT_CTL: i32 = unsafe { 1392i32 }; +#[no_mangle] +pub static mut MSR_SMI_COUNT: i32 = unsafe { 52i32 }; +#[no_mangle] +pub static mut IA32_MCG_CAP: i32 = unsafe { 377i32 }; +#[no_mangle] +pub static mut IA32_KERNEL_GS_BASE: i32 = unsafe { 3221225729u32 as i32 }; +#[no_mangle] +pub static mut MSR_PKG_C2_RESIDENCY: i32 = unsafe { 1549i32 }; +#[no_mangle] +pub static mut IA32_APIC_BASE_BSP: i32 = unsafe { 1i32 << 8i32 }; +#[no_mangle] +pub static mut IA32_APIC_BASE_EXTD: i32 = unsafe { 1i32 << 10i32 }; +#[no_mangle] +pub static mut IA32_APIC_BASE_EN: i32 = unsafe { 1i32 << 11i32 }; +#[no_mangle] +pub static mut APIC_ADDRESS: i32 = unsafe { 4276092928u32 as i32 }; +#[no_mangle] +pub static mut SEG_PREFIX_NONE: i32 = unsafe { -1i32 }; +#[no_mangle] +pub static mut SEG_PREFIX_ZERO: i32 = unsafe { 7i32 }; +#[no_mangle] +pub static mut PREFIX_MASK_REP: i32 = unsafe { 24i32 }; +#[no_mangle] +pub static mut PREFIX_REPZ: i32 = unsafe { 8i32 }; +#[no_mangle] +pub static mut PREFIX_REPNZ: i32 = unsafe { 16i32 }; +#[no_mangle] +pub static mut PREFIX_MASK_SEGMENT: i32 = unsafe { 7i32 }; +#[no_mangle] +pub static mut PREFIX_MASK_OPSIZE: i32 = unsafe { 32i32 }; +#[no_mangle] +pub static mut PREFIX_MASK_ADDRSIZE: i32 = unsafe { 64i32 }; +#[no_mangle] +pub static mut PREFIX_F2: i32 = unsafe { PREFIX_REPNZ }; +#[no_mangle] +pub static mut PREFIX_F3: i32 = unsafe { PREFIX_REPZ }; +#[no_mangle] +pub static mut PREFIX_66: i32 = unsafe { PREFIX_MASK_OPSIZE }; +#[no_mangle] +pub static mut LOG_CPU: i32 = unsafe { 2i32 }; +#[no_mangle] +pub static mut A20_MASK: i32 = unsafe { !(1i32 << 20i32) }; +#[no_mangle] +pub static mut A20_MASK16: i32 = unsafe { !(1i32 << 20i32 - 1i32) }; +#[no_mangle] +pub static mut A20_MASK32: i32 = unsafe { !(1i32 << 20i32 - 2i32) }; +#[no_mangle] +pub static mut MXCSR_MASK: i32 = unsafe { 65535i32 & !(1i32 << 6i32) }; +#[no_mangle] +pub static mut mem8: *mut u8 = unsafe { 0 as *const u8 as *mut u8 }; +#[no_mangle] +pub static mut mem16: *mut u16 = unsafe { 0 as *const u16 as *mut u16 }; +#[no_mangle] +pub static mut mem32s: *mut i32 = unsafe { 0 as *const i32 as *mut i32 }; +#[no_mangle] +pub static mut jit_block_boundary: bool = unsafe { 0 != 0i32 }; +#[no_mangle] +pub static mut VALID_TLB_ENTRY_MAX: i32 = unsafe { 10000i32 }; +#[no_mangle] +pub static mut valid_tlb_entries: [i32; 10000] = unsafe { + [ + 0i32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ] +}; +#[no_mangle] +pub static mut valid_tlb_entries_count: i32 = unsafe { 0i32 }; +#[no_mangle] +pub static mut TLB_VALID: i32 = unsafe { 1i32 << 0i32 }; +#[no_mangle] +pub static mut TLB_READONLY: i32 = unsafe { 1i32 << 1i32 }; +#[no_mangle] +pub static mut TLB_NO_USER: i32 = unsafe { 1i32 << 2i32 }; +#[no_mangle] +pub static mut TLB_IN_MAPPED_RANGE: i32 = unsafe { 1i32 << 3i32 }; +#[no_mangle] +pub static mut TLB_GLOBAL: i32 = unsafe { 1i32 << 4i32 }; +#[no_mangle] +pub static mut TLB_HAS_CODE: i32 = unsafe { 1i32 << 5i32 }; +#[no_mangle] +pub static mut CPU_EXCEPTION_DE: i32 = unsafe { 0i32 }; +#[no_mangle] +pub static mut CPU_EXCEPTION_DB: i32 = unsafe { 1i32 }; +#[no_mangle] +pub static mut CPU_EXCEPTION_NMI: i32 = unsafe { 2i32 }; +#[no_mangle] +pub static mut CPU_EXCEPTION_BP: i32 = unsafe { 3i32 }; +#[no_mangle] +pub static mut CPU_EXCEPTION_OF: i32 = unsafe { 4i32 }; +#[no_mangle] +pub static mut CPU_EXCEPTION_BR: i32 = unsafe { 5i32 }; +#[no_mangle] +pub static mut CPU_EXCEPTION_UD: i32 = unsafe { 6i32 }; +#[no_mangle] +pub static mut CPU_EXCEPTION_NM: i32 = unsafe { 7i32 }; +#[no_mangle] +pub static mut CPU_EXCEPTION_DF: i32 = unsafe { 8i32 }; +#[no_mangle] +pub static mut CPU_EXCEPTION_TS: i32 = unsafe { 10i32 }; +#[no_mangle] +pub static mut CPU_EXCEPTION_NP: i32 = unsafe { 11i32 }; +#[no_mangle] +pub static mut CPU_EXCEPTION_SS: i32 = unsafe { 12i32 }; +#[no_mangle] +pub static mut CPU_EXCEPTION_GP: i32 = unsafe { 13i32 }; +#[no_mangle] +pub static mut CPU_EXCEPTION_PF: i32 = unsafe { 14i32 }; +#[no_mangle] +pub static mut CPU_EXCEPTION_MF: i32 = unsafe { 16i32 }; +#[no_mangle] +pub static mut CPU_EXCEPTION_AC: i32 = unsafe { 17i32 }; +#[no_mangle] +pub static mut CPU_EXCEPTION_MC: i32 = unsafe { 18i32 }; +#[no_mangle] +pub static mut CPU_EXCEPTION_XM: i32 = unsafe { 19i32 }; +#[no_mangle] +pub static mut CPU_EXCEPTION_VE: i32 = unsafe { 20i32 }; +#[no_mangle] +pub unsafe extern "C" fn after_block_boundary() -> () { jit_block_boundary = 0 != 1i32; } +#[no_mangle] +pub unsafe extern "C" fn same_page(mut addr1: i32, mut addr2: i32) -> bool { + return addr1 & !4095i32 == addr2 & !4095i32; +} +#[no_mangle] +pub unsafe extern "C" fn get_eflags() -> i32 { + return *flags & !FLAGS_ALL + | getcf() as i32 + | (getpf() as i32) << 2i32 + | (getaf() as i32) << 4i32 + | (getzf() as i32) << 6i32 + | (getsf() as i32) << 7i32 + | (getof() as i32) << 11i32; +} +#[no_mangle] +pub unsafe extern "C" fn translate_address_read(mut address: i32) -> u32 { + let mut base: i32 = (address as u32 >> 12i32) as i32; + let mut entry: i32 = *tlb_data.offset(base as isize); + let mut user: bool = *cpl.offset(0isize) as i32 == 3i32; + if entry & (TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0i32 }) == TLB_VALID { + return (entry & !4095i32 ^ address) as u32; + } + else { + return (do_page_translation(address, 0 != 0i32, user) | address & 4095i32) as u32; + }; +} +#[no_mangle] +pub unsafe extern "C" fn do_page_translation( + mut addr: i32, + mut for_writing: bool, + mut user: bool, +) -> i32 { + let mut can_write: bool = 0 != 1i32; + let mut global: bool = false; + let mut allow_user: bool = 0 != 1i32; + let mut page: i32 = (addr as u32 >> 12i32) as i32; + let mut high: i32 = 0; + if *cr.offset(0isize) & CR0_PG == 0i32 { + c_comment!(("paging disabled")); + high = (addr as u32 & 4294963200u32) as i32; + global = 0 != 0i32 + } + else { + let mut page_dir_addr: i32 = + (*cr.offset(3isize) as u32 >> 2i32).wrapping_add((page >> 10i32) as u32) as i32; + let mut page_dir_entry: i32 = read_aligned32(page_dir_addr as u32); + c_comment!(("XXX")); + let kernel_write_override: bool = !user && 0 == *cr.offset(0isize) & CR0_WP; + if 0 == page_dir_entry & PAGE_TABLE_PRESENT_MASK { + c_comment!(("to do at this place:")); + c_comment!(("")); + c_comment!(("- set cr2 = addr (which caused the page fault)")); + c_comment!((("- call_interrupt_vector with id 14, error code 0-7 (requires information if read or write)"))); + c_comment!(("- prevent execution of the function that triggered this call")); + *cr.offset(2isize) = addr; + trigger_pagefault(for_writing, user, 0 != 0i32); + c_comment!(("never reached as trigger_pagefault throws")); + dbg_assert!(0 != 0i32); + } + if page_dir_entry & PAGE_TABLE_RW_MASK == 0i32 && !kernel_write_override { + can_write = 0 != 0i32; + if for_writing { + *cr.offset(2isize) = addr; + trigger_pagefault(for_writing, user, 0 != 1i32); + dbg_assert!(0 != 0i32); + } + } + if page_dir_entry & PAGE_TABLE_USER_MASK == 0i32 { + allow_user = 0 != 0i32; + if user { + c_comment!(("Page Fault: page table accessed by non-supervisor")); + *cr.offset(2isize) = addr; + trigger_pagefault(for_writing, user, 0 != 1i32); + dbg_assert!(0 != 0i32); + } + } + if 0 != page_dir_entry & PAGE_TABLE_PSE_MASK && 0 != *cr.offset(4isize) & CR4_PSE { + c_comment!(("size bit is set")); + c_comment!(("set the accessed and dirty bits")); + write_aligned32( + page_dir_addr as u32, + page_dir_entry | PAGE_TABLE_ACCESSED_MASK | if 0 != for_writing as i32 { + PAGE_TABLE_DIRTY_MASK + } + else { + 0i32 + }, + ); + high = (page_dir_entry as u32 & 4290772992u32 | (addr & 4190208i32) as u32) as i32; + global = page_dir_entry & PAGE_TABLE_GLOBAL_MASK == PAGE_TABLE_GLOBAL_MASK + } + else { + let mut page_table_addr: i32 = ((page_dir_entry as u32 & 4294963200u32) >> 2i32) + .wrapping_add((page & 1023i32) as u32) + as i32; + let mut page_table_entry: i32 = read_aligned32(page_table_addr as u32); + if page_table_entry & PAGE_TABLE_PRESENT_MASK == 0i32 { + *cr.offset(2isize) = addr; + trigger_pagefault(for_writing, user, 0 != 0i32); + dbg_assert!(0 != 0i32); + } + if page_table_entry & PAGE_TABLE_RW_MASK == 0i32 && !kernel_write_override { + can_write = 0 != 0i32; + if for_writing { + *cr.offset(2isize) = addr; + trigger_pagefault(for_writing, user, 0 != 1i32); + dbg_assert!(0 != 0i32); + } + } + if page_table_entry & PAGE_TABLE_USER_MASK == 0i32 { + allow_user = 0 != 0i32; + if user { + *cr.offset(2isize) = addr; + trigger_pagefault(for_writing, user, 0 != 1i32); + dbg_assert!(0 != 0i32); + } + } + c_comment!(("set the accessed and dirty bits")); + write_aligned32( + page_dir_addr as u32, + page_dir_entry | PAGE_TABLE_ACCESSED_MASK, + ); + write_aligned32( + page_table_addr as u32, + page_table_entry | PAGE_TABLE_ACCESSED_MASK | if 0 != for_writing as i32 { + PAGE_TABLE_DIRTY_MASK + } + else { + 0i32 + }, + ); + high = (page_table_entry as u32 & 4294963200u32) as i32; + global = page_table_entry & PAGE_TABLE_GLOBAL_MASK == PAGE_TABLE_GLOBAL_MASK + } + } + if *tlb_data.offset(page as isize) == 0i32 { + if valid_tlb_entries_count == VALID_TLB_ENTRY_MAX { + profiler_stat_increment(S_TLB_FULL); + clear_tlb(); + c_comment!( + ("also clear global entries if tlb is almost full after clearing non-global pages") + ); + if valid_tlb_entries_count > VALID_TLB_ENTRY_MAX * 3i32 / 4i32 { + profiler_stat_increment(S_TLB_GLOBAL_FULL); + full_clear_tlb(); + } + } + dbg_assert!(valid_tlb_entries_count < VALID_TLB_ENTRY_MAX); + let fresh0 = valid_tlb_entries_count; + valid_tlb_entries_count = valid_tlb_entries_count + 1; + valid_tlb_entries[fresh0 as usize] = page; + c_comment!(("TODO: Check that there are no duplicates in valid_tlb_entries")); + c_comment!(("XXX: There will probably be duplicates due to invlpg deleting")); + c_comment!(("entries from tlb_data but not from valid_tlb_entries")); + } + else if CHECK_TLB_INVARIANTS { + let mut found: bool = 0 != 0i32; + let mut i: i32 = 0i32; + while i < valid_tlb_entries_count { + if valid_tlb_entries[i as usize] == page { + found = 0 != 1i32; + break; + } + else { + i += 1 + } + } + dbg_assert!(found); + } + let mut is_in_mapped_range: bool = in_mapped_range(high as u32); + let mut physical_page: i32 = (high as u32 >> 12i32) as i32; + let mut has_code: bool = + !is_in_mapped_range && 0 != jit_page_has_code(physical_page as u32) as i32; + let mut info_bits: i32 = TLB_VALID + | if 0 != can_write as i32 { + 0i32 + } + else { + TLB_READONLY + } + | if 0 != allow_user as i32 { + 0i32 + } + else { + TLB_NO_USER + } + | if 0 != is_in_mapped_range as i32 { + TLB_IN_MAPPED_RANGE + } + else { + 0i32 + } + | if 0 != global as i32 && 0 != *cr.offset(4isize) & CR4_PGE { + TLB_GLOBAL + } + else { + 0i32 + } + | if 0 != has_code as i32 { + TLB_HAS_CODE + } + else { + 0i32 + }; + dbg_assert!((high ^ page << 12i32) & 4095i32 == 0i32); + *tlb_data.offset(page as isize) = high ^ page << 12i32 | info_bits; + return high; +} +#[no_mangle] +pub static mut CHECK_TLB_INVARIANTS: bool = unsafe { 0 != 0i32 }; +#[no_mangle] +pub unsafe extern "C" fn full_clear_tlb() -> () { + profiler_stat_increment(S_FULL_CLEAR_TLB); + c_comment!(("clear tlb including global pages")); + *last_virt_eip = -1i32; + *last_virt_esp = -1i32; + let mut i: i32 = 0i32; + while i < valid_tlb_entries_count { + let mut page: i32 = valid_tlb_entries[i as usize]; + *tlb_data.offset(page as isize) = 0i32; + i += 1 + } + valid_tlb_entries_count = 0i32; + if CHECK_TLB_INVARIANTS { + let mut i_0: i32 = 0i32; + while i_0 < 1048576i32 { + dbg_assert!(*tlb_data.offset(i_0 as isize) == 0i32); + i_0 += 1 + } + }; +} +#[no_mangle] +pub unsafe extern "C" fn clear_tlb() -> () { + profiler_stat_increment(S_CLEAR_TLB); + c_comment!(("clear tlb excluding global pages")); + *last_virt_eip = -1i32; + *last_virt_esp = -1i32; + let mut global_page_offset: i32 = 0i32; + let mut i: i32 = 0i32; + while i < valid_tlb_entries_count { + let mut page: i32 = valid_tlb_entries[i as usize]; + let mut entry: i32 = *tlb_data.offset(page as isize); + if 0 != entry & TLB_GLOBAL { + c_comment!(("reinsert at the front")); + let fresh1 = global_page_offset; + global_page_offset = global_page_offset + 1; + valid_tlb_entries[fresh1 as usize] = page + } + else { + *tlb_data.offset(page as isize) = 0i32 + } + i += 1 + } + valid_tlb_entries_count = global_page_offset; + if CHECK_TLB_INVARIANTS { + let mut i_0: i32 = 0i32; + while i_0 < 1048576i32 { + dbg_assert!( + *tlb_data.offset(i_0 as isize) == 0i32 + || 0 != *tlb_data.offset(i_0 as isize) & TLB_GLOBAL + ); + i_0 += 1 + } + }; +} +#[no_mangle] +pub unsafe extern "C" fn trigger_pagefault( + mut write: bool, + mut user: bool, + mut present: bool, +) -> () { + if 0 != 0i32 * 0i32 { + dbg_log_c!( + ("page fault w=%d u=%d p=%d eip=%x cr2=%x"), + write as i32, + user as i32, + present as i32, + *previous_ip, + *cr.offset(2isize) + ); + dbg_trace(); + } + if DEBUG { + if must_not_fault { + dbg_log_c!(("Unexpected page fault")); + dbg_trace(); + dbg_assert!(0 != 0i32); + } + } + if *page_fault { + dbg_log_c!(("double fault")); + dbg_trace(); + dbg_assert!(0 != 0i32); + } + c_comment!(("invalidate tlb entry")); + let mut page: i32 = (*cr.offset(2isize) as u32 >> 12i32) as i32; + *tlb_data.offset(page as isize) = 0i32; + *instruction_pointer = *previous_ip; + *page_fault = 0 != 1i32; + call_interrupt_vector( + CPU_EXCEPTION_PF, + 0 != 0i32, + 0 != 1i32, + (user as i32) << 2i32 | (write as i32) << 1i32 | present as i32, + ); + profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); + throw_cpu_exception(); +} +#[no_mangle] +pub static mut must_not_fault: bool = unsafe { 0 != 0i32 }; +#[no_mangle] +pub static mut DEBUG: bool = unsafe { 0 != 1i32 }; +#[no_mangle] +pub unsafe extern "C" fn translate_address_write(mut address: i32) -> u32 { + let mut base: i32 = (address as u32 >> 12i32) as i32; + let mut entry: i32 = *tlb_data.offset(base as isize); + let mut user: bool = *cpl.offset(0isize) as i32 == 3i32; + if entry & (TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0i32 } | TLB_READONLY) + == TLB_VALID + { + return (entry & !4095i32 ^ address) as u32; + } + else { + return (do_page_translation(address, 0 != 1i32, user) | address & 4095i32) as u32; + }; +} +#[no_mangle] +pub unsafe extern "C" fn tlb_set_has_code(mut physical_page: u32, mut has_code: bool) -> () { + dbg_assert!(physical_page < (1i32 << 20i32) as u32); + let mut i: i32 = 0i32; + while i < valid_tlb_entries_count { + let mut page: i32 = valid_tlb_entries[i as usize]; + let mut entry: i32 = *tlb_data.offset(page as isize); + if 0 != entry { + let mut tlb_physical_page: u32 = entry as u32 >> 12i32 ^ page as u32; + if physical_page == tlb_physical_page { + *tlb_data.offset(page as isize) = if 0 != has_code as i32 { + entry | TLB_HAS_CODE + } + else { + entry & !TLB_HAS_CODE + } + } + } + i += 1 + } + check_tlb_invariants(); +} +#[no_mangle] +pub unsafe extern "C" fn check_tlb_invariants() -> () { + let mut physical_page: u32 = 0; + let mut entry_has_code: bool = false; + let mut has_code: bool = false; + if !CHECK_TLB_INVARIANTS { + return; + } + else { + let mut i: i32 = 0i32; + while i < valid_tlb_entries_count { + let mut page: i32 = valid_tlb_entries[i as usize]; + let mut entry: i32 = *tlb_data.offset(page as isize); + if 0 == entry || 0 != entry & TLB_IN_MAPPED_RANGE { + c_comment!(("there\'s no code in mapped memory")); + } + i += 1 + } + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn writable_or_pagefault(mut addr: i32, mut size: i32) -> () { + dbg_assert!(size < 4096i32); + dbg_assert!(size > 0i32); + if *cr.offset(0isize) & CR0_PG == 0i32 { + return; + } + else { + let mut user: bool = *cpl.offset(0isize) as i32 == 3i32; + let mut mask: i32 = + TLB_READONLY | TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0i32 }; + let mut expect: i32 = TLB_VALID; + let mut page: i32 = (addr as u32 >> 12i32) as i32; + if *tlb_data.offset(page as isize) & mask != expect { + do_page_translation(addr, 0 != 1i32, user); + } + let mut next_page: i32 = ((addr + size - 1i32) as u32 >> 12i32) as i32; + if page != next_page { + dbg_assert!(next_page == page + 1i32); + c_comment!(("XXX: possibly out of bounds")); + if *tlb_data.offset(next_page as isize) & mask != expect { + do_page_translation(next_page << 12i32, 0 != 1i32, user); + } + } + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn read_imm8() -> i32 { + let mut eip: i32 = *instruction_pointer; + if 0 != eip & !4095i32 ^ *last_virt_eip { + *eip_phys = (translate_address_read(eip) ^ eip as u32) as i32; + *last_virt_eip = eip & !4095i32 + } + dbg_assert!(!in_mapped_range((*eip_phys ^ eip) as u32)); + let mut data8: i32 = *mem8.offset((*eip_phys ^ eip) as isize) as i32; + *instruction_pointer = eip + 1i32; + return data8; +} +#[no_mangle] +pub unsafe extern "C" fn read_imm8s() -> i32 { return read_imm8() << 24i32 >> 24i32; } +#[no_mangle] +pub unsafe extern "C" fn read_imm16() -> i32 { + c_comment!(("Two checks in one comparison:")); + c_comment!(("1. Did the high 20 bits of eip change")); + c_comment!(("or 2. Are the low 12 bits of eip 0xFFF (and this read crosses a page boundary)")); + if (*instruction_pointer ^ *last_virt_eip) as u32 > 4094i32 as u32 { + return read_imm8() | read_imm8() << 8i32; + } + else { + let mut data16: i32 = read16((*eip_phys ^ *instruction_pointer) as u32); + *instruction_pointer = *instruction_pointer + 2i32; + return data16; + }; +} +#[no_mangle] +pub unsafe extern "C" fn read_imm32s() -> i32 { + c_comment!(("Analogue to the above comment")); + if (*instruction_pointer ^ *last_virt_eip) as u32 > 4092i32 as u32 { + return read_imm16() | read_imm16() << 16i32; + } + else { + let mut data32: i32 = read32s((*eip_phys ^ *instruction_pointer) as u32); + *instruction_pointer = *instruction_pointer + 4i32; + return data32; + }; +} +#[no_mangle] +pub unsafe extern "C" fn is_osize_32() -> bool { + return *is_32 as i32 != (*prefixes as i32 & PREFIX_MASK_OPSIZE == PREFIX_MASK_OPSIZE) as i32; +} +#[no_mangle] +pub unsafe extern "C" fn is_asize_32() -> bool { + return *is_32 as i32 + != (*prefixes as i32 & PREFIX_MASK_ADDRSIZE == PREFIX_MASK_ADDRSIZE) as i32; +} +#[no_mangle] +pub unsafe extern "C" fn get_seg(mut segment: i32) -> i32 { + dbg_assert!(segment >= 0i32 && segment < 8i32); + c_comment!(("TODO: Remove protected_mode check")); + if *protected_mode { + if *segment_is_null.offset(segment as isize) { + dbg_assert!(segment != CS && segment != SS); + dbg_log_c!(("#gp: Access null segment")); + trigger_gp(0i32); + } + } + return *segment_offsets.offset(segment as isize); +} +#[no_mangle] +pub unsafe extern "C" fn trigger_gp(mut code: i32) -> () { + *instruction_pointer = *previous_ip; + raise_exception_with_code(CPU_EXCEPTION_GP, code); +} +#[no_mangle] +pub unsafe extern "C" fn raise_exception_with_code( + mut interrupt_nr: i32, + mut error_code: i32, +) -> () { + if DEBUG { + if must_not_fault { + dbg_log_c!( + ("Unexpected fault: 0x%x with code 0x%x"), + interrupt_nr, + error_code + ); + dbg_trace(); + dbg_assert!(0 != 0i32); + } + if cpu_exception_hook(interrupt_nr) { + throw_cpu_exception(); + return; + } + } + profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); + call_interrupt_vector(interrupt_nr, 0 != 0i32, 0 != 1i32, error_code); + throw_cpu_exception(); +} +#[no_mangle] +pub unsafe extern "C" fn get_seg_cs() -> i32 { return *segment_offsets.offset(CS as isize); } +#[no_mangle] +pub unsafe extern "C" fn get_seg_ss() -> i32 { return *segment_offsets.offset(SS as isize); } +#[no_mangle] +pub unsafe extern "C" fn get_seg_prefix(mut default_segment: i32) -> i32 { + let mut prefix: i32 = *prefixes as i32 & PREFIX_MASK_SEGMENT; + if 0 != prefix { + if prefix == SEG_PREFIX_ZERO { + return 0i32; + } + else { + return get_seg(prefix - 1i32); + } + } + else { + return get_seg(default_segment); + }; +} +#[no_mangle] +pub unsafe extern "C" fn get_seg_prefix_ds(mut offset: i32) -> i32 { + return get_seg_prefix(DS) + offset; +} +#[no_mangle] +pub unsafe extern "C" fn get_seg_prefix_ss(mut offset: i32) -> i32 { + return get_seg_prefix(SS) + offset; +} +#[no_mangle] +pub unsafe extern "C" fn get_seg_prefix_cs(mut offset: i32) -> i32 { + return get_seg_prefix(CS) + offset; +} +#[no_mangle] +pub unsafe extern "C" fn modrm_resolve(mut modrm_byte: i32) -> i32 { + if is_asize_32() { + return resolve_modrm32(modrm_byte); + } + else { + return resolve_modrm16(modrm_byte); + }; +} +#[no_mangle] +pub unsafe extern "C" fn cycle_internal() -> () { + let mut wasm_table_index: u16 = 0; + let mut initial_tsc: i32 = 0; + let mut initial_state: u16 = 0; + profiler_stat_increment(S_CYCLE_INTERNAL); + *previous_ip = *instruction_pointer; + let mut phys_addr: u32 = get_phys_eip() as u32; + let mut state_flags: cached_state_flags = pack_current_state_flags(); + let mut entry: u32 = jit_find_cache_entry(phys_addr, state_flags); + if 0 != entry { + profiler_stat_increment(S_RUN_FROM_CACHE); + initial_tsc = *timestamp_counter as i32; + wasm_table_index = (entry & 65535i32 as u32) as u16; + initial_state = (entry >> 16i32) as u16; + call_indirect1( + (wasm_table_index as u32).wrapping_add(256i32 as u32) as i32, + initial_state as i32, + ); + clear_current_cpu_exception(); + profiler_stat_increment_by( + S_RUN_FROM_CACHE_STEPS, + (*timestamp_counter).wrapping_sub(initial_tsc as u32) as i32, + ); + } + else { + if DEBUG { + dbg_assert!(!must_not_fault); + must_not_fault = 0 != 1i32 + } + jit_increase_hotness_and_maybe_compile(phys_addr, get_seg_cs() as u32, state_flags); + if DEBUG { + dbg_assert!(must_not_fault); + must_not_fault = 0 != 0i32 + } + let mut initial_tsc_0: i32 = *timestamp_counter as i32; + jit_run_interpreted(phys_addr as i32); + profiler_stat_increment_by( + S_RUN_INTERPRETED_STEPS, + (*timestamp_counter).wrapping_sub(initial_tsc_0 as u32) as i32, + ); + }; +} +#[no_mangle] +pub unsafe extern "C" fn get_phys_eip() -> i32 { + let mut eip: i32 = *instruction_pointer; + if 0 != eip & !4095i32 ^ *last_virt_eip { + *eip_phys = (translate_address_read(eip) ^ eip as u32) as i32; + *last_virt_eip = eip & !4095i32 + } + let mut phys_addr: u32 = (*eip_phys ^ eip) as u32; + dbg_assert!(!in_mapped_range(phys_addr)); + return phys_addr as i32; +} +unsafe extern "C" fn jit_run_interpreted(mut phys_addr: i32) -> () { + profiler_stat_increment(S_RUN_INTERPRETED); + jit_block_boundary = 0 != 0i32; + dbg_assert!(!in_mapped_range(phys_addr as u32)); + let mut opcode: i32 = *mem8.offset(phys_addr as isize) as i32; + *instruction_pointer += 1; + *timestamp_counter = (*timestamp_counter).wrapping_add(1); + run_instruction(opcode | (*is_32 as i32) << 8i32); + clear_current_cpu_exception(); + while !jit_block_boundary && 0 != same_page(*previous_ip, *instruction_pointer) as i32 { + *previous_ip.offset(0isize) = *instruction_pointer.offset(0isize); + *timestamp_counter = (*timestamp_counter).wrapping_add(1); + let mut opcode_0: i32 = read_imm8(); + if DEBUG { + logop(*previous_ip.offset(0isize), opcode_0); + } + run_instruction(opcode_0 | (*is_32 as i32) << 8i32); + clear_current_cpu_exception(); + } +} +#[no_mangle] +pub unsafe extern "C" fn clear_current_cpu_exception() -> () { current_cpu_exception = -1i32; } +#[no_mangle] +pub static mut current_cpu_exception: i32 = unsafe { -1i32 }; +#[no_mangle] +pub unsafe extern "C" fn pack_current_state_flags() -> cached_state_flags { + return ((*is_32 as i32) << 0i32 + | (*stack_size_32 as i32) << 1i32 + | ((*cpl as i32 == 3i32) as i32) << 2i32 + | (has_flat_segmentation() as i32) << 3i32) as cached_state_flags; +} +#[no_mangle] +pub unsafe extern "C" fn has_flat_segmentation() -> bool { + c_comment!(("ss can\'t be null")); + return *segment_offsets.offset(SS as isize) == 0i32 + && !*segment_is_null.offset(DS as isize) + && *segment_offsets.offset(DS as isize) == 0i32; +} +#[no_mangle] +pub unsafe extern "C" fn run_prefix_instruction() -> () { + run_instruction(read_imm8() | (is_osize_32() as i32) << 8i32); +} +#[no_mangle] +pub unsafe extern "C" fn clear_prefixes() -> () { *prefixes = 0i32 as u8; } +#[no_mangle] +pub unsafe extern "C" fn segment_prefix_op(mut seg: i32) -> () { + dbg_assert!(seg <= 5i32); + *prefixes = (*prefixes as i32 | seg + 1i32) as u8; + run_prefix_instruction(); + *prefixes = 0i32 as u8; +} +#[no_mangle] +pub unsafe extern "C" fn do_many_cycles_unsafe() -> () { + profiler_stat_increment(S_DO_MANY_CYCLES); + let mut initial_timestamp_counter: u32 = *timestamp_counter; + while (*timestamp_counter).wrapping_sub(initial_timestamp_counter) < LOOP_COUNTER as u32 + && !*in_hlt.offset(0isize) + { + cycle_internal(); + } +} +#[no_mangle] +pub static mut LOOP_COUNTER: i32 = unsafe { 20011i32 }; +#[no_mangle] +pub unsafe extern "C" fn raise_exception(mut interrupt_nr: i32) -> () { + if DEBUG { + if must_not_fault { + dbg_log_c!(("Unexpected fault: 0x%x"), interrupt_nr); + dbg_trace(); + dbg_assert!(0 != 0i32); + } + if cpu_exception_hook(interrupt_nr) { + throw_cpu_exception(); + return; + } + } + profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); + call_interrupt_vector(interrupt_nr, 0 != 0i32, 0 != 0i32, 0i32); + throw_cpu_exception(); +} +#[no_mangle] +pub unsafe extern "C" fn trigger_de() -> () { + if DEBUG { + if cpu_exception_hook(CPU_EXCEPTION_DE) { + return; + } + } + *instruction_pointer = *previous_ip; + call_interrupt_vector(CPU_EXCEPTION_DE, 0 != 0i32, 0 != 0i32, 0i32); + set_current_cpu_exception(CPU_EXCEPTION_DE); +} +#[no_mangle] +pub unsafe extern "C" fn set_current_cpu_exception(mut n: i32) -> () { current_cpu_exception = n; } +#[no_mangle] +pub unsafe extern "C" fn trigger_ud() -> () { + dbg_log_c!(("#ud")); + dbg_trace(); + if DEBUG { + if cpu_exception_hook(CPU_EXCEPTION_UD) { + return; + } + } + *instruction_pointer = *previous_ip; + call_interrupt_vector(CPU_EXCEPTION_UD, 0 != 0i32, 0 != 0i32, 0i32); + set_current_cpu_exception(CPU_EXCEPTION_UD); +} +#[no_mangle] +pub unsafe extern "C" fn trigger_nm() -> () { + if DEBUG { + if cpu_exception_hook(CPU_EXCEPTION_NM) { + return; + } + } + *instruction_pointer = *previous_ip; + call_interrupt_vector(CPU_EXCEPTION_NM, 0 != 0i32, 0 != 0i32, 0i32); + set_current_cpu_exception(CPU_EXCEPTION_NM); +} +#[no_mangle] +pub unsafe extern "C" fn trigger_gp_non_raising(mut code: i32) -> () { + if DEBUG { + if cpu_exception_hook(CPU_EXCEPTION_GP) { + return; + } + } + *instruction_pointer = *previous_ip; + call_interrupt_vector(CPU_EXCEPTION_GP, 0 != 0i32, 0 != 1i32, code); + set_current_cpu_exception(CPU_EXCEPTION_GP); +} +#[no_mangle] +pub unsafe extern "C" fn virt_boundary_read16(mut low: i32, mut high: i32) -> i32 { + dbg_assert!(low & 4095i32 == 4095i32); + dbg_assert!(high & 4095i32 == 0i32); + return read8(low as u32) | read8(high as u32) << 8i32; +} +#[no_mangle] +pub unsafe extern "C" fn virt_boundary_read32s(mut low: i32, mut high: i32) -> i32 { + dbg_assert!(low & 4095i32 >= 4093i32); + dbg_assert!(high - 3i32 & 4095i32 == low & 4095i32); + let mut mid: i32 = 0i32; + if 0 != low & 1i32 { + if 0 != low & 2i32 { + c_comment!(("0xFFF")); + mid = read_aligned16((high - 2i32 >> 1i32) as u32) + } + else { + c_comment!(("0xFFD")); + mid = read_aligned16((low + 1i32 >> 1i32) as u32) + } + } + else { + c_comment!(("0xFFE")); + mid = virt_boundary_read16(low + 1i32, high - 1i32) + } + return read8(low as u32) | mid << 8i32 | read8(high as u32) << 24i32; +} +#[no_mangle] +pub unsafe extern "C" fn virt_boundary_write16(mut low: i32, mut high: i32, mut value: i32) -> () { + dbg_assert!(low & 4095i32 == 4095i32); + dbg_assert!(high & 4095i32 == 0i32); + write8(low as u32, value); + write8(high as u32, value >> 8i32); +} +#[no_mangle] +pub unsafe extern "C" fn virt_boundary_write32(mut low: i32, mut high: i32, mut value: i32) -> () { + dbg_assert!(low & 4095i32 >= 4093i32); + dbg_assert!(high - 3i32 & 4095i32 == low & 4095i32); + write8(low as u32, value); + if 0 != low & 1i32 { + if 0 != low & 2i32 { + c_comment!(("0xFFF")); + write8((high - 2i32) as u32, value >> 8i32); + write8((high - 1i32) as u32, value >> 16i32); + } + else { + c_comment!(("0xFFD")); + write8((low + 1i32) as u32, value >> 8i32); + write8((low + 2i32) as u32, value >> 16i32); + } + } + else { + c_comment!(("0xFFE")); + write8((low + 1i32) as u32, value >> 8i32); + write8((high - 1i32) as u32, value >> 16i32); + } + write8(high as u32, value >> 24i32); +} +#[no_mangle] +pub unsafe extern "C" fn safe_read8(mut addr: i32) -> i32 { + assert_no_cpu_exception(); + return read8(translate_address_read(addr)); +} +#[no_mangle] +pub unsafe extern "C" fn assert_no_cpu_exception() -> () { + if current_cpu_exception != -1i32 { + dbg_log_c!(("Expected no cpu exception, got %d"), current_cpu_exception); + dbg_trace(); + dbg_assert!(0 != 0i32); + }; +} +#[no_mangle] +pub unsafe extern "C" fn safe_read16(mut address: i32) -> i32 { + let mut base: i32 = (address as u32 >> 12i32) as i32; + let mut entry: i32 = *tlb_data.offset(base as isize); + let mut info_bits: i32 = entry & 4095i32 & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; + if info_bits == TLB_VALID && address & 4095i32 <= 4096i32 - 2i32 { + c_comment!(("- not in memory mapped area")); + c_comment!(("- can be accessed from any cpl")); + let mut phys_address: u32 = (entry & !4095i32 ^ address) as u32; + dbg_assert!(!in_mapped_range(phys_address)); + return *(mem8.offset(phys_address as isize) as *mut u16) as i32; + } + else { + return safe_read16_slow(address); + }; +} +#[no_mangle] +pub unsafe extern "C" fn safe_read16_slow(mut addr: i32) -> i32 { + assert_no_cpu_exception(); + if addr & 4095i32 == 4095i32 { + return safe_read8(addr) | safe_read8(addr + 1i32) << 8i32; + } + else { + return read16(translate_address_read(addr)); + }; +} +#[no_mangle] +pub unsafe extern "C" fn safe_read32s(mut address: i32) -> i32 { + assert_no_cpu_exception(); + let mut base: i32 = (address as u32 >> 12i32) as i32; + let mut entry: i32 = *tlb_data.offset(base as isize); + let mut info_bits: i32 = entry & 4095i32 & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; + if info_bits == TLB_VALID && address & 4095i32 <= 4096i32 - 4i32 { + profiler_stat_increment(S_SAFE_READ32_FAST); + c_comment!(("- not in memory mapped area")); + c_comment!(("- can be accessed from any cpl")); + let mut phys_address: u32 = (entry & !4095i32 ^ address) as u32; + dbg_assert!(!in_mapped_range(phys_address)); + return *(mem8.offset(phys_address as isize) as *mut i32); + } + else { + if address & 4095i32 > 4096i32 - 4i32 { + profiler_stat_increment(S_SAFE_READ32_SLOW_PAGE_CROSSED); + } + else if info_bits & TLB_VALID == 0i32 { + profiler_stat_increment(S_SAFE_READ32_SLOW_NOT_VALID); + } + else if 0 != info_bits & TLB_NO_USER { + profiler_stat_increment(S_SAFE_READ32_SLOW_NOT_USER); + } + else if 0 != info_bits & TLB_IN_MAPPED_RANGE { + profiler_stat_increment(S_SAFE_READ32_SLOW_IN_MAPPED_RANGE); + } + else { + dbg_assert!(0 != 0i32); + } + return safe_read32s_slow(address); + }; +} +#[no_mangle] +pub unsafe extern "C" fn safe_read32s_slow(mut addr: i32) -> i32 { + if addr & 4095i32 >= 4093i32 { + return safe_read16(addr) | safe_read16(addr + 2i32) << 16i32; + } + else { + return read32s(translate_address_read(addr)); + }; +} +#[no_mangle] +pub unsafe extern "C" fn safe_read64s(mut addr: i32) -> reg64 { + let mut addr_phys: i32 = 0; + assert_no_cpu_exception(); + let mut x: reg64 = reg64 { i8_0: [0; 8] }; + if addr & 4095i32 > 4096i32 - 8i32 { + x.u32_0[0usize] = safe_read32s(addr) as u32; + x.u32_0[1usize] = safe_read32s(addr + 4i32) as u32 + } + else { + addr_phys = translate_address_read(addr) as i32; + x.u64_0[0usize] = read64s(addr_phys as u32) as u64 + } + return x; +} +#[no_mangle] +pub unsafe extern "C" fn safe_read128s(mut addr: i32) -> reg128 { + let mut addr_phys: i32 = 0; + assert_no_cpu_exception(); + let mut x: reg128 = reg128 { i8_0: [0; 16] }; + if addr & 4095i32 > 4096i32 - 16i32 { + x.u64_0[0usize] = safe_read64s(addr).u64_0[0usize]; + x.u64_0[1usize] = safe_read64s(addr + 8i32).u64_0[0usize] + } + else { + addr_phys = translate_address_read(addr) as i32; + x = read128(addr_phys as u32) + } + return x; +} +#[no_mangle] +pub unsafe extern "C" fn safe_write8(mut addr: i32, mut value: i32) -> () { + assert_no_cpu_exception(); + write8(translate_address_write(addr), value); +} +#[no_mangle] +pub unsafe extern "C" fn safe_write16(mut address: i32, mut value: i32) -> () { + let mut base: i32 = (address as u32 >> 12i32) as i32; + let mut entry: i32 = *tlb_data.offset(base as isize); + let mut info_bits: i32 = entry & 4095i32 & !TLB_GLOBAL; + if info_bits == TLB_VALID && address & 4095i32 <= 4096i32 - 2i32 { + c_comment!(("- allowed to write in user-mode")); + c_comment!(("- not in memory mapped area")); + c_comment!(("- can be accessed from any cpl")); + c_comment!(("- does not contain code")); + let mut phys_address: u32 = (entry & !4095i32 ^ address) as u32; + dbg_assert!(!jit_page_has_code(phys_address >> 12i32)); + dbg_assert!(!in_mapped_range(phys_address)); + *(mem8.offset(phys_address as isize) as *mut u16) = value as u16; + return; + } + else { + safe_write16_slow(address, value); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn safe_write16_slow(mut addr: i32, mut value: i32) -> () { + assert_no_cpu_exception(); + let mut phys_low: i32 = translate_address_write(addr) as i32; + if addr & 4095i32 == 4095i32 { + virt_boundary_write16(phys_low, translate_address_write(addr + 1i32) as i32, value); + } + else { + write16(phys_low as u32, value); + }; +} +#[no_mangle] +pub unsafe extern "C" fn safe_write32(mut address: i32, mut value: i32) -> () { + assert_no_cpu_exception(); + let mut base: i32 = (address as u32 >> 12i32) as i32; + let mut entry: i32 = *tlb_data.offset(base as isize); + let mut info_bits: i32 = entry & 4095i32 & !TLB_GLOBAL & !if *cpl as i32 == 3i32 { + 0i32 + } + else { + TLB_NO_USER + }; + if info_bits == TLB_VALID && address & 4095i32 <= 4096i32 - 4i32 { + profiler_stat_increment(S_SAFE_WRITE32_FAST); + c_comment!(("- allowed to write in user-mode")); + c_comment!(("- not in memory mapped area")); + c_comment!(("- does not contain code")); + let mut phys_address: u32 = (entry & !4095i32 ^ address) as u32; + dbg_assert!(!jit_page_has_code(phys_address >> 12i32)); + dbg_assert!(!in_mapped_range(phys_address)); + *(mem8.offset(phys_address as isize) as *mut i32) = value; + return; + } + else { + if address & 4095i32 > 4096i32 - 4i32 { + profiler_stat_increment(S_SAFE_WRITE32_SLOW_PAGE_CROSSED); + } + else if info_bits & TLB_VALID == 0i32 { + profiler_stat_increment(S_SAFE_WRITE32_SLOW_NOT_VALID); + } + else if 0 != info_bits & TLB_NO_USER { + profiler_stat_increment(S_SAFE_WRITE32_SLOW_NOT_USER); + } + else if 0 != info_bits & TLB_IN_MAPPED_RANGE { + profiler_stat_increment(S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE); + } + else if 0 != info_bits & TLB_READONLY { + profiler_stat_increment(S_SAFE_WRITE32_SLOW_READ_ONLY); + } + else if 0 != info_bits & TLB_HAS_CODE { + profiler_stat_increment(S_SAFE_WRITE32_SLOW_HAS_CODE); + } + else { + dbg_assert!(0 != 0i32); + } + safe_write32_slow(address, value); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn safe_write32_slow(mut addr: i32, mut value: i32) -> () { + let mut phys_low: i32 = translate_address_write(addr) as i32; + if addr & 4095i32 > 4096i32 - 4i32 { + virt_boundary_write32( + phys_low, + (translate_address_write(addr + 3i32 & !3i32) | (addr + 3i32 & 3i32) as u32) as i32, + value, + ); + } + else { + write32(phys_low as u32, value); + }; +} +#[no_mangle] +pub unsafe extern "C" fn safe_write64(mut addr: i32, mut value: i64) -> () { + assert_no_cpu_exception(); + if addr & 4095i32 > 4096i32 - 8i32 { + writable_or_pagefault(addr, 8i32); + safe_write32(addr, value as i32); + safe_write32(addr + 4i32, (value >> 32i32) as i32); + } + else { + let mut phys: i32 = translate_address_write(addr) as i32; + write64(phys as u32, value); + }; +} +#[no_mangle] +pub unsafe extern "C" fn safe_write128(mut addr: i32, mut value: reg128) -> () { + assert_no_cpu_exception(); + if addr & 4095i32 > 4096i32 - 16i32 { + writable_or_pagefault(addr, 16i32); + safe_write64(addr, value.u64_0[0usize] as i64); + safe_write64(addr + 8i32, value.u64_0[1usize] as i64); + } + else { + let mut phys: i32 = translate_address_write(addr) as i32; + write128(phys as u32, value); + }; +} +#[no_mangle] +pub unsafe extern "C" fn get_reg8_index(mut index: i32) -> i32 { + return index << 2i32 & 12i32 | index >> 2i32 & 1i32; +} +#[no_mangle] +pub unsafe extern "C" fn read_reg8(mut index: i32) -> i32 { + return *reg8.offset(get_reg8_index(index) as isize) as i32; +} +#[no_mangle] +pub unsafe extern "C" fn write_reg8(mut index: i32, mut value: i32) -> () { + *reg8.offset(get_reg8_index(index) as isize) = value as u8; +} +#[no_mangle] +pub unsafe extern "C" fn get_reg16_index(mut index: i32) -> i32 { return index << 1i32; } +#[no_mangle] +pub unsafe extern "C" fn read_reg16(mut index: i32) -> i32 { + return *reg16.offset(get_reg16_index(index) as isize) as i32; +} +#[no_mangle] +pub unsafe extern "C" fn write_reg16(mut index: i32, mut value: i32) -> () { + *reg16.offset(get_reg16_index(index) as isize) = value as u16; +} +#[no_mangle] +pub unsafe extern "C" fn read_reg32(mut index: i32) -> i32 { + return *reg32s.offset(index as isize); +} +#[no_mangle] +pub unsafe extern "C" fn write_reg32(mut index: i32, mut value: i32) -> () { + *reg32s.offset(index as isize) = value; +} +#[no_mangle] +pub unsafe extern "C" fn write_reg_osize(mut index: i32, mut value: i32) -> () { + dbg_assert!(index >= 0i32 && index < 8i32); + if is_osize_32() { + write_reg32(index, value); + } + else { + write_reg16(index, value & 65535i32); + }; +} +#[no_mangle] +pub unsafe extern "C" fn read_mmx32s(mut r: i32) -> i32 { + return (*reg_mmx.offset(r as isize)).u32_0[0usize] as i32; +} +#[no_mangle] +pub unsafe extern "C" fn read_mmx64s(mut r: i32) -> reg64 { return *reg_mmx.offset(r as isize); } +#[no_mangle] +pub unsafe extern "C" fn write_mmx64(mut r: i32, mut low: i32, mut high: i32) -> () { + (*reg_mmx.offset(r as isize)).u32_0[0usize] = low as u32; + (*reg_mmx.offset(r as isize)).u32_0[1usize] = high as u32; +} +#[no_mangle] +pub unsafe extern "C" fn write_mmx_reg64(mut r: i32, mut data: reg64) -> () { + (*reg_mmx.offset(r as isize)).u64_0[0usize] = data.u64_0[0usize]; +} +#[no_mangle] +pub unsafe extern "C" fn read_xmm_f32(mut r: i32) -> f32 { + return (*reg_xmm.offset(r as isize)).f32_0[0usize]; +} +#[no_mangle] +pub unsafe extern "C" fn read_xmm32(mut r: i32) -> i32 { + return (*reg_xmm.offset(r as isize)).u32_0[0usize] as i32; +} +#[no_mangle] +pub unsafe extern "C" fn read_xmm64s(mut r: i32) -> reg64 { + let mut x: reg64 = reg64 { i8_0: [0; 8] }; + x.u64_0[0usize] = (*reg_xmm.offset(r as isize)).u64_0[0usize]; + return x; +} +#[no_mangle] +pub unsafe extern "C" fn read_xmm128s(mut r: i32) -> reg128 { return *reg_xmm.offset(r as isize); } +#[no_mangle] +pub unsafe extern "C" fn write_xmm_f32(mut r: i32, mut data: f32) -> () { + (*reg_xmm.offset(r as isize)).f32_0[0usize] = data; +} +#[no_mangle] +pub unsafe extern "C" fn write_xmm32(mut r: i32, mut data: i32) -> () { + (*reg_xmm.offset(r as isize)).i32_0[0usize] = data; +} +#[no_mangle] +pub unsafe extern "C" fn write_xmm64(mut r: i32, mut data: reg64) -> () { + (*reg_xmm.offset(r as isize)).u64_0[0usize] = data.u64_0[0usize]; +} +#[no_mangle] +pub unsafe extern "C" fn write_xmm128( + mut r: i32, + mut i0: i32, + mut i1: i32, + mut i2: i32, + mut i3: i32, +) -> () { + let mut x: reg128 = reg128 { + u32_0: [i0 as u32, i1 as u32, i2 as u32, i3 as u32], + }; + *reg_xmm.offset(r as isize) = x; +} +#[no_mangle] +pub unsafe extern "C" fn write_xmm_reg128(mut r: i32, mut data: reg128) -> () { + (*reg_xmm.offset(r as isize)).u64_0[0usize] = data.u64_0[0usize]; + (*reg_xmm.offset(r as isize)).u64_0[1usize] = data.u64_0[1usize]; +} +#[no_mangle] +pub unsafe extern "C" fn task_switch_test() -> bool { + if 0 != *cr.offset(0isize) & (CR0_EM | CR0_TS) { + trigger_nm(); + return 0 != 0i32; + } + else { + return 0 != 1i32; + }; +} +#[no_mangle] +pub unsafe extern "C" fn task_switch_test_void() -> () { task_switch_test(); } +#[no_mangle] +pub unsafe extern "C" fn task_switch_test_mmx() -> bool { + if 0 != *cr & CR0_TS { + trigger_nm(); + return 0 != 0i32; + } + else if 0 != *cr & CR0_EM { + trigger_ud(); + return 0 != 0i32; + } + else { + return 0 != 1i32; + }; +} +#[no_mangle] +pub unsafe extern "C" fn task_switch_test_mmx_void() -> () { task_switch_test_mmx(); } +#[no_mangle] +pub unsafe extern "C" fn read_moffs() -> i32 { + c_comment!(("read 2 or 4 byte from ip, depending on address size attribute")); + if is_asize_32() { + return read_imm32s(); + } + else { + return read_imm16(); + }; +} +#[no_mangle] +pub unsafe extern "C" fn get_real_eip() -> i32 { + c_comment!(("Returns the \'real\' instruction pointer, without segment offset")); + return *instruction_pointer - get_seg_cs(); +} +#[no_mangle] +pub unsafe extern "C" fn get_stack_reg() -> i32 { + if *stack_size_32 { + return *reg32s.offset(ESP as isize); + } + else { + return *reg16.offset(SP as isize) as i32; + }; +} +#[no_mangle] +pub unsafe extern "C" fn set_stack_reg(mut value: i32) -> () { + if *stack_size_32 { + *reg32s.offset(ESP as isize) = value + } + else { + *reg16.offset(SP as isize) = value as u16 + }; +} +#[no_mangle] +pub unsafe extern "C" fn get_reg_asize(mut reg: i32) -> i32 { + dbg_assert!(reg == ECX || reg == ESI || reg == EDI); + let mut r: i32 = *reg32s.offset(reg as isize); + if is_asize_32() { + return r; + } + else { + return r & 65535i32; + }; +} +#[no_mangle] +pub unsafe extern "C" fn set_ecx_asize(mut value: i32) -> () { + if is_asize_32() { + *reg32s.offset(ECX as isize) = value + } + else { + *reg16.offset(CX as isize) = value as u16 + }; +} +#[no_mangle] +pub unsafe extern "C" fn add_reg_asize(mut reg: i32, mut value: i32) -> () { + dbg_assert!(reg == ECX || reg == ESI || reg == EDI); + if is_asize_32() { + let ref mut fresh2 = *reg32s.offset(reg as isize); + *fresh2 += value + } + else { + let ref mut fresh3 = *reg16.offset((reg << 1i32) as isize); + *fresh3 = (*fresh3 as i32 + value) as u16 + }; +} +#[no_mangle] +pub unsafe extern "C" fn decr_ecx_asize() -> i32 { + return if 0 != is_asize_32() as i32 { + let ref mut fresh4 = *reg32s.offset(ECX as isize); + *fresh4 -= 1; + *fresh4 + } + else { + let ref mut fresh5 = *reg16.offset(CX as isize); + *fresh5 = (*fresh5).wrapping_sub(1); + *fresh5 as i32 + }; +} +#[no_mangle] +pub unsafe extern "C" fn set_tsc(mut low: u32, mut high: u32) -> () { + let mut new_value: u64 = low as u64 | (high as u64) << 32i32; + let mut current_value: u64 = read_tsc(); + tsc_offset = current_value.wrapping_sub(new_value); +} +#[no_mangle] +pub unsafe extern "C" fn read_tsc() -> u64 { + let mut n: f64 = microtick() * TSC_RATE; + let mut value: u64 = (n as u64).wrapping_sub(tsc_offset); + if 0 != 1i32 + 1i32 { + return value; + } + else { + if value == rdtsc_last_value { + c_comment!(("don\'t go past 1ms")); + if (rdtsc_imprecision_offset as f64) < TSC_RATE { + rdtsc_imprecision_offset = rdtsc_imprecision_offset.wrapping_add(1) + } + } + else { + let mut previous_value: u64 = rdtsc_last_value.wrapping_add(rdtsc_imprecision_offset); + if previous_value <= value { + rdtsc_last_value = value; + rdtsc_imprecision_offset = 0i32 as u64 + } + else { + dbg_log_c!( + ("XXX: Overshot tsc prev=%x:%x offset=%x:%x curr=%x:%x"), + (rdtsc_last_value >> 32i32) as u32 as i32, + rdtsc_last_value as u32 as i32, + (rdtsc_imprecision_offset >> 32i32) as u32 as i32, + rdtsc_imprecision_offset as u32 as i32, + (value >> 32i32) as u32 as i32, + value as u32 as i32 + ); + dbg_assert!(0 != 0i32); + c_comment!(("Keep current value until time catches up")); + } + } + return rdtsc_last_value.wrapping_add(rdtsc_imprecision_offset); + }; +} +#[no_mangle] +pub static mut rdtsc_imprecision_offset: u64 = unsafe { 0i32 as u64 }; +#[no_mangle] +pub static mut rdtsc_last_value: u64 = unsafe { 0i32 as u64 }; +#[no_mangle] +pub static mut tsc_offset: u64 = unsafe { 0i32 as u64 }; +#[no_mangle] +pub static mut TSC_RATE: f64 = unsafe { (50i32 * 1000i32) as f64 }; +#[no_mangle] +pub unsafe extern "C" fn vm86_mode() -> bool { return *flags & FLAG_VM == FLAG_VM; } +#[no_mangle] +pub unsafe extern "C" fn getiopl() -> i32 { return *flags >> 12i32 & 3i32; } +#[no_mangle] +pub unsafe extern "C" fn get_opstats_buffer(mut index: i32) -> i32 { + dbg_assert!(index >= 0i32 && index < 512i32); + if index < 256i32 { + return *opstats_buffer.offset(index as isize) as i32; + } + else { + return *opstats_buffer_0f.offset((index - 256i32) as isize) as i32; + }; +} +#[no_mangle] +pub unsafe extern "C" fn invlpg(mut addr: i32) -> () { + let mut page: i32 = (addr as u32 >> 12i32) as i32; + c_comment!(("Note: Doesn\'t remove this page from valid_tlb_entries: This isn\'t")); + c_comment!(("necessary, because when valid_tlb_entries grows too large, it will be")); + c_comment!(("empties by calling clear_tlb, which removes this entry as it isn\'t global.")); + c_comment!(("This however means that valid_tlb_entries can contain some invalid entries")); + *tlb_data.offset(page as isize) = 0i32; + *last_virt_eip = -1i32; + *last_virt_esp = -1i32; +} +#[no_mangle] +pub unsafe extern "C" fn update_eflags(mut new_flags: i32) -> () { + let mut dont_update: i32 = FLAG_RF | FLAG_VM | FLAG_VIP | FLAG_VIF; + let mut clear: i32 = !FLAG_VIP & !FLAG_VIF & FLAGS_MASK; + if 0 != *flags & FLAG_VM { + c_comment!(("other case needs to be handled in popf or iret")); + dbg_assert!(getiopl() == 3i32); + dont_update |= FLAG_IOPL; + c_comment!(("don\'t clear vip or vif")); + clear |= FLAG_VIP | FLAG_VIF + } + else { + if !*protected_mode { + dbg_assert!(*cpl as i32 == 0i32); + } + if 0 != *cpl { + c_comment!(("cpl > 0")); + c_comment!(("cannot update iopl")); + dont_update |= FLAG_IOPL; + if *cpl as i32 > getiopl() { + c_comment!(("cpl > iopl")); + c_comment!(("cannot update interrupt flag")); + dont_update |= FLAG_INTERRUPT + } + } + } + *flags = (new_flags ^ (*flags ^ new_flags) & dont_update) & clear | FLAGS_DEFAULT; + *flags_changed = 0i32; +} +#[no_mangle] +pub unsafe extern "C" fn get_valid_tlb_entries_count() -> i32 { + let mut result: i32 = 0i32; + let mut i: i32 = 0i32; + while i < valid_tlb_entries_count { + let mut page: i32 = valid_tlb_entries[i as usize]; + let mut entry: i32 = *tlb_data.offset(page as isize); + if 0 != entry { + result += 1 + } + i += 1 + } + return result; +} +#[no_mangle] +pub unsafe extern "C" fn get_valid_global_tlb_entries_count() -> i32 { + let mut result: i32 = 0i32; + let mut i: i32 = 0i32; + while i < valid_tlb_entries_count { + let mut page: i32 = valid_tlb_entries[i as usize]; + let mut entry: i32 = *tlb_data.offset(page as isize); + if 0 != entry & TLB_GLOBAL { + result += 1 + } + i += 1 + } + return result; +} +#[no_mangle] +pub unsafe extern "C" fn translate_address_system_read(mut address: i32) -> u32 { + let mut base: i32 = (address as u32 >> 12i32) as i32; + let mut entry: i32 = *tlb_data.offset(base as isize); + if 0 != entry & TLB_VALID { + return (entry & !4095i32 ^ address) as u32; + } + else { + return (do_page_translation(address, 0 != 0i32, 0 != 0i32) | address & 4095i32) as u32; + }; +} +#[no_mangle] +pub unsafe extern "C" fn translate_address_system_write(mut address: i32) -> u32 { + let mut base: i32 = (address as u32 >> 12i32) as i32; + let mut entry: i32 = *tlb_data.offset(base as isize); + if entry & (TLB_VALID | TLB_READONLY) == TLB_VALID { + return (entry & !4095i32 ^ address) as u32; + } + else { + return (do_page_translation(address, 0 != 1i32, 0 != 0i32) | address & 4095i32) as u32; + }; +} +#[no_mangle] +pub unsafe extern "C" fn trigger_np(mut code: i32) -> () { + if DEBUG { + if cpu_exception_hook(CPU_EXCEPTION_NP) { + return; + } + } + *instruction_pointer = *previous_ip; + call_interrupt_vector(CPU_EXCEPTION_NP, 0 != 0i32, 0 != 1i32, code); + set_current_cpu_exception(CPU_EXCEPTION_NP); +} +#[no_mangle] +pub unsafe extern "C" fn trigger_ss(mut code: i32) -> () { + if DEBUG { + if cpu_exception_hook(CPU_EXCEPTION_SS) { + return; + } + } + *instruction_pointer = *previous_ip; + call_interrupt_vector(CPU_EXCEPTION_SS, 0 != 0i32, 0 != 1i32, code); + set_current_cpu_exception(CPU_EXCEPTION_SS); +} +#[no_mangle] +pub unsafe extern "C" fn store_current_tsc() -> () { *current_tsc = read_tsc(); } diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs new file mode 100644 index 00000000..3957845d --- /dev/null +++ b/src/rust/cpu2/fpu.rs @@ -0,0 +1,1541 @@ +#![allow +( dead_code , mutable_transmutes , non_camel_case_types , non_snake_case , +non_upper_case_globals , unused_mut )] +#![feature ( extern_types , libc )] + +extern "C" { + + #[no_mangle] + fn __fpclassifyl(_: f64) -> i32; + #[no_mangle] + fn ceil(_: f64) -> f64; + #[no_mangle] + fn floor(_: f64) -> f64; + #[no_mangle] + fn fmod(_: f64, _: f64) -> f64; + #[no_mangle] + fn pow(_: f64, _: f64) -> f64; + #[no_mangle] + fn round(_: f64) -> f64; + #[no_mangle] + fn trunc(_: f64) -> f64; + #[no_mangle] + static FLAG_CARRY: i32; + #[no_mangle] + static FLAG_PARITY: i32; + #[no_mangle] + static FLAG_ADJUST: i32; + #[no_mangle] + static FLAG_ZERO: i32; + #[no_mangle] + static FLAG_SIGN: i32; + #[no_mangle] + static FLAG_TRAP: i32; + #[no_mangle] + static FLAG_INTERRUPT: i32; + #[no_mangle] + static FLAG_DIRECTION: i32; + #[no_mangle] + static FLAG_OVERFLOW: i32; + #[no_mangle] + static FLAG_IOPL: i32; + #[no_mangle] + static FLAG_NT: i32; + #[no_mangle] + static FLAG_RF: i32; + #[no_mangle] + static FLAG_VM: i32; + #[no_mangle] + static FLAG_AC: i32; + #[no_mangle] + static FLAG_VIF: i32; + #[no_mangle] + static FLAG_VIP: i32; + #[no_mangle] + static FLAG_ID: i32; + #[no_mangle] + static FLAGS_DEFAULT: i32; + #[no_mangle] + static FLAGS_MASK: i32; + #[no_mangle] + static FLAGS_ALL: i32; + #[no_mangle] + static OPSIZE_8: i32; + #[no_mangle] + static OPSIZE_16: i32; + #[no_mangle] + static OPSIZE_32: i32; + #[no_mangle] + static EAX: i32; + #[no_mangle] + static ECX: i32; + #[no_mangle] + static EDX: i32; + #[no_mangle] + static EBX: i32; + #[no_mangle] + static ESP: i32; + #[no_mangle] + static EBP: i32; + #[no_mangle] + static ESI: i32; + #[no_mangle] + static EDI: i32; + #[no_mangle] + static AX: i32; + #[no_mangle] + static CX: i32; + #[no_mangle] + static DX: i32; + #[no_mangle] + static BX: i32; + #[no_mangle] + static SP: i32; + #[no_mangle] + static BP: i32; + #[no_mangle] + static SI: i32; + #[no_mangle] + static DI: i32; + #[no_mangle] + static AL: i32; + #[no_mangle] + static CL: i32; + #[no_mangle] + static DL: i32; + #[no_mangle] + static BL: i32; + #[no_mangle] + static AH: i32; + #[no_mangle] + static CH: i32; + #[no_mangle] + static DH: i32; + #[no_mangle] + static BH: i32; + #[no_mangle] + static ES: i32; + #[no_mangle] + static CS: i32; + #[no_mangle] + static SS: i32; + #[no_mangle] + static DS: i32; + #[no_mangle] + static FS: i32; + #[no_mangle] + static GS: i32; + #[no_mangle] + static TR: i32; + #[no_mangle] + static LDTR: i32; + #[no_mangle] + static PAGE_TABLE_PRESENT_MASK: i32; + #[no_mangle] + static PAGE_TABLE_RW_MASK: i32; + #[no_mangle] + static PAGE_TABLE_USER_MASK: i32; + #[no_mangle] + static PAGE_TABLE_ACCESSED_MASK: i32; + #[no_mangle] + static PAGE_TABLE_DIRTY_MASK: i32; + #[no_mangle] + static PAGE_TABLE_PSE_MASK: i32; + #[no_mangle] + static PAGE_TABLE_GLOBAL_MASK: i32; + #[no_mangle] + static MMAP_BLOCK_BITS: i32; + #[no_mangle] + static MMAP_BLOCK_SIZE: i32; + #[no_mangle] + static CR0_PE: i32; + #[no_mangle] + static CR0_MP: i32; + #[no_mangle] + static CR0_EM: i32; + #[no_mangle] + static CR0_TS: i32; + #[no_mangle] + static CR0_ET: i32; + #[no_mangle] + static CR0_WP: i32; + #[no_mangle] + static CR0_NW: i32; + #[no_mangle] + static CR0_CD: i32; + #[no_mangle] + static CR0_PG: i32; + #[no_mangle] + static CR4_VME: i32; + #[no_mangle] + static CR4_PVI: i32; + #[no_mangle] + static CR4_TSD: i32; + #[no_mangle] + static CR4_PSE: i32; + #[no_mangle] + static CR4_DE: i32; + #[no_mangle] + static CR4_PAE: i32; + #[no_mangle] + static CR4_PGE: i32; + #[no_mangle] + static IA32_SYSENTER_CS: i32; + #[no_mangle] + static IA32_SYSENTER_ESP: i32; + #[no_mangle] + static IA32_SYSENTER_EIP: i32; + #[no_mangle] + static IA32_TIME_STAMP_COUNTER: i32; + #[no_mangle] + static IA32_PLATFORM_ID: i32; + #[no_mangle] + static IA32_APIC_BASE_MSR: i32; + #[no_mangle] + static IA32_BIOS_SIGN_ID: i32; + #[no_mangle] + static MSR_PLATFORM_INFO: i32; + #[no_mangle] + static MSR_MISC_FEATURE_ENABLES: i32; + #[no_mangle] + static IA32_MISC_ENABLE: i32; + #[no_mangle] + static IA32_RTIT_CTL: i32; + #[no_mangle] + static MSR_SMI_COUNT: i32; + #[no_mangle] + static IA32_MCG_CAP: i32; + #[no_mangle] + static IA32_KERNEL_GS_BASE: i32; + #[no_mangle] + static MSR_PKG_C2_RESIDENCY: i32; + #[no_mangle] + static IA32_APIC_BASE_BSP: i32; + #[no_mangle] + static IA32_APIC_BASE_EXTD: i32; + #[no_mangle] + static IA32_APIC_BASE_EN: i32; + #[no_mangle] + static APIC_ADDRESS: i32; + #[no_mangle] + static SEG_PREFIX_NONE: i32; + #[no_mangle] + static SEG_PREFIX_ZERO: i32; + #[no_mangle] + static PREFIX_MASK_REP: i32; + #[no_mangle] + static PREFIX_REPZ: i32; + #[no_mangle] + static PREFIX_REPNZ: i32; + #[no_mangle] + static PREFIX_MASK_SEGMENT: i32; + #[no_mangle] + static PREFIX_MASK_OPSIZE: i32; + #[no_mangle] + static PREFIX_MASK_ADDRSIZE: i32; + #[no_mangle] + static PREFIX_F2: i32; + #[no_mangle] + static PREFIX_F3: i32; + #[no_mangle] + static PREFIX_66: i32; + #[no_mangle] + static LOG_CPU: i32; + #[no_mangle] + static A20_MASK: i32; + #[no_mangle] + static A20_MASK16: i32; + #[no_mangle] + static A20_MASK32: i32; + #[no_mangle] + static MXCSR_MASK: i32; + + #[no_mangle] + fn dbg_log(m: *const i8) -> (); + #[no_mangle] + fn c_comment(m: *const i8) -> (); + #[no_mangle] + fn isnan_XXX(f: f64) -> bool; + #[no_mangle] + fn isfinite_XXX(f: f64) -> bool; + #[no_mangle] + static mut mem8: *mut u8; + #[no_mangle] + static mut mem16: *mut u16; + #[no_mangle] + static mut mem32s: *mut i32; + #[no_mangle] + static mut jit_block_boundary: bool; + #[no_mangle] + static VALID_TLB_ENTRY_MAX: i32; + #[no_mangle] + static mut valid_tlb_entries: [i32; 10000]; + #[no_mangle] + static mut valid_tlb_entries_count: i32; + #[no_mangle] + static TLB_VALID: i32; + #[no_mangle] + static TLB_READONLY: i32; + #[no_mangle] + static TLB_NO_USER: i32; + #[no_mangle] + static TLB_IN_MAPPED_RANGE: i32; + #[no_mangle] + static TLB_GLOBAL: i32; + #[no_mangle] + static TLB_HAS_CODE: i32; + #[no_mangle] + static CPU_EXCEPTION_DE: i32; + #[no_mangle] + static CPU_EXCEPTION_DB: i32; + #[no_mangle] + static CPU_EXCEPTION_NMI: i32; + #[no_mangle] + static CPU_EXCEPTION_BP: i32; + #[no_mangle] + static CPU_EXCEPTION_OF: i32; + #[no_mangle] + static CPU_EXCEPTION_BR: i32; + #[no_mangle] + static CPU_EXCEPTION_UD: i32; + #[no_mangle] + static CPU_EXCEPTION_NM: i32; + #[no_mangle] + static CPU_EXCEPTION_DF: i32; + #[no_mangle] + static CPU_EXCEPTION_TS: i32; + #[no_mangle] + static CPU_EXCEPTION_NP: i32; + #[no_mangle] + static CPU_EXCEPTION_SS: i32; + #[no_mangle] + static CPU_EXCEPTION_GP: i32; + #[no_mangle] + static CPU_EXCEPTION_PF: i32; + #[no_mangle] + static CPU_EXCEPTION_MF: i32; + #[no_mangle] + static CPU_EXCEPTION_AC: i32; + #[no_mangle] + static CPU_EXCEPTION_MC: i32; + #[no_mangle] + static CPU_EXCEPTION_XM: i32; + #[no_mangle] + static CPU_EXCEPTION_VE: i32; + #[no_mangle] + fn writable_or_pagefault(addr: i32, size: i32) -> (); + #[no_mangle] + fn is_osize_32() -> bool; + #[no_mangle] + fn trigger_ud() -> (); + #[no_mangle] + fn safe_read16(addr: i32) -> i32; + #[no_mangle] + fn safe_read32s(address: i32) -> i32; + #[no_mangle] + fn safe_read64s(addr: i32) -> reg64; + #[no_mangle] + fn safe_write16(addr: i32, value: i32) -> (); + #[no_mangle] + fn safe_write32(address: i32, value: i32) -> (); + #[no_mangle] + fn safe_write64(addr: i32, value: i64) -> (); + #[no_mangle] + static fpu_stack_ptr: *mut u32; + #[no_mangle] + static fpu_st: *mut f64; + #[no_mangle] + static fpu_status_word: *mut i32; + #[no_mangle] + static fpu_stack_empty: *mut i32; + #[no_mangle] + static fpu_control_word: *mut i32; + #[no_mangle] + static flags: *mut i32; + #[no_mangle] + static flags_changed: *mut i32; + #[no_mangle] + static fpu_opcode: *mut i32; + #[no_mangle] + static fpu_dp: *mut i32; + #[no_mangle] + static fpu_ip: *mut i32; + #[no_mangle] + fn convert_f64_to_i32(_: f64) -> i32; + #[no_mangle] + static DEBUG: bool; + #[no_mangle] + static fpu_dp_selector: *mut i32; + #[no_mangle] + static fpu_ip_selector: *mut i32; + #[no_mangle] + static reg16: *mut u16; + #[no_mangle] + static fpu_st8: *mut u8; + #[no_mangle] + static reg8: *mut u8; + #[no_mangle] + static reg8s: *mut i8; + #[no_mangle] + static reg16s: *mut i16; + #[no_mangle] + static reg32s: *mut i32; + #[no_mangle] + static last_op1: *mut i32; + #[no_mangle] + static last_op2: *mut i32; + #[no_mangle] + static last_op_size: *mut i32; + #[no_mangle] + static last_add_result: *mut i32; + #[no_mangle] + static last_result: *mut i32; + #[no_mangle] + static page_fault: *mut bool; + #[no_mangle] + static a20_enabled: *mut bool; + #[no_mangle] + static instruction_pointer: *mut i32; + #[no_mangle] + static previous_ip: *mut i32; + #[no_mangle] + static idtr_size: *mut i32; + #[no_mangle] + static idtr_offset: *mut i32; + #[no_mangle] + static gdtr_size: *mut i32; + #[no_mangle] + static gdtr_offset: *mut i32; + #[no_mangle] + static cr: *mut i32; + #[no_mangle] + static cpl: *mut u8; + #[no_mangle] + static in_hlt: *mut bool; + #[no_mangle] + static last_virt_eip: *mut i32; + #[no_mangle] + static eip_phys: *mut i32; + #[no_mangle] + static last_virt_esp: *mut i32; + #[no_mangle] + static esp_phys: *mut i32; + #[no_mangle] + static sysenter_cs: *mut i32; + #[no_mangle] + static sysenter_esp: *mut i32; + #[no_mangle] + static sysenter_eip: *mut i32; + #[no_mangle] + static prefixes: *mut u8; + #[no_mangle] + static timestamp_counter: *mut u32; + #[no_mangle] + static sreg: *mut u16; + #[no_mangle] + static dreg: *mut i32; + #[no_mangle] + static fw_value: *mut i32; + #[no_mangle] + static segment_is_null: *mut bool; + #[no_mangle] + static segment_offsets: *mut i32; + #[no_mangle] + static segment_limits: *mut u32; + #[no_mangle] + static protected_mode: *mut bool; + #[no_mangle] + static is_32: *mut bool; + #[no_mangle] + static stack_size_32: *mut bool; + #[no_mangle] + static memory_size: *mut u32; + #[no_mangle] + static mxcsr: *mut i32; + #[no_mangle] + static reg_xmm: *mut reg128; + #[no_mangle] + static current_tsc: *mut u64; + #[no_mangle] + static fpu_st32: *mut i32; + #[no_mangle] + static reg_mmx: *mut reg64; + #[no_mangle] + static opstats_buffer: *mut u32; + #[no_mangle] + static opstats_buffer_0f: *mut u32; + #[no_mangle] + static tlb_data: *mut i32; +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union reg64 { + i8_0: [i8; 8], + i16_0: [i16; 4], + i32_0: [i32; 2], + i64_0: [i64; 1], + u8_0: [u8; 8], + u16_0: [u16; 4], + u32_0: [u32; 2], + u64_0: [u64; 1], + f32_0: [f32; 2], + f64_0: [f64; 1], +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union f64_int { + u8_0: [u8; 8], + i32_0: [i32; 2], + u64_0: [u64; 1], + f64_0: f64, +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union f32_int { + u8_0: [u8; 4], + i32_0: i32, + f32_0: f32, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed { + __f: f32, + __i: u32, +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union reg128 { + i8_0: [i8; 16], + i16_0: [i16; 8], + i32_0: [i32; 4], + i64_0: [i64; 2], + u8_0: [u8; 16], + u16_0: [u16; 8], + u32_0: [u32; 4], + u64_0: [u64; 2], + f32_0: [f32; 4], + f64_0: [f64; 2], +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_0 { + __f: f64, + __i: u64, +} +unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { + let mut __u: unnamed = unnamed { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { + let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x >= __y) as i32; +} +#[no_mangle] +pub static mut M_LOG2E: f64 = unsafe { 1.4426950408889634f64 }; +#[no_mangle] +pub static mut M_LN2: f64 = unsafe { 0.6931471805599453f64 }; +#[no_mangle] +pub static mut M_LN10: f64 = unsafe { 2.302585092994046f64 }; +#[no_mangle] +pub static mut M_PI: f64 = unsafe { 3.141592653589793f64 }; +#[no_mangle] +pub static mut FPU_C0: i32 = unsafe { 256i32 }; +#[no_mangle] +pub static mut FPU_C1: i32 = unsafe { 512i32 }; +#[no_mangle] +pub static mut FPU_C2: i32 = unsafe { 1024i32 }; +#[no_mangle] +pub static mut FPU_C3: i32 = unsafe { 16384i32 }; +#[no_mangle] +pub static mut FPU_RESULT_FLAGS: i32 = unsafe { FPU_C0 | FPU_C1 | FPU_C2 | FPU_C3 }; +#[no_mangle] +pub static mut FPU_STACK_TOP: i32 = unsafe { 14336i32 }; +#[no_mangle] +pub unsafe extern "C" fn fpu_get_st0() -> f64 { + if 0 != *fpu_stack_empty >> *fpu_stack_ptr & 1i32 { + *fpu_status_word &= !FPU_C1; + fpu_stack_fault(); + return INDEFINITE_NAN; + } + else { + return *fpu_st.offset(*fpu_stack_ptr as isize); + }; +} +#[no_mangle] +pub static mut INDEFINITE_NAN: f64 = unsafe { ::std::f32::NAN as f64 }; +#[no_mangle] +pub unsafe extern "C" fn fpu_stack_fault() -> () { + c_comment!(("TODO: Interrupt")); + *fpu_status_word |= FPU_EX_SF | FPU_EX_I; +} +#[no_mangle] +pub static mut FPU_EX_I: i32 = unsafe { 1i32 << 0i32 }; +#[no_mangle] +pub static mut FPU_EX_SF: i32 = unsafe { 1i32 << 6i32 }; +#[no_mangle] +pub unsafe extern "C" fn fpu_get_sti(mut i: i32) -> f64 { + dbg_assert!(i >= 0i32 && i < 8i32); + i = ((i as u32).wrapping_add(*fpu_stack_ptr) & 7i32 as u32) as i32; + if 0 != *fpu_stack_empty >> i & 1i32 { + *fpu_status_word &= !FPU_C1; + fpu_stack_fault(); + return INDEFINITE_NAN; + } + else { + return *fpu_st.offset(i as isize); + }; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_integer_round(mut f: f64) -> f64 { + let mut rc: i32 = *fpu_control_word >> 10i32 & 3i32; + c_comment!(("XXX: See https://en.wikipedia.org/wiki/C_mathematical_functions")); + if rc == 0i32 { + c_comment!(("Round to nearest, or even if equidistant")); + let mut rounded: f64 = round(f); + let mut diff: f64 = rounded - f; + if diff == 0.5f64 || diff == -0.5f64 { + rounded = 2.0f64 * round(f * 0.5f64) + } + return rounded; + } + else if rc == 1i32 || rc == 3i32 && f > 0i32 as f64 { + c_comment!(("rc=3 is truncate -> floor for positive numbers")); + return floor(f); + } + else { + return ceil(f); + }; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_load_m32(mut addr: i32) -> f64 { + let mut v: f32_int = f32_int { + i32_0: safe_read32s(addr), + }; + return v.f32_0 as f64; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_load_m64(mut addr: i32) -> f64 { + let mut value: u64 = safe_read64s(addr).u64_0[0usize]; + let mut v: f64_int = f64_int { u64_0: [value] }; + return v.f64_0; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_load_m80(mut addr: u32) -> f64 { + let mut value: u64 = safe_read64s(addr as i32).u64_0[0usize]; + let mut low: u32 = value as u32; + let mut high: u32 = (value >> 32i32) as u32; + let mut exponent: i32 = safe_read16(addr.wrapping_add(8i32 as u32) as i32); + let mut sign: i32 = exponent >> 15i32; + exponent &= !32768i32; + if exponent == 0i32 { + c_comment!(("TODO: denormal numbers")); + return 0i32 as f64; + } + else if exponent < 32767i32 { + exponent -= 16383i32; + c_comment!(("Note: some bits might be lost at this point")); + let mut mantissa: f64 = low as f64 + 4294967296i64 as f64 * high as f64; + if 0 != sign { + mantissa = -mantissa + } + c_comment!(("Simply compute the 64 bit floating point number.")); + c_comment!(("An alternative write the mantissa, sign and exponent in the")); + c_comment!(("float64_byte and return float64[0]")); + return mantissa * pow(2i32 as f64, (exponent - 63i32) as f64); + } + else { + c_comment!(("TODO: NaN, Infinity")); + if 0 != 0i32 * 0i32 { + dbg_log_c!(("Load m80 TODO")); + } + let mut double_int_view: f64_int = f64_int { u8_0: [0; 8] }; + double_int_view.u8_0[7usize] = (127i32 | sign << 7i32) as u8; + double_int_view.u8_0[6usize] = (240i32 as u32 | high >> 30i32 << 3i32 & 8i32 as u32) as u8; + double_int_view.u8_0[5usize] = 0i32 as u8; + double_int_view.u8_0[4usize] = 0i32 as u8; + double_int_view.i32_0[0usize] = 0i32; + return double_int_view.f64_0; + }; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_load_status_word() -> i32 { + return ((*fpu_status_word & !(7i32 << 11i32)) as u32 | *fpu_stack_ptr << 11i32) as i32; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fadd(mut target_index: i32, mut val: f64) -> () { + let mut st0: f64 = fpu_get_st0(); + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = + st0 + val; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fclex() -> () { *fpu_status_word = 0i32; } +#[no_mangle] +pub unsafe extern "C" fn fpu_fcmovcc(mut condition: bool, mut r: i32) -> () { + if condition { + *fpu_st.offset(*fpu_stack_ptr as isize) = fpu_get_sti(r); + *fpu_stack_empty &= !(1i32 << *fpu_stack_ptr) + }; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fcom(mut y: f64) -> () { + let mut x: f64 = fpu_get_st0(); + *fpu_status_word &= !FPU_RESULT_FLAGS; + if !(x > y) { + if y > x { + *fpu_status_word |= FPU_C0 + } + else if x == y { + *fpu_status_word |= FPU_C3 + } + else { + *fpu_status_word |= FPU_C0 | FPU_C2 | FPU_C3 + } + }; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fcomi(mut r: i32) -> () { + let mut y: f64 = fpu_get_sti(r); + let mut x: f64 = *fpu_st.offset(*fpu_stack_ptr as isize); + *flags_changed &= !(1i32 | FLAG_PARITY | FLAG_ZERO); + *flags &= !(1i32 | FLAG_PARITY | FLAG_ZERO); + if !(x > y) { + if y > x { + *flags |= 1i32 + } + else if x == y { + *flags |= FLAG_ZERO + } + else { + *flags |= 1i32 | FLAG_PARITY | FLAG_ZERO + } + }; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fcomip(mut r: i32) -> () { + fpu_fcomi(r); + fpu_pop(); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_pop() -> () { + *fpu_stack_empty |= 1i32 << *fpu_stack_ptr; + *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_add(1i32 as u32) & 7i32 as u32; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fcomp(mut val: f64) -> () { + fpu_fcom(val); + fpu_pop(); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fdiv(mut target_index: i32, mut val: f64) -> () { + let mut st0: f64 = fpu_get_st0(); + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = + st0 / val; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fdivr(mut target_index: i32, mut val: f64) -> () { + let mut st0: f64 = fpu_get_st0(); + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = + val / st0; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_ffree(mut r: i32) -> () { + *fpu_stack_empty |= 1i32 << (*fpu_stack_ptr).wrapping_add(r as u32); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fildm64(mut addr: i32) -> () { + let mut value: i64 = safe_read64s(addr).i64_0[0usize]; + let mut m64: f64 = value as f64; + fpu_push(m64); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_push(mut x: f64) -> () { + *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_sub(1i32 as u32) & 7i32 as u32; + if 0 != *fpu_stack_empty >> *fpu_stack_ptr & 1i32 { + *fpu_status_word &= !FPU_C1; + *fpu_stack_empty &= !(1i32 << *fpu_stack_ptr); + *fpu_st.offset(*fpu_stack_ptr as isize) = x + } + else { + *fpu_status_word |= FPU_C1; + fpu_stack_fault(); + *fpu_st.offset(*fpu_stack_ptr as isize) = INDEFINITE_NAN + }; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_finit() -> () { + *fpu_control_word = 895i32; + *fpu_status_word = 0i32; + *fpu_ip.offset(0isize) = 0i32; + *fpu_dp.offset(0isize) = 0i32; + *fpu_opcode.offset(0isize) = 0i32; + *fpu_stack_empty = 255i32; + *fpu_stack_ptr = 0i32 as u32; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fistm16(mut addr: i32) -> () { + let mut st0: f64 = fpu_integer_round(fpu_get_st0()); + if st0 <= 32767i32 as f64 && st0 >= -32768i32 as f64 { + safe_write16(addr, st0 as i32); + } + else { + fpu_invalid_arithmetic(); + safe_write16(addr, 32768i32); + }; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_invalid_arithmetic() -> () { *fpu_status_word |= FPU_EX_I; } +#[no_mangle] +pub unsafe extern "C" fn fpu_fistm16p(mut addr: i32) -> () { + fpu_fistm16(addr); + fpu_pop(); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fistm32(mut addr: i32) -> () { + let mut st0: f64 = fpu_integer_round(fpu_get_st0()); + let mut i: i32 = convert_f64_to_i32(st0); + if i == 2147483648u32 as i32 { + c_comment!(("XXX: Probably not correct if st0 == 0x80000000")); + c_comment!(("(input fits, but same value as error value)")); + fpu_invalid_arithmetic(); + } + safe_write32(addr, i); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fistm32p(mut addr: i32) -> () { + fpu_fistm32(addr); + fpu_pop(); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fistm64p(mut addr: i32) -> () { + let mut st0: f64 = fpu_integer_round(fpu_get_st0()); + let mut value: i64 = 0; + if st0 < TWO_POW_63 && st0 >= -TWO_POW_63 { + value = st0 as i64 + } + else { + value = 9223372036854775808u64 as i64; + fpu_invalid_arithmetic(); + } + safe_write64(addr, value); + fpu_pop(); +} +#[no_mangle] +pub static mut TWO_POW_63: f64 = unsafe { 9223372036854775808u64 as f64 }; +#[no_mangle] +pub unsafe extern "C" fn fpu_fldcw(mut addr: i32) -> () { + let mut word: i32 = safe_read16(addr); + *fpu_control_word = word; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fldenv(mut addr: i32) -> () { + if is_osize_32() { + *fpu_control_word = safe_read16(addr); + fpu_set_status_word(safe_read16(addr + 4i32)); + fpu_set_tag_word(safe_read16(addr + 8i32)); + *fpu_ip.offset(0isize) = safe_read32s(addr + 12i32); + *fpu_ip_selector.offset(0isize) = safe_read16(addr + 16i32); + *fpu_opcode.offset(0isize) = safe_read16(addr + 18i32); + *fpu_dp.offset(0isize) = safe_read32s(addr + 20i32); + *fpu_dp_selector.offset(0isize) = safe_read16(addr + 24i32) + } + else { + dbg_log_c!(("fldenv16")); + fpu_unimpl(); + }; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_unimpl() -> () { + if DEBUG { + dbg_assert!(0 != 0i32); + } + else { + trigger_ud(); + }; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_set_tag_word(mut tag_word: i32) -> () { + *fpu_stack_empty = 0i32; + let mut i: i32 = 0i32; + while i < 8i32 { + *fpu_stack_empty |= tag_word >> i & tag_word >> i + 1i32 & 1i32 << i; + i += 1 + } +} +#[no_mangle] +pub unsafe extern "C" fn fpu_set_status_word(mut sw: i32) -> () { + *fpu_status_word = sw & !(7i32 << 11i32); + *fpu_stack_ptr = (sw >> 11i32 & 7i32) as u32; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fldm32(mut addr: i32) -> () { fpu_push(safe_read32s(addr) as f64); } +#[no_mangle] +pub unsafe extern "C" fn fpu_fldm64(mut addr: i32) -> () { fpu_push(fpu_load_m64(addr)); } +#[no_mangle] +pub unsafe extern "C" fn fpu_fldm80(mut addr: i32) -> () { fpu_push(fpu_load_m80(addr as u32)); } +#[no_mangle] +pub unsafe extern "C" fn fpu_fmul(mut target_index: i32, mut val: f64) -> () { + let mut st0: f64 = fpu_get_st0(); + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = + st0 * val; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fnstsw_mem(mut addr: i32) -> () { + safe_write16(addr, fpu_load_status_word()); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fnstsw_reg() -> () { + *reg16.offset(AX as isize) = fpu_load_status_word() as u16; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fprem() -> () { + c_comment!(("XXX: This implementation differs from the description in Intel\'s manuals")); + let mut st0: f64 = fpu_get_st0(); + let mut st1: f64 = fpu_get_sti(1i32); + let mut fprem_quotient: i32 = convert_f64_to_i32(trunc(st0 / st1)); + *fpu_st.offset(*fpu_stack_ptr as isize) = fmod(st0, st1); + *fpu_status_word &= !(FPU_C0 | FPU_C1 | FPU_C3); + if 0 != fprem_quotient & 1i32 { + *fpu_status_word |= FPU_C1 + } + if 0 != fprem_quotient & 1i32 << 1i32 { + *fpu_status_word |= FPU_C3 + } + if 0 != fprem_quotient & 1i32 << 2i32 { + *fpu_status_word |= FPU_C0 + } + *fpu_status_word &= !FPU_C2; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_frstor(mut addr: i32) -> () { + fpu_fldenv(addr); + addr += 28i32; + let mut i: i32 = 0i32; + while i < 8i32 { + *fpu_st.offset(((i as u32).wrapping_add(*fpu_stack_ptr) & 7i32 as u32) as isize) = + fpu_load_m80(addr as u32); + addr += 10i32; + i += 1 + } +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fsave(mut addr: i32) -> () { + writable_or_pagefault(addr, 108i32); + fpu_fstenv(addr); + addr += 28i32; + let mut i: i32 = 0i32; + while i < 8i32 { + fpu_store_m80( + addr as u32, + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(i as u32) & 7i32 as u32) as isize), + ); + addr += 10i32; + i += 1 + } + fpu_finit(); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_store_m80(mut addr: u32, mut n: f64) -> () { + let mut double_int_view: f64_int = f64_int { f64_0: n }; + let mut sign: u8 = (double_int_view.u8_0[7usize] as i32 & 128i32) as u8; + let mut exponent: i32 = (double_int_view.u8_0[7usize] as i32 & 127i32) << 4i32 + | double_int_view.u8_0[6usize] as i32 >> 4i32; + let mut low: i32 = 0; + let mut high: i32 = 0; + if exponent == 2047i32 { + c_comment!(("all bits set (NaN and infinity)")); + exponent = 32767i32; + low = 0i32; + high = + (2147483648u32 | ((double_int_view.i32_0[1usize] & 524288i32) << 11i32) as u32) as i32 + } + else if exponent == 0i32 { + c_comment!(("zero and denormal numbers")); + c_comment!(("Just assume zero for now")); + low = 0i32; + high = 0i32 + } + else { + exponent += 16383i32 - 1023i32; + c_comment!(("does the mantissa need to be adjusted?")); + low = double_int_view.i32_0[0usize] << 11i32; + high = (2147483648u32 + | ((double_int_view.i32_0[1usize] & 1048575i32) << 11i32) as u32 + | double_int_view.i32_0[0usize] as u32 >> 21i32) as i32 + } + dbg_assert!(exponent >= 0i32 && exponent < 32768i32); + c_comment!(("writable_or_pagefault must have checked called by the caller!")); + safe_write64( + addr as i32, + (low as u64 & 4294967295u32 as u64 | (high as u64) << 32i32) as i64, + ); + safe_write16( + addr.wrapping_add(8i32 as u32) as i32, + (sign as i32) << 8i32 | exponent, + ); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fstenv(mut addr: i32) -> () { + if is_osize_32() { + writable_or_pagefault(addr, 26i32); + safe_write16(addr, *fpu_control_word); + safe_write16(addr + 4i32, fpu_load_status_word()); + safe_write16(addr + 8i32, fpu_load_tag_word()); + safe_write32(addr + 12i32, *fpu_ip.offset(0isize)); + safe_write16(addr + 16i32, *fpu_ip_selector.offset(0isize)); + safe_write16(addr + 18i32, *fpu_opcode.offset(0isize)); + safe_write32(addr + 20i32, *fpu_dp.offset(0isize)); + safe_write16(addr + 24i32, *fpu_dp_selector.offset(0isize)); + } + else { + dbg_log_c!(("fstenv16")); + fpu_unimpl(); + }; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_load_tag_word() -> i32 { + let mut tag_word: i32 = 0i32; + let mut i: i32 = 0i32; + while i < 8i32 { + let mut value: f64 = *fpu_st.offset(i as isize); + if 0 != *fpu_stack_empty >> i & 1i32 { + tag_word |= 3i32 << (i << 1i32) + } + else if value == 0i32 as f64 { + tag_word |= 1i32 << (i << 1i32) + } + else if !isfinite_XXX(value) { + tag_word |= 2i32 << (i << 1i32) + } + i += 1 + } + return tag_word; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fst(mut r: i32) -> () { + *fpu_st.offset((*fpu_stack_ptr).wrapping_add(r as u32) as isize) = fpu_get_st0(); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fst80p(mut addr: i32) -> () { + writable_or_pagefault(addr, 10i32); + fpu_store_m80(addr as u32, fpu_get_st0()); + fpu_pop(); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fstcw(mut addr: i32) -> () { safe_write16(addr, *fpu_control_word); } +#[no_mangle] +pub unsafe extern "C" fn fpu_fstm32(mut addr: i32) -> () { fpu_store_m32(addr, fpu_get_st0()); } +#[no_mangle] +pub unsafe extern "C" fn fpu_store_m32(mut addr: i32, mut x: f64) -> () { + let mut v: f32_int = f32_int { f32_0: x as f32 }; + safe_write32(addr, v.i32_0); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fstm32p(mut addr: i32) -> () { + fpu_fstm32(addr); + fpu_pop(); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fstm64(mut addr: i32) -> () { fpu_store_m64(addr, fpu_get_st0()); } +#[no_mangle] +pub unsafe extern "C" fn fpu_store_m64(mut addr: i32, mut x: f64) -> () { + let mut v: f64_int = f64_int { f64_0: x }; + safe_write64(addr, v.u64_0[0usize] as i64); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fstm64p(mut addr: i32) -> () { + fpu_fstm64(addr); + fpu_pop(); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fstp(mut r: i32) -> () { + fpu_fst(r); + fpu_pop(); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fsub(mut target_index: i32, mut val: f64) -> () { + let mut st0: f64 = fpu_get_st0(); + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = + st0 - val; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fsubr(mut target_index: i32, mut val: f64) -> () { + let mut st0: f64 = fpu_get_st0(); + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = + val - st0; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_ftst(mut x: f64) -> () { + *fpu_status_word &= !FPU_RESULT_FLAGS; + if isnan_XXX(x) { + *fpu_status_word |= FPU_C3 | FPU_C2 | FPU_C0 + } + else if x == 0i32 as f64 { + *fpu_status_word |= FPU_C3 + } + else if x < 0i32 as f64 { + *fpu_status_word |= FPU_C0 + } + c_comment!(("TODO: unordered (x is nan, etc)")); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fucom(mut r: i32) -> () { + c_comment!(("TODO")); + fpu_fcom(fpu_get_sti(r)); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fucomi(mut r: i32) -> () { + c_comment!(("TODO")); + fpu_fcomi(r); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fucomip(mut r: i32) -> () { + fpu_fucomi(r); + fpu_pop(); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fucomp(mut r: i32) -> () { + fpu_fucom(r); + fpu_pop(); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fucompp() -> () { + fpu_fucom(1i32); + fpu_pop(); + fpu_pop(); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fxam(mut x: f64) -> () { + *fpu_status_word &= !FPU_RESULT_FLAGS; + *fpu_status_word |= fpu_sign(0i32) << 9i32; + if 0 != *fpu_stack_empty >> *fpu_stack_ptr & 1i32 { + *fpu_status_word |= FPU_C3 | FPU_C0 + } + else if isnan_XXX(x) { + *fpu_status_word |= FPU_C0 + } + else if x == 0i32 as f64 { + *fpu_status_word |= FPU_C3 + } + else if x == ::std::f32::INFINITY as f64 || x == -::std::f32::INFINITY as f64 { + *fpu_status_word |= FPU_C2 | FPU_C0 + } + else { + *fpu_status_word |= FPU_C2 + } + c_comment!(("TODO:")); + c_comment!(("Unsupported, Denormal")); +} +#[no_mangle] +pub unsafe extern "C" fn fpu_sign(mut i: i32) -> i32 { + c_comment!(("sign of a number on the stack")); + return *fpu_st8.offset( + (((*fpu_stack_ptr).wrapping_add(i as u32) & 7i32 as u32) << 3i32 | 7i32 as u32) as isize, + ) as i32 + >> 7i32; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fxch(mut i: i32) -> () { + let mut sti: f64 = fpu_get_sti(i); + *fpu_st.offset((*fpu_stack_ptr).wrapping_add(i as u32) as isize) = fpu_get_st0(); + *fpu_st.offset(*fpu_stack_ptr as isize) = sti; +} +#[no_mangle] +pub unsafe extern "C" fn fpu_fxtract() -> () { + let mut double_int_view: f64_int = f64_int { + f64_0: fpu_get_st0(), + }; + let mut exponent: f64 = (((double_int_view.u8_0[7usize] as i32 & 127i32) << 4i32 + | double_int_view.u8_0[6usize] as i32 >> 4i32) + - 1023i32) as f64; + double_int_view.u8_0[7usize] = (63i32 | double_int_view.u8_0[7usize] as i32 & 128i32) as u8; + double_int_view.u8_0[6usize] = (double_int_view.u8_0[6usize] as i32 | 240i32) as u8; + *fpu_st.offset(*fpu_stack_ptr as isize) = exponent; + fpu_push(double_int_view.f64_0); +} +#[no_mangle] +pub unsafe extern "C" fn fwait() -> () { + c_comment!(("NOP unless FPU instructions run in parallel with CPU instructions")); +} +#[no_mangle] +pub static mut FPU_PC: i32 = unsafe { 3i32 << 8i32 }; +#[no_mangle] +pub static mut FPU_RC: i32 = unsafe { 3i32 << 10i32 }; +#[no_mangle] +pub static mut FPU_IF: i32 = unsafe { 1i32 << 12i32 }; +#[no_mangle] +pub static mut FPU_EX_P: i32 = unsafe { 1i32 << 5i32 }; +#[no_mangle] +pub static mut FPU_EX_U: i32 = unsafe { 1i32 << 4i32 }; +#[no_mangle] +pub static mut FPU_EX_O: i32 = unsafe { 1i32 << 3i32 }; +#[no_mangle] +pub static mut FPU_EX_Z: i32 = unsafe { 1i32 << 2i32 }; +#[no_mangle] +pub static mut FPU_EX_D: i32 = unsafe { 1i32 << 1i32 }; diff --git a/src/rust/cpu2/global_pointers.rs b/src/rust/cpu2/global_pointers.rs new file mode 100644 index 00000000..42f635ae --- /dev/null +++ b/src/rust/cpu2/global_pointers.rs @@ -0,0 +1,749 @@ +#![allow +( dead_code , mutable_transmutes , non_camel_case_types , non_snake_case , +non_upper_case_globals , unused_mut )] +#![feature ( extern_types , libc )] + +extern "C" { + pub type reg128; + + pub type reg64; + #[no_mangle] + fn __fpclassifyl(_: f64) -> i32; + #[no_mangle] + static FLAG_CARRY: i32; + #[no_mangle] + static FLAG_PARITY: i32; + #[no_mangle] + static FLAG_ADJUST: i32; + #[no_mangle] + static FLAG_ZERO: i32; + #[no_mangle] + static FLAG_SIGN: i32; + #[no_mangle] + static FLAG_TRAP: i32; + #[no_mangle] + static FLAG_INTERRUPT: i32; + #[no_mangle] + static FLAG_DIRECTION: i32; + #[no_mangle] + static FLAG_OVERFLOW: i32; + #[no_mangle] + static FLAG_IOPL: i32; + #[no_mangle] + static FLAG_NT: i32; + #[no_mangle] + static FLAG_RF: i32; + #[no_mangle] + static FLAG_VM: i32; + #[no_mangle] + static FLAG_AC: i32; + #[no_mangle] + static FLAG_VIF: i32; + #[no_mangle] + static FLAG_VIP: i32; + #[no_mangle] + static FLAG_ID: i32; + #[no_mangle] + static FLAGS_DEFAULT: i32; + #[no_mangle] + static FLAGS_MASK: i32; + #[no_mangle] + static FLAGS_ALL: i32; + #[no_mangle] + static OPSIZE_8: i32; + #[no_mangle] + static OPSIZE_16: i32; + #[no_mangle] + static OPSIZE_32: i32; + #[no_mangle] + static EAX: i32; + #[no_mangle] + static ECX: i32; + #[no_mangle] + static EDX: i32; + #[no_mangle] + static EBX: i32; + #[no_mangle] + static ESP: i32; + #[no_mangle] + static EBP: i32; + #[no_mangle] + static ESI: i32; + #[no_mangle] + static EDI: i32; + #[no_mangle] + static AX: i32; + #[no_mangle] + static CX: i32; + #[no_mangle] + static DX: i32; + #[no_mangle] + static BX: i32; + #[no_mangle] + static SP: i32; + #[no_mangle] + static BP: i32; + #[no_mangle] + static SI: i32; + #[no_mangle] + static DI: i32; + #[no_mangle] + static AL: i32; + #[no_mangle] + static CL: i32; + #[no_mangle] + static DL: i32; + #[no_mangle] + static BL: i32; + #[no_mangle] + static AH: i32; + #[no_mangle] + static CH: i32; + #[no_mangle] + static DH: i32; + #[no_mangle] + static BH: i32; + #[no_mangle] + static ES: i32; + #[no_mangle] + static CS: i32; + #[no_mangle] + static SS: i32; + #[no_mangle] + static DS: i32; + #[no_mangle] + static FS: i32; + #[no_mangle] + static GS: i32; + #[no_mangle] + static TR: i32; + #[no_mangle] + static LDTR: i32; + #[no_mangle] + static PAGE_TABLE_PRESENT_MASK: i32; + #[no_mangle] + static PAGE_TABLE_RW_MASK: i32; + #[no_mangle] + static PAGE_TABLE_USER_MASK: i32; + #[no_mangle] + static PAGE_TABLE_ACCESSED_MASK: i32; + #[no_mangle] + static PAGE_TABLE_DIRTY_MASK: i32; + #[no_mangle] + static PAGE_TABLE_PSE_MASK: i32; + #[no_mangle] + static PAGE_TABLE_GLOBAL_MASK: i32; + #[no_mangle] + static MMAP_BLOCK_BITS: i32; + #[no_mangle] + static MMAP_BLOCK_SIZE: i32; + #[no_mangle] + static CR0_PE: i32; + #[no_mangle] + static CR0_MP: i32; + #[no_mangle] + static CR0_EM: i32; + #[no_mangle] + static CR0_TS: i32; + #[no_mangle] + static CR0_ET: i32; + #[no_mangle] + static CR0_WP: i32; + #[no_mangle] + static CR0_NW: i32; + #[no_mangle] + static CR0_CD: i32; + #[no_mangle] + static CR0_PG: i32; + #[no_mangle] + static CR4_VME: i32; + #[no_mangle] + static CR4_PVI: i32; + #[no_mangle] + static CR4_TSD: i32; + #[no_mangle] + static CR4_PSE: i32; + #[no_mangle] + static CR4_DE: i32; + #[no_mangle] + static CR4_PAE: i32; + #[no_mangle] + static CR4_PGE: i32; + #[no_mangle] + static IA32_SYSENTER_CS: i32; + #[no_mangle] + static IA32_SYSENTER_ESP: i32; + #[no_mangle] + static IA32_SYSENTER_EIP: i32; + #[no_mangle] + static IA32_TIME_STAMP_COUNTER: i32; + #[no_mangle] + static IA32_PLATFORM_ID: i32; + #[no_mangle] + static IA32_APIC_BASE_MSR: i32; + #[no_mangle] + static IA32_BIOS_SIGN_ID: i32; + #[no_mangle] + static MSR_PLATFORM_INFO: i32; + #[no_mangle] + static MSR_MISC_FEATURE_ENABLES: i32; + #[no_mangle] + static IA32_MISC_ENABLE: i32; + #[no_mangle] + static IA32_RTIT_CTL: i32; + #[no_mangle] + static MSR_SMI_COUNT: i32; + #[no_mangle] + static IA32_MCG_CAP: i32; + #[no_mangle] + static IA32_KERNEL_GS_BASE: i32; + #[no_mangle] + static MSR_PKG_C2_RESIDENCY: i32; + #[no_mangle] + static IA32_APIC_BASE_BSP: i32; + #[no_mangle] + static IA32_APIC_BASE_EXTD: i32; + #[no_mangle] + static IA32_APIC_BASE_EN: i32; + #[no_mangle] + static APIC_ADDRESS: i32; + #[no_mangle] + static SEG_PREFIX_NONE: i32; + #[no_mangle] + static SEG_PREFIX_ZERO: i32; + #[no_mangle] + static PREFIX_MASK_REP: i32; + #[no_mangle] + static PREFIX_REPZ: i32; + #[no_mangle] + static PREFIX_REPNZ: i32; + #[no_mangle] + static PREFIX_MASK_SEGMENT: i32; + #[no_mangle] + static PREFIX_MASK_OPSIZE: i32; + #[no_mangle] + static PREFIX_MASK_ADDRSIZE: i32; + #[no_mangle] + static PREFIX_F2: i32; + #[no_mangle] + static PREFIX_F3: i32; + #[no_mangle] + static PREFIX_66: i32; + #[no_mangle] + static LOG_CPU: i32; + #[no_mangle] + static A20_MASK: i32; + #[no_mangle] + static A20_MASK16: i32; + #[no_mangle] + static A20_MASK32: i32; + #[no_mangle] + static MXCSR_MASK: i32; + +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed { + __f: f32, + __i: u32, +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_0 { + __f: f64, + __i: u64, +} +unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { + let mut __u: unnamed = unnamed { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { + let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x >= __y) as i32; +} +#[no_mangle] +pub static mut reg8: *mut u8 = unsafe { 4i32 as *mut u8 }; +#[no_mangle] +pub static mut reg16: *mut u16 = unsafe { 4i32 as *mut u16 }; +#[no_mangle] +pub static mut reg8s: *mut i8 = unsafe { 4i32 as *mut i8 }; +#[no_mangle] +pub static mut reg16s: *mut i16 = unsafe { 4i32 as *mut i16 }; +#[no_mangle] +pub static mut reg32s: *mut i32 = unsafe { 4i32 as *mut i32 }; +#[no_mangle] +pub static mut last_op1: *mut i32 = unsafe { 512i32 as *mut i32 }; +#[no_mangle] +pub static mut last_op2: *mut i32 = unsafe { 516i32 as *mut i32 }; +#[no_mangle] +pub static mut last_op_size: *mut i32 = unsafe { 520i32 as *mut i32 }; +#[no_mangle] +pub static mut last_add_result: *mut i32 = unsafe { 524i32 as *mut i32 }; +#[no_mangle] +pub static mut last_result: *mut i32 = unsafe { 528i32 as *mut i32 }; +#[no_mangle] +pub static mut flags_changed: *mut i32 = unsafe { 532i32 as *mut i32 }; +#[no_mangle] +pub static mut flags: *mut i32 = unsafe { 536i32 as *mut i32 }; +#[no_mangle] +pub static mut page_fault: *mut bool = unsafe { 540i32 as *mut bool }; +#[no_mangle] +pub static mut a20_enabled: *mut bool = unsafe { 552i32 as *mut bool }; +#[no_mangle] +pub static mut instruction_pointer: *mut i32 = unsafe { 556i32 as *mut i32 }; +#[no_mangle] +pub static mut previous_ip: *mut i32 = unsafe { 560i32 as *mut i32 }; +#[no_mangle] +pub static mut idtr_size: *mut i32 = unsafe { 564i32 as *mut i32 }; +#[no_mangle] +pub static mut idtr_offset: *mut i32 = unsafe { 568i32 as *mut i32 }; +#[no_mangle] +pub static mut gdtr_size: *mut i32 = unsafe { 572i32 as *mut i32 }; +#[no_mangle] +pub static mut gdtr_offset: *mut i32 = unsafe { 576i32 as *mut i32 }; +#[no_mangle] +pub static mut cr: *mut i32 = unsafe { 580i32 as *mut i32 }; +#[no_mangle] +pub static mut cpl: *mut u8 = unsafe { 612i32 as *mut u8 }; +#[no_mangle] +pub static mut in_hlt: *mut bool = unsafe { 616i32 as *mut bool }; +#[no_mangle] +pub static mut last_virt_eip: *mut i32 = unsafe { 620i32 as *mut i32 }; +#[no_mangle] +pub static mut eip_phys: *mut i32 = unsafe { 624i32 as *mut i32 }; +#[no_mangle] +pub static mut last_virt_esp: *mut i32 = unsafe { 628i32 as *mut i32 }; +#[no_mangle] +pub static mut esp_phys: *mut i32 = unsafe { 632i32 as *mut i32 }; +#[no_mangle] +pub static mut sysenter_cs: *mut i32 = unsafe { 636i32 as *mut i32 }; +#[no_mangle] +pub static mut sysenter_esp: *mut i32 = unsafe { 640i32 as *mut i32 }; +#[no_mangle] +pub static mut sysenter_eip: *mut i32 = unsafe { 644i32 as *mut i32 }; +#[no_mangle] +pub static mut prefixes: *mut u8 = unsafe { 648i32 as *mut u8 }; +#[no_mangle] +pub static mut timestamp_counter: *mut u32 = unsafe { 664i32 as *mut u32 }; +#[no_mangle] +pub static mut sreg: *mut u16 = unsafe { 668i32 as *mut u16 }; +#[no_mangle] +pub static mut dreg: *mut i32 = unsafe { 684i32 as *mut i32 }; +#[no_mangle] +pub static mut fw_value: *mut i32 = unsafe { 720i32 as *mut i32 }; +#[no_mangle] +pub static mut segment_is_null: *mut bool = unsafe { 724i32 as *mut bool }; +#[no_mangle] +pub static mut segment_offsets: *mut i32 = unsafe { 736i32 as *mut i32 }; +#[no_mangle] +pub static mut segment_limits: *mut u32 = unsafe { 768i32 as *mut u32 }; +#[no_mangle] +pub static mut protected_mode: *mut bool = unsafe { 800i32 as *mut bool }; +#[no_mangle] +pub static mut is_32: *mut bool = unsafe { 804i32 as *mut bool }; +#[no_mangle] +pub static mut stack_size_32: *mut bool = unsafe { 808i32 as *mut bool }; +#[no_mangle] +pub static mut memory_size: *mut u32 = unsafe { 812i32 as *mut u32 }; +#[no_mangle] +pub static mut fpu_stack_empty: *mut i32 = unsafe { 816i32 as *mut i32 }; +#[no_mangle] +pub static mut mxcsr: *mut i32 = unsafe { 824i32 as *mut i32 }; +#[no_mangle] +pub static mut reg_xmm: *mut reg128 = unsafe { 828i32 as *mut reg128 }; +#[no_mangle] +pub static mut current_tsc: *mut u64 = unsafe { 956i32 as *mut u64 }; +#[no_mangle] +pub static mut fpu_st: *mut f64 = unsafe { 968i32 as *mut f64 }; +#[no_mangle] +pub static mut fpu_st8: *mut u8 = unsafe { 968i32 as *mut u8 }; +#[no_mangle] +pub static mut fpu_st32: *mut i32 = unsafe { 968i32 as *mut i32 }; +#[no_mangle] +pub static mut fpu_stack_ptr: *mut u32 = unsafe { 1032i32 as *mut u32 }; +#[no_mangle] +pub static mut fpu_control_word: *mut i32 = unsafe { 1036i32 as *mut i32 }; +#[no_mangle] +pub static mut fpu_status_word: *mut i32 = unsafe { 1040i32 as *mut i32 }; +#[no_mangle] +pub static mut fpu_opcode: *mut i32 = unsafe { 1044i32 as *mut i32 }; +#[no_mangle] +pub static mut fpu_ip: *mut i32 = unsafe { 1048i32 as *mut i32 }; +#[no_mangle] +pub static mut fpu_ip_selector: *mut i32 = unsafe { 1052i32 as *mut i32 }; +#[no_mangle] +pub static mut fpu_dp: *mut i32 = unsafe { 1056i32 as *mut i32 }; +#[no_mangle] +pub static mut fpu_dp_selector: *mut i32 = unsafe { 1060i32 as *mut i32 }; +#[no_mangle] +pub static mut reg_mmx: *mut reg64 = unsafe { 1064i32 as *mut reg64 }; +#[no_mangle] +pub static mut opstats_buffer: *mut u32 = unsafe { 4096i32 as *mut u32 }; +#[no_mangle] +pub static mut opstats_buffer_0f: *mut u32 = unsafe { 5120i32 as *mut u32 }; +#[no_mangle] +pub static mut tlb_data: *mut i32 = unsafe { 4194304i32 as *mut i32 }; diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs new file mode 100644 index 00000000..cd5eb027 --- /dev/null +++ b/src/rust/cpu2/instructions.rs @@ -0,0 +1,5718 @@ +#![allow +( dead_code , mutable_transmutes , non_camel_case_types , non_snake_case , +non_upper_case_globals , unused_mut )] +#![feature ( extern_types , libc )] + +extern "C" { + + #[no_mangle] + fn add8(x: i32, y: i32) -> i32; + #[no_mangle] + fn add16(x: i32, y: i32) -> i32; + #[no_mangle] + fn add32(x: i32, y: i32) -> i32; + #[no_mangle] + fn sub8(x: i32, y: i32) -> i32; + #[no_mangle] + fn sub16(x: i32, y: i32) -> i32; + #[no_mangle] + fn sub32(x: i32, y: i32) -> i32; + #[no_mangle] + fn adc8(x: i32, y: i32) -> i32; + #[no_mangle] + fn adc16(x: i32, y: i32) -> i32; + #[no_mangle] + fn adc32(x: i32, y: i32) -> i32; + #[no_mangle] + fn sbb8(x: i32, y: i32) -> i32; + #[no_mangle] + fn sbb16(x: i32, y: i32) -> i32; + #[no_mangle] + fn sbb32(x: i32, y: i32) -> i32; + #[no_mangle] + fn cmp8(x: i32, y: i32) -> (); + #[no_mangle] + fn cmp16(x: i32, y: i32) -> (); + #[no_mangle] + fn cmp32(x: i32, y: i32) -> (); + #[no_mangle] + fn inc8(x: i32) -> i32; + #[no_mangle] + fn inc16(x: i32) -> i32; + #[no_mangle] + fn inc32(x: i32) -> i32; + #[no_mangle] + fn dec8(x: i32) -> i32; + #[no_mangle] + fn dec16(x: i32) -> i32; + #[no_mangle] + fn dec32(x: i32) -> i32; + #[no_mangle] + fn neg8(x: i32) -> i32; + #[no_mangle] + fn neg16(x: i32) -> i32; + #[no_mangle] + fn neg32(x: i32) -> i32; + #[no_mangle] + fn mul8(source_operand: i32) -> (); + #[no_mangle] + fn imul8(source_operand: i32) -> (); + #[no_mangle] + fn mul16(source_operand: u32) -> (); + #[no_mangle] + fn imul16(source_operand: i32) -> (); + #[no_mangle] + fn imul_reg16(operand1: i32, operand2: i32) -> i32; + #[no_mangle] + fn mul32(source_operand: i32) -> (); + #[no_mangle] + fn imul32(source_operand: i32) -> (); + #[no_mangle] + fn imul_reg32(operand1: i32, operand2: i32) -> i32; + #[no_mangle] + fn bcd_daa() -> (); + #[no_mangle] + fn bcd_das() -> (); + #[no_mangle] + fn bcd_aad(imm8: i32) -> (); + #[no_mangle] + fn bcd_aam(imm8: i32) -> (); + #[no_mangle] + fn bcd_aaa() -> (); + #[no_mangle] + fn bcd_aas() -> (); + #[no_mangle] + fn and8(x: i32, y: i32) -> i32; + #[no_mangle] + fn and16(x: i32, y: i32) -> i32; + #[no_mangle] + fn and32(x: i32, y: i32) -> i32; + #[no_mangle] + fn test8(x: i32, y: i32) -> (); + #[no_mangle] + fn test16(x: i32, y: i32) -> (); + #[no_mangle] + fn test32(x: i32, y: i32) -> (); + #[no_mangle] + fn or8(x: i32, y: i32) -> i32; + #[no_mangle] + fn or16(x: i32, y: i32) -> i32; + #[no_mangle] + fn or32(x: i32, y: i32) -> i32; + #[no_mangle] + fn xor8(x: i32, y: i32) -> i32; + #[no_mangle] + fn xor16(x: i32, y: i32) -> i32; + #[no_mangle] + fn xor32(x: i32, y: i32) -> i32; + #[no_mangle] + fn rol8(dest_operand: i32, count: i32) -> i32; + #[no_mangle] + fn rol16(dest_operand: i32, count: i32) -> i32; + #[no_mangle] + fn rol32(dest_operand: i32, count: i32) -> i32; + #[no_mangle] + fn rcl8(dest_operand: i32, count: i32) -> i32; + #[no_mangle] + fn rcl16(dest_operand: i32, count: i32) -> i32; + #[no_mangle] + fn rcl32(dest_operand: i32, count: i32) -> i32; + #[no_mangle] + fn ror8(dest_operand: i32, count: i32) -> i32; + #[no_mangle] + fn ror16(dest_operand: i32, count: i32) -> i32; + #[no_mangle] + fn ror32(dest_operand: i32, count: i32) -> i32; + #[no_mangle] + fn rcr8(dest_operand: i32, count: i32) -> i32; + #[no_mangle] + fn rcr16(dest_operand: i32, count: i32) -> i32; + #[no_mangle] + fn rcr32(dest_operand: i32, count: i32) -> i32; + #[no_mangle] + fn div8(source_operand: u32) -> (); + #[no_mangle] + fn idiv8(source_operand: i32) -> (); + #[no_mangle] + fn div16(source_operand: u32) -> (); + #[no_mangle] + fn idiv16(source_operand: i32) -> (); + #[no_mangle] + fn div32(source_operand: u32) -> (); + #[no_mangle] + fn idiv32(source_operand: i32) -> (); + #[no_mangle] + fn shl8(dest_operand: i32, count: i32) -> i32; + #[no_mangle] + fn shl16(dest_operand: i32, count: i32) -> i32; + #[no_mangle] + fn shl32(dest_operand: i32, count: i32) -> i32; + #[no_mangle] + fn shr8(dest_operand: i32, count: i32) -> i32; + #[no_mangle] + fn shr16(dest_operand: i32, count: i32) -> i32; + #[no_mangle] + fn shr32(dest_operand: i32, count: i32) -> i32; + #[no_mangle] + fn sar8(dest_operand: i32, count: i32) -> i32; + #[no_mangle] + fn sar16(dest_operand: i32, count: i32) -> i32; + #[no_mangle] + fn sar32(dest_operand: i32, count: i32) -> i32; + #[no_mangle] + static FLAG_CARRY: i32; + #[no_mangle] + static FLAG_PARITY: i32; + #[no_mangle] + static FLAG_ADJUST: i32; + #[no_mangle] + static FLAG_ZERO: i32; + #[no_mangle] + static FLAG_SIGN: i32; + #[no_mangle] + static FLAG_TRAP: i32; + #[no_mangle] + static FLAG_INTERRUPT: i32; + #[no_mangle] + static FLAG_DIRECTION: i32; + #[no_mangle] + static FLAG_OVERFLOW: i32; + #[no_mangle] + static FLAG_IOPL: i32; + #[no_mangle] + static FLAG_NT: i32; + #[no_mangle] + static FLAG_RF: i32; + #[no_mangle] + static FLAG_VM: i32; + #[no_mangle] + static FLAG_AC: i32; + #[no_mangle] + static FLAG_VIF: i32; + #[no_mangle] + static FLAG_VIP: i32; + #[no_mangle] + static FLAG_ID: i32; + #[no_mangle] + static FLAGS_DEFAULT: i32; + #[no_mangle] + static FLAGS_MASK: i32; + #[no_mangle] + static FLAGS_ALL: i32; + #[no_mangle] + static OPSIZE_8: i32; + #[no_mangle] + static OPSIZE_16: i32; + #[no_mangle] + static OPSIZE_32: i32; + #[no_mangle] + static EAX: i32; + #[no_mangle] + static ECX: i32; + #[no_mangle] + static EDX: i32; + #[no_mangle] + static EBX: i32; + #[no_mangle] + static ESP: i32; + #[no_mangle] + static EBP: i32; + #[no_mangle] + static ESI: i32; + #[no_mangle] + static EDI: i32; + #[no_mangle] + static AX: i32; + #[no_mangle] + static CX: i32; + #[no_mangle] + static DX: i32; + #[no_mangle] + static BX: i32; + #[no_mangle] + static SP: i32; + #[no_mangle] + static BP: i32; + #[no_mangle] + static SI: i32; + #[no_mangle] + static DI: i32; + #[no_mangle] + static AL: i32; + #[no_mangle] + static CL: i32; + #[no_mangle] + static DL: i32; + #[no_mangle] + static BL: i32; + #[no_mangle] + static AH: i32; + #[no_mangle] + static CH: i32; + #[no_mangle] + static DH: i32; + #[no_mangle] + static BH: i32; + #[no_mangle] + static ES: i32; + #[no_mangle] + static CS: i32; + #[no_mangle] + static SS: i32; + #[no_mangle] + static DS: i32; + #[no_mangle] + static FS: i32; + #[no_mangle] + static GS: i32; + #[no_mangle] + static TR: i32; + #[no_mangle] + static LDTR: i32; + #[no_mangle] + static PAGE_TABLE_PRESENT_MASK: i32; + #[no_mangle] + static PAGE_TABLE_RW_MASK: i32; + #[no_mangle] + static PAGE_TABLE_USER_MASK: i32; + #[no_mangle] + static PAGE_TABLE_ACCESSED_MASK: i32; + #[no_mangle] + static PAGE_TABLE_DIRTY_MASK: i32; + #[no_mangle] + static PAGE_TABLE_PSE_MASK: i32; + #[no_mangle] + static PAGE_TABLE_GLOBAL_MASK: i32; + #[no_mangle] + static MMAP_BLOCK_BITS: i32; + #[no_mangle] + static MMAP_BLOCK_SIZE: i32; + #[no_mangle] + static CR0_PE: i32; + #[no_mangle] + static CR0_MP: i32; + #[no_mangle] + static CR0_EM: i32; + #[no_mangle] + static CR0_TS: i32; + #[no_mangle] + static CR0_ET: i32; + #[no_mangle] + static CR0_WP: i32; + #[no_mangle] + static CR0_NW: i32; + #[no_mangle] + static CR0_CD: i32; + #[no_mangle] + static CR0_PG: i32; + #[no_mangle] + static CR4_VME: i32; + #[no_mangle] + static CR4_PVI: i32; + #[no_mangle] + static CR4_TSD: i32; + #[no_mangle] + static CR4_PSE: i32; + #[no_mangle] + static CR4_DE: i32; + #[no_mangle] + static CR4_PAE: i32; + #[no_mangle] + static CR4_PGE: i32; + #[no_mangle] + static IA32_SYSENTER_CS: i32; + #[no_mangle] + static IA32_SYSENTER_ESP: i32; + #[no_mangle] + static IA32_SYSENTER_EIP: i32; + #[no_mangle] + static IA32_TIME_STAMP_COUNTER: i32; + #[no_mangle] + static IA32_PLATFORM_ID: i32; + #[no_mangle] + static IA32_APIC_BASE_MSR: i32; + #[no_mangle] + static IA32_BIOS_SIGN_ID: i32; + #[no_mangle] + static MSR_PLATFORM_INFO: i32; + #[no_mangle] + static MSR_MISC_FEATURE_ENABLES: i32; + #[no_mangle] + static IA32_MISC_ENABLE: i32; + #[no_mangle] + static IA32_RTIT_CTL: i32; + #[no_mangle] + static MSR_SMI_COUNT: i32; + #[no_mangle] + static IA32_MCG_CAP: i32; + #[no_mangle] + static IA32_KERNEL_GS_BASE: i32; + #[no_mangle] + static MSR_PKG_C2_RESIDENCY: i32; + #[no_mangle] + static IA32_APIC_BASE_BSP: i32; + #[no_mangle] + static IA32_APIC_BASE_EXTD: i32; + #[no_mangle] + static IA32_APIC_BASE_EN: i32; + #[no_mangle] + static APIC_ADDRESS: i32; + #[no_mangle] + static SEG_PREFIX_NONE: i32; + #[no_mangle] + static SEG_PREFIX_ZERO: i32; + #[no_mangle] + static PREFIX_MASK_REP: i32; + #[no_mangle] + static PREFIX_REPZ: i32; + #[no_mangle] + static PREFIX_REPNZ: i32; + #[no_mangle] + static PREFIX_MASK_SEGMENT: i32; + #[no_mangle] + static PREFIX_MASK_OPSIZE: i32; + #[no_mangle] + static PREFIX_MASK_ADDRSIZE: i32; + #[no_mangle] + static PREFIX_F2: i32; + #[no_mangle] + static PREFIX_F3: i32; + #[no_mangle] + static PREFIX_66: i32; + #[no_mangle] + static LOG_CPU: i32; + #[no_mangle] + static A20_MASK: i32; + #[no_mangle] + static A20_MASK16: i32; + #[no_mangle] + static A20_MASK32: i32; + #[no_mangle] + static MXCSR_MASK: i32; + #[no_mangle] + fn __fpclassifyl(_: f64) -> i32; + #[no_mangle] + fn atan2(_: f64, _: f64) -> f64; + #[no_mangle] + fn cos(_: f64) -> f64; + #[no_mangle] + fn fabs(_: f64) -> f64; + #[no_mangle] + fn fmod(_: f64, _: f64) -> f64; + #[no_mangle] + fn log(_: f64) -> f64; + #[no_mangle] + fn pow(_: f64, _: f64) -> f64; + #[no_mangle] + fn sin(_: f64) -> f64; + #[no_mangle] + fn sqrt(_: f64) -> f64; + #[no_mangle] + fn tan(_: f64) -> f64; + #[no_mangle] + fn trunc(_: f64) -> f64; + + #[no_mangle] + fn dbg_log(m: *const i8) -> (); + #[no_mangle] + fn dbg_log1(m: *const i8, x: i32) -> (); + #[no_mangle] + fn c_comment(m: *const i8) -> (); + #[no_mangle] + static mut mem8: *mut u8; + #[no_mangle] + static mut mem16: *mut u16; + #[no_mangle] + static mut mem32s: *mut i32; + #[no_mangle] + static mut jit_block_boundary: bool; + #[no_mangle] + static VALID_TLB_ENTRY_MAX: i32; + #[no_mangle] + static mut valid_tlb_entries: [i32; 10000]; + #[no_mangle] + static mut valid_tlb_entries_count: i32; + #[no_mangle] + static TLB_VALID: i32; + #[no_mangle] + static TLB_READONLY: i32; + #[no_mangle] + static TLB_NO_USER: i32; + #[no_mangle] + static TLB_IN_MAPPED_RANGE: i32; + #[no_mangle] + static TLB_GLOBAL: i32; + #[no_mangle] + static TLB_HAS_CODE: i32; + #[no_mangle] + static CPU_EXCEPTION_DE: i32; + #[no_mangle] + static CPU_EXCEPTION_DB: i32; + #[no_mangle] + static CPU_EXCEPTION_NMI: i32; + #[no_mangle] + static CPU_EXCEPTION_BP: i32; + #[no_mangle] + static CPU_EXCEPTION_OF: i32; + #[no_mangle] + static CPU_EXCEPTION_BR: i32; + #[no_mangle] + static CPU_EXCEPTION_UD: i32; + #[no_mangle] + static CPU_EXCEPTION_NM: i32; + #[no_mangle] + static CPU_EXCEPTION_DF: i32; + #[no_mangle] + static CPU_EXCEPTION_TS: i32; + #[no_mangle] + static CPU_EXCEPTION_NP: i32; + #[no_mangle] + static CPU_EXCEPTION_SS: i32; + #[no_mangle] + static CPU_EXCEPTION_GP: i32; + #[no_mangle] + static CPU_EXCEPTION_PF: i32; + #[no_mangle] + static CPU_EXCEPTION_MF: i32; + #[no_mangle] + static CPU_EXCEPTION_AC: i32; + #[no_mangle] + static CPU_EXCEPTION_MC: i32; + #[no_mangle] + static CPU_EXCEPTION_XM: i32; + #[no_mangle] + static CPU_EXCEPTION_VE: i32; + #[no_mangle] + fn get_eflags() -> i32; + #[no_mangle] + fn translate_address_read(address: i32) -> u32; + #[no_mangle] + fn read_imm8() -> i32; + #[no_mangle] + fn is_asize_32() -> bool; + #[no_mangle] + fn get_seg_cs() -> i32; + #[no_mangle] + fn get_seg_ss() -> i32; + #[no_mangle] + fn get_seg_prefix(default_segment: i32) -> i32; + #[no_mangle] + fn get_seg_prefix_ds(offset: i32) -> i32; + #[no_mangle] + fn run_prefix_instruction() -> (); + #[no_mangle] + fn segment_prefix_op(seg: i32) -> (); + #[no_mangle] + fn trigger_ud() -> (); + #[no_mangle] + fn trigger_nm() -> (); + #[no_mangle] + fn trigger_gp_non_raising(code: i32) -> (); + #[no_mangle] + fn safe_read8(addr: i32) -> i32; + #[no_mangle] + fn safe_read16(addr: i32) -> i32; + #[no_mangle] + fn safe_read32s(address: i32) -> i32; + #[no_mangle] + fn safe_write8(addr: i32, value: i32) -> (); + #[no_mangle] + fn safe_write16(addr: i32, value: i32) -> (); + #[no_mangle] + fn safe_write32(address: i32, value: i32) -> (); + #[no_mangle] + fn get_reg8_index(index: i32) -> i32; + #[no_mangle] + fn read_reg8(index: i32) -> i32; + #[no_mangle] + fn write_reg8(index: i32, value: i32) -> (); + #[no_mangle] + fn get_reg16_index(index: i32) -> i32; + #[no_mangle] + fn read_reg16(index: i32) -> i32; + #[no_mangle] + fn write_reg16(index: i32, value: i32) -> (); + #[no_mangle] + fn read_reg32(index: i32) -> i32; + #[no_mangle] + fn write_reg32(index: i32, value: i32) -> (); + #[no_mangle] + fn get_real_eip() -> i32; + #[no_mangle] + fn set_stack_reg(value: i32) -> (); + #[no_mangle] + fn vm86_mode() -> bool; + #[no_mangle] + fn getiopl() -> i32; + #[no_mangle] + static M_LOG2E: f64; + #[no_mangle] + static M_LN2: f64; + #[no_mangle] + static M_LN10: f64; + #[no_mangle] + static M_PI: f64; + #[no_mangle] + static FPU_C0: i32; + #[no_mangle] + static FPU_C1: i32; + #[no_mangle] + static FPU_C2: i32; + #[no_mangle] + static FPU_C3: i32; + #[no_mangle] + static FPU_RESULT_FLAGS: i32; + #[no_mangle] + static FPU_STACK_TOP: i32; + #[no_mangle] + fn fpu_get_st0() -> f64; + #[no_mangle] + fn fpu_get_sti(i: i32) -> f64; + #[no_mangle] + fn fpu_integer_round(f: f64) -> f64; + #[no_mangle] + fn fpu_load_m32(addr: i32) -> f64; + #[no_mangle] + fn fpu_load_m64(addr: i32) -> f64; + #[no_mangle] + fn fpu_fadd(target_index: i32, val: f64) -> (); + #[no_mangle] + fn fpu_fclex() -> (); + #[no_mangle] + fn fpu_fcmovcc(condition: bool, r: i32) -> (); + #[no_mangle] + fn fpu_fcom(y: f64) -> (); + #[no_mangle] + fn fpu_fcomi(r: i32) -> (); + #[no_mangle] + fn fpu_fcomip(r: i32) -> (); + #[no_mangle] + fn fpu_fcomp(val: f64) -> (); + #[no_mangle] + fn fpu_fdiv(target_index: i32, val: f64) -> (); + #[no_mangle] + fn fpu_fdivr(target_index: i32, val: f64) -> (); + #[no_mangle] + fn fpu_ffree(r: i32) -> (); + #[no_mangle] + fn fpu_fildm64(addr: i32) -> (); + #[no_mangle] + fn fpu_finit() -> (); + #[no_mangle] + fn fpu_fistm16(addr: i32) -> (); + #[no_mangle] + fn fpu_fistm16p(addr: i32) -> (); + #[no_mangle] + fn fpu_fistm32(addr: i32) -> (); + #[no_mangle] + fn fpu_fistm32p(addr: i32) -> (); + #[no_mangle] + fn fpu_fistm64p(addr: i32) -> (); + #[no_mangle] + fn fpu_fldcw(addr: i32) -> (); + #[no_mangle] + fn fpu_fldenv(addr: i32) -> (); + #[no_mangle] + fn fpu_fldm32(addr: i32) -> (); + #[no_mangle] + fn fpu_fldm64(addr: i32) -> (); + #[no_mangle] + fn fpu_fldm80(addr: i32) -> (); + #[no_mangle] + fn fpu_fmul(target_index: i32, val: f64) -> (); + #[no_mangle] + fn fpu_fnstsw_mem(addr: i32) -> (); + #[no_mangle] + fn fpu_fnstsw_reg() -> (); + #[no_mangle] + fn fpu_fprem() -> (); + #[no_mangle] + fn fpu_frstor(addr: i32) -> (); + #[no_mangle] + fn fpu_fsave(addr: i32) -> (); + #[no_mangle] + fn fpu_fst(r: i32) -> (); + #[no_mangle] + fn fpu_fst80p(addr: i32) -> (); + #[no_mangle] + fn fpu_fstcw(addr: i32) -> (); + #[no_mangle] + fn fpu_fstenv(addr: i32) -> (); + #[no_mangle] + fn fpu_fstm32(addr: i32) -> (); + #[no_mangle] + fn fpu_fstm32p(addr: i32) -> (); + #[no_mangle] + fn fpu_fstm64(addr: i32) -> (); + #[no_mangle] + fn fpu_fstm64p(addr: i32) -> (); + #[no_mangle] + fn fpu_fstp(r: i32) -> (); + #[no_mangle] + fn fpu_fsub(target_index: i32, val: f64) -> (); + #[no_mangle] + fn fpu_fsubr(target_index: i32, val: f64) -> (); + #[no_mangle] + fn fpu_ftst(x: f64) -> (); + #[no_mangle] + fn fpu_fucom(r: i32) -> (); + #[no_mangle] + fn fpu_fucomi(r: i32) -> (); + #[no_mangle] + fn fpu_fucomip(r: i32) -> (); + #[no_mangle] + fn fpu_fucomp(r: i32) -> (); + #[no_mangle] + fn fpu_fucompp() -> (); + #[no_mangle] + fn fpu_fxam(x: f64) -> (); + #[no_mangle] + fn fpu_fxch(i: i32) -> (); + #[no_mangle] + fn fpu_fxtract() -> (); + #[no_mangle] + fn fpu_pop() -> (); + #[no_mangle] + fn fpu_push(x: f64) -> (); + #[no_mangle] + fn fwait() -> (); + #[no_mangle] + static reg8: *mut u8; + #[no_mangle] + static reg16: *mut u16; + #[no_mangle] + static reg8s: *mut i8; + #[no_mangle] + static reg16s: *mut i16; + #[no_mangle] + static reg32s: *mut i32; + #[no_mangle] + static last_op1: *mut i32; + #[no_mangle] + static last_op2: *mut i32; + #[no_mangle] + static last_op_size: *mut i32; + #[no_mangle] + static last_add_result: *mut i32; + #[no_mangle] + static last_result: *mut i32; + #[no_mangle] + static flags_changed: *mut i32; + #[no_mangle] + static flags: *mut i32; + #[no_mangle] + static page_fault: *mut bool; + #[no_mangle] + static a20_enabled: *mut bool; + #[no_mangle] + static instruction_pointer: *mut i32; + #[no_mangle] + static previous_ip: *mut i32; + #[no_mangle] + static idtr_size: *mut i32; + #[no_mangle] + static idtr_offset: *mut i32; + #[no_mangle] + static gdtr_size: *mut i32; + #[no_mangle] + static gdtr_offset: *mut i32; + #[no_mangle] + static cr: *mut i32; + #[no_mangle] + static cpl: *mut u8; + #[no_mangle] + static in_hlt: *mut bool; + #[no_mangle] + static last_virt_eip: *mut i32; + #[no_mangle] + static eip_phys: *mut i32; + #[no_mangle] + static last_virt_esp: *mut i32; + #[no_mangle] + static esp_phys: *mut i32; + #[no_mangle] + static sysenter_cs: *mut i32; + #[no_mangle] + static sysenter_esp: *mut i32; + #[no_mangle] + static sysenter_eip: *mut i32; + #[no_mangle] + static prefixes: *mut u8; + #[no_mangle] + static timestamp_counter: *mut u32; + #[no_mangle] + static sreg: *mut u16; + #[no_mangle] + static dreg: *mut i32; + #[no_mangle] + static fw_value: *mut i32; + #[no_mangle] + static segment_is_null: *mut bool; + #[no_mangle] + static segment_offsets: *mut i32; + #[no_mangle] + static segment_limits: *mut u32; + #[no_mangle] + static protected_mode: *mut bool; + #[no_mangle] + static is_32: *mut bool; + #[no_mangle] + static stack_size_32: *mut bool; + #[no_mangle] + static memory_size: *mut u32; + #[no_mangle] + static fpu_stack_empty: *mut i32; + #[no_mangle] + static mxcsr: *mut i32; + #[no_mangle] + static reg_xmm: *mut reg128; + #[no_mangle] + static current_tsc: *mut u64; + #[no_mangle] + static fpu_st: *mut f64; + #[no_mangle] + static fpu_st8: *mut u8; + #[no_mangle] + static fpu_st32: *mut i32; + #[no_mangle] + static fpu_stack_ptr: *mut u32; + #[no_mangle] + static fpu_control_word: *mut i32; + #[no_mangle] + static fpu_status_word: *mut i32; + #[no_mangle] + static fpu_opcode: *mut i32; + #[no_mangle] + static fpu_ip: *mut i32; + #[no_mangle] + static fpu_ip_selector: *mut i32; + #[no_mangle] + static fpu_dp: *mut i32; + #[no_mangle] + static fpu_dp_selector: *mut i32; + #[no_mangle] + static reg_mmx: *mut reg64; + #[no_mangle] + static opstats_buffer: *mut u32; + #[no_mangle] + static opstats_buffer_0f: *mut u32; + #[no_mangle] + static tlb_data: *mut i32; + #[no_mangle] + #[no_mangle] + #[no_mangle] + #[no_mangle] + fn push16(imm16: i32) -> (); + #[no_mangle] + fn push32(imm32: i32) -> (); + #[no_mangle] + fn adjust_stack_reg(adjustment: i32) -> (); + #[no_mangle] + fn get_stack_pointer(offset: i32) -> i32; + #[no_mangle] + fn switch_seg(_: i32, _: i32) -> bool; + #[no_mangle] + fn run_instruction0f_16(opcode: i32) -> (); + #[no_mangle] + fn run_instruction0f_32(opcode: i32) -> (); + #[no_mangle] + fn pop16() -> i32; + #[no_mangle] + fn pop32s() -> i32; + #[no_mangle] + fn pusha16() -> (); + #[no_mangle] + fn pusha32() -> (); + #[no_mangle] + fn popa16() -> (); + #[no_mangle] + fn popa32() -> (); + #[no_mangle] + fn arpl(_: i32, _: i32) -> i32; + #[no_mangle] + fn insb_no_rep() -> (); + #[no_mangle] + fn insw_no_rep() -> (); + #[no_mangle] + fn insd_no_rep() -> (); + #[no_mangle] + fn outsb_no_rep() -> (); + #[no_mangle] + fn outsw_no_rep() -> (); + #[no_mangle] + fn outsd_no_rep() -> (); + #[no_mangle] + fn xchg8(data: i32, r8: i32) -> i32; + #[no_mangle] + fn xchg16(data: i32, r16: i32) -> i32; + #[no_mangle] + fn xchg32(data: i32, r32: i32) -> i32; + #[no_mangle] + fn xchg16r(r16: i32) -> (); + #[no_mangle] + fn xchg32r(r32: i32) -> (); + #[no_mangle] + fn far_jump(_: i32, _: i32, _: i32) -> (); + #[no_mangle] + fn handle_irqs() -> (); + #[no_mangle] + fn update_eflags(_: i32) -> (); + #[no_mangle] + fn movsb_no_rep() -> (); + #[no_mangle] + fn movsw_no_rep() -> (); + #[no_mangle] + fn movsd_no_rep() -> (); + #[no_mangle] + fn cmpsb_no_rep() -> (); + #[no_mangle] + fn cmpsw_no_rep() -> (); + #[no_mangle] + fn cmpsd_no_rep() -> (); + #[no_mangle] + fn stosb_no_rep() -> (); + #[no_mangle] + fn stosw_no_rep() -> (); + #[no_mangle] + fn stosd_no_rep() -> (); + #[no_mangle] + fn lodsb_no_rep() -> (); + #[no_mangle] + fn lodsw_no_rep() -> (); + #[no_mangle] + fn lodsd_no_rep() -> (); + #[no_mangle] + fn scasb_no_rep() -> (); + #[no_mangle] + fn scasw_no_rep() -> (); + #[no_mangle] + fn scasd_no_rep() -> (); + #[no_mangle] + fn lss16(_: i32, _: i32, _: i32) -> (); + #[no_mangle] + fn lss32(_: i32, _: i32, _: i32) -> (); + #[no_mangle] + fn enter16(_: i32, _: i32) -> (); + #[no_mangle] + fn enter32(_: i32, _: i32) -> (); + #[no_mangle] + fn far_return(_: i32, _: i32, _: i32) -> (); + #[no_mangle] + fn call_interrupt_vector( + interrupt_nr: i32, + is_software_int: bool, + has_error_code: bool, + error_code: i32, + ) -> (); + #[no_mangle] + fn getof() -> bool; + #[no_mangle] + fn iret16() -> (); + #[no_mangle] + fn iret32() -> (); + #[no_mangle] + fn getcf() -> bool; + #[no_mangle] + fn io_port_read8(_: i32) -> i32; + #[no_mangle] + fn test_privileges_for_io(_: i32, _: i32) -> bool; + #[no_mangle] + fn io_port_read16(_: i32) -> i32; + #[no_mangle] + fn io_port_read32(_: i32) -> i32; + #[no_mangle] + fn io_port_write8(_: i32, _: i32) -> (); + #[no_mangle] + fn io_port_write16(_: i32, _: i32) -> (); + #[no_mangle] + fn io_port_write32(_: i32, _: i32) -> (); + #[no_mangle] + fn jmp_rel16(rel16: i32) -> (); + #[no_mangle] + fn hlt_op() -> (); + #[no_mangle] + fn test_o() -> bool; + #[no_mangle] + fn test_b() -> bool; + #[no_mangle] + fn test_z() -> bool; + #[no_mangle] + fn test_s() -> bool; + #[no_mangle] + fn test_p() -> bool; + #[no_mangle] + fn test_be() -> bool; + #[no_mangle] + fn test_l() -> bool; + #[no_mangle] + fn test_le() -> bool; + #[no_mangle] + fn jmpcc16(condition: bool, imm16: i32) -> (); + #[no_mangle] + fn jmpcc32(condition: bool, imm32: i32) -> (); + #[no_mangle] + fn loope16(imm8s: i32) -> (); + #[no_mangle] + fn loopne16(imm8s: i32) -> (); + #[no_mangle] + fn loop16(imm8s: i32) -> (); + #[no_mangle] + fn jcxz16(imm8s: i32) -> (); + #[no_mangle] + fn loope32(imm8s: i32) -> (); + #[no_mangle] + fn loopne32(imm8s: i32) -> (); + #[no_mangle] + fn loop32(imm8s: i32) -> (); + #[no_mangle] + fn jcxz32(imm8s: i32) -> (); + #[no_mangle] + static mut profiler_stat_arr: [profiler_stat; 37]; + #[no_mangle] + fn movsb_rep() -> (); + #[no_mangle] + fn movsw_rep() -> (); + #[no_mangle] + fn movsd_rep() -> (); + #[no_mangle] + fn cmpsb_rep(_: i32) -> (); + #[no_mangle] + fn cmpsw_rep(_: i32) -> (); + #[no_mangle] + fn cmpsd_rep(_: i32) -> (); + #[no_mangle] + fn stosb_rep() -> (); + #[no_mangle] + fn stosw_rep() -> (); + #[no_mangle] + fn stosd_rep() -> (); + #[no_mangle] + fn lodsb_rep() -> (); + #[no_mangle] + fn lodsw_rep() -> (); + #[no_mangle] + fn lodsd_rep() -> (); + #[no_mangle] + fn scasb_rep(_: i32) -> (); + #[no_mangle] + fn scasw_rep(_: i32) -> (); + #[no_mangle] + fn scasd_rep(_: i32) -> (); + #[no_mangle] + fn insb_rep() -> (); + #[no_mangle] + fn insw_rep() -> (); + #[no_mangle] + fn insd_rep() -> (); + #[no_mangle] + fn outsb_rep() -> (); + #[no_mangle] + fn outsw_rep() -> (); + #[no_mangle] + fn outsd_rep() -> (); +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed { + __f: f32, + __i: u32, +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub struct profiler_stat { + pub count: i32, +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union reg64 { + i8_0: [i8; 8], + i16_0: [i16; 4], + i32_0: [i32; 2], + i64_0: [i64; 1], + u8_0: [u8; 8], + u16_0: [u16; 4], + u32_0: [u32; 2], + u64_0: [u64; 1], + f32_0: [f32; 2], + f64_0: [f64; 1], +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_0 { + __f: f64, + __i: u64, +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union reg128 { + i8_0: [i8; 16], + i16_0: [i16; 8], + i32_0: [i32; 4], + i64_0: [i64; 2], + u8_0: [u8; 16], + u16_0: [u16; 8], + u32_0: [u32; 4], + u64_0: [u64; 2], + f32_0: [f32; 4], + f64_0: [f64; 2], +} + +unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { + let mut __u: unnamed = unnamed { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { + let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x >= __y) as i32; +} +#[no_mangle] +pub unsafe extern "C" fn instr_00_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE8!(___, addr, add8(___, read_reg8(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_00_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, add8(____0, read_reg8(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_01_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE16!(___, addr, add16(___, read_reg16(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_01_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, add16(____0, read_reg16(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_01_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE32!(___, addr, add32(___, read_reg32(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_01_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, add32(____0, read_reg32(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_02_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read8(addr); + write_reg8(r, add8(read_reg8(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_02_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r, add8(read_reg8(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_03_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + write_reg16(r, add16(read_reg16(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_03_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r, add16(read_reg16(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_03_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + write_reg32(r, add32(read_reg32(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_03_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r, add32(read_reg32(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_04(mut imm8: i32) -> () { + *reg8.offset(AL as isize) = add8(*reg8.offset(AL as isize) as i32, imm8) as u8; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_05(mut imm16: i32) -> () { + *reg16.offset(AX as isize) = add16(*reg16.offset(AX as isize) as i32, imm16) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_05(mut imm32: i32) -> () { + *reg32s.offset(EAX as isize) = add32(*reg32s.offset(EAX as isize), imm32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_06() -> () { push16(*sreg.offset(ES as isize) as i32); } +#[no_mangle] +pub unsafe extern "C" fn instr32_06() -> () { push32(*sreg.offset(ES as isize) as i32); } +#[no_mangle] +pub unsafe extern "C" fn instr16_07() -> () { + if !switch_seg(ES, safe_read16(get_stack_pointer(0i32))) { + return; + } + else { + adjust_stack_reg(2i32); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_07() -> () { + if !switch_seg(ES, safe_read32s(get_stack_pointer(0i32)) & 65535i32) { + return; + } + else { + adjust_stack_reg(4i32); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_08_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE8!(___, addr, or8(___, read_reg8(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_08_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, or8(____0, read_reg8(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_09_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE16!(___, addr, or16(___, read_reg16(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_09_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, or16(____0, read_reg16(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_09_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE32!(___, addr, or32(___, read_reg32(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_09_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, or32(____0, read_reg32(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0A_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read8(addr); + write_reg8(r, or8(read_reg8(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0A_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r, or8(read_reg8(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0B_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + write_reg16(r, or16(read_reg16(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0B_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r, or16(read_reg16(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0B_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + write_reg32(r, or32(read_reg32(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0B_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r, or32(read_reg32(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0C(mut imm8: i32) -> () { + *reg8.offset(AL as isize) = or8(*reg8.offset(AL as isize) as i32, imm8) as u8; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0D(mut imm16: i32) -> () { + *reg16.offset(AX as isize) = or16(*reg16.offset(AX as isize) as i32, imm16) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0D(mut imm32: i32) -> () { + *reg32s.offset(EAX as isize) = or32(*reg32s.offset(EAX as isize), imm32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0E() -> () { push16(*sreg.offset(CS as isize) as i32); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0E() -> () { push32(*sreg.offset(CS as isize) as i32); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0F() -> () { run_instruction0f_16(read_imm8()); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0F() -> () { run_instruction0f_32(read_imm8()); } +#[no_mangle] +pub unsafe extern "C" fn instr_10_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE8!(___, addr, adc8(___, read_reg8(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_10_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, adc8(____0, read_reg8(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_11_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE16!(___, addr, adc16(___, read_reg16(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_11_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, adc16(____0, read_reg16(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_11_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE32!(___, addr, adc32(___, read_reg32(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_11_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, adc32(____0, read_reg32(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_12_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read8(addr); + write_reg8(r, adc8(read_reg8(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_12_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r, adc8(read_reg8(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_13_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + write_reg16(r, adc16(read_reg16(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_13_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r, adc16(read_reg16(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_13_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + write_reg32(r, adc32(read_reg32(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_13_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r, adc32(read_reg32(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_14(mut imm8: i32) -> () { + *reg8.offset(AL as isize) = adc8(*reg8.offset(AL as isize) as i32, imm8) as u8; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_15(mut imm16: i32) -> () { + *reg16.offset(AX as isize) = adc16(*reg16.offset(AX as isize) as i32, imm16) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_15(mut imm32: i32) -> () { + *reg32s.offset(EAX as isize) = adc32(*reg32s.offset(EAX as isize), imm32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_16() -> () { push16(*sreg.offset(SS as isize) as i32); } +#[no_mangle] +pub unsafe extern "C" fn instr32_16() -> () { push32(*sreg.offset(SS as isize) as i32); } +#[no_mangle] +pub unsafe extern "C" fn instr16_17() -> () { + if !switch_seg(SS, safe_read16(get_stack_pointer(0i32))) { + return; + } + else { + adjust_stack_reg(2i32); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_17() -> () { + if !switch_seg(SS, safe_read32s(get_stack_pointer(0i32)) & 65535i32) { + return; + } + else { + adjust_stack_reg(4i32); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_18_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE8!(___, addr, sbb8(___, read_reg8(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_18_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, sbb8(____0, read_reg8(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_19_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE16!(___, addr, sbb16(___, read_reg16(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_19_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, sbb16(____0, read_reg16(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_19_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE32!(___, addr, sbb32(___, read_reg32(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_19_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, sbb32(____0, read_reg32(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_1A_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read8(addr); + write_reg8(r, sbb8(read_reg8(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_1A_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r, sbb8(read_reg8(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_1B_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + write_reg16(r, sbb16(read_reg16(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_1B_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r, sbb16(read_reg16(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_1B_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + write_reg32(r, sbb32(read_reg32(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_1B_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r, sbb32(read_reg32(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_1C(mut imm8: i32) -> () { + *reg8.offset(AL as isize) = sbb8(*reg8.offset(AL as isize) as i32, imm8) as u8; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_1D(mut imm16: i32) -> () { + *reg16.offset(AX as isize) = sbb16(*reg16.offset(AX as isize) as i32, imm16) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_1D(mut imm32: i32) -> () { + *reg32s.offset(EAX as isize) = sbb32(*reg32s.offset(EAX as isize), imm32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_1E() -> () { push16(*sreg.offset(DS as isize) as i32); } +#[no_mangle] +pub unsafe extern "C" fn instr32_1E() -> () { push32(*sreg.offset(DS as isize) as i32); } +#[no_mangle] +pub unsafe extern "C" fn instr16_1F() -> () { + if !switch_seg(DS, safe_read16(get_stack_pointer(0i32))) { + return; + } + else { + adjust_stack_reg(2i32); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_1F() -> () { + if !switch_seg(DS, safe_read32s(get_stack_pointer(0i32)) & 65535i32) { + return; + } + else { + adjust_stack_reg(4i32); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_20_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE8!(___, addr, and8(___, read_reg8(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_20_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, and8(____0, read_reg8(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_21_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE16!(___, addr, and16(___, read_reg16(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_21_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, and16(____0, read_reg16(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_21_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE32!(___, addr, and32(___, read_reg32(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_21_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, and32(____0, read_reg32(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_22_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read8(addr); + write_reg8(r, and8(read_reg8(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_22_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r, and8(read_reg8(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_23_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + write_reg16(r, and16(read_reg16(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_23_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r, and16(read_reg16(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_23_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + write_reg32(r, and32(read_reg32(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_23_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r, and32(read_reg32(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_24(mut imm8: i32) -> () { + *reg8.offset(AL as isize) = and8(*reg8.offset(AL as isize) as i32, imm8) as u8; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_25(mut imm16: i32) -> () { + *reg16.offset(AX as isize) = and16(*reg16.offset(AX as isize) as i32, imm16) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_25(mut imm32: i32) -> () { + *reg32s.offset(EAX as isize) = and32(*reg32s.offset(EAX as isize), imm32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_26() -> () { segment_prefix_op(ES); } +#[no_mangle] +pub unsafe extern "C" fn instr_27() -> () { bcd_daa(); } +#[no_mangle] +pub unsafe extern "C" fn instr_28_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE8!(___, addr, sub8(___, read_reg8(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_28_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, sub8(____0, read_reg8(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_29_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE16!(___, addr, sub16(___, read_reg16(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_29_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, sub16(____0, read_reg16(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_29_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE32!(___, addr, sub32(___, read_reg32(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_29_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, sub32(____0, read_reg32(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_2A_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read8(addr); + write_reg8(r, sub8(read_reg8(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_2A_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r, sub8(read_reg8(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_2B_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + write_reg16(r, sub16(read_reg16(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_2B_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r, sub16(read_reg16(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_2B_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + write_reg32(r, sub32(read_reg32(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_2B_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r, sub32(read_reg32(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_2C(mut imm8: i32) -> () { + *reg8.offset(AL as isize) = sub8(*reg8.offset(AL as isize) as i32, imm8) as u8; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_2D(mut imm16: i32) -> () { + *reg16.offset(AX as isize) = sub16(*reg16.offset(AX as isize) as i32, imm16) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_2D(mut imm32: i32) -> () { + *reg32s.offset(EAX as isize) = sub32(*reg32s.offset(EAX as isize), imm32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_2E() -> () { segment_prefix_op(CS); } +#[no_mangle] +pub unsafe extern "C" fn instr_2F() -> () { bcd_das(); } +#[no_mangle] +pub unsafe extern "C" fn instr_30_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE8!(___, addr, xor8(___, read_reg8(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_30_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, xor8(____0, read_reg8(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_31_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE16!(___, addr, xor16(___, read_reg16(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_31_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, xor16(____0, read_reg16(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_31_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE32!(___, addr, xor32(___, read_reg32(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_31_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, xor32(____0, read_reg32(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_32_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read8(addr); + write_reg8(r, xor8(read_reg8(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_32_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r, xor8(read_reg8(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_33_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + write_reg16(r, xor16(read_reg16(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_33_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r, xor16(read_reg16(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_33_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + write_reg32(r, xor32(read_reg32(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_33_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r, xor32(read_reg32(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_34(mut imm8: i32) -> () { + *reg8.offset(AL as isize) = xor8(*reg8.offset(AL as isize) as i32, imm8) as u8; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_35(mut imm16: i32) -> () { + *reg16.offset(AX as isize) = xor16(*reg16.offset(AX as isize) as i32, imm16) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_35(mut imm32: i32) -> () { + *reg32s.offset(EAX as isize) = xor32(*reg32s.offset(EAX as isize), imm32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_36() -> () { segment_prefix_op(SS); } +#[no_mangle] +pub unsafe extern "C" fn instr_37() -> () { bcd_aaa(); } +#[no_mangle] +pub unsafe extern "C" fn instr_38_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read8(addr); + cmp8(____0, read_reg8(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_38_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + cmp8(____0, read_reg8(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_39_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + cmp16(____0, read_reg16(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_39_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + cmp16(____0, read_reg16(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_39_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + cmp32(____0, read_reg32(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_39_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + cmp32(____0, read_reg32(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_3A_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read8(addr); + cmp8(read_reg8(r), ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_3A_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + cmp8(read_reg8(r), ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_3B_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + cmp16(read_reg16(r), ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_3B_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + cmp16(read_reg16(r), ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_3B_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + cmp32(read_reg32(r), ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_3B_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + cmp32(read_reg32(r), ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_3C(mut imm8: i32) -> () { + cmp8(*reg8.offset(AL as isize) as i32, imm8); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_3D(mut imm16: i32) -> () { + cmp16(*reg16.offset(AX as isize) as i32, imm16); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_3D(mut imm32: i32) -> () { + cmp32(*reg32s.offset(EAX as isize), imm32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_3E() -> () { segment_prefix_op(DS); } +#[no_mangle] +pub unsafe extern "C" fn instr_3F() -> () { bcd_aas(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_40() -> () { + *reg16.offset(AX as isize) = inc16(*reg16.offset(AX as isize) as i32) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_40() -> () { + *reg32s.offset(EAX as isize) = inc32(*reg32s.offset(EAX as isize)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_41() -> () { + *reg16.offset(CX as isize) = inc16(*reg16.offset(CX as isize) as i32) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_41() -> () { + *reg32s.offset(ECX as isize) = inc32(*reg32s.offset(ECX as isize)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_42() -> () { + *reg16.offset(DX as isize) = inc16(*reg16.offset(DX as isize) as i32) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_42() -> () { + *reg32s.offset(EDX as isize) = inc32(*reg32s.offset(EDX as isize)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_43() -> () { + *reg16.offset(BX as isize) = inc16(*reg16.offset(BX as isize) as i32) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_43() -> () { + *reg32s.offset(EBX as isize) = inc32(*reg32s.offset(EBX as isize)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_44() -> () { + *reg16.offset(SP as isize) = inc16(*reg16.offset(SP as isize) as i32) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_44() -> () { + *reg32s.offset(ESP as isize) = inc32(*reg32s.offset(ESP as isize)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_45() -> () { + *reg16.offset(BP as isize) = inc16(*reg16.offset(BP as isize) as i32) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_45() -> () { + *reg32s.offset(EBP as isize) = inc32(*reg32s.offset(EBP as isize)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_46() -> () { + *reg16.offset(SI as isize) = inc16(*reg16.offset(SI as isize) as i32) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_46() -> () { + *reg32s.offset(ESI as isize) = inc32(*reg32s.offset(ESI as isize)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_47() -> () { + *reg16.offset(DI as isize) = inc16(*reg16.offset(DI as isize) as i32) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_47() -> () { + *reg32s.offset(EDI as isize) = inc32(*reg32s.offset(EDI as isize)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_48() -> () { + *reg16.offset(AX as isize) = dec16(*reg16.offset(AX as isize) as i32) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_48() -> () { + *reg32s.offset(EAX as isize) = dec32(*reg32s.offset(EAX as isize)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_49() -> () { + *reg16.offset(CX as isize) = dec16(*reg16.offset(CX as isize) as i32) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_49() -> () { + *reg32s.offset(ECX as isize) = dec32(*reg32s.offset(ECX as isize)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_4A() -> () { + *reg16.offset(DX as isize) = dec16(*reg16.offset(DX as isize) as i32) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_4A() -> () { + *reg32s.offset(EDX as isize) = dec32(*reg32s.offset(EDX as isize)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_4B() -> () { + *reg16.offset(BX as isize) = dec16(*reg16.offset(BX as isize) as i32) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_4B() -> () { + *reg32s.offset(EBX as isize) = dec32(*reg32s.offset(EBX as isize)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_4C() -> () { + *reg16.offset(SP as isize) = dec16(*reg16.offset(SP as isize) as i32) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_4C() -> () { + *reg32s.offset(ESP as isize) = dec32(*reg32s.offset(ESP as isize)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_4D() -> () { + *reg16.offset(BP as isize) = dec16(*reg16.offset(BP as isize) as i32) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_4D() -> () { + *reg32s.offset(EBP as isize) = dec32(*reg32s.offset(EBP as isize)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_4E() -> () { + *reg16.offset(SI as isize) = dec16(*reg16.offset(SI as isize) as i32) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_4E() -> () { + *reg32s.offset(ESI as isize) = dec32(*reg32s.offset(ESI as isize)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_4F() -> () { + *reg16.offset(DI as isize) = dec16(*reg16.offset(DI as isize) as i32) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_4F() -> () { + *reg32s.offset(EDI as isize) = dec32(*reg32s.offset(EDI as isize)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_50() -> () { push16(*reg16.offset(AX as isize) as i32); } +#[no_mangle] +pub unsafe extern "C" fn instr32_50() -> () { push32(*reg32s.offset(EAX as isize)); } +#[no_mangle] +pub unsafe extern "C" fn instr16_51() -> () { push16(*reg16.offset(CX as isize) as i32); } +#[no_mangle] +pub unsafe extern "C" fn instr32_51() -> () { push32(*reg32s.offset(ECX as isize)); } +#[no_mangle] +pub unsafe extern "C" fn instr16_52() -> () { push16(*reg16.offset(DX as isize) as i32); } +#[no_mangle] +pub unsafe extern "C" fn instr32_52() -> () { push32(*reg32s.offset(EDX as isize)); } +#[no_mangle] +pub unsafe extern "C" fn instr16_53() -> () { push16(*reg16.offset(BX as isize) as i32); } +#[no_mangle] +pub unsafe extern "C" fn instr32_53() -> () { push32(*reg32s.offset(EBX as isize)); } +#[no_mangle] +pub unsafe extern "C" fn instr16_54() -> () { push16(*reg16.offset(SP as isize) as i32); } +#[no_mangle] +pub unsafe extern "C" fn instr32_54() -> () { push32(*reg32s.offset(ESP as isize)); } +#[no_mangle] +pub unsafe extern "C" fn instr16_55() -> () { push16(*reg16.offset(BP as isize) as i32); } +#[no_mangle] +pub unsafe extern "C" fn instr32_55() -> () { push32(*reg32s.offset(EBP as isize)); } +#[no_mangle] +pub unsafe extern "C" fn instr16_56() -> () { push16(*reg16.offset(SI as isize) as i32); } +#[no_mangle] +pub unsafe extern "C" fn instr32_56() -> () { push32(*reg32s.offset(ESI as isize)); } +#[no_mangle] +pub unsafe extern "C" fn instr16_57() -> () { push16(*reg16.offset(DI as isize) as i32); } +#[no_mangle] +pub unsafe extern "C" fn instr32_57() -> () { push32(*reg32s.offset(EDI as isize)); } +#[no_mangle] +pub unsafe extern "C" fn instr16_58() -> () { *reg16.offset(AX as isize) = pop16() as u16; } +#[no_mangle] +pub unsafe extern "C" fn instr32_58() -> () { *reg32s.offset(EAX as isize) = pop32s(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_59() -> () { *reg16.offset(CX as isize) = pop16() as u16; } +#[no_mangle] +pub unsafe extern "C" fn instr32_59() -> () { *reg32s.offset(ECX as isize) = pop32s(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_5A() -> () { *reg16.offset(DX as isize) = pop16() as u16; } +#[no_mangle] +pub unsafe extern "C" fn instr32_5A() -> () { *reg32s.offset(EDX as isize) = pop32s(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_5B() -> () { *reg16.offset(BX as isize) = pop16() as u16; } +#[no_mangle] +pub unsafe extern "C" fn instr32_5B() -> () { *reg32s.offset(EBX as isize) = pop32s(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_5C() -> () { + *reg16.offset(SP as isize) = safe_read16(get_stack_pointer(0i32)) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_5C() -> () { + *reg32s.offset(ESP as isize) = safe_read32s(get_stack_pointer(0i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_5D() -> () { *reg16.offset(BP as isize) = pop16() as u16; } +#[no_mangle] +pub unsafe extern "C" fn instr32_5D() -> () { *reg32s.offset(EBP as isize) = pop32s(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_5E() -> () { *reg16.offset(SI as isize) = pop16() as u16; } +#[no_mangle] +pub unsafe extern "C" fn instr32_5E() -> () { *reg32s.offset(ESI as isize) = pop32s(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_5F() -> () { *reg16.offset(DI as isize) = pop16() as u16; } +#[no_mangle] +pub unsafe extern "C" fn instr32_5F() -> () { *reg32s.offset(EDI as isize) = pop32s(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_60() -> () { pusha16(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_60() -> () { pusha32(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_61() -> () { popa16(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_61() -> () { popa32(); } +#[no_mangle] +pub unsafe extern "C" fn instr_62_reg(mut r2: i32, mut r: i32) -> () { + c_comment!(("bound")); + dbg_log_c!(("Unimplemented BOUND instruction")); + dbg_assert!(0 != 0i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_62_mem(mut addr: i32, mut r: i32) -> () { + dbg_log_c!(("Unimplemented BOUND instruction")); + dbg_assert!(0 != 0i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_63_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE16!(___, addr, arpl(___, read_reg16(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_63_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, arpl(____0, read_reg16(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_64() -> () { segment_prefix_op(FS); } +#[no_mangle] +pub unsafe extern "C" fn instr_65() -> () { segment_prefix_op(GS); } +#[no_mangle] +pub unsafe extern "C" fn instr_66() -> () { + c_comment!(("Operand-size override prefix")); + *prefixes = (*prefixes as i32 | PREFIX_MASK_OPSIZE) as u8; + run_prefix_instruction(); + *prefixes = 0i32 as u8; +} +#[no_mangle] +pub unsafe extern "C" fn instr_67() -> () { + c_comment!(("Address-size override prefix")); + dbg_assert!(is_asize_32() as i32 == *is_32 as i32); + *prefixes = (*prefixes as i32 | PREFIX_MASK_ADDRSIZE) as u8; + run_prefix_instruction(); + *prefixes = 0i32 as u8; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_68(mut imm16: i32) -> () { push16(imm16); } +#[no_mangle] +pub unsafe extern "C" fn instr32_68(mut imm32: i32) -> () { push32(imm32); } +#[no_mangle] +pub unsafe extern "C" fn instr16_69_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { + write_reg16( + r, + imul_reg16(safe_read16(addr) << 16i32 >> 16i32, imm << 16i32 >> 16i32), + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_69_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { + write_reg16( + r, + imul_reg16(read_reg16(r1) << 16i32 >> 16i32, imm << 16i32 >> 16i32), + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_69_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { + write_reg32(r, imul_reg32(safe_read32s(addr), imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_69_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { + write_reg32(r, imul_reg32(read_reg32(r1), imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_6A(mut imm8: i32) -> () { push16(imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr32_6A(mut imm8: i32) -> () { push32(imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr16_6B_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { + write_reg16(r, imul_reg16(safe_read16(addr) << 16i32 >> 16i32, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_6B_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { + write_reg16(r, imul_reg16(read_reg16(r1) << 16i32 >> 16i32, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_6B_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { + write_reg32(r, imul_reg32(safe_read32s(addr), imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_6B_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { + write_reg32(r, imul_reg32(read_reg32(r1), imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_6C() -> () { insb_no_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_6D() -> () { insw_no_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_6D() -> () { insd_no_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr_6E() -> () { outsb_no_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_6F() -> () { outsw_no_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_6F() -> () { outsd_no_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr_80_0_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE8!(___, addr, add8(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_80_0_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, add8(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_80_1_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE8!(___, addr, or8(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_80_1_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, or8(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_80_2_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE8!(___, addr, adc8(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_80_2_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, adc8(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_80_3_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE8!(___, addr, sbb8(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_80_3_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, sbb8(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_80_4_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE8!(___, addr, and8(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_80_4_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, and8(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_80_5_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE8!(___, addr, sub8(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_80_5_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, sub8(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_80_6_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE8!(___, addr, xor8(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_80_6_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, xor8(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_80_7_reg(mut r: i32, mut imm: i32) -> () { cmp8(read_reg8(r), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr_80_7_mem(mut addr: i32, mut imm: i32) -> () { + cmp8(safe_read8(addr), imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_81_0_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, add16(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_81_0_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, add16(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_81_1_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, or16(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_81_1_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, or16(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_81_2_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, adc16(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_81_2_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, adc16(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_81_3_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, sbb16(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_81_3_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, sbb16(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_81_4_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, and16(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_81_4_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, and16(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_81_5_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, sub16(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_81_5_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, sub16(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_81_6_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, xor16(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_81_6_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, xor16(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_81_7_reg(mut r: i32, mut imm: i32) -> () { + cmp16(read_reg16(r), imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_81_7_mem(mut addr: i32, mut imm: i32) -> () { + cmp16(safe_read16(addr), imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_81_0_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, add32(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_81_0_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, add32(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_81_1_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, or32(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_81_1_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, or32(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_81_2_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, adc32(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_81_2_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, adc32(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_81_3_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, sbb32(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_81_3_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, sbb32(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_81_4_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, and32(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_81_4_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, and32(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_81_5_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, sub32(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_81_5_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, sub32(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_81_6_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, xor32(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_81_6_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, xor32(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_81_7_reg(mut r: i32, mut imm: i32) -> () { + cmp32(read_reg32(r), imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_81_7_mem(mut addr: i32, mut imm: i32) -> () { + cmp32(safe_read32s(addr), imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_82_0_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE8!(___, addr, add8(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_82_0_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, add8(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_82_1_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE8!(___, addr, or8(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_82_1_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, or8(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_82_2_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE8!(___, addr, adc8(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_82_2_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, adc8(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_82_3_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE8!(___, addr, sbb8(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_82_3_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, sbb8(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_82_4_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE8!(___, addr, and8(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_82_4_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, and8(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_82_5_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE8!(___, addr, sub8(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_82_5_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, sub8(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_82_6_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE8!(___, addr, xor8(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_82_6_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, xor8(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_82_7_reg(mut r: i32, mut imm: i32) -> () { cmp8(read_reg8(r), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr_82_7_mem(mut addr: i32, mut imm: i32) -> () { + cmp8(safe_read8(addr), imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_83_0_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, add16(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_83_0_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, add16(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_83_1_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, or16(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_83_1_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, or16(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_83_2_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, adc16(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_83_2_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, adc16(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_83_3_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, sbb16(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_83_3_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, sbb16(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_83_4_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, and16(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_83_4_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, and16(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_83_5_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, sub16(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_83_5_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, sub16(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_83_6_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, xor16(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_83_6_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, xor16(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_83_7_reg(mut r: i32, mut imm: i32) -> () { + cmp16(read_reg16(r), imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_83_7_mem(mut addr: i32, mut imm: i32) -> () { + cmp16(safe_read16(addr), imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_83_0_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, add32(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_83_0_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, add32(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_83_1_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, or32(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_83_1_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, or32(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_83_2_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, adc32(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_83_2_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, adc32(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_83_3_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, sbb32(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_83_3_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, sbb32(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_83_4_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, and32(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_83_4_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, and32(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_83_5_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, sub32(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_83_5_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, sub32(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_83_6_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, xor32(___, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_83_6_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, xor32(____0, imm)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_83_7_reg(mut r: i32, mut imm: i32) -> () { + cmp32(read_reg32(r), imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_83_7_mem(mut addr: i32, mut imm: i32) -> () { + cmp32(safe_read32s(addr), imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_84_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read8(addr); + test8(____0, read_reg8(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_84_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + test8(____0, read_reg8(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_85_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + test16(____0, read_reg16(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_85_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + test16(____0, read_reg16(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_85_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + test32(____0, read_reg32(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_85_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + test32(____0, read_reg32(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_86_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE8!(___, addr, xchg8(___, get_reg8_index(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_86_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, xchg8(____0, get_reg8_index(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_87_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE16!(___, addr, xchg16(___, get_reg16_index(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_87_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, xchg16(____0, get_reg16_index(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_87_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE32!(___, addr, xchg32(___, r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_87_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, xchg32(____0, r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_88_reg(mut r2: i32, mut r: i32) -> () { + write_reg8(r2, read_reg8(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_88_mem(mut addr: i32, mut r: i32) -> () { + safe_write8(addr, read_reg8(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_89_reg(mut r2: i32, mut r: i32) -> () { + write_reg16(r2, read_reg16(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_89_mem(mut addr: i32, mut r: i32) -> () { + safe_write16(addr, read_reg16(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_89_reg(mut r2: i32, mut r: i32) -> () { + write_reg32(r2, read_reg32(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_89_mem(mut addr: i32, mut r: i32) -> () { + safe_write32(addr, read_reg32(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_8A_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read8(addr); + write_reg8(r, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_8A_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_8B_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + write_reg16(r, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_8B_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_8B_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + write_reg32(r, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_8B_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_8C_check_sreg(mut seg: i32) -> bool { + if seg >= 6i32 { + dbg_log_c!(("mov sreg #ud")); + trigger_ud(); + return 0 != 0i32; + } + else { + return 0 != 1i32; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_8C_reg(mut r: i32, mut seg: i32) -> () { + if instr_8C_check_sreg(seg) { + write_reg16(r, *sreg.offset(seg as isize) as i32); + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_8C_mem(mut addr: i32, mut seg: i32) -> () { + if instr_8C_check_sreg(seg) { + safe_write16(addr, *sreg.offset(seg as isize) as i32); + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_8C_reg(mut r: i32, mut seg: i32) -> () { + if instr_8C_check_sreg(seg) { + write_reg32(r, *sreg.offset(seg as isize) as i32); + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_8C_mem(mut addr: i32, mut seg: i32) -> () { + if instr_8C_check_sreg(seg) { + safe_write32(addr, *sreg.offset(seg as isize) as i32); + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_8D_reg(mut r: i32, mut r2: i32) -> () { + dbg_log_c!(("lea #ud")); + trigger_ud(); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_8D_mem_pre() -> () { + c_comment!(("override prefix, so modrm_resolve does not return the segment part")); + *prefixes = (*prefixes as i32 | SEG_PREFIX_ZERO) as u8; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_8D_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("lea")); + write_reg16(r, addr); + *prefixes = 0i32 as u8; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_8D_reg(mut r: i32, mut r2: i32) -> () { + dbg_log_c!(("lea #ud")); + trigger_ud(); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_8D_mem_pre() -> () { + c_comment!(("override prefix, so modrm_resolve does not return the segment part")); + *prefixes = (*prefixes as i32 | SEG_PREFIX_ZERO) as u8; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_8D_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("lea")); + write_reg32(r, addr); + *prefixes = 0i32 as u8; +} +#[no_mangle] +pub unsafe extern "C" fn instr_8E_helper(mut data: i32, mut mod_0: i32) -> () { + if mod_0 == ES || mod_0 == SS || mod_0 == DS || mod_0 == FS || mod_0 == GS { + if !switch_seg(mod_0, data) { + return; + } + else { + mod_0 == SS; + } + } + else { + dbg_log_c!(("mov sreg #ud")); + trigger_ud(); + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_8E_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + instr_8E_helper(____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_8E_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + instr_8E_helper(____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_8F_0_mem_pre() -> () { + let mut i: i32 = 0i32; + while i < 8i32 { + translate_address_read(*instruction_pointer + i); + i += 1 + } + c_comment!(("XXX")); + adjust_stack_reg(2i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_8F_0_mem(mut addr: i32) -> () { + c_comment!(("pop")); + adjust_stack_reg(-2i32); + let mut sp: i32 = safe_read16(get_stack_pointer(0i32)); + safe_write16(addr, sp); + adjust_stack_reg(2i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_8F_0_reg(mut r: i32) -> () { write_reg16(r, pop16()); } +#[no_mangle] +pub unsafe extern "C" fn instr32_8F_0_mem_pre() -> () { + c_comment!(("prevent page faults during modrm_resolve")); + let mut i: i32 = 0i32; + while i < 8i32 { + translate_address_read(*instruction_pointer + i); + i += 1 + } + c_comment!(("XXX")); + c_comment!(("esp must be adjusted before calling modrm_resolve")); + c_comment!( + ("The order of calls is: instr32_8F_0_mem_pre -> modrm_resolve -> instr32_8F_0_mem") + ); + adjust_stack_reg(4i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_8F_0_mem(mut addr: i32) -> () { + c_comment!(("Before attempting a write that might cause a page fault,")); + c_comment!(("we must set esp to the old value. Fuck Intel.")); + adjust_stack_reg(-4i32); + let mut sp: i32 = safe_read32s(get_stack_pointer(0i32)); + safe_write32(addr, sp); + adjust_stack_reg(4i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_8F_0_reg(mut r: i32) -> () { write_reg32(r, pop32s()); } +#[no_mangle] +pub unsafe extern "C" fn instr_90() -> () {} +#[no_mangle] +pub unsafe extern "C" fn instr16_91() -> () { xchg16r(CX); } +#[no_mangle] +pub unsafe extern "C" fn instr32_91() -> () { xchg32r(ECX); } +#[no_mangle] +pub unsafe extern "C" fn instr16_92() -> () { xchg16r(DX); } +#[no_mangle] +pub unsafe extern "C" fn instr32_92() -> () { xchg32r(EDX); } +#[no_mangle] +pub unsafe extern "C" fn instr16_93() -> () { xchg16r(BX); } +#[no_mangle] +pub unsafe extern "C" fn instr32_93() -> () { xchg32r(EBX); } +#[no_mangle] +pub unsafe extern "C" fn instr16_94() -> () { xchg16r(SP); } +#[no_mangle] +pub unsafe extern "C" fn instr32_94() -> () { xchg32r(ESP); } +#[no_mangle] +pub unsafe extern "C" fn instr16_95() -> () { xchg16r(BP); } +#[no_mangle] +pub unsafe extern "C" fn instr32_95() -> () { xchg32r(EBP); } +#[no_mangle] +pub unsafe extern "C" fn instr16_96() -> () { xchg16r(SI); } +#[no_mangle] +pub unsafe extern "C" fn instr32_96() -> () { xchg32r(ESI); } +#[no_mangle] +pub unsafe extern "C" fn instr16_97() -> () { xchg16r(DI); } +#[no_mangle] +pub unsafe extern "C" fn instr32_97() -> () { xchg32r(EDI); } +#[no_mangle] +pub unsafe extern "C" fn instr16_98() -> () { + *reg16.offset(AX as isize) = *reg8s.offset(AL as isize) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_98() -> () { + *reg32s.offset(EAX as isize) = *reg16s.offset(AX as isize) as i32; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_99() -> () { + *reg16.offset(DX as isize) = (*reg16s.offset(AX as isize) as i32 >> 15i32) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_99() -> () { + *reg32s.offset(EDX as isize) = *reg32s.offset(EAX as isize) >> 31i32; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_9A(mut new_ip: i32, mut new_cs: i32) -> () { + c_comment!(("callf")); + far_jump(new_ip, new_cs, 1i32); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_9A(mut new_ip: i32, mut new_cs: i32) -> () { + if !*protected_mode || 0 != vm86_mode() as i32 { + if 0 != new_ip as u32 & 4294901760u32 { + dbg_assert!(0 != 0i32); + } + } + far_jump(new_ip, new_cs, 1i32); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_9B() -> () { + c_comment!(("fwait: check for pending fpu exceptions")); + if *cr.offset(0isize) & (CR0_MP | CR0_TS) == CR0_MP | CR0_TS { + c_comment!(("Note: Different from task_switch_test")); + c_comment!(("Triggers when TS and MP bits are set (EM bit is ignored)")); + trigger_nm(); + } + else { + fwait(); + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_9C() -> () { + c_comment!(("pushf")); + if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { + dbg_assert!(*protected_mode); + dbg_log_c!(("pushf #gp")); + trigger_gp_non_raising(0i32); + } + else { + push16(get_eflags()); + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_9C() -> () { + c_comment!(("pushf")); + if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { + c_comment!(("trap to virtual 8086 monitor")); + dbg_assert!(*protected_mode); + dbg_log_c!(("pushf #gp")); + trigger_gp_non_raising(0i32); + } + else { + c_comment!(("vm and rf flag are cleared in image stored on the stack")); + push32(get_eflags() & 16580607i32); + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_9D() -> () { + c_comment!(("popf")); + if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { + dbg_log_c!(("popf #gp")); + trigger_gp_non_raising(0i32); + return; + } + else { + update_eflags(*flags.offset(0isize) & !65535i32 | pop16()); + if 0 != *flags.offset(0isize) & FLAG_TRAP { + let ref mut fresh0 = *flags.offset(0isize); + *fresh0 &= !FLAG_TRAP + } + else { + handle_irqs(); + } + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_9D() -> () { + c_comment!(("popf")); + if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { + dbg_log_c!(("popf #gp")); + trigger_gp_non_raising(0i32); + return; + } + else { + update_eflags(pop32s()); + handle_irqs(); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_9E() -> () { + c_comment!(("sahf")); + *flags.offset(0isize) = *flags.offset(0isize) & !255i32 | *reg8.offset(AH as isize) as i32; + *flags.offset(0isize) = *flags.offset(0isize) & FLAGS_MASK | FLAGS_DEFAULT; + let ref mut fresh1 = *flags_changed.offset(0isize); + *fresh1 &= !255i32; +} +#[no_mangle] +pub unsafe extern "C" fn instr_9F() -> () { + c_comment!(("lahf")); + *reg8.offset(AH as isize) = get_eflags() as u8; +} +#[no_mangle] +pub unsafe extern "C" fn instr_A0(mut moffs: i32) -> () { + c_comment!(("mov")); + let mut data: i32 = safe_read8(get_seg_prefix_ds(moffs)); + *reg8.offset(AL as isize) = data as u8; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_A1(mut moffs: i32) -> () { + c_comment!(("mov")); + let mut data: i32 = safe_read16(get_seg_prefix_ds(moffs)); + *reg16.offset(AX as isize) = data as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_A1(mut moffs: i32) -> () { + let mut data: i32 = safe_read32s(get_seg_prefix_ds(moffs)); + *reg32s.offset(EAX as isize) = data; +} +#[no_mangle] +pub unsafe extern "C" fn instr_A2(mut moffs: i32) -> () { + c_comment!(("mov")); + safe_write8(get_seg_prefix_ds(moffs), *reg8.offset(AL as isize) as i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_A3(mut moffs: i32) -> () { + c_comment!(("mov")); + safe_write16(get_seg_prefix_ds(moffs), *reg16.offset(AX as isize) as i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_A3(mut moffs: i32) -> () { + safe_write32(get_seg_prefix_ds(moffs), *reg32s.offset(EAX as isize)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_A4() -> () { movsb_no_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_A5() -> () { movsw_no_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_A5() -> () { movsd_no_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr_A6() -> () { cmpsb_no_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_A7() -> () { cmpsw_no_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_A7() -> () { cmpsd_no_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr_A8(mut imm8: i32) -> () { + test8(*reg8.offset(AL as isize) as i32, imm8); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_A9(mut imm16: i32) -> () { + test16(*reg16.offset(AX as isize) as i32, imm16); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_A9(mut imm32: i32) -> () { + test32(*reg32s.offset(EAX as isize), imm32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_AA() -> () { stosb_no_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_AB() -> () { stosw_no_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_AB() -> () { stosd_no_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr_AC() -> () { lodsb_no_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_AD() -> () { lodsw_no_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_AD() -> () { lodsd_no_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr_AE() -> () { scasb_no_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_AF() -> () { scasw_no_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_AF() -> () { scasd_no_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr_B0(mut imm8: i32) -> () { *reg8.offset(AL as isize) = imm8 as u8; } +#[no_mangle] +pub unsafe extern "C" fn instr_B1(mut imm8: i32) -> () { *reg8.offset(CL as isize) = imm8 as u8; } +#[no_mangle] +pub unsafe extern "C" fn instr_B2(mut imm8: i32) -> () { *reg8.offset(DL as isize) = imm8 as u8; } +#[no_mangle] +pub unsafe extern "C" fn instr_B3(mut imm8: i32) -> () { *reg8.offset(BL as isize) = imm8 as u8; } +#[no_mangle] +pub unsafe extern "C" fn instr_B4(mut imm8: i32) -> () { *reg8.offset(AH as isize) = imm8 as u8; } +#[no_mangle] +pub unsafe extern "C" fn instr_B5(mut imm8: i32) -> () { *reg8.offset(CH as isize) = imm8 as u8; } +#[no_mangle] +pub unsafe extern "C" fn instr_B6(mut imm8: i32) -> () { *reg8.offset(DH as isize) = imm8 as u8; } +#[no_mangle] +pub unsafe extern "C" fn instr_B7(mut imm8: i32) -> () { *reg8.offset(BH as isize) = imm8 as u8; } +#[no_mangle] +pub unsafe extern "C" fn instr16_B8(mut imm: i32) -> () { *reg16.offset(AX as isize) = imm as u16; } +#[no_mangle] +pub unsafe extern "C" fn instr32_B8(mut imm: i32) -> () { *reg32s.offset(EAX as isize) = imm; } +#[no_mangle] +pub unsafe extern "C" fn instr16_B9(mut imm: i32) -> () { *reg16.offset(CX as isize) = imm as u16; } +#[no_mangle] +pub unsafe extern "C" fn instr32_B9(mut imm: i32) -> () { *reg32s.offset(ECX as isize) = imm; } +#[no_mangle] +pub unsafe extern "C" fn instr16_BA(mut imm: i32) -> () { *reg16.offset(DX as isize) = imm as u16; } +#[no_mangle] +pub unsafe extern "C" fn instr32_BA(mut imm: i32) -> () { *reg32s.offset(EDX as isize) = imm; } +#[no_mangle] +pub unsafe extern "C" fn instr16_BB(mut imm: i32) -> () { *reg16.offset(BX as isize) = imm as u16; } +#[no_mangle] +pub unsafe extern "C" fn instr32_BB(mut imm: i32) -> () { *reg32s.offset(EBX as isize) = imm; } +#[no_mangle] +pub unsafe extern "C" fn instr16_BC(mut imm: i32) -> () { *reg16.offset(SP as isize) = imm as u16; } +#[no_mangle] +pub unsafe extern "C" fn instr32_BC(mut imm: i32) -> () { *reg32s.offset(ESP as isize) = imm; } +#[no_mangle] +pub unsafe extern "C" fn instr16_BD(mut imm: i32) -> () { *reg16.offset(BP as isize) = imm as u16; } +#[no_mangle] +pub unsafe extern "C" fn instr32_BD(mut imm: i32) -> () { *reg32s.offset(EBP as isize) = imm; } +#[no_mangle] +pub unsafe extern "C" fn instr16_BE(mut imm: i32) -> () { *reg16.offset(SI as isize) = imm as u16; } +#[no_mangle] +pub unsafe extern "C" fn instr32_BE(mut imm: i32) -> () { *reg32s.offset(ESI as isize) = imm; } +#[no_mangle] +pub unsafe extern "C" fn instr16_BF(mut imm: i32) -> () { *reg16.offset(DI as isize) = imm as u16; } +#[no_mangle] +pub unsafe extern "C" fn instr32_BF(mut imm: i32) -> () { *reg32s.offset(EDI as isize) = imm; } +#[no_mangle] +pub unsafe extern "C" fn instr_C0_0_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE8!(___, addr, rol8(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_C0_0_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, rol8(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_C0_1_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE8!(___, addr, ror8(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_C0_1_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, ror8(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_C0_2_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE8!(___, addr, rcl8(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_C0_2_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, rcl8(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_C0_3_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE8!(___, addr, rcr8(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_C0_3_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, rcr8(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_C0_4_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE8!(___, addr, shl8(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_C0_4_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, shl8(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_C0_5_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE8!(___, addr, shr8(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_C0_5_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, shr8(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_C0_6_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE8!(___, addr, shl8(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_C0_6_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, shl8(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_C0_7_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE8!(___, addr, sar8(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_C0_7_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, sar8(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C1_0_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, rol16(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C1_0_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, rol16(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C1_1_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, ror16(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C1_1_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, ror16(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C1_2_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, rcl16(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C1_2_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, rcl16(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C1_3_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, rcr16(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C1_3_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, rcr16(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C1_4_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, shl16(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C1_4_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, shl16(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C1_5_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, shr16(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C1_5_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, shr16(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C1_6_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, shl16(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C1_6_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, shl16(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C1_7_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, sar16(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C1_7_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, sar16(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C1_0_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, rol32(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C1_0_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, rol32(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C1_1_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, ror32(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C1_1_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, ror32(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C1_2_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, rcl32(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C1_2_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, rcl32(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C1_3_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, rcr32(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C1_3_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, rcr32(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C1_4_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, shl32(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C1_4_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, shl32(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C1_5_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, shr32(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C1_5_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, shr32(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C1_6_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, shl32(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C1_6_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, shl32(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C1_7_mem(mut addr: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, sar32(___, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C1_7_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, sar32(____0, imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C2(mut imm16: i32) -> () { + c_comment!(("retn")); + let mut cs: i32 = get_seg_cs(); + *instruction_pointer.offset(0isize) = cs + pop16(); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); + adjust_stack_reg(imm16); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C2(mut imm16: i32) -> () { + c_comment!(("retn")); + let mut cs: i32 = get_seg_cs(); + let mut ip: i32 = pop32s(); + dbg_assert!(0 != is_asize_32() as i32 || ip < 65536i32); + *instruction_pointer.offset(0isize) = cs + ip; + adjust_stack_reg(imm16); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C3() -> () { + c_comment!(("retn")); + let mut cs: i32 = get_seg_cs(); + *instruction_pointer.offset(0isize) = cs + pop16(); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C3() -> () { + c_comment!(("retn")); + let mut cs: i32 = get_seg_cs(); + let mut ip: i32 = pop32s(); + dbg_assert!(0 != is_asize_32() as i32 || ip < 65536i32); + *instruction_pointer.offset(0isize) = cs + ip; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C4_reg(mut _unused1: i32, mut _unused2: i32) -> () { + trigger_ud(); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C4_mem(mut addr: i32, mut r: i32) -> () { + lss16(addr, get_reg16_index(r), ES); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C4_reg(mut _unused1: i32, mut _unused2: i32) -> () { + trigger_ud(); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C4_mem(mut addr: i32, mut r: i32) -> () { lss32(addr, r, ES); } +#[no_mangle] +pub unsafe extern "C" fn instr16_C5_reg(mut _unused1: i32, mut _unused2: i32) -> () { + trigger_ud(); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C5_mem(mut addr: i32, mut r: i32) -> () { + lss16(addr, get_reg16_index(r), DS); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C5_reg(mut _unused1: i32, mut _unused2: i32) -> () { + trigger_ud(); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C5_mem(mut addr: i32, mut r: i32) -> () { lss32(addr, r, DS); } +#[no_mangle] +pub unsafe extern "C" fn instr_C6_0_reg(mut r: i32, mut imm: i32) -> () { write_reg8(r, imm); } +#[no_mangle] +pub unsafe extern "C" fn instr_C6_0_mem(mut addr: i32, mut imm: i32) -> () { + safe_write8(addr, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C7_0_reg(mut r: i32, mut imm: i32) -> () { write_reg16(r, imm); } +#[no_mangle] +pub unsafe extern "C" fn instr16_C7_0_mem(mut addr: i32, mut imm: i32) -> () { + safe_write16(addr, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C7_0_reg(mut r: i32, mut imm: i32) -> () { write_reg32(r, imm); } +#[no_mangle] +pub unsafe extern "C" fn instr32_C7_0_mem(mut addr: i32, mut imm: i32) -> () { + safe_write32(addr, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C8(mut size: i32, mut nesting: i32) -> () { + enter16(size, nesting); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C8(mut size: i32, mut nesting: i32) -> () { + enter32(size, nesting); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_C9() -> () { + c_comment!(("leave")); + let mut old_vbp: i32 = if 0 != *stack_size_32 as i32 { + *reg32s.offset(EBP as isize) + } + else { + *reg16.offset(BP as isize) as i32 + }; + let mut new_bp: i32 = safe_read16(get_seg_ss() + old_vbp); + set_stack_reg(old_vbp + 2i32); + *reg16.offset(BP as isize) = new_bp as u16; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_C9() -> () { + let mut old_vbp: i32 = if 0 != *stack_size_32 as i32 { + *reg32s.offset(EBP as isize) + } + else { + *reg16.offset(BP as isize) as i32 + }; + let mut new_ebp: i32 = safe_read32s(get_seg_ss() + old_vbp); + set_stack_reg(old_vbp + 4i32); + *reg32s.offset(EBP as isize) = new_ebp; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_CA(mut imm16: i32) -> () { + c_comment!(("retf")); + let mut ip: i32 = safe_read16(get_stack_pointer(0i32)); + let mut cs: i32 = safe_read16(get_stack_pointer(2i32)); + far_return(ip, cs, imm16); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_CA(mut imm16: i32) -> () { + c_comment!(("retf")); + let mut ip: i32 = safe_read32s(get_stack_pointer(0i32)); + let mut cs: i32 = safe_read32s(get_stack_pointer(4i32)) & 65535i32; + far_return(ip, cs, imm16); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_CB() -> () { + c_comment!(("retf")); + let mut ip: i32 = safe_read16(get_stack_pointer(0i32)); + let mut cs: i32 = safe_read16(get_stack_pointer(2i32)); + far_return(ip, cs, 0i32); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_CB() -> () { + c_comment!(("retf")); + let mut ip: i32 = safe_read32s(get_stack_pointer(0i32)); + let mut cs: i32 = safe_read32s(get_stack_pointer(4i32)) & 65535i32; + far_return(ip, cs, 0i32); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_CC() -> () { + c_comment!(("INT3")); + c_comment!(("TODO: inhibit iopl checks")); + dbg_log_c!(("INT3")); + call_interrupt_vector(3i32, 0 != 1i32, 0 != 0i32, 0i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_CD(mut imm8: i32) -> () { + c_comment!(("INT")); + call_interrupt_vector(imm8, 0 != 1i32, 0 != 0i32, 0i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_CE() -> () { + c_comment!(("INTO")); + dbg_log_c!(("INTO")); + if getof() { + c_comment!(("TODO: inhibit iopl checks")); + call_interrupt_vector(CPU_EXCEPTION_OF, 0 != 1i32, 0 != 0i32, 0i32); + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_CF() -> () { + c_comment!(("iret")); + iret16(); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_CF() -> () { iret32(); } +#[no_mangle] +pub unsafe extern "C" fn instr_D0_0_mem(mut addr: i32) -> () { + SAFE_READ_WRITE8!(___, addr, rol8(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D0_0_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, rol8(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D0_1_mem(mut addr: i32) -> () { + SAFE_READ_WRITE8!(___, addr, ror8(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D0_1_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, ror8(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D0_2_mem(mut addr: i32) -> () { + SAFE_READ_WRITE8!(___, addr, rcl8(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D0_2_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, rcl8(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D0_3_mem(mut addr: i32) -> () { + SAFE_READ_WRITE8!(___, addr, rcr8(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D0_3_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, rcr8(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D0_4_mem(mut addr: i32) -> () { + SAFE_READ_WRITE8!(___, addr, shl8(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D0_4_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, shl8(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D0_5_mem(mut addr: i32) -> () { + SAFE_READ_WRITE8!(___, addr, shr8(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D0_5_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, shr8(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D0_6_mem(mut addr: i32) -> () { + SAFE_READ_WRITE8!(___, addr, shl8(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D0_6_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, shl8(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D0_7_mem(mut addr: i32) -> () { + SAFE_READ_WRITE8!(___, addr, sar8(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D0_7_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, sar8(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D1_0_mem(mut addr: i32) -> () { + SAFE_READ_WRITE16!(___, addr, rol16(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D1_0_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, rol16(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D1_1_mem(mut addr: i32) -> () { + SAFE_READ_WRITE16!(___, addr, ror16(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D1_1_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, ror16(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D1_2_mem(mut addr: i32) -> () { + SAFE_READ_WRITE16!(___, addr, rcl16(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D1_2_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, rcl16(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D1_3_mem(mut addr: i32) -> () { + SAFE_READ_WRITE16!(___, addr, rcr16(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D1_3_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, rcr16(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D1_4_mem(mut addr: i32) -> () { + SAFE_READ_WRITE16!(___, addr, shl16(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D1_4_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, shl16(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D1_5_mem(mut addr: i32) -> () { + SAFE_READ_WRITE16!(___, addr, shr16(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D1_5_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, shr16(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D1_6_mem(mut addr: i32) -> () { + SAFE_READ_WRITE16!(___, addr, shl16(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D1_6_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, shl16(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D1_7_mem(mut addr: i32) -> () { + SAFE_READ_WRITE16!(___, addr, sar16(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D1_7_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, sar16(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D1_0_mem(mut addr: i32) -> () { + SAFE_READ_WRITE32!(___, addr, rol32(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D1_0_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, rol32(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D1_1_mem(mut addr: i32) -> () { + SAFE_READ_WRITE32!(___, addr, ror32(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D1_1_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, ror32(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D1_2_mem(mut addr: i32) -> () { + SAFE_READ_WRITE32!(___, addr, rcl32(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D1_2_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, rcl32(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D1_3_mem(mut addr: i32) -> () { + SAFE_READ_WRITE32!(___, addr, rcr32(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D1_3_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, rcr32(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D1_4_mem(mut addr: i32) -> () { + SAFE_READ_WRITE32!(___, addr, shl32(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D1_4_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, shl32(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D1_5_mem(mut addr: i32) -> () { + SAFE_READ_WRITE32!(___, addr, shr32(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D1_5_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, shr32(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D1_6_mem(mut addr: i32) -> () { + SAFE_READ_WRITE32!(___, addr, shl32(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D1_6_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, shl32(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D1_7_mem(mut addr: i32) -> () { + SAFE_READ_WRITE32!(___, addr, sar32(___, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D1_7_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, sar32(____0, 1i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D2_0_mem(mut addr: i32) -> () { + SAFE_READ_WRITE8!( + ___, + addr, + rol8(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D2_0_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, rol8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D2_1_mem(mut addr: i32) -> () { + SAFE_READ_WRITE8!( + ___, + addr, + ror8(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D2_1_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, ror8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D2_2_mem(mut addr: i32) -> () { + SAFE_READ_WRITE8!( + ___, + addr, + rcl8(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D2_2_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, rcl8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D2_3_mem(mut addr: i32) -> () { + SAFE_READ_WRITE8!( + ___, + addr, + rcr8(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D2_3_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, rcr8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D2_4_mem(mut addr: i32) -> () { + SAFE_READ_WRITE8!( + ___, + addr, + shl8(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D2_4_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, shl8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D2_5_mem(mut addr: i32) -> () { + SAFE_READ_WRITE8!( + ___, + addr, + shr8(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D2_5_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, shr8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D2_6_mem(mut addr: i32) -> () { + SAFE_READ_WRITE8!( + ___, + addr, + shl8(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D2_6_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, shl8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D2_7_mem(mut addr: i32) -> () { + SAFE_READ_WRITE8!( + ___, + addr, + sar8(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D2_7_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, sar8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D3_0_mem(mut addr: i32) -> () { + SAFE_READ_WRITE16!( + ___, + addr, + rol16(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D3_0_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, rol16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D3_1_mem(mut addr: i32) -> () { + SAFE_READ_WRITE16!( + ___, + addr, + ror16(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D3_1_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, ror16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D3_2_mem(mut addr: i32) -> () { + SAFE_READ_WRITE16!( + ___, + addr, + rcl16(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D3_2_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, rcl16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D3_3_mem(mut addr: i32) -> () { + SAFE_READ_WRITE16!( + ___, + addr, + rcr16(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D3_3_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, rcr16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D3_4_mem(mut addr: i32) -> () { + SAFE_READ_WRITE16!( + ___, + addr, + shl16(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D3_4_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, shl16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D3_5_mem(mut addr: i32) -> () { + SAFE_READ_WRITE16!( + ___, + addr, + shr16(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D3_5_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, shr16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D3_6_mem(mut addr: i32) -> () { + SAFE_READ_WRITE16!( + ___, + addr, + shl16(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D3_6_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, shl16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D3_7_mem(mut addr: i32) -> () { + SAFE_READ_WRITE16!( + ___, + addr, + sar16(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_D3_7_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, sar16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D3_0_mem(mut addr: i32) -> () { + SAFE_READ_WRITE32!( + ___, + addr, + rol32(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D3_0_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, rol32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D3_1_mem(mut addr: i32) -> () { + SAFE_READ_WRITE32!( + ___, + addr, + ror32(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D3_1_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, ror32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D3_2_mem(mut addr: i32) -> () { + SAFE_READ_WRITE32!( + ___, + addr, + rcl32(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D3_2_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, rcl32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D3_3_mem(mut addr: i32) -> () { + SAFE_READ_WRITE32!( + ___, + addr, + rcr32(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D3_3_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, rcr32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D3_4_mem(mut addr: i32) -> () { + SAFE_READ_WRITE32!( + ___, + addr, + shl32(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D3_4_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, shl32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D3_5_mem(mut addr: i32) -> () { + SAFE_READ_WRITE32!( + ___, + addr, + shr32(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D3_5_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, shr32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D3_6_mem(mut addr: i32) -> () { + SAFE_READ_WRITE32!( + ___, + addr, + shl32(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D3_6_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, shl32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D3_7_mem(mut addr: i32) -> () { + SAFE_READ_WRITE32!( + ___, + addr, + sar32(___, *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_D3_7_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, sar32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D4(mut arg: i32) -> () { bcd_aam(arg); } +#[no_mangle] +pub unsafe extern "C" fn instr_D5(mut arg: i32) -> () { bcd_aad(arg); } +#[no_mangle] +pub unsafe extern "C" fn instr_D6() -> () { + c_comment!(("salc")); + *reg8.offset(AL as isize) = -(getcf() as i32) as u8; +} +#[no_mangle] +pub unsafe extern "C" fn instr_D7() -> () { + c_comment!(("xlat")); + if is_asize_32() { + *reg8.offset(AL as isize) = safe_read8( + get_seg_prefix(DS) + *reg32s.offset(EBX as isize) + *reg8.offset(AL as isize) as i32, + ) as u8 + } + else { + *reg8.offset(AL as isize) = safe_read8( + get_seg_prefix(DS) + + (*reg16.offset(BX as isize) as i32 + *reg8.offset(AL as isize) as i32 & 65535i32), + ) as u8 + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_E4(mut port: i32) -> () { + if !test_privileges_for_io(port, 1i32) { + return; + } + else { + *reg8.offset(AL as isize) = io_port_read8(port) as u8; + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_E5(mut port: i32) -> () { + if !test_privileges_for_io(port, 2i32) { + return; + } + else { + *reg16.offset(AX as isize) = io_port_read16(port) as u16; + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_E5(mut port: i32) -> () { + if !test_privileges_for_io(port, 4i32) { + return; + } + else { + *reg32s.offset(EAX as isize) = io_port_read32(port); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_E6(mut port: i32) -> () { + if !test_privileges_for_io(port, 1i32) { + return; + } + else { + io_port_write8(port, *reg8.offset(AL as isize) as i32); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_E7(mut port: i32) -> () { + if !test_privileges_for_io(port, 2i32) { + return; + } + else { + io_port_write16(port, *reg16.offset(AX as isize) as i32); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_E7(mut port: i32) -> () { + if !test_privileges_for_io(port, 4i32) { + return; + } + else { + io_port_write32(port, *reg32s.offset(EAX as isize)); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_E8(mut imm16: i32) -> () { + c_comment!(("call")); + push16(get_real_eip()); + jmp_rel16(imm16); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_E8(mut imm32s: i32) -> () { + c_comment!(("call")); + push32(get_real_eip()); + *instruction_pointer.offset(0isize) = *instruction_pointer.offset(0isize) + imm32s; + c_comment!(("dbg_assert!(is_asize_32() || get_real_eip() < 0x10000);")); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_E9(mut imm16: i32) -> () { + c_comment!(("jmp")); + jmp_rel16(imm16); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_E9(mut imm32s: i32) -> () { + c_comment!(("jmp")); + *instruction_pointer.offset(0isize) = *instruction_pointer.offset(0isize) + imm32s; + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_EA(mut new_ip: i32, mut cs: i32) -> () { + c_comment!(("jmpf")); + far_jump(new_ip, cs, 0i32); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_EA(mut new_ip: i32, mut cs: i32) -> () { + c_comment!(("jmpf")); + far_jump(new_ip, cs, 0i32); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_EC() -> () { + let mut port: i32 = *reg16.offset(DX as isize) as i32; + if !test_privileges_for_io(port, 1i32) { + return; + } + else { + *reg8.offset(AL as isize) = io_port_read8(port) as u8; + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_ED() -> () { + let mut port: i32 = *reg16.offset(DX as isize) as i32; + if !test_privileges_for_io(port, 2i32) { + return; + } + else { + *reg16.offset(AX as isize) = io_port_read16(port) as u16; + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_ED() -> () { + let mut port: i32 = *reg16.offset(DX as isize) as i32; + if !test_privileges_for_io(port, 4i32) { + return; + } + else { + *reg32s.offset(EAX as isize) = io_port_read32(port); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_EE() -> () { + let mut port: i32 = *reg16.offset(DX as isize) as i32; + if !test_privileges_for_io(port, 1i32) { + return; + } + else { + io_port_write8(port, *reg8.offset(AL as isize) as i32); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_EF() -> () { + let mut port: i32 = *reg16.offset(DX as isize) as i32; + if !test_privileges_for_io(port, 2i32) { + return; + } + else { + io_port_write16(port, *reg16.offset(AX as isize) as i32); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_EF() -> () { + let mut port: i32 = *reg16.offset(DX as isize) as i32; + if !test_privileges_for_io(port, 4i32) { + return; + } + else { + io_port_write32(port, *reg32s.offset(EAX as isize)); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_F0() -> () { + c_comment!(("lock")); + if 0 != 0i32 * 0i32 { + dbg_log_c!(("lock")); + } + c_comment!(("TODO")); + c_comment!(("This triggers UD when used with")); + c_comment!(("some instructions that don\'t write to memory")); + run_prefix_instruction(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F1() -> () { + c_comment!(("INT1")); + c_comment!(("https://code.google.com/p/corkami/wiki/x86oddities#IceBP")); + dbg_assert!(0 != 0i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F2() -> () { + c_comment!(("repnz")); + dbg_assert!(*prefixes as i32 & PREFIX_MASK_REP == 0i32); + *prefixes = (*prefixes as i32 | PREFIX_REPNZ) as u8; + run_prefix_instruction(); + *prefixes = 0i32 as u8; +} +#[no_mangle] +pub unsafe extern "C" fn instr_F3() -> () { + c_comment!(("repz")); + dbg_assert!(*prefixes as i32 & PREFIX_MASK_REP == 0i32); + *prefixes = (*prefixes as i32 | PREFIX_REPZ) as u8; + run_prefix_instruction(); + *prefixes = 0i32 as u8; +} +#[no_mangle] +pub unsafe extern "C" fn instr_F4() -> () { hlt_op(); } +#[no_mangle] +pub unsafe extern "C" fn instr_F5() -> () { + c_comment!(("cmc")); + *flags.offset(0isize) = (*flags.offset(0isize) | 1i32) ^ getcf() as i32; + let ref mut fresh2 = *flags_changed.offset(0isize); + *fresh2 &= !1i32; +} +#[no_mangle] +pub unsafe extern "C" fn instr_F6_0_mem(mut addr: i32, mut imm: i32) -> () { + let mut ____0: i32 = safe_read8(addr); + test8(____0, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F6_0_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + test8(____0, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F6_1_mem(mut addr: i32, mut imm: i32) -> () { + let mut ____0: i32 = safe_read8(addr); + test8(____0, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F6_1_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + test8(____0, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F6_2_mem(mut addr: i32) -> () { + SAFE_READ_WRITE8!(___, addr, !___); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F6_2_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, !____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F6_3_mem(mut addr: i32) -> () { + SAFE_READ_WRITE8!(___, addr, neg8(___)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F6_3_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, neg8(____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F6_4_mem(mut addr: i32) -> () { + let mut ____0: i32 = safe_read8(addr); + mul8(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F6_4_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + mul8(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F6_5_mem(mut addr: i32) -> () { + let mut ____0: i32 = safe_read8(addr); + imul8(____0 << 24i32 >> 24i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F6_5_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + imul8(____0 << 24i32 >> 24i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F6_6_mem(mut addr: i32) -> () { + let mut ____0: i32 = safe_read8(addr); + div8(____0 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F6_6_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + div8(____0 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F6_7_mem(mut addr: i32) -> () { + let mut ____0: i32 = safe_read8(addr); + idiv8(____0 << 24i32 >> 24i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F6_7_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + idiv8(____0 << 24i32 >> 24i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_F7_0_mem(mut addr: i32, mut imm: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + test16(____0, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_F7_0_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + test16(____0, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_F7_1_mem(mut addr: i32, mut imm: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + test16(____0, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_F7_1_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + test16(____0, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_F7_2_mem(mut addr: i32) -> () { + SAFE_READ_WRITE16!(___, addr, !___); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_F7_2_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, !____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_F7_3_mem(mut addr: i32) -> () { + SAFE_READ_WRITE16!(___, addr, neg16(___)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_F7_3_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, neg16(____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_F7_4_mem(mut addr: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + mul16(____0 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_F7_4_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + mul16(____0 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_F7_5_mem(mut addr: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + imul16(____0 << 16i32 >> 16i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_F7_5_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + imul16(____0 << 16i32 >> 16i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_F7_6_mem(mut addr: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + div16(____0 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_F7_6_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + div16(____0 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_F7_7_mem(mut addr: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + idiv16(____0 << 16i32 >> 16i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_F7_7_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + idiv16(____0 << 16i32 >> 16i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_F7_0_mem(mut addr: i32, mut imm: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + test32(____0, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_F7_0_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + test32(____0, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_F7_1_mem(mut addr: i32, mut imm: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + test32(____0, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_F7_1_reg(mut r1: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + test32(____0, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_F7_2_mem(mut addr: i32) -> () { + SAFE_READ_WRITE32!(___, addr, !___); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_F7_2_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, !____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_F7_3_mem(mut addr: i32) -> () { + SAFE_READ_WRITE32!(___, addr, neg32(___)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_F7_3_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, neg32(____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_F7_4_mem(mut addr: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + mul32(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_F7_4_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + mul32(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_F7_5_mem(mut addr: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + imul32(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_F7_5_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + imul32(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_F7_6_mem(mut addr: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + div32(____0 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_F7_6_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + div32(____0 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_F7_7_mem(mut addr: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + idiv32(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_F7_7_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + idiv32(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F8() -> () { + c_comment!(("clc")); + let ref mut fresh3 = *flags.offset(0isize); + *fresh3 &= !FLAG_CARRY; + let ref mut fresh4 = *flags_changed.offset(0isize); + *fresh4 &= !1i32; +} +#[no_mangle] +pub unsafe extern "C" fn instr_F9() -> () { + c_comment!(("stc")); + let ref mut fresh5 = *flags.offset(0isize); + *fresh5 |= FLAG_CARRY; + let ref mut fresh6 = *flags_changed.offset(0isize); + *fresh6 &= !1i32; +} +#[no_mangle] +pub unsafe extern "C" fn instr_FA() -> () { + c_comment!(("cli")); + if !*protected_mode || 0 != if 0 != *flags.offset(0isize) & FLAG_VM { + (getiopl() == 3i32) as i32 + } + else { + (getiopl() >= *cpl as i32) as i32 + } { + let ref mut fresh7 = *flags.offset(0isize); + *fresh7 &= !FLAG_INTERRUPT + } + else if 0 != 0i32 * 0i32 && getiopl() < 3i32 && 0 != if 0 != *flags & FLAG_VM { + *cr.offset(4isize) & CR4_VME + } + else { + (*cpl as i32 == 3i32 && 0 != *cr.offset(4isize) & CR4_PVI) as i32 + } { + *flags &= !FLAG_VIF + } + else { + dbg_log_c!(("cli #gp")); + trigger_gp_non_raising(0i32); + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_FB() -> () { + c_comment!(("sti")); + let mut old_if: i32 = *flags.offset(0isize) & FLAG_INTERRUPT; + if !*protected_mode || 0 != if 0 != *flags.offset(0isize) & FLAG_VM { + (getiopl() == 3i32) as i32 + } + else { + (getiopl() >= *cpl as i32) as i32 + } { + let ref mut fresh8 = *flags.offset(0isize); + *fresh8 |= FLAG_INTERRUPT; + if old_if == 0i32 { + handle_irqs(); + } + } + else if 0 != 0i32 * 0i32 && getiopl() < 3i32 && *flags & FLAG_VIP == 0i32 && 0 != if 0 + != *flags & FLAG_VM + { + *cr.offset(4isize) & CR4_VME + } + else { + (*cpl as i32 == 3i32 && 0 != *cr.offset(4isize) & CR4_PVI) as i32 + } { + *flags |= FLAG_VIF + } + else { + dbg_log_c!(("sti #gp")); + trigger_gp_non_raising(0i32); + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_FC() -> () { + c_comment!(("cld")); + let ref mut fresh9 = *flags.offset(0isize); + *fresh9 &= !FLAG_DIRECTION; +} +#[no_mangle] +pub unsafe extern "C" fn instr_FD() -> () { + c_comment!(("std")); + let ref mut fresh10 = *flags.offset(0isize); + *fresh10 |= FLAG_DIRECTION; +} +#[no_mangle] +pub unsafe extern "C" fn instr_FE_0_mem(mut addr: i32) -> () { + SAFE_READ_WRITE8!(___, addr, inc8(___)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_FE_0_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, inc8(____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_FE_1_mem(mut addr: i32) -> () { + SAFE_READ_WRITE8!(___, addr, dec8(___)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_FE_1_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, dec8(____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_FF_0_mem(mut addr: i32) -> () { + SAFE_READ_WRITE16!(___, addr, inc16(___)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_FF_0_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, inc16(____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_FF_1_mem(mut addr: i32) -> () { + SAFE_READ_WRITE16!(___, addr, dec16(___)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_FF_1_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, dec16(____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_FF_2_helper(mut data: i32) -> () { + c_comment!(("call near")); + let mut cs: i32 = get_seg_cs(); + push16(get_real_eip()); + *instruction_pointer.offset(0isize) = cs + data; + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_FF_2_mem(mut addr: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + instr16_FF_2_helper(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_FF_2_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + instr16_FF_2_helper(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_FF_3_reg(mut r: i32) -> () { + dbg_log_c!(("callf #ud")); + trigger_ud(); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_FF_3_mem(mut addr: i32) -> () { + c_comment!(("callf")); + let mut new_ip: i32 = safe_read16(addr); + let mut new_cs: i32 = safe_read16(addr + 2i32); + far_jump(new_ip, new_cs, 1i32); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_FF_4_helper(mut data: i32) -> () { + c_comment!(("jmp near")); + *instruction_pointer.offset(0isize) = get_seg_cs() + data; + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_FF_4_mem(mut addr: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + instr16_FF_4_helper(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_FF_4_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + instr16_FF_4_helper(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_FF_5_reg(mut r: i32) -> () { + dbg_log_c!(("jmpf #ud")); + trigger_ud(); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_FF_5_mem(mut addr: i32) -> () { + c_comment!(("jmpf")); + let mut new_ip: i32 = safe_read16(addr); + let mut new_cs: i32 = safe_read16(addr + 2i32); + far_jump(new_ip, new_cs, 0i32); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_FF_6_mem(mut addr: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + push16(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_FF_6_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + push16(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_FF_0_mem(mut addr: i32) -> () { + SAFE_READ_WRITE32!(___, addr, inc32(___)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_FF_0_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, inc32(____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_FF_1_mem(mut addr: i32) -> () { + SAFE_READ_WRITE32!(___, addr, dec32(___)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_FF_1_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, dec32(____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_FF_2_helper(mut data: i32) -> () { + c_comment!(("call near")); + let mut cs: i32 = get_seg_cs(); + push32(get_real_eip()); + dbg_assert!(0 != is_asize_32() as i32 || data < 65536i32); + *instruction_pointer.offset(0isize) = cs + data; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_FF_2_mem(mut addr: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + instr32_FF_2_helper(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_FF_2_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + instr32_FF_2_helper(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_FF_3_reg(mut r: i32) -> () { + dbg_log_c!(("callf #ud")); + trigger_ud(); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_FF_3_mem(mut addr: i32) -> () { + c_comment!(("callf")); + let mut new_ip: i32 = safe_read32s(addr); + let mut new_cs: i32 = safe_read16(addr + 4i32); + if !*protected_mode || 0 != vm86_mode() as i32 { + if 0 != new_ip as u32 & 4294901760u32 { + dbg_assert!(0 != 0i32); + } + } + far_jump(new_ip, new_cs, 1i32); + dbg_assert!(0 != is_asize_32() as i32 || new_ip < 65536i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_FF_4_helper(mut data: i32) -> () { + c_comment!(("jmp near")); + dbg_assert!(0 != is_asize_32() as i32 || data < 65536i32); + *instruction_pointer.offset(0isize) = get_seg_cs() + data; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_FF_4_mem(mut addr: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + instr32_FF_4_helper(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_FF_4_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + instr32_FF_4_helper(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_FF_5_reg(mut r: i32) -> () { + dbg_log_c!(("jmpf #ud")); + trigger_ud(); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_FF_5_mem(mut addr: i32) -> () { + c_comment!(("jmpf")); + let mut new_ip: i32 = safe_read32s(addr); + let mut new_cs: i32 = safe_read16(addr + 4i32); + if !*protected_mode || 0 != vm86_mode() as i32 { + if 0 != new_ip as u32 & 4294901760u32 { + dbg_assert!(0 != 0i32); + } + } + far_jump(new_ip, new_cs, 0i32); + dbg_assert!(0 != is_asize_32() as i32 || new_ip < 65536i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_FF_6_mem(mut addr: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + push32(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_FF_6_reg(mut r1: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + push32(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F26C() -> () { insb_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr_F36C() -> () { insb_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_F26D() -> () { insw_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_F36D() -> () { insw_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_F26D() -> () { insd_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_F36D() -> () { insd_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr_F26E() -> () { outsb_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr_F36E() -> () { outsb_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_F26F() -> () { outsw_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_F36F() -> () { outsw_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_F26F() -> () { outsd_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_F36F() -> () { outsd_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_70(mut imm8: i32) -> () { jmpcc16(test_o(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr16_71(mut imm8: i32) -> () { jmpcc16(!test_o(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr16_72(mut imm8: i32) -> () { jmpcc16(test_b(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr16_73(mut imm8: i32) -> () { jmpcc16(!test_b(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr16_74(mut imm8: i32) -> () { jmpcc16(test_z(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr16_75(mut imm8: i32) -> () { jmpcc16(!test_z(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr16_76(mut imm8: i32) -> () { jmpcc16(test_be(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr16_77(mut imm8: i32) -> () { jmpcc16(!test_be(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr16_78(mut imm8: i32) -> () { jmpcc16(test_s(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr16_79(mut imm8: i32) -> () { jmpcc16(!test_s(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr16_7A(mut imm8: i32) -> () { jmpcc16(test_p(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr16_7B(mut imm8: i32) -> () { jmpcc16(!test_p(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr16_7C(mut imm8: i32) -> () { jmpcc16(test_l(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr16_7D(mut imm8: i32) -> () { jmpcc16(!test_l(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr16_7E(mut imm8: i32) -> () { jmpcc16(test_le(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr16_7F(mut imm8: i32) -> () { jmpcc16(!test_le(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr32_70(mut imm8: i32) -> () { jmpcc32(test_o(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr32_71(mut imm8: i32) -> () { jmpcc32(!test_o(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr32_72(mut imm8: i32) -> () { jmpcc32(test_b(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr32_73(mut imm8: i32) -> () { jmpcc32(!test_b(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr32_74(mut imm8: i32) -> () { jmpcc32(test_z(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr32_75(mut imm8: i32) -> () { jmpcc32(!test_z(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr32_76(mut imm8: i32) -> () { jmpcc32(test_be(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr32_77(mut imm8: i32) -> () { jmpcc32(!test_be(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr32_78(mut imm8: i32) -> () { jmpcc32(test_s(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr32_79(mut imm8: i32) -> () { jmpcc32(!test_s(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr32_7A(mut imm8: i32) -> () { jmpcc32(test_p(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr32_7B(mut imm8: i32) -> () { jmpcc32(!test_p(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr32_7C(mut imm8: i32) -> () { jmpcc32(test_l(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr32_7D(mut imm8: i32) -> () { jmpcc32(!test_l(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr32_7E(mut imm8: i32) -> () { jmpcc32(test_le(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr32_7F(mut imm8: i32) -> () { jmpcc32(!test_le(), imm8); } +#[no_mangle] +pub unsafe extern "C" fn instr_F2A4() -> () { movsb_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr_F3A4() -> () { movsb_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_F2A5() -> () { movsw_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_F3A5() -> () { movsw_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_F2A5() -> () { movsd_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_F3A5() -> () { movsd_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr_F2A6() -> () { cmpsb_rep(PREFIX_F2); } +#[no_mangle] +pub unsafe extern "C" fn instr_F3A6() -> () { cmpsb_rep(PREFIX_F3); } +#[no_mangle] +pub unsafe extern "C" fn instr16_F2A7() -> () { cmpsw_rep(PREFIX_F2); } +#[no_mangle] +pub unsafe extern "C" fn instr16_F3A7() -> () { cmpsw_rep(PREFIX_F3); } +#[no_mangle] +pub unsafe extern "C" fn instr32_F2A7() -> () { cmpsd_rep(PREFIX_F2); } +#[no_mangle] +pub unsafe extern "C" fn instr32_F3A7() -> () { cmpsd_rep(PREFIX_F3); } +#[no_mangle] +pub unsafe extern "C" fn instr_F2AA() -> () { stosb_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr_F3AA() -> () { stosb_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_F2AB() -> () { stosw_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_F3AB() -> () { stosw_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_F2AB() -> () { stosd_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_F3AB() -> () { stosd_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr_F2AC() -> () { lodsb_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr_F3AC() -> () { lodsb_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_F2AD() -> () { lodsw_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_F3AD() -> () { lodsw_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_F2AD() -> () { lodsd_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_F3AD() -> () { lodsd_rep(); } +#[no_mangle] +pub unsafe extern "C" fn instr_F2AE() -> () { scasb_rep(PREFIX_F2); } +#[no_mangle] +pub unsafe extern "C" fn instr_F3AE() -> () { scasb_rep(PREFIX_F3); } +#[no_mangle] +pub unsafe extern "C" fn instr16_F2AF() -> () { scasw_rep(PREFIX_F2); } +#[no_mangle] +pub unsafe extern "C" fn instr16_F3AF() -> () { scasw_rep(PREFIX_F3); } +#[no_mangle] +pub unsafe extern "C" fn instr32_F2AF() -> () { scasd_rep(PREFIX_F2); } +#[no_mangle] +pub unsafe extern "C" fn instr32_F3AF() -> () { scasd_rep(PREFIX_F3); } +#[no_mangle] +pub unsafe extern "C" fn instr_D8_0_mem(mut addr: i32) -> () { + let mut ____0: f64 = fpu_load_m32(addr); + fpu_fadd(0i32, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D8_0_reg(mut r: i32) -> () { + let mut ____0: f64 = fpu_get_sti(r); + fpu_fadd(0i32, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D8_1_mem(mut addr: i32) -> () { + let mut ____0: f64 = fpu_load_m32(addr); + fpu_fmul(0i32, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D8_1_reg(mut r: i32) -> () { + let mut ____0: f64 = fpu_get_sti(r); + fpu_fmul(0i32, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D8_2_mem(mut addr: i32) -> () { + let mut ____0: f64 = fpu_load_m32(addr); + fpu_fcom(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D8_2_reg(mut r: i32) -> () { + let mut ____0: f64 = fpu_get_sti(r); + fpu_fcom(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D8_3_mem(mut addr: i32) -> () { + let mut ____0: f64 = fpu_load_m32(addr); + fpu_fcomp(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D8_3_reg(mut r: i32) -> () { + let mut ____0: f64 = fpu_get_sti(r); + fpu_fcomp(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D8_4_mem(mut addr: i32) -> () { + let mut ____0: f64 = fpu_load_m32(addr); + fpu_fsub(0i32, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D8_4_reg(mut r: i32) -> () { + let mut ____0: f64 = fpu_get_sti(r); + fpu_fsub(0i32, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D8_5_mem(mut addr: i32) -> () { + let mut ____0: f64 = fpu_load_m32(addr); + fpu_fsubr(0i32, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D8_5_reg(mut r: i32) -> () { + let mut ____0: f64 = fpu_get_sti(r); + fpu_fsubr(0i32, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D8_6_mem(mut addr: i32) -> () { + let mut ____0: f64 = fpu_load_m32(addr); + fpu_fdiv(0i32, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D8_6_reg(mut r: i32) -> () { + let mut ____0: f64 = fpu_get_sti(r); + fpu_fdiv(0i32, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D8_7_mem(mut addr: i32) -> () { + let mut ____0: f64 = fpu_load_m32(addr); + fpu_fdivr(0i32, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D8_7_reg(mut r: i32) -> () { + let mut ____0: f64 = fpu_get_sti(r); + fpu_fdivr(0i32, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D9_0_mem(mut addr: i32) -> () { + let mut ____0: f64 = fpu_load_m32(addr); + fpu_push(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D9_0_reg(mut r: i32) -> () { + let mut ____0: f64 = fpu_get_sti(r); + fpu_push(____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D9_1_mem(mut addr: i32) -> () { + dbg_log_c!(("d9/1")); + trigger_ud(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D9_1_reg(mut r: i32) -> () { fpu_fxch(r); } +#[no_mangle] +pub unsafe extern "C" fn instr_D9_2_mem(mut addr: i32) -> () { fpu_fstm32(addr); } +#[no_mangle] +pub unsafe extern "C" fn instr_D9_2_reg(mut r: i32) -> () { + if r != 0i32 { + trigger_ud(); + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_D9_3_mem(mut addr: i32) -> () { fpu_fstm32p(addr); } +#[no_mangle] +pub unsafe extern "C" fn instr_D9_3_reg(mut r: i32) -> () { + dbg_log_c!(("fstp1")); + trigger_ud(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_D9_4_mem(mut addr: i32) -> () { fpu_fldenv(addr); } +#[no_mangle] +pub unsafe extern "C" fn instr_D9_4_reg(mut r: i32) -> () { + let mut st0: f64 = fpu_get_st0(); + match r { + 0 => { + c_comment!(("fchs")); + *fpu_st.offset(*fpu_stack_ptr as isize) = -st0 + }, + 1 => { + c_comment!(("fabs")); + *fpu_st.offset(*fpu_stack_ptr as isize) = fabs(st0) + }, + 4 => { + fpu_ftst(st0); + }, + 5 => { + fpu_fxam(st0); + }, + _ => { + dbg_log_c!(("%x"), r); + trigger_ud(); + }, + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_D9_5_mem(mut addr: i32) -> () { fpu_fldcw(addr); } +#[no_mangle] +pub unsafe extern "C" fn instr_D9_5_reg(mut r: i32) -> () { + c_comment!(("fld1/fldl2t/fldl2e/fldpi/fldlg2/fldln2/fldz")); + match r { + 0 => { + fpu_push(1i32 as f64); + }, + 1 => { + fpu_push(M_LN10 / M_LN2); + }, + 2 => { + fpu_push(M_LOG2E); + }, + 3 => { + fpu_push(M_PI); + }, + 4 => { + fpu_push(M_LN2 / M_LN10); + }, + 5 => { + fpu_push(M_LN2); + }, + 6 => { + fpu_push(0i32 as f64); + }, + 7 => { + dbg_log_c!(("d9/5/7")); + trigger_ud(); + }, + _ => {}, + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_D9_6_mem(mut addr: i32) -> () { fpu_fstenv(addr); } +#[no_mangle] +pub unsafe extern "C" fn instr_D9_6_reg(mut r: i32) -> () { + let mut st0: f64 = fpu_get_st0(); + match r { + 0 => { + c_comment!(("f2xm1")); + *fpu_st.offset(*fpu_stack_ptr as isize) = pow(2i32 as f64, st0) - 1i32 as f64 + }, + 1 => { + c_comment!(("fyl2x")); + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(1i32 as u32) & 7i32 as u32) as isize) = + fpu_get_sti(1i32) * log(st0) / M_LN2; + fpu_pop(); + }, + 2 => { + c_comment!(("fptan")); + *fpu_st.offset(*fpu_stack_ptr as isize) = tan(st0); + fpu_push(1i32 as f64); + c_comment!(("no bug: push constant 1")); + }, + 3 => { + c_comment!(("fpatan")); + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(1i32 as u32) & 7i32 as u32) as isize) = + atan2(fpu_get_sti(1i32), st0); + fpu_pop(); + }, + 4 => { + fpu_fxtract(); + }, + 5 => { + c_comment!(("fprem1")); + *fpu_st.offset(*fpu_stack_ptr as isize) = fmod(st0, fpu_get_sti(1i32)) + }, + 6 => { + c_comment!(("fdecstp")); + *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_sub(1i32 as u32) & 7i32 as u32; + *fpu_status_word &= !FPU_C1 + }, + 7 => { + c_comment!(("fincstp")); + *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_add(1i32 as u32) & 7i32 as u32; + *fpu_status_word &= !FPU_C1 + }, + _ => { + dbg_assert!(0 != 0i32); + }, + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_D9_7_mem(mut addr: i32) -> () { fpu_fstcw(addr); } +#[no_mangle] +pub unsafe extern "C" fn instr_D9_7_reg(mut r: i32) -> () { + let mut st0: f64 = fpu_get_st0(); + match r { + 0 => { + fpu_fprem(); + }, + 1 => { + c_comment!(("fyl2xp1: y * log2(x+1) and pop")); + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(1i32 as u32) & 7i32 as u32) as isize) = + fpu_get_sti(1i32) * log(st0 + 1i32 as f64) / M_LN2; + fpu_pop(); + }, + 2 => *fpu_st.offset(*fpu_stack_ptr as isize) = sqrt(st0), + 3 => { + *fpu_st.offset(*fpu_stack_ptr as isize) = sin(st0); + fpu_push(cos(st0)); + }, + 4 => { + c_comment!(("frndint")); + *fpu_st.offset(*fpu_stack_ptr as isize) = fpu_integer_round(st0) + }, + 5 => { + c_comment!(("fscale")); + *fpu_st.offset(*fpu_stack_ptr as isize) = + st0 * pow(2i32 as f64, trunc(fpu_get_sti(1i32))) + }, + 6 => *fpu_st.offset(*fpu_stack_ptr as isize) = sin(st0), + 7 => *fpu_st.offset(*fpu_stack_ptr as isize) = cos(st0), + _ => { + dbg_assert!(0 != 0i32); + }, + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_DA_0_mem(mut addr: i32) -> () { + fpu_fadd(0i32, safe_read32s(addr) as f64); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DA_1_mem(mut addr: i32) -> () { + fpu_fmul(0i32, safe_read32s(addr) as f64); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DA_2_mem(mut addr: i32) -> () { + fpu_fcom(safe_read32s(addr) as f64); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DA_3_mem(mut addr: i32) -> () { + fpu_fcomp(safe_read32s(addr) as f64); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DA_4_mem(mut addr: i32) -> () { + fpu_fsub(0i32, safe_read32s(addr) as f64); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DA_5_mem(mut addr: i32) -> () { + fpu_fsubr(0i32, safe_read32s(addr) as f64); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DA_6_mem(mut addr: i32) -> () { + fpu_fdiv(0i32, safe_read32s(addr) as f64); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DA_7_mem(mut addr: i32) -> () { + fpu_fdivr(0i32, safe_read32s(addr) as f64); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DA_0_reg(mut r: i32) -> () { fpu_fcmovcc(test_b(), r); } +#[no_mangle] +pub unsafe extern "C" fn instr_DA_1_reg(mut r: i32) -> () { fpu_fcmovcc(test_z(), r); } +#[no_mangle] +pub unsafe extern "C" fn instr_DA_2_reg(mut r: i32) -> () { fpu_fcmovcc(test_be(), r); } +#[no_mangle] +pub unsafe extern "C" fn instr_DA_3_reg(mut r: i32) -> () { fpu_fcmovcc(test_p(), r); } +#[no_mangle] +pub unsafe extern "C" fn instr_DA_4_reg(mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_DA_5_reg(mut r: i32) -> () { + if r == 1i32 { + fpu_fucompp(); + } + else { + trigger_ud(); + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_DA_6_reg(mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_DA_7_reg(mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_DB_0_mem(mut addr: i32) -> () { fpu_fldm32(addr); } +#[no_mangle] +pub unsafe extern "C" fn instr_DB_1_mem(mut addr: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_DB_2_mem(mut addr: i32) -> () { fpu_fistm32(addr); } +#[no_mangle] +pub unsafe extern "C" fn instr_DB_3_mem(mut addr: i32) -> () { fpu_fistm32p(addr); } +#[no_mangle] +pub unsafe extern "C" fn instr_DB_4_mem(mut addr: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_DB_5_mem(mut addr: i32) -> () { fpu_fldm80(addr); } +#[no_mangle] +pub unsafe extern "C" fn instr_DB_6_mem(mut addr: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_DB_7_mem(mut addr: i32) -> () { fpu_fst80p(addr); } +#[no_mangle] +pub unsafe extern "C" fn instr_DB_0_reg(mut r: i32) -> () { fpu_fcmovcc(!test_b(), r); } +#[no_mangle] +pub unsafe extern "C" fn instr_DB_1_reg(mut r: i32) -> () { fpu_fcmovcc(!test_z(), r); } +#[no_mangle] +pub unsafe extern "C" fn instr_DB_2_reg(mut r: i32) -> () { fpu_fcmovcc(!test_be(), r); } +#[no_mangle] +pub unsafe extern "C" fn instr_DB_3_reg(mut r: i32) -> () { fpu_fcmovcc(!test_p(), r); } +#[no_mangle] +pub unsafe extern "C" fn instr_DB_4_reg(mut r: i32) -> () { + if r == 3i32 { + fpu_finit(); + } + else if r == 4i32 || r == 1i32 { + c_comment!(("fsetpm and fdisi; treated as nop")); + } + else if r == 2i32 { + fpu_fclex(); + } + else { + trigger_ud(); + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_DB_5_reg(mut r: i32) -> () { fpu_fucomi(r); } +#[no_mangle] +pub unsafe extern "C" fn instr_DB_6_reg(mut r: i32) -> () { fpu_fcomi(r); } +#[no_mangle] +pub unsafe extern "C" fn instr_DB_7_reg(mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_DC_0_mem(mut addr: i32) -> () { fpu_fadd(0i32, fpu_load_m64(addr)); } +#[no_mangle] +pub unsafe extern "C" fn instr_DC_1_mem(mut addr: i32) -> () { fpu_fmul(0i32, fpu_load_m64(addr)); } +#[no_mangle] +pub unsafe extern "C" fn instr_DC_2_mem(mut addr: i32) -> () { fpu_fcom(fpu_load_m64(addr)); } +#[no_mangle] +pub unsafe extern "C" fn instr_DC_3_mem(mut addr: i32) -> () { fpu_fcomp(fpu_load_m64(addr)); } +#[no_mangle] +pub unsafe extern "C" fn instr_DC_4_mem(mut addr: i32) -> () { fpu_fsub(0i32, fpu_load_m64(addr)); } +#[no_mangle] +pub unsafe extern "C" fn instr_DC_5_mem(mut addr: i32) -> () { + fpu_fsubr(0i32, fpu_load_m64(addr)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DC_6_mem(mut addr: i32) -> () { fpu_fdiv(0i32, fpu_load_m64(addr)); } +#[no_mangle] +pub unsafe extern "C" fn instr_DC_7_mem(mut addr: i32) -> () { + fpu_fdivr(0i32, fpu_load_m64(addr)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DC_0_reg(mut r: i32) -> () { fpu_fadd(r, fpu_get_sti(r)); } +#[no_mangle] +pub unsafe extern "C" fn instr_DC_1_reg(mut r: i32) -> () { fpu_fmul(r, fpu_get_sti(r)); } +#[no_mangle] +pub unsafe extern "C" fn instr_DC_2_reg(mut r: i32) -> () { fpu_fcom(fpu_get_sti(r)); } +#[no_mangle] +pub unsafe extern "C" fn instr_DC_3_reg(mut r: i32) -> () { fpu_fcomp(fpu_get_sti(r)); } +#[no_mangle] +pub unsafe extern "C" fn instr_DC_4_reg(mut r: i32) -> () { fpu_fsub(r, fpu_get_sti(r)); } +#[no_mangle] +pub unsafe extern "C" fn instr_DC_5_reg(mut r: i32) -> () { fpu_fsubr(r, fpu_get_sti(r)); } +#[no_mangle] +pub unsafe extern "C" fn instr_DC_6_reg(mut r: i32) -> () { fpu_fdiv(r, fpu_get_sti(r)); } +#[no_mangle] +pub unsafe extern "C" fn instr_DC_7_reg(mut r: i32) -> () { fpu_fdivr(r, fpu_get_sti(r)); } +#[no_mangle] +pub unsafe extern "C" fn instr_DD_0_mem(mut addr: i32) -> () { fpu_fldm64(addr); } +#[no_mangle] +pub unsafe extern "C" fn instr_DD_1_mem(mut addr: i32) -> () { + dbg_log_c!(("fisttp")); + trigger_ud(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DD_2_mem(mut addr: i32) -> () { fpu_fstm64(addr); } +#[no_mangle] +pub unsafe extern "C" fn instr_DD_3_mem(mut addr: i32) -> () { fpu_fstm64p(addr); } +#[no_mangle] +pub unsafe extern "C" fn instr_DD_4_mem(mut addr: i32) -> () { fpu_frstor(addr); } +#[no_mangle] +pub unsafe extern "C" fn instr_DD_5_mem(mut addr: i32) -> () { + dbg_log_c!(("dd/5")); + trigger_ud(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DD_6_mem(mut addr: i32) -> () { fpu_fsave(addr); } +#[no_mangle] +pub unsafe extern "C" fn instr_DD_7_mem(mut addr: i32) -> () { fpu_fnstsw_mem(addr); } +#[no_mangle] +pub unsafe extern "C" fn instr_DD_0_reg(mut r: i32) -> () { fpu_ffree(r); } +#[no_mangle] +pub unsafe extern "C" fn instr_DD_1_reg(mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_DD_2_reg(mut r: i32) -> () { fpu_fst(r); } +#[no_mangle] +pub unsafe extern "C" fn instr_DD_3_reg(mut r: i32) -> () { fpu_fstp(r); } +#[no_mangle] +pub unsafe extern "C" fn instr_DD_4_reg(mut r: i32) -> () { fpu_fucom(r); } +#[no_mangle] +pub unsafe extern "C" fn instr_DD_5_reg(mut r: i32) -> () { fpu_fucomp(r); } +#[no_mangle] +pub unsafe extern "C" fn instr_DD_6_reg(mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_DD_7_reg(mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_DE_0_mem(mut addr: i32) -> () { + fpu_fadd(0i32, safe_read16(addr) as i16 as f64); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DE_1_mem(mut addr: i32) -> () { + fpu_fmul(0i32, safe_read16(addr) as i16 as f64); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DE_2_mem(mut addr: i32) -> () { + fpu_fcom(safe_read16(addr) as i16 as f64); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DE_3_mem(mut addr: i32) -> () { + fpu_fcomp(safe_read16(addr) as i16 as f64); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DE_4_mem(mut addr: i32) -> () { + fpu_fsub(0i32, safe_read16(addr) as i16 as f64); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DE_5_mem(mut addr: i32) -> () { + fpu_fsubr(0i32, safe_read16(addr) as i16 as f64); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DE_6_mem(mut addr: i32) -> () { + fpu_fdiv(0i32, safe_read16(addr) as i16 as f64); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DE_7_mem(mut addr: i32) -> () { + fpu_fdivr(0i32, safe_read16(addr) as i16 as f64); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DE_0_reg(mut r: i32) -> () { + fpu_fadd(r, fpu_get_sti(r)); + fpu_pop(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DE_1_reg(mut r: i32) -> () { + fpu_fmul(r, fpu_get_sti(r)); + fpu_pop(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DE_2_reg(mut r: i32) -> () { + fpu_fcom(fpu_get_sti(r)); + fpu_pop(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DE_3_reg(mut r: i32) -> () { + fpu_fcomp(fpu_get_sti(r)); + fpu_pop(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DE_4_reg(mut r: i32) -> () { + fpu_fsub(r, fpu_get_sti(r)); + fpu_pop(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DE_5_reg(mut r: i32) -> () { + fpu_fsubr(r, fpu_get_sti(r)); + fpu_pop(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DE_6_reg(mut r: i32) -> () { + fpu_fdiv(r, fpu_get_sti(r)); + fpu_pop(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DE_7_reg(mut r: i32) -> () { + fpu_fdivr(r, fpu_get_sti(r)); + fpu_pop(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DF_0_mem(mut addr: i32) -> () { + fpu_push(safe_read16(addr) as i16 as f64); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DF_1_mem(mut addr: i32) -> () { + dbg_log_c!(("df/fisttp")); + trigger_ud(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DF_2_mem(mut addr: i32) -> () { fpu_fistm16(addr); } +#[no_mangle] +pub unsafe extern "C" fn instr_DF_3_mem(mut addr: i32) -> () { fpu_fistm16p(addr); } +#[no_mangle] +pub unsafe extern "C" fn instr_DF_4_mem(mut addr: i32) -> () { + dbg_log_c!(("fbld")); + trigger_ud(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DF_5_mem(mut addr: i32) -> () { fpu_fildm64(addr); } +#[no_mangle] +pub unsafe extern "C" fn instr_DF_6_mem(mut addr: i32) -> () { + dbg_log_c!(("fbstp")); + trigger_ud(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DF_7_mem(mut addr: i32) -> () { fpu_fistm64p(addr); } +#[no_mangle] +pub unsafe extern "C" fn instr_DF_0_reg(mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_DF_1_reg(mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_DF_2_reg(mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_DF_3_reg(mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_DF_4_reg(mut r: i32) -> () { + if r == 0i32 { + fpu_fnstsw_reg(); + } + else { + trigger_ud(); + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_DF_5_reg(mut r: i32) -> () { fpu_fucomip(r); } +#[no_mangle] +pub unsafe extern "C" fn instr_DF_6_reg(mut r: i32) -> () { fpu_fcomip(r); } +#[no_mangle] +pub unsafe extern "C" fn instr_DF_7_reg(mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_E0(mut imm8s: i32) -> () { loopne16(imm8s); } +#[no_mangle] +pub unsafe extern "C" fn instr16_E1(mut imm8s: i32) -> () { loope16(imm8s); } +#[no_mangle] +pub unsafe extern "C" fn instr16_E2(mut imm8s: i32) -> () { loop16(imm8s); } +#[no_mangle] +pub unsafe extern "C" fn instr16_E3(mut imm8s: i32) -> () { jcxz16(imm8s); } +#[no_mangle] +pub unsafe extern "C" fn instr32_E0(mut imm8s: i32) -> () { loopne32(imm8s); } +#[no_mangle] +pub unsafe extern "C" fn instr32_E1(mut imm8s: i32) -> () { loope32(imm8s); } +#[no_mangle] +pub unsafe extern "C" fn instr32_E2(mut imm8s: i32) -> () { loop32(imm8s); } +#[no_mangle] +pub unsafe extern "C" fn instr32_E3(mut imm8s: i32) -> () { jcxz32(imm8s); } +#[no_mangle] +pub unsafe extern "C" fn instr16_EB(mut imm8: i32) -> () { + c_comment!(("jmp near")); + jmp_rel16(imm8); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_EB(mut imm8: i32) -> () { + c_comment!(("jmp near")); + *instruction_pointer.offset(0isize) = *instruction_pointer.offset(0isize) + imm8; + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); +} diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs new file mode 100644 index 00000000..3db895a8 --- /dev/null +++ b/src/rust/cpu2/instructions_0f.rs @@ -0,0 +1,7810 @@ +#![allow +( dead_code , mutable_transmutes , non_camel_case_types , non_snake_case , +non_upper_case_globals , unused_mut )] +#![feature ( extern_types , libc )] + +extern "C" { + + #[no_mangle] + fn __fpclassifyl(_: f64) -> i32; + #[no_mangle] + fn sqrt(_: f64) -> f64; + #[no_mangle] + fn sqrtf(_: f32) -> f32; + #[no_mangle] + fn abs(_: i32) -> i32; + #[no_mangle] + fn cmp8(x: i32, y: i32) -> (); + #[no_mangle] + fn cmp16(x: i32, y: i32) -> (); + #[no_mangle] + fn cmp32(x: i32, y: i32) -> (); + #[no_mangle] + fn imul_reg16(operand1: i32, operand2: i32) -> i32; + #[no_mangle] + fn imul_reg32(operand1: i32, operand2: i32) -> i32; + #[no_mangle] + fn xadd8(source_operand: i32, reg: i32) -> i32; + #[no_mangle] + fn xadd16(source_operand: i32, reg: i32) -> i32; + #[no_mangle] + fn xadd32(source_operand: i32, reg: i32) -> i32; + #[no_mangle] + fn shrd16(dest_operand: i32, source_operand: i32, count: i32) -> i32; + #[no_mangle] + fn shrd32(dest_operand: i32, source_operand: i32, count: i32) -> i32; + #[no_mangle] + fn shld16(dest_operand: i32, source_operand: i32, count: i32) -> i32; + #[no_mangle] + fn shld32(dest_operand: i32, source_operand: i32, count: i32) -> i32; + #[no_mangle] + fn bt_reg(bit_base: i32, bit_offset: i32) -> (); + #[no_mangle] + fn btc_reg(bit_base: i32, bit_offset: i32) -> i32; + #[no_mangle] + fn bts_reg(bit_base: i32, bit_offset: i32) -> i32; + #[no_mangle] + fn btr_reg(bit_base: i32, bit_offset: i32) -> i32; + #[no_mangle] + fn bt_mem(virt_addr: i32, bit_offset: i32) -> (); + #[no_mangle] + fn btc_mem(virt_addr: i32, bit_offset: i32) -> (); + #[no_mangle] + fn btr_mem(virt_addr: i32, bit_offset: i32) -> (); + #[no_mangle] + fn bts_mem(virt_addr: i32, bit_offset: i32) -> (); + #[no_mangle] + fn bsf16(old: i32, bit_base: i32) -> i32; + #[no_mangle] + fn bsf32(old: i32, bit_base: i32) -> i32; + #[no_mangle] + fn bsr16(old: i32, bit_base: i32) -> i32; + #[no_mangle] + fn bsr32(old: i32, bit_base: i32) -> i32; + #[no_mangle] + fn popcnt(v: i32) -> i32; + #[no_mangle] + fn saturate_sw_to_ub(v: u32) -> u32; + #[no_mangle] + fn saturate_sw_to_sb(v: i32) -> i32; + #[no_mangle] + fn saturate_sd_to_sw(v: u32) -> u32; + #[no_mangle] + fn saturate_sd_to_sb(v: u32) -> u32; + #[no_mangle] + fn saturate_sd_to_ub(v: i32) -> i32; + #[no_mangle] + fn saturate_ud_to_ub(v: u32) -> u32; + #[no_mangle] + fn saturate_uw(v: u32) -> i32; + #[no_mangle] + static FLAG_CARRY: i32; + #[no_mangle] + static FLAG_PARITY: i32; + #[no_mangle] + static FLAG_ADJUST: i32; + #[no_mangle] + static FLAG_ZERO: i32; + #[no_mangle] + static FLAG_SIGN: i32; + #[no_mangle] + static FLAG_TRAP: i32; + #[no_mangle] + static FLAG_INTERRUPT: i32; + #[no_mangle] + static FLAG_DIRECTION: i32; + #[no_mangle] + static FLAG_OVERFLOW: i32; + #[no_mangle] + static FLAG_IOPL: i32; + #[no_mangle] + static FLAG_NT: i32; + #[no_mangle] + static FLAG_RF: i32; + #[no_mangle] + static FLAG_VM: i32; + #[no_mangle] + static FLAG_AC: i32; + #[no_mangle] + static FLAG_VIF: i32; + #[no_mangle] + static FLAG_VIP: i32; + #[no_mangle] + static FLAG_ID: i32; + #[no_mangle] + static FLAGS_DEFAULT: i32; + #[no_mangle] + static FLAGS_MASK: i32; + #[no_mangle] + static FLAGS_ALL: i32; + #[no_mangle] + static OPSIZE_8: i32; + #[no_mangle] + static OPSIZE_16: i32; + #[no_mangle] + static OPSIZE_32: i32; + #[no_mangle] + static EAX: i32; + #[no_mangle] + static ECX: i32; + #[no_mangle] + static EDX: i32; + #[no_mangle] + static EBX: i32; + #[no_mangle] + static ESP: i32; + #[no_mangle] + static EBP: i32; + #[no_mangle] + static ESI: i32; + #[no_mangle] + static EDI: i32; + #[no_mangle] + static AX: i32; + #[no_mangle] + static CX: i32; + #[no_mangle] + static DX: i32; + #[no_mangle] + static BX: i32; + #[no_mangle] + static SP: i32; + #[no_mangle] + static BP: i32; + #[no_mangle] + static SI: i32; + #[no_mangle] + static DI: i32; + #[no_mangle] + static AL: i32; + #[no_mangle] + static CL: i32; + #[no_mangle] + static DL: i32; + #[no_mangle] + static BL: i32; + #[no_mangle] + static AH: i32; + #[no_mangle] + static CH: i32; + #[no_mangle] + static DH: i32; + #[no_mangle] + static BH: i32; + #[no_mangle] + static ES: i32; + #[no_mangle] + static CS: i32; + #[no_mangle] + static SS: i32; + #[no_mangle] + static DS: i32; + #[no_mangle] + static FS: i32; + #[no_mangle] + static GS: i32; + #[no_mangle] + static TR: i32; + #[no_mangle] + static LDTR: i32; + #[no_mangle] + static PAGE_TABLE_PRESENT_MASK: i32; + #[no_mangle] + static PAGE_TABLE_RW_MASK: i32; + #[no_mangle] + static PAGE_TABLE_USER_MASK: i32; + #[no_mangle] + static PAGE_TABLE_ACCESSED_MASK: i32; + #[no_mangle] + static PAGE_TABLE_DIRTY_MASK: i32; + #[no_mangle] + static PAGE_TABLE_PSE_MASK: i32; + #[no_mangle] + static PAGE_TABLE_GLOBAL_MASK: i32; + #[no_mangle] + static MMAP_BLOCK_BITS: i32; + #[no_mangle] + static MMAP_BLOCK_SIZE: i32; + #[no_mangle] + static CR0_PE: i32; + #[no_mangle] + static CR0_MP: i32; + #[no_mangle] + static CR0_EM: i32; + #[no_mangle] + static CR0_TS: i32; + #[no_mangle] + static CR0_ET: i32; + #[no_mangle] + static CR0_WP: i32; + #[no_mangle] + static CR0_NW: i32; + #[no_mangle] + static CR0_CD: i32; + #[no_mangle] + static CR0_PG: i32; + #[no_mangle] + static CR4_VME: i32; + #[no_mangle] + static CR4_PVI: i32; + #[no_mangle] + static CR4_TSD: i32; + #[no_mangle] + static CR4_PSE: i32; + #[no_mangle] + static CR4_DE: i32; + #[no_mangle] + static CR4_PAE: i32; + #[no_mangle] + static CR4_PGE: i32; + #[no_mangle] + static IA32_SYSENTER_CS: i32; + #[no_mangle] + static IA32_SYSENTER_ESP: i32; + #[no_mangle] + static IA32_SYSENTER_EIP: i32; + #[no_mangle] + static IA32_TIME_STAMP_COUNTER: i32; + #[no_mangle] + static IA32_PLATFORM_ID: i32; + #[no_mangle] + static IA32_APIC_BASE_MSR: i32; + #[no_mangle] + static IA32_BIOS_SIGN_ID: i32; + #[no_mangle] + static MSR_PLATFORM_INFO: i32; + #[no_mangle] + static MSR_MISC_FEATURE_ENABLES: i32; + #[no_mangle] + static IA32_MISC_ENABLE: i32; + #[no_mangle] + static IA32_RTIT_CTL: i32; + #[no_mangle] + static MSR_SMI_COUNT: i32; + #[no_mangle] + static IA32_MCG_CAP: i32; + #[no_mangle] + static IA32_KERNEL_GS_BASE: i32; + #[no_mangle] + static MSR_PKG_C2_RESIDENCY: i32; + #[no_mangle] + static IA32_APIC_BASE_BSP: i32; + #[no_mangle] + static IA32_APIC_BASE_EXTD: i32; + #[no_mangle] + static IA32_APIC_BASE_EN: i32; + #[no_mangle] + static APIC_ADDRESS: i32; + #[no_mangle] + static SEG_PREFIX_NONE: i32; + #[no_mangle] + static SEG_PREFIX_ZERO: i32; + #[no_mangle] + static PREFIX_MASK_REP: i32; + #[no_mangle] + static PREFIX_REPZ: i32; + #[no_mangle] + static PREFIX_REPNZ: i32; + #[no_mangle] + static PREFIX_MASK_SEGMENT: i32; + #[no_mangle] + static PREFIX_MASK_OPSIZE: i32; + #[no_mangle] + static PREFIX_MASK_ADDRSIZE: i32; + #[no_mangle] + static PREFIX_F2: i32; + #[no_mangle] + static PREFIX_F3: i32; + #[no_mangle] + static PREFIX_66: i32; + #[no_mangle] + static LOG_CPU: i32; + #[no_mangle] + static A20_MASK: i32; + #[no_mangle] + static A20_MASK16: i32; + #[no_mangle] + static A20_MASK32: i32; + #[no_mangle] + static MXCSR_MASK: i32; + + #[no_mangle] + fn dbg_log(m: *const i8) -> (); + #[no_mangle] + fn dbg_log1(m: *const i8, x: i32) -> (); + #[no_mangle] + fn dbg_log2(m: *const i8, x: i32, y: i32) -> (); + #[no_mangle] + fn dbg_log3(m: *const i8, x: i32, y: i32, z: i32) -> (); + #[no_mangle] + fn c_comment(m: *const i8) -> (); + #[no_mangle] + static mut mem8: *mut u8; + #[no_mangle] + static mut mem16: *mut u16; + #[no_mangle] + static mut mem32s: *mut i32; + #[no_mangle] + static mut jit_block_boundary: bool; + #[no_mangle] + static VALID_TLB_ENTRY_MAX: i32; + #[no_mangle] + static mut valid_tlb_entries: [i32; 10000]; + #[no_mangle] + static mut valid_tlb_entries_count: i32; + #[no_mangle] + static TLB_VALID: i32; + #[no_mangle] + static TLB_READONLY: i32; + #[no_mangle] + static TLB_NO_USER: i32; + #[no_mangle] + static TLB_IN_MAPPED_RANGE: i32; + #[no_mangle] + static TLB_GLOBAL: i32; + #[no_mangle] + static TLB_HAS_CODE: i32; + #[no_mangle] + static CPU_EXCEPTION_DE: i32; + #[no_mangle] + static CPU_EXCEPTION_DB: i32; + #[no_mangle] + static CPU_EXCEPTION_NMI: i32; + #[no_mangle] + static CPU_EXCEPTION_BP: i32; + #[no_mangle] + static CPU_EXCEPTION_OF: i32; + #[no_mangle] + static CPU_EXCEPTION_BR: i32; + #[no_mangle] + static CPU_EXCEPTION_UD: i32; + #[no_mangle] + static CPU_EXCEPTION_NM: i32; + #[no_mangle] + static CPU_EXCEPTION_DF: i32; + #[no_mangle] + static CPU_EXCEPTION_TS: i32; + #[no_mangle] + static CPU_EXCEPTION_NP: i32; + #[no_mangle] + static CPU_EXCEPTION_SS: i32; + #[no_mangle] + static CPU_EXCEPTION_GP: i32; + #[no_mangle] + static CPU_EXCEPTION_PF: i32; + #[no_mangle] + static CPU_EXCEPTION_MF: i32; + #[no_mangle] + static CPU_EXCEPTION_AC: i32; + #[no_mangle] + static CPU_EXCEPTION_MC: i32; + #[no_mangle] + static CPU_EXCEPTION_XM: i32; + #[no_mangle] + static CPU_EXCEPTION_VE: i32; + #[no_mangle] + fn writable_or_pagefault(addr: i32, size: i32) -> (); + #[no_mangle] + fn is_osize_32() -> bool; + #[no_mangle] + fn get_seg_prefix(default_segment: i32) -> i32; + #[no_mangle] + fn trigger_ud() -> (); + #[no_mangle] + fn trigger_gp_non_raising(code: i32) -> (); + #[no_mangle] + fn safe_read8(addr: i32) -> i32; + #[no_mangle] + fn safe_read16(addr: i32) -> i32; + #[no_mangle] + fn safe_read32s(address: i32) -> i32; + #[no_mangle] + fn safe_read64s(addr: i32) -> reg64; + #[no_mangle] + fn safe_read128s(addr: i32) -> reg128; + #[no_mangle] + fn safe_write8(addr: i32, value: i32) -> (); + #[no_mangle] + fn safe_write16(addr: i32, value: i32) -> (); + #[no_mangle] + fn safe_write32(address: i32, value: i32) -> (); + #[no_mangle] + fn safe_write64(addr: i32, value: i64) -> (); + #[no_mangle] + fn safe_write128(addr: i32, value: reg128) -> (); + #[no_mangle] + fn get_reg8_index(index: i32) -> i32; + #[no_mangle] + fn read_reg8(index: i32) -> i32; + #[no_mangle] + fn write_reg8(index: i32, value: i32) -> (); + #[no_mangle] + fn get_reg16_index(index: i32) -> i32; + #[no_mangle] + fn read_reg16(index: i32) -> i32; + #[no_mangle] + fn write_reg16(index: i32, value: i32) -> (); + #[no_mangle] + fn read_reg32(index: i32) -> i32; + #[no_mangle] + fn write_reg32(index: i32, value: i32) -> (); + #[no_mangle] + fn write_reg_osize(index: i32, value: i32) -> (); + #[no_mangle] + fn read_mmx32s(r: i32) -> i32; + #[no_mangle] + fn read_mmx64s(r: i32) -> reg64; + #[no_mangle] + fn write_mmx64(r: i32, low: i32, high: i32) -> (); + #[no_mangle] + fn write_mmx_reg64(r: i32, data: reg64) -> (); + #[no_mangle] + fn read_xmm_f32(r: i32) -> f32; + #[no_mangle] + fn read_xmm64s(r: i32) -> reg64; + #[no_mangle] + fn read_xmm128s(r: i32) -> reg128; + #[no_mangle] + fn write_xmm_f32(r: i32, data: f32) -> (); + #[no_mangle] + fn write_xmm32(r: i32, _: i32) -> (); + #[no_mangle] + fn write_xmm64(r: i32, data: reg64) -> (); + #[no_mangle] + fn write_xmm128(r: i32, i0: i32, i1: i32, i2: i32, i3: i32) -> (); + #[no_mangle] + fn write_xmm_reg128(r: i32, data: reg128) -> (); + #[no_mangle] + fn clear_tlb() -> (); + #[no_mangle] + fn full_clear_tlb() -> (); + #[no_mangle] + fn get_reg_asize(reg: i32) -> i32; + #[no_mangle] + fn set_tsc(_: u32, _: u32) -> (); + #[no_mangle] + fn read_tsc() -> u64; + #[no_mangle] + fn vm86_mode() -> bool; + #[no_mangle] + static M_LOG2E: f64; + #[no_mangle] + static M_LN2: f64; + #[no_mangle] + static M_LN10: f64; + #[no_mangle] + static M_PI: f64; + #[no_mangle] + static FPU_C0: i32; + #[no_mangle] + static FPU_C1: i32; + #[no_mangle] + static FPU_C2: i32; + #[no_mangle] + static FPU_C3: i32; + #[no_mangle] + static FPU_RESULT_FLAGS: i32; + #[no_mangle] + static FPU_STACK_TOP: i32; + #[no_mangle] + fn fpu_load_m32(addr: i32) -> f64; + #[no_mangle] + fn fpu_set_tag_word(tag_word: i32) -> (); + #[no_mangle] + static reg8: *mut u8; + #[no_mangle] + static reg16: *mut u16; + #[no_mangle] + static reg8s: *mut i8; + #[no_mangle] + static reg16s: *mut i16; + #[no_mangle] + static reg32s: *mut i32; + #[no_mangle] + static last_op1: *mut i32; + #[no_mangle] + static last_op2: *mut i32; + #[no_mangle] + static last_op_size: *mut i32; + #[no_mangle] + static last_add_result: *mut i32; + #[no_mangle] + static last_result: *mut i32; + #[no_mangle] + static flags_changed: *mut i32; + #[no_mangle] + static flags: *mut i32; + #[no_mangle] + static page_fault: *mut bool; + #[no_mangle] + static a20_enabled: *mut bool; + #[no_mangle] + static instruction_pointer: *mut i32; + #[no_mangle] + static previous_ip: *mut i32; + #[no_mangle] + static idtr_size: *mut i32; + #[no_mangle] + static idtr_offset: *mut i32; + #[no_mangle] + static gdtr_size: *mut i32; + #[no_mangle] + static gdtr_offset: *mut i32; + #[no_mangle] + static cr: *mut i32; + #[no_mangle] + static cpl: *mut u8; + #[no_mangle] + static in_hlt: *mut bool; + #[no_mangle] + static last_virt_eip: *mut i32; + #[no_mangle] + static eip_phys: *mut i32; + #[no_mangle] + static last_virt_esp: *mut i32; + #[no_mangle] + static esp_phys: *mut i32; + #[no_mangle] + static sysenter_cs: *mut i32; + #[no_mangle] + static sysenter_esp: *mut i32; + #[no_mangle] + static sysenter_eip: *mut i32; + #[no_mangle] + static prefixes: *mut u8; + #[no_mangle] + static timestamp_counter: *mut u32; + #[no_mangle] + static sreg: *mut u16; + #[no_mangle] + static dreg: *mut i32; + #[no_mangle] + static fw_value: *mut i32; + #[no_mangle] + static segment_is_null: *mut bool; + #[no_mangle] + static segment_offsets: *mut i32; + #[no_mangle] + static segment_limits: *mut u32; + #[no_mangle] + static protected_mode: *mut bool; + #[no_mangle] + static is_32: *mut bool; + #[no_mangle] + static stack_size_32: *mut bool; + #[no_mangle] + static memory_size: *mut u32; + #[no_mangle] + static fpu_stack_empty: *mut i32; + #[no_mangle] + static mxcsr: *mut i32; + #[no_mangle] + static reg_xmm: *mut reg128; + #[no_mangle] + static current_tsc: *mut u64; + #[no_mangle] + static fpu_st: *mut f64; + #[no_mangle] + static fpu_st8: *mut u8; + #[no_mangle] + static fpu_st32: *mut i32; + #[no_mangle] + static fpu_stack_ptr: *mut u32; + #[no_mangle] + static fpu_control_word: *mut i32; + #[no_mangle] + static fpu_status_word: *mut i32; + #[no_mangle] + static fpu_opcode: *mut i32; + #[no_mangle] + static fpu_ip: *mut i32; + #[no_mangle] + static fpu_ip_selector: *mut i32; + #[no_mangle] + static fpu_dp: *mut i32; + #[no_mangle] + static fpu_dp_selector: *mut i32; + #[no_mangle] + static reg_mmx: *mut reg64; + #[no_mangle] + static opstats_buffer: *mut u32; + #[no_mangle] + static opstats_buffer_0f: *mut u32; + #[no_mangle] + static tlb_data: *mut i32; + #[no_mangle] + #[no_mangle] + #[no_mangle] + #[no_mangle] + fn load_ldt(_: i32) -> (); + #[no_mangle] + fn load_tr(_: i32) -> (); + #[no_mangle] + fn verr(_: i32) -> i32; + #[no_mangle] + fn verw(_: i32) -> i32; + #[no_mangle] + fn set_cr0(_: i32) -> i32; + #[no_mangle] + fn invlpg(_: i32) -> (); + #[no_mangle] + fn lar(_: i32, _: i32) -> i32; + #[no_mangle] + fn lsl(_: i32, _: i32) -> i32; + #[no_mangle] + fn undefined_instruction() -> (); + #[no_mangle] + fn mov_rm_r128(source: reg128, r: i32) -> (); + #[no_mangle] + fn mov_r_r128(r1: i32, r2: i32) -> (); + #[no_mangle] + fn mov_r_m128(addr: i32, r: i32) -> (); + #[no_mangle] + fn unimplemented_sse() -> (); + #[no_mangle] + fn movl_r128_m64(addr: i32, r: i32) -> (); + #[no_mangle] + fn movh_m64_r128(addr: i32, r: i32) -> (); + #[no_mangle] + fn movh_r128_m64(addr: i32, r: i32) -> (); + #[no_mangle] + fn convert_f64_to_i32(_: f64) -> i32; + #[no_mangle] + fn cpl_changed() -> (); + #[no_mangle] + fn update_cs_size(_: i32) -> (); + #[no_mangle] + fn test_o() -> bool; + #[no_mangle] + fn cmovcc16(condition: bool, value: i32, r: i32) -> (); + #[no_mangle] + fn cmovcc32(condition: bool, value: i32, r: i32) -> (); + #[no_mangle] + fn test_b() -> bool; + #[no_mangle] + fn test_z() -> bool; + #[no_mangle] + fn test_be() -> bool; + #[no_mangle] + fn test_s() -> bool; + #[no_mangle] + fn test_p() -> bool; + #[no_mangle] + fn test_l() -> bool; + #[no_mangle] + fn test_le() -> bool; + #[no_mangle] + fn pand_r128(source: reg128, r: i32) -> (); + #[no_mangle] + fn pandn_r128(source: reg128, r: i32) -> (); + #[no_mangle] + fn por_r128(source: reg128, r: i32) -> (); + #[no_mangle] + fn pxor_r128(source: reg128, r: i32) -> (); + #[no_mangle] + fn psrlw_r64(r: i32, shift: u32) -> (); + #[no_mangle] + fn psraw_r64(r: i32, shift: u32) -> (); + #[no_mangle] + fn psllw_r64(r: i32, shift: u32) -> (); + #[no_mangle] + fn psrlw_r128(r: i32, shift: u32) -> (); + #[no_mangle] + fn psraw_r128(r: i32, shift: u32) -> (); + #[no_mangle] + fn psllw_r128(r: i32, shift: u32) -> (); + #[no_mangle] + fn psrld_r64(r: i32, shift: u32) -> (); + #[no_mangle] + fn psrad_r64(r: i32, shift: u32) -> (); + #[no_mangle] + fn pslld_r64(r: i32, shift: u32) -> (); + #[no_mangle] + fn psrld_r128(r: i32, shift: u32) -> (); + #[no_mangle] + fn psrad_r128(r: i32, shift: u32) -> (); + #[no_mangle] + fn pslld_r128(r: i32, shift: u32) -> (); + #[no_mangle] + fn psrlq_r64(r: i32, shift: u32) -> (); + #[no_mangle] + fn psllq_r64(r: i32, shift: u32) -> (); + #[no_mangle] + fn psrlq_r128(r: i32, shift: u32) -> (); + #[no_mangle] + fn psllq_r128(r: i32, shift: u32) -> (); + #[no_mangle] + fn mov_r_m64(addr: i32, r: i32) -> (); + #[no_mangle] + fn jmpcc16(condition: bool, imm16: i32) -> (); + #[no_mangle] + fn jmpcc32(condition: bool, imm32: i32) -> (); + #[no_mangle] + fn setcc_reg(condition: bool, r: i32) -> (); + #[no_mangle] + fn setcc_mem(condition: bool, addr: i32) -> (); + #[no_mangle] + fn push16(imm16: i32) -> (); + #[no_mangle] + fn push32(imm32: i32) -> (); + #[no_mangle] + fn adjust_stack_reg(adjustment: i32) -> (); + #[no_mangle] + fn get_stack_pointer(offset: i32) -> i32; + #[no_mangle] + fn switch_seg(_: i32, _: i32) -> bool; + #[no_mangle] + fn cpuid() -> (); + #[no_mangle] + fn fxsave(addr: u32) -> (); + #[no_mangle] + fn fxrstor(addr: u32) -> (); + #[no_mangle] + fn getzf() -> bool; + #[no_mangle] + fn lss16(_: i32, _: i32, _: i32) -> (); + #[no_mangle] + fn lss32(_: i32, _: i32, _: i32) -> (); + #[no_mangle] + fn has_rand_int() -> bool; + #[no_mangle] + fn get_rand_int() -> i32; + #[no_mangle] + fn bswap(_: i32) -> i32; + #[no_mangle] + fn sse_comparison(op: i32, x: f64, y: f64) -> bool; + #[no_mangle] + fn sse_min(x: f64, y: f64) -> f64; + #[no_mangle] + fn sse_max(x: f64, y: f64) -> f64; + #[no_mangle] + fn sse_convert_f64_to_i32(x: f64) -> i32; +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed { + __f: f32, + __i: u32, +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union reg64 { + i8_0: [i8; 8], + i16_0: [i16; 4], + i32_0: [i32; 2], + i64_0: [i64; 1], + u8_0: [u8; 8], + u16_0: [u16; 4], + u32_0: [u32; 2], + u64_0: [u64; 1], + f32_0: [f32; 2], + f64_0: [f64; 1], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_0 { + __f: f64, + __i: u64, +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union reg128 { + i8_0: [i8; 16], + i16_0: [i16; 8], + i32_0: [i32; 4], + i64_0: [i64; 2], + u8_0: [u8; 16], + u16_0: [u16; 8], + u32_0: [u32; 4], + u64_0: [u64; 2], + f32_0: [f32; 4], + f64_0: [f64; 2], +} + +unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { + let mut __u: unnamed = unnamed { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { + let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x >= __y) as i32; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F00_0_mem(mut addr: i32) -> () { + c_comment!(("sldt")); + if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + trigger_ud(); + return; + } + else { + safe_write16(addr, *sreg.offset(LDTR as isize) as i32); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F00_0_reg(mut r: i32) -> () { + if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + trigger_ud(); + return; + } + else { + write_reg_osize(r, *sreg.offset(LDTR as isize) as i32); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F00_1_mem(mut addr: i32) -> () { + c_comment!(("str")); + if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + trigger_ud(); + return; + } + else { + safe_write16(addr, *sreg.offset(TR as isize) as i32); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F00_1_reg(mut r: i32) -> () { + if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + trigger_ud(); + return; + } + else { + write_reg_osize(r, *sreg.offset(TR as isize) as i32); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F00_2_mem(mut addr: i32) -> () { + c_comment!(("lldt")); + if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + trigger_ud(); + return; + } + else if 0 != *cpl.offset(0isize) { + trigger_gp_non_raising(0i32); + return; + } + else { + load_ldt(safe_read16(addr)); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F00_2_reg(mut r: i32) -> () { + if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + trigger_ud(); + return; + } + else if 0 != *cpl.offset(0isize) { + trigger_gp_non_raising(0i32); + return; + } + else { + load_ldt(read_reg16(r)); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F00_3_mem(mut addr: i32) -> () { + c_comment!(("ltr")); + if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + trigger_ud(); + return; + } + else if 0 != *cpl.offset(0isize) { + trigger_gp_non_raising(0i32); + return; + } + else { + load_tr(safe_read16(addr)); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F00_3_reg(mut r: i32) -> () { + if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + trigger_ud(); + return; + } + else if 0 != *cpl.offset(0isize) { + trigger_gp_non_raising(0i32); + return; + } + else { + load_tr(read_reg16(r)); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F00_4_mem(mut addr: i32) -> () { + if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + trigger_ud(); + return; + } + else { + verr(safe_read16(addr)); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F00_4_reg(mut r: i32) -> () { + if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + trigger_ud(); + return; + } + else { + verr(read_reg16(r)); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F00_5_mem(mut addr: i32) -> () { + if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + trigger_ud(); + return; + } + else { + verw(safe_read16(addr)); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F00_5_reg(mut r: i32) -> () { + if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + trigger_ud(); + return; + } + else { + verw(read_reg16(r)); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F01_0_reg(mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F01_0_mem(mut addr: i32) -> () { + c_comment!(("sgdt")); + writable_or_pagefault(addr, 6i32); + let mut mask: i32 = if 0 != is_osize_32() as i32 { + -1i32 + } + else { + 16777215i32 + }; + safe_write16(addr, *gdtr_size.offset(0isize)); + safe_write32(addr + 2i32, *gdtr_offset.offset(0isize) & mask); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F01_1_reg(mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F01_1_mem(mut addr: i32) -> () { + c_comment!(("sidt")); + writable_or_pagefault(addr, 6i32); + let mut mask: i32 = if 0 != is_osize_32() as i32 { + -1i32 + } + else { + 16777215i32 + }; + safe_write16(addr, *idtr_size.offset(0isize)); + safe_write32(addr + 2i32, *idtr_offset.offset(0isize) & mask); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F01_2_reg(mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F01_2_mem(mut addr: i32) -> () { + c_comment!(("lgdt")); + if 0 != *cpl.offset(0isize) { + trigger_gp_non_raising(0i32); + return; + } + else { + let mut size: i32 = safe_read16(addr); + let mut offset: i32 = safe_read32s(addr + 2i32); + let mut mask: i32 = if 0 != is_osize_32() as i32 { + -1i32 + } + else { + 16777215i32 + }; + *gdtr_size.offset(0isize) = size; + *gdtr_offset.offset(0isize) = offset & mask; + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F01_3_reg(mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F01_3_mem(mut addr: i32) -> () { + c_comment!(("lidt")); + if 0 != *cpl.offset(0isize) { + trigger_gp_non_raising(0i32); + return; + } + else { + let mut size: i32 = safe_read16(addr); + let mut offset: i32 = safe_read32s(addr + 2i32); + let mut mask: i32 = if 0 != is_osize_32() as i32 { + -1i32 + } + else { + 16777215i32 + }; + *idtr_size.offset(0isize) = size; + *idtr_offset.offset(0isize) = offset & mask; + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F01_4_reg(mut r: i32) -> () { + c_comment!(("smsw")); + write_reg_osize(r, *cr.offset(0isize)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F01_4_mem(mut addr: i32) -> () { + safe_write16(addr, *cr.offset(0isize) & 65535i32); +} +#[no_mangle] +pub unsafe extern "C" fn lmsw(mut new_cr0: i32) -> () { + new_cr0 = *cr.offset(0isize) & !15i32 | new_cr0 & 15i32; + if *protected_mode.offset(0isize) { + c_comment!(("lmsw cannot be used to switch back")); + new_cr0 |= CR0_PE + } + set_cr0(new_cr0); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F01_6_reg(mut r: i32) -> () { + if 0 != *cpl.offset(0isize) { + trigger_gp_non_raising(0i32); + return; + } + else { + lmsw(read_reg16(r)); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F01_6_mem(mut addr: i32) -> () { + if 0 != *cpl.offset(0isize) { + trigger_gp_non_raising(0i32); + return; + } + else { + lmsw(safe_read16(addr)); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F01_7_reg(mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F01_7_mem(mut addr: i32) -> () { + c_comment!(("invlpg")); + if 0 != *cpl.offset(0isize) { + trigger_gp_non_raising(0i32); + return; + } + else { + invlpg(addr); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F02_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + write_reg16(r, lar(____0, read_reg16(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F02_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r, lar(____0, read_reg16(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F02_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + write_reg32(r, lar(____0, read_reg32(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F02_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg32(r, lar(____0, read_reg32(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F03_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + write_reg16(r, lsl(____0, read_reg16(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F03_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r, lsl(____0, read_reg16(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F03_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + write_reg32(r, lsl(____0, read_reg32(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F03_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg32(r, lsl(____0, read_reg32(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F04() -> () { undefined_instruction(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F05() -> () { undefined_instruction(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F06() -> () { + c_comment!(("clts")); + if 0 != *cpl.offset(0isize) { + dbg_log_c!(("clts #gp")); + trigger_gp_non_raising(0i32); + } + else { + if 0 != 0i32 * 0i32 { + dbg_log_c!(("clts")); + } + let ref mut fresh0 = *cr.offset(0isize); + *fresh0 &= !CR0_TS + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F07() -> () { undefined_instruction(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F08() -> () { + c_comment!(("invd")); + undefined_instruction(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F09() -> () { + if 0 != *cpl.offset(0isize) { + dbg_log_c!(("wbinvd #gp")); + trigger_gp_non_raising(0i32); + } + else { + c_comment!(("wbinvd")); + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F0A() -> () { undefined_instruction(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F0B() -> () { + c_comment!(("UD2")); + trigger_ud(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F0C() -> () { undefined_instruction(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F0D() -> () { + c_comment!(("nop")); + undefined_instruction(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F0E() -> () { undefined_instruction(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F0F() -> () { undefined_instruction(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F10(mut source: reg128, mut r: i32) -> () { + c_comment!(("movups xmm, xmm/m128")); + mov_rm_r128(source, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F10_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F10(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F10_mem(mut addr: i32, mut r: i32) -> () { + instr_0F10(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F10_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("movss xmm, xmm/m32")); + let mut data: reg128 = read_xmm128s(r1); + let mut orig: reg128 = read_xmm128s(r2); + write_xmm128( + r2, + data.u32_0[0usize] as i32, + orig.u32_0[1usize] as i32, + orig.u32_0[2usize] as i32, + orig.u32_0[3usize] as i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F10_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movss xmm, xmm/m32")); + let mut data: i32 = safe_read32s(addr); + write_xmm128(r, data, 0i32, 0i32, 0i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F10(mut source: reg128, mut r: i32) -> () { + c_comment!(("movupd xmm, xmm/m128")); + mov_rm_r128(source, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F10_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F10(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F10_mem(mut addr: i32, mut r: i32) -> () { + instr_660F10(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F10_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("movsd xmm, xmm/m64")); + let mut data: reg128 = read_xmm128s(r1); + let mut orig: reg128 = read_xmm128s(r2); + write_xmm128( + r2, + data.u32_0[0usize] as i32, + data.u32_0[1usize] as i32, + orig.u32_0[2usize] as i32, + orig.u32_0[3usize] as i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F10_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movsd xmm, xmm/m64")); + let mut data: reg64 = safe_read64s(addr); + write_xmm128( + r, + data.u32_0[0usize] as i32, + data.u32_0[1usize] as i32, + 0i32, + 0i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F11_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("movups xmm/m128, xmm")); + mov_r_r128(r1, r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F11_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movups xmm/m128, xmm")); + mov_r_m128(addr, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F11_reg(mut rm_dest: i32, mut reg_src: i32) -> () { + c_comment!(("movss xmm/m32, xmm")); + let mut data: reg128 = read_xmm128s(reg_src); + let mut orig: reg128 = read_xmm128s(rm_dest); + write_xmm128( + rm_dest, + data.u32_0[0usize] as i32, + orig.u32_0[1usize] as i32, + orig.u32_0[2usize] as i32, + orig.u32_0[3usize] as i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F11_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movss xmm/m32, xmm")); + let mut data: reg128 = read_xmm128s(r); + safe_write32(addr, data.u32_0[0usize] as i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F11_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("movupd xmm/m128, xmm")); + mov_r_r128(r1, r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F11_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movupd xmm/m128, xmm")); + mov_r_m128(addr, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F11_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("movsd xmm/m64, xmm")); + let mut data: reg128 = read_xmm128s(r2); + let mut orig: reg128 = read_xmm128s(r1); + write_xmm128( + r1, + data.u32_0[0usize] as i32, + data.u32_0[1usize] as i32, + orig.u32_0[2usize] as i32, + orig.u32_0[3usize] as i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F11_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movsd xmm/m64, xmm")); + let mut data: reg64 = read_xmm64s(r); + safe_write64(addr, data.u64_0[0usize] as i64); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F12_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movlps xmm, m64")); + let mut data: reg64 = safe_read64s(addr); + let mut orig: reg128 = read_xmm128s(r); + write_xmm128( + r, + data.u32_0[0usize] as i32, + data.u32_0[1usize] as i32, + orig.u32_0[2usize] as i32, + orig.u32_0[3usize] as i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F12_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("movhlps xmm, xmm")); + let mut data: reg128 = read_xmm128s(r1); + let mut orig: reg128 = read_xmm128s(r2); + write_xmm128( + r2, + data.u32_0[2usize] as i32, + data.u32_0[3usize] as i32, + orig.u32_0[2usize] as i32, + orig.u32_0[3usize] as i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F12_reg(mut r1: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660F12_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movlpd xmm, m64")); + let mut data: reg64 = safe_read64s(addr); + write_xmm64(r, data); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F12_mem(mut addr: i32, mut r: i32) -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_F20F12_reg(mut r1: i32, mut r2: i32) -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_F30F12_mem(mut addr: i32, mut r: i32) -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_F30F12_reg(mut r1: i32, mut r2: i32) -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F13_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movlps m64, xmm")); + movl_r128_m64(addr, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F13_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660F13_reg(mut r1: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660F13_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movlpd xmm/m64, xmm")); + movl_r128_m64(addr, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F14(mut source: reg64, mut r: i32) -> () { + c_comment!(("unpcklps xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg64 = read_xmm64s(r); + write_xmm128( + r, + destination.u32_0[0usize] as i32, + source.u32_0[0usize] as i32, + destination.u32_0[1usize] as i32, + source.u32_0[1usize] as i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F14_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F14(read_xmm64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F14_mem(mut addr: i32, mut r: i32) -> () { + instr_0F14(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F14(mut source: reg64, mut r: i32) -> () { + c_comment!(("unpcklpd xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg64 = read_xmm64s(r); + write_xmm128( + r, + destination.u32_0[0usize] as i32, + destination.u32_0[1usize] as i32, + source.u32_0[0usize] as i32, + source.u32_0[1usize] as i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F14_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F14(read_xmm64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F14_mem(mut addr: i32, mut r: i32) -> () { + instr_660F14(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F15(mut source: reg128, mut r: i32) -> () { + c_comment!(("unpckhps xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + write_xmm128( + r, + destination.u32_0[2usize] as i32, + source.u32_0[2usize] as i32, + destination.u32_0[3usize] as i32, + source.u32_0[3usize] as i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F15_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F15(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F15_mem(mut addr: i32, mut r: i32) -> () { + instr_0F15(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F15(mut source: reg128, mut r: i32) -> () { + c_comment!(("unpckhpd xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + write_xmm128( + r, + destination.u32_0[2usize] as i32, + destination.u32_0[3usize] as i32, + source.u32_0[2usize] as i32, + source.u32_0[3usize] as i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F15_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F15(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F15_mem(mut addr: i32, mut r: i32) -> () { + instr_660F15(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F16_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movhps xmm, m64")); + movh_m64_r128(addr, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F16_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("movlhps xmm, xmm")); + let mut data: reg128 = read_xmm128s(r1); + let mut orig: reg128 = read_xmm128s(r2); + write_xmm128( + r2, + orig.u32_0[0usize] as i32, + orig.u32_0[1usize] as i32, + data.u32_0[0usize] as i32, + data.u32_0[1usize] as i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F16_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movhpd xmm, m64")); + movh_m64_r128(addr, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F16_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F17_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movhps m64, xmm")); + movh_r128_m64(addr, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F17_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660F17_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movhpd m64, xmm")); + movh_r128_m64(addr, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F17_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F18_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("reserved nop")); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F18_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("prefetch")); + c_comment!(("nop for us")); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F1A() -> () { undefined_instruction(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F1B() -> () { undefined_instruction(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F1F_reg(mut r1: i32, mut r2: i32) -> () {} +#[no_mangle] +pub unsafe extern "C" fn instr_0F1F_mem(mut addr: i32, mut r: i32) -> () {} +#[no_mangle] +pub unsafe extern "C" fn instr_0F20(mut r: i32, mut creg: i32) -> () { + if 0 != *cpl.offset(0isize) { + trigger_gp_non_raising(0i32); + return; + } + else { + match creg { + 0 => { + write_reg32(r, *cr.offset(0isize)); + }, + 2 => { + write_reg32(r, *cr.offset(2isize)); + }, + 3 => { + write_reg32(r, *cr.offset(3isize)); + }, + 4 => { + write_reg32(r, *cr.offset(4isize)); + }, + _ => { + dbg_log_c!(("%d"), creg); + undefined_instruction(); + }, + } + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F21(mut r: i32, mut dreg_index: i32) -> () { + if 0 != *cpl.offset(0isize) { + trigger_gp_non_raising(0i32); + return; + } + else { + if dreg_index == 4i32 || dreg_index == 5i32 { + if 0 != *cr.offset(4isize) & CR4_DE { + dbg_log_c!(("#ud mov dreg 4/5 with cr4.DE set")); + trigger_ud(); + return; + } + else { + c_comment!(("DR4 and DR5 refer to DR6 and DR7 respectively")); + dreg_index += 2i32 + } + } + write_reg32(r, *dreg.offset(dreg_index as isize)); + if 0 != 0i32 * 0i32 { + dbg_log_c!( + ("read dr%d: %x"), + dreg_index, + *dreg.offset(dreg_index as isize) + ); + } + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F22(mut r: i32, mut creg: i32) -> () { + if 0 != *cpl.offset(0isize) { + trigger_gp_non_raising(0i32); + return; + } + else { + let mut data: i32 = read_reg32(r); + c_comment!(("mov cr, addr")); + match creg { + 0 => { + if 0 != 0i32 * 0i32 { + dbg_log_c!(("cr0 <- %x"), data); + } + set_cr0(data); + }, + 2 => { + dbg_log_c!(("cr2 <- %x"), data); + *cr.offset(2isize) = data + }, + 3 => { + if 0 != 0i32 * 0i32 { + dbg_log_c!(("cr3 <- %x"), data); + } + data &= !4071i32; + dbg_assert!(data & 4095i32 == 0i32, ("TODO")); + *cr.offset(3isize) = data; + clear_tlb(); + }, + 4 => { + dbg_log_c!(("cr4 <- %d"), *cr.offset(4isize)); + if 0 != data as u32 + & ((1i32 << 11i32 + | 1i32 << 12i32 + | 1i32 << 15i32 + | 1i32 << 16i32 + | 1i32 << 19i32) as u32 + | 4290772992u32) + { + dbg_log_c!(("trigger_gp: Invalid cr4 bit")); + trigger_gp_non_raising(0i32); + return; + } + else { + if 0 != (*cr.offset(4isize) ^ data) & (CR4_PGE | CR4_PSE) { + full_clear_tlb(); + } + *cr.offset(4isize) = data; + if 0 != *cr.offset(4isize) & CR4_PAE { + dbg_assert!(0 != 0i32); + } + } + }, + _ => { + dbg_log_c!(("%d"), creg); + undefined_instruction(); + }, + } + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F23(mut r: i32, mut dreg_index: i32) -> () { + if 0 != *cpl.offset(0isize) { + trigger_gp_non_raising(0i32); + return; + } + else { + if dreg_index == 4i32 || dreg_index == 5i32 { + if 0 != *cr.offset(4isize) & CR4_DE { + dbg_log_c!(("#ud mov dreg 4/5 with cr4.DE set")); + trigger_ud(); + return; + } + else { + c_comment!(("DR4 and DR5 refer to DR6 and DR7 respectively")); + dreg_index += 2i32 + } + } + *dreg.offset(dreg_index as isize) = read_reg32(r); + if 0 != 0i32 * 0i32 { + dbg_log_c!( + ("write dr%d: %x"), + dreg_index, + *dreg.offset(dreg_index as isize) + ); + } + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F24() -> () { undefined_instruction(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F25() -> () { undefined_instruction(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F26() -> () { undefined_instruction(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F27() -> () { undefined_instruction(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F28(mut source: reg128, mut r: i32) -> () { + c_comment!(("movaps xmm, xmm/m128")); + c_comment!(("XXX: Aligned read or #gp")); + mov_rm_r128(source, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F28_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F28(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F28_mem(mut addr: i32, mut r: i32) -> () { + instr_0F28(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F28(mut source: reg128, mut r: i32) -> () { + c_comment!(("movapd xmm, xmm/m128")); + c_comment!(("XXX: Aligned read or #gp")); + c_comment!(("Note: Same as movdqa (660F6F)")); + mov_rm_r128(source, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F28_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F28(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F28_mem(mut addr: i32, mut r: i32) -> () { + instr_660F28(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F29_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movaps m128, xmm")); + let mut data: reg128 = read_xmm128s(r); + c_comment!(("XXX: Aligned write or #gp")); + safe_write128(addr, data); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F29_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("movaps xmm, xmm")); + mov_r_r128(r1, r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F29_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movapd m128, xmm")); + let mut data: reg128 = read_xmm128s(r); + c_comment!(("XXX: Aligned write or #gp")); + safe_write128(addr, data); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F29_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("movapd xmm, xmm")); + mov_r_r128(r1, r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F2B_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F2B_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movntps m128, xmm")); + c_comment!(("XXX: Aligned write or #gp")); + mov_r_m128(addr, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F2B_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660F2B_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movntpd m128, xmm")); + c_comment!(("XXX: Aligned write or #gp")); + mov_r_m128(addr, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F2C_mem(mut addr: i32, mut r: i32) -> () { + instr_0F2C(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F2C(mut source: reg64, mut r: i32) -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F2C_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F2C(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F2C_mem(mut addr: i32, mut r: i32) -> () { + instr_660F2C(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F2C(mut source: reg128, mut r: i32) -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660F2C_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F2C(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F2C(mut source: reg64, mut r: i32) -> () { + let mut si: i32 = 0; + c_comment!(("cvttsd2si r32, xmm/m64")); + c_comment!( + ("emscripten bug causes this ported instruction to throw \'integer result unpresentable\'") + ); + c_comment!(("https://github.com/kripken/emscripten/issues/5433")); + if 0 != 0i32 * 0i32 { + let mut f: f64 = source.f64_0[0usize]; + if f <= 2147483647i32 as f64 && f >= 2147483648u32.wrapping_neg() as f64 { + si = f as i32; + write_reg32(r, si); + } + else { + write_reg32(r, 2147483648u32 as i32); + } + } + else { + write_reg32(r, convert_f64_to_i32(source.f64_0[0usize])); + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F2C_reg(mut r1: i32, mut r2: i32) -> () { + instr_F20F2C(read_xmm64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F2C_mem(mut addr: i32, mut r: i32) -> () { + instr_F20F2C(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F2C_mem(mut addr: i32, mut r: i32) -> () { + instr_F30F2C(fpu_load_m32(addr) as f32, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F2C(mut source: f32, mut r: i32) -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_F30F2C_reg(mut r1: i32, mut r2: i32) -> () { + instr_F30F2C(read_xmm_f32(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F2E() -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F2F() -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F30() -> () { + c_comment!(("wrmsr - write maschine specific register")); + if 0 != *cpl.offset(0isize) { + trigger_gp_non_raising(0i32); + return; + } + else { + let mut index: i32 = *reg32s.offset(ECX as isize); + let mut low: i32 = *reg32s.offset(EAX as isize); + let mut high: i32 = *reg32s.offset(EDX as isize); + if index != IA32_SYSENTER_ESP { + dbg_log_c!(("wrmsr ecx=%x data=%x:%x"), index, high, low); + } + if index == IA32_SYSENTER_CS { + *sysenter_cs.offset(0isize) = low & 65535i32 + } + else if index == IA32_SYSENTER_EIP { + *sysenter_eip.offset(0isize) = low + } + else if index == IA32_SYSENTER_ESP { + *sysenter_esp.offset(0isize) = low + } + else if index == IA32_APIC_BASE_MSR { + dbg_assert!( + high == 0i32, + ("Changing APIC address (high 32 bits) not supported") + ); + let mut address: i32 = + low & !(IA32_APIC_BASE_BSP | IA32_APIC_BASE_EXTD | IA32_APIC_BASE_EN); + dbg_assert!( + address == APIC_ADDRESS, + ("Changing APIC address not supported") + ); + dbg_assert!(low & IA32_APIC_BASE_EXTD == 0i32, ("x2apic not supported")); + apic_enabled = low & IA32_APIC_BASE_EN == IA32_APIC_BASE_EN + } + else if index == IA32_TIME_STAMP_COUNTER { + set_tsc(low as u32, high as u32); + } + else if !(index == IA32_BIOS_SIGN_ID) { + if index == MSR_MISC_FEATURE_ENABLES { + c_comment!(("Linux 4, see: https://patchwork.kernel.org/patch/9528279/")); + } + else if index == IA32_MISC_ENABLE { + c_comment!(("Enable Misc. Processor Features")); + } + else if index == IA32_MCG_CAP { + c_comment!(("netbsd")); + } + else if index == IA32_KERNEL_GS_BASE { + c_comment!(("Only used in 64 bit mode (by SWAPGS), but set by kvm-unit-test")); + dbg_log_c!(("GS Base written")); + } + else { + dbg_log_c!(("Unknown msr: %x"), index); + dbg_assert!(0 != 0i32); + } + } + return; + }; +} +#[no_mangle] +pub static mut apic_enabled: bool = unsafe { 0 != 0i32 }; +#[no_mangle] +pub unsafe extern "C" fn instr_0F31() -> () { + c_comment!(("rdtsc - read timestamp counter")); + if 0 == *cpl.offset(0isize) || 0 == *cr.offset(4isize) & CR4_TSD { + let mut tsc: u64 = read_tsc(); + *reg32s.offset(EAX as isize) = tsc as i32; + *reg32s.offset(EDX as isize) = (tsc >> 32i32) as i32; + if 0 != 0i32 * 0i32 { + dbg_log_c!( + ("rdtsc edx:eax=%x:%x"), + *reg32s.offset(EDX as isize), + *reg32s.offset(EAX as isize) + ); + } + } + else { + trigger_gp_non_raising(0i32); + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F32() -> () { + c_comment!(("rdmsr - read maschine specific register")); + if 0 != *cpl.offset(0isize) { + trigger_gp_non_raising(0i32); + return; + } + else { + let mut index: i32 = *reg32s.offset(ECX as isize); + dbg_log_c!(("rdmsr ecx=%x"), index); + let mut low: i32 = 0i32; + let mut high: i32 = 0i32; + if index == IA32_SYSENTER_CS { + low = *sysenter_cs.offset(0isize) + } + else if index == IA32_SYSENTER_EIP { + low = *sysenter_eip.offset(0isize) + } + else if index == IA32_SYSENTER_ESP { + low = *sysenter_esp.offset(0isize) + } + else if index == IA32_TIME_STAMP_COUNTER { + let mut tsc: u64 = read_tsc(); + low = tsc as i32; + high = (tsc >> 32i32) as i32 + } + else if !(index == IA32_PLATFORM_ID) { + if index == IA32_APIC_BASE_MSR { + if ENABLE_ACPI { + low = APIC_ADDRESS; + if apic_enabled { + low |= IA32_APIC_BASE_EN + } + } + } + else if !(index == IA32_BIOS_SIGN_ID) { + if index == MSR_PLATFORM_INFO { + low = 1i32 << 8i32 + } + else if !(index == MSR_MISC_FEATURE_ENABLES) { + if index == IA32_MISC_ENABLE { + c_comment!(("Enable Misc. Processor Features")); + low = 1i32 << 0i32; + c_comment!(("fast string")); + } + else if index == IA32_RTIT_CTL { + c_comment!(("linux4")); + } + else if !(index == MSR_SMI_COUNT) { + if index == IA32_MCG_CAP { + c_comment!(("netbsd")); + } + else if !(index == MSR_PKG_C2_RESIDENCY) { + dbg_log_c!(("Unknown msr: %x"), index); + dbg_assert!(0 != 0i32); + } + } + } + } + } + *reg32s.offset(EAX as isize) = low; + *reg32s.offset(EDX as isize) = high; + return; + }; +} +#[no_mangle] +pub static mut ENABLE_ACPI: bool = unsafe { 0 != 1i32 }; +#[no_mangle] +pub unsafe extern "C" fn instr_0F33() -> () { + c_comment!(("rdpmc")); + undefined_instruction(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F34() -> () { + c_comment!(("sysenter")); + let mut seg: i32 = *sysenter_cs.offset(0isize) & 65532i32; + if !*protected_mode.offset(0isize) || seg == 0i32 { + trigger_gp_non_raising(0i32); + return; + } + else { + let ref mut fresh1 = *flags.offset(0isize); + *fresh1 &= !FLAG_VM & !FLAG_INTERRUPT; + *instruction_pointer.offset(0isize) = *sysenter_eip.offset(0isize); + *reg32s.offset(ESP as isize) = *sysenter_esp.offset(0isize); + *sreg.offset(CS as isize) = seg as u16; + *segment_is_null.offset(CS as isize) = 0 != 0i32; + *segment_limits.offset(CS as isize) = -1i32 as u32; + *segment_offsets.offset(CS as isize) = 0i32; + update_cs_size(1i32); + *cpl.offset(0isize) = 0i32 as u8; + cpl_changed(); + *sreg.offset(SS as isize) = (seg + 8i32) as u16; + *segment_is_null.offset(SS as isize) = 0 != 0i32; + *segment_limits.offset(SS as isize) = -1i32 as u32; + *segment_offsets.offset(SS as isize) = 0i32; + *stack_size_32.offset(0isize) = 0 != 1i32; + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F35() -> () { + c_comment!(("sysexit")); + let mut seg: i32 = *sysenter_cs.offset(0isize) & 65532i32; + if !*protected_mode.offset(0isize) || 0 != *cpl.offset(0isize) as i32 || seg == 0i32 { + trigger_gp_non_raising(0i32); + return; + } + else { + *instruction_pointer.offset(0isize) = *reg32s.offset(EDX as isize); + *reg32s.offset(ESP as isize) = *reg32s.offset(ECX as isize); + *sreg.offset(CS as isize) = (seg + 16i32 | 3i32) as u16; + *segment_is_null.offset(CS as isize) = 0 != 0i32; + *segment_limits.offset(CS as isize) = -1i32 as u32; + *segment_offsets.offset(CS as isize) = 0i32; + update_cs_size(1i32); + *cpl.offset(0isize) = 3i32 as u8; + cpl_changed(); + *sreg.offset(SS as isize) = (seg + 24i32 | 3i32) as u16; + *segment_is_null.offset(SS as isize) = 0 != 0i32; + *segment_limits.offset(SS as isize) = -1i32 as u32; + *segment_offsets.offset(SS as isize) = 0i32; + *stack_size_32.offset(0isize) = 0 != 1i32; + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F36() -> () { undefined_instruction(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F37() -> () { + c_comment!(("getsec")); + undefined_instruction(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F38() -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F39() -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F3A() -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F3B() -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F3C() -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F3D() -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F3E() -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F3F() -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0F40_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + cmovcc16(test_o(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F40_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + cmovcc16(test_o(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F40_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + cmovcc32(test_o(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F40_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + cmovcc32(test_o(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F41_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + cmovcc16(!test_o(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F41_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + cmovcc16(!test_o(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F41_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + cmovcc32(!test_o(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F41_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + cmovcc32(!test_o(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F42_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + cmovcc16(test_b(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F42_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + cmovcc16(test_b(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F42_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + cmovcc32(test_b(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F42_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + cmovcc32(test_b(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F43_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + cmovcc16(!test_b(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F43_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + cmovcc16(!test_b(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F43_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + cmovcc32(!test_b(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F43_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + cmovcc32(!test_b(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F44_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + cmovcc16(test_z(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F44_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + cmovcc16(test_z(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F44_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + cmovcc32(test_z(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F44_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + cmovcc32(test_z(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F45_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + cmovcc16(!test_z(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F45_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + cmovcc16(!test_z(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F45_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + cmovcc32(!test_z(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F45_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + cmovcc32(!test_z(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F46_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + cmovcc16(test_be(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F46_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + cmovcc16(test_be(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F46_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + cmovcc32(test_be(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F46_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + cmovcc32(test_be(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F47_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + cmovcc16(!test_be(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F47_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + cmovcc16(!test_be(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F47_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + cmovcc32(!test_be(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F47_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + cmovcc32(!test_be(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F48_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + cmovcc16(test_s(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F48_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + cmovcc16(test_s(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F48_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + cmovcc32(test_s(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F48_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + cmovcc32(test_s(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F49_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + cmovcc16(!test_s(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F49_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + cmovcc16(!test_s(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F49_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + cmovcc32(!test_s(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F49_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + cmovcc32(!test_s(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F4A_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + cmovcc16(test_p(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F4A_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + cmovcc16(test_p(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F4A_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + cmovcc32(test_p(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F4A_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + cmovcc32(test_p(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F4B_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + cmovcc16(!test_p(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F4B_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + cmovcc16(!test_p(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F4B_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + cmovcc32(!test_p(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F4B_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + cmovcc32(!test_p(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F4C_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + cmovcc16(test_l(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F4C_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + cmovcc16(test_l(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F4C_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + cmovcc32(test_l(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F4C_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + cmovcc32(test_l(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F4D_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + cmovcc16(!test_l(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F4D_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + cmovcc16(!test_l(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F4D_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + cmovcc32(!test_l(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F4D_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + cmovcc32(!test_l(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F4E_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + cmovcc16(test_le(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F4E_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + cmovcc16(test_le(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F4E_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + cmovcc32(test_le(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F4E_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + cmovcc32(test_le(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F4F_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + cmovcc16(!test_le(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F4F_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + cmovcc16(!test_le(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F4F_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + cmovcc32(!test_le(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0F4F_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + cmovcc32(!test_le(), ____0, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F50_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("movmskps r, xmm")); + let mut source: reg128 = read_xmm128s(r1); + let mut data: i32 = (source.u32_0[0usize] >> 31i32 + | source.u32_0[1usize] >> 31i32 << 1i32 + | source.u32_0[2usize] >> 31i32 << 2i32 + | source.u32_0[3usize] >> 31i32 << 3i32) as i32; + write_reg32(r2, data); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F50_mem(mut addr: i32, mut r1: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660F50_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("movmskpd r, xmm")); + let mut source: reg128 = read_xmm128s(r1); + let mut data: i32 = + (source.u32_0[1usize] >> 31i32 | source.u32_0[3usize] >> 31i32 << 1i32) as i32; + write_reg32(r2, data); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F50_mem(mut addr: i32, mut r1: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F54(mut source: reg128, mut r: i32) -> () { + c_comment!(("andps xmm, xmm/mem128")); + c_comment!(("XXX: Aligned access or #gp")); + pand_r128(source, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F54_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F54(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F54_mem(mut addr: i32, mut r: i32) -> () { + instr_0F54(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F54(mut source: reg128, mut r: i32) -> () { + c_comment!(("andpd xmm, xmm/mem128")); + c_comment!(("XXX: Aligned access or #gp")); + pand_r128(source, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F54_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F54(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F54_mem(mut addr: i32, mut r: i32) -> () { + instr_660F54(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F55(mut source: reg128, mut r: i32) -> () { + c_comment!(("andnps xmm, xmm/mem128")); + c_comment!(("XXX: Aligned access or #gp")); + pandn_r128(source, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F55_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F55(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F55_mem(mut addr: i32, mut r: i32) -> () { + instr_0F55(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F55(mut source: reg128, mut r: i32) -> () { + c_comment!(("andnpd xmm, xmm/mem128")); + c_comment!(("XXX: Aligned access or #gp")); + pandn_r128(source, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F55_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F55(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F55_mem(mut addr: i32, mut r: i32) -> () { + instr_660F55(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F56(mut source: reg128, mut r: i32) -> () { + c_comment!(("orps xmm, xmm/mem128")); + c_comment!(("XXX: Aligned access or #gp")); + por_r128(source, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F56_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F56(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F56_mem(mut addr: i32, mut r: i32) -> () { + instr_0F56(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F56(mut source: reg128, mut r: i32) -> () { + c_comment!(("orpd xmm, xmm/mem128")); + c_comment!(("XXX: Aligned access or #gp")); + por_r128(source, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F56_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F56(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F56_mem(mut addr: i32, mut r: i32) -> () { + instr_660F56(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F57(mut source: reg128, mut r: i32) -> () { + c_comment!(("xorps xmm, xmm/mem128")); + c_comment!(("XXX: Aligned access or #gp")); + pxor_r128(source, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F57_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F57(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F57_mem(mut addr: i32, mut r: i32) -> () { + instr_0F57(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F57(mut source: reg128, mut r: i32) -> () { + c_comment!(("xorpd xmm, xmm/mem128")); + c_comment!(("XXX: Aligned access or #gp")); + pxor_r128(source, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F57_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F57(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F57_mem(mut addr: i32, mut r: i32) -> () { + instr_660F57(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F60(mut source: i32, mut r: i32) -> () { + c_comment!(("punpcklbw mm, mm/m32")); + let mut destination: reg64 = read_mmx64s(r); + let mut byte0: i32 = destination.u8_0[0usize] as i32; + let mut byte1: i32 = source & 255i32; + let mut byte2: i32 = destination.u8_0[1usize] as i32; + let mut byte3: i32 = source >> 8i32 & 255i32; + let mut byte4: i32 = destination.u8_0[2usize] as i32; + let mut byte5: i32 = source >> 16i32 & 255i32; + let mut byte6: i32 = destination.u8_0[3usize] as i32; + let mut byte7: i32 = source >> 24i32; + let mut low: i32 = byte0 | byte1 << 8i32 | byte2 << 16i32 | byte3 << 24i32; + let mut high: i32 = byte4 | byte5 << 8i32 | byte6 << 16i32 | byte7 << 24i32; + write_mmx64(r, low, high); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F60_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F60(read_mmx32s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F60_mem(mut addr: i32, mut r: i32) -> () { + instr_0F60(safe_read32s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F60(mut source: reg64, mut r: i32) -> () { + c_comment!(("punpcklbw xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg64 = read_xmm64s(r); + write_xmm128( + r, + destination.u8_0[0usize] as i32 + | (source.u8_0[0usize] as i32) << 8i32 + | (destination.u8_0[1usize] as i32) << 16i32 + | (source.u8_0[1usize] as i32) << 24i32, + destination.u8_0[2usize] as i32 + | (source.u8_0[2usize] as i32) << 8i32 + | (destination.u8_0[3usize] as i32) << 16i32 + | (source.u8_0[3usize] as i32) << 24i32, + destination.u8_0[4usize] as i32 + | (source.u8_0[4usize] as i32) << 8i32 + | (destination.u8_0[5usize] as i32) << 16i32 + | (source.u8_0[5usize] as i32) << 24i32, + destination.u8_0[6usize] as i32 + | (source.u8_0[6usize] as i32) << 8i32 + | (destination.u8_0[7usize] as i32) << 16i32 + | (source.u8_0[7usize] as i32) << 24i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F60_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F60(read_xmm64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F60_mem(mut addr: i32, mut r: i32) -> () { + instr_660F60(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F61(mut source: i32, mut r: i32) -> () { + c_comment!(("punpcklwd mm, mm/m32")); + let mut destination: reg64 = read_mmx64s(r); + let mut word0: i32 = destination.u16_0[0usize] as i32; + let mut word1: i32 = source & 65535i32; + let mut word2: i32 = destination.u16_0[1usize] as i32; + let mut word3: i32 = source >> 16i32; + let mut low: i32 = word0 | word1 << 16i32; + let mut high: i32 = word2 | word3 << 16i32; + write_mmx64(r, low, high); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F61_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F61(read_mmx32s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F61_mem(mut addr: i32, mut r: i32) -> () { + instr_0F61(safe_read32s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F61(mut source: reg64, mut r: i32) -> () { + c_comment!(("punpcklwd xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg64 = read_xmm64s(r); + write_xmm128( + r, + destination.u16_0[0usize] as i32 | (source.u16_0[0usize] as i32) << 16i32, + destination.u16_0[1usize] as i32 | (source.u16_0[1usize] as i32) << 16i32, + destination.u16_0[2usize] as i32 | (source.u16_0[2usize] as i32) << 16i32, + destination.u16_0[3usize] as i32 | (source.u16_0[3usize] as i32) << 16i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F61_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F61(read_xmm64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F61_mem(mut addr: i32, mut r: i32) -> () { + instr_660F61(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F62(mut source: i32, mut r: i32) -> () { + c_comment!(("punpckldq mm, mm/m32")); + let mut destination: reg64 = read_mmx64s(r); + write_mmx64(r, destination.u32_0[0usize] as i32, source); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F62_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F62(read_mmx32s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F62_mem(mut addr: i32, mut r: i32) -> () { + instr_0F62(safe_read32s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F62(mut source: reg128, mut r: i32) -> () { + c_comment!(("punpckldq xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + write_xmm128( + r, + destination.u32_0[0usize] as i32, + source.u32_0[0usize] as i32, + destination.u32_0[1usize] as i32, + source.u32_0[1usize] as i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F62_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F62(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F62_mem(mut addr: i32, mut r: i32) -> () { + instr_660F62(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F63(mut source: reg64, mut r: i32) -> () { + c_comment!(("packsswb mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut low: i32 = saturate_sw_to_sb(destination.u16_0[0usize] as i32) + | saturate_sw_to_sb(destination.u16_0[1usize] as i32) << 8i32 + | saturate_sw_to_sb(destination.u16_0[2usize] as i32) << 16i32 + | saturate_sw_to_sb(destination.u16_0[3usize] as i32) << 24i32; + let mut high: i32 = saturate_sw_to_sb(source.u16_0[0usize] as i32) + | saturate_sw_to_sb(source.u16_0[1usize] as i32) << 8i32 + | saturate_sw_to_sb(source.u16_0[2usize] as i32) << 16i32 + | saturate_sw_to_sb(source.u16_0[3usize] as i32) << 24i32; + write_mmx64(r, low, high); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F63_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F63(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F63_mem(mut addr: i32, mut r: i32) -> () { + instr_0F63(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F63(mut source: reg128, mut r: i32) -> () { + c_comment!(("packsswb xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut dword0: i32 = saturate_sw_to_sb(destination.u16_0[0usize] as i32) + | saturate_sw_to_sb(destination.u16_0[1usize] as i32) << 8i32 + | saturate_sw_to_sb(destination.u16_0[2usize] as i32) << 16i32 + | saturate_sw_to_sb(destination.u16_0[3usize] as i32) << 24i32; + let mut dword1: i32 = saturate_sw_to_sb(destination.u16_0[4usize] as i32) + | saturate_sw_to_sb(destination.u16_0[5usize] as i32) << 8i32 + | saturate_sw_to_sb(destination.u16_0[6usize] as i32) << 16i32 + | saturate_sw_to_sb(destination.u16_0[7usize] as i32) << 24i32; + let mut dword2: i32 = saturate_sw_to_sb(source.u16_0[0usize] as i32) + | saturate_sw_to_sb(source.u16_0[1usize] as i32) << 8i32 + | saturate_sw_to_sb(source.u16_0[2usize] as i32) << 16i32 + | saturate_sw_to_sb(source.u16_0[3usize] as i32) << 24i32; + let mut dword3: i32 = saturate_sw_to_sb(source.u16_0[4usize] as i32) + | saturate_sw_to_sb(source.u16_0[5usize] as i32) << 8i32 + | saturate_sw_to_sb(source.u16_0[6usize] as i32) << 16i32 + | saturate_sw_to_sb(source.u16_0[7usize] as i32) << 24i32; + write_xmm128(r, dword0, dword1, dword2, dword3); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F63_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F63(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F63_mem(mut addr: i32, mut r: i32) -> () { + instr_660F63(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F64(mut source: reg64, mut r: i32) -> () { + c_comment!(("pcmpgtb mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut result: reg64 = reg64 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + }; + let mut i: u32 = 0i32 as u32; + while i < 8i32 as u32 { + result.u8_0[i as usize] = + (if destination.i8_0[i as usize] as i32 > source.i8_0[i as usize] as i32 { + 255i32 + } + else { + 0i32 + }) as u8; + i = i.wrapping_add(1) + } + write_mmx_reg64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F64_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F64(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F64_mem(mut addr: i32, mut r: i32) -> () { + instr_0F64(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F64(mut source: reg128, mut r: i32) -> () { + c_comment!(("pcmpgtb xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + }; + let mut i: i32 = 0i32; + while i < 16i32 { + result.i8_0[i as usize] = + (if destination.i8_0[i as usize] as i32 > source.i8_0[i as usize] as i32 { + 255i32 + } + else { + 0i32 + }) as i8; + i += 1 + } + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F64_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F64(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F64_mem(mut addr: i32, mut r: i32) -> () { + instr_660F64(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F65(mut source: reg64, mut r: i32) -> () { + c_comment!(("pcmpgtw mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut word0: i32 = if destination.i16_0[0usize] as i32 > source.i16_0[0usize] as i32 { + 65535i32 + } + else { + 0i32 + }; + let mut word1: i32 = if destination.i16_0[1usize] as i32 > source.i16_0[1usize] as i32 { + 65535i32 + } + else { + 0i32 + }; + let mut word2: i32 = if destination.i16_0[2usize] as i32 > source.i16_0[2usize] as i32 { + 65535i32 + } + else { + 0i32 + }; + let mut word3: i32 = if destination.i16_0[3usize] as i32 > source.i16_0[3usize] as i32 { + 65535i32 + } + else { + 0i32 + }; + let mut low: i32 = word0 | word1 << 16i32; + let mut high: i32 = word2 | word3 << 16i32; + write_mmx64(r, low, high); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F65_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F65(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F65_mem(mut addr: i32, mut r: i32) -> () { + instr_0F65(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F65(mut source: reg128, mut r: i32) -> () { + c_comment!(("pcmpgtw xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + }; + let mut i: i32 = 0i32; + while i < 8i32 { + result.u16_0[i as usize] = + (if destination.i16_0[i as usize] as i32 > source.i16_0[i as usize] as i32 { + 65535i32 + } + else { + 0i32 + }) as u16; + i += 1 + } + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F65_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F65(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F65_mem(mut addr: i32, mut r: i32) -> () { + instr_660F65(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F66(mut source: reg64, mut r: i32) -> () { + c_comment!(("pcmpgtd mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut low: i32 = if destination.i32_0[0usize] > source.i32_0[0usize] { + -1i32 + } + else { + 0i32 + }; + let mut high: i32 = if destination.i32_0[1usize] > source.i32_0[1usize] { + -1i32 + } + else { + 0i32 + }; + write_mmx64(r, low, high); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F66_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F66(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F66_mem(mut addr: i32, mut r: i32) -> () { + instr_0F66(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F66(mut source: reg128, mut r: i32) -> () { + c_comment!(("pcmpgtd xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + write_xmm128( + r, + if destination.i32_0[0usize] > source.i32_0[0usize] { + -1i32 + } + else { + 0i32 + }, + if destination.i32_0[1usize] > source.i32_0[1usize] { + -1i32 + } + else { + 0i32 + }, + if destination.i32_0[2usize] > source.i32_0[2usize] { + -1i32 + } + else { + 0i32 + }, + if destination.i32_0[3usize] > source.i32_0[3usize] { + -1i32 + } + else { + 0i32 + }, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F66_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F66(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F66_mem(mut addr: i32, mut r: i32) -> () { + instr_660F66(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F67(mut source: reg64, mut r: i32) -> () { + c_comment!(("packuswb mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut low: u32 = saturate_sw_to_ub(destination.u16_0[0usize] as u32) + | saturate_sw_to_ub(destination.u16_0[1usize] as u32) << 8i32 + | saturate_sw_to_ub(destination.u16_0[2usize] as u32) << 16i32 + | saturate_sw_to_ub(destination.u16_0[3usize] as u32) << 24i32; + let mut high: u32 = saturate_sw_to_ub(source.u16_0[0usize] as u32) + | saturate_sw_to_ub(source.u16_0[1usize] as u32) << 8i32 + | saturate_sw_to_ub(source.u16_0[2usize] as u32) << 16i32 + | saturate_sw_to_ub(source.u16_0[3usize] as u32) << 24i32; + write_mmx64(r, low as i32, high as i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F67_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F67(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F67_mem(mut addr: i32, mut r: i32) -> () { + instr_0F67(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F67(mut source: reg128, mut r: i32) -> () { + c_comment!(("packuswb xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { i8_0: [0; 16] }; + let mut i: i32 = 0i32; + while i < 8i32 { + result.u8_0[i as usize] = saturate_sw_to_ub(destination.u16_0[i as usize] as u32) as u8; + result.u8_0[(i | 8i32) as usize] = saturate_sw_to_ub(source.u16_0[i as usize] as u32) as u8; + i += 1 + } + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F67_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F67(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F67_mem(mut addr: i32, mut r: i32) -> () { + instr_660F67(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F68(mut source: reg64, mut r: i32) -> () { + c_comment!(("punpckhbw mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut byte0: i32 = destination.u8_0[4usize] as i32; + let mut byte1: i32 = source.u8_0[4usize] as i32; + let mut byte2: i32 = destination.u8_0[5usize] as i32; + let mut byte3: i32 = source.u8_0[5usize] as i32; + let mut byte4: i32 = destination.u8_0[6usize] as i32; + let mut byte5: i32 = source.u8_0[6usize] as i32; + let mut byte6: i32 = destination.u8_0[7usize] as i32; + let mut byte7: i32 = source.u8_0[7usize] as i32; + let mut low: i32 = byte0 | byte1 << 8i32 | byte2 << 16i32 | byte3 << 24i32; + let mut high: i32 = byte4 | byte5 << 8i32 | byte6 << 16i32 | byte7 << 24i32; + write_mmx64(r, low, high); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F68_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F68(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F68_mem(mut addr: i32, mut r: i32) -> () { + instr_0F68(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F68(mut source: reg128, mut r: i32) -> () { + c_comment!(("punpckhbw xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + write_xmm128( + r, + destination.u8_0[8usize] as i32 + | (source.u8_0[8usize] as i32) << 8i32 + | (destination.u8_0[9usize] as i32) << 16i32 + | (source.u8_0[9usize] as i32) << 24i32, + destination.u8_0[10usize] as i32 + | (source.u8_0[10usize] as i32) << 8i32 + | (destination.u8_0[11usize] as i32) << 16i32 + | (source.u8_0[11usize] as i32) << 24i32, + destination.u8_0[12usize] as i32 + | (source.u8_0[12usize] as i32) << 8i32 + | (destination.u8_0[13usize] as i32) << 16i32 + | (source.u8_0[13usize] as i32) << 24i32, + destination.u8_0[14usize] as i32 + | (source.u8_0[14usize] as i32) << 8i32 + | (destination.u8_0[15usize] as i32) << 16i32 + | (source.u8_0[15usize] as i32) << 24i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F68_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F68(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F68_mem(mut addr: i32, mut r: i32) -> () { + instr_660F68(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F69(mut source: reg64, mut r: i32) -> () { + c_comment!(("punpckhwd mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut word0: i32 = destination.u16_0[2usize] as i32; + let mut word1: i32 = source.u16_0[2usize] as i32; + let mut word2: i32 = destination.u16_0[3usize] as i32; + let mut word3: i32 = source.u16_0[3usize] as i32; + let mut low: i32 = word0 | word1 << 16i32; + let mut high: i32 = word2 | word3 << 16i32; + write_mmx64(r, low, high); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F69_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F69(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F69_mem(mut addr: i32, mut r: i32) -> () { + instr_0F69(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F69(mut source: reg128, mut r: i32) -> () { + c_comment!(("punpckhwd xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut dword0: i32 = destination.u16_0[4usize] as i32 | (source.u16_0[4usize] as i32) << 16i32; + let mut dword1: i32 = destination.u16_0[5usize] as i32 | (source.u16_0[5usize] as i32) << 16i32; + let mut dword2: i32 = destination.u16_0[6usize] as i32 | (source.u16_0[6usize] as i32) << 16i32; + let mut dword3: i32 = destination.u16_0[7usize] as i32 | (source.u16_0[7usize] as i32) << 16i32; + write_xmm128(r, dword0, dword1, dword2, dword3); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F69_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F69(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F69_mem(mut addr: i32, mut r: i32) -> () { + instr_660F69(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F6A(mut source: reg64, mut r: i32) -> () { + c_comment!(("punpckhdq mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + write_mmx64( + r, + destination.u32_0[1usize] as i32, + source.u32_0[1usize] as i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F6A_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F6A(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F6A_mem(mut addr: i32, mut r: i32) -> () { + instr_0F6A(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F6A(mut source: reg128, mut r: i32) -> () { + c_comment!(("punpckhdq xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + write_xmm128( + r, + destination.u32_0[2usize] as i32, + source.u32_0[2usize] as i32, + destination.u32_0[3usize] as i32, + source.u32_0[3usize] as i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F6A_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F6A(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F6A_mem(mut addr: i32, mut r: i32) -> () { + instr_660F6A(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F6B(mut source: reg64, mut r: i32) -> () { + c_comment!(("packssdw mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut low: i32 = (saturate_sd_to_sw(destination.u32_0[0usize]) + | saturate_sd_to_sw(destination.u32_0[1usize]) << 16i32) as i32; + let mut high: i32 = (saturate_sd_to_sw(source.u32_0[0usize]) + | saturate_sd_to_sw(source.u32_0[1usize]) << 16i32) as i32; + write_mmx64(r, low, high); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F6B_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F6B(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F6B_mem(mut addr: i32, mut r: i32) -> () { + instr_0F6B(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F6B(mut source: reg128, mut r: i32) -> () { + c_comment!(("packssdw xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut dword0: i32 = (saturate_sd_to_sw(destination.u32_0[0usize]) + | saturate_sd_to_sw(destination.u32_0[1usize]) << 16i32) as i32; + let mut dword1: i32 = (saturate_sd_to_sw(destination.u32_0[2usize]) + | saturate_sd_to_sw(destination.u32_0[3usize]) << 16i32) as i32; + let mut dword2: i32 = (saturate_sd_to_sw(source.u32_0[0usize]) + | saturate_sd_to_sw(source.u32_0[1usize]) << 16i32) as i32; + let mut dword3: i32 = (saturate_sd_to_sw(source.u32_0[2usize]) + | saturate_sd_to_sw(source.u32_0[3usize]) << 16i32) as i32; + write_xmm128(r, dword0, dword1, dword2, dword3); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F6B_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F6B(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F6B_mem(mut addr: i32, mut r: i32) -> () { + instr_660F6B(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F6C_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F6C_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660F6C(mut source: reg128, mut r: i32) -> () { + c_comment!(("punpcklqdq xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + write_xmm128( + r, + destination.u32_0[0usize] as i32, + destination.u32_0[1usize] as i32, + source.u32_0[0usize] as i32, + source.u32_0[1usize] as i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F6C_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F6C(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F6C_mem(mut addr: i32, mut r: i32) -> () { + instr_660F6C(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F6D_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F6D_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660F6D(mut source: reg128, mut r: i32) -> () { + c_comment!(("punpckhqdq xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + write_xmm128( + r, + destination.u32_0[2usize] as i32, + destination.u32_0[3usize] as i32, + source.u32_0[2usize] as i32, + source.u32_0[3usize] as i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F6D_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F6D(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F6D_mem(mut addr: i32, mut r: i32) -> () { + instr_660F6D(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F6E(mut source: i32, mut r: i32) -> () { + c_comment!(("movd mm, r/m32")); + write_mmx64(r, source, 0i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F6E_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F6E(read_reg32(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F6E_mem(mut addr: i32, mut r: i32) -> () { + instr_0F6E(safe_read32s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F6E(mut source: i32, mut r: i32) -> () { + c_comment!(("movd mm, r/m32")); + write_xmm128(r, source, 0i32, 0i32, 0i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F6E_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F6E(read_reg32(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F6E_mem(mut addr: i32, mut r: i32) -> () { + instr_660F6E(safe_read32s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F6F(mut source: reg64, mut r: i32) -> () { + c_comment!(("movq mm, mm/m64")); + write_mmx64(r, source.u32_0[0usize] as i32, source.u32_0[1usize] as i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F6F_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F6F(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F6F_mem(mut addr: i32, mut r: i32) -> () { + instr_0F6F(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F6F(mut source: reg128, mut r: i32) -> () { + c_comment!(("movdqa xmm, xmm/mem128")); + c_comment!(("XXX: Aligned access or #gp")); + c_comment!(("XXX: Aligned read or #gp")); + mov_rm_r128(source, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F6F_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F6F(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F6F_mem(mut addr: i32, mut r: i32) -> () { + instr_660F6F(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F6F(mut source: reg128, mut r: i32) -> () { + c_comment!(("movdqu xmm, xmm/m128")); + mov_rm_r128(source, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F6F_reg(mut r1: i32, mut r2: i32) -> () { + instr_F30F6F(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F6F_mem(mut addr: i32, mut r: i32) -> () { + instr_F30F6F(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F70(mut source: reg64, mut r: i32, mut imm8: i32) -> () { + c_comment!(("pshufw mm1, mm2/m64, imm8")); + let mut word0_shift: i32 = imm8 & 3i32; + let mut word0: u32 = source.u32_0[(word0_shift >> 1i32) as usize] + >> ((word0_shift & 1i32) << 4i32) + & 65535i32 as u32; + let mut word1_shift: i32 = imm8 >> 2i32 & 3i32; + let mut word1: u32 = + source.u32_0[(word1_shift >> 1i32) as usize] >> ((word1_shift & 1i32) << 4i32); + let mut low: i32 = (word0 | word1 << 16i32) as i32; + let mut word2_shift: i32 = imm8 >> 4i32 & 3i32; + let mut word2: u32 = source.u32_0[(word2_shift >> 1i32) as usize] + >> ((word2_shift & 1i32) << 4i32) + & 65535i32 as u32; + let mut word3_shift: u32 = (imm8 >> 6i32) as u32; + let mut word3: u32 = + source.u32_0[(word3_shift >> 1i32) as usize] >> ((word3_shift & 1i32 as u32) << 4i32); + let mut high: i32 = (word2 | word3 << 16i32) as i32; + write_mmx64(r, low, high); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { + instr_0F70(read_mmx64s(r1), r2, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { + instr_0F70(safe_read64s(addr), r, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F70(mut source: reg128, mut r: i32, mut imm8: i32) -> () { + c_comment!(("pshufd xmm, xmm/mem128")); + c_comment!(("XXX: Aligned access or #gp")); + write_xmm128( + r, + source.u32_0[(imm8 & 3i32) as usize] as i32, + source.u32_0[(imm8 >> 2i32 & 3i32) as usize] as i32, + source.u32_0[(imm8 >> 4i32 & 3i32) as usize] as i32, + source.u32_0[(imm8 >> 6i32 & 3i32) as usize] as i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { + instr_660F70(read_xmm128s(r1), r2, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { + instr_660F70(safe_read128s(addr), r, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F70(mut source: reg128, mut r: i32, mut imm8: i32) -> () { + c_comment!(("pshuflw xmm, xmm/m128, imm8")); + c_comment!(("XXX: Aligned access or #gp")); + write_xmm128( + r, + source.u16_0[(imm8 & 3i32) as usize] as i32 + | (source.u16_0[(imm8 >> 2i32 & 3i32) as usize] as i32) << 16i32, + source.u16_0[(imm8 >> 4i32 & 3i32) as usize] as i32 + | (source.u16_0[(imm8 >> 6i32 & 3i32) as usize] as i32) << 16i32, + source.u32_0[2usize] as i32, + source.u32_0[3usize] as i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { + instr_F20F70(read_xmm128s(r1), r2, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { + instr_F20F70(safe_read128s(addr), r, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F70(mut source: reg128, mut r: i32, mut imm8: i32) -> () { + c_comment!(("pshufhw xmm, xmm/m128, imm8")); + c_comment!(("XXX: Aligned access or #gp")); + write_xmm128( + r, + source.u32_0[0usize] as i32, + source.u32_0[1usize] as i32, + source.u16_0[(imm8 & 3i32 | 4i32) as usize] as i32 + | (source.u16_0[(imm8 >> 2i32 & 3i32 | 4i32) as usize] as i32) << 16i32, + source.u16_0[(imm8 >> 4i32 & 3i32 | 4i32) as usize] as i32 + | (source.u16_0[(imm8 >> 6i32 & 3i32 | 4i32) as usize] as i32) << 16i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { + instr_F30F70(read_xmm128s(r1), r2, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { + instr_F30F70(safe_read128s(addr), r, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F71_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F71_4_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F71_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F71_2_reg(mut r: i32, mut imm8: i32) -> () { + c_comment!(("psrlw mm, imm8")); + psrlw_r64(r, imm8 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F71_4_reg(mut r: i32, mut imm8: i32) -> () { + c_comment!(("psraw mm, imm8")); + psraw_r64(r, imm8 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F71_6_reg(mut r: i32, mut imm8: i32) -> () { + c_comment!(("psllw mm, imm8")); + psllw_r64(r, imm8 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F71_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660F71_4_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660F71_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660F71_2_reg(mut r: i32, mut imm8: i32) -> () { + c_comment!(("psrlw xmm, imm8")); + psrlw_r128(r, imm8 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F71_4_reg(mut r: i32, mut imm8: i32) -> () { + c_comment!(("psraw xmm, imm8")); + psraw_r128(r, imm8 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F71_6_reg(mut r: i32, mut imm8: i32) -> () { + c_comment!(("psllw xmm, imm8")); + psllw_r128(r, imm8 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F72_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F72_4_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F72_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F72_2_reg(mut r: i32, mut imm8: i32) -> () { + c_comment!(("psrld mm, imm8")); + psrld_r64(r, imm8 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F72_4_reg(mut r: i32, mut imm8: i32) -> () { + c_comment!(("psrad mm, imm8")); + psrad_r64(r, imm8 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F72_6_reg(mut r: i32, mut imm8: i32) -> () { + c_comment!(("pslld mm, imm8")); + pslld_r64(r, imm8 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F72_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660F72_4_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660F72_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660F72_2_reg(mut r: i32, mut imm8: i32) -> () { + c_comment!(("psrld xmm, imm8")); + psrld_r128(r, imm8 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F72_4_reg(mut r: i32, mut imm8: i32) -> () { + c_comment!(("psrad xmm, imm8")); + psrad_r128(r, imm8 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F72_6_reg(mut r: i32, mut imm8: i32) -> () { + c_comment!(("pslld xmm, imm8")); + pslld_r128(r, imm8 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F73_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F73_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F73_2_reg(mut r: i32, mut imm8: i32) -> () { + c_comment!(("psrlq mm, imm8")); + psrlq_r64(r, imm8 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F73_6_reg(mut r: i32, mut imm8: i32) -> () { + c_comment!(("psllq mm, imm8")); + psllq_r64(r, imm8 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F73_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660F73_3_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660F73_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660F73_7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660F73_2_reg(mut r: i32, mut imm8: i32) -> () { + c_comment!(("psrlq xmm, imm8")); + psrlq_r128(r, imm8 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F73_3_reg(mut r: i32, mut imm8: i32) -> () { + c_comment!(("psrldq xmm, imm8")); + let mut destination: reg128 = read_xmm128s(r); + if imm8 == 0i32 { + return; + } + else { + let mut result: reg128 = reg128 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + }; + let mut shift: u32 = (if imm8 > 15i32 { 128i32 } else { imm8 << 3i32 }) as u32; + if shift <= 63i32 as u32 { + result.u64_0[0usize] = destination.u64_0[0usize] >> shift + | destination.u64_0[1usize] << (64i32 as u32).wrapping_sub(shift); + result.u64_0[1usize] = destination.u64_0[1usize] >> shift + } + else if shift <= 127i32 as u32 { + result.u64_0[0usize] = destination.u64_0[1usize] >> shift.wrapping_sub(64i32 as u32); + result.u64_0[1usize] = 0i32 as u64 + } + write_xmm_reg128(r, result); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F73_6_reg(mut r: i32, mut imm8: i32) -> () { + c_comment!(("psllq xmm, imm8")); + psllq_r128(r, imm8 as u32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F73_7_reg(mut r: i32, mut imm8: i32) -> () { + c_comment!(("pslldq xmm, imm8")); + let mut destination: reg128 = read_xmm128s(r); + if imm8 == 0i32 { + return; + } + else { + let mut result: reg128 = reg128 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + }; + let mut shift: u32 = (if imm8 > 15i32 { 128i32 } else { imm8 << 3i32 }) as u32; + if shift <= 63i32 as u32 { + result.u64_0[0usize] = destination.u64_0[0usize] << shift; + result.u64_0[1usize] = destination.u64_0[1usize] << shift + | destination.u64_0[0usize] >> (64i32 as u32).wrapping_sub(shift) + } + else if shift <= 127i32 as u32 { + result.u64_0[0usize] = 0i32 as u64; + result.u64_0[1usize] = destination.u64_0[0usize] << shift.wrapping_sub(64i32 as u32) + } + write_xmm_reg128(r, result); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F74(mut source: reg64, mut r: i32) -> () { + c_comment!(("pcmpeqb mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut result: reg64 = reg64 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + }; + let mut i: u32 = 0i32 as u32; + while i < 8i32 as u32 { + result.u8_0[i as usize] = + (if destination.i8_0[i as usize] as i32 == source.i8_0[i as usize] as i32 { + 255i32 + } + else { + 0i32 + }) as u8; + i = i.wrapping_add(1) + } + write_mmx_reg64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F74_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F74(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F74_mem(mut addr: i32, mut r: i32) -> () { + instr_0F74(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F74(mut source: reg128, mut r: i32) -> () { + c_comment!(("pcmpeqb xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { i8_0: [0; 16] }; + let mut i: i32 = 0i32; + while i < 16i32 { + result.u8_0[i as usize] = + (if source.u8_0[i as usize] as i32 == destination.u8_0[i as usize] as i32 { + 255i32 + } + else { + 0i32 + }) as u8; + i += 1 + } + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F74_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F74(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F74_mem(mut addr: i32, mut r: i32) -> () { + instr_660F74(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F75(mut source: reg64, mut r: i32) -> () { + c_comment!(("pcmpeqw mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut word0: i32 = if destination.u16_0[0usize] as i32 == source.u16_0[0usize] as i32 { + 65535i32 + } + else { + 0i32 + }; + let mut word1: i32 = if destination.u16_0[1usize] as i32 == source.u16_0[1usize] as i32 { + 65535i32 + } + else { + 0i32 + }; + let mut word2: i32 = if destination.u16_0[2usize] as i32 == source.u16_0[2usize] as i32 { + 65535i32 + } + else { + 0i32 + }; + let mut word3: i32 = if destination.u16_0[3usize] as i32 == source.u16_0[3usize] as i32 { + 65535i32 + } + else { + 0i32 + }; + let mut low: i32 = word0 | word1 << 16i32; + let mut high: i32 = word2 | word3 << 16i32; + write_mmx64(r, low, high); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F75_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F75(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F75_mem(mut addr: i32, mut r: i32) -> () { + instr_0F75(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F75(mut source: reg128, mut r: i32) -> () { + c_comment!(("pcmpeqw xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { i8_0: [0; 16] }; + let mut i: i32 = 0i32; + while i < 8i32 { + result.u16_0[i as usize] = + (if source.u16_0[i as usize] as i32 == destination.u16_0[i as usize] as i32 { + 65535i32 + } + else { + 0i32 + }) as u16; + i += 1 + } + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F75_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F75(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F75_mem(mut addr: i32, mut r: i32) -> () { + instr_660F75(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F76(mut source: reg64, mut r: i32) -> () { + c_comment!(("pcmpeqd mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut low: i32 = if destination.u32_0[0usize] == source.u32_0[0usize] { + -1i32 + } + else { + 0i32 + }; + let mut high: i32 = if destination.u32_0[1usize] == source.u32_0[1usize] { + -1i32 + } + else { + 0i32 + }; + write_mmx64(r, low, high); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F76_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F76(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F76_mem(mut addr: i32, mut r: i32) -> () { + instr_0F76(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F76(mut source: reg128, mut r: i32) -> () { + c_comment!(("pcmpeqd xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + write_xmm128( + r, + if source.u32_0[0usize] == destination.u32_0[0usize] { + -1i32 + } + else { + 0i32 + }, + if source.u32_0[1usize] == destination.u32_0[1usize] { + -1i32 + } + else { + 0i32 + }, + if source.u32_0[2usize] == destination.u32_0[2usize] { + -1i32 + } + else { + 0i32 + }, + if source.u32_0[3usize] == destination.u32_0[3usize] { + -1i32 + } + else { + 0i32 + }, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F76_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F76(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F76_mem(mut addr: i32, mut r: i32) -> () { + instr_660F76(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F77() -> () { + c_comment!(("emms")); + fpu_set_tag_word(65535i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F78() -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F79() -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F7A() -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F7B() -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F7C() -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F7D() -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F7E(mut r: i32) -> i32 { + c_comment!(("movd r/m32, mm")); + let mut data: reg64 = read_mmx64s(r); + return data.u32_0[0usize] as i32; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F7E_reg(mut r1: i32, mut r2: i32) -> () { + write_reg32(r1, instr_0F7E(r2)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F7E_mem(mut addr: i32, mut r: i32) -> () { + safe_write32(addr, instr_0F7E(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F7E(mut r: i32) -> i32 { + c_comment!(("movd r/m32, xmm")); + let mut data: reg64 = read_xmm64s(r); + return data.u32_0[0usize] as i32; +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F7E_reg(mut r1: i32, mut r2: i32) -> () { + write_reg32(r1, instr_660F7E(r2)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F7E_mem(mut addr: i32, mut r: i32) -> () { + safe_write32(addr, instr_660F7E(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F7E_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movq xmm, xmm/mem64")); + let mut data: reg64 = safe_read64s(addr); + write_xmm128( + r, + data.u32_0[0usize] as i32, + data.u32_0[1usize] as i32, + 0i32, + 0i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F7E_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("movq xmm, xmm/mem64")); + let mut data: reg64 = read_xmm64s(r1); + write_xmm128( + r2, + data.u32_0[0usize] as i32, + data.u32_0[1usize] as i32, + 0i32, + 0i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F7F_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movq mm/m64, mm")); + mov_r_m64(addr, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F7F_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("movq mm/m64, mm")); + let mut data: reg64 = read_mmx64s(r2); + write_mmx64(r1, data.u32_0[0usize] as i32, data.u32_0[1usize] as i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F7F_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movdqa xmm/m128, xmm")); + c_comment!(("XXX: Aligned write or #gp")); + mov_r_m128(addr, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F7F_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("movdqa xmm/m128, xmm")); + c_comment!(("XXX: Aligned access or #gp")); + mov_r_r128(r1, r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F7F_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movdqu xmm/m128, xmm")); + mov_r_m128(addr, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F7F_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("movdqu xmm/m128, xmm")); + mov_r_r128(r1, r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0F80(mut imm: i32) -> () { jmpcc16(test_o(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0F80(mut imm: i32) -> () { jmpcc32(test_o(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0F81(mut imm: i32) -> () { jmpcc16(!test_o(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0F81(mut imm: i32) -> () { jmpcc32(!test_o(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0F82(mut imm: i32) -> () { jmpcc16(test_b(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0F82(mut imm: i32) -> () { jmpcc32(test_b(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0F83(mut imm: i32) -> () { jmpcc16(!test_b(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0F83(mut imm: i32) -> () { jmpcc32(!test_b(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0F84(mut imm: i32) -> () { jmpcc16(test_z(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0F84(mut imm: i32) -> () { jmpcc32(test_z(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0F85(mut imm: i32) -> () { jmpcc16(!test_z(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0F85(mut imm: i32) -> () { jmpcc32(!test_z(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0F86(mut imm: i32) -> () { jmpcc16(test_be(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0F86(mut imm: i32) -> () { jmpcc32(test_be(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0F87(mut imm: i32) -> () { jmpcc16(!test_be(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0F87(mut imm: i32) -> () { jmpcc32(!test_be(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0F88(mut imm: i32) -> () { jmpcc16(test_s(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0F88(mut imm: i32) -> () { jmpcc32(test_s(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0F89(mut imm: i32) -> () { jmpcc16(!test_s(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0F89(mut imm: i32) -> () { jmpcc32(!test_s(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0F8A(mut imm: i32) -> () { jmpcc16(test_p(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0F8A(mut imm: i32) -> () { jmpcc32(test_p(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0F8B(mut imm: i32) -> () { jmpcc16(!test_p(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0F8B(mut imm: i32) -> () { jmpcc32(!test_p(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0F8C(mut imm: i32) -> () { jmpcc16(test_l(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0F8C(mut imm: i32) -> () { jmpcc32(test_l(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0F8D(mut imm: i32) -> () { jmpcc16(!test_l(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0F8D(mut imm: i32) -> () { jmpcc32(!test_l(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0F8E(mut imm: i32) -> () { jmpcc16(test_le(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0F8E(mut imm: i32) -> () { jmpcc32(test_le(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0F8F(mut imm: i32) -> () { jmpcc16(!test_le(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0F8F(mut imm: i32) -> () { jmpcc32(!test_le(), imm); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F90_reg(mut r: i32, mut unused: i32) -> () { + setcc_reg(test_o(), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F91_reg(mut r: i32, mut unused: i32) -> () { + setcc_reg(!test_o(), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F92_reg(mut r: i32, mut unused: i32) -> () { + setcc_reg(test_b(), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F93_reg(mut r: i32, mut unused: i32) -> () { + setcc_reg(!test_b(), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F94_reg(mut r: i32, mut unused: i32) -> () { + setcc_reg(test_z(), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F95_reg(mut r: i32, mut unused: i32) -> () { + setcc_reg(!test_z(), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F96_reg(mut r: i32, mut unused: i32) -> () { + setcc_reg(test_be(), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F97_reg(mut r: i32, mut unused: i32) -> () { + setcc_reg(!test_be(), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F98_reg(mut r: i32, mut unused: i32) -> () { + setcc_reg(test_s(), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F99_reg(mut r: i32, mut unused: i32) -> () { + setcc_reg(!test_s(), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F9A_reg(mut r: i32, mut unused: i32) -> () { + setcc_reg(test_p(), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F9B_reg(mut r: i32, mut unused: i32) -> () { + setcc_reg(!test_p(), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F9C_reg(mut r: i32, mut unused: i32) -> () { + setcc_reg(test_l(), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F9D_reg(mut r: i32, mut unused: i32) -> () { + setcc_reg(!test_l(), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F9E_reg(mut r: i32, mut unused: i32) -> () { + setcc_reg(test_le(), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F9F_reg(mut r: i32, mut unused: i32) -> () { + setcc_reg(!test_le(), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F90_mem(mut addr: i32, mut unused: i32) -> () { + setcc_mem(test_o(), addr); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F91_mem(mut addr: i32, mut unused: i32) -> () { + setcc_mem(!test_o(), addr); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F92_mem(mut addr: i32, mut unused: i32) -> () { + setcc_mem(test_b(), addr); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F93_mem(mut addr: i32, mut unused: i32) -> () { + setcc_mem(!test_b(), addr); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F94_mem(mut addr: i32, mut unused: i32) -> () { + setcc_mem(test_z(), addr); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F95_mem(mut addr: i32, mut unused: i32) -> () { + setcc_mem(!test_z(), addr); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F96_mem(mut addr: i32, mut unused: i32) -> () { + setcc_mem(test_be(), addr); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F97_mem(mut addr: i32, mut unused: i32) -> () { + setcc_mem(!test_be(), addr); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F98_mem(mut addr: i32, mut unused: i32) -> () { + setcc_mem(test_s(), addr); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F99_mem(mut addr: i32, mut unused: i32) -> () { + setcc_mem(!test_s(), addr); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F9A_mem(mut addr: i32, mut unused: i32) -> () { + setcc_mem(test_p(), addr); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F9B_mem(mut addr: i32, mut unused: i32) -> () { + setcc_mem(!test_p(), addr); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F9C_mem(mut addr: i32, mut unused: i32) -> () { + setcc_mem(test_l(), addr); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F9D_mem(mut addr: i32, mut unused: i32) -> () { + setcc_mem(!test_l(), addr); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F9E_mem(mut addr: i32, mut unused: i32) -> () { + setcc_mem(test_le(), addr); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F9F_mem(mut addr: i32, mut unused: i32) -> () { + setcc_mem(!test_le(), addr); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FA0() -> () { push16(*sreg.offset(FS as isize) as i32); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0FA0() -> () { push32(*sreg.offset(FS as isize) as i32); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0FA1() -> () { + if !switch_seg(FS, safe_read16(get_stack_pointer(0i32))) { + return; + } + else { + adjust_stack_reg(2i32); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FA1() -> () { + if !switch_seg(FS, safe_read32s(get_stack_pointer(0i32)) & 65535i32) { + return; + } + else { + adjust_stack_reg(4i32); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FA2() -> () { cpuid(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0FA3_reg(mut r1: i32, mut r2: i32) -> () { + bt_reg(read_reg16(r1), read_reg16(r2) & 15i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FA3_mem(mut addr: i32, mut r: i32) -> () { + bt_mem(addr, read_reg16(r) << 16i32 >> 16i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FA3_reg(mut r1: i32, mut r2: i32) -> () { + bt_reg(read_reg32(r1), read_reg32(r2) & 31i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FA3_mem(mut addr: i32, mut r: i32) -> () { + bt_mem(addr, read_reg32(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FA4_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, shld16(___, read_reg16(r), imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FA4_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, shld16(____0, read_reg16(r), imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FA4_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, shld32(___, read_reg32(r), imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FA4_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, shld32(____0, read_reg32(r), imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FA5_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE16!( + ___, + addr, + shld16(___, read_reg16(r), *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FA5_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16( + r1, + shld16( + ____0, + read_reg16(r), + *reg8.offset(CL as isize) as i32 & 31i32, + ), + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FA5_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE32!( + ___, + addr, + shld32(___, read_reg32(r), *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FA5_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32( + r1, + shld32( + ____0, + read_reg32(r), + *reg8.offset(CL as isize) as i32 & 31i32, + ), + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FA6() -> () { + c_comment!(("obsolete cmpxchg (os/2)")); + trigger_ud(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FA7() -> () { undefined_instruction(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0FA8() -> () { push16(*sreg.offset(GS as isize) as i32); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0FA8() -> () { push32(*sreg.offset(GS as isize) as i32); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0FA9() -> () { + if !switch_seg(GS, safe_read16(get_stack_pointer(0i32))) { + return; + } + else { + adjust_stack_reg(2i32); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FA9() -> () { + if !switch_seg(GS, safe_read32s(get_stack_pointer(0i32)) & 65535i32) { + return; + } + else { + adjust_stack_reg(4i32); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FAA() -> () { + c_comment!(("rsm")); + undefined_instruction(); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FAB_reg(mut r1: i32, mut r2: i32) -> () { + write_reg16(r1, bts_reg(read_reg16(r1), read_reg16(r2) & 15i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FAB_mem(mut addr: i32, mut r: i32) -> () { + bts_mem(addr, read_reg16(r) << 16i32 >> 16i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FAB_reg(mut r1: i32, mut r2: i32) -> () { + write_reg32(r1, bts_reg(read_reg32(r1), read_reg32(r2) & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FAB_mem(mut addr: i32, mut r: i32) -> () { + bts_mem(addr, read_reg32(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FAC_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { + SAFE_READ_WRITE16!(___, addr, shrd16(___, read_reg16(r), imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FAC_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, shrd16(____0, read_reg16(r), imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FAC_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { + SAFE_READ_WRITE32!(___, addr, shrd32(___, read_reg32(r), imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FAC_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, shrd32(____0, read_reg32(r), imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FAD_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE16!( + ___, + addr, + shrd16(___, read_reg16(r), *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FAD_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16( + r1, + shrd16( + ____0, + read_reg16(r), + *reg8.offset(CL as isize) as i32 & 31i32, + ), + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FAD_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE32!( + ___, + addr, + shrd32(___, read_reg32(r), *reg8.offset(CL as isize) as i32 & 31i32) + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FAD_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32( + r1, + shrd32( + ____0, + read_reg32(r), + *reg8.offset(CL as isize) as i32 & 31i32, + ), + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FAE_0_reg(mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FAE_0_mem(mut addr: i32) -> () { fxsave(addr as u32); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FAE_1_reg(mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FAE_1_mem(mut addr: i32) -> () { fxrstor(addr as u32); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FAE_2_reg(mut r: i32) -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FAE_2_mem(mut addr: i32) -> () { + c_comment!(("ldmxcsr")); + let mut new_mxcsr: i32 = safe_read32s(addr); + if 0 != new_mxcsr & !MXCSR_MASK { + dbg_log_c!(("Invalid mxcsr bits: %x"), new_mxcsr & !MXCSR_MASK); + dbg_assert!(0 != 0i32); + trigger_gp_non_raising(0i32); + return; + } + else { + *mxcsr = new_mxcsr; + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FAE_3_reg(mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FAE_3_mem(mut addr: i32) -> () { + c_comment!(("stmxcsr")); + safe_write32(addr, *mxcsr); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FAE_4_reg(mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FAE_4_mem(mut addr: i32) -> () { + c_comment!(("xsave")); + undefined_instruction(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FAE_5_reg(mut r: i32) -> () { + c_comment!(("lfence")); + dbg_assert!(r == 0i32, ("Unexpected lfence encoding")); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FAE_5_mem(mut addr: i32) -> () { + c_comment!(("xrstor")); + undefined_instruction(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FAE_6_reg(mut r: i32) -> () { + c_comment!(("mfence")); + dbg_assert!(r == 0i32, ("Unexpected mfence encoding")); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FAE_6_mem(mut addr: i32) -> () { + c_comment!(("xsaveopt")); + undefined_instruction(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FAE_7_reg(mut r: i32) -> () { + c_comment!(("sfence")); + dbg_assert!(r == 0i32, ("Unexpected sfence encoding")); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FAE_7_mem(mut addr: i32) -> () { + c_comment!(("clflush")); + undefined_instruction(); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FAF_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + write_reg16( + r, + imul_reg16(read_reg16(r) << 16i32 >> 16i32, ____0 << 16i32 >> 16i32), + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FAF_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16( + r, + imul_reg16(read_reg16(r) << 16i32 >> 16i32, ____0 << 16i32 >> 16i32), + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FAF_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + write_reg32(r, imul_reg32(read_reg32(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FAF_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r, imul_reg32(read_reg32(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FB0_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("cmpxchg8")); + let mut data: i32 = read_reg8(r1); + cmp8(*reg8.offset(AL as isize) as i32, data); + if getzf() { + write_reg8(r1, read_reg8(r2)); + } + else { + *reg8.offset(AL as isize) = data as u8 + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FB0_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("cmpxchg8")); + writable_or_pagefault(addr, 1i32); + let mut data: i32 = safe_read8(addr); + cmp8(*reg8.offset(AL as isize) as i32, data); + if getzf() { + safe_write8(addr, read_reg8(r)); + } + else { + safe_write8(addr, data); + *reg8.offset(AL as isize) = data as u8 + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FB1_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("cmpxchg16")); + let mut data: i32 = read_reg16(r1); + cmp16(*reg16.offset(AX as isize) as i32, data); + if getzf() { + write_reg16(r1, read_reg16(r2)); + } + else { + *reg16.offset(AX as isize) = data as u16 + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FB1_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("cmpxchg16")); + writable_or_pagefault(addr, 2i32); + let mut data: i32 = safe_read16(addr); + cmp16(*reg16.offset(AX as isize) as i32, data); + if getzf() { + safe_write16(addr, read_reg16(r)); + } + else { + safe_write16(addr, data); + *reg16.offset(AX as isize) = data as u16 + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FB1_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("cmpxchg32")); + let mut data: i32 = read_reg32(r1); + cmp32(*reg32s.offset(EAX as isize), data); + if getzf() { + write_reg32(r1, read_reg32(r2)); + } + else { + *reg32s.offset(EAX as isize) = data + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FB1_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("cmpxchg32")); + writable_or_pagefault(addr, 4i32); + let mut data: i32 = safe_read32s(addr); + cmp32(*reg32s.offset(EAX as isize), data); + if getzf() { + safe_write32(addr, read_reg32(r)); + } + else { + safe_write32(addr, data); + *reg32s.offset(EAX as isize) = data + }; +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FB2_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0FB2_mem(mut addr: i32, mut r: i32) -> () { + lss16(addr, get_reg16_index(r), SS); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FB2_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0FB2_mem(mut addr: i32, mut r: i32) -> () { lss32(addr, r, SS); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0FB3_reg(mut r1: i32, mut r2: i32) -> () { + write_reg16(r1, btr_reg(read_reg16(r1), read_reg16(r2) & 15i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FB3_mem(mut addr: i32, mut r: i32) -> () { + btr_mem(addr, read_reg16(r) << 16i32 >> 16i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FB3_reg(mut r1: i32, mut r2: i32) -> () { + write_reg32(r1, btr_reg(read_reg32(r1), read_reg32(r2) & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FB3_mem(mut addr: i32, mut r: i32) -> () { + btr_mem(addr, read_reg32(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FB4_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0FB4_mem(mut addr: i32, mut r: i32) -> () { + lss16(addr, get_reg16_index(r), FS); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FB4_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0FB4_mem(mut addr: i32, mut r: i32) -> () { lss32(addr, r, FS); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0FB5_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0FB5_mem(mut addr: i32, mut r: i32) -> () { + lss16(addr, get_reg16_index(r), GS); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FB5_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0FB5_mem(mut addr: i32, mut r: i32) -> () { lss32(addr, r, GS); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0FB6_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read8(addr); + write_reg16(r, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FB6_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg16(r, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FB6_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read8(addr); + write_reg32(r, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FB6_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg32(r, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FB7_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + write_reg16(r, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FB7_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FB7_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + write_reg32(r, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FB7_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg32(r, ____0); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FB8_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_0FB8_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr16_F30FB8_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + write_reg16(r, popcnt(____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_F30FB8_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r, popcnt(____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FB8_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_0FB8_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr32_F30FB8_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + write_reg32(r, popcnt(____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_F30FB8_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r, popcnt(____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FB9() -> () { + c_comment!(("UD2")); + trigger_ud(); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FBA_4_reg(mut r: i32, mut imm: i32) -> () { + bt_reg(read_reg16(r), imm & 15i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FBA_4_mem(mut addr: i32, mut imm: i32) -> () { + bt_mem(addr, imm & 15i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FBA_5_reg(mut r: i32, mut imm: i32) -> () { + write_reg16(r, bts_reg(read_reg16(r), imm & 15i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FBA_5_mem(mut addr: i32, mut imm: i32) -> () { + bts_mem(addr, imm & 15i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FBA_6_reg(mut r: i32, mut imm: i32) -> () { + write_reg16(r, btr_reg(read_reg16(r), imm & 15i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FBA_6_mem(mut addr: i32, mut imm: i32) -> () { + btr_mem(addr, imm & 15i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FBA_7_reg(mut r: i32, mut imm: i32) -> () { + write_reg16(r, btc_reg(read_reg16(r), imm & 15i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FBA_7_mem(mut addr: i32, mut imm: i32) -> () { + btc_mem(addr, imm & 15i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FBA_4_reg(mut r: i32, mut imm: i32) -> () { + bt_reg(read_reg32(r), imm & 31i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FBA_4_mem(mut addr: i32, mut imm: i32) -> () { + bt_mem(addr, imm & 31i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FBA_5_reg(mut r: i32, mut imm: i32) -> () { + write_reg32(r, bts_reg(read_reg32(r), imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FBA_5_mem(mut addr: i32, mut imm: i32) -> () { + bts_mem(addr, imm & 31i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FBA_6_reg(mut r: i32, mut imm: i32) -> () { + write_reg32(r, btr_reg(read_reg32(r), imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FBA_6_mem(mut addr: i32, mut imm: i32) -> () { + btr_mem(addr, imm & 31i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FBA_7_reg(mut r: i32, mut imm: i32) -> () { + write_reg32(r, btc_reg(read_reg32(r), imm & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FBA_7_mem(mut addr: i32, mut imm: i32) -> () { + btc_mem(addr, imm & 31i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FBB_reg(mut r1: i32, mut r2: i32) -> () { + write_reg16(r1, btc_reg(read_reg16(r1), read_reg16(r2) & 15i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FBB_mem(mut addr: i32, mut r: i32) -> () { + btc_mem(addr, read_reg16(r) << 16i32 >> 16i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FBB_reg(mut r1: i32, mut r2: i32) -> () { + write_reg32(r1, btc_reg(read_reg32(r1), read_reg32(r2) & 31i32)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FBB_mem(mut addr: i32, mut r: i32) -> () { + btc_mem(addr, read_reg32(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FBC_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + write_reg16(r, bsf16(read_reg16(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FBC_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r, bsf16(read_reg16(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FBC_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + write_reg32(r, bsf32(read_reg32(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FBC_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r, bsf32(read_reg32(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FBD_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + write_reg16(r, bsr16(read_reg16(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FBD_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r, bsr16(read_reg16(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FBD_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read32s(addr); + write_reg32(r, bsr32(read_reg32(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FBD_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r, bsr32(read_reg32(r), ____0)); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FBE_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read8(addr); + write_reg16(r, ____0 << 24i32 >> 24i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FBE_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg16(r, ____0 << 24i32 >> 24i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FBE_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read8(addr); + write_reg32(r, ____0 << 24i32 >> 24i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FBE_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg32(r, ____0 << 24i32 >> 24i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FBF_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + write_reg16(r, ____0 << 16i32 >> 16i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FBF_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r, ____0 << 16i32 >> 16i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FBF_mem(mut addr: i32, mut r: i32) -> () { + let mut ____0: i32 = safe_read16(addr); + write_reg32(r, ____0 << 16i32 >> 16i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FBF_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg32(r, ____0 << 16i32 >> 16i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FC0_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE8!(___, addr, xadd8(___, get_reg8_index(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FC0_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg8(r1); + write_reg8(r1, xadd8(____0, get_reg8_index(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FC1_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE16!(___, addr, xadd16(___, get_reg16_index(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr16_0FC1_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg16(r1); + write_reg16(r1, xadd16(____0, get_reg16_index(r))); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FC1_mem(mut addr: i32, mut r: i32) -> () { + SAFE_READ_WRITE32!(___, addr, xadd32(___, r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr32_0FC1_reg(mut r1: i32, mut r: i32) -> () { + let mut ____0: i32 = read_reg32(r1); + write_reg32(r1, xadd32(____0, r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FC3_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FC3_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movnti")); + safe_write32(addr, read_reg32(r)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FC4(mut source: i32, mut r: i32, mut imm8: i32) -> () { + c_comment!(("pinsrw mm, r32/m16, imm8")); + let mut destination: reg64 = read_mmx64s(r); + let mut index: u32 = (imm8 & 3i32) as u32; + destination.u16_0[index as usize] = (source & 65535i32) as u16; + write_mmx_reg64(r, destination); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FC4_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { + instr_0FC4(read_reg32(r1), r2, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FC4_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { + instr_0FC4(safe_read16(addr), r, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FC4(mut source: i32, mut r: i32, mut imm8: i32) -> () { + c_comment!(("pinsrw xmm, r32/m16, imm8")); + let mut destination: reg128 = read_xmm128s(r); + let mut index: u32 = (imm8 & 7i32) as u32; + destination.u16_0[index as usize] = (source & 65535i32) as u16; + write_xmm_reg128(r, destination); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FC4_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { + instr_660FC4(read_reg32(r1), r2, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FC4_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { + instr_660FC4(safe_read16(addr), r, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FC5_mem(mut addr: i32, mut r: i32, mut imm8: i32) -> () { + trigger_ud(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i32) -> () { + c_comment!(("pextrw r32, mm, imm8")); + let mut data: reg64 = read_mmx64s(r1); + let mut index: u32 = (imm8 & 3i32) as u32; + let mut result: u32 = data.u16_0[index as usize] as u32; + write_reg32(r2, result as i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FC5_mem(mut addr: i32, mut r: i32, mut imm8: i32) -> () { + trigger_ud(); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i32) -> () { + c_comment!(("pextrw r32, xmm, imm8")); + let mut data: reg128 = read_xmm128s(r1); + let mut index: u32 = (imm8 & 7i32) as u32; + let mut result: u32 = data.u16_0[index as usize] as u32; + write_reg32(r2, result as i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FC6() -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FC7_1_reg(mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FC7_1_mem(mut addr: i32) -> () { + c_comment!(("cmpxchg8b")); + writable_or_pagefault(addr, 8i32); + let mut m64_low: i32 = safe_read32s(addr); + let mut m64_high: i32 = safe_read32s(addr + 4i32); + if *reg32s.offset(EAX as isize) == m64_low && *reg32s.offset(EDX as isize) == m64_high { + let ref mut fresh2 = *flags.offset(0isize); + *fresh2 |= FLAG_ZERO; + safe_write32(addr, *reg32s.offset(EBX as isize)); + safe_write32(addr + 4i32, *reg32s.offset(ECX as isize)); + } + else { + let ref mut fresh3 = *flags.offset(0isize); + *fresh3 &= !FLAG_ZERO; + *reg32s.offset(EAX as isize) = m64_low; + *reg32s.offset(EDX as isize) = m64_high; + safe_write32(addr, m64_low); + safe_write32(addr + 4i32, m64_high); + } + let ref mut fresh4 = *flags_changed.offset(0isize); + *fresh4 &= !FLAG_ZERO; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FC7_6_reg(mut r: i32) -> () { + c_comment!(("rdrand")); + let mut has_rand: i32 = has_rand_int() as i32; + let mut rand: i32 = 0i32; + if 0 != has_rand { + rand = get_rand_int() + } + write_reg_osize(r, rand); + let ref mut fresh5 = *flags.offset(0isize); + *fresh5 &= !FLAGS_ALL; + let ref mut fresh6 = *flags.offset(0isize); + *fresh6 |= has_rand; + *flags_changed.offset(0isize) = 0i32; +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FC7_6_mem(mut addr: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FC8() -> () { bswap(EAX); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FC9() -> () { bswap(ECX); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FCA() -> () { bswap(EDX); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FCB() -> () { bswap(EBX); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FCC() -> () { bswap(ESP); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FCD() -> () { bswap(EBP); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FCE() -> () { bswap(ESI); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FCF() -> () { bswap(EDI); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FD0() -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FD1(mut source: reg64, mut r: i32) -> () { + c_comment!(("psrlw mm, mm/m64")); + psrlw_r64(r, source.u32_0[0usize]); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FD1_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FD1(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FD1_mem(mut addr: i32, mut r: i32) -> () { + instr_0FD1(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FD1(mut source: reg128, mut r: i32) -> () { + c_comment!(("psrlw xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + psrlw_r128(r, source.u32_0[0usize]); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FD1_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FD1(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FD1_mem(mut addr: i32, mut r: i32) -> () { + instr_660FD1(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FD2(mut source: reg64, mut r: i32) -> () { + c_comment!(("psrld mm, mm/m64")); + psrld_r64(r, source.u32_0[0usize]); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FD2_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FD2(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FD2_mem(mut addr: i32, mut r: i32) -> () { + instr_0FD2(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FD2(mut source: reg128, mut r: i32) -> () { + c_comment!(("psrld xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + psrld_r128(r, source.u32_0[0usize]); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FD2_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FD2(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FD2_mem(mut addr: i32, mut r: i32) -> () { + instr_660FD2(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FD3(mut source: reg64, mut r: i32) -> () { + c_comment!(("psrlq mm, mm/m64")); + psrlq_r64(r, source.u32_0[0usize]); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FD3_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FD3(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FD3_mem(mut addr: i32, mut r: i32) -> () { + instr_0FD3(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FD3(mut source: reg128, mut r: i32) -> () { + c_comment!(("psrlq xmm, mm/m64")); + psrlq_r128(r, source.u32_0[0usize]); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FD3_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FD3(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FD3_mem(mut addr: i32, mut r: i32) -> () { + instr_660FD3(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FD4(mut source: reg64, mut r: i32) -> () { + c_comment!(("paddq mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + destination.u64_0[0usize] = + (destination.u64_0[0usize] as u64).wrapping_add(source.u64_0[0usize]) as u64 as u64; + write_mmx_reg64(r, destination); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FD4_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FD4(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FD4_mem(mut addr: i32, mut r: i32) -> () { + instr_0FD4(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FD4(mut source: reg128, mut r: i32) -> () { + c_comment!(("paddq xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + destination.u64_0[0usize] = + (destination.u64_0[0usize] as u64).wrapping_add(source.u64_0[0usize]) as u64 as u64; + destination.u64_0[1usize] = + (destination.u64_0[1usize] as u64).wrapping_add(source.u64_0[1usize]) as u64 as u64; + write_xmm_reg128(r, destination); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FD4_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FD4(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FD4_mem(mut addr: i32, mut r: i32) -> () { + instr_660FD4(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FD5(mut source: reg64, mut r: i32) -> () { + c_comment!(("pmullw mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut word0: i32 = destination.u16_0[0usize] as i32 * source.u16_0[0usize] as i32 & 65535i32; + let mut word1: i32 = destination.u16_0[1usize] as i32 * source.u16_0[1usize] as i32 & 65535i32; + let mut word2: i32 = destination.u16_0[2usize] as i32 * source.u16_0[2usize] as i32 & 65535i32; + let mut word3: i32 = destination.u16_0[3usize] as i32 * source.u16_0[3usize] as i32 & 65535i32; + let mut low: i32 = word0 | word1 << 16i32; + let mut high: i32 = word2 | word3 << 16i32; + write_mmx64(r, low, high); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FD5_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FD5(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FD5_mem(mut addr: i32, mut r: i32) -> () { + instr_0FD5(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FD5(mut source: reg128, mut r: i32) -> () { + c_comment!(("pmullw xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + write_xmm128( + r, + source.u16_0[0usize] as i32 * destination.u16_0[0usize] as i32 & 65535i32 + | (source.u16_0[1usize] as i32 * destination.u16_0[1usize] as i32) << 16i32, + source.u16_0[2usize] as i32 * destination.u16_0[2usize] as i32 & 65535i32 + | (source.u16_0[3usize] as i32 * destination.u16_0[3usize] as i32) << 16i32, + source.u16_0[4usize] as i32 * destination.u16_0[4usize] as i32 & 65535i32 + | (source.u16_0[5usize] as i32 * destination.u16_0[5usize] as i32) << 16i32, + source.u16_0[6usize] as i32 * destination.u16_0[6usize] as i32 & 65535i32 + | (source.u16_0[7usize] as i32 * destination.u16_0[7usize] as i32) << 16i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FD5_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FD5(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FD5_mem(mut addr: i32, mut r: i32) -> () { + instr_660FD5(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FD6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FD6_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660FD6_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movq xmm/m64, xmm")); + movl_r128_m64(addr, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FD6_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("movq xmm/m64, xmm")); + let mut data: reg64 = read_xmm64s(r2); + write_xmm128( + r1, + data.u32_0[0usize] as i32, + data.u32_0[1usize] as i32, + 0i32, + 0i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20FD6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_F20FD6_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("movdq2q mm, xmm")); + let mut source: reg128 = read_xmm128s(r1); + write_mmx64(r2, source.u32_0[0usize] as i32, source.u32_0[1usize] as i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30FD6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_F30FD6_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("movq2dq xmm, mm")); + let mut source: reg64 = read_mmx64s(r1); + write_xmm128( + r2, + source.u32_0[0usize] as i32, + source.u32_0[1usize] as i32, + 0i32, + 0i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FD7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FD7_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("pmovmskb r, mm")); + let mut x: reg64 = read_mmx64s(r1); + let mut result: u32 = (x.u8_0[0usize] as i32 >> 7i32 << 0i32 + | x.u8_0[1usize] as i32 >> 7i32 << 1i32 + | x.u8_0[2usize] as i32 >> 7i32 << 2i32 + | x.u8_0[3usize] as i32 >> 7i32 << 3i32 + | x.u8_0[4usize] as i32 >> 7i32 << 4i32 + | x.u8_0[5usize] as i32 >> 7i32 << 5i32 + | x.u8_0[6usize] as i32 >> 7i32 << 6i32 + | x.u8_0[7usize] as i32 >> 7i32 << 7i32) as u32; + write_reg32(r2, result as i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FD7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660FD7_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("pmovmskb reg, xmm")); + let mut x: reg128 = read_xmm128s(r1); + let mut result: i32 = x.u8_0[0usize] as i32 >> 7i32 << 0i32 + | x.u8_0[1usize] as i32 >> 7i32 << 1i32 + | x.u8_0[2usize] as i32 >> 7i32 << 2i32 + | x.u8_0[3usize] as i32 >> 7i32 << 3i32 + | x.u8_0[4usize] as i32 >> 7i32 << 4i32 + | x.u8_0[5usize] as i32 >> 7i32 << 5i32 + | x.u8_0[6usize] as i32 >> 7i32 << 6i32 + | x.u8_0[7usize] as i32 >> 7i32 << 7i32 + | x.u8_0[8usize] as i32 >> 7i32 << 8i32 + | x.u8_0[9usize] as i32 >> 7i32 << 9i32 + | x.u8_0[10usize] as i32 >> 7i32 << 10i32 + | x.u8_0[11usize] as i32 >> 7i32 << 11i32 + | x.u8_0[12usize] as i32 >> 7i32 << 12i32 + | x.u8_0[13usize] as i32 >> 7i32 << 13i32 + | x.u8_0[14usize] as i32 >> 7i32 << 14i32 + | x.u8_0[15usize] as i32 >> 7i32 << 15i32; + write_reg32(r2, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FD8(mut source: reg64, mut r: i32) -> () { + c_comment!(("psubusb mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut result: reg64 = reg64 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + }; + let mut i: u32 = 0i32 as u32; + while i < 8i32 as u32 { + result.u8_0[i as usize] = + saturate_sd_to_ub(destination.u8_0[i as usize] as i32 - source.u8_0[i as usize] as i32) + as u8; + i = i.wrapping_add(1) + } + write_mmx_reg64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FD8_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FD8(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FD8_mem(mut addr: i32, mut r: i32) -> () { + instr_0FD8(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FD8(mut source: reg128, mut r: i32) -> () { + c_comment!(("psubusb xmm, xmm/m128")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { i8_0: [0; 16] }; + let mut i: u32 = 0i32 as u32; + while i < 16i32 as u32 { + result.u8_0[i as usize] = + saturate_sd_to_ub(destination.u8_0[i as usize] as i32 - source.u8_0[i as usize] as i32) + as u8; + i = i.wrapping_add(1) + } + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FD8_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FD8(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FD8_mem(mut addr: i32, mut r: i32) -> () { + instr_660FD8(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FD9(mut source: reg64, mut r: i32) -> () { + c_comment!(("psubusw mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut word0: i32 = + saturate_uw((destination.u16_0[0usize] as i32 - source.u16_0[0usize] as i32) as u32); + let mut word1: i32 = + saturate_uw((destination.u16_0[1usize] as i32 - source.u16_0[1usize] as i32) as u32); + let mut word2: i32 = + saturate_uw((destination.u16_0[2usize] as i32 - source.u16_0[2usize] as i32) as u32); + let mut word3: i32 = + saturate_uw((destination.u16_0[3usize] as i32 - source.u16_0[3usize] as i32) as u32); + let mut low: i32 = word0 | word1 << 16i32; + let mut high: i32 = word2 | word3 << 16i32; + write_mmx64(r, low, high); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FD9_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FD9(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FD9_mem(mut addr: i32, mut r: i32) -> () { + instr_0FD9(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FD9(mut source: reg128, mut r: i32) -> () { + c_comment!(("psubusw xmm, xmm/m128")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { i8_0: [0; 16] }; + let mut i: u32 = 0i32 as u32; + while i < 8i32 as u32 { + result.u16_0[i as usize] = saturate_uw( + (destination.u16_0[i as usize] as i32 - source.u16_0[i as usize] as i32) as u32, + ) as u16; + i = i.wrapping_add(1) + } + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FD9_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FD9(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FD9_mem(mut addr: i32, mut r: i32) -> () { + instr_660FD9(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FDA(mut source: reg64, mut r: i32) -> () { + c_comment!(("pminub mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut result: reg64 = reg64 { i8_0: [0; 8] }; + let mut i: u32 = 0i32 as u32; + while i < 8i32 as u32 { + result.u8_0[i as usize] = + (if (source.u8_0[i as usize] as i32) < destination.u8_0[i as usize] as i32 { + source.u8_0[i as usize] as i32 + } + else { + destination.u8_0[i as usize] as i32 + }) as u8; + i = i.wrapping_add(1) + } + write_mmx_reg64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FDA_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FDA(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FDA_mem(mut addr: i32, mut r: i32) -> () { + instr_0FDA(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FDA(mut source: reg128, mut r: i32) -> () { + c_comment!(("pminub xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { i8_0: [0; 16] }; + let mut i: u32 = 0i32 as u32; + while i < 16i32 as u32 { + result.u8_0[i as usize] = + (if (source.u8_0[i as usize] as i32) < destination.u8_0[i as usize] as i32 { + source.u8_0[i as usize] as i32 + } + else { + destination.u8_0[i as usize] as i32 + }) as u8; + i = i.wrapping_add(1) + } + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FDA_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FDA(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FDA_mem(mut addr: i32, mut r: i32) -> () { + instr_660FDA(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FDB(mut source: reg64, mut r: i32) -> () { + c_comment!(("pand mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut result: reg64 = reg64 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + }; + result.u64_0[0usize] = source.u64_0[0usize] & destination.u64_0[0usize]; + write_mmx_reg64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FDB_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FDB(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FDB_mem(mut addr: i32, mut r: i32) -> () { + instr_0FDB(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FDB(mut source: reg128, mut r: i32) -> () { + c_comment!(("pand xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + pand_r128(source, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FDB_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FDB(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FDB_mem(mut addr: i32, mut r: i32) -> () { + instr_660FDB(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FDC(mut source: reg64, mut r: i32) -> () { + c_comment!(("paddusb mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut result: reg64 = reg64 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + }; + let mut i: u32 = 0i32 as u32; + while i < 8i32 as u32 { + result.u8_0[i as usize] = saturate_ud_to_ub( + (destination.u8_0[i as usize] as i32 + source.u8_0[i as usize] as i32) as u32, + ) as u8; + i = i.wrapping_add(1) + } + write_mmx_reg64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FDC_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FDC(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FDC_mem(mut addr: i32, mut r: i32) -> () { + instr_0FDC(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FDC(mut source: reg128, mut r: i32) -> () { + c_comment!(("paddusb xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { i8_0: [0; 16] }; + let mut i: u32 = 0i32 as u32; + while i < 16i32 as u32 { + result.u8_0[i as usize] = saturate_ud_to_ub( + (source.u8_0[i as usize] as i32 + destination.u8_0[i as usize] as i32) as u32, + ) as u8; + i = i.wrapping_add(1) + } + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FDC_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FDC(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FDC_mem(mut addr: i32, mut r: i32) -> () { + instr_660FDC(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FDD(mut source: reg64, mut r: i32) -> () { + c_comment!(("paddusw mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut word0: i32 = + saturate_uw((destination.u16_0[0usize] as i32 + source.u16_0[0usize] as i32) as u32); + let mut word1: i32 = + saturate_uw((destination.u16_0[1usize] as i32 + source.u16_0[1usize] as i32) as u32); + let mut word2: i32 = + saturate_uw((destination.u16_0[2usize] as i32 + source.u16_0[2usize] as i32) as u32); + let mut word3: i32 = + saturate_uw((destination.u16_0[3usize] as i32 + source.u16_0[3usize] as i32) as u32); + let mut low: i32 = word0 | word1 << 16i32; + let mut high: i32 = word2 | word3 << 16i32; + write_mmx64(r, low, high); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FDD_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FDD(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FDD_mem(mut addr: i32, mut r: i32) -> () { + instr_0FDD(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FDD(mut source: reg128, mut r: i32) -> () { + c_comment!(("paddusw xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + write_xmm128( + r, + saturate_uw((source.u16_0[0usize] as i32 + destination.u16_0[0usize] as i32) as u32) + | saturate_uw((source.u16_0[1usize] as i32 + destination.u16_0[1usize] as i32) as u32) + << 16i32, + saturate_uw((source.u16_0[2usize] as i32 + destination.u16_0[2usize] as i32) as u32) + | saturate_uw((source.u16_0[3usize] as i32 + destination.u16_0[3usize] as i32) as u32) + << 16i32, + saturate_uw((source.u16_0[4usize] as i32 + destination.u16_0[4usize] as i32) as u32) + | saturate_uw((source.u16_0[5usize] as i32 + destination.u16_0[5usize] as i32) as u32) + << 16i32, + saturate_uw((source.u16_0[6usize] as i32 + destination.u16_0[6usize] as i32) as u32) + | saturate_uw((source.u16_0[7usize] as i32 + destination.u16_0[7usize] as i32) as u32) + << 16i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FDD_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FDD(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FDD_mem(mut addr: i32, mut r: i32) -> () { + instr_660FDD(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FDE(mut source: reg64, mut r: i32) -> () { + c_comment!(("pmaxub mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut result: reg64 = reg64 { i8_0: [0; 8] }; + let mut i: u32 = 0i32 as u32; + while i < 8i32 as u32 { + result.u8_0[i as usize] = + (if source.u8_0[i as usize] as i32 > destination.u8_0[i as usize] as i32 { + source.u8_0[i as usize] as i32 + } + else { + destination.u8_0[i as usize] as i32 + }) as u8; + i = i.wrapping_add(1) + } + write_mmx_reg64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FDE_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FDE(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FDE_mem(mut addr: i32, mut r: i32) -> () { + instr_0FDE(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FDE(mut source: reg128, mut r: i32) -> () { + c_comment!(("pmaxub xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { i8_0: [0; 16] }; + let mut i: u32 = 0i32 as u32; + while i < 16i32 as u32 { + result.u8_0[i as usize] = + (if source.u8_0[i as usize] as i32 > destination.u8_0[i as usize] as i32 { + source.u8_0[i as usize] as i32 + } + else { + destination.u8_0[i as usize] as i32 + }) as u8; + i = i.wrapping_add(1) + } + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FDE_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FDE(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FDE_mem(mut addr: i32, mut r: i32) -> () { + instr_660FDE(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FDF(mut source: reg64, mut r: i32) -> () { + c_comment!(("pandn mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut result: reg64 = reg64 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + }; + result.u64_0[0usize] = source.u64_0[0usize] & !destination.u64_0[0usize]; + write_mmx_reg64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FDF_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FDF(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FDF_mem(mut addr: i32, mut r: i32) -> () { + instr_0FDF(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FDF(mut source: reg128, mut r: i32) -> () { + c_comment!(("pandn xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + pandn_r128(source, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FDF_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FDF(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FDF_mem(mut addr: i32, mut r: i32) -> () { + instr_660FDF(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE0(mut source: reg64, mut r: i32) -> () { + c_comment!(("pavgb mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut result: reg64 = reg64 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + }; + let mut i: u32 = 0i32 as u32; + while i < 8i32 as u32 { + result.u8_0[i as usize] = + (destination.u8_0[i as usize] as i32 + source.u8_0[i as usize] as i32 + 1i32 >> 1i32) + as u8; + i = i.wrapping_add(1) + } + write_mmx_reg64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE0_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FE0(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE0_mem(mut addr: i32, mut r: i32) -> () { + instr_0FE0(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE0(mut source: reg128, mut r: i32) -> () { + c_comment!(("pavgb xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { i8_0: [0; 16] }; + let mut i: u32 = 0i32 as u32; + while i < 16i32 as u32 { + result.u8_0[i as usize] = + (destination.u8_0[i as usize] as i32 + source.u8_0[i as usize] as i32 + 1i32 >> 1i32) + as u8; + i = i.wrapping_add(1) + } + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE0_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FE0(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE0_mem(mut addr: i32, mut r: i32) -> () { + instr_660FE0(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE1(mut source: reg64, mut r: i32) -> () { + c_comment!(("psraw mm, mm/m64")); + psraw_r64(r, source.u32_0[0usize]); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE1_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FE1(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE1_mem(mut addr: i32, mut r: i32) -> () { + instr_0FE1(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE1(mut source: reg128, mut r: i32) -> () { + c_comment!(("psraw xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + psraw_r128(r, source.u32_0[0usize]); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE1_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FE1(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE1_mem(mut addr: i32, mut r: i32) -> () { + instr_660FE1(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE2(mut source: reg64, mut r: i32) -> () { + c_comment!(("psrad mm, mm/m64")); + psrad_r64(r, source.u32_0[0usize]); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE2_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FE2(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE2_mem(mut addr: i32, mut r: i32) -> () { + instr_0FE2(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE2(mut source: reg128, mut r: i32) -> () { + c_comment!(("psrad xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + psrad_r128(r, source.u32_0[0usize]); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE2_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FE2(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE2_mem(mut addr: i32, mut r: i32) -> () { + instr_660FE2(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE3(mut source: reg64, mut r: i32) -> () { + c_comment!(("pavgw mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + destination.u16_0[0usize] = + (destination.u16_0[0usize] as i32 + source.u16_0[0usize] as i32 + 1i32 >> 1i32) as u16; + destination.u16_0[1usize] = + (destination.u16_0[1usize] as i32 + source.u16_0[1usize] as i32 + 1i32 >> 1i32) as u16; + destination.u16_0[2usize] = + (destination.u16_0[2usize] as i32 + source.u16_0[2usize] as i32 + 1i32 >> 1i32) as u16; + destination.u16_0[3usize] = + (destination.u16_0[3usize] as i32 + source.u16_0[3usize] as i32 + 1i32 >> 1i32) as u16; + write_mmx_reg64(r, destination); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE3_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FE3(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE3_mem(mut addr: i32, mut r: i32) -> () { + instr_0FE3(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE3(mut source: reg128, mut r: i32) -> () { + c_comment!(("pavgw xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + destination.u16_0[0usize] = + (destination.u16_0[0usize] as i32 + source.u16_0[0usize] as i32 + 1i32 >> 1i32) as u16; + destination.u16_0[1usize] = + (destination.u16_0[1usize] as i32 + source.u16_0[1usize] as i32 + 1i32 >> 1i32) as u16; + destination.u16_0[2usize] = + (destination.u16_0[2usize] as i32 + source.u16_0[2usize] as i32 + 1i32 >> 1i32) as u16; + destination.u16_0[3usize] = + (destination.u16_0[3usize] as i32 + source.u16_0[3usize] as i32 + 1i32 >> 1i32) as u16; + destination.u16_0[4usize] = + (destination.u16_0[4usize] as i32 + source.u16_0[4usize] as i32 + 1i32 >> 1i32) as u16; + destination.u16_0[5usize] = + (destination.u16_0[5usize] as i32 + source.u16_0[5usize] as i32 + 1i32 >> 1i32) as u16; + destination.u16_0[6usize] = + (destination.u16_0[6usize] as i32 + source.u16_0[6usize] as i32 + 1i32 >> 1i32) as u16; + destination.u16_0[7usize] = + (destination.u16_0[7usize] as i32 + source.u16_0[7usize] as i32 + 1i32 >> 1i32) as u16; + write_xmm_reg128(r, destination); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE3_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FE3(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE3_mem(mut addr: i32, mut r: i32) -> () { + instr_660FE3(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE4(mut source: reg64, mut r: i32) -> () { + c_comment!(("pmulhuw mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + write_mmx64( + r, + ((source.u16_0[0usize] as i32 * destination.u16_0[0usize] as i32 >> 16i32 & 65535i32) + as u32 + | (source.u16_0[1usize] as i32 * destination.u16_0[1usize] as i32) as u32 + & 4294901760u32) as i32, + ((source.u16_0[2usize] as i32 * destination.u16_0[2usize] as i32 >> 16i32 & 65535i32) + as u32 + | (source.u16_0[3usize] as i32 * destination.u16_0[3usize] as i32) as u32 + & 4294901760u32) as i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE4_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FE4(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE4_mem(mut addr: i32, mut r: i32) -> () { + instr_0FE4(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE4(mut source: reg128, mut r: i32) -> () { + c_comment!(("pmulhuw xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + write_xmm128( + r, + ((source.u16_0[0usize] as i32 * destination.u16_0[0usize] as i32 >> 16i32 & 65535i32) + as u32 + | (source.u16_0[1usize] as i32 * destination.u16_0[1usize] as i32) as u32 + & 4294901760u32) as i32, + ((source.u16_0[2usize] as i32 * destination.u16_0[2usize] as i32 >> 16i32 & 65535i32) + as u32 + | (source.u16_0[3usize] as i32 * destination.u16_0[3usize] as i32) as u32 + & 4294901760u32) as i32, + ((source.u16_0[4usize] as i32 * destination.u16_0[4usize] as i32 >> 16i32 & 65535i32) + as u32 + | (source.u16_0[5usize] as i32 * destination.u16_0[5usize] as i32) as u32 + & 4294901760u32) as i32, + ((source.u16_0[6usize] as i32 * destination.u16_0[6usize] as i32 >> 16i32 & 65535i32) + as u32 + | (source.u16_0[7usize] as i32 * destination.u16_0[7usize] as i32) as u32 + & 4294901760u32) as i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE4_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FE4(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE4_mem(mut addr: i32, mut r: i32) -> () { + instr_660FE4(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE5(mut source: reg64, mut r: i32) -> () { + c_comment!(("pmulhw mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut word0: u32 = + (destination.i16_0[0usize] as i32 * source.i16_0[0usize] as i32 >> 16i32 & 65535i32) as u32; + let mut word1: u32 = + (destination.i16_0[1usize] as i32 * source.i16_0[1usize] as i32 >> 16i32 & 65535i32) as u32; + let mut word2: u32 = + (destination.i16_0[2usize] as i32 * source.i16_0[2usize] as i32 >> 16i32 & 65535i32) as u32; + let mut word3: u32 = + (destination.i16_0[3usize] as i32 * source.i16_0[3usize] as i32 >> 16i32 & 65535i32) as u32; + let mut low: i32 = (word0 | word1 << 16i32) as i32; + let mut high: i32 = (word2 | word3 << 16i32) as i32; + write_mmx64(r, low, high); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE5_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FE5(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE5_mem(mut addr: i32, mut r: i32) -> () { + instr_0FE5(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE5(mut source: reg128, mut r: i32) -> () { + c_comment!(("pmulhw xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut dword0: i32 = ((destination.i16_0[0usize] as i32 * source.i16_0[0usize] as i32 >> 16i32 + & 65535i32) as u32 + | (destination.i16_0[1usize] as i32 * source.i16_0[1usize] as i32) as u32 & 4294901760u32) + as i32; + let mut dword1: i32 = ((destination.i16_0[2usize] as i32 * source.i16_0[2usize] as i32 >> 16i32 + & 65535i32) as u32 + | (destination.i16_0[3usize] as i32 * source.i16_0[3usize] as i32) as u32 & 4294901760u32) + as i32; + let mut dword2: i32 = ((destination.i16_0[4usize] as i32 * source.i16_0[4usize] as i32 >> 16i32 + & 65535i32) as u32 + | (destination.i16_0[5usize] as i32 * source.i16_0[5usize] as i32) as u32 & 4294901760u32) + as i32; + let mut dword3: i32 = ((destination.i16_0[6usize] as i32 * source.i16_0[6usize] as i32 >> 16i32 + & 65535i32) as u32 + | (destination.i16_0[7usize] as i32 * source.i16_0[7usize] as i32) as u32 & 4294901760u32) + as i32; + write_xmm128(r, dword0, dword1, dword2, dword3); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE5_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FE5(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE5_mem(mut addr: i32, mut r: i32) -> () { + instr_660FE5(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FE6_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660FE6_mem(mut addr: i32, mut r: i32) -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660FE6_reg(mut r1: i32, mut r2: i32) -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_F20FE6_mem(mut addr: i32, mut r: i32) -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_F20FE6_reg(mut r1: i32, mut r2: i32) -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_F30FE6_mem(mut addr: i32, mut r: i32) -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_F30FE6_reg(mut r1: i32, mut r2: i32) -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FE7_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movntq m64, mm")); + mov_r_m64(addr, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE7_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660FE7_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660FE7_mem(mut addr: i32, mut r: i32) -> () { + c_comment!(("movntdq m128, xmm")); + mov_r_m128(addr, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE8(mut source: reg64, mut r: i32) -> () { + c_comment!(("psubsb mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut result: reg64 = reg64 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + }; + let mut i: u32 = 0i32 as u32; + while i < 8i32 as u32 { + result.u8_0[i as usize] = saturate_sd_to_sb( + (destination.i8_0[i as usize] as i32 - source.i8_0[i as usize] as i32) as u32, + ) as u8; + i = i.wrapping_add(1) + } + write_mmx_reg64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE8_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FE8(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE8_mem(mut addr: i32, mut r: i32) -> () { + instr_0FE8(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE8(mut source: reg128, mut r: i32) -> () { + c_comment!(("psubsb xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { i8_0: [0; 16] }; + let mut i: u32 = 0i32 as u32; + while i < 16i32 as u32 { + result.i8_0[i as usize] = saturate_sd_to_sb( + (destination.i8_0[i as usize] as i32 - source.i8_0[i as usize] as i32) as u32, + ) as i8; + i = i.wrapping_add(1) + } + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE8_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FE8(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE8_mem(mut addr: i32, mut r: i32) -> () { + instr_660FE8(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE9(mut source: reg64, mut r: i32) -> () { + c_comment!(("psubsw mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut word0: i32 = + saturate_sd_to_sw((destination.i16_0[0usize] as i32 - source.i16_0[0usize] as i32) as u32) + as i32; + let mut word1: i32 = + saturate_sd_to_sw((destination.i16_0[1usize] as i32 - source.i16_0[1usize] as i32) as u32) + as i32; + let mut word2: i32 = + saturate_sd_to_sw((destination.i16_0[2usize] as i32 - source.i16_0[2usize] as i32) as u32) + as i32; + let mut word3: i32 = + saturate_sd_to_sw((destination.i16_0[3usize] as i32 - source.i16_0[3usize] as i32) as u32) + as i32; + let mut low: i32 = word0 | word1 << 16i32; + let mut high: i32 = word2 | word3 << 16i32; + write_mmx64(r, low, high); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE9_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FE9(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FE9_mem(mut addr: i32, mut r: i32) -> () { + instr_0FE9(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE9(mut source: reg128, mut r: i32) -> () { + c_comment!(("psubsw xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut dword0: i32 = + (saturate_sd_to_sw((destination.i16_0[0usize] as i32 - source.i16_0[0usize] as i32) as u32) + | saturate_sd_to_sw( + (destination.i16_0[1usize] as i32 - source.i16_0[1usize] as i32) as u32, + ) << 16i32) as i32; + let mut dword1: i32 = + (saturate_sd_to_sw((destination.i16_0[2usize] as i32 - source.i16_0[2usize] as i32) as u32) + | saturate_sd_to_sw( + (destination.i16_0[3usize] as i32 - source.i16_0[3usize] as i32) as u32, + ) << 16i32) as i32; + let mut dword2: i32 = + (saturate_sd_to_sw((destination.i16_0[4usize] as i32 - source.i16_0[4usize] as i32) as u32) + | saturate_sd_to_sw( + (destination.i16_0[5usize] as i32 - source.i16_0[5usize] as i32) as u32, + ) << 16i32) as i32; + let mut dword3: i32 = + (saturate_sd_to_sw((destination.i16_0[6usize] as i32 - source.i16_0[6usize] as i32) as u32) + | saturate_sd_to_sw( + (destination.i16_0[7usize] as i32 - source.i16_0[7usize] as i32) as u32, + ) << 16i32) as i32; + write_xmm128(r, dword0, dword1, dword2, dword3); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE9_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FE9(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FE9_mem(mut addr: i32, mut r: i32) -> () { + instr_660FE9(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FEA(mut source: reg64, mut r: i32) -> () { + c_comment!(("pminsw mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut result: reg64 = reg64 { i8_0: [0; 8] }; + let mut i: u32 = 0i32 as u32; + while i < 4i32 as u32 { + result.i16_0[i as usize] = + (if (destination.i16_0[i as usize] as i32) < source.i16_0[i as usize] as i32 { + destination.i16_0[i as usize] as i32 + } + else { + source.i16_0[i as usize] as i32 + }) as i16; + i = i.wrapping_add(1) + } + write_mmx_reg64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FEA_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FEA(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FEA_mem(mut addr: i32, mut r: i32) -> () { + instr_0FEA(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FEA(mut source: reg128, mut r: i32) -> () { + c_comment!(("pminsw xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { i8_0: [0; 16] }; + let mut i: u32 = 0i32 as u32; + while i < 8i32 as u32 { + result.i16_0[i as usize] = + (if (destination.i16_0[i as usize] as i32) < source.i16_0[i as usize] as i32 { + destination.i16_0[i as usize] as i32 + } + else { + source.i16_0[i as usize] as i32 + }) as i16; + i = i.wrapping_add(1) + } + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FEA_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FEA(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FEA_mem(mut addr: i32, mut r: i32) -> () { + instr_660FEA(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FEB(mut source: reg64, mut r: i32) -> () { + c_comment!(("por mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut result: reg64 = reg64 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + }; + result.u64_0[0usize] = source.u64_0[0usize] | destination.u64_0[0usize]; + write_mmx_reg64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FEB_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FEB(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FEB_mem(mut addr: i32, mut r: i32) -> () { + instr_0FEB(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FEB(mut source: reg128, mut r: i32) -> () { + c_comment!(("por xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + por_r128(source, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FEB_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FEB(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FEB_mem(mut addr: i32, mut r: i32) -> () { + instr_660FEB(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FEC(mut source: reg64, mut r: i32) -> () { + c_comment!(("paddsb mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut result: reg64 = reg64 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + }; + let mut i: u32 = 0i32 as u32; + while i < 8i32 as u32 { + result.u8_0[i as usize] = saturate_sd_to_sb( + (destination.i8_0[i as usize] as i32 + source.i8_0[i as usize] as i32) as u32, + ) as u8; + i = i.wrapping_add(1) + } + write_mmx_reg64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FEC_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FEC(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FEC_mem(mut addr: i32, mut r: i32) -> () { + instr_0FEC(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FEC(mut source: reg128, mut r: i32) -> () { + c_comment!(("paddsb xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { i8_0: [0; 16] }; + let mut i: u32 = 0i32 as u32; + while i < 16i32 as u32 { + result.i8_0[i as usize] = saturate_sd_to_sb( + (destination.i8_0[i as usize] as i32 + source.i8_0[i as usize] as i32) as u32, + ) as i8; + i = i.wrapping_add(1) + } + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FEC_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FEC(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FEC_mem(mut addr: i32, mut r: i32) -> () { + instr_660FEC(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FED(mut source: reg64, mut r: i32) -> () { + c_comment!(("paddsw mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut word0: i32 = + saturate_sd_to_sw((destination.i16_0[0usize] as i32 + source.i16_0[0usize] as i32) as u32) + as i32; + let mut word1: i32 = + saturate_sd_to_sw((destination.i16_0[1usize] as i32 + source.i16_0[1usize] as i32) as u32) + as i32; + let mut word2: i32 = + saturate_sd_to_sw((destination.i16_0[2usize] as i32 + source.i16_0[2usize] as i32) as u32) + as i32; + let mut word3: i32 = + saturate_sd_to_sw((destination.i16_0[3usize] as i32 + source.i16_0[3usize] as i32) as u32) + as i32; + let mut low: i32 = word0 | word1 << 16i32; + let mut high: i32 = word2 | word3 << 16i32; + write_mmx64(r, low, high); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FED_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FED(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FED_mem(mut addr: i32, mut r: i32) -> () { + instr_0FED(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FED(mut source: reg128, mut r: i32) -> () { + c_comment!(("paddsw xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut dword0: i32 = + (saturate_sd_to_sw((destination.i16_0[0usize] as i32 + source.i16_0[0usize] as i32) as u32) + | saturate_sd_to_sw( + (destination.i16_0[1usize] as i32 + source.i16_0[1usize] as i32) as u32, + ) << 16i32) as i32; + let mut dword1: i32 = + (saturate_sd_to_sw((destination.i16_0[2usize] as i32 + source.i16_0[2usize] as i32) as u32) + | saturate_sd_to_sw( + (destination.i16_0[3usize] as i32 + source.i16_0[3usize] as i32) as u32, + ) << 16i32) as i32; + let mut dword2: i32 = + (saturate_sd_to_sw((destination.i16_0[4usize] as i32 + source.i16_0[4usize] as i32) as u32) + | saturate_sd_to_sw( + (destination.i16_0[5usize] as i32 + source.i16_0[5usize] as i32) as u32, + ) << 16i32) as i32; + let mut dword3: i32 = + (saturate_sd_to_sw((destination.i16_0[6usize] as i32 + source.i16_0[6usize] as i32) as u32) + | saturate_sd_to_sw( + (destination.i16_0[7usize] as i32 + source.i16_0[7usize] as i32) as u32, + ) << 16i32) as i32; + write_xmm128(r, dword0, dword1, dword2, dword3); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FED_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FED(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FED_mem(mut addr: i32, mut r: i32) -> () { + instr_660FED(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FEE(mut source: reg64, mut r: i32) -> () { + c_comment!(("pmaxsw mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut result: reg64 = reg64 { i8_0: [0; 8] }; + let mut i: u32 = 0i32 as u32; + while i < 4i32 as u32 { + result.i16_0[i as usize] = + (if destination.i16_0[i as usize] as i32 >= source.i16_0[i as usize] as i32 { + destination.i16_0[i as usize] as i32 + } + else { + source.i16_0[i as usize] as i32 + }) as i16; + i = i.wrapping_add(1) + } + write_mmx_reg64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FEE_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FEE(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FEE_mem(mut addr: i32, mut r: i32) -> () { + instr_0FEE(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FEE(mut source: reg128, mut r: i32) -> () { + c_comment!(("pmaxsw xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { i8_0: [0; 16] }; + let mut i: u32 = 0i32 as u32; + while i < 8i32 as u32 { + result.i16_0[i as usize] = + (if destination.i16_0[i as usize] as i32 >= source.i16_0[i as usize] as i32 { + destination.i16_0[i as usize] as i32 + } + else { + source.i16_0[i as usize] as i32 + }) as i16; + i = i.wrapping_add(1) + } + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FEE_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FEE(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FEE_mem(mut addr: i32, mut r: i32) -> () { + instr_660FEE(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FEF(mut source: reg64, mut r: i32) -> () { + c_comment!(("pxor mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut result: reg64 = reg64 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + }; + result.u64_0[0usize] = source.u64_0[0usize] ^ destination.u64_0[0usize]; + write_mmx_reg64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FEF_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FEF(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FEF_mem(mut addr: i32, mut r: i32) -> () { + instr_0FEF(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FEF(mut source: reg128, mut r: i32) -> () { + c_comment!(("pxor xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + pxor_r128(source, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FEF_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FEF(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FEF_mem(mut addr: i32, mut r: i32) -> () { + instr_660FEF(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF0() -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FF1(mut source: reg64, mut r: i32) -> () { + c_comment!(("psllw mm, mm/m64")); + psllw_r64(r, source.u32_0[0usize]); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF1_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FF1(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF1_mem(mut addr: i32, mut r: i32) -> () { + instr_0FF1(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF1(mut source: reg128, mut r: i32) -> () { + c_comment!(("psllw xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + psllw_r128(r, source.u32_0[0usize]); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF1_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FF1(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF1_mem(mut addr: i32, mut r: i32) -> () { + instr_660FF1(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF2(mut source: reg64, mut r: i32) -> () { + c_comment!(("pslld mm, mm/m64")); + pslld_r64(r, source.u32_0[0usize]); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF2_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FF2(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF2_mem(mut addr: i32, mut r: i32) -> () { + instr_0FF2(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF2(mut source: reg128, mut r: i32) -> () { + c_comment!(("pslld xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + pslld_r128(r, source.u32_0[0usize]); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF2_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FF2(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF2_mem(mut addr: i32, mut r: i32) -> () { + instr_660FF2(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF3(mut source: reg64, mut r: i32) -> () { + c_comment!(("psllq mm, mm/m64")); + psllq_r64(r, source.u32_0[0usize]); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF3_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FF3(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF3_mem(mut addr: i32, mut r: i32) -> () { + instr_0FF3(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF3(mut source: reg128, mut r: i32) -> () { + c_comment!(("psllq xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + psllq_r128(r, source.u32_0[0usize]); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF3_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FF3(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF3_mem(mut addr: i32, mut r: i32) -> () { + instr_660FF3(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF4(mut source: reg64, mut r: i32) -> () { + c_comment!(("pmuludq mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + destination.u64_0[0usize] = + (source.u32_0[0usize] as u64).wrapping_mul(destination.u32_0[0usize] as u64); + write_mmx_reg64(r, destination); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF4_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FF4(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF4_mem(mut addr: i32, mut r: i32) -> () { + instr_0FF4(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF4(mut source: reg128, mut r: i32) -> () { + c_comment!(("pmuludq xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + destination.u64_0[0usize] = + (source.u32_0[0usize] as u64).wrapping_mul(destination.u32_0[0usize] as u64); + destination.u64_0[1usize] = + (source.u32_0[2usize] as u64).wrapping_mul(destination.u32_0[2usize] as u64); + write_xmm_reg128(r, destination); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF4_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FF4(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF4_mem(mut addr: i32, mut r: i32) -> () { + instr_660FF4(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF5(mut source: reg64, mut r: i32) -> () { + c_comment!(("pmaddwd mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut mul0: i32 = destination.i16_0[0usize] as i32 * source.i16_0[0usize] as i32; + let mut mul1: i32 = destination.i16_0[1usize] as i32 * source.i16_0[1usize] as i32; + let mut mul2: i32 = destination.i16_0[2usize] as i32 * source.i16_0[2usize] as i32; + let mut mul3: i32 = destination.i16_0[3usize] as i32 * source.i16_0[3usize] as i32; + let mut low: i32 = mul0 + mul1; + let mut high: i32 = mul2 + mul3; + write_mmx64(r, low, high); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF5_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FF5(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF5_mem(mut addr: i32, mut r: i32) -> () { + instr_0FF5(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF5(mut source: reg128, mut r: i32) -> () { + c_comment!(("pmaddwd xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut dword0: i32 = destination.i16_0[0usize] as i32 * source.i16_0[0usize] as i32 + + destination.i16_0[1usize] as i32 * source.i16_0[1usize] as i32; + let mut dword1: i32 = destination.i16_0[2usize] as i32 * source.i16_0[2usize] as i32 + + destination.i16_0[3usize] as i32 * source.i16_0[3usize] as i32; + let mut dword2: i32 = destination.i16_0[4usize] as i32 * source.i16_0[4usize] as i32 + + destination.i16_0[5usize] as i32 * source.i16_0[5usize] as i32; + let mut dword3: i32 = destination.i16_0[6usize] as i32 * source.i16_0[6usize] as i32 + + destination.i16_0[7usize] as i32 * source.i16_0[7usize] as i32; + write_xmm128(r, dword0, dword1, dword2, dword3); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF5_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FF5(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF5_mem(mut addr: i32, mut r: i32) -> () { + instr_660FF5(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF6(mut source: reg64, mut r: i32) -> () { + c_comment!(("psadbw mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut sum: u32 = 0i32 as u32; + let mut i: u32 = 0i32 as u32; + while i < 8i32 as u32 { + sum = (sum as u32).wrapping_add(abs( + destination.u8_0[i as usize] as i32 - source.u8_0[i as usize] as i32 + ) as u32) as u32 as u32; + i = i.wrapping_add(1) + } + write_mmx64(r, sum as i32, 0i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF6_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FF6(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF6_mem(mut addr: i32, mut r: i32) -> () { + instr_0FF6(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF6(mut source: reg128, mut r: i32) -> () { + c_comment!(("psadbw xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut sum0: u32 = 0i32 as u32; + let mut sum1: u32 = 0i32 as u32; + let mut i: u32 = 0i32 as u32; + while i < 8i32 as u32 { + sum0 = (sum0 as u32).wrapping_add(abs( + destination.u8_0[i as usize] as i32 - source.u8_0[i as usize] as i32 + ) as u32) as u32 as u32; + sum1 = + (sum1 as u32).wrapping_add(abs(destination.u8_0[i.wrapping_add(8i32 as u32) as usize] + as i32 + - source.u8_0[i.wrapping_add(8i32 as u32) as usize] as i32) + as u32) as u32 as u32; + i = i.wrapping_add(1) + } + write_xmm128(r, sum0 as i32, 0i32, sum1 as i32, 0i32); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF6_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FF6(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF6_mem(mut addr: i32, mut r: i32) -> () { + instr_660FF6(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0FF7_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("maskmovq mm, mm")); + let mut source: reg64 = read_mmx64s(r2); + let mut mask: reg64 = read_mmx64s(r1); + let mut addr: i32 = get_seg_prefix(DS) + get_reg_asize(EDI); + writable_or_pagefault(addr, 8i32); + let mut i: u32 = 0i32 as u32; + while i < 8i32 as u32 { + if 0 != mask.u8_0[i as usize] as i32 & 128i32 { + safe_write8( + (addr as u32).wrapping_add(i) as i32, + source.u8_0[i as usize] as i32, + ); + } + i = i.wrapping_add(1) + } +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660FF7_reg(mut r1: i32, mut r2: i32) -> () { + c_comment!(("maskmovdqu xmm, xmm")); + let mut source: reg128 = read_xmm128s(r2); + let mut mask: reg128 = read_xmm128s(r1); + let mut addr: i32 = get_seg_prefix(DS) + get_reg_asize(EDI); + writable_or_pagefault(addr, 16i32); + let mut i: u32 = 0i32 as u32; + while i < 16i32 as u32 { + if 0 != mask.u8_0[i as usize] as i32 & 128i32 { + safe_write8( + (addr as u32).wrapping_add(i) as i32, + source.u8_0[i as usize] as i32, + ); + } + i = i.wrapping_add(1) + } +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF8(mut source: reg64, mut r: i32) -> () { + c_comment!(("psubb mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut result: reg64 = reg64 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + }; + let mut i: u32 = 0i32 as u32; + while i < 8i32 as u32 { + result.u8_0[i as usize] = + (destination.i8_0[i as usize] as i32 - source.i8_0[i as usize] as i32 & 255i32) as u8; + i = i.wrapping_add(1) + } + write_mmx_reg64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF8_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FF8(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF8_mem(mut addr: i32, mut r: i32) -> () { + instr_0FF8(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF8(mut source: reg128, mut r: i32) -> () { + c_comment!(("psubb xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + }; + let mut i: u32 = 0i32 as u32; + while i < 16i32 as u32 { + result.i8_0[i as usize] = + (destination.i8_0[i as usize] as i32 - source.i8_0[i as usize] as i32 & 255i32) as i8; + i = i.wrapping_add(1) + } + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF8_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FF8(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF8_mem(mut addr: i32, mut r: i32) -> () { + instr_660FF8(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF9(mut source: reg64, mut r: i32) -> () { + c_comment!(("psubw mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut word0: i32 = + (destination.u32_0[0usize].wrapping_sub(source.u32_0[0usize]) & 65535i32 as u32) as i32; + let mut word1: i32 = ((destination.u16_0[1usize] as u32) + .wrapping_sub(source.u16_0[1usize] as u32) + & 65535i32 as u32) as i32; + let mut low: i32 = word0 | word1 << 16i32; + let mut word2: i32 = + (destination.u32_0[1usize].wrapping_sub(source.u32_0[1usize]) & 65535i32 as u32) as i32; + let mut word3: i32 = ((destination.u16_0[3usize] as u32) + .wrapping_sub(source.u16_0[3usize] as u32) + & 65535i32 as u32) as i32; + let mut high: i32 = word2 | word3 << 16i32; + write_mmx64(r, low, high); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF9_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FF9(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FF9_mem(mut addr: i32, mut r: i32) -> () { + instr_0FF9(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF9(mut source: reg128, mut r: i32) -> () { + c_comment!(("psubw xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + }; + let mut i: u32 = 0i32 as u32; + while i < 8i32 as u32 { + result.i16_0[i as usize] = (destination.i16_0[i as usize] as i32 + - source.i16_0[i as usize] as i32 + & 65535i32) as i16; + i = i.wrapping_add(1) + } + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF9_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FF9(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FF9_mem(mut addr: i32, mut r: i32) -> () { + instr_660FF9(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FFA(mut source: reg64, mut r: i32) -> () { + c_comment!(("psubd mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + write_mmx64( + r, + destination.u32_0[0usize].wrapping_sub(source.u32_0[0usize]) as i32, + destination.u32_0[1usize].wrapping_sub(source.u32_0[1usize]) as i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FFA_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FFA(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FFA_mem(mut addr: i32, mut r: i32) -> () { + instr_0FFA(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FFA(mut source: reg128, mut r: i32) -> () { + c_comment!(("psubd xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + write_xmm128( + r, + destination.u32_0[0usize].wrapping_sub(source.u32_0[0usize]) as i32, + destination.u32_0[1usize].wrapping_sub(source.u32_0[1usize]) as i32, + destination.u32_0[2usize].wrapping_sub(source.u32_0[2usize]) as i32, + destination.u32_0[3usize].wrapping_sub(source.u32_0[3usize]) as i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FFA_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FFA(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FFA_mem(mut addr: i32, mut r: i32) -> () { + instr_660FFA(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FFB(mut source: reg64, mut r: i32) -> () { + c_comment!(("psubq mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + destination.u64_0[0usize] = destination.u64_0[0usize].wrapping_sub(source.u64_0[0usize]); + write_mmx_reg64(r, destination); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FFB_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FFB(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FFB_mem(mut addr: i32, mut r: i32) -> () { + instr_0FFB(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FFB(mut source: reg128, mut r: i32) -> () { + c_comment!(("psubq xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + destination.u64_0[0usize] = destination.u64_0[0usize].wrapping_sub(source.u64_0[0usize]); + destination.u64_0[1usize] = destination.u64_0[1usize].wrapping_sub(source.u64_0[1usize]); + write_xmm_reg128(r, destination); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FFB_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FFB(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FFB_mem(mut addr: i32, mut r: i32) -> () { + instr_660FFB(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FFC(mut source: reg64, mut r: i32) -> () { + c_comment!(("paddb mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut result: reg64 = reg64 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + }; + let mut i: u32 = 0i32 as u32; + while i < 8i32 as u32 { + result.u8_0[i as usize] = + (destination.u8_0[i as usize] as i32 + source.u8_0[i as usize] as i32 & 255i32) as u8; + i = i.wrapping_add(1) + } + write_mmx_reg64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FFC_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FFC(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FFC_mem(mut addr: i32, mut r: i32) -> () { + instr_0FFC(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FFC(mut source: reg128, mut r: i32) -> () { + c_comment!(("paddb xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + }; + let mut i: u32 = 0i32 as u32; + while i < 16i32 as u32 { + result.u8_0[i as usize] = + (destination.u8_0[i as usize] as i32 + source.u8_0[i as usize] as i32 & 255i32) as u8; + i = i.wrapping_add(1) + } + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FFC_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FFC(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FFC_mem(mut addr: i32, mut r: i32) -> () { + instr_660FFC(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FFD(mut source: reg64, mut r: i32) -> () { + c_comment!(("paddw mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut word0: i32 = + (destination.u32_0[0usize].wrapping_add(source.u32_0[0usize]) & 65535i32 as u32) as i32; + let mut word1: i32 = destination.u16_0[1usize] as i32 + source.u16_0[1usize] as i32 & 65535i32; + let mut low: i32 = word0 | word1 << 16i32; + let mut word2: i32 = + (destination.u32_0[1usize].wrapping_add(source.u32_0[1usize]) & 65535i32 as u32) as i32; + let mut word3: i32 = destination.u16_0[3usize] as i32 + source.u16_0[3usize] as i32 & 65535i32; + let mut high: i32 = word2 | word3 << 16i32; + write_mmx64(r, low, high); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FFD_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FFD(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FFD_mem(mut addr: i32, mut r: i32) -> () { + instr_0FFD(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FFD(mut source: reg128, mut r: i32) -> () { + c_comment!(("paddw xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + }; + let mut i: u32 = 0i32 as u32; + while i < 8i32 as u32 { + result.u16_0[i as usize] = (destination.u16_0[i as usize] as i32 + + source.u16_0[i as usize] as i32 + & 65535i32) as u16; + i = i.wrapping_add(1) + } + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FFD_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FFD(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FFD_mem(mut addr: i32, mut r: i32) -> () { + instr_660FFD(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FFE(mut source: reg64, mut r: i32) -> () { + c_comment!(("paddd mm, mm/m64")); + let mut destination: reg64 = read_mmx64s(r); + let mut low: i32 = destination.u32_0[0usize].wrapping_add(source.u32_0[0usize]) as i32; + let mut high: i32 = destination.u32_0[1usize].wrapping_add(source.u32_0[1usize]) as i32; + write_mmx64(r, low, high); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FFE_reg(mut r1: i32, mut r2: i32) -> () { + instr_0FFE(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FFE_mem(mut addr: i32, mut r: i32) -> () { + instr_0FFE(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FFE(mut source: reg128, mut r: i32) -> () { + c_comment!(("paddd xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut dword0: i32 = destination.u32_0[0usize].wrapping_add(source.u32_0[0usize]) as i32; + let mut dword1: i32 = destination.u32_0[1usize].wrapping_add(source.u32_0[1usize]) as i32; + let mut dword2: i32 = destination.u32_0[2usize].wrapping_add(source.u32_0[2usize]) as i32; + let mut dword3: i32 = destination.u32_0[3usize].wrapping_add(source.u32_0[3usize]) as i32; + write_xmm128(r, dword0, dword1, dword2, dword3); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FFE_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FFE(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FFE_mem(mut addr: i32, mut r: i32) -> () { + instr_660FFE(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FFF() -> () { + c_comment!(("Windows 98")); + dbg_log_c!(("#ud: 0F FF")); + trigger_ud(); +} +#[no_mangle] +pub static mut CPU_LOG_VERBOSE: bool = unsafe { 0 != 0i32 }; +#[no_mangle] +pub unsafe extern "C" fn instr_F30F16() -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F19_reg(mut r1: i32, mut r2: i32) -> () {} +#[no_mangle] +pub unsafe extern "C" fn instr_0F19_mem(mut addr: i32, mut r: i32) -> () {} +#[no_mangle] +pub unsafe extern "C" fn instr_0F1C_reg(mut r1: i32, mut r2: i32) -> () {} +#[no_mangle] +pub unsafe extern "C" fn instr_0F1C_mem(mut addr: i32, mut r: i32) -> () {} +#[no_mangle] +pub unsafe extern "C" fn instr_0F1D_reg(mut r1: i32, mut r2: i32) -> () {} +#[no_mangle] +pub unsafe extern "C" fn instr_0F1D_mem(mut addr: i32, mut r: i32) -> () {} +#[no_mangle] +pub unsafe extern "C" fn instr_0F1E_reg(mut r1: i32, mut r2: i32) -> () {} +#[no_mangle] +pub unsafe extern "C" fn instr_0F1E_mem(mut addr: i32, mut r: i32) -> () {} +#[no_mangle] +pub unsafe extern "C" fn instr_0F2A(mut source: reg64, mut r: i32) -> () { + c_comment!(("cvtpi2ps xmm, mm/m64")); + c_comment!((("XXX: The non-memory variant causes a transition from x87 FPU to MMX technology operation"))); + c_comment!(("Note: Casts here can fail")); + let mut result: reg64 = reg64 { + f32_0: [source.i32_0[0usize] as f32, source.i32_0[1usize] as f32], + }; + write_xmm64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F2A_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F2A(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F2A_mem(mut addr: i32, mut r: i32) -> () { + instr_0F2A(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F2A(mut source: reg64, mut r: i32) -> () { + c_comment!(("cvtpi2pd xmm, xmm/m64")); + c_comment!((("XXX: The non-memory variant causes a transition from x87 FPU to MMX technology operation"))); + c_comment!(("These casts can\'t fail")); + let mut result: reg128 = reg128 { + f64_0: [source.i32_0[0usize] as f64, source.i32_0[1usize] as f64], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F2A_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F2A(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F2A_mem(mut addr: i32, mut r: i32) -> () { + instr_660F2A(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F2A(mut source: i32, mut r: i32) -> () { + c_comment!(("cvtsi2sd xmm, r32/m32")); + c_comment!(("This cast can\'t fail")); + let mut result: reg64 = reg64 { + f64_0: [source as f64], + }; + write_xmm64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F2A_reg(mut r1: i32, mut r2: i32) -> () { + instr_F20F2A(read_reg32(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F2A_mem(mut addr: i32, mut r: i32) -> () { + instr_F20F2A(safe_read32s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F2A(mut source: i32, mut r: i32) -> () { + c_comment!(("cvtsi2ss xmm, r/m32")); + c_comment!(("Note: This cast can fail")); + let mut result: f32 = source as f32; + write_xmm_f32(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F2A_reg(mut r1: i32, mut r2: i32) -> () { + instr_F30F2A(read_reg32(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F2A_mem(mut addr: i32, mut r: i32) -> () { + instr_F30F2A(safe_read32s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F2D(mut source: reg64, mut r: i32) -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F2D_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F2D(read_mmx64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F2D_mem(mut addr: i32, mut r: i32) -> () { + instr_0F2D(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F2D(mut source: reg128, mut r: i32) -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_660F2D_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F2D(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F2D_mem(mut addr: i32, mut r: i32) -> () { + instr_660F2D(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F2D(mut source: reg64, mut r: i32) -> () { + c_comment!(("cvtsd2si r32, xmm/m64")); + write_reg32(r, sse_convert_f64_to_i32(source.f64_0[0usize])); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F2D_reg(mut r1: i32, mut r2: i32) -> () { + instr_F20F2D(read_xmm64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F2D_mem(mut addr: i32, mut r: i32) -> () { + instr_F20F2D(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F2D(mut source: f32, mut r: i32) -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_F30F2D_reg(mut r1: i32, mut r2: i32) -> () { + instr_F30F2D(read_xmm_f32(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F2D_mem(mut addr: i32, mut r: i32) -> () { + instr_F30F2D(fpu_load_m32(addr) as f32, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F51(mut source: reg128, mut r: i32) -> () { + c_comment!(("sqrtps xmm, xmm/mem128")); + let mut result: reg128 = reg128 { + f32_0: [ + sqrtf(source.f32_0[0usize]), + sqrtf(source.f32_0[1usize]), + sqrtf(source.f32_0[2usize]), + sqrtf(source.f32_0[3usize]), + ], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F51_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F51(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F51_mem(mut addr: i32, mut r: i32) -> () { + instr_0F51(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F51(mut source: reg128, mut r: i32) -> () { + c_comment!(("sqrtpd xmm, xmm/mem128")); + let mut result: reg128 = reg128 { + f64_0: [sqrt(source.f64_0[0usize]), sqrt(source.f64_0[1usize])], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F51_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F51(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F51_mem(mut addr: i32, mut r: i32) -> () { + instr_660F51(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F51(mut source: reg64, mut r: i32) -> () { + c_comment!(("sqrtsd xmm, xmm/mem64")); + let mut result: reg64 = reg64 { + f64_0: [sqrt(source.f64_0[0usize])], + }; + write_xmm64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F51_reg(mut r1: i32, mut r2: i32) -> () { + instr_F20F51(read_xmm64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F51_mem(mut addr: i32, mut r: i32) -> () { + instr_F20F51(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F51(mut source: f32, mut r: i32) -> () { + c_comment!(("sqrtss xmm, xmm/mem32")); + write_xmm_f32(r, sqrtf(source)); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F51_reg(mut r1: i32, mut r2: i32) -> () { + instr_F30F51(read_xmm_f32(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F51_mem(mut addr: i32, mut r: i32) -> () { + instr_F30F51(fpu_load_m32(addr) as f32, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F52() -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F53(mut source: reg128, mut r: i32) -> () { + c_comment!(("rcpps xmm, xmm/m128")); + let mut result: reg128 = reg128 { + f32_0: [ + 1i32 as f32 / source.f32_0[0usize], + 1i32 as f32 / source.f32_0[1usize], + 1i32 as f32 / source.f32_0[2usize], + 1i32 as f32 / source.f32_0[3usize], + ], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F53_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F53(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F53_mem(mut addr: i32, mut r: i32) -> () { + instr_0F53(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F53(mut source: f32, mut r: i32) -> () { + c_comment!(("rcpss xmm, xmm/m32")); + write_xmm_f32(r, 1i32 as f32 / source); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F53_reg(mut r1: i32, mut r2: i32) -> () { + instr_F30F53(read_xmm_f32(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F53_mem(mut addr: i32, mut r: i32) -> () { + instr_F30F53(fpu_load_m32(addr) as f32, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F58(mut source: reg128, mut r: i32) -> () { + c_comment!(("addps xmm, xmm/mem128")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + f32_0: [ + source.f32_0[0usize] + destination.f32_0[0usize], + source.f32_0[1usize] + destination.f32_0[1usize], + source.f32_0[2usize] + destination.f32_0[2usize], + source.f32_0[3usize] + destination.f32_0[3usize], + ], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F58_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F58(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F58_mem(mut addr: i32, mut r: i32) -> () { + instr_0F58(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F58(mut source: reg128, mut r: i32) -> () { + c_comment!(("addpd xmm, xmm/mem128")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + f64_0: [ + source.f64_0[0usize] + destination.f64_0[0usize], + source.f64_0[1usize] + destination.f64_0[1usize], + ], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F58_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F58(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F58_mem(mut addr: i32, mut r: i32) -> () { + instr_660F58(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F58(mut source: reg64, mut r: i32) -> () { + c_comment!(("addsd xmm, xmm/mem64")); + let mut destination: reg64 = read_xmm64s(r); + let mut result: reg64 = reg64 { + f64_0: [source.f64_0[0usize] + destination.f64_0[0usize]], + }; + write_xmm64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F58_reg(mut r1: i32, mut r2: i32) -> () { + instr_F20F58(read_xmm64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F58_mem(mut addr: i32, mut r: i32) -> () { + instr_F20F58(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F58(mut source: f32, mut r: i32) -> () { + c_comment!(("addss xmm, xmm/mem32")); + let mut destination: f32 = read_xmm_f32(r); + let mut result: f32 = source + destination; + write_xmm_f32(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F58_reg(mut r1: i32, mut r2: i32) -> () { + instr_F30F58(read_xmm_f32(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F58_mem(mut addr: i32, mut r: i32) -> () { + instr_F30F58(fpu_load_m32(addr) as f32, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F59(mut source: reg128, mut r: i32) -> () { + c_comment!(("mulps xmm, xmm/mem128")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + f32_0: [ + source.f32_0[0usize] * destination.f32_0[0usize], + source.f32_0[1usize] * destination.f32_0[1usize], + source.f32_0[2usize] * destination.f32_0[2usize], + source.f32_0[3usize] * destination.f32_0[3usize], + ], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F59_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F59(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F59_mem(mut addr: i32, mut r: i32) -> () { + instr_0F59(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F59(mut source: reg128, mut r: i32) -> () { + c_comment!(("mulpd xmm, xmm/mem128")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + f64_0: [ + source.f64_0[0usize] * destination.f64_0[0usize], + source.f64_0[1usize] * destination.f64_0[1usize], + ], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F59_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F59(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F59_mem(mut addr: i32, mut r: i32) -> () { + instr_660F59(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F59(mut source: reg64, mut r: i32) -> () { + c_comment!(("mulsd xmm, xmm/mem64")); + let mut destination: reg64 = read_xmm64s(r); + let mut result: reg64 = reg64 { + f64_0: [source.f64_0[0usize] * destination.f64_0[0usize]], + }; + write_xmm64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F59_reg(mut r1: i32, mut r2: i32) -> () { + instr_F20F59(read_xmm64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F59_mem(mut addr: i32, mut r: i32) -> () { + instr_F20F59(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F59(mut source: f32, mut r: i32) -> () { + c_comment!(("mulss xmm, xmm/mem32")); + let mut destination: f32 = read_xmm_f32(r); + let mut result: f32 = source * destination; + write_xmm_f32(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F59_reg(mut r1: i32, mut r2: i32) -> () { + instr_F30F59(read_xmm_f32(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F59_mem(mut addr: i32, mut r: i32) -> () { + instr_F30F59(fpu_load_m32(addr) as f32, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F5A() -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F5B() -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe extern "C" fn instr_0F5C(mut source: reg128, mut r: i32) -> () { + c_comment!(("subps xmm, xmm/mem128")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + f32_0: [ + destination.f32_0[0usize] - source.f32_0[0usize], + destination.f32_0[1usize] - source.f32_0[1usize], + destination.f32_0[2usize] - source.f32_0[2usize], + destination.f32_0[3usize] - source.f32_0[3usize], + ], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F5C_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F5C(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F5C_mem(mut addr: i32, mut r: i32) -> () { + instr_0F5C(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F5C(mut source: reg128, mut r: i32) -> () { + c_comment!(("subpd xmm, xmm/mem128")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + f64_0: [ + destination.f64_0[0usize] - source.f64_0[0usize], + destination.f64_0[1usize] - source.f64_0[1usize], + ], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F5C_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F5C(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F5C_mem(mut addr: i32, mut r: i32) -> () { + instr_660F5C(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F5C(mut source: reg64, mut r: i32) -> () { + c_comment!(("subsd xmm, xmm/mem64")); + let mut destination: reg64 = read_xmm64s(r); + let mut result: reg64 = reg64 { + f64_0: [destination.f64_0[0usize] - source.f64_0[0usize]], + }; + write_xmm64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F5C_reg(mut r1: i32, mut r2: i32) -> () { + instr_F20F5C(read_xmm64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F5C_mem(mut addr: i32, mut r: i32) -> () { + instr_F20F5C(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F5C(mut source: f32, mut r: i32) -> () { + c_comment!(("subss xmm, xmm/mem32")); + let mut destination: f32 = read_xmm_f32(r); + let mut result: f32 = destination - source; + write_xmm_f32(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F5C_reg(mut r1: i32, mut r2: i32) -> () { + instr_F30F5C(read_xmm_f32(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F5C_mem(mut addr: i32, mut r: i32) -> () { + instr_F30F5C(fpu_load_m32(addr) as f32, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F5D(mut source: reg128, mut r: i32) -> () { + c_comment!(("minps xmm, xmm/mem128")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + f32_0: [ + sse_min( + destination.f32_0[0usize] as f64, + source.f32_0[0usize] as f64, + ) as f32, + sse_min( + destination.f32_0[1usize] as f64, + source.f32_0[1usize] as f64, + ) as f32, + sse_min( + destination.f32_0[2usize] as f64, + source.f32_0[2usize] as f64, + ) as f32, + sse_min( + destination.f32_0[3usize] as f64, + source.f32_0[3usize] as f64, + ) as f32, + ], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F5D_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F5D(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F5D_mem(mut addr: i32, mut r: i32) -> () { + instr_0F5D(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F5D(mut source: reg128, mut r: i32) -> () { + c_comment!(("minpd xmm, xmm/mem128")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + f64_0: [ + sse_min(destination.f64_0[0usize], source.f64_0[0usize]), + sse_min(destination.f64_0[1usize], source.f64_0[1usize]), + ], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F5D_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F5D(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F5D_mem(mut addr: i32, mut r: i32) -> () { + instr_660F5D(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F5D(mut source: reg64, mut r: i32) -> () { + c_comment!(("minsd xmm, xmm/mem64")); + let mut destination: reg64 = read_xmm64s(r); + let mut result: reg64 = reg64 { + f64_0: [sse_min(destination.f64_0[0usize], source.f64_0[0usize])], + }; + write_xmm64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F5D_reg(mut r1: i32, mut r2: i32) -> () { + instr_F20F5D(read_xmm64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F5D_mem(mut addr: i32, mut r: i32) -> () { + instr_F20F5D(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F5D(mut source: f32, mut r: i32) -> () { + c_comment!(("minss xmm, xmm/mem32")); + let mut destination: f32 = read_xmm_f32(r); + let mut result: f32 = sse_min(destination as f64, source as f64) as f32; + write_xmm_f32(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F5D_reg(mut r1: i32, mut r2: i32) -> () { + instr_F30F5D(read_xmm_f32(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F5D_mem(mut addr: i32, mut r: i32) -> () { + instr_F30F5D(fpu_load_m32(addr) as f32, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F5E(mut source: reg128, mut r: i32) -> () { + c_comment!(("divps xmm, xmm/mem128")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + f32_0: [ + destination.f32_0[0usize] / source.f32_0[0usize], + destination.f32_0[1usize] / source.f32_0[1usize], + destination.f32_0[2usize] / source.f32_0[2usize], + destination.f32_0[3usize] / source.f32_0[3usize], + ], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F5E_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F5E(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F5E_mem(mut addr: i32, mut r: i32) -> () { + instr_0F5E(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F5E(mut source: reg128, mut r: i32) -> () { + c_comment!(("divpd xmm, xmm/mem128")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + f64_0: [ + destination.f64_0[0usize] / source.f64_0[0usize], + destination.f64_0[1usize] / source.f64_0[1usize], + ], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F5E_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F5E(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F5E_mem(mut addr: i32, mut r: i32) -> () { + instr_660F5E(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F5E(mut source: reg64, mut r: i32) -> () { + c_comment!(("divsd xmm, xmm/mem64")); + let mut destination: reg64 = read_xmm64s(r); + let mut result: reg64 = reg64 { + f64_0: [destination.f64_0[0usize] / source.f64_0[0usize]], + }; + write_xmm64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F5E_reg(mut r1: i32, mut r2: i32) -> () { + instr_F20F5E(read_xmm64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F5E_mem(mut addr: i32, mut r: i32) -> () { + instr_F20F5E(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F5E(mut source: f32, mut r: i32) -> () { + c_comment!(("divss xmm, xmm/mem32")); + let mut destination: f32 = read_xmm_f32(r); + let mut result: f32 = destination / source; + write_xmm_f32(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F5E_reg(mut r1: i32, mut r2: i32) -> () { + instr_F30F5E(read_xmm_f32(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F5E_mem(mut addr: i32, mut r: i32) -> () { + instr_F30F5E(fpu_load_m32(addr) as f32, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F5F(mut source: reg128, mut r: i32) -> () { + c_comment!(("maxps xmm, xmm/mem128")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + f32_0: [ + sse_max( + destination.f32_0[0usize] as f64, + source.f32_0[0usize] as f64, + ) as f32, + sse_max( + destination.f32_0[1usize] as f64, + source.f32_0[1usize] as f64, + ) as f32, + sse_max( + destination.f32_0[2usize] as f64, + source.f32_0[2usize] as f64, + ) as f32, + sse_max( + destination.f32_0[3usize] as f64, + source.f32_0[3usize] as f64, + ) as f32, + ], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F5F_reg(mut r1: i32, mut r2: i32) -> () { + instr_0F5F(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0F5F_mem(mut addr: i32, mut r: i32) -> () { + instr_0F5F(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F5F(mut source: reg128, mut r: i32) -> () { + c_comment!(("maxpd xmm, xmm/mem128")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + f64_0: [ + sse_max(destination.f64_0[0usize], source.f64_0[0usize]), + sse_max(destination.f64_0[1usize], source.f64_0[1usize]), + ], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F5F_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F5F(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660F5F_mem(mut addr: i32, mut r: i32) -> () { + instr_660F5F(safe_read128s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F5F(mut source: reg64, mut r: i32) -> () { + c_comment!(("maxsd xmm, xmm/mem64")); + let mut destination: reg64 = read_xmm64s(r); + let mut result: reg64 = reg64 { + f64_0: [sse_max(destination.f64_0[0usize], source.f64_0[0usize])], + }; + write_xmm64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F5F_reg(mut r1: i32, mut r2: i32) -> () { + instr_F20F5F(read_xmm64s(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20F5F_mem(mut addr: i32, mut r: i32) -> () { + instr_F20F5F(safe_read64s(addr), r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F5F(mut source: f32, mut r: i32) -> () { + c_comment!(("maxss xmm, xmm/mem32")); + let mut destination: f32 = read_xmm_f32(r); + let mut result: f32 = sse_max(destination as f64, source as f64) as f32; + write_xmm_f32(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F5F_reg(mut r1: i32, mut r2: i32) -> () { + instr_F30F5F(read_xmm_f32(r1), r2); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30F5F_mem(mut addr: i32, mut r: i32) -> () { + instr_F30F5F(fpu_load_m32(addr) as f32, r); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FC2(mut source: reg128, mut r: i32, mut imm8: i32) -> () { + c_comment!(("cmpps xmm, xmm/m128")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + i32_0: [ + if 0 != sse_comparison( + imm8, + destination.f32_0[0usize] as f64, + source.f32_0[0usize] as f64, + ) as i32 + { + -1i32 + } + else { + 0i32 + }, + if 0 != sse_comparison( + imm8, + destination.f32_0[1usize] as f64, + source.f32_0[1usize] as f64, + ) as i32 + { + -1i32 + } + else { + 0i32 + }, + if 0 != sse_comparison( + imm8, + destination.f32_0[2usize] as f64, + source.f32_0[2usize] as f64, + ) as i32 + { + -1i32 + } + else { + 0i32 + }, + if 0 != sse_comparison( + imm8, + destination.f32_0[3usize] as f64, + source.f32_0[3usize] as f64, + ) as i32 + { + -1i32 + } + else { + 0i32 + }, + ], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { + instr_0FC2(read_xmm128s(r1), r2, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_0FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { + instr_0FC2(safe_read128s(addr), r, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FC2(mut source: reg128, mut r: i32, mut imm8: i32) -> () { + c_comment!(("cmppd xmm, xmm/m128")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + i64_0: [ + (if 0 != sse_comparison(imm8, destination.f64_0[0usize], source.f64_0[0usize]) as i32 { + -1i32 + } + else { + 0i32 + }) as i64, + (if 0 != sse_comparison(imm8, destination.f64_0[1usize], source.f64_0[1usize]) as i32 { + -1i32 + } + else { + 0i32 + }) as i64, + ], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { + instr_660FC2(read_xmm128s(r1), r2, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_660FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { + instr_660FC2(safe_read128s(addr), r, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20FC2(mut source: reg64, mut r: i32, mut imm8: i32) -> () { + c_comment!(("cmpsd xmm, xmm/m64")); + let mut destination: reg64 = read_xmm64s(r); + let mut result: reg64 = reg64 { + i64_0: [(if 0 + != sse_comparison(imm8, destination.f64_0[0usize], source.f64_0[0usize]) as i32 + { + -1i32 + } + else { + 0i32 + }) as i64], + }; + write_xmm64(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { + instr_F20FC2(read_xmm64s(r1), r2, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F20FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { + instr_F20FC2(safe_read64s(addr), r, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30FC2(mut source: f32, mut r: i32, mut imm8: i32) -> () { + c_comment!(("cmpss xmm, xmm/m32")); + let mut destination: f32 = read_xmm_f32(r); + let mut result: i32 = if 0 != sse_comparison(imm8, destination as f64, source as f64) as i32 { + -1i32 + } + else { + 0i32 + }; + write_xmm32(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { + instr_F30FC2(read_xmm_f32(r1), r2, imm); +} +#[no_mangle] +pub unsafe extern "C" fn instr_F30FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { + instr_F30FC2(fpu_load_m32(addr) as f32, r, imm); +} diff --git a/src/rust/cpu2/memory.rs b/src/rust/cpu2/memory.rs new file mode 100644 index 00000000..0a282897 --- /dev/null +++ b/src/rust/cpu2/memory.rs @@ -0,0 +1,1072 @@ +#![allow +( dead_code , mutable_transmutes , non_camel_case_types , non_snake_case , +non_upper_case_globals , unused_mut )] +#![feature ( extern_types , libc )] + +extern "C" { + + #[no_mangle] + static FLAG_CARRY: i32; + #[no_mangle] + static FLAG_PARITY: i32; + #[no_mangle] + static FLAG_ADJUST: i32; + #[no_mangle] + static FLAG_ZERO: i32; + #[no_mangle] + static FLAG_SIGN: i32; + #[no_mangle] + static FLAG_TRAP: i32; + #[no_mangle] + static FLAG_INTERRUPT: i32; + #[no_mangle] + static FLAG_DIRECTION: i32; + #[no_mangle] + static FLAG_OVERFLOW: i32; + #[no_mangle] + static FLAG_IOPL: i32; + #[no_mangle] + static FLAG_NT: i32; + #[no_mangle] + static FLAG_RF: i32; + #[no_mangle] + static FLAG_VM: i32; + #[no_mangle] + static FLAG_AC: i32; + #[no_mangle] + static FLAG_VIF: i32; + #[no_mangle] + static FLAG_VIP: i32; + #[no_mangle] + static FLAG_ID: i32; + #[no_mangle] + static FLAGS_DEFAULT: i32; + #[no_mangle] + static FLAGS_MASK: i32; + #[no_mangle] + static FLAGS_ALL: i32; + #[no_mangle] + static OPSIZE_8: i32; + #[no_mangle] + static OPSIZE_16: i32; + #[no_mangle] + static OPSIZE_32: i32; + #[no_mangle] + static EAX: i32; + #[no_mangle] + static ECX: i32; + #[no_mangle] + static EDX: i32; + #[no_mangle] + static EBX: i32; + #[no_mangle] + static ESP: i32; + #[no_mangle] + static EBP: i32; + #[no_mangle] + static ESI: i32; + #[no_mangle] + static EDI: i32; + #[no_mangle] + static AX: i32; + #[no_mangle] + static CX: i32; + #[no_mangle] + static DX: i32; + #[no_mangle] + static BX: i32; + #[no_mangle] + static SP: i32; + #[no_mangle] + static BP: i32; + #[no_mangle] + static SI: i32; + #[no_mangle] + static DI: i32; + #[no_mangle] + static AL: i32; + #[no_mangle] + static CL: i32; + #[no_mangle] + static DL: i32; + #[no_mangle] + static BL: i32; + #[no_mangle] + static AH: i32; + #[no_mangle] + static CH: i32; + #[no_mangle] + static DH: i32; + #[no_mangle] + static BH: i32; + #[no_mangle] + static ES: i32; + #[no_mangle] + static CS: i32; + #[no_mangle] + static SS: i32; + #[no_mangle] + static DS: i32; + #[no_mangle] + static FS: i32; + #[no_mangle] + static GS: i32; + #[no_mangle] + static TR: i32; + #[no_mangle] + static LDTR: i32; + #[no_mangle] + static PAGE_TABLE_PRESENT_MASK: i32; + #[no_mangle] + static PAGE_TABLE_RW_MASK: i32; + #[no_mangle] + static PAGE_TABLE_USER_MASK: i32; + #[no_mangle] + static PAGE_TABLE_ACCESSED_MASK: i32; + #[no_mangle] + static PAGE_TABLE_DIRTY_MASK: i32; + #[no_mangle] + static PAGE_TABLE_PSE_MASK: i32; + #[no_mangle] + static PAGE_TABLE_GLOBAL_MASK: i32; + #[no_mangle] + static MMAP_BLOCK_BITS: i32; + #[no_mangle] + static MMAP_BLOCK_SIZE: i32; + #[no_mangle] + static CR0_PE: i32; + #[no_mangle] + static CR0_MP: i32; + #[no_mangle] + static CR0_EM: i32; + #[no_mangle] + static CR0_TS: i32; + #[no_mangle] + static CR0_ET: i32; + #[no_mangle] + static CR0_WP: i32; + #[no_mangle] + static CR0_NW: i32; + #[no_mangle] + static CR0_CD: i32; + #[no_mangle] + static CR0_PG: i32; + #[no_mangle] + static CR4_VME: i32; + #[no_mangle] + static CR4_PVI: i32; + #[no_mangle] + static CR4_TSD: i32; + #[no_mangle] + static CR4_PSE: i32; + #[no_mangle] + static CR4_DE: i32; + #[no_mangle] + static CR4_PAE: i32; + #[no_mangle] + static CR4_PGE: i32; + #[no_mangle] + static IA32_SYSENTER_CS: i32; + #[no_mangle] + static IA32_SYSENTER_ESP: i32; + #[no_mangle] + static IA32_SYSENTER_EIP: i32; + #[no_mangle] + static IA32_TIME_STAMP_COUNTER: i32; + #[no_mangle] + static IA32_PLATFORM_ID: i32; + #[no_mangle] + static IA32_APIC_BASE_MSR: i32; + #[no_mangle] + static IA32_BIOS_SIGN_ID: i32; + #[no_mangle] + static MSR_PLATFORM_INFO: i32; + #[no_mangle] + static MSR_MISC_FEATURE_ENABLES: i32; + #[no_mangle] + static IA32_MISC_ENABLE: i32; + #[no_mangle] + static IA32_RTIT_CTL: i32; + #[no_mangle] + static MSR_SMI_COUNT: i32; + #[no_mangle] + static IA32_MCG_CAP: i32; + #[no_mangle] + static IA32_KERNEL_GS_BASE: i32; + #[no_mangle] + static MSR_PKG_C2_RESIDENCY: i32; + #[no_mangle] + static IA32_APIC_BASE_BSP: i32; + #[no_mangle] + static IA32_APIC_BASE_EXTD: i32; + #[no_mangle] + static IA32_APIC_BASE_EN: i32; + #[no_mangle] + static APIC_ADDRESS: i32; + #[no_mangle] + static SEG_PREFIX_NONE: i32; + #[no_mangle] + static SEG_PREFIX_ZERO: i32; + #[no_mangle] + static PREFIX_MASK_REP: i32; + #[no_mangle] + static PREFIX_REPZ: i32; + #[no_mangle] + static PREFIX_REPNZ: i32; + #[no_mangle] + static PREFIX_MASK_SEGMENT: i32; + #[no_mangle] + static PREFIX_MASK_OPSIZE: i32; + #[no_mangle] + static PREFIX_MASK_ADDRSIZE: i32; + #[no_mangle] + static PREFIX_F2: i32; + #[no_mangle] + static PREFIX_F3: i32; + #[no_mangle] + static PREFIX_66: i32; + #[no_mangle] + static LOG_CPU: i32; + #[no_mangle] + static A20_MASK: i32; + #[no_mangle] + static A20_MASK16: i32; + #[no_mangle] + static A20_MASK32: i32; + #[no_mangle] + static MXCSR_MASK: i32; + #[no_mangle] + fn __fpclassifyl(_: f64) -> i32; + + #[no_mangle] + static reg8: *mut u8; + #[no_mangle] + static reg16: *mut u16; + #[no_mangle] + static reg8s: *mut i8; + #[no_mangle] + static reg16s: *mut i16; + #[no_mangle] + static reg32s: *mut i32; + #[no_mangle] + static last_op1: *mut i32; + #[no_mangle] + static last_op2: *mut i32; + #[no_mangle] + static last_op_size: *mut i32; + #[no_mangle] + static last_add_result: *mut i32; + #[no_mangle] + static last_result: *mut i32; + #[no_mangle] + static flags_changed: *mut i32; + #[no_mangle] + static flags: *mut i32; + #[no_mangle] + static page_fault: *mut bool; + #[no_mangle] + static a20_enabled: *mut bool; + #[no_mangle] + static instruction_pointer: *mut i32; + #[no_mangle] + static previous_ip: *mut i32; + #[no_mangle] + static idtr_size: *mut i32; + #[no_mangle] + static idtr_offset: *mut i32; + #[no_mangle] + static gdtr_size: *mut i32; + #[no_mangle] + static gdtr_offset: *mut i32; + #[no_mangle] + static cr: *mut i32; + #[no_mangle] + static cpl: *mut u8; + #[no_mangle] + static in_hlt: *mut bool; + #[no_mangle] + static last_virt_eip: *mut i32; + #[no_mangle] + static eip_phys: *mut i32; + #[no_mangle] + static last_virt_esp: *mut i32; + #[no_mangle] + static esp_phys: *mut i32; + #[no_mangle] + static sysenter_cs: *mut i32; + #[no_mangle] + static sysenter_esp: *mut i32; + #[no_mangle] + static sysenter_eip: *mut i32; + #[no_mangle] + static prefixes: *mut u8; + #[no_mangle] + static timestamp_counter: *mut u32; + #[no_mangle] + static sreg: *mut u16; + #[no_mangle] + static dreg: *mut i32; + #[no_mangle] + static fw_value: *mut i32; + #[no_mangle] + static segment_is_null: *mut bool; + #[no_mangle] + static segment_offsets: *mut i32; + #[no_mangle] + static segment_limits: *mut u32; + #[no_mangle] + static protected_mode: *mut bool; + #[no_mangle] + static is_32: *mut bool; + #[no_mangle] + static stack_size_32: *mut bool; + #[no_mangle] + static memory_size: *mut u32; + #[no_mangle] + static fpu_stack_empty: *mut i32; + #[no_mangle] + static mxcsr: *mut i32; + #[no_mangle] + static reg_xmm: *mut reg128; + #[no_mangle] + static current_tsc: *mut u64; + #[no_mangle] + static fpu_st: *mut f64; + #[no_mangle] + static fpu_st8: *mut u8; + #[no_mangle] + static fpu_st32: *mut i32; + #[no_mangle] + static fpu_stack_ptr: *mut u32; + #[no_mangle] + static fpu_control_word: *mut i32; + #[no_mangle] + static fpu_status_word: *mut i32; + #[no_mangle] + static fpu_opcode: *mut i32; + #[no_mangle] + static fpu_ip: *mut i32; + #[no_mangle] + static fpu_ip_selector: *mut i32; + #[no_mangle] + static fpu_dp: *mut i32; + #[no_mangle] + static fpu_dp_selector: *mut i32; + #[no_mangle] + static reg_mmx: *mut reg64; + #[no_mangle] + static opstats_buffer: *mut u32; + #[no_mangle] + static opstats_buffer_0f: *mut u32; + #[no_mangle] + static tlb_data: *mut i32; + #[no_mangle] + static mut mem8: *mut u8; + #[no_mangle] + static mut mem16: *mut u16; + #[no_mangle] + static mut mem32s: *mut i32; + #[no_mangle] + static mut jit_block_boundary: bool; + #[no_mangle] + static VALID_TLB_ENTRY_MAX: i32; + #[no_mangle] + static mut valid_tlb_entries: [i32; 10000]; + #[no_mangle] + static mut valid_tlb_entries_count: i32; + #[no_mangle] + static TLB_VALID: i32; + #[no_mangle] + static TLB_READONLY: i32; + #[no_mangle] + static TLB_NO_USER: i32; + #[no_mangle] + static TLB_IN_MAPPED_RANGE: i32; + #[no_mangle] + static TLB_GLOBAL: i32; + #[no_mangle] + static TLB_HAS_CODE: i32; + #[no_mangle] + static CPU_EXCEPTION_DE: i32; + #[no_mangle] + static CPU_EXCEPTION_DB: i32; + #[no_mangle] + static CPU_EXCEPTION_NMI: i32; + #[no_mangle] + static CPU_EXCEPTION_BP: i32; + #[no_mangle] + static CPU_EXCEPTION_OF: i32; + #[no_mangle] + static CPU_EXCEPTION_BR: i32; + #[no_mangle] + static CPU_EXCEPTION_UD: i32; + #[no_mangle] + static CPU_EXCEPTION_NM: i32; + #[no_mangle] + static CPU_EXCEPTION_DF: i32; + #[no_mangle] + static CPU_EXCEPTION_TS: i32; + #[no_mangle] + static CPU_EXCEPTION_NP: i32; + #[no_mangle] + static CPU_EXCEPTION_SS: i32; + #[no_mangle] + static CPU_EXCEPTION_GP: i32; + #[no_mangle] + static CPU_EXCEPTION_PF: i32; + #[no_mangle] + static CPU_EXCEPTION_MF: i32; + #[no_mangle] + static CPU_EXCEPTION_AC: i32; + #[no_mangle] + static CPU_EXCEPTION_MC: i32; + #[no_mangle] + static CPU_EXCEPTION_XM: i32; + #[no_mangle] + static CPU_EXCEPTION_VE: i32; + #[no_mangle] + fn mmap_read16(_: u32) -> i32; + #[no_mangle] + fn mmap_read32(_: u32) -> i32; + #[no_mangle] + fn mmap_read8(_: u32) -> i32; + #[no_mangle] + fn mmap_write128(_: u32, _: i32, _: i32, _: i32, _: i32) -> (); + #[no_mangle] + fn mmap_write16(_: u32, _: i32) -> (); + #[no_mangle] + fn mmap_write32(_: u32, _: i32) -> (); + #[no_mangle] + fn mmap_write8(_: u32, _: i32) -> (); + #[no_mangle] + fn jit_dirty_cache_single(phys_addr: u32) -> (); + #[no_mangle] + fn jit_dirty_cache_small(phys_start_addr: u32, phys_end_addr: u32) -> (); + #[no_mangle] + static mut profiler_stat_arr: [profiler_stat; 37]; +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed { + __f: f64, + __i: u64, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union reg128 { + i8_0: [i8; 16], + i16_0: [i16; 8], + i32_0: [i32; 4], + i64_0: [i64; 2], + u8_0: [u8; 16], + u16_0: [u16; 8], + u32_0: [u32; 4], + u64_0: [u64; 2], + f32_0: [f32; 4], + f64_0: [f64; 2], +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub struct profiler_stat { + pub count: i32, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_0 { + __f: f32, + __i: u32, +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union reg64 { + i8_0: [i8; 8], + i16_0: [i16; 4], + i32_0: [i32; 2], + i64_0: [i64; 1], + u8_0: [u8; 8], + u16_0: [u16; 4], + u32_0: [u32; 2], + u64_0: [u64; 1], + f32_0: [f32; 2], + f64_0: [f64; 1], +} +unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { + let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { + let mut __u: unnamed = unnamed { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x >= __y) as i32; +} +#[no_mangle] +pub unsafe extern "C" fn in_mapped_range(mut addr: u32) -> bool { + return addr >= 655360i32 as u32 && addr < 786432i32 as u32 || addr >= *memory_size; +} +#[no_mangle] +pub unsafe extern "C" fn read8(mut addr: u32) -> i32 { + if 0 != USE_A20 as i32 && 0 != *a20_enabled as i32 { + addr &= A20_MASK as u32 + } + if in_mapped_range(addr) { + return mmap_read8(addr); + } + else { + return *mem8.offset(addr as isize) as i32; + }; +} +#[no_mangle] +pub static mut USE_A20: bool = unsafe { 0 != 0i32 }; +#[no_mangle] +pub unsafe extern "C" fn read16(mut addr: u32) -> i32 { + if 0 != USE_A20 as i32 && !*a20_enabled { + addr &= A20_MASK as u32 + } + if in_mapped_range(addr) { + return mmap_read16(addr); + } + else { + return *(mem8.offset(addr as isize) as *mut u16) as i32; + }; +} +#[no_mangle] +pub unsafe extern "C" fn read_aligned16(mut addr: u32) -> i32 { + dbg_assert!(addr < 2147483648u32); + if 0 != USE_A20 as i32 && !*a20_enabled { + addr &= A20_MASK16 as u32 + } + if in_mapped_range(addr << 1i32) { + return mmap_read16(addr << 1i32); + } + else { + return *mem16.offset(addr as isize) as i32; + }; +} +#[no_mangle] +pub unsafe extern "C" fn read32s(mut addr: u32) -> i32 { + if 0 != USE_A20 as i32 && 0 != *a20_enabled as i32 { + addr &= A20_MASK as u32 + } + if in_mapped_range(addr) { + return mmap_read32(addr); + } + else { + return *(mem8.offset(addr as isize) as *mut i32); + }; +} +#[no_mangle] +pub unsafe extern "C" fn read64s(mut addr: u32) -> i64 { + if 0 != USE_A20 as i32 && 0 != *a20_enabled as i32 { + addr &= A20_MASK as u32 + } + if in_mapped_range(addr) { + return mmap_read32(addr) as i64 + | (mmap_read32(addr.wrapping_add(4i32 as u32)) as i64) << 32i32; + } + else { + return *(mem8.offset(addr as isize) as *mut i64); + }; +} +#[no_mangle] +pub unsafe extern "C" fn read_aligned32(mut addr: u32) -> i32 { + dbg_assert!(addr < 1073741824i32 as u32); + if 0 != USE_A20 as i32 && !*a20_enabled { + addr &= A20_MASK32 as u32 + } + if in_mapped_range(addr << 2i32) { + return mmap_read32(addr << 2i32); + } + else { + return *mem32s.offset(addr as isize); + }; +} +#[no_mangle] +pub unsafe extern "C" fn read128(mut addr: u32) -> reg128 { + if 0 != USE_A20 as i32 && 0 != *a20_enabled as i32 { + addr &= A20_MASK as u32 + } + let mut value: reg128 = reg128 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + }; + if in_mapped_range(addr) { + value.i32_0[0usize] = mmap_read32(addr); + value.i32_0[1usize] = mmap_read32(addr.wrapping_add(4i32 as u32)); + value.i32_0[2usize] = mmap_read32(addr.wrapping_add(8i32 as u32)); + value.i32_0[3usize] = mmap_read32(addr.wrapping_add(12i32 as u32)) + } + else { + value.i64_0[0usize] = *(mem8.offset(addr as isize) as *mut i64); + value.i64_0[1usize] = *(mem8.offset(addr as isize).offset(8isize) as *mut i64) + } + return value; +} +#[no_mangle] +pub unsafe extern "C" fn write8(mut addr: u32, mut value: i32) -> () { + if 0 != USE_A20 as i32 && !*a20_enabled { + addr &= A20_MASK as u32 + } + if in_mapped_range(addr) { + mmap_write8(addr, value); + } + else { + jit_dirty_cache_single(addr); + *mem8.offset(addr as isize) = value as u8 + }; +} +#[no_mangle] +pub unsafe extern "C" fn write16(mut addr: u32, mut value: i32) -> () { + if 0 != USE_A20 as i32 && !*a20_enabled { + addr &= A20_MASK as u32 + } + if in_mapped_range(addr) { + mmap_write16(addr, value); + } + else { + jit_dirty_cache_small(addr, addr.wrapping_add(2i32 as u32)); + *(mem8.offset(addr as isize) as *mut u16) = value as u16 + }; +} +#[no_mangle] +pub unsafe extern "C" fn write_aligned16(mut addr: u32, mut value: u32) -> () { + dbg_assert!(addr < 2147483648u32); + if 0 != USE_A20 as i32 && !*a20_enabled { + addr &= A20_MASK16 as u32 + } + let mut phys_addr: u32 = addr << 1i32; + if in_mapped_range(phys_addr) { + mmap_write16(phys_addr, value as i32); + } + else { + jit_dirty_cache_small(phys_addr, phys_addr.wrapping_add(2i32 as u32)); + *mem16.offset(addr as isize) = value as u16 + }; +} +#[no_mangle] +pub unsafe extern "C" fn write32(mut addr: u32, mut value: i32) -> () { + if 0 != USE_A20 as i32 && !*a20_enabled { + addr &= A20_MASK as u32 + } + if in_mapped_range(addr) { + mmap_write32(addr, value); + } + else { + jit_dirty_cache_small(addr, addr.wrapping_add(4i32 as u32)); + *(mem8.offset(addr as isize) as *mut i32) = value + }; +} +#[no_mangle] +pub unsafe extern "C" fn write_aligned32(mut addr: u32, mut value: i32) -> () { + dbg_assert!(addr < 1073741824i32 as u32); + if 0 != USE_A20 as i32 && !*a20_enabled { + addr &= A20_MASK32 as u32 + } + let mut phys_addr: u32 = addr << 2i32; + if in_mapped_range(phys_addr) { + mmap_write32(phys_addr, value); + } + else { + jit_dirty_cache_small(phys_addr, phys_addr.wrapping_add(4i32 as u32)); + *mem32s.offset(addr as isize) = value + }; +} +#[no_mangle] +pub unsafe extern "C" fn write64(mut addr: u32, mut value: i64) -> () { + if 0 != USE_A20 as i32 && !*a20_enabled { + addr &= A20_MASK as u32 + } + if in_mapped_range(addr) { + mmap_write32( + addr.wrapping_add(0i32 as u32), + (value & 4294967295u32 as i64) as i32, + ); + mmap_write32(addr.wrapping_add(4i32 as u32), (value >> 32i32) as i32); + } + else { + jit_dirty_cache_small(addr, addr.wrapping_add(8i32 as u32)); + *(mem8.offset(addr as isize) as *mut i64) = value + }; +} +#[no_mangle] +pub unsafe extern "C" fn write128(mut addr: u32, mut value: reg128) -> () { + if 0 != USE_A20 as i32 && !*a20_enabled { + addr &= A20_MASK as u32 + } + if in_mapped_range(addr) { + mmap_write128( + addr, + value.i32_0[0usize], + value.i32_0[1usize], + value.i32_0[2usize], + value.i32_0[3usize], + ); + } + else { + jit_dirty_cache_small(addr, addr.wrapping_add(16i32 as u32)); + *(mem8.offset(addr as isize) as *mut i64) = value.i64_0[0usize]; + *(mem8.offset(addr as isize).offset(8isize) as *mut i64) = value.i64_0[1usize] + }; +} diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs new file mode 100644 index 00000000..4a6bef51 --- /dev/null +++ b/src/rust/cpu2/misc_instr.rs @@ -0,0 +1,1343 @@ +#![allow +( dead_code , mutable_transmutes , non_camel_case_types , non_snake_case , +non_upper_case_globals , unused_mut )] +#![feature ( extern_types , libc )] + +extern "C" { + + #[no_mangle] + fn __fpclassifyl(_: f64) -> i32; + + #[no_mangle] + static FLAG_CARRY: i32; + #[no_mangle] + static FLAG_PARITY: i32; + #[no_mangle] + static FLAG_ADJUST: i32; + #[no_mangle] + static FLAG_ZERO: i32; + #[no_mangle] + static FLAG_SIGN: i32; + #[no_mangle] + static FLAG_TRAP: i32; + #[no_mangle] + static FLAG_INTERRUPT: i32; + #[no_mangle] + static FLAG_DIRECTION: i32; + #[no_mangle] + static FLAG_OVERFLOW: i32; + #[no_mangle] + static FLAG_IOPL: i32; + #[no_mangle] + static FLAG_NT: i32; + #[no_mangle] + static FLAG_RF: i32; + #[no_mangle] + static FLAG_VM: i32; + #[no_mangle] + static FLAG_AC: i32; + #[no_mangle] + static FLAG_VIF: i32; + #[no_mangle] + static FLAG_VIP: i32; + #[no_mangle] + static FLAG_ID: i32; + #[no_mangle] + static FLAGS_DEFAULT: i32; + #[no_mangle] + static FLAGS_MASK: i32; + #[no_mangle] + static FLAGS_ALL: i32; + #[no_mangle] + static OPSIZE_8: i32; + #[no_mangle] + static OPSIZE_16: i32; + #[no_mangle] + static OPSIZE_32: i32; + #[no_mangle] + static EAX: i32; + #[no_mangle] + static ECX: i32; + #[no_mangle] + static EDX: i32; + #[no_mangle] + static EBX: i32; + #[no_mangle] + static ESP: i32; + #[no_mangle] + static EBP: i32; + #[no_mangle] + static ESI: i32; + #[no_mangle] + static EDI: i32; + #[no_mangle] + static AX: i32; + #[no_mangle] + static CX: i32; + #[no_mangle] + static DX: i32; + #[no_mangle] + static BX: i32; + #[no_mangle] + static SP: i32; + #[no_mangle] + static BP: i32; + #[no_mangle] + static SI: i32; + #[no_mangle] + static DI: i32; + #[no_mangle] + static AL: i32; + #[no_mangle] + static CL: i32; + #[no_mangle] + static DL: i32; + #[no_mangle] + static BL: i32; + #[no_mangle] + static AH: i32; + #[no_mangle] + static CH: i32; + #[no_mangle] + static DH: i32; + #[no_mangle] + static BH: i32; + #[no_mangle] + static ES: i32; + #[no_mangle] + static CS: i32; + #[no_mangle] + static SS: i32; + #[no_mangle] + static DS: i32; + #[no_mangle] + static FS: i32; + #[no_mangle] + static GS: i32; + #[no_mangle] + static TR: i32; + #[no_mangle] + static LDTR: i32; + #[no_mangle] + static PAGE_TABLE_PRESENT_MASK: i32; + #[no_mangle] + static PAGE_TABLE_RW_MASK: i32; + #[no_mangle] + static PAGE_TABLE_USER_MASK: i32; + #[no_mangle] + static PAGE_TABLE_ACCESSED_MASK: i32; + #[no_mangle] + static PAGE_TABLE_DIRTY_MASK: i32; + #[no_mangle] + static PAGE_TABLE_PSE_MASK: i32; + #[no_mangle] + static PAGE_TABLE_GLOBAL_MASK: i32; + #[no_mangle] + static MMAP_BLOCK_BITS: i32; + #[no_mangle] + static MMAP_BLOCK_SIZE: i32; + #[no_mangle] + static CR0_PE: i32; + #[no_mangle] + static CR0_MP: i32; + #[no_mangle] + static CR0_EM: i32; + #[no_mangle] + static CR0_TS: i32; + #[no_mangle] + static CR0_ET: i32; + #[no_mangle] + static CR0_WP: i32; + #[no_mangle] + static CR0_NW: i32; + #[no_mangle] + static CR0_CD: i32; + #[no_mangle] + static CR0_PG: i32; + #[no_mangle] + static CR4_VME: i32; + #[no_mangle] + static CR4_PVI: i32; + #[no_mangle] + static CR4_TSD: i32; + #[no_mangle] + static CR4_PSE: i32; + #[no_mangle] + static CR4_DE: i32; + #[no_mangle] + static CR4_PAE: i32; + #[no_mangle] + static CR4_PGE: i32; + #[no_mangle] + static IA32_SYSENTER_CS: i32; + #[no_mangle] + static IA32_SYSENTER_ESP: i32; + #[no_mangle] + static IA32_SYSENTER_EIP: i32; + #[no_mangle] + static IA32_TIME_STAMP_COUNTER: i32; + #[no_mangle] + static IA32_PLATFORM_ID: i32; + #[no_mangle] + static IA32_APIC_BASE_MSR: i32; + #[no_mangle] + static IA32_BIOS_SIGN_ID: i32; + #[no_mangle] + static MSR_PLATFORM_INFO: i32; + #[no_mangle] + static MSR_MISC_FEATURE_ENABLES: i32; + #[no_mangle] + static IA32_MISC_ENABLE: i32; + #[no_mangle] + static IA32_RTIT_CTL: i32; + #[no_mangle] + static MSR_SMI_COUNT: i32; + #[no_mangle] + static IA32_MCG_CAP: i32; + #[no_mangle] + static IA32_KERNEL_GS_BASE: i32; + #[no_mangle] + static MSR_PKG_C2_RESIDENCY: i32; + #[no_mangle] + static IA32_APIC_BASE_BSP: i32; + #[no_mangle] + static IA32_APIC_BASE_EXTD: i32; + #[no_mangle] + static IA32_APIC_BASE_EN: i32; + #[no_mangle] + static APIC_ADDRESS: i32; + #[no_mangle] + static SEG_PREFIX_NONE: i32; + #[no_mangle] + static SEG_PREFIX_ZERO: i32; + #[no_mangle] + static PREFIX_MASK_REP: i32; + #[no_mangle] + static PREFIX_REPZ: i32; + #[no_mangle] + static PREFIX_REPNZ: i32; + #[no_mangle] + static PREFIX_MASK_SEGMENT: i32; + #[no_mangle] + static PREFIX_MASK_OPSIZE: i32; + #[no_mangle] + static PREFIX_MASK_ADDRSIZE: i32; + #[no_mangle] + static PREFIX_F2: i32; + #[no_mangle] + static PREFIX_F3: i32; + #[no_mangle] + static PREFIX_66: i32; + #[no_mangle] + static LOG_CPU: i32; + #[no_mangle] + static A20_MASK: i32; + #[no_mangle] + static A20_MASK16: i32; + #[no_mangle] + static A20_MASK32: i32; + #[no_mangle] + static MXCSR_MASK: i32; + #[no_mangle] + fn dbg_log(m: *const i8) -> (); + #[no_mangle] + fn c_comment(m: *const i8) -> (); + #[no_mangle] + static mut mem8: *mut u8; + #[no_mangle] + static mut mem16: *mut u16; + #[no_mangle] + static mut mem32s: *mut i32; + #[no_mangle] + static mut jit_block_boundary: bool; + #[no_mangle] + static VALID_TLB_ENTRY_MAX: i32; + #[no_mangle] + static mut valid_tlb_entries: [i32; 10000]; + #[no_mangle] + static mut valid_tlb_entries_count: i32; + #[no_mangle] + static TLB_VALID: i32; + #[no_mangle] + static TLB_READONLY: i32; + #[no_mangle] + static TLB_NO_USER: i32; + #[no_mangle] + static TLB_IN_MAPPED_RANGE: i32; + #[no_mangle] + static TLB_GLOBAL: i32; + #[no_mangle] + static TLB_HAS_CODE: i32; + #[no_mangle] + static CPU_EXCEPTION_DE: i32; + #[no_mangle] + static CPU_EXCEPTION_DB: i32; + #[no_mangle] + static CPU_EXCEPTION_NMI: i32; + #[no_mangle] + static CPU_EXCEPTION_BP: i32; + #[no_mangle] + static CPU_EXCEPTION_OF: i32; + #[no_mangle] + static CPU_EXCEPTION_BR: i32; + #[no_mangle] + static CPU_EXCEPTION_UD: i32; + #[no_mangle] + static CPU_EXCEPTION_NM: i32; + #[no_mangle] + static CPU_EXCEPTION_DF: i32; + #[no_mangle] + static CPU_EXCEPTION_TS: i32; + #[no_mangle] + static CPU_EXCEPTION_NP: i32; + #[no_mangle] + static CPU_EXCEPTION_SS: i32; + #[no_mangle] + static CPU_EXCEPTION_GP: i32; + #[no_mangle] + static CPU_EXCEPTION_PF: i32; + #[no_mangle] + static CPU_EXCEPTION_MF: i32; + #[no_mangle] + static CPU_EXCEPTION_AC: i32; + #[no_mangle] + static CPU_EXCEPTION_MC: i32; + #[no_mangle] + static CPU_EXCEPTION_XM: i32; + #[no_mangle] + static CPU_EXCEPTION_VE: i32; + #[no_mangle] + fn translate_address_read(address: i32) -> u32; + #[no_mangle] + fn writable_or_pagefault(addr: i32, size: i32) -> (); + #[no_mangle] + fn get_seg_cs() -> i32; + #[no_mangle] + fn get_seg_ss() -> i32; + #[no_mangle] + fn trigger_gp_non_raising(code: i32) -> (); + #[no_mangle] + fn safe_read8(addr: i32) -> i32; + #[no_mangle] + fn safe_read16(addr: i32) -> i32; + #[no_mangle] + fn safe_read32s(address: i32) -> i32; + #[no_mangle] + fn safe_write8(addr: i32, value: i32) -> (); + #[no_mangle] + fn safe_write16(addr: i32, value: i32) -> (); + #[no_mangle] + fn safe_write32(address: i32, value: i32) -> (); + #[no_mangle] + fn safe_write128(addr: i32, value: reg128) -> (); + #[no_mangle] + fn write_reg8(index: i32, value: i32) -> (); + #[no_mangle] + fn write_reg16(index: i32, value: i32) -> (); + #[no_mangle] + fn write_reg32(index: i32, value: i32) -> (); + #[no_mangle] + fn get_reg_asize(reg: i32) -> i32; + #[no_mangle] + fn decr_ecx_asize() -> i32; + #[no_mangle] + static M_LOG2E: f64; + #[no_mangle] + static M_LN2: f64; + #[no_mangle] + static M_LN10: f64; + #[no_mangle] + static M_PI: f64; + #[no_mangle] + static FPU_C0: i32; + #[no_mangle] + static FPU_C1: i32; + #[no_mangle] + static FPU_C2: i32; + #[no_mangle] + static FPU_C3: i32; + #[no_mangle] + static FPU_RESULT_FLAGS: i32; + #[no_mangle] + static FPU_STACK_TOP: i32; + #[no_mangle] + fn fpu_load_m80(addr: u32) -> f64; + #[no_mangle] + fn fpu_load_status_word() -> i32; + #[no_mangle] + fn fpu_set_status_word(sw: i32) -> (); + #[no_mangle] + fn fpu_store_m80(addr: u32, n: f64) -> (); + #[no_mangle] + static reg8: *mut u8; + #[no_mangle] + static reg16: *mut u16; + #[no_mangle] + static reg8s: *mut i8; + #[no_mangle] + static reg16s: *mut i16; + #[no_mangle] + static reg32s: *mut i32; + #[no_mangle] + static last_op1: *mut i32; + #[no_mangle] + static last_op2: *mut i32; + #[no_mangle] + static last_op_size: *mut i32; + #[no_mangle] + static last_add_result: *mut i32; + #[no_mangle] + static last_result: *mut i32; + #[no_mangle] + static flags_changed: *mut i32; + #[no_mangle] + static flags: *mut i32; + #[no_mangle] + static page_fault: *mut bool; + #[no_mangle] + static a20_enabled: *mut bool; + #[no_mangle] + static instruction_pointer: *mut i32; + #[no_mangle] + static previous_ip: *mut i32; + #[no_mangle] + static idtr_size: *mut i32; + #[no_mangle] + static idtr_offset: *mut i32; + #[no_mangle] + static gdtr_size: *mut i32; + #[no_mangle] + static gdtr_offset: *mut i32; + #[no_mangle] + static cr: *mut i32; + #[no_mangle] + static cpl: *mut u8; + #[no_mangle] + static in_hlt: *mut bool; + #[no_mangle] + static last_virt_eip: *mut i32; + #[no_mangle] + static eip_phys: *mut i32; + #[no_mangle] + static last_virt_esp: *mut i32; + #[no_mangle] + static esp_phys: *mut i32; + #[no_mangle] + static sysenter_cs: *mut i32; + #[no_mangle] + static sysenter_esp: *mut i32; + #[no_mangle] + static sysenter_eip: *mut i32; + #[no_mangle] + static prefixes: *mut u8; + #[no_mangle] + static timestamp_counter: *mut u32; + #[no_mangle] + static sreg: *mut u16; + #[no_mangle] + static dreg: *mut i32; + #[no_mangle] + static fw_value: *mut i32; + #[no_mangle] + static segment_is_null: *mut bool; + #[no_mangle] + static segment_offsets: *mut i32; + #[no_mangle] + static segment_limits: *mut u32; + #[no_mangle] + static protected_mode: *mut bool; + #[no_mangle] + static is_32: *mut bool; + #[no_mangle] + static stack_size_32: *mut bool; + #[no_mangle] + static memory_size: *mut u32; + #[no_mangle] + static fpu_stack_empty: *mut i32; + #[no_mangle] + static mxcsr: *mut i32; + #[no_mangle] + static reg_xmm: *mut reg128; + #[no_mangle] + static current_tsc: *mut u64; + #[no_mangle] + static fpu_st: *mut f64; + #[no_mangle] + static fpu_st8: *mut u8; + #[no_mangle] + static fpu_st32: *mut i32; + #[no_mangle] + static fpu_stack_ptr: *mut u32; + #[no_mangle] + static fpu_control_word: *mut i32; + #[no_mangle] + static fpu_status_word: *mut i32; + #[no_mangle] + static fpu_opcode: *mut i32; + #[no_mangle] + static fpu_ip: *mut i32; + #[no_mangle] + static fpu_ip_selector: *mut i32; + #[no_mangle] + static fpu_dp: *mut i32; + #[no_mangle] + static fpu_dp_selector: *mut i32; + #[no_mangle] + static reg_mmx: *mut reg64; + #[no_mangle] + static opstats_buffer: *mut u32; + #[no_mangle] + static opstats_buffer_0f: *mut u32; + #[no_mangle] + static tlb_data: *mut i32; +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed { + __f: f64, + __i: u64, +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union reg64 { + i8_0: [i8; 8], + i16_0: [i16; 4], + i32_0: [i32; 2], + i64_0: [i64; 1], + u8_0: [u8; 8], + u16_0: [u16; 4], + u32_0: [u32; 2], + u64_0: [u64; 1], + f32_0: [f32; 2], + f64_0: [f64; 1], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_0 { + __f: f32, + __i: u32, +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union reg128 { + i8_0: [i8; 16], + i16_0: [i16; 8], + i32_0: [i32; 4], + i64_0: [i64; 2], + u8_0: [u8; 16], + u16_0: [u16; 8], + u32_0: [u32; 4], + u64_0: [u64; 2], + f32_0: [f32; 4], + f64_0: [f64; 2], +} + +unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { + let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { + let mut __u: unnamed = unnamed { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x >= __y) as i32; +} +#[no_mangle] +pub unsafe extern "C" fn getcf() -> bool { + if 0 != *flags_changed & 1i32 { + return 0 + != (*last_op1 ^ (*last_op1 ^ *last_op2) & (*last_op2 ^ *last_add_result)) + >> *last_op_size + & 1i32; + } + else { + return 0 != *flags & 1i32; + }; +} +#[no_mangle] +pub unsafe extern "C" fn getpf() -> bool { + if 0 != *flags_changed & FLAG_PARITY { + c_comment!(("inverted lookup table")); + return 0 + != 38505i32 << 2i32 >> ((*last_result ^ *last_result >> 4i32) & 15i32) & FLAG_PARITY; + } + else { + return 0 != *flags & FLAG_PARITY; + }; +} +#[no_mangle] +pub unsafe extern "C" fn getaf() -> bool { + if 0 != *flags_changed & FLAG_ADJUST { + return 0 != (*last_op1 ^ *last_op2 ^ *last_add_result) & FLAG_ADJUST; + } + else { + return 0 != *flags & FLAG_ADJUST; + }; +} +#[no_mangle] +pub unsafe extern "C" fn getzf() -> bool { + if 0 != *flags_changed & FLAG_ZERO { + return 0 != (!*last_result & *last_result - 1i32) >> *last_op_size & 1i32; + } + else { + return 0 != *flags & FLAG_ZERO; + }; +} +#[no_mangle] +pub unsafe extern "C" fn getsf() -> bool { + if 0 != *flags_changed & FLAG_SIGN { + return 0 != *last_result >> *last_op_size & 1i32; + } + else { + return 0 != *flags & FLAG_SIGN; + }; +} +#[no_mangle] +pub unsafe extern "C" fn getof() -> bool { + if 0 != *flags_changed & FLAG_OVERFLOW { + return 0 + != ((*last_op1 ^ *last_add_result) & (*last_op2 ^ *last_add_result)) >> *last_op_size + & 1i32; + } + else { + return 0 != *flags & FLAG_OVERFLOW; + }; +} +#[no_mangle] +pub unsafe extern "C" fn test_o() -> bool { return getof(); } +#[no_mangle] +pub unsafe extern "C" fn test_b() -> bool { return getcf(); } +#[no_mangle] +pub unsafe extern "C" fn test_z() -> bool { return getzf(); } +#[no_mangle] +pub unsafe extern "C" fn test_s() -> bool { return getsf(); } +#[no_mangle] +pub unsafe extern "C" fn test_p() -> bool { return getpf(); } +#[no_mangle] +pub unsafe extern "C" fn test_be() -> bool { return 0 != getcf() as i32 || 0 != getzf() as i32; } +#[no_mangle] +pub unsafe extern "C" fn test_l() -> bool { return getsf() as i32 != getof() as i32; } +#[no_mangle] +pub unsafe extern "C" fn test_le() -> bool { + return 0 != getzf() as i32 || getsf() as i32 != getof() as i32; +} +#[no_mangle] +pub unsafe extern "C" fn test_no() -> bool { return !test_o(); } +#[no_mangle] +pub unsafe extern "C" fn test_nb() -> bool { return !test_b(); } +#[no_mangle] +pub unsafe extern "C" fn test_nz() -> bool { return !test_z(); } +#[no_mangle] +pub unsafe extern "C" fn test_ns() -> bool { return !test_s(); } +#[no_mangle] +pub unsafe extern "C" fn test_np() -> bool { return !test_p(); } +#[no_mangle] +pub unsafe extern "C" fn test_nbe() -> bool { return !test_be(); } +#[no_mangle] +pub unsafe extern "C" fn test_nl() -> bool { return !test_l(); } +#[no_mangle] +pub unsafe extern "C" fn test_nle() -> bool { return !test_le(); } +#[no_mangle] +pub unsafe extern "C" fn jmp_rel16(mut rel16: i32) -> () { + let mut cs_offset: i32 = get_seg_cs(); + c_comment!(("limit ip to 16 bit")); + *instruction_pointer = cs_offset + (*instruction_pointer - cs_offset + rel16 & 65535i32); +} +#[no_mangle] +pub unsafe extern "C" fn jmpcc16(mut condition: bool, mut imm16: i32) -> () { + if condition { + jmp_rel16(imm16); + }; +} +#[no_mangle] +pub unsafe extern "C" fn jmpcc32(mut condition: bool, mut imm32: i32) -> () { + if condition { + *instruction_pointer += imm32 + }; +} +#[no_mangle] +pub unsafe extern "C" fn loope16(mut imm8s: i32) -> () { + jmpcc16(0 != decr_ecx_asize() && 0 != getzf() as i32, imm8s); +} +#[no_mangle] +pub unsafe extern "C" fn loopne16(mut imm8s: i32) -> () { + jmpcc16(0 != decr_ecx_asize() && !getzf(), imm8s); +} +#[no_mangle] +pub unsafe extern "C" fn loop16(mut imm8s: i32) -> () { jmpcc16(0 != decr_ecx_asize(), imm8s); } +#[no_mangle] +pub unsafe extern "C" fn jcxz16(mut imm8s: i32) -> () { + jmpcc16(get_reg_asize(ECX) == 0i32, imm8s); +} +#[no_mangle] +pub unsafe extern "C" fn loope32(mut imm8s: i32) -> () { + jmpcc32(0 != decr_ecx_asize() && 0 != getzf() as i32, imm8s); +} +#[no_mangle] +pub unsafe extern "C" fn loopne32(mut imm8s: i32) -> () { + jmpcc32(0 != decr_ecx_asize() && !getzf(), imm8s); +} +#[no_mangle] +pub unsafe extern "C" fn loop32(mut imm8s: i32) -> () { jmpcc32(0 != decr_ecx_asize(), imm8s); } +#[no_mangle] +pub unsafe extern "C" fn jcxz32(mut imm8s: i32) -> () { + jmpcc32(get_reg_asize(ECX) == 0i32, imm8s); +} +#[no_mangle] +pub unsafe extern "C" fn cmovcc16(mut condition: bool, mut value: i32, mut r: i32) -> () { + if condition { + write_reg16(r, value); + }; +} +#[no_mangle] +pub unsafe extern "C" fn cmovcc32(mut condition: bool, mut value: i32, mut r: i32) -> () { + if condition { + write_reg32(r, value); + }; +} +#[no_mangle] +pub unsafe extern "C" fn get_stack_pointer(mut offset: i32) -> i32 { + if *stack_size_32 { + return get_seg_ss() + *reg32s.offset(ESP as isize) + offset; + } + else { + return get_seg_ss() + (*reg16.offset(SP as isize) as i32 + offset & 65535i32); + }; +} +#[no_mangle] +pub unsafe extern "C" fn adjust_stack_reg(mut adjustment: i32) -> () { + if *stack_size_32 { + let ref mut fresh0 = *reg32s.offset(ESP as isize); + *fresh0 += adjustment + } + else { + let ref mut fresh1 = *reg16.offset(SP as isize); + *fresh1 = (*fresh1 as i32 + adjustment) as u16 + }; +} +#[no_mangle] +pub unsafe extern "C" fn push16_ss16(mut imm16: i32) -> () { + let mut sp: i32 = get_seg_ss() + (*reg16.offset(SP as isize) as i32 - 2i32 & 65535i32); + safe_write16(sp, imm16); + let ref mut fresh2 = *reg16.offset(SP as isize); + *fresh2 = (*fresh2 as i32 + -2i32) as u16; +} +#[no_mangle] +pub unsafe extern "C" fn push16_ss32(mut imm16: i32) -> () { + let mut sp: i32 = get_seg_ss() + *reg32s.offset(ESP as isize) - 2i32; + safe_write16(sp, imm16); + let ref mut fresh3 = *reg32s.offset(ESP as isize); + *fresh3 += -2i32; +} +#[no_mangle] +pub unsafe extern "C" fn push16_ss16_mem(mut addr: i32) -> () { push16_ss16(safe_read16(addr)); } +#[no_mangle] +pub unsafe extern "C" fn push16_ss32_mem(mut addr: i32) -> () { push16_ss32(safe_read16(addr)); } +#[no_mangle] +pub unsafe extern "C" fn push16(mut imm16: i32) -> () { + if *stack_size_32 { + push16_ss32(imm16); + } + else { + push16_ss16(imm16); + }; +} +#[no_mangle] +pub unsafe extern "C" fn push32_ss16(mut imm32: i32) -> () { + let mut new_sp: i32 = *reg16.offset(SP as isize) as i32 - 4i32 & 65535i32; + safe_write32(get_seg_ss() + new_sp, imm32); + *reg16.offset(SP as isize) = new_sp as u16; +} +#[no_mangle] +pub unsafe extern "C" fn push32_ss32(mut imm32: i32) -> () { + let mut new_esp: i32 = *reg32s.offset(ESP as isize) - 4i32; + safe_write32(get_seg_ss() + new_esp, imm32); + *reg32s.offset(ESP as isize) = new_esp; +} +#[no_mangle] +pub unsafe extern "C" fn push32_ss16_mem(mut addr: i32) -> () { push32_ss16(safe_read32s(addr)); } +#[no_mangle] +pub unsafe extern "C" fn push32_ss32_mem(mut addr: i32) -> () { push32_ss32(safe_read32s(addr)); } +#[no_mangle] +pub unsafe extern "C" fn push32(mut imm32: i32) -> () { + if *stack_size_32 { + push32_ss32(imm32); + } + else { + push32_ss16(imm32); + }; +} +#[no_mangle] +pub unsafe extern "C" fn pop16() -> i32 { + if *stack_size_32 { + return pop16_ss32(); + } + else { + return pop16_ss16(); + }; +} +#[no_mangle] +pub unsafe extern "C" fn pop16_ss16() -> i32 { + let mut sp: i32 = get_seg_ss() + *reg16.offset(SP as isize) as i32; + let mut result: i32 = safe_read16(sp); + let ref mut fresh4 = *reg16.offset(SP as isize); + *fresh4 = (*fresh4 as i32 + 2i32) as u16; + return result; +} +#[no_mangle] +pub unsafe extern "C" fn pop16_ss32() -> i32 { + let mut esp: i32 = get_seg_ss() + *reg32s.offset(ESP as isize); + let mut result: i32 = safe_read16(esp); + let ref mut fresh5 = *reg32s.offset(ESP as isize); + *fresh5 += 2i32; + return result; +} +#[no_mangle] +pub unsafe extern "C" fn pop32s() -> i32 { + if *stack_size_32 { + return pop32s_ss32(); + } + else { + return pop32s_ss16(); + }; +} +#[no_mangle] +pub unsafe extern "C" fn pop32s_ss16() -> i32 { + let mut sp: i32 = *reg16.offset(SP as isize) as i32; + let mut result: i32 = safe_read32s(get_seg_ss() + sp); + *reg16.offset(SP as isize) = (sp + 4i32) as u16; + return result; +} +#[no_mangle] +pub unsafe extern "C" fn pop32s_ss32() -> i32 { + let mut esp: i32 = *reg32s.offset(ESP as isize); + let mut result: i32 = safe_read32s(get_seg_ss() + esp); + *reg32s.offset(ESP as isize) = esp + 4i32; + return result; +} +#[no_mangle] +pub unsafe extern "C" fn pusha16() -> () { + let mut temp: u16 = *reg16.offset(SP as isize); + c_comment!(("make sure we don\'t get a pagefault after having")); + c_comment!(("pushed several registers already")); + writable_or_pagefault(get_stack_pointer(-16i32), 16i32); + push16(*reg16.offset(AX as isize) as i32); + push16(*reg16.offset(CX as isize) as i32); + push16(*reg16.offset(DX as isize) as i32); + push16(*reg16.offset(BX as isize) as i32); + push16(temp as i32); + push16(*reg16.offset(BP as isize) as i32); + push16(*reg16.offset(SI as isize) as i32); + push16(*reg16.offset(DI as isize) as i32); +} +#[no_mangle] +pub unsafe extern "C" fn pusha32() -> () { + let mut temp: i32 = *reg32s.offset(ESP as isize); + writable_or_pagefault(get_stack_pointer(-32i32), 32i32); + push32(*reg32s.offset(EAX as isize)); + push32(*reg32s.offset(ECX as isize)); + push32(*reg32s.offset(EDX as isize)); + push32(*reg32s.offset(EBX as isize)); + push32(temp); + push32(*reg32s.offset(EBP as isize)); + push32(*reg32s.offset(ESI as isize)); + push32(*reg32s.offset(EDI as isize)); +} +#[no_mangle] +pub unsafe extern "C" fn setcc_reg(mut condition: bool, mut r: i32) -> () { + write_reg8(r, if 0 != condition as i32 { 1i32 } else { 0i32 }); +} +#[no_mangle] +pub unsafe extern "C" fn setcc_mem(mut condition: bool, mut addr: i32) -> () { + safe_write8(addr, if 0 != condition as i32 { 1i32 } else { 0i32 }); +} +#[no_mangle] +pub unsafe extern "C" fn fxsave(mut addr: u32) -> () { + writable_or_pagefault(addr as i32, 512i32); + safe_write16(addr.wrapping_add(0i32 as u32) as i32, *fpu_control_word); + safe_write16( + addr.wrapping_add(2i32 as u32) as i32, + fpu_load_status_word(), + ); + safe_write8( + addr.wrapping_add(4i32 as u32) as i32, + !*fpu_stack_empty & 255i32, + ); + safe_write16(addr.wrapping_add(6i32 as u32) as i32, *fpu_opcode); + safe_write32(addr.wrapping_add(8i32 as u32) as i32, *fpu_ip); + safe_write16(addr.wrapping_add(12i32 as u32) as i32, *fpu_ip_selector); + safe_write32(addr.wrapping_add(16i32 as u32) as i32, *fpu_dp); + safe_write16(addr.wrapping_add(20i32 as u32) as i32, *fpu_dp_selector); + safe_write32(addr.wrapping_add(24i32 as u32) as i32, *mxcsr); + safe_write32(addr.wrapping_add(28i32 as u32) as i32, MXCSR_MASK); + let mut i: i32 = 0i32; + while i < 8i32 { + fpu_store_m80( + addr.wrapping_add(32i32 as u32) + .wrapping_add((i << 4i32) as u32), + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(i as u32) & 7i32 as u32) as isize), + ); + i += 1 + } + c_comment!(("If the OSFXSR bit in control register CR4 is not set, the FXSAVE")); + c_comment!(("instruction may not save these registers. This behavior is")); + c_comment!(("implementation dependent.")); + let mut i_0: i32 = 0i32; + while i_0 < 8i32 { + safe_write128( + addr.wrapping_add(160i32 as u32) + .wrapping_add((i_0 << 4i32) as u32) as i32, + *reg_xmm.offset(i_0 as isize), + ); + i_0 += 1 + } +} +#[no_mangle] +pub unsafe extern "C" fn fxrstor(mut addr: u32) -> () { + translate_address_read(addr as i32); + translate_address_read(addr.wrapping_add(511i32 as u32) as i32); + let mut new_mxcsr: i32 = safe_read32s(addr.wrapping_add(24i32 as u32) as i32); + if 0 != new_mxcsr & !MXCSR_MASK { + dbg_log_c!(("#gp Invalid mxcsr bits")); + trigger_gp_non_raising(0i32); + return; + } + else { + *fpu_control_word = safe_read16(addr.wrapping_add(0i32 as u32) as i32); + fpu_set_status_word(safe_read16(addr.wrapping_add(2i32 as u32) as i32)); + *fpu_stack_empty = !safe_read8(addr.wrapping_add(4i32 as u32) as i32) & 255i32; + *fpu_opcode = safe_read16(addr.wrapping_add(6i32 as u32) as i32); + *fpu_ip = safe_read32s(addr.wrapping_add(8i32 as u32) as i32); + *fpu_ip = safe_read16(addr.wrapping_add(12i32 as u32) as i32); + *fpu_dp = safe_read32s(addr.wrapping_add(16i32 as u32) as i32); + *fpu_dp_selector = safe_read16(addr.wrapping_add(20i32 as u32) as i32); + *mxcsr = new_mxcsr; + let mut i: i32 = 0i32; + while i < 8i32 { + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(i as u32) & 7i32 as u32) as isize) = + fpu_load_m80( + addr.wrapping_add(32i32 as u32) + .wrapping_add((i << 4i32) as u32), + ); + i += 1 + } + let mut i_0: i32 = 0i32; + while i_0 < 8i32 { + (*reg_xmm.offset(i_0 as isize)).u32_0[0usize] = safe_read32s( + addr.wrapping_add(160i32 as u32) + .wrapping_add((i_0 << 4i32) as u32) + .wrapping_add(0i32 as u32) as i32, + ) as u32; + (*reg_xmm.offset(i_0 as isize)).u32_0[1usize] = safe_read32s( + addr.wrapping_add(160i32 as u32) + .wrapping_add((i_0 << 4i32) as u32) + .wrapping_add(4i32 as u32) as i32, + ) as u32; + (*reg_xmm.offset(i_0 as isize)).u32_0[2usize] = safe_read32s( + addr.wrapping_add(160i32 as u32) + .wrapping_add((i_0 << 4i32) as u32) + .wrapping_add(8i32 as u32) as i32, + ) as u32; + (*reg_xmm.offset(i_0 as isize)).u32_0[3usize] = safe_read32s( + addr.wrapping_add(160i32 as u32) + .wrapping_add((i_0 << 4i32) as u32) + .wrapping_add(12i32 as u32) as i32, + ) as u32; + i_0 += 1 + } + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn xchg8(mut data: i32, mut r8: i32) -> i32 { + let mut tmp: i32 = *reg8.offset(r8 as isize) as i32; + *reg8.offset(r8 as isize) = data as u8; + return tmp; +} +#[no_mangle] +pub unsafe extern "C" fn xchg16(mut data: i32, mut r16: i32) -> i32 { + let mut tmp: i32 = *reg16.offset(r16 as isize) as i32; + *reg16.offset(r16 as isize) = data as u16; + return tmp; +} +#[no_mangle] +pub unsafe extern "C" fn xchg16r(mut r16: i32) -> () { + let mut tmp: i32 = *reg16.offset(AX as isize) as i32; + *reg16.offset(AX as isize) = *reg16.offset(r16 as isize); + *reg16.offset(r16 as isize) = tmp as u16; +} +#[no_mangle] +pub unsafe extern "C" fn xchg32(mut data: i32, mut r32: i32) -> i32 { + let mut tmp: i32 = *reg32s.offset(r32 as isize); + *reg32s.offset(r32 as isize) = data; + return tmp; +} +#[no_mangle] +pub unsafe extern "C" fn xchg32r(mut r32: i32) -> () { + let mut tmp: i32 = *reg32s.offset(EAX as isize); + *reg32s.offset(EAX as isize) = *reg32s.offset(r32 as isize); + *reg32s.offset(r32 as isize) = tmp; +} diff --git a/src/rust/cpu2/modrm.rs b/src/rust/cpu2/modrm.rs new file mode 100644 index 00000000..751e2376 --- /dev/null +++ b/src/rust/cpu2/modrm.rs @@ -0,0 +1,1143 @@ +#![allow +( dead_code , mutable_transmutes , non_camel_case_types , non_snake_case , +non_upper_case_globals , unused_mut )] +#![feature ( extern_types , libc )] + +extern "C" { + + #[no_mangle] + fn __fpclassifyl(_: f64) -> i32; + #[no_mangle] + static FLAG_CARRY: i32; + #[no_mangle] + static FLAG_PARITY: i32; + #[no_mangle] + static FLAG_ADJUST: i32; + #[no_mangle] + static FLAG_ZERO: i32; + #[no_mangle] + static FLAG_SIGN: i32; + #[no_mangle] + static FLAG_TRAP: i32; + #[no_mangle] + static FLAG_INTERRUPT: i32; + #[no_mangle] + static FLAG_DIRECTION: i32; + #[no_mangle] + static FLAG_OVERFLOW: i32; + #[no_mangle] + static FLAG_IOPL: i32; + #[no_mangle] + static FLAG_NT: i32; + #[no_mangle] + static FLAG_RF: i32; + #[no_mangle] + static FLAG_VM: i32; + #[no_mangle] + static FLAG_AC: i32; + #[no_mangle] + static FLAG_VIF: i32; + #[no_mangle] + static FLAG_VIP: i32; + #[no_mangle] + static FLAG_ID: i32; + #[no_mangle] + static FLAGS_DEFAULT: i32; + #[no_mangle] + static FLAGS_MASK: i32; + #[no_mangle] + static FLAGS_ALL: i32; + #[no_mangle] + static OPSIZE_8: i32; + #[no_mangle] + static OPSIZE_16: i32; + #[no_mangle] + static OPSIZE_32: i32; + #[no_mangle] + static EAX: i32; + #[no_mangle] + static ECX: i32; + #[no_mangle] + static EDX: i32; + #[no_mangle] + static EBX: i32; + #[no_mangle] + static ESP: i32; + #[no_mangle] + static EBP: i32; + #[no_mangle] + static ESI: i32; + #[no_mangle] + static EDI: i32; + #[no_mangle] + static AX: i32; + #[no_mangle] + static CX: i32; + #[no_mangle] + static DX: i32; + #[no_mangle] + static BX: i32; + #[no_mangle] + static SP: i32; + #[no_mangle] + static BP: i32; + #[no_mangle] + static SI: i32; + #[no_mangle] + static DI: i32; + #[no_mangle] + static AL: i32; + #[no_mangle] + static CL: i32; + #[no_mangle] + static DL: i32; + #[no_mangle] + static BL: i32; + #[no_mangle] + static AH: i32; + #[no_mangle] + static CH: i32; + #[no_mangle] + static DH: i32; + #[no_mangle] + static BH: i32; + #[no_mangle] + static ES: i32; + #[no_mangle] + static CS: i32; + #[no_mangle] + static SS: i32; + #[no_mangle] + static DS: i32; + #[no_mangle] + static FS: i32; + #[no_mangle] + static GS: i32; + #[no_mangle] + static TR: i32; + #[no_mangle] + static LDTR: i32; + #[no_mangle] + static PAGE_TABLE_PRESENT_MASK: i32; + #[no_mangle] + static PAGE_TABLE_RW_MASK: i32; + #[no_mangle] + static PAGE_TABLE_USER_MASK: i32; + #[no_mangle] + static PAGE_TABLE_ACCESSED_MASK: i32; + #[no_mangle] + static PAGE_TABLE_DIRTY_MASK: i32; + #[no_mangle] + static PAGE_TABLE_PSE_MASK: i32; + #[no_mangle] + static PAGE_TABLE_GLOBAL_MASK: i32; + #[no_mangle] + static MMAP_BLOCK_BITS: i32; + #[no_mangle] + static MMAP_BLOCK_SIZE: i32; + #[no_mangle] + static CR0_PE: i32; + #[no_mangle] + static CR0_MP: i32; + #[no_mangle] + static CR0_EM: i32; + #[no_mangle] + static CR0_TS: i32; + #[no_mangle] + static CR0_ET: i32; + #[no_mangle] + static CR0_WP: i32; + #[no_mangle] + static CR0_NW: i32; + #[no_mangle] + static CR0_CD: i32; + #[no_mangle] + static CR0_PG: i32; + #[no_mangle] + static CR4_VME: i32; + #[no_mangle] + static CR4_PVI: i32; + #[no_mangle] + static CR4_TSD: i32; + #[no_mangle] + static CR4_PSE: i32; + #[no_mangle] + static CR4_DE: i32; + #[no_mangle] + static CR4_PAE: i32; + #[no_mangle] + static CR4_PGE: i32; + #[no_mangle] + static IA32_SYSENTER_CS: i32; + #[no_mangle] + static IA32_SYSENTER_ESP: i32; + #[no_mangle] + static IA32_SYSENTER_EIP: i32; + #[no_mangle] + static IA32_TIME_STAMP_COUNTER: i32; + #[no_mangle] + static IA32_PLATFORM_ID: i32; + #[no_mangle] + static IA32_APIC_BASE_MSR: i32; + #[no_mangle] + static IA32_BIOS_SIGN_ID: i32; + #[no_mangle] + static MSR_PLATFORM_INFO: i32; + #[no_mangle] + static MSR_MISC_FEATURE_ENABLES: i32; + #[no_mangle] + static IA32_MISC_ENABLE: i32; + #[no_mangle] + static IA32_RTIT_CTL: i32; + #[no_mangle] + static MSR_SMI_COUNT: i32; + #[no_mangle] + static IA32_MCG_CAP: i32; + #[no_mangle] + static IA32_KERNEL_GS_BASE: i32; + #[no_mangle] + static MSR_PKG_C2_RESIDENCY: i32; + #[no_mangle] + static IA32_APIC_BASE_BSP: i32; + #[no_mangle] + static IA32_APIC_BASE_EXTD: i32; + #[no_mangle] + static IA32_APIC_BASE_EN: i32; + #[no_mangle] + static APIC_ADDRESS: i32; + #[no_mangle] + static SEG_PREFIX_NONE: i32; + #[no_mangle] + static SEG_PREFIX_ZERO: i32; + #[no_mangle] + static PREFIX_MASK_REP: i32; + #[no_mangle] + static PREFIX_REPZ: i32; + #[no_mangle] + static PREFIX_REPNZ: i32; + #[no_mangle] + static PREFIX_MASK_SEGMENT: i32; + #[no_mangle] + static PREFIX_MASK_OPSIZE: i32; + #[no_mangle] + static PREFIX_MASK_ADDRSIZE: i32; + #[no_mangle] + static PREFIX_F2: i32; + #[no_mangle] + static PREFIX_F3: i32; + #[no_mangle] + static PREFIX_66: i32; + #[no_mangle] + static LOG_CPU: i32; + #[no_mangle] + static A20_MASK: i32; + #[no_mangle] + static A20_MASK16: i32; + #[no_mangle] + static A20_MASK32: i32; + #[no_mangle] + static MXCSR_MASK: i32; + + #[no_mangle] + static mut mem8: *mut u8; + #[no_mangle] + static mut mem16: *mut u16; + #[no_mangle] + static mut mem32s: *mut i32; + #[no_mangle] + static mut jit_block_boundary: bool; + #[no_mangle] + static VALID_TLB_ENTRY_MAX: i32; + #[no_mangle] + static mut valid_tlb_entries: [i32; 10000]; + #[no_mangle] + static mut valid_tlb_entries_count: i32; + #[no_mangle] + static TLB_VALID: i32; + #[no_mangle] + static TLB_READONLY: i32; + #[no_mangle] + static TLB_NO_USER: i32; + #[no_mangle] + static TLB_IN_MAPPED_RANGE: i32; + #[no_mangle] + static TLB_GLOBAL: i32; + #[no_mangle] + static TLB_HAS_CODE: i32; + #[no_mangle] + static CPU_EXCEPTION_DE: i32; + #[no_mangle] + static CPU_EXCEPTION_DB: i32; + #[no_mangle] + static CPU_EXCEPTION_NMI: i32; + #[no_mangle] + static CPU_EXCEPTION_BP: i32; + #[no_mangle] + static CPU_EXCEPTION_OF: i32; + #[no_mangle] + static CPU_EXCEPTION_BR: i32; + #[no_mangle] + static CPU_EXCEPTION_UD: i32; + #[no_mangle] + static CPU_EXCEPTION_NM: i32; + #[no_mangle] + static CPU_EXCEPTION_DF: i32; + #[no_mangle] + static CPU_EXCEPTION_TS: i32; + #[no_mangle] + static CPU_EXCEPTION_NP: i32; + #[no_mangle] + static CPU_EXCEPTION_SS: i32; + #[no_mangle] + static CPU_EXCEPTION_GP: i32; + #[no_mangle] + static CPU_EXCEPTION_PF: i32; + #[no_mangle] + static CPU_EXCEPTION_MF: i32; + #[no_mangle] + static CPU_EXCEPTION_AC: i32; + #[no_mangle] + static CPU_EXCEPTION_MC: i32; + #[no_mangle] + static CPU_EXCEPTION_XM: i32; + #[no_mangle] + static CPU_EXCEPTION_VE: i32; + #[no_mangle] + fn read_imm8() -> i32; + #[no_mangle] + fn read_imm8s() -> i32; + #[no_mangle] + fn read_imm16() -> i32; + #[no_mangle] + fn read_imm32s() -> i32; + #[no_mangle] + fn get_seg_prefix(default_segment: i32) -> i32; + #[no_mangle] + fn get_seg_prefix_ds(offset: i32) -> i32; + #[no_mangle] + fn get_seg_prefix_ss(offset: i32) -> i32; + #[no_mangle] + static reg8: *mut u8; + #[no_mangle] + static reg16: *mut u16; + #[no_mangle] + static reg8s: *mut i8; + #[no_mangle] + static reg16s: *mut i16; + #[no_mangle] + static reg32s: *mut i32; + #[no_mangle] + static last_op1: *mut i32; + #[no_mangle] + static last_op2: *mut i32; + #[no_mangle] + static last_op_size: *mut i32; + #[no_mangle] + static last_add_result: *mut i32; + #[no_mangle] + static last_result: *mut i32; + #[no_mangle] + static flags_changed: *mut i32; + #[no_mangle] + static flags: *mut i32; + #[no_mangle] + static page_fault: *mut bool; + #[no_mangle] + static a20_enabled: *mut bool; + #[no_mangle] + static instruction_pointer: *mut i32; + #[no_mangle] + static previous_ip: *mut i32; + #[no_mangle] + static idtr_size: *mut i32; + #[no_mangle] + static idtr_offset: *mut i32; + #[no_mangle] + static gdtr_size: *mut i32; + #[no_mangle] + static gdtr_offset: *mut i32; + #[no_mangle] + static cr: *mut i32; + #[no_mangle] + static cpl: *mut u8; + #[no_mangle] + static in_hlt: *mut bool; + #[no_mangle] + static last_virt_eip: *mut i32; + #[no_mangle] + static eip_phys: *mut i32; + #[no_mangle] + static last_virt_esp: *mut i32; + #[no_mangle] + static esp_phys: *mut i32; + #[no_mangle] + static sysenter_cs: *mut i32; + #[no_mangle] + static sysenter_esp: *mut i32; + #[no_mangle] + static sysenter_eip: *mut i32; + #[no_mangle] + static prefixes: *mut u8; + #[no_mangle] + static timestamp_counter: *mut u32; + #[no_mangle] + static sreg: *mut u16; + #[no_mangle] + static dreg: *mut i32; + #[no_mangle] + static fw_value: *mut i32; + #[no_mangle] + static segment_is_null: *mut bool; + #[no_mangle] + static segment_offsets: *mut i32; + #[no_mangle] + static segment_limits: *mut u32; + #[no_mangle] + static protected_mode: *mut bool; + #[no_mangle] + static is_32: *mut bool; + #[no_mangle] + static stack_size_32: *mut bool; + #[no_mangle] + static memory_size: *mut u32; + #[no_mangle] + static fpu_stack_empty: *mut i32; + #[no_mangle] + static mxcsr: *mut i32; + #[no_mangle] + static reg_xmm: *mut reg128; + #[no_mangle] + static current_tsc: *mut u64; + #[no_mangle] + static fpu_st: *mut f64; + #[no_mangle] + static fpu_st8: *mut u8; + #[no_mangle] + static fpu_st32: *mut i32; + #[no_mangle] + static fpu_stack_ptr: *mut u32; + #[no_mangle] + static fpu_control_word: *mut i32; + #[no_mangle] + static fpu_status_word: *mut i32; + #[no_mangle] + static fpu_opcode: *mut i32; + #[no_mangle] + static fpu_ip: *mut i32; + #[no_mangle] + static fpu_ip_selector: *mut i32; + #[no_mangle] + static fpu_dp: *mut i32; + #[no_mangle] + static fpu_dp_selector: *mut i32; + #[no_mangle] + static reg_mmx: *mut reg64; + #[no_mangle] + static opstats_buffer: *mut u32; + #[no_mangle] + static opstats_buffer_0f: *mut u32; + #[no_mangle] + static tlb_data: *mut i32; +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed { + __f: f64, + __i: u64, +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_0 { + __f: f32, + __i: u32, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union reg64 { + i8_0: [i8; 8], + i16_0: [i16; 4], + i32_0: [i32; 2], + i64_0: [i64; 1], + u8_0: [u8; 8], + u16_0: [u16; 4], + u32_0: [u32; 2], + u64_0: [u64; 1], + f32_0: [f32; 2], + f64_0: [f64; 1], +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union reg128 { + i8_0: [i8; 16], + i16_0: [i16; 8], + i32_0: [i32; 4], + i64_0: [i64; 2], + u8_0: [u8; 16], + u16_0: [u16; 8], + u32_0: [u32; 4], + u64_0: [u64; 2], + f32_0: [f32; 4], + f64_0: [f64; 2], +} + +unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { + let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { + let mut __u: unnamed = unnamed { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x >= __y) as i32; +} +#[no_mangle] +pub unsafe extern "C" fn resolve_modrm16(mut modrm_byte: i32) -> i32 { + match modrm_byte { + 0 | 8 | 16 | 24 | 32 | 40 | 48 | 56 => { + return get_seg_prefix_ds( + *reg16.offset(BX as isize) as i32 + *reg16.offset(SI as isize) as i32 & 65535i32, + ) + }, + 64 | 72 | 80 | 88 | 96 | 104 | 112 | 120 => { + return get_seg_prefix_ds( + *reg16.offset(BX as isize) as i32 + + *reg16.offset(SI as isize) as i32 + + read_imm8s() + & 65535i32, + ) + }, + 128 | 136 | 144 | 152 | 160 | 168 | 176 | 184 => { + return get_seg_prefix_ds( + *reg16.offset(BX as isize) as i32 + + *reg16.offset(SI as isize) as i32 + + read_imm16() + & 65535i32, + ) + }, + 1 | 9 | 17 | 25 | 33 | 41 | 49 | 57 => { + return get_seg_prefix_ds( + *reg16.offset(BX as isize) as i32 + *reg16.offset(DI as isize) as i32 & 65535i32, + ) + }, + 65 | 73 | 81 | 89 | 97 | 105 | 113 | 121 => { + return get_seg_prefix_ds( + *reg16.offset(BX as isize) as i32 + + *reg16.offset(DI as isize) as i32 + + read_imm8s() + & 65535i32, + ) + }, + 129 | 137 | 145 | 153 | 161 | 169 | 177 | 185 => { + return get_seg_prefix_ds( + *reg16.offset(BX as isize) as i32 + + *reg16.offset(DI as isize) as i32 + + read_imm16() + & 65535i32, + ) + }, + 2 | 10 | 18 | 26 | 34 | 42 | 50 | 58 => { + return get_seg_prefix_ss( + *reg16.offset(BP as isize) as i32 + *reg16.offset(SI as isize) as i32 & 65535i32, + ) + }, + 66 | 74 | 82 | 90 | 98 | 106 | 114 | 122 => { + return get_seg_prefix_ss( + *reg16.offset(BP as isize) as i32 + + *reg16.offset(SI as isize) as i32 + + read_imm8s() + & 65535i32, + ) + }, + 130 | 138 | 146 | 154 | 162 | 170 | 178 | 186 => { + return get_seg_prefix_ss( + *reg16.offset(BP as isize) as i32 + + *reg16.offset(SI as isize) as i32 + + read_imm16() + & 65535i32, + ) + }, + 3 | 11 | 19 | 27 | 35 | 43 | 51 | 59 => { + return get_seg_prefix_ss( + *reg16.offset(BP as isize) as i32 + *reg16.offset(DI as isize) as i32 & 65535i32, + ) + }, + 67 | 75 | 83 | 91 | 99 | 107 | 115 | 123 => { + return get_seg_prefix_ss( + *reg16.offset(BP as isize) as i32 + + *reg16.offset(DI as isize) as i32 + + read_imm8s() + & 65535i32, + ) + }, + 131 | 139 | 147 | 155 | 163 | 171 | 179 | 187 => { + return get_seg_prefix_ss( + *reg16.offset(BP as isize) as i32 + + *reg16.offset(DI as isize) as i32 + + read_imm16() + & 65535i32, + ) + }, + 4 | 12 | 20 | 28 | 36 | 44 | 52 | 60 => { + return get_seg_prefix_ds(*reg16.offset(SI as isize) as i32 & 65535i32) + }, + 68 | 76 | 84 | 92 | 100 | 108 | 116 | 124 => { + return get_seg_prefix_ds(*reg16.offset(SI as isize) as i32 + read_imm8s() & 65535i32) + }, + 132 | 140 | 148 | 156 | 164 | 172 | 180 | 188 => { + return get_seg_prefix_ds(*reg16.offset(SI as isize) as i32 + read_imm16() & 65535i32) + }, + 5 | 13 | 21 | 29 | 37 | 45 | 53 | 61 => { + return get_seg_prefix_ds(*reg16.offset(DI as isize) as i32 & 65535i32) + }, + 69 | 77 | 85 | 93 | 101 | 109 | 117 | 125 => { + return get_seg_prefix_ds(*reg16.offset(DI as isize) as i32 + read_imm8s() & 65535i32) + }, + 133 | 141 | 149 | 157 | 165 | 173 | 181 | 189 => { + return get_seg_prefix_ds(*reg16.offset(DI as isize) as i32 + read_imm16() & 65535i32) + }, + 6 | 14 | 22 | 30 | 38 | 46 | 54 | 62 => return get_seg_prefix_ds(read_imm16()), + 70 | 78 | 86 | 94 | 102 | 110 | 118 | 126 => { + return get_seg_prefix_ss(*reg16.offset(BP as isize) as i32 + read_imm8s() & 65535i32) + }, + 134 | 142 | 150 | 158 | 166 | 174 | 182 | 190 => { + return get_seg_prefix_ss(*reg16.offset(BP as isize) as i32 + read_imm16() & 65535i32) + }, + 7 | 15 | 23 | 31 | 39 | 47 | 55 | 63 => { + return get_seg_prefix_ds(*reg16.offset(BX as isize) as i32 & 65535i32) + }, + 71 | 79 | 87 | 95 | 103 | 111 | 119 | 127 => { + return get_seg_prefix_ds(*reg16.offset(BX as isize) as i32 + read_imm8s() & 65535i32) + }, + 135 | 143 | 151 | 159 | 167 | 175 | 183 | 191 => { + return get_seg_prefix_ds(*reg16.offset(BX as isize) as i32 + read_imm16() & 65535i32) + }, + _ => { + dbg_assert!(0 != 0i32); + return 0i32; + }, + }; +} +#[no_mangle] +pub unsafe extern "C" fn resolve_modrm32(mut modrm_byte: i32) -> i32 { + let mut r: u8 = (modrm_byte & 7i32) as u8; + dbg_assert!(modrm_byte < 192i32); + if r as i32 == 4i32 { + if modrm_byte < 64i32 { + return resolve_sib(0 != 0i32); + } + else { + return resolve_sib(0 != 1i32) + if modrm_byte < 128i32 { + read_imm8s() + } + else { + read_imm32s() + }; + } + } + else if r as i32 == 5i32 { + if modrm_byte < 64i32 { + return get_seg_prefix_ds(read_imm32s()); + } + else { + return get_seg_prefix_ss( + *reg32s.offset(EBP as isize) + if modrm_byte < 128i32 { + read_imm8s() + } + else { + read_imm32s() + }, + ); + } + } + else if modrm_byte < 64i32 { + return get_seg_prefix_ds(*reg32s.offset(r as isize)); + } + else { + return get_seg_prefix_ds( + *reg32s.offset(r as isize) + if modrm_byte < 128i32 { + read_imm8s() + } + else { + read_imm32s() + }, + ); + }; +} +unsafe extern "C" fn resolve_sib(mut mod_0: bool) -> i32 { + let mut s: u8 = 0; + let mut sib_byte: u8 = read_imm8() as u8; + let mut r: u8 = (sib_byte as i32 & 7i32) as u8; + let mut m: u8 = (sib_byte as i32 >> 3i32 & 7i32) as u8; + let mut base: i32 = 0; + let mut seg: i32 = 0; + if r as i32 == 4i32 { + base = *reg32s.offset(ESP as isize); + seg = SS + } + else if r as i32 == 5i32 { + if mod_0 { + base = *reg32s.offset(EBP as isize); + seg = SS + } + else { + base = read_imm32s(); + seg = DS + } + } + else { + base = *reg32s.offset(r as isize); + seg = DS + } + let mut offset: i32 = 0; + if m as i32 == 4i32 { + offset = 0i32 + } + else { + s = (sib_byte as i32 >> 6i32 & 3i32) as u8; + offset = *reg32s.offset(m as isize) << s as i32 + } + return get_seg_prefix(seg) + base + offset; +} +#[no_mangle] +pub unsafe extern "C" fn MODRM_ENTRY() -> i32 { return 0i32; } +#[no_mangle] +pub unsafe extern "C" fn MODRM_ENTRY16() -> i32 { return 0i32; } +#[no_mangle] +pub unsafe extern "C" fn MODRM_ENTRY32() -> i32 { return 0i32; } +#[no_mangle] +pub unsafe extern "C" fn resolve_modrm32_(mut modrm_byte: i32) -> i32 { + match modrm_byte { + 0 | 8 | 16 | 24 | 32 | 40 | 48 | 56 => { + return get_seg_prefix_ds(*reg32s.offset(EAX as isize)) + }, + 64 | 72 | 80 | 88 | 96 | 104 | 112 | 120 => { + return get_seg_prefix_ds(*reg32s.offset(EAX as isize) + read_imm8s()) + }, + 128 | 136 | 144 | 152 | 160 | 168 | 176 | 184 => { + return get_seg_prefix_ds(*reg32s.offset(EAX as isize) + read_imm32s()) + }, + 1 | 9 | 17 | 25 | 33 | 41 | 49 | 57 => { + return get_seg_prefix_ds(*reg32s.offset(ECX as isize)) + }, + 65 | 73 | 81 | 89 | 97 | 105 | 113 | 121 => { + return get_seg_prefix_ds(*reg32s.offset(ECX as isize) + read_imm8s()) + }, + 129 | 137 | 145 | 153 | 161 | 169 | 177 | 185 => { + return get_seg_prefix_ds(*reg32s.offset(ECX as isize) + read_imm32s()) + }, + 2 | 10 | 18 | 26 | 34 | 42 | 50 | 58 => { + return get_seg_prefix_ds(*reg32s.offset(EDX as isize)) + }, + 66 | 74 | 82 | 90 | 98 | 106 | 114 | 122 => { + return get_seg_prefix_ds(*reg32s.offset(EDX as isize) + read_imm8s()) + }, + 130 | 138 | 146 | 154 | 162 | 170 | 178 | 186 => { + return get_seg_prefix_ds(*reg32s.offset(EDX as isize) + read_imm32s()) + }, + 3 | 11 | 19 | 27 | 35 | 43 | 51 | 59 => { + return get_seg_prefix_ds(*reg32s.offset(EBX as isize)) + }, + 67 | 75 | 83 | 91 | 99 | 107 | 115 | 123 => { + return get_seg_prefix_ds(*reg32s.offset(EBX as isize) + read_imm8s()) + }, + 131 | 139 | 147 | 155 | 163 | 171 | 179 | 187 => { + return get_seg_prefix_ds(*reg32s.offset(EBX as isize) + read_imm32s()) + }, + 4 | 12 | 20 | 28 | 36 | 44 | 52 | 60 => return resolve_sib(0 != 0i32), + 68 | 76 | 84 | 92 | 100 | 108 | 116 | 124 => return resolve_sib(0 != 1i32) + read_imm8s(), + 132 | 140 | 148 | 156 | 164 | 172 | 180 | 188 => { + return resolve_sib(0 != 1i32) + read_imm32s() + }, + 5 | 13 | 21 | 29 | 37 | 45 | 53 | 61 => return get_seg_prefix_ds(read_imm32s()), + 69 | 77 | 85 | 93 | 101 | 109 | 117 | 125 => { + return get_seg_prefix_ss(*reg32s.offset(EBP as isize) + read_imm8s()) + }, + 133 | 141 | 149 | 157 | 165 | 173 | 181 | 189 => { + return get_seg_prefix_ss(*reg32s.offset(EBP as isize) + read_imm32s()) + }, + 6 | 14 | 22 | 30 | 38 | 46 | 54 | 62 => { + return get_seg_prefix_ds(*reg32s.offset(ESI as isize)) + }, + 70 | 78 | 86 | 94 | 102 | 110 | 118 | 126 => { + return get_seg_prefix_ds(*reg32s.offset(ESI as isize) + read_imm8s()) + }, + 134 | 142 | 150 | 158 | 166 | 174 | 182 | 190 => { + return get_seg_prefix_ds(*reg32s.offset(ESI as isize) + read_imm32s()) + }, + 7 | 15 | 23 | 31 | 39 | 47 | 55 | 63 => { + return get_seg_prefix_ds(*reg32s.offset(EDI as isize)) + }, + 71 | 79 | 87 | 95 | 103 | 111 | 119 | 127 => { + return get_seg_prefix_ds(*reg32s.offset(EDI as isize) + read_imm8s()) + }, + 135 | 143 | 151 | 159 | 167 | 175 | 183 | 191 => { + return get_seg_prefix_ds(*reg32s.offset(EDI as isize) + read_imm32s()) + }, + _ => { + dbg_assert!(0 != 0i32); + return 0i32; + }, + }; +} diff --git a/src/rust/cpu2/profiler.rs b/src/rust/cpu2/profiler.rs new file mode 100644 index 00000000..7c24aec2 --- /dev/null +++ b/src/rust/cpu2/profiler.rs @@ -0,0 +1,350 @@ +#![allow +( dead_code , mutable_transmutes , non_camel_case_types , non_snake_case , +non_upper_case_globals , unused_mut )] +#![feature ( extern_types , libc )] + +extern "C" { + + #[no_mangle] + static FLAG_CARRY: i32; + #[no_mangle] + static FLAG_PARITY: i32; + #[no_mangle] + static FLAG_ADJUST: i32; + #[no_mangle] + static FLAG_ZERO: i32; + #[no_mangle] + static FLAG_SIGN: i32; + #[no_mangle] + static FLAG_TRAP: i32; + #[no_mangle] + static FLAG_INTERRUPT: i32; + #[no_mangle] + static FLAG_DIRECTION: i32; + #[no_mangle] + static FLAG_OVERFLOW: i32; + #[no_mangle] + static FLAG_IOPL: i32; + #[no_mangle] + static FLAG_NT: i32; + #[no_mangle] + static FLAG_RF: i32; + #[no_mangle] + static FLAG_VM: i32; + #[no_mangle] + static FLAG_AC: i32; + #[no_mangle] + static FLAG_VIF: i32; + #[no_mangle] + static FLAG_VIP: i32; + #[no_mangle] + static FLAG_ID: i32; + #[no_mangle] + static FLAGS_DEFAULT: i32; + #[no_mangle] + static FLAGS_MASK: i32; + #[no_mangle] + static FLAGS_ALL: i32; + #[no_mangle] + static OPSIZE_8: i32; + #[no_mangle] + static OPSIZE_16: i32; + #[no_mangle] + static OPSIZE_32: i32; + #[no_mangle] + static EAX: i32; + #[no_mangle] + static ECX: i32; + #[no_mangle] + static EDX: i32; + #[no_mangle] + static EBX: i32; + #[no_mangle] + static ESP: i32; + #[no_mangle] + static EBP: i32; + #[no_mangle] + static ESI: i32; + #[no_mangle] + static EDI: i32; + #[no_mangle] + static AX: i32; + #[no_mangle] + static CX: i32; + #[no_mangle] + static DX: i32; + #[no_mangle] + static BX: i32; + #[no_mangle] + static SP: i32; + #[no_mangle] + static BP: i32; + #[no_mangle] + static SI: i32; + #[no_mangle] + static DI: i32; + #[no_mangle] + static AL: i32; + #[no_mangle] + static CL: i32; + #[no_mangle] + static DL: i32; + #[no_mangle] + static BL: i32; + #[no_mangle] + static AH: i32; + #[no_mangle] + static CH: i32; + #[no_mangle] + static DH: i32; + #[no_mangle] + static BH: i32; + #[no_mangle] + static ES: i32; + #[no_mangle] + static CS: i32; + #[no_mangle] + static SS: i32; + #[no_mangle] + static DS: i32; + #[no_mangle] + static FS: i32; + #[no_mangle] + static GS: i32; + #[no_mangle] + static TR: i32; + #[no_mangle] + static LDTR: i32; + #[no_mangle] + static PAGE_TABLE_PRESENT_MASK: i32; + #[no_mangle] + static PAGE_TABLE_RW_MASK: i32; + #[no_mangle] + static PAGE_TABLE_USER_MASK: i32; + #[no_mangle] + static PAGE_TABLE_ACCESSED_MASK: i32; + #[no_mangle] + static PAGE_TABLE_DIRTY_MASK: i32; + #[no_mangle] + static PAGE_TABLE_PSE_MASK: i32; + #[no_mangle] + static PAGE_TABLE_GLOBAL_MASK: i32; + #[no_mangle] + static MMAP_BLOCK_BITS: i32; + #[no_mangle] + static MMAP_BLOCK_SIZE: i32; + #[no_mangle] + static CR0_PE: i32; + #[no_mangle] + static CR0_MP: i32; + #[no_mangle] + static CR0_EM: i32; + #[no_mangle] + static CR0_TS: i32; + #[no_mangle] + static CR0_ET: i32; + #[no_mangle] + static CR0_WP: i32; + #[no_mangle] + static CR0_NW: i32; + #[no_mangle] + static CR0_CD: i32; + #[no_mangle] + static CR0_PG: i32; + #[no_mangle] + static CR4_VME: i32; + #[no_mangle] + static CR4_PVI: i32; + #[no_mangle] + static CR4_TSD: i32; + #[no_mangle] + static CR4_PSE: i32; + #[no_mangle] + static CR4_DE: i32; + #[no_mangle] + static CR4_PAE: i32; + #[no_mangle] + static CR4_PGE: i32; + #[no_mangle] + static IA32_SYSENTER_CS: i32; + #[no_mangle] + static IA32_SYSENTER_ESP: i32; + #[no_mangle] + static IA32_SYSENTER_EIP: i32; + #[no_mangle] + static IA32_TIME_STAMP_COUNTER: i32; + #[no_mangle] + static IA32_PLATFORM_ID: i32; + #[no_mangle] + static IA32_APIC_BASE_MSR: i32; + #[no_mangle] + static IA32_BIOS_SIGN_ID: i32; + #[no_mangle] + static MSR_PLATFORM_INFO: i32; + #[no_mangle] + static MSR_MISC_FEATURE_ENABLES: i32; + #[no_mangle] + static IA32_MISC_ENABLE: i32; + #[no_mangle] + static IA32_RTIT_CTL: i32; + #[no_mangle] + static MSR_SMI_COUNT: i32; + #[no_mangle] + static IA32_MCG_CAP: i32; + #[no_mangle] + static IA32_KERNEL_GS_BASE: i32; + #[no_mangle] + static MSR_PKG_C2_RESIDENCY: i32; + #[no_mangle] + static IA32_APIC_BASE_BSP: i32; + #[no_mangle] + static IA32_APIC_BASE_EXTD: i32; + #[no_mangle] + static IA32_APIC_BASE_EN: i32; + #[no_mangle] + static APIC_ADDRESS: i32; + #[no_mangle] + static SEG_PREFIX_NONE: i32; + #[no_mangle] + static SEG_PREFIX_ZERO: i32; + #[no_mangle] + static PREFIX_MASK_REP: i32; + #[no_mangle] + static PREFIX_REPZ: i32; + #[no_mangle] + static PREFIX_REPNZ: i32; + #[no_mangle] + static PREFIX_MASK_SEGMENT: i32; + #[no_mangle] + static PREFIX_MASK_OPSIZE: i32; + #[no_mangle] + static PREFIX_MASK_ADDRSIZE: i32; + #[no_mangle] + static PREFIX_F2: i32; + #[no_mangle] + static PREFIX_F3: i32; + #[no_mangle] + static PREFIX_66: i32; + #[no_mangle] + static LOG_CPU: i32; + #[no_mangle] + static A20_MASK: i32; + #[no_mangle] + static A20_MASK16: i32; + #[no_mangle] + static A20_MASK32: i32; + #[no_mangle] + static MXCSR_MASK: i32; +} +pub const S_SAFE_WRITE32_SLOW_NOT_VALID: stat_name = 22; +pub const S_SAFE_WRITE32_SLOW_NOT_USER: stat_name = 23; + +pub const S_CYCLE_INTERNAL: stat_name = 29; +pub const S_COMPILE: stat_name = 0; + +pub const S_RUN_INTERPRETED_PENDING: stat_name = 8; +pub const S_TRIGGER_CPU_EXCEPTION: stat_name = 14; +pub const S_TLB_GLOBAL_FULL: stat_name = 36; +pub const S_SAFE_READ32_FAST: stat_name = 15; +pub const S_SAFE_READ32_SLOW_PAGE_CROSSED: stat_name = 16; +pub const S_INVALIDATE_PAGE: stat_name = 30; +pub const S_SAFE_READ32_SLOW_NOT_VALID: stat_name = 17; +pub const S_COMPILE_SUCCESS: stat_name = 1; +pub const S_COMPILE_ENTRY_POINT: stat_name = 5; +pub const S_SAFE_WRITE32_FAST: stat_name = 20; +pub const S_DO_RUN: stat_name = 27; +pub const S_SAFE_WRITE32_SLOW_HAS_CODE: stat_name = 26; +pub const S_CLEAR_TLB: stat_name = 33; +pub const S_RUN_FROM_CACHE_STEPS: stat_name = 13; +pub const S_CACHE_MISMATCH: stat_name = 6; +pub const S_RUN_INTERPRETED_DIFFERENT_STATE: stat_name = 10; +pub const S_RUN_INTERPRETED_NEAR_END_OF_PAGE: stat_name = 9; +pub const S_COMPILE_WITH_LOOP_SAFETY: stat_name = 3; +pub const S_COMPILE_CUT_OFF_AT_END_OF_PAGE: stat_name = 2; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct profiler_stat { + pub count: i32, +} +pub const S_COMPILE_BASIC_BLOCK: stat_name = 4; +pub const S_SAFE_WRITE32_SLOW_READ_ONLY: stat_name = 25; +pub const S_INVALIDATE_CACHE_ENTRY: stat_name = 31; + +pub const S_RUN_INTERPRETED_STEPS: stat_name = 11; +pub const S_FULL_CLEAR_TLB: stat_name = 34; +pub type stat_name = u32; +pub const S_TLB_FULL: stat_name = 35; +pub const S_DO_MANY_CYCLES: stat_name = 28; +pub const S_SAFE_WRITE32_SLOW_PAGE_CROSSED: stat_name = 21; +pub const S_SAFE_READ32_SLOW_IN_MAPPED_RANGE: stat_name = 19; +pub const S_RUN_INTERPRETED: stat_name = 7; +pub const S_RUN_FROM_CACHE: stat_name = 12; +pub const S_SAFE_READ32_SLOW_NOT_USER: stat_name = 18; +pub const S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE: stat_name = 24; +pub const S_NONFAULTING_OPTIMIZATION: stat_name = 32; +#[no_mangle] +pub static mut profiler_stat_arr: [profiler_stat; 37] = unsafe { + [ + profiler_stat { count: 0i32 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + ] +}; +#[no_mangle] +pub unsafe extern "C" fn profiler_init() -> () { + let mut i: u32 = 0i32 as u32; + while i < (S_TLB_GLOBAL_FULL as i32 - S_COMPILE as i32 + 1i32) as u32 { + profiler_stat_arr[i as usize].count = 0i32; + i = i.wrapping_add(1) + } +} +#[no_mangle] +pub unsafe extern "C" fn profiler_stat_increment(mut stat: stat_name) -> () { + profiler_stat_increment_by(stat, 1i32); +} +#[no_mangle] +pub unsafe extern "C" fn profiler_stat_increment_by(mut stat: stat_name, mut by: i32) -> () { + profiler_stat_arr[stat as usize].count += by; +} +#[no_mangle] +pub unsafe extern "C" fn profiler_stat_get(mut stat: stat_name) -> i32 { + return profiler_stat_arr[stat as usize].count; +} +#[no_mangle] +pub unsafe extern "C" fn profiler_stat_increment_do_run() -> () { + profiler_stat_increment(S_DO_RUN); +} diff --git a/src/rust/cpu2/shared.rs b/src/rust/cpu2/shared.rs new file mode 100644 index 00000000..bf08f2ae --- /dev/null +++ b/src/rust/cpu2/shared.rs @@ -0,0 +1,399 @@ +#![allow +( dead_code , mutable_transmutes , non_camel_case_types , non_snake_case , +non_upper_case_globals , unused_mut )] +#![feature ( libc )] + +extern "C" { + #[no_mangle] + fn __fpclassifyl(_: f64) -> i32; +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed { + __f: f32, + __i: u32, +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_0 { + __f: f64, + __i: u64, +} + +unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { + let mut __u: unnamed = unnamed { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { + let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x >= __y) as i32; +} +#[no_mangle] +pub unsafe extern "C" fn isnan_XXX(mut f: f64) -> bool { return f != f; } +#[no_mangle] +pub unsafe extern "C" fn isfinite_XXX(mut f: f64) -> bool { + return f == ::std::f32::INFINITY as f64 || f == -::std::f32::INFINITY as f64 || !isnan_XXX(f); +} diff --git a/src/rust/cpu2/sse_instr.rs b/src/rust/cpu2/sse_instr.rs new file mode 100644 index 00000000..abdfca14 --- /dev/null +++ b/src/rust/cpu2/sse_instr.rs @@ -0,0 +1,1141 @@ +#![allow +( dead_code , mutable_transmutes , non_camel_case_types , non_snake_case , +non_upper_case_globals , unused_mut )] +#![feature ( extern_types , libc )] + +extern "C" { + + #[no_mangle] + fn __fpclassifyl(_: f64) -> i32; + #[no_mangle] + static FLAG_CARRY: i32; + #[no_mangle] + static FLAG_PARITY: i32; + #[no_mangle] + static FLAG_ADJUST: i32; + #[no_mangle] + static FLAG_ZERO: i32; + #[no_mangle] + static FLAG_SIGN: i32; + #[no_mangle] + static FLAG_TRAP: i32; + #[no_mangle] + static FLAG_INTERRUPT: i32; + #[no_mangle] + static FLAG_DIRECTION: i32; + #[no_mangle] + static FLAG_OVERFLOW: i32; + #[no_mangle] + static FLAG_IOPL: i32; + #[no_mangle] + static FLAG_NT: i32; + #[no_mangle] + static FLAG_RF: i32; + #[no_mangle] + static FLAG_VM: i32; + #[no_mangle] + static FLAG_AC: i32; + #[no_mangle] + static FLAG_VIF: i32; + #[no_mangle] + static FLAG_VIP: i32; + #[no_mangle] + static FLAG_ID: i32; + #[no_mangle] + static FLAGS_DEFAULT: i32; + #[no_mangle] + static FLAGS_MASK: i32; + #[no_mangle] + static FLAGS_ALL: i32; + #[no_mangle] + static OPSIZE_8: i32; + #[no_mangle] + static OPSIZE_16: i32; + #[no_mangle] + static OPSIZE_32: i32; + #[no_mangle] + static EAX: i32; + #[no_mangle] + static ECX: i32; + #[no_mangle] + static EDX: i32; + #[no_mangle] + static EBX: i32; + #[no_mangle] + static ESP: i32; + #[no_mangle] + static EBP: i32; + #[no_mangle] + static ESI: i32; + #[no_mangle] + static EDI: i32; + #[no_mangle] + static AX: i32; + #[no_mangle] + static CX: i32; + #[no_mangle] + static DX: i32; + #[no_mangle] + static BX: i32; + #[no_mangle] + static SP: i32; + #[no_mangle] + static BP: i32; + #[no_mangle] + static SI: i32; + #[no_mangle] + static DI: i32; + #[no_mangle] + static AL: i32; + #[no_mangle] + static CL: i32; + #[no_mangle] + static DL: i32; + #[no_mangle] + static BL: i32; + #[no_mangle] + static AH: i32; + #[no_mangle] + static CH: i32; + #[no_mangle] + static DH: i32; + #[no_mangle] + static BH: i32; + #[no_mangle] + static ES: i32; + #[no_mangle] + static CS: i32; + #[no_mangle] + static SS: i32; + #[no_mangle] + static DS: i32; + #[no_mangle] + static FS: i32; + #[no_mangle] + static GS: i32; + #[no_mangle] + static TR: i32; + #[no_mangle] + static LDTR: i32; + #[no_mangle] + static PAGE_TABLE_PRESENT_MASK: i32; + #[no_mangle] + static PAGE_TABLE_RW_MASK: i32; + #[no_mangle] + static PAGE_TABLE_USER_MASK: i32; + #[no_mangle] + static PAGE_TABLE_ACCESSED_MASK: i32; + #[no_mangle] + static PAGE_TABLE_DIRTY_MASK: i32; + #[no_mangle] + static PAGE_TABLE_PSE_MASK: i32; + #[no_mangle] + static PAGE_TABLE_GLOBAL_MASK: i32; + #[no_mangle] + static MMAP_BLOCK_BITS: i32; + #[no_mangle] + static MMAP_BLOCK_SIZE: i32; + #[no_mangle] + static CR0_PE: i32; + #[no_mangle] + static CR0_MP: i32; + #[no_mangle] + static CR0_EM: i32; + #[no_mangle] + static CR0_TS: i32; + #[no_mangle] + static CR0_ET: i32; + #[no_mangle] + static CR0_WP: i32; + #[no_mangle] + static CR0_NW: i32; + #[no_mangle] + static CR0_CD: i32; + #[no_mangle] + static CR0_PG: i32; + #[no_mangle] + static CR4_VME: i32; + #[no_mangle] + static CR4_PVI: i32; + #[no_mangle] + static CR4_TSD: i32; + #[no_mangle] + static CR4_PSE: i32; + #[no_mangle] + static CR4_DE: i32; + #[no_mangle] + static CR4_PAE: i32; + #[no_mangle] + static CR4_PGE: i32; + #[no_mangle] + static IA32_SYSENTER_CS: i32; + #[no_mangle] + static IA32_SYSENTER_ESP: i32; + #[no_mangle] + static IA32_SYSENTER_EIP: i32; + #[no_mangle] + static IA32_TIME_STAMP_COUNTER: i32; + #[no_mangle] + static IA32_PLATFORM_ID: i32; + #[no_mangle] + static IA32_APIC_BASE_MSR: i32; + #[no_mangle] + static IA32_BIOS_SIGN_ID: i32; + #[no_mangle] + static MSR_PLATFORM_INFO: i32; + #[no_mangle] + static MSR_MISC_FEATURE_ENABLES: i32; + #[no_mangle] + static IA32_MISC_ENABLE: i32; + #[no_mangle] + static IA32_RTIT_CTL: i32; + #[no_mangle] + static MSR_SMI_COUNT: i32; + #[no_mangle] + static IA32_MCG_CAP: i32; + #[no_mangle] + static IA32_KERNEL_GS_BASE: i32; + #[no_mangle] + static MSR_PKG_C2_RESIDENCY: i32; + #[no_mangle] + static IA32_APIC_BASE_BSP: i32; + #[no_mangle] + static IA32_APIC_BASE_EXTD: i32; + #[no_mangle] + static IA32_APIC_BASE_EN: i32; + #[no_mangle] + static APIC_ADDRESS: i32; + #[no_mangle] + static SEG_PREFIX_NONE: i32; + #[no_mangle] + static SEG_PREFIX_ZERO: i32; + #[no_mangle] + static PREFIX_MASK_REP: i32; + #[no_mangle] + static PREFIX_REPZ: i32; + #[no_mangle] + static PREFIX_REPNZ: i32; + #[no_mangle] + static PREFIX_MASK_SEGMENT: i32; + #[no_mangle] + static PREFIX_MASK_OPSIZE: i32; + #[no_mangle] + static PREFIX_MASK_ADDRSIZE: i32; + #[no_mangle] + static PREFIX_F2: i32; + #[no_mangle] + static PREFIX_F3: i32; + #[no_mangle] + static PREFIX_66: i32; + #[no_mangle] + static LOG_CPU: i32; + #[no_mangle] + static A20_MASK: i32; + #[no_mangle] + static A20_MASK16: i32; + #[no_mangle] + static A20_MASK32: i32; + #[no_mangle] + static MXCSR_MASK: i32; + + #[no_mangle] + fn c_comment(m: *const i8) -> (); + #[no_mangle] + fn isnan_XXX(f: f64) -> bool; + #[no_mangle] + static mut mem8: *mut u8; + #[no_mangle] + static mut mem16: *mut u16; + #[no_mangle] + static mut mem32s: *mut i32; + #[no_mangle] + static mut jit_block_boundary: bool; + #[no_mangle] + static VALID_TLB_ENTRY_MAX: i32; + #[no_mangle] + static mut valid_tlb_entries: [i32; 10000]; + #[no_mangle] + static mut valid_tlb_entries_count: i32; + #[no_mangle] + static TLB_VALID: i32; + #[no_mangle] + static TLB_READONLY: i32; + #[no_mangle] + static TLB_NO_USER: i32; + #[no_mangle] + static TLB_IN_MAPPED_RANGE: i32; + #[no_mangle] + static TLB_GLOBAL: i32; + #[no_mangle] + static TLB_HAS_CODE: i32; + #[no_mangle] + static CPU_EXCEPTION_DE: i32; + #[no_mangle] + static CPU_EXCEPTION_DB: i32; + #[no_mangle] + static CPU_EXCEPTION_NMI: i32; + #[no_mangle] + static CPU_EXCEPTION_BP: i32; + #[no_mangle] + static CPU_EXCEPTION_OF: i32; + #[no_mangle] + static CPU_EXCEPTION_BR: i32; + #[no_mangle] + static CPU_EXCEPTION_UD: i32; + #[no_mangle] + static CPU_EXCEPTION_NM: i32; + #[no_mangle] + static CPU_EXCEPTION_DF: i32; + #[no_mangle] + static CPU_EXCEPTION_TS: i32; + #[no_mangle] + static CPU_EXCEPTION_NP: i32; + #[no_mangle] + static CPU_EXCEPTION_SS: i32; + #[no_mangle] + static CPU_EXCEPTION_GP: i32; + #[no_mangle] + static CPU_EXCEPTION_PF: i32; + #[no_mangle] + static CPU_EXCEPTION_MF: i32; + #[no_mangle] + static CPU_EXCEPTION_AC: i32; + #[no_mangle] + static CPU_EXCEPTION_MC: i32; + #[no_mangle] + static CPU_EXCEPTION_XM: i32; + #[no_mangle] + static CPU_EXCEPTION_VE: i32; + #[no_mangle] + fn safe_read64s(addr: i32) -> reg64; + #[no_mangle] + fn safe_write64(addr: i32, value: i64) -> (); + #[no_mangle] + fn safe_write128(addr: i32, value: reg128) -> (); + #[no_mangle] + fn read_mmx64s(r: i32) -> reg64; + #[no_mangle] + fn write_mmx64(r: i32, low: i32, high: i32) -> (); + #[no_mangle] + fn write_mmx_reg64(r: i32, data: reg64) -> (); + #[no_mangle] + fn read_xmm64s(r: i32) -> reg64; + #[no_mangle] + fn read_xmm128s(r: i32) -> reg128; + #[no_mangle] + fn write_xmm128(r: i32, i0: i32, i1: i32, i2: i32, i3: i32) -> (); + #[no_mangle] + fn write_xmm_reg128(r: i32, data: reg128) -> (); +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union reg64 { + i8_0: [i8; 8], + i16_0: [i16; 4], + i32_0: [i32; 2], + i64_0: [i64; 1], + u8_0: [u8; 8], + u16_0: [u16; 4], + u32_0: [u32; 2], + u64_0: [u64; 1], + f32_0: [f32; 2], + f64_0: [f64; 1], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union reg128 { + i8_0: [i8; 16], + i16_0: [i16; 8], + i32_0: [i32; 4], + i64_0: [i64; 2], + u8_0: [u8; 16], + u16_0: [u16; 8], + u32_0: [u32; 4], + u64_0: [u64; 2], + f32_0: [f32; 4], + f64_0: [f64; 2], +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed { + __f: f32, + __i: u32, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_0 { + __f: f64, + __i: u64, +} + +unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { + let mut __u: unnamed = unnamed { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { + let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x >= __y) as i32; +} +#[no_mangle] +pub unsafe extern "C" fn mov_r_m64(mut addr: i32, mut r: i32) -> () { + c_comment!(("mov* m64, mm")); + let mut data: reg64 = read_mmx64s(r); + safe_write64(addr, data.u64_0[0usize] as i64); +} +#[no_mangle] +pub unsafe extern "C" fn movl_r128_m64(mut addr: i32, mut r: i32) -> () { + c_comment!(("mov* m64, xmm")); + let mut data: reg64 = read_xmm64s(r); + safe_write64(addr, data.u64_0[0usize] as i64); +} +#[no_mangle] +pub unsafe extern "C" fn mov_r_r128(mut r1: i32, mut r2: i32) -> () { + c_comment!(("mov* xmm, xmm")); + let mut data: reg128 = read_xmm128s(r2); + write_xmm_reg128(r1, data); +} +#[no_mangle] +pub unsafe extern "C" fn mov_r_m128(mut addr: i32, mut r: i32) -> () { + c_comment!(("mov* m128, xmm")); + let mut data: reg128 = read_xmm128s(r); + safe_write128(addr, data); +} +#[no_mangle] +pub unsafe extern "C" fn mov_rm_r128(mut source: reg128, mut r: i32) -> () { + c_comment!(("mov* xmm, xmm/m128")); + write_xmm_reg128(r, source); +} +#[no_mangle] +pub unsafe extern "C" fn movh_m64_r128(mut addr: i32, mut r: i32) -> () { + c_comment!(("movhp* xmm, m64")); + let mut data: reg64 = safe_read64s(addr); + let mut orig: reg128 = read_xmm128s(r); + write_xmm128( + r, + orig.u32_0[0usize] as i32, + orig.u32_0[1usize] as i32, + data.u32_0[0usize] as i32, + data.u32_0[1usize] as i32, + ); +} +#[no_mangle] +pub unsafe extern "C" fn movh_r128_m64(mut addr: i32, mut r: i32) -> () { + c_comment!(("movhp* m64, xmm")); + let mut data: reg128 = read_xmm128s(r); + safe_write64(addr, data.u64_0[1usize] as i64); +} +#[no_mangle] +pub unsafe extern "C" fn pand_r128(mut source: reg128, mut r: i32) -> () { + c_comment!(("pand xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + }; + result.u64_0[0usize] = source.u64_0[0usize] & destination.u64_0[0usize]; + result.u64_0[1usize] = source.u64_0[1usize] & destination.u64_0[1usize]; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn pandn_r128(mut source: reg128, mut r: i32) -> () { + c_comment!(("pandn xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + }; + result.u64_0[0usize] = source.u64_0[0usize] & !destination.u64_0[0usize]; + result.u64_0[1usize] = source.u64_0[1usize] & !destination.u64_0[1usize]; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn pxor_r128(mut source: reg128, mut r: i32) -> () { + c_comment!(("pxor xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + }; + result.u64_0[0usize] = source.u64_0[0usize] ^ destination.u64_0[0usize]; + result.u64_0[1usize] = source.u64_0[1usize] ^ destination.u64_0[1usize]; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn por_r128(mut source: reg128, mut r: i32) -> () { + c_comment!(("por xmm, xmm/m128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + }; + result.u64_0[0usize] = source.u64_0[0usize] | destination.u64_0[0usize]; + result.u64_0[1usize] = source.u64_0[1usize] | destination.u64_0[1usize]; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe extern "C" fn psrlw_r64(mut r: i32, mut shift: u32) -> () { + c_comment!(("psrlw mm, {shift}")); + let mut destination: reg64 = read_mmx64s(r); + let mut dword0: i32 = 0i32; + let mut dword1: i32 = 0i32; + if shift <= 15i32 as u32 { + dword0 = destination.u16_0[0usize] as i32 >> shift + | destination.u16_0[1usize] as i32 >> shift << 16i32; + dword1 = destination.u16_0[2usize] as i32 >> shift + | destination.u16_0[3usize] as i32 >> shift << 16i32 + } + write_mmx64(r, dword0, dword1); +} +#[no_mangle] +pub unsafe extern "C" fn psraw_r64(mut r: i32, mut shift: u32) -> () { + c_comment!(("psraw mm, {shift}")); + let mut destination: reg64 = read_mmx64s(r); + let mut shift_clamped: i32 = (if shift > 15i32 as u32 { + 16i32 as u32 + } + else { + shift + }) as i32; + let mut dword0: i32 = destination.i16_0[0usize] as i32 >> shift_clamped & 65535i32 + | destination.i16_0[1usize] as i32 >> shift_clamped << 16i32; + let mut dword1: i32 = destination.i16_0[2usize] as i32 >> shift_clamped & 65535i32 + | destination.i16_0[3usize] as i32 >> shift_clamped << 16i32; + write_mmx64(r, dword0, dword1); +} +#[no_mangle] +pub unsafe extern "C" fn psllw_r64(mut r: i32, mut shift: u32) -> () { + c_comment!(("psllw mm, {shift}")); + let mut destination: reg64 = read_mmx64s(r); + let mut dword0: i32 = 0i32; + let mut dword1: i32 = 0i32; + if shift <= 15i32 as u32 { + dword0 = (destination.u16_0[0usize] as i32) << shift & 65535i32 + | (destination.u16_0[1usize] as i32) << shift << 16i32; + dword1 = (destination.u16_0[2usize] as i32) << shift & 65535i32 + | (destination.u16_0[3usize] as i32) << shift << 16i32 + } + write_mmx64(r, dword0, dword1); +} +#[no_mangle] +pub unsafe extern "C" fn psrld_r64(mut r: i32, mut shift: u32) -> () { + c_comment!(("psrld mm, {shift}")); + let mut destination: reg64 = read_mmx64s(r); + let mut dword0: i32 = 0i32; + let mut dword1: i32 = 0i32; + if shift <= 31i32 as u32 { + dword0 = (destination.u32_0[0usize] >> shift) as i32; + dword1 = (destination.u32_0[1usize] >> shift) as i32 + } + write_mmx64(r, dword0, dword1); +} +#[no_mangle] +pub unsafe extern "C" fn psrad_r64(mut r: i32, mut shift: u32) -> () { + c_comment!(("psrad mm, {shift}")); + let mut destination: reg64 = read_mmx64s(r); + let mut shift_clamped: i32 = (if shift > 31i32 as u32 { + 31i32 as u32 + } + else { + shift + }) as i32; + let mut dword0: i32 = destination.i32_0[0usize] >> shift_clamped; + let mut dword1: i32 = destination.i32_0[1usize] >> shift_clamped; + write_mmx64(r, dword0, dword1); +} +#[no_mangle] +pub unsafe extern "C" fn pslld_r64(mut r: i32, mut shift: u32) -> () { + c_comment!(("pslld mm, {shift}")); + let mut destination: reg64 = read_mmx64s(r); + let mut dword0: i32 = 0i32; + let mut dword1: i32 = 0i32; + if shift <= 31i32 as u32 { + dword0 = destination.i32_0[0usize] << shift; + dword1 = destination.i32_0[1usize] << shift + } + write_mmx64(r, dword0, dword1); +} +#[no_mangle] +pub unsafe extern "C" fn psrlq_r64(mut r: i32, mut shift: u32) -> () { + c_comment!(("psrlq mm, {shift}")); + if shift == 0i32 as u32 { + return; + } + else { + let mut destination: reg64 = read_mmx64s(r); + let mut result: reg64 = reg64 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + }; + if shift <= 63i32 as u32 { + result.u64_0[0usize] = destination.u64_0[0usize] >> shift + } + write_mmx_reg64(r, result); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn psllq_r64(mut r: i32, mut shift: u32) -> () { + c_comment!(("psllq mm, {shift}")); + let mut destination: reg64 = read_mmx64s(r); + if shift == 0i32 as u32 { + return; + } + else { + let mut result: reg64 = reg64 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + }; + if shift <= 63i32 as u32 { + result.u64_0[0usize] = destination.u64_0[0usize] << shift + } + write_mmx_reg64(r, result); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn psrlw_r128(mut r: i32, mut shift: u32) -> () { + c_comment!(("psrlw xmm, {shift}")); + let mut destination: reg128 = read_xmm128s(r); + let mut dword0: i32 = 0i32; + let mut dword1: i32 = 0i32; + let mut dword2: i32 = 0i32; + let mut dword3: i32 = 0i32; + if shift <= 15i32 as u32 { + dword0 = destination.u16_0[0usize] as i32 >> shift + | destination.u16_0[1usize] as i32 >> shift << 16i32; + dword1 = destination.u16_0[2usize] as i32 >> shift + | destination.u16_0[3usize] as i32 >> shift << 16i32; + dword2 = destination.u16_0[4usize] as i32 >> shift + | destination.u16_0[5usize] as i32 >> shift << 16i32; + dword3 = destination.u16_0[6usize] as i32 >> shift + | destination.u16_0[7usize] as i32 >> shift << 16i32 + } + write_xmm128(r, dword0, dword1, dword2, dword3); +} +#[no_mangle] +pub unsafe extern "C" fn psraw_r128(mut r: i32, mut shift: u32) -> () { + c_comment!(("psraw xmm, {shift}")); + let mut destination: reg128 = read_xmm128s(r); + let mut shift_clamped: i32 = (if shift > 15i32 as u32 { + 16i32 as u32 + } + else { + shift + }) as i32; + let mut dword0: i32 = destination.i16_0[0usize] as i32 >> shift_clamped & 65535i32 + | destination.i16_0[1usize] as i32 >> shift_clamped << 16i32; + let mut dword1: i32 = destination.i16_0[2usize] as i32 >> shift_clamped & 65535i32 + | destination.i16_0[3usize] as i32 >> shift_clamped << 16i32; + let mut dword2: i32 = destination.i16_0[4usize] as i32 >> shift_clamped & 65535i32 + | destination.i16_0[5usize] as i32 >> shift_clamped << 16i32; + let mut dword3: i32 = destination.i16_0[6usize] as i32 >> shift_clamped & 65535i32 + | destination.i16_0[7usize] as i32 >> shift_clamped << 16i32; + write_xmm128(r, dword0, dword1, dword2, dword3); +} +#[no_mangle] +pub unsafe extern "C" fn psllw_r128(mut r: i32, mut shift: u32) -> () { + c_comment!(("psllw xmm, {shift}")); + let mut destination: reg128 = read_xmm128s(r); + let mut dword0: i32 = 0i32; + let mut dword1: i32 = 0i32; + let mut dword2: i32 = 0i32; + let mut dword3: i32 = 0i32; + if shift <= 15i32 as u32 { + dword0 = (destination.u16_0[0usize] as i32) << shift & 65535i32 + | (destination.u16_0[1usize] as i32) << shift << 16i32; + dword1 = (destination.u16_0[2usize] as i32) << shift & 65535i32 + | (destination.u16_0[3usize] as i32) << shift << 16i32; + dword2 = (destination.u16_0[4usize] as i32) << shift & 65535i32 + | (destination.u16_0[5usize] as i32) << shift << 16i32; + dword3 = (destination.u16_0[6usize] as i32) << shift & 65535i32 + | (destination.u16_0[7usize] as i32) << shift << 16i32 + } + write_xmm128(r, dword0, dword1, dword2, dword3); +} +#[no_mangle] +pub unsafe extern "C" fn psrld_r128(mut r: i32, mut shift: u32) -> () { + c_comment!(("psrld xmm, {shift}")); + let mut destination: reg128 = read_xmm128s(r); + let mut dword0: i32 = 0i32; + let mut dword1: i32 = 0i32; + let mut dword2: i32 = 0i32; + let mut dword3: i32 = 0i32; + if shift <= 31i32 as u32 { + dword0 = (destination.u32_0[0usize] >> shift) as i32; + dword1 = (destination.u32_0[1usize] >> shift) as i32; + dword2 = (destination.u32_0[2usize] >> shift) as i32; + dword3 = (destination.u32_0[3usize] >> shift) as i32 + } + write_xmm128(r, dword0, dword1, dword2, dword3); +} +#[no_mangle] +pub unsafe extern "C" fn psrad_r128(mut r: i32, mut shift: u32) -> () { + c_comment!(("psrad xmm, {shift}")); + let mut destination: reg128 = read_xmm128s(r); + let mut shift_clamped: i32 = (if shift > 31i32 as u32 { + 31i32 as u32 + } + else { + shift + }) as i32; + let mut dword0: i32 = destination.i32_0[0usize] >> shift_clamped; + let mut dword1: i32 = destination.i32_0[1usize] >> shift_clamped; + let mut dword2: i32 = destination.i32_0[2usize] >> shift_clamped; + let mut dword3: i32 = destination.i32_0[3usize] >> shift_clamped; + write_xmm128(r, dword0, dword1, dword2, dword3); +} +#[no_mangle] +pub unsafe extern "C" fn pslld_r128(mut r: i32, mut shift: u32) -> () { + c_comment!(("pslld xmm, {shift}")); + let mut destination: reg128 = read_xmm128s(r); + let mut dword0: i32 = 0i32; + let mut dword1: i32 = 0i32; + let mut dword2: i32 = 0i32; + let mut dword3: i32 = 0i32; + if shift <= 31i32 as u32 { + dword0 = destination.i32_0[0usize] << shift; + dword1 = destination.i32_0[1usize] << shift; + dword2 = destination.i32_0[2usize] << shift; + dword3 = destination.i32_0[3usize] << shift + } + write_xmm128(r, dword0, dword1, dword2, dword3); +} +#[no_mangle] +pub unsafe extern "C" fn psrlq_r128(mut r: i32, mut shift: u32) -> () { + c_comment!(("psrlq xmm, {shift}")); + if shift == 0i32 as u32 { + return; + } + else { + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + }; + if shift <= 63i32 as u32 { + result.u64_0[0usize] = destination.u64_0[0usize] >> shift; + result.u64_0[1usize] = destination.u64_0[1usize] >> shift + } + write_xmm_reg128(r, result); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn psllq_r128(mut r: i32, mut shift: u32) -> () { + c_comment!(("psllq xmm, {shift}")); + let mut destination: reg128 = read_xmm128s(r); + if shift == 0i32 as u32 { + return; + } + else { + let mut result: reg128 = reg128 { + i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + }; + if shift <= 63i32 as u32 { + result.u64_0[0usize] = destination.u64_0[0usize] << shift; + result.u64_0[1usize] = destination.u64_0[1usize] << shift + } + write_xmm_reg128(r, result); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn sse_comparison(mut op: i32, mut x: f64, mut y: f64) -> bool { + c_comment!(("TODO: Signaling")); + match op & 7i32 { + 0 => return x == y, + 1 => return x < y, + 2 => return x <= y, + 3 => return 0 != isnan_XXX(x) as i32 || 0 != isnan_XXX(y) as i32, + 4 => return x != y || 0 != isnan_XXX(x) as i32 || 0 != isnan_XXX(y) as i32, + 5 => return x >= y || 0 != isnan_XXX(x) as i32 || 0 != isnan_XXX(y) as i32, + 6 => return x > y || 0 != isnan_XXX(x) as i32 || 0 != isnan_XXX(y) as i32, + 7 => return !isnan_XXX(x) && !isnan_XXX(y), + _ => { + dbg_assert!(0 != 0i32); + return 0 != 0i32; + }, + }; +} +#[no_mangle] +pub unsafe extern "C" fn sse_min(mut x: f64, mut y: f64) -> f64 { + c_comment!(("if both x and y are 0 or x is nan, y is returned")); + return if x < y { x } else { y }; +} +#[no_mangle] +pub unsafe extern "C" fn sse_max(mut x: f64, mut y: f64) -> f64 { + c_comment!(("if both x and y are 0 or x is nan, y is returned")); + return if x > y { x } else { y }; +} +#[no_mangle] +pub unsafe extern "C" fn sse_convert_f64_to_i32(mut x: f64) -> i32 { + c_comment!(("TODO: Rounding modes")); + if x >= 2147483648u32.wrapping_neg() as f64 && x < 2147483648u32 as f64 { + return x as i64 as i32; + } + else { + c_comment!(("TODO: Signal")); + return 2147483648u32.wrapping_neg() as i32; + }; +} diff --git a/src/rust/cpu2/string.rs b/src/rust/cpu2/string.rs new file mode 100644 index 00000000..846aa17d --- /dev/null +++ b/src/rust/cpu2/string.rs @@ -0,0 +1,2448 @@ +#![allow +( dead_code , mutable_transmutes , non_camel_case_types , non_snake_case , +non_upper_case_globals , unused_mut )] +#![feature ( extern_types , libc )] + +extern "C" { + + #[no_mangle] + fn cmp8(x: i32, y: i32) -> (); + #[no_mangle] + fn cmp16(x: i32, y: i32) -> (); + #[no_mangle] + fn cmp32(x: i32, y: i32) -> (); + #[no_mangle] + fn __fpclassifyl(_: f64) -> i32; + #[no_mangle] + static FLAG_CARRY: i32; + #[no_mangle] + static FLAG_PARITY: i32; + #[no_mangle] + static FLAG_ADJUST: i32; + #[no_mangle] + static FLAG_ZERO: i32; + #[no_mangle] + static FLAG_SIGN: i32; + #[no_mangle] + static FLAG_TRAP: i32; + #[no_mangle] + static FLAG_INTERRUPT: i32; + #[no_mangle] + static FLAG_DIRECTION: i32; + #[no_mangle] + static FLAG_OVERFLOW: i32; + #[no_mangle] + static FLAG_IOPL: i32; + #[no_mangle] + static FLAG_NT: i32; + #[no_mangle] + static FLAG_RF: i32; + #[no_mangle] + static FLAG_VM: i32; + #[no_mangle] + static FLAG_AC: i32; + #[no_mangle] + static FLAG_VIF: i32; + #[no_mangle] + static FLAG_VIP: i32; + #[no_mangle] + static FLAG_ID: i32; + #[no_mangle] + static FLAGS_DEFAULT: i32; + #[no_mangle] + static FLAGS_MASK: i32; + #[no_mangle] + static FLAGS_ALL: i32; + #[no_mangle] + static OPSIZE_8: i32; + #[no_mangle] + static OPSIZE_16: i32; + #[no_mangle] + static OPSIZE_32: i32; + #[no_mangle] + static EAX: i32; + #[no_mangle] + static ECX: i32; + #[no_mangle] + static EDX: i32; + #[no_mangle] + static EBX: i32; + #[no_mangle] + static ESP: i32; + #[no_mangle] + static EBP: i32; + #[no_mangle] + static ESI: i32; + #[no_mangle] + static EDI: i32; + #[no_mangle] + static AX: i32; + #[no_mangle] + static CX: i32; + #[no_mangle] + static DX: i32; + #[no_mangle] + static BX: i32; + #[no_mangle] + static SP: i32; + #[no_mangle] + static BP: i32; + #[no_mangle] + static SI: i32; + #[no_mangle] + static DI: i32; + #[no_mangle] + static AL: i32; + #[no_mangle] + static CL: i32; + #[no_mangle] + static DL: i32; + #[no_mangle] + static BL: i32; + #[no_mangle] + static AH: i32; + #[no_mangle] + static CH: i32; + #[no_mangle] + static DH: i32; + #[no_mangle] + static BH: i32; + #[no_mangle] + static ES: i32; + #[no_mangle] + static CS: i32; + #[no_mangle] + static SS: i32; + #[no_mangle] + static DS: i32; + #[no_mangle] + static FS: i32; + #[no_mangle] + static GS: i32; + #[no_mangle] + static TR: i32; + #[no_mangle] + static LDTR: i32; + #[no_mangle] + static PAGE_TABLE_PRESENT_MASK: i32; + #[no_mangle] + static PAGE_TABLE_RW_MASK: i32; + #[no_mangle] + static PAGE_TABLE_USER_MASK: i32; + #[no_mangle] + static PAGE_TABLE_ACCESSED_MASK: i32; + #[no_mangle] + static PAGE_TABLE_DIRTY_MASK: i32; + #[no_mangle] + static PAGE_TABLE_PSE_MASK: i32; + #[no_mangle] + static PAGE_TABLE_GLOBAL_MASK: i32; + #[no_mangle] + static MMAP_BLOCK_BITS: i32; + #[no_mangle] + static MMAP_BLOCK_SIZE: i32; + #[no_mangle] + static CR0_PE: i32; + #[no_mangle] + static CR0_MP: i32; + #[no_mangle] + static CR0_EM: i32; + #[no_mangle] + static CR0_TS: i32; + #[no_mangle] + static CR0_ET: i32; + #[no_mangle] + static CR0_WP: i32; + #[no_mangle] + static CR0_NW: i32; + #[no_mangle] + static CR0_CD: i32; + #[no_mangle] + static CR0_PG: i32; + #[no_mangle] + static CR4_VME: i32; + #[no_mangle] + static CR4_PVI: i32; + #[no_mangle] + static CR4_TSD: i32; + #[no_mangle] + static CR4_PSE: i32; + #[no_mangle] + static CR4_DE: i32; + #[no_mangle] + static CR4_PAE: i32; + #[no_mangle] + static CR4_PGE: i32; + #[no_mangle] + static IA32_SYSENTER_CS: i32; + #[no_mangle] + static IA32_SYSENTER_ESP: i32; + #[no_mangle] + static IA32_SYSENTER_EIP: i32; + #[no_mangle] + static IA32_TIME_STAMP_COUNTER: i32; + #[no_mangle] + static IA32_PLATFORM_ID: i32; + #[no_mangle] + static IA32_APIC_BASE_MSR: i32; + #[no_mangle] + static IA32_BIOS_SIGN_ID: i32; + #[no_mangle] + static MSR_PLATFORM_INFO: i32; + #[no_mangle] + static MSR_MISC_FEATURE_ENABLES: i32; + #[no_mangle] + static IA32_MISC_ENABLE: i32; + #[no_mangle] + static IA32_RTIT_CTL: i32; + #[no_mangle] + static MSR_SMI_COUNT: i32; + #[no_mangle] + static IA32_MCG_CAP: i32; + #[no_mangle] + static IA32_KERNEL_GS_BASE: i32; + #[no_mangle] + static MSR_PKG_C2_RESIDENCY: i32; + #[no_mangle] + static IA32_APIC_BASE_BSP: i32; + #[no_mangle] + static IA32_APIC_BASE_EXTD: i32; + #[no_mangle] + static IA32_APIC_BASE_EN: i32; + #[no_mangle] + static APIC_ADDRESS: i32; + #[no_mangle] + static SEG_PREFIX_NONE: i32; + #[no_mangle] + static SEG_PREFIX_ZERO: i32; + #[no_mangle] + static PREFIX_MASK_REP: i32; + #[no_mangle] + static PREFIX_REPZ: i32; + #[no_mangle] + static PREFIX_REPNZ: i32; + #[no_mangle] + static PREFIX_MASK_SEGMENT: i32; + #[no_mangle] + static PREFIX_MASK_OPSIZE: i32; + #[no_mangle] + static PREFIX_MASK_ADDRSIZE: i32; + #[no_mangle] + static PREFIX_F2: i32; + #[no_mangle] + static PREFIX_F3: i32; + #[no_mangle] + static PREFIX_66: i32; + #[no_mangle] + static LOG_CPU: i32; + #[no_mangle] + static A20_MASK: i32; + #[no_mangle] + static A20_MASK16: i32; + #[no_mangle] + static A20_MASK32: i32; + #[no_mangle] + static MXCSR_MASK: i32; + + #[no_mangle] + fn c_comment(m: *const i8) -> (); + #[no_mangle] + static mut mem8: *mut u8; + #[no_mangle] + static mut mem16: *mut u16; + #[no_mangle] + static mut mem32s: *mut i32; + #[no_mangle] + static mut jit_block_boundary: bool; + #[no_mangle] + static VALID_TLB_ENTRY_MAX: i32; + #[no_mangle] + static mut valid_tlb_entries: [i32; 10000]; + #[no_mangle] + static mut valid_tlb_entries_count: i32; + #[no_mangle] + static TLB_VALID: i32; + #[no_mangle] + static TLB_READONLY: i32; + #[no_mangle] + static TLB_NO_USER: i32; + #[no_mangle] + static TLB_IN_MAPPED_RANGE: i32; + #[no_mangle] + static TLB_GLOBAL: i32; + #[no_mangle] + static TLB_HAS_CODE: i32; + #[no_mangle] + static CPU_EXCEPTION_DE: i32; + #[no_mangle] + static CPU_EXCEPTION_DB: i32; + #[no_mangle] + static CPU_EXCEPTION_NMI: i32; + #[no_mangle] + static CPU_EXCEPTION_BP: i32; + #[no_mangle] + static CPU_EXCEPTION_OF: i32; + #[no_mangle] + static CPU_EXCEPTION_BR: i32; + #[no_mangle] + static CPU_EXCEPTION_UD: i32; + #[no_mangle] + static CPU_EXCEPTION_NM: i32; + #[no_mangle] + static CPU_EXCEPTION_DF: i32; + #[no_mangle] + static CPU_EXCEPTION_TS: i32; + #[no_mangle] + static CPU_EXCEPTION_NP: i32; + #[no_mangle] + static CPU_EXCEPTION_SS: i32; + #[no_mangle] + static CPU_EXCEPTION_GP: i32; + #[no_mangle] + static CPU_EXCEPTION_PF: i32; + #[no_mangle] + static CPU_EXCEPTION_MF: i32; + #[no_mangle] + static CPU_EXCEPTION_AC: i32; + #[no_mangle] + static CPU_EXCEPTION_MC: i32; + #[no_mangle] + static CPU_EXCEPTION_XM: i32; + #[no_mangle] + static CPU_EXCEPTION_VE: i32; + #[no_mangle] + fn translate_address_read(address: i32) -> u32; + #[no_mangle] + fn translate_address_write(address: i32) -> u32; + #[no_mangle] + fn writable_or_pagefault(addr: i32, size: i32) -> (); + #[no_mangle] + fn get_seg(segment: i32) -> i32; + #[no_mangle] + fn get_seg_prefix(default_segment: i32) -> i32; + #[no_mangle] + fn safe_read8(addr: i32) -> i32; + #[no_mangle] + fn safe_read16(addr: i32) -> i32; + #[no_mangle] + fn safe_read32s(address: i32) -> i32; + #[no_mangle] + fn safe_write8(addr: i32, value: i32) -> (); + #[no_mangle] + fn safe_write16(addr: i32, value: i32) -> (); + #[no_mangle] + fn safe_write32(address: i32, value: i32) -> (); + #[no_mangle] + fn get_reg_asize(reg: i32) -> i32; + #[no_mangle] + fn set_ecx_asize(value: i32) -> (); + #[no_mangle] + fn add_reg_asize(reg: i32, value: i32) -> (); + #[no_mangle] + fn decr_ecx_asize() -> i32; + #[no_mangle] + static reg8: *mut u8; + #[no_mangle] + static reg16: *mut u16; + #[no_mangle] + static reg8s: *mut i8; + #[no_mangle] + static reg16s: *mut i16; + #[no_mangle] + static reg32s: *mut i32; + #[no_mangle] + static last_op1: *mut i32; + #[no_mangle] + static last_op2: *mut i32; + #[no_mangle] + static last_op_size: *mut i32; + #[no_mangle] + static last_add_result: *mut i32; + #[no_mangle] + static last_result: *mut i32; + #[no_mangle] + static flags_changed: *mut i32; + #[no_mangle] + static flags: *mut i32; + #[no_mangle] + static page_fault: *mut bool; + #[no_mangle] + static a20_enabled: *mut bool; + #[no_mangle] + static instruction_pointer: *mut i32; + #[no_mangle] + static previous_ip: *mut i32; + #[no_mangle] + static idtr_size: *mut i32; + #[no_mangle] + static idtr_offset: *mut i32; + #[no_mangle] + static gdtr_size: *mut i32; + #[no_mangle] + static gdtr_offset: *mut i32; + #[no_mangle] + static cr: *mut i32; + #[no_mangle] + static cpl: *mut u8; + #[no_mangle] + static in_hlt: *mut bool; + #[no_mangle] + static last_virt_eip: *mut i32; + #[no_mangle] + static eip_phys: *mut i32; + #[no_mangle] + static last_virt_esp: *mut i32; + #[no_mangle] + static esp_phys: *mut i32; + #[no_mangle] + static sysenter_cs: *mut i32; + #[no_mangle] + static sysenter_esp: *mut i32; + #[no_mangle] + static sysenter_eip: *mut i32; + #[no_mangle] + static prefixes: *mut u8; + #[no_mangle] + static timestamp_counter: *mut u32; + #[no_mangle] + static sreg: *mut u16; + #[no_mangle] + static dreg: *mut i32; + #[no_mangle] + static fw_value: *mut i32; + #[no_mangle] + static segment_is_null: *mut bool; + #[no_mangle] + static segment_offsets: *mut i32; + #[no_mangle] + static segment_limits: *mut u32; + #[no_mangle] + static protected_mode: *mut bool; + #[no_mangle] + static is_32: *mut bool; + #[no_mangle] + static stack_size_32: *mut bool; + #[no_mangle] + static memory_size: *mut u32; + #[no_mangle] + static fpu_stack_empty: *mut i32; + #[no_mangle] + static mxcsr: *mut i32; + #[no_mangle] + static reg_xmm: *mut reg128; + #[no_mangle] + static current_tsc: *mut u64; + #[no_mangle] + static fpu_st: *mut f64; + #[no_mangle] + static fpu_st8: *mut u8; + #[no_mangle] + static fpu_st32: *mut i32; + #[no_mangle] + static fpu_stack_ptr: *mut u32; + #[no_mangle] + static fpu_control_word: *mut i32; + #[no_mangle] + static fpu_status_word: *mut i32; + #[no_mangle] + static fpu_opcode: *mut i32; + #[no_mangle] + static fpu_ip: *mut i32; + #[no_mangle] + static fpu_ip_selector: *mut i32; + #[no_mangle] + static fpu_dp: *mut i32; + #[no_mangle] + static fpu_dp_selector: *mut i32; + #[no_mangle] + static reg_mmx: *mut reg64; + #[no_mangle] + static opstats_buffer: *mut u32; + #[no_mangle] + static opstats_buffer_0f: *mut u32; + #[no_mangle] + static tlb_data: *mut i32; + #[no_mangle] + fn test_privileges_for_io(_: i32, _: i32) -> bool; + #[no_mangle] + fn io_port_read8(_: i32) -> i32; + #[no_mangle] + fn io_port_read16(_: i32) -> i32; + #[no_mangle] + fn io_port_read32(_: i32) -> i32; + #[no_mangle] + fn io_port_write8(_: i32, _: i32) -> (); + #[no_mangle] + fn io_port_write16(_: i32, _: i32) -> (); + #[no_mangle] + fn io_port_write32(_: i32, _: i32) -> (); + #[no_mangle] + fn read8(addr: u32) -> i32; + #[no_mangle] + fn read_aligned16(addr: u32) -> i32; + #[no_mangle] + fn read_aligned32(addr: u32) -> i32; + #[no_mangle] + fn write8(addr: u32, value: i32) -> (); + #[no_mangle] + fn write_aligned16(addr: u32, value: u32) -> (); + #[no_mangle] + fn write_aligned32(addr: u32, value: i32) -> (); +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union reg128 { + i8_0: [i8; 16], + i16_0: [i16; 8], + i32_0: [i32; 4], + i64_0: [i64; 2], + u8_0: [u8; 16], + u16_0: [u16; 8], + u32_0: [u32; 4], + u64_0: [u64; 2], + f32_0: [f32; 4], + f64_0: [f64; 2], +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union reg64 { + i8_0: [i8; 8], + i16_0: [i16; 4], + i32_0: [i32; 2], + i64_0: [i64; 1], + u8_0: [u8; 8], + u16_0: [u16; 4], + u32_0: [u32; 2], + u64_0: [u64; 1], + f32_0: [f32; 2], + f64_0: [f64; 1], +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed { + __f: f32, + __i: u32, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub union unnamed_0 { + __f: f64, + __i: u64, +} + +unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { + let mut __u: unnamed = unnamed { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { + let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; + __u.__f = __f; + return __u.__i; +} +unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x < __y) as i32; +} +unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x <= __y) as i32; +} +unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x != __y) as i32; +} +unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x > __y) as i32; +} +unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x as f64) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y as f64) == 0i32) as i32 + } && __x >= __y) as i32; +} +unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { + return (0 == if 0 != if ::std::mem::size_of::() as u64 + == ::std::mem::size_of::() as u64 + { + (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__x) == 0i32) as i32 + } { + 1i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 + } + else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { + (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 + } + else { + (__fpclassifyl(__y) == 0i32) as i32 + } && __x >= __y) as i32; +} +#[no_mangle] +pub unsafe extern "C" fn string_get_cycle_count(mut size: i32, mut address: i32) -> i32 { + dbg_assert!(0 != size && size <= 4i32 && size >= -4i32); + if size < 0i32 { + size = -size; + address = 4096i32 - address - size + } + dbg_assert!(address & size - 1i32 == 0i32); + c_comment!(("1 -> 0; 2 -> 1; 4 -> 2")); + let mut shift: i32 = size >> 1i32; + return 4096i32 - (address & 4095i32) >> shift; +} +#[no_mangle] +pub unsafe extern "C" fn string_get_cycle_count2( + mut size: i32, + mut addr1: i32, + mut addr2: i32, +) -> i32 { + let mut c1: i32 = string_get_cycle_count(size, addr1); + let mut c2: i32 = string_get_cycle_count(size, addr2); + return if c1 < c2 { c1 } else { c2 }; +} +#[no_mangle] +pub unsafe extern "C" fn movsb_rep() -> () { + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -1i32 + } + else { + 1i32 + }; + let mut count: i32 = get_reg_asize(ECX); + if count == 0i32 { + return; + } + else { + let mut cont: i32 = 0i32; + let mut start_count: i32 = count; + let mut cycle_counter: i32 = string_get_cycle_count2(size, src, dest); + let mut phys_src: i32 = translate_address_read(src) as i32; + let mut phys_dest: i32 = translate_address_write(dest) as i32; + loop { + write8(phys_dest as u32, read8(phys_src as u32)); + phys_dest += size; + phys_src += size; + count -= 1; + cont = (count != 0i32) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + let mut diff: i32 = size * (start_count - count); + add_reg_asize(EDI, diff); + add_reg_asize(ESI, diff); + set_ecx_asize(count); + *timestamp_counter = + (*timestamp_counter as u32).wrapping_add((start_count - count) as u32) as u32 as u32; + if 0 != cont { + *instruction_pointer = *previous_ip + } + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn movsb_no_rep() -> () { + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -1i32 + } + else { + 1i32 + }; + safe_write8(dest, safe_read8(src)); + add_reg_asize(EDI, size); + add_reg_asize(ESI, size); +} +#[no_mangle] +pub unsafe extern "C" fn movsw_rep() -> () { + let mut diff: i32 = 0; + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -2i32 + } + else { + 2i32 + }; + let mut count: i32 = get_reg_asize(ECX); + if count == 0i32 { + return; + } + else { + let mut cont: i32 = 0i32; + let mut start_count: i32 = count; + let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; + if 0 == dest & 1i32 && 0 == src & 1i32 { + let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; + let mut phys_src: i32 = (translate_address_read(src) >> 1i32) as i32; + let mut phys_dest: i32 = (translate_address_write(dest) >> 1i32) as i32; + cycle_counter = string_get_cycle_count2(size, src, dest); + loop { + write_aligned16(phys_dest as u32, read_aligned16(phys_src as u32) as u32); + phys_dest += single_size; + phys_src += single_size; + count -= 1; + cont = (count != 0i32) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + diff = size * (start_count - count); + add_reg_asize(EDI, diff); + add_reg_asize(ESI, diff); + set_ecx_asize(count); + *timestamp_counter = + (*timestamp_counter as u32).wrapping_add((start_count - count) as u32) as u32 as u32 + } + else { + loop { + safe_write16(dest, safe_read16(src)); + dest += size; + add_reg_asize(EDI, size); + src += size; + add_reg_asize(ESI, size); + cont = (decr_ecx_asize() != 0i32) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + } + if 0 != cont { + *instruction_pointer = *previous_ip + } + return; + }; +} +#[no_mangle] +pub static mut MAX_COUNT_PER_CYCLE: i32 = unsafe { 4096i32 }; +#[no_mangle] +pub unsafe extern "C" fn movsw_no_rep() -> () { + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -2i32 + } + else { + 2i32 + }; + safe_write16(dest, safe_read16(src)); + add_reg_asize(EDI, size); + add_reg_asize(ESI, size); +} +#[no_mangle] +pub unsafe extern "C" fn movsd_rep() -> () { + let mut diff: i32 = 0; + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -4i32 + } + else { + 4i32 + }; + let mut count: i32 = get_reg_asize(ECX); + if count == 0i32 { + return; + } + else { + let mut cont: i32 = 0i32; + let mut start_count: i32 = count; + let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; + if 0 == dest & 3i32 && 0 == src & 3i32 { + let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; + let mut phys_src: i32 = (translate_address_read(src) >> 2i32) as i32; + let mut phys_dest: i32 = (translate_address_write(dest) >> 2i32) as i32; + cycle_counter = string_get_cycle_count2(size, src, dest); + loop { + write_aligned32(phys_dest as u32, read_aligned32(phys_src as u32)); + phys_dest += single_size; + phys_src += single_size; + count -= 1; + cont = (count != 0i32) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + diff = size * (start_count - count); + add_reg_asize(EDI, diff); + add_reg_asize(ESI, diff); + set_ecx_asize(count); + *timestamp_counter = + (*timestamp_counter as u32).wrapping_add((start_count - count) as u32) as u32 as u32 + } + else { + loop { + safe_write32(dest, safe_read32s(src)); + dest += size; + add_reg_asize(EDI, size); + src += size; + add_reg_asize(ESI, size); + cont = (decr_ecx_asize() != 0i32) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + } + if 0 != cont { + *instruction_pointer = *previous_ip + } + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn movsd_no_rep() -> () { + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -4i32 + } + else { + 4i32 + }; + safe_write32(dest, safe_read32s(src)); + add_reg_asize(EDI, size); + add_reg_asize(ESI, size); +} +#[no_mangle] +pub unsafe extern "C" fn cmpsb_rep(mut prefix_flag: i32) -> () { + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut data_src: i32 = 0; + let mut data_dest: i32 = 0; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -1i32 + } + else { + 1i32 + }; + let mut count: i32 = get_reg_asize(ECX); + if count == 0i32 { + return; + } + else { + let mut cont: i32 = 0i32; + let mut start_count: i32 = count; + let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; + let mut cycle_counter: i32 = string_get_cycle_count2(size, src, dest); + let mut phys_src: i32 = translate_address_read(src) as i32; + let mut phys_dest: i32 = translate_address_read(dest) as i32; + loop { + data_dest = read8(phys_dest as u32); + data_src = read8(phys_src as u32); + phys_dest += size; + phys_src += size; + count -= 1; + cont = (count != 0i32 && (data_src == data_dest) as i32 == is_repz) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + let mut diff: i32 = size * (start_count - count); + add_reg_asize(EDI, diff); + add_reg_asize(ESI, diff); + set_ecx_asize(count); + *timestamp_counter = + (*timestamp_counter as u32).wrapping_add((start_count - count) as u32) as u32 as u32; + if 0 != cont { + *instruction_pointer = *previous_ip + } + cmp8(data_src, data_dest); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn cmpsb_no_rep() -> () { + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut data_src: i32 = 0; + let mut data_dest: i32 = 0; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -1i32 + } + else { + 1i32 + }; + data_src = safe_read8(src); + data_dest = safe_read8(dest); + add_reg_asize(EDI, size); + add_reg_asize(ESI, size); + cmp8(data_src, data_dest); +} +#[no_mangle] +pub unsafe extern "C" fn cmpsw_rep(mut prefix_flag: i32) -> () { + let mut diff: i32 = 0; + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut data_src: i32 = 0; + let mut data_dest: i32 = 0; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -2i32 + } + else { + 2i32 + }; + let mut count: i32 = get_reg_asize(ECX); + if count == 0i32 { + return; + } + else { + let mut cont: i32 = 0i32; + let mut start_count: i32 = count; + let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; + let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; + if 0 == dest & 1i32 && 0 == src & 1i32 { + let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; + let mut phys_src: i32 = (translate_address_read(src) >> 1i32) as i32; + let mut phys_dest: i32 = (translate_address_read(dest) >> 1i32) as i32; + cycle_counter = string_get_cycle_count2(size, src, dest); + loop { + data_dest = read_aligned16(phys_dest as u32); + data_src = read_aligned16(phys_src as u32); + phys_dest += single_size; + phys_src += single_size; + count -= 1; + cont = (count != 0i32 && (data_src == data_dest) as i32 == is_repz) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + diff = size * (start_count - count); + add_reg_asize(EDI, diff); + add_reg_asize(ESI, diff); + set_ecx_asize(count); + *timestamp_counter = + (*timestamp_counter as u32).wrapping_add((start_count - count) as u32) as u32 as u32 + } + else { + loop { + data_dest = safe_read16(dest); + data_src = safe_read16(src); + dest += size; + add_reg_asize(EDI, size); + src += size; + add_reg_asize(ESI, size); + cont = + (decr_ecx_asize() != 0i32 && (data_src == data_dest) as i32 == is_repz) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + } + if 0 != cont { + *instruction_pointer = *previous_ip + } + cmp16(data_src, data_dest); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn cmpsw_no_rep() -> () { + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut data_src: i32 = 0; + let mut data_dest: i32 = 0; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -2i32 + } + else { + 2i32 + }; + data_dest = safe_read16(dest); + data_src = safe_read16(src); + add_reg_asize(EDI, size); + add_reg_asize(ESI, size); + cmp16(data_src, data_dest); +} +#[no_mangle] +pub unsafe extern "C" fn cmpsd_rep(mut prefix_flag: i32) -> () { + let mut diff: i32 = 0; + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut data_src: i32 = 0; + let mut data_dest: i32 = 0; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -4i32 + } + else { + 4i32 + }; + let mut count: i32 = get_reg_asize(ECX); + if count == 0i32 { + return; + } + else { + let mut cont: i32 = 0i32; + let mut start_count: i32 = count; + let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; + let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; + if 0 == dest & 3i32 && 0 == src & 3i32 { + let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; + let mut phys_src: i32 = (translate_address_read(src) >> 2i32) as i32; + let mut phys_dest: i32 = (translate_address_read(dest) >> 2i32) as i32; + cycle_counter = string_get_cycle_count2(size, src, dest); + loop { + data_dest = read_aligned32(phys_dest as u32); + data_src = read_aligned32(phys_src as u32); + phys_dest += single_size; + phys_src += single_size; + count -= 1; + cont = (count != 0i32 && (data_src == data_dest) as i32 == is_repz) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + diff = size * (start_count - count); + add_reg_asize(EDI, diff); + add_reg_asize(ESI, diff); + set_ecx_asize(count); + *timestamp_counter = + (*timestamp_counter as u32).wrapping_add((start_count - count) as u32) as u32 as u32 + } + else { + loop { + data_dest = safe_read32s(dest); + data_src = safe_read32s(src); + dest += size; + add_reg_asize(EDI, size); + src += size; + add_reg_asize(ESI, size); + cont = + (decr_ecx_asize() != 0i32 && (data_src == data_dest) as i32 == is_repz) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + } + if 0 != cont { + *instruction_pointer = *previous_ip + } + cmp32(data_src, data_dest); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn cmpsd_no_rep() -> () { + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut data_src: i32 = 0; + let mut data_dest: i32 = 0; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -4i32 + } + else { + 4i32 + }; + data_dest = safe_read32s(dest); + data_src = safe_read32s(src); + add_reg_asize(EDI, size); + add_reg_asize(ESI, size); + cmp32(data_src, data_dest); +} +#[no_mangle] +pub unsafe extern "C" fn stosb_rep() -> () { + let mut data: i32 = *reg8.offset(AL as isize) as i32; + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -1i32 + } + else { + 1i32 + }; + let mut count: i32 = get_reg_asize(ECX); + if count == 0i32 { + return; + } + else { + let mut cont: i32 = 0i32; + let mut start_count: i32 = count; + let mut cycle_counter: i32 = string_get_cycle_count(size, dest); + let mut phys_dest: i32 = translate_address_write(dest) as i32; + loop { + write8(phys_dest as u32, data); + phys_dest += size; + count -= 1; + cont = (count != 0i32) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + let mut diff: i32 = size * (start_count - count); + add_reg_asize(EDI, diff); + set_ecx_asize(count); + *timestamp_counter = + (*timestamp_counter as u32).wrapping_add((start_count - count) as u32) as u32 as u32; + if 0 != cont { + *instruction_pointer = *previous_ip + } + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn stosb_no_rep() -> () { + let mut data: i32 = *reg8.offset(AL as isize) as i32; + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -1i32 + } + else { + 1i32 + }; + safe_write8(dest, data); + add_reg_asize(EDI, size); +} +#[no_mangle] +pub unsafe extern "C" fn stosw_rep() -> () { + let mut diff: i32 = 0; + let mut data: i32 = *reg16.offset(AX as isize) as i32; + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -2i32 + } + else { + 2i32 + }; + let mut count: i32 = get_reg_asize(ECX); + if count == 0i32 { + return; + } + else { + let mut cont: i32 = 0i32; + let mut start_count: i32 = count; + let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; + if 0 == dest & 1i32 { + let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; + let mut phys_dest: i32 = (translate_address_write(dest) >> 1i32) as i32; + cycle_counter = string_get_cycle_count(size, dest); + loop { + write_aligned16(phys_dest as u32, data as u32); + phys_dest += single_size; + count -= 1; + cont = (count != 0i32) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + diff = size * (start_count - count); + add_reg_asize(EDI, diff); + set_ecx_asize(count); + *timestamp_counter = + (*timestamp_counter as u32).wrapping_add((start_count - count) as u32) as u32 as u32 + } + else { + loop { + safe_write16(dest, data); + dest += size; + add_reg_asize(EDI, size); + cont = (decr_ecx_asize() != 0i32) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + } + if 0 != cont { + *instruction_pointer = *previous_ip + } + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn stosw_no_rep() -> () { + let mut data: i32 = *reg16.offset(AX as isize) as i32; + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -2i32 + } + else { + 2i32 + }; + safe_write16(dest, data); + add_reg_asize(EDI, size); +} +#[no_mangle] +pub unsafe extern "C" fn stosd_rep() -> () { + let mut diff: i32 = 0; + let mut data: i32 = *reg32s.offset(EAX as isize); + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -4i32 + } + else { + 4i32 + }; + let mut count: i32 = get_reg_asize(ECX); + if count == 0i32 { + return; + } + else { + let mut cont: i32 = 0i32; + let mut start_count: i32 = count; + let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; + if 0 == dest & 3i32 { + let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; + let mut phys_dest: i32 = (translate_address_write(dest) >> 2i32) as i32; + cycle_counter = string_get_cycle_count(size, dest); + loop { + write_aligned32(phys_dest as u32, data); + phys_dest += single_size; + count -= 1; + cont = (count != 0i32) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + diff = size * (start_count - count); + add_reg_asize(EDI, diff); + set_ecx_asize(count); + *timestamp_counter = + (*timestamp_counter as u32).wrapping_add((start_count - count) as u32) as u32 as u32 + } + else { + loop { + safe_write32(dest, data); + dest += size; + add_reg_asize(EDI, size); + cont = (decr_ecx_asize() != 0i32) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + } + if 0 != cont { + *instruction_pointer = *previous_ip + } + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn stosd_no_rep() -> () { + let mut data: i32 = *reg32s.offset(EAX as isize); + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -4i32 + } + else { + 4i32 + }; + safe_write32(dest, data); + add_reg_asize(EDI, size); +} +#[no_mangle] +pub unsafe extern "C" fn lodsb_rep() -> () { + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -1i32 + } + else { + 1i32 + }; + let mut count: i32 = get_reg_asize(ECX); + if count == 0i32 { + return; + } + else { + let mut cont: i32 = 0i32; + let mut start_count: i32 = count; + let mut cycle_counter: i32 = string_get_cycle_count(size, src); + let mut phys_src: i32 = translate_address_read(src) as i32; + loop { + *reg8.offset(AL as isize) = read8(phys_src as u32) as u8; + phys_src += size; + count -= 1; + cont = (count != 0i32) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + let mut diff: i32 = size * (start_count - count); + add_reg_asize(ESI, diff); + set_ecx_asize(count); + *timestamp_counter = + (*timestamp_counter as u32).wrapping_add((start_count - count) as u32) as u32 as u32; + if 0 != cont { + *instruction_pointer = *previous_ip + } + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn lodsb_no_rep() -> () { + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -1i32 + } + else { + 1i32 + }; + *reg8.offset(AL as isize) = safe_read8(src) as u8; + add_reg_asize(ESI, size); +} +#[no_mangle] +pub unsafe extern "C" fn lodsw_rep() -> () { + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -2i32 + } + else { + 2i32 + }; + let mut count: u32 = get_reg_asize(ECX) as u32; + if count == 0i32 as u32 { + return; + } + else { + let mut cont: bool = 0 != 0i32; + let mut cycle_counter: u32 = MAX_COUNT_PER_CYCLE as u32; + loop { + *reg16.offset(AX as isize) = safe_read16(src) as u16; + src += size; + add_reg_asize(ESI, size); + cont = decr_ecx_asize() != 0i32; + if !(0 != cont as i32 && { + cycle_counter = cycle_counter.wrapping_sub(1); + 0 != cycle_counter + }) { + break; + } + } + if cont { + *instruction_pointer = *previous_ip + } + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn lodsw_no_rep() -> () { + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -2i32 + } + else { + 2i32 + }; + *reg16.offset(AX as isize) = safe_read16(src) as u16; + add_reg_asize(ESI, size); +} +#[no_mangle] +pub unsafe extern "C" fn lodsd_rep() -> () { + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -4i32 + } + else { + 4i32 + }; + let mut count: i32 = get_reg_asize(ECX); + if count == 0i32 { + return; + } + else { + let mut cont: i32 = 0i32; + let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; + loop { + *reg32s.offset(EAX as isize) = safe_read32s(src); + src += size; + add_reg_asize(ESI, size); + cont = (decr_ecx_asize() != 0i32) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + if 0 != cont { + *instruction_pointer = *previous_ip + } + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn lodsd_no_rep() -> () { + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -4i32 + } + else { + 4i32 + }; + *reg32s.offset(EAX as isize) = safe_read32s(src); + add_reg_asize(ESI, size); +} +#[no_mangle] +pub unsafe extern "C" fn scasb_rep(mut prefix_flag: i32) -> () { + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -1i32 + } + else { + 1i32 + }; + let mut data_dest: i32 = 0; + let mut data_src: i32 = *reg8.offset(AL as isize) as i32; + let mut count: i32 = get_reg_asize(ECX); + if count == 0i32 { + return; + } + else { + let mut cont: i32 = 0i32; + let mut start_count: i32 = count; + let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; + let mut cycle_counter: i32 = string_get_cycle_count(size, dest); + let mut phys_dest: i32 = translate_address_read(dest) as i32; + loop { + data_dest = read8(phys_dest as u32); + phys_dest += size; + count -= 1; + cont = (count != 0i32 && (data_src == data_dest) as i32 == is_repz) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + let mut diff: i32 = size * (start_count - count); + add_reg_asize(EDI, diff); + set_ecx_asize(count); + *timestamp_counter = + (*timestamp_counter as u32).wrapping_add((start_count - count) as u32) as u32 as u32; + if 0 != cont { + *instruction_pointer = *previous_ip + } + cmp8(data_src, data_dest); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn scasb_no_rep() -> () { + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -1i32 + } + else { + 1i32 + }; + let mut data_dest: i32 = 0; + let mut data_src: i32 = *reg8.offset(AL as isize) as i32; + data_dest = safe_read8(dest); + add_reg_asize(EDI, size); + cmp8(data_src, data_dest); +} +#[no_mangle] +pub unsafe extern "C" fn scasw_rep(mut prefix_flag: i32) -> () { + let mut diff: i32 = 0; + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -2i32 + } + else { + 2i32 + }; + let mut data_dest: i32 = 0; + let mut data_src: i32 = *reg16.offset(AL as isize) as i32; + let mut count: i32 = get_reg_asize(ECX); + if count == 0i32 { + return; + } + else { + let mut cont: i32 = 0i32; + let mut start_count: i32 = count; + let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; + let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; + if 0 == dest & 1i32 { + let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; + let mut phys_dest: i32 = (translate_address_read(dest) >> 1i32) as i32; + cycle_counter = string_get_cycle_count(size, dest); + loop { + data_dest = read_aligned16(phys_dest as u32); + phys_dest += single_size; + count -= 1; + cont = (count != 0i32 && (data_src == data_dest) as i32 == is_repz) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + diff = size * (start_count - count); + add_reg_asize(EDI, diff); + set_ecx_asize(count); + *timestamp_counter = + (*timestamp_counter as u32).wrapping_add((start_count - count) as u32) as u32 as u32 + } + else { + loop { + data_dest = safe_read16(dest); + dest += size; + add_reg_asize(EDI, size); + cont = + (decr_ecx_asize() != 0i32 && (data_src == data_dest) as i32 == is_repz) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + } + if 0 != cont { + *instruction_pointer = *previous_ip + } + cmp16(data_src, data_dest); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn scasw_no_rep() -> () { + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -2i32 + } + else { + 2i32 + }; + let mut data_dest: i32 = 0; + let mut data_src: i32 = *reg16.offset(AL as isize) as i32; + data_dest = safe_read16(dest); + add_reg_asize(EDI, size); + cmp16(data_src, data_dest); +} +#[no_mangle] +pub unsafe extern "C" fn scasd_rep(mut prefix_flag: i32) -> () { + let mut diff: i32 = 0; + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -4i32 + } + else { + 4i32 + }; + let mut data_dest: i32 = 0; + let mut data_src: i32 = *reg32s.offset(EAX as isize); + let mut count: i32 = get_reg_asize(ECX); + if count == 0i32 { + return; + } + else { + let mut cont: i32 = 0i32; + let mut start_count: i32 = count; + let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; + let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; + if 0 == dest & 3i32 { + let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; + let mut phys_dest: i32 = (translate_address_read(dest) >> 2i32) as i32; + cycle_counter = string_get_cycle_count(size, dest); + loop { + data_dest = read_aligned32(phys_dest as u32); + phys_dest += single_size; + count -= 1; + cont = (count != 0i32 && (data_src == data_dest) as i32 == is_repz) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + diff = size * (start_count - count); + add_reg_asize(EDI, diff); + set_ecx_asize(count); + *timestamp_counter = + (*timestamp_counter as u32).wrapping_add((start_count - count) as u32) as u32 as u32 + } + else { + loop { + data_dest = safe_read32s(dest); + dest += size; + add_reg_asize(EDI, size); + cont = + (decr_ecx_asize() != 0i32 && (data_src == data_dest) as i32 == is_repz) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + } + if 0 != cont { + *instruction_pointer = *previous_ip + } + cmp32(data_src, data_dest); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn scasd_no_rep() -> () { + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -4i32 + } + else { + 4i32 + }; + let mut data_dest: i32 = 0; + let mut data_src: i32 = *reg32s.offset(EAX as isize); + data_dest = safe_read32s(dest); + add_reg_asize(EDI, size); + cmp32(data_src, data_dest); +} +#[no_mangle] +pub unsafe extern "C" fn insb_rep() -> () { + let mut port: i32 = *reg16.offset(DX as isize) as i32; + if !test_privileges_for_io(port, 1i32) { + return; + } + else { + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -1i32 + } + else { + 1i32 + }; + let mut count: i32 = get_reg_asize(ECX); + if count == 0i32 { + return; + } + else { + let mut cont: i32 = 0i32; + let mut start_count: i32 = count; + let mut cycle_counter: i32 = string_get_cycle_count(size, dest); + let mut phys_dest: i32 = translate_address_write(dest) as i32; + loop { + write8(phys_dest as u32, io_port_read8(port)); + phys_dest += size; + count -= 1; + cont = (count != 0i32) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + let mut diff: i32 = size * (start_count - count); + add_reg_asize(EDI, diff); + set_ecx_asize(count); + *timestamp_counter = (*timestamp_counter as u32) + .wrapping_add((start_count - count) as u32) as u32 + as u32; + if 0 != cont { + *instruction_pointer = *previous_ip + } + return; + } + }; +} +#[no_mangle] +pub unsafe extern "C" fn insb_no_rep() -> () { + let mut port: i32 = *reg16.offset(DX as isize) as i32; + if !test_privileges_for_io(port, 1i32) { + return; + } + else { + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -1i32 + } + else { + 1i32 + }; + writable_or_pagefault(dest, 1i32); + safe_write8(dest, io_port_read8(port)); + add_reg_asize(EDI, size); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn insw_rep() -> () { + let mut diff: i32 = 0; + let mut port: i32 = *reg16.offset(DX as isize) as i32; + if !test_privileges_for_io(port, 2i32) { + return; + } + else { + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -2i32 + } + else { + 2i32 + }; + let mut count: i32 = get_reg_asize(ECX); + if count == 0i32 { + return; + } + else { + let mut cont: i32 = 0i32; + let mut start_count: i32 = count; + let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; + if 0 == dest & 1i32 { + let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; + let mut phys_dest: i32 = (translate_address_write(dest) >> 1i32) as i32; + cycle_counter = string_get_cycle_count(size, dest); + loop { + write_aligned16(phys_dest as u32, io_port_read16(port) as u32); + phys_dest += single_size; + count -= 1; + cont = (count != 0i32) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + diff = size * (start_count - count); + add_reg_asize(EDI, diff); + set_ecx_asize(count); + *timestamp_counter = (*timestamp_counter as u32) + .wrapping_add((start_count - count) as u32) + as u32 as u32 + } + else { + loop { + writable_or_pagefault(dest, 2i32); + safe_write16(dest, io_port_read16(port)); + dest += size; + add_reg_asize(EDI, size); + cont = (decr_ecx_asize() != 0i32) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + } + if 0 != cont { + *instruction_pointer = *previous_ip + } + return; + } + }; +} +#[no_mangle] +pub unsafe extern "C" fn insw_no_rep() -> () { + let mut port: i32 = *reg16.offset(DX as isize) as i32; + if !test_privileges_for_io(port, 2i32) { + return; + } + else { + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -2i32 + } + else { + 2i32 + }; + writable_or_pagefault(dest, 2i32); + safe_write16(dest, io_port_read16(port)); + add_reg_asize(EDI, size); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn insd_rep() -> () { + let mut diff: i32 = 0; + let mut port: i32 = *reg16.offset(DX as isize) as i32; + if !test_privileges_for_io(port, 4i32) { + return; + } + else { + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -4i32 + } + else { + 4i32 + }; + let mut count: i32 = get_reg_asize(ECX); + if count == 0i32 { + return; + } + else { + let mut cont: i32 = 0i32; + let mut start_count: i32 = count; + let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; + if 0 == dest & 3i32 { + let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; + let mut phys_dest: i32 = (translate_address_write(dest) >> 2i32) as i32; + cycle_counter = string_get_cycle_count(size, dest); + loop { + write_aligned32(phys_dest as u32, io_port_read32(port)); + phys_dest += single_size; + count -= 1; + cont = (count != 0i32) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + diff = size * (start_count - count); + add_reg_asize(EDI, diff); + set_ecx_asize(count); + *timestamp_counter = (*timestamp_counter as u32) + .wrapping_add((start_count - count) as u32) + as u32 as u32 + } + else { + loop { + writable_or_pagefault(dest, 4i32); + safe_write32(dest, io_port_read32(port)); + dest += size; + add_reg_asize(EDI, size); + cont = (decr_ecx_asize() != 0i32) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + } + if 0 != cont { + *instruction_pointer = *previous_ip + } + return; + } + }; +} +#[no_mangle] +pub unsafe extern "C" fn insd_no_rep() -> () { + let mut port: i32 = *reg16.offset(DX as isize) as i32; + if !test_privileges_for_io(port, 4i32) { + return; + } + else { + let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -4i32 + } + else { + 4i32 + }; + writable_or_pagefault(dest, 4i32); + safe_write32(dest, io_port_read32(port)); + add_reg_asize(EDI, size); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn outsb_rep() -> () { + let mut port: i32 = *reg16.offset(DX as isize) as i32; + if !test_privileges_for_io(port, 1i32) { + return; + } + else { + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -1i32 + } + else { + 1i32 + }; + let mut count: i32 = get_reg_asize(ECX); + if count == 0i32 { + return; + } + else { + let mut cont: i32 = 0i32; + let mut start_count: i32 = count; + let mut cycle_counter: i32 = string_get_cycle_count(size, src); + let mut phys_src: i32 = translate_address_read(src) as i32; + loop { + io_port_write8(port, read8(phys_src as u32)); + phys_src += size; + count -= 1; + cont = (count != 0i32) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + let mut diff: i32 = size * (start_count - count); + add_reg_asize(ESI, diff); + set_ecx_asize(count); + *timestamp_counter = (*timestamp_counter as u32) + .wrapping_add((start_count - count) as u32) as u32 + as u32; + if 0 != cont { + *instruction_pointer = *previous_ip + } + return; + } + }; +} +#[no_mangle] +pub unsafe extern "C" fn outsb_no_rep() -> () { + let mut port: i32 = *reg16.offset(DX as isize) as i32; + if !test_privileges_for_io(port, 1i32) { + return; + } + else { + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -1i32 + } + else { + 1i32 + }; + io_port_write8(port, safe_read8(src)); + add_reg_asize(ESI, size); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn outsw_rep() -> () { + let mut diff: i32 = 0; + let mut port: i32 = *reg16.offset(DX as isize) as i32; + if !test_privileges_for_io(port, 2i32) { + return; + } + else { + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -2i32 + } + else { + 2i32 + }; + let mut count: i32 = get_reg_asize(ECX); + if count == 0i32 { + return; + } + else { + let mut cont: i32 = 0i32; + let mut start_count: i32 = count; + let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; + if 0 == src & 1i32 { + let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; + let mut phys_src: i32 = (translate_address_read(src) >> 1i32) as i32; + cycle_counter = string_get_cycle_count(size, src); + loop { + io_port_write16(port, read_aligned16(phys_src as u32)); + phys_src += single_size; + count -= 1; + cont = (count != 0i32) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + diff = size * (start_count - count); + add_reg_asize(ESI, diff); + set_ecx_asize(count); + *timestamp_counter = (*timestamp_counter as u32) + .wrapping_add((start_count - count) as u32) + as u32 as u32 + } + else { + loop { + io_port_write16(port, safe_read16(src)); + src += size; + add_reg_asize(ESI, size); + cont = (decr_ecx_asize() != 0i32) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + } + if 0 != cont { + *instruction_pointer = *previous_ip + } + return; + } + }; +} +#[no_mangle] +pub unsafe extern "C" fn outsw_no_rep() -> () { + let mut port: i32 = *reg16.offset(DX as isize) as i32; + if !test_privileges_for_io(port, 2i32) { + return; + } + else { + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -2i32 + } + else { + 2i32 + }; + io_port_write16(port, safe_read16(src)); + add_reg_asize(ESI, size); + return; + }; +} +#[no_mangle] +pub unsafe extern "C" fn outsd_rep() -> () { + let mut diff: i32 = 0; + let mut port: i32 = *reg16.offset(DX as isize) as i32; + if !test_privileges_for_io(port, 4i32) { + return; + } + else { + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -4i32 + } + else { + 4i32 + }; + let mut count: i32 = get_reg_asize(ECX); + if count == 0i32 { + return; + } + else { + let mut cont: i32 = 0i32; + let mut start_count: i32 = count; + let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; + if 0 == src & 3i32 { + let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; + let mut phys_src: i32 = (translate_address_read(src) >> 2i32) as i32; + cycle_counter = string_get_cycle_count(size, src); + loop { + io_port_write32(port, read_aligned32(phys_src as u32)); + phys_src += single_size; + count -= 1; + cont = (count != 0i32) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + diff = size * (start_count - count); + add_reg_asize(ESI, diff); + set_ecx_asize(count); + *timestamp_counter = (*timestamp_counter as u32) + .wrapping_add((start_count - count) as u32) + as u32 as u32 + } + else { + loop { + io_port_write32(port, safe_read32s(src)); + src += size; + add_reg_asize(ESI, size); + cont = (decr_ecx_asize() != 0i32) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + } + if 0 != cont { + *instruction_pointer = *previous_ip + } + return; + } + }; +} +#[no_mangle] +pub unsafe extern "C" fn outsd_no_rep() -> () { + let mut port: i32 = *reg16.offset(DX as isize) as i32; + if !test_privileges_for_io(port, 4i32) { + return; + } + else { + let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { + -4i32 + } + else { + 4i32 + }; + io_port_write32(port, safe_read32s(src)); + add_reg_asize(ESI, size); + return; + }; +} From 11ee22176dc909a132a42d58e302093126915cac Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 14 Aug 2018 15:55:33 -0500 Subject: [PATCH 1188/2137] Temporarily disable jit --- src/rust/cpu2/cpu.rs | 82 ++++++++++++++++++++++++-------------------- src/rust/jit.rs | 1 + 2 files changed, 46 insertions(+), 37 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index f5dc700a..f433fce6 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1874,46 +1874,54 @@ pub unsafe extern "C" fn modrm_resolve(mut modrm_byte: i32) -> i32 { } #[no_mangle] pub unsafe extern "C" fn cycle_internal() -> () { - let mut wasm_table_index: u16 = 0; - let mut initial_tsc: i32 = 0; - let mut initial_state: u16 = 0; profiler_stat_increment(S_CYCLE_INTERNAL); - *previous_ip = *instruction_pointer; - let mut phys_addr: u32 = get_phys_eip() as u32; - let mut state_flags: cached_state_flags = pack_current_state_flags(); - let mut entry: u32 = jit_find_cache_entry(phys_addr, state_flags); - if 0 != entry { - profiler_stat_increment(S_RUN_FROM_CACHE); - initial_tsc = *timestamp_counter as i32; - wasm_table_index = (entry & 65535i32 as u32) as u16; - initial_state = (entry >> 16i32) as u16; - call_indirect1( - (wasm_table_index as u32).wrapping_add(256i32 as u32) as i32, - initial_state as i32, - ); - clear_current_cpu_exception(); - profiler_stat_increment_by( - S_RUN_FROM_CACHE_STEPS, - (*timestamp_counter).wrapping_sub(initial_tsc as u32) as i32, - ); + if false { + let mut wasm_table_index: u16 = 0; + let mut initial_tsc: i32 = 0; + let mut initial_state: u16 = 0; + *previous_ip = *instruction_pointer; + let mut phys_addr: u32 = return_on_pagefault!(get_phys_eip()) as u32; + let mut state_flags: cached_state_flags = pack_current_state_flags(); + let mut entry: u32 = jit_find_cache_entry(phys_addr, state_flags); + if 0 != entry { + profiler_stat_increment(S_RUN_FROM_CACHE); + initial_tsc = *timestamp_counter as i32; + wasm_table_index = (entry & 65535i32 as u32) as u16; + initial_state = (entry >> 16i32) as u16; + call_indirect1( + (wasm_table_index as u32).wrapping_add(256i32 as u32) as i32, + initial_state as i32, + ); + clear_current_cpu_exception(); + profiler_stat_increment_by( + S_RUN_FROM_CACHE_STEPS, + (*timestamp_counter).wrapping_sub(initial_tsc as u32) as i32, + ); + } + else { + if DEBUG { + dbg_assert!(!must_not_fault); + must_not_fault = 0 != 1i32 + } + jit_increase_hotness_and_maybe_compile(phys_addr, get_seg_cs() as u32, state_flags); + if DEBUG { + dbg_assert!(must_not_fault); + must_not_fault = 0 != 0i32 + } + let mut initial_tsc_0: i32 = *timestamp_counter as i32; + jit_run_interpreted(phys_addr as i32); + profiler_stat_increment_by( + S_RUN_INTERPRETED_STEPS, + (*timestamp_counter).wrapping_sub(initial_tsc_0 as u32) as i32, + ); + }; } else { - if DEBUG { - dbg_assert!(!must_not_fault); - must_not_fault = 0 != 1i32 - } - jit_increase_hotness_and_maybe_compile(phys_addr, get_seg_cs() as u32, state_flags); - if DEBUG { - dbg_assert!(must_not_fault); - must_not_fault = 0 != 0i32 - } - let mut initial_tsc_0: i32 = *timestamp_counter as i32; - jit_run_interpreted(phys_addr as i32); - profiler_stat_increment_by( - S_RUN_INTERPRETED_STEPS, - (*timestamp_counter).wrapping_sub(initial_tsc_0 as u32) as i32, - ); - }; + *previous_ip = *instruction_pointer; + *timestamp_counter += 1; + let opcode = return_on_pagefault!(read_imm8()); + run_instruction(opcode | (*is_32 as i32) << 8); + } } #[no_mangle] pub unsafe extern "C" fn get_phys_eip() -> i32 { diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 87469d8f..de2193b9 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -1157,6 +1157,7 @@ pub fn jit_increase_hotness_and_maybe_compile( cs_offset: u32, state_flags: CachedStateFlags, ) { + return; record_entry_point(ctx, phys_address); let page = Page::page_of(phys_address); let address_hash = jit_hot_hash_page(page) as usize; From a88420910d6d26b9c4bc9c89e43e311e9a227aae Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 14 Aug 2018 16:07:54 -0500 Subject: [PATCH 1189/2137] Handle pagefaults without JS exceptions This commit makes the return type of most basic memory access primitives Result, where the Err(()) case means a page fault happened, the instruction should be aborted and execution should continue at the page fault handler. The following primites have a Result return type: safe_{read,write}*, translate_address_*, read_imm*, writable_or_pagefault, get_phys_eip, modrm_resolve, push*, pop*. Any instruction needs to handle the page fault cases and abort execution appropriately. The return_on_pagefault! macro has been provided to get the same behaviour as the previously used JS exceptions (local to the function). Calls from JavaScript abort on a pagefault, except for writable_or_pagefault, which returns a boolean. JS needs to check before calling any function that may pagefault. This commit does not yet pervasively apply return_on_pagefault!, this will be added in the next commit. Jitted code does not yet properly handle the new form of page faults, this will be added in a later commit. --- gen/generate_interpreter.js | 52 ++-- gen/x86_table.js | 4 +- src/cpu.js | 139 ++++++----- src/rust/cpu2/cpu.rs | 349 +++++++++++++++------------ src/rust/cpu2/instruction_helpers.rs | 69 ++++-- src/rust/cpu2/misc_instr.rs | 181 +++++++------- src/rust/cpu2/modrm.rs | 297 ++++++++++------------- src/rust/js_api.rs | 43 ++++ src/rust/lib.rs | 4 + src/rust/paging.rs | 8 + 10 files changed, 622 insertions(+), 524 deletions(-) create mode 100644 src/rust/js_api.rs create mode 100644 src/rust/paging.rs diff --git a/gen/generate_interpreter.js b/gen/generate_interpreter.js index 0786e614..5d454091 100755 --- a/gen/generate_interpreter.js +++ b/gen/generate_interpreter.js @@ -26,6 +26,11 @@ console.assert( gen_table(); +function wrap_imm_call(imm) +{ + return `match ${imm} { Ok(o) => o, Err(()) => return }`; +} + function gen_read_imm_call(op, size_variant) { let size = (op.os || op.opcode % 2 === 1) ? size_variant : 8; @@ -34,18 +39,18 @@ function gen_read_imm_call(op, size_variant) { if(op.imm8) { - return "read_imm8()"; + return wrap_imm_call("read_imm8()"); } else if(op.imm8s) { - return "read_imm8s()"; + return wrap_imm_call("read_imm8s()"); } else { if(op.immaddr) { // immaddr: depends on address size - return "read_moffs()"; + return wrap_imm_call("read_moffs()"); } else { @@ -53,12 +58,12 @@ function gen_read_imm_call(op, size_variant) if(op.imm1632 && size === 16 || op.imm16) { - return "read_imm16()"; + return wrap_imm_call("read_imm16()"); } else { console.assert(op.imm1632 && size === 32 || op.imm32); - return "read_imm32s()"; + return wrap_imm_call("read_imm32s()"); } } } @@ -124,7 +129,7 @@ function gen_instruction_body(encodings, size) if(encoding.e) { - code.push("let modrm_byte = read_imm8();"); + code.push(`let modrm_byte = ${wrap_imm_call("read_imm8()")};`); } if(has_66.length || has_F2.length || has_F3.length) @@ -246,19 +251,11 @@ function gen_instruction_body_after_fixed_g(encoding, size) const instruction_name = make_instruction_name(encoding, size); - let modrm_resolve_prefix = undefined; - - if(encoding.requires_prefix_call) - { - modrm_resolve_prefix = gen_call(instruction_name + "_mem_pre"); - } - const imm_read = gen_read_imm_call(encoding, size); if(encoding.ignore_mod) { console.assert(!imm_read, "Unexpected instruction (ignore mod with immediate value)"); - console.assert(!modrm_resolve_prefix, "Unexpected instruction (ignore mod with prefix call)"); // Has modrm byte, but the 2 mod bits are ignored and both // operands are always registers (0f20-0f24) @@ -271,7 +268,18 @@ function gen_instruction_body_after_fixed_g(encoding, size) } else { - const mem_args = ["modrm_resolve(modrm_byte)"]; + let mem_args; + + if(encoding.custom_modrm_resolve) + { + // requires special handling around modrm_resolve + mem_args = ["modrm_byte"]; + } + else + { + mem_args = ["match modrm_resolve(modrm_byte) { Ok(a) => a, Err(()) => return }"]; + } + const reg_args = ["modrm_byte & 7"]; if(encoding.fixed_g === undefined) @@ -294,7 +302,6 @@ function gen_instruction_body_after_fixed_g(encoding, size) { condition: "modrm_byte < 0xC0", body: [].concat( - modrm_resolve_prefix ? [modrm_resolve_prefix] : [], gen_call(`${instruction_name}_mem`, mem_args) ), } @@ -319,12 +326,12 @@ function gen_instruction_body_after_fixed_g(encoding, size) if(encoding.extra_imm16) { console.assert(imm_read); - args.push("read_imm16()"); + args.push(wrap_imm_call("read_imm16()")); } else if(encoding.extra_imm8) { console.assert(imm_read); - args.push("read_imm8()"); + args.push(wrap_imm_call("read_imm8()")); } return [].concat( @@ -397,11 +404,12 @@ function gen_table() if(to_generate.interpreter) { const code = [ + "#![cfg_attr(rustfmt, rustfmt_skip)]", + "use cpu2::cpu::*;", "use cpu2::instructions::*;", "use cpu2::global_pointers::*;", - "#[cfg_attr(rustfmt, rustfmt_skip)]", "pub unsafe fn run(opcode: u32) {", table, "}", @@ -466,11 +474,12 @@ function gen_table() if(to_generate.interpreter0f_16) { const code = [ + "#![cfg_attr(rustfmt, rustfmt_skip)]", + "use cpu2::cpu::*;", "use cpu2::instructions_0f::*;", "use cpu2::global_pointers::*;", - "#[cfg_attr(rustfmt, rustfmt_skip)]", "pub unsafe fn run(opcode: u8) {", table0f_16, "}", @@ -486,11 +495,12 @@ function gen_table() if(to_generate.interpreter0f_32) { const code = [ + "#![cfg_attr(rustfmt, rustfmt_skip)]", + "use cpu2::cpu::*;", "use cpu2::instructions_0f::*;", "use cpu2::global_pointers::*;", - "#[cfg_attr(rustfmt, rustfmt_skip)]", "pub unsafe fn run(opcode: u8) {", table0f_32, "}", diff --git a/gen/x86_table.js b/gen/x86_table.js index b85d874e..b892db5a 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -107,9 +107,9 @@ const encodings = [ { opcode: 0x8B, custom: 1, nonfaulting: 1, os: 1, e: 1, }, { opcode: 0x8C, block_boundary: 1, os: 1, e: 1, skip: 1, }, // mov reg, sreg: block_boundary as it can trigger #ud - { opcode: 0x8D, reg_ud: 1, memory_nonfaulting: 1, os: 1, e: 1, requires_prefix_call: 1, custom: 1, }, // lea + { opcode: 0x8D, reg_ud: 1, memory_nonfaulting: 1, os: 1, e: 1, custom_modrm_resolve: 1, custom: 1, }, // lea { opcode: 0x8E, block_boundary: 1, e: 1, skip: 1, }, // mov sreg - { opcode: 0x8F, os: 1, e: 1, fixed_g: 0, requires_prefix_call: 1, custom: 1, }, // pop r/m + { opcode: 0x8F, os: 1, e: 1, fixed_g: 0, custom_modrm_resolve: 1, custom: 1, block_boundary: 1, }, // pop r/m { opcode: 0x90, custom: 1, nonfaulting: 1, }, { opcode: 0x91, nonfaulting: 1, os: 1, }, diff --git a/src/cpu.js b/src/cpu.js index ef2f1cd9..29ecfff2 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -296,8 +296,7 @@ CPU.prototype.wasm_patch = function(wm) this.trigger_np = this.v86oxide.exports["trigger_np"]; this.trigger_ss = this.v86oxide.exports["trigger_ss"]; - //this.do_many_cycles_unsafe = this.wm.exports["_do_many_cycles_unsafe"]; - this.do_many_cycles_unsafe = this.v86oxide.exports["do_many_cycles_unsafe"]; + this.do_many_cycles_native = this.v86oxide.exports["do_many_cycles_native"]; this.cycle_internal = this.v86oxide.exports["cycle_internal"]; this.read8 = this.v86oxide.exports["read8"]; @@ -308,27 +307,27 @@ CPU.prototype.wasm_patch = function(wm) this.write32 = this.v86oxide.exports["write32"]; this.in_mapped_range = this.v86oxide.exports["in_mapped_range"]; - this.push16 = this.v86oxide.exports["push16"]; - this.push32 = this.v86oxide.exports["push32"]; - this.pop16 = this.v86oxide.exports["pop16"]; - this.pop32s = this.v86oxide.exports["pop32s"]; + this.push16 = this.v86oxide.exports["push16_js"]; + this.push32 = this.v86oxide.exports["push32_js"]; + this.pop16 = this.v86oxide.exports["pop16_js"]; + this.pop32s = this.v86oxide.exports["pop32s_js"]; this.set_stack_reg = this.v86oxide.exports["set_stack_reg"]; - this.translate_address_read = this.v86oxide.exports["translate_address_read"]; - this.translate_address_system_read = this.v86oxide.exports["translate_address_system_read"]; - this.translate_address_system_write = this.v86oxide.exports["translate_address_system_write"]; + this.translate_address_read = this.v86oxide.exports["translate_address_read_js"]; + this.translate_address_system_read = this.v86oxide.exports["translate_address_system_read_js"]; + this.translate_address_system_write = this.v86oxide.exports["translate_address_system_write_js"]; this.get_seg = this.v86oxide.exports["get_seg"]; this.adjust_stack_reg = this.v86oxide.exports["adjust_stack_reg"]; this.get_real_eip = this.v86oxide.exports["get_real_eip"]; this.get_stack_pointer = this.v86oxide.exports["get_stack_pointer"]; - this.writable_or_pagefault = this.v86oxide.exports["writable_or_pagefault"]; - this.safe_write32 = this.v86oxide.exports["safe_write32"]; - this.safe_read32s = this.v86oxide.exports["safe_read32s"]; - this.safe_write16 = this.v86oxide.exports["safe_write16"]; - this.safe_read16 = this.v86oxide.exports["safe_read16"]; + this.writable_or_pagefault = this.v86oxide.exports["writable_or_pagefault_js"]; + this.safe_write32 = this.v86oxide.exports["safe_write32_js"]; + this.safe_read32s = this.v86oxide.exports["safe_read32s_js"]; + this.safe_write16 = this.v86oxide.exports["safe_write16_js"]; + this.safe_read16 = this.v86oxide.exports["safe_read16_js"]; this.clear_tlb = this.v86oxide.exports["clear_tlb"]; this.full_clear_tlb = this.v86oxide.exports["full_clear_tlb"]; @@ -596,8 +595,6 @@ CPU.prototype.reboot_internal = function() { this.reset(); this.load_bios(); - - throw MAGIC_CPU_EXCEPTION; }; CPU.prototype.reset = function() @@ -1230,13 +1227,7 @@ CPU.prototype.do_many_cycles = function() var start_time = v86.microtick(); } - try { - this.do_many_cycles_unsafe(); - } - catch(e) - { - this.exception_cleanup(e); - } + this.do_many_cycles_native(); if(ENABLE_PROFILER) { @@ -1250,28 +1241,10 @@ CPU.prototype.do_many_cycles = function() /** @export */ CPU.prototype.cycle = function() { - try { - // XXX: May do several cycles - this.cycle_internal(); - } - catch(e) - { - this.exception_cleanup(e); - } + // XXX: May do several cycles + this.cycle_internal(); }; -// Some functions must not be inlined, because then more code is in the -// deoptimized try-catch block. -// This trick is a bit ugly, but it works without further complication. -if(typeof window !== "undefined") -{ - window["__no_inline_for_closure_compiler__"] = [ - CPU.prototype.exception_cleanup, - CPU.prototype.do_many_cycles_unsafe, - CPU.prototype.do_many_cycles, - ]; -} - var seen_code = {}; var seen_code_uncompiled = {}; @@ -1752,7 +1725,10 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, ha var stack_space = (is_16 ? 2 : 4) * (3 + (has_error_code === true)); // XXX: with current cpl or with cpl 0? - this.writable_or_pagefault(this.get_stack_pointer(-stack_space), stack_space); + if(!this.writable_or_pagefault(this.get_stack_pointer(-stack_space), stack_space)) + { + return; + } // no exceptions below } @@ -1821,10 +1797,7 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, ha { if((this.flags[0] & flag_interrupt) && !(old_flags & flag_interrupt)) { - if(!this.page_fault[0]) // XXX - { - this.handle_irqs(); - } + this.handle_irqs(); } } } @@ -2316,13 +2289,21 @@ CPU.prototype.far_jump = function(eip, selector, is_call) { if(this.is_osize_32()) { - this.writable_or_pagefault(this.get_stack_pointer(-8), 8); + if(!this.writable_or_pagefault(this.get_stack_pointer(-8), 8)) + { + return; + } + this.push32(this.sreg[reg_cs]); this.push32(this.get_real_eip()); } else { - this.writable_or_pagefault(this.get_stack_pointer(-4), 4); + if(!this.writable_or_pagefault(this.get_stack_pointer(-4), 4)) + { + return; + } + this.push16(this.sreg[reg_cs]); this.push16(this.get_real_eip()); } @@ -2460,15 +2441,17 @@ CPU.prototype.far_jump = function(eip, selector, is_call) } if(ss_info.size) { - //try { - this.writable_or_pagefault(ss_info.base + new_esp - stack_space | 0, stack_space); // , cs_info.dpl - //} catch(e) { debugger; } + if(this.writable_or_pagefault(ss_info.base + new_esp - stack_space | 0, stack_space)) // , cs_info.dpl + { + return; + } } else { - //try { - this.writable_or_pagefault(ss_info.base + (new_esp - stack_space & 0xFFFF) | 0, stack_space); // , cs_info.dpl - //} catch(e) { debugger; } + if(this.writable_or_pagefault(ss_info.base + (new_esp - stack_space & 0xFFFF) | 0, stack_space)) // , cs_info.dpl + { + return; + } } var old_esp = this.reg32s[reg_esp]; @@ -2539,13 +2522,21 @@ CPU.prototype.far_jump = function(eip, selector, is_call) { if(is_16) { - this.writable_or_pagefault(this.get_stack_pointer(-4), 4); + if(!this.writable_or_pagefault(this.get_stack_pointer(-4), 4)) + { + return; + } + this.push16(this.sreg[reg_cs]); this.push16(this.get_real_eip()); } else { - this.writable_or_pagefault(this.get_stack_pointer(-8), 8); + if(!this.writable_or_pagefault(this.get_stack_pointer(-8), 8)) + { + return; + } + this.push32(this.sreg[reg_cs]); this.push32(this.get_real_eip()); } @@ -2622,13 +2613,21 @@ CPU.prototype.far_jump = function(eip, selector, is_call) { if(this.is_osize_32()) { - this.writable_or_pagefault(this.get_stack_pointer(-8), 8); + if(!this.writable_or_pagefault(this.get_stack_pointer(-8), 8)) + { + return; + } + this.push32(this.sreg[reg_cs]); this.push32(this.get_real_eip()); } else { - this.writable_or_pagefault(this.get_stack_pointer(-4), 4); + if(!this.writable_or_pagefault(this.get_stack_pointer(-4), 4)) + { + return; + } + this.push16(this.sreg[reg_cs]); this.push16(this.get_real_eip()); } @@ -2730,7 +2729,10 @@ CPU.prototype.do_task_switch = function(selector, error_code) old_eflags &= ~flag_nt; } - this.writable_or_pagefault(tsr_offset, 0x66); + if(this.writable_or_pagefault(tsr_offset, 0x66)) + { + return; + } //this.safe_write32(tsr_offset + TSR_CR3, this.cr[3]); @@ -2944,10 +2946,9 @@ CPU.prototype.pic_call_irq = function(int) CPU.prototype.handle_irqs = function() { - dbg_assert(!this.page_fault[0]); //dbg_assert(this.prefixes[0] === 0); - if((this.flags[0] & flag_interrupt) && !this.page_fault[0]) + if((this.flags[0] & flag_interrupt)) { if(this.devices.pic) { @@ -3740,7 +3741,11 @@ CPU.prototype.enter16 = function(size, nesting_level) } // check if write to final stack pointer would case a page fault - this.writable_or_pagefault(ss + (frame_temp - size & ss_mask), 2); + if(!this.writable_or_pagefault(ss + (frame_temp - size & ss_mask), 2)) + { + return; + } + this.safe_write16(ss + (frame_temp & ss_mask) | 0, this.reg16[reg_bp]); this.reg16[reg_bp] = frame_temp; this.adjust_stack_reg(-size - 2); @@ -3768,7 +3773,11 @@ CPU.prototype.enter32 = function(size, nesting_level) } // check if write to final stack pointer would case a page fault - this.writable_or_pagefault(ss + (frame_temp - size & ss_mask), 4); + if(!this.writable_or_pagefault(ss + (frame_temp - size & ss_mask), 4)) + { + return; + } + this.safe_write32(ss + (frame_temp & ss_mask) | 0, this.reg32s[reg_ebp]); this.reg32s[reg_ebp] = frame_temp; this.adjust_stack_reg(-size - 4); diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index f433fce6..86f70292 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -8,6 +8,8 @@ )] #![feature(extern_types, libc)] +use cpu2::modrm::{resolve_modrm16, resolve_modrm32}; + extern "C" { #[no_mangle] @@ -64,8 +66,6 @@ extern "C" { #[no_mangle] fn write_aligned32(addr: u32, value: i32) -> (); #[no_mangle] - fn throw_cpu_exception() -> (); - #[no_mangle] fn call_interrupt_vector( interrupt_nr: i32, is_software_int: bool, @@ -97,10 +97,6 @@ extern "C" { #[no_mangle] static protected_mode: *mut bool; #[no_mangle] - fn resolve_modrm16(modrm_byte: i32) -> i32; - #[no_mangle] - fn resolve_modrm32(modrm_byte: i32) -> i32; - #[no_mangle] fn run_instruction(opcode: i32) -> (); #[no_mangle] fn logop(_: i32, _: i32) -> (); @@ -248,16 +244,16 @@ pub const S_SAFE_READ32_SLOW_NOT_USER: stat_name = 18; #[derive(Copy, Clone)] #[repr(C)] pub union reg64 { - i8_0: [i8; 8], - i16_0: [i16; 4], - i32_0: [i32; 2], - i64_0: [i64; 1], - u8_0: [u8; 8], - u16_0: [u16; 4], - u32_0: [u32; 2], - u64_0: [u64; 1], - f32_0: [f32; 2], - f64_0: [f64; 1], + pub i8_0: [i8; 8], + pub i16_0: [i16; 4], + pub i32_0: [i32; 2], + pub i64_0: [i64; 1], + pub u8_0: [u8; 8], + pub u16_0: [u16; 4], + pub u32_0: [u32; 2], + pub u64_0: [u64; 1], + pub f32_0: [f32; 2], + pub f64_0: [f64; 1], } pub const S_SAFE_READ32_SLOW_IN_MAPPED_RANGE: stat_name = 19; @@ -284,16 +280,16 @@ pub const S_SAFE_WRITE32_SLOW_NOT_USER: stat_name = 23; #[derive(Copy, Clone)] #[repr(C)] pub union reg128 { - i8_0: [i8; 16], - i16_0: [i16; 8], - i32_0: [i32; 4], - i64_0: [i64; 2], - u8_0: [u8; 16], - u16_0: [u16; 8], - u32_0: [u32; 4], - u64_0: [u64; 2], - f32_0: [f32; 4], - f64_0: [f64; 2], + pub i8_0: [i8; 16], + pub i16_0: [i16; 8], + pub i32_0: [i32; 4], + pub i64_0: [i64; 2], + pub u8_0: [u8; 16], + pub u16_0: [u16; 8], + pub u32_0: [u32; 4], + pub u64_0: [u64; 2], + pub f32_0: [f32; 4], + pub f64_0: [f64; 2], } pub const S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE: stat_name = 24; pub const S_SAFE_WRITE32_SLOW_NOT_VALID: stat_name = 22; @@ -1360,15 +1356,15 @@ pub unsafe extern "C" fn get_eflags() -> i32 { | (getof() as i32) << 11i32; } #[no_mangle] -pub unsafe extern "C" fn translate_address_read(mut address: i32) -> u32 { +pub unsafe extern "C" fn translate_address_read(mut address: i32) -> Result { let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); let mut user: bool = *cpl.offset(0isize) as i32 == 3i32; if entry & (TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0i32 }) == TLB_VALID { - return (entry & !4095i32 ^ address) as u32; + return Ok((entry & !4095i32 ^ address) as u32); } else { - return (do_page_translation(address, 0 != 0i32, user) | address & 4095i32) as u32; + return Ok((do_page_translation(address, 0 != 0i32, user)? | address & 4095i32) as u32); }; } #[no_mangle] @@ -1376,7 +1372,7 @@ pub unsafe extern "C" fn do_page_translation( mut addr: i32, mut for_writing: bool, mut user: bool, -) -> i32 { +) -> Result { let mut can_write: bool = 0 != 1i32; let mut global: bool = false; let mut allow_user: bool = 0 != 1i32; @@ -1401,15 +1397,14 @@ pub unsafe extern "C" fn do_page_translation( c_comment!(("- prevent execution of the function that triggered this call")); *cr.offset(2isize) = addr; trigger_pagefault(for_writing, user, 0 != 0i32); - c_comment!(("never reached as trigger_pagefault throws")); - dbg_assert!(0 != 0i32); + return Err(()); } if page_dir_entry & PAGE_TABLE_RW_MASK == 0i32 && !kernel_write_override { can_write = 0 != 0i32; if for_writing { *cr.offset(2isize) = addr; trigger_pagefault(for_writing, user, 0 != 1i32); - dbg_assert!(0 != 0i32); + return Err(()); } } if page_dir_entry & PAGE_TABLE_USER_MASK == 0i32 { @@ -1418,7 +1413,7 @@ pub unsafe extern "C" fn do_page_translation( c_comment!(("Page Fault: page table accessed by non-supervisor")); *cr.offset(2isize) = addr; trigger_pagefault(for_writing, user, 0 != 1i32); - dbg_assert!(0 != 0i32); + return Err(()); } } if 0 != page_dir_entry & PAGE_TABLE_PSE_MASK && 0 != *cr.offset(4isize) & CR4_PSE { @@ -1444,14 +1439,14 @@ pub unsafe extern "C" fn do_page_translation( if page_table_entry & PAGE_TABLE_PRESENT_MASK == 0i32 { *cr.offset(2isize) = addr; trigger_pagefault(for_writing, user, 0 != 0i32); - dbg_assert!(0 != 0i32); + return Err(()); } if page_table_entry & PAGE_TABLE_RW_MASK == 0i32 && !kernel_write_override { can_write = 0 != 0i32; if for_writing { *cr.offset(2isize) = addr; trigger_pagefault(for_writing, user, 0 != 1i32); - dbg_assert!(0 != 0i32); + return Err(()); } } if page_table_entry & PAGE_TABLE_USER_MASK == 0i32 { @@ -1459,7 +1454,7 @@ pub unsafe extern "C" fn do_page_translation( if user { *cr.offset(2isize) = addr; trigger_pagefault(for_writing, user, 0 != 1i32); - dbg_assert!(0 != 0i32); + return Err(()); } } c_comment!(("set the accessed and dirty bits")); @@ -1551,7 +1546,7 @@ pub unsafe extern "C" fn do_page_translation( }; dbg_assert!((high ^ page << 12i32) & 4095i32 == 0i32); *tlb_data.offset(page as isize) = high ^ page << 12i32 | info_bits; - return high; + return Ok(high); } #[no_mangle] pub static mut CHECK_TLB_INVARIANTS: bool = unsafe { 0 != 0i32 }; @@ -1634,41 +1629,40 @@ pub unsafe extern "C" fn trigger_pagefault( dbg_assert!(0 != 0i32); } } - if *page_fault { - dbg_log_c!(("double fault")); - dbg_trace(); - dbg_assert!(0 != 0i32); - } + //if *page_fault { + // dbg_log_c!(("double fault")); + // dbg_trace(); + // dbg_assert!(0 != 0i32); + //} c_comment!(("invalidate tlb entry")); let mut page: i32 = (*cr.offset(2isize) as u32 >> 12i32) as i32; *tlb_data.offset(page as isize) = 0i32; *instruction_pointer = *previous_ip; - *page_fault = 0 != 1i32; + //*page_fault = 0 != 1i32; call_interrupt_vector( CPU_EXCEPTION_PF, 0 != 0i32, 0 != 1i32, (user as i32) << 2i32 | (write as i32) << 1i32 | present as i32, ); - profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); - throw_cpu_exception(); + //profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); } #[no_mangle] pub static mut must_not_fault: bool = unsafe { 0 != 0i32 }; #[no_mangle] pub static mut DEBUG: bool = unsafe { 0 != 1i32 }; #[no_mangle] -pub unsafe extern "C" fn translate_address_write(mut address: i32) -> u32 { +pub unsafe extern "C" fn translate_address_write(mut address: i32) -> Result { let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); let mut user: bool = *cpl.offset(0isize) as i32 == 3i32; if entry & (TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0i32 } | TLB_READONLY) == TLB_VALID { - return (entry & !4095i32 ^ address) as u32; + return Ok((entry & !4095i32 ^ address) as u32); } else { - return (do_page_translation(address, 0 != 1i32, user) | address & 4095i32) as u32; + return Ok((do_page_translation(address, 0 != 1i32, user)? | address & 4095i32) as u32); }; } #[no_mangle] @@ -1715,11 +1709,11 @@ pub unsafe extern "C" fn check_tlb_invariants() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn writable_or_pagefault(mut addr: i32, mut size: i32) -> () { +pub unsafe extern "C" fn writable_or_pagefault(mut addr: i32, mut size: i32) -> Result<(), ()> { dbg_assert!(size < 4096i32); dbg_assert!(size > 0i32); if *cr.offset(0isize) & CR0_PG == 0i32 { - return; + return Ok(()); } else { let mut user: bool = *cpl.offset(0isize) as i32 == 3i32; @@ -1728,57 +1722,59 @@ pub unsafe extern "C" fn writable_or_pagefault(mut addr: i32, mut size: i32) -> let mut expect: i32 = TLB_VALID; let mut page: i32 = (addr as u32 >> 12i32) as i32; if *tlb_data.offset(page as isize) & mask != expect { - do_page_translation(addr, 0 != 1i32, user); + do_page_translation(addr, 0 != 1i32, user)?; } let mut next_page: i32 = ((addr + size - 1i32) as u32 >> 12i32) as i32; if page != next_page { dbg_assert!(next_page == page + 1i32); c_comment!(("XXX: possibly out of bounds")); if *tlb_data.offset(next_page as isize) & mask != expect { - do_page_translation(next_page << 12i32, 0 != 1i32, user); + do_page_translation(next_page << 12i32, 0 != 1i32, user)?; } } - return; + return Ok(()); }; } #[no_mangle] -pub unsafe extern "C" fn read_imm8() -> i32 { +pub unsafe extern "C" fn read_imm8() -> Result { let mut eip: i32 = *instruction_pointer; if 0 != eip & !4095i32 ^ *last_virt_eip { - *eip_phys = (translate_address_read(eip) ^ eip as u32) as i32; + *eip_phys = (translate_address_read(eip)? ^ eip as u32) as i32; *last_virt_eip = eip & !4095i32 } dbg_assert!(!in_mapped_range((*eip_phys ^ eip) as u32)); let mut data8: i32 = *mem8.offset((*eip_phys ^ eip) as isize) as i32; *instruction_pointer = eip + 1i32; - return data8; + return Ok(data8); } #[no_mangle] -pub unsafe extern "C" fn read_imm8s() -> i32 { return read_imm8() << 24i32 >> 24i32; } +pub unsafe extern "C" fn read_imm8s() -> Result { + return Ok(read_imm8()? << 24i32 >> 24i32); +} #[no_mangle] -pub unsafe extern "C" fn read_imm16() -> i32 { +pub unsafe extern "C" fn read_imm16() -> Result { c_comment!(("Two checks in one comparison:")); c_comment!(("1. Did the high 20 bits of eip change")); c_comment!(("or 2. Are the low 12 bits of eip 0xFFF (and this read crosses a page boundary)")); if (*instruction_pointer ^ *last_virt_eip) as u32 > 4094i32 as u32 { - return read_imm8() | read_imm8() << 8i32; + return Ok(read_imm8()? | read_imm8()? << 8i32); } else { let mut data16: i32 = read16((*eip_phys ^ *instruction_pointer) as u32); *instruction_pointer = *instruction_pointer + 2i32; - return data16; + return Ok(data16); }; } #[no_mangle] -pub unsafe extern "C" fn read_imm32s() -> i32 { +pub unsafe extern "C" fn read_imm32s() -> Result { c_comment!(("Analogue to the above comment")); if (*instruction_pointer ^ *last_virt_eip) as u32 > 4092i32 as u32 { - return read_imm16() | read_imm16() << 16i32; + return Ok(read_imm16()? | read_imm16()? << 16i32); } else { let mut data32: i32 = read32s((*eip_phys ^ *instruction_pointer) as u32); *instruction_pointer = *instruction_pointer + 4i32; - return data32; + return Ok(data32); }; } #[no_mangle] @@ -1798,6 +1794,7 @@ pub unsafe extern "C" fn get_seg(mut segment: i32) -> i32 { if *segment_is_null.offset(segment as isize) { dbg_assert!(segment != CS && segment != SS); dbg_log_c!(("#gp: Access null segment")); + assert!(false); trigger_gp(0i32); } } @@ -1824,13 +1821,13 @@ pub unsafe extern "C" fn raise_exception_with_code( dbg_assert!(0 != 0i32); } if cpu_exception_hook(interrupt_nr) { - throw_cpu_exception(); + assert!(false); return; } } profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); call_interrupt_vector(interrupt_nr, 0 != 0i32, 0 != 1i32, error_code); - throw_cpu_exception(); + assert!(false); } #[no_mangle] pub unsafe extern "C" fn get_seg_cs() -> i32 { return *segment_offsets.offset(CS as isize); } @@ -1864,13 +1861,13 @@ pub unsafe extern "C" fn get_seg_prefix_cs(mut offset: i32) -> i32 { return get_seg_prefix(CS) + offset; } #[no_mangle] -pub unsafe extern "C" fn modrm_resolve(mut modrm_byte: i32) -> i32 { +pub unsafe extern "C" fn modrm_resolve(mut modrm_byte: i32) -> Result { if is_asize_32() { - return resolve_modrm32(modrm_byte); + resolve_modrm32(modrm_byte) } else { - return resolve_modrm16(modrm_byte); - }; + resolve_modrm16(modrm_byte) + } } #[no_mangle] pub unsafe extern "C" fn cycle_internal() -> () { @@ -1924,15 +1921,15 @@ pub unsafe extern "C" fn cycle_internal() -> () { } } #[no_mangle] -pub unsafe extern "C" fn get_phys_eip() -> i32 { +pub unsafe extern "C" fn get_phys_eip() -> Result { let mut eip: i32 = *instruction_pointer; if 0 != eip & !4095i32 ^ *last_virt_eip { - *eip_phys = (translate_address_read(eip) ^ eip as u32) as i32; + *eip_phys = (translate_address_read(eip)? ^ eip as u32) as i32; *last_virt_eip = eip & !4095i32 } let mut phys_addr: u32 = (*eip_phys ^ eip) as u32; dbg_assert!(!in_mapped_range(phys_addr)); - return phys_addr as i32; + return Ok(phys_addr as i32); } unsafe extern "C" fn jit_run_interpreted(mut phys_addr: i32) -> () { profiler_stat_increment(S_RUN_INTERPRETED); @@ -1946,7 +1943,7 @@ unsafe extern "C" fn jit_run_interpreted(mut phys_addr: i32) -> () { while !jit_block_boundary && 0 != same_page(*previous_ip, *instruction_pointer) as i32 { *previous_ip.offset(0isize) = *instruction_pointer.offset(0isize); *timestamp_counter = (*timestamp_counter).wrapping_add(1); - let mut opcode_0: i32 = read_imm8(); + let mut opcode_0: i32 = return_on_pagefault!(read_imm8()); if DEBUG { logop(*previous_ip.offset(0isize), opcode_0); } @@ -1974,7 +1971,7 @@ pub unsafe extern "C" fn has_flat_segmentation() -> bool { } #[no_mangle] pub unsafe extern "C" fn run_prefix_instruction() -> () { - run_instruction(read_imm8() | (is_osize_32() as i32) << 8i32); + run_instruction(return_on_pagefault!(read_imm8()) | (is_osize_32() as i32) << 8i32); } #[no_mangle] pub unsafe extern "C" fn clear_prefixes() -> () { *prefixes = 0i32 as u8; } @@ -1986,7 +1983,7 @@ pub unsafe extern "C" fn segment_prefix_op(mut seg: i32) -> () { *prefixes = 0i32 as u8; } #[no_mangle] -pub unsafe extern "C" fn do_many_cycles_unsafe() -> () { +pub unsafe extern "C" fn do_many_cycles_native() -> () { profiler_stat_increment(S_DO_MANY_CYCLES); let mut initial_timestamp_counter: u32 = *timestamp_counter; while (*timestamp_counter).wrapping_sub(initial_timestamp_counter) < LOOP_COUNTER as u32 @@ -1997,23 +1994,23 @@ pub unsafe extern "C" fn do_many_cycles_unsafe() -> () { } #[no_mangle] pub static mut LOOP_COUNTER: i32 = unsafe { 20011i32 }; -#[no_mangle] -pub unsafe extern "C" fn raise_exception(mut interrupt_nr: i32) -> () { - if DEBUG { - if must_not_fault { - dbg_log_c!(("Unexpected fault: 0x%x"), interrupt_nr); - dbg_trace(); - dbg_assert!(0 != 0i32); - } - if cpu_exception_hook(interrupt_nr) { - throw_cpu_exception(); - return; - } - } - profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); - call_interrupt_vector(interrupt_nr, 0 != 0i32, 0 != 0i32, 0i32); - throw_cpu_exception(); -} +//#[no_mangle] +//pub unsafe extern "C" fn raise_exception(mut interrupt_nr: i32) -> () { +// if DEBUG { +// if must_not_fault { +// dbg_log_c!(("Unexpected fault: 0x%x"), interrupt_nr); +// dbg_trace(); +// dbg_assert!(0 != 0i32); +// } +// if cpu_exception_hook(interrupt_nr) { +// throw_cpu_exception(); +// return; +// } +// } +// profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); +// call_interrupt_vector(interrupt_nr, 0 != 0i32, 0 != 0i32, 0i32); +// throw_cpu_exception(); +//} #[no_mangle] pub unsafe extern "C" fn trigger_de() -> () { if DEBUG { @@ -2121,12 +2118,13 @@ pub unsafe extern "C" fn virt_boundary_write32(mut low: i32, mut high: i32, mut write8(high as u32, value >> 24i32); } #[no_mangle] -pub unsafe extern "C" fn safe_read8(mut addr: i32) -> i32 { +pub unsafe extern "C" fn safe_read8(mut addr: i32) -> Result { assert_no_cpu_exception(); - return read8(translate_address_read(addr)); + return Ok(read8(translate_address_read(addr)?)); } #[no_mangle] pub unsafe extern "C" fn assert_no_cpu_exception() -> () { + return; if current_cpu_exception != -1i32 { dbg_log_c!(("Expected no cpu exception, got %d"), current_cpu_exception); dbg_trace(); @@ -2134,7 +2132,7 @@ pub unsafe extern "C" fn assert_no_cpu_exception() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn safe_read16(mut address: i32) -> i32 { +pub unsafe extern "C" fn safe_read16(mut address: i32) -> Result { let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); let mut info_bits: i32 = entry & 4095i32 & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; @@ -2143,24 +2141,24 @@ pub unsafe extern "C" fn safe_read16(mut address: i32) -> i32 { c_comment!(("- can be accessed from any cpl")); let mut phys_address: u32 = (entry & !4095i32 ^ address) as u32; dbg_assert!(!in_mapped_range(phys_address)); - return *(mem8.offset(phys_address as isize) as *mut u16) as i32; + return Ok(*(mem8.offset(phys_address as isize) as *mut u16) as i32); } else { - return safe_read16_slow(address); + return Ok(safe_read16_slow(address)?); }; } #[no_mangle] -pub unsafe extern "C" fn safe_read16_slow(mut addr: i32) -> i32 { +pub unsafe extern "C" fn safe_read16_slow(mut addr: i32) -> Result { assert_no_cpu_exception(); if addr & 4095i32 == 4095i32 { - return safe_read8(addr) | safe_read8(addr + 1i32) << 8i32; + return Ok(safe_read8(addr)? | safe_read8(addr + 1i32)? << 8i32); } else { - return read16(translate_address_read(addr)); + return Ok(read16(translate_address_read(addr)?)); }; } #[no_mangle] -pub unsafe extern "C" fn safe_read32s(mut address: i32) -> i32 { +pub unsafe extern "C" fn safe_read32s(mut address: i32) -> Result { assert_no_cpu_exception(); let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); @@ -2171,7 +2169,7 @@ pub unsafe extern "C" fn safe_read32s(mut address: i32) -> i32 { c_comment!(("- can be accessed from any cpl")); let mut phys_address: u32 = (entry & !4095i32 ^ address) as u32; dbg_assert!(!in_mapped_range(phys_address)); - return *(mem8.offset(phys_address as isize) as *mut i32); + return Ok(*(mem8.offset(phys_address as isize) as *mut i32)); } else { if address & 4095i32 > 4096i32 - 4i32 { @@ -2193,51 +2191,81 @@ pub unsafe extern "C" fn safe_read32s(mut address: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn safe_read32s_slow(mut addr: i32) -> i32 { +pub unsafe extern "C" fn safe_read32s_slow(mut addr: i32) -> Result { if addr & 4095i32 >= 4093i32 { - return safe_read16(addr) | safe_read16(addr + 2i32) << 16i32; + return Ok(safe_read16(addr)? | safe_read16(addr + 2i32)? << 16i32); } else { - return read32s(translate_address_read(addr)); + return Ok(read32s(translate_address_read(addr)?)); }; } + #[no_mangle] -pub unsafe extern "C" fn safe_read64s(mut addr: i32) -> reg64 { +pub unsafe fn safe_read16_slow_jit(addr: i32) -> i32 { + match safe_read16_slow(addr) { + Ok(v) => { + *page_fault = false; + v + }, + Err(()) => { + *page_fault = true; + -1 + }, + } +} + +#[no_mangle] +pub unsafe fn safe_read32s_slow_jit(addr: i32) -> i32 { + match safe_read32s_slow(addr) { + Ok(v) => { + *page_fault = false; + v + }, + Err(()) => { + *page_fault = true; + -1 + }, + } +} + +#[no_mangle] +pub unsafe extern "C" fn safe_read64s(mut addr: i32) -> Result { let mut addr_phys: i32 = 0; assert_no_cpu_exception(); let mut x: reg64 = reg64 { i8_0: [0; 8] }; if addr & 4095i32 > 4096i32 - 8i32 { - x.u32_0[0usize] = safe_read32s(addr) as u32; - x.u32_0[1usize] = safe_read32s(addr + 4i32) as u32 + x.u32_0[0usize] = safe_read32s(addr)? as u32; + x.u32_0[1usize] = safe_read32s(addr + 4i32)? as u32 } else { - addr_phys = translate_address_read(addr) as i32; + addr_phys = translate_address_read(addr)? as i32; x.u64_0[0usize] = read64s(addr_phys as u32) as u64 } - return x; + Ok(x) } #[no_mangle] -pub unsafe extern "C" fn safe_read128s(mut addr: i32) -> reg128 { +pub unsafe extern "C" fn safe_read128s(mut addr: i32) -> Result { let mut addr_phys: i32 = 0; assert_no_cpu_exception(); let mut x: reg128 = reg128 { i8_0: [0; 16] }; if addr & 4095i32 > 4096i32 - 16i32 { - x.u64_0[0usize] = safe_read64s(addr).u64_0[0usize]; - x.u64_0[1usize] = safe_read64s(addr + 8i32).u64_0[0usize] + x.u64_0[0usize] = safe_read64s(addr)?.u64_0[0usize]; + x.u64_0[1usize] = safe_read64s(addr + 8i32)?.u64_0[0usize] } else { - addr_phys = translate_address_read(addr) as i32; + addr_phys = translate_address_read(addr)? as i32; x = read128(addr_phys as u32) } - return x; + Ok(x) } #[no_mangle] -pub unsafe extern "C" fn safe_write8(mut addr: i32, mut value: i32) -> () { +pub unsafe extern "C" fn safe_write8(mut addr: i32, mut value: i32) -> Result<(), ()> { assert_no_cpu_exception(); - write8(translate_address_write(addr), value); + write8(translate_address_write(addr)?, value); + Ok(()) } #[no_mangle] -pub unsafe extern "C" fn safe_write16(mut address: i32, mut value: i32) -> () { +pub unsafe extern "C" fn safe_write16(mut address: i32, mut value: i32) -> Result<(), ()> { let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); let mut info_bits: i32 = entry & 4095i32 & !TLB_GLOBAL; @@ -2250,26 +2278,30 @@ pub unsafe extern "C" fn safe_write16(mut address: i32, mut value: i32) -> () { dbg_assert!(!jit_page_has_code(phys_address >> 12i32)); dbg_assert!(!in_mapped_range(phys_address)); *(mem8.offset(phys_address as isize) as *mut u16) = value as u16; - return; } else { - safe_write16_slow(address, value); - return; + safe_write16_slow(address, value)?; }; + Ok(()) } #[no_mangle] -pub unsafe extern "C" fn safe_write16_slow(mut addr: i32, mut value: i32) -> () { +pub unsafe extern "C" fn safe_write16_slow(mut addr: i32, mut value: i32) -> Result<(), ()> { assert_no_cpu_exception(); - let mut phys_low: i32 = translate_address_write(addr) as i32; + let mut phys_low: i32 = translate_address_write(addr)? as i32; if addr & 4095i32 == 4095i32 { - virt_boundary_write16(phys_low, translate_address_write(addr + 1i32) as i32, value); + virt_boundary_write16( + phys_low, + translate_address_write(addr + 1i32)? as i32, + value, + ); } else { write16(phys_low as u32, value); }; + Ok(()) } #[no_mangle] -pub unsafe extern "C" fn safe_write32(mut address: i32, mut value: i32) -> () { +pub unsafe extern "C" fn safe_write32(mut address: i32, mut value: i32) -> Result<(), ()> { assert_no_cpu_exception(); let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); @@ -2288,7 +2320,6 @@ pub unsafe extern "C" fn safe_write32(mut address: i32, mut value: i32) -> () { dbg_assert!(!jit_page_has_code(phys_address >> 12i32)); dbg_assert!(!in_mapped_range(phys_address)); *(mem8.offset(phys_address as isize) as *mut i32) = value; - return; } else { if address & 4095i32 > 4096i32 - 4i32 { @@ -2312,49 +2343,63 @@ pub unsafe extern "C" fn safe_write32(mut address: i32, mut value: i32) -> () { else { dbg_assert!(0 != 0i32); } - safe_write32_slow(address, value); - return; + safe_write32_slow(address, value)?; }; + Ok(()) } #[no_mangle] -pub unsafe extern "C" fn safe_write32_slow(mut addr: i32, mut value: i32) -> () { - let mut phys_low: i32 = translate_address_write(addr) as i32; +pub unsafe extern "C" fn safe_write32_slow(mut addr: i32, mut value: i32) -> Result<(), ()> { + let mut phys_low: i32 = translate_address_write(addr)? as i32; if addr & 4095i32 > 4096i32 - 4i32 { virt_boundary_write32( phys_low, - (translate_address_write(addr + 3i32 & !3i32) | (addr + 3i32 & 3i32) as u32) as i32, + (translate_address_write(addr + 3i32 & !3i32)? | (addr + 3i32 & 3i32) as u32) as i32, value, ); } else { write32(phys_low as u32, value); }; + Ok(()) } + #[no_mangle] -pub unsafe extern "C" fn safe_write64(mut addr: i32, mut value: i64) -> () { +pub unsafe fn safe_write16_slow_jit(addr: i32, value: i32) { + let _ = safe_write16_slow(addr, value); +} + +#[no_mangle] +pub unsafe fn safe_write32_slow_jit(addr: i32, value: i32) { + let _ = safe_write32_slow(addr, value); +} + +#[no_mangle] +pub unsafe extern "C" fn safe_write64(mut addr: i32, mut value: i64) -> Result<(), ()> { assert_no_cpu_exception(); if addr & 4095i32 > 4096i32 - 8i32 { - writable_or_pagefault(addr, 8i32); - safe_write32(addr, value as i32); - safe_write32(addr + 4i32, (value >> 32i32) as i32); + writable_or_pagefault(addr, 8i32)?; + safe_write32(addr, value as i32).unwrap(); + safe_write32(addr + 4i32, (value >> 32i32) as i32).unwrap(); } else { - let mut phys: i32 = translate_address_write(addr) as i32; + let mut phys: i32 = translate_address_write(addr)? as i32; write64(phys as u32, value); }; + Ok(()) } #[no_mangle] -pub unsafe extern "C" fn safe_write128(mut addr: i32, mut value: reg128) -> () { +pub unsafe extern "C" fn safe_write128(mut addr: i32, mut value: reg128) -> Result<(), ()> { assert_no_cpu_exception(); if addr & 4095i32 > 4096i32 - 16i32 { - writable_or_pagefault(addr, 16i32); - safe_write64(addr, value.u64_0[0usize] as i64); - safe_write64(addr + 8i32, value.u64_0[1usize] as i64); + writable_or_pagefault(addr, 16i32)?; + safe_write64(addr, value.u64_0[0usize] as i64).unwrap(); + safe_write64(addr + 8i32, value.u64_0[1usize] as i64).unwrap(); } else { - let mut phys: i32 = translate_address_write(addr) as i32; + let mut phys: i32 = translate_address_write(addr)? as i32; write128(phys as u32, value); }; + Ok(()) } #[no_mangle] pub unsafe extern "C" fn get_reg8_index(mut index: i32) -> i32 { @@ -2486,14 +2531,14 @@ pub unsafe extern "C" fn task_switch_test_mmx() -> bool { #[no_mangle] pub unsafe extern "C" fn task_switch_test_mmx_void() -> () { task_switch_test_mmx(); } #[no_mangle] -pub unsafe extern "C" fn read_moffs() -> i32 { +pub unsafe extern "C" fn read_moffs() -> Result { c_comment!(("read 2 or 4 byte from ip, depending on address size attribute")); if is_asize_32() { - return read_imm32s(); + read_imm32s() } else { - return read_imm16(); - }; + read_imm16() + } } #[no_mangle] pub unsafe extern "C" fn get_real_eip() -> i32 { @@ -2697,25 +2742,25 @@ pub unsafe extern "C" fn get_valid_global_tlb_entries_count() -> i32 { return result; } #[no_mangle] -pub unsafe extern "C" fn translate_address_system_read(mut address: i32) -> u32 { +pub unsafe extern "C" fn translate_address_system_read(mut address: i32) -> Result { let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); if 0 != entry & TLB_VALID { - return (entry & !4095i32 ^ address) as u32; + return Ok((entry & !4095i32 ^ address) as u32); } else { - return (do_page_translation(address, 0 != 0i32, 0 != 0i32) | address & 4095i32) as u32; + return Ok((do_page_translation(address, 0 != 0i32, 0 != 0i32)? | address & 4095i32) as u32); }; } #[no_mangle] -pub unsafe extern "C" fn translate_address_system_write(mut address: i32) -> u32 { +pub unsafe extern "C" fn translate_address_system_write(mut address: i32) -> Result { let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); if entry & (TLB_VALID | TLB_READONLY) == TLB_VALID { - return (entry & !4095i32 ^ address) as u32; + return Ok((entry & !4095i32 ^ address) as u32); } else { - return (do_page_translation(address, 0 != 1i32, 0 != 0i32) | address & 4095i32) as u32; + return Ok((do_page_translation(address, 0 != 1i32, 0 != 0i32)? | address & 4095i32) as u32); }; } #[no_mangle] diff --git a/src/rust/cpu2/instruction_helpers.rs b/src/rust/cpu2/instruction_helpers.rs index b435de7e..0af8369d 100644 --- a/src/rust/cpu2/instruction_helpers.rs +++ b/src/rust/cpu2/instruction_helpers.rs @@ -2,24 +2,38 @@ macro_rules! SAFE_READ_WRITE8 { ($value:ident, $addr:expr, $instruction:expr) => {{ use cpu2::cpu::translate_address_write; use cpu2::memory::{read8, write8}; - let phys_addr = translate_address_write($addr); - let $value = read8(phys_addr); - write8(phys_addr, $instruction); + match translate_address_write($addr) { + Err(()) => {}, + Ok(phys_addr) => { + let $value = read8(phys_addr); + write8(phys_addr, $instruction); + }, + } }}; } macro_rules! SAFE_READ_WRITE16 { ($value:ident, $addr:expr, $instruction:expr) => {{ use cpu2::cpu::{translate_address_write, virt_boundary_read16, virt_boundary_write16}; use cpu2::memory::{read16, write16}; - let phys_addr = translate_address_write($addr) as i32; - if phys_addr & 0xFFF == 0xFFF { - let phys_addr_high = translate_address_write($addr + 1) as i32; - let $value = virt_boundary_read16(phys_addr, phys_addr_high); - virt_boundary_write16(phys_addr, phys_addr_high, $instruction); - } - else { - let $value = read16(phys_addr as u32); - write16(phys_addr as u32, $instruction); + match translate_address_write($addr) { + Err(()) => {}, + Ok(phys_addr) => { + let phys_addr = phys_addr as i32; + if phys_addr & 0xFFF == 0xFFF { + match translate_address_write($addr + 1) { + Err(()) => {}, + Ok(phys_addr_high) => { + let phys_addr_high = phys_addr_high as i32; + let $value = virt_boundary_read16(phys_addr, phys_addr_high); + virt_boundary_write16(phys_addr, phys_addr_high, $instruction); + }, + } + } + else { + let $value = read16(phys_addr as u32); + write16(phys_addr as u32, $instruction); + } + }, } }}; } @@ -27,15 +41,28 @@ macro_rules! SAFE_READ_WRITE32 { ($value:ident, $addr:expr, $instruction:expr) => {{ use cpu2::cpu::{translate_address_write, virt_boundary_read32s, virt_boundary_write32}; use cpu2::memory::{read32s, write32}; - let phys_addr = translate_address_write($addr); - if phys_addr & 0xFFF >= 0xFFD { - let phys_addr_high = translate_address_write($addr + 3 & !3) as i32 | $addr + 3 & 3; - let $value = virt_boundary_read32s(phys_addr as i32, phys_addr_high); - virt_boundary_write32(phys_addr as i32, phys_addr_high as i32, $instruction); - } - else { - let $value = read32s(phys_addr); - write32(phys_addr, $instruction); + match translate_address_write($addr) { + Err(()) => {}, + Ok(phys_addr) => { + if phys_addr & 0xFFF >= 0xFFD { + match translate_address_write($addr + 3 & !3) { + Err(()) => {}, + Ok(phys_addr_high) => { + let phys_addr_high = phys_addr_high as i32 | $addr + 3 & 3; + let $value = virt_boundary_read32s(phys_addr as i32, phys_addr_high); + virt_boundary_write32( + phys_addr as i32, + phys_addr_high as i32, + $instruction, + ); + }, + } + } + else { + let $value = read32s(phys_addr); + write32(phys_addr, $instruction); + } + }, } }}; } diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index 4a6bef51..517b4ca1 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -307,30 +307,12 @@ extern "C" { #[no_mangle] static CPU_EXCEPTION_VE: i32; #[no_mangle] - fn translate_address_read(address: i32) -> u32; - #[no_mangle] - fn writable_or_pagefault(addr: i32, size: i32) -> (); - #[no_mangle] fn get_seg_cs() -> i32; #[no_mangle] fn get_seg_ss() -> i32; #[no_mangle] fn trigger_gp_non_raising(code: i32) -> (); #[no_mangle] - fn safe_read8(addr: i32) -> i32; - #[no_mangle] - fn safe_read16(addr: i32) -> i32; - #[no_mangle] - fn safe_read32s(address: i32) -> i32; - #[no_mangle] - fn safe_write8(addr: i32, value: i32) -> (); - #[no_mangle] - fn safe_write16(addr: i32, value: i32) -> (); - #[no_mangle] - fn safe_write32(address: i32, value: i32) -> (); - #[no_mangle] - fn safe_write128(addr: i32, value: reg128) -> (); - #[no_mangle] fn write_reg8(index: i32, value: i32) -> (); #[no_mangle] fn write_reg16(index: i32, value: i32) -> (); @@ -499,20 +481,6 @@ pub union unnamed { __i: u64, } -#[derive(Copy, Clone)] -#[repr(C)] -pub union reg64 { - i8_0: [i8; 8], - i16_0: [i16; 4], - i32_0: [i32; 2], - i64_0: [i64; 1], - u8_0: [u8; 8], - u16_0: [u16; 4], - u32_0: [u32; 2], - u64_0: [u64; 1], - f32_0: [f32; 2], - f64_0: [f64; 1], -} #[derive(Copy, Clone)] #[repr(C)] pub union unnamed_0 { @@ -520,21 +488,6 @@ pub union unnamed_0 { __i: u32, } -#[derive(Copy, Clone)] -#[repr(C)] -pub union reg128 { - i8_0: [i8; 16], - i16_0: [i16; 8], - i32_0: [i32; 4], - i64_0: [i64; 2], - u8_0: [u8; 16], - u16_0: [u16; 8], - u32_0: [u32; 4], - u64_0: [u64; 2], - f32_0: [f32; 4], - f64_0: [f64; 2], -} - unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; __u.__f = __f; @@ -1078,105 +1031,159 @@ pub unsafe extern "C" fn adjust_stack_reg(mut adjustment: i32) -> () { *fresh1 = (*fresh1 as i32 + adjustment) as u16 }; } + #[no_mangle] -pub unsafe extern "C" fn push16_ss16(mut imm16: i32) -> () { +pub unsafe extern "C" fn push16_ss16(mut imm16: i32) -> Result<(), ()> { let mut sp: i32 = get_seg_ss() + (*reg16.offset(SP as isize) as i32 - 2i32 & 65535i32); - safe_write16(sp, imm16); + safe_write16(sp, imm16)?; let ref mut fresh2 = *reg16.offset(SP as isize); *fresh2 = (*fresh2 as i32 + -2i32) as u16; + Ok(()) } #[no_mangle] -pub unsafe extern "C" fn push16_ss32(mut imm16: i32) -> () { +pub unsafe extern "C" fn push16_ss32(mut imm16: i32) -> Result<(), ()> { let mut sp: i32 = get_seg_ss() + *reg32s.offset(ESP as isize) - 2i32; - safe_write16(sp, imm16); + safe_write16(sp, imm16)?; let ref mut fresh3 = *reg32s.offset(ESP as isize); *fresh3 += -2i32; + Ok(()) +} + +#[no_mangle] +pub unsafe extern "C" fn push16_ss16_jit(mut imm16: i32) { + return_on_pagefault!(push16_ss16(imm16)) } #[no_mangle] -pub unsafe extern "C" fn push16_ss16_mem(mut addr: i32) -> () { push16_ss16(safe_read16(addr)); } +pub unsafe extern "C" fn push16_ss32_jit(mut imm16: i32) { + return_on_pagefault!(push16_ss32(imm16)) +} + #[no_mangle] -pub unsafe extern "C" fn push16_ss32_mem(mut addr: i32) -> () { push16_ss32(safe_read16(addr)); } +pub unsafe extern "C" fn push16_ss16_mem(mut addr: i32) -> Result<(), ()> { + push16_ss16(safe_read16(addr)?) +} #[no_mangle] -pub unsafe extern "C" fn push16(mut imm16: i32) -> () { +pub unsafe extern "C" fn push16_ss32_mem(mut addr: i32) -> Result<(), ()> { + push16_ss32(safe_read16(addr)?) +} + +#[no_mangle] +pub unsafe extern "C" fn push16_ss16_mem_jit(mut addr: i32) { + return_on_pagefault!(push16_ss16(addr)) +} +#[no_mangle] +pub unsafe extern "C" fn push16_ss32_mem_jit(mut addr: i32) { + return_on_pagefault!(push16_ss32(addr)) +} + +#[no_mangle] +pub unsafe extern "C" fn push16(mut imm16: i32) -> Result<(), ()> { if *stack_size_32 { - push16_ss32(imm16); + push16_ss32(imm16) } else { - push16_ss16(imm16); - }; + push16_ss16(imm16) + } } + #[no_mangle] -pub unsafe extern "C" fn push32_ss16(mut imm32: i32) -> () { +pub unsafe extern "C" fn push32_ss16(mut imm32: i32) -> Result<(), ()> { let mut new_sp: i32 = *reg16.offset(SP as isize) as i32 - 4i32 & 65535i32; - safe_write32(get_seg_ss() + new_sp, imm32); + safe_write32(get_seg_ss() + new_sp, imm32)?; *reg16.offset(SP as isize) = new_sp as u16; + Ok(()) } #[no_mangle] -pub unsafe extern "C" fn push32_ss32(mut imm32: i32) -> () { +pub unsafe extern "C" fn push32_ss32(mut imm32: i32) -> Result<(), ()> { let mut new_esp: i32 = *reg32s.offset(ESP as isize) - 4i32; - safe_write32(get_seg_ss() + new_esp, imm32); + safe_write32(get_seg_ss() + new_esp, imm32)?; *reg32s.offset(ESP as isize) = new_esp; + Ok(()) +} + +#[no_mangle] +pub unsafe extern "C" fn push32_ss16_jit(mut imm32: i32) { + return_on_pagefault!(push32_ss16(imm32)) } #[no_mangle] -pub unsafe extern "C" fn push32_ss16_mem(mut addr: i32) -> () { push32_ss16(safe_read32s(addr)); } +pub unsafe extern "C" fn push32_ss32_jit(mut imm32: i32) { + return_on_pagefault!(push32_ss32(imm32)) +} + #[no_mangle] -pub unsafe extern "C" fn push32_ss32_mem(mut addr: i32) -> () { push32_ss32(safe_read32s(addr)); } +pub unsafe extern "C" fn push32_ss16_mem(mut addr: i32) -> Result<(), ()> { + push32_ss16(safe_read32s(addr)?) +} #[no_mangle] -pub unsafe extern "C" fn push32(mut imm32: i32) -> () { +pub unsafe extern "C" fn push32_ss32_mem(mut addr: i32) -> Result<(), ()> { + push32_ss32(safe_read32s(addr)?) +} + +#[no_mangle] +pub unsafe extern "C" fn push32_ss16_mem_jit(mut addr: i32) { + return_on_pagefault!(push32_ss16_mem(addr)) +} +#[no_mangle] +pub unsafe extern "C" fn push32_ss32_mem_jit(mut addr: i32) { + return_on_pagefault!(push32_ss32_mem(addr)) +} + +#[no_mangle] +pub unsafe extern "C" fn push32(mut imm32: i32) -> Result<(), ()> { if *stack_size_32 { - push32_ss32(imm32); + push32_ss32(imm32) } else { - push32_ss16(imm32); - }; + push32_ss16(imm32) + } } #[no_mangle] -pub unsafe extern "C" fn pop16() -> i32 { +pub unsafe extern "C" fn pop16() -> Result { if *stack_size_32 { - return pop16_ss32(); + pop16_ss32() } else { - return pop16_ss16(); - }; + pop16_ss16() + } } #[no_mangle] -pub unsafe extern "C" fn pop16_ss16() -> i32 { +pub unsafe extern "C" fn pop16_ss16() -> Result { let mut sp: i32 = get_seg_ss() + *reg16.offset(SP as isize) as i32; - let mut result: i32 = safe_read16(sp); + let mut result: i32 = safe_read16(sp)?; let ref mut fresh4 = *reg16.offset(SP as isize); *fresh4 = (*fresh4 as i32 + 2i32) as u16; - return result; + Ok(result) } #[no_mangle] -pub unsafe extern "C" fn pop16_ss32() -> i32 { +pub unsafe extern "C" fn pop16_ss32() -> Result { let mut esp: i32 = get_seg_ss() + *reg32s.offset(ESP as isize); - let mut result: i32 = safe_read16(esp); + let mut result: i32 = safe_read16(esp)?; let ref mut fresh5 = *reg32s.offset(ESP as isize); *fresh5 += 2i32; - return result; + Ok(result) } #[no_mangle] -pub unsafe extern "C" fn pop32s() -> i32 { +pub unsafe extern "C" fn pop32s() -> Result { if *stack_size_32 { - return pop32s_ss32(); + pop32s_ss32() } else { - return pop32s_ss16(); - }; + pop32s_ss16() + } } #[no_mangle] -pub unsafe extern "C" fn pop32s_ss16() -> i32 { +pub unsafe extern "C" fn pop32s_ss16() -> Result { let mut sp: i32 = *reg16.offset(SP as isize) as i32; - let mut result: i32 = safe_read32s(get_seg_ss() + sp); + let mut result: i32 = safe_read32s(get_seg_ss() + sp)?; *reg16.offset(SP as isize) = (sp + 4i32) as u16; - return result; + Ok(result) } #[no_mangle] -pub unsafe extern "C" fn pop32s_ss32() -> i32 { +pub unsafe extern "C" fn pop32s_ss32() -> Result { let mut esp: i32 = *reg32s.offset(ESP as isize); - let mut result: i32 = safe_read32s(get_seg_ss() + esp); + let mut result: i32 = safe_read32s(get_seg_ss() + esp)?; *reg32s.offset(ESP as isize) = esp + 4i32; - return result; + Ok(result) } #[no_mangle] pub unsafe extern "C" fn pusha16() -> () { diff --git a/src/rust/cpu2/modrm.rs b/src/rust/cpu2/modrm.rs index 751e2376..0d1f2487 100644 --- a/src/rust/cpu2/modrm.rs +++ b/src/rust/cpu2/modrm.rs @@ -1,7 +1,14 @@ -#![allow -( dead_code , mutable_transmutes , non_camel_case_types , non_snake_case , -non_upper_case_globals , unused_mut )] -#![feature ( extern_types , libc )] +#![allow( + dead_code, + mutable_transmutes, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_mut +)] +#![feature(extern_types, libc)] + +use cpu2::cpu::*; extern "C" { @@ -303,14 +310,6 @@ extern "C" { #[no_mangle] static CPU_EXCEPTION_VE: i32; #[no_mangle] - fn read_imm8() -> i32; - #[no_mangle] - fn read_imm8s() -> i32; - #[no_mangle] - fn read_imm16() -> i32; - #[no_mangle] - fn read_imm32s() -> i32; - #[no_mangle] fn get_seg_prefix(default_segment: i32) -> i32; #[no_mangle] fn get_seg_prefix_ds(offset: i32) -> i32; @@ -853,181 +852,141 @@ unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { } && __x >= __y) as i32; } #[no_mangle] -pub unsafe extern "C" fn resolve_modrm16(mut modrm_byte: i32) -> i32 { - match modrm_byte { - 0 | 8 | 16 | 24 | 32 | 40 | 48 | 56 => { - return get_seg_prefix_ds( - *reg16.offset(BX as isize) as i32 + *reg16.offset(SI as isize) as i32 & 65535i32, - ) - }, - 64 | 72 | 80 | 88 | 96 | 104 | 112 | 120 => { - return get_seg_prefix_ds( - *reg16.offset(BX as isize) as i32 - + *reg16.offset(SI as isize) as i32 - + read_imm8s() - & 65535i32, - ) - }, - 128 | 136 | 144 | 152 | 160 | 168 | 176 | 184 => { - return get_seg_prefix_ds( - *reg16.offset(BX as isize) as i32 - + *reg16.offset(SI as isize) as i32 - + read_imm16() - & 65535i32, - ) - }, - 1 | 9 | 17 | 25 | 33 | 41 | 49 | 57 => { - return get_seg_prefix_ds( - *reg16.offset(BX as isize) as i32 + *reg16.offset(DI as isize) as i32 & 65535i32, - ) - }, - 65 | 73 | 81 | 89 | 97 | 105 | 113 | 121 => { - return get_seg_prefix_ds( - *reg16.offset(BX as isize) as i32 - + *reg16.offset(DI as isize) as i32 - + read_imm8s() - & 65535i32, - ) - }, - 129 | 137 | 145 | 153 | 161 | 169 | 177 | 185 => { - return get_seg_prefix_ds( - *reg16.offset(BX as isize) as i32 - + *reg16.offset(DI as isize) as i32 - + read_imm16() - & 65535i32, - ) - }, - 2 | 10 | 18 | 26 | 34 | 42 | 50 | 58 => { - return get_seg_prefix_ss( - *reg16.offset(BP as isize) as i32 + *reg16.offset(SI as isize) as i32 & 65535i32, - ) - }, - 66 | 74 | 82 | 90 | 98 | 106 | 114 | 122 => { - return get_seg_prefix_ss( - *reg16.offset(BP as isize) as i32 - + *reg16.offset(SI as isize) as i32 - + read_imm8s() - & 65535i32, - ) - }, - 130 | 138 | 146 | 154 | 162 | 170 | 178 | 186 => { - return get_seg_prefix_ss( - *reg16.offset(BP as isize) as i32 - + *reg16.offset(SI as isize) as i32 - + read_imm16() - & 65535i32, - ) - }, - 3 | 11 | 19 | 27 | 35 | 43 | 51 | 59 => { - return get_seg_prefix_ss( - *reg16.offset(BP as isize) as i32 + *reg16.offset(DI as isize) as i32 & 65535i32, - ) - }, - 67 | 75 | 83 | 91 | 99 | 107 | 115 | 123 => { - return get_seg_prefix_ss( - *reg16.offset(BP as isize) as i32 - + *reg16.offset(DI as isize) as i32 - + read_imm8s() - & 65535i32, - ) - }, - 131 | 139 | 147 | 155 | 163 | 171 | 179 | 187 => { - return get_seg_prefix_ss( - *reg16.offset(BP as isize) as i32 - + *reg16.offset(DI as isize) as i32 - + read_imm16() - & 65535i32, - ) - }, +pub unsafe extern "C" fn resolve_modrm16(mut modrm_byte: i32) -> Result { + Ok(match modrm_byte { + 0 | 8 | 16 | 24 | 32 | 40 | 48 | 56 => get_seg_prefix_ds( + *reg16.offset(BX as isize) as i32 + *reg16.offset(SI as isize) as i32 & 65535i32, + ), + 64 | 72 | 80 | 88 | 96 | 104 | 112 | 120 => get_seg_prefix_ds( + *reg16.offset(BX as isize) as i32 + *reg16.offset(SI as isize) as i32 + read_imm8s()? + & 65535i32, + ), + 128 | 136 | 144 | 152 | 160 | 168 | 176 | 184 => get_seg_prefix_ds( + *reg16.offset(BX as isize) as i32 + *reg16.offset(SI as isize) as i32 + read_imm16()? + & 65535i32, + ), + 1 | 9 | 17 | 25 | 33 | 41 | 49 | 57 => get_seg_prefix_ds( + *reg16.offset(BX as isize) as i32 + *reg16.offset(DI as isize) as i32 & 65535i32, + ), + 65 | 73 | 81 | 89 | 97 | 105 | 113 | 121 => get_seg_prefix_ds( + *reg16.offset(BX as isize) as i32 + *reg16.offset(DI as isize) as i32 + read_imm8s()? + & 65535i32, + ), + 129 | 137 | 145 | 153 | 161 | 169 | 177 | 185 => get_seg_prefix_ds( + *reg16.offset(BX as isize) as i32 + *reg16.offset(DI as isize) as i32 + read_imm16()? + & 65535i32, + ), + 2 | 10 | 18 | 26 | 34 | 42 | 50 | 58 => get_seg_prefix_ss( + *reg16.offset(BP as isize) as i32 + *reg16.offset(SI as isize) as i32 & 65535i32, + ), + 66 | 74 | 82 | 90 | 98 | 106 | 114 | 122 => get_seg_prefix_ss( + *reg16.offset(BP as isize) as i32 + *reg16.offset(SI as isize) as i32 + read_imm8s()? + & 65535i32, + ), + 130 | 138 | 146 | 154 | 162 | 170 | 178 | 186 => get_seg_prefix_ss( + *reg16.offset(BP as isize) as i32 + *reg16.offset(SI as isize) as i32 + read_imm16()? + & 65535i32, + ), + 3 | 11 | 19 | 27 | 35 | 43 | 51 | 59 => get_seg_prefix_ss( + *reg16.offset(BP as isize) as i32 + *reg16.offset(DI as isize) as i32 & 65535i32, + ), + 67 | 75 | 83 | 91 | 99 | 107 | 115 | 123 => get_seg_prefix_ss( + *reg16.offset(BP as isize) as i32 + *reg16.offset(DI as isize) as i32 + read_imm8s()? + & 65535i32, + ), + 131 | 139 | 147 | 155 | 163 | 171 | 179 | 187 => get_seg_prefix_ss( + *reg16.offset(BP as isize) as i32 + *reg16.offset(DI as isize) as i32 + read_imm16()? + & 65535i32, + ), 4 | 12 | 20 | 28 | 36 | 44 | 52 | 60 => { - return get_seg_prefix_ds(*reg16.offset(SI as isize) as i32 & 65535i32) + get_seg_prefix_ds(*reg16.offset(SI as isize) as i32 & 65535i32) }, 68 | 76 | 84 | 92 | 100 | 108 | 116 | 124 => { - return get_seg_prefix_ds(*reg16.offset(SI as isize) as i32 + read_imm8s() & 65535i32) + get_seg_prefix_ds(*reg16.offset(SI as isize) as i32 + read_imm8s()? & 65535i32) }, 132 | 140 | 148 | 156 | 164 | 172 | 180 | 188 => { - return get_seg_prefix_ds(*reg16.offset(SI as isize) as i32 + read_imm16() & 65535i32) + get_seg_prefix_ds(*reg16.offset(SI as isize) as i32 + read_imm16()? & 65535i32) }, 5 | 13 | 21 | 29 | 37 | 45 | 53 | 61 => { - return get_seg_prefix_ds(*reg16.offset(DI as isize) as i32 & 65535i32) + get_seg_prefix_ds(*reg16.offset(DI as isize) as i32 & 65535i32) }, 69 | 77 | 85 | 93 | 101 | 109 | 117 | 125 => { - return get_seg_prefix_ds(*reg16.offset(DI as isize) as i32 + read_imm8s() & 65535i32) + get_seg_prefix_ds(*reg16.offset(DI as isize) as i32 + read_imm8s()? & 65535i32) }, 133 | 141 | 149 | 157 | 165 | 173 | 181 | 189 => { - return get_seg_prefix_ds(*reg16.offset(DI as isize) as i32 + read_imm16() & 65535i32) + get_seg_prefix_ds(*reg16.offset(DI as isize) as i32 + read_imm16()? & 65535i32) }, - 6 | 14 | 22 | 30 | 38 | 46 | 54 | 62 => return get_seg_prefix_ds(read_imm16()), + 6 | 14 | 22 | 30 | 38 | 46 | 54 | 62 => get_seg_prefix_ds(read_imm16()?), 70 | 78 | 86 | 94 | 102 | 110 | 118 | 126 => { - return get_seg_prefix_ss(*reg16.offset(BP as isize) as i32 + read_imm8s() & 65535i32) + get_seg_prefix_ss(*reg16.offset(BP as isize) as i32 + read_imm8s()? & 65535i32) }, 134 | 142 | 150 | 158 | 166 | 174 | 182 | 190 => { - return get_seg_prefix_ss(*reg16.offset(BP as isize) as i32 + read_imm16() & 65535i32) + get_seg_prefix_ss(*reg16.offset(BP as isize) as i32 + read_imm16()? & 65535i32) }, 7 | 15 | 23 | 31 | 39 | 47 | 55 | 63 => { - return get_seg_prefix_ds(*reg16.offset(BX as isize) as i32 & 65535i32) + get_seg_prefix_ds(*reg16.offset(BX as isize) as i32 & 65535i32) }, 71 | 79 | 87 | 95 | 103 | 111 | 119 | 127 => { - return get_seg_prefix_ds(*reg16.offset(BX as isize) as i32 + read_imm8s() & 65535i32) + get_seg_prefix_ds(*reg16.offset(BX as isize) as i32 + read_imm8s()? & 65535i32) }, 135 | 143 | 151 | 159 | 167 | 175 | 183 | 191 => { - return get_seg_prefix_ds(*reg16.offset(BX as isize) as i32 + read_imm16() & 65535i32) + get_seg_prefix_ds(*reg16.offset(BX as isize) as i32 + read_imm16()? & 65535i32) }, _ => { dbg_assert!(0 != 0i32); - return 0i32; + 0i32 }, - }; + }) } #[no_mangle] -pub unsafe extern "C" fn resolve_modrm32(mut modrm_byte: i32) -> i32 { +pub unsafe extern "C" fn resolve_modrm32_(mut modrm_byte: i32) -> Result { let mut r: u8 = (modrm_byte & 7i32) as u8; dbg_assert!(modrm_byte < 192i32); - if r as i32 == 4i32 { + Ok(if r as i32 == 4i32 { if modrm_byte < 64i32 { - return resolve_sib(0 != 0i32); + resolve_sib(0 != 0i32)? } else { - return resolve_sib(0 != 1i32) + if modrm_byte < 128i32 { - read_imm8s() + resolve_sib(0 != 1i32)? + if modrm_byte < 128i32 { + read_imm8s()? } else { - read_imm32s() - }; + read_imm32s()? + } } } else if r as i32 == 5i32 { if modrm_byte < 64i32 { - return get_seg_prefix_ds(read_imm32s()); + get_seg_prefix_ds(read_imm32s()?) } else { - return get_seg_prefix_ss( + get_seg_prefix_ss( *reg32s.offset(EBP as isize) + if modrm_byte < 128i32 { - read_imm8s() + read_imm8s()? } else { - read_imm32s() + read_imm32s()? }, - ); + ) } } else if modrm_byte < 64i32 { - return get_seg_prefix_ds(*reg32s.offset(r as isize)); + get_seg_prefix_ds(*reg32s.offset(r as isize)) } else { - return get_seg_prefix_ds( + get_seg_prefix_ds( *reg32s.offset(r as isize) + if modrm_byte < 128i32 { - read_imm8s() + read_imm8s()? } else { - read_imm32s() + read_imm32s()? }, - ); - }; + ) + }) } -unsafe extern "C" fn resolve_sib(mut mod_0: bool) -> i32 { +unsafe extern "C" fn resolve_sib(mut mod_0: bool) -> Result { let mut s: u8 = 0; - let mut sib_byte: u8 = read_imm8() as u8; + let mut sib_byte: u8 = read_imm8()? as u8; let mut r: u8 = (sib_byte as i32 & 7i32) as u8; let mut m: u8 = (sib_byte as i32 >> 3i32 & 7i32) as u8; let mut base: i32 = 0; @@ -1042,7 +1001,7 @@ unsafe extern "C" fn resolve_sib(mut mod_0: bool) -> i32 { seg = SS } else { - base = read_imm32s(); + base = read_imm32s()?; seg = DS } } @@ -1058,7 +1017,7 @@ unsafe extern "C" fn resolve_sib(mut mod_0: bool) -> i32 { s = (sib_byte as i32 >> 6i32 & 3i32) as u8; offset = *reg32s.offset(m as isize) << s as i32 } - return get_seg_prefix(seg) + base + offset; + Ok(get_seg_prefix(seg) + base + offset) } #[no_mangle] pub unsafe extern "C" fn MODRM_ENTRY() -> i32 { return 0i32; } @@ -1067,77 +1026,63 @@ pub unsafe extern "C" fn MODRM_ENTRY16() -> i32 { return 0i32; } #[no_mangle] pub unsafe extern "C" fn MODRM_ENTRY32() -> i32 { return 0i32; } #[no_mangle] -pub unsafe extern "C" fn resolve_modrm32_(mut modrm_byte: i32) -> i32 { - match modrm_byte { - 0 | 8 | 16 | 24 | 32 | 40 | 48 | 56 => { - return get_seg_prefix_ds(*reg32s.offset(EAX as isize)) - }, +pub unsafe extern "C" fn resolve_modrm32(mut modrm_byte: i32) -> Result { + Ok(match modrm_byte { + 0 | 8 | 16 | 24 | 32 | 40 | 48 | 56 => get_seg_prefix_ds(*reg32s.offset(EAX as isize)), 64 | 72 | 80 | 88 | 96 | 104 | 112 | 120 => { - return get_seg_prefix_ds(*reg32s.offset(EAX as isize) + read_imm8s()) + get_seg_prefix_ds(*reg32s.offset(EAX as isize) + read_imm8s()?) }, 128 | 136 | 144 | 152 | 160 | 168 | 176 | 184 => { - return get_seg_prefix_ds(*reg32s.offset(EAX as isize) + read_imm32s()) - }, - 1 | 9 | 17 | 25 | 33 | 41 | 49 | 57 => { - return get_seg_prefix_ds(*reg32s.offset(ECX as isize)) + get_seg_prefix_ds(*reg32s.offset(EAX as isize) + read_imm32s()?) }, + 1 | 9 | 17 | 25 | 33 | 41 | 49 | 57 => get_seg_prefix_ds(*reg32s.offset(ECX as isize)), 65 | 73 | 81 | 89 | 97 | 105 | 113 | 121 => { - return get_seg_prefix_ds(*reg32s.offset(ECX as isize) + read_imm8s()) + get_seg_prefix_ds(*reg32s.offset(ECX as isize) + read_imm8s()?) }, 129 | 137 | 145 | 153 | 161 | 169 | 177 | 185 => { - return get_seg_prefix_ds(*reg32s.offset(ECX as isize) + read_imm32s()) - }, - 2 | 10 | 18 | 26 | 34 | 42 | 50 | 58 => { - return get_seg_prefix_ds(*reg32s.offset(EDX as isize)) + get_seg_prefix_ds(*reg32s.offset(ECX as isize) + read_imm32s()?) }, + 2 | 10 | 18 | 26 | 34 | 42 | 50 | 58 => get_seg_prefix_ds(*reg32s.offset(EDX as isize)), 66 | 74 | 82 | 90 | 98 | 106 | 114 | 122 => { - return get_seg_prefix_ds(*reg32s.offset(EDX as isize) + read_imm8s()) + get_seg_prefix_ds(*reg32s.offset(EDX as isize) + read_imm8s()?) }, 130 | 138 | 146 | 154 | 162 | 170 | 178 | 186 => { - return get_seg_prefix_ds(*reg32s.offset(EDX as isize) + read_imm32s()) - }, - 3 | 11 | 19 | 27 | 35 | 43 | 51 | 59 => { - return get_seg_prefix_ds(*reg32s.offset(EBX as isize)) + get_seg_prefix_ds(*reg32s.offset(EDX as isize) + read_imm32s()?) }, + 3 | 11 | 19 | 27 | 35 | 43 | 51 | 59 => get_seg_prefix_ds(*reg32s.offset(EBX as isize)), 67 | 75 | 83 | 91 | 99 | 107 | 115 | 123 => { - return get_seg_prefix_ds(*reg32s.offset(EBX as isize) + read_imm8s()) + get_seg_prefix_ds(*reg32s.offset(EBX as isize) + read_imm8s()?) }, 131 | 139 | 147 | 155 | 163 | 171 | 179 | 187 => { - return get_seg_prefix_ds(*reg32s.offset(EBX as isize) + read_imm32s()) + get_seg_prefix_ds(*reg32s.offset(EBX as isize) + read_imm32s()?) }, - 4 | 12 | 20 | 28 | 36 | 44 | 52 | 60 => return resolve_sib(0 != 0i32), - 68 | 76 | 84 | 92 | 100 | 108 | 116 | 124 => return resolve_sib(0 != 1i32) + read_imm8s(), - 132 | 140 | 148 | 156 | 164 | 172 | 180 | 188 => { - return resolve_sib(0 != 1i32) + read_imm32s() - }, - 5 | 13 | 21 | 29 | 37 | 45 | 53 | 61 => return get_seg_prefix_ds(read_imm32s()), + 4 | 12 | 20 | 28 | 36 | 44 | 52 | 60 => resolve_sib(0 != 0i32)?, + 68 | 76 | 84 | 92 | 100 | 108 | 116 | 124 => resolve_sib(0 != 1i32)? + read_imm8s()?, + 132 | 140 | 148 | 156 | 164 | 172 | 180 | 188 => resolve_sib(0 != 1i32)? + read_imm32s()?, + 5 | 13 | 21 | 29 | 37 | 45 | 53 | 61 => get_seg_prefix_ds(read_imm32s()?), 69 | 77 | 85 | 93 | 101 | 109 | 117 | 125 => { - return get_seg_prefix_ss(*reg32s.offset(EBP as isize) + read_imm8s()) + get_seg_prefix_ss(*reg32s.offset(EBP as isize) + read_imm8s()?) }, 133 | 141 | 149 | 157 | 165 | 173 | 181 | 189 => { - return get_seg_prefix_ss(*reg32s.offset(EBP as isize) + read_imm32s()) - }, - 6 | 14 | 22 | 30 | 38 | 46 | 54 | 62 => { - return get_seg_prefix_ds(*reg32s.offset(ESI as isize)) + get_seg_prefix_ss(*reg32s.offset(EBP as isize) + read_imm32s()?) }, + 6 | 14 | 22 | 30 | 38 | 46 | 54 | 62 => get_seg_prefix_ds(*reg32s.offset(ESI as isize)), 70 | 78 | 86 | 94 | 102 | 110 | 118 | 126 => { - return get_seg_prefix_ds(*reg32s.offset(ESI as isize) + read_imm8s()) + get_seg_prefix_ds(*reg32s.offset(ESI as isize) + read_imm8s()?) }, 134 | 142 | 150 | 158 | 166 | 174 | 182 | 190 => { - return get_seg_prefix_ds(*reg32s.offset(ESI as isize) + read_imm32s()) - }, - 7 | 15 | 23 | 31 | 39 | 47 | 55 | 63 => { - return get_seg_prefix_ds(*reg32s.offset(EDI as isize)) + get_seg_prefix_ds(*reg32s.offset(ESI as isize) + read_imm32s()?) }, + 7 | 15 | 23 | 31 | 39 | 47 | 55 | 63 => get_seg_prefix_ds(*reg32s.offset(EDI as isize)), 71 | 79 | 87 | 95 | 103 | 111 | 119 | 127 => { - return get_seg_prefix_ds(*reg32s.offset(EDI as isize) + read_imm8s()) + get_seg_prefix_ds(*reg32s.offset(EDI as isize) + read_imm8s()?) }, 135 | 143 | 151 | 159 | 167 | 175 | 183 | 191 => { - return get_seg_prefix_ds(*reg32s.offset(EDI as isize) + read_imm32s()) + get_seg_prefix_ds(*reg32s.offset(EDI as isize) + read_imm32s()?) }, _ => { dbg_assert!(0 != 0i32); - return 0i32; + 0i32 }, - }; + }) } diff --git a/src/rust/js_api.rs b/src/rust/js_api.rs new file mode 100644 index 00000000..43806b66 --- /dev/null +++ b/src/rust/js_api.rs @@ -0,0 +1,43 @@ +use cpu2::cpu::{ + safe_read16, safe_read32s, safe_write16, safe_write32, translate_address_read, + translate_address_system_read, translate_address_system_write, writable_or_pagefault, +}; +use cpu2::misc_instr::{pop16, pop32s, push16, push32}; + +#[no_mangle] +pub unsafe fn safe_read16_js(addr: i32) -> i32 { safe_read16(addr).unwrap() } +#[no_mangle] +pub unsafe fn safe_read32s_js(addr: i32) -> i32 { safe_read32s(addr).unwrap() } + +#[no_mangle] +pub unsafe fn safe_write16_js(addr: i32, value: i32) { safe_write16(addr, value).unwrap() } +#[no_mangle] +pub unsafe fn safe_write32_js(addr: i32, value: i32) { safe_write32(addr, value).unwrap() } + +#[no_mangle] +pub unsafe fn translate_address_read_js(addr: i32) -> u32 { translate_address_read(addr).unwrap() } +#[no_mangle] +pub unsafe fn translate_address_system_read_js(addr: i32) -> u32 { + translate_address_system_read(addr).unwrap() +} +#[no_mangle] +pub unsafe fn translate_address_system_write_js(addr: i32) -> u32 { + translate_address_system_write(addr).unwrap() +} + +#[no_mangle] +pub unsafe fn writable_or_pagefault_js(addr: i32, size: i32) -> bool { + writable_or_pagefault(addr, size).is_ok() +} + +#[no_mangle] +pub unsafe fn push16_js(value: i32) { push16(value).unwrap() } + +#[no_mangle] +pub unsafe fn push32_js(value: i32) { push32(value).unwrap() } + +#[no_mangle] +pub unsafe fn pop16_js() -> i32 { pop16().unwrap() } + +#[no_mangle] +pub unsafe fn pop32s_js() -> i32 { pop32s().unwrap() } diff --git a/src/rust/lib.rs b/src/rust/lib.rs index 6ec12ce0..b4334a7f 100644 --- a/src/rust/lib.rs +++ b/src/rust/lib.rs @@ -8,9 +8,13 @@ extern crate quickcheck; #[macro_use] mod dbg; +#[macro_use] +mod paging; + pub mod cpu2; pub mod c_api; +pub mod js_api; mod analysis; mod codegen; diff --git a/src/rust/paging.rs b/src/rust/paging.rs new file mode 100644 index 00000000..e92f0464 --- /dev/null +++ b/src/rust/paging.rs @@ -0,0 +1,8 @@ +macro_rules! return_on_pagefault { + ($expr:expr) => { + match $expr { + Ok(v) => v, + Err(()) => return, + } + }; +} From 25949fff70fc62f86cc330d477293cda514d8fff Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 14 Aug 2018 16:20:51 -0500 Subject: [PATCH 1190/2137] Handle page faults in instructions using return_on_pagefault and writable_or_pagefault --- src/rust/cpu2/arith.rs | 17 +- src/rust/cpu2/fpu.rs | 151 +++---- src/rust/cpu2/global_pointers.rs | 13 +- src/rust/cpu2/instructions.rs | 681 +++++++++++++++++------------- src/rust/cpu2/instructions_0f.rs | 694 +++++++++++++++---------------- src/rust/cpu2/misc_instr.rs | 118 +++--- src/rust/cpu2/sse_instr.rs | 60 +-- src/rust/cpu2/string.rs | 189 +++++---- 8 files changed, 993 insertions(+), 930 deletions(-) diff --git a/src/rust/cpu2/arith.rs b/src/rust/cpu2/arith.rs index 0eba1166..e0a48444 100644 --- a/src/rust/cpu2/arith.rs +++ b/src/rust/cpu2/arith.rs @@ -8,6 +8,8 @@ )] #![feature(extern_types, libc)] +use cpu2::cpu::*; + extern "C" { #[no_mangle] @@ -70,10 +72,6 @@ extern "C" { #[no_mangle] fn c_comment(m: *const i8) -> (); #[no_mangle] - fn safe_read8(addr: i32) -> i32; - #[no_mangle] - fn translate_address_write(address: i32) -> u32; - #[no_mangle] fn read8(addr: u32) -> i32; #[no_mangle] fn write8(addr: u32, value: i32) -> (); @@ -1910,14 +1908,15 @@ pub unsafe extern "C" fn btr_reg(mut bit_base: i32, mut bit_offset: i32) -> i32 } #[no_mangle] pub unsafe extern "C" fn bt_mem(mut virt_addr: i32, mut bit_offset: i32) -> () { - let mut bit_base: i32 = safe_read8(virt_addr + (bit_offset >> 3i32)); + let mut bit_base: i32 = return_on_pagefault!(safe_read8(virt_addr + (bit_offset >> 3i32))); bit_offset &= 7i32; *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; *flags_changed &= !1i32; } #[no_mangle] pub unsafe extern "C" fn btc_mem(mut virt_addr: i32, mut bit_offset: i32) -> () { - let mut phys_addr: i32 = translate_address_write(virt_addr + (bit_offset >> 3i32)) as i32; + let mut phys_addr: i32 = + return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3i32))) as i32; let mut bit_base: i32 = read8(phys_addr as u32); bit_offset &= 7i32; *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; @@ -1926,7 +1925,8 @@ pub unsafe extern "C" fn btc_mem(mut virt_addr: i32, mut bit_offset: i32) -> () } #[no_mangle] pub unsafe extern "C" fn btr_mem(mut virt_addr: i32, mut bit_offset: i32) -> () { - let mut phys_addr: i32 = translate_address_write(virt_addr + (bit_offset >> 3i32)) as i32; + let mut phys_addr: i32 = + return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3i32))) as i32; let mut bit_base: i32 = read8(phys_addr as u32); bit_offset &= 7i32; *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; @@ -1935,7 +1935,8 @@ pub unsafe extern "C" fn btr_mem(mut virt_addr: i32, mut bit_offset: i32) -> () } #[no_mangle] pub unsafe extern "C" fn bts_mem(mut virt_addr: i32, mut bit_offset: i32) -> () { - let mut phys_addr: i32 = translate_address_write(virt_addr + (bit_offset >> 3i32)) as i32; + let mut phys_addr: i32 = + return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3i32))) as i32; let mut bit_base: i32 = read8(phys_addr as u32); bit_offset &= 7i32; *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 3957845d..00a6980e 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -1,7 +1,14 @@ -#![allow -( dead_code , mutable_transmutes , non_camel_case_types , non_snake_case , -non_upper_case_globals , unused_mut )] -#![feature ( extern_types , libc )] +#![allow( + dead_code, + mutable_transmutes, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_mut +)] +#![feature(extern_types, libc)] + +use cpu2::cpu::*; extern "C" { @@ -323,24 +330,10 @@ extern "C" { #[no_mangle] static CPU_EXCEPTION_VE: i32; #[no_mangle] - fn writable_or_pagefault(addr: i32, size: i32) -> (); - #[no_mangle] fn is_osize_32() -> bool; #[no_mangle] fn trigger_ud() -> (); #[no_mangle] - fn safe_read16(addr: i32) -> i32; - #[no_mangle] - fn safe_read32s(address: i32) -> i32; - #[no_mangle] - fn safe_read64s(addr: i32) -> reg64; - #[no_mangle] - fn safe_write16(addr: i32, value: i32) -> (); - #[no_mangle] - fn safe_write32(address: i32, value: i32) -> (); - #[no_mangle] - fn safe_write64(addr: i32, value: i64) -> (); - #[no_mangle] static fpu_stack_ptr: *mut u32; #[no_mangle] static fpu_st: *mut f64; @@ -974,29 +967,29 @@ pub unsafe extern "C" fn fpu_integer_round(mut f: f64) -> f64 { }; } #[no_mangle] -pub unsafe extern "C" fn fpu_load_m32(mut addr: i32) -> f64 { +pub unsafe extern "C" fn fpu_load_m32(mut addr: i32) -> Result { let mut v: f32_int = f32_int { - i32_0: safe_read32s(addr), + i32_0: safe_read32s(addr)?, }; - return v.f32_0 as f64; + Ok(v.f32_0 as f64) } #[no_mangle] -pub unsafe extern "C" fn fpu_load_m64(mut addr: i32) -> f64 { - let mut value: u64 = safe_read64s(addr).u64_0[0usize]; +pub unsafe extern "C" fn fpu_load_m64(mut addr: i32) -> Result { + let mut value: u64 = safe_read64s(addr)?.u64_0[0usize]; let mut v: f64_int = f64_int { u64_0: [value] }; - return v.f64_0; + Ok(v.f64_0) } #[no_mangle] -pub unsafe extern "C" fn fpu_load_m80(mut addr: u32) -> f64 { - let mut value: u64 = safe_read64s(addr as i32).u64_0[0usize]; +pub unsafe extern "C" fn fpu_load_m80(mut addr: u32) -> Result { + let mut value: u64 = safe_read64s(addr as i32)?.u64_0[0usize]; let mut low: u32 = value as u32; let mut high: u32 = (value >> 32i32) as u32; - let mut exponent: i32 = safe_read16(addr.wrapping_add(8i32 as u32) as i32); + let mut exponent: i32 = safe_read16(addr.wrapping_add(8i32 as u32) as i32)?; let mut sign: i32 = exponent >> 15i32; exponent &= !32768i32; if exponent == 0i32 { c_comment!(("TODO: denormal numbers")); - return 0i32 as f64; + Ok(0i32 as f64) } else if exponent < 32767i32 { exponent -= 16383i32; @@ -1008,7 +1001,7 @@ pub unsafe extern "C" fn fpu_load_m80(mut addr: u32) -> f64 { c_comment!(("Simply compute the 64 bit floating point number.")); c_comment!(("An alternative write the mantissa, sign and exponent in the")); c_comment!(("float64_byte and return float64[0]")); - return mantissa * pow(2i32 as f64, (exponent - 63i32) as f64); + Ok(mantissa * pow(2i32 as f64, (exponent - 63i32) as f64)) } else { c_comment!(("TODO: NaN, Infinity")); @@ -1021,8 +1014,8 @@ pub unsafe extern "C" fn fpu_load_m80(mut addr: u32) -> f64 { double_int_view.u8_0[5usize] = 0i32 as u8; double_int_view.u8_0[4usize] = 0i32 as u8; double_int_view.i32_0[0usize] = 0i32; - return double_int_view.f64_0; - }; + Ok(double_int_view.f64_0) + } } #[no_mangle] pub unsafe extern "C" fn fpu_load_status_word() -> i32 { @@ -1110,7 +1103,7 @@ pub unsafe extern "C" fn fpu_ffree(mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn fpu_fildm64(mut addr: i32) -> () { - let mut value: i64 = safe_read64s(addr).i64_0[0usize]; + let mut value: i64 = return_on_pagefault!(safe_read64s(addr)).i64_0[0usize]; let mut m64: f64 = value as f64; fpu_push(m64); } @@ -1142,11 +1135,11 @@ pub unsafe extern "C" fn fpu_finit() -> () { pub unsafe extern "C" fn fpu_fistm16(mut addr: i32) -> () { let mut st0: f64 = fpu_integer_round(fpu_get_st0()); if st0 <= 32767i32 as f64 && st0 >= -32768i32 as f64 { - safe_write16(addr, st0 as i32); + return_on_pagefault!(safe_write16(addr, st0 as i32)); } else { fpu_invalid_arithmetic(); - safe_write16(addr, 32768i32); + return_on_pagefault!(safe_write16(addr, 32768i32)); }; } #[no_mangle] @@ -1165,7 +1158,7 @@ pub unsafe extern "C" fn fpu_fistm32(mut addr: i32) -> () { c_comment!(("(input fits, but same value as error value)")); fpu_invalid_arithmetic(); } - safe_write32(addr, i); + return_on_pagefault!(safe_write32(addr, i)); } #[no_mangle] pub unsafe extern "C" fn fpu_fistm32p(mut addr: i32) -> () { @@ -1183,27 +1176,30 @@ pub unsafe extern "C" fn fpu_fistm64p(mut addr: i32) -> () { value = 9223372036854775808u64 as i64; fpu_invalid_arithmetic(); } - safe_write64(addr, value); + return_on_pagefault!(safe_write64(addr, value)); fpu_pop(); } #[no_mangle] pub static mut TWO_POW_63: f64 = unsafe { 9223372036854775808u64 as f64 }; #[no_mangle] pub unsafe extern "C" fn fpu_fldcw(mut addr: i32) -> () { - let mut word: i32 = safe_read16(addr); + let mut word: i32 = return_on_pagefault!(safe_read16(addr)); *fpu_control_word = word; } #[no_mangle] pub unsafe extern "C" fn fpu_fldenv(mut addr: i32) -> () { if is_osize_32() { - *fpu_control_word = safe_read16(addr); - fpu_set_status_word(safe_read16(addr + 4i32)); - fpu_set_tag_word(safe_read16(addr + 8i32)); - *fpu_ip.offset(0isize) = safe_read32s(addr + 12i32); - *fpu_ip_selector.offset(0isize) = safe_read16(addr + 16i32); - *fpu_opcode.offset(0isize) = safe_read16(addr + 18i32); - *fpu_dp.offset(0isize) = safe_read32s(addr + 20i32); - *fpu_dp_selector.offset(0isize) = safe_read16(addr + 24i32) + // TODO: Add readable_or_pagefault + return_on_pagefault!(translate_address_read(addr)); + return_on_pagefault!(translate_address_read(addr + 28)); + *fpu_control_word = safe_read16(addr).unwrap(); + fpu_set_status_word(safe_read16(addr + 4i32).unwrap()); + fpu_set_tag_word(safe_read16(addr + 8i32).unwrap()); + *fpu_ip.offset(0isize) = safe_read32s(addr + 12i32).unwrap(); + *fpu_ip_selector.offset(0isize) = safe_read16(addr + 16i32).unwrap(); + *fpu_opcode.offset(0isize) = safe_read16(addr + 18i32).unwrap(); + *fpu_dp.offset(0isize) = safe_read32s(addr + 20i32).unwrap(); + *fpu_dp_selector.offset(0isize) = safe_read16(addr + 24i32).unwrap() } else { dbg_log_c!(("fldenv16")); @@ -1234,11 +1230,17 @@ pub unsafe extern "C" fn fpu_set_status_word(mut sw: i32) -> () { *fpu_stack_ptr = (sw >> 11i32 & 7i32) as u32; } #[no_mangle] -pub unsafe extern "C" fn fpu_fldm32(mut addr: i32) -> () { fpu_push(safe_read32s(addr) as f64); } +pub unsafe extern "C" fn fpu_fldm32(mut addr: i32) -> () { + fpu_push(return_on_pagefault!(safe_read32s(addr)) as f64); +} #[no_mangle] -pub unsafe extern "C" fn fpu_fldm64(mut addr: i32) -> () { fpu_push(fpu_load_m64(addr)); } +pub unsafe extern "C" fn fpu_fldm64(mut addr: i32) -> () { + fpu_push(return_on_pagefault!(fpu_load_m64(addr))); +} #[no_mangle] -pub unsafe extern "C" fn fpu_fldm80(mut addr: i32) -> () { fpu_push(fpu_load_m80(addr as u32)); } +pub unsafe extern "C" fn fpu_fldm80(mut addr: i32) -> () { + fpu_push(return_on_pagefault!(fpu_load_m80(addr as u32))); +} #[no_mangle] pub unsafe extern "C" fn fpu_fmul(mut target_index: i32, mut val: f64) -> () { let mut st0: f64 = fpu_get_st0(); @@ -1247,7 +1249,7 @@ pub unsafe extern "C" fn fpu_fmul(mut target_index: i32, mut val: f64) -> () { } #[no_mangle] pub unsafe extern "C" fn fpu_fnstsw_mem(mut addr: i32) -> () { - safe_write16(addr, fpu_load_status_word()); + return_on_pagefault!(safe_write16(addr, fpu_load_status_word())); } #[no_mangle] pub unsafe extern "C" fn fpu_fnstsw_reg() -> () { @@ -1274,19 +1276,22 @@ pub unsafe extern "C" fn fpu_fprem() -> () { } #[no_mangle] pub unsafe extern "C" fn fpu_frstor(mut addr: i32) -> () { + // TODO: Add readable_or_pagefault + return_on_pagefault!(translate_address_read(addr)); + return_on_pagefault!(translate_address_read(addr + 28 + 8 * 10)); fpu_fldenv(addr); addr += 28i32; let mut i: i32 = 0i32; while i < 8i32 { *fpu_st.offset(((i as u32).wrapping_add(*fpu_stack_ptr) & 7i32 as u32) as isize) = - fpu_load_m80(addr as u32); + fpu_load_m80(addr as u32).unwrap(); addr += 10i32; i += 1 } } #[no_mangle] pub unsafe extern "C" fn fpu_fsave(mut addr: i32) -> () { - writable_or_pagefault(addr, 108i32); + return_on_pagefault!(writable_or_pagefault(addr, 108i32)); fpu_fstenv(addr); addr += 28i32; let mut i: i32 = 0i32; @@ -1334,24 +1339,24 @@ pub unsafe extern "C" fn fpu_store_m80(mut addr: u32, mut n: f64) -> () { safe_write64( addr as i32, (low as u64 & 4294967295u32 as u64 | (high as u64) << 32i32) as i64, - ); + ).unwrap(); safe_write16( addr.wrapping_add(8i32 as u32) as i32, (sign as i32) << 8i32 | exponent, - ); + ).unwrap(); } #[no_mangle] pub unsafe extern "C" fn fpu_fstenv(mut addr: i32) -> () { if is_osize_32() { - writable_or_pagefault(addr, 26i32); - safe_write16(addr, *fpu_control_word); - safe_write16(addr + 4i32, fpu_load_status_word()); - safe_write16(addr + 8i32, fpu_load_tag_word()); - safe_write32(addr + 12i32, *fpu_ip.offset(0isize)); - safe_write16(addr + 16i32, *fpu_ip_selector.offset(0isize)); - safe_write16(addr + 18i32, *fpu_opcode.offset(0isize)); - safe_write32(addr + 20i32, *fpu_dp.offset(0isize)); - safe_write16(addr + 24i32, *fpu_dp_selector.offset(0isize)); + return_on_pagefault!(writable_or_pagefault(addr, 26i32)); + safe_write16(addr, *fpu_control_word).unwrap(); + safe_write16(addr + 4i32, fpu_load_status_word()).unwrap(); + safe_write16(addr + 8i32, fpu_load_tag_word()).unwrap(); + safe_write32(addr + 12i32, *fpu_ip.offset(0isize)).unwrap(); + safe_write16(addr + 16i32, *fpu_ip_selector.offset(0isize)).unwrap(); + safe_write16(addr + 18i32, *fpu_opcode.offset(0isize)).unwrap(); + safe_write32(addr + 20i32, *fpu_dp.offset(0isize)).unwrap(); + safe_write16(addr + 24i32, *fpu_dp_selector.offset(0isize)).unwrap(); } else { dbg_log_c!(("fstenv16")); @@ -1383,18 +1388,22 @@ pub unsafe extern "C" fn fpu_fst(mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn fpu_fst80p(mut addr: i32) -> () { - writable_or_pagefault(addr, 10i32); + return_on_pagefault!(writable_or_pagefault(addr, 10i32)); fpu_store_m80(addr as u32, fpu_get_st0()); fpu_pop(); } #[no_mangle] -pub unsafe extern "C" fn fpu_fstcw(mut addr: i32) -> () { safe_write16(addr, *fpu_control_word); } +pub unsafe extern "C" fn fpu_fstcw(mut addr: i32) -> () { + return_on_pagefault!(safe_write16(addr, *fpu_control_word)); +} #[no_mangle] -pub unsafe extern "C" fn fpu_fstm32(mut addr: i32) -> () { fpu_store_m32(addr, fpu_get_st0()); } +pub unsafe extern "C" fn fpu_fstm32(mut addr: i32) -> () { + return_on_pagefault!(fpu_store_m32(addr, fpu_get_st0())); +} #[no_mangle] -pub unsafe extern "C" fn fpu_store_m32(mut addr: i32, mut x: f64) -> () { +pub unsafe extern "C" fn fpu_store_m32(mut addr: i32, mut x: f64) -> Result<(), ()> { let mut v: f32_int = f32_int { f32_0: x as f32 }; - safe_write32(addr, v.i32_0); + safe_write32(addr, v.i32_0) } #[no_mangle] pub unsafe extern "C" fn fpu_fstm32p(mut addr: i32) -> () { @@ -1402,11 +1411,13 @@ pub unsafe extern "C" fn fpu_fstm32p(mut addr: i32) -> () { fpu_pop(); } #[no_mangle] -pub unsafe extern "C" fn fpu_fstm64(mut addr: i32) -> () { fpu_store_m64(addr, fpu_get_st0()); } +pub unsafe extern "C" fn fpu_fstm64(mut addr: i32) -> () { + return_on_pagefault!(fpu_store_m64(addr, fpu_get_st0())); +} #[no_mangle] -pub unsafe extern "C" fn fpu_store_m64(mut addr: i32, mut x: f64) -> () { +pub unsafe extern "C" fn fpu_store_m64(mut addr: i32, mut x: f64) -> Result<(), ()> { let mut v: f64_int = f64_int { f64_0: x }; - safe_write64(addr, v.u64_0[0usize] as i64); + safe_write64(addr, v.u64_0[0usize] as i64) } #[no_mangle] pub unsafe extern "C" fn fpu_fstm64p(mut addr: i32) -> () { diff --git a/src/rust/cpu2/global_pointers.rs b/src/rust/cpu2/global_pointers.rs index 42f635ae..fceaaa97 100644 --- a/src/rust/cpu2/global_pointers.rs +++ b/src/rust/cpu2/global_pointers.rs @@ -1,7 +1,12 @@ -#![allow -( dead_code , mutable_transmutes , non_camel_case_types , non_snake_case , -non_upper_case_globals , unused_mut )] -#![feature ( extern_types , libc )] +#![allow( + dead_code, + mutable_transmutes, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_mut +)] +#![feature(extern_types, libc)] extern "C" { pub type reg128; diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index cd5eb027..a085cf50 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -1,7 +1,16 @@ -#![allow -( dead_code , mutable_transmutes , non_camel_case_types , non_snake_case , -non_upper_case_globals , unused_mut )] -#![feature ( extern_types , libc )] +#![allow( + dead_code, + mutable_transmutes, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_mut +)] +#![feature(extern_types, libc)] + +use cpu2::cpu::*; +use cpu2::fpu::{fpu_load_m32, fpu_load_m64}; +use cpu2::misc_instr::{pop16, pop32s, push16, push32}; extern "C" { @@ -485,10 +494,6 @@ extern "C" { #[no_mangle] fn get_eflags() -> i32; #[no_mangle] - fn translate_address_read(address: i32) -> u32; - #[no_mangle] - fn read_imm8() -> i32; - #[no_mangle] fn is_asize_32() -> bool; #[no_mangle] fn get_seg_cs() -> i32; @@ -509,18 +514,6 @@ extern "C" { #[no_mangle] fn trigger_gp_non_raising(code: i32) -> (); #[no_mangle] - fn safe_read8(addr: i32) -> i32; - #[no_mangle] - fn safe_read16(addr: i32) -> i32; - #[no_mangle] - fn safe_read32s(address: i32) -> i32; - #[no_mangle] - fn safe_write8(addr: i32, value: i32) -> (); - #[no_mangle] - fn safe_write16(addr: i32, value: i32) -> (); - #[no_mangle] - fn safe_write32(address: i32, value: i32) -> (); - #[no_mangle] fn get_reg8_index(index: i32) -> i32; #[no_mangle] fn read_reg8(index: i32) -> i32; @@ -571,10 +564,6 @@ extern "C" { #[no_mangle] fn fpu_integer_round(f: f64) -> f64; #[no_mangle] - fn fpu_load_m32(addr: i32) -> f64; - #[no_mangle] - fn fpu_load_m64(addr: i32) -> f64; - #[no_mangle] fn fpu_fadd(target_index: i32, val: f64) -> (); #[no_mangle] fn fpu_fclex() -> (); @@ -802,10 +791,6 @@ extern "C" { #[no_mangle] #[no_mangle] #[no_mangle] - fn push16(imm16: i32) -> (); - #[no_mangle] - fn push32(imm32: i32) -> (); - #[no_mangle] fn adjust_stack_reg(adjustment: i32) -> (); #[no_mangle] fn get_stack_pointer(offset: i32) -> i32; @@ -816,10 +801,6 @@ extern "C" { #[no_mangle] fn run_instruction0f_32(opcode: i32) -> (); #[no_mangle] - fn pop16() -> i32; - #[no_mangle] - fn pop32s() -> i32; - #[no_mangle] fn pusha16() -> (); #[no_mangle] fn pusha32() -> (); @@ -1461,7 +1442,7 @@ pub unsafe extern "C" fn instr32_01_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_02_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read8(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, add8(read_reg8(r), ____0)); } #[no_mangle] @@ -1471,7 +1452,7 @@ pub unsafe extern "C" fn instr_02_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_03_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, add16(read_reg16(r), ____0)); } #[no_mangle] @@ -1481,7 +1462,7 @@ pub unsafe extern "C" fn instr16_03_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_03_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, add32(read_reg32(r), ____0)); } #[no_mangle] @@ -1502,12 +1483,19 @@ pub unsafe extern "C" fn instr32_05(mut imm32: i32) -> () { *reg32s.offset(EAX as isize) = add32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] -pub unsafe extern "C" fn instr16_06() -> () { push16(*sreg.offset(ES as isize) as i32); } +pub unsafe extern "C" fn instr16_06() -> () { + return_on_pagefault!(push16(*sreg.offset(ES as isize) as i32)); +} #[no_mangle] -pub unsafe extern "C" fn instr32_06() -> () { push32(*sreg.offset(ES as isize) as i32); } +pub unsafe extern "C" fn instr32_06() -> () { + return_on_pagefault!(push32(*sreg.offset(ES as isize) as i32)); +} #[no_mangle] pub unsafe extern "C" fn instr16_07() -> () { - if !switch_seg(ES, safe_read16(get_stack_pointer(0i32))) { + if !switch_seg( + ES, + return_on_pagefault!(safe_read16(get_stack_pointer(0i32))), + ) { return; } else { @@ -1517,7 +1505,10 @@ pub unsafe extern "C" fn instr16_07() -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_07() -> () { - if !switch_seg(ES, safe_read32s(get_stack_pointer(0i32)) & 65535i32) { + if !switch_seg( + ES, + return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))) & 65535i32, + ) { return; } else { @@ -1554,7 +1545,7 @@ pub unsafe extern "C" fn instr32_09_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0A_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read8(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, or8(read_reg8(r), ____0)); } #[no_mangle] @@ -1564,7 +1555,7 @@ pub unsafe extern "C" fn instr_0A_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0B_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, or16(read_reg16(r), ____0)); } #[no_mangle] @@ -1574,7 +1565,7 @@ pub unsafe extern "C" fn instr16_0B_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0B_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, or32(read_reg32(r), ____0)); } #[no_mangle] @@ -1595,13 +1586,21 @@ pub unsafe extern "C" fn instr32_0D(mut imm32: i32) -> () { *reg32s.offset(EAX as isize) = or32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] -pub unsafe extern "C" fn instr16_0E() -> () { push16(*sreg.offset(CS as isize) as i32); } +pub unsafe extern "C" fn instr16_0E() -> () { + return_on_pagefault!(push16(*sreg.offset(CS as isize) as i32)); +} #[no_mangle] -pub unsafe extern "C" fn instr32_0E() -> () { push32(*sreg.offset(CS as isize) as i32); } +pub unsafe extern "C" fn instr32_0E() -> () { + return_on_pagefault!(push32(*sreg.offset(CS as isize) as i32)); +} #[no_mangle] -pub unsafe extern "C" fn instr16_0F() -> () { run_instruction0f_16(read_imm8()); } +pub unsafe extern "C" fn instr16_0F() -> () { + run_instruction0f_16(return_on_pagefault!(read_imm8())); +} #[no_mangle] -pub unsafe extern "C" fn instr32_0F() -> () { run_instruction0f_32(read_imm8()); } +pub unsafe extern "C" fn instr32_0F() -> () { + run_instruction0f_32(return_on_pagefault!(read_imm8())); +} #[no_mangle] pub unsafe extern "C" fn instr_10_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE8!(___, addr, adc8(___, read_reg8(r))); @@ -1631,7 +1630,7 @@ pub unsafe extern "C" fn instr32_11_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_12_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read8(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, adc8(read_reg8(r), ____0)); } #[no_mangle] @@ -1641,7 +1640,7 @@ pub unsafe extern "C" fn instr_12_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_13_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, adc16(read_reg16(r), ____0)); } #[no_mangle] @@ -1651,7 +1650,7 @@ pub unsafe extern "C" fn instr16_13_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_13_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, adc32(read_reg32(r), ____0)); } #[no_mangle] @@ -1672,12 +1671,19 @@ pub unsafe extern "C" fn instr32_15(mut imm32: i32) -> () { *reg32s.offset(EAX as isize) = adc32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] -pub unsafe extern "C" fn instr16_16() -> () { push16(*sreg.offset(SS as isize) as i32); } +pub unsafe extern "C" fn instr16_16() -> () { + return_on_pagefault!(push16(*sreg.offset(SS as isize) as i32)); +} #[no_mangle] -pub unsafe extern "C" fn instr32_16() -> () { push32(*sreg.offset(SS as isize) as i32); } +pub unsafe extern "C" fn instr32_16() -> () { + return_on_pagefault!(push32(*sreg.offset(SS as isize) as i32)); +} #[no_mangle] pub unsafe extern "C" fn instr16_17() -> () { - if !switch_seg(SS, safe_read16(get_stack_pointer(0i32))) { + if !switch_seg( + SS, + return_on_pagefault!(safe_read16(get_stack_pointer(0i32))), + ) { return; } else { @@ -1687,7 +1693,10 @@ pub unsafe extern "C" fn instr16_17() -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_17() -> () { - if !switch_seg(SS, safe_read32s(get_stack_pointer(0i32)) & 65535i32) { + if !switch_seg( + SS, + return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))) & 65535i32, + ) { return; } else { @@ -1724,7 +1733,7 @@ pub unsafe extern "C" fn instr32_19_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_1A_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read8(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, sbb8(read_reg8(r), ____0)); } #[no_mangle] @@ -1734,7 +1743,7 @@ pub unsafe extern "C" fn instr_1A_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_1B_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, sbb16(read_reg16(r), ____0)); } #[no_mangle] @@ -1744,7 +1753,7 @@ pub unsafe extern "C" fn instr16_1B_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_1B_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, sbb32(read_reg32(r), ____0)); } #[no_mangle] @@ -1765,12 +1774,19 @@ pub unsafe extern "C" fn instr32_1D(mut imm32: i32) -> () { *reg32s.offset(EAX as isize) = sbb32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] -pub unsafe extern "C" fn instr16_1E() -> () { push16(*sreg.offset(DS as isize) as i32); } +pub unsafe extern "C" fn instr16_1E() -> () { + return_on_pagefault!(push16(*sreg.offset(DS as isize) as i32)); +} #[no_mangle] -pub unsafe extern "C" fn instr32_1E() -> () { push32(*sreg.offset(DS as isize) as i32); } +pub unsafe extern "C" fn instr32_1E() -> () { + return_on_pagefault!(push32(*sreg.offset(DS as isize) as i32)); +} #[no_mangle] pub unsafe extern "C" fn instr16_1F() -> () { - if !switch_seg(DS, safe_read16(get_stack_pointer(0i32))) { + if !switch_seg( + DS, + return_on_pagefault!(safe_read16(get_stack_pointer(0i32))), + ) { return; } else { @@ -1780,7 +1796,10 @@ pub unsafe extern "C" fn instr16_1F() -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_1F() -> () { - if !switch_seg(DS, safe_read32s(get_stack_pointer(0i32)) & 65535i32) { + if !switch_seg( + DS, + return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))) & 65535i32, + ) { return; } else { @@ -1817,7 +1836,7 @@ pub unsafe extern "C" fn instr32_21_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_22_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read8(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, and8(read_reg8(r), ____0)); } #[no_mangle] @@ -1827,7 +1846,7 @@ pub unsafe extern "C" fn instr_22_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_23_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, and16(read_reg16(r), ____0)); } #[no_mangle] @@ -1837,7 +1856,7 @@ pub unsafe extern "C" fn instr16_23_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_23_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, and32(read_reg32(r), ____0)); } #[no_mangle] @@ -1890,7 +1909,7 @@ pub unsafe extern "C" fn instr32_29_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_2A_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read8(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, sub8(read_reg8(r), ____0)); } #[no_mangle] @@ -1900,7 +1919,7 @@ pub unsafe extern "C" fn instr_2A_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_2B_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, sub16(read_reg16(r), ____0)); } #[no_mangle] @@ -1910,7 +1929,7 @@ pub unsafe extern "C" fn instr16_2B_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_2B_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, sub32(read_reg32(r), ____0)); } #[no_mangle] @@ -1963,7 +1982,7 @@ pub unsafe extern "C" fn instr32_31_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_32_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read8(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, xor8(read_reg8(r), ____0)); } #[no_mangle] @@ -1973,7 +1992,7 @@ pub unsafe extern "C" fn instr_32_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_33_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, xor16(read_reg16(r), ____0)); } #[no_mangle] @@ -1983,7 +2002,7 @@ pub unsafe extern "C" fn instr16_33_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_33_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, xor32(read_reg32(r), ____0)); } #[no_mangle] @@ -2009,7 +2028,7 @@ pub unsafe extern "C" fn instr_36() -> () { segment_prefix_op(SS); } pub unsafe extern "C" fn instr_37() -> () { bcd_aaa(); } #[no_mangle] pub unsafe extern "C" fn instr_38_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read8(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); cmp8(____0, read_reg8(r)); } #[no_mangle] @@ -2019,7 +2038,7 @@ pub unsafe extern "C" fn instr_38_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_39_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmp16(____0, read_reg16(r)); } #[no_mangle] @@ -2029,7 +2048,7 @@ pub unsafe extern "C" fn instr16_39_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_39_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmp32(____0, read_reg32(r)); } #[no_mangle] @@ -2039,7 +2058,7 @@ pub unsafe extern "C" fn instr32_39_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_3A_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read8(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); cmp8(read_reg8(r), ____0); } #[no_mangle] @@ -2049,7 +2068,7 @@ pub unsafe extern "C" fn instr_3A_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_3B_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmp16(read_reg16(r), ____0); } #[no_mangle] @@ -2059,7 +2078,7 @@ pub unsafe extern "C" fn instr16_3B_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_3B_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmp32(read_reg32(r), ____0); } #[no_mangle] @@ -2211,74 +2230,110 @@ pub unsafe extern "C" fn instr16_4F() -> () { pub unsafe extern "C" fn instr32_4F() -> () { *reg32s.offset(EDI as isize) = dec32(*reg32s.offset(EDI as isize)); } + +pub unsafe fn push16_reg(r: i32) { + return_on_pagefault!(push16(*reg16.offset(r as isize) as i32)); +} +pub unsafe fn push32_reg(r: i32) { + return_on_pagefault!(push32(*reg32s.offset(r as isize) as i32)); +} + #[no_mangle] -pub unsafe extern "C" fn instr16_50() -> () { push16(*reg16.offset(AX as isize) as i32); } +pub unsafe extern "C" fn instr16_50() -> () { push16_reg(AX) } #[no_mangle] -pub unsafe extern "C" fn instr32_50() -> () { push32(*reg32s.offset(EAX as isize)); } +pub unsafe extern "C" fn instr32_50() -> () { push32_reg(EAX) } #[no_mangle] -pub unsafe extern "C" fn instr16_51() -> () { push16(*reg16.offset(CX as isize) as i32); } +pub unsafe extern "C" fn instr16_51() -> () { push16_reg(CX) } #[no_mangle] -pub unsafe extern "C" fn instr32_51() -> () { push32(*reg32s.offset(ECX as isize)); } +pub unsafe extern "C" fn instr32_51() -> () { push32_reg(ECX) } #[no_mangle] -pub unsafe extern "C" fn instr16_52() -> () { push16(*reg16.offset(DX as isize) as i32); } +pub unsafe extern "C" fn instr16_52() -> () { push16_reg(DX) } #[no_mangle] -pub unsafe extern "C" fn instr32_52() -> () { push32(*reg32s.offset(EDX as isize)); } +pub unsafe extern "C" fn instr32_52() -> () { push32_reg(EDX) } #[no_mangle] -pub unsafe extern "C" fn instr16_53() -> () { push16(*reg16.offset(BX as isize) as i32); } +pub unsafe extern "C" fn instr16_53() -> () { push16_reg(BX) } #[no_mangle] -pub unsafe extern "C" fn instr32_53() -> () { push32(*reg32s.offset(EBX as isize)); } +pub unsafe extern "C" fn instr32_53() -> () { push32_reg(EBX) } #[no_mangle] -pub unsafe extern "C" fn instr16_54() -> () { push16(*reg16.offset(SP as isize) as i32); } +pub unsafe extern "C" fn instr16_54() -> () { push16_reg(SP) } #[no_mangle] -pub unsafe extern "C" fn instr32_54() -> () { push32(*reg32s.offset(ESP as isize)); } +pub unsafe extern "C" fn instr32_54() -> () { push32_reg(ESP) } #[no_mangle] -pub unsafe extern "C" fn instr16_55() -> () { push16(*reg16.offset(BP as isize) as i32); } +pub unsafe extern "C" fn instr16_55() -> () { push16_reg(BP) } #[no_mangle] -pub unsafe extern "C" fn instr32_55() -> () { push32(*reg32s.offset(EBP as isize)); } +pub unsafe extern "C" fn instr32_55() -> () { push32_reg(EBP) } #[no_mangle] -pub unsafe extern "C" fn instr16_56() -> () { push16(*reg16.offset(SI as isize) as i32); } +pub unsafe extern "C" fn instr16_56() -> () { push16_reg(SI) } #[no_mangle] -pub unsafe extern "C" fn instr32_56() -> () { push32(*reg32s.offset(ESI as isize)); } +pub unsafe extern "C" fn instr32_56() -> () { push32_reg(ESI) } #[no_mangle] -pub unsafe extern "C" fn instr16_57() -> () { push16(*reg16.offset(DI as isize) as i32); } +pub unsafe extern "C" fn instr16_57() -> () { push16_reg(DI) } #[no_mangle] -pub unsafe extern "C" fn instr32_57() -> () { push32(*reg32s.offset(EDI as isize)); } +pub unsafe extern "C" fn instr32_57() -> () { push32_reg(EDI) } #[no_mangle] -pub unsafe extern "C" fn instr16_58() -> () { *reg16.offset(AX as isize) = pop16() as u16; } +pub unsafe extern "C" fn instr16_58() -> () { + *reg16.offset(AX as isize) = return_on_pagefault!(pop16()) as u16; +} #[no_mangle] -pub unsafe extern "C" fn instr32_58() -> () { *reg32s.offset(EAX as isize) = pop32s(); } +pub unsafe extern "C" fn instr32_58() -> () { + *reg32s.offset(EAX as isize) = return_on_pagefault!(pop32s()); +} #[no_mangle] -pub unsafe extern "C" fn instr16_59() -> () { *reg16.offset(CX as isize) = pop16() as u16; } +pub unsafe extern "C" fn instr16_59() -> () { + *reg16.offset(CX as isize) = return_on_pagefault!(pop16()) as u16; +} #[no_mangle] -pub unsafe extern "C" fn instr32_59() -> () { *reg32s.offset(ECX as isize) = pop32s(); } +pub unsafe extern "C" fn instr32_59() -> () { + *reg32s.offset(ECX as isize) = return_on_pagefault!(pop32s()); +} #[no_mangle] -pub unsafe extern "C" fn instr16_5A() -> () { *reg16.offset(DX as isize) = pop16() as u16; } +pub unsafe extern "C" fn instr16_5A() -> () { + *reg16.offset(DX as isize) = return_on_pagefault!(pop16()) as u16; +} #[no_mangle] -pub unsafe extern "C" fn instr32_5A() -> () { *reg32s.offset(EDX as isize) = pop32s(); } +pub unsafe extern "C" fn instr32_5A() -> () { + *reg32s.offset(EDX as isize) = return_on_pagefault!(pop32s()); +} #[no_mangle] -pub unsafe extern "C" fn instr16_5B() -> () { *reg16.offset(BX as isize) = pop16() as u16; } +pub unsafe extern "C" fn instr16_5B() -> () { + *reg16.offset(BX as isize) = return_on_pagefault!(pop16()) as u16; +} #[no_mangle] -pub unsafe extern "C" fn instr32_5B() -> () { *reg32s.offset(EBX as isize) = pop32s(); } +pub unsafe extern "C" fn instr32_5B() -> () { + *reg32s.offset(EBX as isize) = return_on_pagefault!(pop32s()); +} #[no_mangle] pub unsafe extern "C" fn instr16_5C() -> () { - *reg16.offset(SP as isize) = safe_read16(get_stack_pointer(0i32)) as u16; + *reg16.offset(SP as isize) = return_on_pagefault!(safe_read16(get_stack_pointer(0i32))) as u16; } #[no_mangle] pub unsafe extern "C" fn instr32_5C() -> () { - *reg32s.offset(ESP as isize) = safe_read32s(get_stack_pointer(0i32)); + *reg32s.offset(ESP as isize) = return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))); } #[no_mangle] -pub unsafe extern "C" fn instr16_5D() -> () { *reg16.offset(BP as isize) = pop16() as u16; } +pub unsafe extern "C" fn instr16_5D() -> () { + *reg16.offset(BP as isize) = return_on_pagefault!(pop16()) as u16; +} #[no_mangle] -pub unsafe extern "C" fn instr32_5D() -> () { *reg32s.offset(EBP as isize) = pop32s(); } +pub unsafe extern "C" fn instr32_5D() -> () { + *reg32s.offset(EBP as isize) = return_on_pagefault!(pop32s()); +} #[no_mangle] -pub unsafe extern "C" fn instr16_5E() -> () { *reg16.offset(SI as isize) = pop16() as u16; } +pub unsafe extern "C" fn instr16_5E() -> () { + *reg16.offset(SI as isize) = return_on_pagefault!(pop16()) as u16; +} #[no_mangle] -pub unsafe extern "C" fn instr32_5E() -> () { *reg32s.offset(ESI as isize) = pop32s(); } +pub unsafe extern "C" fn instr32_5E() -> () { + *reg32s.offset(ESI as isize) = return_on_pagefault!(pop32s()); +} #[no_mangle] -pub unsafe extern "C" fn instr16_5F() -> () { *reg16.offset(DI as isize) = pop16() as u16; } +pub unsafe extern "C" fn instr16_5F() -> () { + *reg16.offset(DI as isize) = return_on_pagefault!(pop16()) as u16; +} #[no_mangle] -pub unsafe extern "C" fn instr32_5F() -> () { *reg32s.offset(EDI as isize) = pop32s(); } +pub unsafe extern "C" fn instr32_5F() -> () { + *reg32s.offset(EDI as isize) = return_on_pagefault!(pop32s()); +} #[no_mangle] pub unsafe extern "C" fn instr16_60() -> () { pusha16(); } #[no_mangle] @@ -2327,14 +2382,21 @@ pub unsafe extern "C" fn instr_67() -> () { *prefixes = 0i32 as u8; } #[no_mangle] -pub unsafe extern "C" fn instr16_68(mut imm16: i32) -> () { push16(imm16); } +pub unsafe extern "C" fn instr16_68(mut imm16: i32) -> () { + return_on_pagefault!(push16(imm16)); +} #[no_mangle] -pub unsafe extern "C" fn instr32_68(mut imm32: i32) -> () { push32(imm32); } +pub unsafe extern "C" fn instr32_68(mut imm32: i32) -> () { + return_on_pagefault!(push32(imm32)); +} #[no_mangle] pub unsafe extern "C" fn instr16_69_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { write_reg16( r, - imul_reg16(safe_read16(addr) << 16i32 >> 16i32, imm << 16i32 >> 16i32), + imul_reg16( + return_on_pagefault!(safe_read16(addr)) << 16i32 >> 16i32, + imm << 16i32 >> 16i32, + ), ); } #[no_mangle] @@ -2346,19 +2408,29 @@ pub unsafe extern "C" fn instr16_69_reg(mut r1: i32, mut r: i32, mut imm: i32) - } #[no_mangle] pub unsafe extern "C" fn instr32_69_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { - write_reg32(r, imul_reg32(safe_read32s(addr), imm)); + write_reg32(r, imul_reg32(return_on_pagefault!(safe_read32s(addr)), imm)); } #[no_mangle] pub unsafe extern "C" fn instr32_69_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { write_reg32(r, imul_reg32(read_reg32(r1), imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_6A(mut imm8: i32) -> () { push16(imm8); } +pub unsafe extern "C" fn instr16_6A(mut imm8: i32) -> () { + return_on_pagefault!(push16(imm8)); +} #[no_mangle] -pub unsafe extern "C" fn instr32_6A(mut imm8: i32) -> () { push32(imm8); } +pub unsafe extern "C" fn instr32_6A(mut imm8: i32) -> () { + return_on_pagefault!(push32(imm8)); +} #[no_mangle] pub unsafe extern "C" fn instr16_6B_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { - write_reg16(r, imul_reg16(safe_read16(addr) << 16i32 >> 16i32, imm)); + write_reg16( + r, + imul_reg16( + return_on_pagefault!(safe_read16(addr)) << 16i32 >> 16i32, + imm, + ), + ); } #[no_mangle] pub unsafe extern "C" fn instr16_6B_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { @@ -2366,7 +2438,7 @@ pub unsafe extern "C" fn instr16_6B_reg(mut r1: i32, mut r: i32, mut imm: i32) - } #[no_mangle] pub unsafe extern "C" fn instr32_6B_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { - write_reg32(r, imul_reg32(safe_read32s(addr), imm)); + write_reg32(r, imul_reg32(return_on_pagefault!(safe_read32s(addr)), imm)); } #[no_mangle] pub unsafe extern "C" fn instr32_6B_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { @@ -2451,7 +2523,7 @@ pub unsafe extern "C" fn instr_80_6_reg(mut r1: i32, mut imm: i32) -> () { pub unsafe extern "C" fn instr_80_7_reg(mut r: i32, mut imm: i32) -> () { cmp8(read_reg8(r), imm); } #[no_mangle] pub unsafe extern "C" fn instr_80_7_mem(mut addr: i32, mut imm: i32) -> () { - cmp8(safe_read8(addr), imm); + cmp8(return_on_pagefault!(safe_read8(addr)), imm); } #[no_mangle] pub unsafe extern "C" fn instr16_81_0_mem(mut addr: i32, mut imm: i32) -> () { @@ -2522,7 +2594,7 @@ pub unsafe extern "C" fn instr16_81_7_reg(mut r: i32, mut imm: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_81_7_mem(mut addr: i32, mut imm: i32) -> () { - cmp16(safe_read16(addr), imm); + cmp16(return_on_pagefault!(safe_read16(addr)), imm); } #[no_mangle] pub unsafe extern "C" fn instr32_81_0_mem(mut addr: i32, mut imm: i32) -> () { @@ -2593,7 +2665,7 @@ pub unsafe extern "C" fn instr32_81_7_reg(mut r: i32, mut imm: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_81_7_mem(mut addr: i32, mut imm: i32) -> () { - cmp32(safe_read32s(addr), imm); + cmp32(return_on_pagefault!(safe_read32s(addr)), imm); } #[no_mangle] pub unsafe extern "C" fn instr_82_0_mem(mut addr: i32, mut imm: i32) -> () { @@ -2662,7 +2734,7 @@ pub unsafe extern "C" fn instr_82_6_reg(mut r1: i32, mut imm: i32) -> () { pub unsafe extern "C" fn instr_82_7_reg(mut r: i32, mut imm: i32) -> () { cmp8(read_reg8(r), imm); } #[no_mangle] pub unsafe extern "C" fn instr_82_7_mem(mut addr: i32, mut imm: i32) -> () { - cmp8(safe_read8(addr), imm); + cmp8(return_on_pagefault!(safe_read8(addr)), imm); } #[no_mangle] pub unsafe extern "C" fn instr16_83_0_mem(mut addr: i32, mut imm: i32) -> () { @@ -2733,7 +2805,7 @@ pub unsafe extern "C" fn instr16_83_7_reg(mut r: i32, mut imm: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_83_7_mem(mut addr: i32, mut imm: i32) -> () { - cmp16(safe_read16(addr), imm); + cmp16(return_on_pagefault!(safe_read16(addr)), imm); } #[no_mangle] pub unsafe extern "C" fn instr32_83_0_mem(mut addr: i32, mut imm: i32) -> () { @@ -2804,11 +2876,11 @@ pub unsafe extern "C" fn instr32_83_7_reg(mut r: i32, mut imm: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_83_7_mem(mut addr: i32, mut imm: i32) -> () { - cmp32(safe_read32s(addr), imm); + cmp32(return_on_pagefault!(safe_read32s(addr)), imm); } #[no_mangle] pub unsafe extern "C" fn instr_84_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read8(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); test8(____0, read_reg8(r)); } #[no_mangle] @@ -2818,7 +2890,7 @@ pub unsafe extern "C" fn instr_84_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_85_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); test16(____0, read_reg16(r)); } #[no_mangle] @@ -2828,7 +2900,7 @@ pub unsafe extern "C" fn instr16_85_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_85_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); test32(____0, read_reg32(r)); } #[no_mangle] @@ -2869,7 +2941,7 @@ pub unsafe extern "C" fn instr_88_reg(mut r2: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_88_mem(mut addr: i32, mut r: i32) -> () { - safe_write8(addr, read_reg8(r)); + return_on_pagefault!(safe_write8(addr, read_reg8(r))); } #[no_mangle] pub unsafe extern "C" fn instr16_89_reg(mut r2: i32, mut r: i32) -> () { @@ -2877,7 +2949,7 @@ pub unsafe extern "C" fn instr16_89_reg(mut r2: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_89_mem(mut addr: i32, mut r: i32) -> () { - safe_write16(addr, read_reg16(r)); + return_on_pagefault!(safe_write16(addr, read_reg16(r))); } #[no_mangle] pub unsafe extern "C" fn instr32_89_reg(mut r2: i32, mut r: i32) -> () { @@ -2885,11 +2957,11 @@ pub unsafe extern "C" fn instr32_89_reg(mut r2: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_89_mem(mut addr: i32, mut r: i32) -> () { - safe_write32(addr, read_reg32(r)); + return_on_pagefault!(safe_write32(addr, read_reg32(r))); } #[no_mangle] pub unsafe extern "C" fn instr_8A_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read8(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, ____0); } #[no_mangle] @@ -2899,7 +2971,7 @@ pub unsafe extern "C" fn instr_8A_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_8B_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, ____0); } #[no_mangle] @@ -2909,7 +2981,7 @@ pub unsafe extern "C" fn instr16_8B_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_8B_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, ____0); } #[no_mangle] @@ -2937,7 +3009,7 @@ pub unsafe extern "C" fn instr16_8C_reg(mut r: i32, mut seg: i32) -> () { #[no_mangle] pub unsafe extern "C" fn instr16_8C_mem(mut addr: i32, mut seg: i32) -> () { if instr_8C_check_sreg(seg) { - safe_write16(addr, *sreg.offset(seg as isize) as i32); + return_on_pagefault!(safe_write16(addr, *sreg.offset(seg as isize) as i32)); }; } #[no_mangle] @@ -2949,7 +3021,7 @@ pub unsafe extern "C" fn instr32_8C_reg(mut r: i32, mut seg: i32) -> () { #[no_mangle] pub unsafe extern "C" fn instr32_8C_mem(mut addr: i32, mut seg: i32) -> () { if instr_8C_check_sreg(seg) { - safe_write32(addr, *sreg.offset(seg as isize) as i32); + return_on_pagefault!(safe_write32(addr, *sreg.offset(seg as isize) as i32)); }; } #[no_mangle] @@ -2958,14 +3030,12 @@ pub unsafe extern "C" fn instr16_8D_reg(mut r: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr16_8D_mem_pre() -> () { - c_comment!(("override prefix, so modrm_resolve does not return the segment part")); - *prefixes = (*prefixes as i32 | SEG_PREFIX_ZERO) as u8; -} -#[no_mangle] -pub unsafe extern "C" fn instr16_8D_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe extern "C" fn instr16_8D_mem(modrm_byte: i32, mut r: i32) -> () { c_comment!(("lea")); - write_reg16(r, addr); + *prefixes = (*prefixes as i32 | SEG_PREFIX_ZERO) as u8; + if let Ok(addr) = modrm_resolve(modrm_byte) { + write_reg16(r, addr); + } *prefixes = 0i32 as u8; } #[no_mangle] @@ -2974,14 +3044,13 @@ pub unsafe extern "C" fn instr32_8D_reg(mut r: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr32_8D_mem_pre() -> () { +pub unsafe extern "C" fn instr32_8D_mem(modrm_byte: i32, mut r: i32) -> () { + c_comment!(("lea")); c_comment!(("override prefix, so modrm_resolve does not return the segment part")); *prefixes = (*prefixes as i32 | SEG_PREFIX_ZERO) as u8; -} -#[no_mangle] -pub unsafe extern "C" fn instr32_8D_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("lea")); - write_reg32(r, addr); + if let Ok(addr) = modrm_resolve(modrm_byte) { + write_reg32(r, addr); + } *prefixes = 0i32 as u8; } #[no_mangle] @@ -2990,9 +3059,6 @@ pub unsafe extern "C" fn instr_8E_helper(mut data: i32, mut mod_0: i32) -> () { if !switch_seg(mod_0, data) { return; } - else { - mod_0 == SS; - } } else { dbg_log_c!(("mov sreg #ud")); @@ -3001,7 +3067,7 @@ pub unsafe extern "C" fn instr_8E_helper(mut data: i32, mut mod_0: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_8E_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); instr_8E_helper(____0, r); } #[no_mangle] @@ -3009,52 +3075,50 @@ pub unsafe extern "C" fn instr_8E_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); instr_8E_helper(____0, r); } + #[no_mangle] -pub unsafe extern "C" fn instr16_8F_0_mem_pre() -> () { - let mut i: i32 = 0i32; - while i < 8i32 { - translate_address_read(*instruction_pointer + i); - i += 1 - } - c_comment!(("XXX")); - adjust_stack_reg(2i32); -} -#[no_mangle] -pub unsafe extern "C" fn instr16_8F_0_mem(mut addr: i32) -> () { +pub unsafe extern "C" fn instr16_8F_0_mem(modrm_byte: i32) -> () { c_comment!(("pop")); - adjust_stack_reg(-2i32); - let mut sp: i32 = safe_read16(get_stack_pointer(0i32)); - safe_write16(addr, sp); + // Update esp *before* resolving the address adjust_stack_reg(2i32); -} -#[no_mangle] -pub unsafe extern "C" fn instr16_8F_0_reg(mut r: i32) -> () { write_reg16(r, pop16()); } -#[no_mangle] -pub unsafe extern "C" fn instr32_8F_0_mem_pre() -> () { - c_comment!(("prevent page faults during modrm_resolve")); - let mut i: i32 = 0i32; - while i < 8i32 { - translate_address_read(*instruction_pointer + i); - i += 1 + match modrm_resolve(modrm_byte) { + Err(()) => { + // a pagefault happened, reset esp + adjust_stack_reg(-2i32); + }, + Ok(addr) => { + adjust_stack_reg(-2i32); + let mut stack_value: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0i32))); + return_on_pagefault!(safe_write16(addr, stack_value)); + adjust_stack_reg(2i32); + }, } - c_comment!(("XXX")); - c_comment!(("esp must be adjusted before calling modrm_resolve")); - c_comment!( - ("The order of calls is: instr32_8F_0_mem_pre -> modrm_resolve -> instr32_8F_0_mem") - ); - adjust_stack_reg(4i32); } #[no_mangle] -pub unsafe extern "C" fn instr32_8F_0_mem(mut addr: i32) -> () { - c_comment!(("Before attempting a write that might cause a page fault,")); - c_comment!(("we must set esp to the old value. Fuck Intel.")); - adjust_stack_reg(-4i32); - let mut sp: i32 = safe_read32s(get_stack_pointer(0i32)); - safe_write32(addr, sp); - adjust_stack_reg(4i32); +pub unsafe extern "C" fn instr16_8F_0_reg(mut r: i32) -> () { + write_reg16(r, return_on_pagefault!(pop16())); } #[no_mangle] -pub unsafe extern "C" fn instr32_8F_0_reg(mut r: i32) -> () { write_reg32(r, pop32s()); } +pub unsafe extern "C" fn instr32_8F_0_mem(modrm_byte: i32) -> () { + // Update esp *before* resolving the address + adjust_stack_reg(4i32); + match modrm_resolve(modrm_byte) { + Err(()) => { + // a pagefault happened, reset esp + adjust_stack_reg(-4i32); + }, + Ok(addr) => { + adjust_stack_reg(-4i32); + let mut stack_value: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))); + return_on_pagefault!(safe_write32(addr, stack_value)); + adjust_stack_reg(4i32); + }, + } +} +#[no_mangle] +pub unsafe extern "C" fn instr32_8F_0_reg(mut r: i32) -> () { + write_reg32(r, return_on_pagefault!(pop32s())); +} #[no_mangle] pub unsafe extern "C" fn instr_90() -> () {} #[no_mangle] @@ -3138,7 +3202,7 @@ pub unsafe extern "C" fn instr16_9C() -> () { trigger_gp_non_raising(0i32); } else { - push16(get_eflags()); + return_on_pagefault!(push16(get_eflags())); }; } #[no_mangle] @@ -3152,7 +3216,7 @@ pub unsafe extern "C" fn instr32_9C() -> () { } else { c_comment!(("vm and rf flag are cleared in image stored on the stack")); - push32(get_eflags() & 16580607i32); + return_on_pagefault!(push32(get_eflags() & 16580607i32)); }; } #[no_mangle] @@ -3164,7 +3228,7 @@ pub unsafe extern "C" fn instr16_9D() -> () { return; } else { - update_eflags(*flags.offset(0isize) & !65535i32 | pop16()); + update_eflags(*flags.offset(0isize) & !65535i32 | return_on_pagefault!(pop16())); if 0 != *flags.offset(0isize) & FLAG_TRAP { let ref mut fresh0 = *flags.offset(0isize); *fresh0 &= !FLAG_TRAP @@ -3184,7 +3248,7 @@ pub unsafe extern "C" fn instr32_9D() -> () { return; } else { - update_eflags(pop32s()); + update_eflags(return_on_pagefault!(pop32s())); handle_irqs(); return; }; @@ -3205,33 +3269,42 @@ pub unsafe extern "C" fn instr_9F() -> () { #[no_mangle] pub unsafe extern "C" fn instr_A0(mut moffs: i32) -> () { c_comment!(("mov")); - let mut data: i32 = safe_read8(get_seg_prefix_ds(moffs)); + let mut data: i32 = return_on_pagefault!(safe_read8(get_seg_prefix_ds(moffs))); *reg8.offset(AL as isize) = data as u8; } #[no_mangle] pub unsafe extern "C" fn instr16_A1(mut moffs: i32) -> () { c_comment!(("mov")); - let mut data: i32 = safe_read16(get_seg_prefix_ds(moffs)); + let mut data: i32 = return_on_pagefault!(safe_read16(get_seg_prefix_ds(moffs))); *reg16.offset(AX as isize) = data as u16; } #[no_mangle] pub unsafe extern "C" fn instr32_A1(mut moffs: i32) -> () { - let mut data: i32 = safe_read32s(get_seg_prefix_ds(moffs)); + let mut data: i32 = return_on_pagefault!(safe_read32s(get_seg_prefix_ds(moffs))); *reg32s.offset(EAX as isize) = data; } #[no_mangle] pub unsafe extern "C" fn instr_A2(mut moffs: i32) -> () { c_comment!(("mov")); - safe_write8(get_seg_prefix_ds(moffs), *reg8.offset(AL as isize) as i32); + return_on_pagefault!(safe_write8( + get_seg_prefix_ds(moffs), + *reg8.offset(AL as isize) as i32 + )); } #[no_mangle] pub unsafe extern "C" fn instr16_A3(mut moffs: i32) -> () { c_comment!(("mov")); - safe_write16(get_seg_prefix_ds(moffs), *reg16.offset(AX as isize) as i32); + return_on_pagefault!(safe_write16( + get_seg_prefix_ds(moffs), + *reg16.offset(AX as isize) as i32 + )); } #[no_mangle] pub unsafe extern "C" fn instr32_A3(mut moffs: i32) -> () { - safe_write32(get_seg_prefix_ds(moffs), *reg32s.offset(EAX as isize)); + return_on_pagefault!(safe_write32( + get_seg_prefix_ds(moffs), + *reg32s.offset(EAX as isize) + )); } #[no_mangle] pub unsafe extern "C" fn instr_A4() -> () { movsb_no_rep(); } @@ -3543,7 +3616,7 @@ pub unsafe extern "C" fn instr32_C1_7_reg(mut r1: i32, mut imm: i32) -> () { pub unsafe extern "C" fn instr16_C2(mut imm16: i32) -> () { c_comment!(("retn")); let mut cs: i32 = get_seg_cs(); - *instruction_pointer.offset(0isize) = cs + pop16(); + *instruction_pointer.offset(0isize) = cs + return_on_pagefault!(pop16()); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); adjust_stack_reg(imm16); } @@ -3551,7 +3624,7 @@ pub unsafe extern "C" fn instr16_C2(mut imm16: i32) -> () { pub unsafe extern "C" fn instr32_C2(mut imm16: i32) -> () { c_comment!(("retn")); let mut cs: i32 = get_seg_cs(); - let mut ip: i32 = pop32s(); + let mut ip: i32 = return_on_pagefault!(pop32s()); dbg_assert!(0 != is_asize_32() as i32 || ip < 65536i32); *instruction_pointer.offset(0isize) = cs + ip; adjust_stack_reg(imm16); @@ -3560,13 +3633,13 @@ pub unsafe extern "C" fn instr32_C2(mut imm16: i32) -> () { pub unsafe extern "C" fn instr16_C3() -> () { c_comment!(("retn")); let mut cs: i32 = get_seg_cs(); - *instruction_pointer.offset(0isize) = cs + pop16(); + *instruction_pointer.offset(0isize) = cs + return_on_pagefault!(pop16()); } #[no_mangle] pub unsafe extern "C" fn instr32_C3() -> () { c_comment!(("retn")); let mut cs: i32 = get_seg_cs(); - let mut ip: i32 = pop32s(); + let mut ip: i32 = return_on_pagefault!(pop32s()); dbg_assert!(0 != is_asize_32() as i32 || ip < 65536i32); *instruction_pointer.offset(0isize) = cs + ip; } @@ -3602,19 +3675,19 @@ pub unsafe extern "C" fn instr32_C5_mem(mut addr: i32, mut r: i32) -> () { lss32 pub unsafe extern "C" fn instr_C6_0_reg(mut r: i32, mut imm: i32) -> () { write_reg8(r, imm); } #[no_mangle] pub unsafe extern "C" fn instr_C6_0_mem(mut addr: i32, mut imm: i32) -> () { - safe_write8(addr, imm); + return_on_pagefault!(safe_write8(addr, imm)); } #[no_mangle] pub unsafe extern "C" fn instr16_C7_0_reg(mut r: i32, mut imm: i32) -> () { write_reg16(r, imm); } #[no_mangle] pub unsafe extern "C" fn instr16_C7_0_mem(mut addr: i32, mut imm: i32) -> () { - safe_write16(addr, imm); + return_on_pagefault!(safe_write16(addr, imm)); } #[no_mangle] pub unsafe extern "C" fn instr32_C7_0_reg(mut r: i32, mut imm: i32) -> () { write_reg32(r, imm); } #[no_mangle] pub unsafe extern "C" fn instr32_C7_0_mem(mut addr: i32, mut imm: i32) -> () { - safe_write32(addr, imm); + return_on_pagefault!(safe_write32(addr, imm)); } #[no_mangle] pub unsafe extern "C" fn instr16_C8(mut size: i32, mut nesting: i32) -> () { @@ -3633,7 +3706,7 @@ pub unsafe extern "C" fn instr16_C9() -> () { else { *reg16.offset(BP as isize) as i32 }; - let mut new_bp: i32 = safe_read16(get_seg_ss() + old_vbp); + let mut new_bp: i32 = return_on_pagefault!(safe_read16(get_seg_ss() + old_vbp)); set_stack_reg(old_vbp + 2i32); *reg16.offset(BP as isize) = new_bp as u16; } @@ -3645,38 +3718,38 @@ pub unsafe extern "C" fn instr32_C9() -> () { else { *reg16.offset(BP as isize) as i32 }; - let mut new_ebp: i32 = safe_read32s(get_seg_ss() + old_vbp); + let mut new_ebp: i32 = return_on_pagefault!(safe_read32s(get_seg_ss() + old_vbp)); set_stack_reg(old_vbp + 4i32); *reg32s.offset(EBP as isize) = new_ebp; } #[no_mangle] pub unsafe extern "C" fn instr16_CA(mut imm16: i32) -> () { c_comment!(("retf")); - let mut ip: i32 = safe_read16(get_stack_pointer(0i32)); - let mut cs: i32 = safe_read16(get_stack_pointer(2i32)); + let mut ip: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0i32))); + let mut cs: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(2i32))); far_return(ip, cs, imm16); } #[no_mangle] pub unsafe extern "C" fn instr32_CA(mut imm16: i32) -> () { c_comment!(("retf")); - let mut ip: i32 = safe_read32s(get_stack_pointer(0i32)); - let mut cs: i32 = safe_read32s(get_stack_pointer(4i32)) & 65535i32; + let mut ip: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))); + let mut cs: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(4i32))) & 65535i32; far_return(ip, cs, imm16); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] pub unsafe extern "C" fn instr16_CB() -> () { c_comment!(("retf")); - let mut ip: i32 = safe_read16(get_stack_pointer(0i32)); - let mut cs: i32 = safe_read16(get_stack_pointer(2i32)); + let mut ip: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0i32))); + let mut cs: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(2i32))); far_return(ip, cs, 0i32); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] pub unsafe extern "C" fn instr32_CB() -> () { c_comment!(("retf")); - let mut ip: i32 = safe_read32s(get_stack_pointer(0i32)); - let mut cs: i32 = safe_read32s(get_stack_pointer(4i32)) & 65535i32; + let mut ip: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))); + let mut cs: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(4i32))) & 65535i32; far_return(ip, cs, 0i32); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } @@ -4249,15 +4322,15 @@ pub unsafe extern "C" fn instr_D6() -> () { pub unsafe extern "C" fn instr_D7() -> () { c_comment!(("xlat")); if is_asize_32() { - *reg8.offset(AL as isize) = safe_read8( + *reg8.offset(AL as isize) = return_on_pagefault!(safe_read8( get_seg_prefix(DS) + *reg32s.offset(EBX as isize) + *reg8.offset(AL as isize) as i32, - ) as u8 + )) as u8 } else { - *reg8.offset(AL as isize) = safe_read8( + *reg8.offset(AL as isize) = return_on_pagefault!(safe_read8( get_seg_prefix(DS) + (*reg16.offset(BX as isize) as i32 + *reg8.offset(AL as isize) as i32 & 65535i32), - ) as u8 + )) as u8 }; } #[no_mangle] @@ -4323,13 +4396,13 @@ pub unsafe extern "C" fn instr32_E7(mut port: i32) -> () { #[no_mangle] pub unsafe extern "C" fn instr16_E8(mut imm16: i32) -> () { c_comment!(("call")); - push16(get_real_eip()); + return_on_pagefault!(push16(get_real_eip())); jmp_rel16(imm16); } #[no_mangle] pub unsafe extern "C" fn instr32_E8(mut imm32s: i32) -> () { c_comment!(("call")); - push32(get_real_eip()); + return_on_pagefault!(push32(get_real_eip())); *instruction_pointer.offset(0isize) = *instruction_pointer.offset(0isize) + imm32s; c_comment!(("dbg_assert!(is_asize_32() || get_real_eip() < 0x10000);")); } @@ -4466,7 +4539,7 @@ pub unsafe extern "C" fn instr_F5() -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F6_0_mem(mut addr: i32, mut imm: i32) -> () { - let mut ____0: i32 = safe_read8(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); test8(____0, imm); } #[no_mangle] @@ -4476,7 +4549,7 @@ pub unsafe extern "C" fn instr_F6_0_reg(mut r1: i32, mut imm: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F6_1_mem(mut addr: i32, mut imm: i32) -> () { - let mut ____0: i32 = safe_read8(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); test8(____0, imm); } #[no_mangle] @@ -4504,7 +4577,7 @@ pub unsafe extern "C" fn instr_F6_3_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F6_4_mem(mut addr: i32) -> () { - let mut ____0: i32 = safe_read8(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); mul8(____0); } #[no_mangle] @@ -4514,7 +4587,7 @@ pub unsafe extern "C" fn instr_F6_4_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F6_5_mem(mut addr: i32) -> () { - let mut ____0: i32 = safe_read8(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); imul8(____0 << 24i32 >> 24i32); } #[no_mangle] @@ -4524,7 +4597,7 @@ pub unsafe extern "C" fn instr_F6_5_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F6_6_mem(mut addr: i32) -> () { - let mut ____0: i32 = safe_read8(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); div8(____0 as u32); } #[no_mangle] @@ -4534,7 +4607,7 @@ pub unsafe extern "C" fn instr_F6_6_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F6_7_mem(mut addr: i32) -> () { - let mut ____0: i32 = safe_read8(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); idiv8(____0 << 24i32 >> 24i32); } #[no_mangle] @@ -4544,7 +4617,7 @@ pub unsafe extern "C" fn instr_F6_7_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_F7_0_mem(mut addr: i32, mut imm: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); test16(____0, imm); } #[no_mangle] @@ -4554,7 +4627,7 @@ pub unsafe extern "C" fn instr16_F7_0_reg(mut r1: i32, mut imm: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_F7_1_mem(mut addr: i32, mut imm: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); test16(____0, imm); } #[no_mangle] @@ -4582,7 +4655,7 @@ pub unsafe extern "C" fn instr16_F7_3_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_F7_4_mem(mut addr: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); mul16(____0 as u32); } #[no_mangle] @@ -4592,7 +4665,7 @@ pub unsafe extern "C" fn instr16_F7_4_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_F7_5_mem(mut addr: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); imul16(____0 << 16i32 >> 16i32); } #[no_mangle] @@ -4602,7 +4675,7 @@ pub unsafe extern "C" fn instr16_F7_5_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_F7_6_mem(mut addr: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); div16(____0 as u32); } #[no_mangle] @@ -4612,7 +4685,7 @@ pub unsafe extern "C" fn instr16_F7_6_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_F7_7_mem(mut addr: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); idiv16(____0 << 16i32 >> 16i32); } #[no_mangle] @@ -4622,7 +4695,7 @@ pub unsafe extern "C" fn instr16_F7_7_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_F7_0_mem(mut addr: i32, mut imm: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); test32(____0, imm); } #[no_mangle] @@ -4632,7 +4705,7 @@ pub unsafe extern "C" fn instr32_F7_0_reg(mut r1: i32, mut imm: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_F7_1_mem(mut addr: i32, mut imm: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); test32(____0, imm); } #[no_mangle] @@ -4660,7 +4733,7 @@ pub unsafe extern "C" fn instr32_F7_3_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_F7_4_mem(mut addr: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); mul32(____0); } #[no_mangle] @@ -4670,7 +4743,7 @@ pub unsafe extern "C" fn instr32_F7_4_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_F7_5_mem(mut addr: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); imul32(____0); } #[no_mangle] @@ -4680,7 +4753,7 @@ pub unsafe extern "C" fn instr32_F7_5_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_F7_6_mem(mut addr: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); div32(____0 as u32); } #[no_mangle] @@ -4690,7 +4763,7 @@ pub unsafe extern "C" fn instr32_F7_6_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_F7_7_mem(mut addr: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); idiv32(____0); } #[no_mangle] @@ -4822,13 +4895,13 @@ pub unsafe extern "C" fn instr16_FF_1_reg(mut r1: i32) -> () { pub unsafe extern "C" fn instr16_FF_2_helper(mut data: i32) -> () { c_comment!(("call near")); let mut cs: i32 = get_seg_cs(); - push16(get_real_eip()); + return_on_pagefault!(push16(get_real_eip())); *instruction_pointer.offset(0isize) = cs + data; dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] pub unsafe extern "C" fn instr16_FF_2_mem(mut addr: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); instr16_FF_2_helper(____0); } #[no_mangle] @@ -4844,8 +4917,8 @@ pub unsafe extern "C" fn instr16_FF_3_reg(mut r: i32) -> () { #[no_mangle] pub unsafe extern "C" fn instr16_FF_3_mem(mut addr: i32) -> () { c_comment!(("callf")); - let mut new_ip: i32 = safe_read16(addr); - let mut new_cs: i32 = safe_read16(addr + 2i32); + let mut new_ip: i32 = return_on_pagefault!(safe_read16(addr)); + let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 2i32)); far_jump(new_ip, new_cs, 1i32); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } @@ -4857,7 +4930,7 @@ pub unsafe extern "C" fn instr16_FF_4_helper(mut data: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_FF_4_mem(mut addr: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); instr16_FF_4_helper(____0); } #[no_mangle] @@ -4873,20 +4946,20 @@ pub unsafe extern "C" fn instr16_FF_5_reg(mut r: i32) -> () { #[no_mangle] pub unsafe extern "C" fn instr16_FF_5_mem(mut addr: i32) -> () { c_comment!(("jmpf")); - let mut new_ip: i32 = safe_read16(addr); - let mut new_cs: i32 = safe_read16(addr + 2i32); + let mut new_ip: i32 = return_on_pagefault!(safe_read16(addr)); + let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 2i32)); far_jump(new_ip, new_cs, 0i32); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] pub unsafe extern "C" fn instr16_FF_6_mem(mut addr: i32) -> () { - let mut ____0: i32 = safe_read16(addr); - push16(____0); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); + return_on_pagefault!(push16(____0)); } #[no_mangle] pub unsafe extern "C" fn instr16_FF_6_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); - push16(____0); + return_on_pagefault!(push16(____0)); } #[no_mangle] pub unsafe extern "C" fn instr32_FF_0_mem(mut addr: i32) -> () { @@ -4910,13 +4983,13 @@ pub unsafe extern "C" fn instr32_FF_1_reg(mut r1: i32) -> () { pub unsafe extern "C" fn instr32_FF_2_helper(mut data: i32) -> () { c_comment!(("call near")); let mut cs: i32 = get_seg_cs(); - push32(get_real_eip()); + return_on_pagefault!(push32(get_real_eip())); dbg_assert!(0 != is_asize_32() as i32 || data < 65536i32); *instruction_pointer.offset(0isize) = cs + data; } #[no_mangle] pub unsafe extern "C" fn instr32_FF_2_mem(mut addr: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); instr32_FF_2_helper(____0); } #[no_mangle] @@ -4932,8 +5005,8 @@ pub unsafe extern "C" fn instr32_FF_3_reg(mut r: i32) -> () { #[no_mangle] pub unsafe extern "C" fn instr32_FF_3_mem(mut addr: i32) -> () { c_comment!(("callf")); - let mut new_ip: i32 = safe_read32s(addr); - let mut new_cs: i32 = safe_read16(addr + 4i32); + let mut new_ip: i32 = return_on_pagefault!(safe_read32s(addr)); + let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 4i32)); if !*protected_mode || 0 != vm86_mode() as i32 { if 0 != new_ip as u32 & 4294901760u32 { dbg_assert!(0 != 0i32); @@ -4950,7 +5023,7 @@ pub unsafe extern "C" fn instr32_FF_4_helper(mut data: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_FF_4_mem(mut addr: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); instr32_FF_4_helper(____0); } #[no_mangle] @@ -4966,8 +5039,8 @@ pub unsafe extern "C" fn instr32_FF_5_reg(mut r: i32) -> () { #[no_mangle] pub unsafe extern "C" fn instr32_FF_5_mem(mut addr: i32) -> () { c_comment!(("jmpf")); - let mut new_ip: i32 = safe_read32s(addr); - let mut new_cs: i32 = safe_read16(addr + 4i32); + let mut new_ip: i32 = return_on_pagefault!(safe_read32s(addr)); + let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 4i32)); if !*protected_mode || 0 != vm86_mode() as i32 { if 0 != new_ip as u32 & 4294901760u32 { dbg_assert!(0 != 0i32); @@ -4978,13 +5051,13 @@ pub unsafe extern "C" fn instr32_FF_5_mem(mut addr: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_FF_6_mem(mut addr: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); - push32(____0); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); + return_on_pagefault!(push32(____0)); } #[no_mangle] pub unsafe extern "C" fn instr32_FF_6_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); - push32(____0); + return_on_pagefault!(push32(____0)); } #[no_mangle] pub unsafe extern "C" fn instr_F26C() -> () { insb_rep(); } @@ -5136,7 +5209,7 @@ pub unsafe extern "C" fn instr32_F2AF() -> () { scasd_rep(PREFIX_F2); } pub unsafe extern "C" fn instr32_F3AF() -> () { scasd_rep(PREFIX_F3); } #[no_mangle] pub unsafe extern "C" fn instr_D8_0_mem(mut addr: i32) -> () { - let mut ____0: f64 = fpu_load_m32(addr); + let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fadd(0i32, ____0); } #[no_mangle] @@ -5146,7 +5219,7 @@ pub unsafe extern "C" fn instr_D8_0_reg(mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_D8_1_mem(mut addr: i32) -> () { - let mut ____0: f64 = fpu_load_m32(addr); + let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fmul(0i32, ____0); } #[no_mangle] @@ -5156,7 +5229,7 @@ pub unsafe extern "C" fn instr_D8_1_reg(mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_D8_2_mem(mut addr: i32) -> () { - let mut ____0: f64 = fpu_load_m32(addr); + let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fcom(____0); } #[no_mangle] @@ -5166,7 +5239,7 @@ pub unsafe extern "C" fn instr_D8_2_reg(mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_D8_3_mem(mut addr: i32) -> () { - let mut ____0: f64 = fpu_load_m32(addr); + let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fcomp(____0); } #[no_mangle] @@ -5176,7 +5249,7 @@ pub unsafe extern "C" fn instr_D8_3_reg(mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_D8_4_mem(mut addr: i32) -> () { - let mut ____0: f64 = fpu_load_m32(addr); + let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fsub(0i32, ____0); } #[no_mangle] @@ -5186,7 +5259,7 @@ pub unsafe extern "C" fn instr_D8_4_reg(mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_D8_5_mem(mut addr: i32) -> () { - let mut ____0: f64 = fpu_load_m32(addr); + let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fsubr(0i32, ____0); } #[no_mangle] @@ -5196,7 +5269,7 @@ pub unsafe extern "C" fn instr_D8_5_reg(mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_D8_6_mem(mut addr: i32) -> () { - let mut ____0: f64 = fpu_load_m32(addr); + let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fdiv(0i32, ____0); } #[no_mangle] @@ -5206,7 +5279,7 @@ pub unsafe extern "C" fn instr_D8_6_reg(mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_D8_7_mem(mut addr: i32) -> () { - let mut ____0: f64 = fpu_load_m32(addr); + let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fdivr(0i32, ____0); } #[no_mangle] @@ -5216,7 +5289,7 @@ pub unsafe extern "C" fn instr_D8_7_reg(mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_D9_0_mem(mut addr: i32) -> () { - let mut ____0: f64 = fpu_load_m32(addr); + let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_push(____0); } #[no_mangle] @@ -5394,35 +5467,35 @@ pub unsafe extern "C" fn instr_D9_7_reg(mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_DA_0_mem(mut addr: i32) -> () { - fpu_fadd(0i32, safe_read32s(addr) as f64); + fpu_fadd(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] pub unsafe extern "C" fn instr_DA_1_mem(mut addr: i32) -> () { - fpu_fmul(0i32, safe_read32s(addr) as f64); + fpu_fmul(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] pub unsafe extern "C" fn instr_DA_2_mem(mut addr: i32) -> () { - fpu_fcom(safe_read32s(addr) as f64); + fpu_fcom(return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] pub unsafe extern "C" fn instr_DA_3_mem(mut addr: i32) -> () { - fpu_fcomp(safe_read32s(addr) as f64); + fpu_fcomp(return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] pub unsafe extern "C" fn instr_DA_4_mem(mut addr: i32) -> () { - fpu_fsub(0i32, safe_read32s(addr) as f64); + fpu_fsub(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] pub unsafe extern "C" fn instr_DA_5_mem(mut addr: i32) -> () { - fpu_fsubr(0i32, safe_read32s(addr) as f64); + fpu_fsubr(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] pub unsafe extern "C" fn instr_DA_6_mem(mut addr: i32) -> () { - fpu_fdiv(0i32, safe_read32s(addr) as f64); + fpu_fdiv(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] pub unsafe extern "C" fn instr_DA_7_mem(mut addr: i32) -> () { - fpu_fdivr(0i32, safe_read32s(addr) as f64); + fpu_fdivr(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] pub unsafe extern "C" fn instr_DA_0_reg(mut r: i32) -> () { fpu_fcmovcc(test_b(), r); } @@ -5493,24 +5566,36 @@ pub unsafe extern "C" fn instr_DB_6_reg(mut r: i32) -> () { fpu_fcomi(r); } #[no_mangle] pub unsafe extern "C" fn instr_DB_7_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_DC_0_mem(mut addr: i32) -> () { fpu_fadd(0i32, fpu_load_m64(addr)); } -#[no_mangle] -pub unsafe extern "C" fn instr_DC_1_mem(mut addr: i32) -> () { fpu_fmul(0i32, fpu_load_m64(addr)); } -#[no_mangle] -pub unsafe extern "C" fn instr_DC_2_mem(mut addr: i32) -> () { fpu_fcom(fpu_load_m64(addr)); } -#[no_mangle] -pub unsafe extern "C" fn instr_DC_3_mem(mut addr: i32) -> () { fpu_fcomp(fpu_load_m64(addr)); } -#[no_mangle] -pub unsafe extern "C" fn instr_DC_4_mem(mut addr: i32) -> () { fpu_fsub(0i32, fpu_load_m64(addr)); } -#[no_mangle] -pub unsafe extern "C" fn instr_DC_5_mem(mut addr: i32) -> () { - fpu_fsubr(0i32, fpu_load_m64(addr)); +pub unsafe extern "C" fn instr_DC_0_mem(mut addr: i32) -> () { + fpu_fadd(0i32, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe extern "C" fn instr_DC_6_mem(mut addr: i32) -> () { fpu_fdiv(0i32, fpu_load_m64(addr)); } +pub unsafe extern "C" fn instr_DC_1_mem(mut addr: i32) -> () { + fpu_fmul(0i32, return_on_pagefault!(fpu_load_m64(addr))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DC_2_mem(mut addr: i32) -> () { + fpu_fcom(return_on_pagefault!(fpu_load_m64(addr))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DC_3_mem(mut addr: i32) -> () { + fpu_fcomp(return_on_pagefault!(fpu_load_m64(addr))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DC_4_mem(mut addr: i32) -> () { + fpu_fsub(0i32, return_on_pagefault!(fpu_load_m64(addr))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DC_5_mem(mut addr: i32) -> () { + fpu_fsubr(0i32, return_on_pagefault!(fpu_load_m64(addr))); +} +#[no_mangle] +pub unsafe extern "C" fn instr_DC_6_mem(mut addr: i32) -> () { + fpu_fdiv(0i32, return_on_pagefault!(fpu_load_m64(addr))); +} #[no_mangle] pub unsafe extern "C" fn instr_DC_7_mem(mut addr: i32) -> () { - fpu_fdivr(0i32, fpu_load_m64(addr)); + fpu_fdivr(0i32, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] pub unsafe extern "C" fn instr_DC_0_reg(mut r: i32) -> () { fpu_fadd(r, fpu_get_sti(r)); } @@ -5568,35 +5653,35 @@ pub unsafe extern "C" fn instr_DD_6_reg(mut r: i32) -> () { trigger_ud(); } pub unsafe extern "C" fn instr_DD_7_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe extern "C" fn instr_DE_0_mem(mut addr: i32) -> () { - fpu_fadd(0i32, safe_read16(addr) as i16 as f64); + fpu_fadd(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] pub unsafe extern "C" fn instr_DE_1_mem(mut addr: i32) -> () { - fpu_fmul(0i32, safe_read16(addr) as i16 as f64); + fpu_fmul(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] pub unsafe extern "C" fn instr_DE_2_mem(mut addr: i32) -> () { - fpu_fcom(safe_read16(addr) as i16 as f64); + fpu_fcom(return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] pub unsafe extern "C" fn instr_DE_3_mem(mut addr: i32) -> () { - fpu_fcomp(safe_read16(addr) as i16 as f64); + fpu_fcomp(return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] pub unsafe extern "C" fn instr_DE_4_mem(mut addr: i32) -> () { - fpu_fsub(0i32, safe_read16(addr) as i16 as f64); + fpu_fsub(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] pub unsafe extern "C" fn instr_DE_5_mem(mut addr: i32) -> () { - fpu_fsubr(0i32, safe_read16(addr) as i16 as f64); + fpu_fsubr(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] pub unsafe extern "C" fn instr_DE_6_mem(mut addr: i32) -> () { - fpu_fdiv(0i32, safe_read16(addr) as i16 as f64); + fpu_fdiv(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] pub unsafe extern "C" fn instr_DE_7_mem(mut addr: i32) -> () { - fpu_fdivr(0i32, safe_read16(addr) as i16 as f64); + fpu_fdivr(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] pub unsafe extern "C" fn instr_DE_0_reg(mut r: i32) -> () { @@ -5640,7 +5725,7 @@ pub unsafe extern "C" fn instr_DE_7_reg(mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_DF_0_mem(mut addr: i32) -> () { - fpu_push(safe_read16(addr) as i16 as f64); + fpu_push(return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] pub unsafe extern "C" fn instr_DF_1_mem(mut addr: i32) -> () { diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 3db895a8..5d199a60 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -1,7 +1,16 @@ -#![allow -( dead_code , mutable_transmutes , non_camel_case_types , non_snake_case , -non_upper_case_globals , unused_mut )] -#![feature ( extern_types , libc )] +#![allow( + dead_code, + mutable_transmutes, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_mut +)] +#![feature(extern_types, libc)] + +use cpu2::cpu::*; +use cpu2::fpu::fpu_load_m32; +use cpu2::misc_instr::{push16, push32}; extern "C" { @@ -383,8 +392,6 @@ extern "C" { #[no_mangle] static CPU_EXCEPTION_VE: i32; #[no_mangle] - fn writable_or_pagefault(addr: i32, size: i32) -> (); - #[no_mangle] fn is_osize_32() -> bool; #[no_mangle] fn get_seg_prefix(default_segment: i32) -> i32; @@ -393,26 +400,6 @@ extern "C" { #[no_mangle] fn trigger_gp_non_raising(code: i32) -> (); #[no_mangle] - fn safe_read8(addr: i32) -> i32; - #[no_mangle] - fn safe_read16(addr: i32) -> i32; - #[no_mangle] - fn safe_read32s(address: i32) -> i32; - #[no_mangle] - fn safe_read64s(addr: i32) -> reg64; - #[no_mangle] - fn safe_read128s(addr: i32) -> reg128; - #[no_mangle] - fn safe_write8(addr: i32, value: i32) -> (); - #[no_mangle] - fn safe_write16(addr: i32, value: i32) -> (); - #[no_mangle] - fn safe_write32(address: i32, value: i32) -> (); - #[no_mangle] - fn safe_write64(addr: i32, value: i64) -> (); - #[no_mangle] - fn safe_write128(addr: i32, value: reg128) -> (); - #[no_mangle] fn get_reg8_index(index: i32) -> i32; #[no_mangle] fn read_reg8(index: i32) -> i32; @@ -487,8 +474,6 @@ extern "C" { #[no_mangle] static FPU_STACK_TOP: i32; #[no_mangle] - fn fpu_load_m32(addr: i32) -> f64; - #[no_mangle] fn fpu_set_tag_word(tag_word: i32) -> (); #[no_mangle] static reg8: *mut u8; @@ -724,10 +709,6 @@ extern "C" { #[no_mangle] fn setcc_mem(condition: bool, addr: i32) -> (); #[no_mangle] - fn push16(imm16: i32) -> (); - #[no_mangle] - fn push32(imm32: i32) -> (); - #[no_mangle] fn adjust_stack_reg(adjustment: i32) -> (); #[no_mangle] fn get_stack_pointer(offset: i32) -> i32; @@ -768,20 +749,6 @@ pub union unnamed { __i: u32, } -#[derive(Copy, Clone)] -#[repr(C)] -pub union reg64 { - i8_0: [i8; 8], - i16_0: [i16; 4], - i32_0: [i32; 2], - i64_0: [i64; 1], - u8_0: [u8; 8], - u16_0: [u16; 4], - u32_0: [u32; 2], - u64_0: [u64; 1], - f32_0: [f32; 2], - f64_0: [f64; 1], -} #[derive(Copy, Clone)] #[repr(C)] pub union unnamed_0 { @@ -789,21 +756,6 @@ pub union unnamed_0 { __i: u64, } -#[derive(Copy, Clone)] -#[repr(C)] -pub union reg128 { - i8_0: [i8; 16], - i16_0: [i16; 8], - i32_0: [i32; 4], - i64_0: [i64; 2], - u8_0: [u8; 16], - u16_0: [u16; 8], - u32_0: [u32; 4], - u64_0: [u64; 2], - f32_0: [f32; 4], - f64_0: [f64; 2], -} - unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { let mut __u: unnamed = unnamed { __f: 0. }; __u.__f = __f; @@ -1182,7 +1134,7 @@ pub unsafe extern "C" fn instr_0F00_0_mem(mut addr: i32) -> () { return; } else { - safe_write16(addr, *sreg.offset(LDTR as isize) as i32); + return_on_pagefault!(safe_write16(addr, *sreg.offset(LDTR as isize) as i32)); return; }; } @@ -1205,7 +1157,7 @@ pub unsafe extern "C" fn instr_0F00_1_mem(mut addr: i32) -> () { return; } else { - safe_write16(addr, *sreg.offset(TR as isize) as i32); + return_on_pagefault!(safe_write16(addr, *sreg.offset(TR as isize) as i32)); return; }; } @@ -1232,7 +1184,7 @@ pub unsafe extern "C" fn instr_0F00_2_mem(mut addr: i32) -> () { return; } else { - load_ldt(safe_read16(addr)); + load_ldt(return_on_pagefault!(safe_read16(addr))); return; }; } @@ -1263,7 +1215,7 @@ pub unsafe extern "C" fn instr_0F00_3_mem(mut addr: i32) -> () { return; } else { - load_tr(safe_read16(addr)); + load_tr(return_on_pagefault!(safe_read16(addr))); return; }; } @@ -1289,7 +1241,7 @@ pub unsafe extern "C" fn instr_0F00_4_mem(mut addr: i32) -> () { return; } else { - verr(safe_read16(addr)); + verr(return_on_pagefault!(safe_read16(addr))); return; }; } @@ -1311,7 +1263,7 @@ pub unsafe extern "C" fn instr_0F00_5_mem(mut addr: i32) -> () { return; } else { - verw(safe_read16(addr)); + verw(return_on_pagefault!(safe_read16(addr))); return; }; } @@ -1331,30 +1283,30 @@ pub unsafe extern "C" fn instr_0F01_0_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe extern "C" fn instr_0F01_0_mem(mut addr: i32) -> () { c_comment!(("sgdt")); - writable_or_pagefault(addr, 6i32); + return_on_pagefault!(writable_or_pagefault(addr, 6i32)); let mut mask: i32 = if 0 != is_osize_32() as i32 { -1i32 } else { 16777215i32 }; - safe_write16(addr, *gdtr_size.offset(0isize)); - safe_write32(addr + 2i32, *gdtr_offset.offset(0isize) & mask); + safe_write16(addr, *gdtr_size.offset(0isize)).unwrap(); + safe_write32(addr + 2i32, *gdtr_offset.offset(0isize) & mask).unwrap(); } #[no_mangle] pub unsafe extern "C" fn instr_0F01_1_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe extern "C" fn instr_0F01_1_mem(mut addr: i32) -> () { c_comment!(("sidt")); - writable_or_pagefault(addr, 6i32); + return_on_pagefault!(writable_or_pagefault(addr, 6i32)); let mut mask: i32 = if 0 != is_osize_32() as i32 { -1i32 } else { 16777215i32 }; - safe_write16(addr, *idtr_size.offset(0isize)); - safe_write32(addr + 2i32, *idtr_offset.offset(0isize) & mask); + safe_write16(addr, *idtr_size.offset(0isize)).unwrap(); + safe_write32(addr + 2i32, *idtr_offset.offset(0isize) & mask).unwrap(); } #[no_mangle] pub unsafe extern "C" fn instr_0F01_2_reg(mut r: i32) -> () { trigger_ud(); } @@ -1366,8 +1318,8 @@ pub unsafe extern "C" fn instr_0F01_2_mem(mut addr: i32) -> () { return; } else { - let mut size: i32 = safe_read16(addr); - let mut offset: i32 = safe_read32s(addr + 2i32); + let mut size: i32 = return_on_pagefault!(safe_read16(addr)); + let mut offset: i32 = return_on_pagefault!(safe_read32s(addr + 2i32)); let mut mask: i32 = if 0 != is_osize_32() as i32 { -1i32 } @@ -1389,8 +1341,8 @@ pub unsafe extern "C" fn instr_0F01_3_mem(mut addr: i32) -> () { return; } else { - let mut size: i32 = safe_read16(addr); - let mut offset: i32 = safe_read32s(addr + 2i32); + let mut size: i32 = return_on_pagefault!(safe_read16(addr)); + let mut offset: i32 = return_on_pagefault!(safe_read32s(addr + 2i32)); let mut mask: i32 = if 0 != is_osize_32() as i32 { -1i32 } @@ -1409,7 +1361,7 @@ pub unsafe extern "C" fn instr_0F01_4_reg(mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F01_4_mem(mut addr: i32) -> () { - safe_write16(addr, *cr.offset(0isize) & 65535i32); + return_on_pagefault!(safe_write16(addr, *cr.offset(0isize) & 65535i32)); } #[no_mangle] pub unsafe extern "C" fn lmsw(mut new_cr0: i32) -> () { @@ -1438,7 +1390,7 @@ pub unsafe extern "C" fn instr_0F01_6_mem(mut addr: i32) -> () { return; } else { - lmsw(safe_read16(addr)); + lmsw(return_on_pagefault!(safe_read16(addr))); return; }; } @@ -1458,7 +1410,7 @@ pub unsafe extern "C" fn instr_0F01_7_mem(mut addr: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0F02_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, lar(____0, read_reg16(r))); } #[no_mangle] @@ -1468,7 +1420,7 @@ pub unsafe extern "C" fn instr16_0F02_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0F02_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg32(r, lar(____0, read_reg32(r))); } #[no_mangle] @@ -1478,7 +1430,7 @@ pub unsafe extern "C" fn instr32_0F02_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0F03_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, lsl(____0, read_reg16(r))); } #[no_mangle] @@ -1488,7 +1440,7 @@ pub unsafe extern "C" fn instr16_0F03_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0F03_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg32(r, lsl(____0, read_reg32(r))); } #[no_mangle] @@ -1561,7 +1513,7 @@ pub unsafe extern "C" fn instr_0F10_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F10_mem(mut addr: i32, mut r: i32) -> () { - instr_0F10(safe_read128s(addr), r); + instr_0F10(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_F30F10_reg(mut r1: i32, mut r2: i32) -> () { @@ -1579,7 +1531,7 @@ pub unsafe extern "C" fn instr_F30F10_reg(mut r1: i32, mut r2: i32) -> () { #[no_mangle] pub unsafe extern "C" fn instr_F30F10_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movss xmm, xmm/m32")); - let mut data: i32 = safe_read32s(addr); + let mut data: i32 = return_on_pagefault!(safe_read32s(addr)); write_xmm128(r, data, 0i32, 0i32, 0i32); } #[no_mangle] @@ -1593,7 +1545,7 @@ pub unsafe extern "C" fn instr_660F10_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F10_mem(mut addr: i32, mut r: i32) -> () { - instr_660F10(safe_read128s(addr), r); + instr_660F10(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_F20F10_reg(mut r1: i32, mut r2: i32) -> () { @@ -1611,7 +1563,7 @@ pub unsafe extern "C" fn instr_F20F10_reg(mut r1: i32, mut r2: i32) -> () { #[no_mangle] pub unsafe extern "C" fn instr_F20F10_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movsd xmm, xmm/m64")); - let mut data: reg64 = safe_read64s(addr); + let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); write_xmm128( r, data.u32_0[0usize] as i32, @@ -1647,7 +1599,7 @@ pub unsafe extern "C" fn instr_F30F11_reg(mut rm_dest: i32, mut reg_src: i32) -> pub unsafe extern "C" fn instr_F30F11_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movss xmm/m32, xmm")); let mut data: reg128 = read_xmm128s(r); - safe_write32(addr, data.u32_0[0usize] as i32); + return_on_pagefault!(safe_write32(addr, data.u32_0[0usize] as i32)); } #[no_mangle] pub unsafe extern "C" fn instr_660F11_reg(mut r1: i32, mut r2: i32) -> () { @@ -1676,12 +1628,12 @@ pub unsafe extern "C" fn instr_F20F11_reg(mut r1: i32, mut r2: i32) -> () { pub unsafe extern "C" fn instr_F20F11_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movsd xmm/m64, xmm")); let mut data: reg64 = read_xmm64s(r); - safe_write64(addr, data.u64_0[0usize] as i64); + return_on_pagefault!(safe_write64(addr, data.u64_0[0usize] as i64)); } #[no_mangle] pub unsafe extern "C" fn instr_0F12_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movlps xmm, m64")); - let mut data: reg64 = safe_read64s(addr); + let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); let mut orig: reg128 = read_xmm128s(r); write_xmm128( r, @@ -1709,7 +1661,7 @@ pub unsafe extern "C" fn instr_660F12_reg(mut r1: i32, mut r: i32) -> () { trigg #[no_mangle] pub unsafe extern "C" fn instr_660F12_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movlpd xmm, m64")); - let mut data: reg64 = safe_read64s(addr); + let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); write_xmm64(r, data); } #[no_mangle] @@ -1753,7 +1705,7 @@ pub unsafe extern "C" fn instr_0F14_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F14_mem(mut addr: i32, mut r: i32) -> () { - instr_0F14(safe_read64s(addr), r); + instr_0F14(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F14(mut source: reg64, mut r: i32) -> () { @@ -1774,7 +1726,7 @@ pub unsafe extern "C" fn instr_660F14_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F14_mem(mut addr: i32, mut r: i32) -> () { - instr_660F14(safe_read64s(addr), r); + instr_660F14(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F15(mut source: reg128, mut r: i32) -> () { @@ -1795,7 +1747,7 @@ pub unsafe extern "C" fn instr_0F15_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F15_mem(mut addr: i32, mut r: i32) -> () { - instr_0F15(safe_read128s(addr), r); + instr_0F15(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F15(mut source: reg128, mut r: i32) -> () { @@ -1816,7 +1768,7 @@ pub unsafe extern "C" fn instr_660F15_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F15_mem(mut addr: i32, mut r: i32) -> () { - instr_660F15(safe_read128s(addr), r); + instr_660F15(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F16_mem(mut addr: i32, mut r: i32) -> () { @@ -2041,7 +1993,7 @@ pub unsafe extern "C" fn instr_0F28_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F28_mem(mut addr: i32, mut r: i32) -> () { - instr_0F28(safe_read128s(addr), r); + instr_0F28(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F28(mut source: reg128, mut r: i32) -> () { @@ -2056,14 +2008,14 @@ pub unsafe extern "C" fn instr_660F28_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F28_mem(mut addr: i32, mut r: i32) -> () { - instr_660F28(safe_read128s(addr), r); + instr_660F28(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F29_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movaps m128, xmm")); let mut data: reg128 = read_xmm128s(r); c_comment!(("XXX: Aligned write or #gp")); - safe_write128(addr, data); + return_on_pagefault!(safe_write128(addr, data)); } #[no_mangle] pub unsafe extern "C" fn instr_0F29_reg(mut r1: i32, mut r2: i32) -> () { @@ -2075,7 +2027,7 @@ pub unsafe extern "C" fn instr_660F29_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movapd m128, xmm")); let mut data: reg128 = read_xmm128s(r); c_comment!(("XXX: Aligned write or #gp")); - safe_write128(addr, data); + return_on_pagefault!(safe_write128(addr, data)); } #[no_mangle] pub unsafe extern "C" fn instr_660F29_reg(mut r1: i32, mut r2: i32) -> () { @@ -2100,7 +2052,7 @@ pub unsafe extern "C" fn instr_660F2B_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F2C_mem(mut addr: i32, mut r: i32) -> () { - instr_0F2C(safe_read64s(addr), r); + instr_0F2C(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F2C(mut source: reg64, mut r: i32) -> () { unimplemented_sse(); } @@ -2110,7 +2062,7 @@ pub unsafe extern "C" fn instr_0F2C_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F2C_mem(mut addr: i32, mut r: i32) -> () { - instr_660F2C(safe_read128s(addr), r); + instr_660F2C(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F2C(mut source: reg128, mut r: i32) -> () { unimplemented_sse(); } @@ -2146,11 +2098,11 @@ pub unsafe extern "C" fn instr_F20F2C_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F20F2C_mem(mut addr: i32, mut r: i32) -> () { - instr_F20F2C(safe_read64s(addr), r); + instr_F20F2C(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_F30F2C_mem(mut addr: i32, mut r: i32) -> () { - instr_F30F2C(fpu_load_m32(addr) as f32, r); + instr_F30F2C(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] pub unsafe extern "C" fn instr_F30F2C(mut source: f32, mut r: i32) -> () { unimplemented_sse(); } @@ -2396,7 +2348,7 @@ pub unsafe extern "C" fn instr_0F3E() -> () { unimplemented_sse(); } pub unsafe extern "C" fn instr_0F3F() -> () { unimplemented_sse(); } #[no_mangle] pub unsafe extern "C" fn instr16_0F40_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_o(), ____0, r); } #[no_mangle] @@ -2406,7 +2358,7 @@ pub unsafe extern "C" fn instr16_0F40_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0F40_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_o(), ____0, r); } #[no_mangle] @@ -2416,7 +2368,7 @@ pub unsafe extern "C" fn instr32_0F40_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0F41_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_o(), ____0, r); } #[no_mangle] @@ -2426,7 +2378,7 @@ pub unsafe extern "C" fn instr16_0F41_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0F41_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_o(), ____0, r); } #[no_mangle] @@ -2436,7 +2388,7 @@ pub unsafe extern "C" fn instr32_0F41_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0F42_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_b(), ____0, r); } #[no_mangle] @@ -2446,7 +2398,7 @@ pub unsafe extern "C" fn instr16_0F42_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0F42_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_b(), ____0, r); } #[no_mangle] @@ -2456,7 +2408,7 @@ pub unsafe extern "C" fn instr32_0F42_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0F43_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_b(), ____0, r); } #[no_mangle] @@ -2466,7 +2418,7 @@ pub unsafe extern "C" fn instr16_0F43_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0F43_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_b(), ____0, r); } #[no_mangle] @@ -2476,7 +2428,7 @@ pub unsafe extern "C" fn instr32_0F43_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0F44_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_z(), ____0, r); } #[no_mangle] @@ -2486,7 +2438,7 @@ pub unsafe extern "C" fn instr16_0F44_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0F44_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_z(), ____0, r); } #[no_mangle] @@ -2496,7 +2448,7 @@ pub unsafe extern "C" fn instr32_0F44_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0F45_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_z(), ____0, r); } #[no_mangle] @@ -2506,7 +2458,7 @@ pub unsafe extern "C" fn instr16_0F45_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0F45_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_z(), ____0, r); } #[no_mangle] @@ -2516,7 +2468,7 @@ pub unsafe extern "C" fn instr32_0F45_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0F46_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_be(), ____0, r); } #[no_mangle] @@ -2526,7 +2478,7 @@ pub unsafe extern "C" fn instr16_0F46_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0F46_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_be(), ____0, r); } #[no_mangle] @@ -2536,7 +2488,7 @@ pub unsafe extern "C" fn instr32_0F46_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0F47_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_be(), ____0, r); } #[no_mangle] @@ -2546,7 +2498,7 @@ pub unsafe extern "C" fn instr16_0F47_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0F47_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_be(), ____0, r); } #[no_mangle] @@ -2556,7 +2508,7 @@ pub unsafe extern "C" fn instr32_0F47_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0F48_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_s(), ____0, r); } #[no_mangle] @@ -2566,7 +2518,7 @@ pub unsafe extern "C" fn instr16_0F48_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0F48_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_s(), ____0, r); } #[no_mangle] @@ -2576,7 +2528,7 @@ pub unsafe extern "C" fn instr32_0F48_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0F49_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_s(), ____0, r); } #[no_mangle] @@ -2586,7 +2538,7 @@ pub unsafe extern "C" fn instr16_0F49_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0F49_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_s(), ____0, r); } #[no_mangle] @@ -2596,7 +2548,7 @@ pub unsafe extern "C" fn instr32_0F49_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0F4A_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_p(), ____0, r); } #[no_mangle] @@ -2606,7 +2558,7 @@ pub unsafe extern "C" fn instr16_0F4A_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0F4A_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_p(), ____0, r); } #[no_mangle] @@ -2616,7 +2568,7 @@ pub unsafe extern "C" fn instr32_0F4A_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0F4B_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_p(), ____0, r); } #[no_mangle] @@ -2626,7 +2578,7 @@ pub unsafe extern "C" fn instr16_0F4B_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0F4B_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_p(), ____0, r); } #[no_mangle] @@ -2636,7 +2588,7 @@ pub unsafe extern "C" fn instr32_0F4B_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0F4C_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_l(), ____0, r); } #[no_mangle] @@ -2646,7 +2598,7 @@ pub unsafe extern "C" fn instr16_0F4C_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0F4C_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_l(), ____0, r); } #[no_mangle] @@ -2656,7 +2608,7 @@ pub unsafe extern "C" fn instr32_0F4C_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0F4D_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_l(), ____0, r); } #[no_mangle] @@ -2666,7 +2618,7 @@ pub unsafe extern "C" fn instr16_0F4D_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0F4D_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_l(), ____0, r); } #[no_mangle] @@ -2676,7 +2628,7 @@ pub unsafe extern "C" fn instr32_0F4D_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0F4E_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_le(), ____0, r); } #[no_mangle] @@ -2686,7 +2638,7 @@ pub unsafe extern "C" fn instr16_0F4E_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0F4E_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_le(), ____0, r); } #[no_mangle] @@ -2696,7 +2648,7 @@ pub unsafe extern "C" fn instr32_0F4E_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0F4F_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_le(), ____0, r); } #[no_mangle] @@ -2706,7 +2658,7 @@ pub unsafe extern "C" fn instr16_0F4F_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0F4F_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_le(), ____0, r); } #[no_mangle] @@ -2748,7 +2700,7 @@ pub unsafe extern "C" fn instr_0F54_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F54_mem(mut addr: i32, mut r: i32) -> () { - instr_0F54(safe_read128s(addr), r); + instr_0F54(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F54(mut source: reg128, mut r: i32) -> () { @@ -2762,7 +2714,7 @@ pub unsafe extern "C" fn instr_660F54_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F54_mem(mut addr: i32, mut r: i32) -> () { - instr_660F54(safe_read128s(addr), r); + instr_660F54(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F55(mut source: reg128, mut r: i32) -> () { @@ -2776,7 +2728,7 @@ pub unsafe extern "C" fn instr_0F55_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F55_mem(mut addr: i32, mut r: i32) -> () { - instr_0F55(safe_read128s(addr), r); + instr_0F55(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F55(mut source: reg128, mut r: i32) -> () { @@ -2790,7 +2742,7 @@ pub unsafe extern "C" fn instr_660F55_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F55_mem(mut addr: i32, mut r: i32) -> () { - instr_660F55(safe_read128s(addr), r); + instr_660F55(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F56(mut source: reg128, mut r: i32) -> () { @@ -2804,7 +2756,7 @@ pub unsafe extern "C" fn instr_0F56_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F56_mem(mut addr: i32, mut r: i32) -> () { - instr_0F56(safe_read128s(addr), r); + instr_0F56(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F56(mut source: reg128, mut r: i32) -> () { @@ -2818,7 +2770,7 @@ pub unsafe extern "C" fn instr_660F56_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F56_mem(mut addr: i32, mut r: i32) -> () { - instr_660F56(safe_read128s(addr), r); + instr_660F56(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F57(mut source: reg128, mut r: i32) -> () { @@ -2832,7 +2784,7 @@ pub unsafe extern "C" fn instr_0F57_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F57_mem(mut addr: i32, mut r: i32) -> () { - instr_0F57(safe_read128s(addr), r); + instr_0F57(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F57(mut source: reg128, mut r: i32) -> () { @@ -2846,7 +2798,7 @@ pub unsafe extern "C" fn instr_660F57_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F57_mem(mut addr: i32, mut r: i32) -> () { - instr_660F57(safe_read128s(addr), r); + instr_660F57(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F60(mut source: i32, mut r: i32) -> () { @@ -2870,7 +2822,7 @@ pub unsafe extern "C" fn instr_0F60_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F60_mem(mut addr: i32, mut r: i32) -> () { - instr_0F60(safe_read32s(addr), r); + instr_0F60(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F60(mut source: reg64, mut r: i32) -> () { @@ -2903,7 +2855,7 @@ pub unsafe extern "C" fn instr_660F60_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F60_mem(mut addr: i32, mut r: i32) -> () { - instr_660F60(safe_read64s(addr), r); + instr_660F60(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F61(mut source: i32, mut r: i32) -> () { @@ -2923,7 +2875,7 @@ pub unsafe extern "C" fn instr_0F61_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F61_mem(mut addr: i32, mut r: i32) -> () { - instr_0F61(safe_read32s(addr), r); + instr_0F61(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F61(mut source: reg64, mut r: i32) -> () { @@ -2944,7 +2896,7 @@ pub unsafe extern "C" fn instr_660F61_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F61_mem(mut addr: i32, mut r: i32) -> () { - instr_660F61(safe_read64s(addr), r); + instr_660F61(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F62(mut source: i32, mut r: i32) -> () { @@ -2958,7 +2910,7 @@ pub unsafe extern "C" fn instr_0F62_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F62_mem(mut addr: i32, mut r: i32) -> () { - instr_0F62(safe_read32s(addr), r); + instr_0F62(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F62(mut source: reg128, mut r: i32) -> () { @@ -2979,7 +2931,7 @@ pub unsafe extern "C" fn instr_660F62_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F62_mem(mut addr: i32, mut r: i32) -> () { - instr_660F62(safe_read128s(addr), r); + instr_660F62(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F63(mut source: reg64, mut r: i32) -> () { @@ -3001,7 +2953,7 @@ pub unsafe extern "C" fn instr_0F63_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F63_mem(mut addr: i32, mut r: i32) -> () { - instr_0F63(safe_read64s(addr), r); + instr_0F63(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F63(mut source: reg128, mut r: i32) -> () { @@ -3032,7 +2984,7 @@ pub unsafe extern "C" fn instr_660F63_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F63_mem(mut addr: i32, mut r: i32) -> () { - instr_660F63(safe_read128s(addr), r); + instr_660F63(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F64(mut source: reg64, mut r: i32) -> () { @@ -3060,7 +3012,7 @@ pub unsafe extern "C" fn instr_0F64_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F64_mem(mut addr: i32, mut r: i32) -> () { - instr_0F64(safe_read64s(addr), r); + instr_0F64(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F64(mut source: reg128, mut r: i32) -> () { @@ -3089,7 +3041,7 @@ pub unsafe extern "C" fn instr_660F64_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F64_mem(mut addr: i32, mut r: i32) -> () { - instr_660F64(safe_read128s(addr), r); + instr_660F64(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F65(mut source: reg64, mut r: i32) -> () { @@ -3129,7 +3081,7 @@ pub unsafe extern "C" fn instr_0F65_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F65_mem(mut addr: i32, mut r: i32) -> () { - instr_0F65(safe_read64s(addr), r); + instr_0F65(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F65(mut source: reg128, mut r: i32) -> () { @@ -3158,7 +3110,7 @@ pub unsafe extern "C" fn instr_660F65_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F65_mem(mut addr: i32, mut r: i32) -> () { - instr_660F65(safe_read128s(addr), r); + instr_660F65(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F66(mut source: reg64, mut r: i32) -> () { @@ -3184,7 +3136,7 @@ pub unsafe extern "C" fn instr_0F66_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F66_mem(mut addr: i32, mut r: i32) -> () { - instr_0F66(safe_read64s(addr), r); + instr_0F66(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F66(mut source: reg128, mut r: i32) -> () { @@ -3225,7 +3177,7 @@ pub unsafe extern "C" fn instr_660F66_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F66_mem(mut addr: i32, mut r: i32) -> () { - instr_660F66(safe_read128s(addr), r); + instr_660F66(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F67(mut source: reg64, mut r: i32) -> () { @@ -3247,7 +3199,7 @@ pub unsafe extern "C" fn instr_0F67_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F67_mem(mut addr: i32, mut r: i32) -> () { - instr_0F67(safe_read64s(addr), r); + instr_0F67(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F67(mut source: reg128, mut r: i32) -> () { @@ -3269,7 +3221,7 @@ pub unsafe extern "C" fn instr_660F67_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F67_mem(mut addr: i32, mut r: i32) -> () { - instr_660F67(safe_read128s(addr), r); + instr_660F67(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F68(mut source: reg64, mut r: i32) -> () { @@ -3293,7 +3245,7 @@ pub unsafe extern "C" fn instr_0F68_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F68_mem(mut addr: i32, mut r: i32) -> () { - instr_0F68(safe_read64s(addr), r); + instr_0F68(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F68(mut source: reg128, mut r: i32) -> () { @@ -3326,7 +3278,7 @@ pub unsafe extern "C" fn instr_660F68_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F68_mem(mut addr: i32, mut r: i32) -> () { - instr_660F68(safe_read128s(addr), r); + instr_660F68(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F69(mut source: reg64, mut r: i32) -> () { @@ -3346,7 +3298,7 @@ pub unsafe extern "C" fn instr_0F69_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F69_mem(mut addr: i32, mut r: i32) -> () { - instr_0F69(safe_read64s(addr), r); + instr_0F69(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F69(mut source: reg128, mut r: i32) -> () { @@ -3365,7 +3317,7 @@ pub unsafe extern "C" fn instr_660F69_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F69_mem(mut addr: i32, mut r: i32) -> () { - instr_660F69(safe_read128s(addr), r); + instr_660F69(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F6A(mut source: reg64, mut r: i32) -> () { @@ -3383,7 +3335,7 @@ pub unsafe extern "C" fn instr_0F6A_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F6A_mem(mut addr: i32, mut r: i32) -> () { - instr_0F6A(safe_read64s(addr), r); + instr_0F6A(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F6A(mut source: reg128, mut r: i32) -> () { @@ -3404,7 +3356,7 @@ pub unsafe extern "C" fn instr_660F6A_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F6A_mem(mut addr: i32, mut r: i32) -> () { - instr_660F6A(safe_read128s(addr), r); + instr_660F6A(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F6B(mut source: reg64, mut r: i32) -> () { @@ -3422,7 +3374,7 @@ pub unsafe extern "C" fn instr_0F6B_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F6B_mem(mut addr: i32, mut r: i32) -> () { - instr_0F6B(safe_read64s(addr), r); + instr_0F6B(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F6B(mut source: reg128, mut r: i32) -> () { @@ -3445,7 +3397,7 @@ pub unsafe extern "C" fn instr_660F6B_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F6B_mem(mut addr: i32, mut r: i32) -> () { - instr_660F6B(safe_read128s(addr), r); + instr_660F6B(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F6C_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } @@ -3470,7 +3422,7 @@ pub unsafe extern "C" fn instr_660F6C_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F6C_mem(mut addr: i32, mut r: i32) -> () { - instr_660F6C(safe_read128s(addr), r); + instr_660F6C(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F6D_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } @@ -3495,7 +3447,7 @@ pub unsafe extern "C" fn instr_660F6D_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F6D_mem(mut addr: i32, mut r: i32) -> () { - instr_660F6D(safe_read128s(addr), r); + instr_660F6D(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F6E(mut source: i32, mut r: i32) -> () { @@ -3508,7 +3460,7 @@ pub unsafe extern "C" fn instr_0F6E_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F6E_mem(mut addr: i32, mut r: i32) -> () { - instr_0F6E(safe_read32s(addr), r); + instr_0F6E(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F6E(mut source: i32, mut r: i32) -> () { @@ -3521,7 +3473,7 @@ pub unsafe extern "C" fn instr_660F6E_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F6E_mem(mut addr: i32, mut r: i32) -> () { - instr_660F6E(safe_read32s(addr), r); + instr_660F6E(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F6F(mut source: reg64, mut r: i32) -> () { @@ -3534,7 +3486,7 @@ pub unsafe extern "C" fn instr_0F6F_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F6F_mem(mut addr: i32, mut r: i32) -> () { - instr_0F6F(safe_read64s(addr), r); + instr_0F6F(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F6F(mut source: reg128, mut r: i32) -> () { @@ -3549,7 +3501,7 @@ pub unsafe extern "C" fn instr_660F6F_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F6F_mem(mut addr: i32, mut r: i32) -> () { - instr_660F6F(safe_read128s(addr), r); + instr_660F6F(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_F30F6F(mut source: reg128, mut r: i32) -> () { @@ -3562,7 +3514,7 @@ pub unsafe extern "C" fn instr_F30F6F_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F30F6F_mem(mut addr: i32, mut r: i32) -> () { - instr_F30F6F(safe_read128s(addr), r); + instr_F30F6F(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F70(mut source: reg64, mut r: i32, mut imm8: i32) -> () { @@ -3591,7 +3543,7 @@ pub unsafe extern "C" fn instr_0F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) } #[no_mangle] pub unsafe extern "C" fn instr_0F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { - instr_0F70(safe_read64s(addr), r, imm); + instr_0F70(return_on_pagefault!(safe_read64s(addr)), r, imm); } #[no_mangle] pub unsafe extern "C" fn instr_660F70(mut source: reg128, mut r: i32, mut imm8: i32) -> () { @@ -3611,7 +3563,7 @@ pub unsafe extern "C" fn instr_660F70_reg(mut r1: i32, mut r2: i32, mut imm: i32 } #[no_mangle] pub unsafe extern "C" fn instr_660F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { - instr_660F70(safe_read128s(addr), r, imm); + instr_660F70(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] pub unsafe extern "C" fn instr_F20F70(mut source: reg128, mut r: i32, mut imm8: i32) -> () { @@ -3633,7 +3585,7 @@ pub unsafe extern "C" fn instr_F20F70_reg(mut r1: i32, mut r2: i32, mut imm: i32 } #[no_mangle] pub unsafe extern "C" fn instr_F20F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { - instr_F20F70(safe_read128s(addr), r, imm); + instr_F20F70(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] pub unsafe extern "C" fn instr_F30F70(mut source: reg128, mut r: i32, mut imm8: i32) -> () { @@ -3655,7 +3607,7 @@ pub unsafe extern "C" fn instr_F30F70_reg(mut r1: i32, mut r2: i32, mut imm: i32 } #[no_mangle] pub unsafe extern "C" fn instr_F30F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { - instr_F30F70(safe_read128s(addr), r, imm); + instr_F30F70(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] pub unsafe extern "C" fn instr_0F71_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } @@ -3849,7 +3801,7 @@ pub unsafe extern "C" fn instr_0F74_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F74_mem(mut addr: i32, mut r: i32) -> () { - instr_0F74(safe_read64s(addr), r); + instr_0F74(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F74(mut source: reg128, mut r: i32) -> () { @@ -3876,7 +3828,7 @@ pub unsafe extern "C" fn instr_660F74_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F74_mem(mut addr: i32, mut r: i32) -> () { - instr_660F74(safe_read128s(addr), r); + instr_660F74(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F75(mut source: reg64, mut r: i32) -> () { @@ -3916,7 +3868,7 @@ pub unsafe extern "C" fn instr_0F75_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F75_mem(mut addr: i32, mut r: i32) -> () { - instr_0F75(safe_read64s(addr), r); + instr_0F75(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F75(mut source: reg128, mut r: i32) -> () { @@ -3943,7 +3895,7 @@ pub unsafe extern "C" fn instr_660F75_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F75_mem(mut addr: i32, mut r: i32) -> () { - instr_660F75(safe_read128s(addr), r); + instr_660F75(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F76(mut source: reg64, mut r: i32) -> () { @@ -3969,7 +3921,7 @@ pub unsafe extern "C" fn instr_0F76_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F76_mem(mut addr: i32, mut r: i32) -> () { - instr_0F76(safe_read64s(addr), r); + instr_0F76(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F76(mut source: reg128, mut r: i32) -> () { @@ -4010,7 +3962,7 @@ pub unsafe extern "C" fn instr_660F76_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F76_mem(mut addr: i32, mut r: i32) -> () { - instr_660F76(safe_read128s(addr), r); + instr_660F76(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F77() -> () { @@ -4041,7 +3993,7 @@ pub unsafe extern "C" fn instr_0F7E_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F7E_mem(mut addr: i32, mut r: i32) -> () { - safe_write32(addr, instr_0F7E(r)); + return_on_pagefault!(safe_write32(addr, instr_0F7E(r))); } #[no_mangle] pub unsafe extern "C" fn instr_660F7E(mut r: i32) -> i32 { @@ -4055,12 +4007,12 @@ pub unsafe extern "C" fn instr_660F7E_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F7E_mem(mut addr: i32, mut r: i32) -> () { - safe_write32(addr, instr_660F7E(r)); + return_on_pagefault!(safe_write32(addr, instr_660F7E(r))); } #[no_mangle] pub unsafe extern "C" fn instr_F30F7E_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movq xmm, xmm/mem64")); - let mut data: reg64 = safe_read64s(addr); + let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); write_xmm128( r, data.u32_0[0usize] as i32, @@ -4307,12 +4259,19 @@ pub unsafe extern "C" fn instr_0F9F_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(!test_le(), addr); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FA0() -> () { push16(*sreg.offset(FS as isize) as i32); } +pub unsafe extern "C" fn instr16_0FA0() -> () { + return_on_pagefault!(push16(*sreg.offset(FS as isize) as i32)); +} #[no_mangle] -pub unsafe extern "C" fn instr32_0FA0() -> () { push32(*sreg.offset(FS as isize) as i32); } +pub unsafe extern "C" fn instr32_0FA0() -> () { + return_on_pagefault!(push32(*sreg.offset(FS as isize) as i32)); +} #[no_mangle] pub unsafe extern "C" fn instr16_0FA1() -> () { - if !switch_seg(FS, safe_read16(get_stack_pointer(0i32))) { + if !switch_seg( + FS, + return_on_pagefault!(safe_read16(get_stack_pointer(0i32))), + ) { return; } else { @@ -4322,7 +4281,10 @@ pub unsafe extern "C" fn instr16_0FA1() -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0FA1() -> () { - if !switch_seg(FS, safe_read32s(get_stack_pointer(0i32)) & 65535i32) { + if !switch_seg( + FS, + return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))) & 65535i32, + ) { return; } else { @@ -4414,12 +4376,19 @@ pub unsafe extern "C" fn instr_0FA6() -> () { #[no_mangle] pub unsafe extern "C" fn instr_0FA7() -> () { undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FA8() -> () { push16(*sreg.offset(GS as isize) as i32); } +pub unsafe extern "C" fn instr16_0FA8() -> () { + return_on_pagefault!(push16(*sreg.offset(GS as isize) as i32)); +} #[no_mangle] -pub unsafe extern "C" fn instr32_0FA8() -> () { push32(*sreg.offset(GS as isize) as i32); } +pub unsafe extern "C" fn instr32_0FA8() -> () { + return_on_pagefault!(push32(*sreg.offset(GS as isize) as i32)); +} #[no_mangle] pub unsafe extern "C" fn instr16_0FA9() -> () { - if !switch_seg(GS, safe_read16(get_stack_pointer(0i32))) { + if !switch_seg( + GS, + return_on_pagefault!(safe_read16(get_stack_pointer(0i32))), + ) { return; } else { @@ -4429,7 +4398,10 @@ pub unsafe extern "C" fn instr16_0FA9() -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0FA9() -> () { - if !switch_seg(GS, safe_read32s(get_stack_pointer(0i32)) & 65535i32) { + if !switch_seg( + GS, + return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))) & 65535i32, + ) { return; } else { @@ -4529,7 +4501,7 @@ pub unsafe extern "C" fn instr_0FAE_2_reg(mut r: i32) -> () { unimplemented_sse( #[no_mangle] pub unsafe extern "C" fn instr_0FAE_2_mem(mut addr: i32) -> () { c_comment!(("ldmxcsr")); - let mut new_mxcsr: i32 = safe_read32s(addr); + let mut new_mxcsr: i32 = return_on_pagefault!(safe_read32s(addr)); if 0 != new_mxcsr & !MXCSR_MASK { dbg_log_c!(("Invalid mxcsr bits: %x"), new_mxcsr & !MXCSR_MASK); dbg_assert!(0 != 0i32); @@ -4546,7 +4518,7 @@ pub unsafe extern "C" fn instr_0FAE_3_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe extern "C" fn instr_0FAE_3_mem(mut addr: i32) -> () { c_comment!(("stmxcsr")); - safe_write32(addr, *mxcsr); + return_on_pagefault!(safe_write32(addr, *mxcsr)); } #[no_mangle] pub unsafe extern "C" fn instr_0FAE_4_reg(mut r: i32) -> () { trigger_ud(); } @@ -4587,7 +4559,7 @@ pub unsafe extern "C" fn instr_0FAE_7_mem(mut addr: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0FAF_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16( r, imul_reg16(read_reg16(r) << 16i32 >> 16i32, ____0 << 16i32 >> 16i32), @@ -4603,7 +4575,7 @@ pub unsafe extern "C" fn instr16_0FAF_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0FAF_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, imul_reg32(read_reg32(r), ____0)); } #[no_mangle] @@ -4626,14 +4598,14 @@ pub unsafe extern "C" fn instr_0FB0_reg(mut r1: i32, mut r2: i32) -> () { #[no_mangle] pub unsafe extern "C" fn instr_0FB0_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("cmpxchg8")); - writable_or_pagefault(addr, 1i32); - let mut data: i32 = safe_read8(addr); + return_on_pagefault!(writable_or_pagefault(addr, 1i32)); + let mut data: i32 = return_on_pagefault!(safe_read8(addr)); cmp8(*reg8.offset(AL as isize) as i32, data); if getzf() { - safe_write8(addr, read_reg8(r)); + safe_write8(addr, read_reg8(r)).unwrap(); } else { - safe_write8(addr, data); + safe_write8(addr, data).unwrap(); *reg8.offset(AL as isize) = data as u8 }; } @@ -4652,14 +4624,14 @@ pub unsafe extern "C" fn instr16_0FB1_reg(mut r1: i32, mut r2: i32) -> () { #[no_mangle] pub unsafe extern "C" fn instr16_0FB1_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("cmpxchg16")); - writable_or_pagefault(addr, 2i32); - let mut data: i32 = safe_read16(addr); + return_on_pagefault!(writable_or_pagefault(addr, 2i32)); + let mut data: i32 = return_on_pagefault!(safe_read16(addr)); cmp16(*reg16.offset(AX as isize) as i32, data); if getzf() { - safe_write16(addr, read_reg16(r)); + safe_write16(addr, read_reg16(r)).unwrap(); } else { - safe_write16(addr, data); + safe_write16(addr, data).unwrap(); *reg16.offset(AX as isize) = data as u16 }; } @@ -4678,14 +4650,14 @@ pub unsafe extern "C" fn instr32_0FB1_reg(mut r1: i32, mut r2: i32) -> () { #[no_mangle] pub unsafe extern "C" fn instr32_0FB1_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("cmpxchg32")); - writable_or_pagefault(addr, 4i32); - let mut data: i32 = safe_read32s(addr); + return_on_pagefault!(writable_or_pagefault(addr, 4i32)); + let mut data: i32 = return_on_pagefault!(safe_read32s(addr)); cmp32(*reg32s.offset(EAX as isize), data); if getzf() { - safe_write32(addr, read_reg32(r)); + safe_write32(addr, read_reg32(r)).unwrap(); } else { - safe_write32(addr, data); + safe_write32(addr, data).unwrap(); *reg32s.offset(EAX as isize) = data }; } @@ -4737,7 +4709,7 @@ pub unsafe extern "C" fn instr32_0FB5_reg(mut unused: i32, mut unused2: i32) -> pub unsafe extern "C" fn instr32_0FB5_mem(mut addr: i32, mut r: i32) -> () { lss32(addr, r, GS); } #[no_mangle] pub unsafe extern "C" fn instr16_0FB6_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read8(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg16(r, ____0); } #[no_mangle] @@ -4747,7 +4719,7 @@ pub unsafe extern "C" fn instr16_0FB6_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0FB6_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read8(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg32(r, ____0); } #[no_mangle] @@ -4757,7 +4729,7 @@ pub unsafe extern "C" fn instr32_0FB6_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0FB7_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, ____0); } #[no_mangle] @@ -4767,7 +4739,7 @@ pub unsafe extern "C" fn instr16_0FB7_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0FB7_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg32(r, ____0); } #[no_mangle] @@ -4781,7 +4753,7 @@ pub unsafe extern "C" fn instr16_0FB8_reg(mut r1: i32, mut r2: i32) -> () { trig pub unsafe extern "C" fn instr16_0FB8_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe extern "C" fn instr16_F30FB8_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, popcnt(____0)); } #[no_mangle] @@ -4795,7 +4767,7 @@ pub unsafe extern "C" fn instr32_0FB8_reg(mut r1: i32, mut r2: i32) -> () { trig pub unsafe extern "C" fn instr32_0FB8_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe extern "C" fn instr32_F30FB8_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, popcnt(____0)); } #[no_mangle] @@ -4890,7 +4862,7 @@ pub unsafe extern "C" fn instr32_0FBB_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0FBC_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, bsf16(read_reg16(r), ____0)); } #[no_mangle] @@ -4900,7 +4872,7 @@ pub unsafe extern "C" fn instr16_0FBC_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0FBC_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, bsf32(read_reg32(r), ____0)); } #[no_mangle] @@ -4910,7 +4882,7 @@ pub unsafe extern "C" fn instr32_0FBC_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0FBD_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, bsr16(read_reg16(r), ____0)); } #[no_mangle] @@ -4920,7 +4892,7 @@ pub unsafe extern "C" fn instr16_0FBD_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0FBD_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read32s(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, bsr32(read_reg32(r), ____0)); } #[no_mangle] @@ -4930,7 +4902,7 @@ pub unsafe extern "C" fn instr32_0FBD_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0FBE_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read8(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg16(r, ____0 << 24i32 >> 24i32); } #[no_mangle] @@ -4940,7 +4912,7 @@ pub unsafe extern "C" fn instr16_0FBE_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0FBE_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read8(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg32(r, ____0 << 24i32 >> 24i32); } #[no_mangle] @@ -4950,7 +4922,7 @@ pub unsafe extern "C" fn instr32_0FBE_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_0FBF_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, ____0 << 16i32 >> 16i32); } #[no_mangle] @@ -4960,7 +4932,7 @@ pub unsafe extern "C" fn instr16_0FBF_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_0FBF_mem(mut addr: i32, mut r: i32) -> () { - let mut ____0: i32 = safe_read16(addr); + let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg32(r, ____0 << 16i32 >> 16i32); } #[no_mangle] @@ -5000,7 +4972,7 @@ pub unsafe extern "C" fn instr_0FC3_reg(mut r1: i32, mut r2: i32) -> () { trigge #[no_mangle] pub unsafe extern "C" fn instr_0FC3_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movnti")); - safe_write32(addr, read_reg32(r)); + return_on_pagefault!(safe_write32(addr, read_reg32(r))); } #[no_mangle] pub unsafe extern "C" fn instr_0FC4(mut source: i32, mut r: i32, mut imm8: i32) -> () { @@ -5016,7 +4988,7 @@ pub unsafe extern "C" fn instr_0FC4_reg(mut r1: i32, mut r2: i32, mut imm: i32) } #[no_mangle] pub unsafe extern "C" fn instr_0FC4_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { - instr_0FC4(safe_read16(addr), r, imm); + instr_0FC4(return_on_pagefault!(safe_read16(addr)), r, imm); } #[no_mangle] pub unsafe extern "C" fn instr_660FC4(mut source: i32, mut r: i32, mut imm8: i32) -> () { @@ -5032,7 +5004,7 @@ pub unsafe extern "C" fn instr_660FC4_reg(mut r1: i32, mut r2: i32, mut imm: i32 } #[no_mangle] pub unsafe extern "C" fn instr_660FC4_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { - instr_660FC4(safe_read16(addr), r, imm); + instr_660FC4(return_on_pagefault!(safe_read16(addr)), r, imm); } #[no_mangle] pub unsafe extern "C" fn instr_0FC5_mem(mut addr: i32, mut r: i32, mut imm8: i32) -> () { @@ -5065,22 +5037,22 @@ pub unsafe extern "C" fn instr_0FC7_1_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe extern "C" fn instr_0FC7_1_mem(mut addr: i32) -> () { c_comment!(("cmpxchg8b")); - writable_or_pagefault(addr, 8i32); - let mut m64_low: i32 = safe_read32s(addr); - let mut m64_high: i32 = safe_read32s(addr + 4i32); + return_on_pagefault!(writable_or_pagefault(addr, 8i32)); + let mut m64_low: i32 = return_on_pagefault!(safe_read32s(addr)); + let mut m64_high: i32 = return_on_pagefault!(safe_read32s(addr + 4i32)); if *reg32s.offset(EAX as isize) == m64_low && *reg32s.offset(EDX as isize) == m64_high { let ref mut fresh2 = *flags.offset(0isize); *fresh2 |= FLAG_ZERO; - safe_write32(addr, *reg32s.offset(EBX as isize)); - safe_write32(addr + 4i32, *reg32s.offset(ECX as isize)); + safe_write32(addr, *reg32s.offset(EBX as isize)).unwrap(); + safe_write32(addr + 4i32, *reg32s.offset(ECX as isize)).unwrap(); } else { let ref mut fresh3 = *flags.offset(0isize); *fresh3 &= !FLAG_ZERO; *reg32s.offset(EAX as isize) = m64_low; *reg32s.offset(EDX as isize) = m64_high; - safe_write32(addr, m64_low); - safe_write32(addr + 4i32, m64_high); + safe_write32(addr, m64_low).unwrap(); + safe_write32(addr + 4i32, m64_high).unwrap(); } let ref mut fresh4 = *flags_changed.offset(0isize); *fresh4 &= !FLAG_ZERO; @@ -5131,7 +5103,7 @@ pub unsafe extern "C" fn instr_0FD1_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FD1_mem(mut addr: i32, mut r: i32) -> () { - instr_0FD1(safe_read64s(addr), r); + instr_0FD1(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FD1(mut source: reg128, mut r: i32) -> () { @@ -5145,7 +5117,7 @@ pub unsafe extern "C" fn instr_660FD1_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FD1_mem(mut addr: i32, mut r: i32) -> () { - instr_660FD1(safe_read128s(addr), r); + instr_660FD1(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FD2(mut source: reg64, mut r: i32) -> () { @@ -5158,7 +5130,7 @@ pub unsafe extern "C" fn instr_0FD2_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FD2_mem(mut addr: i32, mut r: i32) -> () { - instr_0FD2(safe_read64s(addr), r); + instr_0FD2(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FD2(mut source: reg128, mut r: i32) -> () { @@ -5172,7 +5144,7 @@ pub unsafe extern "C" fn instr_660FD2_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FD2_mem(mut addr: i32, mut r: i32) -> () { - instr_660FD2(safe_read128s(addr), r); + instr_660FD2(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FD3(mut source: reg64, mut r: i32) -> () { @@ -5185,7 +5157,7 @@ pub unsafe extern "C" fn instr_0FD3_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FD3_mem(mut addr: i32, mut r: i32) -> () { - instr_0FD3(safe_read64s(addr), r); + instr_0FD3(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FD3(mut source: reg128, mut r: i32) -> () { @@ -5198,7 +5170,7 @@ pub unsafe extern "C" fn instr_660FD3_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FD3_mem(mut addr: i32, mut r: i32) -> () { - instr_660FD3(safe_read128s(addr), r); + instr_660FD3(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FD4(mut source: reg64, mut r: i32) -> () { @@ -5214,7 +5186,7 @@ pub unsafe extern "C" fn instr_0FD4_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FD4_mem(mut addr: i32, mut r: i32) -> () { - instr_0FD4(safe_read64s(addr), r); + instr_0FD4(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FD4(mut source: reg128, mut r: i32) -> () { @@ -5233,7 +5205,7 @@ pub unsafe extern "C" fn instr_660FD4_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FD4_mem(mut addr: i32, mut r: i32) -> () { - instr_660FD4(safe_read128s(addr), r); + instr_660FD4(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FD5(mut source: reg64, mut r: i32) -> () { @@ -5253,7 +5225,7 @@ pub unsafe extern "C" fn instr_0FD5_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FD5_mem(mut addr: i32, mut r: i32) -> () { - instr_0FD5(safe_read64s(addr), r); + instr_0FD5(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FD5(mut source: reg128, mut r: i32) -> () { @@ -5278,7 +5250,7 @@ pub unsafe extern "C" fn instr_660FD5_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FD5_mem(mut addr: i32, mut r: i32) -> () { - instr_660FD5(safe_read128s(addr), r); + instr_660FD5(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FD6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } @@ -5385,7 +5357,7 @@ pub unsafe extern "C" fn instr_0FD8_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FD8_mem(mut addr: i32, mut r: i32) -> () { - instr_0FD8(safe_read64s(addr), r); + instr_0FD8(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FD8(mut source: reg128, mut r: i32) -> () { @@ -5407,7 +5379,7 @@ pub unsafe extern "C" fn instr_660FD8_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FD8_mem(mut addr: i32, mut r: i32) -> () { - instr_660FD8(safe_read128s(addr), r); + instr_660FD8(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FD9(mut source: reg64, mut r: i32) -> () { @@ -5431,7 +5403,7 @@ pub unsafe extern "C" fn instr_0FD9_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FD9_mem(mut addr: i32, mut r: i32) -> () { - instr_0FD9(safe_read64s(addr), r); + instr_0FD9(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FD9(mut source: reg128, mut r: i32) -> () { @@ -5453,7 +5425,7 @@ pub unsafe extern "C" fn instr_660FD9_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FD9_mem(mut addr: i32, mut r: i32) -> () { - instr_660FD9(safe_read128s(addr), r); + instr_660FD9(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FDA(mut source: reg64, mut r: i32) -> () { @@ -5479,7 +5451,7 @@ pub unsafe extern "C" fn instr_0FDA_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FDA_mem(mut addr: i32, mut r: i32) -> () { - instr_0FDA(safe_read64s(addr), r); + instr_0FDA(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FDA(mut source: reg128, mut r: i32) -> () { @@ -5506,7 +5478,7 @@ pub unsafe extern "C" fn instr_660FDA_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FDA_mem(mut addr: i32, mut r: i32) -> () { - instr_660FDA(safe_read128s(addr), r); + instr_660FDA(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FDB(mut source: reg64, mut r: i32) -> () { @@ -5524,7 +5496,7 @@ pub unsafe extern "C" fn instr_0FDB_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FDB_mem(mut addr: i32, mut r: i32) -> () { - instr_0FDB(safe_read64s(addr), r); + instr_0FDB(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FDB(mut source: reg128, mut r: i32) -> () { @@ -5538,7 +5510,7 @@ pub unsafe extern "C" fn instr_660FDB_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FDB_mem(mut addr: i32, mut r: i32) -> () { - instr_660FDB(safe_read128s(addr), r); + instr_660FDB(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FDC(mut source: reg64, mut r: i32) -> () { @@ -5562,7 +5534,7 @@ pub unsafe extern "C" fn instr_0FDC_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FDC_mem(mut addr: i32, mut r: i32) -> () { - instr_0FDC(safe_read64s(addr), r); + instr_0FDC(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FDC(mut source: reg128, mut r: i32) -> () { @@ -5585,7 +5557,7 @@ pub unsafe extern "C" fn instr_660FDC_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FDC_mem(mut addr: i32, mut r: i32) -> () { - instr_660FDC(safe_read128s(addr), r); + instr_660FDC(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FDD(mut source: reg64, mut r: i32) -> () { @@ -5609,7 +5581,7 @@ pub unsafe extern "C" fn instr_0FDD_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FDD_mem(mut addr: i32, mut r: i32) -> () { - instr_0FDD(safe_read64s(addr), r); + instr_0FDD(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FDD(mut source: reg128, mut r: i32) -> () { @@ -5638,7 +5610,7 @@ pub unsafe extern "C" fn instr_660FDD_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FDD_mem(mut addr: i32, mut r: i32) -> () { - instr_660FDD(safe_read128s(addr), r); + instr_660FDD(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FDE(mut source: reg64, mut r: i32) -> () { @@ -5664,7 +5636,7 @@ pub unsafe extern "C" fn instr_0FDE_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FDE_mem(mut addr: i32, mut r: i32) -> () { - instr_0FDE(safe_read64s(addr), r); + instr_0FDE(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FDE(mut source: reg128, mut r: i32) -> () { @@ -5691,7 +5663,7 @@ pub unsafe extern "C" fn instr_660FDE_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FDE_mem(mut addr: i32, mut r: i32) -> () { - instr_660FDE(safe_read128s(addr), r); + instr_660FDE(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FDF(mut source: reg64, mut r: i32) -> () { @@ -5709,7 +5681,7 @@ pub unsafe extern "C" fn instr_0FDF_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FDF_mem(mut addr: i32, mut r: i32) -> () { - instr_0FDF(safe_read64s(addr), r); + instr_0FDF(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FDF(mut source: reg128, mut r: i32) -> () { @@ -5723,7 +5695,7 @@ pub unsafe extern "C" fn instr_660FDF_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FDF_mem(mut addr: i32, mut r: i32) -> () { - instr_660FDF(safe_read128s(addr), r); + instr_660FDF(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FE0(mut source: reg64, mut r: i32) -> () { @@ -5747,7 +5719,7 @@ pub unsafe extern "C" fn instr_0FE0_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FE0_mem(mut addr: i32, mut r: i32) -> () { - instr_0FE0(safe_read64s(addr), r); + instr_0FE0(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FE0(mut source: reg128, mut r: i32) -> () { @@ -5770,7 +5742,7 @@ pub unsafe extern "C" fn instr_660FE0_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FE0_mem(mut addr: i32, mut r: i32) -> () { - instr_660FE0(safe_read128s(addr), r); + instr_660FE0(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FE1(mut source: reg64, mut r: i32) -> () { @@ -5783,7 +5755,7 @@ pub unsafe extern "C" fn instr_0FE1_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FE1_mem(mut addr: i32, mut r: i32) -> () { - instr_0FE1(safe_read64s(addr), r); + instr_0FE1(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FE1(mut source: reg128, mut r: i32) -> () { @@ -5797,7 +5769,7 @@ pub unsafe extern "C" fn instr_660FE1_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FE1_mem(mut addr: i32, mut r: i32) -> () { - instr_660FE1(safe_read128s(addr), r); + instr_660FE1(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FE2(mut source: reg64, mut r: i32) -> () { @@ -5810,7 +5782,7 @@ pub unsafe extern "C" fn instr_0FE2_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FE2_mem(mut addr: i32, mut r: i32) -> () { - instr_0FE2(safe_read64s(addr), r); + instr_0FE2(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FE2(mut source: reg128, mut r: i32) -> () { @@ -5824,7 +5796,7 @@ pub unsafe extern "C" fn instr_660FE2_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FE2_mem(mut addr: i32, mut r: i32) -> () { - instr_660FE2(safe_read128s(addr), r); + instr_660FE2(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FE3(mut source: reg64, mut r: i32) -> () { @@ -5846,7 +5818,7 @@ pub unsafe extern "C" fn instr_0FE3_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FE3_mem(mut addr: i32, mut r: i32) -> () { - instr_0FE3(safe_read64s(addr), r); + instr_0FE3(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FE3(mut source: reg128, mut r: i32) -> () { @@ -5877,7 +5849,7 @@ pub unsafe extern "C" fn instr_660FE3_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FE3_mem(mut addr: i32, mut r: i32) -> () { - instr_660FE3(safe_read128s(addr), r); + instr_660FE3(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FE4(mut source: reg64, mut r: i32) -> () { @@ -5901,7 +5873,7 @@ pub unsafe extern "C" fn instr_0FE4_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FE4_mem(mut addr: i32, mut r: i32) -> () { - instr_0FE4(safe_read64s(addr), r); + instr_0FE4(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FE4(mut source: reg128, mut r: i32) -> () { @@ -5934,7 +5906,7 @@ pub unsafe extern "C" fn instr_660FE4_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FE4_mem(mut addr: i32, mut r: i32) -> () { - instr_660FE4(safe_read128s(addr), r); + instr_660FE4(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FE5(mut source: reg64, mut r: i32) -> () { @@ -5958,7 +5930,7 @@ pub unsafe extern "C" fn instr_0FE5_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FE5_mem(mut addr: i32, mut r: i32) -> () { - instr_0FE5(safe_read64s(addr), r); + instr_0FE5(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FE5(mut source: reg128, mut r: i32) -> () { @@ -5989,7 +5961,7 @@ pub unsafe extern "C" fn instr_660FE5_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FE5_mem(mut addr: i32, mut r: i32) -> () { - instr_660FE5(safe_read128s(addr), r); + instr_660FE5(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FE6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } @@ -6043,7 +6015,7 @@ pub unsafe extern "C" fn instr_0FE8_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FE8_mem(mut addr: i32, mut r: i32) -> () { - instr_0FE8(safe_read64s(addr), r); + instr_0FE8(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FE8(mut source: reg128, mut r: i32) -> () { @@ -6066,7 +6038,7 @@ pub unsafe extern "C" fn instr_660FE8_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FE8_mem(mut addr: i32, mut r: i32) -> () { - instr_660FE8(safe_read128s(addr), r); + instr_660FE8(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FE9(mut source: reg64, mut r: i32) -> () { @@ -6094,7 +6066,7 @@ pub unsafe extern "C" fn instr_0FE9_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FE9_mem(mut addr: i32, mut r: i32) -> () { - instr_0FE9(safe_read64s(addr), r); + instr_0FE9(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FE9(mut source: reg128, mut r: i32) -> () { @@ -6129,7 +6101,7 @@ pub unsafe extern "C" fn instr_660FE9_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FE9_mem(mut addr: i32, mut r: i32) -> () { - instr_660FE9(safe_read128s(addr), r); + instr_660FE9(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FEA(mut source: reg64, mut r: i32) -> () { @@ -6155,7 +6127,7 @@ pub unsafe extern "C" fn instr_0FEA_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FEA_mem(mut addr: i32, mut r: i32) -> () { - instr_0FEA(safe_read64s(addr), r); + instr_0FEA(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FEA(mut source: reg128, mut r: i32) -> () { @@ -6182,7 +6154,7 @@ pub unsafe extern "C" fn instr_660FEA_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FEA_mem(mut addr: i32, mut r: i32) -> () { - instr_660FEA(safe_read128s(addr), r); + instr_660FEA(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FEB(mut source: reg64, mut r: i32) -> () { @@ -6200,7 +6172,7 @@ pub unsafe extern "C" fn instr_0FEB_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FEB_mem(mut addr: i32, mut r: i32) -> () { - instr_0FEB(safe_read64s(addr), r); + instr_0FEB(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FEB(mut source: reg128, mut r: i32) -> () { @@ -6214,7 +6186,7 @@ pub unsafe extern "C" fn instr_660FEB_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FEB_mem(mut addr: i32, mut r: i32) -> () { - instr_660FEB(safe_read128s(addr), r); + instr_660FEB(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FEC(mut source: reg64, mut r: i32) -> () { @@ -6238,7 +6210,7 @@ pub unsafe extern "C" fn instr_0FEC_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FEC_mem(mut addr: i32, mut r: i32) -> () { - instr_0FEC(safe_read64s(addr), r); + instr_0FEC(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FEC(mut source: reg128, mut r: i32) -> () { @@ -6261,7 +6233,7 @@ pub unsafe extern "C" fn instr_660FEC_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FEC_mem(mut addr: i32, mut r: i32) -> () { - instr_660FEC(safe_read128s(addr), r); + instr_660FEC(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FED(mut source: reg64, mut r: i32) -> () { @@ -6289,7 +6261,7 @@ pub unsafe extern "C" fn instr_0FED_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FED_mem(mut addr: i32, mut r: i32) -> () { - instr_0FED(safe_read64s(addr), r); + instr_0FED(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FED(mut source: reg128, mut r: i32) -> () { @@ -6324,7 +6296,7 @@ pub unsafe extern "C" fn instr_660FED_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FED_mem(mut addr: i32, mut r: i32) -> () { - instr_660FED(safe_read128s(addr), r); + instr_660FED(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FEE(mut source: reg64, mut r: i32) -> () { @@ -6350,7 +6322,7 @@ pub unsafe extern "C" fn instr_0FEE_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FEE_mem(mut addr: i32, mut r: i32) -> () { - instr_0FEE(safe_read64s(addr), r); + instr_0FEE(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FEE(mut source: reg128, mut r: i32) -> () { @@ -6377,7 +6349,7 @@ pub unsafe extern "C" fn instr_660FEE_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FEE_mem(mut addr: i32, mut r: i32) -> () { - instr_660FEE(safe_read128s(addr), r); + instr_660FEE(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FEF(mut source: reg64, mut r: i32) -> () { @@ -6395,7 +6367,7 @@ pub unsafe extern "C" fn instr_0FEF_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FEF_mem(mut addr: i32, mut r: i32) -> () { - instr_0FEF(safe_read64s(addr), r); + instr_0FEF(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FEF(mut source: reg128, mut r: i32) -> () { @@ -6409,7 +6381,7 @@ pub unsafe extern "C" fn instr_660FEF_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FEF_mem(mut addr: i32, mut r: i32) -> () { - instr_660FEF(safe_read128s(addr), r); + instr_660FEF(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FF0() -> () { unimplemented_sse(); } @@ -6424,7 +6396,7 @@ pub unsafe extern "C" fn instr_0FF1_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FF1_mem(mut addr: i32, mut r: i32) -> () { - instr_0FF1(safe_read64s(addr), r); + instr_0FF1(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FF1(mut source: reg128, mut r: i32) -> () { @@ -6438,7 +6410,7 @@ pub unsafe extern "C" fn instr_660FF1_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FF1_mem(mut addr: i32, mut r: i32) -> () { - instr_660FF1(safe_read128s(addr), r); + instr_660FF1(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FF2(mut source: reg64, mut r: i32) -> () { @@ -6451,7 +6423,7 @@ pub unsafe extern "C" fn instr_0FF2_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FF2_mem(mut addr: i32, mut r: i32) -> () { - instr_0FF2(safe_read64s(addr), r); + instr_0FF2(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FF2(mut source: reg128, mut r: i32) -> () { @@ -6465,7 +6437,7 @@ pub unsafe extern "C" fn instr_660FF2_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FF2_mem(mut addr: i32, mut r: i32) -> () { - instr_660FF2(safe_read128s(addr), r); + instr_660FF2(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FF3(mut source: reg64, mut r: i32) -> () { @@ -6478,7 +6450,7 @@ pub unsafe extern "C" fn instr_0FF3_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FF3_mem(mut addr: i32, mut r: i32) -> () { - instr_0FF3(safe_read64s(addr), r); + instr_0FF3(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FF3(mut source: reg128, mut r: i32) -> () { @@ -6492,7 +6464,7 @@ pub unsafe extern "C" fn instr_660FF3_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FF3_mem(mut addr: i32, mut r: i32) -> () { - instr_660FF3(safe_read128s(addr), r); + instr_660FF3(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FF4(mut source: reg64, mut r: i32) -> () { @@ -6508,7 +6480,7 @@ pub unsafe extern "C" fn instr_0FF4_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FF4_mem(mut addr: i32, mut r: i32) -> () { - instr_0FF4(safe_read64s(addr), r); + instr_0FF4(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FF4(mut source: reg128, mut r: i32) -> () { @@ -6527,7 +6499,7 @@ pub unsafe extern "C" fn instr_660FF4_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FF4_mem(mut addr: i32, mut r: i32) -> () { - instr_660FF4(safe_read128s(addr), r); + instr_660FF4(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FF5(mut source: reg64, mut r: i32) -> () { @@ -6547,7 +6519,7 @@ pub unsafe extern "C" fn instr_0FF5_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FF5_mem(mut addr: i32, mut r: i32) -> () { - instr_0FF5(safe_read64s(addr), r); + instr_0FF5(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FF5(mut source: reg128, mut r: i32) -> () { @@ -6570,7 +6542,7 @@ pub unsafe extern "C" fn instr_660FF5_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FF5_mem(mut addr: i32, mut r: i32) -> () { - instr_660FF5(safe_read128s(addr), r); + instr_660FF5(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FF6(mut source: reg64, mut r: i32) -> () { @@ -6592,7 +6564,7 @@ pub unsafe extern "C" fn instr_0FF6_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FF6_mem(mut addr: i32, mut r: i32) -> () { - instr_0FF6(safe_read64s(addr), r); + instr_0FF6(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FF6(mut source: reg128, mut r: i32) -> () { @@ -6621,7 +6593,7 @@ pub unsafe extern "C" fn instr_660FF6_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FF6_mem(mut addr: i32, mut r: i32) -> () { - instr_660FF6(safe_read128s(addr), r); + instr_660FF6(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FF7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } @@ -6631,14 +6603,14 @@ pub unsafe extern "C" fn instr_0FF7_reg(mut r1: i32, mut r2: i32) -> () { let mut source: reg64 = read_mmx64s(r2); let mut mask: reg64 = read_mmx64s(r1); let mut addr: i32 = get_seg_prefix(DS) + get_reg_asize(EDI); - writable_or_pagefault(addr, 8i32); + return_on_pagefault!(writable_or_pagefault(addr, 8i32)); let mut i: u32 = 0i32 as u32; while i < 8i32 as u32 { if 0 != mask.u8_0[i as usize] as i32 & 128i32 { safe_write8( (addr as u32).wrapping_add(i) as i32, source.u8_0[i as usize] as i32, - ); + ).unwrap(); } i = i.wrapping_add(1) } @@ -6651,14 +6623,14 @@ pub unsafe extern "C" fn instr_660FF7_reg(mut r1: i32, mut r2: i32) -> () { let mut source: reg128 = read_xmm128s(r2); let mut mask: reg128 = read_xmm128s(r1); let mut addr: i32 = get_seg_prefix(DS) + get_reg_asize(EDI); - writable_or_pagefault(addr, 16i32); + return_on_pagefault!(writable_or_pagefault(addr, 16i32)); let mut i: u32 = 0i32 as u32; while i < 16i32 as u32 { if 0 != mask.u8_0[i as usize] as i32 & 128i32 { safe_write8( (addr as u32).wrapping_add(i) as i32, source.u8_0[i as usize] as i32, - ); + ).unwrap(); } i = i.wrapping_add(1) } @@ -6684,7 +6656,7 @@ pub unsafe extern "C" fn instr_0FF8_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FF8_mem(mut addr: i32, mut r: i32) -> () { - instr_0FF8(safe_read64s(addr), r); + instr_0FF8(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FF8(mut source: reg128, mut r: i32) -> () { @@ -6708,7 +6680,7 @@ pub unsafe extern "C" fn instr_660FF8_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FF8_mem(mut addr: i32, mut r: i32) -> () { - instr_660FF8(safe_read128s(addr), r); + instr_660FF8(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FF9(mut source: reg64, mut r: i32) -> () { @@ -6734,7 +6706,7 @@ pub unsafe extern "C" fn instr_0FF9_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FF9_mem(mut addr: i32, mut r: i32) -> () { - instr_0FF9(safe_read64s(addr), r); + instr_0FF9(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FF9(mut source: reg128, mut r: i32) -> () { @@ -6759,7 +6731,7 @@ pub unsafe extern "C" fn instr_660FF9_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FF9_mem(mut addr: i32, mut r: i32) -> () { - instr_660FF9(safe_read128s(addr), r); + instr_660FF9(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FFA(mut source: reg64, mut r: i32) -> () { @@ -6777,7 +6749,7 @@ pub unsafe extern "C" fn instr_0FFA_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FFA_mem(mut addr: i32, mut r: i32) -> () { - instr_0FFA(safe_read64s(addr), r); + instr_0FFA(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FFA(mut source: reg128, mut r: i32) -> () { @@ -6798,7 +6770,7 @@ pub unsafe extern "C" fn instr_660FFA_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FFA_mem(mut addr: i32, mut r: i32) -> () { - instr_660FFA(safe_read128s(addr), r); + instr_660FFA(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FFB(mut source: reg64, mut r: i32) -> () { @@ -6813,7 +6785,7 @@ pub unsafe extern "C" fn instr_0FFB_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FFB_mem(mut addr: i32, mut r: i32) -> () { - instr_0FFB(safe_read64s(addr), r); + instr_0FFB(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FFB(mut source: reg128, mut r: i32) -> () { @@ -6830,7 +6802,7 @@ pub unsafe extern "C" fn instr_660FFB_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FFB_mem(mut addr: i32, mut r: i32) -> () { - instr_660FFB(safe_read128s(addr), r); + instr_660FFB(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FFC(mut source: reg64, mut r: i32) -> () { @@ -6853,7 +6825,7 @@ pub unsafe extern "C" fn instr_0FFC_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FFC_mem(mut addr: i32, mut r: i32) -> () { - instr_0FFC(safe_read64s(addr), r); + instr_0FFC(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FFC(mut source: reg128, mut r: i32) -> () { @@ -6877,7 +6849,7 @@ pub unsafe extern "C" fn instr_660FFC_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FFC_mem(mut addr: i32, mut r: i32) -> () { - instr_660FFC(safe_read128s(addr), r); + instr_660FFC(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FFD(mut source: reg64, mut r: i32) -> () { @@ -6899,7 +6871,7 @@ pub unsafe extern "C" fn instr_0FFD_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FFD_mem(mut addr: i32, mut r: i32) -> () { - instr_0FFD(safe_read64s(addr), r); + instr_0FFD(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FFD(mut source: reg128, mut r: i32) -> () { @@ -6924,7 +6896,7 @@ pub unsafe extern "C" fn instr_660FFD_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FFD_mem(mut addr: i32, mut r: i32) -> () { - instr_660FFD(safe_read128s(addr), r); + instr_660FFD(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FFE(mut source: reg64, mut r: i32) -> () { @@ -6940,7 +6912,7 @@ pub unsafe extern "C" fn instr_0FFE_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0FFE_mem(mut addr: i32, mut r: i32) -> () { - instr_0FFE(safe_read64s(addr), r); + instr_0FFE(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660FFE(mut source: reg128, mut r: i32) -> () { @@ -6959,7 +6931,7 @@ pub unsafe extern "C" fn instr_660FFE_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660FFE_mem(mut addr: i32, mut r: i32) -> () { - instr_660FFE(safe_read128s(addr), r); + instr_660FFE(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0FFF() -> () { @@ -7003,7 +6975,7 @@ pub unsafe extern "C" fn instr_0F2A_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F2A_mem(mut addr: i32, mut r: i32) -> () { - instr_0F2A(safe_read64s(addr), r); + instr_0F2A(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F2A(mut source: reg64, mut r: i32) -> () { @@ -7021,7 +6993,7 @@ pub unsafe extern "C" fn instr_660F2A_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F2A_mem(mut addr: i32, mut r: i32) -> () { - instr_660F2A(safe_read64s(addr), r); + instr_660F2A(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_F20F2A(mut source: i32, mut r: i32) -> () { @@ -7038,7 +7010,7 @@ pub unsafe extern "C" fn instr_F20F2A_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F20F2A_mem(mut addr: i32, mut r: i32) -> () { - instr_F20F2A(safe_read32s(addr), r); + instr_F20F2A(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_F30F2A(mut source: i32, mut r: i32) -> () { @@ -7053,7 +7025,7 @@ pub unsafe extern "C" fn instr_F30F2A_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F30F2A_mem(mut addr: i32, mut r: i32) -> () { - instr_F30F2A(safe_read32s(addr), r); + instr_F30F2A(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_0F2D(mut source: reg64, mut r: i32) -> () { unimplemented_sse(); } @@ -7063,7 +7035,7 @@ pub unsafe extern "C" fn instr_0F2D_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F2D_mem(mut addr: i32, mut r: i32) -> () { - instr_0F2D(safe_read64s(addr), r); + instr_0F2D(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F2D(mut source: reg128, mut r: i32) -> () { unimplemented_sse(); } @@ -7073,7 +7045,7 @@ pub unsafe extern "C" fn instr_660F2D_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F2D_mem(mut addr: i32, mut r: i32) -> () { - instr_660F2D(safe_read128s(addr), r); + instr_660F2D(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_F20F2D(mut source: reg64, mut r: i32) -> () { @@ -7086,7 +7058,7 @@ pub unsafe extern "C" fn instr_F20F2D_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F20F2D_mem(mut addr: i32, mut r: i32) -> () { - instr_F20F2D(safe_read64s(addr), r); + instr_F20F2D(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_F30F2D(mut source: f32, mut r: i32) -> () { unimplemented_sse(); } @@ -7096,7 +7068,7 @@ pub unsafe extern "C" fn instr_F30F2D_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F30F2D_mem(mut addr: i32, mut r: i32) -> () { - instr_F30F2D(fpu_load_m32(addr) as f32, r); + instr_F30F2D(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] pub unsafe extern "C" fn instr_0F51(mut source: reg128, mut r: i32) -> () { @@ -7117,7 +7089,7 @@ pub unsafe extern "C" fn instr_0F51_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F51_mem(mut addr: i32, mut r: i32) -> () { - instr_0F51(safe_read128s(addr), r); + instr_0F51(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F51(mut source: reg128, mut r: i32) -> () { @@ -7133,7 +7105,7 @@ pub unsafe extern "C" fn instr_660F51_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F51_mem(mut addr: i32, mut r: i32) -> () { - instr_660F51(safe_read128s(addr), r); + instr_660F51(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_F20F51(mut source: reg64, mut r: i32) -> () { @@ -7149,7 +7121,7 @@ pub unsafe extern "C" fn instr_F20F51_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F20F51_mem(mut addr: i32, mut r: i32) -> () { - instr_F20F51(safe_read64s(addr), r); + instr_F20F51(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_F30F51(mut source: f32, mut r: i32) -> () { @@ -7162,7 +7134,7 @@ pub unsafe extern "C" fn instr_F30F51_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F30F51_mem(mut addr: i32, mut r: i32) -> () { - instr_F30F51(fpu_load_m32(addr) as f32, r); + instr_F30F51(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] pub unsafe extern "C" fn instr_0F52() -> () { unimplemented_sse(); } @@ -7185,7 +7157,7 @@ pub unsafe extern "C" fn instr_0F53_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F53_mem(mut addr: i32, mut r: i32) -> () { - instr_0F53(safe_read128s(addr), r); + instr_0F53(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_F30F53(mut source: f32, mut r: i32) -> () { @@ -7198,7 +7170,7 @@ pub unsafe extern "C" fn instr_F30F53_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F30F53_mem(mut addr: i32, mut r: i32) -> () { - instr_F30F53(fpu_load_m32(addr) as f32, r); + instr_F30F53(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] pub unsafe extern "C" fn instr_0F58(mut source: reg128, mut r: i32) -> () { @@ -7220,7 +7192,7 @@ pub unsafe extern "C" fn instr_0F58_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F58_mem(mut addr: i32, mut r: i32) -> () { - instr_0F58(safe_read128s(addr), r); + instr_0F58(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F58(mut source: reg128, mut r: i32) -> () { @@ -7240,7 +7212,7 @@ pub unsafe extern "C" fn instr_660F58_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F58_mem(mut addr: i32, mut r: i32) -> () { - instr_660F58(safe_read128s(addr), r); + instr_660F58(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_F20F58(mut source: reg64, mut r: i32) -> () { @@ -7257,7 +7229,7 @@ pub unsafe extern "C" fn instr_F20F58_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F20F58_mem(mut addr: i32, mut r: i32) -> () { - instr_F20F58(safe_read64s(addr), r); + instr_F20F58(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_F30F58(mut source: f32, mut r: i32) -> () { @@ -7272,7 +7244,7 @@ pub unsafe extern "C" fn instr_F30F58_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F30F58_mem(mut addr: i32, mut r: i32) -> () { - instr_F30F58(fpu_load_m32(addr) as f32, r); + instr_F30F58(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] pub unsafe extern "C" fn instr_0F59(mut source: reg128, mut r: i32) -> () { @@ -7294,7 +7266,7 @@ pub unsafe extern "C" fn instr_0F59_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F59_mem(mut addr: i32, mut r: i32) -> () { - instr_0F59(safe_read128s(addr), r); + instr_0F59(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F59(mut source: reg128, mut r: i32) -> () { @@ -7314,7 +7286,7 @@ pub unsafe extern "C" fn instr_660F59_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F59_mem(mut addr: i32, mut r: i32) -> () { - instr_660F59(safe_read128s(addr), r); + instr_660F59(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_F20F59(mut source: reg64, mut r: i32) -> () { @@ -7331,7 +7303,7 @@ pub unsafe extern "C" fn instr_F20F59_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F20F59_mem(mut addr: i32, mut r: i32) -> () { - instr_F20F59(safe_read64s(addr), r); + instr_F20F59(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_F30F59(mut source: f32, mut r: i32) -> () { @@ -7346,7 +7318,7 @@ pub unsafe extern "C" fn instr_F30F59_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F30F59_mem(mut addr: i32, mut r: i32) -> () { - instr_F30F59(fpu_load_m32(addr) as f32, r); + instr_F30F59(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] pub unsafe extern "C" fn instr_0F5A() -> () { unimplemented_sse(); } @@ -7372,7 +7344,7 @@ pub unsafe extern "C" fn instr_0F5C_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F5C_mem(mut addr: i32, mut r: i32) -> () { - instr_0F5C(safe_read128s(addr), r); + instr_0F5C(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F5C(mut source: reg128, mut r: i32) -> () { @@ -7392,7 +7364,7 @@ pub unsafe extern "C" fn instr_660F5C_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F5C_mem(mut addr: i32, mut r: i32) -> () { - instr_660F5C(safe_read128s(addr), r); + instr_660F5C(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_F20F5C(mut source: reg64, mut r: i32) -> () { @@ -7409,7 +7381,7 @@ pub unsafe extern "C" fn instr_F20F5C_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F20F5C_mem(mut addr: i32, mut r: i32) -> () { - instr_F20F5C(safe_read64s(addr), r); + instr_F20F5C(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_F30F5C(mut source: f32, mut r: i32) -> () { @@ -7424,7 +7396,7 @@ pub unsafe extern "C" fn instr_F30F5C_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F30F5C_mem(mut addr: i32, mut r: i32) -> () { - instr_F30F5C(fpu_load_m32(addr) as f32, r); + instr_F30F5C(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] pub unsafe extern "C" fn instr_0F5D(mut source: reg128, mut r: i32) -> () { @@ -7458,7 +7430,7 @@ pub unsafe extern "C" fn instr_0F5D_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F5D_mem(mut addr: i32, mut r: i32) -> () { - instr_0F5D(safe_read128s(addr), r); + instr_0F5D(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F5D(mut source: reg128, mut r: i32) -> () { @@ -7478,7 +7450,7 @@ pub unsafe extern "C" fn instr_660F5D_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F5D_mem(mut addr: i32, mut r: i32) -> () { - instr_660F5D(safe_read128s(addr), r); + instr_660F5D(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_F20F5D(mut source: reg64, mut r: i32) -> () { @@ -7495,7 +7467,7 @@ pub unsafe extern "C" fn instr_F20F5D_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F20F5D_mem(mut addr: i32, mut r: i32) -> () { - instr_F20F5D(safe_read64s(addr), r); + instr_F20F5D(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_F30F5D(mut source: f32, mut r: i32) -> () { @@ -7510,7 +7482,7 @@ pub unsafe extern "C" fn instr_F30F5D_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F30F5D_mem(mut addr: i32, mut r: i32) -> () { - instr_F30F5D(fpu_load_m32(addr) as f32, r); + instr_F30F5D(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] pub unsafe extern "C" fn instr_0F5E(mut source: reg128, mut r: i32) -> () { @@ -7532,7 +7504,7 @@ pub unsafe extern "C" fn instr_0F5E_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F5E_mem(mut addr: i32, mut r: i32) -> () { - instr_0F5E(safe_read128s(addr), r); + instr_0F5E(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F5E(mut source: reg128, mut r: i32) -> () { @@ -7552,7 +7524,7 @@ pub unsafe extern "C" fn instr_660F5E_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F5E_mem(mut addr: i32, mut r: i32) -> () { - instr_660F5E(safe_read128s(addr), r); + instr_660F5E(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_F20F5E(mut source: reg64, mut r: i32) -> () { @@ -7569,7 +7541,7 @@ pub unsafe extern "C" fn instr_F20F5E_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F20F5E_mem(mut addr: i32, mut r: i32) -> () { - instr_F20F5E(safe_read64s(addr), r); + instr_F20F5E(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_F30F5E(mut source: f32, mut r: i32) -> () { @@ -7584,7 +7556,7 @@ pub unsafe extern "C" fn instr_F30F5E_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F30F5E_mem(mut addr: i32, mut r: i32) -> () { - instr_F30F5E(fpu_load_m32(addr) as f32, r); + instr_F30F5E(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] pub unsafe extern "C" fn instr_0F5F(mut source: reg128, mut r: i32) -> () { @@ -7618,7 +7590,7 @@ pub unsafe extern "C" fn instr_0F5F_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_0F5F_mem(mut addr: i32, mut r: i32) -> () { - instr_0F5F(safe_read128s(addr), r); + instr_0F5F(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_660F5F(mut source: reg128, mut r: i32) -> () { @@ -7638,7 +7610,7 @@ pub unsafe extern "C" fn instr_660F5F_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_660F5F_mem(mut addr: i32, mut r: i32) -> () { - instr_660F5F(safe_read128s(addr), r); + instr_660F5F(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_F20F5F(mut source: reg64, mut r: i32) -> () { @@ -7655,7 +7627,7 @@ pub unsafe extern "C" fn instr_F20F5F_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F20F5F_mem(mut addr: i32, mut r: i32) -> () { - instr_F20F5F(safe_read64s(addr), r); + instr_F20F5F(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe extern "C" fn instr_F30F5F(mut source: f32, mut r: i32) -> () { @@ -7670,7 +7642,7 @@ pub unsafe extern "C" fn instr_F30F5F_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_F30F5F_mem(mut addr: i32, mut r: i32) -> () { - instr_F30F5F(fpu_load_m32(addr) as f32, r); + instr_F30F5F(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] pub unsafe extern "C" fn instr_0FC2(mut source: reg128, mut r: i32, mut imm8: i32) -> () { @@ -7732,7 +7704,7 @@ pub unsafe extern "C" fn instr_0FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) } #[no_mangle] pub unsafe extern "C" fn instr_0FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { - instr_0FC2(safe_read128s(addr), r, imm); + instr_0FC2(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] pub unsafe extern "C" fn instr_660FC2(mut source: reg128, mut r: i32, mut imm8: i32) -> () { @@ -7762,7 +7734,7 @@ pub unsafe extern "C" fn instr_660FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32 } #[no_mangle] pub unsafe extern "C" fn instr_660FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { - instr_660FC2(safe_read128s(addr), r, imm); + instr_660FC2(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] pub unsafe extern "C" fn instr_F20FC2(mut source: reg64, mut r: i32, mut imm8: i32) -> () { @@ -7786,7 +7758,7 @@ pub unsafe extern "C" fn instr_F20FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32 } #[no_mangle] pub unsafe extern "C" fn instr_F20FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { - instr_F20FC2(safe_read64s(addr), r, imm); + instr_F20FC2(return_on_pagefault!(safe_read64s(addr)), r, imm); } #[no_mangle] pub unsafe extern "C" fn instr_F30FC2(mut source: f32, mut r: i32, mut imm8: i32) -> () { @@ -7806,5 +7778,5 @@ pub unsafe extern "C" fn instr_F30FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32 } #[no_mangle] pub unsafe extern "C" fn instr_F30FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { - instr_F30FC2(fpu_load_m32(addr) as f32, r, imm); + instr_F30FC2(return_on_pagefault!(fpu_load_m32(addr)) as f32, r, imm); } diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index 517b4ca1..9d4459a9 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -1,7 +1,15 @@ -#![allow -( dead_code , mutable_transmutes , non_camel_case_types , non_snake_case , -non_upper_case_globals , unused_mut )] -#![feature ( extern_types , libc )] +#![allow( + dead_code, + mutable_transmutes, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_mut +)] +#![feature(extern_types, libc)] + +use cpu2::cpu::*; +use cpu2::fpu::fpu_load_m80; extern "C" { @@ -343,8 +351,6 @@ extern "C" { #[no_mangle] static FPU_STACK_TOP: i32; #[no_mangle] - fn fpu_load_m80(addr: u32) -> f64; - #[no_mangle] fn fpu_load_status_word() -> i32; #[no_mangle] fn fpu_set_status_word(sw: i32) -> (); @@ -1190,28 +1196,28 @@ pub unsafe extern "C" fn pusha16() -> () { let mut temp: u16 = *reg16.offset(SP as isize); c_comment!(("make sure we don\'t get a pagefault after having")); c_comment!(("pushed several registers already")); - writable_or_pagefault(get_stack_pointer(-16i32), 16i32); - push16(*reg16.offset(AX as isize) as i32); - push16(*reg16.offset(CX as isize) as i32); - push16(*reg16.offset(DX as isize) as i32); - push16(*reg16.offset(BX as isize) as i32); - push16(temp as i32); - push16(*reg16.offset(BP as isize) as i32); - push16(*reg16.offset(SI as isize) as i32); - push16(*reg16.offset(DI as isize) as i32); + return_on_pagefault!(writable_or_pagefault(get_stack_pointer(-16i32), 16i32)); + push16(*reg16.offset(AX as isize) as i32).unwrap(); + push16(*reg16.offset(CX as isize) as i32).unwrap(); + push16(*reg16.offset(DX as isize) as i32).unwrap(); + push16(*reg16.offset(BX as isize) as i32).unwrap(); + push16(temp as i32).unwrap(); + push16(*reg16.offset(BP as isize) as i32).unwrap(); + push16(*reg16.offset(SI as isize) as i32).unwrap(); + push16(*reg16.offset(DI as isize) as i32).unwrap(); } #[no_mangle] pub unsafe extern "C" fn pusha32() -> () { let mut temp: i32 = *reg32s.offset(ESP as isize); - writable_or_pagefault(get_stack_pointer(-32i32), 32i32); - push32(*reg32s.offset(EAX as isize)); - push32(*reg32s.offset(ECX as isize)); - push32(*reg32s.offset(EDX as isize)); - push32(*reg32s.offset(EBX as isize)); - push32(temp); - push32(*reg32s.offset(EBP as isize)); - push32(*reg32s.offset(ESI as isize)); - push32(*reg32s.offset(EDI as isize)); + return_on_pagefault!(writable_or_pagefault(get_stack_pointer(-32i32), 32i32)); + push32(*reg32s.offset(EAX as isize)).unwrap(); + push32(*reg32s.offset(ECX as isize)).unwrap(); + push32(*reg32s.offset(EDX as isize)).unwrap(); + push32(*reg32s.offset(EBX as isize)).unwrap(); + push32(temp).unwrap(); + push32(*reg32s.offset(EBP as isize)).unwrap(); + push32(*reg32s.offset(ESI as isize)).unwrap(); + push32(*reg32s.offset(EDI as isize)).unwrap(); } #[no_mangle] pub unsafe extern "C" fn setcc_reg(mut condition: bool, mut r: i32) -> () { @@ -1219,27 +1225,30 @@ pub unsafe extern "C" fn setcc_reg(mut condition: bool, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn setcc_mem(mut condition: bool, mut addr: i32) -> () { - safe_write8(addr, if 0 != condition as i32 { 1i32 } else { 0i32 }); + return_on_pagefault!(safe_write8( + addr, + if 0 != condition as i32 { 1i32 } else { 0i32 } + )); } #[no_mangle] pub unsafe extern "C" fn fxsave(mut addr: u32) -> () { - writable_or_pagefault(addr as i32, 512i32); - safe_write16(addr.wrapping_add(0i32 as u32) as i32, *fpu_control_word); + return_on_pagefault!(writable_or_pagefault(addr as i32, 512i32)); + safe_write16(addr.wrapping_add(0i32 as u32) as i32, *fpu_control_word).unwrap(); safe_write16( addr.wrapping_add(2i32 as u32) as i32, fpu_load_status_word(), - ); + ).unwrap(); safe_write8( addr.wrapping_add(4i32 as u32) as i32, !*fpu_stack_empty & 255i32, - ); - safe_write16(addr.wrapping_add(6i32 as u32) as i32, *fpu_opcode); - safe_write32(addr.wrapping_add(8i32 as u32) as i32, *fpu_ip); - safe_write16(addr.wrapping_add(12i32 as u32) as i32, *fpu_ip_selector); - safe_write32(addr.wrapping_add(16i32 as u32) as i32, *fpu_dp); - safe_write16(addr.wrapping_add(20i32 as u32) as i32, *fpu_dp_selector); - safe_write32(addr.wrapping_add(24i32 as u32) as i32, *mxcsr); - safe_write32(addr.wrapping_add(28i32 as u32) as i32, MXCSR_MASK); + ).unwrap(); + safe_write16(addr.wrapping_add(6i32 as u32) as i32, *fpu_opcode).unwrap(); + safe_write32(addr.wrapping_add(8i32 as u32) as i32, *fpu_ip).unwrap(); + safe_write16(addr.wrapping_add(12i32 as u32) as i32, *fpu_ip_selector).unwrap(); + safe_write32(addr.wrapping_add(16i32 as u32) as i32, *fpu_dp).unwrap(); + safe_write16(addr.wrapping_add(20i32 as u32) as i32, *fpu_dp_selector).unwrap(); + safe_write32(addr.wrapping_add(24i32 as u32) as i32, *mxcsr).unwrap(); + safe_write32(addr.wrapping_add(28i32 as u32) as i32, MXCSR_MASK).unwrap(); let mut i: i32 = 0i32; while i < 8i32 { fpu_store_m80( @@ -1258,29 +1267,32 @@ pub unsafe extern "C" fn fxsave(mut addr: u32) -> () { addr.wrapping_add(160i32 as u32) .wrapping_add((i_0 << 4i32) as u32) as i32, *reg_xmm.offset(i_0 as isize), - ); + ).unwrap(); i_0 += 1 } } #[no_mangle] pub unsafe extern "C" fn fxrstor(mut addr: u32) -> () { - translate_address_read(addr as i32); - translate_address_read(addr.wrapping_add(511i32 as u32) as i32); - let mut new_mxcsr: i32 = safe_read32s(addr.wrapping_add(24i32 as u32) as i32); + // TODO: Add readable_or_pagefault + return_on_pagefault!(translate_address_read(addr as i32)); + return_on_pagefault!(translate_address_read( + addr.wrapping_add(511i32 as u32) as i32 + )); + let mut new_mxcsr: i32 = safe_read32s(addr.wrapping_add(24i32 as u32) as i32).unwrap(); if 0 != new_mxcsr & !MXCSR_MASK { dbg_log_c!(("#gp Invalid mxcsr bits")); trigger_gp_non_raising(0i32); return; } else { - *fpu_control_word = safe_read16(addr.wrapping_add(0i32 as u32) as i32); - fpu_set_status_word(safe_read16(addr.wrapping_add(2i32 as u32) as i32)); - *fpu_stack_empty = !safe_read8(addr.wrapping_add(4i32 as u32) as i32) & 255i32; - *fpu_opcode = safe_read16(addr.wrapping_add(6i32 as u32) as i32); - *fpu_ip = safe_read32s(addr.wrapping_add(8i32 as u32) as i32); - *fpu_ip = safe_read16(addr.wrapping_add(12i32 as u32) as i32); - *fpu_dp = safe_read32s(addr.wrapping_add(16i32 as u32) as i32); - *fpu_dp_selector = safe_read16(addr.wrapping_add(20i32 as u32) as i32); + *fpu_control_word = safe_read16(addr.wrapping_add(0i32 as u32) as i32).unwrap(); + fpu_set_status_word(safe_read16(addr.wrapping_add(2i32 as u32) as i32).unwrap()); + *fpu_stack_empty = !safe_read8(addr.wrapping_add(4i32 as u32) as i32).unwrap() & 255i32; + *fpu_opcode = safe_read16(addr.wrapping_add(6i32 as u32) as i32).unwrap(); + *fpu_ip = safe_read32s(addr.wrapping_add(8i32 as u32) as i32).unwrap(); + *fpu_ip = safe_read16(addr.wrapping_add(12i32 as u32) as i32).unwrap(); + *fpu_dp = safe_read32s(addr.wrapping_add(16i32 as u32) as i32).unwrap(); + *fpu_dp_selector = safe_read16(addr.wrapping_add(20i32 as u32) as i32).unwrap(); *mxcsr = new_mxcsr; let mut i: i32 = 0i32; while i < 8i32 { @@ -1288,7 +1300,7 @@ pub unsafe extern "C" fn fxrstor(mut addr: u32) -> () { fpu_load_m80( addr.wrapping_add(32i32 as u32) .wrapping_add((i << 4i32) as u32), - ); + ).unwrap(); i += 1 } let mut i_0: i32 = 0i32; @@ -1297,22 +1309,22 @@ pub unsafe extern "C" fn fxrstor(mut addr: u32) -> () { addr.wrapping_add(160i32 as u32) .wrapping_add((i_0 << 4i32) as u32) .wrapping_add(0i32 as u32) as i32, - ) as u32; + ).unwrap() as u32; (*reg_xmm.offset(i_0 as isize)).u32_0[1usize] = safe_read32s( addr.wrapping_add(160i32 as u32) .wrapping_add((i_0 << 4i32) as u32) .wrapping_add(4i32 as u32) as i32, - ) as u32; + ).unwrap() as u32; (*reg_xmm.offset(i_0 as isize)).u32_0[2usize] = safe_read32s( addr.wrapping_add(160i32 as u32) .wrapping_add((i_0 << 4i32) as u32) .wrapping_add(8i32 as u32) as i32, - ) as u32; + ).unwrap() as u32; (*reg_xmm.offset(i_0 as isize)).u32_0[3usize] = safe_read32s( addr.wrapping_add(160i32 as u32) .wrapping_add((i_0 << 4i32) as u32) .wrapping_add(12i32 as u32) as i32, - ) as u32; + ).unwrap() as u32; i_0 += 1 } return; diff --git a/src/rust/cpu2/sse_instr.rs b/src/rust/cpu2/sse_instr.rs index abdfca14..1a3686c5 100644 --- a/src/rust/cpu2/sse_instr.rs +++ b/src/rust/cpu2/sse_instr.rs @@ -1,7 +1,14 @@ -#![allow -( dead_code , mutable_transmutes , non_camel_case_types , non_snake_case , -non_upper_case_globals , unused_mut )] -#![feature ( extern_types , libc )] +#![allow( + dead_code, + mutable_transmutes, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_mut +)] +#![feature(extern_types, libc)] + +use cpu2::cpu::*; extern "C" { @@ -307,12 +314,6 @@ extern "C" { #[no_mangle] static CPU_EXCEPTION_VE: i32; #[no_mangle] - fn safe_read64s(addr: i32) -> reg64; - #[no_mangle] - fn safe_write64(addr: i32, value: i64) -> (); - #[no_mangle] - fn safe_write128(addr: i32, value: reg128) -> (); - #[no_mangle] fn read_mmx64s(r: i32) -> reg64; #[no_mangle] fn write_mmx64(r: i32, low: i32, high: i32) -> (); @@ -328,35 +329,6 @@ extern "C" { fn write_xmm_reg128(r: i32, data: reg128) -> (); } -#[derive(Copy, Clone)] -#[repr(C)] -pub union reg64 { - i8_0: [i8; 8], - i16_0: [i16; 4], - i32_0: [i32; 2], - i64_0: [i64; 1], - u8_0: [u8; 8], - u16_0: [u16; 4], - u32_0: [u32; 2], - u64_0: [u64; 1], - f32_0: [f32; 2], - f64_0: [f64; 1], -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union reg128 { - i8_0: [i8; 16], - i16_0: [i16; 8], - i32_0: [i32; 4], - i64_0: [i64; 2], - u8_0: [u8; 16], - u16_0: [u16; 8], - u32_0: [u32; 4], - u64_0: [u64; 2], - f32_0: [f32; 4], - f64_0: [f64; 2], -} - #[derive(Copy, Clone)] #[repr(C)] pub union unnamed { @@ -744,13 +716,13 @@ unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { pub unsafe extern "C" fn mov_r_m64(mut addr: i32, mut r: i32) -> () { c_comment!(("mov* m64, mm")); let mut data: reg64 = read_mmx64s(r); - safe_write64(addr, data.u64_0[0usize] as i64); + return_on_pagefault!(safe_write64(addr, data.u64_0[0usize] as i64)); } #[no_mangle] pub unsafe extern "C" fn movl_r128_m64(mut addr: i32, mut r: i32) -> () { c_comment!(("mov* m64, xmm")); let mut data: reg64 = read_xmm64s(r); - safe_write64(addr, data.u64_0[0usize] as i64); + return_on_pagefault!(safe_write64(addr, data.u64_0[0usize] as i64)); } #[no_mangle] pub unsafe extern "C" fn mov_r_r128(mut r1: i32, mut r2: i32) -> () { @@ -762,7 +734,7 @@ pub unsafe extern "C" fn mov_r_r128(mut r1: i32, mut r2: i32) -> () { pub unsafe extern "C" fn mov_r_m128(mut addr: i32, mut r: i32) -> () { c_comment!(("mov* m128, xmm")); let mut data: reg128 = read_xmm128s(r); - safe_write128(addr, data); + return_on_pagefault!(safe_write128(addr, data)); } #[no_mangle] pub unsafe extern "C" fn mov_rm_r128(mut source: reg128, mut r: i32) -> () { @@ -772,7 +744,7 @@ pub unsafe extern "C" fn mov_rm_r128(mut source: reg128, mut r: i32) -> () { #[no_mangle] pub unsafe extern "C" fn movh_m64_r128(mut addr: i32, mut r: i32) -> () { c_comment!(("movhp* xmm, m64")); - let mut data: reg64 = safe_read64s(addr); + let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); let mut orig: reg128 = read_xmm128s(r); write_xmm128( r, @@ -786,7 +758,7 @@ pub unsafe extern "C" fn movh_m64_r128(mut addr: i32, mut r: i32) -> () { pub unsafe extern "C" fn movh_r128_m64(mut addr: i32, mut r: i32) -> () { c_comment!(("movhp* m64, xmm")); let mut data: reg128 = read_xmm128s(r); - safe_write64(addr, data.u64_0[1usize] as i64); + return_on_pagefault!(safe_write64(addr, data.u64_0[1usize] as i64)); } #[no_mangle] pub unsafe extern "C" fn pand_r128(mut source: reg128, mut r: i32) -> () { diff --git a/src/rust/cpu2/string.rs b/src/rust/cpu2/string.rs index 846aa17d..16eb36c6 100644 --- a/src/rust/cpu2/string.rs +++ b/src/rust/cpu2/string.rs @@ -1,7 +1,14 @@ -#![allow -( dead_code , mutable_transmutes , non_camel_case_types , non_snake_case , -non_upper_case_globals , unused_mut )] -#![feature ( extern_types , libc )] +#![allow( + dead_code, + mutable_transmutes, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_mut +)] +#![feature(extern_types, libc)] + +use cpu2::cpu::*; extern "C" { @@ -311,28 +318,10 @@ extern "C" { #[no_mangle] static CPU_EXCEPTION_VE: i32; #[no_mangle] - fn translate_address_read(address: i32) -> u32; - #[no_mangle] - fn translate_address_write(address: i32) -> u32; - #[no_mangle] - fn writable_or_pagefault(addr: i32, size: i32) -> (); - #[no_mangle] fn get_seg(segment: i32) -> i32; #[no_mangle] fn get_seg_prefix(default_segment: i32) -> i32; #[no_mangle] - fn safe_read8(addr: i32) -> i32; - #[no_mangle] - fn safe_read16(addr: i32) -> i32; - #[no_mangle] - fn safe_read32s(address: i32) -> i32; - #[no_mangle] - fn safe_write8(addr: i32, value: i32) -> (); - #[no_mangle] - fn safe_write16(addr: i32, value: i32) -> (); - #[no_mangle] - fn safe_write32(address: i32, value: i32) -> (); - #[no_mangle] fn get_reg_asize(reg: i32) -> i32; #[no_mangle] fn set_ecx_asize(value: i32) -> (); @@ -942,8 +931,8 @@ pub unsafe extern "C" fn movsb_rep() -> () { let mut cont: i32 = 0i32; let mut start_count: i32 = count; let mut cycle_counter: i32 = string_get_cycle_count2(size, src, dest); - let mut phys_src: i32 = translate_address_read(src) as i32; - let mut phys_dest: i32 = translate_address_write(dest) as i32; + let mut phys_src: i32 = return_on_pagefault!(translate_address_read(src)) as i32; + let mut phys_dest: i32 = return_on_pagefault!(translate_address_write(dest)) as i32; loop { write8(phys_dest as u32, read8(phys_src as u32)); phys_dest += size; @@ -979,7 +968,7 @@ pub unsafe extern "C" fn movsb_no_rep() -> () { else { 1i32 }; - safe_write8(dest, safe_read8(src)); + return_on_pagefault!(safe_write8(dest, return_on_pagefault!(safe_read8(src)))); add_reg_asize(EDI, size); add_reg_asize(ESI, size); } @@ -1004,8 +993,10 @@ pub unsafe extern "C" fn movsw_rep() -> () { let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 1i32 && 0 == src & 1i32 { let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; - let mut phys_src: i32 = (translate_address_read(src) >> 1i32) as i32; - let mut phys_dest: i32 = (translate_address_write(dest) >> 1i32) as i32; + let mut phys_src: i32 = + (return_on_pagefault!(translate_address_read(src)) >> 1i32) as i32; + let mut phys_dest: i32 = + (return_on_pagefault!(translate_address_write(dest)) >> 1i32) as i32; cycle_counter = string_get_cycle_count2(size, src, dest); loop { write_aligned16(phys_dest as u32, read_aligned16(phys_src as u32) as u32); @@ -1029,7 +1020,7 @@ pub unsafe extern "C" fn movsw_rep() -> () { } else { loop { - safe_write16(dest, safe_read16(src)); + return_on_pagefault!(safe_write16(dest, return_on_pagefault!(safe_read16(src)))); dest += size; add_reg_asize(EDI, size); src += size; @@ -1061,7 +1052,7 @@ pub unsafe extern "C" fn movsw_no_rep() -> () { else { 2i32 }; - safe_write16(dest, safe_read16(src)); + return_on_pagefault!(safe_write16(dest, return_on_pagefault!(safe_read16(src)))); add_reg_asize(EDI, size); add_reg_asize(ESI, size); } @@ -1086,8 +1077,10 @@ pub unsafe extern "C" fn movsd_rep() -> () { let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 3i32 && 0 == src & 3i32 { let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; - let mut phys_src: i32 = (translate_address_read(src) >> 2i32) as i32; - let mut phys_dest: i32 = (translate_address_write(dest) >> 2i32) as i32; + let mut phys_src: i32 = + (return_on_pagefault!(translate_address_read(src)) >> 2i32) as i32; + let mut phys_dest: i32 = + (return_on_pagefault!(translate_address_write(dest)) >> 2i32) as i32; cycle_counter = string_get_cycle_count2(size, src, dest); loop { write_aligned32(phys_dest as u32, read_aligned32(phys_src as u32)); @@ -1111,7 +1104,7 @@ pub unsafe extern "C" fn movsd_rep() -> () { } else { loop { - safe_write32(dest, safe_read32s(src)); + return_on_pagefault!(safe_write32(dest, return_on_pagefault!(safe_read32s(src)))); dest += size; add_reg_asize(EDI, size); src += size; @@ -1141,7 +1134,7 @@ pub unsafe extern "C" fn movsd_no_rep() -> () { else { 4i32 }; - safe_write32(dest, safe_read32s(src)); + return_on_pagefault!(safe_write32(dest, return_on_pagefault!(safe_read32s(src)))); add_reg_asize(EDI, size); add_reg_asize(ESI, size); } @@ -1166,8 +1159,8 @@ pub unsafe extern "C" fn cmpsb_rep(mut prefix_flag: i32) -> () { let mut start_count: i32 = count; let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; let mut cycle_counter: i32 = string_get_cycle_count2(size, src, dest); - let mut phys_src: i32 = translate_address_read(src) as i32; - let mut phys_dest: i32 = translate_address_read(dest) as i32; + let mut phys_src: i32 = return_on_pagefault!(translate_address_read(src)) as i32; + let mut phys_dest: i32 = return_on_pagefault!(translate_address_read(dest)) as i32; loop { data_dest = read8(phys_dest as u32); data_src = read8(phys_src as u32); @@ -1207,8 +1200,8 @@ pub unsafe extern "C" fn cmpsb_no_rep() -> () { else { 1i32 }; - data_src = safe_read8(src); - data_dest = safe_read8(dest); + data_src = return_on_pagefault!(safe_read8(src)); + data_dest = return_on_pagefault!(safe_read8(dest)); add_reg_asize(EDI, size); add_reg_asize(ESI, size); cmp8(data_src, data_dest); @@ -1237,8 +1230,10 @@ pub unsafe extern "C" fn cmpsw_rep(mut prefix_flag: i32) -> () { let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 1i32 && 0 == src & 1i32 { let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; - let mut phys_src: i32 = (translate_address_read(src) >> 1i32) as i32; - let mut phys_dest: i32 = (translate_address_read(dest) >> 1i32) as i32; + let mut phys_src: i32 = + (return_on_pagefault!(translate_address_read(src)) >> 1i32) as i32; + let mut phys_dest: i32 = + (return_on_pagefault!(translate_address_read(dest)) >> 1i32) as i32; cycle_counter = string_get_cycle_count2(size, src, dest); loop { data_dest = read_aligned16(phys_dest as u32); @@ -1263,8 +1258,8 @@ pub unsafe extern "C" fn cmpsw_rep(mut prefix_flag: i32) -> () { } else { loop { - data_dest = safe_read16(dest); - data_src = safe_read16(src); + data_dest = return_on_pagefault!(safe_read16(dest)); + data_src = return_on_pagefault!(safe_read16(src)); dest += size; add_reg_asize(EDI, size); src += size; @@ -1298,8 +1293,8 @@ pub unsafe extern "C" fn cmpsw_no_rep() -> () { else { 2i32 }; - data_dest = safe_read16(dest); - data_src = safe_read16(src); + data_dest = return_on_pagefault!(safe_read16(dest)); + data_src = return_on_pagefault!(safe_read16(src)); add_reg_asize(EDI, size); add_reg_asize(ESI, size); cmp16(data_src, data_dest); @@ -1328,8 +1323,10 @@ pub unsafe extern "C" fn cmpsd_rep(mut prefix_flag: i32) -> () { let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 3i32 && 0 == src & 3i32 { let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; - let mut phys_src: i32 = (translate_address_read(src) >> 2i32) as i32; - let mut phys_dest: i32 = (translate_address_read(dest) >> 2i32) as i32; + let mut phys_src: i32 = + (return_on_pagefault!(translate_address_read(src)) >> 2i32) as i32; + let mut phys_dest: i32 = + (return_on_pagefault!(translate_address_read(dest)) >> 2i32) as i32; cycle_counter = string_get_cycle_count2(size, src, dest); loop { data_dest = read_aligned32(phys_dest as u32); @@ -1354,8 +1351,8 @@ pub unsafe extern "C" fn cmpsd_rep(mut prefix_flag: i32) -> () { } else { loop { - data_dest = safe_read32s(dest); - data_src = safe_read32s(src); + data_dest = return_on_pagefault!(safe_read32s(dest)); + data_src = return_on_pagefault!(safe_read32s(src)); dest += size; add_reg_asize(EDI, size); src += size; @@ -1389,8 +1386,8 @@ pub unsafe extern "C" fn cmpsd_no_rep() -> () { else { 4i32 }; - data_dest = safe_read32s(dest); - data_src = safe_read32s(src); + data_dest = return_on_pagefault!(safe_read32s(dest)); + data_src = return_on_pagefault!(safe_read32s(src)); add_reg_asize(EDI, size); add_reg_asize(ESI, size); cmp32(data_src, data_dest); @@ -1413,7 +1410,7 @@ pub unsafe extern "C" fn stosb_rep() -> () { let mut cont: i32 = 0i32; let mut start_count: i32 = count; let mut cycle_counter: i32 = string_get_cycle_count(size, dest); - let mut phys_dest: i32 = translate_address_write(dest) as i32; + let mut phys_dest: i32 = return_on_pagefault!(translate_address_write(dest)) as i32; loop { write8(phys_dest as u32, data); phys_dest += size; @@ -1447,7 +1444,7 @@ pub unsafe extern "C" fn stosb_no_rep() -> () { else { 1i32 }; - safe_write8(dest, data); + return_on_pagefault!(safe_write8(dest, data)); add_reg_asize(EDI, size); } #[no_mangle] @@ -1471,7 +1468,8 @@ pub unsafe extern "C" fn stosw_rep() -> () { let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 1i32 { let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; - let mut phys_dest: i32 = (translate_address_write(dest) >> 1i32) as i32; + let mut phys_dest: i32 = + (return_on_pagefault!(translate_address_write(dest)) >> 1i32) as i32; cycle_counter = string_get_cycle_count(size, dest); loop { write_aligned16(phys_dest as u32, data as u32); @@ -1493,7 +1491,7 @@ pub unsafe extern "C" fn stosw_rep() -> () { } else { loop { - safe_write16(dest, data); + return_on_pagefault!(safe_write16(dest, data)); dest += size; add_reg_asize(EDI, size); cont = (decr_ecx_asize() != 0i32) as i32; @@ -1521,7 +1519,7 @@ pub unsafe extern "C" fn stosw_no_rep() -> () { else { 2i32 }; - safe_write16(dest, data); + return_on_pagefault!(safe_write16(dest, data)); add_reg_asize(EDI, size); } #[no_mangle] @@ -1545,7 +1543,8 @@ pub unsafe extern "C" fn stosd_rep() -> () { let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 3i32 { let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; - let mut phys_dest: i32 = (translate_address_write(dest) >> 2i32) as i32; + let mut phys_dest: i32 = + (return_on_pagefault!(translate_address_write(dest)) >> 2i32) as i32; cycle_counter = string_get_cycle_count(size, dest); loop { write_aligned32(phys_dest as u32, data); @@ -1567,7 +1566,7 @@ pub unsafe extern "C" fn stosd_rep() -> () { } else { loop { - safe_write32(dest, data); + return_on_pagefault!(safe_write32(dest, data)); dest += size; add_reg_asize(EDI, size); cont = (decr_ecx_asize() != 0i32) as i32; @@ -1595,7 +1594,7 @@ pub unsafe extern "C" fn stosd_no_rep() -> () { else { 4i32 }; - safe_write32(dest, data); + return_on_pagefault!(safe_write32(dest, data)); add_reg_asize(EDI, size); } #[no_mangle] @@ -1615,7 +1614,7 @@ pub unsafe extern "C" fn lodsb_rep() -> () { let mut cont: i32 = 0i32; let mut start_count: i32 = count; let mut cycle_counter: i32 = string_get_cycle_count(size, src); - let mut phys_src: i32 = translate_address_read(src) as i32; + let mut phys_src: i32 = return_on_pagefault!(translate_address_read(src)) as i32; loop { *reg8.offset(AL as isize) = read8(phys_src as u32) as u8; phys_src += size; @@ -1648,7 +1647,7 @@ pub unsafe extern "C" fn lodsb_no_rep() -> () { else { 1i32 }; - *reg8.offset(AL as isize) = safe_read8(src) as u8; + *reg8.offset(AL as isize) = return_on_pagefault!(safe_read8(src)) as u8; add_reg_asize(ESI, size); } #[no_mangle] @@ -1668,7 +1667,7 @@ pub unsafe extern "C" fn lodsw_rep() -> () { let mut cont: bool = 0 != 0i32; let mut cycle_counter: u32 = MAX_COUNT_PER_CYCLE as u32; loop { - *reg16.offset(AX as isize) = safe_read16(src) as u16; + *reg16.offset(AX as isize) = return_on_pagefault!(safe_read16(src)) as u16; src += size; add_reg_asize(ESI, size); cont = decr_ecx_asize() != 0i32; @@ -1694,7 +1693,7 @@ pub unsafe extern "C" fn lodsw_no_rep() -> () { else { 2i32 }; - *reg16.offset(AX as isize) = safe_read16(src) as u16; + *reg16.offset(AX as isize) = return_on_pagefault!(safe_read16(src)) as u16; add_reg_asize(ESI, size); } #[no_mangle] @@ -1714,7 +1713,7 @@ pub unsafe extern "C" fn lodsd_rep() -> () { let mut cont: i32 = 0i32; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; loop { - *reg32s.offset(EAX as isize) = safe_read32s(src); + *reg32s.offset(EAX as isize) = return_on_pagefault!(safe_read32s(src)); src += size; add_reg_asize(ESI, size); cont = (decr_ecx_asize() != 0i32) as i32; @@ -1740,7 +1739,7 @@ pub unsafe extern "C" fn lodsd_no_rep() -> () { else { 4i32 }; - *reg32s.offset(EAX as isize) = safe_read32s(src); + *reg32s.offset(EAX as isize) = return_on_pagefault!(safe_read32s(src)); add_reg_asize(ESI, size); } #[no_mangle] @@ -1763,7 +1762,7 @@ pub unsafe extern "C" fn scasb_rep(mut prefix_flag: i32) -> () { let mut start_count: i32 = count; let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; let mut cycle_counter: i32 = string_get_cycle_count(size, dest); - let mut phys_dest: i32 = translate_address_read(dest) as i32; + let mut phys_dest: i32 = return_on_pagefault!(translate_address_read(dest)) as i32; loop { data_dest = read8(phys_dest as u32); phys_dest += size; @@ -1799,7 +1798,7 @@ pub unsafe extern "C" fn scasb_no_rep() -> () { }; let mut data_dest: i32 = 0; let mut data_src: i32 = *reg8.offset(AL as isize) as i32; - data_dest = safe_read8(dest); + data_dest = return_on_pagefault!(safe_read8(dest)); add_reg_asize(EDI, size); cmp8(data_src, data_dest); } @@ -1826,7 +1825,8 @@ pub unsafe extern "C" fn scasw_rep(mut prefix_flag: i32) -> () { let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 1i32 { let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; - let mut phys_dest: i32 = (translate_address_read(dest) >> 1i32) as i32; + let mut phys_dest: i32 = + (return_on_pagefault!(translate_address_read(dest)) >> 1i32) as i32; cycle_counter = string_get_cycle_count(size, dest); loop { data_dest = read_aligned16(phys_dest as u32); @@ -1848,7 +1848,7 @@ pub unsafe extern "C" fn scasw_rep(mut prefix_flag: i32) -> () { } else { loop { - data_dest = safe_read16(dest); + data_dest = return_on_pagefault!(safe_read16(dest)); dest += size; add_reg_asize(EDI, size); cont = @@ -1879,7 +1879,7 @@ pub unsafe extern "C" fn scasw_no_rep() -> () { }; let mut data_dest: i32 = 0; let mut data_src: i32 = *reg16.offset(AL as isize) as i32; - data_dest = safe_read16(dest); + data_dest = return_on_pagefault!(safe_read16(dest)); add_reg_asize(EDI, size); cmp16(data_src, data_dest); } @@ -1906,7 +1906,8 @@ pub unsafe extern "C" fn scasd_rep(mut prefix_flag: i32) -> () { let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 3i32 { let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; - let mut phys_dest: i32 = (translate_address_read(dest) >> 2i32) as i32; + let mut phys_dest: i32 = + (return_on_pagefault!(translate_address_read(dest)) >> 2i32) as i32; cycle_counter = string_get_cycle_count(size, dest); loop { data_dest = read_aligned32(phys_dest as u32); @@ -1928,7 +1929,7 @@ pub unsafe extern "C" fn scasd_rep(mut prefix_flag: i32) -> () { } else { loop { - data_dest = safe_read32s(dest); + data_dest = return_on_pagefault!(safe_read32s(dest)); dest += size; add_reg_asize(EDI, size); cont = @@ -1959,7 +1960,7 @@ pub unsafe extern "C" fn scasd_no_rep() -> () { }; let mut data_dest: i32 = 0; let mut data_src: i32 = *reg32s.offset(EAX as isize); - data_dest = safe_read32s(dest); + data_dest = return_on_pagefault!(safe_read32s(dest)); add_reg_asize(EDI, size); cmp32(data_src, data_dest); } @@ -1985,7 +1986,7 @@ pub unsafe extern "C" fn insb_rep() -> () { let mut cont: i32 = 0i32; let mut start_count: i32 = count; let mut cycle_counter: i32 = string_get_cycle_count(size, dest); - let mut phys_dest: i32 = translate_address_write(dest) as i32; + let mut phys_dest: i32 = return_on_pagefault!(translate_address_write(dest)) as i32; loop { write8(phys_dest as u32, io_port_read8(port)); phys_dest += size; @@ -2025,8 +2026,8 @@ pub unsafe extern "C" fn insb_no_rep() -> () { else { 1i32 }; - writable_or_pagefault(dest, 1i32); - safe_write8(dest, io_port_read8(port)); + return_on_pagefault!(writable_or_pagefault(dest, 1i32)); + return_on_pagefault!(safe_write8(dest, io_port_read8(port))); add_reg_asize(EDI, size); return; }; @@ -2056,7 +2057,8 @@ pub unsafe extern "C" fn insw_rep() -> () { let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 1i32 { let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; - let mut phys_dest: i32 = (translate_address_write(dest) >> 1i32) as i32; + let mut phys_dest: i32 = + (return_on_pagefault!(translate_address_write(dest)) >> 1i32) as i32; cycle_counter = string_get_cycle_count(size, dest); loop { write_aligned16(phys_dest as u32, io_port_read16(port) as u32); @@ -2079,8 +2081,8 @@ pub unsafe extern "C" fn insw_rep() -> () { } else { loop { - writable_or_pagefault(dest, 2i32); - safe_write16(dest, io_port_read16(port)); + return_on_pagefault!(writable_or_pagefault(dest, 2i32)); + return_on_pagefault!(safe_write16(dest, io_port_read16(port))); dest += size; add_reg_asize(EDI, size); cont = (decr_ecx_asize() != 0i32) as i32; @@ -2113,8 +2115,8 @@ pub unsafe extern "C" fn insw_no_rep() -> () { else { 2i32 }; - writable_or_pagefault(dest, 2i32); - safe_write16(dest, io_port_read16(port)); + return_on_pagefault!(writable_or_pagefault(dest, 2i32)); + return_on_pagefault!(safe_write16(dest, io_port_read16(port))); add_reg_asize(EDI, size); return; }; @@ -2144,7 +2146,8 @@ pub unsafe extern "C" fn insd_rep() -> () { let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 3i32 { let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; - let mut phys_dest: i32 = (translate_address_write(dest) >> 2i32) as i32; + let mut phys_dest: i32 = + (return_on_pagefault!(translate_address_write(dest)) >> 2i32) as i32; cycle_counter = string_get_cycle_count(size, dest); loop { write_aligned32(phys_dest as u32, io_port_read32(port)); @@ -2167,8 +2170,8 @@ pub unsafe extern "C" fn insd_rep() -> () { } else { loop { - writable_or_pagefault(dest, 4i32); - safe_write32(dest, io_port_read32(port)); + return_on_pagefault!(writable_or_pagefault(dest, 4i32)); + return_on_pagefault!(safe_write32(dest, io_port_read32(port))); dest += size; add_reg_asize(EDI, size); cont = (decr_ecx_asize() != 0i32) as i32; @@ -2201,8 +2204,8 @@ pub unsafe extern "C" fn insd_no_rep() -> () { else { 4i32 }; - writable_or_pagefault(dest, 4i32); - safe_write32(dest, io_port_read32(port)); + return_on_pagefault!(writable_or_pagefault(dest, 4i32)); + return_on_pagefault!(safe_write32(dest, io_port_read32(port))); add_reg_asize(EDI, size); return; }; @@ -2229,7 +2232,7 @@ pub unsafe extern "C" fn outsb_rep() -> () { let mut cont: i32 = 0i32; let mut start_count: i32 = count; let mut cycle_counter: i32 = string_get_cycle_count(size, src); - let mut phys_src: i32 = translate_address_read(src) as i32; + let mut phys_src: i32 = return_on_pagefault!(translate_address_read(src)) as i32; loop { io_port_write8(port, read8(phys_src as u32)); phys_src += size; @@ -2269,7 +2272,7 @@ pub unsafe extern "C" fn outsb_no_rep() -> () { else { 1i32 }; - io_port_write8(port, safe_read8(src)); + io_port_write8(port, return_on_pagefault!(safe_read8(src))); add_reg_asize(ESI, size); return; }; @@ -2299,7 +2302,8 @@ pub unsafe extern "C" fn outsw_rep() -> () { let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == src & 1i32 { let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; - let mut phys_src: i32 = (translate_address_read(src) >> 1i32) as i32; + let mut phys_src: i32 = + (return_on_pagefault!(translate_address_read(src)) >> 1i32) as i32; cycle_counter = string_get_cycle_count(size, src); loop { io_port_write16(port, read_aligned16(phys_src as u32)); @@ -2322,7 +2326,7 @@ pub unsafe extern "C" fn outsw_rep() -> () { } else { loop { - io_port_write16(port, safe_read16(src)); + io_port_write16(port, return_on_pagefault!(safe_read16(src))); src += size; add_reg_asize(ESI, size); cont = (decr_ecx_asize() != 0i32) as i32; @@ -2355,7 +2359,7 @@ pub unsafe extern "C" fn outsw_no_rep() -> () { else { 2i32 }; - io_port_write16(port, safe_read16(src)); + io_port_write16(port, return_on_pagefault!(safe_read16(src))); add_reg_asize(ESI, size); return; }; @@ -2385,7 +2389,8 @@ pub unsafe extern "C" fn outsd_rep() -> () { let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == src & 3i32 { let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; - let mut phys_src: i32 = (translate_address_read(src) >> 2i32) as i32; + let mut phys_src: i32 = + (return_on_pagefault!(translate_address_read(src)) >> 2i32) as i32; cycle_counter = string_get_cycle_count(size, src); loop { io_port_write32(port, read_aligned32(phys_src as u32)); @@ -2408,7 +2413,7 @@ pub unsafe extern "C" fn outsd_rep() -> () { } else { loop { - io_port_write32(port, safe_read32s(src)); + io_port_write32(port, return_on_pagefault!(safe_read32s(src))); src += size; add_reg_asize(ESI, size); cont = (decr_ecx_asize() != 0i32) as i32; @@ -2441,7 +2446,7 @@ pub unsafe extern "C" fn outsd_no_rep() -> () { else { 4i32 }; - io_port_write32(port, safe_read32s(src)); + io_port_write32(port, return_on_pagefault!(safe_read32s(src))); add_reg_asize(ESI, size); return; }; From 2c47c85325107672b7bda8b373c4dfecd4aed705 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 15 Aug 2018 17:00:06 -0500 Subject: [PATCH 1191/2137] Fix format strings --- src/rust/cpu2/cpu.rs | 18 +++++----- src/rust/cpu2/fpu.rs | 6 ++-- src/rust/cpu2/instructions.rs | 56 ++++++++++++++++---------------- src/rust/cpu2/instructions_0f.rs | 44 ++++++++++++------------- src/rust/cpu2/misc_instr.rs | 2 +- 5 files changed, 64 insertions(+), 62 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 86f70292..3be494fa 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1613,7 +1613,7 @@ pub unsafe extern "C" fn trigger_pagefault( ) -> () { if 0 != 0i32 * 0i32 { dbg_log_c!( - ("page fault w=%d u=%d p=%d eip=%x cr2=%x"), + "page fault w=%d u=%d p=%d eip=%x cr2=%x", write as i32, user as i32, present as i32, @@ -1624,7 +1624,7 @@ pub unsafe extern "C" fn trigger_pagefault( } if DEBUG { if must_not_fault { - dbg_log_c!(("Unexpected page fault")); + dbg_log_c!("Unexpected page fault"); dbg_trace(); dbg_assert!(0 != 0i32); } @@ -1793,7 +1793,7 @@ pub unsafe extern "C" fn get_seg(mut segment: i32) -> i32 { if *protected_mode { if *segment_is_null.offset(segment as isize) { dbg_assert!(segment != CS && segment != SS); - dbg_log_c!(("#gp: Access null segment")); + dbg_log_c!("#gp: Access null segment"); assert!(false); trigger_gp(0i32); } @@ -1813,7 +1813,7 @@ pub unsafe extern "C" fn raise_exception_with_code( if DEBUG { if must_not_fault { dbg_log_c!( - ("Unexpected fault: 0x%x with code 0x%x"), + "Unexpected fault: 0x%x with code 0x%x", interrupt_nr, error_code ); @@ -1998,7 +1998,7 @@ pub static mut LOOP_COUNTER: i32 = unsafe { 20011i32 }; //pub unsafe extern "C" fn raise_exception(mut interrupt_nr: i32) -> () { // if DEBUG { // if must_not_fault { -// dbg_log_c!(("Unexpected fault: 0x%x"), interrupt_nr); +// dbg_log_c!("Unexpected fault: 0x%x", interrupt_nr); // dbg_trace(); // dbg_assert!(0 != 0i32); // } @@ -2026,7 +2026,7 @@ pub unsafe extern "C" fn trigger_de() -> () { pub unsafe extern "C" fn set_current_cpu_exception(mut n: i32) -> () { current_cpu_exception = n; } #[no_mangle] pub unsafe extern "C" fn trigger_ud() -> () { - dbg_log_c!(("#ud")); + dbg_log_c!("#ud"); dbg_trace(); if DEBUG { if cpu_exception_hook(CPU_EXCEPTION_UD) { @@ -2126,7 +2126,7 @@ pub unsafe extern "C" fn safe_read8(mut addr: i32) -> Result { pub unsafe extern "C" fn assert_no_cpu_exception() -> () { return; if current_cpu_exception != -1i32 { - dbg_log_c!(("Expected no cpu exception, got %d"), current_cpu_exception); + dbg_log_c!("Expected no cpu exception, got %d", current_cpu_exception); dbg_trace(); dbg_assert!(0 != 0i32); }; @@ -2208,6 +2208,7 @@ pub unsafe fn safe_read16_slow_jit(addr: i32) -> i32 { v }, Err(()) => { + dbg_log!("page fault"); *page_fault = true; -1 }, @@ -2222,6 +2223,7 @@ pub unsafe fn safe_read32s_slow_jit(addr: i32) -> i32 { v }, Err(()) => { + dbg_log!("page fault"); *page_fault = true; -1 }, @@ -2636,7 +2638,7 @@ pub unsafe extern "C" fn read_tsc() -> u64 { } else { dbg_log_c!( - ("XXX: Overshot tsc prev=%x:%x offset=%x:%x curr=%x:%x"), + "XXX: Overshot tsc prev=%x:%x offset=%x:%x curr=%x:%x", (rdtsc_last_value >> 32i32) as u32 as i32, rdtsc_last_value as u32 as i32, (rdtsc_imprecision_offset >> 32i32) as u32 as i32, diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 00a6980e..24917671 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -1006,7 +1006,7 @@ pub unsafe extern "C" fn fpu_load_m80(mut addr: u32) -> Result { else { c_comment!(("TODO: NaN, Infinity")); if 0 != 0i32 * 0i32 { - dbg_log_c!(("Load m80 TODO")); + dbg_log_c!("Load m80 TODO"); } let mut double_int_view: f64_int = f64_int { u8_0: [0; 8] }; double_int_view.u8_0[7usize] = (127i32 | sign << 7i32) as u8; @@ -1202,7 +1202,7 @@ pub unsafe extern "C" fn fpu_fldenv(mut addr: i32) -> () { *fpu_dp_selector.offset(0isize) = safe_read16(addr + 24i32).unwrap() } else { - dbg_log_c!(("fldenv16")); + dbg_log_c!("fldenv16"); fpu_unimpl(); }; } @@ -1359,7 +1359,7 @@ pub unsafe extern "C" fn fpu_fstenv(mut addr: i32) -> () { safe_write16(addr + 24i32, *fpu_dp_selector.offset(0isize)).unwrap(); } else { - dbg_log_c!(("fstenv16")); + dbg_log_c!("fstenv16"); fpu_unimpl(); }; } diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index a085cf50..705bfac8 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -2345,12 +2345,12 @@ pub unsafe extern "C" fn instr32_61() -> () { popa32(); } #[no_mangle] pub unsafe extern "C" fn instr_62_reg(mut r2: i32, mut r: i32) -> () { c_comment!(("bound")); - dbg_log_c!(("Unimplemented BOUND instruction")); + dbg_log_c!("Unimplemented BOUND instruction"); dbg_assert!(0 != 0i32); } #[no_mangle] pub unsafe extern "C" fn instr_62_mem(mut addr: i32, mut r: i32) -> () { - dbg_log_c!(("Unimplemented BOUND instruction")); + dbg_log_c!("Unimplemented BOUND instruction"); dbg_assert!(0 != 0i32); } #[no_mangle] @@ -2992,7 +2992,7 @@ pub unsafe extern "C" fn instr32_8B_reg(mut r1: i32, mut r: i32) -> () { #[no_mangle] pub unsafe extern "C" fn instr_8C_check_sreg(mut seg: i32) -> bool { if seg >= 6i32 { - dbg_log_c!(("mov sreg #ud")); + dbg_log_c!("mov sreg #ud"); trigger_ud(); return 0 != 0i32; } @@ -3026,7 +3026,7 @@ pub unsafe extern "C" fn instr32_8C_mem(mut addr: i32, mut seg: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_8D_reg(mut r: i32, mut r2: i32) -> () { - dbg_log_c!(("lea #ud")); + dbg_log_c!("lea #ud"); trigger_ud(); } #[no_mangle] @@ -3040,7 +3040,7 @@ pub unsafe extern "C" fn instr16_8D_mem(modrm_byte: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_8D_reg(mut r: i32, mut r2: i32) -> () { - dbg_log_c!(("lea #ud")); + dbg_log_c!("lea #ud"); trigger_ud(); } #[no_mangle] @@ -3061,7 +3061,7 @@ pub unsafe extern "C" fn instr_8E_helper(mut data: i32, mut mod_0: i32) -> () { } } else { - dbg_log_c!(("mov sreg #ud")); + dbg_log_c!("mov sreg #ud"); trigger_ud(); }; } @@ -3198,7 +3198,7 @@ pub unsafe extern "C" fn instr16_9C() -> () { c_comment!(("pushf")); if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { dbg_assert!(*protected_mode); - dbg_log_c!(("pushf #gp")); + dbg_log_c!("pushf #gp"); trigger_gp_non_raising(0i32); } else { @@ -3211,7 +3211,7 @@ pub unsafe extern "C" fn instr32_9C() -> () { if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { c_comment!(("trap to virtual 8086 monitor")); dbg_assert!(*protected_mode); - dbg_log_c!(("pushf #gp")); + dbg_log_c!("pushf #gp"); trigger_gp_non_raising(0i32); } else { @@ -3223,7 +3223,7 @@ pub unsafe extern "C" fn instr32_9C() -> () { pub unsafe extern "C" fn instr16_9D() -> () { c_comment!(("popf")); if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { - dbg_log_c!(("popf #gp")); + dbg_log_c!("popf #gp"); trigger_gp_non_raising(0i32); return; } @@ -3243,7 +3243,7 @@ pub unsafe extern "C" fn instr16_9D() -> () { pub unsafe extern "C" fn instr32_9D() -> () { c_comment!(("popf")); if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { - dbg_log_c!(("popf #gp")); + dbg_log_c!("popf #gp"); trigger_gp_non_raising(0i32); return; } @@ -3757,7 +3757,7 @@ pub unsafe extern "C" fn instr32_CB() -> () { pub unsafe extern "C" fn instr_CC() -> () { c_comment!(("INT3")); c_comment!(("TODO: inhibit iopl checks")); - dbg_log_c!(("INT3")); + dbg_log_c!("INT3"); call_interrupt_vector(3i32, 0 != 1i32, 0 != 0i32, 0i32); } #[no_mangle] @@ -3768,7 +3768,7 @@ pub unsafe extern "C" fn instr_CD(mut imm8: i32) -> () { #[no_mangle] pub unsafe extern "C" fn instr_CE() -> () { c_comment!(("INTO")); - dbg_log_c!(("INTO")); + dbg_log_c!("INTO"); if getof() { c_comment!(("TODO: inhibit iopl checks")); call_interrupt_vector(CPU_EXCEPTION_OF, 0 != 1i32, 0 != 0i32, 0i32); @@ -4499,7 +4499,7 @@ pub unsafe extern "C" fn instr32_EF() -> () { pub unsafe extern "C" fn instr_F0() -> () { c_comment!(("lock")); if 0 != 0i32 * 0i32 { - dbg_log_c!(("lock")); + dbg_log_c!("lock"); } c_comment!(("TODO")); c_comment!(("This triggers UD when used with")); @@ -4808,7 +4808,7 @@ pub unsafe extern "C" fn instr_FA() -> () { *flags &= !FLAG_VIF } else { - dbg_log_c!(("cli #gp")); + dbg_log_c!("cli #gp"); trigger_gp_non_raising(0i32); }; } @@ -4839,7 +4839,7 @@ pub unsafe extern "C" fn instr_FB() -> () { *flags |= FLAG_VIF } else { - dbg_log_c!(("sti #gp")); + dbg_log_c!("sti #gp"); trigger_gp_non_raising(0i32); }; } @@ -4911,7 +4911,7 @@ pub unsafe extern "C" fn instr16_FF_2_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_FF_3_reg(mut r: i32) -> () { - dbg_log_c!(("callf #ud")); + dbg_log_c!("callf #ud"); trigger_ud(); } #[no_mangle] @@ -4940,7 +4940,7 @@ pub unsafe extern "C" fn instr16_FF_4_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr16_FF_5_reg(mut r: i32) -> () { - dbg_log_c!(("jmpf #ud")); + dbg_log_c!("jmpf #ud"); trigger_ud(); } #[no_mangle] @@ -4999,7 +4999,7 @@ pub unsafe extern "C" fn instr32_FF_2_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_FF_3_reg(mut r: i32) -> () { - dbg_log_c!(("callf #ud")); + dbg_log_c!("callf #ud"); trigger_ud(); } #[no_mangle] @@ -5033,7 +5033,7 @@ pub unsafe extern "C" fn instr32_FF_4_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr32_FF_5_reg(mut r: i32) -> () { - dbg_log_c!(("jmpf #ud")); + dbg_log_c!("jmpf #ud"); trigger_ud(); } #[no_mangle] @@ -5299,7 +5299,7 @@ pub unsafe extern "C" fn instr_D9_0_reg(mut r: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_D9_1_mem(mut addr: i32) -> () { - dbg_log_c!(("d9/1")); + dbg_log_c!("d9/1"); trigger_ud(); } #[no_mangle] @@ -5316,7 +5316,7 @@ pub unsafe extern "C" fn instr_D9_2_reg(mut r: i32) -> () { pub unsafe extern "C" fn instr_D9_3_mem(mut addr: i32) -> () { fpu_fstm32p(addr); } #[no_mangle] pub unsafe extern "C" fn instr_D9_3_reg(mut r: i32) -> () { - dbg_log_c!(("fstp1")); + dbg_log_c!("fstp1"); trigger_ud(); } #[no_mangle] @@ -5340,7 +5340,7 @@ pub unsafe extern "C" fn instr_D9_4_reg(mut r: i32) -> () { fpu_fxam(st0); }, _ => { - dbg_log_c!(("%x"), r); + dbg_log_c!("%x", r); trigger_ud(); }, }; @@ -5373,7 +5373,7 @@ pub unsafe extern "C" fn instr_D9_5_reg(mut r: i32) -> () { fpu_push(0i32 as f64); }, 7 => { - dbg_log_c!(("d9/5/7")); + dbg_log_c!("d9/5/7"); trigger_ud(); }, _ => {}, @@ -5617,7 +5617,7 @@ pub unsafe extern "C" fn instr_DC_7_reg(mut r: i32) -> () { fpu_fdivr(r, fpu_get pub unsafe extern "C" fn instr_DD_0_mem(mut addr: i32) -> () { fpu_fldm64(addr); } #[no_mangle] pub unsafe extern "C" fn instr_DD_1_mem(mut addr: i32) -> () { - dbg_log_c!(("fisttp")); + dbg_log_c!("fisttp"); trigger_ud(); } #[no_mangle] @@ -5628,7 +5628,7 @@ pub unsafe extern "C" fn instr_DD_3_mem(mut addr: i32) -> () { fpu_fstm64p(addr) pub unsafe extern "C" fn instr_DD_4_mem(mut addr: i32) -> () { fpu_frstor(addr); } #[no_mangle] pub unsafe extern "C" fn instr_DD_5_mem(mut addr: i32) -> () { - dbg_log_c!(("dd/5")); + dbg_log_c!("dd/5"); trigger_ud(); } #[no_mangle] @@ -5729,7 +5729,7 @@ pub unsafe extern "C" fn instr_DF_0_mem(mut addr: i32) -> () { } #[no_mangle] pub unsafe extern "C" fn instr_DF_1_mem(mut addr: i32) -> () { - dbg_log_c!(("df/fisttp")); + dbg_log_c!("df/fisttp"); trigger_ud(); } #[no_mangle] @@ -5738,14 +5738,14 @@ pub unsafe extern "C" fn instr_DF_2_mem(mut addr: i32) -> () { fpu_fistm16(addr) pub unsafe extern "C" fn instr_DF_3_mem(mut addr: i32) -> () { fpu_fistm16p(addr); } #[no_mangle] pub unsafe extern "C" fn instr_DF_4_mem(mut addr: i32) -> () { - dbg_log_c!(("fbld")); + dbg_log_c!("fbld"); trigger_ud(); } #[no_mangle] pub unsafe extern "C" fn instr_DF_5_mem(mut addr: i32) -> () { fpu_fildm64(addr); } #[no_mangle] pub unsafe extern "C" fn instr_DF_6_mem(mut addr: i32) -> () { - dbg_log_c!(("fbstp")); + dbg_log_c!("fbstp"); trigger_ud(); } #[no_mangle] diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 5d199a60..c06c8207 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -1456,12 +1456,12 @@ pub unsafe extern "C" fn instr_0F05() -> () { undefined_instruction(); } pub unsafe extern "C" fn instr_0F06() -> () { c_comment!(("clts")); if 0 != *cpl.offset(0isize) { - dbg_log_c!(("clts #gp")); + dbg_log_c!("clts #gp"); trigger_gp_non_raising(0i32); } else { if 0 != 0i32 * 0i32 { - dbg_log_c!(("clts")); + dbg_log_c!("clts"); } let ref mut fresh0 = *cr.offset(0isize); *fresh0 &= !CR0_TS @@ -1477,7 +1477,7 @@ pub unsafe extern "C" fn instr_0F08() -> () { #[no_mangle] pub unsafe extern "C" fn instr_0F09() -> () { if 0 != *cpl.offset(0isize) { - dbg_log_c!(("wbinvd #gp")); + dbg_log_c!("wbinvd #gp"); trigger_gp_non_raising(0i32); } else { @@ -1847,7 +1847,7 @@ pub unsafe extern "C" fn instr_0F20(mut r: i32, mut creg: i32) -> () { write_reg32(r, *cr.offset(4isize)); }, _ => { - dbg_log_c!(("%d"), creg); + dbg_log_c!("%d", creg); undefined_instruction(); }, } @@ -1863,7 +1863,7 @@ pub unsafe extern "C" fn instr_0F21(mut r: i32, mut dreg_index: i32) -> () { else { if dreg_index == 4i32 || dreg_index == 5i32 { if 0 != *cr.offset(4isize) & CR4_DE { - dbg_log_c!(("#ud mov dreg 4/5 with cr4.DE set")); + dbg_log_c!("#ud mov dreg 4/5 with cr4.DE set"); trigger_ud(); return; } @@ -1875,7 +1875,7 @@ pub unsafe extern "C" fn instr_0F21(mut r: i32, mut dreg_index: i32) -> () { write_reg32(r, *dreg.offset(dreg_index as isize)); if 0 != 0i32 * 0i32 { dbg_log_c!( - ("read dr%d: %x"), + "read dr%d: %x", dreg_index, *dreg.offset(dreg_index as isize) ); @@ -1895,17 +1895,17 @@ pub unsafe extern "C" fn instr_0F22(mut r: i32, mut creg: i32) -> () { match creg { 0 => { if 0 != 0i32 * 0i32 { - dbg_log_c!(("cr0 <- %x"), data); + dbg_log_c!("cr0 <- %x", data); } set_cr0(data); }, 2 => { - dbg_log_c!(("cr2 <- %x"), data); + dbg_log_c!("cr2 <- %x", data); *cr.offset(2isize) = data }, 3 => { if 0 != 0i32 * 0i32 { - dbg_log_c!(("cr3 <- %x"), data); + dbg_log_c!("cr3 <- %x", data); } data &= !4071i32; dbg_assert!(data & 4095i32 == 0i32, ("TODO")); @@ -1913,7 +1913,7 @@ pub unsafe extern "C" fn instr_0F22(mut r: i32, mut creg: i32) -> () { clear_tlb(); }, 4 => { - dbg_log_c!(("cr4 <- %d"), *cr.offset(4isize)); + dbg_log_c!("cr4 <- %d", *cr.offset(4isize)); if 0 != data as u32 & ((1i32 << 11i32 | 1i32 << 12i32 @@ -1922,7 +1922,7 @@ pub unsafe extern "C" fn instr_0F22(mut r: i32, mut creg: i32) -> () { | 1i32 << 19i32) as u32 | 4290772992u32) { - dbg_log_c!(("trigger_gp: Invalid cr4 bit")); + dbg_log_c!("trigger_gp: Invalid cr4 bit"); trigger_gp_non_raising(0i32); return; } @@ -1937,7 +1937,7 @@ pub unsafe extern "C" fn instr_0F22(mut r: i32, mut creg: i32) -> () { } }, _ => { - dbg_log_c!(("%d"), creg); + dbg_log_c!("%d", creg); undefined_instruction(); }, } @@ -1953,7 +1953,7 @@ pub unsafe extern "C" fn instr_0F23(mut r: i32, mut dreg_index: i32) -> () { else { if dreg_index == 4i32 || dreg_index == 5i32 { if 0 != *cr.offset(4isize) & CR4_DE { - dbg_log_c!(("#ud mov dreg 4/5 with cr4.DE set")); + dbg_log_c!("#ud mov dreg 4/5 with cr4.DE set"); trigger_ud(); return; } @@ -1965,7 +1965,7 @@ pub unsafe extern "C" fn instr_0F23(mut r: i32, mut dreg_index: i32) -> () { *dreg.offset(dreg_index as isize) = read_reg32(r); if 0 != 0i32 * 0i32 { dbg_log_c!( - ("write dr%d: %x"), + "write dr%d: %x", dreg_index, *dreg.offset(dreg_index as isize) ); @@ -2126,7 +2126,7 @@ pub unsafe extern "C" fn instr_0F30() -> () { let mut low: i32 = *reg32s.offset(EAX as isize); let mut high: i32 = *reg32s.offset(EDX as isize); if index != IA32_SYSENTER_ESP { - dbg_log_c!(("wrmsr ecx=%x data=%x:%x"), index, high, low); + dbg_log_c!("wrmsr ecx=%x data=%x:%x", index, high, low); } if index == IA32_SYSENTER_CS { *sysenter_cs.offset(0isize) = low & 65535i32 @@ -2166,10 +2166,10 @@ pub unsafe extern "C" fn instr_0F30() -> () { } else if index == IA32_KERNEL_GS_BASE { c_comment!(("Only used in 64 bit mode (by SWAPGS), but set by kvm-unit-test")); - dbg_log_c!(("GS Base written")); + dbg_log_c!("GS Base written"); } else { - dbg_log_c!(("Unknown msr: %x"), index); + dbg_log_c!("Unknown msr: %x", index); dbg_assert!(0 != 0i32); } } @@ -2187,7 +2187,7 @@ pub unsafe extern "C" fn instr_0F31() -> () { *reg32s.offset(EDX as isize) = (tsc >> 32i32) as i32; if 0 != 0i32 * 0i32 { dbg_log_c!( - ("rdtsc edx:eax=%x:%x"), + "rdtsc edx:eax=%x:%x", *reg32s.offset(EDX as isize), *reg32s.offset(EAX as isize) ); @@ -2206,7 +2206,7 @@ pub unsafe extern "C" fn instr_0F32() -> () { } else { let mut index: i32 = *reg32s.offset(ECX as isize); - dbg_log_c!(("rdmsr ecx=%x"), index); + dbg_log_c!("rdmsr ecx=%x", index); let mut low: i32 = 0i32; let mut high: i32 = 0i32; if index == IA32_SYSENTER_CS { @@ -2250,7 +2250,7 @@ pub unsafe extern "C" fn instr_0F32() -> () { c_comment!(("netbsd")); } else if !(index == MSR_PKG_C2_RESIDENCY) { - dbg_log_c!(("Unknown msr: %x"), index); + dbg_log_c!("Unknown msr: %x", index); dbg_assert!(0 != 0i32); } } @@ -4503,7 +4503,7 @@ pub unsafe extern "C" fn instr_0FAE_2_mem(mut addr: i32) -> () { c_comment!(("ldmxcsr")); let mut new_mxcsr: i32 = return_on_pagefault!(safe_read32s(addr)); if 0 != new_mxcsr & !MXCSR_MASK { - dbg_log_c!(("Invalid mxcsr bits: %x"), new_mxcsr & !MXCSR_MASK); + dbg_log_c!("Invalid mxcsr bits: %x", new_mxcsr & !MXCSR_MASK); dbg_assert!(0 != 0i32); trigger_gp_non_raising(0i32); return; @@ -6936,7 +6936,7 @@ pub unsafe extern "C" fn instr_660FFE_mem(mut addr: i32, mut r: i32) -> () { #[no_mangle] pub unsafe extern "C" fn instr_0FFF() -> () { c_comment!(("Windows 98")); - dbg_log_c!(("#ud: 0F FF")); + dbg_log_c!("#ud: 0F FF"); trigger_ud(); } #[no_mangle] diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index 9d4459a9..1444d1bb 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -1280,7 +1280,7 @@ pub unsafe extern "C" fn fxrstor(mut addr: u32) -> () { )); let mut new_mxcsr: i32 = safe_read32s(addr.wrapping_add(24i32 as u32) as i32).unwrap(); if 0 != new_mxcsr & !MXCSR_MASK { - dbg_log_c!(("#gp Invalid mxcsr bits")); + dbg_log_c!("#gp Invalid mxcsr bits"); trigger_gp_non_raising(0i32); return; } From a5cbf53da5410d574fb965e7161c55a6b590cec3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 16 Aug 2018 14:37:10 -0500 Subject: [PATCH 1192/2137] Fix jit in presence of new page fault handling Makes the following a block boundary: - push - Any non-custom instruction that uses modrm encoding - Any sse/fpu instruction This commit affects performance negatively. In order to fix this, the above instructions need to be implemented using custom code generators for the memory access. --- gen/generate_analyzer.js | 2 +- gen/generate_jit.js | 2 +- gen/x86_table.js | 59 +++++++++++++++++++++-------------- src/rust/codegen.rs | 30 ++++++++++++++---- src/rust/cpu2/cpu.rs | 12 +++++-- src/rust/cpu2/instructions.rs | 19 +++++++++++ src/rust/cpu2/misc_instr.rs | 4 +-- src/rust/global_pointers.rs | 1 + src/rust/jit.rs | 1 - src/rust/jit_instructions.rs | 51 +++++++++++++++++++++++++----- 10 files changed, 136 insertions(+), 45 deletions(-) diff --git a/gen/generate_analyzer.js b/gen/generate_analyzer.js index dee08c82..95deb0b7 100755 --- a/gen/generate_analyzer.js +++ b/gen/generate_analyzer.js @@ -217,7 +217,7 @@ function gen_instruction_body_after_fixed_g(encoding, size) const imm_read = gen_read_imm_call(encoding, size); const instruction_postfix = []; - if(encoding.block_boundary && !encoding.jump_offset_imm) + if(encoding.block_boundary && !encoding.jump_offset_imm || (!encoding.custom && encoding.e) || encoding.sse || encoding.task_switch_test) { instruction_postfix.push("analysis.ty = ::analysis::AnalysisType::BlockBoundary;"); } diff --git a/gen/generate_jit.js b/gen/generate_jit.js index 36f7185c..2e68d369 100755 --- a/gen/generate_jit.js +++ b/gen/generate_jit.js @@ -216,7 +216,7 @@ function gen_instruction_body_after_fixed_g(encoding, size) { const instruction_postfix = []; - if(encoding.block_boundary) + if(encoding.block_boundary || (!encoding.custom && encoding.e) || encoding.sse || encoding.task_switch_test) { instruction_postfix.push("*instr_flags |= ::jit::JIT_INSTR_BLOCK_BOUNDARY_FLAG;"); } diff --git a/gen/x86_table.js b/gen/x86_table.js index b892db5a..40291d1a 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -51,20 +51,21 @@ const encodings = [ { opcode: 0x4E, nonfaulting: 1, os: 1, }, { opcode: 0x4F, nonfaulting: 1, os: 1, }, - { opcode: 0x50, custom: 1, os: 1, }, - { opcode: 0x51, custom: 1, os: 1, }, - { opcode: 0x52, custom: 1, os: 1, }, - { opcode: 0x53, custom: 1, os: 1, }, - { opcode: 0x54, custom: 1, os: 1, }, - { opcode: 0x55, custom: 1, os: 1, }, - { opcode: 0x56, custom: 1, os: 1, }, - { opcode: 0x57, custom: 1, os: 1, }, + // XXX: temporarily marked as block boundary until uses gen_push + { opcode: 0x50, custom: 1, os: 1, block_boundary: 1, }, + { opcode: 0x51, custom: 1, os: 1, block_boundary: 1, }, + { opcode: 0x52, custom: 1, os: 1, block_boundary: 1, }, + { opcode: 0x53, custom: 1, os: 1, block_boundary: 1, }, + { opcode: 0x54, custom: 1, os: 1, block_boundary: 1, }, + { opcode: 0x55, custom: 1, os: 1, block_boundary: 1, }, + { opcode: 0x56, custom: 1, os: 1, block_boundary: 1, }, + { opcode: 0x57, custom: 1, os: 1, block_boundary: 1, }, { opcode: 0x58, custom: 1, os: 1, }, { opcode: 0x59, custom: 1, os: 1, }, { opcode: 0x5A, custom: 1, os: 1, }, { opcode: 0x5B, custom: 1, os: 1, }, - { opcode: 0x5C, os: 1, }, + { opcode: 0x5C, os: 1, block_boundary: 1 }, { opcode: 0x5D, custom: 1, os: 1, }, { opcode: 0x5E, custom: 1, os: 1, }, { opcode: 0x5F, custom: 1, os: 1, }, @@ -78,9 +79,11 @@ const encodings = [ { opcode: 0x66, prefix: 1, }, { opcode: 0x67, prefix: 1, }, - { opcode: 0x68, custom: 1, os: 1, imm1632: 1, }, + // XXX: Temporary block boundary + { opcode: 0x68, custom: 1, os: 1, imm1632: 1, block_boundary: 1 }, { opcode: 0x69, nonfaulting: 1, os: 1, e: 1, imm1632: 1, mask_flags: af, }, // zf? - { opcode: 0x6A, custom: 1, os: 1, imm8s: 1, }, + // XXX: Temporary block boundary + { opcode: 0x6A, custom: 1, os: 1, imm8s: 1, block_boundary: 1, }, { opcode: 0x6B, nonfaulting: 1, os: 1, e: 1, imm8s: 1, mask_flags: af, }, // zf? { opcode: 0x6C, block_boundary: 1, is_string: 1, skip: 1, }, // ins @@ -131,10 +134,11 @@ const encodings = [ { opcode: 0x9E, }, { opcode: 0x9F, }, - { opcode: 0xA0, immaddr: 1, }, - { opcode: 0xA1, os: 1, immaddr: 1, }, - { opcode: 0xA2, immaddr: 1, }, - { opcode: 0xA3, os: 1, immaddr: 1, }, + // XXX: temporarily marked as block boundary until uses gen_safe_{read,write} + { opcode: 0xA0, immaddr: 1, block_boundary: 1 }, + { opcode: 0xA1, os: 1, immaddr: 1, block_boundary: 1 }, + { opcode: 0xA2, immaddr: 1, block_boundary: 1 }, + { opcode: 0xA3, os: 1, immaddr: 1, block_boundary: 1 }, // string instructions aren't jumps, but they modify eip due to how they're implemented { opcode: 0xA4, block_boundary: 1, is_string: 1, }, @@ -181,11 +185,14 @@ const encodings = [ { opcode: 0xC4, block_boundary: 1, os: 1, e: 1, skip: 1, }, // les { opcode: 0xC5, block_boundary: 1, os: 1, e: 1, skip: 1, }, // lds - { opcode: 0xC6, e: 1, fixed_g: 0, nonfaulting: 1, imm8: 1, }, - { opcode: 0xC7, custom: 1, os: 1, e: 1, fixed_g: 0, nonfaulting: 1, imm1632: 1, }, + // XXX: Temporary block boundary + { opcode: 0xC6, e: 1, fixed_g: 0, imm8: 1, block_boundary: 1, }, + { opcode: 0xC7, custom: 1, os: 1, e: 1, fixed_g: 0, imm1632: 1, block_boundary: 1, }, + + // XXX: Temporary block boundary + { opcode: 0xC8, os: 1, imm16: 1, extra_imm8: 1, block_boundary: 1, }, // enter + { opcode: 0xC9, os: 1, skip: 1, block_boundary: 1, }, // leave: requires valid ebp - { opcode: 0xC8, os: 1, imm16: 1, extra_imm8: 1, }, // enter - { opcode: 0xC9, os: 1, skip: 1, }, // leave: requires valid ebp { opcode: 0xCA, block_boundary: 1, no_next_instruction: 1, os: 1, imm16: 1, skip: 1, }, // retf { opcode: 0xCB, block_boundary: 1, no_next_instruction: 1, os: 1, skip: 1, }, { opcode: 0xCC, block_boundary: 1, skip: 1, }, // int @@ -196,7 +203,9 @@ const encodings = [ { opcode: 0xD4, imm8: 1, block_boundary: 1, }, // aam, may trigger #de { opcode: 0xD5, nonfaulting: 1, imm8: 1, mask_flags: of | cf | af, }, { opcode: 0xD6, nonfaulting: 1, }, - { opcode: 0xD7, skip: 1, }, + + // XXX: Temporary block boundary + { opcode: 0xD7, skip: 1, block_boundary: 1, }, // loop, jcxz, etc. // Conditional jumps, but condition code not supported by code generator @@ -212,7 +221,8 @@ const encodings = [ { opcode: 0xE6, block_boundary: 1, imm8: 1, skip: 1, }, // out { opcode: 0xE7, block_boundary: 1, os: 1, imm8: 1, skip: 1, }, - { opcode: 0xE8, block_boundary: 1, jump_offset_imm: 1, os: 1, imm1632: 1, custom: 1, skip: 1, }, // call + //{ opcode: 0xE8, block_boundary: 1, jump_offset_imm: 1, os: 1, imm1632: 1, custom: 1, skip: 1, }, // call + { opcode: 0xE8, block_boundary: 1, os: 1, imm1632: 1, skip: 1, }, // call { opcode: 0xE9, block_boundary: 1, jump_offset_imm: 1, no_next_instruction: 1, os: 1, imm1632: 1, custom: 1, skip: 1, }, { opcode: 0xEA, block_boundary: 1, no_next_instruction: 1, os: 1, imm1632: 1, extra_imm16: 1, skip: 1, }, // jmpf { opcode: 0xEB, block_boundary: 1, jump_offset_imm: 1, no_next_instruction: 1, os: 1, imm8s: 1, custom: 1, skip: 1, }, @@ -386,11 +396,14 @@ const encodings = [ { opcode: 0x0F9E, nonfaulting: 1, e: 1, }, { opcode: 0x0F9F, nonfaulting: 1, e: 1, }, - { opcode: 0x0FA0, os: 1, skip: 1, }, + // XXX: Temporary block boundary + { opcode: 0x0FA0, os: 1, skip: 1, block_boundary: 1, }, { opcode: 0x0FA1, os: 1, block_boundary: 1, skip: 1, }, // pop fs: block_boundary since it uses non-raising cpu exceptions + { opcode: 0x0FA2, skip: 1, }, - { opcode: 0x0FA8, os: 1, skip: 1, }, + // XXX: Temporary block boundary + { opcode: 0x0FA8, os: 1, skip: 1, block_boundary: 1, }, { opcode: 0x0FA9, os: 1, block_boundary: 1, skip: 1, }, // pop gs { opcode: 0x0FA3, os: 1, e: 1, only_reg: 1, }, // bt (can also index memory, but not supported by test right now) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index f747f337..cd3f74e7 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -236,17 +236,26 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { } // Pseudo: - // else { leave_on_stack(safe_read16_slow(address)); } + // else { leave_on_stack(safe_read*_slow(address)); if(page_fault) return } builder.instruction_body.else_(); builder.instruction_body.get_local(&address_local); match bits { BitSize::WORD => { - gen_call_fn1_ret(builder, "safe_read16_slow"); + gen_call_fn1_ret(builder, "safe_read16_slow_jit"); }, BitSize::DWORD => { - gen_call_fn1_ret(builder, "safe_read32s_slow"); + gen_call_fn1_ret(builder, "safe_read32s_slow_jit"); }, } + + builder + .instruction_body + .load_aligned_i32(global_pointers::PAGE_FAULT); + + builder.instruction_body.if_void(); + builder.instruction_body.return_(); + builder.instruction_body.block_end(); + builder.instruction_body.block_end(); builder.free_local(address_local); @@ -332,18 +341,27 @@ fn gen_safe_write( } // Pseudo: - // else { safe_write16_slow(address, value); } + // else { safe_write*_slow(address, value); if(page_fault) return; } builder.instruction_body.else_(); builder.instruction_body.get_local(&address_local); builder.instruction_body.get_local(&value_local); match bits { BitSize::WORD => { - gen_call_fn2(builder, "safe_write16_slow"); + gen_call_fn2(builder, "safe_write16_slow_jit"); }, BitSize::DWORD => { - gen_call_fn2(builder, "safe_write32_slow"); + gen_call_fn2(builder, "safe_write32_slow_jit"); }, } + + builder + .instruction_body + .load_aligned_i32(global_pointers::PAGE_FAULT); + + builder.instruction_body.if_void(); + builder.instruction_body.return_(); + builder.instruction_body.block_end(); + builder.instruction_body.block_end(); } diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 3be494fa..16c41c5d 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1872,7 +1872,7 @@ pub unsafe extern "C" fn modrm_resolve(mut modrm_byte: i32) -> Result { #[no_mangle] pub unsafe extern "C" fn cycle_internal() -> () { profiler_stat_increment(S_CYCLE_INTERNAL); - if false { + if true { let mut wasm_table_index: u16 = 0; let mut initial_tsc: i32 = 0; let mut initial_state: u16 = 0; @@ -2367,12 +2367,18 @@ pub unsafe extern "C" fn safe_write32_slow(mut addr: i32, mut value: i32) -> Res #[no_mangle] pub unsafe fn safe_write16_slow_jit(addr: i32, value: i32) { - let _ = safe_write16_slow(addr, value); + match safe_write16_slow(addr, value) { + Ok(()) => *page_fault = false, + Err(()) => *page_fault = true, + } } #[no_mangle] pub unsafe fn safe_write32_slow_jit(addr: i32, value: i32) { - let _ = safe_write32_slow(addr, value); + match safe_write32_slow(addr, value) { + Ok(()) => *page_fault = false, + Err(()) => *page_fault = true, + } } #[no_mangle] diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index 705bfac8..e8755bfd 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -3094,6 +3094,15 @@ pub unsafe extern "C" fn instr16_8F_0_mem(modrm_byte: i32) -> () { }, } } + +#[no_mangle] +pub unsafe fn instr16_8F_0_mem_jit(addr: i32) -> () { + adjust_stack_reg(-2i32); + let mut stack_value: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0i32))); + return_on_pagefault!(safe_write16(addr, stack_value)); + adjust_stack_reg(2i32); +} + #[no_mangle] pub unsafe extern "C" fn instr16_8F_0_reg(mut r: i32) -> () { write_reg16(r, return_on_pagefault!(pop16())); @@ -3115,10 +3124,20 @@ pub unsafe extern "C" fn instr32_8F_0_mem(modrm_byte: i32) -> () { }, } } + +#[no_mangle] +pub unsafe fn instr32_8F_0_mem_jit(addr: i32) -> () { + adjust_stack_reg(-4i32); + let mut stack_value: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))); + return_on_pagefault!(safe_write32(addr, stack_value)); + adjust_stack_reg(4i32); +} + #[no_mangle] pub unsafe extern "C" fn instr32_8F_0_reg(mut r: i32) -> () { write_reg32(r, return_on_pagefault!(pop32s())); } + #[no_mangle] pub unsafe extern "C" fn instr_90() -> () {} #[no_mangle] diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index 1444d1bb..812cf6f3 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -1075,11 +1075,11 @@ pub unsafe extern "C" fn push16_ss32_mem(mut addr: i32) -> Result<(), ()> { #[no_mangle] pub unsafe extern "C" fn push16_ss16_mem_jit(mut addr: i32) { - return_on_pagefault!(push16_ss16(addr)) + return_on_pagefault!(push16_ss16_mem(addr)) } #[no_mangle] pub unsafe extern "C" fn push16_ss32_mem_jit(mut addr: i32) { - return_on_pagefault!(push16_ss32(addr)) + return_on_pagefault!(push16_ss32_mem(addr)) } #[no_mangle] diff --git a/src/rust/global_pointers.rs b/src/rust/global_pointers.rs index b65fcc77..e6e7e17e 100644 --- a/src/rust/global_pointers.rs +++ b/src/rust/global_pointers.rs @@ -1,4 +1,5 @@ pub const REG: u32 = 4; +pub const PAGE_FAULT: u32 = 540; pub const INSTRUCTION_POINTER: u32 = 556; pub const PREVIOUS_IP: u32 = 560; pub const CR: u32 = 580; diff --git a/src/rust/jit.rs b/src/rust/jit.rs index de2193b9..87469d8f 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -1157,7 +1157,6 @@ pub fn jit_increase_hotness_and_maybe_compile( cs_offset: u32, state_flags: CachedStateFlags, ) { - return; record_entry_point(ctx, phys_address); let page = Page::page_of(phys_address); let address_hash = jit_hot_hash_page(page) as usize; diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 224f229e..6d55a6c3 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -7,6 +7,7 @@ use jit::JitContext; use modrm; use prefix::SEG_PREFIX_ZERO; use prefix::{PREFIX_66, PREFIX_67, PREFIX_F2, PREFIX_F3}; +use regs; use regs::{AX, BP, BX, CX, DI, DX, SI, SP}; use regs::{CS, DS, ES, FS, GS, SS}; use regs::{EAX, EBP, EBX, ECX, EDI, EDX, ESI, ESP}; @@ -227,9 +228,19 @@ pub fn instr16_7F_jit(_ctx: &mut JitContext, _imm: u32) {} pub fn instr32_7F_jit(_ctx: &mut JitContext, _imm: u32) {} pub fn instr16_89_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - // TODO: Inlining codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_modrm_fn1(ctx, "instr16_89_mem", r); + + let address_local = ctx.builder.set_new_local(); + + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg16_offset(r) as i32); + ctx.builder.instruction_body.load_aligned_u16_from_stack(0); + let value_local = ctx.builder.set_new_local(); + + codegen::gen_safe_write16(ctx, &address_local, &value_local); + ctx.builder.free_local(address_local); + ctx.builder.free_local(value_local); } pub fn instr16_89_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_set_reg16_r(ctx, r1, r2); @@ -254,9 +265,15 @@ pub fn instr32_89_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { } pub fn instr16_8B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - // TODO: Inlining + // Pseudo: reg16[r] = safe_read16(modrm_resolve(modrm_byte)); + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg16_offset(r) as i32); + codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_modrm_fn1(ctx, "instr16_8B_mem", r); + codegen::gen_safe_read16(ctx); + + ctx.builder.instruction_body.store_aligned_u16(); } pub fn instr16_8B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_set_reg16_r(ctx, r2, r1); @@ -300,17 +317,35 @@ pub fn instr32_8D_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { } pub fn instr16_8F_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_fn0_const(ctx, "instr16_8F_0_mem_pre"); + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg16_offset(regs::SP) as i32); + ctx.builder + .instruction_body + .load_aligned_u16(global_pointers::get_reg16_offset(regs::SP)); + ctx.builder.instruction_body.push_i32(2); + ctx.builder.instruction_body.add_i32(); + ctx.builder.instruction_body.store_aligned_u16(); + codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_modrm_fn0(ctx, "instr16_8F_0_mem"); + codegen::gen_modrm_fn0(ctx, "instr16_8F_0_mem_jit"); } pub fn instr16_8F_0_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_fn1_const(ctx, "instr16_8F_0_reg", r); } pub fn instr32_8F_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_fn0_const(ctx, "instr32_8F_0_mem_pre"); + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg32_offset(regs::ESP) as i32); + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_reg32_offset(regs::ESP)); + ctx.builder.instruction_body.push_i32(4); + ctx.builder.instruction_body.add_i32(); + ctx.builder.instruction_body.store_aligned_i32(); + codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_modrm_fn0(ctx, "instr32_8F_0_mem"); + codegen::gen_modrm_fn0(ctx, "instr32_8F_0_mem_jit"); } pub fn instr32_8F_0_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_fn1_const(ctx, "instr32_8F_0_reg", r); From fbe14a3d98695ca9b5ce635790b02df51b3f5227 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 18 Aug 2018 19:52:40 -0500 Subject: [PATCH 1193/2137] Disable safe_{read,write} fast path profiling --- src/rust/cpu2/cpu.rs | 80 ++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 16c41c5d..e38c0859 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -2164,7 +2164,9 @@ pub unsafe extern "C" fn safe_read32s(mut address: i32) -> Result { let mut entry: i32 = *tlb_data.offset(base as isize); let mut info_bits: i32 = entry & 4095i32 & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; if info_bits == TLB_VALID && address & 4095i32 <= 4096i32 - 4i32 { - profiler_stat_increment(S_SAFE_READ32_FAST); + if false { + profiler_stat_increment(S_SAFE_READ32_FAST); + } c_comment!(("- not in memory mapped area")); c_comment!(("- can be accessed from any cpl")); let mut phys_address: u32 = (entry & !4095i32 ^ address) as u32; @@ -2172,20 +2174,22 @@ pub unsafe extern "C" fn safe_read32s(mut address: i32) -> Result { return Ok(*(mem8.offset(phys_address as isize) as *mut i32)); } else { - if address & 4095i32 > 4096i32 - 4i32 { - profiler_stat_increment(S_SAFE_READ32_SLOW_PAGE_CROSSED); - } - else if info_bits & TLB_VALID == 0i32 { - profiler_stat_increment(S_SAFE_READ32_SLOW_NOT_VALID); - } - else if 0 != info_bits & TLB_NO_USER { - profiler_stat_increment(S_SAFE_READ32_SLOW_NOT_USER); - } - else if 0 != info_bits & TLB_IN_MAPPED_RANGE { - profiler_stat_increment(S_SAFE_READ32_SLOW_IN_MAPPED_RANGE); - } - else { - dbg_assert!(0 != 0i32); + if false { + if address & 4095i32 > 4096i32 - 4i32 { + profiler_stat_increment(S_SAFE_READ32_SLOW_PAGE_CROSSED); + } + else if info_bits & TLB_VALID == 0i32 { + profiler_stat_increment(S_SAFE_READ32_SLOW_NOT_VALID); + } + else if 0 != info_bits & TLB_NO_USER { + profiler_stat_increment(S_SAFE_READ32_SLOW_NOT_USER); + } + else if 0 != info_bits & TLB_IN_MAPPED_RANGE { + profiler_stat_increment(S_SAFE_READ32_SLOW_IN_MAPPED_RANGE); + } + else { + dbg_assert!(0 != 0i32); + } } return safe_read32s_slow(address); }; @@ -2314,7 +2318,9 @@ pub unsafe extern "C" fn safe_write32(mut address: i32, mut value: i32) -> Resul TLB_NO_USER }; if info_bits == TLB_VALID && address & 4095i32 <= 4096i32 - 4i32 { - profiler_stat_increment(S_SAFE_WRITE32_FAST); + if false { + profiler_stat_increment(S_SAFE_WRITE32_FAST); + } c_comment!(("- allowed to write in user-mode")); c_comment!(("- not in memory mapped area")); c_comment!(("- does not contain code")); @@ -2324,26 +2330,28 @@ pub unsafe extern "C" fn safe_write32(mut address: i32, mut value: i32) -> Resul *(mem8.offset(phys_address as isize) as *mut i32) = value; } else { - if address & 4095i32 > 4096i32 - 4i32 { - profiler_stat_increment(S_SAFE_WRITE32_SLOW_PAGE_CROSSED); - } - else if info_bits & TLB_VALID == 0i32 { - profiler_stat_increment(S_SAFE_WRITE32_SLOW_NOT_VALID); - } - else if 0 != info_bits & TLB_NO_USER { - profiler_stat_increment(S_SAFE_WRITE32_SLOW_NOT_USER); - } - else if 0 != info_bits & TLB_IN_MAPPED_RANGE { - profiler_stat_increment(S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE); - } - else if 0 != info_bits & TLB_READONLY { - profiler_stat_increment(S_SAFE_WRITE32_SLOW_READ_ONLY); - } - else if 0 != info_bits & TLB_HAS_CODE { - profiler_stat_increment(S_SAFE_WRITE32_SLOW_HAS_CODE); - } - else { - dbg_assert!(0 != 0i32); + if false { + if address & 4095i32 > 4096i32 - 4i32 { + profiler_stat_increment(S_SAFE_WRITE32_SLOW_PAGE_CROSSED); + } + else if info_bits & TLB_VALID == 0i32 { + profiler_stat_increment(S_SAFE_WRITE32_SLOW_NOT_VALID); + } + else if 0 != info_bits & TLB_NO_USER { + profiler_stat_increment(S_SAFE_WRITE32_SLOW_NOT_USER); + } + else if 0 != info_bits & TLB_IN_MAPPED_RANGE { + profiler_stat_increment(S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE); + } + else if 0 != info_bits & TLB_READONLY { + profiler_stat_increment(S_SAFE_WRITE32_SLOW_READ_ONLY); + } + else if 0 != info_bits & TLB_HAS_CODE { + profiler_stat_increment(S_SAFE_WRITE32_SLOW_HAS_CODE); + } + else { + dbg_assert!(0 != 0i32); + } } safe_write32_slow(address, value)?; }; From 4b34beeb7978adb9a0ad274721bd1708497c05b2 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 18 Aug 2018 21:54:42 -0500 Subject: [PATCH 1194/2137] c2rust cleanup: Use Rust imports instead of linking --- src/browser/starter.js | 17 +- src/rust/cpu2/arith.rs | 855 +----------------- src/rust/cpu2/cpu.rs | 625 +------------ src/rust/cpu2/fpu.rs | 876 +----------------- src/rust/cpu2/global_pointers.rs | 622 +------------ src/rust/cpu2/imports.rs | 17 - src/rust/cpu2/instructions.rs | 1453 +----------------------------- src/rust/cpu2/instructions_0f.rs | 1180 ++---------------------- src/rust/cpu2/memory.rs | 876 +----------------- src/rust/cpu2/misc_instr.rs | 859 +----------------- src/rust/cpu2/mod.rs | 1 - src/rust/cpu2/modrm.rs | 842 +---------------- src/rust/cpu2/profiler.rs | 246 +---- src/rust/cpu2/shared.rs | 399 -------- src/rust/cpu2/sse_instr.rs | 712 +-------------- src/rust/cpu2/string.rs | 885 +----------------- 16 files changed, 217 insertions(+), 10248 deletions(-) delete mode 100644 src/rust/cpu2/shared.rs diff --git a/src/browser/starter.js b/src/browser/starter.js index 0e4082d0..00dc28df 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -205,14 +205,10 @@ function V86Starter(options) "mmap_write32": function(addr, value) { return cpu.mmap_write32(addr, value); }, "mmap_write128": function(addr, value0, value1, value2, value3) { return cpu.mmap_write128(addr, value0, value1, value2, value3); }, - "int_log2": function(val) { return v86util.int_log2(val); }, - "popa16": function() { return cpu.popa16.apply(cpu, arguments); }, "popa32": function() { return cpu.popa32.apply(cpu, arguments); }, "arpl": function() { return cpu.arpl.apply(cpu, arguments); }, - "bswap": function() { return cpu.bswap.apply(cpu, arguments); }, - "lar": function() { return cpu.lar.apply(cpu, arguments); }, "lsl": function() { return cpu.lsl.apply(cpu, arguments); }, "verw": function() { return cpu.verw.apply(cpu, arguments); }, @@ -233,15 +229,6 @@ function V86Starter(options) "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, "coverage_log": (fn_name_offset, num_blocks, visited_block) => { @@ -249,10 +236,10 @@ function V86Starter(options) }, // see https://github.com/kripken/emscripten/blob/incoming/src/library.js - "atan2": Math.atan2, + "Math_atan2": Math.atan2, "sin": Math.sin, "cos": Math.cos, - "tan": Math.tan, + "Math_tan": Math.tan, "trunc": Math.trunc, "fmod": (x, y) => x % y, "llvm_exp2_f64": (x) => Math.pow(2, x), diff --git a/src/rust/cpu2/arith.rs b/src/rust/cpu2/arith.rs index e0a48444..229cfc28 100644 --- a/src/rust/cpu2/arith.rs +++ b/src/rust/cpu2/arith.rs @@ -9,859 +9,12 @@ #![feature(extern_types, libc)] use cpu2::cpu::*; +use cpu2::global_pointers::*; +use cpu2::memory::{read8, write8}; +use cpu2::misc_instr::{getaf, getcf}; -extern "C" { +pub fn int_log2(x: i32) -> i32 { 31 - x.leading_zeros() as i32 } - #[no_mangle] - fn __fpclassifyl(_: f64) -> i32; - #[no_mangle] - static FLAGS_ALL: i32; - #[no_mangle] - static flags_changed: *mut i32; - #[no_mangle] - static last_op_size: *mut i32; - #[no_mangle] - static last_result: *mut i32; - #[no_mangle] - static last_add_result: *mut i32; - #[no_mangle] - static last_op2: *mut i32; - #[no_mangle] - static last_op1: *mut i32; - #[no_mangle] - fn getcf() -> bool; - #[no_mangle] - static OPSIZE_8: i32; - #[no_mangle] - static OPSIZE_16: i32; - #[no_mangle] - static OPSIZE_32: i32; - #[no_mangle] - static flags: *mut i32; - #[no_mangle] - static FLAG_OVERFLOW: i32; - #[no_mangle] - static AL: i32; - #[no_mangle] - static reg8: *mut u8; - #[no_mangle] - static AX: i32; - #[no_mangle] - static reg16: *mut u16; - #[no_mangle] - static reg8s: *mut i8; - #[no_mangle] - static DX: i32; - #[no_mangle] - static reg16s: *mut i16; - - #[no_mangle] - static EAX: i32; - #[no_mangle] - static reg32s: *mut i32; - #[no_mangle] - static EDX: i32; - #[no_mangle] - static FLAG_ADJUST: i32; - #[no_mangle] - fn getaf() -> bool; - #[no_mangle] - static AH: i32; - #[no_mangle] - fn trigger_de() -> (); - #[no_mangle] - fn c_comment(m: *const i8) -> (); - #[no_mangle] - fn read8(addr: u32) -> i32; - #[no_mangle] - fn write8(addr: u32, value: i32) -> (); - #[no_mangle] - fn int_log2(_: i32) -> i32; - #[no_mangle] - static FLAG_ZERO: i32; - - #[no_mangle] - static FLAG_CARRY: i32; - #[no_mangle] - static FLAG_PARITY: i32; - #[no_mangle] - static FLAG_SIGN: i32; - #[no_mangle] - static FLAG_TRAP: i32; - #[no_mangle] - static FLAG_INTERRUPT: i32; - #[no_mangle] - static FLAG_DIRECTION: i32; - #[no_mangle] - static FLAG_IOPL: i32; - #[no_mangle] - static FLAG_NT: i32; - #[no_mangle] - static FLAG_RF: i32; - #[no_mangle] - static FLAG_VM: i32; - #[no_mangle] - static FLAG_AC: i32; - #[no_mangle] - static FLAG_VIF: i32; - #[no_mangle] - static FLAG_VIP: i32; - #[no_mangle] - static FLAG_ID: i32; - #[no_mangle] - static FLAGS_DEFAULT: i32; - #[no_mangle] - static FLAGS_MASK: i32; - #[no_mangle] - static ECX: i32; - #[no_mangle] - static EBX: i32; - #[no_mangle] - static ESP: i32; - #[no_mangle] - static EBP: i32; - #[no_mangle] - static ESI: i32; - #[no_mangle] - static EDI: i32; - #[no_mangle] - static CX: i32; - #[no_mangle] - static BX: i32; - #[no_mangle] - static SP: i32; - #[no_mangle] - static BP: i32; - #[no_mangle] - static SI: i32; - #[no_mangle] - static DI: i32; - #[no_mangle] - static CL: i32; - #[no_mangle] - static DL: i32; - #[no_mangle] - static BL: i32; - #[no_mangle] - static CH: i32; - #[no_mangle] - static DH: i32; - #[no_mangle] - static BH: i32; - #[no_mangle] - static ES: i32; - #[no_mangle] - static CS: i32; - #[no_mangle] - static SS: i32; - #[no_mangle] - static DS: i32; - #[no_mangle] - static FS: i32; - #[no_mangle] - static GS: i32; - #[no_mangle] - static TR: i32; - #[no_mangle] - static LDTR: i32; - #[no_mangle] - static PAGE_TABLE_PRESENT_MASK: i32; - #[no_mangle] - static PAGE_TABLE_RW_MASK: i32; - #[no_mangle] - static PAGE_TABLE_USER_MASK: i32; - #[no_mangle] - static PAGE_TABLE_ACCESSED_MASK: i32; - #[no_mangle] - static PAGE_TABLE_DIRTY_MASK: i32; - #[no_mangle] - static PAGE_TABLE_PSE_MASK: i32; - #[no_mangle] - static PAGE_TABLE_GLOBAL_MASK: i32; - #[no_mangle] - static MMAP_BLOCK_BITS: i32; - #[no_mangle] - static MMAP_BLOCK_SIZE: i32; - #[no_mangle] - static CR0_PE: i32; - #[no_mangle] - static CR0_MP: i32; - #[no_mangle] - static CR0_EM: i32; - #[no_mangle] - static CR0_TS: i32; - #[no_mangle] - static CR0_ET: i32; - #[no_mangle] - static CR0_WP: i32; - #[no_mangle] - static CR0_NW: i32; - #[no_mangle] - static CR0_CD: i32; - #[no_mangle] - static CR0_PG: i32; - #[no_mangle] - static CR4_VME: i32; - #[no_mangle] - static CR4_PVI: i32; - #[no_mangle] - static CR4_TSD: i32; - #[no_mangle] - static CR4_PSE: i32; - #[no_mangle] - static CR4_DE: i32; - #[no_mangle] - static CR4_PAE: i32; - #[no_mangle] - static CR4_PGE: i32; - #[no_mangle] - static IA32_SYSENTER_CS: i32; - #[no_mangle] - static IA32_SYSENTER_ESP: i32; - #[no_mangle] - static IA32_SYSENTER_EIP: i32; - #[no_mangle] - static IA32_TIME_STAMP_COUNTER: i32; - #[no_mangle] - static IA32_PLATFORM_ID: i32; - #[no_mangle] - static IA32_APIC_BASE_MSR: i32; - #[no_mangle] - static IA32_BIOS_SIGN_ID: i32; - #[no_mangle] - static MSR_PLATFORM_INFO: i32; - #[no_mangle] - static MSR_MISC_FEATURE_ENABLES: i32; - #[no_mangle] - static IA32_MISC_ENABLE: i32; - #[no_mangle] - static IA32_RTIT_CTL: i32; - #[no_mangle] - static MSR_SMI_COUNT: i32; - #[no_mangle] - static IA32_MCG_CAP: i32; - #[no_mangle] - static IA32_KERNEL_GS_BASE: i32; - #[no_mangle] - static MSR_PKG_C2_RESIDENCY: i32; - #[no_mangle] - static IA32_APIC_BASE_BSP: i32; - #[no_mangle] - static IA32_APIC_BASE_EXTD: i32; - #[no_mangle] - static IA32_APIC_BASE_EN: i32; - #[no_mangle] - static APIC_ADDRESS: i32; - #[no_mangle] - static SEG_PREFIX_NONE: i32; - #[no_mangle] - static SEG_PREFIX_ZERO: i32; - #[no_mangle] - static PREFIX_MASK_REP: i32; - #[no_mangle] - static PREFIX_REPZ: i32; - #[no_mangle] - static PREFIX_REPNZ: i32; - #[no_mangle] - static PREFIX_MASK_SEGMENT: i32; - #[no_mangle] - static PREFIX_MASK_OPSIZE: i32; - #[no_mangle] - static PREFIX_MASK_ADDRSIZE: i32; - #[no_mangle] - static PREFIX_F2: i32; - #[no_mangle] - static PREFIX_F3: i32; - #[no_mangle] - static PREFIX_66: i32; - #[no_mangle] - static LOG_CPU: i32; - #[no_mangle] - static A20_MASK: i32; - #[no_mangle] - static A20_MASK16: i32; - #[no_mangle] - static A20_MASK32: i32; - #[no_mangle] - static MXCSR_MASK: i32; - - #[no_mangle] - static mut mem8: *mut u8; - #[no_mangle] - static mut mem16: *mut u16; - #[no_mangle] - static mut mem32s: *mut i32; - #[no_mangle] - static mut jit_block_boundary: bool; - #[no_mangle] - static VALID_TLB_ENTRY_MAX: i32; - #[no_mangle] - static mut valid_tlb_entries: [i32; 10000]; - #[no_mangle] - static mut valid_tlb_entries_count: i32; - #[no_mangle] - static TLB_VALID: i32; - #[no_mangle] - static TLB_READONLY: i32; - #[no_mangle] - static TLB_NO_USER: i32; - #[no_mangle] - static TLB_IN_MAPPED_RANGE: i32; - #[no_mangle] - static TLB_GLOBAL: i32; - #[no_mangle] - static TLB_HAS_CODE: i32; - #[no_mangle] - static CPU_EXCEPTION_DE: i32; - #[no_mangle] - static CPU_EXCEPTION_DB: i32; - #[no_mangle] - static CPU_EXCEPTION_NMI: i32; - #[no_mangle] - static CPU_EXCEPTION_BP: i32; - #[no_mangle] - static CPU_EXCEPTION_OF: i32; - #[no_mangle] - static CPU_EXCEPTION_BR: i32; - #[no_mangle] - static CPU_EXCEPTION_UD: i32; - #[no_mangle] - static CPU_EXCEPTION_NM: i32; - #[no_mangle] - static CPU_EXCEPTION_DF: i32; - #[no_mangle] - static CPU_EXCEPTION_TS: i32; - #[no_mangle] - static CPU_EXCEPTION_NP: i32; - #[no_mangle] - static CPU_EXCEPTION_SS: i32; - #[no_mangle] - static CPU_EXCEPTION_GP: i32; - #[no_mangle] - static CPU_EXCEPTION_PF: i32; - #[no_mangle] - static CPU_EXCEPTION_MF: i32; - #[no_mangle] - static CPU_EXCEPTION_AC: i32; - #[no_mangle] - static CPU_EXCEPTION_MC: i32; - #[no_mangle] - static CPU_EXCEPTION_XM: i32; - #[no_mangle] - static CPU_EXCEPTION_VE: i32; - #[no_mangle] - static page_fault: *mut bool; - #[no_mangle] - static a20_enabled: *mut bool; - #[no_mangle] - static instruction_pointer: *mut i32; - #[no_mangle] - static previous_ip: *mut i32; - #[no_mangle] - static idtr_size: *mut i32; - #[no_mangle] - static idtr_offset: *mut i32; - #[no_mangle] - static gdtr_size: *mut i32; - #[no_mangle] - static gdtr_offset: *mut i32; - #[no_mangle] - static cr: *mut i32; - #[no_mangle] - static cpl: *mut u8; - #[no_mangle] - static in_hlt: *mut bool; - #[no_mangle] - static last_virt_eip: *mut i32; - #[no_mangle] - static eip_phys: *mut i32; - #[no_mangle] - static last_virt_esp: *mut i32; - #[no_mangle] - static esp_phys: *mut i32; - #[no_mangle] - static sysenter_cs: *mut i32; - #[no_mangle] - static sysenter_esp: *mut i32; - #[no_mangle] - static sysenter_eip: *mut i32; - #[no_mangle] - static prefixes: *mut u8; - #[no_mangle] - static timestamp_counter: *mut u32; - #[no_mangle] - static sreg: *mut u16; - #[no_mangle] - static dreg: *mut i32; - #[no_mangle] - static fw_value: *mut i32; - #[no_mangle] - static segment_is_null: *mut bool; - #[no_mangle] - static segment_offsets: *mut i32; - #[no_mangle] - static segment_limits: *mut u32; - #[no_mangle] - static protected_mode: *mut bool; - #[no_mangle] - static is_32: *mut bool; - #[no_mangle] - static stack_size_32: *mut bool; - #[no_mangle] - static memory_size: *mut u32; - #[no_mangle] - static fpu_stack_empty: *mut i32; - #[no_mangle] - static mxcsr: *mut i32; - #[no_mangle] - static reg_xmm: *mut reg128; - #[no_mangle] - static current_tsc: *mut u64; - #[no_mangle] - static fpu_st: *mut f64; - #[no_mangle] - static fpu_st8: *mut u8; - #[no_mangle] - static fpu_st32: *mut i32; - #[no_mangle] - static fpu_stack_ptr: *mut u32; - #[no_mangle] - static fpu_control_word: *mut i32; - #[no_mangle] - static fpu_status_word: *mut i32; - #[no_mangle] - static fpu_opcode: *mut i32; - #[no_mangle] - static fpu_ip: *mut i32; - #[no_mangle] - static fpu_ip_selector: *mut i32; - #[no_mangle] - static fpu_dp: *mut i32; - #[no_mangle] - static fpu_dp_selector: *mut i32; - #[no_mangle] - static reg_mmx: *mut reg64; - #[no_mangle] - static opstats_buffer: *mut u32; - #[no_mangle] - static opstats_buffer_0f: *mut u32; - #[no_mangle] - static tlb_data: *mut i32; -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub union reg64 { - i8_0: [i8; 8], - i16_0: [i16; 4], - i32_0: [i32; 2], - i64_0: [i64; 1], - u8_0: [u8; 8], - u16_0: [u16; 4], - u32_0: [u32; 2], - u64_0: [u64; 1], - f32_0: [f32; 2], - f64_0: [f64; 1], -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed { - __f: f32, - __i: u32, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub union reg128 { - i8_0: [i8; 16], - i16_0: [i16; 8], - i32_0: [i32; 4], - i64_0: [i64; 2], - u8_0: [u8; 16], - u16_0: [u16; 8], - u32_0: [u32; 4], - u64_0: [u64; 2], - f32_0: [f32; 4], - f64_0: [f64; 2], -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_0 { - __f: f64, - __i: u64, -} - -unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { - let mut __u: unnamed = unnamed { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { - let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x >= __y) as i32; -} #[no_mangle] pub unsafe extern "C" fn add( mut dest_operand: i32, diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index e38c0859..e7b378e4 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -8,224 +8,37 @@ )] #![feature(extern_types, libc)] -use cpu2::modrm::{resolve_modrm16, resolve_modrm32}; - extern "C" { - #[no_mangle] - fn __fpclassifyl(_: f64) -> i32; - + fn call_interrupt_vector(interrupt: i32, is_software: bool, has_error: bool, error: i32); #[no_mangle] - fn dbg_log(m: *const i8) -> (); + fn cpu_exception_hook(interrupt: i32) -> bool; #[no_mangle] - fn dbg_log1(m: *const i8, x: i32) -> (); + fn dbg_trace(); #[no_mangle] - fn dbg_log2(m: *const i8, x: i32, y: i32) -> (); - #[no_mangle] - fn dbg_log5(m: *const i8, x: i32, y: i32, z: i32, i: i32, j: i32) -> (); - #[no_mangle] - fn dbg_log6(m: *const i8, x: i32, y: i32, z: i32, i: i32, j: i32, k: i32) -> (); - #[no_mangle] - fn dbg_trace() -> (); - #[no_mangle] - fn c_comment(m: *const i8) -> (); - #[no_mangle] - fn call_indirect1(index: i32, arg: i32) -> (); - #[no_mangle] - fn getof() -> bool; - #[no_mangle] - fn getsf() -> bool; - #[no_mangle] - fn getzf() -> bool; - #[no_mangle] - fn getaf() -> bool; - #[no_mangle] - fn getpf() -> bool; - #[no_mangle] - fn getcf() -> bool; - #[no_mangle] - static flags: *mut i32; - #[no_mangle] - static cpl: *mut u8; - #[no_mangle] - fn jit_page_has_code(physical_page: u32) -> bool; - #[no_mangle] - fn in_mapped_range(addr: u32) -> bool; - #[no_mangle] - static cr: *mut i32; - #[no_mangle] - static tlb_data: *mut i32; - #[no_mangle] - static last_virt_esp: *mut i32; - #[no_mangle] - static last_virt_eip: *mut i32; - #[no_mangle] - fn profiler_stat_increment(stat: stat_name) -> (); - #[no_mangle] - fn read_aligned32(addr: u32) -> i32; - #[no_mangle] - fn write_aligned32(addr: u32, value: i32) -> (); - #[no_mangle] - fn call_interrupt_vector( - interrupt_nr: i32, - is_software_int: bool, - has_error_code: bool, - error_code: i32, - ) -> (); - #[no_mangle] - static page_fault: *mut bool; - #[no_mangle] - static previous_ip: *mut i32; - #[no_mangle] - static instruction_pointer: *mut i32; - #[no_mangle] - static eip_phys: *mut i32; - #[no_mangle] - fn read16(addr: u32) -> i32; - #[no_mangle] - fn read32s(addr: u32) -> i32; - #[no_mangle] - static prefixes: *mut u8; - #[no_mangle] - static is_32: *mut bool; - #[no_mangle] - static segment_offsets: *mut i32; - #[no_mangle] - fn cpu_exception_hook(_: i32) -> bool; - #[no_mangle] - static segment_is_null: *mut bool; - #[no_mangle] - static protected_mode: *mut bool; - #[no_mangle] - fn run_instruction(opcode: i32) -> (); - #[no_mangle] - fn logop(_: i32, _: i32) -> (); - #[no_mangle] - static timestamp_counter: *mut u32; - #[no_mangle] - fn profiler_stat_increment_by(stat: stat_name, by: i32) -> (); - #[no_mangle] - static stack_size_32: *mut bool; - #[no_mangle] - fn jit_increase_hotness_and_maybe_compile( - phys_addr: u32, - cs_offset: u32, - flags_0: cached_state_flags, - ) -> (); - #[no_mangle] - fn jit_find_cache_entry(phys_addr: u32, flags_0: cached_state_flags) -> u32; - #[no_mangle] - static in_hlt: *mut bool; - #[no_mangle] - fn read8(addr: u32) -> i32; - #[no_mangle] - fn read_aligned16(addr: u32) -> i32; - #[no_mangle] - fn write8(addr: u32, value: i32) -> (); - #[no_mangle] - fn read64s(addr: u32) -> i64; - #[no_mangle] - fn read128(addr: u32) -> reg128; - #[no_mangle] - fn write16(addr: u32, value: i32) -> (); - #[no_mangle] - fn write32(addr: u32, value: i32) -> (); - #[no_mangle] - fn write64(addr: u32, value: i64) -> (); - #[no_mangle] - fn write128(addr: u32, value: reg128) -> (); - #[no_mangle] - static reg8: *mut u8; - #[no_mangle] - static reg16: *mut u16; - #[no_mangle] - static reg32s: *mut i32; - #[no_mangle] - static reg_mmx: *mut reg64; - #[no_mangle] - static reg_xmm: *mut reg128; + fn logop(addr: i32, op: i32); #[no_mangle] fn microtick() -> f64; #[no_mangle] - static opstats_buffer_0f: *mut u32; - #[no_mangle] - static opstats_buffer: *mut u32; - #[no_mangle] - static reg8s: *mut i8; - #[no_mangle] - static reg16s: *mut i16; - #[no_mangle] - static last_op1: *mut i32; - #[no_mangle] - static last_op2: *mut i32; - #[no_mangle] - static last_op_size: *mut i32; - #[no_mangle] - static last_add_result: *mut i32; - #[no_mangle] - static last_result: *mut i32; - #[no_mangle] - static flags_changed: *mut i32; - #[no_mangle] - static a20_enabled: *mut bool; - #[no_mangle] - static idtr_size: *mut i32; - #[no_mangle] - static idtr_offset: *mut i32; - #[no_mangle] - static gdtr_size: *mut i32; - #[no_mangle] - static gdtr_offset: *mut i32; - #[no_mangle] - static esp_phys: *mut i32; - #[no_mangle] - static sysenter_cs: *mut i32; - #[no_mangle] - static sysenter_esp: *mut i32; - #[no_mangle] - static sysenter_eip: *mut i32; - #[no_mangle] - static sreg: *mut u16; - #[no_mangle] - static dreg: *mut i32; - #[no_mangle] - static fw_value: *mut i32; - #[no_mangle] - static segment_limits: *mut u32; - #[no_mangle] - static memory_size: *mut u32; - #[no_mangle] - static fpu_stack_empty: *mut i32; - #[no_mangle] - static mxcsr: *mut i32; - #[no_mangle] - static current_tsc: *mut u64; - #[no_mangle] - static fpu_st: *mut f64; - #[no_mangle] - static fpu_st8: *mut u8; - #[no_mangle] - static fpu_st32: *mut i32; - #[no_mangle] - static fpu_stack_ptr: *mut u32; - #[no_mangle] - static fpu_control_word: *mut i32; - #[no_mangle] - static fpu_status_word: *mut i32; - #[no_mangle] - static fpu_opcode: *mut i32; - #[no_mangle] - static fpu_ip: *mut i32; - #[no_mangle] - static fpu_ip_selector: *mut i32; - #[no_mangle] - static fpu_dp: *mut i32; - #[no_mangle] - static fpu_dp_selector: *mut i32; + fn call_indirect1(f: i32, x: u16); #[no_mangle] - static mut profiler_stat_arr: [profiler_stat; 37]; + fn jit_page_has_code(addr: u32) -> bool; + #[no_mangle] + fn jit_find_cache_entry(addr: u32, flags: u8) -> u32; + #[no_mangle] + fn jit_increase_hotness_and_maybe_compile(phys_address: u32, cs_offset: u32, state_flags: u8); } + +use cpu2::global_pointers::*; +use cpu2::memory::{ + in_mapped_range, read128, read16, read32s, read64s, read8, read_aligned16, read_aligned32, + write128, write16, write32, write64, write8, write_aligned32, +}; +use cpu2::misc_instr::{getaf, getcf, getof, getpf, getsf, getzf}; +use cpu2::modrm::{resolve_modrm16, resolve_modrm32}; +use cpu2::profiler::{profiler_stat_increment, profiler_stat_increment_by}; + pub const S_TRIGGER_CPU_EXCEPTION: stat_name = 14; pub const S_CACHE_MISMATCH: stat_name = 6; @@ -257,12 +70,6 @@ pub union reg64 { } pub const S_SAFE_READ32_SLOW_IN_MAPPED_RANGE: stat_name = 19; -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed { - __f: f64, - __i: u64, -} pub const S_RUN_INTERPRETED_STEPS: stat_name = 11; pub const S_RUN_FROM_CACHE: stat_name = 12; @@ -301,12 +108,7 @@ pub struct profiler_stat { pub const S_COMPILE_CUT_OFF_AT_END_OF_PAGE: stat_name = 2; pub const S_RUN_INTERPRETED_DIFFERENT_STATE: stat_name = 10; pub const S_COMPILE_ENTRY_POINT: stat_name = 5; -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_0 { - __f: f32, - __i: u32, -} + pub const S_CLEAR_TLB: stat_name = 33; pub const S_RUN_INTERPRETED_NEAR_END_OF_PAGE: stat_name = 9; pub const S_COMPILE_WITH_LOOP_SAFETY: stat_name = 3; @@ -319,376 +121,7 @@ pub const S_INVALIDATE_PAGE: stat_name = 30; pub const S_SAFE_READ32_FAST: stat_name = 15; pub const S_SAFE_READ32_SLOW_PAGE_CROSSED: stat_name = 16; -unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { - let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { - let mut __u: unnamed = unnamed { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x >= __y) as i32; -} + #[no_mangle] pub static mut FLAG_CARRY: i32 = unsafe { 1i32 }; #[no_mangle] @@ -1339,6 +772,9 @@ pub static mut CPU_EXCEPTION_MC: i32 = unsafe { 18i32 }; pub static mut CPU_EXCEPTION_XM: i32 = unsafe { 19i32 }; #[no_mangle] pub static mut CPU_EXCEPTION_VE: i32 = unsafe { 20i32 }; + +//pub fn call_indirect1(f: fn(u16), x: u16) { f(x); } + #[no_mangle] pub unsafe extern "C" fn after_block_boundary() -> () { jit_block_boundary = 0 != 1i32; } #[no_mangle] @@ -1869,6 +1305,15 @@ pub unsafe extern "C" fn modrm_resolve(mut modrm_byte: i32) -> Result { resolve_modrm16(modrm_byte) } } + +pub unsafe extern "C" fn run_instruction(opcode: i32) { ::gen::interpreter::run(opcode as u32) } +pub unsafe extern "C" fn run_instruction0f_16(opcode: i32) { + ::gen::interpreter0f_16::run(opcode as u8) +} +pub unsafe extern "C" fn run_instruction0f_32(opcode: i32) { + ::gen::interpreter0f_32::run(opcode as u8) +} + #[no_mangle] pub unsafe extern "C" fn cycle_internal() -> () { profiler_stat_increment(S_CYCLE_INTERNAL); @@ -1887,7 +1332,7 @@ pub unsafe extern "C" fn cycle_internal() -> () { initial_state = (entry >> 16i32) as u16; call_indirect1( (wasm_table_index as u32).wrapping_add(256i32 as u32) as i32, - initial_state as i32, + initial_state, ); clear_current_cpu_exception(); profiler_stat_increment_by( diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 24917671..1016f252 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -9,472 +9,15 @@ #![feature(extern_types, libc)] use cpu2::cpu::*; +use cpu2::global_pointers::*; -extern "C" { - - #[no_mangle] - fn __fpclassifyl(_: f64) -> i32; - #[no_mangle] - fn ceil(_: f64) -> f64; - #[no_mangle] - fn floor(_: f64) -> f64; - #[no_mangle] - fn fmod(_: f64, _: f64) -> f64; - #[no_mangle] - fn pow(_: f64, _: f64) -> f64; - #[no_mangle] - fn round(_: f64) -> f64; - #[no_mangle] - fn trunc(_: f64) -> f64; - #[no_mangle] - static FLAG_CARRY: i32; - #[no_mangle] - static FLAG_PARITY: i32; - #[no_mangle] - static FLAG_ADJUST: i32; - #[no_mangle] - static FLAG_ZERO: i32; - #[no_mangle] - static FLAG_SIGN: i32; - #[no_mangle] - static FLAG_TRAP: i32; - #[no_mangle] - static FLAG_INTERRUPT: i32; - #[no_mangle] - static FLAG_DIRECTION: i32; - #[no_mangle] - static FLAG_OVERFLOW: i32; - #[no_mangle] - static FLAG_IOPL: i32; - #[no_mangle] - static FLAG_NT: i32; - #[no_mangle] - static FLAG_RF: i32; - #[no_mangle] - static FLAG_VM: i32; - #[no_mangle] - static FLAG_AC: i32; - #[no_mangle] - static FLAG_VIF: i32; - #[no_mangle] - static FLAG_VIP: i32; - #[no_mangle] - static FLAG_ID: i32; - #[no_mangle] - static FLAGS_DEFAULT: i32; - #[no_mangle] - static FLAGS_MASK: i32; - #[no_mangle] - static FLAGS_ALL: i32; - #[no_mangle] - static OPSIZE_8: i32; - #[no_mangle] - static OPSIZE_16: i32; - #[no_mangle] - static OPSIZE_32: i32; - #[no_mangle] - static EAX: i32; - #[no_mangle] - static ECX: i32; - #[no_mangle] - static EDX: i32; - #[no_mangle] - static EBX: i32; - #[no_mangle] - static ESP: i32; - #[no_mangle] - static EBP: i32; - #[no_mangle] - static ESI: i32; - #[no_mangle] - static EDI: i32; - #[no_mangle] - static AX: i32; - #[no_mangle] - static CX: i32; - #[no_mangle] - static DX: i32; - #[no_mangle] - static BX: i32; - #[no_mangle] - static SP: i32; - #[no_mangle] - static BP: i32; - #[no_mangle] - static SI: i32; - #[no_mangle] - static DI: i32; - #[no_mangle] - static AL: i32; - #[no_mangle] - static CL: i32; - #[no_mangle] - static DL: i32; - #[no_mangle] - static BL: i32; - #[no_mangle] - static AH: i32; - #[no_mangle] - static CH: i32; - #[no_mangle] - static DH: i32; - #[no_mangle] - static BH: i32; - #[no_mangle] - static ES: i32; - #[no_mangle] - static CS: i32; - #[no_mangle] - static SS: i32; - #[no_mangle] - static DS: i32; - #[no_mangle] - static FS: i32; - #[no_mangle] - static GS: i32; - #[no_mangle] - static TR: i32; - #[no_mangle] - static LDTR: i32; - #[no_mangle] - static PAGE_TABLE_PRESENT_MASK: i32; - #[no_mangle] - static PAGE_TABLE_RW_MASK: i32; - #[no_mangle] - static PAGE_TABLE_USER_MASK: i32; - #[no_mangle] - static PAGE_TABLE_ACCESSED_MASK: i32; - #[no_mangle] - static PAGE_TABLE_DIRTY_MASK: i32; - #[no_mangle] - static PAGE_TABLE_PSE_MASK: i32; - #[no_mangle] - static PAGE_TABLE_GLOBAL_MASK: i32; - #[no_mangle] - static MMAP_BLOCK_BITS: i32; - #[no_mangle] - static MMAP_BLOCK_SIZE: i32; - #[no_mangle] - static CR0_PE: i32; - #[no_mangle] - static CR0_MP: i32; - #[no_mangle] - static CR0_EM: i32; - #[no_mangle] - static CR0_TS: i32; - #[no_mangle] - static CR0_ET: i32; - #[no_mangle] - static CR0_WP: i32; - #[no_mangle] - static CR0_NW: i32; - #[no_mangle] - static CR0_CD: i32; - #[no_mangle] - static CR0_PG: i32; - #[no_mangle] - static CR4_VME: i32; - #[no_mangle] - static CR4_PVI: i32; - #[no_mangle] - static CR4_TSD: i32; - #[no_mangle] - static CR4_PSE: i32; - #[no_mangle] - static CR4_DE: i32; - #[no_mangle] - static CR4_PAE: i32; - #[no_mangle] - static CR4_PGE: i32; - #[no_mangle] - static IA32_SYSENTER_CS: i32; - #[no_mangle] - static IA32_SYSENTER_ESP: i32; - #[no_mangle] - static IA32_SYSENTER_EIP: i32; - #[no_mangle] - static IA32_TIME_STAMP_COUNTER: i32; - #[no_mangle] - static IA32_PLATFORM_ID: i32; - #[no_mangle] - static IA32_APIC_BASE_MSR: i32; - #[no_mangle] - static IA32_BIOS_SIGN_ID: i32; - #[no_mangle] - static MSR_PLATFORM_INFO: i32; - #[no_mangle] - static MSR_MISC_FEATURE_ENABLES: i32; - #[no_mangle] - static IA32_MISC_ENABLE: i32; - #[no_mangle] - static IA32_RTIT_CTL: i32; - #[no_mangle] - static MSR_SMI_COUNT: i32; - #[no_mangle] - static IA32_MCG_CAP: i32; - #[no_mangle] - static IA32_KERNEL_GS_BASE: i32; - #[no_mangle] - static MSR_PKG_C2_RESIDENCY: i32; - #[no_mangle] - static IA32_APIC_BASE_BSP: i32; - #[no_mangle] - static IA32_APIC_BASE_EXTD: i32; - #[no_mangle] - static IA32_APIC_BASE_EN: i32; - #[no_mangle] - static APIC_ADDRESS: i32; - #[no_mangle] - static SEG_PREFIX_NONE: i32; - #[no_mangle] - static SEG_PREFIX_ZERO: i32; - #[no_mangle] - static PREFIX_MASK_REP: i32; - #[no_mangle] - static PREFIX_REPZ: i32; - #[no_mangle] - static PREFIX_REPNZ: i32; - #[no_mangle] - static PREFIX_MASK_SEGMENT: i32; - #[no_mangle] - static PREFIX_MASK_OPSIZE: i32; - #[no_mangle] - static PREFIX_MASK_ADDRSIZE: i32; - #[no_mangle] - static PREFIX_F2: i32; - #[no_mangle] - static PREFIX_F3: i32; - #[no_mangle] - static PREFIX_66: i32; - #[no_mangle] - static LOG_CPU: i32; - #[no_mangle] - static A20_MASK: i32; - #[no_mangle] - static A20_MASK16: i32; - #[no_mangle] - static A20_MASK32: i32; - #[no_mangle] - static MXCSR_MASK: i32; - - #[no_mangle] - fn dbg_log(m: *const i8) -> (); - #[no_mangle] - fn c_comment(m: *const i8) -> (); - #[no_mangle] - fn isnan_XXX(f: f64) -> bool; - #[no_mangle] - fn isfinite_XXX(f: f64) -> bool; - #[no_mangle] - static mut mem8: *mut u8; - #[no_mangle] - static mut mem16: *mut u16; - #[no_mangle] - static mut mem32s: *mut i32; - #[no_mangle] - static mut jit_block_boundary: bool; - #[no_mangle] - static VALID_TLB_ENTRY_MAX: i32; - #[no_mangle] - static mut valid_tlb_entries: [i32; 10000]; - #[no_mangle] - static mut valid_tlb_entries_count: i32; - #[no_mangle] - static TLB_VALID: i32; - #[no_mangle] - static TLB_READONLY: i32; - #[no_mangle] - static TLB_NO_USER: i32; - #[no_mangle] - static TLB_IN_MAPPED_RANGE: i32; - #[no_mangle] - static TLB_GLOBAL: i32; - #[no_mangle] - static TLB_HAS_CODE: i32; - #[no_mangle] - static CPU_EXCEPTION_DE: i32; - #[no_mangle] - static CPU_EXCEPTION_DB: i32; - #[no_mangle] - static CPU_EXCEPTION_NMI: i32; - #[no_mangle] - static CPU_EXCEPTION_BP: i32; - #[no_mangle] - static CPU_EXCEPTION_OF: i32; - #[no_mangle] - static CPU_EXCEPTION_BR: i32; - #[no_mangle] - static CPU_EXCEPTION_UD: i32; - #[no_mangle] - static CPU_EXCEPTION_NM: i32; - #[no_mangle] - static CPU_EXCEPTION_DF: i32; - #[no_mangle] - static CPU_EXCEPTION_TS: i32; - #[no_mangle] - static CPU_EXCEPTION_NP: i32; - #[no_mangle] - static CPU_EXCEPTION_SS: i32; - #[no_mangle] - static CPU_EXCEPTION_GP: i32; - #[no_mangle] - static CPU_EXCEPTION_PF: i32; - #[no_mangle] - static CPU_EXCEPTION_MF: i32; - #[no_mangle] - static CPU_EXCEPTION_AC: i32; - #[no_mangle] - static CPU_EXCEPTION_MC: i32; - #[no_mangle] - static CPU_EXCEPTION_XM: i32; - #[no_mangle] - static CPU_EXCEPTION_VE: i32; - #[no_mangle] - fn is_osize_32() -> bool; - #[no_mangle] - fn trigger_ud() -> (); - #[no_mangle] - static fpu_stack_ptr: *mut u32; - #[no_mangle] - static fpu_st: *mut f64; - #[no_mangle] - static fpu_status_word: *mut i32; - #[no_mangle] - static fpu_stack_empty: *mut i32; - #[no_mangle] - static fpu_control_word: *mut i32; - #[no_mangle] - static flags: *mut i32; - #[no_mangle] - static flags_changed: *mut i32; - #[no_mangle] - static fpu_opcode: *mut i32; - #[no_mangle] - static fpu_dp: *mut i32; - #[no_mangle] - static fpu_ip: *mut i32; - #[no_mangle] - fn convert_f64_to_i32(_: f64) -> i32; - #[no_mangle] - static DEBUG: bool; - #[no_mangle] - static fpu_dp_selector: *mut i32; - #[no_mangle] - static fpu_ip_selector: *mut i32; - #[no_mangle] - static reg16: *mut u16; - #[no_mangle] - static fpu_st8: *mut u8; - #[no_mangle] - static reg8: *mut u8; - #[no_mangle] - static reg8s: *mut i8; - #[no_mangle] - static reg16s: *mut i16; - #[no_mangle] - static reg32s: *mut i32; - #[no_mangle] - static last_op1: *mut i32; - #[no_mangle] - static last_op2: *mut i32; - #[no_mangle] - static last_op_size: *mut i32; - #[no_mangle] - static last_add_result: *mut i32; - #[no_mangle] - static last_result: *mut i32; - #[no_mangle] - static page_fault: *mut bool; - #[no_mangle] - static a20_enabled: *mut bool; - #[no_mangle] - static instruction_pointer: *mut i32; - #[no_mangle] - static previous_ip: *mut i32; - #[no_mangle] - static idtr_size: *mut i32; - #[no_mangle] - static idtr_offset: *mut i32; - #[no_mangle] - static gdtr_size: *mut i32; - #[no_mangle] - static gdtr_offset: *mut i32; - #[no_mangle] - static cr: *mut i32; - #[no_mangle] - static cpl: *mut u8; - #[no_mangle] - static in_hlt: *mut bool; - #[no_mangle] - static last_virt_eip: *mut i32; - #[no_mangle] - static eip_phys: *mut i32; - #[no_mangle] - static last_virt_esp: *mut i32; - #[no_mangle] - static esp_phys: *mut i32; - #[no_mangle] - static sysenter_cs: *mut i32; - #[no_mangle] - static sysenter_esp: *mut i32; - #[no_mangle] - static sysenter_eip: *mut i32; - #[no_mangle] - static prefixes: *mut u8; - #[no_mangle] - static timestamp_counter: *mut u32; - #[no_mangle] - static sreg: *mut u16; - #[no_mangle] - static dreg: *mut i32; - #[no_mangle] - static fw_value: *mut i32; - #[no_mangle] - static segment_is_null: *mut bool; - #[no_mangle] - static segment_offsets: *mut i32; - #[no_mangle] - static segment_limits: *mut u32; - #[no_mangle] - static protected_mode: *mut bool; - #[no_mangle] - static is_32: *mut bool; - #[no_mangle] - static stack_size_32: *mut bool; - #[no_mangle] - static memory_size: *mut u32; - #[no_mangle] - static mxcsr: *mut i32; - #[no_mangle] - static reg_xmm: *mut reg128; - #[no_mangle] - static current_tsc: *mut u64; - #[no_mangle] - static fpu_st32: *mut i32; - #[no_mangle] - static reg_mmx: *mut reg64; - #[no_mangle] - static opstats_buffer: *mut u32; - #[no_mangle] - static opstats_buffer_0f: *mut u32; - #[no_mangle] - static tlb_data: *mut i32; -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub union reg64 { - i8_0: [i8; 8], - i16_0: [i16; 4], - i32_0: [i32; 2], - i64_0: [i64; 1], - u8_0: [u8; 8], - u16_0: [u16; 4], - u32_0: [u32; 2], - u64_0: [u64; 1], - f32_0: [f32; 2], - f64_0: [f64; 1], -} +pub fn round(x: f64) -> f64 { x.round() } +pub fn floor(x: f64) -> f64 { x.floor() } +pub fn ceil(x: f64) -> f64 { x.ceil() } +pub fn pow(x: f64, y: f64) -> f64 { x.powf(y) } +pub fn convert_f64_to_i32(x: f64) -> i32 { x as i32 } +pub fn trunc(x: f64) -> f64 { x.trunc() } +pub fn fmod(x: f64, y: f64) -> f64 { x % y } #[derive(Copy, Clone)] #[repr(C)] @@ -492,404 +35,7 @@ pub union f32_int { i32_0: i32, f32_0: f32, } -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed { - __f: f32, - __i: u32, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union reg128 { - i8_0: [i8; 16], - i16_0: [i16; 8], - i32_0: [i32; 4], - i64_0: [i64; 2], - u8_0: [u8; 16], - u16_0: [u16; 8], - u32_0: [u32; 4], - u64_0: [u64; 2], - f32_0: [f32; 4], - f64_0: [f64; 2], -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_0 { - __f: f64, - __i: u64, -} -unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { - let mut __u: unnamed = unnamed { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { - let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x >= __y) as i32; -} #[no_mangle] pub static mut M_LOG2E: f64 = unsafe { 1.4426950408889634f64 }; #[no_mangle] @@ -1375,7 +521,7 @@ pub unsafe extern "C" fn fpu_load_tag_word() -> i32 { else if value == 0i32 as f64 { tag_word |= 1i32 << (i << 1i32) } - else if !isfinite_XXX(value) { + else if !value.is_finite() { tag_word |= 2i32 << (i << 1i32) } i += 1 @@ -1444,7 +590,7 @@ pub unsafe extern "C" fn fpu_fsubr(mut target_index: i32, mut val: f64) -> () { #[no_mangle] pub unsafe extern "C" fn fpu_ftst(mut x: f64) -> () { *fpu_status_word &= !FPU_RESULT_FLAGS; - if isnan_XXX(x) { + if x.is_nan() { *fpu_status_word |= FPU_C3 | FPU_C2 | FPU_C0 } else if x == 0i32 as f64 { @@ -1488,7 +634,7 @@ pub unsafe extern "C" fn fpu_fxam(mut x: f64) -> () { if 0 != *fpu_stack_empty >> *fpu_stack_ptr & 1i32 { *fpu_status_word |= FPU_C3 | FPU_C0 } - else if isnan_XXX(x) { + else if x.is_nan() { *fpu_status_word |= FPU_C0 } else if x == 0i32 as f64 { diff --git a/src/rust/cpu2/global_pointers.rs b/src/rust/cpu2/global_pointers.rs index fceaaa97..6b01b09a 100644 --- a/src/rust/cpu2/global_pointers.rs +++ b/src/rust/cpu2/global_pointers.rs @@ -8,628 +8,8 @@ )] #![feature(extern_types, libc)] -extern "C" { - pub type reg128; +use cpu2::cpu::{reg128, reg64}; - pub type reg64; - #[no_mangle] - fn __fpclassifyl(_: f64) -> i32; - #[no_mangle] - static FLAG_CARRY: i32; - #[no_mangle] - static FLAG_PARITY: i32; - #[no_mangle] - static FLAG_ADJUST: i32; - #[no_mangle] - static FLAG_ZERO: i32; - #[no_mangle] - static FLAG_SIGN: i32; - #[no_mangle] - static FLAG_TRAP: i32; - #[no_mangle] - static FLAG_INTERRUPT: i32; - #[no_mangle] - static FLAG_DIRECTION: i32; - #[no_mangle] - static FLAG_OVERFLOW: i32; - #[no_mangle] - static FLAG_IOPL: i32; - #[no_mangle] - static FLAG_NT: i32; - #[no_mangle] - static FLAG_RF: i32; - #[no_mangle] - static FLAG_VM: i32; - #[no_mangle] - static FLAG_AC: i32; - #[no_mangle] - static FLAG_VIF: i32; - #[no_mangle] - static FLAG_VIP: i32; - #[no_mangle] - static FLAG_ID: i32; - #[no_mangle] - static FLAGS_DEFAULT: i32; - #[no_mangle] - static FLAGS_MASK: i32; - #[no_mangle] - static FLAGS_ALL: i32; - #[no_mangle] - static OPSIZE_8: i32; - #[no_mangle] - static OPSIZE_16: i32; - #[no_mangle] - static OPSIZE_32: i32; - #[no_mangle] - static EAX: i32; - #[no_mangle] - static ECX: i32; - #[no_mangle] - static EDX: i32; - #[no_mangle] - static EBX: i32; - #[no_mangle] - static ESP: i32; - #[no_mangle] - static EBP: i32; - #[no_mangle] - static ESI: i32; - #[no_mangle] - static EDI: i32; - #[no_mangle] - static AX: i32; - #[no_mangle] - static CX: i32; - #[no_mangle] - static DX: i32; - #[no_mangle] - static BX: i32; - #[no_mangle] - static SP: i32; - #[no_mangle] - static BP: i32; - #[no_mangle] - static SI: i32; - #[no_mangle] - static DI: i32; - #[no_mangle] - static AL: i32; - #[no_mangle] - static CL: i32; - #[no_mangle] - static DL: i32; - #[no_mangle] - static BL: i32; - #[no_mangle] - static AH: i32; - #[no_mangle] - static CH: i32; - #[no_mangle] - static DH: i32; - #[no_mangle] - static BH: i32; - #[no_mangle] - static ES: i32; - #[no_mangle] - static CS: i32; - #[no_mangle] - static SS: i32; - #[no_mangle] - static DS: i32; - #[no_mangle] - static FS: i32; - #[no_mangle] - static GS: i32; - #[no_mangle] - static TR: i32; - #[no_mangle] - static LDTR: i32; - #[no_mangle] - static PAGE_TABLE_PRESENT_MASK: i32; - #[no_mangle] - static PAGE_TABLE_RW_MASK: i32; - #[no_mangle] - static PAGE_TABLE_USER_MASK: i32; - #[no_mangle] - static PAGE_TABLE_ACCESSED_MASK: i32; - #[no_mangle] - static PAGE_TABLE_DIRTY_MASK: i32; - #[no_mangle] - static PAGE_TABLE_PSE_MASK: i32; - #[no_mangle] - static PAGE_TABLE_GLOBAL_MASK: i32; - #[no_mangle] - static MMAP_BLOCK_BITS: i32; - #[no_mangle] - static MMAP_BLOCK_SIZE: i32; - #[no_mangle] - static CR0_PE: i32; - #[no_mangle] - static CR0_MP: i32; - #[no_mangle] - static CR0_EM: i32; - #[no_mangle] - static CR0_TS: i32; - #[no_mangle] - static CR0_ET: i32; - #[no_mangle] - static CR0_WP: i32; - #[no_mangle] - static CR0_NW: i32; - #[no_mangle] - static CR0_CD: i32; - #[no_mangle] - static CR0_PG: i32; - #[no_mangle] - static CR4_VME: i32; - #[no_mangle] - static CR4_PVI: i32; - #[no_mangle] - static CR4_TSD: i32; - #[no_mangle] - static CR4_PSE: i32; - #[no_mangle] - static CR4_DE: i32; - #[no_mangle] - static CR4_PAE: i32; - #[no_mangle] - static CR4_PGE: i32; - #[no_mangle] - static IA32_SYSENTER_CS: i32; - #[no_mangle] - static IA32_SYSENTER_ESP: i32; - #[no_mangle] - static IA32_SYSENTER_EIP: i32; - #[no_mangle] - static IA32_TIME_STAMP_COUNTER: i32; - #[no_mangle] - static IA32_PLATFORM_ID: i32; - #[no_mangle] - static IA32_APIC_BASE_MSR: i32; - #[no_mangle] - static IA32_BIOS_SIGN_ID: i32; - #[no_mangle] - static MSR_PLATFORM_INFO: i32; - #[no_mangle] - static MSR_MISC_FEATURE_ENABLES: i32; - #[no_mangle] - static IA32_MISC_ENABLE: i32; - #[no_mangle] - static IA32_RTIT_CTL: i32; - #[no_mangle] - static MSR_SMI_COUNT: i32; - #[no_mangle] - static IA32_MCG_CAP: i32; - #[no_mangle] - static IA32_KERNEL_GS_BASE: i32; - #[no_mangle] - static MSR_PKG_C2_RESIDENCY: i32; - #[no_mangle] - static IA32_APIC_BASE_BSP: i32; - #[no_mangle] - static IA32_APIC_BASE_EXTD: i32; - #[no_mangle] - static IA32_APIC_BASE_EN: i32; - #[no_mangle] - static APIC_ADDRESS: i32; - #[no_mangle] - static SEG_PREFIX_NONE: i32; - #[no_mangle] - static SEG_PREFIX_ZERO: i32; - #[no_mangle] - static PREFIX_MASK_REP: i32; - #[no_mangle] - static PREFIX_REPZ: i32; - #[no_mangle] - static PREFIX_REPNZ: i32; - #[no_mangle] - static PREFIX_MASK_SEGMENT: i32; - #[no_mangle] - static PREFIX_MASK_OPSIZE: i32; - #[no_mangle] - static PREFIX_MASK_ADDRSIZE: i32; - #[no_mangle] - static PREFIX_F2: i32; - #[no_mangle] - static PREFIX_F3: i32; - #[no_mangle] - static PREFIX_66: i32; - #[no_mangle] - static LOG_CPU: i32; - #[no_mangle] - static A20_MASK: i32; - #[no_mangle] - static A20_MASK16: i32; - #[no_mangle] - static A20_MASK32: i32; - #[no_mangle] - static MXCSR_MASK: i32; - -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed { - __f: f32, - __i: u32, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_0 { - __f: f64, - __i: u64, -} -unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { - let mut __u: unnamed = unnamed { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { - let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x >= __y) as i32; -} #[no_mangle] pub static mut reg8: *mut u8 = unsafe { 4i32 as *mut u8 }; #[no_mangle] diff --git a/src/rust/cpu2/imports.rs b/src/rust/cpu2/imports.rs index 59c24654..28399930 100644 --- a/src/rust/cpu2/imports.rs +++ b/src/rust/cpu2/imports.rs @@ -1,22 +1,5 @@ use std::alloc; -#[no_mangle] -pub unsafe extern "C" fn run_instruction(opcode: u32) { ::gen::interpreter::run(opcode) } -#[no_mangle] -pub unsafe extern "C" fn run_instruction0f_16(opcode: u32) { - ::gen::interpreter0f_16::run(opcode as u8) -} -#[no_mangle] -pub unsafe extern "C" fn run_instruction0f_32(opcode: u32) { - ::gen::interpreter0f_32::run(opcode as u8) -} - -#[no_mangle] -pub fn sqrt(x: f64) -> f64 { x.sqrt() } - -#[no_mangle] -pub fn sqrtf(x: f32) -> f32 { x.sqrt() } - #[no_mangle] pub fn call_indirect1(f: fn(u16), x: u16) { f(x); } diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index e8755bfd..0ba192e4 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -8,1411 +8,50 @@ )] #![feature(extern_types, libc)] -use cpu2::cpu::*; -use cpu2::fpu::{fpu_load_m32, fpu_load_m64}; -use cpu2::misc_instr::{pop16, pop32s, push16, push32}; - extern "C" { + #[no_mangle] + fn switch_seg(seg: i32, value: i32) -> bool; + #[no_mangle] + fn lss16(x: i32, y: i32, z: i32); + #[no_mangle] + fn lss32(x: i32, y: i32, z: i32); + #[no_mangle] + fn enter16(size: i32, nesting_level: i32); + #[no_mangle] + fn enter32(size: i32, nesting_level: i32); #[no_mangle] - fn add8(x: i32, y: i32) -> i32; + fn popa16(); #[no_mangle] - fn add16(x: i32, y: i32) -> i32; + fn popa32(); #[no_mangle] - fn add32(x: i32, y: i32) -> i32; + fn arpl(seg: i32, r: i32) -> i32; #[no_mangle] - fn sub8(x: i32, y: i32) -> i32; + fn far_jump(eip: i32, selector: i32, is_call: bool); #[no_mangle] - fn sub16(x: i32, y: i32) -> i32; + fn far_return(eip: i32, selector: i32, stack_adjust: i32); #[no_mangle] - fn sub32(x: i32, y: i32) -> i32; + fn call_interrupt_vector(interrupt: i32, is_software: bool, has_error: bool, error: i32); #[no_mangle] - fn adc8(x: i32, y: i32) -> i32; + fn iret16(); #[no_mangle] - fn adc16(x: i32, y: i32) -> i32; - #[no_mangle] - fn adc32(x: i32, y: i32) -> i32; - #[no_mangle] - fn sbb8(x: i32, y: i32) -> i32; - #[no_mangle] - fn sbb16(x: i32, y: i32) -> i32; - #[no_mangle] - fn sbb32(x: i32, y: i32) -> i32; - #[no_mangle] - fn cmp8(x: i32, y: i32) -> (); - #[no_mangle] - fn cmp16(x: i32, y: i32) -> (); - #[no_mangle] - fn cmp32(x: i32, y: i32) -> (); - #[no_mangle] - fn inc8(x: i32) -> i32; - #[no_mangle] - fn inc16(x: i32) -> i32; - #[no_mangle] - fn inc32(x: i32) -> i32; - #[no_mangle] - fn dec8(x: i32) -> i32; - #[no_mangle] - fn dec16(x: i32) -> i32; - #[no_mangle] - fn dec32(x: i32) -> i32; - #[no_mangle] - fn neg8(x: i32) -> i32; - #[no_mangle] - fn neg16(x: i32) -> i32; - #[no_mangle] - fn neg32(x: i32) -> i32; - #[no_mangle] - fn mul8(source_operand: i32) -> (); - #[no_mangle] - fn imul8(source_operand: i32) -> (); - #[no_mangle] - fn mul16(source_operand: u32) -> (); - #[no_mangle] - fn imul16(source_operand: i32) -> (); - #[no_mangle] - fn imul_reg16(operand1: i32, operand2: i32) -> i32; - #[no_mangle] - fn mul32(source_operand: i32) -> (); - #[no_mangle] - fn imul32(source_operand: i32) -> (); - #[no_mangle] - fn imul_reg32(operand1: i32, operand2: i32) -> i32; - #[no_mangle] - fn bcd_daa() -> (); - #[no_mangle] - fn bcd_das() -> (); - #[no_mangle] - fn bcd_aad(imm8: i32) -> (); - #[no_mangle] - fn bcd_aam(imm8: i32) -> (); - #[no_mangle] - fn bcd_aaa() -> (); - #[no_mangle] - fn bcd_aas() -> (); - #[no_mangle] - fn and8(x: i32, y: i32) -> i32; - #[no_mangle] - fn and16(x: i32, y: i32) -> i32; - #[no_mangle] - fn and32(x: i32, y: i32) -> i32; - #[no_mangle] - fn test8(x: i32, y: i32) -> (); - #[no_mangle] - fn test16(x: i32, y: i32) -> (); - #[no_mangle] - fn test32(x: i32, y: i32) -> (); - #[no_mangle] - fn or8(x: i32, y: i32) -> i32; - #[no_mangle] - fn or16(x: i32, y: i32) -> i32; - #[no_mangle] - fn or32(x: i32, y: i32) -> i32; - #[no_mangle] - fn xor8(x: i32, y: i32) -> i32; - #[no_mangle] - fn xor16(x: i32, y: i32) -> i32; - #[no_mangle] - fn xor32(x: i32, y: i32) -> i32; - #[no_mangle] - fn rol8(dest_operand: i32, count: i32) -> i32; - #[no_mangle] - fn rol16(dest_operand: i32, count: i32) -> i32; - #[no_mangle] - fn rol32(dest_operand: i32, count: i32) -> i32; - #[no_mangle] - fn rcl8(dest_operand: i32, count: i32) -> i32; - #[no_mangle] - fn rcl16(dest_operand: i32, count: i32) -> i32; - #[no_mangle] - fn rcl32(dest_operand: i32, count: i32) -> i32; - #[no_mangle] - fn ror8(dest_operand: i32, count: i32) -> i32; - #[no_mangle] - fn ror16(dest_operand: i32, count: i32) -> i32; - #[no_mangle] - fn ror32(dest_operand: i32, count: i32) -> i32; - #[no_mangle] - fn rcr8(dest_operand: i32, count: i32) -> i32; - #[no_mangle] - fn rcr16(dest_operand: i32, count: i32) -> i32; - #[no_mangle] - fn rcr32(dest_operand: i32, count: i32) -> i32; - #[no_mangle] - fn div8(source_operand: u32) -> (); - #[no_mangle] - fn idiv8(source_operand: i32) -> (); - #[no_mangle] - fn div16(source_operand: u32) -> (); - #[no_mangle] - fn idiv16(source_operand: i32) -> (); - #[no_mangle] - fn div32(source_operand: u32) -> (); - #[no_mangle] - fn idiv32(source_operand: i32) -> (); - #[no_mangle] - fn shl8(dest_operand: i32, count: i32) -> i32; - #[no_mangle] - fn shl16(dest_operand: i32, count: i32) -> i32; - #[no_mangle] - fn shl32(dest_operand: i32, count: i32) -> i32; - #[no_mangle] - fn shr8(dest_operand: i32, count: i32) -> i32; - #[no_mangle] - fn shr16(dest_operand: i32, count: i32) -> i32; - #[no_mangle] - fn shr32(dest_operand: i32, count: i32) -> i32; - #[no_mangle] - fn sar8(dest_operand: i32, count: i32) -> i32; - #[no_mangle] - fn sar16(dest_operand: i32, count: i32) -> i32; - #[no_mangle] - fn sar32(dest_operand: i32, count: i32) -> i32; - #[no_mangle] - static FLAG_CARRY: i32; - #[no_mangle] - static FLAG_PARITY: i32; - #[no_mangle] - static FLAG_ADJUST: i32; - #[no_mangle] - static FLAG_ZERO: i32; - #[no_mangle] - static FLAG_SIGN: i32; - #[no_mangle] - static FLAG_TRAP: i32; - #[no_mangle] - static FLAG_INTERRUPT: i32; - #[no_mangle] - static FLAG_DIRECTION: i32; - #[no_mangle] - static FLAG_OVERFLOW: i32; - #[no_mangle] - static FLAG_IOPL: i32; - #[no_mangle] - static FLAG_NT: i32; - #[no_mangle] - static FLAG_RF: i32; - #[no_mangle] - static FLAG_VM: i32; - #[no_mangle] - static FLAG_AC: i32; - #[no_mangle] - static FLAG_VIF: i32; - #[no_mangle] - static FLAG_VIP: i32; - #[no_mangle] - static FLAG_ID: i32; - #[no_mangle] - static FLAGS_DEFAULT: i32; - #[no_mangle] - static FLAGS_MASK: i32; - #[no_mangle] - static FLAGS_ALL: i32; - #[no_mangle] - static OPSIZE_8: i32; - #[no_mangle] - static OPSIZE_16: i32; - #[no_mangle] - static OPSIZE_32: i32; - #[no_mangle] - static EAX: i32; - #[no_mangle] - static ECX: i32; - #[no_mangle] - static EDX: i32; - #[no_mangle] - static EBX: i32; - #[no_mangle] - static ESP: i32; - #[no_mangle] - static EBP: i32; - #[no_mangle] - static ESI: i32; - #[no_mangle] - static EDI: i32; - #[no_mangle] - static AX: i32; - #[no_mangle] - static CX: i32; - #[no_mangle] - static DX: i32; - #[no_mangle] - static BX: i32; - #[no_mangle] - static SP: i32; - #[no_mangle] - static BP: i32; - #[no_mangle] - static SI: i32; - #[no_mangle] - static DI: i32; - #[no_mangle] - static AL: i32; - #[no_mangle] - static CL: i32; - #[no_mangle] - static DL: i32; - #[no_mangle] - static BL: i32; - #[no_mangle] - static AH: i32; - #[no_mangle] - static CH: i32; - #[no_mangle] - static DH: i32; - #[no_mangle] - static BH: i32; - #[no_mangle] - static ES: i32; - #[no_mangle] - static CS: i32; - #[no_mangle] - static SS: i32; - #[no_mangle] - static DS: i32; - #[no_mangle] - static FS: i32; - #[no_mangle] - static GS: i32; - #[no_mangle] - static TR: i32; - #[no_mangle] - static LDTR: i32; - #[no_mangle] - static PAGE_TABLE_PRESENT_MASK: i32; - #[no_mangle] - static PAGE_TABLE_RW_MASK: i32; - #[no_mangle] - static PAGE_TABLE_USER_MASK: i32; - #[no_mangle] - static PAGE_TABLE_ACCESSED_MASK: i32; - #[no_mangle] - static PAGE_TABLE_DIRTY_MASK: i32; - #[no_mangle] - static PAGE_TABLE_PSE_MASK: i32; - #[no_mangle] - static PAGE_TABLE_GLOBAL_MASK: i32; - #[no_mangle] - static MMAP_BLOCK_BITS: i32; - #[no_mangle] - static MMAP_BLOCK_SIZE: i32; - #[no_mangle] - static CR0_PE: i32; - #[no_mangle] - static CR0_MP: i32; - #[no_mangle] - static CR0_EM: i32; - #[no_mangle] - static CR0_TS: i32; - #[no_mangle] - static CR0_ET: i32; - #[no_mangle] - static CR0_WP: i32; - #[no_mangle] - static CR0_NW: i32; - #[no_mangle] - static CR0_CD: i32; - #[no_mangle] - static CR0_PG: i32; - #[no_mangle] - static CR4_VME: i32; - #[no_mangle] - static CR4_PVI: i32; - #[no_mangle] - static CR4_TSD: i32; - #[no_mangle] - static CR4_PSE: i32; - #[no_mangle] - static CR4_DE: i32; - #[no_mangle] - static CR4_PAE: i32; - #[no_mangle] - static CR4_PGE: i32; - #[no_mangle] - static IA32_SYSENTER_CS: i32; - #[no_mangle] - static IA32_SYSENTER_ESP: i32; - #[no_mangle] - static IA32_SYSENTER_EIP: i32; - #[no_mangle] - static IA32_TIME_STAMP_COUNTER: i32; - #[no_mangle] - static IA32_PLATFORM_ID: i32; - #[no_mangle] - static IA32_APIC_BASE_MSR: i32; - #[no_mangle] - static IA32_BIOS_SIGN_ID: i32; - #[no_mangle] - static MSR_PLATFORM_INFO: i32; - #[no_mangle] - static MSR_MISC_FEATURE_ENABLES: i32; - #[no_mangle] - static IA32_MISC_ENABLE: i32; - #[no_mangle] - static IA32_RTIT_CTL: i32; - #[no_mangle] - static MSR_SMI_COUNT: i32; - #[no_mangle] - static IA32_MCG_CAP: i32; - #[no_mangle] - static IA32_KERNEL_GS_BASE: i32; - #[no_mangle] - static MSR_PKG_C2_RESIDENCY: i32; - #[no_mangle] - static IA32_APIC_BASE_BSP: i32; - #[no_mangle] - static IA32_APIC_BASE_EXTD: i32; - #[no_mangle] - static IA32_APIC_BASE_EN: i32; - #[no_mangle] - static APIC_ADDRESS: i32; - #[no_mangle] - static SEG_PREFIX_NONE: i32; - #[no_mangle] - static SEG_PREFIX_ZERO: i32; - #[no_mangle] - static PREFIX_MASK_REP: i32; - #[no_mangle] - static PREFIX_REPZ: i32; - #[no_mangle] - static PREFIX_REPNZ: i32; - #[no_mangle] - static PREFIX_MASK_SEGMENT: i32; - #[no_mangle] - static PREFIX_MASK_OPSIZE: i32; - #[no_mangle] - static PREFIX_MASK_ADDRSIZE: i32; - #[no_mangle] - static PREFIX_F2: i32; - #[no_mangle] - static PREFIX_F3: i32; - #[no_mangle] - static PREFIX_66: i32; - #[no_mangle] - static LOG_CPU: i32; - #[no_mangle] - static A20_MASK: i32; - #[no_mangle] - static A20_MASK16: i32; - #[no_mangle] - static A20_MASK32: i32; - #[no_mangle] - static MXCSR_MASK: i32; - #[no_mangle] - fn __fpclassifyl(_: f64) -> i32; - #[no_mangle] - fn atan2(_: f64, _: f64) -> f64; - #[no_mangle] - fn cos(_: f64) -> f64; - #[no_mangle] - fn fabs(_: f64) -> f64; - #[no_mangle] - fn fmod(_: f64, _: f64) -> f64; - #[no_mangle] - fn log(_: f64) -> f64; - #[no_mangle] - fn pow(_: f64, _: f64) -> f64; - #[no_mangle] - fn sin(_: f64) -> f64; - #[no_mangle] - fn sqrt(_: f64) -> f64; - #[no_mangle] - fn tan(_: f64) -> f64; - #[no_mangle] - fn trunc(_: f64) -> f64; + fn iret32(); #[no_mangle] - fn dbg_log(m: *const i8) -> (); + fn handle_irqs(); #[no_mangle] - fn dbg_log1(m: *const i8, x: i32) -> (); - #[no_mangle] - fn c_comment(m: *const i8) -> (); - #[no_mangle] - static mut mem8: *mut u8; - #[no_mangle] - static mut mem16: *mut u16; - #[no_mangle] - static mut mem32s: *mut i32; - #[no_mangle] - static mut jit_block_boundary: bool; - #[no_mangle] - static VALID_TLB_ENTRY_MAX: i32; - #[no_mangle] - static mut valid_tlb_entries: [i32; 10000]; - #[no_mangle] - static mut valid_tlb_entries_count: i32; - #[no_mangle] - static TLB_VALID: i32; - #[no_mangle] - static TLB_READONLY: i32; - #[no_mangle] - static TLB_NO_USER: i32; - #[no_mangle] - static TLB_IN_MAPPED_RANGE: i32; - #[no_mangle] - static TLB_GLOBAL: i32; - #[no_mangle] - static TLB_HAS_CODE: i32; - #[no_mangle] - static CPU_EXCEPTION_DE: i32; - #[no_mangle] - static CPU_EXCEPTION_DB: i32; - #[no_mangle] - static CPU_EXCEPTION_NMI: i32; - #[no_mangle] - static CPU_EXCEPTION_BP: i32; - #[no_mangle] - static CPU_EXCEPTION_OF: i32; - #[no_mangle] - static CPU_EXCEPTION_BR: i32; - #[no_mangle] - static CPU_EXCEPTION_UD: i32; - #[no_mangle] - static CPU_EXCEPTION_NM: i32; - #[no_mangle] - static CPU_EXCEPTION_DF: i32; - #[no_mangle] - static CPU_EXCEPTION_TS: i32; - #[no_mangle] - static CPU_EXCEPTION_NP: i32; - #[no_mangle] - static CPU_EXCEPTION_SS: i32; - #[no_mangle] - static CPU_EXCEPTION_GP: i32; - #[no_mangle] - static CPU_EXCEPTION_PF: i32; - #[no_mangle] - static CPU_EXCEPTION_MF: i32; - #[no_mangle] - static CPU_EXCEPTION_AC: i32; - #[no_mangle] - static CPU_EXCEPTION_MC: i32; - #[no_mangle] - static CPU_EXCEPTION_XM: i32; - #[no_mangle] - static CPU_EXCEPTION_VE: i32; - #[no_mangle] - fn get_eflags() -> i32; - #[no_mangle] - fn is_asize_32() -> bool; - #[no_mangle] - fn get_seg_cs() -> i32; - #[no_mangle] - fn get_seg_ss() -> i32; - #[no_mangle] - fn get_seg_prefix(default_segment: i32) -> i32; - #[no_mangle] - fn get_seg_prefix_ds(offset: i32) -> i32; - #[no_mangle] - fn run_prefix_instruction() -> (); - #[no_mangle] - fn segment_prefix_op(seg: i32) -> (); - #[no_mangle] - fn trigger_ud() -> (); - #[no_mangle] - fn trigger_nm() -> (); - #[no_mangle] - fn trigger_gp_non_raising(code: i32) -> (); - #[no_mangle] - fn get_reg8_index(index: i32) -> i32; - #[no_mangle] - fn read_reg8(index: i32) -> i32; - #[no_mangle] - fn write_reg8(index: i32, value: i32) -> (); - #[no_mangle] - fn get_reg16_index(index: i32) -> i32; - #[no_mangle] - fn read_reg16(index: i32) -> i32; - #[no_mangle] - fn write_reg16(index: i32, value: i32) -> (); - #[no_mangle] - fn read_reg32(index: i32) -> i32; - #[no_mangle] - fn write_reg32(index: i32, value: i32) -> (); - #[no_mangle] - fn get_real_eip() -> i32; - #[no_mangle] - fn set_stack_reg(value: i32) -> (); - #[no_mangle] - fn vm86_mode() -> bool; - #[no_mangle] - fn getiopl() -> i32; - #[no_mangle] - static M_LOG2E: f64; - #[no_mangle] - static M_LN2: f64; - #[no_mangle] - static M_LN10: f64; - #[no_mangle] - static M_PI: f64; - #[no_mangle] - static FPU_C0: i32; - #[no_mangle] - static FPU_C1: i32; - #[no_mangle] - static FPU_C2: i32; - #[no_mangle] - static FPU_C3: i32; - #[no_mangle] - static FPU_RESULT_FLAGS: i32; - #[no_mangle] - static FPU_STACK_TOP: i32; - #[no_mangle] - fn fpu_get_st0() -> f64; - #[no_mangle] - fn fpu_get_sti(i: i32) -> f64; - #[no_mangle] - fn fpu_integer_round(f: f64) -> f64; - #[no_mangle] - fn fpu_fadd(target_index: i32, val: f64) -> (); - #[no_mangle] - fn fpu_fclex() -> (); - #[no_mangle] - fn fpu_fcmovcc(condition: bool, r: i32) -> (); - #[no_mangle] - fn fpu_fcom(y: f64) -> (); - #[no_mangle] - fn fpu_fcomi(r: i32) -> (); - #[no_mangle] - fn fpu_fcomip(r: i32) -> (); - #[no_mangle] - fn fpu_fcomp(val: f64) -> (); - #[no_mangle] - fn fpu_fdiv(target_index: i32, val: f64) -> (); - #[no_mangle] - fn fpu_fdivr(target_index: i32, val: f64) -> (); - #[no_mangle] - fn fpu_ffree(r: i32) -> (); - #[no_mangle] - fn fpu_fildm64(addr: i32) -> (); - #[no_mangle] - fn fpu_finit() -> (); - #[no_mangle] - fn fpu_fistm16(addr: i32) -> (); - #[no_mangle] - fn fpu_fistm16p(addr: i32) -> (); - #[no_mangle] - fn fpu_fistm32(addr: i32) -> (); - #[no_mangle] - fn fpu_fistm32p(addr: i32) -> (); - #[no_mangle] - fn fpu_fistm64p(addr: i32) -> (); - #[no_mangle] - fn fpu_fldcw(addr: i32) -> (); - #[no_mangle] - fn fpu_fldenv(addr: i32) -> (); - #[no_mangle] - fn fpu_fldm32(addr: i32) -> (); - #[no_mangle] - fn fpu_fldm64(addr: i32) -> (); - #[no_mangle] - fn fpu_fldm80(addr: i32) -> (); - #[no_mangle] - fn fpu_fmul(target_index: i32, val: f64) -> (); - #[no_mangle] - fn fpu_fnstsw_mem(addr: i32) -> (); - #[no_mangle] - fn fpu_fnstsw_reg() -> (); - #[no_mangle] - fn fpu_fprem() -> (); - #[no_mangle] - fn fpu_frstor(addr: i32) -> (); - #[no_mangle] - fn fpu_fsave(addr: i32) -> (); - #[no_mangle] - fn fpu_fst(r: i32) -> (); - #[no_mangle] - fn fpu_fst80p(addr: i32) -> (); - #[no_mangle] - fn fpu_fstcw(addr: i32) -> (); - #[no_mangle] - fn fpu_fstenv(addr: i32) -> (); - #[no_mangle] - fn fpu_fstm32(addr: i32) -> (); - #[no_mangle] - fn fpu_fstm32p(addr: i32) -> (); - #[no_mangle] - fn fpu_fstm64(addr: i32) -> (); - #[no_mangle] - fn fpu_fstm64p(addr: i32) -> (); - #[no_mangle] - fn fpu_fstp(r: i32) -> (); - #[no_mangle] - fn fpu_fsub(target_index: i32, val: f64) -> (); - #[no_mangle] - fn fpu_fsubr(target_index: i32, val: f64) -> (); - #[no_mangle] - fn fpu_ftst(x: f64) -> (); - #[no_mangle] - fn fpu_fucom(r: i32) -> (); - #[no_mangle] - fn fpu_fucomi(r: i32) -> (); - #[no_mangle] - fn fpu_fucomip(r: i32) -> (); - #[no_mangle] - fn fpu_fucomp(r: i32) -> (); - #[no_mangle] - fn fpu_fucompp() -> (); - #[no_mangle] - fn fpu_fxam(x: f64) -> (); - #[no_mangle] - fn fpu_fxch(i: i32) -> (); - #[no_mangle] - fn fpu_fxtract() -> (); - #[no_mangle] - fn fpu_pop() -> (); - #[no_mangle] - fn fpu_push(x: f64) -> (); - #[no_mangle] - fn fwait() -> (); - #[no_mangle] - static reg8: *mut u8; - #[no_mangle] - static reg16: *mut u16; - #[no_mangle] - static reg8s: *mut i8; - #[no_mangle] - static reg16s: *mut i16; - #[no_mangle] - static reg32s: *mut i32; - #[no_mangle] - static last_op1: *mut i32; - #[no_mangle] - static last_op2: *mut i32; - #[no_mangle] - static last_op_size: *mut i32; - #[no_mangle] - static last_add_result: *mut i32; - #[no_mangle] - static last_result: *mut i32; - #[no_mangle] - static flags_changed: *mut i32; - #[no_mangle] - static flags: *mut i32; - #[no_mangle] - static page_fault: *mut bool; - #[no_mangle] - static a20_enabled: *mut bool; - #[no_mangle] - static instruction_pointer: *mut i32; - #[no_mangle] - static previous_ip: *mut i32; - #[no_mangle] - static idtr_size: *mut i32; - #[no_mangle] - static idtr_offset: *mut i32; - #[no_mangle] - static gdtr_size: *mut i32; - #[no_mangle] - static gdtr_offset: *mut i32; - #[no_mangle] - static cr: *mut i32; - #[no_mangle] - static cpl: *mut u8; - #[no_mangle] - static in_hlt: *mut bool; - #[no_mangle] - static last_virt_eip: *mut i32; - #[no_mangle] - static eip_phys: *mut i32; - #[no_mangle] - static last_virt_esp: *mut i32; - #[no_mangle] - static esp_phys: *mut i32; - #[no_mangle] - static sysenter_cs: *mut i32; - #[no_mangle] - static sysenter_esp: *mut i32; - #[no_mangle] - static sysenter_eip: *mut i32; - #[no_mangle] - static prefixes: *mut u8; - #[no_mangle] - static timestamp_counter: *mut u32; - #[no_mangle] - static sreg: *mut u16; - #[no_mangle] - static dreg: *mut i32; - #[no_mangle] - static fw_value: *mut i32; - #[no_mangle] - static segment_is_null: *mut bool; - #[no_mangle] - static segment_offsets: *mut i32; - #[no_mangle] - static segment_limits: *mut u32; - #[no_mangle] - static protected_mode: *mut bool; - #[no_mangle] - static is_32: *mut bool; - #[no_mangle] - static stack_size_32: *mut bool; - #[no_mangle] - static memory_size: *mut u32; - #[no_mangle] - static fpu_stack_empty: *mut i32; - #[no_mangle] - static mxcsr: *mut i32; - #[no_mangle] - static reg_xmm: *mut reg128; - #[no_mangle] - static current_tsc: *mut u64; - #[no_mangle] - static fpu_st: *mut f64; - #[no_mangle] - static fpu_st8: *mut u8; - #[no_mangle] - static fpu_st32: *mut i32; - #[no_mangle] - static fpu_stack_ptr: *mut u32; - #[no_mangle] - static fpu_control_word: *mut i32; - #[no_mangle] - static fpu_status_word: *mut i32; - #[no_mangle] - static fpu_opcode: *mut i32; - #[no_mangle] - static fpu_ip: *mut i32; - #[no_mangle] - static fpu_ip_selector: *mut i32; - #[no_mangle] - static fpu_dp: *mut i32; - #[no_mangle] - static fpu_dp_selector: *mut i32; - #[no_mangle] - static reg_mmx: *mut reg64; - #[no_mangle] - static opstats_buffer: *mut u32; - #[no_mangle] - static opstats_buffer_0f: *mut u32; - #[no_mangle] - static tlb_data: *mut i32; - #[no_mangle] - #[no_mangle] - #[no_mangle] - #[no_mangle] - fn adjust_stack_reg(adjustment: i32) -> (); - #[no_mangle] - fn get_stack_pointer(offset: i32) -> i32; - #[no_mangle] - fn switch_seg(_: i32, _: i32) -> bool; - #[no_mangle] - fn run_instruction0f_16(opcode: i32) -> (); - #[no_mangle] - fn run_instruction0f_32(opcode: i32) -> (); - #[no_mangle] - fn pusha16() -> (); - #[no_mangle] - fn pusha32() -> (); - #[no_mangle] - fn popa16() -> (); - #[no_mangle] - fn popa32() -> (); - #[no_mangle] - fn arpl(_: i32, _: i32) -> i32; - #[no_mangle] - fn insb_no_rep() -> (); - #[no_mangle] - fn insw_no_rep() -> (); - #[no_mangle] - fn insd_no_rep() -> (); - #[no_mangle] - fn outsb_no_rep() -> (); - #[no_mangle] - fn outsw_no_rep() -> (); - #[no_mangle] - fn outsd_no_rep() -> (); - #[no_mangle] - fn xchg8(data: i32, r8: i32) -> i32; - #[no_mangle] - fn xchg16(data: i32, r16: i32) -> i32; - #[no_mangle] - fn xchg32(data: i32, r32: i32) -> i32; - #[no_mangle] - fn xchg16r(r16: i32) -> (); - #[no_mangle] - fn xchg32r(r32: i32) -> (); - #[no_mangle] - fn far_jump(_: i32, _: i32, _: i32) -> (); - #[no_mangle] - fn handle_irqs() -> (); - #[no_mangle] - fn update_eflags(_: i32) -> (); - #[no_mangle] - fn movsb_no_rep() -> (); - #[no_mangle] - fn movsw_no_rep() -> (); - #[no_mangle] - fn movsd_no_rep() -> (); - #[no_mangle] - fn cmpsb_no_rep() -> (); - #[no_mangle] - fn cmpsw_no_rep() -> (); - #[no_mangle] - fn cmpsd_no_rep() -> (); - #[no_mangle] - fn stosb_no_rep() -> (); - #[no_mangle] - fn stosw_no_rep() -> (); - #[no_mangle] - fn stosd_no_rep() -> (); - #[no_mangle] - fn lodsb_no_rep() -> (); - #[no_mangle] - fn lodsw_no_rep() -> (); - #[no_mangle] - fn lodsd_no_rep() -> (); - #[no_mangle] - fn scasb_no_rep() -> (); - #[no_mangle] - fn scasw_no_rep() -> (); - #[no_mangle] - fn scasd_no_rep() -> (); - #[no_mangle] - fn lss16(_: i32, _: i32, _: i32) -> (); - #[no_mangle] - fn lss32(_: i32, _: i32, _: i32) -> (); - #[no_mangle] - fn enter16(_: i32, _: i32) -> (); - #[no_mangle] - fn enter32(_: i32, _: i32) -> (); - #[no_mangle] - fn far_return(_: i32, _: i32, _: i32) -> (); - #[no_mangle] - fn call_interrupt_vector( - interrupt_nr: i32, - is_software_int: bool, - has_error_code: bool, - error_code: i32, - ) -> (); - #[no_mangle] - fn getof() -> bool; - #[no_mangle] - fn iret16() -> (); - #[no_mangle] - fn iret32() -> (); - #[no_mangle] - fn getcf() -> bool; - #[no_mangle] - fn io_port_read8(_: i32) -> i32; - #[no_mangle] - fn test_privileges_for_io(_: i32, _: i32) -> bool; - #[no_mangle] - fn io_port_read16(_: i32) -> i32; - #[no_mangle] - fn io_port_read32(_: i32) -> i32; - #[no_mangle] - fn io_port_write8(_: i32, _: i32) -> (); - #[no_mangle] - fn io_port_write16(_: i32, _: i32) -> (); - #[no_mangle] - fn io_port_write32(_: i32, _: i32) -> (); - #[no_mangle] - fn jmp_rel16(rel16: i32) -> (); - #[no_mangle] - fn hlt_op() -> (); - #[no_mangle] - fn test_o() -> bool; - #[no_mangle] - fn test_b() -> bool; - #[no_mangle] - fn test_z() -> bool; - #[no_mangle] - fn test_s() -> bool; - #[no_mangle] - fn test_p() -> bool; - #[no_mangle] - fn test_be() -> bool; - #[no_mangle] - fn test_l() -> bool; - #[no_mangle] - fn test_le() -> bool; - #[no_mangle] - fn jmpcc16(condition: bool, imm16: i32) -> (); - #[no_mangle] - fn jmpcc32(condition: bool, imm32: i32) -> (); - #[no_mangle] - fn loope16(imm8s: i32) -> (); - #[no_mangle] - fn loopne16(imm8s: i32) -> (); - #[no_mangle] - fn loop16(imm8s: i32) -> (); - #[no_mangle] - fn jcxz16(imm8s: i32) -> (); - #[no_mangle] - fn loope32(imm8s: i32) -> (); - #[no_mangle] - fn loopne32(imm8s: i32) -> (); - #[no_mangle] - fn loop32(imm8s: i32) -> (); - #[no_mangle] - fn jcxz32(imm8s: i32) -> (); - #[no_mangle] - static mut profiler_stat_arr: [profiler_stat; 37]; - #[no_mangle] - fn movsb_rep() -> (); - #[no_mangle] - fn movsw_rep() -> (); - #[no_mangle] - fn movsd_rep() -> (); - #[no_mangle] - fn cmpsb_rep(_: i32) -> (); - #[no_mangle] - fn cmpsw_rep(_: i32) -> (); - #[no_mangle] - fn cmpsd_rep(_: i32) -> (); - #[no_mangle] - fn stosb_rep() -> (); - #[no_mangle] - fn stosw_rep() -> (); - #[no_mangle] - fn stosd_rep() -> (); - #[no_mangle] - fn lodsb_rep() -> (); - #[no_mangle] - fn lodsw_rep() -> (); - #[no_mangle] - fn lodsd_rep() -> (); - #[no_mangle] - fn scasb_rep(_: i32) -> (); - #[no_mangle] - fn scasw_rep(_: i32) -> (); - #[no_mangle] - fn scasd_rep(_: i32) -> (); - #[no_mangle] - fn insb_rep() -> (); - #[no_mangle] - fn insw_rep() -> (); - #[no_mangle] - fn insd_rep() -> (); - #[no_mangle] - fn outsb_rep() -> (); - #[no_mangle] - fn outsw_rep() -> (); - #[no_mangle] - fn outsd_rep() -> (); + fn hlt_op(); } -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed { - __f: f32, - __i: u32, -} +use cpu2::arith::*; +use cpu2::cpu::*; +use cpu2::fpu::*; +use cpu2::fpu::{fpu_load_m32, fpu_load_m64}; +use cpu2::global_pointers::*; +use cpu2::misc_instr::*; +use cpu2::misc_instr::{pop16, pop32s, push16, push32}; +use cpu2::string::*; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct profiler_stat { - pub count: i32, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub union reg64 { - i8_0: [i8; 8], - i16_0: [i16; 4], - i32_0: [i32; 2], - i64_0: [i64; 1], - u8_0: [u8; 8], - u16_0: [u16; 4], - u32_0: [u32; 2], - u64_0: [u64; 1], - f32_0: [f32; 2], - f64_0: [f64; 1], -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_0 { - __f: f64, - __i: u64, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub union reg128 { - i8_0: [i8; 16], - i16_0: [i16; 8], - i32_0: [i32; 4], - i64_0: [i64; 2], - u8_0: [u8; 16], - u16_0: [u16; 8], - u32_0: [u32; 4], - u64_0: [u64; 2], - f32_0: [f32; 4], - f64_0: [f64; 2], -} - -unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { - let mut __u: unnamed = unnamed { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { - let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x >= __y) as i32; -} #[no_mangle] pub unsafe extern "C" fn instr_00_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE8!(___, addr, add8(___, read_reg8(r))); @@ -3187,7 +1826,7 @@ pub unsafe extern "C" fn instr32_99() -> () { #[no_mangle] pub unsafe extern "C" fn instr16_9A(mut new_ip: i32, mut new_cs: i32) -> () { c_comment!(("callf")); - far_jump(new_ip, new_cs, 1i32); + far_jump(new_ip, new_cs, true); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] @@ -3197,7 +1836,7 @@ pub unsafe extern "C" fn instr32_9A(mut new_ip: i32, mut new_cs: i32) -> () { dbg_assert!(0 != 0i32); } } - far_jump(new_ip, new_cs, 1i32); + far_jump(new_ip, new_cs, true); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] @@ -4439,13 +3078,13 @@ pub unsafe extern "C" fn instr32_E9(mut imm32s: i32) -> () { #[no_mangle] pub unsafe extern "C" fn instr16_EA(mut new_ip: i32, mut cs: i32) -> () { c_comment!(("jmpf")); - far_jump(new_ip, cs, 0i32); + far_jump(new_ip, cs, false); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] pub unsafe extern "C" fn instr32_EA(mut new_ip: i32, mut cs: i32) -> () { c_comment!(("jmpf")); - far_jump(new_ip, cs, 0i32); + far_jump(new_ip, cs, false); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] @@ -4938,7 +3577,7 @@ pub unsafe extern "C" fn instr16_FF_3_mem(mut addr: i32) -> () { c_comment!(("callf")); let mut new_ip: i32 = return_on_pagefault!(safe_read16(addr)); let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 2i32)); - far_jump(new_ip, new_cs, 1i32); + far_jump(new_ip, new_cs, true); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] @@ -4967,7 +3606,7 @@ pub unsafe extern "C" fn instr16_FF_5_mem(mut addr: i32) -> () { c_comment!(("jmpf")); let mut new_ip: i32 = return_on_pagefault!(safe_read16(addr)); let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 2i32)); - far_jump(new_ip, new_cs, 0i32); + far_jump(new_ip, new_cs, false); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] @@ -5031,7 +3670,7 @@ pub unsafe extern "C" fn instr32_FF_3_mem(mut addr: i32) -> () { dbg_assert!(0 != 0i32); } } - far_jump(new_ip, new_cs, 1i32); + far_jump(new_ip, new_cs, true); dbg_assert!(0 != is_asize_32() as i32 || new_ip < 65536i32); } #[no_mangle] @@ -5065,7 +3704,7 @@ pub unsafe extern "C" fn instr32_FF_5_mem(mut addr: i32) -> () { dbg_assert!(0 != 0i32); } } - far_jump(new_ip, new_cs, 0i32); + far_jump(new_ip, new_cs, false); dbg_assert!(0 != is_asize_32() as i32 || new_ip < 65536i32); } #[no_mangle] @@ -5350,7 +3989,7 @@ pub unsafe extern "C" fn instr_D9_4_reg(mut r: i32) -> () { }, 1 => { c_comment!(("fabs")); - *fpu_st.offset(*fpu_stack_ptr as isize) = fabs(st0) + *fpu_st.offset(*fpu_stack_ptr as isize) = st0.abs() }, 4 => { fpu_ftst(st0); @@ -5411,19 +4050,19 @@ pub unsafe extern "C" fn instr_D9_6_reg(mut r: i32) -> () { 1 => { c_comment!(("fyl2x")); *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(1i32 as u32) & 7i32 as u32) as isize) = - fpu_get_sti(1i32) * log(st0) / M_LN2; + fpu_get_sti(1i32) * st0.ln() / M_LN2; fpu_pop(); }, 2 => { c_comment!(("fptan")); - *fpu_st.offset(*fpu_stack_ptr as isize) = tan(st0); + *fpu_st.offset(*fpu_stack_ptr as isize) = st0.tan(); fpu_push(1i32 as f64); c_comment!(("no bug: push constant 1")); }, 3 => { c_comment!(("fpatan")); *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(1i32 as u32) & 7i32 as u32) as isize) = - atan2(fpu_get_sti(1i32), st0); + fpu_get_sti(1i32).atan2(st0); fpu_pop(); }, 4 => { @@ -5460,13 +4099,13 @@ pub unsafe extern "C" fn instr_D9_7_reg(mut r: i32) -> () { 1 => { c_comment!(("fyl2xp1: y * log2(x+1) and pop")); *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(1i32 as u32) & 7i32 as u32) as isize) = - fpu_get_sti(1i32) * log(st0 + 1i32 as f64) / M_LN2; + fpu_get_sti(1i32) * (st0 + 1i32 as f64).ln() / M_LN2; fpu_pop(); }, - 2 => *fpu_st.offset(*fpu_stack_ptr as isize) = sqrt(st0), + 2 => *fpu_st.offset(*fpu_stack_ptr as isize) = st0.sqrt(), 3 => { - *fpu_st.offset(*fpu_stack_ptr as isize) = sin(st0); - fpu_push(cos(st0)); + *fpu_st.offset(*fpu_stack_ptr as isize) = st0.sin(); + fpu_push(st0.cos()); }, 4 => { c_comment!(("frndint")); @@ -5477,8 +4116,8 @@ pub unsafe extern "C" fn instr_D9_7_reg(mut r: i32) -> () { *fpu_st.offset(*fpu_stack_ptr as isize) = st0 * pow(2i32 as f64, trunc(fpu_get_sti(1i32))) }, - 6 => *fpu_st.offset(*fpu_stack_ptr as isize) = sin(st0), - 7 => *fpu_st.offset(*fpu_stack_ptr as isize) = cos(st0), + 6 => *fpu_st.offset(*fpu_stack_ptr as isize) = st0.sin(), + 7 => *fpu_st.offset(*fpu_stack_ptr as isize) = st0.cos(), _ => { dbg_assert!(0 != 0i32); }, diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index c06c8207..a0b3b02a 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -8,1124 +8,64 @@ )] #![feature(extern_types, libc)] -use cpu2::cpu::*; -use cpu2::fpu::fpu_load_m32; -use cpu2::misc_instr::{push16, push32}; - extern "C" { - #[no_mangle] - fn __fpclassifyl(_: f64) -> i32; + fn unimplemented_sse(); #[no_mangle] - fn sqrt(_: f64) -> f64; + fn undefined_instruction(); #[no_mangle] - fn sqrtf(_: f32) -> f32; + fn lss16(x: i32, y: i32, z: i32); #[no_mangle] - fn abs(_: i32) -> i32; + fn lss32(x: i32, y: i32, z: i32); #[no_mangle] - fn cmp8(x: i32, y: i32) -> (); - #[no_mangle] - fn cmp16(x: i32, y: i32) -> (); - #[no_mangle] - fn cmp32(x: i32, y: i32) -> (); - #[no_mangle] - fn imul_reg16(operand1: i32, operand2: i32) -> i32; - #[no_mangle] - fn imul_reg32(operand1: i32, operand2: i32) -> i32; - #[no_mangle] - fn xadd8(source_operand: i32, reg: i32) -> i32; - #[no_mangle] - fn xadd16(source_operand: i32, reg: i32) -> i32; - #[no_mangle] - fn xadd32(source_operand: i32, reg: i32) -> i32; - #[no_mangle] - fn shrd16(dest_operand: i32, source_operand: i32, count: i32) -> i32; - #[no_mangle] - fn shrd32(dest_operand: i32, source_operand: i32, count: i32) -> i32; - #[no_mangle] - fn shld16(dest_operand: i32, source_operand: i32, count: i32) -> i32; - #[no_mangle] - fn shld32(dest_operand: i32, source_operand: i32, count: i32) -> i32; - #[no_mangle] - fn bt_reg(bit_base: i32, bit_offset: i32) -> (); - #[no_mangle] - fn btc_reg(bit_base: i32, bit_offset: i32) -> i32; - #[no_mangle] - fn bts_reg(bit_base: i32, bit_offset: i32) -> i32; - #[no_mangle] - fn btr_reg(bit_base: i32, bit_offset: i32) -> i32; - #[no_mangle] - fn bt_mem(virt_addr: i32, bit_offset: i32) -> (); - #[no_mangle] - fn btc_mem(virt_addr: i32, bit_offset: i32) -> (); - #[no_mangle] - fn btr_mem(virt_addr: i32, bit_offset: i32) -> (); - #[no_mangle] - fn bts_mem(virt_addr: i32, bit_offset: i32) -> (); - #[no_mangle] - fn bsf16(old: i32, bit_base: i32) -> i32; - #[no_mangle] - fn bsf32(old: i32, bit_base: i32) -> i32; - #[no_mangle] - fn bsr16(old: i32, bit_base: i32) -> i32; - #[no_mangle] - fn bsr32(old: i32, bit_base: i32) -> i32; - #[no_mangle] - fn popcnt(v: i32) -> i32; - #[no_mangle] - fn saturate_sw_to_ub(v: u32) -> u32; - #[no_mangle] - fn saturate_sw_to_sb(v: i32) -> i32; - #[no_mangle] - fn saturate_sd_to_sw(v: u32) -> u32; - #[no_mangle] - fn saturate_sd_to_sb(v: u32) -> u32; - #[no_mangle] - fn saturate_sd_to_ub(v: i32) -> i32; - #[no_mangle] - fn saturate_ud_to_ub(v: u32) -> u32; - #[no_mangle] - fn saturate_uw(v: u32) -> i32; - #[no_mangle] - static FLAG_CARRY: i32; - #[no_mangle] - static FLAG_PARITY: i32; - #[no_mangle] - static FLAG_ADJUST: i32; - #[no_mangle] - static FLAG_ZERO: i32; - #[no_mangle] - static FLAG_SIGN: i32; - #[no_mangle] - static FLAG_TRAP: i32; - #[no_mangle] - static FLAG_INTERRUPT: i32; - #[no_mangle] - static FLAG_DIRECTION: i32; - #[no_mangle] - static FLAG_OVERFLOW: i32; - #[no_mangle] - static FLAG_IOPL: i32; - #[no_mangle] - static FLAG_NT: i32; - #[no_mangle] - static FLAG_RF: i32; - #[no_mangle] - static FLAG_VM: i32; - #[no_mangle] - static FLAG_AC: i32; - #[no_mangle] - static FLAG_VIF: i32; - #[no_mangle] - static FLAG_VIP: i32; - #[no_mangle] - static FLAG_ID: i32; - #[no_mangle] - static FLAGS_DEFAULT: i32; - #[no_mangle] - static FLAGS_MASK: i32; - #[no_mangle] - static FLAGS_ALL: i32; - #[no_mangle] - static OPSIZE_8: i32; - #[no_mangle] - static OPSIZE_16: i32; - #[no_mangle] - static OPSIZE_32: i32; - #[no_mangle] - static EAX: i32; - #[no_mangle] - static ECX: i32; - #[no_mangle] - static EDX: i32; - #[no_mangle] - static EBX: i32; - #[no_mangle] - static ESP: i32; - #[no_mangle] - static EBP: i32; - #[no_mangle] - static ESI: i32; - #[no_mangle] - static EDI: i32; - #[no_mangle] - static AX: i32; - #[no_mangle] - static CX: i32; - #[no_mangle] - static DX: i32; - #[no_mangle] - static BX: i32; - #[no_mangle] - static SP: i32; - #[no_mangle] - static BP: i32; - #[no_mangle] - static SI: i32; - #[no_mangle] - static DI: i32; - #[no_mangle] - static AL: i32; - #[no_mangle] - static CL: i32; - #[no_mangle] - static DL: i32; - #[no_mangle] - static BL: i32; - #[no_mangle] - static AH: i32; - #[no_mangle] - static CH: i32; - #[no_mangle] - static DH: i32; - #[no_mangle] - static BH: i32; - #[no_mangle] - static ES: i32; - #[no_mangle] - static CS: i32; - #[no_mangle] - static SS: i32; - #[no_mangle] - static DS: i32; - #[no_mangle] - static FS: i32; - #[no_mangle] - static GS: i32; - #[no_mangle] - static TR: i32; - #[no_mangle] - static LDTR: i32; - #[no_mangle] - static PAGE_TABLE_PRESENT_MASK: i32; - #[no_mangle] - static PAGE_TABLE_RW_MASK: i32; - #[no_mangle] - static PAGE_TABLE_USER_MASK: i32; - #[no_mangle] - static PAGE_TABLE_ACCESSED_MASK: i32; - #[no_mangle] - static PAGE_TABLE_DIRTY_MASK: i32; - #[no_mangle] - static PAGE_TABLE_PSE_MASK: i32; - #[no_mangle] - static PAGE_TABLE_GLOBAL_MASK: i32; - #[no_mangle] - static MMAP_BLOCK_BITS: i32; - #[no_mangle] - static MMAP_BLOCK_SIZE: i32; - #[no_mangle] - static CR0_PE: i32; - #[no_mangle] - static CR0_MP: i32; - #[no_mangle] - static CR0_EM: i32; - #[no_mangle] - static CR0_TS: i32; - #[no_mangle] - static CR0_ET: i32; - #[no_mangle] - static CR0_WP: i32; - #[no_mangle] - static CR0_NW: i32; - #[no_mangle] - static CR0_CD: i32; - #[no_mangle] - static CR0_PG: i32; - #[no_mangle] - static CR4_VME: i32; - #[no_mangle] - static CR4_PVI: i32; - #[no_mangle] - static CR4_TSD: i32; - #[no_mangle] - static CR4_PSE: i32; - #[no_mangle] - static CR4_DE: i32; - #[no_mangle] - static CR4_PAE: i32; - #[no_mangle] - static CR4_PGE: i32; - #[no_mangle] - static IA32_SYSENTER_CS: i32; - #[no_mangle] - static IA32_SYSENTER_ESP: i32; - #[no_mangle] - static IA32_SYSENTER_EIP: i32; - #[no_mangle] - static IA32_TIME_STAMP_COUNTER: i32; - #[no_mangle] - static IA32_PLATFORM_ID: i32; - #[no_mangle] - static IA32_APIC_BASE_MSR: i32; - #[no_mangle] - static IA32_BIOS_SIGN_ID: i32; - #[no_mangle] - static MSR_PLATFORM_INFO: i32; - #[no_mangle] - static MSR_MISC_FEATURE_ENABLES: i32; - #[no_mangle] - static IA32_MISC_ENABLE: i32; - #[no_mangle] - static IA32_RTIT_CTL: i32; - #[no_mangle] - static MSR_SMI_COUNT: i32; - #[no_mangle] - static IA32_MCG_CAP: i32; - #[no_mangle] - static IA32_KERNEL_GS_BASE: i32; - #[no_mangle] - static MSR_PKG_C2_RESIDENCY: i32; - #[no_mangle] - static IA32_APIC_BASE_BSP: i32; - #[no_mangle] - static IA32_APIC_BASE_EXTD: i32; - #[no_mangle] - static IA32_APIC_BASE_EN: i32; - #[no_mangle] - static APIC_ADDRESS: i32; - #[no_mangle] - static SEG_PREFIX_NONE: i32; - #[no_mangle] - static SEG_PREFIX_ZERO: i32; - #[no_mangle] - static PREFIX_MASK_REP: i32; - #[no_mangle] - static PREFIX_REPZ: i32; - #[no_mangle] - static PREFIX_REPNZ: i32; - #[no_mangle] - static PREFIX_MASK_SEGMENT: i32; - #[no_mangle] - static PREFIX_MASK_OPSIZE: i32; - #[no_mangle] - static PREFIX_MASK_ADDRSIZE: i32; - #[no_mangle] - static PREFIX_F2: i32; - #[no_mangle] - static PREFIX_F3: i32; - #[no_mangle] - static PREFIX_66: i32; - #[no_mangle] - static LOG_CPU: i32; - #[no_mangle] - static A20_MASK: i32; - #[no_mangle] - static A20_MASK16: i32; - #[no_mangle] - static A20_MASK32: i32; - #[no_mangle] - static MXCSR_MASK: i32; - - #[no_mangle] - fn dbg_log(m: *const i8) -> (); - #[no_mangle] - fn dbg_log1(m: *const i8, x: i32) -> (); - #[no_mangle] - fn dbg_log2(m: *const i8, x: i32, y: i32) -> (); - #[no_mangle] - fn dbg_log3(m: *const i8, x: i32, y: i32, z: i32) -> (); - #[no_mangle] - fn c_comment(m: *const i8) -> (); - #[no_mangle] - static mut mem8: *mut u8; - #[no_mangle] - static mut mem16: *mut u16; - #[no_mangle] - static mut mem32s: *mut i32; - #[no_mangle] - static mut jit_block_boundary: bool; - #[no_mangle] - static VALID_TLB_ENTRY_MAX: i32; - #[no_mangle] - static mut valid_tlb_entries: [i32; 10000]; - #[no_mangle] - static mut valid_tlb_entries_count: i32; - #[no_mangle] - static TLB_VALID: i32; - #[no_mangle] - static TLB_READONLY: i32; - #[no_mangle] - static TLB_NO_USER: i32; - #[no_mangle] - static TLB_IN_MAPPED_RANGE: i32; - #[no_mangle] - static TLB_GLOBAL: i32; - #[no_mangle] - static TLB_HAS_CODE: i32; - #[no_mangle] - static CPU_EXCEPTION_DE: i32; - #[no_mangle] - static CPU_EXCEPTION_DB: i32; - #[no_mangle] - static CPU_EXCEPTION_NMI: i32; - #[no_mangle] - static CPU_EXCEPTION_BP: i32; - #[no_mangle] - static CPU_EXCEPTION_OF: i32; - #[no_mangle] - static CPU_EXCEPTION_BR: i32; - #[no_mangle] - static CPU_EXCEPTION_UD: i32; - #[no_mangle] - static CPU_EXCEPTION_NM: i32; - #[no_mangle] - static CPU_EXCEPTION_DF: i32; - #[no_mangle] - static CPU_EXCEPTION_TS: i32; - #[no_mangle] - static CPU_EXCEPTION_NP: i32; - #[no_mangle] - static CPU_EXCEPTION_SS: i32; - #[no_mangle] - static CPU_EXCEPTION_GP: i32; - #[no_mangle] - static CPU_EXCEPTION_PF: i32; - #[no_mangle] - static CPU_EXCEPTION_MF: i32; - #[no_mangle] - static CPU_EXCEPTION_AC: i32; - #[no_mangle] - static CPU_EXCEPTION_MC: i32; - #[no_mangle] - static CPU_EXCEPTION_XM: i32; - #[no_mangle] - static CPU_EXCEPTION_VE: i32; - #[no_mangle] - fn is_osize_32() -> bool; - #[no_mangle] - fn get_seg_prefix(default_segment: i32) -> i32; - #[no_mangle] - fn trigger_ud() -> (); - #[no_mangle] - fn trigger_gp_non_raising(code: i32) -> (); - #[no_mangle] - fn get_reg8_index(index: i32) -> i32; - #[no_mangle] - fn read_reg8(index: i32) -> i32; - #[no_mangle] - fn write_reg8(index: i32, value: i32) -> (); - #[no_mangle] - fn get_reg16_index(index: i32) -> i32; - #[no_mangle] - fn read_reg16(index: i32) -> i32; - #[no_mangle] - fn write_reg16(index: i32, value: i32) -> (); - #[no_mangle] - fn read_reg32(index: i32) -> i32; - #[no_mangle] - fn write_reg32(index: i32, value: i32) -> (); - #[no_mangle] - fn write_reg_osize(index: i32, value: i32) -> (); - #[no_mangle] - fn read_mmx32s(r: i32) -> i32; - #[no_mangle] - fn read_mmx64s(r: i32) -> reg64; - #[no_mangle] - fn write_mmx64(r: i32, low: i32, high: i32) -> (); - #[no_mangle] - fn write_mmx_reg64(r: i32, data: reg64) -> (); - #[no_mangle] - fn read_xmm_f32(r: i32) -> f32; - #[no_mangle] - fn read_xmm64s(r: i32) -> reg64; - #[no_mangle] - fn read_xmm128s(r: i32) -> reg128; - #[no_mangle] - fn write_xmm_f32(r: i32, data: f32) -> (); - #[no_mangle] - fn write_xmm32(r: i32, _: i32) -> (); - #[no_mangle] - fn write_xmm64(r: i32, data: reg64) -> (); - #[no_mangle] - fn write_xmm128(r: i32, i0: i32, i1: i32, i2: i32, i3: i32) -> (); - #[no_mangle] - fn write_xmm_reg128(r: i32, data: reg128) -> (); - #[no_mangle] - fn clear_tlb() -> (); - #[no_mangle] - fn full_clear_tlb() -> (); - #[no_mangle] - fn get_reg_asize(reg: i32) -> i32; - #[no_mangle] - fn set_tsc(_: u32, _: u32) -> (); - #[no_mangle] - fn read_tsc() -> u64; - #[no_mangle] - fn vm86_mode() -> bool; - #[no_mangle] - static M_LOG2E: f64; - #[no_mangle] - static M_LN2: f64; - #[no_mangle] - static M_LN10: f64; - #[no_mangle] - static M_PI: f64; - #[no_mangle] - static FPU_C0: i32; - #[no_mangle] - static FPU_C1: i32; - #[no_mangle] - static FPU_C2: i32; - #[no_mangle] - static FPU_C3: i32; - #[no_mangle] - static FPU_RESULT_FLAGS: i32; - #[no_mangle] - static FPU_STACK_TOP: i32; - #[no_mangle] - fn fpu_set_tag_word(tag_word: i32) -> (); - #[no_mangle] - static reg8: *mut u8; - #[no_mangle] - static reg16: *mut u16; - #[no_mangle] - static reg8s: *mut i8; - #[no_mangle] - static reg16s: *mut i16; - #[no_mangle] - static reg32s: *mut i32; - #[no_mangle] - static last_op1: *mut i32; - #[no_mangle] - static last_op2: *mut i32; - #[no_mangle] - static last_op_size: *mut i32; - #[no_mangle] - static last_add_result: *mut i32; - #[no_mangle] - static last_result: *mut i32; - #[no_mangle] - static flags_changed: *mut i32; - #[no_mangle] - static flags: *mut i32; - #[no_mangle] - static page_fault: *mut bool; - #[no_mangle] - static a20_enabled: *mut bool; - #[no_mangle] - static instruction_pointer: *mut i32; - #[no_mangle] - static previous_ip: *mut i32; - #[no_mangle] - static idtr_size: *mut i32; - #[no_mangle] - static idtr_offset: *mut i32; - #[no_mangle] - static gdtr_size: *mut i32; - #[no_mangle] - static gdtr_offset: *mut i32; - #[no_mangle] - static cr: *mut i32; - #[no_mangle] - static cpl: *mut u8; - #[no_mangle] - static in_hlt: *mut bool; - #[no_mangle] - static last_virt_eip: *mut i32; - #[no_mangle] - static eip_phys: *mut i32; - #[no_mangle] - static last_virt_esp: *mut i32; - #[no_mangle] - static esp_phys: *mut i32; - #[no_mangle] - static sysenter_cs: *mut i32; - #[no_mangle] - static sysenter_esp: *mut i32; - #[no_mangle] - static sysenter_eip: *mut i32; - #[no_mangle] - static prefixes: *mut u8; - #[no_mangle] - static timestamp_counter: *mut u32; - #[no_mangle] - static sreg: *mut u16; - #[no_mangle] - static dreg: *mut i32; - #[no_mangle] - static fw_value: *mut i32; - #[no_mangle] - static segment_is_null: *mut bool; - #[no_mangle] - static segment_offsets: *mut i32; - #[no_mangle] - static segment_limits: *mut u32; - #[no_mangle] - static protected_mode: *mut bool; - #[no_mangle] - static is_32: *mut bool; - #[no_mangle] - static stack_size_32: *mut bool; - #[no_mangle] - static memory_size: *mut u32; - #[no_mangle] - static fpu_stack_empty: *mut i32; - #[no_mangle] - static mxcsr: *mut i32; - #[no_mangle] - static reg_xmm: *mut reg128; - #[no_mangle] - static current_tsc: *mut u64; - #[no_mangle] - static fpu_st: *mut f64; - #[no_mangle] - static fpu_st8: *mut u8; - #[no_mangle] - static fpu_st32: *mut i32; - #[no_mangle] - static fpu_stack_ptr: *mut u32; - #[no_mangle] - static fpu_control_word: *mut i32; - #[no_mangle] - static fpu_status_word: *mut i32; - #[no_mangle] - static fpu_opcode: *mut i32; - #[no_mangle] - static fpu_ip: *mut i32; - #[no_mangle] - static fpu_ip_selector: *mut i32; - #[no_mangle] - static fpu_dp: *mut i32; - #[no_mangle] - static fpu_dp_selector: *mut i32; - #[no_mangle] - static reg_mmx: *mut reg64; - #[no_mangle] - static opstats_buffer: *mut u32; - #[no_mangle] - static opstats_buffer_0f: *mut u32; - #[no_mangle] - static tlb_data: *mut i32; - #[no_mangle] - #[no_mangle] - #[no_mangle] - #[no_mangle] - fn load_ldt(_: i32) -> (); - #[no_mangle] - fn load_tr(_: i32) -> (); - #[no_mangle] - fn verr(_: i32) -> i32; - #[no_mangle] - fn verw(_: i32) -> i32; - #[no_mangle] - fn set_cr0(_: i32) -> i32; - #[no_mangle] - fn invlpg(_: i32) -> (); - #[no_mangle] - fn lar(_: i32, _: i32) -> i32; - #[no_mangle] - fn lsl(_: i32, _: i32) -> i32; - #[no_mangle] - fn undefined_instruction() -> (); - #[no_mangle] - fn mov_rm_r128(source: reg128, r: i32) -> (); - #[no_mangle] - fn mov_r_r128(r1: i32, r2: i32) -> (); - #[no_mangle] - fn mov_r_m128(addr: i32, r: i32) -> (); - #[no_mangle] - fn unimplemented_sse() -> (); - #[no_mangle] - fn movl_r128_m64(addr: i32, r: i32) -> (); - #[no_mangle] - fn movh_m64_r128(addr: i32, r: i32) -> (); - #[no_mangle] - fn movh_r128_m64(addr: i32, r: i32) -> (); - #[no_mangle] - fn convert_f64_to_i32(_: f64) -> i32; - #[no_mangle] - fn cpl_changed() -> (); - #[no_mangle] - fn update_cs_size(_: i32) -> (); - #[no_mangle] - fn test_o() -> bool; - #[no_mangle] - fn cmovcc16(condition: bool, value: i32, r: i32) -> (); - #[no_mangle] - fn cmovcc32(condition: bool, value: i32, r: i32) -> (); - #[no_mangle] - fn test_b() -> bool; - #[no_mangle] - fn test_z() -> bool; - #[no_mangle] - fn test_be() -> bool; - #[no_mangle] - fn test_s() -> bool; - #[no_mangle] - fn test_p() -> bool; - #[no_mangle] - fn test_l() -> bool; - #[no_mangle] - fn test_le() -> bool; - #[no_mangle] - fn pand_r128(source: reg128, r: i32) -> (); - #[no_mangle] - fn pandn_r128(source: reg128, r: i32) -> (); - #[no_mangle] - fn por_r128(source: reg128, r: i32) -> (); - #[no_mangle] - fn pxor_r128(source: reg128, r: i32) -> (); - #[no_mangle] - fn psrlw_r64(r: i32, shift: u32) -> (); - #[no_mangle] - fn psraw_r64(r: i32, shift: u32) -> (); - #[no_mangle] - fn psllw_r64(r: i32, shift: u32) -> (); - #[no_mangle] - fn psrlw_r128(r: i32, shift: u32) -> (); - #[no_mangle] - fn psraw_r128(r: i32, shift: u32) -> (); - #[no_mangle] - fn psllw_r128(r: i32, shift: u32) -> (); - #[no_mangle] - fn psrld_r64(r: i32, shift: u32) -> (); - #[no_mangle] - fn psrad_r64(r: i32, shift: u32) -> (); - #[no_mangle] - fn pslld_r64(r: i32, shift: u32) -> (); - #[no_mangle] - fn psrld_r128(r: i32, shift: u32) -> (); - #[no_mangle] - fn psrad_r128(r: i32, shift: u32) -> (); - #[no_mangle] - fn pslld_r128(r: i32, shift: u32) -> (); - #[no_mangle] - fn psrlq_r64(r: i32, shift: u32) -> (); - #[no_mangle] - fn psllq_r64(r: i32, shift: u32) -> (); - #[no_mangle] - fn psrlq_r128(r: i32, shift: u32) -> (); - #[no_mangle] - fn psllq_r128(r: i32, shift: u32) -> (); - #[no_mangle] - fn mov_r_m64(addr: i32, r: i32) -> (); - #[no_mangle] - fn jmpcc16(condition: bool, imm16: i32) -> (); - #[no_mangle] - fn jmpcc32(condition: bool, imm32: i32) -> (); - #[no_mangle] - fn setcc_reg(condition: bool, r: i32) -> (); - #[no_mangle] - fn setcc_mem(condition: bool, addr: i32) -> (); - #[no_mangle] - fn adjust_stack_reg(adjustment: i32) -> (); - #[no_mangle] - fn get_stack_pointer(offset: i32) -> i32; - #[no_mangle] - fn switch_seg(_: i32, _: i32) -> bool; - #[no_mangle] - fn cpuid() -> (); - #[no_mangle] - fn fxsave(addr: u32) -> (); - #[no_mangle] - fn fxrstor(addr: u32) -> (); - #[no_mangle] - fn getzf() -> bool; - #[no_mangle] - fn lss16(_: i32, _: i32, _: i32) -> (); - #[no_mangle] - fn lss32(_: i32, _: i32, _: i32) -> (); - #[no_mangle] - fn has_rand_int() -> bool; + fn switch_seg(seg: i32, value: i32) -> bool; #[no_mangle] fn get_rand_int() -> i32; #[no_mangle] - fn bswap(_: i32) -> i32; + fn has_rand_int() -> bool; #[no_mangle] - fn sse_comparison(op: i32, x: f64, y: f64) -> bool; + fn cpuid(); #[no_mangle] - fn sse_min(x: f64, y: f64) -> f64; + fn cpl_changed(); #[no_mangle] - fn sse_max(x: f64, y: f64) -> f64; + fn update_cs_size(cs_size: bool); #[no_mangle] - fn sse_convert_f64_to_i32(x: f64) -> i32; + fn set_cr0(cr0: i32); + #[no_mangle] + fn lsl(r: i32, v: i32) -> i32; + #[no_mangle] + fn lar(r: i32, v: i32) -> i32; + #[no_mangle] + fn verw(r: i32); + #[no_mangle] + fn verr(r: i32); + #[no_mangle] + fn load_tr(v: i32); + #[no_mangle] + fn load_ldt(v: i32); } -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed { - __f: f32, - __i: u32, -} +use cpu2::arith::{ + bsf16, bsf32, bsr16, bsr32, bt_mem, bt_reg, btc_mem, btc_reg, btr_mem, btr_reg, bts_mem, + bts_reg, popcnt, shld16, shld32, shrd16, shrd32, xadd16, xadd32, xadd8, +}; +use cpu2::arith::{ + cmp16, cmp32, cmp8, imul_reg16, imul_reg32, saturate_sd_to_sb, saturate_sd_to_sw, + saturate_sd_to_ub, saturate_sw_to_sb, saturate_sw_to_ub, saturate_ud_to_ub, saturate_uw, +}; +use cpu2::cpu::*; +use cpu2::fpu::fpu_load_m32; +use cpu2::fpu::fpu_set_tag_word; +use cpu2::global_pointers::*; +use cpu2::misc_instr::{ + adjust_stack_reg, bswap, cmovcc16, cmovcc32, fxrstor, fxsave, get_stack_pointer, getzf, + jmpcc16, jmpcc32, push16, push32, setcc_mem, setcc_reg, test_b, test_be, test_l, test_le, + test_o, test_p, test_s, test_z, +}; +use cpu2::sse_instr::*; -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_0 { - __f: f64, - __i: u64, -} +pub fn convert_f64_to_i32(x: f64) -> i32 { x as i32 } -unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { - let mut __u: unnamed = unnamed { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { - let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x >= __y) as i32; -} #[no_mangle] pub unsafe extern "C" fn instr_0F00_0_mem(mut addr: i32) -> () { c_comment!(("sldt")); @@ -2286,7 +1226,7 @@ pub unsafe extern "C" fn instr_0F34() -> () { *segment_is_null.offset(CS as isize) = 0 != 0i32; *segment_limits.offset(CS as isize) = -1i32 as u32; *segment_offsets.offset(CS as isize) = 0i32; - update_cs_size(1i32); + update_cs_size(true); *cpl.offset(0isize) = 0i32 as u8; cpl_changed(); *sreg.offset(SS as isize) = (seg + 8i32) as u16; @@ -2312,7 +1252,7 @@ pub unsafe extern "C" fn instr_0F35() -> () { *segment_is_null.offset(CS as isize) = 0 != 0i32; *segment_limits.offset(CS as isize) = -1i32 as u32; *segment_offsets.offset(CS as isize) = 0i32; - update_cs_size(1i32); + update_cs_size(true); *cpl.offset(0isize) = 3i32 as u8; cpl_changed(); *sreg.offset(SS as isize) = (seg + 24i32 | 3i32) as u16; @@ -6551,9 +5491,9 @@ pub unsafe extern "C" fn instr_0FF6(mut source: reg64, mut r: i32) -> () { let mut sum: u32 = 0i32 as u32; let mut i: u32 = 0i32 as u32; while i < 8i32 as u32 { - sum = (sum as u32).wrapping_add(abs( - destination.u8_0[i as usize] as i32 - source.u8_0[i as usize] as i32 - ) as u32) as u32 as u32; + sum = (sum as u32).wrapping_add( + (destination.u8_0[i as usize] as i32 - source.u8_0[i as usize] as i32).abs() as u32, + ) as u32 as u32; i = i.wrapping_add(1) } write_mmx64(r, sum as i32, 0i32); @@ -6575,14 +5515,14 @@ pub unsafe extern "C" fn instr_660FF6(mut source: reg128, mut r: i32) -> () { let mut sum1: u32 = 0i32 as u32; let mut i: u32 = 0i32 as u32; while i < 8i32 as u32 { - sum0 = (sum0 as u32).wrapping_add(abs( - destination.u8_0[i as usize] as i32 - source.u8_0[i as usize] as i32 - ) as u32) as u32 as u32; - sum1 = - (sum1 as u32).wrapping_add(abs(destination.u8_0[i.wrapping_add(8i32 as u32) as usize] - as i32 + sum0 = (sum0 as u32).wrapping_add( + (destination.u8_0[i as usize] as i32 - source.u8_0[i as usize] as i32).abs() as u32, + ) as u32 as u32; + sum1 = (sum1 as u32).wrapping_add( + (destination.u8_0[i.wrapping_add(8i32 as u32) as usize] as i32 - source.u8_0[i.wrapping_add(8i32 as u32) as usize] as i32) - as u32) as u32 as u32; + .abs() as u32, + ) as u32 as u32; i = i.wrapping_add(1) } write_xmm128(r, sum0 as i32, 0i32, sum1 as i32, 0i32); @@ -7075,10 +6015,10 @@ pub unsafe extern "C" fn instr_0F51(mut source: reg128, mut r: i32) -> () { c_comment!(("sqrtps xmm, xmm/mem128")); let mut result: reg128 = reg128 { f32_0: [ - sqrtf(source.f32_0[0usize]), - sqrtf(source.f32_0[1usize]), - sqrtf(source.f32_0[2usize]), - sqrtf(source.f32_0[3usize]), + source.f32_0[0usize].sqrt(), + source.f32_0[1usize].sqrt(), + source.f32_0[2usize].sqrt(), + source.f32_0[3usize].sqrt(), ], }; write_xmm_reg128(r, result); @@ -7095,7 +6035,7 @@ pub unsafe extern "C" fn instr_0F51_mem(mut addr: i32, mut r: i32) -> () { pub unsafe extern "C" fn instr_660F51(mut source: reg128, mut r: i32) -> () { c_comment!(("sqrtpd xmm, xmm/mem128")); let mut result: reg128 = reg128 { - f64_0: [sqrt(source.f64_0[0usize]), sqrt(source.f64_0[1usize])], + f64_0: [source.f64_0[0usize].sqrt(), source.f64_0[1usize].sqrt()], }; write_xmm_reg128(r, result); } @@ -7111,7 +6051,7 @@ pub unsafe extern "C" fn instr_660F51_mem(mut addr: i32, mut r: i32) -> () { pub unsafe extern "C" fn instr_F20F51(mut source: reg64, mut r: i32) -> () { c_comment!(("sqrtsd xmm, xmm/mem64")); let mut result: reg64 = reg64 { - f64_0: [sqrt(source.f64_0[0usize])], + f64_0: [source.f64_0[0usize].sqrt()], }; write_xmm64(r, result); } @@ -7126,7 +6066,7 @@ pub unsafe extern "C" fn instr_F20F51_mem(mut addr: i32, mut r: i32) -> () { #[no_mangle] pub unsafe extern "C" fn instr_F30F51(mut source: f32, mut r: i32) -> () { c_comment!(("sqrtss xmm, xmm/mem32")); - write_xmm_f32(r, sqrtf(source)); + write_xmm_f32(r, source.sqrt()); } #[no_mangle] pub unsafe extern "C" fn instr_F30F51_reg(mut r1: i32, mut r2: i32) -> () { diff --git a/src/rust/cpu2/memory.rs b/src/rust/cpu2/memory.rs index 0a282897..807ba846 100644 --- a/src/rust/cpu2/memory.rs +++ b/src/rust/cpu2/memory.rs @@ -1,872 +1,44 @@ -#![allow -( dead_code , mutable_transmutes , non_camel_case_types , non_snake_case , -non_upper_case_globals , unused_mut )] -#![feature ( extern_types , libc )] +#![allow( + dead_code, + mutable_transmutes, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_mut +)] +#![feature(extern_types, libc)] extern "C" { + #[no_mangle] + fn mmap_read8(addr: u32) -> i32; + #[no_mangle] + fn mmap_read16(addr: u32) -> i32; + #[no_mangle] + fn mmap_read32(addr: u32) -> i32; #[no_mangle] - static FLAG_CARRY: i32; + fn mmap_write8(addr: u32, value: i32); #[no_mangle] - static FLAG_PARITY: i32; + fn mmap_write16(addr: u32, value: i32); #[no_mangle] - static FLAG_ADJUST: i32; + fn mmap_write32(addr: u32, value: i32); #[no_mangle] - static FLAG_ZERO: i32; - #[no_mangle] - static FLAG_SIGN: i32; - #[no_mangle] - static FLAG_TRAP: i32; - #[no_mangle] - static FLAG_INTERRUPT: i32; - #[no_mangle] - static FLAG_DIRECTION: i32; - #[no_mangle] - static FLAG_OVERFLOW: i32; - #[no_mangle] - static FLAG_IOPL: i32; - #[no_mangle] - static FLAG_NT: i32; - #[no_mangle] - static FLAG_RF: i32; - #[no_mangle] - static FLAG_VM: i32; - #[no_mangle] - static FLAG_AC: i32; - #[no_mangle] - static FLAG_VIF: i32; - #[no_mangle] - static FLAG_VIP: i32; - #[no_mangle] - static FLAG_ID: i32; - #[no_mangle] - static FLAGS_DEFAULT: i32; - #[no_mangle] - static FLAGS_MASK: i32; - #[no_mangle] - static FLAGS_ALL: i32; - #[no_mangle] - static OPSIZE_8: i32; - #[no_mangle] - static OPSIZE_16: i32; - #[no_mangle] - static OPSIZE_32: i32; - #[no_mangle] - static EAX: i32; - #[no_mangle] - static ECX: i32; - #[no_mangle] - static EDX: i32; - #[no_mangle] - static EBX: i32; - #[no_mangle] - static ESP: i32; - #[no_mangle] - static EBP: i32; - #[no_mangle] - static ESI: i32; - #[no_mangle] - static EDI: i32; - #[no_mangle] - static AX: i32; - #[no_mangle] - static CX: i32; - #[no_mangle] - static DX: i32; - #[no_mangle] - static BX: i32; - #[no_mangle] - static SP: i32; - #[no_mangle] - static BP: i32; - #[no_mangle] - static SI: i32; - #[no_mangle] - static DI: i32; - #[no_mangle] - static AL: i32; - #[no_mangle] - static CL: i32; - #[no_mangle] - static DL: i32; - #[no_mangle] - static BL: i32; - #[no_mangle] - static AH: i32; - #[no_mangle] - static CH: i32; - #[no_mangle] - static DH: i32; - #[no_mangle] - static BH: i32; - #[no_mangle] - static ES: i32; - #[no_mangle] - static CS: i32; - #[no_mangle] - static SS: i32; - #[no_mangle] - static DS: i32; - #[no_mangle] - static FS: i32; - #[no_mangle] - static GS: i32; - #[no_mangle] - static TR: i32; - #[no_mangle] - static LDTR: i32; - #[no_mangle] - static PAGE_TABLE_PRESENT_MASK: i32; - #[no_mangle] - static PAGE_TABLE_RW_MASK: i32; - #[no_mangle] - static PAGE_TABLE_USER_MASK: i32; - #[no_mangle] - static PAGE_TABLE_ACCESSED_MASK: i32; - #[no_mangle] - static PAGE_TABLE_DIRTY_MASK: i32; - #[no_mangle] - static PAGE_TABLE_PSE_MASK: i32; - #[no_mangle] - static PAGE_TABLE_GLOBAL_MASK: i32; - #[no_mangle] - static MMAP_BLOCK_BITS: i32; - #[no_mangle] - static MMAP_BLOCK_SIZE: i32; - #[no_mangle] - static CR0_PE: i32; - #[no_mangle] - static CR0_MP: i32; - #[no_mangle] - static CR0_EM: i32; - #[no_mangle] - static CR0_TS: i32; - #[no_mangle] - static CR0_ET: i32; - #[no_mangle] - static CR0_WP: i32; - #[no_mangle] - static CR0_NW: i32; - #[no_mangle] - static CR0_CD: i32; - #[no_mangle] - static CR0_PG: i32; - #[no_mangle] - static CR4_VME: i32; - #[no_mangle] - static CR4_PVI: i32; - #[no_mangle] - static CR4_TSD: i32; - #[no_mangle] - static CR4_PSE: i32; - #[no_mangle] - static CR4_DE: i32; - #[no_mangle] - static CR4_PAE: i32; - #[no_mangle] - static CR4_PGE: i32; - #[no_mangle] - static IA32_SYSENTER_CS: i32; - #[no_mangle] - static IA32_SYSENTER_ESP: i32; - #[no_mangle] - static IA32_SYSENTER_EIP: i32; - #[no_mangle] - static IA32_TIME_STAMP_COUNTER: i32; - #[no_mangle] - static IA32_PLATFORM_ID: i32; - #[no_mangle] - static IA32_APIC_BASE_MSR: i32; - #[no_mangle] - static IA32_BIOS_SIGN_ID: i32; - #[no_mangle] - static MSR_PLATFORM_INFO: i32; - #[no_mangle] - static MSR_MISC_FEATURE_ENABLES: i32; - #[no_mangle] - static IA32_MISC_ENABLE: i32; - #[no_mangle] - static IA32_RTIT_CTL: i32; - #[no_mangle] - static MSR_SMI_COUNT: i32; - #[no_mangle] - static IA32_MCG_CAP: i32; - #[no_mangle] - static IA32_KERNEL_GS_BASE: i32; - #[no_mangle] - static MSR_PKG_C2_RESIDENCY: i32; - #[no_mangle] - static IA32_APIC_BASE_BSP: i32; - #[no_mangle] - static IA32_APIC_BASE_EXTD: i32; - #[no_mangle] - static IA32_APIC_BASE_EN: i32; - #[no_mangle] - static APIC_ADDRESS: i32; - #[no_mangle] - static SEG_PREFIX_NONE: i32; - #[no_mangle] - static SEG_PREFIX_ZERO: i32; - #[no_mangle] - static PREFIX_MASK_REP: i32; - #[no_mangle] - static PREFIX_REPZ: i32; - #[no_mangle] - static PREFIX_REPNZ: i32; - #[no_mangle] - static PREFIX_MASK_SEGMENT: i32; - #[no_mangle] - static PREFIX_MASK_OPSIZE: i32; - #[no_mangle] - static PREFIX_MASK_ADDRSIZE: i32; - #[no_mangle] - static PREFIX_F2: i32; - #[no_mangle] - static PREFIX_F3: i32; - #[no_mangle] - static PREFIX_66: i32; - #[no_mangle] - static LOG_CPU: i32; - #[no_mangle] - static A20_MASK: i32; - #[no_mangle] - static A20_MASK16: i32; - #[no_mangle] - static A20_MASK32: i32; - #[no_mangle] - static MXCSR_MASK: i32; - #[no_mangle] - fn __fpclassifyl(_: f64) -> i32; + fn mmap_write128(addr: u32, v0: i32, v1: i32, v2: i32, v3: i32); #[no_mangle] - static reg8: *mut u8; + fn jit_dirty_cache_small(low: u32, high: u32); #[no_mangle] - static reg16: *mut u16; - #[no_mangle] - static reg8s: *mut i8; - #[no_mangle] - static reg16s: *mut i16; - #[no_mangle] - static reg32s: *mut i32; - #[no_mangle] - static last_op1: *mut i32; - #[no_mangle] - static last_op2: *mut i32; - #[no_mangle] - static last_op_size: *mut i32; - #[no_mangle] - static last_add_result: *mut i32; - #[no_mangle] - static last_result: *mut i32; - #[no_mangle] - static flags_changed: *mut i32; - #[no_mangle] - static flags: *mut i32; - #[no_mangle] - static page_fault: *mut bool; - #[no_mangle] - static a20_enabled: *mut bool; - #[no_mangle] - static instruction_pointer: *mut i32; - #[no_mangle] - static previous_ip: *mut i32; - #[no_mangle] - static idtr_size: *mut i32; - #[no_mangle] - static idtr_offset: *mut i32; - #[no_mangle] - static gdtr_size: *mut i32; - #[no_mangle] - static gdtr_offset: *mut i32; - #[no_mangle] - static cr: *mut i32; - #[no_mangle] - static cpl: *mut u8; - #[no_mangle] - static in_hlt: *mut bool; - #[no_mangle] - static last_virt_eip: *mut i32; - #[no_mangle] - static eip_phys: *mut i32; - #[no_mangle] - static last_virt_esp: *mut i32; - #[no_mangle] - static esp_phys: *mut i32; - #[no_mangle] - static sysenter_cs: *mut i32; - #[no_mangle] - static sysenter_esp: *mut i32; - #[no_mangle] - static sysenter_eip: *mut i32; - #[no_mangle] - static prefixes: *mut u8; - #[no_mangle] - static timestamp_counter: *mut u32; - #[no_mangle] - static sreg: *mut u16; - #[no_mangle] - static dreg: *mut i32; - #[no_mangle] - static fw_value: *mut i32; - #[no_mangle] - static segment_is_null: *mut bool; - #[no_mangle] - static segment_offsets: *mut i32; - #[no_mangle] - static segment_limits: *mut u32; - #[no_mangle] - static protected_mode: *mut bool; - #[no_mangle] - static is_32: *mut bool; - #[no_mangle] - static stack_size_32: *mut bool; - #[no_mangle] - static memory_size: *mut u32; - #[no_mangle] - static fpu_stack_empty: *mut i32; - #[no_mangle] - static mxcsr: *mut i32; - #[no_mangle] - static reg_xmm: *mut reg128; - #[no_mangle] - static current_tsc: *mut u64; - #[no_mangle] - static fpu_st: *mut f64; - #[no_mangle] - static fpu_st8: *mut u8; - #[no_mangle] - static fpu_st32: *mut i32; - #[no_mangle] - static fpu_stack_ptr: *mut u32; - #[no_mangle] - static fpu_control_word: *mut i32; - #[no_mangle] - static fpu_status_word: *mut i32; - #[no_mangle] - static fpu_opcode: *mut i32; - #[no_mangle] - static fpu_ip: *mut i32; - #[no_mangle] - static fpu_ip_selector: *mut i32; - #[no_mangle] - static fpu_dp: *mut i32; - #[no_mangle] - static fpu_dp_selector: *mut i32; - #[no_mangle] - static reg_mmx: *mut reg64; - #[no_mangle] - static opstats_buffer: *mut u32; - #[no_mangle] - static opstats_buffer_0f: *mut u32; - #[no_mangle] - static tlb_data: *mut i32; - #[no_mangle] - static mut mem8: *mut u8; - #[no_mangle] - static mut mem16: *mut u16; - #[no_mangle] - static mut mem32s: *mut i32; - #[no_mangle] - static mut jit_block_boundary: bool; - #[no_mangle] - static VALID_TLB_ENTRY_MAX: i32; - #[no_mangle] - static mut valid_tlb_entries: [i32; 10000]; - #[no_mangle] - static mut valid_tlb_entries_count: i32; - #[no_mangle] - static TLB_VALID: i32; - #[no_mangle] - static TLB_READONLY: i32; - #[no_mangle] - static TLB_NO_USER: i32; - #[no_mangle] - static TLB_IN_MAPPED_RANGE: i32; - #[no_mangle] - static TLB_GLOBAL: i32; - #[no_mangle] - static TLB_HAS_CODE: i32; - #[no_mangle] - static CPU_EXCEPTION_DE: i32; - #[no_mangle] - static CPU_EXCEPTION_DB: i32; - #[no_mangle] - static CPU_EXCEPTION_NMI: i32; - #[no_mangle] - static CPU_EXCEPTION_BP: i32; - #[no_mangle] - static CPU_EXCEPTION_OF: i32; - #[no_mangle] - static CPU_EXCEPTION_BR: i32; - #[no_mangle] - static CPU_EXCEPTION_UD: i32; - #[no_mangle] - static CPU_EXCEPTION_NM: i32; - #[no_mangle] - static CPU_EXCEPTION_DF: i32; - #[no_mangle] - static CPU_EXCEPTION_TS: i32; - #[no_mangle] - static CPU_EXCEPTION_NP: i32; - #[no_mangle] - static CPU_EXCEPTION_SS: i32; - #[no_mangle] - static CPU_EXCEPTION_GP: i32; - #[no_mangle] - static CPU_EXCEPTION_PF: i32; - #[no_mangle] - static CPU_EXCEPTION_MF: i32; - #[no_mangle] - static CPU_EXCEPTION_AC: i32; - #[no_mangle] - static CPU_EXCEPTION_MC: i32; - #[no_mangle] - static CPU_EXCEPTION_XM: i32; - #[no_mangle] - static CPU_EXCEPTION_VE: i32; - #[no_mangle] - fn mmap_read16(_: u32) -> i32; - #[no_mangle] - fn mmap_read32(_: u32) -> i32; - #[no_mangle] - fn mmap_read8(_: u32) -> i32; - #[no_mangle] - fn mmap_write128(_: u32, _: i32, _: i32, _: i32, _: i32) -> (); - #[no_mangle] - fn mmap_write16(_: u32, _: i32) -> (); - #[no_mangle] - fn mmap_write32(_: u32, _: i32) -> (); - #[no_mangle] - fn mmap_write8(_: u32, _: i32) -> (); - #[no_mangle] - fn jit_dirty_cache_single(phys_addr: u32) -> (); - #[no_mangle] - fn jit_dirty_cache_small(phys_start_addr: u32, phys_end_addr: u32) -> (); - #[no_mangle] - static mut profiler_stat_arr: [profiler_stat; 37]; + fn jit_dirty_cache_single(addr: u32); } -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed { - __f: f64, - __i: u64, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union reg128 { - i8_0: [i8; 16], - i16_0: [i16; 8], - i32_0: [i32; 4], - i64_0: [i64; 2], - u8_0: [u8; 16], - u16_0: [u16; 8], - u32_0: [u32; 4], - u64_0: [u64; 2], - f32_0: [f32; 4], - f64_0: [f64; 2], -} +use cpu2::cpu::*; +use cpu2::global_pointers::*; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct profiler_stat { - pub count: i32, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_0 { - __f: f32, - __i: u32, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub union reg64 { - i8_0: [i8; 8], - i16_0: [i16; 4], - i32_0: [i32; 2], - i64_0: [i64; 1], - u8_0: [u8; 8], - u16_0: [u16; 4], - u32_0: [u32; 2], - u64_0: [u64; 1], - f32_0: [f32; 2], - f64_0: [f64; 1], -} -unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { - let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { - let mut __u: unnamed = unnamed { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x >= __y) as i32; -} #[no_mangle] pub unsafe extern "C" fn in_mapped_range(mut addr: u32) -> bool { return addr >= 655360i32 as u32 && addr < 786432i32 as u32 || addr >= *memory_size; } + #[no_mangle] pub unsafe extern "C" fn read8(mut addr: u32) -> i32 { if 0 != USE_A20 as i32 && 0 != *a20_enabled as i32 { diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index 812cf6f3..4decc8ff 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -9,861 +9,9 @@ #![feature(extern_types, libc)] use cpu2::cpu::*; -use cpu2::fpu::fpu_load_m80; +use cpu2::fpu::{fpu_load_m80, fpu_load_status_word, fpu_set_status_word, fpu_store_m80}; +use cpu2::global_pointers::*; -extern "C" { - - #[no_mangle] - fn __fpclassifyl(_: f64) -> i32; - - #[no_mangle] - static FLAG_CARRY: i32; - #[no_mangle] - static FLAG_PARITY: i32; - #[no_mangle] - static FLAG_ADJUST: i32; - #[no_mangle] - static FLAG_ZERO: i32; - #[no_mangle] - static FLAG_SIGN: i32; - #[no_mangle] - static FLAG_TRAP: i32; - #[no_mangle] - static FLAG_INTERRUPT: i32; - #[no_mangle] - static FLAG_DIRECTION: i32; - #[no_mangle] - static FLAG_OVERFLOW: i32; - #[no_mangle] - static FLAG_IOPL: i32; - #[no_mangle] - static FLAG_NT: i32; - #[no_mangle] - static FLAG_RF: i32; - #[no_mangle] - static FLAG_VM: i32; - #[no_mangle] - static FLAG_AC: i32; - #[no_mangle] - static FLAG_VIF: i32; - #[no_mangle] - static FLAG_VIP: i32; - #[no_mangle] - static FLAG_ID: i32; - #[no_mangle] - static FLAGS_DEFAULT: i32; - #[no_mangle] - static FLAGS_MASK: i32; - #[no_mangle] - static FLAGS_ALL: i32; - #[no_mangle] - static OPSIZE_8: i32; - #[no_mangle] - static OPSIZE_16: i32; - #[no_mangle] - static OPSIZE_32: i32; - #[no_mangle] - static EAX: i32; - #[no_mangle] - static ECX: i32; - #[no_mangle] - static EDX: i32; - #[no_mangle] - static EBX: i32; - #[no_mangle] - static ESP: i32; - #[no_mangle] - static EBP: i32; - #[no_mangle] - static ESI: i32; - #[no_mangle] - static EDI: i32; - #[no_mangle] - static AX: i32; - #[no_mangle] - static CX: i32; - #[no_mangle] - static DX: i32; - #[no_mangle] - static BX: i32; - #[no_mangle] - static SP: i32; - #[no_mangle] - static BP: i32; - #[no_mangle] - static SI: i32; - #[no_mangle] - static DI: i32; - #[no_mangle] - static AL: i32; - #[no_mangle] - static CL: i32; - #[no_mangle] - static DL: i32; - #[no_mangle] - static BL: i32; - #[no_mangle] - static AH: i32; - #[no_mangle] - static CH: i32; - #[no_mangle] - static DH: i32; - #[no_mangle] - static BH: i32; - #[no_mangle] - static ES: i32; - #[no_mangle] - static CS: i32; - #[no_mangle] - static SS: i32; - #[no_mangle] - static DS: i32; - #[no_mangle] - static FS: i32; - #[no_mangle] - static GS: i32; - #[no_mangle] - static TR: i32; - #[no_mangle] - static LDTR: i32; - #[no_mangle] - static PAGE_TABLE_PRESENT_MASK: i32; - #[no_mangle] - static PAGE_TABLE_RW_MASK: i32; - #[no_mangle] - static PAGE_TABLE_USER_MASK: i32; - #[no_mangle] - static PAGE_TABLE_ACCESSED_MASK: i32; - #[no_mangle] - static PAGE_TABLE_DIRTY_MASK: i32; - #[no_mangle] - static PAGE_TABLE_PSE_MASK: i32; - #[no_mangle] - static PAGE_TABLE_GLOBAL_MASK: i32; - #[no_mangle] - static MMAP_BLOCK_BITS: i32; - #[no_mangle] - static MMAP_BLOCK_SIZE: i32; - #[no_mangle] - static CR0_PE: i32; - #[no_mangle] - static CR0_MP: i32; - #[no_mangle] - static CR0_EM: i32; - #[no_mangle] - static CR0_TS: i32; - #[no_mangle] - static CR0_ET: i32; - #[no_mangle] - static CR0_WP: i32; - #[no_mangle] - static CR0_NW: i32; - #[no_mangle] - static CR0_CD: i32; - #[no_mangle] - static CR0_PG: i32; - #[no_mangle] - static CR4_VME: i32; - #[no_mangle] - static CR4_PVI: i32; - #[no_mangle] - static CR4_TSD: i32; - #[no_mangle] - static CR4_PSE: i32; - #[no_mangle] - static CR4_DE: i32; - #[no_mangle] - static CR4_PAE: i32; - #[no_mangle] - static CR4_PGE: i32; - #[no_mangle] - static IA32_SYSENTER_CS: i32; - #[no_mangle] - static IA32_SYSENTER_ESP: i32; - #[no_mangle] - static IA32_SYSENTER_EIP: i32; - #[no_mangle] - static IA32_TIME_STAMP_COUNTER: i32; - #[no_mangle] - static IA32_PLATFORM_ID: i32; - #[no_mangle] - static IA32_APIC_BASE_MSR: i32; - #[no_mangle] - static IA32_BIOS_SIGN_ID: i32; - #[no_mangle] - static MSR_PLATFORM_INFO: i32; - #[no_mangle] - static MSR_MISC_FEATURE_ENABLES: i32; - #[no_mangle] - static IA32_MISC_ENABLE: i32; - #[no_mangle] - static IA32_RTIT_CTL: i32; - #[no_mangle] - static MSR_SMI_COUNT: i32; - #[no_mangle] - static IA32_MCG_CAP: i32; - #[no_mangle] - static IA32_KERNEL_GS_BASE: i32; - #[no_mangle] - static MSR_PKG_C2_RESIDENCY: i32; - #[no_mangle] - static IA32_APIC_BASE_BSP: i32; - #[no_mangle] - static IA32_APIC_BASE_EXTD: i32; - #[no_mangle] - static IA32_APIC_BASE_EN: i32; - #[no_mangle] - static APIC_ADDRESS: i32; - #[no_mangle] - static SEG_PREFIX_NONE: i32; - #[no_mangle] - static SEG_PREFIX_ZERO: i32; - #[no_mangle] - static PREFIX_MASK_REP: i32; - #[no_mangle] - static PREFIX_REPZ: i32; - #[no_mangle] - static PREFIX_REPNZ: i32; - #[no_mangle] - static PREFIX_MASK_SEGMENT: i32; - #[no_mangle] - static PREFIX_MASK_OPSIZE: i32; - #[no_mangle] - static PREFIX_MASK_ADDRSIZE: i32; - #[no_mangle] - static PREFIX_F2: i32; - #[no_mangle] - static PREFIX_F3: i32; - #[no_mangle] - static PREFIX_66: i32; - #[no_mangle] - static LOG_CPU: i32; - #[no_mangle] - static A20_MASK: i32; - #[no_mangle] - static A20_MASK16: i32; - #[no_mangle] - static A20_MASK32: i32; - #[no_mangle] - static MXCSR_MASK: i32; - #[no_mangle] - fn dbg_log(m: *const i8) -> (); - #[no_mangle] - fn c_comment(m: *const i8) -> (); - #[no_mangle] - static mut mem8: *mut u8; - #[no_mangle] - static mut mem16: *mut u16; - #[no_mangle] - static mut mem32s: *mut i32; - #[no_mangle] - static mut jit_block_boundary: bool; - #[no_mangle] - static VALID_TLB_ENTRY_MAX: i32; - #[no_mangle] - static mut valid_tlb_entries: [i32; 10000]; - #[no_mangle] - static mut valid_tlb_entries_count: i32; - #[no_mangle] - static TLB_VALID: i32; - #[no_mangle] - static TLB_READONLY: i32; - #[no_mangle] - static TLB_NO_USER: i32; - #[no_mangle] - static TLB_IN_MAPPED_RANGE: i32; - #[no_mangle] - static TLB_GLOBAL: i32; - #[no_mangle] - static TLB_HAS_CODE: i32; - #[no_mangle] - static CPU_EXCEPTION_DE: i32; - #[no_mangle] - static CPU_EXCEPTION_DB: i32; - #[no_mangle] - static CPU_EXCEPTION_NMI: i32; - #[no_mangle] - static CPU_EXCEPTION_BP: i32; - #[no_mangle] - static CPU_EXCEPTION_OF: i32; - #[no_mangle] - static CPU_EXCEPTION_BR: i32; - #[no_mangle] - static CPU_EXCEPTION_UD: i32; - #[no_mangle] - static CPU_EXCEPTION_NM: i32; - #[no_mangle] - static CPU_EXCEPTION_DF: i32; - #[no_mangle] - static CPU_EXCEPTION_TS: i32; - #[no_mangle] - static CPU_EXCEPTION_NP: i32; - #[no_mangle] - static CPU_EXCEPTION_SS: i32; - #[no_mangle] - static CPU_EXCEPTION_GP: i32; - #[no_mangle] - static CPU_EXCEPTION_PF: i32; - #[no_mangle] - static CPU_EXCEPTION_MF: i32; - #[no_mangle] - static CPU_EXCEPTION_AC: i32; - #[no_mangle] - static CPU_EXCEPTION_MC: i32; - #[no_mangle] - static CPU_EXCEPTION_XM: i32; - #[no_mangle] - static CPU_EXCEPTION_VE: i32; - #[no_mangle] - fn get_seg_cs() -> i32; - #[no_mangle] - fn get_seg_ss() -> i32; - #[no_mangle] - fn trigger_gp_non_raising(code: i32) -> (); - #[no_mangle] - fn write_reg8(index: i32, value: i32) -> (); - #[no_mangle] - fn write_reg16(index: i32, value: i32) -> (); - #[no_mangle] - fn write_reg32(index: i32, value: i32) -> (); - #[no_mangle] - fn get_reg_asize(reg: i32) -> i32; - #[no_mangle] - fn decr_ecx_asize() -> i32; - #[no_mangle] - static M_LOG2E: f64; - #[no_mangle] - static M_LN2: f64; - #[no_mangle] - static M_LN10: f64; - #[no_mangle] - static M_PI: f64; - #[no_mangle] - static FPU_C0: i32; - #[no_mangle] - static FPU_C1: i32; - #[no_mangle] - static FPU_C2: i32; - #[no_mangle] - static FPU_C3: i32; - #[no_mangle] - static FPU_RESULT_FLAGS: i32; - #[no_mangle] - static FPU_STACK_TOP: i32; - #[no_mangle] - fn fpu_load_status_word() -> i32; - #[no_mangle] - fn fpu_set_status_word(sw: i32) -> (); - #[no_mangle] - fn fpu_store_m80(addr: u32, n: f64) -> (); - #[no_mangle] - static reg8: *mut u8; - #[no_mangle] - static reg16: *mut u16; - #[no_mangle] - static reg8s: *mut i8; - #[no_mangle] - static reg16s: *mut i16; - #[no_mangle] - static reg32s: *mut i32; - #[no_mangle] - static last_op1: *mut i32; - #[no_mangle] - static last_op2: *mut i32; - #[no_mangle] - static last_op_size: *mut i32; - #[no_mangle] - static last_add_result: *mut i32; - #[no_mangle] - static last_result: *mut i32; - #[no_mangle] - static flags_changed: *mut i32; - #[no_mangle] - static flags: *mut i32; - #[no_mangle] - static page_fault: *mut bool; - #[no_mangle] - static a20_enabled: *mut bool; - #[no_mangle] - static instruction_pointer: *mut i32; - #[no_mangle] - static previous_ip: *mut i32; - #[no_mangle] - static idtr_size: *mut i32; - #[no_mangle] - static idtr_offset: *mut i32; - #[no_mangle] - static gdtr_size: *mut i32; - #[no_mangle] - static gdtr_offset: *mut i32; - #[no_mangle] - static cr: *mut i32; - #[no_mangle] - static cpl: *mut u8; - #[no_mangle] - static in_hlt: *mut bool; - #[no_mangle] - static last_virt_eip: *mut i32; - #[no_mangle] - static eip_phys: *mut i32; - #[no_mangle] - static last_virt_esp: *mut i32; - #[no_mangle] - static esp_phys: *mut i32; - #[no_mangle] - static sysenter_cs: *mut i32; - #[no_mangle] - static sysenter_esp: *mut i32; - #[no_mangle] - static sysenter_eip: *mut i32; - #[no_mangle] - static prefixes: *mut u8; - #[no_mangle] - static timestamp_counter: *mut u32; - #[no_mangle] - static sreg: *mut u16; - #[no_mangle] - static dreg: *mut i32; - #[no_mangle] - static fw_value: *mut i32; - #[no_mangle] - static segment_is_null: *mut bool; - #[no_mangle] - static segment_offsets: *mut i32; - #[no_mangle] - static segment_limits: *mut u32; - #[no_mangle] - static protected_mode: *mut bool; - #[no_mangle] - static is_32: *mut bool; - #[no_mangle] - static stack_size_32: *mut bool; - #[no_mangle] - static memory_size: *mut u32; - #[no_mangle] - static fpu_stack_empty: *mut i32; - #[no_mangle] - static mxcsr: *mut i32; - #[no_mangle] - static reg_xmm: *mut reg128; - #[no_mangle] - static current_tsc: *mut u64; - #[no_mangle] - static fpu_st: *mut f64; - #[no_mangle] - static fpu_st8: *mut u8; - #[no_mangle] - static fpu_st32: *mut i32; - #[no_mangle] - static fpu_stack_ptr: *mut u32; - #[no_mangle] - static fpu_control_word: *mut i32; - #[no_mangle] - static fpu_status_word: *mut i32; - #[no_mangle] - static fpu_opcode: *mut i32; - #[no_mangle] - static fpu_ip: *mut i32; - #[no_mangle] - static fpu_ip_selector: *mut i32; - #[no_mangle] - static fpu_dp: *mut i32; - #[no_mangle] - static fpu_dp_selector: *mut i32; - #[no_mangle] - static reg_mmx: *mut reg64; - #[no_mangle] - static opstats_buffer: *mut u32; - #[no_mangle] - static opstats_buffer_0f: *mut u32; - #[no_mangle] - static tlb_data: *mut i32; -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed { - __f: f64, - __i: u64, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_0 { - __f: f32, - __i: u32, -} - -unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { - let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { - let mut __u: unnamed = unnamed { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x >= __y) as i32; -} #[no_mangle] pub unsafe extern "C" fn getcf() -> bool { if 0 != *flags_changed & 1i32 { @@ -1360,3 +508,6 @@ pub unsafe extern "C" fn xchg32r(mut r32: i32) -> () { *reg32s.offset(EAX as isize) = *reg32s.offset(r32 as isize); *reg32s.offset(r32 as isize) = tmp; } + +#[no_mangle] +pub unsafe fn bswap(r: i32) { write_reg32(r, read_reg32(r).swap_bytes()) } diff --git a/src/rust/cpu2/mod.rs b/src/rust/cpu2/mod.rs index 16c5437e..5c1a564c 100644 --- a/src/rust/cpu2/mod.rs +++ b/src/rust/cpu2/mod.rs @@ -16,6 +16,5 @@ pub mod memory; pub mod misc_instr; pub mod modrm; pub mod profiler; -pub mod shared; pub mod sse_instr; pub mod string; diff --git a/src/rust/cpu2/modrm.rs b/src/rust/cpu2/modrm.rs index 0d1f2487..0db6f43f 100644 --- a/src/rust/cpu2/modrm.rs +++ b/src/rust/cpu2/modrm.rs @@ -9,848 +9,8 @@ #![feature(extern_types, libc)] use cpu2::cpu::*; +use cpu2::global_pointers::*; -extern "C" { - - #[no_mangle] - fn __fpclassifyl(_: f64) -> i32; - #[no_mangle] - static FLAG_CARRY: i32; - #[no_mangle] - static FLAG_PARITY: i32; - #[no_mangle] - static FLAG_ADJUST: i32; - #[no_mangle] - static FLAG_ZERO: i32; - #[no_mangle] - static FLAG_SIGN: i32; - #[no_mangle] - static FLAG_TRAP: i32; - #[no_mangle] - static FLAG_INTERRUPT: i32; - #[no_mangle] - static FLAG_DIRECTION: i32; - #[no_mangle] - static FLAG_OVERFLOW: i32; - #[no_mangle] - static FLAG_IOPL: i32; - #[no_mangle] - static FLAG_NT: i32; - #[no_mangle] - static FLAG_RF: i32; - #[no_mangle] - static FLAG_VM: i32; - #[no_mangle] - static FLAG_AC: i32; - #[no_mangle] - static FLAG_VIF: i32; - #[no_mangle] - static FLAG_VIP: i32; - #[no_mangle] - static FLAG_ID: i32; - #[no_mangle] - static FLAGS_DEFAULT: i32; - #[no_mangle] - static FLAGS_MASK: i32; - #[no_mangle] - static FLAGS_ALL: i32; - #[no_mangle] - static OPSIZE_8: i32; - #[no_mangle] - static OPSIZE_16: i32; - #[no_mangle] - static OPSIZE_32: i32; - #[no_mangle] - static EAX: i32; - #[no_mangle] - static ECX: i32; - #[no_mangle] - static EDX: i32; - #[no_mangle] - static EBX: i32; - #[no_mangle] - static ESP: i32; - #[no_mangle] - static EBP: i32; - #[no_mangle] - static ESI: i32; - #[no_mangle] - static EDI: i32; - #[no_mangle] - static AX: i32; - #[no_mangle] - static CX: i32; - #[no_mangle] - static DX: i32; - #[no_mangle] - static BX: i32; - #[no_mangle] - static SP: i32; - #[no_mangle] - static BP: i32; - #[no_mangle] - static SI: i32; - #[no_mangle] - static DI: i32; - #[no_mangle] - static AL: i32; - #[no_mangle] - static CL: i32; - #[no_mangle] - static DL: i32; - #[no_mangle] - static BL: i32; - #[no_mangle] - static AH: i32; - #[no_mangle] - static CH: i32; - #[no_mangle] - static DH: i32; - #[no_mangle] - static BH: i32; - #[no_mangle] - static ES: i32; - #[no_mangle] - static CS: i32; - #[no_mangle] - static SS: i32; - #[no_mangle] - static DS: i32; - #[no_mangle] - static FS: i32; - #[no_mangle] - static GS: i32; - #[no_mangle] - static TR: i32; - #[no_mangle] - static LDTR: i32; - #[no_mangle] - static PAGE_TABLE_PRESENT_MASK: i32; - #[no_mangle] - static PAGE_TABLE_RW_MASK: i32; - #[no_mangle] - static PAGE_TABLE_USER_MASK: i32; - #[no_mangle] - static PAGE_TABLE_ACCESSED_MASK: i32; - #[no_mangle] - static PAGE_TABLE_DIRTY_MASK: i32; - #[no_mangle] - static PAGE_TABLE_PSE_MASK: i32; - #[no_mangle] - static PAGE_TABLE_GLOBAL_MASK: i32; - #[no_mangle] - static MMAP_BLOCK_BITS: i32; - #[no_mangle] - static MMAP_BLOCK_SIZE: i32; - #[no_mangle] - static CR0_PE: i32; - #[no_mangle] - static CR0_MP: i32; - #[no_mangle] - static CR0_EM: i32; - #[no_mangle] - static CR0_TS: i32; - #[no_mangle] - static CR0_ET: i32; - #[no_mangle] - static CR0_WP: i32; - #[no_mangle] - static CR0_NW: i32; - #[no_mangle] - static CR0_CD: i32; - #[no_mangle] - static CR0_PG: i32; - #[no_mangle] - static CR4_VME: i32; - #[no_mangle] - static CR4_PVI: i32; - #[no_mangle] - static CR4_TSD: i32; - #[no_mangle] - static CR4_PSE: i32; - #[no_mangle] - static CR4_DE: i32; - #[no_mangle] - static CR4_PAE: i32; - #[no_mangle] - static CR4_PGE: i32; - #[no_mangle] - static IA32_SYSENTER_CS: i32; - #[no_mangle] - static IA32_SYSENTER_ESP: i32; - #[no_mangle] - static IA32_SYSENTER_EIP: i32; - #[no_mangle] - static IA32_TIME_STAMP_COUNTER: i32; - #[no_mangle] - static IA32_PLATFORM_ID: i32; - #[no_mangle] - static IA32_APIC_BASE_MSR: i32; - #[no_mangle] - static IA32_BIOS_SIGN_ID: i32; - #[no_mangle] - static MSR_PLATFORM_INFO: i32; - #[no_mangle] - static MSR_MISC_FEATURE_ENABLES: i32; - #[no_mangle] - static IA32_MISC_ENABLE: i32; - #[no_mangle] - static IA32_RTIT_CTL: i32; - #[no_mangle] - static MSR_SMI_COUNT: i32; - #[no_mangle] - static IA32_MCG_CAP: i32; - #[no_mangle] - static IA32_KERNEL_GS_BASE: i32; - #[no_mangle] - static MSR_PKG_C2_RESIDENCY: i32; - #[no_mangle] - static IA32_APIC_BASE_BSP: i32; - #[no_mangle] - static IA32_APIC_BASE_EXTD: i32; - #[no_mangle] - static IA32_APIC_BASE_EN: i32; - #[no_mangle] - static APIC_ADDRESS: i32; - #[no_mangle] - static SEG_PREFIX_NONE: i32; - #[no_mangle] - static SEG_PREFIX_ZERO: i32; - #[no_mangle] - static PREFIX_MASK_REP: i32; - #[no_mangle] - static PREFIX_REPZ: i32; - #[no_mangle] - static PREFIX_REPNZ: i32; - #[no_mangle] - static PREFIX_MASK_SEGMENT: i32; - #[no_mangle] - static PREFIX_MASK_OPSIZE: i32; - #[no_mangle] - static PREFIX_MASK_ADDRSIZE: i32; - #[no_mangle] - static PREFIX_F2: i32; - #[no_mangle] - static PREFIX_F3: i32; - #[no_mangle] - static PREFIX_66: i32; - #[no_mangle] - static LOG_CPU: i32; - #[no_mangle] - static A20_MASK: i32; - #[no_mangle] - static A20_MASK16: i32; - #[no_mangle] - static A20_MASK32: i32; - #[no_mangle] - static MXCSR_MASK: i32; - - #[no_mangle] - static mut mem8: *mut u8; - #[no_mangle] - static mut mem16: *mut u16; - #[no_mangle] - static mut mem32s: *mut i32; - #[no_mangle] - static mut jit_block_boundary: bool; - #[no_mangle] - static VALID_TLB_ENTRY_MAX: i32; - #[no_mangle] - static mut valid_tlb_entries: [i32; 10000]; - #[no_mangle] - static mut valid_tlb_entries_count: i32; - #[no_mangle] - static TLB_VALID: i32; - #[no_mangle] - static TLB_READONLY: i32; - #[no_mangle] - static TLB_NO_USER: i32; - #[no_mangle] - static TLB_IN_MAPPED_RANGE: i32; - #[no_mangle] - static TLB_GLOBAL: i32; - #[no_mangle] - static TLB_HAS_CODE: i32; - #[no_mangle] - static CPU_EXCEPTION_DE: i32; - #[no_mangle] - static CPU_EXCEPTION_DB: i32; - #[no_mangle] - static CPU_EXCEPTION_NMI: i32; - #[no_mangle] - static CPU_EXCEPTION_BP: i32; - #[no_mangle] - static CPU_EXCEPTION_OF: i32; - #[no_mangle] - static CPU_EXCEPTION_BR: i32; - #[no_mangle] - static CPU_EXCEPTION_UD: i32; - #[no_mangle] - static CPU_EXCEPTION_NM: i32; - #[no_mangle] - static CPU_EXCEPTION_DF: i32; - #[no_mangle] - static CPU_EXCEPTION_TS: i32; - #[no_mangle] - static CPU_EXCEPTION_NP: i32; - #[no_mangle] - static CPU_EXCEPTION_SS: i32; - #[no_mangle] - static CPU_EXCEPTION_GP: i32; - #[no_mangle] - static CPU_EXCEPTION_PF: i32; - #[no_mangle] - static CPU_EXCEPTION_MF: i32; - #[no_mangle] - static CPU_EXCEPTION_AC: i32; - #[no_mangle] - static CPU_EXCEPTION_MC: i32; - #[no_mangle] - static CPU_EXCEPTION_XM: i32; - #[no_mangle] - static CPU_EXCEPTION_VE: i32; - #[no_mangle] - fn get_seg_prefix(default_segment: i32) -> i32; - #[no_mangle] - fn get_seg_prefix_ds(offset: i32) -> i32; - #[no_mangle] - fn get_seg_prefix_ss(offset: i32) -> i32; - #[no_mangle] - static reg8: *mut u8; - #[no_mangle] - static reg16: *mut u16; - #[no_mangle] - static reg8s: *mut i8; - #[no_mangle] - static reg16s: *mut i16; - #[no_mangle] - static reg32s: *mut i32; - #[no_mangle] - static last_op1: *mut i32; - #[no_mangle] - static last_op2: *mut i32; - #[no_mangle] - static last_op_size: *mut i32; - #[no_mangle] - static last_add_result: *mut i32; - #[no_mangle] - static last_result: *mut i32; - #[no_mangle] - static flags_changed: *mut i32; - #[no_mangle] - static flags: *mut i32; - #[no_mangle] - static page_fault: *mut bool; - #[no_mangle] - static a20_enabled: *mut bool; - #[no_mangle] - static instruction_pointer: *mut i32; - #[no_mangle] - static previous_ip: *mut i32; - #[no_mangle] - static idtr_size: *mut i32; - #[no_mangle] - static idtr_offset: *mut i32; - #[no_mangle] - static gdtr_size: *mut i32; - #[no_mangle] - static gdtr_offset: *mut i32; - #[no_mangle] - static cr: *mut i32; - #[no_mangle] - static cpl: *mut u8; - #[no_mangle] - static in_hlt: *mut bool; - #[no_mangle] - static last_virt_eip: *mut i32; - #[no_mangle] - static eip_phys: *mut i32; - #[no_mangle] - static last_virt_esp: *mut i32; - #[no_mangle] - static esp_phys: *mut i32; - #[no_mangle] - static sysenter_cs: *mut i32; - #[no_mangle] - static sysenter_esp: *mut i32; - #[no_mangle] - static sysenter_eip: *mut i32; - #[no_mangle] - static prefixes: *mut u8; - #[no_mangle] - static timestamp_counter: *mut u32; - #[no_mangle] - static sreg: *mut u16; - #[no_mangle] - static dreg: *mut i32; - #[no_mangle] - static fw_value: *mut i32; - #[no_mangle] - static segment_is_null: *mut bool; - #[no_mangle] - static segment_offsets: *mut i32; - #[no_mangle] - static segment_limits: *mut u32; - #[no_mangle] - static protected_mode: *mut bool; - #[no_mangle] - static is_32: *mut bool; - #[no_mangle] - static stack_size_32: *mut bool; - #[no_mangle] - static memory_size: *mut u32; - #[no_mangle] - static fpu_stack_empty: *mut i32; - #[no_mangle] - static mxcsr: *mut i32; - #[no_mangle] - static reg_xmm: *mut reg128; - #[no_mangle] - static current_tsc: *mut u64; - #[no_mangle] - static fpu_st: *mut f64; - #[no_mangle] - static fpu_st8: *mut u8; - #[no_mangle] - static fpu_st32: *mut i32; - #[no_mangle] - static fpu_stack_ptr: *mut u32; - #[no_mangle] - static fpu_control_word: *mut i32; - #[no_mangle] - static fpu_status_word: *mut i32; - #[no_mangle] - static fpu_opcode: *mut i32; - #[no_mangle] - static fpu_ip: *mut i32; - #[no_mangle] - static fpu_ip_selector: *mut i32; - #[no_mangle] - static fpu_dp: *mut i32; - #[no_mangle] - static fpu_dp_selector: *mut i32; - #[no_mangle] - static reg_mmx: *mut reg64; - #[no_mangle] - static opstats_buffer: *mut u32; - #[no_mangle] - static opstats_buffer_0f: *mut u32; - #[no_mangle] - static tlb_data: *mut i32; -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed { - __f: f64, - __i: u64, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_0 { - __f: f32, - __i: u32, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union reg64 { - i8_0: [i8; 8], - i16_0: [i16; 4], - i32_0: [i32; 2], - i64_0: [i64; 1], - u8_0: [u8; 8], - u16_0: [u16; 4], - u32_0: [u32; 2], - u64_0: [u64; 1], - f32_0: [f32; 2], - f64_0: [f64; 1], -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub union reg128 { - i8_0: [i8; 16], - i16_0: [i16; 8], - i32_0: [i32; 4], - i64_0: [i64; 2], - u8_0: [u8; 16], - u16_0: [u16; 8], - u32_0: [u32; 4], - u64_0: [u64; 2], - f32_0: [f32; 4], - f64_0: [f64; 2], -} - -unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { - let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { - let mut __u: unnamed = unnamed { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x >= __y) as i32; -} #[no_mangle] pub unsafe extern "C" fn resolve_modrm16(mut modrm_byte: i32) -> Result { Ok(match modrm_byte { diff --git a/src/rust/cpu2/profiler.rs b/src/rust/cpu2/profiler.rs index 7c24aec2..756f0d61 100644 --- a/src/rust/cpu2/profiler.rs +++ b/src/rust/cpu2/profiler.rs @@ -1,241 +1,13 @@ -#![allow -( dead_code , mutable_transmutes , non_camel_case_types , non_snake_case , -non_upper_case_globals , unused_mut )] -#![feature ( extern_types , libc )] +#![allow( + dead_code, + mutable_transmutes, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_mut +)] +#![feature(extern_types, libc)] -extern "C" { - - #[no_mangle] - static FLAG_CARRY: i32; - #[no_mangle] - static FLAG_PARITY: i32; - #[no_mangle] - static FLAG_ADJUST: i32; - #[no_mangle] - static FLAG_ZERO: i32; - #[no_mangle] - static FLAG_SIGN: i32; - #[no_mangle] - static FLAG_TRAP: i32; - #[no_mangle] - static FLAG_INTERRUPT: i32; - #[no_mangle] - static FLAG_DIRECTION: i32; - #[no_mangle] - static FLAG_OVERFLOW: i32; - #[no_mangle] - static FLAG_IOPL: i32; - #[no_mangle] - static FLAG_NT: i32; - #[no_mangle] - static FLAG_RF: i32; - #[no_mangle] - static FLAG_VM: i32; - #[no_mangle] - static FLAG_AC: i32; - #[no_mangle] - static FLAG_VIF: i32; - #[no_mangle] - static FLAG_VIP: i32; - #[no_mangle] - static FLAG_ID: i32; - #[no_mangle] - static FLAGS_DEFAULT: i32; - #[no_mangle] - static FLAGS_MASK: i32; - #[no_mangle] - static FLAGS_ALL: i32; - #[no_mangle] - static OPSIZE_8: i32; - #[no_mangle] - static OPSIZE_16: i32; - #[no_mangle] - static OPSIZE_32: i32; - #[no_mangle] - static EAX: i32; - #[no_mangle] - static ECX: i32; - #[no_mangle] - static EDX: i32; - #[no_mangle] - static EBX: i32; - #[no_mangle] - static ESP: i32; - #[no_mangle] - static EBP: i32; - #[no_mangle] - static ESI: i32; - #[no_mangle] - static EDI: i32; - #[no_mangle] - static AX: i32; - #[no_mangle] - static CX: i32; - #[no_mangle] - static DX: i32; - #[no_mangle] - static BX: i32; - #[no_mangle] - static SP: i32; - #[no_mangle] - static BP: i32; - #[no_mangle] - static SI: i32; - #[no_mangle] - static DI: i32; - #[no_mangle] - static AL: i32; - #[no_mangle] - static CL: i32; - #[no_mangle] - static DL: i32; - #[no_mangle] - static BL: i32; - #[no_mangle] - static AH: i32; - #[no_mangle] - static CH: i32; - #[no_mangle] - static DH: i32; - #[no_mangle] - static BH: i32; - #[no_mangle] - static ES: i32; - #[no_mangle] - static CS: i32; - #[no_mangle] - static SS: i32; - #[no_mangle] - static DS: i32; - #[no_mangle] - static FS: i32; - #[no_mangle] - static GS: i32; - #[no_mangle] - static TR: i32; - #[no_mangle] - static LDTR: i32; - #[no_mangle] - static PAGE_TABLE_PRESENT_MASK: i32; - #[no_mangle] - static PAGE_TABLE_RW_MASK: i32; - #[no_mangle] - static PAGE_TABLE_USER_MASK: i32; - #[no_mangle] - static PAGE_TABLE_ACCESSED_MASK: i32; - #[no_mangle] - static PAGE_TABLE_DIRTY_MASK: i32; - #[no_mangle] - static PAGE_TABLE_PSE_MASK: i32; - #[no_mangle] - static PAGE_TABLE_GLOBAL_MASK: i32; - #[no_mangle] - static MMAP_BLOCK_BITS: i32; - #[no_mangle] - static MMAP_BLOCK_SIZE: i32; - #[no_mangle] - static CR0_PE: i32; - #[no_mangle] - static CR0_MP: i32; - #[no_mangle] - static CR0_EM: i32; - #[no_mangle] - static CR0_TS: i32; - #[no_mangle] - static CR0_ET: i32; - #[no_mangle] - static CR0_WP: i32; - #[no_mangle] - static CR0_NW: i32; - #[no_mangle] - static CR0_CD: i32; - #[no_mangle] - static CR0_PG: i32; - #[no_mangle] - static CR4_VME: i32; - #[no_mangle] - static CR4_PVI: i32; - #[no_mangle] - static CR4_TSD: i32; - #[no_mangle] - static CR4_PSE: i32; - #[no_mangle] - static CR4_DE: i32; - #[no_mangle] - static CR4_PAE: i32; - #[no_mangle] - static CR4_PGE: i32; - #[no_mangle] - static IA32_SYSENTER_CS: i32; - #[no_mangle] - static IA32_SYSENTER_ESP: i32; - #[no_mangle] - static IA32_SYSENTER_EIP: i32; - #[no_mangle] - static IA32_TIME_STAMP_COUNTER: i32; - #[no_mangle] - static IA32_PLATFORM_ID: i32; - #[no_mangle] - static IA32_APIC_BASE_MSR: i32; - #[no_mangle] - static IA32_BIOS_SIGN_ID: i32; - #[no_mangle] - static MSR_PLATFORM_INFO: i32; - #[no_mangle] - static MSR_MISC_FEATURE_ENABLES: i32; - #[no_mangle] - static IA32_MISC_ENABLE: i32; - #[no_mangle] - static IA32_RTIT_CTL: i32; - #[no_mangle] - static MSR_SMI_COUNT: i32; - #[no_mangle] - static IA32_MCG_CAP: i32; - #[no_mangle] - static IA32_KERNEL_GS_BASE: i32; - #[no_mangle] - static MSR_PKG_C2_RESIDENCY: i32; - #[no_mangle] - static IA32_APIC_BASE_BSP: i32; - #[no_mangle] - static IA32_APIC_BASE_EXTD: i32; - #[no_mangle] - static IA32_APIC_BASE_EN: i32; - #[no_mangle] - static APIC_ADDRESS: i32; - #[no_mangle] - static SEG_PREFIX_NONE: i32; - #[no_mangle] - static SEG_PREFIX_ZERO: i32; - #[no_mangle] - static PREFIX_MASK_REP: i32; - #[no_mangle] - static PREFIX_REPZ: i32; - #[no_mangle] - static PREFIX_REPNZ: i32; - #[no_mangle] - static PREFIX_MASK_SEGMENT: i32; - #[no_mangle] - static PREFIX_MASK_OPSIZE: i32; - #[no_mangle] - static PREFIX_MASK_ADDRSIZE: i32; - #[no_mangle] - static PREFIX_F2: i32; - #[no_mangle] - static PREFIX_F3: i32; - #[no_mangle] - static PREFIX_66: i32; - #[no_mangle] - static LOG_CPU: i32; - #[no_mangle] - static A20_MASK: i32; - #[no_mangle] - static A20_MASK16: i32; - #[no_mangle] - static A20_MASK32: i32; - #[no_mangle] - static MXCSR_MASK: i32; -} pub const S_SAFE_WRITE32_SLOW_NOT_VALID: stat_name = 22; pub const S_SAFE_WRITE32_SLOW_NOT_USER: stat_name = 23; diff --git a/src/rust/cpu2/shared.rs b/src/rust/cpu2/shared.rs deleted file mode 100644 index bf08f2ae..00000000 --- a/src/rust/cpu2/shared.rs +++ /dev/null @@ -1,399 +0,0 @@ -#![allow -( dead_code , mutable_transmutes , non_camel_case_types , non_snake_case , -non_upper_case_globals , unused_mut )] -#![feature ( libc )] - -extern "C" { - #[no_mangle] - fn __fpclassifyl(_: f64) -> i32; -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed { - __f: f32, - __i: u32, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_0 { - __f: f64, - __i: u64, -} - -unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { - let mut __u: unnamed = unnamed { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { - let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x >= __y) as i32; -} -#[no_mangle] -pub unsafe extern "C" fn isnan_XXX(mut f: f64) -> bool { return f != f; } -#[no_mangle] -pub unsafe extern "C" fn isfinite_XXX(mut f: f64) -> bool { - return f == ::std::f32::INFINITY as f64 || f == -::std::f32::INFINITY as f64 || !isnan_XXX(f); -} diff --git a/src/rust/cpu2/sse_instr.rs b/src/rust/cpu2/sse_instr.rs index 1a3686c5..ee55781a 100644 --- a/src/rust/cpu2/sse_instr.rs +++ b/src/rust/cpu2/sse_instr.rs @@ -10,708 +10,6 @@ use cpu2::cpu::*; -extern "C" { - - #[no_mangle] - fn __fpclassifyl(_: f64) -> i32; - #[no_mangle] - static FLAG_CARRY: i32; - #[no_mangle] - static FLAG_PARITY: i32; - #[no_mangle] - static FLAG_ADJUST: i32; - #[no_mangle] - static FLAG_ZERO: i32; - #[no_mangle] - static FLAG_SIGN: i32; - #[no_mangle] - static FLAG_TRAP: i32; - #[no_mangle] - static FLAG_INTERRUPT: i32; - #[no_mangle] - static FLAG_DIRECTION: i32; - #[no_mangle] - static FLAG_OVERFLOW: i32; - #[no_mangle] - static FLAG_IOPL: i32; - #[no_mangle] - static FLAG_NT: i32; - #[no_mangle] - static FLAG_RF: i32; - #[no_mangle] - static FLAG_VM: i32; - #[no_mangle] - static FLAG_AC: i32; - #[no_mangle] - static FLAG_VIF: i32; - #[no_mangle] - static FLAG_VIP: i32; - #[no_mangle] - static FLAG_ID: i32; - #[no_mangle] - static FLAGS_DEFAULT: i32; - #[no_mangle] - static FLAGS_MASK: i32; - #[no_mangle] - static FLAGS_ALL: i32; - #[no_mangle] - static OPSIZE_8: i32; - #[no_mangle] - static OPSIZE_16: i32; - #[no_mangle] - static OPSIZE_32: i32; - #[no_mangle] - static EAX: i32; - #[no_mangle] - static ECX: i32; - #[no_mangle] - static EDX: i32; - #[no_mangle] - static EBX: i32; - #[no_mangle] - static ESP: i32; - #[no_mangle] - static EBP: i32; - #[no_mangle] - static ESI: i32; - #[no_mangle] - static EDI: i32; - #[no_mangle] - static AX: i32; - #[no_mangle] - static CX: i32; - #[no_mangle] - static DX: i32; - #[no_mangle] - static BX: i32; - #[no_mangle] - static SP: i32; - #[no_mangle] - static BP: i32; - #[no_mangle] - static SI: i32; - #[no_mangle] - static DI: i32; - #[no_mangle] - static AL: i32; - #[no_mangle] - static CL: i32; - #[no_mangle] - static DL: i32; - #[no_mangle] - static BL: i32; - #[no_mangle] - static AH: i32; - #[no_mangle] - static CH: i32; - #[no_mangle] - static DH: i32; - #[no_mangle] - static BH: i32; - #[no_mangle] - static ES: i32; - #[no_mangle] - static CS: i32; - #[no_mangle] - static SS: i32; - #[no_mangle] - static DS: i32; - #[no_mangle] - static FS: i32; - #[no_mangle] - static GS: i32; - #[no_mangle] - static TR: i32; - #[no_mangle] - static LDTR: i32; - #[no_mangle] - static PAGE_TABLE_PRESENT_MASK: i32; - #[no_mangle] - static PAGE_TABLE_RW_MASK: i32; - #[no_mangle] - static PAGE_TABLE_USER_MASK: i32; - #[no_mangle] - static PAGE_TABLE_ACCESSED_MASK: i32; - #[no_mangle] - static PAGE_TABLE_DIRTY_MASK: i32; - #[no_mangle] - static PAGE_TABLE_PSE_MASK: i32; - #[no_mangle] - static PAGE_TABLE_GLOBAL_MASK: i32; - #[no_mangle] - static MMAP_BLOCK_BITS: i32; - #[no_mangle] - static MMAP_BLOCK_SIZE: i32; - #[no_mangle] - static CR0_PE: i32; - #[no_mangle] - static CR0_MP: i32; - #[no_mangle] - static CR0_EM: i32; - #[no_mangle] - static CR0_TS: i32; - #[no_mangle] - static CR0_ET: i32; - #[no_mangle] - static CR0_WP: i32; - #[no_mangle] - static CR0_NW: i32; - #[no_mangle] - static CR0_CD: i32; - #[no_mangle] - static CR0_PG: i32; - #[no_mangle] - static CR4_VME: i32; - #[no_mangle] - static CR4_PVI: i32; - #[no_mangle] - static CR4_TSD: i32; - #[no_mangle] - static CR4_PSE: i32; - #[no_mangle] - static CR4_DE: i32; - #[no_mangle] - static CR4_PAE: i32; - #[no_mangle] - static CR4_PGE: i32; - #[no_mangle] - static IA32_SYSENTER_CS: i32; - #[no_mangle] - static IA32_SYSENTER_ESP: i32; - #[no_mangle] - static IA32_SYSENTER_EIP: i32; - #[no_mangle] - static IA32_TIME_STAMP_COUNTER: i32; - #[no_mangle] - static IA32_PLATFORM_ID: i32; - #[no_mangle] - static IA32_APIC_BASE_MSR: i32; - #[no_mangle] - static IA32_BIOS_SIGN_ID: i32; - #[no_mangle] - static MSR_PLATFORM_INFO: i32; - #[no_mangle] - static MSR_MISC_FEATURE_ENABLES: i32; - #[no_mangle] - static IA32_MISC_ENABLE: i32; - #[no_mangle] - static IA32_RTIT_CTL: i32; - #[no_mangle] - static MSR_SMI_COUNT: i32; - #[no_mangle] - static IA32_MCG_CAP: i32; - #[no_mangle] - static IA32_KERNEL_GS_BASE: i32; - #[no_mangle] - static MSR_PKG_C2_RESIDENCY: i32; - #[no_mangle] - static IA32_APIC_BASE_BSP: i32; - #[no_mangle] - static IA32_APIC_BASE_EXTD: i32; - #[no_mangle] - static IA32_APIC_BASE_EN: i32; - #[no_mangle] - static APIC_ADDRESS: i32; - #[no_mangle] - static SEG_PREFIX_NONE: i32; - #[no_mangle] - static SEG_PREFIX_ZERO: i32; - #[no_mangle] - static PREFIX_MASK_REP: i32; - #[no_mangle] - static PREFIX_REPZ: i32; - #[no_mangle] - static PREFIX_REPNZ: i32; - #[no_mangle] - static PREFIX_MASK_SEGMENT: i32; - #[no_mangle] - static PREFIX_MASK_OPSIZE: i32; - #[no_mangle] - static PREFIX_MASK_ADDRSIZE: i32; - #[no_mangle] - static PREFIX_F2: i32; - #[no_mangle] - static PREFIX_F3: i32; - #[no_mangle] - static PREFIX_66: i32; - #[no_mangle] - static LOG_CPU: i32; - #[no_mangle] - static A20_MASK: i32; - #[no_mangle] - static A20_MASK16: i32; - #[no_mangle] - static A20_MASK32: i32; - #[no_mangle] - static MXCSR_MASK: i32; - - #[no_mangle] - fn c_comment(m: *const i8) -> (); - #[no_mangle] - fn isnan_XXX(f: f64) -> bool; - #[no_mangle] - static mut mem8: *mut u8; - #[no_mangle] - static mut mem16: *mut u16; - #[no_mangle] - static mut mem32s: *mut i32; - #[no_mangle] - static mut jit_block_boundary: bool; - #[no_mangle] - static VALID_TLB_ENTRY_MAX: i32; - #[no_mangle] - static mut valid_tlb_entries: [i32; 10000]; - #[no_mangle] - static mut valid_tlb_entries_count: i32; - #[no_mangle] - static TLB_VALID: i32; - #[no_mangle] - static TLB_READONLY: i32; - #[no_mangle] - static TLB_NO_USER: i32; - #[no_mangle] - static TLB_IN_MAPPED_RANGE: i32; - #[no_mangle] - static TLB_GLOBAL: i32; - #[no_mangle] - static TLB_HAS_CODE: i32; - #[no_mangle] - static CPU_EXCEPTION_DE: i32; - #[no_mangle] - static CPU_EXCEPTION_DB: i32; - #[no_mangle] - static CPU_EXCEPTION_NMI: i32; - #[no_mangle] - static CPU_EXCEPTION_BP: i32; - #[no_mangle] - static CPU_EXCEPTION_OF: i32; - #[no_mangle] - static CPU_EXCEPTION_BR: i32; - #[no_mangle] - static CPU_EXCEPTION_UD: i32; - #[no_mangle] - static CPU_EXCEPTION_NM: i32; - #[no_mangle] - static CPU_EXCEPTION_DF: i32; - #[no_mangle] - static CPU_EXCEPTION_TS: i32; - #[no_mangle] - static CPU_EXCEPTION_NP: i32; - #[no_mangle] - static CPU_EXCEPTION_SS: i32; - #[no_mangle] - static CPU_EXCEPTION_GP: i32; - #[no_mangle] - static CPU_EXCEPTION_PF: i32; - #[no_mangle] - static CPU_EXCEPTION_MF: i32; - #[no_mangle] - static CPU_EXCEPTION_AC: i32; - #[no_mangle] - static CPU_EXCEPTION_MC: i32; - #[no_mangle] - static CPU_EXCEPTION_XM: i32; - #[no_mangle] - static CPU_EXCEPTION_VE: i32; - #[no_mangle] - fn read_mmx64s(r: i32) -> reg64; - #[no_mangle] - fn write_mmx64(r: i32, low: i32, high: i32) -> (); - #[no_mangle] - fn write_mmx_reg64(r: i32, data: reg64) -> (); - #[no_mangle] - fn read_xmm64s(r: i32) -> reg64; - #[no_mangle] - fn read_xmm128s(r: i32) -> reg128; - #[no_mangle] - fn write_xmm128(r: i32, i0: i32, i1: i32, i2: i32, i3: i32) -> (); - #[no_mangle] - fn write_xmm_reg128(r: i32, data: reg128) -> (); -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed { - __f: f32, - __i: u32, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_0 { - __f: f64, - __i: u64, -} - -unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { - let mut __u: unnamed = unnamed { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { - let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x >= __y) as i32; -} #[no_mangle] pub unsafe extern "C" fn mov_r_m64(mut addr: i32, mut r: i32) -> () { c_comment!(("mov* m64, mm")); @@ -1079,11 +377,11 @@ pub unsafe extern "C" fn sse_comparison(mut op: i32, mut x: f64, mut y: f64) -> 0 => return x == y, 1 => return x < y, 2 => return x <= y, - 3 => return 0 != isnan_XXX(x) as i32 || 0 != isnan_XXX(y) as i32, - 4 => return x != y || 0 != isnan_XXX(x) as i32 || 0 != isnan_XXX(y) as i32, - 5 => return x >= y || 0 != isnan_XXX(x) as i32 || 0 != isnan_XXX(y) as i32, - 6 => return x > y || 0 != isnan_XXX(x) as i32 || 0 != isnan_XXX(y) as i32, - 7 => return !isnan_XXX(x) && !isnan_XXX(y), + 3 => return 0 != x.is_nan() as i32 || 0 != y.is_nan() as i32, + 4 => return x != y || 0 != x.is_nan() as i32 || 0 != y.is_nan() as i32, + 5 => return x >= y || 0 != x.is_nan() as i32 || 0 != y.is_nan() as i32, + 6 => return x > y || 0 != x.is_nan() as i32 || 0 != y.is_nan() as i32, + 7 => return !x.is_nan() && !y.is_nan(), _ => { dbg_assert!(0 != 0i32); return 0 != 0i32; diff --git a/src/rust/cpu2/string.rs b/src/rust/cpu2/string.rs index 16eb36c6..a341f412 100644 --- a/src/rust/cpu2/string.rs +++ b/src/rust/cpu2/string.rs @@ -8,889 +8,32 @@ )] #![feature(extern_types, libc)] -use cpu2::cpu::*; - extern "C" { + #[no_mangle] + pub fn test_privileges_for_io(port: i32, size: i32) -> bool; #[no_mangle] - fn cmp8(x: i32, y: i32) -> (); + pub fn io_port_read8(port: i32) -> i32; #[no_mangle] - fn cmp16(x: i32, y: i32) -> (); + pub fn io_port_read16(port: i32) -> i32; #[no_mangle] - fn cmp32(x: i32, y: i32) -> (); - #[no_mangle] - fn __fpclassifyl(_: f64) -> i32; - #[no_mangle] - static FLAG_CARRY: i32; - #[no_mangle] - static FLAG_PARITY: i32; - #[no_mangle] - static FLAG_ADJUST: i32; - #[no_mangle] - static FLAG_ZERO: i32; - #[no_mangle] - static FLAG_SIGN: i32; - #[no_mangle] - static FLAG_TRAP: i32; - #[no_mangle] - static FLAG_INTERRUPT: i32; - #[no_mangle] - static FLAG_DIRECTION: i32; - #[no_mangle] - static FLAG_OVERFLOW: i32; - #[no_mangle] - static FLAG_IOPL: i32; - #[no_mangle] - static FLAG_NT: i32; - #[no_mangle] - static FLAG_RF: i32; - #[no_mangle] - static FLAG_VM: i32; - #[no_mangle] - static FLAG_AC: i32; - #[no_mangle] - static FLAG_VIF: i32; - #[no_mangle] - static FLAG_VIP: i32; - #[no_mangle] - static FLAG_ID: i32; - #[no_mangle] - static FLAGS_DEFAULT: i32; - #[no_mangle] - static FLAGS_MASK: i32; - #[no_mangle] - static FLAGS_ALL: i32; - #[no_mangle] - static OPSIZE_8: i32; - #[no_mangle] - static OPSIZE_16: i32; - #[no_mangle] - static OPSIZE_32: i32; - #[no_mangle] - static EAX: i32; - #[no_mangle] - static ECX: i32; - #[no_mangle] - static EDX: i32; - #[no_mangle] - static EBX: i32; - #[no_mangle] - static ESP: i32; - #[no_mangle] - static EBP: i32; - #[no_mangle] - static ESI: i32; - #[no_mangle] - static EDI: i32; - #[no_mangle] - static AX: i32; - #[no_mangle] - static CX: i32; - #[no_mangle] - static DX: i32; - #[no_mangle] - static BX: i32; - #[no_mangle] - static SP: i32; - #[no_mangle] - static BP: i32; - #[no_mangle] - static SI: i32; - #[no_mangle] - static DI: i32; - #[no_mangle] - static AL: i32; - #[no_mangle] - static CL: i32; - #[no_mangle] - static DL: i32; - #[no_mangle] - static BL: i32; - #[no_mangle] - static AH: i32; - #[no_mangle] - static CH: i32; - #[no_mangle] - static DH: i32; - #[no_mangle] - static BH: i32; - #[no_mangle] - static ES: i32; - #[no_mangle] - static CS: i32; - #[no_mangle] - static SS: i32; - #[no_mangle] - static DS: i32; - #[no_mangle] - static FS: i32; - #[no_mangle] - static GS: i32; - #[no_mangle] - static TR: i32; - #[no_mangle] - static LDTR: i32; - #[no_mangle] - static PAGE_TABLE_PRESENT_MASK: i32; - #[no_mangle] - static PAGE_TABLE_RW_MASK: i32; - #[no_mangle] - static PAGE_TABLE_USER_MASK: i32; - #[no_mangle] - static PAGE_TABLE_ACCESSED_MASK: i32; - #[no_mangle] - static PAGE_TABLE_DIRTY_MASK: i32; - #[no_mangle] - static PAGE_TABLE_PSE_MASK: i32; - #[no_mangle] - static PAGE_TABLE_GLOBAL_MASK: i32; - #[no_mangle] - static MMAP_BLOCK_BITS: i32; - #[no_mangle] - static MMAP_BLOCK_SIZE: i32; - #[no_mangle] - static CR0_PE: i32; - #[no_mangle] - static CR0_MP: i32; - #[no_mangle] - static CR0_EM: i32; - #[no_mangle] - static CR0_TS: i32; - #[no_mangle] - static CR0_ET: i32; - #[no_mangle] - static CR0_WP: i32; - #[no_mangle] - static CR0_NW: i32; - #[no_mangle] - static CR0_CD: i32; - #[no_mangle] - static CR0_PG: i32; - #[no_mangle] - static CR4_VME: i32; - #[no_mangle] - static CR4_PVI: i32; - #[no_mangle] - static CR4_TSD: i32; - #[no_mangle] - static CR4_PSE: i32; - #[no_mangle] - static CR4_DE: i32; - #[no_mangle] - static CR4_PAE: i32; - #[no_mangle] - static CR4_PGE: i32; - #[no_mangle] - static IA32_SYSENTER_CS: i32; - #[no_mangle] - static IA32_SYSENTER_ESP: i32; - #[no_mangle] - static IA32_SYSENTER_EIP: i32; - #[no_mangle] - static IA32_TIME_STAMP_COUNTER: i32; - #[no_mangle] - static IA32_PLATFORM_ID: i32; - #[no_mangle] - static IA32_APIC_BASE_MSR: i32; - #[no_mangle] - static IA32_BIOS_SIGN_ID: i32; - #[no_mangle] - static MSR_PLATFORM_INFO: i32; - #[no_mangle] - static MSR_MISC_FEATURE_ENABLES: i32; - #[no_mangle] - static IA32_MISC_ENABLE: i32; - #[no_mangle] - static IA32_RTIT_CTL: i32; - #[no_mangle] - static MSR_SMI_COUNT: i32; - #[no_mangle] - static IA32_MCG_CAP: i32; - #[no_mangle] - static IA32_KERNEL_GS_BASE: i32; - #[no_mangle] - static MSR_PKG_C2_RESIDENCY: i32; - #[no_mangle] - static IA32_APIC_BASE_BSP: i32; - #[no_mangle] - static IA32_APIC_BASE_EXTD: i32; - #[no_mangle] - static IA32_APIC_BASE_EN: i32; - #[no_mangle] - static APIC_ADDRESS: i32; - #[no_mangle] - static SEG_PREFIX_NONE: i32; - #[no_mangle] - static SEG_PREFIX_ZERO: i32; - #[no_mangle] - static PREFIX_MASK_REP: i32; - #[no_mangle] - static PREFIX_REPZ: i32; - #[no_mangle] - static PREFIX_REPNZ: i32; - #[no_mangle] - static PREFIX_MASK_SEGMENT: i32; - #[no_mangle] - static PREFIX_MASK_OPSIZE: i32; - #[no_mangle] - static PREFIX_MASK_ADDRSIZE: i32; - #[no_mangle] - static PREFIX_F2: i32; - #[no_mangle] - static PREFIX_F3: i32; - #[no_mangle] - static PREFIX_66: i32; - #[no_mangle] - static LOG_CPU: i32; - #[no_mangle] - static A20_MASK: i32; - #[no_mangle] - static A20_MASK16: i32; - #[no_mangle] - static A20_MASK32: i32; - #[no_mangle] - static MXCSR_MASK: i32; + pub fn io_port_read32(port: i32) -> i32; #[no_mangle] - fn c_comment(m: *const i8) -> (); + pub fn io_port_write8(port: i32, value: i32); #[no_mangle] - static mut mem8: *mut u8; + pub fn io_port_write16(port: i32, value: i32); #[no_mangle] - static mut mem16: *mut u16; - #[no_mangle] - static mut mem32s: *mut i32; - #[no_mangle] - static mut jit_block_boundary: bool; - #[no_mangle] - static VALID_TLB_ENTRY_MAX: i32; - #[no_mangle] - static mut valid_tlb_entries: [i32; 10000]; - #[no_mangle] - static mut valid_tlb_entries_count: i32; - #[no_mangle] - static TLB_VALID: i32; - #[no_mangle] - static TLB_READONLY: i32; - #[no_mangle] - static TLB_NO_USER: i32; - #[no_mangle] - static TLB_IN_MAPPED_RANGE: i32; - #[no_mangle] - static TLB_GLOBAL: i32; - #[no_mangle] - static TLB_HAS_CODE: i32; - #[no_mangle] - static CPU_EXCEPTION_DE: i32; - #[no_mangle] - static CPU_EXCEPTION_DB: i32; - #[no_mangle] - static CPU_EXCEPTION_NMI: i32; - #[no_mangle] - static CPU_EXCEPTION_BP: i32; - #[no_mangle] - static CPU_EXCEPTION_OF: i32; - #[no_mangle] - static CPU_EXCEPTION_BR: i32; - #[no_mangle] - static CPU_EXCEPTION_UD: i32; - #[no_mangle] - static CPU_EXCEPTION_NM: i32; - #[no_mangle] - static CPU_EXCEPTION_DF: i32; - #[no_mangle] - static CPU_EXCEPTION_TS: i32; - #[no_mangle] - static CPU_EXCEPTION_NP: i32; - #[no_mangle] - static CPU_EXCEPTION_SS: i32; - #[no_mangle] - static CPU_EXCEPTION_GP: i32; - #[no_mangle] - static CPU_EXCEPTION_PF: i32; - #[no_mangle] - static CPU_EXCEPTION_MF: i32; - #[no_mangle] - static CPU_EXCEPTION_AC: i32; - #[no_mangle] - static CPU_EXCEPTION_MC: i32; - #[no_mangle] - static CPU_EXCEPTION_XM: i32; - #[no_mangle] - static CPU_EXCEPTION_VE: i32; - #[no_mangle] - fn get_seg(segment: i32) -> i32; - #[no_mangle] - fn get_seg_prefix(default_segment: i32) -> i32; - #[no_mangle] - fn get_reg_asize(reg: i32) -> i32; - #[no_mangle] - fn set_ecx_asize(value: i32) -> (); - #[no_mangle] - fn add_reg_asize(reg: i32, value: i32) -> (); - #[no_mangle] - fn decr_ecx_asize() -> i32; - #[no_mangle] - static reg8: *mut u8; - #[no_mangle] - static reg16: *mut u16; - #[no_mangle] - static reg8s: *mut i8; - #[no_mangle] - static reg16s: *mut i16; - #[no_mangle] - static reg32s: *mut i32; - #[no_mangle] - static last_op1: *mut i32; - #[no_mangle] - static last_op2: *mut i32; - #[no_mangle] - static last_op_size: *mut i32; - #[no_mangle] - static last_add_result: *mut i32; - #[no_mangle] - static last_result: *mut i32; - #[no_mangle] - static flags_changed: *mut i32; - #[no_mangle] - static flags: *mut i32; - #[no_mangle] - static page_fault: *mut bool; - #[no_mangle] - static a20_enabled: *mut bool; - #[no_mangle] - static instruction_pointer: *mut i32; - #[no_mangle] - static previous_ip: *mut i32; - #[no_mangle] - static idtr_size: *mut i32; - #[no_mangle] - static idtr_offset: *mut i32; - #[no_mangle] - static gdtr_size: *mut i32; - #[no_mangle] - static gdtr_offset: *mut i32; - #[no_mangle] - static cr: *mut i32; - #[no_mangle] - static cpl: *mut u8; - #[no_mangle] - static in_hlt: *mut bool; - #[no_mangle] - static last_virt_eip: *mut i32; - #[no_mangle] - static eip_phys: *mut i32; - #[no_mangle] - static last_virt_esp: *mut i32; - #[no_mangle] - static esp_phys: *mut i32; - #[no_mangle] - static sysenter_cs: *mut i32; - #[no_mangle] - static sysenter_esp: *mut i32; - #[no_mangle] - static sysenter_eip: *mut i32; - #[no_mangle] - static prefixes: *mut u8; - #[no_mangle] - static timestamp_counter: *mut u32; - #[no_mangle] - static sreg: *mut u16; - #[no_mangle] - static dreg: *mut i32; - #[no_mangle] - static fw_value: *mut i32; - #[no_mangle] - static segment_is_null: *mut bool; - #[no_mangle] - static segment_offsets: *mut i32; - #[no_mangle] - static segment_limits: *mut u32; - #[no_mangle] - static protected_mode: *mut bool; - #[no_mangle] - static is_32: *mut bool; - #[no_mangle] - static stack_size_32: *mut bool; - #[no_mangle] - static memory_size: *mut u32; - #[no_mangle] - static fpu_stack_empty: *mut i32; - #[no_mangle] - static mxcsr: *mut i32; - #[no_mangle] - static reg_xmm: *mut reg128; - #[no_mangle] - static current_tsc: *mut u64; - #[no_mangle] - static fpu_st: *mut f64; - #[no_mangle] - static fpu_st8: *mut u8; - #[no_mangle] - static fpu_st32: *mut i32; - #[no_mangle] - static fpu_stack_ptr: *mut u32; - #[no_mangle] - static fpu_control_word: *mut i32; - #[no_mangle] - static fpu_status_word: *mut i32; - #[no_mangle] - static fpu_opcode: *mut i32; - #[no_mangle] - static fpu_ip: *mut i32; - #[no_mangle] - static fpu_ip_selector: *mut i32; - #[no_mangle] - static fpu_dp: *mut i32; - #[no_mangle] - static fpu_dp_selector: *mut i32; - #[no_mangle] - static reg_mmx: *mut reg64; - #[no_mangle] - static opstats_buffer: *mut u32; - #[no_mangle] - static opstats_buffer_0f: *mut u32; - #[no_mangle] - static tlb_data: *mut i32; - #[no_mangle] - fn test_privileges_for_io(_: i32, _: i32) -> bool; - #[no_mangle] - fn io_port_read8(_: i32) -> i32; - #[no_mangle] - fn io_port_read16(_: i32) -> i32; - #[no_mangle] - fn io_port_read32(_: i32) -> i32; - #[no_mangle] - fn io_port_write8(_: i32, _: i32) -> (); - #[no_mangle] - fn io_port_write16(_: i32, _: i32) -> (); - #[no_mangle] - fn io_port_write32(_: i32, _: i32) -> (); - #[no_mangle] - fn read8(addr: u32) -> i32; - #[no_mangle] - fn read_aligned16(addr: u32) -> i32; - #[no_mangle] - fn read_aligned32(addr: u32) -> i32; - #[no_mangle] - fn write8(addr: u32, value: i32) -> (); - #[no_mangle] - fn write_aligned16(addr: u32, value: u32) -> (); - #[no_mangle] - fn write_aligned32(addr: u32, value: i32) -> (); + pub fn io_port_write32(port: i32, value: i32); } -#[derive(Copy, Clone)] -#[repr(C)] -pub union reg128 { - i8_0: [i8; 16], - i16_0: [i16; 8], - i32_0: [i32; 4], - i64_0: [i64; 2], - u8_0: [u8; 16], - u16_0: [u16; 8], - u32_0: [u32; 4], - u64_0: [u64; 2], - f32_0: [f32; 4], - f64_0: [f64; 2], -} +use cpu2::arith::{cmp16, cmp32, cmp8}; +use cpu2::cpu::*; +use cpu2::global_pointers::*; +use cpu2::memory::{ + read8, read_aligned16, read_aligned32, write8, write_aligned16, write_aligned32, +}; -#[derive(Copy, Clone)] -#[repr(C)] -pub union reg64 { - i8_0: [i8; 8], - i16_0: [i16; 4], - i32_0: [i32; 2], - i64_0: [i64; 1], - u8_0: [u8; 8], - u16_0: [u16; 4], - u32_0: [u32; 2], - u64_0: [u64; 1], - f32_0: [f32; 2], - f64_0: [f64; 1], -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed { - __f: f32, - __i: u32, -} -#[derive(Copy, Clone)] -#[repr(C)] -pub union unnamed_0 { - __f: f64, - __i: u64, -} - -unsafe extern "C" fn __FLOAT_BITS(mut __f: f32) -> u32 { - let mut __u: unnamed = unnamed { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __DOUBLE_BITS(mut __f: f64) -> u64 { - let mut __u: unnamed_0 = unnamed_0 { __f: 0. }; - __u.__f = __f; - return __u.__i; -} -unsafe extern "C" fn __islessf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __isless(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x < __y) as i32; -} -unsafe extern "C" fn __islessequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x <= __y) as i32; -} -unsafe extern "C" fn __islessgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __islessgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x != __y) as i32; -} -unsafe extern "C" fn __isgreaterf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreater(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterl(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x > __y) as i32; -} -unsafe extern "C" fn __isgreaterequalf(mut __x: f32, mut __y: f32) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequal(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x as f64) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y as f64) == 0i32) as i32 - } && __x >= __y) as i32; -} -unsafe extern "C" fn __isgreaterequall(mut __x: f64, mut __y: f64) -> i32 { - return (0 == if 0 != if ::std::mem::size_of::() as u64 - == ::std::mem::size_of::() as u64 - { - (__FLOAT_BITS(__x as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__x as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__x) == 0i32) as i32 - } { - 1i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__FLOAT_BITS(__y as f32) & 2147483647i32 as u32 > 2139095040i32 as u32) as i32 - } - else if ::std::mem::size_of::() as u64 == ::std::mem::size_of::() as u64 { - (__DOUBLE_BITS(__y as f64) & 1u64.wrapping_neg() >> 1i32 > 2047u64 << 52i32) as i32 - } - else { - (__fpclassifyl(__y) == 0i32) as i32 - } && __x >= __y) as i32; -} #[no_mangle] pub unsafe extern "C" fn string_get_cycle_count(mut size: i32, mut address: i32) -> i32 { dbg_assert!(0 != size && size <= 4i32 && size >= -4i32); From a795accee61b7cb24cf896488b1902c70ff4e628 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 18 Aug 2018 22:10:10 -0500 Subject: [PATCH 1195/2137] c2rust cleanup: Make global pointers constants --- src/rust/cpu2/global_pointers.rs | 183 +++++++++++-------------------- 1 file changed, 61 insertions(+), 122 deletions(-) diff --git a/src/rust/cpu2/global_pointers.rs b/src/rust/cpu2/global_pointers.rs index 6b01b09a..b50c3da0 100644 --- a/src/rust/cpu2/global_pointers.rs +++ b/src/rust/cpu2/global_pointers.rs @@ -10,125 +10,64 @@ use cpu2::cpu::{reg128, reg64}; -#[no_mangle] -pub static mut reg8: *mut u8 = unsafe { 4i32 as *mut u8 }; -#[no_mangle] -pub static mut reg16: *mut u16 = unsafe { 4i32 as *mut u16 }; -#[no_mangle] -pub static mut reg8s: *mut i8 = unsafe { 4i32 as *mut i8 }; -#[no_mangle] -pub static mut reg16s: *mut i16 = unsafe { 4i32 as *mut i16 }; -#[no_mangle] -pub static mut reg32s: *mut i32 = unsafe { 4i32 as *mut i32 }; -#[no_mangle] -pub static mut last_op1: *mut i32 = unsafe { 512i32 as *mut i32 }; -#[no_mangle] -pub static mut last_op2: *mut i32 = unsafe { 516i32 as *mut i32 }; -#[no_mangle] -pub static mut last_op_size: *mut i32 = unsafe { 520i32 as *mut i32 }; -#[no_mangle] -pub static mut last_add_result: *mut i32 = unsafe { 524i32 as *mut i32 }; -#[no_mangle] -pub static mut last_result: *mut i32 = unsafe { 528i32 as *mut i32 }; -#[no_mangle] -pub static mut flags_changed: *mut i32 = unsafe { 532i32 as *mut i32 }; -#[no_mangle] -pub static mut flags: *mut i32 = unsafe { 536i32 as *mut i32 }; -#[no_mangle] -pub static mut page_fault: *mut bool = unsafe { 540i32 as *mut bool }; -#[no_mangle] -pub static mut a20_enabled: *mut bool = unsafe { 552i32 as *mut bool }; -#[no_mangle] -pub static mut instruction_pointer: *mut i32 = unsafe { 556i32 as *mut i32 }; -#[no_mangle] -pub static mut previous_ip: *mut i32 = unsafe { 560i32 as *mut i32 }; -#[no_mangle] -pub static mut idtr_size: *mut i32 = unsafe { 564i32 as *mut i32 }; -#[no_mangle] -pub static mut idtr_offset: *mut i32 = unsafe { 568i32 as *mut i32 }; -#[no_mangle] -pub static mut gdtr_size: *mut i32 = unsafe { 572i32 as *mut i32 }; -#[no_mangle] -pub static mut gdtr_offset: *mut i32 = unsafe { 576i32 as *mut i32 }; -#[no_mangle] -pub static mut cr: *mut i32 = unsafe { 580i32 as *mut i32 }; -#[no_mangle] -pub static mut cpl: *mut u8 = unsafe { 612i32 as *mut u8 }; -#[no_mangle] -pub static mut in_hlt: *mut bool = unsafe { 616i32 as *mut bool }; -#[no_mangle] -pub static mut last_virt_eip: *mut i32 = unsafe { 620i32 as *mut i32 }; -#[no_mangle] -pub static mut eip_phys: *mut i32 = unsafe { 624i32 as *mut i32 }; -#[no_mangle] -pub static mut last_virt_esp: *mut i32 = unsafe { 628i32 as *mut i32 }; -#[no_mangle] -pub static mut esp_phys: *mut i32 = unsafe { 632i32 as *mut i32 }; -#[no_mangle] -pub static mut sysenter_cs: *mut i32 = unsafe { 636i32 as *mut i32 }; -#[no_mangle] -pub static mut sysenter_esp: *mut i32 = unsafe { 640i32 as *mut i32 }; -#[no_mangle] -pub static mut sysenter_eip: *mut i32 = unsafe { 644i32 as *mut i32 }; -#[no_mangle] -pub static mut prefixes: *mut u8 = unsafe { 648i32 as *mut u8 }; -#[no_mangle] -pub static mut timestamp_counter: *mut u32 = unsafe { 664i32 as *mut u32 }; -#[no_mangle] -pub static mut sreg: *mut u16 = unsafe { 668i32 as *mut u16 }; -#[no_mangle] -pub static mut dreg: *mut i32 = unsafe { 684i32 as *mut i32 }; -#[no_mangle] -pub static mut fw_value: *mut i32 = unsafe { 720i32 as *mut i32 }; -#[no_mangle] -pub static mut segment_is_null: *mut bool = unsafe { 724i32 as *mut bool }; -#[no_mangle] -pub static mut segment_offsets: *mut i32 = unsafe { 736i32 as *mut i32 }; -#[no_mangle] -pub static mut segment_limits: *mut u32 = unsafe { 768i32 as *mut u32 }; -#[no_mangle] -pub static mut protected_mode: *mut bool = unsafe { 800i32 as *mut bool }; -#[no_mangle] -pub static mut is_32: *mut bool = unsafe { 804i32 as *mut bool }; -#[no_mangle] -pub static mut stack_size_32: *mut bool = unsafe { 808i32 as *mut bool }; -#[no_mangle] -pub static mut memory_size: *mut u32 = unsafe { 812i32 as *mut u32 }; -#[no_mangle] -pub static mut fpu_stack_empty: *mut i32 = unsafe { 816i32 as *mut i32 }; -#[no_mangle] -pub static mut mxcsr: *mut i32 = unsafe { 824i32 as *mut i32 }; -#[no_mangle] -pub static mut reg_xmm: *mut reg128 = unsafe { 828i32 as *mut reg128 }; -#[no_mangle] -pub static mut current_tsc: *mut u64 = unsafe { 956i32 as *mut u64 }; -#[no_mangle] -pub static mut fpu_st: *mut f64 = unsafe { 968i32 as *mut f64 }; -#[no_mangle] -pub static mut fpu_st8: *mut u8 = unsafe { 968i32 as *mut u8 }; -#[no_mangle] -pub static mut fpu_st32: *mut i32 = unsafe { 968i32 as *mut i32 }; -#[no_mangle] -pub static mut fpu_stack_ptr: *mut u32 = unsafe { 1032i32 as *mut u32 }; -#[no_mangle] -pub static mut fpu_control_word: *mut i32 = unsafe { 1036i32 as *mut i32 }; -#[no_mangle] -pub static mut fpu_status_word: *mut i32 = unsafe { 1040i32 as *mut i32 }; -#[no_mangle] -pub static mut fpu_opcode: *mut i32 = unsafe { 1044i32 as *mut i32 }; -#[no_mangle] -pub static mut fpu_ip: *mut i32 = unsafe { 1048i32 as *mut i32 }; -#[no_mangle] -pub static mut fpu_ip_selector: *mut i32 = unsafe { 1052i32 as *mut i32 }; -#[no_mangle] -pub static mut fpu_dp: *mut i32 = unsafe { 1056i32 as *mut i32 }; -#[no_mangle] -pub static mut fpu_dp_selector: *mut i32 = unsafe { 1060i32 as *mut i32 }; -#[no_mangle] -pub static mut reg_mmx: *mut reg64 = unsafe { 1064i32 as *mut reg64 }; -#[no_mangle] -pub static mut opstats_buffer: *mut u32 = unsafe { 4096i32 as *mut u32 }; -#[no_mangle] -pub static mut opstats_buffer_0f: *mut u32 = unsafe { 5120i32 as *mut u32 }; -#[no_mangle] -pub static mut tlb_data: *mut i32 = unsafe { 4194304i32 as *mut i32 }; +pub const reg8: *mut u8 = 4i32 as *mut u8; +pub const reg16: *mut u16 = 4i32 as *mut u16; +pub const reg8s: *mut i8 = 4i32 as *mut i8; +pub const reg16s: *mut i16 = 4i32 as *mut i16; +pub const reg32s: *mut i32 = 4i32 as *mut i32; +pub const last_op1: *mut i32 = 512i32 as *mut i32; +pub const last_op2: *mut i32 = 516i32 as *mut i32; +pub const last_op_size: *mut i32 = 520i32 as *mut i32; +pub const last_add_result: *mut i32 = 524i32 as *mut i32; +pub const last_result: *mut i32 = 528i32 as *mut i32; +pub const flags_changed: *mut i32 = 532i32 as *mut i32; +pub const flags: *mut i32 = 536i32 as *mut i32; +pub const page_fault: *mut bool = 540i32 as *mut bool; +pub const a20_enabled: *mut bool = 552i32 as *mut bool; +pub const instruction_pointer: *mut i32 = 556i32 as *mut i32; +pub const previous_ip: *mut i32 = 560i32 as *mut i32; +pub const idtr_size: *mut i32 = 564i32 as *mut i32; +pub const idtr_offset: *mut i32 = 568i32 as *mut i32; +pub const gdtr_size: *mut i32 = 572i32 as *mut i32; +pub const gdtr_offset: *mut i32 = 576i32 as *mut i32; +pub const cr: *mut i32 = 580i32 as *mut i32; +pub const cpl: *mut u8 = 612i32 as *mut u8; +pub const in_hlt: *mut bool = 616i32 as *mut bool; +pub const last_virt_eip: *mut i32 = 620i32 as *mut i32; +pub const eip_phys: *mut i32 = 624i32 as *mut i32; +pub const last_virt_esp: *mut i32 = 628i32 as *mut i32; +pub const esp_phys: *mut i32 = 632i32 as *mut i32; +pub const sysenter_cs: *mut i32 = 636i32 as *mut i32; +pub const sysenter_esp: *mut i32 = 640i32 as *mut i32; +pub const sysenter_eip: *mut i32 = 644i32 as *mut i32; +pub const prefixes: *mut u8 = 648i32 as *mut u8; +pub const timestamp_counter: *mut u32 = 664i32 as *mut u32; +pub const sreg: *mut u16 = 668i32 as *mut u16; +pub const dreg: *mut i32 = 684i32 as *mut i32; +pub const fw_value: *mut i32 = 720i32 as *mut i32; +pub const segment_is_null: *mut bool = 724i32 as *mut bool; +pub const segment_offsets: *mut i32 = 736i32 as *mut i32; +pub const segment_limits: *mut u32 = 768i32 as *mut u32; +pub const protected_mode: *mut bool = 800i32 as *mut bool; +pub const is_32: *mut bool = 804i32 as *mut bool; +pub const stack_size_32: *mut bool = 808i32 as *mut bool; +pub const memory_size: *mut u32 = 812i32 as *mut u32; +pub const fpu_stack_empty: *mut i32 = 816i32 as *mut i32; +pub const mxcsr: *mut i32 = 824i32 as *mut i32; +pub const reg_xmm: *mut reg128 = 828i32 as *mut reg128; +pub const current_tsc: *mut u64 = 956i32 as *mut u64; +pub const fpu_st: *mut f64 = 968i32 as *mut f64; +pub const fpu_st8: *mut u8 = 968i32 as *mut u8; +pub const fpu_st32: *mut i32 = 968i32 as *mut i32; +pub const fpu_stack_ptr: *mut u32 = 1032i32 as *mut u32; +pub const fpu_control_word: *mut i32 = 1036i32 as *mut i32; +pub const fpu_status_word: *mut i32 = 1040i32 as *mut i32; +pub const fpu_opcode: *mut i32 = 1044i32 as *mut i32; +pub const fpu_ip: *mut i32 = 1048i32 as *mut i32; +pub const fpu_ip_selector: *mut i32 = 1052i32 as *mut i32; +pub const fpu_dp: *mut i32 = 1056i32 as *mut i32; +pub const fpu_dp_selector: *mut i32 = 1060i32 as *mut i32; +pub const reg_mmx: *mut reg64 = 1064i32 as *mut reg64; +pub const opstats_buffer: *mut u32 = 4096i32 as *mut u32; +pub const opstats_buffer_0f: *mut u32 = 5120i32 as *mut u32; +pub const tlb_data: *mut i32 = 4194304i32 as *mut i32; From c489463c835dc12d633baa9c2b85b0322d27847e Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 18 Aug 2018 22:14:08 -0500 Subject: [PATCH 1196/2137] rust2c cleanup: Fix warnings --- src/rust/cpu2/arith.rs | 1 - src/rust/cpu2/cpu.rs | 1 - src/rust/cpu2/fpu.rs | 1 - src/rust/cpu2/global_pointers.rs | 1 - src/rust/cpu2/instructions.rs | 1 - src/rust/cpu2/instructions_0f.rs | 1 - src/rust/cpu2/memory.rs | 1 - src/rust/cpu2/misc_instr.rs | 1 - src/rust/cpu2/modrm.rs | 1 - src/rust/cpu2/profiler.rs | 1 - src/rust/cpu2/sse_instr.rs | 1 - src/rust/cpu2/string.rs | 1 - 12 files changed, 12 deletions(-) diff --git a/src/rust/cpu2/arith.rs b/src/rust/cpu2/arith.rs index 229cfc28..c2e22cfa 100644 --- a/src/rust/cpu2/arith.rs +++ b/src/rust/cpu2/arith.rs @@ -6,7 +6,6 @@ non_upper_case_globals, unused_mut )] -#![feature(extern_types, libc)] use cpu2::cpu::*; use cpu2::global_pointers::*; diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index e7b378e4..b6b7c3b9 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -6,7 +6,6 @@ non_upper_case_globals, unused_mut )] -#![feature(extern_types, libc)] extern "C" { #[no_mangle] diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 1016f252..380dcc58 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -6,7 +6,6 @@ non_upper_case_globals, unused_mut )] -#![feature(extern_types, libc)] use cpu2::cpu::*; use cpu2::global_pointers::*; diff --git a/src/rust/cpu2/global_pointers.rs b/src/rust/cpu2/global_pointers.rs index b50c3da0..7d5261b9 100644 --- a/src/rust/cpu2/global_pointers.rs +++ b/src/rust/cpu2/global_pointers.rs @@ -6,7 +6,6 @@ non_upper_case_globals, unused_mut )] -#![feature(extern_types, libc)] use cpu2::cpu::{reg128, reg64}; diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index 0ba192e4..6bc51ecb 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -6,7 +6,6 @@ non_upper_case_globals, unused_mut )] -#![feature(extern_types, libc)] extern "C" { #[no_mangle] diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index a0b3b02a..0b4b5706 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -6,7 +6,6 @@ non_upper_case_globals, unused_mut )] -#![feature(extern_types, libc)] extern "C" { #[no_mangle] diff --git a/src/rust/cpu2/memory.rs b/src/rust/cpu2/memory.rs index 807ba846..1b1600f8 100644 --- a/src/rust/cpu2/memory.rs +++ b/src/rust/cpu2/memory.rs @@ -6,7 +6,6 @@ non_upper_case_globals, unused_mut )] -#![feature(extern_types, libc)] extern "C" { #[no_mangle] diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index 4decc8ff..a92f2d52 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -6,7 +6,6 @@ non_upper_case_globals, unused_mut )] -#![feature(extern_types, libc)] use cpu2::cpu::*; use cpu2::fpu::{fpu_load_m80, fpu_load_status_word, fpu_set_status_word, fpu_store_m80}; diff --git a/src/rust/cpu2/modrm.rs b/src/rust/cpu2/modrm.rs index 0db6f43f..c5cb650b 100644 --- a/src/rust/cpu2/modrm.rs +++ b/src/rust/cpu2/modrm.rs @@ -6,7 +6,6 @@ non_upper_case_globals, unused_mut )] -#![feature(extern_types, libc)] use cpu2::cpu::*; use cpu2::global_pointers::*; diff --git a/src/rust/cpu2/profiler.rs b/src/rust/cpu2/profiler.rs index 756f0d61..073a9f7b 100644 --- a/src/rust/cpu2/profiler.rs +++ b/src/rust/cpu2/profiler.rs @@ -6,7 +6,6 @@ non_upper_case_globals, unused_mut )] -#![feature(extern_types, libc)] pub const S_SAFE_WRITE32_SLOW_NOT_VALID: stat_name = 22; pub const S_SAFE_WRITE32_SLOW_NOT_USER: stat_name = 23; diff --git a/src/rust/cpu2/sse_instr.rs b/src/rust/cpu2/sse_instr.rs index ee55781a..ea25ed17 100644 --- a/src/rust/cpu2/sse_instr.rs +++ b/src/rust/cpu2/sse_instr.rs @@ -6,7 +6,6 @@ non_upper_case_globals, unused_mut )] -#![feature(extern_types, libc)] use cpu2::cpu::*; diff --git a/src/rust/cpu2/string.rs b/src/rust/cpu2/string.rs index a341f412..7458a02e 100644 --- a/src/rust/cpu2/string.rs +++ b/src/rust/cpu2/string.rs @@ -6,7 +6,6 @@ non_upper_case_globals, unused_mut )] -#![feature(extern_types, libc)] extern "C" { #[no_mangle] From ebf9cb1750353da2260da825a168eeba371ee6cc Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 20 Aug 2018 11:32:14 -0500 Subject: [PATCH 1197/2137] Remove extern from functions --- src/rust/cpu2/arith.rs | 272 ++-- src/rust/cpu2/cpu.rs | 255 ++-- src/rust/cpu2/fpu.rs | 138 +- src/rust/cpu2/instructions.rs | 1972 ++++++++++++------------ src/rust/cpu2/instructions_0f.rs | 2384 +++++++++++++----------------- src/rust/cpu2/memory.rs | 30 +- src/rust/cpu2/misc_instr.rs | 178 +-- src/rust/cpu2/modrm.rs | 14 +- src/rust/cpu2/profiler.rs | 12 +- src/rust/cpu2/sse_instr.rs | 62 +- src/rust/cpu2/string.rs | 92 +- 11 files changed, 2491 insertions(+), 2918 deletions(-) diff --git a/src/rust/cpu2/arith.rs b/src/rust/cpu2/arith.rs index c2e22cfa..e0d8d28f 100644 --- a/src/rust/cpu2/arith.rs +++ b/src/rust/cpu2/arith.rs @@ -15,11 +15,7 @@ use cpu2::misc_instr::{getaf, getcf}; pub fn int_log2(x: i32) -> i32 { 31 - x.leading_zeros() as i32 } #[no_mangle] -pub unsafe extern "C" fn add( - mut dest_operand: i32, - mut source_operand: i32, - mut op_size: i32, -) -> i32 { +pub unsafe fn add(mut dest_operand: i32, mut source_operand: i32, mut op_size: i32) -> i32 { *last_op1 = dest_operand; *last_op2 = source_operand; let mut res: i32 = dest_operand + source_operand; @@ -30,11 +26,7 @@ pub unsafe extern "C" fn add( return res; } #[no_mangle] -pub unsafe extern "C" fn adc( - mut dest_operand: i32, - mut source_operand: i32, - mut op_size: i32, -) -> i32 { +pub unsafe fn adc(mut dest_operand: i32, mut source_operand: i32, mut op_size: i32) -> i32 { let mut cf: i32 = getcf() as i32; *last_op1 = dest_operand; *last_op2 = source_operand; @@ -46,11 +38,7 @@ pub unsafe extern "C" fn adc( return res; } #[no_mangle] -pub unsafe extern "C" fn sub( - mut dest_operand: i32, - mut source_operand: i32, - mut op_size: i32, -) -> i32 { +pub unsafe fn sub(mut dest_operand: i32, mut source_operand: i32, mut op_size: i32) -> i32 { *last_add_result = dest_operand; *last_op2 = source_operand; let mut res: i32 = dest_operand - source_operand; @@ -61,11 +49,7 @@ pub unsafe extern "C" fn sub( return res; } #[no_mangle] -pub unsafe extern "C" fn sbb( - mut dest_operand: i32, - mut source_operand: i32, - mut op_size: i32, -) -> i32 { +pub unsafe fn sbb(mut dest_operand: i32, mut source_operand: i32, mut op_size: i32) -> i32 { let mut cf: i32 = getcf() as i32; *last_add_result = dest_operand; *last_op2 = source_operand; @@ -77,37 +61,37 @@ pub unsafe extern "C" fn sbb( return res; } #[no_mangle] -pub unsafe extern "C" fn add8(mut x: i32, mut y: i32) -> i32 { return add(x, y, OPSIZE_8); } +pub unsafe fn add8(mut x: i32, mut y: i32) -> i32 { return add(x, y, OPSIZE_8); } #[no_mangle] -pub unsafe extern "C" fn add16(mut x: i32, mut y: i32) -> i32 { return add(x, y, OPSIZE_16); } +pub unsafe fn add16(mut x: i32, mut y: i32) -> i32 { return add(x, y, OPSIZE_16); } #[no_mangle] -pub unsafe extern "C" fn add32(mut x: i32, mut y: i32) -> i32 { return add(x, y, OPSIZE_32); } +pub unsafe fn add32(mut x: i32, mut y: i32) -> i32 { return add(x, y, OPSIZE_32); } #[no_mangle] -pub unsafe extern "C" fn sub8(mut x: i32, mut y: i32) -> i32 { return sub(x, y, OPSIZE_8); } +pub unsafe fn sub8(mut x: i32, mut y: i32) -> i32 { return sub(x, y, OPSIZE_8); } #[no_mangle] -pub unsafe extern "C" fn sub16(mut x: i32, mut y: i32) -> i32 { return sub(x, y, OPSIZE_16); } +pub unsafe fn sub16(mut x: i32, mut y: i32) -> i32 { return sub(x, y, OPSIZE_16); } #[no_mangle] -pub unsafe extern "C" fn sub32(mut x: i32, mut y: i32) -> i32 { return sub(x, y, OPSIZE_32); } +pub unsafe fn sub32(mut x: i32, mut y: i32) -> i32 { return sub(x, y, OPSIZE_32); } #[no_mangle] -pub unsafe extern "C" fn adc8(mut x: i32, mut y: i32) -> i32 { return adc(x, y, OPSIZE_8); } +pub unsafe fn adc8(mut x: i32, mut y: i32) -> i32 { return adc(x, y, OPSIZE_8); } #[no_mangle] -pub unsafe extern "C" fn adc16(mut x: i32, mut y: i32) -> i32 { return adc(x, y, OPSIZE_16); } +pub unsafe fn adc16(mut x: i32, mut y: i32) -> i32 { return adc(x, y, OPSIZE_16); } #[no_mangle] -pub unsafe extern "C" fn adc32(mut x: i32, mut y: i32) -> i32 { return adc(x, y, OPSIZE_32); } +pub unsafe fn adc32(mut x: i32, mut y: i32) -> i32 { return adc(x, y, OPSIZE_32); } #[no_mangle] -pub unsafe extern "C" fn sbb8(mut x: i32, mut y: i32) -> i32 { return sbb(x, y, OPSIZE_8); } +pub unsafe fn sbb8(mut x: i32, mut y: i32) -> i32 { return sbb(x, y, OPSIZE_8); } #[no_mangle] -pub unsafe extern "C" fn sbb16(mut x: i32, mut y: i32) -> i32 { return sbb(x, y, OPSIZE_16); } +pub unsafe fn sbb16(mut x: i32, mut y: i32) -> i32 { return sbb(x, y, OPSIZE_16); } #[no_mangle] -pub unsafe extern "C" fn sbb32(mut x: i32, mut y: i32) -> i32 { return sbb(x, y, OPSIZE_32); } +pub unsafe fn sbb32(mut x: i32, mut y: i32) -> i32 { return sbb(x, y, OPSIZE_32); } #[no_mangle] -pub unsafe extern "C" fn cmp8(mut x: i32, mut y: i32) -> () { sub(x, y, OPSIZE_8); } +pub unsafe fn cmp8(mut x: i32, mut y: i32) -> () { sub(x, y, OPSIZE_8); } #[no_mangle] -pub unsafe extern "C" fn cmp16(mut x: i32, mut y: i32) -> () { sub(x, y, OPSIZE_16); } +pub unsafe fn cmp16(mut x: i32, mut y: i32) -> () { sub(x, y, OPSIZE_16); } #[no_mangle] -pub unsafe extern "C" fn cmp32(mut x: i32, mut y: i32) -> () { sub(x, y, OPSIZE_32); } +pub unsafe fn cmp32(mut x: i32, mut y: i32) -> () { sub(x, y, OPSIZE_32); } #[no_mangle] -pub unsafe extern "C" fn inc(mut dest_operand: i32, mut op_size: i32) -> i32 { +pub unsafe fn inc(mut dest_operand: i32, mut op_size: i32) -> i32 { *flags = *flags & !1i32 | getcf() as i32; *last_op1 = dest_operand; *last_op2 = 1i32; @@ -119,7 +103,7 @@ pub unsafe extern "C" fn inc(mut dest_operand: i32, mut op_size: i32) -> i32 { return res; } #[no_mangle] -pub unsafe extern "C" fn dec(mut dest_operand: i32, mut op_size: i32) -> i32 { +pub unsafe fn dec(mut dest_operand: i32, mut op_size: i32) -> i32 { *flags = *flags & !1i32 | getcf() as i32; *last_add_result = dest_operand; *last_op2 = 1i32; @@ -131,19 +115,19 @@ pub unsafe extern "C" fn dec(mut dest_operand: i32, mut op_size: i32) -> i32 { return res; } #[no_mangle] -pub unsafe extern "C" fn inc8(mut x: i32) -> i32 { return inc(x, OPSIZE_8); } +pub unsafe fn inc8(mut x: i32) -> i32 { return inc(x, OPSIZE_8); } #[no_mangle] -pub unsafe extern "C" fn inc16(mut x: i32) -> i32 { return inc(x, OPSIZE_16); } +pub unsafe fn inc16(mut x: i32) -> i32 { return inc(x, OPSIZE_16); } #[no_mangle] -pub unsafe extern "C" fn inc32(mut x: i32) -> i32 { return inc(x, OPSIZE_32); } +pub unsafe fn inc32(mut x: i32) -> i32 { return inc(x, OPSIZE_32); } #[no_mangle] -pub unsafe extern "C" fn dec8(mut x: i32) -> i32 { return dec(x, OPSIZE_8); } +pub unsafe fn dec8(mut x: i32) -> i32 { return dec(x, OPSIZE_8); } #[no_mangle] -pub unsafe extern "C" fn dec16(mut x: i32) -> i32 { return dec(x, OPSIZE_16); } +pub unsafe fn dec16(mut x: i32) -> i32 { return dec(x, OPSIZE_16); } #[no_mangle] -pub unsafe extern "C" fn dec32(mut x: i32) -> i32 { return dec(x, OPSIZE_32); } +pub unsafe fn dec32(mut x: i32) -> i32 { return dec(x, OPSIZE_32); } #[no_mangle] -pub unsafe extern "C" fn neg(mut dest_operand: i32, mut op_size: i32) -> i32 { +pub unsafe fn neg(mut dest_operand: i32, mut op_size: i32) -> i32 { let mut res: i32 = -dest_operand; *last_result = res; *last_op1 = *last_result; @@ -154,13 +138,13 @@ pub unsafe extern "C" fn neg(mut dest_operand: i32, mut op_size: i32) -> i32 { return res; } #[no_mangle] -pub unsafe extern "C" fn neg8(mut x: i32) -> i32 { return neg(x, OPSIZE_8); } +pub unsafe fn neg8(mut x: i32) -> i32 { return neg(x, OPSIZE_8); } #[no_mangle] -pub unsafe extern "C" fn neg16(mut x: i32) -> i32 { return neg(x, OPSIZE_16); } +pub unsafe fn neg16(mut x: i32) -> i32 { return neg(x, OPSIZE_16); } #[no_mangle] -pub unsafe extern "C" fn neg32(mut x: i32) -> i32 { return neg(x, OPSIZE_32); } +pub unsafe fn neg32(mut x: i32) -> i32 { return neg(x, OPSIZE_32); } #[no_mangle] -pub unsafe extern "C" fn mul8(mut source_operand: i32) -> () { +pub unsafe fn mul8(mut source_operand: i32) -> () { let mut result: i32 = source_operand * *reg8.offset(AL as isize) as i32; *reg16.offset(AX as isize) = result as u16; *last_result = result & 255i32; @@ -174,7 +158,7 @@ pub unsafe extern "C" fn mul8(mut source_operand: i32) -> () { *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; } #[no_mangle] -pub unsafe extern "C" fn imul8(mut source_operand: i32) -> () { +pub unsafe fn imul8(mut source_operand: i32) -> () { let mut result: i32 = source_operand * *reg8s.offset(AL as isize) as i32; *reg16.offset(AX as isize) = result as u16; *last_result = result & 255i32; @@ -188,7 +172,7 @@ pub unsafe extern "C" fn imul8(mut source_operand: i32) -> () { *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; } #[no_mangle] -pub unsafe extern "C" fn mul16(mut source_operand: u32) -> () { +pub unsafe fn mul16(mut source_operand: u32) -> () { let mut result: u32 = source_operand.wrapping_mul(*reg16.offset(AX as isize) as u32); let mut high_result: u32 = result >> 16i32; *reg16.offset(AX as isize) = result as u16; @@ -204,7 +188,7 @@ pub unsafe extern "C" fn mul16(mut source_operand: u32) -> () { *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; } #[no_mangle] -pub unsafe extern "C" fn imul16(mut source_operand: i32) -> () { +pub unsafe fn imul16(mut source_operand: i32) -> () { let mut result: i32 = source_operand * *reg16s.offset(AX as isize) as i32; *reg16.offset(AX as isize) = result as u16; *reg16.offset(DX as isize) = (result >> 16i32) as u16; @@ -219,7 +203,7 @@ pub unsafe extern "C" fn imul16(mut source_operand: i32) -> () { *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; } #[no_mangle] -pub unsafe extern "C" fn imul_reg16(mut operand1: i32, mut operand2: i32) -> i32 { +pub unsafe fn imul_reg16(mut operand1: i32, mut operand2: i32) -> i32 { dbg_assert!(operand1 < 32768i32 && operand1 >= -32768i32); dbg_assert!(operand2 < 32768i32 && operand2 >= -32768i32); let mut result: i32 = operand1 * operand2; @@ -235,7 +219,7 @@ pub unsafe extern "C" fn imul_reg16(mut operand1: i32, mut operand2: i32) -> i32 return result; } #[no_mangle] -pub unsafe extern "C" fn mul32(mut source_operand: i32) -> () { +pub unsafe fn mul32(mut source_operand: i32) -> () { let mut dest_operand: i32 = *reg32s.offset(EAX as isize); let mut result: u64 = (dest_operand as u32 as u64).wrapping_mul(source_operand as u32 as u64); let mut result_low: i32 = result as i32; @@ -253,7 +237,7 @@ pub unsafe extern "C" fn mul32(mut source_operand: i32) -> () { *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; } #[no_mangle] -pub unsafe extern "C" fn imul32(mut source_operand: i32) -> () { +pub unsafe fn imul32(mut source_operand: i32) -> () { let mut dest_operand: i32 = *reg32s.offset(EAX as isize); let mut result: i64 = dest_operand as i64 * source_operand as i64; let mut result_low: i32 = result as i32; @@ -271,7 +255,7 @@ pub unsafe extern "C" fn imul32(mut source_operand: i32) -> () { *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; } #[no_mangle] -pub unsafe extern "C" fn imul_reg32(mut operand1: i32, mut operand2: i32) -> i32 { +pub unsafe fn imul_reg32(mut operand1: i32, mut operand2: i32) -> i32 { let mut result: i64 = operand1 as i64 * operand2 as i64; let mut result_low: i32 = result as i32; let mut result_high: i32 = (result >> 32i32) as i32; @@ -287,25 +271,25 @@ pub unsafe extern "C" fn imul_reg32(mut operand1: i32, mut operand2: i32) -> i32 return result_low; } #[no_mangle] -pub unsafe extern "C" fn xadd8(mut source_operand: i32, mut reg: i32) -> i32 { +pub unsafe fn xadd8(mut source_operand: i32, mut reg: i32) -> i32 { let mut tmp: i32 = *reg8.offset(reg as isize) as i32; *reg8.offset(reg as isize) = source_operand as u8; return add(source_operand, tmp, OPSIZE_8); } #[no_mangle] -pub unsafe extern "C" fn xadd16(mut source_operand: i32, mut reg: i32) -> i32 { +pub unsafe fn xadd16(mut source_operand: i32, mut reg: i32) -> i32 { let mut tmp: i32 = *reg16.offset(reg as isize) as i32; *reg16.offset(reg as isize) = source_operand as u16; return add(source_operand, tmp, OPSIZE_16); } #[no_mangle] -pub unsafe extern "C" fn xadd32(mut source_operand: i32, mut reg: i32) -> i32 { +pub unsafe fn xadd32(mut source_operand: i32, mut reg: i32) -> i32 { let mut tmp: i32 = *reg32s.offset(reg as isize); *reg32s.offset(reg as isize) = source_operand; return add(source_operand, tmp, OPSIZE_32); } #[no_mangle] -pub unsafe extern "C" fn bcd_daa() -> () { +pub unsafe fn bcd_daa() -> () { let mut old_al: i32 = *reg8.offset(AL as isize) as i32; let mut old_cf: i32 = getcf() as i32; let mut old_af: i32 = getaf() as i32; @@ -327,7 +311,7 @@ pub unsafe extern "C" fn bcd_daa() -> () { *flags_changed = FLAGS_ALL & !1i32 & !FLAG_ADJUST & !FLAG_OVERFLOW; } #[no_mangle] -pub unsafe extern "C" fn bcd_das() -> () { +pub unsafe fn bcd_das() -> () { let mut old_al: i32 = *reg8.offset(AL as isize) as i32; let mut old_cf: i32 = getcf() as i32; *flags &= !1i32; @@ -352,7 +336,7 @@ pub unsafe extern "C" fn bcd_das() -> () { *flags_changed = FLAGS_ALL & !1i32 & !FLAG_ADJUST & !FLAG_OVERFLOW; } #[no_mangle] -pub unsafe extern "C" fn bcd_aad(mut imm8: i32) -> () { +pub unsafe fn bcd_aad(mut imm8: i32) -> () { let mut result: i32 = *reg8.offset(AL as isize) as i32 + *reg8.offset(AH as isize) as i32 * imm8; *last_result = result & 255i32; @@ -365,7 +349,7 @@ pub unsafe extern "C" fn bcd_aad(mut imm8: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn bcd_aam(mut imm8: i32) -> () { +pub unsafe fn bcd_aam(mut imm8: i32) -> () { c_comment!(("ascii adjust after multiplication")); if imm8 == 0i32 { trigger_de(); @@ -380,7 +364,7 @@ pub unsafe extern "C" fn bcd_aam(mut imm8: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn bcd_aaa() -> () { +pub unsafe fn bcd_aaa() -> () { if *reg8.offset(AL as isize) as i32 & 15i32 > 9i32 || 0 != getaf() as i32 { let ref mut fresh4 = *reg16.offset(AX as isize); *fresh4 = (*fresh4 as i32 + 6i32) as u16; @@ -396,7 +380,7 @@ pub unsafe extern "C" fn bcd_aaa() -> () { *flags_changed &= !FLAG_ADJUST & !1i32; } #[no_mangle] -pub unsafe extern "C" fn bcd_aas() -> () { +pub unsafe fn bcd_aas() -> () { if *reg8.offset(AL as isize) as i32 & 15i32 > 9i32 || 0 != getaf() as i32 { let ref mut fresh7 = *reg16.offset(AX as isize); *fresh7 = (*fresh7 as i32 - 6i32) as u16; @@ -412,11 +396,7 @@ pub unsafe extern "C" fn bcd_aas() -> () { *flags_changed &= !FLAG_ADJUST & !1i32; } #[no_mangle] -pub unsafe extern "C" fn and( - mut dest_operand: i32, - mut source_operand: i32, - mut op_size: i32, -) -> i32 { +pub unsafe fn and(mut dest_operand: i32, mut source_operand: i32, mut op_size: i32) -> i32 { *last_result = dest_operand & source_operand; *last_op_size = op_size; *flags &= !1i32 & !FLAG_OVERFLOW & !FLAG_ADJUST; @@ -424,11 +404,7 @@ pub unsafe extern "C" fn and( return *last_result; } #[no_mangle] -pub unsafe extern "C" fn or( - mut dest_operand: i32, - mut source_operand: i32, - mut op_size: i32, -) -> i32 { +pub unsafe fn or(mut dest_operand: i32, mut source_operand: i32, mut op_size: i32) -> i32 { *last_result = dest_operand | source_operand; *last_op_size = op_size; *flags &= !1i32 & !FLAG_OVERFLOW & !FLAG_ADJUST; @@ -436,11 +412,7 @@ pub unsafe extern "C" fn or( return *last_result; } #[no_mangle] -pub unsafe extern "C" fn xor( - mut dest_operand: i32, - mut source_operand: i32, - mut op_size: i32, -) -> i32 { +pub unsafe fn xor(mut dest_operand: i32, mut source_operand: i32, mut op_size: i32) -> i32 { *last_result = dest_operand ^ source_operand; *last_op_size = op_size; *flags &= !1i32 & !FLAG_OVERFLOW & !FLAG_ADJUST; @@ -448,31 +420,31 @@ pub unsafe extern "C" fn xor( return *last_result; } #[no_mangle] -pub unsafe extern "C" fn and8(mut x: i32, mut y: i32) -> i32 { return and(x, y, OPSIZE_8); } +pub unsafe fn and8(mut x: i32, mut y: i32) -> i32 { return and(x, y, OPSIZE_8); } #[no_mangle] -pub unsafe extern "C" fn and16(mut x: i32, mut y: i32) -> i32 { return and(x, y, OPSIZE_16); } +pub unsafe fn and16(mut x: i32, mut y: i32) -> i32 { return and(x, y, OPSIZE_16); } #[no_mangle] -pub unsafe extern "C" fn and32(mut x: i32, mut y: i32) -> i32 { return and(x, y, OPSIZE_32); } +pub unsafe fn and32(mut x: i32, mut y: i32) -> i32 { return and(x, y, OPSIZE_32); } #[no_mangle] -pub unsafe extern "C" fn test8(mut x: i32, mut y: i32) -> () { and(x, y, OPSIZE_8); } +pub unsafe fn test8(mut x: i32, mut y: i32) -> () { and(x, y, OPSIZE_8); } #[no_mangle] -pub unsafe extern "C" fn test16(mut x: i32, mut y: i32) -> () { and(x, y, OPSIZE_16); } +pub unsafe fn test16(mut x: i32, mut y: i32) -> () { and(x, y, OPSIZE_16); } #[no_mangle] -pub unsafe extern "C" fn test32(mut x: i32, mut y: i32) -> () { and(x, y, OPSIZE_32); } +pub unsafe fn test32(mut x: i32, mut y: i32) -> () { and(x, y, OPSIZE_32); } #[no_mangle] -pub unsafe extern "C" fn or8(mut x: i32, mut y: i32) -> i32 { return or(x, y, OPSIZE_8); } +pub unsafe fn or8(mut x: i32, mut y: i32) -> i32 { return or(x, y, OPSIZE_8); } #[no_mangle] -pub unsafe extern "C" fn or16(mut x: i32, mut y: i32) -> i32 { return or(x, y, OPSIZE_16); } +pub unsafe fn or16(mut x: i32, mut y: i32) -> i32 { return or(x, y, OPSIZE_16); } #[no_mangle] -pub unsafe extern "C" fn or32(mut x: i32, mut y: i32) -> i32 { return or(x, y, OPSIZE_32); } +pub unsafe fn or32(mut x: i32, mut y: i32) -> i32 { return or(x, y, OPSIZE_32); } #[no_mangle] -pub unsafe extern "C" fn xor8(mut x: i32, mut y: i32) -> i32 { return xor(x, y, OPSIZE_8); } +pub unsafe fn xor8(mut x: i32, mut y: i32) -> i32 { return xor(x, y, OPSIZE_8); } #[no_mangle] -pub unsafe extern "C" fn xor16(mut x: i32, mut y: i32) -> i32 { return xor(x, y, OPSIZE_16); } +pub unsafe fn xor16(mut x: i32, mut y: i32) -> i32 { return xor(x, y, OPSIZE_16); } #[no_mangle] -pub unsafe extern "C" fn xor32(mut x: i32, mut y: i32) -> i32 { return xor(x, y, OPSIZE_32); } +pub unsafe fn xor32(mut x: i32, mut y: i32) -> i32 { return xor(x, y, OPSIZE_32); } #[no_mangle] -pub unsafe extern "C" fn rol8(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn rol8(mut dest_operand: i32, mut count: i32) -> i32 { if 0 == count { return dest_operand; } @@ -487,7 +459,7 @@ pub unsafe extern "C" fn rol8(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn rol16(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn rol16(mut dest_operand: i32, mut count: i32) -> i32 { if 0 == count { return dest_operand; } @@ -502,7 +474,7 @@ pub unsafe extern "C" fn rol16(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn rol32(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn rol32(mut dest_operand: i32, mut count: i32) -> i32 { if 0 == count { return dest_operand; } @@ -517,7 +489,7 @@ pub unsafe extern "C" fn rol32(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn rcl8(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn rcl8(mut dest_operand: i32, mut count: i32) -> i32 { count %= 9i32; if 0 == count { return dest_operand; @@ -533,7 +505,7 @@ pub unsafe extern "C" fn rcl8(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn rcl16(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn rcl16(mut dest_operand: i32, mut count: i32) -> i32 { count %= 17i32; if 0 == count { return dest_operand; @@ -550,7 +522,7 @@ pub unsafe extern "C" fn rcl16(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn rcl32(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn rcl32(mut dest_operand: i32, mut count: i32) -> i32 { if 0 == count { return dest_operand; } @@ -567,7 +539,7 @@ pub unsafe extern "C" fn rcl32(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn ror8(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn ror8(mut dest_operand: i32, mut count: i32) -> i32 { if 0 == count { return dest_operand; } @@ -582,7 +554,7 @@ pub unsafe extern "C" fn ror8(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn ror16(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn ror16(mut dest_operand: i32, mut count: i32) -> i32 { if 0 == count { return dest_operand; } @@ -597,7 +569,7 @@ pub unsafe extern "C" fn ror16(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn ror32(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn ror32(mut dest_operand: i32, mut count: i32) -> i32 { if 0 == count { return dest_operand; } @@ -612,7 +584,7 @@ pub unsafe extern "C" fn ror32(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn rcr8(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn rcr8(mut dest_operand: i32, mut count: i32) -> i32 { count %= 9i32; if 0 == count { return dest_operand; @@ -628,7 +600,7 @@ pub unsafe extern "C" fn rcr8(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn rcr16(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn rcr16(mut dest_operand: i32, mut count: i32) -> i32 { count %= 17i32; if 0 == count { return dest_operand; @@ -645,7 +617,7 @@ pub unsafe extern "C" fn rcr16(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn rcr32(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn rcr32(mut dest_operand: i32, mut count: i32) -> i32 { if 0 == count { return dest_operand; } @@ -663,7 +635,7 @@ pub unsafe extern "C" fn rcr32(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn div8(mut source_operand: u32) -> () { +pub unsafe fn div8(mut source_operand: u32) -> () { if source_operand == 0i32 as u32 { trigger_de(); return; @@ -682,7 +654,7 @@ pub unsafe extern "C" fn div8(mut source_operand: u32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn idiv8(mut source_operand: i32) -> () { +pub unsafe fn idiv8(mut source_operand: i32) -> () { if source_operand == 0i32 { trigger_de(); return; @@ -701,7 +673,7 @@ pub unsafe extern "C" fn idiv8(mut source_operand: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn div16(mut source_operand: u32) -> () { +pub unsafe fn div16(mut source_operand: u32) -> () { if source_operand == 0i32 as u32 { trigger_de(); return; @@ -722,7 +694,7 @@ pub unsafe extern "C" fn div16(mut source_operand: u32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn idiv16(mut source_operand: i32) -> () { +pub unsafe fn idiv16(mut source_operand: i32) -> () { if source_operand == 0i32 { trigger_de(); return; @@ -742,7 +714,7 @@ pub unsafe extern "C" fn idiv16(mut source_operand: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn div32(mut source_operand: u32) -> () { +pub unsafe fn div32(mut source_operand: u32) -> () { if source_operand == 0i32 as u32 { trigger_de(); return; @@ -765,7 +737,7 @@ pub unsafe extern "C" fn div32(mut source_operand: u32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn idiv32(mut source_operand: i32) -> () { +pub unsafe fn idiv32(mut source_operand: i32) -> () { if source_operand == 0i32 { trigger_de(); return; @@ -796,7 +768,7 @@ pub unsafe extern "C" fn idiv32(mut source_operand: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn shl8(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn shl8(mut dest_operand: i32, mut count: i32) -> i32 { if count == 0i32 { return dest_operand; } @@ -811,7 +783,7 @@ pub unsafe extern "C" fn shl8(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn shl16(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn shl16(mut dest_operand: i32, mut count: i32) -> i32 { if count == 0i32 { return dest_operand; } @@ -826,7 +798,7 @@ pub unsafe extern "C" fn shl16(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn shl32(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn shl32(mut dest_operand: i32, mut count: i32) -> i32 { if count == 0i32 { return dest_operand; } @@ -841,7 +813,7 @@ pub unsafe extern "C" fn shl32(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn shr8(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn shr8(mut dest_operand: i32, mut count: i32) -> i32 { if count == 0i32 { return dest_operand; } @@ -856,7 +828,7 @@ pub unsafe extern "C" fn shr8(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn shr16(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn shr16(mut dest_operand: i32, mut count: i32) -> i32 { if count == 0i32 { return dest_operand; } @@ -871,7 +843,7 @@ pub unsafe extern "C" fn shr16(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn shr32(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn shr32(mut dest_operand: i32, mut count: i32) -> i32 { if count == 0i32 { return dest_operand; } @@ -886,7 +858,7 @@ pub unsafe extern "C" fn shr32(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn sar8(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn sar8(mut dest_operand: i32, mut count: i32) -> i32 { if count == 0i32 { return dest_operand; } @@ -906,7 +878,7 @@ pub unsafe extern "C" fn sar8(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn sar16(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn sar16(mut dest_operand: i32, mut count: i32) -> i32 { if count == 0i32 { return dest_operand; } @@ -925,7 +897,7 @@ pub unsafe extern "C" fn sar16(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn sar32(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn sar32(mut dest_operand: i32, mut count: i32) -> i32 { if count == 0i32 { return dest_operand; } @@ -939,11 +911,7 @@ pub unsafe extern "C" fn sar32(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn shrd16( - mut dest_operand: i32, - mut source_operand: i32, - mut count: i32, -) -> i32 { +pub unsafe fn shrd16(mut dest_operand: i32, mut source_operand: i32, mut count: i32) -> i32 { if count == 0i32 { return dest_operand; } @@ -963,11 +931,7 @@ pub unsafe extern "C" fn shrd16( }; } #[no_mangle] -pub unsafe extern "C" fn shrd32( - mut dest_operand: i32, - mut source_operand: i32, - mut count: i32, -) -> i32 { +pub unsafe fn shrd32(mut dest_operand: i32, mut source_operand: i32, mut count: i32) -> i32 { if count == 0i32 { return dest_operand; } @@ -983,11 +947,7 @@ pub unsafe extern "C" fn shrd32( }; } #[no_mangle] -pub unsafe extern "C" fn shld16( - mut dest_operand: i32, - mut source_operand: i32, - mut count: i32, -) -> i32 { +pub unsafe fn shld16(mut dest_operand: i32, mut source_operand: i32, mut count: i32) -> i32 { if count == 0i32 { return dest_operand; } @@ -1010,11 +970,7 @@ pub unsafe extern "C" fn shld16( }; } #[no_mangle] -pub unsafe extern "C" fn shld32( - mut dest_operand: i32, - mut source_operand: i32, - mut count: i32, -) -> i32 { +pub unsafe fn shld32(mut dest_operand: i32, mut source_operand: i32, mut count: i32) -> i32 { if count == 0i32 { return dest_operand; } @@ -1036,37 +992,37 @@ pub unsafe extern "C" fn shld32( }; } #[no_mangle] -pub unsafe extern "C" fn bt_reg(mut bit_base: i32, mut bit_offset: i32) -> () { +pub unsafe fn bt_reg(mut bit_base: i32, mut bit_offset: i32) -> () { *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; *flags_changed &= !1i32; } #[no_mangle] -pub unsafe extern "C" fn btc_reg(mut bit_base: i32, mut bit_offset: i32) -> i32 { +pub unsafe fn btc_reg(mut bit_base: i32, mut bit_offset: i32) -> i32 { *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; *flags_changed &= !1i32; return bit_base ^ 1i32 << bit_offset; } #[no_mangle] -pub unsafe extern "C" fn bts_reg(mut bit_base: i32, mut bit_offset: i32) -> i32 { +pub unsafe fn bts_reg(mut bit_base: i32, mut bit_offset: i32) -> i32 { *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; *flags_changed &= !1i32; return bit_base | 1i32 << bit_offset; } #[no_mangle] -pub unsafe extern "C" fn btr_reg(mut bit_base: i32, mut bit_offset: i32) -> i32 { +pub unsafe fn btr_reg(mut bit_base: i32, mut bit_offset: i32) -> i32 { *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; *flags_changed &= !1i32; return bit_base & !(1i32 << bit_offset); } #[no_mangle] -pub unsafe extern "C" fn bt_mem(mut virt_addr: i32, mut bit_offset: i32) -> () { +pub unsafe fn bt_mem(mut virt_addr: i32, mut bit_offset: i32) -> () { let mut bit_base: i32 = return_on_pagefault!(safe_read8(virt_addr + (bit_offset >> 3i32))); bit_offset &= 7i32; *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; *flags_changed &= !1i32; } #[no_mangle] -pub unsafe extern "C" fn btc_mem(mut virt_addr: i32, mut bit_offset: i32) -> () { +pub unsafe fn btc_mem(mut virt_addr: i32, mut bit_offset: i32) -> () { let mut phys_addr: i32 = return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3i32))) as i32; let mut bit_base: i32 = read8(phys_addr as u32); @@ -1076,7 +1032,7 @@ pub unsafe extern "C" fn btc_mem(mut virt_addr: i32, mut bit_offset: i32) -> () write8(phys_addr as u32, bit_base ^ 1i32 << bit_offset); } #[no_mangle] -pub unsafe extern "C" fn btr_mem(mut virt_addr: i32, mut bit_offset: i32) -> () { +pub unsafe fn btr_mem(mut virt_addr: i32, mut bit_offset: i32) -> () { let mut phys_addr: i32 = return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3i32))) as i32; let mut bit_base: i32 = read8(phys_addr as u32); @@ -1086,7 +1042,7 @@ pub unsafe extern "C" fn btr_mem(mut virt_addr: i32, mut bit_offset: i32) -> () write8(phys_addr as u32, bit_base & !(1i32 << bit_offset)); } #[no_mangle] -pub unsafe extern "C" fn bts_mem(mut virt_addr: i32, mut bit_offset: i32) -> () { +pub unsafe fn bts_mem(mut virt_addr: i32, mut bit_offset: i32) -> () { let mut phys_addr: i32 = return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3i32))) as i32; let mut bit_base: i32 = read8(phys_addr as u32); @@ -1096,7 +1052,7 @@ pub unsafe extern "C" fn bts_mem(mut virt_addr: i32, mut bit_offset: i32) -> () write8(phys_addr as u32, bit_base | 1i32 << bit_offset); } #[no_mangle] -pub unsafe extern "C" fn bsf16(mut old: i32, mut bit_base: i32) -> i32 { +pub unsafe fn bsf16(mut old: i32, mut bit_base: i32) -> i32 { *flags_changed = FLAGS_ALL & !FLAG_ZERO; *last_op_size = OPSIZE_16; if bit_base == 0i32 { @@ -1112,7 +1068,7 @@ pub unsafe extern "C" fn bsf16(mut old: i32, mut bit_base: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn bsf32(mut old: i32, mut bit_base: i32) -> i32 { +pub unsafe fn bsf32(mut old: i32, mut bit_base: i32) -> i32 { *flags_changed = FLAGS_ALL & !FLAG_ZERO; *last_op_size = OPSIZE_32; if bit_base == 0i32 { @@ -1127,7 +1083,7 @@ pub unsafe extern "C" fn bsf32(mut old: i32, mut bit_base: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn bsr16(mut old: i32, mut bit_base: i32) -> i32 { +pub unsafe fn bsr16(mut old: i32, mut bit_base: i32) -> i32 { *flags_changed = FLAGS_ALL & !FLAG_ZERO; *last_op_size = OPSIZE_16; if bit_base == 0i32 { @@ -1142,7 +1098,7 @@ pub unsafe extern "C" fn bsr16(mut old: i32, mut bit_base: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn bsr32(mut old: i32, mut bit_base: i32) -> i32 { +pub unsafe fn bsr32(mut old: i32, mut bit_base: i32) -> i32 { *flags_changed = FLAGS_ALL & !FLAG_ZERO; *last_op_size = OPSIZE_32; if bit_base == 0i32 { @@ -1157,7 +1113,7 @@ pub unsafe extern "C" fn bsr32(mut old: i32, mut bit_base: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn popcnt(mut v: i32) -> i32 { +pub unsafe fn popcnt(mut v: i32) -> i32 { *flags_changed = 0i32; *flags &= !FLAGS_ALL; if 0 != v { @@ -1172,7 +1128,7 @@ pub unsafe extern "C" fn popcnt(mut v: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn saturate_sw_to_ub(mut v: u32) -> u32 { +pub unsafe fn saturate_sw_to_ub(mut v: u32) -> u32 { dbg_assert!(v & 4294901760u32 == 0i32 as u32); let mut ret: u32 = v; if ret >= 32768i32 as u32 { @@ -1185,7 +1141,7 @@ pub unsafe extern "C" fn saturate_sw_to_ub(mut v: u32) -> u32 { return ret; } #[no_mangle] -pub unsafe extern "C" fn saturate_sw_to_sb(mut v: i32) -> i32 { +pub unsafe fn saturate_sw_to_sb(mut v: i32) -> i32 { dbg_assert!(v as u32 & 4294901760u32 == 0i32 as u32); let mut ret: i32 = v; if ret > 65408i32 { @@ -1201,7 +1157,7 @@ pub unsafe extern "C" fn saturate_sw_to_sb(mut v: i32) -> i32 { return ret; } #[no_mangle] -pub unsafe extern "C" fn saturate_sd_to_sw(mut v: u32) -> u32 { +pub unsafe fn saturate_sd_to_sw(mut v: u32) -> u32 { let mut ret: u32 = v; if ret > 4294934528u32 { ret = ret & 65535i32 as u32 @@ -1216,7 +1172,7 @@ pub unsafe extern "C" fn saturate_sd_to_sw(mut v: u32) -> u32 { return ret; } #[no_mangle] -pub unsafe extern "C" fn saturate_sd_to_sb(mut v: u32) -> u32 { +pub unsafe fn saturate_sd_to_sb(mut v: u32) -> u32 { let mut ret: u32 = v; if ret > 4294967168u32 { ret = ret & 255i32 as u32 @@ -1231,7 +1187,7 @@ pub unsafe extern "C" fn saturate_sd_to_sb(mut v: u32) -> u32 { return ret; } #[no_mangle] -pub unsafe extern "C" fn saturate_sd_to_ub(mut v: i32) -> i32 { +pub unsafe fn saturate_sd_to_ub(mut v: i32) -> i32 { let mut ret: i32 = v; if ret < 0i32 { ret = 0i32 @@ -1240,7 +1196,7 @@ pub unsafe extern "C" fn saturate_sd_to_ub(mut v: i32) -> i32 { return ret; } #[no_mangle] -pub unsafe extern "C" fn saturate_ud_to_ub(mut v: u32) -> u32 { +pub unsafe fn saturate_ud_to_ub(mut v: u32) -> u32 { let mut ret: u32 = v; if ret > 255i32 as u32 { ret = 255i32 as u32 @@ -1249,7 +1205,7 @@ pub unsafe extern "C" fn saturate_ud_to_ub(mut v: u32) -> u32 { return ret; } #[no_mangle] -pub unsafe extern "C" fn saturate_uw(mut v: u32) -> i32 { +pub unsafe fn saturate_uw(mut v: u32) -> i32 { let mut ret: u32 = v; if ret > 2147483647i32 as u32 { ret = 0i32 as u32 diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index b6b7c3b9..e0d869d7 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -775,13 +775,13 @@ pub static mut CPU_EXCEPTION_VE: i32 = unsafe { 20i32 }; //pub fn call_indirect1(f: fn(u16), x: u16) { f(x); } #[no_mangle] -pub unsafe extern "C" fn after_block_boundary() -> () { jit_block_boundary = 0 != 1i32; } +pub unsafe fn after_block_boundary() -> () { jit_block_boundary = 0 != 1i32; } #[no_mangle] -pub unsafe extern "C" fn same_page(mut addr1: i32, mut addr2: i32) -> bool { +pub unsafe fn same_page(mut addr1: i32, mut addr2: i32) -> bool { return addr1 & !4095i32 == addr2 & !4095i32; } #[no_mangle] -pub unsafe extern "C" fn get_eflags() -> i32 { +pub unsafe fn get_eflags() -> i32 { return *flags & !FLAGS_ALL | getcf() as i32 | (getpf() as i32) << 2i32 @@ -791,7 +791,7 @@ pub unsafe extern "C" fn get_eflags() -> i32 { | (getof() as i32) << 11i32; } #[no_mangle] -pub unsafe extern "C" fn translate_address_read(mut address: i32) -> Result { +pub unsafe fn translate_address_read(mut address: i32) -> Result { let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); let mut user: bool = *cpl.offset(0isize) as i32 == 3i32; @@ -803,7 +803,7 @@ pub unsafe extern "C" fn translate_address_read(mut address: i32) -> Result () { +pub unsafe fn full_clear_tlb() -> () { profiler_stat_increment(S_FULL_CLEAR_TLB); c_comment!(("clear tlb including global pages")); *last_virt_eip = -1i32; @@ -1007,7 +1007,7 @@ pub unsafe extern "C" fn full_clear_tlb() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn clear_tlb() -> () { +pub unsafe fn clear_tlb() -> () { profiler_stat_increment(S_CLEAR_TLB); c_comment!(("clear tlb excluding global pages")); *last_virt_eip = -1i32; @@ -1041,11 +1041,7 @@ pub unsafe extern "C" fn clear_tlb() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn trigger_pagefault( - mut write: bool, - mut user: bool, - mut present: bool, -) -> () { +pub unsafe fn trigger_pagefault(mut write: bool, mut user: bool, mut present: bool) -> () { if 0 != 0i32 * 0i32 { dbg_log_c!( "page fault w=%d u=%d p=%d eip=%x cr2=%x", @@ -1087,7 +1083,7 @@ pub static mut must_not_fault: bool = unsafe { 0 != 0i32 }; #[no_mangle] pub static mut DEBUG: bool = unsafe { 0 != 1i32 }; #[no_mangle] -pub unsafe extern "C" fn translate_address_write(mut address: i32) -> Result { +pub unsafe fn translate_address_write(mut address: i32) -> Result { let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); let mut user: bool = *cpl.offset(0isize) as i32 == 3i32; @@ -1101,7 +1097,7 @@ pub unsafe extern "C" fn translate_address_write(mut address: i32) -> Result () { +pub unsafe fn tlb_set_has_code(mut physical_page: u32, mut has_code: bool) -> () { dbg_assert!(physical_page < (1i32 << 20i32) as u32); let mut i: i32 = 0i32; while i < valid_tlb_entries_count { @@ -1123,7 +1119,7 @@ pub unsafe extern "C" fn tlb_set_has_code(mut physical_page: u32, mut has_code: check_tlb_invariants(); } #[no_mangle] -pub unsafe extern "C" fn check_tlb_invariants() -> () { +pub unsafe fn check_tlb_invariants() -> () { let mut physical_page: u32 = 0; let mut entry_has_code: bool = false; let mut has_code: bool = false; @@ -1144,7 +1140,7 @@ pub unsafe extern "C" fn check_tlb_invariants() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn writable_or_pagefault(mut addr: i32, mut size: i32) -> Result<(), ()> { +pub unsafe fn writable_or_pagefault(mut addr: i32, mut size: i32) -> Result<(), ()> { dbg_assert!(size < 4096i32); dbg_assert!(size > 0i32); if *cr.offset(0isize) & CR0_PG == 0i32 { @@ -1171,7 +1167,7 @@ pub unsafe extern "C" fn writable_or_pagefault(mut addr: i32, mut size: i32) -> }; } #[no_mangle] -pub unsafe extern "C" fn read_imm8() -> Result { +pub unsafe fn read_imm8() -> Result { let mut eip: i32 = *instruction_pointer; if 0 != eip & !4095i32 ^ *last_virt_eip { *eip_phys = (translate_address_read(eip)? ^ eip as u32) as i32; @@ -1183,11 +1179,9 @@ pub unsafe extern "C" fn read_imm8() -> Result { return Ok(data8); } #[no_mangle] -pub unsafe extern "C" fn read_imm8s() -> Result { - return Ok(read_imm8()? << 24i32 >> 24i32); -} +pub unsafe fn read_imm8s() -> Result { return Ok(read_imm8()? << 24i32 >> 24i32); } #[no_mangle] -pub unsafe extern "C" fn read_imm16() -> Result { +pub unsafe fn read_imm16() -> Result { c_comment!(("Two checks in one comparison:")); c_comment!(("1. Did the high 20 bits of eip change")); c_comment!(("or 2. Are the low 12 bits of eip 0xFFF (and this read crosses a page boundary)")); @@ -1201,7 +1195,7 @@ pub unsafe extern "C" fn read_imm16() -> Result { }; } #[no_mangle] -pub unsafe extern "C" fn read_imm32s() -> Result { +pub unsafe fn read_imm32s() -> Result { c_comment!(("Analogue to the above comment")); if (*instruction_pointer ^ *last_virt_eip) as u32 > 4092i32 as u32 { return Ok(read_imm16()? | read_imm16()? << 16i32); @@ -1213,16 +1207,16 @@ pub unsafe extern "C" fn read_imm32s() -> Result { }; } #[no_mangle] -pub unsafe extern "C" fn is_osize_32() -> bool { +pub unsafe fn is_osize_32() -> bool { return *is_32 as i32 != (*prefixes as i32 & PREFIX_MASK_OPSIZE == PREFIX_MASK_OPSIZE) as i32; } #[no_mangle] -pub unsafe extern "C" fn is_asize_32() -> bool { +pub unsafe fn is_asize_32() -> bool { return *is_32 as i32 != (*prefixes as i32 & PREFIX_MASK_ADDRSIZE == PREFIX_MASK_ADDRSIZE) as i32; } #[no_mangle] -pub unsafe extern "C" fn get_seg(mut segment: i32) -> i32 { +pub unsafe fn get_seg(mut segment: i32) -> i32 { dbg_assert!(segment >= 0i32 && segment < 8i32); c_comment!(("TODO: Remove protected_mode check")); if *protected_mode { @@ -1236,15 +1230,12 @@ pub unsafe extern "C" fn get_seg(mut segment: i32) -> i32 { return *segment_offsets.offset(segment as isize); } #[no_mangle] -pub unsafe extern "C" fn trigger_gp(mut code: i32) -> () { +pub unsafe fn trigger_gp(mut code: i32) -> () { *instruction_pointer = *previous_ip; raise_exception_with_code(CPU_EXCEPTION_GP, code); } #[no_mangle] -pub unsafe extern "C" fn raise_exception_with_code( - mut interrupt_nr: i32, - mut error_code: i32, -) -> () { +pub unsafe fn raise_exception_with_code(mut interrupt_nr: i32, mut error_code: i32) -> () { if DEBUG { if must_not_fault { dbg_log_c!( @@ -1265,11 +1256,11 @@ pub unsafe extern "C" fn raise_exception_with_code( assert!(false); } #[no_mangle] -pub unsafe extern "C" fn get_seg_cs() -> i32 { return *segment_offsets.offset(CS as isize); } +pub unsafe fn get_seg_cs() -> i32 { return *segment_offsets.offset(CS as isize); } #[no_mangle] -pub unsafe extern "C" fn get_seg_ss() -> i32 { return *segment_offsets.offset(SS as isize); } +pub unsafe fn get_seg_ss() -> i32 { return *segment_offsets.offset(SS as isize); } #[no_mangle] -pub unsafe extern "C" fn get_seg_prefix(mut default_segment: i32) -> i32 { +pub unsafe fn get_seg_prefix(mut default_segment: i32) -> i32 { let mut prefix: i32 = *prefixes as i32 & PREFIX_MASK_SEGMENT; if 0 != prefix { if prefix == SEG_PREFIX_ZERO { @@ -1284,19 +1275,13 @@ pub unsafe extern "C" fn get_seg_prefix(mut default_segment: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn get_seg_prefix_ds(mut offset: i32) -> i32 { - return get_seg_prefix(DS) + offset; -} +pub unsafe fn get_seg_prefix_ds(mut offset: i32) -> i32 { return get_seg_prefix(DS) + offset; } #[no_mangle] -pub unsafe extern "C" fn get_seg_prefix_ss(mut offset: i32) -> i32 { - return get_seg_prefix(SS) + offset; -} +pub unsafe fn get_seg_prefix_ss(mut offset: i32) -> i32 { return get_seg_prefix(SS) + offset; } #[no_mangle] -pub unsafe extern "C" fn get_seg_prefix_cs(mut offset: i32) -> i32 { - return get_seg_prefix(CS) + offset; -} +pub unsafe fn get_seg_prefix_cs(mut offset: i32) -> i32 { return get_seg_prefix(CS) + offset; } #[no_mangle] -pub unsafe extern "C" fn modrm_resolve(mut modrm_byte: i32) -> Result { +pub unsafe fn modrm_resolve(mut modrm_byte: i32) -> Result { if is_asize_32() { resolve_modrm32(modrm_byte) } @@ -1305,16 +1290,12 @@ pub unsafe extern "C" fn modrm_resolve(mut modrm_byte: i32) -> Result { } } -pub unsafe extern "C" fn run_instruction(opcode: i32) { ::gen::interpreter::run(opcode as u32) } -pub unsafe extern "C" fn run_instruction0f_16(opcode: i32) { - ::gen::interpreter0f_16::run(opcode as u8) -} -pub unsafe extern "C" fn run_instruction0f_32(opcode: i32) { - ::gen::interpreter0f_32::run(opcode as u8) -} +pub unsafe fn run_instruction(opcode: i32) { ::gen::interpreter::run(opcode as u32) } +pub unsafe fn run_instruction0f_16(opcode: i32) { ::gen::interpreter0f_16::run(opcode as u8) } +pub unsafe fn run_instruction0f_32(opcode: i32) { ::gen::interpreter0f_32::run(opcode as u8) } #[no_mangle] -pub unsafe extern "C" fn cycle_internal() -> () { +pub unsafe fn cycle_internal() -> () { profiler_stat_increment(S_CYCLE_INTERNAL); if true { let mut wasm_table_index: u16 = 0; @@ -1365,7 +1346,7 @@ pub unsafe extern "C" fn cycle_internal() -> () { } } #[no_mangle] -pub unsafe extern "C" fn get_phys_eip() -> Result { +pub unsafe fn get_phys_eip() -> Result { let mut eip: i32 = *instruction_pointer; if 0 != eip & !4095i32 ^ *last_virt_eip { *eip_phys = (translate_address_read(eip)? ^ eip as u32) as i32; @@ -1375,7 +1356,7 @@ pub unsafe extern "C" fn get_phys_eip() -> Result { dbg_assert!(!in_mapped_range(phys_addr)); return Ok(phys_addr as i32); } -unsafe extern "C" fn jit_run_interpreted(mut phys_addr: i32) -> () { +unsafe fn jit_run_interpreted(mut phys_addr: i32) -> () { profiler_stat_increment(S_RUN_INTERPRETED); jit_block_boundary = 0 != 0i32; dbg_assert!(!in_mapped_range(phys_addr as u32)); @@ -1396,38 +1377,38 @@ unsafe extern "C" fn jit_run_interpreted(mut phys_addr: i32) -> () { } } #[no_mangle] -pub unsafe extern "C" fn clear_current_cpu_exception() -> () { current_cpu_exception = -1i32; } +pub unsafe fn clear_current_cpu_exception() -> () { current_cpu_exception = -1i32; } #[no_mangle] pub static mut current_cpu_exception: i32 = unsafe { -1i32 }; #[no_mangle] -pub unsafe extern "C" fn pack_current_state_flags() -> cached_state_flags { +pub unsafe fn pack_current_state_flags() -> cached_state_flags { return ((*is_32 as i32) << 0i32 | (*stack_size_32 as i32) << 1i32 | ((*cpl as i32 == 3i32) as i32) << 2i32 | (has_flat_segmentation() as i32) << 3i32) as cached_state_flags; } #[no_mangle] -pub unsafe extern "C" fn has_flat_segmentation() -> bool { +pub unsafe fn has_flat_segmentation() -> bool { c_comment!(("ss can\'t be null")); return *segment_offsets.offset(SS as isize) == 0i32 && !*segment_is_null.offset(DS as isize) && *segment_offsets.offset(DS as isize) == 0i32; } #[no_mangle] -pub unsafe extern "C" fn run_prefix_instruction() -> () { +pub unsafe fn run_prefix_instruction() -> () { run_instruction(return_on_pagefault!(read_imm8()) | (is_osize_32() as i32) << 8i32); } #[no_mangle] -pub unsafe extern "C" fn clear_prefixes() -> () { *prefixes = 0i32 as u8; } +pub unsafe fn clear_prefixes() -> () { *prefixes = 0i32 as u8; } #[no_mangle] -pub unsafe extern "C" fn segment_prefix_op(mut seg: i32) -> () { +pub unsafe fn segment_prefix_op(mut seg: i32) -> () { dbg_assert!(seg <= 5i32); *prefixes = (*prefixes as i32 | seg + 1i32) as u8; run_prefix_instruction(); *prefixes = 0i32 as u8; } #[no_mangle] -pub unsafe extern "C" fn do_many_cycles_native() -> () { +pub unsafe fn do_many_cycles_native() -> () { profiler_stat_increment(S_DO_MANY_CYCLES); let mut initial_timestamp_counter: u32 = *timestamp_counter; while (*timestamp_counter).wrapping_sub(initial_timestamp_counter) < LOOP_COUNTER as u32 @@ -1439,7 +1420,7 @@ pub unsafe extern "C" fn do_many_cycles_native() -> () { #[no_mangle] pub static mut LOOP_COUNTER: i32 = unsafe { 20011i32 }; //#[no_mangle] -//pub unsafe extern "C" fn raise_exception(mut interrupt_nr: i32) -> () { +//pub unsafe fn raise_exception(mut interrupt_nr: i32) -> () { // if DEBUG { // if must_not_fault { // dbg_log_c!("Unexpected fault: 0x%x", interrupt_nr); @@ -1456,7 +1437,7 @@ pub static mut LOOP_COUNTER: i32 = unsafe { 20011i32 }; // throw_cpu_exception(); //} #[no_mangle] -pub unsafe extern "C" fn trigger_de() -> () { +pub unsafe fn trigger_de() -> () { if DEBUG { if cpu_exception_hook(CPU_EXCEPTION_DE) { return; @@ -1467,9 +1448,9 @@ pub unsafe extern "C" fn trigger_de() -> () { set_current_cpu_exception(CPU_EXCEPTION_DE); } #[no_mangle] -pub unsafe extern "C" fn set_current_cpu_exception(mut n: i32) -> () { current_cpu_exception = n; } +pub unsafe fn set_current_cpu_exception(mut n: i32) -> () { current_cpu_exception = n; } #[no_mangle] -pub unsafe extern "C" fn trigger_ud() -> () { +pub unsafe fn trigger_ud() -> () { dbg_log_c!("#ud"); dbg_trace(); if DEBUG { @@ -1482,7 +1463,7 @@ pub unsafe extern "C" fn trigger_ud() -> () { set_current_cpu_exception(CPU_EXCEPTION_UD); } #[no_mangle] -pub unsafe extern "C" fn trigger_nm() -> () { +pub unsafe fn trigger_nm() -> () { if DEBUG { if cpu_exception_hook(CPU_EXCEPTION_NM) { return; @@ -1493,7 +1474,7 @@ pub unsafe extern "C" fn trigger_nm() -> () { set_current_cpu_exception(CPU_EXCEPTION_NM); } #[no_mangle] -pub unsafe extern "C" fn trigger_gp_non_raising(mut code: i32) -> () { +pub unsafe fn trigger_gp_non_raising(mut code: i32) -> () { if DEBUG { if cpu_exception_hook(CPU_EXCEPTION_GP) { return; @@ -1504,13 +1485,13 @@ pub unsafe extern "C" fn trigger_gp_non_raising(mut code: i32) -> () { set_current_cpu_exception(CPU_EXCEPTION_GP); } #[no_mangle] -pub unsafe extern "C" fn virt_boundary_read16(mut low: i32, mut high: i32) -> i32 { +pub unsafe fn virt_boundary_read16(mut low: i32, mut high: i32) -> i32 { dbg_assert!(low & 4095i32 == 4095i32); dbg_assert!(high & 4095i32 == 0i32); return read8(low as u32) | read8(high as u32) << 8i32; } #[no_mangle] -pub unsafe extern "C" fn virt_boundary_read32s(mut low: i32, mut high: i32) -> i32 { +pub unsafe fn virt_boundary_read32s(mut low: i32, mut high: i32) -> i32 { dbg_assert!(low & 4095i32 >= 4093i32); dbg_assert!(high - 3i32 & 4095i32 == low & 4095i32); let mut mid: i32 = 0i32; @@ -1531,14 +1512,14 @@ pub unsafe extern "C" fn virt_boundary_read32s(mut low: i32, mut high: i32) -> i return read8(low as u32) | mid << 8i32 | read8(high as u32) << 24i32; } #[no_mangle] -pub unsafe extern "C" fn virt_boundary_write16(mut low: i32, mut high: i32, mut value: i32) -> () { +pub unsafe fn virt_boundary_write16(mut low: i32, mut high: i32, mut value: i32) -> () { dbg_assert!(low & 4095i32 == 4095i32); dbg_assert!(high & 4095i32 == 0i32); write8(low as u32, value); write8(high as u32, value >> 8i32); } #[no_mangle] -pub unsafe extern "C" fn virt_boundary_write32(mut low: i32, mut high: i32, mut value: i32) -> () { +pub unsafe fn virt_boundary_write32(mut low: i32, mut high: i32, mut value: i32) -> () { dbg_assert!(low & 4095i32 >= 4093i32); dbg_assert!(high - 3i32 & 4095i32 == low & 4095i32); write8(low as u32, value); @@ -1562,12 +1543,12 @@ pub unsafe extern "C" fn virt_boundary_write32(mut low: i32, mut high: i32, mut write8(high as u32, value >> 24i32); } #[no_mangle] -pub unsafe extern "C" fn safe_read8(mut addr: i32) -> Result { +pub unsafe fn safe_read8(mut addr: i32) -> Result { assert_no_cpu_exception(); return Ok(read8(translate_address_read(addr)?)); } #[no_mangle] -pub unsafe extern "C" fn assert_no_cpu_exception() -> () { +pub unsafe fn assert_no_cpu_exception() -> () { return; if current_cpu_exception != -1i32 { dbg_log_c!("Expected no cpu exception, got %d", current_cpu_exception); @@ -1576,7 +1557,7 @@ pub unsafe extern "C" fn assert_no_cpu_exception() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn safe_read16(mut address: i32) -> Result { +pub unsafe fn safe_read16(mut address: i32) -> Result { let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); let mut info_bits: i32 = entry & 4095i32 & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; @@ -1592,7 +1573,7 @@ pub unsafe extern "C" fn safe_read16(mut address: i32) -> Result { }; } #[no_mangle] -pub unsafe extern "C" fn safe_read16_slow(mut addr: i32) -> Result { +pub unsafe fn safe_read16_slow(mut addr: i32) -> Result { assert_no_cpu_exception(); if addr & 4095i32 == 4095i32 { return Ok(safe_read8(addr)? | safe_read8(addr + 1i32)? << 8i32); @@ -1602,7 +1583,7 @@ pub unsafe extern "C" fn safe_read16_slow(mut addr: i32) -> Result { }; } #[no_mangle] -pub unsafe extern "C" fn safe_read32s(mut address: i32) -> Result { +pub unsafe fn safe_read32s(mut address: i32) -> Result { assert_no_cpu_exception(); let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); @@ -1639,7 +1620,7 @@ pub unsafe extern "C" fn safe_read32s(mut address: i32) -> Result { }; } #[no_mangle] -pub unsafe extern "C" fn safe_read32s_slow(mut addr: i32) -> Result { +pub unsafe fn safe_read32s_slow(mut addr: i32) -> Result { if addr & 4095i32 >= 4093i32 { return Ok(safe_read16(addr)? | safe_read16(addr + 2i32)? << 16i32); } @@ -1679,7 +1660,7 @@ pub unsafe fn safe_read32s_slow_jit(addr: i32) -> i32 { } #[no_mangle] -pub unsafe extern "C" fn safe_read64s(mut addr: i32) -> Result { +pub unsafe fn safe_read64s(mut addr: i32) -> Result { let mut addr_phys: i32 = 0; assert_no_cpu_exception(); let mut x: reg64 = reg64 { i8_0: [0; 8] }; @@ -1694,7 +1675,7 @@ pub unsafe extern "C" fn safe_read64s(mut addr: i32) -> Result { Ok(x) } #[no_mangle] -pub unsafe extern "C" fn safe_read128s(mut addr: i32) -> Result { +pub unsafe fn safe_read128s(mut addr: i32) -> Result { let mut addr_phys: i32 = 0; assert_no_cpu_exception(); let mut x: reg128 = reg128 { i8_0: [0; 16] }; @@ -1709,13 +1690,13 @@ pub unsafe extern "C" fn safe_read128s(mut addr: i32) -> Result { Ok(x) } #[no_mangle] -pub unsafe extern "C" fn safe_write8(mut addr: i32, mut value: i32) -> Result<(), ()> { +pub unsafe fn safe_write8(mut addr: i32, mut value: i32) -> Result<(), ()> { assert_no_cpu_exception(); write8(translate_address_write(addr)?, value); Ok(()) } #[no_mangle] -pub unsafe extern "C" fn safe_write16(mut address: i32, mut value: i32) -> Result<(), ()> { +pub unsafe fn safe_write16(mut address: i32, mut value: i32) -> Result<(), ()> { let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); let mut info_bits: i32 = entry & 4095i32 & !TLB_GLOBAL; @@ -1735,7 +1716,7 @@ pub unsafe extern "C" fn safe_write16(mut address: i32, mut value: i32) -> Resul Ok(()) } #[no_mangle] -pub unsafe extern "C" fn safe_write16_slow(mut addr: i32, mut value: i32) -> Result<(), ()> { +pub unsafe fn safe_write16_slow(mut addr: i32, mut value: i32) -> Result<(), ()> { assert_no_cpu_exception(); let mut phys_low: i32 = translate_address_write(addr)? as i32; if addr & 4095i32 == 4095i32 { @@ -1751,7 +1732,7 @@ pub unsafe extern "C" fn safe_write16_slow(mut addr: i32, mut value: i32) -> Res Ok(()) } #[no_mangle] -pub unsafe extern "C" fn safe_write32(mut address: i32, mut value: i32) -> Result<(), ()> { +pub unsafe fn safe_write32(mut address: i32, mut value: i32) -> Result<(), ()> { assert_no_cpu_exception(); let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); @@ -1802,7 +1783,7 @@ pub unsafe extern "C" fn safe_write32(mut address: i32, mut value: i32) -> Resul Ok(()) } #[no_mangle] -pub unsafe extern "C" fn safe_write32_slow(mut addr: i32, mut value: i32) -> Result<(), ()> { +pub unsafe fn safe_write32_slow(mut addr: i32, mut value: i32) -> Result<(), ()> { let mut phys_low: i32 = translate_address_write(addr)? as i32; if addr & 4095i32 > 4096i32 - 4i32 { virt_boundary_write32( @@ -1834,7 +1815,7 @@ pub unsafe fn safe_write32_slow_jit(addr: i32, value: i32) { } #[no_mangle] -pub unsafe extern "C" fn safe_write64(mut addr: i32, mut value: i64) -> Result<(), ()> { +pub unsafe fn safe_write64(mut addr: i32, mut value: i64) -> Result<(), ()> { assert_no_cpu_exception(); if addr & 4095i32 > 4096i32 - 8i32 { writable_or_pagefault(addr, 8i32)?; @@ -1848,7 +1829,7 @@ pub unsafe extern "C" fn safe_write64(mut addr: i32, mut value: i64) -> Result<( Ok(()) } #[no_mangle] -pub unsafe extern "C" fn safe_write128(mut addr: i32, mut value: reg128) -> Result<(), ()> { +pub unsafe fn safe_write128(mut addr: i32, mut value: reg128) -> Result<(), ()> { assert_no_cpu_exception(); if addr & 4095i32 > 4096i32 - 16i32 { writable_or_pagefault(addr, 16i32)?; @@ -1862,37 +1843,35 @@ pub unsafe extern "C" fn safe_write128(mut addr: i32, mut value: reg128) -> Resu Ok(()) } #[no_mangle] -pub unsafe extern "C" fn get_reg8_index(mut index: i32) -> i32 { +pub unsafe fn get_reg8_index(mut index: i32) -> i32 { return index << 2i32 & 12i32 | index >> 2i32 & 1i32; } #[no_mangle] -pub unsafe extern "C" fn read_reg8(mut index: i32) -> i32 { +pub unsafe fn read_reg8(mut index: i32) -> i32 { return *reg8.offset(get_reg8_index(index) as isize) as i32; } #[no_mangle] -pub unsafe extern "C" fn write_reg8(mut index: i32, mut value: i32) -> () { +pub unsafe fn write_reg8(mut index: i32, mut value: i32) -> () { *reg8.offset(get_reg8_index(index) as isize) = value as u8; } #[no_mangle] -pub unsafe extern "C" fn get_reg16_index(mut index: i32) -> i32 { return index << 1i32; } +pub unsafe fn get_reg16_index(mut index: i32) -> i32 { return index << 1i32; } #[no_mangle] -pub unsafe extern "C" fn read_reg16(mut index: i32) -> i32 { +pub unsafe fn read_reg16(mut index: i32) -> i32 { return *reg16.offset(get_reg16_index(index) as isize) as i32; } #[no_mangle] -pub unsafe extern "C" fn write_reg16(mut index: i32, mut value: i32) -> () { +pub unsafe fn write_reg16(mut index: i32, mut value: i32) -> () { *reg16.offset(get_reg16_index(index) as isize) = value as u16; } #[no_mangle] -pub unsafe extern "C" fn read_reg32(mut index: i32) -> i32 { - return *reg32s.offset(index as isize); -} +pub unsafe fn read_reg32(mut index: i32) -> i32 { return *reg32s.offset(index as isize); } #[no_mangle] -pub unsafe extern "C" fn write_reg32(mut index: i32, mut value: i32) -> () { +pub unsafe fn write_reg32(mut index: i32, mut value: i32) -> () { *reg32s.offset(index as isize) = value; } #[no_mangle] -pub unsafe extern "C" fn write_reg_osize(mut index: i32, mut value: i32) -> () { +pub unsafe fn write_reg_osize(mut index: i32, mut value: i32) -> () { dbg_assert!(index >= 0i32 && index < 8i32); if is_osize_32() { write_reg32(index, value); @@ -1902,68 +1881,62 @@ pub unsafe extern "C" fn write_reg_osize(mut index: i32, mut value: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn read_mmx32s(mut r: i32) -> i32 { +pub unsafe fn read_mmx32s(mut r: i32) -> i32 { return (*reg_mmx.offset(r as isize)).u32_0[0usize] as i32; } #[no_mangle] -pub unsafe extern "C" fn read_mmx64s(mut r: i32) -> reg64 { return *reg_mmx.offset(r as isize); } +pub unsafe fn read_mmx64s(mut r: i32) -> reg64 { return *reg_mmx.offset(r as isize); } #[no_mangle] -pub unsafe extern "C" fn write_mmx64(mut r: i32, mut low: i32, mut high: i32) -> () { +pub unsafe fn write_mmx64(mut r: i32, mut low: i32, mut high: i32) -> () { (*reg_mmx.offset(r as isize)).u32_0[0usize] = low as u32; (*reg_mmx.offset(r as isize)).u32_0[1usize] = high as u32; } #[no_mangle] -pub unsafe extern "C" fn write_mmx_reg64(mut r: i32, mut data: reg64) -> () { +pub unsafe fn write_mmx_reg64(mut r: i32, mut data: reg64) -> () { (*reg_mmx.offset(r as isize)).u64_0[0usize] = data.u64_0[0usize]; } #[no_mangle] -pub unsafe extern "C" fn read_xmm_f32(mut r: i32) -> f32 { +pub unsafe fn read_xmm_f32(mut r: i32) -> f32 { return (*reg_xmm.offset(r as isize)).f32_0[0usize]; } #[no_mangle] -pub unsafe extern "C" fn read_xmm32(mut r: i32) -> i32 { +pub unsafe fn read_xmm32(mut r: i32) -> i32 { return (*reg_xmm.offset(r as isize)).u32_0[0usize] as i32; } #[no_mangle] -pub unsafe extern "C" fn read_xmm64s(mut r: i32) -> reg64 { +pub unsafe fn read_xmm64s(mut r: i32) -> reg64 { let mut x: reg64 = reg64 { i8_0: [0; 8] }; x.u64_0[0usize] = (*reg_xmm.offset(r as isize)).u64_0[0usize]; return x; } #[no_mangle] -pub unsafe extern "C" fn read_xmm128s(mut r: i32) -> reg128 { return *reg_xmm.offset(r as isize); } +pub unsafe fn read_xmm128s(mut r: i32) -> reg128 { return *reg_xmm.offset(r as isize); } #[no_mangle] -pub unsafe extern "C" fn write_xmm_f32(mut r: i32, mut data: f32) -> () { +pub unsafe fn write_xmm_f32(mut r: i32, mut data: f32) -> () { (*reg_xmm.offset(r as isize)).f32_0[0usize] = data; } #[no_mangle] -pub unsafe extern "C" fn write_xmm32(mut r: i32, mut data: i32) -> () { +pub unsafe fn write_xmm32(mut r: i32, mut data: i32) -> () { (*reg_xmm.offset(r as isize)).i32_0[0usize] = data; } #[no_mangle] -pub unsafe extern "C" fn write_xmm64(mut r: i32, mut data: reg64) -> () { +pub unsafe fn write_xmm64(mut r: i32, mut data: reg64) -> () { (*reg_xmm.offset(r as isize)).u64_0[0usize] = data.u64_0[0usize]; } #[no_mangle] -pub unsafe extern "C" fn write_xmm128( - mut r: i32, - mut i0: i32, - mut i1: i32, - mut i2: i32, - mut i3: i32, -) -> () { +pub unsafe fn write_xmm128(mut r: i32, mut i0: i32, mut i1: i32, mut i2: i32, mut i3: i32) -> () { let mut x: reg128 = reg128 { u32_0: [i0 as u32, i1 as u32, i2 as u32, i3 as u32], }; *reg_xmm.offset(r as isize) = x; } #[no_mangle] -pub unsafe extern "C" fn write_xmm_reg128(mut r: i32, mut data: reg128) -> () { +pub unsafe fn write_xmm_reg128(mut r: i32, mut data: reg128) -> () { (*reg_xmm.offset(r as isize)).u64_0[0usize] = data.u64_0[0usize]; (*reg_xmm.offset(r as isize)).u64_0[1usize] = data.u64_0[1usize]; } #[no_mangle] -pub unsafe extern "C" fn task_switch_test() -> bool { +pub unsafe fn task_switch_test() -> bool { if 0 != *cr.offset(0isize) & (CR0_EM | CR0_TS) { trigger_nm(); return 0 != 0i32; @@ -1973,9 +1946,9 @@ pub unsafe extern "C" fn task_switch_test() -> bool { }; } #[no_mangle] -pub unsafe extern "C" fn task_switch_test_void() -> () { task_switch_test(); } +pub unsafe fn task_switch_test_void() -> () { task_switch_test(); } #[no_mangle] -pub unsafe extern "C" fn task_switch_test_mmx() -> bool { +pub unsafe fn task_switch_test_mmx() -> bool { if 0 != *cr & CR0_TS { trigger_nm(); return 0 != 0i32; @@ -1989,9 +1962,9 @@ pub unsafe extern "C" fn task_switch_test_mmx() -> bool { }; } #[no_mangle] -pub unsafe extern "C" fn task_switch_test_mmx_void() -> () { task_switch_test_mmx(); } +pub unsafe fn task_switch_test_mmx_void() -> () { task_switch_test_mmx(); } #[no_mangle] -pub unsafe extern "C" fn read_moffs() -> Result { +pub unsafe fn read_moffs() -> Result { c_comment!(("read 2 or 4 byte from ip, depending on address size attribute")); if is_asize_32() { read_imm32s() @@ -2001,12 +1974,12 @@ pub unsafe extern "C" fn read_moffs() -> Result { } } #[no_mangle] -pub unsafe extern "C" fn get_real_eip() -> i32 { +pub unsafe fn get_real_eip() -> i32 { c_comment!(("Returns the \'real\' instruction pointer, without segment offset")); return *instruction_pointer - get_seg_cs(); } #[no_mangle] -pub unsafe extern "C" fn get_stack_reg() -> i32 { +pub unsafe fn get_stack_reg() -> i32 { if *stack_size_32 { return *reg32s.offset(ESP as isize); } @@ -2015,7 +1988,7 @@ pub unsafe extern "C" fn get_stack_reg() -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn set_stack_reg(mut value: i32) -> () { +pub unsafe fn set_stack_reg(mut value: i32) -> () { if *stack_size_32 { *reg32s.offset(ESP as isize) = value } @@ -2024,7 +1997,7 @@ pub unsafe extern "C" fn set_stack_reg(mut value: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn get_reg_asize(mut reg: i32) -> i32 { +pub unsafe fn get_reg_asize(mut reg: i32) -> i32 { dbg_assert!(reg == ECX || reg == ESI || reg == EDI); let mut r: i32 = *reg32s.offset(reg as isize); if is_asize_32() { @@ -2035,7 +2008,7 @@ pub unsafe extern "C" fn get_reg_asize(mut reg: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn set_ecx_asize(mut value: i32) -> () { +pub unsafe fn set_ecx_asize(mut value: i32) -> () { if is_asize_32() { *reg32s.offset(ECX as isize) = value } @@ -2044,7 +2017,7 @@ pub unsafe extern "C" fn set_ecx_asize(mut value: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn add_reg_asize(mut reg: i32, mut value: i32) -> () { +pub unsafe fn add_reg_asize(mut reg: i32, mut value: i32) -> () { dbg_assert!(reg == ECX || reg == ESI || reg == EDI); if is_asize_32() { let ref mut fresh2 = *reg32s.offset(reg as isize); @@ -2056,7 +2029,7 @@ pub unsafe extern "C" fn add_reg_asize(mut reg: i32, mut value: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn decr_ecx_asize() -> i32 { +pub unsafe fn decr_ecx_asize() -> i32 { return if 0 != is_asize_32() as i32 { let ref mut fresh4 = *reg32s.offset(ECX as isize); *fresh4 -= 1; @@ -2069,13 +2042,13 @@ pub unsafe extern "C" fn decr_ecx_asize() -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn set_tsc(mut low: u32, mut high: u32) -> () { +pub unsafe fn set_tsc(mut low: u32, mut high: u32) -> () { let mut new_value: u64 = low as u64 | (high as u64) << 32i32; let mut current_value: u64 = read_tsc(); tsc_offset = current_value.wrapping_sub(new_value); } #[no_mangle] -pub unsafe extern "C" fn read_tsc() -> u64 { +pub unsafe fn read_tsc() -> u64 { let mut n: f64 = microtick() * TSC_RATE; let mut value: u64 = (n as u64).wrapping_sub(tsc_offset); if 0 != 1i32 + 1i32 { @@ -2120,11 +2093,11 @@ pub static mut tsc_offset: u64 = unsafe { 0i32 as u64 }; #[no_mangle] pub static mut TSC_RATE: f64 = unsafe { (50i32 * 1000i32) as f64 }; #[no_mangle] -pub unsafe extern "C" fn vm86_mode() -> bool { return *flags & FLAG_VM == FLAG_VM; } +pub unsafe fn vm86_mode() -> bool { return *flags & FLAG_VM == FLAG_VM; } #[no_mangle] -pub unsafe extern "C" fn getiopl() -> i32 { return *flags >> 12i32 & 3i32; } +pub unsafe fn getiopl() -> i32 { return *flags >> 12i32 & 3i32; } #[no_mangle] -pub unsafe extern "C" fn get_opstats_buffer(mut index: i32) -> i32 { +pub unsafe fn get_opstats_buffer(mut index: i32) -> i32 { dbg_assert!(index >= 0i32 && index < 512i32); if index < 256i32 { return *opstats_buffer.offset(index as isize) as i32; @@ -2134,7 +2107,7 @@ pub unsafe extern "C" fn get_opstats_buffer(mut index: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn invlpg(mut addr: i32) -> () { +pub unsafe fn invlpg(mut addr: i32) -> () { let mut page: i32 = (addr as u32 >> 12i32) as i32; c_comment!(("Note: Doesn\'t remove this page from valid_tlb_entries: This isn\'t")); c_comment!(("necessary, because when valid_tlb_entries grows too large, it will be")); @@ -2145,7 +2118,7 @@ pub unsafe extern "C" fn invlpg(mut addr: i32) -> () { *last_virt_esp = -1i32; } #[no_mangle] -pub unsafe extern "C" fn update_eflags(mut new_flags: i32) -> () { +pub unsafe fn update_eflags(mut new_flags: i32) -> () { let mut dont_update: i32 = FLAG_RF | FLAG_VM | FLAG_VIP | FLAG_VIF; let mut clear: i32 = !FLAG_VIP & !FLAG_VIF & FLAGS_MASK; if 0 != *flags & FLAG_VM { @@ -2174,7 +2147,7 @@ pub unsafe extern "C" fn update_eflags(mut new_flags: i32) -> () { *flags_changed = 0i32; } #[no_mangle] -pub unsafe extern "C" fn get_valid_tlb_entries_count() -> i32 { +pub unsafe fn get_valid_tlb_entries_count() -> i32 { let mut result: i32 = 0i32; let mut i: i32 = 0i32; while i < valid_tlb_entries_count { @@ -2188,7 +2161,7 @@ pub unsafe extern "C" fn get_valid_tlb_entries_count() -> i32 { return result; } #[no_mangle] -pub unsafe extern "C" fn get_valid_global_tlb_entries_count() -> i32 { +pub unsafe fn get_valid_global_tlb_entries_count() -> i32 { let mut result: i32 = 0i32; let mut i: i32 = 0i32; while i < valid_tlb_entries_count { @@ -2202,7 +2175,7 @@ pub unsafe extern "C" fn get_valid_global_tlb_entries_count() -> i32 { return result; } #[no_mangle] -pub unsafe extern "C" fn translate_address_system_read(mut address: i32) -> Result { +pub unsafe fn translate_address_system_read(mut address: i32) -> Result { let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); if 0 != entry & TLB_VALID { @@ -2213,7 +2186,7 @@ pub unsafe extern "C" fn translate_address_system_read(mut address: i32) -> Resu }; } #[no_mangle] -pub unsafe extern "C" fn translate_address_system_write(mut address: i32) -> Result { +pub unsafe fn translate_address_system_write(mut address: i32) -> Result { let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); if entry & (TLB_VALID | TLB_READONLY) == TLB_VALID { @@ -2224,7 +2197,7 @@ pub unsafe extern "C" fn translate_address_system_write(mut address: i32) -> Res }; } #[no_mangle] -pub unsafe extern "C" fn trigger_np(mut code: i32) -> () { +pub unsafe fn trigger_np(mut code: i32) -> () { if DEBUG { if cpu_exception_hook(CPU_EXCEPTION_NP) { return; @@ -2235,7 +2208,7 @@ pub unsafe extern "C" fn trigger_np(mut code: i32) -> () { set_current_cpu_exception(CPU_EXCEPTION_NP); } #[no_mangle] -pub unsafe extern "C" fn trigger_ss(mut code: i32) -> () { +pub unsafe fn trigger_ss(mut code: i32) -> () { if DEBUG { if cpu_exception_hook(CPU_EXCEPTION_SS) { return; @@ -2246,4 +2219,4 @@ pub unsafe extern "C" fn trigger_ss(mut code: i32) -> () { set_current_cpu_exception(CPU_EXCEPTION_SS); } #[no_mangle] -pub unsafe extern "C" fn store_current_tsc() -> () { *current_tsc = read_tsc(); } +pub unsafe fn store_current_tsc() -> () { *current_tsc = read_tsc(); } diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 380dcc58..0d2a825b 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -56,7 +56,7 @@ pub static mut FPU_RESULT_FLAGS: i32 = unsafe { FPU_C0 | FPU_C1 | FPU_C2 | FPU_C #[no_mangle] pub static mut FPU_STACK_TOP: i32 = unsafe { 14336i32 }; #[no_mangle] -pub unsafe extern "C" fn fpu_get_st0() -> f64 { +pub unsafe fn fpu_get_st0() -> f64 { if 0 != *fpu_stack_empty >> *fpu_stack_ptr & 1i32 { *fpu_status_word &= !FPU_C1; fpu_stack_fault(); @@ -69,7 +69,7 @@ pub unsafe extern "C" fn fpu_get_st0() -> f64 { #[no_mangle] pub static mut INDEFINITE_NAN: f64 = unsafe { ::std::f32::NAN as f64 }; #[no_mangle] -pub unsafe extern "C" fn fpu_stack_fault() -> () { +pub unsafe fn fpu_stack_fault() -> () { c_comment!(("TODO: Interrupt")); *fpu_status_word |= FPU_EX_SF | FPU_EX_I; } @@ -78,7 +78,7 @@ pub static mut FPU_EX_I: i32 = unsafe { 1i32 << 0i32 }; #[no_mangle] pub static mut FPU_EX_SF: i32 = unsafe { 1i32 << 6i32 }; #[no_mangle] -pub unsafe extern "C" fn fpu_get_sti(mut i: i32) -> f64 { +pub unsafe fn fpu_get_sti(mut i: i32) -> f64 { dbg_assert!(i >= 0i32 && i < 8i32); i = ((i as u32).wrapping_add(*fpu_stack_ptr) & 7i32 as u32) as i32; if 0 != *fpu_stack_empty >> i & 1i32 { @@ -91,7 +91,7 @@ pub unsafe extern "C" fn fpu_get_sti(mut i: i32) -> f64 { }; } #[no_mangle] -pub unsafe extern "C" fn fpu_integer_round(mut f: f64) -> f64 { +pub unsafe fn fpu_integer_round(mut f: f64) -> f64 { let mut rc: i32 = *fpu_control_word >> 10i32 & 3i32; c_comment!(("XXX: See https://en.wikipedia.org/wiki/C_mathematical_functions")); if rc == 0i32 { @@ -112,20 +112,20 @@ pub unsafe extern "C" fn fpu_integer_round(mut f: f64) -> f64 { }; } #[no_mangle] -pub unsafe extern "C" fn fpu_load_m32(mut addr: i32) -> Result { +pub unsafe fn fpu_load_m32(mut addr: i32) -> Result { let mut v: f32_int = f32_int { i32_0: safe_read32s(addr)?, }; Ok(v.f32_0 as f64) } #[no_mangle] -pub unsafe extern "C" fn fpu_load_m64(mut addr: i32) -> Result { +pub unsafe fn fpu_load_m64(mut addr: i32) -> Result { let mut value: u64 = safe_read64s(addr)?.u64_0[0usize]; let mut v: f64_int = f64_int { u64_0: [value] }; Ok(v.f64_0) } #[no_mangle] -pub unsafe extern "C" fn fpu_load_m80(mut addr: u32) -> Result { +pub unsafe fn fpu_load_m80(mut addr: u32) -> Result { let mut value: u64 = safe_read64s(addr as i32)?.u64_0[0usize]; let mut low: u32 = value as u32; let mut high: u32 = (value >> 32i32) as u32; @@ -163,26 +163,26 @@ pub unsafe extern "C" fn fpu_load_m80(mut addr: u32) -> Result { } } #[no_mangle] -pub unsafe extern "C" fn fpu_load_status_word() -> i32 { +pub unsafe fn fpu_load_status_word() -> i32 { return ((*fpu_status_word & !(7i32 << 11i32)) as u32 | *fpu_stack_ptr << 11i32) as i32; } #[no_mangle] -pub unsafe extern "C" fn fpu_fadd(mut target_index: i32, mut val: f64) -> () { +pub unsafe fn fpu_fadd(mut target_index: i32, mut val: f64) -> () { let mut st0: f64 = fpu_get_st0(); *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = st0 + val; } #[no_mangle] -pub unsafe extern "C" fn fpu_fclex() -> () { *fpu_status_word = 0i32; } +pub unsafe fn fpu_fclex() -> () { *fpu_status_word = 0i32; } #[no_mangle] -pub unsafe extern "C" fn fpu_fcmovcc(mut condition: bool, mut r: i32) -> () { +pub unsafe fn fpu_fcmovcc(mut condition: bool, mut r: i32) -> () { if condition { *fpu_st.offset(*fpu_stack_ptr as isize) = fpu_get_sti(r); *fpu_stack_empty &= !(1i32 << *fpu_stack_ptr) }; } #[no_mangle] -pub unsafe extern "C" fn fpu_fcom(mut y: f64) -> () { +pub unsafe fn fpu_fcom(mut y: f64) -> () { let mut x: f64 = fpu_get_st0(); *fpu_status_word &= !FPU_RESULT_FLAGS; if !(x > y) { @@ -198,7 +198,7 @@ pub unsafe extern "C" fn fpu_fcom(mut y: f64) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn fpu_fcomi(mut r: i32) -> () { +pub unsafe fn fpu_fcomi(mut r: i32) -> () { let mut y: f64 = fpu_get_sti(r); let mut x: f64 = *fpu_st.offset(*fpu_stack_ptr as isize); *flags_changed &= !(1i32 | FLAG_PARITY | FLAG_ZERO); @@ -216,44 +216,44 @@ pub unsafe extern "C" fn fpu_fcomi(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn fpu_fcomip(mut r: i32) -> () { +pub unsafe fn fpu_fcomip(mut r: i32) -> () { fpu_fcomi(r); fpu_pop(); } #[no_mangle] -pub unsafe extern "C" fn fpu_pop() -> () { +pub unsafe fn fpu_pop() -> () { *fpu_stack_empty |= 1i32 << *fpu_stack_ptr; *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_add(1i32 as u32) & 7i32 as u32; } #[no_mangle] -pub unsafe extern "C" fn fpu_fcomp(mut val: f64) -> () { +pub unsafe fn fpu_fcomp(mut val: f64) -> () { fpu_fcom(val); fpu_pop(); } #[no_mangle] -pub unsafe extern "C" fn fpu_fdiv(mut target_index: i32, mut val: f64) -> () { +pub unsafe fn fpu_fdiv(mut target_index: i32, mut val: f64) -> () { let mut st0: f64 = fpu_get_st0(); *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = st0 / val; } #[no_mangle] -pub unsafe extern "C" fn fpu_fdivr(mut target_index: i32, mut val: f64) -> () { +pub unsafe fn fpu_fdivr(mut target_index: i32, mut val: f64) -> () { let mut st0: f64 = fpu_get_st0(); *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = val / st0; } #[no_mangle] -pub unsafe extern "C" fn fpu_ffree(mut r: i32) -> () { +pub unsafe fn fpu_ffree(mut r: i32) -> () { *fpu_stack_empty |= 1i32 << (*fpu_stack_ptr).wrapping_add(r as u32); } #[no_mangle] -pub unsafe extern "C" fn fpu_fildm64(mut addr: i32) -> () { +pub unsafe fn fpu_fildm64(mut addr: i32) -> () { let mut value: i64 = return_on_pagefault!(safe_read64s(addr)).i64_0[0usize]; let mut m64: f64 = value as f64; fpu_push(m64); } #[no_mangle] -pub unsafe extern "C" fn fpu_push(mut x: f64) -> () { +pub unsafe fn fpu_push(mut x: f64) -> () { *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_sub(1i32 as u32) & 7i32 as u32; if 0 != *fpu_stack_empty >> *fpu_stack_ptr & 1i32 { *fpu_status_word &= !FPU_C1; @@ -267,7 +267,7 @@ pub unsafe extern "C" fn fpu_push(mut x: f64) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn fpu_finit() -> () { +pub unsafe fn fpu_finit() -> () { *fpu_control_word = 895i32; *fpu_status_word = 0i32; *fpu_ip.offset(0isize) = 0i32; @@ -277,7 +277,7 @@ pub unsafe extern "C" fn fpu_finit() -> () { *fpu_stack_ptr = 0i32 as u32; } #[no_mangle] -pub unsafe extern "C" fn fpu_fistm16(mut addr: i32) -> () { +pub unsafe fn fpu_fistm16(mut addr: i32) -> () { let mut st0: f64 = fpu_integer_round(fpu_get_st0()); if st0 <= 32767i32 as f64 && st0 >= -32768i32 as f64 { return_on_pagefault!(safe_write16(addr, st0 as i32)); @@ -288,14 +288,14 @@ pub unsafe extern "C" fn fpu_fistm16(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn fpu_invalid_arithmetic() -> () { *fpu_status_word |= FPU_EX_I; } +pub unsafe fn fpu_invalid_arithmetic() -> () { *fpu_status_word |= FPU_EX_I; } #[no_mangle] -pub unsafe extern "C" fn fpu_fistm16p(mut addr: i32) -> () { +pub unsafe fn fpu_fistm16p(mut addr: i32) -> () { fpu_fistm16(addr); fpu_pop(); } #[no_mangle] -pub unsafe extern "C" fn fpu_fistm32(mut addr: i32) -> () { +pub unsafe fn fpu_fistm32(mut addr: i32) -> () { let mut st0: f64 = fpu_integer_round(fpu_get_st0()); let mut i: i32 = convert_f64_to_i32(st0); if i == 2147483648u32 as i32 { @@ -306,12 +306,12 @@ pub unsafe extern "C" fn fpu_fistm32(mut addr: i32) -> () { return_on_pagefault!(safe_write32(addr, i)); } #[no_mangle] -pub unsafe extern "C" fn fpu_fistm32p(mut addr: i32) -> () { +pub unsafe fn fpu_fistm32p(mut addr: i32) -> () { fpu_fistm32(addr); fpu_pop(); } #[no_mangle] -pub unsafe extern "C" fn fpu_fistm64p(mut addr: i32) -> () { +pub unsafe fn fpu_fistm64p(mut addr: i32) -> () { let mut st0: f64 = fpu_integer_round(fpu_get_st0()); let mut value: i64 = 0; if st0 < TWO_POW_63 && st0 >= -TWO_POW_63 { @@ -327,12 +327,12 @@ pub unsafe extern "C" fn fpu_fistm64p(mut addr: i32) -> () { #[no_mangle] pub static mut TWO_POW_63: f64 = unsafe { 9223372036854775808u64 as f64 }; #[no_mangle] -pub unsafe extern "C" fn fpu_fldcw(mut addr: i32) -> () { +pub unsafe fn fpu_fldcw(mut addr: i32) -> () { let mut word: i32 = return_on_pagefault!(safe_read16(addr)); *fpu_control_word = word; } #[no_mangle] -pub unsafe extern "C" fn fpu_fldenv(mut addr: i32) -> () { +pub unsafe fn fpu_fldenv(mut addr: i32) -> () { if is_osize_32() { // TODO: Add readable_or_pagefault return_on_pagefault!(translate_address_read(addr)); @@ -352,7 +352,7 @@ pub unsafe extern "C" fn fpu_fldenv(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn fpu_unimpl() -> () { +pub unsafe fn fpu_unimpl() -> () { if DEBUG { dbg_assert!(0 != 0i32); } @@ -361,7 +361,7 @@ pub unsafe extern "C" fn fpu_unimpl() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn fpu_set_tag_word(mut tag_word: i32) -> () { +pub unsafe fn fpu_set_tag_word(mut tag_word: i32) -> () { *fpu_stack_empty = 0i32; let mut i: i32 = 0i32; while i < 8i32 { @@ -370,38 +370,36 @@ pub unsafe extern "C" fn fpu_set_tag_word(mut tag_word: i32) -> () { } } #[no_mangle] -pub unsafe extern "C" fn fpu_set_status_word(mut sw: i32) -> () { +pub unsafe fn fpu_set_status_word(mut sw: i32) -> () { *fpu_status_word = sw & !(7i32 << 11i32); *fpu_stack_ptr = (sw >> 11i32 & 7i32) as u32; } #[no_mangle] -pub unsafe extern "C" fn fpu_fldm32(mut addr: i32) -> () { +pub unsafe fn fpu_fldm32(mut addr: i32) -> () { fpu_push(return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe extern "C" fn fpu_fldm64(mut addr: i32) -> () { +pub unsafe fn fpu_fldm64(mut addr: i32) -> () { fpu_push(return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe extern "C" fn fpu_fldm80(mut addr: i32) -> () { +pub unsafe fn fpu_fldm80(mut addr: i32) -> () { fpu_push(return_on_pagefault!(fpu_load_m80(addr as u32))); } #[no_mangle] -pub unsafe extern "C" fn fpu_fmul(mut target_index: i32, mut val: f64) -> () { +pub unsafe fn fpu_fmul(mut target_index: i32, mut val: f64) -> () { let mut st0: f64 = fpu_get_st0(); *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = st0 * val; } #[no_mangle] -pub unsafe extern "C" fn fpu_fnstsw_mem(mut addr: i32) -> () { +pub unsafe fn fpu_fnstsw_mem(mut addr: i32) -> () { return_on_pagefault!(safe_write16(addr, fpu_load_status_word())); } #[no_mangle] -pub unsafe extern "C" fn fpu_fnstsw_reg() -> () { - *reg16.offset(AX as isize) = fpu_load_status_word() as u16; -} +pub unsafe fn fpu_fnstsw_reg() -> () { *reg16.offset(AX as isize) = fpu_load_status_word() as u16; } #[no_mangle] -pub unsafe extern "C" fn fpu_fprem() -> () { +pub unsafe fn fpu_fprem() -> () { c_comment!(("XXX: This implementation differs from the description in Intel\'s manuals")); let mut st0: f64 = fpu_get_st0(); let mut st1: f64 = fpu_get_sti(1i32); @@ -420,7 +418,7 @@ pub unsafe extern "C" fn fpu_fprem() -> () { *fpu_status_word &= !FPU_C2; } #[no_mangle] -pub unsafe extern "C" fn fpu_frstor(mut addr: i32) -> () { +pub unsafe fn fpu_frstor(mut addr: i32) -> () { // TODO: Add readable_or_pagefault return_on_pagefault!(translate_address_read(addr)); return_on_pagefault!(translate_address_read(addr + 28 + 8 * 10)); @@ -435,7 +433,7 @@ pub unsafe extern "C" fn fpu_frstor(mut addr: i32) -> () { } } #[no_mangle] -pub unsafe extern "C" fn fpu_fsave(mut addr: i32) -> () { +pub unsafe fn fpu_fsave(mut addr: i32) -> () { return_on_pagefault!(writable_or_pagefault(addr, 108i32)); fpu_fstenv(addr); addr += 28i32; @@ -451,7 +449,7 @@ pub unsafe extern "C" fn fpu_fsave(mut addr: i32) -> () { fpu_finit(); } #[no_mangle] -pub unsafe extern "C" fn fpu_store_m80(mut addr: u32, mut n: f64) -> () { +pub unsafe fn fpu_store_m80(mut addr: u32, mut n: f64) -> () { let mut double_int_view: f64_int = f64_int { f64_0: n }; let mut sign: u8 = (double_int_view.u8_0[7usize] as i32 & 128i32) as u8; let mut exponent: i32 = (double_int_view.u8_0[7usize] as i32 & 127i32) << 4i32 @@ -491,7 +489,7 @@ pub unsafe extern "C" fn fpu_store_m80(mut addr: u32, mut n: f64) -> () { ).unwrap(); } #[no_mangle] -pub unsafe extern "C" fn fpu_fstenv(mut addr: i32) -> () { +pub unsafe fn fpu_fstenv(mut addr: i32) -> () { if is_osize_32() { return_on_pagefault!(writable_or_pagefault(addr, 26i32)); safe_write16(addr, *fpu_control_word).unwrap(); @@ -509,7 +507,7 @@ pub unsafe extern "C" fn fpu_fstenv(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn fpu_load_tag_word() -> i32 { +pub unsafe fn fpu_load_tag_word() -> i32 { let mut tag_word: i32 = 0i32; let mut i: i32 = 0i32; while i < 8i32 { @@ -528,66 +526,66 @@ pub unsafe extern "C" fn fpu_load_tag_word() -> i32 { return tag_word; } #[no_mangle] -pub unsafe extern "C" fn fpu_fst(mut r: i32) -> () { +pub unsafe fn fpu_fst(mut r: i32) -> () { *fpu_st.offset((*fpu_stack_ptr).wrapping_add(r as u32) as isize) = fpu_get_st0(); } #[no_mangle] -pub unsafe extern "C" fn fpu_fst80p(mut addr: i32) -> () { +pub unsafe fn fpu_fst80p(mut addr: i32) -> () { return_on_pagefault!(writable_or_pagefault(addr, 10i32)); fpu_store_m80(addr as u32, fpu_get_st0()); fpu_pop(); } #[no_mangle] -pub unsafe extern "C" fn fpu_fstcw(mut addr: i32) -> () { +pub unsafe fn fpu_fstcw(mut addr: i32) -> () { return_on_pagefault!(safe_write16(addr, *fpu_control_word)); } #[no_mangle] -pub unsafe extern "C" fn fpu_fstm32(mut addr: i32) -> () { +pub unsafe fn fpu_fstm32(mut addr: i32) -> () { return_on_pagefault!(fpu_store_m32(addr, fpu_get_st0())); } #[no_mangle] -pub unsafe extern "C" fn fpu_store_m32(mut addr: i32, mut x: f64) -> Result<(), ()> { +pub unsafe fn fpu_store_m32(mut addr: i32, mut x: f64) -> Result<(), ()> { let mut v: f32_int = f32_int { f32_0: x as f32 }; safe_write32(addr, v.i32_0) } #[no_mangle] -pub unsafe extern "C" fn fpu_fstm32p(mut addr: i32) -> () { +pub unsafe fn fpu_fstm32p(mut addr: i32) -> () { fpu_fstm32(addr); fpu_pop(); } #[no_mangle] -pub unsafe extern "C" fn fpu_fstm64(mut addr: i32) -> () { +pub unsafe fn fpu_fstm64(mut addr: i32) -> () { return_on_pagefault!(fpu_store_m64(addr, fpu_get_st0())); } #[no_mangle] -pub unsafe extern "C" fn fpu_store_m64(mut addr: i32, mut x: f64) -> Result<(), ()> { +pub unsafe fn fpu_store_m64(mut addr: i32, mut x: f64) -> Result<(), ()> { let mut v: f64_int = f64_int { f64_0: x }; safe_write64(addr, v.u64_0[0usize] as i64) } #[no_mangle] -pub unsafe extern "C" fn fpu_fstm64p(mut addr: i32) -> () { +pub unsafe fn fpu_fstm64p(mut addr: i32) -> () { fpu_fstm64(addr); fpu_pop(); } #[no_mangle] -pub unsafe extern "C" fn fpu_fstp(mut r: i32) -> () { +pub unsafe fn fpu_fstp(mut r: i32) -> () { fpu_fst(r); fpu_pop(); } #[no_mangle] -pub unsafe extern "C" fn fpu_fsub(mut target_index: i32, mut val: f64) -> () { +pub unsafe fn fpu_fsub(mut target_index: i32, mut val: f64) -> () { let mut st0: f64 = fpu_get_st0(); *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = st0 - val; } #[no_mangle] -pub unsafe extern "C" fn fpu_fsubr(mut target_index: i32, mut val: f64) -> () { +pub unsafe fn fpu_fsubr(mut target_index: i32, mut val: f64) -> () { let mut st0: f64 = fpu_get_st0(); *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = val - st0; } #[no_mangle] -pub unsafe extern "C" fn fpu_ftst(mut x: f64) -> () { +pub unsafe fn fpu_ftst(mut x: f64) -> () { *fpu_status_word &= !FPU_RESULT_FLAGS; if x.is_nan() { *fpu_status_word |= FPU_C3 | FPU_C2 | FPU_C0 @@ -601,33 +599,33 @@ pub unsafe extern "C" fn fpu_ftst(mut x: f64) -> () { c_comment!(("TODO: unordered (x is nan, etc)")); } #[no_mangle] -pub unsafe extern "C" fn fpu_fucom(mut r: i32) -> () { +pub unsafe fn fpu_fucom(mut r: i32) -> () { c_comment!(("TODO")); fpu_fcom(fpu_get_sti(r)); } #[no_mangle] -pub unsafe extern "C" fn fpu_fucomi(mut r: i32) -> () { +pub unsafe fn fpu_fucomi(mut r: i32) -> () { c_comment!(("TODO")); fpu_fcomi(r); } #[no_mangle] -pub unsafe extern "C" fn fpu_fucomip(mut r: i32) -> () { +pub unsafe fn fpu_fucomip(mut r: i32) -> () { fpu_fucomi(r); fpu_pop(); } #[no_mangle] -pub unsafe extern "C" fn fpu_fucomp(mut r: i32) -> () { +pub unsafe fn fpu_fucomp(mut r: i32) -> () { fpu_fucom(r); fpu_pop(); } #[no_mangle] -pub unsafe extern "C" fn fpu_fucompp() -> () { +pub unsafe fn fpu_fucompp() -> () { fpu_fucom(1i32); fpu_pop(); fpu_pop(); } #[no_mangle] -pub unsafe extern "C" fn fpu_fxam(mut x: f64) -> () { +pub unsafe fn fpu_fxam(mut x: f64) -> () { *fpu_status_word &= !FPU_RESULT_FLAGS; *fpu_status_word |= fpu_sign(0i32) << 9i32; if 0 != *fpu_stack_empty >> *fpu_stack_ptr & 1i32 { @@ -649,7 +647,7 @@ pub unsafe extern "C" fn fpu_fxam(mut x: f64) -> () { c_comment!(("Unsupported, Denormal")); } #[no_mangle] -pub unsafe extern "C" fn fpu_sign(mut i: i32) -> i32 { +pub unsafe fn fpu_sign(mut i: i32) -> i32 { c_comment!(("sign of a number on the stack")); return *fpu_st8.offset( (((*fpu_stack_ptr).wrapping_add(i as u32) & 7i32 as u32) << 3i32 | 7i32 as u32) as isize, @@ -657,13 +655,13 @@ pub unsafe extern "C" fn fpu_sign(mut i: i32) -> i32 { >> 7i32; } #[no_mangle] -pub unsafe extern "C" fn fpu_fxch(mut i: i32) -> () { +pub unsafe fn fpu_fxch(mut i: i32) -> () { let mut sti: f64 = fpu_get_sti(i); *fpu_st.offset((*fpu_stack_ptr).wrapping_add(i as u32) as isize) = fpu_get_st0(); *fpu_st.offset(*fpu_stack_ptr as isize) = sti; } #[no_mangle] -pub unsafe extern "C" fn fpu_fxtract() -> () { +pub unsafe fn fpu_fxtract() -> () { let mut double_int_view: f64_int = f64_int { f64_0: fpu_get_st0(), }; @@ -676,7 +674,7 @@ pub unsafe extern "C" fn fpu_fxtract() -> () { fpu_push(double_int_view.f64_0); } #[no_mangle] -pub unsafe extern "C" fn fwait() -> () { +pub unsafe fn fwait() -> () { c_comment!(("NOP unless FPU instructions run in parallel with CPU instructions")); } #[no_mangle] diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index 6bc51ecb..96e62647 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -52,84 +52,84 @@ use cpu2::misc_instr::{pop16, pop32s, push16, push32}; use cpu2::string::*; #[no_mangle] -pub unsafe extern "C" fn instr_00_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_00_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE8!(___, addr, add8(___, read_reg8(r))); } #[no_mangle] -pub unsafe extern "C" fn instr_00_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_00_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, add8(____0, read_reg8(r))); } #[no_mangle] -pub unsafe extern "C" fn instr16_01_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_01_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE16!(___, addr, add16(___, read_reg16(r))); } #[no_mangle] -pub unsafe extern "C" fn instr16_01_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_01_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, add16(____0, read_reg16(r))); } #[no_mangle] -pub unsafe extern "C" fn instr32_01_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_01_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE32!(___, addr, add32(___, read_reg32(r))); } #[no_mangle] -pub unsafe extern "C" fn instr32_01_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_01_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, add32(____0, read_reg32(r))); } #[no_mangle] -pub unsafe extern "C" fn instr_02_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_02_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, add8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr_02_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_02_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r, add8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_03_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_03_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, add16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_03_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_03_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r, add16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_03_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_03_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, add32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_03_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_03_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r, add32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr_04(mut imm8: i32) -> () { +pub unsafe fn instr_04(mut imm8: i32) -> () { *reg8.offset(AL as isize) = add8(*reg8.offset(AL as isize) as i32, imm8) as u8; } #[no_mangle] -pub unsafe extern "C" fn instr16_05(mut imm16: i32) -> () { +pub unsafe fn instr16_05(mut imm16: i32) -> () { *reg16.offset(AX as isize) = add16(*reg16.offset(AX as isize) as i32, imm16) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_05(mut imm32: i32) -> () { +pub unsafe fn instr32_05(mut imm32: i32) -> () { *reg32s.offset(EAX as isize) = add32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] -pub unsafe extern "C" fn instr16_06() -> () { +pub unsafe fn instr16_06() -> () { return_on_pagefault!(push16(*sreg.offset(ES as isize) as i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_06() -> () { +pub unsafe fn instr32_06() -> () { return_on_pagefault!(push32(*sreg.offset(ES as isize) as i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_07() -> () { +pub unsafe fn instr16_07() -> () { if !switch_seg( ES, return_on_pagefault!(safe_read16(get_stack_pointer(0i32))), @@ -142,7 +142,7 @@ pub unsafe extern "C" fn instr16_07() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr32_07() -> () { +pub unsafe fn instr32_07() -> () { if !switch_seg( ES, return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))) & 65535i32, @@ -155,169 +155,165 @@ pub unsafe extern "C" fn instr32_07() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_08_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_08_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE8!(___, addr, or8(___, read_reg8(r))); } #[no_mangle] -pub unsafe extern "C" fn instr_08_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_08_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, or8(____0, read_reg8(r))); } #[no_mangle] -pub unsafe extern "C" fn instr16_09_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_09_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE16!(___, addr, or16(___, read_reg16(r))); } #[no_mangle] -pub unsafe extern "C" fn instr16_09_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_09_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, or16(____0, read_reg16(r))); } #[no_mangle] -pub unsafe extern "C" fn instr32_09_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_09_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE32!(___, addr, or32(___, read_reg32(r))); } #[no_mangle] -pub unsafe extern "C" fn instr32_09_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_09_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, or32(____0, read_reg32(r))); } #[no_mangle] -pub unsafe extern "C" fn instr_0A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0A_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, or8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr_0A_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_0A_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r, or8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_0B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0B_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, or16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_0B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0B_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r, or16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_0B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0B_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, or32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_0B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0B_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r, or32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr_0C(mut imm8: i32) -> () { +pub unsafe fn instr_0C(mut imm8: i32) -> () { *reg8.offset(AL as isize) = or8(*reg8.offset(AL as isize) as i32, imm8) as u8; } #[no_mangle] -pub unsafe extern "C" fn instr16_0D(mut imm16: i32) -> () { +pub unsafe fn instr16_0D(mut imm16: i32) -> () { *reg16.offset(AX as isize) = or16(*reg16.offset(AX as isize) as i32, imm16) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_0D(mut imm32: i32) -> () { +pub unsafe fn instr32_0D(mut imm32: i32) -> () { *reg32s.offset(EAX as isize) = or32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] -pub unsafe extern "C" fn instr16_0E() -> () { +pub unsafe fn instr16_0E() -> () { return_on_pagefault!(push16(*sreg.offset(CS as isize) as i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_0E() -> () { +pub unsafe fn instr32_0E() -> () { return_on_pagefault!(push32(*sreg.offset(CS as isize) as i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F() -> () { - run_instruction0f_16(return_on_pagefault!(read_imm8())); -} +pub unsafe fn instr16_0F() -> () { run_instruction0f_16(return_on_pagefault!(read_imm8())); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F() -> () { - run_instruction0f_32(return_on_pagefault!(read_imm8())); -} +pub unsafe fn instr32_0F() -> () { run_instruction0f_32(return_on_pagefault!(read_imm8())); } #[no_mangle] -pub unsafe extern "C" fn instr_10_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_10_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE8!(___, addr, adc8(___, read_reg8(r))); } #[no_mangle] -pub unsafe extern "C" fn instr_10_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_10_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, adc8(____0, read_reg8(r))); } #[no_mangle] -pub unsafe extern "C" fn instr16_11_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_11_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE16!(___, addr, adc16(___, read_reg16(r))); } #[no_mangle] -pub unsafe extern "C" fn instr16_11_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_11_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, adc16(____0, read_reg16(r))); } #[no_mangle] -pub unsafe extern "C" fn instr32_11_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_11_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE32!(___, addr, adc32(___, read_reg32(r))); } #[no_mangle] -pub unsafe extern "C" fn instr32_11_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_11_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, adc32(____0, read_reg32(r))); } #[no_mangle] -pub unsafe extern "C" fn instr_12_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_12_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, adc8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr_12_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_12_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r, adc8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_13_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_13_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, adc16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_13_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_13_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r, adc16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_13_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_13_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, adc32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_13_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_13_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r, adc32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr_14(mut imm8: i32) -> () { +pub unsafe fn instr_14(mut imm8: i32) -> () { *reg8.offset(AL as isize) = adc8(*reg8.offset(AL as isize) as i32, imm8) as u8; } #[no_mangle] -pub unsafe extern "C" fn instr16_15(mut imm16: i32) -> () { +pub unsafe fn instr16_15(mut imm16: i32) -> () { *reg16.offset(AX as isize) = adc16(*reg16.offset(AX as isize) as i32, imm16) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_15(mut imm32: i32) -> () { +pub unsafe fn instr32_15(mut imm32: i32) -> () { *reg32s.offset(EAX as isize) = adc32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] -pub unsafe extern "C" fn instr16_16() -> () { +pub unsafe fn instr16_16() -> () { return_on_pagefault!(push16(*sreg.offset(SS as isize) as i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_16() -> () { +pub unsafe fn instr32_16() -> () { return_on_pagefault!(push32(*sreg.offset(SS as isize) as i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_17() -> () { +pub unsafe fn instr16_17() -> () { if !switch_seg( SS, return_on_pagefault!(safe_read16(get_stack_pointer(0i32))), @@ -330,7 +326,7 @@ pub unsafe extern "C" fn instr16_17() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr32_17() -> () { +pub unsafe fn instr32_17() -> () { if !switch_seg( SS, return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))) & 65535i32, @@ -343,84 +339,84 @@ pub unsafe extern "C" fn instr32_17() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_18_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_18_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE8!(___, addr, sbb8(___, read_reg8(r))); } #[no_mangle] -pub unsafe extern "C" fn instr_18_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_18_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, sbb8(____0, read_reg8(r))); } #[no_mangle] -pub unsafe extern "C" fn instr16_19_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_19_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE16!(___, addr, sbb16(___, read_reg16(r))); } #[no_mangle] -pub unsafe extern "C" fn instr16_19_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_19_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, sbb16(____0, read_reg16(r))); } #[no_mangle] -pub unsafe extern "C" fn instr32_19_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_19_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE32!(___, addr, sbb32(___, read_reg32(r))); } #[no_mangle] -pub unsafe extern "C" fn instr32_19_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_19_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, sbb32(____0, read_reg32(r))); } #[no_mangle] -pub unsafe extern "C" fn instr_1A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_1A_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, sbb8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr_1A_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_1A_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r, sbb8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_1B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_1B_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, sbb16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_1B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_1B_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r, sbb16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_1B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_1B_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, sbb32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_1B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_1B_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r, sbb32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr_1C(mut imm8: i32) -> () { +pub unsafe fn instr_1C(mut imm8: i32) -> () { *reg8.offset(AL as isize) = sbb8(*reg8.offset(AL as isize) as i32, imm8) as u8; } #[no_mangle] -pub unsafe extern "C" fn instr16_1D(mut imm16: i32) -> () { +pub unsafe fn instr16_1D(mut imm16: i32) -> () { *reg16.offset(AX as isize) = sbb16(*reg16.offset(AX as isize) as i32, imm16) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_1D(mut imm32: i32) -> () { +pub unsafe fn instr32_1D(mut imm32: i32) -> () { *reg32s.offset(EAX as isize) = sbb32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] -pub unsafe extern "C" fn instr16_1E() -> () { +pub unsafe fn instr16_1E() -> () { return_on_pagefault!(push16(*sreg.offset(DS as isize) as i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_1E() -> () { +pub unsafe fn instr32_1E() -> () { return_on_pagefault!(push32(*sreg.offset(DS as isize) as i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_1F() -> () { +pub unsafe fn instr16_1F() -> () { if !switch_seg( DS, return_on_pagefault!(safe_read16(get_stack_pointer(0i32))), @@ -433,7 +429,7 @@ pub unsafe extern "C" fn instr16_1F() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr32_1F() -> () { +pub unsafe fn instr32_1F() -> () { if !switch_seg( DS, return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))) & 65535i32, @@ -446,426 +442,420 @@ pub unsafe extern "C" fn instr32_1F() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_20_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_20_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE8!(___, addr, and8(___, read_reg8(r))); } #[no_mangle] -pub unsafe extern "C" fn instr_20_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_20_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, and8(____0, read_reg8(r))); } #[no_mangle] -pub unsafe extern "C" fn instr16_21_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_21_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE16!(___, addr, and16(___, read_reg16(r))); } #[no_mangle] -pub unsafe extern "C" fn instr16_21_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_21_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, and16(____0, read_reg16(r))); } #[no_mangle] -pub unsafe extern "C" fn instr32_21_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_21_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE32!(___, addr, and32(___, read_reg32(r))); } #[no_mangle] -pub unsafe extern "C" fn instr32_21_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_21_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, and32(____0, read_reg32(r))); } #[no_mangle] -pub unsafe extern "C" fn instr_22_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_22_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, and8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr_22_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_22_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r, and8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_23_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_23_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, and16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_23_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_23_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r, and16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_23_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_23_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, and32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_23_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_23_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r, and32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr_24(mut imm8: i32) -> () { +pub unsafe fn instr_24(mut imm8: i32) -> () { *reg8.offset(AL as isize) = and8(*reg8.offset(AL as isize) as i32, imm8) as u8; } #[no_mangle] -pub unsafe extern "C" fn instr16_25(mut imm16: i32) -> () { +pub unsafe fn instr16_25(mut imm16: i32) -> () { *reg16.offset(AX as isize) = and16(*reg16.offset(AX as isize) as i32, imm16) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_25(mut imm32: i32) -> () { +pub unsafe fn instr32_25(mut imm32: i32) -> () { *reg32s.offset(EAX as isize) = and32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] -pub unsafe extern "C" fn instr_26() -> () { segment_prefix_op(ES); } +pub unsafe fn instr_26() -> () { segment_prefix_op(ES); } #[no_mangle] -pub unsafe extern "C" fn instr_27() -> () { bcd_daa(); } +pub unsafe fn instr_27() -> () { bcd_daa(); } #[no_mangle] -pub unsafe extern "C" fn instr_28_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_28_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE8!(___, addr, sub8(___, read_reg8(r))); } #[no_mangle] -pub unsafe extern "C" fn instr_28_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_28_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, sub8(____0, read_reg8(r))); } #[no_mangle] -pub unsafe extern "C" fn instr16_29_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_29_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE16!(___, addr, sub16(___, read_reg16(r))); } #[no_mangle] -pub unsafe extern "C" fn instr16_29_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_29_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, sub16(____0, read_reg16(r))); } #[no_mangle] -pub unsafe extern "C" fn instr32_29_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_29_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE32!(___, addr, sub32(___, read_reg32(r))); } #[no_mangle] -pub unsafe extern "C" fn instr32_29_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_29_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, sub32(____0, read_reg32(r))); } #[no_mangle] -pub unsafe extern "C" fn instr_2A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_2A_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, sub8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr_2A_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_2A_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r, sub8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_2B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_2B_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, sub16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_2B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_2B_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r, sub16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_2B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_2B_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, sub32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_2B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_2B_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r, sub32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr_2C(mut imm8: i32) -> () { +pub unsafe fn instr_2C(mut imm8: i32) -> () { *reg8.offset(AL as isize) = sub8(*reg8.offset(AL as isize) as i32, imm8) as u8; } #[no_mangle] -pub unsafe extern "C" fn instr16_2D(mut imm16: i32) -> () { +pub unsafe fn instr16_2D(mut imm16: i32) -> () { *reg16.offset(AX as isize) = sub16(*reg16.offset(AX as isize) as i32, imm16) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_2D(mut imm32: i32) -> () { +pub unsafe fn instr32_2D(mut imm32: i32) -> () { *reg32s.offset(EAX as isize) = sub32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] -pub unsafe extern "C" fn instr_2E() -> () { segment_prefix_op(CS); } +pub unsafe fn instr_2E() -> () { segment_prefix_op(CS); } #[no_mangle] -pub unsafe extern "C" fn instr_2F() -> () { bcd_das(); } +pub unsafe fn instr_2F() -> () { bcd_das(); } #[no_mangle] -pub unsafe extern "C" fn instr_30_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_30_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE8!(___, addr, xor8(___, read_reg8(r))); } #[no_mangle] -pub unsafe extern "C" fn instr_30_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_30_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, xor8(____0, read_reg8(r))); } #[no_mangle] -pub unsafe extern "C" fn instr16_31_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_31_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE16!(___, addr, xor16(___, read_reg16(r))); } #[no_mangle] -pub unsafe extern "C" fn instr16_31_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_31_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, xor16(____0, read_reg16(r))); } #[no_mangle] -pub unsafe extern "C" fn instr32_31_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_31_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE32!(___, addr, xor32(___, read_reg32(r))); } #[no_mangle] -pub unsafe extern "C" fn instr32_31_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_31_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, xor32(____0, read_reg32(r))); } #[no_mangle] -pub unsafe extern "C" fn instr_32_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_32_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, xor8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr_32_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_32_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r, xor8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_33_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_33_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, xor16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_33_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_33_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r, xor16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_33_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_33_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, xor32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_33_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_33_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r, xor32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr_34(mut imm8: i32) -> () { +pub unsafe fn instr_34(mut imm8: i32) -> () { *reg8.offset(AL as isize) = xor8(*reg8.offset(AL as isize) as i32, imm8) as u8; } #[no_mangle] -pub unsafe extern "C" fn instr16_35(mut imm16: i32) -> () { +pub unsafe fn instr16_35(mut imm16: i32) -> () { *reg16.offset(AX as isize) = xor16(*reg16.offset(AX as isize) as i32, imm16) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_35(mut imm32: i32) -> () { +pub unsafe fn instr32_35(mut imm32: i32) -> () { *reg32s.offset(EAX as isize) = xor32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] -pub unsafe extern "C" fn instr_36() -> () { segment_prefix_op(SS); } +pub unsafe fn instr_36() -> () { segment_prefix_op(SS); } #[no_mangle] -pub unsafe extern "C" fn instr_37() -> () { bcd_aaa(); } +pub unsafe fn instr_37() -> () { bcd_aaa(); } #[no_mangle] -pub unsafe extern "C" fn instr_38_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_38_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); cmp8(____0, read_reg8(r)); } #[no_mangle] -pub unsafe extern "C" fn instr_38_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_38_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); cmp8(____0, read_reg8(r)); } #[no_mangle] -pub unsafe extern "C" fn instr16_39_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_39_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmp16(____0, read_reg16(r)); } #[no_mangle] -pub unsafe extern "C" fn instr16_39_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_39_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); cmp16(____0, read_reg16(r)); } #[no_mangle] -pub unsafe extern "C" fn instr32_39_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_39_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmp32(____0, read_reg32(r)); } #[no_mangle] -pub unsafe extern "C" fn instr32_39_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_39_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); cmp32(____0, read_reg32(r)); } #[no_mangle] -pub unsafe extern "C" fn instr_3A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_3A_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); cmp8(read_reg8(r), ____0); } #[no_mangle] -pub unsafe extern "C" fn instr_3A_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_3A_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); cmp8(read_reg8(r), ____0); } #[no_mangle] -pub unsafe extern "C" fn instr16_3B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_3B_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmp16(read_reg16(r), ____0); } #[no_mangle] -pub unsafe extern "C" fn instr16_3B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_3B_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); cmp16(read_reg16(r), ____0); } #[no_mangle] -pub unsafe extern "C" fn instr32_3B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_3B_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmp32(read_reg32(r), ____0); } #[no_mangle] -pub unsafe extern "C" fn instr32_3B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_3B_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); cmp32(read_reg32(r), ____0); } #[no_mangle] -pub unsafe extern "C" fn instr_3C(mut imm8: i32) -> () { - cmp8(*reg8.offset(AL as isize) as i32, imm8); -} +pub unsafe fn instr_3C(mut imm8: i32) -> () { cmp8(*reg8.offset(AL as isize) as i32, imm8); } #[no_mangle] -pub unsafe extern "C" fn instr16_3D(mut imm16: i32) -> () { - cmp16(*reg16.offset(AX as isize) as i32, imm16); -} +pub unsafe fn instr16_3D(mut imm16: i32) -> () { cmp16(*reg16.offset(AX as isize) as i32, imm16); } #[no_mangle] -pub unsafe extern "C" fn instr32_3D(mut imm32: i32) -> () { - cmp32(*reg32s.offset(EAX as isize), imm32); -} +pub unsafe fn instr32_3D(mut imm32: i32) -> () { cmp32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] -pub unsafe extern "C" fn instr_3E() -> () { segment_prefix_op(DS); } +pub unsafe fn instr_3E() -> () { segment_prefix_op(DS); } #[no_mangle] -pub unsafe extern "C" fn instr_3F() -> () { bcd_aas(); } +pub unsafe fn instr_3F() -> () { bcd_aas(); } #[no_mangle] -pub unsafe extern "C" fn instr16_40() -> () { +pub unsafe fn instr16_40() -> () { *reg16.offset(AX as isize) = inc16(*reg16.offset(AX as isize) as i32) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_40() -> () { +pub unsafe fn instr32_40() -> () { *reg32s.offset(EAX as isize) = inc32(*reg32s.offset(EAX as isize)); } #[no_mangle] -pub unsafe extern "C" fn instr16_41() -> () { +pub unsafe fn instr16_41() -> () { *reg16.offset(CX as isize) = inc16(*reg16.offset(CX as isize) as i32) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_41() -> () { +pub unsafe fn instr32_41() -> () { *reg32s.offset(ECX as isize) = inc32(*reg32s.offset(ECX as isize)); } #[no_mangle] -pub unsafe extern "C" fn instr16_42() -> () { +pub unsafe fn instr16_42() -> () { *reg16.offset(DX as isize) = inc16(*reg16.offset(DX as isize) as i32) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_42() -> () { +pub unsafe fn instr32_42() -> () { *reg32s.offset(EDX as isize) = inc32(*reg32s.offset(EDX as isize)); } #[no_mangle] -pub unsafe extern "C" fn instr16_43() -> () { +pub unsafe fn instr16_43() -> () { *reg16.offset(BX as isize) = inc16(*reg16.offset(BX as isize) as i32) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_43() -> () { +pub unsafe fn instr32_43() -> () { *reg32s.offset(EBX as isize) = inc32(*reg32s.offset(EBX as isize)); } #[no_mangle] -pub unsafe extern "C" fn instr16_44() -> () { +pub unsafe fn instr16_44() -> () { *reg16.offset(SP as isize) = inc16(*reg16.offset(SP as isize) as i32) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_44() -> () { +pub unsafe fn instr32_44() -> () { *reg32s.offset(ESP as isize) = inc32(*reg32s.offset(ESP as isize)); } #[no_mangle] -pub unsafe extern "C" fn instr16_45() -> () { +pub unsafe fn instr16_45() -> () { *reg16.offset(BP as isize) = inc16(*reg16.offset(BP as isize) as i32) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_45() -> () { +pub unsafe fn instr32_45() -> () { *reg32s.offset(EBP as isize) = inc32(*reg32s.offset(EBP as isize)); } #[no_mangle] -pub unsafe extern "C" fn instr16_46() -> () { +pub unsafe fn instr16_46() -> () { *reg16.offset(SI as isize) = inc16(*reg16.offset(SI as isize) as i32) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_46() -> () { +pub unsafe fn instr32_46() -> () { *reg32s.offset(ESI as isize) = inc32(*reg32s.offset(ESI as isize)); } #[no_mangle] -pub unsafe extern "C" fn instr16_47() -> () { +pub unsafe fn instr16_47() -> () { *reg16.offset(DI as isize) = inc16(*reg16.offset(DI as isize) as i32) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_47() -> () { +pub unsafe fn instr32_47() -> () { *reg32s.offset(EDI as isize) = inc32(*reg32s.offset(EDI as isize)); } #[no_mangle] -pub unsafe extern "C" fn instr16_48() -> () { +pub unsafe fn instr16_48() -> () { *reg16.offset(AX as isize) = dec16(*reg16.offset(AX as isize) as i32) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_48() -> () { +pub unsafe fn instr32_48() -> () { *reg32s.offset(EAX as isize) = dec32(*reg32s.offset(EAX as isize)); } #[no_mangle] -pub unsafe extern "C" fn instr16_49() -> () { +pub unsafe fn instr16_49() -> () { *reg16.offset(CX as isize) = dec16(*reg16.offset(CX as isize) as i32) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_49() -> () { +pub unsafe fn instr32_49() -> () { *reg32s.offset(ECX as isize) = dec32(*reg32s.offset(ECX as isize)); } #[no_mangle] -pub unsafe extern "C" fn instr16_4A() -> () { +pub unsafe fn instr16_4A() -> () { *reg16.offset(DX as isize) = dec16(*reg16.offset(DX as isize) as i32) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_4A() -> () { +pub unsafe fn instr32_4A() -> () { *reg32s.offset(EDX as isize) = dec32(*reg32s.offset(EDX as isize)); } #[no_mangle] -pub unsafe extern "C" fn instr16_4B() -> () { +pub unsafe fn instr16_4B() -> () { *reg16.offset(BX as isize) = dec16(*reg16.offset(BX as isize) as i32) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_4B() -> () { +pub unsafe fn instr32_4B() -> () { *reg32s.offset(EBX as isize) = dec32(*reg32s.offset(EBX as isize)); } #[no_mangle] -pub unsafe extern "C" fn instr16_4C() -> () { +pub unsafe fn instr16_4C() -> () { *reg16.offset(SP as isize) = dec16(*reg16.offset(SP as isize) as i32) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_4C() -> () { +pub unsafe fn instr32_4C() -> () { *reg32s.offset(ESP as isize) = dec32(*reg32s.offset(ESP as isize)); } #[no_mangle] -pub unsafe extern "C" fn instr16_4D() -> () { +pub unsafe fn instr16_4D() -> () { *reg16.offset(BP as isize) = dec16(*reg16.offset(BP as isize) as i32) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_4D() -> () { +pub unsafe fn instr32_4D() -> () { *reg32s.offset(EBP as isize) = dec32(*reg32s.offset(EBP as isize)); } #[no_mangle] -pub unsafe extern "C" fn instr16_4E() -> () { +pub unsafe fn instr16_4E() -> () { *reg16.offset(SI as isize) = dec16(*reg16.offset(SI as isize) as i32) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_4E() -> () { +pub unsafe fn instr32_4E() -> () { *reg32s.offset(ESI as isize) = dec32(*reg32s.offset(ESI as isize)); } #[no_mangle] -pub unsafe extern "C" fn instr16_4F() -> () { +pub unsafe fn instr16_4F() -> () { *reg16.offset(DI as isize) = dec16(*reg16.offset(DI as isize) as i32) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_4F() -> () { +pub unsafe fn instr32_4F() -> () { *reg32s.offset(EDI as isize) = dec32(*reg32s.offset(EDI as isize)); } @@ -877,142 +867,128 @@ pub unsafe fn push32_reg(r: i32) { } #[no_mangle] -pub unsafe extern "C" fn instr16_50() -> () { push16_reg(AX) } +pub unsafe fn instr16_50() -> () { push16_reg(AX) } #[no_mangle] -pub unsafe extern "C" fn instr32_50() -> () { push32_reg(EAX) } +pub unsafe fn instr32_50() -> () { push32_reg(EAX) } #[no_mangle] -pub unsafe extern "C" fn instr16_51() -> () { push16_reg(CX) } +pub unsafe fn instr16_51() -> () { push16_reg(CX) } #[no_mangle] -pub unsafe extern "C" fn instr32_51() -> () { push32_reg(ECX) } +pub unsafe fn instr32_51() -> () { push32_reg(ECX) } #[no_mangle] -pub unsafe extern "C" fn instr16_52() -> () { push16_reg(DX) } +pub unsafe fn instr16_52() -> () { push16_reg(DX) } #[no_mangle] -pub unsafe extern "C" fn instr32_52() -> () { push32_reg(EDX) } +pub unsafe fn instr32_52() -> () { push32_reg(EDX) } #[no_mangle] -pub unsafe extern "C" fn instr16_53() -> () { push16_reg(BX) } +pub unsafe fn instr16_53() -> () { push16_reg(BX) } #[no_mangle] -pub unsafe extern "C" fn instr32_53() -> () { push32_reg(EBX) } +pub unsafe fn instr32_53() -> () { push32_reg(EBX) } #[no_mangle] -pub unsafe extern "C" fn instr16_54() -> () { push16_reg(SP) } +pub unsafe fn instr16_54() -> () { push16_reg(SP) } #[no_mangle] -pub unsafe extern "C" fn instr32_54() -> () { push32_reg(ESP) } +pub unsafe fn instr32_54() -> () { push32_reg(ESP) } #[no_mangle] -pub unsafe extern "C" fn instr16_55() -> () { push16_reg(BP) } +pub unsafe fn instr16_55() -> () { push16_reg(BP) } #[no_mangle] -pub unsafe extern "C" fn instr32_55() -> () { push32_reg(EBP) } +pub unsafe fn instr32_55() -> () { push32_reg(EBP) } #[no_mangle] -pub unsafe extern "C" fn instr16_56() -> () { push16_reg(SI) } +pub unsafe fn instr16_56() -> () { push16_reg(SI) } #[no_mangle] -pub unsafe extern "C" fn instr32_56() -> () { push32_reg(ESI) } +pub unsafe fn instr32_56() -> () { push32_reg(ESI) } #[no_mangle] -pub unsafe extern "C" fn instr16_57() -> () { push16_reg(DI) } +pub unsafe fn instr16_57() -> () { push16_reg(DI) } #[no_mangle] -pub unsafe extern "C" fn instr32_57() -> () { push32_reg(EDI) } +pub unsafe fn instr32_57() -> () { push32_reg(EDI) } #[no_mangle] -pub unsafe extern "C" fn instr16_58() -> () { +pub unsafe fn instr16_58() -> () { *reg16.offset(AX as isize) = return_on_pagefault!(pop16()) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_58() -> () { - *reg32s.offset(EAX as isize) = return_on_pagefault!(pop32s()); -} +pub unsafe fn instr32_58() -> () { *reg32s.offset(EAX as isize) = return_on_pagefault!(pop32s()); } #[no_mangle] -pub unsafe extern "C" fn instr16_59() -> () { +pub unsafe fn instr16_59() -> () { *reg16.offset(CX as isize) = return_on_pagefault!(pop16()) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_59() -> () { - *reg32s.offset(ECX as isize) = return_on_pagefault!(pop32s()); -} +pub unsafe fn instr32_59() -> () { *reg32s.offset(ECX as isize) = return_on_pagefault!(pop32s()); } #[no_mangle] -pub unsafe extern "C" fn instr16_5A() -> () { +pub unsafe fn instr16_5A() -> () { *reg16.offset(DX as isize) = return_on_pagefault!(pop16()) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_5A() -> () { - *reg32s.offset(EDX as isize) = return_on_pagefault!(pop32s()); -} +pub unsafe fn instr32_5A() -> () { *reg32s.offset(EDX as isize) = return_on_pagefault!(pop32s()); } #[no_mangle] -pub unsafe extern "C" fn instr16_5B() -> () { +pub unsafe fn instr16_5B() -> () { *reg16.offset(BX as isize) = return_on_pagefault!(pop16()) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_5B() -> () { - *reg32s.offset(EBX as isize) = return_on_pagefault!(pop32s()); -} +pub unsafe fn instr32_5B() -> () { *reg32s.offset(EBX as isize) = return_on_pagefault!(pop32s()); } #[no_mangle] -pub unsafe extern "C" fn instr16_5C() -> () { +pub unsafe fn instr16_5C() -> () { *reg16.offset(SP as isize) = return_on_pagefault!(safe_read16(get_stack_pointer(0i32))) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_5C() -> () { +pub unsafe fn instr32_5C() -> () { *reg32s.offset(ESP as isize) = return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))); } #[no_mangle] -pub unsafe extern "C" fn instr16_5D() -> () { +pub unsafe fn instr16_5D() -> () { *reg16.offset(BP as isize) = return_on_pagefault!(pop16()) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_5D() -> () { - *reg32s.offset(EBP as isize) = return_on_pagefault!(pop32s()); -} +pub unsafe fn instr32_5D() -> () { *reg32s.offset(EBP as isize) = return_on_pagefault!(pop32s()); } #[no_mangle] -pub unsafe extern "C" fn instr16_5E() -> () { +pub unsafe fn instr16_5E() -> () { *reg16.offset(SI as isize) = return_on_pagefault!(pop16()) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_5E() -> () { - *reg32s.offset(ESI as isize) = return_on_pagefault!(pop32s()); -} +pub unsafe fn instr32_5E() -> () { *reg32s.offset(ESI as isize) = return_on_pagefault!(pop32s()); } #[no_mangle] -pub unsafe extern "C" fn instr16_5F() -> () { +pub unsafe fn instr16_5F() -> () { *reg16.offset(DI as isize) = return_on_pagefault!(pop16()) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_5F() -> () { - *reg32s.offset(EDI as isize) = return_on_pagefault!(pop32s()); -} +pub unsafe fn instr32_5F() -> () { *reg32s.offset(EDI as isize) = return_on_pagefault!(pop32s()); } #[no_mangle] -pub unsafe extern "C" fn instr16_60() -> () { pusha16(); } +pub unsafe fn instr16_60() -> () { pusha16(); } #[no_mangle] -pub unsafe extern "C" fn instr32_60() -> () { pusha32(); } +pub unsafe fn instr32_60() -> () { pusha32(); } #[no_mangle] -pub unsafe extern "C" fn instr16_61() -> () { popa16(); } +pub unsafe fn instr16_61() -> () { popa16(); } #[no_mangle] -pub unsafe extern "C" fn instr32_61() -> () { popa32(); } +pub unsafe fn instr32_61() -> () { popa32(); } #[no_mangle] -pub unsafe extern "C" fn instr_62_reg(mut r2: i32, mut r: i32) -> () { +pub unsafe fn instr_62_reg(mut r2: i32, mut r: i32) -> () { c_comment!(("bound")); dbg_log_c!("Unimplemented BOUND instruction"); dbg_assert!(0 != 0i32); } #[no_mangle] -pub unsafe extern "C" fn instr_62_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_62_mem(mut addr: i32, mut r: i32) -> () { dbg_log_c!("Unimplemented BOUND instruction"); dbg_assert!(0 != 0i32); } #[no_mangle] -pub unsafe extern "C" fn instr_63_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_63_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE16!(___, addr, arpl(___, read_reg16(r))); } #[no_mangle] -pub unsafe extern "C" fn instr_63_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_63_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, arpl(____0, read_reg16(r))); } #[no_mangle] -pub unsafe extern "C" fn instr_64() -> () { segment_prefix_op(FS); } +pub unsafe fn instr_64() -> () { segment_prefix_op(FS); } #[no_mangle] -pub unsafe extern "C" fn instr_65() -> () { segment_prefix_op(GS); } +pub unsafe fn instr_65() -> () { segment_prefix_op(GS); } #[no_mangle] -pub unsafe extern "C" fn instr_66() -> () { +pub unsafe fn instr_66() -> () { c_comment!(("Operand-size override prefix")); *prefixes = (*prefixes as i32 | PREFIX_MASK_OPSIZE) as u8; run_prefix_instruction(); *prefixes = 0i32 as u8; } #[no_mangle] -pub unsafe extern "C" fn instr_67() -> () { +pub unsafe fn instr_67() -> () { c_comment!(("Address-size override prefix")); dbg_assert!(is_asize_32() as i32 == *is_32 as i32); *prefixes = (*prefixes as i32 | PREFIX_MASK_ADDRSIZE) as u8; @@ -1020,15 +996,15 @@ pub unsafe extern "C" fn instr_67() -> () { *prefixes = 0i32 as u8; } #[no_mangle] -pub unsafe extern "C" fn instr16_68(mut imm16: i32) -> () { +pub unsafe fn instr16_68(mut imm16: i32) -> () { return_on_pagefault!(push16(imm16)); } #[no_mangle] -pub unsafe extern "C" fn instr32_68(mut imm32: i32) -> () { +pub unsafe fn instr32_68(mut imm32: i32) -> () { return_on_pagefault!(push32(imm32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_69_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr16_69_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { write_reg16( r, imul_reg16( @@ -1038,30 +1014,30 @@ pub unsafe extern "C" fn instr16_69_mem(mut addr: i32, mut r: i32, mut imm: i32) ); } #[no_mangle] -pub unsafe extern "C" fn instr16_69_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr16_69_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { write_reg16( r, imul_reg16(read_reg16(r1) << 16i32 >> 16i32, imm << 16i32 >> 16i32), ); } #[no_mangle] -pub unsafe extern "C" fn instr32_69_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr32_69_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { write_reg32(r, imul_reg32(return_on_pagefault!(safe_read32s(addr)), imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_69_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr32_69_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { write_reg32(r, imul_reg32(read_reg32(r1), imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_6A(mut imm8: i32) -> () { +pub unsafe fn instr16_6A(mut imm8: i32) -> () { return_on_pagefault!(push16(imm8)); } #[no_mangle] -pub unsafe extern "C" fn instr32_6A(mut imm8: i32) -> () { +pub unsafe fn instr32_6A(mut imm8: i32) -> () { return_on_pagefault!(push32(imm8)); } #[no_mangle] -pub unsafe extern "C" fn instr16_6B_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr16_6B_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { write_reg16( r, imul_reg16( @@ -1071,564 +1047,550 @@ pub unsafe extern "C" fn instr16_6B_mem(mut addr: i32, mut r: i32, mut imm: i32) ); } #[no_mangle] -pub unsafe extern "C" fn instr16_6B_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr16_6B_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { write_reg16(r, imul_reg16(read_reg16(r1) << 16i32 >> 16i32, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_6B_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr32_6B_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { write_reg32(r, imul_reg32(return_on_pagefault!(safe_read32s(addr)), imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_6B_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr32_6B_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { write_reg32(r, imul_reg32(read_reg32(r1), imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_6C() -> () { insb_no_rep(); } +pub unsafe fn instr_6C() -> () { insb_no_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr16_6D() -> () { insw_no_rep(); } +pub unsafe fn instr16_6D() -> () { insw_no_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr32_6D() -> () { insd_no_rep(); } +pub unsafe fn instr32_6D() -> () { insd_no_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr_6E() -> () { outsb_no_rep(); } +pub unsafe fn instr_6E() -> () { outsb_no_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr16_6F() -> () { outsw_no_rep(); } +pub unsafe fn instr16_6F() -> () { outsw_no_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr32_6F() -> () { outsd_no_rep(); } +pub unsafe fn instr32_6F() -> () { outsd_no_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr_80_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_0_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE8!(___, addr, add8(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_80_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_0_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, add8(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_80_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_1_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE8!(___, addr, or8(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_80_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_1_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, or8(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_80_2_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_2_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE8!(___, addr, adc8(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_80_2_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_2_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, adc8(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_80_3_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_3_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE8!(___, addr, sbb8(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_80_3_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_3_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, sbb8(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_80_4_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_4_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE8!(___, addr, and8(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_80_4_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_4_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, and8(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_80_5_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_5_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE8!(___, addr, sub8(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_80_5_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_5_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, sub8(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_80_6_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_6_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE8!(___, addr, xor8(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_80_6_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_6_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, xor8(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_80_7_reg(mut r: i32, mut imm: i32) -> () { cmp8(read_reg8(r), imm); } +pub unsafe fn instr_80_7_reg(mut r: i32, mut imm: i32) -> () { cmp8(read_reg8(r), imm); } #[no_mangle] -pub unsafe extern "C" fn instr_80_7_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_7_mem(mut addr: i32, mut imm: i32) -> () { cmp8(return_on_pagefault!(safe_read8(addr)), imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_81_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_0_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, add16(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_81_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_0_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, add16(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_81_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_1_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, or16(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_81_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_1_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, or16(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_81_2_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_2_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, adc16(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_81_2_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_2_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, adc16(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_81_3_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_3_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, sbb16(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_81_3_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_3_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, sbb16(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_81_4_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_4_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, and16(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_81_4_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_4_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, and16(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_81_5_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_5_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, sub16(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_81_5_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_5_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, sub16(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_81_6_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_6_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, xor16(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_81_6_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_6_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, xor16(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_81_7_reg(mut r: i32, mut imm: i32) -> () { - cmp16(read_reg16(r), imm); -} +pub unsafe fn instr16_81_7_reg(mut r: i32, mut imm: i32) -> () { cmp16(read_reg16(r), imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_81_7_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_7_mem(mut addr: i32, mut imm: i32) -> () { cmp16(return_on_pagefault!(safe_read16(addr)), imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_81_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_0_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, add32(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_81_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_0_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, add32(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_81_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_1_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, or32(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_81_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_1_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, or32(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_81_2_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_2_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, adc32(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_81_2_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_2_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, adc32(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_81_3_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_3_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, sbb32(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_81_3_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_3_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, sbb32(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_81_4_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_4_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, and32(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_81_4_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_4_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, and32(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_81_5_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_5_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, sub32(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_81_5_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_5_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, sub32(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_81_6_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_6_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, xor32(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_81_6_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_6_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, xor32(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_81_7_reg(mut r: i32, mut imm: i32) -> () { - cmp32(read_reg32(r), imm); -} +pub unsafe fn instr32_81_7_reg(mut r: i32, mut imm: i32) -> () { cmp32(read_reg32(r), imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_81_7_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_7_mem(mut addr: i32, mut imm: i32) -> () { cmp32(return_on_pagefault!(safe_read32s(addr)), imm); } #[no_mangle] -pub unsafe extern "C" fn instr_82_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_0_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE8!(___, addr, add8(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_82_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_0_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, add8(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_82_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_1_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE8!(___, addr, or8(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_82_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_1_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, or8(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_82_2_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_2_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE8!(___, addr, adc8(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_82_2_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_2_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, adc8(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_82_3_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_3_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE8!(___, addr, sbb8(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_82_3_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_3_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, sbb8(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_82_4_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_4_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE8!(___, addr, and8(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_82_4_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_4_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, and8(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_82_5_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_5_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE8!(___, addr, sub8(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_82_5_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_5_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, sub8(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_82_6_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_6_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE8!(___, addr, xor8(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_82_6_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_6_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, xor8(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr_82_7_reg(mut r: i32, mut imm: i32) -> () { cmp8(read_reg8(r), imm); } +pub unsafe fn instr_82_7_reg(mut r: i32, mut imm: i32) -> () { cmp8(read_reg8(r), imm); } #[no_mangle] -pub unsafe extern "C" fn instr_82_7_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_7_mem(mut addr: i32, mut imm: i32) -> () { cmp8(return_on_pagefault!(safe_read8(addr)), imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_83_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_0_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, add16(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_83_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_0_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, add16(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_83_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_1_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, or16(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_83_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_1_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, or16(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_83_2_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_2_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, adc16(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_83_2_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_2_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, adc16(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_83_3_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_3_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, sbb16(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_83_3_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_3_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, sbb16(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_83_4_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_4_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, and16(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_83_4_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_4_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, and16(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_83_5_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_5_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, sub16(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_83_5_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_5_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, sub16(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_83_6_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_6_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, xor16(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_83_6_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_6_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, xor16(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_83_7_reg(mut r: i32, mut imm: i32) -> () { - cmp16(read_reg16(r), imm); -} +pub unsafe fn instr16_83_7_reg(mut r: i32, mut imm: i32) -> () { cmp16(read_reg16(r), imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_83_7_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_7_mem(mut addr: i32, mut imm: i32) -> () { cmp16(return_on_pagefault!(safe_read16(addr)), imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_83_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_0_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, add32(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_83_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_0_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, add32(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_83_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_1_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, or32(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_83_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_1_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, or32(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_83_2_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_2_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, adc32(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_83_2_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_2_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, adc32(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_83_3_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_3_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, sbb32(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_83_3_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_3_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, sbb32(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_83_4_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_4_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, and32(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_83_4_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_4_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, and32(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_83_5_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_5_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, sub32(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_83_5_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_5_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, sub32(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_83_6_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_6_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, xor32(___, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_83_6_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_6_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, xor32(____0, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_83_7_reg(mut r: i32, mut imm: i32) -> () { - cmp32(read_reg32(r), imm); -} +pub unsafe fn instr32_83_7_reg(mut r: i32, mut imm: i32) -> () { cmp32(read_reg32(r), imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_83_7_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_7_mem(mut addr: i32, mut imm: i32) -> () { cmp32(return_on_pagefault!(safe_read32s(addr)), imm); } #[no_mangle] -pub unsafe extern "C" fn instr_84_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_84_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); test8(____0, read_reg8(r)); } #[no_mangle] -pub unsafe extern "C" fn instr_84_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_84_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); test8(____0, read_reg8(r)); } #[no_mangle] -pub unsafe extern "C" fn instr16_85_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_85_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); test16(____0, read_reg16(r)); } #[no_mangle] -pub unsafe extern "C" fn instr16_85_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_85_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); test16(____0, read_reg16(r)); } #[no_mangle] -pub unsafe extern "C" fn instr32_85_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_85_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); test32(____0, read_reg32(r)); } #[no_mangle] -pub unsafe extern "C" fn instr32_85_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_85_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); test32(____0, read_reg32(r)); } #[no_mangle] -pub unsafe extern "C" fn instr_86_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_86_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE8!(___, addr, xchg8(___, get_reg8_index(r))); } #[no_mangle] -pub unsafe extern "C" fn instr_86_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_86_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, xchg8(____0, get_reg8_index(r))); } #[no_mangle] -pub unsafe extern "C" fn instr16_87_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_87_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE16!(___, addr, xchg16(___, get_reg16_index(r))); } #[no_mangle] -pub unsafe extern "C" fn instr16_87_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_87_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, xchg16(____0, get_reg16_index(r))); } #[no_mangle] -pub unsafe extern "C" fn instr32_87_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_87_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE32!(___, addr, xchg32(___, r)); } #[no_mangle] -pub unsafe extern "C" fn instr32_87_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_87_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, xchg32(____0, r)); } #[no_mangle] -pub unsafe extern "C" fn instr_88_reg(mut r2: i32, mut r: i32) -> () { - write_reg8(r2, read_reg8(r)); -} +pub unsafe fn instr_88_reg(mut r2: i32, mut r: i32) -> () { write_reg8(r2, read_reg8(r)); } #[no_mangle] -pub unsafe extern "C" fn instr_88_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_88_mem(mut addr: i32, mut r: i32) -> () { return_on_pagefault!(safe_write8(addr, read_reg8(r))); } #[no_mangle] -pub unsafe extern "C" fn instr16_89_reg(mut r2: i32, mut r: i32) -> () { - write_reg16(r2, read_reg16(r)); -} +pub unsafe fn instr16_89_reg(mut r2: i32, mut r: i32) -> () { write_reg16(r2, read_reg16(r)); } #[no_mangle] -pub unsafe extern "C" fn instr16_89_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_89_mem(mut addr: i32, mut r: i32) -> () { return_on_pagefault!(safe_write16(addr, read_reg16(r))); } #[no_mangle] -pub unsafe extern "C" fn instr32_89_reg(mut r2: i32, mut r: i32) -> () { - write_reg32(r2, read_reg32(r)); -} +pub unsafe fn instr32_89_reg(mut r2: i32, mut r: i32) -> () { write_reg32(r2, read_reg32(r)); } #[no_mangle] -pub unsafe extern "C" fn instr32_89_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_89_mem(mut addr: i32, mut r: i32) -> () { return_on_pagefault!(safe_write32(addr, read_reg32(r))); } #[no_mangle] -pub unsafe extern "C" fn instr_8A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_8A_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr_8A_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_8A_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr16_8B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_8B_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr16_8B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_8B_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr32_8B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_8B_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr32_8B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_8B_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr_8C_check_sreg(mut seg: i32) -> bool { +pub unsafe fn instr_8C_check_sreg(mut seg: i32) -> bool { if seg >= 6i32 { dbg_log_c!("mov sreg #ud"); trigger_ud(); @@ -1639,36 +1601,36 @@ pub unsafe extern "C" fn instr_8C_check_sreg(mut seg: i32) -> bool { }; } #[no_mangle] -pub unsafe extern "C" fn instr16_8C_reg(mut r: i32, mut seg: i32) -> () { +pub unsafe fn instr16_8C_reg(mut r: i32, mut seg: i32) -> () { if instr_8C_check_sreg(seg) { write_reg16(r, *sreg.offset(seg as isize) as i32); }; } #[no_mangle] -pub unsafe extern "C" fn instr16_8C_mem(mut addr: i32, mut seg: i32) -> () { +pub unsafe fn instr16_8C_mem(mut addr: i32, mut seg: i32) -> () { if instr_8C_check_sreg(seg) { return_on_pagefault!(safe_write16(addr, *sreg.offset(seg as isize) as i32)); }; } #[no_mangle] -pub unsafe extern "C" fn instr32_8C_reg(mut r: i32, mut seg: i32) -> () { +pub unsafe fn instr32_8C_reg(mut r: i32, mut seg: i32) -> () { if instr_8C_check_sreg(seg) { write_reg32(r, *sreg.offset(seg as isize) as i32); }; } #[no_mangle] -pub unsafe extern "C" fn instr32_8C_mem(mut addr: i32, mut seg: i32) -> () { +pub unsafe fn instr32_8C_mem(mut addr: i32, mut seg: i32) -> () { if instr_8C_check_sreg(seg) { return_on_pagefault!(safe_write32(addr, *sreg.offset(seg as isize) as i32)); }; } #[no_mangle] -pub unsafe extern "C" fn instr16_8D_reg(mut r: i32, mut r2: i32) -> () { +pub unsafe fn instr16_8D_reg(mut r: i32, mut r2: i32) -> () { dbg_log_c!("lea #ud"); trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr16_8D_mem(modrm_byte: i32, mut r: i32) -> () { +pub unsafe fn instr16_8D_mem(modrm_byte: i32, mut r: i32) -> () { c_comment!(("lea")); *prefixes = (*prefixes as i32 | SEG_PREFIX_ZERO) as u8; if let Ok(addr) = modrm_resolve(modrm_byte) { @@ -1677,12 +1639,12 @@ pub unsafe extern "C" fn instr16_8D_mem(modrm_byte: i32, mut r: i32) -> () { *prefixes = 0i32 as u8; } #[no_mangle] -pub unsafe extern "C" fn instr32_8D_reg(mut r: i32, mut r2: i32) -> () { +pub unsafe fn instr32_8D_reg(mut r: i32, mut r2: i32) -> () { dbg_log_c!("lea #ud"); trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr32_8D_mem(modrm_byte: i32, mut r: i32) -> () { +pub unsafe fn instr32_8D_mem(modrm_byte: i32, mut r: i32) -> () { c_comment!(("lea")); c_comment!(("override prefix, so modrm_resolve does not return the segment part")); *prefixes = (*prefixes as i32 | SEG_PREFIX_ZERO) as u8; @@ -1692,7 +1654,7 @@ pub unsafe extern "C" fn instr32_8D_mem(modrm_byte: i32, mut r: i32) -> () { *prefixes = 0i32 as u8; } #[no_mangle] -pub unsafe extern "C" fn instr_8E_helper(mut data: i32, mut mod_0: i32) -> () { +pub unsafe fn instr_8E_helper(mut data: i32, mut mod_0: i32) -> () { if mod_0 == ES || mod_0 == SS || mod_0 == DS || mod_0 == FS || mod_0 == GS { if !switch_seg(mod_0, data) { return; @@ -1704,18 +1666,18 @@ pub unsafe extern "C" fn instr_8E_helper(mut data: i32, mut mod_0: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_8E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_8E_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); instr_8E_helper(____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr_8E_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_8E_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); instr_8E_helper(____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_8F_0_mem(modrm_byte: i32) -> () { +pub unsafe fn instr16_8F_0_mem(modrm_byte: i32) -> () { c_comment!(("pop")); // Update esp *before* resolving the address adjust_stack_reg(2i32); @@ -1742,11 +1704,9 @@ pub unsafe fn instr16_8F_0_mem_jit(addr: i32) -> () { } #[no_mangle] -pub unsafe extern "C" fn instr16_8F_0_reg(mut r: i32) -> () { - write_reg16(r, return_on_pagefault!(pop16())); -} +pub unsafe fn instr16_8F_0_reg(mut r: i32) -> () { write_reg16(r, return_on_pagefault!(pop16())); } #[no_mangle] -pub unsafe extern "C" fn instr32_8F_0_mem(modrm_byte: i32) -> () { +pub unsafe fn instr32_8F_0_mem(modrm_byte: i32) -> () { // Update esp *before* resolving the address adjust_stack_reg(4i32); match modrm_resolve(modrm_byte) { @@ -1772,64 +1732,60 @@ pub unsafe fn instr32_8F_0_mem_jit(addr: i32) -> () { } #[no_mangle] -pub unsafe extern "C" fn instr32_8F_0_reg(mut r: i32) -> () { - write_reg32(r, return_on_pagefault!(pop32s())); -} +pub unsafe fn instr32_8F_0_reg(mut r: i32) -> () { write_reg32(r, return_on_pagefault!(pop32s())); } #[no_mangle] -pub unsafe extern "C" fn instr_90() -> () {} +pub unsafe fn instr_90() -> () {} #[no_mangle] -pub unsafe extern "C" fn instr16_91() -> () { xchg16r(CX); } +pub unsafe fn instr16_91() -> () { xchg16r(CX); } #[no_mangle] -pub unsafe extern "C" fn instr32_91() -> () { xchg32r(ECX); } +pub unsafe fn instr32_91() -> () { xchg32r(ECX); } #[no_mangle] -pub unsafe extern "C" fn instr16_92() -> () { xchg16r(DX); } +pub unsafe fn instr16_92() -> () { xchg16r(DX); } #[no_mangle] -pub unsafe extern "C" fn instr32_92() -> () { xchg32r(EDX); } +pub unsafe fn instr32_92() -> () { xchg32r(EDX); } #[no_mangle] -pub unsafe extern "C" fn instr16_93() -> () { xchg16r(BX); } +pub unsafe fn instr16_93() -> () { xchg16r(BX); } #[no_mangle] -pub unsafe extern "C" fn instr32_93() -> () { xchg32r(EBX); } +pub unsafe fn instr32_93() -> () { xchg32r(EBX); } #[no_mangle] -pub unsafe extern "C" fn instr16_94() -> () { xchg16r(SP); } +pub unsafe fn instr16_94() -> () { xchg16r(SP); } #[no_mangle] -pub unsafe extern "C" fn instr32_94() -> () { xchg32r(ESP); } +pub unsafe fn instr32_94() -> () { xchg32r(ESP); } #[no_mangle] -pub unsafe extern "C" fn instr16_95() -> () { xchg16r(BP); } +pub unsafe fn instr16_95() -> () { xchg16r(BP); } #[no_mangle] -pub unsafe extern "C" fn instr32_95() -> () { xchg32r(EBP); } +pub unsafe fn instr32_95() -> () { xchg32r(EBP); } #[no_mangle] -pub unsafe extern "C" fn instr16_96() -> () { xchg16r(SI); } +pub unsafe fn instr16_96() -> () { xchg16r(SI); } #[no_mangle] -pub unsafe extern "C" fn instr32_96() -> () { xchg32r(ESI); } +pub unsafe fn instr32_96() -> () { xchg32r(ESI); } #[no_mangle] -pub unsafe extern "C" fn instr16_97() -> () { xchg16r(DI); } +pub unsafe fn instr16_97() -> () { xchg16r(DI); } #[no_mangle] -pub unsafe extern "C" fn instr32_97() -> () { xchg32r(EDI); } +pub unsafe fn instr32_97() -> () { xchg32r(EDI); } #[no_mangle] -pub unsafe extern "C" fn instr16_98() -> () { - *reg16.offset(AX as isize) = *reg8s.offset(AL as isize) as u16; -} +pub unsafe fn instr16_98() -> () { *reg16.offset(AX as isize) = *reg8s.offset(AL as isize) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_98() -> () { +pub unsafe fn instr32_98() -> () { *reg32s.offset(EAX as isize) = *reg16s.offset(AX as isize) as i32; } #[no_mangle] -pub unsafe extern "C" fn instr16_99() -> () { +pub unsafe fn instr16_99() -> () { *reg16.offset(DX as isize) = (*reg16s.offset(AX as isize) as i32 >> 15i32) as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_99() -> () { +pub unsafe fn instr32_99() -> () { *reg32s.offset(EDX as isize) = *reg32s.offset(EAX as isize) >> 31i32; } #[no_mangle] -pub unsafe extern "C" fn instr16_9A(mut new_ip: i32, mut new_cs: i32) -> () { +pub unsafe fn instr16_9A(mut new_ip: i32, mut new_cs: i32) -> () { c_comment!(("callf")); far_jump(new_ip, new_cs, true); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe extern "C" fn instr32_9A(mut new_ip: i32, mut new_cs: i32) -> () { +pub unsafe fn instr32_9A(mut new_ip: i32, mut new_cs: i32) -> () { if !*protected_mode || 0 != vm86_mode() as i32 { if 0 != new_ip as u32 & 4294901760u32 { dbg_assert!(0 != 0i32); @@ -1839,7 +1795,7 @@ pub unsafe extern "C" fn instr32_9A(mut new_ip: i32, mut new_cs: i32) -> () { dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe extern "C" fn instr_9B() -> () { +pub unsafe fn instr_9B() -> () { c_comment!(("fwait: check for pending fpu exceptions")); if *cr.offset(0isize) & (CR0_MP | CR0_TS) == CR0_MP | CR0_TS { c_comment!(("Note: Different from task_switch_test")); @@ -1851,7 +1807,7 @@ pub unsafe extern "C" fn instr_9B() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr16_9C() -> () { +pub unsafe fn instr16_9C() -> () { c_comment!(("pushf")); if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { dbg_assert!(*protected_mode); @@ -1863,7 +1819,7 @@ pub unsafe extern "C" fn instr16_9C() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr32_9C() -> () { +pub unsafe fn instr32_9C() -> () { c_comment!(("pushf")); if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { c_comment!(("trap to virtual 8086 monitor")); @@ -1877,7 +1833,7 @@ pub unsafe extern "C" fn instr32_9C() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr16_9D() -> () { +pub unsafe fn instr16_9D() -> () { c_comment!(("popf")); if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { dbg_log_c!("popf #gp"); @@ -1897,7 +1853,7 @@ pub unsafe extern "C" fn instr16_9D() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr32_9D() -> () { +pub unsafe fn instr32_9D() -> () { c_comment!(("popf")); if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { dbg_log_c!("popf #gp"); @@ -1911,7 +1867,7 @@ pub unsafe extern "C" fn instr32_9D() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_9E() -> () { +pub unsafe fn instr_9E() -> () { c_comment!(("sahf")); *flags.offset(0isize) = *flags.offset(0isize) & !255i32 | *reg8.offset(AH as isize) as i32; *flags.offset(0isize) = *flags.offset(0isize) & FLAGS_MASK | FLAGS_DEFAULT; @@ -1919,29 +1875,29 @@ pub unsafe extern "C" fn instr_9E() -> () { *fresh1 &= !255i32; } #[no_mangle] -pub unsafe extern "C" fn instr_9F() -> () { +pub unsafe fn instr_9F() -> () { c_comment!(("lahf")); *reg8.offset(AH as isize) = get_eflags() as u8; } #[no_mangle] -pub unsafe extern "C" fn instr_A0(mut moffs: i32) -> () { +pub unsafe fn instr_A0(mut moffs: i32) -> () { c_comment!(("mov")); let mut data: i32 = return_on_pagefault!(safe_read8(get_seg_prefix_ds(moffs))); *reg8.offset(AL as isize) = data as u8; } #[no_mangle] -pub unsafe extern "C" fn instr16_A1(mut moffs: i32) -> () { +pub unsafe fn instr16_A1(mut moffs: i32) -> () { c_comment!(("mov")); let mut data: i32 = return_on_pagefault!(safe_read16(get_seg_prefix_ds(moffs))); *reg16.offset(AX as isize) = data as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_A1(mut moffs: i32) -> () { +pub unsafe fn instr32_A1(mut moffs: i32) -> () { let mut data: i32 = return_on_pagefault!(safe_read32s(get_seg_prefix_ds(moffs))); *reg32s.offset(EAX as isize) = data; } #[no_mangle] -pub unsafe extern "C" fn instr_A2(mut moffs: i32) -> () { +pub unsafe fn instr_A2(mut moffs: i32) -> () { c_comment!(("mov")); return_on_pagefault!(safe_write8( get_seg_prefix_ds(moffs), @@ -1949,7 +1905,7 @@ pub unsafe extern "C" fn instr_A2(mut moffs: i32) -> () { )); } #[no_mangle] -pub unsafe extern "C" fn instr16_A3(mut moffs: i32) -> () { +pub unsafe fn instr16_A3(mut moffs: i32) -> () { c_comment!(("mov")); return_on_pagefault!(safe_write16( get_seg_prefix_ds(moffs), @@ -1957,320 +1913,314 @@ pub unsafe extern "C" fn instr16_A3(mut moffs: i32) -> () { )); } #[no_mangle] -pub unsafe extern "C" fn instr32_A3(mut moffs: i32) -> () { +pub unsafe fn instr32_A3(mut moffs: i32) -> () { return_on_pagefault!(safe_write32( get_seg_prefix_ds(moffs), *reg32s.offset(EAX as isize) )); } #[no_mangle] -pub unsafe extern "C" fn instr_A4() -> () { movsb_no_rep(); } +pub unsafe fn instr_A4() -> () { movsb_no_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr16_A5() -> () { movsw_no_rep(); } +pub unsafe fn instr16_A5() -> () { movsw_no_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr32_A5() -> () { movsd_no_rep(); } +pub unsafe fn instr32_A5() -> () { movsd_no_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr_A6() -> () { cmpsb_no_rep(); } +pub unsafe fn instr_A6() -> () { cmpsb_no_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr16_A7() -> () { cmpsw_no_rep(); } +pub unsafe fn instr16_A7() -> () { cmpsw_no_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr32_A7() -> () { cmpsd_no_rep(); } +pub unsafe fn instr32_A7() -> () { cmpsd_no_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr_A8(mut imm8: i32) -> () { - test8(*reg8.offset(AL as isize) as i32, imm8); -} +pub unsafe fn instr_A8(mut imm8: i32) -> () { test8(*reg8.offset(AL as isize) as i32, imm8); } #[no_mangle] -pub unsafe extern "C" fn instr16_A9(mut imm16: i32) -> () { - test16(*reg16.offset(AX as isize) as i32, imm16); -} +pub unsafe fn instr16_A9(mut imm16: i32) -> () { test16(*reg16.offset(AX as isize) as i32, imm16); } #[no_mangle] -pub unsafe extern "C" fn instr32_A9(mut imm32: i32) -> () { - test32(*reg32s.offset(EAX as isize), imm32); -} +pub unsafe fn instr32_A9(mut imm32: i32) -> () { test32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] -pub unsafe extern "C" fn instr_AA() -> () { stosb_no_rep(); } +pub unsafe fn instr_AA() -> () { stosb_no_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr16_AB() -> () { stosw_no_rep(); } +pub unsafe fn instr16_AB() -> () { stosw_no_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr32_AB() -> () { stosd_no_rep(); } +pub unsafe fn instr32_AB() -> () { stosd_no_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr_AC() -> () { lodsb_no_rep(); } +pub unsafe fn instr_AC() -> () { lodsb_no_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr16_AD() -> () { lodsw_no_rep(); } +pub unsafe fn instr16_AD() -> () { lodsw_no_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr32_AD() -> () { lodsd_no_rep(); } +pub unsafe fn instr32_AD() -> () { lodsd_no_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr_AE() -> () { scasb_no_rep(); } +pub unsafe fn instr_AE() -> () { scasb_no_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr16_AF() -> () { scasw_no_rep(); } +pub unsafe fn instr16_AF() -> () { scasw_no_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr32_AF() -> () { scasd_no_rep(); } +pub unsafe fn instr32_AF() -> () { scasd_no_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr_B0(mut imm8: i32) -> () { *reg8.offset(AL as isize) = imm8 as u8; } +pub unsafe fn instr_B0(mut imm8: i32) -> () { *reg8.offset(AL as isize) = imm8 as u8; } #[no_mangle] -pub unsafe extern "C" fn instr_B1(mut imm8: i32) -> () { *reg8.offset(CL as isize) = imm8 as u8; } +pub unsafe fn instr_B1(mut imm8: i32) -> () { *reg8.offset(CL as isize) = imm8 as u8; } #[no_mangle] -pub unsafe extern "C" fn instr_B2(mut imm8: i32) -> () { *reg8.offset(DL as isize) = imm8 as u8; } +pub unsafe fn instr_B2(mut imm8: i32) -> () { *reg8.offset(DL as isize) = imm8 as u8; } #[no_mangle] -pub unsafe extern "C" fn instr_B3(mut imm8: i32) -> () { *reg8.offset(BL as isize) = imm8 as u8; } +pub unsafe fn instr_B3(mut imm8: i32) -> () { *reg8.offset(BL as isize) = imm8 as u8; } #[no_mangle] -pub unsafe extern "C" fn instr_B4(mut imm8: i32) -> () { *reg8.offset(AH as isize) = imm8 as u8; } +pub unsafe fn instr_B4(mut imm8: i32) -> () { *reg8.offset(AH as isize) = imm8 as u8; } #[no_mangle] -pub unsafe extern "C" fn instr_B5(mut imm8: i32) -> () { *reg8.offset(CH as isize) = imm8 as u8; } +pub unsafe fn instr_B5(mut imm8: i32) -> () { *reg8.offset(CH as isize) = imm8 as u8; } #[no_mangle] -pub unsafe extern "C" fn instr_B6(mut imm8: i32) -> () { *reg8.offset(DH as isize) = imm8 as u8; } +pub unsafe fn instr_B6(mut imm8: i32) -> () { *reg8.offset(DH as isize) = imm8 as u8; } #[no_mangle] -pub unsafe extern "C" fn instr_B7(mut imm8: i32) -> () { *reg8.offset(BH as isize) = imm8 as u8; } +pub unsafe fn instr_B7(mut imm8: i32) -> () { *reg8.offset(BH as isize) = imm8 as u8; } #[no_mangle] -pub unsafe extern "C" fn instr16_B8(mut imm: i32) -> () { *reg16.offset(AX as isize) = imm as u16; } +pub unsafe fn instr16_B8(mut imm: i32) -> () { *reg16.offset(AX as isize) = imm as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_B8(mut imm: i32) -> () { *reg32s.offset(EAX as isize) = imm; } +pub unsafe fn instr32_B8(mut imm: i32) -> () { *reg32s.offset(EAX as isize) = imm; } #[no_mangle] -pub unsafe extern "C" fn instr16_B9(mut imm: i32) -> () { *reg16.offset(CX as isize) = imm as u16; } +pub unsafe fn instr16_B9(mut imm: i32) -> () { *reg16.offset(CX as isize) = imm as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_B9(mut imm: i32) -> () { *reg32s.offset(ECX as isize) = imm; } +pub unsafe fn instr32_B9(mut imm: i32) -> () { *reg32s.offset(ECX as isize) = imm; } #[no_mangle] -pub unsafe extern "C" fn instr16_BA(mut imm: i32) -> () { *reg16.offset(DX as isize) = imm as u16; } +pub unsafe fn instr16_BA(mut imm: i32) -> () { *reg16.offset(DX as isize) = imm as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_BA(mut imm: i32) -> () { *reg32s.offset(EDX as isize) = imm; } +pub unsafe fn instr32_BA(mut imm: i32) -> () { *reg32s.offset(EDX as isize) = imm; } #[no_mangle] -pub unsafe extern "C" fn instr16_BB(mut imm: i32) -> () { *reg16.offset(BX as isize) = imm as u16; } +pub unsafe fn instr16_BB(mut imm: i32) -> () { *reg16.offset(BX as isize) = imm as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_BB(mut imm: i32) -> () { *reg32s.offset(EBX as isize) = imm; } +pub unsafe fn instr32_BB(mut imm: i32) -> () { *reg32s.offset(EBX as isize) = imm; } #[no_mangle] -pub unsafe extern "C" fn instr16_BC(mut imm: i32) -> () { *reg16.offset(SP as isize) = imm as u16; } +pub unsafe fn instr16_BC(mut imm: i32) -> () { *reg16.offset(SP as isize) = imm as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_BC(mut imm: i32) -> () { *reg32s.offset(ESP as isize) = imm; } +pub unsafe fn instr32_BC(mut imm: i32) -> () { *reg32s.offset(ESP as isize) = imm; } #[no_mangle] -pub unsafe extern "C" fn instr16_BD(mut imm: i32) -> () { *reg16.offset(BP as isize) = imm as u16; } +pub unsafe fn instr16_BD(mut imm: i32) -> () { *reg16.offset(BP as isize) = imm as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_BD(mut imm: i32) -> () { *reg32s.offset(EBP as isize) = imm; } +pub unsafe fn instr32_BD(mut imm: i32) -> () { *reg32s.offset(EBP as isize) = imm; } #[no_mangle] -pub unsafe extern "C" fn instr16_BE(mut imm: i32) -> () { *reg16.offset(SI as isize) = imm as u16; } +pub unsafe fn instr16_BE(mut imm: i32) -> () { *reg16.offset(SI as isize) = imm as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_BE(mut imm: i32) -> () { *reg32s.offset(ESI as isize) = imm; } +pub unsafe fn instr32_BE(mut imm: i32) -> () { *reg32s.offset(ESI as isize) = imm; } #[no_mangle] -pub unsafe extern "C" fn instr16_BF(mut imm: i32) -> () { *reg16.offset(DI as isize) = imm as u16; } +pub unsafe fn instr16_BF(mut imm: i32) -> () { *reg16.offset(DI as isize) = imm as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_BF(mut imm: i32) -> () { *reg32s.offset(EDI as isize) = imm; } +pub unsafe fn instr32_BF(mut imm: i32) -> () { *reg32s.offset(EDI as isize) = imm; } #[no_mangle] -pub unsafe extern "C" fn instr_C0_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_0_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE8!(___, addr, rol8(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_C0_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_0_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, rol8(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_C0_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_1_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE8!(___, addr, ror8(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_C0_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_1_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, ror8(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_C0_2_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_2_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE8!(___, addr, rcl8(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_C0_2_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_2_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, rcl8(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_C0_3_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_3_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE8!(___, addr, rcr8(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_C0_3_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_3_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, rcr8(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_C0_4_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_4_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE8!(___, addr, shl8(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_C0_4_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_4_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, shl8(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_C0_5_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_5_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE8!(___, addr, shr8(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_C0_5_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_5_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, shr8(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_C0_6_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_6_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE8!(___, addr, shl8(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_C0_6_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_6_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, shl8(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_C0_7_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_7_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE8!(___, addr, sar8(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_C0_7_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_7_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, sar8(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_C1_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_0_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, rol16(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_C1_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_0_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, rol16(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_C1_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_1_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, ror16(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_C1_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_1_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, ror16(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_C1_2_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_2_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, rcl16(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_C1_2_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_2_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, rcl16(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_C1_3_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_3_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, rcr16(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_C1_3_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_3_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, rcr16(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_C1_4_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_4_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, shl16(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_C1_4_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_4_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, shl16(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_C1_5_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_5_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, shr16(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_C1_5_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_5_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, shr16(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_C1_6_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_6_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, shl16(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_C1_6_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_6_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, shl16(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_C1_7_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_7_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, sar16(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_C1_7_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_7_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, sar16(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_C1_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_0_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, rol32(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_C1_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_0_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, rol32(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_C1_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_1_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, ror32(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_C1_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_1_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, ror32(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_C1_2_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_2_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, rcl32(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_C1_2_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_2_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, rcl32(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_C1_3_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_3_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, rcr32(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_C1_3_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_3_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, rcr32(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_C1_4_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_4_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, shl32(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_C1_4_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_4_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, shl32(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_C1_5_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_5_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, shr32(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_C1_5_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_5_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, shr32(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_C1_6_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_6_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, shl32(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_C1_6_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_6_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, shl32(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_C1_7_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_7_mem(mut addr: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, sar32(___, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_C1_7_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_7_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, sar32(____0, imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_C2(mut imm16: i32) -> () { +pub unsafe fn instr16_C2(mut imm16: i32) -> () { c_comment!(("retn")); let mut cs: i32 = get_seg_cs(); *instruction_pointer.offset(0isize) = cs + return_on_pagefault!(pop16()); @@ -2278,7 +2228,7 @@ pub unsafe extern "C" fn instr16_C2(mut imm16: i32) -> () { adjust_stack_reg(imm16); } #[no_mangle] -pub unsafe extern "C" fn instr32_C2(mut imm16: i32) -> () { +pub unsafe fn instr32_C2(mut imm16: i32) -> () { c_comment!(("retn")); let mut cs: i32 = get_seg_cs(); let mut ip: i32 = return_on_pagefault!(pop32s()); @@ -2287,13 +2237,13 @@ pub unsafe extern "C" fn instr32_C2(mut imm16: i32) -> () { adjust_stack_reg(imm16); } #[no_mangle] -pub unsafe extern "C" fn instr16_C3() -> () { +pub unsafe fn instr16_C3() -> () { c_comment!(("retn")); let mut cs: i32 = get_seg_cs(); *instruction_pointer.offset(0isize) = cs + return_on_pagefault!(pop16()); } #[no_mangle] -pub unsafe extern "C" fn instr32_C3() -> () { +pub unsafe fn instr32_C3() -> () { c_comment!(("retn")); let mut cs: i32 = get_seg_cs(); let mut ip: i32 = return_on_pagefault!(pop32s()); @@ -2301,61 +2251,49 @@ pub unsafe extern "C" fn instr32_C3() -> () { *instruction_pointer.offset(0isize) = cs + ip; } #[no_mangle] -pub unsafe extern "C" fn instr16_C4_reg(mut _unused1: i32, mut _unused2: i32) -> () { - trigger_ud(); -} +pub unsafe fn instr16_C4_reg(mut _unused1: i32, mut _unused2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr16_C4_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_C4_mem(mut addr: i32, mut r: i32) -> () { lss16(addr, get_reg16_index(r), ES); } #[no_mangle] -pub unsafe extern "C" fn instr32_C4_reg(mut _unused1: i32, mut _unused2: i32) -> () { - trigger_ud(); -} +pub unsafe fn instr32_C4_reg(mut _unused1: i32, mut _unused2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr32_C4_mem(mut addr: i32, mut r: i32) -> () { lss32(addr, r, ES); } +pub unsafe fn instr32_C4_mem(mut addr: i32, mut r: i32) -> () { lss32(addr, r, ES); } #[no_mangle] -pub unsafe extern "C" fn instr16_C5_reg(mut _unused1: i32, mut _unused2: i32) -> () { - trigger_ud(); -} +pub unsafe fn instr16_C5_reg(mut _unused1: i32, mut _unused2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr16_C5_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_C5_mem(mut addr: i32, mut r: i32) -> () { lss16(addr, get_reg16_index(r), DS); } #[no_mangle] -pub unsafe extern "C" fn instr32_C5_reg(mut _unused1: i32, mut _unused2: i32) -> () { - trigger_ud(); -} +pub unsafe fn instr32_C5_reg(mut _unused1: i32, mut _unused2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr32_C5_mem(mut addr: i32, mut r: i32) -> () { lss32(addr, r, DS); } +pub unsafe fn instr32_C5_mem(mut addr: i32, mut r: i32) -> () { lss32(addr, r, DS); } #[no_mangle] -pub unsafe extern "C" fn instr_C6_0_reg(mut r: i32, mut imm: i32) -> () { write_reg8(r, imm); } +pub unsafe fn instr_C6_0_reg(mut r: i32, mut imm: i32) -> () { write_reg8(r, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_C6_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_C6_0_mem(mut addr: i32, mut imm: i32) -> () { return_on_pagefault!(safe_write8(addr, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_C7_0_reg(mut r: i32, mut imm: i32) -> () { write_reg16(r, imm); } +pub unsafe fn instr16_C7_0_reg(mut r: i32, mut imm: i32) -> () { write_reg16(r, imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_C7_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C7_0_mem(mut addr: i32, mut imm: i32) -> () { return_on_pagefault!(safe_write16(addr, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr32_C7_0_reg(mut r: i32, mut imm: i32) -> () { write_reg32(r, imm); } +pub unsafe fn instr32_C7_0_reg(mut r: i32, mut imm: i32) -> () { write_reg32(r, imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_C7_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C7_0_mem(mut addr: i32, mut imm: i32) -> () { return_on_pagefault!(safe_write32(addr, imm)); } #[no_mangle] -pub unsafe extern "C" fn instr16_C8(mut size: i32, mut nesting: i32) -> () { - enter16(size, nesting); -} +pub unsafe fn instr16_C8(mut size: i32, mut nesting: i32) -> () { enter16(size, nesting); } #[no_mangle] -pub unsafe extern "C" fn instr32_C8(mut size: i32, mut nesting: i32) -> () { - enter32(size, nesting); -} +pub unsafe fn instr32_C8(mut size: i32, mut nesting: i32) -> () { enter32(size, nesting); } #[no_mangle] -pub unsafe extern "C" fn instr16_C9() -> () { +pub unsafe fn instr16_C9() -> () { c_comment!(("leave")); let mut old_vbp: i32 = if 0 != *stack_size_32 as i32 { *reg32s.offset(EBP as isize) @@ -2368,7 +2306,7 @@ pub unsafe extern "C" fn instr16_C9() -> () { *reg16.offset(BP as isize) = new_bp as u16; } #[no_mangle] -pub unsafe extern "C" fn instr32_C9() -> () { +pub unsafe fn instr32_C9() -> () { let mut old_vbp: i32 = if 0 != *stack_size_32 as i32 { *reg32s.offset(EBP as isize) } @@ -2380,14 +2318,14 @@ pub unsafe extern "C" fn instr32_C9() -> () { *reg32s.offset(EBP as isize) = new_ebp; } #[no_mangle] -pub unsafe extern "C" fn instr16_CA(mut imm16: i32) -> () { +pub unsafe fn instr16_CA(mut imm16: i32) -> () { c_comment!(("retf")); let mut ip: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0i32))); let mut cs: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(2i32))); far_return(ip, cs, imm16); } #[no_mangle] -pub unsafe extern "C" fn instr32_CA(mut imm16: i32) -> () { +pub unsafe fn instr32_CA(mut imm16: i32) -> () { c_comment!(("retf")); let mut ip: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))); let mut cs: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(4i32))) & 65535i32; @@ -2395,7 +2333,7 @@ pub unsafe extern "C" fn instr32_CA(mut imm16: i32) -> () { dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe extern "C" fn instr16_CB() -> () { +pub unsafe fn instr16_CB() -> () { c_comment!(("retf")); let mut ip: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0i32))); let mut cs: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(2i32))); @@ -2403,7 +2341,7 @@ pub unsafe extern "C" fn instr16_CB() -> () { dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe extern "C" fn instr32_CB() -> () { +pub unsafe fn instr32_CB() -> () { c_comment!(("retf")); let mut ip: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))); let mut cs: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(4i32))) & 65535i32; @@ -2411,19 +2349,19 @@ pub unsafe extern "C" fn instr32_CB() -> () { dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe extern "C" fn instr_CC() -> () { +pub unsafe fn instr_CC() -> () { c_comment!(("INT3")); c_comment!(("TODO: inhibit iopl checks")); dbg_log_c!("INT3"); call_interrupt_vector(3i32, 0 != 1i32, 0 != 0i32, 0i32); } #[no_mangle] -pub unsafe extern "C" fn instr_CD(mut imm8: i32) -> () { +pub unsafe fn instr_CD(mut imm8: i32) -> () { c_comment!(("INT")); call_interrupt_vector(imm8, 0 != 1i32, 0 != 0i32, 0i32); } #[no_mangle] -pub unsafe extern "C" fn instr_CE() -> () { +pub unsafe fn instr_CE() -> () { c_comment!(("INTO")); dbg_log_c!("INTO"); if getof() { @@ -2432,230 +2370,230 @@ pub unsafe extern "C" fn instr_CE() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr16_CF() -> () { +pub unsafe fn instr16_CF() -> () { c_comment!(("iret")); iret16(); } #[no_mangle] -pub unsafe extern "C" fn instr32_CF() -> () { iret32(); } +pub unsafe fn instr32_CF() -> () { iret32(); } #[no_mangle] -pub unsafe extern "C" fn instr_D0_0_mem(mut addr: i32) -> () { +pub unsafe fn instr_D0_0_mem(mut addr: i32) -> () { SAFE_READ_WRITE8!(___, addr, rol8(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D0_0_reg(mut r1: i32) -> () { +pub unsafe fn instr_D0_0_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, rol8(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D0_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_D0_1_mem(mut addr: i32) -> () { SAFE_READ_WRITE8!(___, addr, ror8(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D0_1_reg(mut r1: i32) -> () { +pub unsafe fn instr_D0_1_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, ror8(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D0_2_mem(mut addr: i32) -> () { +pub unsafe fn instr_D0_2_mem(mut addr: i32) -> () { SAFE_READ_WRITE8!(___, addr, rcl8(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D0_2_reg(mut r1: i32) -> () { +pub unsafe fn instr_D0_2_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, rcl8(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D0_3_mem(mut addr: i32) -> () { +pub unsafe fn instr_D0_3_mem(mut addr: i32) -> () { SAFE_READ_WRITE8!(___, addr, rcr8(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D0_3_reg(mut r1: i32) -> () { +pub unsafe fn instr_D0_3_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, rcr8(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D0_4_mem(mut addr: i32) -> () { +pub unsafe fn instr_D0_4_mem(mut addr: i32) -> () { SAFE_READ_WRITE8!(___, addr, shl8(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D0_4_reg(mut r1: i32) -> () { +pub unsafe fn instr_D0_4_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, shl8(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D0_5_mem(mut addr: i32) -> () { +pub unsafe fn instr_D0_5_mem(mut addr: i32) -> () { SAFE_READ_WRITE8!(___, addr, shr8(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D0_5_reg(mut r1: i32) -> () { +pub unsafe fn instr_D0_5_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, shr8(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D0_6_mem(mut addr: i32) -> () { +pub unsafe fn instr_D0_6_mem(mut addr: i32) -> () { SAFE_READ_WRITE8!(___, addr, shl8(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D0_6_reg(mut r1: i32) -> () { +pub unsafe fn instr_D0_6_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, shl8(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D0_7_mem(mut addr: i32) -> () { +pub unsafe fn instr_D0_7_mem(mut addr: i32) -> () { SAFE_READ_WRITE8!(___, addr, sar8(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D0_7_reg(mut r1: i32) -> () { +pub unsafe fn instr_D0_7_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, sar8(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D1_0_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D1_0_mem(mut addr: i32) -> () { SAFE_READ_WRITE16!(___, addr, rol16(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D1_0_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D1_0_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, rol16(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D1_1_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D1_1_mem(mut addr: i32) -> () { SAFE_READ_WRITE16!(___, addr, ror16(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D1_1_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D1_1_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, ror16(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D1_2_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D1_2_mem(mut addr: i32) -> () { SAFE_READ_WRITE16!(___, addr, rcl16(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D1_2_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D1_2_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, rcl16(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D1_3_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D1_3_mem(mut addr: i32) -> () { SAFE_READ_WRITE16!(___, addr, rcr16(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D1_3_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D1_3_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, rcr16(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D1_4_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D1_4_mem(mut addr: i32) -> () { SAFE_READ_WRITE16!(___, addr, shl16(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D1_4_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D1_4_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, shl16(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D1_5_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D1_5_mem(mut addr: i32) -> () { SAFE_READ_WRITE16!(___, addr, shr16(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D1_5_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D1_5_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, shr16(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D1_6_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D1_6_mem(mut addr: i32) -> () { SAFE_READ_WRITE16!(___, addr, shl16(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D1_6_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D1_6_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, shl16(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D1_7_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D1_7_mem(mut addr: i32) -> () { SAFE_READ_WRITE16!(___, addr, sar16(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D1_7_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D1_7_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, sar16(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D1_0_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D1_0_mem(mut addr: i32) -> () { SAFE_READ_WRITE32!(___, addr, rol32(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D1_0_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D1_0_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, rol32(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D1_1_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D1_1_mem(mut addr: i32) -> () { SAFE_READ_WRITE32!(___, addr, ror32(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D1_1_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D1_1_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, ror32(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D1_2_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D1_2_mem(mut addr: i32) -> () { SAFE_READ_WRITE32!(___, addr, rcl32(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D1_2_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D1_2_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, rcl32(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D1_3_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D1_3_mem(mut addr: i32) -> () { SAFE_READ_WRITE32!(___, addr, rcr32(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D1_3_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D1_3_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, rcr32(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D1_4_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D1_4_mem(mut addr: i32) -> () { SAFE_READ_WRITE32!(___, addr, shl32(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D1_4_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D1_4_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, shl32(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D1_5_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D1_5_mem(mut addr: i32) -> () { SAFE_READ_WRITE32!(___, addr, shr32(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D1_5_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D1_5_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, shr32(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D1_6_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D1_6_mem(mut addr: i32) -> () { SAFE_READ_WRITE32!(___, addr, shl32(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D1_6_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D1_6_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, shl32(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D1_7_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D1_7_mem(mut addr: i32) -> () { SAFE_READ_WRITE32!(___, addr, sar32(___, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D1_7_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D1_7_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, sar32(____0, 1i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D2_0_mem(mut addr: i32) -> () { +pub unsafe fn instr_D2_0_mem(mut addr: i32) -> () { SAFE_READ_WRITE8!( ___, addr, @@ -2663,12 +2601,12 @@ pub unsafe extern "C" fn instr_D2_0_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_D2_0_reg(mut r1: i32) -> () { +pub unsafe fn instr_D2_0_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, rol8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D2_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_D2_1_mem(mut addr: i32) -> () { SAFE_READ_WRITE8!( ___, addr, @@ -2676,12 +2614,12 @@ pub unsafe extern "C" fn instr_D2_1_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_D2_1_reg(mut r1: i32) -> () { +pub unsafe fn instr_D2_1_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, ror8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D2_2_mem(mut addr: i32) -> () { +pub unsafe fn instr_D2_2_mem(mut addr: i32) -> () { SAFE_READ_WRITE8!( ___, addr, @@ -2689,12 +2627,12 @@ pub unsafe extern "C" fn instr_D2_2_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_D2_2_reg(mut r1: i32) -> () { +pub unsafe fn instr_D2_2_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, rcl8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D2_3_mem(mut addr: i32) -> () { +pub unsafe fn instr_D2_3_mem(mut addr: i32) -> () { SAFE_READ_WRITE8!( ___, addr, @@ -2702,12 +2640,12 @@ pub unsafe extern "C" fn instr_D2_3_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_D2_3_reg(mut r1: i32) -> () { +pub unsafe fn instr_D2_3_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, rcr8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D2_4_mem(mut addr: i32) -> () { +pub unsafe fn instr_D2_4_mem(mut addr: i32) -> () { SAFE_READ_WRITE8!( ___, addr, @@ -2715,12 +2653,12 @@ pub unsafe extern "C" fn instr_D2_4_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_D2_4_reg(mut r1: i32) -> () { +pub unsafe fn instr_D2_4_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, shl8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D2_5_mem(mut addr: i32) -> () { +pub unsafe fn instr_D2_5_mem(mut addr: i32) -> () { SAFE_READ_WRITE8!( ___, addr, @@ -2728,12 +2666,12 @@ pub unsafe extern "C" fn instr_D2_5_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_D2_5_reg(mut r1: i32) -> () { +pub unsafe fn instr_D2_5_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, shr8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D2_6_mem(mut addr: i32) -> () { +pub unsafe fn instr_D2_6_mem(mut addr: i32) -> () { SAFE_READ_WRITE8!( ___, addr, @@ -2741,12 +2679,12 @@ pub unsafe extern "C" fn instr_D2_6_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_D2_6_reg(mut r1: i32) -> () { +pub unsafe fn instr_D2_6_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, shl8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D2_7_mem(mut addr: i32) -> () { +pub unsafe fn instr_D2_7_mem(mut addr: i32) -> () { SAFE_READ_WRITE8!( ___, addr, @@ -2754,12 +2692,12 @@ pub unsafe extern "C" fn instr_D2_7_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_D2_7_reg(mut r1: i32) -> () { +pub unsafe fn instr_D2_7_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, sar8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D3_0_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D3_0_mem(mut addr: i32) -> () { SAFE_READ_WRITE16!( ___, addr, @@ -2767,12 +2705,12 @@ pub unsafe extern "C" fn instr16_D3_0_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr16_D3_0_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D3_0_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, rol16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D3_1_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D3_1_mem(mut addr: i32) -> () { SAFE_READ_WRITE16!( ___, addr, @@ -2780,12 +2718,12 @@ pub unsafe extern "C" fn instr16_D3_1_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr16_D3_1_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D3_1_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, ror16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D3_2_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D3_2_mem(mut addr: i32) -> () { SAFE_READ_WRITE16!( ___, addr, @@ -2793,12 +2731,12 @@ pub unsafe extern "C" fn instr16_D3_2_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr16_D3_2_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D3_2_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, rcl16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D3_3_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D3_3_mem(mut addr: i32) -> () { SAFE_READ_WRITE16!( ___, addr, @@ -2806,12 +2744,12 @@ pub unsafe extern "C" fn instr16_D3_3_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr16_D3_3_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D3_3_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, rcr16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D3_4_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D3_4_mem(mut addr: i32) -> () { SAFE_READ_WRITE16!( ___, addr, @@ -2819,12 +2757,12 @@ pub unsafe extern "C" fn instr16_D3_4_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr16_D3_4_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D3_4_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, shl16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D3_5_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D3_5_mem(mut addr: i32) -> () { SAFE_READ_WRITE16!( ___, addr, @@ -2832,12 +2770,12 @@ pub unsafe extern "C" fn instr16_D3_5_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr16_D3_5_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D3_5_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, shr16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D3_6_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D3_6_mem(mut addr: i32) -> () { SAFE_READ_WRITE16!( ___, addr, @@ -2845,12 +2783,12 @@ pub unsafe extern "C" fn instr16_D3_6_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr16_D3_6_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D3_6_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, shl16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_D3_7_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D3_7_mem(mut addr: i32) -> () { SAFE_READ_WRITE16!( ___, addr, @@ -2858,12 +2796,12 @@ pub unsafe extern "C" fn instr16_D3_7_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr16_D3_7_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D3_7_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, sar16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D3_0_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D3_0_mem(mut addr: i32) -> () { SAFE_READ_WRITE32!( ___, addr, @@ -2871,12 +2809,12 @@ pub unsafe extern "C" fn instr32_D3_0_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr32_D3_0_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D3_0_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, rol32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D3_1_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D3_1_mem(mut addr: i32) -> () { SAFE_READ_WRITE32!( ___, addr, @@ -2884,12 +2822,12 @@ pub unsafe extern "C" fn instr32_D3_1_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr32_D3_1_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D3_1_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, ror32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D3_2_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D3_2_mem(mut addr: i32) -> () { SAFE_READ_WRITE32!( ___, addr, @@ -2897,12 +2835,12 @@ pub unsafe extern "C" fn instr32_D3_2_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr32_D3_2_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D3_2_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, rcl32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D3_3_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D3_3_mem(mut addr: i32) -> () { SAFE_READ_WRITE32!( ___, addr, @@ -2910,12 +2848,12 @@ pub unsafe extern "C" fn instr32_D3_3_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr32_D3_3_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D3_3_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, rcr32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D3_4_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D3_4_mem(mut addr: i32) -> () { SAFE_READ_WRITE32!( ___, addr, @@ -2923,12 +2861,12 @@ pub unsafe extern "C" fn instr32_D3_4_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr32_D3_4_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D3_4_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, shl32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D3_5_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D3_5_mem(mut addr: i32) -> () { SAFE_READ_WRITE32!( ___, addr, @@ -2936,12 +2874,12 @@ pub unsafe extern "C" fn instr32_D3_5_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr32_D3_5_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D3_5_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, shr32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D3_6_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D3_6_mem(mut addr: i32) -> () { SAFE_READ_WRITE32!( ___, addr, @@ -2949,12 +2887,12 @@ pub unsafe extern "C" fn instr32_D3_6_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr32_D3_6_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D3_6_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, shl32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_D3_7_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D3_7_mem(mut addr: i32) -> () { SAFE_READ_WRITE32!( ___, addr, @@ -2962,21 +2900,21 @@ pub unsafe extern "C" fn instr32_D3_7_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr32_D3_7_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D3_7_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, sar32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_D4(mut arg: i32) -> () { bcd_aam(arg); } +pub unsafe fn instr_D4(mut arg: i32) -> () { bcd_aam(arg); } #[no_mangle] -pub unsafe extern "C" fn instr_D5(mut arg: i32) -> () { bcd_aad(arg); } +pub unsafe fn instr_D5(mut arg: i32) -> () { bcd_aad(arg); } #[no_mangle] -pub unsafe extern "C" fn instr_D6() -> () { +pub unsafe fn instr_D6() -> () { c_comment!(("salc")); *reg8.offset(AL as isize) = -(getcf() as i32) as u8; } #[no_mangle] -pub unsafe extern "C" fn instr_D7() -> () { +pub unsafe fn instr_D7() -> () { c_comment!(("xlat")); if is_asize_32() { *reg8.offset(AL as isize) = return_on_pagefault!(safe_read8( @@ -2991,7 +2929,7 @@ pub unsafe extern "C" fn instr_D7() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_E4(mut port: i32) -> () { +pub unsafe fn instr_E4(mut port: i32) -> () { if !test_privileges_for_io(port, 1i32) { return; } @@ -3001,7 +2939,7 @@ pub unsafe extern "C" fn instr_E4(mut port: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr16_E5(mut port: i32) -> () { +pub unsafe fn instr16_E5(mut port: i32) -> () { if !test_privileges_for_io(port, 2i32) { return; } @@ -3011,7 +2949,7 @@ pub unsafe extern "C" fn instr16_E5(mut port: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr32_E5(mut port: i32) -> () { +pub unsafe fn instr32_E5(mut port: i32) -> () { if !test_privileges_for_io(port, 4i32) { return; } @@ -3021,7 +2959,7 @@ pub unsafe extern "C" fn instr32_E5(mut port: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_E6(mut port: i32) -> () { +pub unsafe fn instr_E6(mut port: i32) -> () { if !test_privileges_for_io(port, 1i32) { return; } @@ -3031,7 +2969,7 @@ pub unsafe extern "C" fn instr_E6(mut port: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr16_E7(mut port: i32) -> () { +pub unsafe fn instr16_E7(mut port: i32) -> () { if !test_privileges_for_io(port, 2i32) { return; } @@ -3041,7 +2979,7 @@ pub unsafe extern "C" fn instr16_E7(mut port: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr32_E7(mut port: i32) -> () { +pub unsafe fn instr32_E7(mut port: i32) -> () { if !test_privileges_for_io(port, 4i32) { return; } @@ -3051,43 +2989,43 @@ pub unsafe extern "C" fn instr32_E7(mut port: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr16_E8(mut imm16: i32) -> () { +pub unsafe fn instr16_E8(mut imm16: i32) -> () { c_comment!(("call")); return_on_pagefault!(push16(get_real_eip())); jmp_rel16(imm16); } #[no_mangle] -pub unsafe extern "C" fn instr32_E8(mut imm32s: i32) -> () { +pub unsafe fn instr32_E8(mut imm32s: i32) -> () { c_comment!(("call")); return_on_pagefault!(push32(get_real_eip())); *instruction_pointer.offset(0isize) = *instruction_pointer.offset(0isize) + imm32s; c_comment!(("dbg_assert!(is_asize_32() || get_real_eip() < 0x10000);")); } #[no_mangle] -pub unsafe extern "C" fn instr16_E9(mut imm16: i32) -> () { +pub unsafe fn instr16_E9(mut imm16: i32) -> () { c_comment!(("jmp")); jmp_rel16(imm16); } #[no_mangle] -pub unsafe extern "C" fn instr32_E9(mut imm32s: i32) -> () { +pub unsafe fn instr32_E9(mut imm32s: i32) -> () { c_comment!(("jmp")); *instruction_pointer.offset(0isize) = *instruction_pointer.offset(0isize) + imm32s; dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe extern "C" fn instr16_EA(mut new_ip: i32, mut cs: i32) -> () { +pub unsafe fn instr16_EA(mut new_ip: i32, mut cs: i32) -> () { c_comment!(("jmpf")); far_jump(new_ip, cs, false); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe extern "C" fn instr32_EA(mut new_ip: i32, mut cs: i32) -> () { +pub unsafe fn instr32_EA(mut new_ip: i32, mut cs: i32) -> () { c_comment!(("jmpf")); far_jump(new_ip, cs, false); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe extern "C" fn instr_EC() -> () { +pub unsafe fn instr_EC() -> () { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 1i32) { return; @@ -3098,7 +3036,7 @@ pub unsafe extern "C" fn instr_EC() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr16_ED() -> () { +pub unsafe fn instr16_ED() -> () { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 2i32) { return; @@ -3109,7 +3047,7 @@ pub unsafe extern "C" fn instr16_ED() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr32_ED() -> () { +pub unsafe fn instr32_ED() -> () { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 4i32) { return; @@ -3120,7 +3058,7 @@ pub unsafe extern "C" fn instr32_ED() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_EE() -> () { +pub unsafe fn instr_EE() -> () { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 1i32) { return; @@ -3131,7 +3069,7 @@ pub unsafe extern "C" fn instr_EE() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr16_EF() -> () { +pub unsafe fn instr16_EF() -> () { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 2i32) { return; @@ -3142,7 +3080,7 @@ pub unsafe extern "C" fn instr16_EF() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr32_EF() -> () { +pub unsafe fn instr32_EF() -> () { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 4i32) { return; @@ -3153,7 +3091,7 @@ pub unsafe extern "C" fn instr32_EF() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_F0() -> () { +pub unsafe fn instr_F0() -> () { c_comment!(("lock")); if 0 != 0i32 * 0i32 { dbg_log_c!("lock"); @@ -3164,13 +3102,13 @@ pub unsafe extern "C" fn instr_F0() -> () { run_prefix_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr_F1() -> () { +pub unsafe fn instr_F1() -> () { c_comment!(("INT1")); c_comment!(("https://code.google.com/p/corkami/wiki/x86oddities#IceBP")); dbg_assert!(0 != 0i32); } #[no_mangle] -pub unsafe extern "C" fn instr_F2() -> () { +pub unsafe fn instr_F2() -> () { c_comment!(("repnz")); dbg_assert!(*prefixes as i32 & PREFIX_MASK_REP == 0i32); *prefixes = (*prefixes as i32 | PREFIX_REPNZ) as u8; @@ -3178,7 +3116,7 @@ pub unsafe extern "C" fn instr_F2() -> () { *prefixes = 0i32 as u8; } #[no_mangle] -pub unsafe extern "C" fn instr_F3() -> () { +pub unsafe fn instr_F3() -> () { c_comment!(("repz")); dbg_assert!(*prefixes as i32 & PREFIX_MASK_REP == 0i32); *prefixes = (*prefixes as i32 | PREFIX_REPZ) as u8; @@ -3186,250 +3124,250 @@ pub unsafe extern "C" fn instr_F3() -> () { *prefixes = 0i32 as u8; } #[no_mangle] -pub unsafe extern "C" fn instr_F4() -> () { hlt_op(); } +pub unsafe fn instr_F4() -> () { hlt_op(); } #[no_mangle] -pub unsafe extern "C" fn instr_F5() -> () { +pub unsafe fn instr_F5() -> () { c_comment!(("cmc")); *flags.offset(0isize) = (*flags.offset(0isize) | 1i32) ^ getcf() as i32; let ref mut fresh2 = *flags_changed.offset(0isize); *fresh2 &= !1i32; } #[no_mangle] -pub unsafe extern "C" fn instr_F6_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_F6_0_mem(mut addr: i32, mut imm: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); test8(____0, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_F6_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_F6_0_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); test8(____0, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_F6_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_F6_1_mem(mut addr: i32, mut imm: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); test8(____0, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_F6_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_F6_1_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg8(r1); test8(____0, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_F6_2_mem(mut addr: i32) -> () { +pub unsafe fn instr_F6_2_mem(mut addr: i32) -> () { SAFE_READ_WRITE8!(___, addr, !___); } #[no_mangle] -pub unsafe extern "C" fn instr_F6_2_reg(mut r1: i32) -> () { +pub unsafe fn instr_F6_2_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, !____0); } #[no_mangle] -pub unsafe extern "C" fn instr_F6_3_mem(mut addr: i32) -> () { +pub unsafe fn instr_F6_3_mem(mut addr: i32) -> () { SAFE_READ_WRITE8!(___, addr, neg8(___)); } #[no_mangle] -pub unsafe extern "C" fn instr_F6_3_reg(mut r1: i32) -> () { +pub unsafe fn instr_F6_3_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, neg8(____0)); } #[no_mangle] -pub unsafe extern "C" fn instr_F6_4_mem(mut addr: i32) -> () { +pub unsafe fn instr_F6_4_mem(mut addr: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); mul8(____0); } #[no_mangle] -pub unsafe extern "C" fn instr_F6_4_reg(mut r1: i32) -> () { +pub unsafe fn instr_F6_4_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); mul8(____0); } #[no_mangle] -pub unsafe extern "C" fn instr_F6_5_mem(mut addr: i32) -> () { +pub unsafe fn instr_F6_5_mem(mut addr: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); imul8(____0 << 24i32 >> 24i32); } #[no_mangle] -pub unsafe extern "C" fn instr_F6_5_reg(mut r1: i32) -> () { +pub unsafe fn instr_F6_5_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); imul8(____0 << 24i32 >> 24i32); } #[no_mangle] -pub unsafe extern "C" fn instr_F6_6_mem(mut addr: i32) -> () { +pub unsafe fn instr_F6_6_mem(mut addr: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); div8(____0 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr_F6_6_reg(mut r1: i32) -> () { +pub unsafe fn instr_F6_6_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); div8(____0 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr_F6_7_mem(mut addr: i32) -> () { +pub unsafe fn instr_F6_7_mem(mut addr: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); idiv8(____0 << 24i32 >> 24i32); } #[no_mangle] -pub unsafe extern "C" fn instr_F6_7_reg(mut r1: i32) -> () { +pub unsafe fn instr_F6_7_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); idiv8(____0 << 24i32 >> 24i32); } #[no_mangle] -pub unsafe extern "C" fn instr16_F7_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_F7_0_mem(mut addr: i32, mut imm: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); test16(____0, imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_F7_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_F7_0_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); test16(____0, imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_F7_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_F7_1_mem(mut addr: i32, mut imm: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); test16(____0, imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_F7_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_F7_1_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); test16(____0, imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_F7_2_mem(mut addr: i32) -> () { +pub unsafe fn instr16_F7_2_mem(mut addr: i32) -> () { SAFE_READ_WRITE16!(___, addr, !___); } #[no_mangle] -pub unsafe extern "C" fn instr16_F7_2_reg(mut r1: i32) -> () { +pub unsafe fn instr16_F7_2_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, !____0); } #[no_mangle] -pub unsafe extern "C" fn instr16_F7_3_mem(mut addr: i32) -> () { +pub unsafe fn instr16_F7_3_mem(mut addr: i32) -> () { SAFE_READ_WRITE16!(___, addr, neg16(___)); } #[no_mangle] -pub unsafe extern "C" fn instr16_F7_3_reg(mut r1: i32) -> () { +pub unsafe fn instr16_F7_3_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, neg16(____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_F7_4_mem(mut addr: i32) -> () { +pub unsafe fn instr16_F7_4_mem(mut addr: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); mul16(____0 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr16_F7_4_reg(mut r1: i32) -> () { +pub unsafe fn instr16_F7_4_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); mul16(____0 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr16_F7_5_mem(mut addr: i32) -> () { +pub unsafe fn instr16_F7_5_mem(mut addr: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); imul16(____0 << 16i32 >> 16i32); } #[no_mangle] -pub unsafe extern "C" fn instr16_F7_5_reg(mut r1: i32) -> () { +pub unsafe fn instr16_F7_5_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); imul16(____0 << 16i32 >> 16i32); } #[no_mangle] -pub unsafe extern "C" fn instr16_F7_6_mem(mut addr: i32) -> () { +pub unsafe fn instr16_F7_6_mem(mut addr: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); div16(____0 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr16_F7_6_reg(mut r1: i32) -> () { +pub unsafe fn instr16_F7_6_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); div16(____0 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr16_F7_7_mem(mut addr: i32) -> () { +pub unsafe fn instr16_F7_7_mem(mut addr: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); idiv16(____0 << 16i32 >> 16i32); } #[no_mangle] -pub unsafe extern "C" fn instr16_F7_7_reg(mut r1: i32) -> () { +pub unsafe fn instr16_F7_7_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); idiv16(____0 << 16i32 >> 16i32); } #[no_mangle] -pub unsafe extern "C" fn instr32_F7_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_F7_0_mem(mut addr: i32, mut imm: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); test32(____0, imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_F7_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_F7_0_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); test32(____0, imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_F7_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_F7_1_mem(mut addr: i32, mut imm: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); test32(____0, imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_F7_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_F7_1_reg(mut r1: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); test32(____0, imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_F7_2_mem(mut addr: i32) -> () { +pub unsafe fn instr32_F7_2_mem(mut addr: i32) -> () { SAFE_READ_WRITE32!(___, addr, !___); } #[no_mangle] -pub unsafe extern "C" fn instr32_F7_2_reg(mut r1: i32) -> () { +pub unsafe fn instr32_F7_2_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, !____0); } #[no_mangle] -pub unsafe extern "C" fn instr32_F7_3_mem(mut addr: i32) -> () { +pub unsafe fn instr32_F7_3_mem(mut addr: i32) -> () { SAFE_READ_WRITE32!(___, addr, neg32(___)); } #[no_mangle] -pub unsafe extern "C" fn instr32_F7_3_reg(mut r1: i32) -> () { +pub unsafe fn instr32_F7_3_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, neg32(____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_F7_4_mem(mut addr: i32) -> () { +pub unsafe fn instr32_F7_4_mem(mut addr: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); mul32(____0); } #[no_mangle] -pub unsafe extern "C" fn instr32_F7_4_reg(mut r1: i32) -> () { +pub unsafe fn instr32_F7_4_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); mul32(____0); } #[no_mangle] -pub unsafe extern "C" fn instr32_F7_5_mem(mut addr: i32) -> () { +pub unsafe fn instr32_F7_5_mem(mut addr: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); imul32(____0); } #[no_mangle] -pub unsafe extern "C" fn instr32_F7_5_reg(mut r1: i32) -> () { +pub unsafe fn instr32_F7_5_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); imul32(____0); } #[no_mangle] -pub unsafe extern "C" fn instr32_F7_6_mem(mut addr: i32) -> () { +pub unsafe fn instr32_F7_6_mem(mut addr: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); div32(____0 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr32_F7_6_reg(mut r1: i32) -> () { +pub unsafe fn instr32_F7_6_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); div32(____0 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr32_F7_7_mem(mut addr: i32) -> () { +pub unsafe fn instr32_F7_7_mem(mut addr: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); idiv32(____0); } #[no_mangle] -pub unsafe extern "C" fn instr32_F7_7_reg(mut r1: i32) -> () { +pub unsafe fn instr32_F7_7_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); idiv32(____0); } #[no_mangle] -pub unsafe extern "C" fn instr_F8() -> () { +pub unsafe fn instr_F8() -> () { c_comment!(("clc")); let ref mut fresh3 = *flags.offset(0isize); *fresh3 &= !FLAG_CARRY; @@ -3437,7 +3375,7 @@ pub unsafe extern "C" fn instr_F8() -> () { *fresh4 &= !1i32; } #[no_mangle] -pub unsafe extern "C" fn instr_F9() -> () { +pub unsafe fn instr_F9() -> () { c_comment!(("stc")); let ref mut fresh5 = *flags.offset(0isize); *fresh5 |= FLAG_CARRY; @@ -3445,7 +3383,7 @@ pub unsafe extern "C" fn instr_F9() -> () { *fresh6 &= !1i32; } #[no_mangle] -pub unsafe extern "C" fn instr_FA() -> () { +pub unsafe fn instr_FA() -> () { c_comment!(("cli")); if !*protected_mode || 0 != if 0 != *flags.offset(0isize) & FLAG_VM { (getiopl() == 3i32) as i32 @@ -3470,7 +3408,7 @@ pub unsafe extern "C" fn instr_FA() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_FB() -> () { +pub unsafe fn instr_FB() -> () { c_comment!(("sti")); let mut old_if: i32 = *flags.offset(0isize) & FLAG_INTERRUPT; if !*protected_mode || 0 != if 0 != *flags.offset(0isize) & FLAG_VM { @@ -3501,55 +3439,55 @@ pub unsafe extern "C" fn instr_FB() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_FC() -> () { +pub unsafe fn instr_FC() -> () { c_comment!(("cld")); let ref mut fresh9 = *flags.offset(0isize); *fresh9 &= !FLAG_DIRECTION; } #[no_mangle] -pub unsafe extern "C" fn instr_FD() -> () { +pub unsafe fn instr_FD() -> () { c_comment!(("std")); let ref mut fresh10 = *flags.offset(0isize); *fresh10 |= FLAG_DIRECTION; } #[no_mangle] -pub unsafe extern "C" fn instr_FE_0_mem(mut addr: i32) -> () { +pub unsafe fn instr_FE_0_mem(mut addr: i32) -> () { SAFE_READ_WRITE8!(___, addr, inc8(___)); } #[no_mangle] -pub unsafe extern "C" fn instr_FE_0_reg(mut r1: i32) -> () { +pub unsafe fn instr_FE_0_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, inc8(____0)); } #[no_mangle] -pub unsafe extern "C" fn instr_FE_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_FE_1_mem(mut addr: i32) -> () { SAFE_READ_WRITE8!(___, addr, dec8(___)); } #[no_mangle] -pub unsafe extern "C" fn instr_FE_1_reg(mut r1: i32) -> () { +pub unsafe fn instr_FE_1_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, dec8(____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_FF_0_mem(mut addr: i32) -> () { +pub unsafe fn instr16_FF_0_mem(mut addr: i32) -> () { SAFE_READ_WRITE16!(___, addr, inc16(___)); } #[no_mangle] -pub unsafe extern "C" fn instr16_FF_0_reg(mut r1: i32) -> () { +pub unsafe fn instr16_FF_0_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, inc16(____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_FF_1_mem(mut addr: i32) -> () { +pub unsafe fn instr16_FF_1_mem(mut addr: i32) -> () { SAFE_READ_WRITE16!(___, addr, dec16(___)); } #[no_mangle] -pub unsafe extern "C" fn instr16_FF_1_reg(mut r1: i32) -> () { +pub unsafe fn instr16_FF_1_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, dec16(____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_FF_2_helper(mut data: i32) -> () { +pub unsafe fn instr16_FF_2_helper(mut data: i32) -> () { c_comment!(("call near")); let mut cs: i32 = get_seg_cs(); return_on_pagefault!(push16(get_real_eip())); @@ -3557,22 +3495,22 @@ pub unsafe extern "C" fn instr16_FF_2_helper(mut data: i32) -> () { dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe extern "C" fn instr16_FF_2_mem(mut addr: i32) -> () { +pub unsafe fn instr16_FF_2_mem(mut addr: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); instr16_FF_2_helper(____0); } #[no_mangle] -pub unsafe extern "C" fn instr16_FF_2_reg(mut r1: i32) -> () { +pub unsafe fn instr16_FF_2_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); instr16_FF_2_helper(____0); } #[no_mangle] -pub unsafe extern "C" fn instr16_FF_3_reg(mut r: i32) -> () { +pub unsafe fn instr16_FF_3_reg(mut r: i32) -> () { dbg_log_c!("callf #ud"); trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr16_FF_3_mem(mut addr: i32) -> () { +pub unsafe fn instr16_FF_3_mem(mut addr: i32) -> () { c_comment!(("callf")); let mut new_ip: i32 = return_on_pagefault!(safe_read16(addr)); let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 2i32)); @@ -3580,28 +3518,28 @@ pub unsafe extern "C" fn instr16_FF_3_mem(mut addr: i32) -> () { dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe extern "C" fn instr16_FF_4_helper(mut data: i32) -> () { +pub unsafe fn instr16_FF_4_helper(mut data: i32) -> () { c_comment!(("jmp near")); *instruction_pointer.offset(0isize) = get_seg_cs() + data; dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe extern "C" fn instr16_FF_4_mem(mut addr: i32) -> () { +pub unsafe fn instr16_FF_4_mem(mut addr: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); instr16_FF_4_helper(____0); } #[no_mangle] -pub unsafe extern "C" fn instr16_FF_4_reg(mut r1: i32) -> () { +pub unsafe fn instr16_FF_4_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); instr16_FF_4_helper(____0); } #[no_mangle] -pub unsafe extern "C" fn instr16_FF_5_reg(mut r: i32) -> () { +pub unsafe fn instr16_FF_5_reg(mut r: i32) -> () { dbg_log_c!("jmpf #ud"); trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr16_FF_5_mem(mut addr: i32) -> () { +pub unsafe fn instr16_FF_5_mem(mut addr: i32) -> () { c_comment!(("jmpf")); let mut new_ip: i32 = return_on_pagefault!(safe_read16(addr)); let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 2i32)); @@ -3609,35 +3547,35 @@ pub unsafe extern "C" fn instr16_FF_5_mem(mut addr: i32) -> () { dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe extern "C" fn instr16_FF_6_mem(mut addr: i32) -> () { +pub unsafe fn instr16_FF_6_mem(mut addr: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); return_on_pagefault!(push16(____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_FF_6_reg(mut r1: i32) -> () { +pub unsafe fn instr16_FF_6_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg16(r1); return_on_pagefault!(push16(____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_FF_0_mem(mut addr: i32) -> () { +pub unsafe fn instr32_FF_0_mem(mut addr: i32) -> () { SAFE_READ_WRITE32!(___, addr, inc32(___)); } #[no_mangle] -pub unsafe extern "C" fn instr32_FF_0_reg(mut r1: i32) -> () { +pub unsafe fn instr32_FF_0_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, inc32(____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_FF_1_mem(mut addr: i32) -> () { +pub unsafe fn instr32_FF_1_mem(mut addr: i32) -> () { SAFE_READ_WRITE32!(___, addr, dec32(___)); } #[no_mangle] -pub unsafe extern "C" fn instr32_FF_1_reg(mut r1: i32) -> () { +pub unsafe fn instr32_FF_1_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, dec32(____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_FF_2_helper(mut data: i32) -> () { +pub unsafe fn instr32_FF_2_helper(mut data: i32) -> () { c_comment!(("call near")); let mut cs: i32 = get_seg_cs(); return_on_pagefault!(push32(get_real_eip())); @@ -3645,22 +3583,22 @@ pub unsafe extern "C" fn instr32_FF_2_helper(mut data: i32) -> () { *instruction_pointer.offset(0isize) = cs + data; } #[no_mangle] -pub unsafe extern "C" fn instr32_FF_2_mem(mut addr: i32) -> () { +pub unsafe fn instr32_FF_2_mem(mut addr: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); instr32_FF_2_helper(____0); } #[no_mangle] -pub unsafe extern "C" fn instr32_FF_2_reg(mut r1: i32) -> () { +pub unsafe fn instr32_FF_2_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); instr32_FF_2_helper(____0); } #[no_mangle] -pub unsafe extern "C" fn instr32_FF_3_reg(mut r: i32) -> () { +pub unsafe fn instr32_FF_3_reg(mut r: i32) -> () { dbg_log_c!("callf #ud"); trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr32_FF_3_mem(mut addr: i32) -> () { +pub unsafe fn instr32_FF_3_mem(mut addr: i32) -> () { c_comment!(("callf")); let mut new_ip: i32 = return_on_pagefault!(safe_read32s(addr)); let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 4i32)); @@ -3673,28 +3611,28 @@ pub unsafe extern "C" fn instr32_FF_3_mem(mut addr: i32) -> () { dbg_assert!(0 != is_asize_32() as i32 || new_ip < 65536i32); } #[no_mangle] -pub unsafe extern "C" fn instr32_FF_4_helper(mut data: i32) -> () { +pub unsafe fn instr32_FF_4_helper(mut data: i32) -> () { c_comment!(("jmp near")); dbg_assert!(0 != is_asize_32() as i32 || data < 65536i32); *instruction_pointer.offset(0isize) = get_seg_cs() + data; } #[no_mangle] -pub unsafe extern "C" fn instr32_FF_4_mem(mut addr: i32) -> () { +pub unsafe fn instr32_FF_4_mem(mut addr: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); instr32_FF_4_helper(____0); } #[no_mangle] -pub unsafe extern "C" fn instr32_FF_4_reg(mut r1: i32) -> () { +pub unsafe fn instr32_FF_4_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); instr32_FF_4_helper(____0); } #[no_mangle] -pub unsafe extern "C" fn instr32_FF_5_reg(mut r: i32) -> () { +pub unsafe fn instr32_FF_5_reg(mut r: i32) -> () { dbg_log_c!("jmpf #ud"); trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr32_FF_5_mem(mut addr: i32) -> () { +pub unsafe fn instr32_FF_5_mem(mut addr: i32) -> () { c_comment!(("jmpf")); let mut new_ip: i32 = return_on_pagefault!(safe_read32s(addr)); let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 4i32)); @@ -3707,279 +3645,279 @@ pub unsafe extern "C" fn instr32_FF_5_mem(mut addr: i32) -> () { dbg_assert!(0 != is_asize_32() as i32 || new_ip < 65536i32); } #[no_mangle] -pub unsafe extern "C" fn instr32_FF_6_mem(mut addr: i32) -> () { +pub unsafe fn instr32_FF_6_mem(mut addr: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); return_on_pagefault!(push32(____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_FF_6_reg(mut r1: i32) -> () { +pub unsafe fn instr32_FF_6_reg(mut r1: i32) -> () { let mut ____0: i32 = read_reg32(r1); return_on_pagefault!(push32(____0)); } #[no_mangle] -pub unsafe extern "C" fn instr_F26C() -> () { insb_rep(); } +pub unsafe fn instr_F26C() -> () { insb_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr_F36C() -> () { insb_rep(); } +pub unsafe fn instr_F36C() -> () { insb_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr16_F26D() -> () { insw_rep(); } +pub unsafe fn instr16_F26D() -> () { insw_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr16_F36D() -> () { insw_rep(); } +pub unsafe fn instr16_F36D() -> () { insw_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr32_F26D() -> () { insd_rep(); } +pub unsafe fn instr32_F26D() -> () { insd_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr32_F36D() -> () { insd_rep(); } +pub unsafe fn instr32_F36D() -> () { insd_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr_F26E() -> () { outsb_rep(); } +pub unsafe fn instr_F26E() -> () { outsb_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr_F36E() -> () { outsb_rep(); } +pub unsafe fn instr_F36E() -> () { outsb_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr16_F26F() -> () { outsw_rep(); } +pub unsafe fn instr16_F26F() -> () { outsw_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr16_F36F() -> () { outsw_rep(); } +pub unsafe fn instr16_F36F() -> () { outsw_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr32_F26F() -> () { outsd_rep(); } +pub unsafe fn instr32_F26F() -> () { outsd_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr32_F36F() -> () { outsd_rep(); } +pub unsafe fn instr32_F36F() -> () { outsd_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr16_70(mut imm8: i32) -> () { jmpcc16(test_o(), imm8); } +pub unsafe fn instr16_70(mut imm8: i32) -> () { jmpcc16(test_o(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr16_71(mut imm8: i32) -> () { jmpcc16(!test_o(), imm8); } +pub unsafe fn instr16_71(mut imm8: i32) -> () { jmpcc16(!test_o(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr16_72(mut imm8: i32) -> () { jmpcc16(test_b(), imm8); } +pub unsafe fn instr16_72(mut imm8: i32) -> () { jmpcc16(test_b(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr16_73(mut imm8: i32) -> () { jmpcc16(!test_b(), imm8); } +pub unsafe fn instr16_73(mut imm8: i32) -> () { jmpcc16(!test_b(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr16_74(mut imm8: i32) -> () { jmpcc16(test_z(), imm8); } +pub unsafe fn instr16_74(mut imm8: i32) -> () { jmpcc16(test_z(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr16_75(mut imm8: i32) -> () { jmpcc16(!test_z(), imm8); } +pub unsafe fn instr16_75(mut imm8: i32) -> () { jmpcc16(!test_z(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr16_76(mut imm8: i32) -> () { jmpcc16(test_be(), imm8); } +pub unsafe fn instr16_76(mut imm8: i32) -> () { jmpcc16(test_be(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr16_77(mut imm8: i32) -> () { jmpcc16(!test_be(), imm8); } +pub unsafe fn instr16_77(mut imm8: i32) -> () { jmpcc16(!test_be(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr16_78(mut imm8: i32) -> () { jmpcc16(test_s(), imm8); } +pub unsafe fn instr16_78(mut imm8: i32) -> () { jmpcc16(test_s(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr16_79(mut imm8: i32) -> () { jmpcc16(!test_s(), imm8); } +pub unsafe fn instr16_79(mut imm8: i32) -> () { jmpcc16(!test_s(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr16_7A(mut imm8: i32) -> () { jmpcc16(test_p(), imm8); } +pub unsafe fn instr16_7A(mut imm8: i32) -> () { jmpcc16(test_p(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr16_7B(mut imm8: i32) -> () { jmpcc16(!test_p(), imm8); } +pub unsafe fn instr16_7B(mut imm8: i32) -> () { jmpcc16(!test_p(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr16_7C(mut imm8: i32) -> () { jmpcc16(test_l(), imm8); } +pub unsafe fn instr16_7C(mut imm8: i32) -> () { jmpcc16(test_l(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr16_7D(mut imm8: i32) -> () { jmpcc16(!test_l(), imm8); } +pub unsafe fn instr16_7D(mut imm8: i32) -> () { jmpcc16(!test_l(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr16_7E(mut imm8: i32) -> () { jmpcc16(test_le(), imm8); } +pub unsafe fn instr16_7E(mut imm8: i32) -> () { jmpcc16(test_le(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr16_7F(mut imm8: i32) -> () { jmpcc16(!test_le(), imm8); } +pub unsafe fn instr16_7F(mut imm8: i32) -> () { jmpcc16(!test_le(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr32_70(mut imm8: i32) -> () { jmpcc32(test_o(), imm8); } +pub unsafe fn instr32_70(mut imm8: i32) -> () { jmpcc32(test_o(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr32_71(mut imm8: i32) -> () { jmpcc32(!test_o(), imm8); } +pub unsafe fn instr32_71(mut imm8: i32) -> () { jmpcc32(!test_o(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr32_72(mut imm8: i32) -> () { jmpcc32(test_b(), imm8); } +pub unsafe fn instr32_72(mut imm8: i32) -> () { jmpcc32(test_b(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr32_73(mut imm8: i32) -> () { jmpcc32(!test_b(), imm8); } +pub unsafe fn instr32_73(mut imm8: i32) -> () { jmpcc32(!test_b(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr32_74(mut imm8: i32) -> () { jmpcc32(test_z(), imm8); } +pub unsafe fn instr32_74(mut imm8: i32) -> () { jmpcc32(test_z(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr32_75(mut imm8: i32) -> () { jmpcc32(!test_z(), imm8); } +pub unsafe fn instr32_75(mut imm8: i32) -> () { jmpcc32(!test_z(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr32_76(mut imm8: i32) -> () { jmpcc32(test_be(), imm8); } +pub unsafe fn instr32_76(mut imm8: i32) -> () { jmpcc32(test_be(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr32_77(mut imm8: i32) -> () { jmpcc32(!test_be(), imm8); } +pub unsafe fn instr32_77(mut imm8: i32) -> () { jmpcc32(!test_be(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr32_78(mut imm8: i32) -> () { jmpcc32(test_s(), imm8); } +pub unsafe fn instr32_78(mut imm8: i32) -> () { jmpcc32(test_s(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr32_79(mut imm8: i32) -> () { jmpcc32(!test_s(), imm8); } +pub unsafe fn instr32_79(mut imm8: i32) -> () { jmpcc32(!test_s(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr32_7A(mut imm8: i32) -> () { jmpcc32(test_p(), imm8); } +pub unsafe fn instr32_7A(mut imm8: i32) -> () { jmpcc32(test_p(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr32_7B(mut imm8: i32) -> () { jmpcc32(!test_p(), imm8); } +pub unsafe fn instr32_7B(mut imm8: i32) -> () { jmpcc32(!test_p(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr32_7C(mut imm8: i32) -> () { jmpcc32(test_l(), imm8); } +pub unsafe fn instr32_7C(mut imm8: i32) -> () { jmpcc32(test_l(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr32_7D(mut imm8: i32) -> () { jmpcc32(!test_l(), imm8); } +pub unsafe fn instr32_7D(mut imm8: i32) -> () { jmpcc32(!test_l(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr32_7E(mut imm8: i32) -> () { jmpcc32(test_le(), imm8); } +pub unsafe fn instr32_7E(mut imm8: i32) -> () { jmpcc32(test_le(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr32_7F(mut imm8: i32) -> () { jmpcc32(!test_le(), imm8); } +pub unsafe fn instr32_7F(mut imm8: i32) -> () { jmpcc32(!test_le(), imm8); } #[no_mangle] -pub unsafe extern "C" fn instr_F2A4() -> () { movsb_rep(); } +pub unsafe fn instr_F2A4() -> () { movsb_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr_F3A4() -> () { movsb_rep(); } +pub unsafe fn instr_F3A4() -> () { movsb_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr16_F2A5() -> () { movsw_rep(); } +pub unsafe fn instr16_F2A5() -> () { movsw_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr16_F3A5() -> () { movsw_rep(); } +pub unsafe fn instr16_F3A5() -> () { movsw_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr32_F2A5() -> () { movsd_rep(); } +pub unsafe fn instr32_F2A5() -> () { movsd_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr32_F3A5() -> () { movsd_rep(); } +pub unsafe fn instr32_F3A5() -> () { movsd_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr_F2A6() -> () { cmpsb_rep(PREFIX_F2); } +pub unsafe fn instr_F2A6() -> () { cmpsb_rep(PREFIX_F2); } #[no_mangle] -pub unsafe extern "C" fn instr_F3A6() -> () { cmpsb_rep(PREFIX_F3); } +pub unsafe fn instr_F3A6() -> () { cmpsb_rep(PREFIX_F3); } #[no_mangle] -pub unsafe extern "C" fn instr16_F2A7() -> () { cmpsw_rep(PREFIX_F2); } +pub unsafe fn instr16_F2A7() -> () { cmpsw_rep(PREFIX_F2); } #[no_mangle] -pub unsafe extern "C" fn instr16_F3A7() -> () { cmpsw_rep(PREFIX_F3); } +pub unsafe fn instr16_F3A7() -> () { cmpsw_rep(PREFIX_F3); } #[no_mangle] -pub unsafe extern "C" fn instr32_F2A7() -> () { cmpsd_rep(PREFIX_F2); } +pub unsafe fn instr32_F2A7() -> () { cmpsd_rep(PREFIX_F2); } #[no_mangle] -pub unsafe extern "C" fn instr32_F3A7() -> () { cmpsd_rep(PREFIX_F3); } +pub unsafe fn instr32_F3A7() -> () { cmpsd_rep(PREFIX_F3); } #[no_mangle] -pub unsafe extern "C" fn instr_F2AA() -> () { stosb_rep(); } +pub unsafe fn instr_F2AA() -> () { stosb_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr_F3AA() -> () { stosb_rep(); } +pub unsafe fn instr_F3AA() -> () { stosb_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr16_F2AB() -> () { stosw_rep(); } +pub unsafe fn instr16_F2AB() -> () { stosw_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr16_F3AB() -> () { stosw_rep(); } +pub unsafe fn instr16_F3AB() -> () { stosw_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr32_F2AB() -> () { stosd_rep(); } +pub unsafe fn instr32_F2AB() -> () { stosd_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr32_F3AB() -> () { stosd_rep(); } +pub unsafe fn instr32_F3AB() -> () { stosd_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr_F2AC() -> () { lodsb_rep(); } +pub unsafe fn instr_F2AC() -> () { lodsb_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr_F3AC() -> () { lodsb_rep(); } +pub unsafe fn instr_F3AC() -> () { lodsb_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr16_F2AD() -> () { lodsw_rep(); } +pub unsafe fn instr16_F2AD() -> () { lodsw_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr16_F3AD() -> () { lodsw_rep(); } +pub unsafe fn instr16_F3AD() -> () { lodsw_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr32_F2AD() -> () { lodsd_rep(); } +pub unsafe fn instr32_F2AD() -> () { lodsd_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr32_F3AD() -> () { lodsd_rep(); } +pub unsafe fn instr32_F3AD() -> () { lodsd_rep(); } #[no_mangle] -pub unsafe extern "C" fn instr_F2AE() -> () { scasb_rep(PREFIX_F2); } +pub unsafe fn instr_F2AE() -> () { scasb_rep(PREFIX_F2); } #[no_mangle] -pub unsafe extern "C" fn instr_F3AE() -> () { scasb_rep(PREFIX_F3); } +pub unsafe fn instr_F3AE() -> () { scasb_rep(PREFIX_F3); } #[no_mangle] -pub unsafe extern "C" fn instr16_F2AF() -> () { scasw_rep(PREFIX_F2); } +pub unsafe fn instr16_F2AF() -> () { scasw_rep(PREFIX_F2); } #[no_mangle] -pub unsafe extern "C" fn instr16_F3AF() -> () { scasw_rep(PREFIX_F3); } +pub unsafe fn instr16_F3AF() -> () { scasw_rep(PREFIX_F3); } #[no_mangle] -pub unsafe extern "C" fn instr32_F2AF() -> () { scasd_rep(PREFIX_F2); } +pub unsafe fn instr32_F2AF() -> () { scasd_rep(PREFIX_F2); } #[no_mangle] -pub unsafe extern "C" fn instr32_F3AF() -> () { scasd_rep(PREFIX_F3); } +pub unsafe fn instr32_F3AF() -> () { scasd_rep(PREFIX_F3); } #[no_mangle] -pub unsafe extern "C" fn instr_D8_0_mem(mut addr: i32) -> () { +pub unsafe fn instr_D8_0_mem(mut addr: i32) -> () { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fadd(0i32, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr_D8_0_reg(mut r: i32) -> () { +pub unsafe fn instr_D8_0_reg(mut r: i32) -> () { let mut ____0: f64 = fpu_get_sti(r); fpu_fadd(0i32, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr_D8_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_D8_1_mem(mut addr: i32) -> () { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fmul(0i32, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr_D8_1_reg(mut r: i32) -> () { +pub unsafe fn instr_D8_1_reg(mut r: i32) -> () { let mut ____0: f64 = fpu_get_sti(r); fpu_fmul(0i32, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr_D8_2_mem(mut addr: i32) -> () { +pub unsafe fn instr_D8_2_mem(mut addr: i32) -> () { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fcom(____0); } #[no_mangle] -pub unsafe extern "C" fn instr_D8_2_reg(mut r: i32) -> () { +pub unsafe fn instr_D8_2_reg(mut r: i32) -> () { let mut ____0: f64 = fpu_get_sti(r); fpu_fcom(____0); } #[no_mangle] -pub unsafe extern "C" fn instr_D8_3_mem(mut addr: i32) -> () { +pub unsafe fn instr_D8_3_mem(mut addr: i32) -> () { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fcomp(____0); } #[no_mangle] -pub unsafe extern "C" fn instr_D8_3_reg(mut r: i32) -> () { +pub unsafe fn instr_D8_3_reg(mut r: i32) -> () { let mut ____0: f64 = fpu_get_sti(r); fpu_fcomp(____0); } #[no_mangle] -pub unsafe extern "C" fn instr_D8_4_mem(mut addr: i32) -> () { +pub unsafe fn instr_D8_4_mem(mut addr: i32) -> () { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fsub(0i32, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr_D8_4_reg(mut r: i32) -> () { +pub unsafe fn instr_D8_4_reg(mut r: i32) -> () { let mut ____0: f64 = fpu_get_sti(r); fpu_fsub(0i32, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr_D8_5_mem(mut addr: i32) -> () { +pub unsafe fn instr_D8_5_mem(mut addr: i32) -> () { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fsubr(0i32, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr_D8_5_reg(mut r: i32) -> () { +pub unsafe fn instr_D8_5_reg(mut r: i32) -> () { let mut ____0: f64 = fpu_get_sti(r); fpu_fsubr(0i32, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr_D8_6_mem(mut addr: i32) -> () { +pub unsafe fn instr_D8_6_mem(mut addr: i32) -> () { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fdiv(0i32, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr_D8_6_reg(mut r: i32) -> () { +pub unsafe fn instr_D8_6_reg(mut r: i32) -> () { let mut ____0: f64 = fpu_get_sti(r); fpu_fdiv(0i32, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr_D8_7_mem(mut addr: i32) -> () { +pub unsafe fn instr_D8_7_mem(mut addr: i32) -> () { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fdivr(0i32, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr_D8_7_reg(mut r: i32) -> () { +pub unsafe fn instr_D8_7_reg(mut r: i32) -> () { let mut ____0: f64 = fpu_get_sti(r); fpu_fdivr(0i32, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr_D9_0_mem(mut addr: i32) -> () { +pub unsafe fn instr_D9_0_mem(mut addr: i32) -> () { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_push(____0); } #[no_mangle] -pub unsafe extern "C" fn instr_D9_0_reg(mut r: i32) -> () { +pub unsafe fn instr_D9_0_reg(mut r: i32) -> () { let mut ____0: f64 = fpu_get_sti(r); fpu_push(____0); } #[no_mangle] -pub unsafe extern "C" fn instr_D9_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_D9_1_mem(mut addr: i32) -> () { dbg_log_c!("d9/1"); trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_D9_1_reg(mut r: i32) -> () { fpu_fxch(r); } +pub unsafe fn instr_D9_1_reg(mut r: i32) -> () { fpu_fxch(r); } #[no_mangle] -pub unsafe extern "C" fn instr_D9_2_mem(mut addr: i32) -> () { fpu_fstm32(addr); } +pub unsafe fn instr_D9_2_mem(mut addr: i32) -> () { fpu_fstm32(addr); } #[no_mangle] -pub unsafe extern "C" fn instr_D9_2_reg(mut r: i32) -> () { +pub unsafe fn instr_D9_2_reg(mut r: i32) -> () { if r != 0i32 { trigger_ud(); }; } #[no_mangle] -pub unsafe extern "C" fn instr_D9_3_mem(mut addr: i32) -> () { fpu_fstm32p(addr); } +pub unsafe fn instr_D9_3_mem(mut addr: i32) -> () { fpu_fstm32p(addr); } #[no_mangle] -pub unsafe extern "C" fn instr_D9_3_reg(mut r: i32) -> () { +pub unsafe fn instr_D9_3_reg(mut r: i32) -> () { dbg_log_c!("fstp1"); trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_D9_4_mem(mut addr: i32) -> () { fpu_fldenv(addr); } +pub unsafe fn instr_D9_4_mem(mut addr: i32) -> () { fpu_fldenv(addr); } #[no_mangle] -pub unsafe extern "C" fn instr_D9_4_reg(mut r: i32) -> () { +pub unsafe fn instr_D9_4_reg(mut r: i32) -> () { let mut st0: f64 = fpu_get_st0(); match r { 0 => { @@ -4003,9 +3941,9 @@ pub unsafe extern "C" fn instr_D9_4_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_D9_5_mem(mut addr: i32) -> () { fpu_fldcw(addr); } +pub unsafe fn instr_D9_5_mem(mut addr: i32) -> () { fpu_fldcw(addr); } #[no_mangle] -pub unsafe extern "C" fn instr_D9_5_reg(mut r: i32) -> () { +pub unsafe fn instr_D9_5_reg(mut r: i32) -> () { c_comment!(("fld1/fldl2t/fldl2e/fldpi/fldlg2/fldln2/fldz")); match r { 0 => { @@ -4037,9 +3975,9 @@ pub unsafe extern "C" fn instr_D9_5_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_D9_6_mem(mut addr: i32) -> () { fpu_fstenv(addr); } +pub unsafe fn instr_D9_6_mem(mut addr: i32) -> () { fpu_fstenv(addr); } #[no_mangle] -pub unsafe extern "C" fn instr_D9_6_reg(mut r: i32) -> () { +pub unsafe fn instr_D9_6_reg(mut r: i32) -> () { let mut st0: f64 = fpu_get_st0(); match r { 0 => { @@ -4087,9 +4025,9 @@ pub unsafe extern "C" fn instr_D9_6_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_D9_7_mem(mut addr: i32) -> () { fpu_fstcw(addr); } +pub unsafe fn instr_D9_7_mem(mut addr: i32) -> () { fpu_fstcw(addr); } #[no_mangle] -pub unsafe extern "C" fn instr_D9_7_reg(mut r: i32) -> () { +pub unsafe fn instr_D9_7_reg(mut r: i32) -> () { let mut st0: f64 = fpu_get_st0(); match r { 0 => { @@ -4123,49 +4061,49 @@ pub unsafe extern "C" fn instr_D9_7_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_DA_0_mem(mut addr: i32) -> () { +pub unsafe fn instr_DA_0_mem(mut addr: i32) -> () { fpu_fadd(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe extern "C" fn instr_DA_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_DA_1_mem(mut addr: i32) -> () { fpu_fmul(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe extern "C" fn instr_DA_2_mem(mut addr: i32) -> () { +pub unsafe fn instr_DA_2_mem(mut addr: i32) -> () { fpu_fcom(return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe extern "C" fn instr_DA_3_mem(mut addr: i32) -> () { +pub unsafe fn instr_DA_3_mem(mut addr: i32) -> () { fpu_fcomp(return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe extern "C" fn instr_DA_4_mem(mut addr: i32) -> () { +pub unsafe fn instr_DA_4_mem(mut addr: i32) -> () { fpu_fsub(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe extern "C" fn instr_DA_5_mem(mut addr: i32) -> () { +pub unsafe fn instr_DA_5_mem(mut addr: i32) -> () { fpu_fsubr(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe extern "C" fn instr_DA_6_mem(mut addr: i32) -> () { +pub unsafe fn instr_DA_6_mem(mut addr: i32) -> () { fpu_fdiv(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe extern "C" fn instr_DA_7_mem(mut addr: i32) -> () { +pub unsafe fn instr_DA_7_mem(mut addr: i32) -> () { fpu_fdivr(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe extern "C" fn instr_DA_0_reg(mut r: i32) -> () { fpu_fcmovcc(test_b(), r); } +pub unsafe fn instr_DA_0_reg(mut r: i32) -> () { fpu_fcmovcc(test_b(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_DA_1_reg(mut r: i32) -> () { fpu_fcmovcc(test_z(), r); } +pub unsafe fn instr_DA_1_reg(mut r: i32) -> () { fpu_fcmovcc(test_z(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_DA_2_reg(mut r: i32) -> () { fpu_fcmovcc(test_be(), r); } +pub unsafe fn instr_DA_2_reg(mut r: i32) -> () { fpu_fcmovcc(test_be(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_DA_3_reg(mut r: i32) -> () { fpu_fcmovcc(test_p(), r); } +pub unsafe fn instr_DA_3_reg(mut r: i32) -> () { fpu_fcmovcc(test_p(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_DA_4_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DA_4_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_DA_5_reg(mut r: i32) -> () { +pub unsafe fn instr_DA_5_reg(mut r: i32) -> () { if r == 1i32 { fpu_fucompp(); } @@ -4174,35 +4112,35 @@ pub unsafe extern "C" fn instr_DA_5_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_DA_6_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DA_6_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_DA_7_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DA_7_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_DB_0_mem(mut addr: i32) -> () { fpu_fldm32(addr); } +pub unsafe fn instr_DB_0_mem(mut addr: i32) -> () { fpu_fldm32(addr); } #[no_mangle] -pub unsafe extern "C" fn instr_DB_1_mem(mut addr: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DB_1_mem(mut addr: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_DB_2_mem(mut addr: i32) -> () { fpu_fistm32(addr); } +pub unsafe fn instr_DB_2_mem(mut addr: i32) -> () { fpu_fistm32(addr); } #[no_mangle] -pub unsafe extern "C" fn instr_DB_3_mem(mut addr: i32) -> () { fpu_fistm32p(addr); } +pub unsafe fn instr_DB_3_mem(mut addr: i32) -> () { fpu_fistm32p(addr); } #[no_mangle] -pub unsafe extern "C" fn instr_DB_4_mem(mut addr: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DB_4_mem(mut addr: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_DB_5_mem(mut addr: i32) -> () { fpu_fldm80(addr); } +pub unsafe fn instr_DB_5_mem(mut addr: i32) -> () { fpu_fldm80(addr); } #[no_mangle] -pub unsafe extern "C" fn instr_DB_6_mem(mut addr: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DB_6_mem(mut addr: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_DB_7_mem(mut addr: i32) -> () { fpu_fst80p(addr); } +pub unsafe fn instr_DB_7_mem(mut addr: i32) -> () { fpu_fst80p(addr); } #[no_mangle] -pub unsafe extern "C" fn instr_DB_0_reg(mut r: i32) -> () { fpu_fcmovcc(!test_b(), r); } +pub unsafe fn instr_DB_0_reg(mut r: i32) -> () { fpu_fcmovcc(!test_b(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_DB_1_reg(mut r: i32) -> () { fpu_fcmovcc(!test_z(), r); } +pub unsafe fn instr_DB_1_reg(mut r: i32) -> () { fpu_fcmovcc(!test_z(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_DB_2_reg(mut r: i32) -> () { fpu_fcmovcc(!test_be(), r); } +pub unsafe fn instr_DB_2_reg(mut r: i32) -> () { fpu_fcmovcc(!test_be(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_DB_3_reg(mut r: i32) -> () { fpu_fcmovcc(!test_p(), r); } +pub unsafe fn instr_DB_3_reg(mut r: i32) -> () { fpu_fcmovcc(!test_p(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_DB_4_reg(mut r: i32) -> () { +pub unsafe fn instr_DB_4_reg(mut r: i32) -> () { if r == 3i32 { fpu_finit(); } @@ -4217,206 +4155,206 @@ pub unsafe extern "C" fn instr_DB_4_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_DB_5_reg(mut r: i32) -> () { fpu_fucomi(r); } +pub unsafe fn instr_DB_5_reg(mut r: i32) -> () { fpu_fucomi(r); } #[no_mangle] -pub unsafe extern "C" fn instr_DB_6_reg(mut r: i32) -> () { fpu_fcomi(r); } +pub unsafe fn instr_DB_6_reg(mut r: i32) -> () { fpu_fcomi(r); } #[no_mangle] -pub unsafe extern "C" fn instr_DB_7_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DB_7_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_DC_0_mem(mut addr: i32) -> () { +pub unsafe fn instr_DC_0_mem(mut addr: i32) -> () { fpu_fadd(0i32, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe extern "C" fn instr_DC_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_DC_1_mem(mut addr: i32) -> () { fpu_fmul(0i32, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe extern "C" fn instr_DC_2_mem(mut addr: i32) -> () { +pub unsafe fn instr_DC_2_mem(mut addr: i32) -> () { fpu_fcom(return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe extern "C" fn instr_DC_3_mem(mut addr: i32) -> () { +pub unsafe fn instr_DC_3_mem(mut addr: i32) -> () { fpu_fcomp(return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe extern "C" fn instr_DC_4_mem(mut addr: i32) -> () { +pub unsafe fn instr_DC_4_mem(mut addr: i32) -> () { fpu_fsub(0i32, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe extern "C" fn instr_DC_5_mem(mut addr: i32) -> () { +pub unsafe fn instr_DC_5_mem(mut addr: i32) -> () { fpu_fsubr(0i32, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe extern "C" fn instr_DC_6_mem(mut addr: i32) -> () { +pub unsafe fn instr_DC_6_mem(mut addr: i32) -> () { fpu_fdiv(0i32, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe extern "C" fn instr_DC_7_mem(mut addr: i32) -> () { +pub unsafe fn instr_DC_7_mem(mut addr: i32) -> () { fpu_fdivr(0i32, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe extern "C" fn instr_DC_0_reg(mut r: i32) -> () { fpu_fadd(r, fpu_get_sti(r)); } +pub unsafe fn instr_DC_0_reg(mut r: i32) -> () { fpu_fadd(r, fpu_get_sti(r)); } #[no_mangle] -pub unsafe extern "C" fn instr_DC_1_reg(mut r: i32) -> () { fpu_fmul(r, fpu_get_sti(r)); } +pub unsafe fn instr_DC_1_reg(mut r: i32) -> () { fpu_fmul(r, fpu_get_sti(r)); } #[no_mangle] -pub unsafe extern "C" fn instr_DC_2_reg(mut r: i32) -> () { fpu_fcom(fpu_get_sti(r)); } +pub unsafe fn instr_DC_2_reg(mut r: i32) -> () { fpu_fcom(fpu_get_sti(r)); } #[no_mangle] -pub unsafe extern "C" fn instr_DC_3_reg(mut r: i32) -> () { fpu_fcomp(fpu_get_sti(r)); } +pub unsafe fn instr_DC_3_reg(mut r: i32) -> () { fpu_fcomp(fpu_get_sti(r)); } #[no_mangle] -pub unsafe extern "C" fn instr_DC_4_reg(mut r: i32) -> () { fpu_fsub(r, fpu_get_sti(r)); } +pub unsafe fn instr_DC_4_reg(mut r: i32) -> () { fpu_fsub(r, fpu_get_sti(r)); } #[no_mangle] -pub unsafe extern "C" fn instr_DC_5_reg(mut r: i32) -> () { fpu_fsubr(r, fpu_get_sti(r)); } +pub unsafe fn instr_DC_5_reg(mut r: i32) -> () { fpu_fsubr(r, fpu_get_sti(r)); } #[no_mangle] -pub unsafe extern "C" fn instr_DC_6_reg(mut r: i32) -> () { fpu_fdiv(r, fpu_get_sti(r)); } +pub unsafe fn instr_DC_6_reg(mut r: i32) -> () { fpu_fdiv(r, fpu_get_sti(r)); } #[no_mangle] -pub unsafe extern "C" fn instr_DC_7_reg(mut r: i32) -> () { fpu_fdivr(r, fpu_get_sti(r)); } +pub unsafe fn instr_DC_7_reg(mut r: i32) -> () { fpu_fdivr(r, fpu_get_sti(r)); } #[no_mangle] -pub unsafe extern "C" fn instr_DD_0_mem(mut addr: i32) -> () { fpu_fldm64(addr); } +pub unsafe fn instr_DD_0_mem(mut addr: i32) -> () { fpu_fldm64(addr); } #[no_mangle] -pub unsafe extern "C" fn instr_DD_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_DD_1_mem(mut addr: i32) -> () { dbg_log_c!("fisttp"); trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_DD_2_mem(mut addr: i32) -> () { fpu_fstm64(addr); } +pub unsafe fn instr_DD_2_mem(mut addr: i32) -> () { fpu_fstm64(addr); } #[no_mangle] -pub unsafe extern "C" fn instr_DD_3_mem(mut addr: i32) -> () { fpu_fstm64p(addr); } +pub unsafe fn instr_DD_3_mem(mut addr: i32) -> () { fpu_fstm64p(addr); } #[no_mangle] -pub unsafe extern "C" fn instr_DD_4_mem(mut addr: i32) -> () { fpu_frstor(addr); } +pub unsafe fn instr_DD_4_mem(mut addr: i32) -> () { fpu_frstor(addr); } #[no_mangle] -pub unsafe extern "C" fn instr_DD_5_mem(mut addr: i32) -> () { +pub unsafe fn instr_DD_5_mem(mut addr: i32) -> () { dbg_log_c!("dd/5"); trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_DD_6_mem(mut addr: i32) -> () { fpu_fsave(addr); } +pub unsafe fn instr_DD_6_mem(mut addr: i32) -> () { fpu_fsave(addr); } #[no_mangle] -pub unsafe extern "C" fn instr_DD_7_mem(mut addr: i32) -> () { fpu_fnstsw_mem(addr); } +pub unsafe fn instr_DD_7_mem(mut addr: i32) -> () { fpu_fnstsw_mem(addr); } #[no_mangle] -pub unsafe extern "C" fn instr_DD_0_reg(mut r: i32) -> () { fpu_ffree(r); } +pub unsafe fn instr_DD_0_reg(mut r: i32) -> () { fpu_ffree(r); } #[no_mangle] -pub unsafe extern "C" fn instr_DD_1_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DD_1_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_DD_2_reg(mut r: i32) -> () { fpu_fst(r); } +pub unsafe fn instr_DD_2_reg(mut r: i32) -> () { fpu_fst(r); } #[no_mangle] -pub unsafe extern "C" fn instr_DD_3_reg(mut r: i32) -> () { fpu_fstp(r); } +pub unsafe fn instr_DD_3_reg(mut r: i32) -> () { fpu_fstp(r); } #[no_mangle] -pub unsafe extern "C" fn instr_DD_4_reg(mut r: i32) -> () { fpu_fucom(r); } +pub unsafe fn instr_DD_4_reg(mut r: i32) -> () { fpu_fucom(r); } #[no_mangle] -pub unsafe extern "C" fn instr_DD_5_reg(mut r: i32) -> () { fpu_fucomp(r); } +pub unsafe fn instr_DD_5_reg(mut r: i32) -> () { fpu_fucomp(r); } #[no_mangle] -pub unsafe extern "C" fn instr_DD_6_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DD_6_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_DD_7_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DD_7_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_DE_0_mem(mut addr: i32) -> () { +pub unsafe fn instr_DE_0_mem(mut addr: i32) -> () { fpu_fadd(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe extern "C" fn instr_DE_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_DE_1_mem(mut addr: i32) -> () { fpu_fmul(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe extern "C" fn instr_DE_2_mem(mut addr: i32) -> () { +pub unsafe fn instr_DE_2_mem(mut addr: i32) -> () { fpu_fcom(return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe extern "C" fn instr_DE_3_mem(mut addr: i32) -> () { +pub unsafe fn instr_DE_3_mem(mut addr: i32) -> () { fpu_fcomp(return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe extern "C" fn instr_DE_4_mem(mut addr: i32) -> () { +pub unsafe fn instr_DE_4_mem(mut addr: i32) -> () { fpu_fsub(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe extern "C" fn instr_DE_5_mem(mut addr: i32) -> () { +pub unsafe fn instr_DE_5_mem(mut addr: i32) -> () { fpu_fsubr(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe extern "C" fn instr_DE_6_mem(mut addr: i32) -> () { +pub unsafe fn instr_DE_6_mem(mut addr: i32) -> () { fpu_fdiv(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe extern "C" fn instr_DE_7_mem(mut addr: i32) -> () { +pub unsafe fn instr_DE_7_mem(mut addr: i32) -> () { fpu_fdivr(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe extern "C" fn instr_DE_0_reg(mut r: i32) -> () { +pub unsafe fn instr_DE_0_reg(mut r: i32) -> () { fpu_fadd(r, fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe extern "C" fn instr_DE_1_reg(mut r: i32) -> () { +pub unsafe fn instr_DE_1_reg(mut r: i32) -> () { fpu_fmul(r, fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe extern "C" fn instr_DE_2_reg(mut r: i32) -> () { +pub unsafe fn instr_DE_2_reg(mut r: i32) -> () { fpu_fcom(fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe extern "C" fn instr_DE_3_reg(mut r: i32) -> () { +pub unsafe fn instr_DE_3_reg(mut r: i32) -> () { fpu_fcomp(fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe extern "C" fn instr_DE_4_reg(mut r: i32) -> () { +pub unsafe fn instr_DE_4_reg(mut r: i32) -> () { fpu_fsub(r, fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe extern "C" fn instr_DE_5_reg(mut r: i32) -> () { +pub unsafe fn instr_DE_5_reg(mut r: i32) -> () { fpu_fsubr(r, fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe extern "C" fn instr_DE_6_reg(mut r: i32) -> () { +pub unsafe fn instr_DE_6_reg(mut r: i32) -> () { fpu_fdiv(r, fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe extern "C" fn instr_DE_7_reg(mut r: i32) -> () { +pub unsafe fn instr_DE_7_reg(mut r: i32) -> () { fpu_fdivr(r, fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe extern "C" fn instr_DF_0_mem(mut addr: i32) -> () { +pub unsafe fn instr_DF_0_mem(mut addr: i32) -> () { fpu_push(return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe extern "C" fn instr_DF_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_DF_1_mem(mut addr: i32) -> () { dbg_log_c!("df/fisttp"); trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_DF_2_mem(mut addr: i32) -> () { fpu_fistm16(addr); } +pub unsafe fn instr_DF_2_mem(mut addr: i32) -> () { fpu_fistm16(addr); } #[no_mangle] -pub unsafe extern "C" fn instr_DF_3_mem(mut addr: i32) -> () { fpu_fistm16p(addr); } +pub unsafe fn instr_DF_3_mem(mut addr: i32) -> () { fpu_fistm16p(addr); } #[no_mangle] -pub unsafe extern "C" fn instr_DF_4_mem(mut addr: i32) -> () { +pub unsafe fn instr_DF_4_mem(mut addr: i32) -> () { dbg_log_c!("fbld"); trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_DF_5_mem(mut addr: i32) -> () { fpu_fildm64(addr); } +pub unsafe fn instr_DF_5_mem(mut addr: i32) -> () { fpu_fildm64(addr); } #[no_mangle] -pub unsafe extern "C" fn instr_DF_6_mem(mut addr: i32) -> () { +pub unsafe fn instr_DF_6_mem(mut addr: i32) -> () { dbg_log_c!("fbstp"); trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_DF_7_mem(mut addr: i32) -> () { fpu_fistm64p(addr); } +pub unsafe fn instr_DF_7_mem(mut addr: i32) -> () { fpu_fistm64p(addr); } #[no_mangle] -pub unsafe extern "C" fn instr_DF_0_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DF_0_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_DF_1_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DF_1_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_DF_2_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DF_2_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_DF_3_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DF_3_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_DF_4_reg(mut r: i32) -> () { +pub unsafe fn instr_DF_4_reg(mut r: i32) -> () { if r == 0i32 { fpu_fnstsw_reg(); } @@ -4425,35 +4363,35 @@ pub unsafe extern "C" fn instr_DF_4_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_DF_5_reg(mut r: i32) -> () { fpu_fucomip(r); } +pub unsafe fn instr_DF_5_reg(mut r: i32) -> () { fpu_fucomip(r); } #[no_mangle] -pub unsafe extern "C" fn instr_DF_6_reg(mut r: i32) -> () { fpu_fcomip(r); } +pub unsafe fn instr_DF_6_reg(mut r: i32) -> () { fpu_fcomip(r); } #[no_mangle] -pub unsafe extern "C" fn instr_DF_7_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DF_7_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr16_E0(mut imm8s: i32) -> () { loopne16(imm8s); } +pub unsafe fn instr16_E0(mut imm8s: i32) -> () { loopne16(imm8s); } #[no_mangle] -pub unsafe extern "C" fn instr16_E1(mut imm8s: i32) -> () { loope16(imm8s); } +pub unsafe fn instr16_E1(mut imm8s: i32) -> () { loope16(imm8s); } #[no_mangle] -pub unsafe extern "C" fn instr16_E2(mut imm8s: i32) -> () { loop16(imm8s); } +pub unsafe fn instr16_E2(mut imm8s: i32) -> () { loop16(imm8s); } #[no_mangle] -pub unsafe extern "C" fn instr16_E3(mut imm8s: i32) -> () { jcxz16(imm8s); } +pub unsafe fn instr16_E3(mut imm8s: i32) -> () { jcxz16(imm8s); } #[no_mangle] -pub unsafe extern "C" fn instr32_E0(mut imm8s: i32) -> () { loopne32(imm8s); } +pub unsafe fn instr32_E0(mut imm8s: i32) -> () { loopne32(imm8s); } #[no_mangle] -pub unsafe extern "C" fn instr32_E1(mut imm8s: i32) -> () { loope32(imm8s); } +pub unsafe fn instr32_E1(mut imm8s: i32) -> () { loope32(imm8s); } #[no_mangle] -pub unsafe extern "C" fn instr32_E2(mut imm8s: i32) -> () { loop32(imm8s); } +pub unsafe fn instr32_E2(mut imm8s: i32) -> () { loop32(imm8s); } #[no_mangle] -pub unsafe extern "C" fn instr32_E3(mut imm8s: i32) -> () { jcxz32(imm8s); } +pub unsafe fn instr32_E3(mut imm8s: i32) -> () { jcxz32(imm8s); } #[no_mangle] -pub unsafe extern "C" fn instr16_EB(mut imm8: i32) -> () { +pub unsafe fn instr16_EB(mut imm8: i32) -> () { c_comment!(("jmp near")); jmp_rel16(imm8); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe extern "C" fn instr32_EB(mut imm8: i32) -> () { +pub unsafe fn instr32_EB(mut imm8: i32) -> () { c_comment!(("jmp near")); *instruction_pointer.offset(0isize) = *instruction_pointer.offset(0isize) + imm8; dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 0b4b5706..fea92663 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -66,7 +66,7 @@ use cpu2::sse_instr::*; pub fn convert_f64_to_i32(x: f64) -> i32 { x as i32 } #[no_mangle] -pub unsafe extern "C" fn instr_0F00_0_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F00_0_mem(mut addr: i32) -> () { c_comment!(("sldt")); if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { trigger_ud(); @@ -78,7 +78,7 @@ pub unsafe extern "C" fn instr_0F00_0_mem(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F00_0_reg(mut r: i32) -> () { +pub unsafe fn instr_0F00_0_reg(mut r: i32) -> () { if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -89,7 +89,7 @@ pub unsafe extern "C" fn instr_0F00_0_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F00_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F00_1_mem(mut addr: i32) -> () { c_comment!(("str")); if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { trigger_ud(); @@ -101,7 +101,7 @@ pub unsafe extern "C" fn instr_0F00_1_mem(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F00_1_reg(mut r: i32) -> () { +pub unsafe fn instr_0F00_1_reg(mut r: i32) -> () { if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -112,7 +112,7 @@ pub unsafe extern "C" fn instr_0F00_1_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F00_2_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F00_2_mem(mut addr: i32) -> () { c_comment!(("lldt")); if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { trigger_ud(); @@ -128,7 +128,7 @@ pub unsafe extern "C" fn instr_0F00_2_mem(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F00_2_reg(mut r: i32) -> () { +pub unsafe fn instr_0F00_2_reg(mut r: i32) -> () { if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -143,7 +143,7 @@ pub unsafe extern "C" fn instr_0F00_2_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F00_3_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F00_3_mem(mut addr: i32) -> () { c_comment!(("ltr")); if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { trigger_ud(); @@ -159,7 +159,7 @@ pub unsafe extern "C" fn instr_0F00_3_mem(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F00_3_reg(mut r: i32) -> () { +pub unsafe fn instr_0F00_3_reg(mut r: i32) -> () { if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -174,7 +174,7 @@ pub unsafe extern "C" fn instr_0F00_3_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F00_4_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F00_4_mem(mut addr: i32) -> () { if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -185,7 +185,7 @@ pub unsafe extern "C" fn instr_0F00_4_mem(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F00_4_reg(mut r: i32) -> () { +pub unsafe fn instr_0F00_4_reg(mut r: i32) -> () { if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -196,7 +196,7 @@ pub unsafe extern "C" fn instr_0F00_4_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F00_5_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F00_5_mem(mut addr: i32) -> () { if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -207,7 +207,7 @@ pub unsafe extern "C" fn instr_0F00_5_mem(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F00_5_reg(mut r: i32) -> () { +pub unsafe fn instr_0F00_5_reg(mut r: i32) -> () { if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -218,9 +218,9 @@ pub unsafe extern "C" fn instr_0F00_5_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F01_0_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F01_0_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F01_0_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F01_0_mem(mut addr: i32) -> () { c_comment!(("sgdt")); return_on_pagefault!(writable_or_pagefault(addr, 6i32)); let mut mask: i32 = if 0 != is_osize_32() as i32 { @@ -233,9 +233,9 @@ pub unsafe extern "C" fn instr_0F01_0_mem(mut addr: i32) -> () { safe_write32(addr + 2i32, *gdtr_offset.offset(0isize) & mask).unwrap(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F01_1_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F01_1_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F01_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F01_1_mem(mut addr: i32) -> () { c_comment!(("sidt")); return_on_pagefault!(writable_or_pagefault(addr, 6i32)); let mut mask: i32 = if 0 != is_osize_32() as i32 { @@ -248,9 +248,9 @@ pub unsafe extern "C" fn instr_0F01_1_mem(mut addr: i32) -> () { safe_write32(addr + 2i32, *idtr_offset.offset(0isize) & mask).unwrap(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F01_2_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F01_2_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F01_2_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F01_2_mem(mut addr: i32) -> () { c_comment!(("lgdt")); if 0 != *cpl.offset(0isize) { trigger_gp_non_raising(0i32); @@ -271,9 +271,9 @@ pub unsafe extern "C" fn instr_0F01_2_mem(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F01_3_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F01_3_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F01_3_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F01_3_mem(mut addr: i32) -> () { c_comment!(("lidt")); if 0 != *cpl.offset(0isize) { trigger_gp_non_raising(0i32); @@ -294,16 +294,16 @@ pub unsafe extern "C" fn instr_0F01_3_mem(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F01_4_reg(mut r: i32) -> () { +pub unsafe fn instr_0F01_4_reg(mut r: i32) -> () { c_comment!(("smsw")); write_reg_osize(r, *cr.offset(0isize)); } #[no_mangle] -pub unsafe extern "C" fn instr_0F01_4_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F01_4_mem(mut addr: i32) -> () { return_on_pagefault!(safe_write16(addr, *cr.offset(0isize) & 65535i32)); } #[no_mangle] -pub unsafe extern "C" fn lmsw(mut new_cr0: i32) -> () { +pub unsafe fn lmsw(mut new_cr0: i32) -> () { new_cr0 = *cr.offset(0isize) & !15i32 | new_cr0 & 15i32; if *protected_mode.offset(0isize) { c_comment!(("lmsw cannot be used to switch back")); @@ -312,7 +312,7 @@ pub unsafe extern "C" fn lmsw(mut new_cr0: i32) -> () { set_cr0(new_cr0); } #[no_mangle] -pub unsafe extern "C" fn instr_0F01_6_reg(mut r: i32) -> () { +pub unsafe fn instr_0F01_6_reg(mut r: i32) -> () { if 0 != *cpl.offset(0isize) { trigger_gp_non_raising(0i32); return; @@ -323,7 +323,7 @@ pub unsafe extern "C" fn instr_0F01_6_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F01_6_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F01_6_mem(mut addr: i32) -> () { if 0 != *cpl.offset(0isize) { trigger_gp_non_raising(0i32); return; @@ -334,9 +334,9 @@ pub unsafe extern "C" fn instr_0F01_6_mem(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F01_7_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F01_7_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F01_7_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F01_7_mem(mut addr: i32) -> () { c_comment!(("invlpg")); if 0 != *cpl.offset(0isize) { trigger_gp_non_raising(0i32); @@ -348,51 +348,51 @@ pub unsafe extern "C" fn instr_0F01_7_mem(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr16_0F02_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F02_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, lar(____0, read_reg16(r))); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F02_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F02_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r, lar(____0, read_reg16(r))); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F02_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F02_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg32(r, lar(____0, read_reg32(r))); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F02_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F02_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg32(r, lar(____0, read_reg32(r))); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F03_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F03_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, lsl(____0, read_reg16(r))); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F03_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F03_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r, lsl(____0, read_reg16(r))); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F03_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F03_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg32(r, lsl(____0, read_reg32(r))); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F03_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F03_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg32(r, lsl(____0, read_reg32(r))); } #[no_mangle] -pub unsafe extern "C" fn instr_0F04() -> () { undefined_instruction(); } +pub unsafe fn instr_0F04() -> () { undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F05() -> () { undefined_instruction(); } +pub unsafe fn instr_0F05() -> () { undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F06() -> () { +pub unsafe fn instr_0F06() -> () { c_comment!(("clts")); if 0 != *cpl.offset(0isize) { dbg_log_c!("clts #gp"); @@ -407,14 +407,14 @@ pub unsafe extern "C" fn instr_0F06() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F07() -> () { undefined_instruction(); } +pub unsafe fn instr_0F07() -> () { undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F08() -> () { +pub unsafe fn instr_0F08() -> () { c_comment!(("invd")); undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F09() -> () { +pub unsafe fn instr_0F09() -> () { if 0 != *cpl.offset(0isize) { dbg_log_c!("wbinvd #gp"); trigger_gp_non_raising(0i32); @@ -424,38 +424,36 @@ pub unsafe extern "C" fn instr_0F09() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F0A() -> () { undefined_instruction(); } +pub unsafe fn instr_0F0A() -> () { undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F0B() -> () { +pub unsafe fn instr_0F0B() -> () { c_comment!(("UD2")); trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F0C() -> () { undefined_instruction(); } +pub unsafe fn instr_0F0C() -> () { undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F0D() -> () { +pub unsafe fn instr_0F0D() -> () { c_comment!(("nop")); undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F0E() -> () { undefined_instruction(); } +pub unsafe fn instr_0F0E() -> () { undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F0F() -> () { undefined_instruction(); } +pub unsafe fn instr_0F0F() -> () { undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F10(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F10(mut source: reg128, mut r: i32) -> () { c_comment!(("movups xmm, xmm/m128")); mov_rm_r128(source, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F10_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F10(read_xmm128s(r1), r2); -} +pub unsafe fn instr_0F10_reg(mut r1: i32, mut r2: i32) -> () { instr_0F10(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F10_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F10_mem(mut addr: i32, mut r: i32) -> () { instr_0F10(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F10_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F30F10_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("movss xmm, xmm/m32")); let mut data: reg128 = read_xmm128s(r1); let mut orig: reg128 = read_xmm128s(r2); @@ -468,26 +466,26 @@ pub unsafe extern "C" fn instr_F30F10_reg(mut r1: i32, mut r2: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F10_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F10_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movss xmm, xmm/m32")); let mut data: i32 = return_on_pagefault!(safe_read32s(addr)); write_xmm128(r, data, 0i32, 0i32, 0i32); } #[no_mangle] -pub unsafe extern "C" fn instr_660F10(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F10(mut source: reg128, mut r: i32) -> () { c_comment!(("movupd xmm, xmm/m128")); mov_rm_r128(source, r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F10_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F10_reg(mut r1: i32, mut r2: i32) -> () { instr_660F10(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F10_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F10_mem(mut addr: i32, mut r: i32) -> () { instr_660F10(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F10_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F20F10_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("movsd xmm, xmm/m64")); let mut data: reg128 = read_xmm128s(r1); let mut orig: reg128 = read_xmm128s(r2); @@ -500,7 +498,7 @@ pub unsafe extern "C" fn instr_F20F10_reg(mut r1: i32, mut r2: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F10_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F10_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movsd xmm, xmm/m64")); let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); write_xmm128( @@ -512,17 +510,17 @@ pub unsafe extern "C" fn instr_F20F10_mem(mut addr: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_0F11_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_0F11_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("movups xmm/m128, xmm")); mov_r_r128(r1, r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F11_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F11_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movups xmm/m128, xmm")); mov_r_m128(addr, r); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F11_reg(mut rm_dest: i32, mut reg_src: i32) -> () { +pub unsafe fn instr_F30F11_reg(mut rm_dest: i32, mut reg_src: i32) -> () { c_comment!(("movss xmm/m32, xmm")); let mut data: reg128 = read_xmm128s(reg_src); let mut orig: reg128 = read_xmm128s(rm_dest); @@ -535,23 +533,23 @@ pub unsafe extern "C" fn instr_F30F11_reg(mut rm_dest: i32, mut reg_src: i32) -> ); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F11_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F11_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movss xmm/m32, xmm")); let mut data: reg128 = read_xmm128s(r); return_on_pagefault!(safe_write32(addr, data.u32_0[0usize] as i32)); } #[no_mangle] -pub unsafe extern "C" fn instr_660F11_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F11_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("movupd xmm/m128, xmm")); mov_r_r128(r1, r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F11_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F11_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movupd xmm/m128, xmm")); mov_r_m128(addr, r); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F11_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F20F11_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("movsd xmm/m64, xmm")); let mut data: reg128 = read_xmm128s(r2); let mut orig: reg128 = read_xmm128s(r1); @@ -564,13 +562,13 @@ pub unsafe extern "C" fn instr_F20F11_reg(mut r1: i32, mut r2: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F11_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F11_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movsd xmm/m64, xmm")); let mut data: reg64 = read_xmm64s(r); return_on_pagefault!(safe_write64(addr, data.u64_0[0usize] as i64)); } #[no_mangle] -pub unsafe extern "C" fn instr_0F12_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F12_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movlps xmm, m64")); let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); let mut orig: reg128 = read_xmm128s(r); @@ -583,7 +581,7 @@ pub unsafe extern "C" fn instr_0F12_mem(mut addr: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_0F12_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_0F12_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("movhlps xmm, xmm")); let mut data: reg128 = read_xmm128s(r1); let mut orig: reg128 = read_xmm128s(r2); @@ -596,37 +594,37 @@ pub unsafe extern "C" fn instr_0F12_reg(mut r1: i32, mut r2: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_660F12_reg(mut r1: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F12_reg(mut r1: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660F12_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F12_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movlpd xmm, m64")); let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); write_xmm64(r, data); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F12_mem(mut addr: i32, mut r: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_F20F12_mem(mut addr: i32, mut r: i32) -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F12_reg(mut r1: i32, mut r2: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_F20F12_reg(mut r1: i32, mut r2: i32) -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F12_mem(mut addr: i32, mut r: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_F30F12_mem(mut addr: i32, mut r: i32) -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F12_reg(mut r1: i32, mut r2: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_F30F12_reg(mut r1: i32, mut r2: i32) -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F13_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F13_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movlps m64, xmm")); movl_r128_m64(addr, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F13_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F13_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660F13_reg(mut r1: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F13_reg(mut r1: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660F13_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F13_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movlpd xmm/m64, xmm")); movl_r128_m64(addr, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F14(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F14(mut source: reg64, mut r: i32) -> () { c_comment!(("unpcklps xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg64 = read_xmm64s(r); @@ -639,15 +637,13 @@ pub unsafe extern "C" fn instr_0F14(mut source: reg64, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_0F14_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F14(read_xmm64s(r1), r2); -} +pub unsafe fn instr_0F14_reg(mut r1: i32, mut r2: i32) -> () { instr_0F14(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F14_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F14_mem(mut addr: i32, mut r: i32) -> () { instr_0F14(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F14(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_660F14(mut source: reg64, mut r: i32) -> () { c_comment!(("unpcklpd xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg64 = read_xmm64s(r); @@ -660,15 +656,15 @@ pub unsafe extern "C" fn instr_660F14(mut source: reg64, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_660F14_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F14_reg(mut r1: i32, mut r2: i32) -> () { instr_660F14(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F14_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F14_mem(mut addr: i32, mut r: i32) -> () { instr_660F14(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F15(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F15(mut source: reg128, mut r: i32) -> () { c_comment!(("unpckhps xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -681,15 +677,13 @@ pub unsafe extern "C" fn instr_0F15(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_0F15_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F15(read_xmm128s(r1), r2); -} +pub unsafe fn instr_0F15_reg(mut r1: i32, mut r2: i32) -> () { instr_0F15(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F15_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F15_mem(mut addr: i32, mut r: i32) -> () { instr_0F15(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F15(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F15(mut source: reg128, mut r: i32) -> () { c_comment!(("unpckhpd xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -702,20 +696,20 @@ pub unsafe extern "C" fn instr_660F15(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_660F15_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F15_reg(mut r1: i32, mut r2: i32) -> () { instr_660F15(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F15_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F15_mem(mut addr: i32, mut r: i32) -> () { instr_660F15(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F16_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F16_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movhps xmm, m64")); movh_m64_r128(addr, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F16_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_0F16_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("movlhps xmm, xmm")); let mut data: reg128 = read_xmm128s(r1); let mut orig: reg128 = read_xmm128s(r2); @@ -728,45 +722,45 @@ pub unsafe extern "C" fn instr_0F16_reg(mut r1: i32, mut r2: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_660F16_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F16_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movhpd xmm, m64")); movh_m64_r128(addr, r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F16_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F16_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F17_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F17_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movhps m64, xmm")); movh_r128_m64(addr, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F17_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F17_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660F17_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F17_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movhpd m64, xmm")); movh_r128_m64(addr, r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F17_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F17_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F18_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_0F18_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("reserved nop")); } #[no_mangle] -pub unsafe extern "C" fn instr_0F18_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F18_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("prefetch")); c_comment!(("nop for us")); } #[no_mangle] -pub unsafe extern "C" fn instr_0F1A() -> () { undefined_instruction(); } +pub unsafe fn instr_0F1A() -> () { undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F1B() -> () { undefined_instruction(); } +pub unsafe fn instr_0F1B() -> () { undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F1F_reg(mut r1: i32, mut r2: i32) -> () {} +pub unsafe fn instr_0F1F_reg(mut r1: i32, mut r2: i32) -> () {} #[no_mangle] -pub unsafe extern "C" fn instr_0F1F_mem(mut addr: i32, mut r: i32) -> () {} +pub unsafe fn instr_0F1F_mem(mut addr: i32, mut r: i32) -> () {} #[no_mangle] -pub unsafe extern "C" fn instr_0F20(mut r: i32, mut creg: i32) -> () { +pub unsafe fn instr_0F20(mut r: i32, mut creg: i32) -> () { if 0 != *cpl.offset(0isize) { trigger_gp_non_raising(0i32); return; @@ -794,7 +788,7 @@ pub unsafe extern "C" fn instr_0F20(mut r: i32, mut creg: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F21(mut r: i32, mut dreg_index: i32) -> () { +pub unsafe fn instr_0F21(mut r: i32, mut dreg_index: i32) -> () { if 0 != *cpl.offset(0isize) { trigger_gp_non_raising(0i32); return; @@ -823,7 +817,7 @@ pub unsafe extern "C" fn instr_0F21(mut r: i32, mut dreg_index: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F22(mut r: i32, mut creg: i32) -> () { +pub unsafe fn instr_0F22(mut r: i32, mut creg: i32) -> () { if 0 != *cpl.offset(0isize) { trigger_gp_non_raising(0i32); return; @@ -884,7 +878,7 @@ pub unsafe extern "C" fn instr_0F22(mut r: i32, mut creg: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F23(mut r: i32, mut dreg_index: i32) -> () { +pub unsafe fn instr_0F23(mut r: i32, mut dreg_index: i32) -> () { if 0 != *cpl.offset(0isize) { trigger_gp_non_raising(0i32); return; @@ -913,104 +907,100 @@ pub unsafe extern "C" fn instr_0F23(mut r: i32, mut dreg_index: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F24() -> () { undefined_instruction(); } +pub unsafe fn instr_0F24() -> () { undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F25() -> () { undefined_instruction(); } +pub unsafe fn instr_0F25() -> () { undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F26() -> () { undefined_instruction(); } +pub unsafe fn instr_0F26() -> () { undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F27() -> () { undefined_instruction(); } +pub unsafe fn instr_0F27() -> () { undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F28(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F28(mut source: reg128, mut r: i32) -> () { c_comment!(("movaps xmm, xmm/m128")); c_comment!(("XXX: Aligned read or #gp")); mov_rm_r128(source, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F28_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F28(read_xmm128s(r1), r2); -} +pub unsafe fn instr_0F28_reg(mut r1: i32, mut r2: i32) -> () { instr_0F28(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F28_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F28_mem(mut addr: i32, mut r: i32) -> () { instr_0F28(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F28(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F28(mut source: reg128, mut r: i32) -> () { c_comment!(("movapd xmm, xmm/m128")); c_comment!(("XXX: Aligned read or #gp")); c_comment!(("Note: Same as movdqa (660F6F)")); mov_rm_r128(source, r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F28_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F28_reg(mut r1: i32, mut r2: i32) -> () { instr_660F28(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F28_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F28_mem(mut addr: i32, mut r: i32) -> () { instr_660F28(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F29_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F29_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movaps m128, xmm")); let mut data: reg128 = read_xmm128s(r); c_comment!(("XXX: Aligned write or #gp")); return_on_pagefault!(safe_write128(addr, data)); } #[no_mangle] -pub unsafe extern "C" fn instr_0F29_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_0F29_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("movaps xmm, xmm")); mov_r_r128(r1, r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F29_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F29_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movapd m128, xmm")); let mut data: reg128 = read_xmm128s(r); c_comment!(("XXX: Aligned write or #gp")); return_on_pagefault!(safe_write128(addr, data)); } #[no_mangle] -pub unsafe extern "C" fn instr_660F29_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F29_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("movapd xmm, xmm")); mov_r_r128(r1, r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F2B_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F2B_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F2B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F2B_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movntps m128, xmm")); c_comment!(("XXX: Aligned write or #gp")); mov_r_m128(addr, r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F2B_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F2B_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660F2B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F2B_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movntpd m128, xmm")); c_comment!(("XXX: Aligned write or #gp")); mov_r_m128(addr, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F2C_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F2C_mem(mut addr: i32, mut r: i32) -> () { instr_0F2C(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F2C(mut source: reg64, mut r: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_0F2C(mut source: reg64, mut r: i32) -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F2C_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F2C(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0F2C_reg(mut r1: i32, mut r2: i32) -> () { instr_0F2C(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F2C_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F2C_mem(mut addr: i32, mut r: i32) -> () { instr_660F2C(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F2C(mut source: reg128, mut r: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_660F2C(mut source: reg128, mut r: i32) -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_660F2C_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F2C_reg(mut r1: i32, mut r2: i32) -> () { instr_660F2C(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F2C(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_F20F2C(mut source: reg64, mut r: i32) -> () { let mut si: i32 = 0; c_comment!(("cvttsd2si r32, xmm/m64")); c_comment!( @@ -1032,29 +1022,29 @@ pub unsafe extern "C" fn instr_F20F2C(mut source: reg64, mut r: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_F20F2C_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F20F2C_reg(mut r1: i32, mut r2: i32) -> () { instr_F20F2C(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F2C_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F2C_mem(mut addr: i32, mut r: i32) -> () { instr_F20F2C(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F2C_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F2C_mem(mut addr: i32, mut r: i32) -> () { instr_F30F2C(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F2C(mut source: f32, mut r: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_F30F2C(mut source: f32, mut r: i32) -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F2C_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F30F2C_reg(mut r1: i32, mut r2: i32) -> () { instr_F30F2C(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F2E() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F2E() -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F2F() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F2F() -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F30() -> () { +pub unsafe fn instr_0F30() -> () { c_comment!(("wrmsr - write maschine specific register")); if 0 != *cpl.offset(0isize) { trigger_gp_non_raising(0i32); @@ -1118,7 +1108,7 @@ pub unsafe extern "C" fn instr_0F30() -> () { #[no_mangle] pub static mut apic_enabled: bool = unsafe { 0 != 0i32 }; #[no_mangle] -pub unsafe extern "C" fn instr_0F31() -> () { +pub unsafe fn instr_0F31() -> () { c_comment!(("rdtsc - read timestamp counter")); if 0 == *cpl.offset(0isize) || 0 == *cr.offset(4isize) & CR4_TSD { let mut tsc: u64 = read_tsc(); @@ -1137,7 +1127,7 @@ pub unsafe extern "C" fn instr_0F31() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F32() -> () { +pub unsafe fn instr_0F32() -> () { c_comment!(("rdmsr - read maschine specific register")); if 0 != *cpl.offset(0isize) { trigger_gp_non_raising(0i32); @@ -1204,12 +1194,12 @@ pub unsafe extern "C" fn instr_0F32() -> () { #[no_mangle] pub static mut ENABLE_ACPI: bool = unsafe { 0 != 1i32 }; #[no_mangle] -pub unsafe extern "C" fn instr_0F33() -> () { +pub unsafe fn instr_0F33() -> () { c_comment!(("rdpmc")); undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F34() -> () { +pub unsafe fn instr_0F34() -> () { c_comment!(("sysenter")); let mut seg: i32 = *sysenter_cs.offset(0isize) & 65532i32; if !*protected_mode.offset(0isize) || seg == 0i32 { @@ -1237,7 +1227,7 @@ pub unsafe extern "C" fn instr_0F34() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F35() -> () { +pub unsafe fn instr_0F35() -> () { c_comment!(("sysexit")); let mut seg: i32 = *sysenter_cs.offset(0isize) & 65532i32; if !*protected_mode.offset(0isize) || 0 != *cpl.offset(0isize) as i32 || seg == 0i32 { @@ -1263,350 +1253,350 @@ pub unsafe extern "C" fn instr_0F35() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F36() -> () { undefined_instruction(); } +pub unsafe fn instr_0F36() -> () { undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F37() -> () { +pub unsafe fn instr_0F37() -> () { c_comment!(("getsec")); undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F38() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F38() -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F39() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F39() -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F3A() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F3A() -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F3B() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F3B() -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F3C() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F3C() -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F3D() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F3D() -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F3E() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F3E() -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F3F() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F3F() -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F40_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F40_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_o(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F40_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F40_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); cmovcc16(test_o(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F40_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F40_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_o(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F40_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F40_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); cmovcc32(test_o(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F41_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F41_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_o(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F41_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F41_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); cmovcc16(!test_o(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F41_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F41_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_o(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F41_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F41_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); cmovcc32(!test_o(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F42_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F42_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_b(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F42_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F42_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); cmovcc16(test_b(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F42_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F42_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_b(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F42_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F42_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); cmovcc32(test_b(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F43_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F43_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_b(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F43_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F43_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); cmovcc16(!test_b(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F43_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F43_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_b(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F43_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F43_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); cmovcc32(!test_b(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F44_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F44_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_z(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F44_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F44_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); cmovcc16(test_z(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F44_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F44_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_z(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F44_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F44_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); cmovcc32(test_z(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F45_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F45_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_z(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F45_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F45_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); cmovcc16(!test_z(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F45_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F45_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_z(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F45_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F45_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); cmovcc32(!test_z(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F46_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F46_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_be(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F46_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F46_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); cmovcc16(test_be(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F46_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F46_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_be(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F46_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F46_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); cmovcc32(test_be(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F47_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F47_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_be(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F47_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F47_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); cmovcc16(!test_be(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F47_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F47_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_be(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F47_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F47_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); cmovcc32(!test_be(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F48_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F48_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_s(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F48_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F48_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); cmovcc16(test_s(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F48_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F48_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_s(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F48_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F48_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); cmovcc32(test_s(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F49_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F49_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_s(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F49_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F49_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); cmovcc16(!test_s(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F49_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F49_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_s(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F49_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F49_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); cmovcc32(!test_s(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F4A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4A_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_p(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F4A_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4A_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); cmovcc16(test_p(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F4A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4A_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_p(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F4A_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4A_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); cmovcc32(test_p(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F4B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4B_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_p(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F4B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4B_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); cmovcc16(!test_p(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F4B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4B_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_p(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F4B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4B_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); cmovcc32(!test_p(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F4C_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4C_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_l(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F4C_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4C_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); cmovcc16(test_l(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F4C_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4C_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_l(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F4C_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4C_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); cmovcc32(test_l(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F4D_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4D_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_l(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F4D_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4D_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); cmovcc16(!test_l(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F4D_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4D_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_l(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F4D_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4D_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); cmovcc32(!test_l(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F4E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4E_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_le(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F4E_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4E_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); cmovcc16(test_le(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F4E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4E_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_le(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F4E_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4E_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); cmovcc32(test_le(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F4F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4F_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_le(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F4F_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4F_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); cmovcc16(!test_le(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F4F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4F_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_le(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F4F_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4F_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); cmovcc32(!test_le(), ____0, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F50_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_0F50_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("movmskps r, xmm")); let mut source: reg128 = read_xmm128s(r1); let mut data: i32 = (source.u32_0[0usize] >> 31i32 @@ -1616,9 +1606,9 @@ pub unsafe extern "C" fn instr_0F50_reg(mut r1: i32, mut r2: i32) -> () { write_reg32(r2, data); } #[no_mangle] -pub unsafe extern "C" fn instr_0F50_mem(mut addr: i32, mut r1: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F50_mem(mut addr: i32, mut r1: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660F50_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F50_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("movmskpd r, xmm")); let mut source: reg128 = read_xmm128s(r1); let mut data: i32 = @@ -1626,121 +1616,113 @@ pub unsafe extern "C" fn instr_660F50_reg(mut r1: i32, mut r2: i32) -> () { write_reg32(r2, data); } #[no_mangle] -pub unsafe extern "C" fn instr_660F50_mem(mut addr: i32, mut r1: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F50_mem(mut addr: i32, mut r1: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F54(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F54(mut source: reg128, mut r: i32) -> () { c_comment!(("andps xmm, xmm/mem128")); c_comment!(("XXX: Aligned access or #gp")); pand_r128(source, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F54_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F54(read_xmm128s(r1), r2); -} +pub unsafe fn instr_0F54_reg(mut r1: i32, mut r2: i32) -> () { instr_0F54(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F54_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F54_mem(mut addr: i32, mut r: i32) -> () { instr_0F54(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F54(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F54(mut source: reg128, mut r: i32) -> () { c_comment!(("andpd xmm, xmm/mem128")); c_comment!(("XXX: Aligned access or #gp")); pand_r128(source, r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F54_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F54_reg(mut r1: i32, mut r2: i32) -> () { instr_660F54(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F54_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F54_mem(mut addr: i32, mut r: i32) -> () { instr_660F54(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F55(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F55(mut source: reg128, mut r: i32) -> () { c_comment!(("andnps xmm, xmm/mem128")); c_comment!(("XXX: Aligned access or #gp")); pandn_r128(source, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F55_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F55(read_xmm128s(r1), r2); -} +pub unsafe fn instr_0F55_reg(mut r1: i32, mut r2: i32) -> () { instr_0F55(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F55_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F55_mem(mut addr: i32, mut r: i32) -> () { instr_0F55(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F55(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F55(mut source: reg128, mut r: i32) -> () { c_comment!(("andnpd xmm, xmm/mem128")); c_comment!(("XXX: Aligned access or #gp")); pandn_r128(source, r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F55_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F55_reg(mut r1: i32, mut r2: i32) -> () { instr_660F55(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F55_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F55_mem(mut addr: i32, mut r: i32) -> () { instr_660F55(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F56(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F56(mut source: reg128, mut r: i32) -> () { c_comment!(("orps xmm, xmm/mem128")); c_comment!(("XXX: Aligned access or #gp")); por_r128(source, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F56_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F56(read_xmm128s(r1), r2); -} +pub unsafe fn instr_0F56_reg(mut r1: i32, mut r2: i32) -> () { instr_0F56(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F56_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F56_mem(mut addr: i32, mut r: i32) -> () { instr_0F56(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F56(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F56(mut source: reg128, mut r: i32) -> () { c_comment!(("orpd xmm, xmm/mem128")); c_comment!(("XXX: Aligned access or #gp")); por_r128(source, r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F56_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F56_reg(mut r1: i32, mut r2: i32) -> () { instr_660F56(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F56_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F56_mem(mut addr: i32, mut r: i32) -> () { instr_660F56(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F57(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F57(mut source: reg128, mut r: i32) -> () { c_comment!(("xorps xmm, xmm/mem128")); c_comment!(("XXX: Aligned access or #gp")); pxor_r128(source, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F57_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F57(read_xmm128s(r1), r2); -} +pub unsafe fn instr_0F57_reg(mut r1: i32, mut r2: i32) -> () { instr_0F57(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F57_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F57_mem(mut addr: i32, mut r: i32) -> () { instr_0F57(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F57(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F57(mut source: reg128, mut r: i32) -> () { c_comment!(("xorpd xmm, xmm/mem128")); c_comment!(("XXX: Aligned access or #gp")); pxor_r128(source, r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F57_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F57_reg(mut r1: i32, mut r2: i32) -> () { instr_660F57(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F57_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F57_mem(mut addr: i32, mut r: i32) -> () { instr_660F57(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F60(mut source: i32, mut r: i32) -> () { +pub unsafe fn instr_0F60(mut source: i32, mut r: i32) -> () { c_comment!(("punpcklbw mm, mm/m32")); let mut destination: reg64 = read_mmx64s(r); let mut byte0: i32 = destination.u8_0[0usize] as i32; @@ -1756,15 +1738,13 @@ pub unsafe extern "C" fn instr_0F60(mut source: i32, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe extern "C" fn instr_0F60_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F60(read_mmx32s(r1), r2); -} +pub unsafe fn instr_0F60_reg(mut r1: i32, mut r2: i32) -> () { instr_0F60(read_mmx32s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F60_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F60_mem(mut addr: i32, mut r: i32) -> () { instr_0F60(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F60(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_660F60(mut source: reg64, mut r: i32) -> () { c_comment!(("punpcklbw xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg64 = read_xmm64s(r); @@ -1789,15 +1769,15 @@ pub unsafe extern "C" fn instr_660F60(mut source: reg64, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_660F60_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F60_reg(mut r1: i32, mut r2: i32) -> () { instr_660F60(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F60_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F60_mem(mut addr: i32, mut r: i32) -> () { instr_660F60(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F61(mut source: i32, mut r: i32) -> () { +pub unsafe fn instr_0F61(mut source: i32, mut r: i32) -> () { c_comment!(("punpcklwd mm, mm/m32")); let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = destination.u16_0[0usize] as i32; @@ -1809,15 +1789,13 @@ pub unsafe extern "C" fn instr_0F61(mut source: i32, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe extern "C" fn instr_0F61_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F61(read_mmx32s(r1), r2); -} +pub unsafe fn instr_0F61_reg(mut r1: i32, mut r2: i32) -> () { instr_0F61(read_mmx32s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F61_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F61_mem(mut addr: i32, mut r: i32) -> () { instr_0F61(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F61(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_660F61(mut source: reg64, mut r: i32) -> () { c_comment!(("punpcklwd xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg64 = read_xmm64s(r); @@ -1830,29 +1808,27 @@ pub unsafe extern "C" fn instr_660F61(mut source: reg64, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_660F61_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F61_reg(mut r1: i32, mut r2: i32) -> () { instr_660F61(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F61_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F61_mem(mut addr: i32, mut r: i32) -> () { instr_660F61(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F62(mut source: i32, mut r: i32) -> () { +pub unsafe fn instr_0F62(mut source: i32, mut r: i32) -> () { c_comment!(("punpckldq mm, mm/m32")); let mut destination: reg64 = read_mmx64s(r); write_mmx64(r, destination.u32_0[0usize] as i32, source); } #[no_mangle] -pub unsafe extern "C" fn instr_0F62_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F62(read_mmx32s(r1), r2); -} +pub unsafe fn instr_0F62_reg(mut r1: i32, mut r2: i32) -> () { instr_0F62(read_mmx32s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F62_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F62_mem(mut addr: i32, mut r: i32) -> () { instr_0F62(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F62(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F62(mut source: reg128, mut r: i32) -> () { c_comment!(("punpckldq xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -1865,15 +1841,15 @@ pub unsafe extern "C" fn instr_660F62(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_660F62_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F62_reg(mut r1: i32, mut r2: i32) -> () { instr_660F62(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F62_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F62_mem(mut addr: i32, mut r: i32) -> () { instr_660F62(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F63(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F63(mut source: reg64, mut r: i32) -> () { c_comment!(("packsswb mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut low: i32 = saturate_sw_to_sb(destination.u16_0[0usize] as i32) @@ -1887,15 +1863,13 @@ pub unsafe extern "C" fn instr_0F63(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe extern "C" fn instr_0F63_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F63(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0F63_reg(mut r1: i32, mut r2: i32) -> () { instr_0F63(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F63_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F63_mem(mut addr: i32, mut r: i32) -> () { instr_0F63(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F63(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F63(mut source: reg128, mut r: i32) -> () { c_comment!(("packsswb xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -1918,15 +1892,15 @@ pub unsafe extern "C" fn instr_660F63(mut source: reg128, mut r: i32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe extern "C" fn instr_660F63_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F63_reg(mut r1: i32, mut r2: i32) -> () { instr_660F63(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F63_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F63_mem(mut addr: i32, mut r: i32) -> () { instr_660F63(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F64(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F64(mut source: reg64, mut r: i32) -> () { c_comment!(("pcmpgtb mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -1946,15 +1920,13 @@ pub unsafe extern "C" fn instr_0F64(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0F64_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F64(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0F64_reg(mut r1: i32, mut r2: i32) -> () { instr_0F64(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F64_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F64_mem(mut addr: i32, mut r: i32) -> () { instr_0F64(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F64(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F64(mut source: reg128, mut r: i32) -> () { c_comment!(("pcmpgtb xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -1975,15 +1947,15 @@ pub unsafe extern "C" fn instr_660F64(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660F64_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F64_reg(mut r1: i32, mut r2: i32) -> () { instr_660F64(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F64_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F64_mem(mut addr: i32, mut r: i32) -> () { instr_660F64(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F65(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F65(mut source: reg64, mut r: i32) -> () { c_comment!(("pcmpgtw mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = if destination.i16_0[0usize] as i32 > source.i16_0[0usize] as i32 { @@ -2015,15 +1987,13 @@ pub unsafe extern "C" fn instr_0F65(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe extern "C" fn instr_0F65_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F65(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0F65_reg(mut r1: i32, mut r2: i32) -> () { instr_0F65(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F65_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F65_mem(mut addr: i32, mut r: i32) -> () { instr_0F65(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F65(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F65(mut source: reg128, mut r: i32) -> () { c_comment!(("pcmpgtw xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -2044,15 +2014,15 @@ pub unsafe extern "C" fn instr_660F65(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660F65_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F65_reg(mut r1: i32, mut r2: i32) -> () { instr_660F65(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F65_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F65_mem(mut addr: i32, mut r: i32) -> () { instr_660F65(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F66(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F66(mut source: reg64, mut r: i32) -> () { c_comment!(("pcmpgtd mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut low: i32 = if destination.i32_0[0usize] > source.i32_0[0usize] { @@ -2070,15 +2040,13 @@ pub unsafe extern "C" fn instr_0F66(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe extern "C" fn instr_0F66_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F66(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0F66_reg(mut r1: i32, mut r2: i32) -> () { instr_0F66(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F66_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F66_mem(mut addr: i32, mut r: i32) -> () { instr_0F66(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F66(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F66(mut source: reg128, mut r: i32) -> () { c_comment!(("pcmpgtd xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -2111,15 +2079,15 @@ pub unsafe extern "C" fn instr_660F66(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_660F66_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F66_reg(mut r1: i32, mut r2: i32) -> () { instr_660F66(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F66_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F66_mem(mut addr: i32, mut r: i32) -> () { instr_660F66(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F67(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F67(mut source: reg64, mut r: i32) -> () { c_comment!(("packuswb mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut low: u32 = saturate_sw_to_ub(destination.u16_0[0usize] as u32) @@ -2133,15 +2101,13 @@ pub unsafe extern "C" fn instr_0F67(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low as i32, high as i32); } #[no_mangle] -pub unsafe extern "C" fn instr_0F67_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F67(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0F67_reg(mut r1: i32, mut r2: i32) -> () { instr_0F67(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F67_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F67_mem(mut addr: i32, mut r: i32) -> () { instr_0F67(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F67(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F67(mut source: reg128, mut r: i32) -> () { c_comment!(("packuswb xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -2155,15 +2121,15 @@ pub unsafe extern "C" fn instr_660F67(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660F67_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F67_reg(mut r1: i32, mut r2: i32) -> () { instr_660F67(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F67_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F67_mem(mut addr: i32, mut r: i32) -> () { instr_660F67(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F68(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F68(mut source: reg64, mut r: i32) -> () { c_comment!(("punpckhbw mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut byte0: i32 = destination.u8_0[4usize] as i32; @@ -2179,15 +2145,13 @@ pub unsafe extern "C" fn instr_0F68(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe extern "C" fn instr_0F68_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F68(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0F68_reg(mut r1: i32, mut r2: i32) -> () { instr_0F68(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F68_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F68_mem(mut addr: i32, mut r: i32) -> () { instr_0F68(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F68(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F68(mut source: reg128, mut r: i32) -> () { c_comment!(("punpckhbw xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -2212,15 +2176,15 @@ pub unsafe extern "C" fn instr_660F68(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_660F68_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F68_reg(mut r1: i32, mut r2: i32) -> () { instr_660F68(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F68_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F68_mem(mut addr: i32, mut r: i32) -> () { instr_660F68(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F69(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F69(mut source: reg64, mut r: i32) -> () { c_comment!(("punpckhwd mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = destination.u16_0[2usize] as i32; @@ -2232,15 +2196,13 @@ pub unsafe extern "C" fn instr_0F69(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe extern "C" fn instr_0F69_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F69(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0F69_reg(mut r1: i32, mut r2: i32) -> () { instr_0F69(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F69_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F69_mem(mut addr: i32, mut r: i32) -> () { instr_0F69(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F69(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F69(mut source: reg128, mut r: i32) -> () { c_comment!(("punpckhwd xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -2251,15 +2213,15 @@ pub unsafe extern "C" fn instr_660F69(mut source: reg128, mut r: i32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe extern "C" fn instr_660F69_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F69_reg(mut r1: i32, mut r2: i32) -> () { instr_660F69(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F69_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F69_mem(mut addr: i32, mut r: i32) -> () { instr_660F69(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F6A(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F6A(mut source: reg64, mut r: i32) -> () { c_comment!(("punpckhdq mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); write_mmx64( @@ -2269,15 +2231,13 @@ pub unsafe extern "C" fn instr_0F6A(mut source: reg64, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_0F6A_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F6A(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0F6A_reg(mut r1: i32, mut r2: i32) -> () { instr_0F6A(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F6A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F6A_mem(mut addr: i32, mut r: i32) -> () { instr_0F6A(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F6A(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F6A(mut source: reg128, mut r: i32) -> () { c_comment!(("punpckhdq xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -2290,15 +2250,15 @@ pub unsafe extern "C" fn instr_660F6A(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_660F6A_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F6A_reg(mut r1: i32, mut r2: i32) -> () { instr_660F6A(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F6A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F6A_mem(mut addr: i32, mut r: i32) -> () { instr_660F6A(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F6B(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F6B(mut source: reg64, mut r: i32) -> () { c_comment!(("packssdw mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut low: i32 = (saturate_sd_to_sw(destination.u32_0[0usize]) @@ -2308,15 +2268,13 @@ pub unsafe extern "C" fn instr_0F6B(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe extern "C" fn instr_0F6B_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F6B(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0F6B_reg(mut r1: i32, mut r2: i32) -> () { instr_0F6B(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F6B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F6B_mem(mut addr: i32, mut r: i32) -> () { instr_0F6B(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F6B(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F6B(mut source: reg128, mut r: i32) -> () { c_comment!(("packssdw xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -2331,19 +2289,19 @@ pub unsafe extern "C" fn instr_660F6B(mut source: reg128, mut r: i32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe extern "C" fn instr_660F6B_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F6B_reg(mut r1: i32, mut r2: i32) -> () { instr_660F6B(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F6B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F6B_mem(mut addr: i32, mut r: i32) -> () { instr_660F6B(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F6C_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F6C_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F6C_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F6C_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660F6C(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F6C(mut source: reg128, mut r: i32) -> () { c_comment!(("punpcklqdq xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -2356,19 +2314,19 @@ pub unsafe extern "C" fn instr_660F6C(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_660F6C_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F6C_reg(mut r1: i32, mut r2: i32) -> () { instr_660F6C(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F6C_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F6C_mem(mut addr: i32, mut r: i32) -> () { instr_660F6C(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F6D_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F6D_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F6D_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F6D_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660F6D(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F6D(mut source: reg128, mut r: i32) -> () { c_comment!(("punpckhqdq xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -2381,82 +2339,76 @@ pub unsafe extern "C" fn instr_660F6D(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_660F6D_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F6D_reg(mut r1: i32, mut r2: i32) -> () { instr_660F6D(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F6D_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F6D_mem(mut addr: i32, mut r: i32) -> () { instr_660F6D(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F6E(mut source: i32, mut r: i32) -> () { +pub unsafe fn instr_0F6E(mut source: i32, mut r: i32) -> () { c_comment!(("movd mm, r/m32")); write_mmx64(r, source, 0i32); } #[no_mangle] -pub unsafe extern "C" fn instr_0F6E_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F6E(read_reg32(r1), r2); -} +pub unsafe fn instr_0F6E_reg(mut r1: i32, mut r2: i32) -> () { instr_0F6E(read_reg32(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F6E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F6E_mem(mut addr: i32, mut r: i32) -> () { instr_0F6E(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F6E(mut source: i32, mut r: i32) -> () { +pub unsafe fn instr_660F6E(mut source: i32, mut r: i32) -> () { c_comment!(("movd mm, r/m32")); write_xmm128(r, source, 0i32, 0i32, 0i32); } #[no_mangle] -pub unsafe extern "C" fn instr_660F6E_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F6E(read_reg32(r1), r2); -} +pub unsafe fn instr_660F6E_reg(mut r1: i32, mut r2: i32) -> () { instr_660F6E(read_reg32(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F6E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F6E_mem(mut addr: i32, mut r: i32) -> () { instr_660F6E(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F6F(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F6F(mut source: reg64, mut r: i32) -> () { c_comment!(("movq mm, mm/m64")); write_mmx64(r, source.u32_0[0usize] as i32, source.u32_0[1usize] as i32); } #[no_mangle] -pub unsafe extern "C" fn instr_0F6F_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F6F(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0F6F_reg(mut r1: i32, mut r2: i32) -> () { instr_0F6F(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F6F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F6F_mem(mut addr: i32, mut r: i32) -> () { instr_0F6F(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F6F(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F6F(mut source: reg128, mut r: i32) -> () { c_comment!(("movdqa xmm, xmm/mem128")); c_comment!(("XXX: Aligned access or #gp")); c_comment!(("XXX: Aligned read or #gp")); mov_rm_r128(source, r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F6F_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F6F_reg(mut r1: i32, mut r2: i32) -> () { instr_660F6F(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F6F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F6F_mem(mut addr: i32, mut r: i32) -> () { instr_660F6F(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F6F(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_F30F6F(mut source: reg128, mut r: i32) -> () { c_comment!(("movdqu xmm, xmm/m128")); mov_rm_r128(source, r); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F6F_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F30F6F_reg(mut r1: i32, mut r2: i32) -> () { instr_F30F6F(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F6F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F6F_mem(mut addr: i32, mut r: i32) -> () { instr_F30F6F(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F70(mut source: reg64, mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0F70(mut source: reg64, mut r: i32, mut imm8: i32) -> () { c_comment!(("pshufw mm1, mm2/m64, imm8")); let mut word0_shift: i32 = imm8 & 3i32; let mut word0: u32 = source.u32_0[(word0_shift >> 1i32) as usize] @@ -2477,15 +2429,15 @@ pub unsafe extern "C" fn instr_0F70(mut source: reg64, mut r: i32, mut imm8: i32 write_mmx64(r, low, high); } #[no_mangle] -pub unsafe extern "C" fn instr_0F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { +pub unsafe fn instr_0F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { instr_0F70(read_mmx64s(r1), r2, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_0F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr_0F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { instr_0F70(return_on_pagefault!(safe_read64s(addr)), r, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_660F70(mut source: reg128, mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660F70(mut source: reg128, mut r: i32, mut imm8: i32) -> () { c_comment!(("pshufd xmm, xmm/mem128")); c_comment!(("XXX: Aligned access or #gp")); write_xmm128( @@ -2497,15 +2449,15 @@ pub unsafe extern "C" fn instr_660F70(mut source: reg128, mut r: i32, mut imm8: ); } #[no_mangle] -pub unsafe extern "C" fn instr_660F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { +pub unsafe fn instr_660F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { instr_660F70(read_xmm128s(r1), r2, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_660F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr_660F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { instr_660F70(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F70(mut source: reg128, mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_F20F70(mut source: reg128, mut r: i32, mut imm8: i32) -> () { c_comment!(("pshuflw xmm, xmm/m128, imm8")); c_comment!(("XXX: Aligned access or #gp")); write_xmm128( @@ -2519,15 +2471,15 @@ pub unsafe extern "C" fn instr_F20F70(mut source: reg128, mut r: i32, mut imm8: ); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { +pub unsafe fn instr_F20F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { instr_F20F70(read_xmm128s(r1), r2, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr_F20F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { instr_F20F70(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F70(mut source: reg128, mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_F30F70(mut source: reg128, mut r: i32, mut imm8: i32) -> () { c_comment!(("pshufhw xmm, xmm/m128, imm8")); c_comment!(("XXX: Aligned access or #gp")); write_xmm128( @@ -2541,126 +2493,126 @@ pub unsafe extern "C" fn instr_F30F70(mut source: reg128, mut r: i32, mut imm8: ); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { +pub unsafe fn instr_F30F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { instr_F30F70(read_xmm128s(r1), r2, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr_F30F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { instr_F30F70(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_0F71_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F71_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F71_4_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F71_4_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F71_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F71_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F71_2_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0F71_2_reg(mut r: i32, mut imm8: i32) -> () { c_comment!(("psrlw mm, imm8")); psrlw_r64(r, imm8 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr_0F71_4_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0F71_4_reg(mut r: i32, mut imm8: i32) -> () { c_comment!(("psraw mm, imm8")); psraw_r64(r, imm8 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr_0F71_6_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0F71_6_reg(mut r: i32, mut imm8: i32) -> () { c_comment!(("psllw mm, imm8")); psllw_r64(r, imm8 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr_660F71_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F71_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660F71_4_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F71_4_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660F71_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F71_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660F71_2_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660F71_2_reg(mut r: i32, mut imm8: i32) -> () { c_comment!(("psrlw xmm, imm8")); psrlw_r128(r, imm8 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr_660F71_4_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660F71_4_reg(mut r: i32, mut imm8: i32) -> () { c_comment!(("psraw xmm, imm8")); psraw_r128(r, imm8 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr_660F71_6_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660F71_6_reg(mut r: i32, mut imm8: i32) -> () { c_comment!(("psllw xmm, imm8")); psllw_r128(r, imm8 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr_0F72_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F72_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F72_4_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F72_4_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F72_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F72_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F72_2_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0F72_2_reg(mut r: i32, mut imm8: i32) -> () { c_comment!(("psrld mm, imm8")); psrld_r64(r, imm8 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr_0F72_4_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0F72_4_reg(mut r: i32, mut imm8: i32) -> () { c_comment!(("psrad mm, imm8")); psrad_r64(r, imm8 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr_0F72_6_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0F72_6_reg(mut r: i32, mut imm8: i32) -> () { c_comment!(("pslld mm, imm8")); pslld_r64(r, imm8 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr_660F72_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F72_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660F72_4_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F72_4_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660F72_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F72_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660F72_2_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660F72_2_reg(mut r: i32, mut imm8: i32) -> () { c_comment!(("psrld xmm, imm8")); psrld_r128(r, imm8 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr_660F72_4_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660F72_4_reg(mut r: i32, mut imm8: i32) -> () { c_comment!(("psrad xmm, imm8")); psrad_r128(r, imm8 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr_660F72_6_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660F72_6_reg(mut r: i32, mut imm8: i32) -> () { c_comment!(("pslld xmm, imm8")); pslld_r128(r, imm8 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr_0F73_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F73_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F73_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F73_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F73_2_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0F73_2_reg(mut r: i32, mut imm8: i32) -> () { c_comment!(("psrlq mm, imm8")); psrlq_r64(r, imm8 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr_0F73_6_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0F73_6_reg(mut r: i32, mut imm8: i32) -> () { c_comment!(("psllq mm, imm8")); psllq_r64(r, imm8 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr_660F73_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F73_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660F73_3_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F73_3_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660F73_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F73_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660F73_7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F73_7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660F73_2_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660F73_2_reg(mut r: i32, mut imm8: i32) -> () { c_comment!(("psrlq xmm, imm8")); psrlq_r128(r, imm8 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr_660F73_3_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660F73_3_reg(mut r: i32, mut imm8: i32) -> () { c_comment!(("psrldq xmm, imm8")); let mut destination: reg128 = read_xmm128s(r); if imm8 == 0i32 { @@ -2685,12 +2637,12 @@ pub unsafe extern "C" fn instr_660F73_3_reg(mut r: i32, mut imm8: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_660F73_6_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660F73_6_reg(mut r: i32, mut imm8: i32) -> () { c_comment!(("psllq xmm, imm8")); psllq_r128(r, imm8 as u32); } #[no_mangle] -pub unsafe extern "C" fn instr_660F73_7_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660F73_7_reg(mut r: i32, mut imm8: i32) -> () { c_comment!(("pslldq xmm, imm8")); let mut destination: reg128 = read_xmm128s(r); if imm8 == 0i32 { @@ -2715,7 +2667,7 @@ pub unsafe extern "C" fn instr_660F73_7_reg(mut r: i32, mut imm8: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0F74(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F74(mut source: reg64, mut r: i32) -> () { c_comment!(("pcmpeqb mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -2735,15 +2687,13 @@ pub unsafe extern "C" fn instr_0F74(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0F74_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F74(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0F74_reg(mut r1: i32, mut r2: i32) -> () { instr_0F74(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F74_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F74_mem(mut addr: i32, mut r: i32) -> () { instr_0F74(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F74(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F74(mut source: reg128, mut r: i32) -> () { c_comment!(("pcmpeqb xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -2762,15 +2712,15 @@ pub unsafe extern "C" fn instr_660F74(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660F74_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F74_reg(mut r1: i32, mut r2: i32) -> () { instr_660F74(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F74_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F74_mem(mut addr: i32, mut r: i32) -> () { instr_660F74(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F75(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F75(mut source: reg64, mut r: i32) -> () { c_comment!(("pcmpeqw mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = if destination.u16_0[0usize] as i32 == source.u16_0[0usize] as i32 { @@ -2802,15 +2752,13 @@ pub unsafe extern "C" fn instr_0F75(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe extern "C" fn instr_0F75_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F75(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0F75_reg(mut r1: i32, mut r2: i32) -> () { instr_0F75(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F75_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F75_mem(mut addr: i32, mut r: i32) -> () { instr_0F75(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F75(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F75(mut source: reg128, mut r: i32) -> () { c_comment!(("pcmpeqw xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -2829,15 +2777,15 @@ pub unsafe extern "C" fn instr_660F75(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660F75_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F75_reg(mut r1: i32, mut r2: i32) -> () { instr_660F75(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F75_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F75_mem(mut addr: i32, mut r: i32) -> () { instr_660F75(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F76(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F76(mut source: reg64, mut r: i32) -> () { c_comment!(("pcmpeqd mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut low: i32 = if destination.u32_0[0usize] == source.u32_0[0usize] { @@ -2855,15 +2803,13 @@ pub unsafe extern "C" fn instr_0F76(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe extern "C" fn instr_0F76_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F76(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0F76_reg(mut r1: i32, mut r2: i32) -> () { instr_0F76(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F76_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F76_mem(mut addr: i32, mut r: i32) -> () { instr_0F76(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F76(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F76(mut source: reg128, mut r: i32) -> () { c_comment!(("pcmpeqd xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -2896,60 +2842,58 @@ pub unsafe extern "C" fn instr_660F76(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_660F76_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F76_reg(mut r1: i32, mut r2: i32) -> () { instr_660F76(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F76_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F76_mem(mut addr: i32, mut r: i32) -> () { instr_660F76(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F77() -> () { +pub unsafe fn instr_0F77() -> () { c_comment!(("emms")); fpu_set_tag_word(65535i32); } #[no_mangle] -pub unsafe extern "C" fn instr_0F78() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F78() -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F79() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F79() -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F7A() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F7A() -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F7B() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F7B() -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F7C() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F7C() -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F7D() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F7D() -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F7E(mut r: i32) -> i32 { +pub unsafe fn instr_0F7E(mut r: i32) -> i32 { c_comment!(("movd r/m32, mm")); let mut data: reg64 = read_mmx64s(r); return data.u32_0[0usize] as i32; } #[no_mangle] -pub unsafe extern "C" fn instr_0F7E_reg(mut r1: i32, mut r2: i32) -> () { - write_reg32(r1, instr_0F7E(r2)); -} +pub unsafe fn instr_0F7E_reg(mut r1: i32, mut r2: i32) -> () { write_reg32(r1, instr_0F7E(r2)); } #[no_mangle] -pub unsafe extern "C" fn instr_0F7E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F7E_mem(mut addr: i32, mut r: i32) -> () { return_on_pagefault!(safe_write32(addr, instr_0F7E(r))); } #[no_mangle] -pub unsafe extern "C" fn instr_660F7E(mut r: i32) -> i32 { +pub unsafe fn instr_660F7E(mut r: i32) -> i32 { c_comment!(("movd r/m32, xmm")); let mut data: reg64 = read_xmm64s(r); return data.u32_0[0usize] as i32; } #[no_mangle] -pub unsafe extern "C" fn instr_660F7E_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F7E_reg(mut r1: i32, mut r2: i32) -> () { write_reg32(r1, instr_660F7E(r2)); } #[no_mangle] -pub unsafe extern "C" fn instr_660F7E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F7E_mem(mut addr: i32, mut r: i32) -> () { return_on_pagefault!(safe_write32(addr, instr_660F7E(r))); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F7E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F7E_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movq xmm, xmm/mem64")); let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); write_xmm128( @@ -2961,7 +2905,7 @@ pub unsafe extern "C" fn instr_F30F7E_mem(mut addr: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F7E_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F30F7E_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("movq xmm, xmm/mem64")); let mut data: reg64 = read_xmm64s(r1); write_xmm128( @@ -2973,240 +2917,176 @@ pub unsafe extern "C" fn instr_F30F7E_reg(mut r1: i32, mut r2: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_0F7F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F7F_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movq mm/m64, mm")); mov_r_m64(addr, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F7F_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_0F7F_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("movq mm/m64, mm")); let mut data: reg64 = read_mmx64s(r2); write_mmx64(r1, data.u32_0[0usize] as i32, data.u32_0[1usize] as i32); } #[no_mangle] -pub unsafe extern "C" fn instr_660F7F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F7F_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movdqa xmm/m128, xmm")); c_comment!(("XXX: Aligned write or #gp")); mov_r_m128(addr, r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F7F_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F7F_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("movdqa xmm/m128, xmm")); c_comment!(("XXX: Aligned access or #gp")); mov_r_r128(r1, r2); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F7F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F7F_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movdqu xmm/m128, xmm")); mov_r_m128(addr, r); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F7F_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F30F7F_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("movdqu xmm/m128, xmm")); mov_r_r128(r1, r2); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F80(mut imm: i32) -> () { jmpcc16(test_o(), imm); } +pub unsafe fn instr16_0F80(mut imm: i32) -> () { jmpcc16(test_o(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F80(mut imm: i32) -> () { jmpcc32(test_o(), imm); } +pub unsafe fn instr32_0F80(mut imm: i32) -> () { jmpcc32(test_o(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F81(mut imm: i32) -> () { jmpcc16(!test_o(), imm); } +pub unsafe fn instr16_0F81(mut imm: i32) -> () { jmpcc16(!test_o(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F81(mut imm: i32) -> () { jmpcc32(!test_o(), imm); } +pub unsafe fn instr32_0F81(mut imm: i32) -> () { jmpcc32(!test_o(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F82(mut imm: i32) -> () { jmpcc16(test_b(), imm); } +pub unsafe fn instr16_0F82(mut imm: i32) -> () { jmpcc16(test_b(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F82(mut imm: i32) -> () { jmpcc32(test_b(), imm); } +pub unsafe fn instr32_0F82(mut imm: i32) -> () { jmpcc32(test_b(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F83(mut imm: i32) -> () { jmpcc16(!test_b(), imm); } +pub unsafe fn instr16_0F83(mut imm: i32) -> () { jmpcc16(!test_b(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F83(mut imm: i32) -> () { jmpcc32(!test_b(), imm); } +pub unsafe fn instr32_0F83(mut imm: i32) -> () { jmpcc32(!test_b(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F84(mut imm: i32) -> () { jmpcc16(test_z(), imm); } +pub unsafe fn instr16_0F84(mut imm: i32) -> () { jmpcc16(test_z(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F84(mut imm: i32) -> () { jmpcc32(test_z(), imm); } +pub unsafe fn instr32_0F84(mut imm: i32) -> () { jmpcc32(test_z(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F85(mut imm: i32) -> () { jmpcc16(!test_z(), imm); } +pub unsafe fn instr16_0F85(mut imm: i32) -> () { jmpcc16(!test_z(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F85(mut imm: i32) -> () { jmpcc32(!test_z(), imm); } +pub unsafe fn instr32_0F85(mut imm: i32) -> () { jmpcc32(!test_z(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F86(mut imm: i32) -> () { jmpcc16(test_be(), imm); } +pub unsafe fn instr16_0F86(mut imm: i32) -> () { jmpcc16(test_be(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F86(mut imm: i32) -> () { jmpcc32(test_be(), imm); } +pub unsafe fn instr32_0F86(mut imm: i32) -> () { jmpcc32(test_be(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F87(mut imm: i32) -> () { jmpcc16(!test_be(), imm); } +pub unsafe fn instr16_0F87(mut imm: i32) -> () { jmpcc16(!test_be(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F87(mut imm: i32) -> () { jmpcc32(!test_be(), imm); } +pub unsafe fn instr32_0F87(mut imm: i32) -> () { jmpcc32(!test_be(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F88(mut imm: i32) -> () { jmpcc16(test_s(), imm); } +pub unsafe fn instr16_0F88(mut imm: i32) -> () { jmpcc16(test_s(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F88(mut imm: i32) -> () { jmpcc32(test_s(), imm); } +pub unsafe fn instr32_0F88(mut imm: i32) -> () { jmpcc32(test_s(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F89(mut imm: i32) -> () { jmpcc16(!test_s(), imm); } +pub unsafe fn instr16_0F89(mut imm: i32) -> () { jmpcc16(!test_s(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F89(mut imm: i32) -> () { jmpcc32(!test_s(), imm); } +pub unsafe fn instr32_0F89(mut imm: i32) -> () { jmpcc32(!test_s(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F8A(mut imm: i32) -> () { jmpcc16(test_p(), imm); } +pub unsafe fn instr16_0F8A(mut imm: i32) -> () { jmpcc16(test_p(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F8A(mut imm: i32) -> () { jmpcc32(test_p(), imm); } +pub unsafe fn instr32_0F8A(mut imm: i32) -> () { jmpcc32(test_p(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F8B(mut imm: i32) -> () { jmpcc16(!test_p(), imm); } +pub unsafe fn instr16_0F8B(mut imm: i32) -> () { jmpcc16(!test_p(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F8B(mut imm: i32) -> () { jmpcc32(!test_p(), imm); } +pub unsafe fn instr32_0F8B(mut imm: i32) -> () { jmpcc32(!test_p(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F8C(mut imm: i32) -> () { jmpcc16(test_l(), imm); } +pub unsafe fn instr16_0F8C(mut imm: i32) -> () { jmpcc16(test_l(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F8C(mut imm: i32) -> () { jmpcc32(test_l(), imm); } +pub unsafe fn instr32_0F8C(mut imm: i32) -> () { jmpcc32(test_l(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F8D(mut imm: i32) -> () { jmpcc16(!test_l(), imm); } +pub unsafe fn instr16_0F8D(mut imm: i32) -> () { jmpcc16(!test_l(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F8D(mut imm: i32) -> () { jmpcc32(!test_l(), imm); } +pub unsafe fn instr32_0F8D(mut imm: i32) -> () { jmpcc32(!test_l(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F8E(mut imm: i32) -> () { jmpcc16(test_le(), imm); } +pub unsafe fn instr16_0F8E(mut imm: i32) -> () { jmpcc16(test_le(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F8E(mut imm: i32) -> () { jmpcc32(test_le(), imm); } +pub unsafe fn instr32_0F8E(mut imm: i32) -> () { jmpcc32(test_le(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr16_0F8F(mut imm: i32) -> () { jmpcc16(!test_le(), imm); } +pub unsafe fn instr16_0F8F(mut imm: i32) -> () { jmpcc16(!test_le(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr32_0F8F(mut imm: i32) -> () { jmpcc32(!test_le(), imm); } +pub unsafe fn instr32_0F8F(mut imm: i32) -> () { jmpcc32(!test_le(), imm); } #[no_mangle] -pub unsafe extern "C" fn instr_0F90_reg(mut r: i32, mut unused: i32) -> () { - setcc_reg(test_o(), r); -} +pub unsafe fn instr_0F90_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(test_o(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F91_reg(mut r: i32, mut unused: i32) -> () { - setcc_reg(!test_o(), r); -} +pub unsafe fn instr_0F91_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(!test_o(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F92_reg(mut r: i32, mut unused: i32) -> () { - setcc_reg(test_b(), r); -} +pub unsafe fn instr_0F92_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(test_b(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F93_reg(mut r: i32, mut unused: i32) -> () { - setcc_reg(!test_b(), r); -} +pub unsafe fn instr_0F93_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(!test_b(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F94_reg(mut r: i32, mut unused: i32) -> () { - setcc_reg(test_z(), r); -} +pub unsafe fn instr_0F94_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(test_z(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F95_reg(mut r: i32, mut unused: i32) -> () { - setcc_reg(!test_z(), r); -} +pub unsafe fn instr_0F95_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(!test_z(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F96_reg(mut r: i32, mut unused: i32) -> () { - setcc_reg(test_be(), r); -} +pub unsafe fn instr_0F96_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(test_be(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F97_reg(mut r: i32, mut unused: i32) -> () { - setcc_reg(!test_be(), r); -} +pub unsafe fn instr_0F97_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(!test_be(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F98_reg(mut r: i32, mut unused: i32) -> () { - setcc_reg(test_s(), r); -} +pub unsafe fn instr_0F98_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(test_s(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F99_reg(mut r: i32, mut unused: i32) -> () { - setcc_reg(!test_s(), r); -} +pub unsafe fn instr_0F99_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(!test_s(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F9A_reg(mut r: i32, mut unused: i32) -> () { - setcc_reg(test_p(), r); -} +pub unsafe fn instr_0F9A_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(test_p(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F9B_reg(mut r: i32, mut unused: i32) -> () { - setcc_reg(!test_p(), r); -} +pub unsafe fn instr_0F9B_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(!test_p(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F9C_reg(mut r: i32, mut unused: i32) -> () { - setcc_reg(test_l(), r); -} +pub unsafe fn instr_0F9C_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(test_l(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F9D_reg(mut r: i32, mut unused: i32) -> () { - setcc_reg(!test_l(), r); -} +pub unsafe fn instr_0F9D_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(!test_l(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F9E_reg(mut r: i32, mut unused: i32) -> () { - setcc_reg(test_le(), r); -} +pub unsafe fn instr_0F9E_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(test_le(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F9F_reg(mut r: i32, mut unused: i32) -> () { - setcc_reg(!test_le(), r); -} +pub unsafe fn instr_0F9F_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(!test_le(), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F90_mem(mut addr: i32, mut unused: i32) -> () { - setcc_mem(test_o(), addr); -} +pub unsafe fn instr_0F90_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(test_o(), addr); } #[no_mangle] -pub unsafe extern "C" fn instr_0F91_mem(mut addr: i32, mut unused: i32) -> () { - setcc_mem(!test_o(), addr); -} +pub unsafe fn instr_0F91_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(!test_o(), addr); } #[no_mangle] -pub unsafe extern "C" fn instr_0F92_mem(mut addr: i32, mut unused: i32) -> () { - setcc_mem(test_b(), addr); -} +pub unsafe fn instr_0F92_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(test_b(), addr); } #[no_mangle] -pub unsafe extern "C" fn instr_0F93_mem(mut addr: i32, mut unused: i32) -> () { - setcc_mem(!test_b(), addr); -} +pub unsafe fn instr_0F93_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(!test_b(), addr); } #[no_mangle] -pub unsafe extern "C" fn instr_0F94_mem(mut addr: i32, mut unused: i32) -> () { - setcc_mem(test_z(), addr); -} +pub unsafe fn instr_0F94_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(test_z(), addr); } #[no_mangle] -pub unsafe extern "C" fn instr_0F95_mem(mut addr: i32, mut unused: i32) -> () { - setcc_mem(!test_z(), addr); -} +pub unsafe fn instr_0F95_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(!test_z(), addr); } #[no_mangle] -pub unsafe extern "C" fn instr_0F96_mem(mut addr: i32, mut unused: i32) -> () { - setcc_mem(test_be(), addr); -} +pub unsafe fn instr_0F96_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(test_be(), addr); } #[no_mangle] -pub unsafe extern "C" fn instr_0F97_mem(mut addr: i32, mut unused: i32) -> () { - setcc_mem(!test_be(), addr); -} +pub unsafe fn instr_0F97_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(!test_be(), addr); } #[no_mangle] -pub unsafe extern "C" fn instr_0F98_mem(mut addr: i32, mut unused: i32) -> () { - setcc_mem(test_s(), addr); -} +pub unsafe fn instr_0F98_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(test_s(), addr); } #[no_mangle] -pub unsafe extern "C" fn instr_0F99_mem(mut addr: i32, mut unused: i32) -> () { - setcc_mem(!test_s(), addr); -} +pub unsafe fn instr_0F99_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(!test_s(), addr); } #[no_mangle] -pub unsafe extern "C" fn instr_0F9A_mem(mut addr: i32, mut unused: i32) -> () { - setcc_mem(test_p(), addr); -} +pub unsafe fn instr_0F9A_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(test_p(), addr); } #[no_mangle] -pub unsafe extern "C" fn instr_0F9B_mem(mut addr: i32, mut unused: i32) -> () { - setcc_mem(!test_p(), addr); -} +pub unsafe fn instr_0F9B_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(!test_p(), addr); } #[no_mangle] -pub unsafe extern "C" fn instr_0F9C_mem(mut addr: i32, mut unused: i32) -> () { - setcc_mem(test_l(), addr); -} +pub unsafe fn instr_0F9C_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(test_l(), addr); } #[no_mangle] -pub unsafe extern "C" fn instr_0F9D_mem(mut addr: i32, mut unused: i32) -> () { - setcc_mem(!test_l(), addr); -} +pub unsafe fn instr_0F9D_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(!test_l(), addr); } #[no_mangle] -pub unsafe extern "C" fn instr_0F9E_mem(mut addr: i32, mut unused: i32) -> () { - setcc_mem(test_le(), addr); -} +pub unsafe fn instr_0F9E_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(test_le(), addr); } #[no_mangle] -pub unsafe extern "C" fn instr_0F9F_mem(mut addr: i32, mut unused: i32) -> () { - setcc_mem(!test_le(), addr); -} +pub unsafe fn instr_0F9F_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(!test_le(), addr); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FA0() -> () { +pub unsafe fn instr16_0FA0() -> () { return_on_pagefault!(push16(*sreg.offset(FS as isize) as i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FA0() -> () { +pub unsafe fn instr32_0FA0() -> () { return_on_pagefault!(push32(*sreg.offset(FS as isize) as i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FA1() -> () { +pub unsafe fn instr16_0FA1() -> () { if !switch_seg( FS, return_on_pagefault!(safe_read16(get_stack_pointer(0i32))), @@ -3219,7 +3099,7 @@ pub unsafe extern "C" fn instr16_0FA1() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr32_0FA1() -> () { +pub unsafe fn instr32_0FA1() -> () { if !switch_seg( FS, return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))) & 65535i32, @@ -3232,43 +3112,41 @@ pub unsafe extern "C" fn instr32_0FA1() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0FA2() -> () { cpuid(); } +pub unsafe fn instr_0FA2() -> () { cpuid(); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FA3_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr16_0FA3_reg(mut r1: i32, mut r2: i32) -> () { bt_reg(read_reg16(r1), read_reg16(r2) & 15i32); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FA3_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FA3_mem(mut addr: i32, mut r: i32) -> () { bt_mem(addr, read_reg16(r) << 16i32 >> 16i32); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FA3_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr32_0FA3_reg(mut r1: i32, mut r2: i32) -> () { bt_reg(read_reg32(r1), read_reg32(r2) & 31i32); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FA3_mem(mut addr: i32, mut r: i32) -> () { - bt_mem(addr, read_reg32(r)); -} +pub unsafe fn instr32_0FA3_mem(mut addr: i32, mut r: i32) -> () { bt_mem(addr, read_reg32(r)); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FA4_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr16_0FA4_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, shld16(___, read_reg16(r), imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FA4_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr16_0FA4_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, shld16(____0, read_reg16(r), imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FA4_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr32_0FA4_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, shld32(___, read_reg32(r), imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FA4_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr32_0FA4_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, shld32(____0, read_reg32(r), imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FA5_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FA5_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE16!( ___, addr, @@ -3276,7 +3154,7 @@ pub unsafe extern "C" fn instr16_0FA5_mem(mut addr: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FA5_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FA5_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16( r1, @@ -3288,7 +3166,7 @@ pub unsafe extern "C" fn instr16_0FA5_reg(mut r1: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FA5_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FA5_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE32!( ___, addr, @@ -3296,7 +3174,7 @@ pub unsafe extern "C" fn instr32_0FA5_mem(mut addr: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FA5_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FA5_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32( r1, @@ -3308,22 +3186,22 @@ pub unsafe extern "C" fn instr32_0FA5_reg(mut r1: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_0FA6() -> () { +pub unsafe fn instr_0FA6() -> () { c_comment!(("obsolete cmpxchg (os/2)")); trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0FA7() -> () { undefined_instruction(); } +pub unsafe fn instr_0FA7() -> () { undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FA8() -> () { +pub unsafe fn instr16_0FA8() -> () { return_on_pagefault!(push16(*sreg.offset(GS as isize) as i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FA8() -> () { +pub unsafe fn instr32_0FA8() -> () { return_on_pagefault!(push32(*sreg.offset(GS as isize) as i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FA9() -> () { +pub unsafe fn instr16_0FA9() -> () { if !switch_seg( GS, return_on_pagefault!(safe_read16(get_stack_pointer(0i32))), @@ -3336,7 +3214,7 @@ pub unsafe extern "C" fn instr16_0FA9() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr32_0FA9() -> () { +pub unsafe fn instr32_0FA9() -> () { if !switch_seg( GS, return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))) & 65535i32, @@ -3349,46 +3227,44 @@ pub unsafe extern "C" fn instr32_0FA9() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0FAA() -> () { +pub unsafe fn instr_0FAA() -> () { c_comment!(("rsm")); undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FAB_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr16_0FAB_reg(mut r1: i32, mut r2: i32) -> () { write_reg16(r1, bts_reg(read_reg16(r1), read_reg16(r2) & 15i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FAB_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FAB_mem(mut addr: i32, mut r: i32) -> () { bts_mem(addr, read_reg16(r) << 16i32 >> 16i32); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FAB_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr32_0FAB_reg(mut r1: i32, mut r2: i32) -> () { write_reg32(r1, bts_reg(read_reg32(r1), read_reg32(r2) & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FAB_mem(mut addr: i32, mut r: i32) -> () { - bts_mem(addr, read_reg32(r)); -} +pub unsafe fn instr32_0FAB_mem(mut addr: i32, mut r: i32) -> () { bts_mem(addr, read_reg32(r)); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FAC_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr16_0FAC_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { SAFE_READ_WRITE16!(___, addr, shrd16(___, read_reg16(r), imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FAC_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr16_0FAC_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, shrd16(____0, read_reg16(r), imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FAC_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr32_0FAC_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { SAFE_READ_WRITE32!(___, addr, shrd32(___, read_reg32(r), imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FAC_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr32_0FAC_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, shrd32(____0, read_reg32(r), imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FAD_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FAD_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE16!( ___, addr, @@ -3396,7 +3272,7 @@ pub unsafe extern "C" fn instr16_0FAD_mem(mut addr: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FAD_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FAD_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16( r1, @@ -3408,7 +3284,7 @@ pub unsafe extern "C" fn instr16_0FAD_reg(mut r1: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FAD_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FAD_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE32!( ___, addr, @@ -3416,7 +3292,7 @@ pub unsafe extern "C" fn instr32_0FAD_mem(mut addr: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FAD_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FAD_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32( r1, @@ -3428,17 +3304,17 @@ pub unsafe extern "C" fn instr32_0FAD_reg(mut r1: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_0FAE_0_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FAE_0_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0FAE_0_mem(mut addr: i32) -> () { fxsave(addr as u32); } +pub unsafe fn instr_0FAE_0_mem(mut addr: i32) -> () { fxsave(addr as u32); } #[no_mangle] -pub unsafe extern "C" fn instr_0FAE_1_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FAE_1_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0FAE_1_mem(mut addr: i32) -> () { fxrstor(addr as u32); } +pub unsafe fn instr_0FAE_1_mem(mut addr: i32) -> () { fxrstor(addr as u32); } #[no_mangle] -pub unsafe extern "C" fn instr_0FAE_2_reg(mut r: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_0FAE_2_reg(mut r: i32) -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0FAE_2_mem(mut addr: i32) -> () { +pub unsafe fn instr_0FAE_2_mem(mut addr: i32) -> () { c_comment!(("ldmxcsr")); let mut new_mxcsr: i32 = return_on_pagefault!(safe_read32s(addr)); if 0 != new_mxcsr & !MXCSR_MASK { @@ -3453,51 +3329,51 @@ pub unsafe extern "C" fn instr_0FAE_2_mem(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0FAE_3_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FAE_3_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0FAE_3_mem(mut addr: i32) -> () { +pub unsafe fn instr_0FAE_3_mem(mut addr: i32) -> () { c_comment!(("stmxcsr")); return_on_pagefault!(safe_write32(addr, *mxcsr)); } #[no_mangle] -pub unsafe extern "C" fn instr_0FAE_4_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FAE_4_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0FAE_4_mem(mut addr: i32) -> () { +pub unsafe fn instr_0FAE_4_mem(mut addr: i32) -> () { c_comment!(("xsave")); undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr_0FAE_5_reg(mut r: i32) -> () { +pub unsafe fn instr_0FAE_5_reg(mut r: i32) -> () { c_comment!(("lfence")); dbg_assert!(r == 0i32, ("Unexpected lfence encoding")); } #[no_mangle] -pub unsafe extern "C" fn instr_0FAE_5_mem(mut addr: i32) -> () { +pub unsafe fn instr_0FAE_5_mem(mut addr: i32) -> () { c_comment!(("xrstor")); undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr_0FAE_6_reg(mut r: i32) -> () { +pub unsafe fn instr_0FAE_6_reg(mut r: i32) -> () { c_comment!(("mfence")); dbg_assert!(r == 0i32, ("Unexpected mfence encoding")); } #[no_mangle] -pub unsafe extern "C" fn instr_0FAE_6_mem(mut addr: i32) -> () { +pub unsafe fn instr_0FAE_6_mem(mut addr: i32) -> () { c_comment!(("xsaveopt")); undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr_0FAE_7_reg(mut r: i32) -> () { +pub unsafe fn instr_0FAE_7_reg(mut r: i32) -> () { c_comment!(("sfence")); dbg_assert!(r == 0i32, ("Unexpected sfence encoding")); } #[no_mangle] -pub unsafe extern "C" fn instr_0FAE_7_mem(mut addr: i32) -> () { +pub unsafe fn instr_0FAE_7_mem(mut addr: i32) -> () { c_comment!(("clflush")); undefined_instruction(); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FAF_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FAF_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16( r, @@ -3505,7 +3381,7 @@ pub unsafe extern "C" fn instr16_0FAF_mem(mut addr: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FAF_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FAF_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16( r, @@ -3513,17 +3389,17 @@ pub unsafe extern "C" fn instr16_0FAF_reg(mut r1: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FAF_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FAF_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, imul_reg32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FAF_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FAF_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r, imul_reg32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr_0FB0_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_0FB0_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("cmpxchg8")); let mut data: i32 = read_reg8(r1); cmp8(*reg8.offset(AL as isize) as i32, data); @@ -3535,7 +3411,7 @@ pub unsafe extern "C" fn instr_0FB0_reg(mut r1: i32, mut r2: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr_0FB0_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FB0_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("cmpxchg8")); return_on_pagefault!(writable_or_pagefault(addr, 1i32)); let mut data: i32 = return_on_pagefault!(safe_read8(addr)); @@ -3549,7 +3425,7 @@ pub unsafe extern "C" fn instr_0FB0_mem(mut addr: i32, mut r: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr16_0FB1_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr16_0FB1_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("cmpxchg16")); let mut data: i32 = read_reg16(r1); cmp16(*reg16.offset(AX as isize) as i32, data); @@ -3561,7 +3437,7 @@ pub unsafe extern "C" fn instr16_0FB1_reg(mut r1: i32, mut r2: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr16_0FB1_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FB1_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("cmpxchg16")); return_on_pagefault!(writable_or_pagefault(addr, 2i32)); let mut data: i32 = return_on_pagefault!(safe_read16(addr)); @@ -3575,7 +3451,7 @@ pub unsafe extern "C" fn instr16_0FB1_mem(mut addr: i32, mut r: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr32_0FB1_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr32_0FB1_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("cmpxchg32")); let mut data: i32 = read_reg32(r1); cmp32(*reg32s.offset(EAX as isize), data); @@ -3587,7 +3463,7 @@ pub unsafe extern "C" fn instr32_0FB1_reg(mut r1: i32, mut r2: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr32_0FB1_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FB1_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("cmpxchg32")); return_on_pagefault!(writable_or_pagefault(addr, 4i32)); let mut data: i32 = return_on_pagefault!(safe_read32s(addr)); @@ -3601,320 +3477,300 @@ pub unsafe extern "C" fn instr32_0FB1_mem(mut addr: i32, mut r: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn instr16_0FB2_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } +pub unsafe fn instr16_0FB2_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FB2_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FB2_mem(mut addr: i32, mut r: i32) -> () { lss16(addr, get_reg16_index(r), SS); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FB2_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } +pub unsafe fn instr32_0FB2_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FB2_mem(mut addr: i32, mut r: i32) -> () { lss32(addr, r, SS); } +pub unsafe fn instr32_0FB2_mem(mut addr: i32, mut r: i32) -> () { lss32(addr, r, SS); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FB3_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr16_0FB3_reg(mut r1: i32, mut r2: i32) -> () { write_reg16(r1, btr_reg(read_reg16(r1), read_reg16(r2) & 15i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FB3_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FB3_mem(mut addr: i32, mut r: i32) -> () { btr_mem(addr, read_reg16(r) << 16i32 >> 16i32); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FB3_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr32_0FB3_reg(mut r1: i32, mut r2: i32) -> () { write_reg32(r1, btr_reg(read_reg32(r1), read_reg32(r2) & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FB3_mem(mut addr: i32, mut r: i32) -> () { - btr_mem(addr, read_reg32(r)); -} +pub unsafe fn instr32_0FB3_mem(mut addr: i32, mut r: i32) -> () { btr_mem(addr, read_reg32(r)); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FB4_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } +pub unsafe fn instr16_0FB4_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FB4_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FB4_mem(mut addr: i32, mut r: i32) -> () { lss16(addr, get_reg16_index(r), FS); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FB4_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } +pub unsafe fn instr32_0FB4_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FB4_mem(mut addr: i32, mut r: i32) -> () { lss32(addr, r, FS); } +pub unsafe fn instr32_0FB4_mem(mut addr: i32, mut r: i32) -> () { lss32(addr, r, FS); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FB5_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } +pub unsafe fn instr16_0FB5_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FB5_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FB5_mem(mut addr: i32, mut r: i32) -> () { lss16(addr, get_reg16_index(r), GS); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FB5_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } +pub unsafe fn instr32_0FB5_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FB5_mem(mut addr: i32, mut r: i32) -> () { lss32(addr, r, GS); } +pub unsafe fn instr32_0FB5_mem(mut addr: i32, mut r: i32) -> () { lss32(addr, r, GS); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FB6_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FB6_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg16(r, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FB6_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FB6_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg16(r, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FB6_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FB6_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg32(r, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FB6_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FB6_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg32(r, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FB7_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FB7_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FB7_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FB7_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FB7_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FB7_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg32(r, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FB7_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FB7_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg32(r, ____0); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FB8_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr16_0FB8_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FB8_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr16_0FB8_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr16_F30FB8_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_F30FB8_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, popcnt(____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_F30FB8_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_F30FB8_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r, popcnt(____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FB8_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr32_0FB8_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FB8_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr32_0FB8_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr32_F30FB8_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_F30FB8_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, popcnt(____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_F30FB8_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_F30FB8_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r, popcnt(____0)); } #[no_mangle] -pub unsafe extern "C" fn instr_0FB9() -> () { +pub unsafe fn instr_0FB9() -> () { c_comment!(("UD2")); trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FBA_4_reg(mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr16_0FBA_4_reg(mut r: i32, mut imm: i32) -> () { bt_reg(read_reg16(r), imm & 15i32); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FBA_4_mem(mut addr: i32, mut imm: i32) -> () { - bt_mem(addr, imm & 15i32); -} +pub unsafe fn instr16_0FBA_4_mem(mut addr: i32, mut imm: i32) -> () { bt_mem(addr, imm & 15i32); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FBA_5_reg(mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr16_0FBA_5_reg(mut r: i32, mut imm: i32) -> () { write_reg16(r, bts_reg(read_reg16(r), imm & 15i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FBA_5_mem(mut addr: i32, mut imm: i32) -> () { - bts_mem(addr, imm & 15i32); -} +pub unsafe fn instr16_0FBA_5_mem(mut addr: i32, mut imm: i32) -> () { bts_mem(addr, imm & 15i32); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FBA_6_reg(mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr16_0FBA_6_reg(mut r: i32, mut imm: i32) -> () { write_reg16(r, btr_reg(read_reg16(r), imm & 15i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FBA_6_mem(mut addr: i32, mut imm: i32) -> () { - btr_mem(addr, imm & 15i32); -} +pub unsafe fn instr16_0FBA_6_mem(mut addr: i32, mut imm: i32) -> () { btr_mem(addr, imm & 15i32); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FBA_7_reg(mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr16_0FBA_7_reg(mut r: i32, mut imm: i32) -> () { write_reg16(r, btc_reg(read_reg16(r), imm & 15i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FBA_7_mem(mut addr: i32, mut imm: i32) -> () { - btc_mem(addr, imm & 15i32); -} +pub unsafe fn instr16_0FBA_7_mem(mut addr: i32, mut imm: i32) -> () { btc_mem(addr, imm & 15i32); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FBA_4_reg(mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr32_0FBA_4_reg(mut r: i32, mut imm: i32) -> () { bt_reg(read_reg32(r), imm & 31i32); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FBA_4_mem(mut addr: i32, mut imm: i32) -> () { - bt_mem(addr, imm & 31i32); -} +pub unsafe fn instr32_0FBA_4_mem(mut addr: i32, mut imm: i32) -> () { bt_mem(addr, imm & 31i32); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FBA_5_reg(mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr32_0FBA_5_reg(mut r: i32, mut imm: i32) -> () { write_reg32(r, bts_reg(read_reg32(r), imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FBA_5_mem(mut addr: i32, mut imm: i32) -> () { - bts_mem(addr, imm & 31i32); -} +pub unsafe fn instr32_0FBA_5_mem(mut addr: i32, mut imm: i32) -> () { bts_mem(addr, imm & 31i32); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FBA_6_reg(mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr32_0FBA_6_reg(mut r: i32, mut imm: i32) -> () { write_reg32(r, btr_reg(read_reg32(r), imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FBA_6_mem(mut addr: i32, mut imm: i32) -> () { - btr_mem(addr, imm & 31i32); -} +pub unsafe fn instr32_0FBA_6_mem(mut addr: i32, mut imm: i32) -> () { btr_mem(addr, imm & 31i32); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FBA_7_reg(mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr32_0FBA_7_reg(mut r: i32, mut imm: i32) -> () { write_reg32(r, btc_reg(read_reg32(r), imm & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FBA_7_mem(mut addr: i32, mut imm: i32) -> () { - btc_mem(addr, imm & 31i32); -} +pub unsafe fn instr32_0FBA_7_mem(mut addr: i32, mut imm: i32) -> () { btc_mem(addr, imm & 31i32); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FBB_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr16_0FBB_reg(mut r1: i32, mut r2: i32) -> () { write_reg16(r1, btc_reg(read_reg16(r1), read_reg16(r2) & 15i32)); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FBB_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FBB_mem(mut addr: i32, mut r: i32) -> () { btc_mem(addr, read_reg16(r) << 16i32 >> 16i32); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FBB_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr32_0FBB_reg(mut r1: i32, mut r2: i32) -> () { write_reg32(r1, btc_reg(read_reg32(r1), read_reg32(r2) & 31i32)); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FBB_mem(mut addr: i32, mut r: i32) -> () { - btc_mem(addr, read_reg32(r)); -} +pub unsafe fn instr32_0FBB_mem(mut addr: i32, mut r: i32) -> () { btc_mem(addr, read_reg32(r)); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FBC_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FBC_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, bsf16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FBC_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FBC_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r, bsf16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FBC_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FBC_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, bsf32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FBC_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FBC_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r, bsf32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FBD_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FBD_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, bsr16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FBD_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FBD_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r, bsr16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FBD_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FBD_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, bsr32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FBD_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FBD_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r, bsr32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FBE_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FBE_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg16(r, ____0 << 24i32 >> 24i32); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FBE_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FBE_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg16(r, ____0 << 24i32 >> 24i32); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FBE_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FBE_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg32(r, ____0 << 24i32 >> 24i32); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FBE_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FBE_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg32(r, ____0 << 24i32 >> 24i32); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FBF_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FBF_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, ____0 << 16i32 >> 16i32); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FBF_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FBF_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r, ____0 << 16i32 >> 16i32); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FBF_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FBF_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg32(r, ____0 << 16i32 >> 16i32); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FBF_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FBF_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg32(r, ____0 << 16i32 >> 16i32); } #[no_mangle] -pub unsafe extern "C" fn instr_0FC0_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FC0_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE8!(___, addr, xadd8(___, get_reg8_index(r))); } #[no_mangle] -pub unsafe extern "C" fn instr_0FC0_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_0FC0_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, xadd8(____0, get_reg8_index(r))); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FC1_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FC1_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE16!(___, addr, xadd16(___, get_reg16_index(r))); } #[no_mangle] -pub unsafe extern "C" fn instr16_0FC1_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FC1_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, xadd16(____0, get_reg16_index(r))); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FC1_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FC1_mem(mut addr: i32, mut r: i32) -> () { SAFE_READ_WRITE32!(___, addr, xadd32(___, r)); } #[no_mangle] -pub unsafe extern "C" fn instr32_0FC1_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FC1_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, xadd32(____0, r)); } #[no_mangle] -pub unsafe extern "C" fn instr_0FC3_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FC3_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0FC3_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FC3_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movnti")); return_on_pagefault!(safe_write32(addr, read_reg32(r))); } #[no_mangle] -pub unsafe extern "C" fn instr_0FC4(mut source: i32, mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0FC4(mut source: i32, mut r: i32, mut imm8: i32) -> () { c_comment!(("pinsrw mm, r32/m16, imm8")); let mut destination: reg64 = read_mmx64s(r); let mut index: u32 = (imm8 & 3i32) as u32; @@ -3922,15 +3778,15 @@ pub unsafe extern "C" fn instr_0FC4(mut source: i32, mut r: i32, mut imm8: i32) write_mmx_reg64(r, destination); } #[no_mangle] -pub unsafe extern "C" fn instr_0FC4_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { +pub unsafe fn instr_0FC4_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { instr_0FC4(read_reg32(r1), r2, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_0FC4_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr_0FC4_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { instr_0FC4(return_on_pagefault!(safe_read16(addr)), r, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_660FC4(mut source: i32, mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660FC4(mut source: i32, mut r: i32, mut imm8: i32) -> () { c_comment!(("pinsrw xmm, r32/m16, imm8")); let mut destination: reg128 = read_xmm128s(r); let mut index: u32 = (imm8 & 7i32) as u32; @@ -3938,19 +3794,17 @@ pub unsafe extern "C" fn instr_660FC4(mut source: i32, mut r: i32, mut imm8: i32 write_xmm_reg128(r, destination); } #[no_mangle] -pub unsafe extern "C" fn instr_660FC4_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { +pub unsafe fn instr_660FC4_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { instr_660FC4(read_reg32(r1), r2, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_660FC4_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr_660FC4_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { instr_660FC4(return_on_pagefault!(safe_read16(addr)), r, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_0FC5_mem(mut addr: i32, mut r: i32, mut imm8: i32) -> () { - trigger_ud(); -} +pub unsafe fn instr_0FC5_mem(mut addr: i32, mut r: i32, mut imm8: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i32) -> () { c_comment!(("pextrw r32, mm, imm8")); let mut data: reg64 = read_mmx64s(r1); let mut index: u32 = (imm8 & 3i32) as u32; @@ -3958,11 +3812,9 @@ pub unsafe extern "C" fn instr_0FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i32) write_reg32(r2, result as i32); } #[no_mangle] -pub unsafe extern "C" fn instr_660FC5_mem(mut addr: i32, mut r: i32, mut imm8: i32) -> () { - trigger_ud(); -} +pub unsafe fn instr_660FC5_mem(mut addr: i32, mut r: i32, mut imm8: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i32) -> () { c_comment!(("pextrw r32, xmm, imm8")); let mut data: reg128 = read_xmm128s(r1); let mut index: u32 = (imm8 & 7i32) as u32; @@ -3970,11 +3822,11 @@ pub unsafe extern "C" fn instr_660FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i3 write_reg32(r2, result as i32); } #[no_mangle] -pub unsafe extern "C" fn instr_0FC6() -> () { unimplemented_sse(); } +pub unsafe fn instr_0FC6() -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0FC7_1_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FC7_1_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0FC7_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_0FC7_1_mem(mut addr: i32) -> () { c_comment!(("cmpxchg8b")); return_on_pagefault!(writable_or_pagefault(addr, 8i32)); let mut m64_low: i32 = return_on_pagefault!(safe_read32s(addr)); @@ -3997,7 +3849,7 @@ pub unsafe extern "C" fn instr_0FC7_1_mem(mut addr: i32) -> () { *fresh4 &= !FLAG_ZERO; } #[no_mangle] -pub unsafe extern "C" fn instr_0FC7_6_reg(mut r: i32) -> () { +pub unsafe fn instr_0FC7_6_reg(mut r: i32) -> () { c_comment!(("rdrand")); let mut has_rand: i32 = has_rand_int() as i32; let mut rand: i32 = 0i32; @@ -4012,107 +3864,101 @@ pub unsafe extern "C" fn instr_0FC7_6_reg(mut r: i32) -> () { *flags_changed.offset(0isize) = 0i32; } #[no_mangle] -pub unsafe extern "C" fn instr_0FC7_6_mem(mut addr: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FC7_6_mem(mut addr: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0FC8() -> () { bswap(EAX); } +pub unsafe fn instr_0FC8() -> () { bswap(EAX); } #[no_mangle] -pub unsafe extern "C" fn instr_0FC9() -> () { bswap(ECX); } +pub unsafe fn instr_0FC9() -> () { bswap(ECX); } #[no_mangle] -pub unsafe extern "C" fn instr_0FCA() -> () { bswap(EDX); } +pub unsafe fn instr_0FCA() -> () { bswap(EDX); } #[no_mangle] -pub unsafe extern "C" fn instr_0FCB() -> () { bswap(EBX); } +pub unsafe fn instr_0FCB() -> () { bswap(EBX); } #[no_mangle] -pub unsafe extern "C" fn instr_0FCC() -> () { bswap(ESP); } +pub unsafe fn instr_0FCC() -> () { bswap(ESP); } #[no_mangle] -pub unsafe extern "C" fn instr_0FCD() -> () { bswap(EBP); } +pub unsafe fn instr_0FCD() -> () { bswap(EBP); } #[no_mangle] -pub unsafe extern "C" fn instr_0FCE() -> () { bswap(ESI); } +pub unsafe fn instr_0FCE() -> () { bswap(ESI); } #[no_mangle] -pub unsafe extern "C" fn instr_0FCF() -> () { bswap(EDI); } +pub unsafe fn instr_0FCF() -> () { bswap(EDI); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD0() -> () { unimplemented_sse(); } +pub unsafe fn instr_0FD0() -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD1(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FD1(mut source: reg64, mut r: i32) -> () { c_comment!(("psrlw mm, mm/m64")); psrlw_r64(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD1_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FD1(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FD1_reg(mut r1: i32, mut r2: i32) -> () { instr_0FD1(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD1_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FD1_mem(mut addr: i32, mut r: i32) -> () { instr_0FD1(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD1(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FD1(mut source: reg128, mut r: i32) -> () { c_comment!(("psrlw xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); psrlw_r128(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD1_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FD1_reg(mut r1: i32, mut r2: i32) -> () { instr_660FD1(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD1_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FD1_mem(mut addr: i32, mut r: i32) -> () { instr_660FD1(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD2(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FD2(mut source: reg64, mut r: i32) -> () { c_comment!(("psrld mm, mm/m64")); psrld_r64(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD2_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FD2(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FD2_reg(mut r1: i32, mut r2: i32) -> () { instr_0FD2(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD2_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FD2_mem(mut addr: i32, mut r: i32) -> () { instr_0FD2(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD2(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FD2(mut source: reg128, mut r: i32) -> () { c_comment!(("psrld xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); psrld_r128(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD2_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FD2_reg(mut r1: i32, mut r2: i32) -> () { instr_660FD2(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD2_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FD2_mem(mut addr: i32, mut r: i32) -> () { instr_660FD2(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD3(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FD3(mut source: reg64, mut r: i32) -> () { c_comment!(("psrlq mm, mm/m64")); psrlq_r64(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD3_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FD3(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FD3_reg(mut r1: i32, mut r2: i32) -> () { instr_0FD3(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD3_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FD3_mem(mut addr: i32, mut r: i32) -> () { instr_0FD3(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD3(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FD3(mut source: reg128, mut r: i32) -> () { c_comment!(("psrlq xmm, mm/m64")); psrlq_r128(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD3_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FD3_reg(mut r1: i32, mut r2: i32) -> () { instr_660FD3(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD3_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FD3_mem(mut addr: i32, mut r: i32) -> () { instr_660FD3(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD4(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FD4(mut source: reg64, mut r: i32) -> () { c_comment!(("paddq mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); destination.u64_0[0usize] = @@ -4120,15 +3966,13 @@ pub unsafe extern "C" fn instr_0FD4(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, destination); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD4_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FD4(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FD4_reg(mut r1: i32, mut r2: i32) -> () { instr_0FD4(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD4_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FD4_mem(mut addr: i32, mut r: i32) -> () { instr_0FD4(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD4(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FD4(mut source: reg128, mut r: i32) -> () { c_comment!(("paddq xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -4139,15 +3983,15 @@ pub unsafe extern "C" fn instr_660FD4(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, destination); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD4_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FD4_reg(mut r1: i32, mut r2: i32) -> () { instr_660FD4(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD4_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FD4_mem(mut addr: i32, mut r: i32) -> () { instr_660FD4(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD5(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FD5(mut source: reg64, mut r: i32) -> () { c_comment!(("pmullw mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = destination.u16_0[0usize] as i32 * source.u16_0[0usize] as i32 & 65535i32; @@ -4159,15 +4003,13 @@ pub unsafe extern "C" fn instr_0FD5(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD5_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FD5(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FD5_reg(mut r1: i32, mut r2: i32) -> () { instr_0FD5(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD5_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FD5_mem(mut addr: i32, mut r: i32) -> () { instr_0FD5(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD5(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FD5(mut source: reg128, mut r: i32) -> () { c_comment!(("pmullw xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -4184,24 +4026,24 @@ pub unsafe extern "C" fn instr_660FD5(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD5_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FD5_reg(mut r1: i32, mut r2: i32) -> () { instr_660FD5(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD5_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FD5_mem(mut addr: i32, mut r: i32) -> () { instr_660FD5(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FD6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD6_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FD6_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD6_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FD6_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movq xmm/m64, xmm")); movl_r128_m64(addr, r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD6_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FD6_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("movq xmm/m64, xmm")); let mut data: reg64 = read_xmm64s(r2); write_xmm128( @@ -4213,17 +4055,17 @@ pub unsafe extern "C" fn instr_660FD6_reg(mut r1: i32, mut r2: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_F20FD6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_F20FD6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_F20FD6_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F20FD6_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("movdq2q mm, xmm")); let mut source: reg128 = read_xmm128s(r1); write_mmx64(r2, source.u32_0[0usize] as i32, source.u32_0[1usize] as i32); } #[no_mangle] -pub unsafe extern "C" fn instr_F30FD6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_F30FD6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_F30FD6_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F30FD6_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("movq2dq xmm, mm")); let mut source: reg64 = read_mmx64s(r1); write_xmm128( @@ -4235,9 +4077,9 @@ pub unsafe extern "C" fn instr_F30FD6_reg(mut r1: i32, mut r2: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FD7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD7_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_0FD7_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("pmovmskb r, mm")); let mut x: reg64 = read_mmx64s(r1); let mut result: u32 = (x.u8_0[0usize] as i32 >> 7i32 << 0i32 @@ -4251,9 +4093,9 @@ pub unsafe extern "C" fn instr_0FD7_reg(mut r1: i32, mut r2: i32) -> () { write_reg32(r2, result as i32); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660FD7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD7_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FD7_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("pmovmskb reg, xmm")); let mut x: reg128 = read_xmm128s(r1); let mut result: i32 = x.u8_0[0usize] as i32 >> 7i32 << 0i32 @@ -4275,7 +4117,7 @@ pub unsafe extern "C" fn instr_660FD7_reg(mut r1: i32, mut r2: i32) -> () { write_reg32(r2, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD8(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FD8(mut source: reg64, mut r: i32) -> () { c_comment!(("psubusb mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -4291,15 +4133,13 @@ pub unsafe extern "C" fn instr_0FD8(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD8_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FD8(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FD8_reg(mut r1: i32, mut r2: i32) -> () { instr_0FD8(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD8_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FD8_mem(mut addr: i32, mut r: i32) -> () { instr_0FD8(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD8(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FD8(mut source: reg128, mut r: i32) -> () { c_comment!(("psubusb xmm, xmm/m128")); let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; @@ -4313,15 +4153,15 @@ pub unsafe extern "C" fn instr_660FD8(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD8_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FD8_reg(mut r1: i32, mut r2: i32) -> () { instr_660FD8(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD8_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FD8_mem(mut addr: i32, mut r: i32) -> () { instr_660FD8(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD9(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FD9(mut source: reg64, mut r: i32) -> () { c_comment!(("psubusw mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = @@ -4337,15 +4177,13 @@ pub unsafe extern "C" fn instr_0FD9(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD9_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FD9(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FD9_reg(mut r1: i32, mut r2: i32) -> () { instr_0FD9(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FD9_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FD9_mem(mut addr: i32, mut r: i32) -> () { instr_0FD9(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD9(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FD9(mut source: reg128, mut r: i32) -> () { c_comment!(("psubusw xmm, xmm/m128")); let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; @@ -4359,15 +4197,15 @@ pub unsafe extern "C" fn instr_660FD9(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD9_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FD9_reg(mut r1: i32, mut r2: i32) -> () { instr_660FD9(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FD9_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FD9_mem(mut addr: i32, mut r: i32) -> () { instr_660FD9(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FDA(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FDA(mut source: reg64, mut r: i32) -> () { c_comment!(("pminub mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; @@ -4385,15 +4223,13 @@ pub unsafe extern "C" fn instr_0FDA(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0FDA_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FDA(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FDA_reg(mut r1: i32, mut r2: i32) -> () { instr_0FDA(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FDA_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FDA_mem(mut addr: i32, mut r: i32) -> () { instr_0FDA(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FDA(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FDA(mut source: reg128, mut r: i32) -> () { c_comment!(("pminub xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -4412,15 +4248,15 @@ pub unsafe extern "C" fn instr_660FDA(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660FDA_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FDA_reg(mut r1: i32, mut r2: i32) -> () { instr_660FDA(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FDA_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FDA_mem(mut addr: i32, mut r: i32) -> () { instr_660FDA(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FDB(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FDB(mut source: reg64, mut r: i32) -> () { c_comment!(("pand mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -4430,29 +4266,27 @@ pub unsafe extern "C" fn instr_0FDB(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0FDB_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FDB(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FDB_reg(mut r1: i32, mut r2: i32) -> () { instr_0FDB(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FDB_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FDB_mem(mut addr: i32, mut r: i32) -> () { instr_0FDB(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FDB(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FDB(mut source: reg128, mut r: i32) -> () { c_comment!(("pand xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); pand_r128(source, r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FDB_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FDB_reg(mut r1: i32, mut r2: i32) -> () { instr_660FDB(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FDB_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FDB_mem(mut addr: i32, mut r: i32) -> () { instr_660FDB(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FDC(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FDC(mut source: reg64, mut r: i32) -> () { c_comment!(("paddusb mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -4468,15 +4302,13 @@ pub unsafe extern "C" fn instr_0FDC(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0FDC_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FDC(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FDC_reg(mut r1: i32, mut r2: i32) -> () { instr_0FDC(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FDC_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FDC_mem(mut addr: i32, mut r: i32) -> () { instr_0FDC(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FDC(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FDC(mut source: reg128, mut r: i32) -> () { c_comment!(("paddusb xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -4491,15 +4323,15 @@ pub unsafe extern "C" fn instr_660FDC(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660FDC_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FDC_reg(mut r1: i32, mut r2: i32) -> () { instr_660FDC(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FDC_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FDC_mem(mut addr: i32, mut r: i32) -> () { instr_660FDC(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FDD(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FDD(mut source: reg64, mut r: i32) -> () { c_comment!(("paddusw mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = @@ -4515,15 +4347,13 @@ pub unsafe extern "C" fn instr_0FDD(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe extern "C" fn instr_0FDD_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FDD(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FDD_reg(mut r1: i32, mut r2: i32) -> () { instr_0FDD(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FDD_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FDD_mem(mut addr: i32, mut r: i32) -> () { instr_0FDD(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FDD(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FDD(mut source: reg128, mut r: i32) -> () { c_comment!(("paddusw xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -4544,15 +4374,15 @@ pub unsafe extern "C" fn instr_660FDD(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_660FDD_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FDD_reg(mut r1: i32, mut r2: i32) -> () { instr_660FDD(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FDD_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FDD_mem(mut addr: i32, mut r: i32) -> () { instr_660FDD(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FDE(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FDE(mut source: reg64, mut r: i32) -> () { c_comment!(("pmaxub mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; @@ -4570,15 +4400,13 @@ pub unsafe extern "C" fn instr_0FDE(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0FDE_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FDE(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FDE_reg(mut r1: i32, mut r2: i32) -> () { instr_0FDE(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FDE_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FDE_mem(mut addr: i32, mut r: i32) -> () { instr_0FDE(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FDE(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FDE(mut source: reg128, mut r: i32) -> () { c_comment!(("pmaxub xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -4597,15 +4425,15 @@ pub unsafe extern "C" fn instr_660FDE(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660FDE_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FDE_reg(mut r1: i32, mut r2: i32) -> () { instr_660FDE(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FDE_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FDE_mem(mut addr: i32, mut r: i32) -> () { instr_660FDE(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FDF(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FDF(mut source: reg64, mut r: i32) -> () { c_comment!(("pandn mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -4615,29 +4443,27 @@ pub unsafe extern "C" fn instr_0FDF(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0FDF_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FDF(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FDF_reg(mut r1: i32, mut r2: i32) -> () { instr_0FDF(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FDF_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FDF_mem(mut addr: i32, mut r: i32) -> () { instr_0FDF(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FDF(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FDF(mut source: reg128, mut r: i32) -> () { c_comment!(("pandn xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); pandn_r128(source, r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FDF_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FDF_reg(mut r1: i32, mut r2: i32) -> () { instr_660FDF(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FDF_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FDF_mem(mut addr: i32, mut r: i32) -> () { instr_660FDF(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE0(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FE0(mut source: reg64, mut r: i32) -> () { c_comment!(("pavgb mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -4653,15 +4479,13 @@ pub unsafe extern "C" fn instr_0FE0(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE0_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FE0(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FE0_reg(mut r1: i32, mut r2: i32) -> () { instr_0FE0(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE0_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FE0_mem(mut addr: i32, mut r: i32) -> () { instr_0FE0(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE0(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FE0(mut source: reg128, mut r: i32) -> () { c_comment!(("pavgb xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -4676,69 +4500,65 @@ pub unsafe extern "C" fn instr_660FE0(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE0_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FE0_reg(mut r1: i32, mut r2: i32) -> () { instr_660FE0(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE0_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FE0_mem(mut addr: i32, mut r: i32) -> () { instr_660FE0(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE1(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FE1(mut source: reg64, mut r: i32) -> () { c_comment!(("psraw mm, mm/m64")); psraw_r64(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE1_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FE1(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FE1_reg(mut r1: i32, mut r2: i32) -> () { instr_0FE1(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE1_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FE1_mem(mut addr: i32, mut r: i32) -> () { instr_0FE1(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE1(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FE1(mut source: reg128, mut r: i32) -> () { c_comment!(("psraw xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); psraw_r128(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE1_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FE1_reg(mut r1: i32, mut r2: i32) -> () { instr_660FE1(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE1_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FE1_mem(mut addr: i32, mut r: i32) -> () { instr_660FE1(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE2(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FE2(mut source: reg64, mut r: i32) -> () { c_comment!(("psrad mm, mm/m64")); psrad_r64(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE2_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FE2(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FE2_reg(mut r1: i32, mut r2: i32) -> () { instr_0FE2(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE2_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FE2_mem(mut addr: i32, mut r: i32) -> () { instr_0FE2(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE2(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FE2(mut source: reg128, mut r: i32) -> () { c_comment!(("psrad xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); psrad_r128(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE2_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FE2_reg(mut r1: i32, mut r2: i32) -> () { instr_660FE2(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE2_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FE2_mem(mut addr: i32, mut r: i32) -> () { instr_660FE2(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE3(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FE3(mut source: reg64, mut r: i32) -> () { c_comment!(("pavgw mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); destination.u16_0[0usize] = @@ -4752,15 +4572,13 @@ pub unsafe extern "C" fn instr_0FE3(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, destination); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE3_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FE3(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FE3_reg(mut r1: i32, mut r2: i32) -> () { instr_0FE3(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE3_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FE3_mem(mut addr: i32, mut r: i32) -> () { instr_0FE3(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE3(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FE3(mut source: reg128, mut r: i32) -> () { c_comment!(("pavgw xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -4783,15 +4601,15 @@ pub unsafe extern "C" fn instr_660FE3(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, destination); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE3_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FE3_reg(mut r1: i32, mut r2: i32) -> () { instr_660FE3(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE3_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FE3_mem(mut addr: i32, mut r: i32) -> () { instr_660FE3(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE4(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FE4(mut source: reg64, mut r: i32) -> () { c_comment!(("pmulhuw mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); write_mmx64( @@ -4807,15 +4625,13 @@ pub unsafe extern "C" fn instr_0FE4(mut source: reg64, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE4_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FE4(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FE4_reg(mut r1: i32, mut r2: i32) -> () { instr_0FE4(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE4_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FE4_mem(mut addr: i32, mut r: i32) -> () { instr_0FE4(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE4(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FE4(mut source: reg128, mut r: i32) -> () { c_comment!(("pmulhuw xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -4840,15 +4656,15 @@ pub unsafe extern "C" fn instr_660FE4(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE4_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FE4_reg(mut r1: i32, mut r2: i32) -> () { instr_660FE4(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE4_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FE4_mem(mut addr: i32, mut r: i32) -> () { instr_660FE4(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE5(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FE5(mut source: reg64, mut r: i32) -> () { c_comment!(("pmulhw mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut word0: u32 = @@ -4864,15 +4680,13 @@ pub unsafe extern "C" fn instr_0FE5(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE5_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FE5(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FE5_reg(mut r1: i32, mut r2: i32) -> () { instr_0FE5(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE5_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FE5_mem(mut addr: i32, mut r: i32) -> () { instr_0FE5(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE5(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FE5(mut source: reg128, mut r: i32) -> () { c_comment!(("pmulhw xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -4895,45 +4709,45 @@ pub unsafe extern "C" fn instr_660FE5(mut source: reg128, mut r: i32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE5_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FE5_reg(mut r1: i32, mut r2: i32) -> () { instr_660FE5(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE5_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FE5_mem(mut addr: i32, mut r: i32) -> () { instr_660FE5(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FE6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE6_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FE6_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE6_mem(mut addr: i32, mut r: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_660FE6_mem(mut addr: i32, mut r: i32) -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE6_reg(mut r1: i32, mut r2: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_660FE6_reg(mut r1: i32, mut r2: i32) -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_F20FE6_mem(mut addr: i32, mut r: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_F20FE6_mem(mut addr: i32, mut r: i32) -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_F20FE6_reg(mut r1: i32, mut r2: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_F20FE6_reg(mut r1: i32, mut r2: i32) -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_F30FE6_mem(mut addr: i32, mut r: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_F30FE6_mem(mut addr: i32, mut r: i32) -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_F30FE6_reg(mut r1: i32, mut r2: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_F30FE6_reg(mut r1: i32, mut r2: i32) -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE7_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FE7_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movntq m64, mm")); mov_r_m64(addr, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE7_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FE7_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE7_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660FE7_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE7_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FE7_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movntdq m128, xmm")); mov_r_m128(addr, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE8(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FE8(mut source: reg64, mut r: i32) -> () { c_comment!(("psubsb mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -4949,15 +4763,13 @@ pub unsafe extern "C" fn instr_0FE8(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE8_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FE8(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FE8_reg(mut r1: i32, mut r2: i32) -> () { instr_0FE8(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE8_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FE8_mem(mut addr: i32, mut r: i32) -> () { instr_0FE8(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE8(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FE8(mut source: reg128, mut r: i32) -> () { c_comment!(("psubsb xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -4972,15 +4784,15 @@ pub unsafe extern "C" fn instr_660FE8(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE8_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FE8_reg(mut r1: i32, mut r2: i32) -> () { instr_660FE8(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE8_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FE8_mem(mut addr: i32, mut r: i32) -> () { instr_660FE8(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE9(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FE9(mut source: reg64, mut r: i32) -> () { c_comment!(("psubsw mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = @@ -5000,15 +4812,13 @@ pub unsafe extern "C" fn instr_0FE9(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE9_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FE9(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FE9_reg(mut r1: i32, mut r2: i32) -> () { instr_0FE9(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FE9_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FE9_mem(mut addr: i32, mut r: i32) -> () { instr_0FE9(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE9(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FE9(mut source: reg128, mut r: i32) -> () { c_comment!(("psubsw xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -5035,15 +4845,15 @@ pub unsafe extern "C" fn instr_660FE9(mut source: reg128, mut r: i32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE9_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FE9_reg(mut r1: i32, mut r2: i32) -> () { instr_660FE9(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FE9_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FE9_mem(mut addr: i32, mut r: i32) -> () { instr_660FE9(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FEA(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FEA(mut source: reg64, mut r: i32) -> () { c_comment!(("pminsw mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; @@ -5061,15 +4871,13 @@ pub unsafe extern "C" fn instr_0FEA(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0FEA_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FEA(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FEA_reg(mut r1: i32, mut r2: i32) -> () { instr_0FEA(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FEA_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FEA_mem(mut addr: i32, mut r: i32) -> () { instr_0FEA(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FEA(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FEA(mut source: reg128, mut r: i32) -> () { c_comment!(("pminsw xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -5088,15 +4896,15 @@ pub unsafe extern "C" fn instr_660FEA(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660FEA_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FEA_reg(mut r1: i32, mut r2: i32) -> () { instr_660FEA(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FEA_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FEA_mem(mut addr: i32, mut r: i32) -> () { instr_660FEA(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FEB(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FEB(mut source: reg64, mut r: i32) -> () { c_comment!(("por mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -5106,29 +4914,27 @@ pub unsafe extern "C" fn instr_0FEB(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0FEB_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FEB(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FEB_reg(mut r1: i32, mut r2: i32) -> () { instr_0FEB(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FEB_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FEB_mem(mut addr: i32, mut r: i32) -> () { instr_0FEB(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FEB(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FEB(mut source: reg128, mut r: i32) -> () { c_comment!(("por xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); por_r128(source, r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FEB_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FEB_reg(mut r1: i32, mut r2: i32) -> () { instr_660FEB(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FEB_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FEB_mem(mut addr: i32, mut r: i32) -> () { instr_660FEB(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FEC(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FEC(mut source: reg64, mut r: i32) -> () { c_comment!(("paddsb mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -5144,15 +4950,13 @@ pub unsafe extern "C" fn instr_0FEC(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0FEC_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FEC(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FEC_reg(mut r1: i32, mut r2: i32) -> () { instr_0FEC(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FEC_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FEC_mem(mut addr: i32, mut r: i32) -> () { instr_0FEC(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FEC(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FEC(mut source: reg128, mut r: i32) -> () { c_comment!(("paddsb xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -5167,15 +4971,15 @@ pub unsafe extern "C" fn instr_660FEC(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660FEC_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FEC_reg(mut r1: i32, mut r2: i32) -> () { instr_660FEC(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FEC_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FEC_mem(mut addr: i32, mut r: i32) -> () { instr_660FEC(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FED(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FED(mut source: reg64, mut r: i32) -> () { c_comment!(("paddsw mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = @@ -5195,15 +4999,13 @@ pub unsafe extern "C" fn instr_0FED(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe extern "C" fn instr_0FED_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FED(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FED_reg(mut r1: i32, mut r2: i32) -> () { instr_0FED(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FED_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FED_mem(mut addr: i32, mut r: i32) -> () { instr_0FED(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FED(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FED(mut source: reg128, mut r: i32) -> () { c_comment!(("paddsw xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -5230,15 +5032,15 @@ pub unsafe extern "C" fn instr_660FED(mut source: reg128, mut r: i32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe extern "C" fn instr_660FED_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FED_reg(mut r1: i32, mut r2: i32) -> () { instr_660FED(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FED_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FED_mem(mut addr: i32, mut r: i32) -> () { instr_660FED(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FEE(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FEE(mut source: reg64, mut r: i32) -> () { c_comment!(("pmaxsw mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; @@ -5256,15 +5058,13 @@ pub unsafe extern "C" fn instr_0FEE(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0FEE_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FEE(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FEE_reg(mut r1: i32, mut r2: i32) -> () { instr_0FEE(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FEE_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FEE_mem(mut addr: i32, mut r: i32) -> () { instr_0FEE(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FEE(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FEE(mut source: reg128, mut r: i32) -> () { c_comment!(("pmaxsw xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -5283,15 +5083,15 @@ pub unsafe extern "C" fn instr_660FEE(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660FEE_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FEE_reg(mut r1: i32, mut r2: i32) -> () { instr_660FEE(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FEE_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FEE_mem(mut addr: i32, mut r: i32) -> () { instr_660FEE(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FEF(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FEF(mut source: reg64, mut r: i32) -> () { c_comment!(("pxor mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -5301,112 +5101,104 @@ pub unsafe extern "C" fn instr_0FEF(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0FEF_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FEF(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FEF_reg(mut r1: i32, mut r2: i32) -> () { instr_0FEF(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FEF_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FEF_mem(mut addr: i32, mut r: i32) -> () { instr_0FEF(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FEF(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FEF(mut source: reg128, mut r: i32) -> () { c_comment!(("pxor xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); pxor_r128(source, r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FEF_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FEF_reg(mut r1: i32, mut r2: i32) -> () { instr_660FEF(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FEF_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FEF_mem(mut addr: i32, mut r: i32) -> () { instr_660FEF(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF0() -> () { unimplemented_sse(); } +pub unsafe fn instr_0FF0() -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF1(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FF1(mut source: reg64, mut r: i32) -> () { c_comment!(("psllw mm, mm/m64")); psllw_r64(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF1_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FF1(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FF1_reg(mut r1: i32, mut r2: i32) -> () { instr_0FF1(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF1_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FF1_mem(mut addr: i32, mut r: i32) -> () { instr_0FF1(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF1(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FF1(mut source: reg128, mut r: i32) -> () { c_comment!(("psllw xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); psllw_r128(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF1_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FF1_reg(mut r1: i32, mut r2: i32) -> () { instr_660FF1(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF1_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FF1_mem(mut addr: i32, mut r: i32) -> () { instr_660FF1(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF2(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FF2(mut source: reg64, mut r: i32) -> () { c_comment!(("pslld mm, mm/m64")); pslld_r64(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF2_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FF2(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FF2_reg(mut r1: i32, mut r2: i32) -> () { instr_0FF2(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF2_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FF2_mem(mut addr: i32, mut r: i32) -> () { instr_0FF2(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF2(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FF2(mut source: reg128, mut r: i32) -> () { c_comment!(("pslld xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); pslld_r128(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF2_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FF2_reg(mut r1: i32, mut r2: i32) -> () { instr_660FF2(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF2_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FF2_mem(mut addr: i32, mut r: i32) -> () { instr_660FF2(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF3(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FF3(mut source: reg64, mut r: i32) -> () { c_comment!(("psllq mm, mm/m64")); psllq_r64(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF3_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FF3(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FF3_reg(mut r1: i32, mut r2: i32) -> () { instr_0FF3(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF3_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FF3_mem(mut addr: i32, mut r: i32) -> () { instr_0FF3(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF3(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FF3(mut source: reg128, mut r: i32) -> () { c_comment!(("psllq xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); psllq_r128(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF3_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FF3_reg(mut r1: i32, mut r2: i32) -> () { instr_660FF3(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF3_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FF3_mem(mut addr: i32, mut r: i32) -> () { instr_660FF3(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF4(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FF4(mut source: reg64, mut r: i32) -> () { c_comment!(("pmuludq mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); destination.u64_0[0usize] = @@ -5414,15 +5206,13 @@ pub unsafe extern "C" fn instr_0FF4(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, destination); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF4_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FF4(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FF4_reg(mut r1: i32, mut r2: i32) -> () { instr_0FF4(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF4_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FF4_mem(mut addr: i32, mut r: i32) -> () { instr_0FF4(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF4(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FF4(mut source: reg128, mut r: i32) -> () { c_comment!(("pmuludq xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -5433,15 +5223,15 @@ pub unsafe extern "C" fn instr_660FF4(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, destination); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF4_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FF4_reg(mut r1: i32, mut r2: i32) -> () { instr_660FF4(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF4_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FF4_mem(mut addr: i32, mut r: i32) -> () { instr_660FF4(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF5(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FF5(mut source: reg64, mut r: i32) -> () { c_comment!(("pmaddwd mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut mul0: i32 = destination.i16_0[0usize] as i32 * source.i16_0[0usize] as i32; @@ -5453,15 +5243,13 @@ pub unsafe extern "C" fn instr_0FF5(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF5_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FF5(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FF5_reg(mut r1: i32, mut r2: i32) -> () { instr_0FF5(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF5_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FF5_mem(mut addr: i32, mut r: i32) -> () { instr_0FF5(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF5(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FF5(mut source: reg128, mut r: i32) -> () { c_comment!(("pmaddwd xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -5476,15 +5264,15 @@ pub unsafe extern "C" fn instr_660FF5(mut source: reg128, mut r: i32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF5_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FF5_reg(mut r1: i32, mut r2: i32) -> () { instr_660FF5(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF5_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FF5_mem(mut addr: i32, mut r: i32) -> () { instr_660FF5(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF6(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FF6(mut source: reg64, mut r: i32) -> () { c_comment!(("psadbw mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut sum: u32 = 0i32 as u32; @@ -5498,15 +5286,13 @@ pub unsafe extern "C" fn instr_0FF6(mut source: reg64, mut r: i32) -> () { write_mmx64(r, sum as i32, 0i32); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF6_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FF6(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FF6_reg(mut r1: i32, mut r2: i32) -> () { instr_0FF6(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF6_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FF6_mem(mut addr: i32, mut r: i32) -> () { instr_0FF6(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF6(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FF6(mut source: reg128, mut r: i32) -> () { c_comment!(("psadbw xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -5527,17 +5313,17 @@ pub unsafe extern "C" fn instr_660FF6(mut source: reg128, mut r: i32) -> () { write_xmm128(r, sum0 as i32, 0i32, sum1 as i32, 0i32); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF6_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FF6_reg(mut r1: i32, mut r2: i32) -> () { instr_660FF6(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF6_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FF6_mem(mut addr: i32, mut r: i32) -> () { instr_660FF6(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FF7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF7_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_0FF7_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("maskmovq mm, mm")); let mut source: reg64 = read_mmx64s(r2); let mut mask: reg64 = read_mmx64s(r1); @@ -5555,9 +5341,9 @@ pub unsafe extern "C" fn instr_0FF7_reg(mut r1: i32, mut r2: i32) -> () { } } #[no_mangle] -pub unsafe extern "C" fn instr_660FF7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660FF7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF7_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FF7_reg(mut r1: i32, mut r2: i32) -> () { c_comment!(("maskmovdqu xmm, xmm")); let mut source: reg128 = read_xmm128s(r2); let mut mask: reg128 = read_xmm128s(r1); @@ -5575,7 +5361,7 @@ pub unsafe extern "C" fn instr_660FF7_reg(mut r1: i32, mut r2: i32) -> () { } } #[no_mangle] -pub unsafe extern "C" fn instr_0FF8(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FF8(mut source: reg64, mut r: i32) -> () { c_comment!(("psubb mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -5590,15 +5376,13 @@ pub unsafe extern "C" fn instr_0FF8(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF8_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FF8(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FF8_reg(mut r1: i32, mut r2: i32) -> () { instr_0FF8(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF8_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FF8_mem(mut addr: i32, mut r: i32) -> () { instr_0FF8(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF8(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FF8(mut source: reg128, mut r: i32) -> () { c_comment!(("psubb xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -5614,15 +5398,15 @@ pub unsafe extern "C" fn instr_660FF8(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF8_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FF8_reg(mut r1: i32, mut r2: i32) -> () { instr_660FF8(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF8_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FF8_mem(mut addr: i32, mut r: i32) -> () { instr_660FF8(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF9(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FF9(mut source: reg64, mut r: i32) -> () { c_comment!(("psubw mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = @@ -5640,15 +5424,13 @@ pub unsafe extern "C" fn instr_0FF9(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF9_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FF9(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FF9_reg(mut r1: i32, mut r2: i32) -> () { instr_0FF9(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FF9_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FF9_mem(mut addr: i32, mut r: i32) -> () { instr_0FF9(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF9(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FF9(mut source: reg128, mut r: i32) -> () { c_comment!(("psubw xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -5665,15 +5447,15 @@ pub unsafe extern "C" fn instr_660FF9(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF9_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FF9_reg(mut r1: i32, mut r2: i32) -> () { instr_660FF9(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FF9_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FF9_mem(mut addr: i32, mut r: i32) -> () { instr_660FF9(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FFA(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FFA(mut source: reg64, mut r: i32) -> () { c_comment!(("psubd mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); write_mmx64( @@ -5683,15 +5465,13 @@ pub unsafe extern "C" fn instr_0FFA(mut source: reg64, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_0FFA_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FFA(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FFA_reg(mut r1: i32, mut r2: i32) -> () { instr_0FFA(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FFA_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FFA_mem(mut addr: i32, mut r: i32) -> () { instr_0FFA(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FFA(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FFA(mut source: reg128, mut r: i32) -> () { c_comment!(("psubd xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -5704,30 +5484,28 @@ pub unsafe extern "C" fn instr_660FFA(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn instr_660FFA_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FFA_reg(mut r1: i32, mut r2: i32) -> () { instr_660FFA(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FFA_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FFA_mem(mut addr: i32, mut r: i32) -> () { instr_660FFA(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FFB(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FFB(mut source: reg64, mut r: i32) -> () { c_comment!(("psubq mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); destination.u64_0[0usize] = destination.u64_0[0usize].wrapping_sub(source.u64_0[0usize]); write_mmx_reg64(r, destination); } #[no_mangle] -pub unsafe extern "C" fn instr_0FFB_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FFB(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FFB_reg(mut r1: i32, mut r2: i32) -> () { instr_0FFB(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FFB_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FFB_mem(mut addr: i32, mut r: i32) -> () { instr_0FFB(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FFB(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FFB(mut source: reg128, mut r: i32) -> () { c_comment!(("psubq xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -5736,15 +5514,15 @@ pub unsafe extern "C" fn instr_660FFB(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, destination); } #[no_mangle] -pub unsafe extern "C" fn instr_660FFB_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FFB_reg(mut r1: i32, mut r2: i32) -> () { instr_660FFB(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FFB_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FFB_mem(mut addr: i32, mut r: i32) -> () { instr_660FFB(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FFC(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FFC(mut source: reg64, mut r: i32) -> () { c_comment!(("paddb mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -5759,15 +5537,13 @@ pub unsafe extern "C" fn instr_0FFC(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0FFC_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FFC(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FFC_reg(mut r1: i32, mut r2: i32) -> () { instr_0FFC(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FFC_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FFC_mem(mut addr: i32, mut r: i32) -> () { instr_0FFC(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FFC(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FFC(mut source: reg128, mut r: i32) -> () { c_comment!(("paddb xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -5783,15 +5559,15 @@ pub unsafe extern "C" fn instr_660FFC(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660FFC_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FFC_reg(mut r1: i32, mut r2: i32) -> () { instr_660FFC(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FFC_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FFC_mem(mut addr: i32, mut r: i32) -> () { instr_660FFC(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FFD(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FFD(mut source: reg64, mut r: i32) -> () { c_comment!(("paddw mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = @@ -5805,15 +5581,13 @@ pub unsafe extern "C" fn instr_0FFD(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe extern "C" fn instr_0FFD_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FFD(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FFD_reg(mut r1: i32, mut r2: i32) -> () { instr_0FFD(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FFD_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FFD_mem(mut addr: i32, mut r: i32) -> () { instr_0FFD(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FFD(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FFD(mut source: reg128, mut r: i32) -> () { c_comment!(("paddw xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -5830,15 +5604,15 @@ pub unsafe extern "C" fn instr_660FFD(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660FFD_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FFD_reg(mut r1: i32, mut r2: i32) -> () { instr_660FFD(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FFD_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FFD_mem(mut addr: i32, mut r: i32) -> () { instr_660FFD(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FFE(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FFE(mut source: reg64, mut r: i32) -> () { c_comment!(("paddd mm, mm/m64")); let mut destination: reg64 = read_mmx64s(r); let mut low: i32 = destination.u32_0[0usize].wrapping_add(source.u32_0[0usize]) as i32; @@ -5846,15 +5620,13 @@ pub unsafe extern "C" fn instr_0FFE(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe extern "C" fn instr_0FFE_reg(mut r1: i32, mut r2: i32) -> () { - instr_0FFE(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0FFE_reg(mut r1: i32, mut r2: i32) -> () { instr_0FFE(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0FFE_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FFE_mem(mut addr: i32, mut r: i32) -> () { instr_0FFE(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660FFE(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FFE(mut source: reg128, mut r: i32) -> () { c_comment!(("paddd xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -5865,15 +5637,15 @@ pub unsafe extern "C" fn instr_660FFE(mut source: reg128, mut r: i32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe extern "C" fn instr_660FFE_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FFE_reg(mut r1: i32, mut r2: i32) -> () { instr_660FFE(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660FFE_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FFE_mem(mut addr: i32, mut r: i32) -> () { instr_660FFE(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FFF() -> () { +pub unsafe fn instr_0FFF() -> () { c_comment!(("Windows 98")); dbg_log_c!("#ud: 0F FF"); trigger_ud(); @@ -5881,25 +5653,25 @@ pub unsafe extern "C" fn instr_0FFF() -> () { #[no_mangle] pub static mut CPU_LOG_VERBOSE: bool = unsafe { 0 != 0i32 }; #[no_mangle] -pub unsafe extern "C" fn instr_F30F16() -> () { unimplemented_sse(); } +pub unsafe fn instr_F30F16() -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F19_reg(mut r1: i32, mut r2: i32) -> () {} +pub unsafe fn instr_0F19_reg(mut r1: i32, mut r2: i32) -> () {} #[no_mangle] -pub unsafe extern "C" fn instr_0F19_mem(mut addr: i32, mut r: i32) -> () {} +pub unsafe fn instr_0F19_mem(mut addr: i32, mut r: i32) -> () {} #[no_mangle] -pub unsafe extern "C" fn instr_0F1C_reg(mut r1: i32, mut r2: i32) -> () {} +pub unsafe fn instr_0F1C_reg(mut r1: i32, mut r2: i32) -> () {} #[no_mangle] -pub unsafe extern "C" fn instr_0F1C_mem(mut addr: i32, mut r: i32) -> () {} +pub unsafe fn instr_0F1C_mem(mut addr: i32, mut r: i32) -> () {} #[no_mangle] -pub unsafe extern "C" fn instr_0F1D_reg(mut r1: i32, mut r2: i32) -> () {} +pub unsafe fn instr_0F1D_reg(mut r1: i32, mut r2: i32) -> () {} #[no_mangle] -pub unsafe extern "C" fn instr_0F1D_mem(mut addr: i32, mut r: i32) -> () {} +pub unsafe fn instr_0F1D_mem(mut addr: i32, mut r: i32) -> () {} #[no_mangle] -pub unsafe extern "C" fn instr_0F1E_reg(mut r1: i32, mut r2: i32) -> () {} +pub unsafe fn instr_0F1E_reg(mut r1: i32, mut r2: i32) -> () {} #[no_mangle] -pub unsafe extern "C" fn instr_0F1E_mem(mut addr: i32, mut r: i32) -> () {} +pub unsafe fn instr_0F1E_mem(mut addr: i32, mut r: i32) -> () {} #[no_mangle] -pub unsafe extern "C" fn instr_0F2A(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F2A(mut source: reg64, mut r: i32) -> () { c_comment!(("cvtpi2ps xmm, mm/m64")); c_comment!((("XXX: The non-memory variant causes a transition from x87 FPU to MMX technology operation"))); c_comment!(("Note: Casts here can fail")); @@ -5909,15 +5681,13 @@ pub unsafe extern "C" fn instr_0F2A(mut source: reg64, mut r: i32) -> () { write_xmm64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0F2A_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F2A(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0F2A_reg(mut r1: i32, mut r2: i32) -> () { instr_0F2A(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F2A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F2A_mem(mut addr: i32, mut r: i32) -> () { instr_0F2A(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F2A(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_660F2A(mut source: reg64, mut r: i32) -> () { c_comment!(("cvtpi2pd xmm, xmm/m64")); c_comment!((("XXX: The non-memory variant causes a transition from x87 FPU to MMX technology operation"))); c_comment!(("These casts can\'t fail")); @@ -5927,15 +5697,15 @@ pub unsafe extern "C" fn instr_660F2A(mut source: reg64, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660F2A_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F2A_reg(mut r1: i32, mut r2: i32) -> () { instr_660F2A(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F2A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F2A_mem(mut addr: i32, mut r: i32) -> () { instr_660F2A(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F2A(mut source: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F2A(mut source: i32, mut r: i32) -> () { c_comment!(("cvtsi2sd xmm, r32/m32")); c_comment!(("This cast can\'t fail")); let mut result: reg64 = reg64 { @@ -5944,73 +5714,67 @@ pub unsafe extern "C" fn instr_F20F2A(mut source: i32, mut r: i32) -> () { write_xmm64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F2A_reg(mut r1: i32, mut r2: i32) -> () { - instr_F20F2A(read_reg32(r1), r2); -} +pub unsafe fn instr_F20F2A_reg(mut r1: i32, mut r2: i32) -> () { instr_F20F2A(read_reg32(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F2A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F2A_mem(mut addr: i32, mut r: i32) -> () { instr_F20F2A(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F2A(mut source: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F2A(mut source: i32, mut r: i32) -> () { c_comment!(("cvtsi2ss xmm, r/m32")); c_comment!(("Note: This cast can fail")); let mut result: f32 = source as f32; write_xmm_f32(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F2A_reg(mut r1: i32, mut r2: i32) -> () { - instr_F30F2A(read_reg32(r1), r2); -} +pub unsafe fn instr_F30F2A_reg(mut r1: i32, mut r2: i32) -> () { instr_F30F2A(read_reg32(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F2A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F2A_mem(mut addr: i32, mut r: i32) -> () { instr_F30F2A(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F2D(mut source: reg64, mut r: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_0F2D(mut source: reg64, mut r: i32) -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F2D_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F2D(read_mmx64s(r1), r2); -} +pub unsafe fn instr_0F2D_reg(mut r1: i32, mut r2: i32) -> () { instr_0F2D(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F2D_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F2D_mem(mut addr: i32, mut r: i32) -> () { instr_0F2D(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F2D(mut source: reg128, mut r: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_660F2D(mut source: reg128, mut r: i32) -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_660F2D_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F2D_reg(mut r1: i32, mut r2: i32) -> () { instr_660F2D(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F2D_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F2D_mem(mut addr: i32, mut r: i32) -> () { instr_660F2D(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F2D(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_F20F2D(mut source: reg64, mut r: i32) -> () { c_comment!(("cvtsd2si r32, xmm/m64")); write_reg32(r, sse_convert_f64_to_i32(source.f64_0[0usize])); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F2D_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F20F2D_reg(mut r1: i32, mut r2: i32) -> () { instr_F20F2D(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F2D_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F2D_mem(mut addr: i32, mut r: i32) -> () { instr_F20F2D(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F2D(mut source: f32, mut r: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_F30F2D(mut source: f32, mut r: i32) -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F2D_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F30F2D_reg(mut r1: i32, mut r2: i32) -> () { instr_F30F2D(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F2D_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F2D_mem(mut addr: i32, mut r: i32) -> () { instr_F30F2D(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F51(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F51(mut source: reg128, mut r: i32) -> () { c_comment!(("sqrtps xmm, xmm/mem128")); let mut result: reg128 = reg128 { f32_0: [ @@ -6023,15 +5787,13 @@ pub unsafe extern "C" fn instr_0F51(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0F51_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F51(read_xmm128s(r1), r2); -} +pub unsafe fn instr_0F51_reg(mut r1: i32, mut r2: i32) -> () { instr_0F51(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F51_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F51_mem(mut addr: i32, mut r: i32) -> () { instr_0F51(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F51(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F51(mut source: reg128, mut r: i32) -> () { c_comment!(("sqrtpd xmm, xmm/mem128")); let mut result: reg128 = reg128 { f64_0: [source.f64_0[0usize].sqrt(), source.f64_0[1usize].sqrt()], @@ -6039,15 +5801,15 @@ pub unsafe extern "C" fn instr_660F51(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660F51_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F51_reg(mut r1: i32, mut r2: i32) -> () { instr_660F51(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F51_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F51_mem(mut addr: i32, mut r: i32) -> () { instr_660F51(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F51(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_F20F51(mut source: reg64, mut r: i32) -> () { c_comment!(("sqrtsd xmm, xmm/mem64")); let mut result: reg64 = reg64 { f64_0: [source.f64_0[0usize].sqrt()], @@ -6055,30 +5817,30 @@ pub unsafe extern "C" fn instr_F20F51(mut source: reg64, mut r: i32) -> () { write_xmm64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F51_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F20F51_reg(mut r1: i32, mut r2: i32) -> () { instr_F20F51(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F51_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F51_mem(mut addr: i32, mut r: i32) -> () { instr_F20F51(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F51(mut source: f32, mut r: i32) -> () { +pub unsafe fn instr_F30F51(mut source: f32, mut r: i32) -> () { c_comment!(("sqrtss xmm, xmm/mem32")); write_xmm_f32(r, source.sqrt()); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F51_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F30F51_reg(mut r1: i32, mut r2: i32) -> () { instr_F30F51(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F51_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F51_mem(mut addr: i32, mut r: i32) -> () { instr_F30F51(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F52() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F52() -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F53(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F53(mut source: reg128, mut r: i32) -> () { c_comment!(("rcpps xmm, xmm/m128")); let mut result: reg128 = reg128 { f32_0: [ @@ -6091,28 +5853,26 @@ pub unsafe extern "C" fn instr_0F53(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0F53_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F53(read_xmm128s(r1), r2); -} +pub unsafe fn instr_0F53_reg(mut r1: i32, mut r2: i32) -> () { instr_0F53(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F53_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F53_mem(mut addr: i32, mut r: i32) -> () { instr_0F53(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F53(mut source: f32, mut r: i32) -> () { +pub unsafe fn instr_F30F53(mut source: f32, mut r: i32) -> () { c_comment!(("rcpss xmm, xmm/m32")); write_xmm_f32(r, 1i32 as f32 / source); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F53_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F30F53_reg(mut r1: i32, mut r2: i32) -> () { instr_F30F53(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F53_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F53_mem(mut addr: i32, mut r: i32) -> () { instr_F30F53(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F58(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F58(mut source: reg128, mut r: i32) -> () { c_comment!(("addps xmm, xmm/mem128")); let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6126,15 +5886,13 @@ pub unsafe extern "C" fn instr_0F58(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0F58_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F58(read_xmm128s(r1), r2); -} +pub unsafe fn instr_0F58_reg(mut r1: i32, mut r2: i32) -> () { instr_0F58(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F58_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F58_mem(mut addr: i32, mut r: i32) -> () { instr_0F58(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F58(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F58(mut source: reg128, mut r: i32) -> () { c_comment!(("addpd xmm, xmm/mem128")); let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6146,15 +5904,15 @@ pub unsafe extern "C" fn instr_660F58(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660F58_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F58_reg(mut r1: i32, mut r2: i32) -> () { instr_660F58(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F58_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F58_mem(mut addr: i32, mut r: i32) -> () { instr_660F58(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F58(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_F20F58(mut source: reg64, mut r: i32) -> () { c_comment!(("addsd xmm, xmm/mem64")); let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { @@ -6163,30 +5921,30 @@ pub unsafe extern "C" fn instr_F20F58(mut source: reg64, mut r: i32) -> () { write_xmm64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F58_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F20F58_reg(mut r1: i32, mut r2: i32) -> () { instr_F20F58(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F58_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F58_mem(mut addr: i32, mut r: i32) -> () { instr_F20F58(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F58(mut source: f32, mut r: i32) -> () { +pub unsafe fn instr_F30F58(mut source: f32, mut r: i32) -> () { c_comment!(("addss xmm, xmm/mem32")); let mut destination: f32 = read_xmm_f32(r); let mut result: f32 = source + destination; write_xmm_f32(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F58_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F30F58_reg(mut r1: i32, mut r2: i32) -> () { instr_F30F58(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F58_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F58_mem(mut addr: i32, mut r: i32) -> () { instr_F30F58(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F59(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F59(mut source: reg128, mut r: i32) -> () { c_comment!(("mulps xmm, xmm/mem128")); let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6200,15 +5958,13 @@ pub unsafe extern "C" fn instr_0F59(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0F59_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F59(read_xmm128s(r1), r2); -} +pub unsafe fn instr_0F59_reg(mut r1: i32, mut r2: i32) -> () { instr_0F59(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F59_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F59_mem(mut addr: i32, mut r: i32) -> () { instr_0F59(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F59(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F59(mut source: reg128, mut r: i32) -> () { c_comment!(("mulpd xmm, xmm/mem128")); let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6220,15 +5976,15 @@ pub unsafe extern "C" fn instr_660F59(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660F59_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F59_reg(mut r1: i32, mut r2: i32) -> () { instr_660F59(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F59_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F59_mem(mut addr: i32, mut r: i32) -> () { instr_660F59(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F59(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_F20F59(mut source: reg64, mut r: i32) -> () { c_comment!(("mulsd xmm, xmm/mem64")); let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { @@ -6237,34 +5993,34 @@ pub unsafe extern "C" fn instr_F20F59(mut source: reg64, mut r: i32) -> () { write_xmm64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F59_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F20F59_reg(mut r1: i32, mut r2: i32) -> () { instr_F20F59(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F59_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F59_mem(mut addr: i32, mut r: i32) -> () { instr_F20F59(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F59(mut source: f32, mut r: i32) -> () { +pub unsafe fn instr_F30F59(mut source: f32, mut r: i32) -> () { c_comment!(("mulss xmm, xmm/mem32")); let mut destination: f32 = read_xmm_f32(r); let mut result: f32 = source * destination; write_xmm_f32(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F59_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F30F59_reg(mut r1: i32, mut r2: i32) -> () { instr_F30F59(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F59_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F59_mem(mut addr: i32, mut r: i32) -> () { instr_F30F59(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F5A() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F5A() -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F5B() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F5B() -> () { unimplemented_sse(); } #[no_mangle] -pub unsafe extern "C" fn instr_0F5C(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F5C(mut source: reg128, mut r: i32) -> () { c_comment!(("subps xmm, xmm/mem128")); let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6278,15 +6034,13 @@ pub unsafe extern "C" fn instr_0F5C(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0F5C_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F5C(read_xmm128s(r1), r2); -} +pub unsafe fn instr_0F5C_reg(mut r1: i32, mut r2: i32) -> () { instr_0F5C(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F5C_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F5C_mem(mut addr: i32, mut r: i32) -> () { instr_0F5C(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F5C(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F5C(mut source: reg128, mut r: i32) -> () { c_comment!(("subpd xmm, xmm/mem128")); let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6298,15 +6052,15 @@ pub unsafe extern "C" fn instr_660F5C(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660F5C_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F5C_reg(mut r1: i32, mut r2: i32) -> () { instr_660F5C(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F5C_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F5C_mem(mut addr: i32, mut r: i32) -> () { instr_660F5C(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F5C(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_F20F5C(mut source: reg64, mut r: i32) -> () { c_comment!(("subsd xmm, xmm/mem64")); let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { @@ -6315,30 +6069,30 @@ pub unsafe extern "C" fn instr_F20F5C(mut source: reg64, mut r: i32) -> () { write_xmm64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F5C_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F20F5C_reg(mut r1: i32, mut r2: i32) -> () { instr_F20F5C(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F5C_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F5C_mem(mut addr: i32, mut r: i32) -> () { instr_F20F5C(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F5C(mut source: f32, mut r: i32) -> () { +pub unsafe fn instr_F30F5C(mut source: f32, mut r: i32) -> () { c_comment!(("subss xmm, xmm/mem32")); let mut destination: f32 = read_xmm_f32(r); let mut result: f32 = destination - source; write_xmm_f32(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F5C_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F30F5C_reg(mut r1: i32, mut r2: i32) -> () { instr_F30F5C(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F5C_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F5C_mem(mut addr: i32, mut r: i32) -> () { instr_F30F5C(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F5D(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F5D(mut source: reg128, mut r: i32) -> () { c_comment!(("minps xmm, xmm/mem128")); let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6364,15 +6118,13 @@ pub unsafe extern "C" fn instr_0F5D(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0F5D_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F5D(read_xmm128s(r1), r2); -} +pub unsafe fn instr_0F5D_reg(mut r1: i32, mut r2: i32) -> () { instr_0F5D(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F5D_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F5D_mem(mut addr: i32, mut r: i32) -> () { instr_0F5D(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F5D(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F5D(mut source: reg128, mut r: i32) -> () { c_comment!(("minpd xmm, xmm/mem128")); let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6384,15 +6136,15 @@ pub unsafe extern "C" fn instr_660F5D(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660F5D_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F5D_reg(mut r1: i32, mut r2: i32) -> () { instr_660F5D(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F5D_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F5D_mem(mut addr: i32, mut r: i32) -> () { instr_660F5D(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F5D(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_F20F5D(mut source: reg64, mut r: i32) -> () { c_comment!(("minsd xmm, xmm/mem64")); let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { @@ -6401,30 +6153,30 @@ pub unsafe extern "C" fn instr_F20F5D(mut source: reg64, mut r: i32) -> () { write_xmm64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F5D_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F20F5D_reg(mut r1: i32, mut r2: i32) -> () { instr_F20F5D(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F5D_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F5D_mem(mut addr: i32, mut r: i32) -> () { instr_F20F5D(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F5D(mut source: f32, mut r: i32) -> () { +pub unsafe fn instr_F30F5D(mut source: f32, mut r: i32) -> () { c_comment!(("minss xmm, xmm/mem32")); let mut destination: f32 = read_xmm_f32(r); let mut result: f32 = sse_min(destination as f64, source as f64) as f32; write_xmm_f32(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F5D_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F30F5D_reg(mut r1: i32, mut r2: i32) -> () { instr_F30F5D(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F5D_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F5D_mem(mut addr: i32, mut r: i32) -> () { instr_F30F5D(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F5E(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F5E(mut source: reg128, mut r: i32) -> () { c_comment!(("divps xmm, xmm/mem128")); let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6438,15 +6190,13 @@ pub unsafe extern "C" fn instr_0F5E(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0F5E_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F5E(read_xmm128s(r1), r2); -} +pub unsafe fn instr_0F5E_reg(mut r1: i32, mut r2: i32) -> () { instr_0F5E(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F5E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F5E_mem(mut addr: i32, mut r: i32) -> () { instr_0F5E(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F5E(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F5E(mut source: reg128, mut r: i32) -> () { c_comment!(("divpd xmm, xmm/mem128")); let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6458,15 +6208,15 @@ pub unsafe extern "C" fn instr_660F5E(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660F5E_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F5E_reg(mut r1: i32, mut r2: i32) -> () { instr_660F5E(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F5E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F5E_mem(mut addr: i32, mut r: i32) -> () { instr_660F5E(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F5E(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_F20F5E(mut source: reg64, mut r: i32) -> () { c_comment!(("divsd xmm, xmm/mem64")); let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { @@ -6475,30 +6225,30 @@ pub unsafe extern "C" fn instr_F20F5E(mut source: reg64, mut r: i32) -> () { write_xmm64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F5E_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F20F5E_reg(mut r1: i32, mut r2: i32) -> () { instr_F20F5E(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F5E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F5E_mem(mut addr: i32, mut r: i32) -> () { instr_F20F5E(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F5E(mut source: f32, mut r: i32) -> () { +pub unsafe fn instr_F30F5E(mut source: f32, mut r: i32) -> () { c_comment!(("divss xmm, xmm/mem32")); let mut destination: f32 = read_xmm_f32(r); let mut result: f32 = destination / source; write_xmm_f32(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F5E_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F30F5E_reg(mut r1: i32, mut r2: i32) -> () { instr_F30F5E(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F5E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F5E_mem(mut addr: i32, mut r: i32) -> () { instr_F30F5E(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0F5F(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F5F(mut source: reg128, mut r: i32) -> () { c_comment!(("maxps xmm, xmm/mem128")); let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6524,15 +6274,13 @@ pub unsafe extern "C" fn instr_0F5F(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0F5F_reg(mut r1: i32, mut r2: i32) -> () { - instr_0F5F(read_xmm128s(r1), r2); -} +pub unsafe fn instr_0F5F_reg(mut r1: i32, mut r2: i32) -> () { instr_0F5F(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_0F5F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F5F_mem(mut addr: i32, mut r: i32) -> () { instr_0F5F(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_660F5F(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F5F(mut source: reg128, mut r: i32) -> () { c_comment!(("maxpd xmm, xmm/mem128")); let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6544,15 +6292,15 @@ pub unsafe extern "C" fn instr_660F5F(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660F5F_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F5F_reg(mut r1: i32, mut r2: i32) -> () { instr_660F5F(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_660F5F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F5F_mem(mut addr: i32, mut r: i32) -> () { instr_660F5F(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F5F(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_F20F5F(mut source: reg64, mut r: i32) -> () { c_comment!(("maxsd xmm, xmm/mem64")); let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { @@ -6561,30 +6309,30 @@ pub unsafe extern "C" fn instr_F20F5F(mut source: reg64, mut r: i32) -> () { write_xmm64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F5F_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F20F5F_reg(mut r1: i32, mut r2: i32) -> () { instr_F20F5F(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_F20F5F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F5F_mem(mut addr: i32, mut r: i32) -> () { instr_F20F5F(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F5F(mut source: f32, mut r: i32) -> () { +pub unsafe fn instr_F30F5F(mut source: f32, mut r: i32) -> () { c_comment!(("maxss xmm, xmm/mem32")); let mut destination: f32 = read_xmm_f32(r); let mut result: f32 = sse_max(destination as f64, source as f64) as f32; write_xmm_f32(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F5F_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F30F5F_reg(mut r1: i32, mut r2: i32) -> () { instr_F30F5F(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe extern "C" fn instr_F30F5F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F5F_mem(mut addr: i32, mut r: i32) -> () { instr_F30F5F(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe extern "C" fn instr_0FC2(mut source: reg128, mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0FC2(mut source: reg128, mut r: i32, mut imm8: i32) -> () { c_comment!(("cmpps xmm, xmm/m128")); let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6638,15 +6386,15 @@ pub unsafe extern "C" fn instr_0FC2(mut source: reg128, mut r: i32, mut imm8: i3 write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_0FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { +pub unsafe fn instr_0FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { instr_0FC2(read_xmm128s(r1), r2, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_0FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr_0FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { instr_0FC2(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_660FC2(mut source: reg128, mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660FC2(mut source: reg128, mut r: i32, mut imm8: i32) -> () { c_comment!(("cmppd xmm, xmm/m128")); let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6668,15 +6416,15 @@ pub unsafe extern "C" fn instr_660FC2(mut source: reg128, mut r: i32, mut imm8: write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_660FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { +pub unsafe fn instr_660FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { instr_660FC2(read_xmm128s(r1), r2, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_660FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr_660FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { instr_660FC2(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_F20FC2(mut source: reg64, mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_F20FC2(mut source: reg64, mut r: i32, mut imm8: i32) -> () { c_comment!(("cmpsd xmm, xmm/m64")); let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { @@ -6692,15 +6440,15 @@ pub unsafe extern "C" fn instr_F20FC2(mut source: reg64, mut r: i32, mut imm8: i write_xmm64(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_F20FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { +pub unsafe fn instr_F20FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { instr_F20FC2(read_xmm64s(r1), r2, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_F20FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr_F20FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { instr_F20FC2(return_on_pagefault!(safe_read64s(addr)), r, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_F30FC2(mut source: f32, mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_F30FC2(mut source: f32, mut r: i32, mut imm8: i32) -> () { c_comment!(("cmpss xmm, xmm/m32")); let mut destination: f32 = read_xmm_f32(r); let mut result: i32 = if 0 != sse_comparison(imm8, destination as f64, source as f64) as i32 { @@ -6712,10 +6460,10 @@ pub unsafe extern "C" fn instr_F30FC2(mut source: f32, mut r: i32, mut imm8: i32 write_xmm32(r, result); } #[no_mangle] -pub unsafe extern "C" fn instr_F30FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { +pub unsafe fn instr_F30FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { instr_F30FC2(read_xmm_f32(r1), r2, imm); } #[no_mangle] -pub unsafe extern "C" fn instr_F30FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr_F30FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { instr_F30FC2(return_on_pagefault!(fpu_load_m32(addr)) as f32, r, imm); } diff --git a/src/rust/cpu2/memory.rs b/src/rust/cpu2/memory.rs index 1b1600f8..8432de41 100644 --- a/src/rust/cpu2/memory.rs +++ b/src/rust/cpu2/memory.rs @@ -34,12 +34,12 @@ use cpu2::cpu::*; use cpu2::global_pointers::*; #[no_mangle] -pub unsafe extern "C" fn in_mapped_range(mut addr: u32) -> bool { +pub unsafe fn in_mapped_range(mut addr: u32) -> bool { return addr >= 655360i32 as u32 && addr < 786432i32 as u32 || addr >= *memory_size; } #[no_mangle] -pub unsafe extern "C" fn read8(mut addr: u32) -> i32 { +pub unsafe fn read8(mut addr: u32) -> i32 { if 0 != USE_A20 as i32 && 0 != *a20_enabled as i32 { addr &= A20_MASK as u32 } @@ -53,7 +53,7 @@ pub unsafe extern "C" fn read8(mut addr: u32) -> i32 { #[no_mangle] pub static mut USE_A20: bool = unsafe { 0 != 0i32 }; #[no_mangle] -pub unsafe extern "C" fn read16(mut addr: u32) -> i32 { +pub unsafe fn read16(mut addr: u32) -> i32 { if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK as u32 } @@ -65,7 +65,7 @@ pub unsafe extern "C" fn read16(mut addr: u32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn read_aligned16(mut addr: u32) -> i32 { +pub unsafe fn read_aligned16(mut addr: u32) -> i32 { dbg_assert!(addr < 2147483648u32); if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK16 as u32 @@ -78,7 +78,7 @@ pub unsafe extern "C" fn read_aligned16(mut addr: u32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn read32s(mut addr: u32) -> i32 { +pub unsafe fn read32s(mut addr: u32) -> i32 { if 0 != USE_A20 as i32 && 0 != *a20_enabled as i32 { addr &= A20_MASK as u32 } @@ -90,7 +90,7 @@ pub unsafe extern "C" fn read32s(mut addr: u32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn read64s(mut addr: u32) -> i64 { +pub unsafe fn read64s(mut addr: u32) -> i64 { if 0 != USE_A20 as i32 && 0 != *a20_enabled as i32 { addr &= A20_MASK as u32 } @@ -103,7 +103,7 @@ pub unsafe extern "C" fn read64s(mut addr: u32) -> i64 { }; } #[no_mangle] -pub unsafe extern "C" fn read_aligned32(mut addr: u32) -> i32 { +pub unsafe fn read_aligned32(mut addr: u32) -> i32 { dbg_assert!(addr < 1073741824i32 as u32); if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK32 as u32 @@ -116,7 +116,7 @@ pub unsafe extern "C" fn read_aligned32(mut addr: u32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn read128(mut addr: u32) -> reg128 { +pub unsafe fn read128(mut addr: u32) -> reg128 { if 0 != USE_A20 as i32 && 0 != *a20_enabled as i32 { addr &= A20_MASK as u32 } @@ -136,7 +136,7 @@ pub unsafe extern "C" fn read128(mut addr: u32) -> reg128 { return value; } #[no_mangle] -pub unsafe extern "C" fn write8(mut addr: u32, mut value: i32) -> () { +pub unsafe fn write8(mut addr: u32, mut value: i32) -> () { if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK as u32 } @@ -149,7 +149,7 @@ pub unsafe extern "C" fn write8(mut addr: u32, mut value: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn write16(mut addr: u32, mut value: i32) -> () { +pub unsafe fn write16(mut addr: u32, mut value: i32) -> () { if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK as u32 } @@ -162,7 +162,7 @@ pub unsafe extern "C" fn write16(mut addr: u32, mut value: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn write_aligned16(mut addr: u32, mut value: u32) -> () { +pub unsafe fn write_aligned16(mut addr: u32, mut value: u32) -> () { dbg_assert!(addr < 2147483648u32); if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK16 as u32 @@ -177,7 +177,7 @@ pub unsafe extern "C" fn write_aligned16(mut addr: u32, mut value: u32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn write32(mut addr: u32, mut value: i32) -> () { +pub unsafe fn write32(mut addr: u32, mut value: i32) -> () { if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK as u32 } @@ -190,7 +190,7 @@ pub unsafe extern "C" fn write32(mut addr: u32, mut value: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn write_aligned32(mut addr: u32, mut value: i32) -> () { +pub unsafe fn write_aligned32(mut addr: u32, mut value: i32) -> () { dbg_assert!(addr < 1073741824i32 as u32); if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK32 as u32 @@ -205,7 +205,7 @@ pub unsafe extern "C" fn write_aligned32(mut addr: u32, mut value: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn write64(mut addr: u32, mut value: i64) -> () { +pub unsafe fn write64(mut addr: u32, mut value: i64) -> () { if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK as u32 } @@ -222,7 +222,7 @@ pub unsafe extern "C" fn write64(mut addr: u32, mut value: i64) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn write128(mut addr: u32, mut value: reg128) -> () { +pub unsafe fn write128(mut addr: u32, mut value: reg128) -> () { if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK as u32 } diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index a92f2d52..0cbe07c5 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -12,7 +12,7 @@ use cpu2::fpu::{fpu_load_m80, fpu_load_status_word, fpu_set_status_word, fpu_sto use cpu2::global_pointers::*; #[no_mangle] -pub unsafe extern "C" fn getcf() -> bool { +pub unsafe fn getcf() -> bool { if 0 != *flags_changed & 1i32 { return 0 != (*last_op1 ^ (*last_op1 ^ *last_op2) & (*last_op2 ^ *last_add_result)) @@ -24,7 +24,7 @@ pub unsafe extern "C" fn getcf() -> bool { }; } #[no_mangle] -pub unsafe extern "C" fn getpf() -> bool { +pub unsafe fn getpf() -> bool { if 0 != *flags_changed & FLAG_PARITY { c_comment!(("inverted lookup table")); return 0 @@ -35,7 +35,7 @@ pub unsafe extern "C" fn getpf() -> bool { }; } #[no_mangle] -pub unsafe extern "C" fn getaf() -> bool { +pub unsafe fn getaf() -> bool { if 0 != *flags_changed & FLAG_ADJUST { return 0 != (*last_op1 ^ *last_op2 ^ *last_add_result) & FLAG_ADJUST; } @@ -44,7 +44,7 @@ pub unsafe extern "C" fn getaf() -> bool { }; } #[no_mangle] -pub unsafe extern "C" fn getzf() -> bool { +pub unsafe fn getzf() -> bool { if 0 != *flags_changed & FLAG_ZERO { return 0 != (!*last_result & *last_result - 1i32) >> *last_op_size & 1i32; } @@ -53,7 +53,7 @@ pub unsafe extern "C" fn getzf() -> bool { }; } #[no_mangle] -pub unsafe extern "C" fn getsf() -> bool { +pub unsafe fn getsf() -> bool { if 0 != *flags_changed & FLAG_SIGN { return 0 != *last_result >> *last_op_size & 1i32; } @@ -62,7 +62,7 @@ pub unsafe extern "C" fn getsf() -> bool { }; } #[no_mangle] -pub unsafe extern "C" fn getof() -> bool { +pub unsafe fn getof() -> bool { if 0 != *flags_changed & FLAG_OVERFLOW { return 0 != ((*last_op1 ^ *last_add_result) & (*last_op2 ^ *last_add_result)) >> *last_op_size @@ -73,99 +73,89 @@ pub unsafe extern "C" fn getof() -> bool { }; } #[no_mangle] -pub unsafe extern "C" fn test_o() -> bool { return getof(); } +pub unsafe fn test_o() -> bool { return getof(); } #[no_mangle] -pub unsafe extern "C" fn test_b() -> bool { return getcf(); } +pub unsafe fn test_b() -> bool { return getcf(); } #[no_mangle] -pub unsafe extern "C" fn test_z() -> bool { return getzf(); } +pub unsafe fn test_z() -> bool { return getzf(); } #[no_mangle] -pub unsafe extern "C" fn test_s() -> bool { return getsf(); } +pub unsafe fn test_s() -> bool { return getsf(); } #[no_mangle] -pub unsafe extern "C" fn test_p() -> bool { return getpf(); } +pub unsafe fn test_p() -> bool { return getpf(); } #[no_mangle] -pub unsafe extern "C" fn test_be() -> bool { return 0 != getcf() as i32 || 0 != getzf() as i32; } +pub unsafe fn test_be() -> bool { return 0 != getcf() as i32 || 0 != getzf() as i32; } #[no_mangle] -pub unsafe extern "C" fn test_l() -> bool { return getsf() as i32 != getof() as i32; } +pub unsafe fn test_l() -> bool { return getsf() as i32 != getof() as i32; } #[no_mangle] -pub unsafe extern "C" fn test_le() -> bool { - return 0 != getzf() as i32 || getsf() as i32 != getof() as i32; -} +pub unsafe fn test_le() -> bool { return 0 != getzf() as i32 || getsf() as i32 != getof() as i32; } #[no_mangle] -pub unsafe extern "C" fn test_no() -> bool { return !test_o(); } +pub unsafe fn test_no() -> bool { return !test_o(); } #[no_mangle] -pub unsafe extern "C" fn test_nb() -> bool { return !test_b(); } +pub unsafe fn test_nb() -> bool { return !test_b(); } #[no_mangle] -pub unsafe extern "C" fn test_nz() -> bool { return !test_z(); } +pub unsafe fn test_nz() -> bool { return !test_z(); } #[no_mangle] -pub unsafe extern "C" fn test_ns() -> bool { return !test_s(); } +pub unsafe fn test_ns() -> bool { return !test_s(); } #[no_mangle] -pub unsafe extern "C" fn test_np() -> bool { return !test_p(); } +pub unsafe fn test_np() -> bool { return !test_p(); } #[no_mangle] -pub unsafe extern "C" fn test_nbe() -> bool { return !test_be(); } +pub unsafe fn test_nbe() -> bool { return !test_be(); } #[no_mangle] -pub unsafe extern "C" fn test_nl() -> bool { return !test_l(); } +pub unsafe fn test_nl() -> bool { return !test_l(); } #[no_mangle] -pub unsafe extern "C" fn test_nle() -> bool { return !test_le(); } +pub unsafe fn test_nle() -> bool { return !test_le(); } #[no_mangle] -pub unsafe extern "C" fn jmp_rel16(mut rel16: i32) -> () { +pub unsafe fn jmp_rel16(mut rel16: i32) -> () { let mut cs_offset: i32 = get_seg_cs(); c_comment!(("limit ip to 16 bit")); *instruction_pointer = cs_offset + (*instruction_pointer - cs_offset + rel16 & 65535i32); } #[no_mangle] -pub unsafe extern "C" fn jmpcc16(mut condition: bool, mut imm16: i32) -> () { +pub unsafe fn jmpcc16(mut condition: bool, mut imm16: i32) -> () { if condition { jmp_rel16(imm16); }; } #[no_mangle] -pub unsafe extern "C" fn jmpcc32(mut condition: bool, mut imm32: i32) -> () { +pub unsafe fn jmpcc32(mut condition: bool, mut imm32: i32) -> () { if condition { *instruction_pointer += imm32 }; } #[no_mangle] -pub unsafe extern "C" fn loope16(mut imm8s: i32) -> () { +pub unsafe fn loope16(mut imm8s: i32) -> () { jmpcc16(0 != decr_ecx_asize() && 0 != getzf() as i32, imm8s); } #[no_mangle] -pub unsafe extern "C" fn loopne16(mut imm8s: i32) -> () { - jmpcc16(0 != decr_ecx_asize() && !getzf(), imm8s); -} +pub unsafe fn loopne16(mut imm8s: i32) -> () { jmpcc16(0 != decr_ecx_asize() && !getzf(), imm8s); } #[no_mangle] -pub unsafe extern "C" fn loop16(mut imm8s: i32) -> () { jmpcc16(0 != decr_ecx_asize(), imm8s); } +pub unsafe fn loop16(mut imm8s: i32) -> () { jmpcc16(0 != decr_ecx_asize(), imm8s); } #[no_mangle] -pub unsafe extern "C" fn jcxz16(mut imm8s: i32) -> () { - jmpcc16(get_reg_asize(ECX) == 0i32, imm8s); -} +pub unsafe fn jcxz16(mut imm8s: i32) -> () { jmpcc16(get_reg_asize(ECX) == 0i32, imm8s); } #[no_mangle] -pub unsafe extern "C" fn loope32(mut imm8s: i32) -> () { +pub unsafe fn loope32(mut imm8s: i32) -> () { jmpcc32(0 != decr_ecx_asize() && 0 != getzf() as i32, imm8s); } #[no_mangle] -pub unsafe extern "C" fn loopne32(mut imm8s: i32) -> () { - jmpcc32(0 != decr_ecx_asize() && !getzf(), imm8s); -} +pub unsafe fn loopne32(mut imm8s: i32) -> () { jmpcc32(0 != decr_ecx_asize() && !getzf(), imm8s); } #[no_mangle] -pub unsafe extern "C" fn loop32(mut imm8s: i32) -> () { jmpcc32(0 != decr_ecx_asize(), imm8s); } +pub unsafe fn loop32(mut imm8s: i32) -> () { jmpcc32(0 != decr_ecx_asize(), imm8s); } #[no_mangle] -pub unsafe extern "C" fn jcxz32(mut imm8s: i32) -> () { - jmpcc32(get_reg_asize(ECX) == 0i32, imm8s); -} +pub unsafe fn jcxz32(mut imm8s: i32) -> () { jmpcc32(get_reg_asize(ECX) == 0i32, imm8s); } #[no_mangle] -pub unsafe extern "C" fn cmovcc16(mut condition: bool, mut value: i32, mut r: i32) -> () { +pub unsafe fn cmovcc16(mut condition: bool, mut value: i32, mut r: i32) -> () { if condition { write_reg16(r, value); }; } #[no_mangle] -pub unsafe extern "C" fn cmovcc32(mut condition: bool, mut value: i32, mut r: i32) -> () { +pub unsafe fn cmovcc32(mut condition: bool, mut value: i32, mut r: i32) -> () { if condition { write_reg32(r, value); }; } #[no_mangle] -pub unsafe extern "C" fn get_stack_pointer(mut offset: i32) -> i32 { +pub unsafe fn get_stack_pointer(mut offset: i32) -> i32 { if *stack_size_32 { return get_seg_ss() + *reg32s.offset(ESP as isize) + offset; } @@ -174,7 +164,7 @@ pub unsafe extern "C" fn get_stack_pointer(mut offset: i32) -> i32 { }; } #[no_mangle] -pub unsafe extern "C" fn adjust_stack_reg(mut adjustment: i32) -> () { +pub unsafe fn adjust_stack_reg(mut adjustment: i32) -> () { if *stack_size_32 { let ref mut fresh0 = *reg32s.offset(ESP as isize); *fresh0 += adjustment @@ -186,7 +176,7 @@ pub unsafe extern "C" fn adjust_stack_reg(mut adjustment: i32) -> () { } #[no_mangle] -pub unsafe extern "C" fn push16_ss16(mut imm16: i32) -> Result<(), ()> { +pub unsafe fn push16_ss16(mut imm16: i32) -> Result<(), ()> { let mut sp: i32 = get_seg_ss() + (*reg16.offset(SP as isize) as i32 - 2i32 & 65535i32); safe_write16(sp, imm16)?; let ref mut fresh2 = *reg16.offset(SP as isize); @@ -194,7 +184,7 @@ pub unsafe extern "C" fn push16_ss16(mut imm16: i32) -> Result<(), ()> { Ok(()) } #[no_mangle] -pub unsafe extern "C" fn push16_ss32(mut imm16: i32) -> Result<(), ()> { +pub unsafe fn push16_ss32(mut imm16: i32) -> Result<(), ()> { let mut sp: i32 = get_seg_ss() + *reg32s.offset(ESP as isize) - 2i32; safe_write16(sp, imm16)?; let ref mut fresh3 = *reg32s.offset(ESP as isize); @@ -203,34 +193,22 @@ pub unsafe extern "C" fn push16_ss32(mut imm16: i32) -> Result<(), ()> { } #[no_mangle] -pub unsafe extern "C" fn push16_ss16_jit(mut imm16: i32) { - return_on_pagefault!(push16_ss16(imm16)) -} +pub unsafe fn push16_ss16_jit(mut imm16: i32) { return_on_pagefault!(push16_ss16(imm16)) } #[no_mangle] -pub unsafe extern "C" fn push16_ss32_jit(mut imm16: i32) { - return_on_pagefault!(push16_ss32(imm16)) -} +pub unsafe fn push16_ss32_jit(mut imm16: i32) { return_on_pagefault!(push16_ss32(imm16)) } #[no_mangle] -pub unsafe extern "C" fn push16_ss16_mem(mut addr: i32) -> Result<(), ()> { - push16_ss16(safe_read16(addr)?) -} +pub unsafe fn push16_ss16_mem(mut addr: i32) -> Result<(), ()> { push16_ss16(safe_read16(addr)?) } #[no_mangle] -pub unsafe extern "C" fn push16_ss32_mem(mut addr: i32) -> Result<(), ()> { - push16_ss32(safe_read16(addr)?) -} +pub unsafe fn push16_ss32_mem(mut addr: i32) -> Result<(), ()> { push16_ss32(safe_read16(addr)?) } #[no_mangle] -pub unsafe extern "C" fn push16_ss16_mem_jit(mut addr: i32) { - return_on_pagefault!(push16_ss16_mem(addr)) -} +pub unsafe fn push16_ss16_mem_jit(mut addr: i32) { return_on_pagefault!(push16_ss16_mem(addr)) } #[no_mangle] -pub unsafe extern "C" fn push16_ss32_mem_jit(mut addr: i32) { - return_on_pagefault!(push16_ss32_mem(addr)) -} +pub unsafe fn push16_ss32_mem_jit(mut addr: i32) { return_on_pagefault!(push16_ss32_mem(addr)) } #[no_mangle] -pub unsafe extern "C" fn push16(mut imm16: i32) -> Result<(), ()> { +pub unsafe fn push16(mut imm16: i32) -> Result<(), ()> { if *stack_size_32 { push16_ss32(imm16) } @@ -240,14 +218,14 @@ pub unsafe extern "C" fn push16(mut imm16: i32) -> Result<(), ()> { } #[no_mangle] -pub unsafe extern "C" fn push32_ss16(mut imm32: i32) -> Result<(), ()> { +pub unsafe fn push32_ss16(mut imm32: i32) -> Result<(), ()> { let mut new_sp: i32 = *reg16.offset(SP as isize) as i32 - 4i32 & 65535i32; safe_write32(get_seg_ss() + new_sp, imm32)?; *reg16.offset(SP as isize) = new_sp as u16; Ok(()) } #[no_mangle] -pub unsafe extern "C" fn push32_ss32(mut imm32: i32) -> Result<(), ()> { +pub unsafe fn push32_ss32(mut imm32: i32) -> Result<(), ()> { let mut new_esp: i32 = *reg32s.offset(ESP as isize) - 4i32; safe_write32(get_seg_ss() + new_esp, imm32)?; *reg32s.offset(ESP as isize) = new_esp; @@ -255,34 +233,22 @@ pub unsafe extern "C" fn push32_ss32(mut imm32: i32) -> Result<(), ()> { } #[no_mangle] -pub unsafe extern "C" fn push32_ss16_jit(mut imm32: i32) { - return_on_pagefault!(push32_ss16(imm32)) -} +pub unsafe fn push32_ss16_jit(mut imm32: i32) { return_on_pagefault!(push32_ss16(imm32)) } #[no_mangle] -pub unsafe extern "C" fn push32_ss32_jit(mut imm32: i32) { - return_on_pagefault!(push32_ss32(imm32)) -} +pub unsafe fn push32_ss32_jit(mut imm32: i32) { return_on_pagefault!(push32_ss32(imm32)) } #[no_mangle] -pub unsafe extern "C" fn push32_ss16_mem(mut addr: i32) -> Result<(), ()> { - push32_ss16(safe_read32s(addr)?) -} +pub unsafe fn push32_ss16_mem(mut addr: i32) -> Result<(), ()> { push32_ss16(safe_read32s(addr)?) } #[no_mangle] -pub unsafe extern "C" fn push32_ss32_mem(mut addr: i32) -> Result<(), ()> { - push32_ss32(safe_read32s(addr)?) -} +pub unsafe fn push32_ss32_mem(mut addr: i32) -> Result<(), ()> { push32_ss32(safe_read32s(addr)?) } #[no_mangle] -pub unsafe extern "C" fn push32_ss16_mem_jit(mut addr: i32) { - return_on_pagefault!(push32_ss16_mem(addr)) -} +pub unsafe fn push32_ss16_mem_jit(mut addr: i32) { return_on_pagefault!(push32_ss16_mem(addr)) } #[no_mangle] -pub unsafe extern "C" fn push32_ss32_mem_jit(mut addr: i32) { - return_on_pagefault!(push32_ss32_mem(addr)) -} +pub unsafe fn push32_ss32_mem_jit(mut addr: i32) { return_on_pagefault!(push32_ss32_mem(addr)) } #[no_mangle] -pub unsafe extern "C" fn push32(mut imm32: i32) -> Result<(), ()> { +pub unsafe fn push32(mut imm32: i32) -> Result<(), ()> { if *stack_size_32 { push32_ss32(imm32) } @@ -291,7 +257,7 @@ pub unsafe extern "C" fn push32(mut imm32: i32) -> Result<(), ()> { } } #[no_mangle] -pub unsafe extern "C" fn pop16() -> Result { +pub unsafe fn pop16() -> Result { if *stack_size_32 { pop16_ss32() } @@ -300,7 +266,7 @@ pub unsafe extern "C" fn pop16() -> Result { } } #[no_mangle] -pub unsafe extern "C" fn pop16_ss16() -> Result { +pub unsafe fn pop16_ss16() -> Result { let mut sp: i32 = get_seg_ss() + *reg16.offset(SP as isize) as i32; let mut result: i32 = safe_read16(sp)?; let ref mut fresh4 = *reg16.offset(SP as isize); @@ -308,7 +274,7 @@ pub unsafe extern "C" fn pop16_ss16() -> Result { Ok(result) } #[no_mangle] -pub unsafe extern "C" fn pop16_ss32() -> Result { +pub unsafe fn pop16_ss32() -> Result { let mut esp: i32 = get_seg_ss() + *reg32s.offset(ESP as isize); let mut result: i32 = safe_read16(esp)?; let ref mut fresh5 = *reg32s.offset(ESP as isize); @@ -316,7 +282,7 @@ pub unsafe extern "C" fn pop16_ss32() -> Result { Ok(result) } #[no_mangle] -pub unsafe extern "C" fn pop32s() -> Result { +pub unsafe fn pop32s() -> Result { if *stack_size_32 { pop32s_ss32() } @@ -325,21 +291,21 @@ pub unsafe extern "C" fn pop32s() -> Result { } } #[no_mangle] -pub unsafe extern "C" fn pop32s_ss16() -> Result { +pub unsafe fn pop32s_ss16() -> Result { let mut sp: i32 = *reg16.offset(SP as isize) as i32; let mut result: i32 = safe_read32s(get_seg_ss() + sp)?; *reg16.offset(SP as isize) = (sp + 4i32) as u16; Ok(result) } #[no_mangle] -pub unsafe extern "C" fn pop32s_ss32() -> Result { +pub unsafe fn pop32s_ss32() -> Result { let mut esp: i32 = *reg32s.offset(ESP as isize); let mut result: i32 = safe_read32s(get_seg_ss() + esp)?; *reg32s.offset(ESP as isize) = esp + 4i32; Ok(result) } #[no_mangle] -pub unsafe extern "C" fn pusha16() -> () { +pub unsafe fn pusha16() -> () { let mut temp: u16 = *reg16.offset(SP as isize); c_comment!(("make sure we don\'t get a pagefault after having")); c_comment!(("pushed several registers already")); @@ -354,7 +320,7 @@ pub unsafe extern "C" fn pusha16() -> () { push16(*reg16.offset(DI as isize) as i32).unwrap(); } #[no_mangle] -pub unsafe extern "C" fn pusha32() -> () { +pub unsafe fn pusha32() -> () { let mut temp: i32 = *reg32s.offset(ESP as isize); return_on_pagefault!(writable_or_pagefault(get_stack_pointer(-32i32), 32i32)); push32(*reg32s.offset(EAX as isize)).unwrap(); @@ -367,18 +333,18 @@ pub unsafe extern "C" fn pusha32() -> () { push32(*reg32s.offset(EDI as isize)).unwrap(); } #[no_mangle] -pub unsafe extern "C" fn setcc_reg(mut condition: bool, mut r: i32) -> () { +pub unsafe fn setcc_reg(mut condition: bool, mut r: i32) -> () { write_reg8(r, if 0 != condition as i32 { 1i32 } else { 0i32 }); } #[no_mangle] -pub unsafe extern "C" fn setcc_mem(mut condition: bool, mut addr: i32) -> () { +pub unsafe fn setcc_mem(mut condition: bool, mut addr: i32) -> () { return_on_pagefault!(safe_write8( addr, if 0 != condition as i32 { 1i32 } else { 0i32 } )); } #[no_mangle] -pub unsafe extern "C" fn fxsave(mut addr: u32) -> () { +pub unsafe fn fxsave(mut addr: u32) -> () { return_on_pagefault!(writable_or_pagefault(addr as i32, 512i32)); safe_write16(addr.wrapping_add(0i32 as u32) as i32, *fpu_control_word).unwrap(); safe_write16( @@ -419,7 +385,7 @@ pub unsafe extern "C" fn fxsave(mut addr: u32) -> () { } } #[no_mangle] -pub unsafe extern "C" fn fxrstor(mut addr: u32) -> () { +pub unsafe fn fxrstor(mut addr: u32) -> () { // TODO: Add readable_or_pagefault return_on_pagefault!(translate_address_read(addr as i32)); return_on_pagefault!(translate_address_read( @@ -478,31 +444,31 @@ pub unsafe extern "C" fn fxrstor(mut addr: u32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn xchg8(mut data: i32, mut r8: i32) -> i32 { +pub unsafe fn xchg8(mut data: i32, mut r8: i32) -> i32 { let mut tmp: i32 = *reg8.offset(r8 as isize) as i32; *reg8.offset(r8 as isize) = data as u8; return tmp; } #[no_mangle] -pub unsafe extern "C" fn xchg16(mut data: i32, mut r16: i32) -> i32 { +pub unsafe fn xchg16(mut data: i32, mut r16: i32) -> i32 { let mut tmp: i32 = *reg16.offset(r16 as isize) as i32; *reg16.offset(r16 as isize) = data as u16; return tmp; } #[no_mangle] -pub unsafe extern "C" fn xchg16r(mut r16: i32) -> () { +pub unsafe fn xchg16r(mut r16: i32) -> () { let mut tmp: i32 = *reg16.offset(AX as isize) as i32; *reg16.offset(AX as isize) = *reg16.offset(r16 as isize); *reg16.offset(r16 as isize) = tmp as u16; } #[no_mangle] -pub unsafe extern "C" fn xchg32(mut data: i32, mut r32: i32) -> i32 { +pub unsafe fn xchg32(mut data: i32, mut r32: i32) -> i32 { let mut tmp: i32 = *reg32s.offset(r32 as isize); *reg32s.offset(r32 as isize) = data; return tmp; } #[no_mangle] -pub unsafe extern "C" fn xchg32r(mut r32: i32) -> () { +pub unsafe fn xchg32r(mut r32: i32) -> () { let mut tmp: i32 = *reg32s.offset(EAX as isize); *reg32s.offset(EAX as isize) = *reg32s.offset(r32 as isize); *reg32s.offset(r32 as isize) = tmp; diff --git a/src/rust/cpu2/modrm.rs b/src/rust/cpu2/modrm.rs index c5cb650b..064be203 100644 --- a/src/rust/cpu2/modrm.rs +++ b/src/rust/cpu2/modrm.rs @@ -11,7 +11,7 @@ use cpu2::cpu::*; use cpu2::global_pointers::*; #[no_mangle] -pub unsafe extern "C" fn resolve_modrm16(mut modrm_byte: i32) -> Result { +pub unsafe fn resolve_modrm16(mut modrm_byte: i32) -> Result { Ok(match modrm_byte { 0 | 8 | 16 | 24 | 32 | 40 | 48 | 56 => get_seg_prefix_ds( *reg16.offset(BX as isize) as i32 + *reg16.offset(SI as isize) as i32 & 65535i32, @@ -98,7 +98,7 @@ pub unsafe extern "C" fn resolve_modrm16(mut modrm_byte: i32) -> Result }) } #[no_mangle] -pub unsafe extern "C" fn resolve_modrm32_(mut modrm_byte: i32) -> Result { +pub unsafe fn resolve_modrm32_(mut modrm_byte: i32) -> Result { let mut r: u8 = (modrm_byte & 7i32) as u8; dbg_assert!(modrm_byte < 192i32); Ok(if r as i32 == 4i32 { @@ -143,7 +143,7 @@ pub unsafe extern "C" fn resolve_modrm32_(mut modrm_byte: i32) -> Result Result { +unsafe fn resolve_sib(mut mod_0: bool) -> Result { let mut s: u8 = 0; let mut sib_byte: u8 = read_imm8()? as u8; let mut r: u8 = (sib_byte as i32 & 7i32) as u8; @@ -179,13 +179,13 @@ unsafe extern "C" fn resolve_sib(mut mod_0: bool) -> Result { Ok(get_seg_prefix(seg) + base + offset) } #[no_mangle] -pub unsafe extern "C" fn MODRM_ENTRY() -> i32 { return 0i32; } +pub unsafe fn MODRM_ENTRY() -> i32 { return 0i32; } #[no_mangle] -pub unsafe extern "C" fn MODRM_ENTRY16() -> i32 { return 0i32; } +pub unsafe fn MODRM_ENTRY16() -> i32 { return 0i32; } #[no_mangle] -pub unsafe extern "C" fn MODRM_ENTRY32() -> i32 { return 0i32; } +pub unsafe fn MODRM_ENTRY32() -> i32 { return 0i32; } #[no_mangle] -pub unsafe extern "C" fn resolve_modrm32(mut modrm_byte: i32) -> Result { +pub unsafe fn resolve_modrm32(mut modrm_byte: i32) -> Result { Ok(match modrm_byte { 0 | 8 | 16 | 24 | 32 | 40 | 48 | 56 => get_seg_prefix_ds(*reg32s.offset(EAX as isize)), 64 | 72 | 80 | 88 | 96 | 104 | 112 | 120 => { diff --git a/src/rust/cpu2/profiler.rs b/src/rust/cpu2/profiler.rs index 073a9f7b..e05ea624 100644 --- a/src/rust/cpu2/profiler.rs +++ b/src/rust/cpu2/profiler.rs @@ -96,7 +96,7 @@ pub static mut profiler_stat_arr: [profiler_stat; 37] = unsafe { ] }; #[no_mangle] -pub unsafe extern "C" fn profiler_init() -> () { +pub unsafe fn profiler_init() -> () { let mut i: u32 = 0i32 as u32; while i < (S_TLB_GLOBAL_FULL as i32 - S_COMPILE as i32 + 1i32) as u32 { profiler_stat_arr[i as usize].count = 0i32; @@ -104,18 +104,16 @@ pub unsafe extern "C" fn profiler_init() -> () { } } #[no_mangle] -pub unsafe extern "C" fn profiler_stat_increment(mut stat: stat_name) -> () { +pub unsafe fn profiler_stat_increment(mut stat: stat_name) -> () { profiler_stat_increment_by(stat, 1i32); } #[no_mangle] -pub unsafe extern "C" fn profiler_stat_increment_by(mut stat: stat_name, mut by: i32) -> () { +pub unsafe fn profiler_stat_increment_by(mut stat: stat_name, mut by: i32) -> () { profiler_stat_arr[stat as usize].count += by; } #[no_mangle] -pub unsafe extern "C" fn profiler_stat_get(mut stat: stat_name) -> i32 { +pub unsafe fn profiler_stat_get(mut stat: stat_name) -> i32 { return profiler_stat_arr[stat as usize].count; } #[no_mangle] -pub unsafe extern "C" fn profiler_stat_increment_do_run() -> () { - profiler_stat_increment(S_DO_RUN); -} +pub unsafe fn profiler_stat_increment_do_run() -> () { profiler_stat_increment(S_DO_RUN); } diff --git a/src/rust/cpu2/sse_instr.rs b/src/rust/cpu2/sse_instr.rs index ea25ed17..eb43c9bc 100644 --- a/src/rust/cpu2/sse_instr.rs +++ b/src/rust/cpu2/sse_instr.rs @@ -10,36 +10,36 @@ use cpu2::cpu::*; #[no_mangle] -pub unsafe extern "C" fn mov_r_m64(mut addr: i32, mut r: i32) -> () { +pub unsafe fn mov_r_m64(mut addr: i32, mut r: i32) -> () { c_comment!(("mov* m64, mm")); let mut data: reg64 = read_mmx64s(r); return_on_pagefault!(safe_write64(addr, data.u64_0[0usize] as i64)); } #[no_mangle] -pub unsafe extern "C" fn movl_r128_m64(mut addr: i32, mut r: i32) -> () { +pub unsafe fn movl_r128_m64(mut addr: i32, mut r: i32) -> () { c_comment!(("mov* m64, xmm")); let mut data: reg64 = read_xmm64s(r); return_on_pagefault!(safe_write64(addr, data.u64_0[0usize] as i64)); } #[no_mangle] -pub unsafe extern "C" fn mov_r_r128(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn mov_r_r128(mut r1: i32, mut r2: i32) -> () { c_comment!(("mov* xmm, xmm")); let mut data: reg128 = read_xmm128s(r2); write_xmm_reg128(r1, data); } #[no_mangle] -pub unsafe extern "C" fn mov_r_m128(mut addr: i32, mut r: i32) -> () { +pub unsafe fn mov_r_m128(mut addr: i32, mut r: i32) -> () { c_comment!(("mov* m128, xmm")); let mut data: reg128 = read_xmm128s(r); return_on_pagefault!(safe_write128(addr, data)); } #[no_mangle] -pub unsafe extern "C" fn mov_rm_r128(mut source: reg128, mut r: i32) -> () { +pub unsafe fn mov_rm_r128(mut source: reg128, mut r: i32) -> () { c_comment!(("mov* xmm, xmm/m128")); write_xmm_reg128(r, source); } #[no_mangle] -pub unsafe extern "C" fn movh_m64_r128(mut addr: i32, mut r: i32) -> () { +pub unsafe fn movh_m64_r128(mut addr: i32, mut r: i32) -> () { c_comment!(("movhp* xmm, m64")); let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); let mut orig: reg128 = read_xmm128s(r); @@ -52,13 +52,13 @@ pub unsafe extern "C" fn movh_m64_r128(mut addr: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe extern "C" fn movh_r128_m64(mut addr: i32, mut r: i32) -> () { +pub unsafe fn movh_r128_m64(mut addr: i32, mut r: i32) -> () { c_comment!(("movhp* m64, xmm")); let mut data: reg128 = read_xmm128s(r); return_on_pagefault!(safe_write64(addr, data.u64_0[1usize] as i64)); } #[no_mangle] -pub unsafe extern "C" fn pand_r128(mut source: reg128, mut r: i32) -> () { +pub unsafe fn pand_r128(mut source: reg128, mut r: i32) -> () { c_comment!(("pand xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -70,7 +70,7 @@ pub unsafe extern "C" fn pand_r128(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn pandn_r128(mut source: reg128, mut r: i32) -> () { +pub unsafe fn pandn_r128(mut source: reg128, mut r: i32) -> () { c_comment!(("pandn xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -82,7 +82,7 @@ pub unsafe extern "C" fn pandn_r128(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn pxor_r128(mut source: reg128, mut r: i32) -> () { +pub unsafe fn pxor_r128(mut source: reg128, mut r: i32) -> () { c_comment!(("pxor xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -94,7 +94,7 @@ pub unsafe extern "C" fn pxor_r128(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn por_r128(mut source: reg128, mut r: i32) -> () { +pub unsafe fn por_r128(mut source: reg128, mut r: i32) -> () { c_comment!(("por xmm, xmm/m128")); c_comment!(("XXX: Aligned access or #gp")); let mut destination: reg128 = read_xmm128s(r); @@ -106,7 +106,7 @@ pub unsafe extern "C" fn por_r128(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe extern "C" fn psrlw_r64(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psrlw_r64(mut r: i32, mut shift: u32) -> () { c_comment!(("psrlw mm, {shift}")); let mut destination: reg64 = read_mmx64s(r); let mut dword0: i32 = 0i32; @@ -120,7 +120,7 @@ pub unsafe extern "C" fn psrlw_r64(mut r: i32, mut shift: u32) -> () { write_mmx64(r, dword0, dword1); } #[no_mangle] -pub unsafe extern "C" fn psraw_r64(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psraw_r64(mut r: i32, mut shift: u32) -> () { c_comment!(("psraw mm, {shift}")); let mut destination: reg64 = read_mmx64s(r); let mut shift_clamped: i32 = (if shift > 15i32 as u32 { @@ -136,7 +136,7 @@ pub unsafe extern "C" fn psraw_r64(mut r: i32, mut shift: u32) -> () { write_mmx64(r, dword0, dword1); } #[no_mangle] -pub unsafe extern "C" fn psllw_r64(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psllw_r64(mut r: i32, mut shift: u32) -> () { c_comment!(("psllw mm, {shift}")); let mut destination: reg64 = read_mmx64s(r); let mut dword0: i32 = 0i32; @@ -150,7 +150,7 @@ pub unsafe extern "C" fn psllw_r64(mut r: i32, mut shift: u32) -> () { write_mmx64(r, dword0, dword1); } #[no_mangle] -pub unsafe extern "C" fn psrld_r64(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psrld_r64(mut r: i32, mut shift: u32) -> () { c_comment!(("psrld mm, {shift}")); let mut destination: reg64 = read_mmx64s(r); let mut dword0: i32 = 0i32; @@ -162,7 +162,7 @@ pub unsafe extern "C" fn psrld_r64(mut r: i32, mut shift: u32) -> () { write_mmx64(r, dword0, dword1); } #[no_mangle] -pub unsafe extern "C" fn psrad_r64(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psrad_r64(mut r: i32, mut shift: u32) -> () { c_comment!(("psrad mm, {shift}")); let mut destination: reg64 = read_mmx64s(r); let mut shift_clamped: i32 = (if shift > 31i32 as u32 { @@ -176,7 +176,7 @@ pub unsafe extern "C" fn psrad_r64(mut r: i32, mut shift: u32) -> () { write_mmx64(r, dword0, dword1); } #[no_mangle] -pub unsafe extern "C" fn pslld_r64(mut r: i32, mut shift: u32) -> () { +pub unsafe fn pslld_r64(mut r: i32, mut shift: u32) -> () { c_comment!(("pslld mm, {shift}")); let mut destination: reg64 = read_mmx64s(r); let mut dword0: i32 = 0i32; @@ -188,7 +188,7 @@ pub unsafe extern "C" fn pslld_r64(mut r: i32, mut shift: u32) -> () { write_mmx64(r, dword0, dword1); } #[no_mangle] -pub unsafe extern "C" fn psrlq_r64(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psrlq_r64(mut r: i32, mut shift: u32) -> () { c_comment!(("psrlq mm, {shift}")); if shift == 0i32 as u32 { return; @@ -206,7 +206,7 @@ pub unsafe extern "C" fn psrlq_r64(mut r: i32, mut shift: u32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn psllq_r64(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psllq_r64(mut r: i32, mut shift: u32) -> () { c_comment!(("psllq mm, {shift}")); let mut destination: reg64 = read_mmx64s(r); if shift == 0i32 as u32 { @@ -224,7 +224,7 @@ pub unsafe extern "C" fn psllq_r64(mut r: i32, mut shift: u32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn psrlw_r128(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psrlw_r128(mut r: i32, mut shift: u32) -> () { c_comment!(("psrlw xmm, {shift}")); let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = 0i32; @@ -244,7 +244,7 @@ pub unsafe extern "C" fn psrlw_r128(mut r: i32, mut shift: u32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe extern "C" fn psraw_r128(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psraw_r128(mut r: i32, mut shift: u32) -> () { c_comment!(("psraw xmm, {shift}")); let mut destination: reg128 = read_xmm128s(r); let mut shift_clamped: i32 = (if shift > 15i32 as u32 { @@ -264,7 +264,7 @@ pub unsafe extern "C" fn psraw_r128(mut r: i32, mut shift: u32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe extern "C" fn psllw_r128(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psllw_r128(mut r: i32, mut shift: u32) -> () { c_comment!(("psllw xmm, {shift}")); let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = 0i32; @@ -284,7 +284,7 @@ pub unsafe extern "C" fn psllw_r128(mut r: i32, mut shift: u32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe extern "C" fn psrld_r128(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psrld_r128(mut r: i32, mut shift: u32) -> () { c_comment!(("psrld xmm, {shift}")); let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = 0i32; @@ -300,7 +300,7 @@ pub unsafe extern "C" fn psrld_r128(mut r: i32, mut shift: u32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe extern "C" fn psrad_r128(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psrad_r128(mut r: i32, mut shift: u32) -> () { c_comment!(("psrad xmm, {shift}")); let mut destination: reg128 = read_xmm128s(r); let mut shift_clamped: i32 = (if shift > 31i32 as u32 { @@ -316,7 +316,7 @@ pub unsafe extern "C" fn psrad_r128(mut r: i32, mut shift: u32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe extern "C" fn pslld_r128(mut r: i32, mut shift: u32) -> () { +pub unsafe fn pslld_r128(mut r: i32, mut shift: u32) -> () { c_comment!(("pslld xmm, {shift}")); let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = 0i32; @@ -332,7 +332,7 @@ pub unsafe extern "C" fn pslld_r128(mut r: i32, mut shift: u32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe extern "C" fn psrlq_r128(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psrlq_r128(mut r: i32, mut shift: u32) -> () { c_comment!(("psrlq xmm, {shift}")); if shift == 0i32 as u32 { return; @@ -351,7 +351,7 @@ pub unsafe extern "C" fn psrlq_r128(mut r: i32, mut shift: u32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn psllq_r128(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psllq_r128(mut r: i32, mut shift: u32) -> () { c_comment!(("psllq xmm, {shift}")); let mut destination: reg128 = read_xmm128s(r); if shift == 0i32 as u32 { @@ -370,7 +370,7 @@ pub unsafe extern "C" fn psllq_r128(mut r: i32, mut shift: u32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn sse_comparison(mut op: i32, mut x: f64, mut y: f64) -> bool { +pub unsafe fn sse_comparison(mut op: i32, mut x: f64, mut y: f64) -> bool { c_comment!(("TODO: Signaling")); match op & 7i32 { 0 => return x == y, @@ -388,17 +388,17 @@ pub unsafe extern "C" fn sse_comparison(mut op: i32, mut x: f64, mut y: f64) -> }; } #[no_mangle] -pub unsafe extern "C" fn sse_min(mut x: f64, mut y: f64) -> f64 { +pub unsafe fn sse_min(mut x: f64, mut y: f64) -> f64 { c_comment!(("if both x and y are 0 or x is nan, y is returned")); return if x < y { x } else { y }; } #[no_mangle] -pub unsafe extern "C" fn sse_max(mut x: f64, mut y: f64) -> f64 { +pub unsafe fn sse_max(mut x: f64, mut y: f64) -> f64 { c_comment!(("if both x and y are 0 or x is nan, y is returned")); return if x > y { x } else { y }; } #[no_mangle] -pub unsafe extern "C" fn sse_convert_f64_to_i32(mut x: f64) -> i32 { +pub unsafe fn sse_convert_f64_to_i32(mut x: f64) -> i32 { c_comment!(("TODO: Rounding modes")); if x >= 2147483648u32.wrapping_neg() as f64 && x < 2147483648u32 as f64 { return x as i64 as i32; diff --git a/src/rust/cpu2/string.rs b/src/rust/cpu2/string.rs index 7458a02e..693dbf20 100644 --- a/src/rust/cpu2/string.rs +++ b/src/rust/cpu2/string.rs @@ -34,7 +34,7 @@ use cpu2::memory::{ }; #[no_mangle] -pub unsafe extern "C" fn string_get_cycle_count(mut size: i32, mut address: i32) -> i32 { +pub unsafe fn string_get_cycle_count(mut size: i32, mut address: i32) -> i32 { dbg_assert!(0 != size && size <= 4i32 && size >= -4i32); if size < 0i32 { size = -size; @@ -46,17 +46,13 @@ pub unsafe extern "C" fn string_get_cycle_count(mut size: i32, mut address: i32) return 4096i32 - (address & 4095i32) >> shift; } #[no_mangle] -pub unsafe extern "C" fn string_get_cycle_count2( - mut size: i32, - mut addr1: i32, - mut addr2: i32, -) -> i32 { +pub unsafe fn string_get_cycle_count2(mut size: i32, mut addr1: i32, mut addr2: i32) -> i32 { let mut c1: i32 = string_get_cycle_count(size, addr1); let mut c2: i32 = string_get_cycle_count(size, addr2); return if c1 < c2 { c1 } else { c2 }; } #[no_mangle] -pub unsafe extern "C" fn movsb_rep() -> () { +pub unsafe fn movsb_rep() -> () { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -101,7 +97,7 @@ pub unsafe extern "C" fn movsb_rep() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn movsb_no_rep() -> () { +pub unsafe fn movsb_no_rep() -> () { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -115,7 +111,7 @@ pub unsafe extern "C" fn movsb_no_rep() -> () { add_reg_asize(ESI, size); } #[no_mangle] -pub unsafe extern "C" fn movsw_rep() -> () { +pub unsafe fn movsw_rep() -> () { let mut diff: i32 = 0; let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); @@ -185,7 +181,7 @@ pub unsafe extern "C" fn movsw_rep() -> () { #[no_mangle] pub static mut MAX_COUNT_PER_CYCLE: i32 = unsafe { 4096i32 }; #[no_mangle] -pub unsafe extern "C" fn movsw_no_rep() -> () { +pub unsafe fn movsw_no_rep() -> () { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -199,7 +195,7 @@ pub unsafe extern "C" fn movsw_no_rep() -> () { add_reg_asize(ESI, size); } #[no_mangle] -pub unsafe extern "C" fn movsd_rep() -> () { +pub unsafe fn movsd_rep() -> () { let mut diff: i32 = 0; let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); @@ -267,7 +263,7 @@ pub unsafe extern "C" fn movsd_rep() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn movsd_no_rep() -> () { +pub unsafe fn movsd_no_rep() -> () { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -281,7 +277,7 @@ pub unsafe extern "C" fn movsd_no_rep() -> () { add_reg_asize(ESI, size); } #[no_mangle] -pub unsafe extern "C" fn cmpsb_rep(mut prefix_flag: i32) -> () { +pub unsafe fn cmpsb_rep(mut prefix_flag: i32) -> () { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut data_src: i32 = 0; @@ -331,7 +327,7 @@ pub unsafe extern "C" fn cmpsb_rep(mut prefix_flag: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn cmpsb_no_rep() -> () { +pub unsafe fn cmpsb_no_rep() -> () { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut data_src: i32 = 0; @@ -349,7 +345,7 @@ pub unsafe extern "C" fn cmpsb_no_rep() -> () { cmp8(data_src, data_dest); } #[no_mangle] -pub unsafe extern "C" fn cmpsw_rep(mut prefix_flag: i32) -> () { +pub unsafe fn cmpsw_rep(mut prefix_flag: i32) -> () { let mut diff: i32 = 0; let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); @@ -424,7 +420,7 @@ pub unsafe extern "C" fn cmpsw_rep(mut prefix_flag: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn cmpsw_no_rep() -> () { +pub unsafe fn cmpsw_no_rep() -> () { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut data_src: i32 = 0; @@ -442,7 +438,7 @@ pub unsafe extern "C" fn cmpsw_no_rep() -> () { cmp16(data_src, data_dest); } #[no_mangle] -pub unsafe extern "C" fn cmpsd_rep(mut prefix_flag: i32) -> () { +pub unsafe fn cmpsd_rep(mut prefix_flag: i32) -> () { let mut diff: i32 = 0; let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); @@ -517,7 +513,7 @@ pub unsafe extern "C" fn cmpsd_rep(mut prefix_flag: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn cmpsd_no_rep() -> () { +pub unsafe fn cmpsd_no_rep() -> () { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut data_src: i32 = 0; @@ -535,7 +531,7 @@ pub unsafe extern "C" fn cmpsd_no_rep() -> () { cmp32(data_src, data_dest); } #[no_mangle] -pub unsafe extern "C" fn stosb_rep() -> () { +pub unsafe fn stosb_rep() -> () { let mut data: i32 = *reg8.offset(AL as isize) as i32; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -577,7 +573,7 @@ pub unsafe extern "C" fn stosb_rep() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn stosb_no_rep() -> () { +pub unsafe fn stosb_no_rep() -> () { let mut data: i32 = *reg8.offset(AL as isize) as i32; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -590,7 +586,7 @@ pub unsafe extern "C" fn stosb_no_rep() -> () { add_reg_asize(EDI, size); } #[no_mangle] -pub unsafe extern "C" fn stosw_rep() -> () { +pub unsafe fn stosw_rep() -> () { let mut diff: i32 = 0; let mut data: i32 = *reg16.offset(AX as isize) as i32; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); @@ -652,7 +648,7 @@ pub unsafe extern "C" fn stosw_rep() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn stosw_no_rep() -> () { +pub unsafe fn stosw_no_rep() -> () { let mut data: i32 = *reg16.offset(AX as isize) as i32; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -665,7 +661,7 @@ pub unsafe extern "C" fn stosw_no_rep() -> () { add_reg_asize(EDI, size); } #[no_mangle] -pub unsafe extern "C" fn stosd_rep() -> () { +pub unsafe fn stosd_rep() -> () { let mut diff: i32 = 0; let mut data: i32 = *reg32s.offset(EAX as isize); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); @@ -727,7 +723,7 @@ pub unsafe extern "C" fn stosd_rep() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn stosd_no_rep() -> () { +pub unsafe fn stosd_no_rep() -> () { let mut data: i32 = *reg32s.offset(EAX as isize); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -740,7 +736,7 @@ pub unsafe extern "C" fn stosd_no_rep() -> () { add_reg_asize(EDI, size); } #[no_mangle] -pub unsafe extern "C" fn lodsb_rep() -> () { +pub unsafe fn lodsb_rep() -> () { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1i32 @@ -781,7 +777,7 @@ pub unsafe extern "C" fn lodsb_rep() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn lodsb_no_rep() -> () { +pub unsafe fn lodsb_no_rep() -> () { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1i32 @@ -793,7 +789,7 @@ pub unsafe extern "C" fn lodsb_no_rep() -> () { add_reg_asize(ESI, size); } #[no_mangle] -pub unsafe extern "C" fn lodsw_rep() -> () { +pub unsafe fn lodsw_rep() -> () { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2i32 @@ -827,7 +823,7 @@ pub unsafe extern "C" fn lodsw_rep() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn lodsw_no_rep() -> () { +pub unsafe fn lodsw_no_rep() -> () { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2i32 @@ -839,7 +835,7 @@ pub unsafe extern "C" fn lodsw_no_rep() -> () { add_reg_asize(ESI, size); } #[no_mangle] -pub unsafe extern "C" fn lodsd_rep() -> () { +pub unsafe fn lodsd_rep() -> () { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4i32 @@ -873,7 +869,7 @@ pub unsafe extern "C" fn lodsd_rep() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn lodsd_no_rep() -> () { +pub unsafe fn lodsd_no_rep() -> () { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4i32 @@ -885,7 +881,7 @@ pub unsafe extern "C" fn lodsd_no_rep() -> () { add_reg_asize(ESI, size); } #[no_mangle] -pub unsafe extern "C" fn scasb_rep(mut prefix_flag: i32) -> () { +pub unsafe fn scasb_rep(mut prefix_flag: i32) -> () { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1i32 @@ -930,7 +926,7 @@ pub unsafe extern "C" fn scasb_rep(mut prefix_flag: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn scasb_no_rep() -> () { +pub unsafe fn scasb_no_rep() -> () { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1i32 @@ -945,7 +941,7 @@ pub unsafe extern "C" fn scasb_no_rep() -> () { cmp8(data_src, data_dest); } #[no_mangle] -pub unsafe extern "C" fn scasw_rep(mut prefix_flag: i32) -> () { +pub unsafe fn scasw_rep(mut prefix_flag: i32) -> () { let mut diff: i32 = 0; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -1011,7 +1007,7 @@ pub unsafe extern "C" fn scasw_rep(mut prefix_flag: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn scasw_no_rep() -> () { +pub unsafe fn scasw_no_rep() -> () { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2i32 @@ -1026,7 +1022,7 @@ pub unsafe extern "C" fn scasw_no_rep() -> () { cmp16(data_src, data_dest); } #[no_mangle] -pub unsafe extern "C" fn scasd_rep(mut prefix_flag: i32) -> () { +pub unsafe fn scasd_rep(mut prefix_flag: i32) -> () { let mut diff: i32 = 0; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -1092,7 +1088,7 @@ pub unsafe extern "C" fn scasd_rep(mut prefix_flag: i32) -> () { }; } #[no_mangle] -pub unsafe extern "C" fn scasd_no_rep() -> () { +pub unsafe fn scasd_no_rep() -> () { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4i32 @@ -1107,7 +1103,7 @@ pub unsafe extern "C" fn scasd_no_rep() -> () { cmp32(data_src, data_dest); } #[no_mangle] -pub unsafe extern "C" fn insb_rep() -> () { +pub unsafe fn insb_rep() -> () { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 1i32) { return; @@ -1155,7 +1151,7 @@ pub unsafe extern "C" fn insb_rep() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn insb_no_rep() -> () { +pub unsafe fn insb_no_rep() -> () { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 1i32) { return; @@ -1175,7 +1171,7 @@ pub unsafe extern "C" fn insb_no_rep() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn insw_rep() -> () { +pub unsafe fn insw_rep() -> () { let mut diff: i32 = 0; let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 2i32) { @@ -1244,7 +1240,7 @@ pub unsafe extern "C" fn insw_rep() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn insw_no_rep() -> () { +pub unsafe fn insw_no_rep() -> () { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 2i32) { return; @@ -1264,7 +1260,7 @@ pub unsafe extern "C" fn insw_no_rep() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn insd_rep() -> () { +pub unsafe fn insd_rep() -> () { let mut diff: i32 = 0; let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 4i32) { @@ -1333,7 +1329,7 @@ pub unsafe extern "C" fn insd_rep() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn insd_no_rep() -> () { +pub unsafe fn insd_no_rep() -> () { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 4i32) { return; @@ -1353,7 +1349,7 @@ pub unsafe extern "C" fn insd_no_rep() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn outsb_rep() -> () { +pub unsafe fn outsb_rep() -> () { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 1i32) { return; @@ -1401,7 +1397,7 @@ pub unsafe extern "C" fn outsb_rep() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn outsb_no_rep() -> () { +pub unsafe fn outsb_no_rep() -> () { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 1i32) { return; @@ -1420,7 +1416,7 @@ pub unsafe extern "C" fn outsb_no_rep() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn outsw_rep() -> () { +pub unsafe fn outsw_rep() -> () { let mut diff: i32 = 0; let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 2i32) { @@ -1488,7 +1484,7 @@ pub unsafe extern "C" fn outsw_rep() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn outsw_no_rep() -> () { +pub unsafe fn outsw_no_rep() -> () { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 2i32) { return; @@ -1507,7 +1503,7 @@ pub unsafe extern "C" fn outsw_no_rep() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn outsd_rep() -> () { +pub unsafe fn outsd_rep() -> () { let mut diff: i32 = 0; let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 4i32) { @@ -1575,7 +1571,7 @@ pub unsafe extern "C" fn outsd_rep() -> () { }; } #[no_mangle] -pub unsafe extern "C" fn outsd_no_rep() -> () { +pub unsafe fn outsd_no_rep() -> () { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 4i32) { return; From a2b2a7c5aee1e79fa064c61ed358a3a7084d79c7 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 20 Aug 2018 11:45:09 -0500 Subject: [PATCH 1198/2137] Clean up profiler and static array --- src/rust/cpu2/cpu.rs | 392 +------------------------------------------ 1 file changed, 2 insertions(+), 390 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index e0d869d7..30c909f7 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -36,23 +36,9 @@ use cpu2::memory::{ }; use cpu2::misc_instr::{getaf, getcf, getof, getpf, getsf, getzf}; use cpu2::modrm::{resolve_modrm16, resolve_modrm32}; +use cpu2::profiler::*; use cpu2::profiler::{profiler_stat_increment, profiler_stat_increment_by}; -pub const S_TRIGGER_CPU_EXCEPTION: stat_name = 14; - -pub const S_CACHE_MISMATCH: stat_name = 6; -pub const S_RUN_FROM_CACHE_STEPS: stat_name = 13; -pub type stat_name = u32; - -pub const S_COMPILE_SUCCESS: stat_name = 1; -pub const S_TLB_GLOBAL_FULL: stat_name = 36; -pub const S_COMPILE: stat_name = 0; -pub const S_DO_MANY_CYCLES: stat_name = 28; -pub const S_CYCLE_INTERNAL: stat_name = 29; -pub const S_COMPILE_BASIC_BLOCK: stat_name = 4; -pub const S_SAFE_WRITE32_SLOW_PAGE_CROSSED: stat_name = 21; -pub const S_SAFE_READ32_SLOW_NOT_USER: stat_name = 18; - #[derive(Copy, Clone)] #[repr(C)] pub union reg64 { @@ -67,22 +53,8 @@ pub union reg64 { pub f32_0: [f32; 2], pub f64_0: [f64; 1], } -pub const S_SAFE_READ32_SLOW_IN_MAPPED_RANGE: stat_name = 19; - -pub const S_RUN_INTERPRETED_STEPS: stat_name = 11; -pub const S_RUN_FROM_CACHE: stat_name = 12; - -pub const S_TLB_FULL: stat_name = 35; pub type cached_state_flags = u8; -pub const S_SAFE_WRITE32_SLOW_HAS_CODE: stat_name = 26; -pub const S_DO_RUN: stat_name = 27; -pub const S_FULL_CLEAR_TLB: stat_name = 34; -pub const S_RUN_INTERPRETED_PENDING: stat_name = 8; -pub const S_NONFAULTING_OPTIMIZATION: stat_name = 32; - -pub const S_SAFE_WRITE32_FAST: stat_name = 20; -pub const S_SAFE_WRITE32_SLOW_NOT_USER: stat_name = 23; #[derive(Copy, Clone)] #[repr(C)] pub union reg128 { @@ -97,29 +69,6 @@ pub union reg128 { pub f32_0: [f32; 4], pub f64_0: [f64; 2], } -pub const S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE: stat_name = 24; -pub const S_SAFE_WRITE32_SLOW_NOT_VALID: stat_name = 22; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct profiler_stat { - pub count: i32, -} -pub const S_COMPILE_CUT_OFF_AT_END_OF_PAGE: stat_name = 2; -pub const S_RUN_INTERPRETED_DIFFERENT_STATE: stat_name = 10; -pub const S_COMPILE_ENTRY_POINT: stat_name = 5; - -pub const S_CLEAR_TLB: stat_name = 33; -pub const S_RUN_INTERPRETED_NEAR_END_OF_PAGE: stat_name = 9; -pub const S_COMPILE_WITH_LOOP_SAFETY: stat_name = 3; -pub const S_INVALIDATE_CACHE_ENTRY: stat_name = 31; -pub const S_SAFE_WRITE32_SLOW_READ_ONLY: stat_name = 25; - -pub const S_SAFE_READ32_SLOW_NOT_VALID: stat_name = 17; -pub const S_RUN_INTERPRETED: stat_name = 7; -pub const S_INVALIDATE_PAGE: stat_name = 30; -pub const S_SAFE_READ32_FAST: stat_name = 15; - -pub const S_SAFE_READ32_SLOW_PAGE_CROSSED: stat_name = 16; #[no_mangle] pub static mut FLAG_CARRY: i32 = unsafe { 1i32 }; @@ -381,344 +330,7 @@ pub static mut jit_block_boundary: bool = unsafe { 0 != 0i32 }; #[no_mangle] pub static mut VALID_TLB_ENTRY_MAX: i32 = unsafe { 10000i32 }; #[no_mangle] -pub static mut valid_tlb_entries: [i32; 10000] = unsafe { - [ - 0i32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ] -}; +pub static mut valid_tlb_entries: [i32; 10000] = unsafe { [0; 10000] }; #[no_mangle] pub static mut valid_tlb_entries_count: i32 = unsafe { 0i32 }; #[no_mangle] From ee3a3d4fe23653061013678139f060a26c6cb470 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 20 Aug 2018 12:17:40 -0500 Subject: [PATCH 1199/2137] Fix statics and constants --- src/rust/cpu2/cpu.rs | 471 +++++++++++-------------------- src/rust/cpu2/fpu.rs | 67 ++--- src/rust/cpu2/imports.rs | 6 +- src/rust/cpu2/instructions_0f.rs | 9 +- src/rust/cpu2/memory.rs | 4 +- src/rust/cpu2/string.rs | 4 +- 6 files changed, 191 insertions(+), 370 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 30c909f7..6ad6bb90 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -30,6 +30,7 @@ extern "C" { } use cpu2::global_pointers::*; +pub use cpu2::imports::{mem16, mem32s, mem8}; use cpu2::memory::{ in_mapped_range, read128, read16, read32s, read64s, read8, read_aligned16, read_aligned32, write128, write16, write32, write64, write8, write_aligned32, @@ -70,44 +71,25 @@ pub union reg128 { pub f64_0: [f64; 2], } -#[no_mangle] -pub static mut FLAG_CARRY: i32 = unsafe { 1i32 }; -#[no_mangle] -pub static mut FLAG_PARITY: i32 = unsafe { 4i32 }; -#[no_mangle] -pub static mut FLAG_ADJUST: i32 = unsafe { 16i32 }; -#[no_mangle] -pub static mut FLAG_ZERO: i32 = unsafe { 64i32 }; -#[no_mangle] -pub static mut FLAG_SIGN: i32 = unsafe { 128i32 }; -#[no_mangle] -pub static mut FLAG_TRAP: i32 = unsafe { 256i32 }; -#[no_mangle] -pub static mut FLAG_INTERRUPT: i32 = unsafe { 512i32 }; -#[no_mangle] -pub static mut FLAG_DIRECTION: i32 = unsafe { 1024i32 }; -#[no_mangle] -pub static mut FLAG_OVERFLOW: i32 = unsafe { 2048i32 }; -#[no_mangle] -pub static mut FLAG_IOPL: i32 = unsafe { 1i32 << 12i32 | 1i32 << 13i32 }; -#[no_mangle] -pub static mut FLAG_NT: i32 = unsafe { 1i32 << 14i32 }; -#[no_mangle] -pub static mut FLAG_RF: i32 = unsafe { 1i32 << 16i32 }; -#[no_mangle] -pub static mut FLAG_VM: i32 = unsafe { 1i32 << 17i32 }; -#[no_mangle] -pub static mut FLAG_AC: i32 = unsafe { 1i32 << 18i32 }; -#[no_mangle] -pub static mut FLAG_VIF: i32 = unsafe { 1i32 << 19i32 }; -#[no_mangle] -pub static mut FLAG_VIP: i32 = unsafe { 1i32 << 20i32 }; -#[no_mangle] -pub static mut FLAG_ID: i32 = unsafe { 1i32 << 21i32 }; -#[no_mangle] -pub static mut FLAGS_DEFAULT: i32 = unsafe { 1i32 << 1i32 }; -#[no_mangle] -pub static mut FLAGS_MASK: i32 = unsafe { +pub const FLAG_CARRY: i32 = 1i32; +pub const FLAG_PARITY: i32 = 4i32; +pub const FLAG_ADJUST: i32 = 16i32; +pub const FLAG_ZERO: i32 = 64i32; +pub const FLAG_SIGN: i32 = 128i32; +pub const FLAG_TRAP: i32 = 256i32; +pub const FLAG_INTERRUPT: i32 = 512i32; +pub const FLAG_DIRECTION: i32 = 1024i32; +pub const FLAG_OVERFLOW: i32 = 2048i32; +pub const FLAG_IOPL: i32 = 1i32 << 12i32 | 1i32 << 13i32; +pub const FLAG_NT: i32 = 1i32 << 14i32; +pub const FLAG_RF: i32 = 1i32 << 16i32; +pub const FLAG_VM: i32 = 1i32 << 17i32; +pub const FLAG_AC: i32 = 1i32 << 18i32; +pub const FLAG_VIF: i32 = 1i32 << 19i32; +pub const FLAG_VIP: i32 = 1i32 << 20i32; +pub const FLAG_ID: i32 = 1i32 << 21i32; +pub const FLAGS_DEFAULT: i32 = 1i32 << 1i32; +pub const FLAGS_MASK: i32 = unsafe { FLAG_CARRY | FLAG_PARITY | FLAG_ADJUST @@ -126,263 +108,144 @@ pub static mut FLAGS_MASK: i32 = unsafe { | FLAG_VIP | FLAG_ID }; -#[no_mangle] -pub static mut FLAGS_ALL: i32 = - unsafe { FLAG_CARRY | FLAG_PARITY | FLAG_ADJUST | FLAG_ZERO | FLAG_SIGN | FLAG_OVERFLOW }; -#[no_mangle] -pub static mut OPSIZE_8: i32 = unsafe { 7i32 }; -#[no_mangle] -pub static mut OPSIZE_16: i32 = unsafe { 15i32 }; -#[no_mangle] -pub static mut OPSIZE_32: i32 = unsafe { 31i32 }; -#[no_mangle] -pub static mut EAX: i32 = unsafe { 0i32 }; -#[no_mangle] -pub static mut ECX: i32 = unsafe { 1i32 }; -#[no_mangle] -pub static mut EDX: i32 = unsafe { 2i32 }; -#[no_mangle] -pub static mut EBX: i32 = unsafe { 3i32 }; -#[no_mangle] -pub static mut ESP: i32 = unsafe { 4i32 }; -#[no_mangle] -pub static mut EBP: i32 = unsafe { 5i32 }; -#[no_mangle] -pub static mut ESI: i32 = unsafe { 6i32 }; -#[no_mangle] -pub static mut EDI: i32 = unsafe { 7i32 }; -#[no_mangle] -pub static mut AX: i32 = unsafe { 0i32 }; -#[no_mangle] -pub static mut CX: i32 = unsafe { 2i32 }; -#[no_mangle] -pub static mut DX: i32 = unsafe { 4i32 }; -#[no_mangle] -pub static mut BX: i32 = unsafe { 6i32 }; -#[no_mangle] -pub static mut SP: i32 = unsafe { 8i32 }; -#[no_mangle] -pub static mut BP: i32 = unsafe { 10i32 }; -#[no_mangle] -pub static mut SI: i32 = unsafe { 12i32 }; -#[no_mangle] -pub static mut DI: i32 = unsafe { 14i32 }; -#[no_mangle] -pub static mut AL: i32 = unsafe { 0i32 }; -#[no_mangle] -pub static mut CL: i32 = unsafe { 4i32 }; -#[no_mangle] -pub static mut DL: i32 = unsafe { 8i32 }; -#[no_mangle] -pub static mut BL: i32 = unsafe { 12i32 }; -#[no_mangle] -pub static mut AH: i32 = unsafe { 1i32 }; -#[no_mangle] -pub static mut CH: i32 = unsafe { 5i32 }; -#[no_mangle] -pub static mut DH: i32 = unsafe { 9i32 }; -#[no_mangle] -pub static mut BH: i32 = unsafe { 13i32 }; -#[no_mangle] -pub static mut ES: i32 = unsafe { 0i32 }; -#[no_mangle] -pub static mut CS: i32 = unsafe { 1i32 }; -#[no_mangle] -pub static mut SS: i32 = unsafe { 2i32 }; -#[no_mangle] -pub static mut DS: i32 = unsafe { 3i32 }; -#[no_mangle] -pub static mut FS: i32 = unsafe { 4i32 }; -#[no_mangle] -pub static mut GS: i32 = unsafe { 5i32 }; -#[no_mangle] -pub static mut TR: i32 = unsafe { 6i32 }; -#[no_mangle] -pub static mut LDTR: i32 = unsafe { 7i32 }; -#[no_mangle] -pub static mut PAGE_TABLE_PRESENT_MASK: i32 = unsafe { 1i32 << 0i32 }; -#[no_mangle] -pub static mut PAGE_TABLE_RW_MASK: i32 = unsafe { 1i32 << 1i32 }; -#[no_mangle] -pub static mut PAGE_TABLE_USER_MASK: i32 = unsafe { 1i32 << 2i32 }; -#[no_mangle] -pub static mut PAGE_TABLE_ACCESSED_MASK: i32 = unsafe { 1i32 << 5i32 }; -#[no_mangle] -pub static mut PAGE_TABLE_DIRTY_MASK: i32 = unsafe { 1i32 << 6i32 }; -#[no_mangle] -pub static mut PAGE_TABLE_PSE_MASK: i32 = unsafe { 1i32 << 7i32 }; -#[no_mangle] -pub static mut PAGE_TABLE_GLOBAL_MASK: i32 = unsafe { 1i32 << 8i32 }; -#[no_mangle] -pub static mut MMAP_BLOCK_BITS: i32 = unsafe { 17i32 }; -#[no_mangle] -pub static mut MMAP_BLOCK_SIZE: i32 = unsafe { 1i32 << MMAP_BLOCK_BITS }; -#[no_mangle] -pub static mut CR0_PE: i32 = unsafe { 1i32 }; -#[no_mangle] -pub static mut CR0_MP: i32 = unsafe { 1i32 << 1i32 }; -#[no_mangle] -pub static mut CR0_EM: i32 = unsafe { 1i32 << 2i32 }; -#[no_mangle] -pub static mut CR0_TS: i32 = unsafe { 1i32 << 3i32 }; -#[no_mangle] -pub static mut CR0_ET: i32 = unsafe { 1i32 << 4i32 }; -#[no_mangle] -pub static mut CR0_WP: i32 = unsafe { 1i32 << 16i32 }; -#[no_mangle] -pub static mut CR0_NW: i32 = unsafe { 1i32 << 29i32 }; -#[no_mangle] -pub static mut CR0_CD: i32 = unsafe { 1i32 << 30i32 }; -#[no_mangle] -pub static mut CR0_PG: i32 = unsafe { 1i32 << 31i32 }; -#[no_mangle] -pub static mut CR4_VME: i32 = unsafe { 1i32 }; -#[no_mangle] -pub static mut CR4_PVI: i32 = unsafe { 1i32 << 1i32 }; -#[no_mangle] -pub static mut CR4_TSD: i32 = unsafe { 1i32 << 2i32 }; -#[no_mangle] -pub static mut CR4_PSE: i32 = unsafe { 1i32 << 4i32 }; -#[no_mangle] -pub static mut CR4_DE: i32 = unsafe { 1i32 << 3i32 }; -#[no_mangle] -pub static mut CR4_PAE: i32 = unsafe { 1i32 << 5i32 }; -#[no_mangle] -pub static mut CR4_PGE: i32 = unsafe { 1i32 << 7i32 }; -#[no_mangle] -pub static mut IA32_SYSENTER_CS: i32 = unsafe { 372i32 }; -#[no_mangle] -pub static mut IA32_SYSENTER_ESP: i32 = unsafe { 373i32 }; -#[no_mangle] -pub static mut IA32_SYSENTER_EIP: i32 = unsafe { 374i32 }; -#[no_mangle] -pub static mut IA32_TIME_STAMP_COUNTER: i32 = unsafe { 16i32 }; -#[no_mangle] -pub static mut IA32_PLATFORM_ID: i32 = unsafe { 23i32 }; -#[no_mangle] -pub static mut IA32_APIC_BASE_MSR: i32 = unsafe { 27i32 }; -#[no_mangle] -pub static mut IA32_BIOS_SIGN_ID: i32 = unsafe { 139i32 }; -#[no_mangle] -pub static mut MSR_PLATFORM_INFO: i32 = unsafe { 206i32 }; -#[no_mangle] -pub static mut MSR_MISC_FEATURE_ENABLES: i32 = unsafe { 320i32 }; -#[no_mangle] -pub static mut IA32_MISC_ENABLE: i32 = unsafe { 416i32 }; -#[no_mangle] -pub static mut IA32_RTIT_CTL: i32 = unsafe { 1392i32 }; -#[no_mangle] -pub static mut MSR_SMI_COUNT: i32 = unsafe { 52i32 }; -#[no_mangle] -pub static mut IA32_MCG_CAP: i32 = unsafe { 377i32 }; -#[no_mangle] -pub static mut IA32_KERNEL_GS_BASE: i32 = unsafe { 3221225729u32 as i32 }; -#[no_mangle] -pub static mut MSR_PKG_C2_RESIDENCY: i32 = unsafe { 1549i32 }; -#[no_mangle] -pub static mut IA32_APIC_BASE_BSP: i32 = unsafe { 1i32 << 8i32 }; -#[no_mangle] -pub static mut IA32_APIC_BASE_EXTD: i32 = unsafe { 1i32 << 10i32 }; -#[no_mangle] -pub static mut IA32_APIC_BASE_EN: i32 = unsafe { 1i32 << 11i32 }; -#[no_mangle] -pub static mut APIC_ADDRESS: i32 = unsafe { 4276092928u32 as i32 }; -#[no_mangle] -pub static mut SEG_PREFIX_NONE: i32 = unsafe { -1i32 }; -#[no_mangle] -pub static mut SEG_PREFIX_ZERO: i32 = unsafe { 7i32 }; -#[no_mangle] -pub static mut PREFIX_MASK_REP: i32 = unsafe { 24i32 }; -#[no_mangle] -pub static mut PREFIX_REPZ: i32 = unsafe { 8i32 }; -#[no_mangle] -pub static mut PREFIX_REPNZ: i32 = unsafe { 16i32 }; -#[no_mangle] -pub static mut PREFIX_MASK_SEGMENT: i32 = unsafe { 7i32 }; -#[no_mangle] -pub static mut PREFIX_MASK_OPSIZE: i32 = unsafe { 32i32 }; -#[no_mangle] -pub static mut PREFIX_MASK_ADDRSIZE: i32 = unsafe { 64i32 }; -#[no_mangle] -pub static mut PREFIX_F2: i32 = unsafe { PREFIX_REPNZ }; -#[no_mangle] -pub static mut PREFIX_F3: i32 = unsafe { PREFIX_REPZ }; -#[no_mangle] -pub static mut PREFIX_66: i32 = unsafe { PREFIX_MASK_OPSIZE }; -#[no_mangle] -pub static mut LOG_CPU: i32 = unsafe { 2i32 }; -#[no_mangle] -pub static mut A20_MASK: i32 = unsafe { !(1i32 << 20i32) }; -#[no_mangle] -pub static mut A20_MASK16: i32 = unsafe { !(1i32 << 20i32 - 1i32) }; -#[no_mangle] -pub static mut A20_MASK32: i32 = unsafe { !(1i32 << 20i32 - 2i32) }; -#[no_mangle] -pub static mut MXCSR_MASK: i32 = unsafe { 65535i32 & !(1i32 << 6i32) }; -#[no_mangle] -pub static mut mem8: *mut u8 = unsafe { 0 as *const u8 as *mut u8 }; -#[no_mangle] -pub static mut mem16: *mut u16 = unsafe { 0 as *const u16 as *mut u16 }; -#[no_mangle] -pub static mut mem32s: *mut i32 = unsafe { 0 as *const i32 as *mut i32 }; -#[no_mangle] -pub static mut jit_block_boundary: bool = unsafe { 0 != 0i32 }; -#[no_mangle] -pub static mut VALID_TLB_ENTRY_MAX: i32 = unsafe { 10000i32 }; -#[no_mangle] -pub static mut valid_tlb_entries: [i32; 10000] = unsafe { [0; 10000] }; -#[no_mangle] -pub static mut valid_tlb_entries_count: i32 = unsafe { 0i32 }; -#[no_mangle] -pub static mut TLB_VALID: i32 = unsafe { 1i32 << 0i32 }; -#[no_mangle] -pub static mut TLB_READONLY: i32 = unsafe { 1i32 << 1i32 }; -#[no_mangle] -pub static mut TLB_NO_USER: i32 = unsafe { 1i32 << 2i32 }; -#[no_mangle] -pub static mut TLB_IN_MAPPED_RANGE: i32 = unsafe { 1i32 << 3i32 }; -#[no_mangle] -pub static mut TLB_GLOBAL: i32 = unsafe { 1i32 << 4i32 }; -#[no_mangle] -pub static mut TLB_HAS_CODE: i32 = unsafe { 1i32 << 5i32 }; -#[no_mangle] -pub static mut CPU_EXCEPTION_DE: i32 = unsafe { 0i32 }; -#[no_mangle] -pub static mut CPU_EXCEPTION_DB: i32 = unsafe { 1i32 }; -#[no_mangle] -pub static mut CPU_EXCEPTION_NMI: i32 = unsafe { 2i32 }; -#[no_mangle] -pub static mut CPU_EXCEPTION_BP: i32 = unsafe { 3i32 }; -#[no_mangle] -pub static mut CPU_EXCEPTION_OF: i32 = unsafe { 4i32 }; -#[no_mangle] -pub static mut CPU_EXCEPTION_BR: i32 = unsafe { 5i32 }; -#[no_mangle] -pub static mut CPU_EXCEPTION_UD: i32 = unsafe { 6i32 }; -#[no_mangle] -pub static mut CPU_EXCEPTION_NM: i32 = unsafe { 7i32 }; -#[no_mangle] -pub static mut CPU_EXCEPTION_DF: i32 = unsafe { 8i32 }; -#[no_mangle] -pub static mut CPU_EXCEPTION_TS: i32 = unsafe { 10i32 }; -#[no_mangle] -pub static mut CPU_EXCEPTION_NP: i32 = unsafe { 11i32 }; -#[no_mangle] -pub static mut CPU_EXCEPTION_SS: i32 = unsafe { 12i32 }; -#[no_mangle] -pub static mut CPU_EXCEPTION_GP: i32 = unsafe { 13i32 }; -#[no_mangle] -pub static mut CPU_EXCEPTION_PF: i32 = unsafe { 14i32 }; -#[no_mangle] -pub static mut CPU_EXCEPTION_MF: i32 = unsafe { 16i32 }; -#[no_mangle] -pub static mut CPU_EXCEPTION_AC: i32 = unsafe { 17i32 }; -#[no_mangle] -pub static mut CPU_EXCEPTION_MC: i32 = unsafe { 18i32 }; -#[no_mangle] -pub static mut CPU_EXCEPTION_XM: i32 = unsafe { 19i32 }; -#[no_mangle] -pub static mut CPU_EXCEPTION_VE: i32 = unsafe { 20i32 }; +pub const FLAGS_ALL: i32 = + FLAG_CARRY | FLAG_PARITY | FLAG_ADJUST | FLAG_ZERO | FLAG_SIGN | FLAG_OVERFLOW; +pub const OPSIZE_8: i32 = 7i32; +pub const OPSIZE_16: i32 = 15i32; +pub const OPSIZE_32: i32 = 31i32; +pub const EAX: i32 = 0i32; +pub const ECX: i32 = 1i32; +pub const EDX: i32 = 2i32; +pub const EBX: i32 = 3i32; +pub const ESP: i32 = 4i32; +pub const EBP: i32 = 5i32; +pub const ESI: i32 = 6i32; +pub const EDI: i32 = 7i32; +pub const AX: i32 = 0i32; +pub const CX: i32 = 2i32; +pub const DX: i32 = 4i32; +pub const BX: i32 = 6i32; +pub const SP: i32 = 8i32; +pub const BP: i32 = 10i32; +pub const SI: i32 = 12i32; +pub const DI: i32 = 14i32; +pub const AL: i32 = 0i32; +pub const CL: i32 = 4i32; +pub const DL: i32 = 8i32; +pub const BL: i32 = 12i32; +pub const AH: i32 = 1i32; +pub const CH: i32 = 5i32; +pub const DH: i32 = 9i32; +pub const BH: i32 = 13i32; +pub const ES: i32 = 0i32; +pub const CS: i32 = 1i32; +pub const SS: i32 = 2i32; +pub const DS: i32 = 3i32; +pub const FS: i32 = 4i32; +pub const GS: i32 = 5i32; +pub const TR: i32 = 6i32; +pub const LDTR: i32 = 7i32; +pub const PAGE_TABLE_PRESENT_MASK: i32 = 1i32 << 0i32; +pub const PAGE_TABLE_RW_MASK: i32 = 1i32 << 1i32; +pub const PAGE_TABLE_USER_MASK: i32 = 1i32 << 2i32; +pub const PAGE_TABLE_ACCESSED_MASK: i32 = 1i32 << 5i32; +pub const PAGE_TABLE_DIRTY_MASK: i32 = 1i32 << 6i32; +pub const PAGE_TABLE_PSE_MASK: i32 = 1i32 << 7i32; +pub const PAGE_TABLE_GLOBAL_MASK: i32 = 1i32 << 8i32; +pub const MMAP_BLOCK_BITS: i32 = 17i32; +pub const MMAP_BLOCK_SIZE: i32 = 1i32 << MMAP_BLOCK_BITS; +pub const CR0_PE: i32 = 1i32; +pub const CR0_MP: i32 = 1i32 << 1i32; +pub const CR0_EM: i32 = 1i32 << 2i32; +pub const CR0_TS: i32 = 1i32 << 3i32; +pub const CR0_ET: i32 = 1i32 << 4i32; +pub const CR0_WP: i32 = 1i32 << 16i32; +pub const CR0_NW: i32 = 1i32 << 29i32; +pub const CR0_CD: i32 = 1i32 << 30i32; +pub const CR0_PG: i32 = 1i32 << 31i32; +pub const CR4_VME: i32 = 1i32; +pub const CR4_PVI: i32 = 1i32 << 1i32; +pub const CR4_TSD: i32 = 1i32 << 2i32; +pub const CR4_PSE: i32 = 1i32 << 4i32; +pub const CR4_DE: i32 = 1i32 << 3i32; +pub const CR4_PAE: i32 = 1i32 << 5i32; +pub const CR4_PGE: i32 = 1i32 << 7i32; +pub const IA32_SYSENTER_CS: i32 = 372i32; +pub const IA32_SYSENTER_ESP: i32 = 373i32; +pub const IA32_SYSENTER_EIP: i32 = 374i32; +pub const IA32_TIME_STAMP_COUNTER: i32 = 16i32; +pub const IA32_PLATFORM_ID: i32 = 23i32; +pub const IA32_APIC_BASE_MSR: i32 = 27i32; +pub const IA32_BIOS_SIGN_ID: i32 = 139i32; +pub const MSR_PLATFORM_INFO: i32 = 206i32; +pub const MSR_MISC_FEATURE_ENABLES: i32 = 320i32; +pub const IA32_MISC_ENABLE: i32 = 416i32; +pub const IA32_RTIT_CTL: i32 = 1392i32; +pub const MSR_SMI_COUNT: i32 = 52i32; +pub const IA32_MCG_CAP: i32 = 377i32; +pub const IA32_KERNEL_GS_BASE: i32 = 3221225729u32 as i32; +pub const MSR_PKG_C2_RESIDENCY: i32 = 1549i32; +pub const IA32_APIC_BASE_BSP: i32 = 1i32 << 8i32; +pub const IA32_APIC_BASE_EXTD: i32 = 1i32 << 10i32; +pub const IA32_APIC_BASE_EN: i32 = 1i32 << 11i32; +pub const APIC_ADDRESS: i32 = 4276092928u32 as i32; +pub const SEG_PREFIX_NONE: i32 = -1i32; +pub const SEG_PREFIX_ZERO: i32 = 7i32; +pub const PREFIX_MASK_REP: i32 = 24i32; +pub const PREFIX_REPZ: i32 = 8i32; +pub const PREFIX_REPNZ: i32 = 16i32; +pub const PREFIX_MASK_SEGMENT: i32 = 7i32; +pub const PREFIX_MASK_OPSIZE: i32 = 32i32; +pub const PREFIX_MASK_ADDRSIZE: i32 = 64i32; +pub const PREFIX_F2: i32 = PREFIX_REPNZ; +pub const PREFIX_F3: i32 = PREFIX_REPZ; +pub const PREFIX_66: i32 = PREFIX_MASK_OPSIZE; +pub const LOG_CPU: i32 = 2i32; +pub const A20_MASK: i32 = !(1i32 << 20i32); +pub const A20_MASK16: i32 = !(1i32 << 20i32 - 1i32); +pub const A20_MASK32: i32 = !(1i32 << 20i32 - 2i32); +pub const MXCSR_MASK: i32 = 65535i32 & !(1i32 << 6i32); +pub const VALID_TLB_ENTRY_MAX: i32 = 10000i32; +pub const TLB_VALID: i32 = 1i32 << 0i32; +pub const TLB_READONLY: i32 = 1i32 << 1i32; +pub const TLB_NO_USER: i32 = 1i32 << 2i32; +pub const TLB_IN_MAPPED_RANGE: i32 = 1i32 << 3i32; +pub const TLB_GLOBAL: i32 = 1i32 << 4i32; +pub const TLB_HAS_CODE: i32 = 1i32 << 5i32; +pub const CPU_EXCEPTION_DE: i32 = 0i32; +pub const CPU_EXCEPTION_DB: i32 = 1i32; +pub const CPU_EXCEPTION_NMI: i32 = 2i32; +pub const CPU_EXCEPTION_BP: i32 = 3i32; +pub const CPU_EXCEPTION_OF: i32 = 4i32; +pub const CPU_EXCEPTION_BR: i32 = 5i32; +pub const CPU_EXCEPTION_UD: i32 = 6i32; +pub const CPU_EXCEPTION_NM: i32 = 7i32; +pub const CPU_EXCEPTION_DF: i32 = 8i32; +pub const CPU_EXCEPTION_TS: i32 = 10i32; +pub const CPU_EXCEPTION_NP: i32 = 11i32; +pub const CPU_EXCEPTION_SS: i32 = 12i32; +pub const CPU_EXCEPTION_GP: i32 = 13i32; +pub const CPU_EXCEPTION_PF: i32 = 14i32; +pub const CPU_EXCEPTION_MF: i32 = 16i32; +pub const CPU_EXCEPTION_AC: i32 = 17i32; +pub const CPU_EXCEPTION_MC: i32 = 18i32; +pub const CPU_EXCEPTION_XM: i32 = 19i32; +pub const CPU_EXCEPTION_VE: i32 = 20i32; +pub const CHECK_TLB_INVARIANTS: bool = 0 != 0i32; +pub const DEBUG: bool = 0 != 1i32; +pub const LOOP_COUNTER: i32 = 20011i32; +pub const TSC_RATE: f64 = (50i32 * 1000i32) as f64; + +pub static mut jit_block_boundary: bool = 0 != 0i32; + +pub static mut must_not_fault: bool = 0 != 0i32; +pub static mut current_cpu_exception: i32 = -1i32; +pub static mut rdtsc_imprecision_offset: u64 = 0i32 as u64; +pub static mut rdtsc_last_value: u64 = 0i32 as u64; +pub static mut tsc_offset: u64 = 0i32 as u64; + +pub static mut valid_tlb_entries: [i32; 10000] = [0; 10000]; +pub static mut valid_tlb_entries_count: i32 = 0i32; //pub fn call_indirect1(f: fn(u16), x: u16) { f(x); } @@ -596,8 +459,6 @@ pub unsafe fn do_page_translation( return Ok(high); } #[no_mangle] -pub static mut CHECK_TLB_INVARIANTS: bool = unsafe { 0 != 0i32 }; -#[no_mangle] pub unsafe fn full_clear_tlb() -> () { profiler_stat_increment(S_FULL_CLEAR_TLB); c_comment!(("clear tlb including global pages")); @@ -691,10 +552,6 @@ pub unsafe fn trigger_pagefault(mut write: bool, mut user: bool, mut present: bo //profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); } #[no_mangle] -pub static mut must_not_fault: bool = unsafe { 0 != 0i32 }; -#[no_mangle] -pub static mut DEBUG: bool = unsafe { 0 != 1i32 }; -#[no_mangle] pub unsafe fn translate_address_write(mut address: i32) -> Result { let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); @@ -991,8 +848,6 @@ unsafe fn jit_run_interpreted(mut phys_addr: i32) -> () { #[no_mangle] pub unsafe fn clear_current_cpu_exception() -> () { current_cpu_exception = -1i32; } #[no_mangle] -pub static mut current_cpu_exception: i32 = unsafe { -1i32 }; -#[no_mangle] pub unsafe fn pack_current_state_flags() -> cached_state_flags { return ((*is_32 as i32) << 0i32 | (*stack_size_32 as i32) << 1i32 @@ -1029,8 +884,6 @@ pub unsafe fn do_many_cycles_native() -> () { cycle_internal(); } } -#[no_mangle] -pub static mut LOOP_COUNTER: i32 = unsafe { 20011i32 }; //#[no_mangle] //pub unsafe fn raise_exception(mut interrupt_nr: i32) -> () { // if DEBUG { @@ -1697,14 +1550,6 @@ pub unsafe fn read_tsc() -> u64 { }; } #[no_mangle] -pub static mut rdtsc_imprecision_offset: u64 = unsafe { 0i32 as u64 }; -#[no_mangle] -pub static mut rdtsc_last_value: u64 = unsafe { 0i32 as u64 }; -#[no_mangle] -pub static mut tsc_offset: u64 = unsafe { 0i32 as u64 }; -#[no_mangle] -pub static mut TSC_RATE: f64 = unsafe { (50i32 * 1000i32) as f64 }; -#[no_mangle] pub unsafe fn vm86_mode() -> bool { return *flags & FLAG_VM == FLAG_VM; } #[no_mangle] pub unsafe fn getiopl() -> i32 { return *flags >> 12i32 & 3i32; } diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 0d2a825b..b37b5fc7 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -35,26 +35,29 @@ pub union f32_int { f32_0: f32, } -#[no_mangle] -pub static mut M_LOG2E: f64 = unsafe { 1.4426950408889634f64 }; -#[no_mangle] -pub static mut M_LN2: f64 = unsafe { 0.6931471805599453f64 }; -#[no_mangle] -pub static mut M_LN10: f64 = unsafe { 2.302585092994046f64 }; -#[no_mangle] -pub static mut M_PI: f64 = unsafe { 3.141592653589793f64 }; -#[no_mangle] -pub static mut FPU_C0: i32 = unsafe { 256i32 }; -#[no_mangle] -pub static mut FPU_C1: i32 = unsafe { 512i32 }; -#[no_mangle] -pub static mut FPU_C2: i32 = unsafe { 1024i32 }; -#[no_mangle] -pub static mut FPU_C3: i32 = unsafe { 16384i32 }; -#[no_mangle] -pub static mut FPU_RESULT_FLAGS: i32 = unsafe { FPU_C0 | FPU_C1 | FPU_C2 | FPU_C3 }; -#[no_mangle] -pub static mut FPU_STACK_TOP: i32 = unsafe { 14336i32 }; +pub const M_LOG2E: f64 = 1.4426950408889634f64; +pub const M_LN2: f64 = 0.6931471805599453f64; +pub const M_LN10: f64 = 2.302585092994046f64; +pub const M_PI: f64 = 3.141592653589793f64; +const FPU_C0: i32 = 256i32; +pub const FPU_C1: i32 = 512i32; +const FPU_C2: i32 = 1024i32; +const FPU_C3: i32 = 16384i32; +const FPU_RESULT_FLAGS: i32 = FPU_C0 | FPU_C1 | FPU_C2 | FPU_C3; +const FPU_STACK_TOP: i32 = 14336i32; +const INDEFINITE_NAN: f64 = ::std::f64::NAN; +const FPU_EX_I: i32 = 1i32 << 0i32; +const FPU_EX_SF: i32 = 1i32 << 6i32; +const TWO_POW_63: f64 = 9223372036854775808u64 as f64; +const FPU_PC: i32 = 3i32 << 8i32; +const FPU_RC: i32 = 3i32 << 10i32; +const FPU_IF: i32 = 1i32 << 12i32; +const FPU_EX_P: i32 = 1i32 << 5i32; +const FPU_EX_U: i32 = 1i32 << 4i32; +const FPU_EX_O: i32 = 1i32 << 3i32; +const FPU_EX_Z: i32 = 1i32 << 2i32; +const FPU_EX_D: i32 = 1i32 << 1i32; + #[no_mangle] pub unsafe fn fpu_get_st0() -> f64 { if 0 != *fpu_stack_empty >> *fpu_stack_ptr & 1i32 { @@ -67,17 +70,11 @@ pub unsafe fn fpu_get_st0() -> f64 { }; } #[no_mangle] -pub static mut INDEFINITE_NAN: f64 = unsafe { ::std::f32::NAN as f64 }; -#[no_mangle] pub unsafe fn fpu_stack_fault() -> () { c_comment!(("TODO: Interrupt")); *fpu_status_word |= FPU_EX_SF | FPU_EX_I; } #[no_mangle] -pub static mut FPU_EX_I: i32 = unsafe { 1i32 << 0i32 }; -#[no_mangle] -pub static mut FPU_EX_SF: i32 = unsafe { 1i32 << 6i32 }; -#[no_mangle] pub unsafe fn fpu_get_sti(mut i: i32) -> f64 { dbg_assert!(i >= 0i32 && i < 8i32); i = ((i as u32).wrapping_add(*fpu_stack_ptr) & 7i32 as u32) as i32; @@ -325,8 +322,6 @@ pub unsafe fn fpu_fistm64p(mut addr: i32) -> () { fpu_pop(); } #[no_mangle] -pub static mut TWO_POW_63: f64 = unsafe { 9223372036854775808u64 as f64 }; -#[no_mangle] pub unsafe fn fpu_fldcw(mut addr: i32) -> () { let mut word: i32 = return_on_pagefault!(safe_read16(addr)); *fpu_control_word = word; @@ -677,19 +672,3 @@ pub unsafe fn fpu_fxtract() -> () { pub unsafe fn fwait() -> () { c_comment!(("NOP unless FPU instructions run in parallel with CPU instructions")); } -#[no_mangle] -pub static mut FPU_PC: i32 = unsafe { 3i32 << 8i32 }; -#[no_mangle] -pub static mut FPU_RC: i32 = unsafe { 3i32 << 10i32 }; -#[no_mangle] -pub static mut FPU_IF: i32 = unsafe { 1i32 << 12i32 }; -#[no_mangle] -pub static mut FPU_EX_P: i32 = unsafe { 1i32 << 5i32 }; -#[no_mangle] -pub static mut FPU_EX_U: i32 = unsafe { 1i32 << 4i32 }; -#[no_mangle] -pub static mut FPU_EX_O: i32 = unsafe { 1i32 << 3i32 }; -#[no_mangle] -pub static mut FPU_EX_Z: i32 = unsafe { 1i32 << 2i32 }; -#[no_mangle] -pub static mut FPU_EX_D: i32 = unsafe { 1i32 << 1i32 }; diff --git a/src/rust/cpu2/imports.rs b/src/rust/cpu2/imports.rs index 28399930..7131df0e 100644 --- a/src/rust/cpu2/imports.rs +++ b/src/rust/cpu2/imports.rs @@ -5,11 +5,11 @@ pub fn call_indirect1(f: fn(u16), x: u16) { f(x); } extern "C" { #[no_mangle] - static mut mem8: *mut u8; + pub static mut mem8: *mut u8; #[no_mangle] - static mut mem16: *mut u16; + pub static mut mem16: *mut u16; #[no_mangle] - static mut mem32s: *mut i32; + pub static mut mem32s: *mut i32; } #[no_mangle] diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index fea92663..bf1de372 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -63,6 +63,9 @@ use cpu2::misc_instr::{ }; use cpu2::sse_instr::*; +pub static mut apic_enabled: bool = false; +const ENABLE_ACPI: bool = false; + pub fn convert_f64_to_i32(x: f64) -> i32 { x as i32 } #[no_mangle] @@ -1106,8 +1109,6 @@ pub unsafe fn instr_0F30() -> () { }; } #[no_mangle] -pub static mut apic_enabled: bool = unsafe { 0 != 0i32 }; -#[no_mangle] pub unsafe fn instr_0F31() -> () { c_comment!(("rdtsc - read timestamp counter")); if 0 == *cpl.offset(0isize) || 0 == *cr.offset(4isize) & CR4_TSD { @@ -1192,8 +1193,6 @@ pub unsafe fn instr_0F32() -> () { }; } #[no_mangle] -pub static mut ENABLE_ACPI: bool = unsafe { 0 != 1i32 }; -#[no_mangle] pub unsafe fn instr_0F33() -> () { c_comment!(("rdpmc")); undefined_instruction(); @@ -5651,8 +5650,6 @@ pub unsafe fn instr_0FFF() -> () { trigger_ud(); } #[no_mangle] -pub static mut CPU_LOG_VERBOSE: bool = unsafe { 0 != 0i32 }; -#[no_mangle] pub unsafe fn instr_F30F16() -> () { unimplemented_sse(); } #[no_mangle] pub unsafe fn instr_0F19_reg(mut r1: i32, mut r2: i32) -> () {} diff --git a/src/rust/cpu2/memory.rs b/src/rust/cpu2/memory.rs index 8432de41..7a6d22dd 100644 --- a/src/rust/cpu2/memory.rs +++ b/src/rust/cpu2/memory.rs @@ -33,6 +33,8 @@ extern "C" { use cpu2::cpu::*; use cpu2::global_pointers::*; +const USE_A20: bool = false; + #[no_mangle] pub unsafe fn in_mapped_range(mut addr: u32) -> bool { return addr >= 655360i32 as u32 && addr < 786432i32 as u32 || addr >= *memory_size; @@ -51,8 +53,6 @@ pub unsafe fn read8(mut addr: u32) -> i32 { }; } #[no_mangle] -pub static mut USE_A20: bool = unsafe { 0 != 0i32 }; -#[no_mangle] pub unsafe fn read16(mut addr: u32) -> i32 { if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK as u32 diff --git a/src/rust/cpu2/string.rs b/src/rust/cpu2/string.rs index 693dbf20..7acc7469 100644 --- a/src/rust/cpu2/string.rs +++ b/src/rust/cpu2/string.rs @@ -33,6 +33,8 @@ use cpu2::memory::{ read8, read_aligned16, read_aligned32, write8, write_aligned16, write_aligned32, }; +const MAX_COUNT_PER_CYCLE: i32 = 4096i32; + #[no_mangle] pub unsafe fn string_get_cycle_count(mut size: i32, mut address: i32) -> i32 { dbg_assert!(0 != size && size <= 4i32 && size >= -4i32); @@ -179,8 +181,6 @@ pub unsafe fn movsw_rep() -> () { }; } #[no_mangle] -pub static mut MAX_COUNT_PER_CYCLE: i32 = unsafe { 4096i32 }; -#[no_mangle] pub unsafe fn movsw_no_rep() -> () { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); From 1b9ad3ac60fb7ff06c7ccf6775e6935787e7bb5f Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 20 Aug 2018 12:57:27 -0500 Subject: [PATCH 1200/2137] Remove useless #[no_mangle] --- src/rust/cpu2/cpu.rs | 189 +++++++++++++++++++++++------------------ src/rust/cpu2/modrm.rs | 11 +-- 2 files changed, 107 insertions(+), 93 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 6ad6bb90..35052a58 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -249,12 +249,12 @@ pub static mut valid_tlb_entries_count: i32 = 0i32; //pub fn call_indirect1(f: fn(u16), x: u16) { f(x); } -#[no_mangle] pub unsafe fn after_block_boundary() -> () { jit_block_boundary = 0 != 1i32; } -#[no_mangle] + pub unsafe fn same_page(mut addr1: i32, mut addr2: i32) -> bool { return addr1 & !4095i32 == addr2 & !4095i32; } + #[no_mangle] pub unsafe fn get_eflags() -> i32 { return *flags & !FLAGS_ALL @@ -265,7 +265,7 @@ pub unsafe fn get_eflags() -> i32 { | (getsf() as i32) << 7i32 | (getof() as i32) << 11i32; } -#[no_mangle] + pub unsafe fn translate_address_read(mut address: i32) -> Result { let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); @@ -277,7 +277,7 @@ pub unsafe fn translate_address_read(mut address: i32) -> Result { return Ok((do_page_translation(address, 0 != 0i32, user)? | address & 4095i32) as u32); }; } -#[no_mangle] + pub unsafe fn do_page_translation( mut addr: i32, mut for_writing: bool, @@ -458,6 +458,7 @@ pub unsafe fn do_page_translation( *tlb_data.offset(page as isize) = high ^ page << 12i32 | info_bits; return Ok(high); } + #[no_mangle] pub unsafe fn full_clear_tlb() -> () { profiler_stat_increment(S_FULL_CLEAR_TLB); @@ -479,6 +480,7 @@ pub unsafe fn full_clear_tlb() -> () { } }; } + #[no_mangle] pub unsafe fn clear_tlb() -> () { profiler_stat_increment(S_CLEAR_TLB); @@ -513,7 +515,7 @@ pub unsafe fn clear_tlb() -> () { } }; } -#[no_mangle] + pub unsafe fn trigger_pagefault(mut write: bool, mut user: bool, mut present: bool) -> () { if 0 != 0i32 * 0i32 { dbg_log_c!( @@ -551,7 +553,7 @@ pub unsafe fn trigger_pagefault(mut write: bool, mut user: bool, mut present: bo ); //profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); } -#[no_mangle] + pub unsafe fn translate_address_write(mut address: i32) -> Result { let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); @@ -565,6 +567,7 @@ pub unsafe fn translate_address_write(mut address: i32) -> Result { return Ok((do_page_translation(address, 0 != 1i32, user)? | address & 4095i32) as u32); }; } + #[no_mangle] pub unsafe fn tlb_set_has_code(mut physical_page: u32, mut has_code: bool) -> () { dbg_assert!(physical_page < (1i32 << 20i32) as u32); @@ -587,6 +590,7 @@ pub unsafe fn tlb_set_has_code(mut physical_page: u32, mut has_code: bool) -> () } check_tlb_invariants(); } + #[no_mangle] pub unsafe fn check_tlb_invariants() -> () { let mut physical_page: u32 = 0; @@ -608,7 +612,7 @@ pub unsafe fn check_tlb_invariants() -> () { return; }; } -#[no_mangle] + pub unsafe fn writable_or_pagefault(mut addr: i32, mut size: i32) -> Result<(), ()> { dbg_assert!(size < 4096i32); dbg_assert!(size > 0i32); @@ -635,7 +639,7 @@ pub unsafe fn writable_or_pagefault(mut addr: i32, mut size: i32) -> Result<(), return Ok(()); }; } -#[no_mangle] + pub unsafe fn read_imm8() -> Result { let mut eip: i32 = *instruction_pointer; if 0 != eip & !4095i32 ^ *last_virt_eip { @@ -647,9 +651,9 @@ pub unsafe fn read_imm8() -> Result { *instruction_pointer = eip + 1i32; return Ok(data8); } -#[no_mangle] + pub unsafe fn read_imm8s() -> Result { return Ok(read_imm8()? << 24i32 >> 24i32); } -#[no_mangle] + pub unsafe fn read_imm16() -> Result { c_comment!(("Two checks in one comparison:")); c_comment!(("1. Did the high 20 bits of eip change")); @@ -663,7 +667,7 @@ pub unsafe fn read_imm16() -> Result { return Ok(data16); }; } -#[no_mangle] + pub unsafe fn read_imm32s() -> Result { c_comment!(("Analogue to the above comment")); if (*instruction_pointer ^ *last_virt_eip) as u32 > 4092i32 as u32 { @@ -675,15 +679,16 @@ pub unsafe fn read_imm32s() -> Result { return Ok(data32); }; } -#[no_mangle] + pub unsafe fn is_osize_32() -> bool { return *is_32 as i32 != (*prefixes as i32 & PREFIX_MASK_OPSIZE == PREFIX_MASK_OPSIZE) as i32; } -#[no_mangle] + pub unsafe fn is_asize_32() -> bool { return *is_32 as i32 != (*prefixes as i32 & PREFIX_MASK_ADDRSIZE == PREFIX_MASK_ADDRSIZE) as i32; } + #[no_mangle] pub unsafe fn get_seg(mut segment: i32) -> i32 { dbg_assert!(segment >= 0i32 && segment < 8i32); @@ -698,12 +703,12 @@ pub unsafe fn get_seg(mut segment: i32) -> i32 { } return *segment_offsets.offset(segment as isize); } -#[no_mangle] + pub unsafe fn trigger_gp(mut code: i32) -> () { *instruction_pointer = *previous_ip; raise_exception_with_code(CPU_EXCEPTION_GP, code); } -#[no_mangle] + pub unsafe fn raise_exception_with_code(mut interrupt_nr: i32, mut error_code: i32) -> () { if DEBUG { if must_not_fault { @@ -724,11 +729,11 @@ pub unsafe fn raise_exception_with_code(mut interrupt_nr: i32, mut error_code: i call_interrupt_vector(interrupt_nr, 0 != 0i32, 0 != 1i32, error_code); assert!(false); } -#[no_mangle] + pub unsafe fn get_seg_cs() -> i32 { return *segment_offsets.offset(CS as isize); } -#[no_mangle] + pub unsafe fn get_seg_ss() -> i32 { return *segment_offsets.offset(SS as isize); } -#[no_mangle] + pub unsafe fn get_seg_prefix(mut default_segment: i32) -> i32 { let mut prefix: i32 = *prefixes as i32 & PREFIX_MASK_SEGMENT; if 0 != prefix { @@ -743,13 +748,13 @@ pub unsafe fn get_seg_prefix(mut default_segment: i32) -> i32 { return get_seg(default_segment); }; } -#[no_mangle] + pub unsafe fn get_seg_prefix_ds(mut offset: i32) -> i32 { return get_seg_prefix(DS) + offset; } -#[no_mangle] + pub unsafe fn get_seg_prefix_ss(mut offset: i32) -> i32 { return get_seg_prefix(SS) + offset; } -#[no_mangle] + pub unsafe fn get_seg_prefix_cs(mut offset: i32) -> i32 { return get_seg_prefix(CS) + offset; } -#[no_mangle] + pub unsafe fn modrm_resolve(mut modrm_byte: i32) -> Result { if is_asize_32() { resolve_modrm32(modrm_byte) @@ -814,7 +819,7 @@ pub unsafe fn cycle_internal() -> () { run_instruction(opcode | (*is_32 as i32) << 8); } } -#[no_mangle] + pub unsafe fn get_phys_eip() -> Result { let mut eip: i32 = *instruction_pointer; if 0 != eip & !4095i32 ^ *last_virt_eip { @@ -845,8 +850,9 @@ unsafe fn jit_run_interpreted(mut phys_addr: i32) -> () { clear_current_cpu_exception(); } } -#[no_mangle] + pub unsafe fn clear_current_cpu_exception() -> () { current_cpu_exception = -1i32; } + #[no_mangle] pub unsafe fn pack_current_state_flags() -> cached_state_flags { return ((*is_32 as i32) << 0i32 @@ -854,26 +860,27 @@ pub unsafe fn pack_current_state_flags() -> cached_state_flags { | ((*cpl as i32 == 3i32) as i32) << 2i32 | (has_flat_segmentation() as i32) << 3i32) as cached_state_flags; } -#[no_mangle] + pub unsafe fn has_flat_segmentation() -> bool { c_comment!(("ss can\'t be null")); return *segment_offsets.offset(SS as isize) == 0i32 && !*segment_is_null.offset(DS as isize) && *segment_offsets.offset(DS as isize) == 0i32; } -#[no_mangle] + pub unsafe fn run_prefix_instruction() -> () { run_instruction(return_on_pagefault!(read_imm8()) | (is_osize_32() as i32) << 8i32); } -#[no_mangle] + pub unsafe fn clear_prefixes() -> () { *prefixes = 0i32 as u8; } -#[no_mangle] + pub unsafe fn segment_prefix_op(mut seg: i32) -> () { dbg_assert!(seg <= 5i32); *prefixes = (*prefixes as i32 | seg + 1i32) as u8; run_prefix_instruction(); *prefixes = 0i32 as u8; } + #[no_mangle] pub unsafe fn do_many_cycles_native() -> () { profiler_stat_increment(S_DO_MANY_CYCLES); @@ -901,7 +908,7 @@ pub unsafe fn do_many_cycles_native() -> () { // call_interrupt_vector(interrupt_nr, 0 != 0i32, 0 != 0i32, 0i32); // throw_cpu_exception(); //} -#[no_mangle] + pub unsafe fn trigger_de() -> () { if DEBUG { if cpu_exception_hook(CPU_EXCEPTION_DE) { @@ -912,8 +919,9 @@ pub unsafe fn trigger_de() -> () { call_interrupt_vector(CPU_EXCEPTION_DE, 0 != 0i32, 0 != 0i32, 0i32); set_current_cpu_exception(CPU_EXCEPTION_DE); } -#[no_mangle] + pub unsafe fn set_current_cpu_exception(mut n: i32) -> () { current_cpu_exception = n; } + #[no_mangle] pub unsafe fn trigger_ud() -> () { dbg_log_c!("#ud"); @@ -927,7 +935,7 @@ pub unsafe fn trigger_ud() -> () { call_interrupt_vector(CPU_EXCEPTION_UD, 0 != 0i32, 0 != 0i32, 0i32); set_current_cpu_exception(CPU_EXCEPTION_UD); } -#[no_mangle] + pub unsafe fn trigger_nm() -> () { if DEBUG { if cpu_exception_hook(CPU_EXCEPTION_NM) { @@ -938,6 +946,7 @@ pub unsafe fn trigger_nm() -> () { call_interrupt_vector(CPU_EXCEPTION_NM, 0 != 0i32, 0 != 0i32, 0i32); set_current_cpu_exception(CPU_EXCEPTION_NM); } + #[no_mangle] pub unsafe fn trigger_gp_non_raising(mut code: i32) -> () { if DEBUG { @@ -949,13 +958,13 @@ pub unsafe fn trigger_gp_non_raising(mut code: i32) -> () { call_interrupt_vector(CPU_EXCEPTION_GP, 0 != 0i32, 0 != 1i32, code); set_current_cpu_exception(CPU_EXCEPTION_GP); } -#[no_mangle] + pub unsafe fn virt_boundary_read16(mut low: i32, mut high: i32) -> i32 { dbg_assert!(low & 4095i32 == 4095i32); dbg_assert!(high & 4095i32 == 0i32); return read8(low as u32) | read8(high as u32) << 8i32; } -#[no_mangle] + pub unsafe fn virt_boundary_read32s(mut low: i32, mut high: i32) -> i32 { dbg_assert!(low & 4095i32 >= 4093i32); dbg_assert!(high - 3i32 & 4095i32 == low & 4095i32); @@ -976,14 +985,14 @@ pub unsafe fn virt_boundary_read32s(mut low: i32, mut high: i32) -> i32 { } return read8(low as u32) | mid << 8i32 | read8(high as u32) << 24i32; } -#[no_mangle] + pub unsafe fn virt_boundary_write16(mut low: i32, mut high: i32, mut value: i32) -> () { dbg_assert!(low & 4095i32 == 4095i32); dbg_assert!(high & 4095i32 == 0i32); write8(low as u32, value); write8(high as u32, value >> 8i32); } -#[no_mangle] + pub unsafe fn virt_boundary_write32(mut low: i32, mut high: i32, mut value: i32) -> () { dbg_assert!(low & 4095i32 >= 4093i32); dbg_assert!(high - 3i32 & 4095i32 == low & 4095i32); @@ -1007,12 +1016,12 @@ pub unsafe fn virt_boundary_write32(mut low: i32, mut high: i32, mut value: i32) } write8(high as u32, value >> 24i32); } -#[no_mangle] + pub unsafe fn safe_read8(mut addr: i32) -> Result { assert_no_cpu_exception(); return Ok(read8(translate_address_read(addr)?)); } -#[no_mangle] + pub unsafe fn assert_no_cpu_exception() -> () { return; if current_cpu_exception != -1i32 { @@ -1021,7 +1030,7 @@ pub unsafe fn assert_no_cpu_exception() -> () { dbg_assert!(0 != 0i32); }; } -#[no_mangle] + pub unsafe fn safe_read16(mut address: i32) -> Result { let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); @@ -1037,7 +1046,7 @@ pub unsafe fn safe_read16(mut address: i32) -> Result { return Ok(safe_read16_slow(address)?); }; } -#[no_mangle] + pub unsafe fn safe_read16_slow(mut addr: i32) -> Result { assert_no_cpu_exception(); if addr & 4095i32 == 4095i32 { @@ -1047,7 +1056,7 @@ pub unsafe fn safe_read16_slow(mut addr: i32) -> Result { return Ok(read16(translate_address_read(addr)?)); }; } -#[no_mangle] + pub unsafe fn safe_read32s(mut address: i32) -> Result { assert_no_cpu_exception(); let mut base: i32 = (address as u32 >> 12i32) as i32; @@ -1084,7 +1093,7 @@ pub unsafe fn safe_read32s(mut address: i32) -> Result { return safe_read32s_slow(address); }; } -#[no_mangle] + pub unsafe fn safe_read32s_slow(mut addr: i32) -> Result { if addr & 4095i32 >= 4093i32 { return Ok(safe_read16(addr)? | safe_read16(addr + 2i32)? << 16i32); @@ -1124,7 +1133,6 @@ pub unsafe fn safe_read32s_slow_jit(addr: i32) -> i32 { } } -#[no_mangle] pub unsafe fn safe_read64s(mut addr: i32) -> Result { let mut addr_phys: i32 = 0; assert_no_cpu_exception(); @@ -1139,7 +1147,7 @@ pub unsafe fn safe_read64s(mut addr: i32) -> Result { } Ok(x) } -#[no_mangle] + pub unsafe fn safe_read128s(mut addr: i32) -> Result { let mut addr_phys: i32 = 0; assert_no_cpu_exception(); @@ -1154,13 +1162,13 @@ pub unsafe fn safe_read128s(mut addr: i32) -> Result { } Ok(x) } -#[no_mangle] + pub unsafe fn safe_write8(mut addr: i32, mut value: i32) -> Result<(), ()> { assert_no_cpu_exception(); write8(translate_address_write(addr)?, value); Ok(()) } -#[no_mangle] + pub unsafe fn safe_write16(mut address: i32, mut value: i32) -> Result<(), ()> { let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); @@ -1180,7 +1188,7 @@ pub unsafe fn safe_write16(mut address: i32, mut value: i32) -> Result<(), ()> { }; Ok(()) } -#[no_mangle] + pub unsafe fn safe_write16_slow(mut addr: i32, mut value: i32) -> Result<(), ()> { assert_no_cpu_exception(); let mut phys_low: i32 = translate_address_write(addr)? as i32; @@ -1196,7 +1204,7 @@ pub unsafe fn safe_write16_slow(mut addr: i32, mut value: i32) -> Result<(), ()> }; Ok(()) } -#[no_mangle] + pub unsafe fn safe_write32(mut address: i32, mut value: i32) -> Result<(), ()> { assert_no_cpu_exception(); let mut base: i32 = (address as u32 >> 12i32) as i32; @@ -1247,7 +1255,7 @@ pub unsafe fn safe_write32(mut address: i32, mut value: i32) -> Result<(), ()> { }; Ok(()) } -#[no_mangle] + pub unsafe fn safe_write32_slow(mut addr: i32, mut value: i32) -> Result<(), ()> { let mut phys_low: i32 = translate_address_write(addr)? as i32; if addr & 4095i32 > 4096i32 - 4i32 { @@ -1279,7 +1287,6 @@ pub unsafe fn safe_write32_slow_jit(addr: i32, value: i32) { } } -#[no_mangle] pub unsafe fn safe_write64(mut addr: i32, mut value: i64) -> Result<(), ()> { assert_no_cpu_exception(); if addr & 4095i32 > 4096i32 - 8i32 { @@ -1293,7 +1300,7 @@ pub unsafe fn safe_write64(mut addr: i32, mut value: i64) -> Result<(), ()> { }; Ok(()) } -#[no_mangle] + pub unsafe fn safe_write128(mut addr: i32, mut value: reg128) -> Result<(), ()> { assert_no_cpu_exception(); if addr & 4095i32 > 4096i32 - 16i32 { @@ -1307,35 +1314,35 @@ pub unsafe fn safe_write128(mut addr: i32, mut value: reg128) -> Result<(), ()> }; Ok(()) } -#[no_mangle] + pub unsafe fn get_reg8_index(mut index: i32) -> i32 { return index << 2i32 & 12i32 | index >> 2i32 & 1i32; } -#[no_mangle] + pub unsafe fn read_reg8(mut index: i32) -> i32 { return *reg8.offset(get_reg8_index(index) as isize) as i32; } -#[no_mangle] + pub unsafe fn write_reg8(mut index: i32, mut value: i32) -> () { *reg8.offset(get_reg8_index(index) as isize) = value as u8; } -#[no_mangle] + pub unsafe fn get_reg16_index(mut index: i32) -> i32 { return index << 1i32; } -#[no_mangle] + pub unsafe fn read_reg16(mut index: i32) -> i32 { return *reg16.offset(get_reg16_index(index) as isize) as i32; } -#[no_mangle] + pub unsafe fn write_reg16(mut index: i32, mut value: i32) -> () { *reg16.offset(get_reg16_index(index) as isize) = value as u16; } -#[no_mangle] + pub unsafe fn read_reg32(mut index: i32) -> i32 { return *reg32s.offset(index as isize); } -#[no_mangle] + pub unsafe fn write_reg32(mut index: i32, mut value: i32) -> () { *reg32s.offset(index as isize) = value; } -#[no_mangle] + pub unsafe fn write_reg_osize(mut index: i32, mut value: i32) -> () { dbg_assert!(index >= 0i32 && index < 8i32); if is_osize_32() { @@ -1345,62 +1352,62 @@ pub unsafe fn write_reg_osize(mut index: i32, mut value: i32) -> () { write_reg16(index, value & 65535i32); }; } -#[no_mangle] + pub unsafe fn read_mmx32s(mut r: i32) -> i32 { return (*reg_mmx.offset(r as isize)).u32_0[0usize] as i32; } -#[no_mangle] + pub unsafe fn read_mmx64s(mut r: i32) -> reg64 { return *reg_mmx.offset(r as isize); } -#[no_mangle] + pub unsafe fn write_mmx64(mut r: i32, mut low: i32, mut high: i32) -> () { (*reg_mmx.offset(r as isize)).u32_0[0usize] = low as u32; (*reg_mmx.offset(r as isize)).u32_0[1usize] = high as u32; } -#[no_mangle] + pub unsafe fn write_mmx_reg64(mut r: i32, mut data: reg64) -> () { (*reg_mmx.offset(r as isize)).u64_0[0usize] = data.u64_0[0usize]; } -#[no_mangle] + pub unsafe fn read_xmm_f32(mut r: i32) -> f32 { return (*reg_xmm.offset(r as isize)).f32_0[0usize]; } -#[no_mangle] + pub unsafe fn read_xmm32(mut r: i32) -> i32 { return (*reg_xmm.offset(r as isize)).u32_0[0usize] as i32; } -#[no_mangle] + pub unsafe fn read_xmm64s(mut r: i32) -> reg64 { let mut x: reg64 = reg64 { i8_0: [0; 8] }; x.u64_0[0usize] = (*reg_xmm.offset(r as isize)).u64_0[0usize]; return x; } -#[no_mangle] + pub unsafe fn read_xmm128s(mut r: i32) -> reg128 { return *reg_xmm.offset(r as isize); } -#[no_mangle] + pub unsafe fn write_xmm_f32(mut r: i32, mut data: f32) -> () { (*reg_xmm.offset(r as isize)).f32_0[0usize] = data; } -#[no_mangle] + pub unsafe fn write_xmm32(mut r: i32, mut data: i32) -> () { (*reg_xmm.offset(r as isize)).i32_0[0usize] = data; } -#[no_mangle] + pub unsafe fn write_xmm64(mut r: i32, mut data: reg64) -> () { (*reg_xmm.offset(r as isize)).u64_0[0usize] = data.u64_0[0usize]; } -#[no_mangle] + pub unsafe fn write_xmm128(mut r: i32, mut i0: i32, mut i1: i32, mut i2: i32, mut i3: i32) -> () { let mut x: reg128 = reg128 { u32_0: [i0 as u32, i1 as u32, i2 as u32, i3 as u32], }; *reg_xmm.offset(r as isize) = x; } -#[no_mangle] + pub unsafe fn write_xmm_reg128(mut r: i32, mut data: reg128) -> () { (*reg_xmm.offset(r as isize)).u64_0[0usize] = data.u64_0[0usize]; (*reg_xmm.offset(r as isize)).u64_0[1usize] = data.u64_0[1usize]; } -#[no_mangle] + pub unsafe fn task_switch_test() -> bool { if 0 != *cr.offset(0isize) & (CR0_EM | CR0_TS) { trigger_nm(); @@ -1410,9 +1417,10 @@ pub unsafe fn task_switch_test() -> bool { return 0 != 1i32; }; } + #[no_mangle] pub unsafe fn task_switch_test_void() -> () { task_switch_test(); } -#[no_mangle] + pub unsafe fn task_switch_test_mmx() -> bool { if 0 != *cr & CR0_TS { trigger_nm(); @@ -1426,9 +1434,10 @@ pub unsafe fn task_switch_test_mmx() -> bool { return 0 != 1i32; }; } + #[no_mangle] pub unsafe fn task_switch_test_mmx_void() -> () { task_switch_test_mmx(); } -#[no_mangle] + pub unsafe fn read_moffs() -> Result { c_comment!(("read 2 or 4 byte from ip, depending on address size attribute")); if is_asize_32() { @@ -1438,12 +1447,13 @@ pub unsafe fn read_moffs() -> Result { read_imm16() } } + #[no_mangle] pub unsafe fn get_real_eip() -> i32 { c_comment!(("Returns the \'real\' instruction pointer, without segment offset")); return *instruction_pointer - get_seg_cs(); } -#[no_mangle] + pub unsafe fn get_stack_reg() -> i32 { if *stack_size_32 { return *reg32s.offset(ESP as isize); @@ -1452,6 +1462,7 @@ pub unsafe fn get_stack_reg() -> i32 { return *reg16.offset(SP as isize) as i32; }; } + #[no_mangle] pub unsafe fn set_stack_reg(mut value: i32) -> () { if *stack_size_32 { @@ -1461,7 +1472,7 @@ pub unsafe fn set_stack_reg(mut value: i32) -> () { *reg16.offset(SP as isize) = value as u16 }; } -#[no_mangle] + pub unsafe fn get_reg_asize(mut reg: i32) -> i32 { dbg_assert!(reg == ECX || reg == ESI || reg == EDI); let mut r: i32 = *reg32s.offset(reg as isize); @@ -1472,7 +1483,7 @@ pub unsafe fn get_reg_asize(mut reg: i32) -> i32 { return r & 65535i32; }; } -#[no_mangle] + pub unsafe fn set_ecx_asize(mut value: i32) -> () { if is_asize_32() { *reg32s.offset(ECX as isize) = value @@ -1481,7 +1492,7 @@ pub unsafe fn set_ecx_asize(mut value: i32) -> () { *reg16.offset(CX as isize) = value as u16 }; } -#[no_mangle] + pub unsafe fn add_reg_asize(mut reg: i32, mut value: i32) -> () { dbg_assert!(reg == ECX || reg == ESI || reg == EDI); if is_asize_32() { @@ -1493,7 +1504,7 @@ pub unsafe fn add_reg_asize(mut reg: i32, mut value: i32) -> () { *fresh3 = (*fresh3 as i32 + value) as u16 }; } -#[no_mangle] + pub unsafe fn decr_ecx_asize() -> i32 { return if 0 != is_asize_32() as i32 { let ref mut fresh4 = *reg32s.offset(ECX as isize); @@ -1506,13 +1517,14 @@ pub unsafe fn decr_ecx_asize() -> i32 { *fresh5 as i32 }; } + #[no_mangle] pub unsafe fn set_tsc(mut low: u32, mut high: u32) -> () { let mut new_value: u64 = low as u64 | (high as u64) << 32i32; let mut current_value: u64 = read_tsc(); tsc_offset = current_value.wrapping_sub(new_value); } -#[no_mangle] + pub unsafe fn read_tsc() -> u64 { let mut n: f64 = microtick() * TSC_RATE; let mut value: u64 = (n as u64).wrapping_sub(tsc_offset); @@ -1549,10 +1561,13 @@ pub unsafe fn read_tsc() -> u64 { return rdtsc_last_value.wrapping_add(rdtsc_imprecision_offset); }; } + #[no_mangle] pub unsafe fn vm86_mode() -> bool { return *flags & FLAG_VM == FLAG_VM; } + #[no_mangle] pub unsafe fn getiopl() -> i32 { return *flags >> 12i32 & 3i32; } + #[no_mangle] pub unsafe fn get_opstats_buffer(mut index: i32) -> i32 { dbg_assert!(index >= 0i32 && index < 512i32); @@ -1563,7 +1578,7 @@ pub unsafe fn get_opstats_buffer(mut index: i32) -> i32 { return *opstats_buffer_0f.offset((index - 256i32) as isize) as i32; }; } -#[no_mangle] + pub unsafe fn invlpg(mut addr: i32) -> () { let mut page: i32 = (addr as u32 >> 12i32) as i32; c_comment!(("Note: Doesn\'t remove this page from valid_tlb_entries: This isn\'t")); @@ -1574,6 +1589,7 @@ pub unsafe fn invlpg(mut addr: i32) -> () { *last_virt_eip = -1i32; *last_virt_esp = -1i32; } + #[no_mangle] pub unsafe fn update_eflags(mut new_flags: i32) -> () { let mut dont_update: i32 = FLAG_RF | FLAG_VM | FLAG_VIP | FLAG_VIF; @@ -1603,6 +1619,7 @@ pub unsafe fn update_eflags(mut new_flags: i32) -> () { *flags = (new_flags ^ (*flags ^ new_flags) & dont_update) & clear | FLAGS_DEFAULT; *flags_changed = 0i32; } + #[no_mangle] pub unsafe fn get_valid_tlb_entries_count() -> i32 { let mut result: i32 = 0i32; @@ -1617,6 +1634,7 @@ pub unsafe fn get_valid_tlb_entries_count() -> i32 { } return result; } + #[no_mangle] pub unsafe fn get_valid_global_tlb_entries_count() -> i32 { let mut result: i32 = 0i32; @@ -1631,7 +1649,7 @@ pub unsafe fn get_valid_global_tlb_entries_count() -> i32 { } return result; } -#[no_mangle] + pub unsafe fn translate_address_system_read(mut address: i32) -> Result { let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); @@ -1642,7 +1660,7 @@ pub unsafe fn translate_address_system_read(mut address: i32) -> Result return Ok((do_page_translation(address, 0 != 0i32, 0 != 0i32)? | address & 4095i32) as u32); }; } -#[no_mangle] + pub unsafe fn translate_address_system_write(mut address: i32) -> Result { let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); @@ -1653,6 +1671,7 @@ pub unsafe fn translate_address_system_write(mut address: i32) -> Result () { if DEBUG { @@ -1664,6 +1683,7 @@ pub unsafe fn trigger_np(mut code: i32) -> () { call_interrupt_vector(CPU_EXCEPTION_NP, 0 != 0i32, 0 != 1i32, code); set_current_cpu_exception(CPU_EXCEPTION_NP); } + #[no_mangle] pub unsafe fn trigger_ss(mut code: i32) -> () { if DEBUG { @@ -1675,5 +1695,6 @@ pub unsafe fn trigger_ss(mut code: i32) -> () { call_interrupt_vector(CPU_EXCEPTION_SS, 0 != 0i32, 0 != 1i32, code); set_current_cpu_exception(CPU_EXCEPTION_SS); } + #[no_mangle] pub unsafe fn store_current_tsc() -> () { *current_tsc = read_tsc(); } diff --git a/src/rust/cpu2/modrm.rs b/src/rust/cpu2/modrm.rs index 064be203..f9b5188e 100644 --- a/src/rust/cpu2/modrm.rs +++ b/src/rust/cpu2/modrm.rs @@ -10,7 +10,6 @@ use cpu2::cpu::*; use cpu2::global_pointers::*; -#[no_mangle] pub unsafe fn resolve_modrm16(mut modrm_byte: i32) -> Result { Ok(match modrm_byte { 0 | 8 | 16 | 24 | 32 | 40 | 48 | 56 => get_seg_prefix_ds( @@ -97,7 +96,7 @@ pub unsafe fn resolve_modrm16(mut modrm_byte: i32) -> Result { }, }) } -#[no_mangle] + pub unsafe fn resolve_modrm32_(mut modrm_byte: i32) -> Result { let mut r: u8 = (modrm_byte & 7i32) as u8; dbg_assert!(modrm_byte < 192i32); @@ -178,13 +177,7 @@ unsafe fn resolve_sib(mut mod_0: bool) -> Result { } Ok(get_seg_prefix(seg) + base + offset) } -#[no_mangle] -pub unsafe fn MODRM_ENTRY() -> i32 { return 0i32; } -#[no_mangle] -pub unsafe fn MODRM_ENTRY16() -> i32 { return 0i32; } -#[no_mangle] -pub unsafe fn MODRM_ENTRY32() -> i32 { return 0i32; } -#[no_mangle] + pub unsafe fn resolve_modrm32(mut modrm_byte: i32) -> Result { Ok(match modrm_byte { 0 | 8 | 16 | 24 | 32 | 40 | 48 | 56 => get_seg_prefix_ds(*reg32s.offset(EAX as isize)), From 9c9fc4e0e70a52f4206d5c6a78e2199be1182c9c Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 20 Aug 2018 13:06:55 -0500 Subject: [PATCH 1201/2137] Check imports --- src/cpu.js | 99 +++++++++++++++++++++++++++++------------------------- 1 file changed, 53 insertions(+), 46 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index 29ecfff2..59131eb8 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -286,66 +286,73 @@ CPU.prototype.create_jit_imports = function() CPU.prototype.wasm_patch = function(wm) { - this.getiopl = this.v86oxide.exports["getiopl"]; - this.vm86_mode = this.v86oxide.exports["vm86_mode"]; - this.get_eflags = this.v86oxide.exports["get_eflags"]; - this.update_eflags = this.v86oxide.exports["update_eflags"]; + const get_import = (name) => + { + const f = this.v86oxide.exports[name]; + console.assert(f, "Missing import: " + name); + return f; + }; - this.trigger_gp_non_raising = this.v86oxide.exports["trigger_gp_non_raising"]; - this.trigger_ud = this.v86oxide.exports["trigger_ud"]; - this.trigger_np = this.v86oxide.exports["trigger_np"]; - this.trigger_ss = this.v86oxide.exports["trigger_ss"]; + this.getiopl = get_import("getiopl"); + this.vm86_mode = get_import("vm86_mode"); + this.get_eflags = get_import("get_eflags"); + this.update_eflags = get_import("update_eflags"); - this.do_many_cycles_native = this.v86oxide.exports["do_many_cycles_native"]; - this.cycle_internal = this.v86oxide.exports["cycle_internal"]; + this.trigger_gp_non_raising = get_import("trigger_gp_non_raising"); + this.trigger_ud = get_import("trigger_ud"); + this.trigger_np = get_import("trigger_np"); + this.trigger_ss = get_import("trigger_ss"); - this.read8 = this.v86oxide.exports["read8"]; - this.read16 = this.v86oxide.exports["read16"]; - this.read32s = this.v86oxide.exports["read32s"]; - this.write8 = this.v86oxide.exports["write8"]; - this.write16 = this.v86oxide.exports["write16"]; - this.write32 = this.v86oxide.exports["write32"]; - this.in_mapped_range = this.v86oxide.exports["in_mapped_range"]; + this.do_many_cycles_native = get_import("do_many_cycles_native"); + this.cycle_internal = get_import("cycle_internal"); - this.push16 = this.v86oxide.exports["push16_js"]; - this.push32 = this.v86oxide.exports["push32_js"]; - this.pop16 = this.v86oxide.exports["pop16_js"]; - this.pop32s = this.v86oxide.exports["pop32s_js"]; + this.read8 = get_import("read8"); + this.read16 = get_import("read16"); + this.read32s = get_import("read32s"); + this.write8 = get_import("write8"); + this.write16 = get_import("write16"); + this.write32 = get_import("write32"); + this.in_mapped_range = get_import("in_mapped_range"); - this.set_stack_reg = this.v86oxide.exports["set_stack_reg"]; + this.push16 = get_import("push16_js"); + this.push32 = get_import("push32_js"); + this.pop16 = get_import("pop16_js"); + this.pop32s = get_import("pop32s_js"); - this.translate_address_read = this.v86oxide.exports["translate_address_read_js"]; - this.translate_address_system_read = this.v86oxide.exports["translate_address_system_read_js"]; - this.translate_address_system_write = this.v86oxide.exports["translate_address_system_write_js"]; + this.set_stack_reg = get_import("set_stack_reg"); - this.get_seg = this.v86oxide.exports["get_seg"]; - this.adjust_stack_reg = this.v86oxide.exports["adjust_stack_reg"]; - this.get_real_eip = this.v86oxide.exports["get_real_eip"]; - this.get_stack_pointer = this.v86oxide.exports["get_stack_pointer"]; + this.translate_address_read = get_import("translate_address_read_js"); + this.translate_address_system_read = get_import("translate_address_system_read_js"); + this.translate_address_system_write = get_import("translate_address_system_write_js"); - this.writable_or_pagefault = this.v86oxide.exports["writable_or_pagefault_js"]; - this.safe_write32 = this.v86oxide.exports["safe_write32_js"]; - this.safe_read32s = this.v86oxide.exports["safe_read32s_js"]; - this.safe_write16 = this.v86oxide.exports["safe_write16_js"]; - this.safe_read16 = this.v86oxide.exports["safe_read16_js"]; + this.get_seg = get_import("get_seg"); + this.adjust_stack_reg = get_import("adjust_stack_reg"); + this.get_real_eip = get_import("get_real_eip"); + this.get_stack_pointer = get_import("get_stack_pointer"); - this.clear_tlb = this.v86oxide.exports["clear_tlb"]; - this.full_clear_tlb = this.v86oxide.exports["full_clear_tlb"]; + this.writable_or_pagefault = get_import("writable_or_pagefault_js"); + this.safe_write32 = get_import("safe_write32_js"); + this.safe_read32s = get_import("safe_read32s_js"); + this.safe_write16 = get_import("safe_write16_js"); + this.safe_read16 = get_import("safe_read16_js"); - this.set_tsc = this.v86oxide.exports["set_tsc"]; - this.store_current_tsc = this.v86oxide.exports["store_current_tsc"]; + this.clear_tlb = get_import("clear_tlb"); + this.full_clear_tlb = get_import("full_clear_tlb"); - this.pack_current_state_flags = this.v86oxide.exports["pack_current_state_flags"]; + this.set_tsc = get_import("set_tsc"); + this.store_current_tsc = get_import("store_current_tsc"); - this.jit_force_generate_unsafe = this.v86oxide.exports["jit_force_generate_unsafe"]; - this.jit_empty_cache = this.v86oxide.exports["jit_empty_cache"]; - this.jit_dirty_cache = this.v86oxide.exports["jit_dirty_cache"]; - this.codegen_finalize_finished = this.v86oxide.exports["codegen_finalize_finished"]; + this.pack_current_state_flags = get_import("pack_current_state_flags"); - this.jit_get_op_ptr = this.v86oxide.exports["jit_get_op_ptr"]; - this.jit_get_op_len = this.v86oxide.exports["jit_get_op_len"]; + this.jit_force_generate_unsafe = get_import("jit_force_generate_unsafe"); + this.jit_empty_cache = get_import("jit_empty_cache"); + this.jit_dirty_cache = get_import("jit_dirty_cache"); + this.codegen_finalize_finished = get_import("codegen_finalize_finished"); - this.allocate_memory = this.v86oxide.exports["allocate_memory"]; + this.jit_get_op_ptr = get_import("jit_get_op_ptr"); + this.jit_get_op_len = get_import("jit_get_op_len"); + + this.allocate_memory = get_import("allocate_memory"); }; CPU.prototype.jit_force_generate = function(addr) From 1a96072840ed56181233e5ad9771f88b67dc7366 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 20 Aug 2018 13:08:16 -0500 Subject: [PATCH 1202/2137] Use u8 for page_fault --- src/rust/codegen.rs | 2 +- src/rust/wasmgen/wasm_util.rs | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index cd3f74e7..e7d577ac 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -356,7 +356,7 @@ fn gen_safe_write( builder .instruction_body - .load_aligned_i32(global_pointers::PAGE_FAULT); + .load_u8(global_pointers::PAGE_FAULT); builder.instruction_body.if_void(); builder.instruction_body.return_(); diff --git a/src/rust/wasmgen/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs index 532c191f..1ac91cb5 100644 --- a/src/rust/wasmgen/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -30,6 +30,7 @@ pub trait WasmBuf { fn load_unaligned_i32_from_stack(&mut self, byte_offset: u32); fn load_unaligned_u16_from_stack(&mut self, byte_offset: u32); fn load_aligned_i32_from_stack(&mut self, byte_offset: u32); + fn load_u8(&mut self, byte_offset: u32); fn store_unaligned_i32(&mut self, byte_offset: u32); fn store_unaligned_u16(&mut self, byte_offset: u32); fn shr_u32(&mut self); @@ -90,6 +91,13 @@ impl WasmBuf for Vec { self.load_aligned_i32_from_stack(0); } + fn load_u8(&mut self, addr: u32) { + self.push_i32(addr as i32); + self.push(op::OP_I32LOAD8U); + self.push(op::MEM_NO_ALIGN); + self.write_leb_u32(0); + } + fn store_aligned_u16(&mut self) { self.push(op::OP_I32STORE16); self.push(op::MEM_ALIGN16); From 8051db8ac69c7aadd0fd4fa7373669f1d50bf34b Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 20 Aug 2018 13:08:45 -0500 Subject: [PATCH 1203/2137] Access from allocated memory --- src/rust/codegen.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index e7d577ac..9f41dd81 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -739,12 +739,12 @@ fn gen_safe_read_write( BitSize::WORD => { builder .instruction_body - .load_unaligned_u16_from_stack(global_pointers::MEMORY); + .load_unaligned_u16_from_stack(unsafe { mem8 } as u32); }, BitSize::DWORD => { builder .instruction_body - .load_unaligned_i32_from_stack(global_pointers::MEMORY); + .load_unaligned_i32_from_stack(unsafe { mem8 } as u32); }, } @@ -758,12 +758,12 @@ fn gen_safe_read_write( BitSize::WORD => { builder .instruction_body - .store_unaligned_u16(global_pointers::MEMORY); + .store_unaligned_u16(unsafe { mem8 } as u32); }, BitSize::DWORD => { builder .instruction_body - .store_unaligned_i32(global_pointers::MEMORY); + .store_unaligned_i32(unsafe { mem8 } as u32); }, }; builder.free_local(phys_addr_local); From c36a179a5e1069e5134c8fc4adec0555af056537 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 20 Aug 2018 13:11:43 -0500 Subject: [PATCH 1204/2137] Remove block_boundary from push --- gen/x86_table.js | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 40291d1a..72134f02 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -51,15 +51,14 @@ const encodings = [ { opcode: 0x4E, nonfaulting: 1, os: 1, }, { opcode: 0x4F, nonfaulting: 1, os: 1, }, - // XXX: temporarily marked as block boundary until uses gen_push - { opcode: 0x50, custom: 1, os: 1, block_boundary: 1, }, - { opcode: 0x51, custom: 1, os: 1, block_boundary: 1, }, - { opcode: 0x52, custom: 1, os: 1, block_boundary: 1, }, - { opcode: 0x53, custom: 1, os: 1, block_boundary: 1, }, - { opcode: 0x54, custom: 1, os: 1, block_boundary: 1, }, - { opcode: 0x55, custom: 1, os: 1, block_boundary: 1, }, - { opcode: 0x56, custom: 1, os: 1, block_boundary: 1, }, - { opcode: 0x57, custom: 1, os: 1, block_boundary: 1, }, + { opcode: 0x50, custom: 1, os: 1 }, + { opcode: 0x51, custom: 1, os: 1 }, + { opcode: 0x52, custom: 1, os: 1 }, + { opcode: 0x53, custom: 1, os: 1 }, + { opcode: 0x54, custom: 1, os: 1 }, + { opcode: 0x55, custom: 1, os: 1 }, + { opcode: 0x56, custom: 1, os: 1 }, + { opcode: 0x57, custom: 1, os: 1 }, { opcode: 0x58, custom: 1, os: 1, }, { opcode: 0x59, custom: 1, os: 1, }, @@ -79,11 +78,9 @@ const encodings = [ { opcode: 0x66, prefix: 1, }, { opcode: 0x67, prefix: 1, }, - // XXX: Temporary block boundary - { opcode: 0x68, custom: 1, os: 1, imm1632: 1, block_boundary: 1 }, + { opcode: 0x68, custom: 1, os: 1, imm1632: 1 }, { opcode: 0x69, nonfaulting: 1, os: 1, e: 1, imm1632: 1, mask_flags: af, }, // zf? - // XXX: Temporary block boundary - { opcode: 0x6A, custom: 1, os: 1, imm8s: 1, block_boundary: 1, }, + { opcode: 0x6A, custom: 1, os: 1, imm8s: 1 }, { opcode: 0x6B, nonfaulting: 1, os: 1, e: 1, imm8s: 1, mask_flags: af, }, // zf? { opcode: 0x6C, block_boundary: 1, is_string: 1, skip: 1, }, // ins @@ -221,8 +218,7 @@ const encodings = [ { opcode: 0xE6, block_boundary: 1, imm8: 1, skip: 1, }, // out { opcode: 0xE7, block_boundary: 1, os: 1, imm8: 1, skip: 1, }, - //{ opcode: 0xE8, block_boundary: 1, jump_offset_imm: 1, os: 1, imm1632: 1, custom: 1, skip: 1, }, // call - { opcode: 0xE8, block_boundary: 1, os: 1, imm1632: 1, skip: 1, }, // call + { opcode: 0xE8, block_boundary: 1, jump_offset_imm: 1, os: 1, imm1632: 1, custom: 1, skip: 1, }, // call { opcode: 0xE9, block_boundary: 1, jump_offset_imm: 1, no_next_instruction: 1, os: 1, imm1632: 1, custom: 1, skip: 1, }, { opcode: 0xEA, block_boundary: 1, no_next_instruction: 1, os: 1, imm1632: 1, extra_imm16: 1, skip: 1, }, // jmpf { opcode: 0xEB, block_boundary: 1, jump_offset_imm: 1, no_next_instruction: 1, os: 1, imm8s: 1, custom: 1, skip: 1, }, From 5727ed2ecbbc5954603297c14ff6d1804ee52d59 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 20 Aug 2018 13:12:02 -0500 Subject: [PATCH 1205/2137] Interpreter detect same block boundaries as jit/analyzer --- gen/generate_interpreter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gen/generate_interpreter.js b/gen/generate_interpreter.js index 5d454091..5c3909e6 100755 --- a/gen/generate_interpreter.js +++ b/gen/generate_interpreter.js @@ -226,7 +226,7 @@ function gen_instruction_body_after_prefix(encodings, size) function gen_instruction_body_after_fixed_g(encoding, size) { const instruction_prefix = []; - const instruction_postfix = encoding.block_boundary ? ["after_block_boundary();"] : []; + const instruction_postfix = encoding.block_boundary || (!encoding.custom && encoding.e) || encoding.sse || encoding.task_switch_test ? ["after_block_boundary();"] : []; if(encoding.task_switch_test || encoding.sse) { From d67b91b89549a7976f88ca224a8adf9c2c3898e7 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 20 Aug 2018 13:33:27 -0500 Subject: [PATCH 1206/2137] Update expect tests --- tests/expect/tests/call.wast | 26 ++- tests/expect/tests/do-while.wast | 63 ++++--- tests/expect/tests/if.wast | 46 +++-- tests/expect/tests/mov16.wast | 182 ++++++++++++++++--- tests/expect/tests/mov32-mem.wast | 46 +++-- tests/expect/tests/pop.wast | 13 +- tests/expect/tests/push.wast | 13 +- tests/expect/tests/task_switch_test.asm | 4 + tests/expect/tests/task_switch_test.wast | 69 +++++++ tests/expect/tests/task_switch_test_sse.asm | 4 + tests/expect/tests/task_switch_test_sse.wast | 79 ++++++++ tests/expect/tests/while-do.wast | 44 +++-- 12 files changed, 482 insertions(+), 107 deletions(-) create mode 100644 tests/expect/tests/task_switch_test.asm create mode 100644 tests/expect/tests/task_switch_test.wast create mode 100644 tests/expect/tests/task_switch_test_sse.asm create mode 100644 tests/expect/tests/task_switch_test_sse.wast diff --git a/tests/expect/tests/call.wast b/tests/expect/tests/call.wast index be7ac1bb..5bd45076 100644 --- a/tests/expect/tests/call.wast +++ b/tests/expect/tests/call.wast @@ -7,10 +7,10 @@ (type $t5 (func (param i32) (result i32))) (type $t6 (func (param i32 i32) (result i32))) (import "e" "get_seg" (func $e.get_seg (type $t5))) - (import "e" "safe_write32_slow" (func $e.safe_write32_slow (type $t2))) + (import "e" "safe_write32_slow_jit" (func $e.safe_write32_slow_jit (type $t2))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "instr32_40" (func $e.instr32_40 (type $t0))) - (import "e" "safe_read32s_slow" (func $e.safe_read32s_slow (type $t5))) + (import "e" "safe_read32s_slow_jit" (func $e.safe_read32s_slow_jit (type $t5))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) @@ -67,7 +67,7 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.store offset=8388608 align=1 + (i32.store offset=20221952 align=1 (i32.xor (i32.and (get_local $l3) @@ -75,9 +75,14 @@ (get_local $l2)) (get_local $l0))) (else - (call $e.safe_write32_slow + (call $e.safe_write32_slow_jit (get_local $l2) - (get_local $l0)))) + (get_local $l0)) + (if $I6 + (i32.load8_u + (i32.const 540)) + (then + (return))))) (i32.store (i32.const 20) (get_local $l1)) @@ -130,7 +135,7 @@ (i32.const 556) (i32.load (i32.const 740)) - (if $I6 (result i32) + (if $I7 (result i32) (i32.and (i32.eq (i32.and @@ -162,8 +167,13 @@ (i32.const -4096)) (get_local $l1)))) (else - (call $e.safe_read32s_slow - (get_local $l1)))) + (call $e.safe_read32s_slow_jit + (get_local $l1)) + (if $I8 + (i32.load + (i32.const 540)) + (then + (return))))) (i32.store (i32.const 20) (i32.add diff --git a/tests/expect/tests/do-while.wast b/tests/expect/tests/do-while.wast index 83287fce..cdcbb760 100644 --- a/tests/expect/tests/do-while.wast +++ b/tests/expect/tests/do-while.wast @@ -13,48 +13,55 @@ (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) + (local $l0 i32) (set_local $p0 (get_local $p0)) - (set_local $l0 - (i32.const 10000)) (loop $L0 - (set_local $l0 - (i32.add - (get_local $l0) - (i32.const -1))) - (if $I1 - (i32.eqz - (get_local $l0)) - (then - (return))) - (block $B2 - (block $B3 - (block $B4 - (br_table $B4 $B3 $B2 - (get_local $p0))) + (block $B1 + (block $B2 + (block $B3 + (block $B4 + (br_table $B4 $B3 $B2 $B1 + (get_local $p0))) + (i32.store + (i32.const 560) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 1))) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 4))) + (call $e.instr32_43) + (call $e.instr32_83_7_reg + (i32.const 0) + (i32.const 10)) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 2))) + (return)) (i32.store (i32.const 560) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 4))) + (i32.load + (i32.const 556))) (i32.store (i32.const 556) (i32.add (i32.load (i32.const 556)) - (i32.const 6))) - (call $e.instr32_43) - (call $e.instr32_83_7_reg - (i32.const 0) - (i32.const 10)) + (i32.const 2))) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) - (i32.const 3))) + (i32.const 1))) (if $I5 (call $e.test_nz) (then @@ -68,7 +75,7 @@ (i32.const 0))) (else (set_local $p0 - (i32.const 1)))) + (i32.const 2)))) (br $L0)) (i32.store (i32.const 560) diff --git a/tests/expect/tests/if.wast b/tests/expect/tests/if.wast index 96279f0b..60e6f7d4 100644 --- a/tests/expect/tests/if.wast +++ b/tests/expect/tests/if.wast @@ -22,30 +22,46 @@ (block $B2 (block $B3 (block $B4 - (br_table $B4 $B3 $B2 $B1 - (get_local $p0))) + (block $B5 + (br_table $B5 $B4 $B3 $B2 $B1 + (get_local $p0))) + (i32.store + (i32.const 560) + (i32.load + (i32.const 556))) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 3))) + (call $e.instr32_83_7_reg + (i32.const 0) + (i32.const 5)) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) + (return)) (i32.store (i32.const 560) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 3))) + (i32.load + (i32.const 556))) (i32.store (i32.const 556) (i32.add (i32.load (i32.const 556)) - (i32.const 5))) - (call $e.instr32_83_7_reg - (i32.const 0) - (i32.const 5)) + (i32.const 2))) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) - (i32.const 2))) - (if $I5 + (i32.const 1))) + (if $I6 (call $e.test_nle) (then (i32.store @@ -55,10 +71,10 @@ (i32.const 556)) (i32.const 1))) (set_local $p0 - (i32.const 2))) + (i32.const 3))) (else (set_local $p0 - (i32.const 1)))) + (i32.const 2)))) (br $L0)) (call $e.instr32_41) (i32.store @@ -74,7 +90,7 @@ (i32.const 664)) (i32.const 1))) (set_local $p0 - (i32.const 2)) + (i32.const 3)) (br $L0)) (i32.store (i32.const 560) diff --git a/tests/expect/tests/mov16.wast b/tests/expect/tests/mov16.wast index f112a54c..c6acebc5 100644 --- a/tests/expect/tests/mov16.wast +++ b/tests/expect/tests/mov16.wast @@ -8,12 +8,12 @@ (type $t6 (func (param i32 i32) (result i32))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "instr16_B8" (func $e.instr16_B8 (type $t1))) - (import "e" "instr16_8B_mem" (func $e.instr16_8B_mem (type $t2))) - (import "e" "instr16_89_mem" (func $e.instr16_89_mem (type $t2))) + (import "e" "safe_read16_slow_jit" (func $e.safe_read16_slow_jit (type $t5))) + (import "e" "safe_write16_slow_jit" (func $e.safe_write16_slow_jit (type $t2))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (set_local $p0 (get_local $p0)) (loop $L0 @@ -29,24 +29,90 @@ (i32.const 3))) (call $e.instr16_B8 (i32.const 51966)) - (call $e.instr16_8B_mem - (i32.add - (i32.const 32) - (call $e.get_seg - (i32.const 3))) - (i32.const 1)) + (i32.store16 + (i32.const 8) + (if $I3 (result i32) + (i32.and + (i32.eq + (i32.and + (tee_local $l1 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (tee_local $l0 + (i32.add + (i32.const 32) + (call $e.get_seg + (i32.const 3)))) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4073)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l0) + (i32.const 4095)) + (i32.const 4094))) + (then + (i32.load16_u offset=20221952 align=1 + (i32.xor + (i32.and + (get_local $l1) + (i32.const -4096)) + (get_local $l0)))) + (else + (call $e.safe_read16_slow_jit + (get_local $l0)) + (if $I4 + (i32.load + (i32.const 540)) + (then + (return)))))) (i32.store (i32.const 560) (i32.add (i32.load (i32.const 556)) (i32.const 7))) - (call $e.instr16_8B_mem - (i32.add - (i32.const 36) - (call $e.get_seg - (i32.const 3))) - (i32.const 2)) + (i32.store16 + (i32.const 12) + (if $I5 (result i32) + (i32.and + (i32.eq + (i32.and + (tee_local $l0 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (tee_local $l1 + (i32.add + (i32.const 36) + (call $e.get_seg + (i32.const 3)))) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4073)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l1) + (i32.const 4095)) + (i32.const 4094))) + (then + (i32.load16_u offset=20221952 align=1 + (i32.xor + (i32.and + (get_local $l0) + (i32.const -4096)) + (get_local $l1)))) + (else + (call $e.safe_read16_slow_jit + (get_local $l1)) + (if $I6 + (i32.load + (i32.const 540)) + (then + (return)))))) (i32.store (i32.const 560) (i32.add @@ -59,7 +125,7 @@ (i32.store16 (i32.const 28) (i32.const 32)) - (call $e.instr16_89_mem + (set_local $l0 (i32.add (i32.and (i32.add @@ -69,15 +135,52 @@ (i32.const 32))) (i32.const 65535)) (call $e.get_seg - (i32.const 3))) - (i32.const 0)) + (i32.const 3)))) + (set_local $l1 + (i32.load16_u + (i32.const 4))) + (if $I7 + (i32.and + (i32.eq + (i32.and + (tee_local $l2 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (get_local $l0) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4075)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l0) + (i32.const 4095)) + (i32.const 4094))) + (then + (i32.store16 offset=20221952 align=1 + (i32.xor + (i32.and + (get_local $l2) + (i32.const -4096)) + (get_local $l0)) + (get_local $l1))) + (else + (call $e.safe_write16_slow_jit + (get_local $l0) + (get_local $l1)) + (if $I8 + (i32.load8_u + (i32.const 540)) + (then + (return))))) (i32.store (i32.const 560) (i32.add (i32.load (i32.const 556)) (i32.const 21))) - (call $e.instr16_89_mem + (set_local $l1 (i32.add (i32.and (i32.add @@ -87,8 +190,45 @@ (i32.const 28))) (i32.const 65535)) (call $e.get_seg - (i32.const 3))) - (i32.const 1)) + (i32.const 3)))) + (set_local $l0 + (i32.load16_u + (i32.const 8))) + (if $I9 + (i32.and + (i32.eq + (i32.and + (tee_local $l2 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (get_local $l1) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4075)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l1) + (i32.const 4095)) + (i32.const 4094))) + (then + (i32.store16 offset=20221952 align=1 + (i32.xor + (i32.and + (get_local $l2) + (i32.const -4096)) + (get_local $l1)) + (get_local $l0))) + (else + (call $e.safe_write16_slow_jit + (get_local $l1) + (get_local $l0)) + (if $I10 + (i32.load8_u + (i32.const 540)) + (then + (return))))) (i32.store (i32.const 560) (i32.add diff --git a/tests/expect/tests/mov32-mem.wast b/tests/expect/tests/mov32-mem.wast index 498699bb..183987e9 100644 --- a/tests/expect/tests/mov32-mem.wast +++ b/tests/expect/tests/mov32-mem.wast @@ -7,8 +7,8 @@ (type $t5 (func (param i32) (result i32))) (type $t6 (func (param i32 i32) (result i32))) (import "e" "get_seg" (func $e.get_seg (type $t5))) - (import "e" "safe_write32_slow" (func $e.safe_write32_slow (type $t2))) - (import "e" "safe_read32s_slow" (func $e.safe_read32s_slow (type $t5))) + (import "e" "safe_write32_slow_jit" (func $e.safe_write32_slow_jit (type $t2))) + (import "e" "safe_read32s_slow_jit" (func $e.safe_read32s_slow_jit (type $t5))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) @@ -62,9 +62,14 @@ (get_local $l0)) (get_local $l1))) (else - (call $e.safe_write32_slow + (call $e.safe_write32_slow_jit (get_local $l0) - (get_local $l1)))) + (get_local $l1)) + (if $I4 + (i32.load8_u + (i32.const 540)) + (then + (return))))) (i32.store (i32.const 560) (i32.add @@ -82,7 +87,7 @@ (set_local $l0 (i32.load (i32.const 8))) - (if $I4 + (if $I5 (i32.and (i32.eq (i32.and @@ -109,9 +114,14 @@ (get_local $l1)) (get_local $l0))) (else - (call $e.safe_write32_slow + (call $e.safe_write32_slow_jit (get_local $l1) - (get_local $l0)))) + (get_local $l0)) + (if $I6 + (i32.load8_u + (i32.const 540)) + (then + (return))))) (i32.store (i32.const 560) (i32.add @@ -120,7 +130,7 @@ (i32.const 12))) (i32.store (i32.const 28) - (if $I5 (result i32) + (if $I7 (result i32) (i32.and (i32.eq (i32.and @@ -153,8 +163,13 @@ (i32.const -4096)) (get_local $l0)))) (else - (call $e.safe_read32s_slow - (get_local $l0))))) + (call $e.safe_read32s_slow_jit + (get_local $l0)) + (if $I8 + (i32.load + (i32.const 540)) + (then + (return)))))) (i32.store (i32.const 560) (i32.add @@ -163,7 +178,7 @@ (i32.const 18))) (i32.store (i32.const 32) - (if $I6 (result i32) + (if $I9 (result i32) (i32.and (i32.eq (i32.and @@ -196,8 +211,13 @@ (i32.const -4096)) (get_local $l1)))) (else - (call $e.safe_read32s_slow - (get_local $l1))))) + (call $e.safe_read32s_slow_jit + (get_local $l1)) + (if $I10 + (i32.load + (i32.const 540)) + (then + (return)))))) (i32.store (i32.const 560) (i32.add diff --git a/tests/expect/tests/pop.wast b/tests/expect/tests/pop.wast index eaef36ea..0f082bda 100644 --- a/tests/expect/tests/pop.wast +++ b/tests/expect/tests/pop.wast @@ -7,7 +7,7 @@ (type $t5 (func (param i32) (result i32))) (type $t6 (func (param i32 i32) (result i32))) (import "e" "get_seg" (func $e.get_seg (type $t5))) - (import "e" "safe_read32s_slow" (func $e.safe_read32s_slow (type $t5))) + (import "e" "safe_read32s_slow_jit" (func $e.safe_read32s_slow_jit (type $t5))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) @@ -49,15 +49,20 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.load offset=8388608 align=1 + (i32.load offset=20221952 align=1 (i32.xor (i32.and (get_local $l2) (i32.const -4096)) (get_local $l1)))) (else - (call $e.safe_read32s_slow - (get_local $l1)))) + (call $e.safe_read32s_slow_jit + (get_local $l1)) + (if $I4 + (i32.load + (i32.const 540)) + (then + (return))))) (i32.store (i32.const 20) (i32.add diff --git a/tests/expect/tests/push.wast b/tests/expect/tests/push.wast index 21c64ff3..0804b0c5 100644 --- a/tests/expect/tests/push.wast +++ b/tests/expect/tests/push.wast @@ -7,7 +7,7 @@ (type $t5 (func (param i32) (result i32))) (type $t6 (func (param i32 i32) (result i32))) (import "e" "get_seg" (func $e.get_seg (type $t5))) - (import "e" "safe_write32_slow" (func $e.safe_write32_slow (type $t2))) + (import "e" "safe_write32_slow_jit" (func $e.safe_write32_slow_jit (type $t2))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) @@ -54,7 +54,7 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.store offset=8388608 align=1 + (i32.store offset=20221952 align=1 (i32.xor (i32.and (get_local $l3) @@ -62,9 +62,14 @@ (get_local $l2)) (get_local $l0))) (else - (call $e.safe_write32_slow + (call $e.safe_write32_slow_jit (get_local $l2) - (get_local $l0)))) + (get_local $l0)) + (if $I4 + (i32.load8_u + (i32.const 540)) + (then + (return))))) (i32.store (i32.const 20) (get_local $l1)) diff --git a/tests/expect/tests/task_switch_test.asm b/tests/expect/tests/task_switch_test.asm new file mode 100644 index 00000000..9631a7ef --- /dev/null +++ b/tests/expect/tests/task_switch_test.asm @@ -0,0 +1,4 @@ +BITS 32 + + fadd + hlt diff --git a/tests/expect/tests/task_switch_test.wast b/tests/expect/tests/task_switch_test.wast new file mode 100644 index 00000000..a7103237 --- /dev/null +++ b/tests/expect/tests/task_switch_test.wast @@ -0,0 +1,69 @@ +(module + (type $t0 (func)) + (type $t1 (func (param i32))) + (type $t2 (func (param i32 i32))) + (type $t3 (func (param i32 i32 i32))) + (type $t4 (func (result i32))) + (type $t5 (func (param i32) (result i32))) + (type $t6 (func (param i32 i32) (result i32))) + (import "e" "get_seg" (func $e.get_seg (type $t5))) + (import "e" "task_switch_test_void" (func $e.task_switch_test_void (type $t0))) + (import "e" "instr_DE_0_reg" (func $e.instr_DE_0_reg (type $t1))) + (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) + (import "e" "m" (memory $e.m 256)) + (func $f (export "f") (type $t1) (param $p0 i32) + (local $l0 i32) + (set_local $p0 + (get_local $p0)) + (loop $L0 + (block $B1 + (block $B2 + (block $B3 + (br_table $B3 $B2 $B1 + (get_local $p0))) + (i32.store + (i32.const 560) + (i32.load + (i32.const 556))) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 2))) + (if $I4 + (i32.and + (i32.load + (i32.const 580)) + (i32.const 12)) + (then + (call $e.task_switch_test_void) + (return))) + (call $e.instr_DE_0_reg + (i32.const 1)) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) + (return)) + (i32.store + (i32.const 560) + (i32.load + (i32.const 556))) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 1))) + (call $e.instr_F4) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) + (return)) + (unreachable)))) diff --git a/tests/expect/tests/task_switch_test_sse.asm b/tests/expect/tests/task_switch_test_sse.asm new file mode 100644 index 00000000..9e5053c2 --- /dev/null +++ b/tests/expect/tests/task_switch_test_sse.asm @@ -0,0 +1,4 @@ +BITS 32 + + andpd xmm0, xmm1 + hlt diff --git a/tests/expect/tests/task_switch_test_sse.wast b/tests/expect/tests/task_switch_test_sse.wast new file mode 100644 index 00000000..6bb7f7b3 --- /dev/null +++ b/tests/expect/tests/task_switch_test_sse.wast @@ -0,0 +1,79 @@ +(module + (type $t0 (func)) + (type $t1 (func (param i32))) + (type $t2 (func (param i32 i32))) + (type $t3 (func (param i32 i32 i32))) + (type $t4 (func (result i32))) + (type $t5 (func (param i32) (result i32))) + (type $t6 (func (param i32 i32) (result i32))) + (import "e" "get_seg" (func $e.get_seg (type $t5))) + (import "e" "task_switch_test_mmx_void" (func $e.task_switch_test_mmx_void (type $t0))) + (import "e" "instr_660F54_reg" (func $e.instr_660F54_reg (type $t2))) + (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) + (import "e" "m" (memory $e.m 256)) + (func $f (export "f") (type $t1) (param $p0 i32) + (local $l0 i32) + (set_local $p0 + (get_local $p0)) + (loop $L0 + (block $B1 + (block $B2 + (block $B3 + (br_table $B3 $B2 $B1 + (get_local $p0))) + (i32.store + (i32.const 560) + (i32.load + (i32.const 556))) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 4))) + (i32.store + (i32.const 648) + (i32.or + (i32.load + (i32.const 648)) + (i32.const 32))) + (if $I4 + (i32.and + (i32.load + (i32.const 580)) + (i32.const 12)) + (then + (call $e.task_switch_test_mmx_void) + (return))) + (call $e.instr_660F54_reg + (i32.const 1) + (i32.const 0)) + (i32.store + (i32.const 648) + (i32.const 0)) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) + (return)) + (i32.store + (i32.const 560) + (i32.load + (i32.const 556))) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 1))) + (call $e.instr_F4) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) + (return)) + (unreachable)))) diff --git a/tests/expect/tests/while-do.wast b/tests/expect/tests/while-do.wast index a86ab341..37c81c40 100644 --- a/tests/expect/tests/while-do.wast +++ b/tests/expect/tests/while-do.wast @@ -21,30 +21,46 @@ (block $B2 (block $B3 (block $B4 - (br_table $B4 $B3 $B2 $B1 - (get_local $p0))) + (block $B5 + (br_table $B5 $B4 $B3 $B2 $B1 + (get_local $p0))) + (i32.store + (i32.const 560) + (i32.load + (i32.const 556))) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 3))) + (call $e.instr32_83_7_reg + (i32.const 0) + (i32.const 10)) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) + (return)) (i32.store (i32.const 560) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 3))) + (i32.load + (i32.const 556))) (i32.store (i32.const 556) (i32.add (i32.load (i32.const 556)) - (i32.const 5))) - (call $e.instr32_83_7_reg - (i32.const 0) - (i32.const 10)) + (i32.const 2))) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) - (i32.const 2))) - (if $I5 + (i32.const 1))) + (if $I6 (call $e.test_z) (then (i32.store @@ -54,10 +70,10 @@ (i32.const 556)) (i32.const 3))) (set_local $p0 - (i32.const 2))) + (i32.const 3))) (else (set_local $p0 - (i32.const 1)))) + (i32.const 2)))) (br $L0)) (i32.store (i32.const 560) From d9282afec53d3d46d17ebc2ce8e7f64d849f1bc2 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 20 Aug 2018 17:38:27 -0500 Subject: [PATCH 1207/2137] Force logging of panic messages --- src/browser/starter.js | 4 ++++ src/rust/c_api.rs | 4 ++-- src/rust/dbg.rs | 45 +++++++++++++++++++++++++++++++++--------- src/rust/util.rs | 12 ++++++++++- 4 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 00dc28df..55ef3784 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -258,6 +258,10 @@ function V86Starter(options) const str = v86util.read_sized_string_from_mem(v86oxide.exports.memory, offset, len); dbg_log(str, LOG_CPU); }, + "console_log_from_wasm": function(offset, len) { + const str = v86util.read_sized_string_from_mem(v86oxide.exports.memory, offset, len); + console.error(str); + }, "codegen_finalize": (wasm_table_index, start, end, first_opcode, state_flags) => cpu.codegen_finalize(wasm_table_index, start, end, first_opcode, state_flags), "__indirect_function_table": wasm_table, "floor": Math.floor, diff --git a/src/rust/c_api.rs b/src/rust/c_api.rs index 5262d781..ea8145c6 100644 --- a/src/rust/c_api.rs +++ b/src/rust/c_api.rs @@ -22,14 +22,14 @@ pub fn rust_setup() { panic::set_hook(Box::new(|panic_info| { if let Some(location) = panic_info.location() { - dbg_log!( + console_log!( "panic occurred in file '{}' at line {}", location.file(), location.line() ); } else { - dbg_log!("panic occurred but can't get location information..."); + console_log!("panic occurred but can't get location information..."); } })); } diff --git a/src/rust/dbg.rs b/src/rust/dbg.rs index d03dbb7f..bb208a25 100644 --- a/src/rust/dbg.rs +++ b/src/rust/dbg.rs @@ -8,6 +8,16 @@ macro_rules! dbg_log { } } +#[allow(unused_macros)] +macro_rules! console_log { + ($fmt:expr) => { + println!($fmt); + }; + ($fmt:expr, $($arg:tt)*) => { + println!($fmt, $($arg)*); + } +} + #[allow(unused_macros)] macro_rules! dbg_assert { ($($arg:tt)*) => { @@ -17,17 +27,34 @@ macro_rules! dbg_assert { #[cfg(target_arch = "wasm32")] #[allow(unused_macros)] -macro_rules! dbg_log { +macro_rules! console_log { ($fmt:expr) => { { - use ::util::{ DEBUG, _log_to_js_console }; - if DEBUG { _log_to_js_console($fmt); } + use ::util::{ console_log_to_js_console }; + console_log_to_js_console($fmt); } }; ($fmt:expr, $($arg:tt)*) => { { - use ::util::{ DEBUG, _log_to_js_console }; - if DEBUG { _log_to_js_console(format!($fmt, $($arg)*)); } + use ::util::{ console_log_to_js_console }; + console_log_to_js_console(format!($fmt, $($arg)*)); + } + }; +} + +#[cfg(target_arch = "wasm32")] +#[allow(unused_macros)] +macro_rules! dbg_log { + ($fmt:expr) => { + { + use ::util::{ DEBUG, log_to_js_console }; + if DEBUG { log_to_js_console($fmt); } + } + }; + ($fmt:expr, $($arg:tt)*) => { + { + use ::util::{ DEBUG, log_to_js_console }; + if DEBUG { log_to_js_console(format!($fmt, $($arg)*)); } } }; } @@ -36,9 +63,9 @@ macro_rules! dbg_log { #[allow(unused_macros)] macro_rules! dbg_assert { ($cond:expr) => {{ - use util::{_log_to_js_console, abort, DEBUG}; + use util::{abort, log_to_js_console, DEBUG}; if DEBUG && !$cond { - _log_to_js_console(format!( + log_to_js_console(format!( "Assertion failed at {}:{}:{}: '{}'", file!(), line!(), @@ -52,9 +79,9 @@ macro_rules! dbg_assert { } }}; ($cond:expr, $desc:expr) => {{ - use util::{_log_to_js_console, abort, DEBUG}; + use util::{abort, log_to_js_console, DEBUG}; if DEBUG && !$cond { - _log_to_js_console(format!( + log_to_js_console(format!( "Assertion failed at {}:{}:{}: '{}' - '{}'", file!(), line!(), diff --git a/src/rust/util.rs b/src/rust/util.rs index 98af60f6..f446195c 100644 --- a/src/rust/util.rs +++ b/src/rust/util.rs @@ -77,6 +77,7 @@ pub const DEBUG: bool = cfg!(debug_assertions); #[cfg(target_arch = "wasm32")] extern "C" { pub fn log_from_wasm(ptr: *const u8, len: usize); + pub fn console_log_from_wasm(ptr: *const u8, len: usize); pub fn abort(); } @@ -84,10 +85,19 @@ extern "C" { use std::string::ToString; #[cfg(target_arch = "wasm32")] -pub fn _log_to_js_console(s: T) { +pub fn log_to_js_console(s: T) { let s: String = s.to_string(); let len = s.len(); unsafe { log_from_wasm(s.as_bytes().as_ptr(), len); } } + +#[cfg(target_arch = "wasm32")] +pub fn console_log_to_js_console(s: T) { + let s: String = s.to_string(); + let len = s.len(); + unsafe { + console_log_from_wasm(s.as_bytes().as_ptr(), len); + } +} From c8b3d5a618fe451511f73f9789f8c56499588c61 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 20 Aug 2018 20:10:58 -0500 Subject: [PATCH 1208/2137] Add more information to .expect --- src/rust/jit.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 87469d8f..4c730ae7 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -950,7 +950,9 @@ fn jit_generate_module( // - All instructions that don't change eip // - Unconditional jump - let next_bb_index = *basic_block_indices.get(&next_block_addr).expect(""); + let next_bb_index = *basic_block_indices + .get(&next_block_addr) + .expect("basic_block_indices.get (Normal)"); // set state variable to next basic block builder.instruction_body.push_i32(next_bb_index as i32); @@ -997,7 +999,7 @@ fn jit_generate_module( if let Some(next_block_branch_taken_addr) = next_block_branch_taken_addr { let next_basic_block_branch_taken_index = *basic_block_indices .get(&next_block_branch_taken_addr) - .expect(""); + .expect("basic_block_indices.get (branch taken)"); builder .instruction_body @@ -1014,8 +1016,9 @@ fn jit_generate_module( { // Branch not taken // TODO: Could use fall-through here - let next_basic_block_index = - *basic_block_indices.get(&next_block_addr).expect(""); + let next_basic_block_index = *basic_block_indices + .get(&next_block_addr) + .expect("basic_block_indices.get (branch not taken)"); builder .instruction_body From cd8e47a5c587b5381201cb53480c5aba1cba8ad0 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 20 Aug 2018 20:13:33 -0500 Subject: [PATCH 1209/2137] Improve hook handler: Print more information --- src/rust/c_api.rs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/rust/c_api.rs b/src/rust/c_api.rs index ea8145c6..be2f8d01 100644 --- a/src/rust/c_api.rs +++ b/src/rust/c_api.rs @@ -21,16 +21,7 @@ pub fn rust_setup() { use std::panic; panic::set_hook(Box::new(|panic_info| { - if let Some(location) = panic_info.location() { - console_log!( - "panic occurred in file '{}' at line {}", - location.file(), - location.line() - ); - } - else { - console_log!("panic occurred but can't get location information..."); - } + console_log!("{}", panic_info.to_string()); })); } From 92a2ffd4a98e51f34720430973fac98c87405d78 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 21 Aug 2018 11:18:38 -0500 Subject: [PATCH 1210/2137] Use .count_ones() over manual implementation for popcnt --- src/rust/cpu2/arith.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/rust/cpu2/arith.rs b/src/rust/cpu2/arith.rs index e0d8d28f..7d760f3f 100644 --- a/src/rust/cpu2/arith.rs +++ b/src/rust/cpu2/arith.rs @@ -1117,10 +1117,7 @@ pub unsafe fn popcnt(mut v: i32) -> i32 { *flags_changed = 0i32; *flags &= !FLAGS_ALL; if 0 != v { - c_comment!(("http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel")); - v = v - (v >> 1i32 & 1431655765i32); - v = (v & 858993459i32) + (v >> 2i32 & 858993459i32); - return (v + (v >> 4i32) & 252645135i32) * 16843009i32 >> 24i32; + return v.count_ones() as i32; } else { *flags |= FLAG_ZERO; From dc37bac547ebaa97a55155d9a9256aad70edd193 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 21 Aug 2018 12:24:35 -0500 Subject: [PATCH 1211/2137] Analysis: Never emit empty basic blocks, track last instruction of basic block --- src/rust/jit.rs | 118 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 89 insertions(+), 29 deletions(-) diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 4c730ae7..9c1d8fde 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::{BTreeMap, HashMap, HashSet}; use analysis::AnalysisType; use codegen; @@ -346,7 +346,7 @@ enum BasicBlockType { next_block_addr: u32, }, ConditionalJump { - next_block_addr: u32, + next_block_addr: Option, next_block_branch_taken_addr: Option, condition: u8, jump_offset: i32, @@ -357,6 +357,7 @@ enum BasicBlockType { struct BasicBlock { addr: u32, + last_instruction_addr: u32, end_addr: u32, is_entry_block: bool, ty: BasicBlockType, @@ -454,7 +455,7 @@ fn jit_find_basic_blocks( let mut to_visit_stack: Vec = entry_points.iter().cloned().collect(); let mut marked_as_entry: HashSet = entry_points.clone(); let page_high_bits = page.to_address(); - let mut basic_blocks: HashMap = HashMap::new(); + let mut basic_blocks: BTreeMap = BTreeMap::new(); let mut requires_loop_limit = false; while let Some(to_visit_offset) = to_visit_stack.pop() { @@ -462,20 +463,22 @@ fn jit_find_basic_blocks( if basic_blocks.contains_key(&to_visit) { continue; } + if is_near_end_of_page(to_visit) { + // Empty basic block, don't insert + profiler::stat_increment(stat::S_COMPILE_CUT_OFF_AT_END_OF_PAGE); + continue; + } + let mut current_address = to_visit; let mut current_block = BasicBlock { addr: current_address, + last_instruction_addr: 0, end_addr: 0, ty: BasicBlockType::Exit, is_entry_block: false, }; loop { - if is_near_end_of_page(current_address) { - // TODO: Don't insert this block if empty - current_block.end_addr = current_address; - profiler::stat_increment(stat::S_COMPILE_CUT_OFF_AT_END_OF_PAGE); - break; - } + let addr_before_instruction = current_address; let mut ctx = &mut CpuContext { eip: current_address, ..cpu @@ -489,10 +492,13 @@ fn jit_find_basic_blocks( dbg_assert!(has_next_instruction); if basic_blocks.contains_key(¤t_address) { + current_block.last_instruction_addr = addr_before_instruction; current_block.end_addr = current_address; + dbg_assert!(!is_near_end_of_page(current_address)); current_block.ty = BasicBlockType::Normal { next_block_addr: current_address, }; + break; } }, AnalysisType::Jump { @@ -520,7 +526,7 @@ fn jit_find_basic_blocks( let next_block_branch_taken_addr; - if Page::page_of(jump_target) == page { + if Page::page_of(jump_target) == page && !is_near_end_of_page(jump_target) { to_visit_stack.push(jump_target as u16 & 0xFFF); next_block_branch_taken_addr = Some(jump_target); @@ -536,14 +542,22 @@ fn jit_find_basic_blocks( next_block_branch_taken_addr = None; } + let next_block_addr = if is_near_end_of_page(current_address) { + None + } + else { + Some(current_address) + }; + current_block.ty = BasicBlockType::ConditionalJump { - next_block_addr: current_address, + next_block_addr, next_block_branch_taken_addr, condition, jump_offset: offset, jump_offset_is_32: is_32, }; + current_block.last_instruction_addr = addr_before_instruction; current_block.end_addr = current_address; break; @@ -557,7 +571,7 @@ fn jit_find_basic_blocks( to_visit_stack.push(current_address as u16 & 0xFFF); } - if Page::page_of(jump_target) == page { + if Page::page_of(jump_target) == page && !is_near_end_of_page(jump_target) { current_block.ty = BasicBlockType::Normal { next_block_addr: jump_target, }; @@ -567,6 +581,7 @@ fn jit_find_basic_blocks( current_block.ty = BasicBlockType::Exit; } + current_block.last_instruction_addr = addr_before_instruction; current_block.end_addr = current_address; break; @@ -584,13 +599,42 @@ fn jit_find_basic_blocks( to_visit_stack.push(current_address as u16 & 0xFFF); } + current_block.last_instruction_addr = addr_before_instruction; current_block.end_addr = current_address; break; }, } + + if is_near_end_of_page(current_address) { + current_block.last_instruction_addr = addr_before_instruction; + current_block.end_addr = current_address; + profiler::stat_increment(stat::S_COMPILE_CUT_OFF_AT_END_OF_PAGE); + break; + } } - basic_blocks.insert(to_visit, current_block); + let previous_block = basic_blocks + .range(..current_block.addr) + .next_back() + .map(|(_, previous_block)| (previous_block.addr, previous_block.end_addr)); + + if let Some((start_addr, end_addr)) = previous_block { + if current_block.addr < end_addr { + // If this block overlaps with the previous block, re-analyze the previous block + let old_block = basic_blocks.remove(&start_addr); + dbg_assert!(old_block.is_some()); + to_visit_stack.push(start_addr as u16 & 0xFFF); + + // Note that this does not ensure the invariant that two consecutive blocks don't + // overlay. For that, we also need to check the following block. + } + } + + dbg_assert!(current_block.addr < current_block.end_addr); + dbg_assert!(current_block.addr <= current_block.last_instruction_addr); + dbg_assert!(current_block.last_instruction_addr < current_block.end_addr); + + basic_blocks.insert(current_block.addr, current_block); } for block in basic_blocks.values_mut() { @@ -606,12 +650,19 @@ fn jit_find_basic_blocks( for i in 0..basic_blocks.len() - 1 { let next_block_addr = basic_blocks[i + 1].addr; - let block = &mut basic_blocks[i]; + let next_block_end_addr = basic_blocks[i + 1].end_addr; + let next_block_is_entry = basic_blocks[i + 1].is_entry_block; + let block = &basic_blocks[i]; if next_block_addr < block.end_addr { - block.ty = BasicBlockType::Normal { next_block_addr }; - block.end_addr = next_block_addr; - - // TODO: assert that the old type is equal to the type of the following block? + dbg_log!( + "Overlapping first=[from={:x} to={:x} is_entry={}] second=[from={:x} to={:x} is_entry={}]", + block.addr, + block.end_addr, + block.is_entry_block as u8, + next_block_addr, + next_block_end_addr, + next_block_is_entry as u8 + ); } } @@ -927,16 +978,17 @@ fn jit_generate_module( // block end opcode and then the code for that block builder.instruction_body.block_end(); - if block.addr == block.end_addr { - // Empty basic block, generate no code (for example, jump to block - // that is near end of page) - dbg_assert!(block.ty == BasicBlockType::Exit); - } - else { - builder.commit_instruction_body_to_cs(); - jit_generate_basic_block(&mut cpu, builder, block.addr, block.end_addr); - builder.commit_instruction_body_to_cs(); - } + dbg_assert!(block.addr < block.end_addr); + + builder.commit_instruction_body_to_cs(); + jit_generate_basic_block( + &mut cpu, + builder, + block.addr, + block.last_instruction_addr, + block.end_addr, + ); + builder.commit_instruction_body_to_cs(); let invalid_connection_to_next_block = block.end_addr != cpu.eip; @@ -1013,7 +1065,7 @@ fn jit_generate_module( builder.instruction_body.else_(); - { + if let Some(next_block_addr) = next_block_addr { // Branch not taken // TODO: Could use fall-through here let next_basic_block_index = *basic_block_indices @@ -1025,6 +1077,10 @@ fn jit_generate_module( .push_i32(next_basic_block_index as i32); builder.instruction_body.set_local(&gen_local_state); } + else { + // End of this page + builder.instruction_body.return_(); + } builder.instruction_body.block_end(); @@ -1048,6 +1104,7 @@ fn jit_generate_basic_block( mut cpu: &mut CpuContext, builder: &mut WasmBuilder, start_addr: u32, + last_instruction_addr: u32, stop_addr: u32, ) { let mut len = 0; @@ -1085,6 +1142,8 @@ fn jit_generate_basic_block( let instruction_length = end_eip - start_eip; was_block_boundary = instruction_flags & JIT_INSTR_BLOCK_BOUNDARY_FLAG != 0; + dbg_assert!((end_eip == stop_addr) == (start_eip == last_instruction_addr)); + dbg_assert!(instruction_length < MAX_INSTRUCTION_LENGTH); if ENABLE_JIT_NONFAULTING_OPTIMZATION { @@ -1136,6 +1195,7 @@ fn jit_generate_basic_block( if was_block_boundary || is_near_end_of_page(end_addr) || end_addr > stop_addr { dbg_log!("Overlapping basic blocks start={:x} expected_end={:x} end={:x} was_block_boundary={} near_end_of_page={}", start_addr, stop_addr, end_addr, was_block_boundary, is_near_end_of_page(end_addr)); + dbg_assert!(false); break; } } From 60d4a28e2c3b18fd406db447b47247fd96007d73 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 21 Aug 2018 12:25:32 -0500 Subject: [PATCH 1212/2137] jit: Custom instructions can be block boundaries --- gen/generate_jit.js | 3 ++- src/rust/jit.rs | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/gen/generate_jit.js b/gen/generate_jit.js index 2e68d369..b40b28ce 100755 --- a/gen/generate_jit.js +++ b/gen/generate_jit.js @@ -312,7 +312,8 @@ function gen_instruction_body_after_fixed_g(encoding, size) reg_postfix ), }, - } + }, + instruction_postfix ); } else diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 9c1d8fde..4611f774 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -991,6 +991,7 @@ fn jit_generate_module( builder.commit_instruction_body_to_cs(); let invalid_connection_to_next_block = block.end_addr != cpu.eip; + dbg_assert!(!invalid_connection_to_next_block); match (&block.ty, invalid_connection_to_next_block) { (_, true) | (BasicBlockType::Exit, _) => { From d4d7d236d510958b934b0af83d5e2d11bb672612 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 21 Aug 2018 18:07:45 -0500 Subject: [PATCH 1213/2137] Make all instructions non-faulting; handle faulting case in gen_safe_{read,write} (#44) --- src/rust/codegen.rs | 46 +++++++++- src/rust/jit.rs | 90 ++++++-------------- src/rust/jit_instructions.rs | 7 +- tests/expect/tests/call.wast | 44 +++++++--- tests/expect/tests/do-while.wast | 10 +-- tests/expect/tests/if.wast | 16 ++-- tests/expect/tests/indirect-call.wast | 14 +-- tests/expect/tests/mov16.wast | 82 ++++++++++-------- tests/expect/tests/mov32-mem.wast | 56 +++++++----- tests/expect/tests/mov32-reg.wast | 26 +++--- tests/expect/tests/pop.wast | 14 +-- tests/expect/tests/push.wast | 14 +-- tests/expect/tests/task_switch_test.wast | 14 +-- tests/expect/tests/task_switch_test_sse.wast | 14 +-- tests/expect/tests/while-do.wast | 22 ++--- 15 files changed, 261 insertions(+), 208 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 9f41dd81..e05b2f8d 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -236,8 +236,29 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { } // Pseudo: - // else { leave_on_stack(safe_read*_slow(address)); if(page_fault) return } + // else { + // *previous_ip = *instruction_pointer & ~0xFFF | start_of_instruction; + // leave_on_stack(safe_read*_slow(address)); + // if(page_fault) return; + // } builder.instruction_body.else_(); + + builder + .instruction_body + .push_i32(global_pointers::PREVIOUS_IP as i32); + + builder + .instruction_body + .load_aligned_i32(global_pointers::INSTRUCTION_POINTER); + builder.instruction_body.push_i32(!0xFFF); + builder.instruction_body.and_i32(); + builder + .instruction_body + .push_i32(ctx.start_of_current_instruction as i32 & 0xFFF); + builder.instruction_body.or_i32(); + + builder.instruction_body.store_aligned_i32(); + builder.instruction_body.get_local(&address_local); match bits { BitSize::WORD => { @@ -341,8 +362,29 @@ fn gen_safe_write( } // Pseudo: - // else { safe_write*_slow(address, value); if(page_fault) return; } + // else { + // *previous_ip = *instruction_pointer & ~0xFFF | start_of_instruction; + // safe_write*_slow(address, value); + // if(page_fault) return; + // } builder.instruction_body.else_(); + + builder + .instruction_body + .push_i32(global_pointers::PREVIOUS_IP as i32); + + builder + .instruction_body + .load_aligned_i32(global_pointers::INSTRUCTION_POINTER); + builder.instruction_body.push_i32(!0xFFF); + builder.instruction_body.and_i32(); + builder + .instruction_body + .push_i32(ctx.start_of_current_instruction as i32 & 0xFFF); + builder.instruction_body.or_i32(); + + builder.instruction_body.store_aligned_i32(); + builder.instruction_body.get_local(&address_local); builder.instruction_body.get_local(&value_local); match bits { diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 4611f774..1f1d29e4 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -19,7 +19,6 @@ pub const WASM_TABLE_SIZE: u32 = 0x10000; pub const HASH_PRIME: u32 = 6151; pub const CHECK_JIT_CACHE_ARRAY_INVARIANTS: bool = false; -pub const ENABLE_JIT_NONFAULTING_OPTIMZATION: bool = true; pub const JIT_MAX_ITERATIONS_PER_FUNCTION: u32 = 10000; @@ -380,6 +379,7 @@ impl cached_code { pub struct JitContext<'a> { pub cpu: &'a mut CpuContext, pub builder: &'a mut WasmBuilder, + pub start_of_current_instruction: u32, } pub const JIT_INSTR_BLOCK_BOUNDARY_FLAG: u32 = 1 << 0; @@ -643,16 +643,14 @@ fn jit_find_basic_blocks( } } - let mut basic_blocks: Vec = - basic_blocks.into_iter().map(|(_, block)| block).collect(); - - basic_blocks.sort_by_key(|block| block.addr); + let basic_blocks: Vec = basic_blocks.into_iter().map(|(_, block)| block).collect(); for i in 0..basic_blocks.len() - 1 { let next_block_addr = basic_blocks[i + 1].addr; let next_block_end_addr = basic_blocks[i + 1].end_addr; let next_block_is_entry = basic_blocks[i + 1].is_entry_block; let block = &basic_blocks[i]; + dbg_assert!(block.addr < next_block_addr); if next_block_addr < block.end_addr { dbg_log!( "Overlapping first=[from={:x} to={:x} is_entry={}] second=[from={:x} to={:x} is_entry={}]", @@ -1045,6 +1043,7 @@ fn jit_generate_module( let ctx = &mut JitContext { cpu: &mut cpu.clone(), builder, + start_of_current_instruction: 0, }; codegen::gen_fn1_const(ctx, "jmp_rel16", jump_offset as u32); } @@ -1108,11 +1107,7 @@ fn jit_generate_basic_block( last_instruction_addr: u32, stop_addr: u32, ) { - let mut len = 0; - - let mut end_addr; - let mut was_block_boundary; - let mut eip_delta = 0; + let mut count = 0; // First iteration of do-while assumes the caller confirms this condition dbg_assert!(!is_near_end_of_page(start_addr)); @@ -1123,6 +1118,19 @@ fn jit_generate_basic_block( if false { ::opstats::gen_opstats(builder, cpu::read32(cpu.eip)); } + + if cpu.eip == last_instruction_addr { + // Before the last instruction: + // - Set eip to *after* the instruction + // - Set previous_eip to *before* the instruction + builder.commit_instruction_body_to_cs(); + codegen::gen_set_previous_eip_offset_from_eip( + builder, + last_instruction_addr - start_addr, + ); + codegen::gen_increment_instruction_pointer(builder, stop_addr - start_addr); + } + let start_eip = cpu.eip; let mut instruction_flags = 0; jit_instructions::jit_instruction(&mut cpu, builder, &mut instruction_flags); @@ -1141,55 +1149,18 @@ fn jit_generate_basic_block( } let instruction_length = end_eip - start_eip; - was_block_boundary = instruction_flags & JIT_INSTR_BLOCK_BOUNDARY_FLAG != 0; + let was_block_boundary = instruction_flags & JIT_INSTR_BLOCK_BOUNDARY_FLAG != 0; dbg_assert!((end_eip == stop_addr) == (start_eip == last_instruction_addr)); - dbg_assert!(instruction_length < MAX_INSTRUCTION_LENGTH); - if ENABLE_JIT_NONFAULTING_OPTIMZATION { - // There are a few conditions to keep in mind to optimize the update of previous_ip and - // instruction_pointer: - // - previous_ip MUST be updated just before a faulting instruction - // - instruction_pointer MUST be updated before jump instructions (since they use the EIP - // value for instruction logic) - // - Nonfaulting instructions don't need either to be updated - if was_block_boundary { - // prev_ip = eip + eip_delta, so that previous_ip points to the start of this instruction - codegen::gen_set_previous_eip_offset_from_eip(builder, eip_delta); - - // eip += eip_delta + len(jump) so instruction logic uses the correct eip - codegen::gen_increment_instruction_pointer(builder, eip_delta + instruction_length); - builder.commit_instruction_body_to_cs(); - - eip_delta = 0; - } - else if instruction_flags & JIT_INSTR_NONFAULTING_FLAG == 0 { - // Faulting instruction - - // prev_ip = eip + eip_delta, so that previous_ip points to the start of this instruction - codegen::gen_set_previous_eip_offset_from_eip(builder, eip_delta); - builder.commit_instruction_body_to_cs(); - - // Leave this instruction's length to be updated in the next batch, whatever it may be - eip_delta += instruction_length; - } - else { - // Non-faulting, so we skip setting previous_ip and simply queue the instruction length - // for whenever eip is updated next - profiler::stat_increment(stat::S_NONFAULTING_OPTIMIZATION); - eip_delta += instruction_length; - } - } - else { - codegen::gen_set_previous_eip(builder); - codegen::gen_increment_instruction_pointer(builder, instruction_length); - builder.commit_instruction_body_to_cs(); - } - end_addr = cpu.eip; - len += 1; + let end_addr = cpu.eip; + count += 1; if end_addr == stop_addr { + // no page was crossed + dbg_assert!(Page::page_of(end_addr) == Page::page_of(start_addr)); + break; } @@ -1201,18 +1172,7 @@ fn jit_generate_basic_block( } } - if ENABLE_JIT_NONFAULTING_OPTIMZATION { - // When the block ends in a non-jump instruction, we may have uncommitted updates still - if eip_delta > 0 { - builder.commit_instruction_body_to_cs(); - codegen::gen_increment_instruction_pointer(builder, eip_delta); - } - } - - codegen::gen_increment_timestamp_counter(builder, len); - - // no page was crossed - dbg_assert!(Page::page_of(end_addr) == Page::page_of(start_addr)); + codegen::gen_increment_timestamp_counter(builder, count); } pub fn jit_increase_hotness_and_maybe_compile( diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 6d55a6c3..3b8cf496 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -16,7 +16,12 @@ use wasmgen::wasm_util::WasmBuf; pub fn jit_instruction(cpu: &mut CpuContext, builder: &mut WasmBuilder, instr_flags: &mut u32) { cpu.prefixes = 0; - let ctx = &mut JitContext { cpu, builder }; + let start_of_current_instruction = cpu.eip; + let ctx = &mut JitContext { + cpu, + builder, + start_of_current_instruction, + }; ::gen::jit::jit( ctx.cpu.read_imm8() as u32 | (ctx.cpu.osize_32() as u32) << 8, ctx, diff --git a/tests/expect/tests/call.wast b/tests/expect/tests/call.wast index 5bd45076..70368885 100644 --- a/tests/expect/tests/call.wast +++ b/tests/expect/tests/call.wast @@ -33,6 +33,12 @@ (i32.load (i32.const 556)) (i32.const 5))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) (set_local $l0 (i32.sub (i32.load @@ -75,6 +81,14 @@ (get_local $l2)) (get_local $l0))) (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 0))) (call $e.safe_write32_slow_jit (get_local $l2) (get_local $l0)) @@ -92,12 +106,6 @@ (i32.load (i32.const 556)) (i32.const 1))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 1))) (set_local $p0 (i32.const 2)) (br $L0)) @@ -111,14 +119,15 @@ (i32.load (i32.const 556)) (i32.const 1))) - (call $e.instr_F4) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 1))) + (call $e.instr_F4) (return)) + (call $e.instr32_40) (i32.store (i32.const 560) (i32.add @@ -131,7 +140,12 @@ (i32.load (i32.const 556)) (i32.const 2))) - (call $e.instr32_40) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 2))) (i32.const 556) (i32.load (i32.const 740)) @@ -167,6 +181,14 @@ (i32.const -4096)) (get_local $l1)))) (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 7))) (call $e.safe_read32s_slow_jit (get_local $l1)) (if $I8 @@ -181,11 +203,5 @@ (i32.const 4))) (i32.add) (i32.store) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 2))) (return)) (unreachable)))) diff --git a/tests/expect/tests/do-while.wast b/tests/expect/tests/do-while.wast index cdcbb760..6a43b5f1 100644 --- a/tests/expect/tests/do-while.wast +++ b/tests/expect/tests/do-while.wast @@ -23,6 +23,7 @@ (block $B4 (br_table $B4 $B3 $B2 $B1 (get_local $p0))) + (call $e.instr32_43) (i32.store (i32.const 560) (i32.add @@ -35,16 +36,15 @@ (i32.load (i32.const 556)) (i32.const 4))) - (call $e.instr32_43) - (call $e.instr32_83_7_reg - (i32.const 0) - (i32.const 10)) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 2))) + (call $e.instr32_83_7_reg + (i32.const 0) + (i32.const 10)) (return)) (i32.store (i32.const 560) @@ -87,12 +87,12 @@ (i32.load (i32.const 556)) (i32.const 1))) - (call $e.instr_F4) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 1))) + (call $e.instr_F4) (return)) (unreachable)))) diff --git a/tests/expect/tests/if.wast b/tests/expect/tests/if.wast index 60e6f7d4..5aaf0f18 100644 --- a/tests/expect/tests/if.wast +++ b/tests/expect/tests/if.wast @@ -35,15 +35,15 @@ (i32.load (i32.const 556)) (i32.const 3))) - (call $e.instr32_83_7_reg - (i32.const 0) - (i32.const 5)) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 1))) + (call $e.instr32_83_7_reg + (i32.const 0) + (i32.const 5)) (return)) (i32.store (i32.const 560) @@ -76,7 +76,10 @@ (set_local $p0 (i32.const 2)))) (br $L0)) - (call $e.instr32_41) + (i32.store + (i32.const 560) + (i32.load + (i32.const 556))) (i32.store (i32.const 556) (i32.add @@ -89,9 +92,11 @@ (i32.load (i32.const 664)) (i32.const 1))) + (call $e.instr32_41) (set_local $p0 (i32.const 3)) (br $L0)) + (call $e.instr32_43) (i32.store (i32.const 560) (i32.add @@ -104,13 +109,12 @@ (i32.load (i32.const 556)) (i32.const 2))) - (call $e.instr32_43) - (call $e.instr_F4) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 2))) + (call $e.instr_F4) (return)) (unreachable)))) diff --git a/tests/expect/tests/indirect-call.wast b/tests/expect/tests/indirect-call.wast index 04d08758..f5f00765 100644 --- a/tests/expect/tests/indirect-call.wast +++ b/tests/expect/tests/indirect-call.wast @@ -30,18 +30,18 @@ (i32.load (i32.const 556)) (i32.const 2))) - (call $e.instr32_FF_2_mem - (i32.add - (i32.load - (i32.const 4)) - (call $e.get_seg - (i32.const 3)))) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 1))) + (call $e.instr32_FF_2_mem + (i32.add + (i32.load + (i32.const 4)) + (call $e.get_seg + (i32.const 3)))) (return)) (i32.store (i32.const 560) @@ -53,12 +53,12 @@ (i32.load (i32.const 556)) (i32.const 1))) - (call $e.instr_F4) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 1))) + (call $e.instr_F4) (return)) (unreachable)))) diff --git a/tests/expect/tests/mov16.wast b/tests/expect/tests/mov16.wast index c6acebc5..7b415887 100644 --- a/tests/expect/tests/mov16.wast +++ b/tests/expect/tests/mov16.wast @@ -21,12 +21,6 @@ (block $B2 (br_table $B2 $B1 (get_local $p0))) - (i32.store - (i32.const 560) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 3))) (call $e.instr16_B8 (i32.const 51966)) (i32.store16 @@ -61,6 +55,14 @@ (i32.const -4096)) (get_local $l0)))) (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 3))) (call $e.safe_read16_slow_jit (get_local $l0)) (if $I4 @@ -68,12 +70,6 @@ (i32.const 540)) (then (return)))))) - (i32.store - (i32.const 560) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 7))) (i32.store16 (i32.const 12) (if $I5 (result i32) @@ -106,6 +102,14 @@ (i32.const -4096)) (get_local $l1)))) (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 7))) (call $e.safe_read16_slow_jit (get_local $l1)) (if $I6 @@ -113,12 +117,6 @@ (i32.const 540)) (then (return)))))) - (i32.store - (i32.const 560) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 19))) (i32.store16 (i32.const 32) (i32.const 36)) @@ -166,6 +164,14 @@ (get_local $l0)) (get_local $l1))) (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 19))) (call $e.safe_write16_slow_jit (get_local $l0) (get_local $l1)) @@ -174,12 +180,6 @@ (i32.const 540)) (then (return))))) - (i32.store - (i32.const 560) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 21))) (set_local $l1 (i32.add (i32.and @@ -221,6 +221,14 @@ (get_local $l1)) (get_local $l0))) (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 21))) (call $e.safe_write16_slow_jit (get_local $l1) (get_local $l0)) @@ -229,18 +237,6 @@ (i32.const 540)) (then (return))))) - (i32.store - (i32.const 560) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 31))) - (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 32))) (i32.store16 (i32.const 8) (i32.load16_u @@ -257,12 +253,24 @@ (i32.const 4) (i32.load16_u (i32.const 8))) - (call $e.instr_F4) + (i32.store + (i32.const 560) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 31))) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 32))) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 12))) + (call $e.instr_F4) (return)) (unreachable)))) diff --git a/tests/expect/tests/mov32-mem.wast b/tests/expect/tests/mov32-mem.wast index 183987e9..34437751 100644 --- a/tests/expect/tests/mov32-mem.wast +++ b/tests/expect/tests/mov32-mem.wast @@ -20,10 +20,6 @@ (block $B2 (br_table $B2 $B1 (get_local $p0))) - (i32.store - (i32.const 560) - (i32.load - (i32.const 556))) (set_local $l0 (i32.add (i32.add @@ -62,6 +58,14 @@ (get_local $l0)) (get_local $l1))) (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 0))) (call $e.safe_write32_slow_jit (get_local $l0) (get_local $l1)) @@ -70,12 +74,6 @@ (i32.const 540)) (then (return))))) - (i32.store - (i32.const 560) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 6))) (set_local $l1 (i32.add (i32.add @@ -114,6 +112,14 @@ (get_local $l1)) (get_local $l0))) (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 6))) (call $e.safe_write32_slow_jit (get_local $l1) (get_local $l0)) @@ -122,12 +128,6 @@ (i32.const 540)) (then (return))))) - (i32.store - (i32.const 560) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 12))) (i32.store (i32.const 28) (if $I7 (result i32) @@ -163,6 +163,14 @@ (i32.const -4096)) (get_local $l0)))) (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 12))) (call $e.safe_read32s_slow_jit (get_local $l0)) (if $I8 @@ -170,12 +178,6 @@ (i32.const 540)) (then (return)))))) - (i32.store - (i32.const 560) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 18))) (i32.store (i32.const 32) (if $I9 (result i32) @@ -211,6 +213,14 @@ (i32.const -4096)) (get_local $l1)))) (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 18))) (call $e.safe_read32s_slow_jit (get_local $l1)) (if $I10 @@ -230,12 +240,12 @@ (i32.load (i32.const 556)) (i32.const 25))) - (call $e.instr_F4) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 5))) + (call $e.instr_F4) (return)) (unreachable)))) diff --git a/tests/expect/tests/mov32-reg.wast b/tests/expect/tests/mov32-reg.wast index 789e9eaa..a321c8ab 100644 --- a/tests/expect/tests/mov32-reg.wast +++ b/tests/expect/tests/mov32-reg.wast @@ -22,18 +22,6 @@ (block $B2 (br_table $B2 $B1 (get_local $p0))) - (i32.store - (i32.const 560) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 28))) - (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 29))) (call $e.instr32_B8 (i32.const -889270259)) (call $e.instr32_B9 @@ -58,12 +46,24 @@ (i32.const 4) (i32.load (i32.const 8))) - (call $e.instr_F4) + (i32.store + (i32.const 560) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 28))) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 29))) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 9))) + (call $e.instr_F4) (return)) (unreachable)))) diff --git a/tests/expect/tests/pop.wast b/tests/expect/tests/pop.wast index 0f082bda..1845d684 100644 --- a/tests/expect/tests/pop.wast +++ b/tests/expect/tests/pop.wast @@ -19,10 +19,6 @@ (block $B2 (br_table $B2 $B1 (get_local $p0))) - (i32.store - (i32.const 560) - (i32.load - (i32.const 556))) (i32.const 4) (if $I3 (result i32) (i32.and @@ -56,6 +52,14 @@ (i32.const -4096)) (get_local $l1)))) (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 0))) (call $e.safe_read32s_slow_jit (get_local $l1)) (if $I4 @@ -81,12 +85,12 @@ (i32.load (i32.const 556)) (i32.const 2))) - (call $e.instr_F4) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 2))) + (call $e.instr_F4) (return)) (unreachable)))) diff --git a/tests/expect/tests/push.wast b/tests/expect/tests/push.wast index 0804b0c5..74cdf8d5 100644 --- a/tests/expect/tests/push.wast +++ b/tests/expect/tests/push.wast @@ -19,10 +19,6 @@ (block $B2 (br_table $B2 $B1 (get_local $p0))) - (i32.store - (i32.const 560) - (i32.load - (i32.const 556))) (set_local $l0 (i32.load (i32.const 4))) @@ -62,6 +58,14 @@ (get_local $l2)) (get_local $l0))) (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 0))) (call $e.safe_write32_slow_jit (get_local $l2) (get_local $l0)) @@ -85,12 +89,12 @@ (i32.load (i32.const 556)) (i32.const 2))) - (call $e.instr_F4) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 2))) + (call $e.instr_F4) (return)) (unreachable)))) diff --git a/tests/expect/tests/task_switch_test.wast b/tests/expect/tests/task_switch_test.wast index a7103237..847a3977 100644 --- a/tests/expect/tests/task_switch_test.wast +++ b/tests/expect/tests/task_switch_test.wast @@ -31,6 +31,12 @@ (i32.load (i32.const 556)) (i32.const 2))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) (if $I4 (i32.and (i32.load @@ -41,12 +47,6 @@ (return))) (call $e.instr_DE_0_reg (i32.const 1)) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 1))) (return)) (i32.store (i32.const 560) @@ -58,12 +58,12 @@ (i32.load (i32.const 556)) (i32.const 1))) - (call $e.instr_F4) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 1))) + (call $e.instr_F4) (return)) (unreachable)))) diff --git a/tests/expect/tests/task_switch_test_sse.wast b/tests/expect/tests/task_switch_test_sse.wast index 6bb7f7b3..fa596b56 100644 --- a/tests/expect/tests/task_switch_test_sse.wast +++ b/tests/expect/tests/task_switch_test_sse.wast @@ -31,6 +31,12 @@ (i32.load (i32.const 556)) (i32.const 4))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) (i32.store (i32.const 648) (i32.or @@ -51,12 +57,6 @@ (i32.store (i32.const 648) (i32.const 0)) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 1))) (return)) (i32.store (i32.const 560) @@ -68,12 +68,12 @@ (i32.load (i32.const 556)) (i32.const 1))) - (call $e.instr_F4) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 1))) + (call $e.instr_F4) (return)) (unreachable)))) diff --git a/tests/expect/tests/while-do.wast b/tests/expect/tests/while-do.wast index 37c81c40..ef7c40d3 100644 --- a/tests/expect/tests/while-do.wast +++ b/tests/expect/tests/while-do.wast @@ -34,15 +34,15 @@ (i32.load (i32.const 556)) (i32.const 3))) - (call $e.instr32_83_7_reg - (i32.const 0) - (i32.const 10)) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 1))) + (call $e.instr32_83_7_reg + (i32.const 0) + (i32.const 10)) (return)) (i32.store (i32.const 560) @@ -75,6 +75,7 @@ (set_local $p0 (i32.const 2)))) (br $L0)) + (call $e.instr32_43) (i32.store (i32.const 560) (i32.add @@ -87,19 +88,18 @@ (i32.load (i32.const 556)) (i32.const 3))) - (call $e.instr32_43) - (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const -8))) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 2))) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const -8))) (set_local $p0 (i32.const 0)) (br $L0)) @@ -113,12 +113,12 @@ (i32.load (i32.const 556)) (i32.const 1))) - (call $e.instr_F4) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 1))) + (call $e.instr_F4) (return)) (unreachable)))) From 75eecd0d63734ea2660eacc071eaca8931bac198 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 21 Aug 2018 18:11:43 -0500 Subject: [PATCH 1214/2137] Multiboot loader: Skip sections outside of memory --- src/cpu.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index 59131eb8..e5f50f3c 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -1007,12 +1007,18 @@ CPU.prototype.load_multiboot = function(buffer) // virtual and physical address must be equal dbg_assert(program.paddr === program.vaddr); dbg_assert(program.filesz <= program.memsz); - dbg_assert(program.paddr + program.memsz < this.memory_size[0]); - if(program.filesz) // offset mighty be outside of buffer if filesz is 0 + if(program.paddr + program.memsz < this.memory_size[0]) { - let blob = new Uint8Array(buffer, program.offset, program.filesz); - this.write_blob(blob, program.paddr); + if(program.filesz) // offset might be outside of buffer if filesz is 0 + { + let blob = new Uint8Array(buffer, program.offset, program.filesz); + this.write_blob(blob, program.paddr); + } + } + else + { + dbg_log("Warning: Skipped loading section, paddr=" + h(program.paddr) + " memsz=" + program.memsz, LOG_CPU); } } else if( From 3c903338c375cdf7b5ab9d704173d2f062678f4d Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 21 Aug 2018 18:35:41 -0500 Subject: [PATCH 1215/2137] c2rust cleanup: Call more functions directly --- src/cpu.js | 6 +++++- src/rust/c_api.rs | 7 ++----- src/rust/cpu2/cpu.rs | 21 +++++++++------------ src/rust/cpu2/memory.rs | 19 +++++++------------ 4 files changed, 23 insertions(+), 30 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index e5f50f3c..249f2610 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -344,7 +344,11 @@ CPU.prototype.wasm_patch = function(wm) this.pack_current_state_flags = get_import("pack_current_state_flags"); - this.jit_force_generate_unsafe = get_import("jit_force_generate_unsafe"); + if(DEBUG) + { + this.jit_force_generate_unsafe = get_import("jit_force_generate_unsafe"); + } + this.jit_empty_cache = get_import("jit_empty_cache"); this.jit_dirty_cache = get_import("jit_dirty_cache"); this.codegen_finalize_finished = get_import("codegen_finalize_finished"); diff --git a/src/rust/c_api.rs b/src/rust/c_api.rs index be2f8d01..3fa815f1 100644 --- a/src/rust/c_api.rs +++ b/src/rust/c_api.rs @@ -25,7 +25,6 @@ pub fn rust_setup() { })); } -#[no_mangle] pub fn jit_find_cache_entry(phys_address: u32, state_flags: u32) -> u32 { let cached_code { wasm_table_index, @@ -53,7 +52,6 @@ pub fn codegen_finalize_finished( ) } -#[no_mangle] pub fn jit_increase_hotness_and_maybe_compile(phys_address: u32, cs_offset: u32, state_flags: u32) { ::jit::jit_increase_hotness_and_maybe_compile( get_module(), @@ -65,6 +63,7 @@ pub fn jit_increase_hotness_and_maybe_compile(phys_address: u32, cs_offset: u32, #[no_mangle] #[cfg(debug_assertions)] +/// Called from JS pub fn jit_force_generate_unsafe(phys_addr: u32, cs_offset: u32, state_flags: u32) { ::jit::jit_force_generate_unsafe( get_module(), @@ -75,19 +74,17 @@ pub fn jit_force_generate_unsafe(phys_addr: u32, cs_offset: u32, state_flags: u3 } #[no_mangle] +/// Called from JS pub fn jit_dirty_cache(start_addr: u32, end_addr: u32) { ::jit::jit_dirty_cache(get_module(), start_addr, end_addr); } -#[no_mangle] pub fn jit_dirty_cache_small(start_addr: u32, end_addr: u32) { ::jit::jit_dirty_cache_small(get_module(), start_addr, end_addr); } -#[no_mangle] pub fn jit_dirty_cache_single(addr: u32) { ::jit::jit_dirty_cache_single(get_module(), addr); } -#[no_mangle] pub fn jit_page_has_code(page: u32) -> bool { ::jit::jit_page_has_code(get_module(), Page::page_of(page << 12)) } diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 35052a58..71b86804 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -20,13 +20,6 @@ extern "C" { fn microtick() -> f64; #[no_mangle] fn call_indirect1(f: i32, x: u16); - - #[no_mangle] - fn jit_page_has_code(addr: u32) -> bool; - #[no_mangle] - fn jit_find_cache_entry(addr: u32, flags: u8) -> u32; - #[no_mangle] - fn jit_increase_hotness_and_maybe_compile(phys_address: u32, cs_offset: u32, state_flags: u8); } use cpu2::global_pointers::*; @@ -422,7 +415,7 @@ pub unsafe fn do_page_translation( let mut is_in_mapped_range: bool = in_mapped_range(high as u32); let mut physical_page: i32 = (high as u32 >> 12i32) as i32; let mut has_code: bool = - !is_in_mapped_range && 0 != jit_page_has_code(physical_page as u32) as i32; + !is_in_mapped_range && 0 != ::c_api::jit_page_has_code(physical_page as u32) as i32; let mut info_bits: i32 = TLB_VALID | if 0 != can_write as i32 { 0i32 @@ -778,7 +771,7 @@ pub unsafe fn cycle_internal() -> () { *previous_ip = *instruction_pointer; let mut phys_addr: u32 = return_on_pagefault!(get_phys_eip()) as u32; let mut state_flags: cached_state_flags = pack_current_state_flags(); - let mut entry: u32 = jit_find_cache_entry(phys_addr, state_flags); + let mut entry: u32 = ::c_api::jit_find_cache_entry(phys_addr, state_flags as u32); if 0 != entry { profiler_stat_increment(S_RUN_FROM_CACHE); initial_tsc = *timestamp_counter as i32; @@ -799,7 +792,11 @@ pub unsafe fn cycle_internal() -> () { dbg_assert!(!must_not_fault); must_not_fault = 0 != 1i32 } - jit_increase_hotness_and_maybe_compile(phys_addr, get_seg_cs() as u32, state_flags); + ::c_api::jit_increase_hotness_and_maybe_compile( + phys_addr, + get_seg_cs() as u32, + state_flags as u32, + ); if DEBUG { dbg_assert!(must_not_fault); must_not_fault = 0 != 0i32 @@ -1179,7 +1176,7 @@ pub unsafe fn safe_write16(mut address: i32, mut value: i32) -> Result<(), ()> { c_comment!(("- can be accessed from any cpl")); c_comment!(("- does not contain code")); let mut phys_address: u32 = (entry & !4095i32 ^ address) as u32; - dbg_assert!(!jit_page_has_code(phys_address >> 12i32)); + dbg_assert!(!::c_api::jit_page_has_code(phys_address >> 12i32)); dbg_assert!(!in_mapped_range(phys_address)); *(mem8.offset(phys_address as isize) as *mut u16) = value as u16; } @@ -1223,7 +1220,7 @@ pub unsafe fn safe_write32(mut address: i32, mut value: i32) -> Result<(), ()> { c_comment!(("- not in memory mapped area")); c_comment!(("- does not contain code")); let mut phys_address: u32 = (entry & !4095i32 ^ address) as u32; - dbg_assert!(!jit_page_has_code(phys_address >> 12i32)); + dbg_assert!(!::c_api::jit_page_has_code(phys_address >> 12i32)); dbg_assert!(!in_mapped_range(phys_address)); *(mem8.offset(phys_address as isize) as *mut i32) = value; } diff --git a/src/rust/cpu2/memory.rs b/src/rust/cpu2/memory.rs index 7a6d22dd..1012bc8a 100644 --- a/src/rust/cpu2/memory.rs +++ b/src/rust/cpu2/memory.rs @@ -23,11 +23,6 @@ extern "C" { fn mmap_write32(addr: u32, value: i32); #[no_mangle] fn mmap_write128(addr: u32, v0: i32, v1: i32, v2: i32, v3: i32); - - #[no_mangle] - fn jit_dirty_cache_small(low: u32, high: u32); - #[no_mangle] - fn jit_dirty_cache_single(addr: u32); } use cpu2::cpu::*; @@ -144,7 +139,7 @@ pub unsafe fn write8(mut addr: u32, mut value: i32) -> () { mmap_write8(addr, value); } else { - jit_dirty_cache_single(addr); + ::c_api::jit_dirty_cache_single(addr); *mem8.offset(addr as isize) = value as u8 }; } @@ -157,7 +152,7 @@ pub unsafe fn write16(mut addr: u32, mut value: i32) -> () { mmap_write16(addr, value); } else { - jit_dirty_cache_small(addr, addr.wrapping_add(2i32 as u32)); + ::c_api::jit_dirty_cache_small(addr, addr.wrapping_add(2i32 as u32)); *(mem8.offset(addr as isize) as *mut u16) = value as u16 }; } @@ -172,7 +167,7 @@ pub unsafe fn write_aligned16(mut addr: u32, mut value: u32) -> () { mmap_write16(phys_addr, value as i32); } else { - jit_dirty_cache_small(phys_addr, phys_addr.wrapping_add(2i32 as u32)); + ::c_api::jit_dirty_cache_small(phys_addr, phys_addr.wrapping_add(2i32 as u32)); *mem16.offset(addr as isize) = value as u16 }; } @@ -185,7 +180,7 @@ pub unsafe fn write32(mut addr: u32, mut value: i32) -> () { mmap_write32(addr, value); } else { - jit_dirty_cache_small(addr, addr.wrapping_add(4i32 as u32)); + ::c_api::jit_dirty_cache_small(addr, addr.wrapping_add(4i32 as u32)); *(mem8.offset(addr as isize) as *mut i32) = value }; } @@ -200,7 +195,7 @@ pub unsafe fn write_aligned32(mut addr: u32, mut value: i32) -> () { mmap_write32(phys_addr, value); } else { - jit_dirty_cache_small(phys_addr, phys_addr.wrapping_add(4i32 as u32)); + ::c_api::jit_dirty_cache_small(phys_addr, phys_addr.wrapping_add(4i32 as u32)); *mem32s.offset(addr as isize) = value }; } @@ -217,7 +212,7 @@ pub unsafe fn write64(mut addr: u32, mut value: i64) -> () { mmap_write32(addr.wrapping_add(4i32 as u32), (value >> 32i32) as i32); } else { - jit_dirty_cache_small(addr, addr.wrapping_add(8i32 as u32)); + ::c_api::jit_dirty_cache_small(addr, addr.wrapping_add(8i32 as u32)); *(mem8.offset(addr as isize) as *mut i64) = value }; } @@ -236,7 +231,7 @@ pub unsafe fn write128(mut addr: u32, mut value: reg128) -> () { ); } else { - jit_dirty_cache_small(addr, addr.wrapping_add(16i32 as u32)); + ::c_api::jit_dirty_cache_small(addr, addr.wrapping_add(16i32 as u32)); *(mem8.offset(addr as isize) as *mut i64) = value.i64_0[0usize]; *(mem8.offset(addr as isize).offset(8isize) as *mut i64) = value.i64_0[1usize] }; From fbd5e136e1aa9a1c34311d9287d1e131baca24c7 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 23 Aug 2018 10:20:45 -0500 Subject: [PATCH 1216/2137] Temporarily increase JIT_THRESHOLD to account for marking a lot of instructions as block boundary --- src/rust/jit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 1f1d29e4..5c69ccd9 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -24,7 +24,7 @@ pub const JIT_MAX_ITERATIONS_PER_FUNCTION: u32 = 10000; pub const JIT_ALWAYS_USE_LOOP_SAFETY: bool = false; -pub const JIT_THRESHOLD: u32 = 2500; +pub const JIT_THRESHOLD: u32 = 10 * 2500; const CONDITION_FUNCTIONS: [&str; 16] = [ "test_o", "test_no", "test_b", "test_nb", "test_z", "test_nz", "test_be", "test_nbe", "test_s", From 80e339d54c960456074c9d1d7fece02431dc2c8d Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 23 Aug 2018 17:18:00 +0530 Subject: [PATCH 1217/2137] rust-lld-wrapper: Remove export-table to prevent conflict Without this patch, the following error is thrown: rust-lld: error: --import-table and --export-table may not be used together Tested on the following nightly versions: rustc 1.30.0-nightly (7e8ca9f8b 2018-08-03) rustc 1.30.0-nightly (33b923fd4 2018-08-18) --- tools/rust-lld-wrapper | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/rust-lld-wrapper b/tools/rust-lld-wrapper index 7e6aac30..e86cba96 100755 --- a/tools/rust-lld-wrapper +++ b/tools/rust-lld-wrapper @@ -12,6 +12,7 @@ def main(): # filter out args inserted by rustc TO_REMOVE = { + "--export-table", "--stack-first", "--strip-debug", # TODO: Make this configurable } From 71524d1d2cc4018f6ec9baffc5fc5e9352bd7da2 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 21 Aug 2018 19:01:39 -0500 Subject: [PATCH 1218/2137] Use gen_jmp_rel16 for generating jumps in 16-bit mode --- src/rust/jit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 5c69ccd9..9a227fc5 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -1045,7 +1045,7 @@ fn jit_generate_module( builder, start_of_current_instruction: 0, }; - codegen::gen_fn1_const(ctx, "jmp_rel16", jump_offset as u32); + codegen::gen_jmp_rel16(ctx, jump_offset as u16); } if let Some(next_block_branch_taken_addr) = next_block_branch_taken_addr { From b0eff6b9511712d826cdb8a39dfd0db738002bee Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 21 Aug 2018 19:36:44 -0500 Subject: [PATCH 1219/2137] Implement 8-bit memory accesses --- gen/x86_table.js | 8 +-- src/rust/codegen.rs | 78 ++++++++++++++++++----- src/rust/cpu.rs | 1 + src/rust/cpu2/cpu.rs | 22 +++++++ src/rust/global_pointers.rs | 4 ++ src/rust/jit_instructions.rs | 114 ++++++++++++++++++++++++++++++++++ src/rust/wasmgen/wasm_util.rs | 20 ++++-- 7 files changed, 222 insertions(+), 25 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 72134f02..b6cb886f 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -101,9 +101,9 @@ const encodings = [ { opcode: 0x85, nonfaulting: 1, os: 1, e: 1, }, { opcode: 0x86, nonfaulting: 1, e: 1, }, { opcode: 0x87, nonfaulting: 1, os: 1, e: 1, }, - { opcode: 0x88, nonfaulting: 1, e: 1, }, + { opcode: 0x88, custom: 1, nonfaulting: 1, e: 1, }, { opcode: 0x89, custom: 1, nonfaulting: 1, os: 1, e: 1, }, - { opcode: 0x8A, nonfaulting: 1, e: 1, }, + { opcode: 0x8A, custom: 1, nonfaulting: 1, e: 1, }, { opcode: 0x8B, custom: 1, nonfaulting: 1, os: 1, e: 1, }, { opcode: 0x8C, block_boundary: 1, os: 1, e: 1, skip: 1, }, // mov reg, sreg: block_boundary as it can trigger #ud @@ -447,7 +447,7 @@ const encodings = [ { opcode: 0x0FB4, block_boundary: 1, os: 1, e: 1, skip: 1, }, // lfs { opcode: 0x0FB5, block_boundary: 1, os: 1, e: 1, skip: 1, }, // lgs - { opcode: 0x0FB6, nonfaulting: 1, os: 1, e: 1, }, // movzx + { opcode: 0x0FB6, nonfaulting: 1, os: 1, e: 1, custom: 1 }, // movzx { opcode: 0x0FB7, nonfaulting: 1, os: 1, e: 1, }, { opcode: 0xF30FB8, os: 1, e: 1 }, // popcnt @@ -455,7 +455,7 @@ const encodings = [ { opcode: 0x0FB9, block_boundary: 1, }, // ud2 - { opcode: 0x0FBE, nonfaulting: 1, os: 1, e: 1, }, // movsx + { opcode: 0x0FBE, nonfaulting: 1, os: 1, e: 1, custom: 1 }, // movsx { opcode: 0x0FBF, nonfaulting: 1, os: 1, e: 1, }, { opcode: 0x0FC0, nonfaulting: 1, e: 1, }, // xadd diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index e05b2f8d..9f4c642a 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -65,6 +65,14 @@ pub fn gen_increment_mem32(builder: &mut WasmBuilder, addr: u32) { builder.code_section.increment_mem32(addr) } +/// sign-extend a byte value on the stack and leave it on the stack +pub fn sign_extend_i8(builder: &mut WasmBuilder) { + builder.instruction_body.push_i32(24); + builder.instruction_body.shl_i32(); + builder.instruction_body.push_i32(24); + builder.instruction_body.shr_i32(); +} + pub fn gen_fn0_const(ctx: &mut JitContext, name: &str) { let builder = &mut ctx.builder; let fn_idx = builder.get_fn_idx(name, module_init::FN0_TYPE_INDEX); @@ -138,6 +146,17 @@ pub fn gen_modrm_fn2(ctx: &mut JitContext, name: &str, arg0: u32, arg1: u32) { pub fn gen_modrm_resolve(ctx: &mut JitContext, modrm_byte: u8) { modrm::gen(ctx, modrm_byte) } +pub fn gen_set_reg8_r(ctx: &mut JitContext, dest: u32, src: u32) { + // generates: reg8[r_dest] = reg8[r_src] + let builder = &mut ctx.builder; + builder + .instruction_body + .push_i32(global_pointers::get_reg8_offset(dest) as i32); + builder + .instruction_body + .load_u8(global_pointers::get_reg8_offset(src)); + builder.instruction_body.store_u8(0); +} pub fn gen_set_reg16_r(ctx: &mut JitContext, dest: u32, src: u32) { // generates: reg16[r_dest] = reg16[r_src] let builder = &mut ctx.builder; @@ -161,9 +180,13 @@ pub fn gen_set_reg32_r(ctx: &mut JitContext, dest: u32, src: u32) { builder.instruction_body.store_aligned_i32(); } +pub fn gen_safe_read8(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::BYTE) } pub fn gen_safe_read16(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::WORD) } pub fn gen_safe_read32(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::DWORD) } +pub fn gen_safe_write8(ctx: &mut JitContext, address_local: &WasmLocal, value_local: &WasmLocal) { + gen_safe_write(ctx, BitSize::BYTE, address_local, value_local) +} pub fn gen_safe_write16(ctx: &mut JitContext, address_local: &WasmLocal, value_local: &WasmLocal) { gen_safe_write(ctx, BitSize::WORD, address_local, value_local) } @@ -193,7 +216,7 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { let entry_local = builder.tee_new_local(); // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && - // (address & 0xFFF) <= (0x1000 - (bitsize / 8)); + // (bitsize == 8 ? true : (address & 0xFFF) <= (0x1000 - (bitsize / 8))); builder.instruction_body.push_i32( (0xFFF & !TLB_READONLY & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32, @@ -203,15 +226,17 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { builder.instruction_body.push_i32(TLB_VALID as i32); builder.instruction_body.eq_i32(); - builder.instruction_body.get_local(&address_local); - builder.instruction_body.push_i32(0xFFF); - builder.instruction_body.and_i32(); - builder - .instruction_body - .push_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 }); - builder.instruction_body.le_i32(); + if bits != BitSize::BYTE { + builder.instruction_body.get_local(&address_local); + builder.instruction_body.push_i32(0xFFF); + builder.instruction_body.and_i32(); + builder + .instruction_body + .push_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 }); + builder.instruction_body.le_i32(); - builder.instruction_body.and_i32(); + builder.instruction_body.and_i32(); + } // Pseudo: // if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]); @@ -223,6 +248,11 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { builder.instruction_body.xor_i32(); match bits { + BitSize::BYTE => { + builder + .instruction_body + .load_u8_from_stack(unsafe { mem8 } as u32); + }, BitSize::WORD => { builder .instruction_body @@ -261,6 +291,9 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { builder.instruction_body.get_local(&address_local); match bits { + BitSize::BYTE => { + gen_call_fn1_ret(builder, "safe_read8_slow_jit"); + }, BitSize::WORD => { gen_call_fn1_ret(builder, "safe_read16_slow_jit"); }, @@ -319,15 +352,17 @@ fn gen_safe_write( builder.instruction_body.push_i32(TLB_VALID as i32); builder.instruction_body.eq_i32(); - builder.instruction_body.get_local(&address_local); - builder.instruction_body.push_i32(0xFFF); - builder.instruction_body.and_i32(); - builder - .instruction_body - .push_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 }); - builder.instruction_body.le_i32(); + if bits != BitSize::BYTE { + builder.instruction_body.get_local(&address_local); + builder.instruction_body.push_i32(0xFFF); + builder.instruction_body.and_i32(); + builder + .instruction_body + .push_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 }); + builder.instruction_body.le_i32(); - builder.instruction_body.and_i32(); + builder.instruction_body.and_i32(); + } // Pseudo: // if(can_use_fast_path) @@ -349,6 +384,9 @@ fn gen_safe_write( builder.instruction_body.get_local(&value_local); match bits { + BitSize::BYTE => { + builder.instruction_body.store_u8(unsafe { mem8 } as u32); + }, BitSize::WORD => { builder .instruction_body @@ -388,6 +426,9 @@ fn gen_safe_write( builder.instruction_body.get_local(&address_local); builder.instruction_body.get_local(&value_local); match bits { + BitSize::BYTE => { + gen_call_fn2(builder, "safe_write8_slow_jit"); + }, BitSize::WORD => { gen_call_fn2(builder, "safe_write16_slow_jit"); }, @@ -778,6 +819,7 @@ fn gen_safe_read_write( let phys_addr_local = builder.tee_new_local(); match bits { + BitSize::BYTE => {}, BitSize::WORD => { builder .instruction_body @@ -797,6 +839,7 @@ fn gen_safe_read_write( // now store the value on stack to phys_addr builder.instruction_body.get_local(&phys_addr_local); match bits { + BitSize::BYTE => {}, BitSize::WORD => { builder .instruction_body @@ -816,6 +859,7 @@ fn gen_safe_read_write( builder.instruction_body.get_local(&address_local); // for writeXX's first arg builder.instruction_body.get_local(&address_local); // for readXX's first arg match bits { + BitSize::BYTE => {}, BitSize::WORD => { gen_call_fn1_ret(builder, "safe_read16_slow"); builder.instruction_body.call_fn(fn_idx); diff --git a/src/rust/cpu.rs b/src/rust/cpu.rs index 674751d3..8de2466a 100644 --- a/src/rust/cpu.rs +++ b/src/rust/cpu.rs @@ -23,6 +23,7 @@ mod unsafe_cpu { #[derive(Copy, Clone, Eq, PartialEq)] pub enum BitSize { + BYTE, WORD, DWORD, } diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 71b86804..8985ac44 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1100,6 +1100,20 @@ pub unsafe fn safe_read32s_slow(mut addr: i32) -> Result { }; } +#[no_mangle] +pub unsafe fn safe_read8_slow_jit(addr: i32) -> i32 { + match safe_read8(addr) { + Ok(v) => { + *page_fault = false; + v + }, + Err(()) => { + *page_fault = true; + -1 + }, + } +} + #[no_mangle] pub unsafe fn safe_read16_slow_jit(addr: i32) -> i32 { match safe_read16_slow(addr) { @@ -1268,6 +1282,14 @@ pub unsafe fn safe_write32_slow(mut addr: i32, mut value: i32) -> Result<(), ()> Ok(()) } +#[no_mangle] +pub unsafe fn safe_write8_slow_jit(addr: i32, value: i32) { + match safe_write8(addr, value) { + Ok(()) => *page_fault = false, + Err(()) => *page_fault = true, + } +} + #[no_mangle] pub unsafe fn safe_write16_slow_jit(addr: i32, value: i32) { match safe_write16_slow(addr, value) { diff --git a/src/rust/global_pointers.rs b/src/rust/global_pointers.rs index e6e7e17e..f1be2ef4 100644 --- a/src/rust/global_pointers.rs +++ b/src/rust/global_pointers.rs @@ -10,6 +10,10 @@ pub const OPSTATS_BUFFER: u32 = 0x1000; pub const OPSTATS_BUFFER_0F: u32 = 0x1400; pub const TLB_DATA: u32 = 0x400000; +pub fn get_reg8_offset(r: u32) -> u32 { + dbg_assert!(r < 8); + REG + (r << 2 & 12 | r >> 2 & 1) +} pub fn get_reg16_offset(r: u32) -> u32 { dbg_assert!(r < 8); REG + 4 * r diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 3b8cf496..4dced0bf 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -232,6 +232,25 @@ pub fn instr32_7E_jit(_ctx: &mut JitContext, _imm: u32) {} pub fn instr16_7F_jit(_ctx: &mut JitContext, _imm: u32) {} pub fn instr32_7F_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr_88_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + + let address_local = ctx.builder.set_new_local(); + + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg8_offset(r) as i32); + ctx.builder.instruction_body.load_u8_from_stack(0); + let value_local = ctx.builder.set_new_local(); + + codegen::gen_safe_write8(ctx, &address_local, &value_local); + ctx.builder.free_local(address_local); + ctx.builder.free_local(value_local); +} +pub fn instr_88_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_set_reg8_r(ctx, r1, r2); +} + pub fn instr16_89_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); @@ -269,6 +288,21 @@ pub fn instr32_89_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_set_reg32_r(ctx, r1, r2); } +pub fn instr_8A_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + // Pseudo: reg8[r] = safe_read8(modrm_resolve(modrm_byte)); + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg8_offset(r) as i32); + + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read8(ctx); + + ctx.builder.instruction_body.store_u8(0); +} +pub fn instr_8A_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_set_reg8_r(ctx, r2, r1); +} + pub fn instr16_8B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { // Pseudo: reg16[r] = safe_read16(modrm_resolve(modrm_byte)); ctx.builder @@ -497,6 +531,86 @@ pub fn instr_0F1F_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) { } pub fn instr_0F1F_reg_jit(_ctx: &mut JitContext, _r1: u32, _r2: u32) {} +pub fn instr16_0FB6_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + let builder = &mut ctx.builder; + builder + .instruction_body + .push_i32(global_pointers::get_reg16_offset(r2) as i32); + builder + .instruction_body + .load_u8(global_pointers::get_reg8_offset(r1)); + builder.instruction_body.store_aligned_u16(); +} +pub fn instr16_0FB6_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg16_offset(r) as i32); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read8(ctx); + ctx.builder.instruction_body.store_aligned_u16(); +} + +pub fn instr32_0FB6_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + let builder = &mut ctx.builder; + builder + .instruction_body + .push_i32(global_pointers::get_reg32_offset(r2) as i32); + builder + .instruction_body + .load_u8(global_pointers::get_reg8_offset(r1)); + builder.instruction_body.store_aligned_i32(); +} +pub fn instr32_0FB6_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg32_offset(r) as i32); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read8(ctx); + ctx.builder.instruction_body.store_aligned_i32(); +} + +pub fn instr16_0FBE_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + let builder = &mut ctx.builder; + builder + .instruction_body + .push_i32(global_pointers::get_reg16_offset(r2) as i32); + builder + .instruction_body + .load_u8(global_pointers::get_reg8_offset(r1)); + codegen::sign_extend_i8(builder); + builder.instruction_body.store_aligned_u16(); +} +pub fn instr16_0FBE_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg16_offset(r) as i32); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read8(ctx); + codegen::sign_extend_i8(ctx.builder); + ctx.builder.instruction_body.store_aligned_u16(); +} + +pub fn instr32_0FBE_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + let builder = &mut ctx.builder; + builder + .instruction_body + .push_i32(global_pointers::get_reg32_offset(r2) as i32); + builder + .instruction_body + .load_u8(global_pointers::get_reg8_offset(r1)); + codegen::sign_extend_i8(builder); + builder.instruction_body.store_aligned_i32(); +} +pub fn instr32_0FBE_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + ctx.builder + .instruction_body + .push_i32(global_pointers::get_reg32_offset(r) as i32); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read8(ctx); + codegen::sign_extend_i8(ctx.builder); + ctx.builder.instruction_body.store_aligned_i32(); +} + pub fn instr16_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { // reg16[r] = imm; ctx.builder diff --git a/src/rust/wasmgen/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs index 1ac91cb5..1e0225a9 100644 --- a/src/rust/wasmgen/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -30,9 +30,11 @@ pub trait WasmBuf { fn load_unaligned_i32_from_stack(&mut self, byte_offset: u32); fn load_unaligned_u16_from_stack(&mut self, byte_offset: u32); fn load_aligned_i32_from_stack(&mut self, byte_offset: u32); - fn load_u8(&mut self, byte_offset: u32); + fn load_u8(&mut self, addr: u32); + fn load_u8_from_stack(&mut self, byte_offset: u32); fn store_unaligned_i32(&mut self, byte_offset: u32); fn store_unaligned_u16(&mut self, byte_offset: u32); + fn store_u8(&mut self, byte_offset: u32); fn shr_u32(&mut self); fn shr_i32(&mut self); fn eqz_i32(&mut self); @@ -91,11 +93,15 @@ impl WasmBuf for Vec { self.load_aligned_i32_from_stack(0); } - fn load_u8(&mut self, addr: u32) { - self.push_i32(addr as i32); + fn load_u8_from_stack(&mut self, byte_offset: u32) { self.push(op::OP_I32LOAD8U); self.push(op::MEM_NO_ALIGN); - self.write_leb_u32(0); + self.write_leb_u32(byte_offset); + } + + fn load_u8(&mut self, addr: u32) { + self.push_i32(addr as i32); + self.load_u8_from_stack(0); } fn store_aligned_u16(&mut self) { @@ -183,6 +189,12 @@ impl WasmBuf for Vec { self.write_leb_u32(byte_offset); } + fn store_u8(&mut self, byte_offset: u32) { + self.push(op::OP_I32STORE8); + self.push(op::MEM_NO_ALIGN); + self.write_leb_u32(byte_offset); + } + fn shr_u32(&mut self) { self.push(op::OP_I32SHRU); } fn shr_i32(&mut self) { self.push(op::OP_I32SHRS); } From ca36680d5253ff993399ae3e6d63696ce7b8e45c Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 21 Aug 2018 20:49:49 -0500 Subject: [PATCH 1220/2137] PAGE_FAULT is u8 --- src/rust/codegen.rs | 2 +- tests/expect/tests/call.wast | 2 +- tests/expect/tests/mov16.wast | 4 ++-- tests/expect/tests/mov32-mem.wast | 4 ++-- tests/expect/tests/pop.wast | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 9f4c642a..f08fccec 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -304,7 +304,7 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { builder .instruction_body - .load_aligned_i32(global_pointers::PAGE_FAULT); + .load_u8(global_pointers::PAGE_FAULT); builder.instruction_body.if_void(); builder.instruction_body.return_(); diff --git a/tests/expect/tests/call.wast b/tests/expect/tests/call.wast index 70368885..a94b7e68 100644 --- a/tests/expect/tests/call.wast +++ b/tests/expect/tests/call.wast @@ -192,7 +192,7 @@ (call $e.safe_read32s_slow_jit (get_local $l1)) (if $I8 - (i32.load + (i32.load8_u (i32.const 540)) (then (return))))) diff --git a/tests/expect/tests/mov16.wast b/tests/expect/tests/mov16.wast index 7b415887..9350974e 100644 --- a/tests/expect/tests/mov16.wast +++ b/tests/expect/tests/mov16.wast @@ -66,7 +66,7 @@ (call $e.safe_read16_slow_jit (get_local $l0)) (if $I4 - (i32.load + (i32.load8_u (i32.const 540)) (then (return)))))) @@ -113,7 +113,7 @@ (call $e.safe_read16_slow_jit (get_local $l1)) (if $I6 - (i32.load + (i32.load8_u (i32.const 540)) (then (return)))))) diff --git a/tests/expect/tests/mov32-mem.wast b/tests/expect/tests/mov32-mem.wast index 34437751..cf0e37f6 100644 --- a/tests/expect/tests/mov32-mem.wast +++ b/tests/expect/tests/mov32-mem.wast @@ -174,7 +174,7 @@ (call $e.safe_read32s_slow_jit (get_local $l0)) (if $I8 - (i32.load + (i32.load8_u (i32.const 540)) (then (return)))))) @@ -224,7 +224,7 @@ (call $e.safe_read32s_slow_jit (get_local $l1)) (if $I10 - (i32.load + (i32.load8_u (i32.const 540)) (then (return)))))) diff --git a/tests/expect/tests/pop.wast b/tests/expect/tests/pop.wast index 1845d684..dfb735f8 100644 --- a/tests/expect/tests/pop.wast +++ b/tests/expect/tests/pop.wast @@ -63,7 +63,7 @@ (call $e.safe_read32s_slow_jit (get_local $l1)) (if $I4 - (i32.load + (i32.load8_u (i32.const 540)) (then (return))))) From 1d24c5952d9a0f097b5f0fa21cd65708b4f29527 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 21 Aug 2018 21:06:52 -0500 Subject: [PATCH 1221/2137] Cleanup of codegen api --- src/rust/codegen.rs | 243 +++++++++++++++++--------------- src/rust/jit.rs | 10 +- src/rust/jit_instructions.rs | 148 +++++++++---------- src/rust/modrm.rs | 52 +++---- src/rust/wasmgen/module_init.rs | 8 +- src/rust/wasmgen/wasm_util.rs | 77 +++++----- 6 files changed, 260 insertions(+), 278 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index f08fccec..d8df9ede 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -15,42 +15,42 @@ extern "C" { pub fn gen_set_previous_eip_offset_from_eip(builder: &mut WasmBuilder, n: u32) { let cs = &mut builder.code_section; - cs.push_i32(global_pointers::PREVIOUS_IP as i32); // store address of previous ip + cs.const_i32(global_pointers::PREVIOUS_IP as i32); // store address of previous ip cs.load_aligned_i32(global_pointers::INSTRUCTION_POINTER); // load ip if n != 0 { - cs.push_i32(n as i32); + cs.const_i32(n as i32); cs.add_i32(); // add constant to ip value } - cs.store_aligned_i32(); // store it as previous ip + cs.store_aligned_i32(0); // store it as previous ip } pub fn gen_increment_instruction_pointer(builder: &mut WasmBuilder, n: u32) { let cs = &mut builder.code_section; - cs.push_i32(global_pointers::INSTRUCTION_POINTER as i32); // store address of ip + cs.const_i32(global_pointers::INSTRUCTION_POINTER as i32); // store address of ip cs.load_aligned_i32(global_pointers::INSTRUCTION_POINTER); // load ip - cs.push_i32(n as i32); + cs.const_i32(n as i32); cs.add_i32(); - cs.store_aligned_i32(); // store it back in + cs.store_aligned_i32(0); // store it back in } pub fn gen_set_previous_eip(builder: &mut WasmBuilder) { let cs = &mut builder.code_section; - cs.push_i32(global_pointers::PREVIOUS_IP as i32); // store address of previous ip + cs.const_i32(global_pointers::PREVIOUS_IP as i32); // store address of previous ip cs.load_aligned_i32(global_pointers::INSTRUCTION_POINTER); // load ip - cs.store_aligned_i32(); // store it as previous ip + cs.store_aligned_i32(0); // store it as previous ip } pub fn gen_relative_jump(builder: &mut WasmBuilder, n: i32) { // add n to instruction_pointer (without setting the offset as above) let instruction_body = &mut builder.instruction_body; - instruction_body.push_i32(global_pointers::INSTRUCTION_POINTER as i32); + instruction_body.const_i32(global_pointers::INSTRUCTION_POINTER as i32); instruction_body.load_aligned_i32(global_pointers::INSTRUCTION_POINTER); - instruction_body.push_i32(n); + instruction_body.const_i32(n); instruction_body.add_i32(); - instruction_body.store_aligned_i32(); + instruction_body.store_aligned_i32(0); } pub fn gen_increment_variable(builder: &mut WasmBuilder, variable_address: u32, n: i32) { @@ -65,12 +65,33 @@ pub fn gen_increment_mem32(builder: &mut WasmBuilder, addr: u32) { builder.code_section.increment_mem32(addr) } +pub fn gen_get_reg8(builder: &mut WasmBuilder, r: u32) { + builder + .instruction_body + .const_i32(global_pointers::get_reg8_offset(r) as i32); + builder.instruction_body.load_u8_from_stack(0); +} + +pub fn gen_get_reg16(builder: &mut WasmBuilder, r: u32) { + builder + .instruction_body + .const_i32(global_pointers::get_reg16_offset(r) as i32); + builder.instruction_body.load_aligned_u16_from_stack(0); +} + +pub fn gen_get_reg32(builder: &mut WasmBuilder, r: u32) { + builder + .instruction_body + .const_i32(global_pointers::get_reg32_offset(r) as i32); + builder.instruction_body.load_aligned_i32_from_stack(0); +} + /// sign-extend a byte value on the stack and leave it on the stack pub fn sign_extend_i8(builder: &mut WasmBuilder) { - builder.instruction_body.push_i32(24); + builder.instruction_body.const_i32(24); builder.instruction_body.shl_i32(); - builder.instruction_body.push_i32(24); - builder.instruction_body.shr_i32(); + builder.instruction_body.const_i32(24); + builder.instruction_body.shr_s_i32(); } pub fn gen_fn0_const(ctx: &mut JitContext, name: &str) { @@ -87,7 +108,7 @@ pub fn gen_fn0_const_ret(builder: &mut WasmBuilder, name: &str) { pub fn gen_fn1_const(ctx: &mut JitContext, name: &str, arg0: u32) { let builder = &mut ctx.builder; let fn_idx = builder.get_fn_idx(name, module_init::FN1_TYPE_INDEX); - builder.instruction_body.push_i32(arg0 as i32); + builder.instruction_body.const_i32(arg0 as i32); builder.instruction_body.call_fn(fn_idx); } @@ -100,8 +121,8 @@ pub fn gen_call_fn1_ret(builder: &mut WasmBuilder, name: &str) { pub fn gen_fn2_const(ctx: &mut JitContext, name: &str, arg0: u32, arg1: u32) { let builder = &mut ctx.builder; let fn_idx = builder.get_fn_idx(name, module_init::FN2_TYPE_INDEX); - builder.instruction_body.push_i32(arg0 as i32); - builder.instruction_body.push_i32(arg1 as i32); + builder.instruction_body.const_i32(arg0 as i32); + builder.instruction_body.const_i32(arg1 as i32); builder.instruction_body.call_fn(fn_idx); } @@ -114,9 +135,9 @@ pub fn gen_call_fn2(builder: &mut WasmBuilder, name: &str) { pub fn gen_fn3_const(ctx: &mut JitContext, name: &str, arg0: u32, arg1: u32, arg2: u32) { let builder = &mut ctx.builder; let fn_idx = builder.get_fn_idx(name, module_init::FN3_TYPE_INDEX); - builder.instruction_body.push_i32(arg0 as i32); - builder.instruction_body.push_i32(arg1 as i32); - builder.instruction_body.push_i32(arg2 as i32); + builder.instruction_body.const_i32(arg0 as i32); + builder.instruction_body.const_i32(arg1 as i32); + builder.instruction_body.const_i32(arg2 as i32); builder.instruction_body.call_fn(fn_idx); } @@ -131,7 +152,7 @@ pub fn gen_modrm_fn1(ctx: &mut JitContext, name: &str, arg0: u32) { // generates: fn( _, arg0 ) let builder = &mut ctx.builder; let fn_idx = builder.get_fn_idx(name, module_init::FN2_TYPE_INDEX); - builder.instruction_body.push_i32(arg0 as i32); + builder.instruction_body.const_i32(arg0 as i32); builder.instruction_body.call_fn(fn_idx); } @@ -139,8 +160,8 @@ pub fn gen_modrm_fn2(ctx: &mut JitContext, name: &str, arg0: u32, arg1: u32) { // generates: fn( _, arg0, arg1 ) let builder = &mut ctx.builder; let fn_idx = builder.get_fn_idx(name, module_init::FN3_TYPE_INDEX); - builder.instruction_body.push_i32(arg0 as i32); - builder.instruction_body.push_i32(arg1 as i32); + builder.instruction_body.const_i32(arg0 as i32); + builder.instruction_body.const_i32(arg1 as i32); builder.instruction_body.call_fn(fn_idx); } @@ -151,10 +172,8 @@ pub fn gen_set_reg8_r(ctx: &mut JitContext, dest: u32, src: u32) { let builder = &mut ctx.builder; builder .instruction_body - .push_i32(global_pointers::get_reg8_offset(dest) as i32); - builder - .instruction_body - .load_u8(global_pointers::get_reg8_offset(src)); + .const_i32(global_pointers::get_reg8_offset(dest) as i32); + gen_get_reg8(builder, src); builder.instruction_body.store_u8(0); } pub fn gen_set_reg16_r(ctx: &mut JitContext, dest: u32, src: u32) { @@ -162,22 +181,18 @@ pub fn gen_set_reg16_r(ctx: &mut JitContext, dest: u32, src: u32) { let builder = &mut ctx.builder; builder .instruction_body - .push_i32(global_pointers::get_reg16_offset(dest) as i32); - builder - .instruction_body - .load_aligned_u16(global_pointers::get_reg16_offset(src)); - builder.instruction_body.store_aligned_u16(); + .const_i32(global_pointers::get_reg16_offset(dest) as i32); + gen_get_reg16(builder, src); + builder.instruction_body.store_aligned_u16(0); } pub fn gen_set_reg32_r(ctx: &mut JitContext, dest: u32, src: u32) { // generates: reg32s[r_dest] = reg32s[r_src] let builder = &mut ctx.builder; builder .instruction_body - .push_i32(global_pointers::get_reg32_offset(dest) as i32); - builder - .instruction_body - .load_aligned_i32(global_pointers::get_reg32_offset(src)); - builder.instruction_body.store_aligned_i32(); + .const_i32(global_pointers::get_reg32_offset(dest) as i32); + gen_get_reg32(builder, src); + builder.instruction_body.store_aligned_i32(0); } pub fn gen_safe_read8(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::BYTE) } @@ -202,11 +217,11 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { let address_local = builder.tee_new_local(); // Pseudo: base_on_stack = (uint32_t)address >> 12; - builder.instruction_body.push_i32(12); - builder.instruction_body.shr_u32(); + builder.instruction_body.const_i32(12); + builder.instruction_body.shr_u_i32(); // scale index - builder.instruction_body.push_i32(2); + builder.instruction_body.const_i32(2); builder.instruction_body.shl_i32(); // Pseudo: entry = tlb_data[base_on_stack]; @@ -217,22 +232,22 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && // (bitsize == 8 ? true : (address & 0xFFF) <= (0x1000 - (bitsize / 8))); - builder.instruction_body.push_i32( + builder.instruction_body.const_i32( (0xFFF & !TLB_READONLY & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32, ); builder.instruction_body.and_i32(); - builder.instruction_body.push_i32(TLB_VALID as i32); + builder.instruction_body.const_i32(TLB_VALID as i32); builder.instruction_body.eq_i32(); if bits != BitSize::BYTE { builder.instruction_body.get_local(&address_local); - builder.instruction_body.push_i32(0xFFF); + builder.instruction_body.const_i32(0xFFF); builder.instruction_body.and_i32(); builder .instruction_body - .push_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 }); + .const_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 }); builder.instruction_body.le_i32(); builder.instruction_body.and_i32(); @@ -242,7 +257,7 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { // if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]); builder.instruction_body.if_i32(); builder.instruction_body.get_local(&entry_local); - builder.instruction_body.push_i32(!0xFFF); + builder.instruction_body.const_i32(!0xFFF); builder.instruction_body.and_i32(); builder.instruction_body.get_local(&address_local); builder.instruction_body.xor_i32(); @@ -275,19 +290,19 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { builder .instruction_body - .push_i32(global_pointers::PREVIOUS_IP as i32); + .const_i32(global_pointers::PREVIOUS_IP as i32); builder .instruction_body .load_aligned_i32(global_pointers::INSTRUCTION_POINTER); - builder.instruction_body.push_i32(!0xFFF); + builder.instruction_body.const_i32(!0xFFF); builder.instruction_body.and_i32(); builder .instruction_body - .push_i32(ctx.start_of_current_instruction as i32 & 0xFFF); + .const_i32(ctx.start_of_current_instruction as i32 & 0xFFF); builder.instruction_body.or_i32(); - builder.instruction_body.store_aligned_i32(); + builder.instruction_body.store_aligned_i32(0); builder.instruction_body.get_local(&address_local); match bits { @@ -329,11 +344,11 @@ fn gen_safe_write( builder.instruction_body.get_local(&address_local); // Pseudo: base_on_stack = (uint32_t)address >> 12; - builder.instruction_body.push_i32(12); - builder.instruction_body.shr_u32(); + builder.instruction_body.const_i32(12); + builder.instruction_body.shr_u_i32(); // scale index - builder.instruction_body.push_i32(2); + builder.instruction_body.const_i32(2); builder.instruction_body.shl_i32(); // Pseudo: entry = tlb_data[base_on_stack]; @@ -346,19 +361,19 @@ fn gen_safe_write( // (address & 0xFFF) <= (0x1000 - bitsize / 8)); builder .instruction_body - .push_i32((0xFFF & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32); + .const_i32((0xFFF & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32); builder.instruction_body.and_i32(); - builder.instruction_body.push_i32(TLB_VALID as i32); + builder.instruction_body.const_i32(TLB_VALID as i32); builder.instruction_body.eq_i32(); if bits != BitSize::BYTE { builder.instruction_body.get_local(&address_local); - builder.instruction_body.push_i32(0xFFF); + builder.instruction_body.const_i32(0xFFF); builder.instruction_body.and_i32(); builder .instruction_body - .push_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 }); + .const_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 }); builder.instruction_body.le_i32(); builder.instruction_body.and_i32(); @@ -371,7 +386,7 @@ fn gen_safe_write( builder.instruction_body.if_void(); builder.instruction_body.get_local(&entry_local); - builder.instruction_body.push_i32(!0xFFF); + builder.instruction_body.const_i32(!0xFFF); builder.instruction_body.and_i32(); builder.instruction_body.get_local(&address_local); builder.instruction_body.xor_i32(); @@ -409,19 +424,19 @@ fn gen_safe_write( builder .instruction_body - .push_i32(global_pointers::PREVIOUS_IP as i32); + .const_i32(global_pointers::PREVIOUS_IP as i32); builder .instruction_body .load_aligned_i32(global_pointers::INSTRUCTION_POINTER); - builder.instruction_body.push_i32(!0xFFF); + builder.instruction_body.const_i32(!0xFFF); builder.instruction_body.and_i32(); builder .instruction_body - .push_i32(ctx.start_of_current_instruction as i32 & 0xFFF); + .const_i32(ctx.start_of_current_instruction as i32 & 0xFFF); builder.instruction_body.or_i32(); - builder.instruction_body.store_aligned_i32(); + builder.instruction_body.store_aligned_i32(0); builder.instruction_body.get_local(&address_local); builder.instruction_body.get_local(&value_local); @@ -450,22 +465,22 @@ fn gen_safe_write( pub fn gen_clear_prefixes(ctx: &mut JitContext) { let instruction_body = &mut ctx.builder.instruction_body; - instruction_body.push_i32(global_pointers::PREFIXES as i32); // load address of prefixes - instruction_body.push_i32(0); - instruction_body.store_aligned_i32(); + instruction_body.const_i32(global_pointers::PREFIXES as i32); // load address of prefixes + instruction_body.const_i32(0); + instruction_body.store_aligned_i32(0); } pub fn gen_add_prefix_bits(ctx: &mut JitContext, mask: u32) { dbg_assert!(mask < 0x100); let instruction_body = &mut ctx.builder.instruction_body; - instruction_body.push_i32(global_pointers::PREFIXES as i32); // load address of prefixes + instruction_body.const_i32(global_pointers::PREFIXES as i32); // load address of prefixes instruction_body.load_aligned_i32(global_pointers::PREFIXES); // load old value - instruction_body.push_i32(mask as i32); + instruction_body.const_i32(mask as i32); instruction_body.or_i32(); - instruction_body.store_aligned_i32(); + instruction_body.store_aligned_i32(0); } pub fn gen_jmp_rel16(ctx: &mut JitContext, rel16: u16) { @@ -480,31 +495,29 @@ pub fn gen_jmp_rel16(ctx: &mut JitContext, rel16: u16) { { let instruction_body = &mut ctx.builder.instruction_body; - instruction_body.push_i32(global_pointers::INSTRUCTION_POINTER as i32); + instruction_body.const_i32(global_pointers::INSTRUCTION_POINTER as i32); instruction_body.load_aligned_i32(global_pointers::INSTRUCTION_POINTER); instruction_body.get_local(&local); instruction_body.sub_i32(); - instruction_body.push_i32(rel16 as i32); + instruction_body.const_i32(rel16 as i32); instruction_body.add_i32(); - instruction_body.push_i32(0xFFFF); + instruction_body.const_i32(0xFFFF); instruction_body.and_i32(); instruction_body.get_local(&local); instruction_body.add_i32(); - instruction_body.store_aligned_i32(); + instruction_body.store_aligned_i32(0); } ctx.builder.free_local(local); } pub fn gen_pop16_ss16(ctx: &mut JitContext) { // sp = segment_offsets[SS] + reg16[SP] (or just reg16[SP] if has_flat_segmentation) - ctx.builder - .instruction_body - .load_aligned_i32(global_pointers::get_reg16_offset(regs::SP)); + gen_get_reg16(ctx.builder, regs::SP); let sp_local = ctx.builder.tee_new_local(); if !ctx.cpu.has_flat_segmentation() { @@ -520,11 +533,11 @@ pub fn gen_pop16_ss16(ctx: &mut JitContext) { // reg16[SP] += 2; ctx.builder .instruction_body - .push_i32(global_pointers::get_reg16_offset(regs::SP) as i32); + .const_i32(global_pointers::get_reg16_offset(regs::SP) as i32); ctx.builder.instruction_body.get_local(&sp_local); - ctx.builder.instruction_body.push_i32(2); + ctx.builder.instruction_body.const_i32(2); ctx.builder.instruction_body.add_i32(); - ctx.builder.instruction_body.store_aligned_i32(); + ctx.builder.instruction_body.store_aligned_u16(0); ctx.builder.free_local(sp_local); @@ -533,9 +546,7 @@ pub fn gen_pop16_ss16(ctx: &mut JitContext) { pub fn gen_pop16_ss32(ctx: &mut JitContext) { // esp = segment_offsets[SS] + reg32s[ESP] (or just reg32s[ESP] if has_flat_segmentation) - ctx.builder - .instruction_body - .load_aligned_i32(global_pointers::get_reg32_offset(regs::ESP)); + gen_get_reg32(ctx.builder, regs::ESP); let esp_local = ctx.builder.tee_new_local(); if !ctx.cpu.has_flat_segmentation() { @@ -551,11 +562,11 @@ pub fn gen_pop16_ss32(ctx: &mut JitContext) { // reg32s[ESP] += 2; ctx.builder .instruction_body - .push_i32(global_pointers::get_reg32_offset(regs::ESP) as i32); + .const_i32(global_pointers::get_reg32_offset(regs::ESP) as i32); ctx.builder.instruction_body.get_local(&esp_local); - ctx.builder.instruction_body.push_i32(2); + ctx.builder.instruction_body.const_i32(2); ctx.builder.instruction_body.add_i32(); - ctx.builder.instruction_body.store_aligned_i32(); + ctx.builder.instruction_body.store_aligned_i32(0); ctx.builder.free_local(esp_local); // return value is already on stack @@ -572,9 +583,7 @@ pub fn gen_pop16(ctx: &mut JitContext) { pub fn gen_pop32s_ss16(ctx: &mut JitContext) { // sp = reg16[SP] - ctx.builder - .instruction_body - .load_aligned_i32(global_pointers::get_reg16_offset(regs::SP)); + gen_get_reg16(ctx.builder, regs::SP); let local_sp = ctx.builder.tee_new_local(); // result = safe_read32s(segment_offsets[SS] + sp) (or just sp if has_flat_segmentation) @@ -590,11 +599,11 @@ pub fn gen_pop32s_ss16(ctx: &mut JitContext) { // reg16[SP] = sp + 4; ctx.builder .instruction_body - .push_i32(global_pointers::get_reg16_offset(regs::SP) as i32); + .const_i32(global_pointers::get_reg16_offset(regs::SP) as i32); ctx.builder.instruction_body.get_local(&local_sp); - ctx.builder.instruction_body.push_i32(4); + ctx.builder.instruction_body.const_i32(4); ctx.builder.instruction_body.add_i32(); - ctx.builder.instruction_body.store_aligned_i32(); + ctx.builder.instruction_body.store_aligned_u16(0); ctx.builder.free_local(local_sp); @@ -603,9 +612,7 @@ pub fn gen_pop32s_ss16(ctx: &mut JitContext) { pub fn gen_pop32s_ss32(ctx: &mut JitContext) { // esp = reg32s[ESP] - ctx.builder - .instruction_body - .load_aligned_i32(global_pointers::get_reg32_offset(regs::ESP)); + gen_get_reg32(ctx.builder, regs::ESP); let local_esp = ctx.builder.tee_new_local(); // result = safe_read32s(segment_offsets[SS] + esp) (or just esp if has_flat_segmentation) @@ -620,11 +627,11 @@ pub fn gen_pop32s_ss32(ctx: &mut JitContext) { // reg32s[ESP] = esp + 4; ctx.builder .instruction_body - .push_i32(global_pointers::get_reg32_offset(regs::ESP) as i32); + .const_i32(global_pointers::get_reg32_offset(regs::ESP) as i32); ctx.builder.instruction_body.get_local(&local_esp); - ctx.builder.instruction_body.push_i32(4); + ctx.builder.instruction_body.const_i32(4); ctx.builder.instruction_body.add_i32(); - ctx.builder.instruction_body.store_aligned_i32(); + ctx.builder.instruction_body.store_aligned_i32(0); ctx.builder.free_local(local_esp); @@ -648,7 +655,7 @@ pub fn gen_task_switch_test(ctx: &mut JitContext) { ctx.builder.instruction_body.load_aligned_i32(cr0_offset); ctx.builder .instruction_body - .push_i32((regs::CR0_EM | regs::CR0_TS) as i32); + .const_i32((regs::CR0_EM | regs::CR0_TS) as i32); ctx.builder.instruction_body.and_i32(); ctx.builder.instruction_body.if_void(); @@ -666,7 +673,7 @@ pub fn gen_task_switch_test_mmx(ctx: &mut JitContext) { ctx.builder.instruction_body.load_aligned_i32(cr0_offset); ctx.builder .instruction_body - .push_i32((regs::CR0_EM | regs::CR0_TS) as i32); + .const_i32((regs::CR0_EM | regs::CR0_TS) as i32); ctx.builder.instruction_body.and_i32(); ctx.builder.instruction_body.if_void(); @@ -679,18 +686,19 @@ pub fn gen_task_switch_test_mmx(ctx: &mut JitContext) { pub fn gen_push16(ctx: &mut JitContext, value_local: &WasmLocal) { let sp_reg = if ctx.cpu.ssize_32() { + gen_get_reg32(ctx.builder, regs::ESP); global_pointers::get_reg32_offset(regs::ESP) } else { + gen_get_reg16(ctx.builder, regs::SP); global_pointers::get_reg16_offset(regs::SP) }; - ctx.builder.instruction_body.load_aligned_i32(sp_reg); - ctx.builder.instruction_body.push_i32(2); + ctx.builder.instruction_body.const_i32(2); ctx.builder.instruction_body.sub_i32(); let reg_updated_local = ctx.builder.tee_new_local(); if !ctx.cpu.ssize_32() { - ctx.builder.instruction_body.push_i32(0xFFFF); + ctx.builder.instruction_body.const_i32(0xFFFF); ctx.builder.instruction_body.and_i32(); } @@ -704,30 +712,31 @@ pub fn gen_push16(ctx: &mut JitContext, value_local: &WasmLocal) { let sp_local = ctx.builder.set_new_local(); gen_safe_write16(ctx, &sp_local, &value_local); ctx.builder.free_local(sp_local); - ctx.builder.instruction_body.push_i32(sp_reg as i32); + ctx.builder.instruction_body.const_i32(sp_reg as i32); ctx.builder.instruction_body.get_local(®_updated_local); if ctx.cpu.ssize_32() { - ctx.builder.instruction_body.store_aligned_i32() + ctx.builder.instruction_body.store_aligned_i32(0) } else { - ctx.builder.instruction_body.store_aligned_u16() + ctx.builder.instruction_body.store_aligned_u16(0) }; ctx.builder.free_local(reg_updated_local); } pub fn gen_push32(ctx: &mut JitContext, value_local: &WasmLocal) { let sp_reg = if ctx.cpu.ssize_32() { + gen_get_reg32(ctx.builder, regs::ESP); global_pointers::get_reg32_offset(regs::ESP) } else { + gen_get_reg16(ctx.builder, regs::SP); global_pointers::get_reg16_offset(regs::SP) }; - ctx.builder.instruction_body.load_aligned_i32(sp_reg); - ctx.builder.instruction_body.push_i32(4); + ctx.builder.instruction_body.const_i32(4); ctx.builder.instruction_body.sub_i32(); if !ctx.cpu.ssize_32() { - ctx.builder.instruction_body.push_i32(0xFFFF); + ctx.builder.instruction_body.const_i32(0xFFFF); ctx.builder.instruction_body.and_i32(); } let new_sp_local = ctx.builder.tee_new_local(); @@ -744,13 +753,13 @@ pub fn gen_push32(ctx: &mut JitContext, value_local: &WasmLocal) { gen_safe_write32(ctx, &sp_local, &value_local); ctx.builder.free_local(sp_local); - ctx.builder.instruction_body.push_i32(sp_reg as i32); + ctx.builder.instruction_body.const_i32(sp_reg as i32); ctx.builder.instruction_body.get_local(&new_sp_local); if ctx.cpu.ssize_32() { - ctx.builder.instruction_body.store_aligned_i32() + ctx.builder.instruction_body.store_aligned_i32(0) } else { - ctx.builder.instruction_body.store_aligned_u16() + ctx.builder.instruction_body.store_aligned_u16(0) }; ctx.builder.free_local(new_sp_local); } @@ -773,11 +782,11 @@ fn gen_safe_read_write( builder.instruction_body.get_local(address_local); // Pseudo: base_on_stack = (uint32_t)address >> 12; - builder.instruction_body.push_i32(12); - builder.instruction_body.shr_u32(); + builder.instruction_body.const_i32(12); + builder.instruction_body.shr_u_i32(); // scale index - builder.instruction_body.push_i32(2); + builder.instruction_body.const_i32(2); builder.instruction_body.shl_i32(); // Pseudo: entry = tlb_data[base_on_stack]; @@ -788,21 +797,21 @@ fn gen_safe_read_write( // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && // (address & 0xFFF) <= (0x1000 - (bitsize / 8)); - builder.instruction_body.push_i32( + builder.instruction_body.const_i32( (0xFFF & !TLB_READONLY & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32, ); builder.instruction_body.and_i32(); - builder.instruction_body.push_i32(TLB_VALID as i32); + builder.instruction_body.const_i32(TLB_VALID as i32); builder.instruction_body.eq_i32(); builder.instruction_body.get_local(&address_local); - builder.instruction_body.push_i32(0xFFF); + builder.instruction_body.const_i32(0xFFF); builder.instruction_body.and_i32(); builder .instruction_body - .push_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 }); + .const_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 }); builder.instruction_body.le_i32(); builder.instruction_body.and_i32(); @@ -811,7 +820,7 @@ fn gen_safe_read_write( // if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]); builder.instruction_body.if_i32(); builder.instruction_body.get_local(&entry_local); - builder.instruction_body.push_i32(!0xFFF); + builder.instruction_body.const_i32(!0xFFF); builder.instruction_body.and_i32(); builder.instruction_body.get_local(&address_local); builder.instruction_body.xor_i32(); diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 9a227fc5..e5c8a4e5 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -925,7 +925,7 @@ fn jit_generate_module( let gen_local_iteration_counter = if JIT_ALWAYS_USE_LOOP_SAFETY || requires_loop_limit { builder .instruction_body - .push_i32(JIT_MAX_ITERATIONS_PER_FUNCTION as i32); + .const_i32(JIT_MAX_ITERATIONS_PER_FUNCTION as i32); Some(builder.set_new_local()) } else { @@ -942,7 +942,7 @@ fn jit_generate_module( builder .instruction_body .get_local(gen_local_iteration_counter); - builder.instruction_body.push_i32(-1); + builder.instruction_body.const_i32(-1); builder.instruction_body.add_i32(); builder .instruction_body @@ -1006,7 +1006,7 @@ fn jit_generate_module( .expect("basic_block_indices.get (Normal)"); // set state variable to next basic block - builder.instruction_body.push_i32(next_bb_index as i32); + builder.instruction_body.const_i32(next_bb_index as i32); builder.instruction_body.set_local(&gen_local_state); builder @@ -1055,7 +1055,7 @@ fn jit_generate_module( builder .instruction_body - .push_i32(next_basic_block_branch_taken_index as i32); + .const_i32(next_basic_block_branch_taken_index as i32); builder.instruction_body.set_local(&gen_local_state); } else { @@ -1074,7 +1074,7 @@ fn jit_generate_module( builder .instruction_body - .push_i32(next_basic_block_index as i32); + .const_i32(next_basic_block_index as i32); builder.instruction_body.set_local(&gen_local_state); } else { diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 4dced0bf..be869a26 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -102,9 +102,7 @@ pub fn instr_F3_jit(ctx: &mut JitContext, instr_flags: &mut u32) { } fn push16_reg_jit(ctx: &mut JitContext, r: u32) { - ctx.builder - .instruction_body - .load_aligned_u16(global_pointers::get_reg16_offset(r)); + codegen::gen_get_reg16(ctx.builder, r); let value_local = ctx.builder.set_new_local(); codegen::gen_push16(ctx, &value_local); ctx.builder.free_local(value_local); @@ -118,13 +116,13 @@ fn push32_reg_jit(ctx: &mut JitContext, r: u32) { ctx.builder.free_local(value_local); } fn push16_imm_jit(ctx: &mut JitContext, imm: u32) { - ctx.builder.instruction_body.push_i32(imm as i32); + ctx.builder.instruction_body.const_i32(imm as i32); let value_local = ctx.builder.set_new_local(); codegen::gen_push16(ctx, &value_local); ctx.builder.free_local(value_local); } fn push32_imm_jit(ctx: &mut JitContext, imm: u32) { - ctx.builder.instruction_body.push_i32(imm as i32); + ctx.builder.instruction_body.const_i32(imm as i32); let value_local = ctx.builder.set_new_local(); codegen::gen_push32(ctx, &value_local); ctx.builder.free_local(value_local); @@ -147,17 +145,17 @@ fn push32_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { fn pop16_reg_jit(ctx: &mut JitContext, reg: u32) { ctx.builder .instruction_body - .push_i32(global_pointers::get_reg16_offset(reg) as i32); + .const_i32(global_pointers::get_reg16_offset(reg) as i32); codegen::gen_pop16(ctx); - ctx.builder.instruction_body.store_aligned_u16(); + ctx.builder.instruction_body.store_aligned_u16(0); } fn pop32_reg_jit(ctx: &mut JitContext, reg: u32) { ctx.builder .instruction_body - .push_i32(global_pointers::get_reg32_offset(reg) as i32); + .const_i32(global_pointers::get_reg32_offset(reg) as i32); codegen::gen_pop32s(ctx); - ctx.builder.instruction_body.store_aligned_i32(); + ctx.builder.instruction_body.store_aligned_i32(0); } pub fn instr16_50_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, AX); } @@ -239,7 +237,7 @@ pub fn instr_88_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { ctx.builder .instruction_body - .push_i32(global_pointers::get_reg8_offset(r) as i32); + .const_i32(global_pointers::get_reg8_offset(r) as i32); ctx.builder.instruction_body.load_u8_from_stack(0); let value_local = ctx.builder.set_new_local(); @@ -256,10 +254,7 @@ pub fn instr16_89_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { let address_local = ctx.builder.set_new_local(); - ctx.builder - .instruction_body - .push_i32(global_pointers::get_reg16_offset(r) as i32); - ctx.builder.instruction_body.load_aligned_u16_from_stack(0); + codegen::gen_get_reg16(ctx.builder, r); let value_local = ctx.builder.set_new_local(); codegen::gen_safe_write16(ctx, &address_local, &value_local); @@ -276,7 +271,7 @@ pub fn instr32_89_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { ctx.builder .instruction_body - .push_i32(global_pointers::get_reg32_offset(r) as i32); + .const_i32(global_pointers::get_reg32_offset(r) as i32); ctx.builder.instruction_body.load_aligned_i32_from_stack(0); let value_local = ctx.builder.set_new_local(); @@ -292,7 +287,7 @@ pub fn instr_8A_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { // Pseudo: reg8[r] = safe_read8(modrm_resolve(modrm_byte)); ctx.builder .instruction_body - .push_i32(global_pointers::get_reg8_offset(r) as i32); + .const_i32(global_pointers::get_reg8_offset(r) as i32); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read8(ctx); @@ -307,12 +302,11 @@ pub fn instr16_8B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { // Pseudo: reg16[r] = safe_read16(modrm_resolve(modrm_byte)); ctx.builder .instruction_body - .push_i32(global_pointers::get_reg16_offset(r) as i32); - + .const_i32(global_pointers::get_reg16_offset(r) as i32); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read16(ctx); - ctx.builder.instruction_body.store_aligned_u16(); + ctx.builder.instruction_body.store_aligned_u16(0); } pub fn instr16_8B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_set_reg16_r(ctx, r2, r1); @@ -321,30 +315,32 @@ pub fn instr32_8B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { // Pseudo: reg32s[r] = safe_read32s(modrm_resolve(modrm_byte)); ctx.builder .instruction_body - .push_i32(global_pointers::get_reg32_offset(r) as i32); + .const_i32(global_pointers::get_reg32_offset(r) as i32); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); - ctx.builder.instruction_body.store_aligned_i32(); + ctx.builder.instruction_body.store_aligned_i32(0); } pub fn instr32_8B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_set_reg32_r(ctx, r2, r1); } pub fn instr16_8D_mem_jit(ctx: &mut JitContext, modrm_byte: u8, reg: u32) { - let loc = global_pointers::get_reg16_offset(reg); - ctx.builder.instruction_body.push_i32(loc as i32); + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg16_offset(reg) as i32); ctx.cpu.prefixes |= SEG_PREFIX_ZERO; codegen::gen_modrm_resolve(ctx, modrm_byte); - ctx.builder.instruction_body.store_aligned_u16(); + ctx.builder.instruction_body.store_aligned_u16(0); } pub fn instr32_8D_mem_jit(ctx: &mut JitContext, modrm_byte: u8, reg: u32) { - let loc = global_pointers::get_reg32_offset(reg); - ctx.builder.instruction_body.push_i32(loc as i32); + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg32_offset(reg) as i32); ctx.cpu.prefixes |= SEG_PREFIX_ZERO; codegen::gen_modrm_resolve(ctx, modrm_byte); - ctx.builder.instruction_body.store_aligned_i32(); + ctx.builder.instruction_body.store_aligned_i32(0); } pub fn instr16_8D_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { @@ -358,13 +354,11 @@ pub fn instr32_8D_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { pub fn instr16_8F_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { ctx.builder .instruction_body - .push_i32(global_pointers::get_reg16_offset(regs::SP) as i32); - ctx.builder - .instruction_body - .load_aligned_u16(global_pointers::get_reg16_offset(regs::SP)); - ctx.builder.instruction_body.push_i32(2); + .const_i32(global_pointers::get_reg16_offset(regs::SP) as i32); + codegen::gen_get_reg16(ctx.builder, regs::SP); + ctx.builder.instruction_body.const_i32(2); ctx.builder.instruction_body.add_i32(); - ctx.builder.instruction_body.store_aligned_u16(); + ctx.builder.instruction_body.store_aligned_u16(0); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_modrm_fn0(ctx, "instr16_8F_0_mem_jit"); @@ -375,13 +369,11 @@ pub fn instr16_8F_0_reg_jit(ctx: &mut JitContext, r: u32) { pub fn instr32_8F_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { ctx.builder .instruction_body - .push_i32(global_pointers::get_reg32_offset(regs::ESP) as i32); - ctx.builder - .instruction_body - .load_aligned_i32(global_pointers::get_reg32_offset(regs::ESP)); - ctx.builder.instruction_body.push_i32(4); + .const_i32(global_pointers::get_reg32_offset(regs::ESP) as i32); + codegen::gen_get_reg32(ctx.builder, regs::ESP); + ctx.builder.instruction_body.const_i32(4); ctx.builder.instruction_body.add_i32(); - ctx.builder.instruction_body.store_aligned_i32(); + ctx.builder.instruction_body.store_aligned_i32(0); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_modrm_fn0(ctx, "instr32_8F_0_mem_jit"); @@ -404,13 +396,13 @@ pub fn instr32_E8_jit(ctx: &mut JitContext, imm: u32) { ctx.builder.free_local(value_local); ctx.builder .instruction_body - .push_i32(global_pointers::INSTRUCTION_POINTER as i32); + .const_i32(global_pointers::INSTRUCTION_POINTER as i32); ctx.builder .instruction_body .load_aligned_i32(global_pointers::INSTRUCTION_POINTER); - ctx.builder.instruction_body.push_i32(imm as i32); + ctx.builder.instruction_body.const_i32(imm as i32); ctx.builder.instruction_body.add_i32(); - ctx.builder.instruction_body.store_aligned_i32(); + ctx.builder.instruction_body.store_aligned_i32(0); } pub fn instr16_E9_jit(ctx: &mut JitContext, imm: u32) { codegen::gen_jmp_rel16(ctx, imm as u16); } @@ -423,19 +415,19 @@ pub fn instr16_C3_jit(ctx: &mut JitContext) { ctx.builder .instruction_body - .push_i32(global_pointers::INSTRUCTION_POINTER as i32); + .const_i32(global_pointers::INSTRUCTION_POINTER as i32); ctx.builder.instruction_body.load_aligned_i32(cs_addr); codegen::gen_pop16(ctx); ctx.builder.instruction_body.add_i32(); - ctx.builder.instruction_body.store_aligned_i32(); + ctx.builder.instruction_body.store_aligned_i32(0); } pub fn instr32_C3_jit(ctx: &mut JitContext) { ctx.builder .instruction_body - .push_i32(global_pointers::INSTRUCTION_POINTER as i32); + .const_i32(global_pointers::INSTRUCTION_POINTER as i32); // cs = segment_offsets[CS] ctx.builder @@ -450,7 +442,7 @@ pub fn instr32_C3_jit(ctx: &mut JitContext) { // dbg_assert(is_asize_32() || ip < 0x10000); - ctx.builder.instruction_body.store_aligned_i32(); + ctx.builder.instruction_body.store_aligned_i32(0); } pub fn instr16_EB_jit(ctx: &mut JitContext, imm8: u32) { @@ -535,96 +527,88 @@ pub fn instr16_0FB6_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { let builder = &mut ctx.builder; builder .instruction_body - .push_i32(global_pointers::get_reg16_offset(r2) as i32); - builder - .instruction_body - .load_u8(global_pointers::get_reg8_offset(r1)); - builder.instruction_body.store_aligned_u16(); + .const_i32(global_pointers::get_reg16_offset(r2) as i32); + codegen::gen_get_reg8(builder, r1); + builder.instruction_body.store_aligned_u16(0); } pub fn instr16_0FB6_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { ctx.builder .instruction_body - .push_i32(global_pointers::get_reg16_offset(r) as i32); + .const_i32(global_pointers::get_reg16_offset(r) as i32); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read8(ctx); - ctx.builder.instruction_body.store_aligned_u16(); + ctx.builder.instruction_body.store_aligned_u16(0); } pub fn instr32_0FB6_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { let builder = &mut ctx.builder; builder .instruction_body - .push_i32(global_pointers::get_reg32_offset(r2) as i32); - builder - .instruction_body - .load_u8(global_pointers::get_reg8_offset(r1)); - builder.instruction_body.store_aligned_i32(); + .const_i32(global_pointers::get_reg32_offset(r2) as i32); + codegen::gen_get_reg8(builder, r1); + builder.instruction_body.store_aligned_i32(0); } pub fn instr32_0FB6_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { ctx.builder .instruction_body - .push_i32(global_pointers::get_reg32_offset(r) as i32); + .const_i32(global_pointers::get_reg32_offset(r) as i32); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read8(ctx); - ctx.builder.instruction_body.store_aligned_i32(); + ctx.builder.instruction_body.store_aligned_i32(0); } pub fn instr16_0FBE_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { let builder = &mut ctx.builder; builder .instruction_body - .push_i32(global_pointers::get_reg16_offset(r2) as i32); - builder - .instruction_body - .load_u8(global_pointers::get_reg8_offset(r1)); + .const_i32(global_pointers::get_reg16_offset(r2) as i32); + codegen::gen_get_reg8(builder, r1); codegen::sign_extend_i8(builder); - builder.instruction_body.store_aligned_u16(); + builder.instruction_body.store_aligned_u16(0); } pub fn instr16_0FBE_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { ctx.builder .instruction_body - .push_i32(global_pointers::get_reg16_offset(r) as i32); + .const_i32(global_pointers::get_reg16_offset(r) as i32); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read8(ctx); codegen::sign_extend_i8(ctx.builder); - ctx.builder.instruction_body.store_aligned_u16(); + ctx.builder.instruction_body.store_aligned_u16(0); } pub fn instr32_0FBE_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { let builder = &mut ctx.builder; builder .instruction_body - .push_i32(global_pointers::get_reg32_offset(r2) as i32); - builder - .instruction_body - .load_u8(global_pointers::get_reg8_offset(r1)); + .const_i32(global_pointers::get_reg32_offset(r2) as i32); + codegen::gen_get_reg8(builder, r1); codegen::sign_extend_i8(builder); - builder.instruction_body.store_aligned_i32(); + builder.instruction_body.store_aligned_i32(0); } pub fn instr32_0FBE_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { ctx.builder .instruction_body - .push_i32(global_pointers::get_reg32_offset(r) as i32); + .const_i32(global_pointers::get_reg32_offset(r) as i32); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read8(ctx); codegen::sign_extend_i8(ctx.builder); - ctx.builder.instruction_body.store_aligned_i32(); + ctx.builder.instruction_body.store_aligned_i32(0); } pub fn instr16_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { // reg16[r] = imm; ctx.builder .instruction_body - .push_i32(global_pointers::get_reg16_offset(r) as i32); - ctx.builder.instruction_body.push_i32(imm as i32); - ctx.builder.instruction_body.store_aligned_u16(); + .const_i32(global_pointers::get_reg16_offset(r) as i32); + ctx.builder.instruction_body.const_i32(imm as i32); + ctx.builder.instruction_body.store_aligned_u16(0); } pub fn instr16_C7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); let imm = ctx.cpu.read_imm16(); - ctx.builder.instruction_body.push_i32(imm as i32); + ctx.builder.instruction_body.const_i32(imm as i32); let value_local = ctx.builder.set_new_local(); codegen::gen_safe_write16(ctx, &address_local, &value_local); ctx.builder.free_local(address_local); @@ -635,16 +619,16 @@ pub fn instr32_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { // reg32s[r] = imm; ctx.builder .instruction_body - .push_i32(global_pointers::get_reg32_offset(r) as i32); - ctx.builder.instruction_body.push_i32(imm as i32); - ctx.builder.instruction_body.store_aligned_i32(); + .const_i32(global_pointers::get_reg32_offset(r) as i32); + ctx.builder.instruction_body.const_i32(imm as i32); + ctx.builder.instruction_body.store_aligned_i32(0); } pub fn instr32_C7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); let imm = ctx.cpu.read_imm32(); - ctx.builder.instruction_body.push_i32(imm as i32); + ctx.builder.instruction_body.const_i32(imm as i32); let value_local = ctx.builder.set_new_local(); codegen::gen_safe_write32(ctx, &address_local, &value_local); ctx.builder.free_local(address_local); diff --git a/src/rust/modrm.rs b/src/rust/modrm.rs index 83f2a6cf..ed6e0abf 100644 --- a/src/rust/modrm.rs +++ b/src/rust/modrm.rs @@ -1,3 +1,4 @@ +use codegen; use cpu_context::CpuContext; use jit::JitContext; use prefix::{PREFIX_MASK_SEGMENT, SEG_PREFIX_ZERO}; @@ -105,36 +106,30 @@ fn gen16_case(ctx: &mut JitContext, seg: u32, offset: Offset16, imm: Imm16) { Offset16::Zero => { ctx.builder .instruction_body - .push_i32(immediate_value & 0xFFFF); + .const_i32(immediate_value & 0xFFFF); }, Offset16::One(r) => { - ctx.builder - .instruction_body - .load_aligned_u16(::global_pointers::get_reg16_offset(r)); + codegen::gen_get_reg16(ctx.builder, r); if immediate_value != 0 { - ctx.builder.instruction_body.push_i32(immediate_value); + ctx.builder.instruction_body.const_i32(immediate_value); ctx.builder.instruction_body.add_i32(); - ctx.builder.instruction_body.push_i32(0xFFFF); + ctx.builder.instruction_body.const_i32(0xFFFF); ctx.builder.instruction_body.and_i32(); } }, Offset16::Two(r1, r2) => { - ctx.builder - .instruction_body - .load_aligned_u16(::global_pointers::get_reg16_offset(r1)); - ctx.builder - .instruction_body - .load_aligned_u16(::global_pointers::get_reg16_offset(r2)); + codegen::gen_get_reg16(ctx.builder, r1); + codegen::gen_get_reg16(ctx.builder, r2); ctx.builder.instruction_body.add_i32(); if immediate_value != 0 { - ctx.builder.instruction_body.push_i32(immediate_value); + ctx.builder.instruction_body.const_i32(immediate_value); ctx.builder.instruction_body.add_i32(); } - ctx.builder.instruction_body.push_i32(0xFFFF); + ctx.builder.instruction_body.const_i32(0xFFFF); ctx.builder.instruction_body.and_i32(); }, } @@ -200,7 +195,7 @@ fn gen32_case(ctx: &mut JitContext, seg: u32, offset: Offset, imm: Imm32) { }; if immediate_value != 0 { - ctx.builder.instruction_body.push_i32(immediate_value); + ctx.builder.instruction_body.const_i32(immediate_value); ctx.builder.instruction_body.add_i32(); } }, @@ -210,11 +205,9 @@ fn gen32_case(ctx: &mut JitContext, seg: u32, offset: Offset, imm: Imm32) { Imm32::Imm8 => ctx.cpu.read_imm8s() as i32, Imm32::Imm32 => ctx.cpu.read_imm32() as i32, }; - ctx.builder - .instruction_body - .load_aligned_i32(::global_pointers::get_reg32_offset(r)); + codegen::gen_get_reg32(ctx.builder, r); if immediate_value != 0 { - ctx.builder.instruction_body.push_i32(immediate_value); + ctx.builder.instruction_body.const_i32(immediate_value); ctx.builder.instruction_body.add_i32(); } jit_add_seg_offset(ctx, seg); @@ -225,7 +218,7 @@ fn gen32_case(ctx: &mut JitContext, seg: u32, offset: Offset, imm: Imm32) { Imm32::Imm8 => ctx.cpu.read_imm8s() as i32, Imm32::Imm32 => ctx.cpu.read_imm32() as i32, }; - ctx.builder.instruction_body.push_i32(immediate_value); + ctx.builder.instruction_body.const_i32(immediate_value); jit_add_seg_offset(ctx, seg); }, } @@ -276,25 +269,22 @@ fn gen_sib(ctx: &mut JitContext, mod_is_nonzero: bool) { if r == 4 { seg = SS; - let base_addr = ::global_pointers::get_reg32_offset(ESP); - ctx.builder.instruction_body.load_aligned_i32(base_addr); + codegen::gen_get_reg32(ctx.builder, ESP); } else if r == 5 { if mod_is_nonzero { seg = SS; - let base_addr = ::global_pointers::get_reg32_offset(EBP); - ctx.builder.instruction_body.load_aligned_i32(base_addr); + codegen::gen_get_reg32(ctx.builder, EBP); } else { seg = DS; let base = ctx.cpu.read_imm32(); - ctx.builder.instruction_body.push_i32(base as i32); + ctx.builder.instruction_body.const_i32(base as i32); } } else { seg = DS; - let base_addr = ::global_pointers::get_reg32_offset(r as u32); - ctx.builder.instruction_body.load_aligned_i32(base_addr); + codegen::gen_get_reg32(ctx.builder, r as u32); } jit_add_seg_offset(ctx, seg); @@ -310,10 +300,8 @@ fn gen_sib(ctx: &mut JitContext, mod_is_nonzero: bool) { let s = sib_byte >> 6 & 3; - ctx.builder - .instruction_body - .load_aligned_i32(::global_pointers::get_reg32_offset(m as u32)); - ctx.builder.instruction_body.push_i32(s as i32); + codegen::gen_get_reg32(ctx.builder, m as u32); + ctx.builder.instruction_body.const_i32(s as i32); ctx.builder.instruction_body.shl_i32(); ctx.builder.instruction_body.add_i32(); @@ -336,7 +324,7 @@ fn jit_add_seg_offset(ctx: &mut JitContext, default_segment: u32) { return; } - ctx.builder.instruction_body.push_i32(seg as i32); + ctx.builder.instruction_body.const_i32(seg as i32); ctx.builder.instruction_body.call_fn(::jit::FN_GET_SEG_IDX); ctx.builder.instruction_body.add_i32(); } diff --git a/src/rust/wasmgen/module_init.rs b/src/rust/wasmgen/module_init.rs index bd54b742..66f7b91c 100644 --- a/src/rust/wasmgen/module_init.rs +++ b/src/rust/wasmgen/module_init.rs @@ -395,18 +395,18 @@ mod tests { m.finish(); m.reset(); - m.code_section.push_i32(2); + m.code_section.const_i32(2); let baz_index = m.get_fn_idx("baz", FN1_RET_TYPE_INDEX); m.instruction_body.call_fn(baz_index); foo_index = m.get_fn_idx("foo", FN1_TYPE_INDEX); m.instruction_body.call_fn(foo_index); - m.code_section.push_i32(10); + m.code_section.const_i32(10); let local1 = m.alloc_local(); m.code_section.tee_local(&local1); // local1 = 10 - m.code_section.push_i32(20); + m.code_section.const_i32(20); m.code_section.add_i32(); let local2 = m.alloc_local(); m.code_section.tee_local(&local2); // local2 = 30 @@ -419,7 +419,7 @@ mod tests { m.free_local(local2); m.free_local(local3); - m.code_section.push_i32(30); + m.code_section.const_i32(30); m.code_section.ne_i32(); m.code_section.if_void(); m.code_section.unreachable(); diff --git a/src/rust/wasmgen/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs index 1e0225a9..841ddb2f 100644 --- a/src/rust/wasmgen/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -7,11 +7,7 @@ pub trait WasmBuf { fn write_leb_u32(&mut self, v: u32); fn write_fixed_leb16_at_idx(&mut self, idx: usize, x: u16); fn write_fixed_leb32_at_idx(&mut self, idx: usize, x: u32); - fn push_i32(&mut self, v: i32); - fn load_aligned_u16(&mut self, addr: u32); - fn load_aligned_i32(&mut self, addr: u32); - fn store_aligned_u16(&mut self); - fn store_aligned_i32(&mut self); + fn const_i32(&mut self, v: i32); fn add_i32(&mut self); fn sub_i32(&mut self); fn and_i32(&mut self); @@ -27,16 +23,24 @@ pub trait WasmBuf { fn if_i32(&mut self); fn block_i32(&mut self); fn xor_i32(&mut self); + + fn load_u8(&mut self, addr: u32); + fn load_u8_from_stack(&mut self, byte_offset: u32); + fn load_aligned_u16(&mut self, addr: u32); + fn load_aligned_i32(&mut self, addr: u32); fn load_unaligned_i32_from_stack(&mut self, byte_offset: u32); fn load_unaligned_u16_from_stack(&mut self, byte_offset: u32); fn load_aligned_i32_from_stack(&mut self, byte_offset: u32); - fn load_u8(&mut self, addr: u32); - fn load_u8_from_stack(&mut self, byte_offset: u32); - fn store_unaligned_i32(&mut self, byte_offset: u32); - fn store_unaligned_u16(&mut self, byte_offset: u32); + fn load_aligned_u16_from_stack(&mut self, byte_offset: u32); + fn store_u8(&mut self, byte_offset: u32); - fn shr_u32(&mut self); - fn shr_i32(&mut self); + fn store_aligned_u16(&mut self, byte_offset: u32); + fn store_aligned_i32(&mut self, byte_offset: u32); + fn store_unaligned_u16(&mut self, byte_offset: u32); + fn store_unaligned_i32(&mut self, byte_offset: u32); + + fn shr_u_i32(&mut self); + fn shr_s_i32(&mut self); fn eqz_i32(&mut self); fn if_void(&mut self); fn else_(&mut self); @@ -53,7 +57,6 @@ pub trait WasmBuf { fn unreachable(&mut self); fn increment_mem32(&mut self, addr: u32); fn increment_variable(&mut self, addr: u32, n: i32); - fn load_aligned_u16_from_stack(&mut self, byte_offset: u32); } impl WasmBuf for Vec { @@ -69,7 +72,7 @@ impl WasmBuf for Vec { write_fixed_leb32_at_idx(self, idx, x) } - fn push_i32(&mut self, v: i32) { + fn const_i32(&mut self, v: i32) { self.push(op::OP_I32CONST); self.write_leb_i32(v); } @@ -89,7 +92,7 @@ impl WasmBuf for Vec { // doesn't cause a failure in the generated code, but it will be much slower dbg_assert!((addr & 3) == 0); - self.push_i32(addr as i32); + self.const_i32(addr as i32); self.load_aligned_i32_from_stack(0); } @@ -100,22 +103,10 @@ impl WasmBuf for Vec { } fn load_u8(&mut self, addr: u32) { - self.push_i32(addr as i32); + self.const_i32(addr as i32); self.load_u8_from_stack(0); } - fn store_aligned_u16(&mut self) { - self.push(op::OP_I32STORE16); - self.push(op::MEM_ALIGN16); - self.push(0); // immediate offset - } - - fn store_aligned_i32(&mut self) { - self.push(op::OP_I32STORE); - self.push(op::MEM_ALIGN32); - self.push(0); // immediate offset - } - fn add_i32(&mut self) { self.push(op::OP_I32ADD); } fn sub_i32(&mut self) { self.push(op::OP_I32SUB); } @@ -175,29 +166,39 @@ impl WasmBuf for Vec { self.write_leb_u32(byte_offset); } - // XXX: Function naming should be consistent regarding both alignment and accepting an - // offset. Leaving as-is for the Rust port to cleanup - fn store_unaligned_i32(&mut self, byte_offset: u32) { - self.push(op::OP_I32STORE); + fn store_u8(&mut self, byte_offset: u32) { + self.push(op::OP_I32STORE8); self.push(op::MEM_NO_ALIGN); self.write_leb_u32(byte_offset); } + fn store_aligned_u16(&mut self, byte_offset: u32) { + self.push(op::OP_I32STORE16); + self.push(op::MEM_ALIGN16); + self.write_leb_u32(byte_offset); + } + + fn store_aligned_i32(&mut self, byte_offset: u32) { + self.push(op::OP_I32STORE); + self.push(op::MEM_ALIGN32); + self.write_leb_u32(byte_offset); + } + fn store_unaligned_u16(&mut self, byte_offset: u32) { self.push(op::OP_I32STORE16); self.push(op::MEM_NO_ALIGN); self.write_leb_u32(byte_offset); } - fn store_u8(&mut self, byte_offset: u32) { - self.push(op::OP_I32STORE8); + fn store_unaligned_i32(&mut self, byte_offset: u32) { + self.push(op::OP_I32STORE); self.push(op::MEM_NO_ALIGN); self.write_leb_u32(byte_offset); } - fn shr_u32(&mut self) { self.push(op::OP_I32SHRU); } + fn shr_u_i32(&mut self) { self.push(op::OP_I32SHRU); } - fn shr_i32(&mut self) { self.push(op::OP_I32SHRS); } + fn shr_s_i32(&mut self) { self.push(op::OP_I32SHRS); } fn eqz_i32(&mut self) { self.push(op::OP_I32EQZ); } @@ -260,11 +261,11 @@ impl WasmBuf for Vec { fn increment_mem32(&mut self, addr: u32) { self.increment_variable(addr, 1) } fn increment_variable(&mut self, addr: u32, n: i32) { - self.push_i32(addr as i32); + self.const_i32(addr as i32); self.load_aligned_i32(addr); - self.push_i32(n); + self.const_i32(n); self.add_i32(); - self.store_aligned_i32(); + self.store_aligned_i32(0); } fn load_aligned_u16_from_stack(&mut self, byte_offset: u32) { From 415e345e5497beac00cdd170c4980d63fa0450cb Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 21 Aug 2018 21:34:17 -0500 Subject: [PATCH 1222/2137] C6/C7 don't need to marked as block boundary --- gen/x86_table.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index b6cb886f..2267d511 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -182,9 +182,8 @@ const encodings = [ { opcode: 0xC4, block_boundary: 1, os: 1, e: 1, skip: 1, }, // les { opcode: 0xC5, block_boundary: 1, os: 1, e: 1, skip: 1, }, // lds - // XXX: Temporary block boundary - { opcode: 0xC6, e: 1, fixed_g: 0, imm8: 1, block_boundary: 1, }, - { opcode: 0xC7, custom: 1, os: 1, e: 1, fixed_g: 0, imm1632: 1, block_boundary: 1, }, + { opcode: 0xC6, e: 1, fixed_g: 0, imm8: 1 }, + { opcode: 0xC7, custom: 1, os: 1, e: 1, fixed_g: 0, imm1632: 1 }, // XXX: Temporary block boundary { opcode: 0xC8, os: 1, imm16: 1, extra_imm8: 1, block_boundary: 1, }, // enter From 9164e0a48f7eebbbad619ea5fea2f2f71c544a41 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 21 Aug 2018 21:38:11 -0500 Subject: [PATCH 1223/2137] Custom implementation for 'mov r/m, imm' --- gen/x86_table.js | 2 +- src/rust/jit_instructions.rs | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 2267d511..63cde1f9 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -182,7 +182,7 @@ const encodings = [ { opcode: 0xC4, block_boundary: 1, os: 1, e: 1, skip: 1, }, // les { opcode: 0xC5, block_boundary: 1, os: 1, e: 1, skip: 1, }, // lds - { opcode: 0xC6, e: 1, fixed_g: 0, imm8: 1 }, + { opcode: 0xC6, custom: 1, e: 1, fixed_g: 0, imm8: 1 }, { opcode: 0xC7, custom: 1, os: 1, e: 1, fixed_g: 0, imm1632: 1 }, // XXX: Temporary block boundary diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index be869a26..7ea47890 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -595,6 +595,26 @@ pub fn instr32_0FBE_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { ctx.builder.instruction_body.store_aligned_i32(0); } +pub fn instr_C6_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { + // reg8[r] = imm; + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg8_offset(r) as i32); + ctx.builder.instruction_body.const_i32(imm as i32); + ctx.builder.instruction_body.store_u8(0); +} + +pub fn instr_C6_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + let imm = ctx.cpu.read_imm8(); + ctx.builder.instruction_body.const_i32(imm as i32); + let value_local = ctx.builder.set_new_local(); + codegen::gen_safe_write8(ctx, &address_local, &value_local); + ctx.builder.free_local(address_local); + ctx.builder.free_local(value_local); +} + pub fn instr16_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { // reg16[r] = imm; ctx.builder From 9de2b926a7e43f543658a0ed3d2408a57f742357 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 21 Aug 2018 21:49:29 -0500 Subject: [PATCH 1224/2137] Custom implementations for test instruction (only wrapper) --- gen/x86_table.js | 4 ++-- src/rust/jit_instructions.rs | 39 ++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 63cde1f9..404245c3 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -97,8 +97,8 @@ const encodings = [ { opcode: 0xF26F, block_boundary: 1, is_string: 1, os: 1, skip: 1, }, { opcode: 0xF36F, block_boundary: 1, is_string: 1, os: 1, skip: 1, }, - { opcode: 0x84, nonfaulting: 1, e: 1, }, - { opcode: 0x85, nonfaulting: 1, os: 1, e: 1, }, + { opcode: 0x84, nonfaulting: 1, custom: 1, e: 1, }, + { opcode: 0x85, nonfaulting: 1, custom: 1, e: 1, os: 1, }, { opcode: 0x86, nonfaulting: 1, e: 1, }, { opcode: 0x87, nonfaulting: 1, os: 1, e: 1, }, { opcode: 0x88, custom: 1, nonfaulting: 1, e: 1, }, diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 7ea47890..2c2175f6 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -230,6 +230,45 @@ pub fn instr32_7E_jit(_ctx: &mut JitContext, _imm: u32) {} pub fn instr16_7F_jit(_ctx: &mut JitContext, _imm: u32) {} pub fn instr32_7F_jit(_ctx: &mut JitContext, _imm: u32) {} +pub fn instr_84_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read8(ctx); + codegen::gen_get_reg8(ctx.builder, r); + codegen::gen_call_fn2(ctx.builder, "test8") +} + +pub fn instr_84_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_get_reg8(ctx.builder, r1); + codegen::gen_get_reg8(ctx.builder, r2); + codegen::gen_call_fn2(ctx.builder, "test8") +} + +pub fn instr16_85_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read16(ctx); + codegen::gen_get_reg16(ctx.builder, r); + codegen::gen_call_fn2(ctx.builder, "test16") +} + +pub fn instr16_85_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_get_reg16(ctx.builder, r1); + codegen::gen_get_reg16(ctx.builder, r2); + codegen::gen_call_fn2(ctx.builder, "test16") +} + +pub fn instr32_85_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read32(ctx); + codegen::gen_get_reg32(ctx.builder, r); + codegen::gen_call_fn2(ctx.builder, "test32") +} + +pub fn instr32_85_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_get_reg32(ctx.builder, r1); + codegen::gen_get_reg32(ctx.builder, r2); + codegen::gen_call_fn2(ctx.builder, "test32") +} + pub fn instr_88_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); From cfb9cd8abe4f99e874f3a1b6a28a4c9b411a397b Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 22 Aug 2018 17:21:16 -0500 Subject: [PATCH 1225/2137] Partial custom implementation for arithmethic instructions with read-memory --- gen/x86_table.js | 44 ++++++- src/rust/codegen.rs | 6 + src/rust/jit_instructions.rs | 226 +++++++++++++++++++++++++++++------ 3 files changed, 234 insertions(+), 42 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 404245c3..792e1347 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -16,6 +16,46 @@ const sf = 1 << 7; // os: the instruction behaves differently depending on the operand size const encodings = [ + { opcode: 0x00, nonfaulting: 1, e: 1, }, + { opcode: 0x01, nonfaulting: 1, os: 1, e: 1, }, + { opcode: 0x02, nonfaulting: 1, custom: 1, e: 1, }, + { opcode: 0x03, nonfaulting: 1, custom: 1, os: 1, e: 1, }, + + { opcode: 0x08, nonfaulting: 1, e: 1, }, + { opcode: 0x09, nonfaulting: 1, os: 1, e: 1, }, + { opcode: 0x0A, nonfaulting: 1, custom: 1, e: 1, }, + { opcode: 0x0B, nonfaulting: 1, custom: 1, os: 1, e: 1, }, + + { opcode: 0x10, nonfaulting: 1, e: 1, }, + { opcode: 0x11, nonfaulting: 1, os: 1, e: 1, }, + { opcode: 0x12, nonfaulting: 1, custom: 1, e: 1, }, + { opcode: 0x13, nonfaulting: 1, custom: 1, os: 1, e: 1, }, + + { opcode: 0x18, nonfaulting: 1, e: 1, }, + { opcode: 0x19, nonfaulting: 1, os: 1, e: 1, }, + { opcode: 0x1A, nonfaulting: 1, custom: 1, e: 1, }, + { opcode: 0x1B, nonfaulting: 1, custom: 1, os: 1, e: 1, }, + + { opcode: 0x20, nonfaulting: 1, e: 1, }, + { opcode: 0x21, nonfaulting: 1, os: 1, e: 1, }, + { opcode: 0x22, nonfaulting: 1, custom: 1, e: 1, }, + { opcode: 0x23, nonfaulting: 1, custom: 1, os: 1, e: 1, }, + + { opcode: 0x28, nonfaulting: 1, e: 1, }, + { opcode: 0x29, nonfaulting: 1, os: 1, e: 1, }, + { opcode: 0x2A, nonfaulting: 1, custom: 1, e: 1, }, + { opcode: 0x2B, nonfaulting: 1, custom: 1, os: 1, e: 1, }, + + { opcode: 0x30, nonfaulting: 1, e: 1, }, + { opcode: 0x31, nonfaulting: 1, os: 1, e: 1, }, + { opcode: 0x32, nonfaulting: 1, custom: 1, e: 1, }, + { opcode: 0x33, nonfaulting: 1, custom: 1, os: 1, e: 1, }, + + { opcode: 0x38, nonfaulting: 1, custom: 1, e: 1, }, + { opcode: 0x39, nonfaulting: 1, custom: 1, os: 1, e: 1, }, + { opcode: 0x3A, nonfaulting: 1, custom: 1, e: 1, }, + { opcode: 0x3B, nonfaulting: 1, custom: 1, os: 1, e: 1, }, + { opcode: 0x06, os: 1, skip: 1, }, { opcode: 0x07, os: 1, skip: 1, block_boundary: 1, }, // pop es: block_boundary since it uses non-raising cpu exceptions { opcode: 0x0E, os: 1, skip: 1, }, @@ -786,10 +826,6 @@ const encodings = [ for(let i = 0; i < 8; i++) { encodings.push.apply(encodings, [ - { opcode: 0x00 | i << 3, nonfaulting: 1, e: 1, }, - { opcode: 0x01 | i << 3, nonfaulting: 1, os: 1, e: 1, }, - { opcode: 0x02 | i << 3, nonfaulting: 1, e: 1, }, - { opcode: 0x03 | i << 3, nonfaulting: 1, os: 1, e: 1, }, { opcode: 0x04 | i << 3, nonfaulting: 1, eax: 1, imm8: 1, }, { opcode: 0x05 | i << 3, nonfaulting: 1, os: 1, eax: 1, imm1632: 1, }, diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index d8df9ede..c0f10290 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -132,6 +132,12 @@ pub fn gen_call_fn2(builder: &mut WasmBuilder, name: &str) { builder.instruction_body.call_fn(fn_idx); } +pub fn gen_call_fn2_ret(builder: &mut WasmBuilder, name: &str) { + // generates: fn( _, _ ) where _ must be left on the stack before calling this, and fn returns a value + let fn_idx = builder.get_fn_idx(name, module_init::FN2_RET_TYPE_INDEX); + builder.instruction_body.call_fn(fn_idx); +} + pub fn gen_fn3_const(ctx: &mut JitContext, name: &str, arg0: u32, arg1: u32, arg2: u32) { let builder = &mut ctx.builder; let fn_idx = builder.get_fn_idx(name, module_init::FN3_TYPE_INDEX); diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 2c2175f6..0ca37dce 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -158,6 +158,191 @@ fn pop32_reg_jit(ctx: &mut JitContext, reg: u32) { ctx.builder.instruction_body.store_aligned_i32(0); } +macro_rules! define_instruction_read8( + ($fn:expr, $name_mem:ident, $name_reg:ident) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read8(ctx); + codegen::gen_get_reg8(ctx.builder, r); + codegen::gen_call_fn2(ctx.builder, $fn) + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_get_reg8(ctx.builder, r1); + codegen::gen_get_reg8(ctx.builder, r2); + codegen::gen_call_fn2(ctx.builder, $fn) + } + ) +); + +macro_rules! define_instruction_read16( + ($fn:expr, $name_mem:ident, $name_reg:ident) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read16(ctx); + codegen::gen_get_reg16(ctx.builder, r); + codegen::gen_call_fn2(ctx.builder, $fn) + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_get_reg16(ctx.builder, r1); + codegen::gen_get_reg16(ctx.builder, r2); + codegen::gen_call_fn2(ctx.builder, $fn) + } + ) +); + +macro_rules! define_instruction_read32( + ($fn:expr, $name_mem:ident, $name_reg:ident) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read32(ctx); + codegen::gen_get_reg32(ctx.builder, r); + codegen::gen_call_fn2(ctx.builder, $fn) + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_get_reg32(ctx.builder, r1); + codegen::gen_get_reg32(ctx.builder, r2); + codegen::gen_call_fn2(ctx.builder, $fn) + } + ) +); + +macro_rules! define_instruction_write_reg8( + ($fn:expr, $name_mem:ident, $name_reg:ident) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + ctx.builder.instruction_body.const_i32(global_pointers::get_reg8_offset(r) as i32); + codegen::gen_get_reg8(ctx.builder, r); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read8(ctx); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + ctx.builder.instruction_body.store_u8(0); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { + ctx.builder.instruction_body.const_i32(global_pointers::get_reg8_offset(r2) as i32); + codegen::gen_get_reg8(ctx.builder, r2); + codegen::gen_get_reg8(ctx.builder, r1); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + ctx.builder.instruction_body.store_u8(0); + } + ) +); + +macro_rules! define_instruction_write_reg16( + ($fn:expr, $name_mem:ident, $name_reg:ident) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r) as i32); + codegen::gen_get_reg16(ctx.builder, r); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read16(ctx); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + ctx.builder.instruction_body.store_aligned_u16(0); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { + ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r2) as i32); + codegen::gen_get_reg16(ctx.builder, r2); + codegen::gen_get_reg16(ctx.builder, r1); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + ctx.builder.instruction_body.store_aligned_u16(0); + } + ) +); + +macro_rules! define_instruction_write_reg32( + ($fn:expr, $name_mem:ident, $name_reg:ident) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r) as i32); + codegen::gen_get_reg32(ctx.builder, r); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read32(ctx); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + ctx.builder.instruction_body.store_aligned_i32(0); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { + ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r2) as i32); + codegen::gen_get_reg32(ctx.builder, r2); + codegen::gen_get_reg32(ctx.builder, r1); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + ctx.builder.instruction_body.store_aligned_i32(0); + } + ) +); + +define_instruction_write_reg8!("add8", instr_02_mem_jit, instr_02_reg_jit); +define_instruction_write_reg16!("add16", instr16_03_mem_jit, instr16_03_reg_jit); +define_instruction_write_reg32!("add32", instr32_03_mem_jit, instr32_03_reg_jit); + +define_instruction_write_reg8!("or8", instr_0A_mem_jit, instr_0A_reg_jit); +define_instruction_write_reg16!("or16", instr16_0B_mem_jit, instr16_0B_reg_jit); +define_instruction_write_reg32!("or32", instr32_0B_mem_jit, instr32_0B_reg_jit); + +define_instruction_write_reg8!("adc8", instr_12_mem_jit, instr_12_reg_jit); +define_instruction_write_reg16!("adc16", instr16_13_mem_jit, instr16_13_reg_jit); +define_instruction_write_reg32!("adc32", instr32_13_mem_jit, instr32_13_reg_jit); + +define_instruction_write_reg8!("sbb8", instr_1A_mem_jit, instr_1A_reg_jit); +define_instruction_write_reg16!("sbb16", instr16_1B_mem_jit, instr16_1B_reg_jit); +define_instruction_write_reg32!("sbb32", instr32_1B_mem_jit, instr32_1B_reg_jit); + +define_instruction_write_reg8!("and8", instr_22_mem_jit, instr_22_reg_jit); +define_instruction_write_reg16!("and16", instr16_23_mem_jit, instr16_23_reg_jit); +define_instruction_write_reg32!("and32", instr32_23_mem_jit, instr32_23_reg_jit); + +define_instruction_write_reg8!("sub8", instr_2A_mem_jit, instr_2A_reg_jit); +define_instruction_write_reg16!("sub16", instr16_2B_mem_jit, instr16_2B_reg_jit); +define_instruction_write_reg32!("sub32", instr32_2B_mem_jit, instr32_2B_reg_jit); + +define_instruction_write_reg8!("xor8", instr_32_mem_jit, instr_32_reg_jit); +define_instruction_write_reg16!("xor16", instr16_33_mem_jit, instr16_33_reg_jit); +define_instruction_write_reg32!("xor32", instr32_33_mem_jit, instr32_33_reg_jit); + +define_instruction_read8!("cmp8", instr_38_mem_jit, instr_38_reg_jit); +define_instruction_read16!("cmp16", instr16_39_mem_jit, instr16_39_reg_jit); +define_instruction_read32!("cmp32", instr32_39_mem_jit, instr32_39_reg_jit); + +pub fn instr_3A_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_get_reg8(ctx.builder, r); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read8(ctx); + codegen::gen_call_fn2(ctx.builder, "cmp8") +} + +pub fn instr_3A_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_get_reg8(ctx.builder, r2); + codegen::gen_get_reg8(ctx.builder, r1); + codegen::gen_call_fn2(ctx.builder, "cmp8") +} + +pub fn instr16_3B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_get_reg16(ctx.builder, r); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read16(ctx); + codegen::gen_call_fn2(ctx.builder, "cmp16") +} + +pub fn instr16_3B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_get_reg16(ctx.builder, r2); + codegen::gen_get_reg16(ctx.builder, r1); + codegen::gen_call_fn2(ctx.builder, "cmp16") +} + +pub fn instr32_3B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_get_reg32(ctx.builder, r); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read32(ctx); + codegen::gen_call_fn2(ctx.builder, "cmp32") +} + +pub fn instr32_3B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_get_reg32(ctx.builder, r2); + codegen::gen_get_reg32(ctx.builder, r1); + codegen::gen_call_fn2(ctx.builder, "cmp32") +} + pub fn instr16_50_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, AX); } pub fn instr32_50_jit(ctx: &mut JitContext) { push32_reg_jit(ctx, EAX); } pub fn instr16_51_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, CX); } @@ -230,44 +415,9 @@ pub fn instr32_7E_jit(_ctx: &mut JitContext, _imm: u32) {} pub fn instr16_7F_jit(_ctx: &mut JitContext, _imm: u32) {} pub fn instr32_7F_jit(_ctx: &mut JitContext, _imm: u32) {} -pub fn instr_84_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read8(ctx); - codegen::gen_get_reg8(ctx.builder, r); - codegen::gen_call_fn2(ctx.builder, "test8") -} - -pub fn instr_84_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - codegen::gen_get_reg8(ctx.builder, r1); - codegen::gen_get_reg8(ctx.builder, r2); - codegen::gen_call_fn2(ctx.builder, "test8") -} - -pub fn instr16_85_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read16(ctx); - codegen::gen_get_reg16(ctx.builder, r); - codegen::gen_call_fn2(ctx.builder, "test16") -} - -pub fn instr16_85_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - codegen::gen_get_reg16(ctx.builder, r1); - codegen::gen_get_reg16(ctx.builder, r2); - codegen::gen_call_fn2(ctx.builder, "test16") -} - -pub fn instr32_85_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read32(ctx); - codegen::gen_get_reg32(ctx.builder, r); - codegen::gen_call_fn2(ctx.builder, "test32") -} - -pub fn instr32_85_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - codegen::gen_get_reg32(ctx.builder, r1); - codegen::gen_get_reg32(ctx.builder, r2); - codegen::gen_call_fn2(ctx.builder, "test32") -} +define_instruction_read8!("test8", instr_84_mem_jit, instr_84_reg_jit); +define_instruction_read16!("test16", instr16_85_mem_jit, instr16_85_reg_jit); +define_instruction_read32!("test32", instr32_85_mem_jit, instr32_85_reg_jit); pub fn instr_88_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); From 0680c1a2c4d5c2cf54b592b18ac63fe1d2880fc3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 23 Aug 2018 15:40:05 -0500 Subject: [PATCH 1226/2137] fpu: Fix out of bounds memory access --- src/rust/cpu2/fpu.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index b37b5fc7..b0bfc613 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -522,7 +522,7 @@ pub unsafe fn fpu_load_tag_word() -> i32 { } #[no_mangle] pub unsafe fn fpu_fst(mut r: i32) -> () { - *fpu_st.offset((*fpu_stack_ptr).wrapping_add(r as u32) as isize) = fpu_get_st0(); + *fpu_st.offset((*fpu_stack_ptr).wrapping_add(r as u32) as isize & 7) = fpu_get_st0(); } #[no_mangle] pub unsafe fn fpu_fst80p(mut addr: i32) -> () { @@ -652,7 +652,7 @@ pub unsafe fn fpu_sign(mut i: i32) -> i32 { #[no_mangle] pub unsafe fn fpu_fxch(mut i: i32) -> () { let mut sti: f64 = fpu_get_sti(i); - *fpu_st.offset((*fpu_stack_ptr).wrapping_add(i as u32) as isize) = fpu_get_st0(); + *fpu_st.offset((*fpu_stack_ptr).wrapping_add(i as u32) as isize & 7) = fpu_get_st0(); *fpu_st.offset(*fpu_stack_ptr as isize) = sti; } #[no_mangle] From 0cf700edee8b17af26da4889474e6101c87690c1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 24 Aug 2018 20:24:11 -0500 Subject: [PATCH 1227/2137] Use cargo features to toggle profiler --- Cargo.toml | 4 ++++ src/rust/cpu2/profiler.rs | 11 +++++++++-- src/rust/profiler.rs | 6 +++--- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 694fe8fe..2a9205cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,10 @@ publish = false [dev-dependencies] quickcheck = "0.6.2" +[features] +default = [] +profiler = [] + [lib] crate-type = ["cdylib"] path = "src/rust/lib.rs" diff --git a/src/rust/cpu2/profiler.rs b/src/rust/cpu2/profiler.rs index e05ea624..9a80857e 100644 --- a/src/rust/cpu2/profiler.rs +++ b/src/rust/cpu2/profiler.rs @@ -109,11 +109,18 @@ pub unsafe fn profiler_stat_increment(mut stat: stat_name) -> () { } #[no_mangle] pub unsafe fn profiler_stat_increment_by(mut stat: stat_name, mut by: i32) -> () { - profiler_stat_arr[stat as usize].count += by; + if cfg!(feature = "profiler") { + profiler_stat_arr[stat as usize].count += by; + } } #[no_mangle] pub unsafe fn profiler_stat_get(mut stat: stat_name) -> i32 { - return profiler_stat_arr[stat as usize].count; + if cfg!(feature = "profiler") { + profiler_stat_arr[stat as usize].count + } + else { + 0 + } } #[no_mangle] pub unsafe fn profiler_stat_increment_do_run() -> () { profiler_stat_increment(S_DO_RUN); } diff --git a/src/rust/profiler.rs b/src/rust/profiler.rs index 80f6dd94..3bae3986 100644 --- a/src/rust/profiler.rs +++ b/src/rust/profiler.rs @@ -49,15 +49,15 @@ pub enum stat { S_TLB_GLOBAL_FULL, } -#[cfg(debug_assertions)] +#[cfg(feature = "profiler")] mod unsafe_extern { extern "C" { pub fn profiler_stat_increment(stat: ::profiler::stat); } } -#[cfg(debug_assertions)] +#[cfg(feature = "profiler")] pub fn stat_increment(stat: stat) { unsafe { unsafe_extern::profiler_stat_increment(stat) } } -#[cfg(not(debug_assertions))] +#[cfg(not(feature = "profiler"))] pub fn stat_increment(_stat: stat) {} From 3706bcac12e47fcd0ec9236f322ac22050bdd48f Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 24 Aug 2018 21:06:20 -0500 Subject: [PATCH 1228/2137] Use jit for read-modify-write arithmetic instructions --- gen/x86_table.js | 18 +- src/rust/codegen.rs | 131 ++++---- src/rust/cpu2/instruction_helpers.rs | 20 +- src/rust/jit_instructions.rs | 458 ++++++++++++++++++++++++++- tests/expect/tests/do-while.wast | 66 ++-- tests/expect/tests/if.wast | 49 +-- tests/expect/tests/while-do.wast | 47 +-- 7 files changed, 618 insertions(+), 171 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 792e1347..f61cf0b1 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -17,37 +17,37 @@ const sf = 1 << 7; // os: the instruction behaves differently depending on the operand size const encodings = [ { opcode: 0x00, nonfaulting: 1, e: 1, }, - { opcode: 0x01, nonfaulting: 1, os: 1, e: 1, }, + { opcode: 0x01, nonfaulting: 1, custom: 1, os: 1, e: 1, }, { opcode: 0x02, nonfaulting: 1, custom: 1, e: 1, }, { opcode: 0x03, nonfaulting: 1, custom: 1, os: 1, e: 1, }, { opcode: 0x08, nonfaulting: 1, e: 1, }, - { opcode: 0x09, nonfaulting: 1, os: 1, e: 1, }, + { opcode: 0x09, nonfaulting: 1, custom: 1, os: 1, e: 1, }, { opcode: 0x0A, nonfaulting: 1, custom: 1, e: 1, }, { opcode: 0x0B, nonfaulting: 1, custom: 1, os: 1, e: 1, }, { opcode: 0x10, nonfaulting: 1, e: 1, }, - { opcode: 0x11, nonfaulting: 1, os: 1, e: 1, }, + { opcode: 0x11, nonfaulting: 1, custom: 1, os: 1, e: 1, }, { opcode: 0x12, nonfaulting: 1, custom: 1, e: 1, }, { opcode: 0x13, nonfaulting: 1, custom: 1, os: 1, e: 1, }, { opcode: 0x18, nonfaulting: 1, e: 1, }, - { opcode: 0x19, nonfaulting: 1, os: 1, e: 1, }, + { opcode: 0x19, nonfaulting: 1, custom: 1, os: 1, e: 1, }, { opcode: 0x1A, nonfaulting: 1, custom: 1, e: 1, }, { opcode: 0x1B, nonfaulting: 1, custom: 1, os: 1, e: 1, }, { opcode: 0x20, nonfaulting: 1, e: 1, }, - { opcode: 0x21, nonfaulting: 1, os: 1, e: 1, }, + { opcode: 0x21, nonfaulting: 1, custom: 1, os: 1, e: 1, }, { opcode: 0x22, nonfaulting: 1, custom: 1, e: 1, }, { opcode: 0x23, nonfaulting: 1, custom: 1, os: 1, e: 1, }, { opcode: 0x28, nonfaulting: 1, e: 1, }, - { opcode: 0x29, nonfaulting: 1, os: 1, e: 1, }, + { opcode: 0x29, nonfaulting: 1, custom: 1, os: 1, e: 1, }, { opcode: 0x2A, nonfaulting: 1, custom: 1, e: 1, }, { opcode: 0x2B, nonfaulting: 1, custom: 1, os: 1, e: 1, }, { opcode: 0x30, nonfaulting: 1, e: 1, }, - { opcode: 0x31, nonfaulting: 1, os: 1, e: 1, }, + { opcode: 0x31, nonfaulting: 1, custom: 1, os: 1, e: 1, }, { opcode: 0x32, nonfaulting: 1, custom: 1, e: 1, }, { opcode: 0x33, nonfaulting: 1, custom: 1, os: 1, e: 1, }, @@ -833,9 +833,9 @@ for(let i = 0; i < 8; i++) { opcode: 0x78 | i, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, os: 1, imm8s: 1, custom: 1, skip: 1, }, { opcode: 0x80, nonfaulting: 1, e: 1, fixed_g: i, imm8: 1, }, - { opcode: 0x81, nonfaulting: 1, os: 1, e: 1, fixed_g: i, imm1632: 1, }, + { opcode: 0x81, nonfaulting: 1, os: 1, e: 1, fixed_g: i, imm1632: 1, custom: 1, }, { opcode: 0x82, nonfaulting: 1, e: 1, fixed_g: i, imm8: 1, }, - { opcode: 0x83, nonfaulting: 1, os: 1, e: 1, fixed_g: i, imm8s: 1, }, + { opcode: 0x83, nonfaulting: 1, os: 1, e: 1, fixed_g: i, imm8s: 1, custom: 1, }, { opcode: 0xB0 | i, nonfaulting: 1, imm8: 1, }, { opcode: 0xB8 | i, nonfaulting: 1, os: 1, imm1632: 1, }, diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index c0f10290..ecad5c70 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -777,115 +777,130 @@ pub fn gen_get_real_eip(ctx: &mut JitContext) { instruction_body.sub_i32(); } -fn gen_safe_read_write( +pub fn gen_safe_read_write( ctx: &mut JitContext, bits: BitSize, address_local: &WasmLocal, - fn_idx: u16, + f: &Fn(&mut JitContext), + fallback_fn: &Fn(&mut JitContext), ) { - let builder = &mut ctx.builder; - - builder.instruction_body.get_local(address_local); + ctx.builder.instruction_body.get_local(address_local); // Pseudo: base_on_stack = (uint32_t)address >> 12; - builder.instruction_body.const_i32(12); - builder.instruction_body.shr_u_i32(); + ctx.builder.instruction_body.const_i32(12); + ctx.builder.instruction_body.shr_u_i32(); // scale index - builder.instruction_body.const_i32(2); - builder.instruction_body.shl_i32(); + ctx.builder.instruction_body.const_i32(2); + ctx.builder.instruction_body.shl_i32(); // Pseudo: entry = tlb_data[base_on_stack]; - builder + ctx.builder .instruction_body .load_aligned_i32_from_stack(global_pointers::TLB_DATA); - let entry_local = builder.tee_new_local(); + let entry_local = ctx.builder.tee_new_local(); // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && // (address & 0xFFF) <= (0x1000 - (bitsize / 8)); - builder.instruction_body.const_i32( - (0xFFF & !TLB_READONLY & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) - as i32, - ); - builder.instruction_body.and_i32(); + ctx.builder + .instruction_body + .const_i32((0xFFF & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32); + ctx.builder.instruction_body.and_i32(); - builder.instruction_body.const_i32(TLB_VALID as i32); - builder.instruction_body.eq_i32(); + ctx.builder.instruction_body.const_i32(TLB_VALID as i32); + ctx.builder.instruction_body.eq_i32(); - builder.instruction_body.get_local(&address_local); - builder.instruction_body.const_i32(0xFFF); - builder.instruction_body.and_i32(); - builder + ctx.builder.instruction_body.get_local(&address_local); + ctx.builder.instruction_body.const_i32(0xFFF); + ctx.builder.instruction_body.and_i32(); + ctx.builder .instruction_body .const_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 }); - builder.instruction_body.le_i32(); + ctx.builder.instruction_body.le_i32(); - builder.instruction_body.and_i32(); + ctx.builder.instruction_body.and_i32(); // Pseudo: // if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]); - builder.instruction_body.if_i32(); - builder.instruction_body.get_local(&entry_local); - builder.instruction_body.const_i32(!0xFFF); - builder.instruction_body.and_i32(); - builder.instruction_body.get_local(&address_local); - builder.instruction_body.xor_i32(); + ctx.builder.instruction_body.if_void(); + ctx.builder.instruction_body.get_local(&entry_local); + ctx.builder.instruction_body.const_i32(!0xFFF); + ctx.builder.instruction_body.and_i32(); + ctx.builder.instruction_body.get_local(&address_local); + ctx.builder.instruction_body.xor_i32(); - let phys_addr_local = builder.tee_new_local(); + let phys_addr_local = ctx.builder.tee_new_local(); + // now store the value on stack to phys_addr + ctx.builder.instruction_body.get_local(&phys_addr_local); match bits { BitSize::BYTE => {}, BitSize::WORD => { - builder + ctx.builder .instruction_body .load_unaligned_u16_from_stack(unsafe { mem8 } as u32); }, BitSize::DWORD => { - builder + ctx.builder .instruction_body .load_unaligned_i32_from_stack(unsafe { mem8 } as u32); }, } - builder.free_local(entry_local); + ctx.builder.free_local(entry_local); - builder.instruction_body.call_fn(fn_idx); + f(ctx); - // now store the value on stack to phys_addr - builder.instruction_body.get_local(&phys_addr_local); match bits { BitSize::BYTE => {}, BitSize::WORD => { - builder + ctx.builder .instruction_body .store_unaligned_u16(unsafe { mem8 } as u32); }, BitSize::DWORD => { - builder + ctx.builder .instruction_body .store_unaligned_i32(unsafe { mem8 } as u32); }, }; - builder.free_local(phys_addr_local); + ctx.builder.free_local(phys_addr_local); // Pseudo: - // else { safe_readXX_slow(address); fn(); safe_writeXX_slow(); } - builder.instruction_body.else_(); - builder.instruction_body.get_local(&address_local); // for writeXX's first arg - builder.instruction_body.get_local(&address_local); // for readXX's first arg - match bits { - BitSize::BYTE => {}, - BitSize::WORD => { - gen_call_fn1_ret(builder, "safe_read16_slow"); - builder.instruction_body.call_fn(fn_idx); - gen_call_fn2(builder, "safe_write16_slow"); - }, - BitSize::DWORD => { - gen_call_fn1_ret(builder, "safe_read32s_slow"); - builder.instruction_body.call_fn(fn_idx); - gen_call_fn2(builder, "safe_write32_slow"); - }, - } + // else { + // *previous_ip = *instruction_pointer & ~0xFFF | start_of_instruction; + // fallback_fn(); + // if(page_fault) return; + // } + ctx.builder.instruction_body.else_(); - builder.instruction_body.block_end(); + ctx.builder + .instruction_body + .const_i32(global_pointers::PREVIOUS_IP as i32); + + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::INSTRUCTION_POINTER); + ctx.builder.instruction_body.const_i32(!0xFFF); + ctx.builder.instruction_body.and_i32(); + ctx.builder + .instruction_body + .const_i32(ctx.start_of_current_instruction as i32 & 0xFFF); + ctx.builder.instruction_body.or_i32(); + + ctx.builder.instruction_body.store_aligned_i32(0); + + ctx.builder.instruction_body.get_local(&address_local); + + fallback_fn(ctx); + + ctx.builder + .instruction_body + .load_u8(global_pointers::PAGE_FAULT); + + ctx.builder.instruction_body.if_void(); + ctx.builder.instruction_body.return_(); + ctx.builder.instruction_body.block_end(); + + ctx.builder.instruction_body.block_end(); } diff --git a/src/rust/cpu2/instruction_helpers.rs b/src/rust/cpu2/instruction_helpers.rs index 0af8369d..5c0bb79b 100644 --- a/src/rust/cpu2/instruction_helpers.rs +++ b/src/rust/cpu2/instruction_helpers.rs @@ -16,13 +16,18 @@ macro_rules! SAFE_READ_WRITE16 { use cpu2::cpu::{translate_address_write, virt_boundary_read16, virt_boundary_write16}; use cpu2::memory::{read16, write16}; match translate_address_write($addr) { - Err(()) => {}, + Err(()) => { + *page_fault = true; + }, Ok(phys_addr) => { let phys_addr = phys_addr as i32; if phys_addr & 0xFFF == 0xFFF { match translate_address_write($addr + 1) { - Err(()) => {}, + Err(()) => { + *page_fault = true; + }, Ok(phys_addr_high) => { + *page_fault = false; let phys_addr_high = phys_addr_high as i32; let $value = virt_boundary_read16(phys_addr, phys_addr_high); virt_boundary_write16(phys_addr, phys_addr_high, $instruction); @@ -30,6 +35,7 @@ macro_rules! SAFE_READ_WRITE16 { } } else { + *page_fault = false; let $value = read16(phys_addr as u32); write16(phys_addr as u32, $instruction); } @@ -42,12 +48,17 @@ macro_rules! SAFE_READ_WRITE32 { use cpu2::cpu::{translate_address_write, virt_boundary_read32s, virt_boundary_write32}; use cpu2::memory::{read32s, write32}; match translate_address_write($addr) { - Err(()) => {}, + Err(()) => { + *page_fault = true; + }, Ok(phys_addr) => { if phys_addr & 0xFFF >= 0xFFD { match translate_address_write($addr + 3 & !3) { - Err(()) => {}, + Err(()) => { + *page_fault = true; + }, Ok(phys_addr_high) => { + *page_fault = false; let phys_addr_high = phys_addr_high as i32 | $addr + 3 & 3; let $value = virt_boundary_read32s(phys_addr as i32, phys_addr_high); virt_boundary_write32( @@ -59,6 +70,7 @@ macro_rules! SAFE_READ_WRITE32 { } } else { + *page_fault = false; let $value = read32s(phys_addr); write32(phys_addr, $instruction); } diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 0ca37dce..8fb47880 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1,6 +1,7 @@ #![allow(non_snake_case)] use codegen; +use cpu::BitSize; use cpu_context::CpuContext; use global_pointers; use jit::JitContext; @@ -189,7 +190,22 @@ macro_rules! define_instruction_read16( codegen::gen_get_reg16(ctx.builder, r2); codegen::gen_call_fn2(ctx.builder, $fn) } - ) + ); + + ($fn:expr, $name_mem:ident, $name_reg:ident, $imm:ident) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read16(ctx); + ctx.builder.instruction_body.const_i32(make_imm_read!(ctx, $imm) as i32); + codegen::gen_call_fn2(ctx.builder, $fn) + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { + codegen::gen_get_reg16(ctx.builder, r1); + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn2(ctx.builder, $fn) + } + ); ); macro_rules! define_instruction_read32( @@ -206,6 +222,21 @@ macro_rules! define_instruction_read32( codegen::gen_get_reg32(ctx.builder, r2); codegen::gen_call_fn2(ctx.builder, $fn) } + ); + + ($fn:expr, $name_mem:ident, $name_reg:ident, $imm:ident) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read32(ctx); + ctx.builder.instruction_body.const_i32(make_imm_read!(ctx, $imm) as i32); + codegen::gen_call_fn2(ctx.builder, $fn) + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { + codegen::gen_get_reg32(ctx.builder, r1); + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn2(ctx.builder, $fn) + } ) ); @@ -272,30 +303,239 @@ macro_rules! define_instruction_write_reg32( ) ); +macro_rules! make_imm_read( + ($ctx:expr, imm8s) => { $ctx.cpu.read_imm8s() }; + ($ctx:expr, imm16) => { $ctx.cpu.read_imm16() }; + ($ctx:expr, imm32) => { $ctx.cpu.read_imm32() }; +); + +macro_rules! define_instruction_read_write_mem16( + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, reg) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_safe_read_write(ctx, BitSize::WORD, &address_local, &|ref mut ctx| { + codegen::gen_get_reg16(ctx.builder, r); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + }, &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_call_fn2(ctx.builder, $fallback_fn) + }); + ctx.builder.free_local(address_local); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { + ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r1) as i32); + codegen::gen_get_reg16(ctx.builder, r1); + codegen::gen_get_reg16(ctx.builder, r2); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + ctx.builder.instruction_body.store_aligned_u16(0); + } + ); + + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, $imm:ident) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + let imm = make_imm_read!(ctx, $imm) as i32; + codegen::gen_safe_read_write(ctx, BitSize::WORD, &address_local, &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + }, &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn2(ctx.builder, $fallback_fn) + }); + ctx.builder.free_local(address_local); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { + ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r1) as i32); + codegen::gen_get_reg16(ctx.builder, r1); + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + ctx.builder.instruction_body.store_aligned_u16(0); + } + ); +); + +macro_rules! define_instruction_read_write_mem32( + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, reg) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { + codegen::gen_get_reg32(ctx.builder, r); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + }, &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_call_fn2(ctx.builder, $fallback_fn) + }); + ctx.builder.free_local(address_local); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { + ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r1) as i32); + codegen::gen_get_reg32(ctx.builder, r1); + codegen::gen_get_reg32(ctx.builder, r2); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + ctx.builder.instruction_body.store_aligned_i32(0); + } + ); + + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, $imm:ident) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + let imm = make_imm_read!(ctx, $imm) as i32; + codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + }, &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn2(ctx.builder, $fallback_fn) + }); + ctx.builder.free_local(address_local); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { + ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r1) as i32); + codegen::gen_get_reg32(ctx.builder, r1); + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + ctx.builder.instruction_body.store_aligned_i32(0); + } + ); +); + +define_instruction_read_write_mem16!( + "add16", + "instr16_01_mem", + instr16_01_mem_jit, + instr16_01_reg_jit, + reg +); +define_instruction_read_write_mem32!( + "add32", + "instr32_01_mem", + instr32_01_mem_jit, + instr32_01_reg_jit, + reg +); + define_instruction_write_reg8!("add8", instr_02_mem_jit, instr_02_reg_jit); define_instruction_write_reg16!("add16", instr16_03_mem_jit, instr16_03_reg_jit); define_instruction_write_reg32!("add32", instr32_03_mem_jit, instr32_03_reg_jit); +define_instruction_read_write_mem16!( + "or16", + "instr16_09_mem", + instr16_09_mem_jit, + instr16_09_reg_jit, + reg +); +define_instruction_read_write_mem32!( + "or32", + "instr32_09_mem", + instr32_09_mem_jit, + instr32_09_reg_jit, + reg +); + define_instruction_write_reg8!("or8", instr_0A_mem_jit, instr_0A_reg_jit); define_instruction_write_reg16!("or16", instr16_0B_mem_jit, instr16_0B_reg_jit); define_instruction_write_reg32!("or32", instr32_0B_mem_jit, instr32_0B_reg_jit); +define_instruction_read_write_mem16!( + "adc16", + "instr16_11_mem", + instr16_11_mem_jit, + instr16_11_reg_jit, + reg +); +define_instruction_read_write_mem32!( + "adc32", + "instr32_11_mem", + instr32_11_mem_jit, + instr32_11_reg_jit, + reg +); + define_instruction_write_reg8!("adc8", instr_12_mem_jit, instr_12_reg_jit); define_instruction_write_reg16!("adc16", instr16_13_mem_jit, instr16_13_reg_jit); define_instruction_write_reg32!("adc32", instr32_13_mem_jit, instr32_13_reg_jit); +define_instruction_read_write_mem16!( + "sbb16", + "instr16_19_mem", + instr16_19_mem_jit, + instr16_19_reg_jit, + reg +); +define_instruction_read_write_mem32!( + "sbb32", + "instr32_19_mem", + instr32_19_mem_jit, + instr32_19_reg_jit, + reg +); + define_instruction_write_reg8!("sbb8", instr_1A_mem_jit, instr_1A_reg_jit); define_instruction_write_reg16!("sbb16", instr16_1B_mem_jit, instr16_1B_reg_jit); define_instruction_write_reg32!("sbb32", instr32_1B_mem_jit, instr32_1B_reg_jit); +define_instruction_read_write_mem16!( + "and16", + "instr16_21_mem", + instr16_21_mem_jit, + instr16_21_reg_jit, + reg +); +define_instruction_read_write_mem32!( + "and32", + "instr32_21_mem", + instr32_21_mem_jit, + instr32_21_reg_jit, + reg +); + define_instruction_write_reg8!("and8", instr_22_mem_jit, instr_22_reg_jit); define_instruction_write_reg16!("and16", instr16_23_mem_jit, instr16_23_reg_jit); define_instruction_write_reg32!("and32", instr32_23_mem_jit, instr32_23_reg_jit); +define_instruction_read_write_mem16!( + "sub16", + "instr16_29_mem", + instr16_29_mem_jit, + instr16_29_reg_jit, + reg +); +define_instruction_read_write_mem32!( + "sub32", + "instr32_29_mem", + instr32_29_mem_jit, + instr32_29_reg_jit, + reg +); + define_instruction_write_reg8!("sub8", instr_2A_mem_jit, instr_2A_reg_jit); define_instruction_write_reg16!("sub16", instr16_2B_mem_jit, instr16_2B_reg_jit); define_instruction_write_reg32!("sub32", instr32_2B_mem_jit, instr32_2B_reg_jit); +define_instruction_read_write_mem16!( + "xor16", + "instr16_31_mem", + instr16_31_mem_jit, + instr16_31_reg_jit, + reg +); +define_instruction_read_write_mem32!( + "xor32", + "instr32_31_mem", + instr32_31_mem_jit, + instr32_31_reg_jit, + reg +); + define_instruction_write_reg8!("xor8", instr_32_mem_jit, instr_32_reg_jit); define_instruction_write_reg16!("xor16", instr16_33_mem_jit, instr16_33_reg_jit); define_instruction_write_reg32!("xor32", instr32_33_mem_jit, instr32_33_reg_jit); @@ -415,6 +655,222 @@ pub fn instr32_7E_jit(_ctx: &mut JitContext, _imm: u32) {} pub fn instr16_7F_jit(_ctx: &mut JitContext, _imm: u32) {} pub fn instr32_7F_jit(_ctx: &mut JitContext, _imm: u32) {} +define_instruction_read_write_mem16!( + "add16", + "instr16_81_0_mem", + instr16_81_0_mem_jit, + instr16_81_0_reg_jit, + imm16 +); +define_instruction_read_write_mem32!( + "add32", + "instr32_81_0_mem", + instr32_81_0_mem_jit, + instr32_81_0_reg_jit, + imm32 +); + +define_instruction_read_write_mem16!( + "or16", + "instr16_81_1_mem", + instr16_81_1_mem_jit, + instr16_81_1_reg_jit, + imm16 +); +define_instruction_read_write_mem32!( + "or32", + "instr32_81_1_mem", + instr32_81_1_mem_jit, + instr32_81_1_reg_jit, + imm32 +); + +define_instruction_read_write_mem16!( + "adc16", + "instr16_81_2_mem", + instr16_81_2_mem_jit, + instr16_81_2_reg_jit, + imm16 +); +define_instruction_read_write_mem32!( + "adc32", + "instr32_81_2_mem", + instr32_81_2_mem_jit, + instr32_81_2_reg_jit, + imm32 +); + +define_instruction_read_write_mem16!( + "sbb16", + "instr16_81_3_mem", + instr16_81_3_mem_jit, + instr16_81_3_reg_jit, + imm16 +); +define_instruction_read_write_mem32!( + "sbb32", + "instr32_81_3_mem", + instr32_81_3_mem_jit, + instr32_81_3_reg_jit, + imm32 +); + +define_instruction_read_write_mem16!( + "and16", + "instr16_81_4_mem", + instr16_81_4_mem_jit, + instr16_81_4_reg_jit, + imm16 +); +define_instruction_read_write_mem32!( + "and32", + "instr32_81_4_mem", + instr32_81_4_mem_jit, + instr32_81_4_reg_jit, + imm32 +); + +define_instruction_read_write_mem16!( + "sub16", + "instr16_81_5_mem", + instr16_81_5_mem_jit, + instr16_81_5_reg_jit, + imm16 +); +define_instruction_read_write_mem32!( + "sub32", + "instr32_81_5_mem", + instr32_81_5_mem_jit, + instr32_81_5_reg_jit, + imm32 +); + +define_instruction_read_write_mem16!( + "xor16", + "instr16_81_6_mem", + instr16_81_6_mem_jit, + instr16_81_6_reg_jit, + imm16 +); +define_instruction_read_write_mem32!( + "xor32", + "instr32_81_6_mem", + instr32_81_6_mem_jit, + instr32_81_6_reg_jit, + imm32 +); + +define_instruction_read_write_mem16!( + "add16", + "instr16_83_0_mem", + instr16_83_0_mem_jit, + instr16_83_0_reg_jit, + imm8s +); +define_instruction_read_write_mem32!( + "add32", + "instr32_83_0_mem", + instr32_83_0_mem_jit, + instr32_83_0_reg_jit, + imm8s +); + +define_instruction_read_write_mem16!( + "or16", + "instr16_83_1_mem", + instr16_83_1_mem_jit, + instr16_83_1_reg_jit, + imm8s +); +define_instruction_read_write_mem32!( + "or32", + "instr32_83_1_mem", + instr32_83_1_mem_jit, + instr32_83_1_reg_jit, + imm8s +); + +define_instruction_read_write_mem16!( + "adc16", + "instr16_83_2_mem", + instr16_83_2_mem_jit, + instr16_83_2_reg_jit, + imm8s +); +define_instruction_read_write_mem32!( + "adc32", + "instr32_83_2_mem", + instr32_83_2_mem_jit, + instr32_83_2_reg_jit, + imm8s +); + +define_instruction_read_write_mem16!( + "sbb16", + "instr16_83_3_mem", + instr16_83_3_mem_jit, + instr16_83_3_reg_jit, + imm8s +); +define_instruction_read_write_mem32!( + "sbb32", + "instr32_83_3_mem", + instr32_83_3_mem_jit, + instr32_83_3_reg_jit, + imm8s +); + +define_instruction_read_write_mem16!( + "and16", + "instr16_83_4_mem", + instr16_83_4_mem_jit, + instr16_83_4_reg_jit, + imm8s +); +define_instruction_read_write_mem32!( + "and32", + "instr32_83_4_mem", + instr32_83_4_mem_jit, + instr32_83_4_reg_jit, + imm8s +); + +define_instruction_read_write_mem16!( + "sub16", + "instr16_83_5_mem", + instr16_83_5_mem_jit, + instr16_83_5_reg_jit, + imm8s +); +define_instruction_read_write_mem32!( + "sub32", + "instr32_83_5_mem", + instr32_83_5_mem_jit, + instr32_83_5_reg_jit, + imm8s +); + +define_instruction_read_write_mem16!( + "xor16", + "instr16_83_6_mem", + instr16_83_6_mem_jit, + instr16_83_6_reg_jit, + imm8s +); +define_instruction_read_write_mem32!( + "xor32", + "instr32_83_6_mem", + instr32_83_6_mem_jit, + instr32_83_6_reg_jit, + imm8s +); + +define_instruction_read16!("cmp16", instr16_81_7_mem_jit, instr16_81_7_reg_jit, imm16); +define_instruction_read32!("cmp32", instr32_81_7_mem_jit, instr32_81_7_reg_jit, imm32); + +define_instruction_read16!("cmp16", instr16_83_7_mem_jit, instr16_83_7_reg_jit, imm8s); +define_instruction_read32!("cmp32", instr32_83_7_mem_jit, instr32_83_7_reg_jit, imm8s); + define_instruction_read8!("test8", instr_84_mem_jit, instr_84_reg_jit); define_instruction_read16!("test16", instr16_85_mem_jit, instr16_85_reg_jit); define_instruction_read32!("test32", instr32_85_mem_jit, instr32_85_reg_jit); diff --git a/tests/expect/tests/do-while.wast b/tests/expect/tests/do-while.wast index 6a43b5f1..072719bb 100644 --- a/tests/expect/tests/do-while.wast +++ b/tests/expect/tests/do-while.wast @@ -8,60 +8,54 @@ (type $t6 (func (param i32 i32) (result i32))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "instr32_43" (func $e.instr32_43 (type $t0))) - (import "e" "instr32_83_7_reg" (func $e.instr32_83_7_reg (type $t2))) + (import "e" "cmp32" (func $e.cmp32 (type $t2))) (import "e" "test_nz" (func $e.test_nz (type $t4))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) + (local $l0 i32) (local $l1 i32) (set_local $p0 (get_local $p0)) + (set_local $l0 + (i32.const 10000)) (loop $L0 - (block $B1 - (block $B2 - (block $B3 - (block $B4 - (br_table $B4 $B3 $B2 $B1 - (get_local $p0))) - (call $e.instr32_43) - (i32.store - (i32.const 560) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 1))) - (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 4))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 2))) - (call $e.instr32_83_7_reg - (i32.const 0) - (i32.const 10)) - (return)) + (set_local $l0 + (i32.add + (get_local $l0) + (i32.const -1))) + (if $I1 + (i32.eqz + (get_local $l0)) + (then + (return))) + (block $B2 + (block $B3 + (block $B4 + (br_table $B4 $B3 $B2 + (get_local $p0))) + (call $e.instr32_43) + (call $e.cmp32 + (i32.load + (i32.const 4)) + (i32.const 10)) (i32.store (i32.const 560) - (i32.load - (i32.const 556))) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 4))) (i32.store (i32.const 556) (i32.add (i32.load (i32.const 556)) - (i32.const 2))) + (i32.const 6))) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) - (i32.const 1))) + (i32.const 3))) (if $I5 (call $e.test_nz) (then @@ -75,7 +69,7 @@ (i32.const 0))) (else (set_local $p0 - (i32.const 2)))) + (i32.const 1)))) (br $L0)) (i32.store (i32.const 560) diff --git a/tests/expect/tests/if.wast b/tests/expect/tests/if.wast index 5aaf0f18..ee22360c 100644 --- a/tests/expect/tests/if.wast +++ b/tests/expect/tests/if.wast @@ -7,7 +7,7 @@ (type $t5 (func (param i32) (result i32))) (type $t6 (func (param i32 i32) (result i32))) (import "e" "get_seg" (func $e.get_seg (type $t5))) - (import "e" "instr32_83_7_reg" (func $e.instr32_83_7_reg (type $t2))) + (import "e" "cmp32" (func $e.cmp32 (type $t2))) (import "e" "test_nle" (func $e.test_nle (type $t4))) (import "e" "instr32_41" (func $e.instr32_41 (type $t0))) (import "e" "instr32_43" (func $e.instr32_43 (type $t0))) @@ -22,46 +22,31 @@ (block $B2 (block $B3 (block $B4 - (block $B5 - (br_table $B5 $B4 $B3 $B2 $B1 - (get_local $p0))) - (i32.store - (i32.const 560) - (i32.load - (i32.const 556))) - (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 3))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 1))) - (call $e.instr32_83_7_reg - (i32.const 0) - (i32.const 5)) - (return)) + (br_table $B4 $B3 $B2 $B1 + (get_local $p0))) + (call $e.cmp32 + (i32.load + (i32.const 4)) + (i32.const 5)) (i32.store (i32.const 560) - (i32.load - (i32.const 556))) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 3))) (i32.store (i32.const 556) (i32.add (i32.load (i32.const 556)) - (i32.const 2))) + (i32.const 5))) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) - (i32.const 1))) - (if $I6 + (i32.const 2))) + (if $I5 (call $e.test_nle) (then (i32.store @@ -71,10 +56,10 @@ (i32.const 556)) (i32.const 1))) (set_local $p0 - (i32.const 3))) + (i32.const 2))) (else (set_local $p0 - (i32.const 2)))) + (i32.const 1)))) (br $L0)) (i32.store (i32.const 560) @@ -94,7 +79,7 @@ (i32.const 1))) (call $e.instr32_41) (set_local $p0 - (i32.const 3)) + (i32.const 2)) (br $L0)) (call $e.instr32_43) (i32.store diff --git a/tests/expect/tests/while-do.wast b/tests/expect/tests/while-do.wast index ef7c40d3..f57c61b2 100644 --- a/tests/expect/tests/while-do.wast +++ b/tests/expect/tests/while-do.wast @@ -7,7 +7,7 @@ (type $t5 (func (param i32) (result i32))) (type $t6 (func (param i32 i32) (result i32))) (import "e" "get_seg" (func $e.get_seg (type $t5))) - (import "e" "instr32_83_7_reg" (func $e.instr32_83_7_reg (type $t2))) + (import "e" "cmp32" (func $e.cmp32 (type $t2))) (import "e" "test_z" (func $e.test_z (type $t4))) (import "e" "instr32_43" (func $e.instr32_43 (type $t0))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) @@ -21,46 +21,31 @@ (block $B2 (block $B3 (block $B4 - (block $B5 - (br_table $B5 $B4 $B3 $B2 $B1 - (get_local $p0))) - (i32.store - (i32.const 560) - (i32.load - (i32.const 556))) - (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 3))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 1))) - (call $e.instr32_83_7_reg - (i32.const 0) - (i32.const 10)) - (return)) + (br_table $B4 $B3 $B2 $B1 + (get_local $p0))) + (call $e.cmp32 + (i32.load + (i32.const 4)) + (i32.const 10)) (i32.store (i32.const 560) - (i32.load - (i32.const 556))) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 3))) (i32.store (i32.const 556) (i32.add (i32.load (i32.const 556)) - (i32.const 2))) + (i32.const 5))) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) - (i32.const 1))) - (if $I6 + (i32.const 2))) + (if $I5 (call $e.test_z) (then (i32.store @@ -70,10 +55,10 @@ (i32.const 556)) (i32.const 3))) (set_local $p0 - (i32.const 3))) + (i32.const 2))) (else (set_local $p0 - (i32.const 2)))) + (i32.const 1)))) (br $L0)) (call $e.instr32_43) (i32.store From 8460d9e1e4a9ae42736950a9daab48b15f680271 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 24 Aug 2018 21:21:53 -0500 Subject: [PATCH 1229/2137] Clean up --- src/rust/config.rs | 2 +- src/rust/cpu2/cpu.rs | 35 ----------------------------------- src/rust/jit.rs | 12 ------------ 3 files changed, 1 insertion(+), 48 deletions(-) diff --git a/src/rust/config.rs b/src/rust/config.rs index 3c1b712c..8b137891 100644 --- a/src/rust/config.rs +++ b/src/rust/config.rs @@ -1 +1 @@ -pub const CHECK_CPU_EXCEPTIONS: bool = false; + diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 8985ac44..238f79a0 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -232,7 +232,6 @@ pub const TSC_RATE: f64 = (50i32 * 1000i32) as f64; pub static mut jit_block_boundary: bool = 0 != 0i32; pub static mut must_not_fault: bool = 0 != 0i32; -pub static mut current_cpu_exception: i32 = -1i32; pub static mut rdtsc_imprecision_offset: u64 = 0i32 as u64; pub static mut rdtsc_last_value: u64 = 0i32 as u64; pub static mut tsc_offset: u64 = 0i32 as u64; @@ -781,7 +780,6 @@ pub unsafe fn cycle_internal() -> () { (wasm_table_index as u32).wrapping_add(256i32 as u32) as i32, initial_state, ); - clear_current_cpu_exception(); profiler_stat_increment_by( S_RUN_FROM_CACHE_STEPS, (*timestamp_counter).wrapping_sub(initial_tsc as u32) as i32, @@ -835,7 +833,6 @@ unsafe fn jit_run_interpreted(mut phys_addr: i32) -> () { *instruction_pointer += 1; *timestamp_counter = (*timestamp_counter).wrapping_add(1); run_instruction(opcode | (*is_32 as i32) << 8i32); - clear_current_cpu_exception(); while !jit_block_boundary && 0 != same_page(*previous_ip, *instruction_pointer) as i32 { *previous_ip.offset(0isize) = *instruction_pointer.offset(0isize); *timestamp_counter = (*timestamp_counter).wrapping_add(1); @@ -844,12 +841,9 @@ unsafe fn jit_run_interpreted(mut phys_addr: i32) -> () { logop(*previous_ip.offset(0isize), opcode_0); } run_instruction(opcode_0 | (*is_32 as i32) << 8i32); - clear_current_cpu_exception(); } } -pub unsafe fn clear_current_cpu_exception() -> () { current_cpu_exception = -1i32; } - #[no_mangle] pub unsafe fn pack_current_state_flags() -> cached_state_flags { return ((*is_32 as i32) << 0i32 @@ -914,11 +908,8 @@ pub unsafe fn trigger_de() -> () { } *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_DE, 0 != 0i32, 0 != 0i32, 0i32); - set_current_cpu_exception(CPU_EXCEPTION_DE); } -pub unsafe fn set_current_cpu_exception(mut n: i32) -> () { current_cpu_exception = n; } - #[no_mangle] pub unsafe fn trigger_ud() -> () { dbg_log_c!("#ud"); @@ -930,7 +921,6 @@ pub unsafe fn trigger_ud() -> () { } *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_UD, 0 != 0i32, 0 != 0i32, 0i32); - set_current_cpu_exception(CPU_EXCEPTION_UD); } pub unsafe fn trigger_nm() -> () { @@ -941,7 +931,6 @@ pub unsafe fn trigger_nm() -> () { } *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_NM, 0 != 0i32, 0 != 0i32, 0i32); - set_current_cpu_exception(CPU_EXCEPTION_NM); } #[no_mangle] @@ -953,7 +942,6 @@ pub unsafe fn trigger_gp_non_raising(mut code: i32) -> () { } *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_GP, 0 != 0i32, 0 != 1i32, code); - set_current_cpu_exception(CPU_EXCEPTION_GP); } pub unsafe fn virt_boundary_read16(mut low: i32, mut high: i32) -> i32 { @@ -1015,19 +1003,9 @@ pub unsafe fn virt_boundary_write32(mut low: i32, mut high: i32, mut value: i32) } pub unsafe fn safe_read8(mut addr: i32) -> Result { - assert_no_cpu_exception(); return Ok(read8(translate_address_read(addr)?)); } -pub unsafe fn assert_no_cpu_exception() -> () { - return; - if current_cpu_exception != -1i32 { - dbg_log_c!("Expected no cpu exception, got %d", current_cpu_exception); - dbg_trace(); - dbg_assert!(0 != 0i32); - }; -} - pub unsafe fn safe_read16(mut address: i32) -> Result { let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); @@ -1045,7 +1023,6 @@ pub unsafe fn safe_read16(mut address: i32) -> Result { } pub unsafe fn safe_read16_slow(mut addr: i32) -> Result { - assert_no_cpu_exception(); if addr & 4095i32 == 4095i32 { return Ok(safe_read8(addr)? | safe_read8(addr + 1i32)? << 8i32); } @@ -1055,7 +1032,6 @@ pub unsafe fn safe_read16_slow(mut addr: i32) -> Result { } pub unsafe fn safe_read32s(mut address: i32) -> Result { - assert_no_cpu_exception(); let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); let mut info_bits: i32 = entry & 4095i32 & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; @@ -1122,7 +1098,6 @@ pub unsafe fn safe_read16_slow_jit(addr: i32) -> i32 { v }, Err(()) => { - dbg_log!("page fault"); *page_fault = true; -1 }, @@ -1137,7 +1112,6 @@ pub unsafe fn safe_read32s_slow_jit(addr: i32) -> i32 { v }, Err(()) => { - dbg_log!("page fault"); *page_fault = true; -1 }, @@ -1146,7 +1120,6 @@ pub unsafe fn safe_read32s_slow_jit(addr: i32) -> i32 { pub unsafe fn safe_read64s(mut addr: i32) -> Result { let mut addr_phys: i32 = 0; - assert_no_cpu_exception(); let mut x: reg64 = reg64 { i8_0: [0; 8] }; if addr & 4095i32 > 4096i32 - 8i32 { x.u32_0[0usize] = safe_read32s(addr)? as u32; @@ -1161,7 +1134,6 @@ pub unsafe fn safe_read64s(mut addr: i32) -> Result { pub unsafe fn safe_read128s(mut addr: i32) -> Result { let mut addr_phys: i32 = 0; - assert_no_cpu_exception(); let mut x: reg128 = reg128 { i8_0: [0; 16] }; if addr & 4095i32 > 4096i32 - 16i32 { x.u64_0[0usize] = safe_read64s(addr)?.u64_0[0usize]; @@ -1175,7 +1147,6 @@ pub unsafe fn safe_read128s(mut addr: i32) -> Result { } pub unsafe fn safe_write8(mut addr: i32, mut value: i32) -> Result<(), ()> { - assert_no_cpu_exception(); write8(translate_address_write(addr)?, value); Ok(()) } @@ -1201,7 +1172,6 @@ pub unsafe fn safe_write16(mut address: i32, mut value: i32) -> Result<(), ()> { } pub unsafe fn safe_write16_slow(mut addr: i32, mut value: i32) -> Result<(), ()> { - assert_no_cpu_exception(); let mut phys_low: i32 = translate_address_write(addr)? as i32; if addr & 4095i32 == 4095i32 { virt_boundary_write16( @@ -1217,7 +1187,6 @@ pub unsafe fn safe_write16_slow(mut addr: i32, mut value: i32) -> Result<(), ()> } pub unsafe fn safe_write32(mut address: i32, mut value: i32) -> Result<(), ()> { - assert_no_cpu_exception(); let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); let mut info_bits: i32 = entry & 4095i32 & !TLB_GLOBAL & !if *cpl as i32 == 3i32 { @@ -1307,7 +1276,6 @@ pub unsafe fn safe_write32_slow_jit(addr: i32, value: i32) { } pub unsafe fn safe_write64(mut addr: i32, mut value: i64) -> Result<(), ()> { - assert_no_cpu_exception(); if addr & 4095i32 > 4096i32 - 8i32 { writable_or_pagefault(addr, 8i32)?; safe_write32(addr, value as i32).unwrap(); @@ -1321,7 +1289,6 @@ pub unsafe fn safe_write64(mut addr: i32, mut value: i64) -> Result<(), ()> { } pub unsafe fn safe_write128(mut addr: i32, mut value: reg128) -> Result<(), ()> { - assert_no_cpu_exception(); if addr & 4095i32 > 4096i32 - 16i32 { writable_or_pagefault(addr, 16i32)?; safe_write64(addr, value.u64_0[0usize] as i64).unwrap(); @@ -1700,7 +1667,6 @@ pub unsafe fn trigger_np(mut code: i32) -> () { } *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_NP, 0 != 0i32, 0 != 1i32, code); - set_current_cpu_exception(CPU_EXCEPTION_NP); } #[no_mangle] @@ -1712,7 +1678,6 @@ pub unsafe fn trigger_ss(mut code: i32) -> () { } *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_SS, 0 != 0i32, 0 != 1i32, code); - set_current_cpu_exception(CPU_EXCEPTION_SS); } #[no_mangle] diff --git a/src/rust/jit.rs b/src/rust/jit.rs index e5c8a4e5..78d30f62 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -1136,18 +1136,6 @@ fn jit_generate_basic_block( jit_instructions::jit_instruction(&mut cpu, builder, &mut instruction_flags); let end_eip = cpu.eip; - #[cfg(debug_assertions)] - { - if ::config::CHECK_CPU_EXCEPTIONS { - // only the last instruction in each basic block is allowed to raise - if end_eip < stop_addr { - let fn_idx = - builder.get_fn_idx("assert_no_cpu_exception", module_init::FN0_TYPE_INDEX); - builder.instruction_body.call_fn(fn_idx); - } - } - } - let instruction_length = end_eip - start_eip; let was_block_boundary = instruction_flags & JIT_INSTR_BLOCK_BOUNDARY_FLAG != 0; From b51c6e7c7818698b2ec95826ed295454dac50d2c Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 26 Aug 2018 19:41:28 -0500 Subject: [PATCH 1230/2137] imul_reg16: Do sign extension in function --- src/rust/cpu2/arith.rs | 4 ++-- src/rust/cpu2/instructions.rs | 23 ++++------------------- src/rust/cpu2/instructions_0f.rs | 10 ++-------- 3 files changed, 8 insertions(+), 29 deletions(-) diff --git a/src/rust/cpu2/arith.rs b/src/rust/cpu2/arith.rs index 7d760f3f..044d5bfa 100644 --- a/src/rust/cpu2/arith.rs +++ b/src/rust/cpu2/arith.rs @@ -204,8 +204,8 @@ pub unsafe fn imul16(mut source_operand: i32) -> () { } #[no_mangle] pub unsafe fn imul_reg16(mut operand1: i32, mut operand2: i32) -> i32 { - dbg_assert!(operand1 < 32768i32 && operand1 >= -32768i32); - dbg_assert!(operand2 < 32768i32 && operand2 >= -32768i32); + operand1 = operand1 << 16 >> 16; + operand2 = operand2 << 16 >> 16; let mut result: i32 = operand1 * operand2; *last_result = result & 65535i32; *last_op_size = OPSIZE_16; diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index 96e62647..605663cd 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -1005,20 +1005,11 @@ pub unsafe fn instr32_68(mut imm32: i32) -> () { } #[no_mangle] pub unsafe fn instr16_69_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { - write_reg16( - r, - imul_reg16( - return_on_pagefault!(safe_read16(addr)) << 16i32 >> 16i32, - imm << 16i32 >> 16i32, - ), - ); + write_reg16(r, imul_reg16(return_on_pagefault!(safe_read16(addr)), imm)); } #[no_mangle] pub unsafe fn instr16_69_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { - write_reg16( - r, - imul_reg16(read_reg16(r1) << 16i32 >> 16i32, imm << 16i32 >> 16i32), - ); + write_reg16(r, imul_reg16(read_reg16(r1), imm)); } #[no_mangle] pub unsafe fn instr32_69_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { @@ -1038,17 +1029,11 @@ pub unsafe fn instr32_6A(mut imm8: i32) -> () { } #[no_mangle] pub unsafe fn instr16_6B_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { - write_reg16( - r, - imul_reg16( - return_on_pagefault!(safe_read16(addr)) << 16i32 >> 16i32, - imm, - ), - ); + write_reg16(r, imul_reg16(return_on_pagefault!(safe_read16(addr)), imm)); } #[no_mangle] pub unsafe fn instr16_6B_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { - write_reg16(r, imul_reg16(read_reg16(r1) << 16i32 >> 16i32, imm)); + write_reg16(r, imul_reg16(read_reg16(r1), imm)); } #[no_mangle] pub unsafe fn instr32_6B_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index bf1de372..23910224 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -3374,18 +3374,12 @@ pub unsafe fn instr_0FAE_7_mem(mut addr: i32) -> () { #[no_mangle] pub unsafe fn instr16_0FAF_mem(mut addr: i32, mut r: i32) -> () { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); - write_reg16( - r, - imul_reg16(read_reg16(r) << 16i32 >> 16i32, ____0 << 16i32 >> 16i32), - ); + write_reg16(r, imul_reg16(read_reg16(r), ____0)); } #[no_mangle] pub unsafe fn instr16_0FAF_reg(mut r1: i32, mut r: i32) -> () { let mut ____0: i32 = read_reg16(r1); - write_reg16( - r, - imul_reg16(read_reg16(r) << 16i32 >> 16i32, ____0 << 16i32 >> 16i32), - ); + write_reg16(r, imul_reg16(read_reg16(r), ____0)); } #[no_mangle] pub unsafe fn instr32_0FAF_mem(mut addr: i32, mut r: i32) -> () { From 3bb3e21962ad3856f8b650bd858bf578a7033f3f Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 26 Aug 2018 19:44:03 -0500 Subject: [PATCH 1231/2137] mxcsr: Warn on 'Denormals Are Zero' --- src/rust/cpu2/cpu.rs | 2 +- src/rust/cpu2/instructions_0f.rs | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 238f79a0..78016b67 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -197,7 +197,7 @@ pub const LOG_CPU: i32 = 2i32; pub const A20_MASK: i32 = !(1i32 << 20i32); pub const A20_MASK16: i32 = !(1i32 << 20i32 - 1i32); pub const A20_MASK32: i32 = !(1i32 << 20i32 - 2i32); -pub const MXCSR_MASK: i32 = 65535i32 & !(1i32 << 6i32); +pub const MXCSR_MASK: i32 = 0xffff; pub const VALID_TLB_ENTRY_MAX: i32 = 10000i32; pub const TLB_VALID: i32 = 1i32 << 0i32; pub const TLB_READONLY: i32 = 1i32 << 1i32; diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 23910224..00d11974 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -3316,9 +3316,11 @@ pub unsafe fn instr_0FAE_2_reg(mut r: i32) -> () { unimplemented_sse(); } pub unsafe fn instr_0FAE_2_mem(mut addr: i32) -> () { c_comment!(("ldmxcsr")); let mut new_mxcsr: i32 = return_on_pagefault!(safe_read32s(addr)); + if new_mxcsr & 1 << 6 != 0 { + dbg_log!("Warning: Unimplemented MXCSR bit: {:x}", new_mxcsr) + } if 0 != new_mxcsr & !MXCSR_MASK { - dbg_log_c!("Invalid mxcsr bits: %x", new_mxcsr & !MXCSR_MASK); - dbg_assert!(0 != 0i32); + dbg_log!("Invalid mxcsr bits: {:x}", new_mxcsr & !MXCSR_MASK); trigger_gp_non_raising(0i32); return; } From 38a84342a2d9bdd89f85b9db77c9d7fb56b7398f Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 26 Aug 2018 19:47:02 -0500 Subject: [PATCH 1232/2137] Give Rust more indirect function slots and clean up the code --- src/browser/starter.js | 2 +- src/const.js | 3 +++ src/cpu.js | 7 +++---- src/rust/cpu2/cpu.rs | 6 +++++- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 55ef3784..89b2c0d7 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -105,7 +105,7 @@ function V86Starter(options) // }, this); //} - const wasm_table = new WebAssembly.Table({ element: "anyfunc", "initial": 0x10000 + 0x100 }); + const wasm_table = new WebAssembly.Table({ element: "anyfunc", "initial": WASM_TABLE_SIZE + WASM_TABLE_OFFSET }); var wasm_shared_funcs = { "__assert_fail": (condition, file, line, fun) => { diff --git a/src/const.js b/src/const.js index d9865c51..4c8c9e6a 100644 --- a/src/const.js +++ b/src/const.js @@ -358,6 +358,9 @@ const P_RUN_INTERPRETED = 4; /** @const */ var WASM_TABLE_SIZE = 0x10000; +/** @const */ +var WASM_TABLE_OFFSET = 1024; + /** @const */ var JIT_CACHE_ARRAY_SIZE = 0x40000; diff --git a/src/cpu.js b/src/cpu.js index 249f2610..fca9b98b 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -369,7 +369,7 @@ CPU.prototype.jit_force_generate = function(addr) CPU.prototype.jit_clear_func = function(index) { dbg_assert(index >= 0 && index < WASM_TABLE_SIZE); - this.wm.imports.env[WASM_EXPORT_TABLE_NAME + 0x100].set(index, null); + this.wm.imports.env[WASM_EXPORT_TABLE_NAME].set(index + WASM_TABLE_OFFSET, null); }; CPU.prototype.get_state = function() @@ -1318,7 +1318,7 @@ CPU.prototype.codegen_finalize = function(wasm_table_index, start, end, first_op first_opcode, state_flags); // The following will throw if f isn't an exported function - this.wm.imports["env"][WASM_EXPORT_TABLE_NAME].set(wasm_table_index + 0x100, f); + this.wm.imports["env"][WASM_EXPORT_TABLE_NAME].set(wasm_table_index + WASM_TABLE_OFFSET, f); if(this.test_hook_did_finalize_wasm) { @@ -1498,11 +1498,10 @@ CPU.prototype.jit_clear_cache = function() this.jit_empty_cache(); const table = this.wm.exports[WASM_EXPORT_TABLE_NAME] || this.wm.imports["env"][WASM_EXPORT_TABLE_NAME]; - const offset = 0x100; for(let i = 0; i < WASM_TABLE_SIZE; i++) { - table.set(offset + i, null); + table.set(WASM_TABLE_OFFSET + i, null); } }; diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 78016b67..b490445b 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -33,6 +33,10 @@ use cpu2::modrm::{resolve_modrm16, resolve_modrm32}; use cpu2::profiler::*; use cpu2::profiler::{profiler_stat_increment, profiler_stat_increment_by}; +/// The offset for our generated functions in the wasm table. Every index less than this is +/// reserved for rustc's indirect functions +pub const WASM_TABLE_OFFSET: u32 = 1024; + #[derive(Copy, Clone)] #[repr(C)] pub union reg64 { @@ -777,7 +781,7 @@ pub unsafe fn cycle_internal() -> () { wasm_table_index = (entry & 65535i32 as u32) as u16; initial_state = (entry >> 16i32) as u16; call_indirect1( - (wasm_table_index as u32).wrapping_add(256i32 as u32) as i32, + (wasm_table_index as u32).wrapping_add(WASM_TABLE_OFFSET as u32) as i32, initial_state, ); profiler_stat_increment_by( From 33f781e3ba158ed9808c256066a2f428bffb3854 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 26 Aug 2018 19:52:52 -0500 Subject: [PATCH 1233/2137] Set DEBUG to false for release build --- src/rust/cpu2/cpu.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index b490445b..898bbdf5 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -228,8 +228,8 @@ pub const CPU_EXCEPTION_AC: i32 = 17i32; pub const CPU_EXCEPTION_MC: i32 = 18i32; pub const CPU_EXCEPTION_XM: i32 = 19i32; pub const CPU_EXCEPTION_VE: i32 = 20i32; -pub const CHECK_TLB_INVARIANTS: bool = 0 != 0i32; -pub const DEBUG: bool = 0 != 1i32; +pub const CHECK_TLB_INVARIANTS: bool = false; +pub const DEBUG: bool = cfg!(debug_assertions); pub const LOOP_COUNTER: i32 = 20011i32; pub const TSC_RATE: f64 = (50i32 * 1000i32) as f64; From 3b1063d58a80d6543ab732ed393b64edd3e7011c Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 26 Aug 2018 20:07:01 -0500 Subject: [PATCH 1234/2137] Expect tests: Accept TEST_NAME env variable --- tests/expect/run.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/expect/run.js b/tests/expect/run.js index ac3bca51..26b6425a 100755 --- a/tests/expect/run.js +++ b/tests/expect/run.js @@ -18,6 +18,8 @@ catch(e) { process.exit(1); } +const TEST_NAME = process.env.TEST_NAME; + const LOG_LEVEL = 0; const GIT_DIFF_FLAGS = ["--no-index", "--patience", "--color=always"]; @@ -39,7 +41,7 @@ function run_all() asm_file: path.join(TEST_DIR, name + ".asm"), executable_file: path.join(BUILD_DIR, name + ".bin"), }; - }); + }).filter(({ name }) => !TEST_NAME || name === TEST_NAME); next_test(0); From 12eb838939a95ef0f4dfc4156d742981794b75fe Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 26 Aug 2018 20:07:23 -0500 Subject: [PATCH 1235/2137] Expect tests: Catch libwabt errors and try to help --- tests/expect/run.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/expect/run.js b/tests/expect/run.js index 26b6425a..70dd307f 100755 --- a/tests/expect/run.js +++ b/tests/expect/run.js @@ -211,6 +211,12 @@ function disassemble_wasm(wasm) module.applyNames(); return module.toText({ foldExprs: true, inlineExport: true }); } + catch(e) + { + console.error("Error while running libwabt: " + e.toString()); + console.error("Did you forget an ending hlt instruction?\n"); + throw e; + } finally { module && module.destroy(); From fa50294b47e71fa582624c85e446dff02cf762d8 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 26 Aug 2018 20:10:34 -0500 Subject: [PATCH 1236/2137] Generate code for read-modify-write instructions (C1/D1/D3: Shifts and rotates) --- gen/x86_table.js | 6 +- src/rust/codegen.rs | 12 + src/rust/jit_instructions.rs | 497 +++++++++++++++++++++++++++++++++++ src/rust/regs.rs | 10 +- 4 files changed, 521 insertions(+), 4 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index f61cf0b1..8dd42ac1 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -843,11 +843,11 @@ for(let i = 0; i < 8; i++) // note: overflow flag only undefined if shift is > 1 // note: the adjust flag is undefined for shifts > 0 and unaffected by rotates { opcode: 0xC0, nonfaulting: 1, e: 1, fixed_g: i, imm8: 1, mask_flags: of | af, }, - { opcode: 0xC1, nonfaulting: 1, os: 1, e: 1, fixed_g: i, imm8: 1, mask_flags: of | af, }, + { opcode: 0xC1, nonfaulting: 1, os: 1, e: 1, fixed_g: i, imm8: 1, mask_flags: of | af, custom: 1, }, { opcode: 0xD0, nonfaulting: 1, e: 1, fixed_g: i, mask_flags: af, }, - { opcode: 0xD1, nonfaulting: 1, os: 1, e: 1, fixed_g: i, mask_flags: af, }, + { opcode: 0xD1, nonfaulting: 1, os: 1, e: 1, fixed_g: i, mask_flags: af, custom: 1, }, { opcode: 0xD2, nonfaulting: 1, e: 1, fixed_g: i, mask_flags: of | af, }, - { opcode: 0xD3, nonfaulting: 1, os: 1, e: 1, fixed_g: i, mask_flags: of | af, }, + { opcode: 0xD3, nonfaulting: 1, os: 1, e: 1, fixed_g: i, mask_flags: of | af, custom: 1, }, { opcode: 0xD8, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, }, diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index ecad5c70..7f516692 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -126,6 +126,12 @@ pub fn gen_fn2_const(ctx: &mut JitContext, name: &str, arg0: u32, arg1: u32) { builder.instruction_body.call_fn(fn_idx); } +pub fn gen_call_fn1(builder: &mut WasmBuilder, name: &str) { + // generates: fn( _ ) where _ must be left on the stack before calling this + let fn_idx = builder.get_fn_idx(name, module_init::FN1_TYPE_INDEX); + builder.instruction_body.call_fn(fn_idx); +} + pub fn gen_call_fn2(builder: &mut WasmBuilder, name: &str) { // generates: fn( _, _ ) where _ must be left on the stack before calling this let fn_idx = builder.get_fn_idx(name, module_init::FN2_TYPE_INDEX); @@ -138,6 +144,12 @@ pub fn gen_call_fn2_ret(builder: &mut WasmBuilder, name: &str) { builder.instruction_body.call_fn(fn_idx); } +pub fn gen_call_fn3(ctx: &mut JitContext, name: &str) { + let builder = &mut ctx.builder; + let fn_idx = builder.get_fn_idx(name, module_init::FN3_TYPE_INDEX); + builder.instruction_body.call_fn(fn_idx); +} + pub fn gen_fn3_const(ctx: &mut JitContext, name: &str, arg0: u32, arg1: u32, arg2: u32) { let builder = &mut ctx.builder; let fn_idx = builder.get_fn_idx(name, module_init::FN3_TYPE_INDEX); diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 8fb47880..ae28fc65 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -304,6 +304,7 @@ macro_rules! define_instruction_write_reg32( ); macro_rules! make_imm_read( + ($ctx:expr, imm8) => { $ctx.cpu.read_imm8() }; ($ctx:expr, imm8s) => { $ctx.cpu.read_imm8s() }; ($ctx:expr, imm16) => { $ctx.cpu.read_imm16() }; ($ctx:expr, imm32) => { $ctx.cpu.read_imm32() }; @@ -333,6 +334,74 @@ macro_rules! define_instruction_read_write_mem16( } ); + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, constant_one) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_safe_read_write(ctx, BitSize::WORD, &address_local, &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(1); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + }, &|ref mut ctx| { + codegen::gen_call_fn1(ctx.builder, $fallback_fn) + }); + ctx.builder.free_local(address_local); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32) { + ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r1) as i32); + codegen::gen_get_reg16(ctx.builder, r1); + ctx.builder.instruction_body.const_i32(1); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + ctx.builder.instruction_body.store_aligned_u16(0); + } + ); + + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, cl) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_safe_read_write(ctx, BitSize::WORD, &address_local, &|ref mut ctx| { + codegen::gen_get_reg8(ctx.builder, regs::CL); + ctx.builder.instruction_body.const_i32(31); + ctx.builder.instruction_body.and_i32(); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + }, &|ref mut ctx| { + codegen::gen_call_fn1(ctx.builder, $fallback_fn) + }); + ctx.builder.free_local(address_local); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32) { + ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r1) as i32); + codegen::gen_get_reg16(ctx.builder, r1); + codegen::gen_get_reg8(ctx.builder, regs::CL); + ctx.builder.instruction_body.const_i32(31); + ctx.builder.instruction_body.and_i32(); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + ctx.builder.instruction_body.store_aligned_u16(0); + } + ); + + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, none) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_safe_read_write(ctx, BitSize::WORD, &address_local, &|ref mut ctx| { + codegen::gen_call_fn1_ret(ctx.builder, $fn); + }, &|ref mut ctx| { + codegen::gen_call_fn1(ctx.builder, $fallback_fn) + }); + ctx.builder.free_local(address_local); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32) { + ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r1) as i32); + codegen::gen_get_reg16(ctx.builder, r1); + codegen::gen_call_fn1_ret(ctx.builder, $fn); + ctx.builder.instruction_body.store_aligned_u16(0); + } + ); + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, $imm:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); @@ -382,6 +451,74 @@ macro_rules! define_instruction_read_write_mem32( } ); + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, constant_one) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(1); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + }, &|ref mut ctx| { + codegen::gen_call_fn1(ctx.builder, $fallback_fn) + }); + ctx.builder.free_local(address_local); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32) { + ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r1) as i32); + codegen::gen_get_reg32(ctx.builder, r1); + ctx.builder.instruction_body.const_i32(1); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + ctx.builder.instruction_body.store_aligned_i32(0); + } + ); + + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, cl) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { + codegen::gen_get_reg8(ctx.builder, regs::CL); + ctx.builder.instruction_body.const_i32(31); + ctx.builder.instruction_body.and_i32(); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + }, &|ref mut ctx| { + codegen::gen_call_fn1(ctx.builder, $fallback_fn) + }); + ctx.builder.free_local(address_local); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32) { + ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r1) as i32); + codegen::gen_get_reg32(ctx.builder, r1); + codegen::gen_get_reg8(ctx.builder, regs::CL); + ctx.builder.instruction_body.const_i32(31); + ctx.builder.instruction_body.and_i32(); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + ctx.builder.instruction_body.store_aligned_i32(0); + } + ); + + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, none) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { + codegen::gen_call_fn1_ret(ctx.builder, $fn); + }, &|ref mut ctx| { + codegen::gen_call_fn1(ctx.builder, $fallback_fn) + }); + ctx.builder.free_local(address_local); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32) { + ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r1) as i32); + codegen::gen_get_reg32(ctx.builder, r1); + codegen::gen_call_fn1_ret(ctx.builder, $fn); + ctx.builder.instruction_body.store_aligned_i32(0); + } + ); + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, $imm:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); @@ -1027,6 +1164,126 @@ pub fn instr32_8F_0_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_fn1_const(ctx, "instr32_8F_0_reg", r); } +define_instruction_read_write_mem16!( + "rol16", + "instr16_C1_0_mem", + instr16_C1_0_mem_jit, + instr16_C1_0_reg_jit, + imm8 +); +define_instruction_read_write_mem32!( + "rol32", + "instr32_C1_0_mem", + instr32_C1_0_mem_jit, + instr32_C1_0_reg_jit, + imm8 +); + +define_instruction_read_write_mem16!( + "ror16", + "instr16_C1_1_mem", + instr16_C1_1_mem_jit, + instr16_C1_1_reg_jit, + imm8 +); +define_instruction_read_write_mem32!( + "ror32", + "instr32_C1_1_mem", + instr32_C1_1_mem_jit, + instr32_C1_1_reg_jit, + imm8 +); + +define_instruction_read_write_mem16!( + "rcl16", + "instr16_C1_2_mem", + instr16_C1_2_mem_jit, + instr16_C1_2_reg_jit, + imm8 +); +define_instruction_read_write_mem32!( + "rcl32", + "instr32_C1_2_mem", + instr32_C1_2_mem_jit, + instr32_C1_2_reg_jit, + imm8 +); + +define_instruction_read_write_mem16!( + "rcr16", + "instr16_C1_3_mem", + instr16_C1_3_mem_jit, + instr16_C1_3_reg_jit, + imm8 +); +define_instruction_read_write_mem32!( + "rcr32", + "instr32_C1_3_mem", + instr32_C1_3_mem_jit, + instr32_C1_3_reg_jit, + imm8 +); + +define_instruction_read_write_mem16!( + "shl16", + "instr16_C1_4_mem", + instr16_C1_4_mem_jit, + instr16_C1_4_reg_jit, + imm8 +); +define_instruction_read_write_mem32!( + "shl32", + "instr32_C1_4_mem", + instr32_C1_4_mem_jit, + instr32_C1_4_reg_jit, + imm8 +); + +define_instruction_read_write_mem16!( + "shr16", + "instr16_C1_5_mem", + instr16_C1_5_mem_jit, + instr16_C1_5_reg_jit, + imm8 +); +define_instruction_read_write_mem32!( + "shr32", + "instr32_C1_5_mem", + instr32_C1_5_mem_jit, + instr32_C1_5_reg_jit, + imm8 +); + +define_instruction_read_write_mem16!( + "shl16", + "instr16_C1_6_mem", + instr16_C1_6_mem_jit, + instr16_C1_6_reg_jit, + imm8 +); +define_instruction_read_write_mem32!( + "shl32", + "instr32_C1_6_mem", + instr32_C1_6_mem_jit, + instr32_C1_6_reg_jit, + imm8 +); + +define_instruction_read_write_mem16!( + "sar16", + "instr16_C1_7_mem", + instr16_C1_7_mem_jit, + instr16_C1_7_reg_jit, + imm8 +); +define_instruction_read_write_mem32!( + "sar32", + "instr32_C1_7_mem", + instr32_C1_7_mem_jit, + instr32_C1_7_reg_jit, + imm8 +); + pub fn instr16_E8_jit(ctx: &mut JitContext, imm: u32) { codegen::gen_get_real_eip(ctx); let value_local = ctx.builder.set_new_local(); @@ -1090,6 +1347,246 @@ pub fn instr32_C3_jit(ctx: &mut JitContext) { ctx.builder.instruction_body.store_aligned_i32(0); } +define_instruction_read_write_mem16!( + "rol16", + "instr16_D1_0_mem", + instr16_D1_0_mem_jit, + instr16_D1_0_reg_jit, + constant_one +); +define_instruction_read_write_mem32!( + "rol32", + "instr32_D1_0_mem", + instr32_D1_0_mem_jit, + instr32_D1_0_reg_jit, + constant_one +); + +define_instruction_read_write_mem16!( + "ror16", + "instr16_D1_1_mem", + instr16_D1_1_mem_jit, + instr16_D1_1_reg_jit, + constant_one +); +define_instruction_read_write_mem32!( + "ror32", + "instr32_D1_1_mem", + instr32_D1_1_mem_jit, + instr32_D1_1_reg_jit, + constant_one +); + +define_instruction_read_write_mem16!( + "rcl16", + "instr16_D1_2_mem", + instr16_D1_2_mem_jit, + instr16_D1_2_reg_jit, + constant_one +); +define_instruction_read_write_mem32!( + "rcl32", + "instr32_D1_2_mem", + instr32_D1_2_mem_jit, + instr32_D1_2_reg_jit, + constant_one +); + +define_instruction_read_write_mem16!( + "rcr16", + "instr16_D1_3_mem", + instr16_D1_3_mem_jit, + instr16_D1_3_reg_jit, + constant_one +); +define_instruction_read_write_mem32!( + "rcr32", + "instr32_D1_3_mem", + instr32_D1_3_mem_jit, + instr32_D1_3_reg_jit, + constant_one +); + +define_instruction_read_write_mem16!( + "shl16", + "instr16_D1_4_mem", + instr16_D1_4_mem_jit, + instr16_D1_4_reg_jit, + constant_one +); +define_instruction_read_write_mem32!( + "shl32", + "instr32_D1_4_mem", + instr32_D1_4_mem_jit, + instr32_D1_4_reg_jit, + constant_one +); + +define_instruction_read_write_mem16!( + "shr16", + "instr16_D1_5_mem", + instr16_D1_5_mem_jit, + instr16_D1_5_reg_jit, + constant_one +); +define_instruction_read_write_mem32!( + "shr32", + "instr32_D1_5_mem", + instr32_D1_5_mem_jit, + instr32_D1_5_reg_jit, + constant_one +); + +define_instruction_read_write_mem16!( + "shl16", + "instr16_D1_6_mem", + instr16_D1_6_mem_jit, + instr16_D1_6_reg_jit, + constant_one +); +define_instruction_read_write_mem32!( + "shl32", + "instr32_D1_6_mem", + instr32_D1_6_mem_jit, + instr32_D1_6_reg_jit, + constant_one +); + +define_instruction_read_write_mem16!( + "sar16", + "instr16_D1_7_mem", + instr16_D1_7_mem_jit, + instr16_D1_7_reg_jit, + constant_one +); +define_instruction_read_write_mem32!( + "sar32", + "instr32_D1_7_mem", + instr32_D1_7_mem_jit, + instr32_D1_7_reg_jit, + constant_one +); + +define_instruction_read_write_mem16!( + "rol16", + "instr16_D3_0_mem", + instr16_D3_0_mem_jit, + instr16_D3_0_reg_jit, + cl +); +define_instruction_read_write_mem32!( + "rol32", + "instr32_D3_0_mem", + instr32_D3_0_mem_jit, + instr32_D3_0_reg_jit, + cl +); + +define_instruction_read_write_mem16!( + "ror16", + "instr16_D3_1_mem", + instr16_D3_1_mem_jit, + instr16_D3_1_reg_jit, + cl +); +define_instruction_read_write_mem32!( + "ror32", + "instr32_D3_1_mem", + instr32_D3_1_mem_jit, + instr32_D3_1_reg_jit, + cl +); + +define_instruction_read_write_mem16!( + "rcl16", + "instr16_D3_2_mem", + instr16_D3_2_mem_jit, + instr16_D3_2_reg_jit, + cl +); +define_instruction_read_write_mem32!( + "rcl32", + "instr32_D3_2_mem", + instr32_D3_2_mem_jit, + instr32_D3_2_reg_jit, + cl +); + +define_instruction_read_write_mem16!( + "rcr16", + "instr16_D3_3_mem", + instr16_D3_3_mem_jit, + instr16_D3_3_reg_jit, + cl +); +define_instruction_read_write_mem32!( + "rcr32", + "instr32_D3_3_mem", + instr32_D3_3_mem_jit, + instr32_D3_3_reg_jit, + cl +); + +define_instruction_read_write_mem16!( + "shl16", + "instr16_D3_4_mem", + instr16_D3_4_mem_jit, + instr16_D3_4_reg_jit, + cl +); +define_instruction_read_write_mem32!( + "shl32", + "instr32_D3_4_mem", + instr32_D3_4_mem_jit, + instr32_D3_4_reg_jit, + cl +); + +define_instruction_read_write_mem16!( + "shr16", + "instr16_D3_5_mem", + instr16_D3_5_mem_jit, + instr16_D3_5_reg_jit, + cl +); +define_instruction_read_write_mem32!( + "shr32", + "instr32_D3_5_mem", + instr32_D3_5_mem_jit, + instr32_D3_5_reg_jit, + cl +); + +define_instruction_read_write_mem16!( + "shl16", + "instr16_D3_6_mem", + instr16_D3_6_mem_jit, + instr16_D3_6_reg_jit, + cl +); +define_instruction_read_write_mem32!( + "shl32", + "instr32_D3_6_mem", + instr32_D3_6_mem_jit, + instr32_D3_6_reg_jit, + cl +); + +define_instruction_read_write_mem16!( + "sar16", + "instr16_D3_7_mem", + instr16_D3_7_mem_jit, + instr16_D3_7_reg_jit, + cl +); +define_instruction_read_write_mem32!( + "sar32", + "instr32_D3_7_mem", + instr32_D3_7_mem_jit, + instr32_D3_7_reg_jit, + cl +); + pub fn instr16_EB_jit(ctx: &mut JitContext, imm8: u32) { codegen::gen_jmp_rel16(ctx, imm8 as u16); // dbg_assert(is_asize_32() || get_real_eip() < 0x10000); diff --git a/src/rust/regs.rs b/src/rust/regs.rs index 4f32dce2..007953dc 100644 --- a/src/rust/regs.rs +++ b/src/rust/regs.rs @@ -14,7 +14,6 @@ pub const EBP: u32 = 5; pub const ESI: u32 = 6; pub const EDI: u32 = 7; -// Note: Different from C constants pub const AX: u32 = 0; pub const CX: u32 = 1; pub const DX: u32 = 2; @@ -24,5 +23,14 @@ pub const BP: u32 = 5; pub const SI: u32 = 6; pub const DI: u32 = 7; +pub const AL: u32 = 0; +pub const CL: u32 = 1; +pub const DL: u32 = 2; +pub const BL: u32 = 3; +pub const AH: u32 = 4; +pub const CH: u32 = 5; +pub const DH: u32 = 6; +pub const BH: u32 = 7; + pub const CR0_EM: u32 = 1 << 2; pub const CR0_TS: u32 = 1 << 3; From de01a4b2658405dabbaca80ef7201dd956fdf08a Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 26 Aug 2018 20:18:22 -0500 Subject: [PATCH 1237/2137] Generate code for memory instructions (F6/F7/FF_{0,1}: test/inc/dec) --- gen/x86_table.js | 12 ++--- src/rust/jit_instructions.rs | 93 ++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 6 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 8dd42ac1..96dc335c 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -274,8 +274,8 @@ const encodings = [ { opcode: 0xF4, block_boundary: 1, no_next_instruction: 1, skip: 1, }, // hlt { opcode: 0xF5, nonfaulting: 1, }, - { opcode: 0xF6, e: 1, fixed_g: 0, nonfaulting: 1, imm8: 1, }, - { opcode: 0xF6, e: 1, fixed_g: 1, nonfaulting: 1, imm8: 1, }, + { opcode: 0xF6, e: 1, fixed_g: 0, nonfaulting: 1, imm8: 1, custom: 1 }, + { opcode: 0xF6, e: 1, fixed_g: 1, nonfaulting: 1, imm8: 1, custom: 1 }, { opcode: 0xF6, e: 1, fixed_g: 2, nonfaulting: 1, }, { opcode: 0xF6, e: 1, fixed_g: 3, nonfaulting: 1, }, { opcode: 0xF6, e: 1, fixed_g: 4, nonfaulting: 1, mask_flags: af | zf, }, @@ -283,8 +283,8 @@ const encodings = [ { opcode: 0xF6, e: 1, fixed_g: 6, block_boundary: 1, }, // div/idiv: Not a block boundary, but doesn't use control flow exceptions { opcode: 0xF6, e: 1, fixed_g: 7, block_boundary: 1, }, - { opcode: 0xF7, os: 1, e: 1, fixed_g: 0, nonfaulting: 1, imm1632: 1, }, - { opcode: 0xF7, os: 1, e: 1, fixed_g: 1, nonfaulting: 1, imm1632: 1, }, + { opcode: 0xF7, os: 1, e: 1, fixed_g: 0, nonfaulting: 1, imm1632: 1, custom: 1 }, + { opcode: 0xF7, os: 1, e: 1, fixed_g: 1, nonfaulting: 1, imm1632: 1, custom: 1 }, { opcode: 0xF7, os: 1, e: 1, fixed_g: 2, nonfaulting: 1, }, { opcode: 0xF7, os: 1, e: 1, fixed_g: 3, nonfaulting: 1, }, { opcode: 0xF7, os: 1, e: 1, fixed_g: 4, nonfaulting: 1, mask_flags: zf | af, }, @@ -303,8 +303,8 @@ const encodings = [ { opcode: 0xFE, e: 1, fixed_g: 0, nonfaulting: 1, }, { opcode: 0xFE, e: 1, fixed_g: 1, nonfaulting: 1, }, - { opcode: 0xFF, os: 1, e: 1, fixed_g: 0, nonfaulting: 1, }, - { opcode: 0xFF, os: 1, e: 1, fixed_g: 1, nonfaulting: 1, }, + { opcode: 0xFF, os: 1, e: 1, fixed_g: 0, nonfaulting: 1, custom: 1, }, + { opcode: 0xFF, os: 1, e: 1, fixed_g: 1, nonfaulting: 1, custom: 1, }, { opcode: 0xFF, os: 1, e: 1, fixed_g: 2, block_boundary: 1, skip: 1, }, { opcode: 0xFF, os: 1, e: 1, fixed_g: 3, block_boundary: 1, skip: 1, }, { opcode: 0xFF, os: 1, e: 1, fixed_g: 4, block_boundary: 1, no_next_instruction: 1, skip: 1, }, diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index ae28fc65..fdf19d88 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1598,6 +1598,99 @@ pub fn instr32_EB_jit(ctx: &mut JitContext, imm8: u32) { // dbg_assert(is_asize_32() || get_real_eip() < 0x10000); } +pub fn instr_F6_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read8(ctx); + let imm = ctx.cpu.read_imm8(); + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn2(ctx.builder, "test8") +} + +pub fn instr_F6_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { + codegen::gen_get_reg8(ctx.builder, r); + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn2(ctx.builder, "test8") +} + +pub fn instr_F6_1_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + instr_F6_0_mem_jit(ctx, modrm_byte) +} +pub fn instr_F6_1_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { + instr_F6_0_reg_jit(ctx, r, imm) +} + +pub fn instr16_F7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read16(ctx); + let imm = ctx.cpu.read_imm16(); + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn2(ctx.builder, "test16") +} + +pub fn instr16_F7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { + codegen::gen_get_reg16(ctx.builder, r); + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn2(ctx.builder, "test16") +} + +pub fn instr16_F7_1_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + instr16_F7_0_mem_jit(ctx, modrm_byte) +} +pub fn instr16_F7_1_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { + instr16_F7_0_reg_jit(ctx, r, imm) +} + +pub fn instr32_F7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read32(ctx); + let imm = ctx.cpu.read_imm32(); + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn2(ctx.builder, "test32") +} + +pub fn instr32_F7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { + codegen::gen_get_reg32(ctx.builder, r); + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn2(ctx.builder, "test32") +} + +pub fn instr32_F7_1_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + instr32_F7_0_mem_jit(ctx, modrm_byte) +} +pub fn instr32_F7_1_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { + instr32_F7_0_reg_jit(ctx, r, imm) +} + +define_instruction_read_write_mem16!( + "inc16", + "instr16_FF_0_mem", + instr16_FF_0_mem_jit, + instr16_FF_0_reg_jit, + none +); +define_instruction_read_write_mem32!( + "inc32", + "instr32_FF_0_mem", + instr32_FF_0_mem_jit, + instr32_FF_0_reg_jit, + none +); + +define_instruction_read_write_mem16!( + "dec16", + "instr16_FF_1_mem", + instr16_FF_1_mem_jit, + instr16_FF_1_reg_jit, + none +); +define_instruction_read_write_mem32!( + "dec32", + "instr32_FF_1_mem", + instr32_FF_1_mem_jit, + instr32_FF_1_reg_jit, + none +); + pub fn instr16_FF_6_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { push16_mem_jit(ctx, modrm_byte) } From 5dd26ead30fcceafde8132095ef5393bb336a538 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 26 Aug 2018 20:22:17 -0500 Subject: [PATCH 1238/2137] Generate code for memory instructions (0F4*, 0F9*, 0FAF: cmovcc, setcc, imul) --- gen/x86_table.js | 66 +++++++++---------- src/rust/jit_instructions.rs | 119 +++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+), 33 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 96dc335c..1253180d 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -380,22 +380,22 @@ const encodings = [ { opcode: 0x0F3E, skip: 1 }, { opcode: 0x0F3F, skip: 1 }, - { opcode: 0x0F40, nonfaulting: 1, e: 1, os: 1, }, - { opcode: 0x0F41, nonfaulting: 1, e: 1, os: 1, }, - { opcode: 0x0F42, nonfaulting: 1, e: 1, os: 1, }, - { opcode: 0x0F43, nonfaulting: 1, e: 1, os: 1, }, - { opcode: 0x0F44, nonfaulting: 1, e: 1, os: 1, }, - { opcode: 0x0F45, nonfaulting: 1, e: 1, os: 1, }, - { opcode: 0x0F46, nonfaulting: 1, e: 1, os: 1, }, - { opcode: 0x0F47, nonfaulting: 1, e: 1, os: 1, }, - { opcode: 0x0F48, nonfaulting: 1, e: 1, os: 1, }, - { opcode: 0x0F49, nonfaulting: 1, e: 1, os: 1, }, - { opcode: 0x0F4A, nonfaulting: 1, e: 1, os: 1, }, - { opcode: 0x0F4B, nonfaulting: 1, e: 1, os: 1, }, - { opcode: 0x0F4C, nonfaulting: 1, e: 1, os: 1, }, - { opcode: 0x0F4D, nonfaulting: 1, e: 1, os: 1, }, - { opcode: 0x0F4E, nonfaulting: 1, e: 1, os: 1, }, - { opcode: 0x0F4F, nonfaulting: 1, e: 1, os: 1, }, + { opcode: 0x0F40, nonfaulting: 1, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F41, nonfaulting: 1, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F42, nonfaulting: 1, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F43, nonfaulting: 1, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F44, nonfaulting: 1, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F45, nonfaulting: 1, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F46, nonfaulting: 1, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F47, nonfaulting: 1, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F48, nonfaulting: 1, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F49, nonfaulting: 1, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F4A, nonfaulting: 1, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F4B, nonfaulting: 1, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F4C, nonfaulting: 1, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F4D, nonfaulting: 1, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F4E, nonfaulting: 1, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F4F, nonfaulting: 1, e: 1, os: 1, custom: 1, }, { opcode: 0x0F80, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, { opcode: 0x0F81, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, @@ -414,22 +414,22 @@ const encodings = [ { opcode: 0x0F8E, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, { opcode: 0x0F8F, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, - { opcode: 0x0F90, nonfaulting: 1, e: 1, }, - { opcode: 0x0F91, nonfaulting: 1, e: 1, }, - { opcode: 0x0F92, nonfaulting: 1, e: 1, }, - { opcode: 0x0F93, nonfaulting: 1, e: 1, }, - { opcode: 0x0F94, nonfaulting: 1, e: 1, }, - { opcode: 0x0F95, nonfaulting: 1, e: 1, }, - { opcode: 0x0F96, nonfaulting: 1, e: 1, }, - { opcode: 0x0F97, nonfaulting: 1, e: 1, }, - { opcode: 0x0F98, nonfaulting: 1, e: 1, }, - { opcode: 0x0F99, nonfaulting: 1, e: 1, }, - { opcode: 0x0F9A, nonfaulting: 1, e: 1, }, - { opcode: 0x0F9B, nonfaulting: 1, e: 1, }, - { opcode: 0x0F9C, nonfaulting: 1, e: 1, }, - { opcode: 0x0F9D, nonfaulting: 1, e: 1, }, - { opcode: 0x0F9E, nonfaulting: 1, e: 1, }, - { opcode: 0x0F9F, nonfaulting: 1, e: 1, }, + { opcode: 0x0F90, nonfaulting: 1, e: 1, custom: 1, }, + { opcode: 0x0F91, nonfaulting: 1, e: 1, custom: 1, }, + { opcode: 0x0F92, nonfaulting: 1, e: 1, custom: 1, }, + { opcode: 0x0F93, nonfaulting: 1, e: 1, custom: 1, }, + { opcode: 0x0F94, nonfaulting: 1, e: 1, custom: 1, }, + { opcode: 0x0F95, nonfaulting: 1, e: 1, custom: 1, }, + { opcode: 0x0F96, nonfaulting: 1, e: 1, custom: 1, }, + { opcode: 0x0F97, nonfaulting: 1, e: 1, custom: 1, }, + { opcode: 0x0F98, nonfaulting: 1, e: 1, custom: 1, }, + { opcode: 0x0F99, nonfaulting: 1, e: 1, custom: 1, }, + { opcode: 0x0F9A, nonfaulting: 1, e: 1, custom: 1, }, + { opcode: 0x0F9B, nonfaulting: 1, e: 1, custom: 1, }, + { opcode: 0x0F9C, nonfaulting: 1, e: 1, custom: 1, }, + { opcode: 0x0F9D, nonfaulting: 1, e: 1, custom: 1, }, + { opcode: 0x0F9E, nonfaulting: 1, e: 1, custom: 1, }, + { opcode: 0x0F9F, nonfaulting: 1, e: 1, custom: 1, }, // XXX: Temporary block boundary { opcode: 0x0FA0, os: 1, skip: 1, block_boundary: 1, }, @@ -475,7 +475,7 @@ const encodings = [ { opcode: 0x0FAE, e: 1, fixed_g: 6, skip: 1, block_boundary: 1, }, // mfence (reg, only 0), xsaveopt (mem, not implemented) { opcode: 0x0FAE, e: 1, fixed_g: 7, skip: 1, block_boundary: 1, }, // sfence (reg, only 0), clflush (mem) - { opcode: 0x0FAF, nonfaulting: 1, os: 1, e: 1, mask_flags: af | zf }, // imul + { opcode: 0x0FAF, nonfaulting: 1, os: 1, e: 1, mask_flags: af | zf, custom: 1, }, // imul { opcode: 0x0FB0, nonfaulting: 1, e: 1 }, // cmxchg { opcode: 0x0FB1, nonfaulting: 1, os: 1, e: 1 }, diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index fdf19d88..e89d77e7 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1889,3 +1889,122 @@ pub fn instr32_C7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { ctx.builder.free_local(address_local); ctx.builder.free_local(value_local); } + +define_instruction_write_reg16!("imul_reg16", instr16_0FAF_mem_jit, instr16_0FAF_reg_jit); +define_instruction_write_reg32!("imul_reg32", instr32_0FAF_mem_jit, instr32_0FAF_reg_jit); + +macro_rules! define_cmovcc16( + ($cond:expr, $name_mem:ident, $name_reg:ident) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_fn0_const_ret(ctx.builder, $cond); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read16(ctx); + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_call_fn3(ctx, "cmovcc16") + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_fn0_const_ret(ctx.builder, $cond); + codegen::gen_get_reg16(ctx.builder, r1); + ctx.builder.instruction_body.const_i32(r2 as i32); + codegen::gen_call_fn3(ctx, "cmovcc16") + } + ); +); + +macro_rules! define_cmovcc32( + ($cond:expr, $name_mem:ident, $name_reg:ident) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_fn0_const_ret(ctx.builder, $cond); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read32(ctx); + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_call_fn3(ctx, "cmovcc32") + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_fn0_const_ret(ctx.builder, $cond); + codegen::gen_get_reg32(ctx.builder, r1); + ctx.builder.instruction_body.const_i32(r2 as i32); + codegen::gen_call_fn3(ctx, "cmovcc32") + } + ); +); + +define_cmovcc16!("test_o", instr16_0F40_mem_jit, instr16_0F40_reg_jit); +define_cmovcc16!("test_no", instr16_0F41_mem_jit, instr16_0F41_reg_jit); +define_cmovcc16!("test_b", instr16_0F42_mem_jit, instr16_0F42_reg_jit); +define_cmovcc16!("test_nb", instr16_0F43_mem_jit, instr16_0F43_reg_jit); +define_cmovcc16!("test_z", instr16_0F44_mem_jit, instr16_0F44_reg_jit); +define_cmovcc16!("test_nz", instr16_0F45_mem_jit, instr16_0F45_reg_jit); +define_cmovcc16!("test_be", instr16_0F46_mem_jit, instr16_0F46_reg_jit); +define_cmovcc16!("test_nbe", instr16_0F47_mem_jit, instr16_0F47_reg_jit); + +define_cmovcc16!("test_s", instr16_0F48_mem_jit, instr16_0F48_reg_jit); +define_cmovcc16!("test_ns", instr16_0F49_mem_jit, instr16_0F49_reg_jit); +define_cmovcc16!("test_p", instr16_0F4A_mem_jit, instr16_0F4A_reg_jit); +define_cmovcc16!("test_np", instr16_0F4B_mem_jit, instr16_0F4B_reg_jit); +define_cmovcc16!("test_l", instr16_0F4C_mem_jit, instr16_0F4C_reg_jit); +define_cmovcc16!("test_nl", instr16_0F4D_mem_jit, instr16_0F4D_reg_jit); +define_cmovcc16!("test_le", instr16_0F4E_mem_jit, instr16_0F4E_reg_jit); +define_cmovcc16!("test_nle", instr16_0F4F_mem_jit, instr16_0F4F_reg_jit); + +define_cmovcc32!("test_o", instr32_0F40_mem_jit, instr32_0F40_reg_jit); +define_cmovcc32!("test_no", instr32_0F41_mem_jit, instr32_0F41_reg_jit); +define_cmovcc32!("test_b", instr32_0F42_mem_jit, instr32_0F42_reg_jit); +define_cmovcc32!("test_nb", instr32_0F43_mem_jit, instr32_0F43_reg_jit); +define_cmovcc32!("test_z", instr32_0F44_mem_jit, instr32_0F44_reg_jit); +define_cmovcc32!("test_nz", instr32_0F45_mem_jit, instr32_0F45_reg_jit); +define_cmovcc32!("test_be", instr32_0F46_mem_jit, instr32_0F46_reg_jit); +define_cmovcc32!("test_nbe", instr32_0F47_mem_jit, instr32_0F47_reg_jit); + +define_cmovcc32!("test_s", instr32_0F48_mem_jit, instr32_0F48_reg_jit); +define_cmovcc32!("test_ns", instr32_0F49_mem_jit, instr32_0F49_reg_jit); +define_cmovcc32!("test_p", instr32_0F4A_mem_jit, instr32_0F4A_reg_jit); +define_cmovcc32!("test_np", instr32_0F4B_mem_jit, instr32_0F4B_reg_jit); +define_cmovcc32!("test_l", instr32_0F4C_mem_jit, instr32_0F4C_reg_jit); +define_cmovcc32!("test_nl", instr32_0F4D_mem_jit, instr32_0F4D_reg_jit); +define_cmovcc32!("test_le", instr32_0F4E_mem_jit, instr32_0F4E_reg_jit); +define_cmovcc32!("test_nle", instr32_0F4F_mem_jit, instr32_0F4F_reg_jit); + +macro_rules! define_setcc( + ($cond:expr, $name_mem:ident, $name_reg:ident) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, _r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_fn0_const_ret(ctx.builder, $cond); + ctx.builder.instruction_body.const_i32(0); + ctx.builder.instruction_body.ne_i32(); + let value_local = ctx.builder.set_new_local(); + codegen::gen_safe_write8(ctx, &address_local, &value_local); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, _r2: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg8_offset(r1) as i32); + codegen::gen_fn0_const_ret(ctx.builder, $cond); + ctx.builder.instruction_body.const_i32(0); + ctx.builder.instruction_body.ne_i32(); + ctx.builder.instruction_body.store_u8(0); + } + ); +); + +define_setcc!("test_o", instr_0F90_mem_jit, instr_0F90_reg_jit); +define_setcc!("test_no", instr_0F91_mem_jit, instr_0F91_reg_jit); +define_setcc!("test_b", instr_0F92_mem_jit, instr_0F92_reg_jit); +define_setcc!("test_nb", instr_0F93_mem_jit, instr_0F93_reg_jit); +define_setcc!("test_z", instr_0F94_mem_jit, instr_0F94_reg_jit); +define_setcc!("test_nz", instr_0F95_mem_jit, instr_0F95_reg_jit); +define_setcc!("test_be", instr_0F96_mem_jit, instr_0F96_reg_jit); +define_setcc!("test_nbe", instr_0F97_mem_jit, instr_0F97_reg_jit); + +define_setcc!("test_s", instr_0F98_mem_jit, instr_0F98_reg_jit); +define_setcc!("test_ns", instr_0F99_mem_jit, instr_0F99_reg_jit); +define_setcc!("test_p", instr_0F9A_mem_jit, instr_0F9A_reg_jit); +define_setcc!("test_np", instr_0F9B_mem_jit, instr_0F9B_reg_jit); +define_setcc!("test_l", instr_0F9C_mem_jit, instr_0F9C_reg_jit); +define_setcc!("test_nl", instr_0F9D_mem_jit, instr_0F9D_reg_jit); +define_setcc!("test_le", instr_0F9E_mem_jit, instr_0F9E_reg_jit); +define_setcc!("test_nle", instr_0F9F_mem_jit, instr_0F9F_reg_jit); From 9e902eb1dccc7ff8a73cbc1bdca363bb13b37f99 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Aug 2018 12:27:25 -0500 Subject: [PATCH 1239/2137] sse: Implement 0F52/rcpps (#57) --- gen/x86_table.js | 8 +++++--- src/rust/cpu2/instructions_0f.rs | 34 +++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 1253180d..b4aac8fc 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -511,8 +511,7 @@ const encodings = [ // mmx, sse - // - Skipped are not implemented - // - Missing are sse3+, and floating point + // - skipped or missing are sse3+ { sse: 1, opcode: 0x0F10, e: 1 }, { sse: 1, opcode: 0xF30F10, e: 1 }, @@ -567,7 +566,10 @@ const encodings = [ { sse: 1, opcode: 0x660F51, e: 1 }, { sse: 1, opcode: 0xF20F51, e: 1 }, { sse: 1, opcode: 0xF30F51, e: 1 }, - { sse: 1, opcode: 0x0F52, skip: 1 }, + + // approximation of 1/sqrt(x). Skipped because our approximation doesn't match intel's + { sse: 1, opcode: 0x0F52, e: 1, skip: 1, }, + { sse: 1, opcode: 0xF30F52, e: 1, skip: 1, }, // reciprocal: approximation of 1/x. Skipped because our approximation doesn't match intel's { sse: 1, opcode: 0x0F53, e: 1, skip: 1, }, diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 00d11974..840cad77 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -5830,8 +5830,40 @@ pub unsafe fn instr_F30F51_reg(mut r1: i32, mut r2: i32) -> () { pub unsafe fn instr_F30F51_mem(mut addr: i32, mut r: i32) -> () { instr_F30F51(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } + #[no_mangle] -pub unsafe fn instr_0F52() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F52(mut source: reg128, mut r: i32) -> () { + c_comment!(("rcpps xmm1, xmm2/m128")); + let mut result: reg128 = reg128 { + f32_0: [ + 1i32 as f32 / source.f32_0[0usize].sqrt(), + 1i32 as f32 / source.f32_0[1usize].sqrt(), + 1i32 as f32 / source.f32_0[2usize].sqrt(), + 1i32 as f32 / source.f32_0[3usize].sqrt(), + ], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe fn instr_0F52_reg(mut r1: i32, mut r2: i32) -> () { instr_0F52(read_xmm128s(r1), r2); } +#[no_mangle] +pub unsafe fn instr_0F52_mem(mut addr: i32, mut r: i32) -> () { + instr_0F52(return_on_pagefault!(safe_read128s(addr)), r); +} +#[no_mangle] +pub unsafe fn instr_F30F52(mut source: f32, mut r: i32) -> () { + c_comment!(("rsqrtss xmm1, xmm2/m32")); + write_xmm_f32(r, 1i32 as f32 / source.sqrt()); +} +#[no_mangle] +pub unsafe fn instr_F30F52_reg(mut r1: i32, mut r2: i32) -> () { + instr_F30F52(read_xmm_f32(r1), r2); +} +#[no_mangle] +pub unsafe fn instr_F30F52_mem(mut addr: i32, mut r: i32) -> () { + instr_F30F52(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); +} + #[no_mangle] pub unsafe fn instr_0F53(mut source: reg128, mut r: i32) -> () { c_comment!(("rcpps xmm, xmm/m128")); From cc507db69bf3a096a2bb45d3d8a2ad33cfdc7410 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Aug 2018 12:29:39 -0500 Subject: [PATCH 1240/2137] sse: Implement 0FC6/shufp[sd] (#57) --- gen/x86_table.js | 3 ++- src/rust/cpu2/instructions_0f.rs | 44 +++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index b4aac8fc..1973e2a5 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -711,7 +711,8 @@ const encodings = [ { sse: 1, opcode: 0x0FC5, e: 1, mem_ud: 1, imm8: 1 }, { sse: 1, opcode: 0x660FC5, e: 1, mem_ud: 1, imm8: 1, }, - { sse: 1, opcode: 0x0FC6, skip: 1, }, + { sse: 1, opcode: 0x0FC6, e: 1, imm8: 1 }, + { sse: 1, opcode: 0x660FC6, e: 1, imm8: 1 }, { sse: 1, opcode: 0x0FD0, skip: 1, }, // sse3 diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 840cad77..134b44bc 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -3816,8 +3816,50 @@ pub unsafe fn instr_660FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i32) -> () { let mut result: u32 = data.u16_0[index as usize] as u32; write_reg32(r2, result as i32); } + #[no_mangle] -pub unsafe fn instr_0FC6() -> () { unimplemented_sse(); } +pub unsafe fn instr_0FC6(mut source: reg128, mut r: i32, mut imm8: i32) -> () { + c_comment!(("shufps xmm, xmm/mem128")); + c_comment!(("XXX: Aligned access or #gp")); + let mut destination: reg128 = read_xmm128s(r); + write_xmm128( + r, + destination.u32_0[(imm8 & 3i32) as usize] as i32, + destination.u32_0[(imm8 >> 2i32 & 3i32) as usize] as i32, + source.u32_0[(imm8 >> 4i32 & 3i32) as usize] as i32, + source.u32_0[(imm8 >> 6i32 & 3i32) as usize] as i32, + ); +} +#[no_mangle] +pub unsafe fn instr_0FC6_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { + instr_0FC6(read_xmm128s(r1), r2, imm); +} +#[no_mangle] +pub unsafe fn instr_0FC6_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { + instr_0FC6(return_on_pagefault!(safe_read128s(addr)), r, imm); +} + +#[no_mangle] +pub unsafe fn instr_660FC6(mut source: reg128, mut r: i32, mut imm8: i32) -> () { + c_comment!(("shufpd xmm, xmm/mem128")); + let mut destination: reg128 = read_xmm128s(r); + let mut result: reg128 = reg128 { + i64_0: [ + destination.i64_0[imm8 as usize & 1], + source.i64_0[imm8 as usize >> 1 & 1], + ], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe fn instr_660FC6_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { + instr_660FC6(read_xmm128s(r1), r2, imm); +} +#[no_mangle] +pub unsafe fn instr_660FC6_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { + instr_660FC6(return_on_pagefault!(safe_read128s(addr)), r, imm); +} + #[no_mangle] pub unsafe fn instr_0FC7_1_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] From 8dc066f73d8d8a4b10dcfeecbdfe5d9d1a038091 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Aug 2018 12:31:21 -0500 Subject: [PATCH 1241/2137] sse: Expand sse3 instruction --- gen/x86_table.js | 2 +- src/rust/cpu2/instructions_0f.rs | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 1973e2a5..43cf3651 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -533,7 +533,7 @@ const encodings = [ { sse: 1, opcode: 0x660F15, e: 1 }, { sse: 1, opcode: 0x0F16, e: 1 }, { sse: 1, opcode: 0x660F16, reg_ud: 1, e: 1 }, - { sse: 1, opcode: 0xF30F16, skip: 1, }, // sse3 + { sse: 1, opcode: 0xF30F16, skip: 1, e: 1 }, // sse3 { sse: 1, opcode: 0x0F17, reg_ud: 1, e: 1 }, { sse: 1, opcode: 0x660F17, reg_ud: 1, e: 1 }, diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 134b44bc..da6631fb 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -5688,7 +5688,10 @@ pub unsafe fn instr_0FFF() -> () { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_F30F16() -> () { unimplemented_sse(); } +pub unsafe fn instr_F30F16_reg(mut r1: i32, mut r2: i32) -> () { unimplemented_sse(); } +#[no_mangle] +pub unsafe fn instr_F30F16_mem(mut addr: i32, mut r: i32) -> () { unimplemented_sse(); } + #[no_mangle] pub unsafe fn instr_0F19_reg(mut r1: i32, mut r2: i32) -> () {} #[no_mangle] From 9665dbf99444927cb01ba02d7360a295046f447c Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Aug 2018 12:34:44 -0500 Subject: [PATCH 1242/2137] sse: Implement 0F2E/0F2F/u?comis[sd] (#57) --- gen/x86_table.js | 6 +- src/rust/cpu2/instructions_0f.rs | 108 ++++++++++++++++++++++++++++++- 2 files changed, 110 insertions(+), 4 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 43cf3651..925b3f40 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -557,8 +557,10 @@ const encodings = [ { sse: 1, opcode: 0xF20F2D, e: 1, }, { sse: 1, opcode: 0xF30F2D, e: 1, skip: 1, }, - { sse: 1, opcode: 0x0F2E, skip: 1 }, - { sse: 1, opcode: 0x0F2F, skip: 1 }, + { sse: 1, opcode: 0x0F2E, e: 1 }, + { sse: 1, opcode: 0x660F2E, e: 1 }, + { sse: 1, opcode: 0x0F2F, e: 1 }, + { sse: 1, opcode: 0x660F2F, e: 1 }, { sse: 1, opcode: 0x0F50, mem_ud: 1, e: 1 }, { sse: 1, opcode: 0x660F50, mem_ud: 1, e: 1 }, diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index da6631fb..4eba2537 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -1042,10 +1042,113 @@ pub unsafe fn instr_F30F2C(mut source: f32, mut r: i32) -> () { unimplemented_ss pub unsafe fn instr_F30F2C_reg(mut r1: i32, mut r2: i32) -> () { instr_F30F2C(read_xmm_f32(r1), r2); } + +pub unsafe fn instr_0F2E(source: f32, r: i32) { + // ucomiss xmm1, xmm2/m32 + let destination = read_xmm_f32(r); + *flags_changed = 0; + *flags &= !FLAGS_ALL; + if destination == source { + *flags |= FLAG_ZERO + } + else if destination < source { + *flags |= FLAG_CARRY + } + else if destination > source { + // all flags cleared + } + else { + // TODO: Signal on SNaN + *flags |= FLAG_ZERO | FLAG_PARITY | FLAG_CARRY + } +} #[no_mangle] -pub unsafe fn instr_0F2E() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F2E_reg(r1: i32, r2: i32) -> () { instr_0F2E(read_xmm_f32(r1), r2) } #[no_mangle] -pub unsafe fn instr_0F2F() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F2E_mem(addr: i32, r: i32) -> () { + instr_0F2E(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); +} + +pub unsafe fn instr_660F2E(source: reg64, r: i32) { + // ucomisd xmm1, xmm2/m64 + let destination = read_xmm64s(r).f64_0[0]; + let source = source.f64_0[0]; + *flags_changed = 0; + *flags &= !FLAGS_ALL; + if destination == source { + *flags |= FLAG_ZERO + } + else if destination < source { + *flags |= FLAG_CARRY + } + else if destination > source { + // all flags cleared + } + else { + // TODO: Signal on SNaN + *flags |= FLAG_ZERO | FLAG_PARITY | FLAG_CARRY + } +} +#[no_mangle] +pub unsafe fn instr_660F2E_reg(r1: i32, r: i32) { instr_660F2E(read_xmm64s(r1), r); } +#[no_mangle] +pub unsafe fn instr_660F2E_mem(addr: i32, r: i32) { + instr_660F2E(return_on_pagefault!(safe_read64s(addr)), r) +} + +pub unsafe fn instr_0F2F(source: f32, r: i32) { + // comiss xmm1, xmm2/m32 + let destination = read_xmm_f32(r); + *flags_changed = 0; + *flags &= !FLAGS_ALL; + if destination == source { + *flags |= FLAG_ZERO + } + else if destination < source { + *flags |= FLAG_CARRY + } + else if destination > source { + // all flags cleared + } + else { + // TODO: Signal on SNaN or QNaN + *flags |= FLAG_ZERO | FLAG_PARITY | FLAG_CARRY + } +} +#[no_mangle] +pub unsafe fn instr_0F2F_reg(r1: i32, r2: i32) -> () { instr_0F2F(read_xmm_f32(r1), r2) } +#[no_mangle] +pub unsafe fn instr_0F2F_mem(addr: i32, r: i32) -> () { + instr_0F2F(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); +} + +pub unsafe fn instr_660F2F(source: reg64, r: i32) { + // comisd xmm1, xmm2/m64 + let destination = read_xmm64s(r).f64_0[0]; + let source = source.f64_0[0]; + *flags_changed = 0; + *flags &= !FLAGS_ALL; + if destination == source { + *flags |= FLAG_ZERO + } + else if destination < source { + *flags |= FLAG_CARRY + } + else if destination > source { + // all flags cleared + } + else { + // TODO: Signal on SNaN or QNaN + *flags |= FLAG_ZERO | FLAG_PARITY | FLAG_CARRY + } +} +#[no_mangle] +pub unsafe fn instr_660F2F_reg(r1: i32, r: i32) { instr_660F2F(read_xmm64s(r1), r); } +#[no_mangle] +pub unsafe fn instr_660F2F_mem(addr: i32, r: i32) { + instr_660F2F(return_on_pagefault!(safe_read64s(addr)), r) +} + #[no_mangle] pub unsafe fn instr_0F30() -> () { c_comment!(("wrmsr - write maschine specific register")); @@ -2455,6 +2558,7 @@ pub unsafe fn instr_660F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { pub unsafe fn instr_660F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { instr_660F70(return_on_pagefault!(safe_read128s(addr)), r, imm); } + #[no_mangle] pub unsafe fn instr_F20F70(mut source: reg128, mut r: i32, mut imm8: i32) -> () { c_comment!(("pshuflw xmm, xmm/m128, imm8")); From 3ea00898781b9873f346af6decc52ffffbb08338 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Aug 2018 12:43:06 -0500 Subject: [PATCH 1243/2137] sse: Implement 0F2C/0F2D/CVTT[PS][SD]2[SP]I (#57) --- gen/x86_table.js | 12 +++--- src/rust/cpu2/instructions_0f.rs | 70 +++++++++++++++++++++++++++----- src/rust/cpu2/sse_instr.rs | 17 +++++++- 3 files changed, 81 insertions(+), 18 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 925b3f40..78792eab 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -548,14 +548,14 @@ const encodings = [ { sse: 1, opcode: 0x0F2B, reg_ud: 1, e: 1 }, { sse: 1, opcode: 0x660F2B, reg_ud: 1, e: 1 }, - { sse: 1, opcode: 0x0F2C, e: 1, skip: 1, }, - { sse: 1, opcode: 0x660F2C, e: 1, skip: 1, }, + { sse: 1, opcode: 0x0F2C, e: 1, }, + { sse: 1, opcode: 0x660F2C, e: 1, }, { sse: 1, opcode: 0xF20F2C, e: 1, }, - { sse: 1, opcode: 0xF30F2C, e: 1, skip: 1, }, - { sse: 1, opcode: 0x0F2D, e: 1, skip: 1, }, - { sse: 1, opcode: 0x660F2D, e: 1, skip: 1, }, + { sse: 1, opcode: 0xF30F2C, e: 1, }, + { sse: 1, opcode: 0x0F2D, e: 1, }, + { sse: 1, opcode: 0x660F2D, e: 1, }, { sse: 1, opcode: 0xF20F2D, e: 1, }, - { sse: 1, opcode: 0xF30F2D, e: 1, skip: 1, }, + { sse: 1, opcode: 0xF30F2D, e: 1, }, { sse: 1, opcode: 0x0F2E, e: 1 }, { sse: 1, opcode: 0x660F2E, e: 1 }, diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 4eba2537..3b48d4b6 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -984,24 +984,46 @@ pub unsafe fn instr_660F2B_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("XXX: Aligned write or #gp")); mov_r_m128(addr, r); } + +#[no_mangle] +pub unsafe fn instr_0F2C(mut source: reg64, mut r: i32) -> () { + // cvttps2pi mm, xmm/m64 + let result = reg64 { + i32_0: [ + sse_convert_f32_to_i32(source.f32_0[0].trunc()), + sse_convert_f32_to_i32(source.f32_0[1].trunc()), + ], + }; + write_mmx_reg64(r, result); +} #[no_mangle] pub unsafe fn instr_0F2C_mem(mut addr: i32, mut r: i32) -> () { instr_0F2C(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F2C(mut source: reg64, mut r: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_0F2C_reg(mut r1: i32, mut r2: i32) -> () { instr_0F2C(read_xmm64s(r1), r2); } + #[no_mangle] -pub unsafe fn instr_0F2C_reg(mut r1: i32, mut r2: i32) -> () { instr_0F2C(read_mmx64s(r1), r2); } +pub unsafe fn instr_660F2C(mut source: reg128, mut r: i32) -> () { + // cvttpd2pi mm, xmm/m128 + let result = reg64 { + // XXX: Check conversion + i32_0: [ + sse_convert_f64_to_i32(source.f64_0[0]), + sse_convert_f64_to_i32(source.f64_0[1]), + ], + }; + write_mmx_reg64(r, result); +} #[no_mangle] pub unsafe fn instr_660F2C_mem(mut addr: i32, mut r: i32) -> () { instr_660F2C(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F2C(mut source: reg128, mut r: i32) -> () { unimplemented_sse(); } -#[no_mangle] pub unsafe fn instr_660F2C_reg(mut r1: i32, mut r2: i32) -> () { instr_660F2C(read_xmm128s(r1), r2); } + #[no_mangle] pub unsafe fn instr_F20F2C(mut source: reg64, mut r: i32) -> () { let mut si: i32 = 0; @@ -1032,13 +1054,17 @@ pub unsafe fn instr_F20F2C_reg(mut r1: i32, mut r2: i32) -> () { pub unsafe fn instr_F20F2C_mem(mut addr: i32, mut r: i32) -> () { instr_F20F2C(return_on_pagefault!(safe_read64s(addr)), r); } + +#[no_mangle] +pub unsafe fn instr_F30F2C(source: f32, mut r: i32) -> () { + let result = source.trunc(); + write_reg32(r, sse_convert_f32_to_i32(source)); +} #[no_mangle] pub unsafe fn instr_F30F2C_mem(mut addr: i32, mut r: i32) -> () { instr_F30F2C(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_F30F2C(mut source: f32, mut r: i32) -> () { unimplemented_sse(); } -#[no_mangle] pub unsafe fn instr_F30F2C_reg(mut r1: i32, mut r2: i32) -> () { instr_F30F2C(read_xmm_f32(r1), r2); } @@ -5874,16 +5900,36 @@ pub unsafe fn instr_F30F2A_reg(mut r1: i32, mut r2: i32) -> () { instr_F30F2A(re pub unsafe fn instr_F30F2A_mem(mut addr: i32, mut r: i32) -> () { instr_F30F2A(return_on_pagefault!(safe_read32s(addr)), r); } + #[no_mangle] -pub unsafe fn instr_0F2D(mut source: reg64, mut r: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_0F2D(mut source: reg64, mut r: i32) -> () { + // cvtps2pi mm, xmm/m64 + let result = reg64 { + i32_0: [ + sse_convert_f32_to_i32(source.f32_0[0].round()), + sse_convert_f32_to_i32(source.f32_0[1].round()), + ], + }; + write_mmx_reg64(r, result); +} #[no_mangle] -pub unsafe fn instr_0F2D_reg(mut r1: i32, mut r2: i32) -> () { instr_0F2D(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F2D_reg(mut r1: i32, mut r2: i32) -> () { instr_0F2D(read_xmm64s(r1), r2); } #[no_mangle] pub unsafe fn instr_0F2D_mem(mut addr: i32, mut r: i32) -> () { instr_0F2D(return_on_pagefault!(safe_read64s(addr)), r); } + #[no_mangle] -pub unsafe fn instr_660F2D(mut source: reg128, mut r: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_660F2D(mut source: reg128, mut r: i32) -> () { + // cvtpd2pi mm, xmm/m128 + let result = reg64 { + i32_0: [ + sse_convert_f64_to_i32(source.f64_0[0].round()), + sse_convert_f64_to_i32(source.f64_0[1].round()), + ], + }; + write_mmx_reg64(r, result); +} #[no_mangle] pub unsafe fn instr_660F2D_reg(mut r1: i32, mut r2: i32) -> () { instr_660F2D(read_xmm128s(r1), r2); @@ -5906,7 +5952,10 @@ pub unsafe fn instr_F20F2D_mem(mut addr: i32, mut r: i32) -> () { instr_F20F2D(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F2D(mut source: f32, mut r: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_F30F2D(mut source: f32, mut r: i32) -> () { + // cvtss2si r32, xmm1/m32 + write_reg32(r, sse_convert_f32_to_i32(source.round())); +} #[no_mangle] pub unsafe fn instr_F30F2D_reg(mut r1: i32, mut r2: i32) -> () { instr_F30F2D(read_xmm_f32(r1), r2); @@ -5915,6 +5964,7 @@ pub unsafe fn instr_F30F2D_reg(mut r1: i32, mut r2: i32) -> () { pub unsafe fn instr_F30F2D_mem(mut addr: i32, mut r: i32) -> () { instr_F30F2D(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } + #[no_mangle] pub unsafe fn instr_0F51(mut source: reg128, mut r: i32) -> () { c_comment!(("sqrtps xmm, xmm/mem128")); diff --git a/src/rust/cpu2/sse_instr.rs b/src/rust/cpu2/sse_instr.rs index eb43c9bc..f589d0e9 100644 --- a/src/rust/cpu2/sse_instr.rs +++ b/src/rust/cpu2/sse_instr.rs @@ -397,10 +397,23 @@ pub unsafe fn sse_max(mut x: f64, mut y: f64) -> f64 { c_comment!(("if both x and y are 0 or x is nan, y is returned")); return if x > y { x } else { y }; } + #[no_mangle] -pub unsafe fn sse_convert_f64_to_i32(mut x: f64) -> i32 { +pub unsafe fn sse_convert_f32_to_i32(mut x: f32) -> i32 { c_comment!(("TODO: Rounding modes")); - if x >= 2147483648u32.wrapping_neg() as f64 && x < 2147483648u32 as f64 { + if x >= -2147483648.0 && x < 2147483648.0 { + return x as i64 as i32; + } + else { + c_comment!(("TODO: Signal")); + return 2147483648u32.wrapping_neg() as i32; + }; +} + +#[no_mangle] +pub unsafe fn sse_convert_f64_to_i32(mut x: f64) -> i32 { + c_comment!(("TODO: Rounding modes")); + if x >= -2147483648.0 as f64 && x < 2147483648.0 as f64 { return x as i64 as i32; } else { From 8ab707dbc2e98f37e17e3d646e0e1452f432aa15 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Aug 2018 12:45:37 -0500 Subject: [PATCH 1244/2137] sse: Implement 0FE6/CVTPD2DQ/CVTTPD2DQ/CVTDQ2PD (#57) --- gen/x86_table.js | 6 +-- src/rust/cpu2/instructions_0f.rs | 68 +++++++++++++++++++++++++++++--- 2 files changed, 65 insertions(+), 9 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 78792eab..c2b827f0 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -767,9 +767,9 @@ const encodings = [ { sse: 1, opcode: 0x0FE5, e: 1 }, { sse: 1, opcode: 0x660FE5, e: 1 }, - { sse: 1, opcode: 0x660FE6, e: 1, skip: 1, }, - { sse: 1, opcode: 0xF20FE6, e: 1, skip: 1, }, - { sse: 1, opcode: 0xF30FE6, e: 1, skip: 1, }, + { sse: 1, opcode: 0x660FE6, e: 1 }, + { sse: 1, opcode: 0xF20FE6, e: 1 }, + { sse: 1, opcode: 0xF30FE6, e: 1 }, { sse: 1, opcode: 0x0FE6, e: 1, block_boundary: 1, }, // ud { sse: 1, opcode: 0x0FE7, e: 1, reg_ud: 1 }, { sse: 1, opcode: 0x660FE7, e: 1, reg_ud: 1, }, diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 3b48d4b6..bd5b60bc 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -4883,22 +4883,78 @@ pub unsafe fn instr_660FE5_reg(mut r1: i32, mut r2: i32) -> () { pub unsafe fn instr_660FE5_mem(mut addr: i32, mut r: i32) -> () { instr_660FE5(return_on_pagefault!(safe_read128s(addr)), r); } + #[no_mangle] pub unsafe fn instr_0FE6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0FE6_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } + #[no_mangle] -pub unsafe fn instr_660FE6_mem(mut addr: i32, mut r: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_660FE6(mut source: reg128, mut r: i32) -> () { + // cvttpd2dq xmm1, xmm2/m128 + let mut result = reg128 { + i32_0: [ + sse_convert_f64_to_i32(source.f64_0[0].trunc()), + sse_convert_f64_to_i32(source.f64_0[1].trunc()), + 0, + 0, + ], + }; + write_xmm_reg128(r, result); +} #[no_mangle] -pub unsafe fn instr_660FE6_reg(mut r1: i32, mut r2: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_660FE6_mem(mut addr: i32, mut r: i32) -> () { + instr_660FE6(return_on_pagefault!(safe_read128s(addr)), r); +} #[no_mangle] -pub unsafe fn instr_F20FE6_mem(mut addr: i32, mut r: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_660FE6_reg(mut r1: i32, mut r2: i32) -> () { + instr_660FE6(read_xmm128s(r1), r2); +} + #[no_mangle] -pub unsafe fn instr_F20FE6_reg(mut r1: i32, mut r2: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_F20FE6(mut source: reg128, mut r: i32) -> () { + // cvtpd2dq xmm1, xmm2/m128 + let mut result = reg128 { + i32_0: [ + // XXX: Precision exception + sse_convert_f64_to_i32(source.f64_0[0].round()), + sse_convert_f64_to_i32(source.f64_0[1].round()), + 0, + 0, + ], + }; + write_xmm_reg128(r, result); +} #[no_mangle] -pub unsafe fn instr_F30FE6_mem(mut addr: i32, mut r: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_F20FE6_mem(mut addr: i32, mut r: i32) -> () { + instr_F20FE6(return_on_pagefault!(safe_read128s(addr)), r); +} #[no_mangle] -pub unsafe fn instr_F30FE6_reg(mut r1: i32, mut r2: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_F20FE6_reg(mut r1: i32, mut r2: i32) -> () { + instr_F20FE6(read_xmm128s(r1), r2); +} + +#[no_mangle] +pub unsafe fn instr_F30FE6(mut source: reg64, mut r: i32) -> () { + // cvtdq2pd xmm1, xmm2/m64 + let mut result: reg128 = reg128 { + f64_0: [ + // Note: Conversion never fails (i32 fits into f64) + source.i32_0[0] as f64, + source.i32_0[1] as f64, + ], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe fn instr_F30FE6_mem(mut addr: i32, mut r: i32) -> () { + instr_F30FE6(return_on_pagefault!(safe_read64s(addr)), r); +} +#[no_mangle] +pub unsafe fn instr_F30FE6_reg(mut r1: i32, mut r2: i32) -> () { + instr_F30FE6(read_xmm64s(r1), r2); +} + #[no_mangle] pub unsafe fn instr_0FE7_mem(mut addr: i32, mut r: i32) -> () { c_comment!(("movntq m64, mm")); From d63c956a89b64b3f1ae108f854bbe556282ff77b Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Aug 2018 12:48:05 -0500 Subject: [PATCH 1245/2137] sse: Implement 0F5A/0F5B/CVTT?[SPD][SDQ]2[SPD][SDQ] (#57) --- gen/x86_table.js | 10 ++- src/rust/cpu2/instructions_0f.rs | 127 ++++++++++++++++++++++++++++++- 2 files changed, 133 insertions(+), 4 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index c2b827f0..e04f6bf6 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -595,8 +595,14 @@ const encodings = [ { sse: 1, opcode: 0xF20F59, e: 1, }, { sse: 1, opcode: 0xF30F59, e: 1, }, - { sse: 1, opcode: 0x0F5A, skip: 1, }, - { sse: 1, opcode: 0x0F5B, skip: 1, }, + { sse: 1, opcode: 0x0F5A, e: 1, }, + { sse: 1, opcode: 0x660F5A, e: 1, }, + { sse: 1, opcode: 0xF20F5A, e: 1, }, + { sse: 1, opcode: 0xF30F5A, e: 1, }, + { sse: 1, opcode: 0x0F5B, e: 1, }, + { sse: 1, opcode: 0x660F5B, e: 1, }, + // no F2 variant + { sse: 1, opcode: 0xF30F5B, e: 1, }, { sse: 1, opcode: 0x0F5C, e: 1, }, { sse: 1, opcode: 0x660F5C, e: 1, }, diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index bd5b60bc..97902b49 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -6295,10 +6295,133 @@ pub unsafe fn instr_F30F59_reg(mut r1: i32, mut r2: i32) -> () { pub unsafe fn instr_F30F59_mem(mut addr: i32, mut r: i32) -> () { instr_F30F59(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } + #[no_mangle] -pub unsafe fn instr_0F5A() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F5A(mut source: reg64, mut r: i32) -> () { + c_comment!(("cvtps2pd xmm1, xmm2/m64")); + let mut result: reg128 = reg128 { + f64_0: [source.f32_0[0] as f64, source.f32_0[1] as f64], + }; + write_xmm_reg128(r, result); +} #[no_mangle] -pub unsafe fn instr_0F5B() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F5A_reg(mut r1: i32, mut r2: i32) -> () { instr_0F5A(read_xmm64s(r1), r2); } +#[no_mangle] +pub unsafe fn instr_0F5A_mem(mut addr: i32, mut r: i32) -> () { + instr_0F5A(return_on_pagefault!(safe_read64s(addr)), r); +} +#[no_mangle] +pub unsafe fn instr_660F5A(mut source: reg128, mut r: i32) -> () { + c_comment!(("cvtpd2ps xmm1, xmm2/m128")); + let mut result: reg128 = reg128 { + // XXX: These conversions are lossy and should round according to the round control + f32_0: [source.f64_0[0] as f32, source.f64_0[1] as f32, 0., 0.], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe fn instr_660F5A_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F5A(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe fn instr_660F5A_mem(mut addr: i32, mut r: i32) -> () { + instr_660F5A(return_on_pagefault!(safe_read128s(addr)), r); +} +#[no_mangle] +pub unsafe fn instr_F20F5A(mut source: reg64, mut r: i32) -> () { + c_comment!(("cvtsd2ss xmm1, xmm2/m64")); + // XXX: This conversions is lossy and should round according to the round control + write_xmm_f32(r, source.f64_0[0] as f32); +} +#[no_mangle] +pub unsafe fn instr_F20F5A_reg(mut r1: i32, mut r2: i32) -> () { + instr_F20F5A(read_xmm64s(r1), r2); +} +#[no_mangle] +pub unsafe fn instr_F20F5A_mem(mut addr: i32, mut r: i32) -> () { + instr_F20F5A(return_on_pagefault!(safe_read64s(addr)), r); +} +#[no_mangle] +pub unsafe fn instr_F30F5A(mut source: f32, mut r: i32) -> () { + c_comment!(("cvtss2sd xmm1, xmm2/m32")); + let mut result: reg64 = reg64 { + f64_0: [source as f64], + }; + write_xmm64(r, result); +} +#[no_mangle] +pub unsafe fn instr_F30F5A_reg(mut r1: i32, mut r2: i32) -> () { + instr_F30F5A(read_xmm_f32(r1), r2); +} +#[no_mangle] +pub unsafe fn instr_F30F5A_mem(mut addr: i32, mut r: i32) -> () { + instr_F30F5A(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); +} + +#[no_mangle] +pub unsafe fn instr_0F5B(mut source: reg128, mut r: i32) -> () { + c_comment!(("cvtdq2ps xmm1, xmm2/m128")); + let mut result: reg128 = reg128 { + f32_0: [ + // XXX: Precision exception + source.i32_0[0] as f32, + source.i32_0[1] as f32, + source.i32_0[2] as f32, + source.i32_0[3] as f32, + ], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe fn instr_0F5B_reg(mut r1: i32, mut r2: i32) -> () { instr_0F5B(read_xmm128s(r1), r2); } +#[no_mangle] +pub unsafe fn instr_0F5B_mem(mut addr: i32, mut r: i32) -> () { + instr_0F5B(return_on_pagefault!(safe_read128s(addr)), r); +} +#[no_mangle] +pub unsafe fn instr_660F5B(mut source: reg128, mut r: i32) -> () { + c_comment!(("cvtps2dq xmm1, xmm2/m128")); + let mut result = reg128 { + i32_0: [ + // XXX: Precision exception + sse_convert_f32_to_i32(source.f32_0[0].round()), + sse_convert_f32_to_i32(source.f32_0[1].round()), + sse_convert_f32_to_i32(source.f32_0[2].round()), + sse_convert_f32_to_i32(source.f32_0[3].round()), + ], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe fn instr_660F5B_reg(mut r1: i32, mut r2: i32) -> () { + instr_660F5B(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe fn instr_660F5B_mem(mut addr: i32, mut r: i32) -> () { + instr_660F5B(return_on_pagefault!(safe_read128s(addr)), r); +} +#[no_mangle] +pub unsafe fn instr_F30F5B(mut source: reg128, mut r: i32) -> () { + c_comment!(("cvttps2dq xmm1, xmm2/m128")); + let mut result = reg128 { + i32_0: [ + sse_convert_f32_to_i32(source.f32_0[0].trunc()), + sse_convert_f32_to_i32(source.f32_0[1].trunc()), + sse_convert_f32_to_i32(source.f32_0[2].trunc()), + sse_convert_f32_to_i32(source.f32_0[3].trunc()), + ], + }; + write_xmm_reg128(r, result); +} +#[no_mangle] +pub unsafe fn instr_F30F5B_reg(mut r1: i32, mut r2: i32) -> () { + instr_F30F5B(read_xmm128s(r1), r2); +} +#[no_mangle] +pub unsafe fn instr_F30F5B_mem(mut addr: i32, mut r: i32) -> () { + instr_F30F5B(return_on_pagefault!(safe_read128s(addr)), r); +} + #[no_mangle] pub unsafe fn instr_0F5C(mut source: reg128, mut r: i32) -> () { c_comment!(("subps xmm, xmm/mem128")); From 221e5489b4b81f47e44c77c9cfc0f0e0d5c62ab2 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Aug 2018 12:48:38 -0500 Subject: [PATCH 1246/2137] sse: Clean up old cvt instruction --- src/rust/cpu2/instructions_0f.rs | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 97902b49..6259dd90 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -66,8 +66,6 @@ use cpu2::sse_instr::*; pub static mut apic_enabled: bool = false; const ENABLE_ACPI: bool = false; -pub fn convert_f64_to_i32(x: f64) -> i32 { x as i32 } - #[no_mangle] pub unsafe fn instr_0F00_0_mem(mut addr: i32) -> () { c_comment!(("sldt")); @@ -1026,25 +1024,8 @@ pub unsafe fn instr_660F2C_reg(mut r1: i32, mut r2: i32) -> () { #[no_mangle] pub unsafe fn instr_F20F2C(mut source: reg64, mut r: i32) -> () { - let mut si: i32 = 0; c_comment!(("cvttsd2si r32, xmm/m64")); - c_comment!( - ("emscripten bug causes this ported instruction to throw \'integer result unpresentable\'") - ); - c_comment!(("https://github.com/kripken/emscripten/issues/5433")); - if 0 != 0i32 * 0i32 { - let mut f: f64 = source.f64_0[0usize]; - if f <= 2147483647i32 as f64 && f >= 2147483648u32.wrapping_neg() as f64 { - si = f as i32; - write_reg32(r, si); - } - else { - write_reg32(r, 2147483648u32 as i32); - } - } - else { - write_reg32(r, convert_f64_to_i32(source.f64_0[0usize])); - }; + write_reg32(r, sse_convert_f64_to_i32(source.f64_0[0usize])); } #[no_mangle] pub unsafe fn instr_F20F2C_reg(mut r1: i32, mut r2: i32) -> () { @@ -5997,7 +5978,7 @@ pub unsafe fn instr_660F2D_mem(mut addr: i32, mut r: i32) -> () { #[no_mangle] pub unsafe fn instr_F20F2D(mut source: reg64, mut r: i32) -> () { c_comment!(("cvtsd2si r32, xmm/m64")); - write_reg32(r, sse_convert_f64_to_i32(source.f64_0[0usize])); + write_reg32(r, sse_convert_f64_to_i32(source.f64_0[0usize].round())); } #[no_mangle] pub unsafe fn instr_F20F2D_reg(mut r1: i32, mut r2: i32) -> () { @@ -6151,6 +6132,7 @@ pub unsafe fn instr_F30F53_reg(mut r1: i32, mut r2: i32) -> () { pub unsafe fn instr_F30F53_mem(mut addr: i32, mut r: i32) -> () { instr_F30F53(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } + #[no_mangle] pub unsafe fn instr_0F58(mut source: reg128, mut r: i32) -> () { c_comment!(("addps xmm, xmm/mem128")); @@ -6223,6 +6205,7 @@ pub unsafe fn instr_F30F58_reg(mut r1: i32, mut r2: i32) -> () { pub unsafe fn instr_F30F58_mem(mut addr: i32, mut r: i32) -> () { instr_F30F58(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } + #[no_mangle] pub unsafe fn instr_0F59(mut source: reg128, mut r: i32) -> () { c_comment!(("mulps xmm, xmm/mem128")); From 2b27510198499738ed02f2afe7dda8330489c4aa Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Aug 2018 13:21:40 -0500 Subject: [PATCH 1247/2137] sse: Warn on unimplemented mxcsr features --- src/rust/cpu2/cpu.rs | 29 +++++++++++++++++++++++++++++ src/rust/cpu2/instructions_0f.rs | 5 +---- src/rust/cpu2/misc_instr.rs | 2 +- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 898bbdf5..9c91b7fb 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1408,6 +1408,35 @@ pub unsafe fn task_switch_test() -> bool { }; } +pub unsafe fn set_mxcsr(new_mxcsr: i32) { + dbg_assert!(new_mxcsr & !MXCSR_MASK == 0); // checked by caller + + if new_mxcsr & 1 << 6 != 0 { + dbg_log!("Warning: Unimplemented MXCSR bit: Denormals Are Zero") + } + if new_mxcsr & 1 << 15 != 0 { + dbg_log!("Warning: Unimplemented MXCSR bit: Flush To Zero") + } + + let rounding_mode = new_mxcsr >> 13 & 3; + if rounding_mode != 0 { + dbg_log!( + "Warning: Unimplemented MXCSR rounding mode: {}", + rounding_mode + ) + } + + let exception_mask = new_mxcsr >> 7 & 0b111111; + if exception_mask != 0x111111 { + dbg_log!( + "Warning: Unimplemented MXCSR exception mask: {:b}", + exception_mask + ) + } + + *mxcsr = new_mxcsr; +} + #[no_mangle] pub unsafe fn task_switch_test_void() -> () { task_switch_test(); } diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 6259dd90..ad8c845d 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -3427,16 +3427,13 @@ pub unsafe fn instr_0FAE_2_reg(mut r: i32) -> () { unimplemented_sse(); } pub unsafe fn instr_0FAE_2_mem(mut addr: i32) -> () { c_comment!(("ldmxcsr")); let mut new_mxcsr: i32 = return_on_pagefault!(safe_read32s(addr)); - if new_mxcsr & 1 << 6 != 0 { - dbg_log!("Warning: Unimplemented MXCSR bit: {:x}", new_mxcsr) - } if 0 != new_mxcsr & !MXCSR_MASK { dbg_log!("Invalid mxcsr bits: {:x}", new_mxcsr & !MXCSR_MASK); trigger_gp_non_raising(0i32); return; } else { - *mxcsr = new_mxcsr; + set_mxcsr(new_mxcsr); return; }; } diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index 0cbe07c5..5fd52c04 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -406,7 +406,7 @@ pub unsafe fn fxrstor(mut addr: u32) -> () { *fpu_ip = safe_read16(addr.wrapping_add(12i32 as u32) as i32).unwrap(); *fpu_dp = safe_read32s(addr.wrapping_add(16i32 as u32) as i32).unwrap(); *fpu_dp_selector = safe_read16(addr.wrapping_add(20i32 as u32) as i32).unwrap(); - *mxcsr = new_mxcsr; + set_mxcsr(new_mxcsr); let mut i: i32 = 0i32; while i < 8i32 { *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(i as u32) & 7i32 as u32) as isize) = From 0a9c2bf6e2b21443bc4b810020f6b9ae04b842c4 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Aug 2018 14:37:37 -0500 Subject: [PATCH 1248/2137] qemu tests: init fpu before fxsave as fpu state contains undefined values from previous operations --- tests/qemu/test-i386.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/qemu/test-i386.c b/tests/qemu/test-i386.c index 2ffc093e..d2b07b1e 100644 --- a/tests/qemu/test-i386.c +++ b/tests/qemu/test-i386.c @@ -2586,6 +2586,7 @@ void test_fxsave(void) #if defined(__x86_64__) "movdqa %2, %%xmm15\n" #endif + " fninit\n" " fld1\n" " fld1\n" " fldz\n" From 920d150c8bda36f8ca2c0eeb1001c144d42a2af7 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Aug 2018 14:37:59 -0500 Subject: [PATCH 1249/2137] qemu: Enable all sse2 tests, add tests for approximate operations --- tests/qemu/test-i386.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/tests/qemu/test-i386.c b/tests/qemu/test-i386.c index d2b07b1e..4a36d2eb 100644 --- a/tests/qemu/test-i386.c +++ b/tests/qemu/test-i386.c @@ -2491,12 +2491,10 @@ SSE_OP(a ## sd); void test_sse_comi(double a1, double b1) { - /* SSE_COMI(ucomiss, s); SSE_COMI(ucomisd, d); SSE_COMI(comiss, s); SSE_COMI(comisd, d); - */ } #define CVT_OP_XMM(op)\ @@ -2741,9 +2739,8 @@ void test_sse(void) SSE_OP2(unpckhps); SSE_OP2(unpckhpd); - // TODO: These instructions pull in some other unimplemented instructions on v86 - //SHUF_OP(shufps, 0x78); - //SHUF_OP(shufpd, 0x02); + SHUF_OP(shufps, 0x78); + SHUF_OP(shufpd, 0x02); SHUF_OP_MMX(pshufw, 0x78); SHUF_OP_MMX(pshufw, 0x02); @@ -2861,8 +2858,15 @@ void test_sse(void) SSE_OPD(cmpord); } + // approximating instructions: Pick some nice round values + a.s[0] = 1024.0; + a.s[1] = 1.0 / 256.0; + b.s[0] = 1024.0; + b.s[1] = 1.0 / 256.0; + SSE_OPS(rsqrt); + SSE_OPS(rcp); + /* float to float/int */ - /* a.s[0] = 2.7; a.s[1] = 3.4; a.s[2] = 4; @@ -2886,14 +2890,12 @@ void test_sse(void) CVT_OP_XMM2REG(cvttsd2si); CVT_OP_XMM(cvtpd2dq); CVT_OP_XMM(cvttpd2dq); - */ /* sse/mmx moves */ CVT_OP_XMM2MMX(movdq2q); CVT_OP_MMX2XMM(movq2dq); /* int to float */ - /* a.l[0] = -6; a.l[1] = 2; a.l[2] = 100; @@ -2904,7 +2906,6 @@ void test_sse(void) CVT_OP_REG2XMM(cvtsi2sd); CVT_OP_XMM(cvtdq2ps); CVT_OP_XMM(cvtdq2pd); - */ /* XXX: test PNI insns */ #if 0 SSE_OP2(movshdup); From 36fede1906451bceb65b64ffd4d4527cda9a104f Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Aug 2018 14:38:18 -0500 Subject: [PATCH 1250/2137] Simplify fpu_set_tag_word --- src/rust/cpu2/fpu.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index b0bfc613..07b59f9c 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -360,7 +360,8 @@ pub unsafe fn fpu_set_tag_word(mut tag_word: i32) -> () { *fpu_stack_empty = 0i32; let mut i: i32 = 0i32; while i < 8i32 { - *fpu_stack_empty |= tag_word >> i & tag_word >> i + 1i32 & 1i32 << i; + let empty = tag_word >> (2 * i) & 3 == 3; + *fpu_stack_empty |= (empty as i32) << i; i += 1 } } From d08f5fd4601c4c0baca38072ea1e0b290864ceac Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Aug 2018 21:04:54 -0500 Subject: [PATCH 1251/2137] c2rust cleanup: Fix comments --- src/rust/cpu2/arith.rs | 8 +- src/rust/cpu2/cpu.rs | 118 +++-- src/rust/cpu2/fpu.rs | 50 +- src/rust/cpu2/imports.rs | 4 - src/rust/cpu2/instructions.rs | 174 +++---- src/rust/cpu2/instructions_0f.rs | 814 +++++++++++++++---------------- src/rust/cpu2/misc_instr.rs | 14 +- src/rust/cpu2/sse_instr.rs | 76 +-- src/rust/cpu2/string.rs | 2 +- 9 files changed, 627 insertions(+), 633 deletions(-) diff --git a/src/rust/cpu2/arith.rs b/src/rust/cpu2/arith.rs index 044d5bfa..ac5e7be2 100644 --- a/src/rust/cpu2/arith.rs +++ b/src/rust/cpu2/arith.rs @@ -350,7 +350,7 @@ pub unsafe fn bcd_aad(mut imm8: i32) -> () { } #[no_mangle] pub unsafe fn bcd_aam(mut imm8: i32) -> () { - c_comment!(("ascii adjust after multiplication")); + // ascii adjust after multiplication if imm8 == 0i32 { trigger_de(); } @@ -806,7 +806,7 @@ pub unsafe fn shl32(mut dest_operand: i32, mut count: i32) -> i32 { *last_result = dest_operand << count; *last_op_size = OPSIZE_32; *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; - c_comment!(("test this")); + // test this *flags = *flags & !1i32 & !FLAG_OVERFLOW | dest_operand >> 32i32 - count & 1i32; *flags |= (*flags & 1i32 ^ *last_result >> 31i32 & 1i32) << 11i32 & FLAG_OVERFLOW; return *last_result; @@ -865,7 +865,7 @@ pub unsafe fn sar8(mut dest_operand: i32, mut count: i32) -> i32 { else { if count < 8i32 { *last_result = dest_operand << 24i32 >> count + 24i32; - c_comment!(("of is zero")); + // of is zero *flags = *flags & !1i32 & !FLAG_OVERFLOW | dest_operand >> count - 1i32 & 1i32 } else { @@ -1058,7 +1058,7 @@ pub unsafe fn bsf16(mut old: i32, mut bit_base: i32) -> i32 { if bit_base == 0i32 { *flags |= FLAG_ZERO; *last_result = bit_base; - c_comment!(("not defined in the docs, but value doesn\'t change on my intel machine")); + // not defined in the docs, but value doesn't change on my intel machine return old; } else { diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 9c91b7fb..6c1ce5c0 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -285,7 +285,7 @@ pub unsafe fn do_page_translation( let mut page: i32 = (addr as u32 >> 12i32) as i32; let mut high: i32 = 0; if *cr.offset(0isize) & CR0_PG == 0i32 { - c_comment!(("paging disabled")); + // paging disabled high = (addr as u32 & 4294963200u32) as i32; global = 0 != 0i32 } @@ -293,14 +293,14 @@ pub unsafe fn do_page_translation( let mut page_dir_addr: i32 = (*cr.offset(3isize) as u32 >> 2i32).wrapping_add((page >> 10i32) as u32) as i32; let mut page_dir_entry: i32 = read_aligned32(page_dir_addr as u32); - c_comment!(("XXX")); + // XXX let kernel_write_override: bool = !user && 0 == *cr.offset(0isize) & CR0_WP; if 0 == page_dir_entry & PAGE_TABLE_PRESENT_MASK { - c_comment!(("to do at this place:")); - c_comment!(("")); - c_comment!(("- set cr2 = addr (which caused the page fault)")); - c_comment!((("- call_interrupt_vector with id 14, error code 0-7 (requires information if read or write)"))); - c_comment!(("- prevent execution of the function that triggered this call")); + // to do at this place: + // + // - set cr2 = addr (which caused the page fault) + // - call_interrupt_vector with id 14, error code 0-7 (requires information if read or write) + // - prevent execution of the function that triggered this call *cr.offset(2isize) = addr; trigger_pagefault(for_writing, user, 0 != 0i32); return Err(()); @@ -316,15 +316,15 @@ pub unsafe fn do_page_translation( if page_dir_entry & PAGE_TABLE_USER_MASK == 0i32 { allow_user = 0 != 0i32; if user { - c_comment!(("Page Fault: page table accessed by non-supervisor")); + // Page Fault: page table accessed by non-supervisor *cr.offset(2isize) = addr; trigger_pagefault(for_writing, user, 0 != 1i32); return Err(()); } } if 0 != page_dir_entry & PAGE_TABLE_PSE_MASK && 0 != *cr.offset(4isize) & CR4_PSE { - c_comment!(("size bit is set")); - c_comment!(("set the accessed and dirty bits")); + // size bit is set + // set the accessed and dirty bits write_aligned32( page_dir_addr as u32, page_dir_entry | PAGE_TABLE_ACCESSED_MASK | if 0 != for_writing as i32 { @@ -363,7 +363,7 @@ pub unsafe fn do_page_translation( return Err(()); } } - c_comment!(("set the accessed and dirty bits")); + // set the accessed and dirty bits write_aligned32( page_dir_addr as u32, page_dir_entry | PAGE_TABLE_ACCESSED_MASK, @@ -385,9 +385,7 @@ pub unsafe fn do_page_translation( if valid_tlb_entries_count == VALID_TLB_ENTRY_MAX { profiler_stat_increment(S_TLB_FULL); clear_tlb(); - c_comment!( - ("also clear global entries if tlb is almost full after clearing non-global pages") - ); + // also clear global entries if tlb is almost full after clearing non-global pages if valid_tlb_entries_count > VALID_TLB_ENTRY_MAX * 3i32 / 4i32 { profiler_stat_increment(S_TLB_GLOBAL_FULL); full_clear_tlb(); @@ -397,9 +395,9 @@ pub unsafe fn do_page_translation( let fresh0 = valid_tlb_entries_count; valid_tlb_entries_count = valid_tlb_entries_count + 1; valid_tlb_entries[fresh0 as usize] = page; - c_comment!(("TODO: Check that there are no duplicates in valid_tlb_entries")); - c_comment!(("XXX: There will probably be duplicates due to invlpg deleting")); - c_comment!(("entries from tlb_data but not from valid_tlb_entries")); + // TODO: Check that there are no duplicates in valid_tlb_entries + // XXX: There will probably be duplicates due to invlpg deleting + // entries from tlb_data but not from valid_tlb_entries } else if CHECK_TLB_INVARIANTS { let mut found: bool = 0 != 0i32; @@ -458,7 +456,7 @@ pub unsafe fn do_page_translation( #[no_mangle] pub unsafe fn full_clear_tlb() -> () { profiler_stat_increment(S_FULL_CLEAR_TLB); - c_comment!(("clear tlb including global pages")); + // clear tlb including global pages *last_virt_eip = -1i32; *last_virt_esp = -1i32; let mut i: i32 = 0i32; @@ -480,7 +478,7 @@ pub unsafe fn full_clear_tlb() -> () { #[no_mangle] pub unsafe fn clear_tlb() -> () { profiler_stat_increment(S_CLEAR_TLB); - c_comment!(("clear tlb excluding global pages")); + // clear tlb excluding global pages *last_virt_eip = -1i32; *last_virt_esp = -1i32; let mut global_page_offset: i32 = 0i32; @@ -489,7 +487,7 @@ pub unsafe fn clear_tlb() -> () { let mut page: i32 = valid_tlb_entries[i as usize]; let mut entry: i32 = *tlb_data.offset(page as isize); if 0 != entry & TLB_GLOBAL { - c_comment!(("reinsert at the front")); + // reinsert at the front let fresh1 = global_page_offset; global_page_offset = global_page_offset + 1; valid_tlb_entries[fresh1 as usize] = page @@ -536,7 +534,7 @@ pub unsafe fn trigger_pagefault(mut write: bool, mut user: bool, mut present: bo // dbg_trace(); // dbg_assert!(0 != 0i32); //} - c_comment!(("invalidate tlb entry")); + // invalidate tlb entry let mut page: i32 = (*cr.offset(2isize) as u32 >> 12i32) as i32; *tlb_data.offset(page as isize) = 0i32; *instruction_pointer = *previous_ip; @@ -601,7 +599,7 @@ pub unsafe fn check_tlb_invariants() -> () { let mut page: i32 = valid_tlb_entries[i as usize]; let mut entry: i32 = *tlb_data.offset(page as isize); if 0 == entry || 0 != entry & TLB_IN_MAPPED_RANGE { - c_comment!(("there\'s no code in mapped memory")); + // there's no code in mapped memory } i += 1 } @@ -627,7 +625,7 @@ pub unsafe fn writable_or_pagefault(mut addr: i32, mut size: i32) -> Result<(), let mut next_page: i32 = ((addr + size - 1i32) as u32 >> 12i32) as i32; if page != next_page { dbg_assert!(next_page == page + 1i32); - c_comment!(("XXX: possibly out of bounds")); + // XXX: possibly out of bounds if *tlb_data.offset(next_page as isize) & mask != expect { do_page_translation(next_page << 12i32, 0 != 1i32, user)?; } @@ -651,9 +649,9 @@ pub unsafe fn read_imm8() -> Result { pub unsafe fn read_imm8s() -> Result { return Ok(read_imm8()? << 24i32 >> 24i32); } pub unsafe fn read_imm16() -> Result { - c_comment!(("Two checks in one comparison:")); - c_comment!(("1. Did the high 20 bits of eip change")); - c_comment!(("or 2. Are the low 12 bits of eip 0xFFF (and this read crosses a page boundary)")); + // Two checks in one comparison: + // 1. Did the high 20 bits of eip change + // or 2. Are the low 12 bits of eip 0xFFF (and this read crosses a page boundary) if (*instruction_pointer ^ *last_virt_eip) as u32 > 4094i32 as u32 { return Ok(read_imm8()? | read_imm8()? << 8i32); } @@ -665,7 +663,7 @@ pub unsafe fn read_imm16() -> Result { } pub unsafe fn read_imm32s() -> Result { - c_comment!(("Analogue to the above comment")); + // Analogue to the above comment if (*instruction_pointer ^ *last_virt_eip) as u32 > 4092i32 as u32 { return Ok(read_imm16()? | read_imm16()? << 16i32); } @@ -688,7 +686,7 @@ pub unsafe fn is_asize_32() -> bool { #[no_mangle] pub unsafe fn get_seg(mut segment: i32) -> i32 { dbg_assert!(segment >= 0i32 && segment < 8i32); - c_comment!(("TODO: Remove protected_mode check")); + // TODO: Remove protected_mode check if *protected_mode { if *segment_is_null.offset(segment as isize) { dbg_assert!(segment != CS && segment != SS); @@ -857,7 +855,7 @@ pub unsafe fn pack_current_state_flags() -> cached_state_flags { } pub unsafe fn has_flat_segmentation() -> bool { - c_comment!(("ss can\'t be null")); + // ss can't be null return *segment_offsets.offset(SS as isize) == 0i32 && !*segment_is_null.offset(DS as isize) && *segment_offsets.offset(DS as isize) == 0i32; @@ -960,16 +958,16 @@ pub unsafe fn virt_boundary_read32s(mut low: i32, mut high: i32) -> i32 { let mut mid: i32 = 0i32; if 0 != low & 1i32 { if 0 != low & 2i32 { - c_comment!(("0xFFF")); + // 0xFFF mid = read_aligned16((high - 2i32 >> 1i32) as u32) } else { - c_comment!(("0xFFD")); + // 0xFFD mid = read_aligned16((low + 1i32 >> 1i32) as u32) } } else { - c_comment!(("0xFFE")); + // 0xFFE mid = virt_boundary_read16(low + 1i32, high - 1i32) } return read8(low as u32) | mid << 8i32 | read8(high as u32) << 24i32; @@ -988,18 +986,18 @@ pub unsafe fn virt_boundary_write32(mut low: i32, mut high: i32, mut value: i32) write8(low as u32, value); if 0 != low & 1i32 { if 0 != low & 2i32 { - c_comment!(("0xFFF")); + // 0xFFF write8((high - 2i32) as u32, value >> 8i32); write8((high - 1i32) as u32, value >> 16i32); } else { - c_comment!(("0xFFD")); + // 0xFFD write8((low + 1i32) as u32, value >> 8i32); write8((low + 2i32) as u32, value >> 16i32); } } else { - c_comment!(("0xFFE")); + // 0xFFE write8((low + 1i32) as u32, value >> 8i32); write8((high - 1i32) as u32, value >> 16i32); } @@ -1015,8 +1013,8 @@ pub unsafe fn safe_read16(mut address: i32) -> Result { let mut entry: i32 = *tlb_data.offset(base as isize); let mut info_bits: i32 = entry & 4095i32 & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; if info_bits == TLB_VALID && address & 4095i32 <= 4096i32 - 2i32 { - c_comment!(("- not in memory mapped area")); - c_comment!(("- can be accessed from any cpl")); + // - not in memory mapped area + // - can be accessed from any cpl let mut phys_address: u32 = (entry & !4095i32 ^ address) as u32; dbg_assert!(!in_mapped_range(phys_address)); return Ok(*(mem8.offset(phys_address as isize) as *mut u16) as i32); @@ -1043,8 +1041,8 @@ pub unsafe fn safe_read32s(mut address: i32) -> Result { if false { profiler_stat_increment(S_SAFE_READ32_FAST); } - c_comment!(("- not in memory mapped area")); - c_comment!(("- can be accessed from any cpl")); + // - not in memory mapped area + // - can be accessed from any cpl let mut phys_address: u32 = (entry & !4095i32 ^ address) as u32; dbg_assert!(!in_mapped_range(phys_address)); return Ok(*(mem8.offset(phys_address as isize) as *mut i32)); @@ -1160,10 +1158,10 @@ pub unsafe fn safe_write16(mut address: i32, mut value: i32) -> Result<(), ()> { let mut entry: i32 = *tlb_data.offset(base as isize); let mut info_bits: i32 = entry & 4095i32 & !TLB_GLOBAL; if info_bits == TLB_VALID && address & 4095i32 <= 4096i32 - 2i32 { - c_comment!(("- allowed to write in user-mode")); - c_comment!(("- not in memory mapped area")); - c_comment!(("- can be accessed from any cpl")); - c_comment!(("- does not contain code")); + // - allowed to write in user-mode + // - not in memory mapped area + // - can be accessed from any cpl + // - does not contain code let mut phys_address: u32 = (entry & !4095i32 ^ address) as u32; dbg_assert!(!::c_api::jit_page_has_code(phys_address >> 12i32)); dbg_assert!(!in_mapped_range(phys_address)); @@ -1203,9 +1201,9 @@ pub unsafe fn safe_write32(mut address: i32, mut value: i32) -> Result<(), ()> { if false { profiler_stat_increment(S_SAFE_WRITE32_FAST); } - c_comment!(("- allowed to write in user-mode")); - c_comment!(("- not in memory mapped area")); - c_comment!(("- does not contain code")); + // - allowed to write in user-mode + // - not in memory mapped area + // - does not contain code let mut phys_address: u32 = (entry & !4095i32 ^ address) as u32; dbg_assert!(!::c_api::jit_page_has_code(phys_address >> 12i32)); dbg_assert!(!in_mapped_range(phys_address)); @@ -1458,7 +1456,7 @@ pub unsafe fn task_switch_test_mmx() -> bool { pub unsafe fn task_switch_test_mmx_void() -> () { task_switch_test_mmx(); } pub unsafe fn read_moffs() -> Result { - c_comment!(("read 2 or 4 byte from ip, depending on address size attribute")); + // read 2 or 4 byte from ip, depending on address size attribute if is_asize_32() { read_imm32s() } @@ -1469,7 +1467,7 @@ pub unsafe fn read_moffs() -> Result { #[no_mangle] pub unsafe fn get_real_eip() -> i32 { - c_comment!(("Returns the \'real\' instruction pointer, without segment offset")); + // Returns the 'real' instruction pointer, without segment offset return *instruction_pointer - get_seg_cs(); } @@ -1552,7 +1550,7 @@ pub unsafe fn read_tsc() -> u64 { } else { if value == rdtsc_last_value { - c_comment!(("don\'t go past 1ms")); + // don't go past 1ms if (rdtsc_imprecision_offset as f64) < TSC_RATE { rdtsc_imprecision_offset = rdtsc_imprecision_offset.wrapping_add(1) } @@ -1574,7 +1572,7 @@ pub unsafe fn read_tsc() -> u64 { value as u32 as i32 ); dbg_assert!(0 != 0i32); - c_comment!(("Keep current value until time catches up")); + // Keep current value until time catches up } } return rdtsc_last_value.wrapping_add(rdtsc_imprecision_offset); @@ -1600,10 +1598,10 @@ pub unsafe fn get_opstats_buffer(mut index: i32) -> i32 { pub unsafe fn invlpg(mut addr: i32) -> () { let mut page: i32 = (addr as u32 >> 12i32) as i32; - c_comment!(("Note: Doesn\'t remove this page from valid_tlb_entries: This isn\'t")); - c_comment!(("necessary, because when valid_tlb_entries grows too large, it will be")); - c_comment!(("empties by calling clear_tlb, which removes this entry as it isn\'t global.")); - c_comment!(("This however means that valid_tlb_entries can contain some invalid entries")); + // Note: Doesn't remove this page from valid_tlb_entries: This isn't + // necessary, because when valid_tlb_entries grows too large, it will be + // empties by calling clear_tlb, which removes this entry as it isn't global. + // This however means that valid_tlb_entries can contain some invalid entries *tlb_data.offset(page as isize) = 0i32; *last_virt_eip = -1i32; *last_virt_esp = -1i32; @@ -1614,10 +1612,10 @@ pub unsafe fn update_eflags(mut new_flags: i32) -> () { let mut dont_update: i32 = FLAG_RF | FLAG_VM | FLAG_VIP | FLAG_VIF; let mut clear: i32 = !FLAG_VIP & !FLAG_VIF & FLAGS_MASK; if 0 != *flags & FLAG_VM { - c_comment!(("other case needs to be handled in popf or iret")); + // other case needs to be handled in popf or iret dbg_assert!(getiopl() == 3i32); dont_update |= FLAG_IOPL; - c_comment!(("don\'t clear vip or vif")); + // don't clear vip or vif clear |= FLAG_VIP | FLAG_VIF } else { @@ -1625,12 +1623,12 @@ pub unsafe fn update_eflags(mut new_flags: i32) -> () { dbg_assert!(*cpl as i32 == 0i32); } if 0 != *cpl { - c_comment!(("cpl > 0")); - c_comment!(("cannot update iopl")); + // cpl > 0 + // cannot update iopl dont_update |= FLAG_IOPL; if *cpl as i32 > getiopl() { - c_comment!(("cpl > iopl")); - c_comment!(("cannot update interrupt flag")); + // cpl > iopl + // cannot update interrupt flag dont_update |= FLAG_INTERRUPT } } diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 07b59f9c..9a5c8da8 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -71,7 +71,7 @@ pub unsafe fn fpu_get_st0() -> f64 { } #[no_mangle] pub unsafe fn fpu_stack_fault() -> () { - c_comment!(("TODO: Interrupt")); + // TODO: Interrupt *fpu_status_word |= FPU_EX_SF | FPU_EX_I; } #[no_mangle] @@ -90,9 +90,9 @@ pub unsafe fn fpu_get_sti(mut i: i32) -> f64 { #[no_mangle] pub unsafe fn fpu_integer_round(mut f: f64) -> f64 { let mut rc: i32 = *fpu_control_word >> 10i32 & 3i32; - c_comment!(("XXX: See https://en.wikipedia.org/wiki/C_mathematical_functions")); + // XXX: See https://en.wikipedia.org/wiki/C_mathematical_functions if rc == 0i32 { - c_comment!(("Round to nearest, or even if equidistant")); + // Round to nearest, or even if equidistant let mut rounded: f64 = round(f); let mut diff: f64 = rounded - f; if diff == 0.5f64 || diff == -0.5f64 { @@ -101,7 +101,7 @@ pub unsafe fn fpu_integer_round(mut f: f64) -> f64 { return rounded; } else if rc == 1i32 || rc == 3i32 && f > 0i32 as f64 { - c_comment!(("rc=3 is truncate -> floor for positive numbers")); + // rc=3 is truncate -> floor for positive numbers return floor(f); } else { @@ -130,23 +130,23 @@ pub unsafe fn fpu_load_m80(mut addr: u32) -> Result { let mut sign: i32 = exponent >> 15i32; exponent &= !32768i32; if exponent == 0i32 { - c_comment!(("TODO: denormal numbers")); + // TODO: denormal numbers Ok(0i32 as f64) } else if exponent < 32767i32 { exponent -= 16383i32; - c_comment!(("Note: some bits might be lost at this point")); + // Note: some bits might be lost at this point let mut mantissa: f64 = low as f64 + 4294967296i64 as f64 * high as f64; if 0 != sign { mantissa = -mantissa } - c_comment!(("Simply compute the 64 bit floating point number.")); - c_comment!(("An alternative write the mantissa, sign and exponent in the")); - c_comment!(("float64_byte and return float64[0]")); + // Simply compute the 64 bit floating point number. + // An alternative write the mantissa, sign and exponent in the + // float64_byte and return float64[0] Ok(mantissa * pow(2i32 as f64, (exponent - 63i32) as f64)) } else { - c_comment!(("TODO: NaN, Infinity")); + // TODO: NaN, Infinity if 0 != 0i32 * 0i32 { dbg_log_c!("Load m80 TODO"); } @@ -296,8 +296,8 @@ pub unsafe fn fpu_fistm32(mut addr: i32) -> () { let mut st0: f64 = fpu_integer_round(fpu_get_st0()); let mut i: i32 = convert_f64_to_i32(st0); if i == 2147483648u32 as i32 { - c_comment!(("XXX: Probably not correct if st0 == 0x80000000")); - c_comment!(("(input fits, but same value as error value)")); + // XXX: Probably not correct if st0 == 0x80000000 + // (input fits, but same value as error value) fpu_invalid_arithmetic(); } return_on_pagefault!(safe_write32(addr, i)); @@ -396,7 +396,7 @@ pub unsafe fn fpu_fnstsw_mem(mut addr: i32) -> () { pub unsafe fn fpu_fnstsw_reg() -> () { *reg16.offset(AX as isize) = fpu_load_status_word() as u16; } #[no_mangle] pub unsafe fn fpu_fprem() -> () { - c_comment!(("XXX: This implementation differs from the description in Intel\'s manuals")); + // XXX: This implementation differs from the description in Intel's manuals let mut st0: f64 = fpu_get_st0(); let mut st1: f64 = fpu_get_sti(1i32); let mut fprem_quotient: i32 = convert_f64_to_i32(trunc(st0 / st1)); @@ -453,28 +453,28 @@ pub unsafe fn fpu_store_m80(mut addr: u32, mut n: f64) -> () { let mut low: i32 = 0; let mut high: i32 = 0; if exponent == 2047i32 { - c_comment!(("all bits set (NaN and infinity)")); + // all bits set (NaN and infinity) exponent = 32767i32; low = 0i32; high = (2147483648u32 | ((double_int_view.i32_0[1usize] & 524288i32) << 11i32) as u32) as i32 } else if exponent == 0i32 { - c_comment!(("zero and denormal numbers")); - c_comment!(("Just assume zero for now")); + // zero and denormal numbers + // Just assume zero for now low = 0i32; high = 0i32 } else { exponent += 16383i32 - 1023i32; - c_comment!(("does the mantissa need to be adjusted?")); + // does the mantissa need to be adjusted? low = double_int_view.i32_0[0usize] << 11i32; high = (2147483648u32 | ((double_int_view.i32_0[1usize] & 1048575i32) << 11i32) as u32 | double_int_view.i32_0[0usize] as u32 >> 21i32) as i32 } dbg_assert!(exponent >= 0i32 && exponent < 32768i32); - c_comment!(("writable_or_pagefault must have checked called by the caller!")); + // writable_or_pagefault must have checked called by the caller! safe_write64( addr as i32, (low as u64 & 4294967295u32 as u64 | (high as u64) << 32i32) as i64, @@ -592,16 +592,16 @@ pub unsafe fn fpu_ftst(mut x: f64) -> () { else if x < 0i32 as f64 { *fpu_status_word |= FPU_C0 } - c_comment!(("TODO: unordered (x is nan, etc)")); + // TODO: unordered (x is nan, etc) } #[no_mangle] pub unsafe fn fpu_fucom(mut r: i32) -> () { - c_comment!(("TODO")); + // TODO fpu_fcom(fpu_get_sti(r)); } #[no_mangle] pub unsafe fn fpu_fucomi(mut r: i32) -> () { - c_comment!(("TODO")); + // TODO fpu_fcomi(r); } #[no_mangle] @@ -639,12 +639,12 @@ pub unsafe fn fpu_fxam(mut x: f64) -> () { else { *fpu_status_word |= FPU_C2 } - c_comment!(("TODO:")); - c_comment!(("Unsupported, Denormal")); + // TODO: + // Unsupported, Denormal } #[no_mangle] pub unsafe fn fpu_sign(mut i: i32) -> i32 { - c_comment!(("sign of a number on the stack")); + // sign of a number on the stack return *fpu_st8.offset( (((*fpu_stack_ptr).wrapping_add(i as u32) & 7i32 as u32) << 3i32 | 7i32 as u32) as isize, ) as i32 @@ -671,5 +671,5 @@ pub unsafe fn fpu_fxtract() -> () { } #[no_mangle] pub unsafe fn fwait() -> () { - c_comment!(("NOP unless FPU instructions run in parallel with CPU instructions")); + // NOP unless FPU instructions run in parallel with CPU instructions } diff --git a/src/rust/cpu2/imports.rs b/src/rust/cpu2/imports.rs index 7131df0e..1fcff55f 100644 --- a/src/rust/cpu2/imports.rs +++ b/src/rust/cpu2/imports.rs @@ -33,7 +33,3 @@ macro_rules! dbg_log_c { dbg_log!($fmt); }}; } - -macro_rules! c_comment { - ($fmt:expr) => {{}}; -} diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index 605663cd..92218d31 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -958,7 +958,7 @@ pub unsafe fn instr16_61() -> () { popa16(); } pub unsafe fn instr32_61() -> () { popa32(); } #[no_mangle] pub unsafe fn instr_62_reg(mut r2: i32, mut r: i32) -> () { - c_comment!(("bound")); + // bound dbg_log_c!("Unimplemented BOUND instruction"); dbg_assert!(0 != 0i32); } @@ -982,14 +982,14 @@ pub unsafe fn instr_64() -> () { segment_prefix_op(FS); } pub unsafe fn instr_65() -> () { segment_prefix_op(GS); } #[no_mangle] pub unsafe fn instr_66() -> () { - c_comment!(("Operand-size override prefix")); + // Operand-size override prefix *prefixes = (*prefixes as i32 | PREFIX_MASK_OPSIZE) as u8; run_prefix_instruction(); *prefixes = 0i32 as u8; } #[no_mangle] pub unsafe fn instr_67() -> () { - c_comment!(("Address-size override prefix")); + // Address-size override prefix dbg_assert!(is_asize_32() as i32 == *is_32 as i32); *prefixes = (*prefixes as i32 | PREFIX_MASK_ADDRSIZE) as u8; run_prefix_instruction(); @@ -1616,7 +1616,7 @@ pub unsafe fn instr16_8D_reg(mut r: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe fn instr16_8D_mem(modrm_byte: i32, mut r: i32) -> () { - c_comment!(("lea")); + // lea *prefixes = (*prefixes as i32 | SEG_PREFIX_ZERO) as u8; if let Ok(addr) = modrm_resolve(modrm_byte) { write_reg16(r, addr); @@ -1630,8 +1630,8 @@ pub unsafe fn instr32_8D_reg(mut r: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe fn instr32_8D_mem(modrm_byte: i32, mut r: i32) -> () { - c_comment!(("lea")); - c_comment!(("override prefix, so modrm_resolve does not return the segment part")); + // lea + // override prefix, so modrm_resolve does not return the segment part *prefixes = (*prefixes as i32 | SEG_PREFIX_ZERO) as u8; if let Ok(addr) = modrm_resolve(modrm_byte) { write_reg32(r, addr); @@ -1663,7 +1663,7 @@ pub unsafe fn instr_8E_reg(mut r1: i32, mut r: i32) -> () { #[no_mangle] pub unsafe fn instr16_8F_0_mem(modrm_byte: i32) -> () { - c_comment!(("pop")); + // pop // Update esp *before* resolving the address adjust_stack_reg(2i32); match modrm_resolve(modrm_byte) { @@ -1765,7 +1765,7 @@ pub unsafe fn instr32_99() -> () { } #[no_mangle] pub unsafe fn instr16_9A(mut new_ip: i32, mut new_cs: i32) -> () { - c_comment!(("callf")); + // callf far_jump(new_ip, new_cs, true); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } @@ -1781,10 +1781,10 @@ pub unsafe fn instr32_9A(mut new_ip: i32, mut new_cs: i32) -> () { } #[no_mangle] pub unsafe fn instr_9B() -> () { - c_comment!(("fwait: check for pending fpu exceptions")); + // fwait: check for pending fpu exceptions if *cr.offset(0isize) & (CR0_MP | CR0_TS) == CR0_MP | CR0_TS { - c_comment!(("Note: Different from task_switch_test")); - c_comment!(("Triggers when TS and MP bits are set (EM bit is ignored)")); + // Note: Different from task_switch_test + // Triggers when TS and MP bits are set (EM bit is ignored) trigger_nm(); } else { @@ -1793,7 +1793,7 @@ pub unsafe fn instr_9B() -> () { } #[no_mangle] pub unsafe fn instr16_9C() -> () { - c_comment!(("pushf")); + // pushf if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { dbg_assert!(*protected_mode); dbg_log_c!("pushf #gp"); @@ -1805,21 +1805,21 @@ pub unsafe fn instr16_9C() -> () { } #[no_mangle] pub unsafe fn instr32_9C() -> () { - c_comment!(("pushf")); + // pushf if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { - c_comment!(("trap to virtual 8086 monitor")); + // trap to virtual 8086 monitor dbg_assert!(*protected_mode); dbg_log_c!("pushf #gp"); trigger_gp_non_raising(0i32); } else { - c_comment!(("vm and rf flag are cleared in image stored on the stack")); + // vm and rf flag are cleared in image stored on the stack return_on_pagefault!(push32(get_eflags() & 16580607i32)); }; } #[no_mangle] pub unsafe fn instr16_9D() -> () { - c_comment!(("popf")); + // popf if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { dbg_log_c!("popf #gp"); trigger_gp_non_raising(0i32); @@ -1839,7 +1839,7 @@ pub unsafe fn instr16_9D() -> () { } #[no_mangle] pub unsafe fn instr32_9D() -> () { - c_comment!(("popf")); + // popf if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { dbg_log_c!("popf #gp"); trigger_gp_non_raising(0i32); @@ -1853,7 +1853,7 @@ pub unsafe fn instr32_9D() -> () { } #[no_mangle] pub unsafe fn instr_9E() -> () { - c_comment!(("sahf")); + // sahf *flags.offset(0isize) = *flags.offset(0isize) & !255i32 | *reg8.offset(AH as isize) as i32; *flags.offset(0isize) = *flags.offset(0isize) & FLAGS_MASK | FLAGS_DEFAULT; let ref mut fresh1 = *flags_changed.offset(0isize); @@ -1861,18 +1861,18 @@ pub unsafe fn instr_9E() -> () { } #[no_mangle] pub unsafe fn instr_9F() -> () { - c_comment!(("lahf")); + // lahf *reg8.offset(AH as isize) = get_eflags() as u8; } #[no_mangle] pub unsafe fn instr_A0(mut moffs: i32) -> () { - c_comment!(("mov")); + // mov let mut data: i32 = return_on_pagefault!(safe_read8(get_seg_prefix_ds(moffs))); *reg8.offset(AL as isize) = data as u8; } #[no_mangle] pub unsafe fn instr16_A1(mut moffs: i32) -> () { - c_comment!(("mov")); + // mov let mut data: i32 = return_on_pagefault!(safe_read16(get_seg_prefix_ds(moffs))); *reg16.offset(AX as isize) = data as u16; } @@ -1883,7 +1883,7 @@ pub unsafe fn instr32_A1(mut moffs: i32) -> () { } #[no_mangle] pub unsafe fn instr_A2(mut moffs: i32) -> () { - c_comment!(("mov")); + // mov return_on_pagefault!(safe_write8( get_seg_prefix_ds(moffs), *reg8.offset(AL as isize) as i32 @@ -1891,7 +1891,7 @@ pub unsafe fn instr_A2(mut moffs: i32) -> () { } #[no_mangle] pub unsafe fn instr16_A3(mut moffs: i32) -> () { - c_comment!(("mov")); + // mov return_on_pagefault!(safe_write16( get_seg_prefix_ds(moffs), *reg16.offset(AX as isize) as i32 @@ -2206,7 +2206,7 @@ pub unsafe fn instr32_C1_7_reg(mut r1: i32, mut imm: i32) -> () { } #[no_mangle] pub unsafe fn instr16_C2(mut imm16: i32) -> () { - c_comment!(("retn")); + // retn let mut cs: i32 = get_seg_cs(); *instruction_pointer.offset(0isize) = cs + return_on_pagefault!(pop16()); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); @@ -2214,7 +2214,7 @@ pub unsafe fn instr16_C2(mut imm16: i32) -> () { } #[no_mangle] pub unsafe fn instr32_C2(mut imm16: i32) -> () { - c_comment!(("retn")); + // retn let mut cs: i32 = get_seg_cs(); let mut ip: i32 = return_on_pagefault!(pop32s()); dbg_assert!(0 != is_asize_32() as i32 || ip < 65536i32); @@ -2223,13 +2223,13 @@ pub unsafe fn instr32_C2(mut imm16: i32) -> () { } #[no_mangle] pub unsafe fn instr16_C3() -> () { - c_comment!(("retn")); + // retn let mut cs: i32 = get_seg_cs(); *instruction_pointer.offset(0isize) = cs + return_on_pagefault!(pop16()); } #[no_mangle] pub unsafe fn instr32_C3() -> () { - c_comment!(("retn")); + // retn let mut cs: i32 = get_seg_cs(); let mut ip: i32 = return_on_pagefault!(pop32s()); dbg_assert!(0 != is_asize_32() as i32 || ip < 65536i32); @@ -2279,7 +2279,7 @@ pub unsafe fn instr16_C8(mut size: i32, mut nesting: i32) -> () { enter16(size, pub unsafe fn instr32_C8(mut size: i32, mut nesting: i32) -> () { enter32(size, nesting); } #[no_mangle] pub unsafe fn instr16_C9() -> () { - c_comment!(("leave")); + // leave let mut old_vbp: i32 = if 0 != *stack_size_32 as i32 { *reg32s.offset(EBP as isize) } @@ -2304,14 +2304,14 @@ pub unsafe fn instr32_C9() -> () { } #[no_mangle] pub unsafe fn instr16_CA(mut imm16: i32) -> () { - c_comment!(("retf")); + // retf let mut ip: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0i32))); let mut cs: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(2i32))); far_return(ip, cs, imm16); } #[no_mangle] pub unsafe fn instr32_CA(mut imm16: i32) -> () { - c_comment!(("retf")); + // retf let mut ip: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))); let mut cs: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(4i32))) & 65535i32; far_return(ip, cs, imm16); @@ -2319,7 +2319,7 @@ pub unsafe fn instr32_CA(mut imm16: i32) -> () { } #[no_mangle] pub unsafe fn instr16_CB() -> () { - c_comment!(("retf")); + // retf let mut ip: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0i32))); let mut cs: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(2i32))); far_return(ip, cs, 0i32); @@ -2327,7 +2327,7 @@ pub unsafe fn instr16_CB() -> () { } #[no_mangle] pub unsafe fn instr32_CB() -> () { - c_comment!(("retf")); + // retf let mut ip: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))); let mut cs: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(4i32))) & 65535i32; far_return(ip, cs, 0i32); @@ -2335,28 +2335,28 @@ pub unsafe fn instr32_CB() -> () { } #[no_mangle] pub unsafe fn instr_CC() -> () { - c_comment!(("INT3")); - c_comment!(("TODO: inhibit iopl checks")); + // INT3 + // TODO: inhibit iopl checks dbg_log_c!("INT3"); call_interrupt_vector(3i32, 0 != 1i32, 0 != 0i32, 0i32); } #[no_mangle] pub unsafe fn instr_CD(mut imm8: i32) -> () { - c_comment!(("INT")); + // INT call_interrupt_vector(imm8, 0 != 1i32, 0 != 0i32, 0i32); } #[no_mangle] pub unsafe fn instr_CE() -> () { - c_comment!(("INTO")); + // INTO dbg_log_c!("INTO"); if getof() { - c_comment!(("TODO: inhibit iopl checks")); + // TODO: inhibit iopl checks call_interrupt_vector(CPU_EXCEPTION_OF, 0 != 1i32, 0 != 0i32, 0i32); }; } #[no_mangle] pub unsafe fn instr16_CF() -> () { - c_comment!(("iret")); + // iret iret16(); } #[no_mangle] @@ -2895,12 +2895,12 @@ pub unsafe fn instr_D4(mut arg: i32) -> () { bcd_aam(arg); } pub unsafe fn instr_D5(mut arg: i32) -> () { bcd_aad(arg); } #[no_mangle] pub unsafe fn instr_D6() -> () { - c_comment!(("salc")); + // salc *reg8.offset(AL as isize) = -(getcf() as i32) as u8; } #[no_mangle] pub unsafe fn instr_D7() -> () { - c_comment!(("xlat")); + // xlat if is_asize_32() { *reg8.offset(AL as isize) = return_on_pagefault!(safe_read8( get_seg_prefix(DS) + *reg32s.offset(EBX as isize) + *reg8.offset(AL as isize) as i32, @@ -2975,37 +2975,37 @@ pub unsafe fn instr32_E7(mut port: i32) -> () { } #[no_mangle] pub unsafe fn instr16_E8(mut imm16: i32) -> () { - c_comment!(("call")); + // call return_on_pagefault!(push16(get_real_eip())); jmp_rel16(imm16); } #[no_mangle] pub unsafe fn instr32_E8(mut imm32s: i32) -> () { - c_comment!(("call")); + // call return_on_pagefault!(push32(get_real_eip())); *instruction_pointer.offset(0isize) = *instruction_pointer.offset(0isize) + imm32s; - c_comment!(("dbg_assert!(is_asize_32() || get_real_eip() < 0x10000);")); + // dbg_assert!(is_asize_32() || get_real_eip() < 0x10000); } #[no_mangle] pub unsafe fn instr16_E9(mut imm16: i32) -> () { - c_comment!(("jmp")); + // jmp jmp_rel16(imm16); } #[no_mangle] pub unsafe fn instr32_E9(mut imm32s: i32) -> () { - c_comment!(("jmp")); + // jmp *instruction_pointer.offset(0isize) = *instruction_pointer.offset(0isize) + imm32s; dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] pub unsafe fn instr16_EA(mut new_ip: i32, mut cs: i32) -> () { - c_comment!(("jmpf")); + // jmpf far_jump(new_ip, cs, false); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] pub unsafe fn instr32_EA(mut new_ip: i32, mut cs: i32) -> () { - c_comment!(("jmpf")); + // jmpf far_jump(new_ip, cs, false); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } @@ -3077,24 +3077,24 @@ pub unsafe fn instr32_EF() -> () { } #[no_mangle] pub unsafe fn instr_F0() -> () { - c_comment!(("lock")); + // lock if 0 != 0i32 * 0i32 { dbg_log_c!("lock"); } - c_comment!(("TODO")); - c_comment!(("This triggers UD when used with")); - c_comment!(("some instructions that don\'t write to memory")); + // TODO + // This triggers UD when used with + // some instructions that don't write to memory run_prefix_instruction(); } #[no_mangle] pub unsafe fn instr_F1() -> () { - c_comment!(("INT1")); - c_comment!(("https://code.google.com/p/corkami/wiki/x86oddities#IceBP")); + // INT1 + // https://code.google.com/p/corkami/wiki/x86oddities#IceBP dbg_assert!(0 != 0i32); } #[no_mangle] pub unsafe fn instr_F2() -> () { - c_comment!(("repnz")); + // repnz dbg_assert!(*prefixes as i32 & PREFIX_MASK_REP == 0i32); *prefixes = (*prefixes as i32 | PREFIX_REPNZ) as u8; run_prefix_instruction(); @@ -3102,7 +3102,7 @@ pub unsafe fn instr_F2() -> () { } #[no_mangle] pub unsafe fn instr_F3() -> () { - c_comment!(("repz")); + // repz dbg_assert!(*prefixes as i32 & PREFIX_MASK_REP == 0i32); *prefixes = (*prefixes as i32 | PREFIX_REPZ) as u8; run_prefix_instruction(); @@ -3112,7 +3112,7 @@ pub unsafe fn instr_F3() -> () { pub unsafe fn instr_F4() -> () { hlt_op(); } #[no_mangle] pub unsafe fn instr_F5() -> () { - c_comment!(("cmc")); + // cmc *flags.offset(0isize) = (*flags.offset(0isize) | 1i32) ^ getcf() as i32; let ref mut fresh2 = *flags_changed.offset(0isize); *fresh2 &= !1i32; @@ -3353,7 +3353,7 @@ pub unsafe fn instr32_F7_7_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe fn instr_F8() -> () { - c_comment!(("clc")); + // clc let ref mut fresh3 = *flags.offset(0isize); *fresh3 &= !FLAG_CARRY; let ref mut fresh4 = *flags_changed.offset(0isize); @@ -3361,7 +3361,7 @@ pub unsafe fn instr_F8() -> () { } #[no_mangle] pub unsafe fn instr_F9() -> () { - c_comment!(("stc")); + // stc let ref mut fresh5 = *flags.offset(0isize); *fresh5 |= FLAG_CARRY; let ref mut fresh6 = *flags_changed.offset(0isize); @@ -3369,7 +3369,7 @@ pub unsafe fn instr_F9() -> () { } #[no_mangle] pub unsafe fn instr_FA() -> () { - c_comment!(("cli")); + // cli if !*protected_mode || 0 != if 0 != *flags.offset(0isize) & FLAG_VM { (getiopl() == 3i32) as i32 } @@ -3394,7 +3394,7 @@ pub unsafe fn instr_FA() -> () { } #[no_mangle] pub unsafe fn instr_FB() -> () { - c_comment!(("sti")); + // sti let mut old_if: i32 = *flags.offset(0isize) & FLAG_INTERRUPT; if !*protected_mode || 0 != if 0 != *flags.offset(0isize) & FLAG_VM { (getiopl() == 3i32) as i32 @@ -3425,13 +3425,13 @@ pub unsafe fn instr_FB() -> () { } #[no_mangle] pub unsafe fn instr_FC() -> () { - c_comment!(("cld")); + // cld let ref mut fresh9 = *flags.offset(0isize); *fresh9 &= !FLAG_DIRECTION; } #[no_mangle] pub unsafe fn instr_FD() -> () { - c_comment!(("std")); + // std let ref mut fresh10 = *flags.offset(0isize); *fresh10 |= FLAG_DIRECTION; } @@ -3473,7 +3473,7 @@ pub unsafe fn instr16_FF_1_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe fn instr16_FF_2_helper(mut data: i32) -> () { - c_comment!(("call near")); + // call near let mut cs: i32 = get_seg_cs(); return_on_pagefault!(push16(get_real_eip())); *instruction_pointer.offset(0isize) = cs + data; @@ -3496,7 +3496,7 @@ pub unsafe fn instr16_FF_3_reg(mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr16_FF_3_mem(mut addr: i32) -> () { - c_comment!(("callf")); + // callf let mut new_ip: i32 = return_on_pagefault!(safe_read16(addr)); let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 2i32)); far_jump(new_ip, new_cs, true); @@ -3504,7 +3504,7 @@ pub unsafe fn instr16_FF_3_mem(mut addr: i32) -> () { } #[no_mangle] pub unsafe fn instr16_FF_4_helper(mut data: i32) -> () { - c_comment!(("jmp near")); + // jmp near *instruction_pointer.offset(0isize) = get_seg_cs() + data; dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } @@ -3525,7 +3525,7 @@ pub unsafe fn instr16_FF_5_reg(mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr16_FF_5_mem(mut addr: i32) -> () { - c_comment!(("jmpf")); + // jmpf let mut new_ip: i32 = return_on_pagefault!(safe_read16(addr)); let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 2i32)); far_jump(new_ip, new_cs, false); @@ -3561,7 +3561,7 @@ pub unsafe fn instr32_FF_1_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe fn instr32_FF_2_helper(mut data: i32) -> () { - c_comment!(("call near")); + // call near let mut cs: i32 = get_seg_cs(); return_on_pagefault!(push32(get_real_eip())); dbg_assert!(0 != is_asize_32() as i32 || data < 65536i32); @@ -3584,7 +3584,7 @@ pub unsafe fn instr32_FF_3_reg(mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr32_FF_3_mem(mut addr: i32) -> () { - c_comment!(("callf")); + // callf let mut new_ip: i32 = return_on_pagefault!(safe_read32s(addr)); let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 4i32)); if !*protected_mode || 0 != vm86_mode() as i32 { @@ -3597,7 +3597,7 @@ pub unsafe fn instr32_FF_3_mem(mut addr: i32) -> () { } #[no_mangle] pub unsafe fn instr32_FF_4_helper(mut data: i32) -> () { - c_comment!(("jmp near")); + // jmp near dbg_assert!(0 != is_asize_32() as i32 || data < 65536i32); *instruction_pointer.offset(0isize) = get_seg_cs() + data; } @@ -3618,7 +3618,7 @@ pub unsafe fn instr32_FF_5_reg(mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr32_FF_5_mem(mut addr: i32) -> () { - c_comment!(("jmpf")); + // jmpf let mut new_ip: i32 = return_on_pagefault!(safe_read32s(addr)); let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 4i32)); if !*protected_mode || 0 != vm86_mode() as i32 { @@ -3906,11 +3906,11 @@ pub unsafe fn instr_D9_4_reg(mut r: i32) -> () { let mut st0: f64 = fpu_get_st0(); match r { 0 => { - c_comment!(("fchs")); + // fchs *fpu_st.offset(*fpu_stack_ptr as isize) = -st0 }, 1 => { - c_comment!(("fabs")); + // fabs *fpu_st.offset(*fpu_stack_ptr as isize) = st0.abs() }, 4 => { @@ -3929,7 +3929,7 @@ pub unsafe fn instr_D9_4_reg(mut r: i32) -> () { pub unsafe fn instr_D9_5_mem(mut addr: i32) -> () { fpu_fldcw(addr); } #[no_mangle] pub unsafe fn instr_D9_5_reg(mut r: i32) -> () { - c_comment!(("fld1/fldl2t/fldl2e/fldpi/fldlg2/fldln2/fldz")); + // fld1/fldl2t/fldl2e/fldpi/fldlg2/fldln2/fldz match r { 0 => { fpu_push(1i32 as f64); @@ -3966,23 +3966,23 @@ pub unsafe fn instr_D9_6_reg(mut r: i32) -> () { let mut st0: f64 = fpu_get_st0(); match r { 0 => { - c_comment!(("f2xm1")); + // f2xm1 *fpu_st.offset(*fpu_stack_ptr as isize) = pow(2i32 as f64, st0) - 1i32 as f64 }, 1 => { - c_comment!(("fyl2x")); + // fyl2x *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(1i32 as u32) & 7i32 as u32) as isize) = fpu_get_sti(1i32) * st0.ln() / M_LN2; fpu_pop(); }, 2 => { - c_comment!(("fptan")); + // fptan *fpu_st.offset(*fpu_stack_ptr as isize) = st0.tan(); fpu_push(1i32 as f64); - c_comment!(("no bug: push constant 1")); + // no bug: push constant 1 }, 3 => { - c_comment!(("fpatan")); + // fpatan *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(1i32 as u32) & 7i32 as u32) as isize) = fpu_get_sti(1i32).atan2(st0); fpu_pop(); @@ -3991,16 +3991,16 @@ pub unsafe fn instr_D9_6_reg(mut r: i32) -> () { fpu_fxtract(); }, 5 => { - c_comment!(("fprem1")); + // fprem1 *fpu_st.offset(*fpu_stack_ptr as isize) = fmod(st0, fpu_get_sti(1i32)) }, 6 => { - c_comment!(("fdecstp")); + // fdecstp *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_sub(1i32 as u32) & 7i32 as u32; *fpu_status_word &= !FPU_C1 }, 7 => { - c_comment!(("fincstp")); + // fincstp *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_add(1i32 as u32) & 7i32 as u32; *fpu_status_word &= !FPU_C1 }, @@ -4019,7 +4019,7 @@ pub unsafe fn instr_D9_7_reg(mut r: i32) -> () { fpu_fprem(); }, 1 => { - c_comment!(("fyl2xp1: y * log2(x+1) and pop")); + // fyl2xp1: y * log2(x+1) and pop *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(1i32 as u32) & 7i32 as u32) as isize) = fpu_get_sti(1i32) * (st0 + 1i32 as f64).ln() / M_LN2; fpu_pop(); @@ -4030,11 +4030,11 @@ pub unsafe fn instr_D9_7_reg(mut r: i32) -> () { fpu_push(st0.cos()); }, 4 => { - c_comment!(("frndint")); + // frndint *fpu_st.offset(*fpu_stack_ptr as isize) = fpu_integer_round(st0) }, 5 => { - c_comment!(("fscale")); + // fscale *fpu_st.offset(*fpu_stack_ptr as isize) = st0 * pow(2i32 as f64, trunc(fpu_get_sti(1i32))) }, @@ -4130,7 +4130,7 @@ pub unsafe fn instr_DB_4_reg(mut r: i32) -> () { fpu_finit(); } else if r == 4i32 || r == 1i32 { - c_comment!(("fsetpm and fdisi; treated as nop")); + // fsetpm and fdisi; treated as nop } else if r == 2i32 { fpu_fclex(); @@ -4371,13 +4371,13 @@ pub unsafe fn instr32_E2(mut imm8s: i32) -> () { loop32(imm8s); } pub unsafe fn instr32_E3(mut imm8s: i32) -> () { jcxz32(imm8s); } #[no_mangle] pub unsafe fn instr16_EB(mut imm8: i32) -> () { - c_comment!(("jmp near")); + // jmp near jmp_rel16(imm8); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] pub unsafe fn instr32_EB(mut imm8: i32) -> () { - c_comment!(("jmp near")); + // jmp near *instruction_pointer.offset(0isize) = *instruction_pointer.offset(0isize) + imm8; dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index ad8c845d..0818efd2 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -68,7 +68,7 @@ const ENABLE_ACPI: bool = false; #[no_mangle] pub unsafe fn instr_0F00_0_mem(mut addr: i32) -> () { - c_comment!(("sldt")); + // sldt if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -91,7 +91,7 @@ pub unsafe fn instr_0F00_0_reg(mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F00_1_mem(mut addr: i32) -> () { - c_comment!(("str")); + // str if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -114,7 +114,7 @@ pub unsafe fn instr_0F00_1_reg(mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F00_2_mem(mut addr: i32) -> () { - c_comment!(("lldt")); + // lldt if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -145,7 +145,7 @@ pub unsafe fn instr_0F00_2_reg(mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F00_3_mem(mut addr: i32) -> () { - c_comment!(("ltr")); + // ltr if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -222,7 +222,7 @@ pub unsafe fn instr_0F00_5_reg(mut r: i32) -> () { pub unsafe fn instr_0F01_0_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0F01_0_mem(mut addr: i32) -> () { - c_comment!(("sgdt")); + // sgdt return_on_pagefault!(writable_or_pagefault(addr, 6i32)); let mut mask: i32 = if 0 != is_osize_32() as i32 { -1i32 @@ -237,7 +237,7 @@ pub unsafe fn instr_0F01_0_mem(mut addr: i32) -> () { pub unsafe fn instr_0F01_1_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0F01_1_mem(mut addr: i32) -> () { - c_comment!(("sidt")); + // sidt return_on_pagefault!(writable_or_pagefault(addr, 6i32)); let mut mask: i32 = if 0 != is_osize_32() as i32 { -1i32 @@ -252,7 +252,7 @@ pub unsafe fn instr_0F01_1_mem(mut addr: i32) -> () { pub unsafe fn instr_0F01_2_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0F01_2_mem(mut addr: i32) -> () { - c_comment!(("lgdt")); + // lgdt if 0 != *cpl.offset(0isize) { trigger_gp_non_raising(0i32); return; @@ -275,7 +275,7 @@ pub unsafe fn instr_0F01_2_mem(mut addr: i32) -> () { pub unsafe fn instr_0F01_3_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0F01_3_mem(mut addr: i32) -> () { - c_comment!(("lidt")); + // lidt if 0 != *cpl.offset(0isize) { trigger_gp_non_raising(0i32); return; @@ -296,7 +296,7 @@ pub unsafe fn instr_0F01_3_mem(mut addr: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F01_4_reg(mut r: i32) -> () { - c_comment!(("smsw")); + // smsw write_reg_osize(r, *cr.offset(0isize)); } #[no_mangle] @@ -307,7 +307,7 @@ pub unsafe fn instr_0F01_4_mem(mut addr: i32) -> () { pub unsafe fn lmsw(mut new_cr0: i32) -> () { new_cr0 = *cr.offset(0isize) & !15i32 | new_cr0 & 15i32; if *protected_mode.offset(0isize) { - c_comment!(("lmsw cannot be used to switch back")); + // lmsw cannot be used to switch back new_cr0 |= CR0_PE } set_cr0(new_cr0); @@ -338,7 +338,7 @@ pub unsafe fn instr_0F01_6_mem(mut addr: i32) -> () { pub unsafe fn instr_0F01_7_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0F01_7_mem(mut addr: i32) -> () { - c_comment!(("invlpg")); + // invlpg if 0 != *cpl.offset(0isize) { trigger_gp_non_raising(0i32); return; @@ -394,7 +394,7 @@ pub unsafe fn instr_0F04() -> () { undefined_instruction(); } pub unsafe fn instr_0F05() -> () { undefined_instruction(); } #[no_mangle] pub unsafe fn instr_0F06() -> () { - c_comment!(("clts")); + // clts if 0 != *cpl.offset(0isize) { dbg_log_c!("clts #gp"); trigger_gp_non_raising(0i32); @@ -411,7 +411,7 @@ pub unsafe fn instr_0F06() -> () { pub unsafe fn instr_0F07() -> () { undefined_instruction(); } #[no_mangle] pub unsafe fn instr_0F08() -> () { - c_comment!(("invd")); + // invd undefined_instruction(); } #[no_mangle] @@ -421,21 +421,21 @@ pub unsafe fn instr_0F09() -> () { trigger_gp_non_raising(0i32); } else { - c_comment!(("wbinvd")); + // wbinvd }; } #[no_mangle] pub unsafe fn instr_0F0A() -> () { undefined_instruction(); } #[no_mangle] pub unsafe fn instr_0F0B() -> () { - c_comment!(("UD2")); + // UD2 trigger_ud(); } #[no_mangle] pub unsafe fn instr_0F0C() -> () { undefined_instruction(); } #[no_mangle] pub unsafe fn instr_0F0D() -> () { - c_comment!(("nop")); + // nop undefined_instruction(); } #[no_mangle] @@ -444,7 +444,7 @@ pub unsafe fn instr_0F0E() -> () { undefined_instruction(); } pub unsafe fn instr_0F0F() -> () { undefined_instruction(); } #[no_mangle] pub unsafe fn instr_0F10(mut source: reg128, mut r: i32) -> () { - c_comment!(("movups xmm, xmm/m128")); + // movups xmm, xmm/m128 mov_rm_r128(source, r); } #[no_mangle] @@ -455,7 +455,7 @@ pub unsafe fn instr_0F10_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F30F10_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("movss xmm, xmm/m32")); + // movss xmm, xmm/m32 let mut data: reg128 = read_xmm128s(r1); let mut orig: reg128 = read_xmm128s(r2); write_xmm128( @@ -468,13 +468,13 @@ pub unsafe fn instr_F30F10_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe fn instr_F30F10_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movss xmm, xmm/m32")); + // movss xmm, xmm/m32 let mut data: i32 = return_on_pagefault!(safe_read32s(addr)); write_xmm128(r, data, 0i32, 0i32, 0i32); } #[no_mangle] pub unsafe fn instr_660F10(mut source: reg128, mut r: i32) -> () { - c_comment!(("movupd xmm, xmm/m128")); + // movupd xmm, xmm/m128 mov_rm_r128(source, r); } #[no_mangle] @@ -487,7 +487,7 @@ pub unsafe fn instr_660F10_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F20F10_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("movsd xmm, xmm/m64")); + // movsd xmm, xmm/m64 let mut data: reg128 = read_xmm128s(r1); let mut orig: reg128 = read_xmm128s(r2); write_xmm128( @@ -500,7 +500,7 @@ pub unsafe fn instr_F20F10_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe fn instr_F20F10_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movsd xmm, xmm/m64")); + // movsd xmm, xmm/m64 let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); write_xmm128( r, @@ -512,17 +512,17 @@ pub unsafe fn instr_F20F10_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F11_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("movups xmm/m128, xmm")); + // movups xmm/m128, xmm mov_r_r128(r1, r2); } #[no_mangle] pub unsafe fn instr_0F11_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movups xmm/m128, xmm")); + // movups xmm/m128, xmm mov_r_m128(addr, r); } #[no_mangle] pub unsafe fn instr_F30F11_reg(mut rm_dest: i32, mut reg_src: i32) -> () { - c_comment!(("movss xmm/m32, xmm")); + // movss xmm/m32, xmm let mut data: reg128 = read_xmm128s(reg_src); let mut orig: reg128 = read_xmm128s(rm_dest); write_xmm128( @@ -535,23 +535,23 @@ pub unsafe fn instr_F30F11_reg(mut rm_dest: i32, mut reg_src: i32) -> () { } #[no_mangle] pub unsafe fn instr_F30F11_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movss xmm/m32, xmm")); + // movss xmm/m32, xmm let mut data: reg128 = read_xmm128s(r); return_on_pagefault!(safe_write32(addr, data.u32_0[0usize] as i32)); } #[no_mangle] pub unsafe fn instr_660F11_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("movupd xmm/m128, xmm")); + // movupd xmm/m128, xmm mov_r_r128(r1, r2); } #[no_mangle] pub unsafe fn instr_660F11_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movupd xmm/m128, xmm")); + // movupd xmm/m128, xmm mov_r_m128(addr, r); } #[no_mangle] pub unsafe fn instr_F20F11_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("movsd xmm/m64, xmm")); + // movsd xmm/m64, xmm let mut data: reg128 = read_xmm128s(r2); let mut orig: reg128 = read_xmm128s(r1); write_xmm128( @@ -564,13 +564,13 @@ pub unsafe fn instr_F20F11_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe fn instr_F20F11_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movsd xmm/m64, xmm")); + // movsd xmm/m64, xmm let mut data: reg64 = read_xmm64s(r); return_on_pagefault!(safe_write64(addr, data.u64_0[0usize] as i64)); } #[no_mangle] pub unsafe fn instr_0F12_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movlps xmm, m64")); + // movlps xmm, m64 let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); let mut orig: reg128 = read_xmm128s(r); write_xmm128( @@ -583,7 +583,7 @@ pub unsafe fn instr_0F12_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F12_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("movhlps xmm, xmm")); + // movhlps xmm, xmm let mut data: reg128 = read_xmm128s(r1); let mut orig: reg128 = read_xmm128s(r2); write_xmm128( @@ -598,7 +598,7 @@ pub unsafe fn instr_0F12_reg(mut r1: i32, mut r2: i32) -> () { pub unsafe fn instr_660F12_reg(mut r1: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_660F12_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movlpd xmm, m64")); + // movlpd xmm, m64 let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); write_xmm64(r, data); } @@ -612,7 +612,7 @@ pub unsafe fn instr_F30F12_mem(mut addr: i32, mut r: i32) -> () { unimplemented_ pub unsafe fn instr_F30F12_reg(mut r1: i32, mut r2: i32) -> () { unimplemented_sse(); } #[no_mangle] pub unsafe fn instr_0F13_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movlps m64, xmm")); + // movlps m64, xmm movl_r128_m64(addr, r); } #[no_mangle] @@ -621,13 +621,13 @@ pub unsafe fn instr_0F13_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } pub unsafe fn instr_660F13_reg(mut r1: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_660F13_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movlpd xmm/m64, xmm")); + // movlpd xmm/m64, xmm movl_r128_m64(addr, r); } #[no_mangle] pub unsafe fn instr_0F14(mut source: reg64, mut r: i32) -> () { - c_comment!(("unpcklps xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // unpcklps xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg64 = read_xmm64s(r); write_xmm128( r, @@ -645,8 +645,8 @@ pub unsafe fn instr_0F14_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F14(mut source: reg64, mut r: i32) -> () { - c_comment!(("unpcklpd xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // unpcklpd xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg64 = read_xmm64s(r); write_xmm128( r, @@ -666,8 +666,8 @@ pub unsafe fn instr_660F14_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F15(mut source: reg128, mut r: i32) -> () { - c_comment!(("unpckhps xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // unpckhps xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, @@ -685,8 +685,8 @@ pub unsafe fn instr_0F15_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F15(mut source: reg128, mut r: i32) -> () { - c_comment!(("unpckhpd xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // unpckhpd xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, @@ -706,12 +706,12 @@ pub unsafe fn instr_660F15_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F16_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movhps xmm, m64")); + // movhps xmm, m64 movh_m64_r128(addr, r); } #[no_mangle] pub unsafe fn instr_0F16_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("movlhps xmm, xmm")); + // movlhps xmm, xmm let mut data: reg128 = read_xmm128s(r1); let mut orig: reg128 = read_xmm128s(r2); write_xmm128( @@ -724,33 +724,33 @@ pub unsafe fn instr_0F16_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F16_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movhpd xmm, m64")); + // movhpd xmm, m64 movh_m64_r128(addr, r); } #[no_mangle] pub unsafe fn instr_660F16_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0F17_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movhps m64, xmm")); + // movhps m64, xmm movh_r128_m64(addr, r); } #[no_mangle] pub unsafe fn instr_0F17_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_660F17_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movhpd m64, xmm")); + // movhpd m64, xmm movh_r128_m64(addr, r); } #[no_mangle] pub unsafe fn instr_660F17_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0F18_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("reserved nop")); + // reserved nop } #[no_mangle] pub unsafe fn instr_0F18_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("prefetch")); - c_comment!(("nop for us")); + // prefetch + // nop for us } #[no_mangle] pub unsafe fn instr_0F1A() -> () { undefined_instruction(); } @@ -802,7 +802,7 @@ pub unsafe fn instr_0F21(mut r: i32, mut dreg_index: i32) -> () { return; } else { - c_comment!(("DR4 and DR5 refer to DR6 and DR7 respectively")); + // DR4 and DR5 refer to DR6 and DR7 respectively dreg_index += 2i32 } } @@ -825,7 +825,7 @@ pub unsafe fn instr_0F22(mut r: i32, mut creg: i32) -> () { } else { let mut data: i32 = read_reg32(r); - c_comment!(("mov cr, addr")); + // mov cr, addr match creg { 0 => { if 0 != 0i32 * 0i32 { @@ -892,7 +892,7 @@ pub unsafe fn instr_0F23(mut r: i32, mut dreg_index: i32) -> () { return; } else { - c_comment!(("DR4 and DR5 refer to DR6 and DR7 respectively")); + // DR4 and DR5 refer to DR6 and DR7 respectively dreg_index += 2i32 } } @@ -917,8 +917,8 @@ pub unsafe fn instr_0F26() -> () { undefined_instruction(); } pub unsafe fn instr_0F27() -> () { undefined_instruction(); } #[no_mangle] pub unsafe fn instr_0F28(mut source: reg128, mut r: i32) -> () { - c_comment!(("movaps xmm, xmm/m128")); - c_comment!(("XXX: Aligned read or #gp")); + // movaps xmm, xmm/m128 + // XXX: Aligned read or #gp mov_rm_r128(source, r); } #[no_mangle] @@ -929,9 +929,9 @@ pub unsafe fn instr_0F28_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F28(mut source: reg128, mut r: i32) -> () { - c_comment!(("movapd xmm, xmm/m128")); - c_comment!(("XXX: Aligned read or #gp")); - c_comment!(("Note: Same as movdqa (660F6F)")); + // movapd xmm, xmm/m128 + // XXX: Aligned read or #gp + // Note: Same as movdqa (660F6F) mov_rm_r128(source, r); } #[no_mangle] @@ -944,42 +944,42 @@ pub unsafe fn instr_660F28_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F29_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movaps m128, xmm")); + // movaps m128, xmm let mut data: reg128 = read_xmm128s(r); - c_comment!(("XXX: Aligned write or #gp")); + // XXX: Aligned write or #gp return_on_pagefault!(safe_write128(addr, data)); } #[no_mangle] pub unsafe fn instr_0F29_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("movaps xmm, xmm")); + // movaps xmm, xmm mov_r_r128(r1, r2); } #[no_mangle] pub unsafe fn instr_660F29_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movapd m128, xmm")); + // movapd m128, xmm let mut data: reg128 = read_xmm128s(r); - c_comment!(("XXX: Aligned write or #gp")); + // XXX: Aligned write or #gp return_on_pagefault!(safe_write128(addr, data)); } #[no_mangle] pub unsafe fn instr_660F29_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("movapd xmm, xmm")); + // movapd xmm, xmm mov_r_r128(r1, r2); } #[no_mangle] pub unsafe fn instr_0F2B_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0F2B_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movntps m128, xmm")); - c_comment!(("XXX: Aligned write or #gp")); + // movntps m128, xmm + // XXX: Aligned write or #gp mov_r_m128(addr, r); } #[no_mangle] pub unsafe fn instr_660F2B_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_660F2B_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movntpd m128, xmm")); - c_comment!(("XXX: Aligned write or #gp")); + // movntpd m128, xmm + // XXX: Aligned write or #gp mov_r_m128(addr, r); } @@ -1024,7 +1024,7 @@ pub unsafe fn instr_660F2C_reg(mut r1: i32, mut r2: i32) -> () { #[no_mangle] pub unsafe fn instr_F20F2C(mut source: reg64, mut r: i32) -> () { - c_comment!(("cvttsd2si r32, xmm/m64")); + // cvttsd2si r32, xmm/m64 write_reg32(r, sse_convert_f64_to_i32(source.f64_0[0usize])); } #[no_mangle] @@ -1158,7 +1158,7 @@ pub unsafe fn instr_660F2F_mem(addr: i32, r: i32) { #[no_mangle] pub unsafe fn instr_0F30() -> () { - c_comment!(("wrmsr - write maschine specific register")); + // wrmsr - write maschine specific register if 0 != *cpl.offset(0isize) { trigger_gp_non_raising(0i32); return; @@ -1198,16 +1198,16 @@ pub unsafe fn instr_0F30() -> () { } else if !(index == IA32_BIOS_SIGN_ID) { if index == MSR_MISC_FEATURE_ENABLES { - c_comment!(("Linux 4, see: https://patchwork.kernel.org/patch/9528279/")); + // Linux 4, see: https://patchwork.kernel.org/patch/9528279/ } else if index == IA32_MISC_ENABLE { - c_comment!(("Enable Misc. Processor Features")); + // Enable Misc. Processor Features } else if index == IA32_MCG_CAP { - c_comment!(("netbsd")); + // netbsd } else if index == IA32_KERNEL_GS_BASE { - c_comment!(("Only used in 64 bit mode (by SWAPGS), but set by kvm-unit-test")); + // Only used in 64 bit mode (by SWAPGS), but set by kvm-unit-test dbg_log_c!("GS Base written"); } else { @@ -1220,7 +1220,7 @@ pub unsafe fn instr_0F30() -> () { } #[no_mangle] pub unsafe fn instr_0F31() -> () { - c_comment!(("rdtsc - read timestamp counter")); + // rdtsc - read timestamp counter if 0 == *cpl.offset(0isize) || 0 == *cr.offset(4isize) & CR4_TSD { let mut tsc: u64 = read_tsc(); *reg32s.offset(EAX as isize) = tsc as i32; @@ -1239,7 +1239,7 @@ pub unsafe fn instr_0F31() -> () { } #[no_mangle] pub unsafe fn instr_0F32() -> () { - c_comment!(("rdmsr - read maschine specific register")); + // rdmsr - read maschine specific register if 0 != *cpl.offset(0isize) { trigger_gp_non_raising(0i32); return; @@ -1278,16 +1278,16 @@ pub unsafe fn instr_0F32() -> () { } else if !(index == MSR_MISC_FEATURE_ENABLES) { if index == IA32_MISC_ENABLE { - c_comment!(("Enable Misc. Processor Features")); + // Enable Misc. Processor Features low = 1i32 << 0i32; - c_comment!(("fast string")); + // fast string } else if index == IA32_RTIT_CTL { - c_comment!(("linux4")); + // linux4 } else if !(index == MSR_SMI_COUNT) { if index == IA32_MCG_CAP { - c_comment!(("netbsd")); + // netbsd } else if !(index == MSR_PKG_C2_RESIDENCY) { dbg_log_c!("Unknown msr: %x", index); @@ -1304,12 +1304,12 @@ pub unsafe fn instr_0F32() -> () { } #[no_mangle] pub unsafe fn instr_0F33() -> () { - c_comment!(("rdpmc")); + // rdpmc undefined_instruction(); } #[no_mangle] pub unsafe fn instr_0F34() -> () { - c_comment!(("sysenter")); + // sysenter let mut seg: i32 = *sysenter_cs.offset(0isize) & 65532i32; if !*protected_mode.offset(0isize) || seg == 0i32 { trigger_gp_non_raising(0i32); @@ -1337,7 +1337,7 @@ pub unsafe fn instr_0F34() -> () { } #[no_mangle] pub unsafe fn instr_0F35() -> () { - c_comment!(("sysexit")); + // sysexit let mut seg: i32 = *sysenter_cs.offset(0isize) & 65532i32; if !*protected_mode.offset(0isize) || 0 != *cpl.offset(0isize) as i32 || seg == 0i32 { trigger_gp_non_raising(0i32); @@ -1365,7 +1365,7 @@ pub unsafe fn instr_0F35() -> () { pub unsafe fn instr_0F36() -> () { undefined_instruction(); } #[no_mangle] pub unsafe fn instr_0F37() -> () { - c_comment!(("getsec")); + // getsec undefined_instruction(); } #[no_mangle] @@ -1706,7 +1706,7 @@ pub unsafe fn instr32_0F4F_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F50_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("movmskps r, xmm")); + // movmskps r, xmm let mut source: reg128 = read_xmm128s(r1); let mut data: i32 = (source.u32_0[0usize] >> 31i32 | source.u32_0[1usize] >> 31i32 << 1i32 @@ -1718,7 +1718,7 @@ pub unsafe fn instr_0F50_reg(mut r1: i32, mut r2: i32) -> () { pub unsafe fn instr_0F50_mem(mut addr: i32, mut r1: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_660F50_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("movmskpd r, xmm")); + // movmskpd r, xmm let mut source: reg128 = read_xmm128s(r1); let mut data: i32 = (source.u32_0[1usize] >> 31i32 | source.u32_0[3usize] >> 31i32 << 1i32) as i32; @@ -1728,8 +1728,8 @@ pub unsafe fn instr_660F50_reg(mut r1: i32, mut r2: i32) -> () { pub unsafe fn instr_660F50_mem(mut addr: i32, mut r1: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0F54(mut source: reg128, mut r: i32) -> () { - c_comment!(("andps xmm, xmm/mem128")); - c_comment!(("XXX: Aligned access or #gp")); + // andps xmm, xmm/mem128 + // XXX: Aligned access or #gp pand_r128(source, r); } #[no_mangle] @@ -1740,8 +1740,8 @@ pub unsafe fn instr_0F54_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F54(mut source: reg128, mut r: i32) -> () { - c_comment!(("andpd xmm, xmm/mem128")); - c_comment!(("XXX: Aligned access or #gp")); + // andpd xmm, xmm/mem128 + // XXX: Aligned access or #gp pand_r128(source, r); } #[no_mangle] @@ -1754,8 +1754,8 @@ pub unsafe fn instr_660F54_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F55(mut source: reg128, mut r: i32) -> () { - c_comment!(("andnps xmm, xmm/mem128")); - c_comment!(("XXX: Aligned access or #gp")); + // andnps xmm, xmm/mem128 + // XXX: Aligned access or #gp pandn_r128(source, r); } #[no_mangle] @@ -1766,8 +1766,8 @@ pub unsafe fn instr_0F55_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F55(mut source: reg128, mut r: i32) -> () { - c_comment!(("andnpd xmm, xmm/mem128")); - c_comment!(("XXX: Aligned access or #gp")); + // andnpd xmm, xmm/mem128 + // XXX: Aligned access or #gp pandn_r128(source, r); } #[no_mangle] @@ -1780,8 +1780,8 @@ pub unsafe fn instr_660F55_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F56(mut source: reg128, mut r: i32) -> () { - c_comment!(("orps xmm, xmm/mem128")); - c_comment!(("XXX: Aligned access or #gp")); + // orps xmm, xmm/mem128 + // XXX: Aligned access or #gp por_r128(source, r); } #[no_mangle] @@ -1792,8 +1792,8 @@ pub unsafe fn instr_0F56_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F56(mut source: reg128, mut r: i32) -> () { - c_comment!(("orpd xmm, xmm/mem128")); - c_comment!(("XXX: Aligned access or #gp")); + // orpd xmm, xmm/mem128 + // XXX: Aligned access or #gp por_r128(source, r); } #[no_mangle] @@ -1806,8 +1806,8 @@ pub unsafe fn instr_660F56_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F57(mut source: reg128, mut r: i32) -> () { - c_comment!(("xorps xmm, xmm/mem128")); - c_comment!(("XXX: Aligned access or #gp")); + // xorps xmm, xmm/mem128 + // XXX: Aligned access or #gp pxor_r128(source, r); } #[no_mangle] @@ -1818,8 +1818,8 @@ pub unsafe fn instr_0F57_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F57(mut source: reg128, mut r: i32) -> () { - c_comment!(("xorpd xmm, xmm/mem128")); - c_comment!(("XXX: Aligned access or #gp")); + // xorpd xmm, xmm/mem128 + // XXX: Aligned access or #gp pxor_r128(source, r); } #[no_mangle] @@ -1832,7 +1832,7 @@ pub unsafe fn instr_660F57_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F60(mut source: i32, mut r: i32) -> () { - c_comment!(("punpcklbw mm, mm/m32")); + // punpcklbw mm, mm/m32 let mut destination: reg64 = read_mmx64s(r); let mut byte0: i32 = destination.u8_0[0usize] as i32; let mut byte1: i32 = source & 255i32; @@ -1854,8 +1854,8 @@ pub unsafe fn instr_0F60_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F60(mut source: reg64, mut r: i32) -> () { - c_comment!(("punpcklbw xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // punpcklbw xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg64 = read_xmm64s(r); write_xmm128( r, @@ -1887,7 +1887,7 @@ pub unsafe fn instr_660F60_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F61(mut source: i32, mut r: i32) -> () { - c_comment!(("punpcklwd mm, mm/m32")); + // punpcklwd mm, mm/m32 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = destination.u16_0[0usize] as i32; let mut word1: i32 = source & 65535i32; @@ -1905,8 +1905,8 @@ pub unsafe fn instr_0F61_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F61(mut source: reg64, mut r: i32) -> () { - c_comment!(("punpcklwd xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // punpcklwd xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg64 = read_xmm64s(r); write_xmm128( r, @@ -1926,7 +1926,7 @@ pub unsafe fn instr_660F61_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F62(mut source: i32, mut r: i32) -> () { - c_comment!(("punpckldq mm, mm/m32")); + // punpckldq mm, mm/m32 let mut destination: reg64 = read_mmx64s(r); write_mmx64(r, destination.u32_0[0usize] as i32, source); } @@ -1938,8 +1938,8 @@ pub unsafe fn instr_0F62_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F62(mut source: reg128, mut r: i32) -> () { - c_comment!(("punpckldq xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // punpckldq xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, @@ -1959,7 +1959,7 @@ pub unsafe fn instr_660F62_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F63(mut source: reg64, mut r: i32) -> () { - c_comment!(("packsswb mm, mm/m64")); + // packsswb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut low: i32 = saturate_sw_to_sb(destination.u16_0[0usize] as i32) | saturate_sw_to_sb(destination.u16_0[1usize] as i32) << 8i32 @@ -1979,8 +1979,8 @@ pub unsafe fn instr_0F63_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F63(mut source: reg128, mut r: i32) -> () { - c_comment!(("packsswb xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // packsswb xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = saturate_sw_to_sb(destination.u16_0[0usize] as i32) | saturate_sw_to_sb(destination.u16_0[1usize] as i32) << 8i32 @@ -2010,7 +2010,7 @@ pub unsafe fn instr_660F63_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F64(mut source: reg64, mut r: i32) -> () { - c_comment!(("pcmpgtb mm, mm/m64")); + // pcmpgtb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], @@ -2036,8 +2036,8 @@ pub unsafe fn instr_0F64_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F64(mut source: reg128, mut r: i32) -> () { - c_comment!(("pcmpgtb xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pcmpgtb xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], @@ -2065,7 +2065,7 @@ pub unsafe fn instr_660F64_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F65(mut source: reg64, mut r: i32) -> () { - c_comment!(("pcmpgtw mm, mm/m64")); + // pcmpgtw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = if destination.i16_0[0usize] as i32 > source.i16_0[0usize] as i32 { 65535i32 @@ -2103,8 +2103,8 @@ pub unsafe fn instr_0F65_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F65(mut source: reg128, mut r: i32) -> () { - c_comment!(("pcmpgtw xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pcmpgtw xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], @@ -2132,7 +2132,7 @@ pub unsafe fn instr_660F65_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F66(mut source: reg64, mut r: i32) -> () { - c_comment!(("pcmpgtd mm, mm/m64")); + // pcmpgtd mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut low: i32 = if destination.i32_0[0usize] > source.i32_0[0usize] { -1i32 @@ -2156,8 +2156,8 @@ pub unsafe fn instr_0F66_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F66(mut source: reg128, mut r: i32) -> () { - c_comment!(("pcmpgtd xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pcmpgtd xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, @@ -2197,7 +2197,7 @@ pub unsafe fn instr_660F66_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F67(mut source: reg64, mut r: i32) -> () { - c_comment!(("packuswb mm, mm/m64")); + // packuswb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut low: u32 = saturate_sw_to_ub(destination.u16_0[0usize] as u32) | saturate_sw_to_ub(destination.u16_0[1usize] as u32) << 8i32 @@ -2217,8 +2217,8 @@ pub unsafe fn instr_0F67_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F67(mut source: reg128, mut r: i32) -> () { - c_comment!(("packuswb xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // packuswb xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; let mut i: i32 = 0i32; @@ -2239,7 +2239,7 @@ pub unsafe fn instr_660F67_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F68(mut source: reg64, mut r: i32) -> () { - c_comment!(("punpckhbw mm, mm/m64")); + // punpckhbw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut byte0: i32 = destination.u8_0[4usize] as i32; let mut byte1: i32 = source.u8_0[4usize] as i32; @@ -2261,8 +2261,8 @@ pub unsafe fn instr_0F68_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F68(mut source: reg128, mut r: i32) -> () { - c_comment!(("punpckhbw xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // punpckhbw xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, @@ -2294,7 +2294,7 @@ pub unsafe fn instr_660F68_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F69(mut source: reg64, mut r: i32) -> () { - c_comment!(("punpckhwd mm, mm/m64")); + // punpckhwd mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = destination.u16_0[2usize] as i32; let mut word1: i32 = source.u16_0[2usize] as i32; @@ -2312,8 +2312,8 @@ pub unsafe fn instr_0F69_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F69(mut source: reg128, mut r: i32) -> () { - c_comment!(("punpckhwd xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // punpckhwd xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = destination.u16_0[4usize] as i32 | (source.u16_0[4usize] as i32) << 16i32; let mut dword1: i32 = destination.u16_0[5usize] as i32 | (source.u16_0[5usize] as i32) << 16i32; @@ -2331,7 +2331,7 @@ pub unsafe fn instr_660F69_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F6A(mut source: reg64, mut r: i32) -> () { - c_comment!(("punpckhdq mm, mm/m64")); + // punpckhdq mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); write_mmx64( r, @@ -2347,8 +2347,8 @@ pub unsafe fn instr_0F6A_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F6A(mut source: reg128, mut r: i32) -> () { - c_comment!(("punpckhdq xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // punpckhdq xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, @@ -2368,7 +2368,7 @@ pub unsafe fn instr_660F6A_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F6B(mut source: reg64, mut r: i32) -> () { - c_comment!(("packssdw mm, mm/m64")); + // packssdw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut low: i32 = (saturate_sd_to_sw(destination.u32_0[0usize]) | saturate_sd_to_sw(destination.u32_0[1usize]) << 16i32) as i32; @@ -2384,8 +2384,8 @@ pub unsafe fn instr_0F6B_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F6B(mut source: reg128, mut r: i32) -> () { - c_comment!(("packssdw xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // packssdw xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = (saturate_sd_to_sw(destination.u32_0[0usize]) | saturate_sd_to_sw(destination.u32_0[1usize]) << 16i32) as i32; @@ -2411,8 +2411,8 @@ pub unsafe fn instr_0F6C_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } pub unsafe fn instr_0F6C_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_660F6C(mut source: reg128, mut r: i32) -> () { - c_comment!(("punpcklqdq xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // punpcklqdq xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, @@ -2436,8 +2436,8 @@ pub unsafe fn instr_0F6D_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } pub unsafe fn instr_0F6D_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_660F6D(mut source: reg128, mut r: i32) -> () { - c_comment!(("punpckhqdq xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // punpckhqdq xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, @@ -2457,7 +2457,7 @@ pub unsafe fn instr_660F6D_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F6E(mut source: i32, mut r: i32) -> () { - c_comment!(("movd mm, r/m32")); + // movd mm, r/m32 write_mmx64(r, source, 0i32); } #[no_mangle] @@ -2468,7 +2468,7 @@ pub unsafe fn instr_0F6E_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F6E(mut source: i32, mut r: i32) -> () { - c_comment!(("movd mm, r/m32")); + // movd mm, r/m32 write_xmm128(r, source, 0i32, 0i32, 0i32); } #[no_mangle] @@ -2479,7 +2479,7 @@ pub unsafe fn instr_660F6E_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F6F(mut source: reg64, mut r: i32) -> () { - c_comment!(("movq mm, mm/m64")); + // movq mm, mm/m64 write_mmx64(r, source.u32_0[0usize] as i32, source.u32_0[1usize] as i32); } #[no_mangle] @@ -2490,9 +2490,9 @@ pub unsafe fn instr_0F6F_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F6F(mut source: reg128, mut r: i32) -> () { - c_comment!(("movdqa xmm, xmm/mem128")); - c_comment!(("XXX: Aligned access or #gp")); - c_comment!(("XXX: Aligned read or #gp")); + // movdqa xmm, xmm/mem128 + // XXX: Aligned access or #gp + // XXX: Aligned read or #gp mov_rm_r128(source, r); } #[no_mangle] @@ -2505,7 +2505,7 @@ pub unsafe fn instr_660F6F_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F30F6F(mut source: reg128, mut r: i32) -> () { - c_comment!(("movdqu xmm, xmm/m128")); + // movdqu xmm, xmm/m128 mov_rm_r128(source, r); } #[no_mangle] @@ -2518,7 +2518,7 @@ pub unsafe fn instr_F30F6F_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F70(mut source: reg64, mut r: i32, mut imm8: i32) -> () { - c_comment!(("pshufw mm1, mm2/m64, imm8")); + // pshufw mm1, mm2/m64, imm8 let mut word0_shift: i32 = imm8 & 3i32; let mut word0: u32 = source.u32_0[(word0_shift >> 1i32) as usize] >> ((word0_shift & 1i32) << 4i32) @@ -2547,8 +2547,8 @@ pub unsafe fn instr_0F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F70(mut source: reg128, mut r: i32, mut imm8: i32) -> () { - c_comment!(("pshufd xmm, xmm/mem128")); - c_comment!(("XXX: Aligned access or #gp")); + // pshufd xmm, xmm/mem128 + // XXX: Aligned access or #gp write_xmm128( r, source.u32_0[(imm8 & 3i32) as usize] as i32, @@ -2568,8 +2568,8 @@ pub unsafe fn instr_660F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { #[no_mangle] pub unsafe fn instr_F20F70(mut source: reg128, mut r: i32, mut imm8: i32) -> () { - c_comment!(("pshuflw xmm, xmm/m128, imm8")); - c_comment!(("XXX: Aligned access or #gp")); + // pshuflw xmm, xmm/m128, imm8 + // XXX: Aligned access or #gp write_xmm128( r, source.u16_0[(imm8 & 3i32) as usize] as i32 @@ -2590,8 +2590,8 @@ pub unsafe fn instr_F20F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { } #[no_mangle] pub unsafe fn instr_F30F70(mut source: reg128, mut r: i32, mut imm8: i32) -> () { - c_comment!(("pshufhw xmm, xmm/m128, imm8")); - c_comment!(("XXX: Aligned access or #gp")); + // pshufhw xmm, xmm/m128, imm8 + // XXX: Aligned access or #gp write_xmm128( r, source.u32_0[0usize] as i32, @@ -2618,17 +2618,17 @@ pub unsafe fn instr_0F71_4_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); pub unsafe fn instr_0F71_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0F71_2_reg(mut r: i32, mut imm8: i32) -> () { - c_comment!(("psrlw mm, imm8")); + // psrlw mm, imm8 psrlw_r64(r, imm8 as u32); } #[no_mangle] pub unsafe fn instr_0F71_4_reg(mut r: i32, mut imm8: i32) -> () { - c_comment!(("psraw mm, imm8")); + // psraw mm, imm8 psraw_r64(r, imm8 as u32); } #[no_mangle] pub unsafe fn instr_0F71_6_reg(mut r: i32, mut imm8: i32) -> () { - c_comment!(("psllw mm, imm8")); + // psllw mm, imm8 psllw_r64(r, imm8 as u32); } #[no_mangle] @@ -2639,17 +2639,17 @@ pub unsafe fn instr_660F71_4_mem(mut addr: i32, mut r: i32) -> () { trigger_ud() pub unsafe fn instr_660F71_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_660F71_2_reg(mut r: i32, mut imm8: i32) -> () { - c_comment!(("psrlw xmm, imm8")); + // psrlw xmm, imm8 psrlw_r128(r, imm8 as u32); } #[no_mangle] pub unsafe fn instr_660F71_4_reg(mut r: i32, mut imm8: i32) -> () { - c_comment!(("psraw xmm, imm8")); + // psraw xmm, imm8 psraw_r128(r, imm8 as u32); } #[no_mangle] pub unsafe fn instr_660F71_6_reg(mut r: i32, mut imm8: i32) -> () { - c_comment!(("psllw xmm, imm8")); + // psllw xmm, imm8 psllw_r128(r, imm8 as u32); } #[no_mangle] @@ -2660,17 +2660,17 @@ pub unsafe fn instr_0F72_4_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); pub unsafe fn instr_0F72_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0F72_2_reg(mut r: i32, mut imm8: i32) -> () { - c_comment!(("psrld mm, imm8")); + // psrld mm, imm8 psrld_r64(r, imm8 as u32); } #[no_mangle] pub unsafe fn instr_0F72_4_reg(mut r: i32, mut imm8: i32) -> () { - c_comment!(("psrad mm, imm8")); + // psrad mm, imm8 psrad_r64(r, imm8 as u32); } #[no_mangle] pub unsafe fn instr_0F72_6_reg(mut r: i32, mut imm8: i32) -> () { - c_comment!(("pslld mm, imm8")); + // pslld mm, imm8 pslld_r64(r, imm8 as u32); } #[no_mangle] @@ -2681,17 +2681,17 @@ pub unsafe fn instr_660F72_4_mem(mut addr: i32, mut r: i32) -> () { trigger_ud() pub unsafe fn instr_660F72_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_660F72_2_reg(mut r: i32, mut imm8: i32) -> () { - c_comment!(("psrld xmm, imm8")); + // psrld xmm, imm8 psrld_r128(r, imm8 as u32); } #[no_mangle] pub unsafe fn instr_660F72_4_reg(mut r: i32, mut imm8: i32) -> () { - c_comment!(("psrad xmm, imm8")); + // psrad xmm, imm8 psrad_r128(r, imm8 as u32); } #[no_mangle] pub unsafe fn instr_660F72_6_reg(mut r: i32, mut imm8: i32) -> () { - c_comment!(("pslld xmm, imm8")); + // pslld xmm, imm8 pslld_r128(r, imm8 as u32); } #[no_mangle] @@ -2700,12 +2700,12 @@ pub unsafe fn instr_0F73_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); pub unsafe fn instr_0F73_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0F73_2_reg(mut r: i32, mut imm8: i32) -> () { - c_comment!(("psrlq mm, imm8")); + // psrlq mm, imm8 psrlq_r64(r, imm8 as u32); } #[no_mangle] pub unsafe fn instr_0F73_6_reg(mut r: i32, mut imm8: i32) -> () { - c_comment!(("psllq mm, imm8")); + // psllq mm, imm8 psllq_r64(r, imm8 as u32); } #[no_mangle] @@ -2718,12 +2718,12 @@ pub unsafe fn instr_660F73_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud() pub unsafe fn instr_660F73_7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_660F73_2_reg(mut r: i32, mut imm8: i32) -> () { - c_comment!(("psrlq xmm, imm8")); + // psrlq xmm, imm8 psrlq_r128(r, imm8 as u32); } #[no_mangle] pub unsafe fn instr_660F73_3_reg(mut r: i32, mut imm8: i32) -> () { - c_comment!(("psrldq xmm, imm8")); + // psrldq xmm, imm8 let mut destination: reg128 = read_xmm128s(r); if imm8 == 0i32 { return; @@ -2748,12 +2748,12 @@ pub unsafe fn instr_660F73_3_reg(mut r: i32, mut imm8: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F73_6_reg(mut r: i32, mut imm8: i32) -> () { - c_comment!(("psllq xmm, imm8")); + // psllq xmm, imm8 psllq_r128(r, imm8 as u32); } #[no_mangle] pub unsafe fn instr_660F73_7_reg(mut r: i32, mut imm8: i32) -> () { - c_comment!(("pslldq xmm, imm8")); + // pslldq xmm, imm8 let mut destination: reg128 = read_xmm128s(r); if imm8 == 0i32 { return; @@ -2778,7 +2778,7 @@ pub unsafe fn instr_660F73_7_reg(mut r: i32, mut imm8: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F74(mut source: reg64, mut r: i32) -> () { - c_comment!(("pcmpeqb mm, mm/m64")); + // pcmpeqb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], @@ -2804,8 +2804,8 @@ pub unsafe fn instr_0F74_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F74(mut source: reg128, mut r: i32) -> () { - c_comment!(("pcmpeqb xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pcmpeqb xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; let mut i: i32 = 0i32; @@ -2831,7 +2831,7 @@ pub unsafe fn instr_660F74_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F75(mut source: reg64, mut r: i32) -> () { - c_comment!(("pcmpeqw mm, mm/m64")); + // pcmpeqw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = if destination.u16_0[0usize] as i32 == source.u16_0[0usize] as i32 { 65535i32 @@ -2869,8 +2869,8 @@ pub unsafe fn instr_0F75_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F75(mut source: reg128, mut r: i32) -> () { - c_comment!(("pcmpeqw xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pcmpeqw xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; let mut i: i32 = 0i32; @@ -2896,7 +2896,7 @@ pub unsafe fn instr_660F75_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F76(mut source: reg64, mut r: i32) -> () { - c_comment!(("pcmpeqd mm, mm/m64")); + // pcmpeqd mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut low: i32 = if destination.u32_0[0usize] == source.u32_0[0usize] { -1i32 @@ -2920,8 +2920,8 @@ pub unsafe fn instr_0F76_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F76(mut source: reg128, mut r: i32) -> () { - c_comment!(("pcmpeqd xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pcmpeqd xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, @@ -2961,7 +2961,7 @@ pub unsafe fn instr_660F76_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F77() -> () { - c_comment!(("emms")); + // emms fpu_set_tag_word(65535i32); } #[no_mangle] @@ -2978,7 +2978,7 @@ pub unsafe fn instr_0F7C() -> () { unimplemented_sse(); } pub unsafe fn instr_0F7D() -> () { unimplemented_sse(); } #[no_mangle] pub unsafe fn instr_0F7E(mut r: i32) -> i32 { - c_comment!(("movd r/m32, mm")); + // movd r/m32, mm let mut data: reg64 = read_mmx64s(r); return data.u32_0[0usize] as i32; } @@ -2990,7 +2990,7 @@ pub unsafe fn instr_0F7E_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F7E(mut r: i32) -> i32 { - c_comment!(("movd r/m32, xmm")); + // movd r/m32, xmm let mut data: reg64 = read_xmm64s(r); return data.u32_0[0usize] as i32; } @@ -3004,7 +3004,7 @@ pub unsafe fn instr_660F7E_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F30F7E_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movq xmm, xmm/mem64")); + // movq xmm, xmm/mem64 let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); write_xmm128( r, @@ -3016,7 +3016,7 @@ pub unsafe fn instr_F30F7E_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F30F7E_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("movq xmm, xmm/mem64")); + // movq xmm, xmm/mem64 let mut data: reg64 = read_xmm64s(r1); write_xmm128( r2, @@ -3028,35 +3028,35 @@ pub unsafe fn instr_F30F7E_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F7F_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movq mm/m64, mm")); + // movq mm/m64, mm mov_r_m64(addr, r); } #[no_mangle] pub unsafe fn instr_0F7F_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("movq mm/m64, mm")); + // movq mm/m64, mm let mut data: reg64 = read_mmx64s(r2); write_mmx64(r1, data.u32_0[0usize] as i32, data.u32_0[1usize] as i32); } #[no_mangle] pub unsafe fn instr_660F7F_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movdqa xmm/m128, xmm")); - c_comment!(("XXX: Aligned write or #gp")); + // movdqa xmm/m128, xmm + // XXX: Aligned write or #gp mov_r_m128(addr, r); } #[no_mangle] pub unsafe fn instr_660F7F_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("movdqa xmm/m128, xmm")); - c_comment!(("XXX: Aligned access or #gp")); + // movdqa xmm/m128, xmm + // XXX: Aligned access or #gp mov_r_r128(r1, r2); } #[no_mangle] pub unsafe fn instr_F30F7F_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movdqu xmm/m128, xmm")); + // movdqu xmm/m128, xmm mov_r_m128(addr, r); } #[no_mangle] pub unsafe fn instr_F30F7F_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("movdqu xmm/m128, xmm")); + // movdqu xmm/m128, xmm mov_r_r128(r1, r2); } #[no_mangle] @@ -3297,7 +3297,7 @@ pub unsafe fn instr32_0FA5_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FA6() -> () { - c_comment!(("obsolete cmpxchg (os/2)")); + // obsolete cmpxchg (os/2) trigger_ud(); } #[no_mangle] @@ -3338,7 +3338,7 @@ pub unsafe fn instr32_0FA9() -> () { } #[no_mangle] pub unsafe fn instr_0FAA() -> () { - c_comment!(("rsm")); + // rsm undefined_instruction(); } #[no_mangle] @@ -3425,7 +3425,7 @@ pub unsafe fn instr_0FAE_1_mem(mut addr: i32) -> () { fxrstor(addr as u32); } pub unsafe fn instr_0FAE_2_reg(mut r: i32) -> () { unimplemented_sse(); } #[no_mangle] pub unsafe fn instr_0FAE_2_mem(mut addr: i32) -> () { - c_comment!(("ldmxcsr")); + // ldmxcsr let mut new_mxcsr: i32 = return_on_pagefault!(safe_read32s(addr)); if 0 != new_mxcsr & !MXCSR_MASK { dbg_log!("Invalid mxcsr bits: {:x}", new_mxcsr & !MXCSR_MASK); @@ -3441,44 +3441,44 @@ pub unsafe fn instr_0FAE_2_mem(mut addr: i32) -> () { pub unsafe fn instr_0FAE_3_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0FAE_3_mem(mut addr: i32) -> () { - c_comment!(("stmxcsr")); + // stmxcsr return_on_pagefault!(safe_write32(addr, *mxcsr)); } #[no_mangle] pub unsafe fn instr_0FAE_4_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0FAE_4_mem(mut addr: i32) -> () { - c_comment!(("xsave")); + // xsave undefined_instruction(); } #[no_mangle] pub unsafe fn instr_0FAE_5_reg(mut r: i32) -> () { - c_comment!(("lfence")); + // lfence dbg_assert!(r == 0i32, ("Unexpected lfence encoding")); } #[no_mangle] pub unsafe fn instr_0FAE_5_mem(mut addr: i32) -> () { - c_comment!(("xrstor")); + // xrstor undefined_instruction(); } #[no_mangle] pub unsafe fn instr_0FAE_6_reg(mut r: i32) -> () { - c_comment!(("mfence")); + // mfence dbg_assert!(r == 0i32, ("Unexpected mfence encoding")); } #[no_mangle] pub unsafe fn instr_0FAE_6_mem(mut addr: i32) -> () { - c_comment!(("xsaveopt")); + // xsaveopt undefined_instruction(); } #[no_mangle] pub unsafe fn instr_0FAE_7_reg(mut r: i32) -> () { - c_comment!(("sfence")); + // sfence dbg_assert!(r == 0i32, ("Unexpected sfence encoding")); } #[no_mangle] pub unsafe fn instr_0FAE_7_mem(mut addr: i32) -> () { - c_comment!(("clflush")); + // clflush undefined_instruction(); } #[no_mangle] @@ -3503,7 +3503,7 @@ pub unsafe fn instr32_0FAF_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FB0_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("cmpxchg8")); + // cmpxchg8 let mut data: i32 = read_reg8(r1); cmp8(*reg8.offset(AL as isize) as i32, data); if getzf() { @@ -3515,7 +3515,7 @@ pub unsafe fn instr_0FB0_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FB0_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("cmpxchg8")); + // cmpxchg8 return_on_pagefault!(writable_or_pagefault(addr, 1i32)); let mut data: i32 = return_on_pagefault!(safe_read8(addr)); cmp8(*reg8.offset(AL as isize) as i32, data); @@ -3529,7 +3529,7 @@ pub unsafe fn instr_0FB0_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr16_0FB1_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("cmpxchg16")); + // cmpxchg16 let mut data: i32 = read_reg16(r1); cmp16(*reg16.offset(AX as isize) as i32, data); if getzf() { @@ -3541,7 +3541,7 @@ pub unsafe fn instr16_0FB1_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe fn instr16_0FB1_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("cmpxchg16")); + // cmpxchg16 return_on_pagefault!(writable_or_pagefault(addr, 2i32)); let mut data: i32 = return_on_pagefault!(safe_read16(addr)); cmp16(*reg16.offset(AX as isize) as i32, data); @@ -3555,7 +3555,7 @@ pub unsafe fn instr16_0FB1_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr32_0FB1_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("cmpxchg32")); + // cmpxchg32 let mut data: i32 = read_reg32(r1); cmp32(*reg32s.offset(EAX as isize), data); if getzf() { @@ -3567,7 +3567,7 @@ pub unsafe fn instr32_0FB1_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe fn instr32_0FB1_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("cmpxchg32")); + // cmpxchg32 return_on_pagefault!(writable_or_pagefault(addr, 4i32)); let mut data: i32 = return_on_pagefault!(safe_read32s(addr)); cmp32(*reg32s.offset(EAX as isize), data); @@ -3693,7 +3693,7 @@ pub unsafe fn instr32_F30FB8_reg(mut r1: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FB9() -> () { - c_comment!(("UD2")); + // UD2 trigger_ud(); } #[no_mangle] @@ -3869,12 +3869,12 @@ pub unsafe fn instr32_0FC1_reg(mut r1: i32, mut r: i32) -> () { pub unsafe fn instr_0FC3_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0FC3_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movnti")); + // movnti return_on_pagefault!(safe_write32(addr, read_reg32(r))); } #[no_mangle] pub unsafe fn instr_0FC4(mut source: i32, mut r: i32, mut imm8: i32) -> () { - c_comment!(("pinsrw mm, r32/m16, imm8")); + // pinsrw mm, r32/m16, imm8 let mut destination: reg64 = read_mmx64s(r); let mut index: u32 = (imm8 & 3i32) as u32; destination.u16_0[index as usize] = (source & 65535i32) as u16; @@ -3890,7 +3890,7 @@ pub unsafe fn instr_0FC4_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FC4(mut source: i32, mut r: i32, mut imm8: i32) -> () { - c_comment!(("pinsrw xmm, r32/m16, imm8")); + // pinsrw xmm, r32/m16, imm8 let mut destination: reg128 = read_xmm128s(r); let mut index: u32 = (imm8 & 7i32) as u32; destination.u16_0[index as usize] = (source & 65535i32) as u16; @@ -3908,7 +3908,7 @@ pub unsafe fn instr_660FC4_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { pub unsafe fn instr_0FC5_mem(mut addr: i32, mut r: i32, mut imm8: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i32) -> () { - c_comment!(("pextrw r32, mm, imm8")); + // pextrw r32, mm, imm8 let mut data: reg64 = read_mmx64s(r1); let mut index: u32 = (imm8 & 3i32) as u32; let mut result: u32 = data.u16_0[index as usize] as u32; @@ -3918,7 +3918,7 @@ pub unsafe fn instr_0FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i32) -> () { pub unsafe fn instr_660FC5_mem(mut addr: i32, mut r: i32, mut imm8: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_660FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i32) -> () { - c_comment!(("pextrw r32, xmm, imm8")); + // pextrw r32, xmm, imm8 let mut data: reg128 = read_xmm128s(r1); let mut index: u32 = (imm8 & 7i32) as u32; let mut result: u32 = data.u16_0[index as usize] as u32; @@ -3927,8 +3927,8 @@ pub unsafe fn instr_660FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i32) -> () { #[no_mangle] pub unsafe fn instr_0FC6(mut source: reg128, mut r: i32, mut imm8: i32) -> () { - c_comment!(("shufps xmm, xmm/mem128")); - c_comment!(("XXX: Aligned access or #gp")); + // shufps xmm, xmm/mem128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, @@ -3949,7 +3949,7 @@ pub unsafe fn instr_0FC6_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { #[no_mangle] pub unsafe fn instr_660FC6(mut source: reg128, mut r: i32, mut imm8: i32) -> () { - c_comment!(("shufpd xmm, xmm/mem128")); + // shufpd xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i64_0: [ @@ -3972,7 +3972,7 @@ pub unsafe fn instr_660FC6_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { pub unsafe fn instr_0FC7_1_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0FC7_1_mem(mut addr: i32) -> () { - c_comment!(("cmpxchg8b")); + // cmpxchg8b return_on_pagefault!(writable_or_pagefault(addr, 8i32)); let mut m64_low: i32 = return_on_pagefault!(safe_read32s(addr)); let mut m64_high: i32 = return_on_pagefault!(safe_read32s(addr + 4i32)); @@ -3995,7 +3995,7 @@ pub unsafe fn instr_0FC7_1_mem(mut addr: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FC7_6_reg(mut r: i32) -> () { - c_comment!(("rdrand")); + // rdrand let mut has_rand: i32 = has_rand_int() as i32; let mut rand: i32 = 0i32; if 0 != has_rand { @@ -4030,7 +4030,7 @@ pub unsafe fn instr_0FCF() -> () { bswap(EDI); } pub unsafe fn instr_0FD0() -> () { unimplemented_sse(); } #[no_mangle] pub unsafe fn instr_0FD1(mut source: reg64, mut r: i32) -> () { - c_comment!(("psrlw mm, mm/m64")); + // psrlw mm, mm/m64 psrlw_r64(r, source.u32_0[0usize]); } #[no_mangle] @@ -4041,8 +4041,8 @@ pub unsafe fn instr_0FD1_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FD1(mut source: reg128, mut r: i32) -> () { - c_comment!(("psrlw xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // psrlw xmm, xmm/m128 + // XXX: Aligned access or #gp psrlw_r128(r, source.u32_0[0usize]); } #[no_mangle] @@ -4055,7 +4055,7 @@ pub unsafe fn instr_660FD1_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FD2(mut source: reg64, mut r: i32) -> () { - c_comment!(("psrld mm, mm/m64")); + // psrld mm, mm/m64 psrld_r64(r, source.u32_0[0usize]); } #[no_mangle] @@ -4066,8 +4066,8 @@ pub unsafe fn instr_0FD2_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FD2(mut source: reg128, mut r: i32) -> () { - c_comment!(("psrld xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // psrld xmm, xmm/m128 + // XXX: Aligned access or #gp psrld_r128(r, source.u32_0[0usize]); } #[no_mangle] @@ -4080,7 +4080,7 @@ pub unsafe fn instr_660FD2_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FD3(mut source: reg64, mut r: i32) -> () { - c_comment!(("psrlq mm, mm/m64")); + // psrlq mm, mm/m64 psrlq_r64(r, source.u32_0[0usize]); } #[no_mangle] @@ -4091,7 +4091,7 @@ pub unsafe fn instr_0FD3_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FD3(mut source: reg128, mut r: i32) -> () { - c_comment!(("psrlq xmm, mm/m64")); + // psrlq xmm, mm/m64 psrlq_r128(r, source.u32_0[0usize]); } #[no_mangle] @@ -4104,7 +4104,7 @@ pub unsafe fn instr_660FD3_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FD4(mut source: reg64, mut r: i32) -> () { - c_comment!(("paddq mm, mm/m64")); + // paddq mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); destination.u64_0[0usize] = (destination.u64_0[0usize] as u64).wrapping_add(source.u64_0[0usize]) as u64 as u64; @@ -4118,8 +4118,8 @@ pub unsafe fn instr_0FD4_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FD4(mut source: reg128, mut r: i32) -> () { - c_comment!(("paddq xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // paddq xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); destination.u64_0[0usize] = (destination.u64_0[0usize] as u64).wrapping_add(source.u64_0[0usize]) as u64 as u64; @@ -4137,7 +4137,7 @@ pub unsafe fn instr_660FD4_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FD5(mut source: reg64, mut r: i32) -> () { - c_comment!(("pmullw mm, mm/m64")); + // pmullw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = destination.u16_0[0usize] as i32 * source.u16_0[0usize] as i32 & 65535i32; let mut word1: i32 = destination.u16_0[1usize] as i32 * source.u16_0[1usize] as i32 & 65535i32; @@ -4155,8 +4155,8 @@ pub unsafe fn instr_0FD5_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FD5(mut source: reg128, mut r: i32) -> () { - c_comment!(("pmullw xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pmullw xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, @@ -4184,12 +4184,12 @@ pub unsafe fn instr_0FD6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } pub unsafe fn instr_0FD6_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_660FD6_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movq xmm/m64, xmm")); + // movq xmm/m64, xmm movl_r128_m64(addr, r); } #[no_mangle] pub unsafe fn instr_660FD6_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("movq xmm/m64, xmm")); + // movq xmm/m64, xmm let mut data: reg64 = read_xmm64s(r2); write_xmm128( r1, @@ -4203,7 +4203,7 @@ pub unsafe fn instr_660FD6_reg(mut r1: i32, mut r2: i32) -> () { pub unsafe fn instr_F20FD6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_F20FD6_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("movdq2q mm, xmm")); + // movdq2q mm, xmm let mut source: reg128 = read_xmm128s(r1); write_mmx64(r2, source.u32_0[0usize] as i32, source.u32_0[1usize] as i32); } @@ -4211,7 +4211,7 @@ pub unsafe fn instr_F20FD6_reg(mut r1: i32, mut r2: i32) -> () { pub unsafe fn instr_F30FD6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_F30FD6_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("movq2dq xmm, mm")); + // movq2dq xmm, mm let mut source: reg64 = read_mmx64s(r1); write_xmm128( r2, @@ -4225,7 +4225,7 @@ pub unsafe fn instr_F30FD6_reg(mut r1: i32, mut r2: i32) -> () { pub unsafe fn instr_0FD7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0FD7_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("pmovmskb r, mm")); + // pmovmskb r, mm let mut x: reg64 = read_mmx64s(r1); let mut result: u32 = (x.u8_0[0usize] as i32 >> 7i32 << 0i32 | x.u8_0[1usize] as i32 >> 7i32 << 1i32 @@ -4241,7 +4241,7 @@ pub unsafe fn instr_0FD7_reg(mut r1: i32, mut r2: i32) -> () { pub unsafe fn instr_660FD7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_660FD7_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("pmovmskb reg, xmm")); + // pmovmskb reg, xmm let mut x: reg128 = read_xmm128s(r1); let mut result: i32 = x.u8_0[0usize] as i32 >> 7i32 << 0i32 | x.u8_0[1usize] as i32 >> 7i32 << 1i32 @@ -4263,7 +4263,7 @@ pub unsafe fn instr_660FD7_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FD8(mut source: reg64, mut r: i32) -> () { - c_comment!(("psubusb mm, mm/m64")); + // psubusb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], @@ -4285,7 +4285,7 @@ pub unsafe fn instr_0FD8_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FD8(mut source: reg128, mut r: i32) -> () { - c_comment!(("psubusb xmm, xmm/m128")); + // psubusb xmm, xmm/m128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; let mut i: u32 = 0i32 as u32; @@ -4307,7 +4307,7 @@ pub unsafe fn instr_660FD8_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FD9(mut source: reg64, mut r: i32) -> () { - c_comment!(("psubusw mm, mm/m64")); + // psubusw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = saturate_uw((destination.u16_0[0usize] as i32 - source.u16_0[0usize] as i32) as u32); @@ -4329,7 +4329,7 @@ pub unsafe fn instr_0FD9_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FD9(mut source: reg128, mut r: i32) -> () { - c_comment!(("psubusw xmm, xmm/m128")); + // psubusw xmm, xmm/m128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; let mut i: u32 = 0i32 as u32; @@ -4351,7 +4351,7 @@ pub unsafe fn instr_660FD9_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FDA(mut source: reg64, mut r: i32) -> () { - c_comment!(("pminub mm, mm/m64")); + // pminub mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; let mut i: u32 = 0i32 as u32; @@ -4375,8 +4375,8 @@ pub unsafe fn instr_0FDA_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FDA(mut source: reg128, mut r: i32) -> () { - c_comment!(("pminub xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pminub xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; let mut i: u32 = 0i32 as u32; @@ -4402,7 +4402,7 @@ pub unsafe fn instr_660FDA_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FDB(mut source: reg64, mut r: i32) -> () { - c_comment!(("pand mm, mm/m64")); + // pand mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], @@ -4418,8 +4418,8 @@ pub unsafe fn instr_0FDB_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FDB(mut source: reg128, mut r: i32) -> () { - c_comment!(("pand xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pand xmm, xmm/m128 + // XXX: Aligned access or #gp pand_r128(source, r); } #[no_mangle] @@ -4432,7 +4432,7 @@ pub unsafe fn instr_660FDB_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FDC(mut source: reg64, mut r: i32) -> () { - c_comment!(("paddusb mm, mm/m64")); + // paddusb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], @@ -4454,8 +4454,8 @@ pub unsafe fn instr_0FDC_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FDC(mut source: reg128, mut r: i32) -> () { - c_comment!(("paddusb xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // paddusb xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; let mut i: u32 = 0i32 as u32; @@ -4477,7 +4477,7 @@ pub unsafe fn instr_660FDC_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FDD(mut source: reg64, mut r: i32) -> () { - c_comment!(("paddusw mm, mm/m64")); + // paddusw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = saturate_uw((destination.u16_0[0usize] as i32 + source.u16_0[0usize] as i32) as u32); @@ -4499,8 +4499,8 @@ pub unsafe fn instr_0FDD_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FDD(mut source: reg128, mut r: i32) -> () { - c_comment!(("paddusw xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // paddusw xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, @@ -4528,7 +4528,7 @@ pub unsafe fn instr_660FDD_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FDE(mut source: reg64, mut r: i32) -> () { - c_comment!(("pmaxub mm, mm/m64")); + // pmaxub mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; let mut i: u32 = 0i32 as u32; @@ -4552,8 +4552,8 @@ pub unsafe fn instr_0FDE_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FDE(mut source: reg128, mut r: i32) -> () { - c_comment!(("pmaxub xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pmaxub xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; let mut i: u32 = 0i32 as u32; @@ -4579,7 +4579,7 @@ pub unsafe fn instr_660FDE_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FDF(mut source: reg64, mut r: i32) -> () { - c_comment!(("pandn mm, mm/m64")); + // pandn mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], @@ -4595,8 +4595,8 @@ pub unsafe fn instr_0FDF_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FDF(mut source: reg128, mut r: i32) -> () { - c_comment!(("pandn xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pandn xmm, xmm/m128 + // XXX: Aligned access or #gp pandn_r128(source, r); } #[no_mangle] @@ -4609,7 +4609,7 @@ pub unsafe fn instr_660FDF_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FE0(mut source: reg64, mut r: i32) -> () { - c_comment!(("pavgb mm, mm/m64")); + // pavgb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], @@ -4631,8 +4631,8 @@ pub unsafe fn instr_0FE0_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FE0(mut source: reg128, mut r: i32) -> () { - c_comment!(("pavgb xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pavgb xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; let mut i: u32 = 0i32 as u32; @@ -4654,7 +4654,7 @@ pub unsafe fn instr_660FE0_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FE1(mut source: reg64, mut r: i32) -> () { - c_comment!(("psraw mm, mm/m64")); + // psraw mm, mm/m64 psraw_r64(r, source.u32_0[0usize]); } #[no_mangle] @@ -4665,8 +4665,8 @@ pub unsafe fn instr_0FE1_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FE1(mut source: reg128, mut r: i32) -> () { - c_comment!(("psraw xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // psraw xmm, xmm/m128 + // XXX: Aligned access or #gp psraw_r128(r, source.u32_0[0usize]); } #[no_mangle] @@ -4679,7 +4679,7 @@ pub unsafe fn instr_660FE1_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FE2(mut source: reg64, mut r: i32) -> () { - c_comment!(("psrad mm, mm/m64")); + // psrad mm, mm/m64 psrad_r64(r, source.u32_0[0usize]); } #[no_mangle] @@ -4690,8 +4690,8 @@ pub unsafe fn instr_0FE2_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FE2(mut source: reg128, mut r: i32) -> () { - c_comment!(("psrad xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // psrad xmm, xmm/m128 + // XXX: Aligned access or #gp psrad_r128(r, source.u32_0[0usize]); } #[no_mangle] @@ -4704,7 +4704,7 @@ pub unsafe fn instr_660FE2_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FE3(mut source: reg64, mut r: i32) -> () { - c_comment!(("pavgw mm, mm/m64")); + // pavgw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); destination.u16_0[0usize] = (destination.u16_0[0usize] as i32 + source.u16_0[0usize] as i32 + 1i32 >> 1i32) as u16; @@ -4724,8 +4724,8 @@ pub unsafe fn instr_0FE3_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FE3(mut source: reg128, mut r: i32) -> () { - c_comment!(("pavgw xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pavgw xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); destination.u16_0[0usize] = (destination.u16_0[0usize] as i32 + source.u16_0[0usize] as i32 + 1i32 >> 1i32) as u16; @@ -4755,7 +4755,7 @@ pub unsafe fn instr_660FE3_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FE4(mut source: reg64, mut r: i32) -> () { - c_comment!(("pmulhuw mm, mm/m64")); + // pmulhuw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); write_mmx64( r, @@ -4777,8 +4777,8 @@ pub unsafe fn instr_0FE4_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FE4(mut source: reg128, mut r: i32) -> () { - c_comment!(("pmulhuw xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pmulhuw xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, @@ -4810,7 +4810,7 @@ pub unsafe fn instr_660FE4_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FE5(mut source: reg64, mut r: i32) -> () { - c_comment!(("pmulhw mm, mm/m64")); + // pmulhw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: u32 = (destination.i16_0[0usize] as i32 * source.i16_0[0usize] as i32 >> 16i32 & 65535i32) as u32; @@ -4832,8 +4832,8 @@ pub unsafe fn instr_0FE5_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FE5(mut source: reg128, mut r: i32) -> () { - c_comment!(("pmulhw xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pmulhw xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = ((destination.i16_0[0usize] as i32 * source.i16_0[0usize] as i32 >> 16i32 & 65535i32) as u32 @@ -4935,7 +4935,7 @@ pub unsafe fn instr_F30FE6_reg(mut r1: i32, mut r2: i32) -> () { #[no_mangle] pub unsafe fn instr_0FE7_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movntq m64, mm")); + // movntq m64, mm mov_r_m64(addr, r); } #[no_mangle] @@ -4944,12 +4944,12 @@ pub unsafe fn instr_0FE7_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } pub unsafe fn instr_660FE7_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_660FE7_mem(mut addr: i32, mut r: i32) -> () { - c_comment!(("movntdq m128, xmm")); + // movntdq m128, xmm mov_r_m128(addr, r); } #[no_mangle] pub unsafe fn instr_0FE8(mut source: reg64, mut r: i32) -> () { - c_comment!(("psubsb mm, mm/m64")); + // psubsb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], @@ -4971,8 +4971,8 @@ pub unsafe fn instr_0FE8_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FE8(mut source: reg128, mut r: i32) -> () { - c_comment!(("psubsb xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // psubsb xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; let mut i: u32 = 0i32 as u32; @@ -4994,7 +4994,7 @@ pub unsafe fn instr_660FE8_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FE9(mut source: reg64, mut r: i32) -> () { - c_comment!(("psubsw mm, mm/m64")); + // psubsw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = saturate_sd_to_sw((destination.i16_0[0usize] as i32 - source.i16_0[0usize] as i32) as u32) @@ -5020,8 +5020,8 @@ pub unsafe fn instr_0FE9_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FE9(mut source: reg128, mut r: i32) -> () { - c_comment!(("psubsw xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // psubsw xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = (saturate_sd_to_sw((destination.i16_0[0usize] as i32 - source.i16_0[0usize] as i32) as u32) @@ -5055,7 +5055,7 @@ pub unsafe fn instr_660FE9_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FEA(mut source: reg64, mut r: i32) -> () { - c_comment!(("pminsw mm, mm/m64")); + // pminsw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; let mut i: u32 = 0i32 as u32; @@ -5079,8 +5079,8 @@ pub unsafe fn instr_0FEA_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FEA(mut source: reg128, mut r: i32) -> () { - c_comment!(("pminsw xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pminsw xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; let mut i: u32 = 0i32 as u32; @@ -5106,7 +5106,7 @@ pub unsafe fn instr_660FEA_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FEB(mut source: reg64, mut r: i32) -> () { - c_comment!(("por mm, mm/m64")); + // por mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], @@ -5122,8 +5122,8 @@ pub unsafe fn instr_0FEB_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FEB(mut source: reg128, mut r: i32) -> () { - c_comment!(("por xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // por xmm, xmm/m128 + // XXX: Aligned access or #gp por_r128(source, r); } #[no_mangle] @@ -5136,7 +5136,7 @@ pub unsafe fn instr_660FEB_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FEC(mut source: reg64, mut r: i32) -> () { - c_comment!(("paddsb mm, mm/m64")); + // paddsb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], @@ -5158,8 +5158,8 @@ pub unsafe fn instr_0FEC_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FEC(mut source: reg128, mut r: i32) -> () { - c_comment!(("paddsb xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // paddsb xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; let mut i: u32 = 0i32 as u32; @@ -5181,7 +5181,7 @@ pub unsafe fn instr_660FEC_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FED(mut source: reg64, mut r: i32) -> () { - c_comment!(("paddsw mm, mm/m64")); + // paddsw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = saturate_sd_to_sw((destination.i16_0[0usize] as i32 + source.i16_0[0usize] as i32) as u32) @@ -5207,8 +5207,8 @@ pub unsafe fn instr_0FED_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FED(mut source: reg128, mut r: i32) -> () { - c_comment!(("paddsw xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // paddsw xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = (saturate_sd_to_sw((destination.i16_0[0usize] as i32 + source.i16_0[0usize] as i32) as u32) @@ -5242,7 +5242,7 @@ pub unsafe fn instr_660FED_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FEE(mut source: reg64, mut r: i32) -> () { - c_comment!(("pmaxsw mm, mm/m64")); + // pmaxsw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; let mut i: u32 = 0i32 as u32; @@ -5266,8 +5266,8 @@ pub unsafe fn instr_0FEE_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FEE(mut source: reg128, mut r: i32) -> () { - c_comment!(("pmaxsw xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pmaxsw xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; let mut i: u32 = 0i32 as u32; @@ -5293,7 +5293,7 @@ pub unsafe fn instr_660FEE_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FEF(mut source: reg64, mut r: i32) -> () { - c_comment!(("pxor mm, mm/m64")); + // pxor mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], @@ -5309,8 +5309,8 @@ pub unsafe fn instr_0FEF_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FEF(mut source: reg128, mut r: i32) -> () { - c_comment!(("pxor xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pxor xmm, xmm/m128 + // XXX: Aligned access or #gp pxor_r128(source, r); } #[no_mangle] @@ -5325,7 +5325,7 @@ pub unsafe fn instr_660FEF_mem(mut addr: i32, mut r: i32) -> () { pub unsafe fn instr_0FF0() -> () { unimplemented_sse(); } #[no_mangle] pub unsafe fn instr_0FF1(mut source: reg64, mut r: i32) -> () { - c_comment!(("psllw mm, mm/m64")); + // psllw mm, mm/m64 psllw_r64(r, source.u32_0[0usize]); } #[no_mangle] @@ -5336,8 +5336,8 @@ pub unsafe fn instr_0FF1_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FF1(mut source: reg128, mut r: i32) -> () { - c_comment!(("psllw xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // psllw xmm, xmm/m128 + // XXX: Aligned access or #gp psllw_r128(r, source.u32_0[0usize]); } #[no_mangle] @@ -5350,7 +5350,7 @@ pub unsafe fn instr_660FF1_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FF2(mut source: reg64, mut r: i32) -> () { - c_comment!(("pslld mm, mm/m64")); + // pslld mm, mm/m64 pslld_r64(r, source.u32_0[0usize]); } #[no_mangle] @@ -5361,8 +5361,8 @@ pub unsafe fn instr_0FF2_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FF2(mut source: reg128, mut r: i32) -> () { - c_comment!(("pslld xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pslld xmm, xmm/m128 + // XXX: Aligned access or #gp pslld_r128(r, source.u32_0[0usize]); } #[no_mangle] @@ -5375,7 +5375,7 @@ pub unsafe fn instr_660FF2_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FF3(mut source: reg64, mut r: i32) -> () { - c_comment!(("psllq mm, mm/m64")); + // psllq mm, mm/m64 psllq_r64(r, source.u32_0[0usize]); } #[no_mangle] @@ -5386,8 +5386,8 @@ pub unsafe fn instr_0FF3_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FF3(mut source: reg128, mut r: i32) -> () { - c_comment!(("psllq xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // psllq xmm, xmm/m128 + // XXX: Aligned access or #gp psllq_r128(r, source.u32_0[0usize]); } #[no_mangle] @@ -5400,7 +5400,7 @@ pub unsafe fn instr_660FF3_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FF4(mut source: reg64, mut r: i32) -> () { - c_comment!(("pmuludq mm, mm/m64")); + // pmuludq mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); destination.u64_0[0usize] = (source.u32_0[0usize] as u64).wrapping_mul(destination.u32_0[0usize] as u64); @@ -5414,8 +5414,8 @@ pub unsafe fn instr_0FF4_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FF4(mut source: reg128, mut r: i32) -> () { - c_comment!(("pmuludq xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pmuludq xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); destination.u64_0[0usize] = (source.u32_0[0usize] as u64).wrapping_mul(destination.u32_0[0usize] as u64); @@ -5433,7 +5433,7 @@ pub unsafe fn instr_660FF4_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FF5(mut source: reg64, mut r: i32) -> () { - c_comment!(("pmaddwd mm, mm/m64")); + // pmaddwd mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut mul0: i32 = destination.i16_0[0usize] as i32 * source.i16_0[0usize] as i32; let mut mul1: i32 = destination.i16_0[1usize] as i32 * source.i16_0[1usize] as i32; @@ -5451,8 +5451,8 @@ pub unsafe fn instr_0FF5_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FF5(mut source: reg128, mut r: i32) -> () { - c_comment!(("pmaddwd xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pmaddwd xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = destination.i16_0[0usize] as i32 * source.i16_0[0usize] as i32 + destination.i16_0[1usize] as i32 * source.i16_0[1usize] as i32; @@ -5474,7 +5474,7 @@ pub unsafe fn instr_660FF5_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FF6(mut source: reg64, mut r: i32) -> () { - c_comment!(("psadbw mm, mm/m64")); + // psadbw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut sum: u32 = 0i32 as u32; let mut i: u32 = 0i32 as u32; @@ -5494,8 +5494,8 @@ pub unsafe fn instr_0FF6_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FF6(mut source: reg128, mut r: i32) -> () { - c_comment!(("psadbw xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // psadbw xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut sum0: u32 = 0i32 as u32; let mut sum1: u32 = 0i32 as u32; @@ -5525,7 +5525,7 @@ pub unsafe fn instr_660FF6_mem(mut addr: i32, mut r: i32) -> () { pub unsafe fn instr_0FF7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0FF7_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("maskmovq mm, mm")); + // maskmovq mm, mm let mut source: reg64 = read_mmx64s(r2); let mut mask: reg64 = read_mmx64s(r1); let mut addr: i32 = get_seg_prefix(DS) + get_reg_asize(EDI); @@ -5545,7 +5545,7 @@ pub unsafe fn instr_0FF7_reg(mut r1: i32, mut r2: i32) -> () { pub unsafe fn instr_660FF7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_660FF7_reg(mut r1: i32, mut r2: i32) -> () { - c_comment!(("maskmovdqu xmm, xmm")); + // maskmovdqu xmm, xmm let mut source: reg128 = read_xmm128s(r2); let mut mask: reg128 = read_xmm128s(r1); let mut addr: i32 = get_seg_prefix(DS) + get_reg_asize(EDI); @@ -5563,7 +5563,7 @@ pub unsafe fn instr_660FF7_reg(mut r1: i32, mut r2: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FF8(mut source: reg64, mut r: i32) -> () { - c_comment!(("psubb mm, mm/m64")); + // psubb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], @@ -5584,8 +5584,8 @@ pub unsafe fn instr_0FF8_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FF8(mut source: reg128, mut r: i32) -> () { - c_comment!(("psubb xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // psubb xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], @@ -5608,7 +5608,7 @@ pub unsafe fn instr_660FF8_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FF9(mut source: reg64, mut r: i32) -> () { - c_comment!(("psubw mm, mm/m64")); + // psubw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = (destination.u32_0[0usize].wrapping_sub(source.u32_0[0usize]) & 65535i32 as u32) as i32; @@ -5632,8 +5632,8 @@ pub unsafe fn instr_0FF9_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FF9(mut source: reg128, mut r: i32) -> () { - c_comment!(("psubw xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // psubw xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], @@ -5657,7 +5657,7 @@ pub unsafe fn instr_660FF9_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FFA(mut source: reg64, mut r: i32) -> () { - c_comment!(("psubd mm, mm/m64")); + // psubd mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); write_mmx64( r, @@ -5673,8 +5673,8 @@ pub unsafe fn instr_0FFA_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FFA(mut source: reg128, mut r: i32) -> () { - c_comment!(("psubd xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // psubd xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, @@ -5694,7 +5694,7 @@ pub unsafe fn instr_660FFA_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FFB(mut source: reg64, mut r: i32) -> () { - c_comment!(("psubq mm, mm/m64")); + // psubq mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); destination.u64_0[0usize] = destination.u64_0[0usize].wrapping_sub(source.u64_0[0usize]); write_mmx_reg64(r, destination); @@ -5707,8 +5707,8 @@ pub unsafe fn instr_0FFB_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FFB(mut source: reg128, mut r: i32) -> () { - c_comment!(("psubq xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // psubq xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); destination.u64_0[0usize] = destination.u64_0[0usize].wrapping_sub(source.u64_0[0usize]); destination.u64_0[1usize] = destination.u64_0[1usize].wrapping_sub(source.u64_0[1usize]); @@ -5724,7 +5724,7 @@ pub unsafe fn instr_660FFB_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FFC(mut source: reg64, mut r: i32) -> () { - c_comment!(("paddb mm, mm/m64")); + // paddb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], @@ -5745,8 +5745,8 @@ pub unsafe fn instr_0FFC_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FFC(mut source: reg128, mut r: i32) -> () { - c_comment!(("paddb xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // paddb xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], @@ -5769,7 +5769,7 @@ pub unsafe fn instr_660FFC_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FFD(mut source: reg64, mut r: i32) -> () { - c_comment!(("paddw mm, mm/m64")); + // paddw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = (destination.u32_0[0usize].wrapping_add(source.u32_0[0usize]) & 65535i32 as u32) as i32; @@ -5789,8 +5789,8 @@ pub unsafe fn instr_0FFD_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FFD(mut source: reg128, mut r: i32) -> () { - c_comment!(("paddw xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // paddw xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], @@ -5814,7 +5814,7 @@ pub unsafe fn instr_660FFD_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FFE(mut source: reg64, mut r: i32) -> () { - c_comment!(("paddd mm, mm/m64")); + // paddd mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut low: i32 = destination.u32_0[0usize].wrapping_add(source.u32_0[0usize]) as i32; let mut high: i32 = destination.u32_0[1usize].wrapping_add(source.u32_0[1usize]) as i32; @@ -5828,8 +5828,8 @@ pub unsafe fn instr_0FFE_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FFE(mut source: reg128, mut r: i32) -> () { - c_comment!(("paddd xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // paddd xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = destination.u32_0[0usize].wrapping_add(source.u32_0[0usize]) as i32; let mut dword1: i32 = destination.u32_0[1usize].wrapping_add(source.u32_0[1usize]) as i32; @@ -5847,7 +5847,7 @@ pub unsafe fn instr_660FFE_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FFF() -> () { - c_comment!(("Windows 98")); + // Windows 98 dbg_log_c!("#ud: 0F FF"); trigger_ud(); } @@ -5874,9 +5874,9 @@ pub unsafe fn instr_0F1E_reg(mut r1: i32, mut r2: i32) -> () {} pub unsafe fn instr_0F1E_mem(mut addr: i32, mut r: i32) -> () {} #[no_mangle] pub unsafe fn instr_0F2A(mut source: reg64, mut r: i32) -> () { - c_comment!(("cvtpi2ps xmm, mm/m64")); - c_comment!((("XXX: The non-memory variant causes a transition from x87 FPU to MMX technology operation"))); - c_comment!(("Note: Casts here can fail")); + // cvtpi2ps xmm, mm/m64 + // XXX: The non-memory variant causes a transition from x87 FPU to MMX technology operation + // Note: Casts here can fail let mut result: reg64 = reg64 { f32_0: [source.i32_0[0usize] as f32, source.i32_0[1usize] as f32], }; @@ -5890,9 +5890,9 @@ pub unsafe fn instr_0F2A_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F2A(mut source: reg64, mut r: i32) -> () { - c_comment!(("cvtpi2pd xmm, xmm/m64")); - c_comment!((("XXX: The non-memory variant causes a transition from x87 FPU to MMX technology operation"))); - c_comment!(("These casts can\'t fail")); + // cvtpi2pd xmm, xmm/m64 + // XXX: The non-memory variant causes a transition from x87 FPU to MMX technology operation + // These casts can't fail let mut result: reg128 = reg128 { f64_0: [source.i32_0[0usize] as f64, source.i32_0[1usize] as f64], }; @@ -5908,8 +5908,8 @@ pub unsafe fn instr_660F2A_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F20F2A(mut source: i32, mut r: i32) -> () { - c_comment!(("cvtsi2sd xmm, r32/m32")); - c_comment!(("This cast can\'t fail")); + // cvtsi2sd xmm, r32/m32 + // This cast can't fail let mut result: reg64 = reg64 { f64_0: [source as f64], }; @@ -5923,8 +5923,8 @@ pub unsafe fn instr_F20F2A_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F30F2A(mut source: i32, mut r: i32) -> () { - c_comment!(("cvtsi2ss xmm, r/m32")); - c_comment!(("Note: This cast can fail")); + // cvtsi2ss xmm, r/m32 + // Note: This cast can fail let mut result: f32 = source as f32; write_xmm_f32(r, result); } @@ -5974,7 +5974,7 @@ pub unsafe fn instr_660F2D_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F20F2D(mut source: reg64, mut r: i32) -> () { - c_comment!(("cvtsd2si r32, xmm/m64")); + // cvtsd2si r32, xmm/m64 write_reg32(r, sse_convert_f64_to_i32(source.f64_0[0usize].round())); } #[no_mangle] @@ -6001,7 +6001,7 @@ pub unsafe fn instr_F30F2D_mem(mut addr: i32, mut r: i32) -> () { #[no_mangle] pub unsafe fn instr_0F51(mut source: reg128, mut r: i32) -> () { - c_comment!(("sqrtps xmm, xmm/mem128")); + // sqrtps xmm, xmm/mem128 let mut result: reg128 = reg128 { f32_0: [ source.f32_0[0usize].sqrt(), @@ -6020,7 +6020,7 @@ pub unsafe fn instr_0F51_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F51(mut source: reg128, mut r: i32) -> () { - c_comment!(("sqrtpd xmm, xmm/mem128")); + // sqrtpd xmm, xmm/mem128 let mut result: reg128 = reg128 { f64_0: [source.f64_0[0usize].sqrt(), source.f64_0[1usize].sqrt()], }; @@ -6036,7 +6036,7 @@ pub unsafe fn instr_660F51_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F20F51(mut source: reg64, mut r: i32) -> () { - c_comment!(("sqrtsd xmm, xmm/mem64")); + // sqrtsd xmm, xmm/mem64 let mut result: reg64 = reg64 { f64_0: [source.f64_0[0usize].sqrt()], }; @@ -6052,7 +6052,7 @@ pub unsafe fn instr_F20F51_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F30F51(mut source: f32, mut r: i32) -> () { - c_comment!(("sqrtss xmm, xmm/mem32")); + // sqrtss xmm, xmm/mem32 write_xmm_f32(r, source.sqrt()); } #[no_mangle] @@ -6066,7 +6066,7 @@ pub unsafe fn instr_F30F51_mem(mut addr: i32, mut r: i32) -> () { #[no_mangle] pub unsafe fn instr_0F52(mut source: reg128, mut r: i32) -> () { - c_comment!(("rcpps xmm1, xmm2/m128")); + // rcpps xmm1, xmm2/m128 let mut result: reg128 = reg128 { f32_0: [ 1i32 as f32 / source.f32_0[0usize].sqrt(), @@ -6085,7 +6085,7 @@ pub unsafe fn instr_0F52_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F30F52(mut source: f32, mut r: i32) -> () { - c_comment!(("rsqrtss xmm1, xmm2/m32")); + // rsqrtss xmm1, xmm2/m32 write_xmm_f32(r, 1i32 as f32 / source.sqrt()); } #[no_mangle] @@ -6099,7 +6099,7 @@ pub unsafe fn instr_F30F52_mem(mut addr: i32, mut r: i32) -> () { #[no_mangle] pub unsafe fn instr_0F53(mut source: reg128, mut r: i32) -> () { - c_comment!(("rcpps xmm, xmm/m128")); + // rcpps xmm, xmm/m128 let mut result: reg128 = reg128 { f32_0: [ 1i32 as f32 / source.f32_0[0usize], @@ -6118,7 +6118,7 @@ pub unsafe fn instr_0F53_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F30F53(mut source: f32, mut r: i32) -> () { - c_comment!(("rcpss xmm, xmm/m32")); + // rcpss xmm, xmm/m32 write_xmm_f32(r, 1i32 as f32 / source); } #[no_mangle] @@ -6132,7 +6132,7 @@ pub unsafe fn instr_F30F53_mem(mut addr: i32, mut r: i32) -> () { #[no_mangle] pub unsafe fn instr_0F58(mut source: reg128, mut r: i32) -> () { - c_comment!(("addps xmm, xmm/mem128")); + // addps xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f32_0: [ @@ -6152,7 +6152,7 @@ pub unsafe fn instr_0F58_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F58(mut source: reg128, mut r: i32) -> () { - c_comment!(("addpd xmm, xmm/mem128")); + // addpd xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f64_0: [ @@ -6172,7 +6172,7 @@ pub unsafe fn instr_660F58_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F20F58(mut source: reg64, mut r: i32) -> () { - c_comment!(("addsd xmm, xmm/mem64")); + // addsd xmm, xmm/mem64 let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { f64_0: [source.f64_0[0usize] + destination.f64_0[0usize]], @@ -6189,7 +6189,7 @@ pub unsafe fn instr_F20F58_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F30F58(mut source: f32, mut r: i32) -> () { - c_comment!(("addss xmm, xmm/mem32")); + // addss xmm, xmm/mem32 let mut destination: f32 = read_xmm_f32(r); let mut result: f32 = source + destination; write_xmm_f32(r, result); @@ -6205,7 +6205,7 @@ pub unsafe fn instr_F30F58_mem(mut addr: i32, mut r: i32) -> () { #[no_mangle] pub unsafe fn instr_0F59(mut source: reg128, mut r: i32) -> () { - c_comment!(("mulps xmm, xmm/mem128")); + // mulps xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f32_0: [ @@ -6225,7 +6225,7 @@ pub unsafe fn instr_0F59_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F59(mut source: reg128, mut r: i32) -> () { - c_comment!(("mulpd xmm, xmm/mem128")); + // mulpd xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f64_0: [ @@ -6245,7 +6245,7 @@ pub unsafe fn instr_660F59_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F20F59(mut source: reg64, mut r: i32) -> () { - c_comment!(("mulsd xmm, xmm/mem64")); + // mulsd xmm, xmm/mem64 let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { f64_0: [source.f64_0[0usize] * destination.f64_0[0usize]], @@ -6262,7 +6262,7 @@ pub unsafe fn instr_F20F59_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F30F59(mut source: f32, mut r: i32) -> () { - c_comment!(("mulss xmm, xmm/mem32")); + // mulss xmm, xmm/mem32 let mut destination: f32 = read_xmm_f32(r); let mut result: f32 = source * destination; write_xmm_f32(r, result); @@ -6278,7 +6278,7 @@ pub unsafe fn instr_F30F59_mem(mut addr: i32, mut r: i32) -> () { #[no_mangle] pub unsafe fn instr_0F5A(mut source: reg64, mut r: i32) -> () { - c_comment!(("cvtps2pd xmm1, xmm2/m64")); + // cvtps2pd xmm1, xmm2/m64 let mut result: reg128 = reg128 { f64_0: [source.f32_0[0] as f64, source.f32_0[1] as f64], }; @@ -6292,7 +6292,7 @@ pub unsafe fn instr_0F5A_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F5A(mut source: reg128, mut r: i32) -> () { - c_comment!(("cvtpd2ps xmm1, xmm2/m128")); + // cvtpd2ps xmm1, xmm2/m128 let mut result: reg128 = reg128 { // XXX: These conversions are lossy and should round according to the round control f32_0: [source.f64_0[0] as f32, source.f64_0[1] as f32, 0., 0.], @@ -6309,7 +6309,7 @@ pub unsafe fn instr_660F5A_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F20F5A(mut source: reg64, mut r: i32) -> () { - c_comment!(("cvtsd2ss xmm1, xmm2/m64")); + // cvtsd2ss xmm1, xmm2/m64 // XXX: This conversions is lossy and should round according to the round control write_xmm_f32(r, source.f64_0[0] as f32); } @@ -6323,7 +6323,7 @@ pub unsafe fn instr_F20F5A_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F30F5A(mut source: f32, mut r: i32) -> () { - c_comment!(("cvtss2sd xmm1, xmm2/m32")); + // cvtss2sd xmm1, xmm2/m32 let mut result: reg64 = reg64 { f64_0: [source as f64], }; @@ -6340,7 +6340,7 @@ pub unsafe fn instr_F30F5A_mem(mut addr: i32, mut r: i32) -> () { #[no_mangle] pub unsafe fn instr_0F5B(mut source: reg128, mut r: i32) -> () { - c_comment!(("cvtdq2ps xmm1, xmm2/m128")); + // cvtdq2ps xmm1, xmm2/m128 let mut result: reg128 = reg128 { f32_0: [ // XXX: Precision exception @@ -6360,7 +6360,7 @@ pub unsafe fn instr_0F5B_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F5B(mut source: reg128, mut r: i32) -> () { - c_comment!(("cvtps2dq xmm1, xmm2/m128")); + // cvtps2dq xmm1, xmm2/m128 let mut result = reg128 { i32_0: [ // XXX: Precision exception @@ -6382,7 +6382,7 @@ pub unsafe fn instr_660F5B_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F30F5B(mut source: reg128, mut r: i32) -> () { - c_comment!(("cvttps2dq xmm1, xmm2/m128")); + // cvttps2dq xmm1, xmm2/m128 let mut result = reg128 { i32_0: [ sse_convert_f32_to_i32(source.f32_0[0].trunc()), @@ -6404,7 +6404,7 @@ pub unsafe fn instr_F30F5B_mem(mut addr: i32, mut r: i32) -> () { #[no_mangle] pub unsafe fn instr_0F5C(mut source: reg128, mut r: i32) -> () { - c_comment!(("subps xmm, xmm/mem128")); + // subps xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f32_0: [ @@ -6424,7 +6424,7 @@ pub unsafe fn instr_0F5C_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F5C(mut source: reg128, mut r: i32) -> () { - c_comment!(("subpd xmm, xmm/mem128")); + // subpd xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f64_0: [ @@ -6444,7 +6444,7 @@ pub unsafe fn instr_660F5C_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F20F5C(mut source: reg64, mut r: i32) -> () { - c_comment!(("subsd xmm, xmm/mem64")); + // subsd xmm, xmm/mem64 let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { f64_0: [destination.f64_0[0usize] - source.f64_0[0usize]], @@ -6461,7 +6461,7 @@ pub unsafe fn instr_F20F5C_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F30F5C(mut source: f32, mut r: i32) -> () { - c_comment!(("subss xmm, xmm/mem32")); + // subss xmm, xmm/mem32 let mut destination: f32 = read_xmm_f32(r); let mut result: f32 = destination - source; write_xmm_f32(r, result); @@ -6476,7 +6476,7 @@ pub unsafe fn instr_F30F5C_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F5D(mut source: reg128, mut r: i32) -> () { - c_comment!(("minps xmm, xmm/mem128")); + // minps xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f32_0: [ @@ -6508,7 +6508,7 @@ pub unsafe fn instr_0F5D_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F5D(mut source: reg128, mut r: i32) -> () { - c_comment!(("minpd xmm, xmm/mem128")); + // minpd xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f64_0: [ @@ -6528,7 +6528,7 @@ pub unsafe fn instr_660F5D_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F20F5D(mut source: reg64, mut r: i32) -> () { - c_comment!(("minsd xmm, xmm/mem64")); + // minsd xmm, xmm/mem64 let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { f64_0: [sse_min(destination.f64_0[0usize], source.f64_0[0usize])], @@ -6545,7 +6545,7 @@ pub unsafe fn instr_F20F5D_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F30F5D(mut source: f32, mut r: i32) -> () { - c_comment!(("minss xmm, xmm/mem32")); + // minss xmm, xmm/mem32 let mut destination: f32 = read_xmm_f32(r); let mut result: f32 = sse_min(destination as f64, source as f64) as f32; write_xmm_f32(r, result); @@ -6560,7 +6560,7 @@ pub unsafe fn instr_F30F5D_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F5E(mut source: reg128, mut r: i32) -> () { - c_comment!(("divps xmm, xmm/mem128")); + // divps xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f32_0: [ @@ -6580,7 +6580,7 @@ pub unsafe fn instr_0F5E_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F5E(mut source: reg128, mut r: i32) -> () { - c_comment!(("divpd xmm, xmm/mem128")); + // divpd xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f64_0: [ @@ -6600,7 +6600,7 @@ pub unsafe fn instr_660F5E_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F20F5E(mut source: reg64, mut r: i32) -> () { - c_comment!(("divsd xmm, xmm/mem64")); + // divsd xmm, xmm/mem64 let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { f64_0: [destination.f64_0[0usize] / source.f64_0[0usize]], @@ -6617,7 +6617,7 @@ pub unsafe fn instr_F20F5E_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F30F5E(mut source: f32, mut r: i32) -> () { - c_comment!(("divss xmm, xmm/mem32")); + // divss xmm, xmm/mem32 let mut destination: f32 = read_xmm_f32(r); let mut result: f32 = destination / source; write_xmm_f32(r, result); @@ -6632,7 +6632,7 @@ pub unsafe fn instr_F30F5E_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F5F(mut source: reg128, mut r: i32) -> () { - c_comment!(("maxps xmm, xmm/mem128")); + // maxps xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f32_0: [ @@ -6664,7 +6664,7 @@ pub unsafe fn instr_0F5F_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_660F5F(mut source: reg128, mut r: i32) -> () { - c_comment!(("maxpd xmm, xmm/mem128")); + // maxpd xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f64_0: [ @@ -6684,7 +6684,7 @@ pub unsafe fn instr_660F5F_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F20F5F(mut source: reg64, mut r: i32) -> () { - c_comment!(("maxsd xmm, xmm/mem64")); + // maxsd xmm, xmm/mem64 let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { f64_0: [sse_max(destination.f64_0[0usize], source.f64_0[0usize])], @@ -6701,7 +6701,7 @@ pub unsafe fn instr_F20F5F_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_F30F5F(mut source: f32, mut r: i32) -> () { - c_comment!(("maxss xmm, xmm/mem32")); + // maxss xmm, xmm/mem32 let mut destination: f32 = read_xmm_f32(r); let mut result: f32 = sse_max(destination as f64, source as f64) as f32; write_xmm_f32(r, result); @@ -6716,7 +6716,7 @@ pub unsafe fn instr_F30F5F_mem(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0FC2(mut source: reg128, mut r: i32, mut imm8: i32) -> () { - c_comment!(("cmpps xmm, xmm/m128")); + // cmpps xmm, xmm/m128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i32_0: [ @@ -6778,7 +6778,7 @@ pub unsafe fn instr_0FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { } #[no_mangle] pub unsafe fn instr_660FC2(mut source: reg128, mut r: i32, mut imm8: i32) -> () { - c_comment!(("cmppd xmm, xmm/m128")); + // cmppd xmm, xmm/m128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i64_0: [ @@ -6808,7 +6808,7 @@ pub unsafe fn instr_660FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { } #[no_mangle] pub unsafe fn instr_F20FC2(mut source: reg64, mut r: i32, mut imm8: i32) -> () { - c_comment!(("cmpsd xmm, xmm/m64")); + // cmpsd xmm, xmm/m64 let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { i64_0: [(if 0 @@ -6832,7 +6832,7 @@ pub unsafe fn instr_F20FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { } #[no_mangle] pub unsafe fn instr_F30FC2(mut source: f32, mut r: i32, mut imm8: i32) -> () { - c_comment!(("cmpss xmm, xmm/m32")); + // cmpss xmm, xmm/m32 let mut destination: f32 = read_xmm_f32(r); let mut result: i32 = if 0 != sse_comparison(imm8, destination as f64, source as f64) as i32 { -1i32 diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index 5fd52c04..7e8503e9 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -26,7 +26,7 @@ pub unsafe fn getcf() -> bool { #[no_mangle] pub unsafe fn getpf() -> bool { if 0 != *flags_changed & FLAG_PARITY { - c_comment!(("inverted lookup table")); + // inverted lookup table return 0 != 38505i32 << 2i32 >> ((*last_result ^ *last_result >> 4i32) & 15i32) & FLAG_PARITY; } @@ -107,7 +107,7 @@ pub unsafe fn test_nle() -> bool { return !test_le(); } #[no_mangle] pub unsafe fn jmp_rel16(mut rel16: i32) -> () { let mut cs_offset: i32 = get_seg_cs(); - c_comment!(("limit ip to 16 bit")); + // limit ip to 16 bit *instruction_pointer = cs_offset + (*instruction_pointer - cs_offset + rel16 & 65535i32); } #[no_mangle] @@ -307,8 +307,8 @@ pub unsafe fn pop32s_ss32() -> Result { #[no_mangle] pub unsafe fn pusha16() -> () { let mut temp: u16 = *reg16.offset(SP as isize); - c_comment!(("make sure we don\'t get a pagefault after having")); - c_comment!(("pushed several registers already")); + // make sure we don't get a pagefault after having + // pushed several registers already return_on_pagefault!(writable_or_pagefault(get_stack_pointer(-16i32), 16i32)); push16(*reg16.offset(AX as isize) as i32).unwrap(); push16(*reg16.offset(CX as isize) as i32).unwrap(); @@ -371,9 +371,9 @@ pub unsafe fn fxsave(mut addr: u32) -> () { ); i += 1 } - c_comment!(("If the OSFXSR bit in control register CR4 is not set, the FXSAVE")); - c_comment!(("instruction may not save these registers. This behavior is")); - c_comment!(("implementation dependent.")); + // If the OSFXSR bit in control register CR4 is not set, the FXSAVE + // instruction may not save these registers. This behavior is + // implementation dependent. let mut i_0: i32 = 0i32; while i_0 < 8i32 { safe_write128( diff --git a/src/rust/cpu2/sse_instr.rs b/src/rust/cpu2/sse_instr.rs index f589d0e9..a07cf84d 100644 --- a/src/rust/cpu2/sse_instr.rs +++ b/src/rust/cpu2/sse_instr.rs @@ -11,36 +11,36 @@ use cpu2::cpu::*; #[no_mangle] pub unsafe fn mov_r_m64(mut addr: i32, mut r: i32) -> () { - c_comment!(("mov* m64, mm")); + // mov* m64, mm let mut data: reg64 = read_mmx64s(r); return_on_pagefault!(safe_write64(addr, data.u64_0[0usize] as i64)); } #[no_mangle] pub unsafe fn movl_r128_m64(mut addr: i32, mut r: i32) -> () { - c_comment!(("mov* m64, xmm")); + // mov* m64, xmm let mut data: reg64 = read_xmm64s(r); return_on_pagefault!(safe_write64(addr, data.u64_0[0usize] as i64)); } #[no_mangle] pub unsafe fn mov_r_r128(mut r1: i32, mut r2: i32) -> () { - c_comment!(("mov* xmm, xmm")); + // mov* xmm, xmm let mut data: reg128 = read_xmm128s(r2); write_xmm_reg128(r1, data); } #[no_mangle] pub unsafe fn mov_r_m128(mut addr: i32, mut r: i32) -> () { - c_comment!(("mov* m128, xmm")); + // mov* m128, xmm let mut data: reg128 = read_xmm128s(r); return_on_pagefault!(safe_write128(addr, data)); } #[no_mangle] pub unsafe fn mov_rm_r128(mut source: reg128, mut r: i32) -> () { - c_comment!(("mov* xmm, xmm/m128")); + // mov* xmm, xmm/m128 write_xmm_reg128(r, source); } #[no_mangle] pub unsafe fn movh_m64_r128(mut addr: i32, mut r: i32) -> () { - c_comment!(("movhp* xmm, m64")); + // movhp* xmm, m64 let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); let mut orig: reg128 = read_xmm128s(r); write_xmm128( @@ -53,14 +53,14 @@ pub unsafe fn movh_m64_r128(mut addr: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn movh_r128_m64(mut addr: i32, mut r: i32) -> () { - c_comment!(("movhp* m64, xmm")); + // movhp* m64, xmm let mut data: reg128 = read_xmm128s(r); return_on_pagefault!(safe_write64(addr, data.u64_0[1usize] as i64)); } #[no_mangle] pub unsafe fn pand_r128(mut source: reg128, mut r: i32) -> () { - c_comment!(("pand xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pand xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], @@ -71,8 +71,8 @@ pub unsafe fn pand_r128(mut source: reg128, mut r: i32) -> () { } #[no_mangle] pub unsafe fn pandn_r128(mut source: reg128, mut r: i32) -> () { - c_comment!(("pandn xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pandn xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], @@ -83,8 +83,8 @@ pub unsafe fn pandn_r128(mut source: reg128, mut r: i32) -> () { } #[no_mangle] pub unsafe fn pxor_r128(mut source: reg128, mut r: i32) -> () { - c_comment!(("pxor xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // pxor xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], @@ -95,8 +95,8 @@ pub unsafe fn pxor_r128(mut source: reg128, mut r: i32) -> () { } #[no_mangle] pub unsafe fn por_r128(mut source: reg128, mut r: i32) -> () { - c_comment!(("por xmm, xmm/m128")); - c_comment!(("XXX: Aligned access or #gp")); + // por xmm, xmm/m128 + // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], @@ -107,7 +107,7 @@ pub unsafe fn por_r128(mut source: reg128, mut r: i32) -> () { } #[no_mangle] pub unsafe fn psrlw_r64(mut r: i32, mut shift: u32) -> () { - c_comment!(("psrlw mm, {shift}")); + // psrlw mm, {shift} let mut destination: reg64 = read_mmx64s(r); let mut dword0: i32 = 0i32; let mut dword1: i32 = 0i32; @@ -121,7 +121,7 @@ pub unsafe fn psrlw_r64(mut r: i32, mut shift: u32) -> () { } #[no_mangle] pub unsafe fn psraw_r64(mut r: i32, mut shift: u32) -> () { - c_comment!(("psraw mm, {shift}")); + // psraw mm, {shift} let mut destination: reg64 = read_mmx64s(r); let mut shift_clamped: i32 = (if shift > 15i32 as u32 { 16i32 as u32 @@ -137,7 +137,7 @@ pub unsafe fn psraw_r64(mut r: i32, mut shift: u32) -> () { } #[no_mangle] pub unsafe fn psllw_r64(mut r: i32, mut shift: u32) -> () { - c_comment!(("psllw mm, {shift}")); + // psllw mm, {shift} let mut destination: reg64 = read_mmx64s(r); let mut dword0: i32 = 0i32; let mut dword1: i32 = 0i32; @@ -151,7 +151,7 @@ pub unsafe fn psllw_r64(mut r: i32, mut shift: u32) -> () { } #[no_mangle] pub unsafe fn psrld_r64(mut r: i32, mut shift: u32) -> () { - c_comment!(("psrld mm, {shift}")); + // psrld mm, {shift} let mut destination: reg64 = read_mmx64s(r); let mut dword0: i32 = 0i32; let mut dword1: i32 = 0i32; @@ -163,7 +163,7 @@ pub unsafe fn psrld_r64(mut r: i32, mut shift: u32) -> () { } #[no_mangle] pub unsafe fn psrad_r64(mut r: i32, mut shift: u32) -> () { - c_comment!(("psrad mm, {shift}")); + // psrad mm, {shift} let mut destination: reg64 = read_mmx64s(r); let mut shift_clamped: i32 = (if shift > 31i32 as u32 { 31i32 as u32 @@ -177,7 +177,7 @@ pub unsafe fn psrad_r64(mut r: i32, mut shift: u32) -> () { } #[no_mangle] pub unsafe fn pslld_r64(mut r: i32, mut shift: u32) -> () { - c_comment!(("pslld mm, {shift}")); + // pslld mm, {shift} let mut destination: reg64 = read_mmx64s(r); let mut dword0: i32 = 0i32; let mut dword1: i32 = 0i32; @@ -189,7 +189,7 @@ pub unsafe fn pslld_r64(mut r: i32, mut shift: u32) -> () { } #[no_mangle] pub unsafe fn psrlq_r64(mut r: i32, mut shift: u32) -> () { - c_comment!(("psrlq mm, {shift}")); + // psrlq mm, {shift} if shift == 0i32 as u32 { return; } @@ -207,7 +207,7 @@ pub unsafe fn psrlq_r64(mut r: i32, mut shift: u32) -> () { } #[no_mangle] pub unsafe fn psllq_r64(mut r: i32, mut shift: u32) -> () { - c_comment!(("psllq mm, {shift}")); + // psllq mm, {shift} let mut destination: reg64 = read_mmx64s(r); if shift == 0i32 as u32 { return; @@ -225,7 +225,7 @@ pub unsafe fn psllq_r64(mut r: i32, mut shift: u32) -> () { } #[no_mangle] pub unsafe fn psrlw_r128(mut r: i32, mut shift: u32) -> () { - c_comment!(("psrlw xmm, {shift}")); + // psrlw xmm, {shift} let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = 0i32; let mut dword1: i32 = 0i32; @@ -245,7 +245,7 @@ pub unsafe fn psrlw_r128(mut r: i32, mut shift: u32) -> () { } #[no_mangle] pub unsafe fn psraw_r128(mut r: i32, mut shift: u32) -> () { - c_comment!(("psraw xmm, {shift}")); + // psraw xmm, {shift} let mut destination: reg128 = read_xmm128s(r); let mut shift_clamped: i32 = (if shift > 15i32 as u32 { 16i32 as u32 @@ -265,7 +265,7 @@ pub unsafe fn psraw_r128(mut r: i32, mut shift: u32) -> () { } #[no_mangle] pub unsafe fn psllw_r128(mut r: i32, mut shift: u32) -> () { - c_comment!(("psllw xmm, {shift}")); + // psllw xmm, {shift} let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = 0i32; let mut dword1: i32 = 0i32; @@ -285,7 +285,7 @@ pub unsafe fn psllw_r128(mut r: i32, mut shift: u32) -> () { } #[no_mangle] pub unsafe fn psrld_r128(mut r: i32, mut shift: u32) -> () { - c_comment!(("psrld xmm, {shift}")); + // psrld xmm, {shift} let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = 0i32; let mut dword1: i32 = 0i32; @@ -301,7 +301,7 @@ pub unsafe fn psrld_r128(mut r: i32, mut shift: u32) -> () { } #[no_mangle] pub unsafe fn psrad_r128(mut r: i32, mut shift: u32) -> () { - c_comment!(("psrad xmm, {shift}")); + // psrad xmm, {shift} let mut destination: reg128 = read_xmm128s(r); let mut shift_clamped: i32 = (if shift > 31i32 as u32 { 31i32 as u32 @@ -317,7 +317,7 @@ pub unsafe fn psrad_r128(mut r: i32, mut shift: u32) -> () { } #[no_mangle] pub unsafe fn pslld_r128(mut r: i32, mut shift: u32) -> () { - c_comment!(("pslld xmm, {shift}")); + // pslld xmm, {shift} let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = 0i32; let mut dword1: i32 = 0i32; @@ -333,7 +333,7 @@ pub unsafe fn pslld_r128(mut r: i32, mut shift: u32) -> () { } #[no_mangle] pub unsafe fn psrlq_r128(mut r: i32, mut shift: u32) -> () { - c_comment!(("psrlq xmm, {shift}")); + // psrlq xmm, {shift} if shift == 0i32 as u32 { return; } @@ -352,7 +352,7 @@ pub unsafe fn psrlq_r128(mut r: i32, mut shift: u32) -> () { } #[no_mangle] pub unsafe fn psllq_r128(mut r: i32, mut shift: u32) -> () { - c_comment!(("psllq xmm, {shift}")); + // psllq xmm, {shift} let mut destination: reg128 = read_xmm128s(r); if shift == 0i32 as u32 { return; @@ -371,7 +371,7 @@ pub unsafe fn psllq_r128(mut r: i32, mut shift: u32) -> () { } #[no_mangle] pub unsafe fn sse_comparison(mut op: i32, mut x: f64, mut y: f64) -> bool { - c_comment!(("TODO: Signaling")); + // TODO: Signaling match op & 7i32 { 0 => return x == y, 1 => return x < y, @@ -389,35 +389,35 @@ pub unsafe fn sse_comparison(mut op: i32, mut x: f64, mut y: f64) -> bool { } #[no_mangle] pub unsafe fn sse_min(mut x: f64, mut y: f64) -> f64 { - c_comment!(("if both x and y are 0 or x is nan, y is returned")); + // if both x and y are 0 or x is nan, y is returned return if x < y { x } else { y }; } #[no_mangle] pub unsafe fn sse_max(mut x: f64, mut y: f64) -> f64 { - c_comment!(("if both x and y are 0 or x is nan, y is returned")); + // if both x and y are 0 or x is nan, y is returned return if x > y { x } else { y }; } #[no_mangle] pub unsafe fn sse_convert_f32_to_i32(mut x: f32) -> i32 { - c_comment!(("TODO: Rounding modes")); + // TODO: Rounding modes if x >= -2147483648.0 && x < 2147483648.0 { return x as i64 as i32; } else { - c_comment!(("TODO: Signal")); + // TODO: Signal return 2147483648u32.wrapping_neg() as i32; }; } #[no_mangle] pub unsafe fn sse_convert_f64_to_i32(mut x: f64) -> i32 { - c_comment!(("TODO: Rounding modes")); + // TODO: Rounding modes if x >= -2147483648.0 as f64 && x < 2147483648.0 as f64 { return x as i64 as i32; } else { - c_comment!(("TODO: Signal")); + // TODO: Signal return 2147483648u32.wrapping_neg() as i32; }; } diff --git a/src/rust/cpu2/string.rs b/src/rust/cpu2/string.rs index 7acc7469..cfef9b80 100644 --- a/src/rust/cpu2/string.rs +++ b/src/rust/cpu2/string.rs @@ -43,7 +43,7 @@ pub unsafe fn string_get_cycle_count(mut size: i32, mut address: i32) -> i32 { address = 4096i32 - address - size } dbg_assert!(address & size - 1i32 == 0i32); - c_comment!(("1 -> 0; 2 -> 1; 4 -> 2")); + // 1 -> 0; 2 -> 1; 4 -> 2 let mut shift: i32 = size >> 1i32; return 4096i32 - (address & 4095i32) >> shift; } From 652c4f4322c5d591778da29e15e347bfb89dbfe7 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Aug 2018 21:05:32 -0500 Subject: [PATCH 1252/2137] c2rust cleanup: Remove old makefile --- src/rust/cpu2/Makefile | 129 ----------------------------------------- 1 file changed, 129 deletions(-) delete mode 100644 src/rust/cpu2/Makefile diff --git a/src/rust/cpu2/Makefile b/src/rust/cpu2/Makefile deleted file mode 100644 index 93aa5b7f..00000000 --- a/src/rust/cpu2/Makefile +++ /dev/null @@ -1,129 +0,0 @@ -ALL:= arith.rs cpu.rs fpu.rs instructions_0f.rs instructions.rs \ - memory.rs misc_instr.rs modrm.rs shared.rs sse_instr.rs string.rs \ - global_pointers.rs profiler.rs - -all: $(ALL) - -profiler.rs: profiler/profiler.rs - cp profiler/profiler.rs profiler.rs - -%.rs: - #citrus --api=rust $< -I ../../native/ ../../native/profiler/ > $@.tmp - #cat import-prefix $@.tmp | grep -v cpu2::$(basename $@):: > $@ - #rm $@.tmp - #sed -i 's/assert(/assert!(/' $@ - #sed -i 's/dbg_assert(/dbg_assert!(/' $@ - #sed -i 's/dbg_log(/dbg_log!(/' $@ - #sed -i 's/%x/{:x}/g' $@ - #sed -i 's/%d/{}/g' $@ - #sed -i '/:.*= ()/d' $@ - #sed -i 's/!= 0 != 0//' $@ - #sed -i 's/fn(,/fn(i32,/' $@ - #sed -i 's/is_32 != 0/is_32/' $@ - #sed -i 's/SAFE_READ_WRITE8/SAFE_READ_WRITE8!/' $@ - #sed -i 's/SAFE_READ_WRITE16/SAFE_READ_WRITE16!/' $@ - #sed -i 's/SAFE_READ_WRITE32/SAFE_READ_WRITE32!/' $@ - #sed -i 's/pub fn SAFE_READ_WRITE8!();//' $@ - #sed -i 's/pub fn SAFE_READ_WRITE16!();//' $@ - #sed -i 's/pub fn SAFE_READ_WRITE32!();//' $@ - - cp ~/DL/c2rust/scripts/v86/src/native/$@ $@ - #cat import-prefix $@.tmp | grep -v cpu2::$(basename $@):: > $@ - #cat $@.tmp | grep -v cpu2::$(basename $@):: > $@ - -rm $@.tmp - - #sed -i 's/assert(/assert_c!(/' $@ - ##sed -i 's/dbg_assert(/dbg_assert!(/' $@ - #sed -i 's/dbg_log(/dbg_log_c!(/' $@ - ##sed -i 's/pub unsafe extern "C" fn assert_c!() -> () { }//' $@ - ##sed -i 's/pub unsafe extern "C" fn dbg_assert_c!() -> () { }//' $@ - ##sed -i 's/pub unsafe extern "C" fn dbg_log_c!() -> () { }//' $@ - - #sed -i 's/fn assert_c!() -> ();//' $@ - #sed -i 's/fn dbg_assert_c!() -> ();//' $@ - #sed -i 's/fn dbg_log_c!() -> ();//' $@ - - #sed -i 's/fn assert_c!/fn assert_c/' $@ - #sed -i 's/fn dbg_assert_c!/fn dbg_assert_c/' $@ - #sed -i 's/fn dbg_log_c!/fn dbg_log_c/' $@ - - sed -i 's/libc::c_char/i8/g' $@ - sed -i 's/libc::c_double/f64/g' $@ - sed -i 's/libc::c_float/f32/g' $@ - sed -i 's/libc::c_int/i32/g' $@ - sed -i 's/libc::c_longlong/i64/g' $@ - sed -i 's/libc::c_long/i64/g' $@ - sed -i 's/libc::c_schar/i8/g' $@ - sed -i 's/libc::c_short/i16/g' $@ - sed -i 's/libc::c_uchar/u8/g' $@ - sed -i 's/libc::c_uint/u32/g' $@ - sed -i 's/libc::c_ulonglong/u64/g' $@ - sed -i 's/libc::c_ulong/u64/g' $@ - sed -i 's/libc::c_ushort/u16/g' $@ - - sed -i 's/pub type double_t = f64;//' $@ - sed -i 's/pub type float_t = f32;//' $@ - sed -i 's/pub type uint64_t = u64;//' $@ - sed -i 's/pub type int64_t = i64;//' $@ - sed -i 's/pub type int32_t = i32;//' $@ - sed -i 's/pub type uint32_t = u32;//' $@ - sed -i 's/pub type int16_t = i16;//' $@ - sed -i 's/pub type uint16_t = u16;//' $@ - sed -i 's/pub type int8_t = i8;//' $@ - sed -i 's/pub type uint8_t = u8;//' $@ - - sed -i 's/double_t/f64/g' $@ - sed -i 's/float_t/f32/g' $@ - sed -i 's/uint64_t/u64/g' $@ - sed -i 's/int64_t/i64/g' $@ - sed -i 's/uint32_t/u32/g' $@ - sed -i 's/int32_t/i32/g' $@ - sed -i 's/uint16_t/u16/g' $@ - sed -i 's/int16_t/i16/g' $@ - sed -i 's/uint8_t/u8/g' $@ - sed -i 's/int8_t/i8/g' $@ - - sed -i 's/SAFE_READ_WRITE8/SAFE_READ_WRITE8!/' $@ - sed -i 's/SAFE_READ_WRITE16/SAFE_READ_WRITE16!/' $@ - sed -i 's/SAFE_READ_WRITE32/SAFE_READ_WRITE32!/' $@ - sed -i 's/fn SAFE_READ_WRITE8!() -> ();//' $@ - sed -i 's/fn SAFE_READ_WRITE16!() -> ();//' $@ - sed -i 's/fn SAFE_READ_WRITE32!() -> ();//' $@ - - sed -i 's/pub type _IO_FILE;//' $@ - sed -i 's/pub type FILE = _IO_FILE;//' $@ - sed -i ':a;N;$$!ba;s/#\[no_mangle]\n static stdin: \*mut FILE;//' $@ - sed -i ':a;N;$$!ba;s/#\[no_mangle]\n static stdout: \*mut FILE;//' $@ - sed -i ':a;N;$$!ba;s/#\[no_mangle]\n static stderr: \*mut FILE;//' $@ - - sed -i ':a;N;$$!ba;s/#\[no_mangle]\n static mut ___: i32;//' $@ - - sed -i 's/SAFE_READ_WRITE8!(/SAFE_READ_WRITE8!(___, /' $@ - sed -i 's/SAFE_READ_WRITE16!(/SAFE_READ_WRITE16!(___, /' $@ - sed -i 's/SAFE_READ_WRITE32!(/SAFE_READ_WRITE32!(___, /' $@ - - sed -i 's/extern crate libc;//' $@ - - sed -i 's/.as_mut_ptr()//' $@ - sed -i ':a;N;$$!ba;s/\*::std::mem::transmute::<&\[u8; [0-9]\+],[ \n]\+&mut \[i8; [0-9]\+]>//g' $@ - sed -i 's/\\x00//' $@ - sed -i 's/b"/"/' $@ - - sed -i 's/dbg_log[0-9]\?((/dbg_log_c!((/' $@ - - sed -i ':a;N;$$!ba;s/#\[no_mangle]\n fn dbg_assert[^\n]*//' $@ - sed -i ':a;N;$$!ba;s/#\[no_mangle]\n fn assert[^\n]*//' $@ - - sed -i 's/dbg_assert_message(/dbg_assert!(/' $@ - sed -i 's/dbg_assert(/dbg_assert!(/' $@ - sed -i 's/assert(/dbg_assert!(/' $@ - - sed -i 's/ c_comment(/ c_comment!(/' $@ - - # This works, but requires manual cleanup afterwards - #sed -i 's/\([0-9]\)[i]32/\1/' $@ - - -clean: - -rm $(ALL) - -rm profiler/profiler.rs From 3a00eedf218a7ed83f76c0d9e29ba6062ee1d75b Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Aug 2018 21:07:26 -0500 Subject: [PATCH 1253/2137] c2rust cleanup: Re-enable some warnings --- src/rust/cpu2/arith.rs | 9 +--- src/rust/cpu2/cpu.rs | 17 ++---- src/rust/cpu2/fpu.rs | 9 +--- src/rust/cpu2/global_pointers.rs | 9 +--- src/rust/cpu2/instructions.rs | 9 +--- src/rust/cpu2/instructions_0f.rs | 2 - src/rust/cpu2/memory.rs | 9 +--- src/rust/cpu2/misc_instr.rs | 9 +--- src/rust/cpu2/modrm.rs | 9 +--- src/rust/cpu2/profiler.rs | 91 +++++++++++++++----------------- src/rust/cpu2/sse_instr.rs | 9 +--- src/rust/cpu2/string.rs | 9 +--- 12 files changed, 56 insertions(+), 135 deletions(-) diff --git a/src/rust/cpu2/arith.rs b/src/rust/cpu2/arith.rs index ac5e7be2..014f476a 100644 --- a/src/rust/cpu2/arith.rs +++ b/src/rust/cpu2/arith.rs @@ -1,11 +1,4 @@ -#![allow( - dead_code, - mutable_transmutes, - non_camel_case_types, - non_snake_case, - non_upper_case_globals, - unused_mut -)] +#![allow(mutable_transmutes, unused_mut)] use cpu2::cpu::*; use cpu2::global_pointers::*; diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 6c1ce5c0..fe2c659d 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1,11 +1,4 @@ -#![allow( - dead_code, - mutable_transmutes, - non_camel_case_types, - non_snake_case, - non_upper_case_globals, - unused_mut -)] +#![allow(mutable_transmutes, non_upper_case_globals, unused_mut)] extern "C" { #[no_mangle] @@ -51,7 +44,7 @@ pub union reg64 { pub f32_0: [f32; 2], pub f64_0: [f64; 1], } -pub type cached_state_flags = u8; +pub type CachedStateFlags = u8; #[derive(Copy, Clone)] #[repr(C)] @@ -771,7 +764,7 @@ pub unsafe fn cycle_internal() -> () { let mut initial_state: u16 = 0; *previous_ip = *instruction_pointer; let mut phys_addr: u32 = return_on_pagefault!(get_phys_eip()) as u32; - let mut state_flags: cached_state_flags = pack_current_state_flags(); + let mut state_flags: CachedStateFlags = pack_current_state_flags(); let mut entry: u32 = ::c_api::jit_find_cache_entry(phys_addr, state_flags as u32); if 0 != entry { profiler_stat_increment(S_RUN_FROM_CACHE); @@ -847,11 +840,11 @@ unsafe fn jit_run_interpreted(mut phys_addr: i32) -> () { } #[no_mangle] -pub unsafe fn pack_current_state_flags() -> cached_state_flags { +pub unsafe fn pack_current_state_flags() -> CachedStateFlags { return ((*is_32 as i32) << 0i32 | (*stack_size_32 as i32) << 1i32 | ((*cpl as i32 == 3i32) as i32) << 2i32 - | (has_flat_segmentation() as i32) << 3i32) as cached_state_flags; + | (has_flat_segmentation() as i32) << 3i32) as CachedStateFlags; } pub unsafe fn has_flat_segmentation() -> bool { diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 9a5c8da8..8e5f5b0d 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -1,11 +1,4 @@ -#![allow( - dead_code, - mutable_transmutes, - non_camel_case_types, - non_snake_case, - non_upper_case_globals, - unused_mut -)] +#![allow(mutable_transmutes, unused_mut)] use cpu2::cpu::*; use cpu2::global_pointers::*; diff --git a/src/rust/cpu2/global_pointers.rs b/src/rust/cpu2/global_pointers.rs index 7d5261b9..ec33a7d3 100644 --- a/src/rust/cpu2/global_pointers.rs +++ b/src/rust/cpu2/global_pointers.rs @@ -1,11 +1,4 @@ -#![allow( - dead_code, - mutable_transmutes, - non_camel_case_types, - non_snake_case, - non_upper_case_globals, - unused_mut -)] +#![allow(mutable_transmutes, non_upper_case_globals, unused_mut)] use cpu2::cpu::{reg128, reg64}; diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index 92218d31..82c76a5f 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -1,11 +1,4 @@ -#![allow( - dead_code, - mutable_transmutes, - non_camel_case_types, - non_snake_case, - non_upper_case_globals, - unused_mut -)] +#![allow(mutable_transmutes, non_snake_case, unused_mut)] extern "C" { #[no_mangle] diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 0818efd2..5fb08fac 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -1,7 +1,5 @@ #![allow( - dead_code, mutable_transmutes, - non_camel_case_types, non_snake_case, non_upper_case_globals, unused_mut diff --git a/src/rust/cpu2/memory.rs b/src/rust/cpu2/memory.rs index 1012bc8a..bdc30d61 100644 --- a/src/rust/cpu2/memory.rs +++ b/src/rust/cpu2/memory.rs @@ -1,11 +1,4 @@ -#![allow( - dead_code, - mutable_transmutes, - non_camel_case_types, - non_snake_case, - non_upper_case_globals, - unused_mut -)] +#![allow(mutable_transmutes, unused_mut)] extern "C" { #[no_mangle] diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index 7e8503e9..632695f7 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -1,11 +1,4 @@ -#![allow( - dead_code, - mutable_transmutes, - non_camel_case_types, - non_snake_case, - non_upper_case_globals, - unused_mut -)] +#![allow(mutable_transmutes, unused_mut)] use cpu2::cpu::*; use cpu2::fpu::{fpu_load_m80, fpu_load_status_word, fpu_set_status_word, fpu_store_m80}; diff --git a/src/rust/cpu2/modrm.rs b/src/rust/cpu2/modrm.rs index f9b5188e..97043c87 100644 --- a/src/rust/cpu2/modrm.rs +++ b/src/rust/cpu2/modrm.rs @@ -1,11 +1,4 @@ -#![allow( - dead_code, - mutable_transmutes, - non_camel_case_types, - non_snake_case, - non_upper_case_globals, - unused_mut -)] +#![allow(mutable_transmutes, unused_mut)] use cpu2::cpu::*; use cpu2::global_pointers::*; diff --git a/src/rust/cpu2/profiler.rs b/src/rust/cpu2/profiler.rs index 9a80857e..f798a56a 100644 --- a/src/rust/cpu2/profiler.rs +++ b/src/rust/cpu2/profiler.rs @@ -1,58 +1,51 @@ -#![allow( - dead_code, - mutable_transmutes, - non_camel_case_types, - non_snake_case, - non_upper_case_globals, - unused_mut -)] +#![allow(mutable_transmutes, unused_mut)] -pub const S_SAFE_WRITE32_SLOW_NOT_VALID: stat_name = 22; -pub const S_SAFE_WRITE32_SLOW_NOT_USER: stat_name = 23; +pub const S_SAFE_WRITE32_SLOW_NOT_VALID: StatName = 22; +pub const S_SAFE_WRITE32_SLOW_NOT_USER: StatName = 23; -pub const S_CYCLE_INTERNAL: stat_name = 29; -pub const S_COMPILE: stat_name = 0; +pub const S_CYCLE_INTERNAL: StatName = 29; +pub const S_COMPILE: StatName = 0; -pub const S_RUN_INTERPRETED_PENDING: stat_name = 8; -pub const S_TRIGGER_CPU_EXCEPTION: stat_name = 14; -pub const S_TLB_GLOBAL_FULL: stat_name = 36; -pub const S_SAFE_READ32_FAST: stat_name = 15; -pub const S_SAFE_READ32_SLOW_PAGE_CROSSED: stat_name = 16; -pub const S_INVALIDATE_PAGE: stat_name = 30; -pub const S_SAFE_READ32_SLOW_NOT_VALID: stat_name = 17; -pub const S_COMPILE_SUCCESS: stat_name = 1; -pub const S_COMPILE_ENTRY_POINT: stat_name = 5; -pub const S_SAFE_WRITE32_FAST: stat_name = 20; -pub const S_DO_RUN: stat_name = 27; -pub const S_SAFE_WRITE32_SLOW_HAS_CODE: stat_name = 26; -pub const S_CLEAR_TLB: stat_name = 33; -pub const S_RUN_FROM_CACHE_STEPS: stat_name = 13; -pub const S_CACHE_MISMATCH: stat_name = 6; -pub const S_RUN_INTERPRETED_DIFFERENT_STATE: stat_name = 10; -pub const S_RUN_INTERPRETED_NEAR_END_OF_PAGE: stat_name = 9; -pub const S_COMPILE_WITH_LOOP_SAFETY: stat_name = 3; -pub const S_COMPILE_CUT_OFF_AT_END_OF_PAGE: stat_name = 2; +pub const S_RUN_INTERPRETED_PENDING: StatName = 8; +pub const S_TRIGGER_CPU_EXCEPTION: StatName = 14; +pub const S_TLB_GLOBAL_FULL: StatName = 36; +pub const S_SAFE_READ32_FAST: StatName = 15; +pub const S_SAFE_READ32_SLOW_PAGE_CROSSED: StatName = 16; +pub const S_INVALIDATE_PAGE: StatName = 30; +pub const S_SAFE_READ32_SLOW_NOT_VALID: StatName = 17; +pub const S_COMPILE_SUCCESS: StatName = 1; +pub const S_COMPILE_ENTRY_POINT: StatName = 5; +pub const S_SAFE_WRITE32_FAST: StatName = 20; +pub const S_DO_RUN: StatName = 27; +pub const S_SAFE_WRITE32_SLOW_HAS_CODE: StatName = 26; +pub const S_CLEAR_TLB: StatName = 33; +pub const S_RUN_FROM_CACHE_STEPS: StatName = 13; +pub const S_CACHE_MISMATCH: StatName = 6; +pub const S_RUN_INTERPRETED_DIFFERENT_STATE: StatName = 10; +pub const S_RUN_INTERPRETED_NEAR_END_OF_PAGE: StatName = 9; +pub const S_COMPILE_WITH_LOOP_SAFETY: StatName = 3; +pub const S_COMPILE_CUT_OFF_AT_END_OF_PAGE: StatName = 2; #[derive(Copy, Clone)] #[repr(C)] pub struct profiler_stat { pub count: i32, } -pub const S_COMPILE_BASIC_BLOCK: stat_name = 4; -pub const S_SAFE_WRITE32_SLOW_READ_ONLY: stat_name = 25; -pub const S_INVALIDATE_CACHE_ENTRY: stat_name = 31; +pub const S_COMPILE_BASIC_BLOCK: StatName = 4; +pub const S_SAFE_WRITE32_SLOW_READ_ONLY: StatName = 25; +pub const S_INVALIDATE_CACHE_ENTRY: StatName = 31; -pub const S_RUN_INTERPRETED_STEPS: stat_name = 11; -pub const S_FULL_CLEAR_TLB: stat_name = 34; -pub type stat_name = u32; -pub const S_TLB_FULL: stat_name = 35; -pub const S_DO_MANY_CYCLES: stat_name = 28; -pub const S_SAFE_WRITE32_SLOW_PAGE_CROSSED: stat_name = 21; -pub const S_SAFE_READ32_SLOW_IN_MAPPED_RANGE: stat_name = 19; -pub const S_RUN_INTERPRETED: stat_name = 7; -pub const S_RUN_FROM_CACHE: stat_name = 12; -pub const S_SAFE_READ32_SLOW_NOT_USER: stat_name = 18; -pub const S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE: stat_name = 24; -pub const S_NONFAULTING_OPTIMIZATION: stat_name = 32; +pub const S_RUN_INTERPRETED_STEPS: StatName = 11; +pub const S_FULL_CLEAR_TLB: StatName = 34; +pub type StatName = u32; +pub const S_TLB_FULL: StatName = 35; +pub const S_DO_MANY_CYCLES: StatName = 28; +pub const S_SAFE_WRITE32_SLOW_PAGE_CROSSED: StatName = 21; +pub const S_SAFE_READ32_SLOW_IN_MAPPED_RANGE: StatName = 19; +pub const S_RUN_INTERPRETED: StatName = 7; +pub const S_RUN_FROM_CACHE: StatName = 12; +pub const S_SAFE_READ32_SLOW_NOT_USER: StatName = 18; +pub const S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE: StatName = 24; +pub const S_NONFAULTING_OPTIMIZATION: StatName = 32; #[no_mangle] pub static mut profiler_stat_arr: [profiler_stat; 37] = unsafe { [ @@ -104,17 +97,17 @@ pub unsafe fn profiler_init() -> () { } } #[no_mangle] -pub unsafe fn profiler_stat_increment(mut stat: stat_name) -> () { +pub unsafe fn profiler_stat_increment(mut stat: StatName) -> () { profiler_stat_increment_by(stat, 1i32); } #[no_mangle] -pub unsafe fn profiler_stat_increment_by(mut stat: stat_name, mut by: i32) -> () { +pub unsafe fn profiler_stat_increment_by(mut stat: StatName, mut by: i32) -> () { if cfg!(feature = "profiler") { profiler_stat_arr[stat as usize].count += by; } } #[no_mangle] -pub unsafe fn profiler_stat_get(mut stat: stat_name) -> i32 { +pub unsafe fn profiler_stat_get(mut stat: StatName) -> i32 { if cfg!(feature = "profiler") { profiler_stat_arr[stat as usize].count } diff --git a/src/rust/cpu2/sse_instr.rs b/src/rust/cpu2/sse_instr.rs index a07cf84d..6cbf4e95 100644 --- a/src/rust/cpu2/sse_instr.rs +++ b/src/rust/cpu2/sse_instr.rs @@ -1,11 +1,4 @@ -#![allow( - dead_code, - mutable_transmutes, - non_camel_case_types, - non_snake_case, - non_upper_case_globals, - unused_mut -)] +#![allow(mutable_transmutes, unused_mut)] use cpu2::cpu::*; diff --git a/src/rust/cpu2/string.rs b/src/rust/cpu2/string.rs index cfef9b80..c22f7630 100644 --- a/src/rust/cpu2/string.rs +++ b/src/rust/cpu2/string.rs @@ -1,11 +1,4 @@ -#![allow( - dead_code, - mutable_transmutes, - non_camel_case_types, - non_snake_case, - non_upper_case_globals, - unused_mut -)] +#![allow(mutable_transmutes, non_upper_case_globals, unused_mut)] extern "C" { #[no_mangle] From ef796d7f62e713f3938cd8579423cc79b220aaac Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Aug 2018 21:39:05 -0500 Subject: [PATCH 1254/2137] c2rust cleanup: Remove fresh variables --- src/rust/cpu2/arith.rs | 30 ++++++++++-------------------- src/rust/cpu2/cpu.rs | 26 ++++++++++---------------- src/rust/cpu2/instructions.rs | 30 ++++++++++-------------------- src/rust/cpu2/instructions_0f.rs | 21 +++++++-------------- src/rust/cpu2/misc_instr.rs | 18 ++++++------------ 5 files changed, 43 insertions(+), 82 deletions(-) diff --git a/src/rust/cpu2/arith.rs b/src/rust/cpu2/arith.rs index 014f476a..2586c57d 100644 --- a/src/rust/cpu2/arith.rs +++ b/src/rust/cpu2/arith.rs @@ -288,13 +288,11 @@ pub unsafe fn bcd_daa() -> () { let mut old_af: i32 = getaf() as i32; *flags &= !1i32 & !FLAG_ADJUST; if old_al & 15i32 > 9i32 || 0 != old_af { - let ref mut fresh0 = *reg8.offset(AL as isize); - *fresh0 = (*fresh0 as i32 + 6i32) as u8; + *reg8.offset(AL as isize) += 6; *flags |= FLAG_ADJUST } if old_al > 153i32 || 0 != old_cf { - let ref mut fresh1 = *reg8.offset(AL as isize); - *fresh1 = (*fresh1 as i32 + 96i32) as u8; + *reg8.offset(AL as isize) += 96; *flags |= 1i32 } *last_result = *reg8.offset(AL as isize) as i32; @@ -309,8 +307,7 @@ pub unsafe fn bcd_das() -> () { let mut old_cf: i32 = getcf() as i32; *flags &= !1i32; if old_al & 15i32 > 9i32 || 0 != getaf() as i32 { - let ref mut fresh2 = *reg8.offset(AL as isize); - *fresh2 = (*fresh2 as i32 - 6i32) as u8; + *reg8.offset(AL as isize) -= 6; *flags |= FLAG_ADJUST; *flags = *flags & !1i32 | old_cf | (old_al < 6i32) as i32 } @@ -318,8 +315,7 @@ pub unsafe fn bcd_das() -> () { *flags &= !FLAG_ADJUST } if old_al > 153i32 || 0 != old_cf { - let ref mut fresh3 = *reg8.offset(AL as isize); - *fresh3 = (*fresh3 as i32 - 96i32) as u8; + *reg8.offset(AL as isize) -= 96; *flags |= 1i32 } *last_result = *reg8.offset(AL as isize) as i32; @@ -359,33 +355,27 @@ pub unsafe fn bcd_aam(mut imm8: i32) -> () { #[no_mangle] pub unsafe fn bcd_aaa() -> () { if *reg8.offset(AL as isize) as i32 & 15i32 > 9i32 || 0 != getaf() as i32 { - let ref mut fresh4 = *reg16.offset(AX as isize); - *fresh4 = (*fresh4 as i32 + 6i32) as u16; - let ref mut fresh5 = *reg8.offset(AH as isize); - *fresh5 = (*fresh5 as i32 + 1i32) as u8; + *reg16.offset(AX as isize) += 6; + *reg8.offset(AH as isize) += 1; *flags |= FLAG_ADJUST | 1i32 } else { *flags &= !FLAG_ADJUST & !1i32 } - let ref mut fresh6 = *reg8.offset(AL as isize); - *fresh6 = (*fresh6 as i32 & 15i32) as u8; + *reg8.offset(AL as isize) &= 15; *flags_changed &= !FLAG_ADJUST & !1i32; } #[no_mangle] pub unsafe fn bcd_aas() -> () { if *reg8.offset(AL as isize) as i32 & 15i32 > 9i32 || 0 != getaf() as i32 { - let ref mut fresh7 = *reg16.offset(AX as isize); - *fresh7 = (*fresh7 as i32 - 6i32) as u16; - let ref mut fresh8 = *reg8.offset(AH as isize); - *fresh8 = (*fresh8 as i32 - 1i32) as u8; + *reg16.offset(AX as isize) -= 6; + *reg8.offset(AH as isize) -= 1; *flags |= FLAG_ADJUST | 1i32 } else { *flags &= !FLAG_ADJUST & !1i32 } - let ref mut fresh9 = *reg8.offset(AL as isize); - *fresh9 = (*fresh9 as i32 & 15i32) as u8; + *reg8.offset(AL as isize) &= 15; *flags_changed &= !FLAG_ADJUST & !1i32; } #[no_mangle] diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index fe2c659d..cf9776a0 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -385,9 +385,8 @@ pub unsafe fn do_page_translation( } } dbg_assert!(valid_tlb_entries_count < VALID_TLB_ENTRY_MAX); - let fresh0 = valid_tlb_entries_count; - valid_tlb_entries_count = valid_tlb_entries_count + 1; - valid_tlb_entries[fresh0 as usize] = page; + valid_tlb_entries[valid_tlb_entries_count as usize] = page; + valid_tlb_entries_count += 1; // TODO: Check that there are no duplicates in valid_tlb_entries // XXX: There will probably be duplicates due to invlpg deleting // entries from tlb_data but not from valid_tlb_entries @@ -481,9 +480,8 @@ pub unsafe fn clear_tlb() -> () { let mut entry: i32 = *tlb_data.offset(page as isize); if 0 != entry & TLB_GLOBAL { // reinsert at the front - let fresh1 = global_page_offset; - global_page_offset = global_page_offset + 1; - valid_tlb_entries[fresh1 as usize] = page + valid_tlb_entries[global_page_offset as usize] = page; + global_page_offset += 1; } else { *tlb_data.offset(page as isize) = 0i32 @@ -1506,25 +1504,21 @@ pub unsafe fn set_ecx_asize(mut value: i32) -> () { pub unsafe fn add_reg_asize(mut reg: i32, mut value: i32) -> () { dbg_assert!(reg == ECX || reg == ESI || reg == EDI); if is_asize_32() { - let ref mut fresh2 = *reg32s.offset(reg as isize); - *fresh2 += value + *reg32s.offset(reg as isize) += value; } else { - let ref mut fresh3 = *reg16.offset((reg << 1i32) as isize); - *fresh3 = (*fresh3 as i32 + value) as u16 + *reg16.offset((reg << 1i32) as isize) += value as u16; }; } pub unsafe fn decr_ecx_asize() -> i32 { return if 0 != is_asize_32() as i32 { - let ref mut fresh4 = *reg32s.offset(ECX as isize); - *fresh4 -= 1; - *fresh4 + *reg32s.offset(ECX as isize) -= 1; + *reg32s.offset(ECX as isize) } else { - let ref mut fresh5 = *reg16.offset(CX as isize); - *fresh5 = (*fresh5).wrapping_sub(1); - *fresh5 as i32 + *reg16.offset(CX as isize) -= 1; + *reg16.offset(CX as isize) as i32 }; } diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index 82c76a5f..75b3228c 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -1849,8 +1849,7 @@ pub unsafe fn instr_9E() -> () { // sahf *flags.offset(0isize) = *flags.offset(0isize) & !255i32 | *reg8.offset(AH as isize) as i32; *flags.offset(0isize) = *flags.offset(0isize) & FLAGS_MASK | FLAGS_DEFAULT; - let ref mut fresh1 = *flags_changed.offset(0isize); - *fresh1 &= !255i32; + *flags_changed.offset(0isize) &= !255i32; } #[no_mangle] pub unsafe fn instr_9F() -> () { @@ -3107,8 +3106,7 @@ pub unsafe fn instr_F4() -> () { hlt_op(); } pub unsafe fn instr_F5() -> () { // cmc *flags.offset(0isize) = (*flags.offset(0isize) | 1i32) ^ getcf() as i32; - let ref mut fresh2 = *flags_changed.offset(0isize); - *fresh2 &= !1i32; + *flags_changed.offset(0isize) &= !1i32; } #[no_mangle] pub unsafe fn instr_F6_0_mem(mut addr: i32, mut imm: i32) -> () { @@ -3347,18 +3345,14 @@ pub unsafe fn instr32_F7_7_reg(mut r1: i32) -> () { #[no_mangle] pub unsafe fn instr_F8() -> () { // clc - let ref mut fresh3 = *flags.offset(0isize); - *fresh3 &= !FLAG_CARRY; - let ref mut fresh4 = *flags_changed.offset(0isize); - *fresh4 &= !1i32; + *flags.offset(0isize) &= !FLAG_CARRY; + *flags_changed.offset(0isize) &= !1i32; } #[no_mangle] pub unsafe fn instr_F9() -> () { // stc - let ref mut fresh5 = *flags.offset(0isize); - *fresh5 |= FLAG_CARRY; - let ref mut fresh6 = *flags_changed.offset(0isize); - *fresh6 &= !1i32; + *flags.offset(0isize) |= FLAG_CARRY; + *flags_changed.offset(0isize) &= !1i32; } #[no_mangle] pub unsafe fn instr_FA() -> () { @@ -3369,8 +3363,7 @@ pub unsafe fn instr_FA() -> () { else { (getiopl() >= *cpl as i32) as i32 } { - let ref mut fresh7 = *flags.offset(0isize); - *fresh7 &= !FLAG_INTERRUPT + *flags.offset(0isize) &= !FLAG_INTERRUPT; } else if 0 != 0i32 * 0i32 && getiopl() < 3i32 && 0 != if 0 != *flags & FLAG_VM { *cr.offset(4isize) & CR4_VME @@ -3395,8 +3388,7 @@ pub unsafe fn instr_FB() -> () { else { (getiopl() >= *cpl as i32) as i32 } { - let ref mut fresh8 = *flags.offset(0isize); - *fresh8 |= FLAG_INTERRUPT; + *flags.offset(0isize) |= FLAG_INTERRUPT; if old_if == 0i32 { handle_irqs(); } @@ -3419,14 +3411,12 @@ pub unsafe fn instr_FB() -> () { #[no_mangle] pub unsafe fn instr_FC() -> () { // cld - let ref mut fresh9 = *flags.offset(0isize); - *fresh9 &= !FLAG_DIRECTION; + *flags.offset(0isize) &= !FLAG_DIRECTION; } #[no_mangle] pub unsafe fn instr_FD() -> () { // std - let ref mut fresh10 = *flags.offset(0isize); - *fresh10 |= FLAG_DIRECTION; + *flags.offset(0isize) |= FLAG_DIRECTION; } #[no_mangle] pub unsafe fn instr_FE_0_mem(mut addr: i32) -> () { diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 5fb08fac..bbd5b928 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -401,8 +401,7 @@ pub unsafe fn instr_0F06() -> () { if 0 != 0i32 * 0i32 { dbg_log_c!("clts"); } - let ref mut fresh0 = *cr.offset(0isize); - *fresh0 &= !CR0_TS + *cr.offset(0isize) &= !CR0_TS; }; } #[no_mangle] @@ -1314,8 +1313,7 @@ pub unsafe fn instr_0F34() -> () { return; } else { - let ref mut fresh1 = *flags.offset(0isize); - *fresh1 &= !FLAG_VM & !FLAG_INTERRUPT; + *flags.offset(0isize) &= !FLAG_VM & !FLAG_INTERRUPT; *instruction_pointer.offset(0isize) = *sysenter_eip.offset(0isize); *reg32s.offset(ESP as isize) = *sysenter_esp.offset(0isize); *sreg.offset(CS as isize) = seg as u16; @@ -3975,21 +3973,18 @@ pub unsafe fn instr_0FC7_1_mem(mut addr: i32) -> () { let mut m64_low: i32 = return_on_pagefault!(safe_read32s(addr)); let mut m64_high: i32 = return_on_pagefault!(safe_read32s(addr + 4i32)); if *reg32s.offset(EAX as isize) == m64_low && *reg32s.offset(EDX as isize) == m64_high { - let ref mut fresh2 = *flags.offset(0isize); - *fresh2 |= FLAG_ZERO; + *flags.offset(0isize) |= FLAG_ZERO; safe_write32(addr, *reg32s.offset(EBX as isize)).unwrap(); safe_write32(addr + 4i32, *reg32s.offset(ECX as isize)).unwrap(); } else { - let ref mut fresh3 = *flags.offset(0isize); - *fresh3 &= !FLAG_ZERO; + *flags.offset(0isize) &= !FLAG_ZERO; *reg32s.offset(EAX as isize) = m64_low; *reg32s.offset(EDX as isize) = m64_high; safe_write32(addr, m64_low).unwrap(); safe_write32(addr + 4i32, m64_high).unwrap(); } - let ref mut fresh4 = *flags_changed.offset(0isize); - *fresh4 &= !FLAG_ZERO; + *flags_changed.offset(0isize) &= !FLAG_ZERO; } #[no_mangle] pub unsafe fn instr_0FC7_6_reg(mut r: i32) -> () { @@ -4000,10 +3995,8 @@ pub unsafe fn instr_0FC7_6_reg(mut r: i32) -> () { rand = get_rand_int() } write_reg_osize(r, rand); - let ref mut fresh5 = *flags.offset(0isize); - *fresh5 &= !FLAGS_ALL; - let ref mut fresh6 = *flags.offset(0isize); - *fresh6 |= has_rand; + *flags.offset(0isize) &= !FLAGS_ALL; + *flags.offset(0isize) |= has_rand; *flags_changed.offset(0isize) = 0i32; } #[no_mangle] diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index 632695f7..e84cb665 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -159,12 +159,10 @@ pub unsafe fn get_stack_pointer(mut offset: i32) -> i32 { #[no_mangle] pub unsafe fn adjust_stack_reg(mut adjustment: i32) -> () { if *stack_size_32 { - let ref mut fresh0 = *reg32s.offset(ESP as isize); - *fresh0 += adjustment + *reg32s.offset(ESP as isize) += adjustment; } else { - let ref mut fresh1 = *reg16.offset(SP as isize); - *fresh1 = (*fresh1 as i32 + adjustment) as u16 + *reg16.offset(SP as isize) += adjustment as u16; }; } @@ -172,16 +170,14 @@ pub unsafe fn adjust_stack_reg(mut adjustment: i32) -> () { pub unsafe fn push16_ss16(mut imm16: i32) -> Result<(), ()> { let mut sp: i32 = get_seg_ss() + (*reg16.offset(SP as isize) as i32 - 2i32 & 65535i32); safe_write16(sp, imm16)?; - let ref mut fresh2 = *reg16.offset(SP as isize); - *fresh2 = (*fresh2 as i32 + -2i32) as u16; + *reg16.offset(SP as isize) -= 2; Ok(()) } #[no_mangle] pub unsafe fn push16_ss32(mut imm16: i32) -> Result<(), ()> { let mut sp: i32 = get_seg_ss() + *reg32s.offset(ESP as isize) - 2i32; safe_write16(sp, imm16)?; - let ref mut fresh3 = *reg32s.offset(ESP as isize); - *fresh3 += -2i32; + *reg32s.offset(ESP as isize) -= 2; Ok(()) } @@ -262,16 +258,14 @@ pub unsafe fn pop16() -> Result { pub unsafe fn pop16_ss16() -> Result { let mut sp: i32 = get_seg_ss() + *reg16.offset(SP as isize) as i32; let mut result: i32 = safe_read16(sp)?; - let ref mut fresh4 = *reg16.offset(SP as isize); - *fresh4 = (*fresh4 as i32 + 2i32) as u16; + *reg16.offset(SP as isize) += 2; Ok(result) } #[no_mangle] pub unsafe fn pop16_ss32() -> Result { let mut esp: i32 = get_seg_ss() + *reg32s.offset(ESP as isize); let mut result: i32 = safe_read16(esp)?; - let ref mut fresh5 = *reg32s.offset(ESP as isize); - *fresh5 += 2i32; + *reg32s.offset(ESP as isize) += 2; Ok(result) } #[no_mangle] From 44bc613af33742167439aadd25e6faf026114797 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Aug 2018 22:08:22 -0500 Subject: [PATCH 1255/2137] c2rust cleanup: Remove dbg_log_c --- src/rust/cpu2/cpu.rs | 22 ++++++------- src/rust/cpu2/fpu.rs | 6 ++-- src/rust/cpu2/imports.rs | 10 ------ src/rust/cpu2/instructions.rs | 56 ++++++++++++++++---------------- src/rust/cpu2/instructions_0f.rs | 48 +++++++++++++-------------- src/rust/cpu2/misc_instr.rs | 2 +- 6 files changed, 67 insertions(+), 77 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index cf9776a0..c6537c01 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -503,8 +503,8 @@ pub unsafe fn clear_tlb() -> () { pub unsafe fn trigger_pagefault(mut write: bool, mut user: bool, mut present: bool) -> () { if 0 != 0i32 * 0i32 { - dbg_log_c!( - "page fault w=%d u=%d p=%d eip=%x cr2=%x", + dbg_log!( + "page fault w={} u={} p={} eip={:x} cr2={:x}", write as i32, user as i32, present as i32, @@ -515,13 +515,13 @@ pub unsafe fn trigger_pagefault(mut write: bool, mut user: bool, mut present: bo } if DEBUG { if must_not_fault { - dbg_log_c!("Unexpected page fault"); + dbg_log!("Unexpected page fault"); dbg_trace(); dbg_assert!(0 != 0i32); } } //if *page_fault { - // dbg_log_c!(("double fault")); + // dbg_log!(("double fault")); // dbg_trace(); // dbg_assert!(0 != 0i32); //} @@ -681,7 +681,7 @@ pub unsafe fn get_seg(mut segment: i32) -> i32 { if *protected_mode { if *segment_is_null.offset(segment as isize) { dbg_assert!(segment != CS && segment != SS); - dbg_log_c!("#gp: Access null segment"); + dbg_log!("#gp: Access null segment"); assert!(false); trigger_gp(0i32); } @@ -697,8 +697,8 @@ pub unsafe fn trigger_gp(mut code: i32) -> () { pub unsafe fn raise_exception_with_code(mut interrupt_nr: i32, mut error_code: i32) -> () { if DEBUG { if must_not_fault { - dbg_log_c!( - "Unexpected fault: 0x%x with code 0x%x", + dbg_log!( + "Unexpected fault: 0x{:x} with code 0x{:x}", interrupt_nr, error_code ); @@ -879,7 +879,7 @@ pub unsafe fn do_many_cycles_native() -> () { //pub unsafe fn raise_exception(mut interrupt_nr: i32) -> () { // if DEBUG { // if must_not_fault { -// dbg_log_c!("Unexpected fault: 0x%x", interrupt_nr); +// dbg_log!("Unexpected fault: 0x{:x}", interrupt_nr); // dbg_trace(); // dbg_assert!(0 != 0i32); // } @@ -905,7 +905,7 @@ pub unsafe fn trigger_de() -> () { #[no_mangle] pub unsafe fn trigger_ud() -> () { - dbg_log_c!("#ud"); + dbg_log!("#ud"); dbg_trace(); if DEBUG { if cpu_exception_hook(CPU_EXCEPTION_UD) { @@ -1549,8 +1549,8 @@ pub unsafe fn read_tsc() -> u64 { rdtsc_imprecision_offset = 0i32 as u64 } else { - dbg_log_c!( - "XXX: Overshot tsc prev=%x:%x offset=%x:%x curr=%x:%x", + dbg_log!( + "XXX: Overshot tsc prev={:x}:{:x} offset={:x}:{:x} curr={:x}:{:x}", (rdtsc_last_value >> 32i32) as u32 as i32, rdtsc_last_value as u32 as i32, (rdtsc_imprecision_offset >> 32i32) as u32 as i32, diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 8e5f5b0d..13ff20b1 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -141,7 +141,7 @@ pub unsafe fn fpu_load_m80(mut addr: u32) -> Result { else { // TODO: NaN, Infinity if 0 != 0i32 * 0i32 { - dbg_log_c!("Load m80 TODO"); + dbg_log!("Load m80 TODO"); } let mut double_int_view: f64_int = f64_int { u8_0: [0; 8] }; double_int_view.u8_0[7usize] = (127i32 | sign << 7i32) as u8; @@ -335,7 +335,7 @@ pub unsafe fn fpu_fldenv(mut addr: i32) -> () { *fpu_dp_selector.offset(0isize) = safe_read16(addr + 24i32).unwrap() } else { - dbg_log_c!("fldenv16"); + dbg_log!("fldenv16"); fpu_unimpl(); }; } @@ -491,7 +491,7 @@ pub unsafe fn fpu_fstenv(mut addr: i32) -> () { safe_write16(addr + 24i32, *fpu_dp_selector.offset(0isize)).unwrap(); } else { - dbg_log_c!("fstenv16"); + dbg_log!("fstenv16"); fpu_unimpl(); }; } diff --git a/src/rust/cpu2/imports.rs b/src/rust/cpu2/imports.rs index 1fcff55f..bd08128b 100644 --- a/src/rust/cpu2/imports.rs +++ b/src/rust/cpu2/imports.rs @@ -23,13 +23,3 @@ pub fn allocate_memory(size: u32) -> u32 { }; ptr } - -macro_rules! dbg_log_c { - ($fmt:expr) => {{ - dbg_log!($fmt); - }}; - ($fmt:expr, $($arg:tt)*) => {{ - // TODO: Arguments - dbg_log!($fmt); - }}; -} diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index 75b3228c..506367eb 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -952,12 +952,12 @@ pub unsafe fn instr32_61() -> () { popa32(); } #[no_mangle] pub unsafe fn instr_62_reg(mut r2: i32, mut r: i32) -> () { // bound - dbg_log_c!("Unimplemented BOUND instruction"); + dbg_log!("Unimplemented BOUND instruction"); dbg_assert!(0 != 0i32); } #[no_mangle] pub unsafe fn instr_62_mem(mut addr: i32, mut r: i32) -> () { - dbg_log_c!("Unimplemented BOUND instruction"); + dbg_log!("Unimplemented BOUND instruction"); dbg_assert!(0 != 0i32); } #[no_mangle] @@ -1570,7 +1570,7 @@ pub unsafe fn instr32_8B_reg(mut r1: i32, mut r: i32) -> () { #[no_mangle] pub unsafe fn instr_8C_check_sreg(mut seg: i32) -> bool { if seg >= 6i32 { - dbg_log_c!("mov sreg #ud"); + dbg_log!("mov sreg #ud"); trigger_ud(); return 0 != 0i32; } @@ -1604,7 +1604,7 @@ pub unsafe fn instr32_8C_mem(mut addr: i32, mut seg: i32) -> () { } #[no_mangle] pub unsafe fn instr16_8D_reg(mut r: i32, mut r2: i32) -> () { - dbg_log_c!("lea #ud"); + dbg_log!("lea #ud"); trigger_ud(); } #[no_mangle] @@ -1618,7 +1618,7 @@ pub unsafe fn instr16_8D_mem(modrm_byte: i32, mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr32_8D_reg(mut r: i32, mut r2: i32) -> () { - dbg_log_c!("lea #ud"); + dbg_log!("lea #ud"); trigger_ud(); } #[no_mangle] @@ -1639,7 +1639,7 @@ pub unsafe fn instr_8E_helper(mut data: i32, mut mod_0: i32) -> () { } } else { - dbg_log_c!("mov sreg #ud"); + dbg_log!("mov sreg #ud"); trigger_ud(); }; } @@ -1789,7 +1789,7 @@ pub unsafe fn instr16_9C() -> () { // pushf if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { dbg_assert!(*protected_mode); - dbg_log_c!("pushf #gp"); + dbg_log!("pushf #gp"); trigger_gp_non_raising(0i32); } else { @@ -1802,7 +1802,7 @@ pub unsafe fn instr32_9C() -> () { if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { // trap to virtual 8086 monitor dbg_assert!(*protected_mode); - dbg_log_c!("pushf #gp"); + dbg_log!("pushf #gp"); trigger_gp_non_raising(0i32); } else { @@ -1814,7 +1814,7 @@ pub unsafe fn instr32_9C() -> () { pub unsafe fn instr16_9D() -> () { // popf if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { - dbg_log_c!("popf #gp"); + dbg_log!("popf #gp"); trigger_gp_non_raising(0i32); return; } @@ -1834,7 +1834,7 @@ pub unsafe fn instr16_9D() -> () { pub unsafe fn instr32_9D() -> () { // popf if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { - dbg_log_c!("popf #gp"); + dbg_log!("popf #gp"); trigger_gp_non_raising(0i32); return; } @@ -2329,7 +2329,7 @@ pub unsafe fn instr32_CB() -> () { pub unsafe fn instr_CC() -> () { // INT3 // TODO: inhibit iopl checks - dbg_log_c!("INT3"); + dbg_log!("INT3"); call_interrupt_vector(3i32, 0 != 1i32, 0 != 0i32, 0i32); } #[no_mangle] @@ -2340,7 +2340,7 @@ pub unsafe fn instr_CD(mut imm8: i32) -> () { #[no_mangle] pub unsafe fn instr_CE() -> () { // INTO - dbg_log_c!("INTO"); + dbg_log!("INTO"); if getof() { // TODO: inhibit iopl checks call_interrupt_vector(CPU_EXCEPTION_OF, 0 != 1i32, 0 != 0i32, 0i32); @@ -3071,7 +3071,7 @@ pub unsafe fn instr32_EF() -> () { pub unsafe fn instr_F0() -> () { // lock if 0 != 0i32 * 0i32 { - dbg_log_c!("lock"); + dbg_log!("lock"); } // TODO // This triggers UD when used with @@ -3374,7 +3374,7 @@ pub unsafe fn instr_FA() -> () { *flags &= !FLAG_VIF } else { - dbg_log_c!("cli #gp"); + dbg_log!("cli #gp"); trigger_gp_non_raising(0i32); }; } @@ -3404,7 +3404,7 @@ pub unsafe fn instr_FB() -> () { *flags |= FLAG_VIF } else { - dbg_log_c!("sti #gp"); + dbg_log!("sti #gp"); trigger_gp_non_raising(0i32); }; } @@ -3474,7 +3474,7 @@ pub unsafe fn instr16_FF_2_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe fn instr16_FF_3_reg(mut r: i32) -> () { - dbg_log_c!("callf #ud"); + dbg_log!("callf #ud"); trigger_ud(); } #[no_mangle] @@ -3503,7 +3503,7 @@ pub unsafe fn instr16_FF_4_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe fn instr16_FF_5_reg(mut r: i32) -> () { - dbg_log_c!("jmpf #ud"); + dbg_log!("jmpf #ud"); trigger_ud(); } #[no_mangle] @@ -3562,7 +3562,7 @@ pub unsafe fn instr32_FF_2_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe fn instr32_FF_3_reg(mut r: i32) -> () { - dbg_log_c!("callf #ud"); + dbg_log!("callf #ud"); trigger_ud(); } #[no_mangle] @@ -3596,7 +3596,7 @@ pub unsafe fn instr32_FF_4_reg(mut r1: i32) -> () { } #[no_mangle] pub unsafe fn instr32_FF_5_reg(mut r: i32) -> () { - dbg_log_c!("jmpf #ud"); + dbg_log!("jmpf #ud"); trigger_ud(); } #[no_mangle] @@ -3862,7 +3862,7 @@ pub unsafe fn instr_D9_0_reg(mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_D9_1_mem(mut addr: i32) -> () { - dbg_log_c!("d9/1"); + dbg_log!("d9/1"); trigger_ud(); } #[no_mangle] @@ -3879,7 +3879,7 @@ pub unsafe fn instr_D9_2_reg(mut r: i32) -> () { pub unsafe fn instr_D9_3_mem(mut addr: i32) -> () { fpu_fstm32p(addr); } #[no_mangle] pub unsafe fn instr_D9_3_reg(mut r: i32) -> () { - dbg_log_c!("fstp1"); + dbg_log!("fstp1"); trigger_ud(); } #[no_mangle] @@ -3903,7 +3903,7 @@ pub unsafe fn instr_D9_4_reg(mut r: i32) -> () { fpu_fxam(st0); }, _ => { - dbg_log_c!("%x", r); + dbg_log!("{:x}", r); trigger_ud(); }, }; @@ -3936,7 +3936,7 @@ pub unsafe fn instr_D9_5_reg(mut r: i32) -> () { fpu_push(0i32 as f64); }, 7 => { - dbg_log_c!("d9/5/7"); + dbg_log!("d9/5/7"); trigger_ud(); }, _ => {}, @@ -4180,7 +4180,7 @@ pub unsafe fn instr_DC_7_reg(mut r: i32) -> () { fpu_fdivr(r, fpu_get_sti(r)); } pub unsafe fn instr_DD_0_mem(mut addr: i32) -> () { fpu_fldm64(addr); } #[no_mangle] pub unsafe fn instr_DD_1_mem(mut addr: i32) -> () { - dbg_log_c!("fisttp"); + dbg_log!("fisttp"); trigger_ud(); } #[no_mangle] @@ -4191,7 +4191,7 @@ pub unsafe fn instr_DD_3_mem(mut addr: i32) -> () { fpu_fstm64p(addr); } pub unsafe fn instr_DD_4_mem(mut addr: i32) -> () { fpu_frstor(addr); } #[no_mangle] pub unsafe fn instr_DD_5_mem(mut addr: i32) -> () { - dbg_log_c!("dd/5"); + dbg_log!("dd/5"); trigger_ud(); } #[no_mangle] @@ -4292,7 +4292,7 @@ pub unsafe fn instr_DF_0_mem(mut addr: i32) -> () { } #[no_mangle] pub unsafe fn instr_DF_1_mem(mut addr: i32) -> () { - dbg_log_c!("df/fisttp"); + dbg_log!("df/fisttp"); trigger_ud(); } #[no_mangle] @@ -4301,14 +4301,14 @@ pub unsafe fn instr_DF_2_mem(mut addr: i32) -> () { fpu_fistm16(addr); } pub unsafe fn instr_DF_3_mem(mut addr: i32) -> () { fpu_fistm16p(addr); } #[no_mangle] pub unsafe fn instr_DF_4_mem(mut addr: i32) -> () { - dbg_log_c!("fbld"); + dbg_log!("fbld"); trigger_ud(); } #[no_mangle] pub unsafe fn instr_DF_5_mem(mut addr: i32) -> () { fpu_fildm64(addr); } #[no_mangle] pub unsafe fn instr_DF_6_mem(mut addr: i32) -> () { - dbg_log_c!("fbstp"); + dbg_log!("fbstp"); trigger_ud(); } #[no_mangle] diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index bbd5b928..91f691c9 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -394,12 +394,12 @@ pub unsafe fn instr_0F05() -> () { undefined_instruction(); } pub unsafe fn instr_0F06() -> () { // clts if 0 != *cpl.offset(0isize) { - dbg_log_c!("clts #gp"); + dbg_log!("clts #gp"); trigger_gp_non_raising(0i32); } else { if 0 != 0i32 * 0i32 { - dbg_log_c!("clts"); + dbg_log!("clts"); } *cr.offset(0isize) &= !CR0_TS; }; @@ -414,7 +414,7 @@ pub unsafe fn instr_0F08() -> () { #[no_mangle] pub unsafe fn instr_0F09() -> () { if 0 != *cpl.offset(0isize) { - dbg_log_c!("wbinvd #gp"); + dbg_log!("wbinvd #gp"); trigger_gp_non_raising(0i32); } else { @@ -778,7 +778,7 @@ pub unsafe fn instr_0F20(mut r: i32, mut creg: i32) -> () { write_reg32(r, *cr.offset(4isize)); }, _ => { - dbg_log_c!("%d", creg); + dbg_log!("{}", creg); undefined_instruction(); }, } @@ -794,7 +794,7 @@ pub unsafe fn instr_0F21(mut r: i32, mut dreg_index: i32) -> () { else { if dreg_index == 4i32 || dreg_index == 5i32 { if 0 != *cr.offset(4isize) & CR4_DE { - dbg_log_c!("#ud mov dreg 4/5 with cr4.DE set"); + dbg_log!("#ud mov dreg 4/5 with cr4.DE set"); trigger_ud(); return; } @@ -805,8 +805,8 @@ pub unsafe fn instr_0F21(mut r: i32, mut dreg_index: i32) -> () { } write_reg32(r, *dreg.offset(dreg_index as isize)); if 0 != 0i32 * 0i32 { - dbg_log_c!( - "read dr%d: %x", + dbg_log!( + "read dr{}: {:x}", dreg_index, *dreg.offset(dreg_index as isize) ); @@ -826,17 +826,17 @@ pub unsafe fn instr_0F22(mut r: i32, mut creg: i32) -> () { match creg { 0 => { if 0 != 0i32 * 0i32 { - dbg_log_c!("cr0 <- %x", data); + dbg_log!("cr0 <- {:x}", data); } set_cr0(data); }, 2 => { - dbg_log_c!("cr2 <- %x", data); + dbg_log!("cr2 <- {:x}", data); *cr.offset(2isize) = data }, 3 => { if 0 != 0i32 * 0i32 { - dbg_log_c!("cr3 <- %x", data); + dbg_log!("cr3 <- {:x}", data); } data &= !4071i32; dbg_assert!(data & 4095i32 == 0i32, ("TODO")); @@ -844,7 +844,7 @@ pub unsafe fn instr_0F22(mut r: i32, mut creg: i32) -> () { clear_tlb(); }, 4 => { - dbg_log_c!("cr4 <- %d", *cr.offset(4isize)); + dbg_log!("cr4 <- {}", *cr.offset(4isize)); if 0 != data as u32 & ((1i32 << 11i32 | 1i32 << 12i32 @@ -853,7 +853,7 @@ pub unsafe fn instr_0F22(mut r: i32, mut creg: i32) -> () { | 1i32 << 19i32) as u32 | 4290772992u32) { - dbg_log_c!("trigger_gp: Invalid cr4 bit"); + dbg_log!("trigger_gp: Invalid cr4 bit"); trigger_gp_non_raising(0i32); return; } @@ -868,7 +868,7 @@ pub unsafe fn instr_0F22(mut r: i32, mut creg: i32) -> () { } }, _ => { - dbg_log_c!("%d", creg); + dbg_log!("{}", creg); undefined_instruction(); }, } @@ -884,7 +884,7 @@ pub unsafe fn instr_0F23(mut r: i32, mut dreg_index: i32) -> () { else { if dreg_index == 4i32 || dreg_index == 5i32 { if 0 != *cr.offset(4isize) & CR4_DE { - dbg_log_c!("#ud mov dreg 4/5 with cr4.DE set"); + dbg_log!("#ud mov dreg 4/5 with cr4.DE set"); trigger_ud(); return; } @@ -895,8 +895,8 @@ pub unsafe fn instr_0F23(mut r: i32, mut dreg_index: i32) -> () { } *dreg.offset(dreg_index as isize) = read_reg32(r); if 0 != 0i32 * 0i32 { - dbg_log_c!( - "write dr%d: %x", + dbg_log!( + "write dr{}: {:x}", dreg_index, *dreg.offset(dreg_index as isize) ); @@ -1165,7 +1165,7 @@ pub unsafe fn instr_0F30() -> () { let mut low: i32 = *reg32s.offset(EAX as isize); let mut high: i32 = *reg32s.offset(EDX as isize); if index != IA32_SYSENTER_ESP { - dbg_log_c!("wrmsr ecx=%x data=%x:%x", index, high, low); + dbg_log!("wrmsr ecx={:x} data={:x}:{:x}", index, high, low); } if index == IA32_SYSENTER_CS { *sysenter_cs.offset(0isize) = low & 65535i32 @@ -1205,10 +1205,10 @@ pub unsafe fn instr_0F30() -> () { } else if index == IA32_KERNEL_GS_BASE { // Only used in 64 bit mode (by SWAPGS), but set by kvm-unit-test - dbg_log_c!("GS Base written"); + dbg_log!("GS Base written"); } else { - dbg_log_c!("Unknown msr: %x", index); + dbg_log!("Unknown msr: {:x}", index); dbg_assert!(0 != 0i32); } } @@ -1223,8 +1223,8 @@ pub unsafe fn instr_0F31() -> () { *reg32s.offset(EAX as isize) = tsc as i32; *reg32s.offset(EDX as isize) = (tsc >> 32i32) as i32; if 0 != 0i32 * 0i32 { - dbg_log_c!( - "rdtsc edx:eax=%x:%x", + dbg_log!( + "rdtsc edx:eax={:x}:{:x}", *reg32s.offset(EDX as isize), *reg32s.offset(EAX as isize) ); @@ -1243,7 +1243,7 @@ pub unsafe fn instr_0F32() -> () { } else { let mut index: i32 = *reg32s.offset(ECX as isize); - dbg_log_c!("rdmsr ecx=%x", index); + dbg_log!("rdmsr ecx={:x}", index); let mut low: i32 = 0i32; let mut high: i32 = 0i32; if index == IA32_SYSENTER_CS { @@ -1287,7 +1287,7 @@ pub unsafe fn instr_0F32() -> () { // netbsd } else if !(index == MSR_PKG_C2_RESIDENCY) { - dbg_log_c!("Unknown msr: %x", index); + dbg_log!("Unknown msr: {:x}", index); dbg_assert!(0 != 0i32); } } @@ -5839,7 +5839,7 @@ pub unsafe fn instr_660FFE_mem(mut addr: i32, mut r: i32) -> () { #[no_mangle] pub unsafe fn instr_0FFF() -> () { // Windows 98 - dbg_log_c!("#ud: 0F FF"); + dbg_log!("#ud: 0F FF"); trigger_ud(); } #[no_mangle] diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index e84cb665..30326d61 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -380,7 +380,7 @@ pub unsafe fn fxrstor(mut addr: u32) -> () { )); let mut new_mxcsr: i32 = safe_read32s(addr.wrapping_add(24i32 as u32) as i32).unwrap(); if 0 != new_mxcsr & !MXCSR_MASK { - dbg_log_c!("#gp Invalid mxcsr bits"); + dbg_log!("#gp Invalid mxcsr bits"); trigger_gp_non_raising(0i32); return; } From 015232f46674f812c4010d0fbb1910e4f0721f70 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Aug 2018 22:19:00 -0500 Subject: [PATCH 1256/2137] c2rust cleanup: Remove .offset(0) --- src/rust/cpu2/cpu.rs | 20 ++--- src/rust/cpu2/fpu.rs | 26 +++--- src/rust/cpu2/instructions.rs | 64 +++++++-------- src/rust/cpu2/instructions_0f.rs | 136 +++++++++++++++---------------- 4 files changed, 123 insertions(+), 123 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index c6537c01..2119bb08 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -258,7 +258,7 @@ pub unsafe fn get_eflags() -> i32 { pub unsafe fn translate_address_read(mut address: i32) -> Result { let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); - let mut user: bool = *cpl.offset(0isize) as i32 == 3i32; + let mut user: bool = *cpl as i32 == 3i32; if entry & (TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0i32 }) == TLB_VALID { return Ok((entry & !4095i32 ^ address) as u32); } @@ -277,7 +277,7 @@ pub unsafe fn do_page_translation( let mut allow_user: bool = 0 != 1i32; let mut page: i32 = (addr as u32 >> 12i32) as i32; let mut high: i32 = 0; - if *cr.offset(0isize) & CR0_PG == 0i32 { + if *cr & CR0_PG == 0i32 { // paging disabled high = (addr as u32 & 4294963200u32) as i32; global = 0 != 0i32 @@ -287,7 +287,7 @@ pub unsafe fn do_page_translation( (*cr.offset(3isize) as u32 >> 2i32).wrapping_add((page >> 10i32) as u32) as i32; let mut page_dir_entry: i32 = read_aligned32(page_dir_addr as u32); // XXX - let kernel_write_override: bool = !user && 0 == *cr.offset(0isize) & CR0_WP; + let kernel_write_override: bool = !user && 0 == *cr & CR0_WP; if 0 == page_dir_entry & PAGE_TABLE_PRESENT_MASK { // to do at this place: // @@ -542,7 +542,7 @@ pub unsafe fn trigger_pagefault(mut write: bool, mut user: bool, mut present: bo pub unsafe fn translate_address_write(mut address: i32) -> Result { let mut base: i32 = (address as u32 >> 12i32) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); - let mut user: bool = *cpl.offset(0isize) as i32 == 3i32; + let mut user: bool = *cpl as i32 == 3i32; if entry & (TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0i32 } | TLB_READONLY) == TLB_VALID { @@ -601,11 +601,11 @@ pub unsafe fn check_tlb_invariants() -> () { pub unsafe fn writable_or_pagefault(mut addr: i32, mut size: i32) -> Result<(), ()> { dbg_assert!(size < 4096i32); dbg_assert!(size > 0i32); - if *cr.offset(0isize) & CR0_PG == 0i32 { + if *cr & CR0_PG == 0i32 { return Ok(()); } else { - let mut user: bool = *cpl.offset(0isize) as i32 == 3i32; + let mut user: bool = *cpl as i32 == 3i32; let mut mask: i32 = TLB_READONLY | TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0i32 }; let mut expect: i32 = TLB_VALID; @@ -827,11 +827,11 @@ unsafe fn jit_run_interpreted(mut phys_addr: i32) -> () { *timestamp_counter = (*timestamp_counter).wrapping_add(1); run_instruction(opcode | (*is_32 as i32) << 8i32); while !jit_block_boundary && 0 != same_page(*previous_ip, *instruction_pointer) as i32 { - *previous_ip.offset(0isize) = *instruction_pointer.offset(0isize); + *previous_ip = *instruction_pointer; *timestamp_counter = (*timestamp_counter).wrapping_add(1); let mut opcode_0: i32 = return_on_pagefault!(read_imm8()); if DEBUG { - logop(*previous_ip.offset(0isize), opcode_0); + logop(*previous_ip, opcode_0); } run_instruction(opcode_0 | (*is_32 as i32) << 8i32); } @@ -870,7 +870,7 @@ pub unsafe fn do_many_cycles_native() -> () { profiler_stat_increment(S_DO_MANY_CYCLES); let mut initial_timestamp_counter: u32 = *timestamp_counter; while (*timestamp_counter).wrapping_sub(initial_timestamp_counter) < LOOP_COUNTER as u32 - && !*in_hlt.offset(0isize) + && !*in_hlt { cycle_internal(); } @@ -1388,7 +1388,7 @@ pub unsafe fn write_xmm_reg128(mut r: i32, mut data: reg128) -> () { } pub unsafe fn task_switch_test() -> bool { - if 0 != *cr.offset(0isize) & (CR0_EM | CR0_TS) { + if 0 != *cr & (CR0_EM | CR0_TS) { trigger_nm(); return 0 != 0i32; } diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 13ff20b1..4f25109d 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -260,9 +260,9 @@ pub unsafe fn fpu_push(mut x: f64) -> () { pub unsafe fn fpu_finit() -> () { *fpu_control_word = 895i32; *fpu_status_word = 0i32; - *fpu_ip.offset(0isize) = 0i32; - *fpu_dp.offset(0isize) = 0i32; - *fpu_opcode.offset(0isize) = 0i32; + *fpu_ip = 0i32; + *fpu_dp = 0i32; + *fpu_opcode = 0i32; *fpu_stack_empty = 255i32; *fpu_stack_ptr = 0i32 as u32; } @@ -328,11 +328,11 @@ pub unsafe fn fpu_fldenv(mut addr: i32) -> () { *fpu_control_word = safe_read16(addr).unwrap(); fpu_set_status_word(safe_read16(addr + 4i32).unwrap()); fpu_set_tag_word(safe_read16(addr + 8i32).unwrap()); - *fpu_ip.offset(0isize) = safe_read32s(addr + 12i32).unwrap(); - *fpu_ip_selector.offset(0isize) = safe_read16(addr + 16i32).unwrap(); - *fpu_opcode.offset(0isize) = safe_read16(addr + 18i32).unwrap(); - *fpu_dp.offset(0isize) = safe_read32s(addr + 20i32).unwrap(); - *fpu_dp_selector.offset(0isize) = safe_read16(addr + 24i32).unwrap() + *fpu_ip = safe_read32s(addr + 12i32).unwrap(); + *fpu_ip_selector = safe_read16(addr + 16i32).unwrap(); + *fpu_opcode = safe_read16(addr + 18i32).unwrap(); + *fpu_dp = safe_read32s(addr + 20i32).unwrap(); + *fpu_dp_selector = safe_read16(addr + 24i32).unwrap() } else { dbg_log!("fldenv16"); @@ -484,11 +484,11 @@ pub unsafe fn fpu_fstenv(mut addr: i32) -> () { safe_write16(addr, *fpu_control_word).unwrap(); safe_write16(addr + 4i32, fpu_load_status_word()).unwrap(); safe_write16(addr + 8i32, fpu_load_tag_word()).unwrap(); - safe_write32(addr + 12i32, *fpu_ip.offset(0isize)).unwrap(); - safe_write16(addr + 16i32, *fpu_ip_selector.offset(0isize)).unwrap(); - safe_write16(addr + 18i32, *fpu_opcode.offset(0isize)).unwrap(); - safe_write32(addr + 20i32, *fpu_dp.offset(0isize)).unwrap(); - safe_write16(addr + 24i32, *fpu_dp_selector.offset(0isize)).unwrap(); + safe_write32(addr + 12i32, *fpu_ip).unwrap(); + safe_write16(addr + 16i32, *fpu_ip_selector).unwrap(); + safe_write16(addr + 18i32, *fpu_opcode).unwrap(); + safe_write32(addr + 20i32, *fpu_dp).unwrap(); + safe_write16(addr + 24i32, *fpu_dp_selector).unwrap(); } else { dbg_log!("fstenv16"); diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index 506367eb..cf416e27 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -1775,7 +1775,7 @@ pub unsafe fn instr32_9A(mut new_ip: i32, mut new_cs: i32) -> () { #[no_mangle] pub unsafe fn instr_9B() -> () { // fwait: check for pending fpu exceptions - if *cr.offset(0isize) & (CR0_MP | CR0_TS) == CR0_MP | CR0_TS { + if *cr & (CR0_MP | CR0_TS) == CR0_MP | CR0_TS { // Note: Different from task_switch_test // Triggers when TS and MP bits are set (EM bit is ignored) trigger_nm(); @@ -1787,7 +1787,7 @@ pub unsafe fn instr_9B() -> () { #[no_mangle] pub unsafe fn instr16_9C() -> () { // pushf - if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { + if 0 != *flags & FLAG_VM && getiopl() < 3i32 { dbg_assert!(*protected_mode); dbg_log!("pushf #gp"); trigger_gp_non_raising(0i32); @@ -1799,7 +1799,7 @@ pub unsafe fn instr16_9C() -> () { #[no_mangle] pub unsafe fn instr32_9C() -> () { // pushf - if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { + if 0 != *flags & FLAG_VM && getiopl() < 3i32 { // trap to virtual 8086 monitor dbg_assert!(*protected_mode); dbg_log!("pushf #gp"); @@ -1813,7 +1813,7 @@ pub unsafe fn instr32_9C() -> () { #[no_mangle] pub unsafe fn instr16_9D() -> () { // popf - if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { + if 0 != *flags & FLAG_VM && getiopl() < 3i32 { dbg_log!("popf #gp"); trigger_gp_non_raising(0i32); return; @@ -1833,7 +1833,7 @@ pub unsafe fn instr16_9D() -> () { #[no_mangle] pub unsafe fn instr32_9D() -> () { // popf - if 0 != *flags.offset(0isize) & FLAG_VM && getiopl() < 3i32 { + if 0 != *flags & FLAG_VM && getiopl() < 3i32 { dbg_log!("popf #gp"); trigger_gp_non_raising(0i32); return; @@ -1847,9 +1847,9 @@ pub unsafe fn instr32_9D() -> () { #[no_mangle] pub unsafe fn instr_9E() -> () { // sahf - *flags.offset(0isize) = *flags.offset(0isize) & !255i32 | *reg8.offset(AH as isize) as i32; - *flags.offset(0isize) = *flags.offset(0isize) & FLAGS_MASK | FLAGS_DEFAULT; - *flags_changed.offset(0isize) &= !255i32; + *flags = *flags & !255i32 | *reg8.offset(AH as isize) as i32; + *flags = *flags & FLAGS_MASK | FLAGS_DEFAULT; + *flags_changed &= !255i32; } #[no_mangle] pub unsafe fn instr_9F() -> () { @@ -2200,7 +2200,7 @@ pub unsafe fn instr32_C1_7_reg(mut r1: i32, mut imm: i32) -> () { pub unsafe fn instr16_C2(mut imm16: i32) -> () { // retn let mut cs: i32 = get_seg_cs(); - *instruction_pointer.offset(0isize) = cs + return_on_pagefault!(pop16()); + *instruction_pointer = cs + return_on_pagefault!(pop16()); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); adjust_stack_reg(imm16); } @@ -2210,14 +2210,14 @@ pub unsafe fn instr32_C2(mut imm16: i32) -> () { let mut cs: i32 = get_seg_cs(); let mut ip: i32 = return_on_pagefault!(pop32s()); dbg_assert!(0 != is_asize_32() as i32 || ip < 65536i32); - *instruction_pointer.offset(0isize) = cs + ip; + *instruction_pointer = cs + ip; adjust_stack_reg(imm16); } #[no_mangle] pub unsafe fn instr16_C3() -> () { // retn let mut cs: i32 = get_seg_cs(); - *instruction_pointer.offset(0isize) = cs + return_on_pagefault!(pop16()); + *instruction_pointer = cs + return_on_pagefault!(pop16()); } #[no_mangle] pub unsafe fn instr32_C3() -> () { @@ -2225,7 +2225,7 @@ pub unsafe fn instr32_C3() -> () { let mut cs: i32 = get_seg_cs(); let mut ip: i32 = return_on_pagefault!(pop32s()); dbg_assert!(0 != is_asize_32() as i32 || ip < 65536i32); - *instruction_pointer.offset(0isize) = cs + ip; + *instruction_pointer = cs + ip; } #[no_mangle] pub unsafe fn instr16_C4_reg(mut _unused1: i32, mut _unused2: i32) -> () { trigger_ud(); } @@ -2975,7 +2975,7 @@ pub unsafe fn instr16_E8(mut imm16: i32) -> () { pub unsafe fn instr32_E8(mut imm32s: i32) -> () { // call return_on_pagefault!(push32(get_real_eip())); - *instruction_pointer.offset(0isize) = *instruction_pointer.offset(0isize) + imm32s; + *instruction_pointer = *instruction_pointer + imm32s; // dbg_assert!(is_asize_32() || get_real_eip() < 0x10000); } #[no_mangle] @@ -2986,7 +2986,7 @@ pub unsafe fn instr16_E9(mut imm16: i32) -> () { #[no_mangle] pub unsafe fn instr32_E9(mut imm32s: i32) -> () { // jmp - *instruction_pointer.offset(0isize) = *instruction_pointer.offset(0isize) + imm32s; + *instruction_pointer = *instruction_pointer + imm32s; dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] @@ -3105,8 +3105,8 @@ pub unsafe fn instr_F4() -> () { hlt_op(); } #[no_mangle] pub unsafe fn instr_F5() -> () { // cmc - *flags.offset(0isize) = (*flags.offset(0isize) | 1i32) ^ getcf() as i32; - *flags_changed.offset(0isize) &= !1i32; + *flags = (*flags | 1i32) ^ getcf() as i32; + *flags_changed &= !1i32; } #[no_mangle] pub unsafe fn instr_F6_0_mem(mut addr: i32, mut imm: i32) -> () { @@ -3345,25 +3345,25 @@ pub unsafe fn instr32_F7_7_reg(mut r1: i32) -> () { #[no_mangle] pub unsafe fn instr_F8() -> () { // clc - *flags.offset(0isize) &= !FLAG_CARRY; - *flags_changed.offset(0isize) &= !1i32; + *flags &= !FLAG_CARRY; + *flags_changed &= !1i32; } #[no_mangle] pub unsafe fn instr_F9() -> () { // stc - *flags.offset(0isize) |= FLAG_CARRY; - *flags_changed.offset(0isize) &= !1i32; + *flags |= FLAG_CARRY; + *flags_changed &= !1i32; } #[no_mangle] pub unsafe fn instr_FA() -> () { // cli - if !*protected_mode || 0 != if 0 != *flags.offset(0isize) & FLAG_VM { + if !*protected_mode || 0 != if 0 != *flags & FLAG_VM { (getiopl() == 3i32) as i32 } else { (getiopl() >= *cpl as i32) as i32 } { - *flags.offset(0isize) &= !FLAG_INTERRUPT; + *flags &= !FLAG_INTERRUPT; } else if 0 != 0i32 * 0i32 && getiopl() < 3i32 && 0 != if 0 != *flags & FLAG_VM { *cr.offset(4isize) & CR4_VME @@ -3381,14 +3381,14 @@ pub unsafe fn instr_FA() -> () { #[no_mangle] pub unsafe fn instr_FB() -> () { // sti - let mut old_if: i32 = *flags.offset(0isize) & FLAG_INTERRUPT; - if !*protected_mode || 0 != if 0 != *flags.offset(0isize) & FLAG_VM { + let mut old_if: i32 = *flags & FLAG_INTERRUPT; + if !*protected_mode || 0 != if 0 != *flags & FLAG_VM { (getiopl() == 3i32) as i32 } else { (getiopl() >= *cpl as i32) as i32 } { - *flags.offset(0isize) |= FLAG_INTERRUPT; + *flags |= FLAG_INTERRUPT; if old_if == 0i32 { handle_irqs(); } @@ -3411,12 +3411,12 @@ pub unsafe fn instr_FB() -> () { #[no_mangle] pub unsafe fn instr_FC() -> () { // cld - *flags.offset(0isize) &= !FLAG_DIRECTION; + *flags &= !FLAG_DIRECTION; } #[no_mangle] pub unsafe fn instr_FD() -> () { // std - *flags.offset(0isize) |= FLAG_DIRECTION; + *flags |= FLAG_DIRECTION; } #[no_mangle] pub unsafe fn instr_FE_0_mem(mut addr: i32) -> () { @@ -3459,7 +3459,7 @@ pub unsafe fn instr16_FF_2_helper(mut data: i32) -> () { // call near let mut cs: i32 = get_seg_cs(); return_on_pagefault!(push16(get_real_eip())); - *instruction_pointer.offset(0isize) = cs + data; + *instruction_pointer = cs + data; dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] @@ -3488,7 +3488,7 @@ pub unsafe fn instr16_FF_3_mem(mut addr: i32) -> () { #[no_mangle] pub unsafe fn instr16_FF_4_helper(mut data: i32) -> () { // jmp near - *instruction_pointer.offset(0isize) = get_seg_cs() + data; + *instruction_pointer = get_seg_cs() + data; dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] @@ -3548,7 +3548,7 @@ pub unsafe fn instr32_FF_2_helper(mut data: i32) -> () { let mut cs: i32 = get_seg_cs(); return_on_pagefault!(push32(get_real_eip())); dbg_assert!(0 != is_asize_32() as i32 || data < 65536i32); - *instruction_pointer.offset(0isize) = cs + data; + *instruction_pointer = cs + data; } #[no_mangle] pub unsafe fn instr32_FF_2_mem(mut addr: i32) -> () { @@ -3582,7 +3582,7 @@ pub unsafe fn instr32_FF_3_mem(mut addr: i32) -> () { pub unsafe fn instr32_FF_4_helper(mut data: i32) -> () { // jmp near dbg_assert!(0 != is_asize_32() as i32 || data < 65536i32); - *instruction_pointer.offset(0isize) = get_seg_cs() + data; + *instruction_pointer = get_seg_cs() + data; } #[no_mangle] pub unsafe fn instr32_FF_4_mem(mut addr: i32) -> () { @@ -4361,6 +4361,6 @@ pub unsafe fn instr16_EB(mut imm8: i32) -> () { #[no_mangle] pub unsafe fn instr32_EB(mut imm8: i32) -> () { // jmp near - *instruction_pointer.offset(0isize) = *instruction_pointer.offset(0isize) + imm8; + *instruction_pointer = *instruction_pointer + imm8; dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 91f691c9..ef8cb1c4 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -67,7 +67,7 @@ const ENABLE_ACPI: bool = false; #[no_mangle] pub unsafe fn instr_0F00_0_mem(mut addr: i32) -> () { // sldt - if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; } @@ -78,7 +78,7 @@ pub unsafe fn instr_0F00_0_mem(mut addr: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F00_0_reg(mut r: i32) -> () { - if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; } @@ -90,7 +90,7 @@ pub unsafe fn instr_0F00_0_reg(mut r: i32) -> () { #[no_mangle] pub unsafe fn instr_0F00_1_mem(mut addr: i32) -> () { // str - if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; } @@ -101,7 +101,7 @@ pub unsafe fn instr_0F00_1_mem(mut addr: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F00_1_reg(mut r: i32) -> () { - if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; } @@ -113,11 +113,11 @@ pub unsafe fn instr_0F00_1_reg(mut r: i32) -> () { #[no_mangle] pub unsafe fn instr_0F00_2_mem(mut addr: i32) -> () { // lldt - if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; } - else if 0 != *cpl.offset(0isize) { + else if 0 != *cpl { trigger_gp_non_raising(0i32); return; } @@ -128,11 +128,11 @@ pub unsafe fn instr_0F00_2_mem(mut addr: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F00_2_reg(mut r: i32) -> () { - if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; } - else if 0 != *cpl.offset(0isize) { + else if 0 != *cpl { trigger_gp_non_raising(0i32); return; } @@ -144,11 +144,11 @@ pub unsafe fn instr_0F00_2_reg(mut r: i32) -> () { #[no_mangle] pub unsafe fn instr_0F00_3_mem(mut addr: i32) -> () { // ltr - if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; } - else if 0 != *cpl.offset(0isize) { + else if 0 != *cpl { trigger_gp_non_raising(0i32); return; } @@ -159,11 +159,11 @@ pub unsafe fn instr_0F00_3_mem(mut addr: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F00_3_reg(mut r: i32) -> () { - if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; } - else if 0 != *cpl.offset(0isize) { + else if 0 != *cpl { trigger_gp_non_raising(0i32); return; } @@ -174,7 +174,7 @@ pub unsafe fn instr_0F00_3_reg(mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F00_4_mem(mut addr: i32) -> () { - if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; } @@ -185,7 +185,7 @@ pub unsafe fn instr_0F00_4_mem(mut addr: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F00_4_reg(mut r: i32) -> () { - if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; } @@ -196,7 +196,7 @@ pub unsafe fn instr_0F00_4_reg(mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F00_5_mem(mut addr: i32) -> () { - if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; } @@ -207,7 +207,7 @@ pub unsafe fn instr_0F00_5_mem(mut addr: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F00_5_reg(mut r: i32) -> () { - if !*protected_mode.offset(0isize) || 0 != vm86_mode() as i32 { + if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; } @@ -228,8 +228,8 @@ pub unsafe fn instr_0F01_0_mem(mut addr: i32) -> () { else { 16777215i32 }; - safe_write16(addr, *gdtr_size.offset(0isize)).unwrap(); - safe_write32(addr + 2i32, *gdtr_offset.offset(0isize) & mask).unwrap(); + safe_write16(addr, *gdtr_size).unwrap(); + safe_write32(addr + 2i32, *gdtr_offset & mask).unwrap(); } #[no_mangle] pub unsafe fn instr_0F01_1_reg(mut r: i32) -> () { trigger_ud(); } @@ -243,15 +243,15 @@ pub unsafe fn instr_0F01_1_mem(mut addr: i32) -> () { else { 16777215i32 }; - safe_write16(addr, *idtr_size.offset(0isize)).unwrap(); - safe_write32(addr + 2i32, *idtr_offset.offset(0isize) & mask).unwrap(); + safe_write16(addr, *idtr_size).unwrap(); + safe_write32(addr + 2i32, *idtr_offset & mask).unwrap(); } #[no_mangle] pub unsafe fn instr_0F01_2_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0F01_2_mem(mut addr: i32) -> () { // lgdt - if 0 != *cpl.offset(0isize) { + if 0 != *cpl { trigger_gp_non_raising(0i32); return; } @@ -264,8 +264,8 @@ pub unsafe fn instr_0F01_2_mem(mut addr: i32) -> () { else { 16777215i32 }; - *gdtr_size.offset(0isize) = size; - *gdtr_offset.offset(0isize) = offset & mask; + *gdtr_size = size; + *gdtr_offset = offset & mask; return; }; } @@ -274,7 +274,7 @@ pub unsafe fn instr_0F01_3_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0F01_3_mem(mut addr: i32) -> () { // lidt - if 0 != *cpl.offset(0isize) { + if 0 != *cpl { trigger_gp_non_raising(0i32); return; } @@ -287,24 +287,24 @@ pub unsafe fn instr_0F01_3_mem(mut addr: i32) -> () { else { 16777215i32 }; - *idtr_size.offset(0isize) = size; - *idtr_offset.offset(0isize) = offset & mask; + *idtr_size = size; + *idtr_offset = offset & mask; return; }; } #[no_mangle] pub unsafe fn instr_0F01_4_reg(mut r: i32) -> () { // smsw - write_reg_osize(r, *cr.offset(0isize)); + write_reg_osize(r, *cr); } #[no_mangle] pub unsafe fn instr_0F01_4_mem(mut addr: i32) -> () { - return_on_pagefault!(safe_write16(addr, *cr.offset(0isize) & 65535i32)); + return_on_pagefault!(safe_write16(addr, *cr & 65535i32)); } #[no_mangle] pub unsafe fn lmsw(mut new_cr0: i32) -> () { - new_cr0 = *cr.offset(0isize) & !15i32 | new_cr0 & 15i32; - if *protected_mode.offset(0isize) { + new_cr0 = *cr & !15i32 | new_cr0 & 15i32; + if *protected_mode { // lmsw cannot be used to switch back new_cr0 |= CR0_PE } @@ -312,7 +312,7 @@ pub unsafe fn lmsw(mut new_cr0: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F01_6_reg(mut r: i32) -> () { - if 0 != *cpl.offset(0isize) { + if 0 != *cpl { trigger_gp_non_raising(0i32); return; } @@ -323,7 +323,7 @@ pub unsafe fn instr_0F01_6_reg(mut r: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F01_6_mem(mut addr: i32) -> () { - if 0 != *cpl.offset(0isize) { + if 0 != *cpl { trigger_gp_non_raising(0i32); return; } @@ -337,7 +337,7 @@ pub unsafe fn instr_0F01_7_reg(mut r: i32) -> () { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0F01_7_mem(mut addr: i32) -> () { // invlpg - if 0 != *cpl.offset(0isize) { + if 0 != *cpl { trigger_gp_non_raising(0i32); return; } @@ -393,7 +393,7 @@ pub unsafe fn instr_0F05() -> () { undefined_instruction(); } #[no_mangle] pub unsafe fn instr_0F06() -> () { // clts - if 0 != *cpl.offset(0isize) { + if 0 != *cpl { dbg_log!("clts #gp"); trigger_gp_non_raising(0i32); } @@ -401,7 +401,7 @@ pub unsafe fn instr_0F06() -> () { if 0 != 0i32 * 0i32 { dbg_log!("clts"); } - *cr.offset(0isize) &= !CR0_TS; + *cr &= !CR0_TS; }; } #[no_mangle] @@ -413,7 +413,7 @@ pub unsafe fn instr_0F08() -> () { } #[no_mangle] pub unsafe fn instr_0F09() -> () { - if 0 != *cpl.offset(0isize) { + if 0 != *cpl { dbg_log!("wbinvd #gp"); trigger_gp_non_raising(0i32); } @@ -759,14 +759,14 @@ pub unsafe fn instr_0F1F_reg(mut r1: i32, mut r2: i32) -> () {} pub unsafe fn instr_0F1F_mem(mut addr: i32, mut r: i32) -> () {} #[no_mangle] pub unsafe fn instr_0F20(mut r: i32, mut creg: i32) -> () { - if 0 != *cpl.offset(0isize) { + if 0 != *cpl { trigger_gp_non_raising(0i32); return; } else { match creg { 0 => { - write_reg32(r, *cr.offset(0isize)); + write_reg32(r, *cr); }, 2 => { write_reg32(r, *cr.offset(2isize)); @@ -787,7 +787,7 @@ pub unsafe fn instr_0F20(mut r: i32, mut creg: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F21(mut r: i32, mut dreg_index: i32) -> () { - if 0 != *cpl.offset(0isize) { + if 0 != *cpl { trigger_gp_non_raising(0i32); return; } @@ -816,7 +816,7 @@ pub unsafe fn instr_0F21(mut r: i32, mut dreg_index: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F22(mut r: i32, mut creg: i32) -> () { - if 0 != *cpl.offset(0isize) { + if 0 != *cpl { trigger_gp_non_raising(0i32); return; } @@ -877,7 +877,7 @@ pub unsafe fn instr_0F22(mut r: i32, mut creg: i32) -> () { } #[no_mangle] pub unsafe fn instr_0F23(mut r: i32, mut dreg_index: i32) -> () { - if 0 != *cpl.offset(0isize) { + if 0 != *cpl { trigger_gp_non_raising(0i32); return; } @@ -1156,7 +1156,7 @@ pub unsafe fn instr_660F2F_mem(addr: i32, r: i32) { #[no_mangle] pub unsafe fn instr_0F30() -> () { // wrmsr - write maschine specific register - if 0 != *cpl.offset(0isize) { + if 0 != *cpl { trigger_gp_non_raising(0i32); return; } @@ -1168,13 +1168,13 @@ pub unsafe fn instr_0F30() -> () { dbg_log!("wrmsr ecx={:x} data={:x}:{:x}", index, high, low); } if index == IA32_SYSENTER_CS { - *sysenter_cs.offset(0isize) = low & 65535i32 + *sysenter_cs = low & 65535i32 } else if index == IA32_SYSENTER_EIP { - *sysenter_eip.offset(0isize) = low + *sysenter_eip = low } else if index == IA32_SYSENTER_ESP { - *sysenter_esp.offset(0isize) = low + *sysenter_esp = low } else if index == IA32_APIC_BASE_MSR { dbg_assert!( @@ -1218,7 +1218,7 @@ pub unsafe fn instr_0F30() -> () { #[no_mangle] pub unsafe fn instr_0F31() -> () { // rdtsc - read timestamp counter - if 0 == *cpl.offset(0isize) || 0 == *cr.offset(4isize) & CR4_TSD { + if 0 == *cpl || 0 == *cr.offset(4isize) & CR4_TSD { let mut tsc: u64 = read_tsc(); *reg32s.offset(EAX as isize) = tsc as i32; *reg32s.offset(EDX as isize) = (tsc >> 32i32) as i32; @@ -1237,7 +1237,7 @@ pub unsafe fn instr_0F31() -> () { #[no_mangle] pub unsafe fn instr_0F32() -> () { // rdmsr - read maschine specific register - if 0 != *cpl.offset(0isize) { + if 0 != *cpl { trigger_gp_non_raising(0i32); return; } @@ -1247,13 +1247,13 @@ pub unsafe fn instr_0F32() -> () { let mut low: i32 = 0i32; let mut high: i32 = 0i32; if index == IA32_SYSENTER_CS { - low = *sysenter_cs.offset(0isize) + low = *sysenter_cs } else if index == IA32_SYSENTER_EIP { - low = *sysenter_eip.offset(0isize) + low = *sysenter_eip } else if index == IA32_SYSENTER_ESP { - low = *sysenter_esp.offset(0isize) + low = *sysenter_esp } else if index == IA32_TIME_STAMP_COUNTER { let mut tsc: u64 = read_tsc(); @@ -1307,53 +1307,53 @@ pub unsafe fn instr_0F33() -> () { #[no_mangle] pub unsafe fn instr_0F34() -> () { // sysenter - let mut seg: i32 = *sysenter_cs.offset(0isize) & 65532i32; - if !*protected_mode.offset(0isize) || seg == 0i32 { + let mut seg: i32 = *sysenter_cs & 65532i32; + if !*protected_mode || seg == 0i32 { trigger_gp_non_raising(0i32); return; } else { - *flags.offset(0isize) &= !FLAG_VM & !FLAG_INTERRUPT; - *instruction_pointer.offset(0isize) = *sysenter_eip.offset(0isize); - *reg32s.offset(ESP as isize) = *sysenter_esp.offset(0isize); + *flags &= !FLAG_VM & !FLAG_INTERRUPT; + *instruction_pointer = *sysenter_eip; + *reg32s.offset(ESP as isize) = *sysenter_esp; *sreg.offset(CS as isize) = seg as u16; *segment_is_null.offset(CS as isize) = 0 != 0i32; *segment_limits.offset(CS as isize) = -1i32 as u32; *segment_offsets.offset(CS as isize) = 0i32; update_cs_size(true); - *cpl.offset(0isize) = 0i32 as u8; + *cpl = 0i32 as u8; cpl_changed(); *sreg.offset(SS as isize) = (seg + 8i32) as u16; *segment_is_null.offset(SS as isize) = 0 != 0i32; *segment_limits.offset(SS as isize) = -1i32 as u32; *segment_offsets.offset(SS as isize) = 0i32; - *stack_size_32.offset(0isize) = 0 != 1i32; + *stack_size_32 = 0 != 1i32; return; }; } #[no_mangle] pub unsafe fn instr_0F35() -> () { // sysexit - let mut seg: i32 = *sysenter_cs.offset(0isize) & 65532i32; - if !*protected_mode.offset(0isize) || 0 != *cpl.offset(0isize) as i32 || seg == 0i32 { + let mut seg: i32 = *sysenter_cs & 65532i32; + if !*protected_mode || 0 != *cpl as i32 || seg == 0i32 { trigger_gp_non_raising(0i32); return; } else { - *instruction_pointer.offset(0isize) = *reg32s.offset(EDX as isize); + *instruction_pointer = *reg32s.offset(EDX as isize); *reg32s.offset(ESP as isize) = *reg32s.offset(ECX as isize); *sreg.offset(CS as isize) = (seg + 16i32 | 3i32) as u16; *segment_is_null.offset(CS as isize) = 0 != 0i32; *segment_limits.offset(CS as isize) = -1i32 as u32; *segment_offsets.offset(CS as isize) = 0i32; update_cs_size(true); - *cpl.offset(0isize) = 3i32 as u8; + *cpl = 3i32 as u8; cpl_changed(); *sreg.offset(SS as isize) = (seg + 24i32 | 3i32) as u16; *segment_is_null.offset(SS as isize) = 0 != 0i32; *segment_limits.offset(SS as isize) = -1i32 as u32; *segment_offsets.offset(SS as isize) = 0i32; - *stack_size_32.offset(0isize) = 0 != 1i32; + *stack_size_32 = 0 != 1i32; return; }; } @@ -3973,18 +3973,18 @@ pub unsafe fn instr_0FC7_1_mem(mut addr: i32) -> () { let mut m64_low: i32 = return_on_pagefault!(safe_read32s(addr)); let mut m64_high: i32 = return_on_pagefault!(safe_read32s(addr + 4i32)); if *reg32s.offset(EAX as isize) == m64_low && *reg32s.offset(EDX as isize) == m64_high { - *flags.offset(0isize) |= FLAG_ZERO; + *flags |= FLAG_ZERO; safe_write32(addr, *reg32s.offset(EBX as isize)).unwrap(); safe_write32(addr + 4i32, *reg32s.offset(ECX as isize)).unwrap(); } else { - *flags.offset(0isize) &= !FLAG_ZERO; + *flags &= !FLAG_ZERO; *reg32s.offset(EAX as isize) = m64_low; *reg32s.offset(EDX as isize) = m64_high; safe_write32(addr, m64_low).unwrap(); safe_write32(addr + 4i32, m64_high).unwrap(); } - *flags_changed.offset(0isize) &= !FLAG_ZERO; + *flags_changed &= !FLAG_ZERO; } #[no_mangle] pub unsafe fn instr_0FC7_6_reg(mut r: i32) -> () { @@ -3995,9 +3995,9 @@ pub unsafe fn instr_0FC7_6_reg(mut r: i32) -> () { rand = get_rand_int() } write_reg_osize(r, rand); - *flags.offset(0isize) &= !FLAGS_ALL; - *flags.offset(0isize) |= has_rand; - *flags_changed.offset(0isize) = 0i32; + *flags &= !FLAGS_ALL; + *flags |= has_rand; + *flags_changed = 0i32; } #[no_mangle] pub unsafe fn instr_0FC7_6_mem(mut addr: i32) -> () { trigger_ud(); } From fc0fd368c41e0247751610cce1762211a2badb00 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Aug 2018 22:26:54 -0500 Subject: [PATCH 1257/2137] c2rust cleanup: Enable unused_unsafe warning and a few warnings --- src/rust/cpu2/cpu.rs | 36 +++++++++--------- src/rust/cpu2/mod.rs | 2 +- src/rust/cpu2/profiler.rs | 80 +++++++++++++++++++-------------------- 3 files changed, 57 insertions(+), 61 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 2119bb08..938f41c1 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -79,25 +79,23 @@ pub const FLAG_VIF: i32 = 1i32 << 19i32; pub const FLAG_VIP: i32 = 1i32 << 20i32; pub const FLAG_ID: i32 = 1i32 << 21i32; pub const FLAGS_DEFAULT: i32 = 1i32 << 1i32; -pub const FLAGS_MASK: i32 = unsafe { - FLAG_CARRY - | FLAG_PARITY - | FLAG_ADJUST - | FLAG_ZERO - | FLAG_SIGN - | FLAG_TRAP - | FLAG_INTERRUPT - | FLAG_DIRECTION - | FLAG_OVERFLOW - | FLAG_IOPL - | FLAG_NT - | FLAG_RF - | FLAG_VM - | FLAG_AC - | FLAG_VIF - | FLAG_VIP - | FLAG_ID -}; +pub const FLAGS_MASK: i32 = FLAG_CARRY + | FLAG_PARITY + | FLAG_ADJUST + | FLAG_ZERO + | FLAG_SIGN + | FLAG_TRAP + | FLAG_INTERRUPT + | FLAG_DIRECTION + | FLAG_OVERFLOW + | FLAG_IOPL + | FLAG_NT + | FLAG_RF + | FLAG_VM + | FLAG_AC + | FLAG_VIF + | FLAG_VIP + | FLAG_ID; pub const FLAGS_ALL: i32 = FLAG_CARRY | FLAG_PARITY | FLAG_ADJUST | FLAG_ZERO | FLAG_SIGN | FLAG_OVERFLOW; pub const OPSIZE_8: i32 = 7i32; diff --git a/src/rust/cpu2/mod.rs b/src/rust/cpu2/mod.rs index 5c1a564c..e4b212df 100644 --- a/src/rust/cpu2/mod.rs +++ b/src/rust/cpu2/mod.rs @@ -1,4 +1,4 @@ -#![allow(unused_assignments, unused_variables, unused_unsafe)] +#![allow(unused_assignments, unused_variables)] #[macro_use] pub mod imports; diff --git a/src/rust/cpu2/profiler.rs b/src/rust/cpu2/profiler.rs index f798a56a..bb206252 100644 --- a/src/rust/cpu2/profiler.rs +++ b/src/rust/cpu2/profiler.rs @@ -47,47 +47,45 @@ pub const S_SAFE_READ32_SLOW_NOT_USER: StatName = 18; pub const S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE: StatName = 24; pub const S_NONFAULTING_OPTIMIZATION: StatName = 32; #[no_mangle] -pub static mut profiler_stat_arr: [profiler_stat; 37] = unsafe { - [ - profiler_stat { count: 0i32 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - ] -}; +pub static mut profiler_stat_arr: [profiler_stat; 37] = [ + profiler_stat { count: 0i32 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, + profiler_stat { count: 0 }, +]; #[no_mangle] pub unsafe fn profiler_init() -> () { let mut i: u32 = 0i32 as u32; From 6b8bf885a2b113041ba99079ae7ef374a40f1207 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 28 Aug 2018 22:48:53 -0500 Subject: [PATCH 1258/2137] c2rust cleanup: Enable unused_assignments and unused_variables warnings and fix them --- src/rust/cpu2/cpu.rs | 24 +++----- src/rust/cpu2/fpu.rs | 6 +- src/rust/cpu2/instructions.rs | 7 ++- src/rust/cpu2/instructions_0f.rs | 3 +- src/rust/cpu2/mod.rs | 2 - src/rust/cpu2/modrm.rs | 8 +-- src/rust/cpu2/string.rs | 102 +++++++++++++++---------------- 7 files changed, 74 insertions(+), 78 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 938f41c1..2ce88779 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -271,10 +271,10 @@ pub unsafe fn do_page_translation( mut user: bool, ) -> Result { let mut can_write: bool = 0 != 1i32; - let mut global: bool = false; + let mut global; let mut allow_user: bool = 0 != 1i32; let mut page: i32 = (addr as u32 >> 12i32) as i32; - let mut high: i32 = 0; + let mut high; if *cr & CR0_PG == 0i32 { // paging disabled high = (addr as u32 & 4294963200u32) as i32; @@ -576,9 +576,6 @@ pub unsafe fn tlb_set_has_code(mut physical_page: u32, mut has_code: bool) -> () #[no_mangle] pub unsafe fn check_tlb_invariants() -> () { - let mut physical_page: u32 = 0; - let mut entry_has_code: bool = false; - let mut has_code: bool = false; if !CHECK_TLB_INVARIANTS { return; } @@ -755,18 +752,15 @@ pub unsafe fn run_instruction0f_32(opcode: i32) { ::gen::interpreter0f_32::run(o pub unsafe fn cycle_internal() -> () { profiler_stat_increment(S_CYCLE_INTERNAL); if true { - let mut wasm_table_index: u16 = 0; - let mut initial_tsc: i32 = 0; - let mut initial_state: u16 = 0; *previous_ip = *instruction_pointer; let mut phys_addr: u32 = return_on_pagefault!(get_phys_eip()) as u32; let mut state_flags: CachedStateFlags = pack_current_state_flags(); let mut entry: u32 = ::c_api::jit_find_cache_entry(phys_addr, state_flags as u32); if 0 != entry { profiler_stat_increment(S_RUN_FROM_CACHE); - initial_tsc = *timestamp_counter as i32; - wasm_table_index = (entry & 65535i32 as u32) as u16; - initial_state = (entry >> 16i32) as u16; + let initial_tsc = *timestamp_counter as i32; + let wasm_table_index = (entry & 65535i32 as u32) as u16; + let initial_state = (entry >> 16i32) as u16; call_indirect1( (wasm_table_index as u32).wrapping_add(WASM_TABLE_OFFSET as u32) as i32, initial_state, @@ -944,7 +938,7 @@ pub unsafe fn virt_boundary_read16(mut low: i32, mut high: i32) -> i32 { pub unsafe fn virt_boundary_read32s(mut low: i32, mut high: i32) -> i32 { dbg_assert!(low & 4095i32 >= 4093i32); dbg_assert!(high - 3i32 & 4095i32 == low & 4095i32); - let mut mid: i32 = 0i32; + let mut mid; if 0 != low & 1i32 { if 0 != low & 2i32 { // 0xFFF @@ -1110,28 +1104,26 @@ pub unsafe fn safe_read32s_slow_jit(addr: i32) -> i32 { } pub unsafe fn safe_read64s(mut addr: i32) -> Result { - let mut addr_phys: i32 = 0; let mut x: reg64 = reg64 { i8_0: [0; 8] }; if addr & 4095i32 > 4096i32 - 8i32 { x.u32_0[0usize] = safe_read32s(addr)? as u32; x.u32_0[1usize] = safe_read32s(addr + 4i32)? as u32 } else { - addr_phys = translate_address_read(addr)? as i32; + let addr_phys = translate_address_read(addr)? as i32; x.u64_0[0usize] = read64s(addr_phys as u32) as u64 } Ok(x) } pub unsafe fn safe_read128s(mut addr: i32) -> Result { - let mut addr_phys: i32 = 0; let mut x: reg128 = reg128 { i8_0: [0; 16] }; if addr & 4095i32 > 4096i32 - 16i32 { x.u64_0[0usize] = safe_read64s(addr)?.u64_0[0usize]; x.u64_0[1usize] = safe_read64s(addr + 8i32)?.u64_0[0usize] } else { - addr_phys = translate_address_read(addr)? as i32; + let addr_phys = translate_address_read(addr)? as i32; x = read128(addr_phys as u32) } Ok(x) diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 4f25109d..9956a0e8 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -303,7 +303,7 @@ pub unsafe fn fpu_fistm32p(mut addr: i32) -> () { #[no_mangle] pub unsafe fn fpu_fistm64p(mut addr: i32) -> () { let mut st0: f64 = fpu_integer_round(fpu_get_st0()); - let mut value: i64 = 0; + let mut value; if st0 < TWO_POW_63 && st0 >= -TWO_POW_63 { value = st0 as i64 } @@ -443,8 +443,8 @@ pub unsafe fn fpu_store_m80(mut addr: u32, mut n: f64) -> () { let mut sign: u8 = (double_int_view.u8_0[7usize] as i32 & 128i32) as u8; let mut exponent: i32 = (double_int_view.u8_0[7usize] as i32 & 127i32) << 4i32 | double_int_view.u8_0[6usize] as i32 >> 4i32; - let mut low: i32 = 0; - let mut high: i32 = 0; + let mut low; + let mut high; if exponent == 2047i32 { // all bits set (NaN and infinity) exponent = 32767i32; diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index cf416e27..dc62b1e2 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -1,4 +1,9 @@ -#![allow(mutable_transmutes, non_snake_case, unused_mut)] +#![allow( + mutable_transmutes, + non_snake_case, + unused_mut, + unused_variables, +)] extern "C" { #[no_mangle] diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index ef8cb1c4..4fb8ce6d 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -2,7 +2,8 @@ mutable_transmutes, non_snake_case, non_upper_case_globals, - unused_mut + unused_mut, + unused_variables, )] extern "C" { diff --git a/src/rust/cpu2/mod.rs b/src/rust/cpu2/mod.rs index e4b212df..877331e6 100644 --- a/src/rust/cpu2/mod.rs +++ b/src/rust/cpu2/mod.rs @@ -1,5 +1,3 @@ -#![allow(unused_assignments, unused_variables)] - #[macro_use] pub mod imports; diff --git a/src/rust/cpu2/modrm.rs b/src/rust/cpu2/modrm.rs index 97043c87..a7ad55c0 100644 --- a/src/rust/cpu2/modrm.rs +++ b/src/rust/cpu2/modrm.rs @@ -136,12 +136,12 @@ pub unsafe fn resolve_modrm32_(mut modrm_byte: i32) -> Result { }) } unsafe fn resolve_sib(mut mod_0: bool) -> Result { - let mut s: u8 = 0; + let mut s; let mut sib_byte: u8 = read_imm8()? as u8; let mut r: u8 = (sib_byte as i32 & 7i32) as u8; let mut m: u8 = (sib_byte as i32 >> 3i32 & 7i32) as u8; - let mut base: i32 = 0; - let mut seg: i32 = 0; + let mut base; + let mut seg; if r as i32 == 4i32 { base = *reg32s.offset(ESP as isize); seg = SS @@ -160,7 +160,7 @@ unsafe fn resolve_sib(mut mod_0: bool) -> Result { base = *reg32s.offset(r as isize); seg = DS } - let mut offset: i32 = 0; + let mut offset; if m as i32 == 4i32 { offset = 0i32 } diff --git a/src/rust/cpu2/string.rs b/src/rust/cpu2/string.rs index c22f7630..02b51c7c 100644 --- a/src/rust/cpu2/string.rs +++ b/src/rust/cpu2/string.rs @@ -61,7 +61,7 @@ pub unsafe fn movsb_rep() -> () { return; } else { - let mut cont: i32 = 0i32; + let mut cont; let mut start_count: i32 = count; let mut cycle_counter: i32 = string_get_cycle_count2(size, src, dest); let mut phys_src: i32 = return_on_pagefault!(translate_address_read(src)) as i32; @@ -107,7 +107,7 @@ pub unsafe fn movsb_no_rep() -> () { } #[no_mangle] pub unsafe fn movsw_rep() -> () { - let mut diff: i32 = 0; + let mut diff; let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -121,7 +121,7 @@ pub unsafe fn movsw_rep() -> () { return; } else { - let mut cont: i32 = 0i32; + let mut cont; let mut start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 1i32 && 0 == src & 1i32 { @@ -189,7 +189,7 @@ pub unsafe fn movsw_no_rep() -> () { } #[no_mangle] pub unsafe fn movsd_rep() -> () { - let mut diff: i32 = 0; + let mut diff; let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -203,7 +203,7 @@ pub unsafe fn movsd_rep() -> () { return; } else { - let mut cont: i32 = 0i32; + let mut cont; let mut start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 3i32 && 0 == src & 3i32 { @@ -273,8 +273,8 @@ pub unsafe fn movsd_no_rep() -> () { pub unsafe fn cmpsb_rep(mut prefix_flag: i32) -> () { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut data_src: i32 = 0; - let mut data_dest: i32 = 0; + let mut data_src; + let mut data_dest; let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1i32 } @@ -286,7 +286,7 @@ pub unsafe fn cmpsb_rep(mut prefix_flag: i32) -> () { return; } else { - let mut cont: i32 = 0i32; + let mut cont; let mut start_count: i32 = count; let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; let mut cycle_counter: i32 = string_get_cycle_count2(size, src, dest); @@ -323,8 +323,8 @@ pub unsafe fn cmpsb_rep(mut prefix_flag: i32) -> () { pub unsafe fn cmpsb_no_rep() -> () { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut data_src: i32 = 0; - let mut data_dest: i32 = 0; + let mut data_src; + let mut data_dest; let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1i32 } @@ -339,11 +339,11 @@ pub unsafe fn cmpsb_no_rep() -> () { } #[no_mangle] pub unsafe fn cmpsw_rep(mut prefix_flag: i32) -> () { - let mut diff: i32 = 0; + let mut diff; let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut data_src: i32 = 0; - let mut data_dest: i32 = 0; + let mut data_src; + let mut data_dest; let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2i32 } @@ -355,7 +355,7 @@ pub unsafe fn cmpsw_rep(mut prefix_flag: i32) -> () { return; } else { - let mut cont: i32 = 0i32; + let mut cont; let mut start_count: i32 = count; let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; @@ -416,8 +416,8 @@ pub unsafe fn cmpsw_rep(mut prefix_flag: i32) -> () { pub unsafe fn cmpsw_no_rep() -> () { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut data_src: i32 = 0; - let mut data_dest: i32 = 0; + let mut data_src; + let mut data_dest; let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2i32 } @@ -432,11 +432,11 @@ pub unsafe fn cmpsw_no_rep() -> () { } #[no_mangle] pub unsafe fn cmpsd_rep(mut prefix_flag: i32) -> () { - let mut diff: i32 = 0; + let mut diff; let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut data_src: i32 = 0; - let mut data_dest: i32 = 0; + let mut data_src; + let mut data_dest; let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4i32 } @@ -448,7 +448,7 @@ pub unsafe fn cmpsd_rep(mut prefix_flag: i32) -> () { return; } else { - let mut cont: i32 = 0i32; + let mut cont; let mut start_count: i32 = count; let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; @@ -509,8 +509,8 @@ pub unsafe fn cmpsd_rep(mut prefix_flag: i32) -> () { pub unsafe fn cmpsd_no_rep() -> () { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut data_src: i32 = 0; - let mut data_dest: i32 = 0; + let mut data_src; + let mut data_dest; let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4i32 } @@ -538,7 +538,7 @@ pub unsafe fn stosb_rep() -> () { return; } else { - let mut cont: i32 = 0i32; + let mut cont; let mut start_count: i32 = count; let mut cycle_counter: i32 = string_get_cycle_count(size, dest); let mut phys_dest: i32 = return_on_pagefault!(translate_address_write(dest)) as i32; @@ -580,7 +580,7 @@ pub unsafe fn stosb_no_rep() -> () { } #[no_mangle] pub unsafe fn stosw_rep() -> () { - let mut diff: i32 = 0; + let mut diff; let mut data: i32 = *reg16.offset(AX as isize) as i32; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -594,7 +594,7 @@ pub unsafe fn stosw_rep() -> () { return; } else { - let mut cont: i32 = 0i32; + let mut cont; let mut start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 1i32 { @@ -655,7 +655,7 @@ pub unsafe fn stosw_no_rep() -> () { } #[no_mangle] pub unsafe fn stosd_rep() -> () { - let mut diff: i32 = 0; + let mut diff; let mut data: i32 = *reg32s.offset(EAX as isize); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -669,7 +669,7 @@ pub unsafe fn stosd_rep() -> () { return; } else { - let mut cont: i32 = 0i32; + let mut cont; let mut start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 3i32 { @@ -742,7 +742,7 @@ pub unsafe fn lodsb_rep() -> () { return; } else { - let mut cont: i32 = 0i32; + let mut cont; let mut start_count: i32 = count; let mut cycle_counter: i32 = string_get_cycle_count(size, src); let mut phys_src: i32 = return_on_pagefault!(translate_address_read(src)) as i32; @@ -795,7 +795,7 @@ pub unsafe fn lodsw_rep() -> () { return; } else { - let mut cont: bool = 0 != 0i32; + let mut cont; let mut cycle_counter: u32 = MAX_COUNT_PER_CYCLE as u32; loop { *reg16.offset(AX as isize) = return_on_pagefault!(safe_read16(src)) as u16; @@ -841,7 +841,7 @@ pub unsafe fn lodsd_rep() -> () { return; } else { - let mut cont: i32 = 0i32; + let mut cont; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; loop { *reg32s.offset(EAX as isize) = return_on_pagefault!(safe_read32s(src)); @@ -882,14 +882,14 @@ pub unsafe fn scasb_rep(mut prefix_flag: i32) -> () { else { 1i32 }; - let mut data_dest: i32 = 0; + let mut data_dest; let mut data_src: i32 = *reg8.offset(AL as isize) as i32; let mut count: i32 = get_reg_asize(ECX); if count == 0i32 { return; } else { - let mut cont: i32 = 0i32; + let mut cont; let mut start_count: i32 = count; let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; let mut cycle_counter: i32 = string_get_cycle_count(size, dest); @@ -927,7 +927,7 @@ pub unsafe fn scasb_no_rep() -> () { else { 1i32 }; - let mut data_dest: i32 = 0; + let mut data_dest; let mut data_src: i32 = *reg8.offset(AL as isize) as i32; data_dest = return_on_pagefault!(safe_read8(dest)); add_reg_asize(EDI, size); @@ -935,7 +935,7 @@ pub unsafe fn scasb_no_rep() -> () { } #[no_mangle] pub unsafe fn scasw_rep(mut prefix_flag: i32) -> () { - let mut diff: i32 = 0; + let mut diff; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2i32 @@ -943,14 +943,14 @@ pub unsafe fn scasw_rep(mut prefix_flag: i32) -> () { else { 2i32 }; - let mut data_dest: i32 = 0; + let mut data_dest; let mut data_src: i32 = *reg16.offset(AL as isize) as i32; let mut count: i32 = get_reg_asize(ECX); if count == 0i32 { return; } else { - let mut cont: i32 = 0i32; + let mut cont; let mut start_count: i32 = count; let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; @@ -1008,7 +1008,7 @@ pub unsafe fn scasw_no_rep() -> () { else { 2i32 }; - let mut data_dest: i32 = 0; + let mut data_dest; let mut data_src: i32 = *reg16.offset(AL as isize) as i32; data_dest = return_on_pagefault!(safe_read16(dest)); add_reg_asize(EDI, size); @@ -1016,7 +1016,7 @@ pub unsafe fn scasw_no_rep() -> () { } #[no_mangle] pub unsafe fn scasd_rep(mut prefix_flag: i32) -> () { - let mut diff: i32 = 0; + let mut diff; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4i32 @@ -1024,14 +1024,14 @@ pub unsafe fn scasd_rep(mut prefix_flag: i32) -> () { else { 4i32 }; - let mut data_dest: i32 = 0; + let mut data_dest; let mut data_src: i32 = *reg32s.offset(EAX as isize); let mut count: i32 = get_reg_asize(ECX); if count == 0i32 { return; } else { - let mut cont: i32 = 0i32; + let mut cont; let mut start_count: i32 = count; let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; @@ -1089,7 +1089,7 @@ pub unsafe fn scasd_no_rep() -> () { else { 4i32 }; - let mut data_dest: i32 = 0; + let mut data_dest; let mut data_src: i32 = *reg32s.offset(EAX as isize); data_dest = return_on_pagefault!(safe_read32s(dest)); add_reg_asize(EDI, size); @@ -1114,7 +1114,7 @@ pub unsafe fn insb_rep() -> () { return; } else { - let mut cont: i32 = 0i32; + let mut cont; let mut start_count: i32 = count; let mut cycle_counter: i32 = string_get_cycle_count(size, dest); let mut phys_dest: i32 = return_on_pagefault!(translate_address_write(dest)) as i32; @@ -1165,7 +1165,7 @@ pub unsafe fn insb_no_rep() -> () { } #[no_mangle] pub unsafe fn insw_rep() -> () { - let mut diff: i32 = 0; + let mut diff; let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 2i32) { return; @@ -1183,7 +1183,7 @@ pub unsafe fn insw_rep() -> () { return; } else { - let mut cont: i32 = 0i32; + let mut cont; let mut start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 1i32 { @@ -1254,7 +1254,7 @@ pub unsafe fn insw_no_rep() -> () { } #[no_mangle] pub unsafe fn insd_rep() -> () { - let mut diff: i32 = 0; + let mut diff; let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 4i32) { return; @@ -1272,7 +1272,7 @@ pub unsafe fn insd_rep() -> () { return; } else { - let mut cont: i32 = 0i32; + let mut cont; let mut start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 3i32 { @@ -1360,7 +1360,7 @@ pub unsafe fn outsb_rep() -> () { return; } else { - let mut cont: i32 = 0i32; + let mut cont; let mut start_count: i32 = count; let mut cycle_counter: i32 = string_get_cycle_count(size, src); let mut phys_src: i32 = return_on_pagefault!(translate_address_read(src)) as i32; @@ -1410,7 +1410,7 @@ pub unsafe fn outsb_no_rep() -> () { } #[no_mangle] pub unsafe fn outsw_rep() -> () { - let mut diff: i32 = 0; + let mut diff; let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 2i32) { return; @@ -1428,7 +1428,7 @@ pub unsafe fn outsw_rep() -> () { return; } else { - let mut cont: i32 = 0i32; + let mut cont; let mut start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == src & 1i32 { @@ -1497,7 +1497,7 @@ pub unsafe fn outsw_no_rep() -> () { } #[no_mangle] pub unsafe fn outsd_rep() -> () { - let mut diff: i32 = 0; + let mut diff; let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 4i32) { return; @@ -1515,7 +1515,7 @@ pub unsafe fn outsd_rep() -> () { return; } else { - let mut cont: i32 = 0i32; + let mut cont; let mut start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == src & 3i32 { From cb80830881400cf284b09bf1a42bfe26254efdee Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 29 Aug 2018 12:13:54 -0500 Subject: [PATCH 1259/2137] c2rust cleanup: Enable mutable_transmutes warnings --- src/rust/cpu2/arith.rs | 2 +- src/rust/cpu2/cpu.rs | 2 +- src/rust/cpu2/fpu.rs | 2 +- src/rust/cpu2/global_pointers.rs | 2 +- src/rust/cpu2/instructions.rs | 7 +------ src/rust/cpu2/instructions_0f.rs | 1 - src/rust/cpu2/memory.rs | 2 +- src/rust/cpu2/misc_instr.rs | 2 +- src/rust/cpu2/modrm.rs | 2 +- src/rust/cpu2/profiler.rs | 2 +- src/rust/cpu2/sse_instr.rs | 2 +- src/rust/cpu2/string.rs | 2 +- 12 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/rust/cpu2/arith.rs b/src/rust/cpu2/arith.rs index 2586c57d..310809da 100644 --- a/src/rust/cpu2/arith.rs +++ b/src/rust/cpu2/arith.rs @@ -1,4 +1,4 @@ -#![allow(mutable_transmutes, unused_mut)] +#![allow(unused_mut)] use cpu2::cpu::*; use cpu2::global_pointers::*; diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 2ce88779..9e8570e9 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1,4 +1,4 @@ -#![allow(mutable_transmutes, non_upper_case_globals, unused_mut)] +#![allow(non_upper_case_globals, unused_mut)] extern "C" { #[no_mangle] diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 9956a0e8..0fb66eba 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -1,4 +1,4 @@ -#![allow(mutable_transmutes, unused_mut)] +#![allow(unused_mut)] use cpu2::cpu::*; use cpu2::global_pointers::*; diff --git a/src/rust/cpu2/global_pointers.rs b/src/rust/cpu2/global_pointers.rs index ec33a7d3..d2706e7d 100644 --- a/src/rust/cpu2/global_pointers.rs +++ b/src/rust/cpu2/global_pointers.rs @@ -1,4 +1,4 @@ -#![allow(mutable_transmutes, non_upper_case_globals, unused_mut)] +#![allow(non_upper_case_globals, unused_mut)] use cpu2::cpu::{reg128, reg64}; diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index dc62b1e2..e333342b 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -1,9 +1,4 @@ -#![allow( - mutable_transmutes, - non_snake_case, - unused_mut, - unused_variables, -)] +#![allow(non_snake_case, unused_mut, unused_variables,)] extern "C" { #[no_mangle] diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 4fb8ce6d..5db03896 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -1,5 +1,4 @@ #![allow( - mutable_transmutes, non_snake_case, non_upper_case_globals, unused_mut, diff --git a/src/rust/cpu2/memory.rs b/src/rust/cpu2/memory.rs index bdc30d61..4ce7347a 100644 --- a/src/rust/cpu2/memory.rs +++ b/src/rust/cpu2/memory.rs @@ -1,4 +1,4 @@ -#![allow(mutable_transmutes, unused_mut)] +#![allow(unused_mut)] extern "C" { #[no_mangle] diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index 30326d61..08f4337a 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -1,4 +1,4 @@ -#![allow(mutable_transmutes, unused_mut)] +#![allow(unused_mut)] use cpu2::cpu::*; use cpu2::fpu::{fpu_load_m80, fpu_load_status_word, fpu_set_status_word, fpu_store_m80}; diff --git a/src/rust/cpu2/modrm.rs b/src/rust/cpu2/modrm.rs index a7ad55c0..9c86bfd0 100644 --- a/src/rust/cpu2/modrm.rs +++ b/src/rust/cpu2/modrm.rs @@ -1,4 +1,4 @@ -#![allow(mutable_transmutes, unused_mut)] +#![allow(unused_mut)] use cpu2::cpu::*; use cpu2::global_pointers::*; diff --git a/src/rust/cpu2/profiler.rs b/src/rust/cpu2/profiler.rs index bb206252..8ea1afc1 100644 --- a/src/rust/cpu2/profiler.rs +++ b/src/rust/cpu2/profiler.rs @@ -1,4 +1,4 @@ -#![allow(mutable_transmutes, unused_mut)] +#![allow(unused_mut)] pub const S_SAFE_WRITE32_SLOW_NOT_VALID: StatName = 22; pub const S_SAFE_WRITE32_SLOW_NOT_USER: StatName = 23; diff --git a/src/rust/cpu2/sse_instr.rs b/src/rust/cpu2/sse_instr.rs index 6cbf4e95..84949411 100644 --- a/src/rust/cpu2/sse_instr.rs +++ b/src/rust/cpu2/sse_instr.rs @@ -1,4 +1,4 @@ -#![allow(mutable_transmutes, unused_mut)] +#![allow(unused_mut)] use cpu2::cpu::*; diff --git a/src/rust/cpu2/string.rs b/src/rust/cpu2/string.rs index 02b51c7c..f0b3e732 100644 --- a/src/rust/cpu2/string.rs +++ b/src/rust/cpu2/string.rs @@ -1,4 +1,4 @@ -#![allow(mutable_transmutes, non_upper_case_globals, unused_mut)] +#![allow(non_upper_case_globals, unused_mut)] extern "C" { #[no_mangle] From b5ed5f7c5be05e58f2a317a6b31737ad4fc69628 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 29 Aug 2018 12:18:20 -0500 Subject: [PATCH 1260/2137] c2rust cleanup: Remove -> () --- src/rust/cpu2/arith.rs | 58 +- src/rust/cpu2/cpu.rs | 86 +- src/rust/cpu2/fpu.rs | 116 +- src/rust/cpu2/instructions.rs | 1970 ++++++++++++------------ src/rust/cpu2/instructions_0f.rs | 2420 ++++++++++++++---------------- src/rust/cpu2/memory.rs | 14 +- src/rust/cpu2/misc_instr.rs | 44 +- src/rust/cpu2/profiler.rs | 8 +- src/rust/cpu2/sse_instr.rs | 54 +- src/rust/cpu2/string.rs | 84 +- 10 files changed, 2286 insertions(+), 2568 deletions(-) diff --git a/src/rust/cpu2/arith.rs b/src/rust/cpu2/arith.rs index 310809da..5d3ecbf9 100644 --- a/src/rust/cpu2/arith.rs +++ b/src/rust/cpu2/arith.rs @@ -78,11 +78,11 @@ pub unsafe fn sbb16(mut x: i32, mut y: i32) -> i32 { return sbb(x, y, OPSIZE_16) #[no_mangle] pub unsafe fn sbb32(mut x: i32, mut y: i32) -> i32 { return sbb(x, y, OPSIZE_32); } #[no_mangle] -pub unsafe fn cmp8(mut x: i32, mut y: i32) -> () { sub(x, y, OPSIZE_8); } +pub unsafe fn cmp8(mut x: i32, mut y: i32) { sub(x, y, OPSIZE_8); } #[no_mangle] -pub unsafe fn cmp16(mut x: i32, mut y: i32) -> () { sub(x, y, OPSIZE_16); } +pub unsafe fn cmp16(mut x: i32, mut y: i32) { sub(x, y, OPSIZE_16); } #[no_mangle] -pub unsafe fn cmp32(mut x: i32, mut y: i32) -> () { sub(x, y, OPSIZE_32); } +pub unsafe fn cmp32(mut x: i32, mut y: i32) { sub(x, y, OPSIZE_32); } #[no_mangle] pub unsafe fn inc(mut dest_operand: i32, mut op_size: i32) -> i32 { *flags = *flags & !1i32 | getcf() as i32; @@ -137,7 +137,7 @@ pub unsafe fn neg16(mut x: i32) -> i32 { return neg(x, OPSIZE_16); } #[no_mangle] pub unsafe fn neg32(mut x: i32) -> i32 { return neg(x, OPSIZE_32); } #[no_mangle] -pub unsafe fn mul8(mut source_operand: i32) -> () { +pub unsafe fn mul8(mut source_operand: i32) { let mut result: i32 = source_operand * *reg8.offset(AL as isize) as i32; *reg16.offset(AX as isize) = result as u16; *last_result = result & 255i32; @@ -151,7 +151,7 @@ pub unsafe fn mul8(mut source_operand: i32) -> () { *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; } #[no_mangle] -pub unsafe fn imul8(mut source_operand: i32) -> () { +pub unsafe fn imul8(mut source_operand: i32) { let mut result: i32 = source_operand * *reg8s.offset(AL as isize) as i32; *reg16.offset(AX as isize) = result as u16; *last_result = result & 255i32; @@ -165,7 +165,7 @@ pub unsafe fn imul8(mut source_operand: i32) -> () { *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; } #[no_mangle] -pub unsafe fn mul16(mut source_operand: u32) -> () { +pub unsafe fn mul16(mut source_operand: u32) { let mut result: u32 = source_operand.wrapping_mul(*reg16.offset(AX as isize) as u32); let mut high_result: u32 = result >> 16i32; *reg16.offset(AX as isize) = result as u16; @@ -181,7 +181,7 @@ pub unsafe fn mul16(mut source_operand: u32) -> () { *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; } #[no_mangle] -pub unsafe fn imul16(mut source_operand: i32) -> () { +pub unsafe fn imul16(mut source_operand: i32) { let mut result: i32 = source_operand * *reg16s.offset(AX as isize) as i32; *reg16.offset(AX as isize) = result as u16; *reg16.offset(DX as isize) = (result >> 16i32) as u16; @@ -212,7 +212,7 @@ pub unsafe fn imul_reg16(mut operand1: i32, mut operand2: i32) -> i32 { return result; } #[no_mangle] -pub unsafe fn mul32(mut source_operand: i32) -> () { +pub unsafe fn mul32(mut source_operand: i32) { let mut dest_operand: i32 = *reg32s.offset(EAX as isize); let mut result: u64 = (dest_operand as u32 as u64).wrapping_mul(source_operand as u32 as u64); let mut result_low: i32 = result as i32; @@ -230,7 +230,7 @@ pub unsafe fn mul32(mut source_operand: i32) -> () { *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; } #[no_mangle] -pub unsafe fn imul32(mut source_operand: i32) -> () { +pub unsafe fn imul32(mut source_operand: i32) { let mut dest_operand: i32 = *reg32s.offset(EAX as isize); let mut result: i64 = dest_operand as i64 * source_operand as i64; let mut result_low: i32 = result as i32; @@ -282,7 +282,7 @@ pub unsafe fn xadd32(mut source_operand: i32, mut reg: i32) -> i32 { return add(source_operand, tmp, OPSIZE_32); } #[no_mangle] -pub unsafe fn bcd_daa() -> () { +pub unsafe fn bcd_daa() { let mut old_al: i32 = *reg8.offset(AL as isize) as i32; let mut old_cf: i32 = getcf() as i32; let mut old_af: i32 = getaf() as i32; @@ -302,7 +302,7 @@ pub unsafe fn bcd_daa() -> () { *flags_changed = FLAGS_ALL & !1i32 & !FLAG_ADJUST & !FLAG_OVERFLOW; } #[no_mangle] -pub unsafe fn bcd_das() -> () { +pub unsafe fn bcd_das() { let mut old_al: i32 = *reg8.offset(AL as isize) as i32; let mut old_cf: i32 = getcf() as i32; *flags &= !1i32; @@ -325,7 +325,7 @@ pub unsafe fn bcd_das() -> () { *flags_changed = FLAGS_ALL & !1i32 & !FLAG_ADJUST & !FLAG_OVERFLOW; } #[no_mangle] -pub unsafe fn bcd_aad(mut imm8: i32) -> () { +pub unsafe fn bcd_aad(mut imm8: i32) { let mut result: i32 = *reg8.offset(AL as isize) as i32 + *reg8.offset(AH as isize) as i32 * imm8; *last_result = result & 255i32; @@ -338,7 +338,7 @@ pub unsafe fn bcd_aad(mut imm8: i32) -> () { }; } #[no_mangle] -pub unsafe fn bcd_aam(mut imm8: i32) -> () { +pub unsafe fn bcd_aam(mut imm8: i32) { // ascii adjust after multiplication if imm8 == 0i32 { trigger_de(); @@ -353,7 +353,7 @@ pub unsafe fn bcd_aam(mut imm8: i32) -> () { }; } #[no_mangle] -pub unsafe fn bcd_aaa() -> () { +pub unsafe fn bcd_aaa() { if *reg8.offset(AL as isize) as i32 & 15i32 > 9i32 || 0 != getaf() as i32 { *reg16.offset(AX as isize) += 6; *reg8.offset(AH as isize) += 1; @@ -366,7 +366,7 @@ pub unsafe fn bcd_aaa() -> () { *flags_changed &= !FLAG_ADJUST & !1i32; } #[no_mangle] -pub unsafe fn bcd_aas() -> () { +pub unsafe fn bcd_aas() { if *reg8.offset(AL as isize) as i32 & 15i32 > 9i32 || 0 != getaf() as i32 { *reg16.offset(AX as isize) -= 6; *reg8.offset(AH as isize) -= 1; @@ -409,11 +409,11 @@ pub unsafe fn and16(mut x: i32, mut y: i32) -> i32 { return and(x, y, OPSIZE_16) #[no_mangle] pub unsafe fn and32(mut x: i32, mut y: i32) -> i32 { return and(x, y, OPSIZE_32); } #[no_mangle] -pub unsafe fn test8(mut x: i32, mut y: i32) -> () { and(x, y, OPSIZE_8); } +pub unsafe fn test8(mut x: i32, mut y: i32) { and(x, y, OPSIZE_8); } #[no_mangle] -pub unsafe fn test16(mut x: i32, mut y: i32) -> () { and(x, y, OPSIZE_16); } +pub unsafe fn test16(mut x: i32, mut y: i32) { and(x, y, OPSIZE_16); } #[no_mangle] -pub unsafe fn test32(mut x: i32, mut y: i32) -> () { and(x, y, OPSIZE_32); } +pub unsafe fn test32(mut x: i32, mut y: i32) { and(x, y, OPSIZE_32); } #[no_mangle] pub unsafe fn or8(mut x: i32, mut y: i32) -> i32 { return or(x, y, OPSIZE_8); } #[no_mangle] @@ -618,7 +618,7 @@ pub unsafe fn rcr32(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn div8(mut source_operand: u32) -> () { +pub unsafe fn div8(mut source_operand: u32) { if source_operand == 0i32 as u32 { trigger_de(); return; @@ -637,7 +637,7 @@ pub unsafe fn div8(mut source_operand: u32) -> () { }; } #[no_mangle] -pub unsafe fn idiv8(mut source_operand: i32) -> () { +pub unsafe fn idiv8(mut source_operand: i32) { if source_operand == 0i32 { trigger_de(); return; @@ -656,7 +656,7 @@ pub unsafe fn idiv8(mut source_operand: i32) -> () { }; } #[no_mangle] -pub unsafe fn div16(mut source_operand: u32) -> () { +pub unsafe fn div16(mut source_operand: u32) { if source_operand == 0i32 as u32 { trigger_de(); return; @@ -677,7 +677,7 @@ pub unsafe fn div16(mut source_operand: u32) -> () { }; } #[no_mangle] -pub unsafe fn idiv16(mut source_operand: i32) -> () { +pub unsafe fn idiv16(mut source_operand: i32) { if source_operand == 0i32 { trigger_de(); return; @@ -697,7 +697,7 @@ pub unsafe fn idiv16(mut source_operand: i32) -> () { }; } #[no_mangle] -pub unsafe fn div32(mut source_operand: u32) -> () { +pub unsafe fn div32(mut source_operand: u32) { if source_operand == 0i32 as u32 { trigger_de(); return; @@ -720,7 +720,7 @@ pub unsafe fn div32(mut source_operand: u32) -> () { }; } #[no_mangle] -pub unsafe fn idiv32(mut source_operand: i32) -> () { +pub unsafe fn idiv32(mut source_operand: i32) { if source_operand == 0i32 { trigger_de(); return; @@ -975,7 +975,7 @@ pub unsafe fn shld32(mut dest_operand: i32, mut source_operand: i32, mut count: }; } #[no_mangle] -pub unsafe fn bt_reg(mut bit_base: i32, mut bit_offset: i32) -> () { +pub unsafe fn bt_reg(mut bit_base: i32, mut bit_offset: i32) { *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; *flags_changed &= !1i32; } @@ -998,14 +998,14 @@ pub unsafe fn btr_reg(mut bit_base: i32, mut bit_offset: i32) -> i32 { return bit_base & !(1i32 << bit_offset); } #[no_mangle] -pub unsafe fn bt_mem(mut virt_addr: i32, mut bit_offset: i32) -> () { +pub unsafe fn bt_mem(mut virt_addr: i32, mut bit_offset: i32) { let mut bit_base: i32 = return_on_pagefault!(safe_read8(virt_addr + (bit_offset >> 3i32))); bit_offset &= 7i32; *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; *flags_changed &= !1i32; } #[no_mangle] -pub unsafe fn btc_mem(mut virt_addr: i32, mut bit_offset: i32) -> () { +pub unsafe fn btc_mem(mut virt_addr: i32, mut bit_offset: i32) { let mut phys_addr: i32 = return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3i32))) as i32; let mut bit_base: i32 = read8(phys_addr as u32); @@ -1015,7 +1015,7 @@ pub unsafe fn btc_mem(mut virt_addr: i32, mut bit_offset: i32) -> () { write8(phys_addr as u32, bit_base ^ 1i32 << bit_offset); } #[no_mangle] -pub unsafe fn btr_mem(mut virt_addr: i32, mut bit_offset: i32) -> () { +pub unsafe fn btr_mem(mut virt_addr: i32, mut bit_offset: i32) { let mut phys_addr: i32 = return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3i32))) as i32; let mut bit_base: i32 = read8(phys_addr as u32); @@ -1025,7 +1025,7 @@ pub unsafe fn btr_mem(mut virt_addr: i32, mut bit_offset: i32) -> () { write8(phys_addr as u32, bit_base & !(1i32 << bit_offset)); } #[no_mangle] -pub unsafe fn bts_mem(mut virt_addr: i32, mut bit_offset: i32) -> () { +pub unsafe fn bts_mem(mut virt_addr: i32, mut bit_offset: i32) { let mut phys_addr: i32 = return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3i32))) as i32; let mut bit_base: i32 = read8(phys_addr as u32); diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 9e8570e9..0b9bf6f8 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -236,7 +236,7 @@ pub static mut valid_tlb_entries_count: i32 = 0i32; //pub fn call_indirect1(f: fn(u16), x: u16) { f(x); } -pub unsafe fn after_block_boundary() -> () { jit_block_boundary = 0 != 1i32; } +pub unsafe fn after_block_boundary() { jit_block_boundary = 0 != 1i32; } pub unsafe fn same_page(mut addr1: i32, mut addr2: i32) -> bool { return addr1 & !4095i32 == addr2 & !4095i32; @@ -444,7 +444,7 @@ pub unsafe fn do_page_translation( } #[no_mangle] -pub unsafe fn full_clear_tlb() -> () { +pub unsafe fn full_clear_tlb() { profiler_stat_increment(S_FULL_CLEAR_TLB); // clear tlb including global pages *last_virt_eip = -1i32; @@ -466,7 +466,7 @@ pub unsafe fn full_clear_tlb() -> () { } #[no_mangle] -pub unsafe fn clear_tlb() -> () { +pub unsafe fn clear_tlb() { profiler_stat_increment(S_CLEAR_TLB); // clear tlb excluding global pages *last_virt_eip = -1i32; @@ -499,7 +499,7 @@ pub unsafe fn clear_tlb() -> () { }; } -pub unsafe fn trigger_pagefault(mut write: bool, mut user: bool, mut present: bool) -> () { +pub unsafe fn trigger_pagefault(mut write: bool, mut user: bool, mut present: bool) { if 0 != 0i32 * 0i32 { dbg_log!( "page fault w={} u={} p={} eip={:x} cr2={:x}", @@ -552,7 +552,7 @@ pub unsafe fn translate_address_write(mut address: i32) -> Result { } #[no_mangle] -pub unsafe fn tlb_set_has_code(mut physical_page: u32, mut has_code: bool) -> () { +pub unsafe fn tlb_set_has_code(mut physical_page: u32, mut has_code: bool) { dbg_assert!(physical_page < (1i32 << 20i32) as u32); let mut i: i32 = 0i32; while i < valid_tlb_entries_count { @@ -575,7 +575,7 @@ pub unsafe fn tlb_set_has_code(mut physical_page: u32, mut has_code: bool) -> () } #[no_mangle] -pub unsafe fn check_tlb_invariants() -> () { +pub unsafe fn check_tlb_invariants() { if !CHECK_TLB_INVARIANTS { return; } @@ -684,12 +684,12 @@ pub unsafe fn get_seg(mut segment: i32) -> i32 { return *segment_offsets.offset(segment as isize); } -pub unsafe fn trigger_gp(mut code: i32) -> () { +pub unsafe fn trigger_gp(mut code: i32) { *instruction_pointer = *previous_ip; raise_exception_with_code(CPU_EXCEPTION_GP, code); } -pub unsafe fn raise_exception_with_code(mut interrupt_nr: i32, mut error_code: i32) -> () { +pub unsafe fn raise_exception_with_code(mut interrupt_nr: i32, mut error_code: i32) { if DEBUG { if must_not_fault { dbg_log!( @@ -749,7 +749,7 @@ pub unsafe fn run_instruction0f_16(opcode: i32) { ::gen::interpreter0f_16::run(o pub unsafe fn run_instruction0f_32(opcode: i32) { ::gen::interpreter0f_32::run(opcode as u8) } #[no_mangle] -pub unsafe fn cycle_internal() -> () { +pub unsafe fn cycle_internal() { profiler_stat_increment(S_CYCLE_INTERNAL); if true { *previous_ip = *instruction_pointer; @@ -810,7 +810,7 @@ pub unsafe fn get_phys_eip() -> Result { dbg_assert!(!in_mapped_range(phys_addr)); return Ok(phys_addr as i32); } -unsafe fn jit_run_interpreted(mut phys_addr: i32) -> () { +unsafe fn jit_run_interpreted(mut phys_addr: i32) { profiler_stat_increment(S_RUN_INTERPRETED); jit_block_boundary = 0 != 0i32; dbg_assert!(!in_mapped_range(phys_addr as u32)); @@ -844,13 +844,13 @@ pub unsafe fn has_flat_segmentation() -> bool { && *segment_offsets.offset(DS as isize) == 0i32; } -pub unsafe fn run_prefix_instruction() -> () { +pub unsafe fn run_prefix_instruction() { run_instruction(return_on_pagefault!(read_imm8()) | (is_osize_32() as i32) << 8i32); } -pub unsafe fn clear_prefixes() -> () { *prefixes = 0i32 as u8; } +pub unsafe fn clear_prefixes() { *prefixes = 0i32 as u8; } -pub unsafe fn segment_prefix_op(mut seg: i32) -> () { +pub unsafe fn segment_prefix_op(mut seg: i32) { dbg_assert!(seg <= 5i32); *prefixes = (*prefixes as i32 | seg + 1i32) as u8; run_prefix_instruction(); @@ -858,7 +858,7 @@ pub unsafe fn segment_prefix_op(mut seg: i32) -> () { } #[no_mangle] -pub unsafe fn do_many_cycles_native() -> () { +pub unsafe fn do_many_cycles_native() { profiler_stat_increment(S_DO_MANY_CYCLES); let mut initial_timestamp_counter: u32 = *timestamp_counter; while (*timestamp_counter).wrapping_sub(initial_timestamp_counter) < LOOP_COUNTER as u32 @@ -868,7 +868,7 @@ pub unsafe fn do_many_cycles_native() -> () { } } //#[no_mangle] -//pub unsafe fn raise_exception(mut interrupt_nr: i32) -> () { +//pub unsafe fn raise_exception(mut interrupt_nr: i32) { // if DEBUG { // if must_not_fault { // dbg_log!("Unexpected fault: 0x{:x}", interrupt_nr); @@ -885,7 +885,7 @@ pub unsafe fn do_many_cycles_native() -> () { // throw_cpu_exception(); //} -pub unsafe fn trigger_de() -> () { +pub unsafe fn trigger_de() { if DEBUG { if cpu_exception_hook(CPU_EXCEPTION_DE) { return; @@ -896,7 +896,7 @@ pub unsafe fn trigger_de() -> () { } #[no_mangle] -pub unsafe fn trigger_ud() -> () { +pub unsafe fn trigger_ud() { dbg_log!("#ud"); dbg_trace(); if DEBUG { @@ -908,7 +908,7 @@ pub unsafe fn trigger_ud() -> () { call_interrupt_vector(CPU_EXCEPTION_UD, 0 != 0i32, 0 != 0i32, 0i32); } -pub unsafe fn trigger_nm() -> () { +pub unsafe fn trigger_nm() { if DEBUG { if cpu_exception_hook(CPU_EXCEPTION_NM) { return; @@ -919,7 +919,7 @@ pub unsafe fn trigger_nm() -> () { } #[no_mangle] -pub unsafe fn trigger_gp_non_raising(mut code: i32) -> () { +pub unsafe fn trigger_gp_non_raising(mut code: i32) { if DEBUG { if cpu_exception_hook(CPU_EXCEPTION_GP) { return; @@ -956,14 +956,14 @@ pub unsafe fn virt_boundary_read32s(mut low: i32, mut high: i32) -> i32 { return read8(low as u32) | mid << 8i32 | read8(high as u32) << 24i32; } -pub unsafe fn virt_boundary_write16(mut low: i32, mut high: i32, mut value: i32) -> () { +pub unsafe fn virt_boundary_write16(mut low: i32, mut high: i32, mut value: i32) { dbg_assert!(low & 4095i32 == 4095i32); dbg_assert!(high & 4095i32 == 0i32); write8(low as u32, value); write8(high as u32, value >> 8i32); } -pub unsafe fn virt_boundary_write32(mut low: i32, mut high: i32, mut value: i32) -> () { +pub unsafe fn virt_boundary_write32(mut low: i32, mut high: i32, mut value: i32) { dbg_assert!(low & 4095i32 >= 4093i32); dbg_assert!(high - 3i32 & 4095i32 == low & 4095i32); write8(low as u32, value); @@ -1292,7 +1292,7 @@ pub unsafe fn read_reg8(mut index: i32) -> i32 { return *reg8.offset(get_reg8_index(index) as isize) as i32; } -pub unsafe fn write_reg8(mut index: i32, mut value: i32) -> () { +pub unsafe fn write_reg8(mut index: i32, mut value: i32) { *reg8.offset(get_reg8_index(index) as isize) = value as u8; } @@ -1302,17 +1302,17 @@ pub unsafe fn read_reg16(mut index: i32) -> i32 { return *reg16.offset(get_reg16_index(index) as isize) as i32; } -pub unsafe fn write_reg16(mut index: i32, mut value: i32) -> () { +pub unsafe fn write_reg16(mut index: i32, mut value: i32) { *reg16.offset(get_reg16_index(index) as isize) = value as u16; } pub unsafe fn read_reg32(mut index: i32) -> i32 { return *reg32s.offset(index as isize); } -pub unsafe fn write_reg32(mut index: i32, mut value: i32) -> () { +pub unsafe fn write_reg32(mut index: i32, mut value: i32) { *reg32s.offset(index as isize) = value; } -pub unsafe fn write_reg_osize(mut index: i32, mut value: i32) -> () { +pub unsafe fn write_reg_osize(mut index: i32, mut value: i32) { dbg_assert!(index >= 0i32 && index < 8i32); if is_osize_32() { write_reg32(index, value); @@ -1328,12 +1328,12 @@ pub unsafe fn read_mmx32s(mut r: i32) -> i32 { pub unsafe fn read_mmx64s(mut r: i32) -> reg64 { return *reg_mmx.offset(r as isize); } -pub unsafe fn write_mmx64(mut r: i32, mut low: i32, mut high: i32) -> () { +pub unsafe fn write_mmx64(mut r: i32, mut low: i32, mut high: i32) { (*reg_mmx.offset(r as isize)).u32_0[0usize] = low as u32; (*reg_mmx.offset(r as isize)).u32_0[1usize] = high as u32; } -pub unsafe fn write_mmx_reg64(mut r: i32, mut data: reg64) -> () { +pub unsafe fn write_mmx_reg64(mut r: i32, mut data: reg64) { (*reg_mmx.offset(r as isize)).u64_0[0usize] = data.u64_0[0usize]; } @@ -1353,26 +1353,26 @@ pub unsafe fn read_xmm64s(mut r: i32) -> reg64 { pub unsafe fn read_xmm128s(mut r: i32) -> reg128 { return *reg_xmm.offset(r as isize); } -pub unsafe fn write_xmm_f32(mut r: i32, mut data: f32) -> () { +pub unsafe fn write_xmm_f32(mut r: i32, mut data: f32) { (*reg_xmm.offset(r as isize)).f32_0[0usize] = data; } -pub unsafe fn write_xmm32(mut r: i32, mut data: i32) -> () { +pub unsafe fn write_xmm32(mut r: i32, mut data: i32) { (*reg_xmm.offset(r as isize)).i32_0[0usize] = data; } -pub unsafe fn write_xmm64(mut r: i32, mut data: reg64) -> () { +pub unsafe fn write_xmm64(mut r: i32, mut data: reg64) { (*reg_xmm.offset(r as isize)).u64_0[0usize] = data.u64_0[0usize]; } -pub unsafe fn write_xmm128(mut r: i32, mut i0: i32, mut i1: i32, mut i2: i32, mut i3: i32) -> () { +pub unsafe fn write_xmm128(mut r: i32, mut i0: i32, mut i1: i32, mut i2: i32, mut i3: i32) { let mut x: reg128 = reg128 { u32_0: [i0 as u32, i1 as u32, i2 as u32, i3 as u32], }; *reg_xmm.offset(r as isize) = x; } -pub unsafe fn write_xmm_reg128(mut r: i32, mut data: reg128) -> () { +pub unsafe fn write_xmm_reg128(mut r: i32, mut data: reg128) { (*reg_xmm.offset(r as isize)).u64_0[0usize] = data.u64_0[0usize]; (*reg_xmm.offset(r as isize)).u64_0[1usize] = data.u64_0[1usize]; } @@ -1417,7 +1417,7 @@ pub unsafe fn set_mxcsr(new_mxcsr: i32) { } #[no_mangle] -pub unsafe fn task_switch_test_void() -> () { task_switch_test(); } +pub unsafe fn task_switch_test_void() { task_switch_test(); } pub unsafe fn task_switch_test_mmx() -> bool { if 0 != *cr & CR0_TS { @@ -1434,7 +1434,7 @@ pub unsafe fn task_switch_test_mmx() -> bool { } #[no_mangle] -pub unsafe fn task_switch_test_mmx_void() -> () { task_switch_test_mmx(); } +pub unsafe fn task_switch_test_mmx_void() { task_switch_test_mmx(); } pub unsafe fn read_moffs() -> Result { // read 2 or 4 byte from ip, depending on address size attribute @@ -1462,7 +1462,7 @@ pub unsafe fn get_stack_reg() -> i32 { } #[no_mangle] -pub unsafe fn set_stack_reg(mut value: i32) -> () { +pub unsafe fn set_stack_reg(mut value: i32) { if *stack_size_32 { *reg32s.offset(ESP as isize) = value } @@ -1482,7 +1482,7 @@ pub unsafe fn get_reg_asize(mut reg: i32) -> i32 { }; } -pub unsafe fn set_ecx_asize(mut value: i32) -> () { +pub unsafe fn set_ecx_asize(mut value: i32) { if is_asize_32() { *reg32s.offset(ECX as isize) = value } @@ -1491,7 +1491,7 @@ pub unsafe fn set_ecx_asize(mut value: i32) -> () { }; } -pub unsafe fn add_reg_asize(mut reg: i32, mut value: i32) -> () { +pub unsafe fn add_reg_asize(mut reg: i32, mut value: i32) { dbg_assert!(reg == ECX || reg == ESI || reg == EDI); if is_asize_32() { *reg32s.offset(reg as isize) += value; @@ -1513,7 +1513,7 @@ pub unsafe fn decr_ecx_asize() -> i32 { } #[no_mangle] -pub unsafe fn set_tsc(mut low: u32, mut high: u32) -> () { +pub unsafe fn set_tsc(mut low: u32, mut high: u32) { let mut new_value: u64 = low as u64 | (high as u64) << 32i32; let mut current_value: u64 = read_tsc(); tsc_offset = current_value.wrapping_sub(new_value); @@ -1573,7 +1573,7 @@ pub unsafe fn get_opstats_buffer(mut index: i32) -> i32 { }; } -pub unsafe fn invlpg(mut addr: i32) -> () { +pub unsafe fn invlpg(mut addr: i32) { let mut page: i32 = (addr as u32 >> 12i32) as i32; // Note: Doesn't remove this page from valid_tlb_entries: This isn't // necessary, because when valid_tlb_entries grows too large, it will be @@ -1585,7 +1585,7 @@ pub unsafe fn invlpg(mut addr: i32) -> () { } #[no_mangle] -pub unsafe fn update_eflags(mut new_flags: i32) -> () { +pub unsafe fn update_eflags(mut new_flags: i32) { let mut dont_update: i32 = FLAG_RF | FLAG_VM | FLAG_VIP | FLAG_VIF; let mut clear: i32 = !FLAG_VIP & !FLAG_VIF & FLAGS_MASK; if 0 != *flags & FLAG_VM { @@ -1667,7 +1667,7 @@ pub unsafe fn translate_address_system_write(mut address: i32) -> Result () { +pub unsafe fn trigger_np(mut code: i32) { if DEBUG { if cpu_exception_hook(CPU_EXCEPTION_NP) { return; @@ -1678,7 +1678,7 @@ pub unsafe fn trigger_np(mut code: i32) -> () { } #[no_mangle] -pub unsafe fn trigger_ss(mut code: i32) -> () { +pub unsafe fn trigger_ss(mut code: i32) { if DEBUG { if cpu_exception_hook(CPU_EXCEPTION_SS) { return; @@ -1689,4 +1689,4 @@ pub unsafe fn trigger_ss(mut code: i32) -> () { } #[no_mangle] -pub unsafe fn store_current_tsc() -> () { *current_tsc = read_tsc(); } +pub unsafe fn store_current_tsc() { *current_tsc = read_tsc(); } diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 0fb66eba..1ef945e7 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -63,7 +63,7 @@ pub unsafe fn fpu_get_st0() -> f64 { }; } #[no_mangle] -pub unsafe fn fpu_stack_fault() -> () { +pub unsafe fn fpu_stack_fault() { // TODO: Interrupt *fpu_status_word |= FPU_EX_SF | FPU_EX_I; } @@ -157,22 +157,22 @@ pub unsafe fn fpu_load_status_word() -> i32 { return ((*fpu_status_word & !(7i32 << 11i32)) as u32 | *fpu_stack_ptr << 11i32) as i32; } #[no_mangle] -pub unsafe fn fpu_fadd(mut target_index: i32, mut val: f64) -> () { +pub unsafe fn fpu_fadd(mut target_index: i32, mut val: f64) { let mut st0: f64 = fpu_get_st0(); *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = st0 + val; } #[no_mangle] -pub unsafe fn fpu_fclex() -> () { *fpu_status_word = 0i32; } +pub unsafe fn fpu_fclex() { *fpu_status_word = 0i32; } #[no_mangle] -pub unsafe fn fpu_fcmovcc(mut condition: bool, mut r: i32) -> () { +pub unsafe fn fpu_fcmovcc(mut condition: bool, mut r: i32) { if condition { *fpu_st.offset(*fpu_stack_ptr as isize) = fpu_get_sti(r); *fpu_stack_empty &= !(1i32 << *fpu_stack_ptr) }; } #[no_mangle] -pub unsafe fn fpu_fcom(mut y: f64) -> () { +pub unsafe fn fpu_fcom(mut y: f64) { let mut x: f64 = fpu_get_st0(); *fpu_status_word &= !FPU_RESULT_FLAGS; if !(x > y) { @@ -188,7 +188,7 @@ pub unsafe fn fpu_fcom(mut y: f64) -> () { }; } #[no_mangle] -pub unsafe fn fpu_fcomi(mut r: i32) -> () { +pub unsafe fn fpu_fcomi(mut r: i32) { let mut y: f64 = fpu_get_sti(r); let mut x: f64 = *fpu_st.offset(*fpu_stack_ptr as isize); *flags_changed &= !(1i32 | FLAG_PARITY | FLAG_ZERO); @@ -206,44 +206,44 @@ pub unsafe fn fpu_fcomi(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe fn fpu_fcomip(mut r: i32) -> () { +pub unsafe fn fpu_fcomip(mut r: i32) { fpu_fcomi(r); fpu_pop(); } #[no_mangle] -pub unsafe fn fpu_pop() -> () { +pub unsafe fn fpu_pop() { *fpu_stack_empty |= 1i32 << *fpu_stack_ptr; *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_add(1i32 as u32) & 7i32 as u32; } #[no_mangle] -pub unsafe fn fpu_fcomp(mut val: f64) -> () { +pub unsafe fn fpu_fcomp(mut val: f64) { fpu_fcom(val); fpu_pop(); } #[no_mangle] -pub unsafe fn fpu_fdiv(mut target_index: i32, mut val: f64) -> () { +pub unsafe fn fpu_fdiv(mut target_index: i32, mut val: f64) { let mut st0: f64 = fpu_get_st0(); *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = st0 / val; } #[no_mangle] -pub unsafe fn fpu_fdivr(mut target_index: i32, mut val: f64) -> () { +pub unsafe fn fpu_fdivr(mut target_index: i32, mut val: f64) { let mut st0: f64 = fpu_get_st0(); *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = val / st0; } #[no_mangle] -pub unsafe fn fpu_ffree(mut r: i32) -> () { +pub unsafe fn fpu_ffree(mut r: i32) { *fpu_stack_empty |= 1i32 << (*fpu_stack_ptr).wrapping_add(r as u32); } #[no_mangle] -pub unsafe fn fpu_fildm64(mut addr: i32) -> () { +pub unsafe fn fpu_fildm64(mut addr: i32) { let mut value: i64 = return_on_pagefault!(safe_read64s(addr)).i64_0[0usize]; let mut m64: f64 = value as f64; fpu_push(m64); } #[no_mangle] -pub unsafe fn fpu_push(mut x: f64) -> () { +pub unsafe fn fpu_push(mut x: f64) { *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_sub(1i32 as u32) & 7i32 as u32; if 0 != *fpu_stack_empty >> *fpu_stack_ptr & 1i32 { *fpu_status_word &= !FPU_C1; @@ -257,7 +257,7 @@ pub unsafe fn fpu_push(mut x: f64) -> () { }; } #[no_mangle] -pub unsafe fn fpu_finit() -> () { +pub unsafe fn fpu_finit() { *fpu_control_word = 895i32; *fpu_status_word = 0i32; *fpu_ip = 0i32; @@ -267,7 +267,7 @@ pub unsafe fn fpu_finit() -> () { *fpu_stack_ptr = 0i32 as u32; } #[no_mangle] -pub unsafe fn fpu_fistm16(mut addr: i32) -> () { +pub unsafe fn fpu_fistm16(mut addr: i32) { let mut st0: f64 = fpu_integer_round(fpu_get_st0()); if st0 <= 32767i32 as f64 && st0 >= -32768i32 as f64 { return_on_pagefault!(safe_write16(addr, st0 as i32)); @@ -278,14 +278,14 @@ pub unsafe fn fpu_fistm16(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe fn fpu_invalid_arithmetic() -> () { *fpu_status_word |= FPU_EX_I; } +pub unsafe fn fpu_invalid_arithmetic() { *fpu_status_word |= FPU_EX_I; } #[no_mangle] -pub unsafe fn fpu_fistm16p(mut addr: i32) -> () { +pub unsafe fn fpu_fistm16p(mut addr: i32) { fpu_fistm16(addr); fpu_pop(); } #[no_mangle] -pub unsafe fn fpu_fistm32(mut addr: i32) -> () { +pub unsafe fn fpu_fistm32(mut addr: i32) { let mut st0: f64 = fpu_integer_round(fpu_get_st0()); let mut i: i32 = convert_f64_to_i32(st0); if i == 2147483648u32 as i32 { @@ -296,12 +296,12 @@ pub unsafe fn fpu_fistm32(mut addr: i32) -> () { return_on_pagefault!(safe_write32(addr, i)); } #[no_mangle] -pub unsafe fn fpu_fistm32p(mut addr: i32) -> () { +pub unsafe fn fpu_fistm32p(mut addr: i32) { fpu_fistm32(addr); fpu_pop(); } #[no_mangle] -pub unsafe fn fpu_fistm64p(mut addr: i32) -> () { +pub unsafe fn fpu_fistm64p(mut addr: i32) { let mut st0: f64 = fpu_integer_round(fpu_get_st0()); let mut value; if st0 < TWO_POW_63 && st0 >= -TWO_POW_63 { @@ -315,12 +315,12 @@ pub unsafe fn fpu_fistm64p(mut addr: i32) -> () { fpu_pop(); } #[no_mangle] -pub unsafe fn fpu_fldcw(mut addr: i32) -> () { +pub unsafe fn fpu_fldcw(mut addr: i32) { let mut word: i32 = return_on_pagefault!(safe_read16(addr)); *fpu_control_word = word; } #[no_mangle] -pub unsafe fn fpu_fldenv(mut addr: i32) -> () { +pub unsafe fn fpu_fldenv(mut addr: i32) { if is_osize_32() { // TODO: Add readable_or_pagefault return_on_pagefault!(translate_address_read(addr)); @@ -340,7 +340,7 @@ pub unsafe fn fpu_fldenv(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe fn fpu_unimpl() -> () { +pub unsafe fn fpu_unimpl() { if DEBUG { dbg_assert!(0 != 0i32); } @@ -349,7 +349,7 @@ pub unsafe fn fpu_unimpl() -> () { }; } #[no_mangle] -pub unsafe fn fpu_set_tag_word(mut tag_word: i32) -> () { +pub unsafe fn fpu_set_tag_word(mut tag_word: i32) { *fpu_stack_empty = 0i32; let mut i: i32 = 0i32; while i < 8i32 { @@ -359,36 +359,34 @@ pub unsafe fn fpu_set_tag_word(mut tag_word: i32) -> () { } } #[no_mangle] -pub unsafe fn fpu_set_status_word(mut sw: i32) -> () { +pub unsafe fn fpu_set_status_word(mut sw: i32) { *fpu_status_word = sw & !(7i32 << 11i32); *fpu_stack_ptr = (sw >> 11i32 & 7i32) as u32; } #[no_mangle] -pub unsafe fn fpu_fldm32(mut addr: i32) -> () { +pub unsafe fn fpu_fldm32(mut addr: i32) { fpu_push(return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe fn fpu_fldm64(mut addr: i32) -> () { - fpu_push(return_on_pagefault!(fpu_load_m64(addr))); -} +pub unsafe fn fpu_fldm64(mut addr: i32) { fpu_push(return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe fn fpu_fldm80(mut addr: i32) -> () { +pub unsafe fn fpu_fldm80(mut addr: i32) { fpu_push(return_on_pagefault!(fpu_load_m80(addr as u32))); } #[no_mangle] -pub unsafe fn fpu_fmul(mut target_index: i32, mut val: f64) -> () { +pub unsafe fn fpu_fmul(mut target_index: i32, mut val: f64) { let mut st0: f64 = fpu_get_st0(); *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = st0 * val; } #[no_mangle] -pub unsafe fn fpu_fnstsw_mem(mut addr: i32) -> () { +pub unsafe fn fpu_fnstsw_mem(mut addr: i32) { return_on_pagefault!(safe_write16(addr, fpu_load_status_word())); } #[no_mangle] -pub unsafe fn fpu_fnstsw_reg() -> () { *reg16.offset(AX as isize) = fpu_load_status_word() as u16; } +pub unsafe fn fpu_fnstsw_reg() { *reg16.offset(AX as isize) = fpu_load_status_word() as u16; } #[no_mangle] -pub unsafe fn fpu_fprem() -> () { +pub unsafe fn fpu_fprem() { // XXX: This implementation differs from the description in Intel's manuals let mut st0: f64 = fpu_get_st0(); let mut st1: f64 = fpu_get_sti(1i32); @@ -407,7 +405,7 @@ pub unsafe fn fpu_fprem() -> () { *fpu_status_word &= !FPU_C2; } #[no_mangle] -pub unsafe fn fpu_frstor(mut addr: i32) -> () { +pub unsafe fn fpu_frstor(mut addr: i32) { // TODO: Add readable_or_pagefault return_on_pagefault!(translate_address_read(addr)); return_on_pagefault!(translate_address_read(addr + 28 + 8 * 10)); @@ -422,7 +420,7 @@ pub unsafe fn fpu_frstor(mut addr: i32) -> () { } } #[no_mangle] -pub unsafe fn fpu_fsave(mut addr: i32) -> () { +pub unsafe fn fpu_fsave(mut addr: i32) { return_on_pagefault!(writable_or_pagefault(addr, 108i32)); fpu_fstenv(addr); addr += 28i32; @@ -438,7 +436,7 @@ pub unsafe fn fpu_fsave(mut addr: i32) -> () { fpu_finit(); } #[no_mangle] -pub unsafe fn fpu_store_m80(mut addr: u32, mut n: f64) -> () { +pub unsafe fn fpu_store_m80(mut addr: u32, mut n: f64) { let mut double_int_view: f64_int = f64_int { f64_0: n }; let mut sign: u8 = (double_int_view.u8_0[7usize] as i32 & 128i32) as u8; let mut exponent: i32 = (double_int_view.u8_0[7usize] as i32 & 127i32) << 4i32 @@ -478,7 +476,7 @@ pub unsafe fn fpu_store_m80(mut addr: u32, mut n: f64) -> () { ).unwrap(); } #[no_mangle] -pub unsafe fn fpu_fstenv(mut addr: i32) -> () { +pub unsafe fn fpu_fstenv(mut addr: i32) { if is_osize_32() { return_on_pagefault!(writable_or_pagefault(addr, 26i32)); safe_write16(addr, *fpu_control_word).unwrap(); @@ -515,21 +513,21 @@ pub unsafe fn fpu_load_tag_word() -> i32 { return tag_word; } #[no_mangle] -pub unsafe fn fpu_fst(mut r: i32) -> () { +pub unsafe fn fpu_fst(mut r: i32) { *fpu_st.offset((*fpu_stack_ptr).wrapping_add(r as u32) as isize & 7) = fpu_get_st0(); } #[no_mangle] -pub unsafe fn fpu_fst80p(mut addr: i32) -> () { +pub unsafe fn fpu_fst80p(mut addr: i32) { return_on_pagefault!(writable_or_pagefault(addr, 10i32)); fpu_store_m80(addr as u32, fpu_get_st0()); fpu_pop(); } #[no_mangle] -pub unsafe fn fpu_fstcw(mut addr: i32) -> () { +pub unsafe fn fpu_fstcw(mut addr: i32) { return_on_pagefault!(safe_write16(addr, *fpu_control_word)); } #[no_mangle] -pub unsafe fn fpu_fstm32(mut addr: i32) -> () { +pub unsafe fn fpu_fstm32(mut addr: i32) { return_on_pagefault!(fpu_store_m32(addr, fpu_get_st0())); } #[no_mangle] @@ -538,12 +536,12 @@ pub unsafe fn fpu_store_m32(mut addr: i32, mut x: f64) -> Result<(), ()> { safe_write32(addr, v.i32_0) } #[no_mangle] -pub unsafe fn fpu_fstm32p(mut addr: i32) -> () { +pub unsafe fn fpu_fstm32p(mut addr: i32) { fpu_fstm32(addr); fpu_pop(); } #[no_mangle] -pub unsafe fn fpu_fstm64(mut addr: i32) -> () { +pub unsafe fn fpu_fstm64(mut addr: i32) { return_on_pagefault!(fpu_store_m64(addr, fpu_get_st0())); } #[no_mangle] @@ -552,29 +550,29 @@ pub unsafe fn fpu_store_m64(mut addr: i32, mut x: f64) -> Result<(), ()> { safe_write64(addr, v.u64_0[0usize] as i64) } #[no_mangle] -pub unsafe fn fpu_fstm64p(mut addr: i32) -> () { +pub unsafe fn fpu_fstm64p(mut addr: i32) { fpu_fstm64(addr); fpu_pop(); } #[no_mangle] -pub unsafe fn fpu_fstp(mut r: i32) -> () { +pub unsafe fn fpu_fstp(mut r: i32) { fpu_fst(r); fpu_pop(); } #[no_mangle] -pub unsafe fn fpu_fsub(mut target_index: i32, mut val: f64) -> () { +pub unsafe fn fpu_fsub(mut target_index: i32, mut val: f64) { let mut st0: f64 = fpu_get_st0(); *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = st0 - val; } #[no_mangle] -pub unsafe fn fpu_fsubr(mut target_index: i32, mut val: f64) -> () { +pub unsafe fn fpu_fsubr(mut target_index: i32, mut val: f64) { let mut st0: f64 = fpu_get_st0(); *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = val - st0; } #[no_mangle] -pub unsafe fn fpu_ftst(mut x: f64) -> () { +pub unsafe fn fpu_ftst(mut x: f64) { *fpu_status_word &= !FPU_RESULT_FLAGS; if x.is_nan() { *fpu_status_word |= FPU_C3 | FPU_C2 | FPU_C0 @@ -588,33 +586,33 @@ pub unsafe fn fpu_ftst(mut x: f64) -> () { // TODO: unordered (x is nan, etc) } #[no_mangle] -pub unsafe fn fpu_fucom(mut r: i32) -> () { +pub unsafe fn fpu_fucom(mut r: i32) { // TODO fpu_fcom(fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn fpu_fucomi(mut r: i32) -> () { +pub unsafe fn fpu_fucomi(mut r: i32) { // TODO fpu_fcomi(r); } #[no_mangle] -pub unsafe fn fpu_fucomip(mut r: i32) -> () { +pub unsafe fn fpu_fucomip(mut r: i32) { fpu_fucomi(r); fpu_pop(); } #[no_mangle] -pub unsafe fn fpu_fucomp(mut r: i32) -> () { +pub unsafe fn fpu_fucomp(mut r: i32) { fpu_fucom(r); fpu_pop(); } #[no_mangle] -pub unsafe fn fpu_fucompp() -> () { +pub unsafe fn fpu_fucompp() { fpu_fucom(1i32); fpu_pop(); fpu_pop(); } #[no_mangle] -pub unsafe fn fpu_fxam(mut x: f64) -> () { +pub unsafe fn fpu_fxam(mut x: f64) { *fpu_status_word &= !FPU_RESULT_FLAGS; *fpu_status_word |= fpu_sign(0i32) << 9i32; if 0 != *fpu_stack_empty >> *fpu_stack_ptr & 1i32 { @@ -644,13 +642,13 @@ pub unsafe fn fpu_sign(mut i: i32) -> i32 { >> 7i32; } #[no_mangle] -pub unsafe fn fpu_fxch(mut i: i32) -> () { +pub unsafe fn fpu_fxch(mut i: i32) { let mut sti: f64 = fpu_get_sti(i); *fpu_st.offset((*fpu_stack_ptr).wrapping_add(i as u32) as isize & 7) = fpu_get_st0(); *fpu_st.offset(*fpu_stack_ptr as isize) = sti; } #[no_mangle] -pub unsafe fn fpu_fxtract() -> () { +pub unsafe fn fpu_fxtract() { let mut double_int_view: f64_int = f64_int { f64_0: fpu_get_st0(), }; @@ -663,6 +661,6 @@ pub unsafe fn fpu_fxtract() -> () { fpu_push(double_int_view.f64_0); } #[no_mangle] -pub unsafe fn fwait() -> () { +pub unsafe fn fwait() { // NOP unless FPU instructions run in parallel with CPU instructions } diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index e333342b..faae6179 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -45,84 +45,84 @@ use cpu2::misc_instr::{pop16, pop32s, push16, push32}; use cpu2::string::*; #[no_mangle] -pub unsafe fn instr_00_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_00_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE8!(___, addr, add8(___, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr_00_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_00_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, add8(____0, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr16_01_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_01_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE16!(___, addr, add16(___, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr16_01_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_01_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, add16(____0, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr32_01_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_01_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE32!(___, addr, add32(___, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr32_01_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_01_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, add32(____0, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr_02_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_02_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, add8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr_02_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_02_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r, add8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_03_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_03_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, add16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_03_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_03_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r, add16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_03_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_03_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, add32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_03_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_03_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r, add32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr_04(mut imm8: i32) -> () { +pub unsafe fn instr_04(mut imm8: i32) { *reg8.offset(AL as isize) = add8(*reg8.offset(AL as isize) as i32, imm8) as u8; } #[no_mangle] -pub unsafe fn instr16_05(mut imm16: i32) -> () { +pub unsafe fn instr16_05(mut imm16: i32) { *reg16.offset(AX as isize) = add16(*reg16.offset(AX as isize) as i32, imm16) as u16; } #[no_mangle] -pub unsafe fn instr32_05(mut imm32: i32) -> () { +pub unsafe fn instr32_05(mut imm32: i32) { *reg32s.offset(EAX as isize) = add32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] -pub unsafe fn instr16_06() -> () { +pub unsafe fn instr16_06() { return_on_pagefault!(push16(*sreg.offset(ES as isize) as i32)); } #[no_mangle] -pub unsafe fn instr32_06() -> () { +pub unsafe fn instr32_06() { return_on_pagefault!(push32(*sreg.offset(ES as isize) as i32)); } #[no_mangle] -pub unsafe fn instr16_07() -> () { +pub unsafe fn instr16_07() { if !switch_seg( ES, return_on_pagefault!(safe_read16(get_stack_pointer(0i32))), @@ -135,7 +135,7 @@ pub unsafe fn instr16_07() -> () { }; } #[no_mangle] -pub unsafe fn instr32_07() -> () { +pub unsafe fn instr32_07() { if !switch_seg( ES, return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))) & 65535i32, @@ -148,165 +148,165 @@ pub unsafe fn instr32_07() -> () { }; } #[no_mangle] -pub unsafe fn instr_08_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_08_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE8!(___, addr, or8(___, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr_08_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_08_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, or8(____0, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr16_09_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_09_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE16!(___, addr, or16(___, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr16_09_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_09_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, or16(____0, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr32_09_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_09_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE32!(___, addr, or32(___, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr32_09_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_09_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, or32(____0, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr_0A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0A_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, or8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr_0A_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_0A_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r, or8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_0B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0B_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, or16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_0B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0B_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r, or16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_0B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0B_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, or32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_0B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0B_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r, or32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr_0C(mut imm8: i32) -> () { +pub unsafe fn instr_0C(mut imm8: i32) { *reg8.offset(AL as isize) = or8(*reg8.offset(AL as isize) as i32, imm8) as u8; } #[no_mangle] -pub unsafe fn instr16_0D(mut imm16: i32) -> () { +pub unsafe fn instr16_0D(mut imm16: i32) { *reg16.offset(AX as isize) = or16(*reg16.offset(AX as isize) as i32, imm16) as u16; } #[no_mangle] -pub unsafe fn instr32_0D(mut imm32: i32) -> () { +pub unsafe fn instr32_0D(mut imm32: i32) { *reg32s.offset(EAX as isize) = or32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] -pub unsafe fn instr16_0E() -> () { +pub unsafe fn instr16_0E() { return_on_pagefault!(push16(*sreg.offset(CS as isize) as i32)); } #[no_mangle] -pub unsafe fn instr32_0E() -> () { +pub unsafe fn instr32_0E() { return_on_pagefault!(push32(*sreg.offset(CS as isize) as i32)); } #[no_mangle] -pub unsafe fn instr16_0F() -> () { run_instruction0f_16(return_on_pagefault!(read_imm8())); } +pub unsafe fn instr16_0F() { run_instruction0f_16(return_on_pagefault!(read_imm8())); } #[no_mangle] -pub unsafe fn instr32_0F() -> () { run_instruction0f_32(return_on_pagefault!(read_imm8())); } +pub unsafe fn instr32_0F() { run_instruction0f_32(return_on_pagefault!(read_imm8())); } #[no_mangle] -pub unsafe fn instr_10_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_10_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE8!(___, addr, adc8(___, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr_10_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_10_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, adc8(____0, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr16_11_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_11_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE16!(___, addr, adc16(___, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr16_11_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_11_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, adc16(____0, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr32_11_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_11_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE32!(___, addr, adc32(___, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr32_11_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_11_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, adc32(____0, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr_12_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_12_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, adc8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr_12_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_12_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r, adc8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_13_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_13_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, adc16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_13_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_13_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r, adc16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_13_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_13_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, adc32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_13_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_13_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r, adc32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr_14(mut imm8: i32) -> () { +pub unsafe fn instr_14(mut imm8: i32) { *reg8.offset(AL as isize) = adc8(*reg8.offset(AL as isize) as i32, imm8) as u8; } #[no_mangle] -pub unsafe fn instr16_15(mut imm16: i32) -> () { +pub unsafe fn instr16_15(mut imm16: i32) { *reg16.offset(AX as isize) = adc16(*reg16.offset(AX as isize) as i32, imm16) as u16; } #[no_mangle] -pub unsafe fn instr32_15(mut imm32: i32) -> () { +pub unsafe fn instr32_15(mut imm32: i32) { *reg32s.offset(EAX as isize) = adc32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] -pub unsafe fn instr16_16() -> () { +pub unsafe fn instr16_16() { return_on_pagefault!(push16(*sreg.offset(SS as isize) as i32)); } #[no_mangle] -pub unsafe fn instr32_16() -> () { +pub unsafe fn instr32_16() { return_on_pagefault!(push32(*sreg.offset(SS as isize) as i32)); } #[no_mangle] -pub unsafe fn instr16_17() -> () { +pub unsafe fn instr16_17() { if !switch_seg( SS, return_on_pagefault!(safe_read16(get_stack_pointer(0i32))), @@ -319,7 +319,7 @@ pub unsafe fn instr16_17() -> () { }; } #[no_mangle] -pub unsafe fn instr32_17() -> () { +pub unsafe fn instr32_17() { if !switch_seg( SS, return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))) & 65535i32, @@ -332,84 +332,84 @@ pub unsafe fn instr32_17() -> () { }; } #[no_mangle] -pub unsafe fn instr_18_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_18_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE8!(___, addr, sbb8(___, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr_18_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_18_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, sbb8(____0, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr16_19_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_19_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE16!(___, addr, sbb16(___, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr16_19_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_19_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, sbb16(____0, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr32_19_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_19_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE32!(___, addr, sbb32(___, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr32_19_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_19_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, sbb32(____0, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr_1A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_1A_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, sbb8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr_1A_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_1A_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r, sbb8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_1B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_1B_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, sbb16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_1B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_1B_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r, sbb16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_1B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_1B_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, sbb32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_1B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_1B_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r, sbb32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr_1C(mut imm8: i32) -> () { +pub unsafe fn instr_1C(mut imm8: i32) { *reg8.offset(AL as isize) = sbb8(*reg8.offset(AL as isize) as i32, imm8) as u8; } #[no_mangle] -pub unsafe fn instr16_1D(mut imm16: i32) -> () { +pub unsafe fn instr16_1D(mut imm16: i32) { *reg16.offset(AX as isize) = sbb16(*reg16.offset(AX as isize) as i32, imm16) as u16; } #[no_mangle] -pub unsafe fn instr32_1D(mut imm32: i32) -> () { +pub unsafe fn instr32_1D(mut imm32: i32) { *reg32s.offset(EAX as isize) = sbb32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] -pub unsafe fn instr16_1E() -> () { +pub unsafe fn instr16_1E() { return_on_pagefault!(push16(*sreg.offset(DS as isize) as i32)); } #[no_mangle] -pub unsafe fn instr32_1E() -> () { +pub unsafe fn instr32_1E() { return_on_pagefault!(push32(*sreg.offset(DS as isize) as i32)); } #[no_mangle] -pub unsafe fn instr16_1F() -> () { +pub unsafe fn instr16_1F() { if !switch_seg( DS, return_on_pagefault!(safe_read16(get_stack_pointer(0i32))), @@ -422,7 +422,7 @@ pub unsafe fn instr16_1F() -> () { }; } #[no_mangle] -pub unsafe fn instr32_1F() -> () { +pub unsafe fn instr32_1F() { if !switch_seg( DS, return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))) & 65535i32, @@ -435,422 +435,390 @@ pub unsafe fn instr32_1F() -> () { }; } #[no_mangle] -pub unsafe fn instr_20_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_20_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE8!(___, addr, and8(___, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr_20_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_20_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, and8(____0, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr16_21_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_21_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE16!(___, addr, and16(___, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr16_21_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_21_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, and16(____0, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr32_21_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_21_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE32!(___, addr, and32(___, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr32_21_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_21_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, and32(____0, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr_22_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_22_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, and8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr_22_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_22_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r, and8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_23_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_23_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, and16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_23_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_23_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r, and16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_23_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_23_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, and32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_23_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_23_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r, and32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr_24(mut imm8: i32) -> () { +pub unsafe fn instr_24(mut imm8: i32) { *reg8.offset(AL as isize) = and8(*reg8.offset(AL as isize) as i32, imm8) as u8; } #[no_mangle] -pub unsafe fn instr16_25(mut imm16: i32) -> () { +pub unsafe fn instr16_25(mut imm16: i32) { *reg16.offset(AX as isize) = and16(*reg16.offset(AX as isize) as i32, imm16) as u16; } #[no_mangle] -pub unsafe fn instr32_25(mut imm32: i32) -> () { +pub unsafe fn instr32_25(mut imm32: i32) { *reg32s.offset(EAX as isize) = and32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] -pub unsafe fn instr_26() -> () { segment_prefix_op(ES); } +pub unsafe fn instr_26() { segment_prefix_op(ES); } #[no_mangle] -pub unsafe fn instr_27() -> () { bcd_daa(); } +pub unsafe fn instr_27() { bcd_daa(); } #[no_mangle] -pub unsafe fn instr_28_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_28_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE8!(___, addr, sub8(___, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr_28_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_28_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, sub8(____0, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr16_29_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_29_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE16!(___, addr, sub16(___, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr16_29_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_29_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, sub16(____0, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr32_29_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_29_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE32!(___, addr, sub32(___, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr32_29_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_29_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, sub32(____0, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr_2A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_2A_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, sub8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr_2A_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_2A_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r, sub8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_2B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_2B_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, sub16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_2B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_2B_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r, sub16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_2B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_2B_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, sub32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_2B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_2B_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r, sub32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr_2C(mut imm8: i32) -> () { +pub unsafe fn instr_2C(mut imm8: i32) { *reg8.offset(AL as isize) = sub8(*reg8.offset(AL as isize) as i32, imm8) as u8; } #[no_mangle] -pub unsafe fn instr16_2D(mut imm16: i32) -> () { +pub unsafe fn instr16_2D(mut imm16: i32) { *reg16.offset(AX as isize) = sub16(*reg16.offset(AX as isize) as i32, imm16) as u16; } #[no_mangle] -pub unsafe fn instr32_2D(mut imm32: i32) -> () { +pub unsafe fn instr32_2D(mut imm32: i32) { *reg32s.offset(EAX as isize) = sub32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] -pub unsafe fn instr_2E() -> () { segment_prefix_op(CS); } +pub unsafe fn instr_2E() { segment_prefix_op(CS); } #[no_mangle] -pub unsafe fn instr_2F() -> () { bcd_das(); } +pub unsafe fn instr_2F() { bcd_das(); } #[no_mangle] -pub unsafe fn instr_30_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_30_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE8!(___, addr, xor8(___, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr_30_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_30_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, xor8(____0, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr16_31_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_31_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE16!(___, addr, xor16(___, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr16_31_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_31_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, xor16(____0, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr32_31_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_31_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE32!(___, addr, xor32(___, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr32_31_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_31_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, xor32(____0, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr_32_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_32_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, xor8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr_32_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_32_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r, xor8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_33_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_33_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, xor16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_33_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_33_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r, xor16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_33_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_33_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, xor32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_33_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_33_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r, xor32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr_34(mut imm8: i32) -> () { +pub unsafe fn instr_34(mut imm8: i32) { *reg8.offset(AL as isize) = xor8(*reg8.offset(AL as isize) as i32, imm8) as u8; } #[no_mangle] -pub unsafe fn instr16_35(mut imm16: i32) -> () { +pub unsafe fn instr16_35(mut imm16: i32) { *reg16.offset(AX as isize) = xor16(*reg16.offset(AX as isize) as i32, imm16) as u16; } #[no_mangle] -pub unsafe fn instr32_35(mut imm32: i32) -> () { +pub unsafe fn instr32_35(mut imm32: i32) { *reg32s.offset(EAX as isize) = xor32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] -pub unsafe fn instr_36() -> () { segment_prefix_op(SS); } +pub unsafe fn instr_36() { segment_prefix_op(SS); } #[no_mangle] -pub unsafe fn instr_37() -> () { bcd_aaa(); } +pub unsafe fn instr_37() { bcd_aaa(); } #[no_mangle] -pub unsafe fn instr_38_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_38_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); cmp8(____0, read_reg8(r)); } #[no_mangle] -pub unsafe fn instr_38_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_38_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); cmp8(____0, read_reg8(r)); } #[no_mangle] -pub unsafe fn instr16_39_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_39_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmp16(____0, read_reg16(r)); } #[no_mangle] -pub unsafe fn instr16_39_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_39_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); cmp16(____0, read_reg16(r)); } #[no_mangle] -pub unsafe fn instr32_39_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_39_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmp32(____0, read_reg32(r)); } #[no_mangle] -pub unsafe fn instr32_39_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_39_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); cmp32(____0, read_reg32(r)); } #[no_mangle] -pub unsafe fn instr_3A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_3A_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); cmp8(read_reg8(r), ____0); } #[no_mangle] -pub unsafe fn instr_3A_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_3A_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); cmp8(read_reg8(r), ____0); } #[no_mangle] -pub unsafe fn instr16_3B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_3B_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmp16(read_reg16(r), ____0); } #[no_mangle] -pub unsafe fn instr16_3B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_3B_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); cmp16(read_reg16(r), ____0); } #[no_mangle] -pub unsafe fn instr32_3B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_3B_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmp32(read_reg32(r), ____0); } #[no_mangle] -pub unsafe fn instr32_3B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_3B_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); cmp32(read_reg32(r), ____0); } #[no_mangle] -pub unsafe fn instr_3C(mut imm8: i32) -> () { cmp8(*reg8.offset(AL as isize) as i32, imm8); } +pub unsafe fn instr_3C(mut imm8: i32) { cmp8(*reg8.offset(AL as isize) as i32, imm8); } #[no_mangle] -pub unsafe fn instr16_3D(mut imm16: i32) -> () { cmp16(*reg16.offset(AX as isize) as i32, imm16); } +pub unsafe fn instr16_3D(mut imm16: i32) { cmp16(*reg16.offset(AX as isize) as i32, imm16); } #[no_mangle] -pub unsafe fn instr32_3D(mut imm32: i32) -> () { cmp32(*reg32s.offset(EAX as isize), imm32); } +pub unsafe fn instr32_3D(mut imm32: i32) { cmp32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] -pub unsafe fn instr_3E() -> () { segment_prefix_op(DS); } +pub unsafe fn instr_3E() { segment_prefix_op(DS); } #[no_mangle] -pub unsafe fn instr_3F() -> () { bcd_aas(); } +pub unsafe fn instr_3F() { bcd_aas(); } #[no_mangle] -pub unsafe fn instr16_40() -> () { +pub unsafe fn instr16_40() { *reg16.offset(AX as isize) = inc16(*reg16.offset(AX as isize) as i32) as u16; } #[no_mangle] -pub unsafe fn instr32_40() -> () { - *reg32s.offset(EAX as isize) = inc32(*reg32s.offset(EAX as isize)); -} +pub unsafe fn instr32_40() { *reg32s.offset(EAX as isize) = inc32(*reg32s.offset(EAX as isize)); } #[no_mangle] -pub unsafe fn instr16_41() -> () { +pub unsafe fn instr16_41() { *reg16.offset(CX as isize) = inc16(*reg16.offset(CX as isize) as i32) as u16; } #[no_mangle] -pub unsafe fn instr32_41() -> () { - *reg32s.offset(ECX as isize) = inc32(*reg32s.offset(ECX as isize)); -} +pub unsafe fn instr32_41() { *reg32s.offset(ECX as isize) = inc32(*reg32s.offset(ECX as isize)); } #[no_mangle] -pub unsafe fn instr16_42() -> () { +pub unsafe fn instr16_42() { *reg16.offset(DX as isize) = inc16(*reg16.offset(DX as isize) as i32) as u16; } #[no_mangle] -pub unsafe fn instr32_42() -> () { - *reg32s.offset(EDX as isize) = inc32(*reg32s.offset(EDX as isize)); -} +pub unsafe fn instr32_42() { *reg32s.offset(EDX as isize) = inc32(*reg32s.offset(EDX as isize)); } #[no_mangle] -pub unsafe fn instr16_43() -> () { +pub unsafe fn instr16_43() { *reg16.offset(BX as isize) = inc16(*reg16.offset(BX as isize) as i32) as u16; } #[no_mangle] -pub unsafe fn instr32_43() -> () { - *reg32s.offset(EBX as isize) = inc32(*reg32s.offset(EBX as isize)); -} +pub unsafe fn instr32_43() { *reg32s.offset(EBX as isize) = inc32(*reg32s.offset(EBX as isize)); } #[no_mangle] -pub unsafe fn instr16_44() -> () { +pub unsafe fn instr16_44() { *reg16.offset(SP as isize) = inc16(*reg16.offset(SP as isize) as i32) as u16; } #[no_mangle] -pub unsafe fn instr32_44() -> () { - *reg32s.offset(ESP as isize) = inc32(*reg32s.offset(ESP as isize)); -} +pub unsafe fn instr32_44() { *reg32s.offset(ESP as isize) = inc32(*reg32s.offset(ESP as isize)); } #[no_mangle] -pub unsafe fn instr16_45() -> () { +pub unsafe fn instr16_45() { *reg16.offset(BP as isize) = inc16(*reg16.offset(BP as isize) as i32) as u16; } #[no_mangle] -pub unsafe fn instr32_45() -> () { - *reg32s.offset(EBP as isize) = inc32(*reg32s.offset(EBP as isize)); -} +pub unsafe fn instr32_45() { *reg32s.offset(EBP as isize) = inc32(*reg32s.offset(EBP as isize)); } #[no_mangle] -pub unsafe fn instr16_46() -> () { +pub unsafe fn instr16_46() { *reg16.offset(SI as isize) = inc16(*reg16.offset(SI as isize) as i32) as u16; } #[no_mangle] -pub unsafe fn instr32_46() -> () { - *reg32s.offset(ESI as isize) = inc32(*reg32s.offset(ESI as isize)); -} +pub unsafe fn instr32_46() { *reg32s.offset(ESI as isize) = inc32(*reg32s.offset(ESI as isize)); } #[no_mangle] -pub unsafe fn instr16_47() -> () { +pub unsafe fn instr16_47() { *reg16.offset(DI as isize) = inc16(*reg16.offset(DI as isize) as i32) as u16; } #[no_mangle] -pub unsafe fn instr32_47() -> () { - *reg32s.offset(EDI as isize) = inc32(*reg32s.offset(EDI as isize)); -} +pub unsafe fn instr32_47() { *reg32s.offset(EDI as isize) = inc32(*reg32s.offset(EDI as isize)); } #[no_mangle] -pub unsafe fn instr16_48() -> () { +pub unsafe fn instr16_48() { *reg16.offset(AX as isize) = dec16(*reg16.offset(AX as isize) as i32) as u16; } #[no_mangle] -pub unsafe fn instr32_48() -> () { - *reg32s.offset(EAX as isize) = dec32(*reg32s.offset(EAX as isize)); -} +pub unsafe fn instr32_48() { *reg32s.offset(EAX as isize) = dec32(*reg32s.offset(EAX as isize)); } #[no_mangle] -pub unsafe fn instr16_49() -> () { +pub unsafe fn instr16_49() { *reg16.offset(CX as isize) = dec16(*reg16.offset(CX as isize) as i32) as u16; } #[no_mangle] -pub unsafe fn instr32_49() -> () { - *reg32s.offset(ECX as isize) = dec32(*reg32s.offset(ECX as isize)); -} +pub unsafe fn instr32_49() { *reg32s.offset(ECX as isize) = dec32(*reg32s.offset(ECX as isize)); } #[no_mangle] -pub unsafe fn instr16_4A() -> () { +pub unsafe fn instr16_4A() { *reg16.offset(DX as isize) = dec16(*reg16.offset(DX as isize) as i32) as u16; } #[no_mangle] -pub unsafe fn instr32_4A() -> () { - *reg32s.offset(EDX as isize) = dec32(*reg32s.offset(EDX as isize)); -} +pub unsafe fn instr32_4A() { *reg32s.offset(EDX as isize) = dec32(*reg32s.offset(EDX as isize)); } #[no_mangle] -pub unsafe fn instr16_4B() -> () { +pub unsafe fn instr16_4B() { *reg16.offset(BX as isize) = dec16(*reg16.offset(BX as isize) as i32) as u16; } #[no_mangle] -pub unsafe fn instr32_4B() -> () { - *reg32s.offset(EBX as isize) = dec32(*reg32s.offset(EBX as isize)); -} +pub unsafe fn instr32_4B() { *reg32s.offset(EBX as isize) = dec32(*reg32s.offset(EBX as isize)); } #[no_mangle] -pub unsafe fn instr16_4C() -> () { +pub unsafe fn instr16_4C() { *reg16.offset(SP as isize) = dec16(*reg16.offset(SP as isize) as i32) as u16; } #[no_mangle] -pub unsafe fn instr32_4C() -> () { - *reg32s.offset(ESP as isize) = dec32(*reg32s.offset(ESP as isize)); -} +pub unsafe fn instr32_4C() { *reg32s.offset(ESP as isize) = dec32(*reg32s.offset(ESP as isize)); } #[no_mangle] -pub unsafe fn instr16_4D() -> () { +pub unsafe fn instr16_4D() { *reg16.offset(BP as isize) = dec16(*reg16.offset(BP as isize) as i32) as u16; } #[no_mangle] -pub unsafe fn instr32_4D() -> () { - *reg32s.offset(EBP as isize) = dec32(*reg32s.offset(EBP as isize)); -} +pub unsafe fn instr32_4D() { *reg32s.offset(EBP as isize) = dec32(*reg32s.offset(EBP as isize)); } #[no_mangle] -pub unsafe fn instr16_4E() -> () { +pub unsafe fn instr16_4E() { *reg16.offset(SI as isize) = dec16(*reg16.offset(SI as isize) as i32) as u16; } #[no_mangle] -pub unsafe fn instr32_4E() -> () { - *reg32s.offset(ESI as isize) = dec32(*reg32s.offset(ESI as isize)); -} +pub unsafe fn instr32_4E() { *reg32s.offset(ESI as isize) = dec32(*reg32s.offset(ESI as isize)); } #[no_mangle] -pub unsafe fn instr16_4F() -> () { +pub unsafe fn instr16_4F() { *reg16.offset(DI as isize) = dec16(*reg16.offset(DI as isize) as i32) as u16; } #[no_mangle] -pub unsafe fn instr32_4F() -> () { - *reg32s.offset(EDI as isize) = dec32(*reg32s.offset(EDI as isize)); -} +pub unsafe fn instr32_4F() { *reg32s.offset(EDI as isize) = dec32(*reg32s.offset(EDI as isize)); } pub unsafe fn push16_reg(r: i32) { return_on_pagefault!(push16(*reg16.offset(r as isize) as i32)); @@ -860,128 +828,114 @@ pub unsafe fn push32_reg(r: i32) { } #[no_mangle] -pub unsafe fn instr16_50() -> () { push16_reg(AX) } +pub unsafe fn instr16_50() { push16_reg(AX) } #[no_mangle] -pub unsafe fn instr32_50() -> () { push32_reg(EAX) } +pub unsafe fn instr32_50() { push32_reg(EAX) } #[no_mangle] -pub unsafe fn instr16_51() -> () { push16_reg(CX) } +pub unsafe fn instr16_51() { push16_reg(CX) } #[no_mangle] -pub unsafe fn instr32_51() -> () { push32_reg(ECX) } +pub unsafe fn instr32_51() { push32_reg(ECX) } #[no_mangle] -pub unsafe fn instr16_52() -> () { push16_reg(DX) } +pub unsafe fn instr16_52() { push16_reg(DX) } #[no_mangle] -pub unsafe fn instr32_52() -> () { push32_reg(EDX) } +pub unsafe fn instr32_52() { push32_reg(EDX) } #[no_mangle] -pub unsafe fn instr16_53() -> () { push16_reg(BX) } +pub unsafe fn instr16_53() { push16_reg(BX) } #[no_mangle] -pub unsafe fn instr32_53() -> () { push32_reg(EBX) } +pub unsafe fn instr32_53() { push32_reg(EBX) } #[no_mangle] -pub unsafe fn instr16_54() -> () { push16_reg(SP) } +pub unsafe fn instr16_54() { push16_reg(SP) } #[no_mangle] -pub unsafe fn instr32_54() -> () { push32_reg(ESP) } +pub unsafe fn instr32_54() { push32_reg(ESP) } #[no_mangle] -pub unsafe fn instr16_55() -> () { push16_reg(BP) } +pub unsafe fn instr16_55() { push16_reg(BP) } #[no_mangle] -pub unsafe fn instr32_55() -> () { push32_reg(EBP) } +pub unsafe fn instr32_55() { push32_reg(EBP) } #[no_mangle] -pub unsafe fn instr16_56() -> () { push16_reg(SI) } +pub unsafe fn instr16_56() { push16_reg(SI) } #[no_mangle] -pub unsafe fn instr32_56() -> () { push32_reg(ESI) } +pub unsafe fn instr32_56() { push32_reg(ESI) } #[no_mangle] -pub unsafe fn instr16_57() -> () { push16_reg(DI) } +pub unsafe fn instr16_57() { push16_reg(DI) } #[no_mangle] -pub unsafe fn instr32_57() -> () { push32_reg(EDI) } +pub unsafe fn instr32_57() { push32_reg(EDI) } #[no_mangle] -pub unsafe fn instr16_58() -> () { - *reg16.offset(AX as isize) = return_on_pagefault!(pop16()) as u16; -} +pub unsafe fn instr16_58() { *reg16.offset(AX as isize) = return_on_pagefault!(pop16()) as u16; } #[no_mangle] -pub unsafe fn instr32_58() -> () { *reg32s.offset(EAX as isize) = return_on_pagefault!(pop32s()); } +pub unsafe fn instr32_58() { *reg32s.offset(EAX as isize) = return_on_pagefault!(pop32s()); } #[no_mangle] -pub unsafe fn instr16_59() -> () { - *reg16.offset(CX as isize) = return_on_pagefault!(pop16()) as u16; -} +pub unsafe fn instr16_59() { *reg16.offset(CX as isize) = return_on_pagefault!(pop16()) as u16; } #[no_mangle] -pub unsafe fn instr32_59() -> () { *reg32s.offset(ECX as isize) = return_on_pagefault!(pop32s()); } +pub unsafe fn instr32_59() { *reg32s.offset(ECX as isize) = return_on_pagefault!(pop32s()); } #[no_mangle] -pub unsafe fn instr16_5A() -> () { - *reg16.offset(DX as isize) = return_on_pagefault!(pop16()) as u16; -} +pub unsafe fn instr16_5A() { *reg16.offset(DX as isize) = return_on_pagefault!(pop16()) as u16; } #[no_mangle] -pub unsafe fn instr32_5A() -> () { *reg32s.offset(EDX as isize) = return_on_pagefault!(pop32s()); } +pub unsafe fn instr32_5A() { *reg32s.offset(EDX as isize) = return_on_pagefault!(pop32s()); } #[no_mangle] -pub unsafe fn instr16_5B() -> () { - *reg16.offset(BX as isize) = return_on_pagefault!(pop16()) as u16; -} +pub unsafe fn instr16_5B() { *reg16.offset(BX as isize) = return_on_pagefault!(pop16()) as u16; } #[no_mangle] -pub unsafe fn instr32_5B() -> () { *reg32s.offset(EBX as isize) = return_on_pagefault!(pop32s()); } +pub unsafe fn instr32_5B() { *reg32s.offset(EBX as isize) = return_on_pagefault!(pop32s()); } #[no_mangle] -pub unsafe fn instr16_5C() -> () { +pub unsafe fn instr16_5C() { *reg16.offset(SP as isize) = return_on_pagefault!(safe_read16(get_stack_pointer(0i32))) as u16; } #[no_mangle] -pub unsafe fn instr32_5C() -> () { +pub unsafe fn instr32_5C() { *reg32s.offset(ESP as isize) = return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))); } #[no_mangle] -pub unsafe fn instr16_5D() -> () { - *reg16.offset(BP as isize) = return_on_pagefault!(pop16()) as u16; -} +pub unsafe fn instr16_5D() { *reg16.offset(BP as isize) = return_on_pagefault!(pop16()) as u16; } #[no_mangle] -pub unsafe fn instr32_5D() -> () { *reg32s.offset(EBP as isize) = return_on_pagefault!(pop32s()); } +pub unsafe fn instr32_5D() { *reg32s.offset(EBP as isize) = return_on_pagefault!(pop32s()); } #[no_mangle] -pub unsafe fn instr16_5E() -> () { - *reg16.offset(SI as isize) = return_on_pagefault!(pop16()) as u16; -} +pub unsafe fn instr16_5E() { *reg16.offset(SI as isize) = return_on_pagefault!(pop16()) as u16; } #[no_mangle] -pub unsafe fn instr32_5E() -> () { *reg32s.offset(ESI as isize) = return_on_pagefault!(pop32s()); } +pub unsafe fn instr32_5E() { *reg32s.offset(ESI as isize) = return_on_pagefault!(pop32s()); } #[no_mangle] -pub unsafe fn instr16_5F() -> () { - *reg16.offset(DI as isize) = return_on_pagefault!(pop16()) as u16; -} +pub unsafe fn instr16_5F() { *reg16.offset(DI as isize) = return_on_pagefault!(pop16()) as u16; } #[no_mangle] -pub unsafe fn instr32_5F() -> () { *reg32s.offset(EDI as isize) = return_on_pagefault!(pop32s()); } +pub unsafe fn instr32_5F() { *reg32s.offset(EDI as isize) = return_on_pagefault!(pop32s()); } #[no_mangle] -pub unsafe fn instr16_60() -> () { pusha16(); } +pub unsafe fn instr16_60() { pusha16(); } #[no_mangle] -pub unsafe fn instr32_60() -> () { pusha32(); } +pub unsafe fn instr32_60() { pusha32(); } #[no_mangle] -pub unsafe fn instr16_61() -> () { popa16(); } +pub unsafe fn instr16_61() { popa16(); } #[no_mangle] -pub unsafe fn instr32_61() -> () { popa32(); } +pub unsafe fn instr32_61() { popa32(); } #[no_mangle] -pub unsafe fn instr_62_reg(mut r2: i32, mut r: i32) -> () { +pub unsafe fn instr_62_reg(mut r2: i32, mut r: i32) { // bound dbg_log!("Unimplemented BOUND instruction"); dbg_assert!(0 != 0i32); } #[no_mangle] -pub unsafe fn instr_62_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_62_mem(mut addr: i32, mut r: i32) { dbg_log!("Unimplemented BOUND instruction"); dbg_assert!(0 != 0i32); } #[no_mangle] -pub unsafe fn instr_63_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_63_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE16!(___, addr, arpl(___, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr_63_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_63_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, arpl(____0, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr_64() -> () { segment_prefix_op(FS); } +pub unsafe fn instr_64() { segment_prefix_op(FS); } #[no_mangle] -pub unsafe fn instr_65() -> () { segment_prefix_op(GS); } +pub unsafe fn instr_65() { segment_prefix_op(GS); } #[no_mangle] -pub unsafe fn instr_66() -> () { +pub unsafe fn instr_66() { // Operand-size override prefix *prefixes = (*prefixes as i32 | PREFIX_MASK_OPSIZE) as u8; run_prefix_instruction(); *prefixes = 0i32 as u8; } #[no_mangle] -pub unsafe fn instr_67() -> () { +pub unsafe fn instr_67() { // Address-size override prefix dbg_assert!(is_asize_32() as i32 == *is_32 as i32); *prefixes = (*prefixes as i32 | PREFIX_MASK_ADDRSIZE) as u8; @@ -989,581 +943,581 @@ pub unsafe fn instr_67() -> () { *prefixes = 0i32 as u8; } #[no_mangle] -pub unsafe fn instr16_68(mut imm16: i32) -> () { +pub unsafe fn instr16_68(mut imm16: i32) { return_on_pagefault!(push16(imm16)); } #[no_mangle] -pub unsafe fn instr32_68(mut imm32: i32) -> () { +pub unsafe fn instr32_68(mut imm32: i32) { return_on_pagefault!(push32(imm32)); } #[no_mangle] -pub unsafe fn instr16_69_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr16_69_mem(mut addr: i32, mut r: i32, mut imm: i32) { write_reg16(r, imul_reg16(return_on_pagefault!(safe_read16(addr)), imm)); } #[no_mangle] -pub unsafe fn instr16_69_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr16_69_reg(mut r1: i32, mut r: i32, mut imm: i32) { write_reg16(r, imul_reg16(read_reg16(r1), imm)); } #[no_mangle] -pub unsafe fn instr32_69_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr32_69_mem(mut addr: i32, mut r: i32, mut imm: i32) { write_reg32(r, imul_reg32(return_on_pagefault!(safe_read32s(addr)), imm)); } #[no_mangle] -pub unsafe fn instr32_69_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr32_69_reg(mut r1: i32, mut r: i32, mut imm: i32) { write_reg32(r, imul_reg32(read_reg32(r1), imm)); } #[no_mangle] -pub unsafe fn instr16_6A(mut imm8: i32) -> () { +pub unsafe fn instr16_6A(mut imm8: i32) { return_on_pagefault!(push16(imm8)); } #[no_mangle] -pub unsafe fn instr32_6A(mut imm8: i32) -> () { +pub unsafe fn instr32_6A(mut imm8: i32) { return_on_pagefault!(push32(imm8)); } #[no_mangle] -pub unsafe fn instr16_6B_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr16_6B_mem(mut addr: i32, mut r: i32, mut imm: i32) { write_reg16(r, imul_reg16(return_on_pagefault!(safe_read16(addr)), imm)); } #[no_mangle] -pub unsafe fn instr16_6B_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr16_6B_reg(mut r1: i32, mut r: i32, mut imm: i32) { write_reg16(r, imul_reg16(read_reg16(r1), imm)); } #[no_mangle] -pub unsafe fn instr32_6B_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr32_6B_mem(mut addr: i32, mut r: i32, mut imm: i32) { write_reg32(r, imul_reg32(return_on_pagefault!(safe_read32s(addr)), imm)); } #[no_mangle] -pub unsafe fn instr32_6B_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr32_6B_reg(mut r1: i32, mut r: i32, mut imm: i32) { write_reg32(r, imul_reg32(read_reg32(r1), imm)); } #[no_mangle] -pub unsafe fn instr_6C() -> () { insb_no_rep(); } +pub unsafe fn instr_6C() { insb_no_rep(); } #[no_mangle] -pub unsafe fn instr16_6D() -> () { insw_no_rep(); } +pub unsafe fn instr16_6D() { insw_no_rep(); } #[no_mangle] -pub unsafe fn instr32_6D() -> () { insd_no_rep(); } +pub unsafe fn instr32_6D() { insd_no_rep(); } #[no_mangle] -pub unsafe fn instr_6E() -> () { outsb_no_rep(); } +pub unsafe fn instr_6E() { outsb_no_rep(); } #[no_mangle] -pub unsafe fn instr16_6F() -> () { outsw_no_rep(); } +pub unsafe fn instr16_6F() { outsw_no_rep(); } #[no_mangle] -pub unsafe fn instr32_6F() -> () { outsd_no_rep(); } +pub unsafe fn instr32_6F() { outsd_no_rep(); } #[no_mangle] -pub unsafe fn instr_80_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_0_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE8!(___, addr, add8(___, imm)); } #[no_mangle] -pub unsafe fn instr_80_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_0_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, add8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_80_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_1_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE8!(___, addr, or8(___, imm)); } #[no_mangle] -pub unsafe fn instr_80_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_1_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, or8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_80_2_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_2_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE8!(___, addr, adc8(___, imm)); } #[no_mangle] -pub unsafe fn instr_80_2_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_2_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, adc8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_80_3_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_3_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE8!(___, addr, sbb8(___, imm)); } #[no_mangle] -pub unsafe fn instr_80_3_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_3_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, sbb8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_80_4_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_4_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE8!(___, addr, and8(___, imm)); } #[no_mangle] -pub unsafe fn instr_80_4_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_4_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, and8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_80_5_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_5_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE8!(___, addr, sub8(___, imm)); } #[no_mangle] -pub unsafe fn instr_80_5_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_5_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, sub8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_80_6_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_6_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE8!(___, addr, xor8(___, imm)); } #[no_mangle] -pub unsafe fn instr_80_6_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_6_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, xor8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_80_7_reg(mut r: i32, mut imm: i32) -> () { cmp8(read_reg8(r), imm); } +pub unsafe fn instr_80_7_reg(mut r: i32, mut imm: i32) { cmp8(read_reg8(r), imm); } #[no_mangle] -pub unsafe fn instr_80_7_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_80_7_mem(mut addr: i32, mut imm: i32) { cmp8(return_on_pagefault!(safe_read8(addr)), imm); } #[no_mangle] -pub unsafe fn instr16_81_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_0_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, add16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_81_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_0_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, add16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_81_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_1_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, or16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_81_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_1_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, or16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_81_2_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_2_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, adc16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_81_2_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_2_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, adc16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_81_3_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_3_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, sbb16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_81_3_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_3_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, sbb16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_81_4_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_4_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, and16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_81_4_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_4_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, and16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_81_5_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_5_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, sub16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_81_5_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_5_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, sub16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_81_6_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_6_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, xor16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_81_6_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_6_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, xor16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_81_7_reg(mut r: i32, mut imm: i32) -> () { cmp16(read_reg16(r), imm); } +pub unsafe fn instr16_81_7_reg(mut r: i32, mut imm: i32) { cmp16(read_reg16(r), imm); } #[no_mangle] -pub unsafe fn instr16_81_7_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_81_7_mem(mut addr: i32, mut imm: i32) { cmp16(return_on_pagefault!(safe_read16(addr)), imm); } #[no_mangle] -pub unsafe fn instr32_81_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_0_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, add32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_81_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_0_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, add32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_81_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_1_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, or32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_81_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_1_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, or32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_81_2_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_2_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, adc32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_81_2_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_2_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, adc32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_81_3_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_3_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, sbb32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_81_3_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_3_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, sbb32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_81_4_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_4_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, and32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_81_4_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_4_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, and32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_81_5_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_5_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, sub32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_81_5_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_5_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, sub32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_81_6_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_6_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, xor32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_81_6_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_6_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, xor32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_81_7_reg(mut r: i32, mut imm: i32) -> () { cmp32(read_reg32(r), imm); } +pub unsafe fn instr32_81_7_reg(mut r: i32, mut imm: i32) { cmp32(read_reg32(r), imm); } #[no_mangle] -pub unsafe fn instr32_81_7_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_81_7_mem(mut addr: i32, mut imm: i32) { cmp32(return_on_pagefault!(safe_read32s(addr)), imm); } #[no_mangle] -pub unsafe fn instr_82_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_0_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE8!(___, addr, add8(___, imm)); } #[no_mangle] -pub unsafe fn instr_82_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_0_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, add8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_82_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_1_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE8!(___, addr, or8(___, imm)); } #[no_mangle] -pub unsafe fn instr_82_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_1_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, or8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_82_2_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_2_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE8!(___, addr, adc8(___, imm)); } #[no_mangle] -pub unsafe fn instr_82_2_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_2_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, adc8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_82_3_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_3_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE8!(___, addr, sbb8(___, imm)); } #[no_mangle] -pub unsafe fn instr_82_3_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_3_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, sbb8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_82_4_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_4_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE8!(___, addr, and8(___, imm)); } #[no_mangle] -pub unsafe fn instr_82_4_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_4_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, and8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_82_5_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_5_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE8!(___, addr, sub8(___, imm)); } #[no_mangle] -pub unsafe fn instr_82_5_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_5_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, sub8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_82_6_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_6_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE8!(___, addr, xor8(___, imm)); } #[no_mangle] -pub unsafe fn instr_82_6_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_6_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, xor8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_82_7_reg(mut r: i32, mut imm: i32) -> () { cmp8(read_reg8(r), imm); } +pub unsafe fn instr_82_7_reg(mut r: i32, mut imm: i32) { cmp8(read_reg8(r), imm); } #[no_mangle] -pub unsafe fn instr_82_7_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_82_7_mem(mut addr: i32, mut imm: i32) { cmp8(return_on_pagefault!(safe_read8(addr)), imm); } #[no_mangle] -pub unsafe fn instr16_83_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_0_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, add16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_83_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_0_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, add16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_83_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_1_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, or16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_83_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_1_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, or16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_83_2_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_2_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, adc16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_83_2_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_2_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, adc16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_83_3_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_3_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, sbb16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_83_3_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_3_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, sbb16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_83_4_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_4_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, and16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_83_4_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_4_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, and16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_83_5_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_5_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, sub16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_83_5_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_5_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, sub16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_83_6_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_6_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, xor16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_83_6_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_6_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, xor16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_83_7_reg(mut r: i32, mut imm: i32) -> () { cmp16(read_reg16(r), imm); } +pub unsafe fn instr16_83_7_reg(mut r: i32, mut imm: i32) { cmp16(read_reg16(r), imm); } #[no_mangle] -pub unsafe fn instr16_83_7_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_83_7_mem(mut addr: i32, mut imm: i32) { cmp16(return_on_pagefault!(safe_read16(addr)), imm); } #[no_mangle] -pub unsafe fn instr32_83_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_0_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, add32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_83_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_0_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, add32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_83_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_1_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, or32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_83_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_1_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, or32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_83_2_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_2_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, adc32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_83_2_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_2_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, adc32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_83_3_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_3_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, sbb32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_83_3_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_3_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, sbb32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_83_4_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_4_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, and32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_83_4_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_4_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, and32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_83_5_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_5_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, sub32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_83_5_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_5_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, sub32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_83_6_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_6_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, xor32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_83_6_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_6_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, xor32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_83_7_reg(mut r: i32, mut imm: i32) -> () { cmp32(read_reg32(r), imm); } +pub unsafe fn instr32_83_7_reg(mut r: i32, mut imm: i32) { cmp32(read_reg32(r), imm); } #[no_mangle] -pub unsafe fn instr32_83_7_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_83_7_mem(mut addr: i32, mut imm: i32) { cmp32(return_on_pagefault!(safe_read32s(addr)), imm); } #[no_mangle] -pub unsafe fn instr_84_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_84_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); test8(____0, read_reg8(r)); } #[no_mangle] -pub unsafe fn instr_84_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_84_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); test8(____0, read_reg8(r)); } #[no_mangle] -pub unsafe fn instr16_85_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_85_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); test16(____0, read_reg16(r)); } #[no_mangle] -pub unsafe fn instr16_85_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_85_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); test16(____0, read_reg16(r)); } #[no_mangle] -pub unsafe fn instr32_85_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_85_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); test32(____0, read_reg32(r)); } #[no_mangle] -pub unsafe fn instr32_85_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_85_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); test32(____0, read_reg32(r)); } #[no_mangle] -pub unsafe fn instr_86_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_86_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE8!(___, addr, xchg8(___, get_reg8_index(r))); } #[no_mangle] -pub unsafe fn instr_86_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_86_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, xchg8(____0, get_reg8_index(r))); } #[no_mangle] -pub unsafe fn instr16_87_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_87_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE16!(___, addr, xchg16(___, get_reg16_index(r))); } #[no_mangle] -pub unsafe fn instr16_87_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_87_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, xchg16(____0, get_reg16_index(r))); } #[no_mangle] -pub unsafe fn instr32_87_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_87_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE32!(___, addr, xchg32(___, r)); } #[no_mangle] -pub unsafe fn instr32_87_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_87_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, xchg32(____0, r)); } #[no_mangle] -pub unsafe fn instr_88_reg(mut r2: i32, mut r: i32) -> () { write_reg8(r2, read_reg8(r)); } +pub unsafe fn instr_88_reg(mut r2: i32, mut r: i32) { write_reg8(r2, read_reg8(r)); } #[no_mangle] -pub unsafe fn instr_88_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_88_mem(mut addr: i32, mut r: i32) { return_on_pagefault!(safe_write8(addr, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr16_89_reg(mut r2: i32, mut r: i32) -> () { write_reg16(r2, read_reg16(r)); } +pub unsafe fn instr16_89_reg(mut r2: i32, mut r: i32) { write_reg16(r2, read_reg16(r)); } #[no_mangle] -pub unsafe fn instr16_89_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_89_mem(mut addr: i32, mut r: i32) { return_on_pagefault!(safe_write16(addr, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr32_89_reg(mut r2: i32, mut r: i32) -> () { write_reg32(r2, read_reg32(r)); } +pub unsafe fn instr32_89_reg(mut r2: i32, mut r: i32) { write_reg32(r2, read_reg32(r)); } #[no_mangle] -pub unsafe fn instr32_89_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_89_mem(mut addr: i32, mut r: i32) { return_on_pagefault!(safe_write32(addr, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr_8A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_8A_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, ____0); } #[no_mangle] -pub unsafe fn instr_8A_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_8A_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r, ____0); } #[no_mangle] -pub unsafe fn instr16_8B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_8B_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, ____0); } #[no_mangle] -pub unsafe fn instr16_8B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_8B_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r, ____0); } #[no_mangle] -pub unsafe fn instr32_8B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_8B_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, ____0); } #[no_mangle] -pub unsafe fn instr32_8B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_8B_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r, ____0); } @@ -1579,36 +1533,36 @@ pub unsafe fn instr_8C_check_sreg(mut seg: i32) -> bool { }; } #[no_mangle] -pub unsafe fn instr16_8C_reg(mut r: i32, mut seg: i32) -> () { +pub unsafe fn instr16_8C_reg(mut r: i32, mut seg: i32) { if instr_8C_check_sreg(seg) { write_reg16(r, *sreg.offset(seg as isize) as i32); }; } #[no_mangle] -pub unsafe fn instr16_8C_mem(mut addr: i32, mut seg: i32) -> () { +pub unsafe fn instr16_8C_mem(mut addr: i32, mut seg: i32) { if instr_8C_check_sreg(seg) { return_on_pagefault!(safe_write16(addr, *sreg.offset(seg as isize) as i32)); }; } #[no_mangle] -pub unsafe fn instr32_8C_reg(mut r: i32, mut seg: i32) -> () { +pub unsafe fn instr32_8C_reg(mut r: i32, mut seg: i32) { if instr_8C_check_sreg(seg) { write_reg32(r, *sreg.offset(seg as isize) as i32); }; } #[no_mangle] -pub unsafe fn instr32_8C_mem(mut addr: i32, mut seg: i32) -> () { +pub unsafe fn instr32_8C_mem(mut addr: i32, mut seg: i32) { if instr_8C_check_sreg(seg) { return_on_pagefault!(safe_write32(addr, *sreg.offset(seg as isize) as i32)); }; } #[no_mangle] -pub unsafe fn instr16_8D_reg(mut r: i32, mut r2: i32) -> () { +pub unsafe fn instr16_8D_reg(mut r: i32, mut r2: i32) { dbg_log!("lea #ud"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_8D_mem(modrm_byte: i32, mut r: i32) -> () { +pub unsafe fn instr16_8D_mem(modrm_byte: i32, mut r: i32) { // lea *prefixes = (*prefixes as i32 | SEG_PREFIX_ZERO) as u8; if let Ok(addr) = modrm_resolve(modrm_byte) { @@ -1617,12 +1571,12 @@ pub unsafe fn instr16_8D_mem(modrm_byte: i32, mut r: i32) -> () { *prefixes = 0i32 as u8; } #[no_mangle] -pub unsafe fn instr32_8D_reg(mut r: i32, mut r2: i32) -> () { +pub unsafe fn instr32_8D_reg(mut r: i32, mut r2: i32) { dbg_log!("lea #ud"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr32_8D_mem(modrm_byte: i32, mut r: i32) -> () { +pub unsafe fn instr32_8D_mem(modrm_byte: i32, mut r: i32) { // lea // override prefix, so modrm_resolve does not return the segment part *prefixes = (*prefixes as i32 | SEG_PREFIX_ZERO) as u8; @@ -1632,7 +1586,7 @@ pub unsafe fn instr32_8D_mem(modrm_byte: i32, mut r: i32) -> () { *prefixes = 0i32 as u8; } #[no_mangle] -pub unsafe fn instr_8E_helper(mut data: i32, mut mod_0: i32) -> () { +pub unsafe fn instr_8E_helper(mut data: i32, mut mod_0: i32) { if mod_0 == ES || mod_0 == SS || mod_0 == DS || mod_0 == FS || mod_0 == GS { if !switch_seg(mod_0, data) { return; @@ -1644,18 +1598,18 @@ pub unsafe fn instr_8E_helper(mut data: i32, mut mod_0: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_8E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_8E_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); instr_8E_helper(____0, r); } #[no_mangle] -pub unsafe fn instr_8E_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_8E_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); instr_8E_helper(____0, r); } #[no_mangle] -pub unsafe fn instr16_8F_0_mem(modrm_byte: i32) -> () { +pub unsafe fn instr16_8F_0_mem(modrm_byte: i32) { // pop // Update esp *before* resolving the address adjust_stack_reg(2i32); @@ -1674,7 +1628,7 @@ pub unsafe fn instr16_8F_0_mem(modrm_byte: i32) -> () { } #[no_mangle] -pub unsafe fn instr16_8F_0_mem_jit(addr: i32) -> () { +pub unsafe fn instr16_8F_0_mem_jit(addr: i32) { adjust_stack_reg(-2i32); let mut stack_value: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0i32))); return_on_pagefault!(safe_write16(addr, stack_value)); @@ -1682,9 +1636,9 @@ pub unsafe fn instr16_8F_0_mem_jit(addr: i32) -> () { } #[no_mangle] -pub unsafe fn instr16_8F_0_reg(mut r: i32) -> () { write_reg16(r, return_on_pagefault!(pop16())); } +pub unsafe fn instr16_8F_0_reg(mut r: i32) { write_reg16(r, return_on_pagefault!(pop16())); } #[no_mangle] -pub unsafe fn instr32_8F_0_mem(modrm_byte: i32) -> () { +pub unsafe fn instr32_8F_0_mem(modrm_byte: i32) { // Update esp *before* resolving the address adjust_stack_reg(4i32); match modrm_resolve(modrm_byte) { @@ -1702,7 +1656,7 @@ pub unsafe fn instr32_8F_0_mem(modrm_byte: i32) -> () { } #[no_mangle] -pub unsafe fn instr32_8F_0_mem_jit(addr: i32) -> () { +pub unsafe fn instr32_8F_0_mem_jit(addr: i32) { adjust_stack_reg(-4i32); let mut stack_value: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))); return_on_pagefault!(safe_write32(addr, stack_value)); @@ -1710,60 +1664,56 @@ pub unsafe fn instr32_8F_0_mem_jit(addr: i32) -> () { } #[no_mangle] -pub unsafe fn instr32_8F_0_reg(mut r: i32) -> () { write_reg32(r, return_on_pagefault!(pop32s())); } +pub unsafe fn instr32_8F_0_reg(mut r: i32) { write_reg32(r, return_on_pagefault!(pop32s())); } #[no_mangle] -pub unsafe fn instr_90() -> () {} +pub unsafe fn instr_90() {} #[no_mangle] -pub unsafe fn instr16_91() -> () { xchg16r(CX); } +pub unsafe fn instr16_91() { xchg16r(CX); } #[no_mangle] -pub unsafe fn instr32_91() -> () { xchg32r(ECX); } +pub unsafe fn instr32_91() { xchg32r(ECX); } #[no_mangle] -pub unsafe fn instr16_92() -> () { xchg16r(DX); } +pub unsafe fn instr16_92() { xchg16r(DX); } #[no_mangle] -pub unsafe fn instr32_92() -> () { xchg32r(EDX); } +pub unsafe fn instr32_92() { xchg32r(EDX); } #[no_mangle] -pub unsafe fn instr16_93() -> () { xchg16r(BX); } +pub unsafe fn instr16_93() { xchg16r(BX); } #[no_mangle] -pub unsafe fn instr32_93() -> () { xchg32r(EBX); } +pub unsafe fn instr32_93() { xchg32r(EBX); } #[no_mangle] -pub unsafe fn instr16_94() -> () { xchg16r(SP); } +pub unsafe fn instr16_94() { xchg16r(SP); } #[no_mangle] -pub unsafe fn instr32_94() -> () { xchg32r(ESP); } +pub unsafe fn instr32_94() { xchg32r(ESP); } #[no_mangle] -pub unsafe fn instr16_95() -> () { xchg16r(BP); } +pub unsafe fn instr16_95() { xchg16r(BP); } #[no_mangle] -pub unsafe fn instr32_95() -> () { xchg32r(EBP); } +pub unsafe fn instr32_95() { xchg32r(EBP); } #[no_mangle] -pub unsafe fn instr16_96() -> () { xchg16r(SI); } +pub unsafe fn instr16_96() { xchg16r(SI); } #[no_mangle] -pub unsafe fn instr32_96() -> () { xchg32r(ESI); } +pub unsafe fn instr32_96() { xchg32r(ESI); } #[no_mangle] -pub unsafe fn instr16_97() -> () { xchg16r(DI); } +pub unsafe fn instr16_97() { xchg16r(DI); } #[no_mangle] -pub unsafe fn instr32_97() -> () { xchg32r(EDI); } +pub unsafe fn instr32_97() { xchg32r(EDI); } #[no_mangle] -pub unsafe fn instr16_98() -> () { *reg16.offset(AX as isize) = *reg8s.offset(AL as isize) as u16; } +pub unsafe fn instr16_98() { *reg16.offset(AX as isize) = *reg8s.offset(AL as isize) as u16; } #[no_mangle] -pub unsafe fn instr32_98() -> () { - *reg32s.offset(EAX as isize) = *reg16s.offset(AX as isize) as i32; -} +pub unsafe fn instr32_98() { *reg32s.offset(EAX as isize) = *reg16s.offset(AX as isize) as i32; } #[no_mangle] -pub unsafe fn instr16_99() -> () { +pub unsafe fn instr16_99() { *reg16.offset(DX as isize) = (*reg16s.offset(AX as isize) as i32 >> 15i32) as u16; } #[no_mangle] -pub unsafe fn instr32_99() -> () { - *reg32s.offset(EDX as isize) = *reg32s.offset(EAX as isize) >> 31i32; -} +pub unsafe fn instr32_99() { *reg32s.offset(EDX as isize) = *reg32s.offset(EAX as isize) >> 31i32; } #[no_mangle] -pub unsafe fn instr16_9A(mut new_ip: i32, mut new_cs: i32) -> () { +pub unsafe fn instr16_9A(mut new_ip: i32, mut new_cs: i32) { // callf far_jump(new_ip, new_cs, true); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe fn instr32_9A(mut new_ip: i32, mut new_cs: i32) -> () { +pub unsafe fn instr32_9A(mut new_ip: i32, mut new_cs: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { if 0 != new_ip as u32 & 4294901760u32 { dbg_assert!(0 != 0i32); @@ -1773,7 +1723,7 @@ pub unsafe fn instr32_9A(mut new_ip: i32, mut new_cs: i32) -> () { dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe fn instr_9B() -> () { +pub unsafe fn instr_9B() { // fwait: check for pending fpu exceptions if *cr & (CR0_MP | CR0_TS) == CR0_MP | CR0_TS { // Note: Different from task_switch_test @@ -1785,7 +1735,7 @@ pub unsafe fn instr_9B() -> () { }; } #[no_mangle] -pub unsafe fn instr16_9C() -> () { +pub unsafe fn instr16_9C() { // pushf if 0 != *flags & FLAG_VM && getiopl() < 3i32 { dbg_assert!(*protected_mode); @@ -1797,7 +1747,7 @@ pub unsafe fn instr16_9C() -> () { }; } #[no_mangle] -pub unsafe fn instr32_9C() -> () { +pub unsafe fn instr32_9C() { // pushf if 0 != *flags & FLAG_VM && getiopl() < 3i32 { // trap to virtual 8086 monitor @@ -1811,7 +1761,7 @@ pub unsafe fn instr32_9C() -> () { }; } #[no_mangle] -pub unsafe fn instr16_9D() -> () { +pub unsafe fn instr16_9D() { // popf if 0 != *flags & FLAG_VM && getiopl() < 3i32 { dbg_log!("popf #gp"); @@ -1831,7 +1781,7 @@ pub unsafe fn instr16_9D() -> () { }; } #[no_mangle] -pub unsafe fn instr32_9D() -> () { +pub unsafe fn instr32_9D() { // popf if 0 != *flags & FLAG_VM && getiopl() < 3i32 { dbg_log!("popf #gp"); @@ -1845,36 +1795,36 @@ pub unsafe fn instr32_9D() -> () { }; } #[no_mangle] -pub unsafe fn instr_9E() -> () { +pub unsafe fn instr_9E() { // sahf *flags = *flags & !255i32 | *reg8.offset(AH as isize) as i32; *flags = *flags & FLAGS_MASK | FLAGS_DEFAULT; *flags_changed &= !255i32; } #[no_mangle] -pub unsafe fn instr_9F() -> () { +pub unsafe fn instr_9F() { // lahf *reg8.offset(AH as isize) = get_eflags() as u8; } #[no_mangle] -pub unsafe fn instr_A0(mut moffs: i32) -> () { +pub unsafe fn instr_A0(mut moffs: i32) { // mov let mut data: i32 = return_on_pagefault!(safe_read8(get_seg_prefix_ds(moffs))); *reg8.offset(AL as isize) = data as u8; } #[no_mangle] -pub unsafe fn instr16_A1(mut moffs: i32) -> () { +pub unsafe fn instr16_A1(mut moffs: i32) { // mov let mut data: i32 = return_on_pagefault!(safe_read16(get_seg_prefix_ds(moffs))); *reg16.offset(AX as isize) = data as u16; } #[no_mangle] -pub unsafe fn instr32_A1(mut moffs: i32) -> () { +pub unsafe fn instr32_A1(mut moffs: i32) { let mut data: i32 = return_on_pagefault!(safe_read32s(get_seg_prefix_ds(moffs))); *reg32s.offset(EAX as isize) = data; } #[no_mangle] -pub unsafe fn instr_A2(mut moffs: i32) -> () { +pub unsafe fn instr_A2(mut moffs: i32) { // mov return_on_pagefault!(safe_write8( get_seg_prefix_ds(moffs), @@ -1882,7 +1832,7 @@ pub unsafe fn instr_A2(mut moffs: i32) -> () { )); } #[no_mangle] -pub unsafe fn instr16_A3(mut moffs: i32) -> () { +pub unsafe fn instr16_A3(mut moffs: i32) { // mov return_on_pagefault!(safe_write16( get_seg_prefix_ds(moffs), @@ -1890,314 +1840,314 @@ pub unsafe fn instr16_A3(mut moffs: i32) -> () { )); } #[no_mangle] -pub unsafe fn instr32_A3(mut moffs: i32) -> () { +pub unsafe fn instr32_A3(mut moffs: i32) { return_on_pagefault!(safe_write32( get_seg_prefix_ds(moffs), *reg32s.offset(EAX as isize) )); } #[no_mangle] -pub unsafe fn instr_A4() -> () { movsb_no_rep(); } +pub unsafe fn instr_A4() { movsb_no_rep(); } #[no_mangle] -pub unsafe fn instr16_A5() -> () { movsw_no_rep(); } +pub unsafe fn instr16_A5() { movsw_no_rep(); } #[no_mangle] -pub unsafe fn instr32_A5() -> () { movsd_no_rep(); } +pub unsafe fn instr32_A5() { movsd_no_rep(); } #[no_mangle] -pub unsafe fn instr_A6() -> () { cmpsb_no_rep(); } +pub unsafe fn instr_A6() { cmpsb_no_rep(); } #[no_mangle] -pub unsafe fn instr16_A7() -> () { cmpsw_no_rep(); } +pub unsafe fn instr16_A7() { cmpsw_no_rep(); } #[no_mangle] -pub unsafe fn instr32_A7() -> () { cmpsd_no_rep(); } +pub unsafe fn instr32_A7() { cmpsd_no_rep(); } #[no_mangle] -pub unsafe fn instr_A8(mut imm8: i32) -> () { test8(*reg8.offset(AL as isize) as i32, imm8); } +pub unsafe fn instr_A8(mut imm8: i32) { test8(*reg8.offset(AL as isize) as i32, imm8); } #[no_mangle] -pub unsafe fn instr16_A9(mut imm16: i32) -> () { test16(*reg16.offset(AX as isize) as i32, imm16); } +pub unsafe fn instr16_A9(mut imm16: i32) { test16(*reg16.offset(AX as isize) as i32, imm16); } #[no_mangle] -pub unsafe fn instr32_A9(mut imm32: i32) -> () { test32(*reg32s.offset(EAX as isize), imm32); } +pub unsafe fn instr32_A9(mut imm32: i32) { test32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] -pub unsafe fn instr_AA() -> () { stosb_no_rep(); } +pub unsafe fn instr_AA() { stosb_no_rep(); } #[no_mangle] -pub unsafe fn instr16_AB() -> () { stosw_no_rep(); } +pub unsafe fn instr16_AB() { stosw_no_rep(); } #[no_mangle] -pub unsafe fn instr32_AB() -> () { stosd_no_rep(); } +pub unsafe fn instr32_AB() { stosd_no_rep(); } #[no_mangle] -pub unsafe fn instr_AC() -> () { lodsb_no_rep(); } +pub unsafe fn instr_AC() { lodsb_no_rep(); } #[no_mangle] -pub unsafe fn instr16_AD() -> () { lodsw_no_rep(); } +pub unsafe fn instr16_AD() { lodsw_no_rep(); } #[no_mangle] -pub unsafe fn instr32_AD() -> () { lodsd_no_rep(); } +pub unsafe fn instr32_AD() { lodsd_no_rep(); } #[no_mangle] -pub unsafe fn instr_AE() -> () { scasb_no_rep(); } +pub unsafe fn instr_AE() { scasb_no_rep(); } #[no_mangle] -pub unsafe fn instr16_AF() -> () { scasw_no_rep(); } +pub unsafe fn instr16_AF() { scasw_no_rep(); } #[no_mangle] -pub unsafe fn instr32_AF() -> () { scasd_no_rep(); } +pub unsafe fn instr32_AF() { scasd_no_rep(); } #[no_mangle] -pub unsafe fn instr_B0(mut imm8: i32) -> () { *reg8.offset(AL as isize) = imm8 as u8; } +pub unsafe fn instr_B0(mut imm8: i32) { *reg8.offset(AL as isize) = imm8 as u8; } #[no_mangle] -pub unsafe fn instr_B1(mut imm8: i32) -> () { *reg8.offset(CL as isize) = imm8 as u8; } +pub unsafe fn instr_B1(mut imm8: i32) { *reg8.offset(CL as isize) = imm8 as u8; } #[no_mangle] -pub unsafe fn instr_B2(mut imm8: i32) -> () { *reg8.offset(DL as isize) = imm8 as u8; } +pub unsafe fn instr_B2(mut imm8: i32) { *reg8.offset(DL as isize) = imm8 as u8; } #[no_mangle] -pub unsafe fn instr_B3(mut imm8: i32) -> () { *reg8.offset(BL as isize) = imm8 as u8; } +pub unsafe fn instr_B3(mut imm8: i32) { *reg8.offset(BL as isize) = imm8 as u8; } #[no_mangle] -pub unsafe fn instr_B4(mut imm8: i32) -> () { *reg8.offset(AH as isize) = imm8 as u8; } +pub unsafe fn instr_B4(mut imm8: i32) { *reg8.offset(AH as isize) = imm8 as u8; } #[no_mangle] -pub unsafe fn instr_B5(mut imm8: i32) -> () { *reg8.offset(CH as isize) = imm8 as u8; } +pub unsafe fn instr_B5(mut imm8: i32) { *reg8.offset(CH as isize) = imm8 as u8; } #[no_mangle] -pub unsafe fn instr_B6(mut imm8: i32) -> () { *reg8.offset(DH as isize) = imm8 as u8; } +pub unsafe fn instr_B6(mut imm8: i32) { *reg8.offset(DH as isize) = imm8 as u8; } #[no_mangle] -pub unsafe fn instr_B7(mut imm8: i32) -> () { *reg8.offset(BH as isize) = imm8 as u8; } +pub unsafe fn instr_B7(mut imm8: i32) { *reg8.offset(BH as isize) = imm8 as u8; } #[no_mangle] -pub unsafe fn instr16_B8(mut imm: i32) -> () { *reg16.offset(AX as isize) = imm as u16; } +pub unsafe fn instr16_B8(mut imm: i32) { *reg16.offset(AX as isize) = imm as u16; } #[no_mangle] -pub unsafe fn instr32_B8(mut imm: i32) -> () { *reg32s.offset(EAX as isize) = imm; } +pub unsafe fn instr32_B8(mut imm: i32) { *reg32s.offset(EAX as isize) = imm; } #[no_mangle] -pub unsafe fn instr16_B9(mut imm: i32) -> () { *reg16.offset(CX as isize) = imm as u16; } +pub unsafe fn instr16_B9(mut imm: i32) { *reg16.offset(CX as isize) = imm as u16; } #[no_mangle] -pub unsafe fn instr32_B9(mut imm: i32) -> () { *reg32s.offset(ECX as isize) = imm; } +pub unsafe fn instr32_B9(mut imm: i32) { *reg32s.offset(ECX as isize) = imm; } #[no_mangle] -pub unsafe fn instr16_BA(mut imm: i32) -> () { *reg16.offset(DX as isize) = imm as u16; } +pub unsafe fn instr16_BA(mut imm: i32) { *reg16.offset(DX as isize) = imm as u16; } #[no_mangle] -pub unsafe fn instr32_BA(mut imm: i32) -> () { *reg32s.offset(EDX as isize) = imm; } +pub unsafe fn instr32_BA(mut imm: i32) { *reg32s.offset(EDX as isize) = imm; } #[no_mangle] -pub unsafe fn instr16_BB(mut imm: i32) -> () { *reg16.offset(BX as isize) = imm as u16; } +pub unsafe fn instr16_BB(mut imm: i32) { *reg16.offset(BX as isize) = imm as u16; } #[no_mangle] -pub unsafe fn instr32_BB(mut imm: i32) -> () { *reg32s.offset(EBX as isize) = imm; } +pub unsafe fn instr32_BB(mut imm: i32) { *reg32s.offset(EBX as isize) = imm; } #[no_mangle] -pub unsafe fn instr16_BC(mut imm: i32) -> () { *reg16.offset(SP as isize) = imm as u16; } +pub unsafe fn instr16_BC(mut imm: i32) { *reg16.offset(SP as isize) = imm as u16; } #[no_mangle] -pub unsafe fn instr32_BC(mut imm: i32) -> () { *reg32s.offset(ESP as isize) = imm; } +pub unsafe fn instr32_BC(mut imm: i32) { *reg32s.offset(ESP as isize) = imm; } #[no_mangle] -pub unsafe fn instr16_BD(mut imm: i32) -> () { *reg16.offset(BP as isize) = imm as u16; } +pub unsafe fn instr16_BD(mut imm: i32) { *reg16.offset(BP as isize) = imm as u16; } #[no_mangle] -pub unsafe fn instr32_BD(mut imm: i32) -> () { *reg32s.offset(EBP as isize) = imm; } +pub unsafe fn instr32_BD(mut imm: i32) { *reg32s.offset(EBP as isize) = imm; } #[no_mangle] -pub unsafe fn instr16_BE(mut imm: i32) -> () { *reg16.offset(SI as isize) = imm as u16; } +pub unsafe fn instr16_BE(mut imm: i32) { *reg16.offset(SI as isize) = imm as u16; } #[no_mangle] -pub unsafe fn instr32_BE(mut imm: i32) -> () { *reg32s.offset(ESI as isize) = imm; } +pub unsafe fn instr32_BE(mut imm: i32) { *reg32s.offset(ESI as isize) = imm; } #[no_mangle] -pub unsafe fn instr16_BF(mut imm: i32) -> () { *reg16.offset(DI as isize) = imm as u16; } +pub unsafe fn instr16_BF(mut imm: i32) { *reg16.offset(DI as isize) = imm as u16; } #[no_mangle] -pub unsafe fn instr32_BF(mut imm: i32) -> () { *reg32s.offset(EDI as isize) = imm; } +pub unsafe fn instr32_BF(mut imm: i32) { *reg32s.offset(EDI as isize) = imm; } #[no_mangle] -pub unsafe fn instr_C0_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_0_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE8!(___, addr, rol8(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr_C0_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_0_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, rol8(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr_C0_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_1_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE8!(___, addr, ror8(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr_C0_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_1_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, ror8(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr_C0_2_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_2_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE8!(___, addr, rcl8(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr_C0_2_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_2_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, rcl8(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr_C0_3_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_3_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE8!(___, addr, rcr8(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr_C0_3_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_3_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, rcr8(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr_C0_4_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_4_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE8!(___, addr, shl8(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr_C0_4_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_4_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, shl8(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr_C0_5_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_5_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE8!(___, addr, shr8(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr_C0_5_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_5_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, shr8(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr_C0_6_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_6_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE8!(___, addr, shl8(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr_C0_6_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_6_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, shl8(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr_C0_7_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_7_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE8!(___, addr, sar8(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr_C0_7_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_C0_7_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, sar8(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr16_C1_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_0_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, rol16(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr16_C1_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_0_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, rol16(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr16_C1_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_1_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, ror16(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr16_C1_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_1_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, ror16(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr16_C1_2_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_2_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, rcl16(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr16_C1_2_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_2_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, rcl16(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr16_C1_3_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_3_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, rcr16(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr16_C1_3_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_3_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, rcr16(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr16_C1_4_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_4_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, shl16(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr16_C1_4_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_4_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, shl16(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr16_C1_5_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_5_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, shr16(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr16_C1_5_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_5_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, shr16(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr16_C1_6_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_6_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, shl16(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr16_C1_6_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_6_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, shl16(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr16_C1_7_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_7_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, sar16(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr16_C1_7_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C1_7_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, sar16(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr32_C1_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_0_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, rol32(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr32_C1_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_0_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, rol32(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr32_C1_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_1_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, ror32(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr32_C1_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_1_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, ror32(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr32_C1_2_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_2_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, rcl32(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr32_C1_2_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_2_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, rcl32(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr32_C1_3_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_3_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, rcr32(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr32_C1_3_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_3_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, rcr32(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr32_C1_4_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_4_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, shl32(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr32_C1_4_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_4_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, shl32(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr32_C1_5_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_5_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, shr32(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr32_C1_5_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_5_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, shr32(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr32_C1_6_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_6_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, shl32(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr32_C1_6_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_6_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, shl32(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr32_C1_7_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_7_mem(mut addr: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, sar32(___, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr32_C1_7_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C1_7_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, sar32(____0, imm & 31i32)); } #[no_mangle] -pub unsafe fn instr16_C2(mut imm16: i32) -> () { +pub unsafe fn instr16_C2(mut imm16: i32) { // retn let mut cs: i32 = get_seg_cs(); *instruction_pointer = cs + return_on_pagefault!(pop16()); @@ -2205,7 +2155,7 @@ pub unsafe fn instr16_C2(mut imm16: i32) -> () { adjust_stack_reg(imm16); } #[no_mangle] -pub unsafe fn instr32_C2(mut imm16: i32) -> () { +pub unsafe fn instr32_C2(mut imm16: i32) { // retn let mut cs: i32 = get_seg_cs(); let mut ip: i32 = return_on_pagefault!(pop32s()); @@ -2214,13 +2164,13 @@ pub unsafe fn instr32_C2(mut imm16: i32) -> () { adjust_stack_reg(imm16); } #[no_mangle] -pub unsafe fn instr16_C3() -> () { +pub unsafe fn instr16_C3() { // retn let mut cs: i32 = get_seg_cs(); *instruction_pointer = cs + return_on_pagefault!(pop16()); } #[no_mangle] -pub unsafe fn instr32_C3() -> () { +pub unsafe fn instr32_C3() { // retn let mut cs: i32 = get_seg_cs(); let mut ip: i32 = return_on_pagefault!(pop32s()); @@ -2228,49 +2178,45 @@ pub unsafe fn instr32_C3() -> () { *instruction_pointer = cs + ip; } #[no_mangle] -pub unsafe fn instr16_C4_reg(mut _unused1: i32, mut _unused2: i32) -> () { trigger_ud(); } +pub unsafe fn instr16_C4_reg(mut _unused1: i32, mut _unused2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_C4_mem(mut addr: i32, mut r: i32) -> () { - lss16(addr, get_reg16_index(r), ES); -} +pub unsafe fn instr16_C4_mem(mut addr: i32, mut r: i32) { lss16(addr, get_reg16_index(r), ES); } #[no_mangle] -pub unsafe fn instr32_C4_reg(mut _unused1: i32, mut _unused2: i32) -> () { trigger_ud(); } +pub unsafe fn instr32_C4_reg(mut _unused1: i32, mut _unused2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr32_C4_mem(mut addr: i32, mut r: i32) -> () { lss32(addr, r, ES); } +pub unsafe fn instr32_C4_mem(mut addr: i32, mut r: i32) { lss32(addr, r, ES); } #[no_mangle] -pub unsafe fn instr16_C5_reg(mut _unused1: i32, mut _unused2: i32) -> () { trigger_ud(); } +pub unsafe fn instr16_C5_reg(mut _unused1: i32, mut _unused2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_C5_mem(mut addr: i32, mut r: i32) -> () { - lss16(addr, get_reg16_index(r), DS); -} +pub unsafe fn instr16_C5_mem(mut addr: i32, mut r: i32) { lss16(addr, get_reg16_index(r), DS); } #[no_mangle] -pub unsafe fn instr32_C5_reg(mut _unused1: i32, mut _unused2: i32) -> () { trigger_ud(); } +pub unsafe fn instr32_C5_reg(mut _unused1: i32, mut _unused2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr32_C5_mem(mut addr: i32, mut r: i32) -> () { lss32(addr, r, DS); } +pub unsafe fn instr32_C5_mem(mut addr: i32, mut r: i32) { lss32(addr, r, DS); } #[no_mangle] -pub unsafe fn instr_C6_0_reg(mut r: i32, mut imm: i32) -> () { write_reg8(r, imm); } +pub unsafe fn instr_C6_0_reg(mut r: i32, mut imm: i32) { write_reg8(r, imm); } #[no_mangle] -pub unsafe fn instr_C6_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_C6_0_mem(mut addr: i32, mut imm: i32) { return_on_pagefault!(safe_write8(addr, imm)); } #[no_mangle] -pub unsafe fn instr16_C7_0_reg(mut r: i32, mut imm: i32) -> () { write_reg16(r, imm); } +pub unsafe fn instr16_C7_0_reg(mut r: i32, mut imm: i32) { write_reg16(r, imm); } #[no_mangle] -pub unsafe fn instr16_C7_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_C7_0_mem(mut addr: i32, mut imm: i32) { return_on_pagefault!(safe_write16(addr, imm)); } #[no_mangle] -pub unsafe fn instr32_C7_0_reg(mut r: i32, mut imm: i32) -> () { write_reg32(r, imm); } +pub unsafe fn instr32_C7_0_reg(mut r: i32, mut imm: i32) { write_reg32(r, imm); } #[no_mangle] -pub unsafe fn instr32_C7_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_C7_0_mem(mut addr: i32, mut imm: i32) { return_on_pagefault!(safe_write32(addr, imm)); } #[no_mangle] -pub unsafe fn instr16_C8(mut size: i32, mut nesting: i32) -> () { enter16(size, nesting); } +pub unsafe fn instr16_C8(mut size: i32, mut nesting: i32) { enter16(size, nesting); } #[no_mangle] -pub unsafe fn instr32_C8(mut size: i32, mut nesting: i32) -> () { enter32(size, nesting); } +pub unsafe fn instr32_C8(mut size: i32, mut nesting: i32) { enter32(size, nesting); } #[no_mangle] -pub unsafe fn instr16_C9() -> () { +pub unsafe fn instr16_C9() { // leave let mut old_vbp: i32 = if 0 != *stack_size_32 as i32 { *reg32s.offset(EBP as isize) @@ -2283,7 +2229,7 @@ pub unsafe fn instr16_C9() -> () { *reg16.offset(BP as isize) = new_bp as u16; } #[no_mangle] -pub unsafe fn instr32_C9() -> () { +pub unsafe fn instr32_C9() { let mut old_vbp: i32 = if 0 != *stack_size_32 as i32 { *reg32s.offset(EBP as isize) } @@ -2295,14 +2241,14 @@ pub unsafe fn instr32_C9() -> () { *reg32s.offset(EBP as isize) = new_ebp; } #[no_mangle] -pub unsafe fn instr16_CA(mut imm16: i32) -> () { +pub unsafe fn instr16_CA(mut imm16: i32) { // retf let mut ip: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0i32))); let mut cs: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(2i32))); far_return(ip, cs, imm16); } #[no_mangle] -pub unsafe fn instr32_CA(mut imm16: i32) -> () { +pub unsafe fn instr32_CA(mut imm16: i32) { // retf let mut ip: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))); let mut cs: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(4i32))) & 65535i32; @@ -2310,7 +2256,7 @@ pub unsafe fn instr32_CA(mut imm16: i32) -> () { dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe fn instr16_CB() -> () { +pub unsafe fn instr16_CB() { // retf let mut ip: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0i32))); let mut cs: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(2i32))); @@ -2318,7 +2264,7 @@ pub unsafe fn instr16_CB() -> () { dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe fn instr32_CB() -> () { +pub unsafe fn instr32_CB() { // retf let mut ip: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))); let mut cs: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(4i32))) & 65535i32; @@ -2326,19 +2272,19 @@ pub unsafe fn instr32_CB() -> () { dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe fn instr_CC() -> () { +pub unsafe fn instr_CC() { // INT3 // TODO: inhibit iopl checks dbg_log!("INT3"); call_interrupt_vector(3i32, 0 != 1i32, 0 != 0i32, 0i32); } #[no_mangle] -pub unsafe fn instr_CD(mut imm8: i32) -> () { +pub unsafe fn instr_CD(mut imm8: i32) { // INT call_interrupt_vector(imm8, 0 != 1i32, 0 != 0i32, 0i32); } #[no_mangle] -pub unsafe fn instr_CE() -> () { +pub unsafe fn instr_CE() { // INTO dbg_log!("INTO"); if getof() { @@ -2347,230 +2293,230 @@ pub unsafe fn instr_CE() -> () { }; } #[no_mangle] -pub unsafe fn instr16_CF() -> () { +pub unsafe fn instr16_CF() { // iret iret16(); } #[no_mangle] -pub unsafe fn instr32_CF() -> () { iret32(); } +pub unsafe fn instr32_CF() { iret32(); } #[no_mangle] -pub unsafe fn instr_D0_0_mem(mut addr: i32) -> () { +pub unsafe fn instr_D0_0_mem(mut addr: i32) { SAFE_READ_WRITE8!(___, addr, rol8(___, 1i32)); } #[no_mangle] -pub unsafe fn instr_D0_0_reg(mut r1: i32) -> () { +pub unsafe fn instr_D0_0_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, rol8(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr_D0_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_D0_1_mem(mut addr: i32) { SAFE_READ_WRITE8!(___, addr, ror8(___, 1i32)); } #[no_mangle] -pub unsafe fn instr_D0_1_reg(mut r1: i32) -> () { +pub unsafe fn instr_D0_1_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, ror8(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr_D0_2_mem(mut addr: i32) -> () { +pub unsafe fn instr_D0_2_mem(mut addr: i32) { SAFE_READ_WRITE8!(___, addr, rcl8(___, 1i32)); } #[no_mangle] -pub unsafe fn instr_D0_2_reg(mut r1: i32) -> () { +pub unsafe fn instr_D0_2_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, rcl8(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr_D0_3_mem(mut addr: i32) -> () { +pub unsafe fn instr_D0_3_mem(mut addr: i32) { SAFE_READ_WRITE8!(___, addr, rcr8(___, 1i32)); } #[no_mangle] -pub unsafe fn instr_D0_3_reg(mut r1: i32) -> () { +pub unsafe fn instr_D0_3_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, rcr8(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr_D0_4_mem(mut addr: i32) -> () { +pub unsafe fn instr_D0_4_mem(mut addr: i32) { SAFE_READ_WRITE8!(___, addr, shl8(___, 1i32)); } #[no_mangle] -pub unsafe fn instr_D0_4_reg(mut r1: i32) -> () { +pub unsafe fn instr_D0_4_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, shl8(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr_D0_5_mem(mut addr: i32) -> () { +pub unsafe fn instr_D0_5_mem(mut addr: i32) { SAFE_READ_WRITE8!(___, addr, shr8(___, 1i32)); } #[no_mangle] -pub unsafe fn instr_D0_5_reg(mut r1: i32) -> () { +pub unsafe fn instr_D0_5_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, shr8(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr_D0_6_mem(mut addr: i32) -> () { +pub unsafe fn instr_D0_6_mem(mut addr: i32) { SAFE_READ_WRITE8!(___, addr, shl8(___, 1i32)); } #[no_mangle] -pub unsafe fn instr_D0_6_reg(mut r1: i32) -> () { +pub unsafe fn instr_D0_6_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, shl8(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr_D0_7_mem(mut addr: i32) -> () { +pub unsafe fn instr_D0_7_mem(mut addr: i32) { SAFE_READ_WRITE8!(___, addr, sar8(___, 1i32)); } #[no_mangle] -pub unsafe fn instr_D0_7_reg(mut r1: i32) -> () { +pub unsafe fn instr_D0_7_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, sar8(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr16_D1_0_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D1_0_mem(mut addr: i32) { SAFE_READ_WRITE16!(___, addr, rol16(___, 1i32)); } #[no_mangle] -pub unsafe fn instr16_D1_0_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D1_0_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, rol16(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr16_D1_1_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D1_1_mem(mut addr: i32) { SAFE_READ_WRITE16!(___, addr, ror16(___, 1i32)); } #[no_mangle] -pub unsafe fn instr16_D1_1_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D1_1_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, ror16(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr16_D1_2_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D1_2_mem(mut addr: i32) { SAFE_READ_WRITE16!(___, addr, rcl16(___, 1i32)); } #[no_mangle] -pub unsafe fn instr16_D1_2_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D1_2_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, rcl16(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr16_D1_3_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D1_3_mem(mut addr: i32) { SAFE_READ_WRITE16!(___, addr, rcr16(___, 1i32)); } #[no_mangle] -pub unsafe fn instr16_D1_3_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D1_3_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, rcr16(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr16_D1_4_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D1_4_mem(mut addr: i32) { SAFE_READ_WRITE16!(___, addr, shl16(___, 1i32)); } #[no_mangle] -pub unsafe fn instr16_D1_4_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D1_4_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, shl16(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr16_D1_5_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D1_5_mem(mut addr: i32) { SAFE_READ_WRITE16!(___, addr, shr16(___, 1i32)); } #[no_mangle] -pub unsafe fn instr16_D1_5_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D1_5_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, shr16(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr16_D1_6_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D1_6_mem(mut addr: i32) { SAFE_READ_WRITE16!(___, addr, shl16(___, 1i32)); } #[no_mangle] -pub unsafe fn instr16_D1_6_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D1_6_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, shl16(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr16_D1_7_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D1_7_mem(mut addr: i32) { SAFE_READ_WRITE16!(___, addr, sar16(___, 1i32)); } #[no_mangle] -pub unsafe fn instr16_D1_7_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D1_7_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, sar16(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr32_D1_0_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D1_0_mem(mut addr: i32) { SAFE_READ_WRITE32!(___, addr, rol32(___, 1i32)); } #[no_mangle] -pub unsafe fn instr32_D1_0_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D1_0_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, rol32(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr32_D1_1_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D1_1_mem(mut addr: i32) { SAFE_READ_WRITE32!(___, addr, ror32(___, 1i32)); } #[no_mangle] -pub unsafe fn instr32_D1_1_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D1_1_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, ror32(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr32_D1_2_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D1_2_mem(mut addr: i32) { SAFE_READ_WRITE32!(___, addr, rcl32(___, 1i32)); } #[no_mangle] -pub unsafe fn instr32_D1_2_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D1_2_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, rcl32(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr32_D1_3_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D1_3_mem(mut addr: i32) { SAFE_READ_WRITE32!(___, addr, rcr32(___, 1i32)); } #[no_mangle] -pub unsafe fn instr32_D1_3_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D1_3_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, rcr32(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr32_D1_4_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D1_4_mem(mut addr: i32) { SAFE_READ_WRITE32!(___, addr, shl32(___, 1i32)); } #[no_mangle] -pub unsafe fn instr32_D1_4_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D1_4_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, shl32(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr32_D1_5_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D1_5_mem(mut addr: i32) { SAFE_READ_WRITE32!(___, addr, shr32(___, 1i32)); } #[no_mangle] -pub unsafe fn instr32_D1_5_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D1_5_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, shr32(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr32_D1_6_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D1_6_mem(mut addr: i32) { SAFE_READ_WRITE32!(___, addr, shl32(___, 1i32)); } #[no_mangle] -pub unsafe fn instr32_D1_6_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D1_6_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, shl32(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr32_D1_7_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D1_7_mem(mut addr: i32) { SAFE_READ_WRITE32!(___, addr, sar32(___, 1i32)); } #[no_mangle] -pub unsafe fn instr32_D1_7_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D1_7_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, sar32(____0, 1i32)); } #[no_mangle] -pub unsafe fn instr_D2_0_mem(mut addr: i32) -> () { +pub unsafe fn instr_D2_0_mem(mut addr: i32) { SAFE_READ_WRITE8!( ___, addr, @@ -2578,12 +2524,12 @@ pub unsafe fn instr_D2_0_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_D2_0_reg(mut r1: i32) -> () { +pub unsafe fn instr_D2_0_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, rol8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr_D2_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_D2_1_mem(mut addr: i32) { SAFE_READ_WRITE8!( ___, addr, @@ -2591,12 +2537,12 @@ pub unsafe fn instr_D2_1_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_D2_1_reg(mut r1: i32) -> () { +pub unsafe fn instr_D2_1_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, ror8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr_D2_2_mem(mut addr: i32) -> () { +pub unsafe fn instr_D2_2_mem(mut addr: i32) { SAFE_READ_WRITE8!( ___, addr, @@ -2604,12 +2550,12 @@ pub unsafe fn instr_D2_2_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_D2_2_reg(mut r1: i32) -> () { +pub unsafe fn instr_D2_2_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, rcl8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr_D2_3_mem(mut addr: i32) -> () { +pub unsafe fn instr_D2_3_mem(mut addr: i32) { SAFE_READ_WRITE8!( ___, addr, @@ -2617,12 +2563,12 @@ pub unsafe fn instr_D2_3_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_D2_3_reg(mut r1: i32) -> () { +pub unsafe fn instr_D2_3_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, rcr8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr_D2_4_mem(mut addr: i32) -> () { +pub unsafe fn instr_D2_4_mem(mut addr: i32) { SAFE_READ_WRITE8!( ___, addr, @@ -2630,12 +2576,12 @@ pub unsafe fn instr_D2_4_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_D2_4_reg(mut r1: i32) -> () { +pub unsafe fn instr_D2_4_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, shl8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr_D2_5_mem(mut addr: i32) -> () { +pub unsafe fn instr_D2_5_mem(mut addr: i32) { SAFE_READ_WRITE8!( ___, addr, @@ -2643,12 +2589,12 @@ pub unsafe fn instr_D2_5_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_D2_5_reg(mut r1: i32) -> () { +pub unsafe fn instr_D2_5_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, shr8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr_D2_6_mem(mut addr: i32) -> () { +pub unsafe fn instr_D2_6_mem(mut addr: i32) { SAFE_READ_WRITE8!( ___, addr, @@ -2656,12 +2602,12 @@ pub unsafe fn instr_D2_6_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_D2_6_reg(mut r1: i32) -> () { +pub unsafe fn instr_D2_6_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, shl8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr_D2_7_mem(mut addr: i32) -> () { +pub unsafe fn instr_D2_7_mem(mut addr: i32) { SAFE_READ_WRITE8!( ___, addr, @@ -2669,12 +2615,12 @@ pub unsafe fn instr_D2_7_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_D2_7_reg(mut r1: i32) -> () { +pub unsafe fn instr_D2_7_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, sar8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr16_D3_0_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D3_0_mem(mut addr: i32) { SAFE_READ_WRITE16!( ___, addr, @@ -2682,12 +2628,12 @@ pub unsafe fn instr16_D3_0_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr16_D3_0_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D3_0_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, rol16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr16_D3_1_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D3_1_mem(mut addr: i32) { SAFE_READ_WRITE16!( ___, addr, @@ -2695,12 +2641,12 @@ pub unsafe fn instr16_D3_1_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr16_D3_1_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D3_1_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, ror16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr16_D3_2_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D3_2_mem(mut addr: i32) { SAFE_READ_WRITE16!( ___, addr, @@ -2708,12 +2654,12 @@ pub unsafe fn instr16_D3_2_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr16_D3_2_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D3_2_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, rcl16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr16_D3_3_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D3_3_mem(mut addr: i32) { SAFE_READ_WRITE16!( ___, addr, @@ -2721,12 +2667,12 @@ pub unsafe fn instr16_D3_3_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr16_D3_3_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D3_3_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, rcr16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr16_D3_4_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D3_4_mem(mut addr: i32) { SAFE_READ_WRITE16!( ___, addr, @@ -2734,12 +2680,12 @@ pub unsafe fn instr16_D3_4_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr16_D3_4_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D3_4_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, shl16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr16_D3_5_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D3_5_mem(mut addr: i32) { SAFE_READ_WRITE16!( ___, addr, @@ -2747,12 +2693,12 @@ pub unsafe fn instr16_D3_5_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr16_D3_5_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D3_5_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, shr16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr16_D3_6_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D3_6_mem(mut addr: i32) { SAFE_READ_WRITE16!( ___, addr, @@ -2760,12 +2706,12 @@ pub unsafe fn instr16_D3_6_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr16_D3_6_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D3_6_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, shl16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr16_D3_7_mem(mut addr: i32) -> () { +pub unsafe fn instr16_D3_7_mem(mut addr: i32) { SAFE_READ_WRITE16!( ___, addr, @@ -2773,12 +2719,12 @@ pub unsafe fn instr16_D3_7_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr16_D3_7_reg(mut r1: i32) -> () { +pub unsafe fn instr16_D3_7_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, sar16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr32_D3_0_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D3_0_mem(mut addr: i32) { SAFE_READ_WRITE32!( ___, addr, @@ -2786,12 +2732,12 @@ pub unsafe fn instr32_D3_0_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr32_D3_0_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D3_0_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, rol32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr32_D3_1_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D3_1_mem(mut addr: i32) { SAFE_READ_WRITE32!( ___, addr, @@ -2799,12 +2745,12 @@ pub unsafe fn instr32_D3_1_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr32_D3_1_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D3_1_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, ror32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr32_D3_2_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D3_2_mem(mut addr: i32) { SAFE_READ_WRITE32!( ___, addr, @@ -2812,12 +2758,12 @@ pub unsafe fn instr32_D3_2_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr32_D3_2_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D3_2_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, rcl32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr32_D3_3_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D3_3_mem(mut addr: i32) { SAFE_READ_WRITE32!( ___, addr, @@ -2825,12 +2771,12 @@ pub unsafe fn instr32_D3_3_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr32_D3_3_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D3_3_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, rcr32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr32_D3_4_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D3_4_mem(mut addr: i32) { SAFE_READ_WRITE32!( ___, addr, @@ -2838,12 +2784,12 @@ pub unsafe fn instr32_D3_4_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr32_D3_4_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D3_4_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, shl32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr32_D3_5_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D3_5_mem(mut addr: i32) { SAFE_READ_WRITE32!( ___, addr, @@ -2851,12 +2797,12 @@ pub unsafe fn instr32_D3_5_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr32_D3_5_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D3_5_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, shr32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr32_D3_6_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D3_6_mem(mut addr: i32) { SAFE_READ_WRITE32!( ___, addr, @@ -2864,12 +2810,12 @@ pub unsafe fn instr32_D3_6_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr32_D3_6_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D3_6_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, shl32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr32_D3_7_mem(mut addr: i32) -> () { +pub unsafe fn instr32_D3_7_mem(mut addr: i32) { SAFE_READ_WRITE32!( ___, addr, @@ -2877,21 +2823,21 @@ pub unsafe fn instr32_D3_7_mem(mut addr: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr32_D3_7_reg(mut r1: i32) -> () { +pub unsafe fn instr32_D3_7_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, sar32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); } #[no_mangle] -pub unsafe fn instr_D4(mut arg: i32) -> () { bcd_aam(arg); } +pub unsafe fn instr_D4(mut arg: i32) { bcd_aam(arg); } #[no_mangle] -pub unsafe fn instr_D5(mut arg: i32) -> () { bcd_aad(arg); } +pub unsafe fn instr_D5(mut arg: i32) { bcd_aad(arg); } #[no_mangle] -pub unsafe fn instr_D6() -> () { +pub unsafe fn instr_D6() { // salc *reg8.offset(AL as isize) = -(getcf() as i32) as u8; } #[no_mangle] -pub unsafe fn instr_D7() -> () { +pub unsafe fn instr_D7() { // xlat if is_asize_32() { *reg8.offset(AL as isize) = return_on_pagefault!(safe_read8( @@ -2906,7 +2852,7 @@ pub unsafe fn instr_D7() -> () { }; } #[no_mangle] -pub unsafe fn instr_E4(mut port: i32) -> () { +pub unsafe fn instr_E4(mut port: i32) { if !test_privileges_for_io(port, 1i32) { return; } @@ -2916,7 +2862,7 @@ pub unsafe fn instr_E4(mut port: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr16_E5(mut port: i32) -> () { +pub unsafe fn instr16_E5(mut port: i32) { if !test_privileges_for_io(port, 2i32) { return; } @@ -2926,7 +2872,7 @@ pub unsafe fn instr16_E5(mut port: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr32_E5(mut port: i32) -> () { +pub unsafe fn instr32_E5(mut port: i32) { if !test_privileges_for_io(port, 4i32) { return; } @@ -2936,7 +2882,7 @@ pub unsafe fn instr32_E5(mut port: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_E6(mut port: i32) -> () { +pub unsafe fn instr_E6(mut port: i32) { if !test_privileges_for_io(port, 1i32) { return; } @@ -2946,7 +2892,7 @@ pub unsafe fn instr_E6(mut port: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr16_E7(mut port: i32) -> () { +pub unsafe fn instr16_E7(mut port: i32) { if !test_privileges_for_io(port, 2i32) { return; } @@ -2956,7 +2902,7 @@ pub unsafe fn instr16_E7(mut port: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr32_E7(mut port: i32) -> () { +pub unsafe fn instr32_E7(mut port: i32) { if !test_privileges_for_io(port, 4i32) { return; } @@ -2966,43 +2912,43 @@ pub unsafe fn instr32_E7(mut port: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr16_E8(mut imm16: i32) -> () { +pub unsafe fn instr16_E8(mut imm16: i32) { // call return_on_pagefault!(push16(get_real_eip())); jmp_rel16(imm16); } #[no_mangle] -pub unsafe fn instr32_E8(mut imm32s: i32) -> () { +pub unsafe fn instr32_E8(mut imm32s: i32) { // call return_on_pagefault!(push32(get_real_eip())); *instruction_pointer = *instruction_pointer + imm32s; // dbg_assert!(is_asize_32() || get_real_eip() < 0x10000); } #[no_mangle] -pub unsafe fn instr16_E9(mut imm16: i32) -> () { +pub unsafe fn instr16_E9(mut imm16: i32) { // jmp jmp_rel16(imm16); } #[no_mangle] -pub unsafe fn instr32_E9(mut imm32s: i32) -> () { +pub unsafe fn instr32_E9(mut imm32s: i32) { // jmp *instruction_pointer = *instruction_pointer + imm32s; dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe fn instr16_EA(mut new_ip: i32, mut cs: i32) -> () { +pub unsafe fn instr16_EA(mut new_ip: i32, mut cs: i32) { // jmpf far_jump(new_ip, cs, false); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe fn instr32_EA(mut new_ip: i32, mut cs: i32) -> () { +pub unsafe fn instr32_EA(mut new_ip: i32, mut cs: i32) { // jmpf far_jump(new_ip, cs, false); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe fn instr_EC() -> () { +pub unsafe fn instr_EC() { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 1i32) { return; @@ -3013,7 +2959,7 @@ pub unsafe fn instr_EC() -> () { }; } #[no_mangle] -pub unsafe fn instr16_ED() -> () { +pub unsafe fn instr16_ED() { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 2i32) { return; @@ -3024,7 +2970,7 @@ pub unsafe fn instr16_ED() -> () { }; } #[no_mangle] -pub unsafe fn instr32_ED() -> () { +pub unsafe fn instr32_ED() { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 4i32) { return; @@ -3035,7 +2981,7 @@ pub unsafe fn instr32_ED() -> () { }; } #[no_mangle] -pub unsafe fn instr_EE() -> () { +pub unsafe fn instr_EE() { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 1i32) { return; @@ -3046,7 +2992,7 @@ pub unsafe fn instr_EE() -> () { }; } #[no_mangle] -pub unsafe fn instr16_EF() -> () { +pub unsafe fn instr16_EF() { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 2i32) { return; @@ -3057,7 +3003,7 @@ pub unsafe fn instr16_EF() -> () { }; } #[no_mangle] -pub unsafe fn instr32_EF() -> () { +pub unsafe fn instr32_EF() { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 4i32) { return; @@ -3068,7 +3014,7 @@ pub unsafe fn instr32_EF() -> () { }; } #[no_mangle] -pub unsafe fn instr_F0() -> () { +pub unsafe fn instr_F0() { // lock if 0 != 0i32 * 0i32 { dbg_log!("lock"); @@ -3079,13 +3025,13 @@ pub unsafe fn instr_F0() -> () { run_prefix_instruction(); } #[no_mangle] -pub unsafe fn instr_F1() -> () { +pub unsafe fn instr_F1() { // INT1 // https://code.google.com/p/corkami/wiki/x86oddities#IceBP dbg_assert!(0 != 0i32); } #[no_mangle] -pub unsafe fn instr_F2() -> () { +pub unsafe fn instr_F2() { // repnz dbg_assert!(*prefixes as i32 & PREFIX_MASK_REP == 0i32); *prefixes = (*prefixes as i32 | PREFIX_REPNZ) as u8; @@ -3093,7 +3039,7 @@ pub unsafe fn instr_F2() -> () { *prefixes = 0i32 as u8; } #[no_mangle] -pub unsafe fn instr_F3() -> () { +pub unsafe fn instr_F3() { // repz dbg_assert!(*prefixes as i32 & PREFIX_MASK_REP == 0i32); *prefixes = (*prefixes as i32 | PREFIX_REPZ) as u8; @@ -3101,261 +3047,261 @@ pub unsafe fn instr_F3() -> () { *prefixes = 0i32 as u8; } #[no_mangle] -pub unsafe fn instr_F4() -> () { hlt_op(); } +pub unsafe fn instr_F4() { hlt_op(); } #[no_mangle] -pub unsafe fn instr_F5() -> () { +pub unsafe fn instr_F5() { // cmc *flags = (*flags | 1i32) ^ getcf() as i32; *flags_changed &= !1i32; } #[no_mangle] -pub unsafe fn instr_F6_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_F6_0_mem(mut addr: i32, mut imm: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); test8(____0, imm); } #[no_mangle] -pub unsafe fn instr_F6_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_F6_0_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); test8(____0, imm); } #[no_mangle] -pub unsafe fn instr_F6_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr_F6_1_mem(mut addr: i32, mut imm: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); test8(____0, imm); } #[no_mangle] -pub unsafe fn instr_F6_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr_F6_1_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); test8(____0, imm); } #[no_mangle] -pub unsafe fn instr_F6_2_mem(mut addr: i32) -> () { +pub unsafe fn instr_F6_2_mem(mut addr: i32) { SAFE_READ_WRITE8!(___, addr, !___); } #[no_mangle] -pub unsafe fn instr_F6_2_reg(mut r1: i32) -> () { +pub unsafe fn instr_F6_2_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, !____0); } #[no_mangle] -pub unsafe fn instr_F6_3_mem(mut addr: i32) -> () { +pub unsafe fn instr_F6_3_mem(mut addr: i32) { SAFE_READ_WRITE8!(___, addr, neg8(___)); } #[no_mangle] -pub unsafe fn instr_F6_3_reg(mut r1: i32) -> () { +pub unsafe fn instr_F6_3_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, neg8(____0)); } #[no_mangle] -pub unsafe fn instr_F6_4_mem(mut addr: i32) -> () { +pub unsafe fn instr_F6_4_mem(mut addr: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); mul8(____0); } #[no_mangle] -pub unsafe fn instr_F6_4_reg(mut r1: i32) -> () { +pub unsafe fn instr_F6_4_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); mul8(____0); } #[no_mangle] -pub unsafe fn instr_F6_5_mem(mut addr: i32) -> () { +pub unsafe fn instr_F6_5_mem(mut addr: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); imul8(____0 << 24i32 >> 24i32); } #[no_mangle] -pub unsafe fn instr_F6_5_reg(mut r1: i32) -> () { +pub unsafe fn instr_F6_5_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); imul8(____0 << 24i32 >> 24i32); } #[no_mangle] -pub unsafe fn instr_F6_6_mem(mut addr: i32) -> () { +pub unsafe fn instr_F6_6_mem(mut addr: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); div8(____0 as u32); } #[no_mangle] -pub unsafe fn instr_F6_6_reg(mut r1: i32) -> () { +pub unsafe fn instr_F6_6_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); div8(____0 as u32); } #[no_mangle] -pub unsafe fn instr_F6_7_mem(mut addr: i32) -> () { +pub unsafe fn instr_F6_7_mem(mut addr: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); idiv8(____0 << 24i32 >> 24i32); } #[no_mangle] -pub unsafe fn instr_F6_7_reg(mut r1: i32) -> () { +pub unsafe fn instr_F6_7_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); idiv8(____0 << 24i32 >> 24i32); } #[no_mangle] -pub unsafe fn instr16_F7_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_F7_0_mem(mut addr: i32, mut imm: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); test16(____0, imm); } #[no_mangle] -pub unsafe fn instr16_F7_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_F7_0_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); test16(____0, imm); } #[no_mangle] -pub unsafe fn instr16_F7_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr16_F7_1_mem(mut addr: i32, mut imm: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); test16(____0, imm); } #[no_mangle] -pub unsafe fn instr16_F7_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr16_F7_1_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); test16(____0, imm); } #[no_mangle] -pub unsafe fn instr16_F7_2_mem(mut addr: i32) -> () { +pub unsafe fn instr16_F7_2_mem(mut addr: i32) { SAFE_READ_WRITE16!(___, addr, !___); } #[no_mangle] -pub unsafe fn instr16_F7_2_reg(mut r1: i32) -> () { +pub unsafe fn instr16_F7_2_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, !____0); } #[no_mangle] -pub unsafe fn instr16_F7_3_mem(mut addr: i32) -> () { +pub unsafe fn instr16_F7_3_mem(mut addr: i32) { SAFE_READ_WRITE16!(___, addr, neg16(___)); } #[no_mangle] -pub unsafe fn instr16_F7_3_reg(mut r1: i32) -> () { +pub unsafe fn instr16_F7_3_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, neg16(____0)); } #[no_mangle] -pub unsafe fn instr16_F7_4_mem(mut addr: i32) -> () { +pub unsafe fn instr16_F7_4_mem(mut addr: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); mul16(____0 as u32); } #[no_mangle] -pub unsafe fn instr16_F7_4_reg(mut r1: i32) -> () { +pub unsafe fn instr16_F7_4_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); mul16(____0 as u32); } #[no_mangle] -pub unsafe fn instr16_F7_5_mem(mut addr: i32) -> () { +pub unsafe fn instr16_F7_5_mem(mut addr: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); imul16(____0 << 16i32 >> 16i32); } #[no_mangle] -pub unsafe fn instr16_F7_5_reg(mut r1: i32) -> () { +pub unsafe fn instr16_F7_5_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); imul16(____0 << 16i32 >> 16i32); } #[no_mangle] -pub unsafe fn instr16_F7_6_mem(mut addr: i32) -> () { +pub unsafe fn instr16_F7_6_mem(mut addr: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); div16(____0 as u32); } #[no_mangle] -pub unsafe fn instr16_F7_6_reg(mut r1: i32) -> () { +pub unsafe fn instr16_F7_6_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); div16(____0 as u32); } #[no_mangle] -pub unsafe fn instr16_F7_7_mem(mut addr: i32) -> () { +pub unsafe fn instr16_F7_7_mem(mut addr: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); idiv16(____0 << 16i32 >> 16i32); } #[no_mangle] -pub unsafe fn instr16_F7_7_reg(mut r1: i32) -> () { +pub unsafe fn instr16_F7_7_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); idiv16(____0 << 16i32 >> 16i32); } #[no_mangle] -pub unsafe fn instr32_F7_0_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_F7_0_mem(mut addr: i32, mut imm: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); test32(____0, imm); } #[no_mangle] -pub unsafe fn instr32_F7_0_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_F7_0_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); test32(____0, imm); } #[no_mangle] -pub unsafe fn instr32_F7_1_mem(mut addr: i32, mut imm: i32) -> () { +pub unsafe fn instr32_F7_1_mem(mut addr: i32, mut imm: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); test32(____0, imm); } #[no_mangle] -pub unsafe fn instr32_F7_1_reg(mut r1: i32, mut imm: i32) -> () { +pub unsafe fn instr32_F7_1_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); test32(____0, imm); } #[no_mangle] -pub unsafe fn instr32_F7_2_mem(mut addr: i32) -> () { +pub unsafe fn instr32_F7_2_mem(mut addr: i32) { SAFE_READ_WRITE32!(___, addr, !___); } #[no_mangle] -pub unsafe fn instr32_F7_2_reg(mut r1: i32) -> () { +pub unsafe fn instr32_F7_2_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, !____0); } #[no_mangle] -pub unsafe fn instr32_F7_3_mem(mut addr: i32) -> () { +pub unsafe fn instr32_F7_3_mem(mut addr: i32) { SAFE_READ_WRITE32!(___, addr, neg32(___)); } #[no_mangle] -pub unsafe fn instr32_F7_3_reg(mut r1: i32) -> () { +pub unsafe fn instr32_F7_3_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, neg32(____0)); } #[no_mangle] -pub unsafe fn instr32_F7_4_mem(mut addr: i32) -> () { +pub unsafe fn instr32_F7_4_mem(mut addr: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); mul32(____0); } #[no_mangle] -pub unsafe fn instr32_F7_4_reg(mut r1: i32) -> () { +pub unsafe fn instr32_F7_4_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); mul32(____0); } #[no_mangle] -pub unsafe fn instr32_F7_5_mem(mut addr: i32) -> () { +pub unsafe fn instr32_F7_5_mem(mut addr: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); imul32(____0); } #[no_mangle] -pub unsafe fn instr32_F7_5_reg(mut r1: i32) -> () { +pub unsafe fn instr32_F7_5_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); imul32(____0); } #[no_mangle] -pub unsafe fn instr32_F7_6_mem(mut addr: i32) -> () { +pub unsafe fn instr32_F7_6_mem(mut addr: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); div32(____0 as u32); } #[no_mangle] -pub unsafe fn instr32_F7_6_reg(mut r1: i32) -> () { +pub unsafe fn instr32_F7_6_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); div32(____0 as u32); } #[no_mangle] -pub unsafe fn instr32_F7_7_mem(mut addr: i32) -> () { +pub unsafe fn instr32_F7_7_mem(mut addr: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); idiv32(____0); } #[no_mangle] -pub unsafe fn instr32_F7_7_reg(mut r1: i32) -> () { +pub unsafe fn instr32_F7_7_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); idiv32(____0); } #[no_mangle] -pub unsafe fn instr_F8() -> () { +pub unsafe fn instr_F8() { // clc *flags &= !FLAG_CARRY; *flags_changed &= !1i32; } #[no_mangle] -pub unsafe fn instr_F9() -> () { +pub unsafe fn instr_F9() { // stc *flags |= FLAG_CARRY; *flags_changed &= !1i32; } #[no_mangle] -pub unsafe fn instr_FA() -> () { +pub unsafe fn instr_FA() { // cli if !*protected_mode || 0 != if 0 != *flags & FLAG_VM { (getiopl() == 3i32) as i32 @@ -3379,7 +3325,7 @@ pub unsafe fn instr_FA() -> () { }; } #[no_mangle] -pub unsafe fn instr_FB() -> () { +pub unsafe fn instr_FB() { // sti let mut old_if: i32 = *flags & FLAG_INTERRUPT; if !*protected_mode || 0 != if 0 != *flags & FLAG_VM { @@ -3409,53 +3355,53 @@ pub unsafe fn instr_FB() -> () { }; } #[no_mangle] -pub unsafe fn instr_FC() -> () { +pub unsafe fn instr_FC() { // cld *flags &= !FLAG_DIRECTION; } #[no_mangle] -pub unsafe fn instr_FD() -> () { +pub unsafe fn instr_FD() { // std *flags |= FLAG_DIRECTION; } #[no_mangle] -pub unsafe fn instr_FE_0_mem(mut addr: i32) -> () { +pub unsafe fn instr_FE_0_mem(mut addr: i32) { SAFE_READ_WRITE8!(___, addr, inc8(___)); } #[no_mangle] -pub unsafe fn instr_FE_0_reg(mut r1: i32) -> () { +pub unsafe fn instr_FE_0_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, inc8(____0)); } #[no_mangle] -pub unsafe fn instr_FE_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_FE_1_mem(mut addr: i32) { SAFE_READ_WRITE8!(___, addr, dec8(___)); } #[no_mangle] -pub unsafe fn instr_FE_1_reg(mut r1: i32) -> () { +pub unsafe fn instr_FE_1_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, dec8(____0)); } #[no_mangle] -pub unsafe fn instr16_FF_0_mem(mut addr: i32) -> () { +pub unsafe fn instr16_FF_0_mem(mut addr: i32) { SAFE_READ_WRITE16!(___, addr, inc16(___)); } #[no_mangle] -pub unsafe fn instr16_FF_0_reg(mut r1: i32) -> () { +pub unsafe fn instr16_FF_0_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, inc16(____0)); } #[no_mangle] -pub unsafe fn instr16_FF_1_mem(mut addr: i32) -> () { +pub unsafe fn instr16_FF_1_mem(mut addr: i32) { SAFE_READ_WRITE16!(___, addr, dec16(___)); } #[no_mangle] -pub unsafe fn instr16_FF_1_reg(mut r1: i32) -> () { +pub unsafe fn instr16_FF_1_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, dec16(____0)); } #[no_mangle] -pub unsafe fn instr16_FF_2_helper(mut data: i32) -> () { +pub unsafe fn instr16_FF_2_helper(mut data: i32) { // call near let mut cs: i32 = get_seg_cs(); return_on_pagefault!(push16(get_real_eip())); @@ -3463,22 +3409,22 @@ pub unsafe fn instr16_FF_2_helper(mut data: i32) -> () { dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe fn instr16_FF_2_mem(mut addr: i32) -> () { +pub unsafe fn instr16_FF_2_mem(mut addr: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); instr16_FF_2_helper(____0); } #[no_mangle] -pub unsafe fn instr16_FF_2_reg(mut r1: i32) -> () { +pub unsafe fn instr16_FF_2_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); instr16_FF_2_helper(____0); } #[no_mangle] -pub unsafe fn instr16_FF_3_reg(mut r: i32) -> () { +pub unsafe fn instr16_FF_3_reg(mut r: i32) { dbg_log!("callf #ud"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_FF_3_mem(mut addr: i32) -> () { +pub unsafe fn instr16_FF_3_mem(mut addr: i32) { // callf let mut new_ip: i32 = return_on_pagefault!(safe_read16(addr)); let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 2i32)); @@ -3486,28 +3432,28 @@ pub unsafe fn instr16_FF_3_mem(mut addr: i32) -> () { dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe fn instr16_FF_4_helper(mut data: i32) -> () { +pub unsafe fn instr16_FF_4_helper(mut data: i32) { // jmp near *instruction_pointer = get_seg_cs() + data; dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe fn instr16_FF_4_mem(mut addr: i32) -> () { +pub unsafe fn instr16_FF_4_mem(mut addr: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); instr16_FF_4_helper(____0); } #[no_mangle] -pub unsafe fn instr16_FF_4_reg(mut r1: i32) -> () { +pub unsafe fn instr16_FF_4_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); instr16_FF_4_helper(____0); } #[no_mangle] -pub unsafe fn instr16_FF_5_reg(mut r: i32) -> () { +pub unsafe fn instr16_FF_5_reg(mut r: i32) { dbg_log!("jmpf #ud"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_FF_5_mem(mut addr: i32) -> () { +pub unsafe fn instr16_FF_5_mem(mut addr: i32) { // jmpf let mut new_ip: i32 = return_on_pagefault!(safe_read16(addr)); let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 2i32)); @@ -3515,35 +3461,35 @@ pub unsafe fn instr16_FF_5_mem(mut addr: i32) -> () { dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe fn instr16_FF_6_mem(mut addr: i32) -> () { +pub unsafe fn instr16_FF_6_mem(mut addr: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); return_on_pagefault!(push16(____0)); } #[no_mangle] -pub unsafe fn instr16_FF_6_reg(mut r1: i32) -> () { +pub unsafe fn instr16_FF_6_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); return_on_pagefault!(push16(____0)); } #[no_mangle] -pub unsafe fn instr32_FF_0_mem(mut addr: i32) -> () { +pub unsafe fn instr32_FF_0_mem(mut addr: i32) { SAFE_READ_WRITE32!(___, addr, inc32(___)); } #[no_mangle] -pub unsafe fn instr32_FF_0_reg(mut r1: i32) -> () { +pub unsafe fn instr32_FF_0_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, inc32(____0)); } #[no_mangle] -pub unsafe fn instr32_FF_1_mem(mut addr: i32) -> () { +pub unsafe fn instr32_FF_1_mem(mut addr: i32) { SAFE_READ_WRITE32!(___, addr, dec32(___)); } #[no_mangle] -pub unsafe fn instr32_FF_1_reg(mut r1: i32) -> () { +pub unsafe fn instr32_FF_1_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, dec32(____0)); } #[no_mangle] -pub unsafe fn instr32_FF_2_helper(mut data: i32) -> () { +pub unsafe fn instr32_FF_2_helper(mut data: i32) { // call near let mut cs: i32 = get_seg_cs(); return_on_pagefault!(push32(get_real_eip())); @@ -3551,22 +3497,22 @@ pub unsafe fn instr32_FF_2_helper(mut data: i32) -> () { *instruction_pointer = cs + data; } #[no_mangle] -pub unsafe fn instr32_FF_2_mem(mut addr: i32) -> () { +pub unsafe fn instr32_FF_2_mem(mut addr: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); instr32_FF_2_helper(____0); } #[no_mangle] -pub unsafe fn instr32_FF_2_reg(mut r1: i32) -> () { +pub unsafe fn instr32_FF_2_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); instr32_FF_2_helper(____0); } #[no_mangle] -pub unsafe fn instr32_FF_3_reg(mut r: i32) -> () { +pub unsafe fn instr32_FF_3_reg(mut r: i32) { dbg_log!("callf #ud"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr32_FF_3_mem(mut addr: i32) -> () { +pub unsafe fn instr32_FF_3_mem(mut addr: i32) { // callf let mut new_ip: i32 = return_on_pagefault!(safe_read32s(addr)); let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 4i32)); @@ -3579,28 +3525,28 @@ pub unsafe fn instr32_FF_3_mem(mut addr: i32) -> () { dbg_assert!(0 != is_asize_32() as i32 || new_ip < 65536i32); } #[no_mangle] -pub unsafe fn instr32_FF_4_helper(mut data: i32) -> () { +pub unsafe fn instr32_FF_4_helper(mut data: i32) { // jmp near dbg_assert!(0 != is_asize_32() as i32 || data < 65536i32); *instruction_pointer = get_seg_cs() + data; } #[no_mangle] -pub unsafe fn instr32_FF_4_mem(mut addr: i32) -> () { +pub unsafe fn instr32_FF_4_mem(mut addr: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); instr32_FF_4_helper(____0); } #[no_mangle] -pub unsafe fn instr32_FF_4_reg(mut r1: i32) -> () { +pub unsafe fn instr32_FF_4_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); instr32_FF_4_helper(____0); } #[no_mangle] -pub unsafe fn instr32_FF_5_reg(mut r: i32) -> () { +pub unsafe fn instr32_FF_5_reg(mut r: i32) { dbg_log!("jmpf #ud"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr32_FF_5_mem(mut addr: i32) -> () { +pub unsafe fn instr32_FF_5_mem(mut addr: i32) { // jmpf let mut new_ip: i32 = return_on_pagefault!(safe_read32s(addr)); let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 4i32)); @@ -3613,279 +3559,279 @@ pub unsafe fn instr32_FF_5_mem(mut addr: i32) -> () { dbg_assert!(0 != is_asize_32() as i32 || new_ip < 65536i32); } #[no_mangle] -pub unsafe fn instr32_FF_6_mem(mut addr: i32) -> () { +pub unsafe fn instr32_FF_6_mem(mut addr: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); return_on_pagefault!(push32(____0)); } #[no_mangle] -pub unsafe fn instr32_FF_6_reg(mut r1: i32) -> () { +pub unsafe fn instr32_FF_6_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); return_on_pagefault!(push32(____0)); } #[no_mangle] -pub unsafe fn instr_F26C() -> () { insb_rep(); } +pub unsafe fn instr_F26C() { insb_rep(); } #[no_mangle] -pub unsafe fn instr_F36C() -> () { insb_rep(); } +pub unsafe fn instr_F36C() { insb_rep(); } #[no_mangle] -pub unsafe fn instr16_F26D() -> () { insw_rep(); } +pub unsafe fn instr16_F26D() { insw_rep(); } #[no_mangle] -pub unsafe fn instr16_F36D() -> () { insw_rep(); } +pub unsafe fn instr16_F36D() { insw_rep(); } #[no_mangle] -pub unsafe fn instr32_F26D() -> () { insd_rep(); } +pub unsafe fn instr32_F26D() { insd_rep(); } #[no_mangle] -pub unsafe fn instr32_F36D() -> () { insd_rep(); } +pub unsafe fn instr32_F36D() { insd_rep(); } #[no_mangle] -pub unsafe fn instr_F26E() -> () { outsb_rep(); } +pub unsafe fn instr_F26E() { outsb_rep(); } #[no_mangle] -pub unsafe fn instr_F36E() -> () { outsb_rep(); } +pub unsafe fn instr_F36E() { outsb_rep(); } #[no_mangle] -pub unsafe fn instr16_F26F() -> () { outsw_rep(); } +pub unsafe fn instr16_F26F() { outsw_rep(); } #[no_mangle] -pub unsafe fn instr16_F36F() -> () { outsw_rep(); } +pub unsafe fn instr16_F36F() { outsw_rep(); } #[no_mangle] -pub unsafe fn instr32_F26F() -> () { outsd_rep(); } +pub unsafe fn instr32_F26F() { outsd_rep(); } #[no_mangle] -pub unsafe fn instr32_F36F() -> () { outsd_rep(); } +pub unsafe fn instr32_F36F() { outsd_rep(); } #[no_mangle] -pub unsafe fn instr16_70(mut imm8: i32) -> () { jmpcc16(test_o(), imm8); } +pub unsafe fn instr16_70(mut imm8: i32) { jmpcc16(test_o(), imm8); } #[no_mangle] -pub unsafe fn instr16_71(mut imm8: i32) -> () { jmpcc16(!test_o(), imm8); } +pub unsafe fn instr16_71(mut imm8: i32) { jmpcc16(!test_o(), imm8); } #[no_mangle] -pub unsafe fn instr16_72(mut imm8: i32) -> () { jmpcc16(test_b(), imm8); } +pub unsafe fn instr16_72(mut imm8: i32) { jmpcc16(test_b(), imm8); } #[no_mangle] -pub unsafe fn instr16_73(mut imm8: i32) -> () { jmpcc16(!test_b(), imm8); } +pub unsafe fn instr16_73(mut imm8: i32) { jmpcc16(!test_b(), imm8); } #[no_mangle] -pub unsafe fn instr16_74(mut imm8: i32) -> () { jmpcc16(test_z(), imm8); } +pub unsafe fn instr16_74(mut imm8: i32) { jmpcc16(test_z(), imm8); } #[no_mangle] -pub unsafe fn instr16_75(mut imm8: i32) -> () { jmpcc16(!test_z(), imm8); } +pub unsafe fn instr16_75(mut imm8: i32) { jmpcc16(!test_z(), imm8); } #[no_mangle] -pub unsafe fn instr16_76(mut imm8: i32) -> () { jmpcc16(test_be(), imm8); } +pub unsafe fn instr16_76(mut imm8: i32) { jmpcc16(test_be(), imm8); } #[no_mangle] -pub unsafe fn instr16_77(mut imm8: i32) -> () { jmpcc16(!test_be(), imm8); } +pub unsafe fn instr16_77(mut imm8: i32) { jmpcc16(!test_be(), imm8); } #[no_mangle] -pub unsafe fn instr16_78(mut imm8: i32) -> () { jmpcc16(test_s(), imm8); } +pub unsafe fn instr16_78(mut imm8: i32) { jmpcc16(test_s(), imm8); } #[no_mangle] -pub unsafe fn instr16_79(mut imm8: i32) -> () { jmpcc16(!test_s(), imm8); } +pub unsafe fn instr16_79(mut imm8: i32) { jmpcc16(!test_s(), imm8); } #[no_mangle] -pub unsafe fn instr16_7A(mut imm8: i32) -> () { jmpcc16(test_p(), imm8); } +pub unsafe fn instr16_7A(mut imm8: i32) { jmpcc16(test_p(), imm8); } #[no_mangle] -pub unsafe fn instr16_7B(mut imm8: i32) -> () { jmpcc16(!test_p(), imm8); } +pub unsafe fn instr16_7B(mut imm8: i32) { jmpcc16(!test_p(), imm8); } #[no_mangle] -pub unsafe fn instr16_7C(mut imm8: i32) -> () { jmpcc16(test_l(), imm8); } +pub unsafe fn instr16_7C(mut imm8: i32) { jmpcc16(test_l(), imm8); } #[no_mangle] -pub unsafe fn instr16_7D(mut imm8: i32) -> () { jmpcc16(!test_l(), imm8); } +pub unsafe fn instr16_7D(mut imm8: i32) { jmpcc16(!test_l(), imm8); } #[no_mangle] -pub unsafe fn instr16_7E(mut imm8: i32) -> () { jmpcc16(test_le(), imm8); } +pub unsafe fn instr16_7E(mut imm8: i32) { jmpcc16(test_le(), imm8); } #[no_mangle] -pub unsafe fn instr16_7F(mut imm8: i32) -> () { jmpcc16(!test_le(), imm8); } +pub unsafe fn instr16_7F(mut imm8: i32) { jmpcc16(!test_le(), imm8); } #[no_mangle] -pub unsafe fn instr32_70(mut imm8: i32) -> () { jmpcc32(test_o(), imm8); } +pub unsafe fn instr32_70(mut imm8: i32) { jmpcc32(test_o(), imm8); } #[no_mangle] -pub unsafe fn instr32_71(mut imm8: i32) -> () { jmpcc32(!test_o(), imm8); } +pub unsafe fn instr32_71(mut imm8: i32) { jmpcc32(!test_o(), imm8); } #[no_mangle] -pub unsafe fn instr32_72(mut imm8: i32) -> () { jmpcc32(test_b(), imm8); } +pub unsafe fn instr32_72(mut imm8: i32) { jmpcc32(test_b(), imm8); } #[no_mangle] -pub unsafe fn instr32_73(mut imm8: i32) -> () { jmpcc32(!test_b(), imm8); } +pub unsafe fn instr32_73(mut imm8: i32) { jmpcc32(!test_b(), imm8); } #[no_mangle] -pub unsafe fn instr32_74(mut imm8: i32) -> () { jmpcc32(test_z(), imm8); } +pub unsafe fn instr32_74(mut imm8: i32) { jmpcc32(test_z(), imm8); } #[no_mangle] -pub unsafe fn instr32_75(mut imm8: i32) -> () { jmpcc32(!test_z(), imm8); } +pub unsafe fn instr32_75(mut imm8: i32) { jmpcc32(!test_z(), imm8); } #[no_mangle] -pub unsafe fn instr32_76(mut imm8: i32) -> () { jmpcc32(test_be(), imm8); } +pub unsafe fn instr32_76(mut imm8: i32) { jmpcc32(test_be(), imm8); } #[no_mangle] -pub unsafe fn instr32_77(mut imm8: i32) -> () { jmpcc32(!test_be(), imm8); } +pub unsafe fn instr32_77(mut imm8: i32) { jmpcc32(!test_be(), imm8); } #[no_mangle] -pub unsafe fn instr32_78(mut imm8: i32) -> () { jmpcc32(test_s(), imm8); } +pub unsafe fn instr32_78(mut imm8: i32) { jmpcc32(test_s(), imm8); } #[no_mangle] -pub unsafe fn instr32_79(mut imm8: i32) -> () { jmpcc32(!test_s(), imm8); } +pub unsafe fn instr32_79(mut imm8: i32) { jmpcc32(!test_s(), imm8); } #[no_mangle] -pub unsafe fn instr32_7A(mut imm8: i32) -> () { jmpcc32(test_p(), imm8); } +pub unsafe fn instr32_7A(mut imm8: i32) { jmpcc32(test_p(), imm8); } #[no_mangle] -pub unsafe fn instr32_7B(mut imm8: i32) -> () { jmpcc32(!test_p(), imm8); } +pub unsafe fn instr32_7B(mut imm8: i32) { jmpcc32(!test_p(), imm8); } #[no_mangle] -pub unsafe fn instr32_7C(mut imm8: i32) -> () { jmpcc32(test_l(), imm8); } +pub unsafe fn instr32_7C(mut imm8: i32) { jmpcc32(test_l(), imm8); } #[no_mangle] -pub unsafe fn instr32_7D(mut imm8: i32) -> () { jmpcc32(!test_l(), imm8); } +pub unsafe fn instr32_7D(mut imm8: i32) { jmpcc32(!test_l(), imm8); } #[no_mangle] -pub unsafe fn instr32_7E(mut imm8: i32) -> () { jmpcc32(test_le(), imm8); } +pub unsafe fn instr32_7E(mut imm8: i32) { jmpcc32(test_le(), imm8); } #[no_mangle] -pub unsafe fn instr32_7F(mut imm8: i32) -> () { jmpcc32(!test_le(), imm8); } +pub unsafe fn instr32_7F(mut imm8: i32) { jmpcc32(!test_le(), imm8); } #[no_mangle] -pub unsafe fn instr_F2A4() -> () { movsb_rep(); } +pub unsafe fn instr_F2A4() { movsb_rep(); } #[no_mangle] -pub unsafe fn instr_F3A4() -> () { movsb_rep(); } +pub unsafe fn instr_F3A4() { movsb_rep(); } #[no_mangle] -pub unsafe fn instr16_F2A5() -> () { movsw_rep(); } +pub unsafe fn instr16_F2A5() { movsw_rep(); } #[no_mangle] -pub unsafe fn instr16_F3A5() -> () { movsw_rep(); } +pub unsafe fn instr16_F3A5() { movsw_rep(); } #[no_mangle] -pub unsafe fn instr32_F2A5() -> () { movsd_rep(); } +pub unsafe fn instr32_F2A5() { movsd_rep(); } #[no_mangle] -pub unsafe fn instr32_F3A5() -> () { movsd_rep(); } +pub unsafe fn instr32_F3A5() { movsd_rep(); } #[no_mangle] -pub unsafe fn instr_F2A6() -> () { cmpsb_rep(PREFIX_F2); } +pub unsafe fn instr_F2A6() { cmpsb_rep(PREFIX_F2); } #[no_mangle] -pub unsafe fn instr_F3A6() -> () { cmpsb_rep(PREFIX_F3); } +pub unsafe fn instr_F3A6() { cmpsb_rep(PREFIX_F3); } #[no_mangle] -pub unsafe fn instr16_F2A7() -> () { cmpsw_rep(PREFIX_F2); } +pub unsafe fn instr16_F2A7() { cmpsw_rep(PREFIX_F2); } #[no_mangle] -pub unsafe fn instr16_F3A7() -> () { cmpsw_rep(PREFIX_F3); } +pub unsafe fn instr16_F3A7() { cmpsw_rep(PREFIX_F3); } #[no_mangle] -pub unsafe fn instr32_F2A7() -> () { cmpsd_rep(PREFIX_F2); } +pub unsafe fn instr32_F2A7() { cmpsd_rep(PREFIX_F2); } #[no_mangle] -pub unsafe fn instr32_F3A7() -> () { cmpsd_rep(PREFIX_F3); } +pub unsafe fn instr32_F3A7() { cmpsd_rep(PREFIX_F3); } #[no_mangle] -pub unsafe fn instr_F2AA() -> () { stosb_rep(); } +pub unsafe fn instr_F2AA() { stosb_rep(); } #[no_mangle] -pub unsafe fn instr_F3AA() -> () { stosb_rep(); } +pub unsafe fn instr_F3AA() { stosb_rep(); } #[no_mangle] -pub unsafe fn instr16_F2AB() -> () { stosw_rep(); } +pub unsafe fn instr16_F2AB() { stosw_rep(); } #[no_mangle] -pub unsafe fn instr16_F3AB() -> () { stosw_rep(); } +pub unsafe fn instr16_F3AB() { stosw_rep(); } #[no_mangle] -pub unsafe fn instr32_F2AB() -> () { stosd_rep(); } +pub unsafe fn instr32_F2AB() { stosd_rep(); } #[no_mangle] -pub unsafe fn instr32_F3AB() -> () { stosd_rep(); } +pub unsafe fn instr32_F3AB() { stosd_rep(); } #[no_mangle] -pub unsafe fn instr_F2AC() -> () { lodsb_rep(); } +pub unsafe fn instr_F2AC() { lodsb_rep(); } #[no_mangle] -pub unsafe fn instr_F3AC() -> () { lodsb_rep(); } +pub unsafe fn instr_F3AC() { lodsb_rep(); } #[no_mangle] -pub unsafe fn instr16_F2AD() -> () { lodsw_rep(); } +pub unsafe fn instr16_F2AD() { lodsw_rep(); } #[no_mangle] -pub unsafe fn instr16_F3AD() -> () { lodsw_rep(); } +pub unsafe fn instr16_F3AD() { lodsw_rep(); } #[no_mangle] -pub unsafe fn instr32_F2AD() -> () { lodsd_rep(); } +pub unsafe fn instr32_F2AD() { lodsd_rep(); } #[no_mangle] -pub unsafe fn instr32_F3AD() -> () { lodsd_rep(); } +pub unsafe fn instr32_F3AD() { lodsd_rep(); } #[no_mangle] -pub unsafe fn instr_F2AE() -> () { scasb_rep(PREFIX_F2); } +pub unsafe fn instr_F2AE() { scasb_rep(PREFIX_F2); } #[no_mangle] -pub unsafe fn instr_F3AE() -> () { scasb_rep(PREFIX_F3); } +pub unsafe fn instr_F3AE() { scasb_rep(PREFIX_F3); } #[no_mangle] -pub unsafe fn instr16_F2AF() -> () { scasw_rep(PREFIX_F2); } +pub unsafe fn instr16_F2AF() { scasw_rep(PREFIX_F2); } #[no_mangle] -pub unsafe fn instr16_F3AF() -> () { scasw_rep(PREFIX_F3); } +pub unsafe fn instr16_F3AF() { scasw_rep(PREFIX_F3); } #[no_mangle] -pub unsafe fn instr32_F2AF() -> () { scasd_rep(PREFIX_F2); } +pub unsafe fn instr32_F2AF() { scasd_rep(PREFIX_F2); } #[no_mangle] -pub unsafe fn instr32_F3AF() -> () { scasd_rep(PREFIX_F3); } +pub unsafe fn instr32_F3AF() { scasd_rep(PREFIX_F3); } #[no_mangle] -pub unsafe fn instr_D8_0_mem(mut addr: i32) -> () { +pub unsafe fn instr_D8_0_mem(mut addr: i32) { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fadd(0i32, ____0); } #[no_mangle] -pub unsafe fn instr_D8_0_reg(mut r: i32) -> () { +pub unsafe fn instr_D8_0_reg(mut r: i32) { let mut ____0: f64 = fpu_get_sti(r); fpu_fadd(0i32, ____0); } #[no_mangle] -pub unsafe fn instr_D8_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_D8_1_mem(mut addr: i32) { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fmul(0i32, ____0); } #[no_mangle] -pub unsafe fn instr_D8_1_reg(mut r: i32) -> () { +pub unsafe fn instr_D8_1_reg(mut r: i32) { let mut ____0: f64 = fpu_get_sti(r); fpu_fmul(0i32, ____0); } #[no_mangle] -pub unsafe fn instr_D8_2_mem(mut addr: i32) -> () { +pub unsafe fn instr_D8_2_mem(mut addr: i32) { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fcom(____0); } #[no_mangle] -pub unsafe fn instr_D8_2_reg(mut r: i32) -> () { +pub unsafe fn instr_D8_2_reg(mut r: i32) { let mut ____0: f64 = fpu_get_sti(r); fpu_fcom(____0); } #[no_mangle] -pub unsafe fn instr_D8_3_mem(mut addr: i32) -> () { +pub unsafe fn instr_D8_3_mem(mut addr: i32) { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fcomp(____0); } #[no_mangle] -pub unsafe fn instr_D8_3_reg(mut r: i32) -> () { +pub unsafe fn instr_D8_3_reg(mut r: i32) { let mut ____0: f64 = fpu_get_sti(r); fpu_fcomp(____0); } #[no_mangle] -pub unsafe fn instr_D8_4_mem(mut addr: i32) -> () { +pub unsafe fn instr_D8_4_mem(mut addr: i32) { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fsub(0i32, ____0); } #[no_mangle] -pub unsafe fn instr_D8_4_reg(mut r: i32) -> () { +pub unsafe fn instr_D8_4_reg(mut r: i32) { let mut ____0: f64 = fpu_get_sti(r); fpu_fsub(0i32, ____0); } #[no_mangle] -pub unsafe fn instr_D8_5_mem(mut addr: i32) -> () { +pub unsafe fn instr_D8_5_mem(mut addr: i32) { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fsubr(0i32, ____0); } #[no_mangle] -pub unsafe fn instr_D8_5_reg(mut r: i32) -> () { +pub unsafe fn instr_D8_5_reg(mut r: i32) { let mut ____0: f64 = fpu_get_sti(r); fpu_fsubr(0i32, ____0); } #[no_mangle] -pub unsafe fn instr_D8_6_mem(mut addr: i32) -> () { +pub unsafe fn instr_D8_6_mem(mut addr: i32) { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fdiv(0i32, ____0); } #[no_mangle] -pub unsafe fn instr_D8_6_reg(mut r: i32) -> () { +pub unsafe fn instr_D8_6_reg(mut r: i32) { let mut ____0: f64 = fpu_get_sti(r); fpu_fdiv(0i32, ____0); } #[no_mangle] -pub unsafe fn instr_D8_7_mem(mut addr: i32) -> () { +pub unsafe fn instr_D8_7_mem(mut addr: i32) { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fdivr(0i32, ____0); } #[no_mangle] -pub unsafe fn instr_D8_7_reg(mut r: i32) -> () { +pub unsafe fn instr_D8_7_reg(mut r: i32) { let mut ____0: f64 = fpu_get_sti(r); fpu_fdivr(0i32, ____0); } #[no_mangle] -pub unsafe fn instr_D9_0_mem(mut addr: i32) -> () { +pub unsafe fn instr_D9_0_mem(mut addr: i32) { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_push(____0); } #[no_mangle] -pub unsafe fn instr_D9_0_reg(mut r: i32) -> () { +pub unsafe fn instr_D9_0_reg(mut r: i32) { let mut ____0: f64 = fpu_get_sti(r); fpu_push(____0); } #[no_mangle] -pub unsafe fn instr_D9_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_D9_1_mem(mut addr: i32) { dbg_log!("d9/1"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr_D9_1_reg(mut r: i32) -> () { fpu_fxch(r); } +pub unsafe fn instr_D9_1_reg(mut r: i32) { fpu_fxch(r); } #[no_mangle] -pub unsafe fn instr_D9_2_mem(mut addr: i32) -> () { fpu_fstm32(addr); } +pub unsafe fn instr_D9_2_mem(mut addr: i32) { fpu_fstm32(addr); } #[no_mangle] -pub unsafe fn instr_D9_2_reg(mut r: i32) -> () { +pub unsafe fn instr_D9_2_reg(mut r: i32) { if r != 0i32 { trigger_ud(); }; } #[no_mangle] -pub unsafe fn instr_D9_3_mem(mut addr: i32) -> () { fpu_fstm32p(addr); } +pub unsafe fn instr_D9_3_mem(mut addr: i32) { fpu_fstm32p(addr); } #[no_mangle] -pub unsafe fn instr_D9_3_reg(mut r: i32) -> () { +pub unsafe fn instr_D9_3_reg(mut r: i32) { dbg_log!("fstp1"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr_D9_4_mem(mut addr: i32) -> () { fpu_fldenv(addr); } +pub unsafe fn instr_D9_4_mem(mut addr: i32) { fpu_fldenv(addr); } #[no_mangle] -pub unsafe fn instr_D9_4_reg(mut r: i32) -> () { +pub unsafe fn instr_D9_4_reg(mut r: i32) { let mut st0: f64 = fpu_get_st0(); match r { 0 => { @@ -3909,9 +3855,9 @@ pub unsafe fn instr_D9_4_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_D9_5_mem(mut addr: i32) -> () { fpu_fldcw(addr); } +pub unsafe fn instr_D9_5_mem(mut addr: i32) { fpu_fldcw(addr); } #[no_mangle] -pub unsafe fn instr_D9_5_reg(mut r: i32) -> () { +pub unsafe fn instr_D9_5_reg(mut r: i32) { // fld1/fldl2t/fldl2e/fldpi/fldlg2/fldln2/fldz match r { 0 => { @@ -3943,9 +3889,9 @@ pub unsafe fn instr_D9_5_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_D9_6_mem(mut addr: i32) -> () { fpu_fstenv(addr); } +pub unsafe fn instr_D9_6_mem(mut addr: i32) { fpu_fstenv(addr); } #[no_mangle] -pub unsafe fn instr_D9_6_reg(mut r: i32) -> () { +pub unsafe fn instr_D9_6_reg(mut r: i32) { let mut st0: f64 = fpu_get_st0(); match r { 0 => { @@ -3993,9 +3939,9 @@ pub unsafe fn instr_D9_6_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_D9_7_mem(mut addr: i32) -> () { fpu_fstcw(addr); } +pub unsafe fn instr_D9_7_mem(mut addr: i32) { fpu_fstcw(addr); } #[no_mangle] -pub unsafe fn instr_D9_7_reg(mut r: i32) -> () { +pub unsafe fn instr_D9_7_reg(mut r: i32) { let mut st0: f64 = fpu_get_st0(); match r { 0 => { @@ -4029,49 +3975,49 @@ pub unsafe fn instr_D9_7_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_DA_0_mem(mut addr: i32) -> () { +pub unsafe fn instr_DA_0_mem(mut addr: i32) { fpu_fadd(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe fn instr_DA_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_DA_1_mem(mut addr: i32) { fpu_fmul(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe fn instr_DA_2_mem(mut addr: i32) -> () { +pub unsafe fn instr_DA_2_mem(mut addr: i32) { fpu_fcom(return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe fn instr_DA_3_mem(mut addr: i32) -> () { +pub unsafe fn instr_DA_3_mem(mut addr: i32) { fpu_fcomp(return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe fn instr_DA_4_mem(mut addr: i32) -> () { +pub unsafe fn instr_DA_4_mem(mut addr: i32) { fpu_fsub(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe fn instr_DA_5_mem(mut addr: i32) -> () { +pub unsafe fn instr_DA_5_mem(mut addr: i32) { fpu_fsubr(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe fn instr_DA_6_mem(mut addr: i32) -> () { +pub unsafe fn instr_DA_6_mem(mut addr: i32) { fpu_fdiv(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe fn instr_DA_7_mem(mut addr: i32) -> () { +pub unsafe fn instr_DA_7_mem(mut addr: i32) { fpu_fdivr(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe fn instr_DA_0_reg(mut r: i32) -> () { fpu_fcmovcc(test_b(), r); } +pub unsafe fn instr_DA_0_reg(mut r: i32) { fpu_fcmovcc(test_b(), r); } #[no_mangle] -pub unsafe fn instr_DA_1_reg(mut r: i32) -> () { fpu_fcmovcc(test_z(), r); } +pub unsafe fn instr_DA_1_reg(mut r: i32) { fpu_fcmovcc(test_z(), r); } #[no_mangle] -pub unsafe fn instr_DA_2_reg(mut r: i32) -> () { fpu_fcmovcc(test_be(), r); } +pub unsafe fn instr_DA_2_reg(mut r: i32) { fpu_fcmovcc(test_be(), r); } #[no_mangle] -pub unsafe fn instr_DA_3_reg(mut r: i32) -> () { fpu_fcmovcc(test_p(), r); } +pub unsafe fn instr_DA_3_reg(mut r: i32) { fpu_fcmovcc(test_p(), r); } #[no_mangle] -pub unsafe fn instr_DA_4_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DA_4_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DA_5_reg(mut r: i32) -> () { +pub unsafe fn instr_DA_5_reg(mut r: i32) { if r == 1i32 { fpu_fucompp(); } @@ -4080,35 +4026,35 @@ pub unsafe fn instr_DA_5_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_DA_6_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DA_6_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DA_7_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DA_7_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DB_0_mem(mut addr: i32) -> () { fpu_fldm32(addr); } +pub unsafe fn instr_DB_0_mem(mut addr: i32) { fpu_fldm32(addr); } #[no_mangle] -pub unsafe fn instr_DB_1_mem(mut addr: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DB_1_mem(mut addr: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DB_2_mem(mut addr: i32) -> () { fpu_fistm32(addr); } +pub unsafe fn instr_DB_2_mem(mut addr: i32) { fpu_fistm32(addr); } #[no_mangle] -pub unsafe fn instr_DB_3_mem(mut addr: i32) -> () { fpu_fistm32p(addr); } +pub unsafe fn instr_DB_3_mem(mut addr: i32) { fpu_fistm32p(addr); } #[no_mangle] -pub unsafe fn instr_DB_4_mem(mut addr: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DB_4_mem(mut addr: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DB_5_mem(mut addr: i32) -> () { fpu_fldm80(addr); } +pub unsafe fn instr_DB_5_mem(mut addr: i32) { fpu_fldm80(addr); } #[no_mangle] -pub unsafe fn instr_DB_6_mem(mut addr: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DB_6_mem(mut addr: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DB_7_mem(mut addr: i32) -> () { fpu_fst80p(addr); } +pub unsafe fn instr_DB_7_mem(mut addr: i32) { fpu_fst80p(addr); } #[no_mangle] -pub unsafe fn instr_DB_0_reg(mut r: i32) -> () { fpu_fcmovcc(!test_b(), r); } +pub unsafe fn instr_DB_0_reg(mut r: i32) { fpu_fcmovcc(!test_b(), r); } #[no_mangle] -pub unsafe fn instr_DB_1_reg(mut r: i32) -> () { fpu_fcmovcc(!test_z(), r); } +pub unsafe fn instr_DB_1_reg(mut r: i32) { fpu_fcmovcc(!test_z(), r); } #[no_mangle] -pub unsafe fn instr_DB_2_reg(mut r: i32) -> () { fpu_fcmovcc(!test_be(), r); } +pub unsafe fn instr_DB_2_reg(mut r: i32) { fpu_fcmovcc(!test_be(), r); } #[no_mangle] -pub unsafe fn instr_DB_3_reg(mut r: i32) -> () { fpu_fcmovcc(!test_p(), r); } +pub unsafe fn instr_DB_3_reg(mut r: i32) { fpu_fcmovcc(!test_p(), r); } #[no_mangle] -pub unsafe fn instr_DB_4_reg(mut r: i32) -> () { +pub unsafe fn instr_DB_4_reg(mut r: i32) { if r == 3i32 { fpu_finit(); } @@ -4123,206 +4069,202 @@ pub unsafe fn instr_DB_4_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_DB_5_reg(mut r: i32) -> () { fpu_fucomi(r); } +pub unsafe fn instr_DB_5_reg(mut r: i32) { fpu_fucomi(r); } #[no_mangle] -pub unsafe fn instr_DB_6_reg(mut r: i32) -> () { fpu_fcomi(r); } +pub unsafe fn instr_DB_6_reg(mut r: i32) { fpu_fcomi(r); } #[no_mangle] -pub unsafe fn instr_DB_7_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DB_7_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DC_0_mem(mut addr: i32) -> () { +pub unsafe fn instr_DC_0_mem(mut addr: i32) { fpu_fadd(0i32, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe fn instr_DC_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_DC_1_mem(mut addr: i32) { fpu_fmul(0i32, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe fn instr_DC_2_mem(mut addr: i32) -> () { - fpu_fcom(return_on_pagefault!(fpu_load_m64(addr))); -} +pub unsafe fn instr_DC_2_mem(mut addr: i32) { fpu_fcom(return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe fn instr_DC_3_mem(mut addr: i32) -> () { - fpu_fcomp(return_on_pagefault!(fpu_load_m64(addr))); -} +pub unsafe fn instr_DC_3_mem(mut addr: i32) { fpu_fcomp(return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe fn instr_DC_4_mem(mut addr: i32) -> () { +pub unsafe fn instr_DC_4_mem(mut addr: i32) { fpu_fsub(0i32, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe fn instr_DC_5_mem(mut addr: i32) -> () { +pub unsafe fn instr_DC_5_mem(mut addr: i32) { fpu_fsubr(0i32, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe fn instr_DC_6_mem(mut addr: i32) -> () { +pub unsafe fn instr_DC_6_mem(mut addr: i32) { fpu_fdiv(0i32, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe fn instr_DC_7_mem(mut addr: i32) -> () { +pub unsafe fn instr_DC_7_mem(mut addr: i32) { fpu_fdivr(0i32, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe fn instr_DC_0_reg(mut r: i32) -> () { fpu_fadd(r, fpu_get_sti(r)); } +pub unsafe fn instr_DC_0_reg(mut r: i32) { fpu_fadd(r, fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_DC_1_reg(mut r: i32) -> () { fpu_fmul(r, fpu_get_sti(r)); } +pub unsafe fn instr_DC_1_reg(mut r: i32) { fpu_fmul(r, fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_DC_2_reg(mut r: i32) -> () { fpu_fcom(fpu_get_sti(r)); } +pub unsafe fn instr_DC_2_reg(mut r: i32) { fpu_fcom(fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_DC_3_reg(mut r: i32) -> () { fpu_fcomp(fpu_get_sti(r)); } +pub unsafe fn instr_DC_3_reg(mut r: i32) { fpu_fcomp(fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_DC_4_reg(mut r: i32) -> () { fpu_fsub(r, fpu_get_sti(r)); } +pub unsafe fn instr_DC_4_reg(mut r: i32) { fpu_fsub(r, fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_DC_5_reg(mut r: i32) -> () { fpu_fsubr(r, fpu_get_sti(r)); } +pub unsafe fn instr_DC_5_reg(mut r: i32) { fpu_fsubr(r, fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_DC_6_reg(mut r: i32) -> () { fpu_fdiv(r, fpu_get_sti(r)); } +pub unsafe fn instr_DC_6_reg(mut r: i32) { fpu_fdiv(r, fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_DC_7_reg(mut r: i32) -> () { fpu_fdivr(r, fpu_get_sti(r)); } +pub unsafe fn instr_DC_7_reg(mut r: i32) { fpu_fdivr(r, fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_DD_0_mem(mut addr: i32) -> () { fpu_fldm64(addr); } +pub unsafe fn instr_DD_0_mem(mut addr: i32) { fpu_fldm64(addr); } #[no_mangle] -pub unsafe fn instr_DD_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_DD_1_mem(mut addr: i32) { dbg_log!("fisttp"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DD_2_mem(mut addr: i32) -> () { fpu_fstm64(addr); } +pub unsafe fn instr_DD_2_mem(mut addr: i32) { fpu_fstm64(addr); } #[no_mangle] -pub unsafe fn instr_DD_3_mem(mut addr: i32) -> () { fpu_fstm64p(addr); } +pub unsafe fn instr_DD_3_mem(mut addr: i32) { fpu_fstm64p(addr); } #[no_mangle] -pub unsafe fn instr_DD_4_mem(mut addr: i32) -> () { fpu_frstor(addr); } +pub unsafe fn instr_DD_4_mem(mut addr: i32) { fpu_frstor(addr); } #[no_mangle] -pub unsafe fn instr_DD_5_mem(mut addr: i32) -> () { +pub unsafe fn instr_DD_5_mem(mut addr: i32) { dbg_log!("dd/5"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DD_6_mem(mut addr: i32) -> () { fpu_fsave(addr); } +pub unsafe fn instr_DD_6_mem(mut addr: i32) { fpu_fsave(addr); } #[no_mangle] -pub unsafe fn instr_DD_7_mem(mut addr: i32) -> () { fpu_fnstsw_mem(addr); } +pub unsafe fn instr_DD_7_mem(mut addr: i32) { fpu_fnstsw_mem(addr); } #[no_mangle] -pub unsafe fn instr_DD_0_reg(mut r: i32) -> () { fpu_ffree(r); } +pub unsafe fn instr_DD_0_reg(mut r: i32) { fpu_ffree(r); } #[no_mangle] -pub unsafe fn instr_DD_1_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DD_1_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DD_2_reg(mut r: i32) -> () { fpu_fst(r); } +pub unsafe fn instr_DD_2_reg(mut r: i32) { fpu_fst(r); } #[no_mangle] -pub unsafe fn instr_DD_3_reg(mut r: i32) -> () { fpu_fstp(r); } +pub unsafe fn instr_DD_3_reg(mut r: i32) { fpu_fstp(r); } #[no_mangle] -pub unsafe fn instr_DD_4_reg(mut r: i32) -> () { fpu_fucom(r); } +pub unsafe fn instr_DD_4_reg(mut r: i32) { fpu_fucom(r); } #[no_mangle] -pub unsafe fn instr_DD_5_reg(mut r: i32) -> () { fpu_fucomp(r); } +pub unsafe fn instr_DD_5_reg(mut r: i32) { fpu_fucomp(r); } #[no_mangle] -pub unsafe fn instr_DD_6_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DD_6_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DD_7_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DD_7_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DE_0_mem(mut addr: i32) -> () { +pub unsafe fn instr_DE_0_mem(mut addr: i32) { fpu_fadd(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe fn instr_DE_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_DE_1_mem(mut addr: i32) { fpu_fmul(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe fn instr_DE_2_mem(mut addr: i32) -> () { +pub unsafe fn instr_DE_2_mem(mut addr: i32) { fpu_fcom(return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe fn instr_DE_3_mem(mut addr: i32) -> () { +pub unsafe fn instr_DE_3_mem(mut addr: i32) { fpu_fcomp(return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe fn instr_DE_4_mem(mut addr: i32) -> () { +pub unsafe fn instr_DE_4_mem(mut addr: i32) { fpu_fsub(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe fn instr_DE_5_mem(mut addr: i32) -> () { +pub unsafe fn instr_DE_5_mem(mut addr: i32) { fpu_fsubr(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe fn instr_DE_6_mem(mut addr: i32) -> () { +pub unsafe fn instr_DE_6_mem(mut addr: i32) { fpu_fdiv(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe fn instr_DE_7_mem(mut addr: i32) -> () { +pub unsafe fn instr_DE_7_mem(mut addr: i32) { fpu_fdivr(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe fn instr_DE_0_reg(mut r: i32) -> () { +pub unsafe fn instr_DE_0_reg(mut r: i32) { fpu_fadd(r, fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe fn instr_DE_1_reg(mut r: i32) -> () { +pub unsafe fn instr_DE_1_reg(mut r: i32) { fpu_fmul(r, fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe fn instr_DE_2_reg(mut r: i32) -> () { +pub unsafe fn instr_DE_2_reg(mut r: i32) { fpu_fcom(fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe fn instr_DE_3_reg(mut r: i32) -> () { +pub unsafe fn instr_DE_3_reg(mut r: i32) { fpu_fcomp(fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe fn instr_DE_4_reg(mut r: i32) -> () { +pub unsafe fn instr_DE_4_reg(mut r: i32) { fpu_fsub(r, fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe fn instr_DE_5_reg(mut r: i32) -> () { +pub unsafe fn instr_DE_5_reg(mut r: i32) { fpu_fsubr(r, fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe fn instr_DE_6_reg(mut r: i32) -> () { +pub unsafe fn instr_DE_6_reg(mut r: i32) { fpu_fdiv(r, fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe fn instr_DE_7_reg(mut r: i32) -> () { +pub unsafe fn instr_DE_7_reg(mut r: i32) { fpu_fdivr(r, fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe fn instr_DF_0_mem(mut addr: i32) -> () { +pub unsafe fn instr_DF_0_mem(mut addr: i32) { fpu_push(return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe fn instr_DF_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_DF_1_mem(mut addr: i32) { dbg_log!("df/fisttp"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DF_2_mem(mut addr: i32) -> () { fpu_fistm16(addr); } +pub unsafe fn instr_DF_2_mem(mut addr: i32) { fpu_fistm16(addr); } #[no_mangle] -pub unsafe fn instr_DF_3_mem(mut addr: i32) -> () { fpu_fistm16p(addr); } +pub unsafe fn instr_DF_3_mem(mut addr: i32) { fpu_fistm16p(addr); } #[no_mangle] -pub unsafe fn instr_DF_4_mem(mut addr: i32) -> () { +pub unsafe fn instr_DF_4_mem(mut addr: i32) { dbg_log!("fbld"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DF_5_mem(mut addr: i32) -> () { fpu_fildm64(addr); } +pub unsafe fn instr_DF_5_mem(mut addr: i32) { fpu_fildm64(addr); } #[no_mangle] -pub unsafe fn instr_DF_6_mem(mut addr: i32) -> () { +pub unsafe fn instr_DF_6_mem(mut addr: i32) { dbg_log!("fbstp"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DF_7_mem(mut addr: i32) -> () { fpu_fistm64p(addr); } +pub unsafe fn instr_DF_7_mem(mut addr: i32) { fpu_fistm64p(addr); } #[no_mangle] -pub unsafe fn instr_DF_0_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DF_0_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DF_1_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DF_1_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DF_2_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DF_2_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DF_3_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DF_3_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DF_4_reg(mut r: i32) -> () { +pub unsafe fn instr_DF_4_reg(mut r: i32) { if r == 0i32 { fpu_fnstsw_reg(); } @@ -4331,35 +4273,35 @@ pub unsafe fn instr_DF_4_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_DF_5_reg(mut r: i32) -> () { fpu_fucomip(r); } +pub unsafe fn instr_DF_5_reg(mut r: i32) { fpu_fucomip(r); } #[no_mangle] -pub unsafe fn instr_DF_6_reg(mut r: i32) -> () { fpu_fcomip(r); } +pub unsafe fn instr_DF_6_reg(mut r: i32) { fpu_fcomip(r); } #[no_mangle] -pub unsafe fn instr_DF_7_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_DF_7_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_E0(mut imm8s: i32) -> () { loopne16(imm8s); } +pub unsafe fn instr16_E0(mut imm8s: i32) { loopne16(imm8s); } #[no_mangle] -pub unsafe fn instr16_E1(mut imm8s: i32) -> () { loope16(imm8s); } +pub unsafe fn instr16_E1(mut imm8s: i32) { loope16(imm8s); } #[no_mangle] -pub unsafe fn instr16_E2(mut imm8s: i32) -> () { loop16(imm8s); } +pub unsafe fn instr16_E2(mut imm8s: i32) { loop16(imm8s); } #[no_mangle] -pub unsafe fn instr16_E3(mut imm8s: i32) -> () { jcxz16(imm8s); } +pub unsafe fn instr16_E3(mut imm8s: i32) { jcxz16(imm8s); } #[no_mangle] -pub unsafe fn instr32_E0(mut imm8s: i32) -> () { loopne32(imm8s); } +pub unsafe fn instr32_E0(mut imm8s: i32) { loopne32(imm8s); } #[no_mangle] -pub unsafe fn instr32_E1(mut imm8s: i32) -> () { loope32(imm8s); } +pub unsafe fn instr32_E1(mut imm8s: i32) { loope32(imm8s); } #[no_mangle] -pub unsafe fn instr32_E2(mut imm8s: i32) -> () { loop32(imm8s); } +pub unsafe fn instr32_E2(mut imm8s: i32) { loop32(imm8s); } #[no_mangle] -pub unsafe fn instr32_E3(mut imm8s: i32) -> () { jcxz32(imm8s); } +pub unsafe fn instr32_E3(mut imm8s: i32) { jcxz32(imm8s); } #[no_mangle] -pub unsafe fn instr16_EB(mut imm8: i32) -> () { +pub unsafe fn instr16_EB(mut imm8: i32) { // jmp near jmp_rel16(imm8); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); } #[no_mangle] -pub unsafe fn instr32_EB(mut imm8: i32) -> () { +pub unsafe fn instr32_EB(mut imm8: i32) { // jmp near *instruction_pointer = *instruction_pointer + imm8; dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 5db03896..b8705530 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -65,7 +65,7 @@ pub static mut apic_enabled: bool = false; const ENABLE_ACPI: bool = false; #[no_mangle] -pub unsafe fn instr_0F00_0_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F00_0_mem(mut addr: i32) { // sldt if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); @@ -77,7 +77,7 @@ pub unsafe fn instr_0F00_0_mem(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_0F00_0_reg(mut r: i32) -> () { +pub unsafe fn instr_0F00_0_reg(mut r: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -88,7 +88,7 @@ pub unsafe fn instr_0F00_0_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_0F00_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F00_1_mem(mut addr: i32) { // str if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); @@ -100,7 +100,7 @@ pub unsafe fn instr_0F00_1_mem(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_0F00_1_reg(mut r: i32) -> () { +pub unsafe fn instr_0F00_1_reg(mut r: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -111,7 +111,7 @@ pub unsafe fn instr_0F00_1_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_0F00_2_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F00_2_mem(mut addr: i32) { // lldt if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); @@ -127,7 +127,7 @@ pub unsafe fn instr_0F00_2_mem(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_0F00_2_reg(mut r: i32) -> () { +pub unsafe fn instr_0F00_2_reg(mut r: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -142,7 +142,7 @@ pub unsafe fn instr_0F00_2_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_0F00_3_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F00_3_mem(mut addr: i32) { // ltr if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); @@ -158,7 +158,7 @@ pub unsafe fn instr_0F00_3_mem(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_0F00_3_reg(mut r: i32) -> () { +pub unsafe fn instr_0F00_3_reg(mut r: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -173,7 +173,7 @@ pub unsafe fn instr_0F00_3_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_0F00_4_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F00_4_mem(mut addr: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -184,7 +184,7 @@ pub unsafe fn instr_0F00_4_mem(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_0F00_4_reg(mut r: i32) -> () { +pub unsafe fn instr_0F00_4_reg(mut r: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -195,7 +195,7 @@ pub unsafe fn instr_0F00_4_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_0F00_5_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F00_5_mem(mut addr: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -206,7 +206,7 @@ pub unsafe fn instr_0F00_5_mem(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_0F00_5_reg(mut r: i32) -> () { +pub unsafe fn instr_0F00_5_reg(mut r: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -217,9 +217,9 @@ pub unsafe fn instr_0F00_5_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_0F01_0_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F01_0_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F01_0_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F01_0_mem(mut addr: i32) { // sgdt return_on_pagefault!(writable_or_pagefault(addr, 6i32)); let mut mask: i32 = if 0 != is_osize_32() as i32 { @@ -232,9 +232,9 @@ pub unsafe fn instr_0F01_0_mem(mut addr: i32) -> () { safe_write32(addr + 2i32, *gdtr_offset & mask).unwrap(); } #[no_mangle] -pub unsafe fn instr_0F01_1_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F01_1_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F01_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F01_1_mem(mut addr: i32) { // sidt return_on_pagefault!(writable_or_pagefault(addr, 6i32)); let mut mask: i32 = if 0 != is_osize_32() as i32 { @@ -247,9 +247,9 @@ pub unsafe fn instr_0F01_1_mem(mut addr: i32) -> () { safe_write32(addr + 2i32, *idtr_offset & mask).unwrap(); } #[no_mangle] -pub unsafe fn instr_0F01_2_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F01_2_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F01_2_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F01_2_mem(mut addr: i32) { // lgdt if 0 != *cpl { trigger_gp_non_raising(0i32); @@ -270,9 +270,9 @@ pub unsafe fn instr_0F01_2_mem(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_0F01_3_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F01_3_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F01_3_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F01_3_mem(mut addr: i32) { // lidt if 0 != *cpl { trigger_gp_non_raising(0i32); @@ -293,16 +293,16 @@ pub unsafe fn instr_0F01_3_mem(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_0F01_4_reg(mut r: i32) -> () { +pub unsafe fn instr_0F01_4_reg(mut r: i32) { // smsw write_reg_osize(r, *cr); } #[no_mangle] -pub unsafe fn instr_0F01_4_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F01_4_mem(mut addr: i32) { return_on_pagefault!(safe_write16(addr, *cr & 65535i32)); } #[no_mangle] -pub unsafe fn lmsw(mut new_cr0: i32) -> () { +pub unsafe fn lmsw(mut new_cr0: i32) { new_cr0 = *cr & !15i32 | new_cr0 & 15i32; if *protected_mode { // lmsw cannot be used to switch back @@ -311,7 +311,7 @@ pub unsafe fn lmsw(mut new_cr0: i32) -> () { set_cr0(new_cr0); } #[no_mangle] -pub unsafe fn instr_0F01_6_reg(mut r: i32) -> () { +pub unsafe fn instr_0F01_6_reg(mut r: i32) { if 0 != *cpl { trigger_gp_non_raising(0i32); return; @@ -322,7 +322,7 @@ pub unsafe fn instr_0F01_6_reg(mut r: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_0F01_6_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F01_6_mem(mut addr: i32) { if 0 != *cpl { trigger_gp_non_raising(0i32); return; @@ -333,9 +333,9 @@ pub unsafe fn instr_0F01_6_mem(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_0F01_7_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F01_7_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F01_7_mem(mut addr: i32) -> () { +pub unsafe fn instr_0F01_7_mem(mut addr: i32) { // invlpg if 0 != *cpl { trigger_gp_non_raising(0i32); @@ -347,51 +347,51 @@ pub unsafe fn instr_0F01_7_mem(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr16_0F02_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F02_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, lar(____0, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr16_0F02_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F02_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r, lar(____0, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr32_0F02_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F02_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg32(r, lar(____0, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr32_0F02_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F02_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg32(r, lar(____0, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr16_0F03_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F03_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, lsl(____0, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr16_0F03_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F03_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r, lsl(____0, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr32_0F03_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F03_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg32(r, lsl(____0, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr32_0F03_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F03_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg32(r, lsl(____0, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr_0F04() -> () { undefined_instruction(); } +pub unsafe fn instr_0F04() { undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0F05() -> () { undefined_instruction(); } +pub unsafe fn instr_0F05() { undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0F06() -> () { +pub unsafe fn instr_0F06() { // clts if 0 != *cpl { dbg_log!("clts #gp"); @@ -405,14 +405,14 @@ pub unsafe fn instr_0F06() -> () { }; } #[no_mangle] -pub unsafe fn instr_0F07() -> () { undefined_instruction(); } +pub unsafe fn instr_0F07() { undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0F08() -> () { +pub unsafe fn instr_0F08() { // invd undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0F09() -> () { +pub unsafe fn instr_0F09() { if 0 != *cpl { dbg_log!("wbinvd #gp"); trigger_gp_non_raising(0i32); @@ -422,36 +422,36 @@ pub unsafe fn instr_0F09() -> () { }; } #[no_mangle] -pub unsafe fn instr_0F0A() -> () { undefined_instruction(); } +pub unsafe fn instr_0F0A() { undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0F0B() -> () { +pub unsafe fn instr_0F0B() { // UD2 trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F0C() -> () { undefined_instruction(); } +pub unsafe fn instr_0F0C() { undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0F0D() -> () { +pub unsafe fn instr_0F0D() { // nop undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0F0E() -> () { undefined_instruction(); } +pub unsafe fn instr_0F0E() { undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0F0F() -> () { undefined_instruction(); } +pub unsafe fn instr_0F0F() { undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0F10(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F10(mut source: reg128, mut r: i32) { // movups xmm, xmm/m128 mov_rm_r128(source, r); } #[no_mangle] -pub unsafe fn instr_0F10_reg(mut r1: i32, mut r2: i32) -> () { instr_0F10(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F10_reg(mut r1: i32, mut r2: i32) { instr_0F10(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F10_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F10_mem(mut addr: i32, mut r: i32) { instr_0F10(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F10_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F30F10_reg(mut r1: i32, mut r2: i32) { // movss xmm, xmm/m32 let mut data: reg128 = read_xmm128s(r1); let mut orig: reg128 = read_xmm128s(r2); @@ -464,26 +464,24 @@ pub unsafe fn instr_F30F10_reg(mut r1: i32, mut r2: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_F30F10_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F10_mem(mut addr: i32, mut r: i32) { // movss xmm, xmm/m32 let mut data: i32 = return_on_pagefault!(safe_read32s(addr)); write_xmm128(r, data, 0i32, 0i32, 0i32); } #[no_mangle] -pub unsafe fn instr_660F10(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F10(mut source: reg128, mut r: i32) { // movupd xmm, xmm/m128 mov_rm_r128(source, r); } #[no_mangle] -pub unsafe fn instr_660F10_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F10(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F10_reg(mut r1: i32, mut r2: i32) { instr_660F10(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F10_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F10_mem(mut addr: i32, mut r: i32) { instr_660F10(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20F10_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F20F10_reg(mut r1: i32, mut r2: i32) { // movsd xmm, xmm/m64 let mut data: reg128 = read_xmm128s(r1); let mut orig: reg128 = read_xmm128s(r2); @@ -496,7 +494,7 @@ pub unsafe fn instr_F20F10_reg(mut r1: i32, mut r2: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_F20F10_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F10_mem(mut addr: i32, mut r: i32) { // movsd xmm, xmm/m64 let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); write_xmm128( @@ -508,17 +506,17 @@ pub unsafe fn instr_F20F10_mem(mut addr: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_0F11_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_0F11_reg(mut r1: i32, mut r2: i32) { // movups xmm/m128, xmm mov_r_r128(r1, r2); } #[no_mangle] -pub unsafe fn instr_0F11_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F11_mem(mut addr: i32, mut r: i32) { // movups xmm/m128, xmm mov_r_m128(addr, r); } #[no_mangle] -pub unsafe fn instr_F30F11_reg(mut rm_dest: i32, mut reg_src: i32) -> () { +pub unsafe fn instr_F30F11_reg(mut rm_dest: i32, mut reg_src: i32) { // movss xmm/m32, xmm let mut data: reg128 = read_xmm128s(reg_src); let mut orig: reg128 = read_xmm128s(rm_dest); @@ -531,23 +529,23 @@ pub unsafe fn instr_F30F11_reg(mut rm_dest: i32, mut reg_src: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_F30F11_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F11_mem(mut addr: i32, mut r: i32) { // movss xmm/m32, xmm let mut data: reg128 = read_xmm128s(r); return_on_pagefault!(safe_write32(addr, data.u32_0[0usize] as i32)); } #[no_mangle] -pub unsafe fn instr_660F11_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F11_reg(mut r1: i32, mut r2: i32) { // movupd xmm/m128, xmm mov_r_r128(r1, r2); } #[no_mangle] -pub unsafe fn instr_660F11_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F11_mem(mut addr: i32, mut r: i32) { // movupd xmm/m128, xmm mov_r_m128(addr, r); } #[no_mangle] -pub unsafe fn instr_F20F11_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F20F11_reg(mut r1: i32, mut r2: i32) { // movsd xmm/m64, xmm let mut data: reg128 = read_xmm128s(r2); let mut orig: reg128 = read_xmm128s(r1); @@ -560,13 +558,13 @@ pub unsafe fn instr_F20F11_reg(mut r1: i32, mut r2: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_F20F11_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F11_mem(mut addr: i32, mut r: i32) { // movsd xmm/m64, xmm let mut data: reg64 = read_xmm64s(r); return_on_pagefault!(safe_write64(addr, data.u64_0[0usize] as i64)); } #[no_mangle] -pub unsafe fn instr_0F12_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F12_mem(mut addr: i32, mut r: i32) { // movlps xmm, m64 let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); let mut orig: reg128 = read_xmm128s(r); @@ -579,7 +577,7 @@ pub unsafe fn instr_0F12_mem(mut addr: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_0F12_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_0F12_reg(mut r1: i32, mut r2: i32) { // movhlps xmm, xmm let mut data: reg128 = read_xmm128s(r1); let mut orig: reg128 = read_xmm128s(r2); @@ -592,37 +590,37 @@ pub unsafe fn instr_0F12_reg(mut r1: i32, mut r2: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_660F12_reg(mut r1: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F12_reg(mut r1: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F12_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F12_mem(mut addr: i32, mut r: i32) { // movlpd xmm, m64 let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); write_xmm64(r, data); } #[no_mangle] -pub unsafe fn instr_F20F12_mem(mut addr: i32, mut r: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_F20F12_mem(mut addr: i32, mut r: i32) { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_F20F12_reg(mut r1: i32, mut r2: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_F20F12_reg(mut r1: i32, mut r2: i32) { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_F30F12_mem(mut addr: i32, mut r: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_F30F12_mem(mut addr: i32, mut r: i32) { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_F30F12_reg(mut r1: i32, mut r2: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_F30F12_reg(mut r1: i32, mut r2: i32) { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_0F13_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F13_mem(mut addr: i32, mut r: i32) { // movlps m64, xmm movl_r128_m64(addr, r); } #[no_mangle] -pub unsafe fn instr_0F13_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F13_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F13_reg(mut r1: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F13_reg(mut r1: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F13_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F13_mem(mut addr: i32, mut r: i32) { // movlpd xmm/m64, xmm movl_r128_m64(addr, r); } #[no_mangle] -pub unsafe fn instr_0F14(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F14(mut source: reg64, mut r: i32) { // unpcklps xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg64 = read_xmm64s(r); @@ -635,13 +633,13 @@ pub unsafe fn instr_0F14(mut source: reg64, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_0F14_reg(mut r1: i32, mut r2: i32) -> () { instr_0F14(read_xmm64s(r1), r2); } +pub unsafe fn instr_0F14_reg(mut r1: i32, mut r2: i32) { instr_0F14(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F14_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F14_mem(mut addr: i32, mut r: i32) { instr_0F14(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F14(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_660F14(mut source: reg64, mut r: i32) { // unpcklpd xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg64 = read_xmm64s(r); @@ -654,15 +652,13 @@ pub unsafe fn instr_660F14(mut source: reg64, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_660F14_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F14(read_xmm64s(r1), r2); -} +pub unsafe fn instr_660F14_reg(mut r1: i32, mut r2: i32) { instr_660F14(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F14_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F14_mem(mut addr: i32, mut r: i32) { instr_660F14(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F15(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F15(mut source: reg128, mut r: i32) { // unpckhps xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -675,13 +671,13 @@ pub unsafe fn instr_0F15(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_0F15_reg(mut r1: i32, mut r2: i32) -> () { instr_0F15(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F15_reg(mut r1: i32, mut r2: i32) { instr_0F15(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F15_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F15_mem(mut addr: i32, mut r: i32) { instr_0F15(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F15(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F15(mut source: reg128, mut r: i32) { // unpckhpd xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -694,20 +690,18 @@ pub unsafe fn instr_660F15(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_660F15_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F15(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F15_reg(mut r1: i32, mut r2: i32) { instr_660F15(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F15_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F15_mem(mut addr: i32, mut r: i32) { instr_660F15(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F16_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F16_mem(mut addr: i32, mut r: i32) { // movhps xmm, m64 movh_m64_r128(addr, r); } #[no_mangle] -pub unsafe fn instr_0F16_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_0F16_reg(mut r1: i32, mut r2: i32) { // movlhps xmm, xmm let mut data: reg128 = read_xmm128s(r1); let mut orig: reg128 = read_xmm128s(r2); @@ -720,45 +714,45 @@ pub unsafe fn instr_0F16_reg(mut r1: i32, mut r2: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_660F16_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F16_mem(mut addr: i32, mut r: i32) { // movhpd xmm, m64 movh_m64_r128(addr, r); } #[no_mangle] -pub unsafe fn instr_660F16_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F16_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F17_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F17_mem(mut addr: i32, mut r: i32) { // movhps m64, xmm movh_r128_m64(addr, r); } #[no_mangle] -pub unsafe fn instr_0F17_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F17_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F17_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F17_mem(mut addr: i32, mut r: i32) { // movhpd m64, xmm movh_r128_m64(addr, r); } #[no_mangle] -pub unsafe fn instr_660F17_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F17_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F18_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_0F18_reg(mut r1: i32, mut r2: i32) { // reserved nop } #[no_mangle] -pub unsafe fn instr_0F18_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F18_mem(mut addr: i32, mut r: i32) { // prefetch // nop for us } #[no_mangle] -pub unsafe fn instr_0F1A() -> () { undefined_instruction(); } +pub unsafe fn instr_0F1A() { undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0F1B() -> () { undefined_instruction(); } +pub unsafe fn instr_0F1B() { undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0F1F_reg(mut r1: i32, mut r2: i32) -> () {} +pub unsafe fn instr_0F1F_reg(mut r1: i32, mut r2: i32) {} #[no_mangle] -pub unsafe fn instr_0F1F_mem(mut addr: i32, mut r: i32) -> () {} +pub unsafe fn instr_0F1F_mem(mut addr: i32, mut r: i32) {} #[no_mangle] -pub unsafe fn instr_0F20(mut r: i32, mut creg: i32) -> () { +pub unsafe fn instr_0F20(mut r: i32, mut creg: i32) { if 0 != *cpl { trigger_gp_non_raising(0i32); return; @@ -786,7 +780,7 @@ pub unsafe fn instr_0F20(mut r: i32, mut creg: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_0F21(mut r: i32, mut dreg_index: i32) -> () { +pub unsafe fn instr_0F21(mut r: i32, mut dreg_index: i32) { if 0 != *cpl { trigger_gp_non_raising(0i32); return; @@ -815,7 +809,7 @@ pub unsafe fn instr_0F21(mut r: i32, mut dreg_index: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_0F22(mut r: i32, mut creg: i32) -> () { +pub unsafe fn instr_0F22(mut r: i32, mut creg: i32) { if 0 != *cpl { trigger_gp_non_raising(0i32); return; @@ -876,7 +870,7 @@ pub unsafe fn instr_0F22(mut r: i32, mut creg: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_0F23(mut r: i32, mut dreg_index: i32) -> () { +pub unsafe fn instr_0F23(mut r: i32, mut dreg_index: i32) { if 0 != *cpl { trigger_gp_non_raising(0i32); return; @@ -905,83 +899,81 @@ pub unsafe fn instr_0F23(mut r: i32, mut dreg_index: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_0F24() -> () { undefined_instruction(); } +pub unsafe fn instr_0F24() { undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0F25() -> () { undefined_instruction(); } +pub unsafe fn instr_0F25() { undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0F26() -> () { undefined_instruction(); } +pub unsafe fn instr_0F26() { undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0F27() -> () { undefined_instruction(); } +pub unsafe fn instr_0F27() { undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0F28(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F28(mut source: reg128, mut r: i32) { // movaps xmm, xmm/m128 // XXX: Aligned read or #gp mov_rm_r128(source, r); } #[no_mangle] -pub unsafe fn instr_0F28_reg(mut r1: i32, mut r2: i32) -> () { instr_0F28(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F28_reg(mut r1: i32, mut r2: i32) { instr_0F28(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F28_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F28_mem(mut addr: i32, mut r: i32) { instr_0F28(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F28(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F28(mut source: reg128, mut r: i32) { // movapd xmm, xmm/m128 // XXX: Aligned read or #gp // Note: Same as movdqa (660F6F) mov_rm_r128(source, r); } #[no_mangle] -pub unsafe fn instr_660F28_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F28(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F28_reg(mut r1: i32, mut r2: i32) { instr_660F28(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F28_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F28_mem(mut addr: i32, mut r: i32) { instr_660F28(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F29_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F29_mem(mut addr: i32, mut r: i32) { // movaps m128, xmm let mut data: reg128 = read_xmm128s(r); // XXX: Aligned write or #gp return_on_pagefault!(safe_write128(addr, data)); } #[no_mangle] -pub unsafe fn instr_0F29_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_0F29_reg(mut r1: i32, mut r2: i32) { // movaps xmm, xmm mov_r_r128(r1, r2); } #[no_mangle] -pub unsafe fn instr_660F29_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F29_mem(mut addr: i32, mut r: i32) { // movapd m128, xmm let mut data: reg128 = read_xmm128s(r); // XXX: Aligned write or #gp return_on_pagefault!(safe_write128(addr, data)); } #[no_mangle] -pub unsafe fn instr_660F29_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F29_reg(mut r1: i32, mut r2: i32) { // movapd xmm, xmm mov_r_r128(r1, r2); } #[no_mangle] -pub unsafe fn instr_0F2B_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F2B_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F2B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F2B_mem(mut addr: i32, mut r: i32) { // movntps m128, xmm // XXX: Aligned write or #gp mov_r_m128(addr, r); } #[no_mangle] -pub unsafe fn instr_660F2B_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F2B_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F2B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F2B_mem(mut addr: i32, mut r: i32) { // movntpd m128, xmm // XXX: Aligned write or #gp mov_r_m128(addr, r); } #[no_mangle] -pub unsafe fn instr_0F2C(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F2C(mut source: reg64, mut r: i32) { // cvttps2pi mm, xmm/m64 let result = reg64 { i32_0: [ @@ -992,14 +984,14 @@ pub unsafe fn instr_0F2C(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe fn instr_0F2C_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F2C_mem(mut addr: i32, mut r: i32) { instr_0F2C(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F2C_reg(mut r1: i32, mut r2: i32) -> () { instr_0F2C(read_xmm64s(r1), r2); } +pub unsafe fn instr_0F2C_reg(mut r1: i32, mut r2: i32) { instr_0F2C(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F2C(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F2C(mut source: reg128, mut r: i32) { // cvttpd2pi mm, xmm/m128 let result = reg64 { // XXX: Check conversion @@ -1011,41 +1003,35 @@ pub unsafe fn instr_660F2C(mut source: reg128, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe fn instr_660F2C_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F2C_mem(mut addr: i32, mut r: i32) { instr_660F2C(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F2C_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F2C(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F2C_reg(mut r1: i32, mut r2: i32) { instr_660F2C(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F2C(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_F20F2C(mut source: reg64, mut r: i32) { // cvttsd2si r32, xmm/m64 write_reg32(r, sse_convert_f64_to_i32(source.f64_0[0usize])); } #[no_mangle] -pub unsafe fn instr_F20F2C_reg(mut r1: i32, mut r2: i32) -> () { - instr_F20F2C(read_xmm64s(r1), r2); -} +pub unsafe fn instr_F20F2C_reg(mut r1: i32, mut r2: i32) { instr_F20F2C(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F2C_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F2C_mem(mut addr: i32, mut r: i32) { instr_F20F2C(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F2C(source: f32, mut r: i32) -> () { +pub unsafe fn instr_F30F2C(source: f32, mut r: i32) { let result = source.trunc(); write_reg32(r, sse_convert_f32_to_i32(source)); } #[no_mangle] -pub unsafe fn instr_F30F2C_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F2C_mem(mut addr: i32, mut r: i32) { instr_F30F2C(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_F30F2C_reg(mut r1: i32, mut r2: i32) -> () { - instr_F30F2C(read_xmm_f32(r1), r2); -} +pub unsafe fn instr_F30F2C_reg(mut r1: i32, mut r2: i32) { instr_F30F2C(read_xmm_f32(r1), r2); } pub unsafe fn instr_0F2E(source: f32, r: i32) { // ucomiss xmm1, xmm2/m32 @@ -1067,9 +1053,9 @@ pub unsafe fn instr_0F2E(source: f32, r: i32) { } } #[no_mangle] -pub unsafe fn instr_0F2E_reg(r1: i32, r2: i32) -> () { instr_0F2E(read_xmm_f32(r1), r2) } +pub unsafe fn instr_0F2E_reg(r1: i32, r2: i32) { instr_0F2E(read_xmm_f32(r1), r2) } #[no_mangle] -pub unsafe fn instr_0F2E_mem(addr: i32, r: i32) -> () { +pub unsafe fn instr_0F2E_mem(addr: i32, r: i32) { instr_0F2E(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } @@ -1120,9 +1106,9 @@ pub unsafe fn instr_0F2F(source: f32, r: i32) { } } #[no_mangle] -pub unsafe fn instr_0F2F_reg(r1: i32, r2: i32) -> () { instr_0F2F(read_xmm_f32(r1), r2) } +pub unsafe fn instr_0F2F_reg(r1: i32, r2: i32) { instr_0F2F(read_xmm_f32(r1), r2) } #[no_mangle] -pub unsafe fn instr_0F2F_mem(addr: i32, r: i32) -> () { +pub unsafe fn instr_0F2F_mem(addr: i32, r: i32) { instr_0F2F(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } @@ -1154,7 +1140,7 @@ pub unsafe fn instr_660F2F_mem(addr: i32, r: i32) { } #[no_mangle] -pub unsafe fn instr_0F30() -> () { +pub unsafe fn instr_0F30() { // wrmsr - write maschine specific register if 0 != *cpl { trigger_gp_non_raising(0i32); @@ -1216,7 +1202,7 @@ pub unsafe fn instr_0F30() -> () { }; } #[no_mangle] -pub unsafe fn instr_0F31() -> () { +pub unsafe fn instr_0F31() { // rdtsc - read timestamp counter if 0 == *cpl || 0 == *cr.offset(4isize) & CR4_TSD { let mut tsc: u64 = read_tsc(); @@ -1235,7 +1221,7 @@ pub unsafe fn instr_0F31() -> () { }; } #[no_mangle] -pub unsafe fn instr_0F32() -> () { +pub unsafe fn instr_0F32() { // rdmsr - read maschine specific register if 0 != *cpl { trigger_gp_non_raising(0i32); @@ -1300,12 +1286,12 @@ pub unsafe fn instr_0F32() -> () { }; } #[no_mangle] -pub unsafe fn instr_0F33() -> () { +pub unsafe fn instr_0F33() { // rdpmc undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0F34() -> () { +pub unsafe fn instr_0F34() { // sysenter let mut seg: i32 = *sysenter_cs & 65532i32; if !*protected_mode || seg == 0i32 { @@ -1332,7 +1318,7 @@ pub unsafe fn instr_0F34() -> () { }; } #[no_mangle] -pub unsafe fn instr_0F35() -> () { +pub unsafe fn instr_0F35() { // sysexit let mut seg: i32 = *sysenter_cs & 65532i32; if !*protected_mode || 0 != *cpl as i32 || seg == 0i32 { @@ -1358,350 +1344,350 @@ pub unsafe fn instr_0F35() -> () { }; } #[no_mangle] -pub unsafe fn instr_0F36() -> () { undefined_instruction(); } +pub unsafe fn instr_0F36() { undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0F37() -> () { +pub unsafe fn instr_0F37() { // getsec undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0F38() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F38() { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_0F39() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F39() { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_0F3A() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F3A() { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_0F3B() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F3B() { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_0F3C() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F3C() { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_0F3D() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F3D() { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_0F3E() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F3E() { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_0F3F() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F3F() { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr16_0F40_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F40_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_o(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F40_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F40_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); cmovcc16(test_o(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F40_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F40_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_o(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F40_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F40_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); cmovcc32(test_o(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F41_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F41_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_o(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F41_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F41_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); cmovcc16(!test_o(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F41_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F41_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_o(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F41_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F41_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); cmovcc32(!test_o(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F42_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F42_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_b(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F42_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F42_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); cmovcc16(test_b(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F42_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F42_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_b(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F42_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F42_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); cmovcc32(test_b(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F43_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F43_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_b(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F43_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F43_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); cmovcc16(!test_b(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F43_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F43_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_b(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F43_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F43_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); cmovcc32(!test_b(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F44_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F44_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_z(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F44_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F44_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); cmovcc16(test_z(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F44_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F44_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_z(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F44_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F44_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); cmovcc32(test_z(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F45_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F45_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_z(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F45_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F45_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); cmovcc16(!test_z(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F45_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F45_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_z(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F45_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F45_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); cmovcc32(!test_z(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F46_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F46_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_be(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F46_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F46_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); cmovcc16(test_be(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F46_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F46_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_be(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F46_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F46_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); cmovcc32(test_be(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F47_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F47_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_be(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F47_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F47_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); cmovcc16(!test_be(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F47_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F47_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_be(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F47_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F47_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); cmovcc32(!test_be(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F48_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F48_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_s(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F48_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F48_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); cmovcc16(test_s(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F48_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F48_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_s(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F48_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F48_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); cmovcc32(test_s(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F49_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F49_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_s(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F49_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F49_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); cmovcc16(!test_s(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F49_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F49_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_s(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F49_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F49_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); cmovcc32(!test_s(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4A_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_p(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4A_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4A_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); cmovcc16(test_p(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4A_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_p(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4A_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4A_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); cmovcc32(test_p(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4B_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_p(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4B_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); cmovcc16(!test_p(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4B_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_p(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4B_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4B_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); cmovcc32(!test_p(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4C_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4C_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_l(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4C_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4C_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); cmovcc16(test_l(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4C_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4C_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_l(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4C_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4C_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); cmovcc32(test_l(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4D_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4D_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_l(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4D_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4D_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); cmovcc16(!test_l(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4D_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4D_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_l(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4D_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4D_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); cmovcc32(!test_l(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4E_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_le(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4E_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4E_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); cmovcc16(test_le(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4E_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_le(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4E_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4E_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); cmovcc32(test_le(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4F_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_le(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4F_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0F4F_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); cmovcc16(!test_le(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4F_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_le(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4F_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0F4F_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); cmovcc32(!test_le(), ____0, r); } #[no_mangle] -pub unsafe fn instr_0F50_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_0F50_reg(mut r1: i32, mut r2: i32) { // movmskps r, xmm let mut source: reg128 = read_xmm128s(r1); let mut data: i32 = (source.u32_0[0usize] >> 31i32 @@ -1711,9 +1697,9 @@ pub unsafe fn instr_0F50_reg(mut r1: i32, mut r2: i32) -> () { write_reg32(r2, data); } #[no_mangle] -pub unsafe fn instr_0F50_mem(mut addr: i32, mut r1: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F50_mem(mut addr: i32, mut r1: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F50_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F50_reg(mut r1: i32, mut r2: i32) { // movmskpd r, xmm let mut source: reg128 = read_xmm128s(r1); let mut data: i32 = @@ -1721,113 +1707,105 @@ pub unsafe fn instr_660F50_reg(mut r1: i32, mut r2: i32) -> () { write_reg32(r2, data); } #[no_mangle] -pub unsafe fn instr_660F50_mem(mut addr: i32, mut r1: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F50_mem(mut addr: i32, mut r1: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F54(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F54(mut source: reg128, mut r: i32) { // andps xmm, xmm/mem128 // XXX: Aligned access or #gp pand_r128(source, r); } #[no_mangle] -pub unsafe fn instr_0F54_reg(mut r1: i32, mut r2: i32) -> () { instr_0F54(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F54_reg(mut r1: i32, mut r2: i32) { instr_0F54(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F54_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F54_mem(mut addr: i32, mut r: i32) { instr_0F54(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F54(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F54(mut source: reg128, mut r: i32) { // andpd xmm, xmm/mem128 // XXX: Aligned access or #gp pand_r128(source, r); } #[no_mangle] -pub unsafe fn instr_660F54_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F54(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F54_reg(mut r1: i32, mut r2: i32) { instr_660F54(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F54_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F54_mem(mut addr: i32, mut r: i32) { instr_660F54(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F55(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F55(mut source: reg128, mut r: i32) { // andnps xmm, xmm/mem128 // XXX: Aligned access or #gp pandn_r128(source, r); } #[no_mangle] -pub unsafe fn instr_0F55_reg(mut r1: i32, mut r2: i32) -> () { instr_0F55(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F55_reg(mut r1: i32, mut r2: i32) { instr_0F55(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F55_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F55_mem(mut addr: i32, mut r: i32) { instr_0F55(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F55(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F55(mut source: reg128, mut r: i32) { // andnpd xmm, xmm/mem128 // XXX: Aligned access or #gp pandn_r128(source, r); } #[no_mangle] -pub unsafe fn instr_660F55_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F55(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F55_reg(mut r1: i32, mut r2: i32) { instr_660F55(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F55_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F55_mem(mut addr: i32, mut r: i32) { instr_660F55(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F56(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F56(mut source: reg128, mut r: i32) { // orps xmm, xmm/mem128 // XXX: Aligned access or #gp por_r128(source, r); } #[no_mangle] -pub unsafe fn instr_0F56_reg(mut r1: i32, mut r2: i32) -> () { instr_0F56(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F56_reg(mut r1: i32, mut r2: i32) { instr_0F56(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F56_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F56_mem(mut addr: i32, mut r: i32) { instr_0F56(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F56(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F56(mut source: reg128, mut r: i32) { // orpd xmm, xmm/mem128 // XXX: Aligned access or #gp por_r128(source, r); } #[no_mangle] -pub unsafe fn instr_660F56_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F56(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F56_reg(mut r1: i32, mut r2: i32) { instr_660F56(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F56_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F56_mem(mut addr: i32, mut r: i32) { instr_660F56(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F57(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F57(mut source: reg128, mut r: i32) { // xorps xmm, xmm/mem128 // XXX: Aligned access or #gp pxor_r128(source, r); } #[no_mangle] -pub unsafe fn instr_0F57_reg(mut r1: i32, mut r2: i32) -> () { instr_0F57(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F57_reg(mut r1: i32, mut r2: i32) { instr_0F57(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F57_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F57_mem(mut addr: i32, mut r: i32) { instr_0F57(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F57(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F57(mut source: reg128, mut r: i32) { // xorpd xmm, xmm/mem128 // XXX: Aligned access or #gp pxor_r128(source, r); } #[no_mangle] -pub unsafe fn instr_660F57_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F57(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F57_reg(mut r1: i32, mut r2: i32) { instr_660F57(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F57_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F57_mem(mut addr: i32, mut r: i32) { instr_660F57(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F60(mut source: i32, mut r: i32) -> () { +pub unsafe fn instr_0F60(mut source: i32, mut r: i32) { // punpcklbw mm, mm/m32 let mut destination: reg64 = read_mmx64s(r); let mut byte0: i32 = destination.u8_0[0usize] as i32; @@ -1843,13 +1821,13 @@ pub unsafe fn instr_0F60(mut source: i32, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe fn instr_0F60_reg(mut r1: i32, mut r2: i32) -> () { instr_0F60(read_mmx32s(r1), r2); } +pub unsafe fn instr_0F60_reg(mut r1: i32, mut r2: i32) { instr_0F60(read_mmx32s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F60_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F60_mem(mut addr: i32, mut r: i32) { instr_0F60(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F60(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_660F60(mut source: reg64, mut r: i32) { // punpcklbw xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg64 = read_xmm64s(r); @@ -1874,15 +1852,13 @@ pub unsafe fn instr_660F60(mut source: reg64, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_660F60_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F60(read_xmm64s(r1), r2); -} +pub unsafe fn instr_660F60_reg(mut r1: i32, mut r2: i32) { instr_660F60(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F60_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F60_mem(mut addr: i32, mut r: i32) { instr_660F60(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F61(mut source: i32, mut r: i32) -> () { +pub unsafe fn instr_0F61(mut source: i32, mut r: i32) { // punpcklwd mm, mm/m32 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = destination.u16_0[0usize] as i32; @@ -1894,13 +1870,13 @@ pub unsafe fn instr_0F61(mut source: i32, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe fn instr_0F61_reg(mut r1: i32, mut r2: i32) -> () { instr_0F61(read_mmx32s(r1), r2); } +pub unsafe fn instr_0F61_reg(mut r1: i32, mut r2: i32) { instr_0F61(read_mmx32s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F61_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F61_mem(mut addr: i32, mut r: i32) { instr_0F61(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F61(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_660F61(mut source: reg64, mut r: i32) { // punpcklwd xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg64 = read_xmm64s(r); @@ -1913,27 +1889,25 @@ pub unsafe fn instr_660F61(mut source: reg64, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_660F61_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F61(read_xmm64s(r1), r2); -} +pub unsafe fn instr_660F61_reg(mut r1: i32, mut r2: i32) { instr_660F61(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F61_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F61_mem(mut addr: i32, mut r: i32) { instr_660F61(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F62(mut source: i32, mut r: i32) -> () { +pub unsafe fn instr_0F62(mut source: i32, mut r: i32) { // punpckldq mm, mm/m32 let mut destination: reg64 = read_mmx64s(r); write_mmx64(r, destination.u32_0[0usize] as i32, source); } #[no_mangle] -pub unsafe fn instr_0F62_reg(mut r1: i32, mut r2: i32) -> () { instr_0F62(read_mmx32s(r1), r2); } +pub unsafe fn instr_0F62_reg(mut r1: i32, mut r2: i32) { instr_0F62(read_mmx32s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F62_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F62_mem(mut addr: i32, mut r: i32) { instr_0F62(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F62(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F62(mut source: reg128, mut r: i32) { // punpckldq xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -1946,15 +1920,13 @@ pub unsafe fn instr_660F62(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_660F62_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F62(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F62_reg(mut r1: i32, mut r2: i32) { instr_660F62(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F62_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F62_mem(mut addr: i32, mut r: i32) { instr_660F62(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F63(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F63(mut source: reg64, mut r: i32) { // packsswb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut low: i32 = saturate_sw_to_sb(destination.u16_0[0usize] as i32) @@ -1968,13 +1940,13 @@ pub unsafe fn instr_0F63(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe fn instr_0F63_reg(mut r1: i32, mut r2: i32) -> () { instr_0F63(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F63_reg(mut r1: i32, mut r2: i32) { instr_0F63(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F63_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F63_mem(mut addr: i32, mut r: i32) { instr_0F63(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F63(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F63(mut source: reg128, mut r: i32) { // packsswb xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -1997,15 +1969,13 @@ pub unsafe fn instr_660F63(mut source: reg128, mut r: i32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn instr_660F63_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F63(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F63_reg(mut r1: i32, mut r2: i32) { instr_660F63(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F63_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F63_mem(mut addr: i32, mut r: i32) { instr_660F63(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F64(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F64(mut source: reg64, mut r: i32) { // pcmpgtb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -2025,13 +1995,13 @@ pub unsafe fn instr_0F64(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe fn instr_0F64_reg(mut r1: i32, mut r2: i32) -> () { instr_0F64(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F64_reg(mut r1: i32, mut r2: i32) { instr_0F64(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F64_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F64_mem(mut addr: i32, mut r: i32) { instr_0F64(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F64(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F64(mut source: reg128, mut r: i32) { // pcmpgtb xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -2052,15 +2022,13 @@ pub unsafe fn instr_660F64(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F64_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F64(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F64_reg(mut r1: i32, mut r2: i32) { instr_660F64(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F64_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F64_mem(mut addr: i32, mut r: i32) { instr_660F64(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F65(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F65(mut source: reg64, mut r: i32) { // pcmpgtw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = if destination.i16_0[0usize] as i32 > source.i16_0[0usize] as i32 { @@ -2092,13 +2060,13 @@ pub unsafe fn instr_0F65(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe fn instr_0F65_reg(mut r1: i32, mut r2: i32) -> () { instr_0F65(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F65_reg(mut r1: i32, mut r2: i32) { instr_0F65(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F65_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F65_mem(mut addr: i32, mut r: i32) { instr_0F65(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F65(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F65(mut source: reg128, mut r: i32) { // pcmpgtw xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -2119,15 +2087,13 @@ pub unsafe fn instr_660F65(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F65_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F65(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F65_reg(mut r1: i32, mut r2: i32) { instr_660F65(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F65_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F65_mem(mut addr: i32, mut r: i32) { instr_660F65(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F66(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F66(mut source: reg64, mut r: i32) { // pcmpgtd mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut low: i32 = if destination.i32_0[0usize] > source.i32_0[0usize] { @@ -2145,13 +2111,13 @@ pub unsafe fn instr_0F66(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe fn instr_0F66_reg(mut r1: i32, mut r2: i32) -> () { instr_0F66(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F66_reg(mut r1: i32, mut r2: i32) { instr_0F66(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F66_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F66_mem(mut addr: i32, mut r: i32) { instr_0F66(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F66(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F66(mut source: reg128, mut r: i32) { // pcmpgtd xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -2184,15 +2150,13 @@ pub unsafe fn instr_660F66(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_660F66_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F66(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F66_reg(mut r1: i32, mut r2: i32) { instr_660F66(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F66_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F66_mem(mut addr: i32, mut r: i32) { instr_660F66(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F67(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F67(mut source: reg64, mut r: i32) { // packuswb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut low: u32 = saturate_sw_to_ub(destination.u16_0[0usize] as u32) @@ -2206,13 +2170,13 @@ pub unsafe fn instr_0F67(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low as i32, high as i32); } #[no_mangle] -pub unsafe fn instr_0F67_reg(mut r1: i32, mut r2: i32) -> () { instr_0F67(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F67_reg(mut r1: i32, mut r2: i32) { instr_0F67(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F67_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F67_mem(mut addr: i32, mut r: i32) { instr_0F67(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F67(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F67(mut source: reg128, mut r: i32) { // packuswb xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -2226,15 +2190,13 @@ pub unsafe fn instr_660F67(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F67_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F67(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F67_reg(mut r1: i32, mut r2: i32) { instr_660F67(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F67_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F67_mem(mut addr: i32, mut r: i32) { instr_660F67(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F68(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F68(mut source: reg64, mut r: i32) { // punpckhbw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut byte0: i32 = destination.u8_0[4usize] as i32; @@ -2250,13 +2212,13 @@ pub unsafe fn instr_0F68(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe fn instr_0F68_reg(mut r1: i32, mut r2: i32) -> () { instr_0F68(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F68_reg(mut r1: i32, mut r2: i32) { instr_0F68(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F68_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F68_mem(mut addr: i32, mut r: i32) { instr_0F68(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F68(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F68(mut source: reg128, mut r: i32) { // punpckhbw xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -2281,15 +2243,13 @@ pub unsafe fn instr_660F68(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_660F68_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F68(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F68_reg(mut r1: i32, mut r2: i32) { instr_660F68(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F68_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F68_mem(mut addr: i32, mut r: i32) { instr_660F68(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F69(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F69(mut source: reg64, mut r: i32) { // punpckhwd mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = destination.u16_0[2usize] as i32; @@ -2301,13 +2261,13 @@ pub unsafe fn instr_0F69(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe fn instr_0F69_reg(mut r1: i32, mut r2: i32) -> () { instr_0F69(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F69_reg(mut r1: i32, mut r2: i32) { instr_0F69(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F69_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F69_mem(mut addr: i32, mut r: i32) { instr_0F69(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F69(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F69(mut source: reg128, mut r: i32) { // punpckhwd xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -2318,15 +2278,13 @@ pub unsafe fn instr_660F69(mut source: reg128, mut r: i32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn instr_660F69_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F69(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F69_reg(mut r1: i32, mut r2: i32) { instr_660F69(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F69_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F69_mem(mut addr: i32, mut r: i32) { instr_660F69(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F6A(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F6A(mut source: reg64, mut r: i32) { // punpckhdq mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); write_mmx64( @@ -2336,13 +2294,13 @@ pub unsafe fn instr_0F6A(mut source: reg64, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_0F6A_reg(mut r1: i32, mut r2: i32) -> () { instr_0F6A(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F6A_reg(mut r1: i32, mut r2: i32) { instr_0F6A(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F6A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F6A_mem(mut addr: i32, mut r: i32) { instr_0F6A(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F6A(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F6A(mut source: reg128, mut r: i32) { // punpckhdq xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -2355,15 +2313,13 @@ pub unsafe fn instr_660F6A(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_660F6A_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F6A(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F6A_reg(mut r1: i32, mut r2: i32) { instr_660F6A(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F6A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F6A_mem(mut addr: i32, mut r: i32) { instr_660F6A(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F6B(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F6B(mut source: reg64, mut r: i32) { // packssdw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut low: i32 = (saturate_sd_to_sw(destination.u32_0[0usize]) @@ -2373,13 +2329,13 @@ pub unsafe fn instr_0F6B(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe fn instr_0F6B_reg(mut r1: i32, mut r2: i32) -> () { instr_0F6B(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F6B_reg(mut r1: i32, mut r2: i32) { instr_0F6B(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F6B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F6B_mem(mut addr: i32, mut r: i32) { instr_0F6B(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F6B(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F6B(mut source: reg128, mut r: i32) { // packssdw xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -2394,19 +2350,17 @@ pub unsafe fn instr_660F6B(mut source: reg128, mut r: i32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn instr_660F6B_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F6B(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F6B_reg(mut r1: i32, mut r2: i32) { instr_660F6B(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F6B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F6B_mem(mut addr: i32, mut r: i32) { instr_660F6B(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F6C_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F6C_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F6C_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F6C_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F6C(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F6C(mut source: reg128, mut r: i32) { // punpcklqdq xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -2419,19 +2373,17 @@ pub unsafe fn instr_660F6C(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_660F6C_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F6C(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F6C_reg(mut r1: i32, mut r2: i32) { instr_660F6C(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F6C_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F6C_mem(mut addr: i32, mut r: i32) { instr_660F6C(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F6D_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F6D_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F6D_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F6D_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F6D(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F6D(mut source: reg128, mut r: i32) { // punpckhqdq xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -2444,76 +2396,70 @@ pub unsafe fn instr_660F6D(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_660F6D_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F6D(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F6D_reg(mut r1: i32, mut r2: i32) { instr_660F6D(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F6D_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F6D_mem(mut addr: i32, mut r: i32) { instr_660F6D(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F6E(mut source: i32, mut r: i32) -> () { +pub unsafe fn instr_0F6E(mut source: i32, mut r: i32) { // movd mm, r/m32 write_mmx64(r, source, 0i32); } #[no_mangle] -pub unsafe fn instr_0F6E_reg(mut r1: i32, mut r2: i32) -> () { instr_0F6E(read_reg32(r1), r2); } +pub unsafe fn instr_0F6E_reg(mut r1: i32, mut r2: i32) { instr_0F6E(read_reg32(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F6E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F6E_mem(mut addr: i32, mut r: i32) { instr_0F6E(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F6E(mut source: i32, mut r: i32) -> () { +pub unsafe fn instr_660F6E(mut source: i32, mut r: i32) { // movd mm, r/m32 write_xmm128(r, source, 0i32, 0i32, 0i32); } #[no_mangle] -pub unsafe fn instr_660F6E_reg(mut r1: i32, mut r2: i32) -> () { instr_660F6E(read_reg32(r1), r2); } +pub unsafe fn instr_660F6E_reg(mut r1: i32, mut r2: i32) { instr_660F6E(read_reg32(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F6E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F6E_mem(mut addr: i32, mut r: i32) { instr_660F6E(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F6F(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F6F(mut source: reg64, mut r: i32) { // movq mm, mm/m64 write_mmx64(r, source.u32_0[0usize] as i32, source.u32_0[1usize] as i32); } #[no_mangle] -pub unsafe fn instr_0F6F_reg(mut r1: i32, mut r2: i32) -> () { instr_0F6F(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F6F_reg(mut r1: i32, mut r2: i32) { instr_0F6F(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F6F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F6F_mem(mut addr: i32, mut r: i32) { instr_0F6F(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F6F(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F6F(mut source: reg128, mut r: i32) { // movdqa xmm, xmm/mem128 // XXX: Aligned access or #gp // XXX: Aligned read or #gp mov_rm_r128(source, r); } #[no_mangle] -pub unsafe fn instr_660F6F_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F6F(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F6F_reg(mut r1: i32, mut r2: i32) { instr_660F6F(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F6F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F6F_mem(mut addr: i32, mut r: i32) { instr_660F6F(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F6F(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_F30F6F(mut source: reg128, mut r: i32) { // movdqu xmm, xmm/m128 mov_rm_r128(source, r); } #[no_mangle] -pub unsafe fn instr_F30F6F_reg(mut r1: i32, mut r2: i32) -> () { - instr_F30F6F(read_xmm128s(r1), r2); -} +pub unsafe fn instr_F30F6F_reg(mut r1: i32, mut r2: i32) { instr_F30F6F(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F6F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F6F_mem(mut addr: i32, mut r: i32) { instr_F30F6F(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F70(mut source: reg64, mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0F70(mut source: reg64, mut r: i32, mut imm8: i32) { // pshufw mm1, mm2/m64, imm8 let mut word0_shift: i32 = imm8 & 3i32; let mut word0: u32 = source.u32_0[(word0_shift >> 1i32) as usize] @@ -2534,15 +2480,15 @@ pub unsafe fn instr_0F70(mut source: reg64, mut r: i32, mut imm8: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe fn instr_0F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { +pub unsafe fn instr_0F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) { instr_0F70(read_mmx64s(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_0F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr_0F70_mem(mut addr: i32, mut r: i32, mut imm: i32) { instr_0F70(return_on_pagefault!(safe_read64s(addr)), r, imm); } #[no_mangle] -pub unsafe fn instr_660F70(mut source: reg128, mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660F70(mut source: reg128, mut r: i32, mut imm8: i32) { // pshufd xmm, xmm/mem128 // XXX: Aligned access or #gp write_xmm128( @@ -2554,16 +2500,16 @@ pub unsafe fn instr_660F70(mut source: reg128, mut r: i32, mut imm8: i32) -> () ); } #[no_mangle] -pub unsafe fn instr_660F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { +pub unsafe fn instr_660F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) { instr_660F70(read_xmm128s(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_660F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr_660F70_mem(mut addr: i32, mut r: i32, mut imm: i32) { instr_660F70(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] -pub unsafe fn instr_F20F70(mut source: reg128, mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_F20F70(mut source: reg128, mut r: i32, mut imm8: i32) { // pshuflw xmm, xmm/m128, imm8 // XXX: Aligned access or #gp write_xmm128( @@ -2577,15 +2523,15 @@ pub unsafe fn instr_F20F70(mut source: reg128, mut r: i32, mut imm8: i32) -> () ); } #[no_mangle] -pub unsafe fn instr_F20F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { +pub unsafe fn instr_F20F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) { instr_F20F70(read_xmm128s(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_F20F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr_F20F70_mem(mut addr: i32, mut r: i32, mut imm: i32) { instr_F20F70(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] -pub unsafe fn instr_F30F70(mut source: reg128, mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_F30F70(mut source: reg128, mut r: i32, mut imm8: i32) { // pshufhw xmm, xmm/m128, imm8 // XXX: Aligned access or #gp write_xmm128( @@ -2599,126 +2545,126 @@ pub unsafe fn instr_F30F70(mut source: reg128, mut r: i32, mut imm8: i32) -> () ); } #[no_mangle] -pub unsafe fn instr_F30F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { +pub unsafe fn instr_F30F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) { instr_F30F70(read_xmm128s(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_F30F70_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr_F30F70_mem(mut addr: i32, mut r: i32, mut imm: i32) { instr_F30F70(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] -pub unsafe fn instr_0F71_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F71_2_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F71_4_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F71_4_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F71_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F71_6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F71_2_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0F71_2_reg(mut r: i32, mut imm8: i32) { // psrlw mm, imm8 psrlw_r64(r, imm8 as u32); } #[no_mangle] -pub unsafe fn instr_0F71_4_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0F71_4_reg(mut r: i32, mut imm8: i32) { // psraw mm, imm8 psraw_r64(r, imm8 as u32); } #[no_mangle] -pub unsafe fn instr_0F71_6_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0F71_6_reg(mut r: i32, mut imm8: i32) { // psllw mm, imm8 psllw_r64(r, imm8 as u32); } #[no_mangle] -pub unsafe fn instr_660F71_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F71_2_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F71_4_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F71_4_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F71_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F71_6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F71_2_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660F71_2_reg(mut r: i32, mut imm8: i32) { // psrlw xmm, imm8 psrlw_r128(r, imm8 as u32); } #[no_mangle] -pub unsafe fn instr_660F71_4_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660F71_4_reg(mut r: i32, mut imm8: i32) { // psraw xmm, imm8 psraw_r128(r, imm8 as u32); } #[no_mangle] -pub unsafe fn instr_660F71_6_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660F71_6_reg(mut r: i32, mut imm8: i32) { // psllw xmm, imm8 psllw_r128(r, imm8 as u32); } #[no_mangle] -pub unsafe fn instr_0F72_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F72_2_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F72_4_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F72_4_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F72_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F72_6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F72_2_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0F72_2_reg(mut r: i32, mut imm8: i32) { // psrld mm, imm8 psrld_r64(r, imm8 as u32); } #[no_mangle] -pub unsafe fn instr_0F72_4_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0F72_4_reg(mut r: i32, mut imm8: i32) { // psrad mm, imm8 psrad_r64(r, imm8 as u32); } #[no_mangle] -pub unsafe fn instr_0F72_6_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0F72_6_reg(mut r: i32, mut imm8: i32) { // pslld mm, imm8 pslld_r64(r, imm8 as u32); } #[no_mangle] -pub unsafe fn instr_660F72_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F72_2_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F72_4_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F72_4_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F72_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F72_6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F72_2_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660F72_2_reg(mut r: i32, mut imm8: i32) { // psrld xmm, imm8 psrld_r128(r, imm8 as u32); } #[no_mangle] -pub unsafe fn instr_660F72_4_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660F72_4_reg(mut r: i32, mut imm8: i32) { // psrad xmm, imm8 psrad_r128(r, imm8 as u32); } #[no_mangle] -pub unsafe fn instr_660F72_6_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660F72_6_reg(mut r: i32, mut imm8: i32) { // pslld xmm, imm8 pslld_r128(r, imm8 as u32); } #[no_mangle] -pub unsafe fn instr_0F73_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F73_2_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F73_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0F73_6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F73_2_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0F73_2_reg(mut r: i32, mut imm8: i32) { // psrlq mm, imm8 psrlq_r64(r, imm8 as u32); } #[no_mangle] -pub unsafe fn instr_0F73_6_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0F73_6_reg(mut r: i32, mut imm8: i32) { // psllq mm, imm8 psllq_r64(r, imm8 as u32); } #[no_mangle] -pub unsafe fn instr_660F73_2_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F73_2_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F73_3_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F73_3_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F73_6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F73_6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F73_7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660F73_7_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F73_2_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660F73_2_reg(mut r: i32, mut imm8: i32) { // psrlq xmm, imm8 psrlq_r128(r, imm8 as u32); } #[no_mangle] -pub unsafe fn instr_660F73_3_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660F73_3_reg(mut r: i32, mut imm8: i32) { // psrldq xmm, imm8 let mut destination: reg128 = read_xmm128s(r); if imm8 == 0i32 { @@ -2743,12 +2689,12 @@ pub unsafe fn instr_660F73_3_reg(mut r: i32, mut imm8: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_660F73_6_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660F73_6_reg(mut r: i32, mut imm8: i32) { // psllq xmm, imm8 psllq_r128(r, imm8 as u32); } #[no_mangle] -pub unsafe fn instr_660F73_7_reg(mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660F73_7_reg(mut r: i32, mut imm8: i32) { // pslldq xmm, imm8 let mut destination: reg128 = read_xmm128s(r); if imm8 == 0i32 { @@ -2773,7 +2719,7 @@ pub unsafe fn instr_660F73_7_reg(mut r: i32, mut imm8: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_0F74(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F74(mut source: reg64, mut r: i32) { // pcmpeqb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -2793,13 +2739,13 @@ pub unsafe fn instr_0F74(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe fn instr_0F74_reg(mut r1: i32, mut r2: i32) -> () { instr_0F74(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F74_reg(mut r1: i32, mut r2: i32) { instr_0F74(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F74_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F74_mem(mut addr: i32, mut r: i32) { instr_0F74(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F74(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F74(mut source: reg128, mut r: i32) { // pcmpeqb xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -2818,15 +2764,13 @@ pub unsafe fn instr_660F74(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F74_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F74(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F74_reg(mut r1: i32, mut r2: i32) { instr_660F74(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F74_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F74_mem(mut addr: i32, mut r: i32) { instr_660F74(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F75(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F75(mut source: reg64, mut r: i32) { // pcmpeqw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = if destination.u16_0[0usize] as i32 == source.u16_0[0usize] as i32 { @@ -2858,13 +2802,13 @@ pub unsafe fn instr_0F75(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe fn instr_0F75_reg(mut r1: i32, mut r2: i32) -> () { instr_0F75(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F75_reg(mut r1: i32, mut r2: i32) { instr_0F75(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F75_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F75_mem(mut addr: i32, mut r: i32) { instr_0F75(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F75(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F75(mut source: reg128, mut r: i32) { // pcmpeqw xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -2883,15 +2827,13 @@ pub unsafe fn instr_660F75(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F75_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F75(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F75_reg(mut r1: i32, mut r2: i32) { instr_660F75(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F75_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F75_mem(mut addr: i32, mut r: i32) { instr_660F75(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F76(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F76(mut source: reg64, mut r: i32) { // pcmpeqd mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut low: i32 = if destination.u32_0[0usize] == source.u32_0[0usize] { @@ -2909,13 +2851,13 @@ pub unsafe fn instr_0F76(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe fn instr_0F76_reg(mut r1: i32, mut r2: i32) -> () { instr_0F76(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F76_reg(mut r1: i32, mut r2: i32) { instr_0F76(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F76_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F76_mem(mut addr: i32, mut r: i32) { instr_0F76(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F76(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F76(mut source: reg128, mut r: i32) { // pcmpeqd xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -2948,30 +2890,28 @@ pub unsafe fn instr_660F76(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_660F76_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F76(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F76_reg(mut r1: i32, mut r2: i32) { instr_660F76(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F76_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F76_mem(mut addr: i32, mut r: i32) { instr_660F76(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F77() -> () { +pub unsafe fn instr_0F77() { // emms fpu_set_tag_word(65535i32); } #[no_mangle] -pub unsafe fn instr_0F78() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F78() { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_0F79() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F79() { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_0F7A() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F7A() { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_0F7B() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F7B() { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_0F7C() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F7C() { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_0F7D() -> () { unimplemented_sse(); } +pub unsafe fn instr_0F7D() { unimplemented_sse(); } #[no_mangle] pub unsafe fn instr_0F7E(mut r: i32) -> i32 { // movd r/m32, mm @@ -2979,9 +2919,9 @@ pub unsafe fn instr_0F7E(mut r: i32) -> i32 { return data.u32_0[0usize] as i32; } #[no_mangle] -pub unsafe fn instr_0F7E_reg(mut r1: i32, mut r2: i32) -> () { write_reg32(r1, instr_0F7E(r2)); } +pub unsafe fn instr_0F7E_reg(mut r1: i32, mut r2: i32) { write_reg32(r1, instr_0F7E(r2)); } #[no_mangle] -pub unsafe fn instr_0F7E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F7E_mem(mut addr: i32, mut r: i32) { return_on_pagefault!(safe_write32(addr, instr_0F7E(r))); } #[no_mangle] @@ -2991,15 +2931,13 @@ pub unsafe fn instr_660F7E(mut r: i32) -> i32 { return data.u32_0[0usize] as i32; } #[no_mangle] -pub unsafe fn instr_660F7E_reg(mut r1: i32, mut r2: i32) -> () { - write_reg32(r1, instr_660F7E(r2)); -} +pub unsafe fn instr_660F7E_reg(mut r1: i32, mut r2: i32) { write_reg32(r1, instr_660F7E(r2)); } #[no_mangle] -pub unsafe fn instr_660F7E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F7E_mem(mut addr: i32, mut r: i32) { return_on_pagefault!(safe_write32(addr, instr_660F7E(r))); } #[no_mangle] -pub unsafe fn instr_F30F7E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F7E_mem(mut addr: i32, mut r: i32) { // movq xmm, xmm/mem64 let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); write_xmm128( @@ -3011,7 +2949,7 @@ pub unsafe fn instr_F30F7E_mem(mut addr: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_F30F7E_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F30F7E_reg(mut r1: i32, mut r2: i32) { // movq xmm, xmm/mem64 let mut data: reg64 = read_xmm64s(r1); write_xmm128( @@ -3023,176 +2961,176 @@ pub unsafe fn instr_F30F7E_reg(mut r1: i32, mut r2: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_0F7F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F7F_mem(mut addr: i32, mut r: i32) { // movq mm/m64, mm mov_r_m64(addr, r); } #[no_mangle] -pub unsafe fn instr_0F7F_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_0F7F_reg(mut r1: i32, mut r2: i32) { // movq mm/m64, mm let mut data: reg64 = read_mmx64s(r2); write_mmx64(r1, data.u32_0[0usize] as i32, data.u32_0[1usize] as i32); } #[no_mangle] -pub unsafe fn instr_660F7F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F7F_mem(mut addr: i32, mut r: i32) { // movdqa xmm/m128, xmm // XXX: Aligned write or #gp mov_r_m128(addr, r); } #[no_mangle] -pub unsafe fn instr_660F7F_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660F7F_reg(mut r1: i32, mut r2: i32) { // movdqa xmm/m128, xmm // XXX: Aligned access or #gp mov_r_r128(r1, r2); } #[no_mangle] -pub unsafe fn instr_F30F7F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F7F_mem(mut addr: i32, mut r: i32) { // movdqu xmm/m128, xmm mov_r_m128(addr, r); } #[no_mangle] -pub unsafe fn instr_F30F7F_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F30F7F_reg(mut r1: i32, mut r2: i32) { // movdqu xmm/m128, xmm mov_r_r128(r1, r2); } #[no_mangle] -pub unsafe fn instr16_0F80(mut imm: i32) -> () { jmpcc16(test_o(), imm); } +pub unsafe fn instr16_0F80(mut imm: i32) { jmpcc16(test_o(), imm); } #[no_mangle] -pub unsafe fn instr32_0F80(mut imm: i32) -> () { jmpcc32(test_o(), imm); } +pub unsafe fn instr32_0F80(mut imm: i32) { jmpcc32(test_o(), imm); } #[no_mangle] -pub unsafe fn instr16_0F81(mut imm: i32) -> () { jmpcc16(!test_o(), imm); } +pub unsafe fn instr16_0F81(mut imm: i32) { jmpcc16(!test_o(), imm); } #[no_mangle] -pub unsafe fn instr32_0F81(mut imm: i32) -> () { jmpcc32(!test_o(), imm); } +pub unsafe fn instr32_0F81(mut imm: i32) { jmpcc32(!test_o(), imm); } #[no_mangle] -pub unsafe fn instr16_0F82(mut imm: i32) -> () { jmpcc16(test_b(), imm); } +pub unsafe fn instr16_0F82(mut imm: i32) { jmpcc16(test_b(), imm); } #[no_mangle] -pub unsafe fn instr32_0F82(mut imm: i32) -> () { jmpcc32(test_b(), imm); } +pub unsafe fn instr32_0F82(mut imm: i32) { jmpcc32(test_b(), imm); } #[no_mangle] -pub unsafe fn instr16_0F83(mut imm: i32) -> () { jmpcc16(!test_b(), imm); } +pub unsafe fn instr16_0F83(mut imm: i32) { jmpcc16(!test_b(), imm); } #[no_mangle] -pub unsafe fn instr32_0F83(mut imm: i32) -> () { jmpcc32(!test_b(), imm); } +pub unsafe fn instr32_0F83(mut imm: i32) { jmpcc32(!test_b(), imm); } #[no_mangle] -pub unsafe fn instr16_0F84(mut imm: i32) -> () { jmpcc16(test_z(), imm); } +pub unsafe fn instr16_0F84(mut imm: i32) { jmpcc16(test_z(), imm); } #[no_mangle] -pub unsafe fn instr32_0F84(mut imm: i32) -> () { jmpcc32(test_z(), imm); } +pub unsafe fn instr32_0F84(mut imm: i32) { jmpcc32(test_z(), imm); } #[no_mangle] -pub unsafe fn instr16_0F85(mut imm: i32) -> () { jmpcc16(!test_z(), imm); } +pub unsafe fn instr16_0F85(mut imm: i32) { jmpcc16(!test_z(), imm); } #[no_mangle] -pub unsafe fn instr32_0F85(mut imm: i32) -> () { jmpcc32(!test_z(), imm); } +pub unsafe fn instr32_0F85(mut imm: i32) { jmpcc32(!test_z(), imm); } #[no_mangle] -pub unsafe fn instr16_0F86(mut imm: i32) -> () { jmpcc16(test_be(), imm); } +pub unsafe fn instr16_0F86(mut imm: i32) { jmpcc16(test_be(), imm); } #[no_mangle] -pub unsafe fn instr32_0F86(mut imm: i32) -> () { jmpcc32(test_be(), imm); } +pub unsafe fn instr32_0F86(mut imm: i32) { jmpcc32(test_be(), imm); } #[no_mangle] -pub unsafe fn instr16_0F87(mut imm: i32) -> () { jmpcc16(!test_be(), imm); } +pub unsafe fn instr16_0F87(mut imm: i32) { jmpcc16(!test_be(), imm); } #[no_mangle] -pub unsafe fn instr32_0F87(mut imm: i32) -> () { jmpcc32(!test_be(), imm); } +pub unsafe fn instr32_0F87(mut imm: i32) { jmpcc32(!test_be(), imm); } #[no_mangle] -pub unsafe fn instr16_0F88(mut imm: i32) -> () { jmpcc16(test_s(), imm); } +pub unsafe fn instr16_0F88(mut imm: i32) { jmpcc16(test_s(), imm); } #[no_mangle] -pub unsafe fn instr32_0F88(mut imm: i32) -> () { jmpcc32(test_s(), imm); } +pub unsafe fn instr32_0F88(mut imm: i32) { jmpcc32(test_s(), imm); } #[no_mangle] -pub unsafe fn instr16_0F89(mut imm: i32) -> () { jmpcc16(!test_s(), imm); } +pub unsafe fn instr16_0F89(mut imm: i32) { jmpcc16(!test_s(), imm); } #[no_mangle] -pub unsafe fn instr32_0F89(mut imm: i32) -> () { jmpcc32(!test_s(), imm); } +pub unsafe fn instr32_0F89(mut imm: i32) { jmpcc32(!test_s(), imm); } #[no_mangle] -pub unsafe fn instr16_0F8A(mut imm: i32) -> () { jmpcc16(test_p(), imm); } +pub unsafe fn instr16_0F8A(mut imm: i32) { jmpcc16(test_p(), imm); } #[no_mangle] -pub unsafe fn instr32_0F8A(mut imm: i32) -> () { jmpcc32(test_p(), imm); } +pub unsafe fn instr32_0F8A(mut imm: i32) { jmpcc32(test_p(), imm); } #[no_mangle] -pub unsafe fn instr16_0F8B(mut imm: i32) -> () { jmpcc16(!test_p(), imm); } +pub unsafe fn instr16_0F8B(mut imm: i32) { jmpcc16(!test_p(), imm); } #[no_mangle] -pub unsafe fn instr32_0F8B(mut imm: i32) -> () { jmpcc32(!test_p(), imm); } +pub unsafe fn instr32_0F8B(mut imm: i32) { jmpcc32(!test_p(), imm); } #[no_mangle] -pub unsafe fn instr16_0F8C(mut imm: i32) -> () { jmpcc16(test_l(), imm); } +pub unsafe fn instr16_0F8C(mut imm: i32) { jmpcc16(test_l(), imm); } #[no_mangle] -pub unsafe fn instr32_0F8C(mut imm: i32) -> () { jmpcc32(test_l(), imm); } +pub unsafe fn instr32_0F8C(mut imm: i32) { jmpcc32(test_l(), imm); } #[no_mangle] -pub unsafe fn instr16_0F8D(mut imm: i32) -> () { jmpcc16(!test_l(), imm); } +pub unsafe fn instr16_0F8D(mut imm: i32) { jmpcc16(!test_l(), imm); } #[no_mangle] -pub unsafe fn instr32_0F8D(mut imm: i32) -> () { jmpcc32(!test_l(), imm); } +pub unsafe fn instr32_0F8D(mut imm: i32) { jmpcc32(!test_l(), imm); } #[no_mangle] -pub unsafe fn instr16_0F8E(mut imm: i32) -> () { jmpcc16(test_le(), imm); } +pub unsafe fn instr16_0F8E(mut imm: i32) { jmpcc16(test_le(), imm); } #[no_mangle] -pub unsafe fn instr32_0F8E(mut imm: i32) -> () { jmpcc32(test_le(), imm); } +pub unsafe fn instr32_0F8E(mut imm: i32) { jmpcc32(test_le(), imm); } #[no_mangle] -pub unsafe fn instr16_0F8F(mut imm: i32) -> () { jmpcc16(!test_le(), imm); } +pub unsafe fn instr16_0F8F(mut imm: i32) { jmpcc16(!test_le(), imm); } #[no_mangle] -pub unsafe fn instr32_0F8F(mut imm: i32) -> () { jmpcc32(!test_le(), imm); } +pub unsafe fn instr32_0F8F(mut imm: i32) { jmpcc32(!test_le(), imm); } #[no_mangle] -pub unsafe fn instr_0F90_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(test_o(), r); } +pub unsafe fn instr_0F90_reg(mut r: i32, mut unused: i32) { setcc_reg(test_o(), r); } #[no_mangle] -pub unsafe fn instr_0F91_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(!test_o(), r); } +pub unsafe fn instr_0F91_reg(mut r: i32, mut unused: i32) { setcc_reg(!test_o(), r); } #[no_mangle] -pub unsafe fn instr_0F92_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(test_b(), r); } +pub unsafe fn instr_0F92_reg(mut r: i32, mut unused: i32) { setcc_reg(test_b(), r); } #[no_mangle] -pub unsafe fn instr_0F93_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(!test_b(), r); } +pub unsafe fn instr_0F93_reg(mut r: i32, mut unused: i32) { setcc_reg(!test_b(), r); } #[no_mangle] -pub unsafe fn instr_0F94_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(test_z(), r); } +pub unsafe fn instr_0F94_reg(mut r: i32, mut unused: i32) { setcc_reg(test_z(), r); } #[no_mangle] -pub unsafe fn instr_0F95_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(!test_z(), r); } +pub unsafe fn instr_0F95_reg(mut r: i32, mut unused: i32) { setcc_reg(!test_z(), r); } #[no_mangle] -pub unsafe fn instr_0F96_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(test_be(), r); } +pub unsafe fn instr_0F96_reg(mut r: i32, mut unused: i32) { setcc_reg(test_be(), r); } #[no_mangle] -pub unsafe fn instr_0F97_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(!test_be(), r); } +pub unsafe fn instr_0F97_reg(mut r: i32, mut unused: i32) { setcc_reg(!test_be(), r); } #[no_mangle] -pub unsafe fn instr_0F98_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(test_s(), r); } +pub unsafe fn instr_0F98_reg(mut r: i32, mut unused: i32) { setcc_reg(test_s(), r); } #[no_mangle] -pub unsafe fn instr_0F99_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(!test_s(), r); } +pub unsafe fn instr_0F99_reg(mut r: i32, mut unused: i32) { setcc_reg(!test_s(), r); } #[no_mangle] -pub unsafe fn instr_0F9A_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(test_p(), r); } +pub unsafe fn instr_0F9A_reg(mut r: i32, mut unused: i32) { setcc_reg(test_p(), r); } #[no_mangle] -pub unsafe fn instr_0F9B_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(!test_p(), r); } +pub unsafe fn instr_0F9B_reg(mut r: i32, mut unused: i32) { setcc_reg(!test_p(), r); } #[no_mangle] -pub unsafe fn instr_0F9C_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(test_l(), r); } +pub unsafe fn instr_0F9C_reg(mut r: i32, mut unused: i32) { setcc_reg(test_l(), r); } #[no_mangle] -pub unsafe fn instr_0F9D_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(!test_l(), r); } +pub unsafe fn instr_0F9D_reg(mut r: i32, mut unused: i32) { setcc_reg(!test_l(), r); } #[no_mangle] -pub unsafe fn instr_0F9E_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(test_le(), r); } +pub unsafe fn instr_0F9E_reg(mut r: i32, mut unused: i32) { setcc_reg(test_le(), r); } #[no_mangle] -pub unsafe fn instr_0F9F_reg(mut r: i32, mut unused: i32) -> () { setcc_reg(!test_le(), r); } +pub unsafe fn instr_0F9F_reg(mut r: i32, mut unused: i32) { setcc_reg(!test_le(), r); } #[no_mangle] -pub unsafe fn instr_0F90_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(test_o(), addr); } +pub unsafe fn instr_0F90_mem(mut addr: i32, mut unused: i32) { setcc_mem(test_o(), addr); } #[no_mangle] -pub unsafe fn instr_0F91_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(!test_o(), addr); } +pub unsafe fn instr_0F91_mem(mut addr: i32, mut unused: i32) { setcc_mem(!test_o(), addr); } #[no_mangle] -pub unsafe fn instr_0F92_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(test_b(), addr); } +pub unsafe fn instr_0F92_mem(mut addr: i32, mut unused: i32) { setcc_mem(test_b(), addr); } #[no_mangle] -pub unsafe fn instr_0F93_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(!test_b(), addr); } +pub unsafe fn instr_0F93_mem(mut addr: i32, mut unused: i32) { setcc_mem(!test_b(), addr); } #[no_mangle] -pub unsafe fn instr_0F94_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(test_z(), addr); } +pub unsafe fn instr_0F94_mem(mut addr: i32, mut unused: i32) { setcc_mem(test_z(), addr); } #[no_mangle] -pub unsafe fn instr_0F95_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(!test_z(), addr); } +pub unsafe fn instr_0F95_mem(mut addr: i32, mut unused: i32) { setcc_mem(!test_z(), addr); } #[no_mangle] -pub unsafe fn instr_0F96_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(test_be(), addr); } +pub unsafe fn instr_0F96_mem(mut addr: i32, mut unused: i32) { setcc_mem(test_be(), addr); } #[no_mangle] -pub unsafe fn instr_0F97_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(!test_be(), addr); } +pub unsafe fn instr_0F97_mem(mut addr: i32, mut unused: i32) { setcc_mem(!test_be(), addr); } #[no_mangle] -pub unsafe fn instr_0F98_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(test_s(), addr); } +pub unsafe fn instr_0F98_mem(mut addr: i32, mut unused: i32) { setcc_mem(test_s(), addr); } #[no_mangle] -pub unsafe fn instr_0F99_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(!test_s(), addr); } +pub unsafe fn instr_0F99_mem(mut addr: i32, mut unused: i32) { setcc_mem(!test_s(), addr); } #[no_mangle] -pub unsafe fn instr_0F9A_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(test_p(), addr); } +pub unsafe fn instr_0F9A_mem(mut addr: i32, mut unused: i32) { setcc_mem(test_p(), addr); } #[no_mangle] -pub unsafe fn instr_0F9B_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(!test_p(), addr); } +pub unsafe fn instr_0F9B_mem(mut addr: i32, mut unused: i32) { setcc_mem(!test_p(), addr); } #[no_mangle] -pub unsafe fn instr_0F9C_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(test_l(), addr); } +pub unsafe fn instr_0F9C_mem(mut addr: i32, mut unused: i32) { setcc_mem(test_l(), addr); } #[no_mangle] -pub unsafe fn instr_0F9D_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(!test_l(), addr); } +pub unsafe fn instr_0F9D_mem(mut addr: i32, mut unused: i32) { setcc_mem(!test_l(), addr); } #[no_mangle] -pub unsafe fn instr_0F9E_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(test_le(), addr); } +pub unsafe fn instr_0F9E_mem(mut addr: i32, mut unused: i32) { setcc_mem(test_le(), addr); } #[no_mangle] -pub unsafe fn instr_0F9F_mem(mut addr: i32, mut unused: i32) -> () { setcc_mem(!test_le(), addr); } +pub unsafe fn instr_0F9F_mem(mut addr: i32, mut unused: i32) { setcc_mem(!test_le(), addr); } #[no_mangle] -pub unsafe fn instr16_0FA0() -> () { +pub unsafe fn instr16_0FA0() { return_on_pagefault!(push16(*sreg.offset(FS as isize) as i32)); } #[no_mangle] -pub unsafe fn instr32_0FA0() -> () { +pub unsafe fn instr32_0FA0() { return_on_pagefault!(push32(*sreg.offset(FS as isize) as i32)); } #[no_mangle] -pub unsafe fn instr16_0FA1() -> () { +pub unsafe fn instr16_0FA1() { if !switch_seg( FS, return_on_pagefault!(safe_read16(get_stack_pointer(0i32))), @@ -3205,7 +3143,7 @@ pub unsafe fn instr16_0FA1() -> () { }; } #[no_mangle] -pub unsafe fn instr32_0FA1() -> () { +pub unsafe fn instr32_0FA1() { if !switch_seg( FS, return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))) & 65535i32, @@ -3218,41 +3156,41 @@ pub unsafe fn instr32_0FA1() -> () { }; } #[no_mangle] -pub unsafe fn instr_0FA2() -> () { cpuid(); } +pub unsafe fn instr_0FA2() { cpuid(); } #[no_mangle] -pub unsafe fn instr16_0FA3_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr16_0FA3_reg(mut r1: i32, mut r2: i32) { bt_reg(read_reg16(r1), read_reg16(r2) & 15i32); } #[no_mangle] -pub unsafe fn instr16_0FA3_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FA3_mem(mut addr: i32, mut r: i32) { bt_mem(addr, read_reg16(r) << 16i32 >> 16i32); } #[no_mangle] -pub unsafe fn instr32_0FA3_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr32_0FA3_reg(mut r1: i32, mut r2: i32) { bt_reg(read_reg32(r1), read_reg32(r2) & 31i32); } #[no_mangle] -pub unsafe fn instr32_0FA3_mem(mut addr: i32, mut r: i32) -> () { bt_mem(addr, read_reg32(r)); } +pub unsafe fn instr32_0FA3_mem(mut addr: i32, mut r: i32) { bt_mem(addr, read_reg32(r)); } #[no_mangle] -pub unsafe fn instr16_0FA4_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr16_0FA4_mem(mut addr: i32, mut r: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, shld16(___, read_reg16(r), imm & 31i32)); } #[no_mangle] -pub unsafe fn instr16_0FA4_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr16_0FA4_reg(mut r1: i32, mut r: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, shld16(____0, read_reg16(r), imm & 31i32)); } #[no_mangle] -pub unsafe fn instr32_0FA4_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr32_0FA4_mem(mut addr: i32, mut r: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, shld32(___, read_reg32(r), imm & 31i32)); } #[no_mangle] -pub unsafe fn instr32_0FA4_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr32_0FA4_reg(mut r1: i32, mut r: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, shld32(____0, read_reg32(r), imm & 31i32)); } #[no_mangle] -pub unsafe fn instr16_0FA5_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FA5_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE16!( ___, addr, @@ -3260,7 +3198,7 @@ pub unsafe fn instr16_0FA5_mem(mut addr: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr16_0FA5_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FA5_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16( r1, @@ -3272,7 +3210,7 @@ pub unsafe fn instr16_0FA5_reg(mut r1: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr32_0FA5_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FA5_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE32!( ___, addr, @@ -3280,7 +3218,7 @@ pub unsafe fn instr32_0FA5_mem(mut addr: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr32_0FA5_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FA5_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32( r1, @@ -3292,22 +3230,22 @@ pub unsafe fn instr32_0FA5_reg(mut r1: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_0FA6() -> () { +pub unsafe fn instr_0FA6() { // obsolete cmpxchg (os/2) trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FA7() -> () { undefined_instruction(); } +pub unsafe fn instr_0FA7() { undefined_instruction(); } #[no_mangle] -pub unsafe fn instr16_0FA8() -> () { +pub unsafe fn instr16_0FA8() { return_on_pagefault!(push16(*sreg.offset(GS as isize) as i32)); } #[no_mangle] -pub unsafe fn instr32_0FA8() -> () { +pub unsafe fn instr32_0FA8() { return_on_pagefault!(push32(*sreg.offset(GS as isize) as i32)); } #[no_mangle] -pub unsafe fn instr16_0FA9() -> () { +pub unsafe fn instr16_0FA9() { if !switch_seg( GS, return_on_pagefault!(safe_read16(get_stack_pointer(0i32))), @@ -3320,7 +3258,7 @@ pub unsafe fn instr16_0FA9() -> () { }; } #[no_mangle] -pub unsafe fn instr32_0FA9() -> () { +pub unsafe fn instr32_0FA9() { if !switch_seg( GS, return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))) & 65535i32, @@ -3333,44 +3271,44 @@ pub unsafe fn instr32_0FA9() -> () { }; } #[no_mangle] -pub unsafe fn instr_0FAA() -> () { +pub unsafe fn instr_0FAA() { // rsm undefined_instruction(); } #[no_mangle] -pub unsafe fn instr16_0FAB_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr16_0FAB_reg(mut r1: i32, mut r2: i32) { write_reg16(r1, bts_reg(read_reg16(r1), read_reg16(r2) & 15i32)); } #[no_mangle] -pub unsafe fn instr16_0FAB_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FAB_mem(mut addr: i32, mut r: i32) { bts_mem(addr, read_reg16(r) << 16i32 >> 16i32); } #[no_mangle] -pub unsafe fn instr32_0FAB_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr32_0FAB_reg(mut r1: i32, mut r2: i32) { write_reg32(r1, bts_reg(read_reg32(r1), read_reg32(r2) & 31i32)); } #[no_mangle] -pub unsafe fn instr32_0FAB_mem(mut addr: i32, mut r: i32) -> () { bts_mem(addr, read_reg32(r)); } +pub unsafe fn instr32_0FAB_mem(mut addr: i32, mut r: i32) { bts_mem(addr, read_reg32(r)); } #[no_mangle] -pub unsafe fn instr16_0FAC_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr16_0FAC_mem(mut addr: i32, mut r: i32, mut imm: i32) { SAFE_READ_WRITE16!(___, addr, shrd16(___, read_reg16(r), imm & 31i32)); } #[no_mangle] -pub unsafe fn instr16_0FAC_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr16_0FAC_reg(mut r1: i32, mut r: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, shrd16(____0, read_reg16(r), imm & 31i32)); } #[no_mangle] -pub unsafe fn instr32_0FAC_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr32_0FAC_mem(mut addr: i32, mut r: i32, mut imm: i32) { SAFE_READ_WRITE32!(___, addr, shrd32(___, read_reg32(r), imm & 31i32)); } #[no_mangle] -pub unsafe fn instr32_0FAC_reg(mut r1: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr32_0FAC_reg(mut r1: i32, mut r: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, shrd32(____0, read_reg32(r), imm & 31i32)); } #[no_mangle] -pub unsafe fn instr16_0FAD_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FAD_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE16!( ___, addr, @@ -3378,7 +3316,7 @@ pub unsafe fn instr16_0FAD_mem(mut addr: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr16_0FAD_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FAD_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16( r1, @@ -3390,7 +3328,7 @@ pub unsafe fn instr16_0FAD_reg(mut r1: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr32_0FAD_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FAD_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE32!( ___, addr, @@ -3398,7 +3336,7 @@ pub unsafe fn instr32_0FAD_mem(mut addr: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr32_0FAD_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FAD_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32( r1, @@ -3410,17 +3348,17 @@ pub unsafe fn instr32_0FAD_reg(mut r1: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_0FAE_0_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FAE_0_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FAE_0_mem(mut addr: i32) -> () { fxsave(addr as u32); } +pub unsafe fn instr_0FAE_0_mem(mut addr: i32) { fxsave(addr as u32); } #[no_mangle] -pub unsafe fn instr_0FAE_1_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FAE_1_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FAE_1_mem(mut addr: i32) -> () { fxrstor(addr as u32); } +pub unsafe fn instr_0FAE_1_mem(mut addr: i32) { fxrstor(addr as u32); } #[no_mangle] -pub unsafe fn instr_0FAE_2_reg(mut r: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_0FAE_2_reg(mut r: i32) { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_0FAE_2_mem(mut addr: i32) -> () { +pub unsafe fn instr_0FAE_2_mem(mut addr: i32) { // ldmxcsr let mut new_mxcsr: i32 = return_on_pagefault!(safe_read32s(addr)); if 0 != new_mxcsr & !MXCSR_MASK { @@ -3434,71 +3372,71 @@ pub unsafe fn instr_0FAE_2_mem(mut addr: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_0FAE_3_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FAE_3_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FAE_3_mem(mut addr: i32) -> () { +pub unsafe fn instr_0FAE_3_mem(mut addr: i32) { // stmxcsr return_on_pagefault!(safe_write32(addr, *mxcsr)); } #[no_mangle] -pub unsafe fn instr_0FAE_4_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FAE_4_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FAE_4_mem(mut addr: i32) -> () { +pub unsafe fn instr_0FAE_4_mem(mut addr: i32) { // xsave undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0FAE_5_reg(mut r: i32) -> () { +pub unsafe fn instr_0FAE_5_reg(mut r: i32) { // lfence dbg_assert!(r == 0i32, ("Unexpected lfence encoding")); } #[no_mangle] -pub unsafe fn instr_0FAE_5_mem(mut addr: i32) -> () { +pub unsafe fn instr_0FAE_5_mem(mut addr: i32) { // xrstor undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0FAE_6_reg(mut r: i32) -> () { +pub unsafe fn instr_0FAE_6_reg(mut r: i32) { // mfence dbg_assert!(r == 0i32, ("Unexpected mfence encoding")); } #[no_mangle] -pub unsafe fn instr_0FAE_6_mem(mut addr: i32) -> () { +pub unsafe fn instr_0FAE_6_mem(mut addr: i32) { // xsaveopt undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0FAE_7_reg(mut r: i32) -> () { +pub unsafe fn instr_0FAE_7_reg(mut r: i32) { // sfence dbg_assert!(r == 0i32, ("Unexpected sfence encoding")); } #[no_mangle] -pub unsafe fn instr_0FAE_7_mem(mut addr: i32) -> () { +pub unsafe fn instr_0FAE_7_mem(mut addr: i32) { // clflush undefined_instruction(); } #[no_mangle] -pub unsafe fn instr16_0FAF_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FAF_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, imul_reg16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_0FAF_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FAF_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r, imul_reg16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_0FAF_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FAF_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, imul_reg32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_0FAF_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FAF_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r, imul_reg32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr_0FB0_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_0FB0_reg(mut r1: i32, mut r2: i32) { // cmpxchg8 let mut data: i32 = read_reg8(r1); cmp8(*reg8.offset(AL as isize) as i32, data); @@ -3510,7 +3448,7 @@ pub unsafe fn instr_0FB0_reg(mut r1: i32, mut r2: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr_0FB0_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FB0_mem(mut addr: i32, mut r: i32) { // cmpxchg8 return_on_pagefault!(writable_or_pagefault(addr, 1i32)); let mut data: i32 = return_on_pagefault!(safe_read8(addr)); @@ -3524,7 +3462,7 @@ pub unsafe fn instr_0FB0_mem(mut addr: i32, mut r: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr16_0FB1_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr16_0FB1_reg(mut r1: i32, mut r2: i32) { // cmpxchg16 let mut data: i32 = read_reg16(r1); cmp16(*reg16.offset(AX as isize) as i32, data); @@ -3536,7 +3474,7 @@ pub unsafe fn instr16_0FB1_reg(mut r1: i32, mut r2: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr16_0FB1_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FB1_mem(mut addr: i32, mut r: i32) { // cmpxchg16 return_on_pagefault!(writable_or_pagefault(addr, 2i32)); let mut data: i32 = return_on_pagefault!(safe_read16(addr)); @@ -3550,7 +3488,7 @@ pub unsafe fn instr16_0FB1_mem(mut addr: i32, mut r: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr32_0FB1_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr32_0FB1_reg(mut r1: i32, mut r2: i32) { // cmpxchg32 let mut data: i32 = read_reg32(r1); cmp32(*reg32s.offset(EAX as isize), data); @@ -3562,7 +3500,7 @@ pub unsafe fn instr32_0FB1_reg(mut r1: i32, mut r2: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr32_0FB1_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FB1_mem(mut addr: i32, mut r: i32) { // cmpxchg32 return_on_pagefault!(writable_or_pagefault(addr, 4i32)); let mut data: i32 = return_on_pagefault!(safe_read32s(addr)); @@ -3576,300 +3514,290 @@ pub unsafe fn instr32_0FB1_mem(mut addr: i32, mut r: i32) -> () { }; } #[no_mangle] -pub unsafe fn instr16_0FB2_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } +pub unsafe fn instr16_0FB2_reg(mut unused: i32, mut unused2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_0FB2_mem(mut addr: i32, mut r: i32) -> () { - lss16(addr, get_reg16_index(r), SS); -} +pub unsafe fn instr16_0FB2_mem(mut addr: i32, mut r: i32) { lss16(addr, get_reg16_index(r), SS); } #[no_mangle] -pub unsafe fn instr32_0FB2_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } +pub unsafe fn instr32_0FB2_reg(mut unused: i32, mut unused2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr32_0FB2_mem(mut addr: i32, mut r: i32) -> () { lss32(addr, r, SS); } +pub unsafe fn instr32_0FB2_mem(mut addr: i32, mut r: i32) { lss32(addr, r, SS); } #[no_mangle] -pub unsafe fn instr16_0FB3_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr16_0FB3_reg(mut r1: i32, mut r2: i32) { write_reg16(r1, btr_reg(read_reg16(r1), read_reg16(r2) & 15i32)); } #[no_mangle] -pub unsafe fn instr16_0FB3_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FB3_mem(mut addr: i32, mut r: i32) { btr_mem(addr, read_reg16(r) << 16i32 >> 16i32); } #[no_mangle] -pub unsafe fn instr32_0FB3_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr32_0FB3_reg(mut r1: i32, mut r2: i32) { write_reg32(r1, btr_reg(read_reg32(r1), read_reg32(r2) & 31i32)); } #[no_mangle] -pub unsafe fn instr32_0FB3_mem(mut addr: i32, mut r: i32) -> () { btr_mem(addr, read_reg32(r)); } +pub unsafe fn instr32_0FB3_mem(mut addr: i32, mut r: i32) { btr_mem(addr, read_reg32(r)); } #[no_mangle] -pub unsafe fn instr16_0FB4_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } +pub unsafe fn instr16_0FB4_reg(mut unused: i32, mut unused2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_0FB4_mem(mut addr: i32, mut r: i32) -> () { - lss16(addr, get_reg16_index(r), FS); -} +pub unsafe fn instr16_0FB4_mem(mut addr: i32, mut r: i32) { lss16(addr, get_reg16_index(r), FS); } #[no_mangle] -pub unsafe fn instr32_0FB4_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } +pub unsafe fn instr32_0FB4_reg(mut unused: i32, mut unused2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr32_0FB4_mem(mut addr: i32, mut r: i32) -> () { lss32(addr, r, FS); } +pub unsafe fn instr32_0FB4_mem(mut addr: i32, mut r: i32) { lss32(addr, r, FS); } #[no_mangle] -pub unsafe fn instr16_0FB5_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } +pub unsafe fn instr16_0FB5_reg(mut unused: i32, mut unused2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_0FB5_mem(mut addr: i32, mut r: i32) -> () { - lss16(addr, get_reg16_index(r), GS); -} +pub unsafe fn instr16_0FB5_mem(mut addr: i32, mut r: i32) { lss16(addr, get_reg16_index(r), GS); } #[no_mangle] -pub unsafe fn instr32_0FB5_reg(mut unused: i32, mut unused2: i32) -> () { trigger_ud(); } +pub unsafe fn instr32_0FB5_reg(mut unused: i32, mut unused2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr32_0FB5_mem(mut addr: i32, mut r: i32) -> () { lss32(addr, r, GS); } +pub unsafe fn instr32_0FB5_mem(mut addr: i32, mut r: i32) { lss32(addr, r, GS); } #[no_mangle] -pub unsafe fn instr16_0FB6_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FB6_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg16(r, ____0); } #[no_mangle] -pub unsafe fn instr16_0FB6_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FB6_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); write_reg16(r, ____0); } #[no_mangle] -pub unsafe fn instr32_0FB6_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FB6_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg32(r, ____0); } #[no_mangle] -pub unsafe fn instr32_0FB6_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FB6_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); write_reg32(r, ____0); } #[no_mangle] -pub unsafe fn instr16_0FB7_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FB7_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, ____0); } #[no_mangle] -pub unsafe fn instr16_0FB7_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FB7_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r, ____0); } #[no_mangle] -pub unsafe fn instr32_0FB7_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FB7_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg32(r, ____0); } #[no_mangle] -pub unsafe fn instr32_0FB7_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FB7_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg32(r, ____0); } #[no_mangle] -pub unsafe fn instr16_0FB8_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr16_0FB8_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_0FB8_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr16_0FB8_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_F30FB8_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_F30FB8_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, popcnt(____0)); } #[no_mangle] -pub unsafe fn instr16_F30FB8_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_F30FB8_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r, popcnt(____0)); } #[no_mangle] -pub unsafe fn instr32_0FB8_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr32_0FB8_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr32_0FB8_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr32_0FB8_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr32_F30FB8_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_F30FB8_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, popcnt(____0)); } #[no_mangle] -pub unsafe fn instr32_F30FB8_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_F30FB8_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r, popcnt(____0)); } #[no_mangle] -pub unsafe fn instr_0FB9() -> () { +pub unsafe fn instr_0FB9() { // UD2 trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_0FBA_4_reg(mut r: i32, mut imm: i32) -> () { - bt_reg(read_reg16(r), imm & 15i32); -} +pub unsafe fn instr16_0FBA_4_reg(mut r: i32, mut imm: i32) { bt_reg(read_reg16(r), imm & 15i32); } #[no_mangle] -pub unsafe fn instr16_0FBA_4_mem(mut addr: i32, mut imm: i32) -> () { bt_mem(addr, imm & 15i32); } +pub unsafe fn instr16_0FBA_4_mem(mut addr: i32, mut imm: i32) { bt_mem(addr, imm & 15i32); } #[no_mangle] -pub unsafe fn instr16_0FBA_5_reg(mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr16_0FBA_5_reg(mut r: i32, mut imm: i32) { write_reg16(r, bts_reg(read_reg16(r), imm & 15i32)); } #[no_mangle] -pub unsafe fn instr16_0FBA_5_mem(mut addr: i32, mut imm: i32) -> () { bts_mem(addr, imm & 15i32); } +pub unsafe fn instr16_0FBA_5_mem(mut addr: i32, mut imm: i32) { bts_mem(addr, imm & 15i32); } #[no_mangle] -pub unsafe fn instr16_0FBA_6_reg(mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr16_0FBA_6_reg(mut r: i32, mut imm: i32) { write_reg16(r, btr_reg(read_reg16(r), imm & 15i32)); } #[no_mangle] -pub unsafe fn instr16_0FBA_6_mem(mut addr: i32, mut imm: i32) -> () { btr_mem(addr, imm & 15i32); } +pub unsafe fn instr16_0FBA_6_mem(mut addr: i32, mut imm: i32) { btr_mem(addr, imm & 15i32); } #[no_mangle] -pub unsafe fn instr16_0FBA_7_reg(mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr16_0FBA_7_reg(mut r: i32, mut imm: i32) { write_reg16(r, btc_reg(read_reg16(r), imm & 15i32)); } #[no_mangle] -pub unsafe fn instr16_0FBA_7_mem(mut addr: i32, mut imm: i32) -> () { btc_mem(addr, imm & 15i32); } +pub unsafe fn instr16_0FBA_7_mem(mut addr: i32, mut imm: i32) { btc_mem(addr, imm & 15i32); } #[no_mangle] -pub unsafe fn instr32_0FBA_4_reg(mut r: i32, mut imm: i32) -> () { - bt_reg(read_reg32(r), imm & 31i32); -} +pub unsafe fn instr32_0FBA_4_reg(mut r: i32, mut imm: i32) { bt_reg(read_reg32(r), imm & 31i32); } #[no_mangle] -pub unsafe fn instr32_0FBA_4_mem(mut addr: i32, mut imm: i32) -> () { bt_mem(addr, imm & 31i32); } +pub unsafe fn instr32_0FBA_4_mem(mut addr: i32, mut imm: i32) { bt_mem(addr, imm & 31i32); } #[no_mangle] -pub unsafe fn instr32_0FBA_5_reg(mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr32_0FBA_5_reg(mut r: i32, mut imm: i32) { write_reg32(r, bts_reg(read_reg32(r), imm & 31i32)); } #[no_mangle] -pub unsafe fn instr32_0FBA_5_mem(mut addr: i32, mut imm: i32) -> () { bts_mem(addr, imm & 31i32); } +pub unsafe fn instr32_0FBA_5_mem(mut addr: i32, mut imm: i32) { bts_mem(addr, imm & 31i32); } #[no_mangle] -pub unsafe fn instr32_0FBA_6_reg(mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr32_0FBA_6_reg(mut r: i32, mut imm: i32) { write_reg32(r, btr_reg(read_reg32(r), imm & 31i32)); } #[no_mangle] -pub unsafe fn instr32_0FBA_6_mem(mut addr: i32, mut imm: i32) -> () { btr_mem(addr, imm & 31i32); } +pub unsafe fn instr32_0FBA_6_mem(mut addr: i32, mut imm: i32) { btr_mem(addr, imm & 31i32); } #[no_mangle] -pub unsafe fn instr32_0FBA_7_reg(mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr32_0FBA_7_reg(mut r: i32, mut imm: i32) { write_reg32(r, btc_reg(read_reg32(r), imm & 31i32)); } #[no_mangle] -pub unsafe fn instr32_0FBA_7_mem(mut addr: i32, mut imm: i32) -> () { btc_mem(addr, imm & 31i32); } +pub unsafe fn instr32_0FBA_7_mem(mut addr: i32, mut imm: i32) { btc_mem(addr, imm & 31i32); } #[no_mangle] -pub unsafe fn instr16_0FBB_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr16_0FBB_reg(mut r1: i32, mut r2: i32) { write_reg16(r1, btc_reg(read_reg16(r1), read_reg16(r2) & 15i32)); } #[no_mangle] -pub unsafe fn instr16_0FBB_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FBB_mem(mut addr: i32, mut r: i32) { btc_mem(addr, read_reg16(r) << 16i32 >> 16i32); } #[no_mangle] -pub unsafe fn instr32_0FBB_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr32_0FBB_reg(mut r1: i32, mut r2: i32) { write_reg32(r1, btc_reg(read_reg32(r1), read_reg32(r2) & 31i32)); } #[no_mangle] -pub unsafe fn instr32_0FBB_mem(mut addr: i32, mut r: i32) -> () { btc_mem(addr, read_reg32(r)); } +pub unsafe fn instr32_0FBB_mem(mut addr: i32, mut r: i32) { btc_mem(addr, read_reg32(r)); } #[no_mangle] -pub unsafe fn instr16_0FBC_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FBC_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, bsf16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_0FBC_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FBC_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r, bsf16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_0FBC_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FBC_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, bsf32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_0FBC_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FBC_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r, bsf32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_0FBD_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FBD_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, bsr16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_0FBD_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FBD_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r, bsr16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_0FBD_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FBD_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, bsr32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_0FBD_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FBD_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r, bsr32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_0FBE_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FBE_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg16(r, ____0 << 24i32 >> 24i32); } #[no_mangle] -pub unsafe fn instr16_0FBE_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FBE_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); write_reg16(r, ____0 << 24i32 >> 24i32); } #[no_mangle] -pub unsafe fn instr32_0FBE_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FBE_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg32(r, ____0 << 24i32 >> 24i32); } #[no_mangle] -pub unsafe fn instr32_0FBE_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FBE_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); write_reg32(r, ____0 << 24i32 >> 24i32); } #[no_mangle] -pub unsafe fn instr16_0FBF_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FBF_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, ____0 << 16i32 >> 16i32); } #[no_mangle] -pub unsafe fn instr16_0FBF_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FBF_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r, ____0 << 16i32 >> 16i32); } #[no_mangle] -pub unsafe fn instr32_0FBF_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FBF_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg32(r, ____0 << 16i32 >> 16i32); } #[no_mangle] -pub unsafe fn instr32_0FBF_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FBF_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg32(r, ____0 << 16i32 >> 16i32); } #[no_mangle] -pub unsafe fn instr_0FC0_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FC0_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE8!(___, addr, xadd8(___, get_reg8_index(r))); } #[no_mangle] -pub unsafe fn instr_0FC0_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr_0FC0_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); write_reg8(r1, xadd8(____0, get_reg8_index(r))); } #[no_mangle] -pub unsafe fn instr16_0FC1_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FC1_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE16!(___, addr, xadd16(___, get_reg16_index(r))); } #[no_mangle] -pub unsafe fn instr16_0FC1_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr16_0FC1_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16(r1, xadd16(____0, get_reg16_index(r))); } #[no_mangle] -pub unsafe fn instr32_0FC1_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FC1_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE32!(___, addr, xadd32(___, r)); } #[no_mangle] -pub unsafe fn instr32_0FC1_reg(mut r1: i32, mut r: i32) -> () { +pub unsafe fn instr32_0FC1_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32(r1, xadd32(____0, r)); } #[no_mangle] -pub unsafe fn instr_0FC3_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FC3_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FC3_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FC3_mem(mut addr: i32, mut r: i32) { // movnti return_on_pagefault!(safe_write32(addr, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr_0FC4(mut source: i32, mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0FC4(mut source: i32, mut r: i32, mut imm8: i32) { // pinsrw mm, r32/m16, imm8 let mut destination: reg64 = read_mmx64s(r); let mut index: u32 = (imm8 & 3i32) as u32; @@ -3877,15 +3805,15 @@ pub unsafe fn instr_0FC4(mut source: i32, mut r: i32, mut imm8: i32) -> () { write_mmx_reg64(r, destination); } #[no_mangle] -pub unsafe fn instr_0FC4_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { +pub unsafe fn instr_0FC4_reg(mut r1: i32, mut r2: i32, mut imm: i32) { instr_0FC4(read_reg32(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_0FC4_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr_0FC4_mem(mut addr: i32, mut r: i32, mut imm: i32) { instr_0FC4(return_on_pagefault!(safe_read16(addr)), r, imm); } #[no_mangle] -pub unsafe fn instr_660FC4(mut source: i32, mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660FC4(mut source: i32, mut r: i32, mut imm8: i32) { // pinsrw xmm, r32/m16, imm8 let mut destination: reg128 = read_xmm128s(r); let mut index: u32 = (imm8 & 7i32) as u32; @@ -3893,17 +3821,17 @@ pub unsafe fn instr_660FC4(mut source: i32, mut r: i32, mut imm8: i32) -> () { write_xmm_reg128(r, destination); } #[no_mangle] -pub unsafe fn instr_660FC4_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { +pub unsafe fn instr_660FC4_reg(mut r1: i32, mut r2: i32, mut imm: i32) { instr_660FC4(read_reg32(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_660FC4_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr_660FC4_mem(mut addr: i32, mut r: i32, mut imm: i32) { instr_660FC4(return_on_pagefault!(safe_read16(addr)), r, imm); } #[no_mangle] -pub unsafe fn instr_0FC5_mem(mut addr: i32, mut r: i32, mut imm8: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FC5_mem(mut addr: i32, mut r: i32, mut imm8: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i32) { // pextrw r32, mm, imm8 let mut data: reg64 = read_mmx64s(r1); let mut index: u32 = (imm8 & 3i32) as u32; @@ -3911,9 +3839,9 @@ pub unsafe fn instr_0FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i32) -> () { write_reg32(r2, result as i32); } #[no_mangle] -pub unsafe fn instr_660FC5_mem(mut addr: i32, mut r: i32, mut imm8: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660FC5_mem(mut addr: i32, mut r: i32, mut imm8: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i32) { // pextrw r32, xmm, imm8 let mut data: reg128 = read_xmm128s(r1); let mut index: u32 = (imm8 & 7i32) as u32; @@ -3922,7 +3850,7 @@ pub unsafe fn instr_660FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i32) -> () { } #[no_mangle] -pub unsafe fn instr_0FC6(mut source: reg128, mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0FC6(mut source: reg128, mut r: i32, mut imm8: i32) { // shufps xmm, xmm/mem128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -3935,16 +3863,16 @@ pub unsafe fn instr_0FC6(mut source: reg128, mut r: i32, mut imm8: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_0FC6_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { +pub unsafe fn instr_0FC6_reg(mut r1: i32, mut r2: i32, mut imm: i32) { instr_0FC6(read_xmm128s(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_0FC6_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr_0FC6_mem(mut addr: i32, mut r: i32, mut imm: i32) { instr_0FC6(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] -pub unsafe fn instr_660FC6(mut source: reg128, mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660FC6(mut source: reg128, mut r: i32, mut imm8: i32) { // shufpd xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -3956,18 +3884,18 @@ pub unsafe fn instr_660FC6(mut source: reg128, mut r: i32, mut imm8: i32) -> () write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FC6_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { +pub unsafe fn instr_660FC6_reg(mut r1: i32, mut r2: i32, mut imm: i32) { instr_660FC6(read_xmm128s(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_660FC6_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr_660FC6_mem(mut addr: i32, mut r: i32, mut imm: i32) { instr_660FC6(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] -pub unsafe fn instr_0FC7_1_reg(mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FC7_1_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FC7_1_mem(mut addr: i32) -> () { +pub unsafe fn instr_0FC7_1_mem(mut addr: i32) { // cmpxchg8b return_on_pagefault!(writable_or_pagefault(addr, 8i32)); let mut m64_low: i32 = return_on_pagefault!(safe_read32s(addr)); @@ -3987,7 +3915,7 @@ pub unsafe fn instr_0FC7_1_mem(mut addr: i32) -> () { *flags_changed &= !FLAG_ZERO; } #[no_mangle] -pub unsafe fn instr_0FC7_6_reg(mut r: i32) -> () { +pub unsafe fn instr_0FC7_6_reg(mut r: i32) { // rdrand let mut has_rand: i32 = has_rand_int() as i32; let mut rand: i32 = 0i32; @@ -4000,101 +3928,95 @@ pub unsafe fn instr_0FC7_6_reg(mut r: i32) -> () { *flags_changed = 0i32; } #[no_mangle] -pub unsafe fn instr_0FC7_6_mem(mut addr: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FC7_6_mem(mut addr: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FC8() -> () { bswap(EAX); } +pub unsafe fn instr_0FC8() { bswap(EAX); } #[no_mangle] -pub unsafe fn instr_0FC9() -> () { bswap(ECX); } +pub unsafe fn instr_0FC9() { bswap(ECX); } #[no_mangle] -pub unsafe fn instr_0FCA() -> () { bswap(EDX); } +pub unsafe fn instr_0FCA() { bswap(EDX); } #[no_mangle] -pub unsafe fn instr_0FCB() -> () { bswap(EBX); } +pub unsafe fn instr_0FCB() { bswap(EBX); } #[no_mangle] -pub unsafe fn instr_0FCC() -> () { bswap(ESP); } +pub unsafe fn instr_0FCC() { bswap(ESP); } #[no_mangle] -pub unsafe fn instr_0FCD() -> () { bswap(EBP); } +pub unsafe fn instr_0FCD() { bswap(EBP); } #[no_mangle] -pub unsafe fn instr_0FCE() -> () { bswap(ESI); } +pub unsafe fn instr_0FCE() { bswap(ESI); } #[no_mangle] -pub unsafe fn instr_0FCF() -> () { bswap(EDI); } +pub unsafe fn instr_0FCF() { bswap(EDI); } #[no_mangle] -pub unsafe fn instr_0FD0() -> () { unimplemented_sse(); } +pub unsafe fn instr_0FD0() { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_0FD1(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FD1(mut source: reg64, mut r: i32) { // psrlw mm, mm/m64 psrlw_r64(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe fn instr_0FD1_reg(mut r1: i32, mut r2: i32) -> () { instr_0FD1(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FD1_reg(mut r1: i32, mut r2: i32) { instr_0FD1(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FD1_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FD1_mem(mut addr: i32, mut r: i32) { instr_0FD1(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FD1(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FD1(mut source: reg128, mut r: i32) { // psrlw xmm, xmm/m128 // XXX: Aligned access or #gp psrlw_r128(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe fn instr_660FD1_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FD1(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FD1_reg(mut r1: i32, mut r2: i32) { instr_660FD1(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FD1_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FD1_mem(mut addr: i32, mut r: i32) { instr_660FD1(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FD2(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FD2(mut source: reg64, mut r: i32) { // psrld mm, mm/m64 psrld_r64(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe fn instr_0FD2_reg(mut r1: i32, mut r2: i32) -> () { instr_0FD2(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FD2_reg(mut r1: i32, mut r2: i32) { instr_0FD2(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FD2_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FD2_mem(mut addr: i32, mut r: i32) { instr_0FD2(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FD2(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FD2(mut source: reg128, mut r: i32) { // psrld xmm, xmm/m128 // XXX: Aligned access or #gp psrld_r128(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe fn instr_660FD2_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FD2(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FD2_reg(mut r1: i32, mut r2: i32) { instr_660FD2(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FD2_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FD2_mem(mut addr: i32, mut r: i32) { instr_660FD2(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FD3(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FD3(mut source: reg64, mut r: i32) { // psrlq mm, mm/m64 psrlq_r64(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe fn instr_0FD3_reg(mut r1: i32, mut r2: i32) -> () { instr_0FD3(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FD3_reg(mut r1: i32, mut r2: i32) { instr_0FD3(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FD3_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FD3_mem(mut addr: i32, mut r: i32) { instr_0FD3(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FD3(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FD3(mut source: reg128, mut r: i32) { // psrlq xmm, mm/m64 psrlq_r128(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe fn instr_660FD3_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FD3(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FD3_reg(mut r1: i32, mut r2: i32) { instr_660FD3(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FD3_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FD3_mem(mut addr: i32, mut r: i32) { instr_660FD3(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FD4(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FD4(mut source: reg64, mut r: i32) { // paddq mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); destination.u64_0[0usize] = @@ -4102,13 +4024,13 @@ pub unsafe fn instr_0FD4(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, destination); } #[no_mangle] -pub unsafe fn instr_0FD4_reg(mut r1: i32, mut r2: i32) -> () { instr_0FD4(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FD4_reg(mut r1: i32, mut r2: i32) { instr_0FD4(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FD4_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FD4_mem(mut addr: i32, mut r: i32) { instr_0FD4(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FD4(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FD4(mut source: reg128, mut r: i32) { // paddq xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -4119,15 +4041,13 @@ pub unsafe fn instr_660FD4(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, destination); } #[no_mangle] -pub unsafe fn instr_660FD4_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FD4(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FD4_reg(mut r1: i32, mut r2: i32) { instr_660FD4(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FD4_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FD4_mem(mut addr: i32, mut r: i32) { instr_660FD4(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FD5(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FD5(mut source: reg64, mut r: i32) { // pmullw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = destination.u16_0[0usize] as i32 * source.u16_0[0usize] as i32 & 65535i32; @@ -4139,13 +4059,13 @@ pub unsafe fn instr_0FD5(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe fn instr_0FD5_reg(mut r1: i32, mut r2: i32) -> () { instr_0FD5(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FD5_reg(mut r1: i32, mut r2: i32) { instr_0FD5(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FD5_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FD5_mem(mut addr: i32, mut r: i32) { instr_0FD5(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FD5(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FD5(mut source: reg128, mut r: i32) { // pmullw xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -4162,24 +4082,22 @@ pub unsafe fn instr_660FD5(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_660FD5_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FD5(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FD5_reg(mut r1: i32, mut r2: i32) { instr_660FD5(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FD5_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FD5_mem(mut addr: i32, mut r: i32) { instr_660FD5(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FD6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FD6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FD6_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FD6_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660FD6_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FD6_mem(mut addr: i32, mut r: i32) { // movq xmm/m64, xmm movl_r128_m64(addr, r); } #[no_mangle] -pub unsafe fn instr_660FD6_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FD6_reg(mut r1: i32, mut r2: i32) { // movq xmm/m64, xmm let mut data: reg64 = read_xmm64s(r2); write_xmm128( @@ -4191,17 +4109,17 @@ pub unsafe fn instr_660FD6_reg(mut r1: i32, mut r2: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_F20FD6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_F20FD6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_F20FD6_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F20FD6_reg(mut r1: i32, mut r2: i32) { // movdq2q mm, xmm let mut source: reg128 = read_xmm128s(r1); write_mmx64(r2, source.u32_0[0usize] as i32, source.u32_0[1usize] as i32); } #[no_mangle] -pub unsafe fn instr_F30FD6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_F30FD6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_F30FD6_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_F30FD6_reg(mut r1: i32, mut r2: i32) { // movq2dq xmm, mm let mut source: reg64 = read_mmx64s(r1); write_xmm128( @@ -4213,9 +4131,9 @@ pub unsafe fn instr_F30FD6_reg(mut r1: i32, mut r2: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_0FD7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FD7_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FD7_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_0FD7_reg(mut r1: i32, mut r2: i32) { // pmovmskb r, mm let mut x: reg64 = read_mmx64s(r1); let mut result: u32 = (x.u8_0[0usize] as i32 >> 7i32 << 0i32 @@ -4229,9 +4147,9 @@ pub unsafe fn instr_0FD7_reg(mut r1: i32, mut r2: i32) -> () { write_reg32(r2, result as i32); } #[no_mangle] -pub unsafe fn instr_660FD7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660FD7_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660FD7_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FD7_reg(mut r1: i32, mut r2: i32) { // pmovmskb reg, xmm let mut x: reg128 = read_xmm128s(r1); let mut result: i32 = x.u8_0[0usize] as i32 >> 7i32 << 0i32 @@ -4253,7 +4171,7 @@ pub unsafe fn instr_660FD7_reg(mut r1: i32, mut r2: i32) -> () { write_reg32(r2, result); } #[no_mangle] -pub unsafe fn instr_0FD8(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FD8(mut source: reg64, mut r: i32) { // psubusb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -4269,13 +4187,13 @@ pub unsafe fn instr_0FD8(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe fn instr_0FD8_reg(mut r1: i32, mut r2: i32) -> () { instr_0FD8(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FD8_reg(mut r1: i32, mut r2: i32) { instr_0FD8(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FD8_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FD8_mem(mut addr: i32, mut r: i32) { instr_0FD8(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FD8(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FD8(mut source: reg128, mut r: i32) { // psubusb xmm, xmm/m128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; @@ -4289,15 +4207,13 @@ pub unsafe fn instr_660FD8(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FD8_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FD8(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FD8_reg(mut r1: i32, mut r2: i32) { instr_660FD8(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FD8_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FD8_mem(mut addr: i32, mut r: i32) { instr_660FD8(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FD9(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FD9(mut source: reg64, mut r: i32) { // psubusw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = @@ -4313,13 +4229,13 @@ pub unsafe fn instr_0FD9(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe fn instr_0FD9_reg(mut r1: i32, mut r2: i32) -> () { instr_0FD9(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FD9_reg(mut r1: i32, mut r2: i32) { instr_0FD9(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FD9_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FD9_mem(mut addr: i32, mut r: i32) { instr_0FD9(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FD9(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FD9(mut source: reg128, mut r: i32) { // psubusw xmm, xmm/m128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; @@ -4333,15 +4249,13 @@ pub unsafe fn instr_660FD9(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FD9_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FD9(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FD9_reg(mut r1: i32, mut r2: i32) { instr_660FD9(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FD9_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FD9_mem(mut addr: i32, mut r: i32) { instr_660FD9(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FDA(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FDA(mut source: reg64, mut r: i32) { // pminub mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; @@ -4359,13 +4273,13 @@ pub unsafe fn instr_0FDA(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe fn instr_0FDA_reg(mut r1: i32, mut r2: i32) -> () { instr_0FDA(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FDA_reg(mut r1: i32, mut r2: i32) { instr_0FDA(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FDA_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FDA_mem(mut addr: i32, mut r: i32) { instr_0FDA(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FDA(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FDA(mut source: reg128, mut r: i32) { // pminub xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -4384,15 +4298,13 @@ pub unsafe fn instr_660FDA(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FDA_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FDA(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FDA_reg(mut r1: i32, mut r2: i32) { instr_660FDA(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FDA_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FDA_mem(mut addr: i32, mut r: i32) { instr_660FDA(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FDB(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FDB(mut source: reg64, mut r: i32) { // pand mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -4402,27 +4314,25 @@ pub unsafe fn instr_0FDB(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe fn instr_0FDB_reg(mut r1: i32, mut r2: i32) -> () { instr_0FDB(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FDB_reg(mut r1: i32, mut r2: i32) { instr_0FDB(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FDB_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FDB_mem(mut addr: i32, mut r: i32) { instr_0FDB(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FDB(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FDB(mut source: reg128, mut r: i32) { // pand xmm, xmm/m128 // XXX: Aligned access or #gp pand_r128(source, r); } #[no_mangle] -pub unsafe fn instr_660FDB_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FDB(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FDB_reg(mut r1: i32, mut r2: i32) { instr_660FDB(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FDB_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FDB_mem(mut addr: i32, mut r: i32) { instr_660FDB(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FDC(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FDC(mut source: reg64, mut r: i32) { // paddusb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -4438,13 +4348,13 @@ pub unsafe fn instr_0FDC(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe fn instr_0FDC_reg(mut r1: i32, mut r2: i32) -> () { instr_0FDC(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FDC_reg(mut r1: i32, mut r2: i32) { instr_0FDC(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FDC_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FDC_mem(mut addr: i32, mut r: i32) { instr_0FDC(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FDC(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FDC(mut source: reg128, mut r: i32) { // paddusb xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -4459,15 +4369,13 @@ pub unsafe fn instr_660FDC(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FDC_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FDC(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FDC_reg(mut r1: i32, mut r2: i32) { instr_660FDC(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FDC_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FDC_mem(mut addr: i32, mut r: i32) { instr_660FDC(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FDD(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FDD(mut source: reg64, mut r: i32) { // paddusw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = @@ -4483,13 +4391,13 @@ pub unsafe fn instr_0FDD(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe fn instr_0FDD_reg(mut r1: i32, mut r2: i32) -> () { instr_0FDD(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FDD_reg(mut r1: i32, mut r2: i32) { instr_0FDD(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FDD_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FDD_mem(mut addr: i32, mut r: i32) { instr_0FDD(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FDD(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FDD(mut source: reg128, mut r: i32) { // paddusw xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -4510,15 +4418,13 @@ pub unsafe fn instr_660FDD(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_660FDD_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FDD(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FDD_reg(mut r1: i32, mut r2: i32) { instr_660FDD(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FDD_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FDD_mem(mut addr: i32, mut r: i32) { instr_660FDD(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FDE(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FDE(mut source: reg64, mut r: i32) { // pmaxub mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; @@ -4536,13 +4442,13 @@ pub unsafe fn instr_0FDE(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe fn instr_0FDE_reg(mut r1: i32, mut r2: i32) -> () { instr_0FDE(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FDE_reg(mut r1: i32, mut r2: i32) { instr_0FDE(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FDE_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FDE_mem(mut addr: i32, mut r: i32) { instr_0FDE(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FDE(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FDE(mut source: reg128, mut r: i32) { // pmaxub xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -4561,15 +4467,13 @@ pub unsafe fn instr_660FDE(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FDE_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FDE(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FDE_reg(mut r1: i32, mut r2: i32) { instr_660FDE(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FDE_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FDE_mem(mut addr: i32, mut r: i32) { instr_660FDE(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FDF(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FDF(mut source: reg64, mut r: i32) { // pandn mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -4579,27 +4483,25 @@ pub unsafe fn instr_0FDF(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe fn instr_0FDF_reg(mut r1: i32, mut r2: i32) -> () { instr_0FDF(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FDF_reg(mut r1: i32, mut r2: i32) { instr_0FDF(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FDF_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FDF_mem(mut addr: i32, mut r: i32) { instr_0FDF(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FDF(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FDF(mut source: reg128, mut r: i32) { // pandn xmm, xmm/m128 // XXX: Aligned access or #gp pandn_r128(source, r); } #[no_mangle] -pub unsafe fn instr_660FDF_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FDF(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FDF_reg(mut r1: i32, mut r2: i32) { instr_660FDF(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FDF_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FDF_mem(mut addr: i32, mut r: i32) { instr_660FDF(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FE0(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FE0(mut source: reg64, mut r: i32) { // pavgb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -4615,13 +4517,13 @@ pub unsafe fn instr_0FE0(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe fn instr_0FE0_reg(mut r1: i32, mut r2: i32) -> () { instr_0FE0(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FE0_reg(mut r1: i32, mut r2: i32) { instr_0FE0(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FE0_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FE0_mem(mut addr: i32, mut r: i32) { instr_0FE0(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FE0(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FE0(mut source: reg128, mut r: i32) { // pavgb xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -4636,65 +4538,59 @@ pub unsafe fn instr_660FE0(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FE0_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FE0(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FE0_reg(mut r1: i32, mut r2: i32) { instr_660FE0(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FE0_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FE0_mem(mut addr: i32, mut r: i32) { instr_660FE0(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FE1(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FE1(mut source: reg64, mut r: i32) { // psraw mm, mm/m64 psraw_r64(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe fn instr_0FE1_reg(mut r1: i32, mut r2: i32) -> () { instr_0FE1(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FE1_reg(mut r1: i32, mut r2: i32) { instr_0FE1(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FE1_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FE1_mem(mut addr: i32, mut r: i32) { instr_0FE1(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FE1(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FE1(mut source: reg128, mut r: i32) { // psraw xmm, xmm/m128 // XXX: Aligned access or #gp psraw_r128(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe fn instr_660FE1_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FE1(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FE1_reg(mut r1: i32, mut r2: i32) { instr_660FE1(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FE1_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FE1_mem(mut addr: i32, mut r: i32) { instr_660FE1(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FE2(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FE2(mut source: reg64, mut r: i32) { // psrad mm, mm/m64 psrad_r64(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe fn instr_0FE2_reg(mut r1: i32, mut r2: i32) -> () { instr_0FE2(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FE2_reg(mut r1: i32, mut r2: i32) { instr_0FE2(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FE2_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FE2_mem(mut addr: i32, mut r: i32) { instr_0FE2(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FE2(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FE2(mut source: reg128, mut r: i32) { // psrad xmm, xmm/m128 // XXX: Aligned access or #gp psrad_r128(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe fn instr_660FE2_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FE2(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FE2_reg(mut r1: i32, mut r2: i32) { instr_660FE2(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FE2_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FE2_mem(mut addr: i32, mut r: i32) { instr_660FE2(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FE3(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FE3(mut source: reg64, mut r: i32) { // pavgw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); destination.u16_0[0usize] = @@ -4708,13 +4604,13 @@ pub unsafe fn instr_0FE3(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, destination); } #[no_mangle] -pub unsafe fn instr_0FE3_reg(mut r1: i32, mut r2: i32) -> () { instr_0FE3(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FE3_reg(mut r1: i32, mut r2: i32) { instr_0FE3(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FE3_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FE3_mem(mut addr: i32, mut r: i32) { instr_0FE3(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FE3(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FE3(mut source: reg128, mut r: i32) { // pavgw xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -4737,15 +4633,13 @@ pub unsafe fn instr_660FE3(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, destination); } #[no_mangle] -pub unsafe fn instr_660FE3_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FE3(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FE3_reg(mut r1: i32, mut r2: i32) { instr_660FE3(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FE3_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FE3_mem(mut addr: i32, mut r: i32) { instr_660FE3(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FE4(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FE4(mut source: reg64, mut r: i32) { // pmulhuw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); write_mmx64( @@ -4761,13 +4655,13 @@ pub unsafe fn instr_0FE4(mut source: reg64, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_0FE4_reg(mut r1: i32, mut r2: i32) -> () { instr_0FE4(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FE4_reg(mut r1: i32, mut r2: i32) { instr_0FE4(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FE4_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FE4_mem(mut addr: i32, mut r: i32) { instr_0FE4(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FE4(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FE4(mut source: reg128, mut r: i32) { // pmulhuw xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -4792,15 +4686,13 @@ pub unsafe fn instr_660FE4(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_660FE4_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FE4(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FE4_reg(mut r1: i32, mut r2: i32) { instr_660FE4(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FE4_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FE4_mem(mut addr: i32, mut r: i32) { instr_660FE4(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FE5(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FE5(mut source: reg64, mut r: i32) { // pmulhw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: u32 = @@ -4816,13 +4708,13 @@ pub unsafe fn instr_0FE5(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe fn instr_0FE5_reg(mut r1: i32, mut r2: i32) -> () { instr_0FE5(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FE5_reg(mut r1: i32, mut r2: i32) { instr_0FE5(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FE5_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FE5_mem(mut addr: i32, mut r: i32) { instr_0FE5(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FE5(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FE5(mut source: reg128, mut r: i32) { // pmulhw xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -4845,21 +4737,19 @@ pub unsafe fn instr_660FE5(mut source: reg128, mut r: i32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn instr_660FE5_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FE5(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FE5_reg(mut r1: i32, mut r2: i32) { instr_660FE5(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FE5_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FE5_mem(mut addr: i32, mut r: i32) { instr_660FE5(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FE6_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FE6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FE6_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FE6_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660FE6(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FE6(mut source: reg128, mut r: i32) { // cvttpd2dq xmm1, xmm2/m128 let mut result = reg128 { i32_0: [ @@ -4872,16 +4762,14 @@ pub unsafe fn instr_660FE6(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FE6_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FE6_mem(mut addr: i32, mut r: i32) { instr_660FE6(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FE6_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FE6(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FE6_reg(mut r1: i32, mut r2: i32) { instr_660FE6(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20FE6(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_F20FE6(mut source: reg128, mut r: i32) { // cvtpd2dq xmm1, xmm2/m128 let mut result = reg128 { i32_0: [ @@ -4895,16 +4783,14 @@ pub unsafe fn instr_F20FE6(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_F20FE6_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20FE6_mem(mut addr: i32, mut r: i32) { instr_F20FE6(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20FE6_reg(mut r1: i32, mut r2: i32) -> () { - instr_F20FE6(read_xmm128s(r1), r2); -} +pub unsafe fn instr_F20FE6_reg(mut r1: i32, mut r2: i32) { instr_F20FE6(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30FE6(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_F30FE6(mut source: reg64, mut r: i32) { // cvtdq2pd xmm1, xmm2/m64 let mut result: reg128 = reg128 { f64_0: [ @@ -4916,30 +4802,28 @@ pub unsafe fn instr_F30FE6(mut source: reg64, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_F30FE6_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30FE6_mem(mut addr: i32, mut r: i32) { instr_F30FE6(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30FE6_reg(mut r1: i32, mut r2: i32) -> () { - instr_F30FE6(read_xmm64s(r1), r2); -} +pub unsafe fn instr_F30FE6_reg(mut r1: i32, mut r2: i32) { instr_F30FE6(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FE7_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FE7_mem(mut addr: i32, mut r: i32) { // movntq m64, mm mov_r_m64(addr, r); } #[no_mangle] -pub unsafe fn instr_0FE7_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FE7_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660FE7_reg(mut r1: i32, mut r2: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660FE7_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660FE7_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FE7_mem(mut addr: i32, mut r: i32) { // movntdq m128, xmm mov_r_m128(addr, r); } #[no_mangle] -pub unsafe fn instr_0FE8(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FE8(mut source: reg64, mut r: i32) { // psubsb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -4955,13 +4839,13 @@ pub unsafe fn instr_0FE8(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe fn instr_0FE8_reg(mut r1: i32, mut r2: i32) -> () { instr_0FE8(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FE8_reg(mut r1: i32, mut r2: i32) { instr_0FE8(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FE8_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FE8_mem(mut addr: i32, mut r: i32) { instr_0FE8(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FE8(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FE8(mut source: reg128, mut r: i32) { // psubsb xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -4976,15 +4860,13 @@ pub unsafe fn instr_660FE8(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FE8_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FE8(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FE8_reg(mut r1: i32, mut r2: i32) { instr_660FE8(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FE8_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FE8_mem(mut addr: i32, mut r: i32) { instr_660FE8(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FE9(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FE9(mut source: reg64, mut r: i32) { // psubsw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = @@ -5004,13 +4886,13 @@ pub unsafe fn instr_0FE9(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe fn instr_0FE9_reg(mut r1: i32, mut r2: i32) -> () { instr_0FE9(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FE9_reg(mut r1: i32, mut r2: i32) { instr_0FE9(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FE9_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FE9_mem(mut addr: i32, mut r: i32) { instr_0FE9(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FE9(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FE9(mut source: reg128, mut r: i32) { // psubsw xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -5037,15 +4919,13 @@ pub unsafe fn instr_660FE9(mut source: reg128, mut r: i32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn instr_660FE9_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FE9(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FE9_reg(mut r1: i32, mut r2: i32) { instr_660FE9(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FE9_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FE9_mem(mut addr: i32, mut r: i32) { instr_660FE9(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FEA(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FEA(mut source: reg64, mut r: i32) { // pminsw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; @@ -5063,13 +4943,13 @@ pub unsafe fn instr_0FEA(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe fn instr_0FEA_reg(mut r1: i32, mut r2: i32) -> () { instr_0FEA(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FEA_reg(mut r1: i32, mut r2: i32) { instr_0FEA(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FEA_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FEA_mem(mut addr: i32, mut r: i32) { instr_0FEA(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FEA(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FEA(mut source: reg128, mut r: i32) { // pminsw xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -5088,15 +4968,13 @@ pub unsafe fn instr_660FEA(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FEA_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FEA(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FEA_reg(mut r1: i32, mut r2: i32) { instr_660FEA(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FEA_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FEA_mem(mut addr: i32, mut r: i32) { instr_660FEA(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FEB(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FEB(mut source: reg64, mut r: i32) { // por mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -5106,27 +4984,25 @@ pub unsafe fn instr_0FEB(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe fn instr_0FEB_reg(mut r1: i32, mut r2: i32) -> () { instr_0FEB(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FEB_reg(mut r1: i32, mut r2: i32) { instr_0FEB(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FEB_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FEB_mem(mut addr: i32, mut r: i32) { instr_0FEB(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FEB(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FEB(mut source: reg128, mut r: i32) { // por xmm, xmm/m128 // XXX: Aligned access or #gp por_r128(source, r); } #[no_mangle] -pub unsafe fn instr_660FEB_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FEB(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FEB_reg(mut r1: i32, mut r2: i32) { instr_660FEB(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FEB_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FEB_mem(mut addr: i32, mut r: i32) { instr_660FEB(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FEC(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FEC(mut source: reg64, mut r: i32) { // paddsb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -5142,13 +5018,13 @@ pub unsafe fn instr_0FEC(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe fn instr_0FEC_reg(mut r1: i32, mut r2: i32) -> () { instr_0FEC(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FEC_reg(mut r1: i32, mut r2: i32) { instr_0FEC(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FEC_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FEC_mem(mut addr: i32, mut r: i32) { instr_0FEC(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FEC(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FEC(mut source: reg128, mut r: i32) { // paddsb xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -5163,15 +5039,13 @@ pub unsafe fn instr_660FEC(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FEC_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FEC(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FEC_reg(mut r1: i32, mut r2: i32) { instr_660FEC(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FEC_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FEC_mem(mut addr: i32, mut r: i32) { instr_660FEC(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FED(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FED(mut source: reg64, mut r: i32) { // paddsw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = @@ -5191,13 +5065,13 @@ pub unsafe fn instr_0FED(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe fn instr_0FED_reg(mut r1: i32, mut r2: i32) -> () { instr_0FED(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FED_reg(mut r1: i32, mut r2: i32) { instr_0FED(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FED_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FED_mem(mut addr: i32, mut r: i32) { instr_0FED(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FED(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FED(mut source: reg128, mut r: i32) { // paddsw xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -5224,15 +5098,13 @@ pub unsafe fn instr_660FED(mut source: reg128, mut r: i32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn instr_660FED_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FED(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FED_reg(mut r1: i32, mut r2: i32) { instr_660FED(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FED_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FED_mem(mut addr: i32, mut r: i32) { instr_660FED(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FEE(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FEE(mut source: reg64, mut r: i32) { // pmaxsw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; @@ -5250,13 +5122,13 @@ pub unsafe fn instr_0FEE(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe fn instr_0FEE_reg(mut r1: i32, mut r2: i32) -> () { instr_0FEE(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FEE_reg(mut r1: i32, mut r2: i32) { instr_0FEE(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FEE_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FEE_mem(mut addr: i32, mut r: i32) { instr_0FEE(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FEE(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FEE(mut source: reg128, mut r: i32) { // pmaxsw xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -5275,15 +5147,13 @@ pub unsafe fn instr_660FEE(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FEE_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FEE(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FEE_reg(mut r1: i32, mut r2: i32) { instr_660FEE(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FEE_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FEE_mem(mut addr: i32, mut r: i32) { instr_660FEE(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FEF(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FEF(mut source: reg64, mut r: i32) { // pxor mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -5293,104 +5163,96 @@ pub unsafe fn instr_0FEF(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe fn instr_0FEF_reg(mut r1: i32, mut r2: i32) -> () { instr_0FEF(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FEF_reg(mut r1: i32, mut r2: i32) { instr_0FEF(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FEF_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FEF_mem(mut addr: i32, mut r: i32) { instr_0FEF(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FEF(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FEF(mut source: reg128, mut r: i32) { // pxor xmm, xmm/m128 // XXX: Aligned access or #gp pxor_r128(source, r); } #[no_mangle] -pub unsafe fn instr_660FEF_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FEF(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FEF_reg(mut r1: i32, mut r2: i32) { instr_660FEF(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FEF_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FEF_mem(mut addr: i32, mut r: i32) { instr_660FEF(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FF0() -> () { unimplemented_sse(); } +pub unsafe fn instr_0FF0() { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_0FF1(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FF1(mut source: reg64, mut r: i32) { // psllw mm, mm/m64 psllw_r64(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe fn instr_0FF1_reg(mut r1: i32, mut r2: i32) -> () { instr_0FF1(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FF1_reg(mut r1: i32, mut r2: i32) { instr_0FF1(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FF1_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FF1_mem(mut addr: i32, mut r: i32) { instr_0FF1(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FF1(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FF1(mut source: reg128, mut r: i32) { // psllw xmm, xmm/m128 // XXX: Aligned access or #gp psllw_r128(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe fn instr_660FF1_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FF1(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FF1_reg(mut r1: i32, mut r2: i32) { instr_660FF1(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FF1_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FF1_mem(mut addr: i32, mut r: i32) { instr_660FF1(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FF2(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FF2(mut source: reg64, mut r: i32) { // pslld mm, mm/m64 pslld_r64(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe fn instr_0FF2_reg(mut r1: i32, mut r2: i32) -> () { instr_0FF2(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FF2_reg(mut r1: i32, mut r2: i32) { instr_0FF2(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FF2_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FF2_mem(mut addr: i32, mut r: i32) { instr_0FF2(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FF2(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FF2(mut source: reg128, mut r: i32) { // pslld xmm, xmm/m128 // XXX: Aligned access or #gp pslld_r128(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe fn instr_660FF2_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FF2(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FF2_reg(mut r1: i32, mut r2: i32) { instr_660FF2(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FF2_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FF2_mem(mut addr: i32, mut r: i32) { instr_660FF2(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FF3(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FF3(mut source: reg64, mut r: i32) { // psllq mm, mm/m64 psllq_r64(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe fn instr_0FF3_reg(mut r1: i32, mut r2: i32) -> () { instr_0FF3(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FF3_reg(mut r1: i32, mut r2: i32) { instr_0FF3(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FF3_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FF3_mem(mut addr: i32, mut r: i32) { instr_0FF3(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FF3(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FF3(mut source: reg128, mut r: i32) { // psllq xmm, xmm/m128 // XXX: Aligned access or #gp psllq_r128(r, source.u32_0[0usize]); } #[no_mangle] -pub unsafe fn instr_660FF3_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FF3(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FF3_reg(mut r1: i32, mut r2: i32) { instr_660FF3(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FF3_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FF3_mem(mut addr: i32, mut r: i32) { instr_660FF3(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FF4(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FF4(mut source: reg64, mut r: i32) { // pmuludq mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); destination.u64_0[0usize] = @@ -5398,13 +5260,13 @@ pub unsafe fn instr_0FF4(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, destination); } #[no_mangle] -pub unsafe fn instr_0FF4_reg(mut r1: i32, mut r2: i32) -> () { instr_0FF4(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FF4_reg(mut r1: i32, mut r2: i32) { instr_0FF4(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FF4_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FF4_mem(mut addr: i32, mut r: i32) { instr_0FF4(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FF4(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FF4(mut source: reg128, mut r: i32) { // pmuludq xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -5415,15 +5277,13 @@ pub unsafe fn instr_660FF4(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, destination); } #[no_mangle] -pub unsafe fn instr_660FF4_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FF4(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FF4_reg(mut r1: i32, mut r2: i32) { instr_660FF4(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FF4_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FF4_mem(mut addr: i32, mut r: i32) { instr_660FF4(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FF5(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FF5(mut source: reg64, mut r: i32) { // pmaddwd mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut mul0: i32 = destination.i16_0[0usize] as i32 * source.i16_0[0usize] as i32; @@ -5435,13 +5295,13 @@ pub unsafe fn instr_0FF5(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe fn instr_0FF5_reg(mut r1: i32, mut r2: i32) -> () { instr_0FF5(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FF5_reg(mut r1: i32, mut r2: i32) { instr_0FF5(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FF5_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FF5_mem(mut addr: i32, mut r: i32) { instr_0FF5(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FF5(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FF5(mut source: reg128, mut r: i32) { // pmaddwd xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -5456,15 +5316,13 @@ pub unsafe fn instr_660FF5(mut source: reg128, mut r: i32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn instr_660FF5_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FF5(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FF5_reg(mut r1: i32, mut r2: i32) { instr_660FF5(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FF5_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FF5_mem(mut addr: i32, mut r: i32) { instr_660FF5(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FF6(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FF6(mut source: reg64, mut r: i32) { // psadbw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut sum: u32 = 0i32 as u32; @@ -5478,13 +5336,13 @@ pub unsafe fn instr_0FF6(mut source: reg64, mut r: i32) -> () { write_mmx64(r, sum as i32, 0i32); } #[no_mangle] -pub unsafe fn instr_0FF6_reg(mut r1: i32, mut r2: i32) -> () { instr_0FF6(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FF6_reg(mut r1: i32, mut r2: i32) { instr_0FF6(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FF6_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FF6_mem(mut addr: i32, mut r: i32) { instr_0FF6(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FF6(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FF6(mut source: reg128, mut r: i32) { // psadbw xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -5505,17 +5363,15 @@ pub unsafe fn instr_660FF6(mut source: reg128, mut r: i32) -> () { write_xmm128(r, sum0 as i32, 0i32, sum1 as i32, 0i32); } #[no_mangle] -pub unsafe fn instr_660FF6_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FF6(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FF6_reg(mut r1: i32, mut r2: i32) { instr_660FF6(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FF6_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FF6_mem(mut addr: i32, mut r: i32) { instr_660FF6(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FF7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_0FF7_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FF7_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_0FF7_reg(mut r1: i32, mut r2: i32) { // maskmovq mm, mm let mut source: reg64 = read_mmx64s(r2); let mut mask: reg64 = read_mmx64s(r1); @@ -5533,9 +5389,9 @@ pub unsafe fn instr_0FF7_reg(mut r1: i32, mut r2: i32) -> () { } } #[no_mangle] -pub unsafe fn instr_660FF7_mem(mut addr: i32, mut r: i32) -> () { trigger_ud(); } +pub unsafe fn instr_660FF7_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660FF7_reg(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn instr_660FF7_reg(mut r1: i32, mut r2: i32) { // maskmovdqu xmm, xmm let mut source: reg128 = read_xmm128s(r2); let mut mask: reg128 = read_xmm128s(r1); @@ -5553,7 +5409,7 @@ pub unsafe fn instr_660FF7_reg(mut r1: i32, mut r2: i32) -> () { } } #[no_mangle] -pub unsafe fn instr_0FF8(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FF8(mut source: reg64, mut r: i32) { // psubb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -5568,13 +5424,13 @@ pub unsafe fn instr_0FF8(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe fn instr_0FF8_reg(mut r1: i32, mut r2: i32) -> () { instr_0FF8(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FF8_reg(mut r1: i32, mut r2: i32) { instr_0FF8(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FF8_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FF8_mem(mut addr: i32, mut r: i32) { instr_0FF8(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FF8(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FF8(mut source: reg128, mut r: i32) { // psubb xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -5590,15 +5446,13 @@ pub unsafe fn instr_660FF8(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FF8_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FF8(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FF8_reg(mut r1: i32, mut r2: i32) { instr_660FF8(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FF8_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FF8_mem(mut addr: i32, mut r: i32) { instr_660FF8(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FF9(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FF9(mut source: reg64, mut r: i32) { // psubw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = @@ -5616,13 +5470,13 @@ pub unsafe fn instr_0FF9(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe fn instr_0FF9_reg(mut r1: i32, mut r2: i32) -> () { instr_0FF9(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FF9_reg(mut r1: i32, mut r2: i32) { instr_0FF9(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FF9_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FF9_mem(mut addr: i32, mut r: i32) { instr_0FF9(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FF9(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FF9(mut source: reg128, mut r: i32) { // psubw xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -5639,15 +5493,13 @@ pub unsafe fn instr_660FF9(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FF9_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FF9(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FF9_reg(mut r1: i32, mut r2: i32) { instr_660FF9(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FF9_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FF9_mem(mut addr: i32, mut r: i32) { instr_660FF9(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FFA(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FFA(mut source: reg64, mut r: i32) { // psubd mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); write_mmx64( @@ -5657,13 +5509,13 @@ pub unsafe fn instr_0FFA(mut source: reg64, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_0FFA_reg(mut r1: i32, mut r2: i32) -> () { instr_0FFA(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FFA_reg(mut r1: i32, mut r2: i32) { instr_0FFA(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FFA_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FFA_mem(mut addr: i32, mut r: i32) { instr_0FFA(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FFA(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FFA(mut source: reg128, mut r: i32) { // psubd xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -5676,28 +5528,26 @@ pub unsafe fn instr_660FFA(mut source: reg128, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn instr_660FFA_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FFA(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FFA_reg(mut r1: i32, mut r2: i32) { instr_660FFA(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FFA_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FFA_mem(mut addr: i32, mut r: i32) { instr_660FFA(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FFB(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FFB(mut source: reg64, mut r: i32) { // psubq mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); destination.u64_0[0usize] = destination.u64_0[0usize].wrapping_sub(source.u64_0[0usize]); write_mmx_reg64(r, destination); } #[no_mangle] -pub unsafe fn instr_0FFB_reg(mut r1: i32, mut r2: i32) -> () { instr_0FFB(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FFB_reg(mut r1: i32, mut r2: i32) { instr_0FFB(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FFB_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FFB_mem(mut addr: i32, mut r: i32) { instr_0FFB(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FFB(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FFB(mut source: reg128, mut r: i32) { // psubq xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -5706,15 +5556,13 @@ pub unsafe fn instr_660FFB(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, destination); } #[no_mangle] -pub unsafe fn instr_660FFB_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FFB(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FFB_reg(mut r1: i32, mut r2: i32) { instr_660FFB(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FFB_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FFB_mem(mut addr: i32, mut r: i32) { instr_660FFB(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FFC(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FFC(mut source: reg64, mut r: i32) { // paddb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { @@ -5729,13 +5577,13 @@ pub unsafe fn instr_0FFC(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe fn instr_0FFC_reg(mut r1: i32, mut r2: i32) -> () { instr_0FFC(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FFC_reg(mut r1: i32, mut r2: i32) { instr_0FFC(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FFC_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FFC_mem(mut addr: i32, mut r: i32) { instr_0FFC(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FFC(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FFC(mut source: reg128, mut r: i32) { // paddb xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -5751,15 +5599,13 @@ pub unsafe fn instr_660FFC(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FFC_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FFC(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FFC_reg(mut r1: i32, mut r2: i32) { instr_660FFC(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FFC_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FFC_mem(mut addr: i32, mut r: i32) { instr_660FFC(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FFD(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FFD(mut source: reg64, mut r: i32) { // paddw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = @@ -5773,13 +5619,13 @@ pub unsafe fn instr_0FFD(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe fn instr_0FFD_reg(mut r1: i32, mut r2: i32) -> () { instr_0FFD(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FFD_reg(mut r1: i32, mut r2: i32) { instr_0FFD(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FFD_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FFD_mem(mut addr: i32, mut r: i32) { instr_0FFD(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FFD(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FFD(mut source: reg128, mut r: i32) { // paddw xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -5796,15 +5642,13 @@ pub unsafe fn instr_660FFD(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FFD_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FFD(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FFD_reg(mut r1: i32, mut r2: i32) { instr_660FFD(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FFD_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FFD_mem(mut addr: i32, mut r: i32) { instr_660FFD(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FFE(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0FFE(mut source: reg64, mut r: i32) { // paddd mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut low: i32 = destination.u32_0[0usize].wrapping_add(source.u32_0[0usize]) as i32; @@ -5812,13 +5656,13 @@ pub unsafe fn instr_0FFE(mut source: reg64, mut r: i32) -> () { write_mmx64(r, low, high); } #[no_mangle] -pub unsafe fn instr_0FFE_reg(mut r1: i32, mut r2: i32) -> () { instr_0FFE(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FFE_reg(mut r1: i32, mut r2: i32) { instr_0FFE(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FFE_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0FFE_mem(mut addr: i32, mut r: i32) { instr_0FFE(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FFE(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660FFE(mut source: reg128, mut r: i32) { // paddd xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -5829,42 +5673,40 @@ pub unsafe fn instr_660FFE(mut source: reg128, mut r: i32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn instr_660FFE_reg(mut r1: i32, mut r2: i32) -> () { - instr_660FFE(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660FFE_reg(mut r1: i32, mut r2: i32) { instr_660FFE(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FFE_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660FFE_mem(mut addr: i32, mut r: i32) { instr_660FFE(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FFF() -> () { +pub unsafe fn instr_0FFF() { // Windows 98 dbg_log!("#ud: 0F FF"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr_F30F16_reg(mut r1: i32, mut r2: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_F30F16_reg(mut r1: i32, mut r2: i32) { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_F30F16_mem(mut addr: i32, mut r: i32) -> () { unimplemented_sse(); } +pub unsafe fn instr_F30F16_mem(mut addr: i32, mut r: i32) { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_0F19_reg(mut r1: i32, mut r2: i32) -> () {} +pub unsafe fn instr_0F19_reg(mut r1: i32, mut r2: i32) {} #[no_mangle] -pub unsafe fn instr_0F19_mem(mut addr: i32, mut r: i32) -> () {} +pub unsafe fn instr_0F19_mem(mut addr: i32, mut r: i32) {} #[no_mangle] -pub unsafe fn instr_0F1C_reg(mut r1: i32, mut r2: i32) -> () {} +pub unsafe fn instr_0F1C_reg(mut r1: i32, mut r2: i32) {} #[no_mangle] -pub unsafe fn instr_0F1C_mem(mut addr: i32, mut r: i32) -> () {} +pub unsafe fn instr_0F1C_mem(mut addr: i32, mut r: i32) {} #[no_mangle] -pub unsafe fn instr_0F1D_reg(mut r1: i32, mut r2: i32) -> () {} +pub unsafe fn instr_0F1D_reg(mut r1: i32, mut r2: i32) {} #[no_mangle] -pub unsafe fn instr_0F1D_mem(mut addr: i32, mut r: i32) -> () {} +pub unsafe fn instr_0F1D_mem(mut addr: i32, mut r: i32) {} #[no_mangle] -pub unsafe fn instr_0F1E_reg(mut r1: i32, mut r2: i32) -> () {} +pub unsafe fn instr_0F1E_reg(mut r1: i32, mut r2: i32) {} #[no_mangle] -pub unsafe fn instr_0F1E_mem(mut addr: i32, mut r: i32) -> () {} +pub unsafe fn instr_0F1E_mem(mut addr: i32, mut r: i32) {} #[no_mangle] -pub unsafe fn instr_0F2A(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F2A(mut source: reg64, mut r: i32) { // cvtpi2ps xmm, mm/m64 // XXX: The non-memory variant causes a transition from x87 FPU to MMX technology operation // Note: Casts here can fail @@ -5874,13 +5716,13 @@ pub unsafe fn instr_0F2A(mut source: reg64, mut r: i32) -> () { write_xmm64(r, result); } #[no_mangle] -pub unsafe fn instr_0F2A_reg(mut r1: i32, mut r2: i32) -> () { instr_0F2A(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F2A_reg(mut r1: i32, mut r2: i32) { instr_0F2A(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F2A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F2A_mem(mut addr: i32, mut r: i32) { instr_0F2A(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F2A(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_660F2A(mut source: reg64, mut r: i32) { // cvtpi2pd xmm, xmm/m64 // XXX: The non-memory variant causes a transition from x87 FPU to MMX technology operation // These casts can't fail @@ -5890,15 +5732,13 @@ pub unsafe fn instr_660F2A(mut source: reg64, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F2A_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F2A(read_mmx64s(r1), r2); -} +pub unsafe fn instr_660F2A_reg(mut r1: i32, mut r2: i32) { instr_660F2A(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F2A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F2A_mem(mut addr: i32, mut r: i32) { instr_660F2A(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20F2A(mut source: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F2A(mut source: i32, mut r: i32) { // cvtsi2sd xmm, r32/m32 // This cast can't fail let mut result: reg64 = reg64 { @@ -5907,27 +5747,27 @@ pub unsafe fn instr_F20F2A(mut source: i32, mut r: i32) -> () { write_xmm64(r, result); } #[no_mangle] -pub unsafe fn instr_F20F2A_reg(mut r1: i32, mut r2: i32) -> () { instr_F20F2A(read_reg32(r1), r2); } +pub unsafe fn instr_F20F2A_reg(mut r1: i32, mut r2: i32) { instr_F20F2A(read_reg32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F2A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F2A_mem(mut addr: i32, mut r: i32) { instr_F20F2A(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F2A(mut source: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F2A(mut source: i32, mut r: i32) { // cvtsi2ss xmm, r/m32 // Note: This cast can fail let mut result: f32 = source as f32; write_xmm_f32(r, result); } #[no_mangle] -pub unsafe fn instr_F30F2A_reg(mut r1: i32, mut r2: i32) -> () { instr_F30F2A(read_reg32(r1), r2); } +pub unsafe fn instr_F30F2A_reg(mut r1: i32, mut r2: i32) { instr_F30F2A(read_reg32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F2A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F2A_mem(mut addr: i32, mut r: i32) { instr_F30F2A(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F2D(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F2D(mut source: reg64, mut r: i32) { // cvtps2pi mm, xmm/m64 let result = reg64 { i32_0: [ @@ -5938,14 +5778,14 @@ pub unsafe fn instr_0F2D(mut source: reg64, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe fn instr_0F2D_reg(mut r1: i32, mut r2: i32) -> () { instr_0F2D(read_xmm64s(r1), r2); } +pub unsafe fn instr_0F2D_reg(mut r1: i32, mut r2: i32) { instr_0F2D(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F2D_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F2D_mem(mut addr: i32, mut r: i32) { instr_0F2D(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F2D(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F2D(mut source: reg128, mut r: i32) { // cvtpd2pi mm, xmm/m128 let result = reg64 { i32_0: [ @@ -5956,42 +5796,36 @@ pub unsafe fn instr_660F2D(mut source: reg128, mut r: i32) -> () { write_mmx_reg64(r, result); } #[no_mangle] -pub unsafe fn instr_660F2D_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F2D(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F2D_reg(mut r1: i32, mut r2: i32) { instr_660F2D(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F2D_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F2D_mem(mut addr: i32, mut r: i32) { instr_660F2D(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20F2D(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_F20F2D(mut source: reg64, mut r: i32) { // cvtsd2si r32, xmm/m64 write_reg32(r, sse_convert_f64_to_i32(source.f64_0[0usize].round())); } #[no_mangle] -pub unsafe fn instr_F20F2D_reg(mut r1: i32, mut r2: i32) -> () { - instr_F20F2D(read_xmm64s(r1), r2); -} +pub unsafe fn instr_F20F2D_reg(mut r1: i32, mut r2: i32) { instr_F20F2D(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F2D_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F2D_mem(mut addr: i32, mut r: i32) { instr_F20F2D(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F2D(mut source: f32, mut r: i32) -> () { +pub unsafe fn instr_F30F2D(mut source: f32, mut r: i32) { // cvtss2si r32, xmm1/m32 write_reg32(r, sse_convert_f32_to_i32(source.round())); } #[no_mangle] -pub unsafe fn instr_F30F2D_reg(mut r1: i32, mut r2: i32) -> () { - instr_F30F2D(read_xmm_f32(r1), r2); -} +pub unsafe fn instr_F30F2D_reg(mut r1: i32, mut r2: i32) { instr_F30F2D(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F2D_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F2D_mem(mut addr: i32, mut r: i32) { instr_F30F2D(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_0F51(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F51(mut source: reg128, mut r: i32) { // sqrtps xmm, xmm/mem128 let mut result: reg128 = reg128 { f32_0: [ @@ -6004,13 +5838,13 @@ pub unsafe fn instr_0F51(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0F51_reg(mut r1: i32, mut r2: i32) -> () { instr_0F51(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F51_reg(mut r1: i32, mut r2: i32) { instr_0F51(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F51_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F51_mem(mut addr: i32, mut r: i32) { instr_0F51(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F51(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F51(mut source: reg128, mut r: i32) { // sqrtpd xmm, xmm/mem128 let mut result: reg128 = reg128 { f64_0: [source.f64_0[0usize].sqrt(), source.f64_0[1usize].sqrt()], @@ -6018,15 +5852,13 @@ pub unsafe fn instr_660F51(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F51_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F51(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F51_reg(mut r1: i32, mut r2: i32) { instr_660F51(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F51_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F51_mem(mut addr: i32, mut r: i32) { instr_660F51(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20F51(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_F20F51(mut source: reg64, mut r: i32) { // sqrtsd xmm, xmm/mem64 let mut result: reg64 = reg64 { f64_0: [source.f64_0[0usize].sqrt()], @@ -6034,29 +5866,25 @@ pub unsafe fn instr_F20F51(mut source: reg64, mut r: i32) -> () { write_xmm64(r, result); } #[no_mangle] -pub unsafe fn instr_F20F51_reg(mut r1: i32, mut r2: i32) -> () { - instr_F20F51(read_xmm64s(r1), r2); -} +pub unsafe fn instr_F20F51_reg(mut r1: i32, mut r2: i32) { instr_F20F51(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F51_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F51_mem(mut addr: i32, mut r: i32) { instr_F20F51(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F51(mut source: f32, mut r: i32) -> () { +pub unsafe fn instr_F30F51(mut source: f32, mut r: i32) { // sqrtss xmm, xmm/mem32 write_xmm_f32(r, source.sqrt()); } #[no_mangle] -pub unsafe fn instr_F30F51_reg(mut r1: i32, mut r2: i32) -> () { - instr_F30F51(read_xmm_f32(r1), r2); -} +pub unsafe fn instr_F30F51_reg(mut r1: i32, mut r2: i32) { instr_F30F51(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F51_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F51_mem(mut addr: i32, mut r: i32) { instr_F30F51(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_0F52(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F52(mut source: reg128, mut r: i32) { // rcpps xmm1, xmm2/m128 let mut result: reg128 = reg128 { f32_0: [ @@ -6069,27 +5897,25 @@ pub unsafe fn instr_0F52(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0F52_reg(mut r1: i32, mut r2: i32) -> () { instr_0F52(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F52_reg(mut r1: i32, mut r2: i32) { instr_0F52(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F52_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F52_mem(mut addr: i32, mut r: i32) { instr_0F52(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F52(mut source: f32, mut r: i32) -> () { +pub unsafe fn instr_F30F52(mut source: f32, mut r: i32) { // rsqrtss xmm1, xmm2/m32 write_xmm_f32(r, 1i32 as f32 / source.sqrt()); } #[no_mangle] -pub unsafe fn instr_F30F52_reg(mut r1: i32, mut r2: i32) -> () { - instr_F30F52(read_xmm_f32(r1), r2); -} +pub unsafe fn instr_F30F52_reg(mut r1: i32, mut r2: i32) { instr_F30F52(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F52_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F52_mem(mut addr: i32, mut r: i32) { instr_F30F52(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_0F53(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F53(mut source: reg128, mut r: i32) { // rcpps xmm, xmm/m128 let mut result: reg128 = reg128 { f32_0: [ @@ -6102,27 +5928,25 @@ pub unsafe fn instr_0F53(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0F53_reg(mut r1: i32, mut r2: i32) -> () { instr_0F53(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F53_reg(mut r1: i32, mut r2: i32) { instr_0F53(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F53_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F53_mem(mut addr: i32, mut r: i32) { instr_0F53(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F53(mut source: f32, mut r: i32) -> () { +pub unsafe fn instr_F30F53(mut source: f32, mut r: i32) { // rcpss xmm, xmm/m32 write_xmm_f32(r, 1i32 as f32 / source); } #[no_mangle] -pub unsafe fn instr_F30F53_reg(mut r1: i32, mut r2: i32) -> () { - instr_F30F53(read_xmm_f32(r1), r2); -} +pub unsafe fn instr_F30F53_reg(mut r1: i32, mut r2: i32) { instr_F30F53(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F53_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F53_mem(mut addr: i32, mut r: i32) { instr_F30F53(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_0F58(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F58(mut source: reg128, mut r: i32) { // addps xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6136,13 +5960,13 @@ pub unsafe fn instr_0F58(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0F58_reg(mut r1: i32, mut r2: i32) -> () { instr_0F58(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F58_reg(mut r1: i32, mut r2: i32) { instr_0F58(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F58_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F58_mem(mut addr: i32, mut r: i32) { instr_0F58(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F58(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F58(mut source: reg128, mut r: i32) { // addpd xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6154,15 +5978,13 @@ pub unsafe fn instr_660F58(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F58_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F58(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F58_reg(mut r1: i32, mut r2: i32) { instr_660F58(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F58_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F58_mem(mut addr: i32, mut r: i32) { instr_660F58(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20F58(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_F20F58(mut source: reg64, mut r: i32) { // addsd xmm, xmm/mem64 let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { @@ -6171,31 +5993,27 @@ pub unsafe fn instr_F20F58(mut source: reg64, mut r: i32) -> () { write_xmm64(r, result); } #[no_mangle] -pub unsafe fn instr_F20F58_reg(mut r1: i32, mut r2: i32) -> () { - instr_F20F58(read_xmm64s(r1), r2); -} +pub unsafe fn instr_F20F58_reg(mut r1: i32, mut r2: i32) { instr_F20F58(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F58_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F58_mem(mut addr: i32, mut r: i32) { instr_F20F58(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F58(mut source: f32, mut r: i32) -> () { +pub unsafe fn instr_F30F58(mut source: f32, mut r: i32) { // addss xmm, xmm/mem32 let mut destination: f32 = read_xmm_f32(r); let mut result: f32 = source + destination; write_xmm_f32(r, result); } #[no_mangle] -pub unsafe fn instr_F30F58_reg(mut r1: i32, mut r2: i32) -> () { - instr_F30F58(read_xmm_f32(r1), r2); -} +pub unsafe fn instr_F30F58_reg(mut r1: i32, mut r2: i32) { instr_F30F58(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F58_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F58_mem(mut addr: i32, mut r: i32) { instr_F30F58(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_0F59(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F59(mut source: reg128, mut r: i32) { // mulps xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6209,13 +6027,13 @@ pub unsafe fn instr_0F59(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0F59_reg(mut r1: i32, mut r2: i32) -> () { instr_0F59(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F59_reg(mut r1: i32, mut r2: i32) { instr_0F59(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F59_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F59_mem(mut addr: i32, mut r: i32) { instr_0F59(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F59(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F59(mut source: reg128, mut r: i32) { // mulpd xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6227,15 +6045,13 @@ pub unsafe fn instr_660F59(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F59_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F59(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F59_reg(mut r1: i32, mut r2: i32) { instr_660F59(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F59_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F59_mem(mut addr: i32, mut r: i32) { instr_660F59(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20F59(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_F20F59(mut source: reg64, mut r: i32) { // mulsd xmm, xmm/mem64 let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { @@ -6244,31 +6060,27 @@ pub unsafe fn instr_F20F59(mut source: reg64, mut r: i32) -> () { write_xmm64(r, result); } #[no_mangle] -pub unsafe fn instr_F20F59_reg(mut r1: i32, mut r2: i32) -> () { - instr_F20F59(read_xmm64s(r1), r2); -} +pub unsafe fn instr_F20F59_reg(mut r1: i32, mut r2: i32) { instr_F20F59(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F59_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F59_mem(mut addr: i32, mut r: i32) { instr_F20F59(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F59(mut source: f32, mut r: i32) -> () { +pub unsafe fn instr_F30F59(mut source: f32, mut r: i32) { // mulss xmm, xmm/mem32 let mut destination: f32 = read_xmm_f32(r); let mut result: f32 = source * destination; write_xmm_f32(r, result); } #[no_mangle] -pub unsafe fn instr_F30F59_reg(mut r1: i32, mut r2: i32) -> () { - instr_F30F59(read_xmm_f32(r1), r2); -} +pub unsafe fn instr_F30F59_reg(mut r1: i32, mut r2: i32) { instr_F30F59(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F59_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F59_mem(mut addr: i32, mut r: i32) { instr_F30F59(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_0F5A(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_0F5A(mut source: reg64, mut r: i32) { // cvtps2pd xmm1, xmm2/m64 let mut result: reg128 = reg128 { f64_0: [source.f32_0[0] as f64, source.f32_0[1] as f64], @@ -6276,13 +6088,13 @@ pub unsafe fn instr_0F5A(mut source: reg64, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0F5A_reg(mut r1: i32, mut r2: i32) -> () { instr_0F5A(read_xmm64s(r1), r2); } +pub unsafe fn instr_0F5A_reg(mut r1: i32, mut r2: i32) { instr_0F5A(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F5A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F5A_mem(mut addr: i32, mut r: i32) { instr_0F5A(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F5A(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F5A(mut source: reg128, mut r: i32) { // cvtpd2ps xmm1, xmm2/m128 let mut result: reg128 = reg128 { // XXX: These conversions are lossy and should round according to the round control @@ -6291,29 +6103,25 @@ pub unsafe fn instr_660F5A(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F5A_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F5A(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F5A_reg(mut r1: i32, mut r2: i32) { instr_660F5A(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F5A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F5A_mem(mut addr: i32, mut r: i32) { instr_660F5A(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20F5A(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_F20F5A(mut source: reg64, mut r: i32) { // cvtsd2ss xmm1, xmm2/m64 // XXX: This conversions is lossy and should round according to the round control write_xmm_f32(r, source.f64_0[0] as f32); } #[no_mangle] -pub unsafe fn instr_F20F5A_reg(mut r1: i32, mut r2: i32) -> () { - instr_F20F5A(read_xmm64s(r1), r2); -} +pub unsafe fn instr_F20F5A_reg(mut r1: i32, mut r2: i32) { instr_F20F5A(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F5A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F5A_mem(mut addr: i32, mut r: i32) { instr_F20F5A(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F5A(mut source: f32, mut r: i32) -> () { +pub unsafe fn instr_F30F5A(mut source: f32, mut r: i32) { // cvtss2sd xmm1, xmm2/m32 let mut result: reg64 = reg64 { f64_0: [source as f64], @@ -6321,16 +6129,14 @@ pub unsafe fn instr_F30F5A(mut source: f32, mut r: i32) -> () { write_xmm64(r, result); } #[no_mangle] -pub unsafe fn instr_F30F5A_reg(mut r1: i32, mut r2: i32) -> () { - instr_F30F5A(read_xmm_f32(r1), r2); -} +pub unsafe fn instr_F30F5A_reg(mut r1: i32, mut r2: i32) { instr_F30F5A(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F5A_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F5A_mem(mut addr: i32, mut r: i32) { instr_F30F5A(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_0F5B(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F5B(mut source: reg128, mut r: i32) { // cvtdq2ps xmm1, xmm2/m128 let mut result: reg128 = reg128 { f32_0: [ @@ -6344,13 +6150,13 @@ pub unsafe fn instr_0F5B(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0F5B_reg(mut r1: i32, mut r2: i32) -> () { instr_0F5B(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F5B_reg(mut r1: i32, mut r2: i32) { instr_0F5B(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F5B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F5B_mem(mut addr: i32, mut r: i32) { instr_0F5B(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F5B(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F5B(mut source: reg128, mut r: i32) { // cvtps2dq xmm1, xmm2/m128 let mut result = reg128 { i32_0: [ @@ -6364,15 +6170,13 @@ pub unsafe fn instr_660F5B(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F5B_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F5B(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F5B_reg(mut r1: i32, mut r2: i32) { instr_660F5B(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F5B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F5B_mem(mut addr: i32, mut r: i32) { instr_660F5B(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F5B(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_F30F5B(mut source: reg128, mut r: i32) { // cvttps2dq xmm1, xmm2/m128 let mut result = reg128 { i32_0: [ @@ -6385,16 +6189,14 @@ pub unsafe fn instr_F30F5B(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_F30F5B_reg(mut r1: i32, mut r2: i32) -> () { - instr_F30F5B(read_xmm128s(r1), r2); -} +pub unsafe fn instr_F30F5B_reg(mut r1: i32, mut r2: i32) { instr_F30F5B(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F5B_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F5B_mem(mut addr: i32, mut r: i32) { instr_F30F5B(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F5C(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F5C(mut source: reg128, mut r: i32) { // subps xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6408,13 +6210,13 @@ pub unsafe fn instr_0F5C(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0F5C_reg(mut r1: i32, mut r2: i32) -> () { instr_0F5C(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F5C_reg(mut r1: i32, mut r2: i32) { instr_0F5C(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F5C_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F5C_mem(mut addr: i32, mut r: i32) { instr_0F5C(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F5C(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F5C(mut source: reg128, mut r: i32) { // subpd xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6426,15 +6228,13 @@ pub unsafe fn instr_660F5C(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F5C_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F5C(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F5C_reg(mut r1: i32, mut r2: i32) { instr_660F5C(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F5C_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F5C_mem(mut addr: i32, mut r: i32) { instr_660F5C(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20F5C(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_F20F5C(mut source: reg64, mut r: i32) { // subsd xmm, xmm/mem64 let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { @@ -6443,30 +6243,26 @@ pub unsafe fn instr_F20F5C(mut source: reg64, mut r: i32) -> () { write_xmm64(r, result); } #[no_mangle] -pub unsafe fn instr_F20F5C_reg(mut r1: i32, mut r2: i32) -> () { - instr_F20F5C(read_xmm64s(r1), r2); -} +pub unsafe fn instr_F20F5C_reg(mut r1: i32, mut r2: i32) { instr_F20F5C(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F5C_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F5C_mem(mut addr: i32, mut r: i32) { instr_F20F5C(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F5C(mut source: f32, mut r: i32) -> () { +pub unsafe fn instr_F30F5C(mut source: f32, mut r: i32) { // subss xmm, xmm/mem32 let mut destination: f32 = read_xmm_f32(r); let mut result: f32 = destination - source; write_xmm_f32(r, result); } #[no_mangle] -pub unsafe fn instr_F30F5C_reg(mut r1: i32, mut r2: i32) -> () { - instr_F30F5C(read_xmm_f32(r1), r2); -} +pub unsafe fn instr_F30F5C_reg(mut r1: i32, mut r2: i32) { instr_F30F5C(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F5C_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F5C_mem(mut addr: i32, mut r: i32) { instr_F30F5C(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_0F5D(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F5D(mut source: reg128, mut r: i32) { // minps xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6492,13 +6288,13 @@ pub unsafe fn instr_0F5D(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0F5D_reg(mut r1: i32, mut r2: i32) -> () { instr_0F5D(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F5D_reg(mut r1: i32, mut r2: i32) { instr_0F5D(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F5D_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F5D_mem(mut addr: i32, mut r: i32) { instr_0F5D(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F5D(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F5D(mut source: reg128, mut r: i32) { // minpd xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6510,15 +6306,13 @@ pub unsafe fn instr_660F5D(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F5D_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F5D(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F5D_reg(mut r1: i32, mut r2: i32) { instr_660F5D(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F5D_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F5D_mem(mut addr: i32, mut r: i32) { instr_660F5D(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20F5D(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_F20F5D(mut source: reg64, mut r: i32) { // minsd xmm, xmm/mem64 let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { @@ -6527,30 +6321,26 @@ pub unsafe fn instr_F20F5D(mut source: reg64, mut r: i32) -> () { write_xmm64(r, result); } #[no_mangle] -pub unsafe fn instr_F20F5D_reg(mut r1: i32, mut r2: i32) -> () { - instr_F20F5D(read_xmm64s(r1), r2); -} +pub unsafe fn instr_F20F5D_reg(mut r1: i32, mut r2: i32) { instr_F20F5D(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F5D_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F5D_mem(mut addr: i32, mut r: i32) { instr_F20F5D(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F5D(mut source: f32, mut r: i32) -> () { +pub unsafe fn instr_F30F5D(mut source: f32, mut r: i32) { // minss xmm, xmm/mem32 let mut destination: f32 = read_xmm_f32(r); let mut result: f32 = sse_min(destination as f64, source as f64) as f32; write_xmm_f32(r, result); } #[no_mangle] -pub unsafe fn instr_F30F5D_reg(mut r1: i32, mut r2: i32) -> () { - instr_F30F5D(read_xmm_f32(r1), r2); -} +pub unsafe fn instr_F30F5D_reg(mut r1: i32, mut r2: i32) { instr_F30F5D(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F5D_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F5D_mem(mut addr: i32, mut r: i32) { instr_F30F5D(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_0F5E(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F5E(mut source: reg128, mut r: i32) { // divps xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6564,13 +6354,13 @@ pub unsafe fn instr_0F5E(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0F5E_reg(mut r1: i32, mut r2: i32) -> () { instr_0F5E(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F5E_reg(mut r1: i32, mut r2: i32) { instr_0F5E(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F5E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F5E_mem(mut addr: i32, mut r: i32) { instr_0F5E(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F5E(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F5E(mut source: reg128, mut r: i32) { // divpd xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6582,15 +6372,13 @@ pub unsafe fn instr_660F5E(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F5E_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F5E(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F5E_reg(mut r1: i32, mut r2: i32) { instr_660F5E(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F5E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F5E_mem(mut addr: i32, mut r: i32) { instr_660F5E(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20F5E(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_F20F5E(mut source: reg64, mut r: i32) { // divsd xmm, xmm/mem64 let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { @@ -6599,30 +6387,26 @@ pub unsafe fn instr_F20F5E(mut source: reg64, mut r: i32) -> () { write_xmm64(r, result); } #[no_mangle] -pub unsafe fn instr_F20F5E_reg(mut r1: i32, mut r2: i32) -> () { - instr_F20F5E(read_xmm64s(r1), r2); -} +pub unsafe fn instr_F20F5E_reg(mut r1: i32, mut r2: i32) { instr_F20F5E(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F5E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F5E_mem(mut addr: i32, mut r: i32) { instr_F20F5E(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F5E(mut source: f32, mut r: i32) -> () { +pub unsafe fn instr_F30F5E(mut source: f32, mut r: i32) { // divss xmm, xmm/mem32 let mut destination: f32 = read_xmm_f32(r); let mut result: f32 = destination / source; write_xmm_f32(r, result); } #[no_mangle] -pub unsafe fn instr_F30F5E_reg(mut r1: i32, mut r2: i32) -> () { - instr_F30F5E(read_xmm_f32(r1), r2); -} +pub unsafe fn instr_F30F5E_reg(mut r1: i32, mut r2: i32) { instr_F30F5E(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F5E_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F5E_mem(mut addr: i32, mut r: i32) { instr_F30F5E(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_0F5F(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_0F5F(mut source: reg128, mut r: i32) { // maxps xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6648,13 +6432,13 @@ pub unsafe fn instr_0F5F(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0F5F_reg(mut r1: i32, mut r2: i32) -> () { instr_0F5F(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F5F_reg(mut r1: i32, mut r2: i32) { instr_0F5F(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F5F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_0F5F_mem(mut addr: i32, mut r: i32) { instr_0F5F(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F5F(mut source: reg128, mut r: i32) -> () { +pub unsafe fn instr_660F5F(mut source: reg128, mut r: i32) { // maxpd xmm, xmm/mem128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6666,15 +6450,13 @@ pub unsafe fn instr_660F5F(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F5F_reg(mut r1: i32, mut r2: i32) -> () { - instr_660F5F(read_xmm128s(r1), r2); -} +pub unsafe fn instr_660F5F_reg(mut r1: i32, mut r2: i32) { instr_660F5F(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F5F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_660F5F_mem(mut addr: i32, mut r: i32) { instr_660F5F(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20F5F(mut source: reg64, mut r: i32) -> () { +pub unsafe fn instr_F20F5F(mut source: reg64, mut r: i32) { // maxsd xmm, xmm/mem64 let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { @@ -6683,30 +6465,26 @@ pub unsafe fn instr_F20F5F(mut source: reg64, mut r: i32) -> () { write_xmm64(r, result); } #[no_mangle] -pub unsafe fn instr_F20F5F_reg(mut r1: i32, mut r2: i32) -> () { - instr_F20F5F(read_xmm64s(r1), r2); -} +pub unsafe fn instr_F20F5F_reg(mut r1: i32, mut r2: i32) { instr_F20F5F(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F5F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F20F5F_mem(mut addr: i32, mut r: i32) { instr_F20F5F(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F5F(mut source: f32, mut r: i32) -> () { +pub unsafe fn instr_F30F5F(mut source: f32, mut r: i32) { // maxss xmm, xmm/mem32 let mut destination: f32 = read_xmm_f32(r); let mut result: f32 = sse_max(destination as f64, source as f64) as f32; write_xmm_f32(r, result); } #[no_mangle] -pub unsafe fn instr_F30F5F_reg(mut r1: i32, mut r2: i32) -> () { - instr_F30F5F(read_xmm_f32(r1), r2); -} +pub unsafe fn instr_F30F5F_reg(mut r1: i32, mut r2: i32) { instr_F30F5F(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F5F_mem(mut addr: i32, mut r: i32) -> () { +pub unsafe fn instr_F30F5F_mem(mut addr: i32, mut r: i32) { instr_F30F5F(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_0FC2(mut source: reg128, mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_0FC2(mut source: reg128, mut r: i32, mut imm8: i32) { // cmpps xmm, xmm/m128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6760,15 +6538,15 @@ pub unsafe fn instr_0FC2(mut source: reg128, mut r: i32, mut imm8: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { +pub unsafe fn instr_0FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) { instr_0FC2(read_xmm128s(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_0FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr_0FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) { instr_0FC2(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] -pub unsafe fn instr_660FC2(mut source: reg128, mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_660FC2(mut source: reg128, mut r: i32, mut imm8: i32) { // cmppd xmm, xmm/m128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { @@ -6790,15 +6568,15 @@ pub unsafe fn instr_660FC2(mut source: reg128, mut r: i32, mut imm8: i32) -> () write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { +pub unsafe fn instr_660FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) { instr_660FC2(read_xmm128s(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_660FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr_660FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) { instr_660FC2(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] -pub unsafe fn instr_F20FC2(mut source: reg64, mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_F20FC2(mut source: reg64, mut r: i32, mut imm8: i32) { // cmpsd xmm, xmm/m64 let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { @@ -6814,15 +6592,15 @@ pub unsafe fn instr_F20FC2(mut source: reg64, mut r: i32, mut imm8: i32) -> () { write_xmm64(r, result); } #[no_mangle] -pub unsafe fn instr_F20FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { +pub unsafe fn instr_F20FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) { instr_F20FC2(read_xmm64s(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_F20FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr_F20FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) { instr_F20FC2(return_on_pagefault!(safe_read64s(addr)), r, imm); } #[no_mangle] -pub unsafe fn instr_F30FC2(mut source: f32, mut r: i32, mut imm8: i32) -> () { +pub unsafe fn instr_F30FC2(mut source: f32, mut r: i32, mut imm8: i32) { // cmpss xmm, xmm/m32 let mut destination: f32 = read_xmm_f32(r); let mut result: i32 = if 0 != sse_comparison(imm8, destination as f64, source as f64) as i32 { @@ -6834,10 +6612,10 @@ pub unsafe fn instr_F30FC2(mut source: f32, mut r: i32, mut imm8: i32) -> () { write_xmm32(r, result); } #[no_mangle] -pub unsafe fn instr_F30FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) -> () { +pub unsafe fn instr_F30FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) { instr_F30FC2(read_xmm_f32(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_F30FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) -> () { +pub unsafe fn instr_F30FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) { instr_F30FC2(return_on_pagefault!(fpu_load_m32(addr)) as f32, r, imm); } diff --git a/src/rust/cpu2/memory.rs b/src/rust/cpu2/memory.rs index 4ce7347a..18b1b793 100644 --- a/src/rust/cpu2/memory.rs +++ b/src/rust/cpu2/memory.rs @@ -124,7 +124,7 @@ pub unsafe fn read128(mut addr: u32) -> reg128 { return value; } #[no_mangle] -pub unsafe fn write8(mut addr: u32, mut value: i32) -> () { +pub unsafe fn write8(mut addr: u32, mut value: i32) { if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK as u32 } @@ -137,7 +137,7 @@ pub unsafe fn write8(mut addr: u32, mut value: i32) -> () { }; } #[no_mangle] -pub unsafe fn write16(mut addr: u32, mut value: i32) -> () { +pub unsafe fn write16(mut addr: u32, mut value: i32) { if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK as u32 } @@ -150,7 +150,7 @@ pub unsafe fn write16(mut addr: u32, mut value: i32) -> () { }; } #[no_mangle] -pub unsafe fn write_aligned16(mut addr: u32, mut value: u32) -> () { +pub unsafe fn write_aligned16(mut addr: u32, mut value: u32) { dbg_assert!(addr < 2147483648u32); if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK16 as u32 @@ -165,7 +165,7 @@ pub unsafe fn write_aligned16(mut addr: u32, mut value: u32) -> () { }; } #[no_mangle] -pub unsafe fn write32(mut addr: u32, mut value: i32) -> () { +pub unsafe fn write32(mut addr: u32, mut value: i32) { if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK as u32 } @@ -178,7 +178,7 @@ pub unsafe fn write32(mut addr: u32, mut value: i32) -> () { }; } #[no_mangle] -pub unsafe fn write_aligned32(mut addr: u32, mut value: i32) -> () { +pub unsafe fn write_aligned32(mut addr: u32, mut value: i32) { dbg_assert!(addr < 1073741824i32 as u32); if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK32 as u32 @@ -193,7 +193,7 @@ pub unsafe fn write_aligned32(mut addr: u32, mut value: i32) -> () { }; } #[no_mangle] -pub unsafe fn write64(mut addr: u32, mut value: i64) -> () { +pub unsafe fn write64(mut addr: u32, mut value: i64) { if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK as u32 } @@ -210,7 +210,7 @@ pub unsafe fn write64(mut addr: u32, mut value: i64) -> () { }; } #[no_mangle] -pub unsafe fn write128(mut addr: u32, mut value: reg128) -> () { +pub unsafe fn write128(mut addr: u32, mut value: reg128) { if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK as u32 } diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index 08f4337a..b416795f 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -98,51 +98,51 @@ pub unsafe fn test_nl() -> bool { return !test_l(); } #[no_mangle] pub unsafe fn test_nle() -> bool { return !test_le(); } #[no_mangle] -pub unsafe fn jmp_rel16(mut rel16: i32) -> () { +pub unsafe fn jmp_rel16(mut rel16: i32) { let mut cs_offset: i32 = get_seg_cs(); // limit ip to 16 bit *instruction_pointer = cs_offset + (*instruction_pointer - cs_offset + rel16 & 65535i32); } #[no_mangle] -pub unsafe fn jmpcc16(mut condition: bool, mut imm16: i32) -> () { +pub unsafe fn jmpcc16(mut condition: bool, mut imm16: i32) { if condition { jmp_rel16(imm16); }; } #[no_mangle] -pub unsafe fn jmpcc32(mut condition: bool, mut imm32: i32) -> () { +pub unsafe fn jmpcc32(mut condition: bool, mut imm32: i32) { if condition { *instruction_pointer += imm32 }; } #[no_mangle] -pub unsafe fn loope16(mut imm8s: i32) -> () { +pub unsafe fn loope16(mut imm8s: i32) { jmpcc16(0 != decr_ecx_asize() && 0 != getzf() as i32, imm8s); } #[no_mangle] -pub unsafe fn loopne16(mut imm8s: i32) -> () { jmpcc16(0 != decr_ecx_asize() && !getzf(), imm8s); } +pub unsafe fn loopne16(mut imm8s: i32) { jmpcc16(0 != decr_ecx_asize() && !getzf(), imm8s); } #[no_mangle] -pub unsafe fn loop16(mut imm8s: i32) -> () { jmpcc16(0 != decr_ecx_asize(), imm8s); } +pub unsafe fn loop16(mut imm8s: i32) { jmpcc16(0 != decr_ecx_asize(), imm8s); } #[no_mangle] -pub unsafe fn jcxz16(mut imm8s: i32) -> () { jmpcc16(get_reg_asize(ECX) == 0i32, imm8s); } +pub unsafe fn jcxz16(mut imm8s: i32) { jmpcc16(get_reg_asize(ECX) == 0i32, imm8s); } #[no_mangle] -pub unsafe fn loope32(mut imm8s: i32) -> () { +pub unsafe fn loope32(mut imm8s: i32) { jmpcc32(0 != decr_ecx_asize() && 0 != getzf() as i32, imm8s); } #[no_mangle] -pub unsafe fn loopne32(mut imm8s: i32) -> () { jmpcc32(0 != decr_ecx_asize() && !getzf(), imm8s); } +pub unsafe fn loopne32(mut imm8s: i32) { jmpcc32(0 != decr_ecx_asize() && !getzf(), imm8s); } #[no_mangle] -pub unsafe fn loop32(mut imm8s: i32) -> () { jmpcc32(0 != decr_ecx_asize(), imm8s); } +pub unsafe fn loop32(mut imm8s: i32) { jmpcc32(0 != decr_ecx_asize(), imm8s); } #[no_mangle] -pub unsafe fn jcxz32(mut imm8s: i32) -> () { jmpcc32(get_reg_asize(ECX) == 0i32, imm8s); } +pub unsafe fn jcxz32(mut imm8s: i32) { jmpcc32(get_reg_asize(ECX) == 0i32, imm8s); } #[no_mangle] -pub unsafe fn cmovcc16(mut condition: bool, mut value: i32, mut r: i32) -> () { +pub unsafe fn cmovcc16(mut condition: bool, mut value: i32, mut r: i32) { if condition { write_reg16(r, value); }; } #[no_mangle] -pub unsafe fn cmovcc32(mut condition: bool, mut value: i32, mut r: i32) -> () { +pub unsafe fn cmovcc32(mut condition: bool, mut value: i32, mut r: i32) { if condition { write_reg32(r, value); }; @@ -157,7 +157,7 @@ pub unsafe fn get_stack_pointer(mut offset: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn adjust_stack_reg(mut adjustment: i32) -> () { +pub unsafe fn adjust_stack_reg(mut adjustment: i32) { if *stack_size_32 { *reg32s.offset(ESP as isize) += adjustment; } @@ -292,7 +292,7 @@ pub unsafe fn pop32s_ss32() -> Result { Ok(result) } #[no_mangle] -pub unsafe fn pusha16() -> () { +pub unsafe fn pusha16() { let mut temp: u16 = *reg16.offset(SP as isize); // make sure we don't get a pagefault after having // pushed several registers already @@ -307,7 +307,7 @@ pub unsafe fn pusha16() -> () { push16(*reg16.offset(DI as isize) as i32).unwrap(); } #[no_mangle] -pub unsafe fn pusha32() -> () { +pub unsafe fn pusha32() { let mut temp: i32 = *reg32s.offset(ESP as isize); return_on_pagefault!(writable_or_pagefault(get_stack_pointer(-32i32), 32i32)); push32(*reg32s.offset(EAX as isize)).unwrap(); @@ -320,18 +320,18 @@ pub unsafe fn pusha32() -> () { push32(*reg32s.offset(EDI as isize)).unwrap(); } #[no_mangle] -pub unsafe fn setcc_reg(mut condition: bool, mut r: i32) -> () { +pub unsafe fn setcc_reg(mut condition: bool, mut r: i32) { write_reg8(r, if 0 != condition as i32 { 1i32 } else { 0i32 }); } #[no_mangle] -pub unsafe fn setcc_mem(mut condition: bool, mut addr: i32) -> () { +pub unsafe fn setcc_mem(mut condition: bool, mut addr: i32) { return_on_pagefault!(safe_write8( addr, if 0 != condition as i32 { 1i32 } else { 0i32 } )); } #[no_mangle] -pub unsafe fn fxsave(mut addr: u32) -> () { +pub unsafe fn fxsave(mut addr: u32) { return_on_pagefault!(writable_or_pagefault(addr as i32, 512i32)); safe_write16(addr.wrapping_add(0i32 as u32) as i32, *fpu_control_word).unwrap(); safe_write16( @@ -372,7 +372,7 @@ pub unsafe fn fxsave(mut addr: u32) -> () { } } #[no_mangle] -pub unsafe fn fxrstor(mut addr: u32) -> () { +pub unsafe fn fxrstor(mut addr: u32) { // TODO: Add readable_or_pagefault return_on_pagefault!(translate_address_read(addr as i32)); return_on_pagefault!(translate_address_read( @@ -443,7 +443,7 @@ pub unsafe fn xchg16(mut data: i32, mut r16: i32) -> i32 { return tmp; } #[no_mangle] -pub unsafe fn xchg16r(mut r16: i32) -> () { +pub unsafe fn xchg16r(mut r16: i32) { let mut tmp: i32 = *reg16.offset(AX as isize) as i32; *reg16.offset(AX as isize) = *reg16.offset(r16 as isize); *reg16.offset(r16 as isize) = tmp as u16; @@ -455,7 +455,7 @@ pub unsafe fn xchg32(mut data: i32, mut r32: i32) -> i32 { return tmp; } #[no_mangle] -pub unsafe fn xchg32r(mut r32: i32) -> () { +pub unsafe fn xchg32r(mut r32: i32) { let mut tmp: i32 = *reg32s.offset(EAX as isize); *reg32s.offset(EAX as isize) = *reg32s.offset(r32 as isize); *reg32s.offset(r32 as isize) = tmp; diff --git a/src/rust/cpu2/profiler.rs b/src/rust/cpu2/profiler.rs index 8ea1afc1..93dceeb1 100644 --- a/src/rust/cpu2/profiler.rs +++ b/src/rust/cpu2/profiler.rs @@ -87,7 +87,7 @@ pub static mut profiler_stat_arr: [profiler_stat; 37] = [ profiler_stat { count: 0 }, ]; #[no_mangle] -pub unsafe fn profiler_init() -> () { +pub unsafe fn profiler_init() { let mut i: u32 = 0i32 as u32; while i < (S_TLB_GLOBAL_FULL as i32 - S_COMPILE as i32 + 1i32) as u32 { profiler_stat_arr[i as usize].count = 0i32; @@ -95,11 +95,11 @@ pub unsafe fn profiler_init() -> () { } } #[no_mangle] -pub unsafe fn profiler_stat_increment(mut stat: StatName) -> () { +pub unsafe fn profiler_stat_increment(mut stat: StatName) { profiler_stat_increment_by(stat, 1i32); } #[no_mangle] -pub unsafe fn profiler_stat_increment_by(mut stat: StatName, mut by: i32) -> () { +pub unsafe fn profiler_stat_increment_by(mut stat: StatName, mut by: i32) { if cfg!(feature = "profiler") { profiler_stat_arr[stat as usize].count += by; } @@ -114,4 +114,4 @@ pub unsafe fn profiler_stat_get(mut stat: StatName) -> i32 { } } #[no_mangle] -pub unsafe fn profiler_stat_increment_do_run() -> () { profiler_stat_increment(S_DO_RUN); } +pub unsafe fn profiler_stat_increment_do_run() { profiler_stat_increment(S_DO_RUN); } diff --git a/src/rust/cpu2/sse_instr.rs b/src/rust/cpu2/sse_instr.rs index 84949411..49619c01 100644 --- a/src/rust/cpu2/sse_instr.rs +++ b/src/rust/cpu2/sse_instr.rs @@ -3,36 +3,36 @@ use cpu2::cpu::*; #[no_mangle] -pub unsafe fn mov_r_m64(mut addr: i32, mut r: i32) -> () { +pub unsafe fn mov_r_m64(mut addr: i32, mut r: i32) { // mov* m64, mm let mut data: reg64 = read_mmx64s(r); return_on_pagefault!(safe_write64(addr, data.u64_0[0usize] as i64)); } #[no_mangle] -pub unsafe fn movl_r128_m64(mut addr: i32, mut r: i32) -> () { +pub unsafe fn movl_r128_m64(mut addr: i32, mut r: i32) { // mov* m64, xmm let mut data: reg64 = read_xmm64s(r); return_on_pagefault!(safe_write64(addr, data.u64_0[0usize] as i64)); } #[no_mangle] -pub unsafe fn mov_r_r128(mut r1: i32, mut r2: i32) -> () { +pub unsafe fn mov_r_r128(mut r1: i32, mut r2: i32) { // mov* xmm, xmm let mut data: reg128 = read_xmm128s(r2); write_xmm_reg128(r1, data); } #[no_mangle] -pub unsafe fn mov_r_m128(mut addr: i32, mut r: i32) -> () { +pub unsafe fn mov_r_m128(mut addr: i32, mut r: i32) { // mov* m128, xmm let mut data: reg128 = read_xmm128s(r); return_on_pagefault!(safe_write128(addr, data)); } #[no_mangle] -pub unsafe fn mov_rm_r128(mut source: reg128, mut r: i32) -> () { +pub unsafe fn mov_rm_r128(mut source: reg128, mut r: i32) { // mov* xmm, xmm/m128 write_xmm_reg128(r, source); } #[no_mangle] -pub unsafe fn movh_m64_r128(mut addr: i32, mut r: i32) -> () { +pub unsafe fn movh_m64_r128(mut addr: i32, mut r: i32) { // movhp* xmm, m64 let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); let mut orig: reg128 = read_xmm128s(r); @@ -45,13 +45,13 @@ pub unsafe fn movh_m64_r128(mut addr: i32, mut r: i32) -> () { ); } #[no_mangle] -pub unsafe fn movh_r128_m64(mut addr: i32, mut r: i32) -> () { +pub unsafe fn movh_r128_m64(mut addr: i32, mut r: i32) { // movhp* m64, xmm let mut data: reg128 = read_xmm128s(r); return_on_pagefault!(safe_write64(addr, data.u64_0[1usize] as i64)); } #[no_mangle] -pub unsafe fn pand_r128(mut source: reg128, mut r: i32) -> () { +pub unsafe fn pand_r128(mut source: reg128, mut r: i32) { // pand xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -63,7 +63,7 @@ pub unsafe fn pand_r128(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn pandn_r128(mut source: reg128, mut r: i32) -> () { +pub unsafe fn pandn_r128(mut source: reg128, mut r: i32) { // pandn xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -75,7 +75,7 @@ pub unsafe fn pandn_r128(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn pxor_r128(mut source: reg128, mut r: i32) -> () { +pub unsafe fn pxor_r128(mut source: reg128, mut r: i32) { // pxor xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -87,7 +87,7 @@ pub unsafe fn pxor_r128(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn por_r128(mut source: reg128, mut r: i32) -> () { +pub unsafe fn por_r128(mut source: reg128, mut r: i32) { // por xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -99,7 +99,7 @@ pub unsafe fn por_r128(mut source: reg128, mut r: i32) -> () { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn psrlw_r64(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psrlw_r64(mut r: i32, mut shift: u32) { // psrlw mm, {shift} let mut destination: reg64 = read_mmx64s(r); let mut dword0: i32 = 0i32; @@ -113,7 +113,7 @@ pub unsafe fn psrlw_r64(mut r: i32, mut shift: u32) -> () { write_mmx64(r, dword0, dword1); } #[no_mangle] -pub unsafe fn psraw_r64(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psraw_r64(mut r: i32, mut shift: u32) { // psraw mm, {shift} let mut destination: reg64 = read_mmx64s(r); let mut shift_clamped: i32 = (if shift > 15i32 as u32 { @@ -129,7 +129,7 @@ pub unsafe fn psraw_r64(mut r: i32, mut shift: u32) -> () { write_mmx64(r, dword0, dword1); } #[no_mangle] -pub unsafe fn psllw_r64(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psllw_r64(mut r: i32, mut shift: u32) { // psllw mm, {shift} let mut destination: reg64 = read_mmx64s(r); let mut dword0: i32 = 0i32; @@ -143,7 +143,7 @@ pub unsafe fn psllw_r64(mut r: i32, mut shift: u32) -> () { write_mmx64(r, dword0, dword1); } #[no_mangle] -pub unsafe fn psrld_r64(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psrld_r64(mut r: i32, mut shift: u32) { // psrld mm, {shift} let mut destination: reg64 = read_mmx64s(r); let mut dword0: i32 = 0i32; @@ -155,7 +155,7 @@ pub unsafe fn psrld_r64(mut r: i32, mut shift: u32) -> () { write_mmx64(r, dword0, dword1); } #[no_mangle] -pub unsafe fn psrad_r64(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psrad_r64(mut r: i32, mut shift: u32) { // psrad mm, {shift} let mut destination: reg64 = read_mmx64s(r); let mut shift_clamped: i32 = (if shift > 31i32 as u32 { @@ -169,7 +169,7 @@ pub unsafe fn psrad_r64(mut r: i32, mut shift: u32) -> () { write_mmx64(r, dword0, dword1); } #[no_mangle] -pub unsafe fn pslld_r64(mut r: i32, mut shift: u32) -> () { +pub unsafe fn pslld_r64(mut r: i32, mut shift: u32) { // pslld mm, {shift} let mut destination: reg64 = read_mmx64s(r); let mut dword0: i32 = 0i32; @@ -181,7 +181,7 @@ pub unsafe fn pslld_r64(mut r: i32, mut shift: u32) -> () { write_mmx64(r, dword0, dword1); } #[no_mangle] -pub unsafe fn psrlq_r64(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psrlq_r64(mut r: i32, mut shift: u32) { // psrlq mm, {shift} if shift == 0i32 as u32 { return; @@ -199,7 +199,7 @@ pub unsafe fn psrlq_r64(mut r: i32, mut shift: u32) -> () { }; } #[no_mangle] -pub unsafe fn psllq_r64(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psllq_r64(mut r: i32, mut shift: u32) { // psllq mm, {shift} let mut destination: reg64 = read_mmx64s(r); if shift == 0i32 as u32 { @@ -217,7 +217,7 @@ pub unsafe fn psllq_r64(mut r: i32, mut shift: u32) -> () { }; } #[no_mangle] -pub unsafe fn psrlw_r128(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psrlw_r128(mut r: i32, mut shift: u32) { // psrlw xmm, {shift} let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = 0i32; @@ -237,7 +237,7 @@ pub unsafe fn psrlw_r128(mut r: i32, mut shift: u32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn psraw_r128(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psraw_r128(mut r: i32, mut shift: u32) { // psraw xmm, {shift} let mut destination: reg128 = read_xmm128s(r); let mut shift_clamped: i32 = (if shift > 15i32 as u32 { @@ -257,7 +257,7 @@ pub unsafe fn psraw_r128(mut r: i32, mut shift: u32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn psllw_r128(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psllw_r128(mut r: i32, mut shift: u32) { // psllw xmm, {shift} let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = 0i32; @@ -277,7 +277,7 @@ pub unsafe fn psllw_r128(mut r: i32, mut shift: u32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn psrld_r128(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psrld_r128(mut r: i32, mut shift: u32) { // psrld xmm, {shift} let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = 0i32; @@ -293,7 +293,7 @@ pub unsafe fn psrld_r128(mut r: i32, mut shift: u32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn psrad_r128(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psrad_r128(mut r: i32, mut shift: u32) { // psrad xmm, {shift} let mut destination: reg128 = read_xmm128s(r); let mut shift_clamped: i32 = (if shift > 31i32 as u32 { @@ -309,7 +309,7 @@ pub unsafe fn psrad_r128(mut r: i32, mut shift: u32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn pslld_r128(mut r: i32, mut shift: u32) -> () { +pub unsafe fn pslld_r128(mut r: i32, mut shift: u32) { // pslld xmm, {shift} let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = 0i32; @@ -325,7 +325,7 @@ pub unsafe fn pslld_r128(mut r: i32, mut shift: u32) -> () { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn psrlq_r128(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psrlq_r128(mut r: i32, mut shift: u32) { // psrlq xmm, {shift} if shift == 0i32 as u32 { return; @@ -344,7 +344,7 @@ pub unsafe fn psrlq_r128(mut r: i32, mut shift: u32) -> () { }; } #[no_mangle] -pub unsafe fn psllq_r128(mut r: i32, mut shift: u32) -> () { +pub unsafe fn psllq_r128(mut r: i32, mut shift: u32) { // psllq xmm, {shift} let mut destination: reg128 = read_xmm128s(r); if shift == 0i32 as u32 { diff --git a/src/rust/cpu2/string.rs b/src/rust/cpu2/string.rs index f0b3e732..19159950 100644 --- a/src/rust/cpu2/string.rs +++ b/src/rust/cpu2/string.rs @@ -47,7 +47,7 @@ pub unsafe fn string_get_cycle_count2(mut size: i32, mut addr1: i32, mut addr2: return if c1 < c2 { c1 } else { c2 }; } #[no_mangle] -pub unsafe fn movsb_rep() -> () { +pub unsafe fn movsb_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -92,7 +92,7 @@ pub unsafe fn movsb_rep() -> () { }; } #[no_mangle] -pub unsafe fn movsb_no_rep() -> () { +pub unsafe fn movsb_no_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -106,7 +106,7 @@ pub unsafe fn movsb_no_rep() -> () { add_reg_asize(ESI, size); } #[no_mangle] -pub unsafe fn movsw_rep() -> () { +pub unsafe fn movsw_rep() { let mut diff; let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); @@ -174,7 +174,7 @@ pub unsafe fn movsw_rep() -> () { }; } #[no_mangle] -pub unsafe fn movsw_no_rep() -> () { +pub unsafe fn movsw_no_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -188,7 +188,7 @@ pub unsafe fn movsw_no_rep() -> () { add_reg_asize(ESI, size); } #[no_mangle] -pub unsafe fn movsd_rep() -> () { +pub unsafe fn movsd_rep() { let mut diff; let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); @@ -256,7 +256,7 @@ pub unsafe fn movsd_rep() -> () { }; } #[no_mangle] -pub unsafe fn movsd_no_rep() -> () { +pub unsafe fn movsd_no_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -270,7 +270,7 @@ pub unsafe fn movsd_no_rep() -> () { add_reg_asize(ESI, size); } #[no_mangle] -pub unsafe fn cmpsb_rep(mut prefix_flag: i32) -> () { +pub unsafe fn cmpsb_rep(mut prefix_flag: i32) { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut data_src; @@ -320,7 +320,7 @@ pub unsafe fn cmpsb_rep(mut prefix_flag: i32) -> () { }; } #[no_mangle] -pub unsafe fn cmpsb_no_rep() -> () { +pub unsafe fn cmpsb_no_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut data_src; @@ -338,7 +338,7 @@ pub unsafe fn cmpsb_no_rep() -> () { cmp8(data_src, data_dest); } #[no_mangle] -pub unsafe fn cmpsw_rep(mut prefix_flag: i32) -> () { +pub unsafe fn cmpsw_rep(mut prefix_flag: i32) { let mut diff; let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); @@ -413,7 +413,7 @@ pub unsafe fn cmpsw_rep(mut prefix_flag: i32) -> () { }; } #[no_mangle] -pub unsafe fn cmpsw_no_rep() -> () { +pub unsafe fn cmpsw_no_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut data_src; @@ -431,7 +431,7 @@ pub unsafe fn cmpsw_no_rep() -> () { cmp16(data_src, data_dest); } #[no_mangle] -pub unsafe fn cmpsd_rep(mut prefix_flag: i32) -> () { +pub unsafe fn cmpsd_rep(mut prefix_flag: i32) { let mut diff; let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); @@ -506,7 +506,7 @@ pub unsafe fn cmpsd_rep(mut prefix_flag: i32) -> () { }; } #[no_mangle] -pub unsafe fn cmpsd_no_rep() -> () { +pub unsafe fn cmpsd_no_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut data_src; @@ -524,7 +524,7 @@ pub unsafe fn cmpsd_no_rep() -> () { cmp32(data_src, data_dest); } #[no_mangle] -pub unsafe fn stosb_rep() -> () { +pub unsafe fn stosb_rep() { let mut data: i32 = *reg8.offset(AL as isize) as i32; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -566,7 +566,7 @@ pub unsafe fn stosb_rep() -> () { }; } #[no_mangle] -pub unsafe fn stosb_no_rep() -> () { +pub unsafe fn stosb_no_rep() { let mut data: i32 = *reg8.offset(AL as isize) as i32; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -579,7 +579,7 @@ pub unsafe fn stosb_no_rep() -> () { add_reg_asize(EDI, size); } #[no_mangle] -pub unsafe fn stosw_rep() -> () { +pub unsafe fn stosw_rep() { let mut diff; let mut data: i32 = *reg16.offset(AX as isize) as i32; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); @@ -641,7 +641,7 @@ pub unsafe fn stosw_rep() -> () { }; } #[no_mangle] -pub unsafe fn stosw_no_rep() -> () { +pub unsafe fn stosw_no_rep() { let mut data: i32 = *reg16.offset(AX as isize) as i32; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -654,7 +654,7 @@ pub unsafe fn stosw_no_rep() -> () { add_reg_asize(EDI, size); } #[no_mangle] -pub unsafe fn stosd_rep() -> () { +pub unsafe fn stosd_rep() { let mut diff; let mut data: i32 = *reg32s.offset(EAX as isize); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); @@ -716,7 +716,7 @@ pub unsafe fn stosd_rep() -> () { }; } #[no_mangle] -pub unsafe fn stosd_no_rep() -> () { +pub unsafe fn stosd_no_rep() { let mut data: i32 = *reg32s.offset(EAX as isize); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -729,7 +729,7 @@ pub unsafe fn stosd_no_rep() -> () { add_reg_asize(EDI, size); } #[no_mangle] -pub unsafe fn lodsb_rep() -> () { +pub unsafe fn lodsb_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1i32 @@ -770,7 +770,7 @@ pub unsafe fn lodsb_rep() -> () { }; } #[no_mangle] -pub unsafe fn lodsb_no_rep() -> () { +pub unsafe fn lodsb_no_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1i32 @@ -782,7 +782,7 @@ pub unsafe fn lodsb_no_rep() -> () { add_reg_asize(ESI, size); } #[no_mangle] -pub unsafe fn lodsw_rep() -> () { +pub unsafe fn lodsw_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2i32 @@ -816,7 +816,7 @@ pub unsafe fn lodsw_rep() -> () { }; } #[no_mangle] -pub unsafe fn lodsw_no_rep() -> () { +pub unsafe fn lodsw_no_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2i32 @@ -828,7 +828,7 @@ pub unsafe fn lodsw_no_rep() -> () { add_reg_asize(ESI, size); } #[no_mangle] -pub unsafe fn lodsd_rep() -> () { +pub unsafe fn lodsd_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4i32 @@ -862,7 +862,7 @@ pub unsafe fn lodsd_rep() -> () { }; } #[no_mangle] -pub unsafe fn lodsd_no_rep() -> () { +pub unsafe fn lodsd_no_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4i32 @@ -874,7 +874,7 @@ pub unsafe fn lodsd_no_rep() -> () { add_reg_asize(ESI, size); } #[no_mangle] -pub unsafe fn scasb_rep(mut prefix_flag: i32) -> () { +pub unsafe fn scasb_rep(mut prefix_flag: i32) { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1i32 @@ -919,7 +919,7 @@ pub unsafe fn scasb_rep(mut prefix_flag: i32) -> () { }; } #[no_mangle] -pub unsafe fn scasb_no_rep() -> () { +pub unsafe fn scasb_no_rep() { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1i32 @@ -934,7 +934,7 @@ pub unsafe fn scasb_no_rep() -> () { cmp8(data_src, data_dest); } #[no_mangle] -pub unsafe fn scasw_rep(mut prefix_flag: i32) -> () { +pub unsafe fn scasw_rep(mut prefix_flag: i32) { let mut diff; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -1000,7 +1000,7 @@ pub unsafe fn scasw_rep(mut prefix_flag: i32) -> () { }; } #[no_mangle] -pub unsafe fn scasw_no_rep() -> () { +pub unsafe fn scasw_no_rep() { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2i32 @@ -1015,7 +1015,7 @@ pub unsafe fn scasw_no_rep() -> () { cmp16(data_src, data_dest); } #[no_mangle] -pub unsafe fn scasd_rep(mut prefix_flag: i32) -> () { +pub unsafe fn scasd_rep(mut prefix_flag: i32) { let mut diff; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { @@ -1081,7 +1081,7 @@ pub unsafe fn scasd_rep(mut prefix_flag: i32) -> () { }; } #[no_mangle] -pub unsafe fn scasd_no_rep() -> () { +pub unsafe fn scasd_no_rep() { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4i32 @@ -1096,7 +1096,7 @@ pub unsafe fn scasd_no_rep() -> () { cmp32(data_src, data_dest); } #[no_mangle] -pub unsafe fn insb_rep() -> () { +pub unsafe fn insb_rep() { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 1i32) { return; @@ -1144,7 +1144,7 @@ pub unsafe fn insb_rep() -> () { }; } #[no_mangle] -pub unsafe fn insb_no_rep() -> () { +pub unsafe fn insb_no_rep() { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 1i32) { return; @@ -1164,7 +1164,7 @@ pub unsafe fn insb_no_rep() -> () { }; } #[no_mangle] -pub unsafe fn insw_rep() -> () { +pub unsafe fn insw_rep() { let mut diff; let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 2i32) { @@ -1233,7 +1233,7 @@ pub unsafe fn insw_rep() -> () { }; } #[no_mangle] -pub unsafe fn insw_no_rep() -> () { +pub unsafe fn insw_no_rep() { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 2i32) { return; @@ -1253,7 +1253,7 @@ pub unsafe fn insw_no_rep() -> () { }; } #[no_mangle] -pub unsafe fn insd_rep() -> () { +pub unsafe fn insd_rep() { let mut diff; let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 4i32) { @@ -1322,7 +1322,7 @@ pub unsafe fn insd_rep() -> () { }; } #[no_mangle] -pub unsafe fn insd_no_rep() -> () { +pub unsafe fn insd_no_rep() { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 4i32) { return; @@ -1342,7 +1342,7 @@ pub unsafe fn insd_no_rep() -> () { }; } #[no_mangle] -pub unsafe fn outsb_rep() -> () { +pub unsafe fn outsb_rep() { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 1i32) { return; @@ -1390,7 +1390,7 @@ pub unsafe fn outsb_rep() -> () { }; } #[no_mangle] -pub unsafe fn outsb_no_rep() -> () { +pub unsafe fn outsb_no_rep() { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 1i32) { return; @@ -1409,7 +1409,7 @@ pub unsafe fn outsb_no_rep() -> () { }; } #[no_mangle] -pub unsafe fn outsw_rep() -> () { +pub unsafe fn outsw_rep() { let mut diff; let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 2i32) { @@ -1477,7 +1477,7 @@ pub unsafe fn outsw_rep() -> () { }; } #[no_mangle] -pub unsafe fn outsw_no_rep() -> () { +pub unsafe fn outsw_no_rep() { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 2i32) { return; @@ -1496,7 +1496,7 @@ pub unsafe fn outsw_no_rep() -> () { }; } #[no_mangle] -pub unsafe fn outsd_rep() -> () { +pub unsafe fn outsd_rep() { let mut diff; let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 4i32) { @@ -1564,7 +1564,7 @@ pub unsafe fn outsd_rep() -> () { }; } #[no_mangle] -pub unsafe fn outsd_no_rep() -> () { +pub unsafe fn outsd_no_rep() { let mut port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 4i32) { return; From 0a50a8474eed122a42c7d54fc4b64f3dfb4eb23b Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 29 Aug 2018 12:29:12 -0500 Subject: [PATCH 1261/2137] c2rust cleanup: Remove unnecessary suffixes on numbers --- src/rust/cpu2/arith.rs | 664 +++++----- src/rust/cpu2/cpu.rs | 844 +++++++------ src/rust/cpu2/fpu.rs | 299 +++-- src/rust/cpu2/global_pointers.rs | 122 +- src/rust/cpu2/instructions.rs | 785 +++++------- src/rust/cpu2/instructions_0f.rs | 1992 ++++++++++++++---------------- src/rust/cpu2/memory.rs | 69 +- src/rust/cpu2/misc_instr.rs | 162 ++- src/rust/cpu2/modrm.rs | 96 +- src/rust/cpu2/profiler.rs | 12 +- src/rust/cpu2/sse_instr.rs | 278 ++--- src/rust/cpu2/string.rs | 538 +++----- 12 files changed, 2652 insertions(+), 3209 deletions(-) diff --git a/src/rust/cpu2/arith.rs b/src/rust/cpu2/arith.rs index 5d3ecbf9..6127c530 100644 --- a/src/rust/cpu2/arith.rs +++ b/src/rust/cpu2/arith.rs @@ -85,26 +85,26 @@ pub unsafe fn cmp16(mut x: i32, mut y: i32) { sub(x, y, OPSIZE_16); } pub unsafe fn cmp32(mut x: i32, mut y: i32) { sub(x, y, OPSIZE_32); } #[no_mangle] pub unsafe fn inc(mut dest_operand: i32, mut op_size: i32) -> i32 { - *flags = *flags & !1i32 | getcf() as i32; + *flags = *flags & !1 | getcf() as i32; *last_op1 = dest_operand; - *last_op2 = 1i32; - let mut res: i32 = dest_operand + 1i32; + *last_op2 = 1; + let mut res: i32 = dest_operand + 1; *last_result = res; *last_add_result = *last_result; *last_op_size = op_size; - *flags_changed = FLAGS_ALL & !1i32; + *flags_changed = FLAGS_ALL & !1; return res; } #[no_mangle] pub unsafe fn dec(mut dest_operand: i32, mut op_size: i32) -> i32 { - *flags = *flags & !1i32 | getcf() as i32; + *flags = *flags & !1 | getcf() as i32; *last_add_result = dest_operand; - *last_op2 = 1i32; - let mut res: i32 = dest_operand - 1i32; + *last_op2 = 1; + let mut res: i32 = dest_operand - 1; *last_result = res; *last_op1 = *last_result; *last_op_size = op_size; - *flags_changed = FLAGS_ALL & !1i32; + *flags_changed = FLAGS_ALL & !1; return res; } #[no_mangle] @@ -125,7 +125,7 @@ pub unsafe fn neg(mut dest_operand: i32, mut op_size: i32) -> i32 { *last_result = res; *last_op1 = *last_result; *flags_changed = FLAGS_ALL; - *last_add_result = 0i32; + *last_add_result = 0; *last_op2 = dest_operand; *last_op_size = op_size; return res; @@ -140,75 +140,75 @@ pub unsafe fn neg32(mut x: i32) -> i32 { return neg(x, OPSIZE_32); } pub unsafe fn mul8(mut source_operand: i32) { let mut result: i32 = source_operand * *reg8.offset(AL as isize) as i32; *reg16.offset(AX as isize) = result as u16; - *last_result = result & 255i32; + *last_result = result & 255; *last_op_size = OPSIZE_8; - if result < 256i32 { - *flags = *flags & !1i32 & !FLAG_OVERFLOW + if result < 256 { + *flags = *flags & !1 & !FLAG_OVERFLOW } else { - *flags = *flags | 1i32 | FLAG_OVERFLOW + *flags = *flags | 1 | FLAG_OVERFLOW } - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; } #[no_mangle] pub unsafe fn imul8(mut source_operand: i32) { let mut result: i32 = source_operand * *reg8s.offset(AL as isize) as i32; *reg16.offset(AX as isize) = result as u16; - *last_result = result & 255i32; + *last_result = result & 255; *last_op_size = OPSIZE_8; - if result > 127i32 || result < -128i32 { - *flags = *flags | 1i32 | FLAG_OVERFLOW + if result > 127 || result < -128 { + *flags = *flags | 1 | FLAG_OVERFLOW } else { - *flags = *flags & !1i32 & !FLAG_OVERFLOW + *flags = *flags & !1 & !FLAG_OVERFLOW } - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; } #[no_mangle] pub unsafe fn mul16(mut source_operand: u32) { let mut result: u32 = source_operand.wrapping_mul(*reg16.offset(AX as isize) as u32); - let mut high_result: u32 = result >> 16i32; + let mut high_result: u32 = result >> 16; *reg16.offset(AX as isize) = result as u16; *reg16.offset(DX as isize) = high_result as u16; - *last_result = (result & 65535i32 as u32) as i32; + *last_result = (result & 65535 as u32) as i32; *last_op_size = OPSIZE_16; - if high_result == 0i32 as u32 { - *flags &= !1i32 & !FLAG_OVERFLOW + if high_result == 0 as u32 { + *flags &= !1 & !FLAG_OVERFLOW } else { - *flags |= *flags | 1i32 | FLAG_OVERFLOW + *flags |= *flags | 1 | FLAG_OVERFLOW } - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; } #[no_mangle] pub unsafe fn imul16(mut source_operand: i32) { let mut result: i32 = source_operand * *reg16s.offset(AX as isize) as i32; *reg16.offset(AX as isize) = result as u16; - *reg16.offset(DX as isize) = (result >> 16i32) as u16; - *last_result = result & 65535i32; + *reg16.offset(DX as isize) = (result >> 16) as u16; + *last_result = result & 65535; *last_op_size = OPSIZE_16; - if result > 32767i32 || result < -32768i32 { - *flags |= 1i32 | FLAG_OVERFLOW + if result > 32767 || result < -32768 { + *flags |= 1 | FLAG_OVERFLOW } else { - *flags &= !1i32 & !FLAG_OVERFLOW + *flags &= !1 & !FLAG_OVERFLOW } - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; } #[no_mangle] pub unsafe fn imul_reg16(mut operand1: i32, mut operand2: i32) -> i32 { operand1 = operand1 << 16 >> 16; operand2 = operand2 << 16 >> 16; let mut result: i32 = operand1 * operand2; - *last_result = result & 65535i32; + *last_result = result & 65535; *last_op_size = OPSIZE_16; - if result > 32767i32 || result < -32768i32 { - *flags |= 1i32 | FLAG_OVERFLOW + if result > 32767 || result < -32768 { + *flags |= 1 | FLAG_OVERFLOW } else { - *flags &= !1i32 & !FLAG_OVERFLOW + *flags &= !1 & !FLAG_OVERFLOW } - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; return result; } #[no_mangle] @@ -216,51 +216,51 @@ pub unsafe fn mul32(mut source_operand: i32) { let mut dest_operand: i32 = *reg32s.offset(EAX as isize); let mut result: u64 = (dest_operand as u32 as u64).wrapping_mul(source_operand as u32 as u64); let mut result_low: i32 = result as i32; - let mut result_high: i32 = (result >> 32i32) as i32; + let mut result_high: i32 = (result >> 32) as i32; *reg32s.offset(EAX as isize) = result_low; *reg32s.offset(EDX as isize) = result_high; *last_result = result_low; *last_op_size = OPSIZE_32; - if result_high == 0i32 { - *flags &= !1i32 & !FLAG_OVERFLOW + if result_high == 0 { + *flags &= !1 & !FLAG_OVERFLOW } else { - *flags |= 1i32 | FLAG_OVERFLOW + *flags |= 1 | FLAG_OVERFLOW } - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; } #[no_mangle] pub unsafe fn imul32(mut source_operand: i32) { let mut dest_operand: i32 = *reg32s.offset(EAX as isize); let mut result: i64 = dest_operand as i64 * source_operand as i64; let mut result_low: i32 = result as i32; - let mut result_high: i32 = (result >> 32i32) as i32; + let mut result_high: i32 = (result >> 32) as i32; *reg32s.offset(EAX as isize) = result_low; *reg32s.offset(EDX as isize) = result_high; *last_result = result_low; *last_op_size = OPSIZE_32; - if result_high == result_low >> 31i32 { - *flags &= !1i32 & !FLAG_OVERFLOW + if result_high == result_low >> 31 { + *flags &= !1 & !FLAG_OVERFLOW } else { - *flags |= 1i32 | FLAG_OVERFLOW + *flags |= 1 | FLAG_OVERFLOW } - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; } #[no_mangle] pub unsafe fn imul_reg32(mut operand1: i32, mut operand2: i32) -> i32 { let mut result: i64 = operand1 as i64 * operand2 as i64; let mut result_low: i32 = result as i32; - let mut result_high: i32 = (result >> 32i32) as i32; + let mut result_high: i32 = (result >> 32) as i32; *last_result = result_low; *last_op_size = OPSIZE_32; - if result_high == result_low >> 31i32 { - *flags &= !1i32 & !FLAG_OVERFLOW + if result_high == result_low >> 31 { + *flags &= !1 & !FLAG_OVERFLOW } else { - *flags |= 1i32 | FLAG_OVERFLOW + *flags |= 1 | FLAG_OVERFLOW } - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; return result_low; } #[no_mangle] @@ -286,61 +286,61 @@ pub unsafe fn bcd_daa() { let mut old_al: i32 = *reg8.offset(AL as isize) as i32; let mut old_cf: i32 = getcf() as i32; let mut old_af: i32 = getaf() as i32; - *flags &= !1i32 & !FLAG_ADJUST; - if old_al & 15i32 > 9i32 || 0 != old_af { + *flags &= !1 & !FLAG_ADJUST; + if old_al & 15 > 9 || 0 != old_af { *reg8.offset(AL as isize) += 6; *flags |= FLAG_ADJUST } - if old_al > 153i32 || 0 != old_cf { + if old_al > 153 || 0 != old_cf { *reg8.offset(AL as isize) += 96; - *flags |= 1i32 + *flags |= 1 } *last_result = *reg8.offset(AL as isize) as i32; *last_op_size = OPSIZE_8; - *last_op2 = 0i32; + *last_op2 = 0; *last_op1 = *last_op2; - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_ADJUST & !FLAG_OVERFLOW; + *flags_changed = FLAGS_ALL & !1 & !FLAG_ADJUST & !FLAG_OVERFLOW; } #[no_mangle] pub unsafe fn bcd_das() { let mut old_al: i32 = *reg8.offset(AL as isize) as i32; let mut old_cf: i32 = getcf() as i32; - *flags &= !1i32; - if old_al & 15i32 > 9i32 || 0 != getaf() as i32 { + *flags &= !1; + if old_al & 15 > 9 || 0 != getaf() as i32 { *reg8.offset(AL as isize) -= 6; *flags |= FLAG_ADJUST; - *flags = *flags & !1i32 | old_cf | (old_al < 6i32) as i32 + *flags = *flags & !1 | old_cf | (old_al < 6) as i32 } else { *flags &= !FLAG_ADJUST } - if old_al > 153i32 || 0 != old_cf { + if old_al > 153 || 0 != old_cf { *reg8.offset(AL as isize) -= 96; - *flags |= 1i32 + *flags |= 1 } *last_result = *reg8.offset(AL as isize) as i32; *last_op_size = OPSIZE_8; - *last_op2 = 0i32; + *last_op2 = 0; *last_op1 = *last_op2; - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_ADJUST & !FLAG_OVERFLOW; + *flags_changed = FLAGS_ALL & !1 & !FLAG_ADJUST & !FLAG_OVERFLOW; } #[no_mangle] pub unsafe fn bcd_aad(mut imm8: i32) { let mut result: i32 = *reg8.offset(AL as isize) as i32 + *reg8.offset(AH as isize) as i32 * imm8; - *last_result = result & 255i32; + *last_result = result & 255; *reg16.offset(AX as isize) = *last_result as u16; *last_op_size = OPSIZE_8; - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_ADJUST & !FLAG_OVERFLOW; - *flags &= !1i32 & !FLAG_ADJUST & !FLAG_OVERFLOW; - if result > 65535i32 { - *flags |= 1i32 + *flags_changed = FLAGS_ALL & !1 & !FLAG_ADJUST & !FLAG_OVERFLOW; + *flags &= !1 & !FLAG_ADJUST & !FLAG_OVERFLOW; + if result > 65535 { + *flags |= 1 }; } #[no_mangle] pub unsafe fn bcd_aam(mut imm8: i32) { // ascii adjust after multiplication - if imm8 == 0i32 { + if imm8 == 0 { trigger_de(); } else { @@ -348,58 +348,58 @@ pub unsafe fn bcd_aam(mut imm8: i32) { *reg8.offset(AH as isize) = (temp as i32 / imm8) as u8; *reg8.offset(AL as isize) = (temp as i32 % imm8) as u8; *last_result = *reg8.offset(AL as isize) as i32; - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_ADJUST & !FLAG_OVERFLOW; - *flags &= !1i32 & !FLAG_ADJUST & !FLAG_OVERFLOW + *flags_changed = FLAGS_ALL & !1 & !FLAG_ADJUST & !FLAG_OVERFLOW; + *flags &= !1 & !FLAG_ADJUST & !FLAG_OVERFLOW }; } #[no_mangle] pub unsafe fn bcd_aaa() { - if *reg8.offset(AL as isize) as i32 & 15i32 > 9i32 || 0 != getaf() as i32 { + if *reg8.offset(AL as isize) as i32 & 15 > 9 || 0 != getaf() as i32 { *reg16.offset(AX as isize) += 6; *reg8.offset(AH as isize) += 1; - *flags |= FLAG_ADJUST | 1i32 + *flags |= FLAG_ADJUST | 1 } else { - *flags &= !FLAG_ADJUST & !1i32 + *flags &= !FLAG_ADJUST & !1 } *reg8.offset(AL as isize) &= 15; - *flags_changed &= !FLAG_ADJUST & !1i32; + *flags_changed &= !FLAG_ADJUST & !1; } #[no_mangle] pub unsafe fn bcd_aas() { - if *reg8.offset(AL as isize) as i32 & 15i32 > 9i32 || 0 != getaf() as i32 { + if *reg8.offset(AL as isize) as i32 & 15 > 9 || 0 != getaf() as i32 { *reg16.offset(AX as isize) -= 6; *reg8.offset(AH as isize) -= 1; - *flags |= FLAG_ADJUST | 1i32 + *flags |= FLAG_ADJUST | 1 } else { - *flags &= !FLAG_ADJUST & !1i32 + *flags &= !FLAG_ADJUST & !1 } *reg8.offset(AL as isize) &= 15; - *flags_changed &= !FLAG_ADJUST & !1i32; + *flags_changed &= !FLAG_ADJUST & !1; } #[no_mangle] pub unsafe fn and(mut dest_operand: i32, mut source_operand: i32, mut op_size: i32) -> i32 { *last_result = dest_operand & source_operand; *last_op_size = op_size; - *flags &= !1i32 & !FLAG_OVERFLOW & !FLAG_ADJUST; - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW & !FLAG_ADJUST; + *flags &= !1 & !FLAG_OVERFLOW & !FLAG_ADJUST; + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW & !FLAG_ADJUST; return *last_result; } #[no_mangle] pub unsafe fn or(mut dest_operand: i32, mut source_operand: i32, mut op_size: i32) -> i32 { *last_result = dest_operand | source_operand; *last_op_size = op_size; - *flags &= !1i32 & !FLAG_OVERFLOW & !FLAG_ADJUST; - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW & !FLAG_ADJUST; + *flags &= !1 & !FLAG_OVERFLOW & !FLAG_ADJUST; + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW & !FLAG_ADJUST; return *last_result; } #[no_mangle] pub unsafe fn xor(mut dest_operand: i32, mut source_operand: i32, mut op_size: i32) -> i32 { *last_result = dest_operand ^ source_operand; *last_op_size = op_size; - *flags &= !1i32 & !FLAG_OVERFLOW & !FLAG_ADJUST; - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW & !FLAG_ADJUST; + *flags &= !1 & !FLAG_OVERFLOW & !FLAG_ADJUST; + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW & !FLAG_ADJUST; return *last_result; } #[no_mangle] @@ -432,12 +432,12 @@ pub unsafe fn rol8(mut dest_operand: i32, mut count: i32) -> i32 { return dest_operand; } else { - count &= 7i32; - let mut result: i32 = dest_operand << count | dest_operand >> 8i32 - count; - *flags_changed &= !1i32 & !FLAG_OVERFLOW; - *flags = *flags & !1i32 & !FLAG_OVERFLOW - | result & 1i32 - | (result << 11i32 ^ result << 4i32) & FLAG_OVERFLOW; + count &= 7; + let mut result: i32 = dest_operand << count | dest_operand >> 8 - count; + *flags_changed &= !1 & !FLAG_OVERFLOW; + *flags = *flags & !1 & !FLAG_OVERFLOW + | result & 1 + | (result << 11 ^ result << 4) & FLAG_OVERFLOW; return result; }; } @@ -447,12 +447,12 @@ pub unsafe fn rol16(mut dest_operand: i32, mut count: i32) -> i32 { return dest_operand; } else { - count &= 15i32; - let mut result: i32 = dest_operand << count | dest_operand >> 16i32 - count; - *flags_changed &= !1i32 & !FLAG_OVERFLOW; - *flags = *flags & !1i32 & !FLAG_OVERFLOW - | result & 1i32 - | (result << 11i32 ^ result >> 4i32) & FLAG_OVERFLOW; + count &= 15; + let mut result: i32 = dest_operand << count | dest_operand >> 16 - count; + *flags_changed &= !1 & !FLAG_OVERFLOW; + *flags = *flags & !1 & !FLAG_OVERFLOW + | result & 1 + | (result << 11 ^ result >> 4) & FLAG_OVERFLOW; return result; }; } @@ -463,44 +463,43 @@ pub unsafe fn rol32(mut dest_operand: i32, mut count: i32) -> i32 { } else { let mut result: i32 = - ((dest_operand << count) as u32 | dest_operand as u32 >> 32i32 - count) as i32; - *flags_changed &= !1i32 & !FLAG_OVERFLOW; - *flags = *flags & !1i32 & !FLAG_OVERFLOW - | result & 1i32 - | (result << 11i32 ^ result >> 20i32) & FLAG_OVERFLOW; + ((dest_operand << count) as u32 | dest_operand as u32 >> 32 - count) as i32; + *flags_changed &= !1 & !FLAG_OVERFLOW; + *flags = *flags & !1 & !FLAG_OVERFLOW + | result & 1 + | (result << 11 ^ result >> 20) & FLAG_OVERFLOW; return result; }; } #[no_mangle] pub unsafe fn rcl8(mut dest_operand: i32, mut count: i32) -> i32 { - count %= 9i32; + count %= 9; if 0 == count { return dest_operand; } else { let mut result: i32 = - dest_operand << count | (getcf() as i32) << count - 1i32 | dest_operand >> 9i32 - count; - *flags_changed &= !1i32 & !FLAG_OVERFLOW; - *flags = *flags & !1i32 & !FLAG_OVERFLOW - | result >> 8i32 & 1i32 - | (result << 3i32 ^ result << 4i32) & FLAG_OVERFLOW; + dest_operand << count | (getcf() as i32) << count - 1 | dest_operand >> 9 - count; + *flags_changed &= !1 & !FLAG_OVERFLOW; + *flags = *flags & !1 & !FLAG_OVERFLOW + | result >> 8 & 1 + | (result << 3 ^ result << 4) & FLAG_OVERFLOW; return result; }; } #[no_mangle] pub unsafe fn rcl16(mut dest_operand: i32, mut count: i32) -> i32 { - count %= 17i32; + count %= 17; if 0 == count { return dest_operand; } else { - let mut result: i32 = dest_operand << count - | (getcf() as i32) << count - 1i32 - | dest_operand >> 17i32 - count; - *flags_changed &= !1i32 & !FLAG_OVERFLOW; - *flags = *flags & !1i32 & !FLAG_OVERFLOW - | result >> 16i32 & 1i32 - | (result >> 5i32 ^ result >> 4i32) & FLAG_OVERFLOW; + let mut result: i32 = + dest_operand << count | (getcf() as i32) << count - 1 | dest_operand >> 17 - count; + *flags_changed &= !1 & !FLAG_OVERFLOW; + *flags = *flags & !1 & !FLAG_OVERFLOW + | result >> 16 & 1 + | (result >> 5 ^ result >> 4) & FLAG_OVERFLOW; return result; }; } @@ -510,14 +509,14 @@ pub unsafe fn rcl32(mut dest_operand: i32, mut count: i32) -> i32 { return dest_operand; } else { - let mut result: i32 = dest_operand << count | (getcf() as i32) << count - 1i32; - if count > 1i32 { - result = (result as u32 | dest_operand as u32 >> 33i32 - count) as i32 + let mut result: i32 = dest_operand << count | (getcf() as i32) << count - 1; + if count > 1 { + result = (result as u32 | dest_operand as u32 >> 33 - count) as i32 } - *flags_changed &= !1i32 & !FLAG_OVERFLOW; - *flags = ((*flags & !1i32 & !FLAG_OVERFLOW) as u32 - | dest_operand as u32 >> 32i32 - count & 1i32 as u32) as i32; - *flags |= (*flags << 11i32 ^ result >> 20i32) & FLAG_OVERFLOW; + *flags_changed &= !1 & !FLAG_OVERFLOW; + *flags = ((*flags & !1 & !FLAG_OVERFLOW) as u32 + | dest_operand as u32 >> 32 - count & 1 as u32) as i32; + *flags |= (*flags << 11 ^ result >> 20) & FLAG_OVERFLOW; return result; }; } @@ -527,12 +526,12 @@ pub unsafe fn ror8(mut dest_operand: i32, mut count: i32) -> i32 { return dest_operand; } else { - count &= 7i32; - let mut result: i32 = dest_operand >> count | dest_operand << 8i32 - count; - *flags_changed &= !1i32 & !FLAG_OVERFLOW; - *flags = *flags & !1i32 & !FLAG_OVERFLOW - | result >> 7i32 & 1i32 - | (result << 4i32 ^ result << 5i32) & FLAG_OVERFLOW; + count &= 7; + let mut result: i32 = dest_operand >> count | dest_operand << 8 - count; + *flags_changed &= !1 & !FLAG_OVERFLOW; + *flags = *flags & !1 & !FLAG_OVERFLOW + | result >> 7 & 1 + | (result << 4 ^ result << 5) & FLAG_OVERFLOW; return result; }; } @@ -542,12 +541,12 @@ pub unsafe fn ror16(mut dest_operand: i32, mut count: i32) -> i32 { return dest_operand; } else { - count &= 15i32; - let mut result: i32 = dest_operand >> count | dest_operand << 16i32 - count; - *flags_changed &= !1i32 & !FLAG_OVERFLOW; - *flags = *flags & !1i32 & !FLAG_OVERFLOW - | result >> 15i32 & 1i32 - | (result >> 4i32 ^ result >> 3i32) & FLAG_OVERFLOW; + count &= 15; + let mut result: i32 = dest_operand >> count | dest_operand << 16 - count; + *flags_changed &= !1 & !FLAG_OVERFLOW; + *flags = *flags & !1 & !FLAG_OVERFLOW + | result >> 15 & 1 + | (result >> 4 ^ result >> 3) & FLAG_OVERFLOW; return result; }; } @@ -558,44 +557,43 @@ pub unsafe fn ror32(mut dest_operand: i32, mut count: i32) -> i32 { } else { let mut result: i32 = - (dest_operand as u32 >> count | (dest_operand << 32i32 - count) as u32) as i32; - *flags_changed &= !1i32 & !FLAG_OVERFLOW; - *flags = *flags & !1i32 & !FLAG_OVERFLOW - | result >> 31i32 & 1i32 - | (result >> 20i32 ^ result >> 19i32) & FLAG_OVERFLOW; + (dest_operand as u32 >> count | (dest_operand << 32 - count) as u32) as i32; + *flags_changed &= !1 & !FLAG_OVERFLOW; + *flags = *flags & !1 & !FLAG_OVERFLOW + | result >> 31 & 1 + | (result >> 20 ^ result >> 19) & FLAG_OVERFLOW; return result; }; } #[no_mangle] pub unsafe fn rcr8(mut dest_operand: i32, mut count: i32) -> i32 { - count %= 9i32; + count %= 9; if 0 == count { return dest_operand; } else { let mut result: i32 = - dest_operand >> count | (getcf() as i32) << 8i32 - count | dest_operand << 9i32 - count; - *flags_changed &= !1i32 & !FLAG_OVERFLOW; - *flags = *flags & !1i32 & !FLAG_OVERFLOW - | result >> 8i32 & 1i32 - | (result << 4i32 ^ result << 5i32) & FLAG_OVERFLOW; + dest_operand >> count | (getcf() as i32) << 8 - count | dest_operand << 9 - count; + *flags_changed &= !1 & !FLAG_OVERFLOW; + *flags = *flags & !1 & !FLAG_OVERFLOW + | result >> 8 & 1 + | (result << 4 ^ result << 5) & FLAG_OVERFLOW; return result; }; } #[no_mangle] pub unsafe fn rcr16(mut dest_operand: i32, mut count: i32) -> i32 { - count %= 17i32; + count %= 17; if 0 == count { return dest_operand; } else { - let mut result: i32 = dest_operand >> count - | (getcf() as i32) << 16i32 - count - | dest_operand << 17i32 - count; - *flags_changed &= !1i32 & !FLAG_OVERFLOW; - *flags = *flags & !1i32 & !FLAG_OVERFLOW - | result >> 16i32 & 1i32 - | (result >> 4i32 ^ result >> 3i32) & FLAG_OVERFLOW; + let mut result: i32 = + dest_operand >> count | (getcf() as i32) << 16 - count | dest_operand << 17 - count; + *flags_changed &= !1 & !FLAG_OVERFLOW; + *flags = *flags & !1 & !FLAG_OVERFLOW + | result >> 16 & 1 + | (result >> 4 ^ result >> 3) & FLAG_OVERFLOW; return result; }; } @@ -606,27 +604,27 @@ pub unsafe fn rcr32(mut dest_operand: i32, mut count: i32) -> i32 { } else { let mut result: i32 = - (dest_operand as u32 >> count | ((getcf() as i32) << 32i32 - count) as u32) as i32; - if count > 1i32 { - result |= dest_operand << 33i32 - count + (dest_operand as u32 >> count | ((getcf() as i32) << 32 - count) as u32) as i32; + if count > 1 { + result |= dest_operand << 33 - count } - *flags_changed &= !1i32 & !FLAG_OVERFLOW; - *flags = *flags & !1i32 & !FLAG_OVERFLOW - | dest_operand >> count - 1i32 & 1i32 - | (result >> 20i32 ^ result >> 19i32) & FLAG_OVERFLOW; + *flags_changed &= !1 & !FLAG_OVERFLOW; + *flags = *flags & !1 & !FLAG_OVERFLOW + | dest_operand >> count - 1 & 1 + | (result >> 20 ^ result >> 19) & FLAG_OVERFLOW; return result; }; } #[no_mangle] pub unsafe fn div8(mut source_operand: u32) { - if source_operand == 0i32 as u32 { + if source_operand == 0 as u32 { trigger_de(); return; } else { let mut target_operand: u16 = *reg16.offset(AX as isize); let mut result: u16 = (target_operand as u32).wrapping_div(source_operand) as u16; - if result as i32 >= 256i32 { + if result as i32 >= 256 { trigger_de(); } else { @@ -638,14 +636,14 @@ pub unsafe fn div8(mut source_operand: u32) { } #[no_mangle] pub unsafe fn idiv8(mut source_operand: i32) { - if source_operand == 0i32 { + if source_operand == 0 { trigger_de(); return; } else { let mut target_operand: i32 = *reg16s.offset(AX as isize) as i32; let mut result: i32 = target_operand / source_operand; - if result >= 128i32 || result <= -129i32 { + if result >= 128 || result <= -129 { trigger_de(); } else { @@ -657,16 +655,15 @@ pub unsafe fn idiv8(mut source_operand: i32) { } #[no_mangle] pub unsafe fn div16(mut source_operand: u32) { - if source_operand == 0i32 as u32 { + if source_operand == 0 as u32 { trigger_de(); return; } else { - let mut target_operand: u32 = (*reg16.offset(AX as isize) as i32 - | (*reg16.offset(DX as isize) as i32) << 16i32) - as u32; + let mut target_operand: u32 = + (*reg16.offset(AX as isize) as i32 | (*reg16.offset(DX as isize) as i32) << 16) as u32; let mut result: u32 = target_operand.wrapping_div(source_operand); - if result >= 65536i32 as u32 { + if result >= 65536 as u32 { trigger_de(); } else { @@ -678,15 +675,15 @@ pub unsafe fn div16(mut source_operand: u32) { } #[no_mangle] pub unsafe fn idiv16(mut source_operand: i32) { - if source_operand == 0i32 { + if source_operand == 0 { trigger_de(); return; } else { let mut target_operand: i32 = - *reg16.offset(AX as isize) as i32 | (*reg16.offset(DX as isize) as i32) << 16i32; + *reg16.offset(AX as isize) as i32 | (*reg16.offset(DX as isize) as i32) << 16; let mut result: i32 = target_operand / source_operand; - if result >= 32768i32 || result <= -32769i32 { + if result >= 32768 || result <= -32769 { trigger_de(); } else { @@ -698,16 +695,16 @@ pub unsafe fn idiv16(mut source_operand: i32) { } #[no_mangle] pub unsafe fn div32(mut source_operand: u32) { - if source_operand == 0i32 as u32 { + if source_operand == 0 as u32 { trigger_de(); return; } else { let mut target_low: u32 = *reg32s.offset(EAX as isize) as u32; let mut target_high: u32 = *reg32s.offset(EDX as isize) as u32; - let mut target_operand: u64 = (target_high as u64) << 32i32 | target_low as u64; + let mut target_operand: u64 = (target_high as u64) << 32 | target_low as u64; let mut result: u64 = target_operand.wrapping_div(source_operand as u64); - if result > 4294967295u32 as u64 { + if result > 4294967295 as u64 { trigger_de(); return; } @@ -721,23 +718,21 @@ pub unsafe fn div32(mut source_operand: u32) { } #[no_mangle] pub unsafe fn idiv32(mut source_operand: i32) { - if source_operand == 0i32 { + if source_operand == 0 { trigger_de(); return; } else { let mut target_low: u32 = *reg32s.offset(EAX as isize) as u32; let mut target_high: u32 = *reg32s.offset(EDX as isize) as u32; - let mut target_operand: i64 = ((target_high as u64) << 32i32 | target_low as u64) as i64; - if source_operand == -1i32 - && target_operand == (-1i32 as i64 - 9223372036854775807i64) as i64 - { + let mut target_operand: i64 = ((target_high as u64) << 32 | target_low as u64) as i64; + if source_operand == -1 && target_operand == (-1 as i64 - 9223372036854775807i64) as i64 { trigger_de(); return; } else { let mut result: i64 = target_operand / source_operand as i64; - if result < (-1i32 - 2147483647i32) as i64 || result > 2147483647i32 as i64 { + if result < (-1 - 2147483647) as i64 || result > 2147483647 as i64 { trigger_de(); return; } @@ -752,221 +747,216 @@ pub unsafe fn idiv32(mut source_operand: i32) { } #[no_mangle] pub unsafe fn shl8(mut dest_operand: i32, mut count: i32) -> i32 { - if count == 0i32 { + if count == 0 { return dest_operand; } else { *last_result = dest_operand << count; *last_op_size = OPSIZE_8; - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; - *flags = *flags & !1i32 & !FLAG_OVERFLOW - | *last_result >> 8i32 & 1i32 - | (*last_result << 3i32 ^ *last_result << 4i32) & FLAG_OVERFLOW; + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; + *flags = *flags & !1 & !FLAG_OVERFLOW + | *last_result >> 8 & 1 + | (*last_result << 3 ^ *last_result << 4) & FLAG_OVERFLOW; return *last_result; }; } #[no_mangle] pub unsafe fn shl16(mut dest_operand: i32, mut count: i32) -> i32 { - if count == 0i32 { + if count == 0 { return dest_operand; } else { *last_result = dest_operand << count; *last_op_size = OPSIZE_16; - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; - *flags = *flags & !1i32 & !FLAG_OVERFLOW - | *last_result >> 16i32 & 1i32 - | (*last_result >> 5i32 ^ *last_result >> 4i32) & FLAG_OVERFLOW; + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; + *flags = *flags & !1 & !FLAG_OVERFLOW + | *last_result >> 16 & 1 + | (*last_result >> 5 ^ *last_result >> 4) & FLAG_OVERFLOW; return *last_result; }; } #[no_mangle] pub unsafe fn shl32(mut dest_operand: i32, mut count: i32) -> i32 { - if count == 0i32 { + if count == 0 { return dest_operand; } else { *last_result = dest_operand << count; *last_op_size = OPSIZE_32; - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; // test this - *flags = *flags & !1i32 & !FLAG_OVERFLOW | dest_operand >> 32i32 - count & 1i32; - *flags |= (*flags & 1i32 ^ *last_result >> 31i32 & 1i32) << 11i32 & FLAG_OVERFLOW; + *flags = *flags & !1 & !FLAG_OVERFLOW | dest_operand >> 32 - count & 1; + *flags |= (*flags & 1 ^ *last_result >> 31 & 1) << 11 & FLAG_OVERFLOW; return *last_result; }; } #[no_mangle] pub unsafe fn shr8(mut dest_operand: i32, mut count: i32) -> i32 { - if count == 0i32 { + if count == 0 { return dest_operand; } else { *last_result = dest_operand >> count; *last_op_size = OPSIZE_8; - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; - *flags = *flags & !1i32 & !FLAG_OVERFLOW - | dest_operand >> count - 1i32 & 1i32 - | (dest_operand >> 7i32 & 1i32) << 11i32 & FLAG_OVERFLOW; + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; + *flags = *flags & !1 & !FLAG_OVERFLOW + | dest_operand >> count - 1 & 1 + | (dest_operand >> 7 & 1) << 11 & FLAG_OVERFLOW; return *last_result; }; } #[no_mangle] pub unsafe fn shr16(mut dest_operand: i32, mut count: i32) -> i32 { - if count == 0i32 { + if count == 0 { return dest_operand; } else { *last_result = dest_operand >> count; *last_op_size = OPSIZE_16; - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; - *flags = *flags & !1i32 & !FLAG_OVERFLOW - | dest_operand >> count - 1i32 & 1i32 - | dest_operand >> 4i32 & FLAG_OVERFLOW; + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; + *flags = *flags & !1 & !FLAG_OVERFLOW + | dest_operand >> count - 1 & 1 + | dest_operand >> 4 & FLAG_OVERFLOW; return *last_result; }; } #[no_mangle] pub unsafe fn shr32(mut dest_operand: i32, mut count: i32) -> i32 { - if count == 0i32 { + if count == 0 { return dest_operand; } else { *last_result = (dest_operand as u32 >> count) as i32; *last_op_size = OPSIZE_32; - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; - *flags = ((*flags & !1i32 & !FLAG_OVERFLOW) as u32 - | dest_operand as u32 >> count - 1i32 & 1i32 as u32 - | (dest_operand >> 20i32 & FLAG_OVERFLOW) as u32) as i32; + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; + *flags = ((*flags & !1 & !FLAG_OVERFLOW) as u32 + | dest_operand as u32 >> count - 1 & 1 as u32 + | (dest_operand >> 20 & FLAG_OVERFLOW) as u32) as i32; return *last_result; }; } #[no_mangle] pub unsafe fn sar8(mut dest_operand: i32, mut count: i32) -> i32 { - if count == 0i32 { + if count == 0 { return dest_operand; } else { - if count < 8i32 { - *last_result = dest_operand << 24i32 >> count + 24i32; + if count < 8 { + *last_result = dest_operand << 24 >> count + 24; // of is zero - *flags = *flags & !1i32 & !FLAG_OVERFLOW | dest_operand >> count - 1i32 & 1i32 + *flags = *flags & !1 & !FLAG_OVERFLOW | dest_operand >> count - 1 & 1 } else { - *last_result = dest_operand << 24i32 >> 31i32; - *flags = *flags & !1i32 & !FLAG_OVERFLOW | *last_result & 1i32 + *last_result = dest_operand << 24 >> 31; + *flags = *flags & !1 & !FLAG_OVERFLOW | *last_result & 1 } *last_op_size = OPSIZE_8; - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; return *last_result; }; } #[no_mangle] pub unsafe fn sar16(mut dest_operand: i32, mut count: i32) -> i32 { - if count == 0i32 { + if count == 0 { return dest_operand; } else { - if count < 16i32 { - *last_result = dest_operand << 16i32 >> count + 16i32; - *flags = *flags & !1i32 & !FLAG_OVERFLOW | dest_operand >> count - 1i32 & 1i32 + if count < 16 { + *last_result = dest_operand << 16 >> count + 16; + *flags = *flags & !1 & !FLAG_OVERFLOW | dest_operand >> count - 1 & 1 } else { - *last_result = dest_operand << 16i32 >> 31i32; - *flags = *flags & !1i32 & !FLAG_OVERFLOW | *last_result & 1i32 + *last_result = dest_operand << 16 >> 31; + *flags = *flags & !1 & !FLAG_OVERFLOW | *last_result & 1 } *last_op_size = OPSIZE_16; - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; return *last_result; }; } #[no_mangle] pub unsafe fn sar32(mut dest_operand: i32, mut count: i32) -> i32 { - if count == 0i32 { + if count == 0 { return dest_operand; } else { *last_result = dest_operand >> count; *last_op_size = OPSIZE_32; - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; - *flags = ((*flags & !1i32 & !FLAG_OVERFLOW) as u32 - | dest_operand as u32 >> count - 1i32 & 1i32 as u32) as i32; + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; + *flags = ((*flags & !1 & !FLAG_OVERFLOW) as u32 + | dest_operand as u32 >> count - 1 & 1 as u32) as i32; return *last_result; }; } #[no_mangle] pub unsafe fn shrd16(mut dest_operand: i32, mut source_operand: i32, mut count: i32) -> i32 { - if count == 0i32 { + if count == 0 { return dest_operand; } else { - if count <= 16i32 { - *last_result = dest_operand >> count | source_operand << 16i32 - count; - *flags = *flags & !1i32 | dest_operand >> count - 1i32 & 1i32 + if count <= 16 { + *last_result = dest_operand >> count | source_operand << 16 - count; + *flags = *flags & !1 | dest_operand >> count - 1 & 1 } else { - *last_result = dest_operand << 32i32 - count | source_operand >> count - 16i32; - *flags = *flags & !1i32 | source_operand >> count - 17i32 & 1i32 + *last_result = dest_operand << 32 - count | source_operand >> count - 16; + *flags = *flags & !1 | source_operand >> count - 17 & 1 } *last_op_size = OPSIZE_16; - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; - *flags = *flags & !FLAG_OVERFLOW | (*last_result ^ dest_operand) >> 4i32 & FLAG_OVERFLOW; + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; + *flags = *flags & !FLAG_OVERFLOW | (*last_result ^ dest_operand) >> 4 & FLAG_OVERFLOW; return *last_result; }; } #[no_mangle] pub unsafe fn shrd32(mut dest_operand: i32, mut source_operand: i32, mut count: i32) -> i32 { - if count == 0i32 { + if count == 0 { return dest_operand; } else { *last_result = - (dest_operand as u32 >> count | (source_operand << 32i32 - count) as u32) as i32; + (dest_operand as u32 >> count | (source_operand << 32 - count) as u32) as i32; *last_op_size = OPSIZE_32; - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; - *flags = - ((*flags & !1i32) as u32 | dest_operand as u32 >> count - 1i32 & 1i32 as u32) as i32; - *flags = *flags & !FLAG_OVERFLOW | (*last_result ^ dest_operand) >> 20i32 & FLAG_OVERFLOW; + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; + *flags = ((*flags & !1) as u32 | dest_operand as u32 >> count - 1 & 1 as u32) as i32; + *flags = *flags & !FLAG_OVERFLOW | (*last_result ^ dest_operand) >> 20 & FLAG_OVERFLOW; return *last_result; }; } #[no_mangle] pub unsafe fn shld16(mut dest_operand: i32, mut source_operand: i32, mut count: i32) -> i32 { - if count == 0i32 { + if count == 0 { return dest_operand; } else { - if count <= 16i32 { + if count <= 16 { *last_result = - ((dest_operand << count) as u32 | source_operand as u32 >> 16i32 - count) as i32; - *flags = ((*flags & !1i32) as u32 | dest_operand as u32 >> 16i32 - count & 1i32 as u32) - as i32 + ((dest_operand << count) as u32 | source_operand as u32 >> 16 - count) as i32; + *flags = ((*flags & !1) as u32 | dest_operand as u32 >> 16 - count & 1 as u32) as i32 } else { - *last_result = dest_operand >> 32i32 - count | source_operand << count - 16i32; - *flags = ((*flags & !1i32) as u32 - | source_operand as u32 >> 32i32 - count & 1i32 as u32) as i32 + *last_result = dest_operand >> 32 - count | source_operand << count - 16; + *flags = ((*flags & !1) as u32 | source_operand as u32 >> 32 - count & 1 as u32) as i32 } *last_op_size = OPSIZE_16; - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; - *flags = *flags & !FLAG_OVERFLOW | (*flags & 1i32 ^ *last_result >> 15i32 & 1i32) << 11i32; + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; + *flags = *flags & !FLAG_OVERFLOW | (*flags & 1 ^ *last_result >> 15 & 1) << 11; return *last_result; }; } #[no_mangle] pub unsafe fn shld32(mut dest_operand: i32, mut source_operand: i32, mut count: i32) -> i32 { - if count == 0i32 { + if count == 0 { return dest_operand; } else { *last_result = - ((dest_operand << count) as u32 | source_operand as u32 >> 32i32 - count) as i32; + ((dest_operand << count) as u32 | source_operand as u32 >> 32 - count) as i32; *last_op_size = OPSIZE_32; - *flags_changed = FLAGS_ALL & !1i32 & !FLAG_OVERFLOW; - *flags = - ((*flags & !1i32) as u32 | dest_operand as u32 >> 32i32 - count & 1i32 as u32) as i32; - if count == 1i32 { - *flags = - *flags & !FLAG_OVERFLOW | (*flags & 1i32 ^ *last_result >> 31i32 & 1i32) << 11i32 + *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; + *flags = ((*flags & !1) as u32 | dest_operand as u32 >> 32 - count & 1 as u32) as i32; + if count == 1 { + *flags = *flags & !FLAG_OVERFLOW | (*flags & 1 ^ *last_result >> 31 & 1) << 11 } else { *flags &= !FLAG_OVERFLOW @@ -976,69 +966,69 @@ pub unsafe fn shld32(mut dest_operand: i32, mut source_operand: i32, mut count: } #[no_mangle] pub unsafe fn bt_reg(mut bit_base: i32, mut bit_offset: i32) { - *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; - *flags_changed &= !1i32; + *flags = *flags & !1 | bit_base >> bit_offset & 1; + *flags_changed &= !1; } #[no_mangle] pub unsafe fn btc_reg(mut bit_base: i32, mut bit_offset: i32) -> i32 { - *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; - *flags_changed &= !1i32; - return bit_base ^ 1i32 << bit_offset; + *flags = *flags & !1 | bit_base >> bit_offset & 1; + *flags_changed &= !1; + return bit_base ^ 1 << bit_offset; } #[no_mangle] pub unsafe fn bts_reg(mut bit_base: i32, mut bit_offset: i32) -> i32 { - *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; - *flags_changed &= !1i32; - return bit_base | 1i32 << bit_offset; + *flags = *flags & !1 | bit_base >> bit_offset & 1; + *flags_changed &= !1; + return bit_base | 1 << bit_offset; } #[no_mangle] pub unsafe fn btr_reg(mut bit_base: i32, mut bit_offset: i32) -> i32 { - *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; - *flags_changed &= !1i32; - return bit_base & !(1i32 << bit_offset); + *flags = *flags & !1 | bit_base >> bit_offset & 1; + *flags_changed &= !1; + return bit_base & !(1 << bit_offset); } #[no_mangle] pub unsafe fn bt_mem(mut virt_addr: i32, mut bit_offset: i32) { - let mut bit_base: i32 = return_on_pagefault!(safe_read8(virt_addr + (bit_offset >> 3i32))); - bit_offset &= 7i32; - *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; - *flags_changed &= !1i32; + let mut bit_base: i32 = return_on_pagefault!(safe_read8(virt_addr + (bit_offset >> 3))); + bit_offset &= 7; + *flags = *flags & !1 | bit_base >> bit_offset & 1; + *flags_changed &= !1; } #[no_mangle] pub unsafe fn btc_mem(mut virt_addr: i32, mut bit_offset: i32) { let mut phys_addr: i32 = - return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3i32))) as i32; + return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3))) as i32; let mut bit_base: i32 = read8(phys_addr as u32); - bit_offset &= 7i32; - *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; - *flags_changed &= !1i32; - write8(phys_addr as u32, bit_base ^ 1i32 << bit_offset); + bit_offset &= 7; + *flags = *flags & !1 | bit_base >> bit_offset & 1; + *flags_changed &= !1; + write8(phys_addr as u32, bit_base ^ 1 << bit_offset); } #[no_mangle] pub unsafe fn btr_mem(mut virt_addr: i32, mut bit_offset: i32) { let mut phys_addr: i32 = - return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3i32))) as i32; + return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3))) as i32; let mut bit_base: i32 = read8(phys_addr as u32); - bit_offset &= 7i32; - *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; - *flags_changed &= !1i32; - write8(phys_addr as u32, bit_base & !(1i32 << bit_offset)); + bit_offset &= 7; + *flags = *flags & !1 | bit_base >> bit_offset & 1; + *flags_changed &= !1; + write8(phys_addr as u32, bit_base & !(1 << bit_offset)); } #[no_mangle] pub unsafe fn bts_mem(mut virt_addr: i32, mut bit_offset: i32) { let mut phys_addr: i32 = - return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3i32))) as i32; + return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3))) as i32; let mut bit_base: i32 = read8(phys_addr as u32); - bit_offset &= 7i32; - *flags = *flags & !1i32 | bit_base >> bit_offset & 1i32; - *flags_changed &= !1i32; - write8(phys_addr as u32, bit_base | 1i32 << bit_offset); + bit_offset &= 7; + *flags = *flags & !1 | bit_base >> bit_offset & 1; + *flags_changed &= !1; + write8(phys_addr as u32, bit_base | 1 << bit_offset); } #[no_mangle] pub unsafe fn bsf16(mut old: i32, mut bit_base: i32) -> i32 { *flags_changed = FLAGS_ALL & !FLAG_ZERO; *last_op_size = OPSIZE_16; - if bit_base == 0i32 { + if bit_base == 0 { *flags |= FLAG_ZERO; *last_result = bit_base; // not defined in the docs, but value doesn't change on my intel machine @@ -1054,7 +1044,7 @@ pub unsafe fn bsf16(mut old: i32, mut bit_base: i32) -> i32 { pub unsafe fn bsf32(mut old: i32, mut bit_base: i32) -> i32 { *flags_changed = FLAGS_ALL & !FLAG_ZERO; *last_op_size = OPSIZE_32; - if bit_base == 0i32 { + if bit_base == 0 { *flags |= FLAG_ZERO; *last_result = bit_base; return old; @@ -1069,7 +1059,7 @@ pub unsafe fn bsf32(mut old: i32, mut bit_base: i32) -> i32 { pub unsafe fn bsr16(mut old: i32, mut bit_base: i32) -> i32 { *flags_changed = FLAGS_ALL & !FLAG_ZERO; *last_op_size = OPSIZE_16; - if bit_base == 0i32 { + if bit_base == 0 { *flags |= FLAG_ZERO; *last_result = bit_base; return old; @@ -1084,7 +1074,7 @@ pub unsafe fn bsr16(mut old: i32, mut bit_base: i32) -> i32 { pub unsafe fn bsr32(mut old: i32, mut bit_base: i32) -> i32 { *flags_changed = FLAGS_ALL & !FLAG_ZERO; *last_op_size = OPSIZE_32; - if bit_base == 0i32 { + if bit_base == 0 { *flags |= FLAG_ZERO; *last_result = bit_base; return old; @@ -1097,102 +1087,102 @@ pub unsafe fn bsr32(mut old: i32, mut bit_base: i32) -> i32 { } #[no_mangle] pub unsafe fn popcnt(mut v: i32) -> i32 { - *flags_changed = 0i32; + *flags_changed = 0; *flags &= !FLAGS_ALL; if 0 != v { return v.count_ones() as i32; } else { *flags |= FLAG_ZERO; - return 0i32; + return 0; }; } #[no_mangle] pub unsafe fn saturate_sw_to_ub(mut v: u32) -> u32 { - dbg_assert!(v & 4294901760u32 == 0i32 as u32); + dbg_assert!(v & 4294901760 == 0 as u32); let mut ret: u32 = v; - if ret >= 32768i32 as u32 { - ret = 0i32 as u32 + if ret >= 32768 as u32 { + ret = 0 as u32 } - else if ret > 255i32 as u32 { - ret = 255i32 as u32 + else if ret > 255 as u32 { + ret = 255 as u32 } - dbg_assert!(ret & 4294967040u32 == 0i32 as u32); + dbg_assert!(ret & 4294967040 == 0 as u32); return ret; } #[no_mangle] pub unsafe fn saturate_sw_to_sb(mut v: i32) -> i32 { - dbg_assert!(v as u32 & 4294901760u32 == 0i32 as u32); + dbg_assert!(v as u32 & 4294901760 == 0 as u32); let mut ret: i32 = v; - if ret > 65408i32 { - ret = ret & 255i32 + if ret > 65408 { + ret = ret & 255 } - else if ret > 32767i32 { - ret = 128i32 + else if ret > 32767 { + ret = 128 } - else if ret > 127i32 { - ret = 127i32 + else if ret > 127 { + ret = 127 } - dbg_assert!(ret as u32 & 4294967040u32 == 0i32 as u32); + dbg_assert!(ret as u32 & 4294967040 == 0 as u32); return ret; } #[no_mangle] pub unsafe fn saturate_sd_to_sw(mut v: u32) -> u32 { let mut ret: u32 = v; - if ret > 4294934528u32 { - ret = ret & 65535i32 as u32 + if ret > 4294934528 { + ret = ret & 65535 as u32 } - else if ret > 2147483647i32 as u32 { - ret = 32768i32 as u32 + else if ret > 2147483647 as u32 { + ret = 32768 as u32 } - else if ret > 32767i32 as u32 { - ret = 32767i32 as u32 + else if ret > 32767 as u32 { + ret = 32767 as u32 } - dbg_assert!(ret & 4294901760u32 == 0i32 as u32); + dbg_assert!(ret & 4294901760 == 0 as u32); return ret; } #[no_mangle] pub unsafe fn saturate_sd_to_sb(mut v: u32) -> u32 { let mut ret: u32 = v; - if ret > 4294967168u32 { - ret = ret & 255i32 as u32 + if ret > 4294967168 { + ret = ret & 255 as u32 } - else if ret > 2147483647i32 as u32 { - ret = 128i32 as u32 + else if ret > 2147483647 as u32 { + ret = 128 as u32 } - else if ret > 127i32 as u32 { - ret = 127i32 as u32 + else if ret > 127 as u32 { + ret = 127 as u32 } - dbg_assert!(ret & 4294967040u32 == 0i32 as u32); + dbg_assert!(ret & 4294967040 == 0 as u32); return ret; } #[no_mangle] pub unsafe fn saturate_sd_to_ub(mut v: i32) -> i32 { let mut ret: i32 = v; - if ret < 0i32 { - ret = 0i32 + if ret < 0 { + ret = 0 } - dbg_assert!(ret as u32 & 4294967040u32 == 0i32 as u32); + dbg_assert!(ret as u32 & 4294967040 == 0 as u32); return ret; } #[no_mangle] pub unsafe fn saturate_ud_to_ub(mut v: u32) -> u32 { let mut ret: u32 = v; - if ret > 255i32 as u32 { - ret = 255i32 as u32 + if ret > 255 as u32 { + ret = 255 as u32 } - dbg_assert!(ret & 4294967040u32 == 0i32 as u32); + dbg_assert!(ret & 4294967040 == 0 as u32); return ret; } #[no_mangle] pub unsafe fn saturate_uw(mut v: u32) -> i32 { let mut ret: u32 = v; - if ret > 2147483647i32 as u32 { - ret = 0i32 as u32 + if ret > 2147483647 as u32 { + ret = 0 as u32 } - else if ret > 65535i32 as u32 { - ret = 65535i32 as u32 + else if ret > 65535 as u32 { + ret = 65535 as u32 } - dbg_assert!(ret & 4294901760u32 == 0i32 as u32); + dbg_assert!(ret & 4294901760 == 0 as u32); return ret as i32; } diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 0b9bf6f8..f6cfc347 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -61,24 +61,24 @@ pub union reg128 { pub f64_0: [f64; 2], } -pub const FLAG_CARRY: i32 = 1i32; -pub const FLAG_PARITY: i32 = 4i32; -pub const FLAG_ADJUST: i32 = 16i32; -pub const FLAG_ZERO: i32 = 64i32; -pub const FLAG_SIGN: i32 = 128i32; -pub const FLAG_TRAP: i32 = 256i32; -pub const FLAG_INTERRUPT: i32 = 512i32; -pub const FLAG_DIRECTION: i32 = 1024i32; -pub const FLAG_OVERFLOW: i32 = 2048i32; -pub const FLAG_IOPL: i32 = 1i32 << 12i32 | 1i32 << 13i32; -pub const FLAG_NT: i32 = 1i32 << 14i32; -pub const FLAG_RF: i32 = 1i32 << 16i32; -pub const FLAG_VM: i32 = 1i32 << 17i32; -pub const FLAG_AC: i32 = 1i32 << 18i32; -pub const FLAG_VIF: i32 = 1i32 << 19i32; -pub const FLAG_VIP: i32 = 1i32 << 20i32; -pub const FLAG_ID: i32 = 1i32 << 21i32; -pub const FLAGS_DEFAULT: i32 = 1i32 << 1i32; +pub const FLAG_CARRY: i32 = 1; +pub const FLAG_PARITY: i32 = 4; +pub const FLAG_ADJUST: i32 = 16; +pub const FLAG_ZERO: i32 = 64; +pub const FLAG_SIGN: i32 = 128; +pub const FLAG_TRAP: i32 = 256; +pub const FLAG_INTERRUPT: i32 = 512; +pub const FLAG_DIRECTION: i32 = 1024; +pub const FLAG_OVERFLOW: i32 = 2048; +pub const FLAG_IOPL: i32 = 1 << 12 | 1 << 13; +pub const FLAG_NT: i32 = 1 << 14; +pub const FLAG_RF: i32 = 1 << 16; +pub const FLAG_VM: i32 = 1 << 17; +pub const FLAG_AC: i32 = 1 << 18; +pub const FLAG_VIF: i32 = 1 << 19; +pub const FLAG_VIP: i32 = 1 << 20; +pub const FLAG_ID: i32 = 1 << 21; +pub const FLAGS_DEFAULT: i32 = 1 << 1; pub const FLAGS_MASK: i32 = FLAG_CARRY | FLAG_PARITY | FLAG_ADJUST @@ -98,170 +98,170 @@ pub const FLAGS_MASK: i32 = FLAG_CARRY | FLAG_ID; pub const FLAGS_ALL: i32 = FLAG_CARRY | FLAG_PARITY | FLAG_ADJUST | FLAG_ZERO | FLAG_SIGN | FLAG_OVERFLOW; -pub const OPSIZE_8: i32 = 7i32; -pub const OPSIZE_16: i32 = 15i32; -pub const OPSIZE_32: i32 = 31i32; -pub const EAX: i32 = 0i32; -pub const ECX: i32 = 1i32; -pub const EDX: i32 = 2i32; -pub const EBX: i32 = 3i32; -pub const ESP: i32 = 4i32; -pub const EBP: i32 = 5i32; -pub const ESI: i32 = 6i32; -pub const EDI: i32 = 7i32; -pub const AX: i32 = 0i32; -pub const CX: i32 = 2i32; -pub const DX: i32 = 4i32; -pub const BX: i32 = 6i32; -pub const SP: i32 = 8i32; -pub const BP: i32 = 10i32; -pub const SI: i32 = 12i32; -pub const DI: i32 = 14i32; -pub const AL: i32 = 0i32; -pub const CL: i32 = 4i32; -pub const DL: i32 = 8i32; -pub const BL: i32 = 12i32; -pub const AH: i32 = 1i32; -pub const CH: i32 = 5i32; -pub const DH: i32 = 9i32; -pub const BH: i32 = 13i32; -pub const ES: i32 = 0i32; -pub const CS: i32 = 1i32; -pub const SS: i32 = 2i32; -pub const DS: i32 = 3i32; -pub const FS: i32 = 4i32; -pub const GS: i32 = 5i32; -pub const TR: i32 = 6i32; -pub const LDTR: i32 = 7i32; -pub const PAGE_TABLE_PRESENT_MASK: i32 = 1i32 << 0i32; -pub const PAGE_TABLE_RW_MASK: i32 = 1i32 << 1i32; -pub const PAGE_TABLE_USER_MASK: i32 = 1i32 << 2i32; -pub const PAGE_TABLE_ACCESSED_MASK: i32 = 1i32 << 5i32; -pub const PAGE_TABLE_DIRTY_MASK: i32 = 1i32 << 6i32; -pub const PAGE_TABLE_PSE_MASK: i32 = 1i32 << 7i32; -pub const PAGE_TABLE_GLOBAL_MASK: i32 = 1i32 << 8i32; -pub const MMAP_BLOCK_BITS: i32 = 17i32; -pub const MMAP_BLOCK_SIZE: i32 = 1i32 << MMAP_BLOCK_BITS; -pub const CR0_PE: i32 = 1i32; -pub const CR0_MP: i32 = 1i32 << 1i32; -pub const CR0_EM: i32 = 1i32 << 2i32; -pub const CR0_TS: i32 = 1i32 << 3i32; -pub const CR0_ET: i32 = 1i32 << 4i32; -pub const CR0_WP: i32 = 1i32 << 16i32; -pub const CR0_NW: i32 = 1i32 << 29i32; -pub const CR0_CD: i32 = 1i32 << 30i32; -pub const CR0_PG: i32 = 1i32 << 31i32; -pub const CR4_VME: i32 = 1i32; -pub const CR4_PVI: i32 = 1i32 << 1i32; -pub const CR4_TSD: i32 = 1i32 << 2i32; -pub const CR4_PSE: i32 = 1i32 << 4i32; -pub const CR4_DE: i32 = 1i32 << 3i32; -pub const CR4_PAE: i32 = 1i32 << 5i32; -pub const CR4_PGE: i32 = 1i32 << 7i32; -pub const IA32_SYSENTER_CS: i32 = 372i32; -pub const IA32_SYSENTER_ESP: i32 = 373i32; -pub const IA32_SYSENTER_EIP: i32 = 374i32; -pub const IA32_TIME_STAMP_COUNTER: i32 = 16i32; -pub const IA32_PLATFORM_ID: i32 = 23i32; -pub const IA32_APIC_BASE_MSR: i32 = 27i32; -pub const IA32_BIOS_SIGN_ID: i32 = 139i32; -pub const MSR_PLATFORM_INFO: i32 = 206i32; -pub const MSR_MISC_FEATURE_ENABLES: i32 = 320i32; -pub const IA32_MISC_ENABLE: i32 = 416i32; -pub const IA32_RTIT_CTL: i32 = 1392i32; -pub const MSR_SMI_COUNT: i32 = 52i32; -pub const IA32_MCG_CAP: i32 = 377i32; -pub const IA32_KERNEL_GS_BASE: i32 = 3221225729u32 as i32; -pub const MSR_PKG_C2_RESIDENCY: i32 = 1549i32; -pub const IA32_APIC_BASE_BSP: i32 = 1i32 << 8i32; -pub const IA32_APIC_BASE_EXTD: i32 = 1i32 << 10i32; -pub const IA32_APIC_BASE_EN: i32 = 1i32 << 11i32; -pub const APIC_ADDRESS: i32 = 4276092928u32 as i32; -pub const SEG_PREFIX_NONE: i32 = -1i32; -pub const SEG_PREFIX_ZERO: i32 = 7i32; -pub const PREFIX_MASK_REP: i32 = 24i32; -pub const PREFIX_REPZ: i32 = 8i32; -pub const PREFIX_REPNZ: i32 = 16i32; -pub const PREFIX_MASK_SEGMENT: i32 = 7i32; -pub const PREFIX_MASK_OPSIZE: i32 = 32i32; -pub const PREFIX_MASK_ADDRSIZE: i32 = 64i32; +pub const OPSIZE_8: i32 = 7; +pub const OPSIZE_16: i32 = 15; +pub const OPSIZE_32: i32 = 31; +pub const EAX: i32 = 0; +pub const ECX: i32 = 1; +pub const EDX: i32 = 2; +pub const EBX: i32 = 3; +pub const ESP: i32 = 4; +pub const EBP: i32 = 5; +pub const ESI: i32 = 6; +pub const EDI: i32 = 7; +pub const AX: i32 = 0; +pub const CX: i32 = 2; +pub const DX: i32 = 4; +pub const BX: i32 = 6; +pub const SP: i32 = 8; +pub const BP: i32 = 10; +pub const SI: i32 = 12; +pub const DI: i32 = 14; +pub const AL: i32 = 0; +pub const CL: i32 = 4; +pub const DL: i32 = 8; +pub const BL: i32 = 12; +pub const AH: i32 = 1; +pub const CH: i32 = 5; +pub const DH: i32 = 9; +pub const BH: i32 = 13; +pub const ES: i32 = 0; +pub const CS: i32 = 1; +pub const SS: i32 = 2; +pub const DS: i32 = 3; +pub const FS: i32 = 4; +pub const GS: i32 = 5; +pub const TR: i32 = 6; +pub const LDTR: i32 = 7; +pub const PAGE_TABLE_PRESENT_MASK: i32 = 1 << 0; +pub const PAGE_TABLE_RW_MASK: i32 = 1 << 1; +pub const PAGE_TABLE_USER_MASK: i32 = 1 << 2; +pub const PAGE_TABLE_ACCESSED_MASK: i32 = 1 << 5; +pub const PAGE_TABLE_DIRTY_MASK: i32 = 1 << 6; +pub const PAGE_TABLE_PSE_MASK: i32 = 1 << 7; +pub const PAGE_TABLE_GLOBAL_MASK: i32 = 1 << 8; +pub const MMAP_BLOCK_BITS: i32 = 17; +pub const MMAP_BLOCK_SIZE: i32 = 1 << MMAP_BLOCK_BITS; +pub const CR0_PE: i32 = 1; +pub const CR0_MP: i32 = 1 << 1; +pub const CR0_EM: i32 = 1 << 2; +pub const CR0_TS: i32 = 1 << 3; +pub const CR0_ET: i32 = 1 << 4; +pub const CR0_WP: i32 = 1 << 16; +pub const CR0_NW: i32 = 1 << 29; +pub const CR0_CD: i32 = 1 << 30; +pub const CR0_PG: i32 = 1 << 31; +pub const CR4_VME: i32 = 1; +pub const CR4_PVI: i32 = 1 << 1; +pub const CR4_TSD: i32 = 1 << 2; +pub const CR4_PSE: i32 = 1 << 4; +pub const CR4_DE: i32 = 1 << 3; +pub const CR4_PAE: i32 = 1 << 5; +pub const CR4_PGE: i32 = 1 << 7; +pub const IA32_SYSENTER_CS: i32 = 372; +pub const IA32_SYSENTER_ESP: i32 = 373; +pub const IA32_SYSENTER_EIP: i32 = 374; +pub const IA32_TIME_STAMP_COUNTER: i32 = 16; +pub const IA32_PLATFORM_ID: i32 = 23; +pub const IA32_APIC_BASE_MSR: i32 = 27; +pub const IA32_BIOS_SIGN_ID: i32 = 139; +pub const MSR_PLATFORM_INFO: i32 = 206; +pub const MSR_MISC_FEATURE_ENABLES: i32 = 320; +pub const IA32_MISC_ENABLE: i32 = 416; +pub const IA32_RTIT_CTL: i32 = 1392; +pub const MSR_SMI_COUNT: i32 = 52; +pub const IA32_MCG_CAP: i32 = 377; +pub const IA32_KERNEL_GS_BASE: i32 = 0xC0000101u32 as i32; +pub const MSR_PKG_C2_RESIDENCY: i32 = 1549; +pub const IA32_APIC_BASE_BSP: i32 = 1 << 8; +pub const IA32_APIC_BASE_EXTD: i32 = 1 << 10; +pub const IA32_APIC_BASE_EN: i32 = 1 << 11; +pub const APIC_ADDRESS: i32 = 0xFEE00000u32 as i32; +pub const SEG_PREFIX_NONE: i32 = -1; +pub const SEG_PREFIX_ZERO: i32 = 7; +pub const PREFIX_MASK_REP: i32 = 24; +pub const PREFIX_REPZ: i32 = 8; +pub const PREFIX_REPNZ: i32 = 16; +pub const PREFIX_MASK_SEGMENT: i32 = 7; +pub const PREFIX_MASK_OPSIZE: i32 = 32; +pub const PREFIX_MASK_ADDRSIZE: i32 = 64; pub const PREFIX_F2: i32 = PREFIX_REPNZ; pub const PREFIX_F3: i32 = PREFIX_REPZ; pub const PREFIX_66: i32 = PREFIX_MASK_OPSIZE; -pub const LOG_CPU: i32 = 2i32; -pub const A20_MASK: i32 = !(1i32 << 20i32); -pub const A20_MASK16: i32 = !(1i32 << 20i32 - 1i32); -pub const A20_MASK32: i32 = !(1i32 << 20i32 - 2i32); +pub const LOG_CPU: i32 = 2; +pub const A20_MASK: i32 = !(1 << 20); +pub const A20_MASK16: i32 = !(1 << 20 - 1); +pub const A20_MASK32: i32 = !(1 << 20 - 2); pub const MXCSR_MASK: i32 = 0xffff; -pub const VALID_TLB_ENTRY_MAX: i32 = 10000i32; -pub const TLB_VALID: i32 = 1i32 << 0i32; -pub const TLB_READONLY: i32 = 1i32 << 1i32; -pub const TLB_NO_USER: i32 = 1i32 << 2i32; -pub const TLB_IN_MAPPED_RANGE: i32 = 1i32 << 3i32; -pub const TLB_GLOBAL: i32 = 1i32 << 4i32; -pub const TLB_HAS_CODE: i32 = 1i32 << 5i32; -pub const CPU_EXCEPTION_DE: i32 = 0i32; -pub const CPU_EXCEPTION_DB: i32 = 1i32; -pub const CPU_EXCEPTION_NMI: i32 = 2i32; -pub const CPU_EXCEPTION_BP: i32 = 3i32; -pub const CPU_EXCEPTION_OF: i32 = 4i32; -pub const CPU_EXCEPTION_BR: i32 = 5i32; -pub const CPU_EXCEPTION_UD: i32 = 6i32; -pub const CPU_EXCEPTION_NM: i32 = 7i32; -pub const CPU_EXCEPTION_DF: i32 = 8i32; -pub const CPU_EXCEPTION_TS: i32 = 10i32; -pub const CPU_EXCEPTION_NP: i32 = 11i32; -pub const CPU_EXCEPTION_SS: i32 = 12i32; -pub const CPU_EXCEPTION_GP: i32 = 13i32; -pub const CPU_EXCEPTION_PF: i32 = 14i32; -pub const CPU_EXCEPTION_MF: i32 = 16i32; -pub const CPU_EXCEPTION_AC: i32 = 17i32; -pub const CPU_EXCEPTION_MC: i32 = 18i32; -pub const CPU_EXCEPTION_XM: i32 = 19i32; -pub const CPU_EXCEPTION_VE: i32 = 20i32; +pub const VALID_TLB_ENTRY_MAX: i32 = 10000; +pub const TLB_VALID: i32 = 1 << 0; +pub const TLB_READONLY: i32 = 1 << 1; +pub const TLB_NO_USER: i32 = 1 << 2; +pub const TLB_IN_MAPPED_RANGE: i32 = 1 << 3; +pub const TLB_GLOBAL: i32 = 1 << 4; +pub const TLB_HAS_CODE: i32 = 1 << 5; +pub const CPU_EXCEPTION_DE: i32 = 0; +pub const CPU_EXCEPTION_DB: i32 = 1; +pub const CPU_EXCEPTION_NMI: i32 = 2; +pub const CPU_EXCEPTION_BP: i32 = 3; +pub const CPU_EXCEPTION_OF: i32 = 4; +pub const CPU_EXCEPTION_BR: i32 = 5; +pub const CPU_EXCEPTION_UD: i32 = 6; +pub const CPU_EXCEPTION_NM: i32 = 7; +pub const CPU_EXCEPTION_DF: i32 = 8; +pub const CPU_EXCEPTION_TS: i32 = 10; +pub const CPU_EXCEPTION_NP: i32 = 11; +pub const CPU_EXCEPTION_SS: i32 = 12; +pub const CPU_EXCEPTION_GP: i32 = 13; +pub const CPU_EXCEPTION_PF: i32 = 14; +pub const CPU_EXCEPTION_MF: i32 = 16; +pub const CPU_EXCEPTION_AC: i32 = 17; +pub const CPU_EXCEPTION_MC: i32 = 18; +pub const CPU_EXCEPTION_XM: i32 = 19; +pub const CPU_EXCEPTION_VE: i32 = 20; pub const CHECK_TLB_INVARIANTS: bool = false; pub const DEBUG: bool = cfg!(debug_assertions); -pub const LOOP_COUNTER: i32 = 20011i32; -pub const TSC_RATE: f64 = (50i32 * 1000i32) as f64; +pub const LOOP_COUNTER: i32 = 20011; +pub const TSC_RATE: f64 = (50 * 1000) as f64; -pub static mut jit_block_boundary: bool = 0 != 0i32; +pub static mut jit_block_boundary: bool = 0 != 0; -pub static mut must_not_fault: bool = 0 != 0i32; -pub static mut rdtsc_imprecision_offset: u64 = 0i32 as u64; -pub static mut rdtsc_last_value: u64 = 0i32 as u64; -pub static mut tsc_offset: u64 = 0i32 as u64; +pub static mut must_not_fault: bool = 0 != 0; +pub static mut rdtsc_imprecision_offset: u64 = 0 as u64; +pub static mut rdtsc_last_value: u64 = 0 as u64; +pub static mut tsc_offset: u64 = 0 as u64; pub static mut valid_tlb_entries: [i32; 10000] = [0; 10000]; -pub static mut valid_tlb_entries_count: i32 = 0i32; +pub static mut valid_tlb_entries_count: i32 = 0; //pub fn call_indirect1(f: fn(u16), x: u16) { f(x); } -pub unsafe fn after_block_boundary() { jit_block_boundary = 0 != 1i32; } +pub unsafe fn after_block_boundary() { jit_block_boundary = 0 != 1; } pub unsafe fn same_page(mut addr1: i32, mut addr2: i32) -> bool { - return addr1 & !4095i32 == addr2 & !4095i32; + return addr1 & !4095 == addr2 & !4095; } #[no_mangle] pub unsafe fn get_eflags() -> i32 { return *flags & !FLAGS_ALL | getcf() as i32 - | (getpf() as i32) << 2i32 - | (getaf() as i32) << 4i32 - | (getzf() as i32) << 6i32 - | (getsf() as i32) << 7i32 - | (getof() as i32) << 11i32; + | (getpf() as i32) << 2 + | (getaf() as i32) << 4 + | (getzf() as i32) << 6 + | (getsf() as i32) << 7 + | (getof() as i32) << 11; } pub unsafe fn translate_address_read(mut address: i32) -> Result { - let mut base: i32 = (address as u32 >> 12i32) as i32; + let mut base: i32 = (address as u32 >> 12) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); - let mut user: bool = *cpl as i32 == 3i32; - if entry & (TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0i32 }) == TLB_VALID { - return Ok((entry & !4095i32 ^ address) as u32); + let mut user: bool = *cpl as i32 == 3; + if entry & (TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0 }) == TLB_VALID { + return Ok((entry & !4095 ^ address) as u32); } else { - return Ok((do_page_translation(address, 0 != 0i32, user)? | address & 4095i32) as u32); + return Ok((do_page_translation(address, 0 != 0, user)? | address & 4095) as u32); }; } @@ -270,19 +270,19 @@ pub unsafe fn do_page_translation( mut for_writing: bool, mut user: bool, ) -> Result { - let mut can_write: bool = 0 != 1i32; + let mut can_write: bool = 0 != 1; let mut global; - let mut allow_user: bool = 0 != 1i32; - let mut page: i32 = (addr as u32 >> 12i32) as i32; + let mut allow_user: bool = 0 != 1; + let mut page: i32 = (addr as u32 >> 12) as i32; let mut high; - if *cr & CR0_PG == 0i32 { + if *cr & CR0_PG == 0 { // paging disabled - high = (addr as u32 & 4294963200u32) as i32; - global = 0 != 0i32 + high = (addr as u32 & 4294963200) as i32; + global = 0 != 0 } else { let mut page_dir_addr: i32 = - (*cr.offset(3isize) as u32 >> 2i32).wrapping_add((page >> 10i32) as u32) as i32; + (*cr.offset(3) as u32 >> 2).wrapping_add((page >> 10) as u32) as i32; let mut page_dir_entry: i32 = read_aligned32(page_dir_addr as u32); // XXX let kernel_write_override: bool = !user && 0 == *cr & CR0_WP; @@ -292,28 +292,28 @@ pub unsafe fn do_page_translation( // - set cr2 = addr (which caused the page fault) // - call_interrupt_vector with id 14, error code 0-7 (requires information if read or write) // - prevent execution of the function that triggered this call - *cr.offset(2isize) = addr; - trigger_pagefault(for_writing, user, 0 != 0i32); + *cr.offset(2) = addr; + trigger_pagefault(for_writing, user, 0 != 0); return Err(()); } - if page_dir_entry & PAGE_TABLE_RW_MASK == 0i32 && !kernel_write_override { - can_write = 0 != 0i32; + if page_dir_entry & PAGE_TABLE_RW_MASK == 0 && !kernel_write_override { + can_write = 0 != 0; if for_writing { - *cr.offset(2isize) = addr; - trigger_pagefault(for_writing, user, 0 != 1i32); + *cr.offset(2) = addr; + trigger_pagefault(for_writing, user, 0 != 1); return Err(()); } } - if page_dir_entry & PAGE_TABLE_USER_MASK == 0i32 { - allow_user = 0 != 0i32; + if page_dir_entry & PAGE_TABLE_USER_MASK == 0 { + allow_user = 0 != 0; if user { // Page Fault: page table accessed by non-supervisor - *cr.offset(2isize) = addr; - trigger_pagefault(for_writing, user, 0 != 1i32); + *cr.offset(2) = addr; + trigger_pagefault(for_writing, user, 0 != 1); return Err(()); } } - if 0 != page_dir_entry & PAGE_TABLE_PSE_MASK && 0 != *cr.offset(4isize) & CR4_PSE { + if 0 != page_dir_entry & PAGE_TABLE_PSE_MASK && 0 != *cr.offset(4) & CR4_PSE { // size bit is set // set the accessed and dirty bits write_aligned32( @@ -322,35 +322,35 @@ pub unsafe fn do_page_translation( PAGE_TABLE_DIRTY_MASK } else { - 0i32 + 0 }, ); - high = (page_dir_entry as u32 & 4290772992u32 | (addr & 4190208i32) as u32) as i32; + high = (page_dir_entry as u32 & 4290772992 | (addr & 4190208) as u32) as i32; global = page_dir_entry & PAGE_TABLE_GLOBAL_MASK == PAGE_TABLE_GLOBAL_MASK } else { - let mut page_table_addr: i32 = ((page_dir_entry as u32 & 4294963200u32) >> 2i32) - .wrapping_add((page & 1023i32) as u32) + let mut page_table_addr: i32 = ((page_dir_entry as u32 & 4294963200) >> 2) + .wrapping_add((page & 1023) as u32) as i32; let mut page_table_entry: i32 = read_aligned32(page_table_addr as u32); - if page_table_entry & PAGE_TABLE_PRESENT_MASK == 0i32 { - *cr.offset(2isize) = addr; - trigger_pagefault(for_writing, user, 0 != 0i32); + if page_table_entry & PAGE_TABLE_PRESENT_MASK == 0 { + *cr.offset(2) = addr; + trigger_pagefault(for_writing, user, 0 != 0); return Err(()); } - if page_table_entry & PAGE_TABLE_RW_MASK == 0i32 && !kernel_write_override { - can_write = 0 != 0i32; + if page_table_entry & PAGE_TABLE_RW_MASK == 0 && !kernel_write_override { + can_write = 0 != 0; if for_writing { - *cr.offset(2isize) = addr; - trigger_pagefault(for_writing, user, 0 != 1i32); + *cr.offset(2) = addr; + trigger_pagefault(for_writing, user, 0 != 1); return Err(()); } } - if page_table_entry & PAGE_TABLE_USER_MASK == 0i32 { - allow_user = 0 != 0i32; + if page_table_entry & PAGE_TABLE_USER_MASK == 0 { + allow_user = 0 != 0; if user { - *cr.offset(2isize) = addr; - trigger_pagefault(for_writing, user, 0 != 1i32); + *cr.offset(2) = addr; + trigger_pagefault(for_writing, user, 0 != 1); return Err(()); } } @@ -365,19 +365,19 @@ pub unsafe fn do_page_translation( PAGE_TABLE_DIRTY_MASK } else { - 0i32 + 0 }, ); - high = (page_table_entry as u32 & 4294963200u32) as i32; + high = (page_table_entry as u32 & 4294963200) as i32; global = page_table_entry & PAGE_TABLE_GLOBAL_MASK == PAGE_TABLE_GLOBAL_MASK } } - if *tlb_data.offset(page as isize) == 0i32 { + if *tlb_data.offset(page as isize) == 0 { if valid_tlb_entries_count == VALID_TLB_ENTRY_MAX { profiler_stat_increment(S_TLB_FULL); clear_tlb(); // also clear global entries if tlb is almost full after clearing non-global pages - if valid_tlb_entries_count > VALID_TLB_ENTRY_MAX * 3i32 / 4i32 { + if valid_tlb_entries_count > VALID_TLB_ENTRY_MAX * 3 / 4 { profiler_stat_increment(S_TLB_GLOBAL_FULL); full_clear_tlb(); } @@ -390,11 +390,11 @@ pub unsafe fn do_page_translation( // entries from tlb_data but not from valid_tlb_entries } else if CHECK_TLB_INVARIANTS { - let mut found: bool = 0 != 0i32; - let mut i: i32 = 0i32; + let mut found: bool = 0 != 0; + let mut i: i32 = 0; while i < valid_tlb_entries_count { if valid_tlb_entries[i as usize] == page { - found = 0 != 1i32; + found = 0 != 1; break; } else { @@ -404,18 +404,18 @@ pub unsafe fn do_page_translation( dbg_assert!(found); } let mut is_in_mapped_range: bool = in_mapped_range(high as u32); - let mut physical_page: i32 = (high as u32 >> 12i32) as i32; + let mut physical_page: i32 = (high as u32 >> 12) as i32; let mut has_code: bool = !is_in_mapped_range && 0 != ::c_api::jit_page_has_code(physical_page as u32) as i32; let mut info_bits: i32 = TLB_VALID | if 0 != can_write as i32 { - 0i32 + 0 } else { TLB_READONLY } | if 0 != allow_user as i32 { - 0i32 + 0 } else { TLB_NO_USER @@ -424,22 +424,22 @@ pub unsafe fn do_page_translation( TLB_IN_MAPPED_RANGE } else { - 0i32 + 0 } - | if 0 != global as i32 && 0 != *cr.offset(4isize) & CR4_PGE { + | if 0 != global as i32 && 0 != *cr.offset(4) & CR4_PGE { TLB_GLOBAL } else { - 0i32 + 0 } | if 0 != has_code as i32 { TLB_HAS_CODE } else { - 0i32 + 0 }; - dbg_assert!((high ^ page << 12i32) & 4095i32 == 0i32); - *tlb_data.offset(page as isize) = high ^ page << 12i32 | info_bits; + dbg_assert!((high ^ page << 12) & 4095 == 0); + *tlb_data.offset(page as isize) = high ^ page << 12 | info_bits; return Ok(high); } @@ -447,19 +447,19 @@ pub unsafe fn do_page_translation( pub unsafe fn full_clear_tlb() { profiler_stat_increment(S_FULL_CLEAR_TLB); // clear tlb including global pages - *last_virt_eip = -1i32; - *last_virt_esp = -1i32; - let mut i: i32 = 0i32; + *last_virt_eip = -1; + *last_virt_esp = -1; + let mut i: i32 = 0; while i < valid_tlb_entries_count { let mut page: i32 = valid_tlb_entries[i as usize]; - *tlb_data.offset(page as isize) = 0i32; + *tlb_data.offset(page as isize) = 0; i += 1 } - valid_tlb_entries_count = 0i32; + valid_tlb_entries_count = 0; if CHECK_TLB_INVARIANTS { - let mut i_0: i32 = 0i32; - while i_0 < 1048576i32 { - dbg_assert!(*tlb_data.offset(i_0 as isize) == 0i32); + let mut i_0: i32 = 0; + while i_0 < 1048576 { + dbg_assert!(*tlb_data.offset(i_0 as isize) == 0); i_0 += 1 } }; @@ -469,10 +469,10 @@ pub unsafe fn full_clear_tlb() { pub unsafe fn clear_tlb() { profiler_stat_increment(S_CLEAR_TLB); // clear tlb excluding global pages - *last_virt_eip = -1i32; - *last_virt_esp = -1i32; - let mut global_page_offset: i32 = 0i32; - let mut i: i32 = 0i32; + *last_virt_eip = -1; + *last_virt_esp = -1; + let mut global_page_offset: i32 = 0; + let mut i: i32 = 0; while i < valid_tlb_entries_count { let mut page: i32 = valid_tlb_entries[i as usize]; let mut entry: i32 = *tlb_data.offset(page as isize); @@ -482,16 +482,16 @@ pub unsafe fn clear_tlb() { global_page_offset += 1; } else { - *tlb_data.offset(page as isize) = 0i32 + *tlb_data.offset(page as isize) = 0 } i += 1 } valid_tlb_entries_count = global_page_offset; if CHECK_TLB_INVARIANTS { - let mut i_0: i32 = 0i32; - while i_0 < 1048576i32 { + let mut i_0: i32 = 0; + while i_0 < 1048576 { dbg_assert!( - *tlb_data.offset(i_0 as isize) == 0i32 + *tlb_data.offset(i_0 as isize) == 0 || 0 != *tlb_data.offset(i_0 as isize) & TLB_GLOBAL ); i_0 += 1 @@ -500,14 +500,14 @@ pub unsafe fn clear_tlb() { } pub unsafe fn trigger_pagefault(mut write: bool, mut user: bool, mut present: bool) { - if 0 != 0i32 * 0i32 { + if 0 != 0 * 0 { dbg_log!( "page fault w={} u={} p={} eip={:x} cr2={:x}", write as i32, user as i32, present as i32, *previous_ip, - *cr.offset(2isize) + *cr.offset(2) ); dbg_trace(); } @@ -515,51 +515,51 @@ pub unsafe fn trigger_pagefault(mut write: bool, mut user: bool, mut present: bo if must_not_fault { dbg_log!("Unexpected page fault"); dbg_trace(); - dbg_assert!(0 != 0i32); + dbg_assert!(0 != 0); } } //if *page_fault { // dbg_log!(("double fault")); // dbg_trace(); - // dbg_assert!(0 != 0i32); + // dbg_assert!(0 != 0); //} // invalidate tlb entry - let mut page: i32 = (*cr.offset(2isize) as u32 >> 12i32) as i32; - *tlb_data.offset(page as isize) = 0i32; + let mut page: i32 = (*cr.offset(2) as u32 >> 12) as i32; + *tlb_data.offset(page as isize) = 0; *instruction_pointer = *previous_ip; - //*page_fault = 0 != 1i32; + //*page_fault = 0 != 1; call_interrupt_vector( CPU_EXCEPTION_PF, - 0 != 0i32, - 0 != 1i32, - (user as i32) << 2i32 | (write as i32) << 1i32 | present as i32, + 0 != 0, + 0 != 1, + (user as i32) << 2 | (write as i32) << 1 | present as i32, ); //profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); } pub unsafe fn translate_address_write(mut address: i32) -> Result { - let mut base: i32 = (address as u32 >> 12i32) as i32; + let mut base: i32 = (address as u32 >> 12) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); - let mut user: bool = *cpl as i32 == 3i32; - if entry & (TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0i32 } | TLB_READONLY) + let mut user: bool = *cpl as i32 == 3; + if entry & (TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0 } | TLB_READONLY) == TLB_VALID { - return Ok((entry & !4095i32 ^ address) as u32); + return Ok((entry & !4095 ^ address) as u32); } else { - return Ok((do_page_translation(address, 0 != 1i32, user)? | address & 4095i32) as u32); + return Ok((do_page_translation(address, 0 != 1, user)? | address & 4095) as u32); }; } #[no_mangle] pub unsafe fn tlb_set_has_code(mut physical_page: u32, mut has_code: bool) { - dbg_assert!(physical_page < (1i32 << 20i32) as u32); - let mut i: i32 = 0i32; + dbg_assert!(physical_page < (1 << 20) as u32); + let mut i: i32 = 0; while i < valid_tlb_entries_count { let mut page: i32 = valid_tlb_entries[i as usize]; let mut entry: i32 = *tlb_data.offset(page as isize); if 0 != entry { - let mut tlb_physical_page: u32 = entry as u32 >> 12i32 ^ page as u32; + let mut tlb_physical_page: u32 = entry as u32 >> 12 ^ page as u32; if physical_page == tlb_physical_page { *tlb_data.offset(page as isize) = if 0 != has_code as i32 { entry | TLB_HAS_CODE @@ -580,7 +580,7 @@ pub unsafe fn check_tlb_invariants() { return; } else { - let mut i: i32 = 0i32; + let mut i: i32 = 0; while i < valid_tlb_entries_count { let mut page: i32 = valid_tlb_entries[i as usize]; let mut entry: i32 = *tlb_data.offset(page as isize); @@ -594,26 +594,26 @@ pub unsafe fn check_tlb_invariants() { } pub unsafe fn writable_or_pagefault(mut addr: i32, mut size: i32) -> Result<(), ()> { - dbg_assert!(size < 4096i32); - dbg_assert!(size > 0i32); - if *cr & CR0_PG == 0i32 { + dbg_assert!(size < 4096); + dbg_assert!(size > 0); + if *cr & CR0_PG == 0 { return Ok(()); } else { - let mut user: bool = *cpl as i32 == 3i32; + let mut user: bool = *cpl as i32 == 3; let mut mask: i32 = - TLB_READONLY | TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0i32 }; + TLB_READONLY | TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0 }; let mut expect: i32 = TLB_VALID; - let mut page: i32 = (addr as u32 >> 12i32) as i32; + let mut page: i32 = (addr as u32 >> 12) as i32; if *tlb_data.offset(page as isize) & mask != expect { - do_page_translation(addr, 0 != 1i32, user)?; + do_page_translation(addr, 0 != 1, user)?; } - let mut next_page: i32 = ((addr + size - 1i32) as u32 >> 12i32) as i32; + let mut next_page: i32 = ((addr + size - 1) as u32 >> 12) as i32; if page != next_page { - dbg_assert!(next_page == page + 1i32); + dbg_assert!(next_page == page + 1); // XXX: possibly out of bounds if *tlb_data.offset(next_page as isize) & mask != expect { - do_page_translation(next_page << 12i32, 0 != 1i32, user)?; + do_page_translation(next_page << 12, 0 != 1, user)?; } } return Ok(()); @@ -622,40 +622,40 @@ pub unsafe fn writable_or_pagefault(mut addr: i32, mut size: i32) -> Result<(), pub unsafe fn read_imm8() -> Result { let mut eip: i32 = *instruction_pointer; - if 0 != eip & !4095i32 ^ *last_virt_eip { + if 0 != eip & !4095 ^ *last_virt_eip { *eip_phys = (translate_address_read(eip)? ^ eip as u32) as i32; - *last_virt_eip = eip & !4095i32 + *last_virt_eip = eip & !4095 } dbg_assert!(!in_mapped_range((*eip_phys ^ eip) as u32)); let mut data8: i32 = *mem8.offset((*eip_phys ^ eip) as isize) as i32; - *instruction_pointer = eip + 1i32; + *instruction_pointer = eip + 1; return Ok(data8); } -pub unsafe fn read_imm8s() -> Result { return Ok(read_imm8()? << 24i32 >> 24i32); } +pub unsafe fn read_imm8s() -> Result { return Ok(read_imm8()? << 24 >> 24); } pub unsafe fn read_imm16() -> Result { // Two checks in one comparison: // 1. Did the high 20 bits of eip change // or 2. Are the low 12 bits of eip 0xFFF (and this read crosses a page boundary) - if (*instruction_pointer ^ *last_virt_eip) as u32 > 4094i32 as u32 { - return Ok(read_imm8()? | read_imm8()? << 8i32); + if (*instruction_pointer ^ *last_virt_eip) as u32 > 4094 as u32 { + return Ok(read_imm8()? | read_imm8()? << 8); } else { let mut data16: i32 = read16((*eip_phys ^ *instruction_pointer) as u32); - *instruction_pointer = *instruction_pointer + 2i32; + *instruction_pointer = *instruction_pointer + 2; return Ok(data16); }; } pub unsafe fn read_imm32s() -> Result { // Analogue to the above comment - if (*instruction_pointer ^ *last_virt_eip) as u32 > 4092i32 as u32 { - return Ok(read_imm16()? | read_imm16()? << 16i32); + if (*instruction_pointer ^ *last_virt_eip) as u32 > 4092 as u32 { + return Ok(read_imm16()? | read_imm16()? << 16); } else { let mut data32: i32 = read32s((*eip_phys ^ *instruction_pointer) as u32); - *instruction_pointer = *instruction_pointer + 4i32; + *instruction_pointer = *instruction_pointer + 4; return Ok(data32); }; } @@ -671,14 +671,14 @@ pub unsafe fn is_asize_32() -> bool { #[no_mangle] pub unsafe fn get_seg(mut segment: i32) -> i32 { - dbg_assert!(segment >= 0i32 && segment < 8i32); + dbg_assert!(segment >= 0 && segment < 8); // TODO: Remove protected_mode check if *protected_mode { if *segment_is_null.offset(segment as isize) { dbg_assert!(segment != CS && segment != SS); dbg_log!("#gp: Access null segment"); assert!(false); - trigger_gp(0i32); + trigger_gp(0); } } return *segment_offsets.offset(segment as isize); @@ -698,7 +698,7 @@ pub unsafe fn raise_exception_with_code(mut interrupt_nr: i32, mut error_code: i error_code ); dbg_trace(); - dbg_assert!(0 != 0i32); + dbg_assert!(0 != 0); } if cpu_exception_hook(interrupt_nr) { assert!(false); @@ -706,7 +706,7 @@ pub unsafe fn raise_exception_with_code(mut interrupt_nr: i32, mut error_code: i } } profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); - call_interrupt_vector(interrupt_nr, 0 != 0i32, 0 != 1i32, error_code); + call_interrupt_vector(interrupt_nr, 0 != 0, 0 != 1, error_code); assert!(false); } @@ -718,10 +718,10 @@ pub unsafe fn get_seg_prefix(mut default_segment: i32) -> i32 { let mut prefix: i32 = *prefixes as i32 & PREFIX_MASK_SEGMENT; if 0 != prefix { if prefix == SEG_PREFIX_ZERO { - return 0i32; + return 0; } else { - return get_seg(prefix - 1i32); + return get_seg(prefix - 1); } } else { @@ -759,8 +759,8 @@ pub unsafe fn cycle_internal() { if 0 != entry { profiler_stat_increment(S_RUN_FROM_CACHE); let initial_tsc = *timestamp_counter as i32; - let wasm_table_index = (entry & 65535i32 as u32) as u16; - let initial_state = (entry >> 16i32) as u16; + let wasm_table_index = (entry & 65535 as u32) as u16; + let initial_state = (entry >> 16) as u16; call_indirect1( (wasm_table_index as u32).wrapping_add(WASM_TABLE_OFFSET as u32) as i32, initial_state, @@ -773,7 +773,7 @@ pub unsafe fn cycle_internal() { else { if DEBUG { dbg_assert!(!must_not_fault); - must_not_fault = 0 != 1i32 + must_not_fault = 0 != 1 } ::c_api::jit_increase_hotness_and_maybe_compile( phys_addr, @@ -782,7 +782,7 @@ pub unsafe fn cycle_internal() { ); if DEBUG { dbg_assert!(must_not_fault); - must_not_fault = 0 != 0i32 + must_not_fault = 0 != 0 } let mut initial_tsc_0: i32 = *timestamp_counter as i32; jit_run_interpreted(phys_addr as i32); @@ -802,9 +802,9 @@ pub unsafe fn cycle_internal() { pub unsafe fn get_phys_eip() -> Result { let mut eip: i32 = *instruction_pointer; - if 0 != eip & !4095i32 ^ *last_virt_eip { + if 0 != eip & !4095 ^ *last_virt_eip { *eip_phys = (translate_address_read(eip)? ^ eip as u32) as i32; - *last_virt_eip = eip & !4095i32 + *last_virt_eip = eip & !4095 } let mut phys_addr: u32 = (*eip_phys ^ eip) as u32; dbg_assert!(!in_mapped_range(phys_addr)); @@ -812,12 +812,12 @@ pub unsafe fn get_phys_eip() -> Result { } unsafe fn jit_run_interpreted(mut phys_addr: i32) { profiler_stat_increment(S_RUN_INTERPRETED); - jit_block_boundary = 0 != 0i32; + jit_block_boundary = 0 != 0; dbg_assert!(!in_mapped_range(phys_addr as u32)); let mut opcode: i32 = *mem8.offset(phys_addr as isize) as i32; *instruction_pointer += 1; *timestamp_counter = (*timestamp_counter).wrapping_add(1); - run_instruction(opcode | (*is_32 as i32) << 8i32); + run_instruction(opcode | (*is_32 as i32) << 8); while !jit_block_boundary && 0 != same_page(*previous_ip, *instruction_pointer) as i32 { *previous_ip = *instruction_pointer; *timestamp_counter = (*timestamp_counter).wrapping_add(1); @@ -825,36 +825,36 @@ unsafe fn jit_run_interpreted(mut phys_addr: i32) { if DEBUG { logop(*previous_ip, opcode_0); } - run_instruction(opcode_0 | (*is_32 as i32) << 8i32); + run_instruction(opcode_0 | (*is_32 as i32) << 8); } } #[no_mangle] pub unsafe fn pack_current_state_flags() -> CachedStateFlags { - return ((*is_32 as i32) << 0i32 - | (*stack_size_32 as i32) << 1i32 - | ((*cpl as i32 == 3i32) as i32) << 2i32 - | (has_flat_segmentation() as i32) << 3i32) as CachedStateFlags; + return ((*is_32 as i32) << 0 + | (*stack_size_32 as i32) << 1 + | ((*cpl as i32 == 3) as i32) << 2 + | (has_flat_segmentation() as i32) << 3) as CachedStateFlags; } pub unsafe fn has_flat_segmentation() -> bool { // ss can't be null - return *segment_offsets.offset(SS as isize) == 0i32 + return *segment_offsets.offset(SS as isize) == 0 && !*segment_is_null.offset(DS as isize) - && *segment_offsets.offset(DS as isize) == 0i32; + && *segment_offsets.offset(DS as isize) == 0; } pub unsafe fn run_prefix_instruction() { - run_instruction(return_on_pagefault!(read_imm8()) | (is_osize_32() as i32) << 8i32); + run_instruction(return_on_pagefault!(read_imm8()) | (is_osize_32() as i32) << 8); } -pub unsafe fn clear_prefixes() { *prefixes = 0i32 as u8; } +pub unsafe fn clear_prefixes() { *prefixes = 0 as u8; } pub unsafe fn segment_prefix_op(mut seg: i32) { - dbg_assert!(seg <= 5i32); - *prefixes = (*prefixes as i32 | seg + 1i32) as u8; + dbg_assert!(seg <= 5); + *prefixes = (*prefixes as i32 | seg + 1) as u8; run_prefix_instruction(); - *prefixes = 0i32 as u8; + *prefixes = 0 as u8; } #[no_mangle] @@ -873,7 +873,7 @@ pub unsafe fn do_many_cycles_native() { // if must_not_fault { // dbg_log!("Unexpected fault: 0x{:x}", interrupt_nr); // dbg_trace(); -// dbg_assert!(0 != 0i32); +// dbg_assert!(0 != 0); // } // if cpu_exception_hook(interrupt_nr) { // throw_cpu_exception(); @@ -881,7 +881,7 @@ pub unsafe fn do_many_cycles_native() { // } // } // profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); -// call_interrupt_vector(interrupt_nr, 0 != 0i32, 0 != 0i32, 0i32); +// call_interrupt_vector(interrupt_nr, 0 != 0, 0 != 0, 0); // throw_cpu_exception(); //} @@ -892,7 +892,7 @@ pub unsafe fn trigger_de() { } } *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_DE, 0 != 0i32, 0 != 0i32, 0i32); + call_interrupt_vector(CPU_EXCEPTION_DE, 0 != 0, 0 != 0, 0); } #[no_mangle] @@ -905,7 +905,7 @@ pub unsafe fn trigger_ud() { } } *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_UD, 0 != 0i32, 0 != 0i32, 0i32); + call_interrupt_vector(CPU_EXCEPTION_UD, 0 != 0, 0 != 0, 0); } pub unsafe fn trigger_nm() { @@ -915,7 +915,7 @@ pub unsafe fn trigger_nm() { } } *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_NM, 0 != 0i32, 0 != 0i32, 0i32); + call_interrupt_vector(CPU_EXCEPTION_NM, 0 != 0, 0 != 0, 0); } #[no_mangle] @@ -926,65 +926,65 @@ pub unsafe fn trigger_gp_non_raising(mut code: i32) { } } *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_GP, 0 != 0i32, 0 != 1i32, code); + call_interrupt_vector(CPU_EXCEPTION_GP, 0 != 0, 0 != 1, code); } pub unsafe fn virt_boundary_read16(mut low: i32, mut high: i32) -> i32 { - dbg_assert!(low & 4095i32 == 4095i32); - dbg_assert!(high & 4095i32 == 0i32); - return read8(low as u32) | read8(high as u32) << 8i32; + dbg_assert!(low & 4095 == 4095); + dbg_assert!(high & 4095 == 0); + return read8(low as u32) | read8(high as u32) << 8; } pub unsafe fn virt_boundary_read32s(mut low: i32, mut high: i32) -> i32 { - dbg_assert!(low & 4095i32 >= 4093i32); - dbg_assert!(high - 3i32 & 4095i32 == low & 4095i32); + dbg_assert!(low & 4095 >= 4093); + dbg_assert!(high - 3 & 4095 == low & 4095); let mut mid; - if 0 != low & 1i32 { - if 0 != low & 2i32 { + if 0 != low & 1 { + if 0 != low & 2 { // 0xFFF - mid = read_aligned16((high - 2i32 >> 1i32) as u32) + mid = read_aligned16((high - 2 >> 1) as u32) } else { // 0xFFD - mid = read_aligned16((low + 1i32 >> 1i32) as u32) + mid = read_aligned16((low + 1 >> 1) as u32) } } else { // 0xFFE - mid = virt_boundary_read16(low + 1i32, high - 1i32) + mid = virt_boundary_read16(low + 1, high - 1) } - return read8(low as u32) | mid << 8i32 | read8(high as u32) << 24i32; + return read8(low as u32) | mid << 8 | read8(high as u32) << 24; } pub unsafe fn virt_boundary_write16(mut low: i32, mut high: i32, mut value: i32) { - dbg_assert!(low & 4095i32 == 4095i32); - dbg_assert!(high & 4095i32 == 0i32); + dbg_assert!(low & 4095 == 4095); + dbg_assert!(high & 4095 == 0); write8(low as u32, value); - write8(high as u32, value >> 8i32); + write8(high as u32, value >> 8); } pub unsafe fn virt_boundary_write32(mut low: i32, mut high: i32, mut value: i32) { - dbg_assert!(low & 4095i32 >= 4093i32); - dbg_assert!(high - 3i32 & 4095i32 == low & 4095i32); + dbg_assert!(low & 4095 >= 4093); + dbg_assert!(high - 3 & 4095 == low & 4095); write8(low as u32, value); - if 0 != low & 1i32 { - if 0 != low & 2i32 { + if 0 != low & 1 { + if 0 != low & 2 { // 0xFFF - write8((high - 2i32) as u32, value >> 8i32); - write8((high - 1i32) as u32, value >> 16i32); + write8((high - 2) as u32, value >> 8); + write8((high - 1) as u32, value >> 16); } else { // 0xFFD - write8((low + 1i32) as u32, value >> 8i32); - write8((low + 2i32) as u32, value >> 16i32); + write8((low + 1) as u32, value >> 8); + write8((low + 2) as u32, value >> 16); } } else { // 0xFFE - write8((low + 1i32) as u32, value >> 8i32); - write8((high - 1i32) as u32, value >> 16i32); + write8((low + 1) as u32, value >> 8); + write8((high - 1) as u32, value >> 16); } - write8(high as u32, value >> 24i32); + write8(high as u32, value >> 24); } pub unsafe fn safe_read8(mut addr: i32) -> Result { @@ -992,13 +992,13 @@ pub unsafe fn safe_read8(mut addr: i32) -> Result { } pub unsafe fn safe_read16(mut address: i32) -> Result { - let mut base: i32 = (address as u32 >> 12i32) as i32; + let mut base: i32 = (address as u32 >> 12) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); - let mut info_bits: i32 = entry & 4095i32 & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; - if info_bits == TLB_VALID && address & 4095i32 <= 4096i32 - 2i32 { + let mut info_bits: i32 = entry & 4095 & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; + if info_bits == TLB_VALID && address & 4095 <= 4096 - 2 { // - not in memory mapped area // - can be accessed from any cpl - let mut phys_address: u32 = (entry & !4095i32 ^ address) as u32; + let mut phys_address: u32 = (entry & !4095 ^ address) as u32; dbg_assert!(!in_mapped_range(phys_address)); return Ok(*(mem8.offset(phys_address as isize) as *mut u16) as i32); } @@ -1008,8 +1008,8 @@ pub unsafe fn safe_read16(mut address: i32) -> Result { } pub unsafe fn safe_read16_slow(mut addr: i32) -> Result { - if addr & 4095i32 == 4095i32 { - return Ok(safe_read8(addr)? | safe_read8(addr + 1i32)? << 8i32); + if addr & 4095 == 4095 { + return Ok(safe_read8(addr)? | safe_read8(addr + 1)? << 8); } else { return Ok(read16(translate_address_read(addr)?)); @@ -1017,25 +1017,25 @@ pub unsafe fn safe_read16_slow(mut addr: i32) -> Result { } pub unsafe fn safe_read32s(mut address: i32) -> Result { - let mut base: i32 = (address as u32 >> 12i32) as i32; + let mut base: i32 = (address as u32 >> 12) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); - let mut info_bits: i32 = entry & 4095i32 & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; - if info_bits == TLB_VALID && address & 4095i32 <= 4096i32 - 4i32 { + let mut info_bits: i32 = entry & 4095 & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; + if info_bits == TLB_VALID && address & 4095 <= 4096 - 4 { if false { profiler_stat_increment(S_SAFE_READ32_FAST); } // - not in memory mapped area // - can be accessed from any cpl - let mut phys_address: u32 = (entry & !4095i32 ^ address) as u32; + let mut phys_address: u32 = (entry & !4095 ^ address) as u32; dbg_assert!(!in_mapped_range(phys_address)); return Ok(*(mem8.offset(phys_address as isize) as *mut i32)); } else { if false { - if address & 4095i32 > 4096i32 - 4i32 { + if address & 4095 > 4096 - 4 { profiler_stat_increment(S_SAFE_READ32_SLOW_PAGE_CROSSED); } - else if info_bits & TLB_VALID == 0i32 { + else if info_bits & TLB_VALID == 0 { profiler_stat_increment(S_SAFE_READ32_SLOW_NOT_VALID); } else if 0 != info_bits & TLB_NO_USER { @@ -1045,7 +1045,7 @@ pub unsafe fn safe_read32s(mut address: i32) -> Result { profiler_stat_increment(S_SAFE_READ32_SLOW_IN_MAPPED_RANGE); } else { - dbg_assert!(0 != 0i32); + dbg_assert!(0 != 0); } } return safe_read32s_slow(address); @@ -1053,8 +1053,8 @@ pub unsafe fn safe_read32s(mut address: i32) -> Result { } pub unsafe fn safe_read32s_slow(mut addr: i32) -> Result { - if addr & 4095i32 >= 4093i32 { - return Ok(safe_read16(addr)? | safe_read16(addr + 2i32)? << 16i32); + if addr & 4095 >= 4093 { + return Ok(safe_read16(addr)? | safe_read16(addr + 2)? << 16); } else { return Ok(read32s(translate_address_read(addr)?)); @@ -1105,22 +1105,22 @@ pub unsafe fn safe_read32s_slow_jit(addr: i32) -> i32 { pub unsafe fn safe_read64s(mut addr: i32) -> Result { let mut x: reg64 = reg64 { i8_0: [0; 8] }; - if addr & 4095i32 > 4096i32 - 8i32 { - x.u32_0[0usize] = safe_read32s(addr)? as u32; - x.u32_0[1usize] = safe_read32s(addr + 4i32)? as u32 + if addr & 4095 > 4096 - 8 { + x.u32_0[0] = safe_read32s(addr)? as u32; + x.u32_0[1] = safe_read32s(addr + 4)? as u32 } else { let addr_phys = translate_address_read(addr)? as i32; - x.u64_0[0usize] = read64s(addr_phys as u32) as u64 + x.u64_0[0] = read64s(addr_phys as u32) as u64 } Ok(x) } pub unsafe fn safe_read128s(mut addr: i32) -> Result { let mut x: reg128 = reg128 { i8_0: [0; 16] }; - if addr & 4095i32 > 4096i32 - 16i32 { - x.u64_0[0usize] = safe_read64s(addr)?.u64_0[0usize]; - x.u64_0[1usize] = safe_read64s(addr + 8i32)?.u64_0[0usize] + if addr & 4095 > 4096 - 16 { + x.u64_0[0] = safe_read64s(addr)?.u64_0[0]; + x.u64_0[1] = safe_read64s(addr + 8)?.u64_0[0] } else { let addr_phys = translate_address_read(addr)? as i32; @@ -1135,16 +1135,16 @@ pub unsafe fn safe_write8(mut addr: i32, mut value: i32) -> Result<(), ()> { } pub unsafe fn safe_write16(mut address: i32, mut value: i32) -> Result<(), ()> { - let mut base: i32 = (address as u32 >> 12i32) as i32; + let mut base: i32 = (address as u32 >> 12) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); - let mut info_bits: i32 = entry & 4095i32 & !TLB_GLOBAL; - if info_bits == TLB_VALID && address & 4095i32 <= 4096i32 - 2i32 { + let mut info_bits: i32 = entry & 4095 & !TLB_GLOBAL; + if info_bits == TLB_VALID && address & 4095 <= 4096 - 2 { // - allowed to write in user-mode // - not in memory mapped area // - can be accessed from any cpl // - does not contain code - let mut phys_address: u32 = (entry & !4095i32 ^ address) as u32; - dbg_assert!(!::c_api::jit_page_has_code(phys_address >> 12i32)); + let mut phys_address: u32 = (entry & !4095 ^ address) as u32; + dbg_assert!(!::c_api::jit_page_has_code(phys_address >> 12)); dbg_assert!(!in_mapped_range(phys_address)); *(mem8.offset(phys_address as isize) as *mut u16) = value as u16; } @@ -1156,12 +1156,8 @@ pub unsafe fn safe_write16(mut address: i32, mut value: i32) -> Result<(), ()> { pub unsafe fn safe_write16_slow(mut addr: i32, mut value: i32) -> Result<(), ()> { let mut phys_low: i32 = translate_address_write(addr)? as i32; - if addr & 4095i32 == 4095i32 { - virt_boundary_write16( - phys_low, - translate_address_write(addr + 1i32)? as i32, - value, - ); + if addr & 4095 == 4095 { + virt_boundary_write16(phys_low, translate_address_write(addr + 1)? as i32, value); } else { write16(phys_low as u32, value); @@ -1170,32 +1166,28 @@ pub unsafe fn safe_write16_slow(mut addr: i32, mut value: i32) -> Result<(), ()> } pub unsafe fn safe_write32(mut address: i32, mut value: i32) -> Result<(), ()> { - let mut base: i32 = (address as u32 >> 12i32) as i32; + let mut base: i32 = (address as u32 >> 12) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); - let mut info_bits: i32 = entry & 4095i32 & !TLB_GLOBAL & !if *cpl as i32 == 3i32 { - 0i32 - } - else { - TLB_NO_USER - }; - if info_bits == TLB_VALID && address & 4095i32 <= 4096i32 - 4i32 { + let mut info_bits: i32 = + entry & 4095 & !TLB_GLOBAL & !if *cpl as i32 == 3 { 0 } else { TLB_NO_USER }; + if info_bits == TLB_VALID && address & 4095 <= 4096 - 4 { if false { profiler_stat_increment(S_SAFE_WRITE32_FAST); } // - allowed to write in user-mode // - not in memory mapped area // - does not contain code - let mut phys_address: u32 = (entry & !4095i32 ^ address) as u32; - dbg_assert!(!::c_api::jit_page_has_code(phys_address >> 12i32)); + let mut phys_address: u32 = (entry & !4095 ^ address) as u32; + dbg_assert!(!::c_api::jit_page_has_code(phys_address >> 12)); dbg_assert!(!in_mapped_range(phys_address)); *(mem8.offset(phys_address as isize) as *mut i32) = value; } else { if false { - if address & 4095i32 > 4096i32 - 4i32 { + if address & 4095 > 4096 - 4 { profiler_stat_increment(S_SAFE_WRITE32_SLOW_PAGE_CROSSED); } - else if info_bits & TLB_VALID == 0i32 { + else if info_bits & TLB_VALID == 0 { profiler_stat_increment(S_SAFE_WRITE32_SLOW_NOT_VALID); } else if 0 != info_bits & TLB_NO_USER { @@ -1211,7 +1203,7 @@ pub unsafe fn safe_write32(mut address: i32, mut value: i32) -> Result<(), ()> { profiler_stat_increment(S_SAFE_WRITE32_SLOW_HAS_CODE); } else { - dbg_assert!(0 != 0i32); + dbg_assert!(0 != 0); } } safe_write32_slow(address, value)?; @@ -1221,10 +1213,10 @@ pub unsafe fn safe_write32(mut address: i32, mut value: i32) -> Result<(), ()> { pub unsafe fn safe_write32_slow(mut addr: i32, mut value: i32) -> Result<(), ()> { let mut phys_low: i32 = translate_address_write(addr)? as i32; - if addr & 4095i32 > 4096i32 - 4i32 { + if addr & 4095 > 4096 - 4 { virt_boundary_write32( phys_low, - (translate_address_write(addr + 3i32 & !3i32)? | (addr + 3i32 & 3i32) as u32) as i32, + (translate_address_write(addr + 3 & !3)? | (addr + 3 & 3) as u32) as i32, value, ); } @@ -1259,10 +1251,10 @@ pub unsafe fn safe_write32_slow_jit(addr: i32, value: i32) { } pub unsafe fn safe_write64(mut addr: i32, mut value: i64) -> Result<(), ()> { - if addr & 4095i32 > 4096i32 - 8i32 { - writable_or_pagefault(addr, 8i32)?; + if addr & 4095 > 4096 - 8 { + writable_or_pagefault(addr, 8)?; safe_write32(addr, value as i32).unwrap(); - safe_write32(addr + 4i32, (value >> 32i32) as i32).unwrap(); + safe_write32(addr + 4, (value >> 32) as i32).unwrap(); } else { let mut phys: i32 = translate_address_write(addr)? as i32; @@ -1272,10 +1264,10 @@ pub unsafe fn safe_write64(mut addr: i32, mut value: i64) -> Result<(), ()> { } pub unsafe fn safe_write128(mut addr: i32, mut value: reg128) -> Result<(), ()> { - if addr & 4095i32 > 4096i32 - 16i32 { - writable_or_pagefault(addr, 16i32)?; - safe_write64(addr, value.u64_0[0usize] as i64).unwrap(); - safe_write64(addr + 8i32, value.u64_0[1usize] as i64).unwrap(); + if addr & 4095 > 4096 - 16 { + writable_or_pagefault(addr, 16)?; + safe_write64(addr, value.u64_0[0] as i64).unwrap(); + safe_write64(addr + 8, value.u64_0[1] as i64).unwrap(); } else { let mut phys: i32 = translate_address_write(addr)? as i32; @@ -1284,9 +1276,7 @@ pub unsafe fn safe_write128(mut addr: i32, mut value: reg128) -> Result<(), ()> Ok(()) } -pub unsafe fn get_reg8_index(mut index: i32) -> i32 { - return index << 2i32 & 12i32 | index >> 2i32 & 1i32; -} +pub unsafe fn get_reg8_index(mut index: i32) -> i32 { return index << 2 & 12 | index >> 2 & 1; } pub unsafe fn read_reg8(mut index: i32) -> i32 { return *reg8.offset(get_reg8_index(index) as isize) as i32; @@ -1296,7 +1286,7 @@ pub unsafe fn write_reg8(mut index: i32, mut value: i32) { *reg8.offset(get_reg8_index(index) as isize) = value as u8; } -pub unsafe fn get_reg16_index(mut index: i32) -> i32 { return index << 1i32; } +pub unsafe fn get_reg16_index(mut index: i32) -> i32 { return index << 1; } pub unsafe fn read_reg16(mut index: i32) -> i32 { return *reg16.offset(get_reg16_index(index) as isize) as i32; @@ -1313,56 +1303,54 @@ pub unsafe fn write_reg32(mut index: i32, mut value: i32) { } pub unsafe fn write_reg_osize(mut index: i32, mut value: i32) { - dbg_assert!(index >= 0i32 && index < 8i32); + dbg_assert!(index >= 0 && index < 8); if is_osize_32() { write_reg32(index, value); } else { - write_reg16(index, value & 65535i32); + write_reg16(index, value & 65535); }; } pub unsafe fn read_mmx32s(mut r: i32) -> i32 { - return (*reg_mmx.offset(r as isize)).u32_0[0usize] as i32; + return (*reg_mmx.offset(r as isize)).u32_0[0] as i32; } pub unsafe fn read_mmx64s(mut r: i32) -> reg64 { return *reg_mmx.offset(r as isize); } pub unsafe fn write_mmx64(mut r: i32, mut low: i32, mut high: i32) { - (*reg_mmx.offset(r as isize)).u32_0[0usize] = low as u32; - (*reg_mmx.offset(r as isize)).u32_0[1usize] = high as u32; + (*reg_mmx.offset(r as isize)).u32_0[0] = low as u32; + (*reg_mmx.offset(r as isize)).u32_0[1] = high as u32; } pub unsafe fn write_mmx_reg64(mut r: i32, mut data: reg64) { - (*reg_mmx.offset(r as isize)).u64_0[0usize] = data.u64_0[0usize]; + (*reg_mmx.offset(r as isize)).u64_0[0] = data.u64_0[0]; } -pub unsafe fn read_xmm_f32(mut r: i32) -> f32 { - return (*reg_xmm.offset(r as isize)).f32_0[0usize]; -} +pub unsafe fn read_xmm_f32(mut r: i32) -> f32 { return (*reg_xmm.offset(r as isize)).f32_0[0]; } pub unsafe fn read_xmm32(mut r: i32) -> i32 { - return (*reg_xmm.offset(r as isize)).u32_0[0usize] as i32; + return (*reg_xmm.offset(r as isize)).u32_0[0] as i32; } pub unsafe fn read_xmm64s(mut r: i32) -> reg64 { let mut x: reg64 = reg64 { i8_0: [0; 8] }; - x.u64_0[0usize] = (*reg_xmm.offset(r as isize)).u64_0[0usize]; + x.u64_0[0] = (*reg_xmm.offset(r as isize)).u64_0[0]; return x; } pub unsafe fn read_xmm128s(mut r: i32) -> reg128 { return *reg_xmm.offset(r as isize); } pub unsafe fn write_xmm_f32(mut r: i32, mut data: f32) { - (*reg_xmm.offset(r as isize)).f32_0[0usize] = data; + (*reg_xmm.offset(r as isize)).f32_0[0] = data; } pub unsafe fn write_xmm32(mut r: i32, mut data: i32) { - (*reg_xmm.offset(r as isize)).i32_0[0usize] = data; + (*reg_xmm.offset(r as isize)).i32_0[0] = data; } pub unsafe fn write_xmm64(mut r: i32, mut data: reg64) { - (*reg_xmm.offset(r as isize)).u64_0[0usize] = data.u64_0[0usize]; + (*reg_xmm.offset(r as isize)).u64_0[0] = data.u64_0[0]; } pub unsafe fn write_xmm128(mut r: i32, mut i0: i32, mut i1: i32, mut i2: i32, mut i3: i32) { @@ -1373,17 +1361,17 @@ pub unsafe fn write_xmm128(mut r: i32, mut i0: i32, mut i1: i32, mut i2: i32, mu } pub unsafe fn write_xmm_reg128(mut r: i32, mut data: reg128) { - (*reg_xmm.offset(r as isize)).u64_0[0usize] = data.u64_0[0usize]; - (*reg_xmm.offset(r as isize)).u64_0[1usize] = data.u64_0[1usize]; + (*reg_xmm.offset(r as isize)).u64_0[0] = data.u64_0[0]; + (*reg_xmm.offset(r as isize)).u64_0[1] = data.u64_0[1]; } pub unsafe fn task_switch_test() -> bool { if 0 != *cr & (CR0_EM | CR0_TS) { trigger_nm(); - return 0 != 0i32; + return 0 != 0; } else { - return 0 != 1i32; + return 0 != 1; }; } @@ -1422,14 +1410,14 @@ pub unsafe fn task_switch_test_void() { task_switch_test(); } pub unsafe fn task_switch_test_mmx() -> bool { if 0 != *cr & CR0_TS { trigger_nm(); - return 0 != 0i32; + return 0 != 0; } else if 0 != *cr & CR0_EM { trigger_ud(); - return 0 != 0i32; + return 0 != 0; } else { - return 0 != 1i32; + return 0 != 1; }; } @@ -1478,7 +1466,7 @@ pub unsafe fn get_reg_asize(mut reg: i32) -> i32 { return r; } else { - return r & 65535i32; + return r & 65535; }; } @@ -1497,7 +1485,7 @@ pub unsafe fn add_reg_asize(mut reg: i32, mut value: i32) { *reg32s.offset(reg as isize) += value; } else { - *reg16.offset((reg << 1i32) as isize) += value as u16; + *reg16.offset((reg << 1) as isize) += value as u16; }; } @@ -1514,7 +1502,7 @@ pub unsafe fn decr_ecx_asize() -> i32 { #[no_mangle] pub unsafe fn set_tsc(mut low: u32, mut high: u32) { - let mut new_value: u64 = low as u64 | (high as u64) << 32i32; + let mut new_value: u64 = low as u64 | (high as u64) << 32; let mut current_value: u64 = read_tsc(); tsc_offset = current_value.wrapping_sub(new_value); } @@ -1522,7 +1510,7 @@ pub unsafe fn set_tsc(mut low: u32, mut high: u32) { pub unsafe fn read_tsc() -> u64 { let mut n: f64 = microtick() * TSC_RATE; let mut value: u64 = (n as u64).wrapping_sub(tsc_offset); - if 0 != 1i32 + 1i32 { + if 0 != 1 + 1 { return value; } else { @@ -1536,19 +1524,19 @@ pub unsafe fn read_tsc() -> u64 { let mut previous_value: u64 = rdtsc_last_value.wrapping_add(rdtsc_imprecision_offset); if previous_value <= value { rdtsc_last_value = value; - rdtsc_imprecision_offset = 0i32 as u64 + rdtsc_imprecision_offset = 0 as u64 } else { dbg_log!( "XXX: Overshot tsc prev={:x}:{:x} offset={:x}:{:x} curr={:x}:{:x}", - (rdtsc_last_value >> 32i32) as u32 as i32, + (rdtsc_last_value >> 32) as u32 as i32, rdtsc_last_value as u32 as i32, - (rdtsc_imprecision_offset >> 32i32) as u32 as i32, + (rdtsc_imprecision_offset >> 32) as u32 as i32, rdtsc_imprecision_offset as u32 as i32, - (value >> 32i32) as u32 as i32, + (value >> 32) as u32 as i32, value as u32 as i32 ); - dbg_assert!(0 != 0i32); + dbg_assert!(0 != 0); // Keep current value until time catches up } } @@ -1560,28 +1548,28 @@ pub unsafe fn read_tsc() -> u64 { pub unsafe fn vm86_mode() -> bool { return *flags & FLAG_VM == FLAG_VM; } #[no_mangle] -pub unsafe fn getiopl() -> i32 { return *flags >> 12i32 & 3i32; } +pub unsafe fn getiopl() -> i32 { return *flags >> 12 & 3; } #[no_mangle] pub unsafe fn get_opstats_buffer(mut index: i32) -> i32 { - dbg_assert!(index >= 0i32 && index < 512i32); - if index < 256i32 { + dbg_assert!(index >= 0 && index < 512); + if index < 256 { return *opstats_buffer.offset(index as isize) as i32; } else { - return *opstats_buffer_0f.offset((index - 256i32) as isize) as i32; + return *opstats_buffer_0f.offset((index - 256) as isize) as i32; }; } pub unsafe fn invlpg(mut addr: i32) { - let mut page: i32 = (addr as u32 >> 12i32) as i32; + let mut page: i32 = (addr as u32 >> 12) as i32; // Note: Doesn't remove this page from valid_tlb_entries: This isn't // necessary, because when valid_tlb_entries grows too large, it will be // empties by calling clear_tlb, which removes this entry as it isn't global. // This however means that valid_tlb_entries can contain some invalid entries - *tlb_data.offset(page as isize) = 0i32; - *last_virt_eip = -1i32; - *last_virt_esp = -1i32; + *tlb_data.offset(page as isize) = 0; + *last_virt_eip = -1; + *last_virt_esp = -1; } #[no_mangle] @@ -1590,14 +1578,14 @@ pub unsafe fn update_eflags(mut new_flags: i32) { let mut clear: i32 = !FLAG_VIP & !FLAG_VIF & FLAGS_MASK; if 0 != *flags & FLAG_VM { // other case needs to be handled in popf or iret - dbg_assert!(getiopl() == 3i32); + dbg_assert!(getiopl() == 3); dont_update |= FLAG_IOPL; // don't clear vip or vif clear |= FLAG_VIP | FLAG_VIF } else { if !*protected_mode { - dbg_assert!(*cpl as i32 == 0i32); + dbg_assert!(*cpl as i32 == 0); } if 0 != *cpl { // cpl > 0 @@ -1611,13 +1599,13 @@ pub unsafe fn update_eflags(mut new_flags: i32) { } } *flags = (new_flags ^ (*flags ^ new_flags) & dont_update) & clear | FLAGS_DEFAULT; - *flags_changed = 0i32; + *flags_changed = 0; } #[no_mangle] pub unsafe fn get_valid_tlb_entries_count() -> i32 { - let mut result: i32 = 0i32; - let mut i: i32 = 0i32; + let mut result: i32 = 0; + let mut i: i32 = 0; while i < valid_tlb_entries_count { let mut page: i32 = valid_tlb_entries[i as usize]; let mut entry: i32 = *tlb_data.offset(page as isize); @@ -1631,8 +1619,8 @@ pub unsafe fn get_valid_tlb_entries_count() -> i32 { #[no_mangle] pub unsafe fn get_valid_global_tlb_entries_count() -> i32 { - let mut result: i32 = 0i32; - let mut i: i32 = 0i32; + let mut result: i32 = 0; + let mut i: i32 = 0; while i < valid_tlb_entries_count { let mut page: i32 = valid_tlb_entries[i as usize]; let mut entry: i32 = *tlb_data.offset(page as isize); @@ -1645,24 +1633,24 @@ pub unsafe fn get_valid_global_tlb_entries_count() -> i32 { } pub unsafe fn translate_address_system_read(mut address: i32) -> Result { - let mut base: i32 = (address as u32 >> 12i32) as i32; + let mut base: i32 = (address as u32 >> 12) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); if 0 != entry & TLB_VALID { - return Ok((entry & !4095i32 ^ address) as u32); + return Ok((entry & !4095 ^ address) as u32); } else { - return Ok((do_page_translation(address, 0 != 0i32, 0 != 0i32)? | address & 4095i32) as u32); + return Ok((do_page_translation(address, 0 != 0, 0 != 0)? | address & 4095) as u32); }; } pub unsafe fn translate_address_system_write(mut address: i32) -> Result { - let mut base: i32 = (address as u32 >> 12i32) as i32; + let mut base: i32 = (address as u32 >> 12) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); if entry & (TLB_VALID | TLB_READONLY) == TLB_VALID { - return Ok((entry & !4095i32 ^ address) as u32); + return Ok((entry & !4095 ^ address) as u32); } else { - return Ok((do_page_translation(address, 0 != 1i32, 0 != 0i32)? | address & 4095i32) as u32); + return Ok((do_page_translation(address, 0 != 1, 0 != 0)? | address & 4095) as u32); }; } @@ -1674,7 +1662,7 @@ pub unsafe fn trigger_np(mut code: i32) { } } *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_NP, 0 != 0i32, 0 != 1i32, code); + call_interrupt_vector(CPU_EXCEPTION_NP, 0 != 0, 0 != 1, code); } #[no_mangle] @@ -1685,7 +1673,7 @@ pub unsafe fn trigger_ss(mut code: i32) { } } *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_SS, 0 != 0i32, 0 != 1i32, code); + call_interrupt_vector(CPU_EXCEPTION_SS, 0 != 0, 0 != 1, code); } #[no_mangle] diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 1ef945e7..8e8d75a8 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -32,28 +32,28 @@ pub const M_LOG2E: f64 = 1.4426950408889634f64; pub const M_LN2: f64 = 0.6931471805599453f64; pub const M_LN10: f64 = 2.302585092994046f64; pub const M_PI: f64 = 3.141592653589793f64; -const FPU_C0: i32 = 256i32; -pub const FPU_C1: i32 = 512i32; -const FPU_C2: i32 = 1024i32; -const FPU_C3: i32 = 16384i32; +const FPU_C0: i32 = 256; +pub const FPU_C1: i32 = 512; +const FPU_C2: i32 = 1024; +const FPU_C3: i32 = 16384; const FPU_RESULT_FLAGS: i32 = FPU_C0 | FPU_C1 | FPU_C2 | FPU_C3; -const FPU_STACK_TOP: i32 = 14336i32; +const FPU_STACK_TOP: i32 = 14336; const INDEFINITE_NAN: f64 = ::std::f64::NAN; -const FPU_EX_I: i32 = 1i32 << 0i32; -const FPU_EX_SF: i32 = 1i32 << 6i32; +const FPU_EX_I: i32 = 1 << 0; +const FPU_EX_SF: i32 = 1 << 6; const TWO_POW_63: f64 = 9223372036854775808u64 as f64; -const FPU_PC: i32 = 3i32 << 8i32; -const FPU_RC: i32 = 3i32 << 10i32; -const FPU_IF: i32 = 1i32 << 12i32; -const FPU_EX_P: i32 = 1i32 << 5i32; -const FPU_EX_U: i32 = 1i32 << 4i32; -const FPU_EX_O: i32 = 1i32 << 3i32; -const FPU_EX_Z: i32 = 1i32 << 2i32; -const FPU_EX_D: i32 = 1i32 << 1i32; +const FPU_PC: i32 = 3 << 8; +const FPU_RC: i32 = 3 << 10; +const FPU_IF: i32 = 1 << 12; +const FPU_EX_P: i32 = 1 << 5; +const FPU_EX_U: i32 = 1 << 4; +const FPU_EX_O: i32 = 1 << 3; +const FPU_EX_Z: i32 = 1 << 2; +const FPU_EX_D: i32 = 1 << 1; #[no_mangle] pub unsafe fn fpu_get_st0() -> f64 { - if 0 != *fpu_stack_empty >> *fpu_stack_ptr & 1i32 { + if 0 != *fpu_stack_empty >> *fpu_stack_ptr & 1 { *fpu_status_word &= !FPU_C1; fpu_stack_fault(); return INDEFINITE_NAN; @@ -69,9 +69,9 @@ pub unsafe fn fpu_stack_fault() { } #[no_mangle] pub unsafe fn fpu_get_sti(mut i: i32) -> f64 { - dbg_assert!(i >= 0i32 && i < 8i32); - i = ((i as u32).wrapping_add(*fpu_stack_ptr) & 7i32 as u32) as i32; - if 0 != *fpu_stack_empty >> i & 1i32 { + dbg_assert!(i >= 0 && i < 8); + i = ((i as u32).wrapping_add(*fpu_stack_ptr) & 7 as u32) as i32; + if 0 != *fpu_stack_empty >> i & 1 { *fpu_status_word &= !FPU_C1; fpu_stack_fault(); return INDEFINITE_NAN; @@ -82,9 +82,9 @@ pub unsafe fn fpu_get_sti(mut i: i32) -> f64 { } #[no_mangle] pub unsafe fn fpu_integer_round(mut f: f64) -> f64 { - let mut rc: i32 = *fpu_control_word >> 10i32 & 3i32; + let mut rc: i32 = *fpu_control_word >> 10 & 3; // XXX: See https://en.wikipedia.org/wiki/C_mathematical_functions - if rc == 0i32 { + if rc == 0 { // Round to nearest, or even if equidistant let mut rounded: f64 = round(f); let mut diff: f64 = rounded - f; @@ -93,7 +93,7 @@ pub unsafe fn fpu_integer_round(mut f: f64) -> f64 { } return rounded; } - else if rc == 1i32 || rc == 3i32 && f > 0i32 as f64 { + else if rc == 1 || rc == 3 && f > 0 as f64 { // rc=3 is truncate -> floor for positive numbers return floor(f); } @@ -110,24 +110,24 @@ pub unsafe fn fpu_load_m32(mut addr: i32) -> Result { } #[no_mangle] pub unsafe fn fpu_load_m64(mut addr: i32) -> Result { - let mut value: u64 = safe_read64s(addr)?.u64_0[0usize]; + let mut value: u64 = safe_read64s(addr)?.u64_0[0]; let mut v: f64_int = f64_int { u64_0: [value] }; Ok(v.f64_0) } #[no_mangle] pub unsafe fn fpu_load_m80(mut addr: u32) -> Result { - let mut value: u64 = safe_read64s(addr as i32)?.u64_0[0usize]; + let mut value: u64 = safe_read64s(addr as i32)?.u64_0[0]; let mut low: u32 = value as u32; - let mut high: u32 = (value >> 32i32) as u32; - let mut exponent: i32 = safe_read16(addr.wrapping_add(8i32 as u32) as i32)?; - let mut sign: i32 = exponent >> 15i32; - exponent &= !32768i32; - if exponent == 0i32 { + let mut high: u32 = (value >> 32) as u32; + let mut exponent: i32 = safe_read16(addr.wrapping_add(8 as u32) as i32)?; + let mut sign: i32 = exponent >> 15; + exponent &= !32768; + if exponent == 0 { // TODO: denormal numbers - Ok(0i32 as f64) + Ok(0 as f64) } - else if exponent < 32767i32 { - exponent -= 16383i32; + else if exponent < 32767 { + exponent -= 16383; // Note: some bits might be lost at this point let mut mantissa: f64 = low as f64 + 4294967296i64 as f64 * high as f64; if 0 != sign { @@ -136,39 +136,39 @@ pub unsafe fn fpu_load_m80(mut addr: u32) -> Result { // Simply compute the 64 bit floating point number. // An alternative write the mantissa, sign and exponent in the // float64_byte and return float64[0] - Ok(mantissa * pow(2i32 as f64, (exponent - 63i32) as f64)) + Ok(mantissa * pow(2 as f64, (exponent - 63) as f64)) } else { // TODO: NaN, Infinity - if 0 != 0i32 * 0i32 { + if 0 != 0 * 0 { dbg_log!("Load m80 TODO"); } let mut double_int_view: f64_int = f64_int { u8_0: [0; 8] }; - double_int_view.u8_0[7usize] = (127i32 | sign << 7i32) as u8; - double_int_view.u8_0[6usize] = (240i32 as u32 | high >> 30i32 << 3i32 & 8i32 as u32) as u8; - double_int_view.u8_0[5usize] = 0i32 as u8; - double_int_view.u8_0[4usize] = 0i32 as u8; - double_int_view.i32_0[0usize] = 0i32; + double_int_view.u8_0[7] = (127 | sign << 7) as u8; + double_int_view.u8_0[6] = (240 as u32 | high >> 30 << 3 & 8 as u32) as u8; + double_int_view.u8_0[5] = 0 as u8; + double_int_view.u8_0[4] = 0 as u8; + double_int_view.i32_0[0] = 0; Ok(double_int_view.f64_0) } } #[no_mangle] pub unsafe fn fpu_load_status_word() -> i32 { - return ((*fpu_status_word & !(7i32 << 11i32)) as u32 | *fpu_stack_ptr << 11i32) as i32; + return ((*fpu_status_word & !(7 << 11)) as u32 | *fpu_stack_ptr << 11) as i32; } #[no_mangle] pub unsafe fn fpu_fadd(mut target_index: i32, mut val: f64) { let mut st0: f64 = fpu_get_st0(); - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7 as u32) as isize) = st0 + val; } #[no_mangle] -pub unsafe fn fpu_fclex() { *fpu_status_word = 0i32; } +pub unsafe fn fpu_fclex() { *fpu_status_word = 0; } #[no_mangle] pub unsafe fn fpu_fcmovcc(mut condition: bool, mut r: i32) { if condition { *fpu_st.offset(*fpu_stack_ptr as isize) = fpu_get_sti(r); - *fpu_stack_empty &= !(1i32 << *fpu_stack_ptr) + *fpu_stack_empty &= !(1 << *fpu_stack_ptr) }; } #[no_mangle] @@ -191,17 +191,17 @@ pub unsafe fn fpu_fcom(mut y: f64) { pub unsafe fn fpu_fcomi(mut r: i32) { let mut y: f64 = fpu_get_sti(r); let mut x: f64 = *fpu_st.offset(*fpu_stack_ptr as isize); - *flags_changed &= !(1i32 | FLAG_PARITY | FLAG_ZERO); - *flags &= !(1i32 | FLAG_PARITY | FLAG_ZERO); + *flags_changed &= !(1 | FLAG_PARITY | FLAG_ZERO); + *flags &= !(1 | FLAG_PARITY | FLAG_ZERO); if !(x > y) { if y > x { - *flags |= 1i32 + *flags |= 1 } else if x == y { *flags |= FLAG_ZERO } else { - *flags |= 1i32 | FLAG_PARITY | FLAG_ZERO + *flags |= 1 | FLAG_PARITY | FLAG_ZERO } }; } @@ -212,8 +212,8 @@ pub unsafe fn fpu_fcomip(mut r: i32) { } #[no_mangle] pub unsafe fn fpu_pop() { - *fpu_stack_empty |= 1i32 << *fpu_stack_ptr; - *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_add(1i32 as u32) & 7i32 as u32; + *fpu_stack_empty |= 1 << *fpu_stack_ptr; + *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_add(1 as u32) & 7 as u32; } #[no_mangle] pub unsafe fn fpu_fcomp(mut val: f64) { @@ -223,31 +223,31 @@ pub unsafe fn fpu_fcomp(mut val: f64) { #[no_mangle] pub unsafe fn fpu_fdiv(mut target_index: i32, mut val: f64) { let mut st0: f64 = fpu_get_st0(); - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7 as u32) as isize) = st0 / val; } #[no_mangle] pub unsafe fn fpu_fdivr(mut target_index: i32, mut val: f64) { let mut st0: f64 = fpu_get_st0(); - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7 as u32) as isize) = val / st0; } #[no_mangle] pub unsafe fn fpu_ffree(mut r: i32) { - *fpu_stack_empty |= 1i32 << (*fpu_stack_ptr).wrapping_add(r as u32); + *fpu_stack_empty |= 1 << (*fpu_stack_ptr).wrapping_add(r as u32); } #[no_mangle] pub unsafe fn fpu_fildm64(mut addr: i32) { - let mut value: i64 = return_on_pagefault!(safe_read64s(addr)).i64_0[0usize]; + let mut value: i64 = return_on_pagefault!(safe_read64s(addr)).i64_0[0]; let mut m64: f64 = value as f64; fpu_push(m64); } #[no_mangle] pub unsafe fn fpu_push(mut x: f64) { - *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_sub(1i32 as u32) & 7i32 as u32; - if 0 != *fpu_stack_empty >> *fpu_stack_ptr & 1i32 { + *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_sub(1 as u32) & 7 as u32; + if 0 != *fpu_stack_empty >> *fpu_stack_ptr & 1 { *fpu_status_word &= !FPU_C1; - *fpu_stack_empty &= !(1i32 << *fpu_stack_ptr); + *fpu_stack_empty &= !(1 << *fpu_stack_ptr); *fpu_st.offset(*fpu_stack_ptr as isize) = x } else { @@ -258,23 +258,23 @@ pub unsafe fn fpu_push(mut x: f64) { } #[no_mangle] pub unsafe fn fpu_finit() { - *fpu_control_word = 895i32; - *fpu_status_word = 0i32; - *fpu_ip = 0i32; - *fpu_dp = 0i32; - *fpu_opcode = 0i32; - *fpu_stack_empty = 255i32; - *fpu_stack_ptr = 0i32 as u32; + *fpu_control_word = 895; + *fpu_status_word = 0; + *fpu_ip = 0; + *fpu_dp = 0; + *fpu_opcode = 0; + *fpu_stack_empty = 255; + *fpu_stack_ptr = 0 as u32; } #[no_mangle] pub unsafe fn fpu_fistm16(mut addr: i32) { let mut st0: f64 = fpu_integer_round(fpu_get_st0()); - if st0 <= 32767i32 as f64 && st0 >= -32768i32 as f64 { + if st0 <= 32767 as f64 && st0 >= -32768 as f64 { return_on_pagefault!(safe_write16(addr, st0 as i32)); } else { fpu_invalid_arithmetic(); - return_on_pagefault!(safe_write16(addr, 32768i32)); + return_on_pagefault!(safe_write16(addr, 32768)); }; } #[no_mangle] @@ -288,7 +288,7 @@ pub unsafe fn fpu_fistm16p(mut addr: i32) { pub unsafe fn fpu_fistm32(mut addr: i32) { let mut st0: f64 = fpu_integer_round(fpu_get_st0()); let mut i: i32 = convert_f64_to_i32(st0); - if i == 2147483648u32 as i32 { + if i == -0x80000000 { // XXX: Probably not correct if st0 == 0x80000000 // (input fits, but same value as error value) fpu_invalid_arithmetic(); @@ -326,13 +326,13 @@ pub unsafe fn fpu_fldenv(mut addr: i32) { return_on_pagefault!(translate_address_read(addr)); return_on_pagefault!(translate_address_read(addr + 28)); *fpu_control_word = safe_read16(addr).unwrap(); - fpu_set_status_word(safe_read16(addr + 4i32).unwrap()); - fpu_set_tag_word(safe_read16(addr + 8i32).unwrap()); - *fpu_ip = safe_read32s(addr + 12i32).unwrap(); - *fpu_ip_selector = safe_read16(addr + 16i32).unwrap(); - *fpu_opcode = safe_read16(addr + 18i32).unwrap(); - *fpu_dp = safe_read32s(addr + 20i32).unwrap(); - *fpu_dp_selector = safe_read16(addr + 24i32).unwrap() + fpu_set_status_word(safe_read16(addr + 4).unwrap()); + fpu_set_tag_word(safe_read16(addr + 8).unwrap()); + *fpu_ip = safe_read32s(addr + 12).unwrap(); + *fpu_ip_selector = safe_read16(addr + 16).unwrap(); + *fpu_opcode = safe_read16(addr + 18).unwrap(); + *fpu_dp = safe_read32s(addr + 20).unwrap(); + *fpu_dp_selector = safe_read16(addr + 24).unwrap() } else { dbg_log!("fldenv16"); @@ -342,7 +342,7 @@ pub unsafe fn fpu_fldenv(mut addr: i32) { #[no_mangle] pub unsafe fn fpu_unimpl() { if DEBUG { - dbg_assert!(0 != 0i32); + dbg_assert!(0 != 0); } else { trigger_ud(); @@ -350,9 +350,9 @@ pub unsafe fn fpu_unimpl() { } #[no_mangle] pub unsafe fn fpu_set_tag_word(mut tag_word: i32) { - *fpu_stack_empty = 0i32; - let mut i: i32 = 0i32; - while i < 8i32 { + *fpu_stack_empty = 0; + let mut i: i32 = 0; + while i < 8 { let empty = tag_word >> (2 * i) & 3 == 3; *fpu_stack_empty |= (empty as i32) << i; i += 1 @@ -360,8 +360,8 @@ pub unsafe fn fpu_set_tag_word(mut tag_word: i32) { } #[no_mangle] pub unsafe fn fpu_set_status_word(mut sw: i32) { - *fpu_status_word = sw & !(7i32 << 11i32); - *fpu_stack_ptr = (sw >> 11i32 & 7i32) as u32; + *fpu_status_word = sw & !(7 << 11); + *fpu_stack_ptr = (sw >> 11 & 7) as u32; } #[no_mangle] pub unsafe fn fpu_fldm32(mut addr: i32) { @@ -376,7 +376,7 @@ pub unsafe fn fpu_fldm80(mut addr: i32) { #[no_mangle] pub unsafe fn fpu_fmul(mut target_index: i32, mut val: f64) { let mut st0: f64 = fpu_get_st0(); - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7 as u32) as isize) = st0 * val; } #[no_mangle] @@ -389,17 +389,17 @@ pub unsafe fn fpu_fnstsw_reg() { *reg16.offset(AX as isize) = fpu_load_status_wo pub unsafe fn fpu_fprem() { // XXX: This implementation differs from the description in Intel's manuals let mut st0: f64 = fpu_get_st0(); - let mut st1: f64 = fpu_get_sti(1i32); + let mut st1: f64 = fpu_get_sti(1); let mut fprem_quotient: i32 = convert_f64_to_i32(trunc(st0 / st1)); *fpu_st.offset(*fpu_stack_ptr as isize) = fmod(st0, st1); *fpu_status_word &= !(FPU_C0 | FPU_C1 | FPU_C3); - if 0 != fprem_quotient & 1i32 { + if 0 != fprem_quotient & 1 { *fpu_status_word |= FPU_C1 } - if 0 != fprem_quotient & 1i32 << 1i32 { + if 0 != fprem_quotient & 1 << 1 { *fpu_status_word |= FPU_C3 } - if 0 != fprem_quotient & 1i32 << 2i32 { + if 0 != fprem_quotient & 1 << 2 { *fpu_status_word |= FPU_C0 } *fpu_status_word &= !FPU_C2; @@ -410,27 +410,27 @@ pub unsafe fn fpu_frstor(mut addr: i32) { return_on_pagefault!(translate_address_read(addr)); return_on_pagefault!(translate_address_read(addr + 28 + 8 * 10)); fpu_fldenv(addr); - addr += 28i32; - let mut i: i32 = 0i32; - while i < 8i32 { - *fpu_st.offset(((i as u32).wrapping_add(*fpu_stack_ptr) & 7i32 as u32) as isize) = + addr += 28; + let mut i: i32 = 0; + while i < 8 { + *fpu_st.offset(((i as u32).wrapping_add(*fpu_stack_ptr) & 7 as u32) as isize) = fpu_load_m80(addr as u32).unwrap(); - addr += 10i32; + addr += 10; i += 1 } } #[no_mangle] pub unsafe fn fpu_fsave(mut addr: i32) { - return_on_pagefault!(writable_or_pagefault(addr, 108i32)); + return_on_pagefault!(writable_or_pagefault(addr, 108)); fpu_fstenv(addr); - addr += 28i32; - let mut i: i32 = 0i32; - while i < 8i32 { + addr += 28; + let mut i: i32 = 0; + while i < 8 { fpu_store_m80( addr as u32, - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(i as u32) & 7i32 as u32) as isize), + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(i as u32) & 7 as u32) as isize), ); - addr += 10i32; + addr += 10; i += 1 } fpu_finit(); @@ -438,55 +438,54 @@ pub unsafe fn fpu_fsave(mut addr: i32) { #[no_mangle] pub unsafe fn fpu_store_m80(mut addr: u32, mut n: f64) { let mut double_int_view: f64_int = f64_int { f64_0: n }; - let mut sign: u8 = (double_int_view.u8_0[7usize] as i32 & 128i32) as u8; - let mut exponent: i32 = (double_int_view.u8_0[7usize] as i32 & 127i32) << 4i32 - | double_int_view.u8_0[6usize] as i32 >> 4i32; + let mut sign: u8 = (double_int_view.u8_0[7] as i32 & 128) as u8; + let mut exponent: i32 = + (double_int_view.u8_0[7] as i32 & 127) << 4 | double_int_view.u8_0[6] as i32 >> 4; let mut low; let mut high; - if exponent == 2047i32 { + if exponent == 2047 { // all bits set (NaN and infinity) - exponent = 32767i32; - low = 0i32; - high = - (2147483648u32 | ((double_int_view.i32_0[1usize] & 524288i32) << 11i32) as u32) as i32 + exponent = 32767; + low = 0; + high = (2147483648 | ((double_int_view.i32_0[1] & 524288) << 11) as u32) as i32 } - else if exponent == 0i32 { + else if exponent == 0 { // zero and denormal numbers // Just assume zero for now - low = 0i32; - high = 0i32 + low = 0; + high = 0 } else { - exponent += 16383i32 - 1023i32; + exponent += 16383 - 1023; // does the mantissa need to be adjusted? - low = double_int_view.i32_0[0usize] << 11i32; - high = (2147483648u32 - | ((double_int_view.i32_0[1usize] & 1048575i32) << 11i32) as u32 - | double_int_view.i32_0[0usize] as u32 >> 21i32) as i32 + low = double_int_view.i32_0[0] << 11; + high = (2147483648 + | ((double_int_view.i32_0[1] & 1048575) << 11) as u32 + | double_int_view.i32_0[0] as u32 >> 21) as i32 } - dbg_assert!(exponent >= 0i32 && exponent < 32768i32); + dbg_assert!(exponent >= 0 && exponent < 32768); // writable_or_pagefault must have checked called by the caller! safe_write64( addr as i32, - (low as u64 & 4294967295u32 as u64 | (high as u64) << 32i32) as i64, + (low as u64 & 4294967295 as u64 | (high as u64) << 32) as i64, ).unwrap(); safe_write16( - addr.wrapping_add(8i32 as u32) as i32, - (sign as i32) << 8i32 | exponent, + addr.wrapping_add(8 as u32) as i32, + (sign as i32) << 8 | exponent, ).unwrap(); } #[no_mangle] pub unsafe fn fpu_fstenv(mut addr: i32) { if is_osize_32() { - return_on_pagefault!(writable_or_pagefault(addr, 26i32)); + return_on_pagefault!(writable_or_pagefault(addr, 26)); safe_write16(addr, *fpu_control_word).unwrap(); - safe_write16(addr + 4i32, fpu_load_status_word()).unwrap(); - safe_write16(addr + 8i32, fpu_load_tag_word()).unwrap(); - safe_write32(addr + 12i32, *fpu_ip).unwrap(); - safe_write16(addr + 16i32, *fpu_ip_selector).unwrap(); - safe_write16(addr + 18i32, *fpu_opcode).unwrap(); - safe_write32(addr + 20i32, *fpu_dp).unwrap(); - safe_write16(addr + 24i32, *fpu_dp_selector).unwrap(); + safe_write16(addr + 4, fpu_load_status_word()).unwrap(); + safe_write16(addr + 8, fpu_load_tag_word()).unwrap(); + safe_write32(addr + 12, *fpu_ip).unwrap(); + safe_write16(addr + 16, *fpu_ip_selector).unwrap(); + safe_write16(addr + 18, *fpu_opcode).unwrap(); + safe_write32(addr + 20, *fpu_dp).unwrap(); + safe_write16(addr + 24, *fpu_dp_selector).unwrap(); } else { dbg_log!("fstenv16"); @@ -495,18 +494,18 @@ pub unsafe fn fpu_fstenv(mut addr: i32) { } #[no_mangle] pub unsafe fn fpu_load_tag_word() -> i32 { - let mut tag_word: i32 = 0i32; - let mut i: i32 = 0i32; - while i < 8i32 { + let mut tag_word: i32 = 0; + let mut i: i32 = 0; + while i < 8 { let mut value: f64 = *fpu_st.offset(i as isize); - if 0 != *fpu_stack_empty >> i & 1i32 { - tag_word |= 3i32 << (i << 1i32) + if 0 != *fpu_stack_empty >> i & 1 { + tag_word |= 3 << (i << 1) } - else if value == 0i32 as f64 { - tag_word |= 1i32 << (i << 1i32) + else if value == 0 as f64 { + tag_word |= 1 << (i << 1) } else if !value.is_finite() { - tag_word |= 2i32 << (i << 1i32) + tag_word |= 2 << (i << 1) } i += 1 } @@ -518,7 +517,7 @@ pub unsafe fn fpu_fst(mut r: i32) { } #[no_mangle] pub unsafe fn fpu_fst80p(mut addr: i32) { - return_on_pagefault!(writable_or_pagefault(addr, 10i32)); + return_on_pagefault!(writable_or_pagefault(addr, 10)); fpu_store_m80(addr as u32, fpu_get_st0()); fpu_pop(); } @@ -547,7 +546,7 @@ pub unsafe fn fpu_fstm64(mut addr: i32) { #[no_mangle] pub unsafe fn fpu_store_m64(mut addr: i32, mut x: f64) -> Result<(), ()> { let mut v: f64_int = f64_int { f64_0: x }; - safe_write64(addr, v.u64_0[0usize] as i64) + safe_write64(addr, v.u64_0[0] as i64) } #[no_mangle] pub unsafe fn fpu_fstm64p(mut addr: i32) { @@ -562,13 +561,13 @@ pub unsafe fn fpu_fstp(mut r: i32) { #[no_mangle] pub unsafe fn fpu_fsub(mut target_index: i32, mut val: f64) { let mut st0: f64 = fpu_get_st0(); - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7 as u32) as isize) = st0 - val; } #[no_mangle] pub unsafe fn fpu_fsubr(mut target_index: i32, mut val: f64) { let mut st0: f64 = fpu_get_st0(); - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7i32 as u32) as isize) = + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7 as u32) as isize) = val - st0; } #[no_mangle] @@ -577,10 +576,10 @@ pub unsafe fn fpu_ftst(mut x: f64) { if x.is_nan() { *fpu_status_word |= FPU_C3 | FPU_C2 | FPU_C0 } - else if x == 0i32 as f64 { + else if x == 0 as f64 { *fpu_status_word |= FPU_C3 } - else if x < 0i32 as f64 { + else if x < 0 as f64 { *fpu_status_word |= FPU_C0 } // TODO: unordered (x is nan, etc) @@ -607,21 +606,21 @@ pub unsafe fn fpu_fucomp(mut r: i32) { } #[no_mangle] pub unsafe fn fpu_fucompp() { - fpu_fucom(1i32); + fpu_fucom(1); fpu_pop(); fpu_pop(); } #[no_mangle] pub unsafe fn fpu_fxam(mut x: f64) { *fpu_status_word &= !FPU_RESULT_FLAGS; - *fpu_status_word |= fpu_sign(0i32) << 9i32; - if 0 != *fpu_stack_empty >> *fpu_stack_ptr & 1i32 { + *fpu_status_word |= fpu_sign(0) << 9; + if 0 != *fpu_stack_empty >> *fpu_stack_ptr & 1 { *fpu_status_word |= FPU_C3 | FPU_C0 } else if x.is_nan() { *fpu_status_word |= FPU_C0 } - else if x == 0i32 as f64 { + else if x == 0 as f64 { *fpu_status_word |= FPU_C3 } else if x == ::std::f32::INFINITY as f64 || x == -::std::f32::INFINITY as f64 { @@ -636,10 +635,10 @@ pub unsafe fn fpu_fxam(mut x: f64) { #[no_mangle] pub unsafe fn fpu_sign(mut i: i32) -> i32 { // sign of a number on the stack - return *fpu_st8.offset( - (((*fpu_stack_ptr).wrapping_add(i as u32) & 7i32 as u32) << 3i32 | 7i32 as u32) as isize, - ) as i32 - >> 7i32; + return *fpu_st8 + .offset((((*fpu_stack_ptr).wrapping_add(i as u32) & 7 as u32) << 3 | 7 as u32) as isize) + as i32 + >> 7; } #[no_mangle] pub unsafe fn fpu_fxch(mut i: i32) { @@ -652,11 +651,11 @@ pub unsafe fn fpu_fxtract() { let mut double_int_view: f64_int = f64_int { f64_0: fpu_get_st0(), }; - let mut exponent: f64 = (((double_int_view.u8_0[7usize] as i32 & 127i32) << 4i32 - | double_int_view.u8_0[6usize] as i32 >> 4i32) - - 1023i32) as f64; - double_int_view.u8_0[7usize] = (63i32 | double_int_view.u8_0[7usize] as i32 & 128i32) as u8; - double_int_view.u8_0[6usize] = (double_int_view.u8_0[6usize] as i32 | 240i32) as u8; + let mut exponent: f64 = (((double_int_view.u8_0[7] as i32 & 127) << 4 + | double_int_view.u8_0[6] as i32 >> 4) + - 1023) as f64; + double_int_view.u8_0[7] = (63 | double_int_view.u8_0[7] as i32 & 128) as u8; + double_int_view.u8_0[6] = (double_int_view.u8_0[6] as i32 | 240) as u8; *fpu_st.offset(*fpu_stack_ptr as isize) = exponent; fpu_push(double_int_view.f64_0); } diff --git a/src/rust/cpu2/global_pointers.rs b/src/rust/cpu2/global_pointers.rs index d2706e7d..912dc01e 100644 --- a/src/rust/cpu2/global_pointers.rs +++ b/src/rust/cpu2/global_pointers.rs @@ -2,64 +2,64 @@ use cpu2::cpu::{reg128, reg64}; -pub const reg8: *mut u8 = 4i32 as *mut u8; -pub const reg16: *mut u16 = 4i32 as *mut u16; -pub const reg8s: *mut i8 = 4i32 as *mut i8; -pub const reg16s: *mut i16 = 4i32 as *mut i16; -pub const reg32s: *mut i32 = 4i32 as *mut i32; -pub const last_op1: *mut i32 = 512i32 as *mut i32; -pub const last_op2: *mut i32 = 516i32 as *mut i32; -pub const last_op_size: *mut i32 = 520i32 as *mut i32; -pub const last_add_result: *mut i32 = 524i32 as *mut i32; -pub const last_result: *mut i32 = 528i32 as *mut i32; -pub const flags_changed: *mut i32 = 532i32 as *mut i32; -pub const flags: *mut i32 = 536i32 as *mut i32; -pub const page_fault: *mut bool = 540i32 as *mut bool; -pub const a20_enabled: *mut bool = 552i32 as *mut bool; -pub const instruction_pointer: *mut i32 = 556i32 as *mut i32; -pub const previous_ip: *mut i32 = 560i32 as *mut i32; -pub const idtr_size: *mut i32 = 564i32 as *mut i32; -pub const idtr_offset: *mut i32 = 568i32 as *mut i32; -pub const gdtr_size: *mut i32 = 572i32 as *mut i32; -pub const gdtr_offset: *mut i32 = 576i32 as *mut i32; -pub const cr: *mut i32 = 580i32 as *mut i32; -pub const cpl: *mut u8 = 612i32 as *mut u8; -pub const in_hlt: *mut bool = 616i32 as *mut bool; -pub const last_virt_eip: *mut i32 = 620i32 as *mut i32; -pub const eip_phys: *mut i32 = 624i32 as *mut i32; -pub const last_virt_esp: *mut i32 = 628i32 as *mut i32; -pub const esp_phys: *mut i32 = 632i32 as *mut i32; -pub const sysenter_cs: *mut i32 = 636i32 as *mut i32; -pub const sysenter_esp: *mut i32 = 640i32 as *mut i32; -pub const sysenter_eip: *mut i32 = 644i32 as *mut i32; -pub const prefixes: *mut u8 = 648i32 as *mut u8; -pub const timestamp_counter: *mut u32 = 664i32 as *mut u32; -pub const sreg: *mut u16 = 668i32 as *mut u16; -pub const dreg: *mut i32 = 684i32 as *mut i32; -pub const fw_value: *mut i32 = 720i32 as *mut i32; -pub const segment_is_null: *mut bool = 724i32 as *mut bool; -pub const segment_offsets: *mut i32 = 736i32 as *mut i32; -pub const segment_limits: *mut u32 = 768i32 as *mut u32; -pub const protected_mode: *mut bool = 800i32 as *mut bool; -pub const is_32: *mut bool = 804i32 as *mut bool; -pub const stack_size_32: *mut bool = 808i32 as *mut bool; -pub const memory_size: *mut u32 = 812i32 as *mut u32; -pub const fpu_stack_empty: *mut i32 = 816i32 as *mut i32; -pub const mxcsr: *mut i32 = 824i32 as *mut i32; -pub const reg_xmm: *mut reg128 = 828i32 as *mut reg128; -pub const current_tsc: *mut u64 = 956i32 as *mut u64; -pub const fpu_st: *mut f64 = 968i32 as *mut f64; -pub const fpu_st8: *mut u8 = 968i32 as *mut u8; -pub const fpu_st32: *mut i32 = 968i32 as *mut i32; -pub const fpu_stack_ptr: *mut u32 = 1032i32 as *mut u32; -pub const fpu_control_word: *mut i32 = 1036i32 as *mut i32; -pub const fpu_status_word: *mut i32 = 1040i32 as *mut i32; -pub const fpu_opcode: *mut i32 = 1044i32 as *mut i32; -pub const fpu_ip: *mut i32 = 1048i32 as *mut i32; -pub const fpu_ip_selector: *mut i32 = 1052i32 as *mut i32; -pub const fpu_dp: *mut i32 = 1056i32 as *mut i32; -pub const fpu_dp_selector: *mut i32 = 1060i32 as *mut i32; -pub const reg_mmx: *mut reg64 = 1064i32 as *mut reg64; -pub const opstats_buffer: *mut u32 = 4096i32 as *mut u32; -pub const opstats_buffer_0f: *mut u32 = 5120i32 as *mut u32; -pub const tlb_data: *mut i32 = 4194304i32 as *mut i32; +pub const reg8: *mut u8 = 4 as *mut u8; +pub const reg16: *mut u16 = 4 as *mut u16; +pub const reg8s: *mut i8 = 4 as *mut i8; +pub const reg16s: *mut i16 = 4 as *mut i16; +pub const reg32s: *mut i32 = 4 as *mut i32; +pub const last_op1: *mut i32 = 512 as *mut i32; +pub const last_op2: *mut i32 = 516 as *mut i32; +pub const last_op_size: *mut i32 = 520 as *mut i32; +pub const last_add_result: *mut i32 = 524 as *mut i32; +pub const last_result: *mut i32 = 528 as *mut i32; +pub const flags_changed: *mut i32 = 532 as *mut i32; +pub const flags: *mut i32 = 536 as *mut i32; +pub const page_fault: *mut bool = 540 as *mut bool; +pub const a20_enabled: *mut bool = 552 as *mut bool; +pub const instruction_pointer: *mut i32 = 556 as *mut i32; +pub const previous_ip: *mut i32 = 560 as *mut i32; +pub const idtr_size: *mut i32 = 564 as *mut i32; +pub const idtr_offset: *mut i32 = 568 as *mut i32; +pub const gdtr_size: *mut i32 = 572 as *mut i32; +pub const gdtr_offset: *mut i32 = 576 as *mut i32; +pub const cr: *mut i32 = 580 as *mut i32; +pub const cpl: *mut u8 = 612 as *mut u8; +pub const in_hlt: *mut bool = 616 as *mut bool; +pub const last_virt_eip: *mut i32 = 620 as *mut i32; +pub const eip_phys: *mut i32 = 624 as *mut i32; +pub const last_virt_esp: *mut i32 = 628 as *mut i32; +pub const esp_phys: *mut i32 = 632 as *mut i32; +pub const sysenter_cs: *mut i32 = 636 as *mut i32; +pub const sysenter_esp: *mut i32 = 640 as *mut i32; +pub const sysenter_eip: *mut i32 = 644 as *mut i32; +pub const prefixes: *mut u8 = 648 as *mut u8; +pub const timestamp_counter: *mut u32 = 664 as *mut u32; +pub const sreg: *mut u16 = 668 as *mut u16; +pub const dreg: *mut i32 = 684 as *mut i32; +pub const fw_value: *mut i32 = 720 as *mut i32; +pub const segment_is_null: *mut bool = 724 as *mut bool; +pub const segment_offsets: *mut i32 = 736 as *mut i32; +pub const segment_limits: *mut u32 = 768 as *mut u32; +pub const protected_mode: *mut bool = 800 as *mut bool; +pub const is_32: *mut bool = 804 as *mut bool; +pub const stack_size_32: *mut bool = 808 as *mut bool; +pub const memory_size: *mut u32 = 812 as *mut u32; +pub const fpu_stack_empty: *mut i32 = 816 as *mut i32; +pub const mxcsr: *mut i32 = 824 as *mut i32; +pub const reg_xmm: *mut reg128 = 828 as *mut reg128; +pub const current_tsc: *mut u64 = 956 as *mut u64; +pub const fpu_st: *mut f64 = 968 as *mut f64; +pub const fpu_st8: *mut u8 = 968 as *mut u8; +pub const fpu_st32: *mut i32 = 968 as *mut i32; +pub const fpu_stack_ptr: *mut u32 = 1032 as *mut u32; +pub const fpu_control_word: *mut i32 = 1036 as *mut i32; +pub const fpu_status_word: *mut i32 = 1040 as *mut i32; +pub const fpu_opcode: *mut i32 = 1044 as *mut i32; +pub const fpu_ip: *mut i32 = 1048 as *mut i32; +pub const fpu_ip_selector: *mut i32 = 1052 as *mut i32; +pub const fpu_dp: *mut i32 = 1056 as *mut i32; +pub const fpu_dp_selector: *mut i32 = 1060 as *mut i32; +pub const reg_mmx: *mut reg64 = 1064 as *mut reg64; +pub const opstats_buffer: *mut u32 = 4096 as *mut u32; +pub const opstats_buffer_0f: *mut u32 = 5120 as *mut u32; +pub const tlb_data: *mut i32 = 4194304 as *mut i32; diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index faae6179..f17b2fdd 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -123,14 +123,11 @@ pub unsafe fn instr32_06() { } #[no_mangle] pub unsafe fn instr16_07() { - if !switch_seg( - ES, - return_on_pagefault!(safe_read16(get_stack_pointer(0i32))), - ) { + if !switch_seg(ES, return_on_pagefault!(safe_read16(get_stack_pointer(0)))) { return; } else { - adjust_stack_reg(2i32); + adjust_stack_reg(2); return; }; } @@ -138,12 +135,12 @@ pub unsafe fn instr16_07() { pub unsafe fn instr32_07() { if !switch_seg( ES, - return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))) & 65535i32, + return_on_pagefault!(safe_read32s(get_stack_pointer(0))) & 65535, ) { return; } else { - adjust_stack_reg(4i32); + adjust_stack_reg(4); return; }; } @@ -307,14 +304,11 @@ pub unsafe fn instr32_16() { } #[no_mangle] pub unsafe fn instr16_17() { - if !switch_seg( - SS, - return_on_pagefault!(safe_read16(get_stack_pointer(0i32))), - ) { + if !switch_seg(SS, return_on_pagefault!(safe_read16(get_stack_pointer(0)))) { return; } else { - adjust_stack_reg(2i32); + adjust_stack_reg(2); return; }; } @@ -322,12 +316,12 @@ pub unsafe fn instr16_17() { pub unsafe fn instr32_17() { if !switch_seg( SS, - return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))) & 65535i32, + return_on_pagefault!(safe_read32s(get_stack_pointer(0))) & 65535, ) { return; } else { - adjust_stack_reg(4i32); + adjust_stack_reg(4); return; }; } @@ -410,14 +404,11 @@ pub unsafe fn instr32_1E() { } #[no_mangle] pub unsafe fn instr16_1F() { - if !switch_seg( - DS, - return_on_pagefault!(safe_read16(get_stack_pointer(0i32))), - ) { + if !switch_seg(DS, return_on_pagefault!(safe_read16(get_stack_pointer(0)))) { return; } else { - adjust_stack_reg(2i32); + adjust_stack_reg(2); return; }; } @@ -425,12 +416,12 @@ pub unsafe fn instr16_1F() { pub unsafe fn instr32_1F() { if !switch_seg( DS, - return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))) & 65535i32, + return_on_pagefault!(safe_read32s(get_stack_pointer(0))) & 65535, ) { return; } else { - adjust_stack_reg(4i32); + adjust_stack_reg(4); return; }; } @@ -877,11 +868,11 @@ pub unsafe fn instr16_5B() { *reg16.offset(BX as isize) = return_on_pagefault!(p pub unsafe fn instr32_5B() { *reg32s.offset(EBX as isize) = return_on_pagefault!(pop32s()); } #[no_mangle] pub unsafe fn instr16_5C() { - *reg16.offset(SP as isize) = return_on_pagefault!(safe_read16(get_stack_pointer(0i32))) as u16; + *reg16.offset(SP as isize) = return_on_pagefault!(safe_read16(get_stack_pointer(0))) as u16; } #[no_mangle] pub unsafe fn instr32_5C() { - *reg32s.offset(ESP as isize) = return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))); + *reg32s.offset(ESP as isize) = return_on_pagefault!(safe_read32s(get_stack_pointer(0))); } #[no_mangle] pub unsafe fn instr16_5D() { *reg16.offset(BP as isize) = return_on_pagefault!(pop16()) as u16; } @@ -907,12 +898,12 @@ pub unsafe fn instr32_61() { popa32(); } pub unsafe fn instr_62_reg(mut r2: i32, mut r: i32) { // bound dbg_log!("Unimplemented BOUND instruction"); - dbg_assert!(0 != 0i32); + dbg_assert!(0 != 0); } #[no_mangle] pub unsafe fn instr_62_mem(mut addr: i32, mut r: i32) { dbg_log!("Unimplemented BOUND instruction"); - dbg_assert!(0 != 0i32); + dbg_assert!(0 != 0); } #[no_mangle] pub unsafe fn instr_63_mem(mut addr: i32, mut r: i32) { @@ -932,7 +923,7 @@ pub unsafe fn instr_66() { // Operand-size override prefix *prefixes = (*prefixes as i32 | PREFIX_MASK_OPSIZE) as u8; run_prefix_instruction(); - *prefixes = 0i32 as u8; + *prefixes = 0 as u8; } #[no_mangle] pub unsafe fn instr_67() { @@ -940,7 +931,7 @@ pub unsafe fn instr_67() { dbg_assert!(is_asize_32() as i32 == *is_32 as i32); *prefixes = (*prefixes as i32 | PREFIX_MASK_ADDRSIZE) as u8; run_prefix_instruction(); - *prefixes = 0i32 as u8; + *prefixes = 0 as u8; } #[no_mangle] pub unsafe fn instr16_68(mut imm16: i32) { @@ -1523,13 +1514,13 @@ pub unsafe fn instr32_8B_reg(mut r1: i32, mut r: i32) { } #[no_mangle] pub unsafe fn instr_8C_check_sreg(mut seg: i32) -> bool { - if seg >= 6i32 { + if seg >= 6 { dbg_log!("mov sreg #ud"); trigger_ud(); - return 0 != 0i32; + return 0 != 0; } else { - return 0 != 1i32; + return 0 != 1; }; } #[no_mangle] @@ -1568,7 +1559,7 @@ pub unsafe fn instr16_8D_mem(modrm_byte: i32, mut r: i32) { if let Ok(addr) = modrm_resolve(modrm_byte) { write_reg16(r, addr); } - *prefixes = 0i32 as u8; + *prefixes = 0 as u8; } #[no_mangle] pub unsafe fn instr32_8D_reg(mut r: i32, mut r2: i32) { @@ -1583,7 +1574,7 @@ pub unsafe fn instr32_8D_mem(modrm_byte: i32, mut r: i32) { if let Ok(addr) = modrm_resolve(modrm_byte) { write_reg32(r, addr); } - *prefixes = 0i32 as u8; + *prefixes = 0 as u8; } #[no_mangle] pub unsafe fn instr_8E_helper(mut data: i32, mut mod_0: i32) { @@ -1612,27 +1603,27 @@ pub unsafe fn instr_8E_reg(mut r1: i32, mut r: i32) { pub unsafe fn instr16_8F_0_mem(modrm_byte: i32) { // pop // Update esp *before* resolving the address - adjust_stack_reg(2i32); + adjust_stack_reg(2); match modrm_resolve(modrm_byte) { Err(()) => { // a pagefault happened, reset esp - adjust_stack_reg(-2i32); + adjust_stack_reg(-2); }, Ok(addr) => { - adjust_stack_reg(-2i32); - let mut stack_value: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0i32))); + adjust_stack_reg(-2); + let mut stack_value: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0))); return_on_pagefault!(safe_write16(addr, stack_value)); - adjust_stack_reg(2i32); + adjust_stack_reg(2); }, } } #[no_mangle] pub unsafe fn instr16_8F_0_mem_jit(addr: i32) { - adjust_stack_reg(-2i32); - let mut stack_value: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0i32))); + adjust_stack_reg(-2); + let mut stack_value: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0))); return_on_pagefault!(safe_write16(addr, stack_value)); - adjust_stack_reg(2i32); + adjust_stack_reg(2); } #[no_mangle] @@ -1640,27 +1631,27 @@ pub unsafe fn instr16_8F_0_reg(mut r: i32) { write_reg16(r, return_on_pagefault! #[no_mangle] pub unsafe fn instr32_8F_0_mem(modrm_byte: i32) { // Update esp *before* resolving the address - adjust_stack_reg(4i32); + adjust_stack_reg(4); match modrm_resolve(modrm_byte) { Err(()) => { // a pagefault happened, reset esp - adjust_stack_reg(-4i32); + adjust_stack_reg(-4); }, Ok(addr) => { - adjust_stack_reg(-4i32); - let mut stack_value: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))); + adjust_stack_reg(-4); + let mut stack_value: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0))); return_on_pagefault!(safe_write32(addr, stack_value)); - adjust_stack_reg(4i32); + adjust_stack_reg(4); }, } } #[no_mangle] pub unsafe fn instr32_8F_0_mem_jit(addr: i32) { - adjust_stack_reg(-4i32); - let mut stack_value: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))); + adjust_stack_reg(-4); + let mut stack_value: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0))); return_on_pagefault!(safe_write32(addr, stack_value)); - adjust_stack_reg(4i32); + adjust_stack_reg(4); } #[no_mangle] @@ -1702,25 +1693,25 @@ pub unsafe fn instr16_98() { *reg16.offset(AX as isize) = *reg8s.offset(AL as is pub unsafe fn instr32_98() { *reg32s.offset(EAX as isize) = *reg16s.offset(AX as isize) as i32; } #[no_mangle] pub unsafe fn instr16_99() { - *reg16.offset(DX as isize) = (*reg16s.offset(AX as isize) as i32 >> 15i32) as u16; + *reg16.offset(DX as isize) = (*reg16s.offset(AX as isize) as i32 >> 15) as u16; } #[no_mangle] -pub unsafe fn instr32_99() { *reg32s.offset(EDX as isize) = *reg32s.offset(EAX as isize) >> 31i32; } +pub unsafe fn instr32_99() { *reg32s.offset(EDX as isize) = *reg32s.offset(EAX as isize) >> 31; } #[no_mangle] pub unsafe fn instr16_9A(mut new_ip: i32, mut new_cs: i32) { // callf far_jump(new_ip, new_cs, true); - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] pub unsafe fn instr32_9A(mut new_ip: i32, mut new_cs: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { - if 0 != new_ip as u32 & 4294901760u32 { - dbg_assert!(0 != 0i32); + if 0 != new_ip as u32 & 4294901760 { + dbg_assert!(0 != 0); } } far_jump(new_ip, new_cs, true); - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] pub unsafe fn instr_9B() { @@ -1737,10 +1728,10 @@ pub unsafe fn instr_9B() { #[no_mangle] pub unsafe fn instr16_9C() { // pushf - if 0 != *flags & FLAG_VM && getiopl() < 3i32 { + if 0 != *flags & FLAG_VM && getiopl() < 3 { dbg_assert!(*protected_mode); dbg_log!("pushf #gp"); - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); } else { return_on_pagefault!(push16(get_eflags())); @@ -1749,29 +1740,29 @@ pub unsafe fn instr16_9C() { #[no_mangle] pub unsafe fn instr32_9C() { // pushf - if 0 != *flags & FLAG_VM && getiopl() < 3i32 { + if 0 != *flags & FLAG_VM && getiopl() < 3 { // trap to virtual 8086 monitor dbg_assert!(*protected_mode); dbg_log!("pushf #gp"); - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); } else { // vm and rf flag are cleared in image stored on the stack - return_on_pagefault!(push32(get_eflags() & 16580607i32)); + return_on_pagefault!(push32(get_eflags() & 16580607)); }; } #[no_mangle] pub unsafe fn instr16_9D() { // popf - if 0 != *flags & FLAG_VM && getiopl() < 3i32 { + if 0 != *flags & FLAG_VM && getiopl() < 3 { dbg_log!("popf #gp"); - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); return; } else { - update_eflags(*flags.offset(0isize) & !65535i32 | return_on_pagefault!(pop16())); - if 0 != *flags.offset(0isize) & FLAG_TRAP { - let ref mut fresh0 = *flags.offset(0isize); + update_eflags(*flags.offset(0) & !65535 | return_on_pagefault!(pop16())); + if 0 != *flags.offset(0) & FLAG_TRAP { + let ref mut fresh0 = *flags.offset(0); *fresh0 &= !FLAG_TRAP } else { @@ -1783,9 +1774,9 @@ pub unsafe fn instr16_9D() { #[no_mangle] pub unsafe fn instr32_9D() { // popf - if 0 != *flags & FLAG_VM && getiopl() < 3i32 { + if 0 != *flags & FLAG_VM && getiopl() < 3 { dbg_log!("popf #gp"); - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); return; } else { @@ -1797,9 +1788,9 @@ pub unsafe fn instr32_9D() { #[no_mangle] pub unsafe fn instr_9E() { // sahf - *flags = *flags & !255i32 | *reg8.offset(AH as isize) as i32; + *flags = *flags & !255 | *reg8.offset(AH as isize) as i32; *flags = *flags & FLAGS_MASK | FLAGS_DEFAULT; - *flags_changed &= !255i32; + *flags_changed &= !255; } #[no_mangle] pub unsafe fn instr_9F() { @@ -1932,226 +1923,226 @@ pub unsafe fn instr16_BF(mut imm: i32) { *reg16.offset(DI as isize) = imm as u16 pub unsafe fn instr32_BF(mut imm: i32) { *reg32s.offset(EDI as isize) = imm; } #[no_mangle] pub unsafe fn instr_C0_0_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE8!(___, addr, rol8(___, imm & 31i32)); + SAFE_READ_WRITE8!(___, addr, rol8(___, imm & 31)); } #[no_mangle] pub unsafe fn instr_C0_0_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, rol8(____0, imm & 31i32)); + write_reg8(r1, rol8(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr_C0_1_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE8!(___, addr, ror8(___, imm & 31i32)); + SAFE_READ_WRITE8!(___, addr, ror8(___, imm & 31)); } #[no_mangle] pub unsafe fn instr_C0_1_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, ror8(____0, imm & 31i32)); + write_reg8(r1, ror8(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr_C0_2_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE8!(___, addr, rcl8(___, imm & 31i32)); + SAFE_READ_WRITE8!(___, addr, rcl8(___, imm & 31)); } #[no_mangle] pub unsafe fn instr_C0_2_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, rcl8(____0, imm & 31i32)); + write_reg8(r1, rcl8(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr_C0_3_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE8!(___, addr, rcr8(___, imm & 31i32)); + SAFE_READ_WRITE8!(___, addr, rcr8(___, imm & 31)); } #[no_mangle] pub unsafe fn instr_C0_3_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, rcr8(____0, imm & 31i32)); + write_reg8(r1, rcr8(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr_C0_4_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE8!(___, addr, shl8(___, imm & 31i32)); + SAFE_READ_WRITE8!(___, addr, shl8(___, imm & 31)); } #[no_mangle] pub unsafe fn instr_C0_4_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, shl8(____0, imm & 31i32)); + write_reg8(r1, shl8(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr_C0_5_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE8!(___, addr, shr8(___, imm & 31i32)); + SAFE_READ_WRITE8!(___, addr, shr8(___, imm & 31)); } #[no_mangle] pub unsafe fn instr_C0_5_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, shr8(____0, imm & 31i32)); + write_reg8(r1, shr8(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr_C0_6_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE8!(___, addr, shl8(___, imm & 31i32)); + SAFE_READ_WRITE8!(___, addr, shl8(___, imm & 31)); } #[no_mangle] pub unsafe fn instr_C0_6_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, shl8(____0, imm & 31i32)); + write_reg8(r1, shl8(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr_C0_7_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE8!(___, addr, sar8(___, imm & 31i32)); + SAFE_READ_WRITE8!(___, addr, sar8(___, imm & 31)); } #[no_mangle] pub unsafe fn instr_C0_7_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, sar8(____0, imm & 31i32)); + write_reg8(r1, sar8(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr16_C1_0_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE16!(___, addr, rol16(___, imm & 31i32)); + SAFE_READ_WRITE16!(___, addr, rol16(___, imm & 31)); } #[no_mangle] pub unsafe fn instr16_C1_0_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, rol16(____0, imm & 31i32)); + write_reg16(r1, rol16(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr16_C1_1_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE16!(___, addr, ror16(___, imm & 31i32)); + SAFE_READ_WRITE16!(___, addr, ror16(___, imm & 31)); } #[no_mangle] pub unsafe fn instr16_C1_1_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, ror16(____0, imm & 31i32)); + write_reg16(r1, ror16(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr16_C1_2_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE16!(___, addr, rcl16(___, imm & 31i32)); + SAFE_READ_WRITE16!(___, addr, rcl16(___, imm & 31)); } #[no_mangle] pub unsafe fn instr16_C1_2_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, rcl16(____0, imm & 31i32)); + write_reg16(r1, rcl16(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr16_C1_3_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE16!(___, addr, rcr16(___, imm & 31i32)); + SAFE_READ_WRITE16!(___, addr, rcr16(___, imm & 31)); } #[no_mangle] pub unsafe fn instr16_C1_3_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, rcr16(____0, imm & 31i32)); + write_reg16(r1, rcr16(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr16_C1_4_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE16!(___, addr, shl16(___, imm & 31i32)); + SAFE_READ_WRITE16!(___, addr, shl16(___, imm & 31)); } #[no_mangle] pub unsafe fn instr16_C1_4_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, shl16(____0, imm & 31i32)); + write_reg16(r1, shl16(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr16_C1_5_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE16!(___, addr, shr16(___, imm & 31i32)); + SAFE_READ_WRITE16!(___, addr, shr16(___, imm & 31)); } #[no_mangle] pub unsafe fn instr16_C1_5_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, shr16(____0, imm & 31i32)); + write_reg16(r1, shr16(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr16_C1_6_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE16!(___, addr, shl16(___, imm & 31i32)); + SAFE_READ_WRITE16!(___, addr, shl16(___, imm & 31)); } #[no_mangle] pub unsafe fn instr16_C1_6_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, shl16(____0, imm & 31i32)); + write_reg16(r1, shl16(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr16_C1_7_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE16!(___, addr, sar16(___, imm & 31i32)); + SAFE_READ_WRITE16!(___, addr, sar16(___, imm & 31)); } #[no_mangle] pub unsafe fn instr16_C1_7_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, sar16(____0, imm & 31i32)); + write_reg16(r1, sar16(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr32_C1_0_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE32!(___, addr, rol32(___, imm & 31i32)); + SAFE_READ_WRITE32!(___, addr, rol32(___, imm & 31)); } #[no_mangle] pub unsafe fn instr32_C1_0_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, rol32(____0, imm & 31i32)); + write_reg32(r1, rol32(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr32_C1_1_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE32!(___, addr, ror32(___, imm & 31i32)); + SAFE_READ_WRITE32!(___, addr, ror32(___, imm & 31)); } #[no_mangle] pub unsafe fn instr32_C1_1_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, ror32(____0, imm & 31i32)); + write_reg32(r1, ror32(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr32_C1_2_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE32!(___, addr, rcl32(___, imm & 31i32)); + SAFE_READ_WRITE32!(___, addr, rcl32(___, imm & 31)); } #[no_mangle] pub unsafe fn instr32_C1_2_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, rcl32(____0, imm & 31i32)); + write_reg32(r1, rcl32(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr32_C1_3_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE32!(___, addr, rcr32(___, imm & 31i32)); + SAFE_READ_WRITE32!(___, addr, rcr32(___, imm & 31)); } #[no_mangle] pub unsafe fn instr32_C1_3_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, rcr32(____0, imm & 31i32)); + write_reg32(r1, rcr32(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr32_C1_4_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE32!(___, addr, shl32(___, imm & 31i32)); + SAFE_READ_WRITE32!(___, addr, shl32(___, imm & 31)); } #[no_mangle] pub unsafe fn instr32_C1_4_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, shl32(____0, imm & 31i32)); + write_reg32(r1, shl32(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr32_C1_5_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE32!(___, addr, shr32(___, imm & 31i32)); + SAFE_READ_WRITE32!(___, addr, shr32(___, imm & 31)); } #[no_mangle] pub unsafe fn instr32_C1_5_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, shr32(____0, imm & 31i32)); + write_reg32(r1, shr32(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr32_C1_6_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE32!(___, addr, shl32(___, imm & 31i32)); + SAFE_READ_WRITE32!(___, addr, shl32(___, imm & 31)); } #[no_mangle] pub unsafe fn instr32_C1_6_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, shl32(____0, imm & 31i32)); + write_reg32(r1, shl32(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr32_C1_7_mem(mut addr: i32, mut imm: i32) { - SAFE_READ_WRITE32!(___, addr, sar32(___, imm & 31i32)); + SAFE_READ_WRITE32!(___, addr, sar32(___, imm & 31)); } #[no_mangle] pub unsafe fn instr32_C1_7_reg(mut r1: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, sar32(____0, imm & 31i32)); + write_reg32(r1, sar32(____0, imm & 31)); } #[no_mangle] pub unsafe fn instr16_C2(mut imm16: i32) { // retn let mut cs: i32 = get_seg_cs(); *instruction_pointer = cs + return_on_pagefault!(pop16()); - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); adjust_stack_reg(imm16); } #[no_mangle] @@ -2159,7 +2150,7 @@ pub unsafe fn instr32_C2(mut imm16: i32) { // retn let mut cs: i32 = get_seg_cs(); let mut ip: i32 = return_on_pagefault!(pop32s()); - dbg_assert!(0 != is_asize_32() as i32 || ip < 65536i32); + dbg_assert!(0 != is_asize_32() as i32 || ip < 65536); *instruction_pointer = cs + ip; adjust_stack_reg(imm16); } @@ -2174,7 +2165,7 @@ pub unsafe fn instr32_C3() { // retn let mut cs: i32 = get_seg_cs(); let mut ip: i32 = return_on_pagefault!(pop32s()); - dbg_assert!(0 != is_asize_32() as i32 || ip < 65536i32); + dbg_assert!(0 != is_asize_32() as i32 || ip < 65536); *instruction_pointer = cs + ip; } #[no_mangle] @@ -2225,7 +2216,7 @@ pub unsafe fn instr16_C9() { *reg16.offset(BP as isize) as i32 }; let mut new_bp: i32 = return_on_pagefault!(safe_read16(get_seg_ss() + old_vbp)); - set_stack_reg(old_vbp + 2i32); + set_stack_reg(old_vbp + 2); *reg16.offset(BP as isize) = new_bp as u16; } #[no_mangle] @@ -2237,51 +2228,51 @@ pub unsafe fn instr32_C9() { *reg16.offset(BP as isize) as i32 }; let mut new_ebp: i32 = return_on_pagefault!(safe_read32s(get_seg_ss() + old_vbp)); - set_stack_reg(old_vbp + 4i32); + set_stack_reg(old_vbp + 4); *reg32s.offset(EBP as isize) = new_ebp; } #[no_mangle] pub unsafe fn instr16_CA(mut imm16: i32) { // retf - let mut ip: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0i32))); - let mut cs: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(2i32))); + let mut ip: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0))); + let mut cs: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(2))); far_return(ip, cs, imm16); } #[no_mangle] pub unsafe fn instr32_CA(mut imm16: i32) { // retf - let mut ip: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))); - let mut cs: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(4i32))) & 65535i32; + let mut ip: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0))); + let mut cs: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(4))) & 65535; far_return(ip, cs, imm16); - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] pub unsafe fn instr16_CB() { // retf - let mut ip: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0i32))); - let mut cs: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(2i32))); - far_return(ip, cs, 0i32); - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); + let mut ip: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0))); + let mut cs: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(2))); + far_return(ip, cs, 0); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] pub unsafe fn instr32_CB() { // retf - let mut ip: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))); - let mut cs: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(4i32))) & 65535i32; - far_return(ip, cs, 0i32); - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); + let mut ip: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0))); + let mut cs: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(4))) & 65535; + far_return(ip, cs, 0); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] pub unsafe fn instr_CC() { // INT3 // TODO: inhibit iopl checks dbg_log!("INT3"); - call_interrupt_vector(3i32, 0 != 1i32, 0 != 0i32, 0i32); + call_interrupt_vector(3, 0 != 1, 0 != 0, 0); } #[no_mangle] pub unsafe fn instr_CD(mut imm8: i32) { // INT - call_interrupt_vector(imm8, 0 != 1i32, 0 != 0i32, 0i32); + call_interrupt_vector(imm8, 0 != 1, 0 != 0, 0); } #[no_mangle] pub unsafe fn instr_CE() { @@ -2289,7 +2280,7 @@ pub unsafe fn instr_CE() { dbg_log!("INTO"); if getof() { // TODO: inhibit iopl checks - call_interrupt_vector(CPU_EXCEPTION_OF, 0 != 1i32, 0 != 0i32, 0i32); + call_interrupt_vector(CPU_EXCEPTION_OF, 0 != 1, 0 != 0, 0); }; } #[no_mangle] @@ -2301,531 +2292,435 @@ pub unsafe fn instr16_CF() { pub unsafe fn instr32_CF() { iret32(); } #[no_mangle] pub unsafe fn instr_D0_0_mem(mut addr: i32) { - SAFE_READ_WRITE8!(___, addr, rol8(___, 1i32)); + SAFE_READ_WRITE8!(___, addr, rol8(___, 1)); } #[no_mangle] pub unsafe fn instr_D0_0_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, rol8(____0, 1i32)); + write_reg8(r1, rol8(____0, 1)); } #[no_mangle] pub unsafe fn instr_D0_1_mem(mut addr: i32) { - SAFE_READ_WRITE8!(___, addr, ror8(___, 1i32)); + SAFE_READ_WRITE8!(___, addr, ror8(___, 1)); } #[no_mangle] pub unsafe fn instr_D0_1_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, ror8(____0, 1i32)); + write_reg8(r1, ror8(____0, 1)); } #[no_mangle] pub unsafe fn instr_D0_2_mem(mut addr: i32) { - SAFE_READ_WRITE8!(___, addr, rcl8(___, 1i32)); + SAFE_READ_WRITE8!(___, addr, rcl8(___, 1)); } #[no_mangle] pub unsafe fn instr_D0_2_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, rcl8(____0, 1i32)); + write_reg8(r1, rcl8(____0, 1)); } #[no_mangle] pub unsafe fn instr_D0_3_mem(mut addr: i32) { - SAFE_READ_WRITE8!(___, addr, rcr8(___, 1i32)); + SAFE_READ_WRITE8!(___, addr, rcr8(___, 1)); } #[no_mangle] pub unsafe fn instr_D0_3_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, rcr8(____0, 1i32)); + write_reg8(r1, rcr8(____0, 1)); } #[no_mangle] pub unsafe fn instr_D0_4_mem(mut addr: i32) { - SAFE_READ_WRITE8!(___, addr, shl8(___, 1i32)); + SAFE_READ_WRITE8!(___, addr, shl8(___, 1)); } #[no_mangle] pub unsafe fn instr_D0_4_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, shl8(____0, 1i32)); + write_reg8(r1, shl8(____0, 1)); } #[no_mangle] pub unsafe fn instr_D0_5_mem(mut addr: i32) { - SAFE_READ_WRITE8!(___, addr, shr8(___, 1i32)); + SAFE_READ_WRITE8!(___, addr, shr8(___, 1)); } #[no_mangle] pub unsafe fn instr_D0_5_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, shr8(____0, 1i32)); + write_reg8(r1, shr8(____0, 1)); } #[no_mangle] pub unsafe fn instr_D0_6_mem(mut addr: i32) { - SAFE_READ_WRITE8!(___, addr, shl8(___, 1i32)); + SAFE_READ_WRITE8!(___, addr, shl8(___, 1)); } #[no_mangle] pub unsafe fn instr_D0_6_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, shl8(____0, 1i32)); + write_reg8(r1, shl8(____0, 1)); } #[no_mangle] pub unsafe fn instr_D0_7_mem(mut addr: i32) { - SAFE_READ_WRITE8!(___, addr, sar8(___, 1i32)); + SAFE_READ_WRITE8!(___, addr, sar8(___, 1)); } #[no_mangle] pub unsafe fn instr_D0_7_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, sar8(____0, 1i32)); + write_reg8(r1, sar8(____0, 1)); } #[no_mangle] pub unsafe fn instr16_D1_0_mem(mut addr: i32) { - SAFE_READ_WRITE16!(___, addr, rol16(___, 1i32)); + SAFE_READ_WRITE16!(___, addr, rol16(___, 1)); } #[no_mangle] pub unsafe fn instr16_D1_0_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, rol16(____0, 1i32)); + write_reg16(r1, rol16(____0, 1)); } #[no_mangle] pub unsafe fn instr16_D1_1_mem(mut addr: i32) { - SAFE_READ_WRITE16!(___, addr, ror16(___, 1i32)); + SAFE_READ_WRITE16!(___, addr, ror16(___, 1)); } #[no_mangle] pub unsafe fn instr16_D1_1_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, ror16(____0, 1i32)); + write_reg16(r1, ror16(____0, 1)); } #[no_mangle] pub unsafe fn instr16_D1_2_mem(mut addr: i32) { - SAFE_READ_WRITE16!(___, addr, rcl16(___, 1i32)); + SAFE_READ_WRITE16!(___, addr, rcl16(___, 1)); } #[no_mangle] pub unsafe fn instr16_D1_2_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, rcl16(____0, 1i32)); + write_reg16(r1, rcl16(____0, 1)); } #[no_mangle] pub unsafe fn instr16_D1_3_mem(mut addr: i32) { - SAFE_READ_WRITE16!(___, addr, rcr16(___, 1i32)); + SAFE_READ_WRITE16!(___, addr, rcr16(___, 1)); } #[no_mangle] pub unsafe fn instr16_D1_3_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, rcr16(____0, 1i32)); + write_reg16(r1, rcr16(____0, 1)); } #[no_mangle] pub unsafe fn instr16_D1_4_mem(mut addr: i32) { - SAFE_READ_WRITE16!(___, addr, shl16(___, 1i32)); + SAFE_READ_WRITE16!(___, addr, shl16(___, 1)); } #[no_mangle] pub unsafe fn instr16_D1_4_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, shl16(____0, 1i32)); + write_reg16(r1, shl16(____0, 1)); } #[no_mangle] pub unsafe fn instr16_D1_5_mem(mut addr: i32) { - SAFE_READ_WRITE16!(___, addr, shr16(___, 1i32)); + SAFE_READ_WRITE16!(___, addr, shr16(___, 1)); } #[no_mangle] pub unsafe fn instr16_D1_5_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, shr16(____0, 1i32)); + write_reg16(r1, shr16(____0, 1)); } #[no_mangle] pub unsafe fn instr16_D1_6_mem(mut addr: i32) { - SAFE_READ_WRITE16!(___, addr, shl16(___, 1i32)); + SAFE_READ_WRITE16!(___, addr, shl16(___, 1)); } #[no_mangle] pub unsafe fn instr16_D1_6_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, shl16(____0, 1i32)); + write_reg16(r1, shl16(____0, 1)); } #[no_mangle] pub unsafe fn instr16_D1_7_mem(mut addr: i32) { - SAFE_READ_WRITE16!(___, addr, sar16(___, 1i32)); + SAFE_READ_WRITE16!(___, addr, sar16(___, 1)); } #[no_mangle] pub unsafe fn instr16_D1_7_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, sar16(____0, 1i32)); + write_reg16(r1, sar16(____0, 1)); } #[no_mangle] pub unsafe fn instr32_D1_0_mem(mut addr: i32) { - SAFE_READ_WRITE32!(___, addr, rol32(___, 1i32)); + SAFE_READ_WRITE32!(___, addr, rol32(___, 1)); } #[no_mangle] pub unsafe fn instr32_D1_0_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, rol32(____0, 1i32)); + write_reg32(r1, rol32(____0, 1)); } #[no_mangle] pub unsafe fn instr32_D1_1_mem(mut addr: i32) { - SAFE_READ_WRITE32!(___, addr, ror32(___, 1i32)); + SAFE_READ_WRITE32!(___, addr, ror32(___, 1)); } #[no_mangle] pub unsafe fn instr32_D1_1_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, ror32(____0, 1i32)); + write_reg32(r1, ror32(____0, 1)); } #[no_mangle] pub unsafe fn instr32_D1_2_mem(mut addr: i32) { - SAFE_READ_WRITE32!(___, addr, rcl32(___, 1i32)); + SAFE_READ_WRITE32!(___, addr, rcl32(___, 1)); } #[no_mangle] pub unsafe fn instr32_D1_2_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, rcl32(____0, 1i32)); + write_reg32(r1, rcl32(____0, 1)); } #[no_mangle] pub unsafe fn instr32_D1_3_mem(mut addr: i32) { - SAFE_READ_WRITE32!(___, addr, rcr32(___, 1i32)); + SAFE_READ_WRITE32!(___, addr, rcr32(___, 1)); } #[no_mangle] pub unsafe fn instr32_D1_3_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, rcr32(____0, 1i32)); + write_reg32(r1, rcr32(____0, 1)); } #[no_mangle] pub unsafe fn instr32_D1_4_mem(mut addr: i32) { - SAFE_READ_WRITE32!(___, addr, shl32(___, 1i32)); + SAFE_READ_WRITE32!(___, addr, shl32(___, 1)); } #[no_mangle] pub unsafe fn instr32_D1_4_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, shl32(____0, 1i32)); + write_reg32(r1, shl32(____0, 1)); } #[no_mangle] pub unsafe fn instr32_D1_5_mem(mut addr: i32) { - SAFE_READ_WRITE32!(___, addr, shr32(___, 1i32)); + SAFE_READ_WRITE32!(___, addr, shr32(___, 1)); } #[no_mangle] pub unsafe fn instr32_D1_5_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, shr32(____0, 1i32)); + write_reg32(r1, shr32(____0, 1)); } #[no_mangle] pub unsafe fn instr32_D1_6_mem(mut addr: i32) { - SAFE_READ_WRITE32!(___, addr, shl32(___, 1i32)); + SAFE_READ_WRITE32!(___, addr, shl32(___, 1)); } #[no_mangle] pub unsafe fn instr32_D1_6_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, shl32(____0, 1i32)); + write_reg32(r1, shl32(____0, 1)); } #[no_mangle] pub unsafe fn instr32_D1_7_mem(mut addr: i32) { - SAFE_READ_WRITE32!(___, addr, sar32(___, 1i32)); + SAFE_READ_WRITE32!(___, addr, sar32(___, 1)); } #[no_mangle] pub unsafe fn instr32_D1_7_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, sar32(____0, 1i32)); + write_reg32(r1, sar32(____0, 1)); } #[no_mangle] pub unsafe fn instr_D2_0_mem(mut addr: i32) { - SAFE_READ_WRITE8!( - ___, - addr, - rol8(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE8!(___, addr, rol8(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr_D2_0_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, rol8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg8(r1, rol8(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr_D2_1_mem(mut addr: i32) { - SAFE_READ_WRITE8!( - ___, - addr, - ror8(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE8!(___, addr, ror8(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr_D2_1_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, ror8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg8(r1, ror8(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr_D2_2_mem(mut addr: i32) { - SAFE_READ_WRITE8!( - ___, - addr, - rcl8(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE8!(___, addr, rcl8(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr_D2_2_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, rcl8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg8(r1, rcl8(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr_D2_3_mem(mut addr: i32) { - SAFE_READ_WRITE8!( - ___, - addr, - rcr8(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE8!(___, addr, rcr8(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr_D2_3_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, rcr8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg8(r1, rcr8(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr_D2_4_mem(mut addr: i32) { - SAFE_READ_WRITE8!( - ___, - addr, - shl8(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE8!(___, addr, shl8(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr_D2_4_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, shl8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg8(r1, shl8(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr_D2_5_mem(mut addr: i32) { - SAFE_READ_WRITE8!( - ___, - addr, - shr8(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE8!(___, addr, shr8(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr_D2_5_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, shr8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg8(r1, shr8(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr_D2_6_mem(mut addr: i32) { - SAFE_READ_WRITE8!( - ___, - addr, - shl8(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE8!(___, addr, shl8(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr_D2_6_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, shl8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg8(r1, shl8(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr_D2_7_mem(mut addr: i32) { - SAFE_READ_WRITE8!( - ___, - addr, - sar8(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE8!(___, addr, sar8(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr_D2_7_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg8(r1, sar8(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg8(r1, sar8(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr16_D3_0_mem(mut addr: i32) { - SAFE_READ_WRITE16!( - ___, - addr, - rol16(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE16!(___, addr, rol16(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr16_D3_0_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, rol16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg16(r1, rol16(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr16_D3_1_mem(mut addr: i32) { - SAFE_READ_WRITE16!( - ___, - addr, - ror16(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE16!(___, addr, ror16(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr16_D3_1_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, ror16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg16(r1, ror16(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr16_D3_2_mem(mut addr: i32) { - SAFE_READ_WRITE16!( - ___, - addr, - rcl16(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE16!(___, addr, rcl16(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr16_D3_2_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, rcl16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg16(r1, rcl16(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr16_D3_3_mem(mut addr: i32) { - SAFE_READ_WRITE16!( - ___, - addr, - rcr16(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE16!(___, addr, rcr16(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr16_D3_3_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, rcr16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg16(r1, rcr16(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr16_D3_4_mem(mut addr: i32) { - SAFE_READ_WRITE16!( - ___, - addr, - shl16(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE16!(___, addr, shl16(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr16_D3_4_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, shl16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg16(r1, shl16(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr16_D3_5_mem(mut addr: i32) { - SAFE_READ_WRITE16!( - ___, - addr, - shr16(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE16!(___, addr, shr16(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr16_D3_5_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, shr16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg16(r1, shr16(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr16_D3_6_mem(mut addr: i32) { - SAFE_READ_WRITE16!( - ___, - addr, - shl16(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE16!(___, addr, shl16(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr16_D3_6_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, shl16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg16(r1, shl16(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr16_D3_7_mem(mut addr: i32) { - SAFE_READ_WRITE16!( - ___, - addr, - sar16(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE16!(___, addr, sar16(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr16_D3_7_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, sar16(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg16(r1, sar16(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr32_D3_0_mem(mut addr: i32) { - SAFE_READ_WRITE32!( - ___, - addr, - rol32(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE32!(___, addr, rol32(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr32_D3_0_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, rol32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg32(r1, rol32(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr32_D3_1_mem(mut addr: i32) { - SAFE_READ_WRITE32!( - ___, - addr, - ror32(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE32!(___, addr, ror32(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr32_D3_1_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, ror32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg32(r1, ror32(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr32_D3_2_mem(mut addr: i32) { - SAFE_READ_WRITE32!( - ___, - addr, - rcl32(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE32!(___, addr, rcl32(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr32_D3_2_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, rcl32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg32(r1, rcl32(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr32_D3_3_mem(mut addr: i32) { - SAFE_READ_WRITE32!( - ___, - addr, - rcr32(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE32!(___, addr, rcr32(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr32_D3_3_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, rcr32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg32(r1, rcr32(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr32_D3_4_mem(mut addr: i32) { - SAFE_READ_WRITE32!( - ___, - addr, - shl32(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE32!(___, addr, shl32(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr32_D3_4_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, shl32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg32(r1, shl32(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr32_D3_5_mem(mut addr: i32) { - SAFE_READ_WRITE32!( - ___, - addr, - shr32(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE32!(___, addr, shr32(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr32_D3_5_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, shr32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg32(r1, shr32(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr32_D3_6_mem(mut addr: i32) { - SAFE_READ_WRITE32!( - ___, - addr, - shl32(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE32!(___, addr, shl32(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr32_D3_6_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, shl32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg32(r1, shl32(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr32_D3_7_mem(mut addr: i32) { - SAFE_READ_WRITE32!( - ___, - addr, - sar32(___, *reg8.offset(CL as isize) as i32 & 31i32) - ); + SAFE_READ_WRITE32!(___, addr, sar32(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr32_D3_7_reg(mut r1: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, sar32(____0, *reg8.offset(CL as isize) as i32 & 31i32)); + write_reg32(r1, sar32(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] pub unsafe fn instr_D4(mut arg: i32) { bcd_aam(arg); } @@ -2847,13 +2742,13 @@ pub unsafe fn instr_D7() { else { *reg8.offset(AL as isize) = return_on_pagefault!(safe_read8( get_seg_prefix(DS) - + (*reg16.offset(BX as isize) as i32 + *reg8.offset(AL as isize) as i32 & 65535i32), + + (*reg16.offset(BX as isize) as i32 + *reg8.offset(AL as isize) as i32 & 65535), )) as u8 }; } #[no_mangle] pub unsafe fn instr_E4(mut port: i32) { - if !test_privileges_for_io(port, 1i32) { + if !test_privileges_for_io(port, 1) { return; } else { @@ -2863,7 +2758,7 @@ pub unsafe fn instr_E4(mut port: i32) { } #[no_mangle] pub unsafe fn instr16_E5(mut port: i32) { - if !test_privileges_for_io(port, 2i32) { + if !test_privileges_for_io(port, 2) { return; } else { @@ -2873,7 +2768,7 @@ pub unsafe fn instr16_E5(mut port: i32) { } #[no_mangle] pub unsafe fn instr32_E5(mut port: i32) { - if !test_privileges_for_io(port, 4i32) { + if !test_privileges_for_io(port, 4) { return; } else { @@ -2883,7 +2778,7 @@ pub unsafe fn instr32_E5(mut port: i32) { } #[no_mangle] pub unsafe fn instr_E6(mut port: i32) { - if !test_privileges_for_io(port, 1i32) { + if !test_privileges_for_io(port, 1) { return; } else { @@ -2893,7 +2788,7 @@ pub unsafe fn instr_E6(mut port: i32) { } #[no_mangle] pub unsafe fn instr16_E7(mut port: i32) { - if !test_privileges_for_io(port, 2i32) { + if !test_privileges_for_io(port, 2) { return; } else { @@ -2903,7 +2798,7 @@ pub unsafe fn instr16_E7(mut port: i32) { } #[no_mangle] pub unsafe fn instr32_E7(mut port: i32) { - if !test_privileges_for_io(port, 4i32) { + if !test_privileges_for_io(port, 4) { return; } else { @@ -2933,24 +2828,24 @@ pub unsafe fn instr16_E9(mut imm16: i32) { pub unsafe fn instr32_E9(mut imm32s: i32) { // jmp *instruction_pointer = *instruction_pointer + imm32s; - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] pub unsafe fn instr16_EA(mut new_ip: i32, mut cs: i32) { // jmpf far_jump(new_ip, cs, false); - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] pub unsafe fn instr32_EA(mut new_ip: i32, mut cs: i32) { // jmpf far_jump(new_ip, cs, false); - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] pub unsafe fn instr_EC() { let mut port: i32 = *reg16.offset(DX as isize) as i32; - if !test_privileges_for_io(port, 1i32) { + if !test_privileges_for_io(port, 1) { return; } else { @@ -2961,7 +2856,7 @@ pub unsafe fn instr_EC() { #[no_mangle] pub unsafe fn instr16_ED() { let mut port: i32 = *reg16.offset(DX as isize) as i32; - if !test_privileges_for_io(port, 2i32) { + if !test_privileges_for_io(port, 2) { return; } else { @@ -2972,7 +2867,7 @@ pub unsafe fn instr16_ED() { #[no_mangle] pub unsafe fn instr32_ED() { let mut port: i32 = *reg16.offset(DX as isize) as i32; - if !test_privileges_for_io(port, 4i32) { + if !test_privileges_for_io(port, 4) { return; } else { @@ -2983,7 +2878,7 @@ pub unsafe fn instr32_ED() { #[no_mangle] pub unsafe fn instr_EE() { let mut port: i32 = *reg16.offset(DX as isize) as i32; - if !test_privileges_for_io(port, 1i32) { + if !test_privileges_for_io(port, 1) { return; } else { @@ -2994,7 +2889,7 @@ pub unsafe fn instr_EE() { #[no_mangle] pub unsafe fn instr16_EF() { let mut port: i32 = *reg16.offset(DX as isize) as i32; - if !test_privileges_for_io(port, 2i32) { + if !test_privileges_for_io(port, 2) { return; } else { @@ -3005,7 +2900,7 @@ pub unsafe fn instr16_EF() { #[no_mangle] pub unsafe fn instr32_EF() { let mut port: i32 = *reg16.offset(DX as isize) as i32; - if !test_privileges_for_io(port, 4i32) { + if !test_privileges_for_io(port, 4) { return; } else { @@ -3016,7 +2911,7 @@ pub unsafe fn instr32_EF() { #[no_mangle] pub unsafe fn instr_F0() { // lock - if 0 != 0i32 * 0i32 { + if 0 != 0 * 0 { dbg_log!("lock"); } // TODO @@ -3028,31 +2923,31 @@ pub unsafe fn instr_F0() { pub unsafe fn instr_F1() { // INT1 // https://code.google.com/p/corkami/wiki/x86oddities#IceBP - dbg_assert!(0 != 0i32); + dbg_assert!(0 != 0); } #[no_mangle] pub unsafe fn instr_F2() { // repnz - dbg_assert!(*prefixes as i32 & PREFIX_MASK_REP == 0i32); + dbg_assert!(*prefixes as i32 & PREFIX_MASK_REP == 0); *prefixes = (*prefixes as i32 | PREFIX_REPNZ) as u8; run_prefix_instruction(); - *prefixes = 0i32 as u8; + *prefixes = 0 as u8; } #[no_mangle] pub unsafe fn instr_F3() { // repz - dbg_assert!(*prefixes as i32 & PREFIX_MASK_REP == 0i32); + dbg_assert!(*prefixes as i32 & PREFIX_MASK_REP == 0); *prefixes = (*prefixes as i32 | PREFIX_REPZ) as u8; run_prefix_instruction(); - *prefixes = 0i32 as u8; + *prefixes = 0 as u8; } #[no_mangle] pub unsafe fn instr_F4() { hlt_op(); } #[no_mangle] pub unsafe fn instr_F5() { // cmc - *flags = (*flags | 1i32) ^ getcf() as i32; - *flags_changed &= !1i32; + *flags = (*flags | 1) ^ getcf() as i32; + *flags_changed &= !1; } #[no_mangle] pub unsafe fn instr_F6_0_mem(mut addr: i32, mut imm: i32) { @@ -3105,12 +3000,12 @@ pub unsafe fn instr_F6_4_reg(mut r1: i32) { #[no_mangle] pub unsafe fn instr_F6_5_mem(mut addr: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); - imul8(____0 << 24i32 >> 24i32); + imul8(____0 << 24 >> 24); } #[no_mangle] pub unsafe fn instr_F6_5_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); - imul8(____0 << 24i32 >> 24i32); + imul8(____0 << 24 >> 24); } #[no_mangle] pub unsafe fn instr_F6_6_mem(mut addr: i32) { @@ -3125,12 +3020,12 @@ pub unsafe fn instr_F6_6_reg(mut r1: i32) { #[no_mangle] pub unsafe fn instr_F6_7_mem(mut addr: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); - idiv8(____0 << 24i32 >> 24i32); + idiv8(____0 << 24 >> 24); } #[no_mangle] pub unsafe fn instr_F6_7_reg(mut r1: i32) { let mut ____0: i32 = read_reg8(r1); - idiv8(____0 << 24i32 >> 24i32); + idiv8(____0 << 24 >> 24); } #[no_mangle] pub unsafe fn instr16_F7_0_mem(mut addr: i32, mut imm: i32) { @@ -3183,12 +3078,12 @@ pub unsafe fn instr16_F7_4_reg(mut r1: i32) { #[no_mangle] pub unsafe fn instr16_F7_5_mem(mut addr: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); - imul16(____0 << 16i32 >> 16i32); + imul16(____0 << 16 >> 16); } #[no_mangle] pub unsafe fn instr16_F7_5_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); - imul16(____0 << 16i32 >> 16i32); + imul16(____0 << 16 >> 16); } #[no_mangle] pub unsafe fn instr16_F7_6_mem(mut addr: i32) { @@ -3203,12 +3098,12 @@ pub unsafe fn instr16_F7_6_reg(mut r1: i32) { #[no_mangle] pub unsafe fn instr16_F7_7_mem(mut addr: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); - idiv16(____0 << 16i32 >> 16i32); + idiv16(____0 << 16 >> 16); } #[no_mangle] pub unsafe fn instr16_F7_7_reg(mut r1: i32) { let mut ____0: i32 = read_reg16(r1); - idiv16(____0 << 16i32 >> 16i32); + idiv16(____0 << 16 >> 16); } #[no_mangle] pub unsafe fn instr32_F7_0_mem(mut addr: i32, mut imm: i32) { @@ -3292,36 +3187,36 @@ pub unsafe fn instr32_F7_7_reg(mut r1: i32) { pub unsafe fn instr_F8() { // clc *flags &= !FLAG_CARRY; - *flags_changed &= !1i32; + *flags_changed &= !1; } #[no_mangle] pub unsafe fn instr_F9() { // stc *flags |= FLAG_CARRY; - *flags_changed &= !1i32; + *flags_changed &= !1; } #[no_mangle] pub unsafe fn instr_FA() { // cli if !*protected_mode || 0 != if 0 != *flags & FLAG_VM { - (getiopl() == 3i32) as i32 + (getiopl() == 3) as i32 } else { (getiopl() >= *cpl as i32) as i32 } { *flags &= !FLAG_INTERRUPT; } - else if 0 != 0i32 * 0i32 && getiopl() < 3i32 && 0 != if 0 != *flags & FLAG_VM { - *cr.offset(4isize) & CR4_VME + else if 0 != 0 * 0 && getiopl() < 3 && 0 != if 0 != *flags & FLAG_VM { + *cr.offset(4) & CR4_VME } else { - (*cpl as i32 == 3i32 && 0 != *cr.offset(4isize) & CR4_PVI) as i32 + (*cpl as i32 == 3 && 0 != *cr.offset(4) & CR4_PVI) as i32 } { *flags &= !FLAG_VIF } else { dbg_log!("cli #gp"); - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); }; } #[no_mangle] @@ -3329,29 +3224,28 @@ pub unsafe fn instr_FB() { // sti let mut old_if: i32 = *flags & FLAG_INTERRUPT; if !*protected_mode || 0 != if 0 != *flags & FLAG_VM { - (getiopl() == 3i32) as i32 + (getiopl() == 3) as i32 } else { (getiopl() >= *cpl as i32) as i32 } { *flags |= FLAG_INTERRUPT; - if old_if == 0i32 { + if old_if == 0 { handle_irqs(); } } - else if 0 != 0i32 * 0i32 && getiopl() < 3i32 && *flags & FLAG_VIP == 0i32 && 0 != if 0 - != *flags & FLAG_VM + else if 0 != 0 * 0 && getiopl() < 3 && *flags & FLAG_VIP == 0 && 0 != if 0 != *flags & FLAG_VM { - *cr.offset(4isize) & CR4_VME + *cr.offset(4) & CR4_VME } else { - (*cpl as i32 == 3i32 && 0 != *cr.offset(4isize) & CR4_PVI) as i32 + (*cpl as i32 == 3 && 0 != *cr.offset(4) & CR4_PVI) as i32 } { *flags |= FLAG_VIF } else { dbg_log!("sti #gp"); - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); }; } #[no_mangle] @@ -3406,7 +3300,7 @@ pub unsafe fn instr16_FF_2_helper(mut data: i32) { let mut cs: i32 = get_seg_cs(); return_on_pagefault!(push16(get_real_eip())); *instruction_pointer = cs + data; - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] pub unsafe fn instr16_FF_2_mem(mut addr: i32) { @@ -3427,15 +3321,15 @@ pub unsafe fn instr16_FF_3_reg(mut r: i32) { pub unsafe fn instr16_FF_3_mem(mut addr: i32) { // callf let mut new_ip: i32 = return_on_pagefault!(safe_read16(addr)); - let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 2i32)); + let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 2)); far_jump(new_ip, new_cs, true); - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] pub unsafe fn instr16_FF_4_helper(mut data: i32) { // jmp near *instruction_pointer = get_seg_cs() + data; - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] pub unsafe fn instr16_FF_4_mem(mut addr: i32) { @@ -3456,9 +3350,9 @@ pub unsafe fn instr16_FF_5_reg(mut r: i32) { pub unsafe fn instr16_FF_5_mem(mut addr: i32) { // jmpf let mut new_ip: i32 = return_on_pagefault!(safe_read16(addr)); - let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 2i32)); + let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 2)); far_jump(new_ip, new_cs, false); - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] pub unsafe fn instr16_FF_6_mem(mut addr: i32) { @@ -3493,7 +3387,7 @@ pub unsafe fn instr32_FF_2_helper(mut data: i32) { // call near let mut cs: i32 = get_seg_cs(); return_on_pagefault!(push32(get_real_eip())); - dbg_assert!(0 != is_asize_32() as i32 || data < 65536i32); + dbg_assert!(0 != is_asize_32() as i32 || data < 65536); *instruction_pointer = cs + data; } #[no_mangle] @@ -3515,19 +3409,19 @@ pub unsafe fn instr32_FF_3_reg(mut r: i32) { pub unsafe fn instr32_FF_3_mem(mut addr: i32) { // callf let mut new_ip: i32 = return_on_pagefault!(safe_read32s(addr)); - let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 4i32)); + let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 4)); if !*protected_mode || 0 != vm86_mode() as i32 { - if 0 != new_ip as u32 & 4294901760u32 { - dbg_assert!(0 != 0i32); + if 0 != new_ip as u32 & 4294901760 { + dbg_assert!(0 != 0); } } far_jump(new_ip, new_cs, true); - dbg_assert!(0 != is_asize_32() as i32 || new_ip < 65536i32); + dbg_assert!(0 != is_asize_32() as i32 || new_ip < 65536); } #[no_mangle] pub unsafe fn instr32_FF_4_helper(mut data: i32) { // jmp near - dbg_assert!(0 != is_asize_32() as i32 || data < 65536i32); + dbg_assert!(0 != is_asize_32() as i32 || data < 65536); *instruction_pointer = get_seg_cs() + data; } #[no_mangle] @@ -3549,14 +3443,14 @@ pub unsafe fn instr32_FF_5_reg(mut r: i32) { pub unsafe fn instr32_FF_5_mem(mut addr: i32) { // jmpf let mut new_ip: i32 = return_on_pagefault!(safe_read32s(addr)); - let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 4i32)); + let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 4)); if !*protected_mode || 0 != vm86_mode() as i32 { - if 0 != new_ip as u32 & 4294901760u32 { - dbg_assert!(0 != 0i32); + if 0 != new_ip as u32 & 4294901760 { + dbg_assert!(0 != 0); } } far_jump(new_ip, new_cs, false); - dbg_assert!(0 != is_asize_32() as i32 || new_ip < 65536i32); + dbg_assert!(0 != is_asize_32() as i32 || new_ip < 65536); } #[no_mangle] pub unsafe fn instr32_FF_6_mem(mut addr: i32) { @@ -3719,22 +3613,22 @@ pub unsafe fn instr32_F3AF() { scasd_rep(PREFIX_F3); } #[no_mangle] pub unsafe fn instr_D8_0_mem(mut addr: i32) { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); - fpu_fadd(0i32, ____0); + fpu_fadd(0, ____0); } #[no_mangle] pub unsafe fn instr_D8_0_reg(mut r: i32) { let mut ____0: f64 = fpu_get_sti(r); - fpu_fadd(0i32, ____0); + fpu_fadd(0, ____0); } #[no_mangle] pub unsafe fn instr_D8_1_mem(mut addr: i32) { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); - fpu_fmul(0i32, ____0); + fpu_fmul(0, ____0); } #[no_mangle] pub unsafe fn instr_D8_1_reg(mut r: i32) { let mut ____0: f64 = fpu_get_sti(r); - fpu_fmul(0i32, ____0); + fpu_fmul(0, ____0); } #[no_mangle] pub unsafe fn instr_D8_2_mem(mut addr: i32) { @@ -3759,42 +3653,42 @@ pub unsafe fn instr_D8_3_reg(mut r: i32) { #[no_mangle] pub unsafe fn instr_D8_4_mem(mut addr: i32) { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); - fpu_fsub(0i32, ____0); + fpu_fsub(0, ____0); } #[no_mangle] pub unsafe fn instr_D8_4_reg(mut r: i32) { let mut ____0: f64 = fpu_get_sti(r); - fpu_fsub(0i32, ____0); + fpu_fsub(0, ____0); } #[no_mangle] pub unsafe fn instr_D8_5_mem(mut addr: i32) { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); - fpu_fsubr(0i32, ____0); + fpu_fsubr(0, ____0); } #[no_mangle] pub unsafe fn instr_D8_5_reg(mut r: i32) { let mut ____0: f64 = fpu_get_sti(r); - fpu_fsubr(0i32, ____0); + fpu_fsubr(0, ____0); } #[no_mangle] pub unsafe fn instr_D8_6_mem(mut addr: i32) { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); - fpu_fdiv(0i32, ____0); + fpu_fdiv(0, ____0); } #[no_mangle] pub unsafe fn instr_D8_6_reg(mut r: i32) { let mut ____0: f64 = fpu_get_sti(r); - fpu_fdiv(0i32, ____0); + fpu_fdiv(0, ____0); } #[no_mangle] pub unsafe fn instr_D8_7_mem(mut addr: i32) { let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); - fpu_fdivr(0i32, ____0); + fpu_fdivr(0, ____0); } #[no_mangle] pub unsafe fn instr_D8_7_reg(mut r: i32) { let mut ____0: f64 = fpu_get_sti(r); - fpu_fdivr(0i32, ____0); + fpu_fdivr(0, ____0); } #[no_mangle] pub unsafe fn instr_D9_0_mem(mut addr: i32) { @@ -3817,7 +3711,7 @@ pub unsafe fn instr_D9_1_reg(mut r: i32) { fpu_fxch(r); } pub unsafe fn instr_D9_2_mem(mut addr: i32) { fpu_fstm32(addr); } #[no_mangle] pub unsafe fn instr_D9_2_reg(mut r: i32) { - if r != 0i32 { + if r != 0 { trigger_ud(); }; } @@ -3861,7 +3755,7 @@ pub unsafe fn instr_D9_5_reg(mut r: i32) { // fld1/fldl2t/fldl2e/fldpi/fldlg2/fldln2/fldz match r { 0 => { - fpu_push(1i32 as f64); + fpu_push(1 as f64); }, 1 => { fpu_push(M_LN10 / M_LN2); @@ -3879,7 +3773,7 @@ pub unsafe fn instr_D9_5_reg(mut r: i32) { fpu_push(M_LN2); }, 6 => { - fpu_push(0i32 as f64); + fpu_push(0 as f64); }, 7 => { dbg_log!("d9/5/7"); @@ -3896,24 +3790,24 @@ pub unsafe fn instr_D9_6_reg(mut r: i32) { match r { 0 => { // f2xm1 - *fpu_st.offset(*fpu_stack_ptr as isize) = pow(2i32 as f64, st0) - 1i32 as f64 + *fpu_st.offset(*fpu_stack_ptr as isize) = pow(2 as f64, st0) - 1 as f64 }, 1 => { // fyl2x - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(1i32 as u32) & 7i32 as u32) as isize) = - fpu_get_sti(1i32) * st0.ln() / M_LN2; + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(1 as u32) & 7 as u32) as isize) = + fpu_get_sti(1) * st0.ln() / M_LN2; fpu_pop(); }, 2 => { // fptan *fpu_st.offset(*fpu_stack_ptr as isize) = st0.tan(); - fpu_push(1i32 as f64); + fpu_push(1 as f64); // no bug: push constant 1 }, 3 => { // fpatan - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(1i32 as u32) & 7i32 as u32) as isize) = - fpu_get_sti(1i32).atan2(st0); + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(1 as u32) & 7 as u32) as isize) = + fpu_get_sti(1).atan2(st0); fpu_pop(); }, 4 => { @@ -3921,20 +3815,20 @@ pub unsafe fn instr_D9_6_reg(mut r: i32) { }, 5 => { // fprem1 - *fpu_st.offset(*fpu_stack_ptr as isize) = fmod(st0, fpu_get_sti(1i32)) + *fpu_st.offset(*fpu_stack_ptr as isize) = fmod(st0, fpu_get_sti(1)) }, 6 => { // fdecstp - *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_sub(1i32 as u32) & 7i32 as u32; + *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_sub(1 as u32) & 7 as u32; *fpu_status_word &= !FPU_C1 }, 7 => { // fincstp - *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_add(1i32 as u32) & 7i32 as u32; + *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_add(1 as u32) & 7 as u32; *fpu_status_word &= !FPU_C1 }, _ => { - dbg_assert!(0 != 0i32); + dbg_assert!(0 != 0); }, }; } @@ -3949,8 +3843,8 @@ pub unsafe fn instr_D9_7_reg(mut r: i32) { }, 1 => { // fyl2xp1: y * log2(x+1) and pop - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(1i32 as u32) & 7i32 as u32) as isize) = - fpu_get_sti(1i32) * (st0 + 1i32 as f64).ln() / M_LN2; + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(1 as u32) & 7 as u32) as isize) = + fpu_get_sti(1) * (st0 + 1 as f64).ln() / M_LN2; fpu_pop(); }, 2 => *fpu_st.offset(*fpu_stack_ptr as isize) = st0.sqrt(), @@ -3964,23 +3858,22 @@ pub unsafe fn instr_D9_7_reg(mut r: i32) { }, 5 => { // fscale - *fpu_st.offset(*fpu_stack_ptr as isize) = - st0 * pow(2i32 as f64, trunc(fpu_get_sti(1i32))) + *fpu_st.offset(*fpu_stack_ptr as isize) = st0 * pow(2 as f64, trunc(fpu_get_sti(1))) }, 6 => *fpu_st.offset(*fpu_stack_ptr as isize) = st0.sin(), 7 => *fpu_st.offset(*fpu_stack_ptr as isize) = st0.cos(), _ => { - dbg_assert!(0 != 0i32); + dbg_assert!(0 != 0); }, }; } #[no_mangle] pub unsafe fn instr_DA_0_mem(mut addr: i32) { - fpu_fadd(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); + fpu_fadd(0, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] pub unsafe fn instr_DA_1_mem(mut addr: i32) { - fpu_fmul(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); + fpu_fmul(0, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] pub unsafe fn instr_DA_2_mem(mut addr: i32) { @@ -3992,19 +3885,19 @@ pub unsafe fn instr_DA_3_mem(mut addr: i32) { } #[no_mangle] pub unsafe fn instr_DA_4_mem(mut addr: i32) { - fpu_fsub(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); + fpu_fsub(0, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] pub unsafe fn instr_DA_5_mem(mut addr: i32) { - fpu_fsubr(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); + fpu_fsubr(0, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] pub unsafe fn instr_DA_6_mem(mut addr: i32) { - fpu_fdiv(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); + fpu_fdiv(0, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] pub unsafe fn instr_DA_7_mem(mut addr: i32) { - fpu_fdivr(0i32, return_on_pagefault!(safe_read32s(addr)) as f64); + fpu_fdivr(0, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] pub unsafe fn instr_DA_0_reg(mut r: i32) { fpu_fcmovcc(test_b(), r); } @@ -4018,7 +3911,7 @@ pub unsafe fn instr_DA_3_reg(mut r: i32) { fpu_fcmovcc(test_p(), r); } pub unsafe fn instr_DA_4_reg(mut r: i32) { trigger_ud(); } #[no_mangle] pub unsafe fn instr_DA_5_reg(mut r: i32) { - if r == 1i32 { + if r == 1 { fpu_fucompp(); } else { @@ -4055,13 +3948,13 @@ pub unsafe fn instr_DB_2_reg(mut r: i32) { fpu_fcmovcc(!test_be(), r); } pub unsafe fn instr_DB_3_reg(mut r: i32) { fpu_fcmovcc(!test_p(), r); } #[no_mangle] pub unsafe fn instr_DB_4_reg(mut r: i32) { - if r == 3i32 { + if r == 3 { fpu_finit(); } - else if r == 4i32 || r == 1i32 { + else if r == 4 || r == 1 { // fsetpm and fdisi; treated as nop } - else if r == 2i32 { + else if r == 2 { fpu_fclex(); } else { @@ -4076,11 +3969,11 @@ pub unsafe fn instr_DB_6_reg(mut r: i32) { fpu_fcomi(r); } pub unsafe fn instr_DB_7_reg(mut r: i32) { trigger_ud(); } #[no_mangle] pub unsafe fn instr_DC_0_mem(mut addr: i32) { - fpu_fadd(0i32, return_on_pagefault!(fpu_load_m64(addr))); + fpu_fadd(0, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] pub unsafe fn instr_DC_1_mem(mut addr: i32) { - fpu_fmul(0i32, return_on_pagefault!(fpu_load_m64(addr))); + fpu_fmul(0, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] pub unsafe fn instr_DC_2_mem(mut addr: i32) { fpu_fcom(return_on_pagefault!(fpu_load_m64(addr))); } @@ -4088,19 +3981,19 @@ pub unsafe fn instr_DC_2_mem(mut addr: i32) { fpu_fcom(return_on_pagefault!(fpu_ pub unsafe fn instr_DC_3_mem(mut addr: i32) { fpu_fcomp(return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] pub unsafe fn instr_DC_4_mem(mut addr: i32) { - fpu_fsub(0i32, return_on_pagefault!(fpu_load_m64(addr))); + fpu_fsub(0, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] pub unsafe fn instr_DC_5_mem(mut addr: i32) { - fpu_fsubr(0i32, return_on_pagefault!(fpu_load_m64(addr))); + fpu_fsubr(0, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] pub unsafe fn instr_DC_6_mem(mut addr: i32) { - fpu_fdiv(0i32, return_on_pagefault!(fpu_load_m64(addr))); + fpu_fdiv(0, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] pub unsafe fn instr_DC_7_mem(mut addr: i32) { - fpu_fdivr(0i32, return_on_pagefault!(fpu_load_m64(addr))); + fpu_fdivr(0, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] pub unsafe fn instr_DC_0_reg(mut r: i32) { fpu_fadd(r, fpu_get_sti(r)); } @@ -4158,11 +4051,11 @@ pub unsafe fn instr_DD_6_reg(mut r: i32) { trigger_ud(); } pub unsafe fn instr_DD_7_reg(mut r: i32) { trigger_ud(); } #[no_mangle] pub unsafe fn instr_DE_0_mem(mut addr: i32) { - fpu_fadd(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); + fpu_fadd(0, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] pub unsafe fn instr_DE_1_mem(mut addr: i32) { - fpu_fmul(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); + fpu_fmul(0, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] pub unsafe fn instr_DE_2_mem(mut addr: i32) { @@ -4174,19 +4067,19 @@ pub unsafe fn instr_DE_3_mem(mut addr: i32) { } #[no_mangle] pub unsafe fn instr_DE_4_mem(mut addr: i32) { - fpu_fsub(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); + fpu_fsub(0, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] pub unsafe fn instr_DE_5_mem(mut addr: i32) { - fpu_fsubr(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); + fpu_fsubr(0, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] pub unsafe fn instr_DE_6_mem(mut addr: i32) { - fpu_fdiv(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); + fpu_fdiv(0, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] pub unsafe fn instr_DE_7_mem(mut addr: i32) { - fpu_fdivr(0i32, return_on_pagefault!(safe_read16(addr)) as i16 as f64); + fpu_fdivr(0, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] pub unsafe fn instr_DE_0_reg(mut r: i32) { @@ -4265,7 +4158,7 @@ pub unsafe fn instr_DF_2_reg(mut r: i32) { trigger_ud(); } pub unsafe fn instr_DF_3_reg(mut r: i32) { trigger_ud(); } #[no_mangle] pub unsafe fn instr_DF_4_reg(mut r: i32) { - if r == 0i32 { + if r == 0 { fpu_fnstsw_reg(); } else { @@ -4298,11 +4191,11 @@ pub unsafe fn instr32_E3(mut imm8s: i32) { jcxz32(imm8s); } pub unsafe fn instr16_EB(mut imm8: i32) { // jmp near jmp_rel16(imm8); - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] pub unsafe fn instr32_EB(mut imm8: i32) { // jmp near *instruction_pointer = *instruction_pointer + imm8; - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536i32); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index b8705530..ad4faca4 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -118,7 +118,7 @@ pub unsafe fn instr_0F00_2_mem(mut addr: i32) { return; } else if 0 != *cpl { - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); return; } else { @@ -133,7 +133,7 @@ pub unsafe fn instr_0F00_2_reg(mut r: i32) { return; } else if 0 != *cpl { - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); return; } else { @@ -149,7 +149,7 @@ pub unsafe fn instr_0F00_3_mem(mut addr: i32) { return; } else if 0 != *cpl { - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); return; } else { @@ -164,7 +164,7 @@ pub unsafe fn instr_0F00_3_reg(mut r: i32) { return; } else if 0 != *cpl { - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); return; } else { @@ -221,30 +221,30 @@ pub unsafe fn instr_0F01_0_reg(mut r: i32) { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0F01_0_mem(mut addr: i32) { // sgdt - return_on_pagefault!(writable_or_pagefault(addr, 6i32)); + return_on_pagefault!(writable_or_pagefault(addr, 6)); let mut mask: i32 = if 0 != is_osize_32() as i32 { - -1i32 + -1 } else { - 16777215i32 + 16777215 }; safe_write16(addr, *gdtr_size).unwrap(); - safe_write32(addr + 2i32, *gdtr_offset & mask).unwrap(); + safe_write32(addr + 2, *gdtr_offset & mask).unwrap(); } #[no_mangle] pub unsafe fn instr_0F01_1_reg(mut r: i32) { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0F01_1_mem(mut addr: i32) { // sidt - return_on_pagefault!(writable_or_pagefault(addr, 6i32)); + return_on_pagefault!(writable_or_pagefault(addr, 6)); let mut mask: i32 = if 0 != is_osize_32() as i32 { - -1i32 + -1 } else { - 16777215i32 + 16777215 }; safe_write16(addr, *idtr_size).unwrap(); - safe_write32(addr + 2i32, *idtr_offset & mask).unwrap(); + safe_write32(addr + 2, *idtr_offset & mask).unwrap(); } #[no_mangle] pub unsafe fn instr_0F01_2_reg(mut r: i32) { trigger_ud(); } @@ -252,17 +252,17 @@ pub unsafe fn instr_0F01_2_reg(mut r: i32) { trigger_ud(); } pub unsafe fn instr_0F01_2_mem(mut addr: i32) { // lgdt if 0 != *cpl { - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); return; } else { let mut size: i32 = return_on_pagefault!(safe_read16(addr)); - let mut offset: i32 = return_on_pagefault!(safe_read32s(addr + 2i32)); + let mut offset: i32 = return_on_pagefault!(safe_read32s(addr + 2)); let mut mask: i32 = if 0 != is_osize_32() as i32 { - -1i32 + -1 } else { - 16777215i32 + 16777215 }; *gdtr_size = size; *gdtr_offset = offset & mask; @@ -275,17 +275,17 @@ pub unsafe fn instr_0F01_3_reg(mut r: i32) { trigger_ud(); } pub unsafe fn instr_0F01_3_mem(mut addr: i32) { // lidt if 0 != *cpl { - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); return; } else { let mut size: i32 = return_on_pagefault!(safe_read16(addr)); - let mut offset: i32 = return_on_pagefault!(safe_read32s(addr + 2i32)); + let mut offset: i32 = return_on_pagefault!(safe_read32s(addr + 2)); let mut mask: i32 = if 0 != is_osize_32() as i32 { - -1i32 + -1 } else { - 16777215i32 + 16777215 }; *idtr_size = size; *idtr_offset = offset & mask; @@ -299,11 +299,11 @@ pub unsafe fn instr_0F01_4_reg(mut r: i32) { } #[no_mangle] pub unsafe fn instr_0F01_4_mem(mut addr: i32) { - return_on_pagefault!(safe_write16(addr, *cr & 65535i32)); + return_on_pagefault!(safe_write16(addr, *cr & 65535)); } #[no_mangle] pub unsafe fn lmsw(mut new_cr0: i32) { - new_cr0 = *cr & !15i32 | new_cr0 & 15i32; + new_cr0 = *cr & !15 | new_cr0 & 15; if *protected_mode { // lmsw cannot be used to switch back new_cr0 |= CR0_PE @@ -313,7 +313,7 @@ pub unsafe fn lmsw(mut new_cr0: i32) { #[no_mangle] pub unsafe fn instr_0F01_6_reg(mut r: i32) { if 0 != *cpl { - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); return; } else { @@ -324,7 +324,7 @@ pub unsafe fn instr_0F01_6_reg(mut r: i32) { #[no_mangle] pub unsafe fn instr_0F01_6_mem(mut addr: i32) { if 0 != *cpl { - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); return; } else { @@ -338,7 +338,7 @@ pub unsafe fn instr_0F01_7_reg(mut r: i32) { trigger_ud(); } pub unsafe fn instr_0F01_7_mem(mut addr: i32) { // invlpg if 0 != *cpl { - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); return; } else { @@ -395,10 +395,10 @@ pub unsafe fn instr_0F06() { // clts if 0 != *cpl { dbg_log!("clts #gp"); - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); } else { - if 0 != 0i32 * 0i32 { + if 0 != 0 * 0 { dbg_log!("clts"); } *cr &= !CR0_TS; @@ -415,7 +415,7 @@ pub unsafe fn instr_0F08() { pub unsafe fn instr_0F09() { if 0 != *cpl { dbg_log!("wbinvd #gp"); - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); } else { // wbinvd @@ -457,17 +457,17 @@ pub unsafe fn instr_F30F10_reg(mut r1: i32, mut r2: i32) { let mut orig: reg128 = read_xmm128s(r2); write_xmm128( r2, - data.u32_0[0usize] as i32, - orig.u32_0[1usize] as i32, - orig.u32_0[2usize] as i32, - orig.u32_0[3usize] as i32, + data.u32_0[0] as i32, + orig.u32_0[1] as i32, + orig.u32_0[2] as i32, + orig.u32_0[3] as i32, ); } #[no_mangle] pub unsafe fn instr_F30F10_mem(mut addr: i32, mut r: i32) { // movss xmm, xmm/m32 let mut data: i32 = return_on_pagefault!(safe_read32s(addr)); - write_xmm128(r, data, 0i32, 0i32, 0i32); + write_xmm128(r, data, 0, 0, 0); } #[no_mangle] pub unsafe fn instr_660F10(mut source: reg128, mut r: i32) { @@ -487,23 +487,17 @@ pub unsafe fn instr_F20F10_reg(mut r1: i32, mut r2: i32) { let mut orig: reg128 = read_xmm128s(r2); write_xmm128( r2, - data.u32_0[0usize] as i32, - data.u32_0[1usize] as i32, - orig.u32_0[2usize] as i32, - orig.u32_0[3usize] as i32, + data.u32_0[0] as i32, + data.u32_0[1] as i32, + orig.u32_0[2] as i32, + orig.u32_0[3] as i32, ); } #[no_mangle] pub unsafe fn instr_F20F10_mem(mut addr: i32, mut r: i32) { // movsd xmm, xmm/m64 let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); - write_xmm128( - r, - data.u32_0[0usize] as i32, - data.u32_0[1usize] as i32, - 0i32, - 0i32, - ); + write_xmm128(r, data.u32_0[0] as i32, data.u32_0[1] as i32, 0, 0); } #[no_mangle] pub unsafe fn instr_0F11_reg(mut r1: i32, mut r2: i32) { @@ -522,17 +516,17 @@ pub unsafe fn instr_F30F11_reg(mut rm_dest: i32, mut reg_src: i32) { let mut orig: reg128 = read_xmm128s(rm_dest); write_xmm128( rm_dest, - data.u32_0[0usize] as i32, - orig.u32_0[1usize] as i32, - orig.u32_0[2usize] as i32, - orig.u32_0[3usize] as i32, + data.u32_0[0] as i32, + orig.u32_0[1] as i32, + orig.u32_0[2] as i32, + orig.u32_0[3] as i32, ); } #[no_mangle] pub unsafe fn instr_F30F11_mem(mut addr: i32, mut r: i32) { // movss xmm/m32, xmm let mut data: reg128 = read_xmm128s(r); - return_on_pagefault!(safe_write32(addr, data.u32_0[0usize] as i32)); + return_on_pagefault!(safe_write32(addr, data.u32_0[0] as i32)); } #[no_mangle] pub unsafe fn instr_660F11_reg(mut r1: i32, mut r2: i32) { @@ -551,17 +545,17 @@ pub unsafe fn instr_F20F11_reg(mut r1: i32, mut r2: i32) { let mut orig: reg128 = read_xmm128s(r1); write_xmm128( r1, - data.u32_0[0usize] as i32, - data.u32_0[1usize] as i32, - orig.u32_0[2usize] as i32, - orig.u32_0[3usize] as i32, + data.u32_0[0] as i32, + data.u32_0[1] as i32, + orig.u32_0[2] as i32, + orig.u32_0[3] as i32, ); } #[no_mangle] pub unsafe fn instr_F20F11_mem(mut addr: i32, mut r: i32) { // movsd xmm/m64, xmm let mut data: reg64 = read_xmm64s(r); - return_on_pagefault!(safe_write64(addr, data.u64_0[0usize] as i64)); + return_on_pagefault!(safe_write64(addr, data.u64_0[0] as i64)); } #[no_mangle] pub unsafe fn instr_0F12_mem(mut addr: i32, mut r: i32) { @@ -570,10 +564,10 @@ pub unsafe fn instr_0F12_mem(mut addr: i32, mut r: i32) { let mut orig: reg128 = read_xmm128s(r); write_xmm128( r, - data.u32_0[0usize] as i32, - data.u32_0[1usize] as i32, - orig.u32_0[2usize] as i32, - orig.u32_0[3usize] as i32, + data.u32_0[0] as i32, + data.u32_0[1] as i32, + orig.u32_0[2] as i32, + orig.u32_0[3] as i32, ); } #[no_mangle] @@ -583,10 +577,10 @@ pub unsafe fn instr_0F12_reg(mut r1: i32, mut r2: i32) { let mut orig: reg128 = read_xmm128s(r2); write_xmm128( r2, - data.u32_0[2usize] as i32, - data.u32_0[3usize] as i32, - orig.u32_0[2usize] as i32, - orig.u32_0[3usize] as i32, + data.u32_0[2] as i32, + data.u32_0[3] as i32, + orig.u32_0[2] as i32, + orig.u32_0[3] as i32, ); } #[no_mangle] @@ -626,10 +620,10 @@ pub unsafe fn instr_0F14(mut source: reg64, mut r: i32) { let mut destination: reg64 = read_xmm64s(r); write_xmm128( r, - destination.u32_0[0usize] as i32, - source.u32_0[0usize] as i32, - destination.u32_0[1usize] as i32, - source.u32_0[1usize] as i32, + destination.u32_0[0] as i32, + source.u32_0[0] as i32, + destination.u32_0[1] as i32, + source.u32_0[1] as i32, ); } #[no_mangle] @@ -645,10 +639,10 @@ pub unsafe fn instr_660F14(mut source: reg64, mut r: i32) { let mut destination: reg64 = read_xmm64s(r); write_xmm128( r, - destination.u32_0[0usize] as i32, - destination.u32_0[1usize] as i32, - source.u32_0[0usize] as i32, - source.u32_0[1usize] as i32, + destination.u32_0[0] as i32, + destination.u32_0[1] as i32, + source.u32_0[0] as i32, + source.u32_0[1] as i32, ); } #[no_mangle] @@ -664,10 +658,10 @@ pub unsafe fn instr_0F15(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, - destination.u32_0[2usize] as i32, - source.u32_0[2usize] as i32, - destination.u32_0[3usize] as i32, - source.u32_0[3usize] as i32, + destination.u32_0[2] as i32, + source.u32_0[2] as i32, + destination.u32_0[3] as i32, + source.u32_0[3] as i32, ); } #[no_mangle] @@ -683,10 +677,10 @@ pub unsafe fn instr_660F15(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, - destination.u32_0[2usize] as i32, - destination.u32_0[3usize] as i32, - source.u32_0[2usize] as i32, - source.u32_0[3usize] as i32, + destination.u32_0[2] as i32, + destination.u32_0[3] as i32, + source.u32_0[2] as i32, + source.u32_0[3] as i32, ); } #[no_mangle] @@ -707,10 +701,10 @@ pub unsafe fn instr_0F16_reg(mut r1: i32, mut r2: i32) { let mut orig: reg128 = read_xmm128s(r2); write_xmm128( r2, - orig.u32_0[0usize] as i32, - orig.u32_0[1usize] as i32, - data.u32_0[0usize] as i32, - data.u32_0[1usize] as i32, + orig.u32_0[0] as i32, + orig.u32_0[1] as i32, + data.u32_0[0] as i32, + data.u32_0[1] as i32, ); } #[no_mangle] @@ -754,7 +748,7 @@ pub unsafe fn instr_0F1F_mem(mut addr: i32, mut r: i32) {} #[no_mangle] pub unsafe fn instr_0F20(mut r: i32, mut creg: i32) { if 0 != *cpl { - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); return; } else { @@ -763,13 +757,13 @@ pub unsafe fn instr_0F20(mut r: i32, mut creg: i32) { write_reg32(r, *cr); }, 2 => { - write_reg32(r, *cr.offset(2isize)); + write_reg32(r, *cr.offset(2)); }, 3 => { - write_reg32(r, *cr.offset(3isize)); + write_reg32(r, *cr.offset(3)); }, 4 => { - write_reg32(r, *cr.offset(4isize)); + write_reg32(r, *cr.offset(4)); }, _ => { dbg_log!("{}", creg); @@ -782,23 +776,23 @@ pub unsafe fn instr_0F20(mut r: i32, mut creg: i32) { #[no_mangle] pub unsafe fn instr_0F21(mut r: i32, mut dreg_index: i32) { if 0 != *cpl { - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); return; } else { - if dreg_index == 4i32 || dreg_index == 5i32 { - if 0 != *cr.offset(4isize) & CR4_DE { + if dreg_index == 4 || dreg_index == 5 { + if 0 != *cr.offset(4) & CR4_DE { dbg_log!("#ud mov dreg 4/5 with cr4.DE set"); trigger_ud(); return; } else { // DR4 and DR5 refer to DR6 and DR7 respectively - dreg_index += 2i32 + dreg_index += 2 } } write_reg32(r, *dreg.offset(dreg_index as isize)); - if 0 != 0i32 * 0i32 { + if 0 != 0 * 0 { dbg_log!( "read dr{}: {:x}", dreg_index, @@ -811,7 +805,7 @@ pub unsafe fn instr_0F21(mut r: i32, mut dreg_index: i32) { #[no_mangle] pub unsafe fn instr_0F22(mut r: i32, mut creg: i32) { if 0 != *cpl { - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); return; } else { @@ -819,45 +813,40 @@ pub unsafe fn instr_0F22(mut r: i32, mut creg: i32) { // mov cr, addr match creg { 0 => { - if 0 != 0i32 * 0i32 { + if 0 != 0 * 0 { dbg_log!("cr0 <- {:x}", data); } set_cr0(data); }, 2 => { dbg_log!("cr2 <- {:x}", data); - *cr.offset(2isize) = data + *cr.offset(2) = data }, 3 => { - if 0 != 0i32 * 0i32 { + if 0 != 0 * 0 { dbg_log!("cr3 <- {:x}", data); } - data &= !4071i32; - dbg_assert!(data & 4095i32 == 0i32, ("TODO")); - *cr.offset(3isize) = data; + data &= !4071; + dbg_assert!(data & 4095 == 0, ("TODO")); + *cr.offset(3) = data; clear_tlb(); }, 4 => { - dbg_log!("cr4 <- {}", *cr.offset(4isize)); + dbg_log!("cr4 <- {}", *cr.offset(4)); if 0 != data as u32 - & ((1i32 << 11i32 - | 1i32 << 12i32 - | 1i32 << 15i32 - | 1i32 << 16i32 - | 1i32 << 19i32) as u32 - | 4290772992u32) + & ((1 << 11 | 1 << 12 | 1 << 15 | 1 << 16 | 1 << 19) as u32 | 4290772992) { dbg_log!("trigger_gp: Invalid cr4 bit"); - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); return; } else { - if 0 != (*cr.offset(4isize) ^ data) & (CR4_PGE | CR4_PSE) { + if 0 != (*cr.offset(4) ^ data) & (CR4_PGE | CR4_PSE) { full_clear_tlb(); } - *cr.offset(4isize) = data; - if 0 != *cr.offset(4isize) & CR4_PAE { - dbg_assert!(0 != 0i32); + *cr.offset(4) = data; + if 0 != *cr.offset(4) & CR4_PAE { + dbg_assert!(0 != 0); } } }, @@ -872,23 +861,23 @@ pub unsafe fn instr_0F22(mut r: i32, mut creg: i32) { #[no_mangle] pub unsafe fn instr_0F23(mut r: i32, mut dreg_index: i32) { if 0 != *cpl { - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); return; } else { - if dreg_index == 4i32 || dreg_index == 5i32 { - if 0 != *cr.offset(4isize) & CR4_DE { + if dreg_index == 4 || dreg_index == 5 { + if 0 != *cr.offset(4) & CR4_DE { dbg_log!("#ud mov dreg 4/5 with cr4.DE set"); trigger_ud(); return; } else { // DR4 and DR5 refer to DR6 and DR7 respectively - dreg_index += 2i32 + dreg_index += 2 } } *dreg.offset(dreg_index as isize) = read_reg32(r); - if 0 != 0i32 * 0i32 { + if 0 != 0 * 0 { dbg_log!( "write dr{}: {:x}", dreg_index, @@ -1012,7 +1001,7 @@ pub unsafe fn instr_660F2C_reg(mut r1: i32, mut r2: i32) { instr_660F2C(read_xmm #[no_mangle] pub unsafe fn instr_F20F2C(mut source: reg64, mut r: i32) { // cvttsd2si r32, xmm/m64 - write_reg32(r, sse_convert_f64_to_i32(source.f64_0[0usize])); + write_reg32(r, sse_convert_f64_to_i32(source.f64_0[0])); } #[no_mangle] pub unsafe fn instr_F20F2C_reg(mut r1: i32, mut r2: i32) { instr_F20F2C(read_xmm64s(r1), r2); } @@ -1143,7 +1132,7 @@ pub unsafe fn instr_660F2F_mem(addr: i32, r: i32) { pub unsafe fn instr_0F30() { // wrmsr - write maschine specific register if 0 != *cpl { - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); return; } else { @@ -1154,7 +1143,7 @@ pub unsafe fn instr_0F30() { dbg_log!("wrmsr ecx={:x} data={:x}:{:x}", index, high, low); } if index == IA32_SYSENTER_CS { - *sysenter_cs = low & 65535i32 + *sysenter_cs = low & 65535 } else if index == IA32_SYSENTER_EIP { *sysenter_eip = low @@ -1164,7 +1153,7 @@ pub unsafe fn instr_0F30() { } else if index == IA32_APIC_BASE_MSR { dbg_assert!( - high == 0i32, + high == 0, ("Changing APIC address (high 32 bits) not supported") ); let mut address: i32 = @@ -1173,7 +1162,7 @@ pub unsafe fn instr_0F30() { address == APIC_ADDRESS, ("Changing APIC address not supported") ); - dbg_assert!(low & IA32_APIC_BASE_EXTD == 0i32, ("x2apic not supported")); + dbg_assert!(low & IA32_APIC_BASE_EXTD == 0, ("x2apic not supported")); apic_enabled = low & IA32_APIC_BASE_EN == IA32_APIC_BASE_EN } else if index == IA32_TIME_STAMP_COUNTER { @@ -1195,7 +1184,7 @@ pub unsafe fn instr_0F30() { } else { dbg_log!("Unknown msr: {:x}", index); - dbg_assert!(0 != 0i32); + dbg_assert!(0 != 0); } } return; @@ -1204,11 +1193,11 @@ pub unsafe fn instr_0F30() { #[no_mangle] pub unsafe fn instr_0F31() { // rdtsc - read timestamp counter - if 0 == *cpl || 0 == *cr.offset(4isize) & CR4_TSD { + if 0 == *cpl || 0 == *cr.offset(4) & CR4_TSD { let mut tsc: u64 = read_tsc(); *reg32s.offset(EAX as isize) = tsc as i32; - *reg32s.offset(EDX as isize) = (tsc >> 32i32) as i32; - if 0 != 0i32 * 0i32 { + *reg32s.offset(EDX as isize) = (tsc >> 32) as i32; + if 0 != 0 * 0 { dbg_log!( "rdtsc edx:eax={:x}:{:x}", *reg32s.offset(EDX as isize), @@ -1217,21 +1206,21 @@ pub unsafe fn instr_0F31() { } } else { - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); }; } #[no_mangle] pub unsafe fn instr_0F32() { // rdmsr - read maschine specific register if 0 != *cpl { - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); return; } else { let mut index: i32 = *reg32s.offset(ECX as isize); dbg_log!("rdmsr ecx={:x}", index); - let mut low: i32 = 0i32; - let mut high: i32 = 0i32; + let mut low: i32 = 0; + let mut high: i32 = 0; if index == IA32_SYSENTER_CS { low = *sysenter_cs } @@ -1244,7 +1233,7 @@ pub unsafe fn instr_0F32() { else if index == IA32_TIME_STAMP_COUNTER { let mut tsc: u64 = read_tsc(); low = tsc as i32; - high = (tsc >> 32i32) as i32 + high = (tsc >> 32) as i32 } else if !(index == IA32_PLATFORM_ID) { if index == IA32_APIC_BASE_MSR { @@ -1257,12 +1246,12 @@ pub unsafe fn instr_0F32() { } else if !(index == IA32_BIOS_SIGN_ID) { if index == MSR_PLATFORM_INFO { - low = 1i32 << 8i32 + low = 1 << 8 } else if !(index == MSR_MISC_FEATURE_ENABLES) { if index == IA32_MISC_ENABLE { // Enable Misc. Processor Features - low = 1i32 << 0i32; + low = 1 << 0; // fast string } else if index == IA32_RTIT_CTL { @@ -1274,7 +1263,7 @@ pub unsafe fn instr_0F32() { } else if !(index == MSR_PKG_C2_RESIDENCY) { dbg_log!("Unknown msr: {:x}", index); - dbg_assert!(0 != 0i32); + dbg_assert!(0 != 0); } } } @@ -1293,9 +1282,9 @@ pub unsafe fn instr_0F33() { #[no_mangle] pub unsafe fn instr_0F34() { // sysenter - let mut seg: i32 = *sysenter_cs & 65532i32; - if !*protected_mode || seg == 0i32 { - trigger_gp_non_raising(0i32); + let mut seg: i32 = *sysenter_cs & 65532; + if !*protected_mode || seg == 0 { + trigger_gp_non_raising(0); return; } else { @@ -1303,43 +1292,43 @@ pub unsafe fn instr_0F34() { *instruction_pointer = *sysenter_eip; *reg32s.offset(ESP as isize) = *sysenter_esp; *sreg.offset(CS as isize) = seg as u16; - *segment_is_null.offset(CS as isize) = 0 != 0i32; + *segment_is_null.offset(CS as isize) = 0 != 0; *segment_limits.offset(CS as isize) = -1i32 as u32; - *segment_offsets.offset(CS as isize) = 0i32; + *segment_offsets.offset(CS as isize) = 0; update_cs_size(true); - *cpl = 0i32 as u8; + *cpl = 0 as u8; cpl_changed(); - *sreg.offset(SS as isize) = (seg + 8i32) as u16; - *segment_is_null.offset(SS as isize) = 0 != 0i32; + *sreg.offset(SS as isize) = (seg + 8) as u16; + *segment_is_null.offset(SS as isize) = 0 != 0; *segment_limits.offset(SS as isize) = -1i32 as u32; - *segment_offsets.offset(SS as isize) = 0i32; - *stack_size_32 = 0 != 1i32; + *segment_offsets.offset(SS as isize) = 0; + *stack_size_32 = 0 != 1; return; }; } #[no_mangle] pub unsafe fn instr_0F35() { // sysexit - let mut seg: i32 = *sysenter_cs & 65532i32; - if !*protected_mode || 0 != *cpl as i32 || seg == 0i32 { - trigger_gp_non_raising(0i32); + let mut seg: i32 = *sysenter_cs & 65532; + if !*protected_mode || 0 != *cpl as i32 || seg == 0 { + trigger_gp_non_raising(0); return; } else { *instruction_pointer = *reg32s.offset(EDX as isize); *reg32s.offset(ESP as isize) = *reg32s.offset(ECX as isize); - *sreg.offset(CS as isize) = (seg + 16i32 | 3i32) as u16; - *segment_is_null.offset(CS as isize) = 0 != 0i32; + *sreg.offset(CS as isize) = (seg + 16 | 3) as u16; + *segment_is_null.offset(CS as isize) = 0 != 0; *segment_limits.offset(CS as isize) = -1i32 as u32; - *segment_offsets.offset(CS as isize) = 0i32; + *segment_offsets.offset(CS as isize) = 0; update_cs_size(true); - *cpl = 3i32 as u8; + *cpl = 3 as u8; cpl_changed(); - *sreg.offset(SS as isize) = (seg + 24i32 | 3i32) as u16; - *segment_is_null.offset(SS as isize) = 0 != 0i32; + *sreg.offset(SS as isize) = (seg + 24 | 3) as u16; + *segment_is_null.offset(SS as isize) = 0 != 0; *segment_limits.offset(SS as isize) = -1i32 as u32; - *segment_offsets.offset(SS as isize) = 0i32; - *stack_size_32 = 0 != 1i32; + *segment_offsets.offset(SS as isize) = 0; + *stack_size_32 = 0 != 1; return; }; } @@ -1690,10 +1679,10 @@ pub unsafe fn instr32_0F4F_reg(mut r1: i32, mut r: i32) { pub unsafe fn instr_0F50_reg(mut r1: i32, mut r2: i32) { // movmskps r, xmm let mut source: reg128 = read_xmm128s(r1); - let mut data: i32 = (source.u32_0[0usize] >> 31i32 - | source.u32_0[1usize] >> 31i32 << 1i32 - | source.u32_0[2usize] >> 31i32 << 2i32 - | source.u32_0[3usize] >> 31i32 << 3i32) as i32; + let mut data: i32 = (source.u32_0[0] >> 31 + | source.u32_0[1] >> 31 << 1 + | source.u32_0[2] >> 31 << 2 + | source.u32_0[3] >> 31 << 3) as i32; write_reg32(r2, data); } #[no_mangle] @@ -1702,8 +1691,7 @@ pub unsafe fn instr_0F50_mem(mut addr: i32, mut r1: i32) { trigger_ud(); } pub unsafe fn instr_660F50_reg(mut r1: i32, mut r2: i32) { // movmskpd r, xmm let mut source: reg128 = read_xmm128s(r1); - let mut data: i32 = - (source.u32_0[1usize] >> 31i32 | source.u32_0[3usize] >> 31i32 << 1i32) as i32; + let mut data: i32 = (source.u32_0[1] >> 31 | source.u32_0[3] >> 31 << 1) as i32; write_reg32(r2, data); } #[no_mangle] @@ -1808,16 +1796,16 @@ pub unsafe fn instr_660F57_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0F60(mut source: i32, mut r: i32) { // punpcklbw mm, mm/m32 let mut destination: reg64 = read_mmx64s(r); - let mut byte0: i32 = destination.u8_0[0usize] as i32; - let mut byte1: i32 = source & 255i32; - let mut byte2: i32 = destination.u8_0[1usize] as i32; - let mut byte3: i32 = source >> 8i32 & 255i32; - let mut byte4: i32 = destination.u8_0[2usize] as i32; - let mut byte5: i32 = source >> 16i32 & 255i32; - let mut byte6: i32 = destination.u8_0[3usize] as i32; - let mut byte7: i32 = source >> 24i32; - let mut low: i32 = byte0 | byte1 << 8i32 | byte2 << 16i32 | byte3 << 24i32; - let mut high: i32 = byte4 | byte5 << 8i32 | byte6 << 16i32 | byte7 << 24i32; + let mut byte0: i32 = destination.u8_0[0] as i32; + let mut byte1: i32 = source & 255; + let mut byte2: i32 = destination.u8_0[1] as i32; + let mut byte3: i32 = source >> 8 & 255; + let mut byte4: i32 = destination.u8_0[2] as i32; + let mut byte5: i32 = source >> 16 & 255; + let mut byte6: i32 = destination.u8_0[3] as i32; + let mut byte7: i32 = source >> 24; + let mut low: i32 = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24; + let mut high: i32 = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24; write_mmx64(r, low, high); } #[no_mangle] @@ -1833,22 +1821,22 @@ pub unsafe fn instr_660F60(mut source: reg64, mut r: i32) { let mut destination: reg64 = read_xmm64s(r); write_xmm128( r, - destination.u8_0[0usize] as i32 - | (source.u8_0[0usize] as i32) << 8i32 - | (destination.u8_0[1usize] as i32) << 16i32 - | (source.u8_0[1usize] as i32) << 24i32, - destination.u8_0[2usize] as i32 - | (source.u8_0[2usize] as i32) << 8i32 - | (destination.u8_0[3usize] as i32) << 16i32 - | (source.u8_0[3usize] as i32) << 24i32, - destination.u8_0[4usize] as i32 - | (source.u8_0[4usize] as i32) << 8i32 - | (destination.u8_0[5usize] as i32) << 16i32 - | (source.u8_0[5usize] as i32) << 24i32, - destination.u8_0[6usize] as i32 - | (source.u8_0[6usize] as i32) << 8i32 - | (destination.u8_0[7usize] as i32) << 16i32 - | (source.u8_0[7usize] as i32) << 24i32, + destination.u8_0[0] as i32 + | (source.u8_0[0] as i32) << 8 + | (destination.u8_0[1] as i32) << 16 + | (source.u8_0[1] as i32) << 24, + destination.u8_0[2] as i32 + | (source.u8_0[2] as i32) << 8 + | (destination.u8_0[3] as i32) << 16 + | (source.u8_0[3] as i32) << 24, + destination.u8_0[4] as i32 + | (source.u8_0[4] as i32) << 8 + | (destination.u8_0[5] as i32) << 16 + | (source.u8_0[5] as i32) << 24, + destination.u8_0[6] as i32 + | (source.u8_0[6] as i32) << 8 + | (destination.u8_0[7] as i32) << 16 + | (source.u8_0[7] as i32) << 24, ); } #[no_mangle] @@ -1861,12 +1849,12 @@ pub unsafe fn instr_660F60_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0F61(mut source: i32, mut r: i32) { // punpcklwd mm, mm/m32 let mut destination: reg64 = read_mmx64s(r); - let mut word0: i32 = destination.u16_0[0usize] as i32; - let mut word1: i32 = source & 65535i32; - let mut word2: i32 = destination.u16_0[1usize] as i32; - let mut word3: i32 = source >> 16i32; - let mut low: i32 = word0 | word1 << 16i32; - let mut high: i32 = word2 | word3 << 16i32; + let mut word0: i32 = destination.u16_0[0] as i32; + let mut word1: i32 = source & 65535; + let mut word2: i32 = destination.u16_0[1] as i32; + let mut word3: i32 = source >> 16; + let mut low: i32 = word0 | word1 << 16; + let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); } #[no_mangle] @@ -1882,10 +1870,10 @@ pub unsafe fn instr_660F61(mut source: reg64, mut r: i32) { let mut destination: reg64 = read_xmm64s(r); write_xmm128( r, - destination.u16_0[0usize] as i32 | (source.u16_0[0usize] as i32) << 16i32, - destination.u16_0[1usize] as i32 | (source.u16_0[1usize] as i32) << 16i32, - destination.u16_0[2usize] as i32 | (source.u16_0[2usize] as i32) << 16i32, - destination.u16_0[3usize] as i32 | (source.u16_0[3usize] as i32) << 16i32, + destination.u16_0[0] as i32 | (source.u16_0[0] as i32) << 16, + destination.u16_0[1] as i32 | (source.u16_0[1] as i32) << 16, + destination.u16_0[2] as i32 | (source.u16_0[2] as i32) << 16, + destination.u16_0[3] as i32 | (source.u16_0[3] as i32) << 16, ); } #[no_mangle] @@ -1898,7 +1886,7 @@ pub unsafe fn instr_660F61_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0F62(mut source: i32, mut r: i32) { // punpckldq mm, mm/m32 let mut destination: reg64 = read_mmx64s(r); - write_mmx64(r, destination.u32_0[0usize] as i32, source); + write_mmx64(r, destination.u32_0[0] as i32, source); } #[no_mangle] pub unsafe fn instr_0F62_reg(mut r1: i32, mut r2: i32) { instr_0F62(read_mmx32s(r1), r2); } @@ -1913,10 +1901,10 @@ pub unsafe fn instr_660F62(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, - destination.u32_0[0usize] as i32, - source.u32_0[0usize] as i32, - destination.u32_0[1usize] as i32, - source.u32_0[1usize] as i32, + destination.u32_0[0] as i32, + source.u32_0[0] as i32, + destination.u32_0[1] as i32, + source.u32_0[1] as i32, ); } #[no_mangle] @@ -1929,14 +1917,14 @@ pub unsafe fn instr_660F62_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0F63(mut source: reg64, mut r: i32) { // packsswb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - let mut low: i32 = saturate_sw_to_sb(destination.u16_0[0usize] as i32) - | saturate_sw_to_sb(destination.u16_0[1usize] as i32) << 8i32 - | saturate_sw_to_sb(destination.u16_0[2usize] as i32) << 16i32 - | saturate_sw_to_sb(destination.u16_0[3usize] as i32) << 24i32; - let mut high: i32 = saturate_sw_to_sb(source.u16_0[0usize] as i32) - | saturate_sw_to_sb(source.u16_0[1usize] as i32) << 8i32 - | saturate_sw_to_sb(source.u16_0[2usize] as i32) << 16i32 - | saturate_sw_to_sb(source.u16_0[3usize] as i32) << 24i32; + let mut low: i32 = saturate_sw_to_sb(destination.u16_0[0] as i32) + | saturate_sw_to_sb(destination.u16_0[1] as i32) << 8 + | saturate_sw_to_sb(destination.u16_0[2] as i32) << 16 + | saturate_sw_to_sb(destination.u16_0[3] as i32) << 24; + let mut high: i32 = saturate_sw_to_sb(source.u16_0[0] as i32) + | saturate_sw_to_sb(source.u16_0[1] as i32) << 8 + | saturate_sw_to_sb(source.u16_0[2] as i32) << 16 + | saturate_sw_to_sb(source.u16_0[3] as i32) << 24; write_mmx64(r, low, high); } #[no_mangle] @@ -1950,22 +1938,22 @@ pub unsafe fn instr_660F63(mut source: reg128, mut r: i32) { // packsswb xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); - let mut dword0: i32 = saturate_sw_to_sb(destination.u16_0[0usize] as i32) - | saturate_sw_to_sb(destination.u16_0[1usize] as i32) << 8i32 - | saturate_sw_to_sb(destination.u16_0[2usize] as i32) << 16i32 - | saturate_sw_to_sb(destination.u16_0[3usize] as i32) << 24i32; - let mut dword1: i32 = saturate_sw_to_sb(destination.u16_0[4usize] as i32) - | saturate_sw_to_sb(destination.u16_0[5usize] as i32) << 8i32 - | saturate_sw_to_sb(destination.u16_0[6usize] as i32) << 16i32 - | saturate_sw_to_sb(destination.u16_0[7usize] as i32) << 24i32; - let mut dword2: i32 = saturate_sw_to_sb(source.u16_0[0usize] as i32) - | saturate_sw_to_sb(source.u16_0[1usize] as i32) << 8i32 - | saturate_sw_to_sb(source.u16_0[2usize] as i32) << 16i32 - | saturate_sw_to_sb(source.u16_0[3usize] as i32) << 24i32; - let mut dword3: i32 = saturate_sw_to_sb(source.u16_0[4usize] as i32) - | saturate_sw_to_sb(source.u16_0[5usize] as i32) << 8i32 - | saturate_sw_to_sb(source.u16_0[6usize] as i32) << 16i32 - | saturate_sw_to_sb(source.u16_0[7usize] as i32) << 24i32; + let mut dword0: i32 = saturate_sw_to_sb(destination.u16_0[0] as i32) + | saturate_sw_to_sb(destination.u16_0[1] as i32) << 8 + | saturate_sw_to_sb(destination.u16_0[2] as i32) << 16 + | saturate_sw_to_sb(destination.u16_0[3] as i32) << 24; + let mut dword1: i32 = saturate_sw_to_sb(destination.u16_0[4] as i32) + | saturate_sw_to_sb(destination.u16_0[5] as i32) << 8 + | saturate_sw_to_sb(destination.u16_0[6] as i32) << 16 + | saturate_sw_to_sb(destination.u16_0[7] as i32) << 24; + let mut dword2: i32 = saturate_sw_to_sb(source.u16_0[0] as i32) + | saturate_sw_to_sb(source.u16_0[1] as i32) << 8 + | saturate_sw_to_sb(source.u16_0[2] as i32) << 16 + | saturate_sw_to_sb(source.u16_0[3] as i32) << 24; + let mut dword3: i32 = saturate_sw_to_sb(source.u16_0[4] as i32) + | saturate_sw_to_sb(source.u16_0[5] as i32) << 8 + | saturate_sw_to_sb(source.u16_0[6] as i32) << 16 + | saturate_sw_to_sb(source.u16_0[7] as i32) << 24; write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] @@ -1979,16 +1967,16 @@ pub unsafe fn instr_0F64(mut source: reg64, mut r: i32) { // pcmpgtb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0i32 as u32; - while i < 8i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 8 as u32 { result.u8_0[i as usize] = (if destination.i8_0[i as usize] as i32 > source.i8_0[i as usize] as i32 { - 255i32 + 255 } else { - 0i32 + 0 }) as u8; i = i.wrapping_add(1) } @@ -2006,16 +1994,16 @@ pub unsafe fn instr_660F64(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: i32 = 0i32; - while i < 16i32 { + let mut i: i32 = 0; + while i < 16 { result.i8_0[i as usize] = (if destination.i8_0[i as usize] as i32 > source.i8_0[i as usize] as i32 { - 255i32 + 255 } else { - 0i32 + 0 }) as i8; i += 1 } @@ -2031,32 +2019,32 @@ pub unsafe fn instr_660F64_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0F65(mut source: reg64, mut r: i32) { // pcmpgtw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - let mut word0: i32 = if destination.i16_0[0usize] as i32 > source.i16_0[0usize] as i32 { - 65535i32 + let mut word0: i32 = if destination.i16_0[0] as i32 > source.i16_0[0] as i32 { + 65535 } else { - 0i32 + 0 }; - let mut word1: i32 = if destination.i16_0[1usize] as i32 > source.i16_0[1usize] as i32 { - 65535i32 + let mut word1: i32 = if destination.i16_0[1] as i32 > source.i16_0[1] as i32 { + 65535 } else { - 0i32 + 0 }; - let mut word2: i32 = if destination.i16_0[2usize] as i32 > source.i16_0[2usize] as i32 { - 65535i32 + let mut word2: i32 = if destination.i16_0[2] as i32 > source.i16_0[2] as i32 { + 65535 } else { - 0i32 + 0 }; - let mut word3: i32 = if destination.i16_0[3usize] as i32 > source.i16_0[3usize] as i32 { - 65535i32 + let mut word3: i32 = if destination.i16_0[3] as i32 > source.i16_0[3] as i32 { + 65535 } else { - 0i32 + 0 }; - let mut low: i32 = word0 | word1 << 16i32; - let mut high: i32 = word2 | word3 << 16i32; + let mut low: i32 = word0 | word1 << 16; + let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); } #[no_mangle] @@ -2071,16 +2059,16 @@ pub unsafe fn instr_660F65(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: i32 = 0i32; - while i < 8i32 { + let mut i: i32 = 0; + while i < 8 { result.u16_0[i as usize] = (if destination.i16_0[i as usize] as i32 > source.i16_0[i as usize] as i32 { - 65535i32 + 65535 } else { - 0i32 + 0 }) as u16; i += 1 } @@ -2096,17 +2084,17 @@ pub unsafe fn instr_660F65_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0F66(mut source: reg64, mut r: i32) { // pcmpgtd mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - let mut low: i32 = if destination.i32_0[0usize] > source.i32_0[0usize] { - -1i32 + let mut low: i32 = if destination.i32_0[0] > source.i32_0[0] { + -1 } else { - 0i32 + 0 }; - let mut high: i32 = if destination.i32_0[1usize] > source.i32_0[1usize] { - -1i32 + let mut high: i32 = if destination.i32_0[1] > source.i32_0[1] { + -1 } else { - 0i32 + 0 }; write_mmx64(r, low, high); } @@ -2123,29 +2111,29 @@ pub unsafe fn instr_660F66(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, - if destination.i32_0[0usize] > source.i32_0[0usize] { - -1i32 + if destination.i32_0[0] > source.i32_0[0] { + -1 } else { - 0i32 + 0 }, - if destination.i32_0[1usize] > source.i32_0[1usize] { - -1i32 + if destination.i32_0[1] > source.i32_0[1] { + -1 } else { - 0i32 + 0 }, - if destination.i32_0[2usize] > source.i32_0[2usize] { - -1i32 + if destination.i32_0[2] > source.i32_0[2] { + -1 } else { - 0i32 + 0 }, - if destination.i32_0[3usize] > source.i32_0[3usize] { - -1i32 + if destination.i32_0[3] > source.i32_0[3] { + -1 } else { - 0i32 + 0 }, ); } @@ -2159,14 +2147,14 @@ pub unsafe fn instr_660F66_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0F67(mut source: reg64, mut r: i32) { // packuswb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - let mut low: u32 = saturate_sw_to_ub(destination.u16_0[0usize] as u32) - | saturate_sw_to_ub(destination.u16_0[1usize] as u32) << 8i32 - | saturate_sw_to_ub(destination.u16_0[2usize] as u32) << 16i32 - | saturate_sw_to_ub(destination.u16_0[3usize] as u32) << 24i32; - let mut high: u32 = saturate_sw_to_ub(source.u16_0[0usize] as u32) - | saturate_sw_to_ub(source.u16_0[1usize] as u32) << 8i32 - | saturate_sw_to_ub(source.u16_0[2usize] as u32) << 16i32 - | saturate_sw_to_ub(source.u16_0[3usize] as u32) << 24i32; + let mut low: u32 = saturate_sw_to_ub(destination.u16_0[0] as u32) + | saturate_sw_to_ub(destination.u16_0[1] as u32) << 8 + | saturate_sw_to_ub(destination.u16_0[2] as u32) << 16 + | saturate_sw_to_ub(destination.u16_0[3] as u32) << 24; + let mut high: u32 = saturate_sw_to_ub(source.u16_0[0] as u32) + | saturate_sw_to_ub(source.u16_0[1] as u32) << 8 + | saturate_sw_to_ub(source.u16_0[2] as u32) << 16 + | saturate_sw_to_ub(source.u16_0[3] as u32) << 24; write_mmx64(r, low as i32, high as i32); } #[no_mangle] @@ -2181,10 +2169,10 @@ pub unsafe fn instr_660F67(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: i32 = 0i32; - while i < 8i32 { + let mut i: i32 = 0; + while i < 8 { result.u8_0[i as usize] = saturate_sw_to_ub(destination.u16_0[i as usize] as u32) as u8; - result.u8_0[(i | 8i32) as usize] = saturate_sw_to_ub(source.u16_0[i as usize] as u32) as u8; + result.u8_0[(i | 8) as usize] = saturate_sw_to_ub(source.u16_0[i as usize] as u32) as u8; i += 1 } write_xmm_reg128(r, result); @@ -2199,16 +2187,16 @@ pub unsafe fn instr_660F67_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0F68(mut source: reg64, mut r: i32) { // punpckhbw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - let mut byte0: i32 = destination.u8_0[4usize] as i32; - let mut byte1: i32 = source.u8_0[4usize] as i32; - let mut byte2: i32 = destination.u8_0[5usize] as i32; - let mut byte3: i32 = source.u8_0[5usize] as i32; - let mut byte4: i32 = destination.u8_0[6usize] as i32; - let mut byte5: i32 = source.u8_0[6usize] as i32; - let mut byte6: i32 = destination.u8_0[7usize] as i32; - let mut byte7: i32 = source.u8_0[7usize] as i32; - let mut low: i32 = byte0 | byte1 << 8i32 | byte2 << 16i32 | byte3 << 24i32; - let mut high: i32 = byte4 | byte5 << 8i32 | byte6 << 16i32 | byte7 << 24i32; + let mut byte0: i32 = destination.u8_0[4] as i32; + let mut byte1: i32 = source.u8_0[4] as i32; + let mut byte2: i32 = destination.u8_0[5] as i32; + let mut byte3: i32 = source.u8_0[5] as i32; + let mut byte4: i32 = destination.u8_0[6] as i32; + let mut byte5: i32 = source.u8_0[6] as i32; + let mut byte6: i32 = destination.u8_0[7] as i32; + let mut byte7: i32 = source.u8_0[7] as i32; + let mut low: i32 = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24; + let mut high: i32 = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24; write_mmx64(r, low, high); } #[no_mangle] @@ -2224,22 +2212,22 @@ pub unsafe fn instr_660F68(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, - destination.u8_0[8usize] as i32 - | (source.u8_0[8usize] as i32) << 8i32 - | (destination.u8_0[9usize] as i32) << 16i32 - | (source.u8_0[9usize] as i32) << 24i32, - destination.u8_0[10usize] as i32 - | (source.u8_0[10usize] as i32) << 8i32 - | (destination.u8_0[11usize] as i32) << 16i32 - | (source.u8_0[11usize] as i32) << 24i32, - destination.u8_0[12usize] as i32 - | (source.u8_0[12usize] as i32) << 8i32 - | (destination.u8_0[13usize] as i32) << 16i32 - | (source.u8_0[13usize] as i32) << 24i32, - destination.u8_0[14usize] as i32 - | (source.u8_0[14usize] as i32) << 8i32 - | (destination.u8_0[15usize] as i32) << 16i32 - | (source.u8_0[15usize] as i32) << 24i32, + destination.u8_0[8] as i32 + | (source.u8_0[8] as i32) << 8 + | (destination.u8_0[9] as i32) << 16 + | (source.u8_0[9] as i32) << 24, + destination.u8_0[10] as i32 + | (source.u8_0[10] as i32) << 8 + | (destination.u8_0[11] as i32) << 16 + | (source.u8_0[11] as i32) << 24, + destination.u8_0[12] as i32 + | (source.u8_0[12] as i32) << 8 + | (destination.u8_0[13] as i32) << 16 + | (source.u8_0[13] as i32) << 24, + destination.u8_0[14] as i32 + | (source.u8_0[14] as i32) << 8 + | (destination.u8_0[15] as i32) << 16 + | (source.u8_0[15] as i32) << 24, ); } #[no_mangle] @@ -2252,12 +2240,12 @@ pub unsafe fn instr_660F68_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0F69(mut source: reg64, mut r: i32) { // punpckhwd mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - let mut word0: i32 = destination.u16_0[2usize] as i32; - let mut word1: i32 = source.u16_0[2usize] as i32; - let mut word2: i32 = destination.u16_0[3usize] as i32; - let mut word3: i32 = source.u16_0[3usize] as i32; - let mut low: i32 = word0 | word1 << 16i32; - let mut high: i32 = word2 | word3 << 16i32; + let mut word0: i32 = destination.u16_0[2] as i32; + let mut word1: i32 = source.u16_0[2] as i32; + let mut word2: i32 = destination.u16_0[3] as i32; + let mut word3: i32 = source.u16_0[3] as i32; + let mut low: i32 = word0 | word1 << 16; + let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); } #[no_mangle] @@ -2271,10 +2259,10 @@ pub unsafe fn instr_660F69(mut source: reg128, mut r: i32) { // punpckhwd xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); - let mut dword0: i32 = destination.u16_0[4usize] as i32 | (source.u16_0[4usize] as i32) << 16i32; - let mut dword1: i32 = destination.u16_0[5usize] as i32 | (source.u16_0[5usize] as i32) << 16i32; - let mut dword2: i32 = destination.u16_0[6usize] as i32 | (source.u16_0[6usize] as i32) << 16i32; - let mut dword3: i32 = destination.u16_0[7usize] as i32 | (source.u16_0[7usize] as i32) << 16i32; + let mut dword0: i32 = destination.u16_0[4] as i32 | (source.u16_0[4] as i32) << 16; + let mut dword1: i32 = destination.u16_0[5] as i32 | (source.u16_0[5] as i32) << 16; + let mut dword2: i32 = destination.u16_0[6] as i32 | (source.u16_0[6] as i32) << 16; + let mut dword3: i32 = destination.u16_0[7] as i32 | (source.u16_0[7] as i32) << 16; write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] @@ -2287,11 +2275,7 @@ pub unsafe fn instr_660F69_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0F6A(mut source: reg64, mut r: i32) { // punpckhdq mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - write_mmx64( - r, - destination.u32_0[1usize] as i32, - source.u32_0[1usize] as i32, - ); + write_mmx64(r, destination.u32_0[1] as i32, source.u32_0[1] as i32); } #[no_mangle] pub unsafe fn instr_0F6A_reg(mut r1: i32, mut r2: i32) { instr_0F6A(read_mmx64s(r1), r2); } @@ -2306,10 +2290,10 @@ pub unsafe fn instr_660F6A(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, - destination.u32_0[2usize] as i32, - source.u32_0[2usize] as i32, - destination.u32_0[3usize] as i32, - source.u32_0[3usize] as i32, + destination.u32_0[2] as i32, + source.u32_0[2] as i32, + destination.u32_0[3] as i32, + source.u32_0[3] as i32, ); } #[no_mangle] @@ -2322,10 +2306,10 @@ pub unsafe fn instr_660F6A_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0F6B(mut source: reg64, mut r: i32) { // packssdw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - let mut low: i32 = (saturate_sd_to_sw(destination.u32_0[0usize]) - | saturate_sd_to_sw(destination.u32_0[1usize]) << 16i32) as i32; - let mut high: i32 = (saturate_sd_to_sw(source.u32_0[0usize]) - | saturate_sd_to_sw(source.u32_0[1usize]) << 16i32) as i32; + let mut low: i32 = (saturate_sd_to_sw(destination.u32_0[0]) + | saturate_sd_to_sw(destination.u32_0[1]) << 16) as i32; + let mut high: i32 = + (saturate_sd_to_sw(source.u32_0[0]) | saturate_sd_to_sw(source.u32_0[1]) << 16) as i32; write_mmx64(r, low, high); } #[no_mangle] @@ -2339,14 +2323,14 @@ pub unsafe fn instr_660F6B(mut source: reg128, mut r: i32) { // packssdw xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); - let mut dword0: i32 = (saturate_sd_to_sw(destination.u32_0[0usize]) - | saturate_sd_to_sw(destination.u32_0[1usize]) << 16i32) as i32; - let mut dword1: i32 = (saturate_sd_to_sw(destination.u32_0[2usize]) - | saturate_sd_to_sw(destination.u32_0[3usize]) << 16i32) as i32; - let mut dword2: i32 = (saturate_sd_to_sw(source.u32_0[0usize]) - | saturate_sd_to_sw(source.u32_0[1usize]) << 16i32) as i32; - let mut dword3: i32 = (saturate_sd_to_sw(source.u32_0[2usize]) - | saturate_sd_to_sw(source.u32_0[3usize]) << 16i32) as i32; + let mut dword0: i32 = (saturate_sd_to_sw(destination.u32_0[0]) + | saturate_sd_to_sw(destination.u32_0[1]) << 16) as i32; + let mut dword1: i32 = (saturate_sd_to_sw(destination.u32_0[2]) + | saturate_sd_to_sw(destination.u32_0[3]) << 16) as i32; + let mut dword2: i32 = + (saturate_sd_to_sw(source.u32_0[0]) | saturate_sd_to_sw(source.u32_0[1]) << 16) as i32; + let mut dword3: i32 = + (saturate_sd_to_sw(source.u32_0[2]) | saturate_sd_to_sw(source.u32_0[3]) << 16) as i32; write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] @@ -2366,10 +2350,10 @@ pub unsafe fn instr_660F6C(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, - destination.u32_0[0usize] as i32, - destination.u32_0[1usize] as i32, - source.u32_0[0usize] as i32, - source.u32_0[1usize] as i32, + destination.u32_0[0] as i32, + destination.u32_0[1] as i32, + source.u32_0[0] as i32, + source.u32_0[1] as i32, ); } #[no_mangle] @@ -2389,10 +2373,10 @@ pub unsafe fn instr_660F6D(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, - destination.u32_0[2usize] as i32, - destination.u32_0[3usize] as i32, - source.u32_0[2usize] as i32, - source.u32_0[3usize] as i32, + destination.u32_0[2] as i32, + destination.u32_0[3] as i32, + source.u32_0[2] as i32, + source.u32_0[3] as i32, ); } #[no_mangle] @@ -2404,7 +2388,7 @@ pub unsafe fn instr_660F6D_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_0F6E(mut source: i32, mut r: i32) { // movd mm, r/m32 - write_mmx64(r, source, 0i32); + write_mmx64(r, source, 0); } #[no_mangle] pub unsafe fn instr_0F6E_reg(mut r1: i32, mut r2: i32) { instr_0F6E(read_reg32(r1), r2); } @@ -2415,7 +2399,7 @@ pub unsafe fn instr_0F6E_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_660F6E(mut source: i32, mut r: i32) { // movd mm, r/m32 - write_xmm128(r, source, 0i32, 0i32, 0i32); + write_xmm128(r, source, 0, 0, 0); } #[no_mangle] pub unsafe fn instr_660F6E_reg(mut r1: i32, mut r2: i32) { instr_660F6E(read_reg32(r1), r2); } @@ -2426,7 +2410,7 @@ pub unsafe fn instr_660F6E_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_0F6F(mut source: reg64, mut r: i32) { // movq mm, mm/m64 - write_mmx64(r, source.u32_0[0usize] as i32, source.u32_0[1usize] as i32); + write_mmx64(r, source.u32_0[0] as i32, source.u32_0[1] as i32); } #[no_mangle] pub unsafe fn instr_0F6F_reg(mut r1: i32, mut r2: i32) { instr_0F6F(read_mmx64s(r1), r2); } @@ -2461,22 +2445,19 @@ pub unsafe fn instr_F30F6F_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_0F70(mut source: reg64, mut r: i32, mut imm8: i32) { // pshufw mm1, mm2/m64, imm8 - let mut word0_shift: i32 = imm8 & 3i32; - let mut word0: u32 = source.u32_0[(word0_shift >> 1i32) as usize] - >> ((word0_shift & 1i32) << 4i32) - & 65535i32 as u32; - let mut word1_shift: i32 = imm8 >> 2i32 & 3i32; - let mut word1: u32 = - source.u32_0[(word1_shift >> 1i32) as usize] >> ((word1_shift & 1i32) << 4i32); - let mut low: i32 = (word0 | word1 << 16i32) as i32; - let mut word2_shift: i32 = imm8 >> 4i32 & 3i32; - let mut word2: u32 = source.u32_0[(word2_shift >> 1i32) as usize] - >> ((word2_shift & 1i32) << 4i32) - & 65535i32 as u32; - let mut word3_shift: u32 = (imm8 >> 6i32) as u32; + let mut word0_shift: i32 = imm8 & 3; + let mut word0: u32 = + source.u32_0[(word0_shift >> 1) as usize] >> ((word0_shift & 1) << 4) & 65535 as u32; + let mut word1_shift: i32 = imm8 >> 2 & 3; + let mut word1: u32 = source.u32_0[(word1_shift >> 1) as usize] >> ((word1_shift & 1) << 4); + let mut low: i32 = (word0 | word1 << 16) as i32; + let mut word2_shift: i32 = imm8 >> 4 & 3; + let mut word2: u32 = + source.u32_0[(word2_shift >> 1) as usize] >> ((word2_shift & 1) << 4) & 65535 as u32; + let mut word3_shift: u32 = (imm8 >> 6) as u32; let mut word3: u32 = - source.u32_0[(word3_shift >> 1i32) as usize] >> ((word3_shift & 1i32 as u32) << 4i32); - let mut high: i32 = (word2 | word3 << 16i32) as i32; + source.u32_0[(word3_shift >> 1) as usize] >> ((word3_shift & 1 as u32) << 4); + let mut high: i32 = (word2 | word3 << 16) as i32; write_mmx64(r, low, high); } #[no_mangle] @@ -2493,10 +2474,10 @@ pub unsafe fn instr_660F70(mut source: reg128, mut r: i32, mut imm8: i32) { // XXX: Aligned access or #gp write_xmm128( r, - source.u32_0[(imm8 & 3i32) as usize] as i32, - source.u32_0[(imm8 >> 2i32 & 3i32) as usize] as i32, - source.u32_0[(imm8 >> 4i32 & 3i32) as usize] as i32, - source.u32_0[(imm8 >> 6i32 & 3i32) as usize] as i32, + source.u32_0[(imm8 & 3) as usize] as i32, + source.u32_0[(imm8 >> 2 & 3) as usize] as i32, + source.u32_0[(imm8 >> 4 & 3) as usize] as i32, + source.u32_0[(imm8 >> 6 & 3) as usize] as i32, ); } #[no_mangle] @@ -2514,12 +2495,12 @@ pub unsafe fn instr_F20F70(mut source: reg128, mut r: i32, mut imm8: i32) { // XXX: Aligned access or #gp write_xmm128( r, - source.u16_0[(imm8 & 3i32) as usize] as i32 - | (source.u16_0[(imm8 >> 2i32 & 3i32) as usize] as i32) << 16i32, - source.u16_0[(imm8 >> 4i32 & 3i32) as usize] as i32 - | (source.u16_0[(imm8 >> 6i32 & 3i32) as usize] as i32) << 16i32, - source.u32_0[2usize] as i32, - source.u32_0[3usize] as i32, + source.u16_0[(imm8 & 3) as usize] as i32 + | (source.u16_0[(imm8 >> 2 & 3) as usize] as i32) << 16, + source.u16_0[(imm8 >> 4 & 3) as usize] as i32 + | (source.u16_0[(imm8 >> 6 & 3) as usize] as i32) << 16, + source.u32_0[2] as i32, + source.u32_0[3] as i32, ); } #[no_mangle] @@ -2536,12 +2517,12 @@ pub unsafe fn instr_F30F70(mut source: reg128, mut r: i32, mut imm8: i32) { // XXX: Aligned access or #gp write_xmm128( r, - source.u32_0[0usize] as i32, - source.u32_0[1usize] as i32, - source.u16_0[(imm8 & 3i32 | 4i32) as usize] as i32 - | (source.u16_0[(imm8 >> 2i32 & 3i32 | 4i32) as usize] as i32) << 16i32, - source.u16_0[(imm8 >> 4i32 & 3i32 | 4i32) as usize] as i32 - | (source.u16_0[(imm8 >> 6i32 & 3i32 | 4i32) as usize] as i32) << 16i32, + source.u32_0[0] as i32, + source.u32_0[1] as i32, + source.u16_0[(imm8 & 3 | 4) as usize] as i32 + | (source.u16_0[(imm8 >> 2 & 3 | 4) as usize] as i32) << 16, + source.u16_0[(imm8 >> 4 & 3 | 4) as usize] as i32 + | (source.u16_0[(imm8 >> 6 & 3 | 4) as usize] as i32) << 16, ); } #[no_mangle] @@ -2667,22 +2648,22 @@ pub unsafe fn instr_660F73_2_reg(mut r: i32, mut imm8: i32) { pub unsafe fn instr_660F73_3_reg(mut r: i32, mut imm8: i32) { // psrldq xmm, imm8 let mut destination: reg128 = read_xmm128s(r); - if imm8 == 0i32 { + if imm8 == 0 { return; } else { let mut result: reg128 = reg128 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - let mut shift: u32 = (if imm8 > 15i32 { 128i32 } else { imm8 << 3i32 }) as u32; - if shift <= 63i32 as u32 { - result.u64_0[0usize] = destination.u64_0[0usize] >> shift - | destination.u64_0[1usize] << (64i32 as u32).wrapping_sub(shift); - result.u64_0[1usize] = destination.u64_0[1usize] >> shift + let mut shift: u32 = (if imm8 > 15 { 128 } else { imm8 << 3 }) as u32; + if shift <= 63 as u32 { + result.u64_0[0] = destination.u64_0[0] >> shift + | destination.u64_0[1] << (64 as u32).wrapping_sub(shift); + result.u64_0[1] = destination.u64_0[1] >> shift } - else if shift <= 127i32 as u32 { - result.u64_0[0usize] = destination.u64_0[1usize] >> shift.wrapping_sub(64i32 as u32); - result.u64_0[1usize] = 0i32 as u64 + else if shift <= 127 as u32 { + result.u64_0[0] = destination.u64_0[1] >> shift.wrapping_sub(64 as u32); + result.u64_0[1] = 0 as u64 } write_xmm_reg128(r, result); return; @@ -2697,22 +2678,22 @@ pub unsafe fn instr_660F73_6_reg(mut r: i32, mut imm8: i32) { pub unsafe fn instr_660F73_7_reg(mut r: i32, mut imm8: i32) { // pslldq xmm, imm8 let mut destination: reg128 = read_xmm128s(r); - if imm8 == 0i32 { + if imm8 == 0 { return; } else { let mut result: reg128 = reg128 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - let mut shift: u32 = (if imm8 > 15i32 { 128i32 } else { imm8 << 3i32 }) as u32; - if shift <= 63i32 as u32 { - result.u64_0[0usize] = destination.u64_0[0usize] << shift; - result.u64_0[1usize] = destination.u64_0[1usize] << shift - | destination.u64_0[0usize] >> (64i32 as u32).wrapping_sub(shift) + let mut shift: u32 = (if imm8 > 15 { 128 } else { imm8 << 3 }) as u32; + if shift <= 63 as u32 { + result.u64_0[0] = destination.u64_0[0] << shift; + result.u64_0[1] = destination.u64_0[1] << shift + | destination.u64_0[0] >> (64 as u32).wrapping_sub(shift) } - else if shift <= 127i32 as u32 { - result.u64_0[0usize] = 0i32 as u64; - result.u64_0[1usize] = destination.u64_0[0usize] << shift.wrapping_sub(64i32 as u32) + else if shift <= 127 as u32 { + result.u64_0[0] = 0 as u64; + result.u64_0[1] = destination.u64_0[0] << shift.wrapping_sub(64 as u32) } write_xmm_reg128(r, result); return; @@ -2723,16 +2704,16 @@ pub unsafe fn instr_0F74(mut source: reg64, mut r: i32) { // pcmpeqb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0i32 as u32; - while i < 8i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 8 as u32 { result.u8_0[i as usize] = (if destination.i8_0[i as usize] as i32 == source.i8_0[i as usize] as i32 { - 255i32 + 255 } else { - 0i32 + 0 }) as u8; i = i.wrapping_add(1) } @@ -2750,14 +2731,14 @@ pub unsafe fn instr_660F74(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: i32 = 0i32; - while i < 16i32 { + let mut i: i32 = 0; + while i < 16 { result.u8_0[i as usize] = (if source.u8_0[i as usize] as i32 == destination.u8_0[i as usize] as i32 { - 255i32 + 255 } else { - 0i32 + 0 }) as u8; i += 1 } @@ -2773,32 +2754,32 @@ pub unsafe fn instr_660F74_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0F75(mut source: reg64, mut r: i32) { // pcmpeqw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - let mut word0: i32 = if destination.u16_0[0usize] as i32 == source.u16_0[0usize] as i32 { - 65535i32 + let mut word0: i32 = if destination.u16_0[0] as i32 == source.u16_0[0] as i32 { + 65535 } else { - 0i32 + 0 }; - let mut word1: i32 = if destination.u16_0[1usize] as i32 == source.u16_0[1usize] as i32 { - 65535i32 + let mut word1: i32 = if destination.u16_0[1] as i32 == source.u16_0[1] as i32 { + 65535 } else { - 0i32 + 0 }; - let mut word2: i32 = if destination.u16_0[2usize] as i32 == source.u16_0[2usize] as i32 { - 65535i32 + let mut word2: i32 = if destination.u16_0[2] as i32 == source.u16_0[2] as i32 { + 65535 } else { - 0i32 + 0 }; - let mut word3: i32 = if destination.u16_0[3usize] as i32 == source.u16_0[3usize] as i32 { - 65535i32 + let mut word3: i32 = if destination.u16_0[3] as i32 == source.u16_0[3] as i32 { + 65535 } else { - 0i32 + 0 }; - let mut low: i32 = word0 | word1 << 16i32; - let mut high: i32 = word2 | word3 << 16i32; + let mut low: i32 = word0 | word1 << 16; + let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); } #[no_mangle] @@ -2813,14 +2794,14 @@ pub unsafe fn instr_660F75(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: i32 = 0i32; - while i < 8i32 { + let mut i: i32 = 0; + while i < 8 { result.u16_0[i as usize] = (if source.u16_0[i as usize] as i32 == destination.u16_0[i as usize] as i32 { - 65535i32 + 65535 } else { - 0i32 + 0 }) as u16; i += 1 } @@ -2836,17 +2817,17 @@ pub unsafe fn instr_660F75_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0F76(mut source: reg64, mut r: i32) { // pcmpeqd mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - let mut low: i32 = if destination.u32_0[0usize] == source.u32_0[0usize] { - -1i32 + let mut low: i32 = if destination.u32_0[0] == source.u32_0[0] { + -1 } else { - 0i32 + 0 }; - let mut high: i32 = if destination.u32_0[1usize] == source.u32_0[1usize] { - -1i32 + let mut high: i32 = if destination.u32_0[1] == source.u32_0[1] { + -1 } else { - 0i32 + 0 }; write_mmx64(r, low, high); } @@ -2863,29 +2844,29 @@ pub unsafe fn instr_660F76(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, - if source.u32_0[0usize] == destination.u32_0[0usize] { - -1i32 + if source.u32_0[0] == destination.u32_0[0] { + -1 } else { - 0i32 + 0 }, - if source.u32_0[1usize] == destination.u32_0[1usize] { - -1i32 + if source.u32_0[1] == destination.u32_0[1] { + -1 } else { - 0i32 + 0 }, - if source.u32_0[2usize] == destination.u32_0[2usize] { - -1i32 + if source.u32_0[2] == destination.u32_0[2] { + -1 } else { - 0i32 + 0 }, - if source.u32_0[3usize] == destination.u32_0[3usize] { - -1i32 + if source.u32_0[3] == destination.u32_0[3] { + -1 } else { - 0i32 + 0 }, ); } @@ -2898,7 +2879,7 @@ pub unsafe fn instr_660F76_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_0F77() { // emms - fpu_set_tag_word(65535i32); + fpu_set_tag_word(65535); } #[no_mangle] pub unsafe fn instr_0F78() { unimplemented_sse(); } @@ -2916,7 +2897,7 @@ pub unsafe fn instr_0F7D() { unimplemented_sse(); } pub unsafe fn instr_0F7E(mut r: i32) -> i32 { // movd r/m32, mm let mut data: reg64 = read_mmx64s(r); - return data.u32_0[0usize] as i32; + return data.u32_0[0] as i32; } #[no_mangle] pub unsafe fn instr_0F7E_reg(mut r1: i32, mut r2: i32) { write_reg32(r1, instr_0F7E(r2)); } @@ -2928,7 +2909,7 @@ pub unsafe fn instr_0F7E_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_660F7E(mut r: i32) -> i32 { // movd r/m32, xmm let mut data: reg64 = read_xmm64s(r); - return data.u32_0[0usize] as i32; + return data.u32_0[0] as i32; } #[no_mangle] pub unsafe fn instr_660F7E_reg(mut r1: i32, mut r2: i32) { write_reg32(r1, instr_660F7E(r2)); } @@ -2940,25 +2921,13 @@ pub unsafe fn instr_660F7E_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_F30F7E_mem(mut addr: i32, mut r: i32) { // movq xmm, xmm/mem64 let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); - write_xmm128( - r, - data.u32_0[0usize] as i32, - data.u32_0[1usize] as i32, - 0i32, - 0i32, - ); + write_xmm128(r, data.u32_0[0] as i32, data.u32_0[1] as i32, 0, 0); } #[no_mangle] pub unsafe fn instr_F30F7E_reg(mut r1: i32, mut r2: i32) { // movq xmm, xmm/mem64 let mut data: reg64 = read_xmm64s(r1); - write_xmm128( - r2, - data.u32_0[0usize] as i32, - data.u32_0[1usize] as i32, - 0i32, - 0i32, - ); + write_xmm128(r2, data.u32_0[0] as i32, data.u32_0[1] as i32, 0, 0); } #[no_mangle] pub unsafe fn instr_0F7F_mem(mut addr: i32, mut r: i32) { @@ -2969,7 +2938,7 @@ pub unsafe fn instr_0F7F_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0F7F_reg(mut r1: i32, mut r2: i32) { // movq mm/m64, mm let mut data: reg64 = read_mmx64s(r2); - write_mmx64(r1, data.u32_0[0usize] as i32, data.u32_0[1usize] as i32); + write_mmx64(r1, data.u32_0[0] as i32, data.u32_0[1] as i32); } #[no_mangle] pub unsafe fn instr_660F7F_mem(mut addr: i32, mut r: i32) { @@ -3131,14 +3100,11 @@ pub unsafe fn instr32_0FA0() { } #[no_mangle] pub unsafe fn instr16_0FA1() { - if !switch_seg( - FS, - return_on_pagefault!(safe_read16(get_stack_pointer(0i32))), - ) { + if !switch_seg(FS, return_on_pagefault!(safe_read16(get_stack_pointer(0)))) { return; } else { - adjust_stack_reg(2i32); + adjust_stack_reg(2); return; }; } @@ -3146,12 +3112,12 @@ pub unsafe fn instr16_0FA1() { pub unsafe fn instr32_0FA1() { if !switch_seg( FS, - return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))) & 65535i32, + return_on_pagefault!(safe_read32s(get_stack_pointer(0))) & 65535, ) { return; } else { - adjust_stack_reg(4i32); + adjust_stack_reg(4); return; }; } @@ -3159,42 +3125,42 @@ pub unsafe fn instr32_0FA1() { pub unsafe fn instr_0FA2() { cpuid(); } #[no_mangle] pub unsafe fn instr16_0FA3_reg(mut r1: i32, mut r2: i32) { - bt_reg(read_reg16(r1), read_reg16(r2) & 15i32); + bt_reg(read_reg16(r1), read_reg16(r2) & 15); } #[no_mangle] pub unsafe fn instr16_0FA3_mem(mut addr: i32, mut r: i32) { - bt_mem(addr, read_reg16(r) << 16i32 >> 16i32); + bt_mem(addr, read_reg16(r) << 16 >> 16); } #[no_mangle] pub unsafe fn instr32_0FA3_reg(mut r1: i32, mut r2: i32) { - bt_reg(read_reg32(r1), read_reg32(r2) & 31i32); + bt_reg(read_reg32(r1), read_reg32(r2) & 31); } #[no_mangle] pub unsafe fn instr32_0FA3_mem(mut addr: i32, mut r: i32) { bt_mem(addr, read_reg32(r)); } #[no_mangle] pub unsafe fn instr16_0FA4_mem(mut addr: i32, mut r: i32, mut imm: i32) { - SAFE_READ_WRITE16!(___, addr, shld16(___, read_reg16(r), imm & 31i32)); + SAFE_READ_WRITE16!(___, addr, shld16(___, read_reg16(r), imm & 31)); } #[no_mangle] pub unsafe fn instr16_0FA4_reg(mut r1: i32, mut r: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, shld16(____0, read_reg16(r), imm & 31i32)); + write_reg16(r1, shld16(____0, read_reg16(r), imm & 31)); } #[no_mangle] pub unsafe fn instr32_0FA4_mem(mut addr: i32, mut r: i32, mut imm: i32) { - SAFE_READ_WRITE32!(___, addr, shld32(___, read_reg32(r), imm & 31i32)); + SAFE_READ_WRITE32!(___, addr, shld32(___, read_reg32(r), imm & 31)); } #[no_mangle] pub unsafe fn instr32_0FA4_reg(mut r1: i32, mut r: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, shld32(____0, read_reg32(r), imm & 31i32)); + write_reg32(r1, shld32(____0, read_reg32(r), imm & 31)); } #[no_mangle] pub unsafe fn instr16_0FA5_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE16!( ___, addr, - shld16(___, read_reg16(r), *reg8.offset(CL as isize) as i32 & 31i32) + shld16(___, read_reg16(r), *reg8.offset(CL as isize) as i32 & 31) ); } #[no_mangle] @@ -3202,11 +3168,7 @@ pub unsafe fn instr16_0FA5_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16( r1, - shld16( - ____0, - read_reg16(r), - *reg8.offset(CL as isize) as i32 & 31i32, - ), + shld16(____0, read_reg16(r), *reg8.offset(CL as isize) as i32 & 31), ); } #[no_mangle] @@ -3214,7 +3176,7 @@ pub unsafe fn instr32_0FA5_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE32!( ___, addr, - shld32(___, read_reg32(r), *reg8.offset(CL as isize) as i32 & 31i32) + shld32(___, read_reg32(r), *reg8.offset(CL as isize) as i32 & 31) ); } #[no_mangle] @@ -3222,11 +3184,7 @@ pub unsafe fn instr32_0FA5_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32( r1, - shld32( - ____0, - read_reg32(r), - *reg8.offset(CL as isize) as i32 & 31i32, - ), + shld32(____0, read_reg32(r), *reg8.offset(CL as isize) as i32 & 31), ); } #[no_mangle] @@ -3246,14 +3204,11 @@ pub unsafe fn instr32_0FA8() { } #[no_mangle] pub unsafe fn instr16_0FA9() { - if !switch_seg( - GS, - return_on_pagefault!(safe_read16(get_stack_pointer(0i32))), - ) { + if !switch_seg(GS, return_on_pagefault!(safe_read16(get_stack_pointer(0)))) { return; } else { - adjust_stack_reg(2i32); + adjust_stack_reg(2); return; }; } @@ -3261,12 +3216,12 @@ pub unsafe fn instr16_0FA9() { pub unsafe fn instr32_0FA9() { if !switch_seg( GS, - return_on_pagefault!(safe_read32s(get_stack_pointer(0i32))) & 65535i32, + return_on_pagefault!(safe_read32s(get_stack_pointer(0))) & 65535, ) { return; } else { - adjust_stack_reg(4i32); + adjust_stack_reg(4); return; }; } @@ -3277,42 +3232,42 @@ pub unsafe fn instr_0FAA() { } #[no_mangle] pub unsafe fn instr16_0FAB_reg(mut r1: i32, mut r2: i32) { - write_reg16(r1, bts_reg(read_reg16(r1), read_reg16(r2) & 15i32)); + write_reg16(r1, bts_reg(read_reg16(r1), read_reg16(r2) & 15)); } #[no_mangle] pub unsafe fn instr16_0FAB_mem(mut addr: i32, mut r: i32) { - bts_mem(addr, read_reg16(r) << 16i32 >> 16i32); + bts_mem(addr, read_reg16(r) << 16 >> 16); } #[no_mangle] pub unsafe fn instr32_0FAB_reg(mut r1: i32, mut r2: i32) { - write_reg32(r1, bts_reg(read_reg32(r1), read_reg32(r2) & 31i32)); + write_reg32(r1, bts_reg(read_reg32(r1), read_reg32(r2) & 31)); } #[no_mangle] pub unsafe fn instr32_0FAB_mem(mut addr: i32, mut r: i32) { bts_mem(addr, read_reg32(r)); } #[no_mangle] pub unsafe fn instr16_0FAC_mem(mut addr: i32, mut r: i32, mut imm: i32) { - SAFE_READ_WRITE16!(___, addr, shrd16(___, read_reg16(r), imm & 31i32)); + SAFE_READ_WRITE16!(___, addr, shrd16(___, read_reg16(r), imm & 31)); } #[no_mangle] pub unsafe fn instr16_0FAC_reg(mut r1: i32, mut r: i32, mut imm: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r1, shrd16(____0, read_reg16(r), imm & 31i32)); + write_reg16(r1, shrd16(____0, read_reg16(r), imm & 31)); } #[no_mangle] pub unsafe fn instr32_0FAC_mem(mut addr: i32, mut r: i32, mut imm: i32) { - SAFE_READ_WRITE32!(___, addr, shrd32(___, read_reg32(r), imm & 31i32)); + SAFE_READ_WRITE32!(___, addr, shrd32(___, read_reg32(r), imm & 31)); } #[no_mangle] pub unsafe fn instr32_0FAC_reg(mut r1: i32, mut r: i32, mut imm: i32) { let mut ____0: i32 = read_reg32(r1); - write_reg32(r1, shrd32(____0, read_reg32(r), imm & 31i32)); + write_reg32(r1, shrd32(____0, read_reg32(r), imm & 31)); } #[no_mangle] pub unsafe fn instr16_0FAD_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE16!( ___, addr, - shrd16(___, read_reg16(r), *reg8.offset(CL as isize) as i32 & 31i32) + shrd16(___, read_reg16(r), *reg8.offset(CL as isize) as i32 & 31) ); } #[no_mangle] @@ -3320,11 +3275,7 @@ pub unsafe fn instr16_0FAD_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); write_reg16( r1, - shrd16( - ____0, - read_reg16(r), - *reg8.offset(CL as isize) as i32 & 31i32, - ), + shrd16(____0, read_reg16(r), *reg8.offset(CL as isize) as i32 & 31), ); } #[no_mangle] @@ -3332,7 +3283,7 @@ pub unsafe fn instr32_0FAD_mem(mut addr: i32, mut r: i32) { SAFE_READ_WRITE32!( ___, addr, - shrd32(___, read_reg32(r), *reg8.offset(CL as isize) as i32 & 31i32) + shrd32(___, read_reg32(r), *reg8.offset(CL as isize) as i32 & 31) ); } #[no_mangle] @@ -3340,11 +3291,7 @@ pub unsafe fn instr32_0FAD_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg32(r1); write_reg32( r1, - shrd32( - ____0, - read_reg32(r), - *reg8.offset(CL as isize) as i32 & 31i32, - ), + shrd32(____0, read_reg32(r), *reg8.offset(CL as isize) as i32 & 31), ); } #[no_mangle] @@ -3363,7 +3310,7 @@ pub unsafe fn instr_0FAE_2_mem(mut addr: i32) { let mut new_mxcsr: i32 = return_on_pagefault!(safe_read32s(addr)); if 0 != new_mxcsr & !MXCSR_MASK { dbg_log!("Invalid mxcsr bits: {:x}", new_mxcsr & !MXCSR_MASK); - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); return; } else { @@ -3388,7 +3335,7 @@ pub unsafe fn instr_0FAE_4_mem(mut addr: i32) { #[no_mangle] pub unsafe fn instr_0FAE_5_reg(mut r: i32) { // lfence - dbg_assert!(r == 0i32, ("Unexpected lfence encoding")); + dbg_assert!(r == 0, ("Unexpected lfence encoding")); } #[no_mangle] pub unsafe fn instr_0FAE_5_mem(mut addr: i32) { @@ -3398,7 +3345,7 @@ pub unsafe fn instr_0FAE_5_mem(mut addr: i32) { #[no_mangle] pub unsafe fn instr_0FAE_6_reg(mut r: i32) { // mfence - dbg_assert!(r == 0i32, ("Unexpected mfence encoding")); + dbg_assert!(r == 0, ("Unexpected mfence encoding")); } #[no_mangle] pub unsafe fn instr_0FAE_6_mem(mut addr: i32) { @@ -3408,7 +3355,7 @@ pub unsafe fn instr_0FAE_6_mem(mut addr: i32) { #[no_mangle] pub unsafe fn instr_0FAE_7_reg(mut r: i32) { // sfence - dbg_assert!(r == 0i32, ("Unexpected sfence encoding")); + dbg_assert!(r == 0, ("Unexpected sfence encoding")); } #[no_mangle] pub unsafe fn instr_0FAE_7_mem(mut addr: i32) { @@ -3450,7 +3397,7 @@ pub unsafe fn instr_0FB0_reg(mut r1: i32, mut r2: i32) { #[no_mangle] pub unsafe fn instr_0FB0_mem(mut addr: i32, mut r: i32) { // cmpxchg8 - return_on_pagefault!(writable_or_pagefault(addr, 1i32)); + return_on_pagefault!(writable_or_pagefault(addr, 1)); let mut data: i32 = return_on_pagefault!(safe_read8(addr)); cmp8(*reg8.offset(AL as isize) as i32, data); if getzf() { @@ -3476,7 +3423,7 @@ pub unsafe fn instr16_0FB1_reg(mut r1: i32, mut r2: i32) { #[no_mangle] pub unsafe fn instr16_0FB1_mem(mut addr: i32, mut r: i32) { // cmpxchg16 - return_on_pagefault!(writable_or_pagefault(addr, 2i32)); + return_on_pagefault!(writable_or_pagefault(addr, 2)); let mut data: i32 = return_on_pagefault!(safe_read16(addr)); cmp16(*reg16.offset(AX as isize) as i32, data); if getzf() { @@ -3502,7 +3449,7 @@ pub unsafe fn instr32_0FB1_reg(mut r1: i32, mut r2: i32) { #[no_mangle] pub unsafe fn instr32_0FB1_mem(mut addr: i32, mut r: i32) { // cmpxchg32 - return_on_pagefault!(writable_or_pagefault(addr, 4i32)); + return_on_pagefault!(writable_or_pagefault(addr, 4)); let mut data: i32 = return_on_pagefault!(safe_read32s(addr)); cmp32(*reg32s.offset(EAX as isize), data); if getzf() { @@ -3523,15 +3470,15 @@ pub unsafe fn instr32_0FB2_reg(mut unused: i32, mut unused2: i32) { trigger_ud() pub unsafe fn instr32_0FB2_mem(mut addr: i32, mut r: i32) { lss32(addr, r, SS); } #[no_mangle] pub unsafe fn instr16_0FB3_reg(mut r1: i32, mut r2: i32) { - write_reg16(r1, btr_reg(read_reg16(r1), read_reg16(r2) & 15i32)); + write_reg16(r1, btr_reg(read_reg16(r1), read_reg16(r2) & 15)); } #[no_mangle] pub unsafe fn instr16_0FB3_mem(mut addr: i32, mut r: i32) { - btr_mem(addr, read_reg16(r) << 16i32 >> 16i32); + btr_mem(addr, read_reg16(r) << 16 >> 16); } #[no_mangle] pub unsafe fn instr32_0FB3_reg(mut r1: i32, mut r2: i32) { - write_reg32(r1, btr_reg(read_reg32(r1), read_reg32(r2) & 31i32)); + write_reg32(r1, btr_reg(read_reg32(r1), read_reg32(r2) & 31)); } #[no_mangle] pub unsafe fn instr32_0FB3_mem(mut addr: i32, mut r: i32) { btr_mem(addr, read_reg32(r)); } @@ -3625,60 +3572,60 @@ pub unsafe fn instr_0FB9() { trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_0FBA_4_reg(mut r: i32, mut imm: i32) { bt_reg(read_reg16(r), imm & 15i32); } +pub unsafe fn instr16_0FBA_4_reg(mut r: i32, mut imm: i32) { bt_reg(read_reg16(r), imm & 15); } #[no_mangle] -pub unsafe fn instr16_0FBA_4_mem(mut addr: i32, mut imm: i32) { bt_mem(addr, imm & 15i32); } +pub unsafe fn instr16_0FBA_4_mem(mut addr: i32, mut imm: i32) { bt_mem(addr, imm & 15); } #[no_mangle] pub unsafe fn instr16_0FBA_5_reg(mut r: i32, mut imm: i32) { - write_reg16(r, bts_reg(read_reg16(r), imm & 15i32)); + write_reg16(r, bts_reg(read_reg16(r), imm & 15)); } #[no_mangle] -pub unsafe fn instr16_0FBA_5_mem(mut addr: i32, mut imm: i32) { bts_mem(addr, imm & 15i32); } +pub unsafe fn instr16_0FBA_5_mem(mut addr: i32, mut imm: i32) { bts_mem(addr, imm & 15); } #[no_mangle] pub unsafe fn instr16_0FBA_6_reg(mut r: i32, mut imm: i32) { - write_reg16(r, btr_reg(read_reg16(r), imm & 15i32)); + write_reg16(r, btr_reg(read_reg16(r), imm & 15)); } #[no_mangle] -pub unsafe fn instr16_0FBA_6_mem(mut addr: i32, mut imm: i32) { btr_mem(addr, imm & 15i32); } +pub unsafe fn instr16_0FBA_6_mem(mut addr: i32, mut imm: i32) { btr_mem(addr, imm & 15); } #[no_mangle] pub unsafe fn instr16_0FBA_7_reg(mut r: i32, mut imm: i32) { - write_reg16(r, btc_reg(read_reg16(r), imm & 15i32)); + write_reg16(r, btc_reg(read_reg16(r), imm & 15)); } #[no_mangle] -pub unsafe fn instr16_0FBA_7_mem(mut addr: i32, mut imm: i32) { btc_mem(addr, imm & 15i32); } +pub unsafe fn instr16_0FBA_7_mem(mut addr: i32, mut imm: i32) { btc_mem(addr, imm & 15); } #[no_mangle] -pub unsafe fn instr32_0FBA_4_reg(mut r: i32, mut imm: i32) { bt_reg(read_reg32(r), imm & 31i32); } +pub unsafe fn instr32_0FBA_4_reg(mut r: i32, mut imm: i32) { bt_reg(read_reg32(r), imm & 31); } #[no_mangle] -pub unsafe fn instr32_0FBA_4_mem(mut addr: i32, mut imm: i32) { bt_mem(addr, imm & 31i32); } +pub unsafe fn instr32_0FBA_4_mem(mut addr: i32, mut imm: i32) { bt_mem(addr, imm & 31); } #[no_mangle] pub unsafe fn instr32_0FBA_5_reg(mut r: i32, mut imm: i32) { - write_reg32(r, bts_reg(read_reg32(r), imm & 31i32)); + write_reg32(r, bts_reg(read_reg32(r), imm & 31)); } #[no_mangle] -pub unsafe fn instr32_0FBA_5_mem(mut addr: i32, mut imm: i32) { bts_mem(addr, imm & 31i32); } +pub unsafe fn instr32_0FBA_5_mem(mut addr: i32, mut imm: i32) { bts_mem(addr, imm & 31); } #[no_mangle] pub unsafe fn instr32_0FBA_6_reg(mut r: i32, mut imm: i32) { - write_reg32(r, btr_reg(read_reg32(r), imm & 31i32)); + write_reg32(r, btr_reg(read_reg32(r), imm & 31)); } #[no_mangle] -pub unsafe fn instr32_0FBA_6_mem(mut addr: i32, mut imm: i32) { btr_mem(addr, imm & 31i32); } +pub unsafe fn instr32_0FBA_6_mem(mut addr: i32, mut imm: i32) { btr_mem(addr, imm & 31); } #[no_mangle] pub unsafe fn instr32_0FBA_7_reg(mut r: i32, mut imm: i32) { - write_reg32(r, btc_reg(read_reg32(r), imm & 31i32)); + write_reg32(r, btc_reg(read_reg32(r), imm & 31)); } #[no_mangle] -pub unsafe fn instr32_0FBA_7_mem(mut addr: i32, mut imm: i32) { btc_mem(addr, imm & 31i32); } +pub unsafe fn instr32_0FBA_7_mem(mut addr: i32, mut imm: i32) { btc_mem(addr, imm & 31); } #[no_mangle] pub unsafe fn instr16_0FBB_reg(mut r1: i32, mut r2: i32) { - write_reg16(r1, btc_reg(read_reg16(r1), read_reg16(r2) & 15i32)); + write_reg16(r1, btc_reg(read_reg16(r1), read_reg16(r2) & 15)); } #[no_mangle] pub unsafe fn instr16_0FBB_mem(mut addr: i32, mut r: i32) { - btc_mem(addr, read_reg16(r) << 16i32 >> 16i32); + btc_mem(addr, read_reg16(r) << 16 >> 16); } #[no_mangle] pub unsafe fn instr32_0FBB_reg(mut r1: i32, mut r2: i32) { - write_reg32(r1, btc_reg(read_reg32(r1), read_reg32(r2) & 31i32)); + write_reg32(r1, btc_reg(read_reg32(r1), read_reg32(r2) & 31)); } #[no_mangle] pub unsafe fn instr32_0FBB_mem(mut addr: i32, mut r: i32) { btc_mem(addr, read_reg32(r)); } @@ -3725,42 +3672,42 @@ pub unsafe fn instr32_0FBD_reg(mut r1: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr16_0FBE_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); - write_reg16(r, ____0 << 24i32 >> 24i32); + write_reg16(r, ____0 << 24 >> 24); } #[no_mangle] pub unsafe fn instr16_0FBE_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg16(r, ____0 << 24i32 >> 24i32); + write_reg16(r, ____0 << 24 >> 24); } #[no_mangle] pub unsafe fn instr32_0FBE_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); - write_reg32(r, ____0 << 24i32 >> 24i32); + write_reg32(r, ____0 << 24 >> 24); } #[no_mangle] pub unsafe fn instr32_0FBE_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg8(r1); - write_reg32(r, ____0 << 24i32 >> 24i32); + write_reg32(r, ____0 << 24 >> 24); } #[no_mangle] pub unsafe fn instr16_0FBF_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); - write_reg16(r, ____0 << 16i32 >> 16i32); + write_reg16(r, ____0 << 16 >> 16); } #[no_mangle] pub unsafe fn instr16_0FBF_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg16(r, ____0 << 16i32 >> 16i32); + write_reg16(r, ____0 << 16 >> 16); } #[no_mangle] pub unsafe fn instr32_0FBF_mem(mut addr: i32, mut r: i32) { let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); - write_reg32(r, ____0 << 16i32 >> 16i32); + write_reg32(r, ____0 << 16 >> 16); } #[no_mangle] pub unsafe fn instr32_0FBF_reg(mut r1: i32, mut r: i32) { let mut ____0: i32 = read_reg16(r1); - write_reg32(r, ____0 << 16i32 >> 16i32); + write_reg32(r, ____0 << 16 >> 16); } #[no_mangle] pub unsafe fn instr_0FC0_mem(mut addr: i32, mut r: i32) { @@ -3800,8 +3747,8 @@ pub unsafe fn instr_0FC3_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0FC4(mut source: i32, mut r: i32, mut imm8: i32) { // pinsrw mm, r32/m16, imm8 let mut destination: reg64 = read_mmx64s(r); - let mut index: u32 = (imm8 & 3i32) as u32; - destination.u16_0[index as usize] = (source & 65535i32) as u16; + let mut index: u32 = (imm8 & 3) as u32; + destination.u16_0[index as usize] = (source & 65535) as u16; write_mmx_reg64(r, destination); } #[no_mangle] @@ -3816,8 +3763,8 @@ pub unsafe fn instr_0FC4_mem(mut addr: i32, mut r: i32, mut imm: i32) { pub unsafe fn instr_660FC4(mut source: i32, mut r: i32, mut imm8: i32) { // pinsrw xmm, r32/m16, imm8 let mut destination: reg128 = read_xmm128s(r); - let mut index: u32 = (imm8 & 7i32) as u32; - destination.u16_0[index as usize] = (source & 65535i32) as u16; + let mut index: u32 = (imm8 & 7) as u32; + destination.u16_0[index as usize] = (source & 65535) as u16; write_xmm_reg128(r, destination); } #[no_mangle] @@ -3834,7 +3781,7 @@ pub unsafe fn instr_0FC5_mem(mut addr: i32, mut r: i32, mut imm8: i32) { trigger pub unsafe fn instr_0FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i32) { // pextrw r32, mm, imm8 let mut data: reg64 = read_mmx64s(r1); - let mut index: u32 = (imm8 & 3i32) as u32; + let mut index: u32 = (imm8 & 3) as u32; let mut result: u32 = data.u16_0[index as usize] as u32; write_reg32(r2, result as i32); } @@ -3844,7 +3791,7 @@ pub unsafe fn instr_660FC5_mem(mut addr: i32, mut r: i32, mut imm8: i32) { trigg pub unsafe fn instr_660FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i32) { // pextrw r32, xmm, imm8 let mut data: reg128 = read_xmm128s(r1); - let mut index: u32 = (imm8 & 7i32) as u32; + let mut index: u32 = (imm8 & 7) as u32; let mut result: u32 = data.u16_0[index as usize] as u32; write_reg32(r2, result as i32); } @@ -3856,10 +3803,10 @@ pub unsafe fn instr_0FC6(mut source: reg128, mut r: i32, mut imm8: i32) { let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, - destination.u32_0[(imm8 & 3i32) as usize] as i32, - destination.u32_0[(imm8 >> 2i32 & 3i32) as usize] as i32, - source.u32_0[(imm8 >> 4i32 & 3i32) as usize] as i32, - source.u32_0[(imm8 >> 6i32 & 3i32) as usize] as i32, + destination.u32_0[(imm8 & 3) as usize] as i32, + destination.u32_0[(imm8 >> 2 & 3) as usize] as i32, + source.u32_0[(imm8 >> 4 & 3) as usize] as i32, + source.u32_0[(imm8 >> 6 & 3) as usize] as i32, ); } #[no_mangle] @@ -3897,20 +3844,20 @@ pub unsafe fn instr_0FC7_1_reg(mut r: i32) { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0FC7_1_mem(mut addr: i32) { // cmpxchg8b - return_on_pagefault!(writable_or_pagefault(addr, 8i32)); + return_on_pagefault!(writable_or_pagefault(addr, 8)); let mut m64_low: i32 = return_on_pagefault!(safe_read32s(addr)); - let mut m64_high: i32 = return_on_pagefault!(safe_read32s(addr + 4i32)); + let mut m64_high: i32 = return_on_pagefault!(safe_read32s(addr + 4)); if *reg32s.offset(EAX as isize) == m64_low && *reg32s.offset(EDX as isize) == m64_high { *flags |= FLAG_ZERO; safe_write32(addr, *reg32s.offset(EBX as isize)).unwrap(); - safe_write32(addr + 4i32, *reg32s.offset(ECX as isize)).unwrap(); + safe_write32(addr + 4, *reg32s.offset(ECX as isize)).unwrap(); } else { *flags &= !FLAG_ZERO; *reg32s.offset(EAX as isize) = m64_low; *reg32s.offset(EDX as isize) = m64_high; safe_write32(addr, m64_low).unwrap(); - safe_write32(addr + 4i32, m64_high).unwrap(); + safe_write32(addr + 4, m64_high).unwrap(); } *flags_changed &= !FLAG_ZERO; } @@ -3918,14 +3865,14 @@ pub unsafe fn instr_0FC7_1_mem(mut addr: i32) { pub unsafe fn instr_0FC7_6_reg(mut r: i32) { // rdrand let mut has_rand: i32 = has_rand_int() as i32; - let mut rand: i32 = 0i32; + let mut rand: i32 = 0; if 0 != has_rand { rand = get_rand_int() } write_reg_osize(r, rand); *flags &= !FLAGS_ALL; *flags |= has_rand; - *flags_changed = 0i32; + *flags_changed = 0; } #[no_mangle] pub unsafe fn instr_0FC7_6_mem(mut addr: i32) { trigger_ud(); } @@ -3950,7 +3897,7 @@ pub unsafe fn instr_0FD0() { unimplemented_sse(); } #[no_mangle] pub unsafe fn instr_0FD1(mut source: reg64, mut r: i32) { // psrlw mm, mm/m64 - psrlw_r64(r, source.u32_0[0usize]); + psrlw_r64(r, source.u32_0[0]); } #[no_mangle] pub unsafe fn instr_0FD1_reg(mut r1: i32, mut r2: i32) { instr_0FD1(read_mmx64s(r1), r2); } @@ -3962,7 +3909,7 @@ pub unsafe fn instr_0FD1_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_660FD1(mut source: reg128, mut r: i32) { // psrlw xmm, xmm/m128 // XXX: Aligned access or #gp - psrlw_r128(r, source.u32_0[0usize]); + psrlw_r128(r, source.u32_0[0]); } #[no_mangle] pub unsafe fn instr_660FD1_reg(mut r1: i32, mut r2: i32) { instr_660FD1(read_xmm128s(r1), r2); } @@ -3973,7 +3920,7 @@ pub unsafe fn instr_660FD1_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_0FD2(mut source: reg64, mut r: i32) { // psrld mm, mm/m64 - psrld_r64(r, source.u32_0[0usize]); + psrld_r64(r, source.u32_0[0]); } #[no_mangle] pub unsafe fn instr_0FD2_reg(mut r1: i32, mut r2: i32) { instr_0FD2(read_mmx64s(r1), r2); } @@ -3985,7 +3932,7 @@ pub unsafe fn instr_0FD2_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_660FD2(mut source: reg128, mut r: i32) { // psrld xmm, xmm/m128 // XXX: Aligned access or #gp - psrld_r128(r, source.u32_0[0usize]); + psrld_r128(r, source.u32_0[0]); } #[no_mangle] pub unsafe fn instr_660FD2_reg(mut r1: i32, mut r2: i32) { instr_660FD2(read_xmm128s(r1), r2); } @@ -3996,7 +3943,7 @@ pub unsafe fn instr_660FD2_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_0FD3(mut source: reg64, mut r: i32) { // psrlq mm, mm/m64 - psrlq_r64(r, source.u32_0[0usize]); + psrlq_r64(r, source.u32_0[0]); } #[no_mangle] pub unsafe fn instr_0FD3_reg(mut r1: i32, mut r2: i32) { instr_0FD3(read_mmx64s(r1), r2); } @@ -4007,7 +3954,7 @@ pub unsafe fn instr_0FD3_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_660FD3(mut source: reg128, mut r: i32) { // psrlq xmm, mm/m64 - psrlq_r128(r, source.u32_0[0usize]); + psrlq_r128(r, source.u32_0[0]); } #[no_mangle] pub unsafe fn instr_660FD3_reg(mut r1: i32, mut r2: i32) { instr_660FD3(read_xmm128s(r1), r2); } @@ -4019,8 +3966,8 @@ pub unsafe fn instr_660FD3_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0FD4(mut source: reg64, mut r: i32) { // paddq mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - destination.u64_0[0usize] = - (destination.u64_0[0usize] as u64).wrapping_add(source.u64_0[0usize]) as u64 as u64; + destination.u64_0[0] = + (destination.u64_0[0] as u64).wrapping_add(source.u64_0[0]) as u64 as u64; write_mmx_reg64(r, destination); } #[no_mangle] @@ -4034,10 +3981,10 @@ pub unsafe fn instr_660FD4(mut source: reg128, mut r: i32) { // paddq xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); - destination.u64_0[0usize] = - (destination.u64_0[0usize] as u64).wrapping_add(source.u64_0[0usize]) as u64 as u64; - destination.u64_0[1usize] = - (destination.u64_0[1usize] as u64).wrapping_add(source.u64_0[1usize]) as u64 as u64; + destination.u64_0[0] = + (destination.u64_0[0] as u64).wrapping_add(source.u64_0[0]) as u64 as u64; + destination.u64_0[1] = + (destination.u64_0[1] as u64).wrapping_add(source.u64_0[1]) as u64 as u64; write_xmm_reg128(r, destination); } #[no_mangle] @@ -4050,12 +3997,12 @@ pub unsafe fn instr_660FD4_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0FD5(mut source: reg64, mut r: i32) { // pmullw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - let mut word0: i32 = destination.u16_0[0usize] as i32 * source.u16_0[0usize] as i32 & 65535i32; - let mut word1: i32 = destination.u16_0[1usize] as i32 * source.u16_0[1usize] as i32 & 65535i32; - let mut word2: i32 = destination.u16_0[2usize] as i32 * source.u16_0[2usize] as i32 & 65535i32; - let mut word3: i32 = destination.u16_0[3usize] as i32 * source.u16_0[3usize] as i32 & 65535i32; - let mut low: i32 = word0 | word1 << 16i32; - let mut high: i32 = word2 | word3 << 16i32; + let mut word0: i32 = destination.u16_0[0] as i32 * source.u16_0[0] as i32 & 65535; + let mut word1: i32 = destination.u16_0[1] as i32 * source.u16_0[1] as i32 & 65535; + let mut word2: i32 = destination.u16_0[2] as i32 * source.u16_0[2] as i32 & 65535; + let mut word3: i32 = destination.u16_0[3] as i32 * source.u16_0[3] as i32 & 65535; + let mut low: i32 = word0 | word1 << 16; + let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); } #[no_mangle] @@ -4071,14 +4018,14 @@ pub unsafe fn instr_660FD5(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, - source.u16_0[0usize] as i32 * destination.u16_0[0usize] as i32 & 65535i32 - | (source.u16_0[1usize] as i32 * destination.u16_0[1usize] as i32) << 16i32, - source.u16_0[2usize] as i32 * destination.u16_0[2usize] as i32 & 65535i32 - | (source.u16_0[3usize] as i32 * destination.u16_0[3usize] as i32) << 16i32, - source.u16_0[4usize] as i32 * destination.u16_0[4usize] as i32 & 65535i32 - | (source.u16_0[5usize] as i32 * destination.u16_0[5usize] as i32) << 16i32, - source.u16_0[6usize] as i32 * destination.u16_0[6usize] as i32 & 65535i32 - | (source.u16_0[7usize] as i32 * destination.u16_0[7usize] as i32) << 16i32, + source.u16_0[0] as i32 * destination.u16_0[0] as i32 & 65535 + | (source.u16_0[1] as i32 * destination.u16_0[1] as i32) << 16, + source.u16_0[2] as i32 * destination.u16_0[2] as i32 & 65535 + | (source.u16_0[3] as i32 * destination.u16_0[3] as i32) << 16, + source.u16_0[4] as i32 * destination.u16_0[4] as i32 & 65535 + | (source.u16_0[5] as i32 * destination.u16_0[5] as i32) << 16, + source.u16_0[6] as i32 * destination.u16_0[6] as i32 & 65535 + | (source.u16_0[7] as i32 * destination.u16_0[7] as i32) << 16, ); } #[no_mangle] @@ -4100,13 +4047,7 @@ pub unsafe fn instr_660FD6_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_660FD6_reg(mut r1: i32, mut r2: i32) { // movq xmm/m64, xmm let mut data: reg64 = read_xmm64s(r2); - write_xmm128( - r1, - data.u32_0[0usize] as i32, - data.u32_0[1usize] as i32, - 0i32, - 0i32, - ); + write_xmm128(r1, data.u32_0[0] as i32, data.u32_0[1] as i32, 0, 0); } #[no_mangle] pub unsafe fn instr_F20FD6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } @@ -4114,7 +4055,7 @@ pub unsafe fn instr_F20FD6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } pub unsafe fn instr_F20FD6_reg(mut r1: i32, mut r2: i32) { // movdq2q mm, xmm let mut source: reg128 = read_xmm128s(r1); - write_mmx64(r2, source.u32_0[0usize] as i32, source.u32_0[1usize] as i32); + write_mmx64(r2, source.u32_0[0] as i32, source.u32_0[1] as i32); } #[no_mangle] pub unsafe fn instr_F30FD6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } @@ -4122,13 +4063,7 @@ pub unsafe fn instr_F30FD6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } pub unsafe fn instr_F30FD6_reg(mut r1: i32, mut r2: i32) { // movq2dq xmm, mm let mut source: reg64 = read_mmx64s(r1); - write_xmm128( - r2, - source.u32_0[0usize] as i32, - source.u32_0[1usize] as i32, - 0i32, - 0i32, - ); + write_xmm128(r2, source.u32_0[0] as i32, source.u32_0[1] as i32, 0, 0); } #[no_mangle] pub unsafe fn instr_0FD7_mem(mut addr: i32, mut r: i32) { trigger_ud(); } @@ -4136,14 +4071,14 @@ pub unsafe fn instr_0FD7_mem(mut addr: i32, mut r: i32) { trigger_ud(); } pub unsafe fn instr_0FD7_reg(mut r1: i32, mut r2: i32) { // pmovmskb r, mm let mut x: reg64 = read_mmx64s(r1); - let mut result: u32 = (x.u8_0[0usize] as i32 >> 7i32 << 0i32 - | x.u8_0[1usize] as i32 >> 7i32 << 1i32 - | x.u8_0[2usize] as i32 >> 7i32 << 2i32 - | x.u8_0[3usize] as i32 >> 7i32 << 3i32 - | x.u8_0[4usize] as i32 >> 7i32 << 4i32 - | x.u8_0[5usize] as i32 >> 7i32 << 5i32 - | x.u8_0[6usize] as i32 >> 7i32 << 6i32 - | x.u8_0[7usize] as i32 >> 7i32 << 7i32) as u32; + let mut result: u32 = (x.u8_0[0] as i32 >> 7 << 0 + | x.u8_0[1] as i32 >> 7 << 1 + | x.u8_0[2] as i32 >> 7 << 2 + | x.u8_0[3] as i32 >> 7 << 3 + | x.u8_0[4] as i32 >> 7 << 4 + | x.u8_0[5] as i32 >> 7 << 5 + | x.u8_0[6] as i32 >> 7 << 6 + | x.u8_0[7] as i32 >> 7 << 7) as u32; write_reg32(r2, result as i32); } #[no_mangle] @@ -4152,22 +4087,22 @@ pub unsafe fn instr_660FD7_mem(mut addr: i32, mut r: i32) { trigger_ud(); } pub unsafe fn instr_660FD7_reg(mut r1: i32, mut r2: i32) { // pmovmskb reg, xmm let mut x: reg128 = read_xmm128s(r1); - let mut result: i32 = x.u8_0[0usize] as i32 >> 7i32 << 0i32 - | x.u8_0[1usize] as i32 >> 7i32 << 1i32 - | x.u8_0[2usize] as i32 >> 7i32 << 2i32 - | x.u8_0[3usize] as i32 >> 7i32 << 3i32 - | x.u8_0[4usize] as i32 >> 7i32 << 4i32 - | x.u8_0[5usize] as i32 >> 7i32 << 5i32 - | x.u8_0[6usize] as i32 >> 7i32 << 6i32 - | x.u8_0[7usize] as i32 >> 7i32 << 7i32 - | x.u8_0[8usize] as i32 >> 7i32 << 8i32 - | x.u8_0[9usize] as i32 >> 7i32 << 9i32 - | x.u8_0[10usize] as i32 >> 7i32 << 10i32 - | x.u8_0[11usize] as i32 >> 7i32 << 11i32 - | x.u8_0[12usize] as i32 >> 7i32 << 12i32 - | x.u8_0[13usize] as i32 >> 7i32 << 13i32 - | x.u8_0[14usize] as i32 >> 7i32 << 14i32 - | x.u8_0[15usize] as i32 >> 7i32 << 15i32; + let mut result: i32 = x.u8_0[0] as i32 >> 7 << 0 + | x.u8_0[1] as i32 >> 7 << 1 + | x.u8_0[2] as i32 >> 7 << 2 + | x.u8_0[3] as i32 >> 7 << 3 + | x.u8_0[4] as i32 >> 7 << 4 + | x.u8_0[5] as i32 >> 7 << 5 + | x.u8_0[6] as i32 >> 7 << 6 + | x.u8_0[7] as i32 >> 7 << 7 + | x.u8_0[8] as i32 >> 7 << 8 + | x.u8_0[9] as i32 >> 7 << 9 + | x.u8_0[10] as i32 >> 7 << 10 + | x.u8_0[11] as i32 >> 7 << 11 + | x.u8_0[12] as i32 >> 7 << 12 + | x.u8_0[13] as i32 >> 7 << 13 + | x.u8_0[14] as i32 >> 7 << 14 + | x.u8_0[15] as i32 >> 7 << 15; write_reg32(r2, result); } #[no_mangle] @@ -4175,10 +4110,10 @@ pub unsafe fn instr_0FD8(mut source: reg64, mut r: i32) { // psubusb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0i32 as u32; - while i < 8i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 8 as u32 { result.u8_0[i as usize] = saturate_sd_to_ub(destination.u8_0[i as usize] as i32 - source.u8_0[i as usize] as i32) as u8; @@ -4197,8 +4132,8 @@ pub unsafe fn instr_660FD8(mut source: reg128, mut r: i32) { // psubusb xmm, xmm/m128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: u32 = 0i32 as u32; - while i < 16i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 16 as u32 { result.u8_0[i as usize] = saturate_sd_to_ub(destination.u8_0[i as usize] as i32 - source.u8_0[i as usize] as i32) as u8; @@ -4216,16 +4151,12 @@ pub unsafe fn instr_660FD8_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0FD9(mut source: reg64, mut r: i32) { // psubusw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - let mut word0: i32 = - saturate_uw((destination.u16_0[0usize] as i32 - source.u16_0[0usize] as i32) as u32); - let mut word1: i32 = - saturate_uw((destination.u16_0[1usize] as i32 - source.u16_0[1usize] as i32) as u32); - let mut word2: i32 = - saturate_uw((destination.u16_0[2usize] as i32 - source.u16_0[2usize] as i32) as u32); - let mut word3: i32 = - saturate_uw((destination.u16_0[3usize] as i32 - source.u16_0[3usize] as i32) as u32); - let mut low: i32 = word0 | word1 << 16i32; - let mut high: i32 = word2 | word3 << 16i32; + let mut word0: i32 = saturate_uw((destination.u16_0[0] as i32 - source.u16_0[0] as i32) as u32); + let mut word1: i32 = saturate_uw((destination.u16_0[1] as i32 - source.u16_0[1] as i32) as u32); + let mut word2: i32 = saturate_uw((destination.u16_0[2] as i32 - source.u16_0[2] as i32) as u32); + let mut word3: i32 = saturate_uw((destination.u16_0[3] as i32 - source.u16_0[3] as i32) as u32); + let mut low: i32 = word0 | word1 << 16; + let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); } #[no_mangle] @@ -4239,8 +4170,8 @@ pub unsafe fn instr_660FD9(mut source: reg128, mut r: i32) { // psubusw xmm, xmm/m128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: u32 = 0i32 as u32; - while i < 8i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 8 as u32 { result.u16_0[i as usize] = saturate_uw( (destination.u16_0[i as usize] as i32 - source.u16_0[i as usize] as i32) as u32, ) as u16; @@ -4259,8 +4190,8 @@ pub unsafe fn instr_0FDA(mut source: reg64, mut r: i32) { // pminub mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; - let mut i: u32 = 0i32 as u32; - while i < 8i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 8 as u32 { result.u8_0[i as usize] = (if (source.u8_0[i as usize] as i32) < destination.u8_0[i as usize] as i32 { source.u8_0[i as usize] as i32 @@ -4284,8 +4215,8 @@ pub unsafe fn instr_660FDA(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: u32 = 0i32 as u32; - while i < 16i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 16 as u32 { result.u8_0[i as usize] = (if (source.u8_0[i as usize] as i32) < destination.u8_0[i as usize] as i32 { source.u8_0[i as usize] as i32 @@ -4308,9 +4239,9 @@ pub unsafe fn instr_0FDB(mut source: reg64, mut r: i32) { // pand mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - result.u64_0[0usize] = source.u64_0[0usize] & destination.u64_0[0usize]; + result.u64_0[0] = source.u64_0[0] & destination.u64_0[0]; write_mmx_reg64(r, result); } #[no_mangle] @@ -4336,10 +4267,10 @@ pub unsafe fn instr_0FDC(mut source: reg64, mut r: i32) { // paddusb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0i32 as u32; - while i < 8i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 8 as u32 { result.u8_0[i as usize] = saturate_ud_to_ub( (destination.u8_0[i as usize] as i32 + source.u8_0[i as usize] as i32) as u32, ) as u8; @@ -4359,8 +4290,8 @@ pub unsafe fn instr_660FDC(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: u32 = 0i32 as u32; - while i < 16i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 16 as u32 { result.u8_0[i as usize] = saturate_ud_to_ub( (source.u8_0[i as usize] as i32 + destination.u8_0[i as usize] as i32) as u32, ) as u8; @@ -4378,16 +4309,12 @@ pub unsafe fn instr_660FDC_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0FDD(mut source: reg64, mut r: i32) { // paddusw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - let mut word0: i32 = - saturate_uw((destination.u16_0[0usize] as i32 + source.u16_0[0usize] as i32) as u32); - let mut word1: i32 = - saturate_uw((destination.u16_0[1usize] as i32 + source.u16_0[1usize] as i32) as u32); - let mut word2: i32 = - saturate_uw((destination.u16_0[2usize] as i32 + source.u16_0[2usize] as i32) as u32); - let mut word3: i32 = - saturate_uw((destination.u16_0[3usize] as i32 + source.u16_0[3usize] as i32) as u32); - let mut low: i32 = word0 | word1 << 16i32; - let mut high: i32 = word2 | word3 << 16i32; + let mut word0: i32 = saturate_uw((destination.u16_0[0] as i32 + source.u16_0[0] as i32) as u32); + let mut word1: i32 = saturate_uw((destination.u16_0[1] as i32 + source.u16_0[1] as i32) as u32); + let mut word2: i32 = saturate_uw((destination.u16_0[2] as i32 + source.u16_0[2] as i32) as u32); + let mut word3: i32 = saturate_uw((destination.u16_0[3] as i32 + source.u16_0[3] as i32) as u32); + let mut low: i32 = word0 | word1 << 16; + let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); } #[no_mangle] @@ -4403,18 +4330,14 @@ pub unsafe fn instr_660FDD(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, - saturate_uw((source.u16_0[0usize] as i32 + destination.u16_0[0usize] as i32) as u32) - | saturate_uw((source.u16_0[1usize] as i32 + destination.u16_0[1usize] as i32) as u32) - << 16i32, - saturate_uw((source.u16_0[2usize] as i32 + destination.u16_0[2usize] as i32) as u32) - | saturate_uw((source.u16_0[3usize] as i32 + destination.u16_0[3usize] as i32) as u32) - << 16i32, - saturate_uw((source.u16_0[4usize] as i32 + destination.u16_0[4usize] as i32) as u32) - | saturate_uw((source.u16_0[5usize] as i32 + destination.u16_0[5usize] as i32) as u32) - << 16i32, - saturate_uw((source.u16_0[6usize] as i32 + destination.u16_0[6usize] as i32) as u32) - | saturate_uw((source.u16_0[7usize] as i32 + destination.u16_0[7usize] as i32) as u32) - << 16i32, + saturate_uw((source.u16_0[0] as i32 + destination.u16_0[0] as i32) as u32) + | saturate_uw((source.u16_0[1] as i32 + destination.u16_0[1] as i32) as u32) << 16, + saturate_uw((source.u16_0[2] as i32 + destination.u16_0[2] as i32) as u32) + | saturate_uw((source.u16_0[3] as i32 + destination.u16_0[3] as i32) as u32) << 16, + saturate_uw((source.u16_0[4] as i32 + destination.u16_0[4] as i32) as u32) + | saturate_uw((source.u16_0[5] as i32 + destination.u16_0[5] as i32) as u32) << 16, + saturate_uw((source.u16_0[6] as i32 + destination.u16_0[6] as i32) as u32) + | saturate_uw((source.u16_0[7] as i32 + destination.u16_0[7] as i32) as u32) << 16, ); } #[no_mangle] @@ -4428,8 +4351,8 @@ pub unsafe fn instr_0FDE(mut source: reg64, mut r: i32) { // pmaxub mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; - let mut i: u32 = 0i32 as u32; - while i < 8i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 8 as u32 { result.u8_0[i as usize] = (if source.u8_0[i as usize] as i32 > destination.u8_0[i as usize] as i32 { source.u8_0[i as usize] as i32 @@ -4453,8 +4376,8 @@ pub unsafe fn instr_660FDE(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: u32 = 0i32 as u32; - while i < 16i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 16 as u32 { result.u8_0[i as usize] = (if source.u8_0[i as usize] as i32 > destination.u8_0[i as usize] as i32 { source.u8_0[i as usize] as i32 @@ -4477,9 +4400,9 @@ pub unsafe fn instr_0FDF(mut source: reg64, mut r: i32) { // pandn mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - result.u64_0[0usize] = source.u64_0[0usize] & !destination.u64_0[0usize]; + result.u64_0[0] = source.u64_0[0] & !destination.u64_0[0]; write_mmx_reg64(r, result); } #[no_mangle] @@ -4505,13 +4428,12 @@ pub unsafe fn instr_0FE0(mut source: reg64, mut r: i32) { // pavgb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0i32 as u32; - while i < 8i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 8 as u32 { result.u8_0[i as usize] = - (destination.u8_0[i as usize] as i32 + source.u8_0[i as usize] as i32 + 1i32 >> 1i32) - as u8; + (destination.u8_0[i as usize] as i32 + source.u8_0[i as usize] as i32 + 1 >> 1) as u8; i = i.wrapping_add(1) } write_mmx_reg64(r, result); @@ -4528,11 +4450,10 @@ pub unsafe fn instr_660FE0(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: u32 = 0i32 as u32; - while i < 16i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 16 as u32 { result.u8_0[i as usize] = - (destination.u8_0[i as usize] as i32 + source.u8_0[i as usize] as i32 + 1i32 >> 1i32) - as u8; + (destination.u8_0[i as usize] as i32 + source.u8_0[i as usize] as i32 + 1 >> 1) as u8; i = i.wrapping_add(1) } write_xmm_reg128(r, result); @@ -4546,7 +4467,7 @@ pub unsafe fn instr_660FE0_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_0FE1(mut source: reg64, mut r: i32) { // psraw mm, mm/m64 - psraw_r64(r, source.u32_0[0usize]); + psraw_r64(r, source.u32_0[0]); } #[no_mangle] pub unsafe fn instr_0FE1_reg(mut r1: i32, mut r2: i32) { instr_0FE1(read_mmx64s(r1), r2); } @@ -4558,7 +4479,7 @@ pub unsafe fn instr_0FE1_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_660FE1(mut source: reg128, mut r: i32) { // psraw xmm, xmm/m128 // XXX: Aligned access or #gp - psraw_r128(r, source.u32_0[0usize]); + psraw_r128(r, source.u32_0[0]); } #[no_mangle] pub unsafe fn instr_660FE1_reg(mut r1: i32, mut r2: i32) { instr_660FE1(read_xmm128s(r1), r2); } @@ -4569,7 +4490,7 @@ pub unsafe fn instr_660FE1_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_0FE2(mut source: reg64, mut r: i32) { // psrad mm, mm/m64 - psrad_r64(r, source.u32_0[0usize]); + psrad_r64(r, source.u32_0[0]); } #[no_mangle] pub unsafe fn instr_0FE2_reg(mut r1: i32, mut r2: i32) { instr_0FE2(read_mmx64s(r1), r2); } @@ -4581,7 +4502,7 @@ pub unsafe fn instr_0FE2_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_660FE2(mut source: reg128, mut r: i32) { // psrad xmm, xmm/m128 // XXX: Aligned access or #gp - psrad_r128(r, source.u32_0[0usize]); + psrad_r128(r, source.u32_0[0]); } #[no_mangle] pub unsafe fn instr_660FE2_reg(mut r1: i32, mut r2: i32) { instr_660FE2(read_xmm128s(r1), r2); } @@ -4593,14 +4514,10 @@ pub unsafe fn instr_660FE2_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0FE3(mut source: reg64, mut r: i32) { // pavgw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - destination.u16_0[0usize] = - (destination.u16_0[0usize] as i32 + source.u16_0[0usize] as i32 + 1i32 >> 1i32) as u16; - destination.u16_0[1usize] = - (destination.u16_0[1usize] as i32 + source.u16_0[1usize] as i32 + 1i32 >> 1i32) as u16; - destination.u16_0[2usize] = - (destination.u16_0[2usize] as i32 + source.u16_0[2usize] as i32 + 1i32 >> 1i32) as u16; - destination.u16_0[3usize] = - (destination.u16_0[3usize] as i32 + source.u16_0[3usize] as i32 + 1i32 >> 1i32) as u16; + destination.u16_0[0] = (destination.u16_0[0] as i32 + source.u16_0[0] as i32 + 1 >> 1) as u16; + destination.u16_0[1] = (destination.u16_0[1] as i32 + source.u16_0[1] as i32 + 1 >> 1) as u16; + destination.u16_0[2] = (destination.u16_0[2] as i32 + source.u16_0[2] as i32 + 1 >> 1) as u16; + destination.u16_0[3] = (destination.u16_0[3] as i32 + source.u16_0[3] as i32 + 1 >> 1) as u16; write_mmx_reg64(r, destination); } #[no_mangle] @@ -4614,22 +4531,14 @@ pub unsafe fn instr_660FE3(mut source: reg128, mut r: i32) { // pavgw xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); - destination.u16_0[0usize] = - (destination.u16_0[0usize] as i32 + source.u16_0[0usize] as i32 + 1i32 >> 1i32) as u16; - destination.u16_0[1usize] = - (destination.u16_0[1usize] as i32 + source.u16_0[1usize] as i32 + 1i32 >> 1i32) as u16; - destination.u16_0[2usize] = - (destination.u16_0[2usize] as i32 + source.u16_0[2usize] as i32 + 1i32 >> 1i32) as u16; - destination.u16_0[3usize] = - (destination.u16_0[3usize] as i32 + source.u16_0[3usize] as i32 + 1i32 >> 1i32) as u16; - destination.u16_0[4usize] = - (destination.u16_0[4usize] as i32 + source.u16_0[4usize] as i32 + 1i32 >> 1i32) as u16; - destination.u16_0[5usize] = - (destination.u16_0[5usize] as i32 + source.u16_0[5usize] as i32 + 1i32 >> 1i32) as u16; - destination.u16_0[6usize] = - (destination.u16_0[6usize] as i32 + source.u16_0[6usize] as i32 + 1i32 >> 1i32) as u16; - destination.u16_0[7usize] = - (destination.u16_0[7usize] as i32 + source.u16_0[7usize] as i32 + 1i32 >> 1i32) as u16; + destination.u16_0[0] = (destination.u16_0[0] as i32 + source.u16_0[0] as i32 + 1 >> 1) as u16; + destination.u16_0[1] = (destination.u16_0[1] as i32 + source.u16_0[1] as i32 + 1 >> 1) as u16; + destination.u16_0[2] = (destination.u16_0[2] as i32 + source.u16_0[2] as i32 + 1 >> 1) as u16; + destination.u16_0[3] = (destination.u16_0[3] as i32 + source.u16_0[3] as i32 + 1 >> 1) as u16; + destination.u16_0[4] = (destination.u16_0[4] as i32 + source.u16_0[4] as i32 + 1 >> 1) as u16; + destination.u16_0[5] = (destination.u16_0[5] as i32 + source.u16_0[5] as i32 + 1 >> 1) as u16; + destination.u16_0[6] = (destination.u16_0[6] as i32 + source.u16_0[6] as i32 + 1 >> 1) as u16; + destination.u16_0[7] = (destination.u16_0[7] as i32 + source.u16_0[7] as i32 + 1 >> 1) as u16; write_xmm_reg128(r, destination); } #[no_mangle] @@ -4644,14 +4553,12 @@ pub unsafe fn instr_0FE4(mut source: reg64, mut r: i32) { let mut destination: reg64 = read_mmx64s(r); write_mmx64( r, - ((source.u16_0[0usize] as i32 * destination.u16_0[0usize] as i32 >> 16i32 & 65535i32) - as u32 - | (source.u16_0[1usize] as i32 * destination.u16_0[1usize] as i32) as u32 - & 4294901760u32) as i32, - ((source.u16_0[2usize] as i32 * destination.u16_0[2usize] as i32 >> 16i32 & 65535i32) - as u32 - | (source.u16_0[3usize] as i32 * destination.u16_0[3usize] as i32) as u32 - & 4294901760u32) as i32, + ((source.u16_0[0] as i32 * destination.u16_0[0] as i32 >> 16 & 65535) as u32 + | (source.u16_0[1] as i32 * destination.u16_0[1] as i32) as u32 & 4294901760) + as i32, + ((source.u16_0[2] as i32 * destination.u16_0[2] as i32 >> 16 & 65535) as u32 + | (source.u16_0[3] as i32 * destination.u16_0[3] as i32) as u32 & 4294901760) + as i32, ); } #[no_mangle] @@ -4667,22 +4574,18 @@ pub unsafe fn instr_660FE4(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, - ((source.u16_0[0usize] as i32 * destination.u16_0[0usize] as i32 >> 16i32 & 65535i32) - as u32 - | (source.u16_0[1usize] as i32 * destination.u16_0[1usize] as i32) as u32 - & 4294901760u32) as i32, - ((source.u16_0[2usize] as i32 * destination.u16_0[2usize] as i32 >> 16i32 & 65535i32) - as u32 - | (source.u16_0[3usize] as i32 * destination.u16_0[3usize] as i32) as u32 - & 4294901760u32) as i32, - ((source.u16_0[4usize] as i32 * destination.u16_0[4usize] as i32 >> 16i32 & 65535i32) - as u32 - | (source.u16_0[5usize] as i32 * destination.u16_0[5usize] as i32) as u32 - & 4294901760u32) as i32, - ((source.u16_0[6usize] as i32 * destination.u16_0[6usize] as i32 >> 16i32 & 65535i32) - as u32 - | (source.u16_0[7usize] as i32 * destination.u16_0[7usize] as i32) as u32 - & 4294901760u32) as i32, + ((source.u16_0[0] as i32 * destination.u16_0[0] as i32 >> 16 & 65535) as u32 + | (source.u16_0[1] as i32 * destination.u16_0[1] as i32) as u32 & 4294901760) + as i32, + ((source.u16_0[2] as i32 * destination.u16_0[2] as i32 >> 16 & 65535) as u32 + | (source.u16_0[3] as i32 * destination.u16_0[3] as i32) as u32 & 4294901760) + as i32, + ((source.u16_0[4] as i32 * destination.u16_0[4] as i32 >> 16 & 65535) as u32 + | (source.u16_0[5] as i32 * destination.u16_0[5] as i32) as u32 & 4294901760) + as i32, + ((source.u16_0[6] as i32 * destination.u16_0[6] as i32 >> 16 & 65535) as u32 + | (source.u16_0[7] as i32 * destination.u16_0[7] as i32) as u32 & 4294901760) + as i32, ); } #[no_mangle] @@ -4696,15 +4599,15 @@ pub unsafe fn instr_0FE5(mut source: reg64, mut r: i32) { // pmulhw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: u32 = - (destination.i16_0[0usize] as i32 * source.i16_0[0usize] as i32 >> 16i32 & 65535i32) as u32; + (destination.i16_0[0] as i32 * source.i16_0[0] as i32 >> 16 & 65535) as u32; let mut word1: u32 = - (destination.i16_0[1usize] as i32 * source.i16_0[1usize] as i32 >> 16i32 & 65535i32) as u32; + (destination.i16_0[1] as i32 * source.i16_0[1] as i32 >> 16 & 65535) as u32; let mut word2: u32 = - (destination.i16_0[2usize] as i32 * source.i16_0[2usize] as i32 >> 16i32 & 65535i32) as u32; + (destination.i16_0[2] as i32 * source.i16_0[2] as i32 >> 16 & 65535) as u32; let mut word3: u32 = - (destination.i16_0[3usize] as i32 * source.i16_0[3usize] as i32 >> 16i32 & 65535i32) as u32; - let mut low: i32 = (word0 | word1 << 16i32) as i32; - let mut high: i32 = (word2 | word3 << 16i32) as i32; + (destination.i16_0[3] as i32 * source.i16_0[3] as i32 >> 16 & 65535) as u32; + let mut low: i32 = (word0 | word1 << 16) as i32; + let mut high: i32 = (word2 | word3 << 16) as i32; write_mmx64(r, low, high); } #[no_mangle] @@ -4718,21 +4621,21 @@ pub unsafe fn instr_660FE5(mut source: reg128, mut r: i32) { // pmulhw xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); - let mut dword0: i32 = ((destination.i16_0[0usize] as i32 * source.i16_0[0usize] as i32 >> 16i32 - & 65535i32) as u32 - | (destination.i16_0[1usize] as i32 * source.i16_0[1usize] as i32) as u32 & 4294901760u32) + let mut dword0: i32 = ((destination.i16_0[0] as i32 * source.i16_0[0] as i32 >> 16 & 65535) + as u32 + | (destination.i16_0[1] as i32 * source.i16_0[1] as i32) as u32 & 4294901760) as i32; - let mut dword1: i32 = ((destination.i16_0[2usize] as i32 * source.i16_0[2usize] as i32 >> 16i32 - & 65535i32) as u32 - | (destination.i16_0[3usize] as i32 * source.i16_0[3usize] as i32) as u32 & 4294901760u32) + let mut dword1: i32 = ((destination.i16_0[2] as i32 * source.i16_0[2] as i32 >> 16 & 65535) + as u32 + | (destination.i16_0[3] as i32 * source.i16_0[3] as i32) as u32 & 4294901760) as i32; - let mut dword2: i32 = ((destination.i16_0[4usize] as i32 * source.i16_0[4usize] as i32 >> 16i32 - & 65535i32) as u32 - | (destination.i16_0[5usize] as i32 * source.i16_0[5usize] as i32) as u32 & 4294901760u32) + let mut dword2: i32 = ((destination.i16_0[4] as i32 * source.i16_0[4] as i32 >> 16 & 65535) + as u32 + | (destination.i16_0[5] as i32 * source.i16_0[5] as i32) as u32 & 4294901760) as i32; - let mut dword3: i32 = ((destination.i16_0[6usize] as i32 * source.i16_0[6usize] as i32 >> 16i32 - & 65535i32) as u32 - | (destination.i16_0[7usize] as i32 * source.i16_0[7usize] as i32) as u32 & 4294901760u32) + let mut dword3: i32 = ((destination.i16_0[6] as i32 * source.i16_0[6] as i32 >> 16 & 65535) + as u32 + | (destination.i16_0[7] as i32 * source.i16_0[7] as i32) as u32 & 4294901760) as i32; write_xmm128(r, dword0, dword1, dword2, dword3); } @@ -4827,10 +4730,10 @@ pub unsafe fn instr_0FE8(mut source: reg64, mut r: i32) { // psubsb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0i32 as u32; - while i < 8i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 8 as u32 { result.u8_0[i as usize] = saturate_sd_to_sb( (destination.i8_0[i as usize] as i32 - source.i8_0[i as usize] as i32) as u32, ) as u8; @@ -4850,8 +4753,8 @@ pub unsafe fn instr_660FE8(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: u32 = 0i32 as u32; - while i < 16i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 16 as u32 { result.i8_0[i as usize] = saturate_sd_to_sb( (destination.i8_0[i as usize] as i32 - source.i8_0[i as usize] as i32) as u32, ) as i8; @@ -4870,19 +4773,15 @@ pub unsafe fn instr_0FE9(mut source: reg64, mut r: i32) { // psubsw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = - saturate_sd_to_sw((destination.i16_0[0usize] as i32 - source.i16_0[0usize] as i32) as u32) - as i32; + saturate_sd_to_sw((destination.i16_0[0] as i32 - source.i16_0[0] as i32) as u32) as i32; let mut word1: i32 = - saturate_sd_to_sw((destination.i16_0[1usize] as i32 - source.i16_0[1usize] as i32) as u32) - as i32; + saturate_sd_to_sw((destination.i16_0[1] as i32 - source.i16_0[1] as i32) as u32) as i32; let mut word2: i32 = - saturate_sd_to_sw((destination.i16_0[2usize] as i32 - source.i16_0[2usize] as i32) as u32) - as i32; + saturate_sd_to_sw((destination.i16_0[2] as i32 - source.i16_0[2] as i32) as u32) as i32; let mut word3: i32 = - saturate_sd_to_sw((destination.i16_0[3usize] as i32 - source.i16_0[3usize] as i32) as u32) - as i32; - let mut low: i32 = word0 | word1 << 16i32; - let mut high: i32 = word2 | word3 << 16i32; + saturate_sd_to_sw((destination.i16_0[3] as i32 - source.i16_0[3] as i32) as u32) as i32; + let mut low: i32 = word0 | word1 << 16; + let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); } #[no_mangle] @@ -4897,25 +4796,21 @@ pub unsafe fn instr_660FE9(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = - (saturate_sd_to_sw((destination.i16_0[0usize] as i32 - source.i16_0[0usize] as i32) as u32) - | saturate_sd_to_sw( - (destination.i16_0[1usize] as i32 - source.i16_0[1usize] as i32) as u32, - ) << 16i32) as i32; + (saturate_sd_to_sw((destination.i16_0[0] as i32 - source.i16_0[0] as i32) as u32) + | saturate_sd_to_sw((destination.i16_0[1] as i32 - source.i16_0[1] as i32) as u32) + << 16) as i32; let mut dword1: i32 = - (saturate_sd_to_sw((destination.i16_0[2usize] as i32 - source.i16_0[2usize] as i32) as u32) - | saturate_sd_to_sw( - (destination.i16_0[3usize] as i32 - source.i16_0[3usize] as i32) as u32, - ) << 16i32) as i32; + (saturate_sd_to_sw((destination.i16_0[2] as i32 - source.i16_0[2] as i32) as u32) + | saturate_sd_to_sw((destination.i16_0[3] as i32 - source.i16_0[3] as i32) as u32) + << 16) as i32; let mut dword2: i32 = - (saturate_sd_to_sw((destination.i16_0[4usize] as i32 - source.i16_0[4usize] as i32) as u32) - | saturate_sd_to_sw( - (destination.i16_0[5usize] as i32 - source.i16_0[5usize] as i32) as u32, - ) << 16i32) as i32; + (saturate_sd_to_sw((destination.i16_0[4] as i32 - source.i16_0[4] as i32) as u32) + | saturate_sd_to_sw((destination.i16_0[5] as i32 - source.i16_0[5] as i32) as u32) + << 16) as i32; let mut dword3: i32 = - (saturate_sd_to_sw((destination.i16_0[6usize] as i32 - source.i16_0[6usize] as i32) as u32) - | saturate_sd_to_sw( - (destination.i16_0[7usize] as i32 - source.i16_0[7usize] as i32) as u32, - ) << 16i32) as i32; + (saturate_sd_to_sw((destination.i16_0[6] as i32 - source.i16_0[6] as i32) as u32) + | saturate_sd_to_sw((destination.i16_0[7] as i32 - source.i16_0[7] as i32) as u32) + << 16) as i32; write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] @@ -4929,8 +4824,8 @@ pub unsafe fn instr_0FEA(mut source: reg64, mut r: i32) { // pminsw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; - let mut i: u32 = 0i32 as u32; - while i < 4i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 4 as u32 { result.i16_0[i as usize] = (if (destination.i16_0[i as usize] as i32) < source.i16_0[i as usize] as i32 { destination.i16_0[i as usize] as i32 @@ -4954,8 +4849,8 @@ pub unsafe fn instr_660FEA(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: u32 = 0i32 as u32; - while i < 8i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 8 as u32 { result.i16_0[i as usize] = (if (destination.i16_0[i as usize] as i32) < source.i16_0[i as usize] as i32 { destination.i16_0[i as usize] as i32 @@ -4978,9 +4873,9 @@ pub unsafe fn instr_0FEB(mut source: reg64, mut r: i32) { // por mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - result.u64_0[0usize] = source.u64_0[0usize] | destination.u64_0[0usize]; + result.u64_0[0] = source.u64_0[0] | destination.u64_0[0]; write_mmx_reg64(r, result); } #[no_mangle] @@ -5006,10 +4901,10 @@ pub unsafe fn instr_0FEC(mut source: reg64, mut r: i32) { // paddsb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0i32 as u32; - while i < 8i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 8 as u32 { result.u8_0[i as usize] = saturate_sd_to_sb( (destination.i8_0[i as usize] as i32 + source.i8_0[i as usize] as i32) as u32, ) as u8; @@ -5029,8 +4924,8 @@ pub unsafe fn instr_660FEC(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: u32 = 0i32 as u32; - while i < 16i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 16 as u32 { result.i8_0[i as usize] = saturate_sd_to_sb( (destination.i8_0[i as usize] as i32 + source.i8_0[i as usize] as i32) as u32, ) as i8; @@ -5049,19 +4944,15 @@ pub unsafe fn instr_0FED(mut source: reg64, mut r: i32) { // paddsw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut word0: i32 = - saturate_sd_to_sw((destination.i16_0[0usize] as i32 + source.i16_0[0usize] as i32) as u32) - as i32; + saturate_sd_to_sw((destination.i16_0[0] as i32 + source.i16_0[0] as i32) as u32) as i32; let mut word1: i32 = - saturate_sd_to_sw((destination.i16_0[1usize] as i32 + source.i16_0[1usize] as i32) as u32) - as i32; + saturate_sd_to_sw((destination.i16_0[1] as i32 + source.i16_0[1] as i32) as u32) as i32; let mut word2: i32 = - saturate_sd_to_sw((destination.i16_0[2usize] as i32 + source.i16_0[2usize] as i32) as u32) - as i32; + saturate_sd_to_sw((destination.i16_0[2] as i32 + source.i16_0[2] as i32) as u32) as i32; let mut word3: i32 = - saturate_sd_to_sw((destination.i16_0[3usize] as i32 + source.i16_0[3usize] as i32) as u32) - as i32; - let mut low: i32 = word0 | word1 << 16i32; - let mut high: i32 = word2 | word3 << 16i32; + saturate_sd_to_sw((destination.i16_0[3] as i32 + source.i16_0[3] as i32) as u32) as i32; + let mut low: i32 = word0 | word1 << 16; + let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); } #[no_mangle] @@ -5076,25 +4967,21 @@ pub unsafe fn instr_660FED(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = - (saturate_sd_to_sw((destination.i16_0[0usize] as i32 + source.i16_0[0usize] as i32) as u32) - | saturate_sd_to_sw( - (destination.i16_0[1usize] as i32 + source.i16_0[1usize] as i32) as u32, - ) << 16i32) as i32; + (saturate_sd_to_sw((destination.i16_0[0] as i32 + source.i16_0[0] as i32) as u32) + | saturate_sd_to_sw((destination.i16_0[1] as i32 + source.i16_0[1] as i32) as u32) + << 16) as i32; let mut dword1: i32 = - (saturate_sd_to_sw((destination.i16_0[2usize] as i32 + source.i16_0[2usize] as i32) as u32) - | saturate_sd_to_sw( - (destination.i16_0[3usize] as i32 + source.i16_0[3usize] as i32) as u32, - ) << 16i32) as i32; + (saturate_sd_to_sw((destination.i16_0[2] as i32 + source.i16_0[2] as i32) as u32) + | saturate_sd_to_sw((destination.i16_0[3] as i32 + source.i16_0[3] as i32) as u32) + << 16) as i32; let mut dword2: i32 = - (saturate_sd_to_sw((destination.i16_0[4usize] as i32 + source.i16_0[4usize] as i32) as u32) - | saturate_sd_to_sw( - (destination.i16_0[5usize] as i32 + source.i16_0[5usize] as i32) as u32, - ) << 16i32) as i32; + (saturate_sd_to_sw((destination.i16_0[4] as i32 + source.i16_0[4] as i32) as u32) + | saturate_sd_to_sw((destination.i16_0[5] as i32 + source.i16_0[5] as i32) as u32) + << 16) as i32; let mut dword3: i32 = - (saturate_sd_to_sw((destination.i16_0[6usize] as i32 + source.i16_0[6usize] as i32) as u32) - | saturate_sd_to_sw( - (destination.i16_0[7usize] as i32 + source.i16_0[7usize] as i32) as u32, - ) << 16i32) as i32; + (saturate_sd_to_sw((destination.i16_0[6] as i32 + source.i16_0[6] as i32) as u32) + | saturate_sd_to_sw((destination.i16_0[7] as i32 + source.i16_0[7] as i32) as u32) + << 16) as i32; write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] @@ -5108,8 +4995,8 @@ pub unsafe fn instr_0FEE(mut source: reg64, mut r: i32) { // pmaxsw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; - let mut i: u32 = 0i32 as u32; - while i < 4i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 4 as u32 { result.i16_0[i as usize] = (if destination.i16_0[i as usize] as i32 >= source.i16_0[i as usize] as i32 { destination.i16_0[i as usize] as i32 @@ -5133,8 +5020,8 @@ pub unsafe fn instr_660FEE(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: u32 = 0i32 as u32; - while i < 8i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 8 as u32 { result.i16_0[i as usize] = (if destination.i16_0[i as usize] as i32 >= source.i16_0[i as usize] as i32 { destination.i16_0[i as usize] as i32 @@ -5157,9 +5044,9 @@ pub unsafe fn instr_0FEF(mut source: reg64, mut r: i32) { // pxor mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - result.u64_0[0usize] = source.u64_0[0usize] ^ destination.u64_0[0usize]; + result.u64_0[0] = source.u64_0[0] ^ destination.u64_0[0]; write_mmx_reg64(r, result); } #[no_mangle] @@ -5185,7 +5072,7 @@ pub unsafe fn instr_0FF0() { unimplemented_sse(); } #[no_mangle] pub unsafe fn instr_0FF1(mut source: reg64, mut r: i32) { // psllw mm, mm/m64 - psllw_r64(r, source.u32_0[0usize]); + psllw_r64(r, source.u32_0[0]); } #[no_mangle] pub unsafe fn instr_0FF1_reg(mut r1: i32, mut r2: i32) { instr_0FF1(read_mmx64s(r1), r2); } @@ -5197,7 +5084,7 @@ pub unsafe fn instr_0FF1_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_660FF1(mut source: reg128, mut r: i32) { // psllw xmm, xmm/m128 // XXX: Aligned access or #gp - psllw_r128(r, source.u32_0[0usize]); + psllw_r128(r, source.u32_0[0]); } #[no_mangle] pub unsafe fn instr_660FF1_reg(mut r1: i32, mut r2: i32) { instr_660FF1(read_xmm128s(r1), r2); } @@ -5208,7 +5095,7 @@ pub unsafe fn instr_660FF1_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_0FF2(mut source: reg64, mut r: i32) { // pslld mm, mm/m64 - pslld_r64(r, source.u32_0[0usize]); + pslld_r64(r, source.u32_0[0]); } #[no_mangle] pub unsafe fn instr_0FF2_reg(mut r1: i32, mut r2: i32) { instr_0FF2(read_mmx64s(r1), r2); } @@ -5220,7 +5107,7 @@ pub unsafe fn instr_0FF2_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_660FF2(mut source: reg128, mut r: i32) { // pslld xmm, xmm/m128 // XXX: Aligned access or #gp - pslld_r128(r, source.u32_0[0usize]); + pslld_r128(r, source.u32_0[0]); } #[no_mangle] pub unsafe fn instr_660FF2_reg(mut r1: i32, mut r2: i32) { instr_660FF2(read_xmm128s(r1), r2); } @@ -5231,7 +5118,7 @@ pub unsafe fn instr_660FF2_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_0FF3(mut source: reg64, mut r: i32) { // psllq mm, mm/m64 - psllq_r64(r, source.u32_0[0usize]); + psllq_r64(r, source.u32_0[0]); } #[no_mangle] pub unsafe fn instr_0FF3_reg(mut r1: i32, mut r2: i32) { instr_0FF3(read_mmx64s(r1), r2); } @@ -5243,7 +5130,7 @@ pub unsafe fn instr_0FF3_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_660FF3(mut source: reg128, mut r: i32) { // psllq xmm, xmm/m128 // XXX: Aligned access or #gp - psllq_r128(r, source.u32_0[0usize]); + psllq_r128(r, source.u32_0[0]); } #[no_mangle] pub unsafe fn instr_660FF3_reg(mut r1: i32, mut r2: i32) { instr_660FF3(read_xmm128s(r1), r2); } @@ -5255,8 +5142,7 @@ pub unsafe fn instr_660FF3_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0FF4(mut source: reg64, mut r: i32) { // pmuludq mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - destination.u64_0[0usize] = - (source.u32_0[0usize] as u64).wrapping_mul(destination.u32_0[0usize] as u64); + destination.u64_0[0] = (source.u32_0[0] as u64).wrapping_mul(destination.u32_0[0] as u64); write_mmx_reg64(r, destination); } #[no_mangle] @@ -5270,10 +5156,8 @@ pub unsafe fn instr_660FF4(mut source: reg128, mut r: i32) { // pmuludq xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); - destination.u64_0[0usize] = - (source.u32_0[0usize] as u64).wrapping_mul(destination.u32_0[0usize] as u64); - destination.u64_0[1usize] = - (source.u32_0[2usize] as u64).wrapping_mul(destination.u32_0[2usize] as u64); + destination.u64_0[0] = (source.u32_0[0] as u64).wrapping_mul(destination.u32_0[0] as u64); + destination.u64_0[1] = (source.u32_0[2] as u64).wrapping_mul(destination.u32_0[2] as u64); write_xmm_reg128(r, destination); } #[no_mangle] @@ -5286,10 +5170,10 @@ pub unsafe fn instr_660FF4_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0FF5(mut source: reg64, mut r: i32) { // pmaddwd mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - let mut mul0: i32 = destination.i16_0[0usize] as i32 * source.i16_0[0usize] as i32; - let mut mul1: i32 = destination.i16_0[1usize] as i32 * source.i16_0[1usize] as i32; - let mut mul2: i32 = destination.i16_0[2usize] as i32 * source.i16_0[2usize] as i32; - let mut mul3: i32 = destination.i16_0[3usize] as i32 * source.i16_0[3usize] as i32; + let mut mul0: i32 = destination.i16_0[0] as i32 * source.i16_0[0] as i32; + let mut mul1: i32 = destination.i16_0[1] as i32 * source.i16_0[1] as i32; + let mut mul2: i32 = destination.i16_0[2] as i32 * source.i16_0[2] as i32; + let mut mul3: i32 = destination.i16_0[3] as i32 * source.i16_0[3] as i32; let mut low: i32 = mul0 + mul1; let mut high: i32 = mul2 + mul3; write_mmx64(r, low, high); @@ -5305,14 +5189,14 @@ pub unsafe fn instr_660FF5(mut source: reg128, mut r: i32) { // pmaddwd xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); - let mut dword0: i32 = destination.i16_0[0usize] as i32 * source.i16_0[0usize] as i32 - + destination.i16_0[1usize] as i32 * source.i16_0[1usize] as i32; - let mut dword1: i32 = destination.i16_0[2usize] as i32 * source.i16_0[2usize] as i32 - + destination.i16_0[3usize] as i32 * source.i16_0[3usize] as i32; - let mut dword2: i32 = destination.i16_0[4usize] as i32 * source.i16_0[4usize] as i32 - + destination.i16_0[5usize] as i32 * source.i16_0[5usize] as i32; - let mut dword3: i32 = destination.i16_0[6usize] as i32 * source.i16_0[6usize] as i32 - + destination.i16_0[7usize] as i32 * source.i16_0[7usize] as i32; + let mut dword0: i32 = destination.i16_0[0] as i32 * source.i16_0[0] as i32 + + destination.i16_0[1] as i32 * source.i16_0[1] as i32; + let mut dword1: i32 = destination.i16_0[2] as i32 * source.i16_0[2] as i32 + + destination.i16_0[3] as i32 * source.i16_0[3] as i32; + let mut dword2: i32 = destination.i16_0[4] as i32 * source.i16_0[4] as i32 + + destination.i16_0[5] as i32 * source.i16_0[5] as i32; + let mut dword3: i32 = destination.i16_0[6] as i32 * source.i16_0[6] as i32 + + destination.i16_0[7] as i32 * source.i16_0[7] as i32; write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] @@ -5325,15 +5209,15 @@ pub unsafe fn instr_660FF5_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0FF6(mut source: reg64, mut r: i32) { // psadbw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - let mut sum: u32 = 0i32 as u32; - let mut i: u32 = 0i32 as u32; - while i < 8i32 as u32 { + let mut sum: u32 = 0 as u32; + let mut i: u32 = 0 as u32; + while i < 8 as u32 { sum = (sum as u32).wrapping_add( (destination.u8_0[i as usize] as i32 - source.u8_0[i as usize] as i32).abs() as u32, ) as u32 as u32; i = i.wrapping_add(1) } - write_mmx64(r, sum as i32, 0i32); + write_mmx64(r, sum as i32, 0); } #[no_mangle] pub unsafe fn instr_0FF6_reg(mut r1: i32, mut r2: i32) { instr_0FF6(read_mmx64s(r1), r2); } @@ -5346,21 +5230,21 @@ pub unsafe fn instr_660FF6(mut source: reg128, mut r: i32) { // psadbw xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); - let mut sum0: u32 = 0i32 as u32; - let mut sum1: u32 = 0i32 as u32; - let mut i: u32 = 0i32 as u32; - while i < 8i32 as u32 { + let mut sum0: u32 = 0 as u32; + let mut sum1: u32 = 0 as u32; + let mut i: u32 = 0 as u32; + while i < 8 as u32 { sum0 = (sum0 as u32).wrapping_add( (destination.u8_0[i as usize] as i32 - source.u8_0[i as usize] as i32).abs() as u32, ) as u32 as u32; sum1 = (sum1 as u32).wrapping_add( - (destination.u8_0[i.wrapping_add(8i32 as u32) as usize] as i32 - - source.u8_0[i.wrapping_add(8i32 as u32) as usize] as i32) + (destination.u8_0[i.wrapping_add(8 as u32) as usize] as i32 + - source.u8_0[i.wrapping_add(8 as u32) as usize] as i32) .abs() as u32, ) as u32 as u32; i = i.wrapping_add(1) } - write_xmm128(r, sum0 as i32, 0i32, sum1 as i32, 0i32); + write_xmm128(r, sum0 as i32, 0, sum1 as i32, 0); } #[no_mangle] pub unsafe fn instr_660FF6_reg(mut r1: i32, mut r2: i32) { instr_660FF6(read_xmm128s(r1), r2); } @@ -5376,10 +5260,10 @@ pub unsafe fn instr_0FF7_reg(mut r1: i32, mut r2: i32) { let mut source: reg64 = read_mmx64s(r2); let mut mask: reg64 = read_mmx64s(r1); let mut addr: i32 = get_seg_prefix(DS) + get_reg_asize(EDI); - return_on_pagefault!(writable_or_pagefault(addr, 8i32)); - let mut i: u32 = 0i32 as u32; - while i < 8i32 as u32 { - if 0 != mask.u8_0[i as usize] as i32 & 128i32 { + return_on_pagefault!(writable_or_pagefault(addr, 8)); + let mut i: u32 = 0 as u32; + while i < 8 as u32 { + if 0 != mask.u8_0[i as usize] as i32 & 128 { safe_write8( (addr as u32).wrapping_add(i) as i32, source.u8_0[i as usize] as i32, @@ -5396,10 +5280,10 @@ pub unsafe fn instr_660FF7_reg(mut r1: i32, mut r2: i32) { let mut source: reg128 = read_xmm128s(r2); let mut mask: reg128 = read_xmm128s(r1); let mut addr: i32 = get_seg_prefix(DS) + get_reg_asize(EDI); - return_on_pagefault!(writable_or_pagefault(addr, 16i32)); - let mut i: u32 = 0i32 as u32; - while i < 16i32 as u32 { - if 0 != mask.u8_0[i as usize] as i32 & 128i32 { + return_on_pagefault!(writable_or_pagefault(addr, 16)); + let mut i: u32 = 0 as u32; + while i < 16 as u32 { + if 0 != mask.u8_0[i as usize] as i32 & 128 { safe_write8( (addr as u32).wrapping_add(i) as i32, source.u8_0[i as usize] as i32, @@ -5413,12 +5297,12 @@ pub unsafe fn instr_0FF8(mut source: reg64, mut r: i32) { // psubb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0i32 as u32; - while i < 8i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 8 as u32 { result.u8_0[i as usize] = - (destination.i8_0[i as usize] as i32 - source.i8_0[i as usize] as i32 & 255i32) as u8; + (destination.i8_0[i as usize] as i32 - source.i8_0[i as usize] as i32 & 255) as u8; i = i.wrapping_add(1) } write_mmx_reg64(r, result); @@ -5435,12 +5319,12 @@ pub unsafe fn instr_660FF8(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0i32 as u32; - while i < 16i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 16 as u32 { result.i8_0[i as usize] = - (destination.i8_0[i as usize] as i32 - source.i8_0[i as usize] as i32 & 255i32) as i8; + (destination.i8_0[i as usize] as i32 - source.i8_0[i as usize] as i32 & 255) as i8; i = i.wrapping_add(1) } write_xmm_reg128(r, result); @@ -5455,18 +5339,14 @@ pub unsafe fn instr_660FF8_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0FF9(mut source: reg64, mut r: i32) { // psubw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - let mut word0: i32 = - (destination.u32_0[0usize].wrapping_sub(source.u32_0[0usize]) & 65535i32 as u32) as i32; - let mut word1: i32 = ((destination.u16_0[1usize] as u32) - .wrapping_sub(source.u16_0[1usize] as u32) - & 65535i32 as u32) as i32; - let mut low: i32 = word0 | word1 << 16i32; - let mut word2: i32 = - (destination.u32_0[1usize].wrapping_sub(source.u32_0[1usize]) & 65535i32 as u32) as i32; - let mut word3: i32 = ((destination.u16_0[3usize] as u32) - .wrapping_sub(source.u16_0[3usize] as u32) - & 65535i32 as u32) as i32; - let mut high: i32 = word2 | word3 << 16i32; + let mut word0: i32 = (destination.u32_0[0].wrapping_sub(source.u32_0[0]) & 65535 as u32) as i32; + let mut word1: i32 = + ((destination.u16_0[1] as u32).wrapping_sub(source.u16_0[1] as u32) & 65535 as u32) as i32; + let mut low: i32 = word0 | word1 << 16; + let mut word2: i32 = (destination.u32_0[1].wrapping_sub(source.u32_0[1]) & 65535 as u32) as i32; + let mut word3: i32 = + ((destination.u16_0[3] as u32).wrapping_sub(source.u16_0[3] as u32) & 65535 as u32) as i32; + let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); } #[no_mangle] @@ -5481,13 +5361,12 @@ pub unsafe fn instr_660FF9(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0i32 as u32; - while i < 8i32 as u32 { - result.i16_0[i as usize] = (destination.i16_0[i as usize] as i32 - - source.i16_0[i as usize] as i32 - & 65535i32) as i16; + let mut i: u32 = 0 as u32; + while i < 8 as u32 { + result.i16_0[i as usize] = + (destination.i16_0[i as usize] as i32 - source.i16_0[i as usize] as i32 & 65535) as i16; i = i.wrapping_add(1) } write_xmm_reg128(r, result); @@ -5504,8 +5383,8 @@ pub unsafe fn instr_0FFA(mut source: reg64, mut r: i32) { let mut destination: reg64 = read_mmx64s(r); write_mmx64( r, - destination.u32_0[0usize].wrapping_sub(source.u32_0[0usize]) as i32, - destination.u32_0[1usize].wrapping_sub(source.u32_0[1usize]) as i32, + destination.u32_0[0].wrapping_sub(source.u32_0[0]) as i32, + destination.u32_0[1].wrapping_sub(source.u32_0[1]) as i32, ); } #[no_mangle] @@ -5521,10 +5400,10 @@ pub unsafe fn instr_660FFA(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); write_xmm128( r, - destination.u32_0[0usize].wrapping_sub(source.u32_0[0usize]) as i32, - destination.u32_0[1usize].wrapping_sub(source.u32_0[1usize]) as i32, - destination.u32_0[2usize].wrapping_sub(source.u32_0[2usize]) as i32, - destination.u32_0[3usize].wrapping_sub(source.u32_0[3usize]) as i32, + destination.u32_0[0].wrapping_sub(source.u32_0[0]) as i32, + destination.u32_0[1].wrapping_sub(source.u32_0[1]) as i32, + destination.u32_0[2].wrapping_sub(source.u32_0[2]) as i32, + destination.u32_0[3].wrapping_sub(source.u32_0[3]) as i32, ); } #[no_mangle] @@ -5537,7 +5416,7 @@ pub unsafe fn instr_660FFA_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0FFB(mut source: reg64, mut r: i32) { // psubq mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - destination.u64_0[0usize] = destination.u64_0[0usize].wrapping_sub(source.u64_0[0usize]); + destination.u64_0[0] = destination.u64_0[0].wrapping_sub(source.u64_0[0]); write_mmx_reg64(r, destination); } #[no_mangle] @@ -5551,8 +5430,8 @@ pub unsafe fn instr_660FFB(mut source: reg128, mut r: i32) { // psubq xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); - destination.u64_0[0usize] = destination.u64_0[0usize].wrapping_sub(source.u64_0[0usize]); - destination.u64_0[1usize] = destination.u64_0[1usize].wrapping_sub(source.u64_0[1usize]); + destination.u64_0[0] = destination.u64_0[0].wrapping_sub(source.u64_0[0]); + destination.u64_0[1] = destination.u64_0[1].wrapping_sub(source.u64_0[1]); write_xmm_reg128(r, destination); } #[no_mangle] @@ -5566,12 +5445,12 @@ pub unsafe fn instr_0FFC(mut source: reg64, mut r: i32) { // paddb mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0i32 as u32; - while i < 8i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 8 as u32 { result.u8_0[i as usize] = - (destination.u8_0[i as usize] as i32 + source.u8_0[i as usize] as i32 & 255i32) as u8; + (destination.u8_0[i as usize] as i32 + source.u8_0[i as usize] as i32 & 255) as u8; i = i.wrapping_add(1) } write_mmx_reg64(r, result); @@ -5588,12 +5467,12 @@ pub unsafe fn instr_660FFC(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0i32 as u32; - while i < 16i32 as u32 { + let mut i: u32 = 0 as u32; + while i < 16 as u32 { result.u8_0[i as usize] = - (destination.u8_0[i as usize] as i32 + source.u8_0[i as usize] as i32 & 255i32) as u8; + (destination.u8_0[i as usize] as i32 + source.u8_0[i as usize] as i32 & 255) as u8; i = i.wrapping_add(1) } write_xmm_reg128(r, result); @@ -5608,14 +5487,12 @@ pub unsafe fn instr_660FFC_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0FFD(mut source: reg64, mut r: i32) { // paddw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - let mut word0: i32 = - (destination.u32_0[0usize].wrapping_add(source.u32_0[0usize]) & 65535i32 as u32) as i32; - let mut word1: i32 = destination.u16_0[1usize] as i32 + source.u16_0[1usize] as i32 & 65535i32; - let mut low: i32 = word0 | word1 << 16i32; - let mut word2: i32 = - (destination.u32_0[1usize].wrapping_add(source.u32_0[1usize]) & 65535i32 as u32) as i32; - let mut word3: i32 = destination.u16_0[3usize] as i32 + source.u16_0[3usize] as i32 & 65535i32; - let mut high: i32 = word2 | word3 << 16i32; + let mut word0: i32 = (destination.u32_0[0].wrapping_add(source.u32_0[0]) & 65535 as u32) as i32; + let mut word1: i32 = destination.u16_0[1] as i32 + source.u16_0[1] as i32 & 65535; + let mut low: i32 = word0 | word1 << 16; + let mut word2: i32 = (destination.u32_0[1].wrapping_add(source.u32_0[1]) & 65535 as u32) as i32; + let mut word3: i32 = destination.u16_0[3] as i32 + source.u16_0[3] as i32 & 65535; + let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); } #[no_mangle] @@ -5630,13 +5507,12 @@ pub unsafe fn instr_660FFD(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0i32 as u32; - while i < 8i32 as u32 { - result.u16_0[i as usize] = (destination.u16_0[i as usize] as i32 - + source.u16_0[i as usize] as i32 - & 65535i32) as u16; + let mut i: u32 = 0 as u32; + while i < 8 as u32 { + result.u16_0[i as usize] = + (destination.u16_0[i as usize] as i32 + source.u16_0[i as usize] as i32 & 65535) as u16; i = i.wrapping_add(1) } write_xmm_reg128(r, result); @@ -5651,8 +5527,8 @@ pub unsafe fn instr_660FFD_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0FFE(mut source: reg64, mut r: i32) { // paddd mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - let mut low: i32 = destination.u32_0[0usize].wrapping_add(source.u32_0[0usize]) as i32; - let mut high: i32 = destination.u32_0[1usize].wrapping_add(source.u32_0[1usize]) as i32; + let mut low: i32 = destination.u32_0[0].wrapping_add(source.u32_0[0]) as i32; + let mut high: i32 = destination.u32_0[1].wrapping_add(source.u32_0[1]) as i32; write_mmx64(r, low, high); } #[no_mangle] @@ -5666,10 +5542,10 @@ pub unsafe fn instr_660FFE(mut source: reg128, mut r: i32) { // paddd xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); - let mut dword0: i32 = destination.u32_0[0usize].wrapping_add(source.u32_0[0usize]) as i32; - let mut dword1: i32 = destination.u32_0[1usize].wrapping_add(source.u32_0[1usize]) as i32; - let mut dword2: i32 = destination.u32_0[2usize].wrapping_add(source.u32_0[2usize]) as i32; - let mut dword3: i32 = destination.u32_0[3usize].wrapping_add(source.u32_0[3usize]) as i32; + let mut dword0: i32 = destination.u32_0[0].wrapping_add(source.u32_0[0]) as i32; + let mut dword1: i32 = destination.u32_0[1].wrapping_add(source.u32_0[1]) as i32; + let mut dword2: i32 = destination.u32_0[2].wrapping_add(source.u32_0[2]) as i32; + let mut dword3: i32 = destination.u32_0[3].wrapping_add(source.u32_0[3]) as i32; write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] @@ -5711,7 +5587,7 @@ pub unsafe fn instr_0F2A(mut source: reg64, mut r: i32) { // XXX: The non-memory variant causes a transition from x87 FPU to MMX technology operation // Note: Casts here can fail let mut result: reg64 = reg64 { - f32_0: [source.i32_0[0usize] as f32, source.i32_0[1usize] as f32], + f32_0: [source.i32_0[0] as f32, source.i32_0[1] as f32], }; write_xmm64(r, result); } @@ -5727,7 +5603,7 @@ pub unsafe fn instr_660F2A(mut source: reg64, mut r: i32) { // XXX: The non-memory variant causes a transition from x87 FPU to MMX technology operation // These casts can't fail let mut result: reg128 = reg128 { - f64_0: [source.i32_0[0usize] as f64, source.i32_0[1usize] as f64], + f64_0: [source.i32_0[0] as f64, source.i32_0[1] as f64], }; write_xmm_reg128(r, result); } @@ -5804,7 +5680,7 @@ pub unsafe fn instr_660F2D_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_F20F2D(mut source: reg64, mut r: i32) { // cvtsd2si r32, xmm/m64 - write_reg32(r, sse_convert_f64_to_i32(source.f64_0[0usize].round())); + write_reg32(r, sse_convert_f64_to_i32(source.f64_0[0].round())); } #[no_mangle] pub unsafe fn instr_F20F2D_reg(mut r1: i32, mut r2: i32) { instr_F20F2D(read_xmm64s(r1), r2); } @@ -5829,10 +5705,10 @@ pub unsafe fn instr_0F51(mut source: reg128, mut r: i32) { // sqrtps xmm, xmm/mem128 let mut result: reg128 = reg128 { f32_0: [ - source.f32_0[0usize].sqrt(), - source.f32_0[1usize].sqrt(), - source.f32_0[2usize].sqrt(), - source.f32_0[3usize].sqrt(), + source.f32_0[0].sqrt(), + source.f32_0[1].sqrt(), + source.f32_0[2].sqrt(), + source.f32_0[3].sqrt(), ], }; write_xmm_reg128(r, result); @@ -5847,7 +5723,7 @@ pub unsafe fn instr_0F51_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_660F51(mut source: reg128, mut r: i32) { // sqrtpd xmm, xmm/mem128 let mut result: reg128 = reg128 { - f64_0: [source.f64_0[0usize].sqrt(), source.f64_0[1usize].sqrt()], + f64_0: [source.f64_0[0].sqrt(), source.f64_0[1].sqrt()], }; write_xmm_reg128(r, result); } @@ -5861,7 +5737,7 @@ pub unsafe fn instr_660F51_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_F20F51(mut source: reg64, mut r: i32) { // sqrtsd xmm, xmm/mem64 let mut result: reg64 = reg64 { - f64_0: [source.f64_0[0usize].sqrt()], + f64_0: [source.f64_0[0].sqrt()], }; write_xmm64(r, result); } @@ -5888,10 +5764,10 @@ pub unsafe fn instr_0F52(mut source: reg128, mut r: i32) { // rcpps xmm1, xmm2/m128 let mut result: reg128 = reg128 { f32_0: [ - 1i32 as f32 / source.f32_0[0usize].sqrt(), - 1i32 as f32 / source.f32_0[1usize].sqrt(), - 1i32 as f32 / source.f32_0[2usize].sqrt(), - 1i32 as f32 / source.f32_0[3usize].sqrt(), + 1 as f32 / source.f32_0[0].sqrt(), + 1 as f32 / source.f32_0[1].sqrt(), + 1 as f32 / source.f32_0[2].sqrt(), + 1 as f32 / source.f32_0[3].sqrt(), ], }; write_xmm_reg128(r, result); @@ -5905,7 +5781,7 @@ pub unsafe fn instr_0F52_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_F30F52(mut source: f32, mut r: i32) { // rsqrtss xmm1, xmm2/m32 - write_xmm_f32(r, 1i32 as f32 / source.sqrt()); + write_xmm_f32(r, 1 as f32 / source.sqrt()); } #[no_mangle] pub unsafe fn instr_F30F52_reg(mut r1: i32, mut r2: i32) { instr_F30F52(read_xmm_f32(r1), r2); } @@ -5919,10 +5795,10 @@ pub unsafe fn instr_0F53(mut source: reg128, mut r: i32) { // rcpps xmm, xmm/m128 let mut result: reg128 = reg128 { f32_0: [ - 1i32 as f32 / source.f32_0[0usize], - 1i32 as f32 / source.f32_0[1usize], - 1i32 as f32 / source.f32_0[2usize], - 1i32 as f32 / source.f32_0[3usize], + 1 as f32 / source.f32_0[0], + 1 as f32 / source.f32_0[1], + 1 as f32 / source.f32_0[2], + 1 as f32 / source.f32_0[3], ], }; write_xmm_reg128(r, result); @@ -5936,7 +5812,7 @@ pub unsafe fn instr_0F53_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_F30F53(mut source: f32, mut r: i32) { // rcpss xmm, xmm/m32 - write_xmm_f32(r, 1i32 as f32 / source); + write_xmm_f32(r, 1 as f32 / source); } #[no_mangle] pub unsafe fn instr_F30F53_reg(mut r1: i32, mut r2: i32) { instr_F30F53(read_xmm_f32(r1), r2); } @@ -5951,10 +5827,10 @@ pub unsafe fn instr_0F58(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f32_0: [ - source.f32_0[0usize] + destination.f32_0[0usize], - source.f32_0[1usize] + destination.f32_0[1usize], - source.f32_0[2usize] + destination.f32_0[2usize], - source.f32_0[3usize] + destination.f32_0[3usize], + source.f32_0[0] + destination.f32_0[0], + source.f32_0[1] + destination.f32_0[1], + source.f32_0[2] + destination.f32_0[2], + source.f32_0[3] + destination.f32_0[3], ], }; write_xmm_reg128(r, result); @@ -5971,8 +5847,8 @@ pub unsafe fn instr_660F58(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f64_0: [ - source.f64_0[0usize] + destination.f64_0[0usize], - source.f64_0[1usize] + destination.f64_0[1usize], + source.f64_0[0] + destination.f64_0[0], + source.f64_0[1] + destination.f64_0[1], ], }; write_xmm_reg128(r, result); @@ -5988,7 +5864,7 @@ pub unsafe fn instr_F20F58(mut source: reg64, mut r: i32) { // addsd xmm, xmm/mem64 let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { - f64_0: [source.f64_0[0usize] + destination.f64_0[0usize]], + f64_0: [source.f64_0[0] + destination.f64_0[0]], }; write_xmm64(r, result); } @@ -6018,10 +5894,10 @@ pub unsafe fn instr_0F59(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f32_0: [ - source.f32_0[0usize] * destination.f32_0[0usize], - source.f32_0[1usize] * destination.f32_0[1usize], - source.f32_0[2usize] * destination.f32_0[2usize], - source.f32_0[3usize] * destination.f32_0[3usize], + source.f32_0[0] * destination.f32_0[0], + source.f32_0[1] * destination.f32_0[1], + source.f32_0[2] * destination.f32_0[2], + source.f32_0[3] * destination.f32_0[3], ], }; write_xmm_reg128(r, result); @@ -6038,8 +5914,8 @@ pub unsafe fn instr_660F59(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f64_0: [ - source.f64_0[0usize] * destination.f64_0[0usize], - source.f64_0[1usize] * destination.f64_0[1usize], + source.f64_0[0] * destination.f64_0[0], + source.f64_0[1] * destination.f64_0[1], ], }; write_xmm_reg128(r, result); @@ -6055,7 +5931,7 @@ pub unsafe fn instr_F20F59(mut source: reg64, mut r: i32) { // mulsd xmm, xmm/mem64 let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { - f64_0: [source.f64_0[0usize] * destination.f64_0[0usize]], + f64_0: [source.f64_0[0] * destination.f64_0[0]], }; write_xmm64(r, result); } @@ -6201,10 +6077,10 @@ pub unsafe fn instr_0F5C(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f32_0: [ - destination.f32_0[0usize] - source.f32_0[0usize], - destination.f32_0[1usize] - source.f32_0[1usize], - destination.f32_0[2usize] - source.f32_0[2usize], - destination.f32_0[3usize] - source.f32_0[3usize], + destination.f32_0[0] - source.f32_0[0], + destination.f32_0[1] - source.f32_0[1], + destination.f32_0[2] - source.f32_0[2], + destination.f32_0[3] - source.f32_0[3], ], }; write_xmm_reg128(r, result); @@ -6221,8 +6097,8 @@ pub unsafe fn instr_660F5C(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f64_0: [ - destination.f64_0[0usize] - source.f64_0[0usize], - destination.f64_0[1usize] - source.f64_0[1usize], + destination.f64_0[0] - source.f64_0[0], + destination.f64_0[1] - source.f64_0[1], ], }; write_xmm_reg128(r, result); @@ -6238,7 +6114,7 @@ pub unsafe fn instr_F20F5C(mut source: reg64, mut r: i32) { // subsd xmm, xmm/mem64 let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { - f64_0: [destination.f64_0[0usize] - source.f64_0[0usize]], + f64_0: [destination.f64_0[0] - source.f64_0[0]], }; write_xmm64(r, result); } @@ -6267,22 +6143,10 @@ pub unsafe fn instr_0F5D(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f32_0: [ - sse_min( - destination.f32_0[0usize] as f64, - source.f32_0[0usize] as f64, - ) as f32, - sse_min( - destination.f32_0[1usize] as f64, - source.f32_0[1usize] as f64, - ) as f32, - sse_min( - destination.f32_0[2usize] as f64, - source.f32_0[2usize] as f64, - ) as f32, - sse_min( - destination.f32_0[3usize] as f64, - source.f32_0[3usize] as f64, - ) as f32, + sse_min(destination.f32_0[0] as f64, source.f32_0[0] as f64) as f32, + sse_min(destination.f32_0[1] as f64, source.f32_0[1] as f64) as f32, + sse_min(destination.f32_0[2] as f64, source.f32_0[2] as f64) as f32, + sse_min(destination.f32_0[3] as f64, source.f32_0[3] as f64) as f32, ], }; write_xmm_reg128(r, result); @@ -6299,8 +6163,8 @@ pub unsafe fn instr_660F5D(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f64_0: [ - sse_min(destination.f64_0[0usize], source.f64_0[0usize]), - sse_min(destination.f64_0[1usize], source.f64_0[1usize]), + sse_min(destination.f64_0[0], source.f64_0[0]), + sse_min(destination.f64_0[1], source.f64_0[1]), ], }; write_xmm_reg128(r, result); @@ -6316,7 +6180,7 @@ pub unsafe fn instr_F20F5D(mut source: reg64, mut r: i32) { // minsd xmm, xmm/mem64 let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { - f64_0: [sse_min(destination.f64_0[0usize], source.f64_0[0usize])], + f64_0: [sse_min(destination.f64_0[0], source.f64_0[0])], }; write_xmm64(r, result); } @@ -6345,10 +6209,10 @@ pub unsafe fn instr_0F5E(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f32_0: [ - destination.f32_0[0usize] / source.f32_0[0usize], - destination.f32_0[1usize] / source.f32_0[1usize], - destination.f32_0[2usize] / source.f32_0[2usize], - destination.f32_0[3usize] / source.f32_0[3usize], + destination.f32_0[0] / source.f32_0[0], + destination.f32_0[1] / source.f32_0[1], + destination.f32_0[2] / source.f32_0[2], + destination.f32_0[3] / source.f32_0[3], ], }; write_xmm_reg128(r, result); @@ -6365,8 +6229,8 @@ pub unsafe fn instr_660F5E(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f64_0: [ - destination.f64_0[0usize] / source.f64_0[0usize], - destination.f64_0[1usize] / source.f64_0[1usize], + destination.f64_0[0] / source.f64_0[0], + destination.f64_0[1] / source.f64_0[1], ], }; write_xmm_reg128(r, result); @@ -6382,7 +6246,7 @@ pub unsafe fn instr_F20F5E(mut source: reg64, mut r: i32) { // divsd xmm, xmm/mem64 let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { - f64_0: [destination.f64_0[0usize] / source.f64_0[0usize]], + f64_0: [destination.f64_0[0] / source.f64_0[0]], }; write_xmm64(r, result); } @@ -6411,22 +6275,10 @@ pub unsafe fn instr_0F5F(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f32_0: [ - sse_max( - destination.f32_0[0usize] as f64, - source.f32_0[0usize] as f64, - ) as f32, - sse_max( - destination.f32_0[1usize] as f64, - source.f32_0[1usize] as f64, - ) as f32, - sse_max( - destination.f32_0[2usize] as f64, - source.f32_0[2usize] as f64, - ) as f32, - sse_max( - destination.f32_0[3usize] as f64, - source.f32_0[3usize] as f64, - ) as f32, + sse_max(destination.f32_0[0] as f64, source.f32_0[0] as f64) as f32, + sse_max(destination.f32_0[1] as f64, source.f32_0[1] as f64) as f32, + sse_max(destination.f32_0[2] as f64, source.f32_0[2] as f64) as f32, + sse_max(destination.f32_0[3] as f64, source.f32_0[3] as f64) as f32, ], }; write_xmm_reg128(r, result); @@ -6443,8 +6295,8 @@ pub unsafe fn instr_660F5F(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { f64_0: [ - sse_max(destination.f64_0[0usize], source.f64_0[0usize]), - sse_max(destination.f64_0[1usize], source.f64_0[1usize]), + sse_max(destination.f64_0[0], source.f64_0[0]), + sse_max(destination.f64_0[1], source.f64_0[1]), ], }; write_xmm_reg128(r, result); @@ -6460,7 +6312,7 @@ pub unsafe fn instr_F20F5F(mut source: reg64, mut r: i32) { // maxsd xmm, xmm/mem64 let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { - f64_0: [sse_max(destination.f64_0[0usize], source.f64_0[0usize])], + f64_0: [sse_max(destination.f64_0[0], source.f64_0[0])], }; write_xmm64(r, result); } @@ -6489,49 +6341,33 @@ pub unsafe fn instr_0FC2(mut source: reg128, mut r: i32, mut imm8: i32) { let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i32_0: [ - if 0 != sse_comparison( - imm8, - destination.f32_0[0usize] as f64, - source.f32_0[0usize] as f64, - ) as i32 + if 0 != sse_comparison(imm8, destination.f32_0[0] as f64, source.f32_0[0] as f64) as i32 { - -1i32 + -1 } else { - 0i32 + 0 }, - if 0 != sse_comparison( - imm8, - destination.f32_0[1usize] as f64, - source.f32_0[1usize] as f64, - ) as i32 + if 0 != sse_comparison(imm8, destination.f32_0[1] as f64, source.f32_0[1] as f64) as i32 { - -1i32 + -1 } else { - 0i32 + 0 }, - if 0 != sse_comparison( - imm8, - destination.f32_0[2usize] as f64, - source.f32_0[2usize] as f64, - ) as i32 + if 0 != sse_comparison(imm8, destination.f32_0[2] as f64, source.f32_0[2] as f64) as i32 { - -1i32 + -1 } else { - 0i32 + 0 }, - if 0 != sse_comparison( - imm8, - destination.f32_0[3usize] as f64, - source.f32_0[3usize] as f64, - ) as i32 + if 0 != sse_comparison(imm8, destination.f32_0[3] as f64, source.f32_0[3] as f64) as i32 { - -1i32 + -1 } else { - 0i32 + 0 }, ], }; @@ -6551,17 +6387,17 @@ pub unsafe fn instr_660FC2(mut source: reg128, mut r: i32, mut imm8: i32) { let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i64_0: [ - (if 0 != sse_comparison(imm8, destination.f64_0[0usize], source.f64_0[0usize]) as i32 { - -1i32 + (if 0 != sse_comparison(imm8, destination.f64_0[0], source.f64_0[0]) as i32 { + -1 } else { - 0i32 + 0 }) as i64, - (if 0 != sse_comparison(imm8, destination.f64_0[1usize], source.f64_0[1usize]) as i32 { - -1i32 + (if 0 != sse_comparison(imm8, destination.f64_0[1], source.f64_0[1]) as i32 { + -1 } else { - 0i32 + 0 }) as i64, ], }; @@ -6580,14 +6416,14 @@ pub unsafe fn instr_F20FC2(mut source: reg64, mut r: i32, mut imm8: i32) { // cmpsd xmm, xmm/m64 let mut destination: reg64 = read_xmm64s(r); let mut result: reg64 = reg64 { - i64_0: [(if 0 - != sse_comparison(imm8, destination.f64_0[0usize], source.f64_0[0usize]) as i32 - { - -1i32 - } - else { - 0i32 - }) as i64], + i64_0: [ + (if 0 != sse_comparison(imm8, destination.f64_0[0], source.f64_0[0]) as i32 { + -1 + } + else { + 0 + }) as i64, + ], }; write_xmm64(r, result); } @@ -6604,10 +6440,10 @@ pub unsafe fn instr_F30FC2(mut source: f32, mut r: i32, mut imm8: i32) { // cmpss xmm, xmm/m32 let mut destination: f32 = read_xmm_f32(r); let mut result: i32 = if 0 != sse_comparison(imm8, destination as f64, source as f64) as i32 { - -1i32 + -1 } else { - 0i32 + 0 }; write_xmm32(r, result); } diff --git a/src/rust/cpu2/memory.rs b/src/rust/cpu2/memory.rs index 18b1b793..846ed9ea 100644 --- a/src/rust/cpu2/memory.rs +++ b/src/rust/cpu2/memory.rs @@ -25,7 +25,7 @@ const USE_A20: bool = false; #[no_mangle] pub unsafe fn in_mapped_range(mut addr: u32) -> bool { - return addr >= 655360i32 as u32 && addr < 786432i32 as u32 || addr >= *memory_size; + return addr >= 655360 as u32 && addr < 786432 as u32 || addr >= *memory_size; } #[no_mangle] @@ -54,12 +54,12 @@ pub unsafe fn read16(mut addr: u32) -> i32 { } #[no_mangle] pub unsafe fn read_aligned16(mut addr: u32) -> i32 { - dbg_assert!(addr < 2147483648u32); + dbg_assert!(addr < 2147483648); if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK16 as u32 } - if in_mapped_range(addr << 1i32) { - return mmap_read16(addr << 1i32); + if in_mapped_range(addr << 1) { + return mmap_read16(addr << 1); } else { return *mem16.offset(addr as isize) as i32; @@ -83,8 +83,7 @@ pub unsafe fn read64s(mut addr: u32) -> i64 { addr &= A20_MASK as u32 } if in_mapped_range(addr) { - return mmap_read32(addr) as i64 - | (mmap_read32(addr.wrapping_add(4i32 as u32)) as i64) << 32i32; + return mmap_read32(addr) as i64 | (mmap_read32(addr.wrapping_add(4 as u32)) as i64) << 32; } else { return *(mem8.offset(addr as isize) as *mut i64); @@ -92,12 +91,12 @@ pub unsafe fn read64s(mut addr: u32) -> i64 { } #[no_mangle] pub unsafe fn read_aligned32(mut addr: u32) -> i32 { - dbg_assert!(addr < 1073741824i32 as u32); + dbg_assert!(addr < 1073741824 as u32); if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK32 as u32 } - if in_mapped_range(addr << 2i32) { - return mmap_read32(addr << 2i32); + if in_mapped_range(addr << 2) { + return mmap_read32(addr << 2); } else { return *mem32s.offset(addr as isize); @@ -109,17 +108,17 @@ pub unsafe fn read128(mut addr: u32) -> reg128 { addr &= A20_MASK as u32 } let mut value: reg128 = reg128 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; if in_mapped_range(addr) { - value.i32_0[0usize] = mmap_read32(addr); - value.i32_0[1usize] = mmap_read32(addr.wrapping_add(4i32 as u32)); - value.i32_0[2usize] = mmap_read32(addr.wrapping_add(8i32 as u32)); - value.i32_0[3usize] = mmap_read32(addr.wrapping_add(12i32 as u32)) + value.i32_0[0] = mmap_read32(addr); + value.i32_0[1] = mmap_read32(addr.wrapping_add(4 as u32)); + value.i32_0[2] = mmap_read32(addr.wrapping_add(8 as u32)); + value.i32_0[3] = mmap_read32(addr.wrapping_add(12 as u32)) } else { - value.i64_0[0usize] = *(mem8.offset(addr as isize) as *mut i64); - value.i64_0[1usize] = *(mem8.offset(addr as isize).offset(8isize) as *mut i64) + value.i64_0[0] = *(mem8.offset(addr as isize) as *mut i64); + value.i64_0[1] = *(mem8.offset(addr as isize).offset(8) as *mut i64) } return value; } @@ -145,22 +144,22 @@ pub unsafe fn write16(mut addr: u32, mut value: i32) { mmap_write16(addr, value); } else { - ::c_api::jit_dirty_cache_small(addr, addr.wrapping_add(2i32 as u32)); + ::c_api::jit_dirty_cache_small(addr, addr.wrapping_add(2 as u32)); *(mem8.offset(addr as isize) as *mut u16) = value as u16 }; } #[no_mangle] pub unsafe fn write_aligned16(mut addr: u32, mut value: u32) { - dbg_assert!(addr < 2147483648u32); + dbg_assert!(addr < 2147483648); if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK16 as u32 } - let mut phys_addr: u32 = addr << 1i32; + let mut phys_addr: u32 = addr << 1; if in_mapped_range(phys_addr) { mmap_write16(phys_addr, value as i32); } else { - ::c_api::jit_dirty_cache_small(phys_addr, phys_addr.wrapping_add(2i32 as u32)); + ::c_api::jit_dirty_cache_small(phys_addr, phys_addr.wrapping_add(2 as u32)); *mem16.offset(addr as isize) = value as u16 }; } @@ -173,22 +172,22 @@ pub unsafe fn write32(mut addr: u32, mut value: i32) { mmap_write32(addr, value); } else { - ::c_api::jit_dirty_cache_small(addr, addr.wrapping_add(4i32 as u32)); + ::c_api::jit_dirty_cache_small(addr, addr.wrapping_add(4 as u32)); *(mem8.offset(addr as isize) as *mut i32) = value }; } #[no_mangle] pub unsafe fn write_aligned32(mut addr: u32, mut value: i32) { - dbg_assert!(addr < 1073741824i32 as u32); + dbg_assert!(addr < 1073741824 as u32); if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK32 as u32 } - let mut phys_addr: u32 = addr << 2i32; + let mut phys_addr: u32 = addr << 2; if in_mapped_range(phys_addr) { mmap_write32(phys_addr, value); } else { - ::c_api::jit_dirty_cache_small(phys_addr, phys_addr.wrapping_add(4i32 as u32)); + ::c_api::jit_dirty_cache_small(phys_addr, phys_addr.wrapping_add(4 as u32)); *mem32s.offset(addr as isize) = value }; } @@ -199,13 +198,13 @@ pub unsafe fn write64(mut addr: u32, mut value: i64) { } if in_mapped_range(addr) { mmap_write32( - addr.wrapping_add(0i32 as u32), - (value & 4294967295u32 as i64) as i32, + addr.wrapping_add(0 as u32), + (value & 4294967295 as i64) as i32, ); - mmap_write32(addr.wrapping_add(4i32 as u32), (value >> 32i32) as i32); + mmap_write32(addr.wrapping_add(4 as u32), (value >> 32) as i32); } else { - ::c_api::jit_dirty_cache_small(addr, addr.wrapping_add(8i32 as u32)); + ::c_api::jit_dirty_cache_small(addr, addr.wrapping_add(8 as u32)); *(mem8.offset(addr as isize) as *mut i64) = value }; } @@ -217,15 +216,15 @@ pub unsafe fn write128(mut addr: u32, mut value: reg128) { if in_mapped_range(addr) { mmap_write128( addr, - value.i32_0[0usize], - value.i32_0[1usize], - value.i32_0[2usize], - value.i32_0[3usize], + value.i32_0[0], + value.i32_0[1], + value.i32_0[2], + value.i32_0[3], ); } else { - ::c_api::jit_dirty_cache_small(addr, addr.wrapping_add(16i32 as u32)); - *(mem8.offset(addr as isize) as *mut i64) = value.i64_0[0usize]; - *(mem8.offset(addr as isize).offset(8isize) as *mut i64) = value.i64_0[1usize] + ::c_api::jit_dirty_cache_small(addr, addr.wrapping_add(16 as u32)); + *(mem8.offset(addr as isize) as *mut i64) = value.i64_0[0]; + *(mem8.offset(addr as isize).offset(8) as *mut i64) = value.i64_0[1] }; } diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index b416795f..22609662 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -6,22 +6,21 @@ use cpu2::global_pointers::*; #[no_mangle] pub unsafe fn getcf() -> bool { - if 0 != *flags_changed & 1i32 { + if 0 != *flags_changed & 1 { return 0 != (*last_op1 ^ (*last_op1 ^ *last_op2) & (*last_op2 ^ *last_add_result)) >> *last_op_size - & 1i32; + & 1; } else { - return 0 != *flags & 1i32; + return 0 != *flags & 1; }; } #[no_mangle] pub unsafe fn getpf() -> bool { if 0 != *flags_changed & FLAG_PARITY { // inverted lookup table - return 0 - != 38505i32 << 2i32 >> ((*last_result ^ *last_result >> 4i32) & 15i32) & FLAG_PARITY; + return 0 != 38505 << 2 >> ((*last_result ^ *last_result >> 4) & 15) & FLAG_PARITY; } else { return 0 != *flags & FLAG_PARITY; @@ -39,7 +38,7 @@ pub unsafe fn getaf() -> bool { #[no_mangle] pub unsafe fn getzf() -> bool { if 0 != *flags_changed & FLAG_ZERO { - return 0 != (!*last_result & *last_result - 1i32) >> *last_op_size & 1i32; + return 0 != (!*last_result & *last_result - 1) >> *last_op_size & 1; } else { return 0 != *flags & FLAG_ZERO; @@ -48,7 +47,7 @@ pub unsafe fn getzf() -> bool { #[no_mangle] pub unsafe fn getsf() -> bool { if 0 != *flags_changed & FLAG_SIGN { - return 0 != *last_result >> *last_op_size & 1i32; + return 0 != *last_result >> *last_op_size & 1; } else { return 0 != *flags & FLAG_SIGN; @@ -59,7 +58,7 @@ pub unsafe fn getof() -> bool { if 0 != *flags_changed & FLAG_OVERFLOW { return 0 != ((*last_op1 ^ *last_add_result) & (*last_op2 ^ *last_add_result)) >> *last_op_size - & 1i32; + & 1; } else { return 0 != *flags & FLAG_OVERFLOW; @@ -101,7 +100,7 @@ pub unsafe fn test_nle() -> bool { return !test_le(); } pub unsafe fn jmp_rel16(mut rel16: i32) { let mut cs_offset: i32 = get_seg_cs(); // limit ip to 16 bit - *instruction_pointer = cs_offset + (*instruction_pointer - cs_offset + rel16 & 65535i32); + *instruction_pointer = cs_offset + (*instruction_pointer - cs_offset + rel16 & 65535); } #[no_mangle] pub unsafe fn jmpcc16(mut condition: bool, mut imm16: i32) { @@ -124,7 +123,7 @@ pub unsafe fn loopne16(mut imm8s: i32) { jmpcc16(0 != decr_ecx_asize() && !getzf #[no_mangle] pub unsafe fn loop16(mut imm8s: i32) { jmpcc16(0 != decr_ecx_asize(), imm8s); } #[no_mangle] -pub unsafe fn jcxz16(mut imm8s: i32) { jmpcc16(get_reg_asize(ECX) == 0i32, imm8s); } +pub unsafe fn jcxz16(mut imm8s: i32) { jmpcc16(get_reg_asize(ECX) == 0, imm8s); } #[no_mangle] pub unsafe fn loope32(mut imm8s: i32) { jmpcc32(0 != decr_ecx_asize() && 0 != getzf() as i32, imm8s); @@ -134,7 +133,7 @@ pub unsafe fn loopne32(mut imm8s: i32) { jmpcc32(0 != decr_ecx_asize() && !getzf #[no_mangle] pub unsafe fn loop32(mut imm8s: i32) { jmpcc32(0 != decr_ecx_asize(), imm8s); } #[no_mangle] -pub unsafe fn jcxz32(mut imm8s: i32) { jmpcc32(get_reg_asize(ECX) == 0i32, imm8s); } +pub unsafe fn jcxz32(mut imm8s: i32) { jmpcc32(get_reg_asize(ECX) == 0, imm8s); } #[no_mangle] pub unsafe fn cmovcc16(mut condition: bool, mut value: i32, mut r: i32) { if condition { @@ -153,7 +152,7 @@ pub unsafe fn get_stack_pointer(mut offset: i32) -> i32 { return get_seg_ss() + *reg32s.offset(ESP as isize) + offset; } else { - return get_seg_ss() + (*reg16.offset(SP as isize) as i32 + offset & 65535i32); + return get_seg_ss() + (*reg16.offset(SP as isize) as i32 + offset & 65535); }; } #[no_mangle] @@ -168,14 +167,14 @@ pub unsafe fn adjust_stack_reg(mut adjustment: i32) { #[no_mangle] pub unsafe fn push16_ss16(mut imm16: i32) -> Result<(), ()> { - let mut sp: i32 = get_seg_ss() + (*reg16.offset(SP as isize) as i32 - 2i32 & 65535i32); + let mut sp: i32 = get_seg_ss() + (*reg16.offset(SP as isize) as i32 - 2 & 65535); safe_write16(sp, imm16)?; *reg16.offset(SP as isize) -= 2; Ok(()) } #[no_mangle] pub unsafe fn push16_ss32(mut imm16: i32) -> Result<(), ()> { - let mut sp: i32 = get_seg_ss() + *reg32s.offset(ESP as isize) - 2i32; + let mut sp: i32 = get_seg_ss() + *reg32s.offset(ESP as isize) - 2; safe_write16(sp, imm16)?; *reg32s.offset(ESP as isize) -= 2; Ok(()) @@ -208,14 +207,14 @@ pub unsafe fn push16(mut imm16: i32) -> Result<(), ()> { #[no_mangle] pub unsafe fn push32_ss16(mut imm32: i32) -> Result<(), ()> { - let mut new_sp: i32 = *reg16.offset(SP as isize) as i32 - 4i32 & 65535i32; + let mut new_sp: i32 = *reg16.offset(SP as isize) as i32 - 4 & 65535; safe_write32(get_seg_ss() + new_sp, imm32)?; *reg16.offset(SP as isize) = new_sp as u16; Ok(()) } #[no_mangle] pub unsafe fn push32_ss32(mut imm32: i32) -> Result<(), ()> { - let mut new_esp: i32 = *reg32s.offset(ESP as isize) - 4i32; + let mut new_esp: i32 = *reg32s.offset(ESP as isize) - 4; safe_write32(get_seg_ss() + new_esp, imm32)?; *reg32s.offset(ESP as isize) = new_esp; Ok(()) @@ -281,14 +280,14 @@ pub unsafe fn pop32s() -> Result { pub unsafe fn pop32s_ss16() -> Result { let mut sp: i32 = *reg16.offset(SP as isize) as i32; let mut result: i32 = safe_read32s(get_seg_ss() + sp)?; - *reg16.offset(SP as isize) = (sp + 4i32) as u16; + *reg16.offset(SP as isize) = (sp + 4) as u16; Ok(result) } #[no_mangle] pub unsafe fn pop32s_ss32() -> Result { let mut esp: i32 = *reg32s.offset(ESP as isize); let mut result: i32 = safe_read32s(get_seg_ss() + esp)?; - *reg32s.offset(ESP as isize) = esp + 4i32; + *reg32s.offset(ESP as isize) = esp + 4; Ok(result) } #[no_mangle] @@ -296,7 +295,7 @@ pub unsafe fn pusha16() { let mut temp: u16 = *reg16.offset(SP as isize); // make sure we don't get a pagefault after having // pushed several registers already - return_on_pagefault!(writable_or_pagefault(get_stack_pointer(-16i32), 16i32)); + return_on_pagefault!(writable_or_pagefault(get_stack_pointer(-16), 16)); push16(*reg16.offset(AX as isize) as i32).unwrap(); push16(*reg16.offset(CX as isize) as i32).unwrap(); push16(*reg16.offset(DX as isize) as i32).unwrap(); @@ -309,7 +308,7 @@ pub unsafe fn pusha16() { #[no_mangle] pub unsafe fn pusha32() { let mut temp: i32 = *reg32s.offset(ESP as isize); - return_on_pagefault!(writable_or_pagefault(get_stack_pointer(-32i32), 32i32)); + return_on_pagefault!(writable_or_pagefault(get_stack_pointer(-32), 32)); push32(*reg32s.offset(EAX as isize)).unwrap(); push32(*reg32s.offset(ECX as isize)).unwrap(); push32(*reg32s.offset(EDX as isize)).unwrap(); @@ -321,51 +320,41 @@ pub unsafe fn pusha32() { } #[no_mangle] pub unsafe fn setcc_reg(mut condition: bool, mut r: i32) { - write_reg8(r, if 0 != condition as i32 { 1i32 } else { 0i32 }); + write_reg8(r, if 0 != condition as i32 { 1 } else { 0 }); } #[no_mangle] pub unsafe fn setcc_mem(mut condition: bool, mut addr: i32) { - return_on_pagefault!(safe_write8( - addr, - if 0 != condition as i32 { 1i32 } else { 0i32 } - )); + return_on_pagefault!(safe_write8(addr, if 0 != condition as i32 { 1 } else { 0 })); } #[no_mangle] pub unsafe fn fxsave(mut addr: u32) { - return_on_pagefault!(writable_or_pagefault(addr as i32, 512i32)); - safe_write16(addr.wrapping_add(0i32 as u32) as i32, *fpu_control_word).unwrap(); - safe_write16( - addr.wrapping_add(2i32 as u32) as i32, - fpu_load_status_word(), - ).unwrap(); - safe_write8( - addr.wrapping_add(4i32 as u32) as i32, - !*fpu_stack_empty & 255i32, - ).unwrap(); - safe_write16(addr.wrapping_add(6i32 as u32) as i32, *fpu_opcode).unwrap(); - safe_write32(addr.wrapping_add(8i32 as u32) as i32, *fpu_ip).unwrap(); - safe_write16(addr.wrapping_add(12i32 as u32) as i32, *fpu_ip_selector).unwrap(); - safe_write32(addr.wrapping_add(16i32 as u32) as i32, *fpu_dp).unwrap(); - safe_write16(addr.wrapping_add(20i32 as u32) as i32, *fpu_dp_selector).unwrap(); - safe_write32(addr.wrapping_add(24i32 as u32) as i32, *mxcsr).unwrap(); - safe_write32(addr.wrapping_add(28i32 as u32) as i32, MXCSR_MASK).unwrap(); - let mut i: i32 = 0i32; - while i < 8i32 { + return_on_pagefault!(writable_or_pagefault(addr as i32, 512)); + safe_write16(addr.wrapping_add(0 as u32) as i32, *fpu_control_word).unwrap(); + safe_write16(addr.wrapping_add(2 as u32) as i32, fpu_load_status_word()).unwrap(); + safe_write8(addr.wrapping_add(4 as u32) as i32, !*fpu_stack_empty & 255).unwrap(); + safe_write16(addr.wrapping_add(6 as u32) as i32, *fpu_opcode).unwrap(); + safe_write32(addr.wrapping_add(8 as u32) as i32, *fpu_ip).unwrap(); + safe_write16(addr.wrapping_add(12 as u32) as i32, *fpu_ip_selector).unwrap(); + safe_write32(addr.wrapping_add(16 as u32) as i32, *fpu_dp).unwrap(); + safe_write16(addr.wrapping_add(20 as u32) as i32, *fpu_dp_selector).unwrap(); + safe_write32(addr.wrapping_add(24 as u32) as i32, *mxcsr).unwrap(); + safe_write32(addr.wrapping_add(28 as u32) as i32, MXCSR_MASK).unwrap(); + let mut i: i32 = 0; + while i < 8 { fpu_store_m80( - addr.wrapping_add(32i32 as u32) - .wrapping_add((i << 4i32) as u32), - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(i as u32) & 7i32 as u32) as isize), + addr.wrapping_add(32 as u32).wrapping_add((i << 4) as u32), + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(i as u32) & 7 as u32) as isize), ); i += 1 } // If the OSFXSR bit in control register CR4 is not set, the FXSAVE // instruction may not save these registers. This behavior is // implementation dependent. - let mut i_0: i32 = 0i32; - while i_0 < 8i32 { + let mut i_0: i32 = 0; + while i_0 < 8 { safe_write128( - addr.wrapping_add(160i32 as u32) - .wrapping_add((i_0 << 4i32) as u32) as i32, + addr.wrapping_add(160 as u32) + .wrapping_add((i_0 << 4) as u32) as i32, *reg_xmm.offset(i_0 as isize), ).unwrap(); i_0 += 1 @@ -375,55 +364,50 @@ pub unsafe fn fxsave(mut addr: u32) { pub unsafe fn fxrstor(mut addr: u32) { // TODO: Add readable_or_pagefault return_on_pagefault!(translate_address_read(addr as i32)); - return_on_pagefault!(translate_address_read( - addr.wrapping_add(511i32 as u32) as i32 - )); - let mut new_mxcsr: i32 = safe_read32s(addr.wrapping_add(24i32 as u32) as i32).unwrap(); + return_on_pagefault!(translate_address_read(addr.wrapping_add(511 as u32) as i32)); + let mut new_mxcsr: i32 = safe_read32s(addr.wrapping_add(24 as u32) as i32).unwrap(); if 0 != new_mxcsr & !MXCSR_MASK { dbg_log!("#gp Invalid mxcsr bits"); - trigger_gp_non_raising(0i32); + trigger_gp_non_raising(0); return; } else { - *fpu_control_word = safe_read16(addr.wrapping_add(0i32 as u32) as i32).unwrap(); - fpu_set_status_word(safe_read16(addr.wrapping_add(2i32 as u32) as i32).unwrap()); - *fpu_stack_empty = !safe_read8(addr.wrapping_add(4i32 as u32) as i32).unwrap() & 255i32; - *fpu_opcode = safe_read16(addr.wrapping_add(6i32 as u32) as i32).unwrap(); - *fpu_ip = safe_read32s(addr.wrapping_add(8i32 as u32) as i32).unwrap(); - *fpu_ip = safe_read16(addr.wrapping_add(12i32 as u32) as i32).unwrap(); - *fpu_dp = safe_read32s(addr.wrapping_add(16i32 as u32) as i32).unwrap(); - *fpu_dp_selector = safe_read16(addr.wrapping_add(20i32 as u32) as i32).unwrap(); + *fpu_control_word = safe_read16(addr.wrapping_add(0 as u32) as i32).unwrap(); + fpu_set_status_word(safe_read16(addr.wrapping_add(2 as u32) as i32).unwrap()); + *fpu_stack_empty = !safe_read8(addr.wrapping_add(4 as u32) as i32).unwrap() & 255; + *fpu_opcode = safe_read16(addr.wrapping_add(6 as u32) as i32).unwrap(); + *fpu_ip = safe_read32s(addr.wrapping_add(8 as u32) as i32).unwrap(); + *fpu_ip = safe_read16(addr.wrapping_add(12 as u32) as i32).unwrap(); + *fpu_dp = safe_read32s(addr.wrapping_add(16 as u32) as i32).unwrap(); + *fpu_dp_selector = safe_read16(addr.wrapping_add(20 as u32) as i32).unwrap(); set_mxcsr(new_mxcsr); - let mut i: i32 = 0i32; - while i < 8i32 { - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(i as u32) & 7i32 as u32) as isize) = - fpu_load_m80( - addr.wrapping_add(32i32 as u32) - .wrapping_add((i << 4i32) as u32), - ).unwrap(); + let mut i: i32 = 0; + while i < 8 { + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(i as u32) & 7 as u32) as isize) = + fpu_load_m80(addr.wrapping_add(32 as u32).wrapping_add((i << 4) as u32)).unwrap(); i += 1 } - let mut i_0: i32 = 0i32; - while i_0 < 8i32 { - (*reg_xmm.offset(i_0 as isize)).u32_0[0usize] = safe_read32s( - addr.wrapping_add(160i32 as u32) - .wrapping_add((i_0 << 4i32) as u32) - .wrapping_add(0i32 as u32) as i32, + let mut i_0: i32 = 0; + while i_0 < 8 { + (*reg_xmm.offset(i_0 as isize)).u32_0[0] = safe_read32s( + addr.wrapping_add(160 as u32) + .wrapping_add((i_0 << 4) as u32) + .wrapping_add(0 as u32) as i32, ).unwrap() as u32; - (*reg_xmm.offset(i_0 as isize)).u32_0[1usize] = safe_read32s( - addr.wrapping_add(160i32 as u32) - .wrapping_add((i_0 << 4i32) as u32) - .wrapping_add(4i32 as u32) as i32, + (*reg_xmm.offset(i_0 as isize)).u32_0[1] = safe_read32s( + addr.wrapping_add(160 as u32) + .wrapping_add((i_0 << 4) as u32) + .wrapping_add(4 as u32) as i32, ).unwrap() as u32; - (*reg_xmm.offset(i_0 as isize)).u32_0[2usize] = safe_read32s( - addr.wrapping_add(160i32 as u32) - .wrapping_add((i_0 << 4i32) as u32) - .wrapping_add(8i32 as u32) as i32, + (*reg_xmm.offset(i_0 as isize)).u32_0[2] = safe_read32s( + addr.wrapping_add(160 as u32) + .wrapping_add((i_0 << 4) as u32) + .wrapping_add(8 as u32) as i32, ).unwrap() as u32; - (*reg_xmm.offset(i_0 as isize)).u32_0[3usize] = safe_read32s( - addr.wrapping_add(160i32 as u32) - .wrapping_add((i_0 << 4i32) as u32) - .wrapping_add(12i32 as u32) as i32, + (*reg_xmm.offset(i_0 as isize)).u32_0[3] = safe_read32s( + addr.wrapping_add(160 as u32) + .wrapping_add((i_0 << 4) as u32) + .wrapping_add(12 as u32) as i32, ).unwrap() as u32; i_0 += 1 } diff --git a/src/rust/cpu2/modrm.rs b/src/rust/cpu2/modrm.rs index 9c86bfd0..022c203f 100644 --- a/src/rust/cpu2/modrm.rs +++ b/src/rust/cpu2/modrm.rs @@ -6,99 +6,99 @@ use cpu2::global_pointers::*; pub unsafe fn resolve_modrm16(mut modrm_byte: i32) -> Result { Ok(match modrm_byte { 0 | 8 | 16 | 24 | 32 | 40 | 48 | 56 => get_seg_prefix_ds( - *reg16.offset(BX as isize) as i32 + *reg16.offset(SI as isize) as i32 & 65535i32, + *reg16.offset(BX as isize) as i32 + *reg16.offset(SI as isize) as i32 & 65535, ), 64 | 72 | 80 | 88 | 96 | 104 | 112 | 120 => get_seg_prefix_ds( *reg16.offset(BX as isize) as i32 + *reg16.offset(SI as isize) as i32 + read_imm8s()? - & 65535i32, + & 65535, ), 128 | 136 | 144 | 152 | 160 | 168 | 176 | 184 => get_seg_prefix_ds( *reg16.offset(BX as isize) as i32 + *reg16.offset(SI as isize) as i32 + read_imm16()? - & 65535i32, + & 65535, ), 1 | 9 | 17 | 25 | 33 | 41 | 49 | 57 => get_seg_prefix_ds( - *reg16.offset(BX as isize) as i32 + *reg16.offset(DI as isize) as i32 & 65535i32, + *reg16.offset(BX as isize) as i32 + *reg16.offset(DI as isize) as i32 & 65535, ), 65 | 73 | 81 | 89 | 97 | 105 | 113 | 121 => get_seg_prefix_ds( *reg16.offset(BX as isize) as i32 + *reg16.offset(DI as isize) as i32 + read_imm8s()? - & 65535i32, + & 65535, ), 129 | 137 | 145 | 153 | 161 | 169 | 177 | 185 => get_seg_prefix_ds( *reg16.offset(BX as isize) as i32 + *reg16.offset(DI as isize) as i32 + read_imm16()? - & 65535i32, + & 65535, ), 2 | 10 | 18 | 26 | 34 | 42 | 50 | 58 => get_seg_prefix_ss( - *reg16.offset(BP as isize) as i32 + *reg16.offset(SI as isize) as i32 & 65535i32, + *reg16.offset(BP as isize) as i32 + *reg16.offset(SI as isize) as i32 & 65535, ), 66 | 74 | 82 | 90 | 98 | 106 | 114 | 122 => get_seg_prefix_ss( *reg16.offset(BP as isize) as i32 + *reg16.offset(SI as isize) as i32 + read_imm8s()? - & 65535i32, + & 65535, ), 130 | 138 | 146 | 154 | 162 | 170 | 178 | 186 => get_seg_prefix_ss( *reg16.offset(BP as isize) as i32 + *reg16.offset(SI as isize) as i32 + read_imm16()? - & 65535i32, + & 65535, ), 3 | 11 | 19 | 27 | 35 | 43 | 51 | 59 => get_seg_prefix_ss( - *reg16.offset(BP as isize) as i32 + *reg16.offset(DI as isize) as i32 & 65535i32, + *reg16.offset(BP as isize) as i32 + *reg16.offset(DI as isize) as i32 & 65535, ), 67 | 75 | 83 | 91 | 99 | 107 | 115 | 123 => get_seg_prefix_ss( *reg16.offset(BP as isize) as i32 + *reg16.offset(DI as isize) as i32 + read_imm8s()? - & 65535i32, + & 65535, ), 131 | 139 | 147 | 155 | 163 | 171 | 179 | 187 => get_seg_prefix_ss( *reg16.offset(BP as isize) as i32 + *reg16.offset(DI as isize) as i32 + read_imm16()? - & 65535i32, + & 65535, ), 4 | 12 | 20 | 28 | 36 | 44 | 52 | 60 => { - get_seg_prefix_ds(*reg16.offset(SI as isize) as i32 & 65535i32) + get_seg_prefix_ds(*reg16.offset(SI as isize) as i32 & 65535) }, 68 | 76 | 84 | 92 | 100 | 108 | 116 | 124 => { - get_seg_prefix_ds(*reg16.offset(SI as isize) as i32 + read_imm8s()? & 65535i32) + get_seg_prefix_ds(*reg16.offset(SI as isize) as i32 + read_imm8s()? & 65535) }, 132 | 140 | 148 | 156 | 164 | 172 | 180 | 188 => { - get_seg_prefix_ds(*reg16.offset(SI as isize) as i32 + read_imm16()? & 65535i32) + get_seg_prefix_ds(*reg16.offset(SI as isize) as i32 + read_imm16()? & 65535) }, 5 | 13 | 21 | 29 | 37 | 45 | 53 | 61 => { - get_seg_prefix_ds(*reg16.offset(DI as isize) as i32 & 65535i32) + get_seg_prefix_ds(*reg16.offset(DI as isize) as i32 & 65535) }, 69 | 77 | 85 | 93 | 101 | 109 | 117 | 125 => { - get_seg_prefix_ds(*reg16.offset(DI as isize) as i32 + read_imm8s()? & 65535i32) + get_seg_prefix_ds(*reg16.offset(DI as isize) as i32 + read_imm8s()? & 65535) }, 133 | 141 | 149 | 157 | 165 | 173 | 181 | 189 => { - get_seg_prefix_ds(*reg16.offset(DI as isize) as i32 + read_imm16()? & 65535i32) + get_seg_prefix_ds(*reg16.offset(DI as isize) as i32 + read_imm16()? & 65535) }, 6 | 14 | 22 | 30 | 38 | 46 | 54 | 62 => get_seg_prefix_ds(read_imm16()?), 70 | 78 | 86 | 94 | 102 | 110 | 118 | 126 => { - get_seg_prefix_ss(*reg16.offset(BP as isize) as i32 + read_imm8s()? & 65535i32) + get_seg_prefix_ss(*reg16.offset(BP as isize) as i32 + read_imm8s()? & 65535) }, 134 | 142 | 150 | 158 | 166 | 174 | 182 | 190 => { - get_seg_prefix_ss(*reg16.offset(BP as isize) as i32 + read_imm16()? & 65535i32) + get_seg_prefix_ss(*reg16.offset(BP as isize) as i32 + read_imm16()? & 65535) }, 7 | 15 | 23 | 31 | 39 | 47 | 55 | 63 => { - get_seg_prefix_ds(*reg16.offset(BX as isize) as i32 & 65535i32) + get_seg_prefix_ds(*reg16.offset(BX as isize) as i32 & 65535) }, 71 | 79 | 87 | 95 | 103 | 111 | 119 | 127 => { - get_seg_prefix_ds(*reg16.offset(BX as isize) as i32 + read_imm8s()? & 65535i32) + get_seg_prefix_ds(*reg16.offset(BX as isize) as i32 + read_imm8s()? & 65535) }, 135 | 143 | 151 | 159 | 167 | 175 | 183 | 191 => { - get_seg_prefix_ds(*reg16.offset(BX as isize) as i32 + read_imm16()? & 65535i32) + get_seg_prefix_ds(*reg16.offset(BX as isize) as i32 + read_imm16()? & 65535) }, _ => { - dbg_assert!(0 != 0i32); - 0i32 + dbg_assert!(0 != 0); + 0 }, }) } pub unsafe fn resolve_modrm32_(mut modrm_byte: i32) -> Result { - let mut r: u8 = (modrm_byte & 7i32) as u8; - dbg_assert!(modrm_byte < 192i32); - Ok(if r as i32 == 4i32 { - if modrm_byte < 64i32 { - resolve_sib(0 != 0i32)? + let mut r: u8 = (modrm_byte & 7) as u8; + dbg_assert!(modrm_byte < 192); + Ok(if r as i32 == 4 { + if modrm_byte < 64 { + resolve_sib(0 != 0)? } else { - resolve_sib(0 != 1i32)? + if modrm_byte < 128i32 { + resolve_sib(0 != 1)? + if modrm_byte < 128 { read_imm8s()? } else { @@ -106,13 +106,13 @@ pub unsafe fn resolve_modrm32_(mut modrm_byte: i32) -> Result { } } } - else if r as i32 == 5i32 { - if modrm_byte < 64i32 { + else if r as i32 == 5 { + if modrm_byte < 64 { get_seg_prefix_ds(read_imm32s()?) } else { get_seg_prefix_ss( - *reg32s.offset(EBP as isize) + if modrm_byte < 128i32 { + *reg32s.offset(EBP as isize) + if modrm_byte < 128 { read_imm8s()? } else { @@ -121,12 +121,12 @@ pub unsafe fn resolve_modrm32_(mut modrm_byte: i32) -> Result { ) } } - else if modrm_byte < 64i32 { + else if modrm_byte < 64 { get_seg_prefix_ds(*reg32s.offset(r as isize)) } else { get_seg_prefix_ds( - *reg32s.offset(r as isize) + if modrm_byte < 128i32 { + *reg32s.offset(r as isize) + if modrm_byte < 128 { read_imm8s()? } else { @@ -138,15 +138,15 @@ pub unsafe fn resolve_modrm32_(mut modrm_byte: i32) -> Result { unsafe fn resolve_sib(mut mod_0: bool) -> Result { let mut s; let mut sib_byte: u8 = read_imm8()? as u8; - let mut r: u8 = (sib_byte as i32 & 7i32) as u8; - let mut m: u8 = (sib_byte as i32 >> 3i32 & 7i32) as u8; + let mut r: u8 = (sib_byte as i32 & 7) as u8; + let mut m: u8 = (sib_byte as i32 >> 3 & 7) as u8; let mut base; let mut seg; - if r as i32 == 4i32 { + if r as i32 == 4 { base = *reg32s.offset(ESP as isize); seg = SS } - else if r as i32 == 5i32 { + else if r as i32 == 5 { if mod_0 { base = *reg32s.offset(EBP as isize); seg = SS @@ -161,11 +161,11 @@ unsafe fn resolve_sib(mut mod_0: bool) -> Result { seg = DS } let mut offset; - if m as i32 == 4i32 { - offset = 0i32 + if m as i32 == 4 { + offset = 0 } else { - s = (sib_byte as i32 >> 6i32 & 3i32) as u8; + s = (sib_byte as i32 >> 6 & 3) as u8; offset = *reg32s.offset(m as isize) << s as i32 } Ok(get_seg_prefix(seg) + base + offset) @@ -201,9 +201,9 @@ pub unsafe fn resolve_modrm32(mut modrm_byte: i32) -> Result { 131 | 139 | 147 | 155 | 163 | 171 | 179 | 187 => { get_seg_prefix_ds(*reg32s.offset(EBX as isize) + read_imm32s()?) }, - 4 | 12 | 20 | 28 | 36 | 44 | 52 | 60 => resolve_sib(0 != 0i32)?, - 68 | 76 | 84 | 92 | 100 | 108 | 116 | 124 => resolve_sib(0 != 1i32)? + read_imm8s()?, - 132 | 140 | 148 | 156 | 164 | 172 | 180 | 188 => resolve_sib(0 != 1i32)? + read_imm32s()?, + 4 | 12 | 20 | 28 | 36 | 44 | 52 | 60 => resolve_sib(0 != 0)?, + 68 | 76 | 84 | 92 | 100 | 108 | 116 | 124 => resolve_sib(0 != 1)? + read_imm8s()?, + 132 | 140 | 148 | 156 | 164 | 172 | 180 | 188 => resolve_sib(0 != 1)? + read_imm32s()?, 5 | 13 | 21 | 29 | 37 | 45 | 53 | 61 => get_seg_prefix_ds(read_imm32s()?), 69 | 77 | 85 | 93 | 101 | 109 | 117 | 125 => { get_seg_prefix_ss(*reg32s.offset(EBP as isize) + read_imm8s()?) @@ -226,8 +226,8 @@ pub unsafe fn resolve_modrm32(mut modrm_byte: i32) -> Result { get_seg_prefix_ds(*reg32s.offset(EDI as isize) + read_imm32s()?) }, _ => { - dbg_assert!(0 != 0i32); - 0i32 + dbg_assert!(0 != 0); + 0 }, }) } diff --git a/src/rust/cpu2/profiler.rs b/src/rust/cpu2/profiler.rs index 93dceeb1..e4d9d50f 100644 --- a/src/rust/cpu2/profiler.rs +++ b/src/rust/cpu2/profiler.rs @@ -48,7 +48,7 @@ pub const S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE: StatName = 24; pub const S_NONFAULTING_OPTIMIZATION: StatName = 32; #[no_mangle] pub static mut profiler_stat_arr: [profiler_stat; 37] = [ - profiler_stat { count: 0i32 }, + profiler_stat { count: 0 }, profiler_stat { count: 0 }, profiler_stat { count: 0 }, profiler_stat { count: 0 }, @@ -88,16 +88,14 @@ pub static mut profiler_stat_arr: [profiler_stat; 37] = [ ]; #[no_mangle] pub unsafe fn profiler_init() { - let mut i: u32 = 0i32 as u32; - while i < (S_TLB_GLOBAL_FULL as i32 - S_COMPILE as i32 + 1i32) as u32 { - profiler_stat_arr[i as usize].count = 0i32; + let mut i: u32 = 0 as u32; + while i < (S_TLB_GLOBAL_FULL as i32 - S_COMPILE as i32 + 1) as u32 { + profiler_stat_arr[i as usize].count = 0; i = i.wrapping_add(1) } } #[no_mangle] -pub unsafe fn profiler_stat_increment(mut stat: StatName) { - profiler_stat_increment_by(stat, 1i32); -} +pub unsafe fn profiler_stat_increment(mut stat: StatName) { profiler_stat_increment_by(stat, 1); } #[no_mangle] pub unsafe fn profiler_stat_increment_by(mut stat: StatName, mut by: i32) { if cfg!(feature = "profiler") { diff --git a/src/rust/cpu2/sse_instr.rs b/src/rust/cpu2/sse_instr.rs index 49619c01..700279b7 100644 --- a/src/rust/cpu2/sse_instr.rs +++ b/src/rust/cpu2/sse_instr.rs @@ -6,13 +6,13 @@ use cpu2::cpu::*; pub unsafe fn mov_r_m64(mut addr: i32, mut r: i32) { // mov* m64, mm let mut data: reg64 = read_mmx64s(r); - return_on_pagefault!(safe_write64(addr, data.u64_0[0usize] as i64)); + return_on_pagefault!(safe_write64(addr, data.u64_0[0] as i64)); } #[no_mangle] pub unsafe fn movl_r128_m64(mut addr: i32, mut r: i32) { // mov* m64, xmm let mut data: reg64 = read_xmm64s(r); - return_on_pagefault!(safe_write64(addr, data.u64_0[0usize] as i64)); + return_on_pagefault!(safe_write64(addr, data.u64_0[0] as i64)); } #[no_mangle] pub unsafe fn mov_r_r128(mut r1: i32, mut r2: i32) { @@ -38,17 +38,17 @@ pub unsafe fn movh_m64_r128(mut addr: i32, mut r: i32) { let mut orig: reg128 = read_xmm128s(r); write_xmm128( r, - orig.u32_0[0usize] as i32, - orig.u32_0[1usize] as i32, - data.u32_0[0usize] as i32, - data.u32_0[1usize] as i32, + orig.u32_0[0] as i32, + orig.u32_0[1] as i32, + data.u32_0[0] as i32, + data.u32_0[1] as i32, ); } #[no_mangle] pub unsafe fn movh_r128_m64(mut addr: i32, mut r: i32) { // movhp* m64, xmm let mut data: reg128 = read_xmm128s(r); - return_on_pagefault!(safe_write64(addr, data.u64_0[1usize] as i64)); + return_on_pagefault!(safe_write64(addr, data.u64_0[1] as i64)); } #[no_mangle] pub unsafe fn pand_r128(mut source: reg128, mut r: i32) { @@ -56,10 +56,10 @@ pub unsafe fn pand_r128(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - result.u64_0[0usize] = source.u64_0[0usize] & destination.u64_0[0usize]; - result.u64_0[1usize] = source.u64_0[1usize] & destination.u64_0[1usize]; + result.u64_0[0] = source.u64_0[0] & destination.u64_0[0]; + result.u64_0[1] = source.u64_0[1] & destination.u64_0[1]; write_xmm_reg128(r, result); } #[no_mangle] @@ -68,10 +68,10 @@ pub unsafe fn pandn_r128(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - result.u64_0[0usize] = source.u64_0[0usize] & !destination.u64_0[0usize]; - result.u64_0[1usize] = source.u64_0[1usize] & !destination.u64_0[1usize]; + result.u64_0[0] = source.u64_0[0] & !destination.u64_0[0]; + result.u64_0[1] = source.u64_0[1] & !destination.u64_0[1]; write_xmm_reg128(r, result); } #[no_mangle] @@ -80,10 +80,10 @@ pub unsafe fn pxor_r128(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - result.u64_0[0usize] = source.u64_0[0usize] ^ destination.u64_0[0usize]; - result.u64_0[1usize] = source.u64_0[1usize] ^ destination.u64_0[1usize]; + result.u64_0[0] = source.u64_0[0] ^ destination.u64_0[0]; + result.u64_0[1] = source.u64_0[1] ^ destination.u64_0[1]; write_xmm_reg128(r, result); } #[no_mangle] @@ -92,23 +92,21 @@ pub unsafe fn por_r128(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - result.u64_0[0usize] = source.u64_0[0usize] | destination.u64_0[0usize]; - result.u64_0[1usize] = source.u64_0[1usize] | destination.u64_0[1usize]; + result.u64_0[0] = source.u64_0[0] | destination.u64_0[0]; + result.u64_0[1] = source.u64_0[1] | destination.u64_0[1]; write_xmm_reg128(r, result); } #[no_mangle] pub unsafe fn psrlw_r64(mut r: i32, mut shift: u32) { // psrlw mm, {shift} let mut destination: reg64 = read_mmx64s(r); - let mut dword0: i32 = 0i32; - let mut dword1: i32 = 0i32; - if shift <= 15i32 as u32 { - dword0 = destination.u16_0[0usize] as i32 >> shift - | destination.u16_0[1usize] as i32 >> shift << 16i32; - dword1 = destination.u16_0[2usize] as i32 >> shift - | destination.u16_0[3usize] as i32 >> shift << 16i32 + let mut dword0: i32 = 0; + let mut dword1: i32 = 0; + if shift <= 15 as u32 { + dword0 = destination.u16_0[0] as i32 >> shift | destination.u16_0[1] as i32 >> shift << 16; + dword1 = destination.u16_0[2] as i32 >> shift | destination.u16_0[3] as i32 >> shift << 16 } write_mmx64(r, dword0, dword1); } @@ -116,29 +114,24 @@ pub unsafe fn psrlw_r64(mut r: i32, mut shift: u32) { pub unsafe fn psraw_r64(mut r: i32, mut shift: u32) { // psraw mm, {shift} let mut destination: reg64 = read_mmx64s(r); - let mut shift_clamped: i32 = (if shift > 15i32 as u32 { - 16i32 as u32 - } - else { - shift - }) as i32; - let mut dword0: i32 = destination.i16_0[0usize] as i32 >> shift_clamped & 65535i32 - | destination.i16_0[1usize] as i32 >> shift_clamped << 16i32; - let mut dword1: i32 = destination.i16_0[2usize] as i32 >> shift_clamped & 65535i32 - | destination.i16_0[3usize] as i32 >> shift_clamped << 16i32; + let mut shift_clamped: i32 = (if shift > 15 as u32 { 16 as u32 } else { shift }) as i32; + let mut dword0: i32 = destination.i16_0[0] as i32 >> shift_clamped & 65535 + | destination.i16_0[1] as i32 >> shift_clamped << 16; + let mut dword1: i32 = destination.i16_0[2] as i32 >> shift_clamped & 65535 + | destination.i16_0[3] as i32 >> shift_clamped << 16; write_mmx64(r, dword0, dword1); } #[no_mangle] pub unsafe fn psllw_r64(mut r: i32, mut shift: u32) { // psllw mm, {shift} let mut destination: reg64 = read_mmx64s(r); - let mut dword0: i32 = 0i32; - let mut dword1: i32 = 0i32; - if shift <= 15i32 as u32 { - dword0 = (destination.u16_0[0usize] as i32) << shift & 65535i32 - | (destination.u16_0[1usize] as i32) << shift << 16i32; - dword1 = (destination.u16_0[2usize] as i32) << shift & 65535i32 - | (destination.u16_0[3usize] as i32) << shift << 16i32 + let mut dword0: i32 = 0; + let mut dword1: i32 = 0; + if shift <= 15 as u32 { + dword0 = (destination.u16_0[0] as i32) << shift & 65535 + | (destination.u16_0[1] as i32) << shift << 16; + dword1 = (destination.u16_0[2] as i32) << shift & 65535 + | (destination.u16_0[3] as i32) << shift << 16 } write_mmx64(r, dword0, dword1); } @@ -146,11 +139,11 @@ pub unsafe fn psllw_r64(mut r: i32, mut shift: u32) { pub unsafe fn psrld_r64(mut r: i32, mut shift: u32) { // psrld mm, {shift} let mut destination: reg64 = read_mmx64s(r); - let mut dword0: i32 = 0i32; - let mut dword1: i32 = 0i32; - if shift <= 31i32 as u32 { - dword0 = (destination.u32_0[0usize] >> shift) as i32; - dword1 = (destination.u32_0[1usize] >> shift) as i32 + let mut dword0: i32 = 0; + let mut dword1: i32 = 0; + if shift <= 31 as u32 { + dword0 = (destination.u32_0[0] >> shift) as i32; + dword1 = (destination.u32_0[1] >> shift) as i32 } write_mmx64(r, dword0, dword1); } @@ -158,41 +151,36 @@ pub unsafe fn psrld_r64(mut r: i32, mut shift: u32) { pub unsafe fn psrad_r64(mut r: i32, mut shift: u32) { // psrad mm, {shift} let mut destination: reg64 = read_mmx64s(r); - let mut shift_clamped: i32 = (if shift > 31i32 as u32 { - 31i32 as u32 - } - else { - shift - }) as i32; - let mut dword0: i32 = destination.i32_0[0usize] >> shift_clamped; - let mut dword1: i32 = destination.i32_0[1usize] >> shift_clamped; + let mut shift_clamped: i32 = (if shift > 31 as u32 { 31 as u32 } else { shift }) as i32; + let mut dword0: i32 = destination.i32_0[0] >> shift_clamped; + let mut dword1: i32 = destination.i32_0[1] >> shift_clamped; write_mmx64(r, dword0, dword1); } #[no_mangle] pub unsafe fn pslld_r64(mut r: i32, mut shift: u32) { // pslld mm, {shift} let mut destination: reg64 = read_mmx64s(r); - let mut dword0: i32 = 0i32; - let mut dword1: i32 = 0i32; - if shift <= 31i32 as u32 { - dword0 = destination.i32_0[0usize] << shift; - dword1 = destination.i32_0[1usize] << shift + let mut dword0: i32 = 0; + let mut dword1: i32 = 0; + if shift <= 31 as u32 { + dword0 = destination.i32_0[0] << shift; + dword1 = destination.i32_0[1] << shift } write_mmx64(r, dword0, dword1); } #[no_mangle] pub unsafe fn psrlq_r64(mut r: i32, mut shift: u32) { // psrlq mm, {shift} - if shift == 0i32 as u32 { + if shift == 0 as u32 { return; } else { let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - if shift <= 63i32 as u32 { - result.u64_0[0usize] = destination.u64_0[0usize] >> shift + if shift <= 63 as u32 { + result.u64_0[0] = destination.u64_0[0] >> shift } write_mmx_reg64(r, result); return; @@ -202,15 +190,15 @@ pub unsafe fn psrlq_r64(mut r: i32, mut shift: u32) { pub unsafe fn psllq_r64(mut r: i32, mut shift: u32) { // psllq mm, {shift} let mut destination: reg64 = read_mmx64s(r); - if shift == 0i32 as u32 { + if shift == 0 as u32 { return; } else { let mut result: reg64 = reg64 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - if shift <= 63i32 as u32 { - result.u64_0[0usize] = destination.u64_0[0usize] << shift + if shift <= 63 as u32 { + result.u64_0[0] = destination.u64_0[0] << shift } write_mmx_reg64(r, result); return; @@ -220,19 +208,15 @@ pub unsafe fn psllq_r64(mut r: i32, mut shift: u32) { pub unsafe fn psrlw_r128(mut r: i32, mut shift: u32) { // psrlw xmm, {shift} let mut destination: reg128 = read_xmm128s(r); - let mut dword0: i32 = 0i32; - let mut dword1: i32 = 0i32; - let mut dword2: i32 = 0i32; - let mut dword3: i32 = 0i32; - if shift <= 15i32 as u32 { - dword0 = destination.u16_0[0usize] as i32 >> shift - | destination.u16_0[1usize] as i32 >> shift << 16i32; - dword1 = destination.u16_0[2usize] as i32 >> shift - | destination.u16_0[3usize] as i32 >> shift << 16i32; - dword2 = destination.u16_0[4usize] as i32 >> shift - | destination.u16_0[5usize] as i32 >> shift << 16i32; - dword3 = destination.u16_0[6usize] as i32 >> shift - | destination.u16_0[7usize] as i32 >> shift << 16i32 + let mut dword0: i32 = 0; + let mut dword1: i32 = 0; + let mut dword2: i32 = 0; + let mut dword3: i32 = 0; + if shift <= 15 as u32 { + dword0 = destination.u16_0[0] as i32 >> shift | destination.u16_0[1] as i32 >> shift << 16; + dword1 = destination.u16_0[2] as i32 >> shift | destination.u16_0[3] as i32 >> shift << 16; + dword2 = destination.u16_0[4] as i32 >> shift | destination.u16_0[5] as i32 >> shift << 16; + dword3 = destination.u16_0[6] as i32 >> shift | destination.u16_0[7] as i32 >> shift << 16 } write_xmm128(r, dword0, dword1, dword2, dword3); } @@ -240,39 +224,34 @@ pub unsafe fn psrlw_r128(mut r: i32, mut shift: u32) { pub unsafe fn psraw_r128(mut r: i32, mut shift: u32) { // psraw xmm, {shift} let mut destination: reg128 = read_xmm128s(r); - let mut shift_clamped: i32 = (if shift > 15i32 as u32 { - 16i32 as u32 - } - else { - shift - }) as i32; - let mut dword0: i32 = destination.i16_0[0usize] as i32 >> shift_clamped & 65535i32 - | destination.i16_0[1usize] as i32 >> shift_clamped << 16i32; - let mut dword1: i32 = destination.i16_0[2usize] as i32 >> shift_clamped & 65535i32 - | destination.i16_0[3usize] as i32 >> shift_clamped << 16i32; - let mut dword2: i32 = destination.i16_0[4usize] as i32 >> shift_clamped & 65535i32 - | destination.i16_0[5usize] as i32 >> shift_clamped << 16i32; - let mut dword3: i32 = destination.i16_0[6usize] as i32 >> shift_clamped & 65535i32 - | destination.i16_0[7usize] as i32 >> shift_clamped << 16i32; + let mut shift_clamped: i32 = (if shift > 15 as u32 { 16 as u32 } else { shift }) as i32; + let mut dword0: i32 = destination.i16_0[0] as i32 >> shift_clamped & 65535 + | destination.i16_0[1] as i32 >> shift_clamped << 16; + let mut dword1: i32 = destination.i16_0[2] as i32 >> shift_clamped & 65535 + | destination.i16_0[3] as i32 >> shift_clamped << 16; + let mut dword2: i32 = destination.i16_0[4] as i32 >> shift_clamped & 65535 + | destination.i16_0[5] as i32 >> shift_clamped << 16; + let mut dword3: i32 = destination.i16_0[6] as i32 >> shift_clamped & 65535 + | destination.i16_0[7] as i32 >> shift_clamped << 16; write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] pub unsafe fn psllw_r128(mut r: i32, mut shift: u32) { // psllw xmm, {shift} let mut destination: reg128 = read_xmm128s(r); - let mut dword0: i32 = 0i32; - let mut dword1: i32 = 0i32; - let mut dword2: i32 = 0i32; - let mut dword3: i32 = 0i32; - if shift <= 15i32 as u32 { - dword0 = (destination.u16_0[0usize] as i32) << shift & 65535i32 - | (destination.u16_0[1usize] as i32) << shift << 16i32; - dword1 = (destination.u16_0[2usize] as i32) << shift & 65535i32 - | (destination.u16_0[3usize] as i32) << shift << 16i32; - dword2 = (destination.u16_0[4usize] as i32) << shift & 65535i32 - | (destination.u16_0[5usize] as i32) << shift << 16i32; - dword3 = (destination.u16_0[6usize] as i32) << shift & 65535i32 - | (destination.u16_0[7usize] as i32) << shift << 16i32 + let mut dword0: i32 = 0; + let mut dword1: i32 = 0; + let mut dword2: i32 = 0; + let mut dword3: i32 = 0; + if shift <= 15 as u32 { + dword0 = (destination.u16_0[0] as i32) << shift & 65535 + | (destination.u16_0[1] as i32) << shift << 16; + dword1 = (destination.u16_0[2] as i32) << shift & 65535 + | (destination.u16_0[3] as i32) << shift << 16; + dword2 = (destination.u16_0[4] as i32) << shift & 65535 + | (destination.u16_0[5] as i32) << shift << 16; + dword3 = (destination.u16_0[6] as i32) << shift & 65535 + | (destination.u16_0[7] as i32) << shift << 16 } write_xmm128(r, dword0, dword1, dword2, dword3); } @@ -280,15 +259,15 @@ pub unsafe fn psllw_r128(mut r: i32, mut shift: u32) { pub unsafe fn psrld_r128(mut r: i32, mut shift: u32) { // psrld xmm, {shift} let mut destination: reg128 = read_xmm128s(r); - let mut dword0: i32 = 0i32; - let mut dword1: i32 = 0i32; - let mut dword2: i32 = 0i32; - let mut dword3: i32 = 0i32; - if shift <= 31i32 as u32 { - dword0 = (destination.u32_0[0usize] >> shift) as i32; - dword1 = (destination.u32_0[1usize] >> shift) as i32; - dword2 = (destination.u32_0[2usize] >> shift) as i32; - dword3 = (destination.u32_0[3usize] >> shift) as i32 + let mut dword0: i32 = 0; + let mut dword1: i32 = 0; + let mut dword2: i32 = 0; + let mut dword3: i32 = 0; + if shift <= 31 as u32 { + dword0 = (destination.u32_0[0] >> shift) as i32; + dword1 = (destination.u32_0[1] >> shift) as i32; + dword2 = (destination.u32_0[2] >> shift) as i32; + dword3 = (destination.u32_0[3] >> shift) as i32 } write_xmm128(r, dword0, dword1, dword2, dword3); } @@ -296,48 +275,43 @@ pub unsafe fn psrld_r128(mut r: i32, mut shift: u32) { pub unsafe fn psrad_r128(mut r: i32, mut shift: u32) { // psrad xmm, {shift} let mut destination: reg128 = read_xmm128s(r); - let mut shift_clamped: i32 = (if shift > 31i32 as u32 { - 31i32 as u32 - } - else { - shift - }) as i32; - let mut dword0: i32 = destination.i32_0[0usize] >> shift_clamped; - let mut dword1: i32 = destination.i32_0[1usize] >> shift_clamped; - let mut dword2: i32 = destination.i32_0[2usize] >> shift_clamped; - let mut dword3: i32 = destination.i32_0[3usize] >> shift_clamped; + let mut shift_clamped: i32 = (if shift > 31 as u32 { 31 as u32 } else { shift }) as i32; + let mut dword0: i32 = destination.i32_0[0] >> shift_clamped; + let mut dword1: i32 = destination.i32_0[1] >> shift_clamped; + let mut dword2: i32 = destination.i32_0[2] >> shift_clamped; + let mut dword3: i32 = destination.i32_0[3] >> shift_clamped; write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] pub unsafe fn pslld_r128(mut r: i32, mut shift: u32) { // pslld xmm, {shift} let mut destination: reg128 = read_xmm128s(r); - let mut dword0: i32 = 0i32; - let mut dword1: i32 = 0i32; - let mut dword2: i32 = 0i32; - let mut dword3: i32 = 0i32; - if shift <= 31i32 as u32 { - dword0 = destination.i32_0[0usize] << shift; - dword1 = destination.i32_0[1usize] << shift; - dword2 = destination.i32_0[2usize] << shift; - dword3 = destination.i32_0[3usize] << shift + let mut dword0: i32 = 0; + let mut dword1: i32 = 0; + let mut dword2: i32 = 0; + let mut dword3: i32 = 0; + if shift <= 31 as u32 { + dword0 = destination.i32_0[0] << shift; + dword1 = destination.i32_0[1] << shift; + dword2 = destination.i32_0[2] << shift; + dword3 = destination.i32_0[3] << shift } write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] pub unsafe fn psrlq_r128(mut r: i32, mut shift: u32) { // psrlq xmm, {shift} - if shift == 0i32 as u32 { + if shift == 0 as u32 { return; } else { let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - if shift <= 63i32 as u32 { - result.u64_0[0usize] = destination.u64_0[0usize] >> shift; - result.u64_0[1usize] = destination.u64_0[1usize] >> shift + if shift <= 63 as u32 { + result.u64_0[0] = destination.u64_0[0] >> shift; + result.u64_0[1] = destination.u64_0[1] >> shift } write_xmm_reg128(r, result); return; @@ -347,16 +321,16 @@ pub unsafe fn psrlq_r128(mut r: i32, mut shift: u32) { pub unsafe fn psllq_r128(mut r: i32, mut shift: u32) { // psllq xmm, {shift} let mut destination: reg128 = read_xmm128s(r); - if shift == 0i32 as u32 { + if shift == 0 as u32 { return; } else { let mut result: reg128 = reg128 { - i8_0: [0i32 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - if shift <= 63i32 as u32 { - result.u64_0[0usize] = destination.u64_0[0usize] << shift; - result.u64_0[1usize] = destination.u64_0[1usize] << shift + if shift <= 63 as u32 { + result.u64_0[0] = destination.u64_0[0] << shift; + result.u64_0[1] = destination.u64_0[1] << shift } write_xmm_reg128(r, result); return; @@ -365,7 +339,7 @@ pub unsafe fn psllq_r128(mut r: i32, mut shift: u32) { #[no_mangle] pub unsafe fn sse_comparison(mut op: i32, mut x: f64, mut y: f64) -> bool { // TODO: Signaling - match op & 7i32 { + match op & 7 { 0 => return x == y, 1 => return x < y, 2 => return x <= y, @@ -375,8 +349,8 @@ pub unsafe fn sse_comparison(mut op: i32, mut x: f64, mut y: f64) -> bool { 6 => return x > y || 0 != x.is_nan() as i32 || 0 != y.is_nan() as i32, 7 => return !x.is_nan() && !y.is_nan(), _ => { - dbg_assert!(0 != 0i32); - return 0 != 0i32; + dbg_assert!(0 != 0); + return 0 != 0; }, }; } @@ -399,7 +373,7 @@ pub unsafe fn sse_convert_f32_to_i32(mut x: f32) -> i32 { } else { // TODO: Signal - return 2147483648u32.wrapping_neg() as i32; + return -0x80000000; }; } @@ -411,6 +385,6 @@ pub unsafe fn sse_convert_f64_to_i32(mut x: f64) -> i32 { } else { // TODO: Signal - return 2147483648u32.wrapping_neg() as i32; + return -0x80000000; }; } diff --git a/src/rust/cpu2/string.rs b/src/rust/cpu2/string.rs index 19159950..2f95dd90 100644 --- a/src/rust/cpu2/string.rs +++ b/src/rust/cpu2/string.rs @@ -26,19 +26,19 @@ use cpu2::memory::{ read8, read_aligned16, read_aligned32, write8, write_aligned16, write_aligned32, }; -const MAX_COUNT_PER_CYCLE: i32 = 4096i32; +const MAX_COUNT_PER_CYCLE: i32 = 4096; #[no_mangle] pub unsafe fn string_get_cycle_count(mut size: i32, mut address: i32) -> i32 { - dbg_assert!(0 != size && size <= 4i32 && size >= -4i32); - if size < 0i32 { + dbg_assert!(0 != size && size <= 4 && size >= -4); + if size < 0 { size = -size; - address = 4096i32 - address - size + address = 4096 - address - size } - dbg_assert!(address & size - 1i32 == 0i32); + dbg_assert!(address & size - 1 == 0); // 1 -> 0; 2 -> 1; 4 -> 2 - let mut shift: i32 = size >> 1i32; - return 4096i32 - (address & 4095i32) >> shift; + let mut shift: i32 = size >> 1; + return 4096 - (address & 4095) >> shift; } #[no_mangle] pub unsafe fn string_get_cycle_count2(mut size: i32, mut addr1: i32, mut addr2: i32) -> i32 { @@ -50,14 +50,9 @@ pub unsafe fn string_get_cycle_count2(mut size: i32, mut addr1: i32, mut addr2: pub unsafe fn movsb_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -1i32 - } - else { - 1i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; let mut count: i32 = get_reg_asize(ECX); - if count == 0i32 { + if count == 0 { return; } else { @@ -71,7 +66,7 @@ pub unsafe fn movsb_rep() { phys_dest += size; phys_src += size; count -= 1; - cont = (count != 0i32) as i32; + cont = (count != 0) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -95,12 +90,7 @@ pub unsafe fn movsb_rep() { pub unsafe fn movsb_no_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -1i32 - } - else { - 1i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; return_on_pagefault!(safe_write8(dest, return_on_pagefault!(safe_read8(src)))); add_reg_asize(EDI, size); add_reg_asize(ESI, size); @@ -110,33 +100,27 @@ pub unsafe fn movsw_rep() { let mut diff; let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -2i32 - } - else { - 2i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; let mut count: i32 = get_reg_asize(ECX); - if count == 0i32 { + if count == 0 { return; } else { let mut cont; let mut start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; - if 0 == dest & 1i32 && 0 == src & 1i32 { - let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; - let mut phys_src: i32 = - (return_on_pagefault!(translate_address_read(src)) >> 1i32) as i32; + if 0 == dest & 1 && 0 == src & 1 { + let mut single_size: i32 = if size < 0 { -1 } else { 1 }; + let mut phys_src: i32 = (return_on_pagefault!(translate_address_read(src)) >> 1) as i32; let mut phys_dest: i32 = - (return_on_pagefault!(translate_address_write(dest)) >> 1i32) as i32; + (return_on_pagefault!(translate_address_write(dest)) >> 1) as i32; cycle_counter = string_get_cycle_count2(size, src, dest); loop { write_aligned16(phys_dest as u32, read_aligned16(phys_src as u32) as u32); phys_dest += single_size; phys_src += single_size; count -= 1; - cont = (count != 0i32) as i32; + cont = (count != 0) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -158,7 +142,7 @@ pub unsafe fn movsw_rep() { add_reg_asize(EDI, size); src += size; add_reg_asize(ESI, size); - cont = (decr_ecx_asize() != 0i32) as i32; + cont = (decr_ecx_asize() != 0) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -177,12 +161,7 @@ pub unsafe fn movsw_rep() { pub unsafe fn movsw_no_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -2i32 - } - else { - 2i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; return_on_pagefault!(safe_write16(dest, return_on_pagefault!(safe_read16(src)))); add_reg_asize(EDI, size); add_reg_asize(ESI, size); @@ -192,33 +171,27 @@ pub unsafe fn movsd_rep() { let mut diff; let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -4i32 - } - else { - 4i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; let mut count: i32 = get_reg_asize(ECX); - if count == 0i32 { + if count == 0 { return; } else { let mut cont; let mut start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; - if 0 == dest & 3i32 && 0 == src & 3i32 { - let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; - let mut phys_src: i32 = - (return_on_pagefault!(translate_address_read(src)) >> 2i32) as i32; + if 0 == dest & 3 && 0 == src & 3 { + let mut single_size: i32 = if size < 0 { -1 } else { 1 }; + let mut phys_src: i32 = (return_on_pagefault!(translate_address_read(src)) >> 2) as i32; let mut phys_dest: i32 = - (return_on_pagefault!(translate_address_write(dest)) >> 2i32) as i32; + (return_on_pagefault!(translate_address_write(dest)) >> 2) as i32; cycle_counter = string_get_cycle_count2(size, src, dest); loop { write_aligned32(phys_dest as u32, read_aligned32(phys_src as u32)); phys_dest += single_size; phys_src += single_size; count -= 1; - cont = (count != 0i32) as i32; + cont = (count != 0) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -240,7 +213,7 @@ pub unsafe fn movsd_rep() { add_reg_asize(EDI, size); src += size; add_reg_asize(ESI, size); - cont = (decr_ecx_asize() != 0i32) as i32; + cont = (decr_ecx_asize() != 0) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -259,12 +232,7 @@ pub unsafe fn movsd_rep() { pub unsafe fn movsd_no_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -4i32 - } - else { - 4i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; return_on_pagefault!(safe_write32(dest, return_on_pagefault!(safe_read32s(src)))); add_reg_asize(EDI, size); add_reg_asize(ESI, size); @@ -275,14 +243,9 @@ pub unsafe fn cmpsb_rep(mut prefix_flag: i32) { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut data_src; let mut data_dest; - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -1i32 - } - else { - 1i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; let mut count: i32 = get_reg_asize(ECX); - if count == 0i32 { + if count == 0 { return; } else { @@ -298,7 +261,7 @@ pub unsafe fn cmpsb_rep(mut prefix_flag: i32) { phys_dest += size; phys_src += size; count -= 1; - cont = (count != 0i32 && (data_src == data_dest) as i32 == is_repz) as i32; + cont = (count != 0 && (data_src == data_dest) as i32 == is_repz) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -325,12 +288,7 @@ pub unsafe fn cmpsb_no_rep() { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut data_src; let mut data_dest; - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -1i32 - } - else { - 1i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; data_src = return_on_pagefault!(safe_read8(src)); data_dest = return_on_pagefault!(safe_read8(dest)); add_reg_asize(EDI, size); @@ -344,14 +302,9 @@ pub unsafe fn cmpsw_rep(mut prefix_flag: i32) { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut data_src; let mut data_dest; - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -2i32 - } - else { - 2i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; let mut count: i32 = get_reg_asize(ECX); - if count == 0i32 { + if count == 0 { return; } else { @@ -359,12 +312,11 @@ pub unsafe fn cmpsw_rep(mut prefix_flag: i32) { let mut start_count: i32 = count; let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; - if 0 == dest & 1i32 && 0 == src & 1i32 { - let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; - let mut phys_src: i32 = - (return_on_pagefault!(translate_address_read(src)) >> 1i32) as i32; + if 0 == dest & 1 && 0 == src & 1 { + let mut single_size: i32 = if size < 0 { -1 } else { 1 }; + let mut phys_src: i32 = (return_on_pagefault!(translate_address_read(src)) >> 1) as i32; let mut phys_dest: i32 = - (return_on_pagefault!(translate_address_read(dest)) >> 1i32) as i32; + (return_on_pagefault!(translate_address_read(dest)) >> 1) as i32; cycle_counter = string_get_cycle_count2(size, src, dest); loop { data_dest = read_aligned16(phys_dest as u32); @@ -372,7 +324,7 @@ pub unsafe fn cmpsw_rep(mut prefix_flag: i32) { phys_dest += single_size; phys_src += single_size; count -= 1; - cont = (count != 0i32 && (data_src == data_dest) as i32 == is_repz) as i32; + cont = (count != 0 && (data_src == data_dest) as i32 == is_repz) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -395,8 +347,7 @@ pub unsafe fn cmpsw_rep(mut prefix_flag: i32) { add_reg_asize(EDI, size); src += size; add_reg_asize(ESI, size); - cont = - (decr_ecx_asize() != 0i32 && (data_src == data_dest) as i32 == is_repz) as i32; + cont = (decr_ecx_asize() != 0 && (data_src == data_dest) as i32 == is_repz) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -418,12 +369,7 @@ pub unsafe fn cmpsw_no_rep() { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut data_src; let mut data_dest; - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -2i32 - } - else { - 2i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; data_dest = return_on_pagefault!(safe_read16(dest)); data_src = return_on_pagefault!(safe_read16(src)); add_reg_asize(EDI, size); @@ -437,14 +383,9 @@ pub unsafe fn cmpsd_rep(mut prefix_flag: i32) { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut data_src; let mut data_dest; - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -4i32 - } - else { - 4i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; let mut count: i32 = get_reg_asize(ECX); - if count == 0i32 { + if count == 0 { return; } else { @@ -452,12 +393,11 @@ pub unsafe fn cmpsd_rep(mut prefix_flag: i32) { let mut start_count: i32 = count; let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; - if 0 == dest & 3i32 && 0 == src & 3i32 { - let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; - let mut phys_src: i32 = - (return_on_pagefault!(translate_address_read(src)) >> 2i32) as i32; + if 0 == dest & 3 && 0 == src & 3 { + let mut single_size: i32 = if size < 0 { -1 } else { 1 }; + let mut phys_src: i32 = (return_on_pagefault!(translate_address_read(src)) >> 2) as i32; let mut phys_dest: i32 = - (return_on_pagefault!(translate_address_read(dest)) >> 2i32) as i32; + (return_on_pagefault!(translate_address_read(dest)) >> 2) as i32; cycle_counter = string_get_cycle_count2(size, src, dest); loop { data_dest = read_aligned32(phys_dest as u32); @@ -465,7 +405,7 @@ pub unsafe fn cmpsd_rep(mut prefix_flag: i32) { phys_dest += single_size; phys_src += single_size; count -= 1; - cont = (count != 0i32 && (data_src == data_dest) as i32 == is_repz) as i32; + cont = (count != 0 && (data_src == data_dest) as i32 == is_repz) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -488,8 +428,7 @@ pub unsafe fn cmpsd_rep(mut prefix_flag: i32) { add_reg_asize(EDI, size); src += size; add_reg_asize(ESI, size); - cont = - (decr_ecx_asize() != 0i32 && (data_src == data_dest) as i32 == is_repz) as i32; + cont = (decr_ecx_asize() != 0 && (data_src == data_dest) as i32 == is_repz) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -511,12 +450,7 @@ pub unsafe fn cmpsd_no_rep() { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut data_src; let mut data_dest; - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -4i32 - } - else { - 4i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; data_dest = return_on_pagefault!(safe_read32s(dest)); data_src = return_on_pagefault!(safe_read32s(src)); add_reg_asize(EDI, size); @@ -527,14 +461,9 @@ pub unsafe fn cmpsd_no_rep() { pub unsafe fn stosb_rep() { let mut data: i32 = *reg8.offset(AL as isize) as i32; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -1i32 - } - else { - 1i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; let mut count: i32 = get_reg_asize(ECX); - if count == 0i32 { + if count == 0 { return; } else { @@ -546,7 +475,7 @@ pub unsafe fn stosb_rep() { write8(phys_dest as u32, data); phys_dest += size; count -= 1; - cont = (count != 0i32) as i32; + cont = (count != 0) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -569,12 +498,7 @@ pub unsafe fn stosb_rep() { pub unsafe fn stosb_no_rep() { let mut data: i32 = *reg8.offset(AL as isize) as i32; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -1i32 - } - else { - 1i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; return_on_pagefault!(safe_write8(dest, data)); add_reg_asize(EDI, size); } @@ -583,30 +507,25 @@ pub unsafe fn stosw_rep() { let mut diff; let mut data: i32 = *reg16.offset(AX as isize) as i32; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -2i32 - } - else { - 2i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; let mut count: i32 = get_reg_asize(ECX); - if count == 0i32 { + if count == 0 { return; } else { let mut cont; let mut start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; - if 0 == dest & 1i32 { - let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; + if 0 == dest & 1 { + let mut single_size: i32 = if size < 0 { -1 } else { 1 }; let mut phys_dest: i32 = - (return_on_pagefault!(translate_address_write(dest)) >> 1i32) as i32; + (return_on_pagefault!(translate_address_write(dest)) >> 1) as i32; cycle_counter = string_get_cycle_count(size, dest); loop { write_aligned16(phys_dest as u32, data as u32); phys_dest += single_size; count -= 1; - cont = (count != 0i32) as i32; + cont = (count != 0) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -625,7 +544,7 @@ pub unsafe fn stosw_rep() { return_on_pagefault!(safe_write16(dest, data)); dest += size; add_reg_asize(EDI, size); - cont = (decr_ecx_asize() != 0i32) as i32; + cont = (decr_ecx_asize() != 0) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -644,12 +563,7 @@ pub unsafe fn stosw_rep() { pub unsafe fn stosw_no_rep() { let mut data: i32 = *reg16.offset(AX as isize) as i32; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -2i32 - } - else { - 2i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; return_on_pagefault!(safe_write16(dest, data)); add_reg_asize(EDI, size); } @@ -658,30 +572,25 @@ pub unsafe fn stosd_rep() { let mut diff; let mut data: i32 = *reg32s.offset(EAX as isize); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -4i32 - } - else { - 4i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; let mut count: i32 = get_reg_asize(ECX); - if count == 0i32 { + if count == 0 { return; } else { let mut cont; let mut start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; - if 0 == dest & 3i32 { - let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; + if 0 == dest & 3 { + let mut single_size: i32 = if size < 0 { -1 } else { 1 }; let mut phys_dest: i32 = - (return_on_pagefault!(translate_address_write(dest)) >> 2i32) as i32; + (return_on_pagefault!(translate_address_write(dest)) >> 2) as i32; cycle_counter = string_get_cycle_count(size, dest); loop { write_aligned32(phys_dest as u32, data); phys_dest += single_size; count -= 1; - cont = (count != 0i32) as i32; + cont = (count != 0) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -700,7 +609,7 @@ pub unsafe fn stosd_rep() { return_on_pagefault!(safe_write32(dest, data)); dest += size; add_reg_asize(EDI, size); - cont = (decr_ecx_asize() != 0i32) as i32; + cont = (decr_ecx_asize() != 0) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -719,26 +628,16 @@ pub unsafe fn stosd_rep() { pub unsafe fn stosd_no_rep() { let mut data: i32 = *reg32s.offset(EAX as isize); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -4i32 - } - else { - 4i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; return_on_pagefault!(safe_write32(dest, data)); add_reg_asize(EDI, size); } #[no_mangle] pub unsafe fn lodsb_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -1i32 - } - else { - 1i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; let mut count: i32 = get_reg_asize(ECX); - if count == 0i32 { + if count == 0 { return; } else { @@ -750,7 +649,7 @@ pub unsafe fn lodsb_rep() { *reg8.offset(AL as isize) = read8(phys_src as u32) as u8; phys_src += size; count -= 1; - cont = (count != 0i32) as i32; + cont = (count != 0) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -772,26 +671,16 @@ pub unsafe fn lodsb_rep() { #[no_mangle] pub unsafe fn lodsb_no_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -1i32 - } - else { - 1i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; *reg8.offset(AL as isize) = return_on_pagefault!(safe_read8(src)) as u8; add_reg_asize(ESI, size); } #[no_mangle] pub unsafe fn lodsw_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -2i32 - } - else { - 2i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; let mut count: u32 = get_reg_asize(ECX) as u32; - if count == 0i32 as u32 { + if count == 0 as u32 { return; } else { @@ -801,7 +690,7 @@ pub unsafe fn lodsw_rep() { *reg16.offset(AX as isize) = return_on_pagefault!(safe_read16(src)) as u16; src += size; add_reg_asize(ESI, size); - cont = decr_ecx_asize() != 0i32; + cont = decr_ecx_asize() != 0; if !(0 != cont as i32 && { cycle_counter = cycle_counter.wrapping_sub(1); 0 != cycle_counter @@ -818,26 +707,16 @@ pub unsafe fn lodsw_rep() { #[no_mangle] pub unsafe fn lodsw_no_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -2i32 - } - else { - 2i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; *reg16.offset(AX as isize) = return_on_pagefault!(safe_read16(src)) as u16; add_reg_asize(ESI, size); } #[no_mangle] pub unsafe fn lodsd_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -4i32 - } - else { - 4i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; let mut count: i32 = get_reg_asize(ECX); - if count == 0i32 { + if count == 0 { return; } else { @@ -847,7 +726,7 @@ pub unsafe fn lodsd_rep() { *reg32s.offset(EAX as isize) = return_on_pagefault!(safe_read32s(src)); src += size; add_reg_asize(ESI, size); - cont = (decr_ecx_asize() != 0i32) as i32; + cont = (decr_ecx_asize() != 0) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -864,28 +743,18 @@ pub unsafe fn lodsd_rep() { #[no_mangle] pub unsafe fn lodsd_no_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -4i32 - } - else { - 4i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; *reg32s.offset(EAX as isize) = return_on_pagefault!(safe_read32s(src)); add_reg_asize(ESI, size); } #[no_mangle] pub unsafe fn scasb_rep(mut prefix_flag: i32) { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -1i32 - } - else { - 1i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; let mut data_dest; let mut data_src: i32 = *reg8.offset(AL as isize) as i32; let mut count: i32 = get_reg_asize(ECX); - if count == 0i32 { + if count == 0 { return; } else { @@ -898,7 +767,7 @@ pub unsafe fn scasb_rep(mut prefix_flag: i32) { data_dest = read8(phys_dest as u32); phys_dest += size; count -= 1; - cont = (count != 0i32 && (data_src == data_dest) as i32 == is_repz) as i32; + cont = (count != 0 && (data_src == data_dest) as i32 == is_repz) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -921,12 +790,7 @@ pub unsafe fn scasb_rep(mut prefix_flag: i32) { #[no_mangle] pub unsafe fn scasb_no_rep() { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -1i32 - } - else { - 1i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; let mut data_dest; let mut data_src: i32 = *reg8.offset(AL as isize) as i32; data_dest = return_on_pagefault!(safe_read8(dest)); @@ -937,16 +801,11 @@ pub unsafe fn scasb_no_rep() { pub unsafe fn scasw_rep(mut prefix_flag: i32) { let mut diff; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -2i32 - } - else { - 2i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; let mut data_dest; let mut data_src: i32 = *reg16.offset(AL as isize) as i32; let mut count: i32 = get_reg_asize(ECX); - if count == 0i32 { + if count == 0 { return; } else { @@ -954,16 +813,16 @@ pub unsafe fn scasw_rep(mut prefix_flag: i32) { let mut start_count: i32 = count; let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; - if 0 == dest & 1i32 { - let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; + if 0 == dest & 1 { + let mut single_size: i32 = if size < 0 { -1 } else { 1 }; let mut phys_dest: i32 = - (return_on_pagefault!(translate_address_read(dest)) >> 1i32) as i32; + (return_on_pagefault!(translate_address_read(dest)) >> 1) as i32; cycle_counter = string_get_cycle_count(size, dest); loop { data_dest = read_aligned16(phys_dest as u32); phys_dest += single_size; count -= 1; - cont = (count != 0i32 && (data_src == data_dest) as i32 == is_repz) as i32; + cont = (count != 0 && (data_src == data_dest) as i32 == is_repz) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -982,8 +841,7 @@ pub unsafe fn scasw_rep(mut prefix_flag: i32) { data_dest = return_on_pagefault!(safe_read16(dest)); dest += size; add_reg_asize(EDI, size); - cont = - (decr_ecx_asize() != 0i32 && (data_src == data_dest) as i32 == is_repz) as i32; + cont = (decr_ecx_asize() != 0 && (data_src == data_dest) as i32 == is_repz) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -1002,12 +860,7 @@ pub unsafe fn scasw_rep(mut prefix_flag: i32) { #[no_mangle] pub unsafe fn scasw_no_rep() { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -2i32 - } - else { - 2i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; let mut data_dest; let mut data_src: i32 = *reg16.offset(AL as isize) as i32; data_dest = return_on_pagefault!(safe_read16(dest)); @@ -1018,16 +871,11 @@ pub unsafe fn scasw_no_rep() { pub unsafe fn scasd_rep(mut prefix_flag: i32) { let mut diff; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -4i32 - } - else { - 4i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; let mut data_dest; let mut data_src: i32 = *reg32s.offset(EAX as isize); let mut count: i32 = get_reg_asize(ECX); - if count == 0i32 { + if count == 0 { return; } else { @@ -1035,16 +883,16 @@ pub unsafe fn scasd_rep(mut prefix_flag: i32) { let mut start_count: i32 = count; let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; - if 0 == dest & 3i32 { - let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; + if 0 == dest & 3 { + let mut single_size: i32 = if size < 0 { -1 } else { 1 }; let mut phys_dest: i32 = - (return_on_pagefault!(translate_address_read(dest)) >> 2i32) as i32; + (return_on_pagefault!(translate_address_read(dest)) >> 2) as i32; cycle_counter = string_get_cycle_count(size, dest); loop { data_dest = read_aligned32(phys_dest as u32); phys_dest += single_size; count -= 1; - cont = (count != 0i32 && (data_src == data_dest) as i32 == is_repz) as i32; + cont = (count != 0 && (data_src == data_dest) as i32 == is_repz) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -1063,8 +911,7 @@ pub unsafe fn scasd_rep(mut prefix_flag: i32) { data_dest = return_on_pagefault!(safe_read32s(dest)); dest += size; add_reg_asize(EDI, size); - cont = - (decr_ecx_asize() != 0i32 && (data_src == data_dest) as i32 == is_repz) as i32; + cont = (decr_ecx_asize() != 0 && (data_src == data_dest) as i32 == is_repz) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -1083,12 +930,7 @@ pub unsafe fn scasd_rep(mut prefix_flag: i32) { #[no_mangle] pub unsafe fn scasd_no_rep() { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -4i32 - } - else { - 4i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; let mut data_dest; let mut data_src: i32 = *reg32s.offset(EAX as isize); data_dest = return_on_pagefault!(safe_read32s(dest)); @@ -1098,19 +940,14 @@ pub unsafe fn scasd_no_rep() { #[no_mangle] pub unsafe fn insb_rep() { let mut port: i32 = *reg16.offset(DX as isize) as i32; - if !test_privileges_for_io(port, 1i32) { + if !test_privileges_for_io(port, 1) { return; } else { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -1i32 - } - else { - 1i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; let mut count: i32 = get_reg_asize(ECX); - if count == 0i32 { + if count == 0 { return; } else { @@ -1122,7 +959,7 @@ pub unsafe fn insb_rep() { write8(phys_dest as u32, io_port_read8(port)); phys_dest += size; count -= 1; - cont = (count != 0i32) as i32; + cont = (count != 0) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -1146,18 +983,13 @@ pub unsafe fn insb_rep() { #[no_mangle] pub unsafe fn insb_no_rep() { let mut port: i32 = *reg16.offset(DX as isize) as i32; - if !test_privileges_for_io(port, 1i32) { + if !test_privileges_for_io(port, 1) { return; } else { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -1i32 - } - else { - 1i32 - }; - return_on_pagefault!(writable_or_pagefault(dest, 1i32)); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; + return_on_pagefault!(writable_or_pagefault(dest, 1)); return_on_pagefault!(safe_write8(dest, io_port_read8(port))); add_reg_asize(EDI, size); return; @@ -1167,35 +999,30 @@ pub unsafe fn insb_no_rep() { pub unsafe fn insw_rep() { let mut diff; let mut port: i32 = *reg16.offset(DX as isize) as i32; - if !test_privileges_for_io(port, 2i32) { + if !test_privileges_for_io(port, 2) { return; } else { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -2i32 - } - else { - 2i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; let mut count: i32 = get_reg_asize(ECX); - if count == 0i32 { + if count == 0 { return; } else { let mut cont; let mut start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; - if 0 == dest & 1i32 { - let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; + if 0 == dest & 1 { + let mut single_size: i32 = if size < 0 { -1 } else { 1 }; let mut phys_dest: i32 = - (return_on_pagefault!(translate_address_write(dest)) >> 1i32) as i32; + (return_on_pagefault!(translate_address_write(dest)) >> 1) as i32; cycle_counter = string_get_cycle_count(size, dest); loop { write_aligned16(phys_dest as u32, io_port_read16(port) as u32); phys_dest += single_size; count -= 1; - cont = (count != 0i32) as i32; + cont = (count != 0) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -1212,11 +1039,11 @@ pub unsafe fn insw_rep() { } else { loop { - return_on_pagefault!(writable_or_pagefault(dest, 2i32)); + return_on_pagefault!(writable_or_pagefault(dest, 2)); return_on_pagefault!(safe_write16(dest, io_port_read16(port))); dest += size; add_reg_asize(EDI, size); - cont = (decr_ecx_asize() != 0i32) as i32; + cont = (decr_ecx_asize() != 0) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -1235,18 +1062,13 @@ pub unsafe fn insw_rep() { #[no_mangle] pub unsafe fn insw_no_rep() { let mut port: i32 = *reg16.offset(DX as isize) as i32; - if !test_privileges_for_io(port, 2i32) { + if !test_privileges_for_io(port, 2) { return; } else { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -2i32 - } - else { - 2i32 - }; - return_on_pagefault!(writable_or_pagefault(dest, 2i32)); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; + return_on_pagefault!(writable_or_pagefault(dest, 2)); return_on_pagefault!(safe_write16(dest, io_port_read16(port))); add_reg_asize(EDI, size); return; @@ -1256,35 +1078,30 @@ pub unsafe fn insw_no_rep() { pub unsafe fn insd_rep() { let mut diff; let mut port: i32 = *reg16.offset(DX as isize) as i32; - if !test_privileges_for_io(port, 4i32) { + if !test_privileges_for_io(port, 4) { return; } else { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -4i32 - } - else { - 4i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; let mut count: i32 = get_reg_asize(ECX); - if count == 0i32 { + if count == 0 { return; } else { let mut cont; let mut start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; - if 0 == dest & 3i32 { - let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; + if 0 == dest & 3 { + let mut single_size: i32 = if size < 0 { -1 } else { 1 }; let mut phys_dest: i32 = - (return_on_pagefault!(translate_address_write(dest)) >> 2i32) as i32; + (return_on_pagefault!(translate_address_write(dest)) >> 2) as i32; cycle_counter = string_get_cycle_count(size, dest); loop { write_aligned32(phys_dest as u32, io_port_read32(port)); phys_dest += single_size; count -= 1; - cont = (count != 0i32) as i32; + cont = (count != 0) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -1301,11 +1118,11 @@ pub unsafe fn insd_rep() { } else { loop { - return_on_pagefault!(writable_or_pagefault(dest, 4i32)); + return_on_pagefault!(writable_or_pagefault(dest, 4)); return_on_pagefault!(safe_write32(dest, io_port_read32(port))); dest += size; add_reg_asize(EDI, size); - cont = (decr_ecx_asize() != 0i32) as i32; + cont = (decr_ecx_asize() != 0) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -1324,18 +1141,13 @@ pub unsafe fn insd_rep() { #[no_mangle] pub unsafe fn insd_no_rep() { let mut port: i32 = *reg16.offset(DX as isize) as i32; - if !test_privileges_for_io(port, 4i32) { + if !test_privileges_for_io(port, 4) { return; } else { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -4i32 - } - else { - 4i32 - }; - return_on_pagefault!(writable_or_pagefault(dest, 4i32)); + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; + return_on_pagefault!(writable_or_pagefault(dest, 4)); return_on_pagefault!(safe_write32(dest, io_port_read32(port))); add_reg_asize(EDI, size); return; @@ -1344,19 +1156,14 @@ pub unsafe fn insd_no_rep() { #[no_mangle] pub unsafe fn outsb_rep() { let mut port: i32 = *reg16.offset(DX as isize) as i32; - if !test_privileges_for_io(port, 1i32) { + if !test_privileges_for_io(port, 1) { return; } else { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -1i32 - } - else { - 1i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; let mut count: i32 = get_reg_asize(ECX); - if count == 0i32 { + if count == 0 { return; } else { @@ -1368,7 +1175,7 @@ pub unsafe fn outsb_rep() { io_port_write8(port, read8(phys_src as u32)); phys_src += size; count -= 1; - cont = (count != 0i32) as i32; + cont = (count != 0) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -1392,17 +1199,12 @@ pub unsafe fn outsb_rep() { #[no_mangle] pub unsafe fn outsb_no_rep() { let mut port: i32 = *reg16.offset(DX as isize) as i32; - if !test_privileges_for_io(port, 1i32) { + if !test_privileges_for_io(port, 1) { return; } else { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -1i32 - } - else { - 1i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; io_port_write8(port, return_on_pagefault!(safe_read8(src))); add_reg_asize(ESI, size); return; @@ -1412,35 +1214,30 @@ pub unsafe fn outsb_no_rep() { pub unsafe fn outsw_rep() { let mut diff; let mut port: i32 = *reg16.offset(DX as isize) as i32; - if !test_privileges_for_io(port, 2i32) { + if !test_privileges_for_io(port, 2) { return; } else { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -2i32 - } - else { - 2i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; let mut count: i32 = get_reg_asize(ECX); - if count == 0i32 { + if count == 0 { return; } else { let mut cont; let mut start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; - if 0 == src & 1i32 { - let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; + if 0 == src & 1 { + let mut single_size: i32 = if size < 0 { -1 } else { 1 }; let mut phys_src: i32 = - (return_on_pagefault!(translate_address_read(src)) >> 1i32) as i32; + (return_on_pagefault!(translate_address_read(src)) >> 1) as i32; cycle_counter = string_get_cycle_count(size, src); loop { io_port_write16(port, read_aligned16(phys_src as u32)); phys_src += single_size; count -= 1; - cont = (count != 0i32) as i32; + cont = (count != 0) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -1460,7 +1257,7 @@ pub unsafe fn outsw_rep() { io_port_write16(port, return_on_pagefault!(safe_read16(src))); src += size; add_reg_asize(ESI, size); - cont = (decr_ecx_asize() != 0i32) as i32; + cont = (decr_ecx_asize() != 0) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -1479,17 +1276,12 @@ pub unsafe fn outsw_rep() { #[no_mangle] pub unsafe fn outsw_no_rep() { let mut port: i32 = *reg16.offset(DX as isize) as i32; - if !test_privileges_for_io(port, 2i32) { + if !test_privileges_for_io(port, 2) { return; } else { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -2i32 - } - else { - 2i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; io_port_write16(port, return_on_pagefault!(safe_read16(src))); add_reg_asize(ESI, size); return; @@ -1499,35 +1291,30 @@ pub unsafe fn outsw_no_rep() { pub unsafe fn outsd_rep() { let mut diff; let mut port: i32 = *reg16.offset(DX as isize) as i32; - if !test_privileges_for_io(port, 4i32) { + if !test_privileges_for_io(port, 4) { return; } else { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -4i32 - } - else { - 4i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; let mut count: i32 = get_reg_asize(ECX); - if count == 0i32 { + if count == 0 { return; } else { let mut cont; let mut start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; - if 0 == src & 3i32 { - let mut single_size: i32 = if size < 0i32 { -1i32 } else { 1i32 }; + if 0 == src & 3 { + let mut single_size: i32 = if size < 0 { -1 } else { 1 }; let mut phys_src: i32 = - (return_on_pagefault!(translate_address_read(src)) >> 2i32) as i32; + (return_on_pagefault!(translate_address_read(src)) >> 2) as i32; cycle_counter = string_get_cycle_count(size, src); loop { io_port_write32(port, read_aligned32(phys_src as u32)); phys_src += single_size; count -= 1; - cont = (count != 0i32) as i32; + cont = (count != 0) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -1547,7 +1334,7 @@ pub unsafe fn outsd_rep() { io_port_write32(port, return_on_pagefault!(safe_read32s(src))); src += size; add_reg_asize(ESI, size); - cont = (decr_ecx_asize() != 0i32) as i32; + cont = (decr_ecx_asize() != 0) as i32; if !(0 != cont && { cycle_counter -= 1; 0 != cycle_counter @@ -1566,17 +1353,12 @@ pub unsafe fn outsd_rep() { #[no_mangle] pub unsafe fn outsd_no_rep() { let mut port: i32 = *reg16.offset(DX as isize) as i32; - if !test_privileges_for_io(port, 4i32) { + if !test_privileges_for_io(port, 4) { return; } else { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { - -4i32 - } - else { - 4i32 - }; + let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; io_port_write32(port, return_on_pagefault!(safe_read32s(src))); add_reg_asize(ESI, size); return; From f1b50734c9369984d41f7b3650f34f5ac79fc3cc Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 29 Aug 2018 12:31:54 -0500 Subject: [PATCH 1262/2137] c2rust cleanup: Remove build system --- Makefile | 53 ++--------------------------------------------------- 1 file changed, 2 insertions(+), 51 deletions(-) diff --git a/Makefile b/Makefile index a3013628..653e4ef4 100644 --- a/Makefile +++ b/Makefile @@ -14,13 +14,8 @@ JIT_DEPENDENCIES=$(GEN_DEPENDENCIES) gen/generate_jit.js INTERPRETER_DEPENDENCIES=$(GEN_DEPENDENCIES) gen/generate_interpreter.js ANALYZER_DEPENDENCIES=$(GEN_DEPENDENCIES) gen/generate_analyzer.js -# Enable manually and recompile v86-debug.wasm for coverage-enabled tests -ifeq ($(ENABLE_COV), 1) -CC_COVERAGE_FLAGS=--coverage -fprofile-instr-generate -endif - -all: build/v86_all.js build/libv86.js build/v86.wasm build/v86oxide.wasm -all-debug: build/libv86-debug.js build/v86-debug.wasm build/v86oxide-debug.wasm +all: build/v86_all.js build/libv86.js build/v86oxide.wasm +all-debug: build/libv86-debug.js build/v86oxide-debug.wasm browser: build/v86_all.js # Used for nodejs builds and in order to profile code. @@ -87,19 +82,6 @@ TRANSPILE_ES6_FLAGS=\ --language_in ECMASCRIPT6_STRICT\ --language_out ECMASCRIPT5_STRICT\ -CC_FLAGS=\ - -std=c11 \ - -Isrc/native/ \ - -Wall -Wpedantic -Wextra \ - -Wno-bitwise-op-parentheses -Wno-gnu-binary-literal \ - -fcolor-diagnostics \ - -fwrapv \ - -g4 \ - -s LEGALIZE_JS_FFI=0 \ - -s "BINARYEN_TRAP_MODE='allow'" \ - -s WASM=1 \ - -s SIDE_MODULE=1 - CARGO_FLAGS=\ --target wasm32-unknown-unknown \ -- \ @@ -200,29 +182,6 @@ src/rust/gen/analyzer0f_16.rs: $(ANALYZER_DEPENDENCIES) src/rust/gen/analyzer0f_32.rs: $(ANALYZER_DEPENDENCIES) ./gen/generate_analyzer.js --output-dir build/ --table analyzer0f_32 -build/v86.wasm: src/native/*.c src/native/*.h src/native/profiler/* src/native/*.ll $(INSTRUCTION_TABLES) - mkdir -p build - -ls -lh build/v86.wasm - #emcc src/native/*.c src/native/profiler/*.c src/native/*.ll \ - # $(CC_FLAGS) \ - # -DDEBUG=false \ - # -DNDEBUG \ - # -O3 \ - # --llvm-opts 3 \ - # --llvm-lto 3 \ - # -o build/v86.wasm - ls -lh build/v86.wasm - -build/v86-debug.wasm: src/native/*.c src/native/*.h src/native/profiler/* src/native/*.ll $(INSTRUCTION_TABLES) - mkdir -p build/coverage - -ls -lh build/v86-debug.wasm - #emcc src/native/*.c src/native/profiler/*.c src/native/*.ll \ - # $(CC_FLAGS) \ - # $(CC_COVERAGE_FLAGS) \ - # -Os \ - # -o build/v86-debug.wasm - #ls -lh build/v86-debug.wasm - build/v86oxide.wasm: $(RUST_FILES) Cargo.toml mkdir -p build/ -ls -lh build/v86oxide.wasm @@ -241,8 +200,6 @@ clean: -rm build/libv86.js -rm build/libv86-debug.js -rm build/v86_all.js - -rm build/v86.wasm - -rm build/v86-debug.wasm -rm build/v86oxide.wasm -rm build/v86oxide-debug.wasm -rm $(INSTRUCTION_TABLES) @@ -340,9 +297,3 @@ build/libwabt.js: wget -P build https://github.com/WebAssembly/wabt/archive/1.0.1.zip unzip -j -d build/ build/1.0.1.zip wabt-1.0.1/demo/libwabt.js rm build/1.0.1.zip - -clang-tidy: - clang-tidy \ - src/native/*.c src/native/*.h \ - src/native/profiler/*.c src/native/profiler/*.h \ - -- -I src/native/ -Wall -Wno-bitwise-op-parentheses -Wno-gnu-binary-literal From f182923bbded342cdda229c615f2d37a6d1fef72 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 29 Aug 2018 15:25:32 -0500 Subject: [PATCH 1263/2137] Page table accessed/dirty bits: Only write if necessary --- src/rust/cpu2/cpu.rs | 53 +++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index f6cfc347..6c8b8466 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -316,15 +316,18 @@ pub unsafe fn do_page_translation( if 0 != page_dir_entry & PAGE_TABLE_PSE_MASK && 0 != *cr.offset(4) & CR4_PSE { // size bit is set // set the accessed and dirty bits - write_aligned32( - page_dir_addr as u32, - page_dir_entry | PAGE_TABLE_ACCESSED_MASK | if 0 != for_writing as i32 { - PAGE_TABLE_DIRTY_MASK - } - else { - 0 - }, - ); + + let new_page_dir_entry = page_dir_entry | PAGE_TABLE_ACCESSED_MASK | if for_writing { + PAGE_TABLE_DIRTY_MASK + } + else { + 0 + }; + + if page_dir_entry != new_page_dir_entry { + write_aligned32(page_dir_addr as u32, new_page_dir_entry); + } + high = (page_dir_entry as u32 & 4290772992 | (addr & 4190208) as u32) as i32; global = page_dir_entry & PAGE_TABLE_GLOBAL_MASK == PAGE_TABLE_GLOBAL_MASK } @@ -354,20 +357,24 @@ pub unsafe fn do_page_translation( return Err(()); } } - // set the accessed and dirty bits - write_aligned32( - page_dir_addr as u32, - page_dir_entry | PAGE_TABLE_ACCESSED_MASK, - ); - write_aligned32( - page_table_addr as u32, - page_table_entry | PAGE_TABLE_ACCESSED_MASK | if 0 != for_writing as i32 { - PAGE_TABLE_DIRTY_MASK - } - else { - 0 - }, - ); + + // Set the accessed and dirty bits + // Note: dirty bit is only set on the page table entry + let new_page_dir_entry = page_dir_entry | PAGE_TABLE_ACCESSED_MASK; + if new_page_dir_entry != page_dir_entry { + write_aligned32(page_dir_addr as u32, new_page_dir_entry); + } + let new_page_table_entry = page_table_entry | PAGE_TABLE_ACCESSED_MASK | if for_writing + { + PAGE_TABLE_DIRTY_MASK + } + else { + 0 + }; + if page_table_entry != new_page_table_entry { + write_aligned32(page_table_addr as u32, new_page_table_entry); + } + high = (page_table_entry as u32 & 4294963200) as i32; global = page_table_entry & PAGE_TABLE_GLOBAL_MASK == PAGE_TABLE_GLOBAL_MASK } From d24972e3b5154cc06fbbd7782d3e16197e65450f Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 29 Aug 2018 16:46:48 -0500 Subject: [PATCH 1264/2137] {movs,stos}{b,d}: Call jit_dirty_cache once per page --- src/rust/cpu2/memory.rs | 11 +++ src/rust/cpu2/string.rs | 160 +++++++++++++++++++++++++++++----------- 2 files changed, 128 insertions(+), 43 deletions(-) diff --git a/src/rust/cpu2/memory.rs b/src/rust/cpu2/memory.rs index 846ed9ea..a6bdb3f5 100644 --- a/src/rust/cpu2/memory.rs +++ b/src/rust/cpu2/memory.rs @@ -122,6 +122,7 @@ pub unsafe fn read128(mut addr: u32) -> reg128 { } return value; } + #[no_mangle] pub unsafe fn write8(mut addr: u32, mut value: i32) { if 0 != USE_A20 as i32 && !*a20_enabled { @@ -135,6 +136,11 @@ pub unsafe fn write8(mut addr: u32, mut value: i32) { *mem8.offset(addr as isize) = value as u8 }; } + +pub unsafe fn write8_no_mmap_or_dirty_check(addr: u32, value: i32) { + *mem8.offset(addr as isize) = value as u8 +} + #[no_mangle] pub unsafe fn write16(mut addr: u32, mut value: i32) { if 0 != USE_A20 as i32 && !*a20_enabled { @@ -176,6 +182,11 @@ pub unsafe fn write32(mut addr: u32, mut value: i32) { *(mem8.offset(addr as isize) as *mut i32) = value }; } + +pub unsafe fn write_aligned32_no_mmap_or_dirty_check(addr: u32, value: i32) { + *mem32s.offset(addr as isize) = value +} + #[no_mangle] pub unsafe fn write_aligned32(mut addr: u32, mut value: i32) { dbg_assert!(addr < 1073741824 as u32); diff --git a/src/rust/cpu2/string.rs b/src/rust/cpu2/string.rs index 2f95dd90..fb88beca 100644 --- a/src/rust/cpu2/string.rs +++ b/src/rust/cpu2/string.rs @@ -23,7 +23,8 @@ use cpu2::arith::{cmp16, cmp32, cmp8}; use cpu2::cpu::*; use cpu2::global_pointers::*; use cpu2::memory::{ - read8, read_aligned16, read_aligned32, write8, write_aligned16, write_aligned32, + in_mapped_range, read8, read_aligned16, read_aligned32, write8, write8_no_mmap_or_dirty_check, + write_aligned16, write_aligned32, write_aligned32_no_mmap_or_dirty_check, }; const MAX_COUNT_PER_CYCLE: i32 = 4096; @@ -61,17 +62,35 @@ pub unsafe fn movsb_rep() { let mut cycle_counter: i32 = string_get_cycle_count2(size, src, dest); let mut phys_src: i32 = return_on_pagefault!(translate_address_read(src)) as i32; let mut phys_dest: i32 = return_on_pagefault!(translate_address_write(dest)) as i32; - loop { - write8(phys_dest as u32, read8(phys_src as u32)); - phys_dest += size; - phys_src += size; - count -= 1; - cont = (count != 0) as i32; - if !(0 != cont && { - cycle_counter -= 1; - 0 != cycle_counter - }) { - break; + if !in_mapped_range(phys_dest as u32) { + ::c_api::jit_dirty_cache_single(phys_dest as u32); + loop { + write8_no_mmap_or_dirty_check(phys_dest as u32, read8(phys_src as u32)); + phys_dest += size; + phys_src += size; + count -= 1; + cont = (count != 0) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + } + else { + loop { + write8(phys_dest as u32, read8(phys_src as u32)); + phys_dest += size; + phys_src += size; + count -= 1; + cont = (count != 0) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } } } let mut diff: i32 = size * (start_count - count); @@ -186,17 +205,38 @@ pub unsafe fn movsd_rep() { let mut phys_dest: i32 = (return_on_pagefault!(translate_address_write(dest)) >> 2) as i32; cycle_counter = string_get_cycle_count2(size, src, dest); - loop { - write_aligned32(phys_dest as u32, read_aligned32(phys_src as u32)); - phys_dest += single_size; - phys_src += single_size; - count -= 1; - cont = (count != 0) as i32; - if !(0 != cont && { - cycle_counter -= 1; - 0 != cycle_counter - }) { - break; + if !in_mapped_range((phys_dest << 2) as u32) { + ::c_api::jit_dirty_cache_single((phys_dest << 2) as u32); + loop { + write_aligned32_no_mmap_or_dirty_check( + phys_dest as u32, + read_aligned32(phys_src as u32), + ); + phys_dest += single_size; + phys_src += single_size; + count -= 1; + cont = (count != 0) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + } + else { + loop { + write_aligned32(phys_dest as u32, read_aligned32(phys_src as u32)); + phys_dest += single_size; + phys_src += single_size; + count -= 1; + cont = (count != 0) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } } } diff = size * (start_count - count); @@ -471,16 +511,33 @@ pub unsafe fn stosb_rep() { let mut start_count: i32 = count; let mut cycle_counter: i32 = string_get_cycle_count(size, dest); let mut phys_dest: i32 = return_on_pagefault!(translate_address_write(dest)) as i32; - loop { - write8(phys_dest as u32, data); - phys_dest += size; - count -= 1; - cont = (count != 0) as i32; - if !(0 != cont && { - cycle_counter -= 1; - 0 != cycle_counter - }) { - break; + if !in_mapped_range(phys_dest as u32) { + ::c_api::jit_dirty_cache_single(phys_dest as u32); + loop { + write8_no_mmap_or_dirty_check(phys_dest as u32, data); + phys_dest += size; + count -= 1; + cont = (count != 0) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + } + else { + loop { + write8(phys_dest as u32, data); + phys_dest += size; + count -= 1; + cont = (count != 0) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } } } let mut diff: i32 = size * (start_count - count); @@ -586,16 +643,33 @@ pub unsafe fn stosd_rep() { let mut phys_dest: i32 = (return_on_pagefault!(translate_address_write(dest)) >> 2) as i32; cycle_counter = string_get_cycle_count(size, dest); - loop { - write_aligned32(phys_dest as u32, data); - phys_dest += single_size; - count -= 1; - cont = (count != 0) as i32; - if !(0 != cont && { - cycle_counter -= 1; - 0 != cycle_counter - }) { - break; + if !in_mapped_range(phys_dest as u32) { + ::c_api::jit_dirty_cache_single((phys_dest << 2) as u32); + loop { + write_aligned32_no_mmap_or_dirty_check(phys_dest as u32, data); + phys_dest += single_size; + count -= 1; + cont = (count != 0) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } + } + } + else { + loop { + write_aligned32(phys_dest as u32, data); + phys_dest += single_size; + count -= 1; + cont = (count != 0) as i32; + if !(0 != cont && { + cycle_counter -= 1; + 0 != cycle_counter + }) { + break; + } } } diff = size * (start_count - count); From 1a3c49164744f8fca4502ec2ec6377dc737d0c55 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 29 Aug 2018 16:57:30 -0500 Subject: [PATCH 1265/2137] More tests for rep {movs,stos}{b,d} --- tests/qemu/test-i386.c | 91 ++++++++++++++++++++++++++++-------------- 1 file changed, 60 insertions(+), 31 deletions(-) diff --git a/tests/qemu/test-i386.c b/tests/qemu/test-i386.c index 4a36d2eb..28c8db0a 100644 --- a/tests/qemu/test-i386.c +++ b/tests/qemu/test-i386.c @@ -1675,16 +1675,26 @@ void test_misc(void) #endif } -uint8_t str_buffer[4096]; +void byte_read(uint8_t* buffer, uint16_t offset, size_t num_bytes); -#define TEST_STRING1(OP, size, DF, REP)\ +// 8 pages in every direction +#define STR_BUFFER_SIZE (4096 * 16) +uint8_t __attribute__((aligned (4096))) str_buffer[STR_BUFFER_SIZE]; + +#define TEST_STRING1(OP, size_bytes, size, DF, REP, count, offset1, offset2)\ {\ - long esi, edi, eax, ecx, eflags;\ + long esi, edi, eax, ecx, eflags, i;\ \ - esi = (long)(str_buffer + sizeof(str_buffer) / 2);\ - edi = (long)(str_buffer + sizeof(str_buffer) / 2) + 16;\ + for(i = 0; i < (count + 1) * size_bytes; i++)\ + str_buffer[offset1 + i] = i + 0x56;\ + str_buffer[offset1 - i - 1] = i + 0x97;\ + str_buffer[offset2 + i] = i + 0xa5;\ + str_buffer[offset2 - i - 1] = i + 0x3e;\ +\ + esi = (long)(str_buffer + sizeof(str_buffer)/2 + offset1);\ + edi = (long)(str_buffer + sizeof(str_buffer)/2 + offset2);\ eax = i2l(0x12345678);\ - ecx = 17;\ + ecx = count;\ \ asm volatile ("push $0\n\t"\ "popf\n\t"\ @@ -1698,38 +1708,57 @@ uint8_t str_buffer[4096]; printf("%-10s ESI=" FMTLX " EDI=" FMTLX " EAX=" FMTLX " ECX=" FMTLX " EFL=%04x\n",\ REP #OP size, esi, edi, eax, ecx,\ (int)(eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)));\ + byte_read(str_buffer, offset1, 16); \ + if(count > 16) byte_read(str_buffer, offset1 + count * size_bytes - 16, 16);\ + if(count > 16) byte_read(str_buffer, offset1 - count * size_bytes, 16);\ + byte_read(str_buffer, offset2, 16); \ + if(count > 16) byte_read(str_buffer, offset2 + count * size_bytes - 16, 16);\ + if(count > 16) byte_read(str_buffer, offset2 - count * size_bytes, 16);\ } -#define TEST_STRING(OP, REP)\ - TEST_STRING1(OP, "b", "", REP);\ - TEST_STRING1(OP, "w", "", REP);\ - TEST_STRING1(OP, "l", "", REP);\ - X86_64_ONLY(TEST_STRING1(OP, "q", "", REP));\ - TEST_STRING1(OP, "b", "std", REP);\ - TEST_STRING1(OP, "w", "std", REP);\ - TEST_STRING1(OP, "l", "std", REP);\ - X86_64_ONLY(TEST_STRING1(OP, "q", "std", REP)) +#define TEST_STRING(OP, REP, count, offset1, offset2)\ + TEST_STRING1(OP, 1, "b", "", REP, count, offset1, offset2);\ + TEST_STRING1(OP, 2, "w", "", REP, count, offset1, offset2);\ + TEST_STRING1(OP, 4, "l", "", REP, count, offset1, offset2);\ + TEST_STRING1(OP, 1, "b", "std", REP, count, offset1, offset2);\ + TEST_STRING1(OP, 2, "w", "std", REP, count, offset1, offset2);\ + TEST_STRING1(OP, 4, "l", "std", REP, count, offset1, offset2); void test_string(void) { - int i; - for(i = 0;i < sizeof(str_buffer); i++) - str_buffer[i] = i + 0x56; - TEST_STRING(stos, ""); - TEST_STRING(stos, "rep "); - TEST_STRING(lods, ""); /* to verify stos */ - TEST_STRING(lods, "rep "); - TEST_STRING(movs, ""); - TEST_STRING(movs, "rep "); - TEST_STRING(lods, ""); /* to verify stos */ + TEST_STRING(stos, "", 17, 4096, 4096 + 64); + TEST_STRING(stos, "rep ", 17, 4096, 4096 + 64); + + TEST_STRING(lods, "", 17, 4096, 4096 + 64); + TEST_STRING(lods, "rep ", 17, 4096, 4096 + 64); + + TEST_STRING(movs, "", 17, 4096, 4096 + 64); + TEST_STRING(movs, "rep ", 17, 4096, 4096 + 64); /* XXX: better tests */ - TEST_STRING(scas, ""); - TEST_STRING(scas, "repz "); - TEST_STRING(scas, "repnz "); - TEST_STRING(cmps, ""); - TEST_STRING(cmps, "repz "); - TEST_STRING(cmps, "repnz "); + TEST_STRING(scas, "", 17, 4096, 4096 + 64); + TEST_STRING(scas, "repz ", 17, 4096, 4096 + 64); + TEST_STRING(scas, "repnz ", 17, 4096, 4096 + 64); + + TEST_STRING(cmps, "", 17, 4096, 4096 + 64); + TEST_STRING(cmps, "repz ", 17, 4096, 4096 + 64); + TEST_STRING(cmps, "repnz ", 17, 4096, 4096 + 64); + + int counts[] = { 0, 1, 2, 3, 4095, 4096, 4097, 2047, 2048, 2049, 1023, 1024, 1025 }; + int offsets[] = { 0, 1, 2, 3, 4095, 4096, 4097, 2047, 2048, 2049, 1023, 1024, 1025 }; + + for(int count = 0; count < sizeof(counts) / sizeof(int); count++) + { + for(int offset1 = 0; offset1 < sizeof(offsets) / sizeof(int); offset1++) + { + TEST_STRING(stos, "rep ", counts[count], offsets[offset1], offsets[offset1]); + + for(int offset2 = 0; offset2 < sizeof(offsets) / sizeof(int); offset2++) + { + TEST_STRING(movs, "rep ", counts[count], offsets[offset1], offsets[offset2]); + } + } + } } #ifdef TEST_VM86 From 419ddf765a1bbe842a4d549d28093143dc9afbe1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 29 Aug 2018 19:12:18 -0500 Subject: [PATCH 1266/2137] Remove some functions when profiler is disabled --- src/rust/cpu2/cpu.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 6c8b8466..7d5c979e 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1611,6 +1611,9 @@ pub unsafe fn update_eflags(mut new_flags: i32) { #[no_mangle] pub unsafe fn get_valid_tlb_entries_count() -> i32 { + if !cfg!(feature = "profiler") { + return 0; + } let mut result: i32 = 0; let mut i: i32 = 0; while i < valid_tlb_entries_count { @@ -1626,6 +1629,9 @@ pub unsafe fn get_valid_tlb_entries_count() -> i32 { #[no_mangle] pub unsafe fn get_valid_global_tlb_entries_count() -> i32 { + if !cfg!(feature = "profiler") { + return 0; + } let mut result: i32 = 0; let mut i: i32 = 0; while i < valid_tlb_entries_count { From 26e6452c2c37e3ccb34ab3dc8d2d97ec5da96489 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 29 Aug 2018 19:12:35 -0500 Subject: [PATCH 1267/2137] Fix mxcsr warning --- src/rust/cpu2/cpu.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 7d5c979e..a0da0f0a 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1401,9 +1401,9 @@ pub unsafe fn set_mxcsr(new_mxcsr: i32) { } let exception_mask = new_mxcsr >> 7 & 0b111111; - if exception_mask != 0x111111 { + if exception_mask != 0b111111 { dbg_log!( - "Warning: Unimplemented MXCSR exception mask: {:b}", + "Warning: Unimplemented MXCSR exception mask: 0b{:b}", exception_mask ) } From 456c4cbe65b31f469eb3a5e573ab99f29d18e500 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 29 Aug 2018 20:28:57 -0500 Subject: [PATCH 1268/2137] mxcsr: Print warning only when bit is flipped & use constants --- src/rust/cpu2/cpu.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index a0da0f0a..c5a4c72e 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -192,7 +192,12 @@ pub const LOG_CPU: i32 = 2; pub const A20_MASK: i32 = !(1 << 20); pub const A20_MASK16: i32 = !(1 << 20 - 1); pub const A20_MASK32: i32 = !(1 << 20 - 2); + pub const MXCSR_MASK: i32 = 0xffff; +pub const MXCSR_FZ: i32 = 1 << 15; +pub const MXCSR_DAZ: i32 = 1 << 6; +pub const MXCSR_RC_SHIFT: i32 = 13; + pub const VALID_TLB_ENTRY_MAX: i32 = 10000; pub const TLB_VALID: i32 = 1 << 0; pub const TLB_READONLY: i32 = 1 << 1; @@ -1385,15 +1390,15 @@ pub unsafe fn task_switch_test() -> bool { pub unsafe fn set_mxcsr(new_mxcsr: i32) { dbg_assert!(new_mxcsr & !MXCSR_MASK == 0); // checked by caller - if new_mxcsr & 1 << 6 != 0 { + if *mxcsr & MXCSR_DAZ == 0 && new_mxcsr & MXCSR_DAZ != 0 { dbg_log!("Warning: Unimplemented MXCSR bit: Denormals Are Zero") } - if new_mxcsr & 1 << 15 != 0 { + if *mxcsr & MXCSR_FZ == 0 && new_mxcsr & MXCSR_FZ != 0 { dbg_log!("Warning: Unimplemented MXCSR bit: Flush To Zero") } - let rounding_mode = new_mxcsr >> 13 & 3; - if rounding_mode != 0 { + let rounding_mode = new_mxcsr >> MXCSR_RC_SHIFT & 3; + if *mxcsr >> MXCSR_RC_SHIFT & 3 == 0 && rounding_mode != 0 { dbg_log!( "Warning: Unimplemented MXCSR rounding mode: {}", rounding_mode From 841b528a043bfb26a96f0b1b65c69dc5af81231a Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 31 Aug 2018 14:24:26 -0500 Subject: [PATCH 1269/2137] Remove jit_dirty_cache_single in favour of jit_dirty_page --- src/rust/c_api.rs | 2 +- src/rust/cpu2/memory.rs | 3 ++- src/rust/cpu2/string.rs | 9 +++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/rust/c_api.rs b/src/rust/c_api.rs index 3fa815f1..379bfaef 100644 --- a/src/rust/c_api.rs +++ b/src/rust/c_api.rs @@ -83,7 +83,7 @@ pub fn jit_dirty_cache_small(start_addr: u32, end_addr: u32) { ::jit::jit_dirty_cache_small(get_module(), start_addr, end_addr); } -pub fn jit_dirty_cache_single(addr: u32) { ::jit::jit_dirty_cache_single(get_module(), addr); } +pub fn jit_dirty_page(page: Page) { ::jit::jit_dirty_page(get_module(), page); } pub fn jit_page_has_code(page: u32) -> bool { ::jit::jit_page_has_code(get_module(), Page::page_of(page << 12)) diff --git a/src/rust/cpu2/memory.rs b/src/rust/cpu2/memory.rs index a6bdb3f5..f2888274 100644 --- a/src/rust/cpu2/memory.rs +++ b/src/rust/cpu2/memory.rs @@ -20,6 +20,7 @@ extern "C" { use cpu2::cpu::*; use cpu2::global_pointers::*; +use page::Page; const USE_A20: bool = false; @@ -132,7 +133,7 @@ pub unsafe fn write8(mut addr: u32, mut value: i32) { mmap_write8(addr, value); } else { - ::c_api::jit_dirty_cache_single(addr); + ::c_api::jit_dirty_page(Page::page_of(addr)); *mem8.offset(addr as isize) = value as u8 }; } diff --git a/src/rust/cpu2/string.rs b/src/rust/cpu2/string.rs index fb88beca..8d0b4e41 100644 --- a/src/rust/cpu2/string.rs +++ b/src/rust/cpu2/string.rs @@ -26,6 +26,7 @@ use cpu2::memory::{ in_mapped_range, read8, read_aligned16, read_aligned32, write8, write8_no_mmap_or_dirty_check, write_aligned16, write_aligned32, write_aligned32_no_mmap_or_dirty_check, }; +use page::Page; const MAX_COUNT_PER_CYCLE: i32 = 4096; @@ -63,7 +64,7 @@ pub unsafe fn movsb_rep() { let mut phys_src: i32 = return_on_pagefault!(translate_address_read(src)) as i32; let mut phys_dest: i32 = return_on_pagefault!(translate_address_write(dest)) as i32; if !in_mapped_range(phys_dest as u32) { - ::c_api::jit_dirty_cache_single(phys_dest as u32); + ::c_api::jit_dirty_page(Page::page_of(phys_dest as u32)); loop { write8_no_mmap_or_dirty_check(phys_dest as u32, read8(phys_src as u32)); phys_dest += size; @@ -206,7 +207,7 @@ pub unsafe fn movsd_rep() { (return_on_pagefault!(translate_address_write(dest)) >> 2) as i32; cycle_counter = string_get_cycle_count2(size, src, dest); if !in_mapped_range((phys_dest << 2) as u32) { - ::c_api::jit_dirty_cache_single((phys_dest << 2) as u32); + ::c_api::jit_dirty_page(Page::page_of((phys_dest << 2) as u32)); loop { write_aligned32_no_mmap_or_dirty_check( phys_dest as u32, @@ -512,7 +513,7 @@ pub unsafe fn stosb_rep() { let mut cycle_counter: i32 = string_get_cycle_count(size, dest); let mut phys_dest: i32 = return_on_pagefault!(translate_address_write(dest)) as i32; if !in_mapped_range(phys_dest as u32) { - ::c_api::jit_dirty_cache_single(phys_dest as u32); + ::c_api::jit_dirty_page(Page::page_of(phys_dest as u32)); loop { write8_no_mmap_or_dirty_check(phys_dest as u32, data); phys_dest += size; @@ -644,7 +645,7 @@ pub unsafe fn stosd_rep() { (return_on_pagefault!(translate_address_write(dest)) >> 2) as i32; cycle_counter = string_get_cycle_count(size, dest); if !in_mapped_range(phys_dest as u32) { - ::c_api::jit_dirty_cache_single((phys_dest << 2) as u32); + ::c_api::jit_dirty_page(Page::page_of((phys_dest << 2) as u32)); loop { write_aligned32_no_mmap_or_dirty_check(phys_dest as u32, data); phys_dest += single_size; From fa958d95c328947b1a7755f6cecfd53e74708e8e Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 31 Aug 2018 14:40:19 -0500 Subject: [PATCH 1270/2137] Fix warnings: Remove unused stuff --- src/rust/codegen.rs | 7 ------- src/rust/cpu2/cpu.rs | 1 + src/rust/cpu2/fpu.rs | 9 --------- src/rust/jit.rs | 4 ---- src/rust/lib.rs | 1 - src/rust/regs.rs | 7 ------- 6 files changed, 1 insertion(+), 28 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 7f516692..a9d2eca9 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -36,13 +36,6 @@ pub fn gen_increment_instruction_pointer(builder: &mut WasmBuilder, n: u32) { cs.store_aligned_i32(0); // store it back in } -pub fn gen_set_previous_eip(builder: &mut WasmBuilder) { - let cs = &mut builder.code_section; - cs.const_i32(global_pointers::PREVIOUS_IP as i32); // store address of previous ip - cs.load_aligned_i32(global_pointers::INSTRUCTION_POINTER); // load ip - cs.store_aligned_i32(0); // store it as previous ip -} - pub fn gen_relative_jump(builder: &mut WasmBuilder, n: i32) { // add n to instruction_pointer (without setting the offset as above) let instruction_body = &mut builder.instruction_body; diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index c5a4c72e..68144f5f 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -849,6 +849,7 @@ pub unsafe fn pack_current_state_flags() -> CachedStateFlags { | (has_flat_segmentation() as i32) << 3) as CachedStateFlags; } +#[no_mangle] pub unsafe fn has_flat_segmentation() -> bool { // ss can't be null return *segment_offsets.offset(SS as isize) == 0 diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 8e8d75a8..6c337c66 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -37,19 +37,10 @@ pub const FPU_C1: i32 = 512; const FPU_C2: i32 = 1024; const FPU_C3: i32 = 16384; const FPU_RESULT_FLAGS: i32 = FPU_C0 | FPU_C1 | FPU_C2 | FPU_C3; -const FPU_STACK_TOP: i32 = 14336; const INDEFINITE_NAN: f64 = ::std::f64::NAN; const FPU_EX_I: i32 = 1 << 0; const FPU_EX_SF: i32 = 1 << 6; const TWO_POW_63: f64 = 9223372036854775808u64 as f64; -const FPU_PC: i32 = 3 << 8; -const FPU_RC: i32 = 3 << 10; -const FPU_IF: i32 = 1 << 12; -const FPU_EX_P: i32 = 1 << 5; -const FPU_EX_U: i32 = 1 << 4; -const FPU_EX_O: i32 = 1 << 3; -const FPU_EX_Z: i32 = 1 << 2; -const FPU_EX_D: i32 = 1 << 1; #[no_mangle] pub unsafe fn fpu_get_st0() -> f64 { diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 78d30f62..369e8ef3 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -1338,10 +1338,6 @@ pub fn jit_dirty_cache_small(ctx: &mut JitState, start_addr: u32, end_addr: u32) } } -pub fn jit_dirty_cache_single(ctx: &mut JitState, addr: u32) { - jit_dirty_page(ctx, Page::page_of(addr)); -} - pub fn jit_empty_cache(ctx: &mut JitState) { jit_cache_array::clear(); diff --git a/src/rust/lib.rs b/src/rust/lib.rs index b4334a7f..5612ffab 100644 --- a/src/rust/lib.rs +++ b/src/rust/lib.rs @@ -2,7 +2,6 @@ #![feature(extern_types)] #[cfg(test)] -#[macro_use] extern crate quickcheck; #[macro_use] diff --git a/src/rust/regs.rs b/src/rust/regs.rs index 007953dc..c6f7781c 100644 --- a/src/rust/regs.rs +++ b/src/rust/regs.rs @@ -23,14 +23,7 @@ pub const BP: u32 = 5; pub const SI: u32 = 6; pub const DI: u32 = 7; -pub const AL: u32 = 0; pub const CL: u32 = 1; -pub const DL: u32 = 2; -pub const BL: u32 = 3; -pub const AH: u32 = 4; -pub const CH: u32 = 5; -pub const DH: u32 = 6; -pub const BH: u32 = 7; pub const CR0_EM: u32 = 1 << 2; pub const CR0_TS: u32 = 1 << 3; From 27a374e4fdac25eb72cdf0cf4203c01e599159c8 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 31 Aug 2018 14:40:50 -0500 Subject: [PATCH 1271/2137] Make warnings fatal in Rust test --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 653e4ef4..607d61cd 100644 --- a/Makefile +++ b/Makefile @@ -269,7 +269,7 @@ devices-test: all-debug ./tests/devices/virtio_9p.js rust-test: $(RUST_FILES) - env RUST_BACKTRACE=full RUST_TEST_THREADS=1 cargo +nightly test -- --nocapture + env RUST_BACKTRACE=full RUST_TEST_THREADS=1 RUSTFLAGS="-D warnings" cargo +nightly test -- --nocapture ./tests/rust/verify-wasmgen-dummy-output.js api-tests: all-debug From 46f9bc9d00b983e32647927e10a9efbb36677f65 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 31 Aug 2018 15:06:53 -0500 Subject: [PATCH 1272/2137] Remove non-faulting property of instructions (all instructions are non-faulting) --- gen/generate_jit.js | 21 +-- gen/x86_table.js | 344 +++++++++++++++++++++----------------------- src/rust/jit.rs | 1 - 3 files changed, 167 insertions(+), 199 deletions(-) diff --git a/gen/generate_jit.js b/gen/generate_jit.js index b40b28ce..a8862953 100755 --- a/gen/generate_jit.js +++ b/gen/generate_jit.js @@ -230,8 +230,6 @@ function gen_instruction_body_after_fixed_g(encoding, size) ); } - const APPEND_NONFAULTING_FLAG = "*instr_flags |= ::jit::JIT_INSTR_NONFAULTING_FLAG;"; - const imm_read = gen_read_imm_call(encoding, size); const imm_read_bindings = []; if(imm_read) @@ -243,8 +241,8 @@ function gen_instruction_body_after_fixed_g(encoding, size) if(encoding.e) { - const reg_postfix = encoding.nonfaulting ? [APPEND_NONFAULTING_FLAG] : []; - const mem_postfix = encoding.memory_nonfaulting ? [APPEND_NONFAULTING_FLAG] : []; + const reg_postfix = []; + const mem_postfix = []; if(encoding.mem_ud) { @@ -362,16 +360,6 @@ function gen_instruction_body_after_fixed_g(encoding, size) { // custom, but not modrm - if(encoding.prefix) - { - console.assert(!encoding.nonfaulting, "Prefix instructions cannot be marked as nonfaulting."); - } - - if(encoding.nonfaulting) - { - instruction_postfix.push(APPEND_NONFAULTING_FLAG); - } - const args = ["ctx"]; if(imm_read) @@ -395,11 +383,6 @@ function gen_instruction_body_after_fixed_g(encoding, size) { // instruction without modrm byte or prefix - if(encoding.nonfaulting) - { - instruction_postfix.push(APPEND_NONFAULTING_FLAG); - } - const args = ["ctx", `"${instruction_name}"`]; if(imm_read) diff --git a/gen/x86_table.js b/gen/x86_table.js index e04f6bf6..867d52d5 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -16,45 +16,45 @@ const sf = 1 << 7; // os: the instruction behaves differently depending on the operand size const encodings = [ - { opcode: 0x00, nonfaulting: 1, e: 1, }, - { opcode: 0x01, nonfaulting: 1, custom: 1, os: 1, e: 1, }, - { opcode: 0x02, nonfaulting: 1, custom: 1, e: 1, }, - { opcode: 0x03, nonfaulting: 1, custom: 1, os: 1, e: 1, }, + { opcode: 0x00, e: 1, }, + { opcode: 0x01, custom: 1, os: 1, e: 1, }, + { opcode: 0x02, custom: 1, e: 1, }, + { opcode: 0x03, custom: 1, os: 1, e: 1, }, - { opcode: 0x08, nonfaulting: 1, e: 1, }, - { opcode: 0x09, nonfaulting: 1, custom: 1, os: 1, e: 1, }, - { opcode: 0x0A, nonfaulting: 1, custom: 1, e: 1, }, - { opcode: 0x0B, nonfaulting: 1, custom: 1, os: 1, e: 1, }, + { opcode: 0x08, e: 1, }, + { opcode: 0x09, custom: 1, os: 1, e: 1, }, + { opcode: 0x0A, custom: 1, e: 1, }, + { opcode: 0x0B, custom: 1, os: 1, e: 1, }, - { opcode: 0x10, nonfaulting: 1, e: 1, }, - { opcode: 0x11, nonfaulting: 1, custom: 1, os: 1, e: 1, }, - { opcode: 0x12, nonfaulting: 1, custom: 1, e: 1, }, - { opcode: 0x13, nonfaulting: 1, custom: 1, os: 1, e: 1, }, + { opcode: 0x10, e: 1, }, + { opcode: 0x11, custom: 1, os: 1, e: 1, }, + { opcode: 0x12, custom: 1, e: 1, }, + { opcode: 0x13, custom: 1, os: 1, e: 1, }, - { opcode: 0x18, nonfaulting: 1, e: 1, }, - { opcode: 0x19, nonfaulting: 1, custom: 1, os: 1, e: 1, }, - { opcode: 0x1A, nonfaulting: 1, custom: 1, e: 1, }, - { opcode: 0x1B, nonfaulting: 1, custom: 1, os: 1, e: 1, }, + { opcode: 0x18, e: 1, }, + { opcode: 0x19, custom: 1, os: 1, e: 1, }, + { opcode: 0x1A, custom: 1, e: 1, }, + { opcode: 0x1B, custom: 1, os: 1, e: 1, }, - { opcode: 0x20, nonfaulting: 1, e: 1, }, - { opcode: 0x21, nonfaulting: 1, custom: 1, os: 1, e: 1, }, - { opcode: 0x22, nonfaulting: 1, custom: 1, e: 1, }, - { opcode: 0x23, nonfaulting: 1, custom: 1, os: 1, e: 1, }, + { opcode: 0x20, e: 1, }, + { opcode: 0x21, custom: 1, os: 1, e: 1, }, + { opcode: 0x22, custom: 1, e: 1, }, + { opcode: 0x23, custom: 1, os: 1, e: 1, }, - { opcode: 0x28, nonfaulting: 1, e: 1, }, - { opcode: 0x29, nonfaulting: 1, custom: 1, os: 1, e: 1, }, - { opcode: 0x2A, nonfaulting: 1, custom: 1, e: 1, }, - { opcode: 0x2B, nonfaulting: 1, custom: 1, os: 1, e: 1, }, + { opcode: 0x28, e: 1, }, + { opcode: 0x29, custom: 1, os: 1, e: 1, }, + { opcode: 0x2A, custom: 1, e: 1, }, + { opcode: 0x2B, custom: 1, os: 1, e: 1, }, - { opcode: 0x30, nonfaulting: 1, e: 1, }, - { opcode: 0x31, nonfaulting: 1, custom: 1, os: 1, e: 1, }, - { opcode: 0x32, nonfaulting: 1, custom: 1, e: 1, }, - { opcode: 0x33, nonfaulting: 1, custom: 1, os: 1, e: 1, }, + { opcode: 0x30, e: 1, }, + { opcode: 0x31, custom: 1, os: 1, e: 1, }, + { opcode: 0x32, custom: 1, e: 1, }, + { opcode: 0x33, custom: 1, os: 1, e: 1, }, - { opcode: 0x38, nonfaulting: 1, custom: 1, e: 1, }, - { opcode: 0x39, nonfaulting: 1, custom: 1, os: 1, e: 1, }, - { opcode: 0x3A, nonfaulting: 1, custom: 1, e: 1, }, - { opcode: 0x3B, nonfaulting: 1, custom: 1, os: 1, e: 1, }, + { opcode: 0x38, custom: 1, e: 1, }, + { opcode: 0x39, custom: 1, os: 1, e: 1, }, + { opcode: 0x3A, custom: 1, e: 1, }, + { opcode: 0x3B, custom: 1, os: 1, e: 1, }, { opcode: 0x06, os: 1, skip: 1, }, { opcode: 0x07, os: 1, skip: 1, block_boundary: 1, }, // pop es: block_boundary since it uses non-raising cpu exceptions @@ -65,31 +65,31 @@ const encodings = [ { opcode: 0x1E, os: 1, skip: 1, }, { opcode: 0x1F, block_boundary: 1, os: 1, skip: 1, }, // pop ds { opcode: 0x26, prefix: 1, }, - { opcode: 0x27, nonfaulting: 1, mask_flags: of, }, + { opcode: 0x27, mask_flags: of, }, { opcode: 0x2E, prefix: 1, }, - { opcode: 0x2F, nonfaulting: 1, mask_flags: of, }, + { opcode: 0x2F, mask_flags: of, }, { opcode: 0x36, prefix: 1, }, - { opcode: 0x37, nonfaulting: 1, mask_flags: of | sf | pf | zf, }, + { opcode: 0x37, mask_flags: of | sf | pf | zf, }, { opcode: 0x3E, prefix: 1, }, - { opcode: 0x3F, nonfaulting: 1, mask_flags: of | sf | pf | zf, }, + { opcode: 0x3F, mask_flags: of | sf | pf | zf, }, - { opcode: 0x40, nonfaulting: 1, os: 1, }, - { opcode: 0x41, nonfaulting: 1, os: 1, }, - { opcode: 0x42, nonfaulting: 1, os: 1, }, - { opcode: 0x43, nonfaulting: 1, os: 1, }, - { opcode: 0x44, nonfaulting: 1, os: 1, }, - { opcode: 0x45, nonfaulting: 1, os: 1, }, - { opcode: 0x46, nonfaulting: 1, os: 1, }, - { opcode: 0x47, nonfaulting: 1, os: 1, }, + { 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, nonfaulting: 1, os: 1, }, - { opcode: 0x49, nonfaulting: 1, os: 1, }, - { opcode: 0x4A, nonfaulting: 1, os: 1, }, - { opcode: 0x4B, nonfaulting: 1, os: 1, }, - { opcode: 0x4C, nonfaulting: 1, os: 1, }, - { opcode: 0x4D, nonfaulting: 1, os: 1, }, - { opcode: 0x4E, nonfaulting: 1, os: 1, }, - { opcode: 0x4F, nonfaulting: 1, 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, custom: 1, os: 1 }, { opcode: 0x51, custom: 1, os: 1 }, @@ -119,9 +119,9 @@ const encodings = [ { opcode: 0x67, prefix: 1, }, { opcode: 0x68, custom: 1, os: 1, imm1632: 1 }, - { opcode: 0x69, nonfaulting: 1, os: 1, e: 1, imm1632: 1, mask_flags: af, }, // zf? + { opcode: 0x69, os: 1, e: 1, imm1632: 1, mask_flags: af, }, // zf? { opcode: 0x6A, custom: 1, os: 1, imm8s: 1 }, - { opcode: 0x6B, nonfaulting: 1, os: 1, e: 1, imm8s: 1, mask_flags: af, }, // zf? + { opcode: 0x6B, os: 1, e: 1, imm8s: 1, mask_flags: af, }, // zf? { opcode: 0x6C, block_boundary: 1, is_string: 1, skip: 1, }, // ins { opcode: 0xF26C, block_boundary: 1, is_string: 1, skip: 1, }, @@ -137,31 +137,31 @@ const encodings = [ { opcode: 0xF26F, block_boundary: 1, is_string: 1, os: 1, skip: 1, }, { opcode: 0xF36F, block_boundary: 1, is_string: 1, os: 1, skip: 1, }, - { opcode: 0x84, nonfaulting: 1, custom: 1, e: 1, }, - { opcode: 0x85, nonfaulting: 1, custom: 1, e: 1, os: 1, }, - { opcode: 0x86, nonfaulting: 1, e: 1, }, - { opcode: 0x87, nonfaulting: 1, os: 1, e: 1, }, - { opcode: 0x88, custom: 1, nonfaulting: 1, e: 1, }, - { opcode: 0x89, custom: 1, nonfaulting: 1, os: 1, e: 1, }, - { opcode: 0x8A, custom: 1, nonfaulting: 1, e: 1, }, - { opcode: 0x8B, custom: 1, nonfaulting: 1, os: 1, e: 1, }, + { opcode: 0x84, custom: 1, e: 1, }, + { opcode: 0x85, custom: 1, e: 1, os: 1, }, + { opcode: 0x86, e: 1, }, + { opcode: 0x87, os: 1, e: 1, }, + { opcode: 0x88, custom: 1, e: 1, }, + { opcode: 0x89, custom: 1, os: 1, e: 1, }, + { opcode: 0x8A, custom: 1, e: 1, }, + { opcode: 0x8B, custom: 1, os: 1, e: 1, }, { opcode: 0x8C, block_boundary: 1, os: 1, e: 1, skip: 1, }, // mov reg, sreg: block_boundary as it can trigger #ud - { opcode: 0x8D, reg_ud: 1, memory_nonfaulting: 1, os: 1, e: 1, custom_modrm_resolve: 1, custom: 1, }, // lea + { opcode: 0x8D, reg_ud: 1, os: 1, e: 1, custom_modrm_resolve: 1, custom: 1, }, // lea { opcode: 0x8E, block_boundary: 1, e: 1, skip: 1, }, // mov sreg { opcode: 0x8F, os: 1, e: 1, fixed_g: 0, custom_modrm_resolve: 1, custom: 1, block_boundary: 1, }, // pop r/m - { opcode: 0x90, custom: 1, nonfaulting: 1, }, - { opcode: 0x91, nonfaulting: 1, os: 1, }, - { opcode: 0x92, nonfaulting: 1, os: 1, }, - { opcode: 0x93, nonfaulting: 1, os: 1, }, - { opcode: 0x94, nonfaulting: 1, os: 1, }, - { opcode: 0x95, nonfaulting: 1, os: 1, }, - { opcode: 0x96, nonfaulting: 1, os: 1, }, - { opcode: 0x97, nonfaulting: 1, os: 1, }, + { opcode: 0x90, custom: 1, }, + { 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, nonfaulting: 1, os: 1, }, - { opcode: 0x99, nonfaulting: 1, os: 1, }, + { opcode: 0x98, os: 1, }, + { opcode: 0x99, os: 1, }, { opcode: 0x9A, os: 1, imm1632: 1, extra_imm16: 1, skip: 1, block_boundary: 1, }, // callf { opcode: 0x9B, skip: 1, }, // fwait: block_boundary since it uses non-raising cpu exceptions // pushf: block_boundary since it uses non-raising cpu exceptions @@ -192,8 +192,8 @@ const encodings = [ { opcode: 0xF2A7, block_boundary: 1, is_string: 1, os: 1, }, { opcode: 0xF3A7, block_boundary: 1, is_string: 1, os: 1, }, - { opcode: 0xA8, nonfaulting: 1, imm8: 1, }, - { opcode: 0xA9, nonfaulting: 1, os: 1, imm1632: 1, }, + { opcode: 0xA8, imm8: 1, }, + { opcode: 0xA9, os: 1, imm1632: 1, }, { opcode: 0xAA, block_boundary: 1, is_string: 1, }, { opcode: 0xF2AA, block_boundary: 1, is_string: 1, }, @@ -237,8 +237,8 @@ const encodings = [ { opcode: 0xCF, block_boundary: 1, no_next_instruction: 1, os: 1, skip: 1, }, // iret { opcode: 0xD4, imm8: 1, block_boundary: 1, }, // aam, may trigger #de - { opcode: 0xD5, nonfaulting: 1, imm8: 1, mask_flags: of | cf | af, }, - { opcode: 0xD6, nonfaulting: 1, }, + { opcode: 0xD5, imm8: 1, mask_flags: of | cf | af, }, + { opcode: 0xD6, }, // XXX: Temporary block boundary { opcode: 0xD7, skip: 1, block_boundary: 1, }, @@ -272,39 +272,39 @@ const encodings = [ { opcode: 0xF2, prefix: 1, }, { opcode: 0xF3, prefix: 1, }, { opcode: 0xF4, block_boundary: 1, no_next_instruction: 1, skip: 1, }, // hlt - { opcode: 0xF5, nonfaulting: 1, }, + { opcode: 0xF5, }, - { opcode: 0xF6, e: 1, fixed_g: 0, nonfaulting: 1, imm8: 1, custom: 1 }, - { opcode: 0xF6, e: 1, fixed_g: 1, nonfaulting: 1, imm8: 1, custom: 1 }, - { opcode: 0xF6, e: 1, fixed_g: 2, nonfaulting: 1, }, - { opcode: 0xF6, e: 1, fixed_g: 3, nonfaulting: 1, }, - { opcode: 0xF6, e: 1, fixed_g: 4, nonfaulting: 1, mask_flags: af | zf, }, - { opcode: 0xF6, e: 1, fixed_g: 5, nonfaulting: 1, mask_flags: af | zf, }, + { opcode: 0xF6, e: 1, fixed_g: 0, imm8: 1, custom: 1 }, + { opcode: 0xF6, e: 1, fixed_g: 1, imm8: 1, custom: 1 }, + { opcode: 0xF6, e: 1, fixed_g: 2, }, + { opcode: 0xF6, e: 1, fixed_g: 3, }, + { opcode: 0xF6, e: 1, fixed_g: 4, mask_flags: af | zf, }, + { opcode: 0xF6, e: 1, fixed_g: 5, mask_flags: af | zf, }, { opcode: 0xF6, e: 1, fixed_g: 6, block_boundary: 1, }, // div/idiv: Not a block boundary, but doesn't use control flow exceptions { opcode: 0xF6, e: 1, fixed_g: 7, block_boundary: 1, }, - { opcode: 0xF7, os: 1, e: 1, fixed_g: 0, nonfaulting: 1, imm1632: 1, custom: 1 }, - { opcode: 0xF7, os: 1, e: 1, fixed_g: 1, nonfaulting: 1, imm1632: 1, custom: 1 }, - { opcode: 0xF7, os: 1, e: 1, fixed_g: 2, nonfaulting: 1, }, - { opcode: 0xF7, os: 1, e: 1, fixed_g: 3, nonfaulting: 1, }, - { opcode: 0xF7, os: 1, e: 1, fixed_g: 4, nonfaulting: 1, mask_flags: zf | af, }, - { opcode: 0xF7, os: 1, e: 1, fixed_g: 5, nonfaulting: 1, mask_flags: zf | af, }, + { opcode: 0xF7, os: 1, e: 1, fixed_g: 0, imm1632: 1, custom: 1 }, + { opcode: 0xF7, os: 1, e: 1, fixed_g: 1, imm1632: 1, custom: 1 }, + { opcode: 0xF7, os: 1, e: 1, fixed_g: 2, }, + { opcode: 0xF7, os: 1, e: 1, fixed_g: 3, }, + { opcode: 0xF7, os: 1, e: 1, fixed_g: 4, mask_flags: zf | af, }, + { opcode: 0xF7, os: 1, e: 1, fixed_g: 5, mask_flags: zf | af, }, { opcode: 0xF7, os: 1, e: 1, fixed_g: 6, block_boundary: 1, }, // div/idiv: Not a block boundary, but doesn't use control flow exceptions { opcode: 0xF7, os: 1, e: 1, fixed_g: 7, block_boundary: 1, }, - { opcode: 0xF8, nonfaulting: 1, }, - { opcode: 0xF9, nonfaulting: 1, }, + { opcode: 0xF8, }, + { opcode: 0xF9, }, // cli: block_boundary since it uses non-raising cpu exceptions { opcode: 0xFA, block_boundary: 1, skip: 1, }, // sti: not a jump, but can cause a change in eip { opcode: 0xFB, block_boundary: 1, skip: 1, }, - { opcode: 0xFC, nonfaulting: 1, }, - { opcode: 0xFD, nonfaulting: 1, }, + { opcode: 0xFC, }, + { opcode: 0xFD, }, - { opcode: 0xFE, e: 1, fixed_g: 0, nonfaulting: 1, }, - { opcode: 0xFE, e: 1, fixed_g: 1, nonfaulting: 1, }, - { opcode: 0xFF, os: 1, e: 1, fixed_g: 0, nonfaulting: 1, custom: 1, }, - { opcode: 0xFF, os: 1, e: 1, fixed_g: 1, nonfaulting: 1, custom: 1, }, + { opcode: 0xFE, e: 1, fixed_g: 0, }, + { opcode: 0xFE, e: 1, fixed_g: 1, }, + { opcode: 0xFF, os: 1, e: 1, fixed_g: 0, custom: 1, }, + { opcode: 0xFF, os: 1, e: 1, fixed_g: 1, custom: 1, }, { opcode: 0xFF, os: 1, e: 1, fixed_g: 2, block_boundary: 1, skip: 1, }, { opcode: 0xFF, os: 1, e: 1, fixed_g: 3, block_boundary: 1, skip: 1, }, { opcode: 0xFF, os: 1, e: 1, fixed_g: 4, block_boundary: 1, no_next_instruction: 1, skip: 1, }, @@ -380,22 +380,22 @@ const encodings = [ { opcode: 0x0F3E, skip: 1 }, { opcode: 0x0F3F, skip: 1 }, - { opcode: 0x0F40, nonfaulting: 1, e: 1, os: 1, custom: 1, }, - { opcode: 0x0F41, nonfaulting: 1, e: 1, os: 1, custom: 1, }, - { opcode: 0x0F42, nonfaulting: 1, e: 1, os: 1, custom: 1, }, - { opcode: 0x0F43, nonfaulting: 1, e: 1, os: 1, custom: 1, }, - { opcode: 0x0F44, nonfaulting: 1, e: 1, os: 1, custom: 1, }, - { opcode: 0x0F45, nonfaulting: 1, e: 1, os: 1, custom: 1, }, - { opcode: 0x0F46, nonfaulting: 1, e: 1, os: 1, custom: 1, }, - { opcode: 0x0F47, nonfaulting: 1, e: 1, os: 1, custom: 1, }, - { opcode: 0x0F48, nonfaulting: 1, e: 1, os: 1, custom: 1, }, - { opcode: 0x0F49, nonfaulting: 1, e: 1, os: 1, custom: 1, }, - { opcode: 0x0F4A, nonfaulting: 1, e: 1, os: 1, custom: 1, }, - { opcode: 0x0F4B, nonfaulting: 1, e: 1, os: 1, custom: 1, }, - { opcode: 0x0F4C, nonfaulting: 1, e: 1, os: 1, custom: 1, }, - { opcode: 0x0F4D, nonfaulting: 1, e: 1, os: 1, custom: 1, }, - { opcode: 0x0F4E, nonfaulting: 1, e: 1, os: 1, custom: 1, }, - { opcode: 0x0F4F, nonfaulting: 1, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F40, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F41, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F42, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F43, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F44, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F45, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F46, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F47, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F48, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F49, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F4A, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F4B, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F4C, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F4D, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F4E, e: 1, os: 1, custom: 1, }, + { opcode: 0x0F4F, e: 1, os: 1, custom: 1, }, { opcode: 0x0F80, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, { opcode: 0x0F81, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, @@ -414,22 +414,22 @@ const encodings = [ { opcode: 0x0F8E, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, { opcode: 0x0F8F, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, - { opcode: 0x0F90, nonfaulting: 1, e: 1, custom: 1, }, - { opcode: 0x0F91, nonfaulting: 1, e: 1, custom: 1, }, - { opcode: 0x0F92, nonfaulting: 1, e: 1, custom: 1, }, - { opcode: 0x0F93, nonfaulting: 1, e: 1, custom: 1, }, - { opcode: 0x0F94, nonfaulting: 1, e: 1, custom: 1, }, - { opcode: 0x0F95, nonfaulting: 1, e: 1, custom: 1, }, - { opcode: 0x0F96, nonfaulting: 1, e: 1, custom: 1, }, - { opcode: 0x0F97, nonfaulting: 1, e: 1, custom: 1, }, - { opcode: 0x0F98, nonfaulting: 1, e: 1, custom: 1, }, - { opcode: 0x0F99, nonfaulting: 1, e: 1, custom: 1, }, - { opcode: 0x0F9A, nonfaulting: 1, e: 1, custom: 1, }, - { opcode: 0x0F9B, nonfaulting: 1, e: 1, custom: 1, }, - { opcode: 0x0F9C, nonfaulting: 1, e: 1, custom: 1, }, - { opcode: 0x0F9D, nonfaulting: 1, e: 1, custom: 1, }, - { opcode: 0x0F9E, nonfaulting: 1, e: 1, custom: 1, }, - { opcode: 0x0F9F, nonfaulting: 1, e: 1, custom: 1, }, + { opcode: 0x0F90, e: 1, custom: 1, }, + { opcode: 0x0F91, e: 1, custom: 1, }, + { opcode: 0x0F92, e: 1, custom: 1, }, + { opcode: 0x0F93, e: 1, custom: 1, }, + { opcode: 0x0F94, e: 1, custom: 1, }, + { opcode: 0x0F95, e: 1, custom: 1, }, + { opcode: 0x0F96, e: 1, custom: 1, }, + { opcode: 0x0F97, e: 1, custom: 1, }, + { opcode: 0x0F98, e: 1, custom: 1, }, + { opcode: 0x0F99, e: 1, custom: 1, }, + { opcode: 0x0F9A, e: 1, custom: 1, }, + { opcode: 0x0F9B, e: 1, custom: 1, }, + { opcode: 0x0F9C, e: 1, custom: 1, }, + { opcode: 0x0F9D, e: 1, custom: 1, }, + { opcode: 0x0F9E, e: 1, custom: 1, }, + { opcode: 0x0F9F, e: 1, custom: 1, }, // XXX: Temporary block boundary { opcode: 0x0FA0, os: 1, skip: 1, block_boundary: 1, }, @@ -455,10 +455,10 @@ const encodings = [ { opcode: 0x0FBD, os: 1, e: 1, mask_flags: af, }, // note: overflow flag only undefined if shift is > 1 - { opcode: 0x0FA4, nonfaulting: 1, os: 1, e: 1, imm8: 1, mask_flags: af | of, }, // shld - { opcode: 0x0FA5, nonfaulting: 1, os: 1, e: 1, mask_flags: af | of, }, - { opcode: 0x0FAC, nonfaulting: 1, os: 1, e: 1, imm8: 1, mask_flags: af | of, }, - { opcode: 0x0FAD, nonfaulting: 1, os: 1, e: 1, mask_flags: af | of, }, + { 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: 0x0FA6, skip: 1, block_boundary: 1, }, // ud { opcode: 0x0FA7, skip: 1, block_boundary: 1, }, // ud @@ -475,10 +475,10 @@ const encodings = [ { opcode: 0x0FAE, e: 1, fixed_g: 6, skip: 1, block_boundary: 1, }, // mfence (reg, only 0), xsaveopt (mem, not implemented) { opcode: 0x0FAE, e: 1, fixed_g: 7, skip: 1, block_boundary: 1, }, // sfence (reg, only 0), clflush (mem) - { opcode: 0x0FAF, nonfaulting: 1, os: 1, e: 1, mask_flags: af | zf, custom: 1, }, // imul + { opcode: 0x0FAF, os: 1, e: 1, mask_flags: af | zf, custom: 1, }, // imul - { opcode: 0x0FB0, nonfaulting: 1, e: 1 }, // cmxchg - { opcode: 0x0FB1, nonfaulting: 1, os: 1, e: 1 }, + { opcode: 0x0FB0, e: 1 }, // cmxchg + { opcode: 0x0FB1, os: 1, e: 1 }, { opcode: 0x0FC7, e: 1, fixed_g: 1, reg_ud: 1, }, // cmpxchg8b (memory) { opcode: 0x0FC7, e: 1, fixed_g: 6, mem_ud: 1, skip: 1, }, // rdrand @@ -486,28 +486,28 @@ const encodings = [ { opcode: 0x0FB4, block_boundary: 1, os: 1, e: 1, skip: 1, }, // lfs { opcode: 0x0FB5, block_boundary: 1, os: 1, e: 1, skip: 1, }, // lgs - { opcode: 0x0FB6, nonfaulting: 1, os: 1, e: 1, custom: 1 }, // movzx - { opcode: 0x0FB7, nonfaulting: 1, os: 1, e: 1, }, + { opcode: 0x0FB6, os: 1, e: 1, custom: 1 }, // movzx + { opcode: 0x0FB7, os: 1, e: 1, }, { opcode: 0xF30FB8, os: 1, e: 1 }, // popcnt { opcode: 0x0FB8, os: 1, e: 1, block_boundary: 1, }, // ud { opcode: 0x0FB9, block_boundary: 1, }, // ud2 - { opcode: 0x0FBE, nonfaulting: 1, os: 1, e: 1, custom: 1 }, // movsx - { opcode: 0x0FBF, nonfaulting: 1, os: 1, e: 1, }, + { opcode: 0x0FBE, os: 1, e: 1, custom: 1 }, // movsx + { opcode: 0x0FBF, os: 1, e: 1, }, - { opcode: 0x0FC0, nonfaulting: 1, e: 1, }, // xadd - { opcode: 0x0FC1, nonfaulting: 1, os: 1, e: 1, }, + { opcode: 0x0FC0, e: 1, }, // xadd + { opcode: 0x0FC1, os: 1, e: 1, }, - { opcode: 0x0FC8, nonfaulting: 1, }, // bswap - { opcode: 0x0FC9, nonfaulting: 1, }, - { opcode: 0x0FCA, nonfaulting: 1, }, - { opcode: 0x0FCB, nonfaulting: 1, }, - { opcode: 0x0FCC, nonfaulting: 1, }, - { opcode: 0x0FCD, nonfaulting: 1, }, - { opcode: 0x0FCE, nonfaulting: 1, }, - { opcode: 0x0FCF, nonfaulting: 1, }, + { opcode: 0x0FC8, }, // bswap + { opcode: 0x0FC9, }, + { opcode: 0x0FCA, }, + { opcode: 0x0FCB, }, + { opcode: 0x0FCC, }, + { opcode: 0x0FCD, }, + { opcode: 0x0FCE, }, + { opcode: 0x0FCF, }, // mmx, sse @@ -837,28 +837,28 @@ const encodings = [ for(let i = 0; i < 8; i++) { encodings.push.apply(encodings, [ - { opcode: 0x04 | i << 3, nonfaulting: 1, eax: 1, imm8: 1, }, - { opcode: 0x05 | i << 3, nonfaulting: 1, os: 1, eax: 1, imm1632: 1, }, + { opcode: 0x04 | i << 3, eax: 1, imm8: 1, }, + { opcode: 0x05 | i << 3, os: 1, eax: 1, imm1632: 1, }, { opcode: 0x70 | i, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, os: 1, imm8s: 1, custom: 1, skip: 1, }, { opcode: 0x78 | i, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, os: 1, imm8s: 1, custom: 1, skip: 1, }, - { opcode: 0x80, nonfaulting: 1, e: 1, fixed_g: i, imm8: 1, }, - { opcode: 0x81, nonfaulting: 1, os: 1, e: 1, fixed_g: i, imm1632: 1, custom: 1, }, - { opcode: 0x82, nonfaulting: 1, e: 1, fixed_g: i, imm8: 1, }, - { opcode: 0x83, nonfaulting: 1, os: 1, e: 1, fixed_g: i, imm8s: 1, custom: 1, }, + { opcode: 0x80, e: 1, fixed_g: i, imm8: 1, }, + { opcode: 0x81, os: 1, e: 1, fixed_g: i, imm1632: 1, custom: 1, }, + { opcode: 0x82, e: 1, fixed_g: i, imm8: 1, }, + { opcode: 0x83, os: 1, e: 1, fixed_g: i, imm8s: 1, custom: 1, }, - { opcode: 0xB0 | i, nonfaulting: 1, imm8: 1, }, - { opcode: 0xB8 | i, nonfaulting: 1, os: 1, imm1632: 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, nonfaulting: 1, e: 1, fixed_g: i, imm8: 1, mask_flags: of | af, }, - { opcode: 0xC1, nonfaulting: 1, os: 1, e: 1, fixed_g: i, imm8: 1, mask_flags: of | af, custom: 1, }, - { opcode: 0xD0, nonfaulting: 1, e: 1, fixed_g: i, mask_flags: af, }, - { opcode: 0xD1, nonfaulting: 1, os: 1, e: 1, fixed_g: i, mask_flags: af, custom: 1, }, - { opcode: 0xD2, nonfaulting: 1, e: 1, fixed_g: i, mask_flags: of | af, }, - { opcode: 0xD3, nonfaulting: 1, os: 1, e: 1, fixed_g: i, mask_flags: of | af, custom: 1, }, + { 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, custom: 1, }, + { opcode: 0xD0, e: 1, fixed_g: i, mask_flags: af, }, + { opcode: 0xD1, os: 1, e: 1, fixed_g: i, mask_flags: af, custom: 1, }, + { opcode: 0xD2, e: 1, fixed_g: i, mask_flags: of | af, }, + { opcode: 0xD3, os: 1, e: 1, fixed_g: i, mask_flags: of | af, custom: 1, }, { opcode: 0xD8, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, }, @@ -877,18 +877,4 @@ encodings.sort((e1, e2) => { return o1 - o2 || e1.fixed_g - e2.fixed_g; }); -function test_encodings() -{ - const invalid = encodings.find(e => e.nonfaulting && e.block_boundary); - - if(invalid) - { - console.assert( - false, - "Unsupported: instruction cannot be both a block boundary and nonfaulting. Opcode: " + hex(invalid.opcode) - ); - } -} -test_encodings(); - module.exports = Object.freeze(encodings.map(entry => Object.freeze(entry))); diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 369e8ef3..76393247 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -383,7 +383,6 @@ pub struct JitContext<'a> { } pub const JIT_INSTR_BLOCK_BOUNDARY_FLAG: u32 = 1 << 0; -pub const JIT_INSTR_NONFAULTING_FLAG: u32 = 1 << 1; pub const FN_GET_SEG_IDX: u16 = 0; From 98d69c0befc54c39d8f84b122b7565147a5ee9b6 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 31 Aug 2018 15:29:15 -0500 Subject: [PATCH 1273/2137] Mark unimplemented instructions as block boundaries --- gen/x86_table.js | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 867d52d5..0ed4b9af 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -366,19 +366,22 @@ const encodings = [ { opcode: 0x0F30, skip: 1, block_boundary: 1, }, // wrmsr { opcode: 0x0F31, skip: 1, block_boundary: 1, }, // rdtsc { opcode: 0x0F32, skip: 1, block_boundary: 1, }, // rdmsr - { opcode: 0x0F33, skip: 1, }, // rdpmc + { opcode: 0x0F33, skip: 1, block_boundary: 1, }, // rdpmc { opcode: 0x0F34, skip: 1, block_boundary: 1, no_next_instruction: 1, }, // sysenter { opcode: 0x0F35, skip: 1, block_boundary: 1, no_next_instruction: 1, }, // sysexit - { opcode: 0x0F36, skip: 1, block_boundary: 1, }, - { opcode: 0x0F37, skip: 1 }, - { opcode: 0x0F38, skip: 1 }, - { opcode: 0x0F39, skip: 1 }, - { opcode: 0x0F3A, skip: 1 }, - { opcode: 0x0F3B, skip: 1 }, - { opcode: 0x0F3C, skip: 1 }, - { opcode: 0x0F3D, skip: 1 }, - { opcode: 0x0F3E, skip: 1 }, - { opcode: 0x0F3F, skip: 1 }, + + { opcode: 0x0F36, skip: 1, block_boundary: 1, }, // ud + { opcode: 0x0F37, skip: 1, block_boundary: 1, }, // getsec + + // sse3+ + { opcode: 0x0F38, skip: 1, block_boundary: 1, }, + { opcode: 0x0F39, skip: 1, block_boundary: 1, }, + { opcode: 0x0F3A, skip: 1, block_boundary: 1, }, + { opcode: 0x0F3B, skip: 1, block_boundary: 1, }, + { opcode: 0x0F3C, skip: 1, block_boundary: 1, }, + { opcode: 0x0F3D, skip: 1, block_boundary: 1, }, + { opcode: 0x0F3E, skip: 1, block_boundary: 1, }, + { opcode: 0x0F3F, skip: 1, block_boundary: 1, }, { opcode: 0x0F40, e: 1, os: 1, custom: 1, }, { opcode: 0x0F41, e: 1, os: 1, custom: 1, }, @@ -523,8 +526,8 @@ const encodings = [ { sse: 1, opcode: 0xF20F11, e: 1 }, { sse: 1, opcode: 0x0F12, e: 1 }, { sse: 1, opcode: 0x660F12, reg_ud: 1, e: 1 }, - { sse: 1, opcode: 0xF20F12, e: 1, skip: 1, }, // sse3 - { sse: 1, opcode: 0xF30F12, e: 1, skip: 1, }, // sse3 + { sse: 1, opcode: 0xF20F12, e: 1, skip: 1, block_boundary: 1, }, // sse3 + { sse: 1, opcode: 0xF30F12, e: 1, skip: 1, block_boundary: 1, }, // sse3 { sse: 1, opcode: 0x0F13, reg_ud: 1, e: 1 }, { sse: 1, opcode: 0x660F13, reg_ud: 1, e: 1 }, { sse: 1, opcode: 0x0F14, e: 1 }, @@ -533,7 +536,7 @@ const encodings = [ { sse: 1, opcode: 0x660F15, e: 1 }, { sse: 1, opcode: 0x0F16, e: 1 }, { sse: 1, opcode: 0x660F16, reg_ud: 1, e: 1 }, - { sse: 1, opcode: 0xF30F16, skip: 1, e: 1 }, // sse3 + { sse: 1, opcode: 0xF30F16, skip: 1, e: 1, block_boundary: 1, }, // sse3 { sse: 1, opcode: 0x0F17, reg_ud: 1, e: 1 }, { sse: 1, opcode: 0x660F17, reg_ud: 1, e: 1 }, @@ -692,13 +695,13 @@ const encodings = [ { sse: 1, opcode: 0x0F77 }, // vmx instructions - { opcode: 0x0F78, skip: 1 }, - { opcode: 0x0F79, skip: 1 }, + { opcode: 0x0F78, skip: 1, block_boundary: 1, }, + { opcode: 0x0F79, skip: 1, block_boundary: 1, }, - { opcode: 0x0F7A, skip: 1 }, // ud - { opcode: 0x0F7B, skip: 1 }, // ud - { sse: 1, opcode: 0x0F7C, skip: 1 }, // sse3 - { sse: 1, opcode: 0x0F7D, skip: 1 }, // sse3 + { opcode: 0x0F7A, skip: 1, block_boundary: 1, }, // ud + { opcode: 0x0F7B, skip: 1, block_boundary: 1, }, // ud + { sse: 1, opcode: 0x0F7C, skip: 1, block_boundary: 1, }, // sse3 + { sse: 1, opcode: 0x0F7D, skip: 1, block_boundary: 1, }, // sse3 { sse: 1, opcode: 0x0F7E, e: 1 }, { sse: 1, opcode: 0x660F7E, e: 1 }, @@ -722,7 +725,7 @@ const encodings = [ { sse: 1, opcode: 0x0FC6, e: 1, imm8: 1 }, { sse: 1, opcode: 0x660FC6, e: 1, imm8: 1 }, - { sse: 1, opcode: 0x0FD0, skip: 1, }, // sse3 + { sse: 1, opcode: 0x0FD0, skip: 1, block_boundary: 1, }, // sse3 { sse: 1, opcode: 0x0FD1, e: 1 }, { sse: 1, opcode: 0x660FD1, e: 1 }, @@ -797,7 +800,7 @@ const encodings = [ { sse: 1, opcode: 0x0FEF, e: 1 }, { sse: 1, opcode: 0x660FEF, e: 1 }, - { sse: 1, opcode: 0x0FF0, skip: 1, }, // sse3 + { sse: 1, opcode: 0x0FF0, skip: 1, block_boundary: 1, }, // sse3 { sse: 1, opcode: 0x0FF1, e: 1 }, { sse: 1, opcode: 0x660FF1, e: 1 }, From d691b311a235d4a4101027b08726097127dce3d2 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 31 Aug 2018 16:52:53 -0500 Subject: [PATCH 1274/2137] Simplify some code --- src/rust/jit.rs | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 76393247..484f9540 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -990,12 +990,12 @@ fn jit_generate_module( let invalid_connection_to_next_block = block.end_addr != cpu.eip; dbg_assert!(!invalid_connection_to_next_block); - match (&block.ty, invalid_connection_to_next_block) { - (_, true) | (BasicBlockType::Exit, _) => { + match &block.ty { + BasicBlockType::Exit => { // Exit this function builder.instruction_body.return_(); }, - (BasicBlockType::Normal { next_block_addr }, _) => { + BasicBlockType::Normal { next_block_addr } => { // Unconditional jump to next basic block // - All instructions that don't change eip // - Unconditional jump @@ -1012,16 +1012,13 @@ fn jit_generate_module( .instruction_body .br(basic_blocks.len() as u32 - i as u32); // to the loop }, - ( - &BasicBlockType::ConditionalJump { - next_block_addr, - next_block_branch_taken_addr, - condition, - jump_offset, - jump_offset_is_32, - }, - _, - ) => { + &BasicBlockType::ConditionalJump { + next_block_addr, + next_block_branch_taken_addr, + condition, + jump_offset, + jump_offset_is_32, + } => { // Conditional jump to next basic block // - jnz, jc, etc. From 41b60d278c3ae6ef85419fef0899e60ca116d43b Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 31 Aug 2018 17:01:53 -0500 Subject: [PATCH 1275/2137] Accept builder in gen_jmp_rel16, simplifying --- src/rust/codegen.rs | 12 +++++------- src/rust/jit.rs | 8 +------- src/rust/jit_instructions.rs | 8 +++++--- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index a9d2eca9..8da17566 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -494,17 +494,15 @@ pub fn gen_add_prefix_bits(ctx: &mut JitContext, mask: u32) { instruction_body.store_aligned_i32(0); } -pub fn gen_jmp_rel16(ctx: &mut JitContext, rel16: u16) { +pub fn gen_jmp_rel16(builder: &mut WasmBuilder, rel16: u16) { let cs_offset_addr = global_pointers::get_seg_offset(regs::CS); - ctx.builder - .instruction_body - .load_aligned_i32(cs_offset_addr); - let local = ctx.builder.set_new_local(); + builder.instruction_body.load_aligned_i32(cs_offset_addr); + let local = builder.set_new_local(); // generate: // *instruction_pointer = cs_offset + ((*instruction_pointer - cs_offset + rel16) & 0xFFFF); { - let instruction_body = &mut ctx.builder.instruction_body; + let instruction_body = &mut builder.instruction_body; instruction_body.const_i32(global_pointers::INSTRUCTION_POINTER as i32); @@ -523,7 +521,7 @@ pub fn gen_jmp_rel16(ctx: &mut JitContext, rel16: u16) { instruction_body.store_aligned_i32(0); } - ctx.builder.free_local(local); + builder.free_local(local); } pub fn gen_pop16_ss16(ctx: &mut JitContext) { diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 484f9540..028e7c99 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -1035,13 +1035,7 @@ fn jit_generate_module( codegen::gen_relative_jump(builder, jump_offset); } else { - // TODO: Is this necessary? - let ctx = &mut JitContext { - cpu: &mut cpu.clone(), - builder, - start_of_current_instruction: 0, - }; - codegen::gen_jmp_rel16(ctx, jump_offset as u16); + codegen::gen_jmp_rel16(builder, jump_offset as u16); } if let Some(next_block_branch_taken_addr) = next_block_branch_taken_addr { diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index e89d77e7..6a70382f 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1289,7 +1289,7 @@ pub fn instr16_E8_jit(ctx: &mut JitContext, imm: u32) { let value_local = ctx.builder.set_new_local(); codegen::gen_push16(ctx, &value_local); ctx.builder.free_local(value_local); - codegen::gen_jmp_rel16(ctx, imm as u16); + codegen::gen_jmp_rel16(ctx.builder, imm as u16); } pub fn instr32_E8_jit(ctx: &mut JitContext, imm: u32) { codegen::gen_get_real_eip(ctx); @@ -1307,7 +1307,9 @@ pub fn instr32_E8_jit(ctx: &mut JitContext, imm: u32) { ctx.builder.instruction_body.store_aligned_i32(0); } -pub fn instr16_E9_jit(ctx: &mut JitContext, imm: u32) { codegen::gen_jmp_rel16(ctx, imm as u16); } +pub fn instr16_E9_jit(ctx: &mut JitContext, imm: u32) { + codegen::gen_jmp_rel16(ctx.builder, imm as u16); +} pub fn instr32_E9_jit(ctx: &mut JitContext, imm: u32) { codegen::gen_relative_jump(ctx.builder, imm as i32); } @@ -1588,7 +1590,7 @@ define_instruction_read_write_mem32!( ); pub fn instr16_EB_jit(ctx: &mut JitContext, imm8: u32) { - codegen::gen_jmp_rel16(ctx, imm8 as u16); + codegen::gen_jmp_rel16(ctx.builder, imm8 as u16); // dbg_assert(is_asize_32() || get_real_eip() < 0x10000); } From 295985e8e02a653ab9b697689a5d0c4cf7182282 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 31 Aug 2018 17:09:36 -0500 Subject: [PATCH 1276/2137] Remove code section: Only a single buffer is used for generating code --- src/rust/codegen.rs | 10 +++--- src/rust/jit.rs | 4 --- src/rust/wasmgen/module_init.rs | 37 ++++++++------------ tests/expect/tests/call.wast | 26 +++++++------- tests/expect/tests/do-while.wast | 2 +- tests/expect/tests/if.wast | 4 +-- tests/expect/tests/indirect-call.wast | 14 ++++---- tests/expect/tests/mov16.wast | 2 +- tests/expect/tests/mov32-mem.wast | 2 +- tests/expect/tests/mov32-reg.wast | 2 +- tests/expect/tests/pop.wast | 2 +- tests/expect/tests/push.wast | 2 +- tests/expect/tests/task_switch_test.wast | 14 ++++---- tests/expect/tests/task_switch_test_sse.wast | 14 ++++---- tests/expect/tests/while-do.wast | 14 ++++---- 15 files changed, 69 insertions(+), 80 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 8da17566..2d7720f6 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -14,7 +14,7 @@ extern "C" { } pub fn gen_set_previous_eip_offset_from_eip(builder: &mut WasmBuilder, n: u32) { - let cs = &mut builder.code_section; + let cs = &mut builder.instruction_body; cs.const_i32(global_pointers::PREVIOUS_IP as i32); // store address of previous ip cs.load_aligned_i32(global_pointers::INSTRUCTION_POINTER); // load ip if n != 0 { @@ -25,7 +25,7 @@ pub fn gen_set_previous_eip_offset_from_eip(builder: &mut WasmBuilder, n: u32) { } pub fn gen_increment_instruction_pointer(builder: &mut WasmBuilder, n: u32) { - let cs = &mut builder.code_section; + let cs = &mut builder.instruction_body; cs.const_i32(global_pointers::INSTRUCTION_POINTER as i32); // store address of ip cs.load_aligned_i32(global_pointers::INSTRUCTION_POINTER); // load ip @@ -47,7 +47,9 @@ pub fn gen_relative_jump(builder: &mut WasmBuilder, n: i32) { } pub fn gen_increment_variable(builder: &mut WasmBuilder, variable_address: u32, n: i32) { - builder.code_section.increment_variable(variable_address, n); + builder + .instruction_body + .increment_variable(variable_address, n); } pub fn gen_increment_timestamp_counter(builder: &mut WasmBuilder, n: i32) { @@ -55,7 +57,7 @@ pub fn gen_increment_timestamp_counter(builder: &mut WasmBuilder, n: i32) { } pub fn gen_increment_mem32(builder: &mut WasmBuilder, addr: u32) { - builder.code_section.increment_mem32(addr) + builder.instruction_body.increment_mem32(addr) } pub fn gen_get_reg8(builder: &mut WasmBuilder, r: u32) { diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 028e7c99..7589550b 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -977,7 +977,6 @@ fn jit_generate_module( dbg_assert!(block.addr < block.end_addr); - builder.commit_instruction_body_to_cs(); jit_generate_basic_block( &mut cpu, builder, @@ -985,7 +984,6 @@ fn jit_generate_module( block.last_instruction_addr, block.end_addr, ); - builder.commit_instruction_body_to_cs(); let invalid_connection_to_next_block = block.end_addr != cpu.eip; dbg_assert!(!invalid_connection_to_next_block); @@ -1086,7 +1084,6 @@ fn jit_generate_module( builder.instruction_body.block_end(); // loop - builder.commit_instruction_body_to_cs(); builder.finish(); } @@ -1113,7 +1110,6 @@ fn jit_generate_basic_block( // Before the last instruction: // - Set eip to *after* the instruction // - Set previous_eip to *before* the instruction - builder.commit_instruction_body_to_cs(); codegen::gen_set_previous_eip_offset_from_eip( builder, last_instruction_addr - start_addr, diff --git a/src/rust/wasmgen/module_init.rs b/src/rust/wasmgen/module_init.rs index 66f7b91c..9530165a 100644 --- a/src/rust/wasmgen/module_init.rs +++ b/src/rust/wasmgen/module_init.rs @@ -22,7 +22,6 @@ pub const NR_FN_TYPE_INDEXES: u8 = 7; pub struct WasmBuilder { pub output: Vec, - pub code_section: Vec, pub instruction_body: Vec, idx_import_table_size: usize, // for rewriting once finished @@ -48,7 +47,6 @@ impl WasmBuilder { pub fn new() -> Self { WasmBuilder { output: Vec::with_capacity(256), - code_section: Vec::with_capacity(256), instruction_body: Vec::with_capacity(256), idx_import_table_size: 0, @@ -86,7 +84,6 @@ impl WasmBuilder { self.output.drain(self.initial_static_size..); self.set_import_table_size(2); self.set_import_count(0); - self.code_section.clear(); self.instruction_body.clear(); self.free_locals.clear(); self.local_count = 0; @@ -120,7 +117,7 @@ impl WasmBuilder { self.output.push(self.local_count); self.output.push(op::TYPE_I32); - self.output.append(&mut self.code_section); + self.output.append(&mut self.instruction_body); self.output.push(op::OP_END); @@ -325,10 +322,6 @@ impl WasmBuilder { pub fn get_op_len(&self) -> u32 { self.output.len() as u32 } - pub fn commit_instruction_body_to_cs(&mut self) { - self.code_section.append(&mut self.instruction_body); - } - #[must_use = "local allocated but not used"] fn alloc_local(&mut self) -> WasmLocal { match self.free_locals.pop() { @@ -385,31 +378,31 @@ mod tests { m.init(); let mut foo_index = m.get_fn_idx("foo", FN0_TYPE_INDEX); - m.code_section.call_fn(foo_index); + m.instruction_body.call_fn(foo_index); let bar_index = m.get_fn_idx("bar", FN0_TYPE_INDEX); - m.code_section.call_fn(bar_index); + m.instruction_body.call_fn(bar_index); let _ = m.alloc_local(); // for ensuring that reset clears previous locals m.finish(); m.reset(); - m.code_section.const_i32(2); + m.instruction_body.const_i32(2); let baz_index = m.get_fn_idx("baz", FN1_RET_TYPE_INDEX); m.instruction_body.call_fn(baz_index); foo_index = m.get_fn_idx("foo", FN1_TYPE_INDEX); m.instruction_body.call_fn(foo_index); - m.code_section.const_i32(10); + m.instruction_body.const_i32(10); let local1 = m.alloc_local(); - m.code_section.tee_local(&local1); // local1 = 10 + m.instruction_body.tee_local(&local1); // local1 = 10 - m.code_section.const_i32(20); - m.code_section.add_i32(); + m.instruction_body.const_i32(20); + m.instruction_body.add_i32(); let local2 = m.alloc_local(); - m.code_section.tee_local(&local2); // local2 = 30 + m.instruction_body.tee_local(&local2); // local2 = 30 m.free_local(local1); @@ -419,13 +412,11 @@ mod tests { m.free_local(local2); m.free_local(local3); - m.code_section.const_i32(30); - m.code_section.ne_i32(); - m.code_section.if_void(); - m.code_section.unreachable(); - m.code_section.block_end(); - - m.commit_instruction_body_to_cs(); + m.instruction_body.const_i32(30); + m.instruction_body.ne_i32(); + m.instruction_body.if_void(); + m.instruction_body.unreachable(); + m.instruction_body.block_end(); m.finish(); diff --git a/tests/expect/tests/call.wast b/tests/expect/tests/call.wast index a94b7e68..84bdc6b7 100644 --- a/tests/expect/tests/call.wast +++ b/tests/expect/tests/call.wast @@ -33,12 +33,6 @@ (i32.load (i32.const 556)) (i32.const 5))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 1))) (set_local $l0 (i32.sub (i32.load @@ -106,6 +100,12 @@ (i32.load (i32.const 556)) (i32.const 1))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) (set_local $p0 (i32.const 2)) (br $L0)) @@ -119,13 +119,13 @@ (i32.load (i32.const 556)) (i32.const 1))) + (call $e.instr_F4) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 1))) - (call $e.instr_F4) (return)) (call $e.instr32_40) (i32.store @@ -140,12 +140,6 @@ (i32.load (i32.const 556)) (i32.const 2))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 2))) (i32.const 556) (i32.load (i32.const 740)) @@ -203,5 +197,11 @@ (i32.const 4))) (i32.add) (i32.store) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 2))) (return)) (unreachable)))) diff --git a/tests/expect/tests/do-while.wast b/tests/expect/tests/do-while.wast index 072719bb..5d5fa859 100644 --- a/tests/expect/tests/do-while.wast +++ b/tests/expect/tests/do-while.wast @@ -81,12 +81,12 @@ (i32.load (i32.const 556)) (i32.const 1))) + (call $e.instr_F4) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 1))) - (call $e.instr_F4) (return)) (unreachable)))) diff --git a/tests/expect/tests/if.wast b/tests/expect/tests/if.wast index ee22360c..8eb156bc 100644 --- a/tests/expect/tests/if.wast +++ b/tests/expect/tests/if.wast @@ -71,13 +71,13 @@ (i32.load (i32.const 556)) (i32.const 1))) + (call $e.instr32_41) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 1))) - (call $e.instr32_41) (set_local $p0 (i32.const 2)) (br $L0)) @@ -94,12 +94,12 @@ (i32.load (i32.const 556)) (i32.const 2))) + (call $e.instr_F4) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 2))) - (call $e.instr_F4) (return)) (unreachable)))) diff --git a/tests/expect/tests/indirect-call.wast b/tests/expect/tests/indirect-call.wast index f5f00765..04d08758 100644 --- a/tests/expect/tests/indirect-call.wast +++ b/tests/expect/tests/indirect-call.wast @@ -30,18 +30,18 @@ (i32.load (i32.const 556)) (i32.const 2))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 1))) (call $e.instr32_FF_2_mem (i32.add (i32.load (i32.const 4)) (call $e.get_seg (i32.const 3)))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) (return)) (i32.store (i32.const 560) @@ -53,12 +53,12 @@ (i32.load (i32.const 556)) (i32.const 1))) + (call $e.instr_F4) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 1))) - (call $e.instr_F4) (return)) (unreachable)))) diff --git a/tests/expect/tests/mov16.wast b/tests/expect/tests/mov16.wast index 9350974e..2019d4cf 100644 --- a/tests/expect/tests/mov16.wast +++ b/tests/expect/tests/mov16.wast @@ -265,12 +265,12 @@ (i32.load (i32.const 556)) (i32.const 32))) + (call $e.instr_F4) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 12))) - (call $e.instr_F4) (return)) (unreachable)))) diff --git a/tests/expect/tests/mov32-mem.wast b/tests/expect/tests/mov32-mem.wast index cf0e37f6..d6af9123 100644 --- a/tests/expect/tests/mov32-mem.wast +++ b/tests/expect/tests/mov32-mem.wast @@ -240,12 +240,12 @@ (i32.load (i32.const 556)) (i32.const 25))) + (call $e.instr_F4) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 5))) - (call $e.instr_F4) (return)) (unreachable)))) diff --git a/tests/expect/tests/mov32-reg.wast b/tests/expect/tests/mov32-reg.wast index a321c8ab..503218d1 100644 --- a/tests/expect/tests/mov32-reg.wast +++ b/tests/expect/tests/mov32-reg.wast @@ -58,12 +58,12 @@ (i32.load (i32.const 556)) (i32.const 29))) + (call $e.instr_F4) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 9))) - (call $e.instr_F4) (return)) (unreachable)))) diff --git a/tests/expect/tests/pop.wast b/tests/expect/tests/pop.wast index dfb735f8..14e0f72f 100644 --- a/tests/expect/tests/pop.wast +++ b/tests/expect/tests/pop.wast @@ -85,12 +85,12 @@ (i32.load (i32.const 556)) (i32.const 2))) + (call $e.instr_F4) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 2))) - (call $e.instr_F4) (return)) (unreachable)))) diff --git a/tests/expect/tests/push.wast b/tests/expect/tests/push.wast index 74cdf8d5..740fcedf 100644 --- a/tests/expect/tests/push.wast +++ b/tests/expect/tests/push.wast @@ -89,12 +89,12 @@ (i32.load (i32.const 556)) (i32.const 2))) + (call $e.instr_F4) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 2))) - (call $e.instr_F4) (return)) (unreachable)))) diff --git a/tests/expect/tests/task_switch_test.wast b/tests/expect/tests/task_switch_test.wast index 847a3977..a7103237 100644 --- a/tests/expect/tests/task_switch_test.wast +++ b/tests/expect/tests/task_switch_test.wast @@ -31,12 +31,6 @@ (i32.load (i32.const 556)) (i32.const 2))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 1))) (if $I4 (i32.and (i32.load @@ -47,6 +41,12 @@ (return))) (call $e.instr_DE_0_reg (i32.const 1)) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) (return)) (i32.store (i32.const 560) @@ -58,12 +58,12 @@ (i32.load (i32.const 556)) (i32.const 1))) + (call $e.instr_F4) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 1))) - (call $e.instr_F4) (return)) (unreachable)))) diff --git a/tests/expect/tests/task_switch_test_sse.wast b/tests/expect/tests/task_switch_test_sse.wast index fa596b56..6bb7f7b3 100644 --- a/tests/expect/tests/task_switch_test_sse.wast +++ b/tests/expect/tests/task_switch_test_sse.wast @@ -31,12 +31,6 @@ (i32.load (i32.const 556)) (i32.const 4))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 1))) (i32.store (i32.const 648) (i32.or @@ -57,6 +51,12 @@ (i32.store (i32.const 648) (i32.const 0)) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) (return)) (i32.store (i32.const 560) @@ -68,12 +68,12 @@ (i32.load (i32.const 556)) (i32.const 1))) + (call $e.instr_F4) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 1))) - (call $e.instr_F4) (return)) (unreachable)))) diff --git a/tests/expect/tests/while-do.wast b/tests/expect/tests/while-do.wast index f57c61b2..55e94418 100644 --- a/tests/expect/tests/while-do.wast +++ b/tests/expect/tests/while-do.wast @@ -73,18 +73,18 @@ (i32.load (i32.const 556)) (i32.const 3))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 2))) (i32.store (i32.const 556) (i32.add (i32.load (i32.const 556)) (i32.const -8))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 2))) (set_local $p0 (i32.const 0)) (br $L0)) @@ -98,12 +98,12 @@ (i32.load (i32.const 556)) (i32.const 1))) + (call $e.instr_F4) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 1))) - (call $e.instr_F4) (return)) (unreachable)))) From beaa54feda48aed6f225b5db2cb5a83a78ed34aa Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 31 Aug 2018 17:11:51 -0500 Subject: [PATCH 1277/2137] popf: Call handle_irqs only if interrupt flag is set from 0 to 1 --- src/rust/cpu2/instructions.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index f17b2fdd..e45899ab 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -1760,12 +1760,9 @@ pub unsafe fn instr16_9D() { return; } else { - update_eflags(*flags.offset(0) & !65535 | return_on_pagefault!(pop16())); - if 0 != *flags.offset(0) & FLAG_TRAP { - let ref mut fresh0 = *flags.offset(0); - *fresh0 &= !FLAG_TRAP - } - else { + let old_eflags = *flags; + update_eflags(*flags & !65535 | return_on_pagefault!(pop16())); + if old_eflags & FLAG_INTERRUPT == 0 && *flags & FLAG_INTERRUPT != 0 { handle_irqs(); } return; @@ -1780,8 +1777,11 @@ pub unsafe fn instr32_9D() { return; } else { + let old_eflags = *flags; update_eflags(return_on_pagefault!(pop32s())); - handle_irqs(); + if old_eflags & FLAG_INTERRUPT == 0 && *flags & FLAG_INTERRUPT != 0 { + handle_irqs(); + } return; }; } From 1980a9609345a8fb502f456a23924d89ec94e2a3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 31 Aug 2018 17:14:38 -0500 Subject: [PATCH 1278/2137] popf: Warn on trap flag --- src/rust/cpu2/instructions.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index e45899ab..c4e70d94 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -1765,6 +1765,10 @@ pub unsafe fn instr16_9D() { if old_eflags & FLAG_INTERRUPT == 0 && *flags & FLAG_INTERRUPT != 0 { handle_irqs(); } + if *flags & FLAG_TRAP != 0 { + dbg_log!("Not supported: trap flag"); + } + *flags &= !FLAG_TRAP; return; }; } @@ -1782,6 +1786,10 @@ pub unsafe fn instr32_9D() { if old_eflags & FLAG_INTERRUPT == 0 && *flags & FLAG_INTERRUPT != 0 { handle_irqs(); } + if *flags & FLAG_TRAP != 0 { + dbg_log!("Not supported: trap flag"); + } + *flags &= !FLAG_TRAP; return; }; } From d368ccf6171f993ffd034342093349274b258c25 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 29 Aug 2018 16:39:13 +1200 Subject: [PATCH 1279/2137] Add more tests for filesystem hardlinks --- tests/devices/virtio_9p.js | 87 +++++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 5 deletions(-) diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index 26bf7ddf..f0372f88 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -399,7 +399,6 @@ const tests = { name: "Hard Links", timeout: 60, - allow_failure: true, files: [ { @@ -665,7 +664,6 @@ const tests = { name: "File Attributes", timeout: 60, - allow_failure: true, start: () => { emulator.serial0_send("echo start-capture;"); @@ -677,12 +675,13 @@ const tests = emulator.serial0_send("chmod +x /mnt/file;"); emulator.serial0_send("chmod -w /mnt/file;"); + emulator.serial0_send("ln /mnt/file /mnt/file-link;"); emulator.serial0_send("ls -l --full-time --color=never /mnt/file;"); emulator.serial0_send("chmod -x /mnt/file;"); emulator.serial0_send("truncate -s 100 /mnt/file;"); emulator.serial0_send("touch -t 201011220344 /mnt/file;"); - emulator.serial0_send("ln /mnt/file /mnt/file-link;"); + emulator.serial0_send("rm /mnt/file-link;"); emulator.serial0_send("ls -l --full-time --color=never /mnt/file;"); emulator.serial0_send("echo done-file-attr\n"); @@ -721,7 +720,7 @@ const tests = // mode assert_equal(outputs[1][0], "-r-xr-xr-x"); // nlinks - assert_equal(outputs[1][1], "1"); + assert_equal(outputs[1][1], "2"); // user assert_equal(outputs[1][2], "root"); // group @@ -738,7 +737,7 @@ const tests = // mode assert_equal(outputs[2][0], "-r--r--r--"); // nlinks - assert_equal(outputs[2][1], "2"); + assert_equal(outputs[2][1], "1"); // user assert_equal(outputs[2][2], "root"); // group @@ -1281,6 +1280,84 @@ const tests = done(); }, }, + { + name: "Hard Links Mounted", + timeout: 60, + mounts: + [ + { path: "/fs1a" }, + { path: "/fs1a/fs2a" }, + { path: "/fs1a/fs2a/fs3" }, + { path: "/fs1a/fs2b" }, + { path: "/fs1b" }, + ], + start: () => + { + emulator.serial0_send("echo foobar > /mnt/fs1a/fs2a/file\n"); + + emulator.serial0_send("echo start-capture;\\\n"); + + emulator.serial0_send("ln /mnt/fs1a/fs2a/file /mnt/link-root;\\\n"); + emulator.serial0_send("echo link at root fs >> /mnt/link-root;\\\n"); + emulator.serial0_send("rm /mnt/link-root;\\\n"); + + emulator.serial0_send("{ ln /mnt/fs1a/fs2a/file /mnt/fs1a/fs2a/fs3/link-child 2>/dev/null || \n"); + emulator.serial0_send(" echo link at child fs - fails >> /mnt/fs1a/fs2a/file; };\\\n"); + + emulator.serial0_send("ln /mnt/fs1a/fs2a/file /mnt/fs1a/fs2a/link;\\\n"); + emulator.serial0_send("echo link at common fs >> /mnt/fs1a/fs2a/link;\\\n"); + + emulator.serial0_send("mv /mnt/fs1a/fs2a/link /mnt/fs1a/fs2a/link-renamed;\\\n"); + emulator.serial0_send("echo rename >> /mnt/fs1a/fs2a/link-renamed;\\\n"); + + emulator.serial0_send("mv /mnt/fs1a/fs2a/link-renamed /mnt/link2;\\\n"); + emulator.serial0_send("echo jump to root >> /mnt/link2;\\\n"); + + emulator.serial0_send("{ mv /mnt/link2 /mnt/fs1b/link3 2>/dev/null || \n"); + emulator.serial0_send(" echo jump outside 1 - fails >> /mnt/link2; };\\\n"); + + emulator.serial0_send("mv /mnt/link2 /mnt/fs1a/link4;\\\n"); + emulator.serial0_send("echo jump back one level >> /mnt/fs1a/link4;\\\n"); + + emulator.serial0_send("mv /mnt/fs1a/link4 /mnt/link5;\\\n"); + emulator.serial0_send("echo jump to root >> /mnt/link5;\\\n"); + + emulator.serial0_send("{ mv /mnt/link5 /mnt/fs1a/fs2b/link6 2>/dev/null || \n"); + emulator.serial0_send(" echo jump outside 2 - fails >> /mnt/link5; };\\\n"); + + emulator.serial0_send("{ mv /mnt/link5 /mnt/fs1a/fs2a/fs3/link7 2>/dev/null || \n"); + emulator.serial0_send(" echo jump beyond - fails >> /mnt/link5; };\\\n"); + + emulator.serial0_send("mv /mnt/link5 /mnt/fs1a/fs2a/link8;\\\n"); + emulator.serial0_send("echo jump back two levels >> /mnt/fs1a/fs2a/link8;\\\n"); + + emulator.serial0_send("{ mv /mnt/fs1a/fs2a/link8 /mnt/fs1a/fs2a/fs3/link9 2>/dev/null || \n"); + emulator.serial0_send(" echo jump up - fails >> /mnt/fs1a/fs2a/link8; };\\\n"); + + emulator.serial0_send("cat /mnt/fs1a/fs2a/file;\\\n"); + emulator.serial0_send("echo done-hard-links-mounted\n"); + }, + capture_trigger: "start-capture", + end_trigger: "done-hard-links-mounted", + end: (capture, done) => + { + assert_equal(capture, + "foobar\n" + + "link at root fs\n" + + "link at child fs - fails\n" + + "link at common fs\n" + + "rename\n" + + "jump to root\n" + + "jump outside 1 - fails\n" + + "jump back one level\n" + + "jump to root\n" + + "jump outside 2 - fails\n" + + "jump beyond - fails\n" + + "jump back two levels\n" + + "jump up - fails\n"); + done(); + }, + }, { name: "Using '..' across filesystems", timeout: 60, From d1519d4509ce2a8f711a9cd2246fca1eb9198425 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 29 Aug 2018 21:45:50 +1200 Subject: [PATCH 1280/2137] Filesystem: hard links, replace linked lists with Map. Unfortunately, I didn't split this into multiple commits: - Keeping track of nlinks is now all done by link_under_dir and unlink_from_dir methods. - Inodes are no longer associated with a name. - Directory structure is now represented using a Map, so the directory inode fully owns the directory entries instead a linked list scattered across many inodes. - The parameter order for FS#Link and FS#link_under_dir has been modified to be consistent with 9p's: (dirid, fid, name) - Allowed the movement of hardlinked files between filesystems "vertically", as long as the target inode is reachable within the filesystem and subfilesystems without ever having to traverse to the parent filesystem. - The methods FS#copy_inode and FS#divert does not put the filesystem in an invalid state: FS#copy_inode does not modify inode.nlinks nor inode.direntries, and FS#divert makes sure to delete the original nlinks and direntries after it has been copied over to a new inode. - Added extra assertions in FS#link_under_dir and FS#unlink_from_dir - Forwarders should not be deleted upon unlink: the files are still accessible. - Non-root non-directory forwarders can now be linked under non-forwarder directories for extra freedom for hardlinks. Now, the rule for linking is: never link under a forwarder, and never link a directory more than once. Some tests and some 9p debug code is broken because they rely on inode.name which no longer exists nor makes sense to exist. Will fix in next commit. --- lib/9p.js | 17 +- lib/filesystem.js | 646 +++++++++++++++++++++++++--------------------- 2 files changed, 373 insertions(+), 290 deletions(-) diff --git a/lib/9p.js b/lib/9p.js index 588969c7..35cb79be 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -14,7 +14,6 @@ const VIRTIO_9P_MAX_TAGLEN = 254; // TODO // flush // lock? -// correct hard links var EPERM = 1; /* Operation not permitted */ var ENOENT = 2; /* No such file or directory */ @@ -292,7 +291,21 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { var name = req[2]; message.Debug("[link] dfid=" + dfid + ", name=" + name); - this.fs.Link(this.fids[fid].inodeid, name, this.fids[dfid].inodeid); + var ret = this.fs.Link(this.fids[dfid].inodeid, this.fids[fid].inodeid, name); + + if(ret < 0) + { + let error_message = ""; + if(ret === -EPERM) error_message = "Operation not permitted"; + else + { + error_message = "Unknown error: " + (-ret); + dbg_assert(false, "[link]: Unexpected error code: " + (-ret)); + } + this.SendError(tag, error_message, ENOTEMPTY); + this.SendReply(bufchain); + break; + } this.BuildReply(id, tag, 0); this.SendReply(bufchain); diff --git a/lib/filesystem.js b/lib/filesystem.js index bcbca10a..dd65c430 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -233,7 +233,7 @@ FS.prototype.LoadRecursive = function(data, parentid) { var inode = this.CreateInode(); - inode.name = data[JSONFS_IDX_NAME]; + const name = data[JSONFS_IDX_NAME]; inode.size = data[JSONFS_IDX_SIZE]; inode.mtime = data[JSONFS_IDX_MTIME]; inode.ctime = inode.mtime; @@ -242,27 +242,24 @@ FS.prototype.LoadRecursive = function(data, parentid) inode.uid = data[JSONFS_IDX_UID]; inode.gid = data[JSONFS_IDX_GID]; - inode.parentid = parentid; - - this.inodes[parentid].nlinks++; - var ifmt = inode.mode & S_IFMT; if(ifmt === S_IFDIR) { - inode.nlinks = 2; // . and .. - this.LoadDir(inode, data[JSONFS_IDX_TARGET]); + inode.updatedir = true; + this.PushInode(inode, parentid, name); + this.LoadDir(this.inodes.length - 1, data[JSONFS_IDX_TARGET]); } else if(ifmt === S_IFREG) { inode.status = STATUS_ON_SERVER; inode.sha256sum = data[JSONFS_IDX_SHA256]; - this.PushInode(inode); + this.PushInode(inode, parentid, name); } else if(ifmt === S_IFLNK) { inode.symlink = data[JSONFS_IDX_TARGET]; - this.PushInode(inode); + this.PushInode(inode, parentid, name); } else if(ifmt === S_IFSOCK) { @@ -270,19 +267,14 @@ FS.prototype.LoadRecursive = function(data, parentid) } else { - dbg_log("Unexpected ifmt: " + h(ifmt) + " (" + inode.name + ")"); + dbg_log("Unexpected ifmt: " + h(ifmt) + " (" + name + ")"); } }; -FS.prototype.LoadDir = function(inode, children) +FS.prototype.LoadDir = function(parentid, children) { - inode.updatedir = true; - - var p = this.inodes.length; - this.PushInode(inode); - for(var i = 0; i < children.length; i++) { - this.LoadRecursive(children[i], p); + this.LoadRecursive(children[i], parentid); } }; @@ -340,70 +332,120 @@ FS.prototype.LoadFile = function(idx) { // ----------------------------------------------------- /** - * Non-root forwarders are not linked locally, or else we need to synchronise with the - * corresponding mounted filesystems. * @private + * @param {Inode} directory * @return {boolean} */ -FS.prototype.should_be_linked = function(inode) +FS.prototype.directory_is_linkable = function(directory) { - return !this.is_forwarder(inode) || this.is_root_forwarder(inode); + // Note: Non-root forwarder inode could still have a non-forwarder parent, so don't use + // parent inode to check. + return !this.is_forwarder(directory) || directory.foreign_id === 0; }; /** * @private - * @param {number} idx * @param {number} parentid + * @param {number} idx + * @param {string} name */ -FS.prototype.link_under_dir = function(idx, parentid) +FS.prototype.link_under_dir = function(parentid, idx, name) { const inode = this.inodes[idx]; + const real_inode = this.GetInode(idx); const parent_inode = this.inodes[parentid]; - dbg_assert(!this.is_forwarder(parent_inode), "Filesystem: Shouldn't link non-root fowarders"); - inode.parentid = parentid; - inode.nextid = parent_inode.firstid; - parent_inode.firstid = idx; + + dbg_assert(!this.is_forwarder(parent_inode), + "Filesystem: Shouldn't link under fowarder parents"); + dbg_assert(this.IsDirectory(parentid), + "Filesystem: Can't link under non-directories"); + dbg_assert(real_inode.nlinks >= 0, + "Filesystem: Found negative nlinks value of " + real_inode.nlinks); + dbg_assert(!parent_inode.direntries.has(name), + "Filesystem: Name '" + name + "' is already taken"); + + parent_inode.direntries.set(name, idx); parent_inode.updatedir = true; + + // Never store link information on forwarder. + real_inode.nlinks++; + + if(this.IsDirectory(idx)) + { + // Safe assumption: + // We will never link a directory forwarder apart from the mountpoint. + // Directories cannot be hardlinked to two places, + // so the parent of any non-root directory forwarder must also be a forwarder parent, + // but forwarder parents are already asserted against. + dbg_assert(this.directory_is_linkable(inode), + "Filesystem: Cannot link non-root directory forwarder"); + dbg_assert(!inode.direntries.has(".."), + "Filesystem: Cannot link a directory twice"); + + if(!inode.direntries.has(".")) real_inode.nlinks++; + inode.direntries.set(".", idx); + inode.direntries.set("..", parentid); + parent_inode.nlinks++; + + inode.updatedir = true; + } }; /** * @private - * @param {number} idx + * @param {number} parentid + * @param {string} name */ -FS.prototype.unlink_from_dir = function(idx) +FS.prototype.unlink_from_dir = function(parentid, name) { + const idx = this.Search(parentid, name); const inode = this.inodes[idx]; - const parent_inode = this.inodes[inode.parentid]; - dbg_assert(!this.is_forwarder(parent_inode), "Filesystem: Can't unlink non-root fowarders"); - if(parent_inode.firstid === idx) - { - parent_inode.firstid = inode.nextid; - } - else - { - const id = this.FindPreviousID(idx); - dbg_assert(id !== -1, - "Filesystem: Could not find previous sibling of (" + this.GetInode(idx).name + - ") while unlinking from it's parent"); - this.inodes[id].nextid = inode.nextid; - } + const real_inode = this.GetInode(idx); + const parent_inode = this.inodes[parentid]; + + dbg_assert(!this.is_forwarder(parent_inode), "Filesystem: Can't unlink from fowarders"); + dbg_assert(this.IsDirectory(parentid), "Filesystem: Can't unlink from non-directories"); + + const exists = parent_inode.direntries.delete(name); + dbg_assert(exists, "Filesystem: Can't unlink non-existent file: " + name); + + // Never store link information on forwarder. + real_inode.nlinks--; + parent_inode.updatedir = true; + + if(this.IsDirectory(idx)) + { + dbg_assert(inode.direntries.get("..") === parentid, + "Filesystem: Found directory with bad parent id"); + + inode.direntries.delete(".."); + parent_inode.nlinks--; + + inode.updatedir = true; + } + + dbg_assert(real_inode.nlinks >= 0, + "Filesystem: Found negative nlinks value of " + real_inode.nlinks); }; -FS.prototype.PushInode = function(inode) { - if (inode.parentid != -1) { +FS.prototype.PushInode = function(inode, parentid, name) { + if (parentid != -1) { this.inodes.push(inode); inode.fid = this.inodes.length - 1; - this.link_under_dir(this.inodes.length - 1, inode.parentid); + this.link_under_dir(parentid, inode.fid, name); return; } else { if (this.inodes.length == 0) { // if root directory this.inodes.push(inode); + inode.direntries.set(".", 0); + inode.direntries.set("..", 0); + inode.nlinks = 2; return; } } - message.Debug("Error in Filesystem: Pushed inode with name = "+ inode.name + " has no parent"); + message.Debug("Error in Filesystem: Pushed inode with name = "+ name + " has no parent"); message.Abort(); }; @@ -412,11 +454,8 @@ FS.prototype.PushInode = function(inode) { function Inode(qidnumber) { this.updatedir = false; // did the directory listing changed? - this.parentid = -1; - this.firstid = -1; // first file id in directory - this.nextid = -1; // next id in directory + this.direntries = new Map(); // maps filename to inode id this.status = 0; - this.name = ""; this.size = 0x0; this.uid = 0x0; this.gid = 0x0; @@ -434,7 +473,7 @@ function Inode(qidnumber) path: qidnumber, }; this.caps = undefined; - this.nlinks = 1; + this.nlinks = 0; this.dirty = false; // has this file changed? this.sha256sum = ""; @@ -451,11 +490,11 @@ Inode.prototype.get_state = function() { const state = []; state[0] = this.updatedir; - state[1] = this.parentid; - state[2] = this.firstid; - state[3] = this.nextid; + state[1] = [...this.direntries]; + //state[2] + //state[3] state[4] = this.status; - state[5] = this.name; + //state[5] state[6] = this.size; state[7] = this.uid; state[8] = this.gid; @@ -482,11 +521,11 @@ Inode.prototype.get_state = function() Inode.prototype.set_state = function(state) { this.updatedir = state[0]; - this.parentid = state[1]; - this.firstid = state[2]; - this.nextid = state[3]; + this.direntries = new Map(state[1]); + //state[2]; + //state[3]; this.status = state[4]; - this.name = state[5]; + //state[5]; this.size = state[6]; this.uid = state[7]; this.gid = state[8]; @@ -513,17 +552,21 @@ Inode.prototype.set_state = function(state) * Clones given inode to new idx, effectively diverting the inode to new idx value. * Hence, original idx value is now free to use without losing the original information. * @private - * @param {number} old_idx Target to divert. + * @param {number} parentid Parent of target to divert. + * @param {string} filename Name of target to divert. * @return {number} New idx of diversion. */ -FS.prototype.divert = function(old_idx) +FS.prototype.divert = function(parentid, filename) { - dbg_assert(old_idx !== 0, "Filesystem: can't divert root inode"); - dbg_assert(old_idx > 0, "Filesystem: invalid inode idx: " + old_idx); - + const old_idx = this.Search(parentid, filename); const old_inode = this.inodes[old_idx]; const new_inode = new Inode(-1); + dbg_assert(old_inode, "Filesystem divert: name (" + filename + ") not found"); + dbg_assert(this.IsDirectory(old_idx) || this.GetInode(old_idx).nlinks <= 1, + "Filesystem: can't divert hardlinked file '" + filename + "' with nlinks=" + + this.GetInode(old_idx).nlinks); + // Shallow copy is alright. Object.assign(new_inode, old_inode); @@ -536,20 +579,22 @@ FS.prototype.divert = function(old_idx) { this.mounts[old_inode.mount_id].backtrack.set(old_inode.foreign_id, idx); } - if(this.should_be_linked(old_inode)) + if(!this.is_forwarder(this.inodes[parentid])) { - this.unlink_from_dir(old_idx); - this.link_under_dir(idx, old_inode.parentid); + this.unlink_from_dir(parentid, filename); + this.link_under_dir(parentid, idx, filename); } // Update children if(this.IsDirectory(old_idx) && !this.is_forwarder(old_inode)) { - let child_id = this.inodes[idx].firstid; - while(child_id !== -1) + for(const [name, child_id] of new_inode.direntries) { - this.inodes[child_id].parentid = idx; - child_id = this.inodes[child_id].nextid; + if(name === "." || name === "..") continue; + if(this.IsDirectory(child_id)) + { + this.inodes[child_id].direntries.set("..", idx); + } } } @@ -557,9 +602,29 @@ FS.prototype.divert = function(old_idx) this.inodedata[idx] = this.inodedata[old_idx]; delete this.inodedata[old_idx]; + // Retire old reference information. + old_inode.direntries = new Map(); + old_inode.nlinks = 0; + return idx; }; +/** + * Copy all non-redundant info. + * References left untouched: local idx value and links + * @private + * @param {!Inode} src_inode + * @param {!Inode} dest_inode + */ +FS.prototype.copy_inode = function(src_inode, dest_inode) +{ + Object.assign(dest_inode, src_inode, { + fid: dest_inode.fid, + direntries: dest_inode.direntries, + nlinks: dest_inode.nlinks, + }); +}; + FS.prototype.CreateInode = function() { //console.log("CreateInode", Error().stack); const now = Math.round(Date.now() / 1000); @@ -579,19 +644,15 @@ FS.prototype.CreateDirectory = function(name, parentid) { return this.create_forwarder(parent_inode.mount_id, foreign_id); } var x = this.CreateInode(); - x.name = name; - x.parentid = parentid; x.mode = 0x01FF | S_IFDIR; x.updatedir = true; - x.nlinks = 2; // . and .. if (parentid >= 0) { x.uid = this.inodes[parentid].uid; x.gid = this.inodes[parentid].gid; x.mode = (this.inodes[parentid].mode & 0x1FF) | S_IFDIR; - this.inodes[parentid].nlinks++; } x.qid.type = S_IFDIR >> 8; - this.PushInode(x); + this.PushInode(x, parentid, name); this.NotifyListeners(this.inodes.length-1, 'newdir'); return this.inodes.length-1; }; @@ -606,14 +667,11 @@ FS.prototype.CreateFile = function(filename, parentid) { } var x = this.CreateInode(); x.dirty = true; - x.name = filename; - x.parentid = parentid; x.uid = this.inodes[parentid].uid; x.gid = this.inodes[parentid].gid; - this.inodes[parentid].nlinks++; x.qid.type = S_IFREG >> 8; x.mode = (this.inodes[parentid].mode & 0x1B6) | S_IFREG; - this.PushInode(x); + this.PushInode(x, parentid, filename); this.NotifyListeners(this.inodes.length-1, 'newfile'); return this.inodes.length-1; }; @@ -629,16 +687,13 @@ FS.prototype.CreateNode = function(filename, parentid, major, minor) { return this.create_forwarder(parent_inode.mount_id, foreign_id); } var x = this.CreateInode(); - x.name = filename; - x.parentid = parentid; x.major = major; x.minor = minor; x.uid = this.inodes[parentid].uid; x.gid = this.inodes[parentid].gid; - this.inodes[parentid].nlinks++; x.qid.type = S_IFSOCK >> 8; x.mode = (this.inodes[parentid].mode & 0x1B6); - this.PushInode(x); + this.PushInode(x, parentid, filename); return this.inodes.length-1; }; @@ -652,15 +707,12 @@ FS.prototype.CreateSymlink = function(filename, parentid, symlink) { return this.create_forwarder(parent_inode.mount_id, foreign_id); } var x = this.CreateInode(); - x.name = filename; - x.parentid = parentid; x.uid = this.inodes[parentid].uid; x.gid = this.inodes[parentid].gid; - this.inodes[parentid].nlinks++; x.qid.type = S_IFLNK >> 8; x.symlink = symlink; x.mode = S_IFLNK; - this.PushInode(x); + this.PushInode(x, parentid, filename); return this.inodes.length-1; }; @@ -760,11 +812,13 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { { return -ENOENT; } - var oldpath = this.GetFullPath(oldid); + + // For event notification near end of method. + var oldpath = this.GetFullPath(olddirid) + "/oldname"; var newid = this.Search(newdirid, newname); if (newid != -1) { - const ret = this.Unlink(newid); + const ret = this.Unlink(newdirid, newname); if(ret < 0) return ret; } @@ -777,14 +831,10 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { { // Move inode within current filesystem. - this.unlink_from_dir(idx); - this.link_under_dir(idx, newdirid); + this.unlink_from_dir(olddirid, oldname); + this.link_under_dir(newdirid, idx, newname); - inode.name = newname; inode.qid.version++; - - this.inodes[olddirid].nlinks--; - this.inodes[newdirid].nlinks++; } else if(this.is_forwarder(olddir) && olddir.mount_id === newdir.mount_id) { @@ -795,20 +845,43 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { if(ret < 0) return ret; } - else if(this.GetInode(idx).parentid === -1) + else if(this.GetInode(idx).fid === 0) { // The actual inode is a root of some descendant filesystem. // Moving mountpoint across fs not supported - needs to update all corresponding forwarders. dbg_log("XXX: Attempted to move mountpoint (" + oldname + ") - skipped", LOG_9P); return -EPERM; } + else if(!this.IsDirectory(idx) && this.GetInode(idx).nlinks > 1) + { + // Move hardlinked inode vertically in mount tree. + + if(!this.is_forwarder(inode)) + { + dbg_log("XXX: Attempted to move hardlinked file (" + oldname + ") " + + "to a child filesystem - skipped", LOG_9P); + return -EPERM; + } + if(this.is_forwarder(newdir) && newdir.mount_id !== inode.mount_id) + { + dbg_log("XXX: Attempted to move hardlinked file (" + oldname + ") " + + "to a sibling filesystem - skipped", LOG_9P); + return -EPERM; + } + + const link_ret = this.Link(newdirid, idx, newname); + if(link_ret < 0) return link_ret; + + const unlink_ret = this.Unlink(olddirid, oldname); + if(unlink_ret < 0) return unlink_ret; + } else { // Jump between filesystems. // Can't work with both old and new inode information without first diverting the old // information into a new idx value. - const diverted_old_idx = this.divert(idx); + const diverted_old_idx = this.divert(olddirid, oldname); const old_real_inode = this.GetInode(idx); const data = this.Read(diverted_old_idx, 0, old_real_inode.size); @@ -817,18 +890,12 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { { // Create new inode. const foreign_fs = this.follow_fs(newdir); - const foreign_id = foreign_fs.CreateFile(newname, newdir.foreign_id); - const new_real_inode = foreign_fs.GetInode(foreign_id); + const foreign_id = this.IsDirectory(diverted_old_idx) ? + foreign_fs.CreateDirectory(newname, newdir.foreign_id) : + foreign_fs.CreateFile(newname, newdir.foreign_id); - // Copy over inode info. Reassign info we want to keep. - Object.assign(new_real_inode, old_real_inode, - { - fid: new_real_inode.fid, - parentid: new_real_inode.parentid, - nextid: new_real_inode.nextid, - firstid: -1, - name: newname, - }); + const new_real_inode = foreign_fs.GetInode(foreign_id); + this.copy_inode(old_real_inode, new_real_inode); // Point to this new location. this.set_forwarder(idx, newdir.mount_id, foreign_id); @@ -837,12 +904,10 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { { // Replace current forwarder with real inode. this.delete_forwarder(inode); - Object.assign(inode, old_real_inode); + this.copy_inode(old_real_inode, inode); // Link into new location in this filesystem. - inode.name = newname; - inode.firstid = -1; - this.link_under_dir(idx, newdirid); + this.link_under_dir(newdirid, idx, newname); } // Rewrite data to newly created destination. @@ -864,7 +929,7 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { // Perform destructive changes only after migration succeeded. this.DeleteData(diverted_old_idx); - const ret = this.Unlink(diverted_old_idx); + const ret = this.Unlink(olddirid, oldname); if(ret < 0) return ret; } @@ -930,15 +995,8 @@ FS.prototype.Search = function(parentid, name) { return this.get_forwarder(parent_inode.mount_id, foreign_id); } - var id = parent_inode.firstid; - while(id != -1) { - dbg_assert(this.GetParent(id) === parentid, - "Error in Filesystem: Found inode (" + this.inodes[id].name + ") with wrong parent id. " + - "Expected: " + parentid + ", Actual: " + this.GetParent(id)); - if (this.inodes[id].name == name) return id; - id = this.inodes[id].nextid; - } - return -1; + const childid = parent_inode.direntries.get(name); + return childid === undefined ? -1 : childid; }; FS.prototype.CountUsedInodes = function() @@ -988,94 +1046,108 @@ FS.prototype.GetSpace = function() { return this.total_size; }; +/** + * XXX: Not ideal. + * @param {number} idx + * @return {string} + */ +FS.prototype.GetDirectoryName = function(idx) +{ + const parent_inode = this.inodes[this.GetParent(idx)]; + + if(this.is_forwarder(parent_inode)) + { + return this.follow_fs(parent_inode).GetDirectoryName(this.inodes[idx].foreign_id); + } + + // Root directory. + if(!parent_inode) return ""; + + for(const [name, childid] of parent_inode.direntries) + { + if(childid === idx) return name; + } + + dbg_assert(false, "Filesystem: Found directory inode whose parent doesn't link to it"); + return ""; +}; + FS.prototype.GetFullPath = function(idx) { + dbg_assert(this.IsDirectory(idx), "Filesystem: Cannot get full path of non-directory inode"); + var path = ""; while(idx != 0) { - path = "/" + this.GetInode(idx).name + path; + path = "/" + this.GetDirectoryName(idx) + path; idx = this.GetParent(idx); } return path.substring(1); }; -// no double linked list. So, we need this -FS.prototype.FindPreviousID = function(idx) { - var inode = this.inodes[idx]; - dbg_assert(this.should_be_linked(inode), "Filesystem FindPreviousID assumes linked inode"); - var id = this.inodes[inode.parentid].firstid; - while(id != -1) { - if (this.inodes[id].nextid == idx) return id; - id = this.inodes[id].nextid; - } - return id; -}; - -// XXX: just copying -FS.prototype.Link = function(targetid, name, parentid) +/** + * @param {number} parentid + * @param {number} targetid + * @param {string} name + * @return {number} 0 if success, or -errno if failured. + */ +FS.prototype.Link = function(parentid, targetid, name) { - var inode = this.CreateInode(); - var inodetarget = this.GetInode(targetid); - const targetdata = this.Read(targetid, 0, inodetarget.size); - //inode = inodetarget; - inode.dirty = true; - inode.mode = inodetarget.mode; - inode.size = inodetarget.size; - inode.symlink = inodetarget.symlink; + if(this.IsDirectory(targetid)) + { + return -EPERM; + } - var data = this.inodedata[this.inodes.length] = new Uint8Array(inode.size); - if(targetdata) + const parent_inode = this.inodes[parentid]; + if(this.is_forwarder(parent_inode)) { - data.set(targetdata, 0); + const inode = this.inodes[targetid]; + if(!this.is_forwarder(inode) || inode.mount_id !== parent_inode.mount_id) + { + dbg_log("XXX: Attempted to hardlink a file into a child filesystem - skipped", LOG_9P); + return -EPERM; + } + return this.follow_fs(parent_inode).Link(parent_inode.foreign_id, inode.foreign_id, name); } - inode.name = name; - if(this.is_forwarder(this.inodes[parentid])) - { - inode.parentid = 0; - const newid = this.inodes.length; - this.PushInode(inode); - this.Rename(0, name, parentid, name); - } - else - { - inode.parentid = parentid; - this.PushInode(inode); - } - //inode.uid = inodetarget.uid; - //inode.gid = inodetarget.gid; - //inode.mode = inodetarget.mode | S_IFLNK; + this.link_under_dir(parentid, targetid, name); + return 0; }; -FS.prototype.Unlink = function(idx) { - this.NotifyListeners(idx, 'delete'); - if (idx == 0) return -EPERM; // root node cannot be deleted - var inode = this.inodes[idx]; - const parent_inode = this.inodes[this.GetParent(idx)]; +FS.prototype.Unlink = function(parentid, name) { + if(name === "." || name === "..") + { + // Also guarantees that root cannot be deleted. + return -EPERM; + } + const idx = this.Search(parentid, name); + const inode = this.inodes[idx]; + const parent_inode = this.inodes[parentid]; //message.Debug("Unlink " + inode.name); // forward if necessary - if(!this.should_be_linked(inode)) + if(this.is_forwarder(parent_inode)) { - const foreign_id = inode.foreign_id; - const ret = this.follow_fs(inode).Unlink(foreign_id); - if(ret === 0) this.delete_forwarder(inode); - return ret; + dbg_assert(this.is_forwarder(inode), "Children of forwarders should be forwarders"); + + const foreign_parentid = parent_inode.foreign_id; + return this.follow_fs(parent_inode).Unlink(foreign_parentid, name); + + // Keep the forwarder dangling - file is still accessible. } - // check if directory is not empty - if ((inode.mode&S_IFMT) == S_IFDIR) { - if (inode.firstid != -1) return -ENOTEMPTY; + if(this.IsDirectory(idx) && !this.IsEmpty(idx)) + { + return -ENOTEMPTY; } - this.unlink_from_dir(idx); + this.unlink_from_dir(parentid, name); - // don't delete the content. The file is still accessible - parent_inode.nlinks--; - inode.status = STATUS_UNLINKED; - inode.nextid = -1; - inode.firstid = -1; - inode.parentid = -1; - inode.nlinks--; + if(this.GetInode(idx).nlinks === 0) + { + // don't delete the content. The file is still accessible + inode.status = STATUS_UNLINKED; + this.NotifyListeners(idx, 'delete'); + } return 0; }; @@ -1091,6 +1163,10 @@ FS.prototype.DeleteData = function(idx) delete this.inodedata[idx]; }; +/** + * @param {number} idx + * @return {!Inode} + */ FS.prototype.GetInode = function(idx) { dbg_assert(!isNaN(idx), "Filesystem GetInode: NaN idx"); @@ -1146,26 +1222,35 @@ FS.prototype.SearchPath = function(path) { }; // ----------------------------------------------------- +/** + * @param {number} dirid + * @param {Array<{parentid: number, name: string}>} list + */ FS.prototype.GetRecursiveList = function(dirid, list) { if(this.is_forwarder(this.inodes[dirid])) { const foreign_fs = this.follow_fs(this.inodes[dirid]); const foreign_dirid = this.inodes[dirid].foreign_id; - const foreign_list = []; - foreign_fs.GetRecursiveList(foreign_dirid, foreign_list); - for(const foreign_id of foreign_list) + const mount_id = this.inodes[dirid].mount_id; + + const foreign_start = list.length; + foreign_fs.GetRecursiveList(foreign_dirid, list); + for(let i = foreign_start; i < list.length; i++) { - list.push(this.get_forwarder(this.inodes[dirid].mount_id, foreign_id)); + list[i].parentid = this.get_forwarder(mount_id, list[i].parentid); } return; } - var id = this.inodes[dirid].firstid; - while(id != -1) { - list.push(id); - if ((this.inodes[id].mode&S_IFMT) == S_IFDIR) { - this.GetRecursiveList(id, list); + for(const [name, id] of this.inodes[dirid].direntries) + { + if(name !== "." && name !== "..") + { + list.push({ parentid: dirid, name }); + if(this.IsDirectory(id)) + { + this.GetRecursiveList(id, list); + } } - id = this.inodes[id].nextid; } }; @@ -1178,11 +1263,10 @@ FS.prototype.RecursiveDelete = function(path) { for(var i=toDelete.length-1; i>=0; i--) { - const ret = this.Unlink(toDelete[i]); - dbg_assert(ret === 0, "Filesystem RecursiveDelete failed at inode=" + toDelete[i] + - " with error code: " + (-ret)); + const ret = this.Unlink(toDelete[i].parentid, toDelete[i].name); + dbg_assert(ret === 0, "Filesystem RecursiveDelete failed at parent=" + toDelete[i].parentid + + ", name='" + toDelete[i].name + "' with error code: " + (-ret)); } - }; FS.prototype.DeleteNode = function(path) { @@ -1190,13 +1274,13 @@ FS.prototype.DeleteNode = function(path) { if (ids.id == -1) return; if ((this.inodes[ids.id].mode&S_IFMT) == S_IFREG){ - const ret = this.Unlink(ids.id); + const ret = this.Unlink(ids.parentid, ids.name); dbg_assert(ret === 0, "Filesystem DeleteNode failed with error code: " + (-ret)); return; } if ((this.inodes[ids.id].mode&S_IFMT) == S_IFDIR){ this.RecursiveDelete(path); - const ret = this.Unlink(ids.id); + const ret = this.Unlink(ids.parentid, ids.name); dbg_assert(ret === 0, "Filesystem DeleteNode failed with error code: " + (-ret)); return; } @@ -1225,24 +1309,29 @@ FS.prototype.Check = function() { for(var i=1; i> 12, - "."], - data, offset); - - offset += marshall.Marshall( - ["Q", "d", "b", "s"], - [this.inodes[parentid].qid, - offset+13+8+1+2+2, - this.inodes[parentid].mode >> 12, - ".."], - data, offset); - - id = this.inodes[dirid].firstid; - while(id != -1) { + let offset = 0x0; + for(const [name, id] of inode.direntries) + { + const child = this.GetInode(id); offset += marshall.Marshall( - ["Q", "d", "b", "s"], - [this.inodes[id].qid, - offset+13+8+1+2+UTF8.UTF8Length(this.inodes[id].name), - this.inodes[id].mode >> 12, - this.inodes[id].name], - data, offset); - id = this.inodes[id].nextid; + ["Q", "d", "b", "s"], + [child.qid, + offset+13+8+1+2+UTF8.UTF8Length(name), + child.mode >> 12, + name], + data, offset); } - inode.updatedir = false; }; FS.prototype.RoundToDirentry = function(dirid, offset_target) @@ -1344,28 +1409,44 @@ FS.prototype.IsDirectory = function(idx) return (inode.mode & S_IFMT) === S_IFDIR; }; +/** + * @param {number} idx + * @return {boolean} + */ +FS.prototype.IsEmpty = function(idx) +{ + const inode = this.inodes[idx]; + if(this.is_forwarder(inode)) + { + return this.follow_fs(inode).IsDirectory(inode.foreign_id); + } + for(const name of inode.direntries.keys()) + { + if(name !== "." && name !== "..") return false; + } + return true; +}; + /** * @param {number} idx * @return {!Array} List of children names */ FS.prototype.GetChildren = function(idx) { + dbg_assert(this.IsDirectory(idx), "Filesystem: cannot get children of non-directory inode"); const inode = this.inodes[idx]; - const children = []; - if(this.is_forwarder(inode)) { return this.follow_fs(inode).GetChildren(inode.foreign_id); } - - let child_id = this.inodes[idx].firstid; - - while(child_id !== -1) + const children = []; + for(const name of inode.direntries.keys()) { - children.push(this.inodes[child_id].name); - child_id = this.inodes[child_id].nextid; + if(name !== "." && name !== "..") + { + children.push(name); + } } - return children; }; @@ -1375,19 +1456,18 @@ FS.prototype.GetChildren = function(idx) */ FS.prototype.GetParent = function(idx) { + dbg_assert(this.IsDirectory(idx), "Filesystem: cannot get parent of non-directory inode"); + const inode = this.inodes[idx]; - if(this.should_be_linked(inode)) + if(this.directory_is_linkable(inode)) { - return inode.parentid; + return inode.direntries.get(".."); } else { const foreign_dirid = this.follow_fs(inode).GetParent(inode.foreign_id); - if(foreign_dirid === -1) - { - return -1; - } + dbg_assert(foreign_dirid !== -1, "Filesystem: should not have invalid parent ids"); return this.get_forwarder(inode.mount_id, foreign_dirid); } }; @@ -1489,6 +1569,9 @@ FS.prototype.set_forwarder = function(idx, mount_id, foreign_id) { const inode = this.inodes[idx]; + dbg_assert(inode.nlinks === 0, + "Filesystem: attempted to convert an inode into forwarder before unlinking the inode"); + if(this.is_forwarder(inode)) { this.mounts[inode.mount_id].backtrack.delete(inode.foreign_id); @@ -1529,18 +1612,6 @@ FS.prototype.is_forwarder = function(inode) return inode.status === STATUS_FORWARDING; }; -/** - * @private - * @param {Inode} inode - * @return {boolean} - */ -FS.prototype.is_root_forwarder = function(inode) -{ - // Note: Non-root forwarder inode could still have a non-forwarder parent, so don't use - // parent inode to check. - return this.is_forwarder(inode) && inode.foreign_id === 0; -}; - /** * Ensures forwarder exists, and returns such forwarder, for the described foreign inode. * @private @@ -1589,8 +1660,8 @@ FS.prototype.follow_fs = function(inode) dbg_assert(this.is_forwarder(inode), "Filesystem follow_fs: inode should be a forwarding inode"); - dbg_assert(mount, "Filesystem follow_fs: inode should point to valid mounted FS"); + dbg_assert(mount, "Filesystem follow_fs: inode should point to valid mounted FS"); return mount.fs; }; @@ -1630,8 +1701,7 @@ FS.prototype.Mount = function(path, fs) this.mounts.push(new FSMountInfo(fs)); const idx = this.create_forwarder(mount_id, 0); - this.inodes[idx].name = path_infos.name; - this.link_under_dir(idx, path_infos.parentid); + this.link_under_dir(path_infos.parentid, idx, path_infos.name); return idx; }; From 00b9ad683a12b55642bcf3accd21fc19e291334a Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 29 Aug 2018 21:46:51 +1200 Subject: [PATCH 1281/2137] Filesystem tests: don't rely on inode.name --- tests/devices/virtio_9p.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index f0372f88..fdd52e61 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -88,7 +88,7 @@ const tests = const notfound3 = emulator.fs9p.SearchPath("a/d"); assert_equal(notfound3.id, -1, "notfound3 a/d id"); - assert_equal(emulator.fs9p.GetInode(notfound3.parentid).name, "a", "notfound3 a/d parent name"); + assert_not_equal(notfound3.parentid, -1, "notfound3 a/d parent id"); const idx_a = notfound3.parentid; const notfound4 = emulator.fs9p.SearchPath("a/d/e"); @@ -100,17 +100,17 @@ const tests = assert_equal(dir1.parentid, 0, "dir1 a parentid"); const dir2 = emulator.fs9p.SearchPath("a/b/c"); - assert_equal(emulator.fs9p.GetInode(dir2.id).name, "c", "dir2 a/b/c name"); - assert_equal(emulator.fs9p.GetInode(dir2.parentid).name, "b", "dir2 a/b/c parent name"); + assert_not_equal(dir2.id, -1, "dir2 a/b/c id"); + assert_not_equal(dir2.parentid, -1, "dir2 a/b/c parentid"); const idx_b = dir2.parentid; const idx_c = dir2.id; const file1 = emulator.fs9p.SearchPath("a/b/c/file1"); - assert_equal(emulator.fs9p.GetInode(file1.id).name, "file1", "file1 a/b/c/file1 name"); + assert_not_equal(file1.id, -1, "file1 a/b/c/file1 id"); assert_equal(file1.parentid, idx_c, "file1 a/b/c/file1 parentid"); const file2 = emulator.fs9p.SearchPath("file2"); - assert_equal(emulator.fs9p.GetInode(file2.id).name, "file2", "file2 name"); + assert_not_equal(file2.id, -1, "file2 id"); assert_equal(file2.parentid, 0, "file2 parentid"); const fwdpath1 = emulator.fs9p.SearchPath("x/fs2"); From 5b456b64cb6ac4079a2597d81d509d5ca72be029 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 29 Aug 2018 21:52:10 +1200 Subject: [PATCH 1282/2137] 9p: don't rely on inode.name for debug messages --- lib/9p.js | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/lib/9p.js b/lib/9p.js index 35cb79be..fea48ac3 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -192,8 +192,9 @@ Virtio9p.prototype.set_state = function(state) this.fs = state[9]; }; -Virtio9p.prototype.Createfid = function(inode, type, uid) { - return {inodeid: inode, type: type, uid: uid}; +// Note: dbg_name may not be the up-to-date filename, and is only used for debug messages. +Virtio9p.prototype.Createfid = function(inodeid, type, uid, dbg_name) { + return {inodeid, type, uid, dbg_name}; }; Virtio9p.prototype.Reset = function() { @@ -267,13 +268,13 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { message.Debug("[open] fid=" + fid + ", mode=" + mode); var idx = this.fids[fid].inodeid; var inode = this.fs.GetInode(idx); - message.Debug("file open " + inode.name); + message.Debug("file open " + this.fids[fid].dbg_name); //if (inode.status == STATUS_LOADING) return; var ret = this.fs.OpenInode(idx, mode); this.fs.AddEvent(this.fids[fid].inodeid, function() { - message.Debug("file opened " + inode.name + " tag:"+tag); + message.Debug("file opened " + this.fids[fid].dbg_name + " tag:"+tag); var req = []; req[0] = inode.qid; req[1] = this.msize - 24; @@ -411,7 +412,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { var req = marshall.Unmarshall(["w", "d"], buffer, state); var fid = req[0]; var inode = this.fs.GetInode(this.fids[fid].inodeid); - message.Debug("[getattr]: fid=" + fid + " name=" + inode.name + " request mask=" + req[1]); + message.Debug("[getattr]: fid=" + fid + " name=" + this.fids[fid].dbg_name + " request mask=" + req[1]); if(!inode || inode.status === STATUS_UNLINKED) { message.Debug("getattr: unlinked"); @@ -469,7 +470,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { ], buffer, state); var fid = req[0]; var inode = this.fs.GetInode(this.fids[fid].inodeid); - message.Debug("[setattr]: fid=" + fid + " request mask=" + req[1] + " name=" +inode.name); + message.Debug("[setattr]: fid=" + fid + " request mask=" + req[1] + " name=" + this.fids[fid].dbg_name); if (req[1] & P9_SETATTR_MODE) { inode.mode = req[2]; } @@ -516,7 +517,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { var count = req[2]; var inode = this.fs.GetInode(this.fids[fid].inodeid); if (id == 40) message.Debug("[treaddir]: fid=" + fid + " offset=" + offset + " count=" + count); - if (id == 116) message.Debug("[read]: fid=" + fid + " (" + inode.name + ") offset=" + offset + " count=" + count + " fidtype=" + this.fids[fid].type); + if (id == 116) message.Debug("[read]: fid=" + fid + " (" + this.fids[fid].dbg_name + ") offset=" + offset + " count=" + count + " fidtype=" + this.fids[fid].type); if(!inode || inode.status === STATUS_UNLINKED) { message.Debug("read/treaddir: unlinked"); @@ -537,7 +538,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { this.fs.OpenInode(this.fids[fid].inodeid, undefined); this.fs.AddEvent(this.fids[fid].inodeid, function() { - this.bus.send("9p-read-end", [inode.name, count]); + this.bus.send("9p-read-end", [this.fids[fid].dbg_name, count]); const inodeid = this.fids[fid].inodeid; @@ -571,7 +572,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { var offset = req[1]; var count = req[2]; - const filename = this.fs.GetInode(this.fids[fid].inodeid).name; + const filename = this.fids[fid].dbg_name; message.Debug("[write]: fid=" + fid + " (" + filename + ") offset=" + offset + " count=" + count + " fidtype=" + this.fids[fid].type); if(this.fids[fid].type === FID_XATTR) { @@ -631,7 +632,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { this.SendReply(bufchain); break; } - var ret = this.fs.Unlink(fid); + var ret = this.fs.Unlink(this.fids[dirfd].inodeid, name); if (ret < 0) { let error_message = ""; if(ret === -ENOTEMPTY) error_message = "Directory not empty"; @@ -664,7 +665,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { var fid = req[0]; var uid = req[4]; message.Debug("[attach]: fid=" + fid + " afid=" + hex8(req[1]) + " uname=" + req[2] + " aname=" + req[3]); - this.fids[fid] = this.Createfid(0, FID_INODE, uid); + this.fids[fid] = this.Createfid(0, FID_INODE, uid, ""); var inode = this.fs.GetInode(this.fids[fid].inodeid); marshall.Marshall(["Q"], [inode.qid], this.replybuffer, 7); this.BuildReply(id, tag, 13); @@ -688,7 +689,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { var nwname = req[2]; message.Debug("[walk]: fid=" + req[0] + " nwfid=" + req[1] + " nwname=" + nwname); if (nwname == 0) { - this.fids[nwfid] = this.Createfid(this.fids[fid].inodeid, FID_INODE, this.fids[fid].uid); + this.fids[nwfid] = this.Createfid(this.fids[fid].inodeid, FID_INODE, this.fids[fid].uid, this.fids[fid].dbg_name); //this.fids[nwfid].inodeid = this.fids[fid].inodeid; marshall.Marshall(["h"], [0], this.replybuffer, 7); this.BuildReply(id, tag, 2); @@ -704,7 +705,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { var offset = 7+2; var nwidx = 0; //console.log(idx, this.fs.GetInode(idx)); - message.Debug("walk in dir " + this.fs.GetInode(idx).name + " to: " + walk.toString()); + message.Debug("walk in dir " + this.fids[fid].dbg_name + " to: " + walk.toString()); for(var i=0; i Date: Fri, 31 Aug 2018 15:21:54 +1200 Subject: [PATCH 1285/2137] Filesystem: fix nlinks counting for mountpoints --- lib/filesystem.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index a4d1b13d..8e0f3a7d 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -358,8 +358,12 @@ FS.prototype.link_under_dir = function(parentid, idx, name) parent_inode.direntries.set(name, idx); parent_inode.updatedir = true; - // Never store link information on forwarder. - real_inode.nlinks++; + // Root inode of other filesystems are already linked to themselves. + if(real_inode.fid !== 0) + { + // Never store link information on forwarder. + real_inode.nlinks++; + } if(this.IsDirectory(idx)) { @@ -373,8 +377,9 @@ FS.prototype.link_under_dir = function(parentid, idx, name) dbg_assert(!inode.direntries.has(".."), "Filesystem: Cannot link a directory twice"); - if(!inode.direntries.has(".")) real_inode.nlinks++; + if(!real_inode.direntries.has(".")) real_inode.nlinks++; inode.direntries.set(".", idx); + inode.direntries.set("..", parentid); parent_inode.nlinks++; @@ -400,8 +405,12 @@ FS.prototype.unlink_from_dir = function(parentid, name) const exists = parent_inode.direntries.delete(name); dbg_assert(exists, "Filesystem: Can't unlink non-existent file: " + name); - // Never store link information on forwarder. - real_inode.nlinks--; + // Root inode of other filesystems are still linked to themselves. + if(real_inode.fid !== 0) + { + // Never store link information on forwarder. + real_inode.nlinks--; + } parent_inode.updatedir = true; From 25603948557e07cc367670cd99e91a58ae7117c7 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Fri, 31 Aug 2018 15:59:11 +1200 Subject: [PATCH 1286/2137] Filesystem: set unlinked status on the real inode The real_inode's status is supposedly set to STATUS_UNLINKED when there are no more references to the inode from other directories. Previously, this status was incorrectly applied to the forwarder and not the actual real_inode. --- lib/filesystem.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 8e0f3a7d..a5ce3695 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -1122,6 +1122,7 @@ FS.prototype.Unlink = function(parentid, name) { const idx = this.Search(parentid, name); const inode = this.inodes[idx]; const parent_inode = this.inodes[parentid]; + const real_inode = this.GetInode(idx); //message.Debug("Unlink " + inode.name); // forward if necessary @@ -1142,10 +1143,10 @@ FS.prototype.Unlink = function(parentid, name) { this.unlink_from_dir(parentid, name); - if(this.GetInode(idx).nlinks === 0) + if(real_inode.nlinks === 0) { // don't delete the content. The file is still accessible - inode.status = STATUS_UNLINKED; + real_inode.status = STATUS_UNLINKED; this.NotifyListeners(idx, 'delete'); } return 0; From 0d885e5e8c9e9dea4be0330962e47adf515f2094 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 1 Sep 2018 21:20:52 +1200 Subject: [PATCH 1287/2137] 9p: put dbg_name into state and document its limitations --- lib/9p.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/9p.js b/lib/9p.js index eaa8d747..51a345bd 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -168,7 +168,7 @@ Virtio9p.prototype.get_state = function() state[5] = this.msize; state[6] = this.replybuffer; state[7] = this.replybuffersize; - state[8] = this.fids.map(function(f) { return [f.inodeid, f.type, f.uid]; }); + state[8] = this.fids.map(function(f) { return [f.inodeid, f.type, f.uid, f.dbg_name]; }); state[9] = this.fs; return state; @@ -187,12 +187,14 @@ Virtio9p.prototype.set_state = function(state) this.replybuffersize = state[7]; this.fids = state[8].map(function(f) { - return { inodeid: f[0], type: f[1], uid: f[2] }; + return { inodeid: f[0], type: f[1], uid: f[2], dbg_name: f[3] }; }); this.fs = state[9]; }; -// Note: dbg_name may not be the up-to-date filename, and is only used for debug messages. +// Note: dbg_name is only used for debugging messages and may not be the same as the filename, +// since it is not synchronised with renames done outside of 9p. Hard-links, linking and unlinking +// operations also mean that having a single filename no longer makes sense. Virtio9p.prototype.Createfid = function(inodeid, type, uid, dbg_name) { return {inodeid, type, uid, dbg_name}; }; From 1a7dc59f07767966c162f37188b9869aba41c8e1 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 1 Sep 2018 21:28:26 +1200 Subject: [PATCH 1288/2137] 9p: Track filename during RENAMEAT --- lib/9p.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/9p.js b/lib/9p.js index 51a345bd..fe0f12df 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -199,6 +199,14 @@ Virtio9p.prototype.Createfid = function(inodeid, type, uid, dbg_name) { return {inodeid, type, uid, dbg_name}; }; +Virtio9p.prototype.update_dbg_name = function(idx, newname) +{ + for(const fid of this.fids) + { + if(fid.inodeid === idx) fid.dbg_name = newname; + } +}; + Virtio9p.prototype.Reset = function() { this.fids = []; }; @@ -389,6 +397,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { var idx = this.fs.CreateFile(name, this.fids[fid].inodeid); this.fids[fid].inodeid = idx; this.fids[fid].type = FID_INODE; + this.fids[fid].dbg_name = name; var inode = this.fs.GetInode(idx); inode.uid = this.fids[fid].uid; inode.gid = gid; @@ -618,6 +627,8 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { this.SendReply(bufchain); break; } + const newidx = this.fs.Search(this.fids[newdirfid].inodeid, newname); + this.update_dbg_name(newidx, newname); this.BuildReply(id, tag, 0); this.SendReply(bufchain); break; From c7dda46de1fc7da952edb8ad35c9371d64b35ce0 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 1 Sep 2018 22:40:13 +1200 Subject: [PATCH 1289/2137] Filesystem: Disallow hardlinks across filesystems Although hardlinks across filesystems worked quite well in the current implementation, we will run into problems when we try to implement different backends for each sub-filesystem. Note: EPERM is used instead of EXDEV since the mv command will silently try to use copy-and-unlink when rename(2) fails with EXDEV. The rules for linking has been reverted back: - Before commit: Any inode, including forwarders, could be linked as long as the parent is not a forwarder and is a directory. - After commit: Only non-forwarders and root-forwarders are allowed to be linked, and must be linked under a directory and not a forwarder. --- lib/filesystem.js | 50 +++++++++++------------------- tests/devices/virtio_9p.js | 63 +++++++++++--------------------------- 2 files changed, 36 insertions(+), 77 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index a5ce3695..fada2cda 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -324,14 +324,14 @@ FS.prototype.LoadFile = function(idx) { /** * @private - * @param {Inode} directory + * @param {Inode} inode * @return {boolean} */ -FS.prototype.directory_is_linkable = function(directory) +FS.prototype.should_be_linked = function(inode) { // Note: Non-root forwarder inode could still have a non-forwarder parent, so don't use // parent inode to check. - return !this.is_forwarder(directory) || directory.foreign_id === 0; + return !this.is_forwarder(inode) || inode.foreign_id === 0; }; /** @@ -350,6 +350,8 @@ FS.prototype.link_under_dir = function(parentid, idx, name) "Filesystem: Shouldn't link under fowarder parents"); dbg_assert(this.IsDirectory(parentid), "Filesystem: Can't link under non-directories"); + dbg_assert(this.should_be_linked(inode), + "Filesystem: Can't link across filesystems apart from their root"); dbg_assert(real_inode.nlinks >= 0, "Filesystem: Found negative nlinks value of " + real_inode.nlinks); dbg_assert(!parent_inode.direntries.has(name), @@ -367,13 +369,6 @@ FS.prototype.link_under_dir = function(parentid, idx, name) if(this.IsDirectory(idx)) { - // Safe assumption: - // We will never link a directory forwarder apart from the mountpoint. - // Directories cannot be hardlinked to two places, - // so the parent of any non-root directory forwarder must also be a forwarder parent, - // but forwarder parents are already asserted against. - dbg_assert(this.directory_is_linkable(inode), - "Filesystem: Cannot link non-root directory forwarder"); dbg_assert(!inode.direntries.has(".."), "Filesystem: Cannot link a directory twice"); @@ -579,7 +574,7 @@ FS.prototype.divert = function(parentid, filename) { this.mounts[old_inode.mount_id].backtrack.set(old_inode.foreign_id, idx); } - if(!this.is_forwarder(this.inodes[parentid])) + if(this.should_be_linked(old_inode)) { this.unlink_from_dir(parentid, filename); this.link_under_dir(parentid, idx, filename); @@ -855,25 +850,9 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { else if(!this.IsDirectory(idx) && this.GetInode(idx).nlinks > 1) { // Move hardlinked inode vertically in mount tree. - - if(!this.is_forwarder(inode)) - { - dbg_log("XXX: Attempted to move hardlinked file (" + oldname + ") " + - "to a child filesystem - skipped", LOG_9P); - return -EPERM; - } - if(this.is_forwarder(newdir) && newdir.mount_id !== inode.mount_id) - { - dbg_log("XXX: Attempted to move hardlinked file (" + oldname + ") " + - "to a sibling filesystem - skipped", LOG_9P); - return -EPERM; - } - - const link_ret = this.Link(newdirid, idx, newname); - if(link_ret < 0) return link_ret; - - const unlink_ret = this.Unlink(olddirid, oldname); - if(unlink_ret < 0) return unlink_ret; + dbg_log("XXX: Attempted to move hardlinked file (" + oldname + ") " + + "across filesystems - skipped", LOG_9P); + return -EPERM; } else { @@ -1098,9 +1077,10 @@ FS.prototype.Link = function(parentid, targetid, name) } const parent_inode = this.inodes[parentid]; + const inode = this.inodes[targetid]; + if(this.is_forwarder(parent_inode)) { - const inode = this.inodes[targetid]; if(!this.is_forwarder(inode) || inode.mount_id !== parent_inode.mount_id) { dbg_log("XXX: Attempted to hardlink a file into a child filesystem - skipped", LOG_9P); @@ -1109,6 +1089,12 @@ FS.prototype.Link = function(parentid, targetid, name) return this.follow_fs(parent_inode).Link(parent_inode.foreign_id, inode.foreign_id, name); } + if(this.is_forwarder(inode)) + { + dbg_log("XXX: Attempted to hardlink file across filesystems - skipped", LOG_9P); + return -EPERM; + } + this.link_under_dir(parentid, targetid, name); return 0; }; @@ -1461,7 +1447,7 @@ FS.prototype.GetParent = function(idx) const inode = this.inodes[idx]; - if(this.directory_is_linkable(inode)) + if(this.should_be_linked(inode)) { return inode.direntries.get(".."); } diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index fdd52e61..e33ac607 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -1286,55 +1286,34 @@ const tests = mounts: [ { path: "/fs1a" }, - { path: "/fs1a/fs2a" }, - { path: "/fs1a/fs2a/fs3" }, - { path: "/fs1a/fs2b" }, + { path: "/fs1a/fs2" }, { path: "/fs1b" }, ], start: () => { - emulator.serial0_send("echo foobar > /mnt/fs1a/fs2a/file\n"); + emulator.serial0_send("echo foobar > /mnt/fs1a/file\n"); emulator.serial0_send("echo start-capture;\\\n"); - emulator.serial0_send("ln /mnt/fs1a/fs2a/file /mnt/link-root;\\\n"); - emulator.serial0_send("echo link at root fs >> /mnt/link-root;\\\n"); - emulator.serial0_send("rm /mnt/link-root;\\\n"); + emulator.serial0_send("{ ln /mnt/fs1a/file /mnt/fs1a/fs2/link-child 2>/dev/null || \n"); + emulator.serial0_send(" echo link at child fs - fails >> /mnt/fs1a/file; };\\\n"); - emulator.serial0_send("{ ln /mnt/fs1a/fs2a/file /mnt/fs1a/fs2a/fs3/link-child 2>/dev/null || \n"); - emulator.serial0_send(" echo link at child fs - fails >> /mnt/fs1a/fs2a/file; };\\\n"); + emulator.serial0_send("{ ln /mnt/fs1a/file /mnt/link-parent 2>/dev/null || \n"); + emulator.serial0_send(" echo link at parent fs - fails >> /mnt/fs1a/file; };\\\n"); - emulator.serial0_send("ln /mnt/fs1a/fs2a/file /mnt/fs1a/fs2a/link;\\\n"); - emulator.serial0_send("echo link at common fs >> /mnt/fs1a/fs2a/link;\\\n"); + emulator.serial0_send("ln /mnt/fs1a/file /mnt/fs1a/link;\\\n"); + emulator.serial0_send("echo link at common fs >> /mnt/fs1a/link;\\\n"); - emulator.serial0_send("mv /mnt/fs1a/fs2a/link /mnt/fs1a/fs2a/link-renamed;\\\n"); - emulator.serial0_send("echo rename >> /mnt/fs1a/fs2a/link-renamed;\\\n"); + emulator.serial0_send("mv /mnt/fs1a/link /mnt/fs1a/link2;\\\n"); + emulator.serial0_send("echo rename >> /mnt/fs1a/link2;\\\n"); - emulator.serial0_send("mv /mnt/fs1a/fs2a/link-renamed /mnt/link2;\\\n"); - emulator.serial0_send("echo jump to root >> /mnt/link2;\\\n"); + emulator.serial0_send("{ mv /mnt/fs1a/link2 /mnt/link3 2>/dev/null || \n"); + emulator.serial0_send(" echo jump to parent - fails >> /mnt/fs1a/link2; };\\\n"); - emulator.serial0_send("{ mv /mnt/link2 /mnt/fs1b/link3 2>/dev/null || \n"); - emulator.serial0_send(" echo jump outside 1 - fails >> /mnt/link2; };\\\n"); + emulator.serial0_send("{ mv /mnt/fs1a/link2 /mnt/fs1b/link3 2>/dev/null || \n"); + emulator.serial0_send(" echo jump outside - fails >> /mnt/fs1a/link2; };\\\n"); - emulator.serial0_send("mv /mnt/link2 /mnt/fs1a/link4;\\\n"); - emulator.serial0_send("echo jump back one level >> /mnt/fs1a/link4;\\\n"); - - emulator.serial0_send("mv /mnt/fs1a/link4 /mnt/link5;\\\n"); - emulator.serial0_send("echo jump to root >> /mnt/link5;\\\n"); - - emulator.serial0_send("{ mv /mnt/link5 /mnt/fs1a/fs2b/link6 2>/dev/null || \n"); - emulator.serial0_send(" echo jump outside 2 - fails >> /mnt/link5; };\\\n"); - - emulator.serial0_send("{ mv /mnt/link5 /mnt/fs1a/fs2a/fs3/link7 2>/dev/null || \n"); - emulator.serial0_send(" echo jump beyond - fails >> /mnt/link5; };\\\n"); - - emulator.serial0_send("mv /mnt/link5 /mnt/fs1a/fs2a/link8;\\\n"); - emulator.serial0_send("echo jump back two levels >> /mnt/fs1a/fs2a/link8;\\\n"); - - emulator.serial0_send("{ mv /mnt/fs1a/fs2a/link8 /mnt/fs1a/fs2a/fs3/link9 2>/dev/null || \n"); - emulator.serial0_send(" echo jump up - fails >> /mnt/fs1a/fs2a/link8; };\\\n"); - - emulator.serial0_send("cat /mnt/fs1a/fs2a/file;\\\n"); + emulator.serial0_send("cat /mnt/fs1a/file;\\\n"); emulator.serial0_send("echo done-hard-links-mounted\n"); }, capture_trigger: "start-capture", @@ -1343,18 +1322,12 @@ const tests = { assert_equal(capture, "foobar\n" + - "link at root fs\n" + "link at child fs - fails\n" + + "link at parent fs - fails\n" + "link at common fs\n" + "rename\n" + - "jump to root\n" + - "jump outside 1 - fails\n" + - "jump back one level\n" + - "jump to root\n" + - "jump outside 2 - fails\n" + - "jump beyond - fails\n" + - "jump back two levels\n" + - "jump up - fails\n"); + "jump to parent - fails\n" + + "jump outside - fails\n"); done(); }, }, From c3739fc22a1225ada2ba86a99d597205d6fa734a Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 2 Sep 2018 11:33:19 +1200 Subject: [PATCH 1290/2137] 9p: Disable filename tracking by default --- lib/9p.js | 8 ++++++-- src/config.js | 5 +++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/9p.js b/lib/9p.js index fe0f12df..4551ab91 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -195,6 +195,7 @@ Virtio9p.prototype.set_state = function(state) // Note: dbg_name is only used for debugging messages and may not be the same as the filename, // since it is not synchronised with renames done outside of 9p. Hard-links, linking and unlinking // operations also mean that having a single filename no longer makes sense. +// Set TRACK_FILENAMES = true (in config.js) to sync dbg_name during 9p renames. Virtio9p.prototype.Createfid = function(inodeid, type, uid, dbg_name) { return {inodeid, type, uid, dbg_name}; }; @@ -627,8 +628,11 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { this.SendReply(bufchain); break; } - const newidx = this.fs.Search(this.fids[newdirfid].inodeid, newname); - this.update_dbg_name(newidx, newname); + if(TRACK_FILENAMES) + { + const newidx = this.fs.Search(this.fids[newdirfid].inodeid, newname); + this.update_dbg_name(newidx, newname); + } this.BuildReply(id, tag, 0); this.SendReply(bufchain); break; diff --git a/src/config.js b/src/config.js index 96b8bafb..831b1b17 100644 --- a/src/config.js +++ b/src/config.js @@ -34,6 +34,11 @@ var DUMP_GENERATED_WASM = false; */ var DUMP_UNCOMPILED_ASSEMBLY = false; +/** + * @const + * More accurate filenames in 9p debug messages at the cost of performance. + */ +var TRACK_FILENAMES = false; var LOG_LEVEL = LOG_ALL & ~LOG_PS2 & ~LOG_PIT & ~LOG_VIRTIO & ~LOG_9P & ~LOG_PIC & ~LOG_DMA & ~LOG_SERIAL & ~LOG_NET & ~LOG_FLOPPY & ~LOG_DISK & ~LOG_VGA; From 6c61d48c8f3749d05bb9ae79d5f47d85bf95bb78 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 2 Sep 2018 11:38:30 +1200 Subject: [PATCH 1291/2137] Filesystem: Fix typo with path concatenation during Rename --- lib/filesystem.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index fada2cda..9fc30f8d 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -809,7 +809,7 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { } // For event notification near end of method. - var oldpath = this.GetFullPath(olddirid) + "/oldname"; + var oldpath = this.GetFullPath(olddirid) + "/" + oldname; var newid = this.Search(newdirid, newname); if (newid != -1) { From 66cf97e0a7e68fea4e85d9491df955ee9f4defbc Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 2 Sep 2018 14:25:18 +1200 Subject: [PATCH 1292/2137] Filesystem: Tidy comments, clarify nlinks special case. --- lib/9p.js | 2 +- lib/filesystem.js | 23 ++++++++++++++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/lib/9p.js b/lib/9p.js index 4551ab91..5e9074d0 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -296,7 +296,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { ); break; - case 70: // link (just copying) + case 70: // link var req = marshall.Unmarshall(["w", "w", "s"], buffer, state); var dfid = req[0]; var fid = req[1]; diff --git a/lib/filesystem.js b/lib/filesystem.js index 9fc30f8d..03fa6bcb 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -360,8 +360,9 @@ FS.prototype.link_under_dir = function(parentid, idx, name) parent_inode.direntries.set(name, idx); parent_inode.updatedir = true; - // Root inode of other filesystems are already linked to themselves. - if(real_inode.fid !== 0) + // Root inodes of other filesystems have already accounted for their nlinks (due to their '..'). + // Also, don't mess with other filesystem's nlinks. + if(!this.is_a_root(idx)) { // Never store link information on forwarder. real_inode.nlinks++; @@ -400,8 +401,9 @@ FS.prototype.unlink_from_dir = function(parentid, name) const exists = parent_inode.direntries.delete(name); dbg_assert(exists, "Filesystem: Can't unlink non-existent file: " + name); - // Root inode of other filesystems are still linked to themselves. - if(real_inode.fid !== 0) + // Root inodes of other filesystems have already accounted for their nlinks (due to their '..'). + // Also, don't mess with other filesystem's nlinks. + if(!this.is_a_root(idx)) { // Never store link information on forwarder. real_inode.nlinks--; @@ -840,7 +842,7 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { if(ret < 0) return ret; } - else if(this.GetInode(idx).fid === 0) + else if(this.is_a_root(idx)) { // The actual inode is a root of some descendant filesystem. // Moving mountpoint across fs not supported - needs to update all corresponding forwarders. @@ -1598,6 +1600,17 @@ FS.prototype.is_forwarder = function(inode) return inode.status === STATUS_FORWARDING; }; +/** + * Whether the inode it points to is a root of some filesystem. + * @private + * @param {number} idx + * @return {boolean} + */ +FS.prototype.is_a_root = function(idx) +{ + return this.GetInode(idx).fid === 0; +}; + /** * Ensures forwarder exists, and returns such forwarder, for the described foreign inode. * @private From 40ed4f8dde6057581e38ced63d1da5cbc3d04c7e Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 2 Sep 2018 14:54:05 +1200 Subject: [PATCH 1293/2137] Filesystem: Simplify nlinks management across filesystems Now that hard links aren't allowed across filesystems, it's ok to store the relevant nlinks information within local inode. For mountpoints (forwarder inodes that point to a root inode), it is possible to bump the nlinks of the forwarder during link_under_dir and unlink_from_dir so that this nlinks counter is modified independently from the real inode's nlinks counter. For divert(), it is actually ok to divert forwarder inodes that point to hardlinked files, so I've relaxed the assertion predicate. --- lib/filesystem.js | 41 ++++++++++++++--------------------------- 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 03fa6bcb..469a5726 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -343,7 +343,6 @@ FS.prototype.should_be_linked = function(inode) FS.prototype.link_under_dir = function(parentid, idx, name) { const inode = this.inodes[idx]; - const real_inode = this.GetInode(idx); const parent_inode = this.inodes[parentid]; dbg_assert(!this.is_forwarder(parent_inode), @@ -352,28 +351,21 @@ FS.prototype.link_under_dir = function(parentid, idx, name) "Filesystem: Can't link under non-directories"); dbg_assert(this.should_be_linked(inode), "Filesystem: Can't link across filesystems apart from their root"); - dbg_assert(real_inode.nlinks >= 0, - "Filesystem: Found negative nlinks value of " + real_inode.nlinks); + dbg_assert(inode.nlinks >= 0, + "Filesystem: Found negative nlinks value of " + inode.nlinks); dbg_assert(!parent_inode.direntries.has(name), "Filesystem: Name '" + name + "' is already taken"); parent_inode.direntries.set(name, idx); parent_inode.updatedir = true; - - // Root inodes of other filesystems have already accounted for their nlinks (due to their '..'). - // Also, don't mess with other filesystem's nlinks. - if(!this.is_a_root(idx)) - { - // Never store link information on forwarder. - real_inode.nlinks++; - } + inode.nlinks++; if(this.IsDirectory(idx)) { dbg_assert(!inode.direntries.has(".."), "Filesystem: Cannot link a directory twice"); - if(!real_inode.direntries.has(".")) real_inode.nlinks++; + if(!inode.direntries.has(".")) inode.nlinks++; inode.direntries.set(".", idx); inode.direntries.set("..", parentid); @@ -392,23 +384,19 @@ FS.prototype.unlink_from_dir = function(parentid, name) { const idx = this.Search(parentid, name); const inode = this.inodes[idx]; - const real_inode = this.GetInode(idx); const parent_inode = this.inodes[parentid]; dbg_assert(!this.is_forwarder(parent_inode), "Filesystem: Can't unlink from fowarders"); dbg_assert(this.IsDirectory(parentid), "Filesystem: Can't unlink from non-directories"); const exists = parent_inode.direntries.delete(name); - dbg_assert(exists, "Filesystem: Can't unlink non-existent file: " + name); - - // Root inodes of other filesystems have already accounted for their nlinks (due to their '..'). - // Also, don't mess with other filesystem's nlinks. - if(!this.is_a_root(idx)) + if(!exists) { - // Never store link information on forwarder. - real_inode.nlinks--; + dbg_assert(false, "Filesystem: Can't unlink non-existent file: " + name); + return; } + inode.nlinks--; parent_inode.updatedir = true; if(this.IsDirectory(idx)) @@ -422,8 +410,8 @@ FS.prototype.unlink_from_dir = function(parentid, name) inode.updatedir = true; } - dbg_assert(real_inode.nlinks >= 0, - "Filesystem: Found negative nlinks value of " + real_inode.nlinks); + dbg_assert(inode.nlinks >= 0, + "Filesystem: Found negative nlinks value of " + inode.nlinks); }; FS.prototype.PushInode = function(inode, parentid, name) { @@ -560,9 +548,9 @@ FS.prototype.divert = function(parentid, filename) const new_inode = new Inode(-1); dbg_assert(old_inode, "Filesystem divert: name (" + filename + ") not found"); - dbg_assert(this.IsDirectory(old_idx) || this.GetInode(old_idx).nlinks <= 1, + dbg_assert(this.IsDirectory(old_idx) || old_inode.nlinks <= 1, "Filesystem: can't divert hardlinked file '" + filename + "' with nlinks=" + - this.GetInode(old_idx).nlinks); + old_inode.nlinks); // Shallow copy is alright. Object.assign(new_inode, old_inode); @@ -1110,7 +1098,6 @@ FS.prototype.Unlink = function(parentid, name) { const idx = this.Search(parentid, name); const inode = this.inodes[idx]; const parent_inode = this.inodes[parentid]; - const real_inode = this.GetInode(idx); //message.Debug("Unlink " + inode.name); // forward if necessary @@ -1131,10 +1118,10 @@ FS.prototype.Unlink = function(parentid, name) { this.unlink_from_dir(parentid, name); - if(real_inode.nlinks === 0) + if(inode.nlinks === 0) { // don't delete the content. The file is still accessible - real_inode.status = STATUS_UNLINKED; + inode.status = STATUS_UNLINKED; this.NotifyListeners(idx, 'delete'); } return 0; From e5a689ac2d1c5b4f110f990821a78ef76cbb52b7 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 2 Sep 2018 21:16:41 +1200 Subject: [PATCH 1294/2137] Filesystem: Expand tests for hard links Verify multiple hardlinks and verify nlinks counter. --- tests/devices/virtio_9p.js | 117 +++++++++++++++++++++++++++++++------ 1 file changed, 99 insertions(+), 18 deletions(-) diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index e33ac607..d856a43b 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -408,25 +408,83 @@ const tests = ], start: () => { - emulator.serial0_send("ln /mnt/target /mnt/link\n"); - emulator.serial0_send("echo foo >> /mnt/link\n"); + // Helper script that prints filename followed by nlinks. + emulator.serial0_send('cat << "EOF" > /mnt/nlinks\n'); + emulator.serial0_send('#!/bin/sh\n'); + emulator.serial0_send(`ls -dli $@ | awk '{ print "'$@' "$3 }'\n`); + emulator.serial0_send("EOF\n"); + emulator.serial0_send("chmod +x /mnt/nlinks\n"); - emulator.serial0_send("echo start-capture;"); + // Check nlinks before mkdir. + emulator.serial0_send("/mnt/nlinks /mnt | tee -a /mnt/target\n"); - // "foo" should be added to the target. - emulator.serial0_send("cat /mnt/target;"); + emulator.serial0_send("mkdir /mnt/dir\n"); + emulator.serial0_send("echo other > /mnt/target2\n"); - // Both should have the same inode number - emulator.serial0_send("test /mnt/target -ef /mnt/link && echo same-inode;"); + // Check nlinks after mkdir. + emulator.serial0_send("/mnt/nlinks /mnt | tee -a /mnt/target\n"); + emulator.serial0_send("/mnt/nlinks /mnt/dir | tee -a /mnt/target\n"); + emulator.serial0_send("/mnt/nlinks /mnt/target | tee -a /mnt/target\n"); - // File should still exist after one is renamed. - emulator.serial0_send("mv /mnt/target /mnt/renamed;"); - emulator.serial0_send("echo bar >> /mnt/renamed;"); - emulator.serial0_send("cat /mnt/link;"); + // Create hard links. + emulator.serial0_send("ln /mnt/target /mnt/link1\n"); + emulator.serial0_send("ln /mnt/link1 /mnt/dir/link2\n"); + emulator.serial0_send("ln /mnt/dir/link2 /mnt/dir/link3\n"); + emulator.serial0_send("ln /mnt/target2 /mnt/link-other\n"); - // File should still exist after one of the names are unlinked. - emulator.serial0_send("rm /mnt/renamed;"); - emulator.serial0_send("cat /mnt/link;"); + // Test inode numbers. + emulator.serial0_send("{ test /mnt/target -ef /mnt/link1 && \n"); + emulator.serial0_send(" test /mnt/link1 -ef /mnt/dir/link2 && \n"); + emulator.serial0_send(" test /mnt/target -ef /mnt/dir/link3 && \n"); + emulator.serial0_send(" echo same inode | tee -a /mnt/target; }\n"); + emulator.serial0_send("{ test /mnt/link-other -ef /mnt/dir/link3 || \n"); + emulator.serial0_send(" echo different inode | tee -a /mnt/link1; }\n"); + + // Check nlinks after hard links. + emulator.serial0_send("/mnt/nlinks /mnt | tee -a /mnt/dir/link2\n"); + emulator.serial0_send("/mnt/nlinks /mnt/dir | tee -a /mnt/dir/link2\n"); + emulator.serial0_send("/mnt/nlinks /mnt/target | tee -a /mnt/dir/link2\n"); + emulator.serial0_send("/mnt/nlinks /mnt/dir/link2 | tee -a /mnt/dir/link2\n"); + emulator.serial0_send("/mnt/nlinks /mnt/target2 | tee -a /mnt/dir/link2\n"); + emulator.serial0_send("/mnt/nlinks /mnt/link-other | tee -a /mnt/dir/link2\n"); + + // Movement and unlink. + emulator.serial0_send("mv /mnt/link1 /mnt/link1-renamed\n"); + emulator.serial0_send("echo renamed | tee -a /mnt/link1-renamed\n"); + emulator.serial0_send("mv /mnt/dir/link2 /mnt/link2-moved\n"); + emulator.serial0_send("echo moved | tee -a /mnt/link2-moved\n"); + emulator.serial0_send("rm /mnt/target\n"); + emulator.serial0_send("echo unlinked original | tee -a /mnt/dir/link3\n"); + + // Test inode numbers after movement and unlinking. + emulator.serial0_send("{ test /mnt/link1-renamed -ef /mnt/link2-moved && \n"); + emulator.serial0_send(" test /mnt/link2-moved -ef /mnt/dir/link3 && \n"); + emulator.serial0_send(" echo same inode after mv | tee -a /mnt/link1-renamed; }\n"); + + // Check nlinks after movement and unlinking. + emulator.serial0_send("/mnt/nlinks /mnt | tee -a /mnt/link2-moved\n"); + emulator.serial0_send("/mnt/nlinks /mnt/dir | tee -a /mnt/link2-moved\n"); + emulator.serial0_send("/mnt/nlinks /mnt/link1-renamed | tee -a /mnt/link2-moved\n"); + + emulator.serial0_send("echo start-capture;\\\n"); + + // Unlink the rest and output the above messages. + emulator.serial0_send("rm /mnt/link1-renamed;\\\n"); + emulator.serial0_send("echo unlinked link1 >> /mnt/link2-moved;\\\n"); + emulator.serial0_send("/mnt/nlinks /mnt/link2-moved >> /mnt/link2-moved;\\\n"); + emulator.serial0_send("rm /mnt/link2-moved;\\\n"); + emulator.serial0_send("echo unlinked link2 >> /mnt/dir/link3;\\\n"); + emulator.serial0_send("/mnt/nlinks /mnt/dir/link3 >> /mnt/dir/link3;\\\n"); + emulator.serial0_send("cat /mnt/dir/link3;\\\n"); + emulator.serial0_send("rm /mnt/dir/link3;\\\n"); + + // Verify nlinks of directories after unlinking hardlinks. + emulator.serial0_send("/mnt/nlinks /mnt;\\\n"); + emulator.serial0_send("/mnt/nlinks /mnt/dir;\\\n"); + + // Verify nlinks of root directory after subdirectory is unlinked. + emulator.serial0_send("rmdir /mnt/dir;\\\n"); + emulator.serial0_send("/mnt/nlinks /mnt;\\\n"); emulator.serial0_send("echo done-hard-links\n"); }, @@ -435,10 +493,33 @@ const tests = end: (capture, done) => { assert_equal(capture, - test_file_small_string + "foo\n" + - "same-inode\n" + - test_file_small_string + "foo\nbar\n" + - test_file_small_string + "foo\nbar\n"); + test_file_small_string + + "/mnt 2\n" + + "/mnt 3\n" + + "/mnt/dir 2\n" + + "/mnt/target 1\n" + + "same inode\n" + + "different inode\n" + + "/mnt 3\n" + + "/mnt/dir 2\n" + + "/mnt/target 4\n" + + "/mnt/dir/link2 4\n" + + "/mnt/target2 2\n" + + "/mnt/link-other 2\n" + + "renamed\n" + + "moved\n" + + "unlinked original\n" + + "same inode after mv\n" + + "/mnt 3\n" + + "/mnt/dir 2\n" + + "/mnt/link1-renamed 3\n" + + "unlinked link1\n" + + "/mnt/link2-moved 2\n" + + "unlinked link2\n" + + "/mnt/dir/link3 1\n" + + "/mnt 3\n" + + "/mnt/dir 2\n" + + "/mnt 2\n"); done(); }, }, From 3773f0bfdf470f5b2270454886bf5cf0f3a2558d Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 2 Sep 2018 21:20:16 +1200 Subject: [PATCH 1295/2137] Filesystem tests: Increase memory size to 64MiB OOM Killer was killing the processes. --- tests/devices/virtio_9p.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index d856a43b..5b4dee00 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -1472,7 +1472,7 @@ const emulator = new V86({ vga_bios: { url: __dirname + "/../../bios/vgabios.bin" }, cdrom: { url: __dirname + "/../../images/linux4.iso" }, autostart: true, - memory_size: 32 * 1024 * 1024, + memory_size: 64 * 1024 * 1024, filesystem: { "baseurl": __dirname + "/testfs/", }, From 0377e95c421ea89fa6cb5fbb7c62abce7abe7cde Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Mon, 3 Sep 2018 23:05:48 +0530 Subject: [PATCH 1296/2137] jit 0x0FB7 --- gen/x86_table.js | 2 +- src/rust/jit_instructions.rs | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 0ed4b9af..04aaca14 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -490,7 +490,7 @@ const encodings = [ { opcode: 0x0FB5, block_boundary: 1, os: 1, e: 1, skip: 1, }, // lgs { opcode: 0x0FB6, os: 1, e: 1, custom: 1 }, // movzx - { opcode: 0x0FB7, os: 1, e: 1, }, + { opcode: 0x0FB7, os: 1, e: 1, custom: 1 }, { opcode: 0xF30FB8, os: 1, e: 1 }, // popcnt { opcode: 0x0FB8, os: 1, e: 1, block_boundary: 1, }, // ud diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 6a70382f..f1062e78 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1794,6 +1794,39 @@ pub fn instr32_0FB6_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { ctx.builder.instruction_body.store_aligned_i32(0); } +pub fn instr16_0FB7_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg16_offset(r) as i32); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read16(ctx); + ctx.builder.instruction_body.store_aligned_u16(0); +} +pub fn instr16_0FB7_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + let builder = &mut ctx.builder; + builder + .instruction_body + .const_i32(global_pointers::get_reg16_offset(r2) as i32); + codegen::gen_get_reg16(builder, r1); + builder.instruction_body.store_aligned_u16(0); +} +pub fn instr32_0FB7_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg32_offset(r) as i32); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read16(ctx); + ctx.builder.instruction_body.store_aligned_i32(0); +} +pub fn instr32_0FB7_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + let builder = &mut ctx.builder; + builder + .instruction_body + .const_i32(global_pointers::get_reg32_offset(r2) as i32); + codegen::gen_get_reg16(builder, r1); + builder.instruction_body.store_aligned_i32(0); +} + pub fn instr16_0FBE_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { let builder = &mut ctx.builder; builder From 54151e2306b146e5b0c64be3040b45c08058b0a0 Mon Sep 17 00:00:00 2001 From: Awal Garg Date: Mon, 3 Sep 2018 23:17:51 +0530 Subject: [PATCH 1297/2137] jit 0x0FBF --- gen/x86_table.js | 2 +- src/rust/codegen.rs | 8 ++++++++ src/rust/jit_instructions.rs | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 04aaca14..8fb45225 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -498,7 +498,7 @@ const encodings = [ { opcode: 0x0FB9, block_boundary: 1, }, // ud2 { opcode: 0x0FBE, os: 1, e: 1, custom: 1 }, // movsx - { opcode: 0x0FBF, os: 1, e: 1, }, + { opcode: 0x0FBF, os: 1, e: 1, custom: 1 }, { opcode: 0x0FC0, e: 1, }, // xadd { opcode: 0x0FC1, os: 1, e: 1, }, diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 2d7720f6..2e441963 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -89,6 +89,14 @@ pub fn sign_extend_i8(builder: &mut WasmBuilder) { builder.instruction_body.shr_s_i32(); } +/// sign-extend a two byte value on the stack and leave it on the stack +pub fn sign_extend_i16(builder: &mut WasmBuilder) { + builder.instruction_body.const_i32(16); + builder.instruction_body.shl_i32(); + builder.instruction_body.const_i32(16); + builder.instruction_body.shr_s_i32(); +} + pub fn gen_fn0_const(ctx: &mut JitContext, name: &str) { let builder = &mut ctx.builder; let fn_idx = builder.get_fn_idx(name, module_init::FN0_TYPE_INDEX); diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index f1062e78..955bdf8b 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1865,6 +1865,42 @@ pub fn instr32_0FBE_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { ctx.builder.instruction_body.store_aligned_i32(0); } +pub fn instr16_0FBF_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg16_offset(r2) as i32); + codegen::gen_get_reg16(ctx.builder, r1); + codegen::sign_extend_i16(ctx.builder); + ctx.builder.instruction_body.store_aligned_u16(0); +} +pub fn instr16_0FBF_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg16_offset(r) as i32); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read16(ctx); + codegen::sign_extend_i16(ctx.builder); + ctx.builder.instruction_body.store_aligned_u16(0); +} + +pub fn instr32_0FBF_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg32_offset(r2) as i32); + codegen::gen_get_reg16(ctx.builder, r1); + codegen::sign_extend_i16(ctx.builder); + ctx.builder.instruction_body.store_aligned_i32(0); +} +pub fn instr32_0FBF_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg32_offset(r) as i32); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read16(ctx); + codegen::sign_extend_i16(ctx.builder); + ctx.builder.instruction_body.store_aligned_i32(0); +} + pub fn instr_C6_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { // reg8[r] = imm; ctx.builder From 37c8459392d54d7fd70122a70b19dd226f8a8a6b Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 1 Sep 2018 16:04:21 -0500 Subject: [PATCH 1298/2137] Clean up c2rust-generated profiler --- src/rust/cpu2/cpu.rs | 67 +++++++++++----------- src/rust/cpu2/mod.rs | 1 - src/rust/cpu2/profiler.rs | 115 -------------------------------------- src/rust/lib.rs | 2 +- src/rust/profiler.rs | 39 +++++++++---- 5 files changed, 65 insertions(+), 159 deletions(-) delete mode 100644 src/rust/cpu2/profiler.rs diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 68144f5f..401694d0 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -23,8 +23,8 @@ use cpu2::memory::{ }; use cpu2::misc_instr::{getaf, getcf, getof, getpf, getsf, getzf}; use cpu2::modrm::{resolve_modrm16, resolve_modrm32}; -use cpu2::profiler::*; -use cpu2::profiler::{profiler_stat_increment, profiler_stat_increment_by}; +use profiler; +use profiler::stat::*; /// The offset for our generated functions in the wasm table. Every index less than this is /// reserved for rustc's indirect functions @@ -386,11 +386,11 @@ pub unsafe fn do_page_translation( } if *tlb_data.offset(page as isize) == 0 { if valid_tlb_entries_count == VALID_TLB_ENTRY_MAX { - profiler_stat_increment(S_TLB_FULL); + profiler::stat_increment(S_TLB_FULL); clear_tlb(); // also clear global entries if tlb is almost full after clearing non-global pages if valid_tlb_entries_count > VALID_TLB_ENTRY_MAX * 3 / 4 { - profiler_stat_increment(S_TLB_GLOBAL_FULL); + profiler::stat_increment(S_TLB_GLOBAL_FULL); full_clear_tlb(); } } @@ -457,7 +457,7 @@ pub unsafe fn do_page_translation( #[no_mangle] pub unsafe fn full_clear_tlb() { - profiler_stat_increment(S_FULL_CLEAR_TLB); + profiler::stat_increment(S_FULL_CLEAR_TLB); // clear tlb including global pages *last_virt_eip = -1; *last_virt_esp = -1; @@ -479,7 +479,7 @@ pub unsafe fn full_clear_tlb() { #[no_mangle] pub unsafe fn clear_tlb() { - profiler_stat_increment(S_CLEAR_TLB); + profiler::stat_increment(S_CLEAR_TLB); // clear tlb excluding global pages *last_virt_eip = -1; *last_virt_esp = -1; @@ -546,7 +546,7 @@ pub unsafe fn trigger_pagefault(mut write: bool, mut user: bool, mut present: bo 0 != 1, (user as i32) << 2 | (write as i32) << 1 | present as i32, ); - //profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); + //profiler::stat_increment(S_TRIGGER_CPU_EXCEPTION); } pub unsafe fn translate_address_write(mut address: i32) -> Result { @@ -717,7 +717,7 @@ pub unsafe fn raise_exception_with_code(mut interrupt_nr: i32, mut error_code: i return; } } - profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); + profiler::stat_increment(S_TRIGGER_CPU_EXCEPTION); call_interrupt_vector(interrupt_nr, 0 != 0, 0 != 1, error_code); assert!(false); } @@ -762,14 +762,15 @@ pub unsafe fn run_instruction0f_32(opcode: i32) { ::gen::interpreter0f_32::run(o #[no_mangle] pub unsafe fn cycle_internal() { - profiler_stat_increment(S_CYCLE_INTERNAL); + profiler::stat_increment(S_CYCLE_INTERNAL); if true { *previous_ip = *instruction_pointer; let mut phys_addr: u32 = return_on_pagefault!(get_phys_eip()) as u32; let mut state_flags: CachedStateFlags = pack_current_state_flags(); let mut entry: u32 = ::c_api::jit_find_cache_entry(phys_addr, state_flags as u32); + if 0 != entry { - profiler_stat_increment(S_RUN_FROM_CACHE); + profiler::stat_increment(S_RUN_FROM_CACHE); let initial_tsc = *timestamp_counter as i32; let wasm_table_index = (entry & 65535 as u32) as u16; let initial_state = (entry >> 16) as u16; @@ -777,9 +778,9 @@ pub unsafe fn cycle_internal() { (wasm_table_index as u32).wrapping_add(WASM_TABLE_OFFSET as u32) as i32, initial_state, ); - profiler_stat_increment_by( + profiler::stat_increment_by( S_RUN_FROM_CACHE_STEPS, - (*timestamp_counter).wrapping_sub(initial_tsc as u32) as i32, + (*timestamp_counter).wrapping_sub(initial_tsc as u32), ); } else { @@ -796,11 +797,11 @@ pub unsafe fn cycle_internal() { dbg_assert!(must_not_fault); must_not_fault = 0 != 0 } - let mut initial_tsc_0: i32 = *timestamp_counter as i32; + let mut initial_tsc: i32 = *timestamp_counter as i32; jit_run_interpreted(phys_addr as i32); - profiler_stat_increment_by( + profiler::stat_increment_by( S_RUN_INTERPRETED_STEPS, - (*timestamp_counter).wrapping_sub(initial_tsc_0 as u32) as i32, + (*timestamp_counter).wrapping_sub(initial_tsc as u32), ); }; } @@ -822,11 +823,13 @@ pub unsafe fn get_phys_eip() -> Result { dbg_assert!(!in_mapped_range(phys_addr)); return Ok(phys_addr as i32); } + unsafe fn jit_run_interpreted(mut phys_addr: i32) { - profiler_stat_increment(S_RUN_INTERPRETED); - jit_block_boundary = 0 != 0; + profiler::stat_increment(S_RUN_INTERPRETED); dbg_assert!(!in_mapped_range(phys_addr as u32)); - let mut opcode: i32 = *mem8.offset(phys_addr as isize) as i32; + + jit_block_boundary = false; + let opcode = *mem8.offset(phys_addr as isize) as i32; *instruction_pointer += 1; *timestamp_counter = (*timestamp_counter).wrapping_add(1); run_instruction(opcode | (*is_32 as i32) << 8); @@ -872,7 +875,7 @@ pub unsafe fn segment_prefix_op(mut seg: i32) { #[no_mangle] pub unsafe fn do_many_cycles_native() { - profiler_stat_increment(S_DO_MANY_CYCLES); + profiler::stat_increment(S_DO_MANY_CYCLES); let mut initial_timestamp_counter: u32 = *timestamp_counter; while (*timestamp_counter).wrapping_sub(initial_timestamp_counter) < LOOP_COUNTER as u32 && !*in_hlt @@ -893,7 +896,7 @@ pub unsafe fn do_many_cycles_native() { // return; // } // } -// profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); +// profiler::stat_increment(S_TRIGGER_CPU_EXCEPTION); // call_interrupt_vector(interrupt_nr, 0 != 0, 0 != 0, 0); // throw_cpu_exception(); //} @@ -1035,7 +1038,7 @@ pub unsafe fn safe_read32s(mut address: i32) -> Result { let mut info_bits: i32 = entry & 4095 & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; if info_bits == TLB_VALID && address & 4095 <= 4096 - 4 { if false { - profiler_stat_increment(S_SAFE_READ32_FAST); + profiler::stat_increment(S_SAFE_READ32_FAST); } // - not in memory mapped area // - can be accessed from any cpl @@ -1046,16 +1049,16 @@ pub unsafe fn safe_read32s(mut address: i32) -> Result { else { if false { if address & 4095 > 4096 - 4 { - profiler_stat_increment(S_SAFE_READ32_SLOW_PAGE_CROSSED); + profiler::stat_increment(S_SAFE_READ32_SLOW_PAGE_CROSSED); } else if info_bits & TLB_VALID == 0 { - profiler_stat_increment(S_SAFE_READ32_SLOW_NOT_VALID); + profiler::stat_increment(S_SAFE_READ32_SLOW_NOT_VALID); } else if 0 != info_bits & TLB_NO_USER { - profiler_stat_increment(S_SAFE_READ32_SLOW_NOT_USER); + profiler::stat_increment(S_SAFE_READ32_SLOW_NOT_USER); } else if 0 != info_bits & TLB_IN_MAPPED_RANGE { - profiler_stat_increment(S_SAFE_READ32_SLOW_IN_MAPPED_RANGE); + profiler::stat_increment(S_SAFE_READ32_SLOW_IN_MAPPED_RANGE); } else { dbg_assert!(0 != 0); @@ -1185,7 +1188,7 @@ pub unsafe fn safe_write32(mut address: i32, mut value: i32) -> Result<(), ()> { entry & 4095 & !TLB_GLOBAL & !if *cpl as i32 == 3 { 0 } else { TLB_NO_USER }; if info_bits == TLB_VALID && address & 4095 <= 4096 - 4 { if false { - profiler_stat_increment(S_SAFE_WRITE32_FAST); + profiler::stat_increment(S_SAFE_WRITE32_FAST); } // - allowed to write in user-mode // - not in memory mapped area @@ -1198,22 +1201,22 @@ pub unsafe fn safe_write32(mut address: i32, mut value: i32) -> Result<(), ()> { else { if false { if address & 4095 > 4096 - 4 { - profiler_stat_increment(S_SAFE_WRITE32_SLOW_PAGE_CROSSED); + profiler::stat_increment(S_SAFE_WRITE32_SLOW_PAGE_CROSSED); } else if info_bits & TLB_VALID == 0 { - profiler_stat_increment(S_SAFE_WRITE32_SLOW_NOT_VALID); + profiler::stat_increment(S_SAFE_WRITE32_SLOW_NOT_VALID); } else if 0 != info_bits & TLB_NO_USER { - profiler_stat_increment(S_SAFE_WRITE32_SLOW_NOT_USER); + profiler::stat_increment(S_SAFE_WRITE32_SLOW_NOT_USER); } else if 0 != info_bits & TLB_IN_MAPPED_RANGE { - profiler_stat_increment(S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE); + profiler::stat_increment(S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE); } else if 0 != info_bits & TLB_READONLY { - profiler_stat_increment(S_SAFE_WRITE32_SLOW_READ_ONLY); + profiler::stat_increment(S_SAFE_WRITE32_SLOW_READ_ONLY); } else if 0 != info_bits & TLB_HAS_CODE { - profiler_stat_increment(S_SAFE_WRITE32_SLOW_HAS_CODE); + profiler::stat_increment(S_SAFE_WRITE32_SLOW_HAS_CODE); } else { dbg_assert!(0 != 0); diff --git a/src/rust/cpu2/mod.rs b/src/rust/cpu2/mod.rs index 877331e6..688a3aa2 100644 --- a/src/rust/cpu2/mod.rs +++ b/src/rust/cpu2/mod.rs @@ -13,6 +13,5 @@ pub mod instructions_0f; pub mod memory; pub mod misc_instr; pub mod modrm; -pub mod profiler; pub mod sse_instr; pub mod string; diff --git a/src/rust/cpu2/profiler.rs b/src/rust/cpu2/profiler.rs deleted file mode 100644 index e4d9d50f..00000000 --- a/src/rust/cpu2/profiler.rs +++ /dev/null @@ -1,115 +0,0 @@ -#![allow(unused_mut)] - -pub const S_SAFE_WRITE32_SLOW_NOT_VALID: StatName = 22; -pub const S_SAFE_WRITE32_SLOW_NOT_USER: StatName = 23; - -pub const S_CYCLE_INTERNAL: StatName = 29; -pub const S_COMPILE: StatName = 0; - -pub const S_RUN_INTERPRETED_PENDING: StatName = 8; -pub const S_TRIGGER_CPU_EXCEPTION: StatName = 14; -pub const S_TLB_GLOBAL_FULL: StatName = 36; -pub const S_SAFE_READ32_FAST: StatName = 15; -pub const S_SAFE_READ32_SLOW_PAGE_CROSSED: StatName = 16; -pub const S_INVALIDATE_PAGE: StatName = 30; -pub const S_SAFE_READ32_SLOW_NOT_VALID: StatName = 17; -pub const S_COMPILE_SUCCESS: StatName = 1; -pub const S_COMPILE_ENTRY_POINT: StatName = 5; -pub const S_SAFE_WRITE32_FAST: StatName = 20; -pub const S_DO_RUN: StatName = 27; -pub const S_SAFE_WRITE32_SLOW_HAS_CODE: StatName = 26; -pub const S_CLEAR_TLB: StatName = 33; -pub const S_RUN_FROM_CACHE_STEPS: StatName = 13; -pub const S_CACHE_MISMATCH: StatName = 6; -pub const S_RUN_INTERPRETED_DIFFERENT_STATE: StatName = 10; -pub const S_RUN_INTERPRETED_NEAR_END_OF_PAGE: StatName = 9; -pub const S_COMPILE_WITH_LOOP_SAFETY: StatName = 3; -pub const S_COMPILE_CUT_OFF_AT_END_OF_PAGE: StatName = 2; -#[derive(Copy, Clone)] -#[repr(C)] -pub struct profiler_stat { - pub count: i32, -} -pub const S_COMPILE_BASIC_BLOCK: StatName = 4; -pub const S_SAFE_WRITE32_SLOW_READ_ONLY: StatName = 25; -pub const S_INVALIDATE_CACHE_ENTRY: StatName = 31; - -pub const S_RUN_INTERPRETED_STEPS: StatName = 11; -pub const S_FULL_CLEAR_TLB: StatName = 34; -pub type StatName = u32; -pub const S_TLB_FULL: StatName = 35; -pub const S_DO_MANY_CYCLES: StatName = 28; -pub const S_SAFE_WRITE32_SLOW_PAGE_CROSSED: StatName = 21; -pub const S_SAFE_READ32_SLOW_IN_MAPPED_RANGE: StatName = 19; -pub const S_RUN_INTERPRETED: StatName = 7; -pub const S_RUN_FROM_CACHE: StatName = 12; -pub const S_SAFE_READ32_SLOW_NOT_USER: StatName = 18; -pub const S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE: StatName = 24; -pub const S_NONFAULTING_OPTIMIZATION: StatName = 32; -#[no_mangle] -pub static mut profiler_stat_arr: [profiler_stat; 37] = [ - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, - profiler_stat { count: 0 }, -]; -#[no_mangle] -pub unsafe fn profiler_init() { - let mut i: u32 = 0 as u32; - while i < (S_TLB_GLOBAL_FULL as i32 - S_COMPILE as i32 + 1) as u32 { - profiler_stat_arr[i as usize].count = 0; - i = i.wrapping_add(1) - } -} -#[no_mangle] -pub unsafe fn profiler_stat_increment(mut stat: StatName) { profiler_stat_increment_by(stat, 1); } -#[no_mangle] -pub unsafe fn profiler_stat_increment_by(mut stat: StatName, mut by: i32) { - if cfg!(feature = "profiler") { - profiler_stat_arr[stat as usize].count += by; - } -} -#[no_mangle] -pub unsafe fn profiler_stat_get(mut stat: StatName) -> i32 { - if cfg!(feature = "profiler") { - profiler_stat_arr[stat as usize].count - } - else { - 0 - } -} -#[no_mangle] -pub unsafe fn profiler_stat_increment_do_run() { profiler_stat_increment(S_DO_RUN); } diff --git a/src/rust/lib.rs b/src/rust/lib.rs index 5612ffab..e5e63160 100644 --- a/src/rust/lib.rs +++ b/src/rust/lib.rs @@ -14,6 +14,7 @@ pub mod cpu2; pub mod c_api; pub mod js_api; +pub mod profiler; mod analysis; mod codegen; @@ -29,7 +30,6 @@ mod modrm; mod opstats; mod page; mod prefix; -mod profiler; mod regs; mod state_flags; mod tlb; diff --git a/src/rust/profiler.rs b/src/rust/profiler.rs index 3bae3986..2fb15c7d 100644 --- a/src/rust/profiler.rs +++ b/src/rust/profiler.rs @@ -1,5 +1,4 @@ -#[repr(C)] -#[allow(non_camel_case_types, dead_code)] +#[allow(dead_code, non_camel_case_types)] pub enum stat { S_COMPILE, S_COMPILE_SUCCESS, @@ -49,15 +48,35 @@ pub enum stat { S_TLB_GLOBAL_FULL, } -#[cfg(feature = "profiler")] -mod unsafe_extern { - extern "C" { - pub fn profiler_stat_increment(stat: ::profiler::stat); +#[no_mangle] +pub static mut stat_array: [u32; 100] = [0; 100]; + +pub fn stat_increment(stat: stat) { stat_increment_by(stat, 1); } + +pub fn stat_increment_by(stat: stat, by: u32) { + if cfg!(feature = "profiler") { + unsafe { stat_array[stat as usize] += by } } } -#[cfg(feature = "profiler")] -pub fn stat_increment(stat: stat) { unsafe { unsafe_extern::profiler_stat_increment(stat) } } +#[no_mangle] +pub fn profiler_init() { + unsafe { + for x in stat_array.iter_mut() { + *x = 0 + } + } +} -#[cfg(not(feature = "profiler"))] -pub fn stat_increment(_stat: stat) {} +#[no_mangle] +pub fn profiler_stat_get(stat: stat) -> u32 { + if cfg!(feature = "profiler") { + unsafe { stat_array[stat as usize] } + } + else { + 0 + } +} + +#[no_mangle] +pub fn profiler_stat_increment_do_run() { stat_increment(stat::S_DO_RUN); } From 62dd6be56160decd4b7ca27067eab1d14ac48ed0 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 1 Sep 2018 16:21:09 -0500 Subject: [PATCH 1299/2137] Track missed entry points --- src/browser/print_stats.js | 1 + src/rust/cpu2/cpu.rs | 36 ++++++++++++++++++++++++++++-------- src/rust/profiler.rs | 1 + 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index a564c456..ed9f6c2c 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -25,6 +25,7 @@ const print_stats = { "RUN_INTERPRETED_PENDING", "RUN_INTERPRETED_NEAR_END_OF_PAGE", "RUN_INTERPRETED_DIFFERENT_STATE", + "RUN_INTERPRETED_MISSED_COMPILED_ENTRY", "RUN_INTERPRETED_STEPS", "RUN_FROM_CACHE", "RUN_FROM_CACHE_STEPS", diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 401694d0..ffd4d5cd 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -7,8 +7,8 @@ extern "C" { fn cpu_exception_hook(interrupt: i32) -> bool; #[no_mangle] fn dbg_trace(); - #[no_mangle] - fn logop(addr: i32, op: i32); + //#[no_mangle] + //fn logop(addr: i32, op: i32); #[no_mangle] fn microtick() -> f64; #[no_mangle] @@ -807,8 +807,8 @@ pub unsafe fn cycle_internal() { } else { *previous_ip = *instruction_pointer; - *timestamp_counter += 1; let opcode = return_on_pagefault!(read_imm8()); + *timestamp_counter += 1; run_instruction(opcode | (*is_32 as i32) << 8); } } @@ -831,16 +831,36 @@ unsafe fn jit_run_interpreted(mut phys_addr: i32) { jit_block_boundary = false; let opcode = *mem8.offset(phys_addr as isize) as i32; *instruction_pointer += 1; - *timestamp_counter = (*timestamp_counter).wrapping_add(1); + *timestamp_counter += 1; run_instruction(opcode | (*is_32 as i32) << 8); + while !jit_block_boundary && 0 != same_page(*previous_ip, *instruction_pointer) as i32 { *previous_ip = *instruction_pointer; - *timestamp_counter = (*timestamp_counter).wrapping_add(1); - let mut opcode_0: i32 = return_on_pagefault!(read_imm8()); + let opcode = return_on_pagefault!(read_imm8()); + if DEBUG { - logop(*previous_ip, opcode_0); + let phys_addr = return_on_pagefault!(get_phys_eip()) as u32; + let state_flags: CachedStateFlags = pack_current_state_flags(); + let entry = ::c_api::jit_find_cache_entry(phys_addr, state_flags as u32); + + if entry != 0 { + profiler::stat_increment(S_RUN_INTERPRETED_MISSED_COMPILED_ENTRY); + //dbg_log!( + // "missed entry point at {:x} prev_opcode={:x} opcode={:x}", + // phys_addr, + // prev_opcode, + // opcode + //); + } } - run_instruction(opcode_0 | (*is_32 as i32) << 8); + + *timestamp_counter += 1; + + //if DEBUG { + // logop(*previous_ip, opcode_0); + //} + + run_instruction(opcode | (*is_32 as i32) << 8); } } diff --git a/src/rust/profiler.rs b/src/rust/profiler.rs index 2fb15c7d..fe75ced6 100644 --- a/src/rust/profiler.rs +++ b/src/rust/profiler.rs @@ -12,6 +12,7 @@ pub enum stat { S_RUN_INTERPRETED_PENDING, S_RUN_INTERPRETED_NEAR_END_OF_PAGE, S_RUN_INTERPRETED_DIFFERENT_STATE, + S_RUN_INTERPRETED_MISSED_COMPILED_ENTRY, S_RUN_INTERPRETED_STEPS, S_RUN_FROM_CACHE, From 8919079209369e1c6498a08814fcb6b2184525b2 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 1 Sep 2018 16:24:50 -0500 Subject: [PATCH 1300/2137] Print current state of has_flat_segmentation --- src/browser/print_stats.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index ed9f6c2c..eb26baef 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -75,6 +75,7 @@ const print_stats = { text += "TLB_ENTRIES=" + tlb_entries + " (" + global_tlb_entries + " global, " + nonglobal_tlb_entries + " non-global)\n"; text += "CACHE_UNUSED=" + cpu.v86oxide.exports["jit_unused_cache_stat"]() + "\n"; text += "WASM_TABLE_FREE=" + cpu.v86oxide.exports["jit_get_wasm_table_index_free_list_count"]() + "\n"; + text += "FLAT_SEGMENTS=" + cpu.v86oxide.exports["has_flat_segmentation"]() + "\n"; text += "do_many_cycles avg: " + do_many_cycles_total / do_many_cycles_count + "\n"; From 3cb7f7a0b4159f9a7beae3cc15ac266b0b1f8949 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 1 Sep 2018 17:05:53 -0500 Subject: [PATCH 1301/2137] Clean up casts of physical and virtual addresses --- src/rust/cpu2/arith.rs | 24 ++++----- src/rust/cpu2/cpu.rs | 36 ++++++------- src/rust/cpu2/fpu.rs | 23 ++++---- src/rust/cpu2/instruction_helpers.rs | 16 ++---- src/rust/cpu2/instructions_0f.rs | 4 +- src/rust/cpu2/misc_instr.rs | 79 ++++++++++++++-------------- 6 files changed, 85 insertions(+), 97 deletions(-) diff --git a/src/rust/cpu2/arith.rs b/src/rust/cpu2/arith.rs index 6127c530..d908f17f 100644 --- a/src/rust/cpu2/arith.rs +++ b/src/rust/cpu2/arith.rs @@ -996,33 +996,33 @@ pub unsafe fn bt_mem(mut virt_addr: i32, mut bit_offset: i32) { } #[no_mangle] pub unsafe fn btc_mem(mut virt_addr: i32, mut bit_offset: i32) { - let mut phys_addr: i32 = - return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3))) as i32; - let mut bit_base: i32 = read8(phys_addr as u32); + let mut phys_addr = + return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3))); + let mut bit_base: i32 = read8(phys_addr); bit_offset &= 7; *flags = *flags & !1 | bit_base >> bit_offset & 1; *flags_changed &= !1; - write8(phys_addr as u32, bit_base ^ 1 << bit_offset); + write8(phys_addr, bit_base ^ 1 << bit_offset); } #[no_mangle] pub unsafe fn btr_mem(mut virt_addr: i32, mut bit_offset: i32) { - let mut phys_addr: i32 = - return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3))) as i32; - let mut bit_base: i32 = read8(phys_addr as u32); + let mut phys_addr = + return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3))); + let mut bit_base: i32 = read8(phys_addr); bit_offset &= 7; *flags = *flags & !1 | bit_base >> bit_offset & 1; *flags_changed &= !1; - write8(phys_addr as u32, bit_base & !(1 << bit_offset)); + write8(phys_addr, bit_base & !(1 << bit_offset)); } #[no_mangle] pub unsafe fn bts_mem(mut virt_addr: i32, mut bit_offset: i32) { - let mut phys_addr: i32 = - return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3))) as i32; - let mut bit_base: i32 = read8(phys_addr as u32); + let mut phys_addr = + return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3))); + let mut bit_base: i32 = read8(phys_addr); bit_offset &= 7; *flags = *flags & !1 | bit_base >> bit_offset & 1; *flags_changed &= !1; - write8(phys_addr as u32, bit_base | 1 << bit_offset); + write8(phys_addr, bit_base | 1 << bit_offset); } #[no_mangle] pub unsafe fn bsf16(mut old: i32, mut bit_base: i32) -> i32 { diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index ffd4d5cd..bca4c5ee 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -813,7 +813,7 @@ pub unsafe fn cycle_internal() { } } -pub unsafe fn get_phys_eip() -> Result { +pub unsafe fn get_phys_eip() -> Result { let mut eip: i32 = *instruction_pointer; if 0 != eip & !4095 ^ *last_virt_eip { *eip_phys = (translate_address_read(eip)? ^ eip as u32) as i32; @@ -821,7 +821,7 @@ pub unsafe fn get_phys_eip() -> Result { } let mut phys_addr: u32 = (*eip_phys ^ eip) as u32; dbg_assert!(!in_mapped_range(phys_addr)); - return Ok(phys_addr as i32); + return Ok(phys_addr); } unsafe fn jit_run_interpreted(mut phys_addr: i32) { @@ -965,13 +965,13 @@ pub unsafe fn trigger_gp_non_raising(mut code: i32) { call_interrupt_vector(CPU_EXCEPTION_GP, 0 != 0, 0 != 1, code); } -pub unsafe fn virt_boundary_read16(mut low: i32, mut high: i32) -> i32 { +pub unsafe fn virt_boundary_read16(mut low: u32, mut high: u32) -> i32 { dbg_assert!(low & 4095 == 4095); dbg_assert!(high & 4095 == 0); return read8(low as u32) | read8(high as u32) << 8; } -pub unsafe fn virt_boundary_read32s(mut low: i32, mut high: i32) -> i32 { +pub unsafe fn virt_boundary_read32s(mut low: u32, mut high: u32) -> i32 { dbg_assert!(low & 4095 >= 4093); dbg_assert!(high - 3 & 4095 == low & 4095); let mut mid; @@ -992,14 +992,14 @@ pub unsafe fn virt_boundary_read32s(mut low: i32, mut high: i32) -> i32 { return read8(low as u32) | mid << 8 | read8(high as u32) << 24; } -pub unsafe fn virt_boundary_write16(mut low: i32, mut high: i32, mut value: i32) { +pub unsafe fn virt_boundary_write16(mut low: u32, mut high: u32, mut value: i32) { dbg_assert!(low & 4095 == 4095); dbg_assert!(high & 4095 == 0); write8(low as u32, value); write8(high as u32, value >> 8); } -pub unsafe fn virt_boundary_write32(mut low: i32, mut high: i32, mut value: i32) { +pub unsafe fn virt_boundary_write32(mut low: u32, mut high: u32, mut value: i32) { dbg_assert!(low & 4095 >= 4093); dbg_assert!(high - 3 & 4095 == low & 4095); write8(low as u32, value); @@ -1146,8 +1146,8 @@ pub unsafe fn safe_read64s(mut addr: i32) -> Result { x.u32_0[1] = safe_read32s(addr + 4)? as u32 } else { - let addr_phys = translate_address_read(addr)? as i32; - x.u64_0[0] = read64s(addr_phys as u32) as u64 + let addr_phys = translate_address_read(addr)?; + x.u64_0[0] = read64s(addr_phys) as u64 } Ok(x) } @@ -1159,8 +1159,8 @@ pub unsafe fn safe_read128s(mut addr: i32) -> Result { x.u64_0[1] = safe_read64s(addr + 8)?.u64_0[0] } else { - let addr_phys = translate_address_read(addr)? as i32; - x = read128(addr_phys as u32) + let addr_phys = translate_address_read(addr)?; + x = read128(addr_phys) } Ok(x) } @@ -1191,9 +1191,9 @@ pub unsafe fn safe_write16(mut address: i32, mut value: i32) -> Result<(), ()> { } pub unsafe fn safe_write16_slow(mut addr: i32, mut value: i32) -> Result<(), ()> { - let mut phys_low: i32 = translate_address_write(addr)? as i32; + let mut phys_low = translate_address_write(addr)?; if addr & 4095 == 4095 { - virt_boundary_write16(phys_low, translate_address_write(addr + 1)? as i32, value); + virt_boundary_write16(phys_low, translate_address_write(addr + 1)?, value); } else { write16(phys_low as u32, value); @@ -1248,11 +1248,11 @@ pub unsafe fn safe_write32(mut address: i32, mut value: i32) -> Result<(), ()> { } pub unsafe fn safe_write32_slow(mut addr: i32, mut value: i32) -> Result<(), ()> { - let mut phys_low: i32 = translate_address_write(addr)? as i32; + let mut phys_low = translate_address_write(addr)?; if addr & 4095 > 4096 - 4 { virt_boundary_write32( phys_low, - (translate_address_write(addr + 3 & !3)? | (addr + 3 & 3) as u32) as i32, + translate_address_write(addr + 3 & !3)? | (addr as u32 + 3 & 3), value, ); } @@ -1293,8 +1293,8 @@ pub unsafe fn safe_write64(mut addr: i32, mut value: i64) -> Result<(), ()> { safe_write32(addr + 4, (value >> 32) as i32).unwrap(); } else { - let mut phys: i32 = translate_address_write(addr)? as i32; - write64(phys as u32, value); + let mut phys = translate_address_write(addr)?; + write64(phys, value); }; Ok(()) } @@ -1306,8 +1306,8 @@ pub unsafe fn safe_write128(mut addr: i32, mut value: reg128) -> Result<(), ()> safe_write64(addr + 8, value.u64_0[1] as i64).unwrap(); } else { - let mut phys: i32 = translate_address_write(addr)? as i32; - write128(phys as u32, value); + let mut phys = translate_address_write(addr)?; + write128(phys, value); }; Ok(()) } diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 6c337c66..fe676ca9 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -106,11 +106,11 @@ pub unsafe fn fpu_load_m64(mut addr: i32) -> Result { Ok(v.f64_0) } #[no_mangle] -pub unsafe fn fpu_load_m80(mut addr: u32) -> Result { +pub unsafe fn fpu_load_m80(mut addr: i32) -> Result { let mut value: u64 = safe_read64s(addr as i32)?.u64_0[0]; let mut low: u32 = value as u32; let mut high: u32 = (value >> 32) as u32; - let mut exponent: i32 = safe_read16(addr.wrapping_add(8 as u32) as i32)?; + let mut exponent: i32 = safe_read16(addr.wrapping_add(8) as i32)?; let mut sign: i32 = exponent >> 15; exponent &= !32768; if exponent == 0 { @@ -361,9 +361,7 @@ pub unsafe fn fpu_fldm32(mut addr: i32) { #[no_mangle] pub unsafe fn fpu_fldm64(mut addr: i32) { fpu_push(return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe fn fpu_fldm80(mut addr: i32) { - fpu_push(return_on_pagefault!(fpu_load_m80(addr as u32))); -} +pub unsafe fn fpu_fldm80(mut addr: i32) { fpu_push(return_on_pagefault!(fpu_load_m80(addr))); } #[no_mangle] pub unsafe fn fpu_fmul(mut target_index: i32, mut val: f64) { let mut st0: f64 = fpu_get_st0(); @@ -405,7 +403,7 @@ pub unsafe fn fpu_frstor(mut addr: i32) { let mut i: i32 = 0; while i < 8 { *fpu_st.offset(((i as u32).wrapping_add(*fpu_stack_ptr) & 7 as u32) as isize) = - fpu_load_m80(addr as u32).unwrap(); + fpu_load_m80(addr).unwrap(); addr += 10; i += 1 } @@ -418,8 +416,8 @@ pub unsafe fn fpu_fsave(mut addr: i32) { let mut i: i32 = 0; while i < 8 { fpu_store_m80( - addr as u32, - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(i as u32) & 7 as u32) as isize), + addr, + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(i as u32) & 7) as isize), ); addr += 10; i += 1 @@ -427,7 +425,7 @@ pub unsafe fn fpu_fsave(mut addr: i32) { fpu_finit(); } #[no_mangle] -pub unsafe fn fpu_store_m80(mut addr: u32, mut n: f64) { +pub unsafe fn fpu_store_m80(mut addr: i32, mut n: f64) { let mut double_int_view: f64_int = f64_int { f64_0: n }; let mut sign: u8 = (double_int_view.u8_0[7] as i32 & 128) as u8; let mut exponent: i32 = @@ -460,10 +458,7 @@ pub unsafe fn fpu_store_m80(mut addr: u32, mut n: f64) { addr as i32, (low as u64 & 4294967295 as u64 | (high as u64) << 32) as i64, ).unwrap(); - safe_write16( - addr.wrapping_add(8 as u32) as i32, - (sign as i32) << 8 | exponent, - ).unwrap(); + safe_write16(addr.wrapping_add(8) as i32, (sign as i32) << 8 | exponent).unwrap(); } #[no_mangle] pub unsafe fn fpu_fstenv(mut addr: i32) { @@ -509,7 +504,7 @@ pub unsafe fn fpu_fst(mut r: i32) { #[no_mangle] pub unsafe fn fpu_fst80p(mut addr: i32) { return_on_pagefault!(writable_or_pagefault(addr, 10)); - fpu_store_m80(addr as u32, fpu_get_st0()); + fpu_store_m80(addr, fpu_get_st0()); fpu_pop(); } #[no_mangle] diff --git a/src/rust/cpu2/instruction_helpers.rs b/src/rust/cpu2/instruction_helpers.rs index 5c0bb79b..f63d9d38 100644 --- a/src/rust/cpu2/instruction_helpers.rs +++ b/src/rust/cpu2/instruction_helpers.rs @@ -20,7 +20,6 @@ macro_rules! SAFE_READ_WRITE16 { *page_fault = true; }, Ok(phys_addr) => { - let phys_addr = phys_addr as i32; if phys_addr & 0xFFF == 0xFFF { match translate_address_write($addr + 1) { Err(()) => { @@ -28,7 +27,6 @@ macro_rules! SAFE_READ_WRITE16 { }, Ok(phys_addr_high) => { *page_fault = false; - let phys_addr_high = phys_addr_high as i32; let $value = virt_boundary_read16(phys_addr, phys_addr_high); virt_boundary_write16(phys_addr, phys_addr_high, $instruction); }, @@ -36,8 +34,8 @@ macro_rules! SAFE_READ_WRITE16 { } else { *page_fault = false; - let $value = read16(phys_addr as u32); - write16(phys_addr as u32, $instruction); + let $value = read16(phys_addr); + write16(phys_addr, $instruction); } }, } @@ -59,13 +57,9 @@ macro_rules! SAFE_READ_WRITE32 { }, Ok(phys_addr_high) => { *page_fault = false; - let phys_addr_high = phys_addr_high as i32 | $addr + 3 & 3; - let $value = virt_boundary_read32s(phys_addr as i32, phys_addr_high); - virt_boundary_write32( - phys_addr as i32, - phys_addr_high as i32, - $instruction, - ); + let phys_addr_high = phys_addr_high | ($addr as u32) + 3 & 3; + let $value = virt_boundary_read32s(phys_addr, phys_addr_high); + virt_boundary_write32(phys_addr, phys_addr_high, $instruction); }, } } diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index ad4faca4..14ed1fc8 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -3297,11 +3297,11 @@ pub unsafe fn instr32_0FAD_reg(mut r1: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_0FAE_0_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FAE_0_mem(mut addr: i32) { fxsave(addr as u32); } +pub unsafe fn instr_0FAE_0_mem(mut addr: i32) { fxsave(addr); } #[no_mangle] pub unsafe fn instr_0FAE_1_reg(mut r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FAE_1_mem(mut addr: i32) { fxrstor(addr as u32); } +pub unsafe fn instr_0FAE_1_mem(mut addr: i32) { fxrstor(addr); } #[no_mangle] pub unsafe fn instr_0FAE_2_reg(mut r: i32) { unimplemented_sse(); } #[no_mangle] diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index 22609662..82ba657a 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -327,23 +327,23 @@ pub unsafe fn setcc_mem(mut condition: bool, mut addr: i32) { return_on_pagefault!(safe_write8(addr, if 0 != condition as i32 { 1 } else { 0 })); } #[no_mangle] -pub unsafe fn fxsave(mut addr: u32) { +pub unsafe fn fxsave(mut addr: i32) { return_on_pagefault!(writable_or_pagefault(addr as i32, 512)); - safe_write16(addr.wrapping_add(0 as u32) as i32, *fpu_control_word).unwrap(); - safe_write16(addr.wrapping_add(2 as u32) as i32, fpu_load_status_word()).unwrap(); - safe_write8(addr.wrapping_add(4 as u32) as i32, !*fpu_stack_empty & 255).unwrap(); - safe_write16(addr.wrapping_add(6 as u32) as i32, *fpu_opcode).unwrap(); - safe_write32(addr.wrapping_add(8 as u32) as i32, *fpu_ip).unwrap(); - safe_write16(addr.wrapping_add(12 as u32) as i32, *fpu_ip_selector).unwrap(); - safe_write32(addr.wrapping_add(16 as u32) as i32, *fpu_dp).unwrap(); - safe_write16(addr.wrapping_add(20 as u32) as i32, *fpu_dp_selector).unwrap(); - safe_write32(addr.wrapping_add(24 as u32) as i32, *mxcsr).unwrap(); - safe_write32(addr.wrapping_add(28 as u32) as i32, MXCSR_MASK).unwrap(); + safe_write16(addr.wrapping_add(0) as i32, *fpu_control_word).unwrap(); + safe_write16(addr.wrapping_add(2) as i32, fpu_load_status_word()).unwrap(); + safe_write8(addr.wrapping_add(4) as i32, !*fpu_stack_empty & 255).unwrap(); + safe_write16(addr.wrapping_add(6) as i32, *fpu_opcode).unwrap(); + safe_write32(addr.wrapping_add(8) as i32, *fpu_ip).unwrap(); + safe_write16(addr.wrapping_add(12) as i32, *fpu_ip_selector).unwrap(); + safe_write32(addr.wrapping_add(16) as i32, *fpu_dp).unwrap(); + safe_write16(addr.wrapping_add(20) as i32, *fpu_dp_selector).unwrap(); + safe_write32(addr.wrapping_add(24) as i32, *mxcsr).unwrap(); + safe_write32(addr.wrapping_add(28) as i32, MXCSR_MASK).unwrap(); let mut i: i32 = 0; while i < 8 { fpu_store_m80( - addr.wrapping_add(32 as u32).wrapping_add((i << 4) as u32), - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(i as u32) & 7 as u32) as isize), + addr.wrapping_add(32).wrapping_add(i << 4), + *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(i as u32) & 7) as isize), ); i += 1 } @@ -353,61 +353,60 @@ pub unsafe fn fxsave(mut addr: u32) { let mut i_0: i32 = 0; while i_0 < 8 { safe_write128( - addr.wrapping_add(160 as u32) - .wrapping_add((i_0 << 4) as u32) as i32, + addr.wrapping_add(160).wrapping_add(i_0 << 4) as i32, *reg_xmm.offset(i_0 as isize), ).unwrap(); i_0 += 1 } } #[no_mangle] -pub unsafe fn fxrstor(mut addr: u32) { +pub unsafe fn fxrstor(mut addr: i32) { // TODO: Add readable_or_pagefault - return_on_pagefault!(translate_address_read(addr as i32)); - return_on_pagefault!(translate_address_read(addr.wrapping_add(511 as u32) as i32)); - let mut new_mxcsr: i32 = safe_read32s(addr.wrapping_add(24 as u32) as i32).unwrap(); + return_on_pagefault!(translate_address_read(addr)); + return_on_pagefault!(translate_address_read(addr.wrapping_add(511))); + let mut new_mxcsr: i32 = safe_read32s(addr.wrapping_add(24) as i32).unwrap(); if 0 != new_mxcsr & !MXCSR_MASK { dbg_log!("#gp Invalid mxcsr bits"); trigger_gp_non_raising(0); return; } else { - *fpu_control_word = safe_read16(addr.wrapping_add(0 as u32) as i32).unwrap(); - fpu_set_status_word(safe_read16(addr.wrapping_add(2 as u32) as i32).unwrap()); - *fpu_stack_empty = !safe_read8(addr.wrapping_add(4 as u32) as i32).unwrap() & 255; - *fpu_opcode = safe_read16(addr.wrapping_add(6 as u32) as i32).unwrap(); - *fpu_ip = safe_read32s(addr.wrapping_add(8 as u32) as i32).unwrap(); - *fpu_ip = safe_read16(addr.wrapping_add(12 as u32) as i32).unwrap(); - *fpu_dp = safe_read32s(addr.wrapping_add(16 as u32) as i32).unwrap(); - *fpu_dp_selector = safe_read16(addr.wrapping_add(20 as u32) as i32).unwrap(); + *fpu_control_word = safe_read16(addr.wrapping_add(0) as i32).unwrap(); + fpu_set_status_word(safe_read16(addr.wrapping_add(2) as i32).unwrap()); + *fpu_stack_empty = !safe_read8(addr.wrapping_add(4) as i32).unwrap() & 255; + *fpu_opcode = safe_read16(addr.wrapping_add(6) as i32).unwrap(); + *fpu_ip = safe_read32s(addr.wrapping_add(8) as i32).unwrap(); + *fpu_ip = safe_read16(addr.wrapping_add(12) as i32).unwrap(); + *fpu_dp = safe_read32s(addr.wrapping_add(16) as i32).unwrap(); + *fpu_dp_selector = safe_read16(addr.wrapping_add(20) as i32).unwrap(); set_mxcsr(new_mxcsr); let mut i: i32 = 0; while i < 8 { *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(i as u32) & 7 as u32) as isize) = - fpu_load_m80(addr.wrapping_add(32 as u32).wrapping_add((i << 4) as u32)).unwrap(); + fpu_load_m80(addr.wrapping_add(32).wrapping_add(i << 4)).unwrap(); i += 1 } let mut i_0: i32 = 0; while i_0 < 8 { (*reg_xmm.offset(i_0 as isize)).u32_0[0] = safe_read32s( - addr.wrapping_add(160 as u32) - .wrapping_add((i_0 << 4) as u32) - .wrapping_add(0 as u32) as i32, + addr.wrapping_add(160) + .wrapping_add(i_0 << 4) + .wrapping_add(0), ).unwrap() as u32; (*reg_xmm.offset(i_0 as isize)).u32_0[1] = safe_read32s( - addr.wrapping_add(160 as u32) - .wrapping_add((i_0 << 4) as u32) - .wrapping_add(4 as u32) as i32, + addr.wrapping_add(160) + .wrapping_add(i_0 << 4) + .wrapping_add(4) as i32, ).unwrap() as u32; (*reg_xmm.offset(i_0 as isize)).u32_0[2] = safe_read32s( - addr.wrapping_add(160 as u32) - .wrapping_add((i_0 << 4) as u32) - .wrapping_add(8 as u32) as i32, + addr.wrapping_add(160) + .wrapping_add(i_0 << 4) + .wrapping_add(8) as i32, ).unwrap() as u32; (*reg_xmm.offset(i_0 as isize)).u32_0[3] = safe_read32s( - addr.wrapping_add(160 as u32) - .wrapping_add((i_0 << 4) as u32) - .wrapping_add(12 as u32) as i32, + addr.wrapping_add(160) + .wrapping_add(i_0 << 4) + .wrapping_add(12) as i32, ).unwrap() as u32; i_0 += 1 } From 22ba923f9a78a58682e74bc7e41dd8684416130b Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 1 Sep 2018 17:18:49 -0500 Subject: [PATCH 1302/2137] Track number of module invalidations --- src/browser/print_stats.js | 3 +++ src/rust/jit.rs | 12 ++++++++++++ src/rust/profiler.rs | 4 ++++ 3 files changed, 19 insertions(+) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index eb26baef..a13b8075 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -46,7 +46,10 @@ const print_stats = { "DO_MANY_CYCLES", "CYCLE_INTERNAL", "INVALIDATE_PAGE", + "INVALIDATE_MODULE", "INVALIDATE_CACHE_ENTRY", + "INVALIDATE_MODULE_CACHE_FULL", + "INVALIDATE_SINGLE_ENTRY_CACHE_FULL", "NONFAULTING_OPTIMIZATION", "CLEAR_TLB", "FULL_CLEAR_TLB", diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 7589550b..63907439 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -695,6 +695,8 @@ fn create_cache_entry(ctx: &mut JitState, entry: jit_cache_array::Entry) { dbg_assert!(old_entry.wasm_table_index != 0); if old_entry.wasm_table_index == entry.wasm_table_index { + profiler::stat_increment(stat::S_INVALIDATE_SINGLE_ENTRY_CACHE_FULL); + dbg_assert!(old_entry.pending); dbg_assert!(Page::page_of(old_entry.start_addr) == Page::page_of(phys_addr)); @@ -710,6 +712,8 @@ fn create_cache_entry(ctx: &mut JitState, entry: jit_cache_array::Entry) { old_entry.start_addr = 0; } else { + profiler::stat_increment(stat::S_INVALIDATE_MODULE_CACHE_FULL); + let old_wasm_table_index = old_entry.wasm_table_index; let old_page = Page::page_of(old_entry.start_addr); @@ -1257,11 +1261,14 @@ pub fn jit_dirty_page(ctx: &mut JitState, page: Page) { entry.wasm_table_index = 0; if entry.pending { + dbg_assert!(!index_to_free.contains(&wasm_table_index)); + entry.pending = false; index_to_pending_free.insert(wasm_table_index); } else { + dbg_assert!(!index_to_pending_free.contains(&wasm_table_index)); index_to_free.insert(wasm_table_index); } @@ -1273,6 +1280,11 @@ pub fn jit_dirty_page(ctx: &mut JitState, page: Page) { } } + profiler::stat_increment_by( + stat::S_INVALIDATE_MODULE, + index_to_pending_free.len() as u32 + index_to_free.len() as u32, + ); + for index in index_to_free.iter().cloned() { free_wasm_table_index(ctx, index) } diff --git a/src/rust/profiler.rs b/src/rust/profiler.rs index fe75ced6..684ef06c 100644 --- a/src/rust/profiler.rs +++ b/src/rust/profiler.rs @@ -39,8 +39,12 @@ pub enum stat { S_CYCLE_INTERNAL, S_INVALIDATE_PAGE, + S_INVALIDATE_MODULE, S_INVALIDATE_CACHE_ENTRY, + S_INVALIDATE_MODULE_CACHE_FULL, + S_INVALIDATE_SINGLE_ENTRY_CACHE_FULL, + S_NONFAULTING_OPTIMIZATION, S_CLEAR_TLB, From 36a46bca80ed6bb237cb4b9fbf0d9994d10742ff Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 1 Sep 2018 17:42:33 -0500 Subject: [PATCH 1303/2137] Remove non-faulting stat --- src/browser/print_stats.js | 1 - src/rust/profiler.rs | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index a13b8075..80d27640 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -50,7 +50,6 @@ const print_stats = { "INVALIDATE_CACHE_ENTRY", "INVALIDATE_MODULE_CACHE_FULL", "INVALIDATE_SINGLE_ENTRY_CACHE_FULL", - "NONFAULTING_OPTIMIZATION", "CLEAR_TLB", "FULL_CLEAR_TLB", "TLB_FULL", diff --git a/src/rust/profiler.rs b/src/rust/profiler.rs index 684ef06c..4d7fb293 100644 --- a/src/rust/profiler.rs +++ b/src/rust/profiler.rs @@ -45,8 +45,6 @@ pub enum stat { S_INVALIDATE_MODULE_CACHE_FULL, S_INVALIDATE_SINGLE_ENTRY_CACHE_FULL, - S_NONFAULTING_OPTIMIZATION, - S_CLEAR_TLB, S_FULL_CLEAR_TLB, S_TLB_FULL, From fcdda9487e0aa29cf83bf888a6c1df8fe106399a Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 1 Sep 2018 22:03:36 -0500 Subject: [PATCH 1304/2137] handle_irqs: Do interrupt flag check from Rust --- src/browser/starter.js | 2 +- src/cpu.js | 25 ++++++++++++++++--------- src/rust/cpu2/cpu.rs | 8 ++++++++ src/rust/cpu2/instructions.rs | 2 -- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 89b2c0d7..86443bc0 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -188,7 +188,7 @@ function V86Starter(options) "switch_seg": function(reg, selector) { return cpu.switch_seg(reg, selector); }, "iret16": function() { return cpu.iret16(); }, "iret32": function() { return cpu.iret32(); }, - "handle_irqs": function() { return cpu.handle_irqs(); }, + "pic_acknowledge": function() { cpu.pic_acknowledge(); }, "io_port_read8": function(addr) { return cpu.io.port_read8(addr); }, "io_port_read16": function(addr) { return cpu.io.port_read16(addr); }, diff --git a/src/cpu.js b/src/cpu.js index fca9b98b..10cc240b 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -2964,17 +2964,24 @@ CPU.prototype.handle_irqs = function() { //dbg_assert(this.prefixes[0] === 0); - if((this.flags[0] & flag_interrupt)) + if(this.flags[0] & flag_interrupt) { - if(this.devices.pic) - { - this.devices.pic.acknowledge_irq(); - } + this.pic_acknowledge(); + } +}; - if(this.devices.apic) - { - this.devices.apic.acknowledge_irq(); - } +CPU.prototype.pic_acknowledge = function() +{ + dbg_assert(this.flags[0] & flag_interrupt); + + if(this.devices.pic) + { + this.devices.pic.acknowledge_irq(); + } + + if(this.devices.apic) + { + this.devices.apic.acknowledge_irq(); } }; diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index bca4c5ee..a67b48bb 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -13,6 +13,8 @@ extern "C" { fn microtick() -> f64; #[no_mangle] fn call_indirect1(f: i32, x: u16); + #[no_mangle] + fn pic_acknowledge(); } use cpu2::global_pointers::*; @@ -1720,3 +1722,9 @@ pub unsafe fn trigger_ss(mut code: i32) { #[no_mangle] pub unsafe fn store_current_tsc() { *current_tsc = read_tsc(); } + +pub unsafe fn handle_irqs() { + if *flags & FLAG_INTERRUPT != 0 { + pic_acknowledge() + } +} diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index c4e70d94..1d97c393 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -29,8 +29,6 @@ extern "C" { #[no_mangle] fn iret32(); - #[no_mangle] - fn handle_irqs(); #[no_mangle] fn hlt_op(); } From b70a5c081a456ff1e8cf8df340e2a76c7cd4187f Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 2 Sep 2018 21:11:04 -0500 Subject: [PATCH 1305/2137] Allow fast path for memory reads from pages that contain code --- src/rust/codegen.rs | 14 +++++++++----- src/rust/tlb.rs | 2 +- tests/expect/tests/call.wast | 2 +- tests/expect/tests/mov16.wast | 4 ++-- tests/expect/tests/mov32-mem.wast | 4 ++-- tests/expect/tests/pop.wast | 2 +- 6 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 2e441963..06884975 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -3,7 +3,7 @@ use global_pointers; use jit::JitContext; use modrm; use regs; -use tlb::{TLB_GLOBAL, TLB_NO_USER, TLB_READONLY, TLB_VALID}; +use tlb::{TLB_GLOBAL, TLB_HAS_CODE, TLB_NO_USER, TLB_READONLY, TLB_VALID}; use wasmgen::module_init; use wasmgen::module_init::{WasmBuilder, WasmLocal}; use wasmgen::wasm_util::WasmBuf; @@ -251,11 +251,15 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { .load_aligned_i32_from_stack(global_pointers::TLB_DATA); let entry_local = builder.tee_new_local(); - // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && - // (bitsize == 8 ? true : (address & 0xFFF) <= (0x1000 - (bitsize / 8))); + // Pseudo: bool can_use_fast_path = + // (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~TLB_HAS_CODE & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && + // (bitsize == 8 ? true : (address & 0xFFF) <= (0x1000 - (bitsize / 8))); builder.instruction_body.const_i32( - (0xFFF & !TLB_READONLY & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) - as i32, + (0xFFF + & !TLB_READONLY + & !TLB_GLOBAL + & !TLB_HAS_CODE + & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32, ); builder.instruction_body.and_i32(); diff --git a/src/rust/tlb.rs b/src/rust/tlb.rs index c13856f8..c4cde771 100644 --- a/src/rust/tlb.rs +++ b/src/rust/tlb.rs @@ -3,4 +3,4 @@ pub const TLB_READONLY: u32 = (1 << 1); pub const TLB_NO_USER: u32 = (1 << 2); //const TLB_IN_MAPPED_RANGE: u32 = (1 << 3); pub const TLB_GLOBAL: u32 = (1 << 4); -//const TLB_HAS_CODE: u32 = (1 << 5); +pub const TLB_HAS_CODE: u32 = (1 << 5); diff --git a/tests/expect/tests/call.wast b/tests/expect/tests/call.wast index 84bdc6b7..7eb5478e 100644 --- a/tests/expect/tests/call.wast +++ b/tests/expect/tests/call.wast @@ -160,7 +160,7 @@ (i32.const 744)))) (i32.const 12)) (i32.const 2)))) - (i32.const 4073)) + (i32.const 4041)) (i32.const 1)) (i32.le_s (i32.and diff --git a/tests/expect/tests/mov16.wast b/tests/expect/tests/mov16.wast index 2019d4cf..0a89a35a 100644 --- a/tests/expect/tests/mov16.wast +++ b/tests/expect/tests/mov16.wast @@ -40,7 +40,7 @@ (i32.const 3)))) (i32.const 12)) (i32.const 2)))) - (i32.const 4073)) + (i32.const 4041)) (i32.const 1)) (i32.le_s (i32.and @@ -87,7 +87,7 @@ (i32.const 3)))) (i32.const 12)) (i32.const 2)))) - (i32.const 4073)) + (i32.const 4041)) (i32.const 1)) (i32.le_s (i32.and diff --git a/tests/expect/tests/mov32-mem.wast b/tests/expect/tests/mov32-mem.wast index d6af9123..61b1f892 100644 --- a/tests/expect/tests/mov32-mem.wast +++ b/tests/expect/tests/mov32-mem.wast @@ -148,7 +148,7 @@ (i32.const 3)))) (i32.const 12)) (i32.const 2)))) - (i32.const 4073)) + (i32.const 4041)) (i32.const 1)) (i32.le_s (i32.and @@ -198,7 +198,7 @@ (i32.const 3)))) (i32.const 12)) (i32.const 2)))) - (i32.const 4073)) + (i32.const 4041)) (i32.const 1)) (i32.le_s (i32.and diff --git a/tests/expect/tests/pop.wast b/tests/expect/tests/pop.wast index 14e0f72f..386202d3 100644 --- a/tests/expect/tests/pop.wast +++ b/tests/expect/tests/pop.wast @@ -37,7 +37,7 @@ (i32.const 744)))) (i32.const 12)) (i32.const 2)))) - (i32.const 4073)) + (i32.const 4041)) (i32.const 1)) (i32.le_s (i32.and From bf895ff1b20e6faf8523286bf045148f239c76cd Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 2 Sep 2018 21:09:13 -0500 Subject: [PATCH 1306/2137] profiler: Keep track of fast/slow path for jitted memory access --- src/browser/print_stats.js | 24 +++++++------- src/rust/codegen.rs | 46 +++++++++++++++++++++++--- src/rust/cpu2/cpu.rs | 66 +++++++++++++++++++++++++++++++------- src/rust/profiler.rs | 24 +++++++------- 4 files changed, 120 insertions(+), 40 deletions(-) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index 80d27640..0bc8f0c4 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -30,18 +30,18 @@ const print_stats = { "RUN_FROM_CACHE", "RUN_FROM_CACHE_STEPS", "TRIGGER_CPU_EXCEPTION", - "SAFE_READ32_FAST", - "SAFE_READ32_SLOW_PAGE_CROSSED", - "SAFE_READ32_SLOW_NOT_VALID", - "SAFE_READ32_SLOW_NOT_USER", - "SAFE_READ32_SLOW_IN_MAPPED_RANGE", - "SAFE_WRITE32_FAST", - "SAFE_WRITE32_SLOW_PAGE_CROSSED", - "SAFE_WRITE32_SLOW_NOT_VALID", - "SAFE_WRITE32_SLOW_NOT_USER", - "SAFE_WRITE32_SLOW_IN_MAPPED_RANGE", - "SAFE_WRITE32_SLOW_READ_ONLY", - "SAFE_WRITE32_SLOW_HAS_CODE", + "SAFE_READ_FAST", + "SAFE_READ_SLOW_PAGE_CROSSED", + "SAFE_READ_SLOW_NOT_VALID", + "SAFE_READ_SLOW_NOT_USER", + "SAFE_READ_SLOW_IN_MAPPED_RANGE", + "SAFE_WRITE_FAST", + "SAFE_WRITE_SLOW_PAGE_CROSSED", + "SAFE_WRITE_SLOW_NOT_VALID", + "SAFE_WRITE_SLOW_NOT_USER", + "SAFE_WRITE_SLOW_IN_MAPPED_RANGE", + "SAFE_WRITE_SLOW_READ_ONLY", + "SAFE_WRITE_SLOW_HAS_CODE", "DO_RUN", "DO_MANY_CYCLES", "CYCLE_INTERNAL", diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 06884975..687aa998 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -2,6 +2,7 @@ use cpu::BitSize; use global_pointers; use jit::JitContext; use modrm; +use profiler; use regs; use tlb::{TLB_GLOBAL, TLB_HAS_CODE, TLB_NO_USER, TLB_READONLY, TLB_VALID}; use wasmgen::module_init; @@ -281,6 +282,11 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { // Pseudo: // if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]); builder.instruction_body.if_i32(); + + if cfg!(feature = "profiler") { + gen_profiler_stat_increment(builder, profiler::stat::S_SAFE_READ_FAST); + } + builder.instruction_body.get_local(&entry_local); builder.instruction_body.const_i32(!0xFFF); builder.instruction_body.and_i32(); @@ -313,6 +319,12 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { // } builder.instruction_body.else_(); + if cfg!(feature = "profiler") { + builder.instruction_body.get_local(&address_local); + builder.instruction_body.get_local(&entry_local); + gen_call_fn2(builder, "report_safe_read_jit_slow"); + } + builder .instruction_body .const_i32(global_pointers::PREVIOUS_IP as i32); @@ -410,14 +422,16 @@ fn gen_safe_write( // phys_addr = entry & ~0xFFF ^ address; builder.instruction_body.if_void(); + if cfg!(feature = "profiler") { + gen_profiler_stat_increment(builder, profiler::stat::S_SAFE_WRITE_FAST); + } + builder.instruction_body.get_local(&entry_local); builder.instruction_body.const_i32(!0xFFF); builder.instruction_body.and_i32(); builder.instruction_body.get_local(&address_local); builder.instruction_body.xor_i32(); - builder.free_local(entry_local); - // Pseudo: // /* continued within can_use_fast_path branch */ // mem8[phys_addr] = value; @@ -447,6 +461,12 @@ fn gen_safe_write( // } builder.instruction_body.else_(); + if cfg!(feature = "profiler") { + builder.instruction_body.get_local(&address_local); + builder.instruction_body.get_local(&entry_local); + gen_call_fn2(builder, "report_safe_write_jit_slow"); + } + builder .instruction_body .const_i32(global_pointers::PREVIOUS_IP as i32); @@ -486,6 +506,8 @@ fn gen_safe_write( builder.instruction_body.block_end(); builder.instruction_body.block_end(); + + builder.free_local(entry_local); } pub fn gen_clear_prefixes(ctx: &mut JitContext) { @@ -840,6 +862,11 @@ pub fn gen_safe_read_write( // Pseudo: // if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]); ctx.builder.instruction_body.if_void(); + + if cfg!(feature = "profiler") { + gen_profiler_stat_increment(ctx.builder, profiler::stat::S_SAFE_WRITE_FAST); + } + ctx.builder.instruction_body.get_local(&entry_local); ctx.builder.instruction_body.const_i32(!0xFFF); ctx.builder.instruction_body.and_i32(); @@ -864,8 +891,6 @@ pub fn gen_safe_read_write( }, } - ctx.builder.free_local(entry_local); - f(ctx); match bits { @@ -891,6 +916,12 @@ pub fn gen_safe_read_write( // } ctx.builder.instruction_body.else_(); + if cfg!(feature = "profiler") { + ctx.builder.instruction_body.get_local(&address_local); + ctx.builder.instruction_body.get_local(&entry_local); + gen_call_fn2(ctx.builder, "report_safe_write_jit_slow"); + } + ctx.builder .instruction_body .const_i32(global_pointers::PREVIOUS_IP as i32); @@ -920,4 +951,11 @@ pub fn gen_safe_read_write( ctx.builder.instruction_body.block_end(); ctx.builder.instruction_body.block_end(); + + ctx.builder.free_local(entry_local); +} + +pub fn gen_profiler_stat_increment(builder: &mut WasmBuilder, stat: profiler::stat) { + let addr = unsafe { profiler::stat_array.as_mut_ptr().offset(stat as isize) } as u32; + gen_increment_variable(builder, addr, 1) } diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index a67b48bb..d442bc6e 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1060,7 +1060,7 @@ pub unsafe fn safe_read32s(mut address: i32) -> Result { let mut info_bits: i32 = entry & 4095 & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; if info_bits == TLB_VALID && address & 4095 <= 4096 - 4 { if false { - profiler::stat_increment(S_SAFE_READ32_FAST); + profiler::stat_increment(S_SAFE_READ_FAST); } // - not in memory mapped area // - can be accessed from any cpl @@ -1071,16 +1071,16 @@ pub unsafe fn safe_read32s(mut address: i32) -> Result { else { if false { if address & 4095 > 4096 - 4 { - profiler::stat_increment(S_SAFE_READ32_SLOW_PAGE_CROSSED); + profiler::stat_increment(S_SAFE_READ_SLOW_PAGE_CROSSED); } else if info_bits & TLB_VALID == 0 { - profiler::stat_increment(S_SAFE_READ32_SLOW_NOT_VALID); + profiler::stat_increment(S_SAFE_READ_SLOW_NOT_VALID); } else if 0 != info_bits & TLB_NO_USER { - profiler::stat_increment(S_SAFE_READ32_SLOW_NOT_USER); + profiler::stat_increment(S_SAFE_READ_SLOW_NOT_USER); } else if 0 != info_bits & TLB_IN_MAPPED_RANGE { - profiler::stat_increment(S_SAFE_READ32_SLOW_IN_MAPPED_RANGE); + profiler::stat_increment(S_SAFE_READ_SLOW_IN_MAPPED_RANGE); } else { dbg_assert!(0 != 0); @@ -1090,6 +1090,48 @@ pub unsafe fn safe_read32s(mut address: i32) -> Result { }; } +#[no_mangle] +#[cfg(feature = "profiler")] +pub fn report_safe_read_jit_slow(address: u32, entry: i32) { + if entry & TLB_VALID == 0 { + profiler::stat_increment(S_SAFE_READ_SLOW_NOT_VALID); + } + else if entry & TLB_IN_MAPPED_RANGE != 0 { + profiler::stat_increment(S_SAFE_READ_SLOW_IN_MAPPED_RANGE); + } + else if address & 0xFFF > 0x1000 - 4 { + profiler::stat_increment(S_SAFE_READ_SLOW_PAGE_CROSSED); + } + else { + // NOT_USER is not possible since gen_safe_read generates a mask for cpl0 + dbg_assert!(false); + } +} + +#[no_mangle] +#[cfg(feature = "profiler")] +pub fn report_safe_write_jit_slow(address: u32, entry: i32) { + if entry & TLB_VALID == 0 { + profiler::stat_increment(S_SAFE_WRITE_SLOW_NOT_VALID); + } + else if entry & TLB_IN_MAPPED_RANGE != 0 { + profiler::stat_increment(S_SAFE_WRITE_SLOW_IN_MAPPED_RANGE); + } + else if entry & TLB_HAS_CODE != 0 { + profiler::stat_increment(S_SAFE_WRITE_SLOW_HAS_CODE); + } + else if entry & TLB_READONLY != 0 { + profiler::stat_increment(S_SAFE_WRITE_SLOW_READ_ONLY); + } + else if address & 0xFFF > 0x1000 - 4 { + profiler::stat_increment(S_SAFE_WRITE_SLOW_PAGE_CROSSED); + } + else { + // NOT_USER is not possible since gen_safe_write generates a mask for for cpl0 + dbg_assert!(false); + } +} + pub unsafe fn safe_read32s_slow(mut addr: i32) -> Result { if addr & 4095 >= 4093 { return Ok(safe_read16(addr)? | safe_read16(addr + 2)? << 16); @@ -1210,7 +1252,7 @@ pub unsafe fn safe_write32(mut address: i32, mut value: i32) -> Result<(), ()> { entry & 4095 & !TLB_GLOBAL & !if *cpl as i32 == 3 { 0 } else { TLB_NO_USER }; if info_bits == TLB_VALID && address & 4095 <= 4096 - 4 { if false { - profiler::stat_increment(S_SAFE_WRITE32_FAST); + profiler::stat_increment(S_SAFE_WRITE_FAST); } // - allowed to write in user-mode // - not in memory mapped area @@ -1223,22 +1265,22 @@ pub unsafe fn safe_write32(mut address: i32, mut value: i32) -> Result<(), ()> { else { if false { if address & 4095 > 4096 - 4 { - profiler::stat_increment(S_SAFE_WRITE32_SLOW_PAGE_CROSSED); + profiler::stat_increment(S_SAFE_WRITE_SLOW_PAGE_CROSSED); } else if info_bits & TLB_VALID == 0 { - profiler::stat_increment(S_SAFE_WRITE32_SLOW_NOT_VALID); + profiler::stat_increment(S_SAFE_WRITE_SLOW_NOT_VALID); } else if 0 != info_bits & TLB_NO_USER { - profiler::stat_increment(S_SAFE_WRITE32_SLOW_NOT_USER); + profiler::stat_increment(S_SAFE_WRITE_SLOW_NOT_USER); } else if 0 != info_bits & TLB_IN_MAPPED_RANGE { - profiler::stat_increment(S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE); + profiler::stat_increment(S_SAFE_WRITE_SLOW_IN_MAPPED_RANGE); } else if 0 != info_bits & TLB_READONLY { - profiler::stat_increment(S_SAFE_WRITE32_SLOW_READ_ONLY); + profiler::stat_increment(S_SAFE_WRITE_SLOW_READ_ONLY); } else if 0 != info_bits & TLB_HAS_CODE { - profiler::stat_increment(S_SAFE_WRITE32_SLOW_HAS_CODE); + profiler::stat_increment(S_SAFE_WRITE_SLOW_HAS_CODE); } else { dbg_assert!(0 != 0); diff --git a/src/rust/profiler.rs b/src/rust/profiler.rs index 4d7fb293..9076b602 100644 --- a/src/rust/profiler.rs +++ b/src/rust/profiler.rs @@ -20,19 +20,19 @@ pub enum stat { S_TRIGGER_CPU_EXCEPTION, - S_SAFE_READ32_FAST, - S_SAFE_READ32_SLOW_PAGE_CROSSED, - S_SAFE_READ32_SLOW_NOT_VALID, - S_SAFE_READ32_SLOW_NOT_USER, - S_SAFE_READ32_SLOW_IN_MAPPED_RANGE, + S_SAFE_READ_FAST, + S_SAFE_READ_SLOW_PAGE_CROSSED, + S_SAFE_READ_SLOW_NOT_VALID, + S_SAFE_READ_SLOW_NOT_USER, + S_SAFE_READ_SLOW_IN_MAPPED_RANGE, - S_SAFE_WRITE32_FAST, - S_SAFE_WRITE32_SLOW_PAGE_CROSSED, - S_SAFE_WRITE32_SLOW_NOT_VALID, - S_SAFE_WRITE32_SLOW_NOT_USER, - S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE, - S_SAFE_WRITE32_SLOW_READ_ONLY, - S_SAFE_WRITE32_SLOW_HAS_CODE, + S_SAFE_WRITE_FAST, + S_SAFE_WRITE_SLOW_PAGE_CROSSED, + S_SAFE_WRITE_SLOW_NOT_VALID, + S_SAFE_WRITE_SLOW_NOT_USER, + S_SAFE_WRITE_SLOW_IN_MAPPED_RANGE, + S_SAFE_WRITE_SLOW_READ_ONLY, + S_SAFE_WRITE_SLOW_HAS_CODE, S_DO_RUN, S_DO_MANY_CYCLES, From 83febd13768a492bbc8e19d65c41e41ced2dee65 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 2 Sep 2018 21:16:42 -0500 Subject: [PATCH 1307/2137] Remove duplicated constants (TLB_*) --- src/rust/codegen.rs | 2 +- src/rust/lib.rs | 1 - src/rust/tlb.rs | 6 ------ 3 files changed, 1 insertion(+), 8 deletions(-) delete mode 100644 src/rust/tlb.rs diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 687aa998..6a6f4da2 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -1,10 +1,10 @@ use cpu::BitSize; +use cpu2::cpu::{TLB_GLOBAL, TLB_HAS_CODE, TLB_NO_USER, TLB_READONLY, TLB_VALID}; use global_pointers; use jit::JitContext; use modrm; use profiler; use regs; -use tlb::{TLB_GLOBAL, TLB_HAS_CODE, TLB_NO_USER, TLB_READONLY, TLB_VALID}; use wasmgen::module_init; use wasmgen::module_init::{WasmBuilder, WasmLocal}; use wasmgen::wasm_util::WasmBuf; diff --git a/src/rust/lib.rs b/src/rust/lib.rs index e5e63160..aaf670fa 100644 --- a/src/rust/lib.rs +++ b/src/rust/lib.rs @@ -32,6 +32,5 @@ mod page; mod prefix; mod regs; mod state_flags; -mod tlb; mod util; mod wasmgen; diff --git a/src/rust/tlb.rs b/src/rust/tlb.rs deleted file mode 100644 index c4cde771..00000000 --- a/src/rust/tlb.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub const TLB_VALID: u32 = (1 << 0); -pub const TLB_READONLY: u32 = (1 << 1); -pub const TLB_NO_USER: u32 = (1 << 2); -//const TLB_IN_MAPPED_RANGE: u32 = (1 << 3); -pub const TLB_GLOBAL: u32 = (1 << 4); -pub const TLB_HAS_CODE: u32 = (1 << 5); From 3471663d8454178258bcce905f2e70054d514be7 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 4 Sep 2018 00:56:29 +0530 Subject: [PATCH 1308/2137] Add default profile for Debian (using debian-full Docker image) --- debug.html | 1 + src/browser/main.js | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/debug.html b/debug.html index b5b6a651..6682f5ff 100644 --- a/debug.html +++ b/debug.html @@ -18,6 +18,7 @@ + diff --git a/src/browser/main.js b/src/browser/main.js index cbba6bb7..bc299e60 100644 --- a/src/browser/main.js +++ b/src/browser/main.js @@ -270,6 +270,26 @@ }, name: "Windows", }, + { + id: "debian", + state: { + "url": "images/debian-state-base.bin", + }, + name: "Debian", + memory_size: 512 * 1024 * 1024, + vga_memory_size: 8 * 1024 * 1024, + hda: { + "url": "", + "size": 5, + "async": true, + }, + filesystem: { + "basefs": { + "url": HOST + "images/debian-base-fs.json", + }, + "baseurl": HOST + "images/debian-9p-rootfs-flat/", + }, + }, { id: "linux26", cdrom: { From 880aa5e2d18936e50a124f90c7770f8f998ae1af Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Mon, 3 Sep 2018 20:45:22 +0530 Subject: [PATCH 1309/2137] cpu: Port lookup_segment_selector and switch_seg to Rust We'll keep the JS versions too, since the Rust and JS versions are incompatible, but both are needed in their own respect. --- src/browser/starter.js | 1 - src/rust/cpu2/cpu.rs | 202 +++++++++++++++++++++++++++++++ src/rust/cpu2/instructions.rs | 2 - src/rust/cpu2/instructions_0f.rs | 2 - 4 files changed, 202 insertions(+), 5 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 86443bc0..ca7885e6 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -185,7 +185,6 @@ function V86Starter(options) }, "far_jump": function(eip, selector, is_call) { return cpu.far_jump(eip, selector, !!is_call); }, "far_return": function(eip, selector, stack_adjust) { return cpu.far_return(eip, selector, stack_adjust); }, - "switch_seg": function(reg, selector) { return cpu.switch_seg(reg, selector); }, "iret16": function() { return cpu.iret16(); }, "iret32": function() { return cpu.iret32(); }, "pic_acknowledge": function() { cpu.pic_acknowledge(); }, diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index d442bc6e..cc9af81b 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -27,6 +27,7 @@ use cpu2::misc_instr::{getaf, getcf, getof, getpf, getsf, getzf}; use cpu2::modrm::{resolve_modrm16, resolve_modrm32}; use profiler; use profiler::stat::*; +use std::convert::From; /// The offset for our generated functions in the wasm table. Every index less than this is /// reserved for rustc's indirect functions @@ -241,6 +242,77 @@ pub static mut tsc_offset: u64 = 0 as u64; pub static mut valid_tlb_entries: [i32; 10000] = [0; 10000]; pub static mut valid_tlb_entries_count: i32 = 0; +pub struct SegmentSelector { + rpl: u8, + is_gdt: bool, + descriptor_offset: u16, +} + +impl From for SegmentSelector { + fn from(sel: i32) -> SegmentSelector { + dbg_assert!(sel >= 0 && sel < 0x10000); + SegmentSelector { + rpl: (sel & 3) as u8, + is_gdt: (sel & 4) == 0, + descriptor_offset: (sel & !7) as u16, + } + } +} + +impl SegmentSelector { + pub fn get_original(&self) -> i32 { + ((self.rpl as i32) | (!self.is_gdt as i32) << 2 | (self.descriptor_offset as i32)) as i32 + } + pub fn is_null(&self) -> bool { self.is_gdt && self.descriptor_offset == 0 } + pub unsafe fn is_valid(&self) -> bool { + self.descriptor_offset <= if self.is_gdt { + *gdtr_size as u16 + } + else { + *segment_limits.offset(LDTR as isize) as u16 + } + } +} + +pub struct SegmentDescriptor { + base: i32, + limit: u32, + type_attr: u8, + flags: u8, +} + +impl From for SegmentDescriptor { + fn from(raw: u64) -> SegmentDescriptor { + SegmentDescriptor { + base: ((raw >> 16) & 0xffff | (raw & 0xff_00000000) >> 16 | (raw >> 56 << 24)) as i32, + limit: (raw & 0xffff | ((raw >> 48) & 0xf) << 16) as u32, + type_attr: ((raw >> 40) & 0xff) as u8, + flags: (raw >> 48 >> 4) as u8, + } + } +} + +impl SegmentDescriptor { + pub fn is_system(&self) -> bool { self.type_attr & 0x10 == 0 } + pub fn is_rw(&self) -> bool { self.type_attr & 2 == 2 } + pub fn is_dc(&self) -> bool { self.type_attr & 4 == 4 } + pub fn is_executable(&self) -> bool { self.type_attr & 8 == 8 } + pub fn is_present(&self) -> bool { self.type_attr & 0x80 == 0x80 } + pub fn is_writable(&self) -> bool { self.is_rw() && !self.is_executable() } + pub fn is_readable(&self) -> bool { self.is_rw() || !self.is_executable() } + pub fn is_conforming_executable(&self) -> bool { self.is_dc() && self.is_executable() } + pub fn get_dpl(&self) -> u8 { (self.type_attr >> 5) & 3 } + pub fn is_32(&self) -> bool { self.flags & 4 == 4 } + pub fn get_effective_limit(&self) -> u32 { + if self.flags & 8 == 8 { + self.limit << 12 | 0xFFF + } + else { + self.limit + } + } +} + //pub fn call_indirect1(f: fn(u16), x: u16) { f(x); } pub unsafe fn after_block_boundary() { jit_block_boundary = 0 != 1; } @@ -683,6 +755,136 @@ pub unsafe fn is_asize_32() -> bool { != (*prefixes as i32 & PREFIX_MASK_ADDRSIZE == PREFIX_MASK_ADDRSIZE) as i32; } +pub unsafe fn lookup_segment_selector( + selector: i32, +) -> Result<(SegmentDescriptor, SegmentSelector), ()> { + let selector = SegmentSelector::from(selector); + if selector.is_null() || !selector.is_valid() { + // XXX: The descriptor isn't required if the selector is invalid, so here's a stub + return Ok(( + SegmentDescriptor { + base: 0, + limit: 0, + type_attr: 0, + flags: 0, + }, + selector, + )); + } + + let mut table_offset: u32 = selector.descriptor_offset as u32 + if selector.is_gdt { + *gdtr_offset as u32 + } + else { + *segment_offsets.offset(LDTR as isize) as u32 + }; + + if *cr & CR0_PG != 0 { + table_offset = translate_address_system_read(table_offset as i32)?; + } + + let raw: u64 = read64s(table_offset) as u64; + let descriptor = SegmentDescriptor::from(raw); + + Ok((descriptor, selector)) +} + +pub unsafe fn switch_seg(reg: i32, selector_raw: i32) -> bool { + dbg_assert!(reg >= 0 && reg <= 5); + dbg_assert!(selector_raw >= 0 && selector_raw < 0x10000); + + if !*protected_mode || vm86_mode() { + *sreg.offset(reg as isize) = selector_raw as u16; + *segment_is_null.offset(reg as isize) = false; + *segment_offsets.offset(reg as isize) = selector_raw << 4; + + if reg == SS { + *stack_size_32 = false; + } + return true; + } + + let (descriptor, selector) = match lookup_segment_selector(selector_raw) { + Ok((a, b)) => (a, b), + Err(()) => { + // XXX: Currently, only for #pf, but we could trigger the #gp's due to null or invalid + // selectors here too, if lookup returned error-codes. + return false; + }, + }; + + if reg == SS { + if selector.is_null() { + dbg_log!("#GP for loading 0 in SS sel={:x}", selector_raw); + trigger_gp_non_raising(0); + return false; + } + + if !selector.is_valid() + || descriptor.is_system() + || selector.rpl != *cpl + || !descriptor.is_writable() + || descriptor.get_dpl() != *cpl + { + dbg_log!("#GP for loading invalid in SS sel={:x}", selector_raw); + trigger_gp_non_raising(selector_raw & !3); + return false; + } + + if !descriptor.is_present() { + dbg_log!("#SS for loading non-present in SS sel={:x}", selector_raw); + trigger_ss(selector_raw & !3); + return false; + } + + *stack_size_32 = descriptor.is_32(); + } + else if reg == CS { + // handled by switch_cs_real_mode, far_return or far_jump + dbg_assert!(false); + } + else { + // es, ds, fs, gs + if selector.is_null() { + *sreg.offset(reg as isize) = selector_raw as u16; + *segment_is_null.offset(reg as isize) = true; + return true; + } + + if !selector.is_valid() + || descriptor.is_system() + || !descriptor.is_readable() + || (!descriptor.is_conforming_executable() + && (selector.rpl > descriptor.get_dpl() || *cpl > descriptor.get_dpl())) + { + dbg_log!( + "#GP for loading invalid in seg {} sel={:x}", + reg, + selector_raw, + ); + trigger_gp_non_raising(selector_raw & !3); + return false; + } + + if !descriptor.is_present() { + dbg_log!( + "#NP for loading not-present in seg {} sel={:x}", + reg, + selector_raw, + ); + trigger_np(selector_raw & !3); + return false; + } + } + + *segment_is_null.offset(reg as isize) = false; + *segment_limits.offset(reg as isize) = descriptor.get_effective_limit(); + *segment_offsets.offset(reg as isize) = descriptor.base; + *sreg.offset(reg as isize) = selector_raw as u16; + + true +} + #[no_mangle] pub unsafe fn get_seg(mut segment: i32) -> i32 { dbg_assert!(segment >= 0 && segment < 8); diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index 1d97c393..45cd1c66 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -1,8 +1,6 @@ #![allow(non_snake_case, unused_mut, unused_variables,)] extern "C" { - #[no_mangle] - fn switch_seg(seg: i32, value: i32) -> bool; #[no_mangle] fn lss16(x: i32, y: i32, z: i32); #[no_mangle] diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 14ed1fc8..23611364 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -15,8 +15,6 @@ extern "C" { #[no_mangle] fn lss32(x: i32, y: i32, z: i32); #[no_mangle] - fn switch_seg(seg: i32, value: i32) -> bool; - #[no_mangle] fn get_rand_int() -> i32; #[no_mangle] fn has_rand_int() -> bool; From 8f24d9464bb4dc6bc2cb34d3a6e7aa49bbfb1a52 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 4 Sep 2018 11:55:24 +0530 Subject: [PATCH 1310/2137] cpu: Clean Rust lookup_segment_selector/switch_seg using early-exits --- src/rust/cpu2/cpu.rs | 100 +++++++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 41 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index cc9af81b..a7c7ff59 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -264,14 +264,12 @@ impl SegmentSelector { ((self.rpl as i32) | (!self.is_gdt as i32) << 2 | (self.descriptor_offset as i32)) as i32 } pub fn is_null(&self) -> bool { self.is_gdt && self.descriptor_offset == 0 } - pub unsafe fn is_valid(&self) -> bool { - self.descriptor_offset <= if self.is_gdt { - *gdtr_size as u16 - } - else { - *segment_limits.offset(LDTR as isize) as u16 - } - } +} + +// Used to indicate early that the selector cannot be used to fetch a descriptor +pub struct SelectorNullOrInvalid { + is_null: bool, + is_invalid: bool, } pub struct SegmentDescriptor { @@ -755,21 +753,25 @@ pub unsafe fn is_asize_32() -> bool { != (*prefixes as i32 & PREFIX_MASK_ADDRSIZE == PREFIX_MASK_ADDRSIZE) as i32; } +// XXX: This should be made more readable up the chain +type PageFault = (); + pub unsafe fn lookup_segment_selector( selector: i32, -) -> Result<(SegmentDescriptor, SegmentSelector), ()> { +) -> Result, PageFault> { let selector = SegmentSelector::from(selector); - if selector.is_null() || !selector.is_valid() { - // XXX: The descriptor isn't required if the selector is invalid, so here's a stub - return Ok(( - SegmentDescriptor { - base: 0, - limit: 0, - type_attr: 0, - flags: 0, - }, - selector, - )); + let selector_unusable = SelectorNullOrInvalid { + is_null: selector.is_null(), + is_invalid: selector.descriptor_offset > if selector.is_gdt { + *gdtr_size as u16 + } + else { + *segment_limits.offset(LDTR as isize) as u16 + }, + }; + + if selector_unusable.is_null || selector_unusable.is_invalid { + return Ok(Err(selector_unusable)); } let mut table_offset: u32 = selector.descriptor_offset as u32 + if selector.is_gdt { @@ -786,7 +788,7 @@ pub unsafe fn lookup_segment_selector( let raw: u64 = read64s(table_offset) as u64; let descriptor = SegmentDescriptor::from(raw); - Ok((descriptor, selector)) + Ok(Ok((descriptor, selector))) } pub unsafe fn switch_seg(reg: i32, selector_raw: i32) -> bool { @@ -805,23 +807,47 @@ pub unsafe fn switch_seg(reg: i32, selector_raw: i32) -> bool { } let (descriptor, selector) = match lookup_segment_selector(selector_raw) { - Ok((a, b)) => (a, b), + Ok(result) => match result { + Ok((desc, sel)) => (desc, sel), + Err(selector_unusable) => { + // The selector couldn't be used to fetch a descriptor, so we handle all of those + // cases + if selector_unusable.is_null { + if reg == SS { + dbg_log!("#GP for loading 0 in SS sel={:x}", selector_raw); + trigger_gp_non_raising(0); + return false; + } + else if reg != CS { + // es, ds, fs, gs + *sreg.offset(reg as isize) = selector_raw as u16; + *segment_is_null.offset(reg as isize) = true; + return true; + } + } + + if selector_unusable.is_invalid { + dbg_log!( + "#GP for loading invalid in seg={} sel={:x}", + reg, + selector_raw + ); + trigger_gp_non_raising(selector_raw & !3); + return false; + } + + dbg_assert!(false); + return false; + }, + }, Err(()) => { - // XXX: Currently, only for #pf, but we could trigger the #gp's due to null or invalid - // selectors here too, if lookup returned error-codes. + // Page-fault was already triggered, so we just bubble up here return false; }, }; if reg == SS { - if selector.is_null() { - dbg_log!("#GP for loading 0 in SS sel={:x}", selector_raw); - trigger_gp_non_raising(0); - return false; - } - - if !selector.is_valid() - || descriptor.is_system() + if descriptor.is_system() || selector.rpl != *cpl || !descriptor.is_writable() || descriptor.get_dpl() != *cpl @@ -844,15 +870,7 @@ pub unsafe fn switch_seg(reg: i32, selector_raw: i32) -> bool { dbg_assert!(false); } else { - // es, ds, fs, gs - if selector.is_null() { - *sreg.offset(reg as isize) = selector_raw as u16; - *segment_is_null.offset(reg as isize) = true; - return true; - } - - if !selector.is_valid() - || descriptor.is_system() + if descriptor.is_system() || !descriptor.is_readable() || (!descriptor.is_conforming_executable() && (selector.rpl > descriptor.get_dpl() || *cpl > descriptor.get_dpl())) From 6cc262bdba26f39190bda77dfb613e5478fa6bf2 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 5 Sep 2018 15:31:35 +0530 Subject: [PATCH 1311/2137] cleanup: Use OrPageFault type alias for clarity --- src/rust/cpu2/cpu.rs | 60 ++++++++++++++++++------------------- src/rust/cpu2/fpu.rs | 11 +++---- src/rust/cpu2/misc_instr.rs | 33 ++++++++++---------- src/rust/cpu2/modrm.rs | 9 +++--- src/rust/paging.rs | 2 ++ 5 files changed, 59 insertions(+), 56 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index a7c7ff59..c0a9e285 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -25,6 +25,7 @@ use cpu2::memory::{ }; use cpu2::misc_instr::{getaf, getcf, getof, getpf, getsf, getzf}; use cpu2::modrm::{resolve_modrm16, resolve_modrm32}; +use paging::OrPageFault; use profiler; use profiler::stat::*; use std::convert::From; @@ -330,7 +331,7 @@ pub unsafe fn get_eflags() -> i32 { | (getof() as i32) << 11; } -pub unsafe fn translate_address_read(mut address: i32) -> Result { +pub unsafe fn translate_address_read(mut address: i32) -> OrPageFault { let mut base: i32 = (address as u32 >> 12) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); let mut user: bool = *cpl as i32 == 3; @@ -346,7 +347,7 @@ pub unsafe fn do_page_translation( mut addr: i32, mut for_writing: bool, mut user: bool, -) -> Result { +) -> OrPageFault { let mut can_write: bool = 0 != 1; let mut global; let mut allow_user: bool = 0 != 1; @@ -621,7 +622,7 @@ pub unsafe fn trigger_pagefault(mut write: bool, mut user: bool, mut present: bo //profiler::stat_increment(S_TRIGGER_CPU_EXCEPTION); } -pub unsafe fn translate_address_write(mut address: i32) -> Result { +pub unsafe fn translate_address_write(mut address: i32) -> OrPageFault { let mut base: i32 = (address as u32 >> 12) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); let mut user: bool = *cpl as i32 == 3; @@ -677,7 +678,7 @@ pub unsafe fn check_tlb_invariants() { }; } -pub unsafe fn writable_or_pagefault(mut addr: i32, mut size: i32) -> Result<(), ()> { +pub unsafe fn writable_or_pagefault(mut addr: i32, mut size: i32) -> OrPageFault<()> { dbg_assert!(size < 4096); dbg_assert!(size > 0); if *cr & CR0_PG == 0 { @@ -704,7 +705,7 @@ pub unsafe fn writable_or_pagefault(mut addr: i32, mut size: i32) -> Result<(), }; } -pub unsafe fn read_imm8() -> Result { +pub unsafe fn read_imm8() -> OrPageFault { let mut eip: i32 = *instruction_pointer; if 0 != eip & !4095 ^ *last_virt_eip { *eip_phys = (translate_address_read(eip)? ^ eip as u32) as i32; @@ -716,9 +717,9 @@ pub unsafe fn read_imm8() -> Result { return Ok(data8); } -pub unsafe fn read_imm8s() -> Result { return Ok(read_imm8()? << 24 >> 24); } +pub unsafe fn read_imm8s() -> OrPageFault { return Ok(read_imm8()? << 24 >> 24); } -pub unsafe fn read_imm16() -> Result { +pub unsafe fn read_imm16() -> OrPageFault { // Two checks in one comparison: // 1. Did the high 20 bits of eip change // or 2. Are the low 12 bits of eip 0xFFF (and this read crosses a page boundary) @@ -732,7 +733,7 @@ pub unsafe fn read_imm16() -> Result { }; } -pub unsafe fn read_imm32s() -> Result { +pub unsafe fn read_imm32s() -> OrPageFault { // Analogue to the above comment if (*instruction_pointer ^ *last_virt_eip) as u32 > 4092 as u32 { return Ok(read_imm16()? | read_imm16()? << 16); @@ -753,12 +754,9 @@ pub unsafe fn is_asize_32() -> bool { != (*prefixes as i32 & PREFIX_MASK_ADDRSIZE == PREFIX_MASK_ADDRSIZE) as i32; } -// XXX: This should be made more readable up the chain -type PageFault = (); - pub unsafe fn lookup_segment_selector( selector: i32, -) -> Result, PageFault> { +) -> OrPageFault> { let selector = SegmentSelector::from(selector); let selector_unusable = SelectorNullOrInvalid { is_null: selector.is_null(), @@ -969,7 +967,7 @@ pub unsafe fn get_seg_prefix_ss(mut offset: i32) -> i32 { return get_seg_prefix( pub unsafe fn get_seg_prefix_cs(mut offset: i32) -> i32 { return get_seg_prefix(CS) + offset; } -pub unsafe fn modrm_resolve(mut modrm_byte: i32) -> Result { +pub unsafe fn modrm_resolve(mut modrm_byte: i32) -> OrPageFault { if is_asize_32() { resolve_modrm32(modrm_byte) } @@ -1035,7 +1033,7 @@ pub unsafe fn cycle_internal() { } } -pub unsafe fn get_phys_eip() -> Result { +pub unsafe fn get_phys_eip() -> OrPageFault { let mut eip: i32 = *instruction_pointer; if 0 != eip & !4095 ^ *last_virt_eip { *eip_phys = (translate_address_read(eip)? ^ eip as u32) as i32; @@ -1245,11 +1243,11 @@ pub unsafe fn virt_boundary_write32(mut low: u32, mut high: u32, mut value: i32) write8(high as u32, value >> 24); } -pub unsafe fn safe_read8(mut addr: i32) -> Result { +pub unsafe fn safe_read8(mut addr: i32) -> OrPageFault { return Ok(read8(translate_address_read(addr)?)); } -pub unsafe fn safe_read16(mut address: i32) -> Result { +pub unsafe fn safe_read16(mut address: i32) -> OrPageFault { let mut base: i32 = (address as u32 >> 12) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); let mut info_bits: i32 = entry & 4095 & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; @@ -1265,7 +1263,7 @@ pub unsafe fn safe_read16(mut address: i32) -> Result { }; } -pub unsafe fn safe_read16_slow(mut addr: i32) -> Result { +pub unsafe fn safe_read16_slow(mut addr: i32) -> OrPageFault { if addr & 4095 == 4095 { return Ok(safe_read8(addr)? | safe_read8(addr + 1)? << 8); } @@ -1274,7 +1272,7 @@ pub unsafe fn safe_read16_slow(mut addr: i32) -> Result { }; } -pub unsafe fn safe_read32s(mut address: i32) -> Result { +pub unsafe fn safe_read32s(mut address: i32) -> OrPageFault { let mut base: i32 = (address as u32 >> 12) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); let mut info_bits: i32 = entry & 4095 & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; @@ -1352,7 +1350,7 @@ pub fn report_safe_write_jit_slow(address: u32, entry: i32) { } } -pub unsafe fn safe_read32s_slow(mut addr: i32) -> Result { +pub unsafe fn safe_read32s_slow(mut addr: i32) -> OrPageFault { if addr & 4095 >= 4093 { return Ok(safe_read16(addr)? | safe_read16(addr + 2)? << 16); } @@ -1403,7 +1401,7 @@ pub unsafe fn safe_read32s_slow_jit(addr: i32) -> i32 { } } -pub unsafe fn safe_read64s(mut addr: i32) -> Result { +pub unsafe fn safe_read64s(mut addr: i32) -> OrPageFault { let mut x: reg64 = reg64 { i8_0: [0; 8] }; if addr & 4095 > 4096 - 8 { x.u32_0[0] = safe_read32s(addr)? as u32; @@ -1416,7 +1414,7 @@ pub unsafe fn safe_read64s(mut addr: i32) -> Result { Ok(x) } -pub unsafe fn safe_read128s(mut addr: i32) -> Result { +pub unsafe fn safe_read128s(mut addr: i32) -> OrPageFault { let mut x: reg128 = reg128 { i8_0: [0; 16] }; if addr & 4095 > 4096 - 16 { x.u64_0[0] = safe_read64s(addr)?.u64_0[0]; @@ -1429,12 +1427,12 @@ pub unsafe fn safe_read128s(mut addr: i32) -> Result { Ok(x) } -pub unsafe fn safe_write8(mut addr: i32, mut value: i32) -> Result<(), ()> { +pub unsafe fn safe_write8(mut addr: i32, mut value: i32) -> OrPageFault<()> { write8(translate_address_write(addr)?, value); Ok(()) } -pub unsafe fn safe_write16(mut address: i32, mut value: i32) -> Result<(), ()> { +pub unsafe fn safe_write16(mut address: i32, mut value: i32) -> OrPageFault<()> { let mut base: i32 = (address as u32 >> 12) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); let mut info_bits: i32 = entry & 4095 & !TLB_GLOBAL; @@ -1454,7 +1452,7 @@ pub unsafe fn safe_write16(mut address: i32, mut value: i32) -> Result<(), ()> { Ok(()) } -pub unsafe fn safe_write16_slow(mut addr: i32, mut value: i32) -> Result<(), ()> { +pub unsafe fn safe_write16_slow(mut addr: i32, mut value: i32) -> OrPageFault<()> { let mut phys_low = translate_address_write(addr)?; if addr & 4095 == 4095 { virt_boundary_write16(phys_low, translate_address_write(addr + 1)?, value); @@ -1465,7 +1463,7 @@ pub unsafe fn safe_write16_slow(mut addr: i32, mut value: i32) -> Result<(), ()> Ok(()) } -pub unsafe fn safe_write32(mut address: i32, mut value: i32) -> Result<(), ()> { +pub unsafe fn safe_write32(mut address: i32, mut value: i32) -> OrPageFault<()> { let mut base: i32 = (address as u32 >> 12) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); let mut info_bits: i32 = @@ -1511,7 +1509,7 @@ pub unsafe fn safe_write32(mut address: i32, mut value: i32) -> Result<(), ()> { Ok(()) } -pub unsafe fn safe_write32_slow(mut addr: i32, mut value: i32) -> Result<(), ()> { +pub unsafe fn safe_write32_slow(mut addr: i32, mut value: i32) -> OrPageFault<()> { let mut phys_low = translate_address_write(addr)?; if addr & 4095 > 4096 - 4 { virt_boundary_write32( @@ -1550,7 +1548,7 @@ pub unsafe fn safe_write32_slow_jit(addr: i32, value: i32) { } } -pub unsafe fn safe_write64(mut addr: i32, mut value: i64) -> Result<(), ()> { +pub unsafe fn safe_write64(mut addr: i32, mut value: i64) -> OrPageFault<()> { if addr & 4095 > 4096 - 8 { writable_or_pagefault(addr, 8)?; safe_write32(addr, value as i32).unwrap(); @@ -1563,7 +1561,7 @@ pub unsafe fn safe_write64(mut addr: i32, mut value: i64) -> Result<(), ()> { Ok(()) } -pub unsafe fn safe_write128(mut addr: i32, mut value: reg128) -> Result<(), ()> { +pub unsafe fn safe_write128(mut addr: i32, mut value: reg128) -> OrPageFault<()> { if addr & 4095 > 4096 - 16 { writable_or_pagefault(addr, 16)?; safe_write64(addr, value.u64_0[0] as i64).unwrap(); @@ -1724,7 +1722,7 @@ pub unsafe fn task_switch_test_mmx() -> bool { #[no_mangle] pub unsafe fn task_switch_test_mmx_void() { task_switch_test_mmx(); } -pub unsafe fn read_moffs() -> Result { +pub unsafe fn read_moffs() -> OrPageFault { // read 2 or 4 byte from ip, depending on address size attribute if is_asize_32() { read_imm32s() @@ -1938,7 +1936,7 @@ pub unsafe fn get_valid_global_tlb_entries_count() -> i32 { return result; } -pub unsafe fn translate_address_system_read(mut address: i32) -> Result { +pub unsafe fn translate_address_system_read(mut address: i32) -> OrPageFault { let mut base: i32 = (address as u32 >> 12) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); if 0 != entry & TLB_VALID { @@ -1949,7 +1947,7 @@ pub unsafe fn translate_address_system_read(mut address: i32) -> Result }; } -pub unsafe fn translate_address_system_write(mut address: i32) -> Result { +pub unsafe fn translate_address_system_write(mut address: i32) -> OrPageFault { let mut base: i32 = (address as u32 >> 12) as i32; let mut entry: i32 = *tlb_data.offset(base as isize); if entry & (TLB_VALID | TLB_READONLY) == TLB_VALID { diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index fe676ca9..85d7be22 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -2,6 +2,7 @@ use cpu2::cpu::*; use cpu2::global_pointers::*; +use paging::OrPageFault; pub fn round(x: f64) -> f64 { x.round() } pub fn floor(x: f64) -> f64 { x.floor() } @@ -93,20 +94,20 @@ pub unsafe fn fpu_integer_round(mut f: f64) -> f64 { }; } #[no_mangle] -pub unsafe fn fpu_load_m32(mut addr: i32) -> Result { +pub unsafe fn fpu_load_m32(mut addr: i32) -> OrPageFault { let mut v: f32_int = f32_int { i32_0: safe_read32s(addr)?, }; Ok(v.f32_0 as f64) } #[no_mangle] -pub unsafe fn fpu_load_m64(mut addr: i32) -> Result { +pub unsafe fn fpu_load_m64(mut addr: i32) -> OrPageFault { let mut value: u64 = safe_read64s(addr)?.u64_0[0]; let mut v: f64_int = f64_int { u64_0: [value] }; Ok(v.f64_0) } #[no_mangle] -pub unsafe fn fpu_load_m80(mut addr: i32) -> Result { +pub unsafe fn fpu_load_m80(mut addr: i32) -> OrPageFault { let mut value: u64 = safe_read64s(addr as i32)?.u64_0[0]; let mut low: u32 = value as u32; let mut high: u32 = (value >> 32) as u32; @@ -516,7 +517,7 @@ pub unsafe fn fpu_fstm32(mut addr: i32) { return_on_pagefault!(fpu_store_m32(addr, fpu_get_st0())); } #[no_mangle] -pub unsafe fn fpu_store_m32(mut addr: i32, mut x: f64) -> Result<(), ()> { +pub unsafe fn fpu_store_m32(mut addr: i32, mut x: f64) -> OrPageFault<()> { let mut v: f32_int = f32_int { f32_0: x as f32 }; safe_write32(addr, v.i32_0) } @@ -530,7 +531,7 @@ pub unsafe fn fpu_fstm64(mut addr: i32) { return_on_pagefault!(fpu_store_m64(addr, fpu_get_st0())); } #[no_mangle] -pub unsafe fn fpu_store_m64(mut addr: i32, mut x: f64) -> Result<(), ()> { +pub unsafe fn fpu_store_m64(mut addr: i32, mut x: f64) -> OrPageFault<()> { let mut v: f64_int = f64_int { f64_0: x }; safe_write64(addr, v.u64_0[0] as i64) } diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index 82ba657a..698ed177 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -3,6 +3,7 @@ use cpu2::cpu::*; use cpu2::fpu::{fpu_load_m80, fpu_load_status_word, fpu_set_status_word, fpu_store_m80}; use cpu2::global_pointers::*; +use paging::OrPageFault; #[no_mangle] pub unsafe fn getcf() -> bool { @@ -166,14 +167,14 @@ pub unsafe fn adjust_stack_reg(mut adjustment: i32) { } #[no_mangle] -pub unsafe fn push16_ss16(mut imm16: i32) -> Result<(), ()> { +pub unsafe fn push16_ss16(mut imm16: i32) -> OrPageFault<()> { let mut sp: i32 = get_seg_ss() + (*reg16.offset(SP as isize) as i32 - 2 & 65535); safe_write16(sp, imm16)?; *reg16.offset(SP as isize) -= 2; Ok(()) } #[no_mangle] -pub unsafe fn push16_ss32(mut imm16: i32) -> Result<(), ()> { +pub unsafe fn push16_ss32(mut imm16: i32) -> OrPageFault<()> { let mut sp: i32 = get_seg_ss() + *reg32s.offset(ESP as isize) - 2; safe_write16(sp, imm16)?; *reg32s.offset(ESP as isize) -= 2; @@ -186,9 +187,9 @@ pub unsafe fn push16_ss16_jit(mut imm16: i32) { return_on_pagefault!(push16_ss16 pub unsafe fn push16_ss32_jit(mut imm16: i32) { return_on_pagefault!(push16_ss32(imm16)) } #[no_mangle] -pub unsafe fn push16_ss16_mem(mut addr: i32) -> Result<(), ()> { push16_ss16(safe_read16(addr)?) } +pub unsafe fn push16_ss16_mem(mut addr: i32) -> OrPageFault<()> { push16_ss16(safe_read16(addr)?) } #[no_mangle] -pub unsafe fn push16_ss32_mem(mut addr: i32) -> Result<(), ()> { push16_ss32(safe_read16(addr)?) } +pub unsafe fn push16_ss32_mem(mut addr: i32) -> OrPageFault<()> { push16_ss32(safe_read16(addr)?) } #[no_mangle] pub unsafe fn push16_ss16_mem_jit(mut addr: i32) { return_on_pagefault!(push16_ss16_mem(addr)) } @@ -196,7 +197,7 @@ pub unsafe fn push16_ss16_mem_jit(mut addr: i32) { return_on_pagefault!(push16_s pub unsafe fn push16_ss32_mem_jit(mut addr: i32) { return_on_pagefault!(push16_ss32_mem(addr)) } #[no_mangle] -pub unsafe fn push16(mut imm16: i32) -> Result<(), ()> { +pub unsafe fn push16(mut imm16: i32) -> OrPageFault<()> { if *stack_size_32 { push16_ss32(imm16) } @@ -206,14 +207,14 @@ pub unsafe fn push16(mut imm16: i32) -> Result<(), ()> { } #[no_mangle] -pub unsafe fn push32_ss16(mut imm32: i32) -> Result<(), ()> { +pub unsafe fn push32_ss16(mut imm32: i32) -> OrPageFault<()> { let mut new_sp: i32 = *reg16.offset(SP as isize) as i32 - 4 & 65535; safe_write32(get_seg_ss() + new_sp, imm32)?; *reg16.offset(SP as isize) = new_sp as u16; Ok(()) } #[no_mangle] -pub unsafe fn push32_ss32(mut imm32: i32) -> Result<(), ()> { +pub unsafe fn push32_ss32(mut imm32: i32) -> OrPageFault<()> { let mut new_esp: i32 = *reg32s.offset(ESP as isize) - 4; safe_write32(get_seg_ss() + new_esp, imm32)?; *reg32s.offset(ESP as isize) = new_esp; @@ -226,9 +227,9 @@ pub unsafe fn push32_ss16_jit(mut imm32: i32) { return_on_pagefault!(push32_ss16 pub unsafe fn push32_ss32_jit(mut imm32: i32) { return_on_pagefault!(push32_ss32(imm32)) } #[no_mangle] -pub unsafe fn push32_ss16_mem(mut addr: i32) -> Result<(), ()> { push32_ss16(safe_read32s(addr)?) } +pub unsafe fn push32_ss16_mem(mut addr: i32) -> OrPageFault<()> { push32_ss16(safe_read32s(addr)?) } #[no_mangle] -pub unsafe fn push32_ss32_mem(mut addr: i32) -> Result<(), ()> { push32_ss32(safe_read32s(addr)?) } +pub unsafe fn push32_ss32_mem(mut addr: i32) -> OrPageFault<()> { push32_ss32(safe_read32s(addr)?) } #[no_mangle] pub unsafe fn push32_ss16_mem_jit(mut addr: i32) { return_on_pagefault!(push32_ss16_mem(addr)) } @@ -236,7 +237,7 @@ pub unsafe fn push32_ss16_mem_jit(mut addr: i32) { return_on_pagefault!(push32_s pub unsafe fn push32_ss32_mem_jit(mut addr: i32) { return_on_pagefault!(push32_ss32_mem(addr)) } #[no_mangle] -pub unsafe fn push32(mut imm32: i32) -> Result<(), ()> { +pub unsafe fn push32(mut imm32: i32) -> OrPageFault<()> { if *stack_size_32 { push32_ss32(imm32) } @@ -245,7 +246,7 @@ pub unsafe fn push32(mut imm32: i32) -> Result<(), ()> { } } #[no_mangle] -pub unsafe fn pop16() -> Result { +pub unsafe fn pop16() -> OrPageFault { if *stack_size_32 { pop16_ss32() } @@ -254,21 +255,21 @@ pub unsafe fn pop16() -> Result { } } #[no_mangle] -pub unsafe fn pop16_ss16() -> Result { +pub unsafe fn pop16_ss16() -> OrPageFault { let mut sp: i32 = get_seg_ss() + *reg16.offset(SP as isize) as i32; let mut result: i32 = safe_read16(sp)?; *reg16.offset(SP as isize) += 2; Ok(result) } #[no_mangle] -pub unsafe fn pop16_ss32() -> Result { +pub unsafe fn pop16_ss32() -> OrPageFault { let mut esp: i32 = get_seg_ss() + *reg32s.offset(ESP as isize); let mut result: i32 = safe_read16(esp)?; *reg32s.offset(ESP as isize) += 2; Ok(result) } #[no_mangle] -pub unsafe fn pop32s() -> Result { +pub unsafe fn pop32s() -> OrPageFault { if *stack_size_32 { pop32s_ss32() } @@ -277,14 +278,14 @@ pub unsafe fn pop32s() -> Result { } } #[no_mangle] -pub unsafe fn pop32s_ss16() -> Result { +pub unsafe fn pop32s_ss16() -> OrPageFault { let mut sp: i32 = *reg16.offset(SP as isize) as i32; let mut result: i32 = safe_read32s(get_seg_ss() + sp)?; *reg16.offset(SP as isize) = (sp + 4) as u16; Ok(result) } #[no_mangle] -pub unsafe fn pop32s_ss32() -> Result { +pub unsafe fn pop32s_ss32() -> OrPageFault { let mut esp: i32 = *reg32s.offset(ESP as isize); let mut result: i32 = safe_read32s(get_seg_ss() + esp)?; *reg32s.offset(ESP as isize) = esp + 4; diff --git a/src/rust/cpu2/modrm.rs b/src/rust/cpu2/modrm.rs index 022c203f..dc7887c4 100644 --- a/src/rust/cpu2/modrm.rs +++ b/src/rust/cpu2/modrm.rs @@ -2,8 +2,9 @@ use cpu2::cpu::*; use cpu2::global_pointers::*; +use paging::OrPageFault; -pub unsafe fn resolve_modrm16(mut modrm_byte: i32) -> Result { +pub unsafe fn resolve_modrm16(mut modrm_byte: i32) -> OrPageFault { Ok(match modrm_byte { 0 | 8 | 16 | 24 | 32 | 40 | 48 | 56 => get_seg_prefix_ds( *reg16.offset(BX as isize) as i32 + *reg16.offset(SI as isize) as i32 & 65535, @@ -90,7 +91,7 @@ pub unsafe fn resolve_modrm16(mut modrm_byte: i32) -> Result { }) } -pub unsafe fn resolve_modrm32_(mut modrm_byte: i32) -> Result { +pub unsafe fn resolve_modrm32_(mut modrm_byte: i32) -> OrPageFault { let mut r: u8 = (modrm_byte & 7) as u8; dbg_assert!(modrm_byte < 192); Ok(if r as i32 == 4 { @@ -135,7 +136,7 @@ pub unsafe fn resolve_modrm32_(mut modrm_byte: i32) -> Result { ) }) } -unsafe fn resolve_sib(mut mod_0: bool) -> Result { +unsafe fn resolve_sib(mut mod_0: bool) -> OrPageFault { let mut s; let mut sib_byte: u8 = read_imm8()? as u8; let mut r: u8 = (sib_byte as i32 & 7) as u8; @@ -171,7 +172,7 @@ unsafe fn resolve_sib(mut mod_0: bool) -> Result { Ok(get_seg_prefix(seg) + base + offset) } -pub unsafe fn resolve_modrm32(mut modrm_byte: i32) -> Result { +pub unsafe fn resolve_modrm32(mut modrm_byte: i32) -> OrPageFault { Ok(match modrm_byte { 0 | 8 | 16 | 24 | 32 | 40 | 48 | 56 => get_seg_prefix_ds(*reg32s.offset(EAX as isize)), 64 | 72 | 80 | 88 | 96 | 104 | 112 | 120 => { diff --git a/src/rust/paging.rs b/src/rust/paging.rs index e92f0464..e7ade2c7 100644 --- a/src/rust/paging.rs +++ b/src/rust/paging.rs @@ -1,3 +1,5 @@ +pub type OrPageFault = Result; + macro_rules! return_on_pagefault { ($expr:expr) => { match $expr { From e7741c74caf986da88fce449aed4a84e52234c2d Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 5 Sep 2018 15:49:53 +0530 Subject: [PATCH 1312/2137] cleanup: Make SelectorNullOrInvalid an enum --- src/rust/cpu2/cpu.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index c0a9e285..11c7a4d4 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -268,9 +268,10 @@ impl SegmentSelector { } // Used to indicate early that the selector cannot be used to fetch a descriptor -pub struct SelectorNullOrInvalid { - is_null: bool, - is_invalid: bool, +#[derive(PartialEq)] +pub enum SelectorNullOrInvalid { + IsNull, + IsInvalid, } pub struct SegmentDescriptor { @@ -758,18 +759,18 @@ pub unsafe fn lookup_segment_selector( selector: i32, ) -> OrPageFault> { let selector = SegmentSelector::from(selector); - let selector_unusable = SelectorNullOrInvalid { - is_null: selector.is_null(), - is_invalid: selector.descriptor_offset > if selector.is_gdt { - *gdtr_size as u16 - } - else { - *segment_limits.offset(LDTR as isize) as u16 - }, + let selector_invalid = selector.descriptor_offset > if selector.is_gdt { + *gdtr_size as u16 + } + else { + *segment_limits.offset(LDTR as isize) as u16 }; - if selector_unusable.is_null || selector_unusable.is_invalid { - return Ok(Err(selector_unusable)); + if selector.is_null() { + return Ok(Err(SelectorNullOrInvalid::IsNull)); + } + else if selector_invalid { + return Ok(Err(SelectorNullOrInvalid::IsInvalid)); } let mut table_offset: u32 = selector.descriptor_offset as u32 + if selector.is_gdt { @@ -810,7 +811,7 @@ pub unsafe fn switch_seg(reg: i32, selector_raw: i32) -> bool { Err(selector_unusable) => { // The selector couldn't be used to fetch a descriptor, so we handle all of those // cases - if selector_unusable.is_null { + if selector_unusable == SelectorNullOrInvalid::IsNull { if reg == SS { dbg_log!("#GP for loading 0 in SS sel={:x}", selector_raw); trigger_gp_non_raising(0); @@ -823,8 +824,7 @@ pub unsafe fn switch_seg(reg: i32, selector_raw: i32) -> bool { return true; } } - - if selector_unusable.is_invalid { + else if selector_unusable == SelectorNullOrInvalid::IsInvalid { dbg_log!( "#GP for loading invalid in seg={} sel={:x}", reg, From a8420a6ee120ca7e2c34bd24d8862ce9bb1e4de5 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 5 Sep 2018 16:02:57 +0530 Subject: [PATCH 1313/2137] cleanup: Use methods instead of parsing/storing props for SegmentSelector --- src/rust/cpu2/cpu.rs | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 11c7a4d4..4af49c6f 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -244,27 +244,15 @@ pub static mut valid_tlb_entries: [i32; 10000] = [0; 10000]; pub static mut valid_tlb_entries_count: i32 = 0; pub struct SegmentSelector { - rpl: u8, - is_gdt: bool, - descriptor_offset: u16, -} - -impl From for SegmentSelector { - fn from(sel: i32) -> SegmentSelector { - dbg_assert!(sel >= 0 && sel < 0x10000); - SegmentSelector { - rpl: (sel & 3) as u8, - is_gdt: (sel & 4) == 0, - descriptor_offset: (sel & !7) as u16, - } - } + raw: u16, } impl SegmentSelector { - pub fn get_original(&self) -> i32 { - ((self.rpl as i32) | (!self.is_gdt as i32) << 2 | (self.descriptor_offset as i32)) as i32 - } - pub fn is_null(&self) -> bool { self.is_gdt && self.descriptor_offset == 0 } + pub fn rpl(&self) -> u8 { (self.raw & 3) as u8 } + pub fn is_gdt(&self) -> bool { (self.raw & 4) == 0 } + pub fn descriptor_offset(&self) -> u16 { (self.raw & !7) as u16 } + + pub fn is_null(&self) -> bool { self.is_gdt() && self.descriptor_offset() == 0 } } // Used to indicate early that the selector cannot be used to fetch a descriptor @@ -758,8 +746,10 @@ pub unsafe fn is_asize_32() -> bool { pub unsafe fn lookup_segment_selector( selector: i32, ) -> OrPageFault> { - let selector = SegmentSelector::from(selector); - let selector_invalid = selector.descriptor_offset > if selector.is_gdt { + let selector = SegmentSelector { + raw: selector as u16, + }; + let selector_invalid = selector.descriptor_offset() > if selector.is_gdt() { *gdtr_size as u16 } else { @@ -773,7 +763,7 @@ pub unsafe fn lookup_segment_selector( return Ok(Err(SelectorNullOrInvalid::IsInvalid)); } - let mut table_offset: u32 = selector.descriptor_offset as u32 + if selector.is_gdt { + let mut table_offset: u32 = selector.descriptor_offset() as u32 + if selector.is_gdt() { *gdtr_offset as u32 } else { @@ -846,7 +836,7 @@ pub unsafe fn switch_seg(reg: i32, selector_raw: i32) -> bool { if reg == SS { if descriptor.is_system() - || selector.rpl != *cpl + || selector.rpl() != *cpl || !descriptor.is_writable() || descriptor.get_dpl() != *cpl { @@ -871,7 +861,7 @@ pub unsafe fn switch_seg(reg: i32, selector_raw: i32) -> bool { if descriptor.is_system() || !descriptor.is_readable() || (!descriptor.is_conforming_executable() - && (selector.rpl > descriptor.get_dpl() || *cpl > descriptor.get_dpl())) + && (selector.rpl() > descriptor.get_dpl() || *cpl > descriptor.get_dpl())) { dbg_log!( "#GP for loading invalid in seg {} sel={:x}", From a6e863d3c6ac01ebee10a3216f3920fca3bc6df9 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 5 Sep 2018 16:13:03 +0530 Subject: [PATCH 1314/2137] cleanup: Rename SegmentDescriptor's type_attr to access_byte --- src/rust/cpu2/cpu.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 4af49c6f..f35d462a 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -265,7 +265,7 @@ pub enum SelectorNullOrInvalid { pub struct SegmentDescriptor { base: i32, limit: u32, - type_attr: u8, + access_byte: u8, flags: u8, } @@ -274,22 +274,22 @@ impl From for SegmentDescriptor { SegmentDescriptor { base: ((raw >> 16) & 0xffff | (raw & 0xff_00000000) >> 16 | (raw >> 56 << 24)) as i32, limit: (raw & 0xffff | ((raw >> 48) & 0xf) << 16) as u32, - type_attr: ((raw >> 40) & 0xff) as u8, + access_byte: ((raw >> 40) & 0xff) as u8, flags: (raw >> 48 >> 4) as u8, } } } impl SegmentDescriptor { - pub fn is_system(&self) -> bool { self.type_attr & 0x10 == 0 } - pub fn is_rw(&self) -> bool { self.type_attr & 2 == 2 } - pub fn is_dc(&self) -> bool { self.type_attr & 4 == 4 } - pub fn is_executable(&self) -> bool { self.type_attr & 8 == 8 } - pub fn is_present(&self) -> bool { self.type_attr & 0x80 == 0x80 } + pub fn is_system(&self) -> bool { self.access_byte & 0x10 == 0 } + pub fn is_rw(&self) -> bool { self.access_byte & 2 == 2 } + pub fn is_dc(&self) -> bool { self.access_byte & 4 == 4 } + pub fn is_executable(&self) -> bool { self.access_byte & 8 == 8 } + pub fn is_present(&self) -> bool { self.access_byte & 0x80 == 0x80 } pub fn is_writable(&self) -> bool { self.is_rw() && !self.is_executable() } pub fn is_readable(&self) -> bool { self.is_rw() || !self.is_executable() } pub fn is_conforming_executable(&self) -> bool { self.is_dc() && self.is_executable() } - pub fn get_dpl(&self) -> u8 { (self.type_attr >> 5) & 3 } + pub fn get_dpl(&self) -> u8 { (self.access_byte >> 5) & 3 } pub fn is_32(&self) -> bool { self.flags & 4 == 4 } pub fn get_effective_limit(&self) -> u32 { if self.flags & 8 == 8 { From e4ff8faff0a597c60f97cde700df1a223b947be7 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 5 Sep 2018 16:15:56 +0530 Subject: [PATCH 1315/2137] cleanup: s/get_// for method names of SegmentDescriptor --- src/rust/cpu2/cpu.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index f35d462a..eec19cd4 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -289,9 +289,9 @@ impl SegmentDescriptor { pub fn is_writable(&self) -> bool { self.is_rw() && !self.is_executable() } pub fn is_readable(&self) -> bool { self.is_rw() || !self.is_executable() } pub fn is_conforming_executable(&self) -> bool { self.is_dc() && self.is_executable() } - pub fn get_dpl(&self) -> u8 { (self.access_byte >> 5) & 3 } + pub fn dpl(&self) -> u8 { (self.access_byte >> 5) & 3 } pub fn is_32(&self) -> bool { self.flags & 4 == 4 } - pub fn get_effective_limit(&self) -> u32 { + pub fn effective_limit(&self) -> u32 { if self.flags & 8 == 8 { self.limit << 12 | 0xFFF } @@ -838,7 +838,7 @@ pub unsafe fn switch_seg(reg: i32, selector_raw: i32) -> bool { if descriptor.is_system() || selector.rpl() != *cpl || !descriptor.is_writable() - || descriptor.get_dpl() != *cpl + || descriptor.dpl() != *cpl { dbg_log!("#GP for loading invalid in SS sel={:x}", selector_raw); trigger_gp_non_raising(selector_raw & !3); @@ -861,7 +861,7 @@ pub unsafe fn switch_seg(reg: i32, selector_raw: i32) -> bool { if descriptor.is_system() || !descriptor.is_readable() || (!descriptor.is_conforming_executable() - && (selector.rpl() > descriptor.get_dpl() || *cpl > descriptor.get_dpl())) + && (selector.rpl() > descriptor.dpl() || *cpl > descriptor.dpl())) { dbg_log!( "#GP for loading invalid in seg {} sel={:x}", @@ -884,7 +884,7 @@ pub unsafe fn switch_seg(reg: i32, selector_raw: i32) -> bool { } *segment_is_null.offset(reg as isize) = false; - *segment_limits.offset(reg as isize) = descriptor.get_effective_limit(); + *segment_limits.offset(reg as isize) = descriptor.effective_limit(); *segment_offsets.offset(reg as isize) = descriptor.base; *sreg.offset(reg as isize) = selector_raw as u16; From a209e00523bd6086b9adad6792ef3a1168c09106 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 5 Sep 2018 16:56:36 +0530 Subject: [PATCH 1316/2137] cleanup: Use methods instead of parsing props for SegmentDescriptor --- src/rust/cpu2/cpu.rs | 49 +++++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index eec19cd4..54ca222d 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -28,7 +28,6 @@ use cpu2::modrm::{resolve_modrm16, resolve_modrm32}; use paging::OrPageFault; use profiler; use profiler::stat::*; -use std::convert::From; /// The offset for our generated functions in the wasm table. Every index less than this is /// reserved for rustc's indirect functions @@ -263,40 +262,34 @@ pub enum SelectorNullOrInvalid { } pub struct SegmentDescriptor { - base: i32, - limit: u32, - access_byte: u8, - flags: u8, -} - -impl From for SegmentDescriptor { - fn from(raw: u64) -> SegmentDescriptor { - SegmentDescriptor { - base: ((raw >> 16) & 0xffff | (raw & 0xff_00000000) >> 16 | (raw >> 56 << 24)) as i32, - limit: (raw & 0xffff | ((raw >> 48) & 0xf) << 16) as u32, - access_byte: ((raw >> 40) & 0xff) as u8, - flags: (raw >> 48 >> 4) as u8, - } - } + raw: u64, } impl SegmentDescriptor { - pub fn is_system(&self) -> bool { self.access_byte & 0x10 == 0 } - pub fn is_rw(&self) -> bool { self.access_byte & 2 == 2 } - pub fn is_dc(&self) -> bool { self.access_byte & 4 == 4 } - pub fn is_executable(&self) -> bool { self.access_byte & 8 == 8 } - pub fn is_present(&self) -> bool { self.access_byte & 0x80 == 0x80 } + pub fn base(&self) -> i32 { + ((self.raw >> 16) & 0xffff | (self.raw & 0xff_00000000) >> 16 | (self.raw >> 56 << 24)) + as i32 + } + pub fn limit(&self) -> u32 { (self.raw & 0xffff | ((self.raw >> 48) & 0xf) << 16) as u32 } + pub fn access_byte(&self) -> u8 { ((self.raw >> 40) & 0xff) as u8 } + pub fn flags(&self) -> u8 { ((self.raw >> 48 >> 4) & 0xf) as u8 } + + pub fn is_system(&self) -> bool { self.access_byte() & 0x10 == 0 } + pub fn is_rw(&self) -> bool { self.access_byte() & 2 == 2 } + pub fn is_dc(&self) -> bool { self.access_byte() & 4 == 4 } + pub fn is_executable(&self) -> bool { self.access_byte() & 8 == 8 } + pub fn is_present(&self) -> bool { self.access_byte() & 0x80 == 0x80 } pub fn is_writable(&self) -> bool { self.is_rw() && !self.is_executable() } pub fn is_readable(&self) -> bool { self.is_rw() || !self.is_executable() } pub fn is_conforming_executable(&self) -> bool { self.is_dc() && self.is_executable() } - pub fn dpl(&self) -> u8 { (self.access_byte >> 5) & 3 } - pub fn is_32(&self) -> bool { self.flags & 4 == 4 } + pub fn dpl(&self) -> u8 { (self.access_byte() >> 5) & 3 } + pub fn is_32(&self) -> bool { self.flags() & 4 == 4 } pub fn effective_limit(&self) -> u32 { - if self.flags & 8 == 8 { - self.limit << 12 | 0xFFF + if self.flags() & 8 == 8 { + self.limit() << 12 | 0xFFF } else { - self.limit + self.limit() } } } @@ -775,7 +768,7 @@ pub unsafe fn lookup_segment_selector( } let raw: u64 = read64s(table_offset) as u64; - let descriptor = SegmentDescriptor::from(raw); + let descriptor = SegmentDescriptor { raw }; Ok(Ok((descriptor, selector))) } @@ -885,7 +878,7 @@ pub unsafe fn switch_seg(reg: i32, selector_raw: i32) -> bool { *segment_is_null.offset(reg as isize) = false; *segment_limits.offset(reg as isize) = descriptor.effective_limit(); - *segment_offsets.offset(reg as isize) = descriptor.base; + *segment_offsets.offset(reg as isize) = descriptor.base(); *sreg.offset(reg as isize) = selector_raw as u16; true From 3c3c07079f061239c236f6c584d3141bdee39c60 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 5 Sep 2018 23:14:56 +0530 Subject: [PATCH 1317/2137] cleanup: Use tuples and destructuring for more Rustic code --- src/rust/cpu2/cpu.rs | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 54ca222d..cc21e61b 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -742,34 +742,32 @@ pub unsafe fn lookup_segment_selector( let selector = SegmentSelector { raw: selector as u16, }; - let selector_invalid = selector.descriptor_offset() > if selector.is_gdt() { - *gdtr_size as u16 - } - else { - *segment_limits.offset(LDTR as isize) as u16 - }; if selector.is_null() { return Ok(Err(SelectorNullOrInvalid::IsNull)); } - else if selector_invalid { + + let (table_offset, table_limit) = if selector.is_gdt() { + (*gdtr_offset as u32, *gdtr_size as u16) + } + else { + ( + *segment_offsets.offset(LDTR as isize) as u32, + *segment_limits.offset(LDTR as isize) as u16, + ) + }; + + if selector.descriptor_offset() > table_limit { return Ok(Err(SelectorNullOrInvalid::IsInvalid)); } - let mut table_offset: u32 = selector.descriptor_offset() as u32 + if selector.is_gdt() { - *gdtr_offset as u32 - } - else { - *segment_offsets.offset(LDTR as isize) as u32 + let descriptor_address = + translate_address_system_read(selector.descriptor_offset() as i32 + table_offset as i32)?; + + let descriptor = SegmentDescriptor { + raw: read64s(descriptor_address) as u64, }; - if *cr & CR0_PG != 0 { - table_offset = translate_address_system_read(table_offset as i32)?; - } - - let raw: u64 = read64s(table_offset) as u64; - let descriptor = SegmentDescriptor { raw }; - Ok(Ok((descriptor, selector))) } From 8e7061eff55c5fe47b31e5a100e3947998be8938 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 4 Sep 2018 18:19:38 +0530 Subject: [PATCH 1318/2137] cpu: Port test_privileges_for_io to Rust --- src/browser/starter.js | 2 - src/cpu.js | 63 ++++---------------------------- src/native/global_pointers.c | 2 + src/native/global_pointers.h | 2 + src/native/js_imports.h | 1 - src/rust/cpu2/cpu.rs | 47 ++++++++++++++++++++++++ src/rust/cpu2/global_pointers.rs | 3 +- src/rust/cpu2/string.rs | 3 -- src/rust/paging.rs | 9 +++++ 9 files changed, 70 insertions(+), 62 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index ca7885e6..ff684f97 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -226,8 +226,6 @@ function V86Starter(options) "enter16": function() { return cpu.enter16.apply(cpu, arguments); }, "enter32": function() { return cpu.enter32.apply(cpu, arguments); }, - "test_privileges_for_io": function() { return cpu.test_privileges_for_io.apply(cpu, arguments); }, - "get_time": Date.now, "coverage_log": (fn_name_offset, num_blocks, visited_block) => { diff --git a/src/cpu.js b/src/cpu.js index 10cc240b..997651aa 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -63,7 +63,7 @@ function CPU(bus, wm, v86oxide, coverage_logger) if(false) Object.defineProperty(this, "gdtr_size", { get: () => { return new Int32Array(memory.buffer, 572, 1); } }); if(false) Object.defineProperty(this, "gdtr_offset", { get: () => { return new Int32Array(memory.buffer, 576, 1); } }); - this.tss_size_32 = false; + this.tss_size_32 = v86util.view(Int32Array, memory, 1128, 1); /* * whether or not a page fault occured @@ -440,7 +440,7 @@ CPU.prototype.get_state = function() state[63] = this.devices.ioapic; - state[64] = this.tss_size_32; + state[64] = this.tss_size_32[0]; state[65] = this.reg_mmxs; state[66] = this.reg_xmm32s; @@ -530,7 +530,7 @@ CPU.prototype.set_state = function(state) this.devices.ioapic = state[63]; - this.tss_size_32 = state[64]; + this.tss_size_32[0] = state[64]; this.reg_mmxs.set(state[65]); this.reg_xmm32s.set(state[66]); @@ -1631,7 +1631,7 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, ha //this.debug.dump_regs(); var tss_stack_addr = this.get_tss_stack_addr(info.dpl); - if(this.tss_size_32) + if(this.tss_size_32[0]) { var new_esp = this.read32s(tss_stack_addr); var new_ss = this.read16(tss_stack_addr + 4 | 0); @@ -2413,7 +2413,7 @@ CPU.prototype.far_jump = function(eip, selector, is_call) dbg_log("more privilege call gate is_16=" + is_16 + " from=" + this.cpl[0] + " to=" + cs_info.dpl); var tss_stack_addr = this.get_tss_stack_addr(cs_info.dpl); - if(this.tss_size_32) + if(this.tss_size_32[0]) { var new_esp = this.read32s(tss_stack_addr); var new_ss = this.read16(tss_stack_addr + 4 | 0); @@ -2669,7 +2669,7 @@ CPU.prototype.far_jump = function(eip, selector, is_call) CPU.prototype.get_tss_stack_addr = function(dpl) { - if(this.tss_size_32) + if(this.tss_size_32[0]) { var tss_stack_addr = (dpl << 3) + 4 | 0; @@ -2705,7 +2705,7 @@ CPU.prototype.get_tss_stack_addr = function(dpl) CPU.prototype.do_task_switch = function(selector, error_code) { - dbg_assert(this.tss_size_32, "TODO"); + dbg_assert(this.tss_size_32[0], "TODO"); dbg_log("do_task_switch sel=" + h(selector), LOG_CPU); var descriptor = this.lookup_segment_selector(selector); @@ -3012,53 +3012,6 @@ CPU.prototype.device_lower_irq = function(i) } }; -CPU.prototype.test_privileges_for_io = function(port, size) -{ - if(this.protected_mode[0] && (this.cpl[0] > this.getiopl() || (this.flags[0] & flag_vm))) - { - if(!this.tss_size_32) - { - dbg_log("#GP for port io, 16-bit TSS port=" + h(port) + " size=" + size, LOG_CPU); - CPU_LOG_VERBOSE && this.debug.dump_state(); - this.trigger_gp_non_raising(0); - return false; - } - - var tsr_size = this.segment_limits[reg_tr]; - var tsr_offset = this.segment_offsets[reg_tr]; - - if(tsr_size >= 0x67) - { - dbg_assert((tsr_offset + 0x64 + 2 & 0xFFF) < 0xFFF); - - var iomap_base = this.read16(this.translate_address_system_read(tsr_offset + 0x64 + 2 | 0)), - high_port = port + size - 1 | 0; - - if(tsr_size >= (iomap_base + (high_port >> 3) | 0)) - { - var mask = ((1 << size) - 1) << (port & 7), - addr = this.translate_address_system_read(tsr_offset + iomap_base + (port >> 3) | 0), - port_info = (mask & 0xFF00) ? - this.read16(addr) : this.read8(addr); - - dbg_assert((addr & 0xFFF) < 0xFFF); - - if(!(port_info & mask)) - { - return true; - } - } - } - - dbg_log("#GP for port io port=" + h(port) + " size=" + size, LOG_CPU); - CPU_LOG_VERBOSE && this.debug.dump_state(); - this.trigger_gp_non_raising(0); - return false; - } - - return true; -}; - CPU.prototype.cpuid = function() { // cpuid @@ -3491,7 +3444,7 @@ CPU.prototype.load_tr = function(selector) throw this.debug.unimpl("#NT handler"); } - this.tss_size_32 = info.type === 9; + this.tss_size_32[0] = info.type === 9; this.segment_offsets[reg_tr] = info.base; this.segment_limits[reg_tr] = info.effective_limit; this.sreg[reg_tr] = selector; diff --git a/src/native/global_pointers.c b/src/native/global_pointers.c index fe90780d..5ec4c4ff 100644 --- a/src/native/global_pointers.c +++ b/src/native/global_pointers.c @@ -82,6 +82,8 @@ int32_t* const fpu_dp_selector = (int32_t* const) 1060; union reg64* const reg_mmx = (union reg64* const) 1064; // length 64 +extern bool* const tss_size_32 = (bool* const) 1128; + // gap uint32_t* const opstats_buffer = (uint32_t* const) 0x1000; // length 0x400 diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index 44658ec4..d2c372ea 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -84,6 +84,8 @@ extern int32_t* const fpu_dp_selector; extern union reg64* const reg_mmx; // length 64 +extern bool* const tss_size_32; + // gap extern uint32_t* const opstats_buffer; // length 0x400 diff --git a/src/native/js_imports.h b/src/native/js_imports.h index 1d30df0a..19eaf0bc 100644 --- a/src/native/js_imports.h +++ b/src/native/js_imports.h @@ -51,7 +51,6 @@ extern void update_eflags(int32_t); extern bool switch_seg(int32_t, int32_t); extern void lss16(int32_t, int32_t, int32_t); extern void lss32(int32_t, int32_t, int32_t); -extern bool test_privileges_for_io(int32_t, int32_t); extern int32_t io_port_read8(int32_t); extern int32_t io_port_read16(int32_t); extern int32_t io_port_read32(int32_t); diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index cc21e61b..ef2bcf30 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -897,6 +897,53 @@ pub unsafe fn get_seg(mut segment: i32) -> i32 { return *segment_offsets.offset(segment as isize); } +pub unsafe fn test_privileges_for_io(port: i32, size: i32) -> bool { + if *protected_mode && (*cpl > getiopl() as u8 || (*flags & FLAG_VM != 0)) { + if !*tss_size_32 { + dbg_log!("#GP for port io, 16-bit TSS port={:x} size={}", port, size); + trigger_gp_non_raising(0); + return false; + } + + let tsr_size = *segment_limits.offset(TR as isize); + let tsr_offset = *segment_offsets.offset(TR as isize); + + if tsr_size >= 0x67 { + dbg_assert!(tsr_offset + 0x64 + 2 & 0xFFF < 0xFFF); + + let iomap_base = read16(return_false_on_pagefault!(translate_address_system_read( + tsr_offset + 0x64 + 2 + ))); + let high_port = port + size - 1; + + if tsr_size >= (iomap_base + (high_port >> 3)) as u32 { + let mask = ((1 << size) - 1) << (port & 7); + let addr = return_false_on_pagefault!(translate_address_system_read( + tsr_offset + iomap_base + (port >> 3) + )); + let port_info = if mask & 0xFF00 != 0 { + read16(addr) + } + else { + read8(addr) + }; + + dbg_assert!(addr & 0xFFF < 0xFFF); + + if port_info & mask == 0 { + return true; + } + } + } + + dbg_log!("#GP for port io port={:x} size={}", port, size); + trigger_gp_non_raising(0); + return false; + } + + return true; +} + pub unsafe fn trigger_gp(mut code: i32) { *instruction_pointer = *previous_ip; raise_exception_with_code(CPU_EXCEPTION_GP, code); diff --git a/src/rust/cpu2/global_pointers.rs b/src/rust/cpu2/global_pointers.rs index 912dc01e..f922112e 100644 --- a/src/rust/cpu2/global_pointers.rs +++ b/src/rust/cpu2/global_pointers.rs @@ -60,6 +60,7 @@ pub const fpu_ip_selector: *mut i32 = 1052 as *mut i32; pub const fpu_dp: *mut i32 = 1056 as *mut i32; pub const fpu_dp_selector: *mut i32 = 1060 as *mut i32; pub const reg_mmx: *mut reg64 = 1064 as *mut reg64; +pub const tss_size_32: *mut bool = 1128 as *mut bool; pub const opstats_buffer: *mut u32 = 4096 as *mut u32; pub const opstats_buffer_0f: *mut u32 = 5120 as *mut u32; -pub const tlb_data: *mut i32 = 4194304 as *mut i32; +pub const tlb_data: *mut i32 = 0x400000 as *mut i32; diff --git a/src/rust/cpu2/string.rs b/src/rust/cpu2/string.rs index 8d0b4e41..a110bfef 100644 --- a/src/rust/cpu2/string.rs +++ b/src/rust/cpu2/string.rs @@ -1,9 +1,6 @@ #![allow(non_upper_case_globals, unused_mut)] extern "C" { - #[no_mangle] - pub fn test_privileges_for_io(port: i32, size: i32) -> bool; - #[no_mangle] pub fn io_port_read8(port: i32) -> i32; #[no_mangle] diff --git a/src/rust/paging.rs b/src/rust/paging.rs index e7ade2c7..1e24821b 100644 --- a/src/rust/paging.rs +++ b/src/rust/paging.rs @@ -1,5 +1,14 @@ pub type OrPageFault = Result; +macro_rules! return_false_on_pagefault { + ($expr:expr) => { + match $expr { + Ok(v) => v, + Err(()) => return false, + } + }; +} + macro_rules! return_on_pagefault { ($expr:expr) => { match $expr { From a9bb4619ef2a8b2b2f6776d8c1386a13368108da Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 4 Sep 2018 18:30:04 +0530 Subject: [PATCH 1319/2137] cpu: Expand return_on_pagefault macro for cleanup --- src/rust/cpu2/cpu.rs | 25 +++++++++++-------------- src/rust/paging.rs | 15 ++++++--------- 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index ef2bcf30..a259bc11 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -786,8 +786,8 @@ pub unsafe fn switch_seg(reg: i32, selector_raw: i32) -> bool { return true; } - let (descriptor, selector) = match lookup_segment_selector(selector_raw) { - Ok(result) => match result { + let (descriptor, selector) = + match return_on_pagefault!(lookup_segment_selector(selector_raw), false) { Ok((desc, sel)) => (desc, sel), Err(selector_unusable) => { // The selector couldn't be used to fetch a descriptor, so we handle all of those @@ -818,12 +818,7 @@ pub unsafe fn switch_seg(reg: i32, selector_raw: i32) -> bool { dbg_assert!(false); return false; }, - }, - Err(()) => { - // Page-fault was already triggered, so we just bubble up here - return false; - }, - }; + }; if reg == SS { if descriptor.is_system() @@ -911,16 +906,18 @@ pub unsafe fn test_privileges_for_io(port: i32, size: i32) -> bool { if tsr_size >= 0x67 { dbg_assert!(tsr_offset + 0x64 + 2 & 0xFFF < 0xFFF); - let iomap_base = read16(return_false_on_pagefault!(translate_address_system_read( - tsr_offset + 0x64 + 2 - ))); + let iomap_base = read16(return_on_pagefault!( + translate_address_system_read(tsr_offset + 0x64 + 2), + false + )); let high_port = port + size - 1; if tsr_size >= (iomap_base + (high_port >> 3)) as u32 { let mask = ((1 << size) - 1) << (port & 7); - let addr = return_false_on_pagefault!(translate_address_system_read( - tsr_offset + iomap_base + (port >> 3) - )); + let addr = return_on_pagefault!( + translate_address_system_read(tsr_offset + iomap_base + (port >> 3)), + false + ); let port_info = if mask & 0xFF00 != 0 { read16(addr) } diff --git a/src/rust/paging.rs b/src/rust/paging.rs index 1e24821b..08c05cf3 100644 --- a/src/rust/paging.rs +++ b/src/rust/paging.rs @@ -1,14 +1,5 @@ pub type OrPageFault = Result; -macro_rules! return_false_on_pagefault { - ($expr:expr) => { - match $expr { - Ok(v) => v, - Err(()) => return false, - } - }; -} - macro_rules! return_on_pagefault { ($expr:expr) => { match $expr { @@ -16,4 +7,10 @@ macro_rules! return_on_pagefault { Err(()) => return, } }; + ($expr:expr, $ret:expr) => { + match $expr { + Ok(v) => v, + Err(()) => return $ret, + } + }; } From b4922dc3b1cc2514e28175dcc0d888922d6cd92c Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 7 Sep 2018 18:59:11 +0530 Subject: [PATCH 1320/2137] cpu: Port cpl_changed to Rust We leave the JS version too, since it's used by several other JS functions that we aren't porting yet. --- src/browser/starter.js | 1 - src/rust/cpu2/cpu.rs | 5 +++++ src/rust/cpu2/instructions_0f.rs | 2 -- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index ff684f97..3e97f778 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -213,7 +213,6 @@ function V86Starter(options) "verw": function() { return cpu.verw.apply(cpu, arguments); }, "verr": function() { return cpu.verr.apply(cpu, arguments); }, - "cpl_changed": function() { return cpu.cpl_changed.apply(cpu, arguments); }, "set_cr0": function() { return cpu.set_cr0.apply(cpu, arguments); }, "update_cs_size": function() { return cpu.update_cs_size.apply(cpu, arguments); }, "cpuid": function() { return cpu.cpuid.apply(cpu, arguments); }, diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index a259bc11..12c8717c 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -892,6 +892,11 @@ pub unsafe fn get_seg(mut segment: i32) -> i32 { return *segment_offsets.offset(segment as isize); } +pub unsafe fn cpl_changed() { + *last_virt_eip = -1; + *last_virt_esp = -1; +} + pub unsafe fn test_privileges_for_io(port: i32, size: i32) -> bool { if *protected_mode && (*cpl > getiopl() as u8 || (*flags & FLAG_VM != 0)) { if !*tss_size_32 { diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 23611364..25342084 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -21,8 +21,6 @@ extern "C" { #[no_mangle] fn cpuid(); #[no_mangle] - fn cpl_changed(); - #[no_mangle] fn update_cs_size(cs_size: bool); #[no_mangle] fn set_cr0(cr0: i32); From 1712d25725e3112b03440b18a6a53909009fa1bc Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 7 Sep 2018 19:00:28 +0530 Subject: [PATCH 1321/2137] cpu: Port set_cr0 to Rust --- src/browser/starter.js | 1 - src/cpu.js | 34 -------------------------------- src/native/js_imports.h | 2 -- src/rust/cpu2/cpu.rs | 24 ++++++++++++++++++++++ src/rust/cpu2/instructions_0f.rs | 2 -- 5 files changed, 24 insertions(+), 39 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 3e97f778..ce0bb006 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -213,7 +213,6 @@ function V86Starter(options) "verw": function() { return cpu.verw.apply(cpu, arguments); }, "verr": function() { return cpu.verr.apply(cpu, arguments); }, - "set_cr0": function() { return cpu.set_cr0.apply(cpu, arguments); }, "update_cs_size": function() { return cpu.update_cs_size.apply(cpu, arguments); }, "cpuid": function() { return cpu.cpuid.apply(cpu, arguments); }, diff --git a/src/cpu.js b/src/cpu.js index 997651aa..8cb307b2 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -1453,40 +1453,6 @@ CPU.prototype.run_hardware_timers = function(now) } }; -CPU.prototype.set_cr0 = function(cr0) -{ - //dbg_log("cr0 = " + h(this.cr[0] >>> 0), LOG_CPU); - - if(cr0 & CR0_AM) - { - dbg_log("Warning: Unimplemented: cr0 alignment mask", LOG_CPU); - } - - if((cr0 & (CR0_PE | CR0_PG)) === CR0_PG) - { - // cannot load PG without PE - throw this.debug.unimpl("#GP handler"); - } - - const old_cr0 = this.cr[0]; - - this.cr[0] = cr0; - - //if(!have_fpu) - //{ - // // if there's no FPU, keep emulation set - // this.cr[0] |= CR0_EM; - //} - this.cr[0] |= CR0_ET; - - if((old_cr0 & (CR0_PG | CR0_WP)) !== (cr0 & (CR0_PG | CR0_WP))) - { - this.full_clear_tlb(); - } - - this.protected_mode[0] = +((this.cr[0] & CR0_PE) === CR0_PE); -}; - CPU.prototype.cpl_changed = function() { this.last_virt_eip[0] = -1; diff --git a/src/native/js_imports.h b/src/native/js_imports.h index 19eaf0bc..61feb516 100644 --- a/src/native/js_imports.h +++ b/src/native/js_imports.h @@ -21,11 +21,9 @@ extern int32_t lsl(int32_t, int32_t); extern int32_t mmap_read16(uint32_t); extern int32_t mmap_read32(uint32_t); extern int32_t mmap_read8(uint32_t); -extern int32_t set_cr0(int32_t); extern int32_t verr(int32_t); extern int32_t verw(int32_t); -extern void cpl_changed(void); extern void cpuid(void); extern void enter16(int32_t, int32_t); extern void enter32(int32_t, int32_t); diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 12c8717c..4b221b36 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -151,6 +151,7 @@ pub const CR0_EM: i32 = 1 << 2; pub const CR0_TS: i32 = 1 << 3; pub const CR0_ET: i32 = 1 << 4; pub const CR0_WP: i32 = 1 << 16; +pub const CR0_AM: i32 = 1 << 18; pub const CR0_NW: i32 = 1 << 29; pub const CR0_CD: i32 = 1 << 30; pub const CR0_PG: i32 = 1 << 31; @@ -892,6 +893,29 @@ pub unsafe fn get_seg(mut segment: i32) -> i32 { return *segment_offsets.offset(segment as isize); } +pub unsafe fn set_cr0(cr0: i32) { + if cr0 & CR0_AM != 0 { + dbg_log!("Warning: Unimplemented: cr0 alignment mask"); + } + + if (cr0 & (CR0_PE | CR0_PG)) == CR0_PG { + panic!("cannot load PG without PE"); + } + + let old_cr0 = *cr; + + *cr = cr0; + + // TODO: Consider have_fpu and CR0_EM emulation set + *cr |= CR0_ET; + + if old_cr0 & (CR0_PG | CR0_WP) != cr0 & (CR0_PG | CR0_WP) { + full_clear_tlb(); + } + + *protected_mode = (*cr & CR0_PE) == CR0_PE; +} + pub unsafe fn cpl_changed() { *last_virt_eip = -1; *last_virt_esp = -1; diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 25342084..1221a389 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -23,8 +23,6 @@ extern "C" { #[no_mangle] fn update_cs_size(cs_size: bool); #[no_mangle] - fn set_cr0(cr0: i32); - #[no_mangle] fn lsl(r: i32, v: i32) -> i32; #[no_mangle] fn lar(r: i32, v: i32) -> i32; From 56ec3be5a4cfd5e85397d0ad8f45a32f9f86e560 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 7 Sep 2018 19:12:04 +0530 Subject: [PATCH 1322/2137] cpu: Port update_cs_size to Rust The JS version needs to stay too since it can be called by other JS-only functions. --- src/browser/starter.js | 1 - src/native/js_imports.h | 1 - src/rust/cpu2/cpu.rs | 8 ++++++++ src/rust/cpu2/instructions_0f.rs | 2 -- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index ce0bb006..a63ee3e2 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -213,7 +213,6 @@ function V86Starter(options) "verw": function() { return cpu.verw.apply(cpu, arguments); }, "verr": function() { return cpu.verr.apply(cpu, arguments); }, - "update_cs_size": function() { return cpu.update_cs_size.apply(cpu, arguments); }, "cpuid": function() { return cpu.cpuid.apply(cpu, arguments); }, "load_ldt": function() { return cpu.load_ldt.apply(cpu, arguments); }, diff --git a/src/native/js_imports.h b/src/native/js_imports.h index 61feb516..a32f43f4 100644 --- a/src/native/js_imports.h +++ b/src/native/js_imports.h @@ -44,7 +44,6 @@ extern void popa16(void); extern void popa32(void); extern void undefined_instruction(void); extern void unimplemented_sse(void); -extern void update_cs_size(int32_t); extern void update_eflags(int32_t); extern bool switch_seg(int32_t, int32_t); extern void lss16(int32_t, int32_t, int32_t); diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 4b221b36..0e95bd17 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -921,6 +921,14 @@ pub unsafe fn cpl_changed() { *last_virt_esp = -1; } +pub unsafe fn update_cs_size(new_size: bool) { + if *is_32 != new_size { + *is_32 = new_size; + // TODO: + // update_operand_size(); + } +} + pub unsafe fn test_privileges_for_io(port: i32, size: i32) -> bool { if *protected_mode && (*cpl > getiopl() as u8 || (*flags & FLAG_VM != 0)) { if !*tss_size_32 { diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 1221a389..2eb4a487 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -21,8 +21,6 @@ extern "C" { #[no_mangle] fn cpuid(); #[no_mangle] - fn update_cs_size(cs_size: bool); - #[no_mangle] fn lsl(r: i32, v: i32) -> i32; #[no_mangle] fn lar(r: i32, v: i32) -> i32; From 96ef38e901e82dd68643085374e4d4b568dbc57c Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 7 Sep 2018 20:07:33 +0530 Subject: [PATCH 1323/2137] cpu: Port popa{16,32} to Rust --- src/browser/starter.js | 2 -- src/cpu.js | 32 -------------------------------- src/native/js_imports.h | 2 -- src/rust/cpu2/cpu.rs | 32 +++++++++++++++++++++++++++++++- src/rust/cpu2/instructions.rs | 4 ---- src/rust/js_api.rs | 8 +------- 6 files changed, 32 insertions(+), 48 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index a63ee3e2..2449402b 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -204,8 +204,6 @@ function V86Starter(options) "mmap_write32": function(addr, value) { return cpu.mmap_write32(addr, value); }, "mmap_write128": function(addr, value0, value1, value2, value3) { return cpu.mmap_write128(addr, value0, value1, value2, value3); }, - "popa16": function() { return cpu.popa16.apply(cpu, arguments); }, - "popa32": function() { return cpu.popa32.apply(cpu, arguments); }, "arpl": function() { return cpu.arpl.apply(cpu, arguments); }, "lar": function() { return cpu.lar.apply(cpu, arguments); }, diff --git a/src/cpu.js b/src/cpu.js index 8cb307b2..8ec237d7 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -316,8 +316,6 @@ CPU.prototype.wasm_patch = function(wm) this.push16 = get_import("push16_js"); this.push32 = get_import("push32_js"); - this.pop16 = get_import("pop16_js"); - this.pop32s = get_import("pop32s_js"); this.set_stack_reg = get_import("set_stack_reg"); @@ -3611,36 +3609,6 @@ CPU.prototype.is_asize_32 = function() return Boolean(this.is_32[0]) !== ((this.prefixes[0] & PREFIX_MASK_ADDRSIZE) === PREFIX_MASK_ADDRSIZE); }; -CPU.prototype.popa16 = function() -{ - this.translate_address_read(this.get_stack_pointer(0)); - this.translate_address_read(this.get_stack_pointer(15)); - - this.reg16[reg_di] = this.pop16(); - this.reg16[reg_si] = this.pop16(); - this.reg16[reg_bp] = this.pop16(); - this.adjust_stack_reg(2); - this.reg16[reg_bx] = this.pop16(); - this.reg16[reg_dx] = this.pop16(); - this.reg16[reg_cx] = this.pop16(); - this.reg16[reg_ax] = this.pop16(); -}; - -CPU.prototype.popa32 = function() -{ - this.translate_address_read(this.get_stack_pointer(0)); - this.translate_address_read(this.get_stack_pointer(31)); - - this.reg32s[reg_edi] = this.pop32s(); - this.reg32s[reg_esi] = this.pop32s(); - this.reg32s[reg_ebp] = this.pop32s(); - this.adjust_stack_reg(4); - this.reg32s[reg_ebx] = this.pop32s(); - this.reg32s[reg_edx] = this.pop32s(); - this.reg32s[reg_ecx] = this.pop32s(); - this.reg32s[reg_eax] = this.pop32s(); -}; - CPU.prototype.lss16 = function(addr, reg, seg) { var new_reg = this.safe_read16(addr), diff --git a/src/native/js_imports.h b/src/native/js_imports.h index a32f43f4..689a59df 100644 --- a/src/native/js_imports.h +++ b/src/native/js_imports.h @@ -40,8 +40,6 @@ extern void mmap_write128(uint32_t, int32_t, int32_t, int32_t, int32_t); extern void mmap_write16(uint32_t, int32_t); extern void mmap_write32(uint32_t, int32_t); extern void mmap_write8(uint32_t, int32_t); -extern void popa16(void); -extern void popa32(void); extern void undefined_instruction(void); extern void unimplemented_sse(void); extern void update_eflags(int32_t); diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 0e95bd17..806d26fe 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -23,7 +23,9 @@ use cpu2::memory::{ in_mapped_range, read128, read16, read32s, read64s, read8, read_aligned16, read_aligned32, write128, write16, write32, write64, write8, write_aligned32, }; -use cpu2::misc_instr::{getaf, getcf, getof, getpf, getsf, getzf}; +use cpu2::misc_instr::{ + adjust_stack_reg, get_stack_pointer, getaf, getcf, getof, getpf, getsf, getzf, pop16, pop32s, +}; use cpu2::modrm::{resolve_modrm16, resolve_modrm32}; use paging::OrPageFault; use profiler; @@ -978,6 +980,34 @@ pub unsafe fn test_privileges_for_io(port: i32, size: i32) -> bool { return true; } +pub unsafe fn popa16() { + return_on_pagefault!(translate_address_read(get_stack_pointer(0))); + return_on_pagefault!(translate_address_read(get_stack_pointer(15))); + + *reg16.offset(DI as isize) = pop16().unwrap() as u16; + *reg16.offset(SI as isize) = pop16().unwrap() as u16; + *reg16.offset(BP as isize) = pop16().unwrap() as u16; + adjust_stack_reg(2); + *reg16.offset(BX as isize) = pop16().unwrap() as u16; + *reg16.offset(DX as isize) = pop16().unwrap() as u16; + *reg16.offset(CX as isize) = pop16().unwrap() as u16; + *reg16.offset(AX as isize) = pop16().unwrap() as u16; +} + +pub unsafe fn popa32() { + return_on_pagefault!(translate_address_read(get_stack_pointer(0))); + return_on_pagefault!(translate_address_read(get_stack_pointer(31))); + + *reg32s.offset(EDI as isize) = pop32s().unwrap(); + *reg32s.offset(ESI as isize) = pop32s().unwrap(); + *reg32s.offset(EBP as isize) = pop32s().unwrap(); + adjust_stack_reg(4); + *reg32s.offset(EBX as isize) = pop32s().unwrap(); + *reg32s.offset(EDX as isize) = pop32s().unwrap(); + *reg32s.offset(ECX as isize) = pop32s().unwrap(); + *reg32s.offset(EAX as isize) = pop32s().unwrap(); +} + pub unsafe fn trigger_gp(mut code: i32) { *instruction_pointer = *previous_ip; raise_exception_with_code(CPU_EXCEPTION_GP, code); diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index 45cd1c66..d80b492b 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -10,10 +10,6 @@ extern "C" { #[no_mangle] fn enter32(size: i32, nesting_level: i32); - #[no_mangle] - fn popa16(); - #[no_mangle] - fn popa32(); #[no_mangle] fn arpl(seg: i32, r: i32) -> i32; #[no_mangle] diff --git a/src/rust/js_api.rs b/src/rust/js_api.rs index 43806b66..22646c39 100644 --- a/src/rust/js_api.rs +++ b/src/rust/js_api.rs @@ -2,7 +2,7 @@ use cpu2::cpu::{ safe_read16, safe_read32s, safe_write16, safe_write32, translate_address_read, translate_address_system_read, translate_address_system_write, writable_or_pagefault, }; -use cpu2::misc_instr::{pop16, pop32s, push16, push32}; +use cpu2::misc_instr::{push16, push32}; #[no_mangle] pub unsafe fn safe_read16_js(addr: i32) -> i32 { safe_read16(addr).unwrap() } @@ -35,9 +35,3 @@ pub unsafe fn push16_js(value: i32) { push16(value).unwrap() } #[no_mangle] pub unsafe fn push32_js(value: i32) { push32(value).unwrap() } - -#[no_mangle] -pub unsafe fn pop16_js() -> i32 { pop16().unwrap() } - -#[no_mangle] -pub unsafe fn pop32s_js() -> i32 { pop32s().unwrap() } From 68c9fb111c87c44fc8e5c80eb7b4230bdfe2c74c Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 7 Sep 2018 21:39:40 +0530 Subject: [PATCH 1324/2137] cleanup: Remove unneeded TODO comments and whitespace --- src/rust/cpu2/cpu.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 806d26fe..8df48529 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -899,16 +899,12 @@ pub unsafe fn set_cr0(cr0: i32) { if cr0 & CR0_AM != 0 { dbg_log!("Warning: Unimplemented: cr0 alignment mask"); } - if (cr0 & (CR0_PE | CR0_PG)) == CR0_PG { panic!("cannot load PG without PE"); } let old_cr0 = *cr; - *cr = cr0; - - // TODO: Consider have_fpu and CR0_EM emulation set *cr |= CR0_ET; if old_cr0 & (CR0_PG | CR0_WP) != cr0 & (CR0_PG | CR0_WP) { @@ -926,8 +922,6 @@ pub unsafe fn cpl_changed() { pub unsafe fn update_cs_size(new_size: bool) { if *is_32 != new_size { *is_32 = new_size; - // TODO: - // update_operand_size(); } } From e14ef4b8a90a0f7866688026b4325c2ebb7deb36 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Fri, 7 Sep 2018 12:34:17 +1200 Subject: [PATCH 1325/2137] Filesystem: Add tests for whole-file locks. --- tests/devices/virtio_9p.js | 43 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index 5b4dee00..95bf1193 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -957,6 +957,49 @@ const tests = done(); }, }, + { + name: "File Locks", + timeout: 60, + start: () => + { + emulator.serial0_send("touch /mnt/file\n"); + emulator.serial0_send("mkfifo /mnt/fifo1\n"); + emulator.serial0_send("mkfifo /mnt/fifo2\n"); + + emulator.serial0_send("flock -s /mnt/file -c 'cat /mnt/fifo1 >> /mnt/file' &\n"); + emulator.serial0_send("flock -s /mnt/file -c 'echo lock-shared-2 >> /mnt/file' \n"); + emulator.serial0_send("echo lock-shared-1 > /mnt/fifo1\n"); + + emulator.serial0_send("flock -x /mnt/file -c 'cat /mnt/fifo1 >> /mnt/file' &\n"); + emulator.serial0_send("flock -x /mnt/file -c 'echo lock-exclusive-2 >> /mnt/file' &\n"); + emulator.serial0_send("echo lock-exclusive-1 > /mnt/fifo1\n"); + + emulator.serial0_send("flock -s /mnt/file -c 'cat /mnt/fifo1 >> /mnt/file' &\n"); + emulator.serial0_send("flock -s /mnt/file -c 'cat /mnt/fifo2 >> /mnt/file' &\n"); + emulator.serial0_send("flock -x /mnt/file -c 'echo lock-exclusive-3 >> /mnt/file' &\n"); + emulator.serial0_send("echo lock-shared-4 > /mnt/fifo2\n"); + emulator.serial0_send("echo lock-shared-3 > /mnt/fifo1\n"); + + emulator.serial0_send("echo start-capture;\\\n"); + emulator.serial0_send("cat /mnt/file;\\\n"); + emulator.serial0_send("echo done-locks\n"); + }, + capture_trigger: "start-capture", + end_trigger: "done-locks", + end: (capture, done) => + { + assert_equal(capture, + "lock-shared-2\n" + + "lock-shared-1\n" + + "lock-exclusive-1\n" + + "lock-exclusive-2\n" + + "lock-shared-4\n" + + "lock-shared-3\n" + + "lock-exclusive-3\n"); + + done(); + }, + }, { name: "Stress Files", timeout: 360, From 267083e8978c09be1f7581db32d8f6482e457585 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Fri, 7 Sep 2018 12:36:51 +1200 Subject: [PATCH 1326/2137] Filesystem: Implement POSIX record locks --- lib/9p.js | 51 ++++++++- lib/filesystem.js | 286 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 329 insertions(+), 8 deletions(-) diff --git a/lib/9p.js b/lib/9p.js index 5e9074d0..9286cd0b 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -13,7 +13,6 @@ const VIRTIO_9P_MAX_TAGLEN = 254; // TODO // flush -// lock? var EPERM = 1; /* Operation not permitted */ var ENOENT = 2; /* No such file or directory */ @@ -48,6 +47,18 @@ var P9_STAT_MODE_SETUID = 0x00080000; var P9_STAT_MODE_SETGID = 0x00040000; var P9_STAT_MODE_SETVTX = 0x00010000; +const P9_LOCK_TYPE_RDLCK = 0; +const P9_LOCK_TYPE_WRLCK = 1; +const P9_LOCK_TYPE_UNLCK = 2; + +const P9_LOCK_FLAGS_BLOCK = 1; +const P9_LOCK_FLAGS_RECLAIM = 2; + +const P9_LOCK_SUCCESS = 0; +const P9_LOCK_BLOCKED = 1; +const P9_LOCK_ERROR = 2; +const P9_LOCK_GRACE = 3; + var FID_NONE = -1; var FID_INODE = 1; var FID_XATTR = 2; @@ -408,17 +419,45 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { this.SendReply(bufchain); break; - case 52: // lock always suceed - message.Debug("lock file\n"); - marshall.Marshall(["w"], [0], this.replybuffer, 7); + case 52: // lock + var req = marshall.Unmarshall(["w", "b", "w", "d", "d", "w", "s"], buffer, state); + var fid = req[0]; + var flags = req[2]; + var lock_request = this.fs.DescribeLock(req[1], req[3], req[4], req[5], req[6]); + message.Debug("[lock] fid=" + fid + + ", type=" + lock_request.type + ", start=" + lock_request.start + + ", length=" + lock_request.length + ", proc_id=" + lock_request.proc_id); + + var ret = this.fs.Lock(this.fids[fid].inodeid, lock_request, flags); + + marshall.Marshall(["b"], [ret], this.replybuffer, 7); this.BuildReply(id, tag, 1); this.SendReply(bufchain); break; - /* case 54: // getlock + var req = marshall.Unmarshall(["w", "b", "d", "d", "w", "s"], buffer, state); + var fid = req[0]; + var lock_request = this.fs.DescribeLock(req[1], req[2], req[3], req[4], req[5]); + message.Debug("[getlock] fid=" + fid + + ", type=" + lock_request.type + ", start=" + lock_request.start + + ", length=" + lock_request.length + ", proc_id=" + lock_request.proc_id); + + var ret = this.fs.GetLock(this.fids[fid].inodeid, lock_request); + + if(!ret) + { + ret = lock_request; + ret.type = P9_LOCK_TYPE_UNLCK; + } + + size = marshall.Marshall(["b", "d", "d", "w", "s"], + [ret.type, ret.start, ret.length, ret.proc_id, ret.client_id], + this.replybuffer, 7); + + this.BuildReply(id, tag, size); + this.SendReply(bufchain); break; - */ case 24: // getattr var req = marshall.Unmarshall(["w", "d"], buffer, state); diff --git a/lib/filesystem.js b/lib/filesystem.js index 469a5726..529e8b45 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -462,6 +462,9 @@ function Inode(qidnumber) this.dirty = false; // has this file changed? this.sha256sum = ""; + /** @type{!Array} */ + this.locks = []; // lock regions applied to the file, sorted by starting offset. + // For forwarders: this.mount_id = -1; // which fs in this.mounts does this inode forward to? this.foreign_id = -1; // which foreign inode id does it represent? @@ -476,7 +479,7 @@ Inode.prototype.get_state = function() const state = []; state[0] = this.updatedir; state[1] = [...this.direntries]; - //state[2] + state[2] = this.locks; //state[3] state[4] = this.status; //state[5] @@ -507,7 +510,13 @@ Inode.prototype.set_state = function(state) { this.updatedir = state[0]; this.direntries = new Map(state[1]); - //state[2]; + this.locks = []; + for(const lock_state of state[2]) + { + const lock = new FSLockRegion(); + lock.set_state(lock_state); + this.locks.push(lock); + } //state[3]; this.status = state[4]; //state[5]; @@ -1691,3 +1700,276 @@ FS.prototype.Mount = function(path, fs) return idx; }; + +/** + * @constructor + */ +function FSLockRegion() +{ + this.type = P9_LOCK_TYPE_UNLCK; + this.start = 0; + this.length = 0; + this.proc_id = -1; + this.client_id = ""; +} + +FSLockRegion.prototype.get_state = function() +{ + const state = []; + + state[0] = this.type; + state[1] = this.start; + state[2] = this.length; + state[3] = this.proc_id; + state[4] = this.client_id; + + return state; +}; + +FSLockRegion.prototype.set_state = function(state) +{ + this.type = state[0]; + this.start = state[1]; + this.length = state[2]; + this.proc_id = state[3]; + this.client_id = state[4]; +}; + +/** + * @return {FSLockRegion} + */ +FSLockRegion.prototype.clone = function() +{ + const new_region = new FSLockRegion(); + new_region.set_state(this.get_state()); + return new_region; +}; + +/** + * @param {FSLockRegion} region + * @return {boolean} + */ +FSLockRegion.prototype.conflicts_with = function(region) +{ + if(this.proc_id === region.proc_id && this.client_id === region.client_id) return false; + if(this.type === P9_LOCK_TYPE_UNLCK || region.type === P9_LOCK_TYPE_UNLCK) return false; + if(this.type !== P9_LOCK_TYPE_WRLCK && region.type !== P9_LOCK_TYPE_WRLCK) return false; + if(this.start + this.length <= region.start) return false; + if(region.start + region.length <= this.start) return false; + return true; +}; + +/** + * @param {FSLockRegion} region + * @return {boolean} + */ +FSLockRegion.prototype.is_alike = function(region) +{ + return region.proc_id === this.proc_id && + region.client_id === this.client_id && + region.type === this.type; +}; + +/** + * @param {FSLockRegion} region + * @return {boolean} + */ +FSLockRegion.prototype.may_merge_after = function(region) +{ + return this.is_alike(region) && region.start + region.length === this.start; +}; + +/** + * @param {number} type + * @param {number} start + * @param {number} length + * @param {number} proc_id + * @param {string} client_id + * @return {!FSLockRegion} + */ +FS.prototype.DescribeLock = function(type, start, length, proc_id, client_id) +{ + dbg_assert(type === P9_LOCK_TYPE_RDLCK || + type === P9_LOCK_TYPE_WRLCK || + type === P9_LOCK_TYPE_UNLCK, + "Filesystem: Invalid lock type: " + type); + dbg_assert(start >= 0, "Filesystem: Invalid negative lock starting offset: " + start); + dbg_assert(length >= 0, "Filesystem: Invalid negative lock length: " + length); + + const lock = new FSLockRegion(); + lock.type = type; + lock.start = start; + // Internally represent length of '0' as infinity. + lock.length = length === 0 ? Infinity : length; + lock.proc_id = proc_id; + lock.client_id = client_id; + + return lock; +}; + +/** + * @param {number} id + * @param {FSLockRegion} request + * @return {FSLockRegion} The first conflicting lock found, or null if requested lock is possible. + */ +FS.prototype.GetLock = function(id, request) +{ + const inode = this.inodes[id]; + + if(this.is_forwarder(inode)) + { + const foreign_id = inode.foreign_id; + return this.follow_fs(inode).GetLock(foreign_id, request); + } + + for(const region of inode.locks) + { + if(request.conflicts_with(region)) + { + const ret = region.clone(); + // Convert internal representation of '0' back. + ret.length = ret.length === Infinity ? 0 : ret.length; + return ret; + } + } + return null; +}; + +/** + * @param {number} id + * @param {FSLockRegion} request + * @param {number} flags + * @return {number} One of P9_LOCK_SUCCESS / P9_LOCK_BLOCKED / P9_LOCK_ERROR / P9_LOCK_GRACE. + */ +FS.prototype.Lock = function(id, request, flags) +{ + const inode = this.inodes[id]; + + if(this.is_forwarder(inode)) + { + const foreign_id = inode.foreign_id; + return this.follow_fs(inode).Lock(foreign_id, request, flags); + } + + request = request.clone(); + + // (1) Check whether lock is possible before any modification. + if(request.type !== P9_LOCK_TYPE_UNLCK && this.GetLock(id, request)) + { + return P9_LOCK_BLOCKED; + } + + // (2) Subtract requested region from locks of the same owner. + for(let i = 0; i < inode.locks.length; i++) + { + const region = inode.locks[i]; + + dbg_assert(region.length > 0, + "Filesystem: Found non-positive lock region length: " + region.length); + dbg_assert(region.type === P9_LOCK_TYPE_RDLCK || region.type === P9_LOCK_TYPE_WRLCK, + "Filesystem: Found invalid lock type: " + region.type); + dbg_assert(!inode.locks[i-1] || inode.locks[i-1].start <= region.start, + "Filesystem: Locks should be sorted by starting offset"); + + // Skip to requested region. + if(region.start + region.length <= request.start) continue; + + // Check whether we've skipped past the requested region. + if(request.start + request.length <= region.start) break; + + // Skip over locks of different owners. + if(region.proc_id !== request.proc_id || region.client_id !== request.client_id) + { + dbg_assert(!region.conflicts_with(request), + "Filesytem: Found conflicting lock region, despite already checked for conflicts"); + continue; + } + + // Pretend region would be split into parts 1 and 2. + const start1 = region.start; + const start2 = request.start + request.length; + const length1 = request.start - start1; + const length2 = region.start + region.length - start2; + + if(length1 > 0 && length2 > 0 && region.type === request.type) + { + // Requested region is already locked with the required type. + // Return early - no need to modify anything. + return P9_LOCK_SUCCESS; + } + + if(length1 > 0) + { + // Shrink from right / first half of the split. + region.length = length1; + } + + if(length1 <= 0 && length2 > 0) + { + // Shrink from left. + region.start = start2; + region.length = length2; + } + else if(length2 > 0) + { + // Add second half of the split. + + // Fast-forward to correct location. + while(i < inode.locks.length && inode.locks[i].start < start2) i++; + + inode.locks.splice(i, 0, + this.DescribeLock(region.type, start2, length2, region.proc_id, region.client_id)); + } + else if(length1 <= 0) + { + // Requested region completely covers this region. Delete. + inode.locks.splice(i, 1); + i--; + } + } + + // (3) Insert requested lock region as a whole. + // No point in adding the requested lock region as fragmented bits in the above loop + // and having to merge them all back into one. + if(request.type !== P9_LOCK_TYPE_UNLCK) + { + let new_region = request; + let has_merged = false; + let i = 0; + + // Fast-forward to requested position, and try merging with previous region. + for(; i < inode.locks.length; i++) + { + if(new_region.may_merge_after(inode.locks[i])) + { + inode.locks[i].length += request.length; + new_region = inode.locks[i]; + has_merged = true; + } + if(request.start <= inode.locks[i].start) break; + } + + if(!has_merged) + { + inode.locks.splice(i, 0, new_region); + i++; + } + + // Try merging with the subsequent alike region. + for(; i < inode.locks.length; i++) + { + if(!inode.locks[i].is_alike(new_region)) continue; + + if(inode.locks[i].may_merge_after(new_region)) + { + new_region.length += inode.locks[i].length; + inode.locks.splice(i, 1); + } + + // No more mergable regions after this. + break; + } + } + + return P9_LOCK_SUCCESS; +}; From 400ed64d5422f5ccc5972fb3924c55af92e7ccf6 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Fri, 7 Sep 2018 12:38:18 +1200 Subject: [PATCH 1327/2137] Filesystem: Add tests for byte-range file locks --- tests/devices/virtio_9p.js | 92 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index 95bf1193..a4d12e66 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -997,6 +997,98 @@ const tests = "lock-shared-3\n" + "lock-exclusive-3\n"); + const idx = emulator.fs9p.Search(0, "file"); + + const P9_LOCK_TYPE_RDLCK = 0; + const P9_LOCK_TYPE_WRLCK = 1; + const P9_LOCK_TYPE_UNLCK = 2; + const P9_LOCK_SUCCESS = 0; + const P9_LOCK_BLOCKED = 1; + const CLIENT_ID = "under test"; + + function test_getlock(num, type, pos, proc_id, locked) + { + const lock = emulator.fs9p.DescribeLock(type, pos, 1, proc_id, CLIENT_ID); + const ret = emulator.fs9p.GetLock(idx, lock, 0); + assert_equal(ret !== null, locked, + `getlock ${num}: type=${type}, pos=${pos}, proc_id=${proc_id}. Wrong state:`); + } + + function test_lock(num, type, start, length, proc_id, status, lock_state) + { + console.log(` Lock ${num}: type=${type}, start=${start}, length=${length} ` + + ` proc_id=${proc_id}, expected state=${lock_state}`); + + const lock = emulator.fs9p.DescribeLock(type, start, length, proc_id, CLIENT_ID); + assert_equal(emulator.fs9p.Lock(idx, lock, 0), status, "Wrong status:"); + + for(const [i, state] of [...lock_state].entries()) + { + switch(state) + { + case "1": + test_getlock(num, P9_LOCK_TYPE_WRLCK, i, 1, false); + test_getlock(num, P9_LOCK_TYPE_RDLCK, i, 2, false); + test_getlock(num, P9_LOCK_TYPE_WRLCK, i, 2, true); + break; + case "2": + test_getlock(num, P9_LOCK_TYPE_WRLCK, i, 2, false); + test_getlock(num, P9_LOCK_TYPE_RDLCK, i, 1, false); + test_getlock(num, P9_LOCK_TYPE_WRLCK, i, 1, true); + break; + case "3": + test_getlock(num, P9_LOCK_TYPE_RDLCK, i, 1, false); + test_getlock(num, P9_LOCK_TYPE_WRLCK, i, 1, true); + test_getlock(num, P9_LOCK_TYPE_RDLCK, i, 2, false); + test_getlock(num, P9_LOCK_TYPE_WRLCK, i, 2, true); + break; + case "e": + test_getlock(num, P9_LOCK_TYPE_RDLCK, i, 1, false); + test_getlock(num, P9_LOCK_TYPE_RDLCK, i, 2, true); + break; + case "E": + test_getlock(num, P9_LOCK_TYPE_RDLCK, i, 1, true); + test_getlock(num, P9_LOCK_TYPE_RDLCK, i, 2, false); + break; + case "-": + test_getlock(num, P9_LOCK_TYPE_WRLCK, i, 1, false); + test_getlock(num, P9_LOCK_TYPE_WRLCK, i, 2, false); + break; + } + } + } + + // Key: + // 1/2/3 = shared lock by process 1/2/both + // e/E = exclusive lock by process 1/2 + // - = no locks + test_lock(0, P9_LOCK_TYPE_RDLCK, 0, 1, 1, P9_LOCK_SUCCESS, "1-------"); // First lock. + test_lock(1, P9_LOCK_TYPE_RDLCK, 0, 2, 1, P9_LOCK_SUCCESS, "11------"); // Replace. + test_lock(2, P9_LOCK_TYPE_RDLCK, 1, 1, 2, P9_LOCK_SUCCESS, "13------"); + test_lock(3, P9_LOCK_TYPE_RDLCK, 2, 2, 1, P9_LOCK_SUCCESS, "1311----"); // Skip. Merge before. + test_lock(4, P9_LOCK_TYPE_WRLCK, 0, 1, 1, P9_LOCK_SUCCESS, "e311----"); // Shrink left. + test_lock(5, P9_LOCK_TYPE_WRLCK, 1, 1, 1, P9_LOCK_BLOCKED, "e311----"); + test_lock(6, P9_LOCK_TYPE_UNLCK, 0, 4, 1, P9_LOCK_SUCCESS, "-2------"); // Delete. + test_lock(7, P9_LOCK_TYPE_WRLCK, 1, 2, 1, P9_LOCK_BLOCKED, "-2------"); + test_lock(8, P9_LOCK_TYPE_UNLCK, 1, 3, 2, P9_LOCK_SUCCESS, "--------"); // Delete. + test_lock(9, P9_LOCK_TYPE_WRLCK, 1, 1, 1, P9_LOCK_SUCCESS, "-e------"); + test_lock(10, P9_LOCK_TYPE_RDLCK, 3, 3, 1, P9_LOCK_SUCCESS, "-e-111--"); // Skip. + test_lock(11, P9_LOCK_TYPE_RDLCK, 2, 1, 2, P9_LOCK_SUCCESS, "-e2111--"); // Skip past. + test_lock(12, P9_LOCK_TYPE_UNLCK, 2, 1, 2, P9_LOCK_SUCCESS, "-e-111--"); // Delete. + test_lock(13, P9_LOCK_TYPE_WRLCK, 0, 1, 1, P9_LOCK_SUCCESS, "ee-111--"); + test_lock(14, P9_LOCK_TYPE_WRLCK, 1, 4, 1, P9_LOCK_SUCCESS, "eeeee1--"); // Merge before. Shrink both ways. + test_lock(15, P9_LOCK_TYPE_WRLCK, 1, 2, 2, P9_LOCK_BLOCKED, "eeeee1--"); + test_lock(16, P9_LOCK_TYPE_RDLCK, 4, 5, 2, P9_LOCK_BLOCKED, "eeeee1--"); + test_lock(17, P9_LOCK_TYPE_RDLCK, 5, 0, 2, P9_LOCK_SUCCESS, "eeeee322"); + test_lock(18, P9_LOCK_TYPE_UNLCK, 0, 0, 1, P9_LOCK_SUCCESS, "-----222"); // Replace. + test_lock(19, P9_LOCK_TYPE_RDLCK, 4, 0, 2, P9_LOCK_SUCCESS, "----2222"); // Replace. + test_lock(20, P9_LOCK_TYPE_WRLCK, 2, 0, 2, P9_LOCK_SUCCESS, "--EEEEEE"); // Replace. + test_lock(21, P9_LOCK_TYPE_WRLCK, 0, 1, 2, P9_LOCK_SUCCESS, "E-EEEEEE"); + test_lock(22, P9_LOCK_TYPE_WRLCK, 1, 3, 2, P9_LOCK_SUCCESS, "EEEEEEEE"); // Merge both. Shrink left. + test_lock(23, P9_LOCK_TYPE_RDLCK, 3, 4, 2, P9_LOCK_SUCCESS, "EEE2222E"); // Split. + test_lock(24, P9_LOCK_TYPE_RDLCK, 1, 2, 2, P9_LOCK_SUCCESS, "E222222E"); // Merge after. Shrink right. + test_lock(25, P9_LOCK_TYPE_RDLCK, 2, 3, 2, P9_LOCK_SUCCESS, "E222222E"); // No-op. + done(); }, }, From 2bac2198e803b70dbe079d2006337d54080f1ca7 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Fri, 7 Sep 2018 14:13:43 +1200 Subject: [PATCH 1328/2137] Filesystem: Don't store lock length of Infinity Infinity is not JSON.stringifiable and will turn into null during state save and restore. --- lib/filesystem.js | 52 ++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 529e8b45..4585110f 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -1745,6 +1745,24 @@ FSLockRegion.prototype.clone = function() return new_region; }; +/** + * Handle special interpretation of length of 0. + * @return {number} + */ +FSLockRegion.prototype.get_length = function() +{ + return this.length === 0 ? Infinity : this.length; +}; + +/** + * Handle special interpretation of length of 0. + * @param {number} length + */ +FSLockRegion.prototype.set_length = function(length) +{ + this.length = length === Infinity ? 0 : length; +}; + /** * @param {FSLockRegion} region * @return {boolean} @@ -1754,8 +1772,8 @@ FSLockRegion.prototype.conflicts_with = function(region) if(this.proc_id === region.proc_id && this.client_id === region.client_id) return false; if(this.type === P9_LOCK_TYPE_UNLCK || region.type === P9_LOCK_TYPE_UNLCK) return false; if(this.type !== P9_LOCK_TYPE_WRLCK && region.type !== P9_LOCK_TYPE_WRLCK) return false; - if(this.start + this.length <= region.start) return false; - if(region.start + region.length <= this.start) return false; + if(this.start + this.get_length() <= region.start) return false; + if(region.start + region.get_length() <= this.start) return false; return true; }; @@ -1776,7 +1794,7 @@ FSLockRegion.prototype.is_alike = function(region) */ FSLockRegion.prototype.may_merge_after = function(region) { - return this.is_alike(region) && region.start + region.length === this.start; + return this.is_alike(region) && region.start + region.get_length() === this.start; }; /** @@ -1799,8 +1817,7 @@ FS.prototype.DescribeLock = function(type, start, length, proc_id, client_id) const lock = new FSLockRegion(); lock.type = type; lock.start = start; - // Internally represent length of '0' as infinity. - lock.length = length === 0 ? Infinity : length; + lock.set_length(length); lock.proc_id = proc_id; lock.client_id = client_id; @@ -1826,10 +1843,7 @@ FS.prototype.GetLock = function(id, request) { if(request.conflicts_with(region)) { - const ret = region.clone(); - // Convert internal representation of '0' back. - ret.length = ret.length === Infinity ? 0 : ret.length; - return ret; + return region.clone(); } } return null; @@ -1864,18 +1878,18 @@ FS.prototype.Lock = function(id, request, flags) { const region = inode.locks[i]; - dbg_assert(region.length > 0, - "Filesystem: Found non-positive lock region length: " + region.length); + dbg_assert(region.get_length() > 0, + "Filesystem: Found non-positive lock region length: " + region.get_length()); dbg_assert(region.type === P9_LOCK_TYPE_RDLCK || region.type === P9_LOCK_TYPE_WRLCK, "Filesystem: Found invalid lock type: " + region.type); dbg_assert(!inode.locks[i-1] || inode.locks[i-1].start <= region.start, "Filesystem: Locks should be sorted by starting offset"); // Skip to requested region. - if(region.start + region.length <= request.start) continue; + if(region.start + region.get_length() <= request.start) continue; // Check whether we've skipped past the requested region. - if(request.start + request.length <= region.start) break; + if(request.start + request.get_length() <= region.start) break; // Skip over locks of different owners. if(region.proc_id !== request.proc_id || region.client_id !== request.client_id) @@ -1887,9 +1901,9 @@ FS.prototype.Lock = function(id, request, flags) // Pretend region would be split into parts 1 and 2. const start1 = region.start; - const start2 = request.start + request.length; + const start2 = request.start + request.get_length(); const length1 = request.start - start1; - const length2 = region.start + region.length - start2; + const length2 = region.start + region.get_length() - start2; if(length1 > 0 && length2 > 0 && region.type === request.type) { @@ -1901,14 +1915,14 @@ FS.prototype.Lock = function(id, request, flags) if(length1 > 0) { // Shrink from right / first half of the split. - region.length = length1; + region.set_length(length1); } if(length1 <= 0 && length2 > 0) { // Shrink from left. region.start = start2; - region.length = length2; + region.set_length(length2); } else if(length2 > 0) { @@ -1942,7 +1956,7 @@ FS.prototype.Lock = function(id, request, flags) { if(new_region.may_merge_after(inode.locks[i])) { - inode.locks[i].length += request.length; + inode.locks[i].set_length(inode.locks[i].get_length() + request.get_length()); new_region = inode.locks[i]; has_merged = true; } @@ -1962,7 +1976,7 @@ FS.prototype.Lock = function(id, request, flags) if(inode.locks[i].may_merge_after(new_region)) { - new_region.length += inode.locks[i].length; + new_region.set_length(new_region.get_length() + inode.locks[i].get_length()); inode.locks.splice(i, 1); } From f7ee28d8ca28d858e54ccc030a7bff15dba10ec4 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Fri, 7 Sep 2018 17:02:08 +1200 Subject: [PATCH 1329/2137] Filesystem tests: Replace nlinks script with function Simplifies the code, as well as to experiment to see why there are processes being killed during only the hard links test and only on CI. --- tests/devices/virtio_9p.js | 46 ++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index a4d12e66..f4e683cc 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -408,23 +408,21 @@ const tests = ], start: () => { - // Helper script that prints filename followed by nlinks. - emulator.serial0_send('cat << "EOF" > /mnt/nlinks\n'); - emulator.serial0_send('#!/bin/sh\n'); - emulator.serial0_send(`ls -dli $@ | awk '{ print "'$@' "$3 }'\n`); - emulator.serial0_send("EOF\n"); - emulator.serial0_send("chmod +x /mnt/nlinks\n"); + // Helper that prints filename followed by nlinks. + emulator.serial0_send("nlinks() {\n"); + emulator.serial0_send(` ls -dli $@ | awk '{ print "'$@' "$3 }'\n`); + emulator.serial0_send("}\n"); // Check nlinks before mkdir. - emulator.serial0_send("/mnt/nlinks /mnt | tee -a /mnt/target\n"); + emulator.serial0_send("nlinks /mnt | tee -a /mnt/target\n"); emulator.serial0_send("mkdir /mnt/dir\n"); emulator.serial0_send("echo other > /mnt/target2\n"); // Check nlinks after mkdir. - emulator.serial0_send("/mnt/nlinks /mnt | tee -a /mnt/target\n"); - emulator.serial0_send("/mnt/nlinks /mnt/dir | tee -a /mnt/target\n"); - emulator.serial0_send("/mnt/nlinks /mnt/target | tee -a /mnt/target\n"); + emulator.serial0_send("nlinks /mnt | tee -a /mnt/target\n"); + emulator.serial0_send("nlinks /mnt/dir | tee -a /mnt/target\n"); + emulator.serial0_send("nlinks /mnt/target | tee -a /mnt/target\n"); // Create hard links. emulator.serial0_send("ln /mnt/target /mnt/link1\n"); @@ -441,12 +439,12 @@ const tests = emulator.serial0_send(" echo different inode | tee -a /mnt/link1; }\n"); // Check nlinks after hard links. - emulator.serial0_send("/mnt/nlinks /mnt | tee -a /mnt/dir/link2\n"); - emulator.serial0_send("/mnt/nlinks /mnt/dir | tee -a /mnt/dir/link2\n"); - emulator.serial0_send("/mnt/nlinks /mnt/target | tee -a /mnt/dir/link2\n"); - emulator.serial0_send("/mnt/nlinks /mnt/dir/link2 | tee -a /mnt/dir/link2\n"); - emulator.serial0_send("/mnt/nlinks /mnt/target2 | tee -a /mnt/dir/link2\n"); - emulator.serial0_send("/mnt/nlinks /mnt/link-other | tee -a /mnt/dir/link2\n"); + emulator.serial0_send("nlinks /mnt | tee -a /mnt/dir/link2\n"); + emulator.serial0_send("nlinks /mnt/dir | tee -a /mnt/dir/link2\n"); + emulator.serial0_send("nlinks /mnt/target | tee -a /mnt/dir/link2\n"); + emulator.serial0_send("nlinks /mnt/dir/link2 | tee -a /mnt/dir/link2\n"); + emulator.serial0_send("nlinks /mnt/target2 | tee -a /mnt/dir/link2\n"); + emulator.serial0_send("nlinks /mnt/link-other | tee -a /mnt/dir/link2\n"); // Movement and unlink. emulator.serial0_send("mv /mnt/link1 /mnt/link1-renamed\n"); @@ -462,29 +460,29 @@ const tests = emulator.serial0_send(" echo same inode after mv | tee -a /mnt/link1-renamed; }\n"); // Check nlinks after movement and unlinking. - emulator.serial0_send("/mnt/nlinks /mnt | tee -a /mnt/link2-moved\n"); - emulator.serial0_send("/mnt/nlinks /mnt/dir | tee -a /mnt/link2-moved\n"); - emulator.serial0_send("/mnt/nlinks /mnt/link1-renamed | tee -a /mnt/link2-moved\n"); + emulator.serial0_send("nlinks /mnt | tee -a /mnt/link2-moved\n"); + emulator.serial0_send("nlinks /mnt/dir | tee -a /mnt/link2-moved\n"); + emulator.serial0_send("nlinks /mnt/link1-renamed | tee -a /mnt/link2-moved\n"); emulator.serial0_send("echo start-capture;\\\n"); // Unlink the rest and output the above messages. emulator.serial0_send("rm /mnt/link1-renamed;\\\n"); emulator.serial0_send("echo unlinked link1 >> /mnt/link2-moved;\\\n"); - emulator.serial0_send("/mnt/nlinks /mnt/link2-moved >> /mnt/link2-moved;\\\n"); + emulator.serial0_send("nlinks /mnt/link2-moved >> /mnt/link2-moved;\\\n"); emulator.serial0_send("rm /mnt/link2-moved;\\\n"); emulator.serial0_send("echo unlinked link2 >> /mnt/dir/link3;\\\n"); - emulator.serial0_send("/mnt/nlinks /mnt/dir/link3 >> /mnt/dir/link3;\\\n"); + emulator.serial0_send("nlinks /mnt/dir/link3 >> /mnt/dir/link3;\\\n"); emulator.serial0_send("cat /mnt/dir/link3;\\\n"); emulator.serial0_send("rm /mnt/dir/link3;\\\n"); // Verify nlinks of directories after unlinking hardlinks. - emulator.serial0_send("/mnt/nlinks /mnt;\\\n"); - emulator.serial0_send("/mnt/nlinks /mnt/dir;\\\n"); + emulator.serial0_send("nlinks /mnt;\\\n"); + emulator.serial0_send("nlinks /mnt/dir;\\\n"); // Verify nlinks of root directory after subdirectory is unlinked. emulator.serial0_send("rmdir /mnt/dir;\\\n"); - emulator.serial0_send("/mnt/nlinks /mnt;\\\n"); + emulator.serial0_send("nlinks /mnt;\\\n"); emulator.serial0_send("echo done-hard-links\n"); }, From 401b814f93b05357319479e98cbdad03d93351fb Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 8 Sep 2018 12:46:05 +1200 Subject: [PATCH 1330/2137] Filesystem: Store infinite lock lengths Having both lock.length and lock.get_length() giving different values is confusing. --- lib/9p.js | 10 ++++--- lib/filesystem.js | 55 +++++++++++++------------------------- tests/devices/virtio_9p.js | 9 ++++--- 3 files changed, 31 insertions(+), 43 deletions(-) diff --git a/lib/9p.js b/lib/9p.js index 9286cd0b..280cb756 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -423,7 +423,8 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { var req = marshall.Unmarshall(["w", "b", "w", "d", "d", "w", "s"], buffer, state); var fid = req[0]; var flags = req[2]; - var lock_request = this.fs.DescribeLock(req[1], req[3], req[4], req[5], req[6]); + var lock_length = req[4] === 0 ? Infinity : req[4]; + var lock_request = this.fs.DescribeLock(req[1], req[3], lock_length, req[5], req[6]); message.Debug("[lock] fid=" + fid + ", type=" + lock_request.type + ", start=" + lock_request.start + ", length=" + lock_request.length + ", proc_id=" + lock_request.proc_id); @@ -438,7 +439,8 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { case 54: // getlock var req = marshall.Unmarshall(["w", "b", "d", "d", "w", "s"], buffer, state); var fid = req[0]; - var lock_request = this.fs.DescribeLock(req[1], req[2], req[3], req[4], req[5]); + var lock_length = req[3] === 0 ? Infinity : req[3]; + var lock_request = this.fs.DescribeLock(req[1], req[2], lock_length, req[4], req[5]); message.Debug("[getlock] fid=" + fid + ", type=" + lock_request.type + ", start=" + lock_request.start + ", length=" + lock_request.length + ", proc_id=" + lock_request.proc_id); @@ -451,8 +453,10 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { ret.type = P9_LOCK_TYPE_UNLCK; } + var ret_length = ret.length === Infinity ? 0 : ret.length; + size = marshall.Marshall(["b", "d", "d", "w", "s"], - [ret.type, ret.start, ret.length, ret.proc_id, ret.client_id], + [ret.type, ret.start, ret_length, ret.proc_id, ret.client_id], this.replybuffer, 7); this.BuildReply(id, tag, size); diff --git a/lib/filesystem.js b/lib/filesystem.js index 4585110f..14939f96 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -1708,7 +1708,7 @@ function FSLockRegion() { this.type = P9_LOCK_TYPE_UNLCK; this.start = 0; - this.length = 0; + this.length = Infinity; this.proc_id = -1; this.client_id = ""; } @@ -1719,7 +1719,8 @@ FSLockRegion.prototype.get_state = function() state[0] = this.type; state[1] = this.start; - state[2] = this.length; + // Infinity is not JSON.stringify-able + state[2] = this.length === Infinity ? 0 : this.length; state[3] = this.proc_id; state[4] = this.client_id; @@ -1730,7 +1731,7 @@ FSLockRegion.prototype.set_state = function(state) { this.type = state[0]; this.start = state[1]; - this.length = state[2]; + this.length = state[2] === 0 ? Infinity : state[2]; this.proc_id = state[3]; this.client_id = state[4]; }; @@ -1745,24 +1746,6 @@ FSLockRegion.prototype.clone = function() return new_region; }; -/** - * Handle special interpretation of length of 0. - * @return {number} - */ -FSLockRegion.prototype.get_length = function() -{ - return this.length === 0 ? Infinity : this.length; -}; - -/** - * Handle special interpretation of length of 0. - * @param {number} length - */ -FSLockRegion.prototype.set_length = function(length) -{ - this.length = length === Infinity ? 0 : length; -}; - /** * @param {FSLockRegion} region * @return {boolean} @@ -1772,8 +1755,8 @@ FSLockRegion.prototype.conflicts_with = function(region) if(this.proc_id === region.proc_id && this.client_id === region.client_id) return false; if(this.type === P9_LOCK_TYPE_UNLCK || region.type === P9_LOCK_TYPE_UNLCK) return false; if(this.type !== P9_LOCK_TYPE_WRLCK && region.type !== P9_LOCK_TYPE_WRLCK) return false; - if(this.start + this.get_length() <= region.start) return false; - if(region.start + region.get_length() <= this.start) return false; + if(this.start + this.length <= region.start) return false; + if(region.start + region.length <= this.start) return false; return true; }; @@ -1794,7 +1777,7 @@ FSLockRegion.prototype.is_alike = function(region) */ FSLockRegion.prototype.may_merge_after = function(region) { - return this.is_alike(region) && region.start + region.get_length() === this.start; + return this.is_alike(region) && region.start + region.length === this.start; }; /** @@ -1812,12 +1795,12 @@ FS.prototype.DescribeLock = function(type, start, length, proc_id, client_id) type === P9_LOCK_TYPE_UNLCK, "Filesystem: Invalid lock type: " + type); dbg_assert(start >= 0, "Filesystem: Invalid negative lock starting offset: " + start); - dbg_assert(length >= 0, "Filesystem: Invalid negative lock length: " + length); + dbg_assert(length > 0, "Filesystem: Invalid non-positive lock length: " + length); const lock = new FSLockRegion(); lock.type = type; lock.start = start; - lock.set_length(length); + lock.length = length; lock.proc_id = proc_id; lock.client_id = client_id; @@ -1878,18 +1861,18 @@ FS.prototype.Lock = function(id, request, flags) { const region = inode.locks[i]; - dbg_assert(region.get_length() > 0, - "Filesystem: Found non-positive lock region length: " + region.get_length()); + dbg_assert(region.length > 0, + "Filesystem: Found non-positive lock region length: " + region.length); dbg_assert(region.type === P9_LOCK_TYPE_RDLCK || region.type === P9_LOCK_TYPE_WRLCK, "Filesystem: Found invalid lock type: " + region.type); dbg_assert(!inode.locks[i-1] || inode.locks[i-1].start <= region.start, "Filesystem: Locks should be sorted by starting offset"); // Skip to requested region. - if(region.start + region.get_length() <= request.start) continue; + if(region.start + region.length <= request.start) continue; // Check whether we've skipped past the requested region. - if(request.start + request.get_length() <= region.start) break; + if(request.start + request.length <= region.start) break; // Skip over locks of different owners. if(region.proc_id !== request.proc_id || region.client_id !== request.client_id) @@ -1901,9 +1884,9 @@ FS.prototype.Lock = function(id, request, flags) // Pretend region would be split into parts 1 and 2. const start1 = region.start; - const start2 = request.start + request.get_length(); + const start2 = request.start + request.length; const length1 = request.start - start1; - const length2 = region.start + region.get_length() - start2; + const length2 = region.start + region.length - start2; if(length1 > 0 && length2 > 0 && region.type === request.type) { @@ -1915,14 +1898,14 @@ FS.prototype.Lock = function(id, request, flags) if(length1 > 0) { // Shrink from right / first half of the split. - region.set_length(length1); + region.length = length1; } if(length1 <= 0 && length2 > 0) { // Shrink from left. region.start = start2; - region.set_length(length2); + region.length = length2; } else if(length2 > 0) { @@ -1956,7 +1939,7 @@ FS.prototype.Lock = function(id, request, flags) { if(new_region.may_merge_after(inode.locks[i])) { - inode.locks[i].set_length(inode.locks[i].get_length() + request.get_length()); + inode.locks[i].length += request.length; new_region = inode.locks[i]; has_merged = true; } @@ -1976,7 +1959,7 @@ FS.prototype.Lock = function(id, request, flags) if(inode.locks[i].may_merge_after(new_region)) { - new_region.set_length(new_region.get_length() + inode.locks[i].get_length()); + new_region.length += inode.locks[i].length; inode.locks.splice(i, 1); } diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index f4e683cc..5060b34c 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -1060,6 +1060,7 @@ const tests = // 1/2/3 = shared lock by process 1/2/both // e/E = exclusive lock by process 1/2 // - = no locks + const I = Infinity; test_lock(0, P9_LOCK_TYPE_RDLCK, 0, 1, 1, P9_LOCK_SUCCESS, "1-------"); // First lock. test_lock(1, P9_LOCK_TYPE_RDLCK, 0, 2, 1, P9_LOCK_SUCCESS, "11------"); // Replace. test_lock(2, P9_LOCK_TYPE_RDLCK, 1, 1, 2, P9_LOCK_SUCCESS, "13------"); @@ -1077,10 +1078,10 @@ const tests = test_lock(14, P9_LOCK_TYPE_WRLCK, 1, 4, 1, P9_LOCK_SUCCESS, "eeeee1--"); // Merge before. Shrink both ways. test_lock(15, P9_LOCK_TYPE_WRLCK, 1, 2, 2, P9_LOCK_BLOCKED, "eeeee1--"); test_lock(16, P9_LOCK_TYPE_RDLCK, 4, 5, 2, P9_LOCK_BLOCKED, "eeeee1--"); - test_lock(17, P9_LOCK_TYPE_RDLCK, 5, 0, 2, P9_LOCK_SUCCESS, "eeeee322"); - test_lock(18, P9_LOCK_TYPE_UNLCK, 0, 0, 1, P9_LOCK_SUCCESS, "-----222"); // Replace. - test_lock(19, P9_LOCK_TYPE_RDLCK, 4, 0, 2, P9_LOCK_SUCCESS, "----2222"); // Replace. - test_lock(20, P9_LOCK_TYPE_WRLCK, 2, 0, 2, P9_LOCK_SUCCESS, "--EEEEEE"); // Replace. + test_lock(17, P9_LOCK_TYPE_RDLCK, 5, I, 2, P9_LOCK_SUCCESS, "eeeee322"); + test_lock(18, P9_LOCK_TYPE_UNLCK, 0, I, 1, P9_LOCK_SUCCESS, "-----222"); // Replace. + test_lock(19, P9_LOCK_TYPE_RDLCK, 4, I, 2, P9_LOCK_SUCCESS, "----2222"); // Replace. + test_lock(20, P9_LOCK_TYPE_WRLCK, 2, I, 2, P9_LOCK_SUCCESS, "--EEEEEE"); // Replace. test_lock(21, P9_LOCK_TYPE_WRLCK, 0, 1, 2, P9_LOCK_SUCCESS, "E-EEEEEE"); test_lock(22, P9_LOCK_TYPE_WRLCK, 1, 3, 2, P9_LOCK_SUCCESS, "EEEEEEEE"); // Merge both. Shrink left. test_lock(23, P9_LOCK_TYPE_RDLCK, 3, 4, 2, P9_LOCK_SUCCESS, "EEE2222E"); // Split. From adc035368f4e9bdce78810d6d3e363ab72129286 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 8 Sep 2018 13:16:13 +1200 Subject: [PATCH 1331/2137] Filesystem: Log lock types as readable strings --- lib/9p.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/9p.js b/lib/9p.js index 280cb756..fc7415ea 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -50,6 +50,7 @@ var P9_STAT_MODE_SETVTX = 0x00010000; const P9_LOCK_TYPE_RDLCK = 0; const P9_LOCK_TYPE_WRLCK = 1; const P9_LOCK_TYPE_UNLCK = 2; +const P9_LOCK_TYPES = Object.freeze(["shared", "exclusive", "unlock"]); const P9_LOCK_FLAGS_BLOCK = 1; const P9_LOCK_FLAGS_RECLAIM = 2; @@ -426,7 +427,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { var lock_length = req[4] === 0 ? Infinity : req[4]; var lock_request = this.fs.DescribeLock(req[1], req[3], lock_length, req[5], req[6]); message.Debug("[lock] fid=" + fid + - ", type=" + lock_request.type + ", start=" + lock_request.start + + ", type=" + P9_LOCK_TYPES[lock_request.type] + ", start=" + lock_request.start + ", length=" + lock_request.length + ", proc_id=" + lock_request.proc_id); var ret = this.fs.Lock(this.fids[fid].inodeid, lock_request, flags); @@ -442,7 +443,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { var lock_length = req[3] === 0 ? Infinity : req[3]; var lock_request = this.fs.DescribeLock(req[1], req[2], lock_length, req[4], req[5]); message.Debug("[getlock] fid=" + fid + - ", type=" + lock_request.type + ", start=" + lock_request.start + + ", type=" + P9_LOCK_TYPES[lock_request.type] + ", start=" + lock_request.start + ", length=" + lock_request.length + ", proc_id=" + lock_request.proc_id); var ret = this.fs.GetLock(this.fids[fid].inodeid, lock_request); From a23b4f969e9e8b2e8eff1b4989a83279a3d45d42 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 8 Sep 2018 13:37:33 +1200 Subject: [PATCH 1332/2137] Filesystem tests: Also use non-blocking flock -n --- tests/devices/virtio_9p.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index 5060b34c..e7b8c238 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -961,18 +961,21 @@ const tests = start: () => { emulator.serial0_send("touch /mnt/file\n"); + emulator.serial0_send("touch /mnt/logs\n"); emulator.serial0_send("mkfifo /mnt/fifo1\n"); emulator.serial0_send("mkfifo /mnt/fifo2\n"); emulator.serial0_send("flock -s /mnt/file -c 'cat /mnt/fifo1 >> /mnt/file' &\n"); emulator.serial0_send("flock -s /mnt/file -c 'echo lock-shared-2 >> /mnt/file' \n"); + emulator.serial0_send("flock -xn /mnt/file -c 'echo lock unblocked! >> /mnt/logs' \n"); emulator.serial0_send("echo lock-shared-1 > /mnt/fifo1\n"); emulator.serial0_send("flock -x /mnt/file -c 'cat /mnt/fifo1 >> /mnt/file' &\n"); emulator.serial0_send("flock -x /mnt/file -c 'echo lock-exclusive-2 >> /mnt/file' &\n"); + emulator.serial0_send("flock -sn /mnt/file -c 'echo lock unblocked! >> /mnt/logs' \n"); emulator.serial0_send("echo lock-exclusive-1 > /mnt/fifo1\n"); - emulator.serial0_send("flock -s /mnt/file -c 'cat /mnt/fifo1 >> /mnt/file' &\n"); + emulator.serial0_send("flock -sn /mnt/file -c 'cat /mnt/fifo1 >> /mnt/file' &\n"); emulator.serial0_send("flock -s /mnt/file -c 'cat /mnt/fifo2 >> /mnt/file' &\n"); emulator.serial0_send("flock -x /mnt/file -c 'echo lock-exclusive-3 >> /mnt/file' &\n"); emulator.serial0_send("echo lock-shared-4 > /mnt/fifo2\n"); @@ -980,6 +983,7 @@ const tests = emulator.serial0_send("echo start-capture;\\\n"); emulator.serial0_send("cat /mnt/file;\\\n"); + emulator.serial0_send("cat /mnt/logs;\\\n"); emulator.serial0_send("echo done-locks\n"); }, capture_trigger: "start-capture", From d37c8295aa04aa64855e9ee09331ada18f81e00a Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 7 Sep 2018 16:17:39 -0500 Subject: [PATCH 1333/2137] jit: Mask shifts and rotates to 5 bits --- src/rust/cpu2/arith.rs | 30 +++++++++++++++++++++++++ src/rust/jit_instructions.rs | 43 ++++++++++++++++++++++-------------- 2 files changed, 56 insertions(+), 17 deletions(-) diff --git a/src/rust/cpu2/arith.rs b/src/rust/cpu2/arith.rs index d908f17f..a80517c8 100644 --- a/src/rust/cpu2/arith.rs +++ b/src/rust/cpu2/arith.rs @@ -426,8 +426,10 @@ pub unsafe fn xor8(mut x: i32, mut y: i32) -> i32 { return xor(x, y, OPSIZE_8); pub unsafe fn xor16(mut x: i32, mut y: i32) -> i32 { return xor(x, y, OPSIZE_16); } #[no_mangle] pub unsafe fn xor32(mut x: i32, mut y: i32) -> i32 { return xor(x, y, OPSIZE_32); } + #[no_mangle] pub unsafe fn rol8(mut dest_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); if 0 == count { return dest_operand; } @@ -443,6 +445,7 @@ pub unsafe fn rol8(mut dest_operand: i32, mut count: i32) -> i32 { } #[no_mangle] pub unsafe fn rol16(mut dest_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); if 0 == count { return dest_operand; } @@ -458,6 +461,7 @@ pub unsafe fn rol16(mut dest_operand: i32, mut count: i32) -> i32 { } #[no_mangle] pub unsafe fn rol32(mut dest_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); if 0 == count { return dest_operand; } @@ -473,6 +477,7 @@ pub unsafe fn rol32(mut dest_operand: i32, mut count: i32) -> i32 { } #[no_mangle] pub unsafe fn rcl8(mut dest_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); count %= 9; if 0 == count { return dest_operand; @@ -489,6 +494,7 @@ pub unsafe fn rcl8(mut dest_operand: i32, mut count: i32) -> i32 { } #[no_mangle] pub unsafe fn rcl16(mut dest_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); count %= 17; if 0 == count { return dest_operand; @@ -505,6 +511,7 @@ pub unsafe fn rcl16(mut dest_operand: i32, mut count: i32) -> i32 { } #[no_mangle] pub unsafe fn rcl32(mut dest_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); if 0 == count { return dest_operand; } @@ -522,6 +529,7 @@ pub unsafe fn rcl32(mut dest_operand: i32, mut count: i32) -> i32 { } #[no_mangle] pub unsafe fn ror8(mut dest_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); if 0 == count { return dest_operand; } @@ -537,6 +545,7 @@ pub unsafe fn ror8(mut dest_operand: i32, mut count: i32) -> i32 { } #[no_mangle] pub unsafe fn ror16(mut dest_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); if 0 == count { return dest_operand; } @@ -552,6 +561,7 @@ pub unsafe fn ror16(mut dest_operand: i32, mut count: i32) -> i32 { } #[no_mangle] pub unsafe fn ror32(mut dest_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); if 0 == count { return dest_operand; } @@ -567,6 +577,7 @@ pub unsafe fn ror32(mut dest_operand: i32, mut count: i32) -> i32 { } #[no_mangle] pub unsafe fn rcr8(mut dest_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); count %= 9; if 0 == count { return dest_operand; @@ -583,6 +594,7 @@ pub unsafe fn rcr8(mut dest_operand: i32, mut count: i32) -> i32 { } #[no_mangle] pub unsafe fn rcr16(mut dest_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); count %= 17; if 0 == count { return dest_operand; @@ -599,6 +611,7 @@ pub unsafe fn rcr16(mut dest_operand: i32, mut count: i32) -> i32 { } #[no_mangle] pub unsafe fn rcr32(mut dest_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); if 0 == count { return dest_operand; } @@ -634,6 +647,7 @@ pub unsafe fn div8(mut source_operand: u32) { return; }; } + #[no_mangle] pub unsafe fn idiv8(mut source_operand: i32) { if source_operand == 0 { @@ -745,8 +759,10 @@ pub unsafe fn idiv32(mut source_operand: i32) { } }; } + #[no_mangle] pub unsafe fn shl8(mut dest_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; } @@ -762,6 +778,7 @@ pub unsafe fn shl8(mut dest_operand: i32, mut count: i32) -> i32 { } #[no_mangle] pub unsafe fn shl16(mut dest_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; } @@ -777,6 +794,7 @@ pub unsafe fn shl16(mut dest_operand: i32, mut count: i32) -> i32 { } #[no_mangle] pub unsafe fn shl32(mut dest_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; } @@ -792,6 +810,7 @@ pub unsafe fn shl32(mut dest_operand: i32, mut count: i32) -> i32 { } #[no_mangle] pub unsafe fn shr8(mut dest_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; } @@ -807,6 +826,7 @@ pub unsafe fn shr8(mut dest_operand: i32, mut count: i32) -> i32 { } #[no_mangle] pub unsafe fn shr16(mut dest_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; } @@ -822,6 +842,7 @@ pub unsafe fn shr16(mut dest_operand: i32, mut count: i32) -> i32 { } #[no_mangle] pub unsafe fn shr32(mut dest_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; } @@ -837,6 +858,7 @@ pub unsafe fn shr32(mut dest_operand: i32, mut count: i32) -> i32 { } #[no_mangle] pub unsafe fn sar8(mut dest_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; } @@ -857,6 +879,7 @@ pub unsafe fn sar8(mut dest_operand: i32, mut count: i32) -> i32 { } #[no_mangle] pub unsafe fn sar16(mut dest_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; } @@ -876,6 +899,7 @@ pub unsafe fn sar16(mut dest_operand: i32, mut count: i32) -> i32 { } #[no_mangle] pub unsafe fn sar32(mut dest_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; } @@ -888,8 +912,10 @@ pub unsafe fn sar32(mut dest_operand: i32, mut count: i32) -> i32 { return *last_result; }; } + #[no_mangle] pub unsafe fn shrd16(mut dest_operand: i32, mut source_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; } @@ -910,6 +936,7 @@ pub unsafe fn shrd16(mut dest_operand: i32, mut source_operand: i32, mut count: } #[no_mangle] pub unsafe fn shrd32(mut dest_operand: i32, mut source_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; } @@ -925,6 +952,7 @@ pub unsafe fn shrd32(mut dest_operand: i32, mut source_operand: i32, mut count: } #[no_mangle] pub unsafe fn shld16(mut dest_operand: i32, mut source_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; } @@ -946,6 +974,7 @@ pub unsafe fn shld16(mut dest_operand: i32, mut source_operand: i32, mut count: } #[no_mangle] pub unsafe fn shld32(mut dest_operand: i32, mut source_operand: i32, mut count: i32) -> i32 { + dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; } @@ -964,6 +993,7 @@ pub unsafe fn shld32(mut dest_operand: i32, mut source_operand: i32, mut count: return *last_result; }; } + #[no_mangle] pub unsafe fn bt_reg(mut bit_base: i32, mut bit_offset: i32) { *flags = *flags & !1 | bit_base >> bit_offset & 1; diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 955bdf8b..d2eab995 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -303,8 +303,15 @@ macro_rules! define_instruction_write_reg32( ) ); +macro_rules! mask_imm( + ($imm:expr, imm8_5bits) => { $imm & 31 }; + ($imm:expr, imm8s) => { $imm }; + ($imm:expr, imm16) => { $imm }; + ($imm:expr, imm32) => { $imm }; +); + macro_rules! make_imm_read( - ($ctx:expr, imm8) => { $ctx.cpu.read_imm8() }; + ($ctx:expr, imm8_5bits) => { $ctx.cpu.read_imm8() & 31 }; ($ctx:expr, imm8s) => { $ctx.cpu.read_imm8s() }; ($ctx:expr, imm16) => { $ctx.cpu.read_imm16() }; ($ctx:expr, imm32) => { $ctx.cpu.read_imm32() }; @@ -418,6 +425,7 @@ macro_rules! define_instruction_read_write_mem16( } pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { + let imm = mask_imm!(imm, $imm); ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r1) as i32); codegen::gen_get_reg16(ctx.builder, r1); ctx.builder.instruction_body.const_i32(imm as i32); @@ -535,6 +543,7 @@ macro_rules! define_instruction_read_write_mem32( } pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { + let imm = mask_imm!(imm, $imm); ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r1) as i32); codegen::gen_get_reg32(ctx.builder, r1); ctx.builder.instruction_body.const_i32(imm as i32); @@ -1169,14 +1178,14 @@ define_instruction_read_write_mem16!( "instr16_C1_0_mem", instr16_C1_0_mem_jit, instr16_C1_0_reg_jit, - imm8 + imm8_5bits ); define_instruction_read_write_mem32!( "rol32", "instr32_C1_0_mem", instr32_C1_0_mem_jit, instr32_C1_0_reg_jit, - imm8 + imm8_5bits ); define_instruction_read_write_mem16!( @@ -1184,14 +1193,14 @@ define_instruction_read_write_mem16!( "instr16_C1_1_mem", instr16_C1_1_mem_jit, instr16_C1_1_reg_jit, - imm8 + imm8_5bits ); define_instruction_read_write_mem32!( "ror32", "instr32_C1_1_mem", instr32_C1_1_mem_jit, instr32_C1_1_reg_jit, - imm8 + imm8_5bits ); define_instruction_read_write_mem16!( @@ -1199,14 +1208,14 @@ define_instruction_read_write_mem16!( "instr16_C1_2_mem", instr16_C1_2_mem_jit, instr16_C1_2_reg_jit, - imm8 + imm8_5bits ); define_instruction_read_write_mem32!( "rcl32", "instr32_C1_2_mem", instr32_C1_2_mem_jit, instr32_C1_2_reg_jit, - imm8 + imm8_5bits ); define_instruction_read_write_mem16!( @@ -1214,14 +1223,14 @@ define_instruction_read_write_mem16!( "instr16_C1_3_mem", instr16_C1_3_mem_jit, instr16_C1_3_reg_jit, - imm8 + imm8_5bits ); define_instruction_read_write_mem32!( "rcr32", "instr32_C1_3_mem", instr32_C1_3_mem_jit, instr32_C1_3_reg_jit, - imm8 + imm8_5bits ); define_instruction_read_write_mem16!( @@ -1229,14 +1238,14 @@ define_instruction_read_write_mem16!( "instr16_C1_4_mem", instr16_C1_4_mem_jit, instr16_C1_4_reg_jit, - imm8 + imm8_5bits ); define_instruction_read_write_mem32!( "shl32", "instr32_C1_4_mem", instr32_C1_4_mem_jit, instr32_C1_4_reg_jit, - imm8 + imm8_5bits ); define_instruction_read_write_mem16!( @@ -1244,14 +1253,14 @@ define_instruction_read_write_mem16!( "instr16_C1_5_mem", instr16_C1_5_mem_jit, instr16_C1_5_reg_jit, - imm8 + imm8_5bits ); define_instruction_read_write_mem32!( "shr32", "instr32_C1_5_mem", instr32_C1_5_mem_jit, instr32_C1_5_reg_jit, - imm8 + imm8_5bits ); define_instruction_read_write_mem16!( @@ -1259,14 +1268,14 @@ define_instruction_read_write_mem16!( "instr16_C1_6_mem", instr16_C1_6_mem_jit, instr16_C1_6_reg_jit, - imm8 + imm8_5bits ); define_instruction_read_write_mem32!( "shl32", "instr32_C1_6_mem", instr32_C1_6_mem_jit, instr32_C1_6_reg_jit, - imm8 + imm8_5bits ); define_instruction_read_write_mem16!( @@ -1274,14 +1283,14 @@ define_instruction_read_write_mem16!( "instr16_C1_7_mem", instr16_C1_7_mem_jit, instr16_C1_7_reg_jit, - imm8 + imm8_5bits ); define_instruction_read_write_mem32!( "sar32", "instr32_C1_7_mem", instr32_C1_7_mem_jit, instr32_C1_7_reg_jit, - imm8 + imm8_5bits ); pub fn instr16_E8_jit(ctx: &mut JitContext, imm: u32) { From 76cc19dee4703b4488412e5878570ef4e4e99f4a Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 7 Sep 2018 16:37:57 -0500 Subject: [PATCH 1334/2137] Tests for sse shifts with 64 bit shift operand --- tests/qemu/test-i386.c | 61 ++++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/tests/qemu/test-i386.c b/tests/qemu/test-i386.c index 28c8db0a..6a54ff99 100644 --- a/tests/qemu/test-i386.c +++ b/tests/qemu/test-i386.c @@ -2341,7 +2341,7 @@ static uint64_t __attribute__((aligned(16))) test_values[4][2] = { #define SSE_OP2(op)\ {\ int i;\ - for(i=0;i<2;i++) {\ + for(i=0;i Date: Fri, 7 Sep 2018 16:45:31 -0500 Subject: [PATCH 1335/2137] Fix sse shifts (shift operand is 64 bit) --- src/rust/cpu2/instructions_0f.rs | 70 +++++++++++++++---------------- src/rust/cpu2/sse_instr.rs | 72 ++++++++++++++++---------------- 2 files changed, 71 insertions(+), 71 deletions(-) diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 2eb4a487..c9890d62 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -1887,7 +1887,7 @@ pub unsafe fn instr_0F62_mem(mut addr: i32, mut r: i32) { instr_0F62(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F62(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F62(mut source: reg64, mut r: i32) { // punpckldq xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -1900,10 +1900,10 @@ pub unsafe fn instr_660F62(mut source: reg128, mut r: i32) { ); } #[no_mangle] -pub unsafe fn instr_660F62_reg(mut r1: i32, mut r2: i32) { instr_660F62(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F62_reg(mut r1: i32, mut r2: i32) { instr_660F62(read_xmm64s(r1), r2); } #[no_mangle] pub unsafe fn instr_660F62_mem(mut addr: i32, mut r: i32) { - instr_660F62(return_on_pagefault!(safe_read128s(addr)), r); + instr_660F62(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] pub unsafe fn instr_0F63(mut source: reg64, mut r: i32) { @@ -2534,17 +2534,17 @@ pub unsafe fn instr_0F71_6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0F71_2_reg(mut r: i32, mut imm8: i32) { // psrlw mm, imm8 - psrlw_r64(r, imm8 as u32); + psrlw_r64(r, imm8 as u64); } #[no_mangle] pub unsafe fn instr_0F71_4_reg(mut r: i32, mut imm8: i32) { // psraw mm, imm8 - psraw_r64(r, imm8 as u32); + psraw_r64(r, imm8 as u64); } #[no_mangle] pub unsafe fn instr_0F71_6_reg(mut r: i32, mut imm8: i32) { // psllw mm, imm8 - psllw_r64(r, imm8 as u32); + psllw_r64(r, imm8 as u64); } #[no_mangle] pub unsafe fn instr_660F71_2_mem(mut addr: i32, mut r: i32) { trigger_ud(); } @@ -2555,17 +2555,17 @@ pub unsafe fn instr_660F71_6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] pub unsafe fn instr_660F71_2_reg(mut r: i32, mut imm8: i32) { // psrlw xmm, imm8 - psrlw_r128(r, imm8 as u32); + psrlw_r128(r, imm8 as u64); } #[no_mangle] pub unsafe fn instr_660F71_4_reg(mut r: i32, mut imm8: i32) { // psraw xmm, imm8 - psraw_r128(r, imm8 as u32); + psraw_r128(r, imm8 as u64); } #[no_mangle] pub unsafe fn instr_660F71_6_reg(mut r: i32, mut imm8: i32) { // psllw xmm, imm8 - psllw_r128(r, imm8 as u32); + psllw_r128(r, imm8 as u64); } #[no_mangle] pub unsafe fn instr_0F72_2_mem(mut addr: i32, mut r: i32) { trigger_ud(); } @@ -2576,17 +2576,17 @@ pub unsafe fn instr_0F72_6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0F72_2_reg(mut r: i32, mut imm8: i32) { // psrld mm, imm8 - psrld_r64(r, imm8 as u32); + psrld_r64(r, imm8 as u64); } #[no_mangle] pub unsafe fn instr_0F72_4_reg(mut r: i32, mut imm8: i32) { // psrad mm, imm8 - psrad_r64(r, imm8 as u32); + psrad_r64(r, imm8 as u64); } #[no_mangle] pub unsafe fn instr_0F72_6_reg(mut r: i32, mut imm8: i32) { // pslld mm, imm8 - pslld_r64(r, imm8 as u32); + pslld_r64(r, imm8 as u64); } #[no_mangle] pub unsafe fn instr_660F72_2_mem(mut addr: i32, mut r: i32) { trigger_ud(); } @@ -2597,17 +2597,17 @@ pub unsafe fn instr_660F72_6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] pub unsafe fn instr_660F72_2_reg(mut r: i32, mut imm8: i32) { // psrld xmm, imm8 - psrld_r128(r, imm8 as u32); + psrld_r128(r, imm8 as u64); } #[no_mangle] pub unsafe fn instr_660F72_4_reg(mut r: i32, mut imm8: i32) { // psrad xmm, imm8 - psrad_r128(r, imm8 as u32); + psrad_r128(r, imm8 as u64); } #[no_mangle] pub unsafe fn instr_660F72_6_reg(mut r: i32, mut imm8: i32) { // pslld xmm, imm8 - pslld_r128(r, imm8 as u32); + pslld_r128(r, imm8 as u64); } #[no_mangle] pub unsafe fn instr_0F73_2_mem(mut addr: i32, mut r: i32) { trigger_ud(); } @@ -2616,12 +2616,12 @@ pub unsafe fn instr_0F73_6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0F73_2_reg(mut r: i32, mut imm8: i32) { // psrlq mm, imm8 - psrlq_r64(r, imm8 as u32); + psrlq_r64(r, imm8 as u64); } #[no_mangle] pub unsafe fn instr_0F73_6_reg(mut r: i32, mut imm8: i32) { // psllq mm, imm8 - psllq_r64(r, imm8 as u32); + psllq_r64(r, imm8 as u64); } #[no_mangle] pub unsafe fn instr_660F73_2_mem(mut addr: i32, mut r: i32) { trigger_ud(); } @@ -2634,7 +2634,7 @@ pub unsafe fn instr_660F73_7_mem(mut addr: i32, mut r: i32) { trigger_ud(); } #[no_mangle] pub unsafe fn instr_660F73_2_reg(mut r: i32, mut imm8: i32) { // psrlq xmm, imm8 - psrlq_r128(r, imm8 as u32); + psrlq_r128(r, imm8 as u64); } #[no_mangle] pub unsafe fn instr_660F73_3_reg(mut r: i32, mut imm8: i32) { @@ -2664,7 +2664,7 @@ pub unsafe fn instr_660F73_3_reg(mut r: i32, mut imm8: i32) { #[no_mangle] pub unsafe fn instr_660F73_6_reg(mut r: i32, mut imm8: i32) { // psllq xmm, imm8 - psllq_r128(r, imm8 as u32); + psllq_r128(r, imm8 as u64); } #[no_mangle] pub unsafe fn instr_660F73_7_reg(mut r: i32, mut imm8: i32) { @@ -3889,7 +3889,7 @@ pub unsafe fn instr_0FD0() { unimplemented_sse(); } #[no_mangle] pub unsafe fn instr_0FD1(mut source: reg64, mut r: i32) { // psrlw mm, mm/m64 - psrlw_r64(r, source.u32_0[0]); + psrlw_r64(r, source.u64_0[0]); } #[no_mangle] pub unsafe fn instr_0FD1_reg(mut r1: i32, mut r2: i32) { instr_0FD1(read_mmx64s(r1), r2); } @@ -3901,7 +3901,7 @@ pub unsafe fn instr_0FD1_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_660FD1(mut source: reg128, mut r: i32) { // psrlw xmm, xmm/m128 // XXX: Aligned access or #gp - psrlw_r128(r, source.u32_0[0]); + psrlw_r128(r, source.u64_0[0]); } #[no_mangle] pub unsafe fn instr_660FD1_reg(mut r1: i32, mut r2: i32) { instr_660FD1(read_xmm128s(r1), r2); } @@ -3912,7 +3912,7 @@ pub unsafe fn instr_660FD1_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_0FD2(mut source: reg64, mut r: i32) { // psrld mm, mm/m64 - psrld_r64(r, source.u32_0[0]); + psrld_r64(r, source.u64_0[0]); } #[no_mangle] pub unsafe fn instr_0FD2_reg(mut r1: i32, mut r2: i32) { instr_0FD2(read_mmx64s(r1), r2); } @@ -3924,7 +3924,7 @@ pub unsafe fn instr_0FD2_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_660FD2(mut source: reg128, mut r: i32) { // psrld xmm, xmm/m128 // XXX: Aligned access or #gp - psrld_r128(r, source.u32_0[0]); + psrld_r128(r, source.u64_0[0]); } #[no_mangle] pub unsafe fn instr_660FD2_reg(mut r1: i32, mut r2: i32) { instr_660FD2(read_xmm128s(r1), r2); } @@ -3935,7 +3935,7 @@ pub unsafe fn instr_660FD2_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_0FD3(mut source: reg64, mut r: i32) { // psrlq mm, mm/m64 - psrlq_r64(r, source.u32_0[0]); + psrlq_r64(r, source.u64_0[0]); } #[no_mangle] pub unsafe fn instr_0FD3_reg(mut r1: i32, mut r2: i32) { instr_0FD3(read_mmx64s(r1), r2); } @@ -3946,7 +3946,7 @@ pub unsafe fn instr_0FD3_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_660FD3(mut source: reg128, mut r: i32) { // psrlq xmm, mm/m64 - psrlq_r128(r, source.u32_0[0]); + psrlq_r128(r, source.u64_0[0]); } #[no_mangle] pub unsafe fn instr_660FD3_reg(mut r1: i32, mut r2: i32) { instr_660FD3(read_xmm128s(r1), r2); } @@ -4459,7 +4459,7 @@ pub unsafe fn instr_660FE0_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_0FE1(mut source: reg64, mut r: i32) { // psraw mm, mm/m64 - psraw_r64(r, source.u32_0[0]); + psraw_r64(r, source.u64_0[0]); } #[no_mangle] pub unsafe fn instr_0FE1_reg(mut r1: i32, mut r2: i32) { instr_0FE1(read_mmx64s(r1), r2); } @@ -4471,7 +4471,7 @@ pub unsafe fn instr_0FE1_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_660FE1(mut source: reg128, mut r: i32) { // psraw xmm, xmm/m128 // XXX: Aligned access or #gp - psraw_r128(r, source.u32_0[0]); + psraw_r128(r, source.u64_0[0]); } #[no_mangle] pub unsafe fn instr_660FE1_reg(mut r1: i32, mut r2: i32) { instr_660FE1(read_xmm128s(r1), r2); } @@ -4482,7 +4482,7 @@ pub unsafe fn instr_660FE1_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_0FE2(mut source: reg64, mut r: i32) { // psrad mm, mm/m64 - psrad_r64(r, source.u32_0[0]); + psrad_r64(r, source.u64_0[0]); } #[no_mangle] pub unsafe fn instr_0FE2_reg(mut r1: i32, mut r2: i32) { instr_0FE2(read_mmx64s(r1), r2); } @@ -4494,7 +4494,7 @@ pub unsafe fn instr_0FE2_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_660FE2(mut source: reg128, mut r: i32) { // psrad xmm, xmm/m128 // XXX: Aligned access or #gp - psrad_r128(r, source.u32_0[0]); + psrad_r128(r, source.u64_0[0]); } #[no_mangle] pub unsafe fn instr_660FE2_reg(mut r1: i32, mut r2: i32) { instr_660FE2(read_xmm128s(r1), r2); } @@ -5064,7 +5064,7 @@ pub unsafe fn instr_0FF0() { unimplemented_sse(); } #[no_mangle] pub unsafe fn instr_0FF1(mut source: reg64, mut r: i32) { // psllw mm, mm/m64 - psllw_r64(r, source.u32_0[0]); + psllw_r64(r, source.u64_0[0]); } #[no_mangle] pub unsafe fn instr_0FF1_reg(mut r1: i32, mut r2: i32) { instr_0FF1(read_mmx64s(r1), r2); } @@ -5076,7 +5076,7 @@ pub unsafe fn instr_0FF1_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_660FF1(mut source: reg128, mut r: i32) { // psllw xmm, xmm/m128 // XXX: Aligned access or #gp - psllw_r128(r, source.u32_0[0]); + psllw_r128(r, source.u64_0[0]); } #[no_mangle] pub unsafe fn instr_660FF1_reg(mut r1: i32, mut r2: i32) { instr_660FF1(read_xmm128s(r1), r2); } @@ -5087,7 +5087,7 @@ pub unsafe fn instr_660FF1_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_0FF2(mut source: reg64, mut r: i32) { // pslld mm, mm/m64 - pslld_r64(r, source.u32_0[0]); + pslld_r64(r, source.u64_0[0]); } #[no_mangle] pub unsafe fn instr_0FF2_reg(mut r1: i32, mut r2: i32) { instr_0FF2(read_mmx64s(r1), r2); } @@ -5099,7 +5099,7 @@ pub unsafe fn instr_0FF2_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_660FF2(mut source: reg128, mut r: i32) { // pslld xmm, xmm/m128 // XXX: Aligned access or #gp - pslld_r128(r, source.u32_0[0]); + pslld_r128(r, source.u64_0[0]); } #[no_mangle] pub unsafe fn instr_660FF2_reg(mut r1: i32, mut r2: i32) { instr_660FF2(read_xmm128s(r1), r2); } @@ -5110,7 +5110,7 @@ pub unsafe fn instr_660FF2_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_0FF3(mut source: reg64, mut r: i32) { // psllq mm, mm/m64 - psllq_r64(r, source.u32_0[0]); + psllq_r64(r, source.u64_0[0]); } #[no_mangle] pub unsafe fn instr_0FF3_reg(mut r1: i32, mut r2: i32) { instr_0FF3(read_mmx64s(r1), r2); } @@ -5122,7 +5122,7 @@ pub unsafe fn instr_0FF3_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_660FF3(mut source: reg128, mut r: i32) { // psllq xmm, xmm/m128 // XXX: Aligned access or #gp - psllq_r128(r, source.u32_0[0]); + psllq_r128(r, source.u64_0[0]); } #[no_mangle] pub unsafe fn instr_660FF3_reg(mut r1: i32, mut r2: i32) { instr_660FF3(read_xmm128s(r1), r2); } diff --git a/src/rust/cpu2/sse_instr.rs b/src/rust/cpu2/sse_instr.rs index 700279b7..10ed1ab9 100644 --- a/src/rust/cpu2/sse_instr.rs +++ b/src/rust/cpu2/sse_instr.rs @@ -99,22 +99,22 @@ pub unsafe fn por_r128(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn psrlw_r64(mut r: i32, mut shift: u32) { +pub unsafe fn psrlw_r64(mut r: i32, mut shift: u64) { // psrlw mm, {shift} let mut destination: reg64 = read_mmx64s(r); let mut dword0: i32 = 0; let mut dword1: i32 = 0; - if shift <= 15 as u32 { + if shift <= 15 { dword0 = destination.u16_0[0] as i32 >> shift | destination.u16_0[1] as i32 >> shift << 16; dword1 = destination.u16_0[2] as i32 >> shift | destination.u16_0[3] as i32 >> shift << 16 } write_mmx64(r, dword0, dword1); } #[no_mangle] -pub unsafe fn psraw_r64(mut r: i32, mut shift: u32) { +pub unsafe fn psraw_r64(mut r: i32, mut shift: u64) { // psraw mm, {shift} let mut destination: reg64 = read_mmx64s(r); - let mut shift_clamped: i32 = (if shift > 15 as u32 { 16 as u32 } else { shift }) as i32; + let mut shift_clamped: i32 = (if shift > 15 { 16 } else { shift }) as i32; let mut dword0: i32 = destination.i16_0[0] as i32 >> shift_clamped & 65535 | destination.i16_0[1] as i32 >> shift_clamped << 16; let mut dword1: i32 = destination.i16_0[2] as i32 >> shift_clamped & 65535 @@ -122,12 +122,12 @@ pub unsafe fn psraw_r64(mut r: i32, mut shift: u32) { write_mmx64(r, dword0, dword1); } #[no_mangle] -pub unsafe fn psllw_r64(mut r: i32, mut shift: u32) { +pub unsafe fn psllw_r64(mut r: i32, mut shift: u64) { // psllw mm, {shift} let mut destination: reg64 = read_mmx64s(r); let mut dword0: i32 = 0; let mut dword1: i32 = 0; - if shift <= 15 as u32 { + if shift <= 15 { dword0 = (destination.u16_0[0] as i32) << shift & 65535 | (destination.u16_0[1] as i32) << shift << 16; dword1 = (destination.u16_0[2] as i32) << shift & 65535 @@ -136,42 +136,42 @@ pub unsafe fn psllw_r64(mut r: i32, mut shift: u32) { write_mmx64(r, dword0, dword1); } #[no_mangle] -pub unsafe fn psrld_r64(mut r: i32, mut shift: u32) { +pub unsafe fn psrld_r64(mut r: i32, mut shift: u64) { // psrld mm, {shift} let mut destination: reg64 = read_mmx64s(r); let mut dword0: i32 = 0; let mut dword1: i32 = 0; - if shift <= 31 as u32 { + if shift <= 31 { dword0 = (destination.u32_0[0] >> shift) as i32; dword1 = (destination.u32_0[1] >> shift) as i32 } write_mmx64(r, dword0, dword1); } #[no_mangle] -pub unsafe fn psrad_r64(mut r: i32, mut shift: u32) { +pub unsafe fn psrad_r64(mut r: i32, mut shift: u64) { // psrad mm, {shift} let mut destination: reg64 = read_mmx64s(r); - let mut shift_clamped: i32 = (if shift > 31 as u32 { 31 as u32 } else { shift }) as i32; + let mut shift_clamped: i32 = (if shift > 31 { 31 } else { shift }) as i32; let mut dword0: i32 = destination.i32_0[0] >> shift_clamped; let mut dword1: i32 = destination.i32_0[1] >> shift_clamped; write_mmx64(r, dword0, dword1); } #[no_mangle] -pub unsafe fn pslld_r64(mut r: i32, mut shift: u32) { +pub unsafe fn pslld_r64(mut r: i32, mut shift: u64) { // pslld mm, {shift} let mut destination: reg64 = read_mmx64s(r); let mut dword0: i32 = 0; let mut dword1: i32 = 0; - if shift <= 31 as u32 { + if shift <= 31 { dword0 = destination.i32_0[0] << shift; dword1 = destination.i32_0[1] << shift } write_mmx64(r, dword0, dword1); } #[no_mangle] -pub unsafe fn psrlq_r64(mut r: i32, mut shift: u32) { +pub unsafe fn psrlq_r64(mut r: i32, mut shift: u64) { // psrlq mm, {shift} - if shift == 0 as u32 { + if shift == 0 { return; } else { @@ -179,7 +179,7 @@ pub unsafe fn psrlq_r64(mut r: i32, mut shift: u32) { let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - if shift <= 63 as u32 { + if shift <= 63 { result.u64_0[0] = destination.u64_0[0] >> shift } write_mmx_reg64(r, result); @@ -187,17 +187,17 @@ pub unsafe fn psrlq_r64(mut r: i32, mut shift: u32) { }; } #[no_mangle] -pub unsafe fn psllq_r64(mut r: i32, mut shift: u32) { +pub unsafe fn psllq_r64(mut r: i32, mut shift: u64) { // psllq mm, {shift} let mut destination: reg64 = read_mmx64s(r); - if shift == 0 as u32 { + if shift == 0 { return; } else { let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - if shift <= 63 as u32 { + if shift <= 63 { result.u64_0[0] = destination.u64_0[0] << shift } write_mmx_reg64(r, result); @@ -205,14 +205,14 @@ pub unsafe fn psllq_r64(mut r: i32, mut shift: u32) { }; } #[no_mangle] -pub unsafe fn psrlw_r128(mut r: i32, mut shift: u32) { +pub unsafe fn psrlw_r128(mut r: i32, mut shift: u64) { // psrlw xmm, {shift} let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = 0; let mut dword1: i32 = 0; let mut dword2: i32 = 0; let mut dword3: i32 = 0; - if shift <= 15 as u32 { + if shift <= 15 { dword0 = destination.u16_0[0] as i32 >> shift | destination.u16_0[1] as i32 >> shift << 16; dword1 = destination.u16_0[2] as i32 >> shift | destination.u16_0[3] as i32 >> shift << 16; dword2 = destination.u16_0[4] as i32 >> shift | destination.u16_0[5] as i32 >> shift << 16; @@ -221,10 +221,10 @@ pub unsafe fn psrlw_r128(mut r: i32, mut shift: u32) { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn psraw_r128(mut r: i32, mut shift: u32) { +pub unsafe fn psraw_r128(mut r: i32, mut shift: u64) { // psraw xmm, {shift} let mut destination: reg128 = read_xmm128s(r); - let mut shift_clamped: i32 = (if shift > 15 as u32 { 16 as u32 } else { shift }) as i32; + let mut shift_clamped: i32 = (if shift > 15 { 16 as u32 } else { shift as u32 }) as i32; let mut dword0: i32 = destination.i16_0[0] as i32 >> shift_clamped & 65535 | destination.i16_0[1] as i32 >> shift_clamped << 16; let mut dword1: i32 = destination.i16_0[2] as i32 >> shift_clamped & 65535 @@ -236,14 +236,14 @@ pub unsafe fn psraw_r128(mut r: i32, mut shift: u32) { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn psllw_r128(mut r: i32, mut shift: u32) { +pub unsafe fn psllw_r128(mut r: i32, mut shift: u64) { // psllw xmm, {shift} let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = 0; let mut dword1: i32 = 0; let mut dword2: i32 = 0; let mut dword3: i32 = 0; - if shift <= 15 as u32 { + if shift <= 15 { dword0 = (destination.u16_0[0] as i32) << shift & 65535 | (destination.u16_0[1] as i32) << shift << 16; dword1 = (destination.u16_0[2] as i32) << shift & 65535 @@ -256,14 +256,14 @@ pub unsafe fn psllw_r128(mut r: i32, mut shift: u32) { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn psrld_r128(mut r: i32, mut shift: u32) { +pub unsafe fn psrld_r128(mut r: i32, mut shift: u64) { // psrld xmm, {shift} let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = 0; let mut dword1: i32 = 0; let mut dword2: i32 = 0; let mut dword3: i32 = 0; - if shift <= 31 as u32 { + if shift <= 31 { dword0 = (destination.u32_0[0] >> shift) as i32; dword1 = (destination.u32_0[1] >> shift) as i32; dword2 = (destination.u32_0[2] >> shift) as i32; @@ -272,10 +272,10 @@ pub unsafe fn psrld_r128(mut r: i32, mut shift: u32) { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn psrad_r128(mut r: i32, mut shift: u32) { +pub unsafe fn psrad_r128(mut r: i32, mut shift: u64) { // psrad xmm, {shift} let mut destination: reg128 = read_xmm128s(r); - let mut shift_clamped: i32 = (if shift > 31 as u32 { 31 as u32 } else { shift }) as i32; + let mut shift_clamped: i32 = (if shift > 31 { 31 } else { shift }) as i32; let mut dword0: i32 = destination.i32_0[0] >> shift_clamped; let mut dword1: i32 = destination.i32_0[1] >> shift_clamped; let mut dword2: i32 = destination.i32_0[2] >> shift_clamped; @@ -283,14 +283,14 @@ pub unsafe fn psrad_r128(mut r: i32, mut shift: u32) { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn pslld_r128(mut r: i32, mut shift: u32) { +pub unsafe fn pslld_r128(mut r: i32, mut shift: u64) { // pslld xmm, {shift} let mut destination: reg128 = read_xmm128s(r); let mut dword0: i32 = 0; let mut dword1: i32 = 0; let mut dword2: i32 = 0; let mut dword3: i32 = 0; - if shift <= 31 as u32 { + if shift <= 31 { dword0 = destination.i32_0[0] << shift; dword1 = destination.i32_0[1] << shift; dword2 = destination.i32_0[2] << shift; @@ -299,9 +299,9 @@ pub unsafe fn pslld_r128(mut r: i32, mut shift: u32) { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn psrlq_r128(mut r: i32, mut shift: u32) { +pub unsafe fn psrlq_r128(mut r: i32, mut shift: u64) { // psrlq xmm, {shift} - if shift == 0 as u32 { + if shift == 0 { return; } else { @@ -309,7 +309,7 @@ pub unsafe fn psrlq_r128(mut r: i32, mut shift: u32) { let mut result: reg128 = reg128 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - if shift <= 63 as u32 { + if shift <= 63 { result.u64_0[0] = destination.u64_0[0] >> shift; result.u64_0[1] = destination.u64_0[1] >> shift } @@ -318,17 +318,17 @@ pub unsafe fn psrlq_r128(mut r: i32, mut shift: u32) { }; } #[no_mangle] -pub unsafe fn psllq_r128(mut r: i32, mut shift: u32) { +pub unsafe fn psllq_r128(mut r: i32, mut shift: u64) { // psllq xmm, {shift} let mut destination: reg128 = read_xmm128s(r); - if shift == 0 as u32 { + if shift == 0 { return; } else { let mut result: reg128 = reg128 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - if shift <= 63 as u32 { + if shift <= 63 { result.u64_0[0] = destination.u64_0[0] << shift; result.u64_0[1] = destination.u64_0[1] << shift } From 35cd746940a870d20bb32a71f02ca56e18926520 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 10 Sep 2018 12:18:25 -0500 Subject: [PATCH 1336/2137] Delete dead code --- src/browser/starter.js | 3 --- src/const.js | 9 --------- src/cpu.js | 23 ----------------------- 3 files changed, 35 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 2449402b..e767eea0 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -131,9 +131,6 @@ function V86Starter(options) dbg_assert(false); }, - "throw_cpu_exception": () => { - throw MAGIC_CPU_EXCEPTION; - }, "cpu_exception_hook": (n) => { return this["cpu_exception_hook"] && this["cpu_exception_hook"](n); }, diff --git a/src/const.js b/src/const.js index 4c8c9e6a..d677fd51 100644 --- a/src/const.js +++ b/src/const.js @@ -167,15 +167,6 @@ var /** @const */ MMAP_BLOCK_SIZE = 1 << MMAP_BLOCK_BITS; - -/** @const */ -var MEM_PAGE_WRITTEN = 1; - - -/** @const */ -var MAGIC_CPU_EXCEPTION = 0xDEADBEE; - - var /** @const */ REPEAT_STRING_PREFIX_NONE = 0, diff --git a/src/cpu.js b/src/cpu.js index 8ec237d7..16ba740c 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -577,29 +577,6 @@ CPU.prototype.main_run = function() return 0; }; -CPU.prototype.exception_cleanup = function(e) -{ - if(e === MAGIC_CPU_EXCEPTION) - { - // A legit CPU exception (for instance, a page fault happened) - // call_interrupt_vector has already been called at this point, - // so we just need to reset some state - - this.page_fault[0] = 0; - - // restore state from prefixes - this.prefixes[0] = 0; - } - else - { - console.log(e); - console.log(e.stack); - //var e = new Error(e.message); - //Error.captureStackTrace && Error.captureStackTrace(e); - throw e; - } -}; - CPU.prototype.reboot_internal = function() { this.reset(); From fd1f8e1108ec9307682e222593c7fc0cafdf70bf Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 10 Sep 2018 12:19:37 -0500 Subject: [PATCH 1337/2137] Test more edge cases for sse shifts --- tests/qemu/test-i386.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/tests/qemu/test-i386.c b/tests/qemu/test-i386.c index 6a54ff99..140fa868 100644 --- a/tests/qemu/test-i386.c +++ b/tests/qemu/test-i386.c @@ -2790,32 +2790,42 @@ void test_sse(void) SHIFT_OP(psrlw, 0); SHIFT_OP(psrlw, 7); + SHIFT_OP(psrlw, 15); SHIFT_OP(psrlw, 16); SHIFT_REG(psrlw, 0x100000000); SHIFT_REG_MMX(psrlw, 0x100000000); + SHIFT_OP(psraw, 0); SHIFT_OP(psraw, 7); + SHIFT_OP(psraw, 15); SHIFT_OP(psraw, 16); SHIFT_REG(psraw, 0x100000000); SHIFT_REG_MMX(psraw, 0x100000000); + SHIFT_OP(psllw, 0); SHIFT_OP(psllw, 7); + SHIFT_OP(psllw, 15); SHIFT_OP(psllw, 16); SHIFT_REG(psllw, 0x100000000); SHIFT_REG_MMX(psllw, 0x100000000); SHIFT_OP(psrld, 0); SHIFT_OP(psrld, 7); + SHIFT_OP(psrld, 31); SHIFT_OP(psrld, 32); SHIFT_REG(psrld, 0x100000000); SHIFT_REG_MMX(psrld, 0x100000000); + SHIFT_OP(psrad, 0); SHIFT_OP(psrad, 7); + SHIFT_OP(psrad, 31); SHIFT_OP(psrad, 32); SHIFT_REG(psrad, 0x100000000); SHIFT_REG_MMX(psrad, 0x100000000); + SHIFT_OP(pslld, 0); SHIFT_OP(pslld, 7); + SHIFT_OP(pslld, 31); SHIFT_OP(pslld, 32); SHIFT_REG(pslld, 0x100000000); SHIFT_REG_MMX(pslld, 0x100000000); @@ -2823,22 +2833,34 @@ void test_sse(void) SHIFT_OP(psrlq, 0); SHIFT_OP(psrlq, 7); SHIFT_OP(psrlq, 32); + SHIFT_OP(psrlq, 63); + SHIFT_OP(psrlq, 64); SHIFT_REG(psrlq, 0x100000000); SHIFT_REG_MMX(psrlq, 0x100000000); + SHIFT_OP(psllq, 0); SHIFT_OP(psllq, 7); SHIFT_OP(psllq, 32); + SHIFT_OP(psllq, 63); + SHIFT_OP(psllq, 64); SHIFT_REG(psllq, 0x100000000); SHIFT_REG_MMX(psllq, 0x100000000); // byte-wise shifts SHIFT_IM(psrldq, 0); + SHIFT_IM(psrldq, 1); SHIFT_IM(psrldq, 7); + SHIFT_IM(psrldq, 8); SHIFT_IM(psrldq, 11); + SHIFT_IM(psrldq, 15); SHIFT_IM(psrldq, 16); - SHIFT_IM(pslldq, 7); + SHIFT_IM(pslldq, 0); + SHIFT_IM(pslldq, 1); + SHIFT_IM(pslldq, 7); + SHIFT_IM(pslldq, 8); SHIFT_IM(pslldq, 11); + SHIFT_IM(pslldq, 15); SHIFT_IM(pslldq, 16); MOVMSK(movmskps); From 1de206da494b613cbfad849d56f042e97cccf8b6 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 10 Sep 2018 12:23:51 -0500 Subject: [PATCH 1338/2137] Minor: Print cr4 as hex --- src/rust/cpu2/instructions_0f.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index c9890d62..990e6b1c 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -824,7 +824,7 @@ pub unsafe fn instr_0F22(mut r: i32, mut creg: i32) { clear_tlb(); }, 4 => { - dbg_log!("cr4 <- {}", *cr.offset(4)); + dbg_log!("cr4 <- {:x}", *cr.offset(4)); if 0 != data as u32 & ((1 << 11 | 1 << 12 | 1 << 15 | 1 << 16 | 1 << 19) as u32 | 4290772992) { From aa9d5deefc0a686354e6272c9480ad3b85d42bf0 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 10 Sep 2018 12:28:12 -0500 Subject: [PATCH 1339/2137] Warn on task_switch_test with cr4.osfxsr=0 --- src/rust/cpu2/cpu.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 8df48529..d45c4945 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -164,6 +164,8 @@ pub const CR4_PSE: i32 = 1 << 4; pub const CR4_DE: i32 = 1 << 3; pub const CR4_PAE: i32 = 1 << 5; pub const CR4_PGE: i32 = 1 << 7; +pub const CR4_OSFXSR: i32 = 1 << 9; +pub const CR4_OSXMMEXCPT: i32 = 1 << 10; pub const IA32_SYSENTER_CS: i32 = 372; pub const IA32_SYSENTER_ESP: i32 = 373; pub const IA32_SYSENTER_EIP: i32 = 374; @@ -1792,6 +1794,9 @@ pub unsafe fn set_mxcsr(new_mxcsr: i32) { pub unsafe fn task_switch_test_void() { task_switch_test(); } pub unsafe fn task_switch_test_mmx() -> bool { + if *cr.offset(4) & CR4_OSFXSR == 0 { + dbg_log!("Warning: Unimplemented task switch test with cr4.osfxsr=0"); + } if 0 != *cr & CR0_TS { trigger_nm(); return 0 != 0; From e70e9dc4b26d03e72ede105c6a0b13872aab5ddb Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 10 Sep 2018 15:01:39 -0500 Subject: [PATCH 1340/2137] Factor the conversion out of fpu_{load,store}_m80, add tests, fix the denormal number case --- Makefile | 3 ++ src/rust/cpu2/fpu.rs | 69 +++++++++++++++++++++++++++++++++----------- src/rust/lib.rs | 1 + 3 files changed, 56 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index 607d61cd..c692d8a1 100644 --- a/Makefile +++ b/Makefile @@ -272,6 +272,9 @@ rust-test: $(RUST_FILES) env RUST_BACKTRACE=full RUST_TEST_THREADS=1 RUSTFLAGS="-D warnings" cargo +nightly test -- --nocapture ./tests/rust/verify-wasmgen-dummy-output.js +rust-test-intensive: + QUICKCHECK_TESTS=100000000 make rust-test + api-tests: all-debug ./tests/api/state.js diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 85d7be22..67a38b93 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -1,5 +1,7 @@ #![allow(unused_mut)] +use std::mem::transmute; + use cpu2::cpu::*; use cpu2::global_pointers::*; use paging::OrPageFault; @@ -106,17 +108,26 @@ pub unsafe fn fpu_load_m64(mut addr: i32) -> OrPageFault { let mut v: f64_int = f64_int { u64_0: [value] }; Ok(v.f64_0) } + #[no_mangle] pub unsafe fn fpu_load_m80(mut addr: i32) -> OrPageFault { let mut value: u64 = safe_read64s(addr as i32)?.u64_0[0]; + let mut exponent: i32 = safe_read16(addr.wrapping_add(8) as i32)?; + let f = fpu_i80_to_f64((value, exponent as u16)); + Ok(f) +} + +pub unsafe fn fpu_i80_to_f64(i: (u64, u16)) -> f64 { + let mut value: u64 = i.0; let mut low: u32 = value as u32; let mut high: u32 = (value >> 32) as u32; - let mut exponent: i32 = safe_read16(addr.wrapping_add(8) as i32)?; - let mut sign: i32 = exponent >> 15; + let mut exponent = i.1 as i32; + let mut sign = exponent >> 15; exponent &= !32768; if exponent == 0 { - // TODO: denormal numbers - Ok(0 as f64) + let d: u64 = (sign as u64) << 63 | (high as u64) << 20 | (low as u64) >> 12; + let f: f64 = transmute(d); + f } else if exponent < 32767 { exponent -= 16383; @@ -128,7 +139,7 @@ pub unsafe fn fpu_load_m80(mut addr: i32) -> OrPageFault { // Simply compute the 64 bit floating point number. // An alternative write the mantissa, sign and exponent in the // float64_byte and return float64[0] - Ok(mantissa * pow(2 as f64, (exponent - 63) as f64)) + mantissa * pow(2 as f64, (exponent - 63) as f64) } else { // TODO: NaN, Infinity @@ -141,9 +152,27 @@ pub unsafe fn fpu_load_m80(mut addr: i32) -> OrPageFault { double_int_view.u8_0[5] = 0 as u8; double_int_view.u8_0[4] = 0 as u8; double_int_view.i32_0[0] = 0; - Ok(double_int_view.f64_0) + double_int_view.f64_0 } } + +#[cfg(test)] +mod tests { + use super::{f64_int, fpu_f64_to_i80, fpu_i80_to_f64}; + quickcheck! { + fn i80_f64_conversion(d: u64) -> bool { + let double_int_view = f64_int { u64_0: [d] }; + let f = unsafe { double_int_view.f64_0 }; + unsafe { f == fpu_i80_to_f64(fpu_f64_to_i80(f)) } + } + } + + #[test] + fn more_i80_f64_conversions() { + assert_eq!(unsafe { fpu_f64_to_i80(0.) }, (0, 0)); + } +} + #[no_mangle] pub unsafe fn fpu_load_status_word() -> i32 { return ((*fpu_status_word & !(7 << 11)) as u32 | *fpu_stack_ptr << 11) as i32; @@ -425,12 +454,21 @@ pub unsafe fn fpu_fsave(mut addr: i32) { } fpu_finit(); } + #[no_mangle] pub unsafe fn fpu_store_m80(mut addr: i32, mut n: f64) { - let mut double_int_view: f64_int = f64_int { f64_0: n }; - let mut sign: u8 = (double_int_view.u8_0[7] as i32 & 128) as u8; + let (value, exponent) = fpu_f64_to_i80(n); + // writable_or_pagefault must have checked called by the caller! + safe_write64(addr, value as i64).unwrap(); + safe_write16(addr + 8, exponent as i32).unwrap(); +} + +pub unsafe fn fpu_f64_to_i80(f: f64) -> (u64, u16) { + let mut double_int_view: f64_int = f64_int { f64_0: f }; + let mut sign: u8 = double_int_view.u8_0[7] >> 7; let mut exponent: i32 = (double_int_view.u8_0[7] as i32 & 127) << 4 | double_int_view.u8_0[6] as i32 >> 4; + let mantissa = double_int_view.u64_0[0] & ((1 << 52) - 1); let mut low; let mut high; if exponent == 2047 { @@ -441,9 +479,7 @@ pub unsafe fn fpu_store_m80(mut addr: i32, mut n: f64) { } else if exponent == 0 { // zero and denormal numbers - // Just assume zero for now - low = 0; - high = 0 + return (mantissa << 12, (sign as u16) << 15); } else { exponent += 16383 - 1023; @@ -454,13 +490,12 @@ pub unsafe fn fpu_store_m80(mut addr: i32, mut n: f64) { | double_int_view.i32_0[0] as u32 >> 21) as i32 } dbg_assert!(exponent >= 0 && exponent < 32768); - // writable_or_pagefault must have checked called by the caller! - safe_write64( - addr as i32, - (low as u64 & 4294967295 as u64 | (high as u64) << 32) as i64, - ).unwrap(); - safe_write16(addr.wrapping_add(8) as i32, (sign as i32) << 8 | exponent).unwrap(); + ( + (low as u64 & 4294967295 as u64 | (high as u64) << 32) as u64, + ((sign as i32) << 15 | exponent) as u16, + ) } + #[no_mangle] pub unsafe fn fpu_fstenv(mut addr: i32) { if is_osize_32() { diff --git a/src/rust/lib.rs b/src/rust/lib.rs index aaf670fa..230db563 100644 --- a/src/rust/lib.rs +++ b/src/rust/lib.rs @@ -2,6 +2,7 @@ #![feature(extern_types)] #[cfg(test)] +#[macro_use] extern crate quickcheck; #[macro_use] From 818cece40dbff3a3380a7ac279782e764d5a3662 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 10 Sep 2018 15:08:41 -0500 Subject: [PATCH 1341/2137] Transition from fpu mode on mmx operations --- src/rust/cpu2/cpu.rs | 9 +++++ src/rust/cpu2/instructions_0f.rs | 66 +++++++++++++++++++++++++++++++- src/rust/cpu2/sse_instr.rs | 9 +++++ 3 files changed, 82 insertions(+), 2 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index d45c4945..42320f5f 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -17,6 +17,7 @@ extern "C" { fn pic_acknowledge(); } +use cpu2::fpu::fpu_set_tag_word; use cpu2::global_pointers::*; pub use cpu2::imports::{mem16, mem32s, mem8}; use cpu2::memory::{ @@ -1751,6 +1752,14 @@ pub unsafe fn write_xmm_reg128(mut r: i32, mut data: reg128) { (*reg_xmm.offset(r as isize)).u64_0[1] = data.u64_0[1]; } +/// Set the fpu tag word to valid and the top-of-stack to 0 on mmx instructions +pub fn transition_fpu_to_mmx() { + unsafe { + fpu_set_tag_word(0); + *fpu_stack_ptr = 0; + } +} + pub unsafe fn task_switch_test() -> bool { if 0 != *cr & (CR0_EM | CR0_TS) { trigger_nm(); diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 990e6b1c..5011c241 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -963,6 +963,7 @@ pub unsafe fn instr_0F2C(mut source: reg64, mut r: i32) { ], }; write_mmx_reg64(r, result); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0F2C_mem(mut addr: i32, mut r: i32) { @@ -982,6 +983,7 @@ pub unsafe fn instr_660F2C(mut source: reg128, mut r: i32) { ], }; write_mmx_reg64(r, result); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_660F2C_mem(mut addr: i32, mut r: i32) { @@ -1799,6 +1801,7 @@ pub unsafe fn instr_0F60(mut source: i32, mut r: i32) { let mut low: i32 = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24; let mut high: i32 = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24; write_mmx64(r, low, high); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0F60_reg(mut r1: i32, mut r2: i32) { instr_0F60(read_mmx32s(r1), r2); } @@ -1848,6 +1851,7 @@ pub unsafe fn instr_0F61(mut source: i32, mut r: i32) { let mut low: i32 = word0 | word1 << 16; let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0F61_reg(mut r1: i32, mut r2: i32) { instr_0F61(read_mmx32s(r1), r2); } @@ -1879,6 +1883,7 @@ pub unsafe fn instr_0F62(mut source: i32, mut r: i32) { // punpckldq mm, mm/m32 let mut destination: reg64 = read_mmx64s(r); write_mmx64(r, destination.u32_0[0] as i32, source); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0F62_reg(mut r1: i32, mut r2: i32) { instr_0F62(read_mmx32s(r1), r2); } @@ -1918,6 +1923,7 @@ pub unsafe fn instr_0F63(mut source: reg64, mut r: i32) { | saturate_sw_to_sb(source.u16_0[2] as i32) << 16 | saturate_sw_to_sb(source.u16_0[3] as i32) << 24; write_mmx64(r, low, high); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0F63_reg(mut r1: i32, mut r2: i32) { instr_0F63(read_mmx64s(r1), r2); } @@ -1973,6 +1979,7 @@ pub unsafe fn instr_0F64(mut source: reg64, mut r: i32) { i = i.wrapping_add(1) } write_mmx_reg64(r, result); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0F64_reg(mut r1: i32, mut r2: i32) { instr_0F64(read_mmx64s(r1), r2); } @@ -2038,6 +2045,7 @@ pub unsafe fn instr_0F65(mut source: reg64, mut r: i32) { let mut low: i32 = word0 | word1 << 16; let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0F65_reg(mut r1: i32, mut r2: i32) { instr_0F65(read_mmx64s(r1), r2); } @@ -2089,6 +2097,7 @@ pub unsafe fn instr_0F66(mut source: reg64, mut r: i32) { 0 }; write_mmx64(r, low, high); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0F66_reg(mut r1: i32, mut r2: i32) { instr_0F66(read_mmx64s(r1), r2); } @@ -2148,6 +2157,7 @@ pub unsafe fn instr_0F67(mut source: reg64, mut r: i32) { | saturate_sw_to_ub(source.u16_0[2] as u32) << 16 | saturate_sw_to_ub(source.u16_0[3] as u32) << 24; write_mmx64(r, low as i32, high as i32); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0F67_reg(mut r1: i32, mut r2: i32) { instr_0F67(read_mmx64s(r1), r2); } @@ -2190,6 +2200,7 @@ pub unsafe fn instr_0F68(mut source: reg64, mut r: i32) { let mut low: i32 = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24; let mut high: i32 = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24; write_mmx64(r, low, high); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0F68_reg(mut r1: i32, mut r2: i32) { instr_0F68(read_mmx64s(r1), r2); } @@ -2239,6 +2250,7 @@ pub unsafe fn instr_0F69(mut source: reg64, mut r: i32) { let mut low: i32 = word0 | word1 << 16; let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0F69_reg(mut r1: i32, mut r2: i32) { instr_0F69(read_mmx64s(r1), r2); } @@ -2268,6 +2280,7 @@ pub unsafe fn instr_0F6A(mut source: reg64, mut r: i32) { // punpckhdq mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); write_mmx64(r, destination.u32_0[1] as i32, source.u32_0[1] as i32); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0F6A_reg(mut r1: i32, mut r2: i32) { instr_0F6A(read_mmx64s(r1), r2); } @@ -2303,6 +2316,7 @@ pub unsafe fn instr_0F6B(mut source: reg64, mut r: i32) { let mut high: i32 = (saturate_sd_to_sw(source.u32_0[0]) | saturate_sd_to_sw(source.u32_0[1]) << 16) as i32; write_mmx64(r, low, high); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0F6B_reg(mut r1: i32, mut r2: i32) { instr_0F6B(read_mmx64s(r1), r2); } @@ -2381,6 +2395,7 @@ pub unsafe fn instr_660F6D_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0F6E(mut source: i32, mut r: i32) { // movd mm, r/m32 write_mmx64(r, source, 0); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0F6E_reg(mut r1: i32, mut r2: i32) { instr_0F6E(read_reg32(r1), r2); } @@ -2403,6 +2418,7 @@ pub unsafe fn instr_660F6E_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0F6F(mut source: reg64, mut r: i32) { // movq mm, mm/m64 write_mmx64(r, source.u32_0[0] as i32, source.u32_0[1] as i32); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0F6F_reg(mut r1: i32, mut r2: i32) { instr_0F6F(read_mmx64s(r1), r2); } @@ -2451,6 +2467,7 @@ pub unsafe fn instr_0F70(mut source: reg64, mut r: i32, mut imm8: i32) { source.u32_0[(word3_shift >> 1) as usize] >> ((word3_shift & 1 as u32) << 4); let mut high: i32 = (word2 | word3 << 16) as i32; write_mmx64(r, low, high); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) { @@ -2710,6 +2727,7 @@ pub unsafe fn instr_0F74(mut source: reg64, mut r: i32) { i = i.wrapping_add(1) } write_mmx_reg64(r, result); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0F74_reg(mut r1: i32, mut r2: i32) { instr_0F74(read_mmx64s(r1), r2); } @@ -2773,6 +2791,7 @@ pub unsafe fn instr_0F75(mut source: reg64, mut r: i32) { let mut low: i32 = word0 | word1 << 16; let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0F75_reg(mut r1: i32, mut r2: i32) { instr_0F75(read_mmx64s(r1), r2); } @@ -2822,6 +2841,7 @@ pub unsafe fn instr_0F76(mut source: reg64, mut r: i32) { 0 }; write_mmx64(r, low, high); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0F76_reg(mut r1: i32, mut r2: i32) { instr_0F76(read_mmx64s(r1), r2); } @@ -2889,6 +2909,7 @@ pub unsafe fn instr_0F7D() { unimplemented_sse(); } pub unsafe fn instr_0F7E(mut r: i32) -> i32 { // movd r/m32, mm let mut data: reg64 = read_mmx64s(r); + transition_fpu_to_mmx(); return data.u32_0[0] as i32; } #[no_mangle] @@ -2931,6 +2952,7 @@ pub unsafe fn instr_0F7F_reg(mut r1: i32, mut r2: i32) { // movq mm/m64, mm let mut data: reg64 = read_mmx64s(r2); write_mmx64(r1, data.u32_0[0] as i32, data.u32_0[1] as i32); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_660F7F_mem(mut addr: i32, mut r: i32) { @@ -3742,6 +3764,7 @@ pub unsafe fn instr_0FC4(mut source: i32, mut r: i32, mut imm8: i32) { let mut index: u32 = (imm8 & 3) as u32; destination.u16_0[index as usize] = (source & 65535) as u16; write_mmx_reg64(r, destination); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FC4_reg(mut r1: i32, mut r2: i32, mut imm: i32) { @@ -3776,6 +3799,7 @@ pub unsafe fn instr_0FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i32) { let mut index: u32 = (imm8 & 3) as u32; let mut result: u32 = data.u16_0[index as usize] as u32; write_reg32(r2, result as i32); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_660FC5_mem(mut addr: i32, mut r: i32, mut imm8: i32) { trigger_ud(); } @@ -3961,6 +3985,7 @@ pub unsafe fn instr_0FD4(mut source: reg64, mut r: i32) { destination.u64_0[0] = (destination.u64_0[0] as u64).wrapping_add(source.u64_0[0]) as u64 as u64; write_mmx_reg64(r, destination); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FD4_reg(mut r1: i32, mut r2: i32) { instr_0FD4(read_mmx64s(r1), r2); } @@ -3996,6 +4021,7 @@ pub unsafe fn instr_0FD5(mut source: reg64, mut r: i32) { let mut low: i32 = word0 | word1 << 16; let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FD5_reg(mut r1: i32, mut r2: i32) { instr_0FD5(read_mmx64s(r1), r2); } @@ -4048,6 +4074,7 @@ pub unsafe fn instr_F20FD6_reg(mut r1: i32, mut r2: i32) { // movdq2q mm, xmm let mut source: reg128 = read_xmm128s(r1); write_mmx64(r2, source.u32_0[0] as i32, source.u32_0[1] as i32); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_F30FD6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } @@ -4056,6 +4083,7 @@ pub unsafe fn instr_F30FD6_reg(mut r1: i32, mut r2: i32) { // movq2dq xmm, mm let mut source: reg64 = read_mmx64s(r1); write_xmm128(r2, source.u32_0[0] as i32, source.u32_0[1] as i32, 0, 0); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FD7_mem(mut addr: i32, mut r: i32) { trigger_ud(); } @@ -4072,6 +4100,7 @@ pub unsafe fn instr_0FD7_reg(mut r1: i32, mut r2: i32) { | x.u8_0[6] as i32 >> 7 << 6 | x.u8_0[7] as i32 >> 7 << 7) as u32; write_reg32(r2, result as i32); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_660FD7_mem(mut addr: i32, mut r: i32) { trigger_ud(); } @@ -4112,6 +4141,7 @@ pub unsafe fn instr_0FD8(mut source: reg64, mut r: i32) { i = i.wrapping_add(1) } write_mmx_reg64(r, result); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FD8_reg(mut r1: i32, mut r2: i32) { instr_0FD8(read_mmx64s(r1), r2); } @@ -4150,6 +4180,7 @@ pub unsafe fn instr_0FD9(mut source: reg64, mut r: i32) { let mut low: i32 = word0 | word1 << 16; let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FD9_reg(mut r1: i32, mut r2: i32) { instr_0FD9(read_mmx64s(r1), r2); } @@ -4194,6 +4225,7 @@ pub unsafe fn instr_0FDA(mut source: reg64, mut r: i32) { i = i.wrapping_add(1) } write_mmx_reg64(r, result); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FDA_reg(mut r1: i32, mut r2: i32) { instr_0FDA(read_mmx64s(r1), r2); } @@ -4235,6 +4267,7 @@ pub unsafe fn instr_0FDB(mut source: reg64, mut r: i32) { }; result.u64_0[0] = source.u64_0[0] & destination.u64_0[0]; write_mmx_reg64(r, result); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FDB_reg(mut r1: i32, mut r2: i32) { instr_0FDB(read_mmx64s(r1), r2); } @@ -4269,6 +4302,7 @@ pub unsafe fn instr_0FDC(mut source: reg64, mut r: i32) { i = i.wrapping_add(1) } write_mmx_reg64(r, result); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FDC_reg(mut r1: i32, mut r2: i32) { instr_0FDC(read_mmx64s(r1), r2); } @@ -4308,6 +4342,7 @@ pub unsafe fn instr_0FDD(mut source: reg64, mut r: i32) { let mut low: i32 = word0 | word1 << 16; let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FDD_reg(mut r1: i32, mut r2: i32) { instr_0FDD(read_mmx64s(r1), r2); } @@ -4355,6 +4390,7 @@ pub unsafe fn instr_0FDE(mut source: reg64, mut r: i32) { i = i.wrapping_add(1) } write_mmx_reg64(r, result); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FDE_reg(mut r1: i32, mut r2: i32) { instr_0FDE(read_mmx64s(r1), r2); } @@ -4396,6 +4432,7 @@ pub unsafe fn instr_0FDF(mut source: reg64, mut r: i32) { }; result.u64_0[0] = source.u64_0[0] & !destination.u64_0[0]; write_mmx_reg64(r, result); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FDF_reg(mut r1: i32, mut r2: i32) { instr_0FDF(read_mmx64s(r1), r2); } @@ -4429,6 +4466,7 @@ pub unsafe fn instr_0FE0(mut source: reg64, mut r: i32) { i = i.wrapping_add(1) } write_mmx_reg64(r, result); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FE0_reg(mut r1: i32, mut r2: i32) { instr_0FE0(read_mmx64s(r1), r2); } @@ -4511,6 +4549,7 @@ pub unsafe fn instr_0FE3(mut source: reg64, mut r: i32) { destination.u16_0[2] = (destination.u16_0[2] as i32 + source.u16_0[2] as i32 + 1 >> 1) as u16; destination.u16_0[3] = (destination.u16_0[3] as i32 + source.u16_0[3] as i32 + 1 >> 1) as u16; write_mmx_reg64(r, destination); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FE3_reg(mut r1: i32, mut r2: i32) { instr_0FE3(read_mmx64s(r1), r2); } @@ -4552,6 +4591,7 @@ pub unsafe fn instr_0FE4(mut source: reg64, mut r: i32) { | (source.u16_0[3] as i32 * destination.u16_0[3] as i32) as u32 & 4294901760) as i32, ); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FE4_reg(mut r1: i32, mut r2: i32) { instr_0FE4(read_mmx64s(r1), r2); } @@ -4601,6 +4641,7 @@ pub unsafe fn instr_0FE5(mut source: reg64, mut r: i32) { let mut low: i32 = (word0 | word1 << 16) as i32; let mut high: i32 = (word2 | word3 << 16) as i32; write_mmx64(r, low, high); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FE5_reg(mut r1: i32, mut r2: i32) { instr_0FE5(read_mmx64s(r1), r2); } @@ -4732,6 +4773,7 @@ pub unsafe fn instr_0FE8(mut source: reg64, mut r: i32) { i = i.wrapping_add(1) } write_mmx_reg64(r, result); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FE8_reg(mut r1: i32, mut r2: i32) { instr_0FE8(read_mmx64s(r1), r2); } @@ -4775,6 +4817,7 @@ pub unsafe fn instr_0FE9(mut source: reg64, mut r: i32) { let mut low: i32 = word0 | word1 << 16; let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FE9_reg(mut r1: i32, mut r2: i32) { instr_0FE9(read_mmx64s(r1), r2); } @@ -4828,6 +4871,7 @@ pub unsafe fn instr_0FEA(mut source: reg64, mut r: i32) { i = i.wrapping_add(1) } write_mmx_reg64(r, result); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FEA_reg(mut r1: i32, mut r2: i32) { instr_0FEA(read_mmx64s(r1), r2); } @@ -4869,6 +4913,7 @@ pub unsafe fn instr_0FEB(mut source: reg64, mut r: i32) { }; result.u64_0[0] = source.u64_0[0] | destination.u64_0[0]; write_mmx_reg64(r, result); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FEB_reg(mut r1: i32, mut r2: i32) { instr_0FEB(read_mmx64s(r1), r2); } @@ -4903,6 +4948,7 @@ pub unsafe fn instr_0FEC(mut source: reg64, mut r: i32) { i = i.wrapping_add(1) } write_mmx_reg64(r, result); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FEC_reg(mut r1: i32, mut r2: i32) { instr_0FEC(read_mmx64s(r1), r2); } @@ -4946,6 +4992,7 @@ pub unsafe fn instr_0FED(mut source: reg64, mut r: i32) { let mut low: i32 = word0 | word1 << 16; let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FED_reg(mut r1: i32, mut r2: i32) { instr_0FED(read_mmx64s(r1), r2); } @@ -4999,6 +5046,7 @@ pub unsafe fn instr_0FEE(mut source: reg64, mut r: i32) { i = i.wrapping_add(1) } write_mmx_reg64(r, result); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FEE_reg(mut r1: i32, mut r2: i32) { instr_0FEE(read_mmx64s(r1), r2); } @@ -5040,6 +5088,7 @@ pub unsafe fn instr_0FEF(mut source: reg64, mut r: i32) { }; result.u64_0[0] = source.u64_0[0] ^ destination.u64_0[0]; write_mmx_reg64(r, result); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FEF_reg(mut r1: i32, mut r2: i32) { instr_0FEF(read_mmx64s(r1), r2); } @@ -5136,6 +5185,7 @@ pub unsafe fn instr_0FF4(mut source: reg64, mut r: i32) { let mut destination: reg64 = read_mmx64s(r); destination.u64_0[0] = (source.u32_0[0] as u64).wrapping_mul(destination.u32_0[0] as u64); write_mmx_reg64(r, destination); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FF4_reg(mut r1: i32, mut r2: i32) { instr_0FF4(read_mmx64s(r1), r2); } @@ -5169,6 +5219,7 @@ pub unsafe fn instr_0FF5(mut source: reg64, mut r: i32) { let mut low: i32 = mul0 + mul1; let mut high: i32 = mul2 + mul3; write_mmx64(r, low, high); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FF5_reg(mut r1: i32, mut r2: i32) { instr_0FF5(read_mmx64s(r1), r2); } @@ -5210,6 +5261,7 @@ pub unsafe fn instr_0FF6(mut source: reg64, mut r: i32) { i = i.wrapping_add(1) } write_mmx64(r, sum as i32, 0); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FF6_reg(mut r1: i32, mut r2: i32) { instr_0FF6(read_mmx64s(r1), r2); } @@ -5263,6 +5315,7 @@ pub unsafe fn instr_0FF7_reg(mut r1: i32, mut r2: i32) { } i = i.wrapping_add(1) } + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_660FF7_mem(mut addr: i32, mut r: i32) { trigger_ud(); } @@ -5298,6 +5351,7 @@ pub unsafe fn instr_0FF8(mut source: reg64, mut r: i32) { i = i.wrapping_add(1) } write_mmx_reg64(r, result); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FF8_reg(mut r1: i32, mut r2: i32) { instr_0FF8(read_mmx64s(r1), r2); } @@ -5340,6 +5394,7 @@ pub unsafe fn instr_0FF9(mut source: reg64, mut r: i32) { ((destination.u16_0[3] as u32).wrapping_sub(source.u16_0[3] as u32) & 65535 as u32) as i32; let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FF9_reg(mut r1: i32, mut r2: i32) { instr_0FF9(read_mmx64s(r1), r2); } @@ -5378,6 +5433,7 @@ pub unsafe fn instr_0FFA(mut source: reg64, mut r: i32) { destination.u32_0[0].wrapping_sub(source.u32_0[0]) as i32, destination.u32_0[1].wrapping_sub(source.u32_0[1]) as i32, ); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FFA_reg(mut r1: i32, mut r2: i32) { instr_0FFA(read_mmx64s(r1), r2); } @@ -5410,6 +5466,7 @@ pub unsafe fn instr_0FFB(mut source: reg64, mut r: i32) { let mut destination: reg64 = read_mmx64s(r); destination.u64_0[0] = destination.u64_0[0].wrapping_sub(source.u64_0[0]); write_mmx_reg64(r, destination); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FFB_reg(mut r1: i32, mut r2: i32) { instr_0FFB(read_mmx64s(r1), r2); } @@ -5446,6 +5503,7 @@ pub unsafe fn instr_0FFC(mut source: reg64, mut r: i32) { i = i.wrapping_add(1) } write_mmx_reg64(r, result); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FFC_reg(mut r1: i32, mut r2: i32) { instr_0FFC(read_mmx64s(r1), r2); } @@ -5486,6 +5544,7 @@ pub unsafe fn instr_0FFD(mut source: reg64, mut r: i32) { let mut word3: i32 = destination.u16_0[3] as i32 + source.u16_0[3] as i32 & 65535; let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FFD_reg(mut r1: i32, mut r2: i32) { instr_0FFD(read_mmx64s(r1), r2); } @@ -5522,6 +5581,7 @@ pub unsafe fn instr_0FFE(mut source: reg64, mut r: i32) { let mut low: i32 = destination.u32_0[0].wrapping_add(source.u32_0[0]) as i32; let mut high: i32 = destination.u32_0[1].wrapping_add(source.u32_0[1]) as i32; write_mmx64(r, low, high); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0FFE_reg(mut r1: i32, mut r2: i32) { instr_0FFE(read_mmx64s(r1), r2); } @@ -5576,12 +5636,12 @@ pub unsafe fn instr_0F1E_mem(mut addr: i32, mut r: i32) {} #[no_mangle] pub unsafe fn instr_0F2A(mut source: reg64, mut r: i32) { // cvtpi2ps xmm, mm/m64 - // XXX: The non-memory variant causes a transition from x87 FPU to MMX technology operation // Note: Casts here can fail let mut result: reg64 = reg64 { f32_0: [source.i32_0[0] as f32, source.i32_0[1] as f32], }; write_xmm64(r, result); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0F2A_reg(mut r1: i32, mut r2: i32) { instr_0F2A(read_mmx64s(r1), r2); } @@ -5592,12 +5652,12 @@ pub unsafe fn instr_0F2A_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_660F2A(mut source: reg64, mut r: i32) { // cvtpi2pd xmm, xmm/m64 - // XXX: The non-memory variant causes a transition from x87 FPU to MMX technology operation // These casts can't fail let mut result: reg128 = reg128 { f64_0: [source.i32_0[0] as f64, source.i32_0[1] as f64], }; write_xmm_reg128(r, result); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_660F2A_reg(mut r1: i32, mut r2: i32) { instr_660F2A(read_mmx64s(r1), r2); } @@ -5644,6 +5704,7 @@ pub unsafe fn instr_0F2D(mut source: reg64, mut r: i32) { ], }; write_mmx_reg64(r, result); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_0F2D_reg(mut r1: i32, mut r2: i32) { instr_0F2D(read_xmm64s(r1), r2); } @@ -5662,6 +5723,7 @@ pub unsafe fn instr_660F2D(mut source: reg128, mut r: i32) { ], }; write_mmx_reg64(r, result); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn instr_660F2D_reg(mut r1: i32, mut r2: i32) { instr_660F2D(read_xmm128s(r1), r2); } diff --git a/src/rust/cpu2/sse_instr.rs b/src/rust/cpu2/sse_instr.rs index 10ed1ab9..c6d55517 100644 --- a/src/rust/cpu2/sse_instr.rs +++ b/src/rust/cpu2/sse_instr.rs @@ -7,6 +7,7 @@ pub unsafe fn mov_r_m64(mut addr: i32, mut r: i32) { // mov* m64, mm let mut data: reg64 = read_mmx64s(r); return_on_pagefault!(safe_write64(addr, data.u64_0[0] as i64)); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn movl_r128_m64(mut addr: i32, mut r: i32) { @@ -109,6 +110,7 @@ pub unsafe fn psrlw_r64(mut r: i32, mut shift: u64) { dword1 = destination.u16_0[2] as i32 >> shift | destination.u16_0[3] as i32 >> shift << 16 } write_mmx64(r, dword0, dword1); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn psraw_r64(mut r: i32, mut shift: u64) { @@ -120,6 +122,7 @@ pub unsafe fn psraw_r64(mut r: i32, mut shift: u64) { let mut dword1: i32 = destination.i16_0[2] as i32 >> shift_clamped & 65535 | destination.i16_0[3] as i32 >> shift_clamped << 16; write_mmx64(r, dword0, dword1); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn psllw_r64(mut r: i32, mut shift: u64) { @@ -134,6 +137,7 @@ pub unsafe fn psllw_r64(mut r: i32, mut shift: u64) { | (destination.u16_0[3] as i32) << shift << 16 } write_mmx64(r, dword0, dword1); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn psrld_r64(mut r: i32, mut shift: u64) { @@ -146,6 +150,7 @@ pub unsafe fn psrld_r64(mut r: i32, mut shift: u64) { dword1 = (destination.u32_0[1] >> shift) as i32 } write_mmx64(r, dword0, dword1); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn psrad_r64(mut r: i32, mut shift: u64) { @@ -155,6 +160,7 @@ pub unsafe fn psrad_r64(mut r: i32, mut shift: u64) { let mut dword0: i32 = destination.i32_0[0] >> shift_clamped; let mut dword1: i32 = destination.i32_0[1] >> shift_clamped; write_mmx64(r, dword0, dword1); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn pslld_r64(mut r: i32, mut shift: u64) { @@ -167,6 +173,7 @@ pub unsafe fn pslld_r64(mut r: i32, mut shift: u64) { dword1 = destination.i32_0[1] << shift } write_mmx64(r, dword0, dword1); + transition_fpu_to_mmx(); } #[no_mangle] pub unsafe fn psrlq_r64(mut r: i32, mut shift: u64) { @@ -183,6 +190,7 @@ pub unsafe fn psrlq_r64(mut r: i32, mut shift: u64) { result.u64_0[0] = destination.u64_0[0] >> shift } write_mmx_reg64(r, result); + transition_fpu_to_mmx(); return; }; } @@ -201,6 +209,7 @@ pub unsafe fn psllq_r64(mut r: i32, mut shift: u64) { result.u64_0[0] = destination.u64_0[0] << shift } write_mmx_reg64(r, result); + transition_fpu_to_mmx(); return; }; } From fc35ea3ee2d02fe186e3516906f38da639e06ffe Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 10 Sep 2018 15:21:39 -0500 Subject: [PATCH 1342/2137] Add emms after code that uses mmx registers before code that uses fpu registers --- tests/qemu/test-i386.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/qemu/test-i386.c b/tests/qemu/test-i386.c index 140fa868..253ee993 100644 --- a/tests/qemu/test-i386.c +++ b/tests/qemu/test-i386.c @@ -2874,6 +2874,8 @@ void test_sse(void) asm volatile("ldmxcsr %0" : : "m" (mxcsr)); } + asm volatile ("emms"); + test_sse_comi(2, -1); test_sse_comi(2, 2); test_sse_comi(2, 3); From 96b703f87cf6518240b13b693969243c43d496c7 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 10 Sep 2018 15:34:48 -0500 Subject: [PATCH 1343/2137] Keep track of whether fpu or mmx register has been written recently, store proper register in fx?save --- src/rust/cpu2/cpu.rs | 2 ++ src/rust/cpu2/fpu.rs | 62 +++++++++++++++++--------------- src/rust/cpu2/global_pointers.rs | 1 + src/rust/cpu2/instructions.rs | 40 +++++++++++---------- src/rust/cpu2/misc_instr.rs | 28 ++++++++++++--- 5 files changed, 81 insertions(+), 52 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 42320f5f..f3da7266 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1706,11 +1706,13 @@ pub unsafe fn read_mmx32s(mut r: i32) -> i32 { pub unsafe fn read_mmx64s(mut r: i32) -> reg64 { return *reg_mmx.offset(r as isize); } pub unsafe fn write_mmx64(mut r: i32, mut low: i32, mut high: i32) { + *fxsave_store_fpu_mask &= !(1 << r); (*reg_mmx.offset(r as isize)).u32_0[0] = low as u32; (*reg_mmx.offset(r as isize)).u32_0[1] = high as u32; } pub unsafe fn write_mmx_reg64(mut r: i32, mut data: reg64) { + *fxsave_store_fpu_mask &= !(1 << r); (*reg_mmx.offset(r as isize)).u64_0[0] = data.u64_0[0]; } diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 67a38b93..6477c112 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -45,6 +45,14 @@ const FPU_EX_I: i32 = 1 << 0; const FPU_EX_SF: i32 = 1 << 6; const TWO_POW_63: f64 = 9223372036854775808u64 as f64; +pub fn fpu_write_st(index: i32, value: f64) { + dbg_assert!(index >= 0 && index < 8); + unsafe { + *fxsave_store_fpu_mask |= 1 << index; + *fpu_st.offset(index as isize) = value; + } +} + #[no_mangle] pub unsafe fn fpu_get_st0() -> f64 { if 0 != *fpu_stack_empty >> *fpu_stack_ptr & 1 { @@ -180,15 +188,14 @@ pub unsafe fn fpu_load_status_word() -> i32 { #[no_mangle] pub unsafe fn fpu_fadd(mut target_index: i32, mut val: f64) { let mut st0: f64 = fpu_get_st0(); - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7 as u32) as isize) = - st0 + val; + fpu_write_st(*fpu_stack_ptr as i32 + target_index & 7, st0 + val); } #[no_mangle] pub unsafe fn fpu_fclex() { *fpu_status_word = 0; } #[no_mangle] pub unsafe fn fpu_fcmovcc(mut condition: bool, mut r: i32) { if condition { - *fpu_st.offset(*fpu_stack_ptr as isize) = fpu_get_sti(r); + fpu_write_st(*fpu_stack_ptr as i32, fpu_get_sti(r)); *fpu_stack_empty &= !(1 << *fpu_stack_ptr) }; } @@ -244,14 +251,12 @@ pub unsafe fn fpu_fcomp(mut val: f64) { #[no_mangle] pub unsafe fn fpu_fdiv(mut target_index: i32, mut val: f64) { let mut st0: f64 = fpu_get_st0(); - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7 as u32) as isize) = - st0 / val; + fpu_write_st(*fpu_stack_ptr as i32 + target_index & 7, st0 / val); } #[no_mangle] pub unsafe fn fpu_fdivr(mut target_index: i32, mut val: f64) { let mut st0: f64 = fpu_get_st0(); - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7 as u32) as isize) = - val / st0; + fpu_write_st(*fpu_stack_ptr as i32 + target_index & 7, val / st0); } #[no_mangle] pub unsafe fn fpu_ffree(mut r: i32) { @@ -269,12 +274,12 @@ pub unsafe fn fpu_push(mut x: f64) { if 0 != *fpu_stack_empty >> *fpu_stack_ptr & 1 { *fpu_status_word &= !FPU_C1; *fpu_stack_empty &= !(1 << *fpu_stack_ptr); - *fpu_st.offset(*fpu_stack_ptr as isize) = x + fpu_write_st(*fpu_stack_ptr as i32, x); } else { *fpu_status_word |= FPU_C1; fpu_stack_fault(); - *fpu_st.offset(*fpu_stack_ptr as isize) = INDEFINITE_NAN + fpu_write_st(*fpu_stack_ptr as i32, INDEFINITE_NAN); }; } #[no_mangle] @@ -395,8 +400,7 @@ pub unsafe fn fpu_fldm80(mut addr: i32) { fpu_push(return_on_pagefault!(fpu_load #[no_mangle] pub unsafe fn fpu_fmul(mut target_index: i32, mut val: f64) { let mut st0: f64 = fpu_get_st0(); - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7 as u32) as isize) = - st0 * val; + fpu_write_st(*fpu_stack_ptr as i32 + target_index & 7, st0 * val); } #[no_mangle] pub unsafe fn fpu_fnstsw_mem(mut addr: i32) { @@ -410,7 +414,7 @@ pub unsafe fn fpu_fprem() { let mut st0: f64 = fpu_get_st0(); let mut st1: f64 = fpu_get_sti(1); let mut fprem_quotient: i32 = convert_f64_to_i32(trunc(st0 / st1)); - *fpu_st.offset(*fpu_stack_ptr as isize) = fmod(st0, st1); + fpu_write_st(*fpu_stack_ptr as i32, fmod(st0, st1)); *fpu_status_word &= !(FPU_C0 | FPU_C1 | FPU_C3); if 0 != fprem_quotient & 1 { *fpu_status_word |= FPU_C1 @@ -432,11 +436,14 @@ pub unsafe fn fpu_frstor(mut addr: i32) { addr += 28; let mut i: i32 = 0; while i < 8 { - *fpu_st.offset(((i as u32).wrapping_add(*fpu_stack_ptr) & 7 as u32) as isize) = - fpu_load_m80(addr).unwrap(); + let reg_index = *fpu_stack_ptr as i32 + i & 7; + *fpu_st.offset(reg_index as isize) = fpu_load_m80(addr).unwrap(); + *reg_mmx.offset(reg_index as isize) = safe_read64s(addr).unwrap(); addr += 10; i += 1 } + + *fxsave_store_fpu_mask = 0xff; } #[no_mangle] pub unsafe fn fpu_fsave(mut addr: i32) { @@ -445,10 +452,13 @@ pub unsafe fn fpu_fsave(mut addr: i32) { addr += 28; let mut i: i32 = 0; while i < 8 { - fpu_store_m80( - addr, - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(i as u32) & 7) as isize), - ); + let reg_index = i + *fpu_stack_ptr as i32 & 7; + if *fxsave_store_fpu_mask & 1 << reg_index != 0 { + fpu_store_m80(addr, *fpu_st.offset(reg_index as isize)); + } + else { + safe_write64(addr, (*reg_mmx.offset(reg_index as isize)).i64_0[0]).unwrap(); + } addr += 10; i += 1 } @@ -534,9 +544,7 @@ pub unsafe fn fpu_load_tag_word() -> i32 { return tag_word; } #[no_mangle] -pub unsafe fn fpu_fst(mut r: i32) { - *fpu_st.offset((*fpu_stack_ptr).wrapping_add(r as u32) as isize & 7) = fpu_get_st0(); -} +pub unsafe fn fpu_fst(mut r: i32) { fpu_write_st(*fpu_stack_ptr as i32 + r & 7, fpu_get_st0()); } #[no_mangle] pub unsafe fn fpu_fst80p(mut addr: i32) { return_on_pagefault!(writable_or_pagefault(addr, 10)); @@ -583,14 +591,12 @@ pub unsafe fn fpu_fstp(mut r: i32) { #[no_mangle] pub unsafe fn fpu_fsub(mut target_index: i32, mut val: f64) { let mut st0: f64 = fpu_get_st0(); - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7 as u32) as isize) = - st0 - val; + fpu_write_st(*fpu_stack_ptr as i32 + target_index & 7, st0 - val) } #[no_mangle] pub unsafe fn fpu_fsubr(mut target_index: i32, mut val: f64) { let mut st0: f64 = fpu_get_st0(); - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(target_index as u32) & 7 as u32) as isize) = - val - st0; + fpu_write_st(*fpu_stack_ptr as i32 + target_index & 7, val - st0) } #[no_mangle] pub unsafe fn fpu_ftst(mut x: f64) { @@ -665,8 +671,8 @@ pub unsafe fn fpu_sign(mut i: i32) -> i32 { #[no_mangle] pub unsafe fn fpu_fxch(mut i: i32) { let mut sti: f64 = fpu_get_sti(i); - *fpu_st.offset((*fpu_stack_ptr).wrapping_add(i as u32) as isize & 7) = fpu_get_st0(); - *fpu_st.offset(*fpu_stack_ptr as isize) = sti; + fpu_write_st(*fpu_stack_ptr as i32 + i & 7, fpu_get_st0()); + fpu_write_st(*fpu_stack_ptr as i32, sti); } #[no_mangle] pub unsafe fn fpu_fxtract() { @@ -678,7 +684,7 @@ pub unsafe fn fpu_fxtract() { - 1023) as f64; double_int_view.u8_0[7] = (63 | double_int_view.u8_0[7] as i32 & 128) as u8; double_int_view.u8_0[6] = (double_int_view.u8_0[6] as i32 | 240) as u8; - *fpu_st.offset(*fpu_stack_ptr as isize) = exponent; + fpu_write_st(*fpu_stack_ptr as i32, exponent); fpu_push(double_int_view.f64_0); } #[no_mangle] diff --git a/src/rust/cpu2/global_pointers.rs b/src/rust/cpu2/global_pointers.rs index f922112e..c21da9f4 100644 --- a/src/rust/cpu2/global_pointers.rs +++ b/src/rust/cpu2/global_pointers.rs @@ -61,6 +61,7 @@ pub const fpu_dp: *mut i32 = 1056 as *mut i32; pub const fpu_dp_selector: *mut i32 = 1060 as *mut i32; pub const reg_mmx: *mut reg64 = 1064 as *mut reg64; pub const tss_size_32: *mut bool = 1128 as *mut bool; +pub const fxsave_store_fpu_mask: *mut u8 = 1132 as *mut u8; pub const opstats_buffer: *mut u32 = 4096 as *mut u32; pub const opstats_buffer_0f: *mut u32 = 5120 as *mut u32; pub const tlb_data: *mut i32 = 0x400000 as *mut i32; diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index d80b492b..585c0f1f 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -30,7 +30,7 @@ extern "C" { use cpu2::arith::*; use cpu2::cpu::*; use cpu2::fpu::*; -use cpu2::fpu::{fpu_load_m32, fpu_load_m64}; +use cpu2::fpu::{fpu_load_m32, fpu_load_m64, fpu_write_st}; use cpu2::global_pointers::*; use cpu2::misc_instr::*; use cpu2::misc_instr::{pop16, pop32s, push16, push32}; @@ -3730,11 +3730,11 @@ pub unsafe fn instr_D9_4_reg(mut r: i32) { match r { 0 => { // fchs - *fpu_st.offset(*fpu_stack_ptr as isize) = -st0 + fpu_write_st(*fpu_stack_ptr as i32, -st0); }, 1 => { // fabs - *fpu_st.offset(*fpu_stack_ptr as isize) = st0.abs() + fpu_write_st(*fpu_stack_ptr as i32, st0.abs()); }, 4 => { fpu_ftst(st0); @@ -3790,24 +3790,25 @@ pub unsafe fn instr_D9_6_reg(mut r: i32) { match r { 0 => { // f2xm1 - *fpu_st.offset(*fpu_stack_ptr as isize) = pow(2 as f64, st0) - 1 as f64 + fpu_write_st(*fpu_stack_ptr as i32, pow(2 as f64, st0) - 1 as f64) }, 1 => { // fyl2x - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(1 as u32) & 7 as u32) as isize) = - fpu_get_sti(1) * st0.ln() / M_LN2; + fpu_write_st( + *fpu_stack_ptr as i32 + 1 & 7, + fpu_get_sti(1) * st0.ln() / M_LN2, + ); fpu_pop(); }, 2 => { // fptan - *fpu_st.offset(*fpu_stack_ptr as isize) = st0.tan(); - fpu_push(1 as f64); + fpu_write_st(*fpu_stack_ptr as i32, st0.tan()); // no bug: push constant 1 + fpu_push(1 as f64); }, 3 => { // fpatan - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(1 as u32) & 7 as u32) as isize) = - fpu_get_sti(1).atan2(st0); + fpu_write_st(*fpu_stack_ptr as i32 + 1 & 7, fpu_get_sti(1).atan2(st0)); fpu_pop(); }, 4 => { @@ -3815,7 +3816,7 @@ pub unsafe fn instr_D9_6_reg(mut r: i32) { }, 5 => { // fprem1 - *fpu_st.offset(*fpu_stack_ptr as isize) = fmod(st0, fpu_get_sti(1)) + fpu_write_st(*fpu_stack_ptr as i32, fmod(st0, fpu_get_sti(1))); }, 6 => { // fdecstp @@ -3843,25 +3844,26 @@ pub unsafe fn instr_D9_7_reg(mut r: i32) { }, 1 => { // fyl2xp1: y * log2(x+1) and pop - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(1 as u32) & 7 as u32) as isize) = - fpu_get_sti(1) * (st0 + 1 as f64).ln() / M_LN2; + let y = fpu_get_sti(1) * (st0 + 1 as f64).ln() / M_LN2; + fpu_write_st(*fpu_stack_ptr as i32 + 1 & 7, y); fpu_pop(); }, - 2 => *fpu_st.offset(*fpu_stack_ptr as isize) = st0.sqrt(), + 2 => fpu_write_st(*fpu_stack_ptr as i32, st0.sqrt()), 3 => { - *fpu_st.offset(*fpu_stack_ptr as isize) = st0.sin(); + fpu_write_st(*fpu_stack_ptr as i32, st0.sin()); fpu_push(st0.cos()); }, 4 => { // frndint - *fpu_st.offset(*fpu_stack_ptr as isize) = fpu_integer_round(st0) + fpu_write_st(*fpu_stack_ptr as i32, fpu_integer_round(st0)); }, 5 => { // fscale - *fpu_st.offset(*fpu_stack_ptr as isize) = st0 * pow(2 as f64, trunc(fpu_get_sti(1))) + let y = st0 * pow(2 as f64, trunc(fpu_get_sti(1))); + fpu_write_st(*fpu_stack_ptr as i32, y); }, - 6 => *fpu_st.offset(*fpu_stack_ptr as isize) = st0.sin(), - 7 => *fpu_st.offset(*fpu_stack_ptr as isize) = st0.cos(), + 6 => fpu_write_st(*fpu_stack_ptr as i32, st0.sin()), + 7 => fpu_write_st(*fpu_stack_ptr as i32, st0.cos()), _ => { dbg_assert!(0 != 0); }, diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index 698ed177..d1019368 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -340,14 +340,23 @@ pub unsafe fn fxsave(mut addr: i32) { safe_write16(addr.wrapping_add(20) as i32, *fpu_dp_selector).unwrap(); safe_write32(addr.wrapping_add(24) as i32, *mxcsr).unwrap(); safe_write32(addr.wrapping_add(28) as i32, MXCSR_MASK).unwrap(); + let mut i: i32 = 0; while i < 8 { - fpu_store_m80( - addr.wrapping_add(32).wrapping_add(i << 4), - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(i as u32) & 7) as isize), - ); + let reg_index = i + *fpu_stack_ptr as i32 & 7; + if *fxsave_store_fpu_mask & 1 << reg_index != 0 { + fpu_store_m80(addr + 32 + (i << 4), *fpu_st.offset(reg_index as isize)); + } + else { + safe_write64( + addr + 32 + (i << 4), + (*reg_mmx.offset(reg_index as isize)).i64_0[0], + ).unwrap(); + safe_write64(addr + 32 + (i << 4) | 8, 0).unwrap(); + } i += 1 } + // If the OSFXSR bit in control register CR4 is not set, the FXSAVE // instruction may not save these registers. This behavior is // implementation dependent. @@ -381,12 +390,21 @@ pub unsafe fn fxrstor(mut addr: i32) { *fpu_dp = safe_read32s(addr.wrapping_add(16) as i32).unwrap(); *fpu_dp_selector = safe_read16(addr.wrapping_add(20) as i32).unwrap(); set_mxcsr(new_mxcsr); + let mut i: i32 = 0; while i < 8 { - *fpu_st.offset(((*fpu_stack_ptr).wrapping_add(i as u32) & 7 as u32) as isize) = + let reg_index = *fpu_stack_ptr as i32 + i & 7; + *fpu_st.offset(reg_index as isize) = fpu_load_m80(addr.wrapping_add(32).wrapping_add(i << 4)).unwrap(); + *reg_mmx.offset(reg_index as isize) = + safe_read64s(addr.wrapping_add(32).wrapping_add(i << 4)).unwrap(); i += 1 } + + // Mark values as coming from the fpu: xmm registers fit into x87 registers, but not the + // other way around + *fxsave_store_fpu_mask = 0xff; + let mut i_0: i32 = 0; while i_0 < 8 { (*reg_xmm.offset(i_0 as isize)).u32_0[0] = safe_read32s( From 7620a7cb84a20a242950a51b02030b7176e18395 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 10 Sep 2018 17:31:27 -0500 Subject: [PATCH 1344/2137] fpu: Refactor (de-)serialisation of f32/f64/f80, add tests for denormals and nans --- src/rust/cpu2/fpu.rs | 221 +++++++++++++++++++++++++------------------ 1 file changed, 128 insertions(+), 93 deletions(-) diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 6477c112..535c0de6 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -14,23 +14,6 @@ pub fn convert_f64_to_i32(x: f64) -> i32 { x as i32 } pub fn trunc(x: f64) -> f64 { x.trunc() } pub fn fmod(x: f64, y: f64) -> f64 { x % y } -#[derive(Copy, Clone)] -#[repr(C)] -pub union f64_int { - u8_0: [u8; 8], - i32_0: [i32; 2], - u64_0: [u64; 1], - f64_0: f64, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub union f32_int { - u8_0: [u8; 4], - i32_0: i32, - f32_0: f32, -} - pub const M_LOG2E: f64 = 1.4426950408889634f64; pub const M_LN2: f64 = 0.6931471805599453f64; pub const M_LN10: f64 = 2.302585092994046f64; @@ -45,6 +28,44 @@ const FPU_EX_I: i32 = 1 << 0; const FPU_EX_SF: i32 = 1 << 6; const TWO_POW_63: f64 = 9223372036854775808u64 as f64; +const F64_MANTISSA_MASK: u64 = (1 << 52) - 1; +const F64_EXPONENT_MASK: u16 = 0x7FF; +const F64_EXPONENT_NAN_INF: u16 = 0x7FF; +const F64_SIGN_SHIFT: u32 = 63; +const F64_EXPONENT_SHIFT: u32 = 52; +const F64_EXPONENT_BIAS: u16 = 0x3FF; + +const F80_EXPONENT_MASK: u16 = 0x7FFF; +const F80_EXPONENT_NAN_INF: u16 = 0x7FFF; +const F80_EXPONENT_BIAS: u16 = 0x3FFF; + +pub struct FloatParts { + sign: bool, + exponent: u16, + mantissa: u64, +} + +impl FloatParts { + pub fn to_f64(&self) -> f64 { + dbg_assert!(self.exponent <= F64_EXPONENT_MASK); + dbg_assert!(self.mantissa <= F64_MANTISSA_MASK); + let d = (self.sign as u64) << F64_SIGN_SHIFT + | (self.exponent as u64) << F64_EXPONENT_SHIFT + | self.mantissa; + let f: f64 = unsafe { transmute(d) }; + f + } + + pub fn of_f64(f: f64) -> FloatParts { + let d: u64 = unsafe { transmute(f) }; + FloatParts { + sign: d >> F64_SIGN_SHIFT == 1, + exponent: (d >> F64_EXPONENT_SHIFT) as u16 & F64_EXPONENT_MASK, + mantissa: d & F64_MANTISSA_MASK, + } + } +} + pub fn fpu_write_st(index: i32, value: f64) { dbg_assert!(index >= 0 && index < 8); unsafe { @@ -105,79 +126,98 @@ pub unsafe fn fpu_integer_round(mut f: f64) -> f64 { } #[no_mangle] pub unsafe fn fpu_load_m32(mut addr: i32) -> OrPageFault { - let mut v: f32_int = f32_int { - i32_0: safe_read32s(addr)?, - }; - Ok(v.f32_0 as f64) + let v: f32 = transmute(safe_read32s(addr)?); + Ok(v as f64) } #[no_mangle] pub unsafe fn fpu_load_m64(mut addr: i32) -> OrPageFault { let mut value: u64 = safe_read64s(addr)?.u64_0[0]; - let mut v: f64_int = f64_int { u64_0: [value] }; - Ok(v.f64_0) + let f: f64 = transmute(value); + Ok(f) } #[no_mangle] pub unsafe fn fpu_load_m80(mut addr: i32) -> OrPageFault { let mut value: u64 = safe_read64s(addr as i32)?.u64_0[0]; let mut exponent: i32 = safe_read16(addr.wrapping_add(8) as i32)?; - let f = fpu_i80_to_f64((value, exponent as u16)); + let f = fpu_f80_to_f64((value, exponent as u16)); Ok(f) } -pub unsafe fn fpu_i80_to_f64(i: (u64, u16)) -> f64 { - let mut value: u64 = i.0; - let mut low: u32 = value as u32; - let mut high: u32 = (value >> 32) as u32; - let mut exponent = i.1 as i32; - let mut sign = exponent >> 15; - exponent &= !32768; +pub unsafe fn fpu_f80_to_f64(i: (u64, u16)) -> f64 { + let mantissa: u64 = i.0; + let exponent = i.1 & F80_EXPONENT_MASK; + let sign = i.1 >> 15 == 1; + if exponent == 0 { - let d: u64 = (sign as u64) << 63 | (high as u64) << 20 | (low as u64) >> 12; + // Denormal number + // A few bits of precision lost and "integer part" bit ignored + let d: u64 = (sign as u64) << F64_SIGN_SHIFT | (mantissa >> 11 & F64_MANTISSA_MASK); let f: f64 = transmute(d); f } - else if exponent < 32767 { - exponent -= 16383; + else if exponent < F80_EXPONENT_NAN_INF { + let biased_exponent = exponent as i32 - F80_EXPONENT_BIAS as i32; // Note: some bits might be lost at this point - let mut mantissa: f64 = low as f64 + 4294967296i64 as f64 * high as f64; - if 0 != sign { + let mut mantissa = mantissa as f64; + if sign { mantissa = -mantissa } // Simply compute the 64 bit floating point number. // An alternative write the mantissa, sign and exponent in the // float64_byte and return float64[0] - mantissa * pow(2 as f64, (exponent - 63) as f64) + mantissa * pow(2.0, biased_exponent as f64 - 63.0) } else { - // TODO: NaN, Infinity - if 0 != 0 * 0 { - dbg_log!("Load m80 TODO"); - } - let mut double_int_view: f64_int = f64_int { u8_0: [0; 8] }; - double_int_view.u8_0[7] = (127 | sign << 7) as u8; - double_int_view.u8_0[6] = (240 as u32 | high >> 30 << 3 & 8 as u32) as u8; - double_int_view.u8_0[5] = 0 as u8; - double_int_view.u8_0[4] = 0 as u8; - double_int_view.i32_0[0] = 0; - double_int_view.f64_0 + // NaN, Infinity + // Note: 11 bits of the NaN payload lost and "integer part" bit ignored + let mantissa = (mantissa >> 11) & F64_MANTISSA_MASK; + let f = FloatParts { + sign, + exponent: F64_EXPONENT_NAN_INF, + mantissa, + }; + f.to_f64() } } #[cfg(test)] mod tests { - use super::{f64_int, fpu_f64_to_i80, fpu_i80_to_f64}; + use super::{fpu_f64_to_f80, fpu_f80_to_f64, FloatParts, F64_EXPONENT_NAN_INF}; + use std::mem::transmute; + + fn test_f80_f64_conversion(d: u64) -> bool { + let f = unsafe { transmute(d) }; + let f2 = unsafe { fpu_f80_to_f64(fpu_f64_to_f80(f)) }; + let d2: u64 = unsafe { transmute(f2) }; + d == d2 + } + quickcheck! { - fn i80_f64_conversion(d: u64) -> bool { - let double_int_view = f64_int { u64_0: [d] }; - let f = unsafe { double_int_view.f64_0 }; - unsafe { f == fpu_i80_to_f64(fpu_f64_to_i80(f)) } + fn f80_f64_conversion(d: u64) -> bool { + test_f80_f64_conversion(d) + } + + fn f80_f64_conversion_nan_inf(d: u64) -> bool { + let f = unsafe { transmute(d) }; + let mut parts = FloatParts::of_f64(f); + parts.exponent = F64_EXPONENT_NAN_INF; + let d: u64 = unsafe { transmute(parts.to_f64()) }; + test_f80_f64_conversion(d) + } + + fn f80_f64_conversion_denormal(d: u64) -> bool { + let f = unsafe { transmute(d) }; + let mut parts = FloatParts::of_f64(f); + parts.exponent = 0; + let d: u64 = unsafe { transmute(parts.to_f64()) }; + test_f80_f64_conversion(d) } } #[test] - fn more_i80_f64_conversions() { - assert_eq!(unsafe { fpu_f64_to_i80(0.) }, (0, 0)); + fn more_f80_f64_conversions() { + assert_eq!(unsafe { fpu_f64_to_f80(0.) }, (0, 0)); } } @@ -467,42 +507,40 @@ pub unsafe fn fpu_fsave(mut addr: i32) { #[no_mangle] pub unsafe fn fpu_store_m80(mut addr: i32, mut n: f64) { - let (value, exponent) = fpu_f64_to_i80(n); + let (value, exponent) = fpu_f64_to_f80(n); // writable_or_pagefault must have checked called by the caller! safe_write64(addr, value as i64).unwrap(); safe_write16(addr + 8, exponent as i32).unwrap(); } -pub unsafe fn fpu_f64_to_i80(f: f64) -> (u64, u16) { - let mut double_int_view: f64_int = f64_int { f64_0: f }; - let mut sign: u8 = double_int_view.u8_0[7] >> 7; - let mut exponent: i32 = - (double_int_view.u8_0[7] as i32 & 127) << 4 | double_int_view.u8_0[6] as i32 >> 4; - let mantissa = double_int_view.u64_0[0] & ((1 << 52) - 1); - let mut low; - let mut high; - if exponent == 2047 { +pub unsafe fn fpu_f64_to_f80(f: f64) -> (u64, u16) { + let f = FloatParts::of_f64(f); + + let mut exponent; + + // This bit is implicit (doesn't exist) in f32 and f64. + // See https://en.wikipedia.org/wiki/Extended_precision#x86_extended_precision_format for normal values for this bit + let mut integer_part; + + if f.exponent == F64_EXPONENT_NAN_INF { // all bits set (NaN and infinity) - exponent = 32767; - low = 0; - high = (2147483648 | ((double_int_view.i32_0[1] & 524288) << 11) as u32) as i32 + exponent = F80_EXPONENT_NAN_INF; + integer_part = 1; } - else if exponent == 0 { + else if f.exponent == 0 { // zero and denormal numbers - return (mantissa << 12, (sign as u16) << 15); + exponent = 0; + integer_part = 0; } else { - exponent += 16383 - 1023; - // does the mantissa need to be adjusted? - low = double_int_view.i32_0[0] << 11; - high = (2147483648 - | ((double_int_view.i32_0[1] & 1048575) << 11) as u32 - | double_int_view.i32_0[0] as u32 >> 21) as i32 + exponent = f.exponent + F80_EXPONENT_BIAS - F64_EXPONENT_BIAS; + integer_part = 1; } - dbg_assert!(exponent >= 0 && exponent < 32768); + + dbg_assert!(exponent < 0x8000); ( - (low as u64 & 4294967295 as u64 | (high as u64) << 32) as u64, - ((sign as i32) << 15 | exponent) as u16, + integer_part << 63 | f.mantissa << 11, + (f.sign as u16) << 15 | exponent, ) } @@ -561,8 +599,8 @@ pub unsafe fn fpu_fstm32(mut addr: i32) { } #[no_mangle] pub unsafe fn fpu_store_m32(mut addr: i32, mut x: f64) -> OrPageFault<()> { - let mut v: f32_int = f32_int { f32_0: x as f32 }; - safe_write32(addr, v.i32_0) + let v = transmute(x as f32); + safe_write32(addr, v) } #[no_mangle] pub unsafe fn fpu_fstm32p(mut addr: i32) { @@ -575,8 +613,8 @@ pub unsafe fn fpu_fstm64(mut addr: i32) { } #[no_mangle] pub unsafe fn fpu_store_m64(mut addr: i32, mut x: f64) -> OrPageFault<()> { - let mut v: f64_int = f64_int { f64_0: x }; - safe_write64(addr, v.u64_0[0] as i64) + let v: i64 = transmute(x); + safe_write64(addr, v) } #[no_mangle] pub unsafe fn fpu_fstm64p(mut addr: i32) { @@ -676,16 +714,13 @@ pub unsafe fn fpu_fxch(mut i: i32) { } #[no_mangle] pub unsafe fn fpu_fxtract() { - let mut double_int_view: f64_int = f64_int { - f64_0: fpu_get_st0(), - }; - let mut exponent: f64 = (((double_int_view.u8_0[7] as i32 & 127) << 4 - | double_int_view.u8_0[6] as i32 >> 4) - - 1023) as f64; - double_int_view.u8_0[7] = (63 | double_int_view.u8_0[7] as i32 & 128) as u8; - double_int_view.u8_0[6] = (double_int_view.u8_0[6] as i32 | 240) as u8; - fpu_write_st(*fpu_stack_ptr as i32, exponent); - fpu_push(double_int_view.f64_0); + let mut f = FloatParts::of_f64(fpu_get_st0()); + fpu_write_st( + *fpu_stack_ptr as i32, + f.exponent as f64 - F64_EXPONENT_BIAS as f64, + ); + f.exponent = 0x7FF; + fpu_push(f.to_f64()); } #[no_mangle] pub unsafe fn fwait() { From 13f4a33231950888c2d740e5e3f1a1437011eb9c Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 12 Sep 2018 10:59:38 -0500 Subject: [PATCH 1345/2137] task_switch_test_mmx: Fix order of checks --- src/rust/cpu2/cpu.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index f3da7266..2db569ae 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1808,12 +1808,12 @@ pub unsafe fn task_switch_test_mmx() -> bool { if *cr.offset(4) & CR4_OSFXSR == 0 { dbg_log!("Warning: Unimplemented task switch test with cr4.osfxsr=0"); } - if 0 != *cr & CR0_TS { - trigger_nm(); + if 0 != *cr & CR0_EM { + trigger_ud(); return 0 != 0; } - else if 0 != *cr & CR0_EM { - trigger_ud(); + else if 0 != *cr & CR0_TS { + trigger_nm(); return 0 != 0; } else { From d895985e83772dbe22f3f7e5cd44c21cd2d9cc41 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 10 Sep 2018 22:26:56 -0500 Subject: [PATCH 1346/2137] c2rust cleanup: Turn while loops into for loops --- src/rust/cpu2/cpu.rs | 43 +++------ src/rust/cpu2/fpu.rs | 16 +--- src/rust/cpu2/instructions_0f.rs | 149 ++++++++----------------------- src/rust/cpu2/misc_instr.rs | 52 ++++------- 4 files changed, 71 insertions(+), 189 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 2db569ae..13ea3601 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -464,15 +464,11 @@ pub unsafe fn do_page_translation( } else if CHECK_TLB_INVARIANTS { let mut found: bool = 0 != 0; - let mut i: i32 = 0; - while i < valid_tlb_entries_count { + for i in 0..valid_tlb_entries_count { if valid_tlb_entries[i as usize] == page { found = 0 != 1; break; } - else { - i += 1 - } } dbg_assert!(found); } @@ -522,18 +518,14 @@ pub unsafe fn full_clear_tlb() { // clear tlb including global pages *last_virt_eip = -1; *last_virt_esp = -1; - let mut i: i32 = 0; - while i < valid_tlb_entries_count { + for i in 0..valid_tlb_entries_count { let mut page: i32 = valid_tlb_entries[i as usize]; *tlb_data.offset(page as isize) = 0; - i += 1 } valid_tlb_entries_count = 0; if CHECK_TLB_INVARIANTS { - let mut i_0: i32 = 0; - while i_0 < 1048576 { - dbg_assert!(*tlb_data.offset(i_0 as isize) == 0); - i_0 += 1 + for i in 0..1048576 { + dbg_assert!(*tlb_data.offset(i as isize) == 0); } }; } @@ -545,8 +537,7 @@ pub unsafe fn clear_tlb() { *last_virt_eip = -1; *last_virt_esp = -1; let mut global_page_offset: i32 = 0; - let mut i: i32 = 0; - while i < valid_tlb_entries_count { + for i in 0..valid_tlb_entries_count { let mut page: i32 = valid_tlb_entries[i as usize]; let mut entry: i32 = *tlb_data.offset(page as isize); if 0 != entry & TLB_GLOBAL { @@ -557,17 +548,13 @@ pub unsafe fn clear_tlb() { else { *tlb_data.offset(page as isize) = 0 } - i += 1 } valid_tlb_entries_count = global_page_offset; if CHECK_TLB_INVARIANTS { - let mut i_0: i32 = 0; - while i_0 < 1048576 { + for i in 0..1048576 { dbg_assert!( - *tlb_data.offset(i_0 as isize) == 0 - || 0 != *tlb_data.offset(i_0 as isize) & TLB_GLOBAL + *tlb_data.offset(i as isize) == 0 || 0 != *tlb_data.offset(i as isize) & TLB_GLOBAL ); - i_0 += 1 } }; } @@ -627,8 +614,7 @@ pub unsafe fn translate_address_write(mut address: i32) -> OrPageFault { #[no_mangle] pub unsafe fn tlb_set_has_code(mut physical_page: u32, mut has_code: bool) { dbg_assert!(physical_page < (1 << 20) as u32); - let mut i: i32 = 0; - while i < valid_tlb_entries_count { + for i in 0..valid_tlb_entries_count { let mut page: i32 = valid_tlb_entries[i as usize]; let mut entry: i32 = *tlb_data.offset(page as isize); if 0 != entry { @@ -642,7 +628,6 @@ pub unsafe fn tlb_set_has_code(mut physical_page: u32, mut has_code: bool) { } } } - i += 1 } check_tlb_invariants(); } @@ -653,14 +638,12 @@ pub unsafe fn check_tlb_invariants() { return; } else { - let mut i: i32 = 0; - while i < valid_tlb_entries_count { + for i in 0..valid_tlb_entries_count { let mut page: i32 = valid_tlb_entries[i as usize]; let mut entry: i32 = *tlb_data.offset(page as isize); if 0 == entry || 0 != entry & TLB_IN_MAPPED_RANGE { // there's no code in mapped memory } - i += 1 } return; }; @@ -2008,14 +1991,12 @@ pub unsafe fn get_valid_tlb_entries_count() -> i32 { return 0; } let mut result: i32 = 0; - let mut i: i32 = 0; - while i < valid_tlb_entries_count { + for i in 0..valid_tlb_entries_count { let mut page: i32 = valid_tlb_entries[i as usize]; let mut entry: i32 = *tlb_data.offset(page as isize); if 0 != entry { result += 1 } - i += 1 } return result; } @@ -2026,14 +2007,12 @@ pub unsafe fn get_valid_global_tlb_entries_count() -> i32 { return 0; } let mut result: i32 = 0; - let mut i: i32 = 0; - while i < valid_tlb_entries_count { + for i in 0..valid_tlb_entries_count { let mut page: i32 = valid_tlb_entries[i as usize]; let mut entry: i32 = *tlb_data.offset(page as isize); if 0 != entry & TLB_GLOBAL { result += 1 } - i += 1 } return result; } diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 535c0de6..7a482c66 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -417,11 +417,9 @@ pub unsafe fn fpu_unimpl() { #[no_mangle] pub unsafe fn fpu_set_tag_word(mut tag_word: i32) { *fpu_stack_empty = 0; - let mut i: i32 = 0; - while i < 8 { + for i in 0..8 { let empty = tag_word >> (2 * i) & 3 == 3; *fpu_stack_empty |= (empty as i32) << i; - i += 1 } } #[no_mangle] @@ -474,13 +472,11 @@ pub unsafe fn fpu_frstor(mut addr: i32) { return_on_pagefault!(translate_address_read(addr + 28 + 8 * 10)); fpu_fldenv(addr); addr += 28; - let mut i: i32 = 0; - while i < 8 { + for i in 0..8 { let reg_index = *fpu_stack_ptr as i32 + i & 7; *fpu_st.offset(reg_index as isize) = fpu_load_m80(addr).unwrap(); *reg_mmx.offset(reg_index as isize) = safe_read64s(addr).unwrap(); addr += 10; - i += 1 } *fxsave_store_fpu_mask = 0xff; @@ -490,8 +486,7 @@ pub unsafe fn fpu_fsave(mut addr: i32) { return_on_pagefault!(writable_or_pagefault(addr, 108)); fpu_fstenv(addr); addr += 28; - let mut i: i32 = 0; - while i < 8 { + for i in 0..8 { let reg_index = i + *fpu_stack_ptr as i32 & 7; if *fxsave_store_fpu_mask & 1 << reg_index != 0 { fpu_store_m80(addr, *fpu_st.offset(reg_index as isize)); @@ -500,7 +495,6 @@ pub unsafe fn fpu_fsave(mut addr: i32) { safe_write64(addr, (*reg_mmx.offset(reg_index as isize)).i64_0[0]).unwrap(); } addr += 10; - i += 1 } fpu_finit(); } @@ -565,8 +559,7 @@ pub unsafe fn fpu_fstenv(mut addr: i32) { #[no_mangle] pub unsafe fn fpu_load_tag_word() -> i32 { let mut tag_word: i32 = 0; - let mut i: i32 = 0; - while i < 8 { + for i in 0..8 { let mut value: f64 = *fpu_st.offset(i as isize); if 0 != *fpu_stack_empty >> i & 1 { tag_word |= 3 << (i << 1) @@ -577,7 +570,6 @@ pub unsafe fn fpu_load_tag_word() -> i32 { else if !value.is_finite() { tag_word |= 2 << (i << 1) } - i += 1 } return tag_word; } diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 5011c241..d54e272d 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -1967,8 +1967,7 @@ pub unsafe fn instr_0F64(mut source: reg64, mut r: i32) { let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0 as u32; - while i < 8 as u32 { + for i in 0..8 { result.u8_0[i as usize] = (if destination.i8_0[i as usize] as i32 > source.i8_0[i as usize] as i32 { 255 @@ -1976,7 +1975,6 @@ pub unsafe fn instr_0F64(mut source: reg64, mut r: i32) { else { 0 }) as u8; - i = i.wrapping_add(1) } write_mmx_reg64(r, result); transition_fpu_to_mmx(); @@ -1995,8 +1993,7 @@ pub unsafe fn instr_660F64(mut source: reg128, mut r: i32) { let mut result: reg128 = reg128 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: i32 = 0; - while i < 16 { + for i in 0..16 { result.i8_0[i as usize] = (if destination.i8_0[i as usize] as i32 > source.i8_0[i as usize] as i32 { 255 @@ -2004,7 +2001,6 @@ pub unsafe fn instr_660F64(mut source: reg128, mut r: i32) { else { 0 }) as i8; - i += 1 } write_xmm_reg128(r, result); } @@ -2061,8 +2057,7 @@ pub unsafe fn instr_660F65(mut source: reg128, mut r: i32) { let mut result: reg128 = reg128 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: i32 = 0; - while i < 8 { + for i in 0..8 { result.u16_0[i as usize] = (if destination.i16_0[i as usize] as i32 > source.i16_0[i as usize] as i32 { 65535 @@ -2070,7 +2065,6 @@ pub unsafe fn instr_660F65(mut source: reg128, mut r: i32) { else { 0 }) as u16; - i += 1 } write_xmm_reg128(r, result); } @@ -2171,11 +2165,9 @@ pub unsafe fn instr_660F67(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: i32 = 0; - while i < 8 { + for i in 0..8 { result.u8_0[i as usize] = saturate_sw_to_ub(destination.u16_0[i as usize] as u32) as u8; result.u8_0[(i | 8) as usize] = saturate_sw_to_ub(source.u16_0[i as usize] as u32) as u8; - i += 1 } write_xmm_reg128(r, result); } @@ -2715,8 +2707,7 @@ pub unsafe fn instr_0F74(mut source: reg64, mut r: i32) { let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0 as u32; - while i < 8 as u32 { + for i in 0..8 { result.u8_0[i as usize] = (if destination.i8_0[i as usize] as i32 == source.i8_0[i as usize] as i32 { 255 @@ -2724,7 +2715,6 @@ pub unsafe fn instr_0F74(mut source: reg64, mut r: i32) { else { 0 }) as u8; - i = i.wrapping_add(1) } write_mmx_reg64(r, result); transition_fpu_to_mmx(); @@ -2741,8 +2731,7 @@ pub unsafe fn instr_660F74(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: i32 = 0; - while i < 16 { + for i in 0..16 { result.u8_0[i as usize] = (if source.u8_0[i as usize] as i32 == destination.u8_0[i as usize] as i32 { 255 @@ -2750,7 +2739,6 @@ pub unsafe fn instr_660F74(mut source: reg128, mut r: i32) { else { 0 }) as u8; - i += 1 } write_xmm_reg128(r, result); } @@ -2805,8 +2793,7 @@ pub unsafe fn instr_660F75(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: i32 = 0; - while i < 8 { + for i in 0..8 { result.u16_0[i as usize] = (if source.u16_0[i as usize] as i32 == destination.u16_0[i as usize] as i32 { 65535 @@ -2814,7 +2801,6 @@ pub unsafe fn instr_660F75(mut source: reg128, mut r: i32) { else { 0 }) as u16; - i += 1 } write_xmm_reg128(r, result); } @@ -4133,12 +4119,10 @@ pub unsafe fn instr_0FD8(mut source: reg64, mut r: i32) { let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0 as u32; - while i < 8 as u32 { + for i in 0..8 { result.u8_0[i as usize] = saturate_sd_to_ub(destination.u8_0[i as usize] as i32 - source.u8_0[i as usize] as i32) as u8; - i = i.wrapping_add(1) } write_mmx_reg64(r, result); transition_fpu_to_mmx(); @@ -4154,12 +4138,10 @@ pub unsafe fn instr_660FD8(mut source: reg128, mut r: i32) { // psubusb xmm, xmm/m128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: u32 = 0 as u32; - while i < 16 as u32 { + for i in 0..16 { result.u8_0[i as usize] = saturate_sd_to_ub(destination.u8_0[i as usize] as i32 - source.u8_0[i as usize] as i32) as u8; - i = i.wrapping_add(1) } write_xmm_reg128(r, result); } @@ -4193,12 +4175,10 @@ pub unsafe fn instr_660FD9(mut source: reg128, mut r: i32) { // psubusw xmm, xmm/m128 let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: u32 = 0 as u32; - while i < 8 as u32 { + for i in 0..8 { result.u16_0[i as usize] = saturate_uw( (destination.u16_0[i as usize] as i32 - source.u16_0[i as usize] as i32) as u32, ) as u16; - i = i.wrapping_add(1) } write_xmm_reg128(r, result); } @@ -4213,8 +4193,7 @@ pub unsafe fn instr_0FDA(mut source: reg64, mut r: i32) { // pminub mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; - let mut i: u32 = 0 as u32; - while i < 8 as u32 { + for i in 0..8 { result.u8_0[i as usize] = (if (source.u8_0[i as usize] as i32) < destination.u8_0[i as usize] as i32 { source.u8_0[i as usize] as i32 @@ -4222,7 +4201,6 @@ pub unsafe fn instr_0FDA(mut source: reg64, mut r: i32) { else { destination.u8_0[i as usize] as i32 }) as u8; - i = i.wrapping_add(1) } write_mmx_reg64(r, result); transition_fpu_to_mmx(); @@ -4239,8 +4217,7 @@ pub unsafe fn instr_660FDA(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: u32 = 0 as u32; - while i < 16 as u32 { + for i in 0..16 { result.u8_0[i as usize] = (if (source.u8_0[i as usize] as i32) < destination.u8_0[i as usize] as i32 { source.u8_0[i as usize] as i32 @@ -4248,7 +4225,6 @@ pub unsafe fn instr_660FDA(mut source: reg128, mut r: i32) { else { destination.u8_0[i as usize] as i32 }) as u8; - i = i.wrapping_add(1) } write_xmm_reg128(r, result); } @@ -4294,12 +4270,10 @@ pub unsafe fn instr_0FDC(mut source: reg64, mut r: i32) { let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0 as u32; - while i < 8 as u32 { + for i in 0..8 { result.u8_0[i as usize] = saturate_ud_to_ub( (destination.u8_0[i as usize] as i32 + source.u8_0[i as usize] as i32) as u32, ) as u8; - i = i.wrapping_add(1) } write_mmx_reg64(r, result); transition_fpu_to_mmx(); @@ -4316,12 +4290,10 @@ pub unsafe fn instr_660FDC(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: u32 = 0 as u32; - while i < 16 as u32 { + for i in 0..16 { result.u8_0[i as usize] = saturate_ud_to_ub( (source.u8_0[i as usize] as i32 + destination.u8_0[i as usize] as i32) as u32, ) as u8; - i = i.wrapping_add(1) } write_xmm_reg128(r, result); } @@ -4378,8 +4350,7 @@ pub unsafe fn instr_0FDE(mut source: reg64, mut r: i32) { // pmaxub mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; - let mut i: u32 = 0 as u32; - while i < 8 as u32 { + for i in 0..8 { result.u8_0[i as usize] = (if source.u8_0[i as usize] as i32 > destination.u8_0[i as usize] as i32 { source.u8_0[i as usize] as i32 @@ -4387,7 +4358,6 @@ pub unsafe fn instr_0FDE(mut source: reg64, mut r: i32) { else { destination.u8_0[i as usize] as i32 }) as u8; - i = i.wrapping_add(1) } write_mmx_reg64(r, result); transition_fpu_to_mmx(); @@ -4404,8 +4374,7 @@ pub unsafe fn instr_660FDE(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: u32 = 0 as u32; - while i < 16 as u32 { + for i in 0..16 { result.u8_0[i as usize] = (if source.u8_0[i as usize] as i32 > destination.u8_0[i as usize] as i32 { source.u8_0[i as usize] as i32 @@ -4413,7 +4382,6 @@ pub unsafe fn instr_660FDE(mut source: reg128, mut r: i32) { else { destination.u8_0[i as usize] as i32 }) as u8; - i = i.wrapping_add(1) } write_xmm_reg128(r, result); } @@ -4459,11 +4427,9 @@ pub unsafe fn instr_0FE0(mut source: reg64, mut r: i32) { let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0 as u32; - while i < 8 as u32 { + for i in 0..8 { result.u8_0[i as usize] = (destination.u8_0[i as usize] as i32 + source.u8_0[i as usize] as i32 + 1 >> 1) as u8; - i = i.wrapping_add(1) } write_mmx_reg64(r, result); transition_fpu_to_mmx(); @@ -4480,11 +4446,9 @@ pub unsafe fn instr_660FE0(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: u32 = 0 as u32; - while i < 16 as u32 { + for i in 0..16 { result.u8_0[i as usize] = (destination.u8_0[i as usize] as i32 + source.u8_0[i as usize] as i32 + 1 >> 1) as u8; - i = i.wrapping_add(1) } write_xmm_reg128(r, result); } @@ -4765,12 +4729,10 @@ pub unsafe fn instr_0FE8(mut source: reg64, mut r: i32) { let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0 as u32; - while i < 8 as u32 { + for i in 0..8 { result.u8_0[i as usize] = saturate_sd_to_sb( (destination.i8_0[i as usize] as i32 - source.i8_0[i as usize] as i32) as u32, ) as u8; - i = i.wrapping_add(1) } write_mmx_reg64(r, result); transition_fpu_to_mmx(); @@ -4787,12 +4749,10 @@ pub unsafe fn instr_660FE8(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: u32 = 0 as u32; - while i < 16 as u32 { + for i in 0..16 { result.i8_0[i as usize] = saturate_sd_to_sb( (destination.i8_0[i as usize] as i32 - source.i8_0[i as usize] as i32) as u32, ) as i8; - i = i.wrapping_add(1) } write_xmm_reg128(r, result); } @@ -4859,8 +4819,7 @@ pub unsafe fn instr_0FEA(mut source: reg64, mut r: i32) { // pminsw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; - let mut i: u32 = 0 as u32; - while i < 4 as u32 { + for i in 0..4 { result.i16_0[i as usize] = (if (destination.i16_0[i as usize] as i32) < source.i16_0[i as usize] as i32 { destination.i16_0[i as usize] as i32 @@ -4868,7 +4827,6 @@ pub unsafe fn instr_0FEA(mut source: reg64, mut r: i32) { else { source.i16_0[i as usize] as i32 }) as i16; - i = i.wrapping_add(1) } write_mmx_reg64(r, result); transition_fpu_to_mmx(); @@ -4885,8 +4843,7 @@ pub unsafe fn instr_660FEA(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: u32 = 0 as u32; - while i < 8 as u32 { + for i in 0..8 { result.i16_0[i as usize] = (if (destination.i16_0[i as usize] as i32) < source.i16_0[i as usize] as i32 { destination.i16_0[i as usize] as i32 @@ -4894,7 +4851,6 @@ pub unsafe fn instr_660FEA(mut source: reg128, mut r: i32) { else { source.i16_0[i as usize] as i32 }) as i16; - i = i.wrapping_add(1) } write_xmm_reg128(r, result); } @@ -4940,12 +4896,10 @@ pub unsafe fn instr_0FEC(mut source: reg64, mut r: i32) { let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0 as u32; - while i < 8 as u32 { + for i in 0..8 { result.u8_0[i as usize] = saturate_sd_to_sb( (destination.i8_0[i as usize] as i32 + source.i8_0[i as usize] as i32) as u32, ) as u8; - i = i.wrapping_add(1) } write_mmx_reg64(r, result); transition_fpu_to_mmx(); @@ -4962,12 +4916,10 @@ pub unsafe fn instr_660FEC(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: u32 = 0 as u32; - while i < 16 as u32 { + for i in 0..16 { result.i8_0[i as usize] = saturate_sd_to_sb( (destination.i8_0[i as usize] as i32 + source.i8_0[i as usize] as i32) as u32, ) as i8; - i = i.wrapping_add(1) } write_xmm_reg128(r, result); } @@ -5034,8 +4986,7 @@ pub unsafe fn instr_0FEE(mut source: reg64, mut r: i32) { // pmaxsw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; - let mut i: u32 = 0 as u32; - while i < 4 as u32 { + for i in 0..4 { result.i16_0[i as usize] = (if destination.i16_0[i as usize] as i32 >= source.i16_0[i as usize] as i32 { destination.i16_0[i as usize] as i32 @@ -5043,7 +4994,6 @@ pub unsafe fn instr_0FEE(mut source: reg64, mut r: i32) { else { source.i16_0[i as usize] as i32 }) as i16; - i = i.wrapping_add(1) } write_mmx_reg64(r, result); transition_fpu_to_mmx(); @@ -5060,8 +5010,7 @@ pub unsafe fn instr_660FEE(mut source: reg128, mut r: i32) { // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; - let mut i: u32 = 0 as u32; - while i < 8 as u32 { + for i in 0..8 { result.i16_0[i as usize] = (if destination.i16_0[i as usize] as i32 >= source.i16_0[i as usize] as i32 { destination.i16_0[i as usize] as i32 @@ -5069,7 +5018,6 @@ pub unsafe fn instr_660FEE(mut source: reg128, mut r: i32) { else { source.i16_0[i as usize] as i32 }) as i16; - i = i.wrapping_add(1) } write_xmm_reg128(r, result); } @@ -5253,12 +5201,10 @@ pub unsafe fn instr_0FF6(mut source: reg64, mut r: i32) { // psadbw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); let mut sum: u32 = 0 as u32; - let mut i: u32 = 0 as u32; - while i < 8 as u32 { + for i in 0..8 { sum = (sum as u32).wrapping_add( (destination.u8_0[i as usize] as i32 - source.u8_0[i as usize] as i32).abs() as u32, ) as u32 as u32; - i = i.wrapping_add(1) } write_mmx64(r, sum as i32, 0); transition_fpu_to_mmx(); @@ -5276,17 +5222,14 @@ pub unsafe fn instr_660FF6(mut source: reg128, mut r: i32) { let mut destination: reg128 = read_xmm128s(r); let mut sum0: u32 = 0 as u32; let mut sum1: u32 = 0 as u32; - let mut i: u32 = 0 as u32; - while i < 8 as u32 { + for i in 0..8 { sum0 = (sum0 as u32).wrapping_add( (destination.u8_0[i as usize] as i32 - source.u8_0[i as usize] as i32).abs() as u32, ) as u32 as u32; sum1 = (sum1 as u32).wrapping_add( - (destination.u8_0[i.wrapping_add(8 as u32) as usize] as i32 - - source.u8_0[i.wrapping_add(8 as u32) as usize] as i32) - .abs() as u32, + (destination.u8_0[i + 8 as usize] as i32 - source.u8_0[i + 8 as usize] as i32).abs() + as u32, ) as u32 as u32; - i = i.wrapping_add(1) } write_xmm128(r, sum0 as i32, 0, sum1 as i32, 0); } @@ -5305,15 +5248,13 @@ pub unsafe fn instr_0FF7_reg(mut r1: i32, mut r2: i32) { let mut mask: reg64 = read_mmx64s(r1); let mut addr: i32 = get_seg_prefix(DS) + get_reg_asize(EDI); return_on_pagefault!(writable_or_pagefault(addr, 8)); - let mut i: u32 = 0 as u32; - while i < 8 as u32 { + for i in 0..8 { if 0 != mask.u8_0[i as usize] as i32 & 128 { safe_write8( (addr as u32).wrapping_add(i) as i32, source.u8_0[i as usize] as i32, ).unwrap(); } - i = i.wrapping_add(1) } transition_fpu_to_mmx(); } @@ -5326,15 +5267,13 @@ pub unsafe fn instr_660FF7_reg(mut r1: i32, mut r2: i32) { let mut mask: reg128 = read_xmm128s(r1); let mut addr: i32 = get_seg_prefix(DS) + get_reg_asize(EDI); return_on_pagefault!(writable_or_pagefault(addr, 16)); - let mut i: u32 = 0 as u32; - while i < 16 as u32 { + for i in 0..16 { if 0 != mask.u8_0[i as usize] as i32 & 128 { safe_write8( (addr as u32).wrapping_add(i) as i32, source.u8_0[i as usize] as i32, ).unwrap(); } - i = i.wrapping_add(1) } } #[no_mangle] @@ -5344,11 +5283,9 @@ pub unsafe fn instr_0FF8(mut source: reg64, mut r: i32) { let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0 as u32; - while i < 8 as u32 { + for i in 0..8 { result.u8_0[i as usize] = (destination.i8_0[i as usize] as i32 - source.i8_0[i as usize] as i32 & 255) as u8; - i = i.wrapping_add(1) } write_mmx_reg64(r, result); transition_fpu_to_mmx(); @@ -5367,11 +5304,9 @@ pub unsafe fn instr_660FF8(mut source: reg128, mut r: i32) { let mut result: reg128 = reg128 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0 as u32; - while i < 16 as u32 { + for i in 0..16 { result.i8_0[i as usize] = (destination.i8_0[i as usize] as i32 - source.i8_0[i as usize] as i32 & 255) as i8; - i = i.wrapping_add(1) } write_xmm_reg128(r, result); } @@ -5410,11 +5345,9 @@ pub unsafe fn instr_660FF9(mut source: reg128, mut r: i32) { let mut result: reg128 = reg128 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0 as u32; - while i < 8 as u32 { + for i in 0..8 { result.i16_0[i as usize] = (destination.i16_0[i as usize] as i32 - source.i16_0[i as usize] as i32 & 65535) as i16; - i = i.wrapping_add(1) } write_xmm_reg128(r, result); } @@ -5496,11 +5429,9 @@ pub unsafe fn instr_0FFC(mut source: reg64, mut r: i32) { let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0 as u32; - while i < 8 as u32 { + for i in 0..8 { result.u8_0[i as usize] = (destination.u8_0[i as usize] as i32 + source.u8_0[i as usize] as i32 & 255) as u8; - i = i.wrapping_add(1) } write_mmx_reg64(r, result); transition_fpu_to_mmx(); @@ -5519,11 +5450,9 @@ pub unsafe fn instr_660FFC(mut source: reg128, mut r: i32) { let mut result: reg128 = reg128 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0 as u32; - while i < 16 as u32 { + for i in 0..16 { result.u8_0[i as usize] = (destination.u8_0[i as usize] as i32 + source.u8_0[i as usize] as i32 & 255) as u8; - i = i.wrapping_add(1) } write_xmm_reg128(r, result); } @@ -5560,11 +5489,9 @@ pub unsafe fn instr_660FFD(mut source: reg128, mut r: i32) { let mut result: reg128 = reg128 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - let mut i: u32 = 0 as u32; - while i < 8 as u32 { + for i in 0..8 { result.u16_0[i as usize] = (destination.u16_0[i as usize] as i32 + source.u16_0[i as usize] as i32 & 65535) as u16; - i = i.wrapping_add(1) } write_xmm_reg128(r, result); } diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index d1019368..01c3b746 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -341,8 +341,7 @@ pub unsafe fn fxsave(mut addr: i32) { safe_write32(addr.wrapping_add(24) as i32, *mxcsr).unwrap(); safe_write32(addr.wrapping_add(28) as i32, MXCSR_MASK).unwrap(); - let mut i: i32 = 0; - while i < 8 { + for i in 0..8 { let reg_index = i + *fpu_stack_ptr as i32 & 7; if *fxsave_store_fpu_mask & 1 << reg_index != 0 { fpu_store_m80(addr + 32 + (i << 4), *fpu_st.offset(reg_index as isize)); @@ -354,19 +353,16 @@ pub unsafe fn fxsave(mut addr: i32) { ).unwrap(); safe_write64(addr + 32 + (i << 4) | 8, 0).unwrap(); } - i += 1 } // If the OSFXSR bit in control register CR4 is not set, the FXSAVE // instruction may not save these registers. This behavior is // implementation dependent. - let mut i_0: i32 = 0; - while i_0 < 8 { + for i in 0..8 { safe_write128( - addr.wrapping_add(160).wrapping_add(i_0 << 4) as i32, - *reg_xmm.offset(i_0 as isize), + addr.wrapping_add(160).wrapping_add(i << 4) as i32, + *reg_xmm.offset(i as isize), ).unwrap(); - i_0 += 1 } } #[no_mangle] @@ -391,43 +387,31 @@ pub unsafe fn fxrstor(mut addr: i32) { *fpu_dp_selector = safe_read16(addr.wrapping_add(20) as i32).unwrap(); set_mxcsr(new_mxcsr); - let mut i: i32 = 0; - while i < 8 { + for i in 0..8 { let reg_index = *fpu_stack_ptr as i32 + i & 7; *fpu_st.offset(reg_index as isize) = fpu_load_m80(addr.wrapping_add(32).wrapping_add(i << 4)).unwrap(); *reg_mmx.offset(reg_index as isize) = safe_read64s(addr.wrapping_add(32).wrapping_add(i << 4)).unwrap(); - i += 1 } // Mark values as coming from the fpu: xmm registers fit into x87 registers, but not the // other way around *fxsave_store_fpu_mask = 0xff; - let mut i_0: i32 = 0; - while i_0 < 8 { - (*reg_xmm.offset(i_0 as isize)).u32_0[0] = safe_read32s( - addr.wrapping_add(160) - .wrapping_add(i_0 << 4) - .wrapping_add(0), - ).unwrap() as u32; - (*reg_xmm.offset(i_0 as isize)).u32_0[1] = safe_read32s( - addr.wrapping_add(160) - .wrapping_add(i_0 << 4) - .wrapping_add(4) as i32, - ).unwrap() as u32; - (*reg_xmm.offset(i_0 as isize)).u32_0[2] = safe_read32s( - addr.wrapping_add(160) - .wrapping_add(i_0 << 4) - .wrapping_add(8) as i32, - ).unwrap() as u32; - (*reg_xmm.offset(i_0 as isize)).u32_0[3] = safe_read32s( - addr.wrapping_add(160) - .wrapping_add(i_0 << 4) - .wrapping_add(12) as i32, - ).unwrap() as u32; - i_0 += 1 + for i in 0..8 { + (*reg_xmm.offset(i as isize)).u32_0[0] = + safe_read32s(addr.wrapping_add(160).wrapping_add(i << 4).wrapping_add(0)).unwrap() + as u32; + (*reg_xmm.offset(i as isize)).u32_0[1] = + safe_read32s(addr.wrapping_add(160).wrapping_add(i << 4).wrapping_add(4) as i32) + .unwrap() as u32; + (*reg_xmm.offset(i as isize)).u32_0[2] = + safe_read32s(addr.wrapping_add(160).wrapping_add(i << 4).wrapping_add(8) as i32) + .unwrap() as u32; + (*reg_xmm.offset(i as isize)).u32_0[3] = + safe_read32s(addr.wrapping_add(160).wrapping_add(i << 4).wrapping_add(12) as i32) + .unwrap() as u32; } return; }; From 05ca01c7de7e29b18f69202c5a081c77608380e1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 10 Sep 2018 22:48:44 -0500 Subject: [PATCH 1347/2137] c2rust cleanup: Remove casts on numeric literals --- src/rust/cpu2/arith.rs | 94 ++++++++++++++++---------------- src/rust/cpu2/cpu.rs | 18 +++--- src/rust/cpu2/fpu.rs | 23 ++++---- src/rust/cpu2/instructions.rs | 28 +++++----- src/rust/cpu2/instructions_0f.rs | 78 +++++++++++++------------- src/rust/cpu2/sse_instr.rs | 4 +- src/rust/cpu2/string.rs | 2 +- 7 files changed, 121 insertions(+), 126 deletions(-) diff --git a/src/rust/cpu2/arith.rs b/src/rust/cpu2/arith.rs index a80517c8..31e7158f 100644 --- a/src/rust/cpu2/arith.rs +++ b/src/rust/cpu2/arith.rs @@ -170,9 +170,9 @@ pub unsafe fn mul16(mut source_operand: u32) { let mut high_result: u32 = result >> 16; *reg16.offset(AX as isize) = result as u16; *reg16.offset(DX as isize) = high_result as u16; - *last_result = (result & 65535 as u32) as i32; + *last_result = (result & 65535) as i32; *last_op_size = OPSIZE_16; - if high_result == 0 as u32 { + if high_result == 0 { *flags &= !1 & !FLAG_OVERFLOW } else { @@ -521,8 +521,8 @@ pub unsafe fn rcl32(mut dest_operand: i32, mut count: i32) -> i32 { result = (result as u32 | dest_operand as u32 >> 33 - count) as i32 } *flags_changed &= !1 & !FLAG_OVERFLOW; - *flags = ((*flags & !1 & !FLAG_OVERFLOW) as u32 - | dest_operand as u32 >> 32 - count & 1 as u32) as i32; + *flags = + ((*flags & !1 & !FLAG_OVERFLOW) as u32 | dest_operand as u32 >> 32 - count & 1) as i32; *flags |= (*flags << 11 ^ result >> 20) & FLAG_OVERFLOW; return result; }; @@ -630,7 +630,7 @@ pub unsafe fn rcr32(mut dest_operand: i32, mut count: i32) -> i32 { } #[no_mangle] pub unsafe fn div8(mut source_operand: u32) { - if source_operand == 0 as u32 { + if source_operand == 0 { trigger_de(); return; } @@ -669,7 +669,7 @@ pub unsafe fn idiv8(mut source_operand: i32) { } #[no_mangle] pub unsafe fn div16(mut source_operand: u32) { - if source_operand == 0 as u32 { + if source_operand == 0 { trigger_de(); return; } @@ -677,7 +677,7 @@ pub unsafe fn div16(mut source_operand: u32) { let mut target_operand: u32 = (*reg16.offset(AX as isize) as i32 | (*reg16.offset(DX as isize) as i32) << 16) as u32; let mut result: u32 = target_operand.wrapping_div(source_operand); - if result >= 65536 as u32 { + if result >= 65536 { trigger_de(); } else { @@ -709,7 +709,7 @@ pub unsafe fn idiv16(mut source_operand: i32) { } #[no_mangle] pub unsafe fn div32(mut source_operand: u32) { - if source_operand == 0 as u32 { + if source_operand == 0 { trigger_de(); return; } @@ -718,7 +718,7 @@ pub unsafe fn div32(mut source_operand: u32) { let mut target_high: u32 = *reg32s.offset(EDX as isize) as u32; let mut target_operand: u64 = (target_high as u64) << 32 | target_low as u64; let mut result: u64 = target_operand.wrapping_div(source_operand as u64); - if result > 4294967295 as u64 { + if result > 4294967295 { trigger_de(); return; } @@ -740,13 +740,13 @@ pub unsafe fn idiv32(mut source_operand: i32) { let mut target_low: u32 = *reg32s.offset(EAX as isize) as u32; let mut target_high: u32 = *reg32s.offset(EDX as isize) as u32; let mut target_operand: i64 = ((target_high as u64) << 32 | target_low as u64) as i64; - if source_operand == -1 && target_operand == (-1 as i64 - 9223372036854775807i64) as i64 { + if source_operand == -1 && target_operand == (-1 - 9223372036854775807i64) as i64 { trigger_de(); return; } else { let mut result: i64 = target_operand / source_operand as i64; - if result < (-1 - 2147483647) as i64 || result > 2147483647 as i64 { + if result < (-1 - 2147483647) as i64 || result > 2147483647 { trigger_de(); return; } @@ -851,7 +851,7 @@ pub unsafe fn shr32(mut dest_operand: i32, mut count: i32) -> i32 { *last_op_size = OPSIZE_32; *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; *flags = ((*flags & !1 & !FLAG_OVERFLOW) as u32 - | dest_operand as u32 >> count - 1 & 1 as u32 + | dest_operand as u32 >> count - 1 & 1 | (dest_operand >> 20 & FLAG_OVERFLOW) as u32) as i32; return *last_result; }; @@ -907,8 +907,8 @@ pub unsafe fn sar32(mut dest_operand: i32, mut count: i32) -> i32 { *last_result = dest_operand >> count; *last_op_size = OPSIZE_32; *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; - *flags = ((*flags & !1 & !FLAG_OVERFLOW) as u32 - | dest_operand as u32 >> count - 1 & 1 as u32) as i32; + *flags = + ((*flags & !1 & !FLAG_OVERFLOW) as u32 | dest_operand as u32 >> count - 1 & 1) as i32; return *last_result; }; } @@ -945,7 +945,7 @@ pub unsafe fn shrd32(mut dest_operand: i32, mut source_operand: i32, mut count: (dest_operand as u32 >> count | (source_operand << 32 - count) as u32) as i32; *last_op_size = OPSIZE_32; *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; - *flags = ((*flags & !1) as u32 | dest_operand as u32 >> count - 1 & 1 as u32) as i32; + *flags = ((*flags & !1) as u32 | dest_operand as u32 >> count - 1 & 1) as i32; *flags = *flags & !FLAG_OVERFLOW | (*last_result ^ dest_operand) >> 20 & FLAG_OVERFLOW; return *last_result; }; @@ -960,11 +960,11 @@ pub unsafe fn shld16(mut dest_operand: i32, mut source_operand: i32, mut count: if count <= 16 { *last_result = ((dest_operand << count) as u32 | source_operand as u32 >> 16 - count) as i32; - *flags = ((*flags & !1) as u32 | dest_operand as u32 >> 16 - count & 1 as u32) as i32 + *flags = ((*flags & !1) as u32 | dest_operand as u32 >> 16 - count & 1) as i32 } else { *last_result = dest_operand >> 32 - count | source_operand << count - 16; - *flags = ((*flags & !1) as u32 | source_operand as u32 >> 32 - count & 1 as u32) as i32 + *flags = ((*flags & !1) as u32 | source_operand as u32 >> 32 - count & 1) as i32 } *last_op_size = OPSIZE_16; *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; @@ -983,7 +983,7 @@ pub unsafe fn shld32(mut dest_operand: i32, mut source_operand: i32, mut count: ((dest_operand << count) as u32 | source_operand as u32 >> 32 - count) as i32; *last_op_size = OPSIZE_32; *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; - *flags = ((*flags & !1) as u32 | dest_operand as u32 >> 32 - count & 1 as u32) as i32; + *flags = ((*flags & !1) as u32 | dest_operand as u32 >> 32 - count & 1) as i32; if count == 1 { *flags = *flags & !FLAG_OVERFLOW | (*flags & 1 ^ *last_result >> 31 & 1) << 11 } @@ -1129,20 +1129,20 @@ pub unsafe fn popcnt(mut v: i32) -> i32 { } #[no_mangle] pub unsafe fn saturate_sw_to_ub(mut v: u32) -> u32 { - dbg_assert!(v & 4294901760 == 0 as u32); + dbg_assert!(v & 4294901760 == 0); let mut ret: u32 = v; - if ret >= 32768 as u32 { - ret = 0 as u32 + if ret >= 32768 { + ret = 0 } - else if ret > 255 as u32 { - ret = 255 as u32 + else if ret > 255 { + ret = 255 } - dbg_assert!(ret & 4294967040 == 0 as u32); + dbg_assert!(ret & 4294967040 == 0); return ret; } #[no_mangle] pub unsafe fn saturate_sw_to_sb(mut v: i32) -> i32 { - dbg_assert!(v as u32 & 4294901760 == 0 as u32); + dbg_assert!(v as u32 & 4294901760 == 0); let mut ret: i32 = v; if ret > 65408 { ret = ret & 255 @@ -1153,37 +1153,37 @@ pub unsafe fn saturate_sw_to_sb(mut v: i32) -> i32 { else if ret > 127 { ret = 127 } - dbg_assert!(ret as u32 & 4294967040 == 0 as u32); + dbg_assert!(ret as u32 & 4294967040 == 0); return ret; } #[no_mangle] pub unsafe fn saturate_sd_to_sw(mut v: u32) -> u32 { let mut ret: u32 = v; if ret > 4294934528 { - ret = ret & 65535 as u32 + ret = ret & 65535 } - else if ret > 2147483647 as u32 { - ret = 32768 as u32 + else if ret > 2147483647 { + ret = 32768 } - else if ret > 32767 as u32 { - ret = 32767 as u32 + else if ret > 32767 { + ret = 32767 } - dbg_assert!(ret & 4294901760 == 0 as u32); + dbg_assert!(ret & 4294901760 == 0); return ret; } #[no_mangle] pub unsafe fn saturate_sd_to_sb(mut v: u32) -> u32 { let mut ret: u32 = v; if ret > 4294967168 { - ret = ret & 255 as u32 + ret = ret & 255 } - else if ret > 2147483647 as u32 { - ret = 128 as u32 + else if ret > 2147483647 { + ret = 128 } - else if ret > 127 as u32 { - ret = 127 as u32 + else if ret > 127 { + ret = 127 } - dbg_assert!(ret & 4294967040 == 0 as u32); + dbg_assert!(ret & 4294967040 == 0); return ret; } #[no_mangle] @@ -1192,27 +1192,27 @@ pub unsafe fn saturate_sd_to_ub(mut v: i32) -> i32 { if ret < 0 { ret = 0 } - dbg_assert!(ret as u32 & 4294967040 == 0 as u32); + dbg_assert!(ret as u32 & 4294967040 == 0); return ret; } #[no_mangle] pub unsafe fn saturate_ud_to_ub(mut v: u32) -> u32 { let mut ret: u32 = v; - if ret > 255 as u32 { - ret = 255 as u32 + if ret > 255 { + ret = 255 } - dbg_assert!(ret & 4294967040 == 0 as u32); + dbg_assert!(ret & 4294967040 == 0); return ret; } #[no_mangle] pub unsafe fn saturate_uw(mut v: u32) -> i32 { let mut ret: u32 = v; - if ret > 2147483647 as u32 { - ret = 0 as u32 + if ret > 2147483647 { + ret = 0 } - else if ret > 65535 as u32 { - ret = 65535 as u32 + else if ret > 65535 { + ret = 65535 } - dbg_assert!(ret & 4294901760 == 0 as u32); + dbg_assert!(ret & 4294901760 == 0); return ret as i32; } diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 13ea3601..f2614638 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -241,9 +241,9 @@ pub const TSC_RATE: f64 = (50 * 1000) as f64; pub static mut jit_block_boundary: bool = 0 != 0; pub static mut must_not_fault: bool = 0 != 0; -pub static mut rdtsc_imprecision_offset: u64 = 0 as u64; -pub static mut rdtsc_last_value: u64 = 0 as u64; -pub static mut tsc_offset: u64 = 0 as u64; +pub static mut rdtsc_imprecision_offset: u64 = 0; +pub static mut rdtsc_last_value: u64 = 0; +pub static mut tsc_offset: u64 = 0; pub static mut valid_tlb_entries: [i32; 10000] = [0; 10000]; pub static mut valid_tlb_entries_count: i32 = 0; @@ -694,7 +694,7 @@ pub unsafe fn read_imm16() -> OrPageFault { // Two checks in one comparison: // 1. Did the high 20 bits of eip change // or 2. Are the low 12 bits of eip 0xFFF (and this read crosses a page boundary) - if (*instruction_pointer ^ *last_virt_eip) as u32 > 4094 as u32 { + if (*instruction_pointer ^ *last_virt_eip) as u32 > 4094 { return Ok(read_imm8()? | read_imm8()? << 8); } else { @@ -706,7 +706,7 @@ pub unsafe fn read_imm16() -> OrPageFault { pub unsafe fn read_imm32s() -> OrPageFault { // Analogue to the above comment - if (*instruction_pointer ^ *last_virt_eip) as u32 > 4092 as u32 { + if (*instruction_pointer ^ *last_virt_eip) as u32 > 4092 { return Ok(read_imm16()? | read_imm16()? << 16); } else { @@ -1064,7 +1064,7 @@ pub unsafe fn cycle_internal() { if 0 != entry { profiler::stat_increment(S_RUN_FROM_CACHE); let initial_tsc = *timestamp_counter as i32; - let wasm_table_index = (entry & 65535 as u32) as u16; + let wasm_table_index = (entry & 65535) as u16; let initial_state = (entry >> 16) as u16; call_indirect1( (wasm_table_index as u32).wrapping_add(WASM_TABLE_OFFSET as u32) as i32, @@ -1176,13 +1176,13 @@ pub unsafe fn run_prefix_instruction() { run_instruction(return_on_pagefault!(read_imm8()) | (is_osize_32() as i32) << 8); } -pub unsafe fn clear_prefixes() { *prefixes = 0 as u8; } +pub unsafe fn clear_prefixes() { *prefixes = 0 } pub unsafe fn segment_prefix_op(mut seg: i32) { dbg_assert!(seg <= 5); *prefixes = (*prefixes as i32 | seg + 1) as u8; run_prefix_instruction(); - *prefixes = 0 as u8; + *prefixes = 0 } #[no_mangle] @@ -1907,7 +1907,7 @@ pub unsafe fn read_tsc() -> u64 { let mut previous_value: u64 = rdtsc_last_value.wrapping_add(rdtsc_imprecision_offset); if previous_value <= value { rdtsc_last_value = value; - rdtsc_imprecision_offset = 0 as u64 + rdtsc_imprecision_offset = 0 } else { dbg_log!( diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 7a482c66..ae1a5801 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -93,7 +93,7 @@ pub unsafe fn fpu_stack_fault() { #[no_mangle] pub unsafe fn fpu_get_sti(mut i: i32) -> f64 { dbg_assert!(i >= 0 && i < 8); - i = ((i as u32).wrapping_add(*fpu_stack_ptr) & 7 as u32) as i32; + i = ((i as u32).wrapping_add(*fpu_stack_ptr) & 7) as i32; if 0 != *fpu_stack_empty >> i & 1 { *fpu_status_word &= !FPU_C1; fpu_stack_fault(); @@ -116,7 +116,7 @@ pub unsafe fn fpu_integer_round(mut f: f64) -> f64 { } return rounded; } - else if rc == 1 || rc == 3 && f > 0 as f64 { + else if rc == 1 || rc == 3 && f > 0.0 { // rc=3 is truncate -> floor for positive numbers return floor(f); } @@ -281,7 +281,7 @@ pub unsafe fn fpu_fcomip(mut r: i32) { #[no_mangle] pub unsafe fn fpu_pop() { *fpu_stack_empty |= 1 << *fpu_stack_ptr; - *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_add(1 as u32) & 7 as u32; + *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_add(1) & 7; } #[no_mangle] pub unsafe fn fpu_fcomp(mut val: f64) { @@ -310,7 +310,7 @@ pub unsafe fn fpu_fildm64(mut addr: i32) { } #[no_mangle] pub unsafe fn fpu_push(mut x: f64) { - *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_sub(1 as u32) & 7 as u32; + *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_sub(1) & 7; if 0 != *fpu_stack_empty >> *fpu_stack_ptr & 1 { *fpu_status_word &= !FPU_C1; *fpu_stack_empty &= !(1 << *fpu_stack_ptr); @@ -330,12 +330,12 @@ pub unsafe fn fpu_finit() { *fpu_dp = 0; *fpu_opcode = 0; *fpu_stack_empty = 255; - *fpu_stack_ptr = 0 as u32; + *fpu_stack_ptr = 0; } #[no_mangle] pub unsafe fn fpu_fistm16(mut addr: i32) { let mut st0: f64 = fpu_integer_round(fpu_get_st0()); - if st0 <= 32767 as f64 && st0 >= -32768 as f64 { + if st0 <= 32767.0 && st0 >= -32768.0 { return_on_pagefault!(safe_write16(addr, st0 as i32)); } else { @@ -564,7 +564,7 @@ pub unsafe fn fpu_load_tag_word() -> i32 { if 0 != *fpu_stack_empty >> i & 1 { tag_word |= 3 << (i << 1) } - else if value == 0 as f64 { + else if value == 0.0 { tag_word |= 1 << (i << 1) } else if !value.is_finite() { @@ -634,10 +634,10 @@ pub unsafe fn fpu_ftst(mut x: f64) { if x.is_nan() { *fpu_status_word |= FPU_C3 | FPU_C2 | FPU_C0 } - else if x == 0 as f64 { + else if x == 0.0 { *fpu_status_word |= FPU_C3 } - else if x < 0 as f64 { + else if x < 0.0 { *fpu_status_word |= FPU_C0 } // TODO: unordered (x is nan, etc) @@ -678,7 +678,7 @@ pub unsafe fn fpu_fxam(mut x: f64) { else if x.is_nan() { *fpu_status_word |= FPU_C0 } - else if x == 0 as f64 { + else if x == 0.0 { *fpu_status_word |= FPU_C3 } else if x == ::std::f32::INFINITY as f64 || x == -::std::f32::INFINITY as f64 { @@ -693,8 +693,7 @@ pub unsafe fn fpu_fxam(mut x: f64) { #[no_mangle] pub unsafe fn fpu_sign(mut i: i32) -> i32 { // sign of a number on the stack - return *fpu_st8 - .offset((((*fpu_stack_ptr).wrapping_add(i as u32) & 7 as u32) << 3 | 7 as u32) as isize) + return *fpu_st8.offset((((*fpu_stack_ptr).wrapping_add(i as u32) & 7) << 3 | 7) as isize) as i32 >> 7; } diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index 585c0f1f..58ea4c83 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -915,7 +915,7 @@ pub unsafe fn instr_66() { // Operand-size override prefix *prefixes = (*prefixes as i32 | PREFIX_MASK_OPSIZE) as u8; run_prefix_instruction(); - *prefixes = 0 as u8; + *prefixes = 0; } #[no_mangle] pub unsafe fn instr_67() { @@ -923,7 +923,7 @@ pub unsafe fn instr_67() { dbg_assert!(is_asize_32() as i32 == *is_32 as i32); *prefixes = (*prefixes as i32 | PREFIX_MASK_ADDRSIZE) as u8; run_prefix_instruction(); - *prefixes = 0 as u8; + *prefixes = 0; } #[no_mangle] pub unsafe fn instr16_68(mut imm16: i32) { @@ -1551,7 +1551,7 @@ pub unsafe fn instr16_8D_mem(modrm_byte: i32, mut r: i32) { if let Ok(addr) = modrm_resolve(modrm_byte) { write_reg16(r, addr); } - *prefixes = 0 as u8; + *prefixes = 0; } #[no_mangle] pub unsafe fn instr32_8D_reg(mut r: i32, mut r2: i32) { @@ -1566,7 +1566,7 @@ pub unsafe fn instr32_8D_mem(modrm_byte: i32, mut r: i32) { if let Ok(addr) = modrm_resolve(modrm_byte) { write_reg32(r, addr); } - *prefixes = 0 as u8; + *prefixes = 0; } #[no_mangle] pub unsafe fn instr_8E_helper(mut data: i32, mut mod_0: i32) { @@ -2931,7 +2931,7 @@ pub unsafe fn instr_F2() { dbg_assert!(*prefixes as i32 & PREFIX_MASK_REP == 0); *prefixes = (*prefixes as i32 | PREFIX_REPNZ) as u8; run_prefix_instruction(); - *prefixes = 0 as u8; + *prefixes = 0; } #[no_mangle] pub unsafe fn instr_F3() { @@ -2939,7 +2939,7 @@ pub unsafe fn instr_F3() { dbg_assert!(*prefixes as i32 & PREFIX_MASK_REP == 0); *prefixes = (*prefixes as i32 | PREFIX_REPZ) as u8; run_prefix_instruction(); - *prefixes = 0 as u8; + *prefixes = 0; } #[no_mangle] pub unsafe fn instr_F4() { hlt_op(); } @@ -3755,7 +3755,7 @@ pub unsafe fn instr_D9_5_reg(mut r: i32) { // fld1/fldl2t/fldl2e/fldpi/fldlg2/fldln2/fldz match r { 0 => { - fpu_push(1 as f64); + fpu_push(1.0); }, 1 => { fpu_push(M_LN10 / M_LN2); @@ -3773,7 +3773,7 @@ pub unsafe fn instr_D9_5_reg(mut r: i32) { fpu_push(M_LN2); }, 6 => { - fpu_push(0 as f64); + fpu_push(0.0); }, 7 => { dbg_log!("d9/5/7"); @@ -3790,7 +3790,7 @@ pub unsafe fn instr_D9_6_reg(mut r: i32) { match r { 0 => { // f2xm1 - fpu_write_st(*fpu_stack_ptr as i32, pow(2 as f64, st0) - 1 as f64) + fpu_write_st(*fpu_stack_ptr as i32, pow(2.0, st0) - 1.0) }, 1 => { // fyl2x @@ -3804,7 +3804,7 @@ pub unsafe fn instr_D9_6_reg(mut r: i32) { // fptan fpu_write_st(*fpu_stack_ptr as i32, st0.tan()); // no bug: push constant 1 - fpu_push(1 as f64); + fpu_push(1.0); }, 3 => { // fpatan @@ -3820,12 +3820,12 @@ pub unsafe fn instr_D9_6_reg(mut r: i32) { }, 6 => { // fdecstp - *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_sub(1 as u32) & 7 as u32; + *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_sub(1) & 7; *fpu_status_word &= !FPU_C1 }, 7 => { // fincstp - *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_add(1 as u32) & 7 as u32; + *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_add(1) & 7; *fpu_status_word &= !FPU_C1 }, _ => { @@ -3844,7 +3844,7 @@ pub unsafe fn instr_D9_7_reg(mut r: i32) { }, 1 => { // fyl2xp1: y * log2(x+1) and pop - let y = fpu_get_sti(1) * (st0 + 1 as f64).ln() / M_LN2; + let y = fpu_get_sti(1) * (st0 + 1.0).ln() / M_LN2; fpu_write_st(*fpu_stack_ptr as i32 + 1 & 7, y); fpu_pop(); }, @@ -3859,7 +3859,7 @@ pub unsafe fn instr_D9_7_reg(mut r: i32) { }, 5 => { // fscale - let y = st0 * pow(2 as f64, trunc(fpu_get_sti(1))); + let y = st0 * pow(2.0, trunc(fpu_get_sti(1))); fpu_write_st(*fpu_stack_ptr as i32, y); }, 6 => fpu_write_st(*fpu_stack_ptr as i32, st0.sin()), diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index d54e272d..942e755f 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -1290,7 +1290,7 @@ pub unsafe fn instr_0F34() { *segment_limits.offset(CS as isize) = -1i32 as u32; *segment_offsets.offset(CS as isize) = 0; update_cs_size(true); - *cpl = 0 as u8; + *cpl = 0; cpl_changed(); *sreg.offset(SS as isize) = (seg + 8) as u16; *segment_is_null.offset(SS as isize) = 0 != 0; @@ -1316,7 +1316,7 @@ pub unsafe fn instr_0F35() { *segment_limits.offset(CS as isize) = -1i32 as u32; *segment_offsets.offset(CS as isize) = 0; update_cs_size(true); - *cpl = 3 as u8; + *cpl = 3; cpl_changed(); *sreg.offset(SS as isize) = (seg + 24 | 3) as u16; *segment_is_null.offset(SS as isize) = 0 != 0; @@ -2447,16 +2447,15 @@ pub unsafe fn instr_0F70(mut source: reg64, mut r: i32, mut imm8: i32) { // pshufw mm1, mm2/m64, imm8 let mut word0_shift: i32 = imm8 & 3; let mut word0: u32 = - source.u32_0[(word0_shift >> 1) as usize] >> ((word0_shift & 1) << 4) & 65535 as u32; + source.u32_0[(word0_shift >> 1) as usize] >> ((word0_shift & 1) << 4) & 65535; let mut word1_shift: i32 = imm8 >> 2 & 3; let mut word1: u32 = source.u32_0[(word1_shift >> 1) as usize] >> ((word1_shift & 1) << 4); let mut low: i32 = (word0 | word1 << 16) as i32; let mut word2_shift: i32 = imm8 >> 4 & 3; let mut word2: u32 = - source.u32_0[(word2_shift >> 1) as usize] >> ((word2_shift & 1) << 4) & 65535 as u32; + source.u32_0[(word2_shift >> 1) as usize] >> ((word2_shift & 1) << 4) & 65535; let mut word3_shift: u32 = (imm8 >> 6) as u32; - let mut word3: u32 = - source.u32_0[(word3_shift >> 1) as usize] >> ((word3_shift & 1 as u32) << 4); + let mut word3: u32 = source.u32_0[(word3_shift >> 1) as usize] >> ((word3_shift & 1) << 4); let mut high: i32 = (word2 | word3 << 16) as i32; write_mmx64(r, low, high); transition_fpu_to_mmx(); @@ -2657,14 +2656,13 @@ pub unsafe fn instr_660F73_3_reg(mut r: i32, mut imm8: i32) { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; let mut shift: u32 = (if imm8 > 15 { 128 } else { imm8 << 3 }) as u32; - if shift <= 63 as u32 { - result.u64_0[0] = destination.u64_0[0] >> shift - | destination.u64_0[1] << (64 as u32).wrapping_sub(shift); + if shift <= 63 { + result.u64_0[0] = destination.u64_0[0] >> shift | destination.u64_0[1] << (64 - shift); result.u64_0[1] = destination.u64_0[1] >> shift } - else if shift <= 127 as u32 { - result.u64_0[0] = destination.u64_0[1] >> shift.wrapping_sub(64 as u32); - result.u64_0[1] = 0 as u64 + else if shift <= 127 { + result.u64_0[0] = destination.u64_0[1] >> shift.wrapping_sub(64); + result.u64_0[1] = 0 } write_xmm_reg128(r, result); return; @@ -2687,14 +2685,13 @@ pub unsafe fn instr_660F73_7_reg(mut r: i32, mut imm8: i32) { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; let mut shift: u32 = (if imm8 > 15 { 128 } else { imm8 << 3 }) as u32; - if shift <= 63 as u32 { + if shift <= 63 { result.u64_0[0] = destination.u64_0[0] << shift; - result.u64_0[1] = destination.u64_0[1] << shift - | destination.u64_0[0] >> (64 as u32).wrapping_sub(shift) + result.u64_0[1] = destination.u64_0[1] << shift | destination.u64_0[0] >> (64 - shift) } - else if shift <= 127 as u32 { - result.u64_0[0] = 0 as u64; - result.u64_0[1] = destination.u64_0[0] << shift.wrapping_sub(64 as u32) + else if shift <= 127 { + result.u64_0[0] = 0; + result.u64_0[1] = destination.u64_0[0] << shift.wrapping_sub(64) } write_xmm_reg128(r, result); return; @@ -5200,7 +5197,7 @@ pub unsafe fn instr_660FF5_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0FF6(mut source: reg64, mut r: i32) { // psadbw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - let mut sum: u32 = 0 as u32; + let mut sum: u32 = 0; for i in 0..8 { sum = (sum as u32).wrapping_add( (destination.u8_0[i as usize] as i32 - source.u8_0[i as usize] as i32).abs() as u32, @@ -5220,16 +5217,15 @@ pub unsafe fn instr_660FF6(mut source: reg128, mut r: i32) { // psadbw xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); - let mut sum0: u32 = 0 as u32; - let mut sum1: u32 = 0 as u32; + let mut sum0: u32 = 0; + let mut sum1: u32 = 0; for i in 0..8 { sum0 = (sum0 as u32).wrapping_add( (destination.u8_0[i as usize] as i32 - source.u8_0[i as usize] as i32).abs() as u32, ) as u32 as u32; - sum1 = (sum1 as u32).wrapping_add( - (destination.u8_0[i + 8 as usize] as i32 - source.u8_0[i + 8 as usize] as i32).abs() - as u32, - ) as u32 as u32; + sum1 = (sum1 as u32) + .wrapping_add((destination.u8_0[i + 8] as i32 - source.u8_0[i + 8] as i32).abs() as u32) + as u32 as u32; } write_xmm128(r, sum0 as i32, 0, sum1 as i32, 0); } @@ -5320,13 +5316,13 @@ pub unsafe fn instr_660FF8_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0FF9(mut source: reg64, mut r: i32) { // psubw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - let mut word0: i32 = (destination.u32_0[0].wrapping_sub(source.u32_0[0]) & 65535 as u32) as i32; + let mut word0: i32 = (destination.u32_0[0].wrapping_sub(source.u32_0[0]) & 65535) as i32; let mut word1: i32 = - ((destination.u16_0[1] as u32).wrapping_sub(source.u16_0[1] as u32) & 65535 as u32) as i32; + ((destination.u16_0[1] as u32).wrapping_sub(source.u16_0[1] as u32) & 65535) as i32; let mut low: i32 = word0 | word1 << 16; - let mut word2: i32 = (destination.u32_0[1].wrapping_sub(source.u32_0[1]) & 65535 as u32) as i32; + let mut word2: i32 = (destination.u32_0[1].wrapping_sub(source.u32_0[1]) & 65535) as i32; let mut word3: i32 = - ((destination.u16_0[3] as u32).wrapping_sub(source.u16_0[3] as u32) & 65535 as u32) as i32; + ((destination.u16_0[3] as u32).wrapping_sub(source.u16_0[3] as u32) & 65535) as i32; let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); transition_fpu_to_mmx(); @@ -5466,10 +5462,10 @@ pub unsafe fn instr_660FFC_mem(mut addr: i32, mut r: i32) { pub unsafe fn instr_0FFD(mut source: reg64, mut r: i32) { // paddw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); - let mut word0: i32 = (destination.u32_0[0].wrapping_add(source.u32_0[0]) & 65535 as u32) as i32; + let mut word0: i32 = (destination.u32_0[0].wrapping_add(source.u32_0[0]) & 65535) as i32; let mut word1: i32 = destination.u16_0[1] as i32 + source.u16_0[1] as i32 & 65535; let mut low: i32 = word0 | word1 << 16; - let mut word2: i32 = (destination.u32_0[1].wrapping_add(source.u32_0[1]) & 65535 as u32) as i32; + let mut word2: i32 = (destination.u32_0[1].wrapping_add(source.u32_0[1]) & 65535) as i32; let mut word3: i32 = destination.u16_0[3] as i32 + source.u16_0[3] as i32 & 65535; let mut high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); @@ -5745,10 +5741,10 @@ pub unsafe fn instr_0F52(mut source: reg128, mut r: i32) { // rcpps xmm1, xmm2/m128 let mut result: reg128 = reg128 { f32_0: [ - 1 as f32 / source.f32_0[0].sqrt(), - 1 as f32 / source.f32_0[1].sqrt(), - 1 as f32 / source.f32_0[2].sqrt(), - 1 as f32 / source.f32_0[3].sqrt(), + 1.0 / source.f32_0[0].sqrt(), + 1.0 / source.f32_0[1].sqrt(), + 1.0 / source.f32_0[2].sqrt(), + 1.0 / source.f32_0[3].sqrt(), ], }; write_xmm_reg128(r, result); @@ -5762,7 +5758,7 @@ pub unsafe fn instr_0F52_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_F30F52(mut source: f32, mut r: i32) { // rsqrtss xmm1, xmm2/m32 - write_xmm_f32(r, 1 as f32 / source.sqrt()); + write_xmm_f32(r, 1.0 / source.sqrt()); } #[no_mangle] pub unsafe fn instr_F30F52_reg(mut r1: i32, mut r2: i32) { instr_F30F52(read_xmm_f32(r1), r2); } @@ -5776,10 +5772,10 @@ pub unsafe fn instr_0F53(mut source: reg128, mut r: i32) { // rcpps xmm, xmm/m128 let mut result: reg128 = reg128 { f32_0: [ - 1 as f32 / source.f32_0[0], - 1 as f32 / source.f32_0[1], - 1 as f32 / source.f32_0[2], - 1 as f32 / source.f32_0[3], + 1.0 / source.f32_0[0], + 1.0 / source.f32_0[1], + 1.0 / source.f32_0[2], + 1.0 / source.f32_0[3], ], }; write_xmm_reg128(r, result); @@ -5793,7 +5789,7 @@ pub unsafe fn instr_0F53_mem(mut addr: i32, mut r: i32) { #[no_mangle] pub unsafe fn instr_F30F53(mut source: f32, mut r: i32) { // rcpss xmm, xmm/m32 - write_xmm_f32(r, 1 as f32 / source); + write_xmm_f32(r, 1.0 / source); } #[no_mangle] pub unsafe fn instr_F30F53_reg(mut r1: i32, mut r2: i32) { instr_F30F53(read_xmm_f32(r1), r2); } diff --git a/src/rust/cpu2/sse_instr.rs b/src/rust/cpu2/sse_instr.rs index c6d55517..f9127982 100644 --- a/src/rust/cpu2/sse_instr.rs +++ b/src/rust/cpu2/sse_instr.rs @@ -233,7 +233,7 @@ pub unsafe fn psrlw_r128(mut r: i32, mut shift: u64) { pub unsafe fn psraw_r128(mut r: i32, mut shift: u64) { // psraw xmm, {shift} let mut destination: reg128 = read_xmm128s(r); - let mut shift_clamped: i32 = (if shift > 15 { 16 as u32 } else { shift as u32 }) as i32; + let mut shift_clamped: i32 = (if shift > 15 { 16 } else { shift as u32 }) as i32; let mut dword0: i32 = destination.i16_0[0] as i32 >> shift_clamped & 65535 | destination.i16_0[1] as i32 >> shift_clamped << 16; let mut dword1: i32 = destination.i16_0[2] as i32 >> shift_clamped & 65535 @@ -389,7 +389,7 @@ pub unsafe fn sse_convert_f32_to_i32(mut x: f32) -> i32 { #[no_mangle] pub unsafe fn sse_convert_f64_to_i32(mut x: f64) -> i32 { // TODO: Rounding modes - if x >= -2147483648.0 as f64 && x < 2147483648.0 as f64 { + if x >= -2147483648.0 && x < 2147483648.0 { return x as i64 as i32; } else { diff --git a/src/rust/cpu2/string.rs b/src/rust/cpu2/string.rs index a110bfef..03d1a313 100644 --- a/src/rust/cpu2/string.rs +++ b/src/rust/cpu2/string.rs @@ -752,7 +752,7 @@ pub unsafe fn lodsw_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; let mut count: u32 = get_reg_asize(ECX) as u32; - if count == 0 as u32 { + if count == 0 { return; } else { From 435608d9f06571812b48dec2f7854335f44497eb Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 10 Sep 2018 23:21:23 -0500 Subject: [PATCH 1348/2137] c2rust cleanup: Remove unused mut --- src/rust/cpu2/arith.rs | 366 ++-- src/rust/cpu2/cpu.rs | 324 ++-- src/rust/cpu2/fpu.rs | 162 +- src/rust/cpu2/global_pointers.rs | 2 +- src/rust/cpu2/instructions.rs | 2150 ++++++++++---------- src/rust/cpu2/instructions_0f.rs | 3127 +++++++++++++++--------------- src/rust/cpu2/memory.rs | 22 +- src/rust/cpu2/misc_instr.rs | 132 +- src/rust/cpu2/modrm.rs | 26 +- src/rust/cpu2/sse_instr.rs | 152 +- src/rust/cpu2/string.rs | 360 ++-- 11 files changed, 3367 insertions(+), 3456 deletions(-) diff --git a/src/rust/cpu2/arith.rs b/src/rust/cpu2/arith.rs index 31e7158f..7c498171 100644 --- a/src/rust/cpu2/arith.rs +++ b/src/rust/cpu2/arith.rs @@ -1,5 +1,3 @@ -#![allow(unused_mut)] - use cpu2::cpu::*; use cpu2::global_pointers::*; use cpu2::memory::{read8, write8}; @@ -8,10 +6,10 @@ use cpu2::misc_instr::{getaf, getcf}; pub fn int_log2(x: i32) -> i32 { 31 - x.leading_zeros() as i32 } #[no_mangle] -pub unsafe fn add(mut dest_operand: i32, mut source_operand: i32, mut op_size: i32) -> i32 { +pub unsafe fn add(dest_operand: i32, source_operand: i32, op_size: i32) -> i32 { *last_op1 = dest_operand; *last_op2 = source_operand; - let mut res: i32 = dest_operand + source_operand; + let res: i32 = dest_operand + source_operand; *last_result = res; *last_add_result = *last_result; *last_op_size = op_size; @@ -19,11 +17,11 @@ pub unsafe fn add(mut dest_operand: i32, mut source_operand: i32, mut op_size: i return res; } #[no_mangle] -pub unsafe fn adc(mut dest_operand: i32, mut source_operand: i32, mut op_size: i32) -> i32 { - let mut cf: i32 = getcf() as i32; +pub unsafe fn adc(dest_operand: i32, source_operand: i32, op_size: i32) -> i32 { + let cf: i32 = getcf() as i32; *last_op1 = dest_operand; *last_op2 = source_operand; - let mut res: i32 = dest_operand + source_operand + cf; + let res: i32 = dest_operand + source_operand + cf; *last_result = res; *last_add_result = *last_result; *last_op_size = op_size; @@ -31,10 +29,10 @@ pub unsafe fn adc(mut dest_operand: i32, mut source_operand: i32, mut op_size: i return res; } #[no_mangle] -pub unsafe fn sub(mut dest_operand: i32, mut source_operand: i32, mut op_size: i32) -> i32 { +pub unsafe fn sub(dest_operand: i32, source_operand: i32, op_size: i32) -> i32 { *last_add_result = dest_operand; *last_op2 = source_operand; - let mut res: i32 = dest_operand - source_operand; + let res: i32 = dest_operand - source_operand; *last_result = res; *last_op1 = *last_result; *last_op_size = op_size; @@ -42,11 +40,11 @@ pub unsafe fn sub(mut dest_operand: i32, mut source_operand: i32, mut op_size: i return res; } #[no_mangle] -pub unsafe fn sbb(mut dest_operand: i32, mut source_operand: i32, mut op_size: i32) -> i32 { - let mut cf: i32 = getcf() as i32; +pub unsafe fn sbb(dest_operand: i32, source_operand: i32, op_size: i32) -> i32 { + let cf: i32 = getcf() as i32; *last_add_result = dest_operand; *last_op2 = source_operand; - let mut res: i32 = dest_operand - source_operand - cf; + let res: i32 = dest_operand - source_operand - cf; *last_result = res; *last_op1 = *last_result; *last_op_size = op_size; @@ -54,41 +52,41 @@ pub unsafe fn sbb(mut dest_operand: i32, mut source_operand: i32, mut op_size: i return res; } #[no_mangle] -pub unsafe fn add8(mut x: i32, mut y: i32) -> i32 { return add(x, y, OPSIZE_8); } +pub unsafe fn add8(x: i32, y: i32) -> i32 { return add(x, y, OPSIZE_8); } #[no_mangle] -pub unsafe fn add16(mut x: i32, mut y: i32) -> i32 { return add(x, y, OPSIZE_16); } +pub unsafe fn add16(x: i32, y: i32) -> i32 { return add(x, y, OPSIZE_16); } #[no_mangle] -pub unsafe fn add32(mut x: i32, mut y: i32) -> i32 { return add(x, y, OPSIZE_32); } +pub unsafe fn add32(x: i32, y: i32) -> i32 { return add(x, y, OPSIZE_32); } #[no_mangle] -pub unsafe fn sub8(mut x: i32, mut y: i32) -> i32 { return sub(x, y, OPSIZE_8); } +pub unsafe fn sub8(x: i32, y: i32) -> i32 { return sub(x, y, OPSIZE_8); } #[no_mangle] -pub unsafe fn sub16(mut x: i32, mut y: i32) -> i32 { return sub(x, y, OPSIZE_16); } +pub unsafe fn sub16(x: i32, y: i32) -> i32 { return sub(x, y, OPSIZE_16); } #[no_mangle] -pub unsafe fn sub32(mut x: i32, mut y: i32) -> i32 { return sub(x, y, OPSIZE_32); } +pub unsafe fn sub32(x: i32, y: i32) -> i32 { return sub(x, y, OPSIZE_32); } #[no_mangle] -pub unsafe fn adc8(mut x: i32, mut y: i32) -> i32 { return adc(x, y, OPSIZE_8); } +pub unsafe fn adc8(x: i32, y: i32) -> i32 { return adc(x, y, OPSIZE_8); } #[no_mangle] -pub unsafe fn adc16(mut x: i32, mut y: i32) -> i32 { return adc(x, y, OPSIZE_16); } +pub unsafe fn adc16(x: i32, y: i32) -> i32 { return adc(x, y, OPSIZE_16); } #[no_mangle] -pub unsafe fn adc32(mut x: i32, mut y: i32) -> i32 { return adc(x, y, OPSIZE_32); } +pub unsafe fn adc32(x: i32, y: i32) -> i32 { return adc(x, y, OPSIZE_32); } #[no_mangle] -pub unsafe fn sbb8(mut x: i32, mut y: i32) -> i32 { return sbb(x, y, OPSIZE_8); } +pub unsafe fn sbb8(x: i32, y: i32) -> i32 { return sbb(x, y, OPSIZE_8); } #[no_mangle] -pub unsafe fn sbb16(mut x: i32, mut y: i32) -> i32 { return sbb(x, y, OPSIZE_16); } +pub unsafe fn sbb16(x: i32, y: i32) -> i32 { return sbb(x, y, OPSIZE_16); } #[no_mangle] -pub unsafe fn sbb32(mut x: i32, mut y: i32) -> i32 { return sbb(x, y, OPSIZE_32); } +pub unsafe fn sbb32(x: i32, y: i32) -> i32 { return sbb(x, y, OPSIZE_32); } #[no_mangle] -pub unsafe fn cmp8(mut x: i32, mut y: i32) { sub(x, y, OPSIZE_8); } +pub unsafe fn cmp8(x: i32, y: i32) { sub(x, y, OPSIZE_8); } #[no_mangle] -pub unsafe fn cmp16(mut x: i32, mut y: i32) { sub(x, y, OPSIZE_16); } +pub unsafe fn cmp16(x: i32, y: i32) { sub(x, y, OPSIZE_16); } #[no_mangle] -pub unsafe fn cmp32(mut x: i32, mut y: i32) { sub(x, y, OPSIZE_32); } +pub unsafe fn cmp32(x: i32, y: i32) { sub(x, y, OPSIZE_32); } #[no_mangle] -pub unsafe fn inc(mut dest_operand: i32, mut op_size: i32) -> i32 { +pub unsafe fn inc(dest_operand: i32, op_size: i32) -> i32 { *flags = *flags & !1 | getcf() as i32; *last_op1 = dest_operand; *last_op2 = 1; - let mut res: i32 = dest_operand + 1; + let res: i32 = dest_operand + 1; *last_result = res; *last_add_result = *last_result; *last_op_size = op_size; @@ -96,11 +94,11 @@ pub unsafe fn inc(mut dest_operand: i32, mut op_size: i32) -> i32 { return res; } #[no_mangle] -pub unsafe fn dec(mut dest_operand: i32, mut op_size: i32) -> i32 { +pub unsafe fn dec(dest_operand: i32, op_size: i32) -> i32 { *flags = *flags & !1 | getcf() as i32; *last_add_result = dest_operand; *last_op2 = 1; - let mut res: i32 = dest_operand - 1; + let res: i32 = dest_operand - 1; *last_result = res; *last_op1 = *last_result; *last_op_size = op_size; @@ -108,20 +106,20 @@ pub unsafe fn dec(mut dest_operand: i32, mut op_size: i32) -> i32 { return res; } #[no_mangle] -pub unsafe fn inc8(mut x: i32) -> i32 { return inc(x, OPSIZE_8); } +pub unsafe fn inc8(x: i32) -> i32 { return inc(x, OPSIZE_8); } #[no_mangle] -pub unsafe fn inc16(mut x: i32) -> i32 { return inc(x, OPSIZE_16); } +pub unsafe fn inc16(x: i32) -> i32 { return inc(x, OPSIZE_16); } #[no_mangle] -pub unsafe fn inc32(mut x: i32) -> i32 { return inc(x, OPSIZE_32); } +pub unsafe fn inc32(x: i32) -> i32 { return inc(x, OPSIZE_32); } #[no_mangle] -pub unsafe fn dec8(mut x: i32) -> i32 { return dec(x, OPSIZE_8); } +pub unsafe fn dec8(x: i32) -> i32 { return dec(x, OPSIZE_8); } #[no_mangle] -pub unsafe fn dec16(mut x: i32) -> i32 { return dec(x, OPSIZE_16); } +pub unsafe fn dec16(x: i32) -> i32 { return dec(x, OPSIZE_16); } #[no_mangle] -pub unsafe fn dec32(mut x: i32) -> i32 { return dec(x, OPSIZE_32); } +pub unsafe fn dec32(x: i32) -> i32 { return dec(x, OPSIZE_32); } #[no_mangle] -pub unsafe fn neg(mut dest_operand: i32, mut op_size: i32) -> i32 { - let mut res: i32 = -dest_operand; +pub unsafe fn neg(dest_operand: i32, op_size: i32) -> i32 { + let res: i32 = -dest_operand; *last_result = res; *last_op1 = *last_result; *flags_changed = FLAGS_ALL; @@ -131,14 +129,14 @@ pub unsafe fn neg(mut dest_operand: i32, mut op_size: i32) -> i32 { return res; } #[no_mangle] -pub unsafe fn neg8(mut x: i32) -> i32 { return neg(x, OPSIZE_8); } +pub unsafe fn neg8(x: i32) -> i32 { return neg(x, OPSIZE_8); } #[no_mangle] -pub unsafe fn neg16(mut x: i32) -> i32 { return neg(x, OPSIZE_16); } +pub unsafe fn neg16(x: i32) -> i32 { return neg(x, OPSIZE_16); } #[no_mangle] -pub unsafe fn neg32(mut x: i32) -> i32 { return neg(x, OPSIZE_32); } +pub unsafe fn neg32(x: i32) -> i32 { return neg(x, OPSIZE_32); } #[no_mangle] -pub unsafe fn mul8(mut source_operand: i32) { - let mut result: i32 = source_operand * *reg8.offset(AL as isize) as i32; +pub unsafe fn mul8(source_operand: i32) { + let result: i32 = source_operand * *reg8.offset(AL as isize) as i32; *reg16.offset(AX as isize) = result as u16; *last_result = result & 255; *last_op_size = OPSIZE_8; @@ -151,8 +149,8 @@ pub unsafe fn mul8(mut source_operand: i32) { *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; } #[no_mangle] -pub unsafe fn imul8(mut source_operand: i32) { - let mut result: i32 = source_operand * *reg8s.offset(AL as isize) as i32; +pub unsafe fn imul8(source_operand: i32) { + let result: i32 = source_operand * *reg8s.offset(AL as isize) as i32; *reg16.offset(AX as isize) = result as u16; *last_result = result & 255; *last_op_size = OPSIZE_8; @@ -165,9 +163,9 @@ pub unsafe fn imul8(mut source_operand: i32) { *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; } #[no_mangle] -pub unsafe fn mul16(mut source_operand: u32) { - let mut result: u32 = source_operand.wrapping_mul(*reg16.offset(AX as isize) as u32); - let mut high_result: u32 = result >> 16; +pub unsafe fn mul16(source_operand: u32) { + let result: u32 = source_operand.wrapping_mul(*reg16.offset(AX as isize) as u32); + let high_result: u32 = result >> 16; *reg16.offset(AX as isize) = result as u16; *reg16.offset(DX as isize) = high_result as u16; *last_result = (result & 65535) as i32; @@ -181,8 +179,8 @@ pub unsafe fn mul16(mut source_operand: u32) { *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; } #[no_mangle] -pub unsafe fn imul16(mut source_operand: i32) { - let mut result: i32 = source_operand * *reg16s.offset(AX as isize) as i32; +pub unsafe fn imul16(source_operand: i32) { + let result: i32 = source_operand * *reg16s.offset(AX as isize) as i32; *reg16.offset(AX as isize) = result as u16; *reg16.offset(DX as isize) = (result >> 16) as u16; *last_result = result & 65535; @@ -199,7 +197,7 @@ pub unsafe fn imul16(mut source_operand: i32) { pub unsafe fn imul_reg16(mut operand1: i32, mut operand2: i32) -> i32 { operand1 = operand1 << 16 >> 16; operand2 = operand2 << 16 >> 16; - let mut result: i32 = operand1 * operand2; + let result: i32 = operand1 * operand2; *last_result = result & 65535; *last_op_size = OPSIZE_16; if result > 32767 || result < -32768 { @@ -212,11 +210,11 @@ pub unsafe fn imul_reg16(mut operand1: i32, mut operand2: i32) -> i32 { return result; } #[no_mangle] -pub unsafe fn mul32(mut source_operand: i32) { - let mut dest_operand: i32 = *reg32s.offset(EAX as isize); - let mut result: u64 = (dest_operand as u32 as u64).wrapping_mul(source_operand as u32 as u64); - let mut result_low: i32 = result as i32; - let mut result_high: i32 = (result >> 32) as i32; +pub unsafe fn mul32(source_operand: i32) { + let dest_operand: i32 = *reg32s.offset(EAX as isize); + let result: u64 = (dest_operand as u32 as u64).wrapping_mul(source_operand as u32 as u64); + let result_low: i32 = result as i32; + let result_high: i32 = (result >> 32) as i32; *reg32s.offset(EAX as isize) = result_low; *reg32s.offset(EDX as isize) = result_high; *last_result = result_low; @@ -230,11 +228,11 @@ pub unsafe fn mul32(mut source_operand: i32) { *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; } #[no_mangle] -pub unsafe fn imul32(mut source_operand: i32) { - let mut dest_operand: i32 = *reg32s.offset(EAX as isize); - let mut result: i64 = dest_operand as i64 * source_operand as i64; - let mut result_low: i32 = result as i32; - let mut result_high: i32 = (result >> 32) as i32; +pub unsafe fn imul32(source_operand: i32) { + let dest_operand: i32 = *reg32s.offset(EAX as isize); + let result: i64 = dest_operand as i64 * source_operand as i64; + let result_low: i32 = result as i32; + let result_high: i32 = (result >> 32) as i32; *reg32s.offset(EAX as isize) = result_low; *reg32s.offset(EDX as isize) = result_high; *last_result = result_low; @@ -248,10 +246,10 @@ pub unsafe fn imul32(mut source_operand: i32) { *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; } #[no_mangle] -pub unsafe fn imul_reg32(mut operand1: i32, mut operand2: i32) -> i32 { - let mut result: i64 = operand1 as i64 * operand2 as i64; - let mut result_low: i32 = result as i32; - let mut result_high: i32 = (result >> 32) as i32; +pub unsafe fn imul_reg32(operand1: i32, operand2: i32) -> i32 { + let result: i64 = operand1 as i64 * operand2 as i64; + let result_low: i32 = result as i32; + let result_high: i32 = (result >> 32) as i32; *last_result = result_low; *last_op_size = OPSIZE_32; if result_high == result_low >> 31 { @@ -264,28 +262,28 @@ pub unsafe fn imul_reg32(mut operand1: i32, mut operand2: i32) -> i32 { return result_low; } #[no_mangle] -pub unsafe fn xadd8(mut source_operand: i32, mut reg: i32) -> i32 { - let mut tmp: i32 = *reg8.offset(reg as isize) as i32; +pub unsafe fn xadd8(source_operand: i32, reg: i32) -> i32 { + let tmp: i32 = *reg8.offset(reg as isize) as i32; *reg8.offset(reg as isize) = source_operand as u8; return add(source_operand, tmp, OPSIZE_8); } #[no_mangle] -pub unsafe fn xadd16(mut source_operand: i32, mut reg: i32) -> i32 { - let mut tmp: i32 = *reg16.offset(reg as isize) as i32; +pub unsafe fn xadd16(source_operand: i32, reg: i32) -> i32 { + let tmp: i32 = *reg16.offset(reg as isize) as i32; *reg16.offset(reg as isize) = source_operand as u16; return add(source_operand, tmp, OPSIZE_16); } #[no_mangle] -pub unsafe fn xadd32(mut source_operand: i32, mut reg: i32) -> i32 { - let mut tmp: i32 = *reg32s.offset(reg as isize); +pub unsafe fn xadd32(source_operand: i32, reg: i32) -> i32 { + let tmp: i32 = *reg32s.offset(reg as isize); *reg32s.offset(reg as isize) = source_operand; return add(source_operand, tmp, OPSIZE_32); } #[no_mangle] pub unsafe fn bcd_daa() { - let mut old_al: i32 = *reg8.offset(AL as isize) as i32; - let mut old_cf: i32 = getcf() as i32; - let mut old_af: i32 = getaf() as i32; + let old_al: i32 = *reg8.offset(AL as isize) as i32; + let old_cf: i32 = getcf() as i32; + let old_af: i32 = getaf() as i32; *flags &= !1 & !FLAG_ADJUST; if old_al & 15 > 9 || 0 != old_af { *reg8.offset(AL as isize) += 6; @@ -303,8 +301,8 @@ pub unsafe fn bcd_daa() { } #[no_mangle] pub unsafe fn bcd_das() { - let mut old_al: i32 = *reg8.offset(AL as isize) as i32; - let mut old_cf: i32 = getcf() as i32; + let old_al: i32 = *reg8.offset(AL as isize) as i32; + let old_cf: i32 = getcf() as i32; *flags &= !1; if old_al & 15 > 9 || 0 != getaf() as i32 { *reg8.offset(AL as isize) -= 6; @@ -325,9 +323,8 @@ pub unsafe fn bcd_das() { *flags_changed = FLAGS_ALL & !1 & !FLAG_ADJUST & !FLAG_OVERFLOW; } #[no_mangle] -pub unsafe fn bcd_aad(mut imm8: i32) { - let mut result: i32 = - *reg8.offset(AL as isize) as i32 + *reg8.offset(AH as isize) as i32 * imm8; +pub unsafe fn bcd_aad(imm8: i32) { + let result: i32 = *reg8.offset(AL as isize) as i32 + *reg8.offset(AH as isize) as i32 * imm8; *last_result = result & 255; *reg16.offset(AX as isize) = *last_result as u16; *last_op_size = OPSIZE_8; @@ -338,13 +335,13 @@ pub unsafe fn bcd_aad(mut imm8: i32) { }; } #[no_mangle] -pub unsafe fn bcd_aam(mut imm8: i32) { +pub unsafe fn bcd_aam(imm8: i32) { // ascii adjust after multiplication if imm8 == 0 { trigger_de(); } else { - let mut temp: u8 = *reg8.offset(AL as isize); + let temp: u8 = *reg8.offset(AL as isize); *reg8.offset(AH as isize) = (temp as i32 / imm8) as u8; *reg8.offset(AL as isize) = (temp as i32 % imm8) as u8; *last_result = *reg8.offset(AL as isize) as i32; @@ -379,7 +376,7 @@ pub unsafe fn bcd_aas() { *flags_changed &= !FLAG_ADJUST & !1; } #[no_mangle] -pub unsafe fn and(mut dest_operand: i32, mut source_operand: i32, mut op_size: i32) -> i32 { +pub unsafe fn and(dest_operand: i32, source_operand: i32, op_size: i32) -> i32 { *last_result = dest_operand & source_operand; *last_op_size = op_size; *flags &= !1 & !FLAG_OVERFLOW & !FLAG_ADJUST; @@ -387,7 +384,7 @@ pub unsafe fn and(mut dest_operand: i32, mut source_operand: i32, mut op_size: i return *last_result; } #[no_mangle] -pub unsafe fn or(mut dest_operand: i32, mut source_operand: i32, mut op_size: i32) -> i32 { +pub unsafe fn or(dest_operand: i32, source_operand: i32, op_size: i32) -> i32 { *last_result = dest_operand | source_operand; *last_op_size = op_size; *flags &= !1 & !FLAG_OVERFLOW & !FLAG_ADJUST; @@ -395,7 +392,7 @@ pub unsafe fn or(mut dest_operand: i32, mut source_operand: i32, mut op_size: i3 return *last_result; } #[no_mangle] -pub unsafe fn xor(mut dest_operand: i32, mut source_operand: i32, mut op_size: i32) -> i32 { +pub unsafe fn xor(dest_operand: i32, source_operand: i32, op_size: i32) -> i32 { *last_result = dest_operand ^ source_operand; *last_op_size = op_size; *flags &= !1 & !FLAG_OVERFLOW & !FLAG_ADJUST; @@ -403,39 +400,39 @@ pub unsafe fn xor(mut dest_operand: i32, mut source_operand: i32, mut op_size: i return *last_result; } #[no_mangle] -pub unsafe fn and8(mut x: i32, mut y: i32) -> i32 { return and(x, y, OPSIZE_8); } +pub unsafe fn and8(x: i32, y: i32) -> i32 { return and(x, y, OPSIZE_8); } #[no_mangle] -pub unsafe fn and16(mut x: i32, mut y: i32) -> i32 { return and(x, y, OPSIZE_16); } +pub unsafe fn and16(x: i32, y: i32) -> i32 { return and(x, y, OPSIZE_16); } #[no_mangle] -pub unsafe fn and32(mut x: i32, mut y: i32) -> i32 { return and(x, y, OPSIZE_32); } +pub unsafe fn and32(x: i32, y: i32) -> i32 { return and(x, y, OPSIZE_32); } #[no_mangle] -pub unsafe fn test8(mut x: i32, mut y: i32) { and(x, y, OPSIZE_8); } +pub unsafe fn test8(x: i32, y: i32) { and(x, y, OPSIZE_8); } #[no_mangle] -pub unsafe fn test16(mut x: i32, mut y: i32) { and(x, y, OPSIZE_16); } +pub unsafe fn test16(x: i32, y: i32) { and(x, y, OPSIZE_16); } #[no_mangle] -pub unsafe fn test32(mut x: i32, mut y: i32) { and(x, y, OPSIZE_32); } +pub unsafe fn test32(x: i32, y: i32) { and(x, y, OPSIZE_32); } #[no_mangle] -pub unsafe fn or8(mut x: i32, mut y: i32) -> i32 { return or(x, y, OPSIZE_8); } +pub unsafe fn or8(x: i32, y: i32) -> i32 { return or(x, y, OPSIZE_8); } #[no_mangle] -pub unsafe fn or16(mut x: i32, mut y: i32) -> i32 { return or(x, y, OPSIZE_16); } +pub unsafe fn or16(x: i32, y: i32) -> i32 { return or(x, y, OPSIZE_16); } #[no_mangle] -pub unsafe fn or32(mut x: i32, mut y: i32) -> i32 { return or(x, y, OPSIZE_32); } +pub unsafe fn or32(x: i32, y: i32) -> i32 { return or(x, y, OPSIZE_32); } #[no_mangle] -pub unsafe fn xor8(mut x: i32, mut y: i32) -> i32 { return xor(x, y, OPSIZE_8); } +pub unsafe fn xor8(x: i32, y: i32) -> i32 { return xor(x, y, OPSIZE_8); } #[no_mangle] -pub unsafe fn xor16(mut x: i32, mut y: i32) -> i32 { return xor(x, y, OPSIZE_16); } +pub unsafe fn xor16(x: i32, y: i32) -> i32 { return xor(x, y, OPSIZE_16); } #[no_mangle] -pub unsafe fn xor32(mut x: i32, mut y: i32) -> i32 { return xor(x, y, OPSIZE_32); } +pub unsafe fn xor32(x: i32, y: i32) -> i32 { return xor(x, y, OPSIZE_32); } #[no_mangle] -pub unsafe fn rol8(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn rol8(dest_operand: i32, mut count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); if 0 == count { return dest_operand; } else { count &= 7; - let mut result: i32 = dest_operand << count | dest_operand >> 8 - count; + let result: i32 = dest_operand << count | dest_operand >> 8 - count; *flags_changed &= !1 & !FLAG_OVERFLOW; *flags = *flags & !1 & !FLAG_OVERFLOW | result & 1 @@ -444,14 +441,14 @@ pub unsafe fn rol8(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn rol16(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn rol16(dest_operand: i32, mut count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); if 0 == count { return dest_operand; } else { count &= 15; - let mut result: i32 = dest_operand << count | dest_operand >> 16 - count; + let result: i32 = dest_operand << count | dest_operand >> 16 - count; *flags_changed &= !1 & !FLAG_OVERFLOW; *flags = *flags & !1 & !FLAG_OVERFLOW | result & 1 @@ -460,13 +457,13 @@ pub unsafe fn rol16(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn rol32(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn rol32(dest_operand: i32, count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); if 0 == count { return dest_operand; } else { - let mut result: i32 = + let result: i32 = ((dest_operand << count) as u32 | dest_operand as u32 >> 32 - count) as i32; *flags_changed &= !1 & !FLAG_OVERFLOW; *flags = *flags & !1 & !FLAG_OVERFLOW @@ -476,14 +473,14 @@ pub unsafe fn rol32(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn rcl8(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn rcl8(dest_operand: i32, mut count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); count %= 9; if 0 == count { return dest_operand; } else { - let mut result: i32 = + let result: i32 = dest_operand << count | (getcf() as i32) << count - 1 | dest_operand >> 9 - count; *flags_changed &= !1 & !FLAG_OVERFLOW; *flags = *flags & !1 & !FLAG_OVERFLOW @@ -493,14 +490,14 @@ pub unsafe fn rcl8(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn rcl16(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn rcl16(dest_operand: i32, mut count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); count %= 17; if 0 == count { return dest_operand; } else { - let mut result: i32 = + let result: i32 = dest_operand << count | (getcf() as i32) << count - 1 | dest_operand >> 17 - count; *flags_changed &= !1 & !FLAG_OVERFLOW; *flags = *flags & !1 & !FLAG_OVERFLOW @@ -510,7 +507,7 @@ pub unsafe fn rcl16(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn rcl32(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn rcl32(dest_operand: i32, count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); if 0 == count { return dest_operand; @@ -528,14 +525,14 @@ pub unsafe fn rcl32(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn ror8(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn ror8(dest_operand: i32, mut count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); if 0 == count { return dest_operand; } else { count &= 7; - let mut result: i32 = dest_operand >> count | dest_operand << 8 - count; + let result: i32 = dest_operand >> count | dest_operand << 8 - count; *flags_changed &= !1 & !FLAG_OVERFLOW; *flags = *flags & !1 & !FLAG_OVERFLOW | result >> 7 & 1 @@ -544,14 +541,14 @@ pub unsafe fn ror8(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn ror16(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn ror16(dest_operand: i32, mut count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); if 0 == count { return dest_operand; } else { count &= 15; - let mut result: i32 = dest_operand >> count | dest_operand << 16 - count; + let result: i32 = dest_operand >> count | dest_operand << 16 - count; *flags_changed &= !1 & !FLAG_OVERFLOW; *flags = *flags & !1 & !FLAG_OVERFLOW | result >> 15 & 1 @@ -560,13 +557,13 @@ pub unsafe fn ror16(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn ror32(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn ror32(dest_operand: i32, count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); if 0 == count { return dest_operand; } else { - let mut result: i32 = + let result: i32 = (dest_operand as u32 >> count | (dest_operand << 32 - count) as u32) as i32; *flags_changed &= !1 & !FLAG_OVERFLOW; *flags = *flags & !1 & !FLAG_OVERFLOW @@ -576,14 +573,14 @@ pub unsafe fn ror32(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn rcr8(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn rcr8(dest_operand: i32, mut count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); count %= 9; if 0 == count { return dest_operand; } else { - let mut result: i32 = + let result: i32 = dest_operand >> count | (getcf() as i32) << 8 - count | dest_operand << 9 - count; *flags_changed &= !1 & !FLAG_OVERFLOW; *flags = *flags & !1 & !FLAG_OVERFLOW @@ -593,14 +590,14 @@ pub unsafe fn rcr8(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn rcr16(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn rcr16(dest_operand: i32, mut count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); count %= 17; if 0 == count { return dest_operand; } else { - let mut result: i32 = + let result: i32 = dest_operand >> count | (getcf() as i32) << 16 - count | dest_operand << 17 - count; *flags_changed &= !1 & !FLAG_OVERFLOW; *flags = *flags & !1 & !FLAG_OVERFLOW @@ -610,7 +607,7 @@ pub unsafe fn rcr16(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn rcr32(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn rcr32(dest_operand: i32, count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); if 0 == count { return dest_operand; @@ -629,14 +626,14 @@ pub unsafe fn rcr32(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn div8(mut source_operand: u32) { +pub unsafe fn div8(source_operand: u32) { if source_operand == 0 { trigger_de(); return; } else { - let mut target_operand: u16 = *reg16.offset(AX as isize); - let mut result: u16 = (target_operand as u32).wrapping_div(source_operand) as u16; + let target_operand: u16 = *reg16.offset(AX as isize); + let result: u16 = (target_operand as u32).wrapping_div(source_operand) as u16; if result as i32 >= 256 { trigger_de(); } @@ -649,14 +646,14 @@ pub unsafe fn div8(mut source_operand: u32) { } #[no_mangle] -pub unsafe fn idiv8(mut source_operand: i32) { +pub unsafe fn idiv8(source_operand: i32) { if source_operand == 0 { trigger_de(); return; } else { - let mut target_operand: i32 = *reg16s.offset(AX as isize) as i32; - let mut result: i32 = target_operand / source_operand; + let target_operand: i32 = *reg16s.offset(AX as isize) as i32; + let result: i32 = target_operand / source_operand; if result >= 128 || result <= -129 { trigger_de(); } @@ -668,15 +665,15 @@ pub unsafe fn idiv8(mut source_operand: i32) { }; } #[no_mangle] -pub unsafe fn div16(mut source_operand: u32) { +pub unsafe fn div16(source_operand: u32) { if source_operand == 0 { trigger_de(); return; } else { - let mut target_operand: u32 = + let target_operand: u32 = (*reg16.offset(AX as isize) as i32 | (*reg16.offset(DX as isize) as i32) << 16) as u32; - let mut result: u32 = target_operand.wrapping_div(source_operand); + let result: u32 = target_operand.wrapping_div(source_operand); if result >= 65536 { trigger_de(); } @@ -688,15 +685,15 @@ pub unsafe fn div16(mut source_operand: u32) { }; } #[no_mangle] -pub unsafe fn idiv16(mut source_operand: i32) { +pub unsafe fn idiv16(source_operand: i32) { if source_operand == 0 { trigger_de(); return; } else { - let mut target_operand: i32 = + let target_operand: i32 = *reg16.offset(AX as isize) as i32 | (*reg16.offset(DX as isize) as i32) << 16; - let mut result: i32 = target_operand / source_operand; + let result: i32 = target_operand / source_operand; if result >= 32768 || result <= -32769 { trigger_de(); } @@ -708,22 +705,22 @@ pub unsafe fn idiv16(mut source_operand: i32) { }; } #[no_mangle] -pub unsafe fn div32(mut source_operand: u32) { +pub unsafe fn div32(source_operand: u32) { if source_operand == 0 { trigger_de(); return; } else { - let mut target_low: u32 = *reg32s.offset(EAX as isize) as u32; - let mut target_high: u32 = *reg32s.offset(EDX as isize) as u32; - let mut target_operand: u64 = (target_high as u64) << 32 | target_low as u64; - let mut result: u64 = target_operand.wrapping_div(source_operand as u64); + let target_low: u32 = *reg32s.offset(EAX as isize) as u32; + let target_high: u32 = *reg32s.offset(EDX as isize) as u32; + let target_operand: u64 = (target_high as u64) << 32 | target_low as u64; + let result: u64 = target_operand.wrapping_div(source_operand as u64); if result > 4294967295 { trigger_de(); return; } else { - let mut mod_0: i32 = target_operand.wrapping_rem(source_operand as u64) as i32; + let mod_0: i32 = target_operand.wrapping_rem(source_operand as u64) as i32; *reg32s.offset(EAX as isize) = result as i32; *reg32s.offset(EDX as isize) = mod_0; return; @@ -731,27 +728,27 @@ pub unsafe fn div32(mut source_operand: u32) { }; } #[no_mangle] -pub unsafe fn idiv32(mut source_operand: i32) { +pub unsafe fn idiv32(source_operand: i32) { if source_operand == 0 { trigger_de(); return; } else { - let mut target_low: u32 = *reg32s.offset(EAX as isize) as u32; - let mut target_high: u32 = *reg32s.offset(EDX as isize) as u32; - let mut target_operand: i64 = ((target_high as u64) << 32 | target_low as u64) as i64; + let target_low: u32 = *reg32s.offset(EAX as isize) as u32; + let target_high: u32 = *reg32s.offset(EDX as isize) as u32; + let target_operand: i64 = ((target_high as u64) << 32 | target_low as u64) as i64; if source_operand == -1 && target_operand == (-1 - 9223372036854775807i64) as i64 { trigger_de(); return; } else { - let mut result: i64 = target_operand / source_operand as i64; + let result: i64 = target_operand / source_operand as i64; if result < (-1 - 2147483647) as i64 || result > 2147483647 { trigger_de(); return; } else { - let mut mod_0: i32 = (target_operand % source_operand as i64) as i32; + let mod_0: i32 = (target_operand % source_operand as i64) as i32; *reg32s.offset(EAX as isize) = result as i32; *reg32s.offset(EDX as isize) = mod_0; return; @@ -761,7 +758,7 @@ pub unsafe fn idiv32(mut source_operand: i32) { } #[no_mangle] -pub unsafe fn shl8(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn shl8(dest_operand: i32, count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; @@ -777,7 +774,7 @@ pub unsafe fn shl8(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn shl16(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn shl16(dest_operand: i32, count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; @@ -793,7 +790,7 @@ pub unsafe fn shl16(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn shl32(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn shl32(dest_operand: i32, count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; @@ -809,7 +806,7 @@ pub unsafe fn shl32(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn shr8(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn shr8(dest_operand: i32, count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; @@ -825,7 +822,7 @@ pub unsafe fn shr8(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn shr16(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn shr16(dest_operand: i32, count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; @@ -841,7 +838,7 @@ pub unsafe fn shr16(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn shr32(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn shr32(dest_operand: i32, count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; @@ -857,7 +854,7 @@ pub unsafe fn shr32(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn sar8(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn sar8(dest_operand: i32, count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; @@ -878,7 +875,7 @@ pub unsafe fn sar8(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn sar16(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn sar16(dest_operand: i32, count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; @@ -898,7 +895,7 @@ pub unsafe fn sar16(mut dest_operand: i32, mut count: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn sar32(mut dest_operand: i32, mut count: i32) -> i32 { +pub unsafe fn sar32(dest_operand: i32, count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; @@ -914,7 +911,7 @@ pub unsafe fn sar32(mut dest_operand: i32, mut count: i32) -> i32 { } #[no_mangle] -pub unsafe fn shrd16(mut dest_operand: i32, mut source_operand: i32, mut count: i32) -> i32 { +pub unsafe fn shrd16(dest_operand: i32, source_operand: i32, count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; @@ -935,7 +932,7 @@ pub unsafe fn shrd16(mut dest_operand: i32, mut source_operand: i32, mut count: }; } #[no_mangle] -pub unsafe fn shrd32(mut dest_operand: i32, mut source_operand: i32, mut count: i32) -> i32 { +pub unsafe fn shrd32(dest_operand: i32, source_operand: i32, count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; @@ -951,7 +948,7 @@ pub unsafe fn shrd32(mut dest_operand: i32, mut source_operand: i32, mut count: }; } #[no_mangle] -pub unsafe fn shld16(mut dest_operand: i32, mut source_operand: i32, mut count: i32) -> i32 { +pub unsafe fn shld16(dest_operand: i32, source_operand: i32, count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; @@ -973,7 +970,7 @@ pub unsafe fn shld16(mut dest_operand: i32, mut source_operand: i32, mut count: }; } #[no_mangle] -pub unsafe fn shld32(mut dest_operand: i32, mut source_operand: i32, mut count: i32) -> i32 { +pub unsafe fn shld32(dest_operand: i32, source_operand: i32, count: i32) -> i32 { dbg_assert!(count >= 0 && count < 32); if count == 0 { return dest_operand; @@ -995,67 +992,64 @@ pub unsafe fn shld32(mut dest_operand: i32, mut source_operand: i32, mut count: } #[no_mangle] -pub unsafe fn bt_reg(mut bit_base: i32, mut bit_offset: i32) { +pub unsafe fn bt_reg(bit_base: i32, bit_offset: i32) { *flags = *flags & !1 | bit_base >> bit_offset & 1; *flags_changed &= !1; } #[no_mangle] -pub unsafe fn btc_reg(mut bit_base: i32, mut bit_offset: i32) -> i32 { +pub unsafe fn btc_reg(bit_base: i32, bit_offset: i32) -> i32 { *flags = *flags & !1 | bit_base >> bit_offset & 1; *flags_changed &= !1; return bit_base ^ 1 << bit_offset; } #[no_mangle] -pub unsafe fn bts_reg(mut bit_base: i32, mut bit_offset: i32) -> i32 { +pub unsafe fn bts_reg(bit_base: i32, bit_offset: i32) -> i32 { *flags = *flags & !1 | bit_base >> bit_offset & 1; *flags_changed &= !1; return bit_base | 1 << bit_offset; } #[no_mangle] -pub unsafe fn btr_reg(mut bit_base: i32, mut bit_offset: i32) -> i32 { +pub unsafe fn btr_reg(bit_base: i32, bit_offset: i32) -> i32 { *flags = *flags & !1 | bit_base >> bit_offset & 1; *flags_changed &= !1; return bit_base & !(1 << bit_offset); } #[no_mangle] -pub unsafe fn bt_mem(mut virt_addr: i32, mut bit_offset: i32) { - let mut bit_base: i32 = return_on_pagefault!(safe_read8(virt_addr + (bit_offset >> 3))); +pub unsafe fn bt_mem(virt_addr: i32, mut bit_offset: i32) { + let bit_base: i32 = return_on_pagefault!(safe_read8(virt_addr + (bit_offset >> 3))); bit_offset &= 7; *flags = *flags & !1 | bit_base >> bit_offset & 1; *flags_changed &= !1; } #[no_mangle] -pub unsafe fn btc_mem(mut virt_addr: i32, mut bit_offset: i32) { - let mut phys_addr = - return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3))); - let mut bit_base: i32 = read8(phys_addr); +pub unsafe fn btc_mem(virt_addr: i32, mut bit_offset: i32) { + let phys_addr = return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3))); + let bit_base: i32 = read8(phys_addr); bit_offset &= 7; *flags = *flags & !1 | bit_base >> bit_offset & 1; *flags_changed &= !1; write8(phys_addr, bit_base ^ 1 << bit_offset); } #[no_mangle] -pub unsafe fn btr_mem(mut virt_addr: i32, mut bit_offset: i32) { - let mut phys_addr = - return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3))); - let mut bit_base: i32 = read8(phys_addr); +pub unsafe fn btr_mem(virt_addr: i32, mut bit_offset: i32) { + let phys_addr = return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3))); + let bit_base: i32 = read8(phys_addr); bit_offset &= 7; *flags = *flags & !1 | bit_base >> bit_offset & 1; *flags_changed &= !1; write8(phys_addr, bit_base & !(1 << bit_offset)); } #[no_mangle] -pub unsafe fn bts_mem(mut virt_addr: i32, mut bit_offset: i32) { - let mut phys_addr = - return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3))); - let mut bit_base: i32 = read8(phys_addr); +pub unsafe fn bts_mem(virt_addr: i32, mut bit_offset: i32) { + let phys_addr = return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3))); + let bit_base: i32 = read8(phys_addr); bit_offset &= 7; *flags = *flags & !1 | bit_base >> bit_offset & 1; *flags_changed &= !1; write8(phys_addr, bit_base | 1 << bit_offset); } #[no_mangle] -pub unsafe fn bsf16(mut old: i32, mut bit_base: i32) -> i32 { +pub unsafe fn bsf16(old: i32, bit_base: i32) -> i32 { *flags_changed = FLAGS_ALL & !FLAG_ZERO; *last_op_size = OPSIZE_16; if bit_base == 0 { @@ -1071,7 +1065,7 @@ pub unsafe fn bsf16(mut old: i32, mut bit_base: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn bsf32(mut old: i32, mut bit_base: i32) -> i32 { +pub unsafe fn bsf32(old: i32, bit_base: i32) -> i32 { *flags_changed = FLAGS_ALL & !FLAG_ZERO; *last_op_size = OPSIZE_32; if bit_base == 0 { @@ -1086,7 +1080,7 @@ pub unsafe fn bsf32(mut old: i32, mut bit_base: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn bsr16(mut old: i32, mut bit_base: i32) -> i32 { +pub unsafe fn bsr16(old: i32, bit_base: i32) -> i32 { *flags_changed = FLAGS_ALL & !FLAG_ZERO; *last_op_size = OPSIZE_16; if bit_base == 0 { @@ -1101,7 +1095,7 @@ pub unsafe fn bsr16(mut old: i32, mut bit_base: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn bsr32(mut old: i32, mut bit_base: i32) -> i32 { +pub unsafe fn bsr32(old: i32, bit_base: i32) -> i32 { *flags_changed = FLAGS_ALL & !FLAG_ZERO; *last_op_size = OPSIZE_32; if bit_base == 0 { @@ -1116,7 +1110,7 @@ pub unsafe fn bsr32(mut old: i32, mut bit_base: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn popcnt(mut v: i32) -> i32 { +pub unsafe fn popcnt(v: i32) -> i32 { *flags_changed = 0; *flags &= !FLAGS_ALL; if 0 != v { @@ -1128,7 +1122,7 @@ pub unsafe fn popcnt(mut v: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn saturate_sw_to_ub(mut v: u32) -> u32 { +pub unsafe fn saturate_sw_to_ub(v: u32) -> u32 { dbg_assert!(v & 4294901760 == 0); let mut ret: u32 = v; if ret >= 32768 { @@ -1141,7 +1135,7 @@ pub unsafe fn saturate_sw_to_ub(mut v: u32) -> u32 { return ret; } #[no_mangle] -pub unsafe fn saturate_sw_to_sb(mut v: i32) -> i32 { +pub unsafe fn saturate_sw_to_sb(v: i32) -> i32 { dbg_assert!(v as u32 & 4294901760 == 0); let mut ret: i32 = v; if ret > 65408 { @@ -1157,7 +1151,7 @@ pub unsafe fn saturate_sw_to_sb(mut v: i32) -> i32 { return ret; } #[no_mangle] -pub unsafe fn saturate_sd_to_sw(mut v: u32) -> u32 { +pub unsafe fn saturate_sd_to_sw(v: u32) -> u32 { let mut ret: u32 = v; if ret > 4294934528 { ret = ret & 65535 @@ -1172,7 +1166,7 @@ pub unsafe fn saturate_sd_to_sw(mut v: u32) -> u32 { return ret; } #[no_mangle] -pub unsafe fn saturate_sd_to_sb(mut v: u32) -> u32 { +pub unsafe fn saturate_sd_to_sb(v: u32) -> u32 { let mut ret: u32 = v; if ret > 4294967168 { ret = ret & 255 @@ -1187,7 +1181,7 @@ pub unsafe fn saturate_sd_to_sb(mut v: u32) -> u32 { return ret; } #[no_mangle] -pub unsafe fn saturate_sd_to_ub(mut v: i32) -> i32 { +pub unsafe fn saturate_sd_to_ub(v: i32) -> i32 { let mut ret: i32 = v; if ret < 0 { ret = 0 @@ -1196,7 +1190,7 @@ pub unsafe fn saturate_sd_to_ub(mut v: i32) -> i32 { return ret; } #[no_mangle] -pub unsafe fn saturate_ud_to_ub(mut v: u32) -> u32 { +pub unsafe fn saturate_ud_to_ub(v: u32) -> u32 { let mut ret: u32 = v; if ret > 255 { ret = 255 @@ -1205,7 +1199,7 @@ pub unsafe fn saturate_ud_to_ub(mut v: u32) -> u32 { return ret; } #[no_mangle] -pub unsafe fn saturate_uw(mut v: u32) -> i32 { +pub unsafe fn saturate_uw(v: u32) -> i32 { let mut ret: u32 = v; if ret > 2147483647 { ret = 0 diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index f2614638..d8ead580 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1,4 +1,4 @@ -#![allow(non_upper_case_globals, unused_mut)] +#![allow(non_upper_case_globals)] extern "C" { #[no_mangle] @@ -304,9 +304,7 @@ impl SegmentDescriptor { pub unsafe fn after_block_boundary() { jit_block_boundary = 0 != 1; } -pub unsafe fn same_page(mut addr1: i32, mut addr2: i32) -> bool { - return addr1 & !4095 == addr2 & !4095; -} +pub unsafe fn same_page(addr1: i32, addr2: i32) -> bool { return addr1 & !4095 == addr2 & !4095; } #[no_mangle] pub unsafe fn get_eflags() -> i32 { @@ -319,10 +317,10 @@ pub unsafe fn get_eflags() -> i32 { | (getof() as i32) << 11; } -pub unsafe fn translate_address_read(mut address: i32) -> OrPageFault { - let mut base: i32 = (address as u32 >> 12) as i32; - let mut entry: i32 = *tlb_data.offset(base as isize); - let mut user: bool = *cpl as i32 == 3; +pub unsafe fn translate_address_read(address: i32) -> OrPageFault { + let base: i32 = (address as u32 >> 12) as i32; + let entry: i32 = *tlb_data.offset(base as isize); + let user: bool = *cpl as i32 == 3; if entry & (TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0 }) == TLB_VALID { return Ok((entry & !4095 ^ address) as u32); } @@ -331,25 +329,21 @@ pub unsafe fn translate_address_read(mut address: i32) -> OrPageFault { }; } -pub unsafe fn do_page_translation( - mut addr: i32, - mut for_writing: bool, - mut user: bool, -) -> OrPageFault { +pub unsafe fn do_page_translation(addr: i32, for_writing: bool, user: bool) -> OrPageFault { let mut can_write: bool = 0 != 1; - let mut global; + let global; let mut allow_user: bool = 0 != 1; - let mut page: i32 = (addr as u32 >> 12) as i32; - let mut high; + let page: i32 = (addr as u32 >> 12) as i32; + let high; if *cr & CR0_PG == 0 { // paging disabled high = (addr as u32 & 4294963200) as i32; global = 0 != 0 } else { - let mut page_dir_addr: i32 = + let page_dir_addr: i32 = (*cr.offset(3) as u32 >> 2).wrapping_add((page >> 10) as u32) as i32; - let mut page_dir_entry: i32 = read_aligned32(page_dir_addr as u32); + let page_dir_entry: i32 = read_aligned32(page_dir_addr as u32); // XXX let kernel_write_override: bool = !user && 0 == *cr & CR0_WP; if 0 == page_dir_entry & PAGE_TABLE_PRESENT_MASK { @@ -398,10 +392,9 @@ pub unsafe fn do_page_translation( global = page_dir_entry & PAGE_TABLE_GLOBAL_MASK == PAGE_TABLE_GLOBAL_MASK } else { - let mut page_table_addr: i32 = ((page_dir_entry as u32 & 4294963200) >> 2) - .wrapping_add((page & 1023) as u32) - as i32; - let mut page_table_entry: i32 = read_aligned32(page_table_addr as u32); + let page_table_addr: i32 = ((page_dir_entry as u32 & 4294963200) >> 2) + .wrapping_add((page & 1023) as u32) as i32; + let page_table_entry: i32 = read_aligned32(page_table_addr as u32); if page_table_entry & PAGE_TABLE_PRESENT_MASK == 0 { *cr.offset(2) = addr; trigger_pagefault(for_writing, user, 0 != 0); @@ -472,11 +465,11 @@ pub unsafe fn do_page_translation( } dbg_assert!(found); } - let mut is_in_mapped_range: bool = in_mapped_range(high as u32); - let mut physical_page: i32 = (high as u32 >> 12) as i32; - let mut has_code: bool = + let is_in_mapped_range: bool = in_mapped_range(high as u32); + let physical_page: i32 = (high as u32 >> 12) as i32; + let has_code: bool = !is_in_mapped_range && 0 != ::c_api::jit_page_has_code(physical_page as u32) as i32; - let mut info_bits: i32 = TLB_VALID + let info_bits: i32 = TLB_VALID | if 0 != can_write as i32 { 0 } @@ -519,7 +512,7 @@ pub unsafe fn full_clear_tlb() { *last_virt_eip = -1; *last_virt_esp = -1; for i in 0..valid_tlb_entries_count { - let mut page: i32 = valid_tlb_entries[i as usize]; + let page: i32 = valid_tlb_entries[i as usize]; *tlb_data.offset(page as isize) = 0; } valid_tlb_entries_count = 0; @@ -538,8 +531,8 @@ pub unsafe fn clear_tlb() { *last_virt_esp = -1; let mut global_page_offset: i32 = 0; for i in 0..valid_tlb_entries_count { - let mut page: i32 = valid_tlb_entries[i as usize]; - let mut entry: i32 = *tlb_data.offset(page as isize); + let page: i32 = valid_tlb_entries[i as usize]; + let entry: i32 = *tlb_data.offset(page as isize); if 0 != entry & TLB_GLOBAL { // reinsert at the front valid_tlb_entries[global_page_offset as usize] = page; @@ -559,7 +552,7 @@ pub unsafe fn clear_tlb() { }; } -pub unsafe fn trigger_pagefault(mut write: bool, mut user: bool, mut present: bool) { +pub unsafe fn trigger_pagefault(write: bool, user: bool, present: bool) { if 0 != 0 * 0 { dbg_log!( "page fault w={} u={} p={} eip={:x} cr2={:x}", @@ -584,7 +577,7 @@ pub unsafe fn trigger_pagefault(mut write: bool, mut user: bool, mut present: bo // dbg_assert!(0 != 0); //} // invalidate tlb entry - let mut page: i32 = (*cr.offset(2) as u32 >> 12) as i32; + let page: i32 = (*cr.offset(2) as u32 >> 12) as i32; *tlb_data.offset(page as isize) = 0; *instruction_pointer = *previous_ip; //*page_fault = 0 != 1; @@ -597,10 +590,10 @@ pub unsafe fn trigger_pagefault(mut write: bool, mut user: bool, mut present: bo //profiler::stat_increment(S_TRIGGER_CPU_EXCEPTION); } -pub unsafe fn translate_address_write(mut address: i32) -> OrPageFault { - let mut base: i32 = (address as u32 >> 12) as i32; - let mut entry: i32 = *tlb_data.offset(base as isize); - let mut user: bool = *cpl as i32 == 3; +pub unsafe fn translate_address_write(address: i32) -> OrPageFault { + let base: i32 = (address as u32 >> 12) as i32; + let entry: i32 = *tlb_data.offset(base as isize); + let user: bool = *cpl as i32 == 3; if entry & (TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0 } | TLB_READONLY) == TLB_VALID { @@ -612,13 +605,13 @@ pub unsafe fn translate_address_write(mut address: i32) -> OrPageFault { } #[no_mangle] -pub unsafe fn tlb_set_has_code(mut physical_page: u32, mut has_code: bool) { +pub unsafe fn tlb_set_has_code(physical_page: u32, has_code: bool) { dbg_assert!(physical_page < (1 << 20) as u32); for i in 0..valid_tlb_entries_count { - let mut page: i32 = valid_tlb_entries[i as usize]; - let mut entry: i32 = *tlb_data.offset(page as isize); + let page: i32 = valid_tlb_entries[i as usize]; + let entry: i32 = *tlb_data.offset(page as isize); if 0 != entry { - let mut tlb_physical_page: u32 = entry as u32 >> 12 ^ page as u32; + let tlb_physical_page: u32 = entry as u32 >> 12 ^ page as u32; if physical_page == tlb_physical_page { *tlb_data.offset(page as isize) = if 0 != has_code as i32 { entry | TLB_HAS_CODE @@ -639,8 +632,8 @@ pub unsafe fn check_tlb_invariants() { } else { for i in 0..valid_tlb_entries_count { - let mut page: i32 = valid_tlb_entries[i as usize]; - let mut entry: i32 = *tlb_data.offset(page as isize); + let page: i32 = valid_tlb_entries[i as usize]; + let entry: i32 = *tlb_data.offset(page as isize); if 0 == entry || 0 != entry & TLB_IN_MAPPED_RANGE { // there's no code in mapped memory } @@ -649,22 +642,21 @@ pub unsafe fn check_tlb_invariants() { }; } -pub unsafe fn writable_or_pagefault(mut addr: i32, mut size: i32) -> OrPageFault<()> { +pub unsafe fn writable_or_pagefault(addr: i32, size: i32) -> OrPageFault<()> { dbg_assert!(size < 4096); dbg_assert!(size > 0); if *cr & CR0_PG == 0 { return Ok(()); } else { - let mut user: bool = *cpl as i32 == 3; - let mut mask: i32 = - TLB_READONLY | TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0 }; - let mut expect: i32 = TLB_VALID; - let mut page: i32 = (addr as u32 >> 12) as i32; + let user: bool = *cpl as i32 == 3; + let mask: i32 = TLB_READONLY | TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0 }; + let expect: i32 = TLB_VALID; + let page: i32 = (addr as u32 >> 12) as i32; if *tlb_data.offset(page as isize) & mask != expect { do_page_translation(addr, 0 != 1, user)?; } - let mut next_page: i32 = ((addr + size - 1) as u32 >> 12) as i32; + let next_page: i32 = ((addr + size - 1) as u32 >> 12) as i32; if page != next_page { dbg_assert!(next_page == page + 1); // XXX: possibly out of bounds @@ -677,13 +669,13 @@ pub unsafe fn writable_or_pagefault(mut addr: i32, mut size: i32) -> OrPageFault } pub unsafe fn read_imm8() -> OrPageFault { - let mut eip: i32 = *instruction_pointer; + let eip: i32 = *instruction_pointer; if 0 != eip & !4095 ^ *last_virt_eip { *eip_phys = (translate_address_read(eip)? ^ eip as u32) as i32; *last_virt_eip = eip & !4095 } dbg_assert!(!in_mapped_range((*eip_phys ^ eip) as u32)); - let mut data8: i32 = *mem8.offset((*eip_phys ^ eip) as isize) as i32; + let data8: i32 = *mem8.offset((*eip_phys ^ eip) as isize) as i32; *instruction_pointer = eip + 1; return Ok(data8); } @@ -698,7 +690,7 @@ pub unsafe fn read_imm16() -> OrPageFault { return Ok(read_imm8()? | read_imm8()? << 8); } else { - let mut data16: i32 = read16((*eip_phys ^ *instruction_pointer) as u32); + let data16: i32 = read16((*eip_phys ^ *instruction_pointer) as u32); *instruction_pointer = *instruction_pointer + 2; return Ok(data16); }; @@ -710,7 +702,7 @@ pub unsafe fn read_imm32s() -> OrPageFault { return Ok(read_imm16()? | read_imm16()? << 16); } else { - let mut data32: i32 = read32s((*eip_phys ^ *instruction_pointer) as u32); + let data32: i32 = read32s((*eip_phys ^ *instruction_pointer) as u32); *instruction_pointer = *instruction_pointer + 4; return Ok(data32); }; @@ -867,7 +859,7 @@ pub unsafe fn switch_seg(reg: i32, selector_raw: i32) -> bool { } #[no_mangle] -pub unsafe fn get_seg(mut segment: i32) -> i32 { +pub unsafe fn get_seg(segment: i32) -> i32 { dbg_assert!(segment >= 0 && segment < 8); // TODO: Remove protected_mode check if *protected_mode { @@ -988,12 +980,12 @@ pub unsafe fn popa32() { *reg32s.offset(EAX as isize) = pop32s().unwrap(); } -pub unsafe fn trigger_gp(mut code: i32) { +pub unsafe fn trigger_gp(code: i32) { *instruction_pointer = *previous_ip; raise_exception_with_code(CPU_EXCEPTION_GP, code); } -pub unsafe fn raise_exception_with_code(mut interrupt_nr: i32, mut error_code: i32) { +pub unsafe fn raise_exception_with_code(interrupt_nr: i32, error_code: i32) { if DEBUG { if must_not_fault { dbg_log!( @@ -1018,8 +1010,8 @@ pub unsafe fn get_seg_cs() -> i32 { return *segment_offsets.offset(CS as isize); pub unsafe fn get_seg_ss() -> i32 { return *segment_offsets.offset(SS as isize); } -pub unsafe fn get_seg_prefix(mut default_segment: i32) -> i32 { - let mut prefix: i32 = *prefixes as i32 & PREFIX_MASK_SEGMENT; +pub unsafe fn get_seg_prefix(default_segment: i32) -> i32 { + let prefix: i32 = *prefixes as i32 & PREFIX_MASK_SEGMENT; if 0 != prefix { if prefix == SEG_PREFIX_ZERO { return 0; @@ -1033,13 +1025,13 @@ pub unsafe fn get_seg_prefix(mut default_segment: i32) -> i32 { }; } -pub unsafe fn get_seg_prefix_ds(mut offset: i32) -> i32 { return get_seg_prefix(DS) + offset; } +pub unsafe fn get_seg_prefix_ds(offset: i32) -> i32 { return get_seg_prefix(DS) + offset; } -pub unsafe fn get_seg_prefix_ss(mut offset: i32) -> i32 { return get_seg_prefix(SS) + offset; } +pub unsafe fn get_seg_prefix_ss(offset: i32) -> i32 { return get_seg_prefix(SS) + offset; } -pub unsafe fn get_seg_prefix_cs(mut offset: i32) -> i32 { return get_seg_prefix(CS) + offset; } +pub unsafe fn get_seg_prefix_cs(offset: i32) -> i32 { return get_seg_prefix(CS) + offset; } -pub unsafe fn modrm_resolve(mut modrm_byte: i32) -> OrPageFault { +pub unsafe fn modrm_resolve(modrm_byte: i32) -> OrPageFault { if is_asize_32() { resolve_modrm32(modrm_byte) } @@ -1057,9 +1049,9 @@ pub unsafe fn cycle_internal() { profiler::stat_increment(S_CYCLE_INTERNAL); if true { *previous_ip = *instruction_pointer; - let mut phys_addr: u32 = return_on_pagefault!(get_phys_eip()) as u32; - let mut state_flags: CachedStateFlags = pack_current_state_flags(); - let mut entry: u32 = ::c_api::jit_find_cache_entry(phys_addr, state_flags as u32); + let phys_addr: u32 = return_on_pagefault!(get_phys_eip()) as u32; + let state_flags: CachedStateFlags = pack_current_state_flags(); + let entry: u32 = ::c_api::jit_find_cache_entry(phys_addr, state_flags as u32); if 0 != entry { profiler::stat_increment(S_RUN_FROM_CACHE); @@ -1089,7 +1081,7 @@ pub unsafe fn cycle_internal() { dbg_assert!(must_not_fault); must_not_fault = 0 != 0 } - let mut initial_tsc: i32 = *timestamp_counter as i32; + let initial_tsc: i32 = *timestamp_counter as i32; jit_run_interpreted(phys_addr as i32); profiler::stat_increment_by( S_RUN_INTERPRETED_STEPS, @@ -1106,17 +1098,17 @@ pub unsafe fn cycle_internal() { } pub unsafe fn get_phys_eip() -> OrPageFault { - let mut eip: i32 = *instruction_pointer; + let eip: i32 = *instruction_pointer; if 0 != eip & !4095 ^ *last_virt_eip { *eip_phys = (translate_address_read(eip)? ^ eip as u32) as i32; *last_virt_eip = eip & !4095 } - let mut phys_addr: u32 = (*eip_phys ^ eip) as u32; + let phys_addr: u32 = (*eip_phys ^ eip) as u32; dbg_assert!(!in_mapped_range(phys_addr)); return Ok(phys_addr); } -unsafe fn jit_run_interpreted(mut phys_addr: i32) { +unsafe fn jit_run_interpreted(phys_addr: i32) { profiler::stat_increment(S_RUN_INTERPRETED); dbg_assert!(!in_mapped_range(phys_addr as u32)); @@ -1178,7 +1170,7 @@ pub unsafe fn run_prefix_instruction() { pub unsafe fn clear_prefixes() { *prefixes = 0 } -pub unsafe fn segment_prefix_op(mut seg: i32) { +pub unsafe fn segment_prefix_op(seg: i32) { dbg_assert!(seg <= 5); *prefixes = (*prefixes as i32 | seg + 1) as u8; run_prefix_instruction(); @@ -1188,7 +1180,7 @@ pub unsafe fn segment_prefix_op(mut seg: i32) { #[no_mangle] pub unsafe fn do_many_cycles_native() { profiler::stat_increment(S_DO_MANY_CYCLES); - let mut initial_timestamp_counter: u32 = *timestamp_counter; + let initial_timestamp_counter: u32 = *timestamp_counter; while (*timestamp_counter).wrapping_sub(initial_timestamp_counter) < LOOP_COUNTER as u32 && !*in_hlt { @@ -1196,7 +1188,7 @@ pub unsafe fn do_many_cycles_native() { } } //#[no_mangle] -//pub unsafe fn raise_exception(mut interrupt_nr: i32) { +//pub unsafe fn raise_exception(interrupt_nr: i32) { // if DEBUG { // if must_not_fault { // dbg_log!("Unexpected fault: 0x{:x}", interrupt_nr); @@ -1247,7 +1239,7 @@ pub unsafe fn trigger_nm() { } #[no_mangle] -pub unsafe fn trigger_gp_non_raising(mut code: i32) { +pub unsafe fn trigger_gp_non_raising(code: i32) { if DEBUG { if cpu_exception_hook(CPU_EXCEPTION_GP) { return; @@ -1257,16 +1249,16 @@ pub unsafe fn trigger_gp_non_raising(mut code: i32) { call_interrupt_vector(CPU_EXCEPTION_GP, 0 != 0, 0 != 1, code); } -pub unsafe fn virt_boundary_read16(mut low: u32, mut high: u32) -> i32 { +pub unsafe fn virt_boundary_read16(low: u32, high: u32) -> i32 { dbg_assert!(low & 4095 == 4095); dbg_assert!(high & 4095 == 0); return read8(low as u32) | read8(high as u32) << 8; } -pub unsafe fn virt_boundary_read32s(mut low: u32, mut high: u32) -> i32 { +pub unsafe fn virt_boundary_read32s(low: u32, high: u32) -> i32 { dbg_assert!(low & 4095 >= 4093); dbg_assert!(high - 3 & 4095 == low & 4095); - let mut mid; + let mid; if 0 != low & 1 { if 0 != low & 2 { // 0xFFF @@ -1284,14 +1276,14 @@ pub unsafe fn virt_boundary_read32s(mut low: u32, mut high: u32) -> i32 { return read8(low as u32) | mid << 8 | read8(high as u32) << 24; } -pub unsafe fn virt_boundary_write16(mut low: u32, mut high: u32, mut value: i32) { +pub unsafe fn virt_boundary_write16(low: u32, high: u32, value: i32) { dbg_assert!(low & 4095 == 4095); dbg_assert!(high & 4095 == 0); write8(low as u32, value); write8(high as u32, value >> 8); } -pub unsafe fn virt_boundary_write32(mut low: u32, mut high: u32, mut value: i32) { +pub unsafe fn virt_boundary_write32(low: u32, high: u32, value: i32) { dbg_assert!(low & 4095 >= 4093); dbg_assert!(high - 3 & 4095 == low & 4095); write8(low as u32, value); @@ -1315,18 +1307,18 @@ pub unsafe fn virt_boundary_write32(mut low: u32, mut high: u32, mut value: i32) write8(high as u32, value >> 24); } -pub unsafe fn safe_read8(mut addr: i32) -> OrPageFault { +pub unsafe fn safe_read8(addr: i32) -> OrPageFault { return Ok(read8(translate_address_read(addr)?)); } -pub unsafe fn safe_read16(mut address: i32) -> OrPageFault { - let mut base: i32 = (address as u32 >> 12) as i32; - let mut entry: i32 = *tlb_data.offset(base as isize); - let mut info_bits: i32 = entry & 4095 & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; +pub unsafe fn safe_read16(address: i32) -> OrPageFault { + let base: i32 = (address as u32 >> 12) as i32; + let entry: i32 = *tlb_data.offset(base as isize); + let info_bits: i32 = entry & 4095 & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; if info_bits == TLB_VALID && address & 4095 <= 4096 - 2 { // - not in memory mapped area // - can be accessed from any cpl - let mut phys_address: u32 = (entry & !4095 ^ address) as u32; + let phys_address: u32 = (entry & !4095 ^ address) as u32; dbg_assert!(!in_mapped_range(phys_address)); return Ok(*(mem8.offset(phys_address as isize) as *mut u16) as i32); } @@ -1335,7 +1327,7 @@ pub unsafe fn safe_read16(mut address: i32) -> OrPageFault { }; } -pub unsafe fn safe_read16_slow(mut addr: i32) -> OrPageFault { +pub unsafe fn safe_read16_slow(addr: i32) -> OrPageFault { if addr & 4095 == 4095 { return Ok(safe_read8(addr)? | safe_read8(addr + 1)? << 8); } @@ -1344,17 +1336,17 @@ pub unsafe fn safe_read16_slow(mut addr: i32) -> OrPageFault { }; } -pub unsafe fn safe_read32s(mut address: i32) -> OrPageFault { - let mut base: i32 = (address as u32 >> 12) as i32; - let mut entry: i32 = *tlb_data.offset(base as isize); - let mut info_bits: i32 = entry & 4095 & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; +pub unsafe fn safe_read32s(address: i32) -> OrPageFault { + let base: i32 = (address as u32 >> 12) as i32; + let entry: i32 = *tlb_data.offset(base as isize); + let info_bits: i32 = entry & 4095 & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; if info_bits == TLB_VALID && address & 4095 <= 4096 - 4 { if false { profiler::stat_increment(S_SAFE_READ_FAST); } // - not in memory mapped area // - can be accessed from any cpl - let mut phys_address: u32 = (entry & !4095 ^ address) as u32; + let phys_address: u32 = (entry & !4095 ^ address) as u32; dbg_assert!(!in_mapped_range(phys_address)); return Ok(*(mem8.offset(phys_address as isize) as *mut i32)); } @@ -1422,7 +1414,7 @@ pub fn report_safe_write_jit_slow(address: u32, entry: i32) { } } -pub unsafe fn safe_read32s_slow(mut addr: i32) -> OrPageFault { +pub unsafe fn safe_read32s_slow(addr: i32) -> OrPageFault { if addr & 4095 >= 4093 { return Ok(safe_read16(addr)? | safe_read16(addr + 2)? << 16); } @@ -1473,7 +1465,7 @@ pub unsafe fn safe_read32s_slow_jit(addr: i32) -> i32 { } } -pub unsafe fn safe_read64s(mut addr: i32) -> OrPageFault { +pub unsafe fn safe_read64s(addr: i32) -> OrPageFault { let mut x: reg64 = reg64 { i8_0: [0; 8] }; if addr & 4095 > 4096 - 8 { x.u32_0[0] = safe_read32s(addr)? as u32; @@ -1486,7 +1478,7 @@ pub unsafe fn safe_read64s(mut addr: i32) -> OrPageFault { Ok(x) } -pub unsafe fn safe_read128s(mut addr: i32) -> OrPageFault { +pub unsafe fn safe_read128s(addr: i32) -> OrPageFault { let mut x: reg128 = reg128 { i8_0: [0; 16] }; if addr & 4095 > 4096 - 16 { x.u64_0[0] = safe_read64s(addr)?.u64_0[0]; @@ -1499,21 +1491,21 @@ pub unsafe fn safe_read128s(mut addr: i32) -> OrPageFault { Ok(x) } -pub unsafe fn safe_write8(mut addr: i32, mut value: i32) -> OrPageFault<()> { +pub unsafe fn safe_write8(addr: i32, value: i32) -> OrPageFault<()> { write8(translate_address_write(addr)?, value); Ok(()) } -pub unsafe fn safe_write16(mut address: i32, mut value: i32) -> OrPageFault<()> { - let mut base: i32 = (address as u32 >> 12) as i32; - let mut entry: i32 = *tlb_data.offset(base as isize); - let mut info_bits: i32 = entry & 4095 & !TLB_GLOBAL; +pub unsafe fn safe_write16(address: i32, value: i32) -> OrPageFault<()> { + let base: i32 = (address as u32 >> 12) as i32; + let entry: i32 = *tlb_data.offset(base as isize); + let info_bits: i32 = entry & 4095 & !TLB_GLOBAL; if info_bits == TLB_VALID && address & 4095 <= 4096 - 2 { // - allowed to write in user-mode // - not in memory mapped area // - can be accessed from any cpl // - does not contain code - let mut phys_address: u32 = (entry & !4095 ^ address) as u32; + let phys_address: u32 = (entry & !4095 ^ address) as u32; dbg_assert!(!::c_api::jit_page_has_code(phys_address >> 12)); dbg_assert!(!in_mapped_range(phys_address)); *(mem8.offset(phys_address as isize) as *mut u16) = value as u16; @@ -1524,8 +1516,8 @@ pub unsafe fn safe_write16(mut address: i32, mut value: i32) -> OrPageFault<()> Ok(()) } -pub unsafe fn safe_write16_slow(mut addr: i32, mut value: i32) -> OrPageFault<()> { - let mut phys_low = translate_address_write(addr)?; +pub unsafe fn safe_write16_slow(addr: i32, value: i32) -> OrPageFault<()> { + let phys_low = translate_address_write(addr)?; if addr & 4095 == 4095 { virt_boundary_write16(phys_low, translate_address_write(addr + 1)?, value); } @@ -1535,10 +1527,10 @@ pub unsafe fn safe_write16_slow(mut addr: i32, mut value: i32) -> OrPageFault<() Ok(()) } -pub unsafe fn safe_write32(mut address: i32, mut value: i32) -> OrPageFault<()> { - let mut base: i32 = (address as u32 >> 12) as i32; - let mut entry: i32 = *tlb_data.offset(base as isize); - let mut info_bits: i32 = +pub unsafe fn safe_write32(address: i32, value: i32) -> OrPageFault<()> { + let base: i32 = (address as u32 >> 12) as i32; + let entry: i32 = *tlb_data.offset(base as isize); + let info_bits: i32 = entry & 4095 & !TLB_GLOBAL & !if *cpl as i32 == 3 { 0 } else { TLB_NO_USER }; if info_bits == TLB_VALID && address & 4095 <= 4096 - 4 { if false { @@ -1547,7 +1539,7 @@ pub unsafe fn safe_write32(mut address: i32, mut value: i32) -> OrPageFault<()> // - allowed to write in user-mode // - not in memory mapped area // - does not contain code - let mut phys_address: u32 = (entry & !4095 ^ address) as u32; + let phys_address: u32 = (entry & !4095 ^ address) as u32; dbg_assert!(!::c_api::jit_page_has_code(phys_address >> 12)); dbg_assert!(!in_mapped_range(phys_address)); *(mem8.offset(phys_address as isize) as *mut i32) = value; @@ -1581,8 +1573,8 @@ pub unsafe fn safe_write32(mut address: i32, mut value: i32) -> OrPageFault<()> Ok(()) } -pub unsafe fn safe_write32_slow(mut addr: i32, mut value: i32) -> OrPageFault<()> { - let mut phys_low = translate_address_write(addr)?; +pub unsafe fn safe_write32_slow(addr: i32, value: i32) -> OrPageFault<()> { + let phys_low = translate_address_write(addr)?; if addr & 4095 > 4096 - 4 { virt_boundary_write32( phys_low, @@ -1620,59 +1612,57 @@ pub unsafe fn safe_write32_slow_jit(addr: i32, value: i32) { } } -pub unsafe fn safe_write64(mut addr: i32, mut value: i64) -> OrPageFault<()> { +pub unsafe fn safe_write64(addr: i32, value: i64) -> OrPageFault<()> { if addr & 4095 > 4096 - 8 { writable_or_pagefault(addr, 8)?; safe_write32(addr, value as i32).unwrap(); safe_write32(addr + 4, (value >> 32) as i32).unwrap(); } else { - let mut phys = translate_address_write(addr)?; + let phys = translate_address_write(addr)?; write64(phys, value); }; Ok(()) } -pub unsafe fn safe_write128(mut addr: i32, mut value: reg128) -> OrPageFault<()> { +pub unsafe fn safe_write128(addr: i32, value: reg128) -> OrPageFault<()> { if addr & 4095 > 4096 - 16 { writable_or_pagefault(addr, 16)?; safe_write64(addr, value.u64_0[0] as i64).unwrap(); safe_write64(addr + 8, value.u64_0[1] as i64).unwrap(); } else { - let mut phys = translate_address_write(addr)?; + let phys = translate_address_write(addr)?; write128(phys, value); }; Ok(()) } -pub unsafe fn get_reg8_index(mut index: i32) -> i32 { return index << 2 & 12 | index >> 2 & 1; } +pub unsafe fn get_reg8_index(index: i32) -> i32 { return index << 2 & 12 | index >> 2 & 1; } -pub unsafe fn read_reg8(mut index: i32) -> i32 { +pub unsafe fn read_reg8(index: i32) -> i32 { return *reg8.offset(get_reg8_index(index) as isize) as i32; } -pub unsafe fn write_reg8(mut index: i32, mut value: i32) { +pub unsafe fn write_reg8(index: i32, value: i32) { *reg8.offset(get_reg8_index(index) as isize) = value as u8; } -pub unsafe fn get_reg16_index(mut index: i32) -> i32 { return index << 1; } +pub unsafe fn get_reg16_index(index: i32) -> i32 { return index << 1; } -pub unsafe fn read_reg16(mut index: i32) -> i32 { +pub unsafe fn read_reg16(index: i32) -> i32 { return *reg16.offset(get_reg16_index(index) as isize) as i32; } -pub unsafe fn write_reg16(mut index: i32, mut value: i32) { +pub unsafe fn write_reg16(index: i32, value: i32) { *reg16.offset(get_reg16_index(index) as isize) = value as u16; } -pub unsafe fn read_reg32(mut index: i32) -> i32 { return *reg32s.offset(index as isize); } +pub unsafe fn read_reg32(index: i32) -> i32 { return *reg32s.offset(index as isize); } -pub unsafe fn write_reg32(mut index: i32, mut value: i32) { - *reg32s.offset(index as isize) = value; -} +pub unsafe fn write_reg32(index: i32, value: i32) { *reg32s.offset(index as isize) = value; } -pub unsafe fn write_reg_osize(mut index: i32, mut value: i32) { +pub unsafe fn write_reg_osize(index: i32, value: i32) { dbg_assert!(index >= 0 && index < 8); if is_osize_32() { write_reg32(index, value); @@ -1682,57 +1672,49 @@ pub unsafe fn write_reg_osize(mut index: i32, mut value: i32) { }; } -pub unsafe fn read_mmx32s(mut r: i32) -> i32 { - return (*reg_mmx.offset(r as isize)).u32_0[0] as i32; -} +pub unsafe fn read_mmx32s(r: i32) -> i32 { return (*reg_mmx.offset(r as isize)).u32_0[0] as i32; } -pub unsafe fn read_mmx64s(mut r: i32) -> reg64 { return *reg_mmx.offset(r as isize); } +pub unsafe fn read_mmx64s(r: i32) -> reg64 { return *reg_mmx.offset(r as isize); } -pub unsafe fn write_mmx64(mut r: i32, mut low: i32, mut high: i32) { +pub unsafe fn write_mmx64(r: i32, low: i32, high: i32) { *fxsave_store_fpu_mask &= !(1 << r); (*reg_mmx.offset(r as isize)).u32_0[0] = low as u32; (*reg_mmx.offset(r as isize)).u32_0[1] = high as u32; } -pub unsafe fn write_mmx_reg64(mut r: i32, mut data: reg64) { +pub unsafe fn write_mmx_reg64(r: i32, data: reg64) { *fxsave_store_fpu_mask &= !(1 << r); (*reg_mmx.offset(r as isize)).u64_0[0] = data.u64_0[0]; } -pub unsafe fn read_xmm_f32(mut r: i32) -> f32 { return (*reg_xmm.offset(r as isize)).f32_0[0]; } +pub unsafe fn read_xmm_f32(r: i32) -> f32 { return (*reg_xmm.offset(r as isize)).f32_0[0]; } -pub unsafe fn read_xmm32(mut r: i32) -> i32 { - return (*reg_xmm.offset(r as isize)).u32_0[0] as i32; -} +pub unsafe fn read_xmm32(r: i32) -> i32 { return (*reg_xmm.offset(r as isize)).u32_0[0] as i32; } -pub unsafe fn read_xmm64s(mut r: i32) -> reg64 { +pub unsafe fn read_xmm64s(r: i32) -> reg64 { let mut x: reg64 = reg64 { i8_0: [0; 8] }; x.u64_0[0] = (*reg_xmm.offset(r as isize)).u64_0[0]; return x; } -pub unsafe fn read_xmm128s(mut r: i32) -> reg128 { return *reg_xmm.offset(r as isize); } +pub unsafe fn read_xmm128s(r: i32) -> reg128 { return *reg_xmm.offset(r as isize); } -pub unsafe fn write_xmm_f32(mut r: i32, mut data: f32) { - (*reg_xmm.offset(r as isize)).f32_0[0] = data; -} +pub unsafe fn write_xmm_f32(r: i32, data: f32) { (*reg_xmm.offset(r as isize)).f32_0[0] = data; } -pub unsafe fn write_xmm32(mut r: i32, mut data: i32) { - (*reg_xmm.offset(r as isize)).i32_0[0] = data; -} +pub unsafe fn write_xmm32(r: i32, data: i32) { (*reg_xmm.offset(r as isize)).i32_0[0] = data; } -pub unsafe fn write_xmm64(mut r: i32, mut data: reg64) { +pub unsafe fn write_xmm64(r: i32, data: reg64) { (*reg_xmm.offset(r as isize)).u64_0[0] = data.u64_0[0]; } -pub unsafe fn write_xmm128(mut r: i32, mut i0: i32, mut i1: i32, mut i2: i32, mut i3: i32) { - let mut x: reg128 = reg128 { +pub unsafe fn write_xmm128(r: i32, i0: i32, i1: i32, i2: i32, i3: i32) { + let x: reg128 = reg128 { u32_0: [i0 as u32, i1 as u32, i2 as u32, i3 as u32], }; *reg_xmm.offset(r as isize) = x; } -pub unsafe fn write_xmm_reg128(mut r: i32, mut data: reg128) { +pub unsafe fn write_xmm_reg128(r: i32, data: reg128) { (*reg_xmm.offset(r as isize)).u64_0[0] = data.u64_0[0]; (*reg_xmm.offset(r as isize)).u64_0[1] = data.u64_0[1]; } @@ -1833,7 +1815,7 @@ pub unsafe fn get_stack_reg() -> i32 { } #[no_mangle] -pub unsafe fn set_stack_reg(mut value: i32) { +pub unsafe fn set_stack_reg(value: i32) { if *stack_size_32 { *reg32s.offset(ESP as isize) = value } @@ -1842,9 +1824,9 @@ pub unsafe fn set_stack_reg(mut value: i32) { }; } -pub unsafe fn get_reg_asize(mut reg: i32) -> i32 { +pub unsafe fn get_reg_asize(reg: i32) -> i32 { dbg_assert!(reg == ECX || reg == ESI || reg == EDI); - let mut r: i32 = *reg32s.offset(reg as isize); + let r: i32 = *reg32s.offset(reg as isize); if is_asize_32() { return r; } @@ -1853,7 +1835,7 @@ pub unsafe fn get_reg_asize(mut reg: i32) -> i32 { }; } -pub unsafe fn set_ecx_asize(mut value: i32) { +pub unsafe fn set_ecx_asize(value: i32) { if is_asize_32() { *reg32s.offset(ECX as isize) = value } @@ -1862,7 +1844,7 @@ pub unsafe fn set_ecx_asize(mut value: i32) { }; } -pub unsafe fn add_reg_asize(mut reg: i32, mut value: i32) { +pub unsafe fn add_reg_asize(reg: i32, value: i32) { dbg_assert!(reg == ECX || reg == ESI || reg == EDI); if is_asize_32() { *reg32s.offset(reg as isize) += value; @@ -1884,15 +1866,15 @@ pub unsafe fn decr_ecx_asize() -> i32 { } #[no_mangle] -pub unsafe fn set_tsc(mut low: u32, mut high: u32) { - let mut new_value: u64 = low as u64 | (high as u64) << 32; - let mut current_value: u64 = read_tsc(); +pub unsafe fn set_tsc(low: u32, high: u32) { + let new_value: u64 = low as u64 | (high as u64) << 32; + let current_value: u64 = read_tsc(); tsc_offset = current_value.wrapping_sub(new_value); } pub unsafe fn read_tsc() -> u64 { - let mut n: f64 = microtick() * TSC_RATE; - let mut value: u64 = (n as u64).wrapping_sub(tsc_offset); + let n: f64 = microtick() * TSC_RATE; + let value: u64 = (n as u64).wrapping_sub(tsc_offset); if 0 != 1 + 1 { return value; } @@ -1904,7 +1886,7 @@ pub unsafe fn read_tsc() -> u64 { } } else { - let mut previous_value: u64 = rdtsc_last_value.wrapping_add(rdtsc_imprecision_offset); + let previous_value: u64 = rdtsc_last_value.wrapping_add(rdtsc_imprecision_offset); if previous_value <= value { rdtsc_last_value = value; rdtsc_imprecision_offset = 0 @@ -1934,7 +1916,7 @@ pub unsafe fn vm86_mode() -> bool { return *flags & FLAG_VM == FLAG_VM; } pub unsafe fn getiopl() -> i32 { return *flags >> 12 & 3; } #[no_mangle] -pub unsafe fn get_opstats_buffer(mut index: i32) -> i32 { +pub unsafe fn get_opstats_buffer(index: i32) -> i32 { dbg_assert!(index >= 0 && index < 512); if index < 256 { return *opstats_buffer.offset(index as isize) as i32; @@ -1944,8 +1926,8 @@ pub unsafe fn get_opstats_buffer(mut index: i32) -> i32 { }; } -pub unsafe fn invlpg(mut addr: i32) { - let mut page: i32 = (addr as u32 >> 12) as i32; +pub unsafe fn invlpg(addr: i32) { + let page: i32 = (addr as u32 >> 12) as i32; // Note: Doesn't remove this page from valid_tlb_entries: This isn't // necessary, because when valid_tlb_entries grows too large, it will be // empties by calling clear_tlb, which removes this entry as it isn't global. @@ -1956,7 +1938,7 @@ pub unsafe fn invlpg(mut addr: i32) { } #[no_mangle] -pub unsafe fn update_eflags(mut new_flags: i32) { +pub unsafe fn update_eflags(new_flags: i32) { let mut dont_update: i32 = FLAG_RF | FLAG_VM | FLAG_VIP | FLAG_VIF; let mut clear: i32 = !FLAG_VIP & !FLAG_VIF & FLAGS_MASK; if 0 != *flags & FLAG_VM { @@ -1992,8 +1974,8 @@ pub unsafe fn get_valid_tlb_entries_count() -> i32 { } let mut result: i32 = 0; for i in 0..valid_tlb_entries_count { - let mut page: i32 = valid_tlb_entries[i as usize]; - let mut entry: i32 = *tlb_data.offset(page as isize); + let page: i32 = valid_tlb_entries[i as usize]; + let entry: i32 = *tlb_data.offset(page as isize); if 0 != entry { result += 1 } @@ -2008,8 +1990,8 @@ pub unsafe fn get_valid_global_tlb_entries_count() -> i32 { } let mut result: i32 = 0; for i in 0..valid_tlb_entries_count { - let mut page: i32 = valid_tlb_entries[i as usize]; - let mut entry: i32 = *tlb_data.offset(page as isize); + let page: i32 = valid_tlb_entries[i as usize]; + let entry: i32 = *tlb_data.offset(page as isize); if 0 != entry & TLB_GLOBAL { result += 1 } @@ -2017,9 +1999,9 @@ pub unsafe fn get_valid_global_tlb_entries_count() -> i32 { return result; } -pub unsafe fn translate_address_system_read(mut address: i32) -> OrPageFault { - let mut base: i32 = (address as u32 >> 12) as i32; - let mut entry: i32 = *tlb_data.offset(base as isize); +pub unsafe fn translate_address_system_read(address: i32) -> OrPageFault { + let base: i32 = (address as u32 >> 12) as i32; + let entry: i32 = *tlb_data.offset(base as isize); if 0 != entry & TLB_VALID { return Ok((entry & !4095 ^ address) as u32); } @@ -2028,9 +2010,9 @@ pub unsafe fn translate_address_system_read(mut address: i32) -> OrPageFault OrPageFault { - let mut base: i32 = (address as u32 >> 12) as i32; - let mut entry: i32 = *tlb_data.offset(base as isize); +pub unsafe fn translate_address_system_write(address: i32) -> OrPageFault { + let base: i32 = (address as u32 >> 12) as i32; + let entry: i32 = *tlb_data.offset(base as isize); if entry & (TLB_VALID | TLB_READONLY) == TLB_VALID { return Ok((entry & !4095 ^ address) as u32); } @@ -2040,7 +2022,7 @@ pub unsafe fn translate_address_system_write(mut address: i32) -> OrPageFault f64 { }; } #[no_mangle] -pub unsafe fn fpu_integer_round(mut f: f64) -> f64 { - let mut rc: i32 = *fpu_control_word >> 10 & 3; +pub unsafe fn fpu_integer_round(f: f64) -> f64 { + let rc: i32 = *fpu_control_word >> 10 & 3; // XXX: See https://en.wikipedia.org/wiki/C_mathematical_functions if rc == 0 { // Round to nearest, or even if equidistant let mut rounded: f64 = round(f); - let mut diff: f64 = rounded - f; + let diff: f64 = rounded - f; if diff == 0.5f64 || diff == -0.5f64 { rounded = 2.0f64 * round(f * 0.5f64) } @@ -125,21 +123,21 @@ pub unsafe fn fpu_integer_round(mut f: f64) -> f64 { }; } #[no_mangle] -pub unsafe fn fpu_load_m32(mut addr: i32) -> OrPageFault { +pub unsafe fn fpu_load_m32(addr: i32) -> OrPageFault { let v: f32 = transmute(safe_read32s(addr)?); Ok(v as f64) } #[no_mangle] -pub unsafe fn fpu_load_m64(mut addr: i32) -> OrPageFault { - let mut value: u64 = safe_read64s(addr)?.u64_0[0]; +pub unsafe fn fpu_load_m64(addr: i32) -> OrPageFault { + let value: u64 = safe_read64s(addr)?.u64_0[0]; let f: f64 = transmute(value); Ok(f) } #[no_mangle] -pub unsafe fn fpu_load_m80(mut addr: i32) -> OrPageFault { - let mut value: u64 = safe_read64s(addr as i32)?.u64_0[0]; - let mut exponent: i32 = safe_read16(addr.wrapping_add(8) as i32)?; +pub unsafe fn fpu_load_m80(addr: i32) -> OrPageFault { + let value: u64 = safe_read64s(addr as i32)?.u64_0[0]; + let exponent: i32 = safe_read16(addr.wrapping_add(8) as i32)?; let f = fpu_f80_to_f64((value, exponent as u16)); Ok(f) } @@ -226,22 +224,22 @@ pub unsafe fn fpu_load_status_word() -> i32 { return ((*fpu_status_word & !(7 << 11)) as u32 | *fpu_stack_ptr << 11) as i32; } #[no_mangle] -pub unsafe fn fpu_fadd(mut target_index: i32, mut val: f64) { - let mut st0: f64 = fpu_get_st0(); +pub unsafe fn fpu_fadd(target_index: i32, val: f64) { + let st0: f64 = fpu_get_st0(); fpu_write_st(*fpu_stack_ptr as i32 + target_index & 7, st0 + val); } #[no_mangle] pub unsafe fn fpu_fclex() { *fpu_status_word = 0; } #[no_mangle] -pub unsafe fn fpu_fcmovcc(mut condition: bool, mut r: i32) { +pub unsafe fn fpu_fcmovcc(condition: bool, r: i32) { if condition { fpu_write_st(*fpu_stack_ptr as i32, fpu_get_sti(r)); *fpu_stack_empty &= !(1 << *fpu_stack_ptr) }; } #[no_mangle] -pub unsafe fn fpu_fcom(mut y: f64) { - let mut x: f64 = fpu_get_st0(); +pub unsafe fn fpu_fcom(y: f64) { + let x: f64 = fpu_get_st0(); *fpu_status_word &= !FPU_RESULT_FLAGS; if !(x > y) { if y > x { @@ -256,9 +254,9 @@ pub unsafe fn fpu_fcom(mut y: f64) { }; } #[no_mangle] -pub unsafe fn fpu_fcomi(mut r: i32) { - let mut y: f64 = fpu_get_sti(r); - let mut x: f64 = *fpu_st.offset(*fpu_stack_ptr as isize); +pub unsafe fn fpu_fcomi(r: i32) { + let y: f64 = fpu_get_sti(r); + let x: f64 = *fpu_st.offset(*fpu_stack_ptr as isize); *flags_changed &= !(1 | FLAG_PARITY | FLAG_ZERO); *flags &= !(1 | FLAG_PARITY | FLAG_ZERO); if !(x > y) { @@ -274,7 +272,7 @@ pub unsafe fn fpu_fcomi(mut r: i32) { }; } #[no_mangle] -pub unsafe fn fpu_fcomip(mut r: i32) { +pub unsafe fn fpu_fcomip(r: i32) { fpu_fcomi(r); fpu_pop(); } @@ -284,32 +282,32 @@ pub unsafe fn fpu_pop() { *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_add(1) & 7; } #[no_mangle] -pub unsafe fn fpu_fcomp(mut val: f64) { +pub unsafe fn fpu_fcomp(val: f64) { fpu_fcom(val); fpu_pop(); } #[no_mangle] -pub unsafe fn fpu_fdiv(mut target_index: i32, mut val: f64) { - let mut st0: f64 = fpu_get_st0(); +pub unsafe fn fpu_fdiv(target_index: i32, val: f64) { + let st0: f64 = fpu_get_st0(); fpu_write_st(*fpu_stack_ptr as i32 + target_index & 7, st0 / val); } #[no_mangle] -pub unsafe fn fpu_fdivr(mut target_index: i32, mut val: f64) { - let mut st0: f64 = fpu_get_st0(); +pub unsafe fn fpu_fdivr(target_index: i32, val: f64) { + let st0: f64 = fpu_get_st0(); fpu_write_st(*fpu_stack_ptr as i32 + target_index & 7, val / st0); } #[no_mangle] -pub unsafe fn fpu_ffree(mut r: i32) { +pub unsafe fn fpu_ffree(r: i32) { *fpu_stack_empty |= 1 << (*fpu_stack_ptr).wrapping_add(r as u32); } #[no_mangle] -pub unsafe fn fpu_fildm64(mut addr: i32) { - let mut value: i64 = return_on_pagefault!(safe_read64s(addr)).i64_0[0]; - let mut m64: f64 = value as f64; +pub unsafe fn fpu_fildm64(addr: i32) { + let value: i64 = return_on_pagefault!(safe_read64s(addr)).i64_0[0]; + let m64: f64 = value as f64; fpu_push(m64); } #[no_mangle] -pub unsafe fn fpu_push(mut x: f64) { +pub unsafe fn fpu_push(x: f64) { *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_sub(1) & 7; if 0 != *fpu_stack_empty >> *fpu_stack_ptr & 1 { *fpu_status_word &= !FPU_C1; @@ -333,8 +331,8 @@ pub unsafe fn fpu_finit() { *fpu_stack_ptr = 0; } #[no_mangle] -pub unsafe fn fpu_fistm16(mut addr: i32) { - let mut st0: f64 = fpu_integer_round(fpu_get_st0()); +pub unsafe fn fpu_fistm16(addr: i32) { + let st0: f64 = fpu_integer_round(fpu_get_st0()); if st0 <= 32767.0 && st0 >= -32768.0 { return_on_pagefault!(safe_write16(addr, st0 as i32)); } @@ -346,14 +344,14 @@ pub unsafe fn fpu_fistm16(mut addr: i32) { #[no_mangle] pub unsafe fn fpu_invalid_arithmetic() { *fpu_status_word |= FPU_EX_I; } #[no_mangle] -pub unsafe fn fpu_fistm16p(mut addr: i32) { +pub unsafe fn fpu_fistm16p(addr: i32) { fpu_fistm16(addr); fpu_pop(); } #[no_mangle] -pub unsafe fn fpu_fistm32(mut addr: i32) { - let mut st0: f64 = fpu_integer_round(fpu_get_st0()); - let mut i: i32 = convert_f64_to_i32(st0); +pub unsafe fn fpu_fistm32(addr: i32) { + let st0: f64 = fpu_integer_round(fpu_get_st0()); + let i: i32 = convert_f64_to_i32(st0); if i == -0x80000000 { // XXX: Probably not correct if st0 == 0x80000000 // (input fits, but same value as error value) @@ -362,14 +360,14 @@ pub unsafe fn fpu_fistm32(mut addr: i32) { return_on_pagefault!(safe_write32(addr, i)); } #[no_mangle] -pub unsafe fn fpu_fistm32p(mut addr: i32) { +pub unsafe fn fpu_fistm32p(addr: i32) { fpu_fistm32(addr); fpu_pop(); } #[no_mangle] -pub unsafe fn fpu_fistm64p(mut addr: i32) { - let mut st0: f64 = fpu_integer_round(fpu_get_st0()); - let mut value; +pub unsafe fn fpu_fistm64p(addr: i32) { + let st0: f64 = fpu_integer_round(fpu_get_st0()); + let value; if st0 < TWO_POW_63 && st0 >= -TWO_POW_63 { value = st0 as i64 } @@ -381,12 +379,12 @@ pub unsafe fn fpu_fistm64p(mut addr: i32) { fpu_pop(); } #[no_mangle] -pub unsafe fn fpu_fldcw(mut addr: i32) { - let mut word: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn fpu_fldcw(addr: i32) { + let word: i32 = return_on_pagefault!(safe_read16(addr)); *fpu_control_word = word; } #[no_mangle] -pub unsafe fn fpu_fldenv(mut addr: i32) { +pub unsafe fn fpu_fldenv(addr: i32) { if is_osize_32() { // TODO: Add readable_or_pagefault return_on_pagefault!(translate_address_read(addr)); @@ -415,7 +413,7 @@ pub unsafe fn fpu_unimpl() { }; } #[no_mangle] -pub unsafe fn fpu_set_tag_word(mut tag_word: i32) { +pub unsafe fn fpu_set_tag_word(tag_word: i32) { *fpu_stack_empty = 0; for i in 0..8 { let empty = tag_word >> (2 * i) & 3 == 3; @@ -423,25 +421,23 @@ pub unsafe fn fpu_set_tag_word(mut tag_word: i32) { } } #[no_mangle] -pub unsafe fn fpu_set_status_word(mut sw: i32) { +pub unsafe fn fpu_set_status_word(sw: i32) { *fpu_status_word = sw & !(7 << 11); *fpu_stack_ptr = (sw >> 11 & 7) as u32; } #[no_mangle] -pub unsafe fn fpu_fldm32(mut addr: i32) { - fpu_push(return_on_pagefault!(safe_read32s(addr)) as f64); -} +pub unsafe fn fpu_fldm32(addr: i32) { fpu_push(return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe fn fpu_fldm64(mut addr: i32) { fpu_push(return_on_pagefault!(fpu_load_m64(addr))); } +pub unsafe fn fpu_fldm64(addr: i32) { fpu_push(return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe fn fpu_fldm80(mut addr: i32) { fpu_push(return_on_pagefault!(fpu_load_m80(addr))); } +pub unsafe fn fpu_fldm80(addr: i32) { fpu_push(return_on_pagefault!(fpu_load_m80(addr))); } #[no_mangle] -pub unsafe fn fpu_fmul(mut target_index: i32, mut val: f64) { - let mut st0: f64 = fpu_get_st0(); +pub unsafe fn fpu_fmul(target_index: i32, val: f64) { + let st0: f64 = fpu_get_st0(); fpu_write_st(*fpu_stack_ptr as i32 + target_index & 7, st0 * val); } #[no_mangle] -pub unsafe fn fpu_fnstsw_mem(mut addr: i32) { +pub unsafe fn fpu_fnstsw_mem(addr: i32) { return_on_pagefault!(safe_write16(addr, fpu_load_status_word())); } #[no_mangle] @@ -449,9 +445,9 @@ pub unsafe fn fpu_fnstsw_reg() { *reg16.offset(AX as isize) = fpu_load_status_wo #[no_mangle] pub unsafe fn fpu_fprem() { // XXX: This implementation differs from the description in Intel's manuals - let mut st0: f64 = fpu_get_st0(); - let mut st1: f64 = fpu_get_sti(1); - let mut fprem_quotient: i32 = convert_f64_to_i32(trunc(st0 / st1)); + let st0: f64 = fpu_get_st0(); + let st1: f64 = fpu_get_sti(1); + let fprem_quotient: i32 = convert_f64_to_i32(trunc(st0 / st1)); fpu_write_st(*fpu_stack_ptr as i32, fmod(st0, st1)); *fpu_status_word &= !(FPU_C0 | FPU_C1 | FPU_C3); if 0 != fprem_quotient & 1 { @@ -500,7 +496,7 @@ pub unsafe fn fpu_fsave(mut addr: i32) { } #[no_mangle] -pub unsafe fn fpu_store_m80(mut addr: i32, mut n: f64) { +pub unsafe fn fpu_store_m80(addr: i32, n: f64) { let (value, exponent) = fpu_f64_to_f80(n); // writable_or_pagefault must have checked called by the caller! safe_write64(addr, value as i64).unwrap(); @@ -510,11 +506,11 @@ pub unsafe fn fpu_store_m80(mut addr: i32, mut n: f64) { pub unsafe fn fpu_f64_to_f80(f: f64) -> (u64, u16) { let f = FloatParts::of_f64(f); - let mut exponent; + let exponent; // This bit is implicit (doesn't exist) in f32 and f64. // See https://en.wikipedia.org/wiki/Extended_precision#x86_extended_precision_format for normal values for this bit - let mut integer_part; + let integer_part; if f.exponent == F64_EXPONENT_NAN_INF { // all bits set (NaN and infinity) @@ -539,7 +535,7 @@ pub unsafe fn fpu_f64_to_f80(f: f64) -> (u64, u16) { } #[no_mangle] -pub unsafe fn fpu_fstenv(mut addr: i32) { +pub unsafe fn fpu_fstenv(addr: i32) { if is_osize_32() { return_on_pagefault!(writable_or_pagefault(addr, 26)); safe_write16(addr, *fpu_control_word).unwrap(); @@ -574,62 +570,62 @@ pub unsafe fn fpu_load_tag_word() -> i32 { return tag_word; } #[no_mangle] -pub unsafe fn fpu_fst(mut r: i32) { fpu_write_st(*fpu_stack_ptr as i32 + r & 7, fpu_get_st0()); } +pub unsafe fn fpu_fst(r: i32) { fpu_write_st(*fpu_stack_ptr as i32 + r & 7, fpu_get_st0()); } #[no_mangle] -pub unsafe fn fpu_fst80p(mut addr: i32) { +pub unsafe fn fpu_fst80p(addr: i32) { return_on_pagefault!(writable_or_pagefault(addr, 10)); fpu_store_m80(addr, fpu_get_st0()); fpu_pop(); } #[no_mangle] -pub unsafe fn fpu_fstcw(mut addr: i32) { +pub unsafe fn fpu_fstcw(addr: i32) { return_on_pagefault!(safe_write16(addr, *fpu_control_word)); } #[no_mangle] -pub unsafe fn fpu_fstm32(mut addr: i32) { +pub unsafe fn fpu_fstm32(addr: i32) { return_on_pagefault!(fpu_store_m32(addr, fpu_get_st0())); } #[no_mangle] -pub unsafe fn fpu_store_m32(mut addr: i32, mut x: f64) -> OrPageFault<()> { +pub unsafe fn fpu_store_m32(addr: i32, x: f64) -> OrPageFault<()> { let v = transmute(x as f32); safe_write32(addr, v) } #[no_mangle] -pub unsafe fn fpu_fstm32p(mut addr: i32) { +pub unsafe fn fpu_fstm32p(addr: i32) { fpu_fstm32(addr); fpu_pop(); } #[no_mangle] -pub unsafe fn fpu_fstm64(mut addr: i32) { +pub unsafe fn fpu_fstm64(addr: i32) { return_on_pagefault!(fpu_store_m64(addr, fpu_get_st0())); } #[no_mangle] -pub unsafe fn fpu_store_m64(mut addr: i32, mut x: f64) -> OrPageFault<()> { +pub unsafe fn fpu_store_m64(addr: i32, x: f64) -> OrPageFault<()> { let v: i64 = transmute(x); safe_write64(addr, v) } #[no_mangle] -pub unsafe fn fpu_fstm64p(mut addr: i32) { +pub unsafe fn fpu_fstm64p(addr: i32) { fpu_fstm64(addr); fpu_pop(); } #[no_mangle] -pub unsafe fn fpu_fstp(mut r: i32) { +pub unsafe fn fpu_fstp(r: i32) { fpu_fst(r); fpu_pop(); } #[no_mangle] -pub unsafe fn fpu_fsub(mut target_index: i32, mut val: f64) { - let mut st0: f64 = fpu_get_st0(); +pub unsafe fn fpu_fsub(target_index: i32, val: f64) { + let st0: f64 = fpu_get_st0(); fpu_write_st(*fpu_stack_ptr as i32 + target_index & 7, st0 - val) } #[no_mangle] -pub unsafe fn fpu_fsubr(mut target_index: i32, mut val: f64) { - let mut st0: f64 = fpu_get_st0(); +pub unsafe fn fpu_fsubr(target_index: i32, val: f64) { + let st0: f64 = fpu_get_st0(); fpu_write_st(*fpu_stack_ptr as i32 + target_index & 7, val - st0) } #[no_mangle] -pub unsafe fn fpu_ftst(mut x: f64) { +pub unsafe fn fpu_ftst(x: f64) { *fpu_status_word &= !FPU_RESULT_FLAGS; if x.is_nan() { *fpu_status_word |= FPU_C3 | FPU_C2 | FPU_C0 @@ -643,22 +639,22 @@ pub unsafe fn fpu_ftst(mut x: f64) { // TODO: unordered (x is nan, etc) } #[no_mangle] -pub unsafe fn fpu_fucom(mut r: i32) { +pub unsafe fn fpu_fucom(r: i32) { // TODO fpu_fcom(fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn fpu_fucomi(mut r: i32) { +pub unsafe fn fpu_fucomi(r: i32) { // TODO fpu_fcomi(r); } #[no_mangle] -pub unsafe fn fpu_fucomip(mut r: i32) { +pub unsafe fn fpu_fucomip(r: i32) { fpu_fucomi(r); fpu_pop(); } #[no_mangle] -pub unsafe fn fpu_fucomp(mut r: i32) { +pub unsafe fn fpu_fucomp(r: i32) { fpu_fucom(r); fpu_pop(); } @@ -669,7 +665,7 @@ pub unsafe fn fpu_fucompp() { fpu_pop(); } #[no_mangle] -pub unsafe fn fpu_fxam(mut x: f64) { +pub unsafe fn fpu_fxam(x: f64) { *fpu_status_word &= !FPU_RESULT_FLAGS; *fpu_status_word |= fpu_sign(0) << 9; if 0 != *fpu_stack_empty >> *fpu_stack_ptr & 1 { @@ -691,15 +687,15 @@ pub unsafe fn fpu_fxam(mut x: f64) { // Unsupported, Denormal } #[no_mangle] -pub unsafe fn fpu_sign(mut i: i32) -> i32 { +pub unsafe fn fpu_sign(i: i32) -> i32 { // sign of a number on the stack return *fpu_st8.offset((((*fpu_stack_ptr).wrapping_add(i as u32) & 7) << 3 | 7) as isize) as i32 >> 7; } #[no_mangle] -pub unsafe fn fpu_fxch(mut i: i32) { - let mut sti: f64 = fpu_get_sti(i); +pub unsafe fn fpu_fxch(i: i32) { + let sti: f64 = fpu_get_sti(i); fpu_write_st(*fpu_stack_ptr as i32 + i & 7, fpu_get_st0()); fpu_write_st(*fpu_stack_ptr as i32, sti); } diff --git a/src/rust/cpu2/global_pointers.rs b/src/rust/cpu2/global_pointers.rs index c21da9f4..951f1c74 100644 --- a/src/rust/cpu2/global_pointers.rs +++ b/src/rust/cpu2/global_pointers.rs @@ -1,4 +1,4 @@ -#![allow(non_upper_case_globals, unused_mut)] +#![allow(non_upper_case_globals)] use cpu2::cpu::{reg128, reg64}; diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index 58ea4c83..d42212ed 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -1,4 +1,4 @@ -#![allow(non_snake_case, unused_mut, unused_variables,)] +#![allow(non_snake_case, unused_variables)] extern "C" { #[no_mangle] @@ -37,72 +37,72 @@ use cpu2::misc_instr::{pop16, pop32s, push16, push32}; use cpu2::string::*; #[no_mangle] -pub unsafe fn instr_00_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_00_mem(addr: i32, r: i32) { SAFE_READ_WRITE8!(___, addr, add8(___, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr_00_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_00_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, add8(____0, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr16_01_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr16_01_mem(addr: i32, r: i32) { SAFE_READ_WRITE16!(___, addr, add16(___, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr16_01_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_01_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, add16(____0, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr32_01_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr32_01_mem(addr: i32, r: i32) { SAFE_READ_WRITE32!(___, addr, add32(___, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr32_01_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_01_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, add32(____0, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr_02_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); +pub unsafe fn instr_02_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, add8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr_02_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_02_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r, add8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_03_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_03_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, add16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_03_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_03_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r, add16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_03_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_03_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, add32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_03_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_03_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r, add32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr_04(mut imm8: i32) { +pub unsafe fn instr_04(imm8: i32) { *reg8.offset(AL as isize) = add8(*reg8.offset(AL as isize) as i32, imm8) as u8; } #[no_mangle] -pub unsafe fn instr16_05(mut imm16: i32) { +pub unsafe fn instr16_05(imm16: i32) { *reg16.offset(AX as isize) = add16(*reg16.offset(AX as isize) as i32, imm16) as u16; } #[no_mangle] -pub unsafe fn instr32_05(mut imm32: i32) { +pub unsafe fn instr32_05(imm32: i32) { *reg32s.offset(EAX as isize) = add32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] @@ -137,72 +137,72 @@ pub unsafe fn instr32_07() { }; } #[no_mangle] -pub unsafe fn instr_08_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_08_mem(addr: i32, r: i32) { SAFE_READ_WRITE8!(___, addr, or8(___, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr_08_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_08_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, or8(____0, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr16_09_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr16_09_mem(addr: i32, r: i32) { SAFE_READ_WRITE16!(___, addr, or16(___, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr16_09_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_09_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, or16(____0, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr32_09_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr32_09_mem(addr: i32, r: i32) { SAFE_READ_WRITE32!(___, addr, or32(___, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr32_09_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_09_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, or32(____0, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr_0A_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); +pub unsafe fn instr_0A_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, or8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr_0A_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_0A_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r, or8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_0B_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0B_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, or16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_0B_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0B_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r, or16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_0B_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_0B_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, or32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_0B_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0B_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r, or32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr_0C(mut imm8: i32) { +pub unsafe fn instr_0C(imm8: i32) { *reg8.offset(AL as isize) = or8(*reg8.offset(AL as isize) as i32, imm8) as u8; } #[no_mangle] -pub unsafe fn instr16_0D(mut imm16: i32) { +pub unsafe fn instr16_0D(imm16: i32) { *reg16.offset(AX as isize) = or16(*reg16.offset(AX as isize) as i32, imm16) as u16; } #[no_mangle] -pub unsafe fn instr32_0D(mut imm32: i32) { +pub unsafe fn instr32_0D(imm32: i32) { *reg32s.offset(EAX as isize) = or32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] @@ -218,72 +218,72 @@ pub unsafe fn instr16_0F() { run_instruction0f_16(return_on_pagefault!(read_imm8 #[no_mangle] pub unsafe fn instr32_0F() { run_instruction0f_32(return_on_pagefault!(read_imm8())); } #[no_mangle] -pub unsafe fn instr_10_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_10_mem(addr: i32, r: i32) { SAFE_READ_WRITE8!(___, addr, adc8(___, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr_10_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_10_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, adc8(____0, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr16_11_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr16_11_mem(addr: i32, r: i32) { SAFE_READ_WRITE16!(___, addr, adc16(___, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr16_11_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_11_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, adc16(____0, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr32_11_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr32_11_mem(addr: i32, r: i32) { SAFE_READ_WRITE32!(___, addr, adc32(___, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr32_11_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_11_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, adc32(____0, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr_12_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); +pub unsafe fn instr_12_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, adc8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr_12_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_12_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r, adc8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_13_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_13_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, adc16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_13_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_13_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r, adc16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_13_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_13_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, adc32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_13_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_13_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r, adc32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr_14(mut imm8: i32) { +pub unsafe fn instr_14(imm8: i32) { *reg8.offset(AL as isize) = adc8(*reg8.offset(AL as isize) as i32, imm8) as u8; } #[no_mangle] -pub unsafe fn instr16_15(mut imm16: i32) { +pub unsafe fn instr16_15(imm16: i32) { *reg16.offset(AX as isize) = adc16(*reg16.offset(AX as isize) as i32, imm16) as u16; } #[no_mangle] -pub unsafe fn instr32_15(mut imm32: i32) { +pub unsafe fn instr32_15(imm32: i32) { *reg32s.offset(EAX as isize) = adc32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] @@ -318,72 +318,72 @@ pub unsafe fn instr32_17() { }; } #[no_mangle] -pub unsafe fn instr_18_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_18_mem(addr: i32, r: i32) { SAFE_READ_WRITE8!(___, addr, sbb8(___, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr_18_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_18_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, sbb8(____0, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr16_19_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr16_19_mem(addr: i32, r: i32) { SAFE_READ_WRITE16!(___, addr, sbb16(___, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr16_19_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_19_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, sbb16(____0, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr32_19_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr32_19_mem(addr: i32, r: i32) { SAFE_READ_WRITE32!(___, addr, sbb32(___, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr32_19_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_19_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, sbb32(____0, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr_1A_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); +pub unsafe fn instr_1A_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, sbb8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr_1A_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_1A_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r, sbb8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_1B_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_1B_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, sbb16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_1B_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_1B_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r, sbb16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_1B_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_1B_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, sbb32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_1B_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_1B_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r, sbb32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr_1C(mut imm8: i32) { +pub unsafe fn instr_1C(imm8: i32) { *reg8.offset(AL as isize) = sbb8(*reg8.offset(AL as isize) as i32, imm8) as u8; } #[no_mangle] -pub unsafe fn instr16_1D(mut imm16: i32) { +pub unsafe fn instr16_1D(imm16: i32) { *reg16.offset(AX as isize) = sbb16(*reg16.offset(AX as isize) as i32, imm16) as u16; } #[no_mangle] -pub unsafe fn instr32_1D(mut imm32: i32) { +pub unsafe fn instr32_1D(imm32: i32) { *reg32s.offset(EAX as isize) = sbb32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] @@ -418,72 +418,72 @@ pub unsafe fn instr32_1F() { }; } #[no_mangle] -pub unsafe fn instr_20_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_20_mem(addr: i32, r: i32) { SAFE_READ_WRITE8!(___, addr, and8(___, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr_20_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_20_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, and8(____0, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr16_21_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr16_21_mem(addr: i32, r: i32) { SAFE_READ_WRITE16!(___, addr, and16(___, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr16_21_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_21_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, and16(____0, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr32_21_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr32_21_mem(addr: i32, r: i32) { SAFE_READ_WRITE32!(___, addr, and32(___, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr32_21_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_21_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, and32(____0, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr_22_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); +pub unsafe fn instr_22_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, and8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr_22_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_22_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r, and8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_23_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_23_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, and16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_23_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_23_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r, and16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_23_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_23_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, and32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_23_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_23_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r, and32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr_24(mut imm8: i32) { +pub unsafe fn instr_24(imm8: i32) { *reg8.offset(AL as isize) = and8(*reg8.offset(AL as isize) as i32, imm8) as u8; } #[no_mangle] -pub unsafe fn instr16_25(mut imm16: i32) { +pub unsafe fn instr16_25(imm16: i32) { *reg16.offset(AX as isize) = and16(*reg16.offset(AX as isize) as i32, imm16) as u16; } #[no_mangle] -pub unsafe fn instr32_25(mut imm32: i32) { +pub unsafe fn instr32_25(imm32: i32) { *reg32s.offset(EAX as isize) = and32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] @@ -491,72 +491,72 @@ pub unsafe fn instr_26() { segment_prefix_op(ES); } #[no_mangle] pub unsafe fn instr_27() { bcd_daa(); } #[no_mangle] -pub unsafe fn instr_28_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_28_mem(addr: i32, r: i32) { SAFE_READ_WRITE8!(___, addr, sub8(___, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr_28_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_28_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, sub8(____0, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr16_29_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr16_29_mem(addr: i32, r: i32) { SAFE_READ_WRITE16!(___, addr, sub16(___, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr16_29_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_29_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, sub16(____0, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr32_29_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr32_29_mem(addr: i32, r: i32) { SAFE_READ_WRITE32!(___, addr, sub32(___, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr32_29_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_29_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, sub32(____0, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr_2A_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); +pub unsafe fn instr_2A_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, sub8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr_2A_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_2A_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r, sub8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_2B_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_2B_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, sub16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_2B_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_2B_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r, sub16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_2B_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_2B_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, sub32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_2B_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_2B_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r, sub32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr_2C(mut imm8: i32) { +pub unsafe fn instr_2C(imm8: i32) { *reg8.offset(AL as isize) = sub8(*reg8.offset(AL as isize) as i32, imm8) as u8; } #[no_mangle] -pub unsafe fn instr16_2D(mut imm16: i32) { +pub unsafe fn instr16_2D(imm16: i32) { *reg16.offset(AX as isize) = sub16(*reg16.offset(AX as isize) as i32, imm16) as u16; } #[no_mangle] -pub unsafe fn instr32_2D(mut imm32: i32) { +pub unsafe fn instr32_2D(imm32: i32) { *reg32s.offset(EAX as isize) = sub32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] @@ -564,72 +564,72 @@ pub unsafe fn instr_2E() { segment_prefix_op(CS); } #[no_mangle] pub unsafe fn instr_2F() { bcd_das(); } #[no_mangle] -pub unsafe fn instr_30_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_30_mem(addr: i32, r: i32) { SAFE_READ_WRITE8!(___, addr, xor8(___, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr_30_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_30_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, xor8(____0, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr16_31_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr16_31_mem(addr: i32, r: i32) { SAFE_READ_WRITE16!(___, addr, xor16(___, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr16_31_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_31_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, xor16(____0, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr32_31_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr32_31_mem(addr: i32, r: i32) { SAFE_READ_WRITE32!(___, addr, xor32(___, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr32_31_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_31_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, xor32(____0, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr_32_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); +pub unsafe fn instr_32_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, xor8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr_32_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_32_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r, xor8(read_reg8(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_33_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_33_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, xor16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_33_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_33_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r, xor16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_33_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_33_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, xor32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_33_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_33_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r, xor32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr_34(mut imm8: i32) { +pub unsafe fn instr_34(imm8: i32) { *reg8.offset(AL as isize) = xor8(*reg8.offset(AL as isize) as i32, imm8) as u8; } #[no_mangle] -pub unsafe fn instr16_35(mut imm16: i32) { +pub unsafe fn instr16_35(imm16: i32) { *reg16.offset(AX as isize) = xor16(*reg16.offset(AX as isize) as i32, imm16) as u16; } #[no_mangle] -pub unsafe fn instr32_35(mut imm32: i32) { +pub unsafe fn instr32_35(imm32: i32) { *reg32s.offset(EAX as isize) = xor32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] @@ -637,71 +637,71 @@ pub unsafe fn instr_36() { segment_prefix_op(SS); } #[no_mangle] pub unsafe fn instr_37() { bcd_aaa(); } #[no_mangle] -pub unsafe fn instr_38_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); +pub unsafe fn instr_38_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read8(addr)); cmp8(____0, read_reg8(r)); } #[no_mangle] -pub unsafe fn instr_38_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_38_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); cmp8(____0, read_reg8(r)); } #[no_mangle] -pub unsafe fn instr16_39_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_39_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmp16(____0, read_reg16(r)); } #[no_mangle] -pub unsafe fn instr16_39_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_39_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); cmp16(____0, read_reg16(r)); } #[no_mangle] -pub unsafe fn instr32_39_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_39_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmp32(____0, read_reg32(r)); } #[no_mangle] -pub unsafe fn instr32_39_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_39_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); cmp32(____0, read_reg32(r)); } #[no_mangle] -pub unsafe fn instr_3A_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); +pub unsafe fn instr_3A_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read8(addr)); cmp8(read_reg8(r), ____0); } #[no_mangle] -pub unsafe fn instr_3A_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_3A_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); cmp8(read_reg8(r), ____0); } #[no_mangle] -pub unsafe fn instr16_3B_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_3B_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmp16(read_reg16(r), ____0); } #[no_mangle] -pub unsafe fn instr16_3B_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_3B_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); cmp16(read_reg16(r), ____0); } #[no_mangle] -pub unsafe fn instr32_3B_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_3B_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmp32(read_reg32(r), ____0); } #[no_mangle] -pub unsafe fn instr32_3B_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_3B_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); cmp32(read_reg32(r), ____0); } #[no_mangle] -pub unsafe fn instr_3C(mut imm8: i32) { cmp8(*reg8.offset(AL as isize) as i32, imm8); } +pub unsafe fn instr_3C(imm8: i32) { cmp8(*reg8.offset(AL as isize) as i32, imm8); } #[no_mangle] -pub unsafe fn instr16_3D(mut imm16: i32) { cmp16(*reg16.offset(AX as isize) as i32, imm16); } +pub unsafe fn instr16_3D(imm16: i32) { cmp16(*reg16.offset(AX as isize) as i32, imm16); } #[no_mangle] -pub unsafe fn instr32_3D(mut imm32: i32) { cmp32(*reg32s.offset(EAX as isize), imm32); } +pub unsafe fn instr32_3D(imm32: i32) { cmp32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] pub unsafe fn instr_3E() { segment_prefix_op(DS); } #[no_mangle] @@ -887,23 +887,23 @@ pub unsafe fn instr16_61() { popa16(); } #[no_mangle] pub unsafe fn instr32_61() { popa32(); } #[no_mangle] -pub unsafe fn instr_62_reg(mut r2: i32, mut r: i32) { +pub unsafe fn instr_62_reg(r2: i32, r: i32) { // bound dbg_log!("Unimplemented BOUND instruction"); dbg_assert!(0 != 0); } #[no_mangle] -pub unsafe fn instr_62_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_62_mem(addr: i32, r: i32) { dbg_log!("Unimplemented BOUND instruction"); dbg_assert!(0 != 0); } #[no_mangle] -pub unsafe fn instr_63_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_63_mem(addr: i32, r: i32) { SAFE_READ_WRITE16!(___, addr, arpl(___, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr_63_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr_63_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, arpl(____0, read_reg16(r))); } #[no_mangle] @@ -926,51 +926,51 @@ pub unsafe fn instr_67() { *prefixes = 0; } #[no_mangle] -pub unsafe fn instr16_68(mut imm16: i32) { +pub unsafe fn instr16_68(imm16: i32) { return_on_pagefault!(push16(imm16)); } #[no_mangle] -pub unsafe fn instr32_68(mut imm32: i32) { +pub unsafe fn instr32_68(imm32: i32) { return_on_pagefault!(push32(imm32)); } #[no_mangle] -pub unsafe fn instr16_69_mem(mut addr: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr16_69_mem(addr: i32, r: i32, imm: i32) { write_reg16(r, imul_reg16(return_on_pagefault!(safe_read16(addr)), imm)); } #[no_mangle] -pub unsafe fn instr16_69_reg(mut r1: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr16_69_reg(r1: i32, r: i32, imm: i32) { write_reg16(r, imul_reg16(read_reg16(r1), imm)); } #[no_mangle] -pub unsafe fn instr32_69_mem(mut addr: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr32_69_mem(addr: i32, r: i32, imm: i32) { write_reg32(r, imul_reg32(return_on_pagefault!(safe_read32s(addr)), imm)); } #[no_mangle] -pub unsafe fn instr32_69_reg(mut r1: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr32_69_reg(r1: i32, r: i32, imm: i32) { write_reg32(r, imul_reg32(read_reg32(r1), imm)); } #[no_mangle] -pub unsafe fn instr16_6A(mut imm8: i32) { +pub unsafe fn instr16_6A(imm8: i32) { return_on_pagefault!(push16(imm8)); } #[no_mangle] -pub unsafe fn instr32_6A(mut imm8: i32) { +pub unsafe fn instr32_6A(imm8: i32) { return_on_pagefault!(push32(imm8)); } #[no_mangle] -pub unsafe fn instr16_6B_mem(mut addr: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr16_6B_mem(addr: i32, r: i32, imm: i32) { write_reg16(r, imul_reg16(return_on_pagefault!(safe_read16(addr)), imm)); } #[no_mangle] -pub unsafe fn instr16_6B_reg(mut r1: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr16_6B_reg(r1: i32, r: i32, imm: i32) { write_reg16(r, imul_reg16(read_reg16(r1), imm)); } #[no_mangle] -pub unsafe fn instr32_6B_mem(mut addr: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr32_6B_mem(addr: i32, r: i32, imm: i32) { write_reg32(r, imul_reg32(return_on_pagefault!(safe_read32s(addr)), imm)); } #[no_mangle] -pub unsafe fn instr32_6B_reg(mut r1: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr32_6B_reg(r1: i32, r: i32, imm: i32) { write_reg32(r, imul_reg32(read_reg32(r1), imm)); } #[no_mangle] @@ -986,526 +986,526 @@ pub unsafe fn instr16_6F() { outsw_no_rep(); } #[no_mangle] pub unsafe fn instr32_6F() { outsd_no_rep(); } #[no_mangle] -pub unsafe fn instr_80_0_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_80_0_mem(addr: i32, imm: i32) { SAFE_READ_WRITE8!(___, addr, add8(___, imm)); } #[no_mangle] -pub unsafe fn instr_80_0_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_80_0_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, add8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_80_1_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_80_1_mem(addr: i32, imm: i32) { SAFE_READ_WRITE8!(___, addr, or8(___, imm)); } #[no_mangle] -pub unsafe fn instr_80_1_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_80_1_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, or8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_80_2_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_80_2_mem(addr: i32, imm: i32) { SAFE_READ_WRITE8!(___, addr, adc8(___, imm)); } #[no_mangle] -pub unsafe fn instr_80_2_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_80_2_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, adc8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_80_3_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_80_3_mem(addr: i32, imm: i32) { SAFE_READ_WRITE8!(___, addr, sbb8(___, imm)); } #[no_mangle] -pub unsafe fn instr_80_3_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_80_3_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, sbb8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_80_4_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_80_4_mem(addr: i32, imm: i32) { SAFE_READ_WRITE8!(___, addr, and8(___, imm)); } #[no_mangle] -pub unsafe fn instr_80_4_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_80_4_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, and8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_80_5_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_80_5_mem(addr: i32, imm: i32) { SAFE_READ_WRITE8!(___, addr, sub8(___, imm)); } #[no_mangle] -pub unsafe fn instr_80_5_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_80_5_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, sub8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_80_6_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_80_6_mem(addr: i32, imm: i32) { SAFE_READ_WRITE8!(___, addr, xor8(___, imm)); } #[no_mangle] -pub unsafe fn instr_80_6_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_80_6_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, xor8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_80_7_reg(mut r: i32, mut imm: i32) { cmp8(read_reg8(r), imm); } +pub unsafe fn instr_80_7_reg(r: i32, imm: i32) { cmp8(read_reg8(r), imm); } #[no_mangle] -pub unsafe fn instr_80_7_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_80_7_mem(addr: i32, imm: i32) { cmp8(return_on_pagefault!(safe_read8(addr)), imm); } #[no_mangle] -pub unsafe fn instr16_81_0_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_81_0_mem(addr: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, add16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_81_0_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_81_0_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, add16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_81_1_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_81_1_mem(addr: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, or16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_81_1_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_81_1_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, or16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_81_2_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_81_2_mem(addr: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, adc16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_81_2_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_81_2_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, adc16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_81_3_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_81_3_mem(addr: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, sbb16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_81_3_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_81_3_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, sbb16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_81_4_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_81_4_mem(addr: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, and16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_81_4_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_81_4_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, and16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_81_5_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_81_5_mem(addr: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, sub16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_81_5_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_81_5_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, sub16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_81_6_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_81_6_mem(addr: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, xor16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_81_6_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_81_6_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, xor16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_81_7_reg(mut r: i32, mut imm: i32) { cmp16(read_reg16(r), imm); } +pub unsafe fn instr16_81_7_reg(r: i32, imm: i32) { cmp16(read_reg16(r), imm); } #[no_mangle] -pub unsafe fn instr16_81_7_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_81_7_mem(addr: i32, imm: i32) { cmp16(return_on_pagefault!(safe_read16(addr)), imm); } #[no_mangle] -pub unsafe fn instr32_81_0_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_81_0_mem(addr: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, add32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_81_0_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_81_0_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, add32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_81_1_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_81_1_mem(addr: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, or32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_81_1_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_81_1_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, or32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_81_2_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_81_2_mem(addr: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, adc32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_81_2_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_81_2_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, adc32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_81_3_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_81_3_mem(addr: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, sbb32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_81_3_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_81_3_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, sbb32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_81_4_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_81_4_mem(addr: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, and32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_81_4_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_81_4_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, and32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_81_5_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_81_5_mem(addr: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, sub32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_81_5_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_81_5_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, sub32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_81_6_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_81_6_mem(addr: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, xor32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_81_6_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_81_6_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, xor32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_81_7_reg(mut r: i32, mut imm: i32) { cmp32(read_reg32(r), imm); } +pub unsafe fn instr32_81_7_reg(r: i32, imm: i32) { cmp32(read_reg32(r), imm); } #[no_mangle] -pub unsafe fn instr32_81_7_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_81_7_mem(addr: i32, imm: i32) { cmp32(return_on_pagefault!(safe_read32s(addr)), imm); } #[no_mangle] -pub unsafe fn instr_82_0_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_82_0_mem(addr: i32, imm: i32) { SAFE_READ_WRITE8!(___, addr, add8(___, imm)); } #[no_mangle] -pub unsafe fn instr_82_0_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_82_0_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, add8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_82_1_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_82_1_mem(addr: i32, imm: i32) { SAFE_READ_WRITE8!(___, addr, or8(___, imm)); } #[no_mangle] -pub unsafe fn instr_82_1_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_82_1_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, or8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_82_2_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_82_2_mem(addr: i32, imm: i32) { SAFE_READ_WRITE8!(___, addr, adc8(___, imm)); } #[no_mangle] -pub unsafe fn instr_82_2_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_82_2_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, adc8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_82_3_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_82_3_mem(addr: i32, imm: i32) { SAFE_READ_WRITE8!(___, addr, sbb8(___, imm)); } #[no_mangle] -pub unsafe fn instr_82_3_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_82_3_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, sbb8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_82_4_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_82_4_mem(addr: i32, imm: i32) { SAFE_READ_WRITE8!(___, addr, and8(___, imm)); } #[no_mangle] -pub unsafe fn instr_82_4_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_82_4_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, and8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_82_5_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_82_5_mem(addr: i32, imm: i32) { SAFE_READ_WRITE8!(___, addr, sub8(___, imm)); } #[no_mangle] -pub unsafe fn instr_82_5_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_82_5_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, sub8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_82_6_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_82_6_mem(addr: i32, imm: i32) { SAFE_READ_WRITE8!(___, addr, xor8(___, imm)); } #[no_mangle] -pub unsafe fn instr_82_6_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_82_6_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, xor8(____0, imm)); } #[no_mangle] -pub unsafe fn instr_82_7_reg(mut r: i32, mut imm: i32) { cmp8(read_reg8(r), imm); } +pub unsafe fn instr_82_7_reg(r: i32, imm: i32) { cmp8(read_reg8(r), imm); } #[no_mangle] -pub unsafe fn instr_82_7_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_82_7_mem(addr: i32, imm: i32) { cmp8(return_on_pagefault!(safe_read8(addr)), imm); } #[no_mangle] -pub unsafe fn instr16_83_0_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_83_0_mem(addr: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, add16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_83_0_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_83_0_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, add16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_83_1_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_83_1_mem(addr: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, or16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_83_1_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_83_1_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, or16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_83_2_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_83_2_mem(addr: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, adc16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_83_2_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_83_2_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, adc16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_83_3_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_83_3_mem(addr: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, sbb16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_83_3_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_83_3_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, sbb16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_83_4_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_83_4_mem(addr: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, and16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_83_4_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_83_4_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, and16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_83_5_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_83_5_mem(addr: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, sub16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_83_5_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_83_5_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, sub16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_83_6_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_83_6_mem(addr: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, xor16(___, imm)); } #[no_mangle] -pub unsafe fn instr16_83_6_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_83_6_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, xor16(____0, imm)); } #[no_mangle] -pub unsafe fn instr16_83_7_reg(mut r: i32, mut imm: i32) { cmp16(read_reg16(r), imm); } +pub unsafe fn instr16_83_7_reg(r: i32, imm: i32) { cmp16(read_reg16(r), imm); } #[no_mangle] -pub unsafe fn instr16_83_7_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_83_7_mem(addr: i32, imm: i32) { cmp16(return_on_pagefault!(safe_read16(addr)), imm); } #[no_mangle] -pub unsafe fn instr32_83_0_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_83_0_mem(addr: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, add32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_83_0_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_83_0_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, add32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_83_1_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_83_1_mem(addr: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, or32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_83_1_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_83_1_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, or32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_83_2_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_83_2_mem(addr: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, adc32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_83_2_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_83_2_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, adc32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_83_3_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_83_3_mem(addr: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, sbb32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_83_3_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_83_3_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, sbb32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_83_4_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_83_4_mem(addr: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, and32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_83_4_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_83_4_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, and32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_83_5_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_83_5_mem(addr: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, sub32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_83_5_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_83_5_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, sub32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_83_6_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_83_6_mem(addr: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, xor32(___, imm)); } #[no_mangle] -pub unsafe fn instr32_83_6_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_83_6_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, xor32(____0, imm)); } #[no_mangle] -pub unsafe fn instr32_83_7_reg(mut r: i32, mut imm: i32) { cmp32(read_reg32(r), imm); } +pub unsafe fn instr32_83_7_reg(r: i32, imm: i32) { cmp32(read_reg32(r), imm); } #[no_mangle] -pub unsafe fn instr32_83_7_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_83_7_mem(addr: i32, imm: i32) { cmp32(return_on_pagefault!(safe_read32s(addr)), imm); } #[no_mangle] -pub unsafe fn instr_84_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); +pub unsafe fn instr_84_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read8(addr)); test8(____0, read_reg8(r)); } #[no_mangle] -pub unsafe fn instr_84_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_84_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); test8(____0, read_reg8(r)); } #[no_mangle] -pub unsafe fn instr16_85_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_85_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); test16(____0, read_reg16(r)); } #[no_mangle] -pub unsafe fn instr16_85_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_85_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); test16(____0, read_reg16(r)); } #[no_mangle] -pub unsafe fn instr32_85_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_85_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); test32(____0, read_reg32(r)); } #[no_mangle] -pub unsafe fn instr32_85_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_85_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); test32(____0, read_reg32(r)); } #[no_mangle] -pub unsafe fn instr_86_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_86_mem(addr: i32, r: i32) { SAFE_READ_WRITE8!(___, addr, xchg8(___, get_reg8_index(r))); } #[no_mangle] -pub unsafe fn instr_86_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_86_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, xchg8(____0, get_reg8_index(r))); } #[no_mangle] -pub unsafe fn instr16_87_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr16_87_mem(addr: i32, r: i32) { SAFE_READ_WRITE16!(___, addr, xchg16(___, get_reg16_index(r))); } #[no_mangle] -pub unsafe fn instr16_87_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_87_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, xchg16(____0, get_reg16_index(r))); } #[no_mangle] -pub unsafe fn instr32_87_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr32_87_mem(addr: i32, r: i32) { SAFE_READ_WRITE32!(___, addr, xchg32(___, r)); } #[no_mangle] -pub unsafe fn instr32_87_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_87_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, xchg32(____0, r)); } #[no_mangle] -pub unsafe fn instr_88_reg(mut r2: i32, mut r: i32) { write_reg8(r2, read_reg8(r)); } +pub unsafe fn instr_88_reg(r2: i32, r: i32) { write_reg8(r2, read_reg8(r)); } #[no_mangle] -pub unsafe fn instr_88_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_88_mem(addr: i32, r: i32) { return_on_pagefault!(safe_write8(addr, read_reg8(r))); } #[no_mangle] -pub unsafe fn instr16_89_reg(mut r2: i32, mut r: i32) { write_reg16(r2, read_reg16(r)); } +pub unsafe fn instr16_89_reg(r2: i32, r: i32) { write_reg16(r2, read_reg16(r)); } #[no_mangle] -pub unsafe fn instr16_89_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr16_89_mem(addr: i32, r: i32) { return_on_pagefault!(safe_write16(addr, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr32_89_reg(mut r2: i32, mut r: i32) { write_reg32(r2, read_reg32(r)); } +pub unsafe fn instr32_89_reg(r2: i32, r: i32) { write_reg32(r2, read_reg32(r)); } #[no_mangle] -pub unsafe fn instr32_89_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr32_89_mem(addr: i32, r: i32) { return_on_pagefault!(safe_write32(addr, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr_8A_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); +pub unsafe fn instr_8A_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg8(r, ____0); } #[no_mangle] -pub unsafe fn instr_8A_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_8A_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r, ____0); } #[no_mangle] -pub unsafe fn instr16_8B_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_8B_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, ____0); } #[no_mangle] -pub unsafe fn instr16_8B_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_8B_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r, ____0); } #[no_mangle] -pub unsafe fn instr32_8B_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_8B_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, ____0); } #[no_mangle] -pub unsafe fn instr32_8B_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_8B_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r, ____0); } #[no_mangle] -pub unsafe fn instr_8C_check_sreg(mut seg: i32) -> bool { +pub unsafe fn instr_8C_check_sreg(seg: i32) -> bool { if seg >= 6 { dbg_log!("mov sreg #ud"); trigger_ud(); @@ -1516,36 +1516,36 @@ pub unsafe fn instr_8C_check_sreg(mut seg: i32) -> bool { }; } #[no_mangle] -pub unsafe fn instr16_8C_reg(mut r: i32, mut seg: i32) { +pub unsafe fn instr16_8C_reg(r: i32, seg: i32) { if instr_8C_check_sreg(seg) { write_reg16(r, *sreg.offset(seg as isize) as i32); }; } #[no_mangle] -pub unsafe fn instr16_8C_mem(mut addr: i32, mut seg: i32) { +pub unsafe fn instr16_8C_mem(addr: i32, seg: i32) { if instr_8C_check_sreg(seg) { return_on_pagefault!(safe_write16(addr, *sreg.offset(seg as isize) as i32)); }; } #[no_mangle] -pub unsafe fn instr32_8C_reg(mut r: i32, mut seg: i32) { +pub unsafe fn instr32_8C_reg(r: i32, seg: i32) { if instr_8C_check_sreg(seg) { write_reg32(r, *sreg.offset(seg as isize) as i32); }; } #[no_mangle] -pub unsafe fn instr32_8C_mem(mut addr: i32, mut seg: i32) { +pub unsafe fn instr32_8C_mem(addr: i32, seg: i32) { if instr_8C_check_sreg(seg) { return_on_pagefault!(safe_write32(addr, *sreg.offset(seg as isize) as i32)); }; } #[no_mangle] -pub unsafe fn instr16_8D_reg(mut r: i32, mut r2: i32) { +pub unsafe fn instr16_8D_reg(r: i32, r2: i32) { dbg_log!("lea #ud"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_8D_mem(modrm_byte: i32, mut r: i32) { +pub unsafe fn instr16_8D_mem(modrm_byte: i32, r: i32) { // lea *prefixes = (*prefixes as i32 | SEG_PREFIX_ZERO) as u8; if let Ok(addr) = modrm_resolve(modrm_byte) { @@ -1554,12 +1554,12 @@ pub unsafe fn instr16_8D_mem(modrm_byte: i32, mut r: i32) { *prefixes = 0; } #[no_mangle] -pub unsafe fn instr32_8D_reg(mut r: i32, mut r2: i32) { +pub unsafe fn instr32_8D_reg(r: i32, r2: i32) { dbg_log!("lea #ud"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr32_8D_mem(modrm_byte: i32, mut r: i32) { +pub unsafe fn instr32_8D_mem(modrm_byte: i32, r: i32) { // lea // override prefix, so modrm_resolve does not return the segment part *prefixes = (*prefixes as i32 | SEG_PREFIX_ZERO) as u8; @@ -1569,7 +1569,7 @@ pub unsafe fn instr32_8D_mem(modrm_byte: i32, mut r: i32) { *prefixes = 0; } #[no_mangle] -pub unsafe fn instr_8E_helper(mut data: i32, mut mod_0: i32) { +pub unsafe fn instr_8E_helper(data: i32, mod_0: i32) { if mod_0 == ES || mod_0 == SS || mod_0 == DS || mod_0 == FS || mod_0 == GS { if !switch_seg(mod_0, data) { return; @@ -1581,13 +1581,13 @@ pub unsafe fn instr_8E_helper(mut data: i32, mut mod_0: i32) { }; } #[no_mangle] -pub unsafe fn instr_8E_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr_8E_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); instr_8E_helper(____0, r); } #[no_mangle] -pub unsafe fn instr_8E_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr_8E_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); instr_8E_helper(____0, r); } @@ -1603,7 +1603,7 @@ pub unsafe fn instr16_8F_0_mem(modrm_byte: i32) { }, Ok(addr) => { adjust_stack_reg(-2); - let mut stack_value: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0))); + let stack_value: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0))); return_on_pagefault!(safe_write16(addr, stack_value)); adjust_stack_reg(2); }, @@ -1613,13 +1613,13 @@ pub unsafe fn instr16_8F_0_mem(modrm_byte: i32) { #[no_mangle] pub unsafe fn instr16_8F_0_mem_jit(addr: i32) { adjust_stack_reg(-2); - let mut stack_value: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0))); + let stack_value: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0))); return_on_pagefault!(safe_write16(addr, stack_value)); adjust_stack_reg(2); } #[no_mangle] -pub unsafe fn instr16_8F_0_reg(mut r: i32) { write_reg16(r, return_on_pagefault!(pop16())); } +pub unsafe fn instr16_8F_0_reg(r: i32) { write_reg16(r, return_on_pagefault!(pop16())); } #[no_mangle] pub unsafe fn instr32_8F_0_mem(modrm_byte: i32) { // Update esp *before* resolving the address @@ -1631,7 +1631,7 @@ pub unsafe fn instr32_8F_0_mem(modrm_byte: i32) { }, Ok(addr) => { adjust_stack_reg(-4); - let mut stack_value: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0))); + let stack_value: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0))); return_on_pagefault!(safe_write32(addr, stack_value)); adjust_stack_reg(4); }, @@ -1641,13 +1641,13 @@ pub unsafe fn instr32_8F_0_mem(modrm_byte: i32) { #[no_mangle] pub unsafe fn instr32_8F_0_mem_jit(addr: i32) { adjust_stack_reg(-4); - let mut stack_value: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0))); + let stack_value: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0))); return_on_pagefault!(safe_write32(addr, stack_value)); adjust_stack_reg(4); } #[no_mangle] -pub unsafe fn instr32_8F_0_reg(mut r: i32) { write_reg32(r, return_on_pagefault!(pop32s())); } +pub unsafe fn instr32_8F_0_reg(r: i32) { write_reg32(r, return_on_pagefault!(pop32s())); } #[no_mangle] pub unsafe fn instr_90() {} @@ -1690,13 +1690,13 @@ pub unsafe fn instr16_99() { #[no_mangle] pub unsafe fn instr32_99() { *reg32s.offset(EDX as isize) = *reg32s.offset(EAX as isize) >> 31; } #[no_mangle] -pub unsafe fn instr16_9A(mut new_ip: i32, mut new_cs: i32) { +pub unsafe fn instr16_9A(new_ip: i32, new_cs: i32) { // callf far_jump(new_ip, new_cs, true); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] -pub unsafe fn instr32_9A(mut new_ip: i32, mut new_cs: i32) { +pub unsafe fn instr32_9A(new_ip: i32, new_cs: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { if 0 != new_ip as u32 & 4294901760 { dbg_assert!(0 != 0); @@ -1798,24 +1798,24 @@ pub unsafe fn instr_9F() { *reg8.offset(AH as isize) = get_eflags() as u8; } #[no_mangle] -pub unsafe fn instr_A0(mut moffs: i32) { +pub unsafe fn instr_A0(moffs: i32) { // mov - let mut data: i32 = return_on_pagefault!(safe_read8(get_seg_prefix_ds(moffs))); + let data: i32 = return_on_pagefault!(safe_read8(get_seg_prefix_ds(moffs))); *reg8.offset(AL as isize) = data as u8; } #[no_mangle] -pub unsafe fn instr16_A1(mut moffs: i32) { +pub unsafe fn instr16_A1(moffs: i32) { // mov - let mut data: i32 = return_on_pagefault!(safe_read16(get_seg_prefix_ds(moffs))); + let data: i32 = return_on_pagefault!(safe_read16(get_seg_prefix_ds(moffs))); *reg16.offset(AX as isize) = data as u16; } #[no_mangle] -pub unsafe fn instr32_A1(mut moffs: i32) { - let mut data: i32 = return_on_pagefault!(safe_read32s(get_seg_prefix_ds(moffs))); +pub unsafe fn instr32_A1(moffs: i32) { + let data: i32 = return_on_pagefault!(safe_read32s(get_seg_prefix_ds(moffs))); *reg32s.offset(EAX as isize) = data; } #[no_mangle] -pub unsafe fn instr_A2(mut moffs: i32) { +pub unsafe fn instr_A2(moffs: i32) { // mov return_on_pagefault!(safe_write8( get_seg_prefix_ds(moffs), @@ -1823,7 +1823,7 @@ pub unsafe fn instr_A2(mut moffs: i32) { )); } #[no_mangle] -pub unsafe fn instr16_A3(mut moffs: i32) { +pub unsafe fn instr16_A3(moffs: i32) { // mov return_on_pagefault!(safe_write16( get_seg_prefix_ds(moffs), @@ -1831,7 +1831,7 @@ pub unsafe fn instr16_A3(mut moffs: i32) { )); } #[no_mangle] -pub unsafe fn instr32_A3(mut moffs: i32) { +pub unsafe fn instr32_A3(moffs: i32) { return_on_pagefault!(safe_write32( get_seg_prefix_ds(moffs), *reg32s.offset(EAX as isize) @@ -1850,11 +1850,11 @@ pub unsafe fn instr16_A7() { cmpsw_no_rep(); } #[no_mangle] pub unsafe fn instr32_A7() { cmpsd_no_rep(); } #[no_mangle] -pub unsafe fn instr_A8(mut imm8: i32) { test8(*reg8.offset(AL as isize) as i32, imm8); } +pub unsafe fn instr_A8(imm8: i32) { test8(*reg8.offset(AL as isize) as i32, imm8); } #[no_mangle] -pub unsafe fn instr16_A9(mut imm16: i32) { test16(*reg16.offset(AX as isize) as i32, imm16); } +pub unsafe fn instr16_A9(imm16: i32) { test16(*reg16.offset(AX as isize) as i32, imm16); } #[no_mangle] -pub unsafe fn instr32_A9(mut imm32: i32) { test32(*reg32s.offset(EAX as isize), imm32); } +pub unsafe fn instr32_A9(imm32: i32) { test32(*reg32s.offset(EAX as isize), imm32); } #[no_mangle] pub unsafe fn instr_AA() { stosb_no_rep(); } #[no_mangle] @@ -1874,282 +1874,282 @@ pub unsafe fn instr16_AF() { scasw_no_rep(); } #[no_mangle] pub unsafe fn instr32_AF() { scasd_no_rep(); } #[no_mangle] -pub unsafe fn instr_B0(mut imm8: i32) { *reg8.offset(AL as isize) = imm8 as u8; } +pub unsafe fn instr_B0(imm8: i32) { *reg8.offset(AL as isize) = imm8 as u8; } #[no_mangle] -pub unsafe fn instr_B1(mut imm8: i32) { *reg8.offset(CL as isize) = imm8 as u8; } +pub unsafe fn instr_B1(imm8: i32) { *reg8.offset(CL as isize) = imm8 as u8; } #[no_mangle] -pub unsafe fn instr_B2(mut imm8: i32) { *reg8.offset(DL as isize) = imm8 as u8; } +pub unsafe fn instr_B2(imm8: i32) { *reg8.offset(DL as isize) = imm8 as u8; } #[no_mangle] -pub unsafe fn instr_B3(mut imm8: i32) { *reg8.offset(BL as isize) = imm8 as u8; } +pub unsafe fn instr_B3(imm8: i32) { *reg8.offset(BL as isize) = imm8 as u8; } #[no_mangle] -pub unsafe fn instr_B4(mut imm8: i32) { *reg8.offset(AH as isize) = imm8 as u8; } +pub unsafe fn instr_B4(imm8: i32) { *reg8.offset(AH as isize) = imm8 as u8; } #[no_mangle] -pub unsafe fn instr_B5(mut imm8: i32) { *reg8.offset(CH as isize) = imm8 as u8; } +pub unsafe fn instr_B5(imm8: i32) { *reg8.offset(CH as isize) = imm8 as u8; } #[no_mangle] -pub unsafe fn instr_B6(mut imm8: i32) { *reg8.offset(DH as isize) = imm8 as u8; } +pub unsafe fn instr_B6(imm8: i32) { *reg8.offset(DH as isize) = imm8 as u8; } #[no_mangle] -pub unsafe fn instr_B7(mut imm8: i32) { *reg8.offset(BH as isize) = imm8 as u8; } +pub unsafe fn instr_B7(imm8: i32) { *reg8.offset(BH as isize) = imm8 as u8; } #[no_mangle] -pub unsafe fn instr16_B8(mut imm: i32) { *reg16.offset(AX as isize) = imm as u16; } +pub unsafe fn instr16_B8(imm: i32) { *reg16.offset(AX as isize) = imm as u16; } #[no_mangle] -pub unsafe fn instr32_B8(mut imm: i32) { *reg32s.offset(EAX as isize) = imm; } +pub unsafe fn instr32_B8(imm: i32) { *reg32s.offset(EAX as isize) = imm; } #[no_mangle] -pub unsafe fn instr16_B9(mut imm: i32) { *reg16.offset(CX as isize) = imm as u16; } +pub unsafe fn instr16_B9(imm: i32) { *reg16.offset(CX as isize) = imm as u16; } #[no_mangle] -pub unsafe fn instr32_B9(mut imm: i32) { *reg32s.offset(ECX as isize) = imm; } +pub unsafe fn instr32_B9(imm: i32) { *reg32s.offset(ECX as isize) = imm; } #[no_mangle] -pub unsafe fn instr16_BA(mut imm: i32) { *reg16.offset(DX as isize) = imm as u16; } +pub unsafe fn instr16_BA(imm: i32) { *reg16.offset(DX as isize) = imm as u16; } #[no_mangle] -pub unsafe fn instr32_BA(mut imm: i32) { *reg32s.offset(EDX as isize) = imm; } +pub unsafe fn instr32_BA(imm: i32) { *reg32s.offset(EDX as isize) = imm; } #[no_mangle] -pub unsafe fn instr16_BB(mut imm: i32) { *reg16.offset(BX as isize) = imm as u16; } +pub unsafe fn instr16_BB(imm: i32) { *reg16.offset(BX as isize) = imm as u16; } #[no_mangle] -pub unsafe fn instr32_BB(mut imm: i32) { *reg32s.offset(EBX as isize) = imm; } +pub unsafe fn instr32_BB(imm: i32) { *reg32s.offset(EBX as isize) = imm; } #[no_mangle] -pub unsafe fn instr16_BC(mut imm: i32) { *reg16.offset(SP as isize) = imm as u16; } +pub unsafe fn instr16_BC(imm: i32) { *reg16.offset(SP as isize) = imm as u16; } #[no_mangle] -pub unsafe fn instr32_BC(mut imm: i32) { *reg32s.offset(ESP as isize) = imm; } +pub unsafe fn instr32_BC(imm: i32) { *reg32s.offset(ESP as isize) = imm; } #[no_mangle] -pub unsafe fn instr16_BD(mut imm: i32) { *reg16.offset(BP as isize) = imm as u16; } +pub unsafe fn instr16_BD(imm: i32) { *reg16.offset(BP as isize) = imm as u16; } #[no_mangle] -pub unsafe fn instr32_BD(mut imm: i32) { *reg32s.offset(EBP as isize) = imm; } +pub unsafe fn instr32_BD(imm: i32) { *reg32s.offset(EBP as isize) = imm; } #[no_mangle] -pub unsafe fn instr16_BE(mut imm: i32) { *reg16.offset(SI as isize) = imm as u16; } +pub unsafe fn instr16_BE(imm: i32) { *reg16.offset(SI as isize) = imm as u16; } #[no_mangle] -pub unsafe fn instr32_BE(mut imm: i32) { *reg32s.offset(ESI as isize) = imm; } +pub unsafe fn instr32_BE(imm: i32) { *reg32s.offset(ESI as isize) = imm; } #[no_mangle] -pub unsafe fn instr16_BF(mut imm: i32) { *reg16.offset(DI as isize) = imm as u16; } +pub unsafe fn instr16_BF(imm: i32) { *reg16.offset(DI as isize) = imm as u16; } #[no_mangle] -pub unsafe fn instr32_BF(mut imm: i32) { *reg32s.offset(EDI as isize) = imm; } +pub unsafe fn instr32_BF(imm: i32) { *reg32s.offset(EDI as isize) = imm; } #[no_mangle] -pub unsafe fn instr_C0_0_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_C0_0_mem(addr: i32, imm: i32) { SAFE_READ_WRITE8!(___, addr, rol8(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr_C0_0_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_C0_0_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, rol8(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr_C0_1_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_C0_1_mem(addr: i32, imm: i32) { SAFE_READ_WRITE8!(___, addr, ror8(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr_C0_1_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_C0_1_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, ror8(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr_C0_2_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_C0_2_mem(addr: i32, imm: i32) { SAFE_READ_WRITE8!(___, addr, rcl8(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr_C0_2_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_C0_2_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, rcl8(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr_C0_3_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_C0_3_mem(addr: i32, imm: i32) { SAFE_READ_WRITE8!(___, addr, rcr8(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr_C0_3_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_C0_3_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, rcr8(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr_C0_4_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_C0_4_mem(addr: i32, imm: i32) { SAFE_READ_WRITE8!(___, addr, shl8(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr_C0_4_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_C0_4_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, shl8(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr_C0_5_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_C0_5_mem(addr: i32, imm: i32) { SAFE_READ_WRITE8!(___, addr, shr8(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr_C0_5_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_C0_5_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, shr8(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr_C0_6_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_C0_6_mem(addr: i32, imm: i32) { SAFE_READ_WRITE8!(___, addr, shl8(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr_C0_6_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_C0_6_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, shl8(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr_C0_7_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_C0_7_mem(addr: i32, imm: i32) { SAFE_READ_WRITE8!(___, addr, sar8(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr_C0_7_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_C0_7_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, sar8(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr16_C1_0_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_C1_0_mem(addr: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, rol16(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr16_C1_0_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_C1_0_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, rol16(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr16_C1_1_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_C1_1_mem(addr: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, ror16(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr16_C1_1_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_C1_1_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, ror16(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr16_C1_2_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_C1_2_mem(addr: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, rcl16(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr16_C1_2_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_C1_2_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, rcl16(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr16_C1_3_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_C1_3_mem(addr: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, rcr16(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr16_C1_3_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_C1_3_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, rcr16(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr16_C1_4_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_C1_4_mem(addr: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, shl16(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr16_C1_4_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_C1_4_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, shl16(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr16_C1_5_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_C1_5_mem(addr: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, shr16(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr16_C1_5_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_C1_5_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, shr16(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr16_C1_6_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_C1_6_mem(addr: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, shl16(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr16_C1_6_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_C1_6_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, shl16(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr16_C1_7_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_C1_7_mem(addr: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, sar16(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr16_C1_7_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_C1_7_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, sar16(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr32_C1_0_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_C1_0_mem(addr: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, rol32(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr32_C1_0_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_C1_0_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, rol32(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr32_C1_1_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_C1_1_mem(addr: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, ror32(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr32_C1_1_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_C1_1_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, ror32(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr32_C1_2_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_C1_2_mem(addr: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, rcl32(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr32_C1_2_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_C1_2_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, rcl32(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr32_C1_3_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_C1_3_mem(addr: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, rcr32(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr32_C1_3_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_C1_3_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, rcr32(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr32_C1_4_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_C1_4_mem(addr: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, shl32(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr32_C1_4_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_C1_4_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, shl32(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr32_C1_5_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_C1_5_mem(addr: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, shr32(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr32_C1_5_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_C1_5_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, shr32(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr32_C1_6_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_C1_6_mem(addr: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, shl32(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr32_C1_6_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_C1_6_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, shl32(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr32_C1_7_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_C1_7_mem(addr: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, sar32(___, imm & 31)); } #[no_mangle] -pub unsafe fn instr32_C1_7_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_C1_7_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, sar32(____0, imm & 31)); } #[no_mangle] -pub unsafe fn instr16_C2(mut imm16: i32) { +pub unsafe fn instr16_C2(imm16: i32) { // retn - let mut cs: i32 = get_seg_cs(); + let cs: i32 = get_seg_cs(); *instruction_pointer = cs + return_on_pagefault!(pop16()); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); adjust_stack_reg(imm16); } #[no_mangle] -pub unsafe fn instr32_C2(mut imm16: i32) { +pub unsafe fn instr32_C2(imm16: i32) { // retn - let mut cs: i32 = get_seg_cs(); - let mut ip: i32 = return_on_pagefault!(pop32s()); + let cs: i32 = get_seg_cs(); + let ip: i32 = return_on_pagefault!(pop32s()); dbg_assert!(0 != is_asize_32() as i32 || ip < 65536); *instruction_pointer = cs + ip; adjust_stack_reg(imm16); @@ -2157,108 +2157,108 @@ pub unsafe fn instr32_C2(mut imm16: i32) { #[no_mangle] pub unsafe fn instr16_C3() { // retn - let mut cs: i32 = get_seg_cs(); + let cs: i32 = get_seg_cs(); *instruction_pointer = cs + return_on_pagefault!(pop16()); } #[no_mangle] pub unsafe fn instr32_C3() { // retn - let mut cs: i32 = get_seg_cs(); - let mut ip: i32 = return_on_pagefault!(pop32s()); + let cs: i32 = get_seg_cs(); + let ip: i32 = return_on_pagefault!(pop32s()); dbg_assert!(0 != is_asize_32() as i32 || ip < 65536); *instruction_pointer = cs + ip; } #[no_mangle] -pub unsafe fn instr16_C4_reg(mut _unused1: i32, mut _unused2: i32) { trigger_ud(); } +pub unsafe fn instr16_C4_reg(_unused1: i32, _unused2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_C4_mem(mut addr: i32, mut r: i32) { lss16(addr, get_reg16_index(r), ES); } +pub unsafe fn instr16_C4_mem(addr: i32, r: i32) { lss16(addr, get_reg16_index(r), ES); } #[no_mangle] -pub unsafe fn instr32_C4_reg(mut _unused1: i32, mut _unused2: i32) { trigger_ud(); } +pub unsafe fn instr32_C4_reg(_unused1: i32, _unused2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr32_C4_mem(mut addr: i32, mut r: i32) { lss32(addr, r, ES); } +pub unsafe fn instr32_C4_mem(addr: i32, r: i32) { lss32(addr, r, ES); } #[no_mangle] -pub unsafe fn instr16_C5_reg(mut _unused1: i32, mut _unused2: i32) { trigger_ud(); } +pub unsafe fn instr16_C5_reg(_unused1: i32, _unused2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_C5_mem(mut addr: i32, mut r: i32) { lss16(addr, get_reg16_index(r), DS); } +pub unsafe fn instr16_C5_mem(addr: i32, r: i32) { lss16(addr, get_reg16_index(r), DS); } #[no_mangle] -pub unsafe fn instr32_C5_reg(mut _unused1: i32, mut _unused2: i32) { trigger_ud(); } +pub unsafe fn instr32_C5_reg(_unused1: i32, _unused2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr32_C5_mem(mut addr: i32, mut r: i32) { lss32(addr, r, DS); } +pub unsafe fn instr32_C5_mem(addr: i32, r: i32) { lss32(addr, r, DS); } #[no_mangle] -pub unsafe fn instr_C6_0_reg(mut r: i32, mut imm: i32) { write_reg8(r, imm); } +pub unsafe fn instr_C6_0_reg(r: i32, imm: i32) { write_reg8(r, imm); } #[no_mangle] -pub unsafe fn instr_C6_0_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr_C6_0_mem(addr: i32, imm: i32) { return_on_pagefault!(safe_write8(addr, imm)); } #[no_mangle] -pub unsafe fn instr16_C7_0_reg(mut r: i32, mut imm: i32) { write_reg16(r, imm); } +pub unsafe fn instr16_C7_0_reg(r: i32, imm: i32) { write_reg16(r, imm); } #[no_mangle] -pub unsafe fn instr16_C7_0_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr16_C7_0_mem(addr: i32, imm: i32) { return_on_pagefault!(safe_write16(addr, imm)); } #[no_mangle] -pub unsafe fn instr32_C7_0_reg(mut r: i32, mut imm: i32) { write_reg32(r, imm); } +pub unsafe fn instr32_C7_0_reg(r: i32, imm: i32) { write_reg32(r, imm); } #[no_mangle] -pub unsafe fn instr32_C7_0_mem(mut addr: i32, mut imm: i32) { +pub unsafe fn instr32_C7_0_mem(addr: i32, imm: i32) { return_on_pagefault!(safe_write32(addr, imm)); } #[no_mangle] -pub unsafe fn instr16_C8(mut size: i32, mut nesting: i32) { enter16(size, nesting); } +pub unsafe fn instr16_C8(size: i32, nesting: i32) { enter16(size, nesting); } #[no_mangle] -pub unsafe fn instr32_C8(mut size: i32, mut nesting: i32) { enter32(size, nesting); } +pub unsafe fn instr32_C8(size: i32, nesting: i32) { enter32(size, nesting); } #[no_mangle] pub unsafe fn instr16_C9() { // leave - let mut old_vbp: i32 = if 0 != *stack_size_32 as i32 { + let old_vbp: i32 = if 0 != *stack_size_32 as i32 { *reg32s.offset(EBP as isize) } else { *reg16.offset(BP as isize) as i32 }; - let mut new_bp: i32 = return_on_pagefault!(safe_read16(get_seg_ss() + old_vbp)); + let new_bp: i32 = return_on_pagefault!(safe_read16(get_seg_ss() + old_vbp)); set_stack_reg(old_vbp + 2); *reg16.offset(BP as isize) = new_bp as u16; } #[no_mangle] pub unsafe fn instr32_C9() { - let mut old_vbp: i32 = if 0 != *stack_size_32 as i32 { + let old_vbp: i32 = if 0 != *stack_size_32 as i32 { *reg32s.offset(EBP as isize) } else { *reg16.offset(BP as isize) as i32 }; - let mut new_ebp: i32 = return_on_pagefault!(safe_read32s(get_seg_ss() + old_vbp)); + let new_ebp: i32 = return_on_pagefault!(safe_read32s(get_seg_ss() + old_vbp)); set_stack_reg(old_vbp + 4); *reg32s.offset(EBP as isize) = new_ebp; } #[no_mangle] -pub unsafe fn instr16_CA(mut imm16: i32) { +pub unsafe fn instr16_CA(imm16: i32) { // retf - let mut ip: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0))); - let mut cs: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(2))); + let ip: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0))); + let cs: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(2))); far_return(ip, cs, imm16); } #[no_mangle] -pub unsafe fn instr32_CA(mut imm16: i32) { +pub unsafe fn instr32_CA(imm16: i32) { // retf - let mut ip: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0))); - let mut cs: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(4))) & 65535; + let ip: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0))); + let cs: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(4))) & 65535; far_return(ip, cs, imm16); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] pub unsafe fn instr16_CB() { // retf - let mut ip: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0))); - let mut cs: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(2))); + let ip: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0))); + let cs: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(2))); far_return(ip, cs, 0); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] pub unsafe fn instr32_CB() { // retf - let mut ip: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0))); - let mut cs: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(4))) & 65535; + let ip: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0))); + let cs: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(4))) & 65535; far_return(ip, cs, 0); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } @@ -2270,7 +2270,7 @@ pub unsafe fn instr_CC() { call_interrupt_vector(3, 0 != 1, 0 != 0, 0); } #[no_mangle] -pub unsafe fn instr_CD(mut imm8: i32) { +pub unsafe fn instr_CD(imm8: i32) { // INT call_interrupt_vector(imm8, 0 != 1, 0 != 0, 0); } @@ -2291,441 +2291,441 @@ pub unsafe fn instr16_CF() { #[no_mangle] pub unsafe fn instr32_CF() { iret32(); } #[no_mangle] -pub unsafe fn instr_D0_0_mem(mut addr: i32) { +pub unsafe fn instr_D0_0_mem(addr: i32) { SAFE_READ_WRITE8!(___, addr, rol8(___, 1)); } #[no_mangle] -pub unsafe fn instr_D0_0_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_D0_0_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, rol8(____0, 1)); } #[no_mangle] -pub unsafe fn instr_D0_1_mem(mut addr: i32) { +pub unsafe fn instr_D0_1_mem(addr: i32) { SAFE_READ_WRITE8!(___, addr, ror8(___, 1)); } #[no_mangle] -pub unsafe fn instr_D0_1_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_D0_1_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, ror8(____0, 1)); } #[no_mangle] -pub unsafe fn instr_D0_2_mem(mut addr: i32) { +pub unsafe fn instr_D0_2_mem(addr: i32) { SAFE_READ_WRITE8!(___, addr, rcl8(___, 1)); } #[no_mangle] -pub unsafe fn instr_D0_2_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_D0_2_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, rcl8(____0, 1)); } #[no_mangle] -pub unsafe fn instr_D0_3_mem(mut addr: i32) { +pub unsafe fn instr_D0_3_mem(addr: i32) { SAFE_READ_WRITE8!(___, addr, rcr8(___, 1)); } #[no_mangle] -pub unsafe fn instr_D0_3_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_D0_3_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, rcr8(____0, 1)); } #[no_mangle] -pub unsafe fn instr_D0_4_mem(mut addr: i32) { +pub unsafe fn instr_D0_4_mem(addr: i32) { SAFE_READ_WRITE8!(___, addr, shl8(___, 1)); } #[no_mangle] -pub unsafe fn instr_D0_4_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_D0_4_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, shl8(____0, 1)); } #[no_mangle] -pub unsafe fn instr_D0_5_mem(mut addr: i32) { +pub unsafe fn instr_D0_5_mem(addr: i32) { SAFE_READ_WRITE8!(___, addr, shr8(___, 1)); } #[no_mangle] -pub unsafe fn instr_D0_5_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_D0_5_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, shr8(____0, 1)); } #[no_mangle] -pub unsafe fn instr_D0_6_mem(mut addr: i32) { +pub unsafe fn instr_D0_6_mem(addr: i32) { SAFE_READ_WRITE8!(___, addr, shl8(___, 1)); } #[no_mangle] -pub unsafe fn instr_D0_6_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_D0_6_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, shl8(____0, 1)); } #[no_mangle] -pub unsafe fn instr_D0_7_mem(mut addr: i32) { +pub unsafe fn instr_D0_7_mem(addr: i32) { SAFE_READ_WRITE8!(___, addr, sar8(___, 1)); } #[no_mangle] -pub unsafe fn instr_D0_7_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_D0_7_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, sar8(____0, 1)); } #[no_mangle] -pub unsafe fn instr16_D1_0_mem(mut addr: i32) { +pub unsafe fn instr16_D1_0_mem(addr: i32) { SAFE_READ_WRITE16!(___, addr, rol16(___, 1)); } #[no_mangle] -pub unsafe fn instr16_D1_0_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_D1_0_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, rol16(____0, 1)); } #[no_mangle] -pub unsafe fn instr16_D1_1_mem(mut addr: i32) { +pub unsafe fn instr16_D1_1_mem(addr: i32) { SAFE_READ_WRITE16!(___, addr, ror16(___, 1)); } #[no_mangle] -pub unsafe fn instr16_D1_1_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_D1_1_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, ror16(____0, 1)); } #[no_mangle] -pub unsafe fn instr16_D1_2_mem(mut addr: i32) { +pub unsafe fn instr16_D1_2_mem(addr: i32) { SAFE_READ_WRITE16!(___, addr, rcl16(___, 1)); } #[no_mangle] -pub unsafe fn instr16_D1_2_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_D1_2_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, rcl16(____0, 1)); } #[no_mangle] -pub unsafe fn instr16_D1_3_mem(mut addr: i32) { +pub unsafe fn instr16_D1_3_mem(addr: i32) { SAFE_READ_WRITE16!(___, addr, rcr16(___, 1)); } #[no_mangle] -pub unsafe fn instr16_D1_3_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_D1_3_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, rcr16(____0, 1)); } #[no_mangle] -pub unsafe fn instr16_D1_4_mem(mut addr: i32) { +pub unsafe fn instr16_D1_4_mem(addr: i32) { SAFE_READ_WRITE16!(___, addr, shl16(___, 1)); } #[no_mangle] -pub unsafe fn instr16_D1_4_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_D1_4_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, shl16(____0, 1)); } #[no_mangle] -pub unsafe fn instr16_D1_5_mem(mut addr: i32) { +pub unsafe fn instr16_D1_5_mem(addr: i32) { SAFE_READ_WRITE16!(___, addr, shr16(___, 1)); } #[no_mangle] -pub unsafe fn instr16_D1_5_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_D1_5_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, shr16(____0, 1)); } #[no_mangle] -pub unsafe fn instr16_D1_6_mem(mut addr: i32) { +pub unsafe fn instr16_D1_6_mem(addr: i32) { SAFE_READ_WRITE16!(___, addr, shl16(___, 1)); } #[no_mangle] -pub unsafe fn instr16_D1_6_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_D1_6_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, shl16(____0, 1)); } #[no_mangle] -pub unsafe fn instr16_D1_7_mem(mut addr: i32) { +pub unsafe fn instr16_D1_7_mem(addr: i32) { SAFE_READ_WRITE16!(___, addr, sar16(___, 1)); } #[no_mangle] -pub unsafe fn instr16_D1_7_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_D1_7_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, sar16(____0, 1)); } #[no_mangle] -pub unsafe fn instr32_D1_0_mem(mut addr: i32) { +pub unsafe fn instr32_D1_0_mem(addr: i32) { SAFE_READ_WRITE32!(___, addr, rol32(___, 1)); } #[no_mangle] -pub unsafe fn instr32_D1_0_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_D1_0_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, rol32(____0, 1)); } #[no_mangle] -pub unsafe fn instr32_D1_1_mem(mut addr: i32) { +pub unsafe fn instr32_D1_1_mem(addr: i32) { SAFE_READ_WRITE32!(___, addr, ror32(___, 1)); } #[no_mangle] -pub unsafe fn instr32_D1_1_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_D1_1_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, ror32(____0, 1)); } #[no_mangle] -pub unsafe fn instr32_D1_2_mem(mut addr: i32) { +pub unsafe fn instr32_D1_2_mem(addr: i32) { SAFE_READ_WRITE32!(___, addr, rcl32(___, 1)); } #[no_mangle] -pub unsafe fn instr32_D1_2_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_D1_2_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, rcl32(____0, 1)); } #[no_mangle] -pub unsafe fn instr32_D1_3_mem(mut addr: i32) { +pub unsafe fn instr32_D1_3_mem(addr: i32) { SAFE_READ_WRITE32!(___, addr, rcr32(___, 1)); } #[no_mangle] -pub unsafe fn instr32_D1_3_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_D1_3_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, rcr32(____0, 1)); } #[no_mangle] -pub unsafe fn instr32_D1_4_mem(mut addr: i32) { +pub unsafe fn instr32_D1_4_mem(addr: i32) { SAFE_READ_WRITE32!(___, addr, shl32(___, 1)); } #[no_mangle] -pub unsafe fn instr32_D1_4_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_D1_4_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, shl32(____0, 1)); } #[no_mangle] -pub unsafe fn instr32_D1_5_mem(mut addr: i32) { +pub unsafe fn instr32_D1_5_mem(addr: i32) { SAFE_READ_WRITE32!(___, addr, shr32(___, 1)); } #[no_mangle] -pub unsafe fn instr32_D1_5_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_D1_5_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, shr32(____0, 1)); } #[no_mangle] -pub unsafe fn instr32_D1_6_mem(mut addr: i32) { +pub unsafe fn instr32_D1_6_mem(addr: i32) { SAFE_READ_WRITE32!(___, addr, shl32(___, 1)); } #[no_mangle] -pub unsafe fn instr32_D1_6_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_D1_6_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, shl32(____0, 1)); } #[no_mangle] -pub unsafe fn instr32_D1_7_mem(mut addr: i32) { +pub unsafe fn instr32_D1_7_mem(addr: i32) { SAFE_READ_WRITE32!(___, addr, sar32(___, 1)); } #[no_mangle] -pub unsafe fn instr32_D1_7_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_D1_7_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, sar32(____0, 1)); } #[no_mangle] -pub unsafe fn instr_D2_0_mem(mut addr: i32) { +pub unsafe fn instr_D2_0_mem(addr: i32) { SAFE_READ_WRITE8!(___, addr, rol8(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr_D2_0_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_D2_0_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, rol8(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr_D2_1_mem(mut addr: i32) { +pub unsafe fn instr_D2_1_mem(addr: i32) { SAFE_READ_WRITE8!(___, addr, ror8(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr_D2_1_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_D2_1_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, ror8(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr_D2_2_mem(mut addr: i32) { +pub unsafe fn instr_D2_2_mem(addr: i32) { SAFE_READ_WRITE8!(___, addr, rcl8(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr_D2_2_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_D2_2_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, rcl8(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr_D2_3_mem(mut addr: i32) { +pub unsafe fn instr_D2_3_mem(addr: i32) { SAFE_READ_WRITE8!(___, addr, rcr8(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr_D2_3_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_D2_3_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, rcr8(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr_D2_4_mem(mut addr: i32) { +pub unsafe fn instr_D2_4_mem(addr: i32) { SAFE_READ_WRITE8!(___, addr, shl8(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr_D2_4_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_D2_4_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, shl8(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr_D2_5_mem(mut addr: i32) { +pub unsafe fn instr_D2_5_mem(addr: i32) { SAFE_READ_WRITE8!(___, addr, shr8(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr_D2_5_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_D2_5_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, shr8(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr_D2_6_mem(mut addr: i32) { +pub unsafe fn instr_D2_6_mem(addr: i32) { SAFE_READ_WRITE8!(___, addr, shl8(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr_D2_6_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_D2_6_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, shl8(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr_D2_7_mem(mut addr: i32) { +pub unsafe fn instr_D2_7_mem(addr: i32) { SAFE_READ_WRITE8!(___, addr, sar8(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr_D2_7_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_D2_7_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, sar8(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr16_D3_0_mem(mut addr: i32) { +pub unsafe fn instr16_D3_0_mem(addr: i32) { SAFE_READ_WRITE16!(___, addr, rol16(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr16_D3_0_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_D3_0_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, rol16(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr16_D3_1_mem(mut addr: i32) { +pub unsafe fn instr16_D3_1_mem(addr: i32) { SAFE_READ_WRITE16!(___, addr, ror16(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr16_D3_1_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_D3_1_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, ror16(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr16_D3_2_mem(mut addr: i32) { +pub unsafe fn instr16_D3_2_mem(addr: i32) { SAFE_READ_WRITE16!(___, addr, rcl16(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr16_D3_2_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_D3_2_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, rcl16(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr16_D3_3_mem(mut addr: i32) { +pub unsafe fn instr16_D3_3_mem(addr: i32) { SAFE_READ_WRITE16!(___, addr, rcr16(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr16_D3_3_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_D3_3_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, rcr16(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr16_D3_4_mem(mut addr: i32) { +pub unsafe fn instr16_D3_4_mem(addr: i32) { SAFE_READ_WRITE16!(___, addr, shl16(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr16_D3_4_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_D3_4_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, shl16(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr16_D3_5_mem(mut addr: i32) { +pub unsafe fn instr16_D3_5_mem(addr: i32) { SAFE_READ_WRITE16!(___, addr, shr16(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr16_D3_5_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_D3_5_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, shr16(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr16_D3_6_mem(mut addr: i32) { +pub unsafe fn instr16_D3_6_mem(addr: i32) { SAFE_READ_WRITE16!(___, addr, shl16(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr16_D3_6_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_D3_6_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, shl16(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr16_D3_7_mem(mut addr: i32) { +pub unsafe fn instr16_D3_7_mem(addr: i32) { SAFE_READ_WRITE16!(___, addr, sar16(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr16_D3_7_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_D3_7_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, sar16(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr32_D3_0_mem(mut addr: i32) { +pub unsafe fn instr32_D3_0_mem(addr: i32) { SAFE_READ_WRITE32!(___, addr, rol32(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr32_D3_0_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_D3_0_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, rol32(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr32_D3_1_mem(mut addr: i32) { +pub unsafe fn instr32_D3_1_mem(addr: i32) { SAFE_READ_WRITE32!(___, addr, ror32(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr32_D3_1_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_D3_1_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, ror32(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr32_D3_2_mem(mut addr: i32) { +pub unsafe fn instr32_D3_2_mem(addr: i32) { SAFE_READ_WRITE32!(___, addr, rcl32(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr32_D3_2_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_D3_2_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, rcl32(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr32_D3_3_mem(mut addr: i32) { +pub unsafe fn instr32_D3_3_mem(addr: i32) { SAFE_READ_WRITE32!(___, addr, rcr32(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr32_D3_3_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_D3_3_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, rcr32(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr32_D3_4_mem(mut addr: i32) { +pub unsafe fn instr32_D3_4_mem(addr: i32) { SAFE_READ_WRITE32!(___, addr, shl32(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr32_D3_4_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_D3_4_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, shl32(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr32_D3_5_mem(mut addr: i32) { +pub unsafe fn instr32_D3_5_mem(addr: i32) { SAFE_READ_WRITE32!(___, addr, shr32(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr32_D3_5_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_D3_5_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, shr32(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr32_D3_6_mem(mut addr: i32) { +pub unsafe fn instr32_D3_6_mem(addr: i32) { SAFE_READ_WRITE32!(___, addr, shl32(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr32_D3_6_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_D3_6_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, shl32(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr32_D3_7_mem(mut addr: i32) { +pub unsafe fn instr32_D3_7_mem(addr: i32) { SAFE_READ_WRITE32!(___, addr, sar32(___, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr32_D3_7_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_D3_7_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, sar32(____0, *reg8.offset(CL as isize) as i32 & 31)); } #[no_mangle] -pub unsafe fn instr_D4(mut arg: i32) { bcd_aam(arg); } +pub unsafe fn instr_D4(arg: i32) { bcd_aam(arg); } #[no_mangle] -pub unsafe fn instr_D5(mut arg: i32) { bcd_aad(arg); } +pub unsafe fn instr_D5(arg: i32) { bcd_aad(arg); } #[no_mangle] pub unsafe fn instr_D6() { // salc @@ -2747,7 +2747,7 @@ pub unsafe fn instr_D7() { }; } #[no_mangle] -pub unsafe fn instr_E4(mut port: i32) { +pub unsafe fn instr_E4(port: i32) { if !test_privileges_for_io(port, 1) { return; } @@ -2757,7 +2757,7 @@ pub unsafe fn instr_E4(mut port: i32) { }; } #[no_mangle] -pub unsafe fn instr16_E5(mut port: i32) { +pub unsafe fn instr16_E5(port: i32) { if !test_privileges_for_io(port, 2) { return; } @@ -2767,7 +2767,7 @@ pub unsafe fn instr16_E5(mut port: i32) { }; } #[no_mangle] -pub unsafe fn instr32_E5(mut port: i32) { +pub unsafe fn instr32_E5(port: i32) { if !test_privileges_for_io(port, 4) { return; } @@ -2777,7 +2777,7 @@ pub unsafe fn instr32_E5(mut port: i32) { }; } #[no_mangle] -pub unsafe fn instr_E6(mut port: i32) { +pub unsafe fn instr_E6(port: i32) { if !test_privileges_for_io(port, 1) { return; } @@ -2787,7 +2787,7 @@ pub unsafe fn instr_E6(mut port: i32) { }; } #[no_mangle] -pub unsafe fn instr16_E7(mut port: i32) { +pub unsafe fn instr16_E7(port: i32) { if !test_privileges_for_io(port, 2) { return; } @@ -2797,7 +2797,7 @@ pub unsafe fn instr16_E7(mut port: i32) { }; } #[no_mangle] -pub unsafe fn instr32_E7(mut port: i32) { +pub unsafe fn instr32_E7(port: i32) { if !test_privileges_for_io(port, 4) { return; } @@ -2807,44 +2807,44 @@ pub unsafe fn instr32_E7(mut port: i32) { }; } #[no_mangle] -pub unsafe fn instr16_E8(mut imm16: i32) { +pub unsafe fn instr16_E8(imm16: i32) { // call return_on_pagefault!(push16(get_real_eip())); jmp_rel16(imm16); } #[no_mangle] -pub unsafe fn instr32_E8(mut imm32s: i32) { +pub unsafe fn instr32_E8(imm32s: i32) { // call return_on_pagefault!(push32(get_real_eip())); *instruction_pointer = *instruction_pointer + imm32s; // dbg_assert!(is_asize_32() || get_real_eip() < 0x10000); } #[no_mangle] -pub unsafe fn instr16_E9(mut imm16: i32) { +pub unsafe fn instr16_E9(imm16: i32) { // jmp jmp_rel16(imm16); } #[no_mangle] -pub unsafe fn instr32_E9(mut imm32s: i32) { +pub unsafe fn instr32_E9(imm32s: i32) { // jmp *instruction_pointer = *instruction_pointer + imm32s; dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] -pub unsafe fn instr16_EA(mut new_ip: i32, mut cs: i32) { +pub unsafe fn instr16_EA(new_ip: i32, cs: i32) { // jmpf far_jump(new_ip, cs, false); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] -pub unsafe fn instr32_EA(mut new_ip: i32, mut cs: i32) { +pub unsafe fn instr32_EA(new_ip: i32, cs: i32) { // jmpf far_jump(new_ip, cs, false); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] pub unsafe fn instr_EC() { - let mut port: i32 = *reg16.offset(DX as isize) as i32; + let port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 1) { return; } @@ -2855,7 +2855,7 @@ pub unsafe fn instr_EC() { } #[no_mangle] pub unsafe fn instr16_ED() { - let mut port: i32 = *reg16.offset(DX as isize) as i32; + let port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 2) { return; } @@ -2866,7 +2866,7 @@ pub unsafe fn instr16_ED() { } #[no_mangle] pub unsafe fn instr32_ED() { - let mut port: i32 = *reg16.offset(DX as isize) as i32; + let port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 4) { return; } @@ -2877,7 +2877,7 @@ pub unsafe fn instr32_ED() { } #[no_mangle] pub unsafe fn instr_EE() { - let mut port: i32 = *reg16.offset(DX as isize) as i32; + let port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 1) { return; } @@ -2888,7 +2888,7 @@ pub unsafe fn instr_EE() { } #[no_mangle] pub unsafe fn instr16_EF() { - let mut port: i32 = *reg16.offset(DX as isize) as i32; + let port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 2) { return; } @@ -2899,7 +2899,7 @@ pub unsafe fn instr16_EF() { } #[no_mangle] pub unsafe fn instr32_EF() { - let mut port: i32 = *reg16.offset(DX as isize) as i32; + let port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 4) { return; } @@ -2950,237 +2950,237 @@ pub unsafe fn instr_F5() { *flags_changed &= !1; } #[no_mangle] -pub unsafe fn instr_F6_0_mem(mut addr: i32, mut imm: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); +pub unsafe fn instr_F6_0_mem(addr: i32, imm: i32) { + let ____0: i32 = return_on_pagefault!(safe_read8(addr)); test8(____0, imm); } #[no_mangle] -pub unsafe fn instr_F6_0_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_F6_0_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); test8(____0, imm); } #[no_mangle] -pub unsafe fn instr_F6_1_mem(mut addr: i32, mut imm: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); +pub unsafe fn instr_F6_1_mem(addr: i32, imm: i32) { + let ____0: i32 = return_on_pagefault!(safe_read8(addr)); test8(____0, imm); } #[no_mangle] -pub unsafe fn instr_F6_1_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_F6_1_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg8(r1); test8(____0, imm); } #[no_mangle] -pub unsafe fn instr_F6_2_mem(mut addr: i32) { +pub unsafe fn instr_F6_2_mem(addr: i32) { SAFE_READ_WRITE8!(___, addr, !___); } #[no_mangle] -pub unsafe fn instr_F6_2_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_F6_2_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, !____0); } #[no_mangle] -pub unsafe fn instr_F6_3_mem(mut addr: i32) { +pub unsafe fn instr_F6_3_mem(addr: i32) { SAFE_READ_WRITE8!(___, addr, neg8(___)); } #[no_mangle] -pub unsafe fn instr_F6_3_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_F6_3_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, neg8(____0)); } #[no_mangle] -pub unsafe fn instr_F6_4_mem(mut addr: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); +pub unsafe fn instr_F6_4_mem(addr: i32) { + let ____0: i32 = return_on_pagefault!(safe_read8(addr)); mul8(____0); } #[no_mangle] -pub unsafe fn instr_F6_4_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_F6_4_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); mul8(____0); } #[no_mangle] -pub unsafe fn instr_F6_5_mem(mut addr: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); +pub unsafe fn instr_F6_5_mem(addr: i32) { + let ____0: i32 = return_on_pagefault!(safe_read8(addr)); imul8(____0 << 24 >> 24); } #[no_mangle] -pub unsafe fn instr_F6_5_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_F6_5_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); imul8(____0 << 24 >> 24); } #[no_mangle] -pub unsafe fn instr_F6_6_mem(mut addr: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); +pub unsafe fn instr_F6_6_mem(addr: i32) { + let ____0: i32 = return_on_pagefault!(safe_read8(addr)); div8(____0 as u32); } #[no_mangle] -pub unsafe fn instr_F6_6_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_F6_6_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); div8(____0 as u32); } #[no_mangle] -pub unsafe fn instr_F6_7_mem(mut addr: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); +pub unsafe fn instr_F6_7_mem(addr: i32) { + let ____0: i32 = return_on_pagefault!(safe_read8(addr)); idiv8(____0 << 24 >> 24); } #[no_mangle] -pub unsafe fn instr_F6_7_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_F6_7_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); idiv8(____0 << 24 >> 24); } #[no_mangle] -pub unsafe fn instr16_F7_0_mem(mut addr: i32, mut imm: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_F7_0_mem(addr: i32, imm: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); test16(____0, imm); } #[no_mangle] -pub unsafe fn instr16_F7_0_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_F7_0_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); test16(____0, imm); } #[no_mangle] -pub unsafe fn instr16_F7_1_mem(mut addr: i32, mut imm: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_F7_1_mem(addr: i32, imm: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); test16(____0, imm); } #[no_mangle] -pub unsafe fn instr16_F7_1_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_F7_1_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); test16(____0, imm); } #[no_mangle] -pub unsafe fn instr16_F7_2_mem(mut addr: i32) { +pub unsafe fn instr16_F7_2_mem(addr: i32) { SAFE_READ_WRITE16!(___, addr, !___); } #[no_mangle] -pub unsafe fn instr16_F7_2_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_F7_2_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, !____0); } #[no_mangle] -pub unsafe fn instr16_F7_3_mem(mut addr: i32) { +pub unsafe fn instr16_F7_3_mem(addr: i32) { SAFE_READ_WRITE16!(___, addr, neg16(___)); } #[no_mangle] -pub unsafe fn instr16_F7_3_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_F7_3_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, neg16(____0)); } #[no_mangle] -pub unsafe fn instr16_F7_4_mem(mut addr: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_F7_4_mem(addr: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); mul16(____0 as u32); } #[no_mangle] -pub unsafe fn instr16_F7_4_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_F7_4_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); mul16(____0 as u32); } #[no_mangle] -pub unsafe fn instr16_F7_5_mem(mut addr: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_F7_5_mem(addr: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); imul16(____0 << 16 >> 16); } #[no_mangle] -pub unsafe fn instr16_F7_5_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_F7_5_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); imul16(____0 << 16 >> 16); } #[no_mangle] -pub unsafe fn instr16_F7_6_mem(mut addr: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_F7_6_mem(addr: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); div16(____0 as u32); } #[no_mangle] -pub unsafe fn instr16_F7_6_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_F7_6_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); div16(____0 as u32); } #[no_mangle] -pub unsafe fn instr16_F7_7_mem(mut addr: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_F7_7_mem(addr: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); idiv16(____0 << 16 >> 16); } #[no_mangle] -pub unsafe fn instr16_F7_7_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_F7_7_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); idiv16(____0 << 16 >> 16); } #[no_mangle] -pub unsafe fn instr32_F7_0_mem(mut addr: i32, mut imm: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_F7_0_mem(addr: i32, imm: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); test32(____0, imm); } #[no_mangle] -pub unsafe fn instr32_F7_0_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_F7_0_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); test32(____0, imm); } #[no_mangle] -pub unsafe fn instr32_F7_1_mem(mut addr: i32, mut imm: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_F7_1_mem(addr: i32, imm: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); test32(____0, imm); } #[no_mangle] -pub unsafe fn instr32_F7_1_reg(mut r1: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_F7_1_reg(r1: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); test32(____0, imm); } #[no_mangle] -pub unsafe fn instr32_F7_2_mem(mut addr: i32) { +pub unsafe fn instr32_F7_2_mem(addr: i32) { SAFE_READ_WRITE32!(___, addr, !___); } #[no_mangle] -pub unsafe fn instr32_F7_2_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_F7_2_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, !____0); } #[no_mangle] -pub unsafe fn instr32_F7_3_mem(mut addr: i32) { +pub unsafe fn instr32_F7_3_mem(addr: i32) { SAFE_READ_WRITE32!(___, addr, neg32(___)); } #[no_mangle] -pub unsafe fn instr32_F7_3_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_F7_3_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, neg32(____0)); } #[no_mangle] -pub unsafe fn instr32_F7_4_mem(mut addr: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_F7_4_mem(addr: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); mul32(____0); } #[no_mangle] -pub unsafe fn instr32_F7_4_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_F7_4_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); mul32(____0); } #[no_mangle] -pub unsafe fn instr32_F7_5_mem(mut addr: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_F7_5_mem(addr: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); imul32(____0); } #[no_mangle] -pub unsafe fn instr32_F7_5_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_F7_5_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); imul32(____0); } #[no_mangle] -pub unsafe fn instr32_F7_6_mem(mut addr: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_F7_6_mem(addr: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); div32(____0 as u32); } #[no_mangle] -pub unsafe fn instr32_F7_6_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_F7_6_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); div32(____0 as u32); } #[no_mangle] -pub unsafe fn instr32_F7_7_mem(mut addr: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_F7_7_mem(addr: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); idiv32(____0); } #[no_mangle] -pub unsafe fn instr32_F7_7_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_F7_7_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); idiv32(____0); } #[no_mangle] @@ -3222,7 +3222,7 @@ pub unsafe fn instr_FA() { #[no_mangle] pub unsafe fn instr_FB() { // sti - let mut old_if: i32 = *flags & FLAG_INTERRUPT; + let old_if: i32 = *flags & FLAG_INTERRUPT; if !*protected_mode || 0 != if 0 != *flags & FLAG_VM { (getiopl() == 3) as i32 } @@ -3259,157 +3259,157 @@ pub unsafe fn instr_FD() { *flags |= FLAG_DIRECTION; } #[no_mangle] -pub unsafe fn instr_FE_0_mem(mut addr: i32) { +pub unsafe fn instr_FE_0_mem(addr: i32) { SAFE_READ_WRITE8!(___, addr, inc8(___)); } #[no_mangle] -pub unsafe fn instr_FE_0_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_FE_0_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, inc8(____0)); } #[no_mangle] -pub unsafe fn instr_FE_1_mem(mut addr: i32) { +pub unsafe fn instr_FE_1_mem(addr: i32) { SAFE_READ_WRITE8!(___, addr, dec8(___)); } #[no_mangle] -pub unsafe fn instr_FE_1_reg(mut r1: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_FE_1_reg(r1: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, dec8(____0)); } #[no_mangle] -pub unsafe fn instr16_FF_0_mem(mut addr: i32) { +pub unsafe fn instr16_FF_0_mem(addr: i32) { SAFE_READ_WRITE16!(___, addr, inc16(___)); } #[no_mangle] -pub unsafe fn instr16_FF_0_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_FF_0_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, inc16(____0)); } #[no_mangle] -pub unsafe fn instr16_FF_1_mem(mut addr: i32) { +pub unsafe fn instr16_FF_1_mem(addr: i32) { SAFE_READ_WRITE16!(___, addr, dec16(___)); } #[no_mangle] -pub unsafe fn instr16_FF_1_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_FF_1_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, dec16(____0)); } #[no_mangle] -pub unsafe fn instr16_FF_2_helper(mut data: i32) { +pub unsafe fn instr16_FF_2_helper(data: i32) { // call near - let mut cs: i32 = get_seg_cs(); + let cs: i32 = get_seg_cs(); return_on_pagefault!(push16(get_real_eip())); *instruction_pointer = cs + data; dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] -pub unsafe fn instr16_FF_2_mem(mut addr: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_FF_2_mem(addr: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); instr16_FF_2_helper(____0); } #[no_mangle] -pub unsafe fn instr16_FF_2_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_FF_2_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); instr16_FF_2_helper(____0); } #[no_mangle] -pub unsafe fn instr16_FF_3_reg(mut r: i32) { +pub unsafe fn instr16_FF_3_reg(r: i32) { dbg_log!("callf #ud"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_FF_3_mem(mut addr: i32) { +pub unsafe fn instr16_FF_3_mem(addr: i32) { // callf - let mut new_ip: i32 = return_on_pagefault!(safe_read16(addr)); - let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 2)); + let new_ip: i32 = return_on_pagefault!(safe_read16(addr)); + let new_cs: i32 = return_on_pagefault!(safe_read16(addr + 2)); far_jump(new_ip, new_cs, true); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] -pub unsafe fn instr16_FF_4_helper(mut data: i32) { +pub unsafe fn instr16_FF_4_helper(data: i32) { // jmp near *instruction_pointer = get_seg_cs() + data; dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] -pub unsafe fn instr16_FF_4_mem(mut addr: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_FF_4_mem(addr: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); instr16_FF_4_helper(____0); } #[no_mangle] -pub unsafe fn instr16_FF_4_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_FF_4_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); instr16_FF_4_helper(____0); } #[no_mangle] -pub unsafe fn instr16_FF_5_reg(mut r: i32) { +pub unsafe fn instr16_FF_5_reg(r: i32) { dbg_log!("jmpf #ud"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_FF_5_mem(mut addr: i32) { +pub unsafe fn instr16_FF_5_mem(addr: i32) { // jmpf - let mut new_ip: i32 = return_on_pagefault!(safe_read16(addr)); - let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 2)); + let new_ip: i32 = return_on_pagefault!(safe_read16(addr)); + let new_cs: i32 = return_on_pagefault!(safe_read16(addr + 2)); far_jump(new_ip, new_cs, false); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] -pub unsafe fn instr16_FF_6_mem(mut addr: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_FF_6_mem(addr: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); return_on_pagefault!(push16(____0)); } #[no_mangle] -pub unsafe fn instr16_FF_6_reg(mut r1: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_FF_6_reg(r1: i32) { + let ____0: i32 = read_reg16(r1); return_on_pagefault!(push16(____0)); } #[no_mangle] -pub unsafe fn instr32_FF_0_mem(mut addr: i32) { +pub unsafe fn instr32_FF_0_mem(addr: i32) { SAFE_READ_WRITE32!(___, addr, inc32(___)); } #[no_mangle] -pub unsafe fn instr32_FF_0_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_FF_0_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, inc32(____0)); } #[no_mangle] -pub unsafe fn instr32_FF_1_mem(mut addr: i32) { +pub unsafe fn instr32_FF_1_mem(addr: i32) { SAFE_READ_WRITE32!(___, addr, dec32(___)); } #[no_mangle] -pub unsafe fn instr32_FF_1_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_FF_1_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, dec32(____0)); } #[no_mangle] -pub unsafe fn instr32_FF_2_helper(mut data: i32) { +pub unsafe fn instr32_FF_2_helper(data: i32) { // call near - let mut cs: i32 = get_seg_cs(); + let cs: i32 = get_seg_cs(); return_on_pagefault!(push32(get_real_eip())); dbg_assert!(0 != is_asize_32() as i32 || data < 65536); *instruction_pointer = cs + data; } #[no_mangle] -pub unsafe fn instr32_FF_2_mem(mut addr: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_FF_2_mem(addr: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); instr32_FF_2_helper(____0); } #[no_mangle] -pub unsafe fn instr32_FF_2_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_FF_2_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); instr32_FF_2_helper(____0); } #[no_mangle] -pub unsafe fn instr32_FF_3_reg(mut r: i32) { +pub unsafe fn instr32_FF_3_reg(r: i32) { dbg_log!("callf #ud"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr32_FF_3_mem(mut addr: i32) { +pub unsafe fn instr32_FF_3_mem(addr: i32) { // callf - let mut new_ip: i32 = return_on_pagefault!(safe_read32s(addr)); - let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 4)); + let new_ip: i32 = return_on_pagefault!(safe_read32s(addr)); + let new_cs: i32 = return_on_pagefault!(safe_read16(addr + 4)); if !*protected_mode || 0 != vm86_mode() as i32 { if 0 != new_ip as u32 & 4294901760 { dbg_assert!(0 != 0); @@ -3419,31 +3419,31 @@ pub unsafe fn instr32_FF_3_mem(mut addr: i32) { dbg_assert!(0 != is_asize_32() as i32 || new_ip < 65536); } #[no_mangle] -pub unsafe fn instr32_FF_4_helper(mut data: i32) { +pub unsafe fn instr32_FF_4_helper(data: i32) { // jmp near dbg_assert!(0 != is_asize_32() as i32 || data < 65536); *instruction_pointer = get_seg_cs() + data; } #[no_mangle] -pub unsafe fn instr32_FF_4_mem(mut addr: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_FF_4_mem(addr: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); instr32_FF_4_helper(____0); } #[no_mangle] -pub unsafe fn instr32_FF_4_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_FF_4_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); instr32_FF_4_helper(____0); } #[no_mangle] -pub unsafe fn instr32_FF_5_reg(mut r: i32) { +pub unsafe fn instr32_FF_5_reg(r: i32) { dbg_log!("jmpf #ud"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr32_FF_5_mem(mut addr: i32) { +pub unsafe fn instr32_FF_5_mem(addr: i32) { // jmpf - let mut new_ip: i32 = return_on_pagefault!(safe_read32s(addr)); - let mut new_cs: i32 = return_on_pagefault!(safe_read16(addr + 4)); + let new_ip: i32 = return_on_pagefault!(safe_read32s(addr)); + let new_cs: i32 = return_on_pagefault!(safe_read16(addr + 4)); if !*protected_mode || 0 != vm86_mode() as i32 { if 0 != new_ip as u32 & 4294901760 { dbg_assert!(0 != 0); @@ -3453,13 +3453,13 @@ pub unsafe fn instr32_FF_5_mem(mut addr: i32) { dbg_assert!(0 != is_asize_32() as i32 || new_ip < 65536); } #[no_mangle] -pub unsafe fn instr32_FF_6_mem(mut addr: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_FF_6_mem(addr: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); return_on_pagefault!(push32(____0)); } #[no_mangle] -pub unsafe fn instr32_FF_6_reg(mut r1: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_FF_6_reg(r1: i32) { + let ____0: i32 = read_reg32(r1); return_on_pagefault!(push32(____0)); } #[no_mangle] @@ -3487,69 +3487,69 @@ pub unsafe fn instr32_F26F() { outsd_rep(); } #[no_mangle] pub unsafe fn instr32_F36F() { outsd_rep(); } #[no_mangle] -pub unsafe fn instr16_70(mut imm8: i32) { jmpcc16(test_o(), imm8); } +pub unsafe fn instr16_70(imm8: i32) { jmpcc16(test_o(), imm8); } #[no_mangle] -pub unsafe fn instr16_71(mut imm8: i32) { jmpcc16(!test_o(), imm8); } +pub unsafe fn instr16_71(imm8: i32) { jmpcc16(!test_o(), imm8); } #[no_mangle] -pub unsafe fn instr16_72(mut imm8: i32) { jmpcc16(test_b(), imm8); } +pub unsafe fn instr16_72(imm8: i32) { jmpcc16(test_b(), imm8); } #[no_mangle] -pub unsafe fn instr16_73(mut imm8: i32) { jmpcc16(!test_b(), imm8); } +pub unsafe fn instr16_73(imm8: i32) { jmpcc16(!test_b(), imm8); } #[no_mangle] -pub unsafe fn instr16_74(mut imm8: i32) { jmpcc16(test_z(), imm8); } +pub unsafe fn instr16_74(imm8: i32) { jmpcc16(test_z(), imm8); } #[no_mangle] -pub unsafe fn instr16_75(mut imm8: i32) { jmpcc16(!test_z(), imm8); } +pub unsafe fn instr16_75(imm8: i32) { jmpcc16(!test_z(), imm8); } #[no_mangle] -pub unsafe fn instr16_76(mut imm8: i32) { jmpcc16(test_be(), imm8); } +pub unsafe fn instr16_76(imm8: i32) { jmpcc16(test_be(), imm8); } #[no_mangle] -pub unsafe fn instr16_77(mut imm8: i32) { jmpcc16(!test_be(), imm8); } +pub unsafe fn instr16_77(imm8: i32) { jmpcc16(!test_be(), imm8); } #[no_mangle] -pub unsafe fn instr16_78(mut imm8: i32) { jmpcc16(test_s(), imm8); } +pub unsafe fn instr16_78(imm8: i32) { jmpcc16(test_s(), imm8); } #[no_mangle] -pub unsafe fn instr16_79(mut imm8: i32) { jmpcc16(!test_s(), imm8); } +pub unsafe fn instr16_79(imm8: i32) { jmpcc16(!test_s(), imm8); } #[no_mangle] -pub unsafe fn instr16_7A(mut imm8: i32) { jmpcc16(test_p(), imm8); } +pub unsafe fn instr16_7A(imm8: i32) { jmpcc16(test_p(), imm8); } #[no_mangle] -pub unsafe fn instr16_7B(mut imm8: i32) { jmpcc16(!test_p(), imm8); } +pub unsafe fn instr16_7B(imm8: i32) { jmpcc16(!test_p(), imm8); } #[no_mangle] -pub unsafe fn instr16_7C(mut imm8: i32) { jmpcc16(test_l(), imm8); } +pub unsafe fn instr16_7C(imm8: i32) { jmpcc16(test_l(), imm8); } #[no_mangle] -pub unsafe fn instr16_7D(mut imm8: i32) { jmpcc16(!test_l(), imm8); } +pub unsafe fn instr16_7D(imm8: i32) { jmpcc16(!test_l(), imm8); } #[no_mangle] -pub unsafe fn instr16_7E(mut imm8: i32) { jmpcc16(test_le(), imm8); } +pub unsafe fn instr16_7E(imm8: i32) { jmpcc16(test_le(), imm8); } #[no_mangle] -pub unsafe fn instr16_7F(mut imm8: i32) { jmpcc16(!test_le(), imm8); } +pub unsafe fn instr16_7F(imm8: i32) { jmpcc16(!test_le(), imm8); } #[no_mangle] -pub unsafe fn instr32_70(mut imm8: i32) { jmpcc32(test_o(), imm8); } +pub unsafe fn instr32_70(imm8: i32) { jmpcc32(test_o(), imm8); } #[no_mangle] -pub unsafe fn instr32_71(mut imm8: i32) { jmpcc32(!test_o(), imm8); } +pub unsafe fn instr32_71(imm8: i32) { jmpcc32(!test_o(), imm8); } #[no_mangle] -pub unsafe fn instr32_72(mut imm8: i32) { jmpcc32(test_b(), imm8); } +pub unsafe fn instr32_72(imm8: i32) { jmpcc32(test_b(), imm8); } #[no_mangle] -pub unsafe fn instr32_73(mut imm8: i32) { jmpcc32(!test_b(), imm8); } +pub unsafe fn instr32_73(imm8: i32) { jmpcc32(!test_b(), imm8); } #[no_mangle] -pub unsafe fn instr32_74(mut imm8: i32) { jmpcc32(test_z(), imm8); } +pub unsafe fn instr32_74(imm8: i32) { jmpcc32(test_z(), imm8); } #[no_mangle] -pub unsafe fn instr32_75(mut imm8: i32) { jmpcc32(!test_z(), imm8); } +pub unsafe fn instr32_75(imm8: i32) { jmpcc32(!test_z(), imm8); } #[no_mangle] -pub unsafe fn instr32_76(mut imm8: i32) { jmpcc32(test_be(), imm8); } +pub unsafe fn instr32_76(imm8: i32) { jmpcc32(test_be(), imm8); } #[no_mangle] -pub unsafe fn instr32_77(mut imm8: i32) { jmpcc32(!test_be(), imm8); } +pub unsafe fn instr32_77(imm8: i32) { jmpcc32(!test_be(), imm8); } #[no_mangle] -pub unsafe fn instr32_78(mut imm8: i32) { jmpcc32(test_s(), imm8); } +pub unsafe fn instr32_78(imm8: i32) { jmpcc32(test_s(), imm8); } #[no_mangle] -pub unsafe fn instr32_79(mut imm8: i32) { jmpcc32(!test_s(), imm8); } +pub unsafe fn instr32_79(imm8: i32) { jmpcc32(!test_s(), imm8); } #[no_mangle] -pub unsafe fn instr32_7A(mut imm8: i32) { jmpcc32(test_p(), imm8); } +pub unsafe fn instr32_7A(imm8: i32) { jmpcc32(test_p(), imm8); } #[no_mangle] -pub unsafe fn instr32_7B(mut imm8: i32) { jmpcc32(!test_p(), imm8); } +pub unsafe fn instr32_7B(imm8: i32) { jmpcc32(!test_p(), imm8); } #[no_mangle] -pub unsafe fn instr32_7C(mut imm8: i32) { jmpcc32(test_l(), imm8); } +pub unsafe fn instr32_7C(imm8: i32) { jmpcc32(test_l(), imm8); } #[no_mangle] -pub unsafe fn instr32_7D(mut imm8: i32) { jmpcc32(!test_l(), imm8); } +pub unsafe fn instr32_7D(imm8: i32) { jmpcc32(!test_l(), imm8); } #[no_mangle] -pub unsafe fn instr32_7E(mut imm8: i32) { jmpcc32(test_le(), imm8); } +pub unsafe fn instr32_7E(imm8: i32) { jmpcc32(test_le(), imm8); } #[no_mangle] -pub unsafe fn instr32_7F(mut imm8: i32) { jmpcc32(!test_le(), imm8); } +pub unsafe fn instr32_7F(imm8: i32) { jmpcc32(!test_le(), imm8); } #[no_mangle] pub unsafe fn instr_F2A4() { movsb_rep(); } #[no_mangle] @@ -3611,122 +3611,122 @@ pub unsafe fn instr32_F2AF() { scasd_rep(PREFIX_F2); } #[no_mangle] pub unsafe fn instr32_F3AF() { scasd_rep(PREFIX_F3); } #[no_mangle] -pub unsafe fn instr_D8_0_mem(mut addr: i32) { - let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); +pub unsafe fn instr_D8_0_mem(addr: i32) { + let ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fadd(0, ____0); } #[no_mangle] -pub unsafe fn instr_D8_0_reg(mut r: i32) { - let mut ____0: f64 = fpu_get_sti(r); +pub unsafe fn instr_D8_0_reg(r: i32) { + let ____0: f64 = fpu_get_sti(r); fpu_fadd(0, ____0); } #[no_mangle] -pub unsafe fn instr_D8_1_mem(mut addr: i32) { - let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); +pub unsafe fn instr_D8_1_mem(addr: i32) { + let ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fmul(0, ____0); } #[no_mangle] -pub unsafe fn instr_D8_1_reg(mut r: i32) { - let mut ____0: f64 = fpu_get_sti(r); +pub unsafe fn instr_D8_1_reg(r: i32) { + let ____0: f64 = fpu_get_sti(r); fpu_fmul(0, ____0); } #[no_mangle] -pub unsafe fn instr_D8_2_mem(mut addr: i32) { - let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); +pub unsafe fn instr_D8_2_mem(addr: i32) { + let ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fcom(____0); } #[no_mangle] -pub unsafe fn instr_D8_2_reg(mut r: i32) { - let mut ____0: f64 = fpu_get_sti(r); +pub unsafe fn instr_D8_2_reg(r: i32) { + let ____0: f64 = fpu_get_sti(r); fpu_fcom(____0); } #[no_mangle] -pub unsafe fn instr_D8_3_mem(mut addr: i32) { - let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); +pub unsafe fn instr_D8_3_mem(addr: i32) { + let ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fcomp(____0); } #[no_mangle] -pub unsafe fn instr_D8_3_reg(mut r: i32) { - let mut ____0: f64 = fpu_get_sti(r); +pub unsafe fn instr_D8_3_reg(r: i32) { + let ____0: f64 = fpu_get_sti(r); fpu_fcomp(____0); } #[no_mangle] -pub unsafe fn instr_D8_4_mem(mut addr: i32) { - let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); +pub unsafe fn instr_D8_4_mem(addr: i32) { + let ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fsub(0, ____0); } #[no_mangle] -pub unsafe fn instr_D8_4_reg(mut r: i32) { - let mut ____0: f64 = fpu_get_sti(r); +pub unsafe fn instr_D8_4_reg(r: i32) { + let ____0: f64 = fpu_get_sti(r); fpu_fsub(0, ____0); } #[no_mangle] -pub unsafe fn instr_D8_5_mem(mut addr: i32) { - let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); +pub unsafe fn instr_D8_5_mem(addr: i32) { + let ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fsubr(0, ____0); } #[no_mangle] -pub unsafe fn instr_D8_5_reg(mut r: i32) { - let mut ____0: f64 = fpu_get_sti(r); +pub unsafe fn instr_D8_5_reg(r: i32) { + let ____0: f64 = fpu_get_sti(r); fpu_fsubr(0, ____0); } #[no_mangle] -pub unsafe fn instr_D8_6_mem(mut addr: i32) { - let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); +pub unsafe fn instr_D8_6_mem(addr: i32) { + let ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fdiv(0, ____0); } #[no_mangle] -pub unsafe fn instr_D8_6_reg(mut r: i32) { - let mut ____0: f64 = fpu_get_sti(r); +pub unsafe fn instr_D8_6_reg(r: i32) { + let ____0: f64 = fpu_get_sti(r); fpu_fdiv(0, ____0); } #[no_mangle] -pub unsafe fn instr_D8_7_mem(mut addr: i32) { - let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); +pub unsafe fn instr_D8_7_mem(addr: i32) { + let ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_fdivr(0, ____0); } #[no_mangle] -pub unsafe fn instr_D8_7_reg(mut r: i32) { - let mut ____0: f64 = fpu_get_sti(r); +pub unsafe fn instr_D8_7_reg(r: i32) { + let ____0: f64 = fpu_get_sti(r); fpu_fdivr(0, ____0); } #[no_mangle] -pub unsafe fn instr_D9_0_mem(mut addr: i32) { - let mut ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); +pub unsafe fn instr_D9_0_mem(addr: i32) { + let ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); fpu_push(____0); } #[no_mangle] -pub unsafe fn instr_D9_0_reg(mut r: i32) { - let mut ____0: f64 = fpu_get_sti(r); +pub unsafe fn instr_D9_0_reg(r: i32) { + let ____0: f64 = fpu_get_sti(r); fpu_push(____0); } #[no_mangle] -pub unsafe fn instr_D9_1_mem(mut addr: i32) { +pub unsafe fn instr_D9_1_mem(addr: i32) { dbg_log!("d9/1"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr_D9_1_reg(mut r: i32) { fpu_fxch(r); } +pub unsafe fn instr_D9_1_reg(r: i32) { fpu_fxch(r); } #[no_mangle] -pub unsafe fn instr_D9_2_mem(mut addr: i32) { fpu_fstm32(addr); } +pub unsafe fn instr_D9_2_mem(addr: i32) { fpu_fstm32(addr); } #[no_mangle] -pub unsafe fn instr_D9_2_reg(mut r: i32) { +pub unsafe fn instr_D9_2_reg(r: i32) { if r != 0 { trigger_ud(); }; } #[no_mangle] -pub unsafe fn instr_D9_3_mem(mut addr: i32) { fpu_fstm32p(addr); } +pub unsafe fn instr_D9_3_mem(addr: i32) { fpu_fstm32p(addr); } #[no_mangle] -pub unsafe fn instr_D9_3_reg(mut r: i32) { +pub unsafe fn instr_D9_3_reg(r: i32) { dbg_log!("fstp1"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr_D9_4_mem(mut addr: i32) { fpu_fldenv(addr); } +pub unsafe fn instr_D9_4_mem(addr: i32) { fpu_fldenv(addr); } #[no_mangle] -pub unsafe fn instr_D9_4_reg(mut r: i32) { - let mut st0: f64 = fpu_get_st0(); +pub unsafe fn instr_D9_4_reg(r: i32) { + let st0: f64 = fpu_get_st0(); match r { 0 => { // fchs @@ -3749,9 +3749,9 @@ pub unsafe fn instr_D9_4_reg(mut r: i32) { }; } #[no_mangle] -pub unsafe fn instr_D9_5_mem(mut addr: i32) { fpu_fldcw(addr); } +pub unsafe fn instr_D9_5_mem(addr: i32) { fpu_fldcw(addr); } #[no_mangle] -pub unsafe fn instr_D9_5_reg(mut r: i32) { +pub unsafe fn instr_D9_5_reg(r: i32) { // fld1/fldl2t/fldl2e/fldpi/fldlg2/fldln2/fldz match r { 0 => { @@ -3783,10 +3783,10 @@ pub unsafe fn instr_D9_5_reg(mut r: i32) { }; } #[no_mangle] -pub unsafe fn instr_D9_6_mem(mut addr: i32) { fpu_fstenv(addr); } +pub unsafe fn instr_D9_6_mem(addr: i32) { fpu_fstenv(addr); } #[no_mangle] -pub unsafe fn instr_D9_6_reg(mut r: i32) { - let mut st0: f64 = fpu_get_st0(); +pub unsafe fn instr_D9_6_reg(r: i32) { + let st0: f64 = fpu_get_st0(); match r { 0 => { // f2xm1 @@ -3834,10 +3834,10 @@ pub unsafe fn instr_D9_6_reg(mut r: i32) { }; } #[no_mangle] -pub unsafe fn instr_D9_7_mem(mut addr: i32) { fpu_fstcw(addr); } +pub unsafe fn instr_D9_7_mem(addr: i32) { fpu_fstcw(addr); } #[no_mangle] -pub unsafe fn instr_D9_7_reg(mut r: i32) { - let mut st0: f64 = fpu_get_st0(); +pub unsafe fn instr_D9_7_reg(r: i32) { + let st0: f64 = fpu_get_st0(); match r { 0 => { fpu_fprem(); @@ -3870,49 +3870,49 @@ pub unsafe fn instr_D9_7_reg(mut r: i32) { }; } #[no_mangle] -pub unsafe fn instr_DA_0_mem(mut addr: i32) { +pub unsafe fn instr_DA_0_mem(addr: i32) { fpu_fadd(0, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe fn instr_DA_1_mem(mut addr: i32) { +pub unsafe fn instr_DA_1_mem(addr: i32) { fpu_fmul(0, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe fn instr_DA_2_mem(mut addr: i32) { +pub unsafe fn instr_DA_2_mem(addr: i32) { fpu_fcom(return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe fn instr_DA_3_mem(mut addr: i32) { +pub unsafe fn instr_DA_3_mem(addr: i32) { fpu_fcomp(return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe fn instr_DA_4_mem(mut addr: i32) { +pub unsafe fn instr_DA_4_mem(addr: i32) { fpu_fsub(0, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe fn instr_DA_5_mem(mut addr: i32) { +pub unsafe fn instr_DA_5_mem(addr: i32) { fpu_fsubr(0, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe fn instr_DA_6_mem(mut addr: i32) { +pub unsafe fn instr_DA_6_mem(addr: i32) { fpu_fdiv(0, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe fn instr_DA_7_mem(mut addr: i32) { +pub unsafe fn instr_DA_7_mem(addr: i32) { fpu_fdivr(0, return_on_pagefault!(safe_read32s(addr)) as f64); } #[no_mangle] -pub unsafe fn instr_DA_0_reg(mut r: i32) { fpu_fcmovcc(test_b(), r); } +pub unsafe fn instr_DA_0_reg(r: i32) { fpu_fcmovcc(test_b(), r); } #[no_mangle] -pub unsafe fn instr_DA_1_reg(mut r: i32) { fpu_fcmovcc(test_z(), r); } +pub unsafe fn instr_DA_1_reg(r: i32) { fpu_fcmovcc(test_z(), r); } #[no_mangle] -pub unsafe fn instr_DA_2_reg(mut r: i32) { fpu_fcmovcc(test_be(), r); } +pub unsafe fn instr_DA_2_reg(r: i32) { fpu_fcmovcc(test_be(), r); } #[no_mangle] -pub unsafe fn instr_DA_3_reg(mut r: i32) { fpu_fcmovcc(test_p(), r); } +pub unsafe fn instr_DA_3_reg(r: i32) { fpu_fcmovcc(test_p(), r); } #[no_mangle] -pub unsafe fn instr_DA_4_reg(mut r: i32) { trigger_ud(); } +pub unsafe fn instr_DA_4_reg(r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DA_5_reg(mut r: i32) { +pub unsafe fn instr_DA_5_reg(r: i32) { if r == 1 { fpu_fucompp(); } @@ -3921,35 +3921,35 @@ pub unsafe fn instr_DA_5_reg(mut r: i32) { }; } #[no_mangle] -pub unsafe fn instr_DA_6_reg(mut r: i32) { trigger_ud(); } +pub unsafe fn instr_DA_6_reg(r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DA_7_reg(mut r: i32) { trigger_ud(); } +pub unsafe fn instr_DA_7_reg(r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DB_0_mem(mut addr: i32) { fpu_fldm32(addr); } +pub unsafe fn instr_DB_0_mem(addr: i32) { fpu_fldm32(addr); } #[no_mangle] -pub unsafe fn instr_DB_1_mem(mut addr: i32) { trigger_ud(); } +pub unsafe fn instr_DB_1_mem(addr: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DB_2_mem(mut addr: i32) { fpu_fistm32(addr); } +pub unsafe fn instr_DB_2_mem(addr: i32) { fpu_fistm32(addr); } #[no_mangle] -pub unsafe fn instr_DB_3_mem(mut addr: i32) { fpu_fistm32p(addr); } +pub unsafe fn instr_DB_3_mem(addr: i32) { fpu_fistm32p(addr); } #[no_mangle] -pub unsafe fn instr_DB_4_mem(mut addr: i32) { trigger_ud(); } +pub unsafe fn instr_DB_4_mem(addr: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DB_5_mem(mut addr: i32) { fpu_fldm80(addr); } +pub unsafe fn instr_DB_5_mem(addr: i32) { fpu_fldm80(addr); } #[no_mangle] -pub unsafe fn instr_DB_6_mem(mut addr: i32) { trigger_ud(); } +pub unsafe fn instr_DB_6_mem(addr: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DB_7_mem(mut addr: i32) { fpu_fst80p(addr); } +pub unsafe fn instr_DB_7_mem(addr: i32) { fpu_fst80p(addr); } #[no_mangle] -pub unsafe fn instr_DB_0_reg(mut r: i32) { fpu_fcmovcc(!test_b(), r); } +pub unsafe fn instr_DB_0_reg(r: i32) { fpu_fcmovcc(!test_b(), r); } #[no_mangle] -pub unsafe fn instr_DB_1_reg(mut r: i32) { fpu_fcmovcc(!test_z(), r); } +pub unsafe fn instr_DB_1_reg(r: i32) { fpu_fcmovcc(!test_z(), r); } #[no_mangle] -pub unsafe fn instr_DB_2_reg(mut r: i32) { fpu_fcmovcc(!test_be(), r); } +pub unsafe fn instr_DB_2_reg(r: i32) { fpu_fcmovcc(!test_be(), r); } #[no_mangle] -pub unsafe fn instr_DB_3_reg(mut r: i32) { fpu_fcmovcc(!test_p(), r); } +pub unsafe fn instr_DB_3_reg(r: i32) { fpu_fcmovcc(!test_p(), r); } #[no_mangle] -pub unsafe fn instr_DB_4_reg(mut r: i32) { +pub unsafe fn instr_DB_4_reg(r: i32) { if r == 3 { fpu_finit(); } @@ -3964,202 +3964,190 @@ pub unsafe fn instr_DB_4_reg(mut r: i32) { }; } #[no_mangle] -pub unsafe fn instr_DB_5_reg(mut r: i32) { fpu_fucomi(r); } +pub unsafe fn instr_DB_5_reg(r: i32) { fpu_fucomi(r); } #[no_mangle] -pub unsafe fn instr_DB_6_reg(mut r: i32) { fpu_fcomi(r); } +pub unsafe fn instr_DB_6_reg(r: i32) { fpu_fcomi(r); } #[no_mangle] -pub unsafe fn instr_DB_7_reg(mut r: i32) { trigger_ud(); } +pub unsafe fn instr_DB_7_reg(r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DC_0_mem(mut addr: i32) { - fpu_fadd(0, return_on_pagefault!(fpu_load_m64(addr))); -} +pub unsafe fn instr_DC_0_mem(addr: i32) { fpu_fadd(0, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe fn instr_DC_1_mem(mut addr: i32) { - fpu_fmul(0, return_on_pagefault!(fpu_load_m64(addr))); -} +pub unsafe fn instr_DC_1_mem(addr: i32) { fpu_fmul(0, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe fn instr_DC_2_mem(mut addr: i32) { fpu_fcom(return_on_pagefault!(fpu_load_m64(addr))); } +pub unsafe fn instr_DC_2_mem(addr: i32) { fpu_fcom(return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe fn instr_DC_3_mem(mut addr: i32) { fpu_fcomp(return_on_pagefault!(fpu_load_m64(addr))); } +pub unsafe fn instr_DC_3_mem(addr: i32) { fpu_fcomp(return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe fn instr_DC_4_mem(mut addr: i32) { - fpu_fsub(0, return_on_pagefault!(fpu_load_m64(addr))); -} +pub unsafe fn instr_DC_4_mem(addr: i32) { fpu_fsub(0, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe fn instr_DC_5_mem(mut addr: i32) { - fpu_fsubr(0, return_on_pagefault!(fpu_load_m64(addr))); -} +pub unsafe fn instr_DC_5_mem(addr: i32) { fpu_fsubr(0, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe fn instr_DC_6_mem(mut addr: i32) { - fpu_fdiv(0, return_on_pagefault!(fpu_load_m64(addr))); -} +pub unsafe fn instr_DC_6_mem(addr: i32) { fpu_fdiv(0, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe fn instr_DC_7_mem(mut addr: i32) { - fpu_fdivr(0, return_on_pagefault!(fpu_load_m64(addr))); -} +pub unsafe fn instr_DC_7_mem(addr: i32) { fpu_fdivr(0, return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe fn instr_DC_0_reg(mut r: i32) { fpu_fadd(r, fpu_get_sti(r)); } +pub unsafe fn instr_DC_0_reg(r: i32) { fpu_fadd(r, fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_DC_1_reg(mut r: i32) { fpu_fmul(r, fpu_get_sti(r)); } +pub unsafe fn instr_DC_1_reg(r: i32) { fpu_fmul(r, fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_DC_2_reg(mut r: i32) { fpu_fcom(fpu_get_sti(r)); } +pub unsafe fn instr_DC_2_reg(r: i32) { fpu_fcom(fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_DC_3_reg(mut r: i32) { fpu_fcomp(fpu_get_sti(r)); } +pub unsafe fn instr_DC_3_reg(r: i32) { fpu_fcomp(fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_DC_4_reg(mut r: i32) { fpu_fsub(r, fpu_get_sti(r)); } +pub unsafe fn instr_DC_4_reg(r: i32) { fpu_fsub(r, fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_DC_5_reg(mut r: i32) { fpu_fsubr(r, fpu_get_sti(r)); } +pub unsafe fn instr_DC_5_reg(r: i32) { fpu_fsubr(r, fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_DC_6_reg(mut r: i32) { fpu_fdiv(r, fpu_get_sti(r)); } +pub unsafe fn instr_DC_6_reg(r: i32) { fpu_fdiv(r, fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_DC_7_reg(mut r: i32) { fpu_fdivr(r, fpu_get_sti(r)); } +pub unsafe fn instr_DC_7_reg(r: i32) { fpu_fdivr(r, fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_DD_0_mem(mut addr: i32) { fpu_fldm64(addr); } +pub unsafe fn instr_DD_0_mem(addr: i32) { fpu_fldm64(addr); } #[no_mangle] -pub unsafe fn instr_DD_1_mem(mut addr: i32) { +pub unsafe fn instr_DD_1_mem(addr: i32) { dbg_log!("fisttp"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DD_2_mem(mut addr: i32) { fpu_fstm64(addr); } +pub unsafe fn instr_DD_2_mem(addr: i32) { fpu_fstm64(addr); } #[no_mangle] -pub unsafe fn instr_DD_3_mem(mut addr: i32) { fpu_fstm64p(addr); } +pub unsafe fn instr_DD_3_mem(addr: i32) { fpu_fstm64p(addr); } #[no_mangle] -pub unsafe fn instr_DD_4_mem(mut addr: i32) { fpu_frstor(addr); } +pub unsafe fn instr_DD_4_mem(addr: i32) { fpu_frstor(addr); } #[no_mangle] -pub unsafe fn instr_DD_5_mem(mut addr: i32) { +pub unsafe fn instr_DD_5_mem(addr: i32) { dbg_log!("dd/5"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DD_6_mem(mut addr: i32) { fpu_fsave(addr); } +pub unsafe fn instr_DD_6_mem(addr: i32) { fpu_fsave(addr); } #[no_mangle] -pub unsafe fn instr_DD_7_mem(mut addr: i32) { fpu_fnstsw_mem(addr); } +pub unsafe fn instr_DD_7_mem(addr: i32) { fpu_fnstsw_mem(addr); } #[no_mangle] -pub unsafe fn instr_DD_0_reg(mut r: i32) { fpu_ffree(r); } +pub unsafe fn instr_DD_0_reg(r: i32) { fpu_ffree(r); } #[no_mangle] -pub unsafe fn instr_DD_1_reg(mut r: i32) { trigger_ud(); } +pub unsafe fn instr_DD_1_reg(r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DD_2_reg(mut r: i32) { fpu_fst(r); } +pub unsafe fn instr_DD_2_reg(r: i32) { fpu_fst(r); } #[no_mangle] -pub unsafe fn instr_DD_3_reg(mut r: i32) { fpu_fstp(r); } +pub unsafe fn instr_DD_3_reg(r: i32) { fpu_fstp(r); } #[no_mangle] -pub unsafe fn instr_DD_4_reg(mut r: i32) { fpu_fucom(r); } +pub unsafe fn instr_DD_4_reg(r: i32) { fpu_fucom(r); } #[no_mangle] -pub unsafe fn instr_DD_5_reg(mut r: i32) { fpu_fucomp(r); } +pub unsafe fn instr_DD_5_reg(r: i32) { fpu_fucomp(r); } #[no_mangle] -pub unsafe fn instr_DD_6_reg(mut r: i32) { trigger_ud(); } +pub unsafe fn instr_DD_6_reg(r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DD_7_reg(mut r: i32) { trigger_ud(); } +pub unsafe fn instr_DD_7_reg(r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DE_0_mem(mut addr: i32) { +pub unsafe fn instr_DE_0_mem(addr: i32) { fpu_fadd(0, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe fn instr_DE_1_mem(mut addr: i32) { +pub unsafe fn instr_DE_1_mem(addr: i32) { fpu_fmul(0, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe fn instr_DE_2_mem(mut addr: i32) { +pub unsafe fn instr_DE_2_mem(addr: i32) { fpu_fcom(return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe fn instr_DE_3_mem(mut addr: i32) { +pub unsafe fn instr_DE_3_mem(addr: i32) { fpu_fcomp(return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe fn instr_DE_4_mem(mut addr: i32) { +pub unsafe fn instr_DE_4_mem(addr: i32) { fpu_fsub(0, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe fn instr_DE_5_mem(mut addr: i32) { +pub unsafe fn instr_DE_5_mem(addr: i32) { fpu_fsubr(0, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe fn instr_DE_6_mem(mut addr: i32) { +pub unsafe fn instr_DE_6_mem(addr: i32) { fpu_fdiv(0, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe fn instr_DE_7_mem(mut addr: i32) { +pub unsafe fn instr_DE_7_mem(addr: i32) { fpu_fdivr(0, return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe fn instr_DE_0_reg(mut r: i32) { +pub unsafe fn instr_DE_0_reg(r: i32) { fpu_fadd(r, fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe fn instr_DE_1_reg(mut r: i32) { +pub unsafe fn instr_DE_1_reg(r: i32) { fpu_fmul(r, fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe fn instr_DE_2_reg(mut r: i32) { +pub unsafe fn instr_DE_2_reg(r: i32) { fpu_fcom(fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe fn instr_DE_3_reg(mut r: i32) { +pub unsafe fn instr_DE_3_reg(r: i32) { fpu_fcomp(fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe fn instr_DE_4_reg(mut r: i32) { +pub unsafe fn instr_DE_4_reg(r: i32) { fpu_fsub(r, fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe fn instr_DE_5_reg(mut r: i32) { +pub unsafe fn instr_DE_5_reg(r: i32) { fpu_fsubr(r, fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe fn instr_DE_6_reg(mut r: i32) { +pub unsafe fn instr_DE_6_reg(r: i32) { fpu_fdiv(r, fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe fn instr_DE_7_reg(mut r: i32) { +pub unsafe fn instr_DE_7_reg(r: i32) { fpu_fdivr(r, fpu_get_sti(r)); fpu_pop(); } #[no_mangle] -pub unsafe fn instr_DF_0_mem(mut addr: i32) { +pub unsafe fn instr_DF_0_mem(addr: i32) { fpu_push(return_on_pagefault!(safe_read16(addr)) as i16 as f64); } #[no_mangle] -pub unsafe fn instr_DF_1_mem(mut addr: i32) { +pub unsafe fn instr_DF_1_mem(addr: i32) { dbg_log!("df/fisttp"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DF_2_mem(mut addr: i32) { fpu_fistm16(addr); } +pub unsafe fn instr_DF_2_mem(addr: i32) { fpu_fistm16(addr); } #[no_mangle] -pub unsafe fn instr_DF_3_mem(mut addr: i32) { fpu_fistm16p(addr); } +pub unsafe fn instr_DF_3_mem(addr: i32) { fpu_fistm16p(addr); } #[no_mangle] -pub unsafe fn instr_DF_4_mem(mut addr: i32) { +pub unsafe fn instr_DF_4_mem(addr: i32) { dbg_log!("fbld"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DF_5_mem(mut addr: i32) { fpu_fildm64(addr); } +pub unsafe fn instr_DF_5_mem(addr: i32) { fpu_fildm64(addr); } #[no_mangle] -pub unsafe fn instr_DF_6_mem(mut addr: i32) { +pub unsafe fn instr_DF_6_mem(addr: i32) { dbg_log!("fbstp"); trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DF_7_mem(mut addr: i32) { fpu_fistm64p(addr); } +pub unsafe fn instr_DF_7_mem(addr: i32) { fpu_fistm64p(addr); } #[no_mangle] -pub unsafe fn instr_DF_0_reg(mut r: i32) { trigger_ud(); } +pub unsafe fn instr_DF_0_reg(r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DF_1_reg(mut r: i32) { trigger_ud(); } +pub unsafe fn instr_DF_1_reg(r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DF_2_reg(mut r: i32) { trigger_ud(); } +pub unsafe fn instr_DF_2_reg(r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DF_3_reg(mut r: i32) { trigger_ud(); } +pub unsafe fn instr_DF_3_reg(r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_DF_4_reg(mut r: i32) { +pub unsafe fn instr_DF_4_reg(r: i32) { if r == 0 { fpu_fnstsw_reg(); } @@ -4168,35 +4156,35 @@ pub unsafe fn instr_DF_4_reg(mut r: i32) { }; } #[no_mangle] -pub unsafe fn instr_DF_5_reg(mut r: i32) { fpu_fucomip(r); } +pub unsafe fn instr_DF_5_reg(r: i32) { fpu_fucomip(r); } #[no_mangle] -pub unsafe fn instr_DF_6_reg(mut r: i32) { fpu_fcomip(r); } +pub unsafe fn instr_DF_6_reg(r: i32) { fpu_fcomip(r); } #[no_mangle] -pub unsafe fn instr_DF_7_reg(mut r: i32) { trigger_ud(); } +pub unsafe fn instr_DF_7_reg(r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_E0(mut imm8s: i32) { loopne16(imm8s); } +pub unsafe fn instr16_E0(imm8s: i32) { loopne16(imm8s); } #[no_mangle] -pub unsafe fn instr16_E1(mut imm8s: i32) { loope16(imm8s); } +pub unsafe fn instr16_E1(imm8s: i32) { loope16(imm8s); } #[no_mangle] -pub unsafe fn instr16_E2(mut imm8s: i32) { loop16(imm8s); } +pub unsafe fn instr16_E2(imm8s: i32) { loop16(imm8s); } #[no_mangle] -pub unsafe fn instr16_E3(mut imm8s: i32) { jcxz16(imm8s); } +pub unsafe fn instr16_E3(imm8s: i32) { jcxz16(imm8s); } #[no_mangle] -pub unsafe fn instr32_E0(mut imm8s: i32) { loopne32(imm8s); } +pub unsafe fn instr32_E0(imm8s: i32) { loopne32(imm8s); } #[no_mangle] -pub unsafe fn instr32_E1(mut imm8s: i32) { loope32(imm8s); } +pub unsafe fn instr32_E1(imm8s: i32) { loope32(imm8s); } #[no_mangle] -pub unsafe fn instr32_E2(mut imm8s: i32) { loop32(imm8s); } +pub unsafe fn instr32_E2(imm8s: i32) { loop32(imm8s); } #[no_mangle] -pub unsafe fn instr32_E3(mut imm8s: i32) { jcxz32(imm8s); } +pub unsafe fn instr32_E3(imm8s: i32) { jcxz32(imm8s); } #[no_mangle] -pub unsafe fn instr16_EB(mut imm8: i32) { +pub unsafe fn instr16_EB(imm8: i32) { // jmp near jmp_rel16(imm8); dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); } #[no_mangle] -pub unsafe fn instr32_EB(mut imm8: i32) { +pub unsafe fn instr32_EB(imm8: i32) { // jmp near *instruction_pointer = *instruction_pointer + imm8; dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 942e755f..11176c3e 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -1,9 +1,4 @@ -#![allow( - non_snake_case, - non_upper_case_globals, - unused_mut, - unused_variables, -)] +#![allow(non_snake_case, non_upper_case_globals, unused_variables)] extern "C" { #[no_mangle] @@ -57,7 +52,7 @@ pub static mut apic_enabled: bool = false; const ENABLE_ACPI: bool = false; #[no_mangle] -pub unsafe fn instr_0F00_0_mem(mut addr: i32) { +pub unsafe fn instr_0F00_0_mem(addr: i32) { // sldt if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); @@ -69,7 +64,7 @@ pub unsafe fn instr_0F00_0_mem(mut addr: i32) { }; } #[no_mangle] -pub unsafe fn instr_0F00_0_reg(mut r: i32) { +pub unsafe fn instr_0F00_0_reg(r: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -80,7 +75,7 @@ pub unsafe fn instr_0F00_0_reg(mut r: i32) { }; } #[no_mangle] -pub unsafe fn instr_0F00_1_mem(mut addr: i32) { +pub unsafe fn instr_0F00_1_mem(addr: i32) { // str if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); @@ -92,7 +87,7 @@ pub unsafe fn instr_0F00_1_mem(mut addr: i32) { }; } #[no_mangle] -pub unsafe fn instr_0F00_1_reg(mut r: i32) { +pub unsafe fn instr_0F00_1_reg(r: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -103,7 +98,7 @@ pub unsafe fn instr_0F00_1_reg(mut r: i32) { }; } #[no_mangle] -pub unsafe fn instr_0F00_2_mem(mut addr: i32) { +pub unsafe fn instr_0F00_2_mem(addr: i32) { // lldt if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); @@ -119,7 +114,7 @@ pub unsafe fn instr_0F00_2_mem(mut addr: i32) { }; } #[no_mangle] -pub unsafe fn instr_0F00_2_reg(mut r: i32) { +pub unsafe fn instr_0F00_2_reg(r: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -134,7 +129,7 @@ pub unsafe fn instr_0F00_2_reg(mut r: i32) { }; } #[no_mangle] -pub unsafe fn instr_0F00_3_mem(mut addr: i32) { +pub unsafe fn instr_0F00_3_mem(addr: i32) { // ltr if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); @@ -150,7 +145,7 @@ pub unsafe fn instr_0F00_3_mem(mut addr: i32) { }; } #[no_mangle] -pub unsafe fn instr_0F00_3_reg(mut r: i32) { +pub unsafe fn instr_0F00_3_reg(r: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -165,7 +160,7 @@ pub unsafe fn instr_0F00_3_reg(mut r: i32) { }; } #[no_mangle] -pub unsafe fn instr_0F00_4_mem(mut addr: i32) { +pub unsafe fn instr_0F00_4_mem(addr: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -176,7 +171,7 @@ pub unsafe fn instr_0F00_4_mem(mut addr: i32) { }; } #[no_mangle] -pub unsafe fn instr_0F00_4_reg(mut r: i32) { +pub unsafe fn instr_0F00_4_reg(r: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -187,7 +182,7 @@ pub unsafe fn instr_0F00_4_reg(mut r: i32) { }; } #[no_mangle] -pub unsafe fn instr_0F00_5_mem(mut addr: i32) { +pub unsafe fn instr_0F00_5_mem(addr: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -198,7 +193,7 @@ pub unsafe fn instr_0F00_5_mem(mut addr: i32) { }; } #[no_mangle] -pub unsafe fn instr_0F00_5_reg(mut r: i32) { +pub unsafe fn instr_0F00_5_reg(r: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { trigger_ud(); return; @@ -209,12 +204,12 @@ pub unsafe fn instr_0F00_5_reg(mut r: i32) { }; } #[no_mangle] -pub unsafe fn instr_0F01_0_reg(mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0F01_0_reg(r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F01_0_mem(mut addr: i32) { +pub unsafe fn instr_0F01_0_mem(addr: i32) { // sgdt return_on_pagefault!(writable_or_pagefault(addr, 6)); - let mut mask: i32 = if 0 != is_osize_32() as i32 { + let mask: i32 = if 0 != is_osize_32() as i32 { -1 } else { @@ -224,12 +219,12 @@ pub unsafe fn instr_0F01_0_mem(mut addr: i32) { safe_write32(addr + 2, *gdtr_offset & mask).unwrap(); } #[no_mangle] -pub unsafe fn instr_0F01_1_reg(mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0F01_1_reg(r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F01_1_mem(mut addr: i32) { +pub unsafe fn instr_0F01_1_mem(addr: i32) { // sidt return_on_pagefault!(writable_or_pagefault(addr, 6)); - let mut mask: i32 = if 0 != is_osize_32() as i32 { + let mask: i32 = if 0 != is_osize_32() as i32 { -1 } else { @@ -239,18 +234,18 @@ pub unsafe fn instr_0F01_1_mem(mut addr: i32) { safe_write32(addr + 2, *idtr_offset & mask).unwrap(); } #[no_mangle] -pub unsafe fn instr_0F01_2_reg(mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0F01_2_reg(r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F01_2_mem(mut addr: i32) { +pub unsafe fn instr_0F01_2_mem(addr: i32) { // lgdt if 0 != *cpl { trigger_gp_non_raising(0); return; } else { - let mut size: i32 = return_on_pagefault!(safe_read16(addr)); - let mut offset: i32 = return_on_pagefault!(safe_read32s(addr + 2)); - let mut mask: i32 = if 0 != is_osize_32() as i32 { + let size: i32 = return_on_pagefault!(safe_read16(addr)); + let offset: i32 = return_on_pagefault!(safe_read32s(addr + 2)); + let mask: i32 = if 0 != is_osize_32() as i32 { -1 } else { @@ -262,18 +257,18 @@ pub unsafe fn instr_0F01_2_mem(mut addr: i32) { }; } #[no_mangle] -pub unsafe fn instr_0F01_3_reg(mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0F01_3_reg(r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F01_3_mem(mut addr: i32) { +pub unsafe fn instr_0F01_3_mem(addr: i32) { // lidt if 0 != *cpl { trigger_gp_non_raising(0); return; } else { - let mut size: i32 = return_on_pagefault!(safe_read16(addr)); - let mut offset: i32 = return_on_pagefault!(safe_read32s(addr + 2)); - let mut mask: i32 = if 0 != is_osize_32() as i32 { + let size: i32 = return_on_pagefault!(safe_read16(addr)); + let offset: i32 = return_on_pagefault!(safe_read32s(addr + 2)); + let mask: i32 = if 0 != is_osize_32() as i32 { -1 } else { @@ -285,12 +280,12 @@ pub unsafe fn instr_0F01_3_mem(mut addr: i32) { }; } #[no_mangle] -pub unsafe fn instr_0F01_4_reg(mut r: i32) { +pub unsafe fn instr_0F01_4_reg(r: i32) { // smsw write_reg_osize(r, *cr); } #[no_mangle] -pub unsafe fn instr_0F01_4_mem(mut addr: i32) { +pub unsafe fn instr_0F01_4_mem(addr: i32) { return_on_pagefault!(safe_write16(addr, *cr & 65535)); } #[no_mangle] @@ -303,7 +298,7 @@ pub unsafe fn lmsw(mut new_cr0: i32) { set_cr0(new_cr0); } #[no_mangle] -pub unsafe fn instr_0F01_6_reg(mut r: i32) { +pub unsafe fn instr_0F01_6_reg(r: i32) { if 0 != *cpl { trigger_gp_non_raising(0); return; @@ -314,7 +309,7 @@ pub unsafe fn instr_0F01_6_reg(mut r: i32) { }; } #[no_mangle] -pub unsafe fn instr_0F01_6_mem(mut addr: i32) { +pub unsafe fn instr_0F01_6_mem(addr: i32) { if 0 != *cpl { trigger_gp_non_raising(0); return; @@ -325,9 +320,9 @@ pub unsafe fn instr_0F01_6_mem(mut addr: i32) { }; } #[no_mangle] -pub unsafe fn instr_0F01_7_reg(mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0F01_7_reg(r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F01_7_mem(mut addr: i32) { +pub unsafe fn instr_0F01_7_mem(addr: i32) { // invlpg if 0 != *cpl { trigger_gp_non_raising(0); @@ -339,43 +334,43 @@ pub unsafe fn instr_0F01_7_mem(mut addr: i32) { }; } #[no_mangle] -pub unsafe fn instr16_0F02_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0F02_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, lar(____0, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr16_0F02_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0F02_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r, lar(____0, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr32_0F02_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr32_0F02_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg32(r, lar(____0, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr32_0F02_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr32_0F02_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg32(r, lar(____0, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr16_0F03_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0F03_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, lsl(____0, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr16_0F03_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0F03_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r, lsl(____0, read_reg16(r))); } #[no_mangle] -pub unsafe fn instr32_0F03_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr32_0F03_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg32(r, lsl(____0, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr32_0F03_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr32_0F03_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg32(r, lsl(____0, read_reg32(r))); } #[no_mangle] @@ -432,21 +427,21 @@ pub unsafe fn instr_0F0E() { undefined_instruction(); } #[no_mangle] pub unsafe fn instr_0F0F() { undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0F10(mut source: reg128, mut r: i32) { +pub unsafe fn instr_0F10(source: reg128, r: i32) { // movups xmm, xmm/m128 mov_rm_r128(source, r); } #[no_mangle] -pub unsafe fn instr_0F10_reg(mut r1: i32, mut r2: i32) { instr_0F10(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F10_reg(r1: i32, r2: i32) { instr_0F10(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F10_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F10_mem(addr: i32, r: i32) { instr_0F10(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F10_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_F30F10_reg(r1: i32, r2: i32) { // movss xmm, xmm/m32 - let mut data: reg128 = read_xmm128s(r1); - let mut orig: reg128 = read_xmm128s(r2); + let data: reg128 = read_xmm128s(r1); + let orig: reg128 = read_xmm128s(r2); write_xmm128( r2, data.u32_0[0] as i32, @@ -456,27 +451,27 @@ pub unsafe fn instr_F30F10_reg(mut r1: i32, mut r2: i32) { ); } #[no_mangle] -pub unsafe fn instr_F30F10_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F30F10_mem(addr: i32, r: i32) { // movss xmm, xmm/m32 - let mut data: i32 = return_on_pagefault!(safe_read32s(addr)); + let data: i32 = return_on_pagefault!(safe_read32s(addr)); write_xmm128(r, data, 0, 0, 0); } #[no_mangle] -pub unsafe fn instr_660F10(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F10(source: reg128, r: i32) { // movupd xmm, xmm/m128 mov_rm_r128(source, r); } #[no_mangle] -pub unsafe fn instr_660F10_reg(mut r1: i32, mut r2: i32) { instr_660F10(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F10_reg(r1: i32, r2: i32) { instr_660F10(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F10_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F10_mem(addr: i32, r: i32) { instr_660F10(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20F10_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_F20F10_reg(r1: i32, r2: i32) { // movsd xmm, xmm/m64 - let mut data: reg128 = read_xmm128s(r1); - let mut orig: reg128 = read_xmm128s(r2); + let data: reg128 = read_xmm128s(r1); + let orig: reg128 = read_xmm128s(r2); write_xmm128( r2, data.u32_0[0] as i32, @@ -486,26 +481,26 @@ pub unsafe fn instr_F20F10_reg(mut r1: i32, mut r2: i32) { ); } #[no_mangle] -pub unsafe fn instr_F20F10_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F20F10_mem(addr: i32, r: i32) { // movsd xmm, xmm/m64 - let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); + let data: reg64 = return_on_pagefault!(safe_read64s(addr)); write_xmm128(r, data.u32_0[0] as i32, data.u32_0[1] as i32, 0, 0); } #[no_mangle] -pub unsafe fn instr_0F11_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_0F11_reg(r1: i32, r2: i32) { // movups xmm/m128, xmm mov_r_r128(r1, r2); } #[no_mangle] -pub unsafe fn instr_0F11_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F11_mem(addr: i32, r: i32) { // movups xmm/m128, xmm mov_r_m128(addr, r); } #[no_mangle] -pub unsafe fn instr_F30F11_reg(mut rm_dest: i32, mut reg_src: i32) { +pub unsafe fn instr_F30F11_reg(rm_dest: i32, reg_src: i32) { // movss xmm/m32, xmm - let mut data: reg128 = read_xmm128s(reg_src); - let mut orig: reg128 = read_xmm128s(rm_dest); + let data: reg128 = read_xmm128s(reg_src); + let orig: reg128 = read_xmm128s(rm_dest); write_xmm128( rm_dest, data.u32_0[0] as i32, @@ -515,26 +510,26 @@ pub unsafe fn instr_F30F11_reg(mut rm_dest: i32, mut reg_src: i32) { ); } #[no_mangle] -pub unsafe fn instr_F30F11_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F30F11_mem(addr: i32, r: i32) { // movss xmm/m32, xmm - let mut data: reg128 = read_xmm128s(r); + let data: reg128 = read_xmm128s(r); return_on_pagefault!(safe_write32(addr, data.u32_0[0] as i32)); } #[no_mangle] -pub unsafe fn instr_660F11_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_660F11_reg(r1: i32, r2: i32) { // movupd xmm/m128, xmm mov_r_r128(r1, r2); } #[no_mangle] -pub unsafe fn instr_660F11_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F11_mem(addr: i32, r: i32) { // movupd xmm/m128, xmm mov_r_m128(addr, r); } #[no_mangle] -pub unsafe fn instr_F20F11_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_F20F11_reg(r1: i32, r2: i32) { // movsd xmm/m64, xmm - let mut data: reg128 = read_xmm128s(r2); - let mut orig: reg128 = read_xmm128s(r1); + let data: reg128 = read_xmm128s(r2); + let orig: reg128 = read_xmm128s(r1); write_xmm128( r1, data.u32_0[0] as i32, @@ -544,16 +539,16 @@ pub unsafe fn instr_F20F11_reg(mut r1: i32, mut r2: i32) { ); } #[no_mangle] -pub unsafe fn instr_F20F11_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F20F11_mem(addr: i32, r: i32) { // movsd xmm/m64, xmm - let mut data: reg64 = read_xmm64s(r); + let data: reg64 = read_xmm64s(r); return_on_pagefault!(safe_write64(addr, data.u64_0[0] as i64)); } #[no_mangle] -pub unsafe fn instr_0F12_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F12_mem(addr: i32, r: i32) { // movlps xmm, m64 - let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); - let mut orig: reg128 = read_xmm128s(r); + let data: reg64 = return_on_pagefault!(safe_read64s(addr)); + let orig: reg128 = read_xmm128s(r); write_xmm128( r, data.u32_0[0] as i32, @@ -563,10 +558,10 @@ pub unsafe fn instr_0F12_mem(mut addr: i32, mut r: i32) { ); } #[no_mangle] -pub unsafe fn instr_0F12_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_0F12_reg(r1: i32, r2: i32) { // movhlps xmm, xmm - let mut data: reg128 = read_xmm128s(r1); - let mut orig: reg128 = read_xmm128s(r2); + let data: reg128 = read_xmm128s(r1); + let orig: reg128 = read_xmm128s(r2); write_xmm128( r2, data.u32_0[2] as i32, @@ -576,40 +571,40 @@ pub unsafe fn instr_0F12_reg(mut r1: i32, mut r2: i32) { ); } #[no_mangle] -pub unsafe fn instr_660F12_reg(mut r1: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_660F12_reg(r1: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F12_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F12_mem(addr: i32, r: i32) { // movlpd xmm, m64 - let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); + let data: reg64 = return_on_pagefault!(safe_read64s(addr)); write_xmm64(r, data); } #[no_mangle] -pub unsafe fn instr_F20F12_mem(mut addr: i32, mut r: i32) { unimplemented_sse(); } +pub unsafe fn instr_F20F12_mem(addr: i32, r: i32) { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_F20F12_reg(mut r1: i32, mut r2: i32) { unimplemented_sse(); } +pub unsafe fn instr_F20F12_reg(r1: i32, r2: i32) { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_F30F12_mem(mut addr: i32, mut r: i32) { unimplemented_sse(); } +pub unsafe fn instr_F30F12_mem(addr: i32, r: i32) { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_F30F12_reg(mut r1: i32, mut r2: i32) { unimplemented_sse(); } +pub unsafe fn instr_F30F12_reg(r1: i32, r2: i32) { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_0F13_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F13_mem(addr: i32, r: i32) { // movlps m64, xmm movl_r128_m64(addr, r); } #[no_mangle] -pub unsafe fn instr_0F13_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } +pub unsafe fn instr_0F13_reg(r1: i32, r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F13_reg(mut r1: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_660F13_reg(r1: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F13_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F13_mem(addr: i32, r: i32) { // movlpd xmm/m64, xmm movl_r128_m64(addr, r); } #[no_mangle] -pub unsafe fn instr_0F14(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0F14(source: reg64, r: i32) { // unpcklps xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg64 = read_xmm64s(r); + let destination: reg64 = read_xmm64s(r); write_xmm128( r, destination.u32_0[0] as i32, @@ -619,16 +614,16 @@ pub unsafe fn instr_0F14(mut source: reg64, mut r: i32) { ); } #[no_mangle] -pub unsafe fn instr_0F14_reg(mut r1: i32, mut r2: i32) { instr_0F14(read_xmm64s(r1), r2); } +pub unsafe fn instr_0F14_reg(r1: i32, r2: i32) { instr_0F14(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F14_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F14_mem(addr: i32, r: i32) { instr_0F14(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F14(mut source: reg64, mut r: i32) { +pub unsafe fn instr_660F14(source: reg64, r: i32) { // unpcklpd xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg64 = read_xmm64s(r); + let destination: reg64 = read_xmm64s(r); write_xmm128( r, destination.u32_0[0] as i32, @@ -638,16 +633,16 @@ pub unsafe fn instr_660F14(mut source: reg64, mut r: i32) { ); } #[no_mangle] -pub unsafe fn instr_660F14_reg(mut r1: i32, mut r2: i32) { instr_660F14(read_xmm64s(r1), r2); } +pub unsafe fn instr_660F14_reg(r1: i32, r2: i32) { instr_660F14(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F14_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F14_mem(addr: i32, r: i32) { instr_660F14(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F15(mut source: reg128, mut r: i32) { +pub unsafe fn instr_0F15(source: reg128, r: i32) { // unpckhps xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); write_xmm128( r, destination.u32_0[2] as i32, @@ -657,16 +652,16 @@ pub unsafe fn instr_0F15(mut source: reg128, mut r: i32) { ); } #[no_mangle] -pub unsafe fn instr_0F15_reg(mut r1: i32, mut r2: i32) { instr_0F15(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F15_reg(r1: i32, r2: i32) { instr_0F15(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F15_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F15_mem(addr: i32, r: i32) { instr_0F15(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F15(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F15(source: reg128, r: i32) { // unpckhpd xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); write_xmm128( r, destination.u32_0[2] as i32, @@ -676,21 +671,21 @@ pub unsafe fn instr_660F15(mut source: reg128, mut r: i32) { ); } #[no_mangle] -pub unsafe fn instr_660F15_reg(mut r1: i32, mut r2: i32) { instr_660F15(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F15_reg(r1: i32, r2: i32) { instr_660F15(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F15_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F15_mem(addr: i32, r: i32) { instr_660F15(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F16_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F16_mem(addr: i32, r: i32) { // movhps xmm, m64 movh_m64_r128(addr, r); } #[no_mangle] -pub unsafe fn instr_0F16_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_0F16_reg(r1: i32, r2: i32) { // movlhps xmm, xmm - let mut data: reg128 = read_xmm128s(r1); - let mut orig: reg128 = read_xmm128s(r2); + let data: reg128 = read_xmm128s(r1); + let orig: reg128 = read_xmm128s(r2); write_xmm128( r2, orig.u32_0[0] as i32, @@ -700,32 +695,32 @@ pub unsafe fn instr_0F16_reg(mut r1: i32, mut r2: i32) { ); } #[no_mangle] -pub unsafe fn instr_660F16_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F16_mem(addr: i32, r: i32) { // movhpd xmm, m64 movh_m64_r128(addr, r); } #[no_mangle] -pub unsafe fn instr_660F16_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } +pub unsafe fn instr_660F16_reg(r1: i32, r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F17_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F17_mem(addr: i32, r: i32) { // movhps m64, xmm movh_r128_m64(addr, r); } #[no_mangle] -pub unsafe fn instr_0F17_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } +pub unsafe fn instr_0F17_reg(r1: i32, r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F17_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F17_mem(addr: i32, r: i32) { // movhpd m64, xmm movh_r128_m64(addr, r); } #[no_mangle] -pub unsafe fn instr_660F17_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } +pub unsafe fn instr_660F17_reg(r1: i32, r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F18_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_0F18_reg(r1: i32, r2: i32) { // reserved nop } #[no_mangle] -pub unsafe fn instr_0F18_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F18_mem(addr: i32, r: i32) { // prefetch // nop for us } @@ -734,11 +729,11 @@ pub unsafe fn instr_0F1A() { undefined_instruction(); } #[no_mangle] pub unsafe fn instr_0F1B() { undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0F1F_reg(mut r1: i32, mut r2: i32) {} +pub unsafe fn instr_0F1F_reg(r1: i32, r2: i32) {} #[no_mangle] -pub unsafe fn instr_0F1F_mem(mut addr: i32, mut r: i32) {} +pub unsafe fn instr_0F1F_mem(addr: i32, r: i32) {} #[no_mangle] -pub unsafe fn instr_0F20(mut r: i32, mut creg: i32) { +pub unsafe fn instr_0F20(r: i32, creg: i32) { if 0 != *cpl { trigger_gp_non_raising(0); return; @@ -766,7 +761,7 @@ pub unsafe fn instr_0F20(mut r: i32, mut creg: i32) { }; } #[no_mangle] -pub unsafe fn instr_0F21(mut r: i32, mut dreg_index: i32) { +pub unsafe fn instr_0F21(r: i32, mut dreg_index: i32) { if 0 != *cpl { trigger_gp_non_raising(0); return; @@ -795,7 +790,7 @@ pub unsafe fn instr_0F21(mut r: i32, mut dreg_index: i32) { }; } #[no_mangle] -pub unsafe fn instr_0F22(mut r: i32, mut creg: i32) { +pub unsafe fn instr_0F22(r: i32, creg: i32) { if 0 != *cpl { trigger_gp_non_raising(0); return; @@ -851,7 +846,7 @@ pub unsafe fn instr_0F22(mut r: i32, mut creg: i32) { }; } #[no_mangle] -pub unsafe fn instr_0F23(mut r: i32, mut dreg_index: i32) { +pub unsafe fn instr_0F23(r: i32, mut dreg_index: i32) { if 0 != *cpl { trigger_gp_non_raising(0); return; @@ -888,73 +883,73 @@ pub unsafe fn instr_0F26() { undefined_instruction(); } #[no_mangle] pub unsafe fn instr_0F27() { undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0F28(mut source: reg128, mut r: i32) { +pub unsafe fn instr_0F28(source: reg128, r: i32) { // movaps xmm, xmm/m128 // XXX: Aligned read or #gp mov_rm_r128(source, r); } #[no_mangle] -pub unsafe fn instr_0F28_reg(mut r1: i32, mut r2: i32) { instr_0F28(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F28_reg(r1: i32, r2: i32) { instr_0F28(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F28_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F28_mem(addr: i32, r: i32) { instr_0F28(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F28(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F28(source: reg128, r: i32) { // movapd xmm, xmm/m128 // XXX: Aligned read or #gp // Note: Same as movdqa (660F6F) mov_rm_r128(source, r); } #[no_mangle] -pub unsafe fn instr_660F28_reg(mut r1: i32, mut r2: i32) { instr_660F28(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F28_reg(r1: i32, r2: i32) { instr_660F28(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F28_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F28_mem(addr: i32, r: i32) { instr_660F28(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F29_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F29_mem(addr: i32, r: i32) { // movaps m128, xmm - let mut data: reg128 = read_xmm128s(r); + let data: reg128 = read_xmm128s(r); // XXX: Aligned write or #gp return_on_pagefault!(safe_write128(addr, data)); } #[no_mangle] -pub unsafe fn instr_0F29_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_0F29_reg(r1: i32, r2: i32) { // movaps xmm, xmm mov_r_r128(r1, r2); } #[no_mangle] -pub unsafe fn instr_660F29_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F29_mem(addr: i32, r: i32) { // movapd m128, xmm - let mut data: reg128 = read_xmm128s(r); + let data: reg128 = read_xmm128s(r); // XXX: Aligned write or #gp return_on_pagefault!(safe_write128(addr, data)); } #[no_mangle] -pub unsafe fn instr_660F29_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_660F29_reg(r1: i32, r2: i32) { // movapd xmm, xmm mov_r_r128(r1, r2); } #[no_mangle] -pub unsafe fn instr_0F2B_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } +pub unsafe fn instr_0F2B_reg(r1: i32, r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F2B_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F2B_mem(addr: i32, r: i32) { // movntps m128, xmm // XXX: Aligned write or #gp mov_r_m128(addr, r); } #[no_mangle] -pub unsafe fn instr_660F2B_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } +pub unsafe fn instr_660F2B_reg(r1: i32, r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F2B_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F2B_mem(addr: i32, r: i32) { // movntpd m128, xmm // XXX: Aligned write or #gp mov_r_m128(addr, r); } #[no_mangle] -pub unsafe fn instr_0F2C(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0F2C(source: reg64, r: i32) { // cvttps2pi mm, xmm/m64 let result = reg64 { i32_0: [ @@ -966,14 +961,14 @@ pub unsafe fn instr_0F2C(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0F2C_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F2C_mem(addr: i32, r: i32) { instr_0F2C(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F2C_reg(mut r1: i32, mut r2: i32) { instr_0F2C(read_xmm64s(r1), r2); } +pub unsafe fn instr_0F2C_reg(r1: i32, r2: i32) { instr_0F2C(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F2C(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F2C(source: reg128, r: i32) { // cvttpd2pi mm, xmm/m128 let result = reg64 { // XXX: Check conversion @@ -986,35 +981,35 @@ pub unsafe fn instr_660F2C(mut source: reg128, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_660F2C_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F2C_mem(addr: i32, r: i32) { instr_660F2C(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F2C_reg(mut r1: i32, mut r2: i32) { instr_660F2C(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F2C_reg(r1: i32, r2: i32) { instr_660F2C(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F2C(mut source: reg64, mut r: i32) { +pub unsafe fn instr_F20F2C(source: reg64, r: i32) { // cvttsd2si r32, xmm/m64 write_reg32(r, sse_convert_f64_to_i32(source.f64_0[0])); } #[no_mangle] -pub unsafe fn instr_F20F2C_reg(mut r1: i32, mut r2: i32) { instr_F20F2C(read_xmm64s(r1), r2); } +pub unsafe fn instr_F20F2C_reg(r1: i32, r2: i32) { instr_F20F2C(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F2C_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F20F2C_mem(addr: i32, r: i32) { instr_F20F2C(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F2C(source: f32, mut r: i32) { +pub unsafe fn instr_F30F2C(source: f32, r: i32) { let result = source.trunc(); write_reg32(r, sse_convert_f32_to_i32(source)); } #[no_mangle] -pub unsafe fn instr_F30F2C_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F30F2C_mem(addr: i32, r: i32) { instr_F30F2C(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_F30F2C_reg(mut r1: i32, mut r2: i32) { instr_F30F2C(read_xmm_f32(r1), r2); } +pub unsafe fn instr_F30F2C_reg(r1: i32, r2: i32) { instr_F30F2C(read_xmm_f32(r1), r2); } pub unsafe fn instr_0F2E(source: f32, r: i32) { // ucomiss xmm1, xmm2/m32 @@ -1130,9 +1125,9 @@ pub unsafe fn instr_0F30() { return; } else { - let mut index: i32 = *reg32s.offset(ECX as isize); - let mut low: i32 = *reg32s.offset(EAX as isize); - let mut high: i32 = *reg32s.offset(EDX as isize); + let index: i32 = *reg32s.offset(ECX as isize); + let low: i32 = *reg32s.offset(EAX as isize); + let high: i32 = *reg32s.offset(EDX as isize); if index != IA32_SYSENTER_ESP { dbg_log!("wrmsr ecx={:x} data={:x}:{:x}", index, high, low); } @@ -1150,7 +1145,7 @@ pub unsafe fn instr_0F30() { high == 0, ("Changing APIC address (high 32 bits) not supported") ); - let mut address: i32 = + let address: i32 = low & !(IA32_APIC_BASE_BSP | IA32_APIC_BASE_EXTD | IA32_APIC_BASE_EN); dbg_assert!( address == APIC_ADDRESS, @@ -1188,7 +1183,7 @@ pub unsafe fn instr_0F30() { pub unsafe fn instr_0F31() { // rdtsc - read timestamp counter if 0 == *cpl || 0 == *cr.offset(4) & CR4_TSD { - let mut tsc: u64 = read_tsc(); + let tsc: u64 = read_tsc(); *reg32s.offset(EAX as isize) = tsc as i32; *reg32s.offset(EDX as isize) = (tsc >> 32) as i32; if 0 != 0 * 0 { @@ -1211,7 +1206,7 @@ pub unsafe fn instr_0F32() { return; } else { - let mut index: i32 = *reg32s.offset(ECX as isize); + let index: i32 = *reg32s.offset(ECX as isize); dbg_log!("rdmsr ecx={:x}", index); let mut low: i32 = 0; let mut high: i32 = 0; @@ -1225,7 +1220,7 @@ pub unsafe fn instr_0F32() { low = *sysenter_esp } else if index == IA32_TIME_STAMP_COUNTER { - let mut tsc: u64 = read_tsc(); + let tsc: u64 = read_tsc(); low = tsc as i32; high = (tsc >> 32) as i32 } @@ -1276,7 +1271,7 @@ pub unsafe fn instr_0F33() { #[no_mangle] pub unsafe fn instr_0F34() { // sysenter - let mut seg: i32 = *sysenter_cs & 65532; + let seg: i32 = *sysenter_cs & 65532; if !*protected_mode || seg == 0 { trigger_gp_non_raising(0); return; @@ -1303,7 +1298,7 @@ pub unsafe fn instr_0F34() { #[no_mangle] pub unsafe fn instr_0F35() { // sysexit - let mut seg: i32 = *sysenter_cs & 65532; + let seg: i32 = *sysenter_cs & 65532; if !*protected_mode || 0 != *cpl as i32 || seg == 0 { trigger_gp_non_raising(0); return; @@ -1350,470 +1345,470 @@ pub unsafe fn instr_0F3E() { unimplemented_sse(); } #[no_mangle] pub unsafe fn instr_0F3F() { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr16_0F40_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0F40_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_o(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F40_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0F40_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); cmovcc16(test_o(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F40_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_0F40_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_o(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F40_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0F40_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); cmovcc32(test_o(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F41_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0F41_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_o(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F41_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0F41_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); cmovcc16(!test_o(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F41_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_0F41_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_o(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F41_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0F41_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); cmovcc32(!test_o(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F42_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0F42_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_b(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F42_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0F42_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); cmovcc16(test_b(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F42_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_0F42_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_b(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F42_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0F42_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); cmovcc32(test_b(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F43_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0F43_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_b(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F43_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0F43_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); cmovcc16(!test_b(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F43_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_0F43_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_b(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F43_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0F43_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); cmovcc32(!test_b(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F44_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0F44_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_z(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F44_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0F44_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); cmovcc16(test_z(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F44_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_0F44_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_z(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F44_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0F44_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); cmovcc32(test_z(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F45_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0F45_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_z(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F45_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0F45_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); cmovcc16(!test_z(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F45_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_0F45_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_z(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F45_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0F45_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); cmovcc32(!test_z(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F46_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0F46_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_be(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F46_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0F46_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); cmovcc16(test_be(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F46_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_0F46_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_be(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F46_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0F46_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); cmovcc32(test_be(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F47_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0F47_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_be(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F47_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0F47_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); cmovcc16(!test_be(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F47_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_0F47_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_be(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F47_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0F47_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); cmovcc32(!test_be(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F48_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0F48_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_s(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F48_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0F48_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); cmovcc16(test_s(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F48_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_0F48_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_s(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F48_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0F48_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); cmovcc32(test_s(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F49_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0F49_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_s(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F49_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0F49_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); cmovcc16(!test_s(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F49_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_0F49_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_s(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F49_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0F49_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); cmovcc32(!test_s(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4A_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0F4A_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_p(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4A_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0F4A_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); cmovcc16(test_p(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4A_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_0F4A_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_p(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4A_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0F4A_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); cmovcc32(test_p(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4B_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0F4B_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_p(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4B_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0F4B_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); cmovcc16(!test_p(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4B_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_0F4B_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_p(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4B_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0F4B_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); cmovcc32(!test_p(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4C_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0F4C_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_l(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4C_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0F4C_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); cmovcc16(test_l(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4C_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_0F4C_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_l(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4C_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0F4C_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); cmovcc32(test_l(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4D_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0F4D_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_l(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4D_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0F4D_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); cmovcc16(!test_l(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4D_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_0F4D_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_l(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4D_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0F4D_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); cmovcc32(!test_l(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4E_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0F4E_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(test_le(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4E_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0F4E_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); cmovcc16(test_le(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4E_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_0F4E_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(test_le(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4E_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0F4E_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); cmovcc32(test_le(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4F_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0F4F_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); cmovcc16(!test_le(), ____0, r); } #[no_mangle] -pub unsafe fn instr16_0F4F_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0F4F_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); cmovcc16(!test_le(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4F_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_0F4F_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); cmovcc32(!test_le(), ____0, r); } #[no_mangle] -pub unsafe fn instr32_0F4F_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0F4F_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); cmovcc32(!test_le(), ____0, r); } #[no_mangle] -pub unsafe fn instr_0F50_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_0F50_reg(r1: i32, r2: i32) { // movmskps r, xmm - let mut source: reg128 = read_xmm128s(r1); - let mut data: i32 = (source.u32_0[0] >> 31 + let source: reg128 = read_xmm128s(r1); + let data: i32 = (source.u32_0[0] >> 31 | source.u32_0[1] >> 31 << 1 | source.u32_0[2] >> 31 << 2 | source.u32_0[3] >> 31 << 3) as i32; write_reg32(r2, data); } #[no_mangle] -pub unsafe fn instr_0F50_mem(mut addr: i32, mut r1: i32) { trigger_ud(); } +pub unsafe fn instr_0F50_mem(addr: i32, r1: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F50_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_660F50_reg(r1: i32, r2: i32) { // movmskpd r, xmm - let mut source: reg128 = read_xmm128s(r1); - let mut data: i32 = (source.u32_0[1] >> 31 | source.u32_0[3] >> 31 << 1) as i32; + let source: reg128 = read_xmm128s(r1); + let data: i32 = (source.u32_0[1] >> 31 | source.u32_0[3] >> 31 << 1) as i32; write_reg32(r2, data); } #[no_mangle] -pub unsafe fn instr_660F50_mem(mut addr: i32, mut r1: i32) { trigger_ud(); } +pub unsafe fn instr_660F50_mem(addr: i32, r1: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F54(mut source: reg128, mut r: i32) { +pub unsafe fn instr_0F54(source: reg128, r: i32) { // andps xmm, xmm/mem128 // XXX: Aligned access or #gp pand_r128(source, r); } #[no_mangle] -pub unsafe fn instr_0F54_reg(mut r1: i32, mut r2: i32) { instr_0F54(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F54_reg(r1: i32, r2: i32) { instr_0F54(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F54_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F54_mem(addr: i32, r: i32) { instr_0F54(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F54(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F54(source: reg128, r: i32) { // andpd xmm, xmm/mem128 // XXX: Aligned access or #gp pand_r128(source, r); } #[no_mangle] -pub unsafe fn instr_660F54_reg(mut r1: i32, mut r2: i32) { instr_660F54(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F54_reg(r1: i32, r2: i32) { instr_660F54(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F54_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F54_mem(addr: i32, r: i32) { instr_660F54(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F55(mut source: reg128, mut r: i32) { +pub unsafe fn instr_0F55(source: reg128, r: i32) { // andnps xmm, xmm/mem128 // XXX: Aligned access or #gp pandn_r128(source, r); } #[no_mangle] -pub unsafe fn instr_0F55_reg(mut r1: i32, mut r2: i32) { instr_0F55(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F55_reg(r1: i32, r2: i32) { instr_0F55(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F55_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F55_mem(addr: i32, r: i32) { instr_0F55(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F55(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F55(source: reg128, r: i32) { // andnpd xmm, xmm/mem128 // XXX: Aligned access or #gp pandn_r128(source, r); } #[no_mangle] -pub unsafe fn instr_660F55_reg(mut r1: i32, mut r2: i32) { instr_660F55(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F55_reg(r1: i32, r2: i32) { instr_660F55(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F55_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F55_mem(addr: i32, r: i32) { instr_660F55(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F56(mut source: reg128, mut r: i32) { +pub unsafe fn instr_0F56(source: reg128, r: i32) { // orps xmm, xmm/mem128 // XXX: Aligned access or #gp por_r128(source, r); } #[no_mangle] -pub unsafe fn instr_0F56_reg(mut r1: i32, mut r2: i32) { instr_0F56(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F56_reg(r1: i32, r2: i32) { instr_0F56(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F56_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F56_mem(addr: i32, r: i32) { instr_0F56(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F56(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F56(source: reg128, r: i32) { // orpd xmm, xmm/mem128 // XXX: Aligned access or #gp por_r128(source, r); } #[no_mangle] -pub unsafe fn instr_660F56_reg(mut r1: i32, mut r2: i32) { instr_660F56(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F56_reg(r1: i32, r2: i32) { instr_660F56(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F56_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F56_mem(addr: i32, r: i32) { instr_660F56(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F57(mut source: reg128, mut r: i32) { +pub unsafe fn instr_0F57(source: reg128, r: i32) { // xorps xmm, xmm/mem128 // XXX: Aligned access or #gp pxor_r128(source, r); } #[no_mangle] -pub unsafe fn instr_0F57_reg(mut r1: i32, mut r2: i32) { instr_0F57(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F57_reg(r1: i32, r2: i32) { instr_0F57(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F57_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F57_mem(addr: i32, r: i32) { instr_0F57(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F57(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F57(source: reg128, r: i32) { // xorpd xmm, xmm/mem128 // XXX: Aligned access or #gp pxor_r128(source, r); } #[no_mangle] -pub unsafe fn instr_660F57_reg(mut r1: i32, mut r2: i32) { instr_660F57(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F57_reg(r1: i32, r2: i32) { instr_660F57(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F57_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F57_mem(addr: i32, r: i32) { instr_660F57(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F60(mut source: i32, mut r: i32) { +pub unsafe fn instr_0F60(source: i32, r: i32) { // punpcklbw mm, mm/m32 - let mut destination: reg64 = read_mmx64s(r); - let mut byte0: i32 = destination.u8_0[0] as i32; - let mut byte1: i32 = source & 255; - let mut byte2: i32 = destination.u8_0[1] as i32; - let mut byte3: i32 = source >> 8 & 255; - let mut byte4: i32 = destination.u8_0[2] as i32; - let mut byte5: i32 = source >> 16 & 255; - let mut byte6: i32 = destination.u8_0[3] as i32; - let mut byte7: i32 = source >> 24; - let mut low: i32 = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24; - let mut high: i32 = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24; + let destination: reg64 = read_mmx64s(r); + let byte0: i32 = destination.u8_0[0] as i32; + let byte1: i32 = source & 255; + let byte2: i32 = destination.u8_0[1] as i32; + let byte3: i32 = source >> 8 & 255; + let byte4: i32 = destination.u8_0[2] as i32; + let byte5: i32 = source >> 16 & 255; + let byte6: i32 = destination.u8_0[3] as i32; + let byte7: i32 = source >> 24; + let low: i32 = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24; + let high: i32 = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24; write_mmx64(r, low, high); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0F60_reg(mut r1: i32, mut r2: i32) { instr_0F60(read_mmx32s(r1), r2); } +pub unsafe fn instr_0F60_reg(r1: i32, r2: i32) { instr_0F60(read_mmx32s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F60_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F60_mem(addr: i32, r: i32) { instr_0F60(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F60(mut source: reg64, mut r: i32) { +pub unsafe fn instr_660F60(source: reg64, r: i32) { // punpcklbw xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg64 = read_xmm64s(r); + let destination: reg64 = read_xmm64s(r); write_xmm128( r, destination.u8_0[0] as i32 @@ -1835,35 +1830,35 @@ pub unsafe fn instr_660F60(mut source: reg64, mut r: i32) { ); } #[no_mangle] -pub unsafe fn instr_660F60_reg(mut r1: i32, mut r2: i32) { instr_660F60(read_xmm64s(r1), r2); } +pub unsafe fn instr_660F60_reg(r1: i32, r2: i32) { instr_660F60(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F60_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F60_mem(addr: i32, r: i32) { instr_660F60(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F61(mut source: i32, mut r: i32) { +pub unsafe fn instr_0F61(source: i32, r: i32) { // punpcklwd mm, mm/m32 - let mut destination: reg64 = read_mmx64s(r); - let mut word0: i32 = destination.u16_0[0] as i32; - let mut word1: i32 = source & 65535; - let mut word2: i32 = destination.u16_0[1] as i32; - let mut word3: i32 = source >> 16; - let mut low: i32 = word0 | word1 << 16; - let mut high: i32 = word2 | word3 << 16; + let destination: reg64 = read_mmx64s(r); + let word0: i32 = destination.u16_0[0] as i32; + let word1: i32 = source & 65535; + let word2: i32 = destination.u16_0[1] as i32; + let word3: i32 = source >> 16; + let low: i32 = word0 | word1 << 16; + let high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0F61_reg(mut r1: i32, mut r2: i32) { instr_0F61(read_mmx32s(r1), r2); } +pub unsafe fn instr_0F61_reg(r1: i32, r2: i32) { instr_0F61(read_mmx32s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F61_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F61_mem(addr: i32, r: i32) { instr_0F61(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F61(mut source: reg64, mut r: i32) { +pub unsafe fn instr_660F61(source: reg64, r: i32) { // punpcklwd xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg64 = read_xmm64s(r); + let destination: reg64 = read_xmm64s(r); write_xmm128( r, destination.u16_0[0] as i32 | (source.u16_0[0] as i32) << 16, @@ -1873,29 +1868,29 @@ pub unsafe fn instr_660F61(mut source: reg64, mut r: i32) { ); } #[no_mangle] -pub unsafe fn instr_660F61_reg(mut r1: i32, mut r2: i32) { instr_660F61(read_xmm64s(r1), r2); } +pub unsafe fn instr_660F61_reg(r1: i32, r2: i32) { instr_660F61(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F61_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F61_mem(addr: i32, r: i32) { instr_660F61(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F62(mut source: i32, mut r: i32) { +pub unsafe fn instr_0F62(source: i32, r: i32) { // punpckldq mm, mm/m32 - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); write_mmx64(r, destination.u32_0[0] as i32, source); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0F62_reg(mut r1: i32, mut r2: i32) { instr_0F62(read_mmx32s(r1), r2); } +pub unsafe fn instr_0F62_reg(r1: i32, r2: i32) { instr_0F62(read_mmx32s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F62_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F62_mem(addr: i32, r: i32) { instr_0F62(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F62(mut source: reg64, mut r: i32) { +pub unsafe fn instr_660F62(source: reg64, r: i32) { // punpckldq xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); write_xmm128( r, destination.u32_0[0] as i32, @@ -1905,20 +1900,20 @@ pub unsafe fn instr_660F62(mut source: reg64, mut r: i32) { ); } #[no_mangle] -pub unsafe fn instr_660F62_reg(mut r1: i32, mut r2: i32) { instr_660F62(read_xmm64s(r1), r2); } +pub unsafe fn instr_660F62_reg(r1: i32, r2: i32) { instr_660F62(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F62_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F62_mem(addr: i32, r: i32) { instr_660F62(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F63(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0F63(source: reg64, r: i32) { // packsswb mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); - let mut low: i32 = saturate_sw_to_sb(destination.u16_0[0] as i32) + let destination: reg64 = read_mmx64s(r); + let low: i32 = saturate_sw_to_sb(destination.u16_0[0] as i32) | saturate_sw_to_sb(destination.u16_0[1] as i32) << 8 | saturate_sw_to_sb(destination.u16_0[2] as i32) << 16 | saturate_sw_to_sb(destination.u16_0[3] as i32) << 24; - let mut high: i32 = saturate_sw_to_sb(source.u16_0[0] as i32) + let high: i32 = saturate_sw_to_sb(source.u16_0[0] as i32) | saturate_sw_to_sb(source.u16_0[1] as i32) << 8 | saturate_sw_to_sb(source.u16_0[2] as i32) << 16 | saturate_sw_to_sb(source.u16_0[3] as i32) << 24; @@ -1926,44 +1921,44 @@ pub unsafe fn instr_0F63(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0F63_reg(mut r1: i32, mut r2: i32) { instr_0F63(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F63_reg(r1: i32, r2: i32) { instr_0F63(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F63_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F63_mem(addr: i32, r: i32) { instr_0F63(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F63(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F63(source: reg128, r: i32) { // packsswb xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); - let mut dword0: i32 = saturate_sw_to_sb(destination.u16_0[0] as i32) + let destination: reg128 = read_xmm128s(r); + let dword0: i32 = saturate_sw_to_sb(destination.u16_0[0] as i32) | saturate_sw_to_sb(destination.u16_0[1] as i32) << 8 | saturate_sw_to_sb(destination.u16_0[2] as i32) << 16 | saturate_sw_to_sb(destination.u16_0[3] as i32) << 24; - let mut dword1: i32 = saturate_sw_to_sb(destination.u16_0[4] as i32) + let dword1: i32 = saturate_sw_to_sb(destination.u16_0[4] as i32) | saturate_sw_to_sb(destination.u16_0[5] as i32) << 8 | saturate_sw_to_sb(destination.u16_0[6] as i32) << 16 | saturate_sw_to_sb(destination.u16_0[7] as i32) << 24; - let mut dword2: i32 = saturate_sw_to_sb(source.u16_0[0] as i32) + let dword2: i32 = saturate_sw_to_sb(source.u16_0[0] as i32) | saturate_sw_to_sb(source.u16_0[1] as i32) << 8 | saturate_sw_to_sb(source.u16_0[2] as i32) << 16 | saturate_sw_to_sb(source.u16_0[3] as i32) << 24; - let mut dword3: i32 = saturate_sw_to_sb(source.u16_0[4] as i32) + let dword3: i32 = saturate_sw_to_sb(source.u16_0[4] as i32) | saturate_sw_to_sb(source.u16_0[5] as i32) << 8 | saturate_sw_to_sb(source.u16_0[6] as i32) << 16 | saturate_sw_to_sb(source.u16_0[7] as i32) << 24; write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn instr_660F63_reg(mut r1: i32, mut r2: i32) { instr_660F63(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F63_reg(r1: i32, r2: i32) { instr_660F63(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F63_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F63_mem(addr: i32, r: i32) { instr_660F63(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F64(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0F64(source: reg64, r: i32) { // pcmpgtb mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; @@ -1980,16 +1975,16 @@ pub unsafe fn instr_0F64(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0F64_reg(mut r1: i32, mut r2: i32) { instr_0F64(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F64_reg(r1: i32, r2: i32) { instr_0F64(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F64_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F64_mem(addr: i32, r: i32) { instr_0F64(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F64(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F64(source: reg128, r: i32) { // pcmpgtb xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; @@ -2005,55 +2000,55 @@ pub unsafe fn instr_660F64(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F64_reg(mut r1: i32, mut r2: i32) { instr_660F64(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F64_reg(r1: i32, r2: i32) { instr_660F64(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F64_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F64_mem(addr: i32, r: i32) { instr_660F64(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F65(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0F65(source: reg64, r: i32) { // pcmpgtw mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); - let mut word0: i32 = if destination.i16_0[0] as i32 > source.i16_0[0] as i32 { + let destination: reg64 = read_mmx64s(r); + let word0: i32 = if destination.i16_0[0] as i32 > source.i16_0[0] as i32 { 65535 } else { 0 }; - let mut word1: i32 = if destination.i16_0[1] as i32 > source.i16_0[1] as i32 { + let word1: i32 = if destination.i16_0[1] as i32 > source.i16_0[1] as i32 { 65535 } else { 0 }; - let mut word2: i32 = if destination.i16_0[2] as i32 > source.i16_0[2] as i32 { + let word2: i32 = if destination.i16_0[2] as i32 > source.i16_0[2] as i32 { 65535 } else { 0 }; - let mut word3: i32 = if destination.i16_0[3] as i32 > source.i16_0[3] as i32 { + let word3: i32 = if destination.i16_0[3] as i32 > source.i16_0[3] as i32 { 65535 } else { 0 }; - let mut low: i32 = word0 | word1 << 16; - let mut high: i32 = word2 | word3 << 16; + let low: i32 = word0 | word1 << 16; + let high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0F65_reg(mut r1: i32, mut r2: i32) { instr_0F65(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F65_reg(r1: i32, r2: i32) { instr_0F65(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F65_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F65_mem(addr: i32, r: i32) { instr_0F65(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F65(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F65(source: reg128, r: i32) { // pcmpgtw xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; @@ -2069,22 +2064,22 @@ pub unsafe fn instr_660F65(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F65_reg(mut r1: i32, mut r2: i32) { instr_660F65(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F65_reg(r1: i32, r2: i32) { instr_660F65(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F65_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F65_mem(addr: i32, r: i32) { instr_660F65(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F66(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0F66(source: reg64, r: i32) { // pcmpgtd mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); - let mut low: i32 = if destination.i32_0[0] > source.i32_0[0] { + let destination: reg64 = read_mmx64s(r); + let low: i32 = if destination.i32_0[0] > source.i32_0[0] { -1 } else { 0 }; - let mut high: i32 = if destination.i32_0[1] > source.i32_0[1] { + let high: i32 = if destination.i32_0[1] > source.i32_0[1] { -1 } else { @@ -2094,16 +2089,16 @@ pub unsafe fn instr_0F66(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0F66_reg(mut r1: i32, mut r2: i32) { instr_0F66(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F66_reg(r1: i32, r2: i32) { instr_0F66(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F66_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F66_mem(addr: i32, r: i32) { instr_0F66(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F66(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F66(source: reg128, r: i32) { // pcmpgtd xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); write_xmm128( r, if destination.i32_0[0] > source.i32_0[0] { @@ -2133,20 +2128,20 @@ pub unsafe fn instr_660F66(mut source: reg128, mut r: i32) { ); } #[no_mangle] -pub unsafe fn instr_660F66_reg(mut r1: i32, mut r2: i32) { instr_660F66(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F66_reg(r1: i32, r2: i32) { instr_660F66(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F66_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F66_mem(addr: i32, r: i32) { instr_660F66(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F67(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0F67(source: reg64, r: i32) { // packuswb mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); - let mut low: u32 = saturate_sw_to_ub(destination.u16_0[0] as u32) + let destination: reg64 = read_mmx64s(r); + let low: u32 = saturate_sw_to_ub(destination.u16_0[0] as u32) | saturate_sw_to_ub(destination.u16_0[1] as u32) << 8 | saturate_sw_to_ub(destination.u16_0[2] as u32) << 16 | saturate_sw_to_ub(destination.u16_0[3] as u32) << 24; - let mut high: u32 = saturate_sw_to_ub(source.u16_0[0] as u32) + let high: u32 = saturate_sw_to_ub(source.u16_0[0] as u32) | saturate_sw_to_ub(source.u16_0[1] as u32) << 8 | saturate_sw_to_ub(source.u16_0[2] as u32) << 16 | saturate_sw_to_ub(source.u16_0[3] as u32) << 24; @@ -2154,16 +2149,16 @@ pub unsafe fn instr_0F67(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0F67_reg(mut r1: i32, mut r2: i32) { instr_0F67(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F67_reg(r1: i32, r2: i32) { instr_0F67(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F67_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F67_mem(addr: i32, r: i32) { instr_0F67(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F67(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F67(source: reg128, r: i32) { // packuswb xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; for i in 0..8 { result.u8_0[i as usize] = saturate_sw_to_ub(destination.u16_0[i as usize] as u32) as u8; @@ -2172,39 +2167,39 @@ pub unsafe fn instr_660F67(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F67_reg(mut r1: i32, mut r2: i32) { instr_660F67(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F67_reg(r1: i32, r2: i32) { instr_660F67(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F67_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F67_mem(addr: i32, r: i32) { instr_660F67(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F68(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0F68(source: reg64, r: i32) { // punpckhbw mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); - let mut byte0: i32 = destination.u8_0[4] as i32; - let mut byte1: i32 = source.u8_0[4] as i32; - let mut byte2: i32 = destination.u8_0[5] as i32; - let mut byte3: i32 = source.u8_0[5] as i32; - let mut byte4: i32 = destination.u8_0[6] as i32; - let mut byte5: i32 = source.u8_0[6] as i32; - let mut byte6: i32 = destination.u8_0[7] as i32; - let mut byte7: i32 = source.u8_0[7] as i32; - let mut low: i32 = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24; - let mut high: i32 = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24; + let destination: reg64 = read_mmx64s(r); + let byte0: i32 = destination.u8_0[4] as i32; + let byte1: i32 = source.u8_0[4] as i32; + let byte2: i32 = destination.u8_0[5] as i32; + let byte3: i32 = source.u8_0[5] as i32; + let byte4: i32 = destination.u8_0[6] as i32; + let byte5: i32 = source.u8_0[6] as i32; + let byte6: i32 = destination.u8_0[7] as i32; + let byte7: i32 = source.u8_0[7] as i32; + let low: i32 = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24; + let high: i32 = byte4 | byte5 << 8 | byte6 << 16 | byte7 << 24; write_mmx64(r, low, high); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0F68_reg(mut r1: i32, mut r2: i32) { instr_0F68(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F68_reg(r1: i32, r2: i32) { instr_0F68(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F68_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F68_mem(addr: i32, r: i32) { instr_0F68(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F68(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F68(source: reg128, r: i32) { // punpckhbw xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); write_xmm128( r, destination.u8_0[8] as i32 @@ -2226,65 +2221,65 @@ pub unsafe fn instr_660F68(mut source: reg128, mut r: i32) { ); } #[no_mangle] -pub unsafe fn instr_660F68_reg(mut r1: i32, mut r2: i32) { instr_660F68(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F68_reg(r1: i32, r2: i32) { instr_660F68(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F68_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F68_mem(addr: i32, r: i32) { instr_660F68(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F69(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0F69(source: reg64, r: i32) { // punpckhwd mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); - let mut word0: i32 = destination.u16_0[2] as i32; - let mut word1: i32 = source.u16_0[2] as i32; - let mut word2: i32 = destination.u16_0[3] as i32; - let mut word3: i32 = source.u16_0[3] as i32; - let mut low: i32 = word0 | word1 << 16; - let mut high: i32 = word2 | word3 << 16; + let destination: reg64 = read_mmx64s(r); + let word0: i32 = destination.u16_0[2] as i32; + let word1: i32 = source.u16_0[2] as i32; + let word2: i32 = destination.u16_0[3] as i32; + let word3: i32 = source.u16_0[3] as i32; + let low: i32 = word0 | word1 << 16; + let high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0F69_reg(mut r1: i32, mut r2: i32) { instr_0F69(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F69_reg(r1: i32, r2: i32) { instr_0F69(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F69_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F69_mem(addr: i32, r: i32) { instr_0F69(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F69(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F69(source: reg128, r: i32) { // punpckhwd xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); - let mut dword0: i32 = destination.u16_0[4] as i32 | (source.u16_0[4] as i32) << 16; - let mut dword1: i32 = destination.u16_0[5] as i32 | (source.u16_0[5] as i32) << 16; - let mut dword2: i32 = destination.u16_0[6] as i32 | (source.u16_0[6] as i32) << 16; - let mut dword3: i32 = destination.u16_0[7] as i32 | (source.u16_0[7] as i32) << 16; + let destination: reg128 = read_xmm128s(r); + let dword0: i32 = destination.u16_0[4] as i32 | (source.u16_0[4] as i32) << 16; + let dword1: i32 = destination.u16_0[5] as i32 | (source.u16_0[5] as i32) << 16; + let dword2: i32 = destination.u16_0[6] as i32 | (source.u16_0[6] as i32) << 16; + let dword3: i32 = destination.u16_0[7] as i32 | (source.u16_0[7] as i32) << 16; write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn instr_660F69_reg(mut r1: i32, mut r2: i32) { instr_660F69(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F69_reg(r1: i32, r2: i32) { instr_660F69(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F69_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F69_mem(addr: i32, r: i32) { instr_660F69(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F6A(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0F6A(source: reg64, r: i32) { // punpckhdq mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); write_mmx64(r, destination.u32_0[1] as i32, source.u32_0[1] as i32); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0F6A_reg(mut r1: i32, mut r2: i32) { instr_0F6A(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F6A_reg(r1: i32, r2: i32) { instr_0F6A(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F6A_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F6A_mem(addr: i32, r: i32) { instr_0F6A(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F6A(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F6A(source: reg128, r: i32) { // punpckhdq xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); write_xmm128( r, destination.u32_0[2] as i32, @@ -2294,58 +2289,58 @@ pub unsafe fn instr_660F6A(mut source: reg128, mut r: i32) { ); } #[no_mangle] -pub unsafe fn instr_660F6A_reg(mut r1: i32, mut r2: i32) { instr_660F6A(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F6A_reg(r1: i32, r2: i32) { instr_660F6A(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F6A_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F6A_mem(addr: i32, r: i32) { instr_660F6A(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F6B(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0F6B(source: reg64, r: i32) { // packssdw mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); - let mut low: i32 = (saturate_sd_to_sw(destination.u32_0[0]) + let destination: reg64 = read_mmx64s(r); + let low: i32 = (saturate_sd_to_sw(destination.u32_0[0]) | saturate_sd_to_sw(destination.u32_0[1]) << 16) as i32; - let mut high: i32 = + let high: i32 = (saturate_sd_to_sw(source.u32_0[0]) | saturate_sd_to_sw(source.u32_0[1]) << 16) as i32; write_mmx64(r, low, high); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0F6B_reg(mut r1: i32, mut r2: i32) { instr_0F6B(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F6B_reg(r1: i32, r2: i32) { instr_0F6B(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F6B_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F6B_mem(addr: i32, r: i32) { instr_0F6B(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F6B(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F6B(source: reg128, r: i32) { // packssdw xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); - let mut dword0: i32 = (saturate_sd_to_sw(destination.u32_0[0]) + let destination: reg128 = read_xmm128s(r); + let dword0: i32 = (saturate_sd_to_sw(destination.u32_0[0]) | saturate_sd_to_sw(destination.u32_0[1]) << 16) as i32; - let mut dword1: i32 = (saturate_sd_to_sw(destination.u32_0[2]) + let dword1: i32 = (saturate_sd_to_sw(destination.u32_0[2]) | saturate_sd_to_sw(destination.u32_0[3]) << 16) as i32; - let mut dword2: i32 = + let dword2: i32 = (saturate_sd_to_sw(source.u32_0[0]) | saturate_sd_to_sw(source.u32_0[1]) << 16) as i32; - let mut dword3: i32 = + let dword3: i32 = (saturate_sd_to_sw(source.u32_0[2]) | saturate_sd_to_sw(source.u32_0[3]) << 16) as i32; write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn instr_660F6B_reg(mut r1: i32, mut r2: i32) { instr_660F6B(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F6B_reg(r1: i32, r2: i32) { instr_660F6B(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F6B_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F6B_mem(addr: i32, r: i32) { instr_660F6B(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F6C_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0F6C_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F6C_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } +pub unsafe fn instr_0F6C_reg(r1: i32, r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F6C(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F6C(source: reg128, r: i32) { // punpcklqdq xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); write_xmm128( r, destination.u32_0[0] as i32, @@ -2355,20 +2350,20 @@ pub unsafe fn instr_660F6C(mut source: reg128, mut r: i32) { ); } #[no_mangle] -pub unsafe fn instr_660F6C_reg(mut r1: i32, mut r2: i32) { instr_660F6C(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F6C_reg(r1: i32, r2: i32) { instr_660F6C(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F6C_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F6C_mem(addr: i32, r: i32) { instr_660F6C(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F6D_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0F6D_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F6D_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } +pub unsafe fn instr_0F6D_reg(r1: i32, r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F6D(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F6D(source: reg128, r: i32) { // punpckhqdq xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); write_xmm128( r, destination.u32_0[2] as i32, @@ -2378,98 +2373,94 @@ pub unsafe fn instr_660F6D(mut source: reg128, mut r: i32) { ); } #[no_mangle] -pub unsafe fn instr_660F6D_reg(mut r1: i32, mut r2: i32) { instr_660F6D(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F6D_reg(r1: i32, r2: i32) { instr_660F6D(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F6D_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F6D_mem(addr: i32, r: i32) { instr_660F6D(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F6E(mut source: i32, mut r: i32) { +pub unsafe fn instr_0F6E(source: i32, r: i32) { // movd mm, r/m32 write_mmx64(r, source, 0); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0F6E_reg(mut r1: i32, mut r2: i32) { instr_0F6E(read_reg32(r1), r2); } +pub unsafe fn instr_0F6E_reg(r1: i32, r2: i32) { instr_0F6E(read_reg32(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F6E_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F6E_mem(addr: i32, r: i32) { instr_0F6E(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F6E(mut source: i32, mut r: i32) { +pub unsafe fn instr_660F6E(source: i32, r: i32) { // movd mm, r/m32 write_xmm128(r, source, 0, 0, 0); } #[no_mangle] -pub unsafe fn instr_660F6E_reg(mut r1: i32, mut r2: i32) { instr_660F6E(read_reg32(r1), r2); } +pub unsafe fn instr_660F6E_reg(r1: i32, r2: i32) { instr_660F6E(read_reg32(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F6E_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F6E_mem(addr: i32, r: i32) { instr_660F6E(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F6F(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0F6F(source: reg64, r: i32) { // movq mm, mm/m64 write_mmx64(r, source.u32_0[0] as i32, source.u32_0[1] as i32); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0F6F_reg(mut r1: i32, mut r2: i32) { instr_0F6F(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F6F_reg(r1: i32, r2: i32) { instr_0F6F(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F6F_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F6F_mem(addr: i32, r: i32) { instr_0F6F(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F6F(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F6F(source: reg128, r: i32) { // movdqa xmm, xmm/mem128 // XXX: Aligned access or #gp // XXX: Aligned read or #gp mov_rm_r128(source, r); } #[no_mangle] -pub unsafe fn instr_660F6F_reg(mut r1: i32, mut r2: i32) { instr_660F6F(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F6F_reg(r1: i32, r2: i32) { instr_660F6F(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F6F_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F6F_mem(addr: i32, r: i32) { instr_660F6F(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F6F(mut source: reg128, mut r: i32) { +pub unsafe fn instr_F30F6F(source: reg128, r: i32) { // movdqu xmm, xmm/m128 mov_rm_r128(source, r); } #[no_mangle] -pub unsafe fn instr_F30F6F_reg(mut r1: i32, mut r2: i32) { instr_F30F6F(read_xmm128s(r1), r2); } +pub unsafe fn instr_F30F6F_reg(r1: i32, r2: i32) { instr_F30F6F(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F6F_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F30F6F_mem(addr: i32, r: i32) { instr_F30F6F(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F70(mut source: reg64, mut r: i32, mut imm8: i32) { +pub unsafe fn instr_0F70(source: reg64, r: i32, imm8: i32) { // pshufw mm1, mm2/m64, imm8 - let mut word0_shift: i32 = imm8 & 3; - let mut word0: u32 = - source.u32_0[(word0_shift >> 1) as usize] >> ((word0_shift & 1) << 4) & 65535; - let mut word1_shift: i32 = imm8 >> 2 & 3; - let mut word1: u32 = source.u32_0[(word1_shift >> 1) as usize] >> ((word1_shift & 1) << 4); - let mut low: i32 = (word0 | word1 << 16) as i32; - let mut word2_shift: i32 = imm8 >> 4 & 3; - let mut word2: u32 = - source.u32_0[(word2_shift >> 1) as usize] >> ((word2_shift & 1) << 4) & 65535; - let mut word3_shift: u32 = (imm8 >> 6) as u32; - let mut word3: u32 = source.u32_0[(word3_shift >> 1) as usize] >> ((word3_shift & 1) << 4); - let mut high: i32 = (word2 | word3 << 16) as i32; + let word0_shift: i32 = imm8 & 3; + let word0: u32 = source.u32_0[(word0_shift >> 1) as usize] >> ((word0_shift & 1) << 4) & 65535; + let word1_shift: i32 = imm8 >> 2 & 3; + let word1: u32 = source.u32_0[(word1_shift >> 1) as usize] >> ((word1_shift & 1) << 4); + let low: i32 = (word0 | word1 << 16) as i32; + let word2_shift: i32 = imm8 >> 4 & 3; + let word2: u32 = source.u32_0[(word2_shift >> 1) as usize] >> ((word2_shift & 1) << 4) & 65535; + let word3_shift: u32 = (imm8 >> 6) as u32; + let word3: u32 = source.u32_0[(word3_shift >> 1) as usize] >> ((word3_shift & 1) << 4); + let high: i32 = (word2 | word3 << 16) as i32; write_mmx64(r, low, high); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) { - instr_0F70(read_mmx64s(r1), r2, imm); -} +pub unsafe fn instr_0F70_reg(r1: i32, r2: i32, imm: i32) { instr_0F70(read_mmx64s(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_0F70_mem(mut addr: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr_0F70_mem(addr: i32, r: i32, imm: i32) { instr_0F70(return_on_pagefault!(safe_read64s(addr)), r, imm); } #[no_mangle] -pub unsafe fn instr_660F70(mut source: reg128, mut r: i32, mut imm8: i32) { +pub unsafe fn instr_660F70(source: reg128, r: i32, imm8: i32) { // pshufd xmm, xmm/mem128 // XXX: Aligned access or #gp write_xmm128( @@ -2481,16 +2472,16 @@ pub unsafe fn instr_660F70(mut source: reg128, mut r: i32, mut imm8: i32) { ); } #[no_mangle] -pub unsafe fn instr_660F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) { +pub unsafe fn instr_660F70_reg(r1: i32, r2: i32, imm: i32) { instr_660F70(read_xmm128s(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_660F70_mem(mut addr: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr_660F70_mem(addr: i32, r: i32, imm: i32) { instr_660F70(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] -pub unsafe fn instr_F20F70(mut source: reg128, mut r: i32, mut imm8: i32) { +pub unsafe fn instr_F20F70(source: reg128, r: i32, imm8: i32) { // pshuflw xmm, xmm/m128, imm8 // XXX: Aligned access or #gp write_xmm128( @@ -2504,15 +2495,15 @@ pub unsafe fn instr_F20F70(mut source: reg128, mut r: i32, mut imm8: i32) { ); } #[no_mangle] -pub unsafe fn instr_F20F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) { +pub unsafe fn instr_F20F70_reg(r1: i32, r2: i32, imm: i32) { instr_F20F70(read_xmm128s(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_F20F70_mem(mut addr: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr_F20F70_mem(addr: i32, r: i32, imm: i32) { instr_F20F70(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] -pub unsafe fn instr_F30F70(mut source: reg128, mut r: i32, mut imm8: i32) { +pub unsafe fn instr_F30F70(source: reg128, r: i32, imm8: i32) { // pshufhw xmm, xmm/m128, imm8 // XXX: Aligned access or #gp write_xmm128( @@ -2526,128 +2517,128 @@ pub unsafe fn instr_F30F70(mut source: reg128, mut r: i32, mut imm8: i32) { ); } #[no_mangle] -pub unsafe fn instr_F30F70_reg(mut r1: i32, mut r2: i32, mut imm: i32) { +pub unsafe fn instr_F30F70_reg(r1: i32, r2: i32, imm: i32) { instr_F30F70(read_xmm128s(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_F30F70_mem(mut addr: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr_F30F70_mem(addr: i32, r: i32, imm: i32) { instr_F30F70(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] -pub unsafe fn instr_0F71_2_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0F71_2_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F71_4_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0F71_4_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F71_6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0F71_6_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F71_2_reg(mut r: i32, mut imm8: i32) { +pub unsafe fn instr_0F71_2_reg(r: i32, imm8: i32) { // psrlw mm, imm8 psrlw_r64(r, imm8 as u64); } #[no_mangle] -pub unsafe fn instr_0F71_4_reg(mut r: i32, mut imm8: i32) { +pub unsafe fn instr_0F71_4_reg(r: i32, imm8: i32) { // psraw mm, imm8 psraw_r64(r, imm8 as u64); } #[no_mangle] -pub unsafe fn instr_0F71_6_reg(mut r: i32, mut imm8: i32) { +pub unsafe fn instr_0F71_6_reg(r: i32, imm8: i32) { // psllw mm, imm8 psllw_r64(r, imm8 as u64); } #[no_mangle] -pub unsafe fn instr_660F71_2_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_660F71_2_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F71_4_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_660F71_4_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F71_6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_660F71_6_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F71_2_reg(mut r: i32, mut imm8: i32) { +pub unsafe fn instr_660F71_2_reg(r: i32, imm8: i32) { // psrlw xmm, imm8 psrlw_r128(r, imm8 as u64); } #[no_mangle] -pub unsafe fn instr_660F71_4_reg(mut r: i32, mut imm8: i32) { +pub unsafe fn instr_660F71_4_reg(r: i32, imm8: i32) { // psraw xmm, imm8 psraw_r128(r, imm8 as u64); } #[no_mangle] -pub unsafe fn instr_660F71_6_reg(mut r: i32, mut imm8: i32) { +pub unsafe fn instr_660F71_6_reg(r: i32, imm8: i32) { // psllw xmm, imm8 psllw_r128(r, imm8 as u64); } #[no_mangle] -pub unsafe fn instr_0F72_2_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0F72_2_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F72_4_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0F72_4_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F72_6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0F72_6_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F72_2_reg(mut r: i32, mut imm8: i32) { +pub unsafe fn instr_0F72_2_reg(r: i32, imm8: i32) { // psrld mm, imm8 psrld_r64(r, imm8 as u64); } #[no_mangle] -pub unsafe fn instr_0F72_4_reg(mut r: i32, mut imm8: i32) { +pub unsafe fn instr_0F72_4_reg(r: i32, imm8: i32) { // psrad mm, imm8 psrad_r64(r, imm8 as u64); } #[no_mangle] -pub unsafe fn instr_0F72_6_reg(mut r: i32, mut imm8: i32) { +pub unsafe fn instr_0F72_6_reg(r: i32, imm8: i32) { // pslld mm, imm8 pslld_r64(r, imm8 as u64); } #[no_mangle] -pub unsafe fn instr_660F72_2_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_660F72_2_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F72_4_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_660F72_4_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F72_6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_660F72_6_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F72_2_reg(mut r: i32, mut imm8: i32) { +pub unsafe fn instr_660F72_2_reg(r: i32, imm8: i32) { // psrld xmm, imm8 psrld_r128(r, imm8 as u64); } #[no_mangle] -pub unsafe fn instr_660F72_4_reg(mut r: i32, mut imm8: i32) { +pub unsafe fn instr_660F72_4_reg(r: i32, imm8: i32) { // psrad xmm, imm8 psrad_r128(r, imm8 as u64); } #[no_mangle] -pub unsafe fn instr_660F72_6_reg(mut r: i32, mut imm8: i32) { +pub unsafe fn instr_660F72_6_reg(r: i32, imm8: i32) { // pslld xmm, imm8 pslld_r128(r, imm8 as u64); } #[no_mangle] -pub unsafe fn instr_0F73_2_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0F73_2_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F73_6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0F73_6_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0F73_2_reg(mut r: i32, mut imm8: i32) { +pub unsafe fn instr_0F73_2_reg(r: i32, imm8: i32) { // psrlq mm, imm8 psrlq_r64(r, imm8 as u64); } #[no_mangle] -pub unsafe fn instr_0F73_6_reg(mut r: i32, mut imm8: i32) { +pub unsafe fn instr_0F73_6_reg(r: i32, imm8: i32) { // psllq mm, imm8 psllq_r64(r, imm8 as u64); } #[no_mangle] -pub unsafe fn instr_660F73_2_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_660F73_2_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F73_3_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_660F73_3_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F73_6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_660F73_6_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F73_7_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_660F73_7_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660F73_2_reg(mut r: i32, mut imm8: i32) { +pub unsafe fn instr_660F73_2_reg(r: i32, imm8: i32) { // psrlq xmm, imm8 psrlq_r128(r, imm8 as u64); } #[no_mangle] -pub unsafe fn instr_660F73_3_reg(mut r: i32, mut imm8: i32) { +pub unsafe fn instr_660F73_3_reg(r: i32, imm8: i32) { // psrldq xmm, imm8 - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); if imm8 == 0 { return; } @@ -2655,7 +2646,7 @@ pub unsafe fn instr_660F73_3_reg(mut r: i32, mut imm8: i32) { let mut result: reg128 = reg128 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - let mut shift: u32 = (if imm8 > 15 { 128 } else { imm8 << 3 }) as u32; + let shift: u32 = (if imm8 > 15 { 128 } else { imm8 << 3 }) as u32; if shift <= 63 { result.u64_0[0] = destination.u64_0[0] >> shift | destination.u64_0[1] << (64 - shift); result.u64_0[1] = destination.u64_0[1] >> shift @@ -2669,14 +2660,14 @@ pub unsafe fn instr_660F73_3_reg(mut r: i32, mut imm8: i32) { }; } #[no_mangle] -pub unsafe fn instr_660F73_6_reg(mut r: i32, mut imm8: i32) { +pub unsafe fn instr_660F73_6_reg(r: i32, imm8: i32) { // psllq xmm, imm8 psllq_r128(r, imm8 as u64); } #[no_mangle] -pub unsafe fn instr_660F73_7_reg(mut r: i32, mut imm8: i32) { +pub unsafe fn instr_660F73_7_reg(r: i32, imm8: i32) { // pslldq xmm, imm8 - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); if imm8 == 0 { return; } @@ -2684,7 +2675,7 @@ pub unsafe fn instr_660F73_7_reg(mut r: i32, mut imm8: i32) { let mut result: reg128 = reg128 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; - let mut shift: u32 = (if imm8 > 15 { 128 } else { imm8 << 3 }) as u32; + let shift: u32 = (if imm8 > 15 { 128 } else { imm8 << 3 }) as u32; if shift <= 63 { result.u64_0[0] = destination.u64_0[0] << shift; result.u64_0[1] = destination.u64_0[1] << shift | destination.u64_0[0] >> (64 - shift) @@ -2698,9 +2689,9 @@ pub unsafe fn instr_660F73_7_reg(mut r: i32, mut imm8: i32) { }; } #[no_mangle] -pub unsafe fn instr_0F74(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0F74(source: reg64, r: i32) { // pcmpeqb mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; @@ -2717,16 +2708,16 @@ pub unsafe fn instr_0F74(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0F74_reg(mut r1: i32, mut r2: i32) { instr_0F74(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F74_reg(r1: i32, r2: i32) { instr_0F74(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F74_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F74_mem(addr: i32, r: i32) { instr_0F74(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F74(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F74(source: reg128, r: i32) { // pcmpeqb xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; for i in 0..16 { result.u8_0[i as usize] = @@ -2740,55 +2731,55 @@ pub unsafe fn instr_660F74(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F74_reg(mut r1: i32, mut r2: i32) { instr_660F74(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F74_reg(r1: i32, r2: i32) { instr_660F74(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F74_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F74_mem(addr: i32, r: i32) { instr_660F74(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F75(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0F75(source: reg64, r: i32) { // pcmpeqw mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); - let mut word0: i32 = if destination.u16_0[0] as i32 == source.u16_0[0] as i32 { + let destination: reg64 = read_mmx64s(r); + let word0: i32 = if destination.u16_0[0] as i32 == source.u16_0[0] as i32 { 65535 } else { 0 }; - let mut word1: i32 = if destination.u16_0[1] as i32 == source.u16_0[1] as i32 { + let word1: i32 = if destination.u16_0[1] as i32 == source.u16_0[1] as i32 { 65535 } else { 0 }; - let mut word2: i32 = if destination.u16_0[2] as i32 == source.u16_0[2] as i32 { + let word2: i32 = if destination.u16_0[2] as i32 == source.u16_0[2] as i32 { 65535 } else { 0 }; - let mut word3: i32 = if destination.u16_0[3] as i32 == source.u16_0[3] as i32 { + let word3: i32 = if destination.u16_0[3] as i32 == source.u16_0[3] as i32 { 65535 } else { 0 }; - let mut low: i32 = word0 | word1 << 16; - let mut high: i32 = word2 | word3 << 16; + let low: i32 = word0 | word1 << 16; + let high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0F75_reg(mut r1: i32, mut r2: i32) { instr_0F75(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F75_reg(r1: i32, r2: i32) { instr_0F75(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F75_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F75_mem(addr: i32, r: i32) { instr_0F75(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F75(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F75(source: reg128, r: i32) { // pcmpeqw xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; for i in 0..8 { result.u16_0[i as usize] = @@ -2802,22 +2793,22 @@ pub unsafe fn instr_660F75(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F75_reg(mut r1: i32, mut r2: i32) { instr_660F75(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F75_reg(r1: i32, r2: i32) { instr_660F75(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F75_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F75_mem(addr: i32, r: i32) { instr_660F75(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F76(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0F76(source: reg64, r: i32) { // pcmpeqd mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); - let mut low: i32 = if destination.u32_0[0] == source.u32_0[0] { + let destination: reg64 = read_mmx64s(r); + let low: i32 = if destination.u32_0[0] == source.u32_0[0] { -1 } else { 0 }; - let mut high: i32 = if destination.u32_0[1] == source.u32_0[1] { + let high: i32 = if destination.u32_0[1] == source.u32_0[1] { -1 } else { @@ -2827,16 +2818,16 @@ pub unsafe fn instr_0F76(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0F76_reg(mut r1: i32, mut r2: i32) { instr_0F76(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F76_reg(r1: i32, r2: i32) { instr_0F76(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F76_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F76_mem(addr: i32, r: i32) { instr_0F76(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F76(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F76(source: reg128, r: i32) { // pcmpeqd xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); write_xmm128( r, if source.u32_0[0] == destination.u32_0[0] { @@ -2866,9 +2857,9 @@ pub unsafe fn instr_660F76(mut source: reg128, mut r: i32) { ); } #[no_mangle] -pub unsafe fn instr_660F76_reg(mut r1: i32, mut r2: i32) { instr_660F76(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F76_reg(r1: i32, r2: i32) { instr_660F76(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F76_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F76_mem(addr: i32, r: i32) { instr_660F76(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] @@ -2889,204 +2880,204 @@ pub unsafe fn instr_0F7C() { unimplemented_sse(); } #[no_mangle] pub unsafe fn instr_0F7D() { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_0F7E(mut r: i32) -> i32 { +pub unsafe fn instr_0F7E(r: i32) -> i32 { // movd r/m32, mm - let mut data: reg64 = read_mmx64s(r); + let data: reg64 = read_mmx64s(r); transition_fpu_to_mmx(); return data.u32_0[0] as i32; } #[no_mangle] -pub unsafe fn instr_0F7E_reg(mut r1: i32, mut r2: i32) { write_reg32(r1, instr_0F7E(r2)); } +pub unsafe fn instr_0F7E_reg(r1: i32, r2: i32) { write_reg32(r1, instr_0F7E(r2)); } #[no_mangle] -pub unsafe fn instr_0F7E_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F7E_mem(addr: i32, r: i32) { return_on_pagefault!(safe_write32(addr, instr_0F7E(r))); } #[no_mangle] -pub unsafe fn instr_660F7E(mut r: i32) -> i32 { +pub unsafe fn instr_660F7E(r: i32) -> i32 { // movd r/m32, xmm - let mut data: reg64 = read_xmm64s(r); + let data: reg64 = read_xmm64s(r); return data.u32_0[0] as i32; } #[no_mangle] -pub unsafe fn instr_660F7E_reg(mut r1: i32, mut r2: i32) { write_reg32(r1, instr_660F7E(r2)); } +pub unsafe fn instr_660F7E_reg(r1: i32, r2: i32) { write_reg32(r1, instr_660F7E(r2)); } #[no_mangle] -pub unsafe fn instr_660F7E_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F7E_mem(addr: i32, r: i32) { return_on_pagefault!(safe_write32(addr, instr_660F7E(r))); } #[no_mangle] -pub unsafe fn instr_F30F7E_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F30F7E_mem(addr: i32, r: i32) { // movq xmm, xmm/mem64 - let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); + let data: reg64 = return_on_pagefault!(safe_read64s(addr)); write_xmm128(r, data.u32_0[0] as i32, data.u32_0[1] as i32, 0, 0); } #[no_mangle] -pub unsafe fn instr_F30F7E_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_F30F7E_reg(r1: i32, r2: i32) { // movq xmm, xmm/mem64 - let mut data: reg64 = read_xmm64s(r1); + let data: reg64 = read_xmm64s(r1); write_xmm128(r2, data.u32_0[0] as i32, data.u32_0[1] as i32, 0, 0); } #[no_mangle] -pub unsafe fn instr_0F7F_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F7F_mem(addr: i32, r: i32) { // movq mm/m64, mm mov_r_m64(addr, r); } #[no_mangle] -pub unsafe fn instr_0F7F_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_0F7F_reg(r1: i32, r2: i32) { // movq mm/m64, mm - let mut data: reg64 = read_mmx64s(r2); + let data: reg64 = read_mmx64s(r2); write_mmx64(r1, data.u32_0[0] as i32, data.u32_0[1] as i32); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_660F7F_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F7F_mem(addr: i32, r: i32) { // movdqa xmm/m128, xmm // XXX: Aligned write or #gp mov_r_m128(addr, r); } #[no_mangle] -pub unsafe fn instr_660F7F_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_660F7F_reg(r1: i32, r2: i32) { // movdqa xmm/m128, xmm // XXX: Aligned access or #gp mov_r_r128(r1, r2); } #[no_mangle] -pub unsafe fn instr_F30F7F_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F30F7F_mem(addr: i32, r: i32) { // movdqu xmm/m128, xmm mov_r_m128(addr, r); } #[no_mangle] -pub unsafe fn instr_F30F7F_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_F30F7F_reg(r1: i32, r2: i32) { // movdqu xmm/m128, xmm mov_r_r128(r1, r2); } #[no_mangle] -pub unsafe fn instr16_0F80(mut imm: i32) { jmpcc16(test_o(), imm); } +pub unsafe fn instr16_0F80(imm: i32) { jmpcc16(test_o(), imm); } #[no_mangle] -pub unsafe fn instr32_0F80(mut imm: i32) { jmpcc32(test_o(), imm); } +pub unsafe fn instr32_0F80(imm: i32) { jmpcc32(test_o(), imm); } #[no_mangle] -pub unsafe fn instr16_0F81(mut imm: i32) { jmpcc16(!test_o(), imm); } +pub unsafe fn instr16_0F81(imm: i32) { jmpcc16(!test_o(), imm); } #[no_mangle] -pub unsafe fn instr32_0F81(mut imm: i32) { jmpcc32(!test_o(), imm); } +pub unsafe fn instr32_0F81(imm: i32) { jmpcc32(!test_o(), imm); } #[no_mangle] -pub unsafe fn instr16_0F82(mut imm: i32) { jmpcc16(test_b(), imm); } +pub unsafe fn instr16_0F82(imm: i32) { jmpcc16(test_b(), imm); } #[no_mangle] -pub unsafe fn instr32_0F82(mut imm: i32) { jmpcc32(test_b(), imm); } +pub unsafe fn instr32_0F82(imm: i32) { jmpcc32(test_b(), imm); } #[no_mangle] -pub unsafe fn instr16_0F83(mut imm: i32) { jmpcc16(!test_b(), imm); } +pub unsafe fn instr16_0F83(imm: i32) { jmpcc16(!test_b(), imm); } #[no_mangle] -pub unsafe fn instr32_0F83(mut imm: i32) { jmpcc32(!test_b(), imm); } +pub unsafe fn instr32_0F83(imm: i32) { jmpcc32(!test_b(), imm); } #[no_mangle] -pub unsafe fn instr16_0F84(mut imm: i32) { jmpcc16(test_z(), imm); } +pub unsafe fn instr16_0F84(imm: i32) { jmpcc16(test_z(), imm); } #[no_mangle] -pub unsafe fn instr32_0F84(mut imm: i32) { jmpcc32(test_z(), imm); } +pub unsafe fn instr32_0F84(imm: i32) { jmpcc32(test_z(), imm); } #[no_mangle] -pub unsafe fn instr16_0F85(mut imm: i32) { jmpcc16(!test_z(), imm); } +pub unsafe fn instr16_0F85(imm: i32) { jmpcc16(!test_z(), imm); } #[no_mangle] -pub unsafe fn instr32_0F85(mut imm: i32) { jmpcc32(!test_z(), imm); } +pub unsafe fn instr32_0F85(imm: i32) { jmpcc32(!test_z(), imm); } #[no_mangle] -pub unsafe fn instr16_0F86(mut imm: i32) { jmpcc16(test_be(), imm); } +pub unsafe fn instr16_0F86(imm: i32) { jmpcc16(test_be(), imm); } #[no_mangle] -pub unsafe fn instr32_0F86(mut imm: i32) { jmpcc32(test_be(), imm); } +pub unsafe fn instr32_0F86(imm: i32) { jmpcc32(test_be(), imm); } #[no_mangle] -pub unsafe fn instr16_0F87(mut imm: i32) { jmpcc16(!test_be(), imm); } +pub unsafe fn instr16_0F87(imm: i32) { jmpcc16(!test_be(), imm); } #[no_mangle] -pub unsafe fn instr32_0F87(mut imm: i32) { jmpcc32(!test_be(), imm); } +pub unsafe fn instr32_0F87(imm: i32) { jmpcc32(!test_be(), imm); } #[no_mangle] -pub unsafe fn instr16_0F88(mut imm: i32) { jmpcc16(test_s(), imm); } +pub unsafe fn instr16_0F88(imm: i32) { jmpcc16(test_s(), imm); } #[no_mangle] -pub unsafe fn instr32_0F88(mut imm: i32) { jmpcc32(test_s(), imm); } +pub unsafe fn instr32_0F88(imm: i32) { jmpcc32(test_s(), imm); } #[no_mangle] -pub unsafe fn instr16_0F89(mut imm: i32) { jmpcc16(!test_s(), imm); } +pub unsafe fn instr16_0F89(imm: i32) { jmpcc16(!test_s(), imm); } #[no_mangle] -pub unsafe fn instr32_0F89(mut imm: i32) { jmpcc32(!test_s(), imm); } +pub unsafe fn instr32_0F89(imm: i32) { jmpcc32(!test_s(), imm); } #[no_mangle] -pub unsafe fn instr16_0F8A(mut imm: i32) { jmpcc16(test_p(), imm); } +pub unsafe fn instr16_0F8A(imm: i32) { jmpcc16(test_p(), imm); } #[no_mangle] -pub unsafe fn instr32_0F8A(mut imm: i32) { jmpcc32(test_p(), imm); } +pub unsafe fn instr32_0F8A(imm: i32) { jmpcc32(test_p(), imm); } #[no_mangle] -pub unsafe fn instr16_0F8B(mut imm: i32) { jmpcc16(!test_p(), imm); } +pub unsafe fn instr16_0F8B(imm: i32) { jmpcc16(!test_p(), imm); } #[no_mangle] -pub unsafe fn instr32_0F8B(mut imm: i32) { jmpcc32(!test_p(), imm); } +pub unsafe fn instr32_0F8B(imm: i32) { jmpcc32(!test_p(), imm); } #[no_mangle] -pub unsafe fn instr16_0F8C(mut imm: i32) { jmpcc16(test_l(), imm); } +pub unsafe fn instr16_0F8C(imm: i32) { jmpcc16(test_l(), imm); } #[no_mangle] -pub unsafe fn instr32_0F8C(mut imm: i32) { jmpcc32(test_l(), imm); } +pub unsafe fn instr32_0F8C(imm: i32) { jmpcc32(test_l(), imm); } #[no_mangle] -pub unsafe fn instr16_0F8D(mut imm: i32) { jmpcc16(!test_l(), imm); } +pub unsafe fn instr16_0F8D(imm: i32) { jmpcc16(!test_l(), imm); } #[no_mangle] -pub unsafe fn instr32_0F8D(mut imm: i32) { jmpcc32(!test_l(), imm); } +pub unsafe fn instr32_0F8D(imm: i32) { jmpcc32(!test_l(), imm); } #[no_mangle] -pub unsafe fn instr16_0F8E(mut imm: i32) { jmpcc16(test_le(), imm); } +pub unsafe fn instr16_0F8E(imm: i32) { jmpcc16(test_le(), imm); } #[no_mangle] -pub unsafe fn instr32_0F8E(mut imm: i32) { jmpcc32(test_le(), imm); } +pub unsafe fn instr32_0F8E(imm: i32) { jmpcc32(test_le(), imm); } #[no_mangle] -pub unsafe fn instr16_0F8F(mut imm: i32) { jmpcc16(!test_le(), imm); } +pub unsafe fn instr16_0F8F(imm: i32) { jmpcc16(!test_le(), imm); } #[no_mangle] -pub unsafe fn instr32_0F8F(mut imm: i32) { jmpcc32(!test_le(), imm); } +pub unsafe fn instr32_0F8F(imm: i32) { jmpcc32(!test_le(), imm); } #[no_mangle] -pub unsafe fn instr_0F90_reg(mut r: i32, mut unused: i32) { setcc_reg(test_o(), r); } +pub unsafe fn instr_0F90_reg(r: i32, unused: i32) { setcc_reg(test_o(), r); } #[no_mangle] -pub unsafe fn instr_0F91_reg(mut r: i32, mut unused: i32) { setcc_reg(!test_o(), r); } +pub unsafe fn instr_0F91_reg(r: i32, unused: i32) { setcc_reg(!test_o(), r); } #[no_mangle] -pub unsafe fn instr_0F92_reg(mut r: i32, mut unused: i32) { setcc_reg(test_b(), r); } +pub unsafe fn instr_0F92_reg(r: i32, unused: i32) { setcc_reg(test_b(), r); } #[no_mangle] -pub unsafe fn instr_0F93_reg(mut r: i32, mut unused: i32) { setcc_reg(!test_b(), r); } +pub unsafe fn instr_0F93_reg(r: i32, unused: i32) { setcc_reg(!test_b(), r); } #[no_mangle] -pub unsafe fn instr_0F94_reg(mut r: i32, mut unused: i32) { setcc_reg(test_z(), r); } +pub unsafe fn instr_0F94_reg(r: i32, unused: i32) { setcc_reg(test_z(), r); } #[no_mangle] -pub unsafe fn instr_0F95_reg(mut r: i32, mut unused: i32) { setcc_reg(!test_z(), r); } +pub unsafe fn instr_0F95_reg(r: i32, unused: i32) { setcc_reg(!test_z(), r); } #[no_mangle] -pub unsafe fn instr_0F96_reg(mut r: i32, mut unused: i32) { setcc_reg(test_be(), r); } +pub unsafe fn instr_0F96_reg(r: i32, unused: i32) { setcc_reg(test_be(), r); } #[no_mangle] -pub unsafe fn instr_0F97_reg(mut r: i32, mut unused: i32) { setcc_reg(!test_be(), r); } +pub unsafe fn instr_0F97_reg(r: i32, unused: i32) { setcc_reg(!test_be(), r); } #[no_mangle] -pub unsafe fn instr_0F98_reg(mut r: i32, mut unused: i32) { setcc_reg(test_s(), r); } +pub unsafe fn instr_0F98_reg(r: i32, unused: i32) { setcc_reg(test_s(), r); } #[no_mangle] -pub unsafe fn instr_0F99_reg(mut r: i32, mut unused: i32) { setcc_reg(!test_s(), r); } +pub unsafe fn instr_0F99_reg(r: i32, unused: i32) { setcc_reg(!test_s(), r); } #[no_mangle] -pub unsafe fn instr_0F9A_reg(mut r: i32, mut unused: i32) { setcc_reg(test_p(), r); } +pub unsafe fn instr_0F9A_reg(r: i32, unused: i32) { setcc_reg(test_p(), r); } #[no_mangle] -pub unsafe fn instr_0F9B_reg(mut r: i32, mut unused: i32) { setcc_reg(!test_p(), r); } +pub unsafe fn instr_0F9B_reg(r: i32, unused: i32) { setcc_reg(!test_p(), r); } #[no_mangle] -pub unsafe fn instr_0F9C_reg(mut r: i32, mut unused: i32) { setcc_reg(test_l(), r); } +pub unsafe fn instr_0F9C_reg(r: i32, unused: i32) { setcc_reg(test_l(), r); } #[no_mangle] -pub unsafe fn instr_0F9D_reg(mut r: i32, mut unused: i32) { setcc_reg(!test_l(), r); } +pub unsafe fn instr_0F9D_reg(r: i32, unused: i32) { setcc_reg(!test_l(), r); } #[no_mangle] -pub unsafe fn instr_0F9E_reg(mut r: i32, mut unused: i32) { setcc_reg(test_le(), r); } +pub unsafe fn instr_0F9E_reg(r: i32, unused: i32) { setcc_reg(test_le(), r); } #[no_mangle] -pub unsafe fn instr_0F9F_reg(mut r: i32, mut unused: i32) { setcc_reg(!test_le(), r); } +pub unsafe fn instr_0F9F_reg(r: i32, unused: i32) { setcc_reg(!test_le(), r); } #[no_mangle] -pub unsafe fn instr_0F90_mem(mut addr: i32, mut unused: i32) { setcc_mem(test_o(), addr); } +pub unsafe fn instr_0F90_mem(addr: i32, unused: i32) { setcc_mem(test_o(), addr); } #[no_mangle] -pub unsafe fn instr_0F91_mem(mut addr: i32, mut unused: i32) { setcc_mem(!test_o(), addr); } +pub unsafe fn instr_0F91_mem(addr: i32, unused: i32) { setcc_mem(!test_o(), addr); } #[no_mangle] -pub unsafe fn instr_0F92_mem(mut addr: i32, mut unused: i32) { setcc_mem(test_b(), addr); } +pub unsafe fn instr_0F92_mem(addr: i32, unused: i32) { setcc_mem(test_b(), addr); } #[no_mangle] -pub unsafe fn instr_0F93_mem(mut addr: i32, mut unused: i32) { setcc_mem(!test_b(), addr); } +pub unsafe fn instr_0F93_mem(addr: i32, unused: i32) { setcc_mem(!test_b(), addr); } #[no_mangle] -pub unsafe fn instr_0F94_mem(mut addr: i32, mut unused: i32) { setcc_mem(test_z(), addr); } +pub unsafe fn instr_0F94_mem(addr: i32, unused: i32) { setcc_mem(test_z(), addr); } #[no_mangle] -pub unsafe fn instr_0F95_mem(mut addr: i32, mut unused: i32) { setcc_mem(!test_z(), addr); } +pub unsafe fn instr_0F95_mem(addr: i32, unused: i32) { setcc_mem(!test_z(), addr); } #[no_mangle] -pub unsafe fn instr_0F96_mem(mut addr: i32, mut unused: i32) { setcc_mem(test_be(), addr); } +pub unsafe fn instr_0F96_mem(addr: i32, unused: i32) { setcc_mem(test_be(), addr); } #[no_mangle] -pub unsafe fn instr_0F97_mem(mut addr: i32, mut unused: i32) { setcc_mem(!test_be(), addr); } +pub unsafe fn instr_0F97_mem(addr: i32, unused: i32) { setcc_mem(!test_be(), addr); } #[no_mangle] -pub unsafe fn instr_0F98_mem(mut addr: i32, mut unused: i32) { setcc_mem(test_s(), addr); } +pub unsafe fn instr_0F98_mem(addr: i32, unused: i32) { setcc_mem(test_s(), addr); } #[no_mangle] -pub unsafe fn instr_0F99_mem(mut addr: i32, mut unused: i32) { setcc_mem(!test_s(), addr); } +pub unsafe fn instr_0F99_mem(addr: i32, unused: i32) { setcc_mem(!test_s(), addr); } #[no_mangle] -pub unsafe fn instr_0F9A_mem(mut addr: i32, mut unused: i32) { setcc_mem(test_p(), addr); } +pub unsafe fn instr_0F9A_mem(addr: i32, unused: i32) { setcc_mem(test_p(), addr); } #[no_mangle] -pub unsafe fn instr_0F9B_mem(mut addr: i32, mut unused: i32) { setcc_mem(!test_p(), addr); } +pub unsafe fn instr_0F9B_mem(addr: i32, unused: i32) { setcc_mem(!test_p(), addr); } #[no_mangle] -pub unsafe fn instr_0F9C_mem(mut addr: i32, mut unused: i32) { setcc_mem(test_l(), addr); } +pub unsafe fn instr_0F9C_mem(addr: i32, unused: i32) { setcc_mem(test_l(), addr); } #[no_mangle] -pub unsafe fn instr_0F9D_mem(mut addr: i32, mut unused: i32) { setcc_mem(!test_l(), addr); } +pub unsafe fn instr_0F9D_mem(addr: i32, unused: i32) { setcc_mem(!test_l(), addr); } #[no_mangle] -pub unsafe fn instr_0F9E_mem(mut addr: i32, mut unused: i32) { setcc_mem(test_le(), addr); } +pub unsafe fn instr_0F9E_mem(addr: i32, unused: i32) { setcc_mem(test_le(), addr); } #[no_mangle] -pub unsafe fn instr_0F9F_mem(mut addr: i32, mut unused: i32) { setcc_mem(!test_le(), addr); } +pub unsafe fn instr_0F9F_mem(addr: i32, unused: i32) { setcc_mem(!test_le(), addr); } #[no_mangle] pub unsafe fn instr16_0FA0() { return_on_pagefault!(push16(*sreg.offset(FS as isize) as i32)); @@ -3121,39 +3112,33 @@ pub unsafe fn instr32_0FA1() { #[no_mangle] pub unsafe fn instr_0FA2() { cpuid(); } #[no_mangle] -pub unsafe fn instr16_0FA3_reg(mut r1: i32, mut r2: i32) { - bt_reg(read_reg16(r1), read_reg16(r2) & 15); -} +pub unsafe fn instr16_0FA3_reg(r1: i32, r2: i32) { bt_reg(read_reg16(r1), read_reg16(r2) & 15); } #[no_mangle] -pub unsafe fn instr16_0FA3_mem(mut addr: i32, mut r: i32) { - bt_mem(addr, read_reg16(r) << 16 >> 16); -} +pub unsafe fn instr16_0FA3_mem(addr: i32, r: i32) { bt_mem(addr, read_reg16(r) << 16 >> 16); } #[no_mangle] -pub unsafe fn instr32_0FA3_reg(mut r1: i32, mut r2: i32) { - bt_reg(read_reg32(r1), read_reg32(r2) & 31); -} +pub unsafe fn instr32_0FA3_reg(r1: i32, r2: i32) { bt_reg(read_reg32(r1), read_reg32(r2) & 31); } #[no_mangle] -pub unsafe fn instr32_0FA3_mem(mut addr: i32, mut r: i32) { bt_mem(addr, read_reg32(r)); } +pub unsafe fn instr32_0FA3_mem(addr: i32, r: i32) { bt_mem(addr, read_reg32(r)); } #[no_mangle] -pub unsafe fn instr16_0FA4_mem(mut addr: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr16_0FA4_mem(addr: i32, r: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, shld16(___, read_reg16(r), imm & 31)); } #[no_mangle] -pub unsafe fn instr16_0FA4_reg(mut r1: i32, mut r: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0FA4_reg(r1: i32, r: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, shld16(____0, read_reg16(r), imm & 31)); } #[no_mangle] -pub unsafe fn instr32_0FA4_mem(mut addr: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr32_0FA4_mem(addr: i32, r: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, shld32(___, read_reg32(r), imm & 31)); } #[no_mangle] -pub unsafe fn instr32_0FA4_reg(mut r1: i32, mut r: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0FA4_reg(r1: i32, r: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, shld32(____0, read_reg32(r), imm & 31)); } #[no_mangle] -pub unsafe fn instr16_0FA5_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr16_0FA5_mem(addr: i32, r: i32) { SAFE_READ_WRITE16!( ___, addr, @@ -3161,15 +3146,15 @@ pub unsafe fn instr16_0FA5_mem(mut addr: i32, mut r: i32) { ); } #[no_mangle] -pub unsafe fn instr16_0FA5_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0FA5_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16( r1, shld16(____0, read_reg16(r), *reg8.offset(CL as isize) as i32 & 31), ); } #[no_mangle] -pub unsafe fn instr32_0FA5_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr32_0FA5_mem(addr: i32, r: i32) { SAFE_READ_WRITE32!( ___, addr, @@ -3177,8 +3162,8 @@ pub unsafe fn instr32_0FA5_mem(mut addr: i32, mut r: i32) { ); } #[no_mangle] -pub unsafe fn instr32_0FA5_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0FA5_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); write_reg32( r1, shld32(____0, read_reg32(r), *reg8.offset(CL as isize) as i32 & 31), @@ -3228,39 +3213,37 @@ pub unsafe fn instr_0FAA() { undefined_instruction(); } #[no_mangle] -pub unsafe fn instr16_0FAB_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr16_0FAB_reg(r1: i32, r2: i32) { write_reg16(r1, bts_reg(read_reg16(r1), read_reg16(r2) & 15)); } #[no_mangle] -pub unsafe fn instr16_0FAB_mem(mut addr: i32, mut r: i32) { - bts_mem(addr, read_reg16(r) << 16 >> 16); -} +pub unsafe fn instr16_0FAB_mem(addr: i32, r: i32) { bts_mem(addr, read_reg16(r) << 16 >> 16); } #[no_mangle] -pub unsafe fn instr32_0FAB_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr32_0FAB_reg(r1: i32, r2: i32) { write_reg32(r1, bts_reg(read_reg32(r1), read_reg32(r2) & 31)); } #[no_mangle] -pub unsafe fn instr32_0FAB_mem(mut addr: i32, mut r: i32) { bts_mem(addr, read_reg32(r)); } +pub unsafe fn instr32_0FAB_mem(addr: i32, r: i32) { bts_mem(addr, read_reg32(r)); } #[no_mangle] -pub unsafe fn instr16_0FAC_mem(mut addr: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr16_0FAC_mem(addr: i32, r: i32, imm: i32) { SAFE_READ_WRITE16!(___, addr, shrd16(___, read_reg16(r), imm & 31)); } #[no_mangle] -pub unsafe fn instr16_0FAC_reg(mut r1: i32, mut r: i32, mut imm: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0FAC_reg(r1: i32, r: i32, imm: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, shrd16(____0, read_reg16(r), imm & 31)); } #[no_mangle] -pub unsafe fn instr32_0FAC_mem(mut addr: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr32_0FAC_mem(addr: i32, r: i32, imm: i32) { SAFE_READ_WRITE32!(___, addr, shrd32(___, read_reg32(r), imm & 31)); } #[no_mangle] -pub unsafe fn instr32_0FAC_reg(mut r1: i32, mut r: i32, mut imm: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0FAC_reg(r1: i32, r: i32, imm: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, shrd32(____0, read_reg32(r), imm & 31)); } #[no_mangle] -pub unsafe fn instr16_0FAD_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr16_0FAD_mem(addr: i32, r: i32) { SAFE_READ_WRITE16!( ___, addr, @@ -3268,15 +3251,15 @@ pub unsafe fn instr16_0FAD_mem(mut addr: i32, mut r: i32) { ); } #[no_mangle] -pub unsafe fn instr16_0FAD_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0FAD_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16( r1, shrd16(____0, read_reg16(r), *reg8.offset(CL as isize) as i32 & 31), ); } #[no_mangle] -pub unsafe fn instr32_0FAD_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr32_0FAD_mem(addr: i32, r: i32) { SAFE_READ_WRITE32!( ___, addr, @@ -3284,27 +3267,27 @@ pub unsafe fn instr32_0FAD_mem(mut addr: i32, mut r: i32) { ); } #[no_mangle] -pub unsafe fn instr32_0FAD_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0FAD_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); write_reg32( r1, shrd32(____0, read_reg32(r), *reg8.offset(CL as isize) as i32 & 31), ); } #[no_mangle] -pub unsafe fn instr_0FAE_0_reg(mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0FAE_0_reg(r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FAE_0_mem(mut addr: i32) { fxsave(addr); } +pub unsafe fn instr_0FAE_0_mem(addr: i32) { fxsave(addr); } #[no_mangle] -pub unsafe fn instr_0FAE_1_reg(mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0FAE_1_reg(r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FAE_1_mem(mut addr: i32) { fxrstor(addr); } +pub unsafe fn instr_0FAE_1_mem(addr: i32) { fxrstor(addr); } #[no_mangle] -pub unsafe fn instr_0FAE_2_reg(mut r: i32) { unimplemented_sse(); } +pub unsafe fn instr_0FAE_2_reg(r: i32) { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_0FAE_2_mem(mut addr: i32) { +pub unsafe fn instr_0FAE_2_mem(addr: i32) { // ldmxcsr - let mut new_mxcsr: i32 = return_on_pagefault!(safe_read32s(addr)); + let new_mxcsr: i32 = return_on_pagefault!(safe_read32s(addr)); if 0 != new_mxcsr & !MXCSR_MASK { dbg_log!("Invalid mxcsr bits: {:x}", new_mxcsr & !MXCSR_MASK); trigger_gp_non_raising(0); @@ -3316,73 +3299,73 @@ pub unsafe fn instr_0FAE_2_mem(mut addr: i32) { }; } #[no_mangle] -pub unsafe fn instr_0FAE_3_reg(mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0FAE_3_reg(r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FAE_3_mem(mut addr: i32) { +pub unsafe fn instr_0FAE_3_mem(addr: i32) { // stmxcsr return_on_pagefault!(safe_write32(addr, *mxcsr)); } #[no_mangle] -pub unsafe fn instr_0FAE_4_reg(mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0FAE_4_reg(r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FAE_4_mem(mut addr: i32) { +pub unsafe fn instr_0FAE_4_mem(addr: i32) { // xsave undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0FAE_5_reg(mut r: i32) { +pub unsafe fn instr_0FAE_5_reg(r: i32) { // lfence dbg_assert!(r == 0, ("Unexpected lfence encoding")); } #[no_mangle] -pub unsafe fn instr_0FAE_5_mem(mut addr: i32) { +pub unsafe fn instr_0FAE_5_mem(addr: i32) { // xrstor undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0FAE_6_reg(mut r: i32) { +pub unsafe fn instr_0FAE_6_reg(r: i32) { // mfence dbg_assert!(r == 0, ("Unexpected mfence encoding")); } #[no_mangle] -pub unsafe fn instr_0FAE_6_mem(mut addr: i32) { +pub unsafe fn instr_0FAE_6_mem(addr: i32) { // xsaveopt undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0FAE_7_reg(mut r: i32) { +pub unsafe fn instr_0FAE_7_reg(r: i32) { // sfence dbg_assert!(r == 0, ("Unexpected sfence encoding")); } #[no_mangle] -pub unsafe fn instr_0FAE_7_mem(mut addr: i32) { +pub unsafe fn instr_0FAE_7_mem(addr: i32) { // clflush undefined_instruction(); } #[no_mangle] -pub unsafe fn instr16_0FAF_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0FAF_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, imul_reg16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_0FAF_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0FAF_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r, imul_reg16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_0FAF_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_0FAF_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, imul_reg32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_0FAF_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0FAF_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r, imul_reg32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr_0FB0_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_0FB0_reg(r1: i32, r2: i32) { // cmpxchg8 - let mut data: i32 = read_reg8(r1); + let data: i32 = read_reg8(r1); cmp8(*reg8.offset(AL as isize) as i32, data); if getzf() { write_reg8(r1, read_reg8(r2)); @@ -3392,10 +3375,10 @@ pub unsafe fn instr_0FB0_reg(mut r1: i32, mut r2: i32) { }; } #[no_mangle] -pub unsafe fn instr_0FB0_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FB0_mem(addr: i32, r: i32) { // cmpxchg8 return_on_pagefault!(writable_or_pagefault(addr, 1)); - let mut data: i32 = return_on_pagefault!(safe_read8(addr)); + let data: i32 = return_on_pagefault!(safe_read8(addr)); cmp8(*reg8.offset(AL as isize) as i32, data); if getzf() { safe_write8(addr, read_reg8(r)).unwrap(); @@ -3406,9 +3389,9 @@ pub unsafe fn instr_0FB0_mem(mut addr: i32, mut r: i32) { }; } #[no_mangle] -pub unsafe fn instr16_0FB1_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr16_0FB1_reg(r1: i32, r2: i32) { // cmpxchg16 - let mut data: i32 = read_reg16(r1); + let data: i32 = read_reg16(r1); cmp16(*reg16.offset(AX as isize) as i32, data); if getzf() { write_reg16(r1, read_reg16(r2)); @@ -3418,10 +3401,10 @@ pub unsafe fn instr16_0FB1_reg(mut r1: i32, mut r2: i32) { }; } #[no_mangle] -pub unsafe fn instr16_0FB1_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr16_0FB1_mem(addr: i32, r: i32) { // cmpxchg16 return_on_pagefault!(writable_or_pagefault(addr, 2)); - let mut data: i32 = return_on_pagefault!(safe_read16(addr)); + let data: i32 = return_on_pagefault!(safe_read16(addr)); cmp16(*reg16.offset(AX as isize) as i32, data); if getzf() { safe_write16(addr, read_reg16(r)).unwrap(); @@ -3432,9 +3415,9 @@ pub unsafe fn instr16_0FB1_mem(mut addr: i32, mut r: i32) { }; } #[no_mangle] -pub unsafe fn instr32_0FB1_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr32_0FB1_reg(r1: i32, r2: i32) { // cmpxchg32 - let mut data: i32 = read_reg32(r1); + let data: i32 = read_reg32(r1); cmp32(*reg32s.offset(EAX as isize), data); if getzf() { write_reg32(r1, read_reg32(r2)); @@ -3444,10 +3427,10 @@ pub unsafe fn instr32_0FB1_reg(mut r1: i32, mut r2: i32) { }; } #[no_mangle] -pub unsafe fn instr32_0FB1_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr32_0FB1_mem(addr: i32, r: i32) { // cmpxchg32 return_on_pagefault!(writable_or_pagefault(addr, 4)); - let mut data: i32 = return_on_pagefault!(safe_read32s(addr)); + let data: i32 = return_on_pagefault!(safe_read32s(addr)); cmp32(*reg32s.offset(EAX as isize), data); if getzf() { safe_write32(addr, read_reg32(r)).unwrap(); @@ -3458,109 +3441,107 @@ pub unsafe fn instr32_0FB1_mem(mut addr: i32, mut r: i32) { }; } #[no_mangle] -pub unsafe fn instr16_0FB2_reg(mut unused: i32, mut unused2: i32) { trigger_ud(); } +pub unsafe fn instr16_0FB2_reg(unused: i32, unused2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_0FB2_mem(mut addr: i32, mut r: i32) { lss16(addr, get_reg16_index(r), SS); } +pub unsafe fn instr16_0FB2_mem(addr: i32, r: i32) { lss16(addr, get_reg16_index(r), SS); } #[no_mangle] -pub unsafe fn instr32_0FB2_reg(mut unused: i32, mut unused2: i32) { trigger_ud(); } +pub unsafe fn instr32_0FB2_reg(unused: i32, unused2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr32_0FB2_mem(mut addr: i32, mut r: i32) { lss32(addr, r, SS); } +pub unsafe fn instr32_0FB2_mem(addr: i32, r: i32) { lss32(addr, r, SS); } #[no_mangle] -pub unsafe fn instr16_0FB3_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr16_0FB3_reg(r1: i32, r2: i32) { write_reg16(r1, btr_reg(read_reg16(r1), read_reg16(r2) & 15)); } #[no_mangle] -pub unsafe fn instr16_0FB3_mem(mut addr: i32, mut r: i32) { - btr_mem(addr, read_reg16(r) << 16 >> 16); -} +pub unsafe fn instr16_0FB3_mem(addr: i32, r: i32) { btr_mem(addr, read_reg16(r) << 16 >> 16); } #[no_mangle] -pub unsafe fn instr32_0FB3_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr32_0FB3_reg(r1: i32, r2: i32) { write_reg32(r1, btr_reg(read_reg32(r1), read_reg32(r2) & 31)); } #[no_mangle] -pub unsafe fn instr32_0FB3_mem(mut addr: i32, mut r: i32) { btr_mem(addr, read_reg32(r)); } +pub unsafe fn instr32_0FB3_mem(addr: i32, r: i32) { btr_mem(addr, read_reg32(r)); } #[no_mangle] -pub unsafe fn instr16_0FB4_reg(mut unused: i32, mut unused2: i32) { trigger_ud(); } +pub unsafe fn instr16_0FB4_reg(unused: i32, unused2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_0FB4_mem(mut addr: i32, mut r: i32) { lss16(addr, get_reg16_index(r), FS); } +pub unsafe fn instr16_0FB4_mem(addr: i32, r: i32) { lss16(addr, get_reg16_index(r), FS); } #[no_mangle] -pub unsafe fn instr32_0FB4_reg(mut unused: i32, mut unused2: i32) { trigger_ud(); } +pub unsafe fn instr32_0FB4_reg(unused: i32, unused2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr32_0FB4_mem(mut addr: i32, mut r: i32) { lss32(addr, r, FS); } +pub unsafe fn instr32_0FB4_mem(addr: i32, r: i32) { lss32(addr, r, FS); } #[no_mangle] -pub unsafe fn instr16_0FB5_reg(mut unused: i32, mut unused2: i32) { trigger_ud(); } +pub unsafe fn instr16_0FB5_reg(unused: i32, unused2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_0FB5_mem(mut addr: i32, mut r: i32) { lss16(addr, get_reg16_index(r), GS); } +pub unsafe fn instr16_0FB5_mem(addr: i32, r: i32) { lss16(addr, get_reg16_index(r), GS); } #[no_mangle] -pub unsafe fn instr32_0FB5_reg(mut unused: i32, mut unused2: i32) { trigger_ud(); } +pub unsafe fn instr32_0FB5_reg(unused: i32, unused2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr32_0FB5_mem(mut addr: i32, mut r: i32) { lss32(addr, r, GS); } +pub unsafe fn instr32_0FB5_mem(addr: i32, r: i32) { lss32(addr, r, GS); } #[no_mangle] -pub unsafe fn instr16_0FB6_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); +pub unsafe fn instr16_0FB6_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg16(r, ____0); } #[no_mangle] -pub unsafe fn instr16_0FB6_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr16_0FB6_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); write_reg16(r, ____0); } #[no_mangle] -pub unsafe fn instr32_0FB6_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); +pub unsafe fn instr32_0FB6_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg32(r, ____0); } #[no_mangle] -pub unsafe fn instr32_0FB6_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr32_0FB6_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); write_reg32(r, ____0); } #[no_mangle] -pub unsafe fn instr16_0FB7_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0FB7_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, ____0); } #[no_mangle] -pub unsafe fn instr16_0FB7_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0FB7_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r, ____0); } #[no_mangle] -pub unsafe fn instr32_0FB7_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr32_0FB7_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg32(r, ____0); } #[no_mangle] -pub unsafe fn instr32_0FB7_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr32_0FB7_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg32(r, ____0); } #[no_mangle] -pub unsafe fn instr16_0FB8_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } +pub unsafe fn instr16_0FB8_reg(r1: i32, r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_0FB8_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr16_0FB8_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_F30FB8_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_F30FB8_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, popcnt(____0)); } #[no_mangle] -pub unsafe fn instr16_F30FB8_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_F30FB8_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r, popcnt(____0)); } #[no_mangle] -pub unsafe fn instr32_0FB8_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } +pub unsafe fn instr32_0FB8_reg(r1: i32, r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr32_0FB8_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr32_0FB8_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr32_F30FB8_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_F30FB8_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, popcnt(____0)); } #[no_mangle] -pub unsafe fn instr32_F30FB8_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_F30FB8_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r, popcnt(____0)); } #[no_mangle] @@ -3569,237 +3550,233 @@ pub unsafe fn instr_0FB9() { trigger_ud(); } #[no_mangle] -pub unsafe fn instr16_0FBA_4_reg(mut r: i32, mut imm: i32) { bt_reg(read_reg16(r), imm & 15); } +pub unsafe fn instr16_0FBA_4_reg(r: i32, imm: i32) { bt_reg(read_reg16(r), imm & 15); } #[no_mangle] -pub unsafe fn instr16_0FBA_4_mem(mut addr: i32, mut imm: i32) { bt_mem(addr, imm & 15); } +pub unsafe fn instr16_0FBA_4_mem(addr: i32, imm: i32) { bt_mem(addr, imm & 15); } #[no_mangle] -pub unsafe fn instr16_0FBA_5_reg(mut r: i32, mut imm: i32) { +pub unsafe fn instr16_0FBA_5_reg(r: i32, imm: i32) { write_reg16(r, bts_reg(read_reg16(r), imm & 15)); } #[no_mangle] -pub unsafe fn instr16_0FBA_5_mem(mut addr: i32, mut imm: i32) { bts_mem(addr, imm & 15); } +pub unsafe fn instr16_0FBA_5_mem(addr: i32, imm: i32) { bts_mem(addr, imm & 15); } #[no_mangle] -pub unsafe fn instr16_0FBA_6_reg(mut r: i32, mut imm: i32) { +pub unsafe fn instr16_0FBA_6_reg(r: i32, imm: i32) { write_reg16(r, btr_reg(read_reg16(r), imm & 15)); } #[no_mangle] -pub unsafe fn instr16_0FBA_6_mem(mut addr: i32, mut imm: i32) { btr_mem(addr, imm & 15); } +pub unsafe fn instr16_0FBA_6_mem(addr: i32, imm: i32) { btr_mem(addr, imm & 15); } #[no_mangle] -pub unsafe fn instr16_0FBA_7_reg(mut r: i32, mut imm: i32) { +pub unsafe fn instr16_0FBA_7_reg(r: i32, imm: i32) { write_reg16(r, btc_reg(read_reg16(r), imm & 15)); } #[no_mangle] -pub unsafe fn instr16_0FBA_7_mem(mut addr: i32, mut imm: i32) { btc_mem(addr, imm & 15); } +pub unsafe fn instr16_0FBA_7_mem(addr: i32, imm: i32) { btc_mem(addr, imm & 15); } #[no_mangle] -pub unsafe fn instr32_0FBA_4_reg(mut r: i32, mut imm: i32) { bt_reg(read_reg32(r), imm & 31); } +pub unsafe fn instr32_0FBA_4_reg(r: i32, imm: i32) { bt_reg(read_reg32(r), imm & 31); } #[no_mangle] -pub unsafe fn instr32_0FBA_4_mem(mut addr: i32, mut imm: i32) { bt_mem(addr, imm & 31); } +pub unsafe fn instr32_0FBA_4_mem(addr: i32, imm: i32) { bt_mem(addr, imm & 31); } #[no_mangle] -pub unsafe fn instr32_0FBA_5_reg(mut r: i32, mut imm: i32) { +pub unsafe fn instr32_0FBA_5_reg(r: i32, imm: i32) { write_reg32(r, bts_reg(read_reg32(r), imm & 31)); } #[no_mangle] -pub unsafe fn instr32_0FBA_5_mem(mut addr: i32, mut imm: i32) { bts_mem(addr, imm & 31); } +pub unsafe fn instr32_0FBA_5_mem(addr: i32, imm: i32) { bts_mem(addr, imm & 31); } #[no_mangle] -pub unsafe fn instr32_0FBA_6_reg(mut r: i32, mut imm: i32) { +pub unsafe fn instr32_0FBA_6_reg(r: i32, imm: i32) { write_reg32(r, btr_reg(read_reg32(r), imm & 31)); } #[no_mangle] -pub unsafe fn instr32_0FBA_6_mem(mut addr: i32, mut imm: i32) { btr_mem(addr, imm & 31); } +pub unsafe fn instr32_0FBA_6_mem(addr: i32, imm: i32) { btr_mem(addr, imm & 31); } #[no_mangle] -pub unsafe fn instr32_0FBA_7_reg(mut r: i32, mut imm: i32) { +pub unsafe fn instr32_0FBA_7_reg(r: i32, imm: i32) { write_reg32(r, btc_reg(read_reg32(r), imm & 31)); } #[no_mangle] -pub unsafe fn instr32_0FBA_7_mem(mut addr: i32, mut imm: i32) { btc_mem(addr, imm & 31); } +pub unsafe fn instr32_0FBA_7_mem(addr: i32, imm: i32) { btc_mem(addr, imm & 31); } #[no_mangle] -pub unsafe fn instr16_0FBB_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr16_0FBB_reg(r1: i32, r2: i32) { write_reg16(r1, btc_reg(read_reg16(r1), read_reg16(r2) & 15)); } #[no_mangle] -pub unsafe fn instr16_0FBB_mem(mut addr: i32, mut r: i32) { - btc_mem(addr, read_reg16(r) << 16 >> 16); -} +pub unsafe fn instr16_0FBB_mem(addr: i32, r: i32) { btc_mem(addr, read_reg16(r) << 16 >> 16); } #[no_mangle] -pub unsafe fn instr32_0FBB_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr32_0FBB_reg(r1: i32, r2: i32) { write_reg32(r1, btc_reg(read_reg32(r1), read_reg32(r2) & 31)); } #[no_mangle] -pub unsafe fn instr32_0FBB_mem(mut addr: i32, mut r: i32) { btc_mem(addr, read_reg32(r)); } +pub unsafe fn instr32_0FBB_mem(addr: i32, r: i32) { btc_mem(addr, read_reg32(r)); } #[no_mangle] -pub unsafe fn instr16_0FBC_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0FBC_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, bsf16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_0FBC_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0FBC_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r, bsf16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_0FBC_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_0FBC_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, bsf32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_0FBC_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0FBC_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r, bsf32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_0FBD_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0FBD_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, bsr16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_0FBD_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0FBD_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r, bsr16(read_reg16(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_0FBD_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read32s(addr)); +pub unsafe fn instr32_0FBD_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read32s(addr)); write_reg32(r, bsr32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr32_0FBD_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0FBD_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r, bsr32(read_reg32(r), ____0)); } #[no_mangle] -pub unsafe fn instr16_0FBE_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); +pub unsafe fn instr16_0FBE_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg16(r, ____0 << 24 >> 24); } #[no_mangle] -pub unsafe fn instr16_0FBE_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr16_0FBE_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); write_reg16(r, ____0 << 24 >> 24); } #[no_mangle] -pub unsafe fn instr32_0FBE_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read8(addr)); +pub unsafe fn instr32_0FBE_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read8(addr)); write_reg32(r, ____0 << 24 >> 24); } #[no_mangle] -pub unsafe fn instr32_0FBE_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr32_0FBE_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); write_reg32(r, ____0 << 24 >> 24); } #[no_mangle] -pub unsafe fn instr16_0FBF_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr16_0FBF_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, ____0 << 16 >> 16); } #[no_mangle] -pub unsafe fn instr16_0FBF_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0FBF_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r, ____0 << 16 >> 16); } #[no_mangle] -pub unsafe fn instr32_0FBF_mem(mut addr: i32, mut r: i32) { - let mut ____0: i32 = return_on_pagefault!(safe_read16(addr)); +pub unsafe fn instr32_0FBF_mem(addr: i32, r: i32) { + let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg32(r, ____0 << 16 >> 16); } #[no_mangle] -pub unsafe fn instr32_0FBF_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr32_0FBF_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg32(r, ____0 << 16 >> 16); } #[no_mangle] -pub unsafe fn instr_0FC0_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FC0_mem(addr: i32, r: i32) { SAFE_READ_WRITE8!(___, addr, xadd8(___, get_reg8_index(r))); } #[no_mangle] -pub unsafe fn instr_0FC0_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg8(r1); +pub unsafe fn instr_0FC0_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg8(r1); write_reg8(r1, xadd8(____0, get_reg8_index(r))); } #[no_mangle] -pub unsafe fn instr16_0FC1_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr16_0FC1_mem(addr: i32, r: i32) { SAFE_READ_WRITE16!(___, addr, xadd16(___, get_reg16_index(r))); } #[no_mangle] -pub unsafe fn instr16_0FC1_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg16(r1); +pub unsafe fn instr16_0FC1_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg16(r1); write_reg16(r1, xadd16(____0, get_reg16_index(r))); } #[no_mangle] -pub unsafe fn instr32_0FC1_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr32_0FC1_mem(addr: i32, r: i32) { SAFE_READ_WRITE32!(___, addr, xadd32(___, r)); } #[no_mangle] -pub unsafe fn instr32_0FC1_reg(mut r1: i32, mut r: i32) { - let mut ____0: i32 = read_reg32(r1); +pub unsafe fn instr32_0FC1_reg(r1: i32, r: i32) { + let ____0: i32 = read_reg32(r1); write_reg32(r1, xadd32(____0, r)); } #[no_mangle] -pub unsafe fn instr_0FC3_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } +pub unsafe fn instr_0FC3_reg(r1: i32, r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FC3_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FC3_mem(addr: i32, r: i32) { // movnti return_on_pagefault!(safe_write32(addr, read_reg32(r))); } #[no_mangle] -pub unsafe fn instr_0FC4(mut source: i32, mut r: i32, mut imm8: i32) { +pub unsafe fn instr_0FC4(source: i32, r: i32, imm8: i32) { // pinsrw mm, r32/m16, imm8 let mut destination: reg64 = read_mmx64s(r); - let mut index: u32 = (imm8 & 3) as u32; + let index: u32 = (imm8 & 3) as u32; destination.u16_0[index as usize] = (source & 65535) as u16; write_mmx_reg64(r, destination); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FC4_reg(mut r1: i32, mut r2: i32, mut imm: i32) { - instr_0FC4(read_reg32(r1), r2, imm); -} +pub unsafe fn instr_0FC4_reg(r1: i32, r2: i32, imm: i32) { instr_0FC4(read_reg32(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_0FC4_mem(mut addr: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr_0FC4_mem(addr: i32, r: i32, imm: i32) { instr_0FC4(return_on_pagefault!(safe_read16(addr)), r, imm); } #[no_mangle] -pub unsafe fn instr_660FC4(mut source: i32, mut r: i32, mut imm8: i32) { +pub unsafe fn instr_660FC4(source: i32, r: i32, imm8: i32) { // pinsrw xmm, r32/m16, imm8 let mut destination: reg128 = read_xmm128s(r); - let mut index: u32 = (imm8 & 7) as u32; + let index: u32 = (imm8 & 7) as u32; destination.u16_0[index as usize] = (source & 65535) as u16; write_xmm_reg128(r, destination); } #[no_mangle] -pub unsafe fn instr_660FC4_reg(mut r1: i32, mut r2: i32, mut imm: i32) { +pub unsafe fn instr_660FC4_reg(r1: i32, r2: i32, imm: i32) { instr_660FC4(read_reg32(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_660FC4_mem(mut addr: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr_660FC4_mem(addr: i32, r: i32, imm: i32) { instr_660FC4(return_on_pagefault!(safe_read16(addr)), r, imm); } #[no_mangle] -pub unsafe fn instr_0FC5_mem(mut addr: i32, mut r: i32, mut imm8: i32) { trigger_ud(); } +pub unsafe fn instr_0FC5_mem(addr: i32, r: i32, imm8: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i32) { +pub unsafe fn instr_0FC5_reg(r1: i32, r2: i32, imm8: i32) { // pextrw r32, mm, imm8 - let mut data: reg64 = read_mmx64s(r1); - let mut index: u32 = (imm8 & 3) as u32; - let mut result: u32 = data.u16_0[index as usize] as u32; + let data: reg64 = read_mmx64s(r1); + let index: u32 = (imm8 & 3) as u32; + let result: u32 = data.u16_0[index as usize] as u32; write_reg32(r2, result as i32); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_660FC5_mem(mut addr: i32, mut r: i32, mut imm8: i32) { trigger_ud(); } +pub unsafe fn instr_660FC5_mem(addr: i32, r: i32, imm8: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660FC5_reg(mut r1: i32, mut r2: i32, mut imm8: i32) { +pub unsafe fn instr_660FC5_reg(r1: i32, r2: i32, imm8: i32) { // pextrw r32, xmm, imm8 - let mut data: reg128 = read_xmm128s(r1); - let mut index: u32 = (imm8 & 7) as u32; - let mut result: u32 = data.u16_0[index as usize] as u32; + let data: reg128 = read_xmm128s(r1); + let index: u32 = (imm8 & 7) as u32; + let result: u32 = data.u16_0[index as usize] as u32; write_reg32(r2, result as i32); } #[no_mangle] -pub unsafe fn instr_0FC6(mut source: reg128, mut r: i32, mut imm8: i32) { +pub unsafe fn instr_0FC6(source: reg128, r: i32, imm8: i32) { // shufps xmm, xmm/mem128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); write_xmm128( r, destination.u32_0[(imm8 & 3) as usize] as i32, @@ -3809,19 +3786,17 @@ pub unsafe fn instr_0FC6(mut source: reg128, mut r: i32, mut imm8: i32) { ); } #[no_mangle] -pub unsafe fn instr_0FC6_reg(mut r1: i32, mut r2: i32, mut imm: i32) { - instr_0FC6(read_xmm128s(r1), r2, imm); -} +pub unsafe fn instr_0FC6_reg(r1: i32, r2: i32, imm: i32) { instr_0FC6(read_xmm128s(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_0FC6_mem(mut addr: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr_0FC6_mem(addr: i32, r: i32, imm: i32) { instr_0FC6(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] -pub unsafe fn instr_660FC6(mut source: reg128, mut r: i32, mut imm8: i32) { +pub unsafe fn instr_660FC6(source: reg128, r: i32, imm8: i32) { // shufpd xmm, xmm/mem128 - let mut destination: reg128 = read_xmm128s(r); - let mut result: reg128 = reg128 { + let destination: reg128 = read_xmm128s(r); + let result: reg128 = reg128 { i64_0: [ destination.i64_0[imm8 as usize & 1], source.i64_0[imm8 as usize >> 1 & 1], @@ -3830,22 +3805,22 @@ pub unsafe fn instr_660FC6(mut source: reg128, mut r: i32, mut imm8: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FC6_reg(mut r1: i32, mut r2: i32, mut imm: i32) { +pub unsafe fn instr_660FC6_reg(r1: i32, r2: i32, imm: i32) { instr_660FC6(read_xmm128s(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_660FC6_mem(mut addr: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr_660FC6_mem(addr: i32, r: i32, imm: i32) { instr_660FC6(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] -pub unsafe fn instr_0FC7_1_reg(mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0FC7_1_reg(r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FC7_1_mem(mut addr: i32) { +pub unsafe fn instr_0FC7_1_mem(addr: i32) { // cmpxchg8b return_on_pagefault!(writable_or_pagefault(addr, 8)); - let mut m64_low: i32 = return_on_pagefault!(safe_read32s(addr)); - let mut m64_high: i32 = return_on_pagefault!(safe_read32s(addr + 4)); + let m64_low: i32 = return_on_pagefault!(safe_read32s(addr)); + let m64_high: i32 = return_on_pagefault!(safe_read32s(addr + 4)); if *reg32s.offset(EAX as isize) == m64_low && *reg32s.offset(EDX as isize) == m64_high { *flags |= FLAG_ZERO; safe_write32(addr, *reg32s.offset(EBX as isize)).unwrap(); @@ -3861,9 +3836,9 @@ pub unsafe fn instr_0FC7_1_mem(mut addr: i32) { *flags_changed &= !FLAG_ZERO; } #[no_mangle] -pub unsafe fn instr_0FC7_6_reg(mut r: i32) { +pub unsafe fn instr_0FC7_6_reg(r: i32) { // rdrand - let mut has_rand: i32 = has_rand_int() as i32; + let has_rand: i32 = has_rand_int() as i32; let mut rand: i32 = 0; if 0 != has_rand { rand = get_rand_int() @@ -3874,7 +3849,7 @@ pub unsafe fn instr_0FC7_6_reg(mut r: i32) { *flags_changed = 0; } #[no_mangle] -pub unsafe fn instr_0FC7_6_mem(mut addr: i32) { trigger_ud(); } +pub unsafe fn instr_0FC7_6_mem(addr: i32) { trigger_ud(); } #[no_mangle] pub unsafe fn instr_0FC8() { bswap(EAX); } #[no_mangle] @@ -3894,75 +3869,75 @@ pub unsafe fn instr_0FCF() { bswap(EDI); } #[no_mangle] pub unsafe fn instr_0FD0() { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_0FD1(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FD1(source: reg64, r: i32) { // psrlw mm, mm/m64 psrlw_r64(r, source.u64_0[0]); } #[no_mangle] -pub unsafe fn instr_0FD1_reg(mut r1: i32, mut r2: i32) { instr_0FD1(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FD1_reg(r1: i32, r2: i32) { instr_0FD1(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FD1_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FD1_mem(addr: i32, r: i32) { instr_0FD1(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FD1(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FD1(source: reg128, r: i32) { // psrlw xmm, xmm/m128 // XXX: Aligned access or #gp psrlw_r128(r, source.u64_0[0]); } #[no_mangle] -pub unsafe fn instr_660FD1_reg(mut r1: i32, mut r2: i32) { instr_660FD1(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FD1_reg(r1: i32, r2: i32) { instr_660FD1(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FD1_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FD1_mem(addr: i32, r: i32) { instr_660FD1(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FD2(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FD2(source: reg64, r: i32) { // psrld mm, mm/m64 psrld_r64(r, source.u64_0[0]); } #[no_mangle] -pub unsafe fn instr_0FD2_reg(mut r1: i32, mut r2: i32) { instr_0FD2(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FD2_reg(r1: i32, r2: i32) { instr_0FD2(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FD2_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FD2_mem(addr: i32, r: i32) { instr_0FD2(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FD2(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FD2(source: reg128, r: i32) { // psrld xmm, xmm/m128 // XXX: Aligned access or #gp psrld_r128(r, source.u64_0[0]); } #[no_mangle] -pub unsafe fn instr_660FD2_reg(mut r1: i32, mut r2: i32) { instr_660FD2(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FD2_reg(r1: i32, r2: i32) { instr_660FD2(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FD2_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FD2_mem(addr: i32, r: i32) { instr_660FD2(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FD3(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FD3(source: reg64, r: i32) { // psrlq mm, mm/m64 psrlq_r64(r, source.u64_0[0]); } #[no_mangle] -pub unsafe fn instr_0FD3_reg(mut r1: i32, mut r2: i32) { instr_0FD3(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FD3_reg(r1: i32, r2: i32) { instr_0FD3(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FD3_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FD3_mem(addr: i32, r: i32) { instr_0FD3(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FD3(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FD3(source: reg128, r: i32) { // psrlq xmm, mm/m64 psrlq_r128(r, source.u64_0[0]); } #[no_mangle] -pub unsafe fn instr_660FD3_reg(mut r1: i32, mut r2: i32) { instr_660FD3(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FD3_reg(r1: i32, r2: i32) { instr_660FD3(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FD3_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FD3_mem(addr: i32, r: i32) { instr_660FD3(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FD4(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FD4(source: reg64, r: i32) { // paddq mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); destination.u64_0[0] = @@ -3971,13 +3946,13 @@ pub unsafe fn instr_0FD4(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FD4_reg(mut r1: i32, mut r2: i32) { instr_0FD4(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FD4_reg(r1: i32, r2: i32) { instr_0FD4(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FD4_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FD4_mem(addr: i32, r: i32) { instr_0FD4(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FD4(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FD4(source: reg128, r: i32) { // paddq xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -3988,35 +3963,35 @@ pub unsafe fn instr_660FD4(mut source: reg128, mut r: i32) { write_xmm_reg128(r, destination); } #[no_mangle] -pub unsafe fn instr_660FD4_reg(mut r1: i32, mut r2: i32) { instr_660FD4(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FD4_reg(r1: i32, r2: i32) { instr_660FD4(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FD4_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FD4_mem(addr: i32, r: i32) { instr_660FD4(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FD5(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FD5(source: reg64, r: i32) { // pmullw mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); - let mut word0: i32 = destination.u16_0[0] as i32 * source.u16_0[0] as i32 & 65535; - let mut word1: i32 = destination.u16_0[1] as i32 * source.u16_0[1] as i32 & 65535; - let mut word2: i32 = destination.u16_0[2] as i32 * source.u16_0[2] as i32 & 65535; - let mut word3: i32 = destination.u16_0[3] as i32 * source.u16_0[3] as i32 & 65535; - let mut low: i32 = word0 | word1 << 16; - let mut high: i32 = word2 | word3 << 16; + let destination: reg64 = read_mmx64s(r); + let word0: i32 = destination.u16_0[0] as i32 * source.u16_0[0] as i32 & 65535; + let word1: i32 = destination.u16_0[1] as i32 * source.u16_0[1] as i32 & 65535; + let word2: i32 = destination.u16_0[2] as i32 * source.u16_0[2] as i32 & 65535; + let word3: i32 = destination.u16_0[3] as i32 * source.u16_0[3] as i32 & 65535; + let low: i32 = word0 | word1 << 16; + let high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FD5_reg(mut r1: i32, mut r2: i32) { instr_0FD5(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FD5_reg(r1: i32, r2: i32) { instr_0FD5(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FD5_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FD5_mem(addr: i32, r: i32) { instr_0FD5(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FD5(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FD5(source: reg128, r: i32) { // pmullw xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); write_xmm128( r, source.u16_0[0] as i32 * destination.u16_0[0] as i32 & 65535 @@ -4030,51 +4005,51 @@ pub unsafe fn instr_660FD5(mut source: reg128, mut r: i32) { ); } #[no_mangle] -pub unsafe fn instr_660FD5_reg(mut r1: i32, mut r2: i32) { instr_660FD5(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FD5_reg(r1: i32, r2: i32) { instr_660FD5(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FD5_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FD5_mem(addr: i32, r: i32) { instr_660FD5(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FD6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0FD6_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FD6_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } +pub unsafe fn instr_0FD6_reg(r1: i32, r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660FD6_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FD6_mem(addr: i32, r: i32) { // movq xmm/m64, xmm movl_r128_m64(addr, r); } #[no_mangle] -pub unsafe fn instr_660FD6_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_660FD6_reg(r1: i32, r2: i32) { // movq xmm/m64, xmm - let mut data: reg64 = read_xmm64s(r2); + let data: reg64 = read_xmm64s(r2); write_xmm128(r1, data.u32_0[0] as i32, data.u32_0[1] as i32, 0, 0); } #[no_mangle] -pub unsafe fn instr_F20FD6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_F20FD6_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_F20FD6_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_F20FD6_reg(r1: i32, r2: i32) { // movdq2q mm, xmm - let mut source: reg128 = read_xmm128s(r1); + let source: reg128 = read_xmm128s(r1); write_mmx64(r2, source.u32_0[0] as i32, source.u32_0[1] as i32); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_F30FD6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_F30FD6_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_F30FD6_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_F30FD6_reg(r1: i32, r2: i32) { // movq2dq xmm, mm - let mut source: reg64 = read_mmx64s(r1); + let source: reg64 = read_mmx64s(r1); write_xmm128(r2, source.u32_0[0] as i32, source.u32_0[1] as i32, 0, 0); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FD7_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0FD7_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FD7_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_0FD7_reg(r1: i32, r2: i32) { // pmovmskb r, mm - let mut x: reg64 = read_mmx64s(r1); - let mut result: u32 = (x.u8_0[0] as i32 >> 7 << 0 + let x: reg64 = read_mmx64s(r1); + let result: u32 = (x.u8_0[0] as i32 >> 7 << 0 | x.u8_0[1] as i32 >> 7 << 1 | x.u8_0[2] as i32 >> 7 << 2 | x.u8_0[3] as i32 >> 7 << 3 @@ -4086,12 +4061,12 @@ pub unsafe fn instr_0FD7_reg(mut r1: i32, mut r2: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_660FD7_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_660FD7_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660FD7_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_660FD7_reg(r1: i32, r2: i32) { // pmovmskb reg, xmm - let mut x: reg128 = read_xmm128s(r1); - let mut result: i32 = x.u8_0[0] as i32 >> 7 << 0 + let x: reg128 = read_xmm128s(r1); + let result: i32 = x.u8_0[0] as i32 >> 7 << 0 | x.u8_0[1] as i32 >> 7 << 1 | x.u8_0[2] as i32 >> 7 << 2 | x.u8_0[3] as i32 >> 7 << 3 @@ -4110,9 +4085,9 @@ pub unsafe fn instr_660FD7_reg(mut r1: i32, mut r2: i32) { write_reg32(r2, result); } #[no_mangle] -pub unsafe fn instr_0FD8(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FD8(source: reg64, r: i32) { // psubusb mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; @@ -4125,15 +4100,15 @@ pub unsafe fn instr_0FD8(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FD8_reg(mut r1: i32, mut r2: i32) { instr_0FD8(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FD8_reg(r1: i32, r2: i32) { instr_0FD8(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FD8_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FD8_mem(addr: i32, r: i32) { instr_0FD8(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FD8(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FD8(source: reg128, r: i32) { // psubusb xmm, xmm/m128 - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; for i in 0..16 { result.u8_0[i as usize] = @@ -4143,34 +4118,34 @@ pub unsafe fn instr_660FD8(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FD8_reg(mut r1: i32, mut r2: i32) { instr_660FD8(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FD8_reg(r1: i32, r2: i32) { instr_660FD8(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FD8_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FD8_mem(addr: i32, r: i32) { instr_660FD8(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FD9(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FD9(source: reg64, r: i32) { // psubusw mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); - let mut word0: i32 = saturate_uw((destination.u16_0[0] as i32 - source.u16_0[0] as i32) as u32); - let mut word1: i32 = saturate_uw((destination.u16_0[1] as i32 - source.u16_0[1] as i32) as u32); - let mut word2: i32 = saturate_uw((destination.u16_0[2] as i32 - source.u16_0[2] as i32) as u32); - let mut word3: i32 = saturate_uw((destination.u16_0[3] as i32 - source.u16_0[3] as i32) as u32); - let mut low: i32 = word0 | word1 << 16; - let mut high: i32 = word2 | word3 << 16; + let destination: reg64 = read_mmx64s(r); + let word0: i32 = saturate_uw((destination.u16_0[0] as i32 - source.u16_0[0] as i32) as u32); + let word1: i32 = saturate_uw((destination.u16_0[1] as i32 - source.u16_0[1] as i32) as u32); + let word2: i32 = saturate_uw((destination.u16_0[2] as i32 - source.u16_0[2] as i32) as u32); + let word3: i32 = saturate_uw((destination.u16_0[3] as i32 - source.u16_0[3] as i32) as u32); + let low: i32 = word0 | word1 << 16; + let high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FD9_reg(mut r1: i32, mut r2: i32) { instr_0FD9(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FD9_reg(r1: i32, r2: i32) { instr_0FD9(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FD9_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FD9_mem(addr: i32, r: i32) { instr_0FD9(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FD9(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FD9(source: reg128, r: i32) { // psubusw xmm, xmm/m128 - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; for i in 0..8 { result.u16_0[i as usize] = saturate_uw( @@ -4180,15 +4155,15 @@ pub unsafe fn instr_660FD9(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FD9_reg(mut r1: i32, mut r2: i32) { instr_660FD9(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FD9_reg(r1: i32, r2: i32) { instr_660FD9(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FD9_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FD9_mem(addr: i32, r: i32) { instr_660FD9(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FDA(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FDA(source: reg64, r: i32) { // pminub mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; for i in 0..8 { result.u8_0[i as usize] = @@ -4203,16 +4178,16 @@ pub unsafe fn instr_0FDA(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FDA_reg(mut r1: i32, mut r2: i32) { instr_0FDA(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FDA_reg(r1: i32, r2: i32) { instr_0FDA(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FDA_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FDA_mem(addr: i32, r: i32) { instr_0FDA(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FDA(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FDA(source: reg128, r: i32) { // pminub xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; for i in 0..16 { result.u8_0[i as usize] = @@ -4226,15 +4201,15 @@ pub unsafe fn instr_660FDA(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FDA_reg(mut r1: i32, mut r2: i32) { instr_660FDA(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FDA_reg(r1: i32, r2: i32) { instr_660FDA(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FDA_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FDA_mem(addr: i32, r: i32) { instr_660FDA(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FDB(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FDB(source: reg64, r: i32) { // pand mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; @@ -4243,27 +4218,27 @@ pub unsafe fn instr_0FDB(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FDB_reg(mut r1: i32, mut r2: i32) { instr_0FDB(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FDB_reg(r1: i32, r2: i32) { instr_0FDB(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FDB_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FDB_mem(addr: i32, r: i32) { instr_0FDB(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FDB(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FDB(source: reg128, r: i32) { // pand xmm, xmm/m128 // XXX: Aligned access or #gp pand_r128(source, r); } #[no_mangle] -pub unsafe fn instr_660FDB_reg(mut r1: i32, mut r2: i32) { instr_660FDB(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FDB_reg(r1: i32, r2: i32) { instr_660FDB(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FDB_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FDB_mem(addr: i32, r: i32) { instr_660FDB(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FDC(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FDC(source: reg64, r: i32) { // paddusb mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; @@ -4276,16 +4251,16 @@ pub unsafe fn instr_0FDC(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FDC_reg(mut r1: i32, mut r2: i32) { instr_0FDC(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FDC_reg(r1: i32, r2: i32) { instr_0FDC(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FDC_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FDC_mem(addr: i32, r: i32) { instr_0FDC(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FDC(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FDC(source: reg128, r: i32) { // paddusb xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; for i in 0..16 { result.u8_0[i as usize] = saturate_ud_to_ub( @@ -4295,35 +4270,35 @@ pub unsafe fn instr_660FDC(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FDC_reg(mut r1: i32, mut r2: i32) { instr_660FDC(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FDC_reg(r1: i32, r2: i32) { instr_660FDC(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FDC_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FDC_mem(addr: i32, r: i32) { instr_660FDC(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FDD(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FDD(source: reg64, r: i32) { // paddusw mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); - let mut word0: i32 = saturate_uw((destination.u16_0[0] as i32 + source.u16_0[0] as i32) as u32); - let mut word1: i32 = saturate_uw((destination.u16_0[1] as i32 + source.u16_0[1] as i32) as u32); - let mut word2: i32 = saturate_uw((destination.u16_0[2] as i32 + source.u16_0[2] as i32) as u32); - let mut word3: i32 = saturate_uw((destination.u16_0[3] as i32 + source.u16_0[3] as i32) as u32); - let mut low: i32 = word0 | word1 << 16; - let mut high: i32 = word2 | word3 << 16; + let destination: reg64 = read_mmx64s(r); + let word0: i32 = saturate_uw((destination.u16_0[0] as i32 + source.u16_0[0] as i32) as u32); + let word1: i32 = saturate_uw((destination.u16_0[1] as i32 + source.u16_0[1] as i32) as u32); + let word2: i32 = saturate_uw((destination.u16_0[2] as i32 + source.u16_0[2] as i32) as u32); + let word3: i32 = saturate_uw((destination.u16_0[3] as i32 + source.u16_0[3] as i32) as u32); + let low: i32 = word0 | word1 << 16; + let high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FDD_reg(mut r1: i32, mut r2: i32) { instr_0FDD(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FDD_reg(r1: i32, r2: i32) { instr_0FDD(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FDD_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FDD_mem(addr: i32, r: i32) { instr_0FDD(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FDD(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FDD(source: reg128, r: i32) { // paddusw xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); write_xmm128( r, saturate_uw((source.u16_0[0] as i32 + destination.u16_0[0] as i32) as u32) @@ -4337,15 +4312,15 @@ pub unsafe fn instr_660FDD(mut source: reg128, mut r: i32) { ); } #[no_mangle] -pub unsafe fn instr_660FDD_reg(mut r1: i32, mut r2: i32) { instr_660FDD(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FDD_reg(r1: i32, r2: i32) { instr_660FDD(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FDD_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FDD_mem(addr: i32, r: i32) { instr_660FDD(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FDE(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FDE(source: reg64, r: i32) { // pmaxub mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; for i in 0..8 { result.u8_0[i as usize] = @@ -4360,16 +4335,16 @@ pub unsafe fn instr_0FDE(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FDE_reg(mut r1: i32, mut r2: i32) { instr_0FDE(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FDE_reg(r1: i32, r2: i32) { instr_0FDE(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FDE_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FDE_mem(addr: i32, r: i32) { instr_0FDE(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FDE(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FDE(source: reg128, r: i32) { // pmaxub xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; for i in 0..16 { result.u8_0[i as usize] = @@ -4383,15 +4358,15 @@ pub unsafe fn instr_660FDE(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FDE_reg(mut r1: i32, mut r2: i32) { instr_660FDE(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FDE_reg(r1: i32, r2: i32) { instr_660FDE(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FDE_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FDE_mem(addr: i32, r: i32) { instr_660FDE(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FDF(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FDF(source: reg64, r: i32) { // pandn mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; @@ -4400,27 +4375,27 @@ pub unsafe fn instr_0FDF(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FDF_reg(mut r1: i32, mut r2: i32) { instr_0FDF(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FDF_reg(r1: i32, r2: i32) { instr_0FDF(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FDF_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FDF_mem(addr: i32, r: i32) { instr_0FDF(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FDF(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FDF(source: reg128, r: i32) { // pandn xmm, xmm/m128 // XXX: Aligned access or #gp pandn_r128(source, r); } #[no_mangle] -pub unsafe fn instr_660FDF_reg(mut r1: i32, mut r2: i32) { instr_660FDF(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FDF_reg(r1: i32, r2: i32) { instr_660FDF(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FDF_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FDF_mem(addr: i32, r: i32) { instr_660FDF(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FE0(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FE0(source: reg64, r: i32) { // pavgb mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; @@ -4432,16 +4407,16 @@ pub unsafe fn instr_0FE0(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FE0_reg(mut r1: i32, mut r2: i32) { instr_0FE0(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FE0_reg(r1: i32, r2: i32) { instr_0FE0(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FE0_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FE0_mem(addr: i32, r: i32) { instr_0FE0(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FE0(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FE0(source: reg128, r: i32) { // pavgb xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; for i in 0..16 { result.u8_0[i as usize] = @@ -4450,59 +4425,59 @@ pub unsafe fn instr_660FE0(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FE0_reg(mut r1: i32, mut r2: i32) { instr_660FE0(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FE0_reg(r1: i32, r2: i32) { instr_660FE0(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FE0_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FE0_mem(addr: i32, r: i32) { instr_660FE0(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FE1(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FE1(source: reg64, r: i32) { // psraw mm, mm/m64 psraw_r64(r, source.u64_0[0]); } #[no_mangle] -pub unsafe fn instr_0FE1_reg(mut r1: i32, mut r2: i32) { instr_0FE1(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FE1_reg(r1: i32, r2: i32) { instr_0FE1(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FE1_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FE1_mem(addr: i32, r: i32) { instr_0FE1(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FE1(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FE1(source: reg128, r: i32) { // psraw xmm, xmm/m128 // XXX: Aligned access or #gp psraw_r128(r, source.u64_0[0]); } #[no_mangle] -pub unsafe fn instr_660FE1_reg(mut r1: i32, mut r2: i32) { instr_660FE1(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FE1_reg(r1: i32, r2: i32) { instr_660FE1(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FE1_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FE1_mem(addr: i32, r: i32) { instr_660FE1(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FE2(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FE2(source: reg64, r: i32) { // psrad mm, mm/m64 psrad_r64(r, source.u64_0[0]); } #[no_mangle] -pub unsafe fn instr_0FE2_reg(mut r1: i32, mut r2: i32) { instr_0FE2(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FE2_reg(r1: i32, r2: i32) { instr_0FE2(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FE2_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FE2_mem(addr: i32, r: i32) { instr_0FE2(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FE2(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FE2(source: reg128, r: i32) { // psrad xmm, xmm/m128 // XXX: Aligned access or #gp psrad_r128(r, source.u64_0[0]); } #[no_mangle] -pub unsafe fn instr_660FE2_reg(mut r1: i32, mut r2: i32) { instr_660FE2(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FE2_reg(r1: i32, r2: i32) { instr_660FE2(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FE2_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FE2_mem(addr: i32, r: i32) { instr_660FE2(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FE3(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FE3(source: reg64, r: i32) { // pavgw mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); destination.u16_0[0] = (destination.u16_0[0] as i32 + source.u16_0[0] as i32 + 1 >> 1) as u16; @@ -4513,13 +4488,13 @@ pub unsafe fn instr_0FE3(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FE3_reg(mut r1: i32, mut r2: i32) { instr_0FE3(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FE3_reg(r1: i32, r2: i32) { instr_0FE3(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FE3_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FE3_mem(addr: i32, r: i32) { instr_0FE3(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FE3(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FE3(source: reg128, r: i32) { // pavgw xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -4534,15 +4509,15 @@ pub unsafe fn instr_660FE3(mut source: reg128, mut r: i32) { write_xmm_reg128(r, destination); } #[no_mangle] -pub unsafe fn instr_660FE3_reg(mut r1: i32, mut r2: i32) { instr_660FE3(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FE3_reg(r1: i32, r2: i32) { instr_660FE3(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FE3_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FE3_mem(addr: i32, r: i32) { instr_660FE3(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FE4(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FE4(source: reg64, r: i32) { // pmulhuw mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); write_mmx64( r, ((source.u16_0[0] as i32 * destination.u16_0[0] as i32 >> 16 & 65535) as u32 @@ -4555,16 +4530,16 @@ pub unsafe fn instr_0FE4(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FE4_reg(mut r1: i32, mut r2: i32) { instr_0FE4(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FE4_reg(r1: i32, r2: i32) { instr_0FE4(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FE4_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FE4_mem(addr: i32, r: i32) { instr_0FE4(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FE4(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FE4(source: reg128, r: i32) { // pmulhuw xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); write_xmm128( r, ((source.u16_0[0] as i32 * destination.u16_0[0] as i32 >> 16 & 65535) as u32 @@ -4582,73 +4557,65 @@ pub unsafe fn instr_660FE4(mut source: reg128, mut r: i32) { ); } #[no_mangle] -pub unsafe fn instr_660FE4_reg(mut r1: i32, mut r2: i32) { instr_660FE4(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FE4_reg(r1: i32, r2: i32) { instr_660FE4(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FE4_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FE4_mem(addr: i32, r: i32) { instr_660FE4(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FE5(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FE5(source: reg64, r: i32) { // pmulhw mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); - let mut word0: u32 = - (destination.i16_0[0] as i32 * source.i16_0[0] as i32 >> 16 & 65535) as u32; - let mut word1: u32 = - (destination.i16_0[1] as i32 * source.i16_0[1] as i32 >> 16 & 65535) as u32; - let mut word2: u32 = - (destination.i16_0[2] as i32 * source.i16_0[2] as i32 >> 16 & 65535) as u32; - let mut word3: u32 = - (destination.i16_0[3] as i32 * source.i16_0[3] as i32 >> 16 & 65535) as u32; - let mut low: i32 = (word0 | word1 << 16) as i32; - let mut high: i32 = (word2 | word3 << 16) as i32; + let destination: reg64 = read_mmx64s(r); + let word0: u32 = (destination.i16_0[0] as i32 * source.i16_0[0] as i32 >> 16 & 65535) as u32; + let word1: u32 = (destination.i16_0[1] as i32 * source.i16_0[1] as i32 >> 16 & 65535) as u32; + let word2: u32 = (destination.i16_0[2] as i32 * source.i16_0[2] as i32 >> 16 & 65535) as u32; + let word3: u32 = (destination.i16_0[3] as i32 * source.i16_0[3] as i32 >> 16 & 65535) as u32; + let low: i32 = (word0 | word1 << 16) as i32; + let high: i32 = (word2 | word3 << 16) as i32; write_mmx64(r, low, high); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FE5_reg(mut r1: i32, mut r2: i32) { instr_0FE5(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FE5_reg(r1: i32, r2: i32) { instr_0FE5(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FE5_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FE5_mem(addr: i32, r: i32) { instr_0FE5(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FE5(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FE5(source: reg128, r: i32) { // pmulhw xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); - let mut dword0: i32 = ((destination.i16_0[0] as i32 * source.i16_0[0] as i32 >> 16 & 65535) - as u32 + let destination: reg128 = read_xmm128s(r); + let dword0: i32 = ((destination.i16_0[0] as i32 * source.i16_0[0] as i32 >> 16 & 65535) as u32 | (destination.i16_0[1] as i32 * source.i16_0[1] as i32) as u32 & 4294901760) as i32; - let mut dword1: i32 = ((destination.i16_0[2] as i32 * source.i16_0[2] as i32 >> 16 & 65535) - as u32 + let dword1: i32 = ((destination.i16_0[2] as i32 * source.i16_0[2] as i32 >> 16 & 65535) as u32 | (destination.i16_0[3] as i32 * source.i16_0[3] as i32) as u32 & 4294901760) as i32; - let mut dword2: i32 = ((destination.i16_0[4] as i32 * source.i16_0[4] as i32 >> 16 & 65535) - as u32 + let dword2: i32 = ((destination.i16_0[4] as i32 * source.i16_0[4] as i32 >> 16 & 65535) as u32 | (destination.i16_0[5] as i32 * source.i16_0[5] as i32) as u32 & 4294901760) as i32; - let mut dword3: i32 = ((destination.i16_0[6] as i32 * source.i16_0[6] as i32 >> 16 & 65535) - as u32 + let dword3: i32 = ((destination.i16_0[6] as i32 * source.i16_0[6] as i32 >> 16 & 65535) as u32 | (destination.i16_0[7] as i32 * source.i16_0[7] as i32) as u32 & 4294901760) as i32; write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn instr_660FE5_reg(mut r1: i32, mut r2: i32) { instr_660FE5(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FE5_reg(r1: i32, r2: i32) { instr_660FE5(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FE5_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FE5_mem(addr: i32, r: i32) { instr_660FE5(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FE6_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0FE6_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FE6_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } +pub unsafe fn instr_0FE6_reg(r1: i32, r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660FE6(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FE6(source: reg128, r: i32) { // cvttpd2dq xmm1, xmm2/m128 - let mut result = reg128 { + let result = reg128 { i32_0: [ sse_convert_f64_to_i32(source.f64_0[0].trunc()), sse_convert_f64_to_i32(source.f64_0[1].trunc()), @@ -4659,16 +4626,16 @@ pub unsafe fn instr_660FE6(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FE6_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FE6_mem(addr: i32, r: i32) { instr_660FE6(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FE6_reg(mut r1: i32, mut r2: i32) { instr_660FE6(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FE6_reg(r1: i32, r2: i32) { instr_660FE6(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20FE6(mut source: reg128, mut r: i32) { +pub unsafe fn instr_F20FE6(source: reg128, r: i32) { // cvtpd2dq xmm1, xmm2/m128 - let mut result = reg128 { + let result = reg128 { i32_0: [ // XXX: Precision exception sse_convert_f64_to_i32(source.f64_0[0].round()), @@ -4680,16 +4647,16 @@ pub unsafe fn instr_F20FE6(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_F20FE6_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F20FE6_mem(addr: i32, r: i32) { instr_F20FE6(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20FE6_reg(mut r1: i32, mut r2: i32) { instr_F20FE6(read_xmm128s(r1), r2); } +pub unsafe fn instr_F20FE6_reg(r1: i32, r2: i32) { instr_F20FE6(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30FE6(mut source: reg64, mut r: i32) { +pub unsafe fn instr_F30FE6(source: reg64, r: i32) { // cvtdq2pd xmm1, xmm2/m64 - let mut result: reg128 = reg128 { + let result: reg128 = reg128 { f64_0: [ // Note: Conversion never fails (i32 fits into f64) source.i32_0[0] as f64, @@ -4699,30 +4666,30 @@ pub unsafe fn instr_F30FE6(mut source: reg64, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_F30FE6_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F30FE6_mem(addr: i32, r: i32) { instr_F30FE6(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30FE6_reg(mut r1: i32, mut r2: i32) { instr_F30FE6(read_xmm64s(r1), r2); } +pub unsafe fn instr_F30FE6_reg(r1: i32, r2: i32) { instr_F30FE6(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FE7_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FE7_mem(addr: i32, r: i32) { // movntq m64, mm mov_r_m64(addr, r); } #[no_mangle] -pub unsafe fn instr_0FE7_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } +pub unsafe fn instr_0FE7_reg(r1: i32, r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660FE7_reg(mut r1: i32, mut r2: i32) { trigger_ud(); } +pub unsafe fn instr_660FE7_reg(r1: i32, r2: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660FE7_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FE7_mem(addr: i32, r: i32) { // movntdq m128, xmm mov_r_m128(addr, r); } #[no_mangle] -pub unsafe fn instr_0FE8(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FE8(source: reg64, r: i32) { // psubsb mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; @@ -4735,16 +4702,16 @@ pub unsafe fn instr_0FE8(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FE8_reg(mut r1: i32, mut r2: i32) { instr_0FE8(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FE8_reg(r1: i32, r2: i32) { instr_0FE8(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FE8_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FE8_mem(addr: i32, r: i32) { instr_0FE8(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FE8(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FE8(source: reg128, r: i32) { // psubsb xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; for i in 0..16 { result.i8_0[i as usize] = saturate_sd_to_sb( @@ -4754,67 +4721,67 @@ pub unsafe fn instr_660FE8(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FE8_reg(mut r1: i32, mut r2: i32) { instr_660FE8(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FE8_reg(r1: i32, r2: i32) { instr_660FE8(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FE8_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FE8_mem(addr: i32, r: i32) { instr_660FE8(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FE9(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FE9(source: reg64, r: i32) { // psubsw mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); - let mut word0: i32 = + let destination: reg64 = read_mmx64s(r); + let word0: i32 = saturate_sd_to_sw((destination.i16_0[0] as i32 - source.i16_0[0] as i32) as u32) as i32; - let mut word1: i32 = + let word1: i32 = saturate_sd_to_sw((destination.i16_0[1] as i32 - source.i16_0[1] as i32) as u32) as i32; - let mut word2: i32 = + let word2: i32 = saturate_sd_to_sw((destination.i16_0[2] as i32 - source.i16_0[2] as i32) as u32) as i32; - let mut word3: i32 = + let word3: i32 = saturate_sd_to_sw((destination.i16_0[3] as i32 - source.i16_0[3] as i32) as u32) as i32; - let mut low: i32 = word0 | word1 << 16; - let mut high: i32 = word2 | word3 << 16; + let low: i32 = word0 | word1 << 16; + let high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FE9_reg(mut r1: i32, mut r2: i32) { instr_0FE9(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FE9_reg(r1: i32, r2: i32) { instr_0FE9(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FE9_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FE9_mem(addr: i32, r: i32) { instr_0FE9(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FE9(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FE9(source: reg128, r: i32) { // psubsw xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); - let mut dword0: i32 = + let destination: reg128 = read_xmm128s(r); + let dword0: i32 = (saturate_sd_to_sw((destination.i16_0[0] as i32 - source.i16_0[0] as i32) as u32) | saturate_sd_to_sw((destination.i16_0[1] as i32 - source.i16_0[1] as i32) as u32) << 16) as i32; - let mut dword1: i32 = + let dword1: i32 = (saturate_sd_to_sw((destination.i16_0[2] as i32 - source.i16_0[2] as i32) as u32) | saturate_sd_to_sw((destination.i16_0[3] as i32 - source.i16_0[3] as i32) as u32) << 16) as i32; - let mut dword2: i32 = + let dword2: i32 = (saturate_sd_to_sw((destination.i16_0[4] as i32 - source.i16_0[4] as i32) as u32) | saturate_sd_to_sw((destination.i16_0[5] as i32 - source.i16_0[5] as i32) as u32) << 16) as i32; - let mut dword3: i32 = + let dword3: i32 = (saturate_sd_to_sw((destination.i16_0[6] as i32 - source.i16_0[6] as i32) as u32) | saturate_sd_to_sw((destination.i16_0[7] as i32 - source.i16_0[7] as i32) as u32) << 16) as i32; write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn instr_660FE9_reg(mut r1: i32, mut r2: i32) { instr_660FE9(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FE9_reg(r1: i32, r2: i32) { instr_660FE9(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FE9_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FE9_mem(addr: i32, r: i32) { instr_660FE9(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FEA(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FEA(source: reg64, r: i32) { // pminsw mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; for i in 0..4 { result.i16_0[i as usize] = @@ -4829,16 +4796,16 @@ pub unsafe fn instr_0FEA(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FEA_reg(mut r1: i32, mut r2: i32) { instr_0FEA(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FEA_reg(r1: i32, r2: i32) { instr_0FEA(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FEA_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FEA_mem(addr: i32, r: i32) { instr_0FEA(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FEA(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FEA(source: reg128, r: i32) { // pminsw xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; for i in 0..8 { result.i16_0[i as usize] = @@ -4852,15 +4819,15 @@ pub unsafe fn instr_660FEA(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FEA_reg(mut r1: i32, mut r2: i32) { instr_660FEA(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FEA_reg(r1: i32, r2: i32) { instr_660FEA(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FEA_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FEA_mem(addr: i32, r: i32) { instr_660FEA(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FEB(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FEB(source: reg64, r: i32) { // por mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; @@ -4869,27 +4836,27 @@ pub unsafe fn instr_0FEB(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FEB_reg(mut r1: i32, mut r2: i32) { instr_0FEB(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FEB_reg(r1: i32, r2: i32) { instr_0FEB(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FEB_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FEB_mem(addr: i32, r: i32) { instr_0FEB(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FEB(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FEB(source: reg128, r: i32) { // por xmm, xmm/m128 // XXX: Aligned access or #gp por_r128(source, r); } #[no_mangle] -pub unsafe fn instr_660FEB_reg(mut r1: i32, mut r2: i32) { instr_660FEB(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FEB_reg(r1: i32, r2: i32) { instr_660FEB(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FEB_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FEB_mem(addr: i32, r: i32) { instr_660FEB(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FEC(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FEC(source: reg64, r: i32) { // paddsb mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; @@ -4902,16 +4869,16 @@ pub unsafe fn instr_0FEC(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FEC_reg(mut r1: i32, mut r2: i32) { instr_0FEC(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FEC_reg(r1: i32, r2: i32) { instr_0FEC(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FEC_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FEC_mem(addr: i32, r: i32) { instr_0FEC(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FEC(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FEC(source: reg128, r: i32) { // paddsb xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; for i in 0..16 { result.i8_0[i as usize] = saturate_sd_to_sb( @@ -4921,67 +4888,67 @@ pub unsafe fn instr_660FEC(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FEC_reg(mut r1: i32, mut r2: i32) { instr_660FEC(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FEC_reg(r1: i32, r2: i32) { instr_660FEC(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FEC_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FEC_mem(addr: i32, r: i32) { instr_660FEC(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FED(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FED(source: reg64, r: i32) { // paddsw mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); - let mut word0: i32 = + let destination: reg64 = read_mmx64s(r); + let word0: i32 = saturate_sd_to_sw((destination.i16_0[0] as i32 + source.i16_0[0] as i32) as u32) as i32; - let mut word1: i32 = + let word1: i32 = saturate_sd_to_sw((destination.i16_0[1] as i32 + source.i16_0[1] as i32) as u32) as i32; - let mut word2: i32 = + let word2: i32 = saturate_sd_to_sw((destination.i16_0[2] as i32 + source.i16_0[2] as i32) as u32) as i32; - let mut word3: i32 = + let word3: i32 = saturate_sd_to_sw((destination.i16_0[3] as i32 + source.i16_0[3] as i32) as u32) as i32; - let mut low: i32 = word0 | word1 << 16; - let mut high: i32 = word2 | word3 << 16; + let low: i32 = word0 | word1 << 16; + let high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FED_reg(mut r1: i32, mut r2: i32) { instr_0FED(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FED_reg(r1: i32, r2: i32) { instr_0FED(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FED_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FED_mem(addr: i32, r: i32) { instr_0FED(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FED(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FED(source: reg128, r: i32) { // paddsw xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); - let mut dword0: i32 = + let destination: reg128 = read_xmm128s(r); + let dword0: i32 = (saturate_sd_to_sw((destination.i16_0[0] as i32 + source.i16_0[0] as i32) as u32) | saturate_sd_to_sw((destination.i16_0[1] as i32 + source.i16_0[1] as i32) as u32) << 16) as i32; - let mut dword1: i32 = + let dword1: i32 = (saturate_sd_to_sw((destination.i16_0[2] as i32 + source.i16_0[2] as i32) as u32) | saturate_sd_to_sw((destination.i16_0[3] as i32 + source.i16_0[3] as i32) as u32) << 16) as i32; - let mut dword2: i32 = + let dword2: i32 = (saturate_sd_to_sw((destination.i16_0[4] as i32 + source.i16_0[4] as i32) as u32) | saturate_sd_to_sw((destination.i16_0[5] as i32 + source.i16_0[5] as i32) as u32) << 16) as i32; - let mut dword3: i32 = + let dword3: i32 = (saturate_sd_to_sw((destination.i16_0[6] as i32 + source.i16_0[6] as i32) as u32) | saturate_sd_to_sw((destination.i16_0[7] as i32 + source.i16_0[7] as i32) as u32) << 16) as i32; write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn instr_660FED_reg(mut r1: i32, mut r2: i32) { instr_660FED(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FED_reg(r1: i32, r2: i32) { instr_660FED(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FED_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FED_mem(addr: i32, r: i32) { instr_660FED(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FEE(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FEE(source: reg64, r: i32) { // pmaxsw mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0; 8] }; for i in 0..4 { result.i16_0[i as usize] = @@ -4996,16 +4963,16 @@ pub unsafe fn instr_0FEE(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FEE_reg(mut r1: i32, mut r2: i32) { instr_0FEE(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FEE_reg(r1: i32, r2: i32) { instr_0FEE(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FEE_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FEE_mem(addr: i32, r: i32) { instr_0FEE(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FEE(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FEE(source: reg128, r: i32) { // pmaxsw xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0; 16] }; for i in 0..8 { result.i16_0[i as usize] = @@ -5019,15 +4986,15 @@ pub unsafe fn instr_660FEE(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FEE_reg(mut r1: i32, mut r2: i32) { instr_660FEE(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FEE_reg(r1: i32, r2: i32) { instr_660FEE(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FEE_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FEE_mem(addr: i32, r: i32) { instr_660FEE(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FEF(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FEF(source: reg64, r: i32) { // pxor mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; @@ -5036,96 +5003,96 @@ pub unsafe fn instr_0FEF(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FEF_reg(mut r1: i32, mut r2: i32) { instr_0FEF(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FEF_reg(r1: i32, r2: i32) { instr_0FEF(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FEF_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FEF_mem(addr: i32, r: i32) { instr_0FEF(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FEF(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FEF(source: reg128, r: i32) { // pxor xmm, xmm/m128 // XXX: Aligned access or #gp pxor_r128(source, r); } #[no_mangle] -pub unsafe fn instr_660FEF_reg(mut r1: i32, mut r2: i32) { instr_660FEF(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FEF_reg(r1: i32, r2: i32) { instr_660FEF(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FEF_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FEF_mem(addr: i32, r: i32) { instr_660FEF(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] pub unsafe fn instr_0FF0() { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_0FF1(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FF1(source: reg64, r: i32) { // psllw mm, mm/m64 psllw_r64(r, source.u64_0[0]); } #[no_mangle] -pub unsafe fn instr_0FF1_reg(mut r1: i32, mut r2: i32) { instr_0FF1(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FF1_reg(r1: i32, r2: i32) { instr_0FF1(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FF1_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FF1_mem(addr: i32, r: i32) { instr_0FF1(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FF1(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FF1(source: reg128, r: i32) { // psllw xmm, xmm/m128 // XXX: Aligned access or #gp psllw_r128(r, source.u64_0[0]); } #[no_mangle] -pub unsafe fn instr_660FF1_reg(mut r1: i32, mut r2: i32) { instr_660FF1(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FF1_reg(r1: i32, r2: i32) { instr_660FF1(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FF1_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FF1_mem(addr: i32, r: i32) { instr_660FF1(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FF2(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FF2(source: reg64, r: i32) { // pslld mm, mm/m64 pslld_r64(r, source.u64_0[0]); } #[no_mangle] -pub unsafe fn instr_0FF2_reg(mut r1: i32, mut r2: i32) { instr_0FF2(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FF2_reg(r1: i32, r2: i32) { instr_0FF2(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FF2_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FF2_mem(addr: i32, r: i32) { instr_0FF2(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FF2(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FF2(source: reg128, r: i32) { // pslld xmm, xmm/m128 // XXX: Aligned access or #gp pslld_r128(r, source.u64_0[0]); } #[no_mangle] -pub unsafe fn instr_660FF2_reg(mut r1: i32, mut r2: i32) { instr_660FF2(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FF2_reg(r1: i32, r2: i32) { instr_660FF2(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FF2_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FF2_mem(addr: i32, r: i32) { instr_660FF2(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FF3(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FF3(source: reg64, r: i32) { // psllq mm, mm/m64 psllq_r64(r, source.u64_0[0]); } #[no_mangle] -pub unsafe fn instr_0FF3_reg(mut r1: i32, mut r2: i32) { instr_0FF3(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FF3_reg(r1: i32, r2: i32) { instr_0FF3(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FF3_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FF3_mem(addr: i32, r: i32) { instr_0FF3(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FF3(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FF3(source: reg128, r: i32) { // psllq xmm, xmm/m128 // XXX: Aligned access or #gp psllq_r128(r, source.u64_0[0]); } #[no_mangle] -pub unsafe fn instr_660FF3_reg(mut r1: i32, mut r2: i32) { instr_660FF3(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FF3_reg(r1: i32, r2: i32) { instr_660FF3(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FF3_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FF3_mem(addr: i32, r: i32) { instr_660FF3(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FF4(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FF4(source: reg64, r: i32) { // pmuludq mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); destination.u64_0[0] = (source.u32_0[0] as u64).wrapping_mul(destination.u32_0[0] as u64); @@ -5133,13 +5100,13 @@ pub unsafe fn instr_0FF4(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FF4_reg(mut r1: i32, mut r2: i32) { instr_0FF4(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FF4_reg(r1: i32, r2: i32) { instr_0FF4(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FF4_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FF4_mem(addr: i32, r: i32) { instr_0FF4(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FF4(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FF4(source: reg128, r: i32) { // pmuludq xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -5148,55 +5115,55 @@ pub unsafe fn instr_660FF4(mut source: reg128, mut r: i32) { write_xmm_reg128(r, destination); } #[no_mangle] -pub unsafe fn instr_660FF4_reg(mut r1: i32, mut r2: i32) { instr_660FF4(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FF4_reg(r1: i32, r2: i32) { instr_660FF4(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FF4_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FF4_mem(addr: i32, r: i32) { instr_660FF4(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FF5(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FF5(source: reg64, r: i32) { // pmaddwd mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); - let mut mul0: i32 = destination.i16_0[0] as i32 * source.i16_0[0] as i32; - let mut mul1: i32 = destination.i16_0[1] as i32 * source.i16_0[1] as i32; - let mut mul2: i32 = destination.i16_0[2] as i32 * source.i16_0[2] as i32; - let mut mul3: i32 = destination.i16_0[3] as i32 * source.i16_0[3] as i32; - let mut low: i32 = mul0 + mul1; - let mut high: i32 = mul2 + mul3; + let destination: reg64 = read_mmx64s(r); + let mul0: i32 = destination.i16_0[0] as i32 * source.i16_0[0] as i32; + let mul1: i32 = destination.i16_0[1] as i32 * source.i16_0[1] as i32; + let mul2: i32 = destination.i16_0[2] as i32 * source.i16_0[2] as i32; + let mul3: i32 = destination.i16_0[3] as i32 * source.i16_0[3] as i32; + let low: i32 = mul0 + mul1; + let high: i32 = mul2 + mul3; write_mmx64(r, low, high); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FF5_reg(mut r1: i32, mut r2: i32) { instr_0FF5(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FF5_reg(r1: i32, r2: i32) { instr_0FF5(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FF5_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FF5_mem(addr: i32, r: i32) { instr_0FF5(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FF5(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FF5(source: reg128, r: i32) { // pmaddwd xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); - let mut dword0: i32 = destination.i16_0[0] as i32 * source.i16_0[0] as i32 + let destination: reg128 = read_xmm128s(r); + let dword0: i32 = destination.i16_0[0] as i32 * source.i16_0[0] as i32 + destination.i16_0[1] as i32 * source.i16_0[1] as i32; - let mut dword1: i32 = destination.i16_0[2] as i32 * source.i16_0[2] as i32 + let dword1: i32 = destination.i16_0[2] as i32 * source.i16_0[2] as i32 + destination.i16_0[3] as i32 * source.i16_0[3] as i32; - let mut dword2: i32 = destination.i16_0[4] as i32 * source.i16_0[4] as i32 + let dword2: i32 = destination.i16_0[4] as i32 * source.i16_0[4] as i32 + destination.i16_0[5] as i32 * source.i16_0[5] as i32; - let mut dword3: i32 = destination.i16_0[6] as i32 * source.i16_0[6] as i32 + let dword3: i32 = destination.i16_0[6] as i32 * source.i16_0[6] as i32 + destination.i16_0[7] as i32 * source.i16_0[7] as i32; write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn instr_660FF5_reg(mut r1: i32, mut r2: i32) { instr_660FF5(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FF5_reg(r1: i32, r2: i32) { instr_660FF5(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FF5_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FF5_mem(addr: i32, r: i32) { instr_660FF5(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FF6(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FF6(source: reg64, r: i32) { // psadbw mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); let mut sum: u32 = 0; for i in 0..8 { sum = (sum as u32).wrapping_add( @@ -5207,16 +5174,16 @@ pub unsafe fn instr_0FF6(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FF6_reg(mut r1: i32, mut r2: i32) { instr_0FF6(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FF6_reg(r1: i32, r2: i32) { instr_0FF6(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FF6_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FF6_mem(addr: i32, r: i32) { instr_0FF6(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FF6(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FF6(source: reg128, r: i32) { // psadbw xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut sum0: u32 = 0; let mut sum1: u32 = 0; for i in 0..8 { @@ -5230,19 +5197,19 @@ pub unsafe fn instr_660FF6(mut source: reg128, mut r: i32) { write_xmm128(r, sum0 as i32, 0, sum1 as i32, 0); } #[no_mangle] -pub unsafe fn instr_660FF6_reg(mut r1: i32, mut r2: i32) { instr_660FF6(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FF6_reg(r1: i32, r2: i32) { instr_660FF6(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FF6_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FF6_mem(addr: i32, r: i32) { instr_660FF6(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FF7_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_0FF7_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_0FF7_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_0FF7_reg(r1: i32, r2: i32) { // maskmovq mm, mm - let mut source: reg64 = read_mmx64s(r2); - let mut mask: reg64 = read_mmx64s(r1); - let mut addr: i32 = get_seg_prefix(DS) + get_reg_asize(EDI); + let source: reg64 = read_mmx64s(r2); + let mask: reg64 = read_mmx64s(r1); + let addr: i32 = get_seg_prefix(DS) + get_reg_asize(EDI); return_on_pagefault!(writable_or_pagefault(addr, 8)); for i in 0..8 { if 0 != mask.u8_0[i as usize] as i32 & 128 { @@ -5255,13 +5222,13 @@ pub unsafe fn instr_0FF7_reg(mut r1: i32, mut r2: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_660FF7_mem(mut addr: i32, mut r: i32) { trigger_ud(); } +pub unsafe fn instr_660FF7_mem(addr: i32, r: i32) { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_660FF7_reg(mut r1: i32, mut r2: i32) { +pub unsafe fn instr_660FF7_reg(r1: i32, r2: i32) { // maskmovdqu xmm, xmm - let mut source: reg128 = read_xmm128s(r2); - let mut mask: reg128 = read_xmm128s(r1); - let mut addr: i32 = get_seg_prefix(DS) + get_reg_asize(EDI); + let source: reg128 = read_xmm128s(r2); + let mask: reg128 = read_xmm128s(r1); + let addr: i32 = get_seg_prefix(DS) + get_reg_asize(EDI); return_on_pagefault!(writable_or_pagefault(addr, 16)); for i in 0..16 { if 0 != mask.u8_0[i as usize] as i32 & 128 { @@ -5273,9 +5240,9 @@ pub unsafe fn instr_660FF7_reg(mut r1: i32, mut r2: i32) { } } #[no_mangle] -pub unsafe fn instr_0FF8(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FF8(source: reg64, r: i32) { // psubb mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; @@ -5287,16 +5254,16 @@ pub unsafe fn instr_0FF8(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FF8_reg(mut r1: i32, mut r2: i32) { instr_0FF8(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FF8_reg(r1: i32, r2: i32) { instr_0FF8(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FF8_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FF8_mem(addr: i32, r: i32) { instr_0FF8(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FF8(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FF8(source: reg128, r: i32) { // psubb xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; @@ -5307,37 +5274,37 @@ pub unsafe fn instr_660FF8(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FF8_reg(mut r1: i32, mut r2: i32) { instr_660FF8(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FF8_reg(r1: i32, r2: i32) { instr_660FF8(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FF8_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FF8_mem(addr: i32, r: i32) { instr_660FF8(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FF9(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FF9(source: reg64, r: i32) { // psubw mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); - let mut word0: i32 = (destination.u32_0[0].wrapping_sub(source.u32_0[0]) & 65535) as i32; - let mut word1: i32 = + let destination: reg64 = read_mmx64s(r); + let word0: i32 = (destination.u32_0[0].wrapping_sub(source.u32_0[0]) & 65535) as i32; + let word1: i32 = ((destination.u16_0[1] as u32).wrapping_sub(source.u16_0[1] as u32) & 65535) as i32; - let mut low: i32 = word0 | word1 << 16; - let mut word2: i32 = (destination.u32_0[1].wrapping_sub(source.u32_0[1]) & 65535) as i32; - let mut word3: i32 = + let low: i32 = word0 | word1 << 16; + let word2: i32 = (destination.u32_0[1].wrapping_sub(source.u32_0[1]) & 65535) as i32; + let word3: i32 = ((destination.u16_0[3] as u32).wrapping_sub(source.u16_0[3] as u32) & 65535) as i32; - let mut high: i32 = word2 | word3 << 16; + let high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FF9_reg(mut r1: i32, mut r2: i32) { instr_0FF9(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FF9_reg(r1: i32, r2: i32) { instr_0FF9(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FF9_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FF9_mem(addr: i32, r: i32) { instr_0FF9(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FF9(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FF9(source: reg128, r: i32) { // psubw xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; @@ -5348,15 +5315,15 @@ pub unsafe fn instr_660FF9(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FF9_reg(mut r1: i32, mut r2: i32) { instr_660FF9(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FF9_reg(r1: i32, r2: i32) { instr_660FF9(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FF9_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FF9_mem(addr: i32, r: i32) { instr_660FF9(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FFA(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FFA(source: reg64, r: i32) { // psubd mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); write_mmx64( r, destination.u32_0[0].wrapping_sub(source.u32_0[0]) as i32, @@ -5365,16 +5332,16 @@ pub unsafe fn instr_0FFA(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FFA_reg(mut r1: i32, mut r2: i32) { instr_0FFA(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FFA_reg(r1: i32, r2: i32) { instr_0FFA(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FFA_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FFA_mem(addr: i32, r: i32) { instr_0FFA(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FFA(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FFA(source: reg128, r: i32) { // psubd xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); write_xmm128( r, destination.u32_0[0].wrapping_sub(source.u32_0[0]) as i32, @@ -5384,13 +5351,13 @@ pub unsafe fn instr_660FFA(mut source: reg128, mut r: i32) { ); } #[no_mangle] -pub unsafe fn instr_660FFA_reg(mut r1: i32, mut r2: i32) { instr_660FFA(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FFA_reg(r1: i32, r2: i32) { instr_660FFA(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FFA_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FFA_mem(addr: i32, r: i32) { instr_660FFA(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FFB(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FFB(source: reg64, r: i32) { // psubq mm, mm/m64 let mut destination: reg64 = read_mmx64s(r); destination.u64_0[0] = destination.u64_0[0].wrapping_sub(source.u64_0[0]); @@ -5398,13 +5365,13 @@ pub unsafe fn instr_0FFB(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FFB_reg(mut r1: i32, mut r2: i32) { instr_0FFB(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FFB_reg(r1: i32, r2: i32) { instr_0FFB(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FFB_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FFB_mem(addr: i32, r: i32) { instr_0FFB(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FFB(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FFB(source: reg128, r: i32) { // psubq xmm, xmm/m128 // XXX: Aligned access or #gp let mut destination: reg128 = read_xmm128s(r); @@ -5413,15 +5380,15 @@ pub unsafe fn instr_660FFB(mut source: reg128, mut r: i32) { write_xmm_reg128(r, destination); } #[no_mangle] -pub unsafe fn instr_660FFB_reg(mut r1: i32, mut r2: i32) { instr_660FFB(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FFB_reg(r1: i32, r2: i32) { instr_660FFB(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FFB_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FFB_mem(addr: i32, r: i32) { instr_660FFB(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FFC(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FFC(source: reg64, r: i32) { // paddb mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; @@ -5433,16 +5400,16 @@ pub unsafe fn instr_0FFC(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FFC_reg(mut r1: i32, mut r2: i32) { instr_0FFC(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FFC_reg(r1: i32, r2: i32) { instr_0FFC(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FFC_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FFC_mem(addr: i32, r: i32) { instr_0FFC(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FFC(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FFC(source: reg128, r: i32) { // paddb xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; @@ -5453,35 +5420,35 @@ pub unsafe fn instr_660FFC(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FFC_reg(mut r1: i32, mut r2: i32) { instr_660FFC(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FFC_reg(r1: i32, r2: i32) { instr_660FFC(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FFC_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FFC_mem(addr: i32, r: i32) { instr_660FFC(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FFD(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FFD(source: reg64, r: i32) { // paddw mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); - let mut word0: i32 = (destination.u32_0[0].wrapping_add(source.u32_0[0]) & 65535) as i32; - let mut word1: i32 = destination.u16_0[1] as i32 + source.u16_0[1] as i32 & 65535; - let mut low: i32 = word0 | word1 << 16; - let mut word2: i32 = (destination.u32_0[1].wrapping_add(source.u32_0[1]) & 65535) as i32; - let mut word3: i32 = destination.u16_0[3] as i32 + source.u16_0[3] as i32 & 65535; - let mut high: i32 = word2 | word3 << 16; + let destination: reg64 = read_mmx64s(r); + let word0: i32 = (destination.u32_0[0].wrapping_add(source.u32_0[0]) & 65535) as i32; + let word1: i32 = destination.u16_0[1] as i32 + source.u16_0[1] as i32 & 65535; + let low: i32 = word0 | word1 << 16; + let word2: i32 = (destination.u32_0[1].wrapping_add(source.u32_0[1]) & 65535) as i32; + let word3: i32 = destination.u16_0[3] as i32 + source.u16_0[3] as i32 & 65535; + let high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FFD_reg(mut r1: i32, mut r2: i32) { instr_0FFD(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FFD_reg(r1: i32, r2: i32) { instr_0FFD(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FFD_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FFD_mem(addr: i32, r: i32) { instr_0FFD(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FFD(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FFD(source: reg128, r: i32) { // paddw xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; @@ -5492,41 +5459,41 @@ pub unsafe fn instr_660FFD(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FFD_reg(mut r1: i32, mut r2: i32) { instr_660FFD(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FFD_reg(r1: i32, r2: i32) { instr_660FFD(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FFD_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FFD_mem(addr: i32, r: i32) { instr_660FFD(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0FFE(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0FFE(source: reg64, r: i32) { // paddd mm, mm/m64 - let mut destination: reg64 = read_mmx64s(r); - let mut low: i32 = destination.u32_0[0].wrapping_add(source.u32_0[0]) as i32; - let mut high: i32 = destination.u32_0[1].wrapping_add(source.u32_0[1]) as i32; + let destination: reg64 = read_mmx64s(r); + let low: i32 = destination.u32_0[0].wrapping_add(source.u32_0[0]) as i32; + let high: i32 = destination.u32_0[1].wrapping_add(source.u32_0[1]) as i32; write_mmx64(r, low, high); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0FFE_reg(mut r1: i32, mut r2: i32) { instr_0FFE(read_mmx64s(r1), r2); } +pub unsafe fn instr_0FFE_reg(r1: i32, r2: i32) { instr_0FFE(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0FFE_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0FFE_mem(addr: i32, r: i32) { instr_0FFE(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660FFE(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660FFE(source: reg128, r: i32) { // paddd xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); - let mut dword0: i32 = destination.u32_0[0].wrapping_add(source.u32_0[0]) as i32; - let mut dword1: i32 = destination.u32_0[1].wrapping_add(source.u32_0[1]) as i32; - let mut dword2: i32 = destination.u32_0[2].wrapping_add(source.u32_0[2]) as i32; - let mut dword3: i32 = destination.u32_0[3].wrapping_add(source.u32_0[3]) as i32; + let destination: reg128 = read_xmm128s(r); + let dword0: i32 = destination.u32_0[0].wrapping_add(source.u32_0[0]) as i32; + let dword1: i32 = destination.u32_0[1].wrapping_add(source.u32_0[1]) as i32; + let dword2: i32 = destination.u32_0[2].wrapping_add(source.u32_0[2]) as i32; + let dword3: i32 = destination.u32_0[3].wrapping_add(source.u32_0[3]) as i32; write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn instr_660FFE_reg(mut r1: i32, mut r2: i32) { instr_660FFE(read_xmm128s(r1), r2); } +pub unsafe fn instr_660FFE_reg(r1: i32, r2: i32) { instr_660FFE(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660FFE_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660FFE_mem(addr: i32, r: i32) { instr_660FFE(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] @@ -5536,89 +5503,89 @@ pub unsafe fn instr_0FFF() { trigger_ud(); } #[no_mangle] -pub unsafe fn instr_F30F16_reg(mut r1: i32, mut r2: i32) { unimplemented_sse(); } +pub unsafe fn instr_F30F16_reg(r1: i32, r2: i32) { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_F30F16_mem(mut addr: i32, mut r: i32) { unimplemented_sse(); } +pub unsafe fn instr_F30F16_mem(addr: i32, r: i32) { unimplemented_sse(); } #[no_mangle] -pub unsafe fn instr_0F19_reg(mut r1: i32, mut r2: i32) {} +pub unsafe fn instr_0F19_reg(r1: i32, r2: i32) {} #[no_mangle] -pub unsafe fn instr_0F19_mem(mut addr: i32, mut r: i32) {} +pub unsafe fn instr_0F19_mem(addr: i32, r: i32) {} #[no_mangle] -pub unsafe fn instr_0F1C_reg(mut r1: i32, mut r2: i32) {} +pub unsafe fn instr_0F1C_reg(r1: i32, r2: i32) {} #[no_mangle] -pub unsafe fn instr_0F1C_mem(mut addr: i32, mut r: i32) {} +pub unsafe fn instr_0F1C_mem(addr: i32, r: i32) {} #[no_mangle] -pub unsafe fn instr_0F1D_reg(mut r1: i32, mut r2: i32) {} +pub unsafe fn instr_0F1D_reg(r1: i32, r2: i32) {} #[no_mangle] -pub unsafe fn instr_0F1D_mem(mut addr: i32, mut r: i32) {} +pub unsafe fn instr_0F1D_mem(addr: i32, r: i32) {} #[no_mangle] -pub unsafe fn instr_0F1E_reg(mut r1: i32, mut r2: i32) {} +pub unsafe fn instr_0F1E_reg(r1: i32, r2: i32) {} #[no_mangle] -pub unsafe fn instr_0F1E_mem(mut addr: i32, mut r: i32) {} +pub unsafe fn instr_0F1E_mem(addr: i32, r: i32) {} #[no_mangle] -pub unsafe fn instr_0F2A(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0F2A(source: reg64, r: i32) { // cvtpi2ps xmm, mm/m64 // Note: Casts here can fail - let mut result: reg64 = reg64 { + let result: reg64 = reg64 { f32_0: [source.i32_0[0] as f32, source.i32_0[1] as f32], }; write_xmm64(r, result); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0F2A_reg(mut r1: i32, mut r2: i32) { instr_0F2A(read_mmx64s(r1), r2); } +pub unsafe fn instr_0F2A_reg(r1: i32, r2: i32) { instr_0F2A(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F2A_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F2A_mem(addr: i32, r: i32) { instr_0F2A(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F2A(mut source: reg64, mut r: i32) { +pub unsafe fn instr_660F2A(source: reg64, r: i32) { // cvtpi2pd xmm, xmm/m64 // These casts can't fail - let mut result: reg128 = reg128 { + let result: reg128 = reg128 { f64_0: [source.i32_0[0] as f64, source.i32_0[1] as f64], }; write_xmm_reg128(r, result); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_660F2A_reg(mut r1: i32, mut r2: i32) { instr_660F2A(read_mmx64s(r1), r2); } +pub unsafe fn instr_660F2A_reg(r1: i32, r2: i32) { instr_660F2A(read_mmx64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F2A_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F2A_mem(addr: i32, r: i32) { instr_660F2A(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20F2A(mut source: i32, mut r: i32) { +pub unsafe fn instr_F20F2A(source: i32, r: i32) { // cvtsi2sd xmm, r32/m32 // This cast can't fail - let mut result: reg64 = reg64 { + let result: reg64 = reg64 { f64_0: [source as f64], }; write_xmm64(r, result); } #[no_mangle] -pub unsafe fn instr_F20F2A_reg(mut r1: i32, mut r2: i32) { instr_F20F2A(read_reg32(r1), r2); } +pub unsafe fn instr_F20F2A_reg(r1: i32, r2: i32) { instr_F20F2A(read_reg32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F2A_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F20F2A_mem(addr: i32, r: i32) { instr_F20F2A(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F2A(mut source: i32, mut r: i32) { +pub unsafe fn instr_F30F2A(source: i32, r: i32) { // cvtsi2ss xmm, r/m32 // Note: This cast can fail - let mut result: f32 = source as f32; + let result: f32 = source as f32; write_xmm_f32(r, result); } #[no_mangle] -pub unsafe fn instr_F30F2A_reg(mut r1: i32, mut r2: i32) { instr_F30F2A(read_reg32(r1), r2); } +pub unsafe fn instr_F30F2A_reg(r1: i32, r2: i32) { instr_F30F2A(read_reg32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F2A_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F30F2A_mem(addr: i32, r: i32) { instr_F30F2A(return_on_pagefault!(safe_read32s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F2D(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0F2D(source: reg64, r: i32) { // cvtps2pi mm, xmm/m64 let result = reg64 { i32_0: [ @@ -5630,14 +5597,14 @@ pub unsafe fn instr_0F2D(mut source: reg64, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_0F2D_reg(mut r1: i32, mut r2: i32) { instr_0F2D(read_xmm64s(r1), r2); } +pub unsafe fn instr_0F2D_reg(r1: i32, r2: i32) { instr_0F2D(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F2D_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F2D_mem(addr: i32, r: i32) { instr_0F2D(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F2D(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F2D(source: reg128, r: i32) { // cvtpd2pi mm, xmm/m128 let result = reg64 { i32_0: [ @@ -5649,38 +5616,38 @@ pub unsafe fn instr_660F2D(mut source: reg128, mut r: i32) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn instr_660F2D_reg(mut r1: i32, mut r2: i32) { instr_660F2D(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F2D_reg(r1: i32, r2: i32) { instr_660F2D(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F2D_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F2D_mem(addr: i32, r: i32) { instr_660F2D(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20F2D(mut source: reg64, mut r: i32) { +pub unsafe fn instr_F20F2D(source: reg64, r: i32) { // cvtsd2si r32, xmm/m64 write_reg32(r, sse_convert_f64_to_i32(source.f64_0[0].round())); } #[no_mangle] -pub unsafe fn instr_F20F2D_reg(mut r1: i32, mut r2: i32) { instr_F20F2D(read_xmm64s(r1), r2); } +pub unsafe fn instr_F20F2D_reg(r1: i32, r2: i32) { instr_F20F2D(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F2D_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F20F2D_mem(addr: i32, r: i32) { instr_F20F2D(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F2D(mut source: f32, mut r: i32) { +pub unsafe fn instr_F30F2D(source: f32, r: i32) { // cvtss2si r32, xmm1/m32 write_reg32(r, sse_convert_f32_to_i32(source.round())); } #[no_mangle] -pub unsafe fn instr_F30F2D_reg(mut r1: i32, mut r2: i32) { instr_F30F2D(read_xmm_f32(r1), r2); } +pub unsafe fn instr_F30F2D_reg(r1: i32, r2: i32) { instr_F30F2D(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F2D_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F30F2D_mem(addr: i32, r: i32) { instr_F30F2D(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_0F51(mut source: reg128, mut r: i32) { +pub unsafe fn instr_0F51(source: reg128, r: i32) { // sqrtps xmm, xmm/mem128 - let mut result: reg128 = reg128 { + let result: reg128 = reg128 { f32_0: [ source.f32_0[0].sqrt(), source.f32_0[1].sqrt(), @@ -5691,55 +5658,55 @@ pub unsafe fn instr_0F51(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0F51_reg(mut r1: i32, mut r2: i32) { instr_0F51(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F51_reg(r1: i32, r2: i32) { instr_0F51(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F51_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F51_mem(addr: i32, r: i32) { instr_0F51(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F51(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F51(source: reg128, r: i32) { // sqrtpd xmm, xmm/mem128 - let mut result: reg128 = reg128 { + let result: reg128 = reg128 { f64_0: [source.f64_0[0].sqrt(), source.f64_0[1].sqrt()], }; write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F51_reg(mut r1: i32, mut r2: i32) { instr_660F51(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F51_reg(r1: i32, r2: i32) { instr_660F51(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F51_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F51_mem(addr: i32, r: i32) { instr_660F51(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20F51(mut source: reg64, mut r: i32) { +pub unsafe fn instr_F20F51(source: reg64, r: i32) { // sqrtsd xmm, xmm/mem64 - let mut result: reg64 = reg64 { + let result: reg64 = reg64 { f64_0: [source.f64_0[0].sqrt()], }; write_xmm64(r, result); } #[no_mangle] -pub unsafe fn instr_F20F51_reg(mut r1: i32, mut r2: i32) { instr_F20F51(read_xmm64s(r1), r2); } +pub unsafe fn instr_F20F51_reg(r1: i32, r2: i32) { instr_F20F51(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F51_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F20F51_mem(addr: i32, r: i32) { instr_F20F51(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F51(mut source: f32, mut r: i32) { +pub unsafe fn instr_F30F51(source: f32, r: i32) { // sqrtss xmm, xmm/mem32 write_xmm_f32(r, source.sqrt()); } #[no_mangle] -pub unsafe fn instr_F30F51_reg(mut r1: i32, mut r2: i32) { instr_F30F51(read_xmm_f32(r1), r2); } +pub unsafe fn instr_F30F51_reg(r1: i32, r2: i32) { instr_F30F51(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F51_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F30F51_mem(addr: i32, r: i32) { instr_F30F51(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_0F52(mut source: reg128, mut r: i32) { +pub unsafe fn instr_0F52(source: reg128, r: i32) { // rcpps xmm1, xmm2/m128 - let mut result: reg128 = reg128 { + let result: reg128 = reg128 { f32_0: [ 1.0 / source.f32_0[0].sqrt(), 1.0 / source.f32_0[1].sqrt(), @@ -5750,27 +5717,27 @@ pub unsafe fn instr_0F52(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0F52_reg(mut r1: i32, mut r2: i32) { instr_0F52(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F52_reg(r1: i32, r2: i32) { instr_0F52(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F52_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F52_mem(addr: i32, r: i32) { instr_0F52(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F52(mut source: f32, mut r: i32) { +pub unsafe fn instr_F30F52(source: f32, r: i32) { // rsqrtss xmm1, xmm2/m32 write_xmm_f32(r, 1.0 / source.sqrt()); } #[no_mangle] -pub unsafe fn instr_F30F52_reg(mut r1: i32, mut r2: i32) { instr_F30F52(read_xmm_f32(r1), r2); } +pub unsafe fn instr_F30F52_reg(r1: i32, r2: i32) { instr_F30F52(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F52_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F30F52_mem(addr: i32, r: i32) { instr_F30F52(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_0F53(mut source: reg128, mut r: i32) { +pub unsafe fn instr_0F53(source: reg128, r: i32) { // rcpps xmm, xmm/m128 - let mut result: reg128 = reg128 { + let result: reg128 = reg128 { f32_0: [ 1.0 / source.f32_0[0], 1.0 / source.f32_0[1], @@ -5781,28 +5748,28 @@ pub unsafe fn instr_0F53(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0F53_reg(mut r1: i32, mut r2: i32) { instr_0F53(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F53_reg(r1: i32, r2: i32) { instr_0F53(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F53_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F53_mem(addr: i32, r: i32) { instr_0F53(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F53(mut source: f32, mut r: i32) { +pub unsafe fn instr_F30F53(source: f32, r: i32) { // rcpss xmm, xmm/m32 write_xmm_f32(r, 1.0 / source); } #[no_mangle] -pub unsafe fn instr_F30F53_reg(mut r1: i32, mut r2: i32) { instr_F30F53(read_xmm_f32(r1), r2); } +pub unsafe fn instr_F30F53_reg(r1: i32, r2: i32) { instr_F30F53(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F53_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F30F53_mem(addr: i32, r: i32) { instr_F30F53(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_0F58(mut source: reg128, mut r: i32) { +pub unsafe fn instr_0F58(source: reg128, r: i32) { // addps xmm, xmm/mem128 - let mut destination: reg128 = read_xmm128s(r); - let mut result: reg128 = reg128 { + let destination: reg128 = read_xmm128s(r); + let result: reg128 = reg128 { f32_0: [ source.f32_0[0] + destination.f32_0[0], source.f32_0[1] + destination.f32_0[1], @@ -5813,16 +5780,16 @@ pub unsafe fn instr_0F58(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0F58_reg(mut r1: i32, mut r2: i32) { instr_0F58(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F58_reg(r1: i32, r2: i32) { instr_0F58(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F58_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F58_mem(addr: i32, r: i32) { instr_0F58(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F58(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F58(source: reg128, r: i32) { // addpd xmm, xmm/mem128 - let mut destination: reg128 = read_xmm128s(r); - let mut result: reg128 = reg128 { + let destination: reg128 = read_xmm128s(r); + let result: reg128 = reg128 { f64_0: [ source.f64_0[0] + destination.f64_0[0], source.f64_0[1] + destination.f64_0[1], @@ -5831,45 +5798,45 @@ pub unsafe fn instr_660F58(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F58_reg(mut r1: i32, mut r2: i32) { instr_660F58(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F58_reg(r1: i32, r2: i32) { instr_660F58(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F58_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F58_mem(addr: i32, r: i32) { instr_660F58(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20F58(mut source: reg64, mut r: i32) { +pub unsafe fn instr_F20F58(source: reg64, r: i32) { // addsd xmm, xmm/mem64 - let mut destination: reg64 = read_xmm64s(r); - let mut result: reg64 = reg64 { + let destination: reg64 = read_xmm64s(r); + let result: reg64 = reg64 { f64_0: [source.f64_0[0] + destination.f64_0[0]], }; write_xmm64(r, result); } #[no_mangle] -pub unsafe fn instr_F20F58_reg(mut r1: i32, mut r2: i32) { instr_F20F58(read_xmm64s(r1), r2); } +pub unsafe fn instr_F20F58_reg(r1: i32, r2: i32) { instr_F20F58(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F58_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F20F58_mem(addr: i32, r: i32) { instr_F20F58(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F58(mut source: f32, mut r: i32) { +pub unsafe fn instr_F30F58(source: f32, r: i32) { // addss xmm, xmm/mem32 - let mut destination: f32 = read_xmm_f32(r); - let mut result: f32 = source + destination; + let destination: f32 = read_xmm_f32(r); + let result: f32 = source + destination; write_xmm_f32(r, result); } #[no_mangle] -pub unsafe fn instr_F30F58_reg(mut r1: i32, mut r2: i32) { instr_F30F58(read_xmm_f32(r1), r2); } +pub unsafe fn instr_F30F58_reg(r1: i32, r2: i32) { instr_F30F58(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F58_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F30F58_mem(addr: i32, r: i32) { instr_F30F58(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_0F59(mut source: reg128, mut r: i32) { +pub unsafe fn instr_0F59(source: reg128, r: i32) { // mulps xmm, xmm/mem128 - let mut destination: reg128 = read_xmm128s(r); - let mut result: reg128 = reg128 { + let destination: reg128 = read_xmm128s(r); + let result: reg128 = reg128 { f32_0: [ source.f32_0[0] * destination.f32_0[0], source.f32_0[1] * destination.f32_0[1], @@ -5880,16 +5847,16 @@ pub unsafe fn instr_0F59(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0F59_reg(mut r1: i32, mut r2: i32) { instr_0F59(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F59_reg(r1: i32, r2: i32) { instr_0F59(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F59_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F59_mem(addr: i32, r: i32) { instr_0F59(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F59(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F59(source: reg128, r: i32) { // mulpd xmm, xmm/mem128 - let mut destination: reg128 = read_xmm128s(r); - let mut result: reg128 = reg128 { + let destination: reg128 = read_xmm128s(r); + let result: reg128 = reg128 { f64_0: [ source.f64_0[0] * destination.f64_0[0], source.f64_0[1] * destination.f64_0[1], @@ -5898,100 +5865,100 @@ pub unsafe fn instr_660F59(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F59_reg(mut r1: i32, mut r2: i32) { instr_660F59(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F59_reg(r1: i32, r2: i32) { instr_660F59(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F59_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F59_mem(addr: i32, r: i32) { instr_660F59(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20F59(mut source: reg64, mut r: i32) { +pub unsafe fn instr_F20F59(source: reg64, r: i32) { // mulsd xmm, xmm/mem64 - let mut destination: reg64 = read_xmm64s(r); - let mut result: reg64 = reg64 { + let destination: reg64 = read_xmm64s(r); + let result: reg64 = reg64 { f64_0: [source.f64_0[0] * destination.f64_0[0]], }; write_xmm64(r, result); } #[no_mangle] -pub unsafe fn instr_F20F59_reg(mut r1: i32, mut r2: i32) { instr_F20F59(read_xmm64s(r1), r2); } +pub unsafe fn instr_F20F59_reg(r1: i32, r2: i32) { instr_F20F59(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F59_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F20F59_mem(addr: i32, r: i32) { instr_F20F59(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F59(mut source: f32, mut r: i32) { +pub unsafe fn instr_F30F59(source: f32, r: i32) { // mulss xmm, xmm/mem32 - let mut destination: f32 = read_xmm_f32(r); - let mut result: f32 = source * destination; + let destination: f32 = read_xmm_f32(r); + let result: f32 = source * destination; write_xmm_f32(r, result); } #[no_mangle] -pub unsafe fn instr_F30F59_reg(mut r1: i32, mut r2: i32) { instr_F30F59(read_xmm_f32(r1), r2); } +pub unsafe fn instr_F30F59_reg(r1: i32, r2: i32) { instr_F30F59(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F59_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F30F59_mem(addr: i32, r: i32) { instr_F30F59(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_0F5A(mut source: reg64, mut r: i32) { +pub unsafe fn instr_0F5A(source: reg64, r: i32) { // cvtps2pd xmm1, xmm2/m64 - let mut result: reg128 = reg128 { + let result: reg128 = reg128 { f64_0: [source.f32_0[0] as f64, source.f32_0[1] as f64], }; write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0F5A_reg(mut r1: i32, mut r2: i32) { instr_0F5A(read_xmm64s(r1), r2); } +pub unsafe fn instr_0F5A_reg(r1: i32, r2: i32) { instr_0F5A(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F5A_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F5A_mem(addr: i32, r: i32) { instr_0F5A(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F5A(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F5A(source: reg128, r: i32) { // cvtpd2ps xmm1, xmm2/m128 - let mut result: reg128 = reg128 { + let result: reg128 = reg128 { // XXX: These conversions are lossy and should round according to the round control f32_0: [source.f64_0[0] as f32, source.f64_0[1] as f32, 0., 0.], }; write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F5A_reg(mut r1: i32, mut r2: i32) { instr_660F5A(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F5A_reg(r1: i32, r2: i32) { instr_660F5A(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F5A_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F5A_mem(addr: i32, r: i32) { instr_660F5A(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20F5A(mut source: reg64, mut r: i32) { +pub unsafe fn instr_F20F5A(source: reg64, r: i32) { // cvtsd2ss xmm1, xmm2/m64 // XXX: This conversions is lossy and should round according to the round control write_xmm_f32(r, source.f64_0[0] as f32); } #[no_mangle] -pub unsafe fn instr_F20F5A_reg(mut r1: i32, mut r2: i32) { instr_F20F5A(read_xmm64s(r1), r2); } +pub unsafe fn instr_F20F5A_reg(r1: i32, r2: i32) { instr_F20F5A(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F5A_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F20F5A_mem(addr: i32, r: i32) { instr_F20F5A(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F5A(mut source: f32, mut r: i32) { +pub unsafe fn instr_F30F5A(source: f32, r: i32) { // cvtss2sd xmm1, xmm2/m32 - let mut result: reg64 = reg64 { + let result: reg64 = reg64 { f64_0: [source as f64], }; write_xmm64(r, result); } #[no_mangle] -pub unsafe fn instr_F30F5A_reg(mut r1: i32, mut r2: i32) { instr_F30F5A(read_xmm_f32(r1), r2); } +pub unsafe fn instr_F30F5A_reg(r1: i32, r2: i32) { instr_F30F5A(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F5A_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F30F5A_mem(addr: i32, r: i32) { instr_F30F5A(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_0F5B(mut source: reg128, mut r: i32) { +pub unsafe fn instr_0F5B(source: reg128, r: i32) { // cvtdq2ps xmm1, xmm2/m128 - let mut result: reg128 = reg128 { + let result: reg128 = reg128 { f32_0: [ // XXX: Precision exception source.i32_0[0] as f32, @@ -6003,15 +5970,15 @@ pub unsafe fn instr_0F5B(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0F5B_reg(mut r1: i32, mut r2: i32) { instr_0F5B(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F5B_reg(r1: i32, r2: i32) { instr_0F5B(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F5B_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F5B_mem(addr: i32, r: i32) { instr_0F5B(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F5B(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F5B(source: reg128, r: i32) { // cvtps2dq xmm1, xmm2/m128 - let mut result = reg128 { + let result = reg128 { i32_0: [ // XXX: Precision exception sse_convert_f32_to_i32(source.f32_0[0].round()), @@ -6023,15 +5990,15 @@ pub unsafe fn instr_660F5B(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F5B_reg(mut r1: i32, mut r2: i32) { instr_660F5B(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F5B_reg(r1: i32, r2: i32) { instr_660F5B(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F5B_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F5B_mem(addr: i32, r: i32) { instr_660F5B(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F5B(mut source: reg128, mut r: i32) { +pub unsafe fn instr_F30F5B(source: reg128, r: i32) { // cvttps2dq xmm1, xmm2/m128 - let mut result = reg128 { + let result = reg128 { i32_0: [ sse_convert_f32_to_i32(source.f32_0[0].trunc()), sse_convert_f32_to_i32(source.f32_0[1].trunc()), @@ -6042,17 +6009,17 @@ pub unsafe fn instr_F30F5B(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_F30F5B_reg(mut r1: i32, mut r2: i32) { instr_F30F5B(read_xmm128s(r1), r2); } +pub unsafe fn instr_F30F5B_reg(r1: i32, r2: i32) { instr_F30F5B(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F5B_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F30F5B_mem(addr: i32, r: i32) { instr_F30F5B(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_0F5C(mut source: reg128, mut r: i32) { +pub unsafe fn instr_0F5C(source: reg128, r: i32) { // subps xmm, xmm/mem128 - let mut destination: reg128 = read_xmm128s(r); - let mut result: reg128 = reg128 { + let destination: reg128 = read_xmm128s(r); + let result: reg128 = reg128 { f32_0: [ destination.f32_0[0] - source.f32_0[0], destination.f32_0[1] - source.f32_0[1], @@ -6063,16 +6030,16 @@ pub unsafe fn instr_0F5C(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0F5C_reg(mut r1: i32, mut r2: i32) { instr_0F5C(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F5C_reg(r1: i32, r2: i32) { instr_0F5C(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F5C_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F5C_mem(addr: i32, r: i32) { instr_0F5C(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F5C(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F5C(source: reg128, r: i32) { // subpd xmm, xmm/mem128 - let mut destination: reg128 = read_xmm128s(r); - let mut result: reg128 = reg128 { + let destination: reg128 = read_xmm128s(r); + let result: reg128 = reg128 { f64_0: [ destination.f64_0[0] - source.f64_0[0], destination.f64_0[1] - source.f64_0[1], @@ -6081,44 +6048,44 @@ pub unsafe fn instr_660F5C(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F5C_reg(mut r1: i32, mut r2: i32) { instr_660F5C(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F5C_reg(r1: i32, r2: i32) { instr_660F5C(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F5C_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F5C_mem(addr: i32, r: i32) { instr_660F5C(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20F5C(mut source: reg64, mut r: i32) { +pub unsafe fn instr_F20F5C(source: reg64, r: i32) { // subsd xmm, xmm/mem64 - let mut destination: reg64 = read_xmm64s(r); - let mut result: reg64 = reg64 { + let destination: reg64 = read_xmm64s(r); + let result: reg64 = reg64 { f64_0: [destination.f64_0[0] - source.f64_0[0]], }; write_xmm64(r, result); } #[no_mangle] -pub unsafe fn instr_F20F5C_reg(mut r1: i32, mut r2: i32) { instr_F20F5C(read_xmm64s(r1), r2); } +pub unsafe fn instr_F20F5C_reg(r1: i32, r2: i32) { instr_F20F5C(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F5C_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F20F5C_mem(addr: i32, r: i32) { instr_F20F5C(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F5C(mut source: f32, mut r: i32) { +pub unsafe fn instr_F30F5C(source: f32, r: i32) { // subss xmm, xmm/mem32 - let mut destination: f32 = read_xmm_f32(r); - let mut result: f32 = destination - source; + let destination: f32 = read_xmm_f32(r); + let result: f32 = destination - source; write_xmm_f32(r, result); } #[no_mangle] -pub unsafe fn instr_F30F5C_reg(mut r1: i32, mut r2: i32) { instr_F30F5C(read_xmm_f32(r1), r2); } +pub unsafe fn instr_F30F5C_reg(r1: i32, r2: i32) { instr_F30F5C(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F5C_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F30F5C_mem(addr: i32, r: i32) { instr_F30F5C(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_0F5D(mut source: reg128, mut r: i32) { +pub unsafe fn instr_0F5D(source: reg128, r: i32) { // minps xmm, xmm/mem128 - let mut destination: reg128 = read_xmm128s(r); - let mut result: reg128 = reg128 { + let destination: reg128 = read_xmm128s(r); + let result: reg128 = reg128 { f32_0: [ sse_min(destination.f32_0[0] as f64, source.f32_0[0] as f64) as f32, sse_min(destination.f32_0[1] as f64, source.f32_0[1] as f64) as f32, @@ -6129,16 +6096,16 @@ pub unsafe fn instr_0F5D(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0F5D_reg(mut r1: i32, mut r2: i32) { instr_0F5D(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F5D_reg(r1: i32, r2: i32) { instr_0F5D(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F5D_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F5D_mem(addr: i32, r: i32) { instr_0F5D(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F5D(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F5D(source: reg128, r: i32) { // minpd xmm, xmm/mem128 - let mut destination: reg128 = read_xmm128s(r); - let mut result: reg128 = reg128 { + let destination: reg128 = read_xmm128s(r); + let result: reg128 = reg128 { f64_0: [ sse_min(destination.f64_0[0], source.f64_0[0]), sse_min(destination.f64_0[1], source.f64_0[1]), @@ -6147,44 +6114,44 @@ pub unsafe fn instr_660F5D(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F5D_reg(mut r1: i32, mut r2: i32) { instr_660F5D(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F5D_reg(r1: i32, r2: i32) { instr_660F5D(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F5D_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F5D_mem(addr: i32, r: i32) { instr_660F5D(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20F5D(mut source: reg64, mut r: i32) { +pub unsafe fn instr_F20F5D(source: reg64, r: i32) { // minsd xmm, xmm/mem64 - let mut destination: reg64 = read_xmm64s(r); - let mut result: reg64 = reg64 { + let destination: reg64 = read_xmm64s(r); + let result: reg64 = reg64 { f64_0: [sse_min(destination.f64_0[0], source.f64_0[0])], }; write_xmm64(r, result); } #[no_mangle] -pub unsafe fn instr_F20F5D_reg(mut r1: i32, mut r2: i32) { instr_F20F5D(read_xmm64s(r1), r2); } +pub unsafe fn instr_F20F5D_reg(r1: i32, r2: i32) { instr_F20F5D(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F5D_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F20F5D_mem(addr: i32, r: i32) { instr_F20F5D(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F5D(mut source: f32, mut r: i32) { +pub unsafe fn instr_F30F5D(source: f32, r: i32) { // minss xmm, xmm/mem32 - let mut destination: f32 = read_xmm_f32(r); - let mut result: f32 = sse_min(destination as f64, source as f64) as f32; + let destination: f32 = read_xmm_f32(r); + let result: f32 = sse_min(destination as f64, source as f64) as f32; write_xmm_f32(r, result); } #[no_mangle] -pub unsafe fn instr_F30F5D_reg(mut r1: i32, mut r2: i32) { instr_F30F5D(read_xmm_f32(r1), r2); } +pub unsafe fn instr_F30F5D_reg(r1: i32, r2: i32) { instr_F30F5D(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F5D_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F30F5D_mem(addr: i32, r: i32) { instr_F30F5D(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_0F5E(mut source: reg128, mut r: i32) { +pub unsafe fn instr_0F5E(source: reg128, r: i32) { // divps xmm, xmm/mem128 - let mut destination: reg128 = read_xmm128s(r); - let mut result: reg128 = reg128 { + let destination: reg128 = read_xmm128s(r); + let result: reg128 = reg128 { f32_0: [ destination.f32_0[0] / source.f32_0[0], destination.f32_0[1] / source.f32_0[1], @@ -6195,16 +6162,16 @@ pub unsafe fn instr_0F5E(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0F5E_reg(mut r1: i32, mut r2: i32) { instr_0F5E(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F5E_reg(r1: i32, r2: i32) { instr_0F5E(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F5E_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F5E_mem(addr: i32, r: i32) { instr_0F5E(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F5E(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F5E(source: reg128, r: i32) { // divpd xmm, xmm/mem128 - let mut destination: reg128 = read_xmm128s(r); - let mut result: reg128 = reg128 { + let destination: reg128 = read_xmm128s(r); + let result: reg128 = reg128 { f64_0: [ destination.f64_0[0] / source.f64_0[0], destination.f64_0[1] / source.f64_0[1], @@ -6213,44 +6180,44 @@ pub unsafe fn instr_660F5E(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F5E_reg(mut r1: i32, mut r2: i32) { instr_660F5E(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F5E_reg(r1: i32, r2: i32) { instr_660F5E(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F5E_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F5E_mem(addr: i32, r: i32) { instr_660F5E(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20F5E(mut source: reg64, mut r: i32) { +pub unsafe fn instr_F20F5E(source: reg64, r: i32) { // divsd xmm, xmm/mem64 - let mut destination: reg64 = read_xmm64s(r); - let mut result: reg64 = reg64 { + let destination: reg64 = read_xmm64s(r); + let result: reg64 = reg64 { f64_0: [destination.f64_0[0] / source.f64_0[0]], }; write_xmm64(r, result); } #[no_mangle] -pub unsafe fn instr_F20F5E_reg(mut r1: i32, mut r2: i32) { instr_F20F5E(read_xmm64s(r1), r2); } +pub unsafe fn instr_F20F5E_reg(r1: i32, r2: i32) { instr_F20F5E(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F5E_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F20F5E_mem(addr: i32, r: i32) { instr_F20F5E(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F5E(mut source: f32, mut r: i32) { +pub unsafe fn instr_F30F5E(source: f32, r: i32) { // divss xmm, xmm/mem32 - let mut destination: f32 = read_xmm_f32(r); - let mut result: f32 = destination / source; + let destination: f32 = read_xmm_f32(r); + let result: f32 = destination / source; write_xmm_f32(r, result); } #[no_mangle] -pub unsafe fn instr_F30F5E_reg(mut r1: i32, mut r2: i32) { instr_F30F5E(read_xmm_f32(r1), r2); } +pub unsafe fn instr_F30F5E_reg(r1: i32, r2: i32) { instr_F30F5E(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F5E_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F30F5E_mem(addr: i32, r: i32) { instr_F30F5E(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_0F5F(mut source: reg128, mut r: i32) { +pub unsafe fn instr_0F5F(source: reg128, r: i32) { // maxps xmm, xmm/mem128 - let mut destination: reg128 = read_xmm128s(r); - let mut result: reg128 = reg128 { + let destination: reg128 = read_xmm128s(r); + let result: reg128 = reg128 { f32_0: [ sse_max(destination.f32_0[0] as f64, source.f32_0[0] as f64) as f32, sse_max(destination.f32_0[1] as f64, source.f32_0[1] as f64) as f32, @@ -6261,16 +6228,16 @@ pub unsafe fn instr_0F5F(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0F5F_reg(mut r1: i32, mut r2: i32) { instr_0F5F(read_xmm128s(r1), r2); } +pub unsafe fn instr_0F5F_reg(r1: i32, r2: i32) { instr_0F5F(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_0F5F_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_0F5F_mem(addr: i32, r: i32) { instr_0F5F(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_660F5F(mut source: reg128, mut r: i32) { +pub unsafe fn instr_660F5F(source: reg128, r: i32) { // maxpd xmm, xmm/mem128 - let mut destination: reg128 = read_xmm128s(r); - let mut result: reg128 = reg128 { + let destination: reg128 = read_xmm128s(r); + let result: reg128 = reg128 { f64_0: [ sse_max(destination.f64_0[0], source.f64_0[0]), sse_max(destination.f64_0[1], source.f64_0[1]), @@ -6279,44 +6246,44 @@ pub unsafe fn instr_660F5F(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660F5F_reg(mut r1: i32, mut r2: i32) { instr_660F5F(read_xmm128s(r1), r2); } +pub unsafe fn instr_660F5F_reg(r1: i32, r2: i32) { instr_660F5F(read_xmm128s(r1), r2); } #[no_mangle] -pub unsafe fn instr_660F5F_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_660F5F_mem(addr: i32, r: i32) { instr_660F5F(return_on_pagefault!(safe_read128s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F20F5F(mut source: reg64, mut r: i32) { +pub unsafe fn instr_F20F5F(source: reg64, r: i32) { // maxsd xmm, xmm/mem64 - let mut destination: reg64 = read_xmm64s(r); - let mut result: reg64 = reg64 { + let destination: reg64 = read_xmm64s(r); + let result: reg64 = reg64 { f64_0: [sse_max(destination.f64_0[0], source.f64_0[0])], }; write_xmm64(r, result); } #[no_mangle] -pub unsafe fn instr_F20F5F_reg(mut r1: i32, mut r2: i32) { instr_F20F5F(read_xmm64s(r1), r2); } +pub unsafe fn instr_F20F5F_reg(r1: i32, r2: i32) { instr_F20F5F(read_xmm64s(r1), r2); } #[no_mangle] -pub unsafe fn instr_F20F5F_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F20F5F_mem(addr: i32, r: i32) { instr_F20F5F(return_on_pagefault!(safe_read64s(addr)), r); } #[no_mangle] -pub unsafe fn instr_F30F5F(mut source: f32, mut r: i32) { +pub unsafe fn instr_F30F5F(source: f32, r: i32) { // maxss xmm, xmm/mem32 - let mut destination: f32 = read_xmm_f32(r); - let mut result: f32 = sse_max(destination as f64, source as f64) as f32; + let destination: f32 = read_xmm_f32(r); + let result: f32 = sse_max(destination as f64, source as f64) as f32; write_xmm_f32(r, result); } #[no_mangle] -pub unsafe fn instr_F30F5F_reg(mut r1: i32, mut r2: i32) { instr_F30F5F(read_xmm_f32(r1), r2); } +pub unsafe fn instr_F30F5F_reg(r1: i32, r2: i32) { instr_F30F5F(read_xmm_f32(r1), r2); } #[no_mangle] -pub unsafe fn instr_F30F5F_mem(mut addr: i32, mut r: i32) { +pub unsafe fn instr_F30F5F_mem(addr: i32, r: i32) { instr_F30F5F(return_on_pagefault!(fpu_load_m32(addr)) as f32, r); } #[no_mangle] -pub unsafe fn instr_0FC2(mut source: reg128, mut r: i32, mut imm8: i32) { +pub unsafe fn instr_0FC2(source: reg128, r: i32, imm8: i32) { // cmpps xmm, xmm/m128 - let mut destination: reg128 = read_xmm128s(r); - let mut result: reg128 = reg128 { + let destination: reg128 = read_xmm128s(r); + let result: reg128 = reg128 { i32_0: [ if 0 != sse_comparison(imm8, destination.f32_0[0] as f64, source.f32_0[0] as f64) as i32 { @@ -6351,18 +6318,16 @@ pub unsafe fn instr_0FC2(mut source: reg128, mut r: i32, mut imm8: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_0FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) { - instr_0FC2(read_xmm128s(r1), r2, imm); -} +pub unsafe fn instr_0FC2_reg(r1: i32, r2: i32, imm: i32) { instr_0FC2(read_xmm128s(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_0FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr_0FC2_mem(addr: i32, r: i32, imm: i32) { instr_0FC2(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] -pub unsafe fn instr_660FC2(mut source: reg128, mut r: i32, mut imm8: i32) { +pub unsafe fn instr_660FC2(source: reg128, r: i32, imm8: i32) { // cmppd xmm, xmm/m128 - let mut destination: reg128 = read_xmm128s(r); - let mut result: reg128 = reg128 { + let destination: reg128 = read_xmm128s(r); + let result: reg128 = reg128 { i64_0: [ (if 0 != sse_comparison(imm8, destination.f64_0[0], source.f64_0[0]) as i32 { -1 @@ -6381,18 +6346,18 @@ pub unsafe fn instr_660FC2(mut source: reg128, mut r: i32, mut imm8: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn instr_660FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) { +pub unsafe fn instr_660FC2_reg(r1: i32, r2: i32, imm: i32) { instr_660FC2(read_xmm128s(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_660FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr_660FC2_mem(addr: i32, r: i32, imm: i32) { instr_660FC2(return_on_pagefault!(safe_read128s(addr)), r, imm); } #[no_mangle] -pub unsafe fn instr_F20FC2(mut source: reg64, mut r: i32, mut imm8: i32) { +pub unsafe fn instr_F20FC2(source: reg64, r: i32, imm8: i32) { // cmpsd xmm, xmm/m64 - let mut destination: reg64 = read_xmm64s(r); - let mut result: reg64 = reg64 { + let destination: reg64 = read_xmm64s(r); + let result: reg64 = reg64 { i64_0: [ (if 0 != sse_comparison(imm8, destination.f64_0[0], source.f64_0[0]) as i32 { -1 @@ -6405,18 +6370,18 @@ pub unsafe fn instr_F20FC2(mut source: reg64, mut r: i32, mut imm8: i32) { write_xmm64(r, result); } #[no_mangle] -pub unsafe fn instr_F20FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) { +pub unsafe fn instr_F20FC2_reg(r1: i32, r2: i32, imm: i32) { instr_F20FC2(read_xmm64s(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_F20FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr_F20FC2_mem(addr: i32, r: i32, imm: i32) { instr_F20FC2(return_on_pagefault!(safe_read64s(addr)), r, imm); } #[no_mangle] -pub unsafe fn instr_F30FC2(mut source: f32, mut r: i32, mut imm8: i32) { +pub unsafe fn instr_F30FC2(source: f32, r: i32, imm8: i32) { // cmpss xmm, xmm/m32 - let mut destination: f32 = read_xmm_f32(r); - let mut result: i32 = if 0 != sse_comparison(imm8, destination as f64, source as f64) as i32 { + let destination: f32 = read_xmm_f32(r); + let result: i32 = if 0 != sse_comparison(imm8, destination as f64, source as f64) as i32 { -1 } else { @@ -6425,10 +6390,10 @@ pub unsafe fn instr_F30FC2(mut source: f32, mut r: i32, mut imm8: i32) { write_xmm32(r, result); } #[no_mangle] -pub unsafe fn instr_F30FC2_reg(mut r1: i32, mut r2: i32, mut imm: i32) { +pub unsafe fn instr_F30FC2_reg(r1: i32, r2: i32, imm: i32) { instr_F30FC2(read_xmm_f32(r1), r2, imm); } #[no_mangle] -pub unsafe fn instr_F30FC2_mem(mut addr: i32, mut r: i32, mut imm: i32) { +pub unsafe fn instr_F30FC2_mem(addr: i32, r: i32, imm: i32) { instr_F30FC2(return_on_pagefault!(fpu_load_m32(addr)) as f32, r, imm); } diff --git a/src/rust/cpu2/memory.rs b/src/rust/cpu2/memory.rs index f2888274..febdac56 100644 --- a/src/rust/cpu2/memory.rs +++ b/src/rust/cpu2/memory.rs @@ -1,5 +1,3 @@ -#![allow(unused_mut)] - extern "C" { #[no_mangle] fn mmap_read8(addr: u32) -> i32; @@ -25,7 +23,7 @@ use page::Page; const USE_A20: bool = false; #[no_mangle] -pub unsafe fn in_mapped_range(mut addr: u32) -> bool { +pub unsafe fn in_mapped_range(addr: u32) -> bool { return addr >= 655360 as u32 && addr < 786432 as u32 || addr >= *memory_size; } @@ -125,7 +123,7 @@ pub unsafe fn read128(mut addr: u32) -> reg128 { } #[no_mangle] -pub unsafe fn write8(mut addr: u32, mut value: i32) { +pub unsafe fn write8(mut addr: u32, value: i32) { if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK as u32 } @@ -143,7 +141,7 @@ pub unsafe fn write8_no_mmap_or_dirty_check(addr: u32, value: i32) { } #[no_mangle] -pub unsafe fn write16(mut addr: u32, mut value: i32) { +pub unsafe fn write16(mut addr: u32, value: i32) { if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK as u32 } @@ -156,12 +154,12 @@ pub unsafe fn write16(mut addr: u32, mut value: i32) { }; } #[no_mangle] -pub unsafe fn write_aligned16(mut addr: u32, mut value: u32) { +pub unsafe fn write_aligned16(mut addr: u32, value: u32) { dbg_assert!(addr < 2147483648); if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK16 as u32 } - let mut phys_addr: u32 = addr << 1; + let phys_addr: u32 = addr << 1; if in_mapped_range(phys_addr) { mmap_write16(phys_addr, value as i32); } @@ -171,7 +169,7 @@ pub unsafe fn write_aligned16(mut addr: u32, mut value: u32) { }; } #[no_mangle] -pub unsafe fn write32(mut addr: u32, mut value: i32) { +pub unsafe fn write32(mut addr: u32, value: i32) { if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK as u32 } @@ -189,12 +187,12 @@ pub unsafe fn write_aligned32_no_mmap_or_dirty_check(addr: u32, value: i32) { } #[no_mangle] -pub unsafe fn write_aligned32(mut addr: u32, mut value: i32) { +pub unsafe fn write_aligned32(mut addr: u32, value: i32) { dbg_assert!(addr < 1073741824 as u32); if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK32 as u32 } - let mut phys_addr: u32 = addr << 2; + let phys_addr: u32 = addr << 2; if in_mapped_range(phys_addr) { mmap_write32(phys_addr, value); } @@ -204,7 +202,7 @@ pub unsafe fn write_aligned32(mut addr: u32, mut value: i32) { }; } #[no_mangle] -pub unsafe fn write64(mut addr: u32, mut value: i64) { +pub unsafe fn write64(mut addr: u32, value: i64) { if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK as u32 } @@ -221,7 +219,7 @@ pub unsafe fn write64(mut addr: u32, mut value: i64) { }; } #[no_mangle] -pub unsafe fn write128(mut addr: u32, mut value: reg128) { +pub unsafe fn write128(mut addr: u32, value: reg128) { if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK as u32 } diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index 01c3b746..61df893d 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -1,5 +1,3 @@ -#![allow(unused_mut)] - use cpu2::cpu::*; use cpu2::fpu::{fpu_load_m80, fpu_load_status_word, fpu_set_status_word, fpu_store_m80}; use cpu2::global_pointers::*; @@ -98,57 +96,53 @@ pub unsafe fn test_nl() -> bool { return !test_l(); } #[no_mangle] pub unsafe fn test_nle() -> bool { return !test_le(); } #[no_mangle] -pub unsafe fn jmp_rel16(mut rel16: i32) { - let mut cs_offset: i32 = get_seg_cs(); +pub unsafe fn jmp_rel16(rel16: i32) { + let cs_offset: i32 = get_seg_cs(); // limit ip to 16 bit *instruction_pointer = cs_offset + (*instruction_pointer - cs_offset + rel16 & 65535); } #[no_mangle] -pub unsafe fn jmpcc16(mut condition: bool, mut imm16: i32) { +pub unsafe fn jmpcc16(condition: bool, imm16: i32) { if condition { jmp_rel16(imm16); }; } #[no_mangle] -pub unsafe fn jmpcc32(mut condition: bool, mut imm32: i32) { +pub unsafe fn jmpcc32(condition: bool, imm32: i32) { if condition { *instruction_pointer += imm32 }; } #[no_mangle] -pub unsafe fn loope16(mut imm8s: i32) { - jmpcc16(0 != decr_ecx_asize() && 0 != getzf() as i32, imm8s); -} +pub unsafe fn loope16(imm8s: i32) { jmpcc16(0 != decr_ecx_asize() && 0 != getzf() as i32, imm8s); } #[no_mangle] -pub unsafe fn loopne16(mut imm8s: i32) { jmpcc16(0 != decr_ecx_asize() && !getzf(), imm8s); } +pub unsafe fn loopne16(imm8s: i32) { jmpcc16(0 != decr_ecx_asize() && !getzf(), imm8s); } #[no_mangle] -pub unsafe fn loop16(mut imm8s: i32) { jmpcc16(0 != decr_ecx_asize(), imm8s); } +pub unsafe fn loop16(imm8s: i32) { jmpcc16(0 != decr_ecx_asize(), imm8s); } #[no_mangle] -pub unsafe fn jcxz16(mut imm8s: i32) { jmpcc16(get_reg_asize(ECX) == 0, imm8s); } +pub unsafe fn jcxz16(imm8s: i32) { jmpcc16(get_reg_asize(ECX) == 0, imm8s); } #[no_mangle] -pub unsafe fn loope32(mut imm8s: i32) { - jmpcc32(0 != decr_ecx_asize() && 0 != getzf() as i32, imm8s); -} +pub unsafe fn loope32(imm8s: i32) { jmpcc32(0 != decr_ecx_asize() && 0 != getzf() as i32, imm8s); } #[no_mangle] -pub unsafe fn loopne32(mut imm8s: i32) { jmpcc32(0 != decr_ecx_asize() && !getzf(), imm8s); } +pub unsafe fn loopne32(imm8s: i32) { jmpcc32(0 != decr_ecx_asize() && !getzf(), imm8s); } #[no_mangle] -pub unsafe fn loop32(mut imm8s: i32) { jmpcc32(0 != decr_ecx_asize(), imm8s); } +pub unsafe fn loop32(imm8s: i32) { jmpcc32(0 != decr_ecx_asize(), imm8s); } #[no_mangle] -pub unsafe fn jcxz32(mut imm8s: i32) { jmpcc32(get_reg_asize(ECX) == 0, imm8s); } +pub unsafe fn jcxz32(imm8s: i32) { jmpcc32(get_reg_asize(ECX) == 0, imm8s); } #[no_mangle] -pub unsafe fn cmovcc16(mut condition: bool, mut value: i32, mut r: i32) { +pub unsafe fn cmovcc16(condition: bool, value: i32, r: i32) { if condition { write_reg16(r, value); }; } #[no_mangle] -pub unsafe fn cmovcc32(mut condition: bool, mut value: i32, mut r: i32) { +pub unsafe fn cmovcc32(condition: bool, value: i32, r: i32) { if condition { write_reg32(r, value); }; } #[no_mangle] -pub unsafe fn get_stack_pointer(mut offset: i32) -> i32 { +pub unsafe fn get_stack_pointer(offset: i32) -> i32 { if *stack_size_32 { return get_seg_ss() + *reg32s.offset(ESP as isize) + offset; } @@ -157,7 +151,7 @@ pub unsafe fn get_stack_pointer(mut offset: i32) -> i32 { }; } #[no_mangle] -pub unsafe fn adjust_stack_reg(mut adjustment: i32) { +pub unsafe fn adjust_stack_reg(adjustment: i32) { if *stack_size_32 { *reg32s.offset(ESP as isize) += adjustment; } @@ -167,37 +161,37 @@ pub unsafe fn adjust_stack_reg(mut adjustment: i32) { } #[no_mangle] -pub unsafe fn push16_ss16(mut imm16: i32) -> OrPageFault<()> { - let mut sp: i32 = get_seg_ss() + (*reg16.offset(SP as isize) as i32 - 2 & 65535); +pub unsafe fn push16_ss16(imm16: i32) -> OrPageFault<()> { + let sp: i32 = get_seg_ss() + (*reg16.offset(SP as isize) as i32 - 2 & 65535); safe_write16(sp, imm16)?; *reg16.offset(SP as isize) -= 2; Ok(()) } #[no_mangle] -pub unsafe fn push16_ss32(mut imm16: i32) -> OrPageFault<()> { - let mut sp: i32 = get_seg_ss() + *reg32s.offset(ESP as isize) - 2; +pub unsafe fn push16_ss32(imm16: i32) -> OrPageFault<()> { + let sp: i32 = get_seg_ss() + *reg32s.offset(ESP as isize) - 2; safe_write16(sp, imm16)?; *reg32s.offset(ESP as isize) -= 2; Ok(()) } #[no_mangle] -pub unsafe fn push16_ss16_jit(mut imm16: i32) { return_on_pagefault!(push16_ss16(imm16)) } +pub unsafe fn push16_ss16_jit(imm16: i32) { return_on_pagefault!(push16_ss16(imm16)) } #[no_mangle] -pub unsafe fn push16_ss32_jit(mut imm16: i32) { return_on_pagefault!(push16_ss32(imm16)) } +pub unsafe fn push16_ss32_jit(imm16: i32) { return_on_pagefault!(push16_ss32(imm16)) } #[no_mangle] -pub unsafe fn push16_ss16_mem(mut addr: i32) -> OrPageFault<()> { push16_ss16(safe_read16(addr)?) } +pub unsafe fn push16_ss16_mem(addr: i32) -> OrPageFault<()> { push16_ss16(safe_read16(addr)?) } #[no_mangle] -pub unsafe fn push16_ss32_mem(mut addr: i32) -> OrPageFault<()> { push16_ss32(safe_read16(addr)?) } +pub unsafe fn push16_ss32_mem(addr: i32) -> OrPageFault<()> { push16_ss32(safe_read16(addr)?) } #[no_mangle] -pub unsafe fn push16_ss16_mem_jit(mut addr: i32) { return_on_pagefault!(push16_ss16_mem(addr)) } +pub unsafe fn push16_ss16_mem_jit(addr: i32) { return_on_pagefault!(push16_ss16_mem(addr)) } #[no_mangle] -pub unsafe fn push16_ss32_mem_jit(mut addr: i32) { return_on_pagefault!(push16_ss32_mem(addr)) } +pub unsafe fn push16_ss32_mem_jit(addr: i32) { return_on_pagefault!(push16_ss32_mem(addr)) } #[no_mangle] -pub unsafe fn push16(mut imm16: i32) -> OrPageFault<()> { +pub unsafe fn push16(imm16: i32) -> OrPageFault<()> { if *stack_size_32 { push16_ss32(imm16) } @@ -207,37 +201,37 @@ pub unsafe fn push16(mut imm16: i32) -> OrPageFault<()> { } #[no_mangle] -pub unsafe fn push32_ss16(mut imm32: i32) -> OrPageFault<()> { - let mut new_sp: i32 = *reg16.offset(SP as isize) as i32 - 4 & 65535; +pub unsafe fn push32_ss16(imm32: i32) -> OrPageFault<()> { + let new_sp: i32 = *reg16.offset(SP as isize) as i32 - 4 & 65535; safe_write32(get_seg_ss() + new_sp, imm32)?; *reg16.offset(SP as isize) = new_sp as u16; Ok(()) } #[no_mangle] -pub unsafe fn push32_ss32(mut imm32: i32) -> OrPageFault<()> { - let mut new_esp: i32 = *reg32s.offset(ESP as isize) - 4; +pub unsafe fn push32_ss32(imm32: i32) -> OrPageFault<()> { + let new_esp: i32 = *reg32s.offset(ESP as isize) - 4; safe_write32(get_seg_ss() + new_esp, imm32)?; *reg32s.offset(ESP as isize) = new_esp; Ok(()) } #[no_mangle] -pub unsafe fn push32_ss16_jit(mut imm32: i32) { return_on_pagefault!(push32_ss16(imm32)) } +pub unsafe fn push32_ss16_jit(imm32: i32) { return_on_pagefault!(push32_ss16(imm32)) } #[no_mangle] -pub unsafe fn push32_ss32_jit(mut imm32: i32) { return_on_pagefault!(push32_ss32(imm32)) } +pub unsafe fn push32_ss32_jit(imm32: i32) { return_on_pagefault!(push32_ss32(imm32)) } #[no_mangle] -pub unsafe fn push32_ss16_mem(mut addr: i32) -> OrPageFault<()> { push32_ss16(safe_read32s(addr)?) } +pub unsafe fn push32_ss16_mem(addr: i32) -> OrPageFault<()> { push32_ss16(safe_read32s(addr)?) } #[no_mangle] -pub unsafe fn push32_ss32_mem(mut addr: i32) -> OrPageFault<()> { push32_ss32(safe_read32s(addr)?) } +pub unsafe fn push32_ss32_mem(addr: i32) -> OrPageFault<()> { push32_ss32(safe_read32s(addr)?) } #[no_mangle] -pub unsafe fn push32_ss16_mem_jit(mut addr: i32) { return_on_pagefault!(push32_ss16_mem(addr)) } +pub unsafe fn push32_ss16_mem_jit(addr: i32) { return_on_pagefault!(push32_ss16_mem(addr)) } #[no_mangle] -pub unsafe fn push32_ss32_mem_jit(mut addr: i32) { return_on_pagefault!(push32_ss32_mem(addr)) } +pub unsafe fn push32_ss32_mem_jit(addr: i32) { return_on_pagefault!(push32_ss32_mem(addr)) } #[no_mangle] -pub unsafe fn push32(mut imm32: i32) -> OrPageFault<()> { +pub unsafe fn push32(imm32: i32) -> OrPageFault<()> { if *stack_size_32 { push32_ss32(imm32) } @@ -256,15 +250,15 @@ pub unsafe fn pop16() -> OrPageFault { } #[no_mangle] pub unsafe fn pop16_ss16() -> OrPageFault { - let mut sp: i32 = get_seg_ss() + *reg16.offset(SP as isize) as i32; - let mut result: i32 = safe_read16(sp)?; + let sp: i32 = get_seg_ss() + *reg16.offset(SP as isize) as i32; + let result: i32 = safe_read16(sp)?; *reg16.offset(SP as isize) += 2; Ok(result) } #[no_mangle] pub unsafe fn pop16_ss32() -> OrPageFault { - let mut esp: i32 = get_seg_ss() + *reg32s.offset(ESP as isize); - let mut result: i32 = safe_read16(esp)?; + let esp: i32 = get_seg_ss() + *reg32s.offset(ESP as isize); + let result: i32 = safe_read16(esp)?; *reg32s.offset(ESP as isize) += 2; Ok(result) } @@ -279,21 +273,21 @@ pub unsafe fn pop32s() -> OrPageFault { } #[no_mangle] pub unsafe fn pop32s_ss16() -> OrPageFault { - let mut sp: i32 = *reg16.offset(SP as isize) as i32; - let mut result: i32 = safe_read32s(get_seg_ss() + sp)?; + let sp: i32 = *reg16.offset(SP as isize) as i32; + let result: i32 = safe_read32s(get_seg_ss() + sp)?; *reg16.offset(SP as isize) = (sp + 4) as u16; Ok(result) } #[no_mangle] pub unsafe fn pop32s_ss32() -> OrPageFault { - let mut esp: i32 = *reg32s.offset(ESP as isize); - let mut result: i32 = safe_read32s(get_seg_ss() + esp)?; + let esp: i32 = *reg32s.offset(ESP as isize); + let result: i32 = safe_read32s(get_seg_ss() + esp)?; *reg32s.offset(ESP as isize) = esp + 4; Ok(result) } #[no_mangle] pub unsafe fn pusha16() { - let mut temp: u16 = *reg16.offset(SP as isize); + let temp: u16 = *reg16.offset(SP as isize); // make sure we don't get a pagefault after having // pushed several registers already return_on_pagefault!(writable_or_pagefault(get_stack_pointer(-16), 16)); @@ -308,7 +302,7 @@ pub unsafe fn pusha16() { } #[no_mangle] pub unsafe fn pusha32() { - let mut temp: i32 = *reg32s.offset(ESP as isize); + let temp: i32 = *reg32s.offset(ESP as isize); return_on_pagefault!(writable_or_pagefault(get_stack_pointer(-32), 32)); push32(*reg32s.offset(EAX as isize)).unwrap(); push32(*reg32s.offset(ECX as isize)).unwrap(); @@ -320,15 +314,15 @@ pub unsafe fn pusha32() { push32(*reg32s.offset(EDI as isize)).unwrap(); } #[no_mangle] -pub unsafe fn setcc_reg(mut condition: bool, mut r: i32) { +pub unsafe fn setcc_reg(condition: bool, r: i32) { write_reg8(r, if 0 != condition as i32 { 1 } else { 0 }); } #[no_mangle] -pub unsafe fn setcc_mem(mut condition: bool, mut addr: i32) { +pub unsafe fn setcc_mem(condition: bool, addr: i32) { return_on_pagefault!(safe_write8(addr, if 0 != condition as i32 { 1 } else { 0 })); } #[no_mangle] -pub unsafe fn fxsave(mut addr: i32) { +pub unsafe fn fxsave(addr: i32) { return_on_pagefault!(writable_or_pagefault(addr as i32, 512)); safe_write16(addr.wrapping_add(0) as i32, *fpu_control_word).unwrap(); safe_write16(addr.wrapping_add(2) as i32, fpu_load_status_word()).unwrap(); @@ -366,11 +360,11 @@ pub unsafe fn fxsave(mut addr: i32) { } } #[no_mangle] -pub unsafe fn fxrstor(mut addr: i32) { +pub unsafe fn fxrstor(addr: i32) { // TODO: Add readable_or_pagefault return_on_pagefault!(translate_address_read(addr)); return_on_pagefault!(translate_address_read(addr.wrapping_add(511))); - let mut new_mxcsr: i32 = safe_read32s(addr.wrapping_add(24) as i32).unwrap(); + let new_mxcsr: i32 = safe_read32s(addr.wrapping_add(24) as i32).unwrap(); if 0 != new_mxcsr & !MXCSR_MASK { dbg_log!("#gp Invalid mxcsr bits"); trigger_gp_non_raising(0); @@ -417,32 +411,32 @@ pub unsafe fn fxrstor(mut addr: i32) { }; } #[no_mangle] -pub unsafe fn xchg8(mut data: i32, mut r8: i32) -> i32 { - let mut tmp: i32 = *reg8.offset(r8 as isize) as i32; +pub unsafe fn xchg8(data: i32, r8: i32) -> i32 { + let tmp: i32 = *reg8.offset(r8 as isize) as i32; *reg8.offset(r8 as isize) = data as u8; return tmp; } #[no_mangle] -pub unsafe fn xchg16(mut data: i32, mut r16: i32) -> i32 { - let mut tmp: i32 = *reg16.offset(r16 as isize) as i32; +pub unsafe fn xchg16(data: i32, r16: i32) -> i32 { + let tmp: i32 = *reg16.offset(r16 as isize) as i32; *reg16.offset(r16 as isize) = data as u16; return tmp; } #[no_mangle] -pub unsafe fn xchg16r(mut r16: i32) { - let mut tmp: i32 = *reg16.offset(AX as isize) as i32; +pub unsafe fn xchg16r(r16: i32) { + let tmp: i32 = *reg16.offset(AX as isize) as i32; *reg16.offset(AX as isize) = *reg16.offset(r16 as isize); *reg16.offset(r16 as isize) = tmp as u16; } #[no_mangle] -pub unsafe fn xchg32(mut data: i32, mut r32: i32) -> i32 { - let mut tmp: i32 = *reg32s.offset(r32 as isize); +pub unsafe fn xchg32(data: i32, r32: i32) -> i32 { + let tmp: i32 = *reg32s.offset(r32 as isize); *reg32s.offset(r32 as isize) = data; return tmp; } #[no_mangle] -pub unsafe fn xchg32r(mut r32: i32) { - let mut tmp: i32 = *reg32s.offset(EAX as isize); +pub unsafe fn xchg32r(r32: i32) { + let tmp: i32 = *reg32s.offset(EAX as isize); *reg32s.offset(EAX as isize) = *reg32s.offset(r32 as isize); *reg32s.offset(r32 as isize) = tmp; } diff --git a/src/rust/cpu2/modrm.rs b/src/rust/cpu2/modrm.rs index dc7887c4..3698ef9a 100644 --- a/src/rust/cpu2/modrm.rs +++ b/src/rust/cpu2/modrm.rs @@ -1,10 +1,8 @@ -#![allow(unused_mut)] - use cpu2::cpu::*; use cpu2::global_pointers::*; use paging::OrPageFault; -pub unsafe fn resolve_modrm16(mut modrm_byte: i32) -> OrPageFault { +pub unsafe fn resolve_modrm16(modrm_byte: i32) -> OrPageFault { Ok(match modrm_byte { 0 | 8 | 16 | 24 | 32 | 40 | 48 | 56 => get_seg_prefix_ds( *reg16.offset(BX as isize) as i32 + *reg16.offset(SI as isize) as i32 & 65535, @@ -91,8 +89,8 @@ pub unsafe fn resolve_modrm16(mut modrm_byte: i32) -> OrPageFault { }) } -pub unsafe fn resolve_modrm32_(mut modrm_byte: i32) -> OrPageFault { - let mut r: u8 = (modrm_byte & 7) as u8; +pub unsafe fn resolve_modrm32_(modrm_byte: i32) -> OrPageFault { + let r: u8 = (modrm_byte & 7) as u8; dbg_assert!(modrm_byte < 192); Ok(if r as i32 == 4 { if modrm_byte < 64 { @@ -136,13 +134,13 @@ pub unsafe fn resolve_modrm32_(mut modrm_byte: i32) -> OrPageFault { ) }) } -unsafe fn resolve_sib(mut mod_0: bool) -> OrPageFault { - let mut s; - let mut sib_byte: u8 = read_imm8()? as u8; - let mut r: u8 = (sib_byte as i32 & 7) as u8; - let mut m: u8 = (sib_byte as i32 >> 3 & 7) as u8; - let mut base; - let mut seg; +unsafe fn resolve_sib(mod_0: bool) -> OrPageFault { + let s; + let sib_byte: u8 = read_imm8()? as u8; + let r: u8 = (sib_byte as i32 & 7) as u8; + let m: u8 = (sib_byte as i32 >> 3 & 7) as u8; + let base; + let seg; if r as i32 == 4 { base = *reg32s.offset(ESP as isize); seg = SS @@ -161,7 +159,7 @@ unsafe fn resolve_sib(mut mod_0: bool) -> OrPageFault { base = *reg32s.offset(r as isize); seg = DS } - let mut offset; + let offset; if m as i32 == 4 { offset = 0 } @@ -172,7 +170,7 @@ unsafe fn resolve_sib(mut mod_0: bool) -> OrPageFault { Ok(get_seg_prefix(seg) + base + offset) } -pub unsafe fn resolve_modrm32(mut modrm_byte: i32) -> OrPageFault { +pub unsafe fn resolve_modrm32(modrm_byte: i32) -> OrPageFault { Ok(match modrm_byte { 0 | 8 | 16 | 24 | 32 | 40 | 48 | 56 => get_seg_prefix_ds(*reg32s.offset(EAX as isize)), 64 | 72 | 80 | 88 | 96 | 104 | 112 | 120 => { diff --git a/src/rust/cpu2/sse_instr.rs b/src/rust/cpu2/sse_instr.rs index f9127982..7ddc18e4 100644 --- a/src/rust/cpu2/sse_instr.rs +++ b/src/rust/cpu2/sse_instr.rs @@ -1,42 +1,40 @@ -#![allow(unused_mut)] - use cpu2::cpu::*; #[no_mangle] -pub unsafe fn mov_r_m64(mut addr: i32, mut r: i32) { +pub unsafe fn mov_r_m64(addr: i32, r: i32) { // mov* m64, mm - let mut data: reg64 = read_mmx64s(r); + let data: reg64 = read_mmx64s(r); return_on_pagefault!(safe_write64(addr, data.u64_0[0] as i64)); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn movl_r128_m64(mut addr: i32, mut r: i32) { +pub unsafe fn movl_r128_m64(addr: i32, r: i32) { // mov* m64, xmm - let mut data: reg64 = read_xmm64s(r); + let data: reg64 = read_xmm64s(r); return_on_pagefault!(safe_write64(addr, data.u64_0[0] as i64)); } #[no_mangle] -pub unsafe fn mov_r_r128(mut r1: i32, mut r2: i32) { +pub unsafe fn mov_r_r128(r1: i32, r2: i32) { // mov* xmm, xmm - let mut data: reg128 = read_xmm128s(r2); + let data: reg128 = read_xmm128s(r2); write_xmm_reg128(r1, data); } #[no_mangle] -pub unsafe fn mov_r_m128(mut addr: i32, mut r: i32) { +pub unsafe fn mov_r_m128(addr: i32, r: i32) { // mov* m128, xmm - let mut data: reg128 = read_xmm128s(r); + let data: reg128 = read_xmm128s(r); return_on_pagefault!(safe_write128(addr, data)); } #[no_mangle] -pub unsafe fn mov_rm_r128(mut source: reg128, mut r: i32) { +pub unsafe fn mov_rm_r128(source: reg128, r: i32) { // mov* xmm, xmm/m128 write_xmm_reg128(r, source); } #[no_mangle] -pub unsafe fn movh_m64_r128(mut addr: i32, mut r: i32) { +pub unsafe fn movh_m64_r128(addr: i32, r: i32) { // movhp* xmm, m64 - let mut data: reg64 = return_on_pagefault!(safe_read64s(addr)); - let mut orig: reg128 = read_xmm128s(r); + let data: reg64 = return_on_pagefault!(safe_read64s(addr)); + let orig: reg128 = read_xmm128s(r); write_xmm128( r, orig.u32_0[0] as i32, @@ -46,16 +44,16 @@ pub unsafe fn movh_m64_r128(mut addr: i32, mut r: i32) { ); } #[no_mangle] -pub unsafe fn movh_r128_m64(mut addr: i32, mut r: i32) { +pub unsafe fn movh_r128_m64(addr: i32, r: i32) { // movhp* m64, xmm - let mut data: reg128 = read_xmm128s(r); + let data: reg128 = read_xmm128s(r); return_on_pagefault!(safe_write64(addr, data.u64_0[1] as i64)); } #[no_mangle] -pub unsafe fn pand_r128(mut source: reg128, mut r: i32) { +pub unsafe fn pand_r128(source: reg128, r: i32) { // pand xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; @@ -64,10 +62,10 @@ pub unsafe fn pand_r128(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn pandn_r128(mut source: reg128, mut r: i32) { +pub unsafe fn pandn_r128(source: reg128, r: i32) { // pandn xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; @@ -76,10 +74,10 @@ pub unsafe fn pandn_r128(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn pxor_r128(mut source: reg128, mut r: i32) { +pub unsafe fn pxor_r128(source: reg128, r: i32) { // pxor xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; @@ -88,10 +86,10 @@ pub unsafe fn pxor_r128(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn por_r128(mut source: reg128, mut r: i32) { +pub unsafe fn por_r128(source: reg128, r: i32) { // por xmm, xmm/m128 // XXX: Aligned access or #gp - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; @@ -100,9 +98,9 @@ pub unsafe fn por_r128(mut source: reg128, mut r: i32) { write_xmm_reg128(r, result); } #[no_mangle] -pub unsafe fn psrlw_r64(mut r: i32, mut shift: u64) { +pub unsafe fn psrlw_r64(r: i32, shift: u64) { // psrlw mm, {shift} - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); let mut dword0: i32 = 0; let mut dword1: i32 = 0; if shift <= 15 { @@ -113,21 +111,21 @@ pub unsafe fn psrlw_r64(mut r: i32, mut shift: u64) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn psraw_r64(mut r: i32, mut shift: u64) { +pub unsafe fn psraw_r64(r: i32, shift: u64) { // psraw mm, {shift} - let mut destination: reg64 = read_mmx64s(r); - let mut shift_clamped: i32 = (if shift > 15 { 16 } else { shift }) as i32; - let mut dword0: i32 = destination.i16_0[0] as i32 >> shift_clamped & 65535 + let destination: reg64 = read_mmx64s(r); + let shift_clamped: i32 = (if shift > 15 { 16 } else { shift }) as i32; + let dword0: i32 = destination.i16_0[0] as i32 >> shift_clamped & 65535 | destination.i16_0[1] as i32 >> shift_clamped << 16; - let mut dword1: i32 = destination.i16_0[2] as i32 >> shift_clamped & 65535 + let dword1: i32 = destination.i16_0[2] as i32 >> shift_clamped & 65535 | destination.i16_0[3] as i32 >> shift_clamped << 16; write_mmx64(r, dword0, dword1); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn psllw_r64(mut r: i32, mut shift: u64) { +pub unsafe fn psllw_r64(r: i32, shift: u64) { // psllw mm, {shift} - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); let mut dword0: i32 = 0; let mut dword1: i32 = 0; if shift <= 15 { @@ -140,9 +138,9 @@ pub unsafe fn psllw_r64(mut r: i32, mut shift: u64) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn psrld_r64(mut r: i32, mut shift: u64) { +pub unsafe fn psrld_r64(r: i32, shift: u64) { // psrld mm, {shift} - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); let mut dword0: i32 = 0; let mut dword1: i32 = 0; if shift <= 31 { @@ -153,19 +151,19 @@ pub unsafe fn psrld_r64(mut r: i32, mut shift: u64) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn psrad_r64(mut r: i32, mut shift: u64) { +pub unsafe fn psrad_r64(r: i32, shift: u64) { // psrad mm, {shift} - let mut destination: reg64 = read_mmx64s(r); - let mut shift_clamped: i32 = (if shift > 31 { 31 } else { shift }) as i32; - let mut dword0: i32 = destination.i32_0[0] >> shift_clamped; - let mut dword1: i32 = destination.i32_0[1] >> shift_clamped; + let destination: reg64 = read_mmx64s(r); + let shift_clamped: i32 = (if shift > 31 { 31 } else { shift }) as i32; + let dword0: i32 = destination.i32_0[0] >> shift_clamped; + let dword1: i32 = destination.i32_0[1] >> shift_clamped; write_mmx64(r, dword0, dword1); transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn pslld_r64(mut r: i32, mut shift: u64) { +pub unsafe fn pslld_r64(r: i32, shift: u64) { // pslld mm, {shift} - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); let mut dword0: i32 = 0; let mut dword1: i32 = 0; if shift <= 31 { @@ -176,13 +174,13 @@ pub unsafe fn pslld_r64(mut r: i32, mut shift: u64) { transition_fpu_to_mmx(); } #[no_mangle] -pub unsafe fn psrlq_r64(mut r: i32, mut shift: u64) { +pub unsafe fn psrlq_r64(r: i32, shift: u64) { // psrlq mm, {shift} if shift == 0 { return; } else { - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); let mut result: reg64 = reg64 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0], }; @@ -195,9 +193,9 @@ pub unsafe fn psrlq_r64(mut r: i32, mut shift: u64) { }; } #[no_mangle] -pub unsafe fn psllq_r64(mut r: i32, mut shift: u64) { +pub unsafe fn psllq_r64(r: i32, shift: u64) { // psllq mm, {shift} - let mut destination: reg64 = read_mmx64s(r); + let destination: reg64 = read_mmx64s(r); if shift == 0 { return; } @@ -214,9 +212,9 @@ pub unsafe fn psllq_r64(mut r: i32, mut shift: u64) { }; } #[no_mangle] -pub unsafe fn psrlw_r128(mut r: i32, mut shift: u64) { +pub unsafe fn psrlw_r128(r: i32, shift: u64) { // psrlw xmm, {shift} - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut dword0: i32 = 0; let mut dword1: i32 = 0; let mut dword2: i32 = 0; @@ -230,24 +228,24 @@ pub unsafe fn psrlw_r128(mut r: i32, mut shift: u64) { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn psraw_r128(mut r: i32, mut shift: u64) { +pub unsafe fn psraw_r128(r: i32, shift: u64) { // psraw xmm, {shift} - let mut destination: reg128 = read_xmm128s(r); - let mut shift_clamped: i32 = (if shift > 15 { 16 } else { shift as u32 }) as i32; - let mut dword0: i32 = destination.i16_0[0] as i32 >> shift_clamped & 65535 + let destination: reg128 = read_xmm128s(r); + let shift_clamped: i32 = (if shift > 15 { 16 } else { shift as u32 }) as i32; + let dword0: i32 = destination.i16_0[0] as i32 >> shift_clamped & 65535 | destination.i16_0[1] as i32 >> shift_clamped << 16; - let mut dword1: i32 = destination.i16_0[2] as i32 >> shift_clamped & 65535 + let dword1: i32 = destination.i16_0[2] as i32 >> shift_clamped & 65535 | destination.i16_0[3] as i32 >> shift_clamped << 16; - let mut dword2: i32 = destination.i16_0[4] as i32 >> shift_clamped & 65535 + let dword2: i32 = destination.i16_0[4] as i32 >> shift_clamped & 65535 | destination.i16_0[5] as i32 >> shift_clamped << 16; - let mut dword3: i32 = destination.i16_0[6] as i32 >> shift_clamped & 65535 + let dword3: i32 = destination.i16_0[6] as i32 >> shift_clamped & 65535 | destination.i16_0[7] as i32 >> shift_clamped << 16; write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn psllw_r128(mut r: i32, mut shift: u64) { +pub unsafe fn psllw_r128(r: i32, shift: u64) { // psllw xmm, {shift} - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut dword0: i32 = 0; let mut dword1: i32 = 0; let mut dword2: i32 = 0; @@ -265,9 +263,9 @@ pub unsafe fn psllw_r128(mut r: i32, mut shift: u64) { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn psrld_r128(mut r: i32, mut shift: u64) { +pub unsafe fn psrld_r128(r: i32, shift: u64) { // psrld xmm, {shift} - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut dword0: i32 = 0; let mut dword1: i32 = 0; let mut dword2: i32 = 0; @@ -281,20 +279,20 @@ pub unsafe fn psrld_r128(mut r: i32, mut shift: u64) { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn psrad_r128(mut r: i32, mut shift: u64) { +pub unsafe fn psrad_r128(r: i32, shift: u64) { // psrad xmm, {shift} - let mut destination: reg128 = read_xmm128s(r); - let mut shift_clamped: i32 = (if shift > 31 { 31 } else { shift }) as i32; - let mut dword0: i32 = destination.i32_0[0] >> shift_clamped; - let mut dword1: i32 = destination.i32_0[1] >> shift_clamped; - let mut dword2: i32 = destination.i32_0[2] >> shift_clamped; - let mut dword3: i32 = destination.i32_0[3] >> shift_clamped; + let destination: reg128 = read_xmm128s(r); + let shift_clamped: i32 = (if shift > 31 { 31 } else { shift }) as i32; + let dword0: i32 = destination.i32_0[0] >> shift_clamped; + let dword1: i32 = destination.i32_0[1] >> shift_clamped; + let dword2: i32 = destination.i32_0[2] >> shift_clamped; + let dword3: i32 = destination.i32_0[3] >> shift_clamped; write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn pslld_r128(mut r: i32, mut shift: u64) { +pub unsafe fn pslld_r128(r: i32, shift: u64) { // pslld xmm, {shift} - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut dword0: i32 = 0; let mut dword1: i32 = 0; let mut dword2: i32 = 0; @@ -308,13 +306,13 @@ pub unsafe fn pslld_r128(mut r: i32, mut shift: u64) { write_xmm128(r, dword0, dword1, dword2, dword3); } #[no_mangle] -pub unsafe fn psrlq_r128(mut r: i32, mut shift: u64) { +pub unsafe fn psrlq_r128(r: i32, shift: u64) { // psrlq xmm, {shift} if shift == 0 { return; } else { - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); let mut result: reg128 = reg128 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; @@ -327,9 +325,9 @@ pub unsafe fn psrlq_r128(mut r: i32, mut shift: u64) { }; } #[no_mangle] -pub unsafe fn psllq_r128(mut r: i32, mut shift: u64) { +pub unsafe fn psllq_r128(r: i32, shift: u64) { // psllq xmm, {shift} - let mut destination: reg128 = read_xmm128s(r); + let destination: reg128 = read_xmm128s(r); if shift == 0 { return; } @@ -346,7 +344,7 @@ pub unsafe fn psllq_r128(mut r: i32, mut shift: u64) { }; } #[no_mangle] -pub unsafe fn sse_comparison(mut op: i32, mut x: f64, mut y: f64) -> bool { +pub unsafe fn sse_comparison(op: i32, x: f64, y: f64) -> bool { // TODO: Signaling match op & 7 { 0 => return x == y, @@ -364,18 +362,18 @@ pub unsafe fn sse_comparison(mut op: i32, mut x: f64, mut y: f64) -> bool { }; } #[no_mangle] -pub unsafe fn sse_min(mut x: f64, mut y: f64) -> f64 { +pub unsafe fn sse_min(x: f64, y: f64) -> f64 { // if both x and y are 0 or x is nan, y is returned return if x < y { x } else { y }; } #[no_mangle] -pub unsafe fn sse_max(mut x: f64, mut y: f64) -> f64 { +pub unsafe fn sse_max(x: f64, y: f64) -> f64 { // if both x and y are 0 or x is nan, y is returned return if x > y { x } else { y }; } #[no_mangle] -pub unsafe fn sse_convert_f32_to_i32(mut x: f32) -> i32 { +pub unsafe fn sse_convert_f32_to_i32(x: f32) -> i32 { // TODO: Rounding modes if x >= -2147483648.0 && x < 2147483648.0 { return x as i64 as i32; @@ -387,7 +385,7 @@ pub unsafe fn sse_convert_f32_to_i32(mut x: f32) -> i32 { } #[no_mangle] -pub unsafe fn sse_convert_f64_to_i32(mut x: f64) -> i32 { +pub unsafe fn sse_convert_f64_to_i32(x: f64) -> i32 { // TODO: Rounding modes if x >= -2147483648.0 && x < 2147483648.0 { return x as i64 as i32; diff --git a/src/rust/cpu2/string.rs b/src/rust/cpu2/string.rs index 03d1a313..a9236ed6 100644 --- a/src/rust/cpu2/string.rs +++ b/src/rust/cpu2/string.rs @@ -1,5 +1,3 @@ -#![allow(non_upper_case_globals, unused_mut)] - extern "C" { #[no_mangle] pub fn io_port_read8(port: i32) -> i32; @@ -36,27 +34,27 @@ pub unsafe fn string_get_cycle_count(mut size: i32, mut address: i32) -> i32 { } dbg_assert!(address & size - 1 == 0); // 1 -> 0; 2 -> 1; 4 -> 2 - let mut shift: i32 = size >> 1; + let shift: i32 = size >> 1; return 4096 - (address & 4095) >> shift; } #[no_mangle] -pub unsafe fn string_get_cycle_count2(mut size: i32, mut addr1: i32, mut addr2: i32) -> i32 { - let mut c1: i32 = string_get_cycle_count(size, addr1); - let mut c2: i32 = string_get_cycle_count(size, addr2); +pub unsafe fn string_get_cycle_count2(size: i32, addr1: i32, addr2: i32) -> i32 { + let c1: i32 = string_get_cycle_count(size, addr1); + let c2: i32 = string_get_cycle_count(size, addr2); return if c1 < c2 { c1 } else { c2 }; } #[no_mangle] pub unsafe fn movsb_rep() { - let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; + let src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; let mut count: i32 = get_reg_asize(ECX); if count == 0 { return; } else { let mut cont; - let mut start_count: i32 = count; + let start_count: i32 = count; let mut cycle_counter: i32 = string_get_cycle_count2(size, src, dest); let mut phys_src: i32 = return_on_pagefault!(translate_address_read(src)) as i32; let mut phys_dest: i32 = return_on_pagefault!(translate_address_write(dest)) as i32; @@ -91,7 +89,7 @@ pub unsafe fn movsb_rep() { } } } - let mut diff: i32 = size * (start_count - count); + let diff: i32 = size * (start_count - count); add_reg_asize(EDI, diff); add_reg_asize(ESI, diff); set_ecx_asize(count); @@ -105,29 +103,29 @@ pub unsafe fn movsb_rep() { } #[no_mangle] pub unsafe fn movsb_no_rep() { - let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; + let src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; return_on_pagefault!(safe_write8(dest, return_on_pagefault!(safe_read8(src)))); add_reg_asize(EDI, size); add_reg_asize(ESI, size); } #[no_mangle] pub unsafe fn movsw_rep() { - let mut diff; + let diff; let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; let mut count: i32 = get_reg_asize(ECX); if count == 0 { return; } else { let mut cont; - let mut start_count: i32 = count; + let start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 1 && 0 == src & 1 { - let mut single_size: i32 = if size < 0 { -1 } else { 1 }; + let single_size: i32 = if size < 0 { -1 } else { 1 }; let mut phys_src: i32 = (return_on_pagefault!(translate_address_read(src)) >> 1) as i32; let mut phys_dest: i32 = (return_on_pagefault!(translate_address_write(dest)) >> 1) as i32; @@ -176,29 +174,29 @@ pub unsafe fn movsw_rep() { } #[no_mangle] pub unsafe fn movsw_no_rep() { - let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; + let src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; return_on_pagefault!(safe_write16(dest, return_on_pagefault!(safe_read16(src)))); add_reg_asize(EDI, size); add_reg_asize(ESI, size); } #[no_mangle] pub unsafe fn movsd_rep() { - let mut diff; + let diff; let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; let mut count: i32 = get_reg_asize(ECX); if count == 0 { return; } else { let mut cont; - let mut start_count: i32 = count; + let start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 3 && 0 == src & 3 { - let mut single_size: i32 = if size < 0 { -1 } else { 1 }; + let single_size: i32 = if size < 0 { -1 } else { 1 }; let mut phys_src: i32 = (return_on_pagefault!(translate_address_read(src)) >> 2) as i32; let mut phys_dest: i32 = (return_on_pagefault!(translate_address_write(dest)) >> 2) as i32; @@ -268,28 +266,28 @@ pub unsafe fn movsd_rep() { } #[no_mangle] pub unsafe fn movsd_no_rep() { - let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; + let src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; return_on_pagefault!(safe_write32(dest, return_on_pagefault!(safe_read32s(src)))); add_reg_asize(EDI, size); add_reg_asize(ESI, size); } #[no_mangle] -pub unsafe fn cmpsb_rep(mut prefix_flag: i32) { - let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); +pub unsafe fn cmpsb_rep(prefix_flag: i32) { + let src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut data_src; let mut data_dest; - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; let mut count: i32 = get_reg_asize(ECX); if count == 0 { return; } else { let mut cont; - let mut start_count: i32 = count; - let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; + let start_count: i32 = count; + let is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; let mut cycle_counter: i32 = string_get_cycle_count2(size, src, dest); let mut phys_src: i32 = return_on_pagefault!(translate_address_read(src)) as i32; let mut phys_dest: i32 = return_on_pagefault!(translate_address_read(dest)) as i32; @@ -307,7 +305,7 @@ pub unsafe fn cmpsb_rep(mut prefix_flag: i32) { break; } } - let mut diff: i32 = size * (start_count - count); + let diff: i32 = size * (start_count - count); add_reg_asize(EDI, diff); add_reg_asize(ESI, diff); set_ecx_asize(count); @@ -322,11 +320,11 @@ pub unsafe fn cmpsb_rep(mut prefix_flag: i32) { } #[no_mangle] pub unsafe fn cmpsb_no_rep() { - let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut data_src; - let mut data_dest; - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; + let src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let data_src; + let data_dest; + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; data_src = return_on_pagefault!(safe_read8(src)); data_dest = return_on_pagefault!(safe_read8(dest)); add_reg_asize(EDI, size); @@ -334,24 +332,24 @@ pub unsafe fn cmpsb_no_rep() { cmp8(data_src, data_dest); } #[no_mangle] -pub unsafe fn cmpsw_rep(mut prefix_flag: i32) { - let mut diff; +pub unsafe fn cmpsw_rep(prefix_flag: i32) { + let diff; let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut data_src; let mut data_dest; - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; let mut count: i32 = get_reg_asize(ECX); if count == 0 { return; } else { let mut cont; - let mut start_count: i32 = count; - let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; + let start_count: i32 = count; + let is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 1 && 0 == src & 1 { - let mut single_size: i32 = if size < 0 { -1 } else { 1 }; + let single_size: i32 = if size < 0 { -1 } else { 1 }; let mut phys_src: i32 = (return_on_pagefault!(translate_address_read(src)) >> 1) as i32; let mut phys_dest: i32 = (return_on_pagefault!(translate_address_read(dest)) >> 1) as i32; @@ -403,11 +401,11 @@ pub unsafe fn cmpsw_rep(mut prefix_flag: i32) { } #[no_mangle] pub unsafe fn cmpsw_no_rep() { - let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut data_src; - let mut data_dest; - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; + let src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let data_src; + let data_dest; + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; data_dest = return_on_pagefault!(safe_read16(dest)); data_src = return_on_pagefault!(safe_read16(src)); add_reg_asize(EDI, size); @@ -415,24 +413,24 @@ pub unsafe fn cmpsw_no_rep() { cmp16(data_src, data_dest); } #[no_mangle] -pub unsafe fn cmpsd_rep(mut prefix_flag: i32) { - let mut diff; +pub unsafe fn cmpsd_rep(prefix_flag: i32) { + let diff; let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); let mut data_src; let mut data_dest; - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; let mut count: i32 = get_reg_asize(ECX); if count == 0 { return; } else { let mut cont; - let mut start_count: i32 = count; - let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; + let start_count: i32 = count; + let is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 3 && 0 == src & 3 { - let mut single_size: i32 = if size < 0 { -1 } else { 1 }; + let single_size: i32 = if size < 0 { -1 } else { 1 }; let mut phys_src: i32 = (return_on_pagefault!(translate_address_read(src)) >> 2) as i32; let mut phys_dest: i32 = (return_on_pagefault!(translate_address_read(dest)) >> 2) as i32; @@ -484,11 +482,11 @@ pub unsafe fn cmpsd_rep(mut prefix_flag: i32) { } #[no_mangle] pub unsafe fn cmpsd_no_rep() { - let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut data_src; - let mut data_dest; - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; + let src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let data_src; + let data_dest; + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; data_dest = return_on_pagefault!(safe_read32s(dest)); data_src = return_on_pagefault!(safe_read32s(src)); add_reg_asize(EDI, size); @@ -497,16 +495,16 @@ pub unsafe fn cmpsd_no_rep() { } #[no_mangle] pub unsafe fn stosb_rep() { - let mut data: i32 = *reg8.offset(AL as isize) as i32; - let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; + let data: i32 = *reg8.offset(AL as isize) as i32; + let dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; let mut count: i32 = get_reg_asize(ECX); if count == 0 { return; } else { let mut cont; - let mut start_count: i32 = count; + let start_count: i32 = count; let mut cycle_counter: i32 = string_get_cycle_count(size, dest); let mut phys_dest: i32 = return_on_pagefault!(translate_address_write(dest)) as i32; if !in_mapped_range(phys_dest as u32) { @@ -538,7 +536,7 @@ pub unsafe fn stosb_rep() { } } } - let mut diff: i32 = size * (start_count - count); + let diff: i32 = size * (start_count - count); add_reg_asize(EDI, diff); set_ecx_asize(count); *timestamp_counter = @@ -551,28 +549,28 @@ pub unsafe fn stosb_rep() { } #[no_mangle] pub unsafe fn stosb_no_rep() { - let mut data: i32 = *reg8.offset(AL as isize) as i32; - let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; + let data: i32 = *reg8.offset(AL as isize) as i32; + let dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; return_on_pagefault!(safe_write8(dest, data)); add_reg_asize(EDI, size); } #[no_mangle] pub unsafe fn stosw_rep() { - let mut diff; - let mut data: i32 = *reg16.offset(AX as isize) as i32; + let diff; + let data: i32 = *reg16.offset(AX as isize) as i32; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; let mut count: i32 = get_reg_asize(ECX); if count == 0 { return; } else { let mut cont; - let mut start_count: i32 = count; + let start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 1 { - let mut single_size: i32 = if size < 0 { -1 } else { 1 }; + let single_size: i32 = if size < 0 { -1 } else { 1 }; let mut phys_dest: i32 = (return_on_pagefault!(translate_address_write(dest)) >> 1) as i32; cycle_counter = string_get_cycle_count(size, dest); @@ -616,28 +614,28 @@ pub unsafe fn stosw_rep() { } #[no_mangle] pub unsafe fn stosw_no_rep() { - let mut data: i32 = *reg16.offset(AX as isize) as i32; - let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; + let data: i32 = *reg16.offset(AX as isize) as i32; + let dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; return_on_pagefault!(safe_write16(dest, data)); add_reg_asize(EDI, size); } #[no_mangle] pub unsafe fn stosd_rep() { - let mut diff; - let mut data: i32 = *reg32s.offset(EAX as isize); + let diff; + let data: i32 = *reg32s.offset(EAX as isize); let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; let mut count: i32 = get_reg_asize(ECX); if count == 0 { return; } else { let mut cont; - let mut start_count: i32 = count; + let start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 3 { - let mut single_size: i32 = if size < 0 { -1 } else { 1 }; + let single_size: i32 = if size < 0 { -1 } else { 1 }; let mut phys_dest: i32 = (return_on_pagefault!(translate_address_write(dest)) >> 2) as i32; cycle_counter = string_get_cycle_count(size, dest); @@ -698,23 +696,23 @@ pub unsafe fn stosd_rep() { } #[no_mangle] pub unsafe fn stosd_no_rep() { - let mut data: i32 = *reg32s.offset(EAX as isize); - let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; + let data: i32 = *reg32s.offset(EAX as isize); + let dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; return_on_pagefault!(safe_write32(dest, data)); add_reg_asize(EDI, size); } #[no_mangle] pub unsafe fn lodsb_rep() { - let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; + let src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; let mut count: i32 = get_reg_asize(ECX); if count == 0 { return; } else { let mut cont; - let mut start_count: i32 = count; + let start_count: i32 = count; let mut cycle_counter: i32 = string_get_cycle_count(size, src); let mut phys_src: i32 = return_on_pagefault!(translate_address_read(src)) as i32; loop { @@ -729,7 +727,7 @@ pub unsafe fn lodsb_rep() { break; } } - let mut diff: i32 = size * (start_count - count); + let diff: i32 = size * (start_count - count); add_reg_asize(ESI, diff); set_ecx_asize(count); *timestamp_counter = @@ -742,16 +740,16 @@ pub unsafe fn lodsb_rep() { } #[no_mangle] pub unsafe fn lodsb_no_rep() { - let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; + let src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; *reg8.offset(AL as isize) = return_on_pagefault!(safe_read8(src)) as u8; add_reg_asize(ESI, size); } #[no_mangle] pub unsafe fn lodsw_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; - let mut count: u32 = get_reg_asize(ECX) as u32; + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; + let count: u32 = get_reg_asize(ECX) as u32; if count == 0 { return; } @@ -778,16 +776,16 @@ pub unsafe fn lodsw_rep() { } #[no_mangle] pub unsafe fn lodsw_no_rep() { - let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; + let src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; *reg16.offset(AX as isize) = return_on_pagefault!(safe_read16(src)) as u16; add_reg_asize(ESI, size); } #[no_mangle] pub unsafe fn lodsd_rep() { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; - let mut count: i32 = get_reg_asize(ECX); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; + let count: i32 = get_reg_asize(ECX); if count == 0 { return; } @@ -814,25 +812,25 @@ pub unsafe fn lodsd_rep() { } #[no_mangle] pub unsafe fn lodsd_no_rep() { - let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; + let src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; *reg32s.offset(EAX as isize) = return_on_pagefault!(safe_read32s(src)); add_reg_asize(ESI, size); } #[no_mangle] -pub unsafe fn scasb_rep(mut prefix_flag: i32) { - let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; +pub unsafe fn scasb_rep(prefix_flag: i32) { + let dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; let mut data_dest; - let mut data_src: i32 = *reg8.offset(AL as isize) as i32; + let data_src: i32 = *reg8.offset(AL as isize) as i32; let mut count: i32 = get_reg_asize(ECX); if count == 0 { return; } else { let mut cont; - let mut start_count: i32 = count; - let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; + let start_count: i32 = count; + let is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; let mut cycle_counter: i32 = string_get_cycle_count(size, dest); let mut phys_dest: i32 = return_on_pagefault!(translate_address_read(dest)) as i32; loop { @@ -847,7 +845,7 @@ pub unsafe fn scasb_rep(mut prefix_flag: i32) { break; } } - let mut diff: i32 = size * (start_count - count); + let diff: i32 = size * (start_count - count); add_reg_asize(EDI, diff); set_ecx_asize(count); *timestamp_counter = @@ -861,32 +859,32 @@ pub unsafe fn scasb_rep(mut prefix_flag: i32) { } #[no_mangle] pub unsafe fn scasb_no_rep() { - let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; - let mut data_dest; - let mut data_src: i32 = *reg8.offset(AL as isize) as i32; + let dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; + let data_dest; + let data_src: i32 = *reg8.offset(AL as isize) as i32; data_dest = return_on_pagefault!(safe_read8(dest)); add_reg_asize(EDI, size); cmp8(data_src, data_dest); } #[no_mangle] -pub unsafe fn scasw_rep(mut prefix_flag: i32) { - let mut diff; +pub unsafe fn scasw_rep(prefix_flag: i32) { + let diff; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; let mut data_dest; - let mut data_src: i32 = *reg16.offset(AL as isize) as i32; + let data_src: i32 = *reg16.offset(AL as isize) as i32; let mut count: i32 = get_reg_asize(ECX); if count == 0 { return; } else { let mut cont; - let mut start_count: i32 = count; - let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; + let start_count: i32 = count; + let is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 1 { - let mut single_size: i32 = if size < 0 { -1 } else { 1 }; + let single_size: i32 = if size < 0 { -1 } else { 1 }; let mut phys_dest: i32 = (return_on_pagefault!(translate_address_read(dest)) >> 1) as i32; cycle_counter = string_get_cycle_count(size, dest); @@ -931,32 +929,32 @@ pub unsafe fn scasw_rep(mut prefix_flag: i32) { } #[no_mangle] pub unsafe fn scasw_no_rep() { - let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; - let mut data_dest; - let mut data_src: i32 = *reg16.offset(AL as isize) as i32; + let dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; + let data_dest; + let data_src: i32 = *reg16.offset(AL as isize) as i32; data_dest = return_on_pagefault!(safe_read16(dest)); add_reg_asize(EDI, size); cmp16(data_src, data_dest); } #[no_mangle] -pub unsafe fn scasd_rep(mut prefix_flag: i32) { - let mut diff; +pub unsafe fn scasd_rep(prefix_flag: i32) { + let diff; let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; let mut data_dest; - let mut data_src: i32 = *reg32s.offset(EAX as isize); + let data_src: i32 = *reg32s.offset(EAX as isize); let mut count: i32 = get_reg_asize(ECX); if count == 0 { return; } else { let mut cont; - let mut start_count: i32 = count; - let mut is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; + let start_count: i32 = count; + let is_repz: i32 = (prefix_flag == PREFIX_REPZ) as i32; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 3 { - let mut single_size: i32 = if size < 0 { -1 } else { 1 }; + let single_size: i32 = if size < 0 { -1 } else { 1 }; let mut phys_dest: i32 = (return_on_pagefault!(translate_address_read(dest)) >> 2) as i32; cycle_counter = string_get_cycle_count(size, dest); @@ -1001,30 +999,30 @@ pub unsafe fn scasd_rep(mut prefix_flag: i32) { } #[no_mangle] pub unsafe fn scasd_no_rep() { - let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; - let mut data_dest; - let mut data_src: i32 = *reg32s.offset(EAX as isize); + let dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; + let data_dest; + let data_src: i32 = *reg32s.offset(EAX as isize); data_dest = return_on_pagefault!(safe_read32s(dest)); add_reg_asize(EDI, size); cmp32(data_src, data_dest); } #[no_mangle] pub unsafe fn insb_rep() { - let mut port: i32 = *reg16.offset(DX as isize) as i32; + let port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 1) { return; } else { - let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; + let dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; let mut count: i32 = get_reg_asize(ECX); if count == 0 { return; } else { let mut cont; - let mut start_count: i32 = count; + let start_count: i32 = count; let mut cycle_counter: i32 = string_get_cycle_count(size, dest); let mut phys_dest: i32 = return_on_pagefault!(translate_address_write(dest)) as i32; loop { @@ -1039,7 +1037,7 @@ pub unsafe fn insb_rep() { break; } } - let mut diff: i32 = size * (start_count - count); + let diff: i32 = size * (start_count - count); add_reg_asize(EDI, diff); set_ecx_asize(count); *timestamp_counter = (*timestamp_counter as u32) @@ -1054,13 +1052,13 @@ pub unsafe fn insb_rep() { } #[no_mangle] pub unsafe fn insb_no_rep() { - let mut port: i32 = *reg16.offset(DX as isize) as i32; + let port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 1) { return; } else { - let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; + let dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; return_on_pagefault!(writable_or_pagefault(dest, 1)); return_on_pagefault!(safe_write8(dest, io_port_read8(port))); add_reg_asize(EDI, size); @@ -1069,24 +1067,24 @@ pub unsafe fn insb_no_rep() { } #[no_mangle] pub unsafe fn insw_rep() { - let mut diff; - let mut port: i32 = *reg16.offset(DX as isize) as i32; + let diff; + let port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 2) { return; } else { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; let mut count: i32 = get_reg_asize(ECX); if count == 0 { return; } else { let mut cont; - let mut start_count: i32 = count; + let start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 1 { - let mut single_size: i32 = if size < 0 { -1 } else { 1 }; + let single_size: i32 = if size < 0 { -1 } else { 1 }; let mut phys_dest: i32 = (return_on_pagefault!(translate_address_write(dest)) >> 1) as i32; cycle_counter = string_get_cycle_count(size, dest); @@ -1133,13 +1131,13 @@ pub unsafe fn insw_rep() { } #[no_mangle] pub unsafe fn insw_no_rep() { - let mut port: i32 = *reg16.offset(DX as isize) as i32; + let port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 2) { return; } else { - let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; + let dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; return_on_pagefault!(writable_or_pagefault(dest, 2)); return_on_pagefault!(safe_write16(dest, io_port_read16(port))); add_reg_asize(EDI, size); @@ -1148,24 +1146,24 @@ pub unsafe fn insw_no_rep() { } #[no_mangle] pub unsafe fn insd_rep() { - let mut diff; - let mut port: i32 = *reg16.offset(DX as isize) as i32; + let diff; + let port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 4) { return; } else { let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; let mut count: i32 = get_reg_asize(ECX); if count == 0 { return; } else { let mut cont; - let mut start_count: i32 = count; + let start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == dest & 3 { - let mut single_size: i32 = if size < 0 { -1 } else { 1 }; + let single_size: i32 = if size < 0 { -1 } else { 1 }; let mut phys_dest: i32 = (return_on_pagefault!(translate_address_write(dest)) >> 2) as i32; cycle_counter = string_get_cycle_count(size, dest); @@ -1212,13 +1210,13 @@ pub unsafe fn insd_rep() { } #[no_mangle] pub unsafe fn insd_no_rep() { - let mut port: i32 = *reg16.offset(DX as isize) as i32; + let port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 4) { return; } else { - let mut dest: i32 = get_seg(ES) + get_reg_asize(EDI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; + let dest: i32 = get_seg(ES) + get_reg_asize(EDI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; return_on_pagefault!(writable_or_pagefault(dest, 4)); return_on_pagefault!(safe_write32(dest, io_port_read32(port))); add_reg_asize(EDI, size); @@ -1227,20 +1225,20 @@ pub unsafe fn insd_no_rep() { } #[no_mangle] pub unsafe fn outsb_rep() { - let mut port: i32 = *reg16.offset(DX as isize) as i32; + let port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 1) { return; } else { - let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; + let src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; let mut count: i32 = get_reg_asize(ECX); if count == 0 { return; } else { let mut cont; - let mut start_count: i32 = count; + let start_count: i32 = count; let mut cycle_counter: i32 = string_get_cycle_count(size, src); let mut phys_src: i32 = return_on_pagefault!(translate_address_read(src)) as i32; loop { @@ -1255,7 +1253,7 @@ pub unsafe fn outsb_rep() { break; } } - let mut diff: i32 = size * (start_count - count); + let diff: i32 = size * (start_count - count); add_reg_asize(ESI, diff); set_ecx_asize(count); *timestamp_counter = (*timestamp_counter as u32) @@ -1270,13 +1268,13 @@ pub unsafe fn outsb_rep() { } #[no_mangle] pub unsafe fn outsb_no_rep() { - let mut port: i32 = *reg16.offset(DX as isize) as i32; + let port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 1) { return; } else { - let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; + let src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -1 } else { 1 }; io_port_write8(port, return_on_pagefault!(safe_read8(src))); add_reg_asize(ESI, size); return; @@ -1284,24 +1282,24 @@ pub unsafe fn outsb_no_rep() { } #[no_mangle] pub unsafe fn outsw_rep() { - let mut diff; - let mut port: i32 = *reg16.offset(DX as isize) as i32; + let diff; + let port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 2) { return; } else { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; let mut count: i32 = get_reg_asize(ECX); if count == 0 { return; } else { let mut cont; - let mut start_count: i32 = count; + let start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == src & 1 { - let mut single_size: i32 = if size < 0 { -1 } else { 1 }; + let single_size: i32 = if size < 0 { -1 } else { 1 }; let mut phys_src: i32 = (return_on_pagefault!(translate_address_read(src)) >> 1) as i32; cycle_counter = string_get_cycle_count(size, src); @@ -1347,13 +1345,13 @@ pub unsafe fn outsw_rep() { } #[no_mangle] pub unsafe fn outsw_no_rep() { - let mut port: i32 = *reg16.offset(DX as isize) as i32; + let port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 2) { return; } else { - let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; + let src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -2 } else { 2 }; io_port_write16(port, return_on_pagefault!(safe_read16(src))); add_reg_asize(ESI, size); return; @@ -1361,24 +1359,24 @@ pub unsafe fn outsw_no_rep() { } #[no_mangle] pub unsafe fn outsd_rep() { - let mut diff; - let mut port: i32 = *reg16.offset(DX as isize) as i32; + let diff; + let port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 4) { return; } else { let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; let mut count: i32 = get_reg_asize(ECX); if count == 0 { return; } else { let mut cont; - let mut start_count: i32 = count; + let start_count: i32 = count; let mut cycle_counter: i32 = MAX_COUNT_PER_CYCLE; if 0 == src & 3 { - let mut single_size: i32 = if size < 0 { -1 } else { 1 }; + let single_size: i32 = if size < 0 { -1 } else { 1 }; let mut phys_src: i32 = (return_on_pagefault!(translate_address_read(src)) >> 2) as i32; cycle_counter = string_get_cycle_count(size, src); @@ -1424,13 +1422,13 @@ pub unsafe fn outsd_rep() { } #[no_mangle] pub unsafe fn outsd_no_rep() { - let mut port: i32 = *reg16.offset(DX as isize) as i32; + let port: i32 = *reg16.offset(DX as isize) as i32; if !test_privileges_for_io(port, 4) { return; } else { - let mut src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); - let mut size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; + let src: i32 = get_seg_prefix(DS) + get_reg_asize(ESI); + let size: i32 = if 0 != *flags & FLAG_DIRECTION { -4 } else { 4 }; io_port_write32(port, return_on_pagefault!(safe_read32s(src))); add_reg_asize(ESI, size); return; From cb1348fdc78986d06ec10b7bbd6647dce48dbf7e Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 10 Sep 2018 23:59:54 -0500 Subject: [PATCH 1349/2137] c2rust cleanup: Restore hex constants --- src/rust/cpu2/arith.rs | 26 +++--- src/rust/cpu2/cpu.rs | 112 +++++++++++------------ src/rust/cpu2/fpu.rs | 12 +-- src/rust/cpu2/instructions.rs | 64 ++++++------- src/rust/cpu2/instructions_0f.rs | 148 ++++++++++++++++--------------- src/rust/cpu2/memory.rs | 12 +-- src/rust/cpu2/misc_instr.rs | 10 +-- src/rust/cpu2/modrm.rs | 46 +++++----- src/rust/cpu2/sse_instr.rs | 24 ++--- src/rust/cpu2/string.rs | 4 +- 10 files changed, 230 insertions(+), 228 deletions(-) diff --git a/src/rust/cpu2/arith.rs b/src/rust/cpu2/arith.rs index 7c498171..2e25bc27 100644 --- a/src/rust/cpu2/arith.rs +++ b/src/rust/cpu2/arith.rs @@ -168,7 +168,7 @@ pub unsafe fn mul16(source_operand: u32) { let high_result: u32 = result >> 16; *reg16.offset(AX as isize) = result as u16; *reg16.offset(DX as isize) = high_result as u16; - *last_result = (result & 65535) as i32; + *last_result = (result & 0xFFFF) as i32; *last_op_size = OPSIZE_16; if high_result == 0 { *flags &= !1 & !FLAG_OVERFLOW @@ -183,7 +183,7 @@ pub unsafe fn imul16(source_operand: i32) { let result: i32 = source_operand * *reg16s.offset(AX as isize) as i32; *reg16.offset(AX as isize) = result as u16; *reg16.offset(DX as isize) = (result >> 16) as u16; - *last_result = result & 65535; + *last_result = result & 0xFFFF; *last_op_size = OPSIZE_16; if result > 32767 || result < -32768 { *flags |= 1 | FLAG_OVERFLOW @@ -198,7 +198,7 @@ pub unsafe fn imul_reg16(mut operand1: i32, mut operand2: i32) -> i32 { operand1 = operand1 << 16 >> 16; operand2 = operand2 << 16 >> 16; let result: i32 = operand1 * operand2; - *last_result = result & 65535; + *last_result = result & 0xFFFF; *last_op_size = OPSIZE_16; if result > 32767 || result < -32768 { *flags |= 1 | FLAG_OVERFLOW @@ -330,7 +330,7 @@ pub unsafe fn bcd_aad(imm8: i32) { *last_op_size = OPSIZE_8; *flags_changed = FLAGS_ALL & !1 & !FLAG_ADJUST & !FLAG_OVERFLOW; *flags &= !1 & !FLAG_ADJUST & !FLAG_OVERFLOW; - if result > 65535 { + if result > 0xFFFF { *flags |= 1 }; } @@ -674,7 +674,7 @@ pub unsafe fn div16(source_operand: u32) { let target_operand: u32 = (*reg16.offset(AX as isize) as i32 | (*reg16.offset(DX as isize) as i32) << 16) as u32; let result: u32 = target_operand.wrapping_div(source_operand); - if result >= 65536 { + if result >= 0x10000 { trigger_de(); } else { @@ -737,13 +737,13 @@ pub unsafe fn idiv32(source_operand: i32) { let target_low: u32 = *reg32s.offset(EAX as isize) as u32; let target_high: u32 = *reg32s.offset(EDX as isize) as u32; let target_operand: i64 = ((target_high as u64) << 32 | target_low as u64) as i64; - if source_operand == -1 && target_operand == (-1 - 9223372036854775807i64) as i64 { + if source_operand == -1 && target_operand == -0x80000000_00000000 as i64 { trigger_de(); return; } else { let result: i64 = target_operand / source_operand as i64; - if result < (-1 - 2147483647) as i64 || result > 2147483647 { + if result < -0x80000000 || result > 0x7FFFFFFF { trigger_de(); return; } @@ -1154,9 +1154,9 @@ pub unsafe fn saturate_sw_to_sb(v: i32) -> i32 { pub unsafe fn saturate_sd_to_sw(v: u32) -> u32 { let mut ret: u32 = v; if ret > 4294934528 { - ret = ret & 65535 + ret = ret & 0xFFFF } - else if ret > 2147483647 { + else if ret > 0x7FFFFFFF { ret = 32768 } else if ret > 32767 { @@ -1171,7 +1171,7 @@ pub unsafe fn saturate_sd_to_sb(v: u32) -> u32 { if ret > 4294967168 { ret = ret & 255 } - else if ret > 2147483647 { + else if ret > 0x7FFFFFFF { ret = 128 } else if ret > 127 { @@ -1201,11 +1201,11 @@ pub unsafe fn saturate_ud_to_ub(v: u32) -> u32 { #[no_mangle] pub unsafe fn saturate_uw(v: u32) -> i32 { let mut ret: u32 = v; - if ret > 2147483647 { + if ret > 0x7FFFFFFF { ret = 0 } - else if ret > 65535 { - ret = 65535 + else if ret > 0xFFFF { + ret = 0xFFFF } dbg_assert!(ret & 4294901760 == 0); return ret as i32; diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index d8ead580..0b1f30f1 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -304,7 +304,7 @@ impl SegmentDescriptor { pub unsafe fn after_block_boundary() { jit_block_boundary = 0 != 1; } -pub unsafe fn same_page(addr1: i32, addr2: i32) -> bool { return addr1 & !4095 == addr2 & !4095; } +pub unsafe fn same_page(addr1: i32, addr2: i32) -> bool { return addr1 & !0xFFF == addr2 & !0xFFF; } #[no_mangle] pub unsafe fn get_eflags() -> i32 { @@ -322,10 +322,10 @@ pub unsafe fn translate_address_read(address: i32) -> OrPageFault { let entry: i32 = *tlb_data.offset(base as isize); let user: bool = *cpl as i32 == 3; if entry & (TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0 }) == TLB_VALID { - return Ok((entry & !4095 ^ address) as u32); + return Ok((entry & !0xFFF ^ address) as u32); } else { - return Ok((do_page_translation(address, 0 != 0, user)? | address & 4095) as u32); + return Ok((do_page_translation(address, 0 != 0, user)? | address & 0xFFF) as u32); }; } @@ -337,7 +337,7 @@ pub unsafe fn do_page_translation(addr: i32, for_writing: bool, user: bool) -> O let high; if *cr & CR0_PG == 0 { // paging disabled - high = (addr as u32 & 4294963200) as i32; + high = (addr as u32 & 0xFFFFF000) as i32; global = 0 != 0 } else { @@ -388,11 +388,11 @@ pub unsafe fn do_page_translation(addr: i32, for_writing: bool, user: bool) -> O write_aligned32(page_dir_addr as u32, new_page_dir_entry); } - high = (page_dir_entry as u32 & 4290772992 | (addr & 4190208) as u32) as i32; + high = (page_dir_entry as u32 & 0xFFC00000 | (addr & 0x3FF000) as u32) as i32; global = page_dir_entry & PAGE_TABLE_GLOBAL_MASK == PAGE_TABLE_GLOBAL_MASK } else { - let page_table_addr: i32 = ((page_dir_entry as u32 & 4294963200) >> 2) + let page_table_addr: i32 = ((page_dir_entry as u32 & 0xFFFFF000) >> 2) .wrapping_add((page & 1023) as u32) as i32; let page_table_entry: i32 = read_aligned32(page_table_addr as u32); if page_table_entry & PAGE_TABLE_PRESENT_MASK == 0 { @@ -434,7 +434,7 @@ pub unsafe fn do_page_translation(addr: i32, for_writing: bool, user: bool) -> O write_aligned32(page_table_addr as u32, new_page_table_entry); } - high = (page_table_entry as u32 & 4294963200) as i32; + high = (page_table_entry as u32 & 0xFFFFF000) as i32; global = page_table_entry & PAGE_TABLE_GLOBAL_MASK == PAGE_TABLE_GLOBAL_MASK } } @@ -500,7 +500,7 @@ pub unsafe fn do_page_translation(addr: i32, for_writing: bool, user: bool) -> O else { 0 }; - dbg_assert!((high ^ page << 12) & 4095 == 0); + dbg_assert!((high ^ page << 12) & 0xFFF == 0); *tlb_data.offset(page as isize) = high ^ page << 12 | info_bits; return Ok(high); } @@ -517,7 +517,7 @@ pub unsafe fn full_clear_tlb() { } valid_tlb_entries_count = 0; if CHECK_TLB_INVARIANTS { - for i in 0..1048576 { + for i in 0..0x100000 { dbg_assert!(*tlb_data.offset(i as isize) == 0); } }; @@ -544,7 +544,7 @@ pub unsafe fn clear_tlb() { } valid_tlb_entries_count = global_page_offset; if CHECK_TLB_INVARIANTS { - for i in 0..1048576 { + for i in 0..0x100000 { dbg_assert!( *tlb_data.offset(i as isize) == 0 || 0 != *tlb_data.offset(i as isize) & TLB_GLOBAL ); @@ -597,10 +597,10 @@ pub unsafe fn translate_address_write(address: i32) -> OrPageFault { if entry & (TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0 } | TLB_READONLY) == TLB_VALID { - return Ok((entry & !4095 ^ address) as u32); + return Ok((entry & !0xFFF ^ address) as u32); } else { - return Ok((do_page_translation(address, 0 != 1, user)? | address & 4095) as u32); + return Ok((do_page_translation(address, 0 != 1, user)? | address & 0xFFF) as u32); }; } @@ -643,7 +643,7 @@ pub unsafe fn check_tlb_invariants() { } pub unsafe fn writable_or_pagefault(addr: i32, size: i32) -> OrPageFault<()> { - dbg_assert!(size < 4096); + dbg_assert!(size < 0x1000); dbg_assert!(size > 0); if *cr & CR0_PG == 0 { return Ok(()); @@ -670,9 +670,9 @@ pub unsafe fn writable_or_pagefault(addr: i32, size: i32) -> OrPageFault<()> { pub unsafe fn read_imm8() -> OrPageFault { let eip: i32 = *instruction_pointer; - if 0 != eip & !4095 ^ *last_virt_eip { + if 0 != eip & !0xFFF ^ *last_virt_eip { *eip_phys = (translate_address_read(eip)? ^ eip as u32) as i32; - *last_virt_eip = eip & !4095 + *last_virt_eip = eip & !0xFFF } dbg_assert!(!in_mapped_range((*eip_phys ^ eip) as u32)); let data8: i32 = *mem8.offset((*eip_phys ^ eip) as isize) as i32; @@ -686,7 +686,7 @@ pub unsafe fn read_imm16() -> OrPageFault { // Two checks in one comparison: // 1. Did the high 20 bits of eip change // or 2. Are the low 12 bits of eip 0xFFF (and this read crosses a page boundary) - if (*instruction_pointer ^ *last_virt_eip) as u32 > 4094 { + if (*instruction_pointer ^ *last_virt_eip) as u32 > 0xFFE { return Ok(read_imm8()? | read_imm8()? << 8); } else { @@ -698,7 +698,7 @@ pub unsafe fn read_imm16() -> OrPageFault { pub unsafe fn read_imm32s() -> OrPageFault { // Analogue to the above comment - if (*instruction_pointer ^ *last_virt_eip) as u32 > 4092 { + if (*instruction_pointer ^ *last_virt_eip) as u32 > 0xFFC { return Ok(read_imm16()? | read_imm16()? << 16); } else { @@ -1056,7 +1056,7 @@ pub unsafe fn cycle_internal() { if 0 != entry { profiler::stat_increment(S_RUN_FROM_CACHE); let initial_tsc = *timestamp_counter as i32; - let wasm_table_index = (entry & 65535) as u16; + let wasm_table_index = (entry & 0xFFFF) as u16; let initial_state = (entry >> 16) as u16; call_indirect1( (wasm_table_index as u32).wrapping_add(WASM_TABLE_OFFSET as u32) as i32, @@ -1099,9 +1099,9 @@ pub unsafe fn cycle_internal() { pub unsafe fn get_phys_eip() -> OrPageFault { let eip: i32 = *instruction_pointer; - if 0 != eip & !4095 ^ *last_virt_eip { + if 0 != eip & !0xFFF ^ *last_virt_eip { *eip_phys = (translate_address_read(eip)? ^ eip as u32) as i32; - *last_virt_eip = eip & !4095 + *last_virt_eip = eip & !0xFFF } let phys_addr: u32 = (*eip_phys ^ eip) as u32; dbg_assert!(!in_mapped_range(phys_addr)); @@ -1250,14 +1250,14 @@ pub unsafe fn trigger_gp_non_raising(code: i32) { } pub unsafe fn virt_boundary_read16(low: u32, high: u32) -> i32 { - dbg_assert!(low & 4095 == 4095); - dbg_assert!(high & 4095 == 0); + dbg_assert!(low & 0xFFF == 0xFFF); + dbg_assert!(high & 0xFFF == 0); return read8(low as u32) | read8(high as u32) << 8; } pub unsafe fn virt_boundary_read32s(low: u32, high: u32) -> i32 { - dbg_assert!(low & 4095 >= 4093); - dbg_assert!(high - 3 & 4095 == low & 4095); + dbg_assert!(low & 0xFFF >= 0xFFD); + dbg_assert!(high - 3 & 0xFFF == low & 0xFFF); let mid; if 0 != low & 1 { if 0 != low & 2 { @@ -1277,15 +1277,15 @@ pub unsafe fn virt_boundary_read32s(low: u32, high: u32) -> i32 { } pub unsafe fn virt_boundary_write16(low: u32, high: u32, value: i32) { - dbg_assert!(low & 4095 == 4095); - dbg_assert!(high & 4095 == 0); + dbg_assert!(low & 0xFFF == 0xFFF); + dbg_assert!(high & 0xFFF == 0); write8(low as u32, value); write8(high as u32, value >> 8); } pub unsafe fn virt_boundary_write32(low: u32, high: u32, value: i32) { - dbg_assert!(low & 4095 >= 4093); - dbg_assert!(high - 3 & 4095 == low & 4095); + dbg_assert!(low & 0xFFF >= 0xFFD); + dbg_assert!(high - 3 & 0xFFF == low & 0xFFF); write8(low as u32, value); if 0 != low & 1 { if 0 != low & 2 { @@ -1314,11 +1314,11 @@ pub unsafe fn safe_read8(addr: i32) -> OrPageFault { pub unsafe fn safe_read16(address: i32) -> OrPageFault { let base: i32 = (address as u32 >> 12) as i32; let entry: i32 = *tlb_data.offset(base as isize); - let info_bits: i32 = entry & 4095 & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; - if info_bits == TLB_VALID && address & 4095 <= 4096 - 2 { + let info_bits: i32 = entry & 0xFFF & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; + if info_bits == TLB_VALID && address & 0xFFF <= 0x1000 - 2 { // - not in memory mapped area // - can be accessed from any cpl - let phys_address: u32 = (entry & !4095 ^ address) as u32; + let phys_address: u32 = (entry & !0xFFF ^ address) as u32; dbg_assert!(!in_mapped_range(phys_address)); return Ok(*(mem8.offset(phys_address as isize) as *mut u16) as i32); } @@ -1328,7 +1328,7 @@ pub unsafe fn safe_read16(address: i32) -> OrPageFault { } pub unsafe fn safe_read16_slow(addr: i32) -> OrPageFault { - if addr & 4095 == 4095 { + if addr & 0xFFF == 0xFFF { return Ok(safe_read8(addr)? | safe_read8(addr + 1)? << 8); } else { @@ -1339,20 +1339,20 @@ pub unsafe fn safe_read16_slow(addr: i32) -> OrPageFault { pub unsafe fn safe_read32s(address: i32) -> OrPageFault { let base: i32 = (address as u32 >> 12) as i32; let entry: i32 = *tlb_data.offset(base as isize); - let info_bits: i32 = entry & 4095 & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; - if info_bits == TLB_VALID && address & 4095 <= 4096 - 4 { + let info_bits: i32 = entry & 0xFFF & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; + if info_bits == TLB_VALID && address & 0xFFF <= 0x1000 - 4 { if false { profiler::stat_increment(S_SAFE_READ_FAST); } // - not in memory mapped area // - can be accessed from any cpl - let phys_address: u32 = (entry & !4095 ^ address) as u32; + let phys_address: u32 = (entry & !0xFFF ^ address) as u32; dbg_assert!(!in_mapped_range(phys_address)); return Ok(*(mem8.offset(phys_address as isize) as *mut i32)); } else { if false { - if address & 4095 > 4096 - 4 { + if address & 0xFFF > 0x1000 - 4 { profiler::stat_increment(S_SAFE_READ_SLOW_PAGE_CROSSED); } else if info_bits & TLB_VALID == 0 { @@ -1415,7 +1415,7 @@ pub fn report_safe_write_jit_slow(address: u32, entry: i32) { } pub unsafe fn safe_read32s_slow(addr: i32) -> OrPageFault { - if addr & 4095 >= 4093 { + if addr & 0xFFF >= 0xFFD { return Ok(safe_read16(addr)? | safe_read16(addr + 2)? << 16); } else { @@ -1467,7 +1467,7 @@ pub unsafe fn safe_read32s_slow_jit(addr: i32) -> i32 { pub unsafe fn safe_read64s(addr: i32) -> OrPageFault { let mut x: reg64 = reg64 { i8_0: [0; 8] }; - if addr & 4095 > 4096 - 8 { + if addr & 0xFFF > 0x1000 - 8 { x.u32_0[0] = safe_read32s(addr)? as u32; x.u32_0[1] = safe_read32s(addr + 4)? as u32 } @@ -1480,7 +1480,7 @@ pub unsafe fn safe_read64s(addr: i32) -> OrPageFault { pub unsafe fn safe_read128s(addr: i32) -> OrPageFault { let mut x: reg128 = reg128 { i8_0: [0; 16] }; - if addr & 4095 > 4096 - 16 { + if addr & 0xFFF > 0x1000 - 16 { x.u64_0[0] = safe_read64s(addr)?.u64_0[0]; x.u64_0[1] = safe_read64s(addr + 8)?.u64_0[0] } @@ -1499,13 +1499,13 @@ pub unsafe fn safe_write8(addr: i32, value: i32) -> OrPageFault<()> { pub unsafe fn safe_write16(address: i32, value: i32) -> OrPageFault<()> { let base: i32 = (address as u32 >> 12) as i32; let entry: i32 = *tlb_data.offset(base as isize); - let info_bits: i32 = entry & 4095 & !TLB_GLOBAL; - if info_bits == TLB_VALID && address & 4095 <= 4096 - 2 { + let info_bits: i32 = entry & 0xFFF & !TLB_GLOBAL; + if info_bits == TLB_VALID && address & 0xFFF <= 0x1000 - 2 { // - allowed to write in user-mode // - not in memory mapped area // - can be accessed from any cpl // - does not contain code - let phys_address: u32 = (entry & !4095 ^ address) as u32; + let phys_address: u32 = (entry & !0xFFF ^ address) as u32; dbg_assert!(!::c_api::jit_page_has_code(phys_address >> 12)); dbg_assert!(!in_mapped_range(phys_address)); *(mem8.offset(phys_address as isize) as *mut u16) = value as u16; @@ -1518,7 +1518,7 @@ pub unsafe fn safe_write16(address: i32, value: i32) -> OrPageFault<()> { pub unsafe fn safe_write16_slow(addr: i32, value: i32) -> OrPageFault<()> { let phys_low = translate_address_write(addr)?; - if addr & 4095 == 4095 { + if addr & 0xFFF == 0xFFF { virt_boundary_write16(phys_low, translate_address_write(addr + 1)?, value); } else { @@ -1531,22 +1531,22 @@ pub unsafe fn safe_write32(address: i32, value: i32) -> OrPageFault<()> { let base: i32 = (address as u32 >> 12) as i32; let entry: i32 = *tlb_data.offset(base as isize); let info_bits: i32 = - entry & 4095 & !TLB_GLOBAL & !if *cpl as i32 == 3 { 0 } else { TLB_NO_USER }; - if info_bits == TLB_VALID && address & 4095 <= 4096 - 4 { + entry & 0xFFF & !TLB_GLOBAL & !if *cpl as i32 == 3 { 0 } else { TLB_NO_USER }; + if info_bits == TLB_VALID && address & 0xFFF <= 0x1000 - 4 { if false { profiler::stat_increment(S_SAFE_WRITE_FAST); } // - allowed to write in user-mode // - not in memory mapped area // - does not contain code - let phys_address: u32 = (entry & !4095 ^ address) as u32; + let phys_address: u32 = (entry & !0xFFF ^ address) as u32; dbg_assert!(!::c_api::jit_page_has_code(phys_address >> 12)); dbg_assert!(!in_mapped_range(phys_address)); *(mem8.offset(phys_address as isize) as *mut i32) = value; } else { if false { - if address & 4095 > 4096 - 4 { + if address & 0xFFF > 0x1000 - 4 { profiler::stat_increment(S_SAFE_WRITE_SLOW_PAGE_CROSSED); } else if info_bits & TLB_VALID == 0 { @@ -1575,7 +1575,7 @@ pub unsafe fn safe_write32(address: i32, value: i32) -> OrPageFault<()> { pub unsafe fn safe_write32_slow(addr: i32, value: i32) -> OrPageFault<()> { let phys_low = translate_address_write(addr)?; - if addr & 4095 > 4096 - 4 { + if addr & 0xFFF > 0x1000 - 4 { virt_boundary_write32( phys_low, translate_address_write(addr + 3 & !3)? | (addr as u32 + 3 & 3), @@ -1613,7 +1613,7 @@ pub unsafe fn safe_write32_slow_jit(addr: i32, value: i32) { } pub unsafe fn safe_write64(addr: i32, value: i64) -> OrPageFault<()> { - if addr & 4095 > 4096 - 8 { + if addr & 0xFFF > 0x1000 - 8 { writable_or_pagefault(addr, 8)?; safe_write32(addr, value as i32).unwrap(); safe_write32(addr + 4, (value >> 32) as i32).unwrap(); @@ -1626,7 +1626,7 @@ pub unsafe fn safe_write64(addr: i32, value: i64) -> OrPageFault<()> { } pub unsafe fn safe_write128(addr: i32, value: reg128) -> OrPageFault<()> { - if addr & 4095 > 4096 - 16 { + if addr & 0xFFF > 0x1000 - 16 { writable_or_pagefault(addr, 16)?; safe_write64(addr, value.u64_0[0] as i64).unwrap(); safe_write64(addr + 8, value.u64_0[1] as i64).unwrap(); @@ -1668,7 +1668,7 @@ pub unsafe fn write_reg_osize(index: i32, value: i32) { write_reg32(index, value); } else { - write_reg16(index, value & 65535); + write_reg16(index, value & 0xFFFF); }; } @@ -1831,7 +1831,7 @@ pub unsafe fn get_reg_asize(reg: i32) -> i32 { return r; } else { - return r & 65535; + return r & 0xFFFF; }; } @@ -2003,10 +2003,10 @@ pub unsafe fn translate_address_system_read(address: i32) -> OrPageFault { let base: i32 = (address as u32 >> 12) as i32; let entry: i32 = *tlb_data.offset(base as isize); if 0 != entry & TLB_VALID { - return Ok((entry & !4095 ^ address) as u32); + return Ok((entry & !0xFFF ^ address) as u32); } else { - return Ok((do_page_translation(address, 0 != 0, 0 != 0)? | address & 4095) as u32); + return Ok((do_page_translation(address, 0 != 0, 0 != 0)? | address & 0xFFF) as u32); }; } @@ -2014,10 +2014,10 @@ pub unsafe fn translate_address_system_write(address: i32) -> OrPageFault { let base: i32 = (address as u32 >> 12) as i32; let entry: i32 = *tlb_data.offset(base as isize); if entry & (TLB_VALID | TLB_READONLY) == TLB_VALID { - return Ok((entry & !4095 ^ address) as u32); + return Ok((entry & !0xFFF ^ address) as u32); } else { - return Ok((do_page_translation(address, 0 != 1, 0 != 0)? | address & 4095) as u32); + return Ok((do_page_translation(address, 0 != 1, 0 != 0)? | address & 0xFFF) as u32); }; } diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 4569fa51..45203bd0 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -16,15 +16,15 @@ pub const M_LOG2E: f64 = 1.4426950408889634f64; pub const M_LN2: f64 = 0.6931471805599453f64; pub const M_LN10: f64 = 2.302585092994046f64; pub const M_PI: f64 = 3.141592653589793f64; -const FPU_C0: i32 = 256; -pub const FPU_C1: i32 = 512; -const FPU_C2: i32 = 1024; -const FPU_C3: i32 = 16384; +const FPU_C0: i32 = 0x100; +pub const FPU_C1: i32 = 0x200; +const FPU_C2: i32 = 0x400; +const FPU_C3: i32 = 0x4000; const FPU_RESULT_FLAGS: i32 = FPU_C0 | FPU_C1 | FPU_C2 | FPU_C3; const INDEFINITE_NAN: f64 = ::std::f64::NAN; const FPU_EX_I: i32 = 1 << 0; const FPU_EX_SF: i32 = 1 << 6; -const TWO_POW_63: f64 = 9223372036854775808u64 as f64; +const TWO_POW_63: f64 = 0x8000000000000000u64 as f64; const F64_MANTISSA_MASK: u64 = (1 << 52) - 1; const F64_EXPONENT_MASK: u16 = 0x7FF; @@ -372,7 +372,7 @@ pub unsafe fn fpu_fistm64p(addr: i32) { value = st0 as i64 } else { - value = 9223372036854775808u64 as i64; + value = -0x80000000_00000000; fpu_invalid_arithmetic(); } return_on_pagefault!(safe_write64(addr, value)); diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index d42212ed..56c91745 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -127,7 +127,7 @@ pub unsafe fn instr16_07() { pub unsafe fn instr32_07() { if !switch_seg( ES, - return_on_pagefault!(safe_read32s(get_stack_pointer(0))) & 65535, + return_on_pagefault!(safe_read32s(get_stack_pointer(0))) & 0xFFFF, ) { return; } @@ -308,7 +308,7 @@ pub unsafe fn instr16_17() { pub unsafe fn instr32_17() { if !switch_seg( SS, - return_on_pagefault!(safe_read32s(get_stack_pointer(0))) & 65535, + return_on_pagefault!(safe_read32s(get_stack_pointer(0))) & 0xFFFF, ) { return; } @@ -408,7 +408,7 @@ pub unsafe fn instr16_1F() { pub unsafe fn instr32_1F() { if !switch_seg( DS, - return_on_pagefault!(safe_read32s(get_stack_pointer(0))) & 65535, + return_on_pagefault!(safe_read32s(get_stack_pointer(0))) & 0xFFFF, ) { return; } @@ -1693,17 +1693,17 @@ pub unsafe fn instr32_99() { *reg32s.offset(EDX as isize) = *reg32s.offset(EAX a pub unsafe fn instr16_9A(new_ip: i32, new_cs: i32) { // callf far_jump(new_ip, new_cs, true); - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 0x10000); } #[no_mangle] pub unsafe fn instr32_9A(new_ip: i32, new_cs: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { - if 0 != new_ip as u32 & 4294901760 { + if 0 != new_ip as u32 & 0xFFFF0000 { dbg_assert!(0 != 0); } } far_jump(new_ip, new_cs, true); - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 0x10000); } #[no_mangle] pub unsafe fn instr_9B() { @@ -1740,7 +1740,7 @@ pub unsafe fn instr32_9C() { } else { // vm and rf flag are cleared in image stored on the stack - return_on_pagefault!(push32(get_eflags() & 16580607)); + return_on_pagefault!(push32(get_eflags() & 0xFCFFFF)); }; } #[no_mangle] @@ -1753,7 +1753,7 @@ pub unsafe fn instr16_9D() { } else { let old_eflags = *flags; - update_eflags(*flags & !65535 | return_on_pagefault!(pop16())); + update_eflags(*flags & !0xFFFF | return_on_pagefault!(pop16())); if old_eflags & FLAG_INTERRUPT == 0 && *flags & FLAG_INTERRUPT != 0 { handle_irqs(); } @@ -2142,7 +2142,7 @@ pub unsafe fn instr16_C2(imm16: i32) { // retn let cs: i32 = get_seg_cs(); *instruction_pointer = cs + return_on_pagefault!(pop16()); - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 0x10000); adjust_stack_reg(imm16); } #[no_mangle] @@ -2150,7 +2150,7 @@ pub unsafe fn instr32_C2(imm16: i32) { // retn let cs: i32 = get_seg_cs(); let ip: i32 = return_on_pagefault!(pop32s()); - dbg_assert!(0 != is_asize_32() as i32 || ip < 65536); + dbg_assert!(0 != is_asize_32() as i32 || ip < 0x10000); *instruction_pointer = cs + ip; adjust_stack_reg(imm16); } @@ -2165,7 +2165,7 @@ pub unsafe fn instr32_C3() { // retn let cs: i32 = get_seg_cs(); let ip: i32 = return_on_pagefault!(pop32s()); - dbg_assert!(0 != is_asize_32() as i32 || ip < 65536); + dbg_assert!(0 != is_asize_32() as i32 || ip < 0x10000); *instruction_pointer = cs + ip; } #[no_mangle] @@ -2242,9 +2242,9 @@ pub unsafe fn instr16_CA(imm16: i32) { pub unsafe fn instr32_CA(imm16: i32) { // retf let ip: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0))); - let cs: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(4))) & 65535; + let cs: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(4))) & 0xFFFF; far_return(ip, cs, imm16); - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 0x10000); } #[no_mangle] pub unsafe fn instr16_CB() { @@ -2252,15 +2252,15 @@ pub unsafe fn instr16_CB() { let ip: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0))); let cs: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(2))); far_return(ip, cs, 0); - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 0x10000); } #[no_mangle] pub unsafe fn instr32_CB() { // retf let ip: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0))); - let cs: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(4))) & 65535; + let cs: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(4))) & 0xFFFF; far_return(ip, cs, 0); - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 0x10000); } #[no_mangle] pub unsafe fn instr_CC() { @@ -2742,7 +2742,7 @@ pub unsafe fn instr_D7() { else { *reg8.offset(AL as isize) = return_on_pagefault!(safe_read8( get_seg_prefix(DS) - + (*reg16.offset(BX as isize) as i32 + *reg8.offset(AL as isize) as i32 & 65535), + + (*reg16.offset(BX as isize) as i32 + *reg8.offset(AL as isize) as i32 & 0xFFFF), )) as u8 }; } @@ -2828,19 +2828,19 @@ pub unsafe fn instr16_E9(imm16: i32) { pub unsafe fn instr32_E9(imm32s: i32) { // jmp *instruction_pointer = *instruction_pointer + imm32s; - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 0x10000); } #[no_mangle] pub unsafe fn instr16_EA(new_ip: i32, cs: i32) { // jmpf far_jump(new_ip, cs, false); - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 0x10000); } #[no_mangle] pub unsafe fn instr32_EA(new_ip: i32, cs: i32) { // jmpf far_jump(new_ip, cs, false); - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 0x10000); } #[no_mangle] pub unsafe fn instr_EC() { @@ -3300,7 +3300,7 @@ pub unsafe fn instr16_FF_2_helper(data: i32) { let cs: i32 = get_seg_cs(); return_on_pagefault!(push16(get_real_eip())); *instruction_pointer = cs + data; - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 0x10000); } #[no_mangle] pub unsafe fn instr16_FF_2_mem(addr: i32) { @@ -3323,13 +3323,13 @@ pub unsafe fn instr16_FF_3_mem(addr: i32) { let new_ip: i32 = return_on_pagefault!(safe_read16(addr)); let new_cs: i32 = return_on_pagefault!(safe_read16(addr + 2)); far_jump(new_ip, new_cs, true); - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 0x10000); } #[no_mangle] pub unsafe fn instr16_FF_4_helper(data: i32) { // jmp near *instruction_pointer = get_seg_cs() + data; - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 0x10000); } #[no_mangle] pub unsafe fn instr16_FF_4_mem(addr: i32) { @@ -3352,7 +3352,7 @@ pub unsafe fn instr16_FF_5_mem(addr: i32) { let new_ip: i32 = return_on_pagefault!(safe_read16(addr)); let new_cs: i32 = return_on_pagefault!(safe_read16(addr + 2)); far_jump(new_ip, new_cs, false); - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 0x10000); } #[no_mangle] pub unsafe fn instr16_FF_6_mem(addr: i32) { @@ -3387,7 +3387,7 @@ pub unsafe fn instr32_FF_2_helper(data: i32) { // call near let cs: i32 = get_seg_cs(); return_on_pagefault!(push32(get_real_eip())); - dbg_assert!(0 != is_asize_32() as i32 || data < 65536); + dbg_assert!(0 != is_asize_32() as i32 || data < 0x10000); *instruction_pointer = cs + data; } #[no_mangle] @@ -3411,17 +3411,17 @@ pub unsafe fn instr32_FF_3_mem(addr: i32) { let new_ip: i32 = return_on_pagefault!(safe_read32s(addr)); let new_cs: i32 = return_on_pagefault!(safe_read16(addr + 4)); if !*protected_mode || 0 != vm86_mode() as i32 { - if 0 != new_ip as u32 & 4294901760 { + if 0 != new_ip as u32 & 0xFFFF0000 { dbg_assert!(0 != 0); } } far_jump(new_ip, new_cs, true); - dbg_assert!(0 != is_asize_32() as i32 || new_ip < 65536); + dbg_assert!(0 != is_asize_32() as i32 || new_ip < 0x10000); } #[no_mangle] pub unsafe fn instr32_FF_4_helper(data: i32) { // jmp near - dbg_assert!(0 != is_asize_32() as i32 || data < 65536); + dbg_assert!(0 != is_asize_32() as i32 || data < 0x10000); *instruction_pointer = get_seg_cs() + data; } #[no_mangle] @@ -3445,12 +3445,12 @@ pub unsafe fn instr32_FF_5_mem(addr: i32) { let new_ip: i32 = return_on_pagefault!(safe_read32s(addr)); let new_cs: i32 = return_on_pagefault!(safe_read16(addr + 4)); if !*protected_mode || 0 != vm86_mode() as i32 { - if 0 != new_ip as u32 & 4294901760 { + if 0 != new_ip as u32 & 0xFFFF0000 { dbg_assert!(0 != 0); } } far_jump(new_ip, new_cs, false); - dbg_assert!(0 != is_asize_32() as i32 || new_ip < 65536); + dbg_assert!(0 != is_asize_32() as i32 || new_ip < 0x10000); } #[no_mangle] pub unsafe fn instr32_FF_6_mem(addr: i32) { @@ -4181,11 +4181,11 @@ pub unsafe fn instr32_E3(imm8s: i32) { jcxz32(imm8s); } pub unsafe fn instr16_EB(imm8: i32) { // jmp near jmp_rel16(imm8); - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 0x10000); } #[no_mangle] pub unsafe fn instr32_EB(imm8: i32) { // jmp near *instruction_pointer = *instruction_pointer + imm8; - dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 65536); + dbg_assert!(0 != is_asize_32() as i32 || get_real_eip() < 0x10000); } diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 11176c3e..cb4cf033 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -213,7 +213,7 @@ pub unsafe fn instr_0F01_0_mem(addr: i32) { -1 } else { - 16777215 + 0xFFFFFF }; safe_write16(addr, *gdtr_size).unwrap(); safe_write32(addr + 2, *gdtr_offset & mask).unwrap(); @@ -228,7 +228,7 @@ pub unsafe fn instr_0F01_1_mem(addr: i32) { -1 } else { - 16777215 + 0xFFFFFF }; safe_write16(addr, *idtr_size).unwrap(); safe_write32(addr + 2, *idtr_offset & mask).unwrap(); @@ -249,7 +249,7 @@ pub unsafe fn instr_0F01_2_mem(addr: i32) { -1 } else { - 16777215 + 0xFFFFFF }; *gdtr_size = size; *gdtr_offset = offset & mask; @@ -272,7 +272,7 @@ pub unsafe fn instr_0F01_3_mem(addr: i32) { -1 } else { - 16777215 + 0xFFFFFF }; *idtr_size = size; *idtr_offset = offset & mask; @@ -286,7 +286,7 @@ pub unsafe fn instr_0F01_4_reg(r: i32) { } #[no_mangle] pub unsafe fn instr_0F01_4_mem(addr: i32) { - return_on_pagefault!(safe_write16(addr, *cr & 65535)); + return_on_pagefault!(safe_write16(addr, *cr & 0xFFFF)); } #[no_mangle] pub unsafe fn lmsw(mut new_cr0: i32) { @@ -813,15 +813,15 @@ pub unsafe fn instr_0F22(r: i32, creg: i32) { if 0 != 0 * 0 { dbg_log!("cr3 <- {:x}", data); } - data &= !4071; - dbg_assert!(data & 4095 == 0, ("TODO")); + data &= !0b111111100111; + dbg_assert!(data & 0xFFF == 0, ("TODO")); *cr.offset(3) = data; clear_tlb(); }, 4 => { dbg_log!("cr4 <- {:x}", *cr.offset(4)); if 0 != data as u32 - & ((1 << 11 | 1 << 12 | 1 << 15 | 1 << 16 | 1 << 19) as u32 | 4290772992) + & ((1 << 11 | 1 << 12 | 1 << 15 | 1 << 16 | 1 << 19) as u32 | 0xFFC00000) { dbg_log!("trigger_gp: Invalid cr4 bit"); trigger_gp_non_raising(0); @@ -1132,7 +1132,7 @@ pub unsafe fn instr_0F30() { dbg_log!("wrmsr ecx={:x} data={:x}:{:x}", index, high, low); } if index == IA32_SYSENTER_CS { - *sysenter_cs = low & 65535 + *sysenter_cs = low & 0xFFFF } else if index == IA32_SYSENTER_EIP { *sysenter_eip = low @@ -1271,7 +1271,7 @@ pub unsafe fn instr_0F33() { #[no_mangle] pub unsafe fn instr_0F34() { // sysenter - let seg: i32 = *sysenter_cs & 65532; + let seg: i32 = *sysenter_cs & 0xFFFC; if !*protected_mode || seg == 0 { trigger_gp_non_raising(0); return; @@ -1298,7 +1298,7 @@ pub unsafe fn instr_0F34() { #[no_mangle] pub unsafe fn instr_0F35() { // sysexit - let seg: i32 = *sysenter_cs & 65532; + let seg: i32 = *sysenter_cs & 0xFFFC; if !*protected_mode || 0 != *cpl as i32 || seg == 0 { trigger_gp_non_raising(0); return; @@ -1840,7 +1840,7 @@ pub unsafe fn instr_0F61(source: i32, r: i32) { // punpcklwd mm, mm/m32 let destination: reg64 = read_mmx64s(r); let word0: i32 = destination.u16_0[0] as i32; - let word1: i32 = source & 65535; + let word1: i32 = source & 0xFFFF; let word2: i32 = destination.u16_0[1] as i32; let word3: i32 = source >> 16; let low: i32 = word0 | word1 << 16; @@ -2010,25 +2010,25 @@ pub unsafe fn instr_0F65(source: reg64, r: i32) { // pcmpgtw mm, mm/m64 let destination: reg64 = read_mmx64s(r); let word0: i32 = if destination.i16_0[0] as i32 > source.i16_0[0] as i32 { - 65535 + 0xFFFF } else { 0 }; let word1: i32 = if destination.i16_0[1] as i32 > source.i16_0[1] as i32 { - 65535 + 0xFFFF } else { 0 }; let word2: i32 = if destination.i16_0[2] as i32 > source.i16_0[2] as i32 { - 65535 + 0xFFFF } else { 0 }; let word3: i32 = if destination.i16_0[3] as i32 > source.i16_0[3] as i32 { - 65535 + 0xFFFF } else { 0 @@ -2055,7 +2055,7 @@ pub unsafe fn instr_660F65(source: reg128, r: i32) { for i in 0..8 { result.u16_0[i as usize] = (if destination.i16_0[i as usize] as i32 > source.i16_0[i as usize] as i32 { - 65535 + 0xFFFF } else { 0 @@ -2441,12 +2441,12 @@ pub unsafe fn instr_F30F6F_mem(addr: i32, r: i32) { pub unsafe fn instr_0F70(source: reg64, r: i32, imm8: i32) { // pshufw mm1, mm2/m64, imm8 let word0_shift: i32 = imm8 & 3; - let word0: u32 = source.u32_0[(word0_shift >> 1) as usize] >> ((word0_shift & 1) << 4) & 65535; + let word0: u32 = source.u32_0[(word0_shift >> 1) as usize] >> ((word0_shift & 1) << 4) & 0xFFFF; let word1_shift: i32 = imm8 >> 2 & 3; let word1: u32 = source.u32_0[(word1_shift >> 1) as usize] >> ((word1_shift & 1) << 4); let low: i32 = (word0 | word1 << 16) as i32; let word2_shift: i32 = imm8 >> 4 & 3; - let word2: u32 = source.u32_0[(word2_shift >> 1) as usize] >> ((word2_shift & 1) << 4) & 65535; + let word2: u32 = source.u32_0[(word2_shift >> 1) as usize] >> ((word2_shift & 1) << 4) & 0xFFFF; let word3_shift: u32 = (imm8 >> 6) as u32; let word3: u32 = source.u32_0[(word3_shift >> 1) as usize] >> ((word3_shift & 1) << 4); let high: i32 = (word2 | word3 << 16) as i32; @@ -2741,25 +2741,25 @@ pub unsafe fn instr_0F75(source: reg64, r: i32) { // pcmpeqw mm, mm/m64 let destination: reg64 = read_mmx64s(r); let word0: i32 = if destination.u16_0[0] as i32 == source.u16_0[0] as i32 { - 65535 + 0xFFFF } else { 0 }; let word1: i32 = if destination.u16_0[1] as i32 == source.u16_0[1] as i32 { - 65535 + 0xFFFF } else { 0 }; let word2: i32 = if destination.u16_0[2] as i32 == source.u16_0[2] as i32 { - 65535 + 0xFFFF } else { 0 }; let word3: i32 = if destination.u16_0[3] as i32 == source.u16_0[3] as i32 { - 65535 + 0xFFFF } else { 0 @@ -2784,7 +2784,7 @@ pub unsafe fn instr_660F75(source: reg128, r: i32) { for i in 0..8 { result.u16_0[i as usize] = (if source.u16_0[i as usize] as i32 == destination.u16_0[i as usize] as i32 { - 65535 + 0xFFFF } else { 0 @@ -2865,7 +2865,7 @@ pub unsafe fn instr_660F76_mem(addr: i32, r: i32) { #[no_mangle] pub unsafe fn instr_0F77() { // emms - fpu_set_tag_word(65535); + fpu_set_tag_word(0xFFFF); } #[no_mangle] pub unsafe fn instr_0F78() { unimplemented_sse(); } @@ -3100,7 +3100,7 @@ pub unsafe fn instr16_0FA1() { pub unsafe fn instr32_0FA1() { if !switch_seg( FS, - return_on_pagefault!(safe_read32s(get_stack_pointer(0))) & 65535, + return_on_pagefault!(safe_read32s(get_stack_pointer(0))) & 0xFFFF, ) { return; } @@ -3198,7 +3198,7 @@ pub unsafe fn instr16_0FA9() { pub unsafe fn instr32_0FA9() { if !switch_seg( GS, - return_on_pagefault!(safe_read32s(get_stack_pointer(0))) & 65535, + return_on_pagefault!(safe_read32s(get_stack_pointer(0))) & 0xFFFF, ) { return; } @@ -3724,7 +3724,7 @@ pub unsafe fn instr_0FC4(source: i32, r: i32, imm8: i32) { // pinsrw mm, r32/m16, imm8 let mut destination: reg64 = read_mmx64s(r); let index: u32 = (imm8 & 3) as u32; - destination.u16_0[index as usize] = (source & 65535) as u16; + destination.u16_0[index as usize] = (source & 0xFFFF) as u16; write_mmx_reg64(r, destination); transition_fpu_to_mmx(); } @@ -3739,7 +3739,7 @@ pub unsafe fn instr_660FC4(source: i32, r: i32, imm8: i32) { // pinsrw xmm, r32/m16, imm8 let mut destination: reg128 = read_xmm128s(r); let index: u32 = (imm8 & 7) as u32; - destination.u16_0[index as usize] = (source & 65535) as u16; + destination.u16_0[index as usize] = (source & 0xFFFF) as u16; write_xmm_reg128(r, destination); } #[no_mangle] @@ -3972,10 +3972,10 @@ pub unsafe fn instr_660FD4_mem(addr: i32, r: i32) { pub unsafe fn instr_0FD5(source: reg64, r: i32) { // pmullw mm, mm/m64 let destination: reg64 = read_mmx64s(r); - let word0: i32 = destination.u16_0[0] as i32 * source.u16_0[0] as i32 & 65535; - let word1: i32 = destination.u16_0[1] as i32 * source.u16_0[1] as i32 & 65535; - let word2: i32 = destination.u16_0[2] as i32 * source.u16_0[2] as i32 & 65535; - let word3: i32 = destination.u16_0[3] as i32 * source.u16_0[3] as i32 & 65535; + let word0: i32 = destination.u16_0[0] as i32 * source.u16_0[0] as i32 & 0xFFFF; + let word1: i32 = destination.u16_0[1] as i32 * source.u16_0[1] as i32 & 0xFFFF; + let word2: i32 = destination.u16_0[2] as i32 * source.u16_0[2] as i32 & 0xFFFF; + let word3: i32 = destination.u16_0[3] as i32 * source.u16_0[3] as i32 & 0xFFFF; let low: i32 = word0 | word1 << 16; let high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); @@ -3994,13 +3994,13 @@ pub unsafe fn instr_660FD5(source: reg128, r: i32) { let destination: reg128 = read_xmm128s(r); write_xmm128( r, - source.u16_0[0] as i32 * destination.u16_0[0] as i32 & 65535 + source.u16_0[0] as i32 * destination.u16_0[0] as i32 & 0xFFFF | (source.u16_0[1] as i32 * destination.u16_0[1] as i32) << 16, - source.u16_0[2] as i32 * destination.u16_0[2] as i32 & 65535 + source.u16_0[2] as i32 * destination.u16_0[2] as i32 & 0xFFFF | (source.u16_0[3] as i32 * destination.u16_0[3] as i32) << 16, - source.u16_0[4] as i32 * destination.u16_0[4] as i32 & 65535 + source.u16_0[4] as i32 * destination.u16_0[4] as i32 & 0xFFFF | (source.u16_0[5] as i32 * destination.u16_0[5] as i32) << 16, - source.u16_0[6] as i32 * destination.u16_0[6] as i32 & 65535 + source.u16_0[6] as i32 * destination.u16_0[6] as i32 & 0xFFFF | (source.u16_0[7] as i32 * destination.u16_0[7] as i32) << 16, ); } @@ -4520,11 +4520,11 @@ pub unsafe fn instr_0FE4(source: reg64, r: i32) { let destination: reg64 = read_mmx64s(r); write_mmx64( r, - ((source.u16_0[0] as i32 * destination.u16_0[0] as i32 >> 16 & 65535) as u32 - | (source.u16_0[1] as i32 * destination.u16_0[1] as i32) as u32 & 4294901760) + ((source.u16_0[0] as i32 * destination.u16_0[0] as i32 >> 16 & 0xFFFF) as u32 + | (source.u16_0[1] as i32 * destination.u16_0[1] as i32) as u32 & 0xFFFF0000) as i32, - ((source.u16_0[2] as i32 * destination.u16_0[2] as i32 >> 16 & 65535) as u32 - | (source.u16_0[3] as i32 * destination.u16_0[3] as i32) as u32 & 4294901760) + ((source.u16_0[2] as i32 * destination.u16_0[2] as i32 >> 16 & 0xFFFF) as u32 + | (source.u16_0[3] as i32 * destination.u16_0[3] as i32) as u32 & 0xFFFF0000) as i32, ); transition_fpu_to_mmx(); @@ -4542,17 +4542,17 @@ pub unsafe fn instr_660FE4(source: reg128, r: i32) { let destination: reg128 = read_xmm128s(r); write_xmm128( r, - ((source.u16_0[0] as i32 * destination.u16_0[0] as i32 >> 16 & 65535) as u32 - | (source.u16_0[1] as i32 * destination.u16_0[1] as i32) as u32 & 4294901760) + ((source.u16_0[0] as i32 * destination.u16_0[0] as i32 >> 16 & 0xFFFF) as u32 + | (source.u16_0[1] as i32 * destination.u16_0[1] as i32) as u32 & 0xFFFF0000) as i32, - ((source.u16_0[2] as i32 * destination.u16_0[2] as i32 >> 16 & 65535) as u32 - | (source.u16_0[3] as i32 * destination.u16_0[3] as i32) as u32 & 4294901760) + ((source.u16_0[2] as i32 * destination.u16_0[2] as i32 >> 16 & 0xFFFF) as u32 + | (source.u16_0[3] as i32 * destination.u16_0[3] as i32) as u32 & 0xFFFF0000) as i32, - ((source.u16_0[4] as i32 * destination.u16_0[4] as i32 >> 16 & 65535) as u32 - | (source.u16_0[5] as i32 * destination.u16_0[5] as i32) as u32 & 4294901760) + ((source.u16_0[4] as i32 * destination.u16_0[4] as i32 >> 16 & 0xFFFF) as u32 + | (source.u16_0[5] as i32 * destination.u16_0[5] as i32) as u32 & 0xFFFF0000) as i32, - ((source.u16_0[6] as i32 * destination.u16_0[6] as i32 >> 16 & 65535) as u32 - | (source.u16_0[7] as i32 * destination.u16_0[7] as i32) as u32 & 4294901760) + ((source.u16_0[6] as i32 * destination.u16_0[6] as i32 >> 16 & 0xFFFF) as u32 + | (source.u16_0[7] as i32 * destination.u16_0[7] as i32) as u32 & 0xFFFF0000) as i32, ); } @@ -4566,10 +4566,10 @@ pub unsafe fn instr_660FE4_mem(addr: i32, r: i32) { pub unsafe fn instr_0FE5(source: reg64, r: i32) { // pmulhw mm, mm/m64 let destination: reg64 = read_mmx64s(r); - let word0: u32 = (destination.i16_0[0] as i32 * source.i16_0[0] as i32 >> 16 & 65535) as u32; - let word1: u32 = (destination.i16_0[1] as i32 * source.i16_0[1] as i32 >> 16 & 65535) as u32; - let word2: u32 = (destination.i16_0[2] as i32 * source.i16_0[2] as i32 >> 16 & 65535) as u32; - let word3: u32 = (destination.i16_0[3] as i32 * source.i16_0[3] as i32 >> 16 & 65535) as u32; + let word0: u32 = (destination.i16_0[0] as i32 * source.i16_0[0] as i32 >> 16 & 0xFFFF) as u32; + let word1: u32 = (destination.i16_0[1] as i32 * source.i16_0[1] as i32 >> 16 & 0xFFFF) as u32; + let word2: u32 = (destination.i16_0[2] as i32 * source.i16_0[2] as i32 >> 16 & 0xFFFF) as u32; + let word3: u32 = (destination.i16_0[3] as i32 * source.i16_0[3] as i32 >> 16 & 0xFFFF) as u32; let low: i32 = (word0 | word1 << 16) as i32; let high: i32 = (word2 | word3 << 16) as i32; write_mmx64(r, low, high); @@ -4586,17 +4586,17 @@ pub unsafe fn instr_660FE5(source: reg128, r: i32) { // pmulhw xmm, xmm/m128 // XXX: Aligned access or #gp let destination: reg128 = read_xmm128s(r); - let dword0: i32 = ((destination.i16_0[0] as i32 * source.i16_0[0] as i32 >> 16 & 65535) as u32 - | (destination.i16_0[1] as i32 * source.i16_0[1] as i32) as u32 & 4294901760) + let dword0: i32 = ((destination.i16_0[0] as i32 * source.i16_0[0] as i32 >> 16 & 0xFFFF) as u32 + | (destination.i16_0[1] as i32 * source.i16_0[1] as i32) as u32 & 0xFFFF0000) as i32; - let dword1: i32 = ((destination.i16_0[2] as i32 * source.i16_0[2] as i32 >> 16 & 65535) as u32 - | (destination.i16_0[3] as i32 * source.i16_0[3] as i32) as u32 & 4294901760) + let dword1: i32 = ((destination.i16_0[2] as i32 * source.i16_0[2] as i32 >> 16 & 0xFFFF) as u32 + | (destination.i16_0[3] as i32 * source.i16_0[3] as i32) as u32 & 0xFFFF0000) as i32; - let dword2: i32 = ((destination.i16_0[4] as i32 * source.i16_0[4] as i32 >> 16 & 65535) as u32 - | (destination.i16_0[5] as i32 * source.i16_0[5] as i32) as u32 & 4294901760) + let dword2: i32 = ((destination.i16_0[4] as i32 * source.i16_0[4] as i32 >> 16 & 0xFFFF) as u32 + | (destination.i16_0[5] as i32 * source.i16_0[5] as i32) as u32 & 0xFFFF0000) as i32; - let dword3: i32 = ((destination.i16_0[6] as i32 * source.i16_0[6] as i32 >> 16 & 65535) as u32 - | (destination.i16_0[7] as i32 * source.i16_0[7] as i32) as u32 & 4294901760) + let dword3: i32 = ((destination.i16_0[6] as i32 * source.i16_0[6] as i32 >> 16 & 0xFFFF) as u32 + | (destination.i16_0[7] as i32 * source.i16_0[7] as i32) as u32 & 0xFFFF0000) as i32; write_xmm128(r, dword0, dword1, dword2, dword3); } @@ -5283,13 +5283,13 @@ pub unsafe fn instr_660FF8_mem(addr: i32, r: i32) { pub unsafe fn instr_0FF9(source: reg64, r: i32) { // psubw mm, mm/m64 let destination: reg64 = read_mmx64s(r); - let word0: i32 = (destination.u32_0[0].wrapping_sub(source.u32_0[0]) & 65535) as i32; + let word0: i32 = (destination.u32_0[0].wrapping_sub(source.u32_0[0]) & 0xFFFF) as i32; let word1: i32 = - ((destination.u16_0[1] as u32).wrapping_sub(source.u16_0[1] as u32) & 65535) as i32; + ((destination.u16_0[1] as u32).wrapping_sub(source.u16_0[1] as u32) & 0xFFFF) as i32; let low: i32 = word0 | word1 << 16; - let word2: i32 = (destination.u32_0[1].wrapping_sub(source.u32_0[1]) & 65535) as i32; + let word2: i32 = (destination.u32_0[1].wrapping_sub(source.u32_0[1]) & 0xFFFF) as i32; let word3: i32 = - ((destination.u16_0[3] as u32).wrapping_sub(source.u16_0[3] as u32) & 65535) as i32; + ((destination.u16_0[3] as u32).wrapping_sub(source.u16_0[3] as u32) & 0xFFFF) as i32; let high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); transition_fpu_to_mmx(); @@ -5309,8 +5309,9 @@ pub unsafe fn instr_660FF9(source: reg128, r: i32) { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; for i in 0..8 { - result.i16_0[i as usize] = - (destination.i16_0[i as usize] as i32 - source.i16_0[i as usize] as i32 & 65535) as i16; + result.i16_0[i as usize] = (destination.i16_0[i as usize] as i32 + - source.i16_0[i as usize] as i32 + & 0xFFFF) as i16; } write_xmm_reg128(r, result); } @@ -5429,11 +5430,11 @@ pub unsafe fn instr_660FFC_mem(addr: i32, r: i32) { pub unsafe fn instr_0FFD(source: reg64, r: i32) { // paddw mm, mm/m64 let destination: reg64 = read_mmx64s(r); - let word0: i32 = (destination.u32_0[0].wrapping_add(source.u32_0[0]) & 65535) as i32; - let word1: i32 = destination.u16_0[1] as i32 + source.u16_0[1] as i32 & 65535; + let word0: i32 = (destination.u32_0[0].wrapping_add(source.u32_0[0]) & 0xFFFF) as i32; + let word1: i32 = destination.u16_0[1] as i32 + source.u16_0[1] as i32 & 0xFFFF; let low: i32 = word0 | word1 << 16; - let word2: i32 = (destination.u32_0[1].wrapping_add(source.u32_0[1]) & 65535) as i32; - let word3: i32 = destination.u16_0[3] as i32 + source.u16_0[3] as i32 & 65535; + let word2: i32 = (destination.u32_0[1].wrapping_add(source.u32_0[1]) & 0xFFFF) as i32; + let word3: i32 = destination.u16_0[3] as i32 + source.u16_0[3] as i32 & 0xFFFF; let high: i32 = word2 | word3 << 16; write_mmx64(r, low, high); transition_fpu_to_mmx(); @@ -5453,8 +5454,9 @@ pub unsafe fn instr_660FFD(source: reg128, r: i32) { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; for i in 0..8 { - result.u16_0[i as usize] = - (destination.u16_0[i as usize] as i32 + source.u16_0[i as usize] as i32 & 65535) as u16; + result.u16_0[i as usize] = (destination.u16_0[i as usize] as i32 + + source.u16_0[i as usize] as i32 + & 0xFFFF) as u16; } write_xmm_reg128(r, result); } diff --git a/src/rust/cpu2/memory.rs b/src/rust/cpu2/memory.rs index febdac56..3760b1b4 100644 --- a/src/rust/cpu2/memory.rs +++ b/src/rust/cpu2/memory.rs @@ -24,7 +24,7 @@ const USE_A20: bool = false; #[no_mangle] pub unsafe fn in_mapped_range(addr: u32) -> bool { - return addr >= 655360 as u32 && addr < 786432 as u32 || addr >= *memory_size; + return addr >= 0xA0000 && addr < 0xC0000 || addr >= *memory_size; } #[no_mangle] @@ -53,7 +53,7 @@ pub unsafe fn read16(mut addr: u32) -> i32 { } #[no_mangle] pub unsafe fn read_aligned16(mut addr: u32) -> i32 { - dbg_assert!(addr < 2147483648); + dbg_assert!(addr < 0x80000000); if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK16 as u32 } @@ -90,7 +90,7 @@ pub unsafe fn read64s(mut addr: u32) -> i64 { } #[no_mangle] pub unsafe fn read_aligned32(mut addr: u32) -> i32 { - dbg_assert!(addr < 1073741824 as u32); + dbg_assert!(addr < 0x40000000 as u32); if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK32 as u32 } @@ -155,7 +155,7 @@ pub unsafe fn write16(mut addr: u32, value: i32) { } #[no_mangle] pub unsafe fn write_aligned16(mut addr: u32, value: u32) { - dbg_assert!(addr < 2147483648); + dbg_assert!(addr < 0x80000000); if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK16 as u32 } @@ -188,7 +188,7 @@ pub unsafe fn write_aligned32_no_mmap_or_dirty_check(addr: u32, value: i32) { #[no_mangle] pub unsafe fn write_aligned32(mut addr: u32, value: i32) { - dbg_assert!(addr < 1073741824 as u32); + dbg_assert!(addr < 0x40000000 as u32); if 0 != USE_A20 as i32 && !*a20_enabled { addr &= A20_MASK32 as u32 } @@ -209,7 +209,7 @@ pub unsafe fn write64(mut addr: u32, value: i64) { if in_mapped_range(addr) { mmap_write32( addr.wrapping_add(0 as u32), - (value & 4294967295 as i64) as i32, + (value & 0xFFFFFFFF as i64) as i32, ); mmap_write32(addr.wrapping_add(4 as u32), (value >> 32) as i32); } diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index 61df893d..ca117f34 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -19,7 +19,7 @@ pub unsafe fn getcf() -> bool { pub unsafe fn getpf() -> bool { if 0 != *flags_changed & FLAG_PARITY { // inverted lookup table - return 0 != 38505 << 2 >> ((*last_result ^ *last_result >> 4) & 15) & FLAG_PARITY; + return 0 != 0x9669 << 2 >> ((*last_result ^ *last_result >> 4) & 15) & FLAG_PARITY; } else { return 0 != *flags & FLAG_PARITY; @@ -99,7 +99,7 @@ pub unsafe fn test_nle() -> bool { return !test_le(); } pub unsafe fn jmp_rel16(rel16: i32) { let cs_offset: i32 = get_seg_cs(); // limit ip to 16 bit - *instruction_pointer = cs_offset + (*instruction_pointer - cs_offset + rel16 & 65535); + *instruction_pointer = cs_offset + (*instruction_pointer - cs_offset + rel16 & 0xFFFF); } #[no_mangle] pub unsafe fn jmpcc16(condition: bool, imm16: i32) { @@ -147,7 +147,7 @@ pub unsafe fn get_stack_pointer(offset: i32) -> i32 { return get_seg_ss() + *reg32s.offset(ESP as isize) + offset; } else { - return get_seg_ss() + (*reg16.offset(SP as isize) as i32 + offset & 65535); + return get_seg_ss() + (*reg16.offset(SP as isize) as i32 + offset & 0xFFFF); }; } #[no_mangle] @@ -162,7 +162,7 @@ pub unsafe fn adjust_stack_reg(adjustment: i32) { #[no_mangle] pub unsafe fn push16_ss16(imm16: i32) -> OrPageFault<()> { - let sp: i32 = get_seg_ss() + (*reg16.offset(SP as isize) as i32 - 2 & 65535); + let sp: i32 = get_seg_ss() + (*reg16.offset(SP as isize) as i32 - 2 & 0xFFFF); safe_write16(sp, imm16)?; *reg16.offset(SP as isize) -= 2; Ok(()) @@ -202,7 +202,7 @@ pub unsafe fn push16(imm16: i32) -> OrPageFault<()> { #[no_mangle] pub unsafe fn push32_ss16(imm32: i32) -> OrPageFault<()> { - let new_sp: i32 = *reg16.offset(SP as isize) as i32 - 4 & 65535; + let new_sp: i32 = *reg16.offset(SP as isize) as i32 - 4 & 0xFFFF; safe_write32(get_seg_ss() + new_sp, imm32)?; *reg16.offset(SP as isize) = new_sp as u16; Ok(()) diff --git a/src/rust/cpu2/modrm.rs b/src/rust/cpu2/modrm.rs index 3698ef9a..d453dd74 100644 --- a/src/rust/cpu2/modrm.rs +++ b/src/rust/cpu2/modrm.rs @@ -5,82 +5,82 @@ use paging::OrPageFault; pub unsafe fn resolve_modrm16(modrm_byte: i32) -> OrPageFault { Ok(match modrm_byte { 0 | 8 | 16 | 24 | 32 | 40 | 48 | 56 => get_seg_prefix_ds( - *reg16.offset(BX as isize) as i32 + *reg16.offset(SI as isize) as i32 & 65535, + *reg16.offset(BX as isize) as i32 + *reg16.offset(SI as isize) as i32 & 0xFFFF, ), 64 | 72 | 80 | 88 | 96 | 104 | 112 | 120 => get_seg_prefix_ds( *reg16.offset(BX as isize) as i32 + *reg16.offset(SI as isize) as i32 + read_imm8s()? - & 65535, + & 0xFFFF, ), 128 | 136 | 144 | 152 | 160 | 168 | 176 | 184 => get_seg_prefix_ds( *reg16.offset(BX as isize) as i32 + *reg16.offset(SI as isize) as i32 + read_imm16()? - & 65535, + & 0xFFFF, ), 1 | 9 | 17 | 25 | 33 | 41 | 49 | 57 => get_seg_prefix_ds( - *reg16.offset(BX as isize) as i32 + *reg16.offset(DI as isize) as i32 & 65535, + *reg16.offset(BX as isize) as i32 + *reg16.offset(DI as isize) as i32 & 0xFFFF, ), 65 | 73 | 81 | 89 | 97 | 105 | 113 | 121 => get_seg_prefix_ds( *reg16.offset(BX as isize) as i32 + *reg16.offset(DI as isize) as i32 + read_imm8s()? - & 65535, + & 0xFFFF, ), 129 | 137 | 145 | 153 | 161 | 169 | 177 | 185 => get_seg_prefix_ds( *reg16.offset(BX as isize) as i32 + *reg16.offset(DI as isize) as i32 + read_imm16()? - & 65535, + & 0xFFFF, ), 2 | 10 | 18 | 26 | 34 | 42 | 50 | 58 => get_seg_prefix_ss( - *reg16.offset(BP as isize) as i32 + *reg16.offset(SI as isize) as i32 & 65535, + *reg16.offset(BP as isize) as i32 + *reg16.offset(SI as isize) as i32 & 0xFFFF, ), 66 | 74 | 82 | 90 | 98 | 106 | 114 | 122 => get_seg_prefix_ss( *reg16.offset(BP as isize) as i32 + *reg16.offset(SI as isize) as i32 + read_imm8s()? - & 65535, + & 0xFFFF, ), 130 | 138 | 146 | 154 | 162 | 170 | 178 | 186 => get_seg_prefix_ss( *reg16.offset(BP as isize) as i32 + *reg16.offset(SI as isize) as i32 + read_imm16()? - & 65535, + & 0xFFFF, ), 3 | 11 | 19 | 27 | 35 | 43 | 51 | 59 => get_seg_prefix_ss( - *reg16.offset(BP as isize) as i32 + *reg16.offset(DI as isize) as i32 & 65535, + *reg16.offset(BP as isize) as i32 + *reg16.offset(DI as isize) as i32 & 0xFFFF, ), 67 | 75 | 83 | 91 | 99 | 107 | 115 | 123 => get_seg_prefix_ss( *reg16.offset(BP as isize) as i32 + *reg16.offset(DI as isize) as i32 + read_imm8s()? - & 65535, + & 0xFFFF, ), 131 | 139 | 147 | 155 | 163 | 171 | 179 | 187 => get_seg_prefix_ss( *reg16.offset(BP as isize) as i32 + *reg16.offset(DI as isize) as i32 + read_imm16()? - & 65535, + & 0xFFFF, ), 4 | 12 | 20 | 28 | 36 | 44 | 52 | 60 => { - get_seg_prefix_ds(*reg16.offset(SI as isize) as i32 & 65535) + get_seg_prefix_ds(*reg16.offset(SI as isize) as i32 & 0xFFFF) }, 68 | 76 | 84 | 92 | 100 | 108 | 116 | 124 => { - get_seg_prefix_ds(*reg16.offset(SI as isize) as i32 + read_imm8s()? & 65535) + get_seg_prefix_ds(*reg16.offset(SI as isize) as i32 + read_imm8s()? & 0xFFFF) }, 132 | 140 | 148 | 156 | 164 | 172 | 180 | 188 => { - get_seg_prefix_ds(*reg16.offset(SI as isize) as i32 + read_imm16()? & 65535) + get_seg_prefix_ds(*reg16.offset(SI as isize) as i32 + read_imm16()? & 0xFFFF) }, 5 | 13 | 21 | 29 | 37 | 45 | 53 | 61 => { - get_seg_prefix_ds(*reg16.offset(DI as isize) as i32 & 65535) + get_seg_prefix_ds(*reg16.offset(DI as isize) as i32 & 0xFFFF) }, 69 | 77 | 85 | 93 | 101 | 109 | 117 | 125 => { - get_seg_prefix_ds(*reg16.offset(DI as isize) as i32 + read_imm8s()? & 65535) + get_seg_prefix_ds(*reg16.offset(DI as isize) as i32 + read_imm8s()? & 0xFFFF) }, 133 | 141 | 149 | 157 | 165 | 173 | 181 | 189 => { - get_seg_prefix_ds(*reg16.offset(DI as isize) as i32 + read_imm16()? & 65535) + get_seg_prefix_ds(*reg16.offset(DI as isize) as i32 + read_imm16()? & 0xFFFF) }, 6 | 14 | 22 | 30 | 38 | 46 | 54 | 62 => get_seg_prefix_ds(read_imm16()?), 70 | 78 | 86 | 94 | 102 | 110 | 118 | 126 => { - get_seg_prefix_ss(*reg16.offset(BP as isize) as i32 + read_imm8s()? & 65535) + get_seg_prefix_ss(*reg16.offset(BP as isize) as i32 + read_imm8s()? & 0xFFFF) }, 134 | 142 | 150 | 158 | 166 | 174 | 182 | 190 => { - get_seg_prefix_ss(*reg16.offset(BP as isize) as i32 + read_imm16()? & 65535) + get_seg_prefix_ss(*reg16.offset(BP as isize) as i32 + read_imm16()? & 0xFFFF) }, 7 | 15 | 23 | 31 | 39 | 47 | 55 | 63 => { - get_seg_prefix_ds(*reg16.offset(BX as isize) as i32 & 65535) + get_seg_prefix_ds(*reg16.offset(BX as isize) as i32 & 0xFFFF) }, 71 | 79 | 87 | 95 | 103 | 111 | 119 | 127 => { - get_seg_prefix_ds(*reg16.offset(BX as isize) as i32 + read_imm8s()? & 65535) + get_seg_prefix_ds(*reg16.offset(BX as isize) as i32 + read_imm8s()? & 0xFFFF) }, 135 | 143 | 151 | 159 | 167 | 175 | 183 | 191 => { - get_seg_prefix_ds(*reg16.offset(BX as isize) as i32 + read_imm16()? & 65535) + get_seg_prefix_ds(*reg16.offset(BX as isize) as i32 + read_imm16()? & 0xFFFF) }, _ => { dbg_assert!(0 != 0); diff --git a/src/rust/cpu2/sse_instr.rs b/src/rust/cpu2/sse_instr.rs index 7ddc18e4..f3904b51 100644 --- a/src/rust/cpu2/sse_instr.rs +++ b/src/rust/cpu2/sse_instr.rs @@ -115,9 +115,9 @@ pub unsafe fn psraw_r64(r: i32, shift: u64) { // psraw mm, {shift} let destination: reg64 = read_mmx64s(r); let shift_clamped: i32 = (if shift > 15 { 16 } else { shift }) as i32; - let dword0: i32 = destination.i16_0[0] as i32 >> shift_clamped & 65535 + let dword0: i32 = destination.i16_0[0] as i32 >> shift_clamped & 0xFFFF | destination.i16_0[1] as i32 >> shift_clamped << 16; - let dword1: i32 = destination.i16_0[2] as i32 >> shift_clamped & 65535 + let dword1: i32 = destination.i16_0[2] as i32 >> shift_clamped & 0xFFFF | destination.i16_0[3] as i32 >> shift_clamped << 16; write_mmx64(r, dword0, dword1); transition_fpu_to_mmx(); @@ -129,9 +129,9 @@ pub unsafe fn psllw_r64(r: i32, shift: u64) { let mut dword0: i32 = 0; let mut dword1: i32 = 0; if shift <= 15 { - dword0 = (destination.u16_0[0] as i32) << shift & 65535 + dword0 = (destination.u16_0[0] as i32) << shift & 0xFFFF | (destination.u16_0[1] as i32) << shift << 16; - dword1 = (destination.u16_0[2] as i32) << shift & 65535 + dword1 = (destination.u16_0[2] as i32) << shift & 0xFFFF | (destination.u16_0[3] as i32) << shift << 16 } write_mmx64(r, dword0, dword1); @@ -232,13 +232,13 @@ pub unsafe fn psraw_r128(r: i32, shift: u64) { // psraw xmm, {shift} let destination: reg128 = read_xmm128s(r); let shift_clamped: i32 = (if shift > 15 { 16 } else { shift as u32 }) as i32; - let dword0: i32 = destination.i16_0[0] as i32 >> shift_clamped & 65535 + let dword0: i32 = destination.i16_0[0] as i32 >> shift_clamped & 0xFFFF | destination.i16_0[1] as i32 >> shift_clamped << 16; - let dword1: i32 = destination.i16_0[2] as i32 >> shift_clamped & 65535 + let dword1: i32 = destination.i16_0[2] as i32 >> shift_clamped & 0xFFFF | destination.i16_0[3] as i32 >> shift_clamped << 16; - let dword2: i32 = destination.i16_0[4] as i32 >> shift_clamped & 65535 + let dword2: i32 = destination.i16_0[4] as i32 >> shift_clamped & 0xFFFF | destination.i16_0[5] as i32 >> shift_clamped << 16; - let dword3: i32 = destination.i16_0[6] as i32 >> shift_clamped & 65535 + let dword3: i32 = destination.i16_0[6] as i32 >> shift_clamped & 0xFFFF | destination.i16_0[7] as i32 >> shift_clamped << 16; write_xmm128(r, dword0, dword1, dword2, dword3); } @@ -251,13 +251,13 @@ pub unsafe fn psllw_r128(r: i32, shift: u64) { let mut dword2: i32 = 0; let mut dword3: i32 = 0; if shift <= 15 { - dword0 = (destination.u16_0[0] as i32) << shift & 65535 + dword0 = (destination.u16_0[0] as i32) << shift & 0xFFFF | (destination.u16_0[1] as i32) << shift << 16; - dword1 = (destination.u16_0[2] as i32) << shift & 65535 + dword1 = (destination.u16_0[2] as i32) << shift & 0xFFFF | (destination.u16_0[3] as i32) << shift << 16; - dword2 = (destination.u16_0[4] as i32) << shift & 65535 + dword2 = (destination.u16_0[4] as i32) << shift & 0xFFFF | (destination.u16_0[5] as i32) << shift << 16; - dword3 = (destination.u16_0[6] as i32) << shift & 65535 + dword3 = (destination.u16_0[6] as i32) << shift & 0xFFFF | (destination.u16_0[7] as i32) << shift << 16 } write_xmm128(r, dword0, dword1, dword2, dword3); diff --git a/src/rust/cpu2/string.rs b/src/rust/cpu2/string.rs index a9236ed6..0062a305 100644 --- a/src/rust/cpu2/string.rs +++ b/src/rust/cpu2/string.rs @@ -30,12 +30,12 @@ pub unsafe fn string_get_cycle_count(mut size: i32, mut address: i32) -> i32 { dbg_assert!(0 != size && size <= 4 && size >= -4); if size < 0 { size = -size; - address = 4096 - address - size + address = 0x1000 - address - size } dbg_assert!(address & size - 1 == 0); // 1 -> 0; 2 -> 1; 4 -> 2 let shift: i32 = size >> 1; - return 4096 - (address & 4095) >> shift; + return 0x1000 - (address & 0xFFF) >> shift; } #[no_mangle] pub unsafe fn string_get_cycle_count2(size: i32, addr1: i32, addr2: i32) -> i32 { From c08a99c59102265b7c1d01362908db9069a631df Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 11 Sep 2018 00:09:28 -0500 Subject: [PATCH 1350/2137] c2rust cleanup: Fix boolean literals --- src/rust/cpu2/cpu.rs | 102 +++++++++++++++---------------- src/rust/cpu2/fpu.rs | 2 +- src/rust/cpu2/instructions.rs | 33 +++++----- src/rust/cpu2/instructions_0f.rs | 30 ++++----- src/rust/cpu2/modrm.rs | 14 ++--- src/rust/cpu2/sse_instr.rs | 4 +- 6 files changed, 92 insertions(+), 93 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 0b1f30f1..3c1b8dad 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -238,9 +238,9 @@ pub const DEBUG: bool = cfg!(debug_assertions); pub const LOOP_COUNTER: i32 = 20011; pub const TSC_RATE: f64 = (50 * 1000) as f64; -pub static mut jit_block_boundary: bool = 0 != 0; +pub static mut jit_block_boundary: bool = false; -pub static mut must_not_fault: bool = 0 != 0; +pub static mut must_not_fault: bool = false; pub static mut rdtsc_imprecision_offset: u64 = 0; pub static mut rdtsc_last_value: u64 = 0; pub static mut tsc_offset: u64 = 0; @@ -302,7 +302,7 @@ impl SegmentDescriptor { //pub fn call_indirect1(f: fn(u16), x: u16) { f(x); } -pub unsafe fn after_block_boundary() { jit_block_boundary = 0 != 1; } +pub unsafe fn after_block_boundary() { jit_block_boundary = true; } pub unsafe fn same_page(addr1: i32, addr2: i32) -> bool { return addr1 & !0xFFF == addr2 & !0xFFF; } @@ -325,20 +325,20 @@ pub unsafe fn translate_address_read(address: i32) -> OrPageFault { return Ok((entry & !0xFFF ^ address) as u32); } else { - return Ok((do_page_translation(address, 0 != 0, user)? | address & 0xFFF) as u32); + return Ok((do_page_translation(address, false, user)? | address & 0xFFF) as u32); }; } pub unsafe fn do_page_translation(addr: i32, for_writing: bool, user: bool) -> OrPageFault { - let mut can_write: bool = 0 != 1; + let mut can_write: bool = true; let global; - let mut allow_user: bool = 0 != 1; + let mut allow_user: bool = true; let page: i32 = (addr as u32 >> 12) as i32; let high; if *cr & CR0_PG == 0 { // paging disabled high = (addr as u32 & 0xFFFFF000) as i32; - global = 0 != 0 + global = false } else { let page_dir_addr: i32 = @@ -353,23 +353,23 @@ pub unsafe fn do_page_translation(addr: i32, for_writing: bool, user: bool) -> O // - call_interrupt_vector with id 14, error code 0-7 (requires information if read or write) // - prevent execution of the function that triggered this call *cr.offset(2) = addr; - trigger_pagefault(for_writing, user, 0 != 0); + trigger_pagefault(for_writing, user, false); return Err(()); } if page_dir_entry & PAGE_TABLE_RW_MASK == 0 && !kernel_write_override { - can_write = 0 != 0; + can_write = false; if for_writing { *cr.offset(2) = addr; - trigger_pagefault(for_writing, user, 0 != 1); + trigger_pagefault(for_writing, user, true); return Err(()); } } if page_dir_entry & PAGE_TABLE_USER_MASK == 0 { - allow_user = 0 != 0; + allow_user = false; if user { // Page Fault: page table accessed by non-supervisor *cr.offset(2) = addr; - trigger_pagefault(for_writing, user, 0 != 1); + trigger_pagefault(for_writing, user, true); return Err(()); } } @@ -397,22 +397,22 @@ pub unsafe fn do_page_translation(addr: i32, for_writing: bool, user: bool) -> O let page_table_entry: i32 = read_aligned32(page_table_addr as u32); if page_table_entry & PAGE_TABLE_PRESENT_MASK == 0 { *cr.offset(2) = addr; - trigger_pagefault(for_writing, user, 0 != 0); + trigger_pagefault(for_writing, user, false); return Err(()); } if page_table_entry & PAGE_TABLE_RW_MASK == 0 && !kernel_write_override { - can_write = 0 != 0; + can_write = false; if for_writing { *cr.offset(2) = addr; - trigger_pagefault(for_writing, user, 0 != 1); + trigger_pagefault(for_writing, user, true); return Err(()); } } if page_table_entry & PAGE_TABLE_USER_MASK == 0 { - allow_user = 0 != 0; + allow_user = false; if user { *cr.offset(2) = addr; - trigger_pagefault(for_writing, user, 0 != 1); + trigger_pagefault(for_writing, user, true); return Err(()); } } @@ -456,10 +456,10 @@ pub unsafe fn do_page_translation(addr: i32, for_writing: bool, user: bool) -> O // entries from tlb_data but not from valid_tlb_entries } else if CHECK_TLB_INVARIANTS { - let mut found: bool = 0 != 0; + let mut found: bool = false; for i in 0..valid_tlb_entries_count { if valid_tlb_entries[i as usize] == page { - found = 0 != 1; + found = true; break; } } @@ -553,7 +553,7 @@ pub unsafe fn clear_tlb() { } pub unsafe fn trigger_pagefault(write: bool, user: bool, present: bool) { - if 0 != 0 * 0 { + if false { dbg_log!( "page fault w={} u={} p={} eip={:x} cr2={:x}", write as i32, @@ -568,23 +568,23 @@ pub unsafe fn trigger_pagefault(write: bool, user: bool, present: bool) { if must_not_fault { dbg_log!("Unexpected page fault"); dbg_trace(); - dbg_assert!(0 != 0); + dbg_assert!(false); } } //if *page_fault { // dbg_log!(("double fault")); // dbg_trace(); - // dbg_assert!(0 != 0); + // dbg_assert!(false); //} // invalidate tlb entry let page: i32 = (*cr.offset(2) as u32 >> 12) as i32; *tlb_data.offset(page as isize) = 0; *instruction_pointer = *previous_ip; - //*page_fault = 0 != 1; + //*page_fault = true; call_interrupt_vector( CPU_EXCEPTION_PF, - 0 != 0, - 0 != 1, + false, + true, (user as i32) << 2 | (write as i32) << 1 | present as i32, ); //profiler::stat_increment(S_TRIGGER_CPU_EXCEPTION); @@ -600,7 +600,7 @@ pub unsafe fn translate_address_write(address: i32) -> OrPageFault { return Ok((entry & !0xFFF ^ address) as u32); } else { - return Ok((do_page_translation(address, 0 != 1, user)? | address & 0xFFF) as u32); + return Ok((do_page_translation(address, true, user)? | address & 0xFFF) as u32); }; } @@ -654,14 +654,14 @@ pub unsafe fn writable_or_pagefault(addr: i32, size: i32) -> OrPageFault<()> { let expect: i32 = TLB_VALID; let page: i32 = (addr as u32 >> 12) as i32; if *tlb_data.offset(page as isize) & mask != expect { - do_page_translation(addr, 0 != 1, user)?; + do_page_translation(addr, true, user)?; } let next_page: i32 = ((addr + size - 1) as u32 >> 12) as i32; if page != next_page { dbg_assert!(next_page == page + 1); // XXX: possibly out of bounds if *tlb_data.offset(next_page as isize) & mask != expect { - do_page_translation(next_page << 12, 0 != 1, user)?; + do_page_translation(next_page << 12, true, user)?; } } return Ok(()); @@ -994,7 +994,7 @@ pub unsafe fn raise_exception_with_code(interrupt_nr: i32, error_code: i32) { error_code ); dbg_trace(); - dbg_assert!(0 != 0); + dbg_assert!(false); } if cpu_exception_hook(interrupt_nr) { assert!(false); @@ -1002,7 +1002,7 @@ pub unsafe fn raise_exception_with_code(interrupt_nr: i32, error_code: i32) { } } profiler::stat_increment(S_TRIGGER_CPU_EXCEPTION); - call_interrupt_vector(interrupt_nr, 0 != 0, 0 != 1, error_code); + call_interrupt_vector(interrupt_nr, false, true, error_code); assert!(false); } @@ -1070,7 +1070,7 @@ pub unsafe fn cycle_internal() { else { if DEBUG { dbg_assert!(!must_not_fault); - must_not_fault = 0 != 1 + must_not_fault = true } ::c_api::jit_increase_hotness_and_maybe_compile( phys_addr, @@ -1079,7 +1079,7 @@ pub unsafe fn cycle_internal() { ); if DEBUG { dbg_assert!(must_not_fault); - must_not_fault = 0 != 0 + must_not_fault = false } let initial_tsc: i32 = *timestamp_counter as i32; jit_run_interpreted(phys_addr as i32); @@ -1193,7 +1193,7 @@ pub unsafe fn do_many_cycles_native() { // if must_not_fault { // dbg_log!("Unexpected fault: 0x{:x}", interrupt_nr); // dbg_trace(); -// dbg_assert!(0 != 0); +// dbg_assert!(false); // } // if cpu_exception_hook(interrupt_nr) { // throw_cpu_exception(); @@ -1201,7 +1201,7 @@ pub unsafe fn do_many_cycles_native() { // } // } // profiler::stat_increment(S_TRIGGER_CPU_EXCEPTION); -// call_interrupt_vector(interrupt_nr, 0 != 0, 0 != 0, 0); +// call_interrupt_vector(interrupt_nr, false, false, 0); // throw_cpu_exception(); //} @@ -1212,7 +1212,7 @@ pub unsafe fn trigger_de() { } } *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_DE, 0 != 0, 0 != 0, 0); + call_interrupt_vector(CPU_EXCEPTION_DE, false, false, 0); } #[no_mangle] @@ -1225,7 +1225,7 @@ pub unsafe fn trigger_ud() { } } *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_UD, 0 != 0, 0 != 0, 0); + call_interrupt_vector(CPU_EXCEPTION_UD, false, false, 0); } pub unsafe fn trigger_nm() { @@ -1235,7 +1235,7 @@ pub unsafe fn trigger_nm() { } } *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_NM, 0 != 0, 0 != 0, 0); + call_interrupt_vector(CPU_EXCEPTION_NM, false, false, 0); } #[no_mangle] @@ -1246,7 +1246,7 @@ pub unsafe fn trigger_gp_non_raising(code: i32) { } } *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_GP, 0 != 0, 0 != 1, code); + call_interrupt_vector(CPU_EXCEPTION_GP, false, true, code); } pub unsafe fn virt_boundary_read16(low: u32, high: u32) -> i32 { @@ -1365,7 +1365,7 @@ pub unsafe fn safe_read32s(address: i32) -> OrPageFault { profiler::stat_increment(S_SAFE_READ_SLOW_IN_MAPPED_RANGE); } else { - dbg_assert!(0 != 0); + dbg_assert!(false); } } return safe_read32s_slow(address); @@ -1565,7 +1565,7 @@ pub unsafe fn safe_write32(address: i32, value: i32) -> OrPageFault<()> { profiler::stat_increment(S_SAFE_WRITE_SLOW_HAS_CODE); } else { - dbg_assert!(0 != 0); + dbg_assert!(false); } } safe_write32_slow(address, value)?; @@ -1730,10 +1730,10 @@ pub fn transition_fpu_to_mmx() { pub unsafe fn task_switch_test() -> bool { if 0 != *cr & (CR0_EM | CR0_TS) { trigger_nm(); - return 0 != 0; + return false; } else { - return 0 != 1; + return true; }; } @@ -1775,14 +1775,14 @@ pub unsafe fn task_switch_test_mmx() -> bool { } if 0 != *cr & CR0_EM { trigger_ud(); - return 0 != 0; + return false; } else if 0 != *cr & CR0_TS { trigger_nm(); - return 0 != 0; + return false; } else { - return 0 != 1; + return true; }; } @@ -1875,7 +1875,7 @@ pub unsafe fn set_tsc(low: u32, high: u32) { pub unsafe fn read_tsc() -> u64 { let n: f64 = microtick() * TSC_RATE; let value: u64 = (n as u64).wrapping_sub(tsc_offset); - if 0 != 1 + 1 { + if true { return value; } else { @@ -1901,7 +1901,7 @@ pub unsafe fn read_tsc() -> u64 { (value >> 32) as u32 as i32, value as u32 as i32 ); - dbg_assert!(0 != 0); + dbg_assert!(false); // Keep current value until time catches up } } @@ -2006,7 +2006,7 @@ pub unsafe fn translate_address_system_read(address: i32) -> OrPageFault { return Ok((entry & !0xFFF ^ address) as u32); } else { - return Ok((do_page_translation(address, 0 != 0, 0 != 0)? | address & 0xFFF) as u32); + return Ok((do_page_translation(address, false, false)? | address & 0xFFF) as u32); }; } @@ -2017,7 +2017,7 @@ pub unsafe fn translate_address_system_write(address: i32) -> OrPageFault { return Ok((entry & !0xFFF ^ address) as u32); } else { - return Ok((do_page_translation(address, 0 != 1, 0 != 0)? | address & 0xFFF) as u32); + return Ok((do_page_translation(address, true, false)? | address & 0xFFF) as u32); }; } @@ -2029,7 +2029,7 @@ pub unsafe fn trigger_np(code: i32) { } } *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_NP, 0 != 0, 0 != 1, code); + call_interrupt_vector(CPU_EXCEPTION_NP, false, true, code); } #[no_mangle] @@ -2040,7 +2040,7 @@ pub unsafe fn trigger_ss(code: i32) { } } *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_SS, 0 != 0, 0 != 1, code); + call_interrupt_vector(CPU_EXCEPTION_SS, false, true, code); } #[no_mangle] diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 45203bd0..cc380af0 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -406,7 +406,7 @@ pub unsafe fn fpu_fldenv(addr: i32) { #[no_mangle] pub unsafe fn fpu_unimpl() { if DEBUG { - dbg_assert!(0 != 0); + dbg_assert!(false); } else { trigger_ud(); diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index 56c91745..47fe4554 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -890,12 +890,12 @@ pub unsafe fn instr32_61() { popa32(); } pub unsafe fn instr_62_reg(r2: i32, r: i32) { // bound dbg_log!("Unimplemented BOUND instruction"); - dbg_assert!(0 != 0); + dbg_assert!(false); } #[no_mangle] pub unsafe fn instr_62_mem(addr: i32, r: i32) { dbg_log!("Unimplemented BOUND instruction"); - dbg_assert!(0 != 0); + dbg_assert!(false); } #[no_mangle] pub unsafe fn instr_63_mem(addr: i32, r: i32) { @@ -1509,10 +1509,10 @@ pub unsafe fn instr_8C_check_sreg(seg: i32) -> bool { if seg >= 6 { dbg_log!("mov sreg #ud"); trigger_ud(); - return 0 != 0; + return false; } else { - return 0 != 1; + return true; }; } #[no_mangle] @@ -1699,7 +1699,7 @@ pub unsafe fn instr16_9A(new_ip: i32, new_cs: i32) { pub unsafe fn instr32_9A(new_ip: i32, new_cs: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { if 0 != new_ip as u32 & 0xFFFF0000 { - dbg_assert!(0 != 0); + dbg_assert!(false); } } far_jump(new_ip, new_cs, true); @@ -2267,12 +2267,12 @@ pub unsafe fn instr_CC() { // INT3 // TODO: inhibit iopl checks dbg_log!("INT3"); - call_interrupt_vector(3, 0 != 1, 0 != 0, 0); + call_interrupt_vector(3, true, false, 0); } #[no_mangle] pub unsafe fn instr_CD(imm8: i32) { // INT - call_interrupt_vector(imm8, 0 != 1, 0 != 0, 0); + call_interrupt_vector(imm8, true, false, 0); } #[no_mangle] pub unsafe fn instr_CE() { @@ -2280,7 +2280,7 @@ pub unsafe fn instr_CE() { dbg_log!("INTO"); if getof() { // TODO: inhibit iopl checks - call_interrupt_vector(CPU_EXCEPTION_OF, 0 != 1, 0 != 0, 0); + call_interrupt_vector(CPU_EXCEPTION_OF, true, false, 0); }; } #[no_mangle] @@ -2911,7 +2911,7 @@ pub unsafe fn instr32_EF() { #[no_mangle] pub unsafe fn instr_F0() { // lock - if 0 != 0 * 0 { + if false { dbg_log!("lock"); } // TODO @@ -2923,7 +2923,7 @@ pub unsafe fn instr_F0() { pub unsafe fn instr_F1() { // INT1 // https://code.google.com/p/corkami/wiki/x86oddities#IceBP - dbg_assert!(0 != 0); + dbg_assert!(false); } #[no_mangle] pub unsafe fn instr_F2() { @@ -3206,7 +3206,7 @@ pub unsafe fn instr_FA() { } { *flags &= !FLAG_INTERRUPT; } - else if 0 != 0 * 0 && getiopl() < 3 && 0 != if 0 != *flags & FLAG_VM { + else if false && getiopl() < 3 && 0 != if 0 != *flags & FLAG_VM { *cr.offset(4) & CR4_VME } else { @@ -3234,8 +3234,7 @@ pub unsafe fn instr_FB() { handle_irqs(); } } - else if 0 != 0 * 0 && getiopl() < 3 && *flags & FLAG_VIP == 0 && 0 != if 0 != *flags & FLAG_VM - { + else if false && getiopl() < 3 && *flags & FLAG_VIP == 0 && 0 != if 0 != *flags & FLAG_VM { *cr.offset(4) & CR4_VME } else { @@ -3412,7 +3411,7 @@ pub unsafe fn instr32_FF_3_mem(addr: i32) { let new_cs: i32 = return_on_pagefault!(safe_read16(addr + 4)); if !*protected_mode || 0 != vm86_mode() as i32 { if 0 != new_ip as u32 & 0xFFFF0000 { - dbg_assert!(0 != 0); + dbg_assert!(false); } } far_jump(new_ip, new_cs, true); @@ -3446,7 +3445,7 @@ pub unsafe fn instr32_FF_5_mem(addr: i32) { let new_cs: i32 = return_on_pagefault!(safe_read16(addr + 4)); if !*protected_mode || 0 != vm86_mode() as i32 { if 0 != new_ip as u32 & 0xFFFF0000 { - dbg_assert!(0 != 0); + dbg_assert!(false); } } far_jump(new_ip, new_cs, false); @@ -3829,7 +3828,7 @@ pub unsafe fn instr_D9_6_reg(r: i32) { *fpu_status_word &= !FPU_C1 }, _ => { - dbg_assert!(0 != 0); + dbg_assert!(false); }, }; } @@ -3865,7 +3864,7 @@ pub unsafe fn instr_D9_7_reg(r: i32) { 6 => fpu_write_st(*fpu_stack_ptr as i32, st0.sin()), 7 => fpu_write_st(*fpu_stack_ptr as i32, st0.cos()), _ => { - dbg_assert!(0 != 0); + dbg_assert!(false); }, }; } diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index cb4cf033..e1da1219 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -385,7 +385,7 @@ pub unsafe fn instr_0F06() { trigger_gp_non_raising(0); } else { - if 0 != 0 * 0 { + if false { dbg_log!("clts"); } *cr &= !CR0_TS; @@ -779,7 +779,7 @@ pub unsafe fn instr_0F21(r: i32, mut dreg_index: i32) { } } write_reg32(r, *dreg.offset(dreg_index as isize)); - if 0 != 0 * 0 { + if false { dbg_log!( "read dr{}: {:x}", dreg_index, @@ -800,7 +800,7 @@ pub unsafe fn instr_0F22(r: i32, creg: i32) { // mov cr, addr match creg { 0 => { - if 0 != 0 * 0 { + if false { dbg_log!("cr0 <- {:x}", data); } set_cr0(data); @@ -810,7 +810,7 @@ pub unsafe fn instr_0F22(r: i32, creg: i32) { *cr.offset(2) = data }, 3 => { - if 0 != 0 * 0 { + if false { dbg_log!("cr3 <- {:x}", data); } data &= !0b111111100111; @@ -833,7 +833,7 @@ pub unsafe fn instr_0F22(r: i32, creg: i32) { } *cr.offset(4) = data; if 0 != *cr.offset(4) & CR4_PAE { - dbg_assert!(0 != 0); + dbg_assert!(false); } } }, @@ -864,7 +864,7 @@ pub unsafe fn instr_0F23(r: i32, mut dreg_index: i32) { } } *dreg.offset(dreg_index as isize) = read_reg32(r); - if 0 != 0 * 0 { + if false { dbg_log!( "write dr{}: {:x}", dreg_index, @@ -1173,7 +1173,7 @@ pub unsafe fn instr_0F30() { } else { dbg_log!("Unknown msr: {:x}", index); - dbg_assert!(0 != 0); + dbg_assert!(false); } } return; @@ -1186,7 +1186,7 @@ pub unsafe fn instr_0F31() { let tsc: u64 = read_tsc(); *reg32s.offset(EAX as isize) = tsc as i32; *reg32s.offset(EDX as isize) = (tsc >> 32) as i32; - if 0 != 0 * 0 { + if false { dbg_log!( "rdtsc edx:eax={:x}:{:x}", *reg32s.offset(EDX as isize), @@ -1252,7 +1252,7 @@ pub unsafe fn instr_0F32() { } else if !(index == MSR_PKG_C2_RESIDENCY) { dbg_log!("Unknown msr: {:x}", index); - dbg_assert!(0 != 0); + dbg_assert!(false); } } } @@ -1281,17 +1281,17 @@ pub unsafe fn instr_0F34() { *instruction_pointer = *sysenter_eip; *reg32s.offset(ESP as isize) = *sysenter_esp; *sreg.offset(CS as isize) = seg as u16; - *segment_is_null.offset(CS as isize) = 0 != 0; + *segment_is_null.offset(CS as isize) = false; *segment_limits.offset(CS as isize) = -1i32 as u32; *segment_offsets.offset(CS as isize) = 0; update_cs_size(true); *cpl = 0; cpl_changed(); *sreg.offset(SS as isize) = (seg + 8) as u16; - *segment_is_null.offset(SS as isize) = 0 != 0; + *segment_is_null.offset(SS as isize) = false; *segment_limits.offset(SS as isize) = -1i32 as u32; *segment_offsets.offset(SS as isize) = 0; - *stack_size_32 = 0 != 1; + *stack_size_32 = true; return; }; } @@ -1307,17 +1307,17 @@ pub unsafe fn instr_0F35() { *instruction_pointer = *reg32s.offset(EDX as isize); *reg32s.offset(ESP as isize) = *reg32s.offset(ECX as isize); *sreg.offset(CS as isize) = (seg + 16 | 3) as u16; - *segment_is_null.offset(CS as isize) = 0 != 0; + *segment_is_null.offset(CS as isize) = false; *segment_limits.offset(CS as isize) = -1i32 as u32; *segment_offsets.offset(CS as isize) = 0; update_cs_size(true); *cpl = 3; cpl_changed(); *sreg.offset(SS as isize) = (seg + 24 | 3) as u16; - *segment_is_null.offset(SS as isize) = 0 != 0; + *segment_is_null.offset(SS as isize) = false; *segment_limits.offset(SS as isize) = -1i32 as u32; *segment_offsets.offset(SS as isize) = 0; - *stack_size_32 = 0 != 1; + *stack_size_32 = true; return; }; } diff --git a/src/rust/cpu2/modrm.rs b/src/rust/cpu2/modrm.rs index d453dd74..06056d85 100644 --- a/src/rust/cpu2/modrm.rs +++ b/src/rust/cpu2/modrm.rs @@ -83,7 +83,7 @@ pub unsafe fn resolve_modrm16(modrm_byte: i32) -> OrPageFault { get_seg_prefix_ds(*reg16.offset(BX as isize) as i32 + read_imm16()? & 0xFFFF) }, _ => { - dbg_assert!(0 != 0); + dbg_assert!(false); 0 }, }) @@ -94,10 +94,10 @@ pub unsafe fn resolve_modrm32_(modrm_byte: i32) -> OrPageFault { dbg_assert!(modrm_byte < 192); Ok(if r as i32 == 4 { if modrm_byte < 64 { - resolve_sib(0 != 0)? + resolve_sib(false)? } else { - resolve_sib(0 != 1)? + if modrm_byte < 128 { + resolve_sib(true)? + if modrm_byte < 128 { read_imm8s()? } else { @@ -200,9 +200,9 @@ pub unsafe fn resolve_modrm32(modrm_byte: i32) -> OrPageFault { 131 | 139 | 147 | 155 | 163 | 171 | 179 | 187 => { get_seg_prefix_ds(*reg32s.offset(EBX as isize) + read_imm32s()?) }, - 4 | 12 | 20 | 28 | 36 | 44 | 52 | 60 => resolve_sib(0 != 0)?, - 68 | 76 | 84 | 92 | 100 | 108 | 116 | 124 => resolve_sib(0 != 1)? + read_imm8s()?, - 132 | 140 | 148 | 156 | 164 | 172 | 180 | 188 => resolve_sib(0 != 1)? + read_imm32s()?, + 4 | 12 | 20 | 28 | 36 | 44 | 52 | 60 => resolve_sib(false)?, + 68 | 76 | 84 | 92 | 100 | 108 | 116 | 124 => resolve_sib(true)? + read_imm8s()?, + 132 | 140 | 148 | 156 | 164 | 172 | 180 | 188 => resolve_sib(true)? + read_imm32s()?, 5 | 13 | 21 | 29 | 37 | 45 | 53 | 61 => get_seg_prefix_ds(read_imm32s()?), 69 | 77 | 85 | 93 | 101 | 109 | 117 | 125 => { get_seg_prefix_ss(*reg32s.offset(EBP as isize) + read_imm8s()?) @@ -225,7 +225,7 @@ pub unsafe fn resolve_modrm32(modrm_byte: i32) -> OrPageFault { get_seg_prefix_ds(*reg32s.offset(EDI as isize) + read_imm32s()?) }, _ => { - dbg_assert!(0 != 0); + dbg_assert!(false); 0 }, }) diff --git a/src/rust/cpu2/sse_instr.rs b/src/rust/cpu2/sse_instr.rs index f3904b51..6cb46e12 100644 --- a/src/rust/cpu2/sse_instr.rs +++ b/src/rust/cpu2/sse_instr.rs @@ -356,8 +356,8 @@ pub unsafe fn sse_comparison(op: i32, x: f64, y: f64) -> bool { 6 => return x > y || 0 != x.is_nan() as i32 || 0 != y.is_nan() as i32, 7 => return !x.is_nan() && !y.is_nan(), _ => { - dbg_assert!(0 != 0); - return 0 != 0; + dbg_assert!(false); + return false; }, }; } From 32699a3a7e9f1bed9323acb8c26a479bbf5892f8 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 12 Sep 2018 16:06:29 -0500 Subject: [PATCH 1351/2137] Clear unused wasm modules earlier --- src/browser/starter.js | 1 + src/cpu.js | 2 +- src/rust/cpu.rs | 5 +++++ src/rust/jit.rs | 10 ++++------ 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index e767eea0..797df426 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -252,6 +252,7 @@ function V86Starter(options) console.error(str); }, "codegen_finalize": (wasm_table_index, start, end, first_opcode, state_flags) => cpu.codegen_finalize(wasm_table_index, start, end, first_opcode, state_flags), + "jit_clear_func": (wasm_table_index) => cpu.jit_clear_func(wasm_table_index), "__indirect_function_table": wasm_table, "floor": Math.floor, "ceil": Math.ceil, diff --git a/src/cpu.js b/src/cpu.js index 16ba740c..c3b1be3d 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -367,7 +367,7 @@ CPU.prototype.jit_force_generate = function(addr) CPU.prototype.jit_clear_func = function(index) { dbg_assert(index >= 0 && index < WASM_TABLE_SIZE); - this.wm.imports.env[WASM_EXPORT_TABLE_NAME].set(index + WASM_TABLE_OFFSET, null); + this.wm.imports["env"][WASM_EXPORT_TABLE_NAME].set(index + WASM_TABLE_OFFSET, null); }; CPU.prototype.get_state = function() diff --git a/src/rust/cpu.rs b/src/rust/cpu.rs index 8de2466a..cf76419c 100644 --- a/src/rust/cpu.rs +++ b/src/rust/cpu.rs @@ -18,6 +18,7 @@ mod unsafe_cpu { first_opcode: u32, state_flags: u32, ); + pub fn jit_clear_func(wasm_table_index: u16); } } @@ -55,3 +56,7 @@ pub fn codegen_finalize( ) } } + +pub fn jit_clear_func(wasm_table_index: u16) { + unsafe { unsafe_cpu::jit_clear_func(wasm_table_index) } +} diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 63907439..477bdf1f 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -1173,13 +1173,11 @@ fn free_wasm_table_index(ctx: &mut JitState, wasm_table_index: u16) { if CHECK_JIT_CACHE_ARRAY_INVARIANTS { dbg_assert!(!ctx.wasm_table_index_free_list.contains(&wasm_table_index)); } - ctx.wasm_table_index_free_list.push(wasm_table_index) + ctx.wasm_table_index_free_list.push(wasm_table_index); - // It is not strictly necessary to clear the function, but it will fail - // more predictably if we accidentally use the function - // XXX: This fails in Chromium: - // RangeError: WebAssembly.Table.set(): Modifying existing entry in table not supported. - //jit_clear_func(wasm_table_index); + // It is not strictly necessary to clear the function, but it will fail more predictably if we + // accidentally use the function and may garbage collect unused modules earlier + cpu::jit_clear_func(wasm_table_index); } /// Remove all entries with the given wasm_table_index in page From 7d0521475a7945f252e96a2dd683341ff433ff07 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 12 Sep 2018 16:07:55 -0500 Subject: [PATCH 1352/2137] Store fxsave_store_fpu_mask in state --- src/cpu.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/cpu.js b/src/cpu.js index c3b1be3d..12067bb4 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -218,6 +218,8 @@ function CPU(bus, wm, v86oxide, coverage_logger) this.reg_mmx8s = v86util.view(Int8Array, this.reg_mmxs.buffer, 1064, 64); this.reg_mmx8 = v86util.view(Uint8Array, this.reg_mmxs.buffer, 1064, 64); + this.fxsave_store_fpu_mask = v86util.view(Uint8Array, memory, 1132, 1); + this.reg_xmm32s = v86util.view(Int32Array, memory, 828, 8 * 4); this.mxcsr = v86util.view(Int32Array, memory, 824, 1); @@ -453,6 +455,8 @@ CPU.prototype.get_state = function() state[74] = this.fpu_dp_selector[0]; state[75] = this.fpu_opcode[0]; + state[76] = this.fxsave_store_fpu_mask; + return state; }; @@ -543,6 +547,8 @@ CPU.prototype.set_state = function(state) this.fpu_dp_selector[0] = state[74]; this.fpu_opcode[0] = state[75]; + this.fxsave_store_fpu_mask = state[76]; + this.full_clear_tlb(); this.update_operand_size(); From 014e745810d95625cd56470ade8ecd312998ea97 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 12 Sep 2018 17:53:52 -0500 Subject: [PATCH 1353/2137] Clean up dead code from old exceptions --- src/browser/print_stats.js | 1 - src/rust/cpu2/cpu.rs | 46 +------------------------------------- src/rust/profiler.rs | 2 -- 3 files changed, 1 insertion(+), 48 deletions(-) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index 0bc8f0c4..d28b4e85 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -29,7 +29,6 @@ const print_stats = { "RUN_INTERPRETED_STEPS", "RUN_FROM_CACHE", "RUN_FROM_CACHE_STEPS", - "TRIGGER_CPU_EXCEPTION", "SAFE_READ_FAST", "SAFE_READ_SLOW_PAGE_CROSSED", "SAFE_READ_SLOW_NOT_VALID", diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 3c1b8dad..1435537a 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -587,7 +587,6 @@ pub unsafe fn trigger_pagefault(write: bool, user: bool, present: bool) { true, (user as i32) << 2 | (write as i32) << 1 | present as i32, ); - //profiler::stat_increment(S_TRIGGER_CPU_EXCEPTION); } pub unsafe fn translate_address_write(address: i32) -> OrPageFault { @@ -867,7 +866,7 @@ pub unsafe fn get_seg(segment: i32) -> i32 { dbg_assert!(segment != CS && segment != SS); dbg_log!("#gp: Access null segment"); assert!(false); - trigger_gp(0); + //trigger_gp(0); // TODO } } return *segment_offsets.offset(segment as isize); @@ -980,32 +979,6 @@ pub unsafe fn popa32() { *reg32s.offset(EAX as isize) = pop32s().unwrap(); } -pub unsafe fn trigger_gp(code: i32) { - *instruction_pointer = *previous_ip; - raise_exception_with_code(CPU_EXCEPTION_GP, code); -} - -pub unsafe fn raise_exception_with_code(interrupt_nr: i32, error_code: i32) { - if DEBUG { - if must_not_fault { - dbg_log!( - "Unexpected fault: 0x{:x} with code 0x{:x}", - interrupt_nr, - error_code - ); - dbg_trace(); - dbg_assert!(false); - } - if cpu_exception_hook(interrupt_nr) { - assert!(false); - return; - } - } - profiler::stat_increment(S_TRIGGER_CPU_EXCEPTION); - call_interrupt_vector(interrupt_nr, false, true, error_code); - assert!(false); -} - pub unsafe fn get_seg_cs() -> i32 { return *segment_offsets.offset(CS as isize); } pub unsafe fn get_seg_ss() -> i32 { return *segment_offsets.offset(SS as isize); } @@ -1187,23 +1160,6 @@ pub unsafe fn do_many_cycles_native() { cycle_internal(); } } -//#[no_mangle] -//pub unsafe fn raise_exception(interrupt_nr: i32) { -// if DEBUG { -// if must_not_fault { -// dbg_log!("Unexpected fault: 0x{:x}", interrupt_nr); -// dbg_trace(); -// dbg_assert!(false); -// } -// if cpu_exception_hook(interrupt_nr) { -// throw_cpu_exception(); -// return; -// } -// } -// profiler::stat_increment(S_TRIGGER_CPU_EXCEPTION); -// call_interrupt_vector(interrupt_nr, false, false, 0); -// throw_cpu_exception(); -//} pub unsafe fn trigger_de() { if DEBUG { diff --git a/src/rust/profiler.rs b/src/rust/profiler.rs index 9076b602..9c159b17 100644 --- a/src/rust/profiler.rs +++ b/src/rust/profiler.rs @@ -18,8 +18,6 @@ pub enum stat { S_RUN_FROM_CACHE, S_RUN_FROM_CACHE_STEPS, - S_TRIGGER_CPU_EXCEPTION, - S_SAFE_READ_FAST, S_SAFE_READ_SLOW_PAGE_CROSSED, S_SAFE_READ_SLOW_NOT_VALID, From b98ff1612a2acdac1b42362d8a2c590a0c441a01 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 12 Sep 2018 17:56:32 -0500 Subject: [PATCH 1354/2137] Make profiler stat counters u64 --- src/rust/cpu2/cpu.rs | 8 ++++---- src/rust/jit.rs | 2 +- src/rust/profiler.rs | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 1435537a..420b8af3 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1028,7 +1028,7 @@ pub unsafe fn cycle_internal() { if 0 != entry { profiler::stat_increment(S_RUN_FROM_CACHE); - let initial_tsc = *timestamp_counter as i32; + let initial_tsc = *timestamp_counter; let wasm_table_index = (entry & 0xFFFF) as u16; let initial_state = (entry >> 16) as u16; call_indirect1( @@ -1037,7 +1037,7 @@ pub unsafe fn cycle_internal() { ); profiler::stat_increment_by( S_RUN_FROM_CACHE_STEPS, - (*timestamp_counter).wrapping_sub(initial_tsc as u32), + (*timestamp_counter - initial_tsc) as u64, ); } else { @@ -1054,11 +1054,11 @@ pub unsafe fn cycle_internal() { dbg_assert!(must_not_fault); must_not_fault = false } - let initial_tsc: i32 = *timestamp_counter as i32; + let initial_tsc = *timestamp_counter; jit_run_interpreted(phys_addr as i32); profiler::stat_increment_by( S_RUN_INTERPRETED_STEPS, - (*timestamp_counter).wrapping_sub(initial_tsc as u32), + (*timestamp_counter - initial_tsc) as u64, ); }; } diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 477bdf1f..e9b59475 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -1280,7 +1280,7 @@ pub fn jit_dirty_page(ctx: &mut JitState, page: Page) { profiler::stat_increment_by( stat::S_INVALIDATE_MODULE, - index_to_pending_free.len() as u32 + index_to_free.len() as u32, + index_to_pending_free.len() as u64 + index_to_free.len() as u64, ); for index in index_to_free.iter().cloned() { diff --git a/src/rust/profiler.rs b/src/rust/profiler.rs index 9c159b17..75f8512c 100644 --- a/src/rust/profiler.rs +++ b/src/rust/profiler.rs @@ -50,11 +50,11 @@ pub enum stat { } #[no_mangle] -pub static mut stat_array: [u32; 100] = [0; 100]; +pub static mut stat_array: [u64; 100] = [0; 100]; pub fn stat_increment(stat: stat) { stat_increment_by(stat, 1); } -pub fn stat_increment_by(stat: stat, by: u32) { +pub fn stat_increment_by(stat: stat, by: u64) { if cfg!(feature = "profiler") { unsafe { stat_array[stat as usize] += by } } @@ -70,12 +70,12 @@ pub fn profiler_init() { } #[no_mangle] -pub fn profiler_stat_get(stat: stat) -> u32 { +pub fn profiler_stat_get(stat: stat) -> f64 { if cfg!(feature = "profiler") { - unsafe { stat_array[stat as usize] } + unsafe { stat_array[stat as usize] as f64 } } else { - 0 + 0.0 } } From 2635ed71b4e52d7490eb03ef85f28782c10350d5 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 13 Sep 2018 11:25:13 -0500 Subject: [PATCH 1355/2137] jit memory access for 8-bit read-modify-write operations --- gen/x86_table.js | 14 ++-- src/rust/codegen.rs | 31 +++++---- src/rust/cpu2/instruction_helpers.rs | 3 +- src/rust/jit_instructions.rs | 99 ++++++++++++++++++++++++++++ 4 files changed, 128 insertions(+), 19 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 8fb45225..b84ac165 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -16,37 +16,37 @@ const sf = 1 << 7; // os: the instruction behaves differently depending on the operand size const encodings = [ - { opcode: 0x00, e: 1, }, + { opcode: 0x00, custom: 1, e: 1, }, { opcode: 0x01, custom: 1, os: 1, e: 1, }, { opcode: 0x02, custom: 1, e: 1, }, { opcode: 0x03, custom: 1, os: 1, e: 1, }, - { opcode: 0x08, e: 1, }, + { opcode: 0x08, custom: 1, e: 1, }, { opcode: 0x09, custom: 1, os: 1, e: 1, }, { opcode: 0x0A, custom: 1, e: 1, }, { opcode: 0x0B, custom: 1, os: 1, e: 1, }, - { opcode: 0x10, e: 1, }, + { opcode: 0x10, custom: 1, e: 1, }, { opcode: 0x11, custom: 1, os: 1, e: 1, }, { opcode: 0x12, custom: 1, e: 1, }, { opcode: 0x13, custom: 1, os: 1, e: 1, }, - { opcode: 0x18, e: 1, }, + { opcode: 0x18, custom: 1, e: 1, }, { opcode: 0x19, custom: 1, os: 1, e: 1, }, { opcode: 0x1A, custom: 1, e: 1, }, { opcode: 0x1B, custom: 1, os: 1, e: 1, }, - { opcode: 0x20, e: 1, }, + { opcode: 0x20, custom: 1, e: 1, }, { opcode: 0x21, custom: 1, os: 1, e: 1, }, { opcode: 0x22, custom: 1, e: 1, }, { opcode: 0x23, custom: 1, os: 1, e: 1, }, - { opcode: 0x28, e: 1, }, + { opcode: 0x28, custom: 1, e: 1, }, { opcode: 0x29, custom: 1, os: 1, e: 1, }, { opcode: 0x2A, custom: 1, e: 1, }, { opcode: 0x2B, custom: 1, os: 1, e: 1, }, - { opcode: 0x30, e: 1, }, + { opcode: 0x30, custom: 1, e: 1, }, { opcode: 0x31, custom: 1, os: 1, e: 1, }, { opcode: 0x32, custom: 1, e: 1, }, { opcode: 0x33, custom: 1, os: 1, e: 1, }, diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 6a6f4da2..784d3468 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -849,15 +849,16 @@ pub fn gen_safe_read_write( ctx.builder.instruction_body.const_i32(TLB_VALID as i32); ctx.builder.instruction_body.eq_i32(); - ctx.builder.instruction_body.get_local(&address_local); - ctx.builder.instruction_body.const_i32(0xFFF); - ctx.builder.instruction_body.and_i32(); - ctx.builder - .instruction_body - .const_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 }); - ctx.builder.instruction_body.le_i32(); - - ctx.builder.instruction_body.and_i32(); + if bits != BitSize::BYTE { + ctx.builder.instruction_body.get_local(&address_local); + ctx.builder.instruction_body.const_i32(0xFFF); + ctx.builder.instruction_body.and_i32(); + ctx.builder + .instruction_body + .const_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 }); + ctx.builder.instruction_body.le_i32(); + ctx.builder.instruction_body.and_i32(); + } // Pseudo: // if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]); @@ -878,7 +879,11 @@ pub fn gen_safe_read_write( ctx.builder.instruction_body.get_local(&phys_addr_local); match bits { - BitSize::BYTE => {}, + BitSize::BYTE => { + ctx.builder + .instruction_body + .load_u8_from_stack(unsafe { mem8 } as u32); + }, BitSize::WORD => { ctx.builder .instruction_body @@ -894,7 +899,11 @@ pub fn gen_safe_read_write( f(ctx); match bits { - BitSize::BYTE => {}, + BitSize::BYTE => { + ctx.builder + .instruction_body + .store_u8(unsafe { mem8 } as u32); + }, BitSize::WORD => { ctx.builder .instruction_body diff --git a/src/rust/cpu2/instruction_helpers.rs b/src/rust/cpu2/instruction_helpers.rs index f63d9d38..298e7539 100644 --- a/src/rust/cpu2/instruction_helpers.rs +++ b/src/rust/cpu2/instruction_helpers.rs @@ -3,8 +3,9 @@ macro_rules! SAFE_READ_WRITE8 { use cpu2::cpu::translate_address_write; use cpu2::memory::{read8, write8}; match translate_address_write($addr) { - Err(()) => {}, + Err(()) => *page_fault = true, Ok(phys_addr) => { + *page_fault = false; let $value = read8(phys_addr); write8(phys_addr, $instruction); }, diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index d2eab995..5bc09bf0 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -317,6 +317,56 @@ macro_rules! make_imm_read( ($ctx:expr, imm32) => { $ctx.cpu.read_imm32() }; ); +macro_rules! define_instruction_read_write_mem8( + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, reg) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_safe_read_write(ctx, BitSize::BYTE, &address_local, &|ref mut ctx| { + codegen::gen_get_reg8(ctx.builder, r); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + }, &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_call_fn2(ctx.builder, $fallback_fn) + }); + ctx.builder.free_local(address_local); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { + ctx.builder.instruction_body.const_i32(global_pointers::get_reg8_offset(r1) as i32); + codegen::gen_get_reg8(ctx.builder, r1); + codegen::gen_get_reg8(ctx.builder, r2); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + ctx.builder.instruction_body.store_u8(0); + } + ); + + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, $imm:ident) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + let imm = make_imm_read!(ctx, $imm) as i32; + codegen::gen_safe_read_write(ctx, BitSize::BYTE, &address_local, &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + }, &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn2(ctx.builder, $fallback_fn) + }); + ctx.builder.free_local(address_local); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { + let imm = mask_imm!(imm, $imm); + ctx.builder.instruction_body.const_i32(global_pointers::get_reg8_offset(r1) as i32); + codegen::gen_get_reg8(ctx.builder, r1); + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + ctx.builder.instruction_body.store_u8(0); + } + ); +); + macro_rules! define_instruction_read_write_mem16( ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, reg) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { @@ -553,6 +603,13 @@ macro_rules! define_instruction_read_write_mem32( ); ); +define_instruction_read_write_mem8!( + "add8", + "instr_00_mem", + instr_00_mem_jit, + instr_00_reg_jit, + reg +); define_instruction_read_write_mem16!( "add16", "instr16_01_mem", @@ -572,6 +629,13 @@ define_instruction_write_reg8!("add8", instr_02_mem_jit, instr_02_reg_jit); define_instruction_write_reg16!("add16", instr16_03_mem_jit, instr16_03_reg_jit); define_instruction_write_reg32!("add32", instr32_03_mem_jit, instr32_03_reg_jit); +define_instruction_read_write_mem8!( + "or8", + "instr_08_mem", + instr_08_mem_jit, + instr_08_reg_jit, + reg +); define_instruction_read_write_mem16!( "or16", "instr16_09_mem", @@ -591,6 +655,13 @@ define_instruction_write_reg8!("or8", instr_0A_mem_jit, instr_0A_reg_jit); define_instruction_write_reg16!("or16", instr16_0B_mem_jit, instr16_0B_reg_jit); define_instruction_write_reg32!("or32", instr32_0B_mem_jit, instr32_0B_reg_jit); +define_instruction_read_write_mem8!( + "adc8", + "instr_10_mem", + instr_10_mem_jit, + instr_10_reg_jit, + reg +); define_instruction_read_write_mem16!( "adc16", "instr16_11_mem", @@ -610,6 +681,13 @@ define_instruction_write_reg8!("adc8", instr_12_mem_jit, instr_12_reg_jit); define_instruction_write_reg16!("adc16", instr16_13_mem_jit, instr16_13_reg_jit); define_instruction_write_reg32!("adc32", instr32_13_mem_jit, instr32_13_reg_jit); +define_instruction_read_write_mem8!( + "sbb8", + "instr_18_mem", + instr_18_mem_jit, + instr_18_reg_jit, + reg +); define_instruction_read_write_mem16!( "sbb16", "instr16_19_mem", @@ -629,6 +707,13 @@ define_instruction_write_reg8!("sbb8", instr_1A_mem_jit, instr_1A_reg_jit); define_instruction_write_reg16!("sbb16", instr16_1B_mem_jit, instr16_1B_reg_jit); define_instruction_write_reg32!("sbb32", instr32_1B_mem_jit, instr32_1B_reg_jit); +define_instruction_read_write_mem8!( + "and8", + "instr_20_mem", + instr_20_mem_jit, + instr_20_reg_jit, + reg +); define_instruction_read_write_mem16!( "and16", "instr16_21_mem", @@ -648,6 +733,13 @@ define_instruction_write_reg8!("and8", instr_22_mem_jit, instr_22_reg_jit); define_instruction_write_reg16!("and16", instr16_23_mem_jit, instr16_23_reg_jit); define_instruction_write_reg32!("and32", instr32_23_mem_jit, instr32_23_reg_jit); +define_instruction_read_write_mem8!( + "sub8", + "instr_28_mem", + instr_28_mem_jit, + instr_28_reg_jit, + reg +); define_instruction_read_write_mem16!( "sub16", "instr16_29_mem", @@ -667,6 +759,13 @@ define_instruction_write_reg8!("sub8", instr_2A_mem_jit, instr_2A_reg_jit); define_instruction_write_reg16!("sub16", instr16_2B_mem_jit, instr16_2B_reg_jit); define_instruction_write_reg32!("sub32", instr32_2B_mem_jit, instr32_2B_reg_jit); +define_instruction_read_write_mem8!( + "xor8", + "instr_30_mem", + instr_30_mem_jit, + instr_30_reg_jit, + reg +); define_instruction_read_write_mem16!( "xor16", "instr16_31_mem", From 6a2cd6419d49e6b035fddc83ae9a62f9bbc213e2 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 13 Sep 2018 11:36:39 -0500 Subject: [PATCH 1356/2137] jit memory access for 8-bit read-modify-write operations with immediate --- gen/x86_table.js | 2 +- src/rust/jit_instructions.rs | 70 +++++++++++++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index b84ac165..2b6132d7 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -846,7 +846,7 @@ for(let i = 0; i < 8; i++) { opcode: 0x70 | i, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, os: 1, imm8s: 1, custom: 1, skip: 1, }, { opcode: 0x78 | i, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, os: 1, imm8s: 1, custom: 1, skip: 1, }, - { opcode: 0x80, e: 1, fixed_g: i, imm8: 1, }, + { opcode: 0x80, e: 1, fixed_g: i, imm8: 1, custom: 1, }, { opcode: 0x81, os: 1, e: 1, fixed_g: i, imm1632: 1, custom: 1, }, { opcode: 0x82, e: 1, fixed_g: i, imm8: 1, }, { opcode: 0x83, os: 1, e: 1, fixed_g: i, imm8s: 1, custom: 1, }, diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 5bc09bf0..2efff3a5 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -173,7 +173,22 @@ macro_rules! define_instruction_read8( codegen::gen_get_reg8(ctx.builder, r2); codegen::gen_call_fn2(ctx.builder, $fn) } - ) + ); + + ($fn:expr, $name_mem:ident, $name_reg:ident, $imm:ident) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read8(ctx); + ctx.builder.instruction_body.const_i32(make_imm_read!(ctx, $imm) as i32); + codegen::gen_call_fn2(ctx.builder, $fn) + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { + codegen::gen_get_reg8(ctx.builder, r1); + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn2(ctx.builder, $fn) + } + ); ); macro_rules! define_instruction_read16( @@ -305,6 +320,7 @@ macro_rules! define_instruction_write_reg32( macro_rules! mask_imm( ($imm:expr, imm8_5bits) => { $imm & 31 }; + ($imm:expr, imm8) => { $imm }; ($imm:expr, imm8s) => { $imm }; ($imm:expr, imm16) => { $imm }; ($imm:expr, imm32) => { $imm }; @@ -312,6 +328,7 @@ macro_rules! mask_imm( macro_rules! make_imm_read( ($ctx:expr, imm8_5bits) => { $ctx.cpu.read_imm8() & 31 }; + ($ctx:expr, imm8) => { $ctx.cpu.read_imm8() }; ($ctx:expr, imm8s) => { $ctx.cpu.read_imm8s() }; ($ctx:expr, imm16) => { $ctx.cpu.read_imm16() }; ($ctx:expr, imm32) => { $ctx.cpu.read_imm32() }; @@ -900,6 +917,56 @@ pub fn instr32_7E_jit(_ctx: &mut JitContext, _imm: u32) {} pub fn instr16_7F_jit(_ctx: &mut JitContext, _imm: u32) {} pub fn instr32_7F_jit(_ctx: &mut JitContext, _imm: u32) {} +define_instruction_read_write_mem8!( + "add8", + "instr_80_0_mem", + instr_80_0_mem_jit, + instr_80_0_reg_jit, + imm8 +); +define_instruction_read_write_mem8!( + "or8", + "instr_80_1_mem", + instr_80_1_mem_jit, + instr_80_1_reg_jit, + imm8 +); +define_instruction_read_write_mem8!( + "adc8", + "instr_80_2_mem", + instr_80_2_mem_jit, + instr_80_2_reg_jit, + imm8 +); +define_instruction_read_write_mem8!( + "sbb8", + "instr_80_3_mem", + instr_80_3_mem_jit, + instr_80_3_reg_jit, + imm8 +); +define_instruction_read_write_mem8!( + "and8", + "instr_80_4_mem", + instr_80_4_mem_jit, + instr_80_4_reg_jit, + imm8 +); +define_instruction_read_write_mem8!( + "sub8", + "instr_80_5_mem", + instr_80_5_mem_jit, + instr_80_5_reg_jit, + imm8 +); +define_instruction_read_write_mem8!( + "xor8", + "instr_80_6_mem", + instr_80_6_mem_jit, + instr_80_6_reg_jit, + imm8 +); + define_instruction_read_write_mem16!( "add16", "instr16_81_0_mem", @@ -1110,6 +1177,7 @@ define_instruction_read_write_mem32!( imm8s ); +define_instruction_read8!("cmp8", instr_80_7_mem_jit, instr_80_7_reg_jit, imm8); define_instruction_read16!("cmp16", instr16_81_7_mem_jit, instr16_81_7_reg_jit, imm16); define_instruction_read32!("cmp32", instr32_81_7_mem_jit, instr32_81_7_reg_jit, imm32); From b0f3fd88c472a2690f095de642d9edfd49bbcd8d Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 13 Sep 2018 12:04:26 -0500 Subject: [PATCH 1357/2137] report_safe_{read,write}_jit_slow: not_user can happen (it just doesn't happen very often) --- src/rust/cpu2/cpu.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 420b8af3..832d8ad3 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1337,11 +1337,14 @@ pub fn report_safe_read_jit_slow(address: u32, entry: i32) { else if entry & TLB_IN_MAPPED_RANGE != 0 { profiler::stat_increment(S_SAFE_READ_SLOW_IN_MAPPED_RANGE); } + else if entry & TLB_NO_USER != 0 { + profiler::stat_increment(S_SAFE_READ_SLOW_NOT_USER); + } else if address & 0xFFF > 0x1000 - 4 { profiler::stat_increment(S_SAFE_READ_SLOW_PAGE_CROSSED); } else { - // NOT_USER is not possible since gen_safe_read generates a mask for cpl0 + dbg_log!("Unexpected entry bit: {:x} (read at {:x})", entry, address); dbg_assert!(false); } } @@ -1361,11 +1364,13 @@ pub fn report_safe_write_jit_slow(address: u32, entry: i32) { else if entry & TLB_READONLY != 0 { profiler::stat_increment(S_SAFE_WRITE_SLOW_READ_ONLY); } + else if entry & TLB_NO_USER != 0 { + profiler::stat_increment(S_SAFE_WRITE_SLOW_NOT_USER); + } else if address & 0xFFF > 0x1000 - 4 { profiler::stat_increment(S_SAFE_WRITE_SLOW_PAGE_CROSSED); } else { - // NOT_USER is not possible since gen_safe_write generates a mask for for cpl0 dbg_assert!(false); } } From 8de547455eeac51999c19416860e7375160c40cc Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 13 Sep 2018 12:30:35 -0500 Subject: [PATCH 1358/2137] jit memory access for imul --- gen/x86_table.js | 4 +- src/rust/jit_instructions.rs | 84 ++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 2b6132d7..3d7b805e 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -119,9 +119,9 @@ const encodings = [ { opcode: 0x67, prefix: 1, }, { opcode: 0x68, custom: 1, os: 1, imm1632: 1 }, - { opcode: 0x69, os: 1, e: 1, imm1632: 1, mask_flags: af, }, // zf? + { opcode: 0x69, os: 1, e: 1, custom: 1, imm1632: 1, mask_flags: af, }, // zf? { opcode: 0x6A, custom: 1, os: 1, imm8s: 1 }, - { opcode: 0x6B, os: 1, e: 1, imm8s: 1, mask_flags: af, }, // zf? + { opcode: 0x6B, os: 1, e: 1, custom: 1, imm8s: 1, mask_flags: af, }, // zf? { opcode: 0x6C, block_boundary: 1, is_string: 1, skip: 1, }, // ins { opcode: 0xF26C, block_boundary: 1, is_string: 1, skip: 1, }, diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 2efff3a5..e37d5f06 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -883,6 +883,90 @@ pub fn instr32_68_jit(ctx: &mut JitContext, imm32: u32) { push32_imm_jit(ctx, im pub fn instr16_6A_jit(ctx: &mut JitContext, imm16: u32) { push16_imm_jit(ctx, imm16) } pub fn instr32_6A_jit(ctx: &mut JitContext, imm32: u32) { push32_imm_jit(ctx, imm32) } +pub fn instr16_69_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg16_offset(r) as i32); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read16(ctx); + let imm16 = ctx.cpu.read_imm16(); + ctx.builder.instruction_body.const_i32(imm16 as i32); + codegen::gen_call_fn2_ret(ctx.builder, "imul_reg16"); + ctx.builder.instruction_body.store_aligned_u16(0); +} +pub fn instr16_69_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm16: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg16_offset(r2) as i32); + codegen::gen_get_reg16(ctx.builder, r1); + ctx.builder.instruction_body.const_i32(imm16 as i32); + codegen::gen_call_fn2_ret(ctx.builder, "imul_reg16"); + ctx.builder.instruction_body.store_aligned_u16(0); +} + +pub fn instr32_69_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg32_offset(r) as i32); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read32(ctx); + let imm32 = ctx.cpu.read_imm32(); + ctx.builder.instruction_body.const_i32(imm32 as i32); + codegen::gen_call_fn2_ret(ctx.builder, "imul_reg32"); + ctx.builder.instruction_body.store_aligned_i32(0); +} +pub fn instr32_69_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm32: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg32_offset(r2) as i32); + codegen::gen_get_reg32(ctx.builder, r1); + ctx.builder.instruction_body.const_i32(imm32 as i32); + codegen::gen_call_fn2_ret(ctx.builder, "imul_reg32"); + ctx.builder.instruction_body.store_aligned_i32(0); +} + +pub fn instr16_6B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg16_offset(r) as i32); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read16(ctx); + let imm8s = ctx.cpu.read_imm8s(); + ctx.builder.instruction_body.const_i32(imm8s as i32); + codegen::gen_call_fn2_ret(ctx.builder, "imul_reg16"); + ctx.builder.instruction_body.store_aligned_u16(0); +} +pub fn instr16_6B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm8s: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg16_offset(r2) as i32); + codegen::gen_get_reg16(ctx.builder, r1); + ctx.builder.instruction_body.const_i32(imm8s as i32); + codegen::gen_call_fn2_ret(ctx.builder, "imul_reg16"); + ctx.builder.instruction_body.store_aligned_u16(0); +} + +pub fn instr32_6B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg32_offset(r) as i32); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read32(ctx); + let imm8s = ctx.cpu.read_imm8s(); + ctx.builder.instruction_body.const_i32(imm8s as i32); + codegen::gen_call_fn2_ret(ctx.builder, "imul_reg32"); + ctx.builder.instruction_body.store_aligned_i32(0); +} +pub fn instr32_6B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm8s: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg32_offset(r2) as i32); + codegen::gen_get_reg32(ctx.builder, r1); + ctx.builder.instruction_body.const_i32(imm8s as i32); + codegen::gen_call_fn2_ret(ctx.builder, "imul_reg32"); + ctx.builder.instruction_body.store_aligned_i32(0); +} + // Code for conditional jumps is generated automatically by the basic block codegen pub fn instr16_70_jit(_ctx: &mut JitContext, _imm: u32) {} pub fn instr32_70_jit(_ctx: &mut JitContext, _imm: u32) {} From 3f9b32cdd8e3f2114c6f5e4b0e39ed5617834163 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 13 Sep 2018 12:38:53 -0500 Subject: [PATCH 1359/2137] Improve stats for run_interpreted --- src/rust/jit.rs | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/rust/jit.rs b/src/rust/jit.rs index e9b59475..17eb3afc 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -391,25 +391,27 @@ fn jit_hot_hash_page(page: Page) -> u32 { page.to_u32() % HASH_PRIME } fn is_near_end_of_page(address: u32) -> bool { address & 0xFFF >= 0x1000 - MAX_INSTRUCTION_LENGTH } pub fn jit_find_cache_entry(phys_address: u32, state_flags: CachedStateFlags) -> cached_code { + if is_near_end_of_page(phys_address) { + profiler::stat_increment(stat::S_RUN_INTERPRETED_NEAR_END_OF_PAGE); + } + + let mut run_interpreted_reason = None; + for i in 0..CODE_CACHE_SEARCH_SIZE { let index = (phys_address + i) & jit_cache_array::MASK; let entry = jit_cache_array::get_unchecked(index); - #[cfg(debug_assertions)] - { - if entry.start_addr == phys_address { - if entry.pending { - profiler::stat_increment(stat::S_RUN_INTERPRETED_PENDING) - } - if entry.state_flags != state_flags { - profiler::stat_increment(stat::S_RUN_INTERPRETED_DIFFERENT_STATE) - } + if entry.start_addr == phys_address { + if entry.pending { + run_interpreted_reason = Some(stat::S_RUN_INTERPRETED_PENDING) } + if entry.state_flags != state_flags { + run_interpreted_reason = Some(stat::S_RUN_INTERPRETED_DIFFERENT_STATE) + } + } - if is_near_end_of_page(phys_address) { - dbg_assert!(entry.start_addr != phys_address); - profiler::stat_increment(stat::S_RUN_INTERPRETED_NEAR_END_OF_PAGE); - } + if is_near_end_of_page(phys_address) { + dbg_assert!(entry.start_addr != phys_address); } if !entry.pending && entry.start_addr == phys_address && entry.state_flags == state_flags { @@ -424,6 +426,10 @@ pub fn jit_find_cache_entry(phys_address: u32, state_flags: CachedStateFlags) -> } } + if let Some(reason) = run_interpreted_reason { + profiler::stat_increment(reason); + } + cached_code::NONE } From 5eaece7743f91287ccabce8b9fb3d20cd82721db Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 13 Sep 2018 13:01:04 -0500 Subject: [PATCH 1360/2137] jit memory moves with immediate address (A0/A1/A2/A3) --- gen/x86_table.js | 9 +++--- src/rust/jit_instructions.rs | 60 ++++++++++++++++++++++++++++++++++++ src/rust/modrm.rs | 2 +- src/rust/regs.rs | 1 + 4 files changed, 66 insertions(+), 6 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 3d7b805e..f5511fdd 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -171,11 +171,10 @@ const encodings = [ { opcode: 0x9E, }, { opcode: 0x9F, }, - // XXX: temporarily marked as block boundary until uses gen_safe_{read,write} - { opcode: 0xA0, immaddr: 1, block_boundary: 1 }, - { opcode: 0xA1, os: 1, immaddr: 1, block_boundary: 1 }, - { opcode: 0xA2, immaddr: 1, block_boundary: 1 }, - { opcode: 0xA3, os: 1, immaddr: 1, block_boundary: 1 }, + { opcode: 0xA0, custom: 1, immaddr: 1 }, + { opcode: 0xA1, custom: 1, os: 1, immaddr: 1 }, + { opcode: 0xA2, custom: 1, immaddr: 1 }, + { opcode: 0xA3, custom: 1, os: 1, immaddr: 1 }, // string instructions aren't jumps, but they modify eip due to how they're implemented { opcode: 0xA4, block_boundary: 1, is_string: 1, }, diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index e37d5f06..ead7a8c1 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -6,6 +6,7 @@ use cpu_context::CpuContext; use global_pointers; use jit::JitContext; use modrm; +use modrm::jit_add_seg_offset; use prefix::SEG_PREFIX_ZERO; use prefix::{PREFIX_66, PREFIX_67, PREFIX_F2, PREFIX_F3}; use regs; @@ -1998,6 +1999,65 @@ pub fn instr32_0F8F_jit(_ctx: &mut JitContext, _imm: u32) {} pub fn instr_90_jit(_ctx: &mut JitContext) {} +pub fn instr_A0_jit(ctx: &mut JitContext, immaddr: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg8_offset(regs::AL) as i32); + ctx.builder.instruction_body.const_i32(immaddr as i32); + jit_add_seg_offset(ctx, regs::DS); + codegen::gen_safe_read8(ctx); + ctx.builder.instruction_body.store_u8(0); +} +pub fn instr16_A1_jit(ctx: &mut JitContext, immaddr: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg16_offset(regs::AX) as i32); + ctx.builder.instruction_body.const_i32(immaddr as i32); + jit_add_seg_offset(ctx, regs::DS); + codegen::gen_safe_read16(ctx); + ctx.builder.instruction_body.store_aligned_u16(0); +} +pub fn instr32_A1_jit(ctx: &mut JitContext, immaddr: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg32_offset(regs::EAX) as i32); + ctx.builder.instruction_body.const_i32(immaddr as i32); + jit_add_seg_offset(ctx, regs::DS); + codegen::gen_safe_read32(ctx); + ctx.builder.instruction_body.store_aligned_i32(0); +} + +pub fn instr_A2_jit(ctx: &mut JitContext, immaddr: u32) { + ctx.builder.instruction_body.const_i32(immaddr as i32); + jit_add_seg_offset(ctx, regs::DS); + let address_local = ctx.builder.set_new_local(); + codegen::gen_get_reg8(ctx.builder, regs::AL); + let value_local = ctx.builder.set_new_local(); + codegen::gen_safe_write8(ctx, &address_local, &value_local); + ctx.builder.free_local(address_local); + ctx.builder.free_local(value_local); +} +pub fn instr16_A3_jit(ctx: &mut JitContext, immaddr: u32) { + ctx.builder.instruction_body.const_i32(immaddr as i32); + jit_add_seg_offset(ctx, regs::DS); + let address_local = ctx.builder.set_new_local(); + codegen::gen_get_reg16(ctx.builder, regs::AX); + let value_local = ctx.builder.set_new_local(); + codegen::gen_safe_write16(ctx, &address_local, &value_local); + ctx.builder.free_local(address_local); + ctx.builder.free_local(value_local); +} +pub fn instr32_A3_jit(ctx: &mut JitContext, immaddr: u32) { + ctx.builder.instruction_body.const_i32(immaddr as i32); + jit_add_seg_offset(ctx, regs::DS); + let address_local = ctx.builder.set_new_local(); + codegen::gen_get_reg32(ctx.builder, regs::EAX); + let value_local = ctx.builder.set_new_local(); + codegen::gen_safe_write32(ctx, &address_local, &value_local); + ctx.builder.free_local(address_local); + ctx.builder.free_local(value_local); +} + pub fn instr_0F19_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) { modrm::skip(ctx.cpu, modrm_byte); } diff --git a/src/rust/modrm.rs b/src/rust/modrm.rs index ed6e0abf..b4a92a81 100644 --- a/src/rust/modrm.rs +++ b/src/rust/modrm.rs @@ -311,7 +311,7 @@ fn can_optimize_get_seg(ctx: &mut JitContext, segment: u32) -> bool { (segment == DS || segment == SS) && ctx.cpu.has_flat_segmentation() } -fn jit_add_seg_offset(ctx: &mut JitContext, default_segment: u32) { +pub fn jit_add_seg_offset(ctx: &mut JitContext, default_segment: u32) { let prefix = ctx.cpu.prefixes & PREFIX_MASK_SEGMENT; let seg = if prefix != 0 { prefix - 1 diff --git a/src/rust/regs.rs b/src/rust/regs.rs index c6f7781c..18eb746c 100644 --- a/src/rust/regs.rs +++ b/src/rust/regs.rs @@ -23,6 +23,7 @@ pub const BP: u32 = 5; pub const SI: u32 = 6; pub const DI: u32 = 7; +pub const AL: u32 = 0; pub const CL: u32 = 1; pub const CR0_EM: u32 = 1 << 2; From 8447b6bb836e3b0212f9b60d8e3dd12e9d609526 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 13 Sep 2018 16:55:16 -0500 Subject: [PATCH 1361/2137] Fix prefixes in jitted code: Reset after exception --- src/rust/cpu2/cpu.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 832d8ad3..bf2a6828 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -579,6 +579,7 @@ pub unsafe fn trigger_pagefault(write: bool, user: bool, present: bool) { // invalidate tlb entry let page: i32 = (*cr.offset(2) as u32 >> 12) as i32; *tlb_data.offset(page as isize) = 0; + *prefixes = 0; *instruction_pointer = *previous_ip; //*page_fault = true; call_interrupt_vector( @@ -1031,10 +1032,12 @@ pub unsafe fn cycle_internal() { let initial_tsc = *timestamp_counter; let wasm_table_index = (entry & 0xFFFF) as u16; let initial_state = (entry >> 16) as u16; + dbg_assert!(*prefixes == 0); call_indirect1( (wasm_table_index as u32).wrapping_add(WASM_TABLE_OFFSET as u32) as i32, initial_state, ); + dbg_assert!(*prefixes == 0); profiler::stat_increment_by( S_RUN_FROM_CACHE_STEPS, (*timestamp_counter - initial_tsc) as u64, @@ -1066,7 +1069,9 @@ pub unsafe fn cycle_internal() { *previous_ip = *instruction_pointer; let opcode = return_on_pagefault!(read_imm8()); *timestamp_counter += 1; + dbg_assert!(*prefixes == 0); run_instruction(opcode | (*is_32 as i32) << 8); + dbg_assert!(*prefixes == 0); } } @@ -1089,7 +1094,9 @@ unsafe fn jit_run_interpreted(phys_addr: i32) { let opcode = *mem8.offset(phys_addr as isize) as i32; *instruction_pointer += 1; *timestamp_counter += 1; + dbg_assert!(*prefixes == 0); run_instruction(opcode | (*is_32 as i32) << 8); + dbg_assert!(*prefixes == 0); while !jit_block_boundary && 0 != same_page(*previous_ip, *instruction_pointer) as i32 { *previous_ip = *instruction_pointer; @@ -1117,7 +1124,9 @@ unsafe fn jit_run_interpreted(phys_addr: i32) { // logop(*previous_ip, opcode_0); //} + dbg_assert!(*prefixes == 0); run_instruction(opcode | (*is_32 as i32) << 8); + dbg_assert!(*prefixes == 0); } } @@ -1167,6 +1176,7 @@ pub unsafe fn trigger_de() { return; } } + *prefixes = 0; *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_DE, false, false, 0); } @@ -1180,6 +1190,7 @@ pub unsafe fn trigger_ud() { return; } } + *prefixes = 0; *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_UD, false, false, 0); } @@ -1190,6 +1201,7 @@ pub unsafe fn trigger_nm() { return; } } + *prefixes = 0; *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_NM, false, false, 0); } @@ -1201,6 +1213,7 @@ pub unsafe fn trigger_gp_non_raising(code: i32) { return; } } + *prefixes = 0; *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_GP, false, true, code); } @@ -1989,6 +2002,7 @@ pub unsafe fn trigger_np(code: i32) { return; } } + *prefixes = 0; *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_NP, false, true, code); } @@ -2000,6 +2014,7 @@ pub unsafe fn trigger_ss(code: i32) { return; } } + *prefixes = 0; *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_SS, false, true, code); } From 20d22a0bc003323ce0edfdb9296c9e77adc0d84c Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Mon, 17 Sep 2018 17:28:37 +0530 Subject: [PATCH 1362/2137] loader.js: Try to carry on even if some scripts fail to load For eg. some BUILD_FILES are optional - the order doesn't really matter, so we ought to keep loading whatever we can (i.e. if we don't have Capstone, we should still be able to load libwabt). Note: Even without this change, v86 would have kept trying to load and run, ignoring any 404s; this change just makes it likelier that we'll ignore ignorable errors. --- loader.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/loader.js b/loader.js index d23465b6..9d75796b 100644 --- a/loader.js +++ b/loader.js @@ -44,7 +44,7 @@ function load_next() { - var s = to_load.shift(); + let s = to_load.shift(); if(!s) { @@ -54,6 +54,11 @@ var script = document.createElement("script"); script.src = s; script.onload = load_next; + script.onerror = function() { + dbg_log("Warning: trying to ignore script " + s + ", which failed to load"); + + load_next(); + }; document.head.appendChild(script); } })(); From 7e3f1ad4017323c4d549356a6913f13f77854e8f Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 14 Sep 2018 19:57:38 -0500 Subject: [PATCH 1363/2137] gen_fn: Accept wasm builder, not jit context --- gen/generate_jit.js | 10 +++++----- src/rust/codegen.rs | 31 ++++++++++++------------------- src/rust/jit_instructions.rs | 20 ++++++++++---------- 3 files changed, 27 insertions(+), 34 deletions(-) diff --git a/gen/generate_jit.js b/gen/generate_jit.js index a8862953..6b3f4669 100755 --- a/gen/generate_jit.js +++ b/gen/generate_jit.js @@ -199,7 +199,7 @@ function gen_instruction_body_after_prefix(encodings, size) default_case: { body: [].concat( - gen_call(`::codegen::gen_fn0_const`, ["ctx", '"trigger_ud"']), + gen_call(`::codegen::gen_fn0_const`, ["ctx.builder", '"trigger_ud"']), "*instr_flags |= ::jit::JIT_INSTR_BLOCK_BOUNDARY_FLAG;" ), } @@ -264,7 +264,7 @@ function gen_instruction_body_after_fixed_g(encoding, size) // Has modrm byte, but the 2 mod bits are ignored and both // operands are always registers (0f20-0f24) - const args = ["ctx", `"${instruction_name}"`, "(modrm_byte & 7) as u32", "(modrm_byte >> 3 & 7) as u32"]; + const args = ["ctx.builder", `"${instruction_name}"`, "(modrm_byte & 7) as u32", "(modrm_byte >> 3 & 7) as u32"]; return [].concat( instruction_prefix, @@ -316,8 +316,8 @@ function gen_instruction_body_after_fixed_g(encoding, size) } else { - const mem_args = ["ctx", `"${instruction_name}_mem"`]; - const reg_args = ["ctx", `"${instruction_name}_reg"`, "(modrm_byte & 7) as u32"]; + const mem_args = ["ctx.builder", `"${instruction_name}_mem"`]; + const reg_args = ["ctx.builder", `"${instruction_name}_reg"`, "(modrm_byte & 7) as u32"]; if(encoding.fixed_g === undefined) { @@ -383,7 +383,7 @@ function gen_instruction_body_after_fixed_g(encoding, size) { // instruction without modrm byte or prefix - const args = ["ctx", `"${instruction_name}"`]; + const args = ["ctx.builder", `"${instruction_name}"`]; if(imm_read) { diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 784d3468..0bff2c8d 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -98,8 +98,7 @@ pub fn sign_extend_i16(builder: &mut WasmBuilder) { builder.instruction_body.shr_s_i32(); } -pub fn gen_fn0_const(ctx: &mut JitContext, name: &str) { - let builder = &mut ctx.builder; +pub fn gen_fn0_const(builder: &mut WasmBuilder, name: &str) { let fn_idx = builder.get_fn_idx(name, module_init::FN0_TYPE_INDEX); builder.instruction_body.call_fn(fn_idx); } @@ -109,8 +108,7 @@ pub fn gen_fn0_const_ret(builder: &mut WasmBuilder, name: &str) { builder.instruction_body.call_fn(fn_idx); } -pub fn gen_fn1_const(ctx: &mut JitContext, name: &str, arg0: u32) { - let builder = &mut ctx.builder; +pub fn gen_fn1_const(builder: &mut WasmBuilder, name: &str, arg0: u32) { let fn_idx = builder.get_fn_idx(name, module_init::FN1_TYPE_INDEX); builder.instruction_body.const_i32(arg0 as i32); builder.instruction_body.call_fn(fn_idx); @@ -122,8 +120,7 @@ pub fn gen_call_fn1_ret(builder: &mut WasmBuilder, name: &str) { builder.instruction_body.call_fn(fn_idx); } -pub fn gen_fn2_const(ctx: &mut JitContext, name: &str, arg0: u32, arg1: u32) { - let builder = &mut ctx.builder; +pub fn gen_fn2_const(builder: &mut WasmBuilder, name: &str, arg0: u32, arg1: u32) { let fn_idx = builder.get_fn_idx(name, module_init::FN2_TYPE_INDEX); builder.instruction_body.const_i32(arg0 as i32); builder.instruction_body.const_i32(arg1 as i32); @@ -148,14 +145,12 @@ pub fn gen_call_fn2_ret(builder: &mut WasmBuilder, name: &str) { builder.instruction_body.call_fn(fn_idx); } -pub fn gen_call_fn3(ctx: &mut JitContext, name: &str) { - let builder = &mut ctx.builder; +pub fn gen_call_fn3(builder: &mut WasmBuilder, name: &str) { let fn_idx = builder.get_fn_idx(name, module_init::FN3_TYPE_INDEX); builder.instruction_body.call_fn(fn_idx); } -pub fn gen_fn3_const(ctx: &mut JitContext, name: &str, arg0: u32, arg1: u32, arg2: u32) { - let builder = &mut ctx.builder; +pub fn gen_fn3_const(builder: &mut WasmBuilder, name: &str, arg0: u32, arg1: u32, arg2: u32) { let fn_idx = builder.get_fn_idx(name, module_init::FN3_TYPE_INDEX); builder.instruction_body.const_i32(arg0 as i32); builder.instruction_body.const_i32(arg1 as i32); @@ -163,24 +158,21 @@ pub fn gen_fn3_const(ctx: &mut JitContext, name: &str, arg0: u32, arg1: u32, arg builder.instruction_body.call_fn(fn_idx); } -pub fn gen_modrm_fn0(ctx: &mut JitContext, name: &str) { +pub fn gen_modrm_fn0(builder: &mut WasmBuilder, name: &str) { // generates: fn( _ ) - let builder = &mut ctx.builder; let fn_idx = builder.get_fn_idx(name, module_init::FN1_TYPE_INDEX); builder.instruction_body.call_fn(fn_idx); } -pub fn gen_modrm_fn1(ctx: &mut JitContext, name: &str, arg0: u32) { +pub fn gen_modrm_fn1(builder: &mut WasmBuilder, name: &str, arg0: u32) { // generates: fn( _, arg0 ) - let builder = &mut ctx.builder; let fn_idx = builder.get_fn_idx(name, module_init::FN2_TYPE_INDEX); builder.instruction_body.const_i32(arg0 as i32); builder.instruction_body.call_fn(fn_idx); } -pub fn gen_modrm_fn2(ctx: &mut JitContext, name: &str, arg0: u32, arg1: u32) { +pub fn gen_modrm_fn2(builder: &mut WasmBuilder, name: &str, arg0: u32, arg1: u32) { // generates: fn( _, arg0, arg1 ) - let builder = &mut ctx.builder; let fn_idx = builder.get_fn_idx(name, module_init::FN3_TYPE_INDEX); builder.instruction_body.const_i32(arg0 as i32); builder.instruction_body.const_i32(arg1 as i32); @@ -694,7 +686,6 @@ pub fn gen_pop32s(ctx: &mut JitContext) { pub fn gen_task_switch_test(ctx: &mut JitContext) { // generate if(cr[0] & (CR0_EM | CR0_TS)) { task_switch_test_void(); return; } - let cr0_offset = global_pointers::get_creg_offset(0); ctx.builder.instruction_body.load_aligned_i32(cr0_offset); @@ -705,7 +696,8 @@ pub fn gen_task_switch_test(ctx: &mut JitContext) { ctx.builder.instruction_body.if_void(); - gen_fn0_const(ctx, "task_switch_test_void"); + gen_fn0_const(ctx.builder, "task_switch_test_void"); + ctx.builder.instruction_body.return_(); ctx.builder.instruction_body.block_end(); @@ -723,7 +715,8 @@ pub fn gen_task_switch_test_mmx(ctx: &mut JitContext) { ctx.builder.instruction_body.if_void(); - gen_fn0_const(ctx, "task_switch_test_mmx_void"); + gen_fn0_const(ctx.builder, "task_switch_test_mmx_void"); + ctx.builder.instruction_body.return_(); ctx.builder.instruction_body.block_end(); diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index ead7a8c1..f42621dc 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1387,11 +1387,11 @@ pub fn instr32_8D_mem_jit(ctx: &mut JitContext, modrm_byte: u8, reg: u32) { } pub fn instr16_8D_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - codegen::gen_fn2_const(ctx, "instr16_8D_reg", r1, r2); + codegen::gen_fn2_const(ctx.builder, "instr16_8D_reg", r1, r2); } pub fn instr32_8D_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - codegen::gen_fn2_const(ctx, "instr32_8D_reg", r1, r2); + codegen::gen_fn2_const(ctx.builder, "instr32_8D_reg", r1, r2); } pub fn instr16_8F_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { @@ -1404,10 +1404,10 @@ pub fn instr16_8F_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { ctx.builder.instruction_body.store_aligned_u16(0); codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_modrm_fn0(ctx, "instr16_8F_0_mem_jit"); + codegen::gen_modrm_fn0(ctx.builder, "instr16_8F_0_mem_jit"); } pub fn instr16_8F_0_reg_jit(ctx: &mut JitContext, r: u32) { - codegen::gen_fn1_const(ctx, "instr16_8F_0_reg", r); + codegen::gen_fn1_const(ctx.builder, "instr16_8F_0_reg", r); } pub fn instr32_8F_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { ctx.builder @@ -1419,10 +1419,10 @@ pub fn instr32_8F_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { ctx.builder.instruction_body.store_aligned_i32(0); codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_modrm_fn0(ctx, "instr32_8F_0_mem_jit"); + codegen::gen_modrm_fn0(ctx.builder, "instr32_8F_0_mem_jit"); } pub fn instr32_8F_0_reg_jit(ctx: &mut JitContext, r: u32) { - codegen::gen_fn1_const(ctx, "instr32_8F_0_reg", r); + codegen::gen_fn1_const(ctx.builder, "instr32_8F_0_reg", r); } define_instruction_read_write_mem16!( @@ -2291,14 +2291,14 @@ macro_rules! define_cmovcc16( codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read16(ctx); ctx.builder.instruction_body.const_i32(r as i32); - codegen::gen_call_fn3(ctx, "cmovcc16") + codegen::gen_call_fn3(ctx.builder, "cmovcc16") } pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_fn0_const_ret(ctx.builder, $cond); codegen::gen_get_reg16(ctx.builder, r1); ctx.builder.instruction_body.const_i32(r2 as i32); - codegen::gen_call_fn3(ctx, "cmovcc16") + codegen::gen_call_fn3(ctx.builder, "cmovcc16") } ); ); @@ -2310,14 +2310,14 @@ macro_rules! define_cmovcc32( codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); ctx.builder.instruction_body.const_i32(r as i32); - codegen::gen_call_fn3(ctx, "cmovcc32") + codegen::gen_call_fn3(ctx.builder, "cmovcc32") } pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_fn0_const_ret(ctx.builder, $cond); codegen::gen_get_reg32(ctx.builder, r1); ctx.builder.instruction_body.const_i32(r2 as i32); - codegen::gen_call_fn3(ctx, "cmovcc32") + codegen::gen_call_fn3(ctx.builder, "cmovcc32") } ); ); From 7e1d398e05f0d54c892cf5b3772498770e1625ad Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 17 Sep 2018 17:14:10 -0500 Subject: [PATCH 1364/2137] Track last executed jump instruction, check for missed entry points while looking for compiled code --- src/browser/print_stats.js | 3 +- src/rust/codegen.rs | 11 ++++++ src/rust/cpu2/cpu.rs | 67 +++++++++++++++++++++++++++++++++++-- src/rust/jit.rs | 68 +++++++++++++++++++++++++++++++++++--- src/rust/profiler.rs | 3 +- 5 files changed, 143 insertions(+), 9 deletions(-) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index d28b4e85..bff0ecff 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -25,7 +25,8 @@ const print_stats = { "RUN_INTERPRETED_PENDING", "RUN_INTERPRETED_NEAR_END_OF_PAGE", "RUN_INTERPRETED_DIFFERENT_STATE", - "RUN_INTERPRETED_MISSED_COMPILED_ENTRY", + "RUN_INTERPRETED_MISSED_COMPILED_ENTRY_RUN_INTERPRETED", + "RUN_INTERPRETED_MISSED_COMPILED_ENTRY_LOOKUP", "RUN_INTERPRETED_STEPS", "RUN_FROM_CACHE", "RUN_FROM_CACHE_STEPS", diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 0bff2c8d..145a9326 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -351,6 +351,7 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { .load_u8(global_pointers::PAGE_FAULT); builder.instruction_body.if_void(); + gen_debug_track_jit_exit(builder, ctx.start_of_current_instruction); builder.instruction_body.return_(); builder.instruction_body.block_end(); @@ -494,6 +495,7 @@ fn gen_safe_write( .load_u8(global_pointers::PAGE_FAULT); builder.instruction_body.if_void(); + gen_debug_track_jit_exit(builder, ctx.start_of_current_instruction); builder.instruction_body.return_(); builder.instruction_body.block_end(); @@ -698,6 +700,7 @@ pub fn gen_task_switch_test(ctx: &mut JitContext) { gen_fn0_const(ctx.builder, "task_switch_test_void"); + gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); ctx.builder.instruction_body.return_(); ctx.builder.instruction_body.block_end(); @@ -717,6 +720,7 @@ pub fn gen_task_switch_test_mmx(ctx: &mut JitContext) { gen_fn0_const(ctx.builder, "task_switch_test_mmx_void"); + gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); ctx.builder.instruction_body.return_(); ctx.builder.instruction_body.block_end(); @@ -949,6 +953,7 @@ pub fn gen_safe_read_write( .load_u8(global_pointers::PAGE_FAULT); ctx.builder.instruction_body.if_void(); + gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); ctx.builder.instruction_body.return_(); ctx.builder.instruction_body.block_end(); @@ -961,3 +966,9 @@ pub fn gen_profiler_stat_increment(builder: &mut WasmBuilder, stat: profiler::st let addr = unsafe { profiler::stat_array.as_mut_ptr().offset(stat as isize) } as u32; gen_increment_variable(builder, addr, 1) } + +pub fn gen_debug_track_jit_exit(builder: &mut WasmBuilder, address: u32) { + if cfg!(feature = "profiler") { + gen_fn1_const(builder, "track_jit_exit", address); + } +} diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index bf2a6828..d2f1e65d 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -67,6 +67,8 @@ pub union reg128 { pub f64_0: [f64; 2], } +pub const CHECK_MISSED_ENTRY_POINTS: bool = false; + pub const FLAG_CARRY: i32 = 1; pub const FLAG_PARITY: i32 = 4; pub const FLAG_ADJUST: i32 = 16; @@ -248,6 +250,41 @@ pub static mut tsc_offset: u64 = 0; pub static mut valid_tlb_entries: [i32; 10000] = [0; 10000]; pub static mut valid_tlb_entries_count: i32 = 0; +pub enum LastJump { + Interrupt { + phys_addr: u32, + int: u8, + software: bool, + error: Option, + }, + Compiled { + phys_addr: u32, + }, + Interpreted { + phys_addr: u32, + }, + None, +} +impl LastJump { + pub fn phys_address(&self) -> Option { + match self { + LastJump::Interrupt { phys_addr, .. } => Some(*phys_addr), + LastJump::Compiled { phys_addr } => Some(*phys_addr), + LastJump::Interpreted { phys_addr } => Some(*phys_addr), + LastJump::None => None, + } + } + pub fn name(&self) -> &'static str { + match self { + LastJump::Interrupt { .. } => "interrupt", + LastJump::Compiled { .. } => "compiled", + LastJump::Interpreted { .. } => "interpreted", + LastJump::None => "none", + } + } +} +pub static mut debug_last_jump: LastJump = LastJump::None; + pub struct SegmentSelector { raw: u16, } @@ -304,6 +341,13 @@ impl SegmentDescriptor { pub unsafe fn after_block_boundary() { jit_block_boundary = true; } +#[no_mangle] +pub fn track_jit_exit(phys_addr: u32) { + unsafe { + debug_last_jump = LastJump::Compiled { phys_addr }; + } +} + pub unsafe fn same_page(addr1: i32, addr2: i32) -> bool { return addr1 & !0xFFF == addr2 & !0xFFF; } #[no_mangle] @@ -1044,6 +1088,13 @@ pub unsafe fn cycle_internal() { ); } else { + #[cfg(feature = "profiler")] + { + if CHECK_MISSED_ENTRY_POINTS { + ::jit::check_missed_entry_points(phys_addr, state_flags as u32); + } + } + if DEBUG { dbg_assert!(!must_not_fault); must_not_fault = true @@ -1090,6 +1141,12 @@ unsafe fn jit_run_interpreted(phys_addr: i32) { profiler::stat_increment(S_RUN_INTERPRETED); dbg_assert!(!in_mapped_range(phys_addr as u32)); + if cfg!(debug_assertions) { + debug_last_jump = LastJump::Interpreted { + phys_addr: phys_addr as u32, + }; + } + jit_block_boundary = false; let opcode = *mem8.offset(phys_addr as isize) as i32; *instruction_pointer += 1; @@ -1102,13 +1159,13 @@ unsafe fn jit_run_interpreted(phys_addr: i32) { *previous_ip = *instruction_pointer; let opcode = return_on_pagefault!(read_imm8()); - if DEBUG { + if CHECK_MISSED_ENTRY_POINTS { let phys_addr = return_on_pagefault!(get_phys_eip()) as u32; let state_flags: CachedStateFlags = pack_current_state_flags(); let entry = ::c_api::jit_find_cache_entry(phys_addr, state_flags as u32); if entry != 0 { - profiler::stat_increment(S_RUN_INTERPRETED_MISSED_COMPILED_ENTRY); + profiler::stat_increment(S_RUN_INTERPRETED_MISSED_COMPILED_ENTRY_RUN_INTERPRETED); //dbg_log!( // "missed entry point at {:x} prev_opcode={:x} opcode={:x}", // phys_addr, @@ -1118,6 +1175,12 @@ unsafe fn jit_run_interpreted(phys_addr: i32) { } } + if cfg!(debug_assertions) { + debug_last_jump = LastJump::Interpreted { + phys_addr: phys_addr as u32, + }; + } + *timestamp_counter += 1; //if DEBUG { diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 17eb3afc..02376de8 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -49,7 +49,7 @@ mod jit_cache_array { pub struct Entry { pub start_addr: u32, - #[cfg(debug_assertions)] + #[cfg(any(debug_assertions, feature = "profiler"))] pub len: u32, #[cfg(debug_assertions)] @@ -82,7 +82,7 @@ mod jit_cache_array { state_flags, pending, - #[cfg(debug_assertions)] + #[cfg(any(debug_assertions, feature = "profiler"))] len: 0, #[cfg(debug_assertions)] @@ -116,7 +116,7 @@ mod jit_cache_array { state_flags: CachedStateFlags::EMPTY, pending: false, - #[cfg(debug_assertions)] + #[cfg(any(debug_assertions, feature = "profiler"))] len: 0, #[cfg(debug_assertions)] opcode: 0, @@ -131,7 +131,7 @@ mod jit_cache_array { state_flags: CachedStateFlags::EMPTY, pending: false, - #[cfg(debug_assertions)] + #[cfg(any(debug_assertions, feature = "profiler"))] len: 0, #[cfg(debug_assertions)] opcode: 0, @@ -817,9 +817,13 @@ fn jit_analyze_and_generate( true, ); - #[cfg(debug_assertions)] + #[cfg(any(debug_assertions, feature = "profiler"))] { entry.len = block.end_addr - block.addr; + } + + #[cfg(debug_assertions)] + { entry.opcode = cpu::read32(block.addr); } @@ -963,6 +967,7 @@ fn jit_generate_module( .get_local(gen_local_iteration_counter); builder.instruction_body.eqz_i32(); builder.instruction_body.if_void(); + codegen::gen_debug_track_jit_exit(builder, 0); builder.instruction_body.return_(); builder.instruction_body.block_end(); } @@ -1001,6 +1006,7 @@ fn jit_generate_module( match &block.ty { BasicBlockType::Exit => { // Exit this function + codegen::gen_debug_track_jit_exit(builder, block.last_instruction_addr); builder.instruction_body.return_(); }, BasicBlockType::Normal { next_block_addr } => { @@ -1058,6 +1064,7 @@ fn jit_generate_module( } else { // Jump to different page + codegen::gen_debug_track_jit_exit(builder, block.last_instruction_addr); builder.instruction_body.return_(); } @@ -1077,6 +1084,7 @@ fn jit_generate_module( } else { // End of this page + codegen::gen_debug_track_jit_exit(builder, block.last_instruction_addr); builder.instruction_body.return_(); } @@ -1377,3 +1385,53 @@ pub fn jit_get_wasm_table_index_free_list_count(ctx: &JitState) -> u32 { pub fn jit_get_op_len(ctx: &JitState) -> u32 { ctx.wasm_builder.get_op_len() } pub fn jit_get_op_ptr(ctx: &JitState) -> *const u8 { ctx.wasm_builder.get_op_ptr() } + +#[cfg(feature = "profiler")] +pub fn check_missed_entry_points(phys_address: u32, state_flags: u32) { + let state_flags = CachedStateFlags::of_u32(state_flags); + let page = Page::page_of(phys_address); + + for i in page.to_address()..page.to_address() + 4096 { + // No need to check [CODE_CACHE_SEARCH_SIZE] entries here as we look at consecutive + // addresses anyway + let index = i & jit_cache_array::MASK; + let entry = jit_cache_array::get_unchecked(index); + + if !entry.pending + && entry.state_flags == state_flags + && phys_address >= entry.start_addr + && phys_address < entry.start_addr + entry.len + { + profiler::stat_increment(stat::S_RUN_INTERPRETED_MISSED_COMPILED_ENTRY_LOOKUP); + + let last_jump_type = unsafe { cpu2::cpu::debug_last_jump.name() }; + let last_jump_addr = unsafe { cpu2::cpu::debug_last_jump.phys_address() }.unwrap_or(0); + let last_jump_opcode = if last_jump_addr != 0 { + cpu::read32(last_jump_addr) + } + else { + 0 + }; + + let opcode = cpu::read32(phys_address); + dbg_log!( + "Compiled exists, but no entry point, \ + start={:x} end={:x} phys_addr={:x} opcode={:02x} {:02x} {:02x} {:02x}. \ + Last jump at {:x} ({}) opcode={:02x} {:02x} {:02x} {:02x}", + entry.start_addr, + entry.start_addr + entry.len, + phys_address, + opcode & 0xFF, + opcode >> 8 & 0xFF, + opcode >> 16 & 0xFF, + opcode >> 16 & 0xFF, + last_jump_addr, + last_jump_type, + last_jump_opcode & 0xFF, + last_jump_opcode >> 8 & 0xFF, + last_jump_opcode >> 16 & 0xFF, + last_jump_opcode >> 16 & 0xFF, + ); + } + } +} diff --git a/src/rust/profiler.rs b/src/rust/profiler.rs index 75f8512c..9dd9e894 100644 --- a/src/rust/profiler.rs +++ b/src/rust/profiler.rs @@ -12,7 +12,8 @@ pub enum stat { S_RUN_INTERPRETED_PENDING, S_RUN_INTERPRETED_NEAR_END_OF_PAGE, S_RUN_INTERPRETED_DIFFERENT_STATE, - S_RUN_INTERPRETED_MISSED_COMPILED_ENTRY, + S_RUN_INTERPRETED_MISSED_COMPILED_ENTRY_RUN_INTERPRETED, + S_RUN_INTERPRETED_MISSED_COMPILED_ENTRY_LOOKUP, S_RUN_INTERPRETED_STEPS, S_RUN_FROM_CACHE, From afcce9b371429957616ecf1d5f5d236147faed7d Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 17 Sep 2018 17:33:36 -0500 Subject: [PATCH 1365/2137] Record compiled instructions per opcode --- src/browser/print_stats.js | 35 +++++++++------ src/rust/cpu2/cpu.rs | 14 ++++-- src/rust/cpu2/global_pointers.rs | 6 ++- src/rust/jit.rs | 4 +- src/rust/opstats.rs | 74 ++++++++++++++++++++++++++++---- 5 files changed, 105 insertions(+), 28 deletions(-) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index bff0ecff..ccdcf0e0 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -156,6 +156,12 @@ const print_stats = { }, print_instruction_counts: function(cpu) + { + return print_stats.print_instruction_counts_offset(cpu, 0) + "\n\n" + + print_stats.print_instruction_counts_offset(cpu, 0x200); + }, + + print_instruction_counts_offset: function(cpu, offset) { let text = ""; @@ -163,19 +169,13 @@ const print_stats = { for(let i = 0; i < 0x100; i++) { - const count = cpu.v86oxide.exports["get_opstats_buffer"](i) / 1000 | 0; + const count = cpu.v86oxide.exports["get_opstats_buffer"](i + offset); counts.push([i, count]); - const count_0f = cpu.v86oxide.exports["get_opstats_buffer"](i + 0x100) / 1000 | 0; + const count_0f = cpu.v86oxide.exports["get_opstats_buffer"](i + 0x100 + offset); counts.push([0x0f00 | i, count_0f]); } - const max_count = Math.max.apply(Math, - counts.map(([_, count]) => count) - ); - const pad_length = String(max_count).length; - - text += "Instruction counts (in 1000):\n"; let total = 0; const prefixes = new Set([ 0x26, 0x2E, 0x36, 0x3E, @@ -186,18 +186,29 @@ const print_stats = { { total += i < 0x100 && !prefixes.has(i) ? count : 0; } - text += "Total: " + total + "\n"; if(total === 0) { return ""; } + text += "------------------\n"; + text += "Total: " + total + "\n"; + + const factor = total > 1e7 ? 1000 : 1; + + const max_count = Math.max.apply(Math, + counts.map(([_, count]) => Math.round(count / factor)) + ); + const pad_length = String(max_count).length; + + text += `Instruction counts (in ${factor}):\n`; + for(let [i, count] of counts) { if((i & 0xFF00) === 0) { - text += h(i, 2).slice(2) + ":" + v86util.pads(count, pad_length); + text += h(i, 2).slice(2) + ":" + v86util.pads(Math.round(count / factor), pad_length); if(i % 16 == 15) text += "\n"; @@ -207,13 +218,13 @@ const print_stats = { } text += "\n"; - text += "Instruction counts (0f, in 1000):\n"; + text += `Instruction counts (0f, in ${factor}):\n`; for(let [i, count] of counts) { if((i & 0xFF00) === 0x0F00) { - text += h(i & 0xFF, 2).slice(2) + ":" + v86util.pads(count, pad_length); + text += h(i & 0xFF, 2).slice(2) + ":" + v86util.pads(Math.round(count / factor), pad_length); if(i % 16 == 15) text += "\n"; diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index d2f1e65d..2e7b3be6 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1954,13 +1954,19 @@ pub unsafe fn getiopl() -> i32 { return *flags >> 12 & 3; } #[no_mangle] pub unsafe fn get_opstats_buffer(index: i32) -> i32 { - dbg_assert!(index >= 0 && index < 512); - if index < 256 { + dbg_assert!(index >= 0 && index < 0x400); + if index < 0x100 { return *opstats_buffer.offset(index as isize) as i32; } + else if index < 0x200 { + return *opstats_buffer_0f.offset((index - 0x100) as isize) as i32; + } + else if index < 0x300 { + return *opstats_compiled_buffer.offset((index - 0x200) as isize) as i32; + } else { - return *opstats_buffer_0f.offset((index - 256) as isize) as i32; - }; + return *opstats_compiled_buffer_0f.offset((index - 0x300) as isize) as i32; + } } pub unsafe fn invlpg(addr: i32) { diff --git a/src/rust/cpu2/global_pointers.rs b/src/rust/cpu2/global_pointers.rs index 951f1c74..bb91bb25 100644 --- a/src/rust/cpu2/global_pointers.rs +++ b/src/rust/cpu2/global_pointers.rs @@ -62,6 +62,8 @@ pub const fpu_dp_selector: *mut i32 = 1060 as *mut i32; pub const reg_mmx: *mut reg64 = 1064 as *mut reg64; pub const tss_size_32: *mut bool = 1128 as *mut bool; pub const fxsave_store_fpu_mask: *mut u8 = 1132 as *mut u8; -pub const opstats_buffer: *mut u32 = 4096 as *mut u32; -pub const opstats_buffer_0f: *mut u32 = 5120 as *mut u32; +pub const opstats_buffer: *mut u32 = 0x1000 as *mut u32; +pub const opstats_buffer_0f: *mut u32 = 0x1400 as *mut u32; +pub const opstats_compiled_buffer: *mut u32 = 0x1800 as *mut u32; +pub const opstats_compiled_buffer_0f: *mut u32 = 0x1C00 as *mut u32; pub const tlb_data: *mut i32 = 0x400000 as *mut i32; diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 02376de8..1366107b 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -1121,7 +1121,9 @@ fn jit_generate_basic_block( loop { if false { - ::opstats::gen_opstats(builder, cpu::read32(cpu.eip)); + let instruction = cpu::read32(cpu.eip); + ::opstats::gen_opstats(builder, instruction); + ::opstats::record_opstat_compiled(instruction); } if cpu.eip == last_instruction_addr { diff --git a/src/rust/opstats.rs b/src/rust/opstats.rs index 79f6e2aa..641fbf9b 100644 --- a/src/rust/opstats.rs +++ b/src/rust/opstats.rs @@ -1,15 +1,21 @@ use codegen::gen_increment_mem32; +use cpu2; use global_pointers; use wasmgen::module_init::WasmBuilder; -pub fn gen_opstats(builder: &mut WasmBuilder, mut instruction: u32) { - if !cfg!(debug_assertions) { - return; - } +struct Instruction { + prefixes: Vec, + opcode: u8, + is_0f: bool, +} + +fn decode(mut instruction: u32) -> Instruction { let mut is_0f = false; + let mut prefixes = vec![]; + let mut final_opcode = 0; for _ in 0..4 { - let opcode = instruction & 0xFF; + let opcode = (instruction & 0xFF) as u8; instruction >>= 8; // TODO: @@ -18,12 +24,10 @@ pub fn gen_opstats(builder: &mut WasmBuilder, mut instruction: u32) { // - If the instruction uses 4 or more prefixes, only the prefixes will be counted if is_0f { - gen_increment_mem32(builder, global_pointers::OPSTATS_BUFFER_0F + 4 * opcode); + final_opcode = opcode; break; } else { - gen_increment_mem32(builder, global_pointers::OPSTATS_BUFFER + 4 * opcode); - if opcode == 0x0F { is_0f = true; } @@ -39,11 +43,63 @@ pub fn gen_opstats(builder: &mut WasmBuilder, mut instruction: u32) { || opcode == 0xF2 || opcode == 0xF3 { - // prefix + prefixes.push(opcode); } else { + final_opcode = opcode; break; } } } + + Instruction { + prefixes, + opcode: final_opcode, + is_0f, + } +} + +pub fn gen_opstats(builder: &mut WasmBuilder, opcode: u32) { + if !cfg!(feature = "profiler") { + return; + } + + let instruction = decode(opcode); + + for prefix in instruction.prefixes { + gen_increment_mem32(builder, global_pointers::OPSTATS_BUFFER + 4 * prefix as u32); + } + + if instruction.is_0f { + gen_increment_mem32( + builder, + global_pointers::OPSTATS_BUFFER_0F + 4 * instruction.opcode as u32, + ); + } + else { + gen_increment_mem32( + builder, + global_pointers::OPSTATS_BUFFER + 4 * instruction.opcode as u32, + ); + } +} + +pub fn record_opstat_compiled(opcode: u32) { + let instruction = decode(opcode); + + for prefix in instruction.prefixes { + unsafe { *cpu2::global_pointers::opstats_compiled_buffer.offset(prefix as isize) += 1 } + } + + if instruction.is_0f { + unsafe { + *cpu2::global_pointers::opstats_compiled_buffer_0f + .offset(instruction.opcode as isize) += 1 + } + } + else { + unsafe { + *cpu2::global_pointers::opstats_compiled_buffer.offset(instruction.opcode as isize) += 1 + } + } } From 0798a0b40eae818ad52224af7de173af36cafd4d Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 17 Sep 2018 18:34:10 -0500 Subject: [PATCH 1366/2137] Don't create unnecessary entry points This commit prevents creation of entry points for jumps within the same page. In interpreted mode, execution is continued on these kinds of jumps. Since this prevents the old hotness detection from working efficiently, hotness detection has also been changed to work based on instruction counters, and is such more precise (longer basic blocks are compiled earlier). This also breaks the old detection loop safety mechanism and causes Linux to sometimes loop forever on "calibrating delay loop", so JIT_ALWAYS_USE_LOOP_SAFETY has been set to 1. --- gen/generate_interpreter.js | 6 +- gen/x86_table.js | 75 ++++-- src/rust/c_api.rs | 10 +- src/rust/cpu2/cpu.rs | 29 ++- src/rust/jit.rs | 10 +- tests/expect/tests/call.wast | 71 ++--- tests/expect/tests/if.wast | 25 +- tests/expect/tests/indirect-call.wast | 21 +- tests/expect/tests/mov16.wast | 257 +++++++++--------- tests/expect/tests/mov32-mem.wast | 259 ++++++++++--------- tests/expect/tests/mov32-reg.wast | 19 +- tests/expect/tests/pop.wast | 39 ++- tests/expect/tests/push.wast | 47 ++-- tests/expect/tests/task_switch_test.wast | 23 +- tests/expect/tests/task_switch_test_sse.wast | 23 +- tests/expect/tests/while-do.wast | 25 +- 16 files changed, 559 insertions(+), 380 deletions(-) diff --git a/gen/generate_interpreter.js b/gen/generate_interpreter.js index 5c3909e6..3006f87b 100755 --- a/gen/generate_interpreter.js +++ b/gen/generate_interpreter.js @@ -226,7 +226,11 @@ function gen_instruction_body_after_prefix(encodings, size) function gen_instruction_body_after_fixed_g(encoding, size) { const instruction_prefix = []; - const instruction_postfix = encoding.block_boundary || (!encoding.custom && encoding.e) || encoding.sse || encoding.task_switch_test ? ["after_block_boundary();"] : []; + const instruction_postfix = + (encoding.block_boundary && !encoding.no_block_boundary_in_interpreted) || + (!encoding.custom && encoding.e) || + encoding.sse || + encoding.task_switch_test ? ["after_block_boundary();"] : []; if(encoding.task_switch_test || encoding.sse) { diff --git a/gen/x86_table.js b/gen/x86_table.js index f5511fdd..51f1bd88 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -11,8 +11,38 @@ const af = 1 << 4; const pf = 1 << 2; const sf = 1 << 7; -// TODO: -// - describe which registers are written and read +// === Types of instructions +// +// create entry | check for compiled code | instruction +// -------------+-------------------------+----------------------------------------------------------- +// 1 | optional | pop ds (may change cpu state) +// | | trigger_ud, div (exception that doesn't generate conditional return from BB) +// | | port io, popf, sti (may call interrupt or continue at next instruction) +// | | hlt +// -------------+-------------------------+----------------------------------------------------------- +// 1 | 1 | call [eax], jmp [eax], int, iret, ret, jmpf, callf, sysenter, sysexit +// | | Special case: normal instruction with fallthough to next page +// | | Special case: after execution of compiled code +// | | -> may create redundant entry points depending on last instruction? +// -------------+-------------------------+----------------------------------------------------------- +// 1 | 0 | rep movs, rep lods, rep stos, rep cmps, rep scas +// | | -> Executed as follows: +// | | - Upto including the first call in compiled mode +// | | - Back to main loop and repeated in interpreted mode (as entry point is after instruction, not on) +// | | - When finished entry pointer *after* instruction is hit and execution continues in compiled mode +// -------------+-------------------------+----------------------------------------------------------- +// 0 | optional | jmp foo, jnz foo +// | | (foo is in the same page as the instruction) +// -------------+-------------------------+----------------------------------------------------------- +// 1 | 1 | call foo +// | | (foo is in the same page as the instruction) +// | | -> The entry point is not created for jumps within +// | | this page, but speculatively for calls from +// | | other pages to the function in this page +// -------------+-------------------------+----------------------------------------------------------- +// 1 | 1 | call foo, jmp foo, jnz foo +// | | (foo is in a different page than the instruction) + // os: the instruction behaves differently depending on the operand size const encodings = [ @@ -177,6 +207,7 @@ const encodings = [ { opcode: 0xA3, custom: 1, os: 1, immaddr: 1 }, // string instructions aren't jumps, but they modify eip due to how they're implemented + // TODO: The block_boundary on the non-rep instructions can be removed once they're custom { opcode: 0xA4, block_boundary: 1, is_string: 1, }, { opcode: 0xF2A4, block_boundary: 1, is_string: 1, }, { opcode: 0xF3A4, block_boundary: 1, is_string: 1, }, @@ -257,9 +288,9 @@ const encodings = [ { opcode: 0xE7, block_boundary: 1, os: 1, imm8: 1, skip: 1, }, { opcode: 0xE8, block_boundary: 1, jump_offset_imm: 1, os: 1, imm1632: 1, custom: 1, skip: 1, }, // call - { opcode: 0xE9, block_boundary: 1, jump_offset_imm: 1, no_next_instruction: 1, os: 1, imm1632: 1, custom: 1, skip: 1, }, + { opcode: 0xE9, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, no_next_instruction: 1, os: 1, imm1632: 1, custom: 1, skip: 1, }, { opcode: 0xEA, block_boundary: 1, no_next_instruction: 1, os: 1, imm1632: 1, extra_imm16: 1, skip: 1, }, // jmpf - { opcode: 0xEB, block_boundary: 1, jump_offset_imm: 1, no_next_instruction: 1, os: 1, imm8s: 1, custom: 1, skip: 1, }, + { opcode: 0xEB, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, no_next_instruction: 1, os: 1, imm8s: 1, custom: 1, skip: 1, }, { opcode: 0xEC, block_boundary: 1, skip: 1, }, // in { opcode: 0xED, block_boundary: 1, os: 1, skip: 1, }, @@ -399,22 +430,22 @@ const encodings = [ { opcode: 0x0F4E, e: 1, os: 1, custom: 1, }, { opcode: 0x0F4F, e: 1, os: 1, custom: 1, }, - { opcode: 0x0F80, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, - { opcode: 0x0F81, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, - { opcode: 0x0F82, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, - { opcode: 0x0F83, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, - { opcode: 0x0F84, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, - { opcode: 0x0F85, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, - { opcode: 0x0F86, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, - { opcode: 0x0F87, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, - { opcode: 0x0F88, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, - { opcode: 0x0F89, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, - { opcode: 0x0F8A, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, - { opcode: 0x0F8B, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, - { opcode: 0x0F8C, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, - { opcode: 0x0F8D, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, - { opcode: 0x0F8E, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, - { opcode: 0x0F8F, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, + { opcode: 0x0F80, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, + { opcode: 0x0F81, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, + { opcode: 0x0F82, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, + { opcode: 0x0F83, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, + { opcode: 0x0F84, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, + { opcode: 0x0F85, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, + { opcode: 0x0F86, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, + { opcode: 0x0F87, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, + { opcode: 0x0F88, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, + { opcode: 0x0F89, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, + { opcode: 0x0F8A, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, + { opcode: 0x0F8B, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, + { opcode: 0x0F8C, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, + { opcode: 0x0F8D, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, + { opcode: 0x0F8E, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, + { opcode: 0x0F8F, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, }, { opcode: 0x0F90, e: 1, custom: 1, }, { opcode: 0x0F91, e: 1, custom: 1, }, @@ -842,8 +873,8 @@ for(let i = 0; i < 8; i++) { opcode: 0x04 | i << 3, eax: 1, imm8: 1, }, { opcode: 0x05 | i << 3, os: 1, eax: 1, imm1632: 1, }, - { opcode: 0x70 | i, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, os: 1, imm8s: 1, custom: 1, skip: 1, }, - { opcode: 0x78 | i, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, os: 1, imm8s: 1, custom: 1, skip: 1, }, + { opcode: 0x70 | i, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, os: 1, imm8s: 1, custom: 1, skip: 1, }, + { opcode: 0x78 | i, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, os: 1, imm8s: 1, custom: 1, skip: 1, }, { opcode: 0x80, e: 1, fixed_g: i, imm8: 1, custom: 1, }, { opcode: 0x81, os: 1, e: 1, fixed_g: i, imm1632: 1, custom: 1, }, diff --git a/src/rust/c_api.rs b/src/rust/c_api.rs index 379bfaef..3d7bb2bb 100644 --- a/src/rust/c_api.rs +++ b/src/rust/c_api.rs @@ -8,7 +8,7 @@ use state_flags::CachedStateFlags; static mut MODULE_PTR: NonNull = unsafe { NonNull::new_unchecked(mem::align_of::() as *mut _) }; -fn get_module<'a>() -> &'a mut JitState { unsafe { MODULE_PTR.as_mut() } } +pub fn get_module<'a>() -> &'a mut JitState { unsafe { MODULE_PTR.as_mut() } } #[no_mangle] /// Called from JS, not C @@ -52,12 +52,18 @@ pub fn codegen_finalize_finished( ) } -pub fn jit_increase_hotness_and_maybe_compile(phys_address: u32, cs_offset: u32, state_flags: u32) { +pub fn jit_increase_hotness_and_maybe_compile( + phys_address: u32, + cs_offset: u32, + state_flags: u32, + hotness: u32, +) { ::jit::jit_increase_hotness_and_maybe_compile( get_module(), phys_address, cs_offset, CachedStateFlags::of_u32(state_flags), + hotness, ) } diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 2e7b3be6..53f856ad 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -68,6 +68,7 @@ pub union reg128 { } pub const CHECK_MISSED_ENTRY_POINTS: bool = false; +pub const INTERPRETER_ITERATION_LIMIT: u32 = 1000; pub const FLAG_CARRY: i32 = 1; pub const FLAG_PARITY: i32 = 4; @@ -1088,6 +1089,8 @@ pub unsafe fn cycle_internal() { ); } else { + ::jit::record_entry_point(::c_api::get_module(), phys_addr); + #[cfg(feature = "profiler")] { if CHECK_MISSED_ENTRY_POINTS { @@ -1099,17 +1102,20 @@ pub unsafe fn cycle_internal() { dbg_assert!(!must_not_fault); must_not_fault = true } - ::c_api::jit_increase_hotness_and_maybe_compile( - phys_addr, - get_seg_cs() as u32, - state_flags as u32, - ); if DEBUG { dbg_assert!(must_not_fault); must_not_fault = false } let initial_tsc = *timestamp_counter; jit_run_interpreted(phys_addr as i32); + + ::c_api::jit_increase_hotness_and_maybe_compile( + phys_addr, + get_seg_cs() as u32, + state_flags as u32, + *timestamp_counter - initial_tsc, + ); + profiler::stat_increment_by( S_RUN_INTERPRETED_STEPS, (*timestamp_counter - initial_tsc) as u64, @@ -1118,6 +1124,7 @@ pub unsafe fn cycle_internal() { } else { *previous_ip = *instruction_pointer; + let opcode = return_on_pagefault!(read_imm8()); *timestamp_counter += 1; dbg_assert!(*prefixes == 0); @@ -1155,7 +1162,15 @@ unsafe fn jit_run_interpreted(phys_addr: i32) { run_instruction(opcode | (*is_32 as i32) << 8); dbg_assert!(*prefixes == 0); - while !jit_block_boundary && 0 != same_page(*previous_ip, *instruction_pointer) as i32 { + // We need to limit the number of iterations here as jumps within the same page are not counted + // as block boundaries for the interpreter (as they don't create an entry point and don't need + // a check if the jump target may have compiled code) + let mut i = 0; + + while !jit_block_boundary + && same_page(*previous_ip, *instruction_pointer) + && i < INTERPRETER_ITERATION_LIMIT + { *previous_ip = *instruction_pointer; let opcode = return_on_pagefault!(read_imm8()); @@ -1190,6 +1205,8 @@ unsafe fn jit_run_interpreted(phys_addr: i32) { dbg_assert!(*prefixes == 0); run_instruction(opcode | (*is_32 as i32) << 8); dbg_assert!(*prefixes == 0); + + i += 1; } } diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 1366107b..147e09e6 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -22,9 +22,9 @@ pub const CHECK_JIT_CACHE_ARRAY_INVARIANTS: bool = false; pub const JIT_MAX_ITERATIONS_PER_FUNCTION: u32 = 10000; -pub const JIT_ALWAYS_USE_LOOP_SAFETY: bool = false; +pub const JIT_ALWAYS_USE_LOOP_SAFETY: bool = true; -pub const JIT_THRESHOLD: u32 = 10 * 2500; +pub const JIT_THRESHOLD: u32 = 8 * 10000; const CONDITION_FUNCTIONS: [&str; 16] = [ "test_o", "test_no", "test_b", "test_nb", "test_z", "test_nz", "test_be", "test_nbe", "test_s", @@ -433,7 +433,7 @@ pub fn jit_find_cache_entry(phys_address: u32, state_flags: CachedStateFlags) -> cached_code::NONE } -fn record_entry_point(ctx: &mut JitState, phys_address: u32) { +pub fn record_entry_point(ctx: &mut JitState, phys_address: u32) { if is_near_end_of_page(phys_address) { return; } @@ -1174,11 +1174,11 @@ pub fn jit_increase_hotness_and_maybe_compile( phys_address: u32, cs_offset: u32, state_flags: CachedStateFlags, + hotness: u32, ) { - record_entry_point(ctx, phys_address); let page = Page::page_of(phys_address); let address_hash = jit_hot_hash_page(page) as usize; - ctx.hot_code_addresses[address_hash] += 1; + ctx.hot_code_addresses[address_hash] += hotness; if ctx.hot_code_addresses[address_hash] >= JIT_THRESHOLD { ctx.hot_code_addresses[address_hash] = 0; jit_analyze_and_generate(ctx, page, cs_offset, state_flags) diff --git a/tests/expect/tests/call.wast b/tests/expect/tests/call.wast index 7eb5478e..8346cada 100644 --- a/tests/expect/tests/call.wast +++ b/tests/expect/tests/call.wast @@ -13,15 +13,26 @@ (import "e" "safe_read32s_slow_jit" (func $e.safe_read32s_slow_jit (type $t5))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (set_local $p0 (get_local $p0)) + (set_local $l0 + (i32.const 10000)) (loop $L0 - (block $B1 - (block $B2 - (block $B3 - (block $B4 - (br_table $B4 $B3 $B2 $B1 + (set_local $l0 + (i32.add + (get_local $l0) + (i32.const -1))) + (if $I1 + (i32.eqz + (get_local $l0)) + (then + (return))) + (block $B2 + (block $B3 + (block $B4 + (block $B5 + (br_table $B5 $B4 $B3 $B2 (get_local $p0))) (i32.store (i32.const 560) @@ -33,47 +44,47 @@ (i32.load (i32.const 556)) (i32.const 5))) - (set_local $l0 + (set_local $l1 (i32.sub (i32.load (i32.const 556)) (i32.load (i32.const 740)))) - (set_local $l2 + (set_local $l3 (i32.add - (tee_local $l1 + (tee_local $l2 (i32.sub (i32.load (i32.const 20)) (i32.const 4))) (i32.load (i32.const 744)))) - (if $I5 + (if $I6 (i32.and (i32.eq (i32.and - (tee_local $l3 + (tee_local $l4 (i32.load offset=4194304 (i32.shl (i32.shr_u - (get_local $l2) + (get_local $l3) (i32.const 12)) (i32.const 2)))) (i32.const 4075)) (i32.const 1)) (i32.le_s (i32.and - (get_local $l2) + (get_local $l3) (i32.const 4095)) (i32.const 4092))) (then (i32.store offset=20221952 align=1 (i32.xor (i32.and - (get_local $l3) + (get_local $l4) (i32.const -4096)) - (get_local $l2)) - (get_local $l0))) + (get_local $l3)) + (get_local $l1))) (else (i32.store (i32.const 560) @@ -84,16 +95,16 @@ (i32.const -4096)) (i32.const 0))) (call $e.safe_write32_slow_jit - (get_local $l2) - (get_local $l0)) - (if $I6 + (get_local $l3) + (get_local $l1)) + (if $I7 (i32.load8_u (i32.const 540)) (then (return))))) (i32.store (i32.const 20) - (get_local $l1)) + (get_local $l2)) (i32.store (i32.const 556) (i32.add @@ -143,17 +154,17 @@ (i32.const 556) (i32.load (i32.const 740)) - (if $I7 (result i32) + (if $I8 (result i32) (i32.and (i32.eq (i32.and - (tee_local $l2 + (tee_local $l3 (i32.load offset=4194304 (i32.shl (i32.shr_u - (tee_local $l1 + (tee_local $l2 (i32.add - (tee_local $l0 + (tee_local $l1 (i32.load (i32.const 20))) (i32.load @@ -164,16 +175,16 @@ (i32.const 1)) (i32.le_s (i32.and - (get_local $l1) + (get_local $l2) (i32.const 4095)) (i32.const 4092))) (then (i32.load offset=20221952 align=1 (i32.xor (i32.and - (get_local $l2) + (get_local $l3) (i32.const -4096)) - (get_local $l1)))) + (get_local $l2)))) (else (i32.store (i32.const 560) @@ -184,8 +195,8 @@ (i32.const -4096)) (i32.const 7))) (call $e.safe_read32s_slow_jit - (get_local $l1)) - (if $I8 + (get_local $l2)) + (if $I9 (i32.load8_u (i32.const 540)) (then @@ -193,7 +204,7 @@ (i32.store (i32.const 20) (i32.add - (get_local $l0) + (get_local $l1) (i32.const 4))) (i32.add) (i32.store) diff --git a/tests/expect/tests/if.wast b/tests/expect/tests/if.wast index 8eb156bc..67938e35 100644 --- a/tests/expect/tests/if.wast +++ b/tests/expect/tests/if.wast @@ -14,15 +14,26 @@ (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) + (local $l0 i32) (local $l1 i32) (set_local $p0 (get_local $p0)) + (set_local $l0 + (i32.const 10000)) (loop $L0 - (block $B1 - (block $B2 - (block $B3 - (block $B4 - (br_table $B4 $B3 $B2 $B1 + (set_local $l0 + (i32.add + (get_local $l0) + (i32.const -1))) + (if $I1 + (i32.eqz + (get_local $l0)) + (then + (return))) + (block $B2 + (block $B3 + (block $B4 + (block $B5 + (br_table $B5 $B4 $B3 $B2 (get_local $p0))) (call $e.cmp32 (i32.load @@ -46,7 +57,7 @@ (i32.load (i32.const 664)) (i32.const 2))) - (if $I5 + (if $I6 (call $e.test_nle) (then (i32.store diff --git a/tests/expect/tests/indirect-call.wast b/tests/expect/tests/indirect-call.wast index 04d08758..9692ea76 100644 --- a/tests/expect/tests/indirect-call.wast +++ b/tests/expect/tests/indirect-call.wast @@ -11,14 +11,25 @@ (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) + (local $l0 i32) (local $l1 i32) (set_local $p0 (get_local $p0)) + (set_local $l0 + (i32.const 10000)) (loop $L0 - (block $B1 - (block $B2 - (block $B3 - (br_table $B3 $B2 $B1 + (set_local $l0 + (i32.add + (get_local $l0) + (i32.const -1))) + (if $I1 + (i32.eqz + (get_local $l0)) + (then + (return))) + (block $B2 + (block $B3 + (block $B4 + (br_table $B4 $B3 $B2 (get_local $p0))) (i32.store (i32.const 560) diff --git a/tests/expect/tests/mov16.wast b/tests/expect/tests/mov16.wast index 0a89a35a..86fd0d84 100644 --- a/tests/expect/tests/mov16.wast +++ b/tests/expect/tests/mov16.wast @@ -13,76 +13,40 @@ (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (set_local $p0 (get_local $p0)) + (set_local $l0 + (i32.const 10000)) (loop $L0 - (block $B1 - (block $B2 - (br_table $B2 $B1 + (set_local $l0 + (i32.add + (get_local $l0) + (i32.const -1))) + (if $I1 + (i32.eqz + (get_local $l0)) + (then + (return))) + (block $B2 + (block $B3 + (br_table $B3 $B2 (get_local $p0))) (call $e.instr16_B8 (i32.const 51966)) (i32.store16 (i32.const 8) - (if $I3 (result i32) + (if $I4 (result i32) (i32.and (i32.eq (i32.and - (tee_local $l1 - (i32.load offset=4194304 - (i32.shl - (i32.shr_u - (tee_local $l0 - (i32.add - (i32.const 32) - (call $e.get_seg - (i32.const 3)))) - (i32.const 12)) - (i32.const 2)))) - (i32.const 4041)) - (i32.const 1)) - (i32.le_s - (i32.and - (get_local $l0) - (i32.const 4095)) - (i32.const 4094))) - (then - (i32.load16_u offset=20221952 align=1 - (i32.xor - (i32.and - (get_local $l1) - (i32.const -4096)) - (get_local $l0)))) - (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 3))) - (call $e.safe_read16_slow_jit - (get_local $l0)) - (if $I4 - (i32.load8_u - (i32.const 540)) - (then - (return)))))) - (i32.store16 - (i32.const 12) - (if $I5 (result i32) - (i32.and - (i32.eq - (i32.and - (tee_local $l0 + (tee_local $l2 (i32.load offset=4194304 (i32.shl (i32.shr_u (tee_local $l1 (i32.add - (i32.const 36) + (i32.const 32) (call $e.get_seg (i32.const 3)))) (i32.const 12)) @@ -98,7 +62,7 @@ (i32.load16_u offset=20221952 align=1 (i32.xor (i32.and - (get_local $l0) + (get_local $l2) (i32.const -4096)) (get_local $l1)))) (else @@ -109,10 +73,57 @@ (i32.load (i32.const 556)) (i32.const -4096)) - (i32.const 7))) + (i32.const 3))) (call $e.safe_read16_slow_jit (get_local $l1)) - (if $I6 + (if $I5 + (i32.load8_u + (i32.const 540)) + (then + (return)))))) + (i32.store16 + (i32.const 12) + (if $I6 (result i32) + (i32.and + (i32.eq + (i32.and + (tee_local $l1 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (tee_local $l2 + (i32.add + (i32.const 36) + (call $e.get_seg + (i32.const 3)))) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4041)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l2) + (i32.const 4095)) + (i32.const 4094))) + (then + (i32.load16_u offset=20221952 align=1 + (i32.xor + (i32.and + (get_local $l1) + (i32.const -4096)) + (get_local $l2)))) + (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 7))) + (call $e.safe_read16_slow_jit + (get_local $l2)) + (if $I7 (i32.load8_u (i32.const 540)) (then @@ -123,7 +134,7 @@ (i32.store16 (i32.const 28) (i32.const 32)) - (set_local $l0 + (set_local $l1 (i32.add (i32.and (i32.add @@ -134,71 +145,14 @@ (i32.const 65535)) (call $e.get_seg (i32.const 3)))) - (set_local $l1 + (set_local $l2 (i32.load16_u (i32.const 4))) - (if $I7 + (if $I8 (i32.and (i32.eq (i32.and - (tee_local $l2 - (i32.load offset=4194304 - (i32.shl - (i32.shr_u - (get_local $l0) - (i32.const 12)) - (i32.const 2)))) - (i32.const 4075)) - (i32.const 1)) - (i32.le_s - (i32.and - (get_local $l0) - (i32.const 4095)) - (i32.const 4094))) - (then - (i32.store16 offset=20221952 align=1 - (i32.xor - (i32.and - (get_local $l2) - (i32.const -4096)) - (get_local $l0)) - (get_local $l1))) - (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 19))) - (call $e.safe_write16_slow_jit - (get_local $l0) - (get_local $l1)) - (if $I8 - (i32.load8_u - (i32.const 540)) - (then - (return))))) - (set_local $l1 - (i32.add - (i32.and - (i32.add - (i32.load16_u - (i32.const 16)) - (i32.load16_u - (i32.const 28))) - (i32.const 65535)) - (call $e.get_seg - (i32.const 3)))) - (set_local $l0 - (i32.load16_u - (i32.const 8))) - (if $I9 - (i32.and - (i32.eq - (i32.and - (tee_local $l2 + (tee_local $l3 (i32.load offset=4194304 (i32.shl (i32.shr_u @@ -216,10 +170,67 @@ (i32.store16 offset=20221952 align=1 (i32.xor (i32.and - (get_local $l2) + (get_local $l3) (i32.const -4096)) (get_local $l1)) - (get_local $l0))) + (get_local $l2))) + (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 19))) + (call $e.safe_write16_slow_jit + (get_local $l1) + (get_local $l2)) + (if $I9 + (i32.load8_u + (i32.const 540)) + (then + (return))))) + (set_local $l2 + (i32.add + (i32.and + (i32.add + (i32.load16_u + (i32.const 16)) + (i32.load16_u + (i32.const 28))) + (i32.const 65535)) + (call $e.get_seg + (i32.const 3)))) + (set_local $l1 + (i32.load16_u + (i32.const 8))) + (if $I10 + (i32.and + (i32.eq + (i32.and + (tee_local $l3 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (get_local $l2) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4075)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l2) + (i32.const 4095)) + (i32.const 4094))) + (then + (i32.store16 offset=20221952 align=1 + (i32.xor + (i32.and + (get_local $l3) + (i32.const -4096)) + (get_local $l2)) + (get_local $l1))) (else (i32.store (i32.const 560) @@ -230,9 +241,9 @@ (i32.const -4096)) (i32.const 21))) (call $e.safe_write16_slow_jit - (get_local $l1) - (get_local $l0)) - (if $I10 + (get_local $l2) + (get_local $l1)) + (if $I11 (i32.load8_u (i32.const 540)) (then diff --git a/tests/expect/tests/mov32-mem.wast b/tests/expect/tests/mov32-mem.wast index 61b1f892..87212d6a 100644 --- a/tests/expect/tests/mov32-mem.wast +++ b/tests/expect/tests/mov32-mem.wast @@ -12,15 +12,26 @@ (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (set_local $p0 (get_local $p0)) + (set_local $l0 + (i32.const 10000)) (loop $L0 - (block $B1 - (block $B2 - (br_table $B2 $B1 + (set_local $l0 + (i32.add + (get_local $l0) + (i32.const -1))) + (if $I1 + (i32.eqz + (get_local $l0)) + (then + (return))) + (block $B2 + (block $B3 + (br_table $B3 $B2 (get_local $p0))) - (set_local $l0 + (set_local $l1 (i32.add (i32.add (i32.load @@ -28,68 +39,14 @@ (i32.const 32)) (call $e.get_seg (i32.const 3)))) - (set_local $l1 + (set_local $l2 (i32.load (i32.const 4))) - (if $I3 + (if $I4 (i32.and (i32.eq (i32.and - (tee_local $l2 - (i32.load offset=4194304 - (i32.shl - (i32.shr_u - (get_local $l0) - (i32.const 12)) - (i32.const 2)))) - (i32.const 4075)) - (i32.const 1)) - (i32.le_s - (i32.and - (get_local $l0) - (i32.const 4095)) - (i32.const 4092))) - (then - (i32.store offset=20221952 align=1 - (i32.xor - (i32.and - (get_local $l2) - (i32.const -4096)) - (get_local $l0)) - (get_local $l1))) - (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 0))) - (call $e.safe_write32_slow_jit - (get_local $l0) - (get_local $l1)) - (if $I4 - (i32.load8_u - (i32.const 540)) - (then - (return))))) - (set_local $l1 - (i32.add - (i32.add - (i32.load - (i32.const 12)) - (i32.const 28)) - (call $e.get_seg - (i32.const 3)))) - (set_local $l0 - (i32.load - (i32.const 8))) - (if $I5 - (i32.and - (i32.eq - (i32.and - (tee_local $l2 + (tee_local $l3 (i32.load offset=4194304 (i32.shl (i32.shr_u @@ -107,10 +64,64 @@ (i32.store offset=20221952 align=1 (i32.xor (i32.and - (get_local $l2) + (get_local $l3) (i32.const -4096)) (get_local $l1)) - (get_local $l0))) + (get_local $l2))) + (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 0))) + (call $e.safe_write32_slow_jit + (get_local $l1) + (get_local $l2)) + (if $I5 + (i32.load8_u + (i32.const 540)) + (then + (return))))) + (set_local $l2 + (i32.add + (i32.add + (i32.load + (i32.const 12)) + (i32.const 28)) + (call $e.get_seg + (i32.const 3)))) + (set_local $l1 + (i32.load + (i32.const 8))) + (if $I6 + (i32.and + (i32.eq + (i32.and + (tee_local $l3 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (get_local $l2) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4075)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l2) + (i32.const 4095)) + (i32.const 4092))) + (then + (i32.store offset=20221952 align=1 + (i32.xor + (i32.and + (get_local $l3) + (i32.const -4096)) + (get_local $l2)) + (get_local $l1))) (else (i32.store (i32.const 560) @@ -121,70 +132,20 @@ (i32.const -4096)) (i32.const 6))) (call $e.safe_write32_slow_jit - (get_local $l1) - (get_local $l0)) - (if $I6 + (get_local $l2) + (get_local $l1)) + (if $I7 (i32.load8_u (i32.const 540)) (then (return))))) (i32.store (i32.const 28) - (if $I7 (result i32) + (if $I8 (result i32) (i32.and (i32.eq (i32.and - (tee_local $l1 - (i32.load offset=4194304 - (i32.shl - (i32.shr_u - (tee_local $l0 - (i32.add - (i32.add - (i32.load - (i32.const 16)) - (i32.const 28)) - (call $e.get_seg - (i32.const 3)))) - (i32.const 12)) - (i32.const 2)))) - (i32.const 4041)) - (i32.const 1)) - (i32.le_s - (i32.and - (get_local $l0) - (i32.const 4095)) - (i32.const 4092))) - (then - (i32.load offset=20221952 align=1 - (i32.xor - (i32.and - (get_local $l1) - (i32.const -4096)) - (get_local $l0)))) - (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 12))) - (call $e.safe_read32s_slow_jit - (get_local $l0)) - (if $I8 - (i32.load8_u - (i32.const 540)) - (then - (return)))))) - (i32.store - (i32.const 32) - (if $I9 (result i32) - (i32.and - (i32.eq - (i32.and - (tee_local $l0 + (tee_local $l2 (i32.load offset=4194304 (i32.shl (i32.shr_u @@ -192,8 +153,8 @@ (i32.add (i32.add (i32.load - (i32.const 12)) - (i32.const 32)) + (i32.const 16)) + (i32.const 28)) (call $e.get_seg (i32.const 3)))) (i32.const 12)) @@ -209,7 +170,7 @@ (i32.load offset=20221952 align=1 (i32.xor (i32.and - (get_local $l0) + (get_local $l2) (i32.const -4096)) (get_local $l1)))) (else @@ -220,10 +181,60 @@ (i32.load (i32.const 556)) (i32.const -4096)) - (i32.const 18))) + (i32.const 12))) (call $e.safe_read32s_slow_jit (get_local $l1)) - (if $I10 + (if $I9 + (i32.load8_u + (i32.const 540)) + (then + (return)))))) + (i32.store + (i32.const 32) + (if $I10 (result i32) + (i32.and + (i32.eq + (i32.and + (tee_local $l1 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (tee_local $l2 + (i32.add + (i32.add + (i32.load + (i32.const 12)) + (i32.const 32)) + (call $e.get_seg + (i32.const 3)))) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4041)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l2) + (i32.const 4095)) + (i32.const 4092))) + (then + (i32.load offset=20221952 align=1 + (i32.xor + (i32.and + (get_local $l1) + (i32.const -4096)) + (get_local $l2)))) + (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 18))) + (call $e.safe_read32s_slow_jit + (get_local $l2)) + (if $I11 (i32.load8_u (i32.const 540)) (then diff --git a/tests/expect/tests/mov32-reg.wast b/tests/expect/tests/mov32-reg.wast index 503218d1..d77c42a5 100644 --- a/tests/expect/tests/mov32-reg.wast +++ b/tests/expect/tests/mov32-reg.wast @@ -14,13 +14,24 @@ (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) + (local $l0 i32) (local $l1 i32) (set_local $p0 (get_local $p0)) + (set_local $l0 + (i32.const 10000)) (loop $L0 - (block $B1 - (block $B2 - (br_table $B2 $B1 + (set_local $l0 + (i32.add + (get_local $l0) + (i32.const -1))) + (if $I1 + (i32.eqz + (get_local $l0)) + (then + (return))) + (block $B2 + (block $B3 + (br_table $B3 $B2 (get_local $p0))) (call $e.instr32_B8 (i32.const -889270259)) diff --git a/tests/expect/tests/pop.wast b/tests/expect/tests/pop.wast index 386202d3..457be2bf 100644 --- a/tests/expect/tests/pop.wast +++ b/tests/expect/tests/pop.wast @@ -11,26 +11,37 @@ (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (set_local $p0 (get_local $p0)) + (set_local $l0 + (i32.const 10000)) (loop $L0 - (block $B1 - (block $B2 - (br_table $B2 $B1 + (set_local $l0 + (i32.add + (get_local $l0) + (i32.const -1))) + (if $I1 + (i32.eqz + (get_local $l0)) + (then + (return))) + (block $B2 + (block $B3 + (br_table $B3 $B2 (get_local $p0))) (i32.const 4) - (if $I3 (result i32) + (if $I4 (result i32) (i32.and (i32.eq (i32.and - (tee_local $l2 + (tee_local $l3 (i32.load offset=4194304 (i32.shl (i32.shr_u - (tee_local $l1 + (tee_local $l2 (i32.add - (tee_local $l0 + (tee_local $l1 (i32.load (i32.const 20))) (i32.load @@ -41,16 +52,16 @@ (i32.const 1)) (i32.le_s (i32.and - (get_local $l1) + (get_local $l2) (i32.const 4095)) (i32.const 4092))) (then (i32.load offset=20221952 align=1 (i32.xor (i32.and - (get_local $l2) + (get_local $l3) (i32.const -4096)) - (get_local $l1)))) + (get_local $l2)))) (else (i32.store (i32.const 560) @@ -61,8 +72,8 @@ (i32.const -4096)) (i32.const 0))) (call $e.safe_read32s_slow_jit - (get_local $l1)) - (if $I4 + (get_local $l2)) + (if $I5 (i32.load8_u (i32.const 540)) (then @@ -70,7 +81,7 @@ (i32.store (i32.const 20) (i32.add - (get_local $l0) + (get_local $l1) (i32.const 4))) (i32.store) (i32.store diff --git a/tests/expect/tests/push.wast b/tests/expect/tests/push.wast index 740fcedf..5908ff96 100644 --- a/tests/expect/tests/push.wast +++ b/tests/expect/tests/push.wast @@ -11,52 +11,63 @@ (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (set_local $p0 (get_local $p0)) + (set_local $l0 + (i32.const 10000)) (loop $L0 - (block $B1 - (block $B2 - (br_table $B2 $B1 + (set_local $l0 + (i32.add + (get_local $l0) + (i32.const -1))) + (if $I1 + (i32.eqz + (get_local $l0)) + (then + (return))) + (block $B2 + (block $B3 + (br_table $B3 $B2 (get_local $p0))) - (set_local $l0 + (set_local $l1 (i32.load (i32.const 4))) - (set_local $l2 + (set_local $l3 (i32.add - (tee_local $l1 + (tee_local $l2 (i32.sub (i32.load (i32.const 20)) (i32.const 4))) (i32.load (i32.const 744)))) - (if $I3 + (if $I4 (i32.and (i32.eq (i32.and - (tee_local $l3 + (tee_local $l4 (i32.load offset=4194304 (i32.shl (i32.shr_u - (get_local $l2) + (get_local $l3) (i32.const 12)) (i32.const 2)))) (i32.const 4075)) (i32.const 1)) (i32.le_s (i32.and - (get_local $l2) + (get_local $l3) (i32.const 4095)) (i32.const 4092))) (then (i32.store offset=20221952 align=1 (i32.xor (i32.and - (get_local $l3) + (get_local $l4) (i32.const -4096)) - (get_local $l2)) - (get_local $l0))) + (get_local $l3)) + (get_local $l1))) (else (i32.store (i32.const 560) @@ -67,16 +78,16 @@ (i32.const -4096)) (i32.const 0))) (call $e.safe_write32_slow_jit - (get_local $l2) - (get_local $l0)) - (if $I4 + (get_local $l3) + (get_local $l1)) + (if $I5 (i32.load8_u (i32.const 540)) (then (return))))) (i32.store (i32.const 20) - (get_local $l1)) + (get_local $l2)) (i32.store (i32.const 560) (i32.add diff --git a/tests/expect/tests/task_switch_test.wast b/tests/expect/tests/task_switch_test.wast index a7103237..b3ddc0e1 100644 --- a/tests/expect/tests/task_switch_test.wast +++ b/tests/expect/tests/task_switch_test.wast @@ -12,14 +12,25 @@ (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) + (local $l0 i32) (local $l1 i32) (set_local $p0 (get_local $p0)) + (set_local $l0 + (i32.const 10000)) (loop $L0 - (block $B1 - (block $B2 - (block $B3 - (br_table $B3 $B2 $B1 + (set_local $l0 + (i32.add + (get_local $l0) + (i32.const -1))) + (if $I1 + (i32.eqz + (get_local $l0)) + (then + (return))) + (block $B2 + (block $B3 + (block $B4 + (br_table $B4 $B3 $B2 (get_local $p0))) (i32.store (i32.const 560) @@ -31,7 +42,7 @@ (i32.load (i32.const 556)) (i32.const 2))) - (if $I4 + (if $I5 (i32.and (i32.load (i32.const 580)) diff --git a/tests/expect/tests/task_switch_test_sse.wast b/tests/expect/tests/task_switch_test_sse.wast index 6bb7f7b3..33d00123 100644 --- a/tests/expect/tests/task_switch_test_sse.wast +++ b/tests/expect/tests/task_switch_test_sse.wast @@ -12,14 +12,25 @@ (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) + (local $l0 i32) (local $l1 i32) (set_local $p0 (get_local $p0)) + (set_local $l0 + (i32.const 10000)) (loop $L0 - (block $B1 - (block $B2 - (block $B3 - (br_table $B3 $B2 $B1 + (set_local $l0 + (i32.add + (get_local $l0) + (i32.const -1))) + (if $I1 + (i32.eqz + (get_local $l0)) + (then + (return))) + (block $B2 + (block $B3 + (block $B4 + (br_table $B4 $B3 $B2 (get_local $p0))) (i32.store (i32.const 560) @@ -37,7 +48,7 @@ (i32.load (i32.const 648)) (i32.const 32))) - (if $I4 + (if $I5 (i32.and (i32.load (i32.const 580)) diff --git a/tests/expect/tests/while-do.wast b/tests/expect/tests/while-do.wast index 55e94418..1ac550ae 100644 --- a/tests/expect/tests/while-do.wast +++ b/tests/expect/tests/while-do.wast @@ -13,15 +13,26 @@ (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) + (local $l0 i32) (local $l1 i32) (set_local $p0 (get_local $p0)) + (set_local $l0 + (i32.const 10000)) (loop $L0 - (block $B1 - (block $B2 - (block $B3 - (block $B4 - (br_table $B4 $B3 $B2 $B1 + (set_local $l0 + (i32.add + (get_local $l0) + (i32.const -1))) + (if $I1 + (i32.eqz + (get_local $l0)) + (then + (return))) + (block $B2 + (block $B3 + (block $B4 + (block $B5 + (br_table $B5 $B4 $B3 $B2 (get_local $p0))) (call $e.cmp32 (i32.load @@ -45,7 +56,7 @@ (i32.load (i32.const 664)) (i32.const 2))) - (if $I5 + (if $I6 (call $e.test_z) (then (i32.store From 18b2a0883ae38393e843d31bfffacb331e6f43ca Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 18 Sep 2018 13:08:24 -0500 Subject: [PATCH 1367/2137] Remove same_page, use Page::page_of --- src/rust/cpu2/cpu.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 53f856ad..20da126c 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -28,6 +28,7 @@ use cpu2::misc_instr::{ adjust_stack_reg, get_stack_pointer, getaf, getcf, getof, getpf, getsf, getzf, pop16, pop32s, }; use cpu2::modrm::{resolve_modrm16, resolve_modrm32}; +use page::Page; use paging::OrPageFault; use profiler; use profiler::stat::*; @@ -349,8 +350,6 @@ pub fn track_jit_exit(phys_addr: u32) { } } -pub unsafe fn same_page(addr1: i32, addr2: i32) -> bool { return addr1 & !0xFFF == addr2 & !0xFFF; } - #[no_mangle] pub unsafe fn get_eflags() -> i32 { return *flags & !FLAGS_ALL @@ -1168,7 +1167,7 @@ unsafe fn jit_run_interpreted(phys_addr: i32) { let mut i = 0; while !jit_block_boundary - && same_page(*previous_ip, *instruction_pointer) + && Page::page_of(*previous_ip as u32) == Page::page_of(*instruction_pointer as u32) && i < INTERPRETER_ITERATION_LIMIT { *previous_ip = *instruction_pointer; From 5b2aa6977713d136964838ea4ffffb4aceccea8c Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 18 Sep 2018 13:13:23 -0500 Subject: [PATCH 1368/2137] Use CachedStateFlags type in former C code --- src/rust/c_api.rs | 8 ++++---- src/rust/cpu2/cpu.rs | 24 +++++++++++++----------- src/rust/jit.rs | 3 +-- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/rust/c_api.rs b/src/rust/c_api.rs index 3d7bb2bb..ea6e8420 100644 --- a/src/rust/c_api.rs +++ b/src/rust/c_api.rs @@ -25,11 +25,11 @@ pub fn rust_setup() { })); } -pub fn jit_find_cache_entry(phys_address: u32, state_flags: u32) -> u32 { +pub fn jit_find_cache_entry(phys_address: u32, state_flags: CachedStateFlags) -> u32 { let cached_code { wasm_table_index, initial_state, - } = ::jit::jit_find_cache_entry(phys_address, CachedStateFlags::of_u32(state_flags)); + } = ::jit::jit_find_cache_entry(phys_address, state_flags); wasm_table_index as u32 | (initial_state as u32) << 16 } @@ -55,14 +55,14 @@ pub fn codegen_finalize_finished( pub fn jit_increase_hotness_and_maybe_compile( phys_address: u32, cs_offset: u32, - state_flags: u32, + state_flags: CachedStateFlags, hotness: u32, ) { ::jit::jit_increase_hotness_and_maybe_compile( get_module(), phys_address, cs_offset, - CachedStateFlags::of_u32(state_flags), + state_flags, hotness, ) } diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 20da126c..14d3bbc6 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -32,6 +32,7 @@ use page::Page; use paging::OrPageFault; use profiler; use profiler::stat::*; +use state_flags::CachedStateFlags; /// The offset for our generated functions in the wasm table. Every index less than this is /// reserved for rustc's indirect functions @@ -51,7 +52,6 @@ pub union reg64 { pub f32_0: [f32; 2], pub f64_0: [f64; 1], } -pub type CachedStateFlags = u8; #[derive(Copy, Clone)] #[repr(C)] @@ -1068,8 +1068,8 @@ pub unsafe fn cycle_internal() { if true { *previous_ip = *instruction_pointer; let phys_addr: u32 = return_on_pagefault!(get_phys_eip()) as u32; - let state_flags: CachedStateFlags = pack_current_state_flags(); - let entry: u32 = ::c_api::jit_find_cache_entry(phys_addr, state_flags as u32); + let state_flags = pack_current_state_flags(); + let entry: u32 = ::c_api::jit_find_cache_entry(phys_addr, state_flags); if 0 != entry { profiler::stat_increment(S_RUN_FROM_CACHE); @@ -1093,7 +1093,7 @@ pub unsafe fn cycle_internal() { #[cfg(feature = "profiler")] { if CHECK_MISSED_ENTRY_POINTS { - ::jit::check_missed_entry_points(phys_addr, state_flags as u32); + ::jit::check_missed_entry_points(phys_addr, state_flags); } } @@ -1111,7 +1111,7 @@ pub unsafe fn cycle_internal() { ::c_api::jit_increase_hotness_and_maybe_compile( phys_addr, get_seg_cs() as u32, - state_flags as u32, + state_flags, *timestamp_counter - initial_tsc, ); @@ -1175,8 +1175,8 @@ unsafe fn jit_run_interpreted(phys_addr: i32) { if CHECK_MISSED_ENTRY_POINTS { let phys_addr = return_on_pagefault!(get_phys_eip()) as u32; - let state_flags: CachedStateFlags = pack_current_state_flags(); - let entry = ::c_api::jit_find_cache_entry(phys_addr, state_flags as u32); + let state_flags = pack_current_state_flags(); + let entry = ::c_api::jit_find_cache_entry(phys_addr, state_flags); if entry != 0 { profiler::stat_increment(S_RUN_INTERPRETED_MISSED_COMPILED_ENTRY_RUN_INTERPRETED); @@ -1211,10 +1211,12 @@ unsafe fn jit_run_interpreted(phys_addr: i32) { #[no_mangle] pub unsafe fn pack_current_state_flags() -> CachedStateFlags { - return ((*is_32 as i32) << 0 - | (*stack_size_32 as i32) << 1 - | ((*cpl as i32 == 3) as i32) << 2 - | (has_flat_segmentation() as i32) << 3) as CachedStateFlags; + return CachedStateFlags::of_u32( + (*is_32 as u32) << 0 + | (*stack_size_32 as u32) << 1 + | ((*cpl as i32 == 3) as u32) << 2 + | (has_flat_segmentation() as u32) << 3, + ); } #[no_mangle] diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 147e09e6..06867572 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -1389,8 +1389,7 @@ pub fn jit_get_op_len(ctx: &JitState) -> u32 { ctx.wasm_builder.get_op_len() } pub fn jit_get_op_ptr(ctx: &JitState) -> *const u8 { ctx.wasm_builder.get_op_ptr() } #[cfg(feature = "profiler")] -pub fn check_missed_entry_points(phys_address: u32, state_flags: u32) { - let state_flags = CachedStateFlags::of_u32(state_flags); +pub fn check_missed_entry_points(phys_address: u32, state_flags: CachedStateFlags) { let page = Page::page_of(phys_address); for i in page.to_address()..page.to_address() + 4096 { From 48e6843a87e226f7d06af186fc341ddae534f62e Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 18 Sep 2018 13:23:05 -0500 Subject: [PATCH 1369/2137] Remove S_ prefix from profiler --- src/rust/codegen.rs | 6 ++-- src/rust/cpu2/cpu.rs | 66 +++++++++++++++++------------------ src/rust/jit.rs | 34 +++++++++--------- src/rust/profiler.rs | 82 ++++++++++++++++++++++---------------------- 4 files changed, 94 insertions(+), 94 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 145a9326..6f9aa5af 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -276,7 +276,7 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { builder.instruction_body.if_i32(); if cfg!(feature = "profiler") { - gen_profiler_stat_increment(builder, profiler::stat::S_SAFE_READ_FAST); + gen_profiler_stat_increment(builder, profiler::stat::SAFE_READ_FAST); } builder.instruction_body.get_local(&entry_local); @@ -416,7 +416,7 @@ fn gen_safe_write( builder.instruction_body.if_void(); if cfg!(feature = "profiler") { - gen_profiler_stat_increment(builder, profiler::stat::S_SAFE_WRITE_FAST); + gen_profiler_stat_increment(builder, profiler::stat::SAFE_WRITE_FAST); } builder.instruction_body.get_local(&entry_local); @@ -862,7 +862,7 @@ pub fn gen_safe_read_write( ctx.builder.instruction_body.if_void(); if cfg!(feature = "profiler") { - gen_profiler_stat_increment(ctx.builder, profiler::stat::S_SAFE_WRITE_FAST); + gen_profiler_stat_increment(ctx.builder, profiler::stat::SAFE_WRITE_FAST); } ctx.builder.instruction_body.get_local(&entry_local); diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 14d3bbc6..228ff792 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -484,11 +484,11 @@ pub unsafe fn do_page_translation(addr: i32, for_writing: bool, user: bool) -> O } if *tlb_data.offset(page as isize) == 0 { if valid_tlb_entries_count == VALID_TLB_ENTRY_MAX { - profiler::stat_increment(S_TLB_FULL); + profiler::stat_increment(TLB_FULL); clear_tlb(); // also clear global entries if tlb is almost full after clearing non-global pages if valid_tlb_entries_count > VALID_TLB_ENTRY_MAX * 3 / 4 { - profiler::stat_increment(S_TLB_GLOBAL_FULL); + profiler::stat_increment(TLB_GLOBAL_FULL); full_clear_tlb(); } } @@ -551,7 +551,7 @@ pub unsafe fn do_page_translation(addr: i32, for_writing: bool, user: bool) -> O #[no_mangle] pub unsafe fn full_clear_tlb() { - profiler::stat_increment(S_FULL_CLEAR_TLB); + profiler::stat_increment(FULL_CLEAR_TLB); // clear tlb including global pages *last_virt_eip = -1; *last_virt_esp = -1; @@ -569,7 +569,7 @@ pub unsafe fn full_clear_tlb() { #[no_mangle] pub unsafe fn clear_tlb() { - profiler::stat_increment(S_CLEAR_TLB); + profiler::stat_increment(CLEAR_TLB); // clear tlb excluding global pages *last_virt_eip = -1; *last_virt_esp = -1; @@ -1064,7 +1064,7 @@ pub unsafe fn run_instruction0f_32(opcode: i32) { ::gen::interpreter0f_32::run(o #[no_mangle] pub unsafe fn cycle_internal() { - profiler::stat_increment(S_CYCLE_INTERNAL); + profiler::stat_increment(CYCLE_INTERNAL); if true { *previous_ip = *instruction_pointer; let phys_addr: u32 = return_on_pagefault!(get_phys_eip()) as u32; @@ -1072,7 +1072,7 @@ pub unsafe fn cycle_internal() { let entry: u32 = ::c_api::jit_find_cache_entry(phys_addr, state_flags); if 0 != entry { - profiler::stat_increment(S_RUN_FROM_CACHE); + profiler::stat_increment(RUN_FROM_CACHE); let initial_tsc = *timestamp_counter; let wasm_table_index = (entry & 0xFFFF) as u16; let initial_state = (entry >> 16) as u16; @@ -1083,7 +1083,7 @@ pub unsafe fn cycle_internal() { ); dbg_assert!(*prefixes == 0); profiler::stat_increment_by( - S_RUN_FROM_CACHE_STEPS, + RUN_FROM_CACHE_STEPS, (*timestamp_counter - initial_tsc) as u64, ); } @@ -1116,7 +1116,7 @@ pub unsafe fn cycle_internal() { ); profiler::stat_increment_by( - S_RUN_INTERPRETED_STEPS, + RUN_INTERPRETED_STEPS, (*timestamp_counter - initial_tsc) as u64, ); }; @@ -1144,7 +1144,7 @@ pub unsafe fn get_phys_eip() -> OrPageFault { } unsafe fn jit_run_interpreted(phys_addr: i32) { - profiler::stat_increment(S_RUN_INTERPRETED); + profiler::stat_increment(RUN_INTERPRETED); dbg_assert!(!in_mapped_range(phys_addr as u32)); if cfg!(debug_assertions) { @@ -1179,7 +1179,7 @@ unsafe fn jit_run_interpreted(phys_addr: i32) { let entry = ::c_api::jit_find_cache_entry(phys_addr, state_flags); if entry != 0 { - profiler::stat_increment(S_RUN_INTERPRETED_MISSED_COMPILED_ENTRY_RUN_INTERPRETED); + profiler::stat_increment(RUN_INTERPRETED_MISSED_COMPILED_ENTRY_RUN_INTERPRETED); //dbg_log!( // "missed entry point at {:x} prev_opcode={:x} opcode={:x}", // phys_addr, @@ -1242,7 +1242,7 @@ pub unsafe fn segment_prefix_op(seg: i32) { #[no_mangle] pub unsafe fn do_many_cycles_native() { - profiler::stat_increment(S_DO_MANY_CYCLES); + profiler::stat_increment(DO_MANY_CYCLES); let initial_timestamp_counter: u32 = *timestamp_counter; while (*timestamp_counter).wrapping_sub(initial_timestamp_counter) < LOOP_COUNTER as u32 && !*in_hlt @@ -1392,7 +1392,7 @@ pub unsafe fn safe_read32s(address: i32) -> OrPageFault { let info_bits: i32 = entry & 0xFFF & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE; if info_bits == TLB_VALID && address & 0xFFF <= 0x1000 - 4 { if false { - profiler::stat_increment(S_SAFE_READ_FAST); + profiler::stat_increment(SAFE_READ_FAST); } // - not in memory mapped area // - can be accessed from any cpl @@ -1403,16 +1403,16 @@ pub unsafe fn safe_read32s(address: i32) -> OrPageFault { else { if false { if address & 0xFFF > 0x1000 - 4 { - profiler::stat_increment(S_SAFE_READ_SLOW_PAGE_CROSSED); + profiler::stat_increment(SAFE_READ_SLOW_PAGE_CROSSED); } else if info_bits & TLB_VALID == 0 { - profiler::stat_increment(S_SAFE_READ_SLOW_NOT_VALID); + profiler::stat_increment(SAFE_READ_SLOW_NOT_VALID); } else if 0 != info_bits & TLB_NO_USER { - profiler::stat_increment(S_SAFE_READ_SLOW_NOT_USER); + profiler::stat_increment(SAFE_READ_SLOW_NOT_USER); } else if 0 != info_bits & TLB_IN_MAPPED_RANGE { - profiler::stat_increment(S_SAFE_READ_SLOW_IN_MAPPED_RANGE); + profiler::stat_increment(SAFE_READ_SLOW_IN_MAPPED_RANGE); } else { dbg_assert!(false); @@ -1426,16 +1426,16 @@ pub unsafe fn safe_read32s(address: i32) -> OrPageFault { #[cfg(feature = "profiler")] pub fn report_safe_read_jit_slow(address: u32, entry: i32) { if entry & TLB_VALID == 0 { - profiler::stat_increment(S_SAFE_READ_SLOW_NOT_VALID); + profiler::stat_increment(SAFE_READ_SLOW_NOT_VALID); } else if entry & TLB_IN_MAPPED_RANGE != 0 { - profiler::stat_increment(S_SAFE_READ_SLOW_IN_MAPPED_RANGE); + profiler::stat_increment(SAFE_READ_SLOW_IN_MAPPED_RANGE); } else if entry & TLB_NO_USER != 0 { - profiler::stat_increment(S_SAFE_READ_SLOW_NOT_USER); + profiler::stat_increment(SAFE_READ_SLOW_NOT_USER); } else if address & 0xFFF > 0x1000 - 4 { - profiler::stat_increment(S_SAFE_READ_SLOW_PAGE_CROSSED); + profiler::stat_increment(SAFE_READ_SLOW_PAGE_CROSSED); } else { dbg_log!("Unexpected entry bit: {:x} (read at {:x})", entry, address); @@ -1447,22 +1447,22 @@ pub fn report_safe_read_jit_slow(address: u32, entry: i32) { #[cfg(feature = "profiler")] pub fn report_safe_write_jit_slow(address: u32, entry: i32) { if entry & TLB_VALID == 0 { - profiler::stat_increment(S_SAFE_WRITE_SLOW_NOT_VALID); + profiler::stat_increment(SAFE_WRITE_SLOW_NOT_VALID); } else if entry & TLB_IN_MAPPED_RANGE != 0 { - profiler::stat_increment(S_SAFE_WRITE_SLOW_IN_MAPPED_RANGE); + profiler::stat_increment(SAFE_WRITE_SLOW_IN_MAPPED_RANGE); } else if entry & TLB_HAS_CODE != 0 { - profiler::stat_increment(S_SAFE_WRITE_SLOW_HAS_CODE); + profiler::stat_increment(SAFE_WRITE_SLOW_HAS_CODE); } else if entry & TLB_READONLY != 0 { - profiler::stat_increment(S_SAFE_WRITE_SLOW_READ_ONLY); + profiler::stat_increment(SAFE_WRITE_SLOW_READ_ONLY); } else if entry & TLB_NO_USER != 0 { - profiler::stat_increment(S_SAFE_WRITE_SLOW_NOT_USER); + profiler::stat_increment(SAFE_WRITE_SLOW_NOT_USER); } else if address & 0xFFF > 0x1000 - 4 { - profiler::stat_increment(S_SAFE_WRITE_SLOW_PAGE_CROSSED); + profiler::stat_increment(SAFE_WRITE_SLOW_PAGE_CROSSED); } else { dbg_assert!(false); @@ -1589,7 +1589,7 @@ pub unsafe fn safe_write32(address: i32, value: i32) -> OrPageFault<()> { entry & 0xFFF & !TLB_GLOBAL & !if *cpl as i32 == 3 { 0 } else { TLB_NO_USER }; if info_bits == TLB_VALID && address & 0xFFF <= 0x1000 - 4 { if false { - profiler::stat_increment(S_SAFE_WRITE_FAST); + profiler::stat_increment(SAFE_WRITE_FAST); } // - allowed to write in user-mode // - not in memory mapped area @@ -1602,22 +1602,22 @@ pub unsafe fn safe_write32(address: i32, value: i32) -> OrPageFault<()> { else { if false { if address & 0xFFF > 0x1000 - 4 { - profiler::stat_increment(S_SAFE_WRITE_SLOW_PAGE_CROSSED); + profiler::stat_increment(SAFE_WRITE_SLOW_PAGE_CROSSED); } else if info_bits & TLB_VALID == 0 { - profiler::stat_increment(S_SAFE_WRITE_SLOW_NOT_VALID); + profiler::stat_increment(SAFE_WRITE_SLOW_NOT_VALID); } else if 0 != info_bits & TLB_NO_USER { - profiler::stat_increment(S_SAFE_WRITE_SLOW_NOT_USER); + profiler::stat_increment(SAFE_WRITE_SLOW_NOT_USER); } else if 0 != info_bits & TLB_IN_MAPPED_RANGE { - profiler::stat_increment(S_SAFE_WRITE_SLOW_IN_MAPPED_RANGE); + profiler::stat_increment(SAFE_WRITE_SLOW_IN_MAPPED_RANGE); } else if 0 != info_bits & TLB_READONLY { - profiler::stat_increment(S_SAFE_WRITE_SLOW_READ_ONLY); + profiler::stat_increment(SAFE_WRITE_SLOW_READ_ONLY); } else if 0 != info_bits & TLB_HAS_CODE { - profiler::stat_increment(S_SAFE_WRITE_SLOW_HAS_CODE); + profiler::stat_increment(SAFE_WRITE_SLOW_HAS_CODE); } else { dbg_assert!(false); diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 06867572..a26d7865 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -392,7 +392,7 @@ fn is_near_end_of_page(address: u32) -> bool { address & 0xFFF >= 0x1000 - MAX_I pub fn jit_find_cache_entry(phys_address: u32, state_flags: CachedStateFlags) -> cached_code { if is_near_end_of_page(phys_address) { - profiler::stat_increment(stat::S_RUN_INTERPRETED_NEAR_END_OF_PAGE); + profiler::stat_increment(stat::RUN_INTERPRETED_NEAR_END_OF_PAGE); } let mut run_interpreted_reason = None; @@ -403,10 +403,10 @@ pub fn jit_find_cache_entry(phys_address: u32, state_flags: CachedStateFlags) -> if entry.start_addr == phys_address { if entry.pending { - run_interpreted_reason = Some(stat::S_RUN_INTERPRETED_PENDING) + run_interpreted_reason = Some(stat::RUN_INTERPRETED_PENDING) } if entry.state_flags != state_flags { - run_interpreted_reason = Some(stat::S_RUN_INTERPRETED_DIFFERENT_STATE) + run_interpreted_reason = Some(stat::RUN_INTERPRETED_DIFFERENT_STATE) } } @@ -470,7 +470,7 @@ fn jit_find_basic_blocks( } if is_near_end_of_page(to_visit) { // Empty basic block, don't insert - profiler::stat_increment(stat::S_COMPILE_CUT_OFF_AT_END_OF_PAGE); + profiler::stat_increment(stat::COMPILE_CUT_OFF_AT_END_OF_PAGE); continue; } @@ -613,7 +613,7 @@ fn jit_find_basic_blocks( if is_near_end_of_page(current_address) { current_block.last_instruction_addr = addr_before_instruction; current_block.end_addr = current_address; - profiler::stat_increment(stat::S_COMPILE_CUT_OFF_AT_END_OF_PAGE); + profiler::stat_increment(stat::COMPILE_CUT_OFF_AT_END_OF_PAGE); break; } } @@ -689,7 +689,7 @@ fn create_cache_entry(ctx: &mut JitState, entry: jit_cache_array::Entry) { let found_entry_index = match found_entry_index { Some(i) => i, None => { - profiler::stat_increment(stat::S_CACHE_MISMATCH); + profiler::stat_increment(stat::CACHE_MISMATCH); // no free slots, overwrite the first one let found_entry_index = phys_addr & jit_cache_array::MASK; @@ -701,7 +701,7 @@ fn create_cache_entry(ctx: &mut JitState, entry: jit_cache_array::Entry) { dbg_assert!(old_entry.wasm_table_index != 0); if old_entry.wasm_table_index == entry.wasm_table_index { - profiler::stat_increment(stat::S_INVALIDATE_SINGLE_ENTRY_CACHE_FULL); + profiler::stat_increment(stat::INVALIDATE_SINGLE_ENTRY_CACHE_FULL); dbg_assert!(old_entry.pending); dbg_assert!(Page::page_of(old_entry.start_addr) == Page::page_of(phys_addr)); @@ -718,7 +718,7 @@ fn create_cache_entry(ctx: &mut JitState, entry: jit_cache_array::Entry) { old_entry.start_addr = 0; } else { - profiler::stat_increment(stat::S_INVALIDATE_MODULE_CACHE_FULL); + profiler::stat_increment(stat::INVALIDATE_MODULE_CACHE_FULL); let old_wasm_table_index = old_entry.wasm_table_index; let old_page = Page::page_of(old_entry.start_addr); @@ -760,7 +760,7 @@ fn jit_analyze_and_generate( cs_offset: u32, state_flags: CachedStateFlags, ) { - profiler::stat_increment(stat::S_COMPILE); + profiler::stat_increment(stat::COMPILE); let entry_points = ctx.entry_points.remove(&page); let cpu = CpuContext { @@ -801,7 +801,7 @@ fn jit_analyze_and_generate( let mut entry_point_count = 0; for (i, block) in basic_blocks.iter().enumerate() { - profiler::stat_increment(stat::S_COMPILE_BASIC_BLOCK); + profiler::stat_increment(stat::COMPILE_BASIC_BLOCK); if block.is_entry_block && block.addr != block.end_addr { dbg_assert!(block.addr != 0); @@ -830,7 +830,7 @@ fn jit_analyze_and_generate( create_cache_entry(ctx, entry); entry_point_count += 1; - profiler::stat_increment(stat::S_COMPILE_ENTRY_POINT); + profiler::stat_increment(stat::COMPILE_ENTRY_POINT); } } @@ -854,7 +854,7 @@ fn jit_analyze_and_generate( state_flags, ); - profiler::stat_increment(stat::S_COMPILE_SUCCESS); + profiler::stat_increment(stat::COMPILE_SUCCESS); } else { //dbg_log("No basic blocks, not generating code"); @@ -949,7 +949,7 @@ fn jit_generate_module( builder.instruction_body.loop_void(); if let Some(gen_local_iteration_counter) = gen_local_iteration_counter.as_ref() { - profiler::stat_increment(stat::S_COMPILE_WITH_LOOP_SAFETY); + profiler::stat_increment(stat::COMPILE_WITH_LOOP_SAFETY); // decrement max_iterations builder @@ -1259,10 +1259,10 @@ pub fn jit_dirty_page(ctx: &mut JitState, page: Page) { let mut index_to_pending_free = HashSet::new(); jit_cache_array::set_page_index(page, None); - profiler::stat_increment(stat::S_INVALIDATE_PAGE); + profiler::stat_increment(stat::INVALIDATE_PAGE); loop { - profiler::stat_increment(stat::S_INVALIDATE_CACHE_ENTRY); + profiler::stat_increment(stat::INVALIDATE_CACHE_ENTRY); let entry = jit_cache_array::get_mut(cache_array_index); let wasm_table_index = entry.wasm_table_index; @@ -1295,7 +1295,7 @@ pub fn jit_dirty_page(ctx: &mut JitState, page: Page) { } profiler::stat_increment_by( - stat::S_INVALIDATE_MODULE, + stat::INVALIDATE_MODULE, index_to_pending_free.len() as u64 + index_to_free.len() as u64, ); @@ -1403,7 +1403,7 @@ pub fn check_missed_entry_points(phys_address: u32, state_flags: CachedStateFlag && phys_address >= entry.start_addr && phys_address < entry.start_addr + entry.len { - profiler::stat_increment(stat::S_RUN_INTERPRETED_MISSED_COMPILED_ENTRY_LOOKUP); + profiler::stat_increment(stat::RUN_INTERPRETED_MISSED_COMPILED_ENTRY_LOOKUP); let last_jump_type = unsafe { cpu2::cpu::debug_last_jump.name() }; let last_jump_addr = unsafe { cpu2::cpu::debug_last_jump.phys_address() }.unwrap_or(0); diff --git a/src/rust/profiler.rs b/src/rust/profiler.rs index 9dd9e894..e1515694 100644 --- a/src/rust/profiler.rs +++ b/src/rust/profiler.rs @@ -1,53 +1,53 @@ #[allow(dead_code, non_camel_case_types)] pub enum stat { - S_COMPILE, - S_COMPILE_SUCCESS, - S_COMPILE_CUT_OFF_AT_END_OF_PAGE, - S_COMPILE_WITH_LOOP_SAFETY, - S_COMPILE_BASIC_BLOCK, - S_COMPILE_ENTRY_POINT, - S_CACHE_MISMATCH, + COMPILE, + COMPILE_SUCCESS, + COMPILE_CUT_OFF_AT_END_OF_PAGE, + COMPILE_WITH_LOOP_SAFETY, + COMPILE_BASIC_BLOCK, + COMPILE_ENTRY_POINT, + CACHE_MISMATCH, - S_RUN_INTERPRETED, - S_RUN_INTERPRETED_PENDING, - S_RUN_INTERPRETED_NEAR_END_OF_PAGE, - S_RUN_INTERPRETED_DIFFERENT_STATE, - S_RUN_INTERPRETED_MISSED_COMPILED_ENTRY_RUN_INTERPRETED, - S_RUN_INTERPRETED_MISSED_COMPILED_ENTRY_LOOKUP, - S_RUN_INTERPRETED_STEPS, + RUN_INTERPRETED, + RUN_INTERPRETED_PENDING, + RUN_INTERPRETED_NEAR_END_OF_PAGE, + RUN_INTERPRETED_DIFFERENT_STATE, + RUN_INTERPRETED_MISSED_COMPILED_ENTRY_RUN_INTERPRETED, + RUN_INTERPRETED_MISSED_COMPILED_ENTRY_LOOKUP, + RUN_INTERPRETED_STEPS, - S_RUN_FROM_CACHE, - S_RUN_FROM_CACHE_STEPS, + RUN_FROM_CACHE, + RUN_FROM_CACHE_STEPS, - S_SAFE_READ_FAST, - S_SAFE_READ_SLOW_PAGE_CROSSED, - S_SAFE_READ_SLOW_NOT_VALID, - S_SAFE_READ_SLOW_NOT_USER, - S_SAFE_READ_SLOW_IN_MAPPED_RANGE, + SAFE_READ_FAST, + SAFE_READ_SLOW_PAGE_CROSSED, + SAFE_READ_SLOW_NOT_VALID, + SAFE_READ_SLOW_NOT_USER, + SAFE_READ_SLOW_IN_MAPPED_RANGE, - S_SAFE_WRITE_FAST, - S_SAFE_WRITE_SLOW_PAGE_CROSSED, - S_SAFE_WRITE_SLOW_NOT_VALID, - S_SAFE_WRITE_SLOW_NOT_USER, - S_SAFE_WRITE_SLOW_IN_MAPPED_RANGE, - S_SAFE_WRITE_SLOW_READ_ONLY, - S_SAFE_WRITE_SLOW_HAS_CODE, + SAFE_WRITE_FAST, + SAFE_WRITE_SLOW_PAGE_CROSSED, + SAFE_WRITE_SLOW_NOT_VALID, + SAFE_WRITE_SLOW_NOT_USER, + SAFE_WRITE_SLOW_IN_MAPPED_RANGE, + SAFE_WRITE_SLOW_READ_ONLY, + SAFE_WRITE_SLOW_HAS_CODE, - S_DO_RUN, - S_DO_MANY_CYCLES, - S_CYCLE_INTERNAL, + DO_RUN, + DO_MANY_CYCLES, + CYCLE_INTERNAL, - S_INVALIDATE_PAGE, - S_INVALIDATE_MODULE, - S_INVALIDATE_CACHE_ENTRY, + INVALIDATE_PAGE, + INVALIDATE_MODULE, + INVALIDATE_CACHE_ENTRY, - S_INVALIDATE_MODULE_CACHE_FULL, - S_INVALIDATE_SINGLE_ENTRY_CACHE_FULL, + INVALIDATE_MODULE_CACHE_FULL, + INVALIDATE_SINGLE_ENTRY_CACHE_FULL, - S_CLEAR_TLB, - S_FULL_CLEAR_TLB, - S_TLB_FULL, - S_TLB_GLOBAL_FULL, + CLEAR_TLB, + FULL_CLEAR_TLB, + TLB_FULL, + TLB_GLOBAL_FULL, } #[no_mangle] @@ -81,4 +81,4 @@ pub fn profiler_stat_get(stat: stat) -> f64 { } #[no_mangle] -pub fn profiler_stat_increment_do_run() { stat_increment(stat::S_DO_RUN); } +pub fn profiler_stat_increment_do_run() { stat_increment(stat::DO_RUN); } From 4ef09445e165e8c130441de72798ea445bb5b7e1 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Sat, 15 Sep 2018 18:37:49 +0530 Subject: [PATCH 1370/2137] cpu: Port call_interrupt_vector to Rust --- src/browser/starter.js | 7 +- src/cpu.js | 337 +-------------------------------- src/native/js_imports.h | 1 - src/rust/cpu2/cpu.rs | 338 +++++++++++++++++++++++++++++++++- src/rust/cpu2/instructions.rs | 2 - 5 files changed, 342 insertions(+), 343 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 797df426..27e4e1f2 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -177,9 +177,6 @@ function V86Starter(options) return dest; }, - "call_interrupt_vector": function(interrupt_nr, is_software_int, has_error_code, error_code) { - cpu.call_interrupt_vector(interrupt_nr, is_software_int, !!has_error_code, error_code); - }, "far_jump": function(eip, selector, is_call) { return cpu.far_jump(eip, selector, !!is_call); }, "far_return": function(eip, selector, stack_adjust) { return cpu.far_return(eip, selector, stack_adjust); }, "iret16": function() { return cpu.iret16(); }, @@ -258,6 +255,10 @@ function V86Starter(options) "ceil": Math.ceil, "fabs": Math.abs, "abs": Math.abs, + + "do_task_switch": (selector, error_code) => cpu.do_task_switch(selector, error_code), + "get_tss_stack_addr": (dpl) => cpu.get_tss_stack_addr(dpl), + "switch_cs_real_mode": (selector) => cpu.switch_cs_real_mode(selector), }; const wasm_globals = { diff --git a/src/cpu.js b/src/cpu.js index 12067bb4..892b4de1 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -305,6 +305,8 @@ CPU.prototype.wasm_patch = function(wm) this.trigger_np = get_import("trigger_np"); this.trigger_ss = get_import("trigger_ss"); + this.call_interrupt_vector = get_import("call_interrupt_vector"); + this.do_many_cycles_native = get_import("do_many_cycles_native"); this.cycle_internal = get_import("cycle_internal"); @@ -1452,341 +1454,6 @@ CPU.prototype.jit_clear_cache = function() } }; -CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, has_error_code, error_code) -{ - //dbg_log("int " + h(interrupt_nr, 2) + " (" + (is_software_int ? "soft" : "hard") + "ware)", LOG_CPU); - CPU_LOG_VERBOSE && this.debug.dump_state("int " + h(interrupt_nr) + " start" + - " (" + (is_software_int ? "soft" : "hard") + "ware)"); - CPU_LOG_VERBOSE && this.debug.dump_regs(); - - this.debug.debug_interrupt(interrupt_nr); - - dbg_assert(typeof has_error_code === "boolean"); - dbg_assert(has_error_code === false || typeof error_code === "number"); - - // we have to leave hlt_loop at some point, this is a - // good place to do it - //this.in_hlt && dbg_log("Leave HLT loop", LOG_CPU); - this.in_hlt[0] = +false; - - if(this.protected_mode[0]) - { - if(this.vm86_mode() && (this.cr[4] & CR4_VME)) - { - throw this.debug.unimpl("VME"); - } - - if(this.vm86_mode() && is_software_int && this.getiopl() < 3) - { - dbg_log("call_interrupt_vector #GP. vm86 && software int && iopl < 3", LOG_CPU); - dbg_trace(LOG_CPU); - this.trigger_gp_non_raising(0); - return; - } - - if((interrupt_nr << 3 | 7) > this.idtr_size[0]) - { - dbg_log(interrupt_nr, LOG_CPU); - dbg_trace(LOG_CPU); - throw this.debug.unimpl("#GP handler"); - } - - var addr = this.idtr_offset[0] + (interrupt_nr << 3) | 0; - dbg_assert((addr & 0xFFF) < 0xFF8); - - if(this.cr[0] & CR0_PG) - { - addr = this.translate_address_system_read(addr); - } - - var base = this.read16(addr) | this.read16(addr + 6 | 0) << 16; - var selector = this.read16(addr + 2 | 0); - var access = this.read8(addr + 5 | 0); - var dpl = access >> 5 & 3; - var type = access & 31; - - if((access & 0x80) === 0) - { - // present bit not set - throw this.debug.unimpl("#NP handler"); - } - - if(is_software_int && dpl < this.cpl[0]) - { - dbg_log("#gp software interrupt (" + h(interrupt_nr, 2) + ") and dpl < cpl", LOG_CPU); - dbg_trace(LOG_CPU); - this.trigger_gp_non_raising(interrupt_nr << 3 | 2); - return; - } - - if(type === 5) - { - // task gate - dbg_log("interrupt to task gate: int=" + h(interrupt_nr, 2) + " sel=" + h(selector, 4) + " dpl=" + dpl, LOG_CPU); - dbg_trace(LOG_CPU); - - this.do_task_switch(selector, error_code); - CPU_LOG_VERBOSE && this.debug.dump_state("int end"); - return; - } - - if((type & ~1 & ~8) !== 6) - { - // invalid type - dbg_trace(LOG_CPU); - dbg_log("invalid type: " + h(type)); - dbg_log(h(addr) + " " + h(base >>> 0) + " " + h(selector)); - throw this.debug.unimpl("#GP handler"); - } - - var is_trap = (type & 1) === 1; - var is_16 = (type & 8) === 0; - - var info = this.lookup_segment_selector(selector); - - dbg_assert((base >>> 0) <= info.effective_limit); - dbg_assert(info.is_valid); - - if(info.is_null) - { - dbg_log("is null"); - throw this.debug.unimpl("#GP handler"); - } - if(!info.is_executable || info.dpl > this.cpl[0]) - { - dbg_log("not exec"); - throw this.debug.unimpl("#GP handler"); - } - if(!info.is_present) - { - // kvm-unit-test - dbg_log("not present"); - this.trigger_np(interrupt_nr << 3 | 2); - return; - } - - var old_flags = this.get_eflags(); - - //dbg_log("interrupt " + h(interrupt_nr, 2) + " (" + (is_software_int ? "soft" : "hard") + "ware) from cpl=" + this.cpl[0] + " vm=" + (this.flags[0] & flag_vm) + " cs:eip=" + h(this.sreg[reg_cs], 4) + ":" + h(this.get_real_eip(), 8) + " to cpl=" - - if(!info.dc_bit && info.dpl < this.cpl[0]) - { - // inter privilege level interrupt - // interrupt from vm86 mode - - //dbg_log("Inter privilege interrupt gate=" + h(selector, 4) + ":" + h(base >>> 0, 8) + " trap=" + is_trap + " 16bit=" + is_16, LOG_CPU); - //this.debug.dump_regs(); - var tss_stack_addr = this.get_tss_stack_addr(info.dpl); - - if(this.tss_size_32[0]) - { - var new_esp = this.read32s(tss_stack_addr); - var new_ss = this.read16(tss_stack_addr + 4 | 0); - } - else - { - var new_esp = this.read16(tss_stack_addr); - var new_ss = this.read16(tss_stack_addr + 2 | 0); - } - var ss_info = this.lookup_segment_selector(new_ss); - - // Disabled: Incorrect handling of direction bit - // See http://css.csail.mit.edu/6.858/2014/readings/i386/s06_03.htm - //if(!((new_esp >>> 0) <= ss_info.effective_limit)) - // debugger; - //dbg_assert((new_esp >>> 0) <= ss_info.effective_limit); - dbg_assert(ss_info.is_valid && !ss_info.is_system && ss_info.is_writable); - - if(ss_info.is_null) - { - throw this.debug.unimpl("#TS handler"); - } - if(ss_info.rpl !== info.dpl) // xxx: 0 in v86 mode - { - throw this.debug.unimpl("#TS handler"); - } - if(ss_info.dpl !== info.dpl || !ss_info.rw_bit) - { - throw this.debug.unimpl("#TS handler"); - } - if(!ss_info.is_present) - { - throw this.debug.unimpl("#TS handler"); - } - - var old_esp = this.reg32s[reg_esp]; - var old_ss = this.sreg[reg_ss]; - - if(old_flags & flag_vm) - { - //dbg_log("return from vm86 mode"); - //this.debug.dump_regs(); - dbg_assert(info.dpl === 0, "switch to non-0 dpl from vm86 mode"); - } - - var stack_space = (is_16 ? 2 : 4) * (5 + (has_error_code === true) + 4 * ((old_flags & flag_vm) === flag_vm)); - var new_stack_pointer = ss_info.base + (ss_info.size ? new_esp - stack_space : (new_esp - stack_space & 0xFFFF)); - - // XXX: with new cpl or with cpl 0? - this.translate_address_system_write(new_stack_pointer); - this.translate_address_system_write(ss_info.base + new_esp - 1); - - // no exceptions below - - this.cpl[0] = info.dpl; - this.cpl_changed(); - - this.update_cs_size(info.size); - - this.flags[0] &= ~flag_vm & ~flag_rf; - - if(!this.switch_seg(reg_ss, new_ss)) dbg_assert(false); // XXX - this.set_stack_reg(new_esp); - - if(old_flags & flag_vm) - { - if(is_16) - { - dbg_assert(false); - } - else - { - this.push32(this.sreg[reg_gs]); - this.push32(this.sreg[reg_fs]); - this.push32(this.sreg[reg_ds]); - this.push32(this.sreg[reg_es]); - } - } - - if(is_16) - { - this.push16(old_ss); - this.push16(old_esp); - } - else - { - this.push32(old_ss); - this.push32(old_esp); - } - } - else if(info.dc_bit || info.dpl === this.cpl[0]) - { - // intra privilege level interrupt - - //dbg_log("Intra privilege interrupt gate=" + h(selector, 4) + ":" + h(base >>> 0, 8) + - // " trap=" + is_trap + " 16bit=" + is_16 + - // " cpl=" + this.cpl[0] + " dpl=" + info.dpl + " conforming=" + +info.dc_bit, LOG_CPU); - //this.debug.dump_regs_short(); - - if(this.flags[0] & flag_vm) - { - dbg_assert(false, "check error code"); - this.trigger_gp_non_raising(selector & ~3); - return; - } - - var stack_space = (is_16 ? 2 : 4) * (3 + (has_error_code === true)); - - // XXX: with current cpl or with cpl 0? - if(!this.writable_or_pagefault(this.get_stack_pointer(-stack_space), stack_space)) - { - return; - } - - // no exceptions below - } - else - { - throw this.debug.unimpl("#GP handler"); - } - - if(is_16) - { - this.push16(old_flags); - this.push16(this.sreg[reg_cs]); - this.push16(this.get_real_eip()); - - if(has_error_code === true) - { - this.push16(error_code); - } - - base &= 0xFFFF; - } - else - { - this.push32(old_flags); - this.push32(this.sreg[reg_cs]); - this.push32(this.get_real_eip()); - - if(has_error_code === true) - { - this.push32(error_code); - } - } - - if(old_flags & flag_vm) - { - if( - !this.switch_seg(reg_gs, 0) || - !this.switch_seg(reg_fs, 0) || - !this.switch_seg(reg_ds, 0) || - !this.switch_seg(reg_es, 0) - ) - { - // can't fail - dbg_assert(false); - } - } - - this.sreg[reg_cs] = selector & ~3 | this.cpl[0]; - dbg_assert((this.sreg[reg_cs] & 3) === this.cpl[0]); - - this.update_cs_size(info.size); - - this.segment_limits[reg_cs] = info.effective_limit; - this.segment_offsets[reg_cs] = info.base; - - this.instruction_pointer[0] = this.get_seg(reg_cs) + base | 0; - - this.flags[0] &= ~flag_nt & ~flag_vm & ~flag_rf & ~flag_trap; - - if(!is_trap) - { - // clear int flag for interrupt gates - this.flags[0] &= ~flag_interrupt; - } - else - { - if((this.flags[0] & flag_interrupt) && !(old_flags & flag_interrupt)) - { - this.handle_irqs(); - } - } - } - else - { - // call 4 byte cs:ip interrupt vector from ivt at cpu.memory 0 - - var index = interrupt_nr << 2; - var new_ip = this.read16(index); - var new_cs = this.read16(index + 2 | 0); - - // push flags, cs:ip - this.push16(this.get_eflags()); - this.push16(this.sreg[reg_cs]); - this.push16(this.get_real_eip()); - - this.flags[0] &= ~flag_interrupt; - - this.switch_cs_real_mode(new_cs); - this.instruction_pointer[0] = this.get_seg(reg_cs) + new_ip | 0; - } - - //dbg_log("int to:", LOG_CPU); - CPU_LOG_VERBOSE && this.debug.dump_state("int end"); -}; - CPU.prototype.iret16 = function() { this.iret(true); diff --git a/src/native/js_imports.h b/src/native/js_imports.h index 689a59df..39beae76 100644 --- a/src/native/js_imports.h +++ b/src/native/js_imports.h @@ -54,6 +54,5 @@ extern void io_port_write16(int32_t, int32_t); extern void io_port_write32(int32_t, int32_t); extern int32_t convert_f64_to_i32(double_t); extern void jit_clear_func(int32_t index); -extern void call_interrupt_vector(int32_t interrupt_nr, bool is_software_int, bool has_error_code, int32_t error_code); extern void throw_cpu_exception(void); extern double_t microtick(void); diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 228ff792..1d6df82b 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1,11 +1,15 @@ #![allow(non_upper_case_globals)] extern "C" { - #[no_mangle] - fn call_interrupt_vector(interrupt: i32, is_software: bool, has_error: bool, error: i32); #[no_mangle] fn cpu_exception_hook(interrupt: i32) -> bool; #[no_mangle] + fn do_task_switch(selector: i32, error_code: i32); + #[no_mangle] + fn get_tss_stack_addr(dpl: u8) -> u32; + #[no_mangle] + fn switch_cs_real_mode(selector: i32); + #[no_mangle] fn dbg_trace(); //#[no_mangle] //fn logop(addr: i32, op: i32); @@ -26,6 +30,7 @@ use cpu2::memory::{ }; use cpu2::misc_instr::{ adjust_stack_reg, get_stack_pointer, getaf, getcf, getof, getpf, getsf, getzf, pop16, pop32s, + push16, push32, }; use cpu2::modrm::{resolve_modrm16, resolve_modrm32}; use page::Page; @@ -339,6 +344,335 @@ impl SegmentDescriptor { } } +pub struct InterruptDescriptor { + raw: u64, +} + +impl InterruptDescriptor { + pub fn offset(&self) -> i32 { (self.raw & 0xffff | self.raw >> 32 & 0xffff0000) as i32 } + pub fn selector(&self) -> u16 { (self.raw >> 16 & 0xffff) as u16 } + pub fn access_byte(&self) -> u8 { (self.raw >> 40 & 0xff) as u8 } + pub fn dpl(&self) -> u8 { (self.access_byte() >> 5 & 3) as u8 } + pub fn gate_type(&self) -> u8 { self.access_byte() & 31 } + pub fn is_32(&self) -> bool { self.access_byte() & 8 == 8 } + pub fn is_present(&self) -> bool { self.access_byte() & 0x80 == 0x80 } + + const TASK_GATE: u8 = 0b101; + const TRAP_GATE: u8 = 0b111; +} + +#[no_mangle] +pub unsafe fn call_interrupt_vector( + interrupt_nr: i32, + is_software_int: bool, + has_error_code: bool, + error_code: i32, +) { + // we have to leave hlt_loop at some point, this is a + // good place to do it + *in_hlt = false; + + if *protected_mode { + if vm86_mode() && *cr.offset(4) & CR4_VME != 0 { + panic!("Unimplemented: VME"); + } + + if vm86_mode() && is_software_int && getiopl() < 3 { + dbg_log!("call_interrupt_vector #GP. vm86 && software int && iopl < 3"); + dbg_trace(); + trigger_gp_non_raising(0); + return; + } + + if interrupt_nr << 3 | 7 > *idtr_size { + dbg_log!("interrupt_nr={:x} idtr_size={:x}", interrupt_nr, *idtr_size); + dbg_trace(); + panic!("Unimplemented: #GP handler"); + } + + let descriptor_address = return_on_pagefault!(translate_address_system_read( + *idtr_offset + (interrupt_nr << 3) + )); + + let descriptor = InterruptDescriptor { + raw: read64s(descriptor_address) as u64, + }; + + let mut offset = descriptor.offset(); + let selector = descriptor.selector() as i32; + let dpl = descriptor.dpl(); + let gate_type = descriptor.gate_type(); + + if !descriptor.is_present() { + // present bit not set + panic!("Unimplemented: #NP handler"); + } + + if is_software_int && dpl < *cpl { + dbg_log!("#gp software interrupt ({:x}) and dpl < cpl", interrupt_nr); + dbg_trace(); + trigger_gp_non_raising(interrupt_nr << 3 | 2); + return; + } + + if gate_type == InterruptDescriptor::TASK_GATE { + // task gate + dbg_log!( + "interrupt to task gate: int={:x} sel={:x} dpl={}", + interrupt_nr, + selector, + dpl + ); + dbg_trace(); + + do_task_switch(selector, error_code); + return; + } + + if gate_type & !1 & !8 != 6 { + // invalid gate_type + dbg_trace(); + dbg_log!("invalid gate_type: 0b{:b}", gate_type); + dbg_log!( + "addr={:x} offset={:x} selector={:x}", + descriptor_address, + offset, + selector + ); + panic!("Unimplemented: #GP handler"); + } + + let is_trap = gate_type & 7 == InterruptDescriptor::TRAP_GATE; + let is_16 = !descriptor.is_32(); + + let cs_segment_descriptor = match return_on_pagefault!(lookup_segment_selector(selector)) { + Ok((desc, _)) => desc, + Err(selector_unusable) => match selector_unusable { + SelectorNullOrInvalid::IsNull => { + dbg_log!("is null"); + panic!("Unimplemented: #GP handler"); + }, + SelectorNullOrInvalid::IsInvalid => { + dbg_log!("is invalid"); + panic!("Unimplemented: #GP handler (error code)"); + }, + }, + }; + + dbg_assert!(offset as u32 <= cs_segment_descriptor.effective_limit()); + + if !cs_segment_descriptor.is_executable() || cs_segment_descriptor.dpl() > *cpl { + dbg_log!("not exec"); + panic!("Unimplemented: #GP handler"); + } + if !cs_segment_descriptor.is_present() { + // kvm-unit-test + dbg_log!("not present"); + trigger_np(interrupt_nr << 3 | 2); + return; + } + + let old_flags = get_eflags(); + + if !cs_segment_descriptor.is_dc() && cs_segment_descriptor.dpl() < *cpl { + // inter privilege level interrupt + // interrupt from vm86 mode + + if old_flags & FLAG_VM != 0 && cs_segment_descriptor.dpl() == 0 { + panic!("Unimplemented: #GP handler for non-0 cs segment dpl when in vm86 mode"); + } + + let tss_stack_addr = get_tss_stack_addr(cs_segment_descriptor.dpl()); + + let new_esp = read32s(tss_stack_addr); + let new_ss = read16(tss_stack_addr + if *tss_size_32 { 4 } else { 2 }); + let (ss_segment_descriptor, ss_segment_selector) = + match return_on_pagefault!(lookup_segment_selector(new_ss)) { + Ok((desc, sel)) => (desc, sel), + Err(_) => { + panic!("Unimplemented: #TS handler"); + }, + }; + + // Disabled: Incorrect handling of direction bit + // See http://css.csail.mit.edu/6.858/2014/readings/i386/s06_03.htm + //if !((new_esp >>> 0) <= ss_segment_descriptor.effective_limit()) + // debugger; + //dbg_assert!((new_esp >>> 0) <= ss_segment_descriptor.effective_limit()); + dbg_assert!(!ss_segment_descriptor.is_system() && ss_segment_descriptor.is_writable()); + + if ss_segment_selector.rpl() != cs_segment_descriptor.dpl() { + panic!("Unimplemented: #TS handler"); + } + if ss_segment_descriptor.dpl() != cs_segment_descriptor.dpl() + || !ss_segment_descriptor.is_rw() + { + panic!("Unimplemented: #TS handler"); + } + if !ss_segment_descriptor.is_present() { + panic!("Unimplemented: #TS handler"); + } + + let old_esp = *reg32s.offset(ESP as isize); + let old_ss = *sreg.offset(SS as isize) as i32; + + let error_code_space = if has_error_code == true { 1 } else { 0 }; + let vm86_space = if (old_flags & FLAG_VM) == FLAG_VM { + 1 + } + else { + 0 + }; + let bytes_per_arg = if is_16 { 2 } else { 4 }; + + let stack_space = bytes_per_arg * (5 + error_code_space + 4 * vm86_space); + let new_stack_pointer = ss_segment_descriptor.base() + if ss_segment_descriptor.is_32() + { + new_esp - stack_space + } + else { + new_esp - stack_space & 0xFFFF + }; + + return_on_pagefault!(translate_address_system_write(new_stack_pointer)); + return_on_pagefault!(translate_address_system_write( + ss_segment_descriptor.base() + new_esp - 1 + )); + + *cpl = cs_segment_descriptor.dpl(); + cpl_changed(); + + update_cs_size(cs_segment_descriptor.is_32()); + + *flags &= !FLAG_VM & !FLAG_RF; + + if !switch_seg(SS, new_ss) { + dbg_assert!(false); + } // XXX + set_stack_reg(new_esp); + + if old_flags & FLAG_VM != 0 { + if is_16 { + dbg_assert!(false); + } + else { + push32(*sreg.offset(GS as isize) as i32).unwrap(); + push32(*sreg.offset(FS as isize) as i32).unwrap(); + push32(*sreg.offset(DS as isize) as i32).unwrap(); + push32(*sreg.offset(ES as isize) as i32).unwrap(); + } + } + + if is_16 { + push16(old_ss).unwrap(); + push16(old_esp).unwrap(); + } + else { + push32(old_ss).unwrap(); + push32(old_esp).unwrap(); + } + } + else if cs_segment_descriptor.is_dc() || cs_segment_descriptor.dpl() == *cpl { + // intra privilege level interrupt + + //dbg_log!("Intra privilege interrupt gate=" + h(selector, 4) + ":" + h(offset >>> 0, 8) + + // " trap=" + is_trap + " 16bit=" + is_16 + + // " cpl=" + *cpl + " dpl=" + segment_descriptor.dpl() + " conforming=" + +segment_descriptor.dc_bit(), ); + //debug.dump_regs_short(); + + if *flags & FLAG_VM != 0 { + dbg_assert!(false, "check error code"); + trigger_gp_non_raising(selector & !3); + return; + } + + let bytes_per_arg = if is_16 { 2 } else { 4 }; + let error_code_space = if has_error_code == true { 1 } else { 0 }; + + let stack_space = bytes_per_arg * (3 + error_code_space); + + // XXX: with current cpl or with cpl 0? + return_on_pagefault!(writable_or_pagefault( + get_stack_pointer(-stack_space), + stack_space + )); + + // no exceptions below + } + else { + panic!("Unimplemented: #GP handler"); + } + + if is_16 { + push16(old_flags).unwrap(); + push16(*sreg.offset(CS as isize) as i32).unwrap(); + push16(get_real_eip()).unwrap(); + + if has_error_code == true { + push16(error_code).unwrap(); + } + + offset &= 0xFFFF; + } + else { + push32(old_flags).unwrap(); + push32(*sreg.offset(CS as isize) as i32).unwrap(); + push32(get_real_eip()).unwrap(); + + if has_error_code == true { + push32(error_code).unwrap(); + } + } + + if old_flags & FLAG_VM != 0 { + if !switch_seg(GS, 0) || !switch_seg(FS, 0) || !switch_seg(DS, 0) || !switch_seg(ES, 0) + { + // can't fail + dbg_assert!(false); + } + } + + *sreg.offset(CS as isize) = (selector as u16) & !3 | *cpl as u16; + dbg_assert!((*sreg.offset(CS as isize) & 3) == *cpl as u16); + + update_cs_size(cs_segment_descriptor.is_32()); + + *segment_limits.offset(CS as isize) = cs_segment_descriptor.effective_limit(); + *segment_offsets.offset(CS as isize) = cs_segment_descriptor.base(); + + *instruction_pointer = get_seg(CS) + offset; + + *flags &= !FLAG_NT & !FLAG_VM & !FLAG_RF & !FLAG_TRAP; + + if !is_trap { + // clear int flag for interrupt gates + *flags &= !FLAG_INTERRUPT; + } + else { + if *flags & FLAG_INTERRUPT != 0 && old_flags & FLAG_INTERRUPT == 0 { + handle_irqs(); + } + } + } + else { + // call 4 byte cs:ip interrupt vector from ivt at cpu.memory 0 + + let index = (interrupt_nr << 2) as u32; + let new_ip = read16(index); + let new_cs = read16(index + 2); + + // push flags, cs:ip + push16(get_eflags()).unwrap(); + push16(*sreg.offset(CS as isize) as i32).unwrap(); + push16(get_real_eip()).unwrap(); + + *flags &= !FLAG_INTERRUPT; + + switch_cs_real_mode(new_cs); + *instruction_pointer = get_seg(CS) + new_ip; + } +} + //pub fn call_indirect1(f: fn(u16), x: u16) { f(x); } pub unsafe fn after_block_boundary() { jit_block_boundary = true; } diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index 47fe4554..a513f3ca 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -17,8 +17,6 @@ extern "C" { #[no_mangle] fn far_return(eip: i32, selector: i32, stack_adjust: i32); #[no_mangle] - fn call_interrupt_vector(interrupt: i32, is_software: bool, has_error: bool, error: i32); - #[no_mangle] fn iret16(); #[no_mangle] fn iret32(); From aa789d4129104a15230473cc8c74bcde1731425a Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 18 Sep 2018 18:24:08 +0530 Subject: [PATCH 1371/2137] cpu: Follow call_interrupt_vector's specification more closely --- src/rust/cpu2/cpu.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 1d6df82b..6da59106 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -223,6 +223,7 @@ pub const TLB_NO_USER: i32 = 1 << 2; pub const TLB_IN_MAPPED_RANGE: i32 = 1 << 3; pub const TLB_GLOBAL: i32 = 1 << 4; pub const TLB_HAS_CODE: i32 = 1 << 5; +pub const IVT_SIZE: u32 = 0x400; pub const CPU_EXCEPTION_DE: i32 = 0; pub const CPU_EXCEPTION_DB: i32 = 1; pub const CPU_EXCEPTION_NMI: i32 = 2; @@ -551,6 +552,7 @@ pub unsafe fn call_interrupt_vector( } // XXX set_stack_reg(new_esp); + // XXX: #SS if stack would cross stack limit if old_flags & FLAG_VM != 0 { if is_16 { dbg_assert!(false); @@ -603,6 +605,7 @@ pub unsafe fn call_interrupt_vector( panic!("Unimplemented: #GP handler"); } + // XXX: #SS if stack would cross stack limit if is_16 { push16(old_flags).unwrap(); push16(*sreg.offset(CS as isize) as i32).unwrap(); @@ -661,12 +664,19 @@ pub unsafe fn call_interrupt_vector( let new_ip = read16(index); let new_cs = read16(index + 2); + dbg_assert!( + index | 3 <= IVT_SIZE, + "Unimplemented: #GP for interrupt number out of IVT bounds" + ); + + // XXX: #SS if stack would cross stack limit + // push flags, cs:ip push16(get_eflags()).unwrap(); push16(*sreg.offset(CS as isize) as i32).unwrap(); push16(get_real_eip()).unwrap(); - *flags &= !FLAG_INTERRUPT; + *flags &= !FLAG_INTERRUPT & !FLAG_AC & !FLAG_TRAP; switch_cs_real_mode(new_cs); *instruction_pointer = get_seg(CS) + new_ip; From 8ba3de34c13fbba0f523538924a34d6524f49538 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Wed, 19 Sep 2018 15:34:57 +0530 Subject: [PATCH 1372/2137] cpu: Check for reserved zeros in interrupt descriptor This lets us make our gate type validity check more readable --- src/rust/cpu2/cpu.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 6da59106..0c297529 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -354,11 +354,12 @@ impl InterruptDescriptor { pub fn selector(&self) -> u16 { (self.raw >> 16 & 0xffff) as u16 } pub fn access_byte(&self) -> u8 { (self.raw >> 40 & 0xff) as u8 } pub fn dpl(&self) -> u8 { (self.access_byte() >> 5 & 3) as u8 } - pub fn gate_type(&self) -> u8 { self.access_byte() & 31 } + pub fn gate_type(&self) -> u8 { self.access_byte() & 7 } pub fn is_32(&self) -> bool { self.access_byte() & 8 == 8 } pub fn is_present(&self) -> bool { self.access_byte() & 0x80 == 0x80 } const TASK_GATE: u8 = 0b101; + const INTERRUPT_GATE: u8 = 0b110; const TRAP_GATE: u8 = 0b111; } @@ -430,7 +431,12 @@ pub unsafe fn call_interrupt_vector( return; } - if gate_type & !1 & !8 != 6 { + let is_trap = gate_type == InterruptDescriptor::TRAP_GATE; + let is_valid_type = is_trap || gate_type == InterruptDescriptor::INTERRUPT_GATE; + let reserved_zeroes_are_valid = + descriptor.raw >> 36 & 7 == 0 && descriptor.access_byte() & 16 == 0; + + if !is_valid_type || !reserved_zeroes_are_valid { // invalid gate_type dbg_trace(); dbg_log!("invalid gate_type: 0b{:b}", gate_type); @@ -443,7 +449,6 @@ pub unsafe fn call_interrupt_vector( panic!("Unimplemented: #GP handler"); } - let is_trap = gate_type & 7 == InterruptDescriptor::TRAP_GATE; let is_16 = !descriptor.is_32(); let cs_segment_descriptor = match return_on_pagefault!(lookup_segment_selector(selector)) { From ae70cb7e4febc45ebed829b37763390bb7a1b2b1 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 20 Sep 2018 00:30:32 +0530 Subject: [PATCH 1373/2137] cpu: Minor refactor in call_interrupt_vector --- src/browser/starter.js | 1 + src/rust/cpu2/cpu.rs | 16 +++++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 27e4e1f2..23b44442 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -257,6 +257,7 @@ function V86Starter(options) "abs": Math.abs, "do_task_switch": (selector, error_code) => cpu.do_task_switch(selector, error_code), + // XXX: Port to Rust "get_tss_stack_addr": (dpl) => cpu.get_tss_stack_addr(dpl), "switch_cs_real_mode": (selector) => cpu.switch_cs_real_mode(selector), }; diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 0c297529..138ab556 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -438,14 +438,17 @@ pub unsafe fn call_interrupt_vector( if !is_valid_type || !reserved_zeroes_are_valid { // invalid gate_type - dbg_trace(); - dbg_log!("invalid gate_type: 0b{:b}", gate_type); + dbg_log!( + "gate type invalid or reserved 0s violated. gate_type=0b{:b}", + gate_type + ); dbg_log!( "addr={:x} offset={:x} selector={:x}", descriptor_address, offset, selector ); + dbg_trace(); panic!("Unimplemented: #GP handler"); } @@ -524,14 +527,14 @@ pub unsafe fn call_interrupt_vector( let error_code_space = if has_error_code == true { 1 } else { 0 }; let vm86_space = if (old_flags & FLAG_VM) == FLAG_VM { - 1 + 4 } else { 0 }; let bytes_per_arg = if is_16 { 2 } else { 4 }; - let stack_space = bytes_per_arg * (5 + error_code_space + 4 * vm86_space); + let stack_space = bytes_per_arg * (5 + error_code_space + vm86_space); let new_stack_pointer = ss_segment_descriptor.base() + if ss_segment_descriptor.is_32() { new_esp - stack_space @@ -545,6 +548,7 @@ pub unsafe fn call_interrupt_vector( ss_segment_descriptor.base() + new_esp - 1 )); + // no exceptions below *cpl = cs_segment_descriptor.dpl(); cpl_changed(); @@ -553,11 +557,13 @@ pub unsafe fn call_interrupt_vector( *flags &= !FLAG_VM & !FLAG_RF; if !switch_seg(SS, new_ss) { + // XXX dbg_assert!(false); - } // XXX + } set_stack_reg(new_esp); // XXX: #SS if stack would cross stack limit + if old_flags & FLAG_VM != 0 { if is_16 { dbg_assert!(false); From f7f0f64f84123bf99ab261528291aad9844fd272 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 20 Sep 2018 00:39:54 +0530 Subject: [PATCH 1374/2137] cpu: Use of_ functions to init descriptor and selector structs --- src/rust/cpu2/cpu.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 138ab556..a656b097 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -298,6 +298,7 @@ pub struct SegmentSelector { } impl SegmentSelector { + pub fn of_u16(raw: u16) -> SegmentSelector { SegmentSelector { raw } } pub fn rpl(&self) -> u8 { (self.raw & 3) as u8 } pub fn is_gdt(&self) -> bool { (self.raw & 4) == 0 } pub fn descriptor_offset(&self) -> u16 { (self.raw & !7) as u16 } @@ -317,6 +318,7 @@ pub struct SegmentDescriptor { } impl SegmentDescriptor { + pub fn of_u64(raw: u64) -> SegmentDescriptor { SegmentDescriptor { raw } } pub fn base(&self) -> i32 { ((self.raw >> 16) & 0xffff | (self.raw & 0xff_00000000) >> 16 | (self.raw >> 56 << 24)) as i32 @@ -350,6 +352,7 @@ pub struct InterruptDescriptor { } impl InterruptDescriptor { + pub fn of_u64(raw: u64) -> InterruptDescriptor { InterruptDescriptor { raw } } pub fn offset(&self) -> i32 { (self.raw & 0xffff | self.raw >> 32 & 0xffff0000) as i32 } pub fn selector(&self) -> u16 { (self.raw >> 16 & 0xffff) as u16 } pub fn access_byte(&self) -> u8 { (self.raw >> 40 & 0xff) as u8 } @@ -396,9 +399,7 @@ pub unsafe fn call_interrupt_vector( *idtr_offset + (interrupt_nr << 3) )); - let descriptor = InterruptDescriptor { - raw: read64s(descriptor_address) as u64, - }; + let descriptor = InterruptDescriptor::of_u64(read64s(descriptor_address) as u64); let mut offset = descriptor.offset(); let selector = descriptor.selector() as i32; @@ -1119,9 +1120,7 @@ pub unsafe fn is_asize_32() -> bool { pub unsafe fn lookup_segment_selector( selector: i32, ) -> OrPageFault> { - let selector = SegmentSelector { - raw: selector as u16, - }; + let selector = SegmentSelector::of_u16(selector as u16); if selector.is_null() { return Ok(Err(SelectorNullOrInvalid::IsNull)); @@ -1144,9 +1143,7 @@ pub unsafe fn lookup_segment_selector( let descriptor_address = translate_address_system_read(selector.descriptor_offset() as i32 + table_offset as i32)?; - let descriptor = SegmentDescriptor { - raw: read64s(descriptor_address) as u64, - }; + let descriptor = SegmentDescriptor::of_u64(read64s(descriptor_address) as u64); Ok(Ok((descriptor, selector))) } From ce090cfb4e7136d0cc177b307f8db7c0097cd89d Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 20 Sep 2018 00:52:14 +0530 Subject: [PATCH 1375/2137] cpu: Inline into InterruptDescriptor and clean call_interrupt_vector --- src/rust/cpu2/cpu.rs | 53 ++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index a656b097..b7784d33 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -360,6 +360,9 @@ impl InterruptDescriptor { pub fn gate_type(&self) -> u8 { self.access_byte() & 7 } pub fn is_32(&self) -> bool { self.access_byte() & 8 == 8 } pub fn is_present(&self) -> bool { self.access_byte() & 0x80 == 0x80 } + pub fn reserved_zeros_are_valid(&self) -> bool { + self.raw >> 36 & 7 == 0 && self.access_byte() & 16 == 0 + } const TASK_GATE: u8 = 0b101; const INTERRUPT_GATE: u8 = 0b110; @@ -432,12 +435,10 @@ pub unsafe fn call_interrupt_vector( return; } - let is_trap = gate_type == InterruptDescriptor::TRAP_GATE; - let is_valid_type = is_trap || gate_type == InterruptDescriptor::INTERRUPT_GATE; - let reserved_zeroes_are_valid = - descriptor.raw >> 36 & 7 == 0 && descriptor.access_byte() & 16 == 0; + let is_valid_type = gate_type == InterruptDescriptor::TRAP_GATE + || gate_type == InterruptDescriptor::INTERRUPT_GATE; - if !is_valid_type || !reserved_zeroes_are_valid { + if !is_valid_type || !descriptor.reserved_zeros_are_valid() { // invalid gate_type dbg_log!( "gate type invalid or reserved 0s violated. gate_type=0b{:b}", @@ -453,8 +454,6 @@ pub unsafe fn call_interrupt_vector( panic!("Unimplemented: #GP handler"); } - let is_16 = !descriptor.is_32(); - let cs_segment_descriptor = match return_on_pagefault!(lookup_segment_selector(selector)) { Ok((desc, _)) => desc, Err(selector_unusable) => match selector_unusable { @@ -533,7 +532,7 @@ pub unsafe fn call_interrupt_vector( else { 0 }; - let bytes_per_arg = if is_16 { 2 } else { 4 }; + let bytes_per_arg = if descriptor.is_32() { 4 } else { 2 }; let stack_space = bytes_per_arg * (5 + error_code_space + vm86_space); let new_stack_pointer = ss_segment_descriptor.base() + if ss_segment_descriptor.is_32() @@ -566,7 +565,7 @@ pub unsafe fn call_interrupt_vector( // XXX: #SS if stack would cross stack limit if old_flags & FLAG_VM != 0 { - if is_16 { + if !descriptor.is_32() { dbg_assert!(false); } else { @@ -577,20 +576,20 @@ pub unsafe fn call_interrupt_vector( } } - if is_16 { - push16(old_ss).unwrap(); - push16(old_esp).unwrap(); - } - else { + if descriptor.is_32() { push32(old_ss).unwrap(); push32(old_esp).unwrap(); } + else { + push16(old_ss).unwrap(); + push16(old_esp).unwrap(); + } } else if cs_segment_descriptor.is_dc() || cs_segment_descriptor.dpl() == *cpl { // intra privilege level interrupt //dbg_log!("Intra privilege interrupt gate=" + h(selector, 4) + ":" + h(offset >>> 0, 8) + - // " trap=" + is_trap + " 16bit=" + is_16 + + // " gate_type=" + gate_type + " 16bit=" + descriptor.is_32() + // " cpl=" + *cpl + " dpl=" + segment_descriptor.dpl() + " conforming=" + +segment_descriptor.dc_bit(), ); //debug.dump_regs_short(); @@ -600,7 +599,7 @@ pub unsafe fn call_interrupt_vector( return; } - let bytes_per_arg = if is_16 { 2 } else { 4 }; + let bytes_per_arg = if descriptor.is_32() { 4 } else { 2 }; let error_code_space = if has_error_code == true { 1 } else { 0 }; let stack_space = bytes_per_arg * (3 + error_code_space); @@ -618,7 +617,16 @@ pub unsafe fn call_interrupt_vector( } // XXX: #SS if stack would cross stack limit - if is_16 { + if descriptor.is_32() { + push32(old_flags).unwrap(); + push32(*sreg.offset(CS as isize) as i32).unwrap(); + push32(get_real_eip()).unwrap(); + + if has_error_code == true { + push32(error_code).unwrap(); + } + } + else { push16(old_flags).unwrap(); push16(*sreg.offset(CS as isize) as i32).unwrap(); push16(get_real_eip()).unwrap(); @@ -629,15 +637,6 @@ pub unsafe fn call_interrupt_vector( offset &= 0xFFFF; } - else { - push32(old_flags).unwrap(); - push32(*sreg.offset(CS as isize) as i32).unwrap(); - push32(get_real_eip()).unwrap(); - - if has_error_code == true { - push32(error_code).unwrap(); - } - } if old_flags & FLAG_VM != 0 { if !switch_seg(GS, 0) || !switch_seg(FS, 0) || !switch_seg(DS, 0) || !switch_seg(ES, 0) @@ -659,7 +658,7 @@ pub unsafe fn call_interrupt_vector( *flags &= !FLAG_NT & !FLAG_VM & !FLAG_RF & !FLAG_TRAP; - if !is_trap { + if gate_type == InterruptDescriptor::INTERRUPT_GATE { // clear int flag for interrupt gates *flags &= !FLAG_INTERRUPT; } From 3b94c5f9d34f247240e8b59799092719ac19fb0b Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 20 Sep 2018 01:19:23 +0530 Subject: [PATCH 1376/2137] cpu: Refactor to use error_code: Option for call_interrupt_vector --- src/browser/starter.js | 4 ++- src/cpu.js | 6 ++--- src/rust/cpu2/cpu.rs | 49 +++++++++++++++++++++++------------ src/rust/cpu2/instructions.rs | 6 ++--- 4 files changed, 41 insertions(+), 24 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 23b44442..73a61001 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -256,7 +256,9 @@ function V86Starter(options) "fabs": Math.abs, "abs": Math.abs, - "do_task_switch": (selector, error_code) => cpu.do_task_switch(selector, error_code), + "do_task_switch": (selector, has_error_code, error_code) => { + cpu.do_task_switch(selector, has_error_code, error_code); + }, // XXX: Port to Rust "get_tss_stack_addr": (dpl) => cpu.get_tss_stack_addr(dpl), "switch_cs_real_mode": (selector) => cpu.switch_cs_real_mode(selector), diff --git a/src/cpu.js b/src/cpu.js index 892b4de1..2a2f6c1e 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -305,7 +305,7 @@ CPU.prototype.wasm_patch = function(wm) this.trigger_np = get_import("trigger_np"); this.trigger_ss = get_import("trigger_ss"); - this.call_interrupt_vector = get_import("call_interrupt_vector"); + this.call_interrupt_vector = get_import("call_interrupt_vector_js"); this.do_many_cycles_native = get_import("do_many_cycles_native"); this.cycle_internal = get_import("cycle_internal"); @@ -2317,7 +2317,7 @@ CPU.prototype.get_tss_stack_addr = function(dpl) return tss_stack_addr; }; -CPU.prototype.do_task_switch = function(selector, error_code) +CPU.prototype.do_task_switch = function(selector, has_error_code, error_code) { dbg_assert(this.tss_size_32[0], "TODO"); @@ -2523,7 +2523,7 @@ CPU.prototype.do_task_switch = function(selector, error_code) this.cr[0] |= CR0_TS; - if(error_code !== false) + if(has_error_code !== false) { if(tss_is_16) { diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index b7784d33..a1a09a40 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -4,7 +4,7 @@ extern "C" { #[no_mangle] fn cpu_exception_hook(interrupt: i32) -> bool; #[no_mangle] - fn do_task_switch(selector: i32, error_code: i32); + fn do_task_switch(selector: i32, has_error_code: bool, error_code: i32); #[no_mangle] fn get_tss_stack_addr(dpl: u8) -> u32; #[no_mangle] @@ -370,12 +370,28 @@ impl InterruptDescriptor { } #[no_mangle] -pub unsafe fn call_interrupt_vector( +pub unsafe fn call_interrupt_vector_js( interrupt_nr: i32, is_software_int: bool, has_error_code: bool, error_code: i32, ) { + let ec = if has_error_code { + Some(error_code) + } + else { + None + }; + call_interrupt_vector(interrupt_nr, is_software_int, ec); +} + +pub unsafe fn call_interrupt_vector( + interrupt_nr: i32, + is_software_int: bool, + error_code: Option, +) { + let has_error_code = error_code.is_some(); + // we have to leave hlt_loop at some point, this is a // good place to do it *in_hlt = false; @@ -431,7 +447,7 @@ pub unsafe fn call_interrupt_vector( ); dbg_trace(); - do_task_switch(selector, error_code); + do_task_switch(selector, has_error_code, error_code.unwrap_or(0)); return; } @@ -525,7 +541,7 @@ pub unsafe fn call_interrupt_vector( let old_esp = *reg32s.offset(ESP as isize); let old_ss = *sreg.offset(SS as isize) as i32; - let error_code_space = if has_error_code == true { 1 } else { 0 }; + let error_code_space = if has_error_code { 1 } else { 0 }; let vm86_space = if (old_flags & FLAG_VM) == FLAG_VM { 4 } @@ -600,7 +616,7 @@ pub unsafe fn call_interrupt_vector( } let bytes_per_arg = if descriptor.is_32() { 4 } else { 2 }; - let error_code_space = if has_error_code == true { 1 } else { 0 }; + let error_code_space = if has_error_code { 1 } else { 0 }; let stack_space = bytes_per_arg * (3 + error_code_space); @@ -622,8 +638,8 @@ pub unsafe fn call_interrupt_vector( push32(*sreg.offset(CS as isize) as i32).unwrap(); push32(get_real_eip()).unwrap(); - if has_error_code == true { - push32(error_code).unwrap(); + if let Some(ec) = error_code { + push32(ec).unwrap(); } } else { @@ -631,8 +647,8 @@ pub unsafe fn call_interrupt_vector( push16(*sreg.offset(CS as isize) as i32).unwrap(); push16(get_real_eip()).unwrap(); - if has_error_code == true { - push16(error_code).unwrap(); + if let Some(ec) = error_code { + push16(ec).unwrap(); } offset &= 0xFFFF; @@ -984,8 +1000,7 @@ pub unsafe fn trigger_pagefault(write: bool, user: bool, present: bool) { call_interrupt_vector( CPU_EXCEPTION_PF, false, - true, - (user as i32) << 2 | (write as i32) << 1 | present as i32, + Some((user as i32) << 2 | (write as i32) << 1 | present as i32), ); } @@ -1610,7 +1625,7 @@ pub unsafe fn trigger_de() { } *prefixes = 0; *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_DE, false, false, 0); + call_interrupt_vector(CPU_EXCEPTION_DE, false, None); } #[no_mangle] @@ -1624,7 +1639,7 @@ pub unsafe fn trigger_ud() { } *prefixes = 0; *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_UD, false, false, 0); + call_interrupt_vector(CPU_EXCEPTION_UD, false, None); } pub unsafe fn trigger_nm() { @@ -1635,7 +1650,7 @@ pub unsafe fn trigger_nm() { } *prefixes = 0; *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_NM, false, false, 0); + call_interrupt_vector(CPU_EXCEPTION_NM, false, None); } #[no_mangle] @@ -1647,7 +1662,7 @@ pub unsafe fn trigger_gp_non_raising(code: i32) { } *prefixes = 0; *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_GP, false, true, code); + call_interrupt_vector(CPU_EXCEPTION_GP, false, Some(code)); } pub unsafe fn virt_boundary_read16(low: u32, high: u32) -> i32 { @@ -2442,7 +2457,7 @@ pub unsafe fn trigger_np(code: i32) { } *prefixes = 0; *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_NP, false, true, code); + call_interrupt_vector(CPU_EXCEPTION_NP, false, Some(code)); } #[no_mangle] @@ -2454,7 +2469,7 @@ pub unsafe fn trigger_ss(code: i32) { } *prefixes = 0; *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_SS, false, true, code); + call_interrupt_vector(CPU_EXCEPTION_SS, false, Some(code)); } #[no_mangle] diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index a513f3ca..fed3f291 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -2265,12 +2265,12 @@ pub unsafe fn instr_CC() { // INT3 // TODO: inhibit iopl checks dbg_log!("INT3"); - call_interrupt_vector(3, true, false, 0); + call_interrupt_vector(3, true, None); } #[no_mangle] pub unsafe fn instr_CD(imm8: i32) { // INT - call_interrupt_vector(imm8, true, false, 0); + call_interrupt_vector(imm8, true, None); } #[no_mangle] pub unsafe fn instr_CE() { @@ -2278,7 +2278,7 @@ pub unsafe fn instr_CE() { dbg_log!("INTO"); if getof() { // TODO: inhibit iopl checks - call_interrupt_vector(CPU_EXCEPTION_OF, true, false, 0); + call_interrupt_vector(CPU_EXCEPTION_OF, true, None); }; } #[no_mangle] From de8411f184836dd76476b170160de8481e8d407f Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Thu, 20 Sep 2018 02:00:36 +0530 Subject: [PATCH 1377/2137] Minor: Inline has_error_code --- src/rust/cpu2/cpu.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index a1a09a40..0cd47bb9 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -390,8 +390,6 @@ pub unsafe fn call_interrupt_vector( is_software_int: bool, error_code: Option, ) { - let has_error_code = error_code.is_some(); - // we have to leave hlt_loop at some point, this is a // good place to do it *in_hlt = false; @@ -447,7 +445,7 @@ pub unsafe fn call_interrupt_vector( ); dbg_trace(); - do_task_switch(selector, has_error_code, error_code.unwrap_or(0)); + do_task_switch(selector, error_code.is_some(), error_code.unwrap_or(0)); return; } @@ -541,7 +539,7 @@ pub unsafe fn call_interrupt_vector( let old_esp = *reg32s.offset(ESP as isize); let old_ss = *sreg.offset(SS as isize) as i32; - let error_code_space = if has_error_code { 1 } else { 0 }; + let error_code_space = if error_code.is_some() { 1 } else { 0 }; let vm86_space = if (old_flags & FLAG_VM) == FLAG_VM { 4 } @@ -616,7 +614,7 @@ pub unsafe fn call_interrupt_vector( } let bytes_per_arg = if descriptor.is_32() { 4 } else { 2 }; - let error_code_space = if has_error_code { 1 } else { 0 }; + let error_code_space = if error_code.is_some() { 1 } else { 0 }; let stack_space = bytes_per_arg * (3 + error_code_space); From 0bf4e4faf6bc8b31d87d6211dc3d8e825b70af5d Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 25 Sep 2018 13:12:00 +0530 Subject: [PATCH 1378/2137] cpu: Port get_tss_stack_addr to Rust --- src/browser/starter.js | 1 - src/cpu.js | 37 +------------------------------------ src/rust/cpu2/cpu.rs | 35 ++++++++++++++++++++++++++++++++--- src/rust/js_api.rs | 8 ++++++-- 4 files changed, 39 insertions(+), 42 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 73a61001..6dc26e9f 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -260,7 +260,6 @@ function V86Starter(options) cpu.do_task_switch(selector, has_error_code, error_code); }, // XXX: Port to Rust - "get_tss_stack_addr": (dpl) => cpu.get_tss_stack_addr(dpl), "switch_cs_real_mode": (selector) => cpu.switch_cs_real_mode(selector), }; diff --git a/src/cpu.js b/src/cpu.js index 2a2f6c1e..6a072d28 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -306,6 +306,7 @@ CPU.prototype.wasm_patch = function(wm) this.trigger_ss = get_import("trigger_ss"); this.call_interrupt_vector = get_import("call_interrupt_vector_js"); + this.get_tss_stack_addr = get_import("get_tss_stack_addr_js"); this.do_many_cycles_native = get_import("do_many_cycles_native"); this.cycle_internal = get_import("cycle_internal"); @@ -2281,42 +2282,6 @@ CPU.prototype.far_jump = function(eip, selector, is_call) CPU_LOG_VERBOSE && this.debug.dump_state("far " + ["jump", "call"][+is_call] + " end"); }; -CPU.prototype.get_tss_stack_addr = function(dpl) -{ - if(this.tss_size_32[0]) - { - var tss_stack_addr = (dpl << 3) + 4 | 0; - - if((tss_stack_addr + 5 | 0) > this.segment_limits[reg_tr]) - { - throw this.debug.unimpl("#TS handler"); - } - - tss_stack_addr = tss_stack_addr + this.segment_offsets[reg_tr] | 0; - - dbg_assert((tss_stack_addr & 0xFFF) <= 0x1000 - 6); - } - else - { - var tss_stack_addr = (dpl << 2) + 2 | 0; - - if((tss_stack_addr + 5 | 0) > this.segment_limits[reg_tr]) - { - throw this.debug.unimpl("#TS handler"); - } - - tss_stack_addr = tss_stack_addr + this.segment_offsets[reg_tr] | 0; - dbg_assert((tss_stack_addr & 0xFFF) <= 0x1000 - 4); - } - - if(this.cr[0] & CR0_PG) - { - tss_stack_addr = this.translate_address_system_read(tss_stack_addr); - } - - return tss_stack_addr; -}; - CPU.prototype.do_task_switch = function(selector, has_error_code, error_code) { dbg_assert(this.tss_size_32[0], "TODO"); diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 0cd47bb9..bc5eefb8 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -6,8 +6,6 @@ extern "C" { #[no_mangle] fn do_task_switch(selector: i32, has_error_code: bool, error_code: i32); #[no_mangle] - fn get_tss_stack_addr(dpl: u8) -> u32; - #[no_mangle] fn switch_cs_real_mode(selector: i32); #[no_mangle] fn dbg_trace(); @@ -385,6 +383,36 @@ pub unsafe fn call_interrupt_vector_js( call_interrupt_vector(interrupt_nr, is_software_int, ec); } +pub unsafe fn get_tss_stack_addr(dpl: u8) -> OrPageFault { + let mut tss_stack_addr: u32; + + if *tss_size_32 { + tss_stack_addr = ((dpl << 3) + 4) as u32; + + if tss_stack_addr + 5 > *segment_limits.offset(TR as isize) { + panic!("#TS handler"); + } + + tss_stack_addr = tss_stack_addr + *segment_offsets.offset(TR as isize) as u32; + + dbg_assert!(tss_stack_addr & 0xFFF <= 0x1000 - 6); + } + else { + tss_stack_addr = ((dpl << 2) + 2) as u32; + + if tss_stack_addr + 5 > *segment_limits.offset(TR as isize) { + panic!("#TS handler"); + } + + tss_stack_addr = tss_stack_addr + *segment_offsets.offset(TR as isize) as u32; + dbg_assert!(tss_stack_addr & 0xFFF <= 0x1000 - 4); + } + + tss_stack_addr = translate_address_system_read(tss_stack_addr as i32)?; + + Ok(tss_stack_addr) +} + pub unsafe fn call_interrupt_vector( interrupt_nr: i32, is_software_int: bool, @@ -505,7 +533,8 @@ pub unsafe fn call_interrupt_vector( panic!("Unimplemented: #GP handler for non-0 cs segment dpl when in vm86 mode"); } - let tss_stack_addr = get_tss_stack_addr(cs_segment_descriptor.dpl()); + let tss_stack_addr = + return_on_pagefault!(get_tss_stack_addr(cs_segment_descriptor.dpl())); let new_esp = read32s(tss_stack_addr); let new_ss = read16(tss_stack_addr + if *tss_size_32 { 4 } else { 2 }); diff --git a/src/rust/js_api.rs b/src/rust/js_api.rs index 22646c39..ae0e0947 100644 --- a/src/rust/js_api.rs +++ b/src/rust/js_api.rs @@ -1,6 +1,7 @@ use cpu2::cpu::{ - safe_read16, safe_read32s, safe_write16, safe_write32, translate_address_read, - translate_address_system_read, translate_address_system_write, writable_or_pagefault, + get_tss_stack_addr, safe_read16, safe_read32s, safe_write16, safe_write32, + translate_address_read, translate_address_system_read, translate_address_system_write, + writable_or_pagefault, }; use cpu2::misc_instr::{push16, push32}; @@ -35,3 +36,6 @@ pub unsafe fn push16_js(value: i32) { push16(value).unwrap() } #[no_mangle] pub unsafe fn push32_js(value: i32) { push32(value).unwrap() } + +#[no_mangle] +pub unsafe fn get_tss_stack_addr_js(dpl: u8) -> u32 { get_tss_stack_addr(dpl).unwrap() } From b6b55e5644bb161f284064d7add42db8a3d84b5b Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Tue, 25 Sep 2018 13:29:44 +0530 Subject: [PATCH 1379/2137] cpu: Refactor get_tss_stack_addr to simplify things --- src/rust/cpu2/cpu.rs | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index bc5eefb8..b258be67 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -384,33 +384,22 @@ pub unsafe fn call_interrupt_vector_js( } pub unsafe fn get_tss_stack_addr(dpl: u8) -> OrPageFault { - let mut tss_stack_addr: u32; - - if *tss_size_32 { - tss_stack_addr = ((dpl << 3) + 4) as u32; - - if tss_stack_addr + 5 > *segment_limits.offset(TR as isize) { - panic!("#TS handler"); - } - - tss_stack_addr = tss_stack_addr + *segment_offsets.offset(TR as isize) as u32; - - dbg_assert!(tss_stack_addr & 0xFFF <= 0x1000 - 6); + let (tss_stack_offset, page_boundary) = if *tss_size_32 { + (((dpl << 3) + 4) as u32, 0x1000 - 6) } else { - tss_stack_addr = ((dpl << 2) + 2) as u32; + (((dpl << 2) + 2) as u32, 0x1000 - 4) + }; - if tss_stack_addr + 5 > *segment_limits.offset(TR as isize) { - panic!("#TS handler"); - } - - tss_stack_addr = tss_stack_addr + *segment_offsets.offset(TR as isize) as u32; - dbg_assert!(tss_stack_addr & 0xFFF <= 0x1000 - 4); + if tss_stack_offset + 5 > *segment_limits.offset(TR as isize) { + panic!("#TS handler"); } - tss_stack_addr = translate_address_system_read(tss_stack_addr as i32)?; + let tss_stack_addr = *segment_offsets.offset(TR as isize) as u32 + tss_stack_offset; - Ok(tss_stack_addr) + dbg_assert!(tss_stack_addr & 0xFFF <= page_boundary); + + Ok(translate_address_system_read(tss_stack_addr as i32)?) } pub unsafe fn call_interrupt_vector( From 1a6f3cfef3528ae8044c41158e1b1bd6e6537d77 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 19 Sep 2018 10:49:52 +1200 Subject: [PATCH 1380/2137] Compile from and to ECMASCRIPT_2017 - Want to use async/await features. - We need modern web browsers to run Web Assembly anyway. --- Makefile | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index c692d8a1..f22d5592 100644 --- a/Makefile +++ b/Makefile @@ -76,11 +76,8 @@ CLOSURE_FLAGS=\ --jscomp_error visibility\ --use_types_for_optimization\ --summary_detail_level 3\ - --language_in ECMASCRIPT5_STRICT - -TRANSPILE_ES6_FLAGS=\ - --language_in ECMASCRIPT6_STRICT\ - --language_out ECMASCRIPT5_STRICT\ + --language_in ECMASCRIPT_2017\ + --language_out ECMASCRIPT_2017 CARGO_FLAGS=\ --target wasm32-unknown-unknown \ @@ -117,7 +114,6 @@ build/v86_all.js: $(CLOSURE) src/*.js src/browser/*.js lib/*.js $(CLOSURE_SOURCE_MAP)\ $(CLOSURE_FLAGS)\ --compilation_level ADVANCED\ - $(TRANSPILE_ES6_FLAGS)\ --js $(CORE_FILES)\ --js $(LIB_FILES)\ --js $(BROWSER_FILES)\ @@ -136,7 +132,6 @@ build/libv86.js: $(CLOSURE) src/*.js lib/*.js src/browser/*.js --define=DEBUG=false\ $(CLOSURE_FLAGS)\ --compilation_level SIMPLE\ - $(TRANSPILE_ES6_FLAGS)\ --output_wrapper ';(function(){%output%}).call(this);'\ --js $(CORE_FILES)\ --js $(BROWSER_FILES)\ @@ -151,7 +146,6 @@ build/libv86-debug.js: $(CLOSURE) src/*.js lib/*.js src/browser/*.js $(CLOSURE_FLAGS)\ $(CLOSURE_READABLE)\ --compilation_level SIMPLE\ - $(TRANSPILE_ES6_FLAGS)\ --output_wrapper ';(function(){%output%}).call(this);'\ --js $(CORE_FILES)\ --js $(BROWSER_FILES)\ From 595d6dca5503b5eb0354f5b6f0cc908d06c1d46d Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 19 Sep 2018 22:10:13 +1200 Subject: [PATCH 1381/2137] Filesystem: Refactor inodedata accesses to async methods The "// jshint ignore:line" comments are pretty messy, so squint your eyes. They're systematically placed, so we can regex it out when jshint's new version finally arrives. Using async/await instead of callbacks due to callback hell, and it also helps minimising the diff) --- lib/9p.js | 20 ++++---- lib/filesystem.js | 111 ++++++++++++++++++++++++++--------------- src/browser/starter.js | 36 ++++++------- 3 files changed, 97 insertions(+), 70 deletions(-) diff --git a/lib/9p.js b/lib/9p.js index fc7415ea..03dcd461 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -250,7 +250,7 @@ Virtio9p.prototype.SendReply = function (bufchain) { this.virtqueue.flush_replies(); }; -Virtio9p.prototype.ReceiveRequest = function (bufchain) { +Virtio9p.prototype.ReceiveRequest = async function (bufchain) { // jshint ignore:line // TODO: split into header + data blobs to avoid unnecessary copying. const buffer = new Uint8Array(bufchain.length_readable); bufchain.get_next_blob(buffer); @@ -552,7 +552,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { inode.mtime = req[8]; } if (req[1] & P9_SETATTR_SIZE) { - this.fs.ChangeSize(this.fids[fid].inodeid, req[5]); + await this.fs.ChangeSize(this.fids[fid].inodeid, req[5]); // jshint ignore:line } this.BuildReply(id, tag, 0); this.SendReply(bufchain); @@ -593,7 +593,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { this.fs.OpenInode(this.fids[fid].inodeid, undefined); this.fs.AddEvent(this.fids[fid].inodeid, - function() { + async function() { // jshint ignore:line this.bus.send("9p-read-end", [this.fids[fid].dbg_name, count]); const inodeid = this.fids[fid].inodeid; @@ -610,15 +610,15 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { // See http://ericvh.github.io/9p-rfc/rfc9p2000.html#anchor30 count = 0; } - const data = this.fs.Read(inodeid, offset, count); + const data = await this.fs.Read(inodeid, offset, count); // jshint ignore:line if(data) { this.replybuffer.set(data, 7 + 4); } marshall.Marshall(["w"], [count], this.replybuffer, 7); this.BuildReply(id, tag, 4 + count); this.SendReply(bufchain); - }.bind(this) - ); + }.bind(this) // jshint ignore:line + ); // jshint ignore:line } break; @@ -640,7 +640,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { else { // XXX: Size of the subarray is unchecked - this.fs.Write(this.fids[fid].inodeid, offset, count, buffer.subarray(state.offset)); + await this.fs.Write(this.fids[fid].inodeid, offset, count, buffer.subarray(state.offset)); // jshint ignore:line } this.bus.send("9p-write-end", [filename, count]); @@ -657,7 +657,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { var newdirfid = req[2]; var newname = req[3]; message.Debug("[renameat]: oldname=" + oldname + " newname=" + newname); - var ret = this.fs.Rename(this.fids[olddirfid].inodeid, oldname, this.fids[newdirfid].inodeid, newname); + var ret = await this.fs.Rename(this.fids[olddirfid].inodeid, oldname, this.fids[newdirfid].inodeid, newname); // jshint ignore:line if (ret < 0) { let error_message = ""; if(ret === -ENOENT) error_message = "No such file or directory"; @@ -790,7 +790,7 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { var req = marshall.Unmarshall(["w"], buffer, state); message.Debug("[clunk]: fid=" + req[0]); if (this.fids[req[0]] && this.fids[req[0]].inodeid >= 0) { - this.fs.CloseInode(this.fids[req[0]].inodeid); + await this.fs.CloseInode(this.fids[req[0]].inodeid); // jshint ignore:line this.fids[req[0]].inodeid = -1; this.fids[req[0]].type = FID_NONE; } @@ -844,4 +844,4 @@ Virtio9p.prototype.ReceiveRequest = function (bufchain) { //consistency checks if there are problems with the filesystem //this.fs.Check(); -}; +}; // jshint ignore:line diff --git a/lib/filesystem.js b/lib/filesystem.js index 14939f96..fdf2d091 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -303,15 +303,16 @@ FS.prototype.LoadFile = function(idx) { if(this.baseurl) { LoadBinaryResource(this.baseurl + inode.sha256sum, - function(buffer){ - var data = this.inodedata[idx] = new Uint8Array(buffer); + async function(buffer){ // jshint ignore:line + const data = new Uint8Array(buffer); + await this.set_data(idx, data); // jshint ignore:line inode.size = data.length; // correct size if the previous was wrong. inode.status = STATUS_OK; this.filesinloadingqueue--; this.HandleEvent(idx); - }.bind(this), - function(error){throw error;}); + }.bind(this), // jshint ignore:line + function(error){throw error;}); // jshint ignore:line } else { @@ -710,7 +711,7 @@ FS.prototype.CreateSymlink = function(filename, parentid, symlink) { return this.inodes.length-1; }; -FS.prototype.CreateTextFile = function(filename, parentid, str) { +FS.prototype.CreateTextFile = async function(filename, parentid, str) { // jshint ignore:line const parent_inode = this.inodes[parentid]; if(this.is_forwarder(parent_inode)) { @@ -721,19 +722,20 @@ FS.prototype.CreateTextFile = function(filename, parentid, str) { } var id = this.CreateFile(filename, parentid); var x = this.inodes[id]; - var data = this.inodedata[id] = new Uint8Array(str.length); + var data = new Uint8Array(str.length); x.dirty = true; x.size = str.length; for (var j = 0; j < str.length; j++) { data[j] = str.charCodeAt(j); } + await this.set_data(id, data); // jshint ignore:line return id; -}; +}; // jshint ignore:line /** * @param {Uint8Array} buffer */ -FS.prototype.CreateBinaryFile = function(filename, parentid, buffer) { +FS.prototype.CreateBinaryFile = async function(filename, parentid, buffer) { // jshint ignore:line const parent_inode = this.inodes[parentid]; if(this.is_forwarder(parent_inode)) { @@ -744,12 +746,13 @@ FS.prototype.CreateBinaryFile = function(filename, parentid, buffer) { } var id = this.CreateFile(filename, parentid); var x = this.inodes[id]; - var data = this.inodedata[id] = new Uint8Array(buffer.length); + var data = new Uint8Array(buffer.length); x.dirty = true; data.set(buffer); + await this.set_data(id, data); // jshint ignore:line x.size = buffer.length; return id; -}; +}; // jshint ignore:line FS.prototype.OpenInode = function(id, mode) { @@ -778,7 +781,7 @@ FS.prototype.OpenInode = function(id, mode) { return true; }; -FS.prototype.CloseInode = function(id) { +FS.prototype.CloseInode = async function(id) { // jshint ignore:line //message.Debug("close: " + this.GetFullPath(id)); var inode = this.inodes[id]; if(this.is_forwarder(inode)) @@ -788,15 +791,14 @@ FS.prototype.CloseInode = function(id) { if (inode.status == STATUS_UNLINKED) { //message.Debug("Filesystem: Delete unlinked file"); inode.status = STATUS_INVALID; - delete this.inodedata[id]; - inode.size = 0; + await this.DeleteData(id); // jshint ignore:line } -}; +}; // jshint ignore:line /** * @return {number} 0 if success, or -errno if failured. */ -FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { +FS.prototype.Rename = async function(olddirid, oldname, newdirid, newname) { // jshint ignore:line // message.Debug("Rename " + oldname + " to " + newname); if ((olddirid == newdirid) && (oldname == newname)) { return 0; @@ -834,8 +836,8 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { { // Move inode within the same child filesystem. - const ret = this.follow_fs(olddir) - .Rename(olddir.foreign_id, oldname, newdir.foreign_id, newname); + const ret = await // jshint ignore:line + this.follow_fs(olddir).Rename(olddir.foreign_id, oldname, newdir.foreign_id, newname); if(ret < 0) return ret; } @@ -862,7 +864,7 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { const diverted_old_idx = this.divert(olddirid, oldname); const old_real_inode = this.GetInode(idx); - const data = this.Read(diverted_old_idx, 0, old_real_inode.size); + const data = await this.Read(diverted_old_idx, 0, old_real_inode.size); // jshint ignore:line if(this.is_forwarder(newdir)) { @@ -889,10 +891,10 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { } // Rewrite data to newly created destination. - this.ChangeSize(idx, old_real_inode.size); + await this.ChangeSize(idx, old_real_inode.size); // jshint ignore:line if(data && data.length) { - this.Write(idx, 0, data.length, data); + await this.Write(idx, 0, data.length, data); // jshint ignore:line } // Move children to newly created destination. @@ -900,13 +902,13 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { { for(const child_filename of this.GetChildren(diverted_old_idx)) { - const ret = this.Rename(diverted_old_idx, child_filename, idx, child_filename); + const ret = await this.Rename(diverted_old_idx, child_filename, idx, child_filename); // jshint ignore:line if(ret < 0) return ret; } } // Perform destructive changes only after migration succeeded. - this.DeleteData(diverted_old_idx); + await this.DeleteData(diverted_old_idx); // jshint ignore:line const ret = this.Unlink(olddirid, oldname); if(ret < 0) return ret; } @@ -914,26 +916,26 @@ FS.prototype.Rename = function(olddirid, oldname, newdirid, newname) { this.NotifyListeners(idx, "rename", {oldpath: oldpath}); return 0; -}; +}; // jshint ignore:line -FS.prototype.Write = function(id, offset, count, buffer) { +FS.prototype.Write = async function(id, offset, count, buffer) { // jshint ignore:line this.NotifyListeners(id, 'write'); var inode = this.inodes[id]; if(this.is_forwarder(inode)) { const foreign_id = inode.foreign_id; - this.follow_fs(inode).Write(foreign_id, offset, count, buffer); + await this.follow_fs(inode).Write(foreign_id, offset, count, buffer); // jshint ignore:line return; } inode.dirty = true; - var data = this.inodedata[id]; + var data = await this.get_data(id); // jshint ignore:line if (!data || data.length < (offset+count)) { - this.ChangeSize(id, Math.floor(((offset+count)*3)/2) ); + await this.ChangeSize(id, Math.floor(((offset+count)*3)/2)); // jshint ignore:line inode.size = offset + count; - data = this.inodedata[id]; + data = await this.get_data(id); // jshint ignore:line } else if (inode.size < (offset+count)) { inode.size = offset + count; @@ -942,25 +944,28 @@ FS.prototype.Write = function(id, offset, count, buffer) { { data.set(buffer.subarray(0, count), offset); } -}; + await this.set_data(id, data); // jshint ignore:line +}; // jshint ignore:line -FS.prototype.Read = function(inodeid, offset, count) +FS.prototype.Read = async function(inodeid, offset, count) // jshint ignore:line { const inode = this.inodes[inodeid]; if(this.is_forwarder(inode)) { const foreign_id = inode.foreign_id; - return this.follow_fs(inode).Read(foreign_id, offset, count); + return await this.follow_fs(inode).Read(foreign_id, offset, count); // jshint ignore:line } - else if(!this.inodedata[inodeid]) + + const data = await this.get_data(inodeid); // jshint ignore:line + if(!data) { return null; } else { - return this.inodedata[inodeid].subarray(offset, offset + count); + return data.subarray(offset, offset + count); } -}; +}; // jshint ignore:line FS.prototype.Search = function(parentid, name) { const parent_inode = this.inodes[parentid]; @@ -1136,7 +1141,7 @@ FS.prototype.Unlink = function(parentid, name) { return 0; }; -FS.prototype.DeleteData = function(idx) +FS.prototype.DeleteData = async function(idx) // jshint ignore:line { const inode = this.inodes[idx]; if(this.is_forwarder(inode)) @@ -1146,7 +1151,32 @@ FS.prototype.DeleteData = function(idx) } inode.size = 0; delete this.inodedata[idx]; -}; +}; // jshint ignore:line + +/** + * @private + * @param {number} idx + * @return {Uint8Array} + */ +FS.prototype.get_data = async function(idx) // jshint ignore:line +{ + const inode = this.inodes[idx]; + dbg_assert(inode, `Filesystem get_data: idx ${idx} does not point to an inode`); + + if(this.inodedata[idx]) return this.inodedata[idx]; + return null; +}; // jshint ignore:line + +/** + * @private + * @param {number} idx + * @param {Uint8Array} buffer + */ +FS.prototype.set_data = async function(idx, buffer) // jshint ignore:line +{ + // Current scheme: Save all modified buffers into local inodedata. + this.inodedata[idx] = buffer; +}; // jshint ignore:line /** * @param {number} idx @@ -1166,19 +1196,20 @@ FS.prototype.GetInode = function(idx) return inode; }; -FS.prototype.ChangeSize = function(idx, newsize) +FS.prototype.ChangeSize = async function(idx, newsize) // jshint ignore:line { var inode = this.GetInode(idx); - var temp = this.inodedata[idx]; + var temp = await this.get_data(idx); // jshint ignore:line inode.dirty = true; //message.Debug("change size to: " + newsize); if (newsize == inode.size) return; - var data = this.inodedata[idx] = new Uint8Array(newsize); + var data = new Uint8Array(newsize); + await this.set_data(idx, data); // jshint ignore:line inode.size = newsize; if(!temp) return; var size = Math.min(temp.length, inode.size); data.set(temp.subarray(0, size), 0); -}; +}; // jshint ignore:line FS.prototype.SearchPath = function(path) { //path = path.replace(/\/\//g, "/"); diff --git a/src/browser/starter.js b/src/browser/starter.js index 6dc26e9f..cd3330b9 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -1149,6 +1149,8 @@ V86Starter.prototype.mount_fs = function(path, baseurl, basefs, callback) */ V86Starter.prototype.create_file = function(file, data, callback) { + callback = callback || function() {}; + var fs = this.fs9p; if(!fs) @@ -1165,21 +1167,14 @@ V86Starter.prototype.create_file = function(file, data, callback) if(!not_found) { - fs.CreateBinaryFile(filename, parent_id, data); + fs.CreateBinaryFile(filename, parent_id, data) + .then(() => callback(null)); } - - if(callback) + else { setTimeout(function() { - if(not_found) - { - callback(new FileNotFoundError()); - } - else - { - callback(null); - } + callback(new FileNotFoundError()); }, 0); } }; @@ -1216,16 +1211,17 @@ V86Starter.prototype.read_file = function(file, callback) function() { const size = fs.GetInode(id).size; - const data = fs.Read(id, 0, size); - - if(data) + fs.Read(id, 0, size).then(data => { - callback(null, data); - } - else - { - callback(new FileNotFoundError(), null); - } + if(data) + { + callback(null, data); + } + else + { + callback(new FileNotFoundError(), null); + } + }); } ); } From 0a67e3532f2766d6f917c571cbea152695d2dcbd Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 22 Sep 2018 20:39:19 +1200 Subject: [PATCH 1382/2137] Filesystem: Introduce FileStorage class for server-loaded files --- Makefile | 2 +- lib/filesystem.js | 65 ++------------------------ loader.js | 2 +- src/browser/filestorage.js | 95 ++++++++++++++++++++++++++++++++++++++ src/browser/starter.js | 4 +- 5 files changed, 103 insertions(+), 65 deletions(-) create mode 100644 src/browser/filestorage.js diff --git a/Makefile b/Makefile index f22d5592..232b7c92 100644 --- a/Makefile +++ b/Makefile @@ -94,7 +94,7 @@ CORE_FILES=const.js config.js io.js main.js lib.js coverage.js ide.js pci.js flo LIB_FILES=9p.js filesystem.js jor1k.js marshall.js utf8.js BROWSER_FILES=screen.js \ keyboard.js mouse.js serial.js \ - network.js lib.js starter.js worker_bus.js dummy_screen.js print_stats.js + network.js lib.js starter.js worker_bus.js dummy_screen.js print_stats.js filestorage.js RUST_FILES=$(shell find src/rust/ -name '*.rs') \ src/rust/gen/interpreter.rs src/rust/gen/interpreter0f_16.rs src/rust/gen/interpreter0f_32.rs \ diff --git a/lib/filesystem.js b/lib/filesystem.js index fdf2d091..4966eceb 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -26,8 +26,6 @@ var O_ACCMODE = 0x0003; // mask for above modes var STATUS_INVALID = -0x1; var STATUS_OK = 0x0; -var STATUS_ON_SERVER = 0x2; -var STATUS_LOADING = 0x3; var STATUS_UNLINKED = 0x4; var STATUS_FORWARDING = 0x5; @@ -47,15 +45,15 @@ var STATUS_FORWARDING = 0x5; /** * @constructor - * @param {string=} baseurl + * @param {FileStorage=} storage * @param {{ last_qidnumber: number }=} qidcounter Another fs's qidcounter to synchronise with. */ -function FS(baseurl, qidcounter) { +function FS(storage, qidcounter) { /** @type {Array.} */ this.inodes = []; this.events = []; - this.baseurl = baseurl; + this.storage = storage; this.qidcounter = qidcounter || { last_qidnumber: 0 }; this.filesinloadingqueue = 0; @@ -243,7 +241,6 @@ FS.prototype.LoadRecursive = function(data, parentid) } else if(ifmt === S_IFREG) { - inode.status = STATUS_ON_SERVER; inode.sha256sum = data[JSONFS_IDX_SHA256]; this.PushInode(inode, parentid, name); } @@ -269,57 +266,6 @@ FS.prototype.LoadDir = function(parentid, children) } }; -// Loads the data from a url for a specific inode -FS.prototype.LoadFile = function(idx) { - var inode = this.inodes[idx]; - if(this.is_forwarder(inode)) - { - // Events handled by child filesystem. - this.follow_fs(inode).LoadFile(inode.foreign_id); - return; - } - else if(inode.status != STATUS_ON_SERVER) - { - return; - } - inode.status = STATUS_LOADING; - this.filesinloadingqueue++; - - //if (inode.compressed) { - // inode.data = new Uint8Array(inode.size); - // LoadBinaryResource(inode.url + ".bz2", - // function(buffer){ - // var buffer8 = new Uint8Array(buffer); - // var ofs = 0; - // bzip2.simple(buffer8, function(x){inode.data[ofs++] = x;}.bind(this) ); - // inode.status = STATUS_OK; - // this.filesinloadingqueue--; - // this.HandleEvent(idx); - // }.bind(this), - // function(error){throw error;}); - // return; - //} - - if(this.baseurl) - { - LoadBinaryResource(this.baseurl + inode.sha256sum, - async function(buffer){ // jshint ignore:line - const data = new Uint8Array(buffer); - await this.set_data(idx, data); // jshint ignore:line - inode.size = data.length; // correct size if the previous was wrong. - inode.status = STATUS_OK; - - this.filesinloadingqueue--; - this.HandleEvent(idx); - }.bind(this), // jshint ignore:line - function(error){throw error;}); // jshint ignore:line - } - else - { - // If baseurl is not set, we started with an empty filesystem. No files - // can be loaded - } -}; // ----------------------------------------------------- @@ -774,10 +720,6 @@ FS.prototype.OpenInode = function(id, mode) { } */ //message.Debug("open:" + this.GetFullPath(id) + " type: " + inode.mode + " status:" + inode.status); - if (inode.status == STATUS_ON_SERVER) { - this.LoadFile(id); - return false; - } return true; }; @@ -1164,6 +1106,7 @@ FS.prototype.get_data = async function(idx) // jshint ignore:line dbg_assert(inode, `Filesystem get_data: idx ${idx} does not point to an inode`); if(this.inodedata[idx]) return this.inodedata[idx]; + if(inode.sha256sum && this.storage) return await this.storage.get(inode.sha256sum); // jshint ignore:line return null; }; // jshint ignore:line diff --git a/loader.js b/loader.js index 9d75796b..9b15d6a8 100644 --- a/loader.js +++ b/loader.js @@ -10,7 +10,7 @@ "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"; - var BROWSER_FILES = "main.js screen.js keyboard.js mouse.js serial.js lib.js network.js starter.js worker_bus.js print_stats.js"; + var BROWSER_FILES = "main.js screen.js keyboard.js mouse.js serial.js lib.js network.js starter.js worker_bus.js print_stats.js filestorage.js"; var LIB_FILES = ""; // jor1k stuff diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js new file mode 100644 index 00000000..fd8022d1 --- /dev/null +++ b/src/browser/filestorage.js @@ -0,0 +1,95 @@ +"use strict"; + + +/** @interface */ +function FileStorage() {} + +/** + * @param {string} sha256sum + * @return {!Promise} + */ +FileStorage.prototype.get = function(sha256sum) {}; + +/** + * @param {string} sha256sum + * @param {!Uint8Array} data + * @return {!Promise} + */ +FileStorage.prototype.set = function(sha256sum, buffer) {}; + +/** + * @constructor + * @implements {FileStorage} + * @param {string=} baseurl + */ +function MemoryFileStorage(baseurl) +{ + this.baseurl = baseurl; + + /** + * From sha256sum to file data. + * @type {Map} + */ + this.filedata = new Map(); +} + +/** + * @private + * @param {string} sha256sum + * @return {!Promise} + */ +MemoryFileStorage.prototype.load_from_server = function(sha256sum) +{ + return new Promise((resolve, reject) => + { + if(!this.baseurl) + { + resolve(null); + return; + } + + v86util.load_file(this.baseurl + sha256sum, { done: buffer => + { + const data = new Uint8Array(buffer); + this.filedata.set(sha256sum, data); + resolve(data); + }}); + }); +}; + +/** + * @param {string} sha256sum + * @return {!Promise} + */ +MemoryFileStorage.prototype.get = function(sha256sum) +{ + dbg_assert(sha256sum !== "", "MemoryFileStorage get: sha256sum should not be an empty string"); + + return new Promise((resolve, reject) => + { + if(this.filedata.has(sha256sum)) + { + resolve(this.filedata.get(sha256sum)); + } + else + { + this.load_from_server(sha256sum).then(data => resolve(data)); + } + }); +}; + +/** + * @param {string} sha256sum + * @param {!Uint8Array} data + * @return {!Promise} + */ +MemoryFileStorage.prototype.set = function(sha256sum, buffer) +{ + dbg_assert(sha256sum !== "", "MemoryFileStorage set: sha256sum should not be an empty string"); + + return new Promise((resolve, reject) => + { + this.filedata.set(sha256sum, buffer); + resolve(); + }); +}; diff --git a/src/browser/starter.js b/src/browser/starter.js index cd3330b9..fc4a0797 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -565,7 +565,7 @@ function V86Starter(options) var fs_url = options["filesystem"]["basefs"]; var base_url = options["filesystem"]["baseurl"]; - this.fs9p = new FS(base_url); + this.fs9p = new FS(new MemoryFileStorage(base_url)); settings.fs9p = this.fs9p; if(fs_url) @@ -1099,7 +1099,7 @@ V86Starter.prototype.serial0_send = function(data) */ V86Starter.prototype.mount_fs = function(path, baseurl, basefs, callback) { - const newfs = new FS(baseurl, this.fs9p.qidcounter); + const newfs = new FS(new MemoryFileStorage(base_url), this.fs9p.qidcounter); const mount = () => { const idx = this.fs9p.Mount(path, newfs); From a0c984dc8dad81eeb3f0e587366fe81aaf94e3cf Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 22 Sep 2018 20:44:08 +1200 Subject: [PATCH 1383/2137] Filesystem: Introduce IndexedDBFileStorage Uses MemoryFileStorage as a fallback when: - v86 is used in a browserless environment, e.g. NodeJS - browser doesn't support indexedDB - opening indexedDB fails - existing database is a newer version - existing database is an old version and is under use - blocking current v86 instance to connect to it. --- src/browser/filestorage.js | 152 +++++++++++++++++++++++++++++++++++++ src/browser/starter.js | 10 ++- 2 files changed, 160 insertions(+), 2 deletions(-) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index fd8022d1..c66b1c4e 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -1,5 +1,8 @@ "use strict"; +const INDEXEDDB_STORAGE_VERSION = 1; +const INDEXEDDB_STORAGE_NAME = "IndexedDBFileStorage"; +const INDEXEDDB_STORAGE_STORE = "Store"; /** @interface */ function FileStorage() {} @@ -93,3 +96,152 @@ MemoryFileStorage.prototype.set = function(sha256sum, buffer) resolve(); }); }; + +/** + * @constructor + * @implements {FileStorage} + * @param {string=} baseurl + */ +function IndexedDBFileStorage(baseurl) +{ + this.fallback_storage = new MemoryFileStorage(baseurl); + this.baseurl = baseurl; + this.db = null; + + if(typeof indexedDB === "undefined") + { + dbg_log("IndexedDB not available. Using MemoryFileStorage as fallback.", LOG_9P); + } + else + { + const open_request = indexedDB.open(INDEXEDDB_STORAGE_NAME, INDEXEDDB_STORAGE_VERSION); + + open_request.onblocked = event => + { + dbg_log("IndexedDB blocked by an older database version being opened.", LOG_9P); + dbg_log("Using MemoryFileStorage until unblocked.", LOG_9P); + }; + + open_request.onerror = event => + { + dbg_log("Error opening IndexedDB! Are you in private browsing mode? ", LOG_9P); + dbg_log("Falling back to MemoryFileStorage. Error: " + open_request.error, LOG_9P); + }; + + open_request.onupgradeneeded = event => + { + const db = open_request.result; + db.createObjectStore(INDEXEDDB_STORAGE_STORE, { keyPath: "sha256sum" }); + }; + + open_request.onsuccess = event => + { + // Fallback no longer needed. + this.fallback_storage = null; + + this.db = open_request.result; + this.db.onabort = event => + { + dbg_assert(false, "IndexedDBFileStorage: transaction aborted unexpectedly"); + }; + this.db.onclose = event => + { + dbg_assert(false, "IndexedDBFileStorage: connection closed unexpectedly"); + }; + this.db.onerror = error => + { + dbg_assert(false, "IndexedDBFileStorage: unexpected error: " + error); + }; + this.db.onversionchange = event => + { + dbg_log("Warning: another v86 instance is trying to open IndexedDB database but " + + "is blocked by this current v86 instance.", LOG_9P); + }; + }; + } +} + +/** + * @private + * @param {string} sha256sum + * @return {!Promise} + */ +IndexedDBFileStorage.prototype.load_from_server = function(sha256sum) +{ + dbg_assert(this.db, "IndexedDBFileStorage load_from_server called without opening database"); + + return new Promise((resolve, reject) => + { + if(!this.baseurl) + { + resolve(null); + return; + } + v86util.load_file(this.baseurl + sha256sum, { done: buffer => + { + const data = new Uint8Array(buffer); + const transaction = this.db.transaction(INDEXEDDB_STORAGE_STORE, "readwrite"); + const store = transaction.objectStore(INDEXEDDB_STORAGE_STORE); + const request = store.put({ sha256sum, data }); + request.onsuccess = event => resolve(data); + }}); + }); +}; + +/** + * @param {string} sha256sum + * @return {!Promise} + */ +IndexedDBFileStorage.prototype.get = function(sha256sum) +{ + dbg_assert(sha256sum !== "", "IndexedDBFileStorage get: sha256sum should not be an empty string"); + + if(!this.db) + { + return this.fallback_storage.get(sha256sum); + } + + return new Promise((resolve, reject) => + { + const transaction = this.db.transaction(INDEXEDDB_STORAGE_STORE, "readonly"); + const store = transaction.objectStore(INDEXEDDB_STORAGE_STORE); + const request = store.get(sha256sum); + request.onsuccess = event => + { + dbg_assert(!request.result || request.result.data instanceof Uint8Array, + "IndexedDBFileStorage get: invalid entry format: " + request.result); + + if(request.result && request.result.data instanceof Uint8Array) + { + resolve(request.result.data); + } + else + { + this.load_from_server(sha256sum).then(data => resolve(data)); + } + }; + }); +}; + +/** + * @param {string} sha256sum + * @param {!Uint8Array} data + * @return {!Promise} + */ +IndexedDBFileStorage.prototype.set = function(sha256sum, data) +{ + dbg_assert(sha256sum !== "", "IndexedDBFileStorage set: sha256sum should not be an empty string"); + + if(!this.db) + { + return this.fallback_storage.get(sha256sum); + } + + return new Promise((resolve, reject) => + { + const transaction = this.db.transaction(INDEXEDDB_STORAGE_STORE, "readwrite"); + const store = transaction.objectStore(INDEXEDDB_STORAGE_STORE); + const request = store.put({ sha256sum, data }); + request.onsuccess = event => resolve(); + }); +}; diff --git a/src/browser/starter.js b/src/browser/starter.js index fc4a0797..24318e8e 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -565,7 +565,10 @@ function V86Starter(options) var fs_url = options["filesystem"]["basefs"]; var base_url = options["filesystem"]["baseurl"]; - this.fs9p = new FS(new MemoryFileStorage(base_url)); + const fileStorage = typeof indexedDB === "undefined" ? + new MemoryFileStorage(base_url) : + new IndexedDBFileStorage(base_url); + this.fs9p = new FS(fileStorage); settings.fs9p = this.fs9p; if(fs_url) @@ -1099,7 +1102,10 @@ V86Starter.prototype.serial0_send = function(data) */ V86Starter.prototype.mount_fs = function(path, baseurl, basefs, callback) { - const newfs = new FS(new MemoryFileStorage(base_url), this.fs9p.qidcounter); + const fileStorage = typeof indexedDB === "undefined" ? + new MemoryFileStorage(baseurl) : + new IndexedDBFileStorage(baseurl); + const newfs = new FS(fileStorage, this.fs9p.qidcounter); const mount = () => { const idx = this.fs9p.Mount(path, newfs); From 27a825dce3137179ecd0bd66c71ca3b4dfde6697 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 22 Sep 2018 22:25:36 +1200 Subject: [PATCH 1384/2137] Filestorage: Preserve key names when writing into indexeddb --- src/browser/filestorage.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index c66b1c4e..a95e0ce4 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -3,6 +3,8 @@ const INDEXEDDB_STORAGE_VERSION = 1; const INDEXEDDB_STORAGE_NAME = "IndexedDBFileStorage"; const INDEXEDDB_STORAGE_STORE = "Store"; +const INDEXEDDB_STORAGE_KEYPATH = "sha256sum"; +const INDEXEDDB_STORAGE_VALUEPATH = "data"; /** @interface */ function FileStorage() {} @@ -131,7 +133,7 @@ function IndexedDBFileStorage(baseurl) open_request.onupgradeneeded = event => { const db = open_request.result; - db.createObjectStore(INDEXEDDB_STORAGE_STORE, { keyPath: "sha256sum" }); + db.createObjectStore(INDEXEDDB_STORAGE_STORE, { keyPath: INDEXEDDB_STORAGE_KEYPATH }); }; open_request.onsuccess = event => @@ -182,7 +184,10 @@ IndexedDBFileStorage.prototype.load_from_server = function(sha256sum) const data = new Uint8Array(buffer); const transaction = this.db.transaction(INDEXEDDB_STORAGE_STORE, "readwrite"); const store = transaction.objectStore(INDEXEDDB_STORAGE_STORE); - const request = store.put({ sha256sum, data }); + const request = store.put({ + [INDEXEDDB_STORAGE_KEYPATH]: sha256sum, + [INDEXEDDB_STORAGE_VALUEPATH]: data, + }); request.onsuccess = event => resolve(data); }}); }); @@ -241,7 +246,10 @@ IndexedDBFileStorage.prototype.set = function(sha256sum, data) { const transaction = this.db.transaction(INDEXEDDB_STORAGE_STORE, "readwrite"); const store = transaction.objectStore(INDEXEDDB_STORAGE_STORE); - const request = store.put({ sha256sum, data }); + const request = store.put({ + [INDEXEDDB_STORAGE_KEYPATH]: sha256sum, + [INDEXEDDB_STORAGE_VALUEPATH]: data, + }); request.onsuccess = event => resolve(); }); }; From 6fe226eec9cf55840dfcdd483e178e1b229b4462 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 22 Sep 2018 22:31:18 +1200 Subject: [PATCH 1385/2137] Filestorage: Reuse write-to-indexeddb logic --- src/browser/filestorage.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index a95e0ce4..154204f7 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -182,13 +182,7 @@ IndexedDBFileStorage.prototype.load_from_server = function(sha256sum) v86util.load_file(this.baseurl + sha256sum, { done: buffer => { const data = new Uint8Array(buffer); - const transaction = this.db.transaction(INDEXEDDB_STORAGE_STORE, "readwrite"); - const store = transaction.objectStore(INDEXEDDB_STORAGE_STORE); - const request = store.put({ - [INDEXEDDB_STORAGE_KEYPATH]: sha256sum, - [INDEXEDDB_STORAGE_VALUEPATH]: data, - }); - request.onsuccess = event => resolve(data); + this.set(sha256sum, data).then(() => resolve(data)); }}); }); }; From c1729b7dafe437fe28382ded69a9c17cef11e6e5 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 22 Sep 2018 22:52:51 +1200 Subject: [PATCH 1386/2137] Filesystem: Don't modify local copy of filedata after set_data While the original code would've worked for MemoryFileStorage, it will not work for FileStorages that clone the data before saving (e.g. IndexedDBFileStorage) as local changes won't be reflected onto the storage class. --- lib/filesystem.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 4966eceb..a229fe77 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -1147,11 +1147,13 @@ FS.prototype.ChangeSize = async function(idx, newsize) // jshint ignore:line //message.Debug("change size to: " + newsize); if (newsize == inode.size) return; var data = new Uint8Array(newsize); - await this.set_data(idx, data); // jshint ignore:line inode.size = newsize; - if(!temp) return; - var size = Math.min(temp.length, inode.size); - data.set(temp.subarray(0, size), 0); + if(temp) + { + var size = Math.min(temp.length, inode.size); + data.set(temp.subarray(0, size), 0); + } + await this.set_data(idx, data); // jshint ignore:line }; // jshint ignore:line FS.prototype.SearchPath = function(path) { From 44d54facb7189051da02969e5a2a67159297f4da Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sat, 22 Sep 2018 23:11:58 +1200 Subject: [PATCH 1387/2137] Filesystem: Remove remnants of file loader --- lib/filesystem.js | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index a229fe77..f053cf81 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -56,7 +56,6 @@ function FS(storage, qidcounter) { this.storage = storage; this.qidcounter = qidcounter || { last_qidnumber: 0 }; - this.filesinloadingqueue = 0; this.OnLoaded = function() {}; //this.tar = new TAR(this); @@ -127,16 +126,6 @@ FS.prototype.set_state = function(state) // ----------------------------------------------------- -FS.prototype.IsLoading = function() -{ - if(this.filesinloadingqueue > 0) return true; - for(const mount of this.mounts) - { - if(mount.fs.IsLoading()) return true; - } - return false; -}; - FS.prototype.AddEvent = function(id, OnEvent) { var inode = this.inodes[id]; if (inode.status == STATUS_OK) { @@ -158,10 +147,6 @@ FS.prototype.HandleEvent = function(id) { { this.follow_fs(inode).HandleEvent(inode.foreign_id); } - if (!this.IsLoading()) { - this.OnLoaded(); - this.OnLoaded = function() {}; - } //message.Debug("number of events: " + this.events.length); var newevents = []; for(var i=0; i Date: Wed, 19 Sep 2018 16:12:36 -0500 Subject: [PATCH 1388/2137] Implement NetworkAdapter.change_proxy --- src/browser/network.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/browser/network.js b/src/browser/network.js index 1f793d50..e89341b3 100644 --- a/src/browser/network.js +++ b/src/browser/network.js @@ -13,8 +13,6 @@ */ function NetworkAdapter(url, bus) { - this.send_data = function(x) {}; - this.bus = bus; this.socket = undefined; @@ -133,3 +131,16 @@ NetworkAdapter.prototype.send = function(data) this.socket.send(data); } }; + +NetworkAdapter.prototype.change_proxy = function(url) +{ + this.url = url; + + if(this.socket) + { + this.socket.onclose = function() {}; + this.socket.onerror = function() {}; + this.socket.close(); + this.socket = undefined; + } +}; From 28a6f1a84a6f608a45f6f0194414588bd330257a Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 20 Sep 2018 13:22:03 -0500 Subject: [PATCH 1389/2137] Add pit.dump --- src/pit.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/pit.js b/src/pit.js index c52af5db..f5c62ef4 100644 --- a/src/pit.js +++ b/src/pit.js @@ -311,3 +311,10 @@ PIT.prototype.port43_write = function(reg_byte) this.counter_mode[i] = mode; this.counter_read_mode[i] = read_mode; }; + +PIT.prototype.dump = function() +{ + const reload = this.counter_reload[0]; + const time = (reload || 0x10000) / OSCILLATOR_FREQ; + dbg_log("counter0 ticks every " + time + "ms (reload=" + reload + ")"); +}; From a39d58d4e50c31ca93a2f0d06f16934bdd4b1626 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 20 Sep 2018 13:49:39 -0500 Subject: [PATCH 1390/2137] ne2k: Fix transfer of empty packet and start page after wrap-around --- src/ne2k.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ne2k.js b/src/ne2k.js index 7fda6aa7..c7b34d24 100644 --- a/src/ne2k.js +++ b/src/ne2k.js @@ -160,7 +160,7 @@ function Ne2k(cpu, bus) return; } - if((data_byte | 0x18) && this.rcnt === 0) + if((data_byte & 0x18) && this.rcnt === 0) { this.do_interrupt(ENISR_RDC); } @@ -699,7 +699,7 @@ Ne2k.prototype.receive = function(data) var cut = this.memory.length - data_start; this.memory.set(data.subarray(0, cut), data_start); - this.memory.set(data.subarray(cut), START_RX_PAGE); + this.memory.set(data.subarray(cut), this.pstart << 8); dbg_log("rcv cut=" + h(cut), LOG_NET); } else From 3b86889a99c8951835380fb5baae6d92e7dbd45d Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 1 Oct 2018 15:15:21 -0300 Subject: [PATCH 1391/2137] Throw proper error --- lib/jor1k.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/jor1k.js b/lib/jor1k.js index c195d7e6..d6852b0c 100644 --- a/lib/jor1k.js +++ b/lib/jor1k.js @@ -46,7 +46,7 @@ message.Abort = function() { if(DEBUG) { - throw "abort"; + throw new Error("message.Abort()"); } }; From fbdb4a28eab152a7d39e60bd4f67c10ba2a15837 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 1 Oct 2018 15:18:49 -0300 Subject: [PATCH 1392/2137] Remove all uses of "for in" --- lib/filesystem.js | 2 +- lib/marshall.js | 4 ++-- src/browser/lib.js | 12 ++++-------- src/elf.js | 2 +- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index f053cf81..604f452e 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -1241,7 +1241,7 @@ FS.prototype.NotifyListeners = function(id, action, info) { //if (this.watchFiles[path] == true && action=='write') { // message.Send("WatchFileEvent", path); //} - //for (var directory in this.watchDirectories) { + //for (var directory of this.watchDirectories) { // if (this.watchDirectories.hasOwnProperty(directory)) { // var indexOf = path.indexOf(directory) // if(indexOf == 0 || indexOf == 1) diff --git a/lib/marshall.js b/lib/marshall.js index 3de1d0e6..3a79de67 100644 --- a/lib/marshall.js +++ b/lib/marshall.js @@ -48,8 +48,8 @@ marshall.Marshall = function(typelist, input, struct, offset) { struct[offset++] = 0; // set the length later struct[offset++] = 0; size += 2; - for (var j in item) { - var utf8 = UnicodeToUTF8Stream(item.charCodeAt(j)); + for (var j of item) { + var utf8 = UnicodeToUTF8Stream(j.charCodeAt(0)); utf8.forEach( function(c) { struct[offset++] = c; size += 1; diff --git a/src/browser/lib.js b/src/browser/lib.js index 518e528e..0d47432f 100644 --- a/src/browser/lib.js +++ b/src/browser/lib.js @@ -527,17 +527,13 @@ var ASYNC_SAFE = false; AsyncXHRBuffer.prototype.get_written_blocks = function() { - var count = 0; - for(var _ in this.loaded_blocks) - { - count++; - } + var count = Object.keys(this.loaded_blocks).length; var buffer = new Uint8Array(count * this.block_size); var indices = []; var i = 0; - for(var index in this.loaded_blocks) + for(var index of Object.keys(this.loaded_blocks)) { var block = this.loaded_blocks[index]; dbg_assert(block.length === this.block_size); @@ -562,7 +558,7 @@ var ASYNC_SAFE = false; const state = []; const loaded_blocks = []; - for(let [index, block] in Object.values(this.loaded_blocks)) + for(let [index, block] of Object.values(this.loaded_blocks)) { dbg_assert(isFinite(+index)); loaded_blocks.push([+index, block]); @@ -575,7 +571,7 @@ var ASYNC_SAFE = false; { const loaded_blocks = state[0]; this.loaded_blocks = Object.create(null); - for(let [index, block] of loaded_blocks) + for(let [index, block] of Object.values(loaded_blocks)) { this.loaded_blocks[index] = block; } diff --git a/src/elf.js b/src/elf.js index d3b2bcdc..fed8eb17 100644 --- a/src/elf.js +++ b/src/elf.js @@ -104,7 +104,7 @@ function read_elf(buffer) if(DEBUG) { - for(let key in header) + for(let key of Object.keys(header)) { dbg_log(key + ": 0x" + header[key].toString(16)); } From dd929f52c540ea8761943eca81e0df8cca3ab53f Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 1 Oct 2018 18:43:07 -0300 Subject: [PATCH 1393/2137] 9p: Add create event, add file name to the read event --- lib/9p.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/9p.js b/lib/9p.js index 03dcd461..4a569025 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -406,6 +406,7 @@ Virtio9p.prototype.ReceiveRequest = async function (bufchain) { // jshint ignore var flags = req[2]; var mode = req[3]; var gid = req[4]; + this.bus.send("9p-create", [name, this.fids[fid].inodeid]); message.Debug("[create] fid=" + fid + ", name=" + name + ", flags=" + flags + ", mode=" + mode + ", gid=" + gid); var idx = this.fs.CreateFile(name, this.fids[fid].inodeid); this.fids[fid].inodeid = idx; @@ -589,13 +590,9 @@ Virtio9p.prototype.ReceiveRequest = async function (bufchain) { // jshint ignore this.BuildReply(id, tag, 4 + count); this.SendReply(bufchain); } else { - this.bus.send("9p-read-start"); - this.fs.OpenInode(this.fids[fid].inodeid, undefined); this.fs.AddEvent(this.fids[fid].inodeid, async function() { // jshint ignore:line - this.bus.send("9p-read-end", [this.fids[fid].dbg_name, count]); - const inodeid = this.fids[fid].inodeid; if (inode.size < offset+count) count = inode.size - offset; @@ -610,7 +607,13 @@ Virtio9p.prototype.ReceiveRequest = async function (bufchain) { // jshint ignore // See http://ericvh.github.io/9p-rfc/rfc9p2000.html#anchor30 count = 0; } + + this.bus.send("9p-read-start", [this.fids[fid].dbg_name]); + const data = await this.fs.Read(inodeid, offset, count); // jshint ignore:line + + this.bus.send("9p-read-end", [this.fids[fid].dbg_name, count]); + if(data) { this.replybuffer.set(data, 7 + 4); } From b83ed1b7c128fc4a0858ce0b696fca96621aca15 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 1 Oct 2018 18:48:15 -0300 Subject: [PATCH 1394/2137] Minor --- lib/9p.js | 2 +- src/browser/screen.js | 2 -- src/config.js | 2 +- src/rust/jit.rs | 2 +- tests/full/run.js | 2 +- tests/nasm/run.js | 1 - 6 files changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/9p.js b/lib/9p.js index 4a569025..4146bf22 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -374,8 +374,8 @@ Virtio9p.prototype.ReceiveRequest = async function (bufchain) { // jshint ignore case 22: // TREADLINK var req = marshall.Unmarshall(["w"], buffer, state); var fid = req[0]; - message.Debug("[readlink] fid=" + fid); var inode = this.fs.GetInode(this.fids[fid].inodeid); + message.Debug("[readlink] fid=" + fid + " name=" + this.fids[fid].dbg_name + " target=" + inode.symlink); size = marshall.Marshall(["s"], [inode.symlink], this.replybuffer, 7); this.BuildReply(id, tag, size); this.SendReply(bufchain); diff --git a/src/browser/screen.js b/src/browser/screen.js index 59928dc6..63a84040 100644 --- a/src/browser/screen.js +++ b/src/browser/screen.js @@ -505,5 +505,3 @@ function ScreenAdapter(screen_container, bus) this.init(); } - - diff --git a/src/config.js b/src/config.js index 831b1b17..75f096e8 100644 --- a/src/config.js +++ b/src/config.js @@ -10,7 +10,7 @@ var DEBUG = true; /** @const - * Also needs to be set in config.h + * Also needs to be set in cargo.toml */ var ENABLE_PROFILER = false; diff --git a/src/rust/jit.rs b/src/rust/jit.rs index a26d7865..bac0daa4 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -43,7 +43,7 @@ mod jit_cache_array { const NO_NEXT_ENTRY: u32 = 0xffff_ffff; pub const SIZE: u32 = 0x40000; - pub const MASK: u32 = (SIZE - 1); + pub const MASK: u32 = SIZE - 1; #[derive(Copy, Clone)] pub struct Entry { diff --git a/tests/full/run.js b/tests/full/run.js index 9337a735..317390c4 100755 --- a/tests/full/run.js +++ b/tests/full/run.js @@ -225,7 +225,7 @@ if(cluster.isMaster) { name: "Windows 3.0", skip_if_disk_image_missing: true, - timeout: 5 * 60, + timeout: 10 * 60, cdrom: root_path + "/../v86-images/os/Win30.iso", expected_texts: [ "Press any key to continue", diff --git a/tests/nasm/run.js b/tests/nasm/run.js index 56b75296..4bd78de0 100755 --- a/tests/nasm/run.js +++ b/tests/nasm/run.js @@ -287,7 +287,6 @@ else { // XXX: On gdb execution is stopped at this point. On v86 we // currently don't have this ability, so we record the exception // and continue execution - console.log("recorded", exception); recorded_exceptions.push(exception); return true; }; From 5bcee471caf650bff3984c64b6bbef74ef8e3244 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 1 Oct 2018 18:48:49 -0300 Subject: [PATCH 1395/2137] Remove old C code --- src/native/all.c | 0 src/native/arith.c | 1446 ------------ src/native/arith.h | 118 - src/native/call-indirect.ll | 12 - src/native/config.h | 18 - src/native/const.h | 150 -- src/native/cpu.c | 1900 --------------- src/native/cpu.h | 179 -- src/native/fpu.c | 803 ------- src/native/fpu.h | 91 - src/native/global_pointers.c | 94 - src/native/global_pointers.h | 96 - src/native/instructions.c | 1657 -------------- src/native/instructions.h | 896 -------- src/native/instructions_0f.c | 3940 -------------------------------- src/native/instructions_0f.h | 983 -------- src/native/js_imports.h | 58 - src/native/llvm-prof.ll | 18 - src/native/log.h | 15 - src/native/memory.c | 237 -- src/native/memory.h | 22 - src/native/misc_instr.c | 450 ---- src/native/misc_instr.h | 76 - src/native/modrm.c | 235 -- src/native/modrm.h | 7 - src/native/profiler/profiler.c | 53 - src/native/profiler/profiler.h | 69 - src/native/rust_imports.h | 17 - src/native/shared.c | 103 - src/native/shared.h | 23 - src/native/sse_instr.c | 446 ---- src/native/sse_instr.h | 38 - src/native/string.c | 1141 --------- src/native/string.h | 55 - 34 files changed, 15446 deletions(-) delete mode 100644 src/native/all.c delete mode 100644 src/native/arith.c delete mode 100644 src/native/arith.h delete mode 100644 src/native/call-indirect.ll delete mode 100644 src/native/config.h delete mode 100644 src/native/const.h delete mode 100644 src/native/cpu.c delete mode 100644 src/native/cpu.h delete mode 100644 src/native/fpu.c delete mode 100644 src/native/fpu.h delete mode 100644 src/native/global_pointers.c delete mode 100644 src/native/global_pointers.h delete mode 100644 src/native/instructions.c delete mode 100644 src/native/instructions.h delete mode 100644 src/native/instructions_0f.c delete mode 100644 src/native/instructions_0f.h delete mode 100644 src/native/js_imports.h delete mode 100644 src/native/llvm-prof.ll delete mode 100644 src/native/log.h delete mode 100644 src/native/memory.c delete mode 100644 src/native/memory.h delete mode 100644 src/native/misc_instr.c delete mode 100644 src/native/misc_instr.h delete mode 100644 src/native/modrm.c delete mode 100644 src/native/modrm.h delete mode 100644 src/native/profiler/profiler.c delete mode 100644 src/native/profiler/profiler.h delete mode 100644 src/native/rust_imports.h delete mode 100644 src/native/shared.c delete mode 100644 src/native/shared.h delete mode 100644 src/native/sse_instr.c delete mode 100644 src/native/sse_instr.h delete mode 100644 src/native/string.c delete mode 100644 src/native/string.h diff --git a/src/native/all.c b/src/native/all.c deleted file mode 100644 index e69de29b..00000000 diff --git a/src/native/arith.c b/src/native/arith.c deleted file mode 100644 index c1789bcc..00000000 --- a/src/native/arith.c +++ /dev/null @@ -1,1446 +0,0 @@ -#include -#include -#include - -#include "arith.h" -#include "const.h" -#include "cpu.h" -#include "global_pointers.h" -#include "js_imports.h" -#include "log.h" -#include "memory.h" -#include "misc_instr.h" - -int32_t add(int32_t dest_operand, int32_t source_operand, int32_t op_size) -{ - *last_op1 = dest_operand; - *last_op2 = source_operand; - int32_t res = dest_operand + source_operand; - *last_add_result = *last_result = res; - - *last_op_size = op_size; - *flags_changed = FLAGS_ALL; - - return res; -} - -int32_t adc(int32_t dest_operand, int32_t source_operand, int32_t op_size) -{ - int32_t cf = getcf(); - *last_op1 = dest_operand; - *last_op2 = source_operand; - - int32_t res = dest_operand + source_operand + cf; - - *last_add_result = *last_result = res; - - *last_op_size = op_size; - *flags_changed = FLAGS_ALL; - - return res; -} - -int32_t sub(int32_t dest_operand, int32_t source_operand, int32_t op_size) -{ - *last_add_result = dest_operand; - *last_op2 = source_operand; - - int32_t res = dest_operand - source_operand; - - *last_op1 = *last_result = res; - - *last_op_size = op_size; - *flags_changed = FLAGS_ALL; - - return res; -} - -int32_t sbb(int32_t dest_operand, int32_t source_operand, int32_t op_size) -{ - int32_t cf = getcf(); - *last_add_result = dest_operand; - *last_op2 = source_operand; - - int32_t res = dest_operand - source_operand - cf; - - *last_op1 = *last_result = res; - - *last_op_size = op_size; - *flags_changed = FLAGS_ALL; - - return res; -} - -int32_t add8(int32_t x, int32_t y) { return add(x, y, OPSIZE_8); } -int32_t add16(int32_t x, int32_t y) { return add(x, y, OPSIZE_16); } -int32_t add32(int32_t x, int32_t y) { return add(x, y, OPSIZE_32); } - -int32_t sub8(int32_t x, int32_t y) { return sub(x, y, OPSIZE_8); } -int32_t sub16(int32_t x, int32_t y) { return sub(x, y, OPSIZE_16); } -int32_t sub32(int32_t x, int32_t y) { return sub(x, y, OPSIZE_32); } - -int32_t adc8(int32_t x, int32_t y) { return adc(x, y, OPSIZE_8); } -int32_t adc16(int32_t x, int32_t y) { return adc(x, y, OPSIZE_16); } -int32_t adc32(int32_t x, int32_t y) { return adc(x, y, OPSIZE_32); } - -int32_t sbb8(int32_t x, int32_t y) { return sbb(x, y, OPSIZE_8); } -int32_t sbb16(int32_t x, int32_t y) { return sbb(x, y, OPSIZE_16); } -int32_t sbb32(int32_t x, int32_t y) { return sbb(x, y, OPSIZE_32); } - -void cmp8(int32_t x, int32_t y) { sub(x, y, OPSIZE_8); } -void cmp16(int32_t x, int32_t y) { sub(x, y, OPSIZE_16); } -void cmp32(int32_t x, int32_t y) { sub(x, y, OPSIZE_32); } - -int32_t inc(int32_t dest_operand, int32_t op_size) -{ - *flags = (*flags & ~1) | getcf(); - *last_op1 = dest_operand; - *last_op2 = 1; - - int32_t res = dest_operand + 1; - - *last_add_result = *last_result = res; - *last_op_size = op_size; - *flags_changed = FLAGS_ALL & ~1; - - return res; -} - -int32_t dec(int32_t dest_operand, int32_t op_size) -{ - *flags = (*flags & ~1) | getcf(); - *last_add_result = dest_operand; - *last_op2 = 1; - - int32_t res = dest_operand - 1; - - *last_op1 = *last_result = res; - *last_op_size = op_size; - *flags_changed = FLAGS_ALL & ~1; - - return res; -} - -int32_t inc8(int32_t x) { return inc(x, OPSIZE_8); } -int32_t inc16(int32_t x) { return inc(x, OPSIZE_16); } -int32_t inc32(int32_t x) { return inc(x, OPSIZE_32); } - -int32_t dec8(int32_t x) { return dec(x, OPSIZE_8); } -int32_t dec16(int32_t x) { return dec(x, OPSIZE_16); } -int32_t dec32(int32_t x) { return dec(x, OPSIZE_32); } - -int32_t neg(int32_t dest_operand, int32_t op_size) -{ - int32_t res = -dest_operand; - *last_op1 = *last_result = res; - *flags_changed = FLAGS_ALL; - *last_add_result = 0; - *last_op2 = dest_operand; - *last_op_size = op_size; - - return res; -} - -int32_t neg8(int32_t x) { return neg(x, OPSIZE_8); } -int32_t neg16(int32_t x) { return neg(x, OPSIZE_16); } -int32_t neg32(int32_t x) { return neg(x, OPSIZE_32); } - -void mul8(int32_t source_operand) -{ - int32_t result = source_operand * reg8[AL]; - - reg16[AX] = result; - *last_result = result & 0xFF; - *last_op_size = OPSIZE_8; - - if(result < 0x100) - { - *flags = *flags & ~1 & ~FLAG_OVERFLOW; - } - else - { - *flags = *flags | 1 | FLAG_OVERFLOW; - } - - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; -} - -void imul8(int32_t source_operand) -{ - int32_t result = source_operand * reg8s[AL]; - - reg16[AX] = result; - *last_result = result & 0xFF; - *last_op_size = OPSIZE_8; - - if(result > 0x7F || result < -0x80) - { - *flags = *flags | 1 | FLAG_OVERFLOW; - } - else - { - *flags = *flags & ~1 & ~FLAG_OVERFLOW; - } - - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; -} - -void mul16(uint32_t source_operand) -{ - uint32_t result = source_operand * reg16[AX]; - uint32_t high_result = result >> 16; - - - reg16[AX] = result; - reg16[DX] = high_result; - - *last_result = result & 0xFFFF; - *last_op_size = OPSIZE_16; - - if(high_result == 0) - { - *flags &= ~1 & ~FLAG_OVERFLOW; - } - else - { - *flags |= *flags | 1 | FLAG_OVERFLOW; - } - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; -} - -void imul16(int32_t source_operand) -{ - int32_t result = source_operand * reg16s[AX]; - - reg16[AX] = result; - reg16[DX] = result >> 16; - - *last_result = result & 0xFFFF; - *last_op_size = OPSIZE_16; - - if(result > 0x7FFF || result < -0x8000) - { - *flags |= 1 | FLAG_OVERFLOW; - } - else - { - *flags &= ~1 & ~FLAG_OVERFLOW; - } - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; -} - -int32_t imul_reg16(int32_t operand1, int32_t operand2) -{ - assert(operand1 < 0x8000 && operand1 >= -0x8000); - assert(operand2 < 0x8000 && operand2 >= -0x8000); - - int32_t result = operand1 * operand2; - - *last_result = result & 0xFFFF; - *last_op_size = OPSIZE_16; - - if(result > 0x7FFF || result < -0x8000) - { - *flags |= 1 | FLAG_OVERFLOW; - } - else - { - *flags &= ~1 & ~FLAG_OVERFLOW; - } - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; - - return result; -} - -void mul32(int32_t source_operand) -{ - int32_t dest_operand = reg32s[EAX]; - - 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] = result_low; - reg32s[EDX] = result_high; - - *last_result = result_low; - *last_op_size = OPSIZE_32; - - if(result_high == 0) - { - *flags &= ~1 & ~FLAG_OVERFLOW; - } - else - { - *flags |= 1 | FLAG_OVERFLOW; - } - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; -} - -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; - - reg32s[EAX] = result_low; - reg32s[EDX] = result_high; - - *last_result = result_low; - *last_op_size = OPSIZE_32; - - if(result_high == (result_low >> 31)) - { - *flags &= ~1 & ~FLAG_OVERFLOW; - } - else - { - *flags |= 1 | FLAG_OVERFLOW; - } - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; -} - -int32_t imul_reg32(int32_t operand1, int32_t operand2) -{ - int64_t result = (int64_t)operand1 * (int64_t)operand2; - int32_t result_low = result; - int32_t result_high = result >> 32; - - *last_result = result_low; - *last_op_size = OPSIZE_32; - - if(result_high == (result_low >> 31)) - { - *flags &= ~1 & ~FLAG_OVERFLOW; - } - else - { - *flags |= 1 | FLAG_OVERFLOW; - } - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; - - return result_low; -} - -int32_t xadd8(int32_t source_operand, int32_t reg) -{ - int32_t tmp = reg8[reg]; - - reg8[reg] = source_operand; - - return add(source_operand, tmp, OPSIZE_8); -} - -int32_t xadd16(int32_t source_operand, int32_t reg) -{ - int32_t tmp = reg16[reg]; - - reg16[reg] = source_operand; - - return add(source_operand, tmp, OPSIZE_16); -} - -int32_t xadd32(int32_t source_operand, int32_t reg) -{ - int32_t tmp = reg32s[reg]; - - reg32s[reg] = source_operand; - - return add(source_operand, tmp, OPSIZE_32); -} - -void bcd_daa() -{ - int32_t old_al = reg8[AL]; - int32_t old_cf = getcf(); - int32_t old_af = getaf(); - - *flags &= ~1 & ~FLAG_ADJUST; - - if((old_al & 0xF) > 9 || old_af) - { - reg8[AL] += 6; - *flags |= FLAG_ADJUST; - } - if(old_al > 0x99 || old_cf) - { - reg8[AL] += 0x60; - *flags |= 1; - } - - *last_result = reg8[AL]; - *last_op_size = OPSIZE_8; - *last_op1 = *last_op2 = 0; - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_ADJUST & ~FLAG_OVERFLOW; -} - -void bcd_das() -{ - int32_t old_al = reg8[AL]; - int32_t old_cf = getcf(); - - *flags &= ~1; - - if((old_al & 0xF) > 9 || getaf()) - { - reg8[AL] -= 6; - *flags |= FLAG_ADJUST; - *flags = *flags & ~1 | old_cf | (old_al < 6); - } - else - { - *flags &= ~FLAG_ADJUST; - } - - if(old_al > 0x99 || old_cf) - { - reg8[AL] -= 0x60; - *flags |= 1; - } - - *last_result = reg8[AL]; - *last_op_size = OPSIZE_8; - *last_op1 = *last_op2 = 0; - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_ADJUST & ~FLAG_OVERFLOW; -} - -void bcd_aad(int32_t imm8) -{ - int32_t result = reg8[AL] + reg8[AH] * imm8; - *last_result = result & 0xFF; - reg16[AX] = *last_result; - *last_op_size = OPSIZE_8; - - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_ADJUST & ~FLAG_OVERFLOW; - *flags &= ~1 & ~FLAG_ADJUST & ~FLAG_OVERFLOW; - - if(result > 0xFFFF) - { - *flags |= 1; - } -} - -void bcd_aaa() -{ - if((reg8[AL] & 0xF) > 9 || getaf()) - { - reg16[AX] += 6; - reg8[AH] += 1; - *flags |= FLAG_ADJUST | 1; - } - else - { - *flags &= ~FLAG_ADJUST & ~1; - } - reg8[AL] &= 0xF; - - *flags_changed &= ~FLAG_ADJUST & ~1; -} - -void bcd_aam(int32_t imm8) -{ - c_comment("ascii adjust after multiplication"); - - if(imm8 == 0) - { - trigger_de(); - } - else - { - uint8_t temp = reg8[AL]; - reg8[AH] = temp / imm8; - reg8[AL] = temp % imm8; - - *last_result = reg8[AL]; - - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_ADJUST & ~FLAG_OVERFLOW; - *flags &= ~1 & ~FLAG_ADJUST & ~FLAG_OVERFLOW; - } -} - -void bcd_aas() -{ - if((reg8[AL] & 0xF) > 9 || getaf()) - { - reg16[AX] -= 6; - reg8[AH] -= 1; - *flags |= FLAG_ADJUST | 1; - } - else - { - *flags &= ~FLAG_ADJUST & ~1; - } - reg8[AL] &= 0xF; - - *flags_changed &= ~FLAG_ADJUST & ~1; -} - -int32_t and(int32_t dest_operand, int32_t source_operand, int32_t op_size) -{ - *last_result = dest_operand & source_operand; - - *last_op_size = op_size; - *flags &= ~1 & ~FLAG_OVERFLOW & ~FLAG_ADJUST; - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW & ~FLAG_ADJUST; - - return *last_result; -} - -int32_t or(int32_t dest_operand, int32_t source_operand, int32_t op_size) -{ - *last_result = dest_operand | source_operand; - - *last_op_size = op_size; - *flags &= ~1 & ~FLAG_OVERFLOW & ~FLAG_ADJUST; - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW & ~FLAG_ADJUST; - - return *last_result; -} - -int32_t xor(int32_t dest_operand, int32_t source_operand, int32_t op_size) -{ - *last_result = dest_operand ^ source_operand; - - *last_op_size = op_size; - *flags &= ~1 & ~FLAG_OVERFLOW & ~FLAG_ADJUST; - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW & ~FLAG_ADJUST; - - return *last_result; -} - -int32_t and8(int32_t x, int32_t y) { return and(x, y, OPSIZE_8); } -int32_t and16(int32_t x, int32_t y) { return and(x, y, OPSIZE_16); } -int32_t and32(int32_t x, int32_t y) { return and(x, y, OPSIZE_32); } - -void test8(int32_t x, int32_t y) { and(x, y, OPSIZE_8); } -void test16(int32_t x, int32_t y) { and(x, y, OPSIZE_16); } -void test32(int32_t x, int32_t y) { and(x, y, OPSIZE_32); } - -int32_t or8(int32_t x, int32_t y) { return or(x, y, OPSIZE_8); } -int32_t or16(int32_t x, int32_t y) { return or(x, y, OPSIZE_16); } -int32_t or32(int32_t x, int32_t y) { return or(x, y, OPSIZE_32); } - -int32_t xor8(int32_t x, int32_t y) { return xor(x, y, OPSIZE_8); } -int32_t xor16(int32_t x, int32_t y) { return xor(x, y, OPSIZE_16); } -int32_t xor32(int32_t x, int32_t y) { return xor(x, y, OPSIZE_32); } - -int32_t rol8(int32_t dest_operand, int32_t count) -{ - if(!count) - { - return dest_operand; - } - count &= 7; - - int32_t result = dest_operand << count | dest_operand >> (8 - count); - - *flags_changed &= ~1 & ~FLAG_OVERFLOW; - *flags = (*flags & ~1 & ~FLAG_OVERFLOW) - | (result & 1) - | (result << 11 ^ result << 4) & FLAG_OVERFLOW; - - return result; -} - -int32_t rol16(int32_t dest_operand, int32_t count) -{ - if(!count) - { - return dest_operand; - } - count &= 15; - - int32_t result = dest_operand << count | dest_operand >> (16 - count); - - *flags_changed &= ~1 & ~FLAG_OVERFLOW; - *flags = (*flags & ~1 & ~FLAG_OVERFLOW) - | (result & 1) - | (result << 11 ^ result >> 4) & FLAG_OVERFLOW; - - return result; -} - -int32_t rol32(int32_t dest_operand, int32_t count) -{ - if(!count) - { - return dest_operand; - } - - int32_t result = dest_operand << count | ((uint32_t) dest_operand) >> (32 - count); - - *flags_changed &= ~1 & ~FLAG_OVERFLOW; - *flags = (*flags & ~1 & ~FLAG_OVERFLOW) - | (result & 1) - | (result << 11 ^ result >> 20) & FLAG_OVERFLOW; - - return result; -} - -int32_t rcl8(int32_t dest_operand, int32_t count) -{ - count %= 9; - if(!count) - { - return dest_operand; - } - - int32_t result = dest_operand << count | getcf() << (count - 1) | dest_operand >> (9 - count); - - *flags_changed &= ~1 & ~FLAG_OVERFLOW; - *flags = (*flags & ~1 & ~FLAG_OVERFLOW) - | (result >> 8 & 1) - | (result << 3 ^ result << 4) & FLAG_OVERFLOW; - - return result; -} - -int32_t rcl16(int32_t dest_operand, int32_t count) -{ - count %= 17; - if(!count) - { - return dest_operand; - } - - int32_t result = dest_operand << count | getcf() << (count - 1) | dest_operand >> (17 - count); - - *flags_changed &= ~1 & ~FLAG_OVERFLOW; - *flags = (*flags & ~1 & ~FLAG_OVERFLOW) - | (result >> 16 & 1) - | (result >> 5 ^ result >> 4) & FLAG_OVERFLOW; - - return result; -} - -int32_t rcl32(int32_t dest_operand, int32_t count) -{ - if(!count) - { - return dest_operand; - } - - int32_t result = dest_operand << count | getcf() << (count - 1); - - if(count > 1) - { - result |= ((uint32_t) dest_operand) >> (33 - count); - } - - *flags_changed &= ~1 & ~FLAG_OVERFLOW; - *flags = (*flags & ~1 & ~FLAG_OVERFLOW) | (((uint32_t) dest_operand) >> (32 - count) & 1); - *flags |= (*flags << 11 ^ result >> 20) & FLAG_OVERFLOW; - - return result; -} - -int32_t ror8(int32_t dest_operand, int32_t count) -{ - if(!count) - { - return dest_operand; - } - - count &= 7; - int32_t result = dest_operand >> count | dest_operand << (8 - count); - - *flags_changed &= ~1 & ~FLAG_OVERFLOW; - *flags = (*flags & ~1 & ~FLAG_OVERFLOW) - | (result >> 7 & 1) - | (result << 4 ^ result << 5) & FLAG_OVERFLOW; - - return result; -} - -int32_t ror16(int32_t dest_operand, int32_t count) -{ - if(!count) - { - return dest_operand; - } - - count &= 15; - int32_t result = dest_operand >> count | dest_operand << (16 - count); - - *flags_changed &= ~1 & ~FLAG_OVERFLOW; - *flags = (*flags & ~1 & ~FLAG_OVERFLOW) - | (result >> 15 & 1) - | (result >> 4 ^ result >> 3) & FLAG_OVERFLOW; - - return result; -} - -int32_t ror32(int32_t dest_operand, int32_t count) -{ - if(!count) - { - return dest_operand; - } - - int32_t result = ((uint32_t) dest_operand) >> count | dest_operand << (32 - count); - - *flags_changed &= ~1 & ~FLAG_OVERFLOW; - *flags = (*flags & ~1 & ~FLAG_OVERFLOW) - | (result >> 31 & 1) - | (result >> 20 ^ result >> 19) & FLAG_OVERFLOW; - - return result; -} - -int32_t rcr8(int32_t dest_operand, int32_t count) -{ - count %= 9; - if(!count) - { - return dest_operand; - } - - int32_t result = dest_operand >> count | getcf() << (8 - count) | dest_operand << (9 - count); - - *flags_changed &= ~1 & ~FLAG_OVERFLOW; - *flags = (*flags & ~1 & ~FLAG_OVERFLOW) - | (result >> 8 & 1) - | (result << 4 ^ result << 5) & FLAG_OVERFLOW; - - return result; -} - -int32_t rcr16(int32_t dest_operand, int32_t count) -{ - count %= 17; - if(!count) - { - return dest_operand; - } - - int32_t result = dest_operand >> count | getcf() << (16 - count) | dest_operand << (17 - count); - - *flags_changed &= ~1 & ~FLAG_OVERFLOW; - *flags = (*flags & ~1 & ~FLAG_OVERFLOW) - | (result >> 16 & 1) - | (result >> 4 ^ result >> 3) & FLAG_OVERFLOW; - - return result; -} - -int32_t rcr32(int32_t dest_operand, int32_t count) -{ - if(!count) - { - return dest_operand; - } - - int32_t result = ((uint32_t) dest_operand) >> count | getcf() << (32 - count); - - if(count > 1) - { - result |= dest_operand << (33 - count); - } - - *flags_changed &= ~1 & ~FLAG_OVERFLOW; - *flags = (*flags & ~1 & ~FLAG_OVERFLOW) - | (dest_operand >> (count - 1) & 1) - | (result >> 20 ^ result >> 19) & FLAG_OVERFLOW; - - return result; -} - -void div8(uint32_t source_operand) -{ - if(source_operand == 0) - { - trigger_de(); - return; - } - - uint16_t target_operand = reg16[AX]; - uint16_t result = target_operand / source_operand; - - if(result >= 0x100) - { - trigger_de(); - } - else - { - reg8[AL] = result; - reg8[AH] = target_operand % source_operand; - } -} - -void idiv8(int32_t source_operand) -{ - if(source_operand == 0) - { - trigger_de(); - return; - } - - int32_t target_operand = reg16s[AX]; - int32_t result = target_operand / source_operand; - - if(result >= 0x80 || result <= -0x81) - { - trigger_de(); - } - else - { - reg8[AL] = result; - reg8[AH] = target_operand % source_operand; - } -} - -void div16(uint32_t source_operand) -{ - if(source_operand == 0) - { - trigger_de(); - return; - } - - uint32_t target_operand = reg16[AX] | reg16[DX] << 16; - uint32_t result = target_operand / source_operand; - - if(result >= 0x10000) - { - trigger_de(); - } - else - { - reg16[AX] = result; - reg16[DX] = target_operand % source_operand; - } -} - -void idiv16(int32_t source_operand) -{ - if(source_operand == 0) - { - trigger_de(); - return; - } - - int32_t target_operand = reg16[AX] | (reg16[DX] << 16); - int32_t result = target_operand / source_operand; - - if(result >= 0x8000 || result <= -0x8001) - { - trigger_de(); - } - else - { - reg16[AX] = result; - reg16[DX] = target_operand % source_operand; - } -} - -void div32(uint32_t source_operand) -{ - if(source_operand == 0) - { - trigger_de(); - return; - } - - uint32_t target_low = reg32s[EAX]; - uint32_t target_high = reg32s[EDX]; - - uint64_t target_operand = (((uint64_t) target_high) << 32) | ((uint64_t) target_low); - uint64_t result = target_operand / source_operand; - if(result > UINT32_MAX) - { - trigger_de(); - return; - } - - int32_t mod = target_operand % source_operand; - - reg32s[EAX] = result; - reg32s[EDX] = mod; -} - -void idiv32(int32_t source_operand) -{ - if(source_operand == 0) - { - trigger_de(); - return; - } - - uint32_t target_low = reg32s[EAX]; - uint32_t target_high = reg32s[EDX]; - - int64_t target_operand = (((uint64_t) target_high) << 32) | ((uint64_t) target_low); - - if(source_operand == -1 && target_operand == INT64_MIN) - { - trigger_de(); - return; - } - - int64_t result = target_operand / source_operand; - if(result < INT32_MIN || result > INT32_MAX) - { - trigger_de(); - return; - } - - int32_t mod = target_operand % source_operand; - - reg32s[EAX] = result; - reg32s[EDX] = mod; -} - -int32_t shl8(int32_t dest_operand, int32_t count) -{ - if(count == 0) - { - return dest_operand; - } - - *last_result = dest_operand << count; - - *last_op_size = OPSIZE_8; - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; - *flags = (*flags & ~1 & ~FLAG_OVERFLOW) - | (*last_result >> 8 & 1) - | (*last_result << 3 ^ *last_result << 4) & FLAG_OVERFLOW; - - return *last_result; -} - -int32_t shl16(int32_t dest_operand, int32_t count) -{ - if(count == 0) - { - return dest_operand; - } - - *last_result = dest_operand << count; - - *last_op_size = OPSIZE_16; - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; - *flags = (*flags & ~1 & ~FLAG_OVERFLOW) - | (*last_result >> 16 & 1) - | (*last_result >> 5 ^ *last_result >> 4) & FLAG_OVERFLOW; - - return *last_result; -} - -int32_t shl32(int32_t dest_operand, int32_t count) -{ - if(count == 0) - { - return dest_operand; - } - - *last_result = dest_operand << count; - - *last_op_size = OPSIZE_32; - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; - c_comment("test this"); - *flags = (*flags & ~1 & ~FLAG_OVERFLOW) | (dest_operand >> (32 - count) & 1); - *flags |= ((*flags & 1) ^ (*last_result >> 31 & 1)) << 11 & FLAG_OVERFLOW; - - return *last_result; -} - -int32_t shr8(int32_t dest_operand, int32_t count) -{ - if(count == 0) - { - return dest_operand; - } - - *last_result = dest_operand >> count; - - *last_op_size = OPSIZE_8; - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; - *flags = (*flags & ~1 & ~FLAG_OVERFLOW) - | (dest_operand >> (count - 1) & 1) - | (dest_operand >> 7 & 1) << 11 & FLAG_OVERFLOW; - - return *last_result; -} - -int32_t shr16(int32_t dest_operand, int32_t count) -{ - if(count == 0) - { - return dest_operand; - } - - *last_result = dest_operand >> count; - - *last_op_size = OPSIZE_16; - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; - *flags = (*flags & ~1 & ~FLAG_OVERFLOW) - | (dest_operand >> (count - 1) & 1) - | (dest_operand >> 4) & FLAG_OVERFLOW; - - return *last_result; -} - -int32_t shr32(int32_t dest_operand, int32_t count) -{ - if(count == 0) - { - return dest_operand; - } - - *last_result = ((uint32_t) dest_operand) >> count; - - *last_op_size = OPSIZE_32; - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; - *flags = (*flags & ~1 & ~FLAG_OVERFLOW) - | (((uint32_t) dest_operand) >> (count - 1) & 1) - | (dest_operand >> 20) & FLAG_OVERFLOW; - - return *last_result; -} - -int32_t sar8(int32_t dest_operand, int32_t count) -{ - if(count == 0) - { - return dest_operand; - } - - if(count < 8) - { - *last_result = dest_operand << 24 >> (count + 24); - c_comment("of is zero"); - *flags = (*flags & ~1 & ~FLAG_OVERFLOW) | (dest_operand >> (count - 1) & 1); - } - else - { - *last_result = dest_operand << 24 >> 31; - *flags = (*flags & ~1 & ~FLAG_OVERFLOW) | (*last_result & 1); - } - - *last_op_size = OPSIZE_8; - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; - - return *last_result; -} - -int32_t sar16(int32_t dest_operand, int32_t count) -{ - if(count == 0) - { - return dest_operand; - } - - if(count < 16) - { - *last_result = dest_operand << 16 >> (count + 16); - *flags = (*flags & ~1 & ~FLAG_OVERFLOW) | (dest_operand >> (count - 1) & 1); - } - else - { - *last_result = dest_operand << 16 >> 31; - *flags = (*flags & ~1 & ~FLAG_OVERFLOW) | (*last_result & 1); - } - - *last_op_size = OPSIZE_16; - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; - - return *last_result; -} - -int32_t sar32(int32_t dest_operand, int32_t count) -{ - if(count == 0) - { - return dest_operand; - } - - *last_result = dest_operand >> count; - - *last_op_size = OPSIZE_32; - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; - *flags = (*flags & ~1 & ~FLAG_OVERFLOW) | (((uint32_t) dest_operand) >> (count - 1) & 1); - - return *last_result; -} - -int32_t shrd16(int32_t dest_operand, int32_t source_operand, int32_t count) -{ - if(count == 0) - { - return dest_operand; - } - - if(count <= 16) - { - *last_result = dest_operand >> count | source_operand << (16 - count); - *flags = (*flags & ~1) | (dest_operand >> (count - 1) & 1); - } - else - { - *last_result = dest_operand << (32 - count) | source_operand >> (count - 16); - *flags = (*flags & ~1) | (source_operand >> (count - 17) & 1); - } - - *last_op_size = OPSIZE_16; - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; - *flags = (*flags & ~FLAG_OVERFLOW) | ((*last_result ^ dest_operand) >> 4 & FLAG_OVERFLOW); - - return *last_result; -} - -int32_t shrd32(int32_t dest_operand, int32_t source_operand, int32_t count) -{ - if(count == 0) - { - return dest_operand; - } - - *last_result = ((uint32_t) dest_operand) >> count | source_operand << (32 - count); - - *last_op_size = OPSIZE_32; - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; - *flags = (*flags & ~1) | (((uint32_t) dest_operand) >> (count - 1) & 1); - *flags = (*flags & ~FLAG_OVERFLOW) | ((*last_result ^ dest_operand) >> 20 & FLAG_OVERFLOW); - - return *last_result; -} - -int32_t shld16(int32_t dest_operand, int32_t source_operand, int32_t count) -{ - if(count == 0) - { - return dest_operand; - } - - if(count <= 16) - { - *last_result = dest_operand << count | ((uint32_t) source_operand) >> (16 - count); - *flags = (*flags & ~1) | (((uint32_t) dest_operand) >> (16 - count) & 1); - } - else - { - *last_result = dest_operand >> (32 - count) | source_operand << (count - 16); - *flags = (*flags & ~1) | (((uint32_t) source_operand) >> (32 - count) & 1); - } - - *last_op_size = OPSIZE_16; - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; - *flags = (*flags & ~FLAG_OVERFLOW) | ((*flags & 1) ^ (*last_result >> 15 & 1)) << 11; - - return *last_result; -} - -int32_t shld32(int32_t dest_operand, int32_t source_operand, int32_t count) -{ - if(count == 0) - { - return dest_operand; - } - - *last_result = dest_operand << count | ((uint32_t) source_operand) >> (32 - count); - - *last_op_size = OPSIZE_32; - *flags_changed = FLAGS_ALL & ~1 & ~FLAG_OVERFLOW; - *flags = (*flags & ~1) | (((uint32_t) dest_operand) >> (32 - count) & 1); - - if(count == 1) - { - *flags = (*flags & ~FLAG_OVERFLOW) | ((*flags & 1) ^ (*last_result >> 31 & 1)) << 11; - } - else - { - *flags &= ~FLAG_OVERFLOW; - } - - return *last_result; -} - -void bt_reg(int32_t bit_base, int32_t bit_offset) -{ - *flags = (*flags & ~1) | (bit_base >> bit_offset & 1); - *flags_changed &= ~1; -} - -int32_t btc_reg(int32_t bit_base, int32_t bit_offset) -{ - *flags = (*flags & ~1) | (bit_base >> bit_offset & 1); - *flags_changed &= ~1; - - return bit_base ^ 1 << bit_offset; -} - -int32_t bts_reg(int32_t bit_base, int32_t bit_offset) -{ - *flags = (*flags & ~1) | (bit_base >> bit_offset & 1); - *flags_changed &= ~1; - - return bit_base | 1 << bit_offset; -} - -int32_t btr_reg(int32_t bit_base, int32_t bit_offset) -{ - *flags = (*flags & ~1) | (bit_base >> bit_offset & 1); - *flags_changed &= ~1; - - return bit_base & ~(1 << bit_offset); -} - -void bt_mem(int32_t virt_addr, int32_t bit_offset) -{ - int32_t bit_base = safe_read8(virt_addr + (bit_offset >> 3)); - bit_offset &= 7; - - *flags = (*flags & ~1) | (bit_base >> bit_offset & 1); - *flags_changed &= ~1; -} - -void btc_mem(int32_t virt_addr, int32_t bit_offset) -{ - int32_t phys_addr = translate_address_write(virt_addr + (bit_offset >> 3)); - int32_t bit_base = read8(phys_addr); - - bit_offset &= 7; - - *flags = (*flags & ~1) | (bit_base >> bit_offset & 1); - *flags_changed &= ~1; - - write8(phys_addr, bit_base ^ 1 << 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)); - int32_t bit_base = read8(phys_addr); - - bit_offset &= 7; - - *flags = (*flags & ~1) | (bit_base >> bit_offset & 1); - *flags_changed &= ~1; - - write8(phys_addr, bit_base & ~(1 << 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)); - int32_t bit_base = read8(phys_addr); - - bit_offset &= 7; - - *flags = (*flags & ~1) | (bit_base >> bit_offset & 1); - *flags_changed &= ~1; - - write8(phys_addr, bit_base | 1 << bit_offset); -} - -int32_t bsf16(int32_t old, int32_t bit_base) -{ - *flags_changed = FLAGS_ALL & ~FLAG_ZERO; - *last_op_size = OPSIZE_16; - - if(bit_base == 0) - { - *flags |= FLAG_ZERO; - *last_result = bit_base; - - c_comment("not defined in the docs, but value doesn't change on my intel machine"); - return old; - } - else - { - *flags &= ~FLAG_ZERO; - - return *last_result = int_log2(-bit_base & bit_base); - } -} - -int32_t bsf32(int32_t old, int32_t bit_base) -{ - *flags_changed = FLAGS_ALL & ~FLAG_ZERO; - *last_op_size = OPSIZE_32; - - if(bit_base == 0) - { - *flags |= FLAG_ZERO; - *last_result = bit_base; - - return old; - } - else - { - *flags &= ~FLAG_ZERO; - - return *last_result = int_log2(((uint32_t) (-bit_base & bit_base))); - } -} - -int32_t bsr16(int32_t old, int32_t bit_base) -{ - *flags_changed = FLAGS_ALL & ~FLAG_ZERO; - *last_op_size = OPSIZE_16; - - if(bit_base == 0) - { - *flags |= FLAG_ZERO; - *last_result = bit_base; - - return old; - } - else - { - *flags &= ~FLAG_ZERO; - - return *last_result = int_log2(bit_base); - } -} - -int32_t bsr32(int32_t old, int32_t bit_base) -{ - *flags_changed = FLAGS_ALL & ~FLAG_ZERO; - *last_op_size = OPSIZE_32; - - if(bit_base == 0) - { - *flags |= FLAG_ZERO; - *last_result = bit_base; - - return old; - } - else - { - *flags &= ~FLAG_ZERO; - return *last_result = int_log2(((uint32_t) bit_base)); - } -} - -int32_t popcnt(int32_t v) -{ - *flags_changed = 0; - *flags &= ~FLAGS_ALL; - - if(v) - { - c_comment("http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel"); - v = v - ((v >> 1) & 0x55555555); - v = (v & 0x33333333) + ((v >> 2) & 0x33333333); - return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; - } - else - { - *flags |= FLAG_ZERO; - return 0; - } -} - -uint32_t saturate_sw_to_ub(uint32_t v) -{ - dbg_assert((v & 0xFFFF0000) == 0); - - uint32_t ret = v; - if (ret >= 0x8000) { - ret = 0; - } - else if (ret > 0xFF) { - ret = 0xFF; - } - - dbg_assert((ret & 0xFFFFFF00) == 0); - return ret; -} - -int32_t saturate_sw_to_sb(int32_t v) -{ - dbg_assert((v & 0xFFFF0000) == 0); - - int32_t ret = v; - - if (ret > 0xFF80) { - ret = ret & 0xFF; - } - else if (ret > 0x7FFF) { - ret = 0x80; - } - else if (ret > 0x7F) { - ret = 0x7F; - } - - dbg_assert((ret & 0xFFFFFF00) == 0); - return ret; -} - -uint32_t saturate_sd_to_sw(uint32_t v) -{ - uint32_t ret = v; - - if (ret > 0xFFFF8000) { - ret = ret & 0xFFFF; - } - else if (ret > 0x7FFFFFFF) { - ret = 0x8000; - } - else if (ret > 0x7FFF) { - ret = 0x7FFF; - } - - dbg_assert((ret & 0xFFFF0000) == 0); - return ret; -} - -uint32_t saturate_sd_to_sb(uint32_t v) -{ - uint32_t ret = v; - - if (ret > 0xFFFFFF80) { - ret = ret & 0xFF; - } - else if (ret > 0x7FFFFFFF) { - ret = 0x80; - } - else if (ret > 0x7F) { - ret = 0x7F; - } - - dbg_assert((ret & 0xFFFFFF00) == 0); - return ret; -} - -int32_t saturate_sd_to_ub(int32_t v) -{ - int32_t ret = v; - - if (ret < 0) { - ret = 0; - } - - dbg_assert((ret & 0xFFFFFF00) == 0); - return ret; -} - -uint32_t saturate_ud_to_ub(uint32_t v) -{ - uint32_t ret = v; - - if (ret > 0xFF) { - ret = 0xFF; - } - - dbg_assert((ret & 0xFFFFFF00) == 0); - return ret; -} - -int32_t saturate_uw(uint32_t v) -{ - uint32_t ret = v; - if(ret > 0x7FFFFFFF) - { - ret = 0; - } - else if(ret > 0xFFFF) - { - ret = 0xFFFF; - } - - dbg_assert((ret & 0xFFFF0000) == 0); - return ret; -} diff --git a/src/native/arith.h b/src/native/arith.h deleted file mode 100644 index 8d9c0b78..00000000 --- a/src/native/arith.h +++ /dev/null @@ -1,118 +0,0 @@ -#pragma once - -#include - -int32_t add(int32_t dest_operand, int32_t source_operand, int32_t op_size); -int32_t adc(int32_t dest_operand, int32_t source_operand, int32_t op_size); -int32_t sub(int32_t dest_operand, int32_t source_operand, int32_t op_size); -int32_t sbb(int32_t dest_operand, int32_t source_operand, int32_t op_size); -int32_t add8(int32_t x, int32_t y); -int32_t add16(int32_t x, int32_t y); -int32_t add32(int32_t x, int32_t y); -int32_t sub8(int32_t x, int32_t y); -int32_t sub16(int32_t x, int32_t y); -int32_t sub32(int32_t x, int32_t y); -int32_t adc8(int32_t x, int32_t y); -int32_t adc16(int32_t x, int32_t y); -int32_t adc32(int32_t x, int32_t y); -int32_t sbb8(int32_t x, int32_t y); -int32_t sbb16(int32_t x, int32_t y); -int32_t sbb32(int32_t x, int32_t y); -void cmp8(int32_t x, int32_t y); -void cmp16(int32_t x, int32_t y); -void cmp32(int32_t x, int32_t y); -int32_t inc(int32_t dest_operand, int32_t op_size); -int32_t dec(int32_t dest_operand, int32_t op_size); -int32_t inc8(int32_t x); -int32_t inc16(int32_t x); -int32_t inc32(int32_t x); -int32_t dec8(int32_t x); -int32_t dec16(int32_t x); -int32_t dec32(int32_t x); -int32_t neg(int32_t dest_operand, int32_t op_size); -int32_t neg8(int32_t x); -int32_t neg16(int32_t x); -int32_t neg32(int32_t x); -void mul8(int32_t source_operand); -void imul8(int32_t source_operand); -void mul16(uint32_t source_operand); -void imul16(int32_t source_operand); -int32_t imul_reg16(int32_t operand1, int32_t operand2); -void mul32(int32_t source_operand); -void imul32(int32_t source_operand); -int32_t imul_reg32(int32_t operand1, int32_t operand2); -int32_t xadd8(int32_t source_operand, int32_t reg); -int32_t xadd16(int32_t source_operand, int32_t reg); -int32_t xadd32(int32_t source_operand, int32_t reg); -void bcd_daa(void); -void bcd_das(void); -void bcd_aad(int32_t imm8); -void bcd_aam(int32_t imm8); -void bcd_aaa(void); -void bcd_aas(void); -int32_t and(int32_t dest_operand, int32_t source_operand, int32_t op_size); -int32_t or(int32_t dest_operand, int32_t source_operand, int32_t op_size); -int32_t xor(int32_t dest_operand, int32_t source_operand, int32_t op_size); -int32_t and8(int32_t x, int32_t y); -int32_t and16(int32_t x, int32_t y); -int32_t and32(int32_t x, int32_t y); -void test8(int32_t x, int32_t y); -void test16(int32_t x, int32_t y); -void test32(int32_t x, int32_t y); -int32_t or8(int32_t x, int32_t y); -int32_t or16(int32_t x, int32_t y); -int32_t or32(int32_t x, int32_t y); -int32_t xor8(int32_t x, int32_t y); -int32_t xor16(int32_t x, int32_t y); -int32_t xor32(int32_t x, int32_t y); -int32_t rol8(int32_t dest_operand, int32_t count); -int32_t rol16(int32_t dest_operand, int32_t count); -int32_t rol32(int32_t dest_operand, int32_t count); -int32_t rcl8(int32_t dest_operand, int32_t count); -int32_t rcl16(int32_t dest_operand, int32_t count); -int32_t rcl32(int32_t dest_operand, int32_t count); -int32_t ror8(int32_t dest_operand, int32_t count); -int32_t ror16(int32_t dest_operand, int32_t count); -int32_t ror32(int32_t dest_operand, int32_t count); -int32_t rcr8(int32_t dest_operand, int32_t count); -int32_t rcr16(int32_t dest_operand, int32_t count); -int32_t rcr32(int32_t dest_operand, int32_t count); -void div8(uint32_t source_operand); -void idiv8(int32_t source_operand); -void div16(uint32_t source_operand); -void idiv16(int32_t source_operand); -void div32(uint32_t source_operand); -void idiv32(int32_t source_operand); -int32_t shl8(int32_t dest_operand, int32_t count); -int32_t shl16(int32_t dest_operand, int32_t count); -int32_t shl32(int32_t dest_operand, int32_t count); -int32_t shr8(int32_t dest_operand, int32_t count); -int32_t shr16(int32_t dest_operand, int32_t count); -int32_t shr32(int32_t dest_operand, int32_t count); -int32_t sar8(int32_t dest_operand, int32_t count); -int32_t sar16(int32_t dest_operand, int32_t count); -int32_t sar32(int32_t dest_operand, int32_t count); -int32_t shrd16(int32_t dest_operand, int32_t source_operand, int32_t count); -int32_t shrd32(int32_t dest_operand, int32_t source_operand, int32_t count); -int32_t shld16(int32_t dest_operand, int32_t source_operand, int32_t count); -int32_t shld32(int32_t dest_operand, int32_t source_operand, int32_t count); -void bt_reg(int32_t bit_base, int32_t bit_offset); -int32_t btc_reg(int32_t bit_base, int32_t bit_offset); -int32_t bts_reg(int32_t bit_base, int32_t bit_offset); -int32_t btr_reg(int32_t bit_base, int32_t bit_offset); -void bt_mem(int32_t virt_addr, int32_t bit_offset); -void btc_mem(int32_t virt_addr, int32_t bit_offset); -void btr_mem(int32_t virt_addr, int32_t bit_offset); -void bts_mem(int32_t virt_addr, int32_t bit_offset); -int32_t bsf16(int32_t old, int32_t bit_base); -int32_t bsf32(int32_t old, int32_t bit_base); -int32_t bsr16(int32_t old, int32_t bit_base); -int32_t bsr32(int32_t old, int32_t bit_base); -int32_t popcnt(int32_t v); -uint32_t saturate_sw_to_ub(uint32_t v); -int32_t saturate_sw_to_sb(int32_t v); -uint32_t saturate_sd_to_sw(uint32_t v); -uint32_t saturate_sd_to_sb(uint32_t v); -int32_t saturate_sd_to_ub(int32_t v); -uint32_t saturate_ud_to_ub(uint32_t v); -int32_t saturate_uw(uint32_t v); diff --git a/src/native/call-indirect.ll b/src/native/call-indirect.ll deleted file mode 100644 index 11b2880e..00000000 --- a/src/native/call-indirect.ll +++ /dev/null @@ -1,12 +0,0 @@ -target datalayout = "e-p:32:32-i64:64-v128:32:128-n32-S128" -target triple = "asmjs-unknown-emscripten" - -define void @call_indirect(void ()* %callee) { - call void %callee() - ret void -} - -define void @call_indirect1(void (i32)* %callee, i32 %arg) { - call void %callee(i32 %arg) - ret void -} diff --git a/src/native/config.h b/src/native/config.h deleted file mode 100644 index 1a60db6b..00000000 --- a/src/native/config.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -/** - * How many cycles the CPU does at a time before running hardware timers - */ -//#define LOOP_COUNTER 20011 - -//#define TSC_RATE (50 * 1000) - - -#define ENABLE_PROFILER 1 -#define ENABLE_PROFILER_OPSTATS 1 -#define ENABLE_PROFILER_SAFE_READ_WRITE 1 - -// Note: needs to be enabled here and in config.js -#define DUMP_UNCOMPILED_ASSEMBLY 0 - -//#define LOG_PAGE_FAULTS 0 diff --git a/src/native/const.h b/src/native/const.h deleted file mode 100644 index b3e3432d..00000000 --- a/src/native/const.h +++ /dev/null @@ -1,150 +0,0 @@ -#pragma once - -#include - -extern const int32_t FLAG_CARRY; -extern const int32_t FLAG_PARITY; -extern const int32_t FLAG_ADJUST; -extern const int32_t FLAG_ZERO; -extern const int32_t FLAG_SIGN; -extern const int32_t FLAG_TRAP; -extern const int32_t FLAG_INTERRUPT; -extern const int32_t FLAG_DIRECTION; -extern const int32_t FLAG_OVERFLOW; -extern const int32_t FLAG_IOPL; -extern const int32_t FLAG_NT; -extern const int32_t FLAG_RF; -extern const int32_t FLAG_VM; -extern const int32_t FLAG_AC; -extern const int32_t FLAG_VIF; -extern const int32_t FLAG_VIP; -extern const int32_t FLAG_ID; -extern const int32_t FLAGS_DEFAULT; - -extern const int32_t FLAGS_MASK; - -extern const int32_t FLAGS_ALL; - -extern const int32_t OPSIZE_8; -extern const int32_t OPSIZE_16; -extern const int32_t OPSIZE_32; - -extern const int32_t EAX; -extern const int32_t ECX; -extern const int32_t EDX; -extern const int32_t EBX; -extern const int32_t ESP; -extern const int32_t EBP; -extern const int32_t ESI; -extern const int32_t EDI; - -extern const int32_t AX; -extern const int32_t CX; -extern const int32_t DX; -extern const int32_t BX; -extern const int32_t SP; -extern const int32_t BP; -extern const int32_t SI; -extern const int32_t DI; - -extern const int32_t AL; -extern const int32_t CL; -extern const int32_t DL; -extern const int32_t BL; -extern const int32_t AH; -extern const int32_t CH; -extern const int32_t DH; -extern const int32_t BH; - -extern const int32_t ES; -extern const int32_t CS; -extern const int32_t SS; -extern const int32_t DS; -extern const int32_t FS; -extern const int32_t GS; - -extern const int32_t TR; -extern const int32_t LDTR; - - -extern const int32_t PAGE_TABLE_PRESENT_MASK; -extern const int32_t PAGE_TABLE_RW_MASK; -extern const int32_t PAGE_TABLE_USER_MASK; -extern const int32_t PAGE_TABLE_ACCESSED_MASK; -extern const int32_t PAGE_TABLE_DIRTY_MASK; -extern const int32_t PAGE_TABLE_PSE_MASK; -extern const int32_t PAGE_TABLE_GLOBAL_MASK; - -extern const int32_t MMAP_BLOCK_BITS; -extern const int32_t MMAP_BLOCK_SIZE; - -extern const int32_t CR0_PE; -extern const int32_t CR0_MP; -extern const int32_t CR0_EM; -extern const int32_t CR0_TS; -extern const int32_t CR0_ET; -extern const int32_t CR0_WP; -extern const int32_t CR0_NW; -extern const int32_t CR0_CD; -extern const int32_t CR0_PG; - -extern const int32_t CR4_VME; -extern const int32_t CR4_PVI; -extern const int32_t CR4_TSD; -extern const int32_t CR4_PSE; -extern const int32_t CR4_DE; -extern const int32_t CR4_PAE; -extern const int32_t CR4_PGE; - - -extern const int32_t IA32_SYSENTER_CS; -extern const int32_t IA32_SYSENTER_ESP; -extern const int32_t IA32_SYSENTER_EIP; - -extern const int32_t IA32_TIME_STAMP_COUNTER; -extern const int32_t IA32_PLATFORM_ID; -extern const int32_t IA32_APIC_BASE_MSR; -extern const int32_t IA32_BIOS_SIGN_ID; -extern const int32_t MSR_PLATFORM_INFO; -extern const int32_t MSR_MISC_FEATURE_ENABLES; -extern const int32_t IA32_MISC_ENABLE; -extern const int32_t IA32_RTIT_CTL; -extern const int32_t MSR_SMI_COUNT; -extern const int32_t IA32_MCG_CAP; -extern const int32_t IA32_KERNEL_GS_BASE; -extern const int32_t MSR_PKG_C2_RESIDENCY; - -extern const int32_t IA32_APIC_BASE_BSP; -extern const int32_t IA32_APIC_BASE_EXTD; -extern const int32_t IA32_APIC_BASE_EN; - - -// Note: Duplicated in apic.js -extern const int32_t APIC_ADDRESS; - - -// Segment prefixes must not collide with reg_*s variables -// _ZERO is a special zero offset segment -extern const int32_t SEG_PREFIX_NONE; -extern const int32_t SEG_PREFIX_ZERO; - -extern const int32_t PREFIX_MASK_REP; -extern const int32_t PREFIX_REPZ; -extern const int32_t PREFIX_REPNZ; - -extern const int32_t PREFIX_MASK_SEGMENT; -extern const int32_t PREFIX_MASK_OPSIZE; -extern const int32_t PREFIX_MASK_ADDRSIZE; - -// aliases -extern const int32_t PREFIX_F2; -extern const int32_t PREFIX_F3; -extern const int32_t PREFIX_66; - -extern const int32_t LOG_CPU; - -extern const int32_t A20_MASK; -extern const int32_t A20_MASK16; -extern const int32_t A20_MASK32; - -extern const int32_t MXCSR_MASK; diff --git a/src/native/cpu.c b/src/native/cpu.c deleted file mode 100644 index 25f811e8..00000000 --- a/src/native/cpu.c +++ /dev/null @@ -1,1900 +0,0 @@ -#include -#include -#include -#include - -#include "const.h" -#include "cpu.h" -#include "global_pointers.h" -#include "instructions.h" -#include "js_imports.h" -#include "log.h" -#include "memory.h" -#include "misc_instr.h" -#include "modrm.h" -#include "profiler/profiler.h" -#include "rust_imports.h" -#include "shared.h" - -const int32_t FLAG_CARRY = 1; -const int32_t FLAG_PARITY = 4; -const int32_t FLAG_ADJUST = 16; -const int32_t FLAG_ZERO = 64; -const int32_t FLAG_SIGN = 128; -const int32_t FLAG_TRAP = 256; -const int32_t FLAG_INTERRUPT = 512; -const int32_t FLAG_DIRECTION = 1024; -const int32_t FLAG_OVERFLOW = 2048; -const int32_t FLAG_IOPL = (1 << 12 | 1 << 13); -const int32_t FLAG_NT = (1 << 14); -const int32_t FLAG_RF = (1 << 16); -const int32_t FLAG_VM = (1 << 17); -const int32_t FLAG_AC = (1 << 18); -const int32_t FLAG_VIF = (1 << 19); -const int32_t FLAG_VIP = (1 << 20); -const int32_t FLAG_ID = (1 << 21); -const int32_t FLAGS_DEFAULT = (1 << 1); - -const int32_t FLAGS_MASK = ( - FLAG_CARRY | FLAG_PARITY | FLAG_ADJUST | FLAG_ZERO | FLAG_SIGN | FLAG_TRAP | FLAG_INTERRUPT | - FLAG_DIRECTION | FLAG_OVERFLOW | FLAG_IOPL | FLAG_NT | FLAG_RF | FLAG_VM | FLAG_AC | - FLAG_VIF | FLAG_VIP | FLAG_ID); - -const int32_t FLAGS_ALL = (FLAG_CARRY | FLAG_PARITY | FLAG_ADJUST | FLAG_ZERO | FLAG_SIGN | FLAG_OVERFLOW); - -const int32_t OPSIZE_8 = 7; -const int32_t OPSIZE_16 = 15; -const int32_t OPSIZE_32 = 31; - -const int32_t EAX = 0; -const int32_t ECX = 1; -const int32_t EDX = 2; -const int32_t EBX = 3; -const int32_t ESP = 4; -const int32_t EBP = 5; -const int32_t ESI = 6; -const int32_t EDI = 7; - -const int32_t AX = 0; -const int32_t CX = 2; -const int32_t DX = 4; -const int32_t BX = 6; -const int32_t SP = 8; -const int32_t BP = 10; -const int32_t SI = 12; -const int32_t DI = 14; - -const int32_t AL = 0; -const int32_t CL = 4; -const int32_t DL = 8; -const int32_t BL = 12; -const int32_t AH = 1; -const int32_t CH = 5; -const int32_t DH = 9; -const int32_t BH = 13; - -const int32_t ES = 0; -const int32_t CS = 1; -const int32_t SS = 2; -const int32_t DS = 3; -const int32_t FS = 4; -const int32_t GS = 5; - -const int32_t TR = 6; -const int32_t LDTR = 7; - - -const int32_t PAGE_TABLE_PRESENT_MASK = (1 << 0); -const int32_t PAGE_TABLE_RW_MASK = (1 << 1); -const int32_t PAGE_TABLE_USER_MASK = (1 << 2); -const int32_t PAGE_TABLE_ACCESSED_MASK = (1 << 5); -const int32_t PAGE_TABLE_DIRTY_MASK = (1 << 6); -const int32_t PAGE_TABLE_PSE_MASK = (1 << 7); -const int32_t PAGE_TABLE_GLOBAL_MASK = (1 << 8); - -const int32_t MMAP_BLOCK_BITS = 17; -const int32_t MMAP_BLOCK_SIZE = (1 << MMAP_BLOCK_BITS); - -const int32_t CR0_PE = 1; -const int32_t CR0_MP = (1 << 1); -const int32_t CR0_EM = (1 << 2); -const int32_t CR0_TS = (1 << 3); -const int32_t CR0_ET = (1 << 4); -const int32_t CR0_WP = (1 << 16); -const int32_t CR0_NW = (1 << 29); -const int32_t CR0_CD = (1 << 30); -const int32_t CR0_PG = (1 << 31); - -const int32_t CR4_VME = (1); -const int32_t CR4_PVI = (1 << 1); -const int32_t CR4_TSD = (1 << 2); -const int32_t CR4_PSE = (1 << 4); -const int32_t CR4_DE = (1 << 3); -const int32_t CR4_PAE = (1 << 5); -const int32_t CR4_PGE = (1 << 7); - - -const int32_t IA32_SYSENTER_CS = 0x174; -const int32_t IA32_SYSENTER_ESP = 0x175; -const int32_t IA32_SYSENTER_EIP = 0x176; - -const int32_t IA32_TIME_STAMP_COUNTER = 0x10; -const int32_t IA32_PLATFORM_ID = 0x17; -const int32_t IA32_APIC_BASE_MSR = 0x1B; -const int32_t IA32_BIOS_SIGN_ID = 0x8B; -const int32_t MSR_PLATFORM_INFO = 0xCE; -const int32_t MSR_MISC_FEATURE_ENABLES = 0x140; -const int32_t IA32_MISC_ENABLE = 0x1A0; -const int32_t IA32_RTIT_CTL = 0x570; -const int32_t MSR_SMI_COUNT = 0x34; -const int32_t IA32_MCG_CAP = 0x179; -const int32_t IA32_KERNEL_GS_BASE = 0xC0000101; -const int32_t MSR_PKG_C2_RESIDENCY = 0x60D; - -const int32_t IA32_APIC_BASE_BSP = (1 << 8); -const int32_t IA32_APIC_BASE_EXTD = (1 << 10); -const int32_t IA32_APIC_BASE_EN = (1 << 11); - - -// Note: Duplicated in apic.js -const int32_t APIC_ADDRESS = ((int32_t)0xFEE00000); - - -// Segment prefixes must not collide with reg_*s variables -// _ZERO is a special zero offset segment -const int32_t SEG_PREFIX_NONE = (-1); -const int32_t SEG_PREFIX_ZERO = 7; - -const int32_t PREFIX_MASK_REP = 0b11000; -const int32_t PREFIX_REPZ = 0b01000; -const int32_t PREFIX_REPNZ = 0b10000; - -const int32_t PREFIX_MASK_SEGMENT = 0b111; -const int32_t PREFIX_MASK_OPSIZE = 0b100000; -const int32_t PREFIX_MASK_ADDRSIZE = 0b1000000; - -// aliases -const int32_t PREFIX_F2 = PREFIX_REPNZ; -const int32_t PREFIX_F3 = PREFIX_REPZ; -const int32_t PREFIX_66 = PREFIX_MASK_OPSIZE; - -const int32_t LOG_CPU = 0x000002; - -const int32_t A20_MASK = (~(1 << 20)); -const int32_t A20_MASK16 = (~(1 << (20 - 1))); -const int32_t A20_MASK32 = (~(1 << (20 - 2))); - -const int32_t MXCSR_MASK = (0xFFFF & ~(1 << 6)); - -const int32_t CPU_EXCEPTION_DE = 0; // Divide Error -const int32_t CPU_EXCEPTION_DB = 1; // Debug Exception -const int32_t CPU_EXCEPTION_NMI = 2; // NMI Interrupt -const int32_t CPU_EXCEPTION_BP = 3; // Breakpoint -const int32_t CPU_EXCEPTION_OF = 4; // Overflow -const int32_t CPU_EXCEPTION_BR = 5; // BOUND Range Exceeded -const int32_t CPU_EXCEPTION_UD = 6; // Invalid Opcode -const int32_t CPU_EXCEPTION_NM = 7; // Device Not Available -const int32_t CPU_EXCEPTION_DF = 8; // Double Fault -const int32_t CPU_EXCEPTION_TS = 10; // Invalid TSS -const int32_t CPU_EXCEPTION_NP = 11; // Segment Not Present -const int32_t CPU_EXCEPTION_SS = 12; // Stack-Segment Fault -const int32_t CPU_EXCEPTION_GP = 13; // General Protection -const int32_t CPU_EXCEPTION_PF = 14; // Page Fault -const int32_t CPU_EXCEPTION_MF = 16; // x87 FPU Floating-Point Error -const int32_t CPU_EXCEPTION_AC = 17; // Alignment Check -const int32_t CPU_EXCEPTION_MC = 18; // Machine Check Abort -const int32_t CPU_EXCEPTION_XM = 19; // SIMD Floating-Point Exception -const int32_t CPU_EXCEPTION_VE = 20; // Virtualization Exception - -const int32_t LOOP_COUNTER = 20011; -const double_t TSC_RATE = (50 * 1000); - -const bool CHECK_TLB_INVARIANTS = false; - -const bool DEBUG = true; - -const int32_t TLB_VALID = (1 << 0); -const int32_t TLB_READONLY = (1 << 1); -const int32_t TLB_NO_USER = (1 << 2); -const int32_t TLB_IN_MAPPED_RANGE = (1 << 3); -const int32_t TLB_GLOBAL = (1 << 4); -const int32_t TLB_HAS_CODE = (1 << 5); - - -uint8_t* mem8 = NULL; -uint16_t* mem16 = NULL; -int32_t* mem32s = NULL; - -bool must_not_fault = false; - -#if 1 -int32_t current_cpu_exception = -1; -void assert_no_cpu_exception() { - if(current_cpu_exception != -1) - { - dbg_log1("Expected no cpu exception, got %d", current_cpu_exception); - dbg_trace(); - assert(false); - } -} -void set_current_cpu_exception(int32_t n) { current_cpu_exception = n; } -void clear_current_cpu_exception() { current_cpu_exception = -1; } -#else -void assert_no_cpu_exception() {} -void set_current_cpu_exception(int32_t n) { UNUSED(n); } -void clear_current_cpu_exception() { } -#endif - -uint64_t tsc_offset = 0; - -bool jit_block_boundary = false; - -const int32_t VALID_TLB_ENTRY_MAX = 10000; -int32_t valid_tlb_entries[VALID_TLB_ENTRY_MAX] = {0}; -int32_t valid_tlb_entries_count = 0; - -void after_block_boundary() -{ - jit_block_boundary = true; -} - -int32_t get_eflags() -{ - return (*flags & ~FLAGS_ALL) | !!getcf() | !!getpf() << 2 | !!getaf() << 4 | - !!getzf() << 6 | !!getsf() << 7 | !!getof() << 11; -} - -int32_t getiopl(void) -{ - return *flags >> 12 & 3; -} - -bool vm86_mode(void) -{ - return (*flags & FLAG_VM) == FLAG_VM; -} - -/* - * Update the flags register depending on iopl and cpl - */ -void update_eflags(int32_t new_flags) -{ - int32_t dont_update = FLAG_RF | FLAG_VM | FLAG_VIP | FLAG_VIF; - int32_t clear = ~FLAG_VIP & ~FLAG_VIF & FLAGS_MASK; - - if(*flags & FLAG_VM) - { - c_comment("other case needs to be handled in popf or iret"); - dbg_assert(getiopl() == 3); - - dont_update |= FLAG_IOPL; - - c_comment("don't clear vip or vif"); - clear |= FLAG_VIP | FLAG_VIF; - } - else - { - if(!*protected_mode) dbg_assert(*cpl == 0); - - if(*cpl) - { - c_comment("cpl > 0"); - c_comment("cannot update iopl"); - dont_update |= FLAG_IOPL; - - if(*cpl > getiopl()) - { - c_comment("cpl > iopl"); - c_comment("cannot update interrupt flag"); - dont_update |= FLAG_INTERRUPT; - } - } - } - - *flags = (new_flags ^ ((*flags ^ new_flags) & dont_update)) & clear | FLAGS_DEFAULT; - - *flags_changed = 0; -} - -void trigger_pagefault(bool write, bool user, bool present) -{ - if(0 * 0) - { - dbg_log5("page fault w=%d u=%d p=%d eip=%x cr2=%x", - write, user, present, *previous_ip, cr[2]); - dbg_trace(); - } - -if( DEBUG) { - if(must_not_fault) - { - dbg_log("Unexpected page fault"); - dbg_trace(); - assert(false); - } -} - - if(*page_fault) - { - dbg_log("double fault"); - dbg_trace(); - assert(false); - } - - c_comment("invalidate tlb entry"); - int32_t page = (uint32_t)cr[2] >> 12; - tlb_data[page] = 0; - - *instruction_pointer = *previous_ip; - *page_fault = true; - call_interrupt_vector(CPU_EXCEPTION_PF, false, true, user << 2 | write << 1 | present); - - profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); - throw_cpu_exception(); -} - -int32_t do_page_translation(int32_t addr, bool for_writing, bool user) -{ - bool can_write = true; - bool global; - bool allow_user = true; - - int32_t page = (uint32_t)addr >> 12; - int32_t high; - - if((cr[0] & CR0_PG) == 0) - { - c_comment("paging disabled"); - high = addr & 0xFFFFF000; - global = false; - } - else - { - int32_t page_dir_addr = ((uint32_t)cr[3] >> 2) + (page >> 10); - int32_t page_dir_entry = read_aligned32(page_dir_addr); - - c_comment("XXX"); - const bool kernel_write_override = !user && !(cr[0] & CR0_WP); - - if(!(page_dir_entry & PAGE_TABLE_PRESENT_MASK)) - { - c_comment("to do at this place:"); - c_comment(""); - c_comment("- set cr2 = addr (which caused the page fault)"); - c_comment("- call_interrupt_vector with id 14, error code 0-7 (requires information if read or write)"); - c_comment("- prevent execution of the function that triggered this call"); - //dbg_log("#PF not present", LOG_CPU); - - cr[2] = addr; - trigger_pagefault(for_writing, user, 0); - - c_comment("never reached as trigger_pagefault throws"); - dbg_assert(false); - } - - if((page_dir_entry & PAGE_TABLE_RW_MASK) == 0 && !kernel_write_override) - { - can_write = false; - - if(for_writing) - { - cr[2] = addr; - trigger_pagefault(for_writing, user, 1); - dbg_assert(false); - } - } - - if((page_dir_entry & PAGE_TABLE_USER_MASK) == 0) - { - allow_user = false; - - if(user) - { - c_comment("Page Fault: page table accessed by non-supervisor"); - //dbg_log("#PF supervisor", LOG_CPU); - cr[2] = addr; - trigger_pagefault(for_writing, user, 1); - dbg_assert(false); - } - } - - if((page_dir_entry & PAGE_TABLE_PSE_MASK) && (cr[4] & CR4_PSE)) - { - c_comment("size bit is set"); - - c_comment("set the accessed and dirty bits"); - write_aligned32(page_dir_addr, page_dir_entry | PAGE_TABLE_ACCESSED_MASK | - (for_writing ? PAGE_TABLE_DIRTY_MASK : 0)); - - high = (page_dir_entry & 0xFFC00000) | (addr & 0x3FF000); - global = (page_dir_entry & PAGE_TABLE_GLOBAL_MASK) == PAGE_TABLE_GLOBAL_MASK; - } - else - { - int32_t page_table_addr = ((uint32_t)(page_dir_entry & 0xFFFFF000) >> 2) + (page & 0x3FF); - int32_t page_table_entry = read_aligned32(page_table_addr); - - if((page_table_entry & PAGE_TABLE_PRESENT_MASK) == 0) - { - //dbg_log("#PF not present table", LOG_CPU); - cr[2] = addr; - trigger_pagefault(for_writing, user, 0); - dbg_assert(false); - } - - if((page_table_entry & PAGE_TABLE_RW_MASK) == 0 && !kernel_write_override) - { - can_write = false; - - if(for_writing) - { - //dbg_log("#PF not writable page", LOG_CPU); - cr[2] = addr; - trigger_pagefault(for_writing, user, 1); - dbg_assert(false); - } - } - - if((page_table_entry & PAGE_TABLE_USER_MASK) == 0) - { - allow_user = false; - - if(user) - { - //dbg_log("#PF not supervisor page", LOG_CPU); - cr[2] = addr; - trigger_pagefault(for_writing, user, 1); - dbg_assert(false); - } - } - - c_comment("set the accessed and dirty bits"); - write_aligned32(page_dir_addr, page_dir_entry | PAGE_TABLE_ACCESSED_MASK); - write_aligned32(page_table_addr, - page_table_entry | PAGE_TABLE_ACCESSED_MASK | - (for_writing ? PAGE_TABLE_DIRTY_MASK : 0)); - - high = page_table_entry & 0xFFFFF000; - global = (page_table_entry & PAGE_TABLE_GLOBAL_MASK) == PAGE_TABLE_GLOBAL_MASK; - } - } - - if(tlb_data[page] == 0) - { - if(valid_tlb_entries_count == VALID_TLB_ENTRY_MAX) - { - profiler_stat_increment(S_TLB_FULL); - clear_tlb(); - - c_comment("also clear global entries if tlb is almost full after clearing non-global pages"); - if(valid_tlb_entries_count > VALID_TLB_ENTRY_MAX * 3 / 4) - { - profiler_stat_increment(S_TLB_GLOBAL_FULL); - full_clear_tlb(); - } - } - - assert(valid_tlb_entries_count < VALID_TLB_ENTRY_MAX); - valid_tlb_entries[valid_tlb_entries_count++] = page; - - c_comment("TODO: Check that there are no duplicates in valid_tlb_entries"); - c_comment("XXX: There will probably be duplicates due to invlpg deleting"); - c_comment("entries from tlb_data but not from valid_tlb_entries"); - } - else - { - if(CHECK_TLB_INVARIANTS) - { - bool found = false; - - for(int32_t i = 0; i < valid_tlb_entries_count; i++) - { - if(valid_tlb_entries[i] == page) - { - found = true; - break; - } - } - - assert(found); - } - } - - bool is_in_mapped_range = in_mapped_range(high); - int32_t physical_page = (uint32_t)high >> 12; - - bool has_code = !is_in_mapped_range && jit_page_has_code(physical_page); - - int32_t info_bits = - TLB_VALID | - (can_write ? 0 : TLB_READONLY) | - (allow_user ? 0 : TLB_NO_USER) | - (is_in_mapped_range ? TLB_IN_MAPPED_RANGE : 0) | - (global && (cr[4] & CR4_PGE) ? TLB_GLOBAL : 0) | - (has_code ? TLB_HAS_CODE : 0); - - assert(((high ^ page << 12) & 0xFFF) == 0); - tlb_data[page] = high ^ page << 12 | info_bits; - - return high; -} - -void tlb_set_has_code(uint32_t physical_page, bool has_code) -{ - assert(physical_page < (1 << 20)); - - for(int32_t i = 0; i < valid_tlb_entries_count; i++) - { - int32_t page = valid_tlb_entries[i]; - int32_t entry = tlb_data[page]; - - if(entry) - { - uint32_t tlb_physical_page = (uint32_t)entry >> 12 ^ page; - - if(physical_page == tlb_physical_page) - { - tlb_data[page] = has_code ? entry | TLB_HAS_CODE : entry & ~TLB_HAS_CODE; - } - } - } - - check_tlb_invariants(); -} - -void check_tlb_invariants(void) -{ - if(!CHECK_TLB_INVARIANTS) return; - - for(int32_t i = 0; i < valid_tlb_entries_count; i++) - { - int32_t page = valid_tlb_entries[i]; - int32_t entry = tlb_data[page]; - - if(!entry || (entry & TLB_IN_MAPPED_RANGE)) c_comment("there's no code in mapped memory"); - { - continue; - } - - uint32_t physical_page = (uint32_t)entry >> 12 ^ page; - dbg_assert(!in_mapped_range(physical_page << 12)); - - bool entry_has_code = entry & TLB_HAS_CODE; - bool has_code = jit_page_has_code(physical_page); - - c_comment("If some code has been created in a page, the corresponding tlb entries must be marked"); - dbg_assert(!has_code || entry_has_code); - - c_comment("If a tlb entry is marked to have code, the physical page should"); - c_comment("contain code (the converse is not a bug, but indicates a cleanup"); - c_comment("problem when clearing code from a page)"); - dbg_assert(!entry_has_code || has_code); - } -} - -int32_t get_valid_tlb_entries_count(void) -{ - int32_t result = 0; - - for(int32_t i = 0; i < valid_tlb_entries_count; i++) - { - int32_t page = valid_tlb_entries[i]; - int32_t entry = tlb_data[page]; - - if(entry) - { - result++; - } - } - - return result; -} - -int32_t get_valid_global_tlb_entries_count(void) -{ - int32_t result = 0; - - for(int32_t i = 0; i < valid_tlb_entries_count; i++) - { - int32_t page = valid_tlb_entries[i]; - int32_t entry = tlb_data[page]; - - if(entry & TLB_GLOBAL) - { - result++; - } - } - - return result; -} - -void writable_or_pagefault(int32_t addr, int32_t size) -{ - dbg_assert(size < 0x1000); - dbg_assert(size > 0); - - if((cr[0] & CR0_PG) == 0) - { - return; - } - - bool user = cpl[0] == 3; - int32_t mask = TLB_READONLY | TLB_VALID | (user ? TLB_NO_USER : 0); - int32_t expect = TLB_VALID; - int32_t page = (uint32_t)addr >> 12; - - if((tlb_data[page] & mask) != expect) - { - do_page_translation(addr, true, user); - } - - int32_t next_page = (uint32_t)(addr + size - 1) >> 12; - - if(page != next_page) - { - assert(next_page == page + 1); - - c_comment("XXX: possibly out of bounds"); - if((tlb_data[next_page] & mask) != expect) - { - do_page_translation(next_page << 12, true, user); - } - } -} - -uint32_t translate_address_read(int32_t address) -{ - int32_t base = (uint32_t)address >> 12; - int32_t entry = tlb_data[base]; - bool user = cpl[0] == 3; - if((entry & (TLB_VALID | (user ? TLB_NO_USER : 0))) == TLB_VALID) - { - return entry & ~0xFFF ^ address; - } - else - { - return do_page_translation(address, false, user) | address & 0xFFF; - } -} - -uint32_t translate_address_write(int32_t address) -{ - int32_t base = (uint32_t)address >> 12; - int32_t entry = tlb_data[base]; - bool user = cpl[0] == 3; - if((entry & (TLB_VALID | (user ? TLB_NO_USER : 0) | TLB_READONLY)) == TLB_VALID) - { - return entry & ~0xFFF ^ address; - } - else - { - return do_page_translation(address, true, user) | address & 0xFFF; - } -} - -uint32_t translate_address_system_read(int32_t address) -{ - int32_t base = (uint32_t)address >> 12; - int32_t entry = tlb_data[base]; - if(entry & TLB_VALID) - { - return entry & ~0xFFF ^ address; - } - else - { - return do_page_translation(address, false, false) | address & 0xFFF; - } -} - -uint32_t translate_address_system_write(int32_t address) -{ - int32_t base = (uint32_t)address >> 12; - int32_t entry = tlb_data[base]; - if((entry & (TLB_VALID | TLB_READONLY)) == TLB_VALID) - { - return entry & ~0xFFF ^ address; - } - else - { - return do_page_translation(address, true, false) | address & 0xFFF; - } -} - -int32_t get_phys_eip() -{ - int32_t eip = *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)); - return phys_addr; -} - -int32_t read_imm8() -{ - int32_t eip = *instruction_pointer; - - if((eip & ~0xFFF) ^ *last_virt_eip) - { - *eip_phys = translate_address_read(eip) ^ eip; - *last_virt_eip = eip & ~0xFFF; - } - - assert(!in_mapped_range(*eip_phys ^ eip)); - int32_t data8 = mem8[*eip_phys ^ eip]; - *instruction_pointer = eip + 1; - - return data8; -} - -int32_t read_imm8s() -{ - return read_imm8() << 24 >> 24; -} - -int32_t read_imm16() -{ - c_comment("Two checks in one comparison:"); - c_comment("1. Did the high 20 bits of eip change"); - c_comment("or 2. Are the low 12 bits of eip 0xFFF (and this read crosses a page boundary)"); - if((uint32_t)(*instruction_pointer ^ *last_virt_eip) > 0xFFE) - { - return read_imm8() | read_imm8() << 8; - } - - int32_t data16 = read16(*eip_phys ^ *instruction_pointer); - *instruction_pointer = *instruction_pointer + 2; - - return data16; -} - -int32_t read_imm32s() -{ - c_comment("Analogue to the above comment"); - if((uint32_t)(*instruction_pointer ^ *last_virt_eip) > 0xFFC) - { - return read_imm16() | read_imm16() << 16; - } - - int32_t data32 = read32s(*eip_phys ^ *instruction_pointer); - *instruction_pointer = *instruction_pointer + 4; - - return data32; -} - -bool is_osize_32() -{ - return *is_32 != ((*prefixes & PREFIX_MASK_OPSIZE) == PREFIX_MASK_OPSIZE); -} - -bool is_asize_32() -{ - return *is_32 != ((*prefixes & PREFIX_MASK_ADDRSIZE) == PREFIX_MASK_ADDRSIZE); -} - -int32_t get_seg(int32_t segment) -{ - assert(segment >= 0 && segment < 8); - - c_comment("TODO: Remove protected_mode check"); - if(*protected_mode) - { - if(segment_is_null[segment]) - { - assert(segment != CS && segment != SS); - dbg_log("#gp: Access null segment"); - trigger_gp(0); - } - } - - return segment_offsets[segment]; -} - -int32_t get_seg_cs(void) -{ - return segment_offsets[CS]; -} - -int32_t get_seg_ss(void) -{ - return segment_offsets[SS]; -} - -int32_t get_seg_prefix(int32_t default_segment) -{ - int32_t prefix = *prefixes & PREFIX_MASK_SEGMENT; - - if(prefix) - { - if(prefix == SEG_PREFIX_ZERO) - { - return 0; c_comment("TODO: Remove this special case"); - } - else - { - return get_seg(prefix - 1); - } - } - else - { - return get_seg(default_segment); - } -} - -int32_t get_seg_prefix_ds(int32_t offset) { return get_seg_prefix(DS) + offset; } -int32_t get_seg_prefix_ss(int32_t offset) { return get_seg_prefix(SS) + offset; } -int32_t get_seg_prefix_cs(int32_t offset) { return get_seg_prefix(CS) + offset; } - -int32_t modrm_resolve(int32_t modrm_byte) -{ - if(is_asize_32()) - { - return resolve_modrm32(modrm_byte); - } - else - { - return resolve_modrm16(modrm_byte); - } -} - -static void jit_run_interpreted(int32_t phys_addr) -{ - profiler_stat_increment(S_RUN_INTERPRETED); - - jit_block_boundary = false; - - assert(!in_mapped_range(phys_addr)); - int32_t opcode = mem8[phys_addr]; - (*instruction_pointer)++; - (*timestamp_counter)++; - - run_instruction(opcode | !!*is_32 << 8); - - clear_current_cpu_exception(); - - while(!jit_block_boundary && same_page(*previous_ip, *instruction_pointer)) - { - previous_ip[0] = instruction_pointer[0]; - (*timestamp_counter)++; - - int32_t opcode = read_imm8(); - - if(DEBUG) - logop(previous_ip[0], opcode); - - run_instruction(opcode | !!*is_32 << 8); - - clear_current_cpu_exception(); - } -} - -bool has_flat_segmentation(void) -{ - c_comment("ss can't be null"); - return segment_offsets[SS] == 0 && !segment_is_null[DS] && segment_offsets[DS] == 0; -} - -cached_state_flags pack_current_state_flags() -{ - return *is_32 << 0 | *stack_size_32 << 1 | (*cpl == 3) << 2 | has_flat_segmentation() << 3; -} - -bool same_page(int32_t addr1, int32_t addr2) -{ - return (addr1 & ~0xFFF) == (addr2 & ~0xFFF); -} - -void cycle_internal() -{ - profiler_stat_increment(S_CYCLE_INTERNAL); - if(true) { - - *previous_ip = *instruction_pointer; - uint32_t phys_addr = get_phys_eip(); - - cached_state_flags state_flags = pack_current_state_flags(); - uint32_t entry = jit_find_cache_entry(phys_addr, state_flags); - - if(entry) - { - profiler_stat_increment(S_RUN_FROM_CACHE); - - int32_t initial_tsc = *timestamp_counter; - - //uint32_t old_start_address = entry->start_addr; - - uint16_t wasm_table_index = entry & 0xFFFF; - uint16_t initial_state = entry >> 16; - call_indirect1((uint32_t)wasm_table_index + 0x100, initial_state); - - clear_current_cpu_exception(); - - // XXX: New clearing: This should fail on self-modifying code - //assert(entry->start_addr == old_start_address); - - //UNUSED(old_start_address); - - profiler_stat_increment_by(S_RUN_FROM_CACHE_STEPS, *timestamp_counter - initial_tsc); - } - else - { - if(DEBUG) { - assert(!must_not_fault); must_not_fault = true; - } - jit_increase_hotness_and_maybe_compile(phys_addr, get_seg_cs(), state_flags); - - if(DEBUG) { - assert(must_not_fault); must_not_fault = false; - } - - int32_t initial_tsc = *timestamp_counter; - - jit_run_interpreted(phys_addr); - - profiler_stat_increment_by(S_RUN_INTERPRETED_STEPS, *timestamp_counter - initial_tsc); - } - - } - 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); - - - run_instruction(opcode | !!*is_32 << 8); - } -} - -void run_prefix_instruction() -{ - run_instruction(read_imm8() | is_osize_32() << 8); -} - -void clear_prefixes() -{ - *prefixes = 0; -} - -void segment_prefix_op(int32_t seg) -{ - assert(seg <= 5); - *prefixes |= seg + 1; - run_prefix_instruction(); - *prefixes = 0; -} - -void do_many_cycles_unsafe() -{ - profiler_stat_increment(S_DO_MANY_CYCLES); - - uint32_t initial_timestamp_counter = *timestamp_counter; - - for(; *timestamp_counter - initial_timestamp_counter < LOOP_COUNTER && !in_hlt[0]; ) - { - cycle_internal(); - } -} - -void raise_exception(int32_t interrupt_nr) -{ - if(DEBUG) { - if(must_not_fault) - { - dbg_log1("Unexpected fault: 0x%x", interrupt_nr); - dbg_trace(); - assert(false); - } - - if(cpu_exception_hook(interrupt_nr)) - { - throw_cpu_exception(); - return; - } - } - profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); - 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(must_not_fault) - { - dbg_log2("Unexpected fault: 0x%x with code 0x%x", interrupt_nr, error_code); - dbg_trace(); - assert(false); - } - - if(cpu_exception_hook(interrupt_nr)) - { - throw_cpu_exception(); - return; - } - } - profiler_stat_increment(S_TRIGGER_CPU_EXCEPTION); - call_interrupt_vector(interrupt_nr, false, true, error_code); - throw_cpu_exception(); -} - -__attribute__((noinline)) -void trigger_de() -{ - if(DEBUG) { - if(cpu_exception_hook(CPU_EXCEPTION_DE)) - { - return; - } - } - *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_DE, false, false, 0); - set_current_cpu_exception(CPU_EXCEPTION_DE); -} - -__attribute__((noinline)) -void trigger_ud() -{ - dbg_log("#ud"); - dbg_trace(); - if(DEBUG) { - if(cpu_exception_hook(CPU_EXCEPTION_UD)) - { - return; - } - } - *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_UD, false, false, 0); - set_current_cpu_exception(CPU_EXCEPTION_UD); -} - -__attribute__((noinline)) -void trigger_nm() -{ - if(DEBUG) { - if(cpu_exception_hook(CPU_EXCEPTION_NM)) - { - return; - } - } - *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_NM, false, false, 0); - set_current_cpu_exception(CPU_EXCEPTION_NM); -} - -__attribute__((noinline)) -void trigger_np(int32_t code) -{ - if(DEBUG) { - if(cpu_exception_hook(CPU_EXCEPTION_NP)) - { - return; - } - } - *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_NP, false, true, code); - set_current_cpu_exception(CPU_EXCEPTION_NP); -} - -__attribute__((noinline)) -void trigger_ss(int32_t code) -{ - if(DEBUG) { - if(cpu_exception_hook(CPU_EXCEPTION_SS)) - { - return; - } - } - *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_SS, false, true, code); - set_current_cpu_exception(CPU_EXCEPTION_SS); -} - -__attribute__((noinline)) -void trigger_gp(int32_t code) -{ - *instruction_pointer = *previous_ip; - raise_exception_with_code(CPU_EXCEPTION_GP, code); -} - -__attribute__((noinline)) -void trigger_gp_non_raising(int32_t code) -{ - if(DEBUG) { - if(cpu_exception_hook(CPU_EXCEPTION_GP)) - { - return; - } - } - *instruction_pointer = *previous_ip; - call_interrupt_vector(CPU_EXCEPTION_GP, false, true, code); - set_current_cpu_exception(CPU_EXCEPTION_GP); -} - -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) - { - c_comment("0xFFF"); - mid = read_aligned16((high - 2) >> 1); - } - else - { - c_comment("0xFFD"); - mid = read_aligned16((low + 1) >> 1); - } - } - else - { - c_comment("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) - { - c_comment("0xFFF"); - write8(high - 2, value >> 8); - write8(high - 1, value >> 16); - } - else - { - c_comment("0xFFD"); - write8(low + 1, value >> 8); - write8(low + 2, value >> 16); - } - } - else - { - c_comment("0xFFE"); - write8(low + 1, value >> 8); - write8(high - 1, value >> 16); - } - - write8(high, value >> 24); -} - -int32_t safe_read8(int32_t addr) -{ - assert_no_cpu_exception(); - return read8(translate_address_read(addr)); -} - -__attribute__((noinline)) -int32_t safe_read16_slow(int32_t addr) -{ - assert_no_cpu_exception(); - if((addr & 0xFFF) == 0xFFF) - { - return safe_read8(addr) | safe_read8(addr + 1) << 8; - } - else - { - return read16(translate_address_read(addr)); - } -} - -__attribute__((always_inline)) -int32_t safe_read16(int32_t address) -{ -#if 1 - int32_t base = (uint32_t)address >> 12; - int32_t entry = tlb_data[base]; - int32_t info_bits = entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~TLB_HAS_CODE; - - if(info_bits == TLB_VALID && (address & 0xFFF) <= (0x1000 - 2)) - { - c_comment("- not in memory mapped area"); - c_comment("- can be accessed from any cpl"); - - uint32_t phys_address = entry & ~0xFFF ^ address; - assert(!in_mapped_range(phys_address)); - return *(uint16_t*)(mem8 + phys_address); - } -#endif - - return safe_read16_slow(address); -} - -__attribute__((noinline)) -int32_t safe_read32s_slow(int32_t addr) -{ - if((addr & 0xFFF) >= 0xFFD) - { - return safe_read16(addr) | safe_read16(addr + 2) << 16; - } - else - { - return read32s(translate_address_read(addr)); - } -} - -__attribute__((always_inline)) -int32_t safe_read32s(int32_t address) -{ - assert_no_cpu_exception(); -#if 1 - int32_t base = (uint32_t)address >> 12; - int32_t entry = tlb_data[base]; - int32_t info_bits = entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~TLB_HAS_CODE; - - if(info_bits == TLB_VALID && (address & 0xFFF) <= (0x1000 - 4)) - { -if( ENABLE_PROFILER_SAFE_READ_WRITE) - profiler_stat_increment(S_SAFE_READ32_FAST); - - c_comment("- not in memory mapped area"); - c_comment("- can be accessed from any cpl"); - - uint32_t phys_address = entry & ~0xFFF ^ address; - assert(!in_mapped_range(phys_address)); - return *(int32_t*)(mem8 + phys_address); - } - else - { -if( ENABLE_PROFILER_SAFE_READ_WRITE) { - if((address & 0xFFF) > 0x1000 - 4) - { - profiler_stat_increment(S_SAFE_READ32_SLOW_PAGE_CROSSED); - } - else if((info_bits & TLB_VALID) == 0) - { - profiler_stat_increment(S_SAFE_READ32_SLOW_NOT_VALID); - } - else if(info_bits & TLB_NO_USER) - { - profiler_stat_increment(S_SAFE_READ32_SLOW_NOT_USER); - } - else if(info_bits & TLB_IN_MAPPED_RANGE) - { - profiler_stat_increment(S_SAFE_READ32_SLOW_IN_MAPPED_RANGE); - } - else - { - dbg_assert(false); - } - } - } -#endif - - return safe_read32s_slow(address); -} - -union reg64 safe_read64s(int32_t addr) -{ - assert_no_cpu_exception(); - - union reg64 x; - if((addr & 0xFFF) > (0x1000 - 8)) - { - x.u32[0] = safe_read32s(addr); - x.u32[1] = safe_read32s(addr + 4); - } - else - { - int32_t addr_phys = translate_address_read(addr); - x.u64[0] = read64s(addr_phys); - } - return x; -} - -__attribute__((always_inline)) -union reg128 safe_read128s(int32_t addr) -{ - assert_no_cpu_exception(); - - union reg128 x; - if((addr & 0xFFF) > (0x1000 - 16)) - { - x.u64[0] = safe_read64s(addr).u64[0]; - x.u64[1] = safe_read64s(addr + 8).u64[0]; - } - else - { - int32_t addr_phys = translate_address_read(addr); - x = read128(addr_phys); - } - return x; -} - -void safe_write8(int32_t addr, int32_t value) -{ - assert_no_cpu_exception(); - - write8(translate_address_write(addr), value); -} - -__attribute__((noinline)) -void safe_write16_slow(int32_t addr, int32_t value) -{ - assert_no_cpu_exception(); - - int32_t phys_low = translate_address_write(addr); - - if((addr & 0xFFF) == 0xFFF) - { - virt_boundary_write16(phys_low, translate_address_write(addr + 1), value); - } - else - { - write16(phys_low, value); - } -} - -__attribute__((always_inline)) -void safe_write16(int32_t address, int32_t value) -{ -#if 1 - int32_t base = (uint32_t)address >> 12; - int32_t entry = tlb_data[base]; - int32_t info_bits = entry & 0xFFF & ~TLB_GLOBAL; - - if(info_bits == TLB_VALID && (address & 0xFFF) <= (0x1000 - 2)) - { - c_comment("- allowed to write in user-mode"); - c_comment("- not in memory mapped area"); - c_comment("- can be accessed from any cpl"); - c_comment("- does not contain code"); - - uint32_t phys_address = entry & ~0xFFF ^ address; - assert(!jit_page_has_code(phys_address >> 12)); - assert(!in_mapped_range(phys_address)); - *(uint16_t*)(mem8 + phys_address) = value; - return; - } -#endif - - safe_write16_slow(address, value); -} - -__attribute__((noinline)) -void safe_write32_slow(int32_t addr, int32_t value) -{ - int32_t phys_low = translate_address_write(addr); - - if((addr & 0xFFF) > (0x1000 - 4)) - { - virt_boundary_write32(phys_low, translate_address_write(addr + 3 & ~3) | (addr + 3) & 3, value); - } - else - { - write32(phys_low, value); - } -} - -__attribute__((always_inline)) -void safe_write32(int32_t address, int32_t value) -{ - assert_no_cpu_exception(); - -#if 1 - int32_t base = (uint32_t)address >> 12; - int32_t entry = tlb_data[base]; - int32_t info_bits = entry & 0xFFF & ~TLB_GLOBAL & ~(*cpl == 3 ? 0 : TLB_NO_USER); - - if(info_bits == TLB_VALID && (address & 0xFFF) <= (0x1000 - 4)) - { -if( ENABLE_PROFILER_SAFE_READ_WRITE) - profiler_stat_increment(S_SAFE_WRITE32_FAST); - c_comment("- allowed to write in user-mode"); - c_comment("- not in memory mapped area"); - c_comment("- does not contain code"); - - uint32_t phys_address = entry & ~0xFFF ^ address; - assert(!jit_page_has_code(phys_address >> 12)); - assert(!in_mapped_range(phys_address)); - *(int32_t*)(mem8 + phys_address) = value; - return; - } - else - { -if( ENABLE_PROFILER_SAFE_READ_WRITE) { - if((address & 0xFFF) > 0x1000 - 4) - { - profiler_stat_increment(S_SAFE_WRITE32_SLOW_PAGE_CROSSED); - } - else if((info_bits & TLB_VALID) == 0) - { - profiler_stat_increment(S_SAFE_WRITE32_SLOW_NOT_VALID); - } - else if(info_bits & TLB_NO_USER) - { - profiler_stat_increment(S_SAFE_WRITE32_SLOW_NOT_USER); - } - else if(info_bits & TLB_IN_MAPPED_RANGE) - { - profiler_stat_increment(S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE); - } - else if(info_bits & TLB_READONLY) - { - profiler_stat_increment(S_SAFE_WRITE32_SLOW_READ_ONLY); - } - else if(info_bits & TLB_HAS_CODE) - { - profiler_stat_increment(S_SAFE_WRITE32_SLOW_HAS_CODE); - } - else - { - dbg_assert(false); - } -} - } -#endif - - safe_write32_slow(address, value); -} - -void safe_write64(int32_t addr, int64_t value) -{ - assert_no_cpu_exception(); - - if((addr & 0xFFF) > (0x1000 - 8)) - { - writable_or_pagefault(addr, 8); - safe_write32(addr, value); - safe_write32(addr + 4, value >> 32); - } - else - { - int32_t phys = translate_address_write(addr); - write64(phys, value); - } -} - -__attribute__((always_inline)) -void safe_write128(int32_t addr, union reg128 value) -{ - assert_no_cpu_exception(); - - if((addr & 0xFFF) > (0x1000 - 16)) - { - writable_or_pagefault(addr, 16); - safe_write64(addr, value.u64[0]); - safe_write64(addr + 8, value.u64[1]); - } - else - { - int32_t phys = translate_address_write(addr); - write128(phys, value); - } -} - -int32_t get_reg8_index(int32_t index) { return index << 2 & 0xC | index >> 2 & 1; } - -int32_t read_reg8(int32_t index) -{ - return reg8[get_reg8_index(index)]; -} - -void write_reg8(int32_t index, int32_t value) -{ - reg8[get_reg8_index(index)] = value; -} - -int32_t get_reg16_index(int32_t index) { return index << 1; } - -int32_t read_reg16(int32_t index) -{ - return reg16[get_reg16_index(index)]; -} - -void write_reg16(int32_t index, int32_t value) -{ - reg16[get_reg16_index(index)] = value; -} - - -int32_t read_reg32(int32_t index) -{ - return reg32s[index]; -} - -void write_reg32(int32_t index, int32_t value) -{ - reg32s[index] = value; -} - -void write_reg_osize(int32_t index, int32_t value) -{ - assert(index >= 0 && index < 8); - - if(is_osize_32()) - { - write_reg32(index, value); - } - else - { - write_reg16(index, value & 0xFFFF); - } -} - -int32_t read_mmx32s(int32_t r) -{ - return reg_mmx[r].u32[0]; -} - -union reg64 read_mmx64s(int32_t r) -{ - return reg_mmx[r]; -} - -void write_mmx64(int32_t r, int32_t low, int32_t high) -{ - reg_mmx[r].u32[0] = low; - reg_mmx[r].u32[1] = high; -} - -void write_mmx_reg64(int32_t r, union reg64 data) -{ - reg_mmx[r].u64[0] = data.u64[0]; -} - -float_t read_xmm_f32(int32_t r) -{ - return reg_xmm[r].f32[0]; -} - -int32_t read_xmm32(int32_t r) -{ - return reg_xmm[r].u32[0]; -} - -union reg64 read_xmm64s(int32_t r) -{ - union reg64 x; - x.u64[0] = reg_xmm[r].u64[0]; - return x; -} - -union reg128 read_xmm128s(int32_t r) -{ - return reg_xmm[r]; -} - -void write_xmm_f32(int32_t r, float_t data) -{ - reg_xmm[r].f32[0] = data; -} - -void write_xmm32(int32_t r, int32_t data) -{ - reg_xmm[r].i32[0] = data; -} - -void write_xmm64(int32_t r, union reg64 data) -{ - reg_xmm[r].u64[0] = data.u64[0]; -} - -void write_xmm128(int32_t r, int32_t i0, int32_t i1, int32_t i2, int32_t i3) -{ - union reg128 x = { .u32 = { i0, i1, i2, i3 } }; - reg_xmm[r] = x; -} - -void write_xmm_reg128(int32_t r, union reg128 data) -{ - reg_xmm[r].u64[0] = data.u64[0]; - reg_xmm[r].u64[1] = data.u64[1]; -} - -void clear_tlb() -{ - profiler_stat_increment(S_CLEAR_TLB); - c_comment("clear tlb excluding global pages"); - - *last_virt_eip = -1; - *last_virt_esp = -1; - - int32_t global_page_offset = 0; - - for(int32_t i = 0; i < valid_tlb_entries_count; i++) - { - int32_t page = valid_tlb_entries[i]; - int32_t entry = tlb_data[page]; - - if(entry & TLB_GLOBAL) - { - c_comment("reinsert at the front"); - valid_tlb_entries[global_page_offset++] = page; - } - else - { - tlb_data[page] = 0; - } - } - - valid_tlb_entries_count = global_page_offset; - - if(CHECK_TLB_INVARIANTS) - { - for(int32_t i = 0; i < 0x100000; i++) - { - assert(tlb_data[i] == 0 || (tlb_data[i] & TLB_GLOBAL)); - } - } -} - -void full_clear_tlb() -{ - profiler_stat_increment(S_FULL_CLEAR_TLB); - c_comment("clear tlb including global pages"); - - *last_virt_eip = -1; - *last_virt_esp = -1; - - for(int32_t i = 0; i < valid_tlb_entries_count; i++) - { - int32_t page = valid_tlb_entries[i]; - tlb_data[page] = 0; - } - - valid_tlb_entries_count = 0; - - if(CHECK_TLB_INVARIANTS) - { - for(int32_t i = 0; i < 0x100000; i++) - { - assert(tlb_data[i] == 0); - } - } -} - -void invlpg(int32_t addr) -{ - //dbg_log("invlpg: addr=" + h(addr >>> 0), LOG_CPU); - int32_t page = (uint32_t)addr >> 12; - - c_comment("Note: Doesn't remove this page from valid_tlb_entries: This isn't"); - c_comment("necessary, because when valid_tlb_entries grows too large, it will be"); - c_comment("empties by calling clear_tlb, which removes this entry as it isn't global."); - c_comment("This however means that valid_tlb_entries can contain some invalid entries"); - tlb_data[page] = 0; - - *last_virt_eip = -1; - *last_virt_esp = -1; -} - -bool task_switch_test() -{ - if(cr[0] & (CR0_EM | CR0_TS)) - { - trigger_nm(); - return false; - } - - return true; -} -void task_switch_test_void() { task_switch_test(); } - -bool task_switch_test_mmx() -{ - if(*cr & CR0_TS) - { - trigger_nm(); - return false; - } - else if(*cr & CR0_EM) - { - trigger_ud(); - return false; - } - - return true; -} -void task_switch_test_mmx_void() { task_switch_test_mmx(); } - -int32_t read_moffs() -{ - c_comment("read 2 or 4 byte from ip, depending on address size attribute"); - if(is_asize_32()) - { - return read_imm32s(); - } - else - { - return read_imm16(); - } -} - -int32_t get_real_eip() -{ - c_comment("Returns the 'real' instruction pointer, without segment offset"); - return *instruction_pointer - get_seg_cs(); -} - -int32_t get_stack_reg() -{ - if(*stack_size_32) - { - return reg32s[ESP]; - } - else - { - return reg16[SP]; - } -} - -void set_stack_reg(int32_t value) -{ - if(*stack_size_32) - { - reg32s[ESP] = value; - } - else - { - reg16[SP] = value; - } -} - -int32_t get_reg_asize(int32_t reg) -{ - dbg_assert(reg == ECX || reg == ESI || reg == EDI); - int32_t r = reg32s[reg]; - - if(is_asize_32()) - { - return r; - } - else - { - return r & 0xFFFF; - } -} - -void set_ecx_asize(int32_t value) -{ - if(is_asize_32()) - { - reg32s[ECX] = value; - } - else - { - reg16[CX] = value; - } -} - -void add_reg_asize(int32_t reg, int32_t value) -{ - dbg_assert(reg == ECX || reg == ESI || reg == EDI); - if(is_asize_32()) - { - reg32s[reg] += value; - } - else - { - reg16[reg << 1] += value; - } -} - -int32_t decr_ecx_asize() -{ - return is_asize_32() ? --reg32s[ECX] : --reg16[CX]; -} - -void set_tsc(uint32_t low, uint32_t high) -{ - uint64_t new_value = low | (uint64_t)high << 32; - uint64_t current_value = read_tsc(); - tsc_offset = current_value - new_value; -} - - -uint64_t rdtsc_last_value = 0; -uint64_t rdtsc_imprecision_offset = 0; - -uint64_t read_tsc() -{ - double_t n = microtick() * TSC_RATE; - uint64_t value = (uint64_t)n - tsc_offset; - - if(1 + 1) { - return value; - } - else { - - if(value == rdtsc_last_value) - { - c_comment("don't go past 1ms"); - - if(rdtsc_imprecision_offset < TSC_RATE) - { - rdtsc_imprecision_offset++; - } - } - else - { - uint64_t previous_value = rdtsc_last_value + rdtsc_imprecision_offset; - - if(previous_value <= value) - { - rdtsc_last_value = value; - rdtsc_imprecision_offset = 0; - } - else - { - dbg_log6("XXX: Overshot tsc prev=%x:%x offset=%x:%x curr=%x:%x", - (uint32_t)(rdtsc_last_value >> 32), (uint32_t)rdtsc_last_value, - (uint32_t)(rdtsc_imprecision_offset >> 32), (uint32_t)rdtsc_imprecision_offset, - (uint32_t)(value >> 32), (uint32_t)value - ); - dbg_assert(false); - - c_comment("Keep current value until time catches up"); - } - } - - return rdtsc_last_value + rdtsc_imprecision_offset; - } -} - -void store_current_tsc() -{ - *current_tsc = read_tsc(); -} - - -int32_t get_opstats_buffer(int32_t index) -{ - assert(index >= 0 && index < 0x200); - -if( ENABLE_PROFILER_OPSTATS) { - if(index < 0x100) - { - return opstats_buffer[index]; - } - else - { - return opstats_buffer_0f[index - 0x100]; - } -} - - UNUSED(index); - return 0; -} diff --git a/src/native/cpu.h b/src/native/cpu.h deleted file mode 100644 index 7e460f62..00000000 --- a/src/native/cpu.h +++ /dev/null @@ -1,179 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "const.h" -#include "config.h" -#include "shared.h" - -extern uint8_t* mem8; -extern uint16_t* mem16; -extern int32_t* mem32s; - -union reg128 { - int8_t i8[16]; - int16_t i16[8]; - int32_t i32[4]; - int64_t i64[2]; - uint8_t u8[16]; - uint16_t u16[8]; - uint32_t u32[4]; - uint64_t u64[2]; - float_t f32[4]; - double_t f64[2]; -}; -//_Static_assert(sizeof(union reg128) == 16, "reg128 is 16 bytes"); - -union reg64 { - int8_t i8[8]; - int16_t i16[4]; - int32_t i32[2]; - int64_t i64[1]; - uint8_t u8[8]; - uint16_t u16[4]; - uint32_t u32[2]; - uint64_t u64[1]; - float_t f32[2]; - double f64[1]; -}; -//_Static_assert(sizeof(union reg64) == 8, "reg64 is 8 bytes"); - -typedef uint8_t cached_state_flags; - -// Flag indicating whether the instruction that just ran was at a block's boundary (jump, -// state-altering, etc.) -extern bool jit_block_boundary; - -extern const int32_t VALID_TLB_ENTRY_MAX; -extern int32_t valid_tlb_entries[10000]; -extern int32_t valid_tlb_entries_count; - -extern const int32_t TLB_VALID; -extern const int32_t TLB_READONLY; -extern const int32_t TLB_NO_USER; -extern const int32_t TLB_IN_MAPPED_RANGE; -extern const int32_t TLB_GLOBAL; -extern const int32_t TLB_HAS_CODE; - -extern const int32_t CPU_EXCEPTION_DE; // Divide Error -extern const int32_t CPU_EXCEPTION_DB; // Debug Exception -extern const int32_t CPU_EXCEPTION_NMI; // NMI Interrupt -extern const int32_t CPU_EXCEPTION_BP; // Breakpoint -extern const int32_t CPU_EXCEPTION_OF; // Overflow -extern const int32_t CPU_EXCEPTION_BR; // BOUND Range Exceeded -extern const int32_t CPU_EXCEPTION_UD; // Invalid Opcode -extern const int32_t CPU_EXCEPTION_NM; // Device Not Available -extern const int32_t CPU_EXCEPTION_DF; // Double Fault -extern const int32_t CPU_EXCEPTION_TS; // Invalid TSS -extern const int32_t CPU_EXCEPTION_NP; // Segment Not Present -extern const int32_t CPU_EXCEPTION_SS; // Stack-Segment Fault -extern const int32_t CPU_EXCEPTION_GP; // General Protection -extern const int32_t CPU_EXCEPTION_PF; // Page Fault -extern const int32_t CPU_EXCEPTION_MF; // x87 FPU Floating-Point Error -extern const int32_t CPU_EXCEPTION_AC; // Alignment Check -extern const int32_t CPU_EXCEPTION_MC; // Machine Check Abort -extern const int32_t CPU_EXCEPTION_XM; // SIMD Floating-Point Exception -extern const int32_t CPU_EXCEPTION_VE; // Virtualization Exception - -// defined in call-indirect.ll -extern void call_indirect(int32_t index); -extern void call_indirect1(int32_t index, int32_t arg); - -void after_block_boundary(void); - -bool same_page(int32_t, int32_t); - -int32_t get_eflags(void); -uint32_t translate_address_read(int32_t address); -uint32_t translate_address_write(int32_t address); -void tlb_set_has_code(uint32_t physical_page, bool has_code); -void check_tlb_invariants(void); - -void writable_or_pagefault(int32_t addr, int32_t size); -int32_t read_imm8(void); -int32_t read_imm8s(void); -int32_t read_imm16(void); -int32_t read_imm32s(void); -bool is_osize_32(void); -bool is_asize_32(void); -int32_t get_seg(int32_t segment); -int32_t get_seg_cs(void); -int32_t get_seg_ss(void); -int32_t get_seg_prefix(int32_t default_segment); -int32_t get_seg_prefix_ds(int32_t offset); -int32_t get_seg_prefix_ss(int32_t offset); -int32_t get_seg_prefix_cs(int32_t offset); -int32_t modrm_resolve(int32_t modrm_byte); - -void cycle_internal(void); -void run_prefix_instruction(void); -void clear_prefixes(void); -void segment_prefix_op(int32_t seg); - -bool has_flat_segmentation(void); -void do_many_cycles_unsafe(void); -void raise_exception(int32_t interrupt_nr); -void raise_exception_with_code(int32_t interrupt_nr, int32_t error_code); -void trigger_de(void); -void trigger_ud(void); -void trigger_nm(void); -void trigger_gp(int32_t code); -void trigger_gp_non_raising(int32_t code); -int32_t virt_boundary_read16(int32_t low, int32_t high); -int32_t virt_boundary_read32s(int32_t low, int32_t high); -void virt_boundary_write16(int32_t low, int32_t high, int32_t value); -void virt_boundary_write32(int32_t low, int32_t high, int32_t value); -int32_t safe_read8(int32_t addr); -int32_t safe_read16(int32_t addr); -int32_t safe_read32s(int32_t address); -union reg64 safe_read64s(int32_t addr); -union reg128 safe_read128s(int32_t addr); -void safe_write8(int32_t addr, int32_t value); -void safe_write16(int32_t addr, int32_t value); -void safe_write32(int32_t address, int32_t value); -void safe_write64(int32_t addr, int64_t value); -void safe_write128(int32_t addr, union reg128 value); -int32_t get_reg8_index(int32_t index); -int32_t read_reg8(int32_t index); -void write_reg8(int32_t index, int32_t value); -int32_t get_reg16_index(int32_t index); -int32_t read_reg16(int32_t index); -void write_reg16(int32_t index, int32_t value); -int32_t read_reg32(int32_t index); -void write_reg32(int32_t index, int32_t value); -void write_reg_osize(int32_t index, int32_t value); -int32_t read_mmx32s(int32_t r); -union reg64 read_mmx64s(int32_t r); -void write_mmx64(int32_t r, int32_t low, int32_t high); -void write_mmx_reg64(int32_t r, union reg64 data); -float_t read_xmm_f32(int32_t r); -int32_t read_xmm32(int32_t r); -union reg64 read_xmm64s(int32_t r); -union reg128 read_xmm128s(int32_t r); -void write_xmm_f32(int32_t r, float_t data); -void write_xmm32(int32_t r, int32_t); -void write_xmm64(int32_t r, union reg64 data); -void write_xmm128(int32_t r, int32_t i0, int32_t i1, int32_t i2, int32_t i3); -void write_xmm_reg128(int32_t r, union reg128 data); -void clear_tlb(void); -void full_clear_tlb(void); -bool task_switch_test(void); -void task_switch_test_void(void); -bool task_switch_test_mmx(void); -void task_switch_test_mmx_void(void); -int32_t read_moffs(void); -int32_t get_real_eip(void); -int32_t get_stack_reg(void); -void set_stack_reg(int32_t value); -int32_t get_reg_asize(int32_t reg); -void set_ecx_asize(int32_t value); -void add_reg_asize(int32_t reg, int32_t value); -int32_t decr_ecx_asize(void); -void set_tsc(uint32_t, uint32_t); -uint64_t read_tsc(void); -bool vm86_mode(void); -int32_t getiopl(void); - -int32_t get_opstats_buffer(int32_t index); diff --git a/src/native/fpu.c b/src/native/fpu.c deleted file mode 100644 index 53a8be5d..00000000 --- a/src/native/fpu.c +++ /dev/null @@ -1,803 +0,0 @@ -#include -#include -#include - -#include "const.h" -#include "cpu.h" -#include "fpu.h" -#include "global_pointers.h" -#include "js_imports.h" -#include "log.h" -#include "misc_instr.h" - -extern const bool DEBUG; - -//#ifndef M_LOG2E -const double_t M_LOG2E = 1.44269504088896340736; -//#endif - -//#ifndef M_LN2 -const double_t M_LN2 = 0.693147180559945309417; -//#endif - -//#ifndef M_LN10 -const double_t M_LN10 = 2.30258509299404568402; -//#endif - -//#ifndef M_PI -const double_t M_PI = 3.14159265358979323846; -//#endif - -const int32_t FPU_C0 = 0x100; -const int32_t FPU_C1 = 0x200; -const int32_t FPU_C2 = 0x400; -const int32_t FPU_C3 = 0x4000; -const int32_t FPU_RESULT_FLAGS = (FPU_C0 | FPU_C1 | FPU_C2 | FPU_C3); -const int32_t FPU_STACK_TOP = 0x3800; - -// precision, round & infinity control -const int32_t - FPU_PC = 3 << 8, - FPU_RC = 3 << 10, - FPU_IF = 1 << 12; - -// exception bits in the status word -const int32_t - FPU_EX_SF = 1 << 6, - FPU_EX_P = 1 << 5, - FPU_EX_U = 1 << 4, - FPU_EX_O = 1 << 3, - FPU_EX_Z = 1 << 2, - FPU_EX_D = 1 << 1, - FPU_EX_I = 1 << 0; - -const double_t TWO_POW_63 = 0x8000000000000000; -const double_t INDEFINITE_NAN = NAN; - -union f64_int { - uint8_t u8[8]; - int32_t i32[2]; - uint64_t u64[1]; - double_t f64; -}; - -union f32_int { - uint8_t u8[4]; - int32_t i32; - float_t f32; -}; - -void fpu_set_tag_word(int32_t tag_word) -{ - *fpu_stack_empty = 0; - - for(int i = 0; i < 8; i++) - { - *fpu_stack_empty |= (tag_word >> i) & (tag_word >> (i + 1)) & 1 << i; - } -} - -void fpu_fcomi(int32_t r) -{ - double y = fpu_get_sti(r); - double_t x = fpu_st[*fpu_stack_ptr]; - *flags_changed &= ~(1 | FLAG_PARITY | FLAG_ZERO); - *flags &= ~(1 | FLAG_PARITY | FLAG_ZERO); - - if(x > y) - { - } - else if(y > x) - { - *flags |= 1; - } - else if(x == y) - { - *flags |= FLAG_ZERO; - } - else - { - *flags |= 1 | FLAG_PARITY | FLAG_ZERO; - } -} - -void fpu_fcomip(int32_t r) { fpu_fcomi(r); fpu_pop(); } - -int32_t fpu_load_status_word() -{ - return *fpu_status_word & ~(7 << 11) | *fpu_stack_ptr << 11; -} - -void fpu_set_status_word(int32_t sw) -{ - *fpu_status_word = sw & ~(7 << 11); - *fpu_stack_ptr = sw >> 11 & 7; -} - -int32_t fpu_sign(int32_t i) -{ - c_comment("sign of a number on the stack"); - return fpu_st8[(*fpu_stack_ptr + i & 7) << 3 | 7] >> 7; -} - -void fpu_store_m80(uint32_t addr, double_t n) -{ - union f64_int double_int_view = { .f64 = n }; - - uint8_t sign = double_int_view.u8[7] & 0x80; - int32_t exponent = (double_int_view.u8[7] & 0x7f) << 4 | double_int_view.u8[6] >> 4; - int32_t low, high; - - if(exponent == 0x7FF) - { - c_comment("all bits set (NaN and infinity)"); - exponent = 0x7FFF; - low = 0; - high = 0x80000000 | (double_int_view.i32[1] & 0x80000) << 11; - } - else if(exponent == 0) - { - c_comment("zero and denormal numbers"); - c_comment("Just assume zero for now"); - low = 0; - high = 0; - } - else - { - exponent += 0x3FFF - 0x3FF; - - c_comment("does the mantissa need to be adjusted?"); - low = double_int_view.i32[0] << 11; - high = 0x80000000 | (double_int_view.i32[1] & 0xFFFFF) << 11 | (((uint32_t)(double_int_view.i32[0])) >> 21); - } - - dbg_assert(exponent >= 0 && exponent < 0x8000); - - c_comment("writable_or_pagefault must have checked called by the caller!"); - safe_write64(addr, (uint64_t)low & 0xFFFFFFFF | (uint64_t)high << 32); - safe_write16(addr + 8, sign << 8 | exponent); -} - -double_t fpu_load_m80(uint32_t addr) -{ - uint64_t value = safe_read64s(addr).u64[0]; - uint32_t low = value; - uint32_t high = value >> 32; - int32_t exponent = safe_read16(addr + 8); - - int32_t sign = exponent >> 15; - exponent &= ~0x8000; - - if(exponent == 0) - { - c_comment("TODO: denormal numbers"); - return 0; - } - - if(exponent < 0x7FFF) - { - exponent -= 0x3FFF; - } - else - { - c_comment("TODO: NaN, Infinity"); - if(0 * 0) dbg_log("Load m80 TODO"); - - union f64_int double_int_view; - - double_int_view.u8[7] = 0x7F | sign << 7; - double_int_view.u8[6] = 0xF0 | high >> 30 << 3 & 0x08; - - double_int_view.u8[5] = 0; - double_int_view.u8[4] = 0; - - double_int_view.i32[0] = 0; - - return double_int_view.f64; - } - - c_comment("Note: some bits might be lost at this point"); - double_t mantissa = ((double_t)(low)) + 0x100000000 * ((double_t)(high)); - - if(sign) - { - mantissa = -mantissa; - } - - c_comment("Simply compute the 64 bit floating point number."); - c_comment("An alternative write the mantissa, sign and exponent in the"); - c_comment("float64_byte and return float64[0]"); - - return mantissa * pow(2, exponent - 63); -} - -void fpu_stack_fault() -{ - c_comment("TODO: Interrupt"); - *fpu_status_word |= FPU_EX_SF | FPU_EX_I; -} - -void fpu_invalid_arithmetic() -{ - *fpu_status_word |= FPU_EX_I; -} - -double_t fpu_get_st0() -{ - if(*fpu_stack_empty >> *fpu_stack_ptr & 1) - { - *fpu_status_word &= ~FPU_C1; - fpu_stack_fault(); - return INDEFINITE_NAN; - } - else - { - return fpu_st[*fpu_stack_ptr]; - } -} - -void fpu_fcom(double_t y) -{ - double_t x = fpu_get_st0(); - - *fpu_status_word &= ~FPU_RESULT_FLAGS; - - if(x > y) - { - } - else if(y > x) - { - *fpu_status_word |= FPU_C0; - } - else if(x == y) - { - *fpu_status_word |= FPU_C3; - } - else - { - *fpu_status_word |= FPU_C0 | FPU_C2 | FPU_C3; - } -} - -void fpu_fucom(int32_t r) -{ - c_comment("TODO"); - fpu_fcom(fpu_get_sti(r)); -} - - -void fpu_fucomi(int32_t r) -{ - c_comment("TODO"); - fpu_fcomi(r); -} - -void fpu_fucomip(int32_t r) { fpu_fucomi(r); fpu_pop(); } - -void fpu_ftst(double_t x) -{ - *fpu_status_word &= ~FPU_RESULT_FLAGS; - - if(isnan_XXX(x)) - { - *fpu_status_word |= FPU_C3 | FPU_C2 | FPU_C0; - } - else if(x == 0) - { - *fpu_status_word |= FPU_C3; - } - else if(x < 0) - { - *fpu_status_word |= FPU_C0; - } - - c_comment("TODO: unordered (x is nan, etc)"); -} - -void fpu_fxam(double_t x) -{ - *fpu_status_word &= ~FPU_RESULT_FLAGS; - *fpu_status_word |= fpu_sign(0) << 9; - - if(*fpu_stack_empty >> *fpu_stack_ptr & 1) - { - *fpu_status_word |= FPU_C3 | FPU_C0; - } - else if(isnan_XXX(x)) - { - *fpu_status_word |= FPU_C0; - } - else if(x == 0) - { - *fpu_status_word |= FPU_C3; - } - else if(x == INFINITY || x == -INFINITY) - { - *fpu_status_word |= FPU_C2 | FPU_C0; - } - else - { - *fpu_status_word |= FPU_C2; - } - c_comment("TODO:"); - c_comment("Unsupported, Denormal"); -} - -void fpu_finit(void) -{ - *fpu_control_word = 0x37F; - *fpu_status_word = 0; - fpu_ip[0] = 0; - fpu_dp[0] = 0; - fpu_opcode[0] = 0; - - *fpu_stack_empty = 0xFF; - *fpu_stack_ptr = 0; -} - -int32_t fpu_load_tag_word() -{ - int32_t tag_word = 0; - - for(int32_t i = 0; i < 8; i++) - { - double_t value = fpu_st[i]; - - if(*fpu_stack_empty >> i & 1) - { - tag_word |= 3 << (i << 1); - } - else if(value == 0) - { - tag_word |= 1 << (i << 1); - } - else if(!isfinite_XXX(value)) - { - tag_word |= 2 << (i << 1); - } - } - - return tag_word; -} - -void fpu_unimpl() -{ - if(DEBUG) - { - assert(false); - } - else - { - trigger_ud(); - } -} - -void fpu_fstenv(int32_t addr) -{ - if(is_osize_32()) - { - writable_or_pagefault(addr, 26); - - safe_write16(addr, *fpu_control_word); - - safe_write16(addr + 4, fpu_load_status_word()); - safe_write16(addr + 8, fpu_load_tag_word()); - - safe_write32(addr + 12, fpu_ip[0]); - safe_write16(addr + 16, fpu_ip_selector[0]); - safe_write16(addr + 18, fpu_opcode[0]); - safe_write32(addr + 20, fpu_dp[0]); - safe_write16(addr + 24, fpu_dp_selector[0]); - } - else - { - dbg_log("fstenv16"); - fpu_unimpl(); - } -} - -void fpu_fldenv(int32_t addr) -{ - if(is_osize_32()) - { - *fpu_control_word = safe_read16(addr); - - fpu_set_status_word(safe_read16(addr + 4)); - fpu_set_tag_word(safe_read16(addr + 8)); - - fpu_ip[0] = safe_read32s(addr + 12); - fpu_ip_selector[0] = safe_read16(addr + 16); - fpu_opcode[0] = safe_read16(addr + 18); - fpu_dp[0] = safe_read32s(addr + 20); - fpu_dp_selector[0] = safe_read16(addr + 24); - } - else - { - dbg_log("fldenv16"); - fpu_unimpl(); - } -} - -void fpu_fsave(int32_t addr) -{ - writable_or_pagefault(addr, 108); - - fpu_fstenv(addr); - addr += 28; - - for(int32_t i = 0; i < 8; i++) - { - fpu_store_m80(addr, fpu_st[*fpu_stack_ptr + i & 7]); - addr += 10; - } - - fpu_finit(); -} - -void fpu_frstor(int32_t addr) -{ - fpu_fldenv(addr); - addr += 28; - - for(int32_t i = 0; i < 8; i++) - { - fpu_st[(i + *fpu_stack_ptr) & 7] = fpu_load_m80(addr); - addr += 10; - } -} - -void fpu_push(double_t x) -{ - *fpu_stack_ptr = *fpu_stack_ptr - 1 & 7; - - if(*fpu_stack_empty >> *fpu_stack_ptr & 1) - { - *fpu_status_word &= ~FPU_C1; - *fpu_stack_empty &= ~(1 << *fpu_stack_ptr); - fpu_st[*fpu_stack_ptr] = x; - } - else - { - *fpu_status_word |= FPU_C1; - fpu_stack_fault(); - fpu_st[*fpu_stack_ptr] = INDEFINITE_NAN; - } -} - -void fpu_pop() -{ - *fpu_stack_empty |= 1 << *fpu_stack_ptr; - *fpu_stack_ptr = *fpu_stack_ptr + 1 & 7; -} - -double_t fpu_get_sti(int32_t i) -{ - dbg_assert(i >= 0 && i < 8); - - i = i + *fpu_stack_ptr & 7; - - if(*fpu_stack_empty >> i & 1) - { - *fpu_status_word &= ~FPU_C1; - fpu_stack_fault(); - return INDEFINITE_NAN; - } - else - { - return fpu_st[i]; - } -} - -void fpu_fxtract(void) -{ - union f64_int double_int_view = { .f64 = fpu_get_st0() }; - - double_t exponent = ((double_int_view.u8[7] & 0x7F) << 4 | double_int_view.u8[6] >> 4) - 0x3FF; - - double_int_view.u8[7] = 0x3F | (double_int_view.u8[7] & 0x80); - double_int_view.u8[6] |= 0xF0; - - fpu_st[*fpu_stack_ptr] = exponent; - fpu_push(double_int_view.f64); -} - -void fpu_fprem(void) -{ - c_comment("XXX: This implementation differs from the description in Intel's manuals"); - - double_t st0 = fpu_get_st0(); - double_t st1 = fpu_get_sti(1); - int32_t fprem_quotient = convert_f64_to_i32(trunc(st0 / st1)); - fpu_st[*fpu_stack_ptr] = fmod(st0, st1); - - *fpu_status_word &= ~(FPU_C0 | FPU_C1 | FPU_C3); - if (fprem_quotient & 1) { - *fpu_status_word |= FPU_C1; - } - if (fprem_quotient & (1 << 1)) { - *fpu_status_word |= FPU_C3; - } - if (fprem_quotient & (1 << 2)) { - *fpu_status_word |= FPU_C0; - } - - *fpu_status_word &= ~FPU_C2; -} - -double_t fpu_integer_round(double_t f) -{ - int32_t rc = *fpu_control_word >> 10 & 3; - - c_comment("XXX: See https://en.wikipedia.org/wiki/C_mathematical_functions"); - - if(rc == 0) - { - c_comment("Round to nearest, or even if equidistant"); - - double_t rounded = round(f); - double_t diff = rounded - f; - - if(diff == 0.5 || diff == -0.5) - { - rounded = 2.0 * round(f * 0.5); - } - - return rounded; - } - else if(rc == 1 || (rc == 3 && f > 0)) - { - c_comment("rc=3 is truncate -> floor for positive numbers"); - return floor(f); - } - else - { - return ceil(f); - } -} - -double_t fpu_load_m64(int32_t addr) -{ - uint64_t value = safe_read64s(addr).u64[0]; - - union f64_int v = { .u64 = { value } }; - - return v.f64; -} - -void fpu_store_m64(int32_t addr, double_t x) -{ - union f64_int v = { .f64 = x }; - - safe_write64(addr, v.u64[0]); -} - -double_t fpu_load_m32(int32_t addr) -{ - union f32_int v = { .i32 = safe_read32s(addr) }; - return v.f32; -} - -void fpu_store_m32(int32_t addr, double_t x) -{ - union f32_int v = { .f32 = x }; - safe_write32(addr, v.i32); -} - -void fwait(void) -{ - c_comment("NOP unless FPU instructions run in parallel with CPU instructions"); -} - -void fpu_fadd(int32_t target_index, double_t val) -{ - double_t st0 = fpu_get_st0(); - fpu_st[*fpu_stack_ptr + target_index & 7] = st0 + val; -} - -void fpu_fmul(int32_t target_index, double_t val) -{ - double_t st0 = fpu_get_st0(); - fpu_st[*fpu_stack_ptr + target_index & 7] = st0 * val; -} - -void fpu_fcomp(double_t val) -{ - fpu_fcom(val); - fpu_pop(); -} - -void fpu_fsub(int32_t target_index, double_t val) -{ - double_t st0 = fpu_get_st0(); - fpu_st[*fpu_stack_ptr + target_index & 7] = st0 - val; -} - -void fpu_fsubr(int32_t target_index, double_t val) -{ - double_t st0 = fpu_get_st0(); - fpu_st[*fpu_stack_ptr + target_index & 7] = val - st0; -} - -void fpu_fdiv(int32_t target_index, double_t val) -{ - double_t st0 = fpu_get_st0(); - fpu_st[*fpu_stack_ptr + target_index & 7] = st0 / val; -} - -void fpu_fdivr(int32_t target_index, double_t val) -{ - double_t st0 = fpu_get_st0(); - fpu_st[*fpu_stack_ptr + target_index & 7] = val / st0; -} - -void fpu_fxch(int32_t i) -{ - double_t sti = fpu_get_sti(i); - fpu_st[*fpu_stack_ptr + i] = fpu_get_st0(); - fpu_st[*fpu_stack_ptr] = sti; -} - -void fpu_fldm32(int32_t addr) -{ - fpu_push(safe_read32s(addr)); -} - -void fpu_fstm32(int32_t addr) -{ - fpu_store_m32(addr, fpu_get_st0()); -} - -void fpu_fstm32p(int32_t addr) -{ - fpu_fstm32(addr); - fpu_pop(); -} - -void fpu_fldm64(int32_t addr) -{ - fpu_push(fpu_load_m64(addr)); -} - -void fpu_fstm64(int32_t addr) -{ - fpu_store_m64(addr, fpu_get_st0()); -} - -void fpu_fstm64p(int32_t addr) -{ - fpu_fstm64(addr); - fpu_pop(); -} - -void fpu_fnstsw_mem(int32_t addr) -{ - safe_write16(addr, fpu_load_status_word()); -} - -void fpu_fnstsw_reg(void) -{ - reg16[AX] = fpu_load_status_word(); -} - -void fpu_fldcw(int32_t addr) -{ - int32_t word = safe_read16(addr); - *fpu_control_word = word; -} - -void fpu_fstcw(int32_t addr) -{ - safe_write16(addr, *fpu_control_word); -} - -void fpu_fcmovcc(bool condition, int32_t r) -{ - if(condition) - { - fpu_st[*fpu_stack_ptr] = fpu_get_sti(r); - *fpu_stack_empty &= ~(1 << *fpu_stack_ptr); - } -} - -void fpu_fucomp(int32_t r) -{ - fpu_fucom(r); - fpu_pop(); -} - -void fpu_fucompp(void) -{ - fpu_fucom(1); - fpu_pop(); - fpu_pop(); -} - -void fpu_fclex(void) { *fpu_status_word = 0; } - -void fpu_fistm16(int32_t addr) -{ - double_t st0 = fpu_integer_round(fpu_get_st0()); - if(st0 <= 0x7FFF && st0 >= -0x8000) - { - safe_write16(addr, st0); - } - else - { - fpu_invalid_arithmetic(); - safe_write16(addr, 0x8000); - } -} -void fpu_fistm16p(int32_t addr) { fpu_fistm16(addr); fpu_pop(); } - -void fpu_fistm32(int32_t addr) -{ - double_t st0 = fpu_integer_round(fpu_get_st0()); - int32_t i = convert_f64_to_i32(st0); - if(i == (int32_t)0x80000000) - { - c_comment("XXX: Probably not correct if st0 == 0x80000000"); - c_comment("(input fits, but same value as error value)"); - fpu_invalid_arithmetic(); - } - safe_write32(addr, i); -} - -void fpu_fistm32p(int32_t addr) { fpu_fistm32(addr); fpu_pop(); } - -void fpu_fldm80(int32_t addr) -{ - fpu_push(fpu_load_m80(addr)); -} - -void fpu_fst80p(int32_t addr) -{ - writable_or_pagefault(addr, 10); - fpu_store_m80(addr, fpu_get_st0()); - fpu_pop(); -} - -void fpu_ffree(int32_t r) -{ - *fpu_stack_empty |= 1 << (*fpu_stack_ptr + r); -} - -void fpu_fst(int32_t r) -{ - fpu_st[*fpu_stack_ptr + r] = fpu_get_st0(); -} - -void fpu_fstp(int32_t r) -{ - fpu_fst(r); - fpu_pop(); -} - -void fpu_fildm64(int32_t addr) -{ - int64_t value = safe_read64s(addr).i64[0]; - - double_t m64 = (double_t)value; - - fpu_push(m64); -} - -void fpu_fistm64p(int32_t addr) -{ - double_t st0 = fpu_integer_round(fpu_get_st0()); - - int64_t value; - - if(st0 < TWO_POW_63 && st0 >= -TWO_POW_63) - { - value = st0; - } - else - { - value = 0x8000000000000000; - fpu_invalid_arithmetic(); - } - - safe_write64(addr, value); - - fpu_pop(); -} diff --git a/src/native/fpu.h b/src/native/fpu.h deleted file mode 100644 index abea6e1c..00000000 --- a/src/native/fpu.h +++ /dev/null @@ -1,91 +0,0 @@ -#pragma once - -#include -#include -#include - -//#ifndef M_LOG2E -extern const double_t M_LOG2E; -//#endif - -//#ifndef M_LN2 -extern const double_t M_LN2; -//#endif - -//#ifndef M_LN10 -extern const double_t M_LN10; -//#endif - -//#ifndef M_PI -extern const double_t M_PI; -//#endif - -extern const int32_t FPU_C0; -extern const int32_t FPU_C1; -extern const int32_t FPU_C2; -extern const int32_t FPU_C3; -extern const int32_t FPU_RESULT_FLAGS; -extern const int32_t FPU_STACK_TOP; - -double_t fpu_get_st0(void); -double_t fpu_get_sti(int32_t i); -double_t fpu_integer_round(double_t f); -double_t fpu_load_m32(int32_t addr); -double_t fpu_load_m64(int32_t addr); -double_t fpu_load_m80(uint32_t addr); -double_t fpu_truncate(double_t x); -int32_t fpu_load_status_word(void); -void fpu_fadd(int32_t target_index, double_t val); -void fpu_fclex(void); -void fpu_fcmovcc(bool condition, int32_t r); -void fpu_fcom(double_t y); -void fpu_fcomi(int32_t r); -void fpu_fcomip(int32_t r); -void fpu_fcomp(double_t val); -void fpu_fdiv(int32_t target_index, double_t val); -void fpu_fdivr(int32_t target_index, double_t val); -void fpu_ffree(int32_t r); -void fpu_fildm64(int32_t addr); -void fpu_finit(void); -void fpu_fistm16(int32_t addr); -void fpu_fistm16p(int32_t addr); -void fpu_fistm32(int32_t addr); -void fpu_fistm32p(int32_t addr); -void fpu_fistm64p(int32_t addr); -void fpu_fldcw(int32_t addr); -void fpu_fldenv(int32_t addr); -void fpu_fldm32(int32_t addr); -void fpu_fldm64(int32_t addr); -void fpu_fldm80(int32_t addr); -void fpu_fmul(int32_t target_index, double_t val); -void fpu_fnstsw_mem(int32_t addr); -void fpu_fnstsw_reg(void); -void fpu_fprem(void); -void fpu_frstor(int32_t addr); -void fpu_fsave(int32_t addr); -void fpu_fst(int32_t r); -void fpu_fst80p(int32_t addr); -void fpu_fstcw(int32_t addr); -void fpu_fstenv(int32_t addr); -void fpu_fstm32(int32_t addr); -void fpu_fstm32p(int32_t addr); -void fpu_fstm64(int32_t addr); -void fpu_fstm64p(int32_t addr); -void fpu_fstp(int32_t r); -void fpu_fsub(int32_t target_index, double_t val); -void fpu_fsubr(int32_t target_index, double_t val); -void fpu_ftst(double_t x); -void fpu_fucom(int32_t r); -void fpu_fucomi(int32_t r); -void fpu_fucomip(int32_t r); -void fpu_fucomp(int32_t r); -void fpu_fucompp(void); -void fpu_fxam(double_t x); -void fpu_fxch(int32_t i); -void fpu_fxtract(void); -void fpu_pop(void); -void fpu_push(double_t x); -void fpu_set_status_word(int32_t sw); -void fpu_set_tag_word(int32_t tag_word); -void fpu_store_m80(uint32_t addr, double_t n); -void fwait(void); diff --git a/src/native/global_pointers.c b/src/native/global_pointers.c deleted file mode 100644 index 5ec4c4ff..00000000 --- a/src/native/global_pointers.c +++ /dev/null @@ -1,94 +0,0 @@ -#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; -int16_t* const reg16s = (int16_t* const) 4; -int32_t* const reg32s = (int32_t* const) 4; - -int32_t* const last_op1 = (int32_t* const) 512; -int32_t* const last_op2 = (int32_t* const) 516; -int32_t* const last_op_size = (int32_t* const) 520; -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; - -bool* const page_fault = (bool* const) 540; - -// gap - -bool* const a20_enabled = (bool* const) 552; -int32_t* const instruction_pointer = (int32_t* const) 556; -int32_t* const previous_ip = (int32_t* const) 560; - -int32_t* const idtr_size = (int32_t* const) 564; -int32_t* const idtr_offset = (int32_t* const) 568; -int32_t* const gdtr_size = (int32_t* const) 572; -int32_t* const gdtr_offset = (int32_t* const) 576; -int32_t* const cr = (int32_t* const) 580; // length 32 - -uint8_t* const cpl = (uint8_t* const) 612; -bool* const in_hlt = (bool* const) 616; -int32_t* const last_virt_eip = (int32_t* const) 620; -int32_t* const eip_phys = (int32_t* const) 624; -int32_t* const last_virt_esp = (int32_t* const) 628; -int32_t* const esp_phys = (int32_t* const) 632; -int32_t* const sysenter_cs = (int32_t* const) 636; -int32_t* const sysenter_esp = (int32_t* const) 640; -int32_t* const sysenter_eip = (int32_t* const) 644; -uint8_t* const prefixes = (uint8_t* const) 648; -// gap -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 -int32_t* const fw_value = (int32_t* const) 720; -bool* const segment_is_null = (bool* const) 724; // length 8 -int32_t* const segment_offsets = (int32_t* const) 736; // length 32 -uint32_t* const segment_limits = (uint32_t* const) 768; // length 32 - -bool* const protected_mode = (bool* const) 800; -bool* const is_32 = (bool* const) 804; -bool* const stack_size_32 = (bool* const) 808; -uint32_t* const memory_size = (uint32_t* const) 812; -int32_t* const fpu_stack_empty = (int32_t* const) 816; - -// gap - -int32_t* const mxcsr = (int32_t* const) 824; - -union reg128* const reg_xmm = (union reg128* const) 828; // length 128 - -uint64_t* const current_tsc = (uint64_t* const) 956; - -double_t* const fpu_st = (double_t* const) 968; // length 64 -uint8_t* const fpu_st8 = (uint8_t* const) 968; -int32_t* const fpu_st32 = (int32_t* const) 968; - -uint32_t* const fpu_stack_ptr = (uint32_t* const) 1032; -int32_t* const fpu_control_word = (int32_t* const) 1036; -int32_t* const fpu_status_word = (int32_t* const) 1040; -int32_t* const fpu_opcode = (int32_t* const) 1044; -int32_t* const fpu_ip = (int32_t* const) 1048; -int32_t* const fpu_ip_selector = (int32_t* const) 1052; -int32_t* const fpu_dp = (int32_t* const) 1056; -int32_t* const fpu_dp_selector = (int32_t* const) 1060; - -union reg64* const reg_mmx = (union reg64* const) 1064; // length 64 - -extern bool* const tss_size_32 = (bool* const) 1128; - -// gap - -uint32_t* const opstats_buffer = (uint32_t* const) 0x1000; // length 0x400 -uint32_t* const opstats_buffer_0f = (uint32_t* const) 0x1400; // length 0x400 - -// gap - -int32_t* const tlb_data = (int32_t* const) 0x400000; // length 0x100000*4 diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h deleted file mode 100644 index d2c372ea..00000000 --- a/src/native/global_pointers.h +++ /dev/null @@ -1,96 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "const.h" -#include "shared.h" - -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; - -extern int32_t* const last_op1; -extern int32_t* const last_op2; -extern int32_t* const last_op_size; -extern int32_t* const last_add_result; -extern int32_t* const last_result; -extern int32_t* const flags_changed; -extern int32_t* const flags; - -extern bool* const page_fault; - -// gap - -extern bool* const a20_enabled; -extern int32_t* const instruction_pointer; -extern int32_t* const previous_ip; - -extern int32_t* const idtr_size; -extern int32_t* const idtr_offset; -extern int32_t* const gdtr_size; -extern int32_t* const gdtr_offset; -extern int32_t* const cr; // length 32 - -extern uint8_t* const cpl; -extern bool* const in_hlt; -extern int32_t* const last_virt_eip; -extern int32_t* const eip_phys; -extern int32_t* const last_virt_esp; -extern int32_t* const esp_phys; -extern int32_t* const sysenter_cs; -extern int32_t* const sysenter_esp; -extern int32_t* const sysenter_eip; -extern uint8_t* const prefixes; -// gap -extern uint32_t* const timestamp_counter; - -extern uint16_t* const sreg; -extern int32_t* const dreg; // length 32 -extern int32_t* const fw_value; -extern bool* const segment_is_null; // length 8 -extern int32_t* const segment_offsets; // length 32 -extern uint32_t* const segment_limits; // length 32 - -extern bool* const protected_mode; -extern bool* const is_32; -extern bool* const stack_size_32; -extern uint32_t* const memory_size; -extern int32_t* const fpu_stack_empty; - -// gap - -extern int32_t* const mxcsr; - -extern union reg128* const reg_xmm; // length 128 - -extern uint64_t* const current_tsc; - -extern double_t* const fpu_st; // length 64 -extern uint8_t* const fpu_st8; -extern int32_t* const fpu_st32; - -extern uint32_t* const fpu_stack_ptr; -extern int32_t* const fpu_control_word; -extern int32_t* const fpu_status_word; -extern int32_t* const fpu_opcode; -extern int32_t* const fpu_ip; -extern int32_t* const fpu_ip_selector; -extern int32_t* const fpu_dp; -extern int32_t* const fpu_dp_selector; - -extern union reg64* const reg_mmx; // length 64 - -extern bool* const tss_size_32; - -// gap - -extern uint32_t* const opstats_buffer; // length 0x400 -extern uint32_t* const opstats_buffer_0f; // length 0x400 - -// gap - -extern int32_t* const tlb_data; // length 0x100000*4 diff --git a/src/native/instructions.c b/src/native/instructions.c deleted file mode 100644 index 20f9cdcf..00000000 --- a/src/native/instructions.c +++ /dev/null @@ -1,1657 +0,0 @@ -#include -#include - -#include "arith.h" -#include "const.h" -#include "cpu.h" -#include "fpu.h" -#include "global_pointers.h" -#include "instructions.h" -#include "instructions_0f.h" -#include "js_imports.h" -#include "log.h" -#include "memory.h" -#include "misc_instr.h" -#include "profiler/profiler.h" -#include "shared.h" -#include "string.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-parameter" - -DEFINE_MODRM_INSTR_READ_WRITE_8(instr_00, add8(___, read_reg8(r))) -DEFINE_MODRM_INSTR_READ_WRITE_16(instr16_01, add16(___, read_reg16(r))) -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), ___))) -void instr_04(int32_t imm8) { reg8[AL] = add8(reg8[AL], imm8); } -void instr16_05(int32_t imm16) { reg16[AX] = add16(reg16[AX], imm16); } -void instr32_05(int32_t imm32) { reg32s[EAX] = add32(reg32s[EAX], imm32); } - -void instr16_06() { push16(sreg[ES]); } -void instr32_06() { push32(sreg[ES]); } -void instr16_07() { - if(!switch_seg(ES, safe_read16(get_stack_pointer(0)))) return; - adjust_stack_reg(2); -} -void instr32_07() { - if(!switch_seg(ES, safe_read32s(get_stack_pointer(0)) & 0xFFFF)) return; - adjust_stack_reg(4); -} - -DEFINE_MODRM_INSTR_READ_WRITE_8(instr_08, or8(___, read_reg8(r))) -DEFINE_MODRM_INSTR_READ_WRITE_16(instr16_09, or16(___, read_reg16(r))) -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), ___))) -void instr_0C(int32_t imm8) { reg8[AL] = or8(reg8[AL], imm8); } -void instr16_0D(int32_t imm16) { reg16[AX] = or16(reg16[AX], imm16); } -void instr32_0D(int32_t imm32) { reg32s[EAX] = or32(reg32s[EAX], imm32); } - - -void instr16_0E() { push16(sreg[CS]); } -void instr32_0E() { push32(sreg[CS]); } -void instr16_0F() { - run_instruction0f_16(read_imm8()); -} -void instr32_0F() { - run_instruction0f_32(read_imm8()); -} - - -DEFINE_MODRM_INSTR_READ_WRITE_8(instr_10, adc8(___, read_reg8(r))) -DEFINE_MODRM_INSTR_READ_WRITE_16(instr16_11, adc16(___, read_reg16(r))) -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), ___))) -void instr_14(int32_t imm8) { reg8[AL] = adc8(reg8[AL], imm8); } -void instr16_15(int32_t imm16) { reg16[AX] = adc16(reg16[AX], imm16); } -void instr32_15(int32_t imm32) { reg32s[EAX] = adc32(reg32s[EAX], imm32); } - -void instr16_16() { push16(sreg[SS]); } -void instr32_16() { push32(sreg[SS]); } -void instr16_17() { - if(!switch_seg(SS, safe_read16(get_stack_pointer(0)))) return; - adjust_stack_reg(2); - //clear_prefixes(); - //cycle_internal(); -} -void instr32_17() { - if(!switch_seg(SS, safe_read32s(get_stack_pointer(0)) & 0xFFFF)) return; - adjust_stack_reg(4); - //clear_prefixes(); - //cycle_internal(); -} - -DEFINE_MODRM_INSTR_READ_WRITE_8(instr_18, sbb8(___, read_reg8(r))) -DEFINE_MODRM_INSTR_READ_WRITE_16(instr16_19, sbb16(___, read_reg16(r))) -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), ___))) -void instr_1C(int32_t imm8) { reg8[AL] = sbb8(reg8[AL], imm8); } -void instr16_1D(int32_t imm16) { reg16[AX] = sbb16(reg16[AX], imm16); } -void instr32_1D(int32_t imm32) { reg32s[EAX] = sbb32(reg32s[EAX], imm32); } - - -void instr16_1E() { push16(sreg[DS]); } -void instr32_1E() { push32(sreg[DS]); } -void instr16_1F() { - if(!switch_seg(DS, safe_read16(get_stack_pointer(0)))) return; - adjust_stack_reg(2); -} -void instr32_1F() { - if(!switch_seg(DS, safe_read32s(get_stack_pointer(0)) & 0xFFFF)) return; - adjust_stack_reg(4); -} - -DEFINE_MODRM_INSTR_READ_WRITE_8(instr_20, and8(___, read_reg8(r))) -DEFINE_MODRM_INSTR_READ_WRITE_16(instr16_21, and16(___, read_reg16(r))) -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), ___))) -void instr_24(int32_t imm8) { reg8[AL] = and8(reg8[AL], imm8); } -void instr16_25(int32_t imm16) { reg16[AX] = and16(reg16[AX], imm16); } -void instr32_25(int32_t imm32) { reg32s[EAX] = and32(reg32s[EAX], imm32); } - - -void instr_26() { segment_prefix_op(ES); } -void instr_27() { bcd_daa(); } - -DEFINE_MODRM_INSTR_READ_WRITE_8(instr_28, sub8(___, read_reg8(r))) -DEFINE_MODRM_INSTR_READ_WRITE_16(instr16_29, sub16(___, read_reg16(r))) -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), ___))) -void instr_2C(int32_t imm8) { reg8[AL] = sub8(reg8[AL], imm8); } -void instr16_2D(int32_t imm16) { reg16[AX] = sub16(reg16[AX], imm16); } -void instr32_2D(int32_t imm32) { reg32s[EAX] = sub32(reg32s[EAX], imm32); } - -void instr_2E() { segment_prefix_op(CS); } -void instr_2F() { bcd_das(); } - -DEFINE_MODRM_INSTR_READ_WRITE_8(instr_30, xor8(___, read_reg8(r))) -DEFINE_MODRM_INSTR_READ_WRITE_16(instr16_31, xor16(___, read_reg16(r))) -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), ___))) -void instr_34(int32_t imm8) { reg8[AL] = xor8(reg8[AL], imm8); } -void instr16_35(int32_t imm16) { reg16[AX] = xor16(reg16[AX], imm16); } -void instr32_35(int32_t imm32) { reg32s[EAX] = xor32(reg32s[EAX], imm32); } - -void instr_36() { segment_prefix_op(SS); } -void instr_37() { bcd_aaa(); } - -DEFINE_MODRM_INSTR_READ8(instr_38, cmp8(___, read_reg8(r))) -DEFINE_MODRM_INSTR_READ16(instr16_39, cmp16(___, read_reg16(r))) -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), ___)) -void instr_3C(int32_t imm8) { cmp8(reg8[AL], imm8); } -void instr16_3D(int32_t imm16) { cmp16(reg16[AX], imm16); } -void instr32_3D(int32_t imm32) { cmp32(reg32s[EAX], imm32); } - -void instr_3E() { segment_prefix_op(DS); } -void instr_3F() { bcd_aas(); } - - -void instr16_40() { reg16[AX] = inc16(reg16[AX]); } -void instr32_40() { reg32s[EAX] = inc32(reg32s[EAX]); } -void instr16_41() { reg16[CX] = inc16(reg16[CX]); } -void instr32_41() { reg32s[ECX] = inc32(reg32s[ECX]); } -void instr16_42() { reg16[DX] = inc16(reg16[DX]); } -void instr32_42() { reg32s[EDX] = inc32(reg32s[EDX]); } -void instr16_43() { reg16[BX] = inc16(reg16[BX]); } -void instr32_43() { reg32s[EBX] = inc32(reg32s[EBX]); } -void instr16_44() { reg16[SP] = inc16(reg16[SP]); } -void instr32_44() { reg32s[ESP] = inc32(reg32s[ESP]); } -void instr16_45() { reg16[BP] = inc16(reg16[BP]); } -void instr32_45() { reg32s[EBP] = inc32(reg32s[EBP]); } -void instr16_46() { reg16[SI] = inc16(reg16[SI]); } -void instr32_46() { reg32s[ESI] = inc32(reg32s[ESI]); } -void instr16_47() { reg16[DI] = inc16(reg16[DI]); } -void instr32_47() { reg32s[EDI] = inc32(reg32s[EDI]); } - - -void instr16_48() { reg16[AX] = dec16(reg16[AX]); } -void instr32_48() { reg32s[EAX] = dec32(reg32s[EAX]); } -void instr16_49() { reg16[CX] = dec16(reg16[CX]); } -void instr32_49() { reg32s[ECX] = dec32(reg32s[ECX]); } -void instr16_4A() { reg16[DX] = dec16(reg16[DX]); } -void instr32_4A() { reg32s[EDX] = dec32(reg32s[EDX]); } -void instr16_4B() { reg16[BX] = dec16(reg16[BX]); } -void instr32_4B() { reg32s[EBX] = dec32(reg32s[EBX]); } -void instr16_4C() { reg16[SP] = dec16(reg16[SP]); } -void instr32_4C() { reg32s[ESP] = dec32(reg32s[ESP]); } -void instr16_4D() { reg16[BP] = dec16(reg16[BP]); } -void instr32_4D() { reg32s[EBP] = dec32(reg32s[EBP]); } -void instr16_4E() { reg16[SI] = dec16(reg16[SI]); } -void instr32_4E() { reg32s[ESI] = dec32(reg32s[ESI]); } -void instr16_4F() { reg16[DI] = dec16(reg16[DI]); } -void instr32_4F() { reg32s[EDI] = dec32(reg32s[EDI]); } - - -void instr16_50() { push16(reg16[AX]); } -void instr32_50() { push32(reg32s[EAX]); } -void instr16_51() { push16(reg16[CX]); } -void instr32_51() { push32(reg32s[ECX]); } -void instr16_52() { push16(reg16[DX]); } -void instr32_52() { push32(reg32s[EDX]); } -void instr16_53() { push16(reg16[BX]); } -void instr32_53() { push32(reg32s[EBX]); } -void instr16_54() { push16(reg16[SP]); } -void instr32_54() { push32(reg32s[ESP]); } -void instr16_55() { push16(reg16[BP]); } -void instr32_55() { push32(reg32s[EBP]); } -void instr16_56() { push16(reg16[SI]); } -void instr32_56() { push32(reg32s[ESI]); } -void instr16_57() { push16(reg16[DI]); } -void instr32_57() { push32(reg32s[EDI]); } - -void instr16_58() { reg16[AX] = pop16(); } -void instr32_58() { reg32s[EAX] = pop32s(); } -void instr16_59() { reg16[CX] = pop16(); } -void instr32_59() { reg32s[ECX] = pop32s(); } -void instr16_5A() { reg16[DX] = pop16(); } -void instr32_5A() { reg32s[EDX] = pop32s(); } -void instr16_5B() { reg16[BX] = pop16(); } -void instr32_5B() { reg32s[EBX] = pop32s(); } -void instr16_5C() { reg16[SP] = safe_read16(get_stack_pointer(0)); } -void instr32_5C() { reg32s[ESP] = safe_read32s(get_stack_pointer(0)); } -void instr16_5D() { reg16[BP] = pop16(); } -void instr32_5D() { reg32s[EBP] = pop32s(); } -void instr16_5E() { reg16[SI] = pop16(); } -void instr32_5E() { reg32s[ESI] = pop32s(); } -void instr16_5F() { reg16[DI] = pop16(); } -void instr32_5F() { reg32s[EDI] = pop32s(); } - -void instr16_60() { pusha16(); } -void instr32_60() { pusha32(); } -void instr16_61() { popa16(); } -void instr32_61() { popa32(); } - -void instr_62_reg(int32_t r2, int32_t r) { - c_comment("bound"); - dbg_log("Unimplemented BOUND instruction"); - dbg_assert(false); -} -void instr_62_mem(int32_t addr, int32_t r) { - dbg_log("Unimplemented BOUND instruction"); - dbg_assert(false); -} - -DEFINE_MODRM_INSTR_READ_WRITE_16(instr_63, arpl(___, read_reg16(r))) - -void instr_64() { segment_prefix_op(FS); } -void instr_65() { segment_prefix_op(GS); } - -void instr_66() { - c_comment("Operand-size override prefix"); - *prefixes |= PREFIX_MASK_OPSIZE; - run_prefix_instruction(); - *prefixes = 0; -} - -void instr_67() { - c_comment("Address-size override prefix"); - dbg_assert(is_asize_32() == *is_32); - *prefixes |= PREFIX_MASK_ADDRSIZE; - run_prefix_instruction(); - *prefixes = 0; -} - -void instr16_68(int32_t imm16) { push16(imm16); } -void instr32_68(int32_t imm32) { push32(imm32); } - -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)); } -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)); } -void instr32_69_mem(int32_t addr, int32_t r, int32_t imm) { write_reg32(r, imul_reg32(safe_read32s(addr), imm)); } -void instr32_69_reg(int32_t r1, int32_t r, int32_t imm) { write_reg32(r, imul_reg32(read_reg32(r1), imm)); } - -void instr16_6A(int32_t imm8) { push16(imm8); } -void instr32_6A(int32_t imm8) { push32(imm8); } - -void instr16_6B_mem(int32_t addr, int32_t r, int32_t imm) { write_reg16(r, imul_reg16(safe_read16(addr) << 16 >> 16, imm)); } -void instr16_6B_reg(int32_t r1, int32_t r, int32_t imm) { write_reg16(r, imul_reg16(read_reg16(r1) << 16 >> 16, imm)); } -void instr32_6B_mem(int32_t addr, int32_t r, int32_t imm) { write_reg32(r, imul_reg32(safe_read32s(addr), imm)); } -void instr32_6B_reg(int32_t r1, int32_t r, int32_t imm) { write_reg32(r, imul_reg32(read_reg32(r1), imm)); } - -void instr_6C() { insb_no_rep(); } -void instr_F26C() { insb_rep(); } -void instr_F36C() { insb_rep(); } -void instr16_6D() { insw_no_rep(); } -void instr16_F26D() { insw_rep(); } -void instr16_F36D() { insw_rep(); } -void instr32_6D() { insd_no_rep(); } -void instr32_F26D() { insd_rep(); } -void instr32_F36D() { insd_rep(); } - -void instr_6E() { outsb_no_rep(); } -void instr_F26E() { outsb_rep(); } -void instr_F36E() { outsb_rep(); } -void instr16_6F() { outsw_no_rep(); } -void instr16_F26F() { outsw_rep(); } -void instr16_F36F() { outsw_rep(); } -void instr32_6F() { outsd_no_rep(); } -void instr32_F26F() { outsd_rep(); } -void instr32_F36F() { outsd_rep(); } - -void instr16_70(int32_t imm8) { jmpcc16( test_o(), imm8); } -void instr16_71(int32_t imm8) { jmpcc16(!test_o(), imm8); } -void instr16_72(int32_t imm8) { jmpcc16( test_b(), imm8); } -void instr16_73(int32_t imm8) { jmpcc16(!test_b(), imm8); } -void instr16_74(int32_t imm8) { jmpcc16( test_z(), imm8); } -void instr16_75(int32_t imm8) { jmpcc16(!test_z(), imm8); } -void instr16_76(int32_t imm8) { jmpcc16( test_be(), imm8); } -void instr16_77(int32_t imm8) { jmpcc16(!test_be(), imm8); } -void instr16_78(int32_t imm8) { jmpcc16( test_s(), imm8); } -void instr16_79(int32_t imm8) { jmpcc16(!test_s(), imm8); } -void instr16_7A(int32_t imm8) { jmpcc16( test_p(), imm8); } -void instr16_7B(int32_t imm8) { jmpcc16(!test_p(), imm8); } -void instr16_7C(int32_t imm8) { jmpcc16( test_l(), imm8); } -void instr16_7D(int32_t imm8) { jmpcc16(!test_l(), imm8); } -void instr16_7E(int32_t imm8) { jmpcc16( test_le(), imm8); } -void instr16_7F(int32_t imm8) { jmpcc16(!test_le(), imm8); } - -void instr32_70(int32_t imm8) { jmpcc32( test_o(), imm8); } -void instr32_71(int32_t imm8) { jmpcc32(!test_o(), imm8); } -void instr32_72(int32_t imm8) { jmpcc32( test_b(), imm8); } -void instr32_73(int32_t imm8) { jmpcc32(!test_b(), imm8); } -void instr32_74(int32_t imm8) { jmpcc32( test_z(), imm8); } -void instr32_75(int32_t imm8) { jmpcc32(!test_z(), imm8); } -void instr32_76(int32_t imm8) { jmpcc32( test_be(), imm8); } -void instr32_77(int32_t imm8) { jmpcc32(!test_be(), imm8); } -void instr32_78(int32_t imm8) { jmpcc32( test_s(), imm8); } -void instr32_79(int32_t imm8) { jmpcc32(!test_s(), imm8); } -void instr32_7A(int32_t imm8) { jmpcc32( test_p(), imm8); } -void instr32_7B(int32_t imm8) { jmpcc32(!test_p(), imm8); } -void instr32_7C(int32_t imm8) { jmpcc32( test_l(), imm8); } -void instr32_7D(int32_t imm8) { jmpcc32(!test_l(), imm8); } -void instr32_7E(int32_t imm8) { jmpcc32( test_le(), imm8); } -void instr32_7F(int32_t imm8) { jmpcc32(!test_le(), imm8); } - -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)) -void instr_80_7_reg(int32_t r, int32_t imm) { cmp8(read_reg8(r), imm); } -void instr_80_7_mem(int32_t addr, int32_t imm) { cmp8(safe_read8(addr), imm); } - -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)) -void instr16_81_7_reg(int32_t r, int32_t imm) { cmp16(read_reg16(r), imm); } -void instr16_81_7_mem(int32_t addr, int32_t imm) { cmp16(safe_read16(addr), imm); } - -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)) -void instr32_81_7_reg(int32_t r, int32_t imm) { cmp32(read_reg32(r), imm); } -void instr32_81_7_mem(int32_t addr, int32_t imm) { cmp32(safe_read32s(addr), imm); } - -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)) -void instr_82_7_reg(int32_t r, int32_t imm) { cmp8(read_reg8(r), imm); } -void instr_82_7_mem(int32_t addr, int32_t imm) { cmp8(safe_read8(addr), imm); } - -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)) -void instr16_83_7_reg(int32_t r, int32_t imm) { cmp16(read_reg16(r), imm); } -void instr16_83_7_mem(int32_t addr, int32_t imm) { cmp16(safe_read16(addr), imm); } - -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)) -void instr32_83_7_reg(int32_t r, int32_t imm) { cmp32(read_reg32(r), imm); } -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))) -DEFINE_MODRM_INSTR_READ32(instr32_85, test32(___, read_reg32(r))) - -DEFINE_MODRM_INSTR_READ_WRITE_8(instr_86, xchg8(___, get_reg8_index(r))) -DEFINE_MODRM_INSTR_READ_WRITE_16(instr16_87, xchg16(___, get_reg16_index(r))) -DEFINE_MODRM_INSTR_READ_WRITE_32(instr32_87, xchg32(___, r)) - -void instr_88_reg(int32_t r2, int32_t r) { write_reg8(r2, read_reg8(r)); } -void instr_88_mem(int32_t addr, int32_t r) { safe_write8(addr, read_reg8(r)); } -void instr16_89_reg(int32_t r2, int32_t r) { write_reg16(r2, read_reg16(r)); } -void instr16_89_mem(int32_t addr, int32_t r) { safe_write16(addr, read_reg16(r)); } -void instr32_89_reg(int32_t r2, int32_t r) { write_reg32(r2, read_reg32(r)); } -void instr32_89_mem(int32_t addr, int32_t r) { safe_write32(addr, read_reg32(r)); } - -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, ___)) - -bool instr_8C_check_sreg(int32_t seg) { - if(seg >= 6) - { - dbg_log("mov sreg #ud"); - trigger_ud(); - return false; - } - - return true; -} -void instr16_8C_reg(int32_t r, int32_t seg) { if(instr_8C_check_sreg(seg)) write_reg16(r, sreg[seg]); } -void instr16_8C_mem(int32_t addr, int32_t seg) { if(instr_8C_check_sreg(seg)) safe_write16(addr, sreg[seg]); } -void instr32_8C_reg(int32_t r, int32_t seg) { if(instr_8C_check_sreg(seg)) write_reg32(r, sreg[seg]); } -void instr32_8C_mem(int32_t addr, int32_t seg) { if(instr_8C_check_sreg(seg)) safe_write32(addr, sreg[seg]); } - -void instr16_8D_reg(int32_t r, int32_t r2) -{ - dbg_log("lea #ud"); - trigger_ud(); -} -void instr16_8D_mem_pre() -{ - c_comment("override prefix, so modrm_resolve does not return the segment part"); - *prefixes |= SEG_PREFIX_ZERO; -} -void instr16_8D_mem(int32_t addr, int32_t r) -{ - c_comment("lea"); - write_reg16(r, addr); - *prefixes = 0; -} -void instr32_8D_reg(int32_t r, int32_t r2) -{ - dbg_log("lea #ud"); - trigger_ud(); -} -void instr32_8D_mem_pre() -{ - c_comment("override prefix, so modrm_resolve does not return the segment part"); - *prefixes |= SEG_PREFIX_ZERO; -} -void instr32_8D_mem(int32_t addr, int32_t r) { - c_comment("lea"); - write_reg32(r, addr); - *prefixes = 0; -} - -void instr_8E_helper(int32_t data, int32_t mod) -{ - if(mod == ES || mod == SS || mod == DS || mod == FS || mod == GS) - { - if(!switch_seg(mod, data)) return; - - if(mod == SS) - { - // run next instruction, so no interrupts are handled - //clear_prefixes(); - //cycle_internal(); - } - } - else - { - dbg_log("mov sreg #ud"); - trigger_ud(); - } -} -DEFINE_MODRM_INSTR_READ16(instr_8E, instr_8E_helper(___, r)) - -void instr16_8F_0_mem_pre() -{ - for(int32_t i = 0; i < 8; i++) { translate_address_read(*instruction_pointer + i); }; c_comment("XXX"); - adjust_stack_reg(2); -} -void instr16_8F_0_mem(int32_t addr) -{ - c_comment("pop"); - adjust_stack_reg(-2); - int32_t sp = safe_read16(get_stack_pointer(0)); - safe_write16(addr, sp); - adjust_stack_reg(2); -} -void instr16_8F_0_reg(int32_t r) -{ - write_reg16(r, pop16()); -} -void instr32_8F_0_mem_pre() -{ - c_comment("prevent page faults during modrm_resolve"); - for(int32_t i = 0; i < 8; i++) { translate_address_read(*instruction_pointer + i); }; c_comment("XXX"); - - c_comment("esp must be adjusted before calling modrm_resolve"); - c_comment("The order of calls is: instr32_8F_0_mem_pre -> modrm_resolve -> instr32_8F_0_mem"); - adjust_stack_reg(4); -} -void instr32_8F_0_mem(int32_t addr) -{ - c_comment("Before attempting a write that might cause a page fault,"); - c_comment("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); -} -void instr32_8F_0_reg(int32_t r) -{ - write_reg32(r, pop32s()); -} - -void instr_90() { } -void instr16_91() { xchg16r(CX); } -void instr32_91() { xchg32r(ECX); } -void instr16_92() { xchg16r(DX); } -void instr32_92() { xchg32r(EDX); } -void instr16_93() { xchg16r(BX); } -void instr32_93() { xchg32r(EBX); } -void instr16_94() { xchg16r(SP); } -void instr32_94() { xchg32r(ESP); } -void instr16_95() { xchg16r(BP); } -void instr32_95() { xchg32r(EBP); } -void instr16_96() { xchg16r(SI); } -void instr32_96() { xchg32r(ESI); } -void instr16_97() { xchg16r(DI); } -void instr32_97() { xchg32r(EDI); } - -void instr16_98() { /* cbw */ reg16[AX] = reg8s[AL]; } -void instr32_98() { /* cwde */ reg32s[EAX] = reg16s[AX]; } -void instr16_99() { /* cwd */ reg16[DX] = reg16s[AX] >> 15; } -void instr32_99() { /* cdq */ reg32s[EDX] = reg32s[EAX] >> 31; } - -void instr16_9A(int32_t new_ip, int32_t new_cs) { - c_comment("callf"); - far_jump(new_ip, new_cs, true); - dbg_assert(is_asize_32() || get_real_eip() < 0x10000); -} -void instr32_9A(int32_t new_ip, int32_t new_cs) { - if(!*protected_mode || vm86_mode()) - { - if(new_ip & 0xFFFF0000) - { - assert(false); - } - } - - far_jump(new_ip, new_cs, true); - dbg_assert(is_asize_32() || get_real_eip() < 0x10000); -} - -void instr_9B() { - c_comment("fwait: check for pending fpu exceptions"); - if((cr[0] & (CR0_MP | CR0_TS)) == (CR0_MP | CR0_TS)) - { - c_comment("Note: Different from task_switch_test"); - c_comment("Triggers when TS and MP bits are set (EM bit is ignored)"); - trigger_nm(); - } - else - { - fwait(); - } -} -void instr16_9C() { - c_comment("pushf"); - if((flags[0] & FLAG_VM) && getiopl() < 3) - { - dbg_assert(*protected_mode); - dbg_log("pushf #gp"); - trigger_gp_non_raising(0); - } - else - { - push16(get_eflags()); - } -} -void instr32_9C() { - c_comment("pushf"); - if((flags[0] & FLAG_VM) && getiopl() < 3) - { - c_comment("trap to virtual 8086 monitor"); - dbg_assert(*protected_mode); - dbg_log("pushf #gp"); - trigger_gp_non_raising(0); - } - else - { - c_comment("vm and rf flag are cleared in image stored on the stack"); - push32(get_eflags() & 0x00FCFFFF); - } -} -void instr16_9D() { - c_comment("popf"); - if((flags[0] & FLAG_VM) && getiopl() < 3) - { - dbg_log("popf #gp"); - trigger_gp_non_raising(0); - return; - } - - update_eflags((flags[0] & ~0xFFFF) | pop16()); - - if(flags[0] & FLAG_TRAP) - { - // XXX: Problems with fdgame - //clear_prefixes(); - //cycle_internal(); - flags[0] &= ~FLAG_TRAP; - //instruction_pointer = previous_ip; - //raise_exception(1); - } - else - { - handle_irqs(); - } -} -void instr32_9D() { - c_comment("popf"); - if((flags[0] & FLAG_VM) && getiopl() < 3) - { - dbg_log("popf #gp"); - trigger_gp_non_raising(0); - return; - } - - update_eflags(pop32s()); - handle_irqs(); -} -void instr_9E() { - c_comment("sahf"); - flags[0] = (flags[0] & ~0xFF) | reg8[AH]; - flags[0] = (flags[0] & FLAGS_MASK) | FLAGS_DEFAULT; - flags_changed[0] &= ~0xFF; -} -void instr_9F() { - c_comment("lahf"); - reg8[AH] = get_eflags(); -} - -void instr_A0(int32_t moffs) { - c_comment("mov"); - int32_t data = safe_read8(get_seg_prefix_ds(moffs)); - reg8[AL] = data; -} -void instr16_A1(int32_t moffs) { - c_comment("mov"); - int32_t data = safe_read16(get_seg_prefix_ds(moffs)); - reg16[AX] = data; -} -void instr32_A1(int32_t moffs) { - int32_t data = safe_read32s(get_seg_prefix_ds(moffs)); - reg32s[EAX] = data; -} -void instr_A2(int32_t moffs) { - c_comment("mov"); - safe_write8(get_seg_prefix_ds(moffs), reg8[AL]); -} -void instr16_A3(int32_t moffs) { - c_comment("mov"); - safe_write16(get_seg_prefix_ds(moffs), reg16[AX]); -} -void instr32_A3(int32_t moffs) { - safe_write32(get_seg_prefix_ds(moffs), reg32s[EAX]); -} - -void instr_A4() { movsb_no_rep(); } -void instr_F2A4() { movsb_rep(); } -void instr_F3A4() { movsb_rep(); } -void instr16_A5() { movsw_no_rep(); } -void instr16_F2A5() { movsw_rep(); } -void instr16_F3A5() { movsw_rep(); } -void instr32_A5() { movsd_no_rep(); } -void instr32_F2A5() { movsd_rep(); } -void instr32_F3A5() { movsd_rep(); } - -void instr_A6() { cmpsb_no_rep(); } -void instr_F2A6() { cmpsb_rep(PREFIX_F2); } -void instr_F3A6() { cmpsb_rep(PREFIX_F3); } -void instr16_A7() { cmpsw_no_rep(); } -void instr16_F2A7() { cmpsw_rep(PREFIX_F2); } -void instr16_F3A7() { cmpsw_rep(PREFIX_F3); } -void instr32_A7() { cmpsd_no_rep(); } -void instr32_F2A7() { cmpsd_rep(PREFIX_F2); } -void instr32_F3A7() { cmpsd_rep(PREFIX_F3); } - -void instr_A8(int32_t imm8) { - test8(reg8[AL], imm8); -} -void instr16_A9(int32_t imm16) { - test16(reg16[AX], imm16); -} -void instr32_A9(int32_t imm32) { - test32(reg32s[EAX], imm32); -} - -void instr_AA() { stosb_no_rep(); } -void instr_F2AA() { stosb_rep(); } -void instr_F3AA() { stosb_rep(); } -void instr16_AB() { stosw_no_rep(); } -void instr16_F2AB() { stosw_rep(); } -void instr16_F3AB() { stosw_rep(); } -void instr32_AB() { stosd_no_rep(); } -void instr32_F2AB() { stosd_rep(); } -void instr32_F3AB() { stosd_rep(); } - -void instr_AC() { lodsb_no_rep(); } -void instr_F2AC() { lodsb_rep(); } -void instr_F3AC() { lodsb_rep(); } -void instr16_AD() { lodsw_no_rep(); } -void instr16_F2AD() { lodsw_rep(); } -void instr16_F3AD() { lodsw_rep(); } -void instr32_AD() { lodsd_no_rep(); } -void instr32_F2AD() { lodsd_rep(); } -void instr32_F3AD() { lodsd_rep(); } - -void instr_AE() { scasb_no_rep(); } -void instr_F2AE() { scasb_rep(PREFIX_F2); } -void instr_F3AE() { scasb_rep(PREFIX_F3); } -void instr16_AF() { scasw_no_rep(); } -void instr16_F2AF() { scasw_rep(PREFIX_F2); } -void instr16_F3AF() { scasw_rep(PREFIX_F3); } -void instr32_AF() { scasd_no_rep(); } -void instr32_F2AF() { scasd_rep(PREFIX_F2); } -void instr32_F3AF() { scasd_rep(PREFIX_F3); } - - -void instr_B0(int32_t imm8) { reg8[AL] = imm8; } -void instr_B1(int32_t imm8) { reg8[CL] = imm8; } -void instr_B2(int32_t imm8) { reg8[DL] = imm8; } -void instr_B3(int32_t imm8) { reg8[BL] = imm8; } -void instr_B4(int32_t imm8) { reg8[AH] = imm8; } -void instr_B5(int32_t imm8) { reg8[CH] = imm8; } -void instr_B6(int32_t imm8) { reg8[DH] = imm8; } -void instr_B7(int32_t imm8) { reg8[BH] = imm8; } - -void instr16_B8(int32_t imm) { reg16[AX] = imm; } -void instr32_B8(int32_t imm) { reg32s[EAX] = imm; } -void instr16_B9(int32_t imm) { reg16[CX] = imm; } -void instr32_B9(int32_t imm) { reg32s[ECX] = imm; } -void instr16_BA(int32_t imm) { reg16[DX] = imm; } -void instr32_BA(int32_t imm) { reg32s[EDX] = imm; } -void instr16_BB(int32_t imm) { reg16[BX] = imm; } -void instr32_BB(int32_t imm) { reg32s[EBX] = imm; } -void instr16_BC(int32_t imm) { reg16[SP] = imm; } -void instr32_BC(int32_t imm) { reg32s[ESP] = imm; } -void instr16_BD(int32_t imm) { reg16[BP] = imm; } -void instr32_BD(int32_t imm) { reg32s[EBP] = imm; } -void instr16_BE(int32_t imm) { reg16[SI] = imm; } -void instr32_BE(int32_t imm) { reg32s[ESI] = imm; } -void instr16_BF(int32_t imm) { reg16[DI] = imm; } -void instr32_BF(int32_t imm) { reg32s[EDI] = imm; } - -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_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_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)) - -void instr16_C2(int32_t imm16) { - c_comment("retn"); - int32_t cs = get_seg_cs(); - - instruction_pointer[0] = cs + pop16(); - dbg_assert(is_asize_32() || get_real_eip() < 0x10000); - adjust_stack_reg(imm16); -} -void instr32_C2(int32_t imm16) { - c_comment("retn"); - int32_t cs = get_seg_cs(); - int32_t ip = pop32s(); - - dbg_assert(is_asize_32() || ip < 0x10000); - instruction_pointer[0] = cs + ip; - adjust_stack_reg(imm16); -} -void instr16_C3() { - c_comment("retn"); - int32_t cs = get_seg_cs(); - instruction_pointer[0] = cs + pop16(); -} -void instr32_C3() { - c_comment("retn"); - int32_t cs = get_seg_cs(); - int32_t ip = pop32s(); - dbg_assert(is_asize_32() || ip < 0x10000); - instruction_pointer[0] = cs + ip; -} - -void instr16_C4_reg(int32_t _unused1, int32_t _unused2) { trigger_ud(); } -void instr16_C4_mem(int32_t addr, int32_t r) { - lss16(addr, get_reg16_index(r), ES); -} -void instr32_C4_reg(int32_t _unused1, int32_t _unused2) { trigger_ud(); } -void instr32_C4_mem(int32_t addr, int32_t r) { - lss32(addr, r, ES); -} -void instr16_C5_reg(int32_t _unused1, int32_t _unused2) { trigger_ud(); } -void instr16_C5_mem(int32_t addr, int32_t r) { - lss16(addr, get_reg16_index(r), DS); -} -void instr32_C5_reg(int32_t _unused1, int32_t _unused2) { trigger_ud(); } -void instr32_C5_mem(int32_t addr, int32_t r) { - lss32(addr, r, DS); -} - -void instr_C6_0_reg(int32_t r, int32_t imm) { write_reg8(r, imm); } -void instr_C6_0_mem(int32_t addr, int32_t imm) { safe_write8(addr, imm); } -void instr16_C7_0_reg(int32_t r, int32_t imm) { write_reg16(r, imm); } -void instr16_C7_0_mem(int32_t addr, int32_t imm) { safe_write16(addr, imm); } -void instr32_C7_0_reg(int32_t r, int32_t imm) { write_reg32(r, imm); } -void instr32_C7_0_mem(int32_t addr, int32_t imm) { safe_write32(addr, imm); } - -void instr16_C8(int32_t size, int32_t nesting) { enter16(size, nesting); } -void instr32_C8(int32_t size, int32_t nesting) { enter32(size, nesting); } -void instr16_C9() { - c_comment("leave"); - int32_t old_vbp = *stack_size_32 ? reg32s[EBP] : reg16[BP]; - int32_t new_bp = safe_read16(get_seg_ss() + old_vbp); - set_stack_reg(old_vbp + 2); - reg16[BP] = new_bp; -} -void instr32_C9() { - int32_t old_vbp = *stack_size_32 ? reg32s[EBP] : reg16[BP]; - int32_t new_ebp = safe_read32s(get_seg_ss() + old_vbp); - set_stack_reg(old_vbp + 4); - reg32s[EBP] = new_ebp; -} -void instr16_CA(int32_t imm16) { - c_comment("retf"); - int32_t ip = safe_read16(get_stack_pointer(0)); - int32_t cs = safe_read16(get_stack_pointer(2)); - - far_return(ip, cs, imm16); -} -void instr32_CA(int32_t imm16) { - c_comment("retf"); - int32_t ip = safe_read32s(get_stack_pointer(0)); - int32_t cs = safe_read32s(get_stack_pointer(4)) & 0xFFFF; - - far_return(ip, cs, imm16); - dbg_assert(is_asize_32() || get_real_eip() < 0x10000); -} -void instr16_CB() { - c_comment("retf"); - int32_t ip = safe_read16(get_stack_pointer(0)); - int32_t cs = safe_read16(get_stack_pointer(2)); - - far_return(ip, cs, 0); - dbg_assert(is_asize_32() || get_real_eip() < 0x10000); -} -void instr32_CB() { - c_comment("retf"); - int32_t ip = safe_read32s(get_stack_pointer(0)); - int32_t cs = safe_read32s(get_stack_pointer(4)) & 0xFFFF; - - far_return(ip, cs, 0); - dbg_assert(is_asize_32() || get_real_eip() < 0x10000); -} - -void instr_CC() { - c_comment("INT3"); - c_comment("TODO: inhibit iopl checks"); - dbg_log("INT3"); - call_interrupt_vector(3, true, false, 0); -} -void instr_CD(int32_t imm8) { - c_comment("INT"); - call_interrupt_vector(imm8, true, false, 0); -} -void instr_CE() { - c_comment("INTO"); - dbg_log("INTO"); - if(getof()) - { - c_comment("TODO: inhibit iopl checks"); - call_interrupt_vector(CPU_EXCEPTION_OF, true, false, 0); - } -} - -void instr16_CF() { - c_comment("iret"); - iret16(); -} -void instr32_CF() { - iret32(); -} - -DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D0_0, rol8(___, 1)) -DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D0_1, ror8(___, 1)) -DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D0_2, rcl8(___, 1)) -DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D0_3, rcr8(___, 1)) -DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D0_4, shl8(___, 1)) -DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D0_5, shr8(___, 1)) -DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D0_6, shl8(___, 1)) -DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D0_7, sar8(___, 1)) - -DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D1_0, rol16(___, 1)) -DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D1_1, ror16(___, 1)) -DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D1_2, rcl16(___, 1)) -DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D1_3, rcr16(___, 1)) -DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D1_4, shl16(___, 1)) -DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D1_5, shr16(___, 1)) -DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D1_6, shl16(___, 1)) -DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D1_7, sar16(___, 1)) - -DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D1_0, rol32(___, 1)) -DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D1_1, ror32(___, 1)) -DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D1_2, rcl32(___, 1)) -DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D1_3, rcr32(___, 1)) -DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D1_4, shl32(___, 1)) -DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D1_5, shr32(___, 1)) -DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D1_6, shl32(___, 1)) -DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D1_7, sar32(___, 1)) - -DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D2_0, rol8(___, reg8[CL] & 31)) -DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D2_1, ror8(___, reg8[CL] & 31)) -DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D2_2, rcl8(___, reg8[CL] & 31)) -DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D2_3, rcr8(___, reg8[CL] & 31)) -DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D2_4, shl8(___, reg8[CL] & 31)) -DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D2_5, shr8(___, reg8[CL] & 31)) -DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D2_6, shl8(___, reg8[CL] & 31)) -DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_D2_7, sar8(___, reg8[CL] & 31)) - -DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D3_0, rol16(___, reg8[CL] & 31)) -DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D3_1, ror16(___, reg8[CL] & 31)) -DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D3_2, rcl16(___, reg8[CL] & 31)) -DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D3_3, rcr16(___, reg8[CL] & 31)) -DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D3_4, shl16(___, reg8[CL] & 31)) -DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D3_5, shr16(___, reg8[CL] & 31)) -DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D3_6, shl16(___, reg8[CL] & 31)) -DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_D3_7, sar16(___, reg8[CL] & 31)) - -DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D3_0, rol32(___, reg8[CL] & 31)) -DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D3_1, ror32(___, reg8[CL] & 31)) -DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D3_2, rcl32(___, reg8[CL] & 31)) -DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D3_3, rcr32(___, reg8[CL] & 31)) -DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_D3_4, shl32(___, reg8[CL] & 31)) -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)) - -void instr_D4(int32_t arg) { - bcd_aam(arg); -} -void instr_D5(int32_t arg) { - bcd_aad(arg); -} - -void instr_D6() { - c_comment("salc"); - reg8[AL] = -getcf(); -} -void instr_D7() { - c_comment("xlat"); - if(is_asize_32()) - { - reg8[AL] = safe_read8(get_seg_prefix(DS) + reg32s[EBX] + reg8[AL]); - } - else - { - reg8[AL] = safe_read8(get_seg_prefix(DS) + (reg16[BX] + reg8[AL] & 0xFFFF)); - } -} - -DEFINE_MODRM_INSTR_FPU_READ32(instr_D8_0, fpu_fadd(0, ___)) -DEFINE_MODRM_INSTR_FPU_READ32(instr_D8_1, fpu_fmul(0, ___)) -DEFINE_MODRM_INSTR_FPU_READ32(instr_D8_2, fpu_fcom(___)) -DEFINE_MODRM_INSTR_FPU_READ32(instr_D8_3, fpu_fcomp(___)) -DEFINE_MODRM_INSTR_FPU_READ32(instr_D8_4, fpu_fsub(0, ___)) -DEFINE_MODRM_INSTR_FPU_READ32(instr_D8_5, fpu_fsubr(0, ___)) -DEFINE_MODRM_INSTR_FPU_READ32(instr_D8_6, fpu_fdiv(0, ___)) -DEFINE_MODRM_INSTR_FPU_READ32(instr_D8_7, fpu_fdivr(0, ___)) - -DEFINE_MODRM_INSTR_FPU_READ32(instr_D9_0, fpu_push(___)) -void instr_D9_1_mem(int32_t addr) { dbg_log("d9/1"); trigger_ud(); } -void instr_D9_1_reg(int32_t r) { fpu_fxch(r); } -void instr_D9_2_mem(int32_t addr) { fpu_fstm32(addr); } -void instr_D9_2_reg(int32_t r) { if(r != 0) { trigger_ud(); } } -void instr_D9_3_mem(int32_t addr) { fpu_fstm32p(addr); } -void instr_D9_3_reg(int32_t r) { dbg_log("fstp1"); trigger_ud(); } -void instr_D9_4_mem(int32_t addr) { fpu_fldenv(addr); } -void instr_D9_4_reg(int32_t r) -{ - double_t st0 = fpu_get_st0(); - switch(r) - { - case 0: - c_comment("fchs"); - fpu_st[*fpu_stack_ptr] = -st0; - break; - case 1: - c_comment("fabs"); - fpu_st[*fpu_stack_ptr] = fabs(st0); - break; - case 4: - fpu_ftst(st0); - break; - case 5: - fpu_fxam(st0); - break; - default: - dbg_log1("%x", r); - trigger_ud(); - } -} -void instr_D9_5_mem(int32_t addr) { fpu_fldcw(addr); } -void instr_D9_5_reg(int32_t r) -{ - c_comment("fld1/fldl2t/fldl2e/fldpi/fldlg2/fldln2/fldz"); - switch(r) - { - case 0: fpu_push(1); break; - case 1: fpu_push(M_LN10 / M_LN2); break; - case 2: fpu_push(M_LOG2E); break; - case 3: fpu_push(M_PI); break; - case 4: fpu_push(M_LN2 / M_LN10); break; - case 5: fpu_push(M_LN2); break; - case 6: fpu_push(0); break; - case 7: dbg_log("d9/5/7"); trigger_ud(); break; - } -} -void instr_D9_6_mem(int32_t addr) { fpu_fstenv(addr); } -void instr_D9_6_reg(int32_t r) -{ - double_t st0 = fpu_get_st0(); - - switch(r) - { - case 0: - c_comment("f2xm1"); - fpu_st[*fpu_stack_ptr] = pow(2, st0) - 1; - break; - case 1: - c_comment("fyl2x"); - fpu_st[*fpu_stack_ptr + 1 & 7] = fpu_get_sti(1) * log(st0) / M_LN2; - fpu_pop(); - break; - case 2: - c_comment("fptan"); - fpu_st[*fpu_stack_ptr] = tan(st0); - fpu_push(1); c_comment("no bug: push constant 1"); - break; - case 3: - c_comment("fpatan"); - fpu_st[*fpu_stack_ptr + 1 & 7] = atan2(fpu_get_sti(1), st0); - fpu_pop(); - break; - case 4: - fpu_fxtract(); - break; - case 5: - c_comment("fprem1"); - fpu_st[*fpu_stack_ptr] = fmod(st0, fpu_get_sti(1)); - break; - case 6: - c_comment("fdecstp"); - *fpu_stack_ptr = *fpu_stack_ptr - 1 & 7; - *fpu_status_word &= ~FPU_C1; - break; - case 7: - c_comment("fincstp"); - *fpu_stack_ptr = *fpu_stack_ptr + 1 & 7; - *fpu_status_word &= ~FPU_C1; - break; - default: - dbg_assert(false); - } -} -void instr_D9_7_mem(int32_t addr) { fpu_fstcw(addr); } -void instr_D9_7_reg(int32_t r) -{ - double_t st0 = fpu_get_st0(); - - switch(r) - { - case 0: - fpu_fprem(); - break; - case 1: - c_comment("fyl2xp1: y * log2(x+1) and pop"); - fpu_st[*fpu_stack_ptr + 1 & 7] = fpu_get_sti(1) * log(st0 + 1) / M_LN2; - fpu_pop(); - break; - case 2: - fpu_st[*fpu_stack_ptr] = sqrt(st0); - break; - case 3: - fpu_st[*fpu_stack_ptr] = sin(st0); - fpu_push(cos(st0)); - break; - case 4: - c_comment("frndint"); - fpu_st[*fpu_stack_ptr] = fpu_integer_round(st0); - break; - case 5: - c_comment("fscale"); - fpu_st[*fpu_stack_ptr] = st0 * pow(2, trunc(fpu_get_sti(1))); - break; - case 6: - fpu_st[*fpu_stack_ptr] = sin(st0); - break; - case 7: - fpu_st[*fpu_stack_ptr] = cos(st0); - break; - default: - dbg_assert(false); - } -} - -void instr_DA_0_mem(int32_t addr) { fpu_fadd(0, safe_read32s(addr)); } -void instr_DA_1_mem(int32_t addr) { fpu_fmul(0, safe_read32s(addr)); } -void instr_DA_2_mem(int32_t addr) { fpu_fcom(safe_read32s(addr)); } -void instr_DA_3_mem(int32_t addr) { fpu_fcomp(safe_read32s(addr)); } -void instr_DA_4_mem(int32_t addr) { fpu_fsub(0, safe_read32s(addr)); } -void instr_DA_5_mem(int32_t addr) { fpu_fsubr(0, safe_read32s(addr)); } -void instr_DA_6_mem(int32_t addr) { fpu_fdiv(0, safe_read32s(addr)); } -void instr_DA_7_mem(int32_t addr) { fpu_fdivr(0, safe_read32s(addr)); } - -void instr_DA_0_reg(int32_t r) { fpu_fcmovcc(test_b(), r); } -void instr_DA_1_reg(int32_t r) { fpu_fcmovcc(test_z(), r); } -void instr_DA_2_reg(int32_t r) { fpu_fcmovcc(test_be(), r); } -void instr_DA_3_reg(int32_t r) { fpu_fcmovcc(test_p(), r); } -void instr_DA_4_reg(int32_t r) { trigger_ud(); } -void instr_DA_5_reg(int32_t r) { if(r == 1) { fpu_fucompp(); } else { trigger_ud(); } } -void instr_DA_6_reg(int32_t r) { trigger_ud(); } -void instr_DA_7_reg(int32_t r) { trigger_ud(); } - -void instr_DB_0_mem(int32_t addr) { fpu_fldm32(addr); } -void instr_DB_1_mem(int32_t addr) { trigger_ud(); } -void instr_DB_2_mem(int32_t addr) { fpu_fistm32(addr); } -void instr_DB_3_mem(int32_t addr) { fpu_fistm32p(addr); } -void instr_DB_4_mem(int32_t addr) { trigger_ud(); } -void instr_DB_5_mem(int32_t addr) { fpu_fldm80(addr); } -void instr_DB_6_mem(int32_t addr) { trigger_ud(); } -void instr_DB_7_mem(int32_t addr) { fpu_fst80p(addr); } - -void instr_DB_0_reg(int32_t r) { fpu_fcmovcc(!test_b(), r); } -void instr_DB_1_reg(int32_t r) { fpu_fcmovcc(!test_z(), r); } -void instr_DB_2_reg(int32_t r) { fpu_fcmovcc(!test_be(), r); } -void instr_DB_3_reg(int32_t r) { fpu_fcmovcc(!test_p(), r); } -void instr_DB_4_reg(int32_t r) -{ - if(r == 3) - { - fpu_finit(); - } - else if(r == 4 || r == 1) - { - c_comment("fsetpm and fdisi; treated as nop"); - } - else if(r == 2) - { - fpu_fclex(); - } - else - { - trigger_ud(); - } -} -void instr_DB_5_reg(int32_t r) { fpu_fucomi(r); } -void instr_DB_6_reg(int32_t r) { fpu_fcomi(r); } -void instr_DB_7_reg(int32_t r) { trigger_ud(); } - -void instr_DC_0_mem(int32_t addr) { fpu_fadd(0, fpu_load_m64(addr)); } -void instr_DC_1_mem(int32_t addr) { fpu_fmul(0, fpu_load_m64(addr)); } -void instr_DC_2_mem(int32_t addr) { fpu_fcom(fpu_load_m64(addr)); } -void instr_DC_3_mem(int32_t addr) { fpu_fcomp(fpu_load_m64(addr)); } -void instr_DC_4_mem(int32_t addr) { fpu_fsub(0, fpu_load_m64(addr)); } -void instr_DC_5_mem(int32_t addr) { fpu_fsubr(0, fpu_load_m64(addr)); } -void instr_DC_6_mem(int32_t addr) { fpu_fdiv(0, fpu_load_m64(addr)); } -void instr_DC_7_mem(int32_t addr) { fpu_fdivr(0, fpu_load_m64(addr)); } - -void instr_DC_0_reg(int32_t r) { fpu_fadd(r, fpu_get_sti(r)); } -void instr_DC_1_reg(int32_t r) { fpu_fmul(r, fpu_get_sti(r)); } -void instr_DC_2_reg(int32_t r) { fpu_fcom(fpu_get_sti(r)); } -void instr_DC_3_reg(int32_t r) { fpu_fcomp(fpu_get_sti(r)); } -void instr_DC_4_reg(int32_t r) { fpu_fsub(r, fpu_get_sti(r)); } -void instr_DC_5_reg(int32_t r) { fpu_fsubr(r, fpu_get_sti(r)); } -void instr_DC_6_reg(int32_t r) { fpu_fdiv(r, fpu_get_sti(r)); } -void instr_DC_7_reg(int32_t r) { fpu_fdivr(r, fpu_get_sti(r)); } - -void instr_DD_0_mem(int32_t addr) { fpu_fldm64(addr); } -void instr_DD_1_mem(int32_t addr) { dbg_log("fisttp"); trigger_ud(); } -void instr_DD_2_mem(int32_t addr) { fpu_fstm64(addr); } -void instr_DD_3_mem(int32_t addr) { fpu_fstm64p(addr); } -void instr_DD_4_mem(int32_t addr) { fpu_frstor(addr); } -void instr_DD_5_mem(int32_t addr) { dbg_log("dd/5"); trigger_ud(); } -void instr_DD_6_mem(int32_t addr) { fpu_fsave(addr); } -void instr_DD_7_mem(int32_t addr) { fpu_fnstsw_mem(addr); } - -void instr_DD_0_reg(int32_t r) { fpu_ffree(r); } -void instr_DD_1_reg(int32_t r) { trigger_ud(); } -void instr_DD_2_reg(int32_t r) { fpu_fst(r); } -void instr_DD_3_reg(int32_t r) { fpu_fstp(r); } -void instr_DD_4_reg(int32_t r) { fpu_fucom(r); } -void instr_DD_5_reg(int32_t r) { fpu_fucomp(r); } -void instr_DD_6_reg(int32_t r) { trigger_ud(); } -void instr_DD_7_reg(int32_t r) { trigger_ud(); } - -void instr_DE_0_mem(int32_t addr) { fpu_fadd(0, (int16_t) safe_read16(addr)); } -void instr_DE_1_mem(int32_t addr) { fpu_fmul(0, (int16_t) safe_read16(addr)); } -void instr_DE_2_mem(int32_t addr) { fpu_fcom((int16_t) safe_read16(addr)); } -void instr_DE_3_mem(int32_t addr) { fpu_fcomp((int16_t) safe_read16(addr)); } -void instr_DE_4_mem(int32_t addr) { fpu_fsub(0, (int16_t) safe_read16(addr)); } -void instr_DE_5_mem(int32_t addr) { fpu_fsubr(0, (int16_t) safe_read16(addr)); } -void instr_DE_6_mem(int32_t addr) { fpu_fdiv(0, (int16_t) safe_read16(addr)); } -void instr_DE_7_mem(int32_t addr) { fpu_fdivr(0, (int16_t) safe_read16(addr)); } - -void instr_DE_0_reg(int32_t r) { fpu_fadd(r, fpu_get_sti(r)); fpu_pop(); } -void instr_DE_1_reg(int32_t r) { fpu_fmul(r, fpu_get_sti(r)); fpu_pop(); } -void instr_DE_2_reg(int32_t r) { fpu_fcom(fpu_get_sti(r)); fpu_pop(); } -void instr_DE_3_reg(int32_t r) { fpu_fcomp(fpu_get_sti(r)); fpu_pop(); } -void instr_DE_4_reg(int32_t r) { fpu_fsub(r, fpu_get_sti(r)); fpu_pop(); } -void instr_DE_5_reg(int32_t r) { fpu_fsubr(r, fpu_get_sti(r)); fpu_pop(); } -void instr_DE_6_reg(int32_t r) { fpu_fdiv(r, fpu_get_sti(r)); fpu_pop(); } -void instr_DE_7_reg(int32_t r) { fpu_fdivr(r, fpu_get_sti(r)); fpu_pop(); } - -void instr_DF_0_mem(int32_t addr) { fpu_push((int16_t) safe_read16(addr)); } -void instr_DF_1_mem(int32_t addr) { dbg_log("df/fisttp"); trigger_ud(); } -void instr_DF_2_mem(int32_t addr) { fpu_fistm16(addr); } -void instr_DF_3_mem(int32_t addr) { fpu_fistm16p(addr); } -void instr_DF_4_mem(int32_t addr) { dbg_log("fbld"); trigger_ud(); } -void instr_DF_5_mem(int32_t addr) { fpu_fildm64(addr); } -void instr_DF_6_mem(int32_t addr) { dbg_log("fbstp"); trigger_ud(); } -void instr_DF_7_mem(int32_t addr) { fpu_fistm64p(addr); } - -void instr_DF_0_reg(int32_t r) { trigger_ud(); } -void instr_DF_1_reg(int32_t r) { trigger_ud(); } -void instr_DF_2_reg(int32_t r) { trigger_ud(); } -void instr_DF_3_reg(int32_t r) { trigger_ud(); } -void instr_DF_4_reg(int32_t r) { if(r == 0) { fpu_fnstsw_reg(); } else { trigger_ud(); } } -void instr_DF_5_reg(int32_t r) { fpu_fucomip(r); } -void instr_DF_6_reg(int32_t r) { fpu_fcomip(r); } -void instr_DF_7_reg(int32_t r) { trigger_ud(); } - -void instr16_E0(int32_t imm8s) { loopne16(imm8s); } -void instr16_E1(int32_t imm8s) { loope16(imm8s); } -void instr16_E2(int32_t imm8s) { loop16(imm8s); } -void instr16_E3(int32_t imm8s) { jcxz16(imm8s); } - -void instr32_E0(int32_t imm8s) { loopne32(imm8s); } -void instr32_E1(int32_t imm8s) { loope32(imm8s); } -void instr32_E2(int32_t imm8s) { loop32(imm8s); } -void instr32_E3(int32_t imm8s) { jcxz32(imm8s); } - -void instr_E4(int32_t port) { - if(!test_privileges_for_io(port, 1)) return; - reg8[AL] = io_port_read8(port); -} -void instr16_E5(int32_t port) { - if(!test_privileges_for_io(port, 2)) return; - reg16[AX] = io_port_read16(port); -} -void instr32_E5(int32_t port) { - if(!test_privileges_for_io(port, 4)) return; - reg32s[EAX] = io_port_read32(port); -} -void instr_E6(int32_t port) { - if(!test_privileges_for_io(port, 1)) return; - io_port_write8(port, reg8[AL]); -} -void instr16_E7(int32_t port) { - if(!test_privileges_for_io(port, 2)) return; - io_port_write16(port, reg16[AX]); -} -void instr32_E7(int32_t port) { - if(!test_privileges_for_io(port, 4)) return; - io_port_write32(port, reg32s[EAX]); -} - -void instr16_E8(int32_t imm16) { - c_comment("call"); - push16(get_real_eip()); - - jmp_rel16(imm16); -} -void instr32_E8(int32_t imm32s) { - c_comment("call"); - push32(get_real_eip()); - - instruction_pointer[0] = instruction_pointer[0] + imm32s; - c_comment("dbg_assert(is_asize_32() || get_real_eip() < 0x10000);"); -} - -void instr16_E9(int32_t imm16) { - c_comment("jmp"); - jmp_rel16(imm16); -} -void instr32_E9(int32_t imm32s) { - c_comment("jmp"); - instruction_pointer[0] = instruction_pointer[0] + imm32s; - dbg_assert(is_asize_32() || get_real_eip() < 0x10000); -} - -void instr16_EA(int32_t new_ip, int32_t cs) { - c_comment("jmpf"); - far_jump(new_ip, cs, false); - dbg_assert(is_asize_32() || get_real_eip() < 0x10000); -} -void instr32_EA(int32_t new_ip, int32_t cs) { - c_comment("jmpf"); - far_jump(new_ip, cs, false); - dbg_assert(is_asize_32() || get_real_eip() < 0x10000); -} - -void instr16_EB(int32_t imm8) { - c_comment("jmp near"); - jmp_rel16(imm8); - dbg_assert(is_asize_32() || get_real_eip() < 0x10000); -} -void instr32_EB(int32_t imm8) { - c_comment("jmp near"); - instruction_pointer[0] = instruction_pointer[0] + imm8; - dbg_assert(is_asize_32() || get_real_eip() < 0x10000); -} - - -void instr_EC() { - int32_t port = reg16[DX]; - if(!test_privileges_for_io(port, 1)) return; - reg8[AL] = io_port_read8(port); -} -void instr16_ED() { - int32_t port = reg16[DX]; - if(!test_privileges_for_io(port, 2)) return; - reg16[AX] = io_port_read16(port); -} -void instr32_ED() { - int32_t port = reg16[DX]; - if(!test_privileges_for_io(port, 4)) return; - reg32s[EAX] = io_port_read32(port); -} -void instr_EE() { - int32_t port = reg16[DX]; - if(!test_privileges_for_io(port, 1)) return; - io_port_write8(port, reg8[AL]); -} -void instr16_EF() { - int32_t port = reg16[DX]; - if(!test_privileges_for_io(port, 2)) return; - io_port_write16(port, reg16[AX]); -} -void instr32_EF() { - int32_t port = reg16[DX]; - if(!test_privileges_for_io(port, 4)) return; - io_port_write32(port, reg32s[EAX]); -} - -void instr_F0() { - c_comment("lock"); - if(0 * 0) dbg_log("lock"); - - c_comment("TODO"); - c_comment("This triggers UD when used with"); - c_comment("some instructions that don't write to memory"); - run_prefix_instruction(); -} -void instr_F1() { - c_comment("INT1"); - c_comment("https://code.google.com/p/corkami/wiki/x86oddities#IceBP"); - assert(false); -} - -void instr_F2() { - c_comment("repnz"); - dbg_assert((*prefixes & PREFIX_MASK_REP) == 0); - *prefixes |= PREFIX_REPNZ; - run_prefix_instruction(); - *prefixes = 0; -} - -void instr_F3() { - c_comment("repz"); - dbg_assert((*prefixes & PREFIX_MASK_REP) == 0); - *prefixes |= PREFIX_REPZ; - run_prefix_instruction(); - *prefixes = 0; -} - -void instr_F4() { - hlt_op(); -} - -void instr_F5() { - c_comment("cmc"); - flags[0] = (flags[0] | 1) ^ getcf(); - flags_changed[0] &= ~1; -} - -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(___)) -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_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(___)) -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_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(___)) -DEFINE_MODRM_INSTR1_READ32(instr32_F7_5, imul32(___)) -DEFINE_MODRM_INSTR1_READ32(instr32_F7_6, div32(___)) -DEFINE_MODRM_INSTR1_READ32(instr32_F7_7, idiv32(___)) - -void instr_F8() { - c_comment("clc"); - flags[0] &= ~FLAG_CARRY; - flags_changed[0] &= ~1; -} -void instr_F9() { - c_comment("stc"); - flags[0] |= FLAG_CARRY; - flags_changed[0] &= ~1; -} - -void instr_FA() { - c_comment("cli"); - //dbg_log("interrupts off"); - - if(!*protected_mode || ((flags[0] & FLAG_VM) ? - getiopl() == 3 : getiopl() >= *cpl)) - { - flags[0] &= ~FLAG_INTERRUPT; - } - else - { - if(0 * 0 && getiopl() < 3 && ((*flags & FLAG_VM) ? - (cr[4] & CR4_VME) : - (*cpl == 3 && (cr[4] & CR4_PVI)))) - { - *flags &= ~FLAG_VIF; - } - else - { - dbg_log("cli #gp"); - trigger_gp_non_raising(0); - } - } -} -void instr_FB() { - c_comment("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; - - if(old_if == 0) - { - //clear_prefixes(); - //cycle_internal(); - - handle_irqs(); - } - } - else - { - if(0 * 0 && getiopl() < 3 && (*flags & FLAG_VIP) == 0 && ((*flags & FLAG_VM) ? - (cr[4] & CR4_VME) : - (*cpl == 3 && (cr[4] & CR4_PVI)))) - { - *flags |= FLAG_VIF; - } - else - { - dbg_log("sti #gp"); - trigger_gp_non_raising(0); - } - } - -} - -void instr_FC() { - c_comment("cld"); - flags[0] &= ~FLAG_DIRECTION; -} -void instr_FD() { - c_comment("std"); - flags[0] |= FLAG_DIRECTION; -} - -DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_FE_0, inc8(___)) -DEFINE_MODRM_INSTR1_READ_WRITE_8(instr_FE_1, dec8(___)) - - -DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_FF_0, inc16(___)) -DEFINE_MODRM_INSTR1_READ_WRITE_16(instr16_FF_1, dec16(___)) -void instr16_FF_2_helper(int32_t data) -{ - c_comment("call near"); - int32_t cs = get_seg_cs(); - push16(get_real_eip()); - instruction_pointer[0] = cs + data; - dbg_assert(is_asize_32() || get_real_eip() < 0x10000); -} -DEFINE_MODRM_INSTR1_READ16(instr16_FF_2, instr16_FF_2_helper(___)) -void instr16_FF_3_reg(int32_t r) -{ - dbg_log("callf #ud"); - trigger_ud(); -} -void instr16_FF_3_mem(int32_t addr) -{ - c_comment("callf"); - int32_t new_ip = safe_read16(addr); - int32_t new_cs = safe_read16(addr + 2); - - far_jump(new_ip, new_cs, true); - dbg_assert(is_asize_32() || get_real_eip() < 0x10000); -} -void instr16_FF_4_helper(int32_t data) -{ - c_comment("jmp near"); - instruction_pointer[0] = get_seg_cs() + data; - dbg_assert(is_asize_32() || get_real_eip() < 0x10000); -} -DEFINE_MODRM_INSTR1_READ16(instr16_FF_4, instr16_FF_4_helper(___)) -void instr16_FF_5_reg(int32_t r) -{ - dbg_log("jmpf #ud"); - trigger_ud(); -} -void instr16_FF_5_mem(int32_t addr) -{ - c_comment("jmpf"); - int32_t new_ip = safe_read16(addr); - int32_t new_cs = safe_read16(addr + 2); - - far_jump(new_ip, new_cs, false); - dbg_assert(is_asize_32() || get_real_eip() < 0x10000); -} -DEFINE_MODRM_INSTR1_READ16(instr16_FF_6, push16(___)) - -DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_FF_0, inc32(___)) -DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_FF_1, dec32(___)) -void instr32_FF_2_helper(int32_t data) -{ - c_comment("call near"); - int32_t cs = get_seg_cs(); - push32(get_real_eip()); - dbg_assert(is_asize_32() || data < 0x10000); - instruction_pointer[0] = cs + data; -} -DEFINE_MODRM_INSTR1_READ32(instr32_FF_2, instr32_FF_2_helper(___)) -void instr32_FF_3_reg(int32_t r) -{ - dbg_log("callf #ud"); - trigger_ud(); -} -void instr32_FF_3_mem(int32_t addr) -{ - c_comment("callf"); - int32_t new_ip = safe_read32s(addr); - int32_t new_cs = safe_read16(addr + 4); - - if(!*protected_mode || vm86_mode()) - { - if(new_ip & 0xFFFF0000) - { - //throw debug.unimpl("#GP handler"); - assert(false); - } - } - - far_jump(new_ip, new_cs, true); - dbg_assert(is_asize_32() || new_ip < 0x10000); -} -void instr32_FF_4_helper(int32_t data) -{ - c_comment("jmp near"); - dbg_assert(is_asize_32() || data < 0x10000); - instruction_pointer[0] = get_seg_cs() + data; -} -DEFINE_MODRM_INSTR1_READ32(instr32_FF_4, instr32_FF_4_helper(___)) -void instr32_FF_5_reg(int32_t r) -{ - dbg_log("jmpf #ud"); - trigger_ud(); -} -void instr32_FF_5_mem(int32_t addr) -{ - c_comment("jmpf"); - int32_t new_ip = safe_read32s(addr); - int32_t new_cs = safe_read16(addr + 4); - - if(!*protected_mode || vm86_mode()) - { - if(new_ip & 0xFFFF0000) - { - //throw debug.unimpl("#GP handler"); - assert(false); - } - } - - far_jump(new_ip, new_cs, false); - dbg_assert(is_asize_32() || new_ip < 0x10000); -} -DEFINE_MODRM_INSTR1_READ32(instr32_FF_6, push32(___)) - -//void run_instruction(int32_t opcode) -//{ -//#include "../../build/interpreter.c" -//} - -#pragma clang diagnostic pop diff --git a/src/native/instructions.h b/src/native/instructions.h deleted file mode 100644 index 680a2faa..00000000 --- a/src/native/instructions.h +++ /dev/null @@ -1,896 +0,0 @@ -#pragma once - -#include "cpu.h" -#include - -extern void SAFE_READ_WRITE8(); -extern void SAFE_READ_WRITE16(); -extern void SAFE_READ_WRITE32(); - -extern int32_t ___; - -//#define SAFE_READ_WRITE8(addr, fun) \ -// int32_t phys_addr = translate_address_write(addr); \ -// int32_t ___ = read8(phys_addr); \ -// write8(phys_addr, fun); -// -//#define SAFE_READ_WRITE16(addr, fun) \ -// int32_t phys_addr = translate_address_write(addr); \ -// if((phys_addr & 0xFFF) == 0xFFF) \ -// { \ -// int32_t phys_addr_high = translate_address_write((addr) + 1); \ -// int32_t ___ = virt_boundary_read16(phys_addr, phys_addr_high); \ -// virt_boundary_write16(phys_addr, phys_addr_high, fun); \ -// } \ -// else \ -// { \ -// int32_t ___ = read16(phys_addr); \ -// write16(phys_addr, fun); \ -// } -// -//#define SAFE_READ_WRITE32(addr, fun) \ -// int32_t phys_addr = translate_address_write(addr); \ -// if((phys_addr & 0xFFF) >= 0xFFD) \ -// { \ -// int32_t phys_addr_high = translate_address_write((addr) + 3 & ~3) | ((addr) + 3) & 3; \ -// int32_t ___ = virt_boundary_read32s(phys_addr, phys_addr_high); \ -// virt_boundary_write32(phys_addr, phys_addr_high, fun); \ -// } \ -// else \ -// { \ -// int32_t ___ = read32s(phys_addr); \ -// write32(phys_addr, fun); \ -// } - -#define DEFINE_MODRM_INSTR1_READ_WRITE_8(name, fun) \ - void name ## _mem(int32_t addr) { SAFE_READ_WRITE8(addr, fun); } \ - void name ## _reg(int32_t r1) { int32_t ___ = read_reg8(r1); write_reg8(r1, fun); } - -#define DEFINE_MODRM_INSTR1_READ_WRITE_16(name, fun) \ - void name ## _mem(int32_t addr) { SAFE_READ_WRITE16(addr, fun); } \ - void name ## _reg(int32_t r1) { int32_t ___ = read_reg16(r1); write_reg16(r1, fun); } - -#define DEFINE_MODRM_INSTR1_READ_WRITE_32(name, fun) \ - void name ## _mem(int32_t addr) { SAFE_READ_WRITE32(addr, fun); } \ - void name ## _reg(int32_t r1) { int32_t ___ = read_reg32(r1); write_reg32(r1, fun); } - - -#define DEFINE_MODRM_INSTR2_READ_WRITE_8(name, fun) \ - void name ## _mem(int32_t addr, int32_t imm) { SAFE_READ_WRITE8(addr, fun); } \ - 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) \ - void name ## _mem(int32_t addr, int32_t imm) { SAFE_READ_WRITE16(addr, fun); } \ - 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) \ - void name ## _mem(int32_t addr, int32_t imm) { SAFE_READ_WRITE32(addr, fun); } \ - 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) \ - void name ## _mem(int32_t addr, int32_t r) { SAFE_READ_WRITE8(addr, fun); } \ - 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) \ - void name ## _mem(int32_t addr, int32_t r) { SAFE_READ_WRITE16(addr, fun); } \ - 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) \ - void name ## _mem(int32_t addr, int32_t r) { SAFE_READ_WRITE32(addr, fun); } \ - void name ## _reg(int32_t r1, int32_t r) { int32_t ___ = read_reg32(r1); write_reg32(r1, fun); } - - -#define DEFINE_MODRM_INSTR1_READ8(name, fun) \ - void name ## _mem(int32_t addr) { int32_t ___ = safe_read8(addr); fun; } \ - void name ## _reg(int32_t r1) { int32_t ___ = read_reg8(r1); fun; } - -#define DEFINE_MODRM_INSTR1_READ16(name, fun) \ - void name ## _mem(int32_t addr) { int32_t ___ = safe_read16(addr); fun; } \ - void name ## _reg(int32_t r1) { int32_t ___ = read_reg16(r1); fun; } - -#define DEFINE_MODRM_INSTR1_READ32(name, fun) \ - void name ## _mem(int32_t addr) { int32_t ___ = safe_read32s(addr); fun; } \ - void name ## _reg(int32_t r1) { int32_t ___ = read_reg32(r1); fun; } - - -#define DEFINE_MODRM_INSTR2_READ8(name, fun) \ - void name ## _mem(int32_t addr, int32_t imm) { int32_t ___ = safe_read8(addr); fun; } \ - void name ## _reg(int32_t r1, int32_t imm) { int32_t ___ = read_reg8(r1); fun; } - -#define DEFINE_MODRM_INSTR2_READ16(name, fun) \ - void name ## _mem(int32_t addr, int32_t imm) { int32_t ___ = safe_read16(addr); fun; } \ - void name ## _reg(int32_t r1, int32_t imm) { int32_t ___ = read_reg16(r1); fun; } - -#define DEFINE_MODRM_INSTR2_READ32(name, fun) \ - void name ## _mem(int32_t addr, int32_t imm) { int32_t ___ = safe_read32s(addr); fun; } \ - void name ## _reg(int32_t r1, int32_t imm) { int32_t ___ = read_reg32(r1); fun; } - - -#define DEFINE_MODRM_INSTR_READ8(name, fun) \ - void name ## _mem(int32_t addr, int32_t r) { int32_t ___ = safe_read8(addr); fun; } \ - void name ## _reg(int32_t r1, int32_t r) { int32_t ___ = read_reg8(r1); fun; } - -#define DEFINE_MODRM_INSTR_READ16(name, fun) \ - void name ## _mem(int32_t addr, int32_t r) { int32_t ___ = safe_read16(addr); fun; } \ - void name ## _reg(int32_t r1, int32_t r) { int32_t ___ = read_reg16(r1); fun; } - -#define DEFINE_MODRM_INSTR_READ32(name, fun) \ - void name ## _mem(int32_t addr, int32_t r) { int32_t ___ = safe_read32s(addr); fun; } \ - void name ## _reg(int32_t r1, int32_t r) { int32_t ___ = read_reg32(r1); fun; } - -#define DEFINE_MODRM_INSTR_FPU_READ32(name, fun) \ - void name ## _mem(int32_t addr) { double_t ___ = fpu_load_m32(addr); fun; } \ - void name ## _reg(int32_t r) { double_t ___ = fpu_get_sti(r); fun; } - -void instr_00_mem(int32_t addr, int32_t r); -void instr_00_reg(int32_t r1, int32_t r); -void instr16_01_mem(int32_t addr, int32_t r); -void instr16_01_reg(int32_t r1, int32_t r); -void instr32_01_mem(int32_t addr, int32_t r); -void instr32_01_reg(int32_t r1, int32_t r); -void instr_02_mem(int32_t addr, int32_t r); -void instr_02_reg(int32_t r1, int32_t r); -void instr16_03_mem(int32_t addr, int32_t r); -void instr16_03_reg(int32_t r1, int32_t r); -void instr32_03_mem(int32_t addr, int32_t r); -void instr32_03_reg(int32_t r1, int32_t r); -void instr_04(int32_t imm8); -void instr16_05(int32_t imm16); -void instr32_05(int32_t imm32); -void instr16_06(void); -void instr32_06(void); -void instr16_07(void); -void instr32_07(void); -void instr_08_mem(int32_t addr, int32_t r); -void instr_08_reg(int32_t r1, int32_t r); -void instr16_09_mem(int32_t addr, int32_t r); -void instr16_09_reg(int32_t r1, int32_t r); -void instr32_09_mem(int32_t addr, int32_t r); -void instr32_09_reg(int32_t r1, int32_t r); -void instr_0A_mem(int32_t addr, int32_t r); -void instr_0A_reg(int32_t r1, int32_t r); -void instr16_0B_mem(int32_t addr, int32_t r); -void instr16_0B_reg(int32_t r1, int32_t r); -void instr32_0B_mem(int32_t addr, int32_t r); -void instr32_0B_reg(int32_t r1, int32_t r); -void instr_0C(int32_t imm8); -void instr16_0D(int32_t imm16); -void instr32_0D(int32_t imm32); -void instr16_0E(void); -void instr32_0E(void); -void instr16_0F(void); -void instr32_0F(void); -void instr_10_mem(int32_t addr, int32_t r); -void instr_10_reg(int32_t r1, int32_t r); -void instr16_11_mem(int32_t addr, int32_t r); -void instr16_11_reg(int32_t r1, int32_t r); -void instr32_11_mem(int32_t addr, int32_t r); -void instr32_11_reg(int32_t r1, int32_t r); -void instr_12_mem(int32_t addr, int32_t r); -void instr_12_reg(int32_t r1, int32_t r); -void instr16_13_mem(int32_t addr, int32_t r); -void instr16_13_reg(int32_t r1, int32_t r); -void instr32_13_mem(int32_t addr, int32_t r); -void instr32_13_reg(int32_t r1, int32_t r); -void instr_14(int32_t imm8); -void instr16_15(int32_t imm16); -void instr32_15(int32_t imm32); -void instr16_16(void); -void instr32_16(void); -void instr16_17(void); -void instr32_17(void); -void instr_18_mem(int32_t addr, int32_t r); -void instr_18_reg(int32_t r1, int32_t r); -void instr16_19_mem(int32_t addr, int32_t r); -void instr16_19_reg(int32_t r1, int32_t r); -void instr32_19_mem(int32_t addr, int32_t r); -void instr32_19_reg(int32_t r1, int32_t r); -void instr_1A_mem(int32_t addr, int32_t r); -void instr_1A_reg(int32_t r1, int32_t r); -void instr16_1B_mem(int32_t addr, int32_t r); -void instr16_1B_reg(int32_t r1, int32_t r); -void instr32_1B_mem(int32_t addr, int32_t r); -void instr32_1B_reg(int32_t r1, int32_t r); -void instr_1C(int32_t imm8); -void instr16_1D(int32_t imm16); -void instr32_1D(int32_t imm32); -void instr16_1E(void); -void instr32_1E(void); -void instr16_1F(void); -void instr32_1F(void); -void instr_20_mem(int32_t addr, int32_t r); -void instr_20_reg(int32_t r1, int32_t r); -void instr16_21_mem(int32_t addr, int32_t r); -void instr16_21_reg(int32_t r1, int32_t r); -void instr32_21_mem(int32_t addr, int32_t r); -void instr32_21_reg(int32_t r1, int32_t r); -void instr_22_mem(int32_t addr, int32_t r); -void instr_22_reg(int32_t r1, int32_t r); -void instr16_23_mem(int32_t addr, int32_t r); -void instr16_23_reg(int32_t r1, int32_t r); -void instr32_23_mem(int32_t addr, int32_t r); -void instr32_23_reg(int32_t r1, int32_t r); -void instr_24(int32_t imm8); -void instr16_25(int32_t imm16); -void instr32_25(int32_t imm32); -void instr_26(void); -void instr_27(void); -void instr_28_mem(int32_t addr, int32_t r); -void instr_28_reg(int32_t r1, int32_t r); -void instr16_29_mem(int32_t addr, int32_t r); -void instr16_29_reg(int32_t r1, int32_t r); -void instr32_29_mem(int32_t addr, int32_t r); -void instr32_29_reg(int32_t r1, int32_t r); -void instr_2A_mem(int32_t addr, int32_t r); -void instr_2A_reg(int32_t r1, int32_t r); -void instr16_2B_mem(int32_t addr, int32_t r); -void instr16_2B_reg(int32_t r1, int32_t r); -void instr32_2B_mem(int32_t addr, int32_t r); -void instr32_2B_reg(int32_t r1, int32_t r); -void instr_2C(int32_t imm8); -void instr16_2D(int32_t imm16); -void instr32_2D(int32_t imm32); -void instr_2E(void); -void instr_2F(void); -void instr_30_mem(int32_t addr, int32_t r); -void instr_30_reg(int32_t r1, int32_t r); -void instr16_31_mem(int32_t addr, int32_t r); -void instr16_31_reg(int32_t r1, int32_t r); -void instr32_31_mem(int32_t addr, int32_t r); -void instr32_31_reg(int32_t r1, int32_t r); -void instr_32_mem(int32_t addr, int32_t r); -void instr_32_reg(int32_t r1, int32_t r); -void instr16_33_mem(int32_t addr, int32_t r); -void instr16_33_reg(int32_t r1, int32_t r); -void instr32_33_mem(int32_t addr, int32_t r); -void instr32_33_reg(int32_t r1, int32_t r); -void instr_34(int32_t imm8); -void instr16_35(int32_t imm16); -void instr32_35(int32_t imm32); -void instr_36(void); -void instr_37(void); -void instr_38_mem(int32_t addr, int32_t r); -void instr_38_reg(int32_t r1, int32_t r); -void instr16_39_mem(int32_t addr, int32_t r); -void instr16_39_reg(int32_t r1, int32_t r); -void instr32_39_mem(int32_t addr, int32_t r); -void instr32_39_reg(int32_t r1, int32_t r); -void instr_3A_mem(int32_t addr, int32_t r); -void instr_3A_reg(int32_t r1, int32_t r); -void instr16_3B_mem(int32_t addr, int32_t r); -void instr16_3B_reg(int32_t r1, int32_t r); -void instr32_3B_mem(int32_t addr, int32_t r); -void instr32_3B_reg(int32_t r1, int32_t r); -void instr_3C(int32_t imm8); -void instr16_3D(int32_t imm16); -void instr32_3D(int32_t imm32); -void instr_3E(void); -void instr_3F(void); -void instr16_40(void); -void instr32_40(void); -void instr16_41(void); -void instr32_41(void); -void instr16_42(void); -void instr32_42(void); -void instr16_43(void); -void instr32_43(void); -void instr16_44(void); -void instr32_44(void); -void instr16_45(void); -void instr32_45(void); -void instr16_46(void); -void instr32_46(void); -void instr16_47(void); -void instr32_47(void); -void instr16_48(void); -void instr32_48(void); -void instr16_49(void); -void instr32_49(void); -void instr16_4A(void); -void instr32_4A(void); -void instr16_4B(void); -void instr32_4B(void); -void instr16_4C(void); -void instr32_4C(void); -void instr16_4D(void); -void instr32_4D(void); -void instr16_4E(void); -void instr32_4E(void); -void instr16_4F(void); -void instr32_4F(void); -void instr16_50(void); -void instr32_50(void); -void instr16_51(void); -void instr32_51(void); -void instr16_52(void); -void instr32_52(void); -void instr16_53(void); -void instr32_53(void); -void instr16_54(void); -void instr32_54(void); -void instr16_55(void); -void instr32_55(void); -void instr16_56(void); -void instr32_56(void); -void instr16_57(void); -void instr32_57(void); -void instr16_58(void); -void instr32_58(void); -void instr16_59(void); -void instr32_59(void); -void instr16_5A(void); -void instr32_5A(void); -void instr16_5B(void); -void instr32_5B(void); -void instr16_5C(void); -void instr32_5C(void); -void instr16_5D(void); -void instr32_5D(void); -void instr16_5E(void); -void instr32_5E(void); -void instr16_5F(void); -void instr32_5F(void); -void instr16_60(void); -void instr32_60(void); -void instr16_61(void); -void instr32_61(void); -void instr_62_reg(int32_t r2, int32_t r); -void instr_62_mem(int32_t addr, int32_t r); -void instr_63_mem(int32_t addr, int32_t r); -void instr_63_reg(int32_t r1, int32_t r); -void instr_64(void); -void instr_65(void); -void instr_66(void); -void instr_67(void); -void instr16_68(int32_t imm16); -void instr32_68(int32_t imm32); -void instr16_69_mem(int32_t addr, int32_t r, int32_t imm); -void instr16_69_reg(int32_t r1, int32_t r, int32_t imm); -void instr32_69_mem(int32_t addr, int32_t r, int32_t imm); -void instr32_69_reg(int32_t r1, int32_t r, int32_t imm); -void instr16_6A(int32_t imm8); -void instr32_6A(int32_t imm8); -void instr16_6B_mem(int32_t addr, int32_t r, int32_t imm); -void instr16_6B_reg(int32_t r1, int32_t r, int32_t imm); -void instr32_6B_mem(int32_t addr, int32_t r, int32_t imm); -void instr32_6B_reg(int32_t r1, int32_t r, int32_t imm); -void instr_6C(void); -void instr16_6D(void); -void instr32_6D(void); -void instr_6E(void); -void instr16_6F(void); -void instr32_6F(void); -void instr_70(int32_t imm8); -void instr_71(int32_t imm8); -void instr_72(int32_t imm8); -void instr_73(int32_t imm8); -void instr_74(int32_t imm8); -void instr_75(int32_t imm8); -void instr_76(int32_t imm8); -void instr_77(int32_t imm8); -void instr_78(int32_t imm8); -void instr_79(int32_t imm8); -void instr_7A(int32_t imm8); -void instr_7B(int32_t imm8); -void instr_7C(int32_t imm8); -void instr_7D(int32_t imm8); -void instr_7E(int32_t imm8); -void instr_7F(int32_t imm8); -void instr_80_0_mem(int32_t addr, int32_t imm); -void instr_80_0_reg(int32_t r1, int32_t imm); -void instr_80_1_mem(int32_t addr, int32_t imm); -void instr_80_1_reg(int32_t r1, int32_t imm); -void instr_80_2_mem(int32_t addr, int32_t imm); -void instr_80_2_reg(int32_t r1, int32_t imm); -void instr_80_3_mem(int32_t addr, int32_t imm); -void instr_80_3_reg(int32_t r1, int32_t imm); -void instr_80_4_mem(int32_t addr, int32_t imm); -void instr_80_4_reg(int32_t r1, int32_t imm); -void instr_80_5_mem(int32_t addr, int32_t imm); -void instr_80_5_reg(int32_t r1, int32_t imm); -void instr_80_6_mem(int32_t addr, int32_t imm); -void instr_80_6_reg(int32_t r1, int32_t imm); -void instr_80_7_reg(int32_t r, int32_t imm); -void instr_80_7_mem(int32_t addr, int32_t imm); -void instr16_81_0_mem(int32_t addr, int32_t imm); -void instr16_81_0_reg(int32_t r1, int32_t imm); -void instr16_81_1_mem(int32_t addr, int32_t imm); -void instr16_81_1_reg(int32_t r1, int32_t imm); -void instr16_81_2_mem(int32_t addr, int32_t imm); -void instr16_81_2_reg(int32_t r1, int32_t imm); -void instr16_81_3_mem(int32_t addr, int32_t imm); -void instr16_81_3_reg(int32_t r1, int32_t imm); -void instr16_81_4_mem(int32_t addr, int32_t imm); -void instr16_81_4_reg(int32_t r1, int32_t imm); -void instr16_81_5_mem(int32_t addr, int32_t imm); -void instr16_81_5_reg(int32_t r1, int32_t imm); -void instr16_81_6_mem(int32_t addr, int32_t imm); -void instr16_81_6_reg(int32_t r1, int32_t imm); -void instr16_81_7_reg(int32_t r, int32_t imm); -void instr16_81_7_mem(int32_t addr, int32_t imm); -void instr32_81_0_mem(int32_t addr, int32_t imm); -void instr32_81_0_reg(int32_t r1, int32_t imm); -void instr32_81_1_mem(int32_t addr, int32_t imm); -void instr32_81_1_reg(int32_t r1, int32_t imm); -void instr32_81_2_mem(int32_t addr, int32_t imm); -void instr32_81_2_reg(int32_t r1, int32_t imm); -void instr32_81_3_mem(int32_t addr, int32_t imm); -void instr32_81_3_reg(int32_t r1, int32_t imm); -void instr32_81_4_mem(int32_t addr, int32_t imm); -void instr32_81_4_reg(int32_t r1, int32_t imm); -void instr32_81_5_mem(int32_t addr, int32_t imm); -void instr32_81_5_reg(int32_t r1, int32_t imm); -void instr32_81_6_mem(int32_t addr, int32_t imm); -void instr32_81_6_reg(int32_t r1, int32_t imm); -void instr32_81_7_reg(int32_t r, int32_t imm); -void instr32_81_7_mem(int32_t addr, int32_t imm); -void instr_82_0_mem(int32_t addr, int32_t imm); -void instr_82_0_reg(int32_t r1, int32_t imm); -void instr_82_1_mem(int32_t addr, int32_t imm); -void instr_82_1_reg(int32_t r1, int32_t imm); -void instr_82_2_mem(int32_t addr, int32_t imm); -void instr_82_2_reg(int32_t r1, int32_t imm); -void instr_82_3_mem(int32_t addr, int32_t imm); -void instr_82_3_reg(int32_t r1, int32_t imm); -void instr_82_4_mem(int32_t addr, int32_t imm); -void instr_82_4_reg(int32_t r1, int32_t imm); -void instr_82_5_mem(int32_t addr, int32_t imm); -void instr_82_5_reg(int32_t r1, int32_t imm); -void instr_82_6_mem(int32_t addr, int32_t imm); -void instr_82_6_reg(int32_t r1, int32_t imm); -void instr_82_7_reg(int32_t r, int32_t imm); -void instr_82_7_mem(int32_t addr, int32_t imm); -void instr16_83_0_mem(int32_t addr, int32_t imm); -void instr16_83_0_reg(int32_t r1, int32_t imm); -void instr16_83_1_mem(int32_t addr, int32_t imm); -void instr16_83_1_reg(int32_t r1, int32_t imm); -void instr16_83_2_mem(int32_t addr, int32_t imm); -void instr16_83_2_reg(int32_t r1, int32_t imm); -void instr16_83_3_mem(int32_t addr, int32_t imm); -void instr16_83_3_reg(int32_t r1, int32_t imm); -void instr16_83_4_mem(int32_t addr, int32_t imm); -void instr16_83_4_reg(int32_t r1, int32_t imm); -void instr16_83_5_mem(int32_t addr, int32_t imm); -void instr16_83_5_reg(int32_t r1, int32_t imm); -void instr16_83_6_mem(int32_t addr, int32_t imm); -void instr16_83_6_reg(int32_t r1, int32_t imm); -void instr16_83_7_reg(int32_t r, int32_t imm); -void instr16_83_7_mem(int32_t addr, int32_t imm); -void instr32_83_0_mem(int32_t addr, int32_t imm); -void instr32_83_0_reg(int32_t r1, int32_t imm); -void instr32_83_1_mem(int32_t addr, int32_t imm); -void instr32_83_1_reg(int32_t r1, int32_t imm); -void instr32_83_2_mem(int32_t addr, int32_t imm); -void instr32_83_2_reg(int32_t r1, int32_t imm); -void instr32_83_3_mem(int32_t addr, int32_t imm); -void instr32_83_3_reg(int32_t r1, int32_t imm); -void instr32_83_4_mem(int32_t addr, int32_t imm); -void instr32_83_4_reg(int32_t r1, int32_t imm); -void instr32_83_5_mem(int32_t addr, int32_t imm); -void instr32_83_5_reg(int32_t r1, int32_t imm); -void instr32_83_6_mem(int32_t addr, int32_t imm); -void instr32_83_6_reg(int32_t r1, int32_t imm); -void instr32_83_7_reg(int32_t r, int32_t imm); -void instr32_83_7_mem(int32_t addr, int32_t imm); -void instr_84_mem(int32_t addr, int32_t r); -void instr_84_reg(int32_t r1, int32_t r); -void instr16_85_mem(int32_t addr, int32_t r); -void instr16_85_reg(int32_t r1, int32_t r); -void instr32_85_mem(int32_t addr, int32_t r); -void instr32_85_reg(int32_t r1, int32_t r); -void instr_86_mem(int32_t addr, int32_t r); -void instr_86_reg(int32_t r1, int32_t r); -void instr16_87_mem(int32_t addr, int32_t r); -void instr16_87_reg(int32_t r1, int32_t r); -void instr32_87_mem(int32_t addr, int32_t r); -void instr32_87_reg(int32_t r1, int32_t r); -void instr_88_reg(int32_t r2, int32_t r); -void instr_88_mem(int32_t addr, int32_t r); -void instr16_89_reg(int32_t r2, int32_t r); -void instr16_89_mem(int32_t addr, int32_t r); -void instr32_89_reg(int32_t r2, int32_t r); -void instr32_89_mem(int32_t addr, int32_t r); -void instr_8A_mem(int32_t addr, int32_t r); -void instr_8A_reg(int32_t r1, int32_t r); -void instr16_8B_mem(int32_t addr, int32_t r); -void instr16_8B_reg(int32_t r1, int32_t r); -void instr32_8B_mem(int32_t addr, int32_t r); -void instr32_8B_reg(int32_t r1, int32_t r); -bool instr_8C_check_sreg(int32_t sreg); -void instr16_8C_reg(int32_t r, int32_t seg); -void instr16_8C_mem(int32_t addr, int32_t seg); -void instr32_8C_reg(int32_t r, int32_t seg); -void instr32_8C_mem(int32_t addr, int32_t seg); -void instr16_8D_reg(int32_t r, int32_t r2); -void instr16_8D_mem_pre(void); -void instr16_8D_mem(int32_t addr, int32_t r); -void instr32_8D_reg(int32_t r, int32_t r2); -void instr32_8D_mem_pre(void); -void instr32_8D_mem(int32_t addr, int32_t r); -void instr_8E_helper(int32_t data, int32_t mod); -void instr_8E_mem(int32_t addr, int32_t r); -void instr_8E_reg(int32_t r1, int32_t r); -void instr16_8F_0_mem_pre(void); -void instr16_8F_0_mem(int32_t addr); -void instr16_8F_0_reg(int32_t r); -void instr32_8F_0_mem_pre(void); -void instr32_8F_0_mem(int32_t addr); -void instr32_8F_0_reg(int32_t r); -void instr_90(void); -void instr16_91(void); -void instr32_91(void); -void instr16_92(void); -void instr32_92(void); -void instr16_93(void); -void instr32_93(void); -void instr16_94(void); -void instr32_94(void); -void instr16_95(void); -void instr32_95(void); -void instr16_96(void); -void instr32_96(void); -void instr16_97(void); -void instr32_97(void); -void instr16_98(void); -void instr32_98(void); -void instr16_99(void); -void instr32_99(void); -void instr16_9A(int32_t new_ip, int32_t new_cs); -void instr32_9A(int32_t new_ip, int32_t new_cs); -void instr_9B(void); -void instr16_9C(void); -void instr32_9C(void); -void instr16_9D(void); -void instr32_9D(void); -void instr_9E(void); -void instr_9F(void); -void instr_A0(int32_t moffs); -void instr16_A1(int32_t moffs); -void instr32_A1(int32_t moffs); -void instr_A2(int32_t moffs); -void instr16_A3(int32_t moffs); -void instr32_A3(int32_t moffs); -void instr_A4(void); -void instr16_A5(void); -void instr32_A5(void); -void instr_A6(void); -void instr16_A7(void); -void instr32_A7(void); -void instr_A8(int32_t imm8); -void instr16_A9(int32_t imm16); -void instr32_A9(int32_t imm32); -void instr_AA(void); -void instr16_AB(void); -void instr32_AB(void); -void instr_AC(void); -void instr16_AD(void); -void instr32_AD(void); -void instr_AE(void); -void instr16_AF(void); -void instr32_AF(void); -void instr_B0(int32_t imm8); -void instr_B1(int32_t imm8); -void instr_B2(int32_t imm8); -void instr_B3(int32_t imm8); -void instr_B4(int32_t imm8); -void instr_B5(int32_t imm8); -void instr_B6(int32_t imm8); -void instr_B7(int32_t imm8); -void instr16_B8(int32_t imm); -void instr32_B8(int32_t imm); -void instr16_B9(int32_t imm); -void instr32_B9(int32_t imm); -void instr16_BA(int32_t imm); -void instr32_BA(int32_t imm); -void instr16_BB(int32_t imm); -void instr32_BB(int32_t imm); -void instr16_BC(int32_t imm); -void instr32_BC(int32_t imm); -void instr16_BD(int32_t imm); -void instr32_BD(int32_t imm); -void instr16_BE(int32_t imm); -void instr32_BE(int32_t imm); -void instr16_BF(int32_t imm); -void instr32_BF(int32_t imm); -void instr_C0_0_mem(int32_t addr, int32_t imm); -void instr_C0_0_reg(int32_t r1, int32_t imm); -void instr_C0_1_mem(int32_t addr, int32_t imm); -void instr_C0_1_reg(int32_t r1, int32_t imm); -void instr_C0_2_mem(int32_t addr, int32_t imm); -void instr_C0_2_reg(int32_t r1, int32_t imm); -void instr_C0_3_mem(int32_t addr, int32_t imm); -void instr_C0_3_reg(int32_t r1, int32_t imm); -void instr_C0_4_mem(int32_t addr, int32_t imm); -void instr_C0_4_reg(int32_t r1, int32_t imm); -void instr_C0_5_mem(int32_t addr, int32_t imm); -void instr_C0_5_reg(int32_t r1, int32_t imm); -void instr_C0_6_mem(int32_t addr, int32_t imm); -void instr_C0_6_reg(int32_t r1, int32_t imm); -void instr_C0_7_mem(int32_t addr, int32_t imm); -void instr_C0_7_reg(int32_t r1, int32_t imm); -void instr16_C1_0_mem(int32_t addr, int32_t imm); -void instr16_C1_0_reg(int32_t r1, int32_t imm); -void instr16_C1_1_mem(int32_t addr, int32_t imm); -void instr16_C1_1_reg(int32_t r1, int32_t imm); -void instr16_C1_2_mem(int32_t addr, int32_t imm); -void instr16_C1_2_reg(int32_t r1, int32_t imm); -void instr16_C1_3_mem(int32_t addr, int32_t imm); -void instr16_C1_3_reg(int32_t r1, int32_t imm); -void instr16_C1_4_mem(int32_t addr, int32_t imm); -void instr16_C1_4_reg(int32_t r1, int32_t imm); -void instr16_C1_5_mem(int32_t addr, int32_t imm); -void instr16_C1_5_reg(int32_t r1, int32_t imm); -void instr16_C1_6_mem(int32_t addr, int32_t imm); -void instr16_C1_6_reg(int32_t r1, int32_t imm); -void instr16_C1_7_mem(int32_t addr, int32_t imm); -void instr16_C1_7_reg(int32_t r1, int32_t imm); -void instr32_C1_0_mem(int32_t addr, int32_t imm); -void instr32_C1_0_reg(int32_t r1, int32_t imm); -void instr32_C1_1_mem(int32_t addr, int32_t imm); -void instr32_C1_1_reg(int32_t r1, int32_t imm); -void instr32_C1_2_mem(int32_t addr, int32_t imm); -void instr32_C1_2_reg(int32_t r1, int32_t imm); -void instr32_C1_3_mem(int32_t addr, int32_t imm); -void instr32_C1_3_reg(int32_t r1, int32_t imm); -void instr32_C1_4_mem(int32_t addr, int32_t imm); -void instr32_C1_4_reg(int32_t r1, int32_t imm); -void instr32_C1_5_mem(int32_t addr, int32_t imm); -void instr32_C1_5_reg(int32_t r1, int32_t imm); -void instr32_C1_6_mem(int32_t addr, int32_t imm); -void instr32_C1_6_reg(int32_t r1, int32_t imm); -void instr32_C1_7_mem(int32_t addr, int32_t imm); -void instr32_C1_7_reg(int32_t r1, int32_t imm); -void instr16_C2(int32_t imm16); -void instr32_C2(int32_t imm16); -void instr16_C3(void); -void instr32_C3(void); -void instr16_C4_reg(int32_t _unused1, int32_t _unused2); -void instr16_C4_mem(int32_t addr, int32_t r); -void instr32_C4_reg(int32_t _unused1, int32_t _unused2); -void instr32_C4_mem(int32_t addr, int32_t r); -void instr16_C5_reg(int32_t _unused1, int32_t _unused2); -void instr16_C5_mem(int32_t addr, int32_t r); -void instr32_C5_reg(int32_t _unused1, int32_t _unused2); -void instr32_C5_mem(int32_t addr, int32_t r); -void instr_C6_0_reg(int32_t r, int32_t imm); -void instr_C6_0_mem(int32_t addr, int32_t imm); -void instr16_C7_0_reg(int32_t r, int32_t imm); -void instr16_C7_0_mem(int32_t addr, int32_t imm); -void instr32_C7_0_reg(int32_t r, int32_t imm); -void instr32_C7_0_mem(int32_t addr, int32_t imm); -void instr16_C8(int32_t size, int32_t nesting); -void instr32_C8(int32_t size, int32_t nesting); -void instr16_C9(void); -void instr32_C9(void); -void instr16_CA(int32_t imm16); -void instr32_CA(int32_t imm16); -void instr16_CB(void); -void instr32_CB(void); -void instr_CC(void); -void instr_CD(int32_t imm8); -void instr_CE(void); -void instr16_CF(void); -void instr32_CF(void); -void instr_D0_0_mem(int32_t addr); -void instr_D0_0_reg(int32_t r1); -void instr_D0_1_mem(int32_t addr); -void instr_D0_1_reg(int32_t r1); -void instr_D0_2_mem(int32_t addr); -void instr_D0_2_reg(int32_t r1); -void instr_D0_3_mem(int32_t addr); -void instr_D0_3_reg(int32_t r1); -void instr_D0_4_mem(int32_t addr); -void instr_D0_4_reg(int32_t r1); -void instr_D0_5_mem(int32_t addr); -void instr_D0_5_reg(int32_t r1); -void instr_D0_6_mem(int32_t addr); -void instr_D0_6_reg(int32_t r1); -void instr_D0_7_mem(int32_t addr); -void instr_D0_7_reg(int32_t r1); -void instr16_D1_0_mem(int32_t addr); -void instr16_D1_0_reg(int32_t r1); -void instr16_D1_1_mem(int32_t addr); -void instr16_D1_1_reg(int32_t r1); -void instr16_D1_2_mem(int32_t addr); -void instr16_D1_2_reg(int32_t r1); -void instr16_D1_3_mem(int32_t addr); -void instr16_D1_3_reg(int32_t r1); -void instr16_D1_4_mem(int32_t addr); -void instr16_D1_4_reg(int32_t r1); -void instr16_D1_5_mem(int32_t addr); -void instr16_D1_5_reg(int32_t r1); -void instr16_D1_6_mem(int32_t addr); -void instr16_D1_6_reg(int32_t r1); -void instr16_D1_7_mem(int32_t addr); -void instr16_D1_7_reg(int32_t r1); -void instr32_D1_0_mem(int32_t addr); -void instr32_D1_0_reg(int32_t r1); -void instr32_D1_1_mem(int32_t addr); -void instr32_D1_1_reg(int32_t r1); -void instr32_D1_2_mem(int32_t addr); -void instr32_D1_2_reg(int32_t r1); -void instr32_D1_3_mem(int32_t addr); -void instr32_D1_3_reg(int32_t r1); -void instr32_D1_4_mem(int32_t addr); -void instr32_D1_4_reg(int32_t r1); -void instr32_D1_5_mem(int32_t addr); -void instr32_D1_5_reg(int32_t r1); -void instr32_D1_6_mem(int32_t addr); -void instr32_D1_6_reg(int32_t r1); -void instr32_D1_7_mem(int32_t addr); -void instr32_D1_7_reg(int32_t r1); -void instr_D2_0_mem(int32_t addr); -void instr_D2_0_reg(int32_t r1); -void instr_D2_1_mem(int32_t addr); -void instr_D2_1_reg(int32_t r1); -void instr_D2_2_mem(int32_t addr); -void instr_D2_2_reg(int32_t r1); -void instr_D2_3_mem(int32_t addr); -void instr_D2_3_reg(int32_t r1); -void instr_D2_4_mem(int32_t addr); -void instr_D2_4_reg(int32_t r1); -void instr_D2_5_mem(int32_t addr); -void instr_D2_5_reg(int32_t r1); -void instr_D2_6_mem(int32_t addr); -void instr_D2_6_reg(int32_t r1); -void instr_D2_7_mem(int32_t addr); -void instr_D2_7_reg(int32_t r1); -void instr16_D3_0_mem(int32_t addr); -void instr16_D3_0_reg(int32_t r1); -void instr16_D3_1_mem(int32_t addr); -void instr16_D3_1_reg(int32_t r1); -void instr16_D3_2_mem(int32_t addr); -void instr16_D3_2_reg(int32_t r1); -void instr16_D3_3_mem(int32_t addr); -void instr16_D3_3_reg(int32_t r1); -void instr16_D3_4_mem(int32_t addr); -void instr16_D3_4_reg(int32_t r1); -void instr16_D3_5_mem(int32_t addr); -void instr16_D3_5_reg(int32_t r1); -void instr16_D3_6_mem(int32_t addr); -void instr16_D3_6_reg(int32_t r1); -void instr16_D3_7_mem(int32_t addr); -void instr16_D3_7_reg(int32_t r1); -void instr32_D3_0_mem(int32_t addr); -void instr32_D3_0_reg(int32_t r1); -void instr32_D3_1_mem(int32_t addr); -void instr32_D3_1_reg(int32_t r1); -void instr32_D3_2_mem(int32_t addr); -void instr32_D3_2_reg(int32_t r1); -void instr32_D3_3_mem(int32_t addr); -void instr32_D3_3_reg(int32_t r1); -void instr32_D3_4_mem(int32_t addr); -void instr32_D3_4_reg(int32_t r1); -void instr32_D3_5_mem(int32_t addr); -void instr32_D3_5_reg(int32_t r1); -void instr32_D3_6_mem(int32_t addr); -void instr32_D3_6_reg(int32_t r1); -void instr32_D3_7_mem(int32_t addr); -void instr32_D3_7_reg(int32_t r1); -void instr_D4(int32_t arg); -void instr_D5(int32_t arg); -void instr_D6(void); -void instr_D7(void); - -void instr_E0(int32_t off); -void instr_E1(int32_t off); -void instr_E2(int32_t off); -void instr_E3(int32_t off); -void instr_E4(int32_t port); -void instr16_E5(int32_t port); -void instr32_E5(int32_t port); -void instr_E6(int32_t port); -void instr16_E7(int32_t port); -void instr32_E7(int32_t port); -void instr16_E8(int32_t imm16); -void instr32_E8(int32_t imm32s); -void instr16_E9(int32_t imm16); -void instr32_E9(int32_t imm32s); -void instr16_EA(int32_t new_ip, int32_t cs); -void instr32_EA(int32_t new_ip, int32_t cs); -void instr_EB(int32_t imm8); -void instr_EC(void); -void instr16_ED(void); -void instr32_ED(void); -void instr_EE(void); -void instr16_EF(void); -void instr32_EF(void); -void instr_F0(void); -void instr_F1(void); -void instr_F2(void); -void instr_F3(void); -void instr_F4(void); -void instr_F5(void); -void instr_F6_0_mem(int32_t addr, int32_t imm); -void instr_F6_0_reg(int32_t r1, int32_t imm); -void instr_F6_1_mem(int32_t addr, int32_t imm); -void instr_F6_1_reg(int32_t r1, int32_t imm); -void instr_F6_2_mem(int32_t addr); -void instr_F6_2_reg(int32_t r1); -void instr_F6_3_mem(int32_t addr); -void instr_F6_3_reg(int32_t r1); -void instr_F6_4_mem(int32_t addr); -void instr_F6_4_reg(int32_t r1); -void instr_F6_5_mem(int32_t addr); -void instr_F6_5_reg(int32_t r1); -void instr_F6_6_mem(int32_t addr); -void instr_F6_6_reg(int32_t r1); -void instr_F6_7_mem(int32_t addr); -void instr_F6_7_reg(int32_t r1); -void instr16_F7_0_mem(int32_t addr, int32_t imm); -void instr16_F7_0_reg(int32_t r1, int32_t imm); -void instr16_F7_1_mem(int32_t addr, int32_t imm); -void instr16_F7_1_reg(int32_t r1, int32_t imm); -void instr16_F7_2_mem(int32_t addr); -void instr16_F7_2_reg(int32_t r1); -void instr16_F7_3_mem(int32_t addr); -void instr16_F7_3_reg(int32_t r1); -void instr16_F7_4_mem(int32_t addr); -void instr16_F7_4_reg(int32_t r1); -void instr16_F7_5_mem(int32_t addr); -void instr16_F7_5_reg(int32_t r1); -void instr16_F7_6_mem(int32_t addr); -void instr16_F7_6_reg(int32_t r1); -void instr16_F7_7_mem(int32_t addr); -void instr16_F7_7_reg(int32_t r1); -void instr32_F7_0_mem(int32_t addr, int32_t imm); -void instr32_F7_0_reg(int32_t r1, int32_t imm); -void instr32_F7_1_mem(int32_t addr, int32_t imm); -void instr32_F7_1_reg(int32_t r1, int32_t imm); -void instr32_F7_2_mem(int32_t addr); -void instr32_F7_2_reg(int32_t r1); -void instr32_F7_3_mem(int32_t addr); -void instr32_F7_3_reg(int32_t r1); -void instr32_F7_4_mem(int32_t addr); -void instr32_F7_4_reg(int32_t r1); -void instr32_F7_5_mem(int32_t addr); -void instr32_F7_5_reg(int32_t r1); -void instr32_F7_6_mem(int32_t addr); -void instr32_F7_6_reg(int32_t r1); -void instr32_F7_7_mem(int32_t addr); -void instr32_F7_7_reg(int32_t r1); -void instr_F8(void); -void instr_F9(void); -void instr_FA(void); -void instr_FB(void); -void instr_FC(void); -void instr_FD(void); -void instr_FE_0_mem(int32_t addr); -void instr_FE_0_reg(int32_t r1); -void instr_FE_1_mem(int32_t addr); -void instr_FE_1_reg(int32_t r1); -void instr16_FF_0_mem(int32_t addr); -void instr16_FF_0_reg(int32_t r1); -void instr16_FF_1_mem(int32_t addr); -void instr16_FF_1_reg(int32_t r1); -void instr16_FF_2_helper(int32_t data); -void instr16_FF_2_mem(int32_t addr); -void instr16_FF_2_reg(int32_t r1); -void instr16_FF_3_reg(int32_t r); -void instr16_FF_3_mem(int32_t addr); -void instr16_FF_4_helper(int32_t data); -void instr16_FF_4_mem(int32_t addr); -void instr16_FF_4_reg(int32_t r1); -void instr16_FF_5_reg(int32_t r); -void instr16_FF_5_mem(int32_t addr); -void instr16_FF_6_mem(int32_t addr); -void instr16_FF_6_reg(int32_t r1); -void instr32_FF_0_mem(int32_t addr); -void instr32_FF_0_reg(int32_t r1); -void instr32_FF_1_mem(int32_t addr); -void instr32_FF_1_reg(int32_t r1); -void instr32_FF_2_helper(int32_t data); -void instr32_FF_2_mem(int32_t addr); -void instr32_FF_2_reg(int32_t r1); -void instr32_FF_3_reg(int32_t r); -void instr32_FF_3_mem(int32_t addr); -void instr32_FF_4_helper(int32_t data); -void instr32_FF_4_mem(int32_t addr); -void instr32_FF_4_reg(int32_t r1); -void instr32_FF_5_reg(int32_t r); -void instr32_FF_5_mem(int32_t addr); -void instr32_FF_6_mem(int32_t addr); -void instr32_FF_6_reg(int32_t r1); - -void run_instruction(int32_t opcode); diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c deleted file mode 100644 index 4dd7def0..00000000 --- a/src/native/instructions_0f.c +++ /dev/null @@ -1,3940 +0,0 @@ -#include -#include -#include -#include - -#include "arith.h" -#include "const.h" -#include "cpu.h" -#include "fpu.h" -#include "global_pointers.h" -#include "instructions.h" -#include "instructions_0f.h" -#include "js_imports.h" -#include "log.h" -#include "memory.h" -#include "misc_instr.h" -#include "sse_instr.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-parameter" - -const bool CPU_LOG_VERBOSE = false; -const bool ENABLE_ACPI = true; - -bool apic_enabled = false; - -void instr_0F00_0_mem(int32_t addr) { - c_comment("sldt"); - if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } - safe_write16(addr, sreg[LDTR]); -} -void instr_0F00_0_reg(int32_t r) { - if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } - write_reg_osize(r, sreg[LDTR]); -} -void instr_0F00_1_mem(int32_t addr) { - c_comment("str"); - if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } - safe_write16(addr, sreg[TR]); -} -void instr_0F00_1_reg(int32_t r) { - if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } - write_reg_osize(r, sreg[TR]); -} -void instr_0F00_2_mem(int32_t addr) { - c_comment("lldt"); - if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } - if(cpl[0]) { trigger_gp_non_raising(0); return; } - load_ldt(safe_read16(addr)); -} -void instr_0F00_2_reg(int32_t r) { - if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } - if(cpl[0]) { trigger_gp_non_raising(0); return; } - load_ldt(read_reg16(r)); -} -void instr_0F00_3_mem(int32_t addr) { - c_comment("ltr"); - if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } - if(cpl[0]) { trigger_gp_non_raising(0); return; } - load_tr(safe_read16(addr)); -} -void instr_0F00_3_reg(int32_t r) { - if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } - if(cpl[0]) { trigger_gp_non_raising(0); return; } - load_tr(read_reg16(r)); -} -void instr_0F00_4_mem(int32_t addr) { - if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } - verr(safe_read16(addr)); -} -void instr_0F00_4_reg(int32_t r) { - if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } - verr(read_reg16(r)); -} -void instr_0F00_5_mem(int32_t addr) { - if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } - verw(safe_read16(addr)); -} -void instr_0F00_5_reg(int32_t r) { - if(!protected_mode[0] || vm86_mode()) { trigger_ud(); return; } - verw(read_reg16(r)); -} - - -void instr_0F01_0_reg(int32_t r) { trigger_ud(); } -void instr_0F01_0_mem(int32_t addr) { - c_comment("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); -} -void instr_0F01_1_reg(int32_t r) { trigger_ud(); } -void instr_0F01_1_mem(int32_t addr) { - c_comment("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); -} -void instr_0F01_2_reg(int32_t r) { trigger_ud(); } -void instr_0F01_2_mem(int32_t addr) { - c_comment("lgdt"); - if(cpl[0]) { trigger_gp_non_raising(0); return; } - 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; -} -void instr_0F01_3_reg(int32_t r) { trigger_ud(); } -void instr_0F01_3_mem(int32_t addr) { - c_comment("lidt"); - if(cpl[0]) { trigger_gp_non_raising(0); return; } - 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; -} - -void instr_0F01_4_reg(int32_t r) { - c_comment("smsw"); - write_reg_osize(r, cr[0]); -} -void instr_0F01_4_mem(int32_t addr) { - safe_write16(addr, cr[0] & 0xFFFF); -} - -void lmsw(int32_t new_cr0) { - new_cr0 = (cr[0] & ~0xF) | (new_cr0 & 0xF); - - if(protected_mode[0]) - { - c_comment("lmsw cannot be used to switch back"); - new_cr0 |= CR0_PE; - } - - set_cr0(new_cr0); -} -void instr_0F01_6_reg(int32_t r) { - if(cpl[0]) { trigger_gp_non_raising(0); return; } - lmsw(read_reg16(r)); -} -void instr_0F01_6_mem(int32_t addr) { - if(cpl[0]) { trigger_gp_non_raising(0); return; } - lmsw(safe_read16(addr)); -} - -void instr_0F01_7_reg(int32_t r) { trigger_ud(); } -void instr_0F01_7_mem(int32_t addr) { - c_comment("invlpg"); - if(cpl[0]) { trigger_gp_non_raising(0); return; } - 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)))) - -void instr_0F04() { undefined_instruction(); } -void instr_0F05() { undefined_instruction(); } - -void instr_0F06() { - c_comment("clts"); - if(cpl[0]) - { - dbg_log("clts #gp"); - trigger_gp_non_raising(0); - } - else - { - if(0 * 0) dbg_log("clts"); - cr[0] &= ~CR0_TS; - } -} - -void instr_0F07() { undefined_instruction(); } -void instr_0F08() { - c_comment("invd"); - undefined_instruction(); -} - -void instr_0F09() { - if(cpl[0]) - { - dbg_log("wbinvd #gp"); - trigger_gp_non_raising(0); - } - else - { - c_comment("wbinvd"); - } -} - - -void instr_0F0A() { undefined_instruction(); } -void instr_0F0B() { - c_comment("UD2"); - trigger_ud(); -} -void instr_0F0C() { undefined_instruction(); } - -void instr_0F0D() { - c_comment("nop"); - undefined_instruction(); -} - -void instr_0F0E() { undefined_instruction(); } -void instr_0F0F() { undefined_instruction(); } - -void instr_0F10(union reg128 source, int32_t r) { - c_comment("movups xmm, xmm/m128"); - mov_rm_r128(source, r); -} -DEFINE_SSE_SPLIT(instr_0F10, safe_read128s, read_xmm128s) - -void instr_F30F10_reg(int32_t r1, int32_t r2) { - c_comment("movss xmm, xmm/m32"); - union reg128 data = read_xmm128s(r1); - union reg128 orig = read_xmm128s(r2); - write_xmm128(r2, data.u32[0], orig.u32[1], orig.u32[2], orig.u32[3]); -} -void instr_F30F10_mem(int32_t addr, int32_t r) { - c_comment("movss xmm, xmm/m32"); - int32_t data = safe_read32s(addr); - write_xmm128(r, data, 0, 0, 0); -} - -void instr_660F10(union reg128 source, int32_t r) { - c_comment("movupd xmm, xmm/m128"); - mov_rm_r128(source, r); -} -DEFINE_SSE_SPLIT(instr_660F10, safe_read128s, read_xmm128s) - -void instr_F20F10_reg(int32_t r1, int32_t r2) { - c_comment("movsd xmm, xmm/m64"); - union reg128 data = read_xmm128s(r1); - union reg128 orig = read_xmm128s(r2); - write_xmm128(r2, data.u32[0], data.u32[1], orig.u32[2], orig.u32[3]); -} -void instr_F20F10_mem(int32_t addr, int32_t r) { - c_comment("movsd xmm, xmm/m64"); - union reg64 data = safe_read64s(addr); - write_xmm128(r, data.u32[0], data.u32[1], 0, 0); -} - -void instr_0F11_reg(int32_t r1, int32_t r2) { - c_comment("movups xmm/m128, xmm"); - mov_r_r128(r1, r2); -} -void instr_0F11_mem(int32_t addr, int32_t r) { - c_comment("movups xmm/m128, xmm"); - mov_r_m128(addr, r); -} - -void instr_F30F11_reg(int32_t rm_dest, int32_t reg_src) { - c_comment("movss xmm/m32, xmm"); - union reg128 data = read_xmm128s(reg_src); - union reg128 orig = read_xmm128s(rm_dest); - write_xmm128(rm_dest, data.u32[0], orig.u32[1], orig.u32[2], orig.u32[3]); -} -void instr_F30F11_mem(int32_t addr, int32_t r) { - c_comment("movss xmm/m32, xmm"); - union reg128 data = read_xmm128s(r); - safe_write32(addr, data.u32[0]); -} - -void instr_660F11_reg(int32_t r1, int32_t r2) { - c_comment("movupd xmm/m128, xmm"); - mov_r_r128(r1, r2); -} -void instr_660F11_mem(int32_t addr, int32_t r) { - c_comment("movupd xmm/m128, xmm"); - mov_r_m128(addr, r); -} - -void instr_F20F11_reg(int32_t r1, int32_t r2) { - c_comment("movsd xmm/m64, xmm"); - union reg128 data = read_xmm128s(r2); - union reg128 orig = read_xmm128s(r1); - write_xmm128(r1, data.u32[0], data.u32[1], orig.u32[2], orig.u32[3]); -} -void instr_F20F11_mem(int32_t addr, int32_t r) { - c_comment("movsd xmm/m64, xmm"); - union reg64 data = read_xmm64s(r); - safe_write64(addr, data.u64[0]); -} - -void instr_0F12_mem(int32_t addr, int32_t r) { - c_comment("movlps xmm, m64"); - union reg64 data = safe_read64s(addr); - union reg128 orig = read_xmm128s(r); - write_xmm128(r, data.u32[0], data.u32[1], orig.u32[2], orig.u32[3]); -} -void instr_0F12_reg(int32_t r1, int32_t r2) { - c_comment("movhlps xmm, xmm"); - union reg128 data = read_xmm128s(r1); - union reg128 orig = read_xmm128s(r2); - write_xmm128(r2, data.u32[2], data.u32[3], orig.u32[2], orig.u32[3]); -} - -void instr_660F12_reg(int32_t r1, int32_t r) { trigger_ud(); } -void instr_660F12_mem(int32_t addr, int32_t r) { - c_comment("movlpd xmm, m64"); - union reg64 data = safe_read64s(addr); - write_xmm64(r, data); -} -void instr_F20F12_mem(int32_t addr, int32_t r) { unimplemented_sse(); } -void instr_F20F12_reg(int32_t r1, int32_t r2) { unimplemented_sse(); } -void instr_F30F12_mem(int32_t addr, int32_t r) { unimplemented_sse(); } -void instr_F30F12_reg(int32_t r1, int32_t r2) { unimplemented_sse(); } - -void instr_0F13_mem(int32_t addr, int32_t r) { - c_comment("movlps m64, xmm"); - movl_r128_m64(addr, r); -} - -void instr_0F13_reg(int32_t r1, int32_t r2) { trigger_ud(); } - -void instr_660F13_reg(int32_t r1, int32_t r) { trigger_ud(); } -void instr_660F13_mem(int32_t addr, int32_t r) { - c_comment("movlpd xmm/m64, xmm"); - movl_r128_m64(addr, r); -} - -void instr_0F14(union reg64 source, int32_t r) { - c_comment("unpcklps xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg64 destination = read_xmm64s(r); - - write_xmm128( - r, - destination.u32[0], - source.u32[0], - destination.u32[1], - source.u32[1] - ); -} -DEFINE_SSE_SPLIT(instr_0F14, safe_read64s, read_xmm64s) - -void instr_660F14(union reg64 source, int32_t r) { - c_comment("unpcklpd xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg64 destination = read_xmm64s(r); - - write_xmm128( - r, - destination.u32[0], - destination.u32[1], - source.u32[0], - source.u32[1] - ); -} -DEFINE_SSE_SPLIT(instr_660F14, safe_read64s, read_xmm64s) - -void instr_0F15(union reg128 source, int32_t r) { - c_comment("unpckhps xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg128 destination = read_xmm128s(r); - - write_xmm128( - r, - destination.u32[2], - source.u32[2], - destination.u32[3], - source.u32[3] - ); -} -DEFINE_SSE_SPLIT(instr_0F15, safe_read128s, read_xmm128s) - -void instr_660F15(union reg128 source, int32_t r) { - c_comment("unpckhpd xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg128 destination = read_xmm128s(r); - - write_xmm128( - r, - destination.u32[2], - destination.u32[3], - source.u32[2], - source.u32[3] - ); -} -DEFINE_SSE_SPLIT(instr_660F15, safe_read128s, read_xmm128s) - -void instr_0F16_mem(int32_t addr, int32_t r) { - c_comment("movhps xmm, m64"); - movh_m64_r128(addr, r); -} -void instr_0F16_reg(int32_t r1, int32_t r2) { - c_comment("movlhps xmm, xmm"); - union reg128 data = read_xmm128s(r1); - union reg128 orig = read_xmm128s(r2); - write_xmm128(r2, orig.u32[0], orig.u32[1], data.u32[0], data.u32[1]); -} - -void instr_660F16_mem(int32_t addr, int32_t r) { - c_comment("movhpd xmm, m64"); - movh_m64_r128(addr, r); -} -void instr_660F16_reg(int32_t r1, int32_t r2) { trigger_ud(); } -void instr_F30F16() { unimplemented_sse(); } - -void instr_0F17_mem(int32_t addr, int32_t r) { - c_comment("movhps m64, xmm"); - movh_r128_m64(addr, r); -} -void instr_0F17_reg(int32_t r1, int32_t r2) { trigger_ud(); } - -void instr_660F17_mem(int32_t addr, int32_t r) { - c_comment("movhpd m64, xmm"); - movh_r128_m64(addr, r); -} -void instr_660F17_reg(int32_t r1, int32_t r2) { trigger_ud(); } - -void instr_0F18_reg(int32_t r1, int32_t r2) { - c_comment("reserved nop"); -} -void instr_0F18_mem(int32_t addr, int32_t r) { - c_comment("prefetch"); - c_comment("nop for us"); -} - -void instr_0F19_reg(int32_t r1, int32_t r2) { } -void instr_0F19_mem(int32_t addr, int32_t r) { } -void instr_0F1A() { undefined_instruction(); } -void instr_0F1B() { undefined_instruction(); } -void instr_0F1C_reg(int32_t r1, int32_t r2) { } -void instr_0F1C_mem(int32_t addr, int32_t r) { } -void instr_0F1D_reg(int32_t r1, int32_t r2) { } -void instr_0F1D_mem(int32_t addr, int32_t r) { } -void instr_0F1E_reg(int32_t r1, int32_t r2) { } -void instr_0F1E_mem(int32_t addr, int32_t r) { } -void instr_0F1F_reg(int32_t r1, int32_t r2) { } -void instr_0F1F_mem(int32_t addr, int32_t r) { } - - -void instr_0F20(int32_t r, int32_t creg) { - - if(cpl[0]) - { - trigger_gp_non_raising(0); - return; - } - - switch(creg) - { - case 0: - write_reg32(r, cr[0]); - break; - case 2: - write_reg32(r, cr[2]); - break; - case 3: - write_reg32(r, cr[3]); - break; - case 4: - write_reg32(r, cr[4]); - break; - default: - dbg_log1("%d", creg); - undefined_instruction(); - } -} - -void instr_0F21(int32_t r, int32_t dreg_index) { - if(cpl[0]) - { - trigger_gp_non_raising(0); - return; - } - - if(dreg_index == 4 || dreg_index == 5) - { - if(cr[4] & CR4_DE) - { - dbg_log("#ud mov dreg 4/5 with cr4.DE set"); - trigger_ud(); - return; - } - else - { - c_comment("DR4 and DR5 refer to DR6 and DR7 respectively"); - dreg_index += 2; - } - } - - write_reg32(r, dreg[dreg_index]); - - if(0 * 0) dbg_log2("read dr%d: %x", dreg_index, dreg[dreg_index]); -} - -void instr_0F22(int32_t r, int32_t creg) { - - if(cpl[0]) - { - trigger_gp_non_raising(0); - return; - } - - int32_t data = read_reg32(r); - - c_comment("mov cr, addr"); - switch(creg) - { - case 0: - if(0 * 0) dbg_log1("cr0 <- %x", data); - set_cr0(data); - break; - - case 2: - dbg_log1("cr2 <- %x", data); - cr[2] = data; - break; - - case 3: - if(0 * 0) dbg_log1("cr3 <- %x", data); - data &= ~0b111111100111; - dbg_assert_message((data & 0xFFF) == 0, "TODO"); - cr[3] = data; - clear_tlb(); - break; - - case 4: - dbg_log1("cr4 <- %d", cr[4]); - - if(data & (1 << 11 | 1 << 12 | 1 << 15 | 1 << 16 | 1 << 19 | 0xFFC00000)) - { - dbg_log("trigger_gp: Invalid cr4 bit"); - trigger_gp_non_raising(0); - return; - } - - if((cr[4] ^ data) & (CR4_PGE | CR4_PSE)) - { - full_clear_tlb(); - } - - cr[4] = data; - - if(cr[4] & CR4_PAE) - { - assert(false); - } - - break; - - default: - dbg_log1("%d", creg); - undefined_instruction(); - } -} -void instr_0F23(int32_t r, int32_t dreg_index) { - if(cpl[0]) - { - trigger_gp_non_raising(0); - return; - } - - if(dreg_index == 4 || dreg_index == 5) - { - if(cr[4] & CR4_DE) - { - dbg_log("#ud mov dreg 4/5 with cr4.DE set"); - trigger_ud(); - return; - } - else - { - c_comment("DR4 and DR5 refer to DR6 and DR7 respectively"); - dreg_index += 2; - } - } - - dreg[dreg_index] = read_reg32(r); - - if(0 * 0) dbg_log2("write dr%d: %x", dreg_index, dreg[dreg_index]); -} - -void instr_0F24() { undefined_instruction(); } -void instr_0F25() { undefined_instruction(); } -void instr_0F26() { undefined_instruction(); } -void instr_0F27() { undefined_instruction(); } - -void instr_0F28(union reg128 source, int32_t r) { - c_comment("movaps xmm, xmm/m128"); - c_comment("XXX: Aligned read or #gp"); - mov_rm_r128(source, r); -} -DEFINE_SSE_SPLIT(instr_0F28, safe_read128s, read_xmm128s) - -void instr_660F28(union reg128 source, int32_t r) { - c_comment("movapd xmm, xmm/m128"); - c_comment("XXX: Aligned read or #gp"); - c_comment("Note: Same as movdqa (660F6F)"); - mov_rm_r128(source, r); -} -DEFINE_SSE_SPLIT(instr_660F28, safe_read128s, read_xmm128s) - -void instr_0F29_mem(int32_t addr, int32_t r) { - c_comment("movaps m128, xmm"); - union reg128 data = read_xmm128s(r); - c_comment("XXX: Aligned write or #gp"); - safe_write128(addr, data); -} -void instr_0F29_reg(int32_t r1, int32_t r2) { - c_comment("movaps xmm, xmm"); - mov_r_r128(r1, r2); -} -void instr_660F29_mem(int32_t addr, int32_t r) { - c_comment("movapd m128, xmm"); - union reg128 data = read_xmm128s(r); - c_comment("XXX: Aligned write or #gp"); - safe_write128(addr, data); -} -void instr_660F29_reg(int32_t r1, int32_t r2) { - c_comment("movapd xmm, xmm"); - mov_r_r128(r1, r2); -} - -void instr_0F2A(union reg64 source, int32_t r) { - c_comment("cvtpi2ps xmm, mm/m64"); - c_comment("XXX: The non-memory variant causes a transition from x87 FPU to MMX technology operation"); - c_comment("Note: Casts here can fail"); - union reg64 result = { - .f32 = { - source.i32[0], - source.i32[1], - } - }; - write_xmm64(r, result); -} -DEFINE_SSE_SPLIT(instr_0F2A, safe_read64s, read_mmx64s) -void instr_660F2A(union reg64 source, int32_t r) { - c_comment("cvtpi2pd xmm, xmm/m64"); - c_comment("XXX: The non-memory variant causes a transition from x87 FPU to MMX technology operation"); - c_comment("These casts can't fail"); - union reg128 result = { - .f64 = { - source.i32[0], - source.i32[1], - } - }; - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660F2A, safe_read64s, read_mmx64s) -void instr_F20F2A(int32_t source, int32_t r) { - c_comment("cvtsi2sd xmm, r32/m32"); - c_comment("This cast can't fail"); - union reg64 result = { - .f64 = { source } - }; - write_xmm64(r, result); -} -DEFINE_SSE_SPLIT(instr_F20F2A, safe_read32s, read_reg32) -void instr_F30F2A(int32_t source, int32_t r) { - c_comment("cvtsi2ss xmm, r/m32"); - c_comment("Note: This cast can fail"); - float_t result = source; - write_xmm_f32(r, result); -} -DEFINE_SSE_SPLIT(instr_F30F2A, safe_read32s, read_reg32) - -void instr_0F2B_reg(int32_t r1, int32_t r2) { trigger_ud(); } -void instr_0F2B_mem(int32_t addr, int32_t r) { - c_comment("movntps m128, xmm"); - c_comment("XXX: Aligned write or #gp"); - mov_r_m128(addr, r); -} - -void instr_660F2B_reg(int32_t r1, int32_t r2) { trigger_ud(); } -void instr_660F2B_mem(int32_t addr, int32_t r) { - c_comment("movntpd m128, xmm"); - c_comment("XXX: Aligned write or #gp"); - mov_r_m128(addr, r); -} - -void instr_0F2C(union reg64 source, int32_t r) { unimplemented_sse(); } -DEFINE_SSE_SPLIT(instr_0F2C, safe_read64s, read_mmx64s) - -void instr_660F2C(union reg128 source, int32_t r) { unimplemented_sse(); } -DEFINE_SSE_SPLIT(instr_660F2C, safe_read128s, read_xmm128s) - -void instr_F20F2C(union reg64 source, int32_t r) { - c_comment("cvttsd2si r32, xmm/m64"); - c_comment("emscripten bug causes this ported instruction to throw 'integer result unpresentable'"); - c_comment("https://github.com/kripken/emscripten/issues/5433"); - if(0 * 0) - { - double f = source.f64[0]; - - if(f <= 0x7FFFFFFF && f >= -0x80000000) - { - int32_t si = (int32_t) f; - write_reg32(r, si); - } - else - { - write_reg32(r, 0x80000000); - } - } - else - { - write_reg32(r, convert_f64_to_i32(source.f64[0])); - } -} -DEFINE_SSE_SPLIT(instr_F20F2C, safe_read64s, read_xmm64s) - -void instr_F30F2C(float_t source, int32_t r) { unimplemented_sse(); } -DEFINE_SSE_SPLIT(instr_F30F2C, fpu_load_m32, read_xmm_f32) - -void instr_0F2D(union reg64 source, int32_t r) { unimplemented_sse(); } -DEFINE_SSE_SPLIT(instr_0F2D, safe_read64s, read_mmx64s) - -void instr_660F2D(union reg128 source, int32_t r) { unimplemented_sse(); } -DEFINE_SSE_SPLIT(instr_660F2D, safe_read128s, read_xmm128s) - -void instr_F20F2D(union reg64 source, int32_t r) { - c_comment("cvtsd2si r32, xmm/m64"); - write_reg32(r, sse_convert_f64_to_i32(source.f64[0])); -} -DEFINE_SSE_SPLIT(instr_F20F2D, safe_read64s, read_xmm64s) - -void instr_F30F2D(float_t source, int32_t r) { unimplemented_sse(); } -DEFINE_SSE_SPLIT(instr_F30F2D, fpu_load_m32, read_xmm_f32) - -void instr_0F2E() { unimplemented_sse(); } -void instr_0F2F() { unimplemented_sse(); } - -void instr_0F30() { - c_comment("wrmsr - write maschine specific register"); - - if(cpl[0]) - { - trigger_gp_non_raising(0); - return; - } - - int32_t index = reg32s[ECX]; - int32_t low = reg32s[EAX]; - int32_t high = reg32s[EDX]; - - if(index != IA32_SYSENTER_ESP) - { - dbg_log3("wrmsr ecx=%x data=%x:%x", index, high, low); - } - - if(index == IA32_SYSENTER_CS) - { - sysenter_cs[0] = low & 0xFFFF; - } - else if(index == IA32_SYSENTER_EIP) - { - sysenter_eip[0] = low; - - } - else if(index == IA32_SYSENTER_ESP) - { - sysenter_esp[0] = low; - - } - else if(index == IA32_APIC_BASE_MSR) - { - { - dbg_assert_message(high == 0, "Changing APIC address (high 32 bits) not supported"); - int32_t address = low & ~(IA32_APIC_BASE_BSP | IA32_APIC_BASE_EXTD | IA32_APIC_BASE_EN); - dbg_assert_message(address == APIC_ADDRESS, "Changing APIC address not supported"); - dbg_assert_message((low & IA32_APIC_BASE_EXTD) == 0, "x2apic not supported"); - apic_enabled = (low & IA32_APIC_BASE_EN) == IA32_APIC_BASE_EN; - } - - } - else if(index == IA32_TIME_STAMP_COUNTER) - { - set_tsc(low, high); - - } - else if(index == IA32_BIOS_SIGN_ID) - { - - } - else if(index == MSR_MISC_FEATURE_ENABLES) - { - c_comment("Linux 4, see: https://patchwork.kernel.org/patch/9528279/"); - - } - else if(index == IA32_MISC_ENABLE) - { c_comment("Enable Misc. Processor Features"); - - } - else if(index == IA32_MCG_CAP) - { - c_comment("netbsd"); - } - else if(index == IA32_KERNEL_GS_BASE) - { - c_comment("Only used in 64 bit mode (by SWAPGS), but set by kvm-unit-test"); - dbg_log("GS Base written"); - } - else - { - dbg_log1("Unknown msr: %x", index); - assert(false); - } -} - -void instr_0F31() { - c_comment("rdtsc - read timestamp counter"); - - if(!cpl[0] || !(cr[4] & CR4_TSD)) - { - uint64_t tsc = read_tsc(); - - reg32s[EAX] = tsc; - reg32s[EDX] = tsc >> 32; - - if(0 * 0) dbg_log2("rdtsc edx:eax=%x:%x", reg32s[EDX], reg32s[EAX]); - } - else - { - trigger_gp_non_raising(0); - } -} - -void instr_0F32() { - c_comment("rdmsr - read maschine specific register"); - if(cpl[0]) - { - trigger_gp_non_raising(0); - return; - } - - int32_t index = reg32s[ECX]; - - dbg_log1("rdmsr ecx=%x", index); - - int32_t low = 0; - int32_t high = 0; - - if(index == IA32_SYSENTER_CS) - { - low = sysenter_cs[0]; - - } - else if(index == IA32_SYSENTER_EIP) - { - low = sysenter_eip[0]; - - } - else if(index == IA32_SYSENTER_ESP) - { - low = sysenter_esp[0]; - - } - else if(index == IA32_TIME_STAMP_COUNTER) - { - { - uint64_t tsc = read_tsc(); - low = tsc; - high = tsc >> 32; - } - - } - else if(index == IA32_PLATFORM_ID) - { - - } - else if(index == IA32_APIC_BASE_MSR) - { - if(ENABLE_ACPI) - { - low = APIC_ADDRESS; - - if(apic_enabled) - { - low |= IA32_APIC_BASE_EN; - } - } - - } - else if(index == IA32_BIOS_SIGN_ID) - { - - } - else if(index == MSR_PLATFORM_INFO) - { - low = 1 << 8; - - } - else if(index == MSR_MISC_FEATURE_ENABLES) - { - - } - else if(index == IA32_MISC_ENABLE) - { c_comment("Enable Misc. Processor Features"); - low = 1 << 0; c_comment("fast string"); - - } - else if(index == IA32_RTIT_CTL) - { - c_comment("linux4"); - - } - else if(index == MSR_SMI_COUNT) - { - - } - else if(index == IA32_MCG_CAP) - { - c_comment("netbsd"); - - } - else if(index == MSR_PKG_C2_RESIDENCY) - { - } - else - { - dbg_log1("Unknown msr: %x", index); - assert(false); - } - - reg32s[EAX] = low; - reg32s[EDX] = high; -} - -void instr_0F33() { - c_comment("rdpmc"); - undefined_instruction(); -} - -void instr_0F34() { - c_comment("sysenter"); - int32_t seg = sysenter_cs[0] & 0xFFFC; - - if(!protected_mode[0] || seg == 0) - { - trigger_gp_non_raising(0); - return; - } - - flags[0] &= ~FLAG_VM & ~FLAG_INTERRUPT; - - instruction_pointer[0] = sysenter_eip[0]; - reg32s[ESP] = sysenter_esp[0]; - - sreg[CS] = seg; - segment_is_null[CS] = 0; - segment_limits[CS] = -1; - segment_offsets[CS] = 0; - - update_cs_size(true); - - cpl[0] = 0; - cpl_changed(); - - sreg[SS] = seg + 8; - segment_is_null[SS] = 0; - segment_limits[SS] = -1; - segment_offsets[SS] = 0; - - stack_size_32[0] = true; -} - -void instr_0F35() { - c_comment("sysexit"); - int32_t seg = sysenter_cs[0] & 0xFFFC; - - if(!protected_mode[0] || cpl[0] || seg == 0) - { - trigger_gp_non_raising(0); - return; - } - - instruction_pointer[0] = reg32s[EDX]; - reg32s[ESP] = reg32s[ECX]; - - sreg[CS] = seg + 16 | 3; - - segment_is_null[CS] = 0; - segment_limits[CS] = -1; - segment_offsets[CS] = 0; - - update_cs_size(true); - - cpl[0] = 3; - cpl_changed(); - - sreg[SS] = seg + 24 | 3; - segment_is_null[SS] = 0; - segment_limits[SS] = -1; - segment_offsets[SS] = 0; - - stack_size_32[0] = true; -} - -void instr_0F36() { undefined_instruction(); } - -void instr_0F37() { - c_comment("getsec"); - undefined_instruction(); -} - -// sse3+ -void instr_0F38() { unimplemented_sse(); } -void instr_0F39() { unimplemented_sse(); } -void instr_0F3A() { unimplemented_sse(); } -void instr_0F3B() { unimplemented_sse(); } -void instr_0F3C() { unimplemented_sse(); } -void instr_0F3D() { unimplemented_sse(); } -void instr_0F3E() { unimplemented_sse(); } -void instr_0F3F() { unimplemented_sse(); } - - -// cmov -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)) - - -void instr_0F50_reg(int32_t r1, int32_t r2) { - c_comment("movmskps r, xmm"); - union reg128 source = read_xmm128s(r1); - int32_t data = source.u32[0] >> 31 | (source.u32[1] >> 31) << 1 | - (source.u32[2] >> 31) << 2 | (source.u32[3] >> 31) << 3; - write_reg32(r2, data); -} -void instr_0F50_mem(int32_t addr, int32_t r1) { trigger_ud(); } - -void instr_660F50_reg(int32_t r1, int32_t r2) { - c_comment("movmskpd r, xmm"); - union reg128 source = read_xmm128s(r1); - int32_t data = (source.u32[1] >> 31) | (source.u32[3] >> 31) << 1; - write_reg32(r2, data); -} -void instr_660F50_mem(int32_t addr, int32_t r1) { trigger_ud(); } - -void instr_0F51(union reg128 source, int32_t r) { - c_comment("sqrtps xmm, xmm/mem128"); - union reg128 result = { - .f32 = { - sqrtf(source.f32[0]), - sqrtf(source.f32[1]), - sqrtf(source.f32[2]), - sqrtf(source.f32[3]), - } - }; - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_0F51, safe_read128s, read_xmm128s) -void instr_660F51(union reg128 source, int32_t r) { - c_comment("sqrtpd xmm, xmm/mem128"); - union reg128 result = { - .f64 = { - sqrt(source.f64[0]), - sqrt(source.f64[1]), - } - }; - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660F51, safe_read128s, read_xmm128s) -void instr_F20F51(union reg64 source, int32_t r) { - c_comment("sqrtsd xmm, xmm/mem64"); - union reg64 result = { - .f64 = { sqrt(source.f64[0]), } - }; - write_xmm64(r, result); -} -DEFINE_SSE_SPLIT(instr_F20F51, safe_read64s, read_xmm64s) -void instr_F30F51(float_t source, int32_t r) { - c_comment("sqrtss xmm, xmm/mem32"); - write_xmm_f32(r, sqrtf(source)); -} -DEFINE_SSE_SPLIT(instr_F30F51, fpu_load_m32, read_xmm_f32) - -void instr_0F52() { unimplemented_sse(); } - -void instr_0F53(union reg128 source, int32_t r) { - c_comment("rcpps xmm, xmm/m128"); - union reg128 result = { - .f32 = { - 1 / source.f32[0], - 1 / source.f32[1], - 1 / source.f32[2], - 1 / source.f32[3], - } - }; - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_0F53, safe_read128s, read_xmm128s) - -void instr_F30F53(float_t source, int32_t r) { - c_comment("rcpss xmm, xmm/m32"); - write_xmm_f32(r, 1 / source); -} -DEFINE_SSE_SPLIT(instr_F30F53, fpu_load_m32, read_xmm_f32) - -void instr_0F54(union reg128 source, int32_t r) { - c_comment("andps xmm, xmm/mem128"); - c_comment("XXX: Aligned access or #gp"); - pand_r128(source, r); -} -DEFINE_SSE_SPLIT(instr_0F54, safe_read128s, read_xmm128s) - -void instr_660F54(union reg128 source, int32_t r) { - c_comment("andpd xmm, xmm/mem128"); - c_comment("XXX: Aligned access or #gp"); - pand_r128(source, r); -} -DEFINE_SSE_SPLIT(instr_660F54, safe_read128s, read_xmm128s) - -void instr_0F55(union reg128 source, int32_t r) { - c_comment("andnps xmm, xmm/mem128"); - c_comment("XXX: Aligned access or #gp"); - pandn_r128(source, r); -} -DEFINE_SSE_SPLIT(instr_0F55, safe_read128s, read_xmm128s) - -void instr_660F55(union reg128 source, int32_t r) { - c_comment("andnpd xmm, xmm/mem128"); - c_comment("XXX: Aligned access or #gp"); - pandn_r128(source, r); -} -DEFINE_SSE_SPLIT(instr_660F55, safe_read128s, read_xmm128s) - -void instr_0F56(union reg128 source, int32_t r) { - c_comment("orps xmm, xmm/mem128"); - c_comment("XXX: Aligned access or #gp"); - por_r128(source, r); -} -DEFINE_SSE_SPLIT(instr_0F56, safe_read128s, read_xmm128s) - -void instr_660F56(union reg128 source, int32_t r) { - c_comment("orpd xmm, xmm/mem128"); - c_comment("XXX: Aligned access or #gp"); - por_r128(source, r); -} -DEFINE_SSE_SPLIT(instr_660F56, safe_read128s, read_xmm128s) - -void instr_0F57(union reg128 source, int32_t r) { - c_comment("xorps xmm, xmm/mem128"); - c_comment("XXX: Aligned access or #gp"); - pxor_r128(source, r); -} -DEFINE_SSE_SPLIT(instr_0F57, safe_read128s, read_xmm128s) - -void instr_660F57(union reg128 source, int32_t r) { - c_comment("xorpd xmm, xmm/mem128"); - c_comment("XXX: Aligned access or #gp"); - pxor_r128(source, r); -} -DEFINE_SSE_SPLIT(instr_660F57, safe_read128s, read_xmm128s) - -void instr_0F58(union reg128 source, int32_t r) { - c_comment("addps xmm, xmm/mem128"); - union reg128 destination = read_xmm128s(r); - union reg128 result = { - .f32 = { - source.f32[0] + destination.f32[0], - source.f32[1] + destination.f32[1], - source.f32[2] + destination.f32[2], - source.f32[3] + destination.f32[3], - } - }; - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_0F58, safe_read128s, read_xmm128s) -void instr_660F58(union reg128 source, int32_t r) { - c_comment("addpd xmm, xmm/mem128"); - union reg128 destination = read_xmm128s(r); - union reg128 result = { - .f64 = { - source.f64[0] + destination.f64[0], - source.f64[1] + destination.f64[1], - } - }; - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660F58, safe_read128s, read_xmm128s) -void instr_F20F58(union reg64 source, int32_t r) { - c_comment("addsd xmm, xmm/mem64"); - union reg64 destination = read_xmm64s(r); - union reg64 result = { - .f64 = { source.f64[0] + destination.f64[0], } - }; - write_xmm64(r, result); -} -DEFINE_SSE_SPLIT(instr_F20F58, safe_read64s, read_xmm64s) -void instr_F30F58(float_t source, int32_t r) { - c_comment("addss xmm, xmm/mem32"); - float_t destination = read_xmm_f32(r); - float result = source + destination; - write_xmm_f32(r, result); -} -DEFINE_SSE_SPLIT(instr_F30F58, fpu_load_m32, read_xmm_f32) - -void instr_0F59(union reg128 source, int32_t r) { - c_comment("mulps xmm, xmm/mem128"); - union reg128 destination = read_xmm128s(r); - union reg128 result = { - .f32 = { - source.f32[0] * destination.f32[0], - source.f32[1] * destination.f32[1], - source.f32[2] * destination.f32[2], - source.f32[3] * destination.f32[3], - } - }; - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_0F59, safe_read128s, read_xmm128s) -void instr_660F59(union reg128 source, int32_t r) { - c_comment("mulpd xmm, xmm/mem128"); - union reg128 destination = read_xmm128s(r); - union reg128 result = { - .f64 = { - source.f64[0] * destination.f64[0], - source.f64[1] * destination.f64[1], - } - }; - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660F59, safe_read128s, read_xmm128s) -void instr_F20F59(union reg64 source, int32_t r) { - c_comment("mulsd xmm, xmm/mem64"); - union reg64 destination = read_xmm64s(r); - union reg64 result = { - .f64 = { source.f64[0] * destination.f64[0], } - }; - write_xmm64(r, result); -} -DEFINE_SSE_SPLIT(instr_F20F59, safe_read64s, read_xmm64s) -void instr_F30F59(float_t source, int32_t r) { - c_comment("mulss xmm, xmm/mem32"); - float_t destination = read_xmm_f32(r); - float result = source * destination; - write_xmm_f32(r, result); -} -DEFINE_SSE_SPLIT(instr_F30F59, fpu_load_m32, read_xmm_f32) - -void instr_0F5A() { unimplemented_sse(); } -void instr_0F5B() { unimplemented_sse(); } - -void instr_0F5C(union reg128 source, int32_t r) { - c_comment("subps xmm, xmm/mem128"); - union reg128 destination = read_xmm128s(r); - union reg128 result = { - .f32 = { - destination.f32[0] - source.f32[0], - destination.f32[1] - source.f32[1], - destination.f32[2] - source.f32[2], - destination.f32[3] - source.f32[3], - } - }; - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_0F5C, safe_read128s, read_xmm128s) -void instr_660F5C(union reg128 source, int32_t r) { - c_comment("subpd xmm, xmm/mem128"); - union reg128 destination = read_xmm128s(r); - union reg128 result = { - .f64 = { - destination.f64[0] - source.f64[0], - destination.f64[1] - source.f64[1], - } - }; - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660F5C, safe_read128s, read_xmm128s) -void instr_F20F5C(union reg64 source, int32_t r) { - c_comment("subsd xmm, xmm/mem64"); - union reg64 destination = read_xmm64s(r); - union reg64 result = { - .f64 = { destination.f64[0] - source.f64[0], } - }; - write_xmm64(r, result); -} -DEFINE_SSE_SPLIT(instr_F20F5C, safe_read64s, read_xmm64s) -void instr_F30F5C(float_t source, int32_t r) { - c_comment("subss xmm, xmm/mem32"); - float_t destination = read_xmm_f32(r); - float result = destination - source; - write_xmm_f32(r, result); -} -DEFINE_SSE_SPLIT(instr_F30F5C, fpu_load_m32, read_xmm_f32) - -void instr_0F5D(union reg128 source, int32_t r) { - c_comment("minps xmm, xmm/mem128"); - union reg128 destination = read_xmm128s(r); - union reg128 result = { - .f32 = { - sse_min(destination.f32[0], source.f32[0]), - sse_min(destination.f32[1], source.f32[1]), - sse_min(destination.f32[2], source.f32[2]), - sse_min(destination.f32[3], source.f32[3]), - } - }; - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_0F5D, safe_read128s, read_xmm128s) -void instr_660F5D(union reg128 source, int32_t r) { - c_comment("minpd xmm, xmm/mem128"); - union reg128 destination = read_xmm128s(r); - union reg128 result = { - .f64 = { - sse_min(destination.f64[0], source.f64[0]), - sse_min(destination.f64[1], source.f64[1]), - } - }; - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660F5D, safe_read128s, read_xmm128s) -void instr_F20F5D(union reg64 source, int32_t r) { - c_comment("minsd xmm, xmm/mem64"); - union reg64 destination = read_xmm64s(r); - union reg64 result = { - .f64 = { sse_min(destination.f64[0], source.f64[0]), } - }; - write_xmm64(r, result); -} -DEFINE_SSE_SPLIT(instr_F20F5D, safe_read64s, read_xmm64s) -void instr_F30F5D(float_t source, int32_t r) { - c_comment("minss xmm, xmm/mem32"); - float_t destination = read_xmm_f32(r); - float result = sse_min(destination, source); - write_xmm_f32(r, result); -} -DEFINE_SSE_SPLIT(instr_F30F5D, fpu_load_m32, read_xmm_f32) - -void instr_0F5E(union reg128 source, int32_t r) { - c_comment("divps xmm, xmm/mem128"); - union reg128 destination = read_xmm128s(r); - union reg128 result = { - .f32 = { - destination.f32[0] / source.f32[0], - destination.f32[1] / source.f32[1], - destination.f32[2] / source.f32[2], - destination.f32[3] / source.f32[3], - } - }; - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_0F5E, safe_read128s, read_xmm128s) -void instr_660F5E(union reg128 source, int32_t r) { - c_comment("divpd xmm, xmm/mem128"); - union reg128 destination = read_xmm128s(r); - union reg128 result = { - .f64 = { - destination.f64[0] / source.f64[0], - destination.f64[1] / source.f64[1], - } - }; - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660F5E, safe_read128s, read_xmm128s) -void instr_F20F5E(union reg64 source, int32_t r) { - c_comment("divsd xmm, xmm/mem64"); - union reg64 destination = read_xmm64s(r); - union reg64 result = { - .f64 = { destination.f64[0] / source.f64[0], } - }; - write_xmm64(r, result); -} -DEFINE_SSE_SPLIT(instr_F20F5E, safe_read64s, read_xmm64s) -void instr_F30F5E(float_t source, int32_t r) { - c_comment("divss xmm, xmm/mem32"); - float_t destination = read_xmm_f32(r); - float result = destination / source; - write_xmm_f32(r, result); -} -DEFINE_SSE_SPLIT(instr_F30F5E, fpu_load_m32, read_xmm_f32) - -void instr_0F5F(union reg128 source, int32_t r) { - c_comment("maxps xmm, xmm/mem128"); - union reg128 destination = read_xmm128s(r); - union reg128 result = { - .f32 = { - sse_max(destination.f32[0], source.f32[0]), - sse_max(destination.f32[1], source.f32[1]), - sse_max(destination.f32[2], source.f32[2]), - sse_max(destination.f32[3], source.f32[3]), - } - }; - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_0F5F, safe_read128s, read_xmm128s) -void instr_660F5F(union reg128 source, int32_t r) { - c_comment("maxpd xmm, xmm/mem128"); - union reg128 destination = read_xmm128s(r); - union reg128 result = { - .f64 = { - sse_max(destination.f64[0], source.f64[0]), - sse_max(destination.f64[1], source.f64[1]), - } - }; - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660F5F, safe_read128s, read_xmm128s) -void instr_F20F5F(union reg64 source, int32_t r) { - c_comment("maxsd xmm, xmm/mem64"); - union reg64 destination = read_xmm64s(r); - union reg64 result = { - .f64 = { sse_max(destination.f64[0], source.f64[0]), } - }; - write_xmm64(r, result); -} -DEFINE_SSE_SPLIT(instr_F20F5F, safe_read64s, read_xmm64s) -void instr_F30F5F(float_t source, int32_t r) { - c_comment("maxss xmm, xmm/mem32"); - float_t destination = read_xmm_f32(r); - float result = sse_max(destination, source); - write_xmm_f32(r, result); -} -DEFINE_SSE_SPLIT(instr_F30F5F, fpu_load_m32, read_xmm_f32) - - -void instr_0F60(int32_t source, int32_t r) { - c_comment("punpcklbw mm, mm/m32"); - union reg64 destination = read_mmx64s(r); - - int32_t byte0 = destination.u8[0]; - int32_t byte1 = source & 0xFF; - int32_t byte2 = destination.u8[1]; - int32_t byte3 = (source >> 8) & 0xFF; - int32_t byte4 = destination.u8[2]; - int32_t byte5 = (source >> 16) & 0xFF; - 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_mmx64(r, low, high); -} -DEFINE_SSE_SPLIT(instr_0F60, safe_read32s, read_mmx32s) - -void instr_660F60(union reg64 source, int32_t r) { - c_comment("punpcklbw xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - 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) - -void instr_0F61(int32_t source, int32_t r) { - c_comment("punpcklwd mm, mm/m32"); - union reg64 destination = read_mmx64s(r); - - int32_t word0 = destination.u16[0]; - int32_t word1 = source & 0xFFFF; - int32_t word2 = destination.u16[1]; - int32_t word3 = source >> 16; - - int32_t low = word0 | word1 << 16; - int32_t high = word2 | word3 << 16; - - write_mmx64(r, low, high); -} -DEFINE_SSE_SPLIT(instr_0F61, safe_read32s, read_mmx32s) - -void instr_660F61(union reg64 source, int32_t r) { - c_comment("punpcklwd xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - 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) - -void instr_0F62(int32_t source, int32_t r) { - c_comment("punpckldq mm, mm/m32"); - union reg64 destination = read_mmx64s(r); - write_mmx64(r, destination.u32[0], source); -} -DEFINE_SSE_SPLIT(instr_0F62, safe_read32s, read_mmx32s) - -void instr_660F62(union reg128 source, int32_t r) { - c_comment("punpckldq xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg128 destination = read_xmm128s(r); - write_xmm128( - r, - destination.u32[0], - source.u32[0], - destination.u32[1], - source.u32[1] - ); -} -DEFINE_SSE_SPLIT(instr_660F62, safe_read128s, read_xmm128s) - -void instr_0F63(union reg64 source, int32_t r) { - c_comment("packsswb mm, mm/m64"); - union reg64 destination = read_mmx64s(r); - - int32_t low = saturate_sw_to_sb(destination.u16[0]) | - saturate_sw_to_sb(destination.u16[1]) << 8 | - saturate_sw_to_sb(destination.u16[2]) << 16 | - saturate_sw_to_sb(destination.u16[3]) << 24; - - int32_t high = saturate_sw_to_sb(source.u16[0]) | - saturate_sw_to_sb(source.u16[1]) << 8 | - saturate_sw_to_sb(source.u16[2]) << 16 | - saturate_sw_to_sb(source.u16[3]) << 24; - - write_mmx64(r, low, high); -} -DEFINE_SSE_SPLIT(instr_0F63, safe_read64s, read_mmx64s) - -void instr_660F63(union reg128 source, int32_t r) { - c_comment("packsswb xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg128 destination = read_xmm128s(r); - - int32_t dword0 = saturate_sw_to_sb(destination.u16[0]) | - saturate_sw_to_sb(destination.u16[1]) << 8 | - saturate_sw_to_sb(destination.u16[2]) << 16 | - saturate_sw_to_sb(destination.u16[3]) << 24; - - int32_t dword1 = saturate_sw_to_sb(destination.u16[4]) | - saturate_sw_to_sb(destination.u16[5]) << 8 | - saturate_sw_to_sb(destination.u16[6]) << 16 | - saturate_sw_to_sb(destination.u16[7]) << 24; - - int32_t dword2 = saturate_sw_to_sb(source.u16[0]) | - saturate_sw_to_sb(source.u16[1]) << 8 | - saturate_sw_to_sb(source.u16[2]) << 16 | - saturate_sw_to_sb(source.u16[3]) << 24; - - int32_t dword3 = saturate_sw_to_sb(source.u16[4]) | - saturate_sw_to_sb(source.u16[5]) << 8 | - saturate_sw_to_sb(source.u16[6]) << 16 | - saturate_sw_to_sb(source.u16[7]) << 24; - - write_xmm128(r, dword0, dword1, dword2, dword3); -} -DEFINE_SSE_SPLIT(instr_660F63, safe_read128s, read_xmm128s) - -void instr_0F64(union reg64 source, int32_t r) { - c_comment("pcmpgtb mm, mm/m64"); - union reg64 destination = read_mmx64s(r); - union reg64 result = { { 0 } }; - - for(uint32_t i = 0; i < 8; i++) - { - result.u8[i] = destination.i8[i] > source.i8[i] ? 0xFF : 0; - } - - write_mmx_reg64(r, result); -} -DEFINE_SSE_SPLIT(instr_0F64, safe_read64s, read_mmx64s) - -void instr_660F64(union reg128 source, int32_t r) { - c_comment("pcmpgtb xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg128 destination = read_xmm128s(r); - union reg128 result = { { 0 } }; - - for(int32_t i = 0; i < 16; i++) - { - result.i8[i] = destination.i8[i] > source.i8[i] ? 0xFF : 0; - } - - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660F64, safe_read128s, read_xmm128s) - -void instr_0F65(union reg64 source, int32_t r) { - c_comment("pcmpgtw mm, mm/m64"); - union reg64 destination = read_mmx64s(r); - - 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_mmx64(r, low, high); -} -DEFINE_SSE_SPLIT(instr_0F65, safe_read64s, read_mmx64s) - -void instr_660F65(union reg128 source, int32_t r) { - c_comment("pcmpgtw xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg128 destination = read_xmm128s(r); - union reg128 result = { { 0 } }; - - for(int32_t i = 0; i < 8; i++) - { - result.u16[i] = destination.i16[i] > source.i16[i] ? 0xFFFF : 0; - } - - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660F65, safe_read128s, read_xmm128s) - -void instr_0F66(union reg64 source, int32_t r) { - c_comment("pcmpgtd mm, mm/m64"); - union reg64 destination = read_mmx64s(r); - - int32_t low = destination.i32[0] > source.i32[0] ? -1 : 0; - int32_t high = destination.i32[1] > source.i32[1] ? -1 : 0; - - write_mmx64(r, low, high); -} -DEFINE_SSE_SPLIT(instr_0F66, safe_read64s, read_mmx64s) - -void instr_660F66(union reg128 source, int32_t r) { - c_comment("pcmpgtd xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg128 destination = read_xmm128s(r); - - write_xmm128( - r, - destination.i32[0] > source.i32[0] ? -1 : 0, - destination.i32[1] > source.i32[1] ? -1 : 0, - destination.i32[2] > source.i32[2] ? -1 : 0, - destination.i32[3] > source.i32[3] ? -1 : 0 - ); -} -DEFINE_SSE_SPLIT(instr_660F66, safe_read128s, read_xmm128s) - -void instr_0F67(union reg64 source, int32_t r) { - c_comment("packuswb mm, mm/m64"); - union reg64 destination = read_mmx64s(r); - - uint32_t low = saturate_sw_to_ub(destination.u16[0]) | - saturate_sw_to_ub(destination.u16[1]) << 8 | - saturate_sw_to_ub(destination.u16[2]) << 16 | - saturate_sw_to_ub(destination.u16[3]) << 24; - - uint32_t high = saturate_sw_to_ub(source.u16[0]) | - saturate_sw_to_ub(source.u16[1]) << 8 | - saturate_sw_to_ub(source.u16[2]) << 16 | - saturate_sw_to_ub(source.u16[3]) << 24; - - write_mmx64(r, low, high); -} -DEFINE_SSE_SPLIT(instr_0F67, safe_read64s, read_mmx64s) - -void instr_660F67(union reg128 source, int32_t r) { - c_comment("packuswb xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg128 destination = read_xmm128s(r); - union reg128 result; - - for(int32_t i = 0; i < 8; i++) - { - result.u8[i] = saturate_sw_to_ub(destination.u16[i]); - result.u8[i | 8] = saturate_sw_to_ub(source.u16[i]); - } - - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660F67, safe_read128s, read_xmm128s) - - -void instr_0F68(union reg64 source, int32_t r) { - c_comment("punpckhbw mm, mm/m64"); - union reg64 destination = read_mmx64s(r); - - 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_mmx64(r, low, high); -} -DEFINE_SSE_SPLIT(instr_0F68, safe_read64s, read_mmx64s) - -void instr_660F68(union reg128 source, int32_t r) { - c_comment("punpckhbw xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg128 destination = read_xmm128s(r); - - 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) - -void instr_0F69(union reg64 source, int32_t r) { - c_comment("punpckhwd mm, mm/m64"); - union reg64 destination = read_mmx64s(r); - - 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_mmx64(r, low, high); -} -DEFINE_SSE_SPLIT(instr_0F69, safe_read64s, read_mmx64s) - -void instr_660F69(union reg128 source, int32_t r) { - c_comment("punpckhwd xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg128 destination = read_xmm128s(r); - - int32_t dword0 = destination.u16[4] | source.u16[4] << 16; - int32_t dword1 = destination.u16[5] | source.u16[5] << 16; - int32_t dword2 = destination.u16[6] | source.u16[6] << 16; - int32_t dword3 = destination.u16[7] | source.u16[7] << 16; - - write_xmm128(r, dword0, dword1, dword2, dword3); -} -DEFINE_SSE_SPLIT(instr_660F69, safe_read128s, read_xmm128s) - -void instr_0F6A(union reg64 source, int32_t r) { - c_comment("punpckhdq mm, mm/m64"); - union reg64 destination = read_mmx64s(r); - write_mmx64(r, destination.u32[1], source.u32[1]); -} -DEFINE_SSE_SPLIT(instr_0F6A, safe_read64s, read_mmx64s) - -void instr_660F6A(union reg128 source, int32_t r) { - c_comment("punpckhdq xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg128 destination = read_xmm128s(r); - write_xmm128(r, destination.u32[2], source.u32[2], destination.u32[3], source.u32[3]); -} -DEFINE_SSE_SPLIT(instr_660F6A, safe_read128s, read_xmm128s) - -void instr_0F6B(union reg64 source, int32_t r) { - c_comment("packssdw mm, mm/m64"); - union reg64 destination = read_mmx64s(r); - - int32_t low = saturate_sd_to_sw(destination.u32[0]) | - saturate_sd_to_sw(destination.u32[1]) << 16; - int32_t high = saturate_sd_to_sw(source.u32[0]) | - saturate_sd_to_sw(source.u32[1]) << 16; - - write_mmx64(r, low, high); -} -DEFINE_SSE_SPLIT(instr_0F6B, safe_read64s, read_mmx64s) - -void instr_660F6B(union reg128 source, int32_t r) { - c_comment("packssdw xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg128 destination = read_xmm128s(r); - - int32_t dword0 = saturate_sd_to_sw(destination.u32[0]) | - saturate_sd_to_sw(destination.u32[1]) << 16; - int32_t dword1 = saturate_sd_to_sw(destination.u32[2]) | - saturate_sd_to_sw(destination.u32[3]) << 16; - int32_t dword2 = saturate_sd_to_sw(source.u32[0]) | - saturate_sd_to_sw(source.u32[1]) << 16; - int32_t dword3 = saturate_sd_to_sw(source.u32[2]) | - saturate_sd_to_sw(source.u32[3]) << 16; - - write_xmm128(r, dword0, dword1, dword2, dword3); -} -DEFINE_SSE_SPLIT(instr_660F6B, safe_read128s, read_xmm128s) - -void instr_0F6C_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_0F6C_reg(int32_t r1, int32_t r2) { trigger_ud(); } - -void instr_660F6C(union reg128 source, int32_t r) { - c_comment("punpcklqdq xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg128 destination = read_xmm128s(r); - - write_xmm128(r, destination.u32[0], destination.u32[1], source.u32[0], source.u32[1]); -} -DEFINE_SSE_SPLIT(instr_660F6C, safe_read128s, read_xmm128s) - -void instr_0F6D_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_0F6D_reg(int32_t r1, int32_t r2) { trigger_ud(); } - -void instr_660F6D(union reg128 source, int32_t r) { - c_comment("punpckhqdq xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg128 destination = read_xmm128s(r); - - write_xmm128(r, destination.u32[2], destination.u32[3], source.u32[2], source.u32[3]); -} -DEFINE_SSE_SPLIT(instr_660F6D, safe_read128s, read_xmm128s) - -void instr_0F6E(int32_t source, int32_t r) { - c_comment("movd mm, r/m32"); - write_mmx64(r, source, 0); -} -DEFINE_SSE_SPLIT(instr_0F6E, safe_read32s, read_reg32) - -void instr_660F6E(int32_t source, int32_t r) { - c_comment("movd mm, r/m32"); - write_xmm128(r, source, 0, 0, 0); -} -DEFINE_SSE_SPLIT(instr_660F6E, safe_read32s, read_reg32) - -void instr_0F6F(union reg64 source, int32_t r) { - c_comment("movq mm, mm/m64"); - write_mmx64(r, source.u32[0], source.u32[1]); -} -DEFINE_SSE_SPLIT(instr_0F6F, safe_read64s, read_mmx64s) - -void instr_660F6F(union reg128 source, int32_t r) { - c_comment("movdqa xmm, xmm/mem128"); - c_comment("XXX: Aligned access or #gp"); - c_comment("XXX: Aligned read or #gp"); - mov_rm_r128(source, r); -} -DEFINE_SSE_SPLIT(instr_660F6F, safe_read128s, read_xmm128s) -void instr_F30F6F(union reg128 source, int32_t r) { - c_comment("movdqu xmm, xmm/m128"); - mov_rm_r128(source, r); -} -DEFINE_SSE_SPLIT(instr_F30F6F, safe_read128s, read_xmm128s) - -void instr_0F70(union reg64 source, int32_t r, int32_t imm8) { - c_comment("pshufw mm1, mm2/m64, imm8"); - - int32_t word0_shift = imm8 & 0b11; - uint32_t word0 = source.u32[word0_shift >> 1] >> ((word0_shift & 1) << 4) & 0xFFFF; - 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 = (imm8 >> 4) & 0b11; - uint32_t word2 = source.u32[word2_shift >> 1] >> ((word2_shift & 1) << 4) & 0xFFFF; - 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_mmx64(r, low, high); -} -DEFINE_SSE_SPLIT_IMM(instr_0F70, safe_read64s, read_mmx64s) - -void instr_660F70(union reg128 source, int32_t r, int32_t imm8) { - c_comment("pshufd xmm, xmm/mem128"); - c_comment("XXX: Aligned access or #gp"); - 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) - -void instr_F20F70(union reg128 source, int32_t r, int32_t imm8) { - c_comment("pshuflw xmm, xmm/m128, imm8"); - c_comment("XXX: Aligned access or #gp"); - 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) - -void instr_F30F70(union reg128 source, int32_t r, int32_t imm8) { - c_comment("pshufhw xmm, xmm/m128, imm8"); - c_comment("XXX: Aligned access or #gp"); - write_xmm128( - r, - source.u32[0], - source.u32[1], - 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) - -void instr_0F71_2_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_0F71_4_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_0F71_6_mem(int32_t addr, int32_t r) { trigger_ud(); } - -void instr_0F71_2_reg(int32_t r, int32_t imm8) { - c_comment("psrlw mm, imm8"); - psrlw_r64(r, imm8); -} - -void instr_0F71_4_reg(int32_t r, int32_t imm8) { - c_comment("psraw mm, imm8"); - psraw_r64(r, imm8); -} - -void instr_0F71_6_reg(int32_t r, int32_t imm8) { - c_comment("psllw mm, imm8"); - psllw_r64(r, imm8); -} - -void instr_660F71_2_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_660F71_4_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_660F71_6_mem(int32_t addr, int32_t r) { trigger_ud(); } - -void instr_660F71_2_reg(int32_t r, int32_t imm8) { - c_comment("psrlw xmm, imm8"); - psrlw_r128(r, imm8); -} - -void instr_660F71_4_reg(int32_t r, int32_t imm8) { - c_comment("psraw xmm, imm8"); - psraw_r128(r, imm8); -} - -void instr_660F71_6_reg(int32_t r, int32_t imm8) { - c_comment("psllw xmm, imm8"); - psllw_r128(r, imm8); -} - -void instr_0F72_2_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_0F72_4_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_0F72_6_mem(int32_t addr, int32_t r) { trigger_ud(); } - -void instr_0F72_2_reg(int32_t r, int32_t imm8) { - c_comment("psrld mm, imm8"); - psrld_r64(r, imm8); -} - -void instr_0F72_4_reg(int32_t r, int32_t imm8) { - c_comment("psrad mm, imm8"); - psrad_r64(r, imm8); -} - -void instr_0F72_6_reg(int32_t r, int32_t imm8) { - c_comment("pslld mm, imm8"); - pslld_r64(r, imm8); -} - -void instr_660F72_2_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_660F72_4_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_660F72_6_mem(int32_t addr, int32_t r) { trigger_ud(); } - -void instr_660F72_2_reg(int32_t r, int32_t imm8) { - c_comment("psrld xmm, imm8"); - psrld_r128(r, imm8); -} - -void instr_660F72_4_reg(int32_t r, int32_t imm8) { - c_comment("psrad xmm, imm8"); - psrad_r128(r, imm8); -} - -void instr_660F72_6_reg(int32_t r, int32_t imm8) { - c_comment("pslld xmm, imm8"); - pslld_r128(r, imm8); -} - -void instr_0F73_2_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_0F73_6_mem(int32_t addr, int32_t r) { trigger_ud(); } - -void instr_0F73_2_reg(int32_t r, int32_t imm8) { - c_comment("psrlq mm, imm8"); - psrlq_r64(r, imm8); -} - -void instr_0F73_6_reg(int32_t r, int32_t imm8) { - c_comment("psllq mm, imm8"); - psllq_r64(r, imm8); -} - -void instr_660F73_2_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_660F73_3_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_660F73_6_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_660F73_7_mem(int32_t addr, int32_t r) { trigger_ud(); } - -void instr_660F73_2_reg(int32_t r, int32_t imm8) { - c_comment("psrlq xmm, imm8"); - psrlq_r128(r, imm8); -} - -void instr_660F73_3_reg(int32_t r, int32_t imm8) { - c_comment("psrldq xmm, imm8"); - union reg128 destination = read_xmm128s(r); - - if(imm8 == 0) - { - return; - } - - union reg128 result = { { 0 } }; - uint32_t shift = imm8 > 15 ? 128 : imm8 << 3; - - if(shift <= 63) - { - result.u64[0] = destination.u64[0] >> shift | destination.u64[1] << (64 - shift); - result.u64[1] = destination.u64[1] >> shift; - } - else if(shift <= 127) - { - result.u64[0] = destination.u64[1] >> (shift - 64); - result.u64[1] = 0; - } - - write_xmm_reg128(r, result); -} - -void instr_660F73_6_reg(int32_t r, int32_t imm8) { - c_comment("psllq xmm, imm8"); - psllq_r128(r, imm8); -} - - -void instr_660F73_7_reg(int32_t r, int32_t imm8) { - c_comment("pslldq xmm, imm8"); - union reg128 destination = read_xmm128s(r); - - if(imm8 == 0) - { - return; - } - - union reg128 result = { { 0 } }; - uint32_t shift = imm8 > 15 ? 128 : imm8 << 3; - - if(shift <= 63) - { - result.u64[0] = destination.u64[0] << shift; - result.u64[1] = destination.u64[1] << shift | destination.u64[0] >> (64 - shift); - } - else if(shift <= 127) - { - result.u64[0] = 0; - result.u64[1] = destination.u64[0] << (shift - 64); - } - - write_xmm_reg128(r, result); -} - -void instr_0F74(union reg64 source, int32_t r) { - c_comment("pcmpeqb mm, mm/m64"); - union reg64 destination = read_mmx64s(r); - union reg64 result = { { 0 } }; - - for(uint32_t i = 0; i < 8; i++) - { - result.u8[i] = destination.i8[i] == source.i8[i] ? 0xFF : 0; - } - - write_mmx_reg64(r, result); -} -DEFINE_SSE_SPLIT(instr_0F74, safe_read64s, read_mmx64s) - -void instr_660F74(union reg128 source, int32_t r) { - c_comment("pcmpeqb xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - union reg128 result; - - for(int32_t i = 0; i < 16; i++) - { - result.u8[i] = source.u8[i] == destination.u8[i] ? 0xFF : 0; - } - - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660F74, safe_read128s, read_xmm128s) - -void instr_0F75(union reg64 source, int32_t r) { - c_comment("pcmpeqw mm, mm/m64"); - union reg64 destination = read_mmx64s(r); - - 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_mmx64(r, low, high); -} -DEFINE_SSE_SPLIT(instr_0F75, safe_read64s, read_mmx64s) - -void instr_660F75(union reg128 source, int32_t r) { - c_comment("pcmpeqw xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg128 destination = read_xmm128s(r); - union reg128 result; - - for(int32_t i = 0; i < 8; i++) - { - result.u16[i] = source.u16[i] == destination.u16[i] ? 0xFFFF : 0; - } - - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660F75, safe_read128s, read_xmm128s) - -void instr_0F76(union reg64 source, int32_t r) { - c_comment("pcmpeqd mm, mm/m64"); - 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_mmx64(r, low, high); -} -DEFINE_SSE_SPLIT(instr_0F76, safe_read64s, read_mmx64s) - -void instr_660F76(union reg128 source, int32_t r) { - c_comment("pcmpeqd xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg128 destination = read_xmm128s(r); - - 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) - -void instr_0F77() { - c_comment("emms"); - fpu_set_tag_word(0xFFFF); -} - -void instr_0F78() { unimplemented_sse(); } -void instr_0F79() { unimplemented_sse(); } -void instr_0F7A() { unimplemented_sse(); } -void instr_0F7B() { unimplemented_sse(); } -void instr_0F7C() { unimplemented_sse(); } -void instr_0F7D() { unimplemented_sse(); } - -int32_t instr_0F7E(int32_t r) { - c_comment("movd r/m32, mm"); - union reg64 data = read_mmx64s(r); - return data.u32[0]; -} -DEFINE_SSE_SPLIT_WRITE(instr_0F7E, safe_write32, write_reg32) -int32_t instr_660F7E(int32_t r) { - c_comment("movd r/m32, xmm"); - union reg64 data = read_xmm64s(r); - return data.u32[0]; -} -DEFINE_SSE_SPLIT_WRITE(instr_660F7E, safe_write32, write_reg32) -void instr_F30F7E_mem(int32_t addr, int32_t r) { - c_comment("movq xmm, xmm/mem64"); - union reg64 data = safe_read64s(addr); - write_xmm128(r, data.u32[0], data.u32[1], 0, 0); -} -void instr_F30F7E_reg(int32_t r1, int32_t r2) { - c_comment("movq xmm, xmm/mem64"); - union reg64 data = read_xmm64s(r1); - write_xmm128(r2, data.u32[0], data.u32[1], 0, 0); -} - -void instr_0F7F_mem(int32_t addr, int32_t r) { - c_comment("movq mm/m64, mm"); - mov_r_m64(addr, r); -} -void instr_0F7F_reg(int32_t r1, int32_t r2) { - c_comment("movq mm/m64, mm"); - union reg64 data = read_mmx64s(r2); - write_mmx64(r1, data.u32[0], data.u32[1]); -} -void instr_660F7F_mem(int32_t addr, int32_t r) { - c_comment("movdqa xmm/m128, xmm"); - c_comment("XXX: Aligned write or #gp"); - mov_r_m128(addr, r); -} -void instr_660F7F_reg(int32_t r1, int32_t r2) { - c_comment("movdqa xmm/m128, xmm"); - c_comment("XXX: Aligned access or #gp"); - mov_r_r128(r1, r2); -} -void instr_F30F7F_mem(int32_t addr, int32_t r) { - c_comment("movdqu xmm/m128, xmm"); - mov_r_m128(addr, r); -} -void instr_F30F7F_reg(int32_t r1, int32_t r2) { - c_comment("movdqu xmm/m128, xmm"); - mov_r_r128(r1, r2); -} - -// jmpcc -void instr16_0F80(int32_t imm) { jmpcc16( test_o(), imm); } -void instr32_0F80(int32_t imm) { jmpcc32( test_o(), imm); } -void instr16_0F81(int32_t imm) { jmpcc16(!test_o(), imm); } -void instr32_0F81(int32_t imm) { jmpcc32(!test_o(), imm); } -void instr16_0F82(int32_t imm) { jmpcc16( test_b(), imm); } -void instr32_0F82(int32_t imm) { jmpcc32( test_b(), imm); } -void instr16_0F83(int32_t imm) { jmpcc16(!test_b(), imm); } -void instr32_0F83(int32_t imm) { jmpcc32(!test_b(), imm); } -void instr16_0F84(int32_t imm) { jmpcc16( test_z(), imm); } -void instr32_0F84(int32_t imm) { jmpcc32( test_z(), imm); } -void instr16_0F85(int32_t imm) { jmpcc16(!test_z(), imm); } -void instr32_0F85(int32_t imm) { jmpcc32(!test_z(), imm); } -void instr16_0F86(int32_t imm) { jmpcc16( test_be(), imm); } -void instr32_0F86(int32_t imm) { jmpcc32( test_be(), imm); } -void instr16_0F87(int32_t imm) { jmpcc16(!test_be(), imm); } -void instr32_0F87(int32_t imm) { jmpcc32(!test_be(), imm); } -void instr16_0F88(int32_t imm) { jmpcc16( test_s(), imm); } -void instr32_0F88(int32_t imm) { jmpcc32( test_s(), imm); } -void instr16_0F89(int32_t imm) { jmpcc16(!test_s(), imm); } -void instr32_0F89(int32_t imm) { jmpcc32(!test_s(), imm); } -void instr16_0F8A(int32_t imm) { jmpcc16( test_p(), imm); } -void instr32_0F8A(int32_t imm) { jmpcc32( test_p(), imm); } -void instr16_0F8B(int32_t imm) { jmpcc16(!test_p(), imm); } -void instr32_0F8B(int32_t imm) { jmpcc32(!test_p(), imm); } -void instr16_0F8C(int32_t imm) { jmpcc16( test_l(), imm); } -void instr32_0F8C(int32_t imm) { jmpcc32( test_l(), imm); } -void instr16_0F8D(int32_t imm) { jmpcc16(!test_l(), imm); } -void instr32_0F8D(int32_t imm) { jmpcc32(!test_l(), imm); } -void instr16_0F8E(int32_t imm) { jmpcc16( test_le(), imm); } -void instr32_0F8E(int32_t imm) { jmpcc32( test_le(), imm); } -void instr16_0F8F(int32_t imm) { jmpcc16(!test_le(), imm); } -void instr32_0F8F(int32_t imm) { jmpcc32(!test_le(), imm); } - -// setcc -void instr_0F90_reg(int32_t r, int32_t unused) { setcc_reg( test_o(), r); } -void instr_0F91_reg(int32_t r, int32_t unused) { setcc_reg(!test_o(), r); } -void instr_0F92_reg(int32_t r, int32_t unused) { setcc_reg( test_b(), r); } -void instr_0F93_reg(int32_t r, int32_t unused) { setcc_reg(!test_b(), r); } -void instr_0F94_reg(int32_t r, int32_t unused) { setcc_reg( test_z(), r); } -void instr_0F95_reg(int32_t r, int32_t unused) { setcc_reg(!test_z(), r); } -void instr_0F96_reg(int32_t r, int32_t unused) { setcc_reg( test_be(), r); } -void instr_0F97_reg(int32_t r, int32_t unused) { setcc_reg(!test_be(), r); } -void instr_0F98_reg(int32_t r, int32_t unused) { setcc_reg( test_s(), r); } -void instr_0F99_reg(int32_t r, int32_t unused) { setcc_reg(!test_s(), r); } -void instr_0F9A_reg(int32_t r, int32_t unused) { setcc_reg( test_p(), r); } -void instr_0F9B_reg(int32_t r, int32_t unused) { setcc_reg(!test_p(), r); } -void instr_0F9C_reg(int32_t r, int32_t unused) { setcc_reg( test_l(), r); } -void instr_0F9D_reg(int32_t r, int32_t unused) { setcc_reg(!test_l(), r); } -void instr_0F9E_reg(int32_t r, int32_t unused) { setcc_reg( test_le(), r); } -void instr_0F9F_reg(int32_t r, int32_t unused) { setcc_reg(!test_le(), r); } - -void instr_0F90_mem(int32_t addr, int32_t unused) { setcc_mem( test_o(), addr); } -void instr_0F91_mem(int32_t addr, int32_t unused) { setcc_mem(!test_o(), addr); } -void instr_0F92_mem(int32_t addr, int32_t unused) { setcc_mem( test_b(), addr); } -void instr_0F93_mem(int32_t addr, int32_t unused) { setcc_mem(!test_b(), addr); } -void instr_0F94_mem(int32_t addr, int32_t unused) { setcc_mem( test_z(), addr); } -void instr_0F95_mem(int32_t addr, int32_t unused) { setcc_mem(!test_z(), addr); } -void instr_0F96_mem(int32_t addr, int32_t unused) { setcc_mem( test_be(), addr); } -void instr_0F97_mem(int32_t addr, int32_t unused) { setcc_mem(!test_be(), addr); } -void instr_0F98_mem(int32_t addr, int32_t unused) { setcc_mem( test_s(), addr); } -void instr_0F99_mem(int32_t addr, int32_t unused) { setcc_mem(!test_s(), addr); } -void instr_0F9A_mem(int32_t addr, int32_t unused) { setcc_mem( test_p(), addr); } -void instr_0F9B_mem(int32_t addr, int32_t unused) { setcc_mem(!test_p(), addr); } -void instr_0F9C_mem(int32_t addr, int32_t unused) { setcc_mem( test_l(), addr); } -void instr_0F9D_mem(int32_t addr, int32_t unused) { setcc_mem(!test_l(), addr); } -void instr_0F9E_mem(int32_t addr, int32_t unused) { setcc_mem( test_le(), addr); } -void instr_0F9F_mem(int32_t addr, int32_t unused) { setcc_mem(!test_le(), addr); } - - -void instr16_0FA0() { push16(sreg[FS]); } -void instr32_0FA0() { push32(sreg[FS]); } -void instr16_0FA1() { - if(!switch_seg(FS, safe_read16(get_stack_pointer(0)))) return; - adjust_stack_reg(2); -} -void instr32_0FA1() { - if(!switch_seg(FS, safe_read32s(get_stack_pointer(0)) & 0xFFFF)) return; - adjust_stack_reg(4); -} - -void instr_0FA2() { cpuid(); } - -void instr16_0FA3_reg(int32_t r1, int32_t r2) { bt_reg(read_reg16(r1), read_reg16(r2) & 15); } -void instr16_0FA3_mem(int32_t addr, int32_t r) { bt_mem(addr, read_reg16(r) << 16 >> 16); } -void instr32_0FA3_reg(int32_t r1, int32_t r2) { bt_reg(read_reg32(r1), read_reg32(r2) & 31); } -void instr32_0FA3_mem(int32_t addr, int32_t r) { bt_mem(addr, read_reg32(r)); } - -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)) - -void instr_0FA6() { - c_comment("obsolete cmpxchg (os/2)"); - trigger_ud(); -} -void instr_0FA7() { undefined_instruction(); } - -void instr16_0FA8() { push16(sreg[GS]); } -void instr32_0FA8() { push32(sreg[GS]); } -void instr16_0FA9() { - if(!switch_seg(GS, safe_read16(get_stack_pointer(0)))) return; - adjust_stack_reg(2); -} -void instr32_0FA9() { - if(!switch_seg(GS, safe_read32s(get_stack_pointer(0)) & 0xFFFF)) return; - adjust_stack_reg(4); -} - - -void instr_0FAA() { - c_comment("rsm"); - undefined_instruction(); -} - -void instr16_0FAB_reg(int32_t r1, int32_t r2) { write_reg16(r1, bts_reg(read_reg16(r1), read_reg16(r2) & 15)); } -void instr16_0FAB_mem(int32_t addr, int32_t r) { bts_mem(addr, read_reg16(r) << 16 >> 16); } -void instr32_0FAB_reg(int32_t r1, int32_t r2) { write_reg32(r1, bts_reg(read_reg32(r1), read_reg32(r2) & 31)); } -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)) - -void instr_0FAE_0_reg(int32_t r) { trigger_ud(); } -void instr_0FAE_0_mem(int32_t addr) { - fxsave(addr); -} -void instr_0FAE_1_reg(int32_t r) { trigger_ud(); } -void instr_0FAE_1_mem(int32_t addr) { - fxrstor(addr); -} -void instr_0FAE_2_reg(int32_t r) { unimplemented_sse(); } -void instr_0FAE_2_mem(int32_t addr) { - c_comment("ldmxcsr"); - int32_t new_mxcsr = safe_read32s(addr); - if(new_mxcsr & ~MXCSR_MASK) - { - dbg_log1("Invalid mxcsr bits: %x", (new_mxcsr & ~MXCSR_MASK)); - assert(false); - trigger_gp_non_raising(0); - return; - } - *mxcsr = new_mxcsr; -} -void instr_0FAE_3_reg(int32_t r) { trigger_ud(); } -void instr_0FAE_3_mem(int32_t addr) { - c_comment("stmxcsr"); - safe_write32(addr, *mxcsr); -} -void instr_0FAE_4_reg(int32_t r) { trigger_ud(); } -void instr_0FAE_4_mem(int32_t addr) { - c_comment("xsave"); - undefined_instruction(); -} -void instr_0FAE_5_reg(int32_t r) { - c_comment("lfence"); - dbg_assert_message(r == 0, "Unexpected lfence encoding"); -} -void instr_0FAE_5_mem(int32_t addr) { - c_comment("xrstor"); - undefined_instruction(); -} -void instr_0FAE_6_reg(int32_t r) { - c_comment("mfence"); - dbg_assert_message(r == 0, "Unexpected mfence encoding"); -} -void instr_0FAE_6_mem(int32_t addr) { - c_comment("xsaveopt"); - undefined_instruction(); -} -void instr_0FAE_7_reg(int32_t r) { - c_comment("sfence"); - dbg_assert_message(r == 0, "Unexpected sfence encoding"); -} -void instr_0FAE_7_mem(int32_t addr) { - c_comment("clflush"); - undefined_instruction(); -} - -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), ___))) - -void instr_0FB0_reg(int32_t r1, int32_t r2) { - c_comment("cmpxchg8"); - int32_t data = read_reg8(r1); - cmp8(reg8[AL], data); - - if(getzf()) - { - write_reg8(r1, read_reg8(r2)); - } - else - { - reg8[AL] = data; - } -} -void instr_0FB0_mem(int32_t addr, int32_t r) { - c_comment("cmpxchg8"); - writable_or_pagefault(addr, 1); - int32_t data = safe_read8(addr); - cmp8(reg8[AL], data); - - if(getzf()) - { - safe_write8(addr, read_reg8(r)); - } - else - { - safe_write8(addr, data); - reg8[AL] = data; - } -} - -void instr16_0FB1_reg(int32_t r1, int32_t r2) { - c_comment("cmpxchg16"); - int32_t data = read_reg16(r1); - cmp16(reg16[AX], data); - - if(getzf()) - { - write_reg16(r1, read_reg16(r2)); - } - else - { - reg16[AX] = data; - } -} -void instr16_0FB1_mem(int32_t addr, int32_t r) { - c_comment("cmpxchg16"); - writable_or_pagefault(addr, 2); - int32_t data = safe_read16(addr); - cmp16(reg16[AX], data); - - if(getzf()) - { - safe_write16(addr, read_reg16(r)); - } - else - { - safe_write16(addr, data); - reg16[AX] = data; - } -} - -void instr32_0FB1_reg(int32_t r1, int32_t r2) { - c_comment("cmpxchg32"); - int32_t data = read_reg32(r1); - cmp32(reg32s[EAX], data); - - if(getzf()) - { - write_reg32(r1, read_reg32(r2)); - } - else - { - reg32s[EAX] = data; - } -} -void instr32_0FB1_mem(int32_t addr, int32_t r) { - c_comment("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 -void instr16_0FB2_reg(int32_t unused, int32_t unused2) { trigger_ud(); } -void instr16_0FB2_mem(int32_t addr, int32_t r) { - lss16(addr, get_reg16_index(r), SS); -} -void instr32_0FB2_reg(int32_t unused, int32_t unused2) { trigger_ud(); } -void instr32_0FB2_mem(int32_t addr, int32_t r) { - lss32(addr, r, SS); -} - -void instr16_0FB3_reg(int32_t r1, int32_t r2) { write_reg16(r1, btr_reg(read_reg16(r1), read_reg16(r2) & 15)); } -void instr16_0FB3_mem(int32_t addr, int32_t r) { btr_mem(addr, read_reg16(r) << 16 >> 16); } -void instr32_0FB3_reg(int32_t r1, int32_t r2) { write_reg32(r1, btr_reg(read_reg32(r1), read_reg32(r2) & 31)); } -void instr32_0FB3_mem(int32_t addr, int32_t r) { btr_mem(addr, read_reg32(r)); } - -// lfs, lgs -void instr16_0FB4_reg(int32_t unused, int32_t unused2) { trigger_ud(); } -void instr16_0FB4_mem(int32_t addr, int32_t r) { - lss16(addr, get_reg16_index(r), FS); -} -void instr32_0FB4_reg(int32_t unused, int32_t unused2) { trigger_ud(); } -void instr32_0FB4_mem(int32_t addr, int32_t r) { - lss32(addr, r, FS); -} -void instr16_0FB5_reg(int32_t unused, int32_t unused2) { trigger_ud(); } -void instr16_0FB5_mem(int32_t addr, int32_t r) { - lss16(addr, get_reg16_index(r), GS); -} -void instr32_0FB5_reg(int32_t unused, int32_t unused2) { trigger_ud(); } -void instr32_0FB5_mem(int32_t addr, int32_t r) { - lss32(addr, r, GS); -} - -// 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, ___)) - -void instr16_0FB8_reg(int32_t r1, int32_t r2) { trigger_ud(); } -void instr16_0FB8_mem(int32_t addr, int32_t r) { trigger_ud(); } -DEFINE_MODRM_INSTR_READ16(instr16_F30FB8, write_reg16(r, popcnt(___))) - -void instr32_0FB8_reg(int32_t r1, int32_t r2) { trigger_ud(); } -void instr32_0FB8_mem(int32_t addr, int32_t r) { trigger_ud(); } -DEFINE_MODRM_INSTR_READ32(instr32_F30FB8, write_reg32(r, popcnt(___))) - -void instr_0FB9() { - c_comment("UD2"); - trigger_ud(); -} - -void instr16_0FBA_4_reg(int32_t r, int32_t imm) { - bt_reg(read_reg16(r), imm & 15); -} -void instr16_0FBA_4_mem(int32_t addr, int32_t imm) { - bt_mem(addr, imm & 15); -} -void instr16_0FBA_5_reg(int32_t r, int32_t imm) { - write_reg16(r, bts_reg(read_reg16(r), imm & 15)); -} -void instr16_0FBA_5_mem(int32_t addr, int32_t imm) { - bts_mem(addr, imm & 15); -} -void instr16_0FBA_6_reg(int32_t r, int32_t imm) { - write_reg16(r, btr_reg(read_reg16(r), imm & 15)); -} -void instr16_0FBA_6_mem(int32_t addr, int32_t imm) { - btr_mem(addr, imm & 15); -} -void instr16_0FBA_7_reg(int32_t r, int32_t imm) { - write_reg16(r, btc_reg(read_reg16(r), imm & 15)); -} -void instr16_0FBA_7_mem(int32_t addr, int32_t imm) { - btc_mem(addr, imm & 15); -} - -void instr32_0FBA_4_reg(int32_t r, int32_t imm) { - bt_reg(read_reg32(r), imm & 31); -} -void instr32_0FBA_4_mem(int32_t addr, int32_t imm) { - bt_mem(addr, imm & 31); -} -void instr32_0FBA_5_reg(int32_t r, int32_t imm) { - write_reg32(r, bts_reg(read_reg32(r), imm & 31)); -} -void instr32_0FBA_5_mem(int32_t addr, int32_t imm) { - bts_mem(addr, imm & 31); -} -void instr32_0FBA_6_reg(int32_t r, int32_t imm) { - write_reg32(r, btr_reg(read_reg32(r), imm & 31)); -} -void instr32_0FBA_6_mem(int32_t addr, int32_t imm) { - btr_mem(addr, imm & 31); -} -void instr32_0FBA_7_reg(int32_t r, int32_t imm) { - write_reg32(r, btc_reg(read_reg32(r), imm & 31)); -} -void instr32_0FBA_7_mem(int32_t addr, int32_t imm) { - btc_mem(addr, imm & 31); -} - -void instr16_0FBB_reg(int32_t r1, int32_t r2) { write_reg16(r1, btc_reg(read_reg16(r1), read_reg16(r2) & 15)); } -void instr16_0FBB_mem(int32_t addr, int32_t r) { btc_mem(addr, read_reg16(r) << 16 >> 16); } -void instr32_0FBB_reg(int32_t r1, int32_t r2) { write_reg32(r1, btc_reg(read_reg32(r1), read_reg32(r2) & 31)); } -void instr32_0FBB_mem(int32_t addr, int32_t r) { btc_mem(addr, read_reg32(r)); } - -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), ___))) - -// 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)) - -void instr_0FC2(union reg128 source, int32_t r, int32_t imm8) { - c_comment("cmpps xmm, xmm/m128"); - union reg128 destination = read_xmm128s(r); - union reg128 result = { - .i32 = { - sse_comparison(imm8, destination.f32[0], source.f32[0]) ? -1 : 0, - sse_comparison(imm8, destination.f32[1], source.f32[1]) ? -1 : 0, - sse_comparison(imm8, destination.f32[2], source.f32[2]) ? -1 : 0, - sse_comparison(imm8, destination.f32[3], source.f32[3]) ? -1 : 0, - } - }; - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT_IMM(instr_0FC2, safe_read128s, read_xmm128s) - -void instr_660FC2(union reg128 source, int32_t r, int32_t imm8) { - c_comment("cmppd xmm, xmm/m128"); - union reg128 destination = read_xmm128s(r); - union reg128 result = { - .i64 = { - sse_comparison(imm8, destination.f64[0], source.f64[0]) ? -1 : 0, - sse_comparison(imm8, destination.f64[1], source.f64[1]) ? -1 : 0, - } - }; - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT_IMM(instr_660FC2, safe_read128s, read_xmm128s) -void instr_F20FC2(union reg64 source, int32_t r, int32_t imm8) { - c_comment("cmpsd xmm, xmm/m64"); - union reg64 destination = read_xmm64s(r); - union reg64 result = { - .i64 = { sse_comparison(imm8, destination.f64[0], source.f64[0]) ? -1 : 0, } - }; - write_xmm64(r, result); -} -DEFINE_SSE_SPLIT_IMM(instr_F20FC2, safe_read64s, read_xmm64s) -void instr_F30FC2(float_t source, int32_t r, int32_t imm8) { - c_comment("cmpss xmm, xmm/m32"); - float_t destination = read_xmm_f32(r); - int32_t result = sse_comparison(imm8, destination, source) ? -1 : 0; - write_xmm32(r, result); -} -DEFINE_SSE_SPLIT_IMM(instr_F30FC2, fpu_load_m32, read_xmm_f32) - -void instr_0FC3_reg(int32_t r1, int32_t r2) { trigger_ud(); } -void instr_0FC3_mem(int32_t addr, int32_t r) { - c_comment("movnti"); - safe_write32(addr, read_reg32(r)); -} - -void instr_0FC4(int32_t source, int32_t r, int32_t imm8) { - c_comment("pinsrw mm, r32/m16, imm8"); - union reg64 destination = read_mmx64s(r); - - uint32_t index = imm8 & 3; - destination.u16[index] = source & 0xffff; - - write_mmx_reg64(r, destination); -} -DEFINE_SSE_SPLIT_IMM(instr_0FC4, safe_read16, read_reg32) - -void instr_660FC4(int32_t source, int32_t r, int32_t imm8) { - c_comment("pinsrw xmm, r32/m16, imm8"); - union reg128 destination = read_xmm128s(r); - - uint32_t index = imm8 & 7; - destination.u16[index] = source & 0xffff; - - write_xmm_reg128(r, destination); -} -DEFINE_SSE_SPLIT_IMM(instr_660FC4, safe_read16, read_reg32) - -void instr_0FC5_mem(int32_t addr, int32_t r, int32_t imm8) { trigger_ud(); } -void instr_0FC5_reg(int32_t r1, int32_t r2, int32_t imm8) { - c_comment("pextrw r32, mm, imm8"); - - union reg64 data = read_mmx64s(r1); - uint32_t index = imm8 & 3; - uint32_t result = data.u16[index]; - - write_reg32(r2, result); -} - -void instr_660FC5_mem(int32_t addr, int32_t r, int32_t imm8) { trigger_ud(); } -void instr_660FC5_reg(int32_t r1, int32_t r2, int32_t imm8) { - c_comment("pextrw r32, xmm, imm8"); - - union reg128 data = read_xmm128s(r1); - uint32_t index = imm8 & 7; - uint32_t result = data.u16[index]; - - write_reg32(r2, result); -} - -void instr_0FC6() { unimplemented_sse(); } - -void instr_0FC7_1_reg(int32_t r) { trigger_ud(); } -void instr_0FC7_1_mem(int32_t addr) { - c_comment("cmpxchg8b"); - 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; -} - -void instr_0FC7_6_reg(int32_t r) { - c_comment("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; -} -void instr_0FC7_6_mem(int32_t addr) { - trigger_ud(); -} - -void instr_0FC8() { bswap(EAX); } -void instr_0FC9() { bswap(ECX); } -void instr_0FCA() { bswap(EDX); } -void instr_0FCB() { bswap(EBX); } -void instr_0FCC() { bswap(ESP); } -void instr_0FCD() { bswap(EBP); } -void instr_0FCE() { bswap(ESI); } -void instr_0FCF() { bswap(EDI); } - -void instr_0FD0() { unimplemented_sse(); } - -void instr_0FD1(union reg64 source, int32_t r) { - c_comment("psrlw mm, mm/m64"); - psrlw_r64(r, source.u32[0]); -} -DEFINE_SSE_SPLIT(instr_0FD1, safe_read64s, read_mmx64s) - -void instr_660FD1(union reg128 source, int32_t r) { - c_comment("psrlw xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - psrlw_r128(r, source.u32[0]); -} -DEFINE_SSE_SPLIT(instr_660FD1, safe_read128s, read_xmm128s) - -void instr_0FD2(union reg64 source, int32_t r) { - c_comment("psrld mm, mm/m64"); - psrld_r64(r, source.u32[0]); -} -DEFINE_SSE_SPLIT(instr_0FD2, safe_read64s, read_mmx64s) - -void instr_660FD2(union reg128 source, int32_t r) { - c_comment("psrld xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - psrld_r128(r, source.u32[0]); -} -DEFINE_SSE_SPLIT(instr_660FD2, safe_read128s, read_xmm128s) - -void instr_0FD3(union reg64 source, int32_t r) { - c_comment("psrlq mm, mm/m64"); - psrlq_r64(r, source.u32[0]); -} -DEFINE_SSE_SPLIT(instr_0FD3, safe_read64s, read_mmx64s) - -void instr_660FD3(union reg128 source, int32_t r) { - c_comment("psrlq xmm, mm/m64"); - psrlq_r128(r, source.u32[0]); -} -DEFINE_SSE_SPLIT(instr_660FD3, safe_read128s, read_xmm128s) - -void instr_0FD4(union reg64 source, int32_t r) { - c_comment("paddq mm, mm/m64"); - union reg64 destination = read_mmx64s(r); - destination.u64[0] += source.u64[0]; - write_mmx_reg64(r, destination); -} -DEFINE_SSE_SPLIT(instr_0FD4, safe_read64s, read_mmx64s) - -void instr_660FD4(union reg128 source, int32_t r) { - c_comment("paddq xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg128 destination = read_xmm128s(r); - destination.u64[0] += source.u64[0]; - destination.u64[1] += source.u64[1]; - write_xmm_reg128(r, destination); -} -DEFINE_SSE_SPLIT(instr_660FD4, safe_read128s, read_xmm128s) - -void instr_0FD5(union reg64 source, int32_t r) { - c_comment("pmullw mm, mm/m64"); - - 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 low = word0 | word1 << 16; - int32_t high = word2 | word3 << 16; - - write_mmx64(r, low, high); -} -DEFINE_SSE_SPLIT(instr_0FD5, safe_read64s, read_mmx64s) - -void instr_660FD5(union reg128 source, int32_t r) { - c_comment("pmullw xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg128 destination = read_xmm128s(r); - - 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) - -void instr_0FD6_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_0FD6_reg(int32_t r1, int32_t r2) { trigger_ud(); } - -void instr_660FD6_mem(int32_t addr, int32_t r) { - c_comment("movq xmm/m64, xmm"); - movl_r128_m64(addr, r); -} -void instr_660FD6_reg(int32_t r1, int32_t r2) { - c_comment("movq xmm/m64, xmm"); - union reg64 data = read_xmm64s(r2); - write_xmm128(r1, data.u32[0], data.u32[1], 0, 0); -} - -void instr_F20FD6_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_F20FD6_reg(int32_t r1, int32_t r2) { - c_comment("movdq2q mm, xmm"); - union reg128 source = read_xmm128s(r1); - write_mmx64(r2, source.u32[0], source.u32[1]); -} - -void instr_F30FD6_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_F30FD6_reg(int32_t r1, int32_t r2) { - c_comment("movq2dq xmm, mm"); - union reg64 source = read_mmx64s(r1); - write_xmm128(r2, source.u32[0], source.u32[1], 0, 0); -} - -void instr_0FD7_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_0FD7_reg(int32_t r1, int32_t r2) { - c_comment("pmovmskb r, mm"); - union reg64 x = read_mmx64s(r1); - uint32_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; - write_reg32(r2, result); -} - -void instr_660FD7_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_660FD7_reg(int32_t r1, int32_t r2) { - c_comment("pmovmskb reg, xmm"); - - 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_reg32(r2, result); -} - -void instr_0FD8(union reg64 source, int32_t r) { - c_comment("psubusb mm, mm/m64"); - - union reg64 destination = read_mmx64s(r); - union reg64 result = { { 0 } }; - - for(uint32_t i = 0; i < 8; i++) - { - result.u8[i] = saturate_sd_to_ub(destination.u8[i] - source.u8[i]); - } - - write_mmx_reg64(r, result); -} -DEFINE_SSE_SPLIT(instr_0FD8, safe_read64s, read_mmx64s) - -void instr_660FD8(union reg128 source, int32_t r) { - c_comment("psubusb xmm, xmm/m128"); - - union reg128 destination = read_xmm128s(r); - union reg128 result; - - for(uint32_t i = 0; i < 16; i++) - { - result.u8[i] = saturate_sd_to_ub(destination.u8[i] - source.u8[i]); - } - - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660FD8, safe_read128s, read_xmm128s) - -void instr_0FD9(union reg64 source, int32_t r) { - c_comment("psubusw mm, mm/m64"); - - union reg64 destination = read_mmx64s(r); - - 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_mmx64(r, low, high); -} -DEFINE_SSE_SPLIT(instr_0FD9, safe_read64s, read_mmx64s) - -void instr_660FD9(union reg128 source, int32_t r) { - c_comment("psubusw xmm, xmm/m128"); - - union reg128 destination = read_xmm128s(r); - union reg128 result; - - for(uint32_t i = 0; i < 8; i++) - { - result.u16[i] = saturate_uw(destination.u16[i] - source.u16[i]); - } - - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660FD9, safe_read128s, read_xmm128s) - -void instr_0FDA(union reg64 source, int32_t r) { - c_comment("pminub mm, mm/m64"); - - union reg64 destination = read_mmx64s(r); - union reg64 result; - - for(uint32_t i = 0; i < 8; i++) - { - result.u8[i] = source.u8[i] < destination.u8[i] ? source.u8[i] : destination.u8[i]; - } - - write_mmx_reg64(r, result); -} -DEFINE_SSE_SPLIT(instr_0FDA, safe_read64s, read_mmx64s) - -void instr_660FDA(union reg128 source, int32_t r) { - c_comment("pminub xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - union reg128 result; - - for(uint32_t i = 0; i < 16; i++) - { - result.u8[i] = source.u8[i] < destination.u8[i] ? source.u8[i] : destination.u8[i]; - } - - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660FDA, safe_read128s, read_xmm128s) - -void instr_0FDB(union reg64 source, int32_t r) { - c_comment("pand mm, mm/m64"); - - union reg64 destination = read_mmx64s(r); - union reg64 result = { { 0 } }; - - result.u64[0] = source.u64[0] & destination.u64[0]; - - write_mmx_reg64(r, result); -} -DEFINE_SSE_SPLIT(instr_0FDB, safe_read64s, read_mmx64s) - -void instr_660FDB(union reg128 source, int32_t r) { - c_comment("pand xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - pand_r128(source, r); -} -DEFINE_SSE_SPLIT(instr_660FDB, safe_read128s, read_xmm128s) - -void instr_0FDC(union reg64 source, int32_t r) { - c_comment("paddusb mm, mm/m64"); - - union reg64 destination = read_mmx64s(r); - union reg64 result = { { 0 } }; - - for(uint32_t i = 0; i < 8; i++) - { - result.u8[i] = saturate_ud_to_ub(destination.u8[i] + source.u8[i]); - } - - write_mmx_reg64(r, result); -} -DEFINE_SSE_SPLIT(instr_0FDC, safe_read64s, read_mmx64s) - -void instr_660FDC(union reg128 source, int32_t r) { - c_comment("paddusb xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - union reg128 result; - - for(uint32_t i = 0; i < 16; i++) - { - result.u8[i] = saturate_ud_to_ub(source.u8[i] + destination.u8[i]); - } - - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660FDC, safe_read128s, read_xmm128s) - -void instr_0FDD(union reg64 source, int32_t r) { - c_comment("paddusw mm, mm/m64"); - - union reg64 destination = read_mmx64s(r); - - 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_mmx64(r, low, high); -} -DEFINE_SSE_SPLIT(instr_0FDD, safe_read64s, read_mmx64s) - -void instr_660FDD(union reg128 source, int32_t r) { - c_comment("paddusw xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - - 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) - -void instr_0FDE(union reg64 source, int32_t r) { - c_comment("pmaxub mm, mm/m64"); - - union reg64 destination = read_mmx64s(r); - union reg64 result; - - for(uint32_t i = 0; i < 8; i++) - { - result.u8[i] = source.u8[i] > destination.u8[i] ? source.u8[i] : destination.u8[i]; - } - - write_mmx_reg64(r, result); -} -DEFINE_SSE_SPLIT(instr_0FDE, safe_read64s, read_mmx64s) - -void instr_660FDE(union reg128 source, int32_t r) { - c_comment("pmaxub xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - union reg128 result; - - for(uint32_t i = 0; i < 16; i++) - { - result.u8[i] = source.u8[i] > destination.u8[i] ? source.u8[i] : destination.u8[i]; - } - - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660FDE, safe_read128s, read_xmm128s) - -void instr_0FDF(union reg64 source, int32_t r) { - c_comment("pandn mm, mm/m64"); - - union reg64 destination = read_mmx64s(r); - union reg64 result = { { 0 } }; - - result.u64[0] = source.u64[0] & ~destination.u64[0]; - - write_mmx_reg64(r, result); -} -DEFINE_SSE_SPLIT(instr_0FDF, safe_read64s, read_mmx64s) - -void instr_660FDF(union reg128 source, int32_t r) { - c_comment("pandn xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - pandn_r128(source, r); -} -DEFINE_SSE_SPLIT(instr_660FDF, safe_read128s, read_xmm128s) - -void instr_0FE0(union reg64 source, int32_t r) { - c_comment("pavgb mm, mm/m64"); - union reg64 destination = read_mmx64s(r); - union reg64 result = { { 0 } }; - - for(uint32_t i = 0; i < 8; i++) - { - result.u8[i] = (destination.u8[i] + source.u8[i] + 1) >> 1; - } - - write_mmx_reg64(r, result); -} -DEFINE_SSE_SPLIT(instr_0FE0, safe_read64s, read_mmx64s) - -void instr_660FE0(union reg128 source, int32_t r) { - c_comment("pavgb xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg128 destination = read_xmm128s(r); - union reg128 result; - - for(uint32_t i = 0; i < 16; i++) - { - result.u8[i] = (destination.u8[i] + source.u8[i] + 1) >> 1; - } - - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660FE0, safe_read128s, read_xmm128s) - -void instr_0FE1(union reg64 source, int32_t r) { - c_comment("psraw mm, mm/m64"); - psraw_r64(r, source.u32[0]); -} -DEFINE_SSE_SPLIT(instr_0FE1, safe_read64s, read_mmx64s) - -void instr_660FE1(union reg128 source, int32_t r) { - c_comment("psraw xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - psraw_r128(r, source.u32[0]); -} -DEFINE_SSE_SPLIT(instr_660FE1, safe_read128s, read_xmm128s) - -void instr_0FE2(union reg64 source, int32_t r) { - c_comment("psrad mm, mm/m64"); - psrad_r64(r, source.u32[0]); -} -DEFINE_SSE_SPLIT(instr_0FE2, safe_read64s, read_mmx64s) - -void instr_660FE2(union reg128 source, int32_t r) { - c_comment("psrad xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - psrad_r128(r, source.u32[0]); -} -DEFINE_SSE_SPLIT(instr_660FE2, safe_read128s, read_xmm128s) - -void instr_0FE3(union reg64 source, int32_t r) { - c_comment("pavgw mm, mm/m64"); - union reg64 destination = read_mmx64s(r); - - destination.u16[0] = (destination.u16[0] + source.u16[0] + 1) >> 1; - destination.u16[1] = (destination.u16[1] + source.u16[1] + 1) >> 1; - destination.u16[2] = (destination.u16[2] + source.u16[2] + 1) >> 1; - destination.u16[3] = (destination.u16[3] + source.u16[3] + 1) >> 1; - - write_mmx_reg64(r, destination); -} -DEFINE_SSE_SPLIT(instr_0FE3, safe_read64s, read_mmx64s) - -void instr_660FE3(union reg128 source, int32_t r) { - c_comment("pavgw xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg128 destination = read_xmm128s(r); - - destination.u16[0] = (destination.u16[0] + source.u16[0] + 1) >> 1; - destination.u16[1] = (destination.u16[1] + source.u16[1] + 1) >> 1; - destination.u16[2] = (destination.u16[2] + source.u16[2] + 1) >> 1; - destination.u16[3] = (destination.u16[3] + source.u16[3] + 1) >> 1; - destination.u16[4] = (destination.u16[4] + source.u16[4] + 1) >> 1; - destination.u16[5] = (destination.u16[5] + source.u16[5] + 1) >> 1; - destination.u16[6] = (destination.u16[6] + source.u16[6] + 1) >> 1; - destination.u16[7] = (destination.u16[7] + source.u16[7] + 1) >> 1; - - write_xmm_reg128(r, destination); -} -DEFINE_SSE_SPLIT(instr_660FE3, safe_read128s, read_xmm128s) - -void instr_0FE4(union reg64 source, int32_t r) { - c_comment("pmulhuw mm, mm/m64"); - - union reg64 destination = read_mmx64s(r); - - write_mmx64( - 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 - ); -} -DEFINE_SSE_SPLIT(instr_0FE4, safe_read64s, read_mmx64s) - -void instr_660FE4(union reg128 source, int32_t r) { - c_comment("pmulhuw xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - - 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) - -void instr_0FE5(union reg64 source, int32_t r) { - c_comment("pmulhw mm, mm/m64"); - - union reg64 destination = read_mmx64s(r); - - 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_mmx64(r, low, high); -} -DEFINE_SSE_SPLIT(instr_0FE5, safe_read64s, read_mmx64s) - -void instr_660FE5(union reg128 source, int32_t r) { - c_comment("pmulhw xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - - int32_t dword0 = ((destination.i16[0] * source.i16[0]) >> 16) & 0xFFFF | - ((destination.i16[1] * source.i16[1]) & 0xFFFF0000); - int32_t dword1 = ((destination.i16[2] * source.i16[2]) >> 16) & 0xFFFF | - ((destination.i16[3] * source.i16[3]) & 0xFFFF0000); - int32_t dword2 = ((destination.i16[4] * source.i16[4]) >> 16) & 0xFFFF | - ((destination.i16[5] * source.i16[5]) & 0xFFFF0000); - int32_t dword3 = ((destination.i16[6] * source.i16[6]) >> 16) & 0xFFFF | - ((destination.i16[7] * source.i16[7]) & 0xFFFF0000); - - write_xmm128(r, dword0, dword1, dword2, dword3); -} -DEFINE_SSE_SPLIT(instr_660FE5, safe_read128s, read_xmm128s) - -void instr_0FE6_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_0FE6_reg(int32_t r1, int32_t r2) { trigger_ud(); } -void instr_660FE6_mem(int32_t addr, int32_t r) { unimplemented_sse(); } -void instr_660FE6_reg(int32_t r1, int32_t r2) { unimplemented_sse(); } -void instr_F20FE6_mem(int32_t addr, int32_t r) { unimplemented_sse(); } -void instr_F20FE6_reg(int32_t r1, int32_t r2) { unimplemented_sse(); } -void instr_F30FE6_mem(int32_t addr, int32_t r) { unimplemented_sse(); } -void instr_F30FE6_reg(int32_t r1, int32_t r2) { unimplemented_sse(); } - -void instr_0FE7_mem(int32_t addr, int32_t r) { - c_comment("movntq m64, mm"); - mov_r_m64(addr, r); -} -void instr_0FE7_reg(int32_t r1, int32_t r2) { trigger_ud(); } - -void instr_660FE7_reg(int32_t r1, int32_t r2) { trigger_ud(); } -void instr_660FE7_mem(int32_t addr, int32_t r) { - c_comment("movntdq m128, xmm"); - mov_r_m128(addr, r); -} - -void instr_0FE8(union reg64 source, int32_t r) { - c_comment("psubsb mm, mm/m64"); - - union reg64 destination = read_mmx64s(r); - union reg64 result = { { 0 } }; - - for(uint32_t i = 0; i < 8; i++) - { - result.u8[i] = saturate_sd_to_sb(destination.i8[i] - source.i8[i]); - } - - write_mmx_reg64(r, result); -} -DEFINE_SSE_SPLIT(instr_0FE8, safe_read64s, read_mmx64s) - -void instr_660FE8(union reg128 source, int32_t r) { - c_comment("psubsb xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - union reg128 result; - - for(uint32_t i = 0; i < 16; i++) - { - result.i8[i] = saturate_sd_to_sb(destination.i8[i] - source.i8[i]); - } - - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660FE8, safe_read128s, read_xmm128s) - -void instr_0FE9(union reg64 source, int32_t r) { - c_comment("psubsw mm, mm/m64"); - - union reg64 destination = read_mmx64s(r); - - 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_mmx64(r, low, high); -} -DEFINE_SSE_SPLIT(instr_0FE9, safe_read64s, read_mmx64s) - -void instr_660FE9(union reg128 source, int32_t r) { - c_comment("psubsw xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - - int32_t dword0 = saturate_sd_to_sw(destination.i16[0] - source.i16[0]) | - saturate_sd_to_sw(destination.i16[1] - source.i16[1]) << 16; - int32_t dword1 = saturate_sd_to_sw(destination.i16[2] - source.i16[2]) | - saturate_sd_to_sw(destination.i16[3] - source.i16[3]) << 16; - int32_t dword2 = saturate_sd_to_sw(destination.i16[4] - source.i16[4]) | - saturate_sd_to_sw(destination.i16[5] - source.i16[5]) << 16; - int32_t dword3 = saturate_sd_to_sw(destination.i16[6] - source.i16[6]) | - saturate_sd_to_sw(destination.i16[7] - source.i16[7]) << 16; - - write_xmm128(r, dword0, dword1, dword2, dword3); -} -DEFINE_SSE_SPLIT(instr_660FE9, safe_read128s, read_xmm128s) - -void instr_0FEA(union reg64 source, int32_t r) { - c_comment("pminsw mm, mm/m64"); - - union reg64 destination = read_mmx64s(r); - union reg64 result; - - for(uint32_t i = 0; i < 4; i++) - { - result.i16[i] = destination.i16[i] < source.i16[i] ? destination.i16[i] : source.i16[i]; - } - - write_mmx_reg64(r, result); -} -DEFINE_SSE_SPLIT(instr_0FEA, safe_read64s, read_mmx64s) - -void instr_660FEA(union reg128 source, int32_t r) { - c_comment("pminsw xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - union reg128 result; - - for(uint32_t i = 0; i < 8; i++) - { - result.i16[i] = destination.i16[i] < source.i16[i] ? destination.i16[i] : source.i16[i]; - } - - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660FEA, safe_read128s, read_xmm128s) - -void instr_0FEB(union reg64 source, int32_t r) { - c_comment("por mm, mm/m64"); - - union reg64 destination = read_mmx64s(r); - union reg64 result = { { 0 } }; - - result.u64[0] = source.u64[0] | destination.u64[0]; - - write_mmx_reg64(r, result); -} -DEFINE_SSE_SPLIT(instr_0FEB, safe_read64s, read_mmx64s) - -void instr_660FEB(union reg128 source, int32_t r) { - c_comment("por xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - por_r128(source, r); -} -DEFINE_SSE_SPLIT(instr_660FEB, safe_read128s, read_xmm128s) - -void instr_0FEC(union reg64 source, int32_t r) { - c_comment("paddsb mm, mm/m64"); - - union reg64 destination = read_mmx64s(r); - union reg64 result = { { 0 } }; - - for(uint32_t i = 0; i < 8; i++) - { - result.u8[i] = saturate_sd_to_sb(destination.i8[i] + source.i8[i]); - } - - write_mmx_reg64(r, result); -} -DEFINE_SSE_SPLIT(instr_0FEC, safe_read64s, read_mmx64s) - -void instr_660FEC(union reg128 source, int32_t r) { - c_comment("paddsb xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - union reg128 result; - - for(uint32_t i = 0; i < 16; i++) - { - result.i8[i] = saturate_sd_to_sb(destination.i8[i] + source.i8[i]); - } - - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660FEC, safe_read128s, read_xmm128s) - -void instr_0FED(union reg64 source, int32_t r) { - c_comment("paddsw mm, mm/m64"); - - union reg64 destination = read_mmx64s(r); - - 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_mmx64(r, low, high); -} -DEFINE_SSE_SPLIT(instr_0FED, safe_read64s, read_mmx64s) - -void instr_660FED(union reg128 source, int32_t r) { - c_comment("paddsw xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - - int32_t dword0 = saturate_sd_to_sw(destination.i16[0] + source.i16[0]) | - saturate_sd_to_sw(destination.i16[1] + source.i16[1]) << 16; - int32_t dword1 = saturate_sd_to_sw(destination.i16[2] + source.i16[2]) | - saturate_sd_to_sw(destination.i16[3] + source.i16[3]) << 16; - int32_t dword2 = saturate_sd_to_sw(destination.i16[4] + source.i16[4]) | - saturate_sd_to_sw(destination.i16[5] + source.i16[5]) << 16; - int32_t dword3 = saturate_sd_to_sw(destination.i16[6] + source.i16[6]) | - saturate_sd_to_sw(destination.i16[7] + source.i16[7]) << 16; - - write_xmm128(r, dword0, dword1, dword2, dword3); -} -DEFINE_SSE_SPLIT(instr_660FED, safe_read128s, read_xmm128s) - -void instr_0FEE(union reg64 source, int32_t r) { - c_comment("pmaxsw mm, mm/m64"); - - union reg64 destination = read_mmx64s(r); - union reg64 result; - - for(uint32_t i = 0; i < 4; i++) - { - result.i16[i] = destination.i16[i] >= source.i16[i] ? destination.i16[i] : source.i16[i]; - } - - write_mmx_reg64(r, result); -} -DEFINE_SSE_SPLIT(instr_0FEE, safe_read64s, read_mmx64s) - -void instr_660FEE(union reg128 source, int32_t r) { - c_comment("pmaxsw xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - union reg128 result; - - for(uint32_t i = 0; i < 8; i++) - { - result.i16[i] = destination.i16[i] >= source.i16[i] ? destination.i16[i] : source.i16[i]; - } - - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660FEE, safe_read128s, read_xmm128s) - -void instr_0FEF(union reg64 source, int32_t r) { - c_comment("pxor mm, mm/m64"); - union reg64 destination = read_mmx64s(r); - union reg64 result = { { 0 } }; - - result.u64[0] = source.u64[0] ^ destination.u64[0]; - - write_mmx_reg64(r, result); -} -DEFINE_SSE_SPLIT(instr_0FEF, safe_read64s, read_mmx64s) - -void instr_660FEF(union reg128 source, int32_t r) { - c_comment("pxor xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - pxor_r128(source, r); -} -DEFINE_SSE_SPLIT(instr_660FEF, safe_read128s, read_xmm128s) - -void instr_0FF0() { unimplemented_sse(); } - -void instr_0FF1(union reg64 source, int32_t r) { - c_comment("psllw mm, mm/m64"); - psllw_r64(r, source.u32[0]); -} -DEFINE_SSE_SPLIT(instr_0FF1, safe_read64s, read_mmx64s) - -void instr_660FF1(union reg128 source, int32_t r) { - c_comment("psllw xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - psllw_r128(r, source.u32[0]); -} -DEFINE_SSE_SPLIT(instr_660FF1, safe_read128s, read_xmm128s) - -void instr_0FF2(union reg64 source, int32_t r) { - c_comment("pslld mm, mm/m64"); - pslld_r64(r, source.u32[0]); -} -DEFINE_SSE_SPLIT(instr_0FF2, safe_read64s, read_mmx64s) - -void instr_660FF2(union reg128 source, int32_t r) { - c_comment("pslld xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - pslld_r128(r, source.u32[0]); -} -DEFINE_SSE_SPLIT(instr_660FF2, safe_read128s, read_xmm128s) - -void instr_0FF3(union reg64 source, int32_t r) { - c_comment("psllq mm, mm/m64"); - psllq_r64(r, source.u32[0]); -} -DEFINE_SSE_SPLIT(instr_0FF3, safe_read64s, read_mmx64s) - -void instr_660FF3(union reg128 source, int32_t r) { - c_comment("psllq xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - psllq_r128(r, source.u32[0]); -} -DEFINE_SSE_SPLIT(instr_660FF3, safe_read128s, read_xmm128s) - -void instr_0FF4(union reg64 source, int32_t r) { - c_comment("pmuludq mm, mm/m64"); - union reg64 destination = read_mmx64s(r); - - destination.u64[0] = (uint64_t) source.u32[0] * (uint64_t) destination.u32[0]; - write_mmx_reg64(r, destination); -} -DEFINE_SSE_SPLIT(instr_0FF4, safe_read64s, read_mmx64s) - -void instr_660FF4(union reg128 source, int32_t r) { - c_comment("pmuludq xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg128 destination = read_xmm128s(r); - - destination.u64[0] = (uint64_t) source.u32[0] * (uint64_t) destination.u32[0]; - destination.u64[1] = (uint64_t) source.u32[2] * (uint64_t) destination.u32[2]; - write_xmm_reg128(r, destination); -} -DEFINE_SSE_SPLIT(instr_660FF4, safe_read128s, read_xmm128s) - -void instr_0FF5(union reg64 source, int32_t r) { - c_comment("pmaddwd mm, mm/m64"); - - union reg64 destination = read_mmx64s(r); - - 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_mmx64(r, low, high); -} -DEFINE_SSE_SPLIT(instr_0FF5, safe_read64s, read_mmx64s) - -void instr_660FF5(union reg128 source, int32_t r) { - c_comment("pmaddwd xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - - int32_t dword0 = (destination.i16[0] * source.i16[0]) + - (destination.i16[1] * source.i16[1]); - int32_t dword1 = (destination.i16[2] * source.i16[2]) + - (destination.i16[3] * source.i16[3]); - int32_t dword2 = (destination.i16[4] * source.i16[4]) + - (destination.i16[5] * source.i16[5]); - int32_t dword3 = (destination.i16[6] * source.i16[6]) + - (destination.i16[7] * source.i16[7]); - - write_xmm128(r, dword0, dword1, dword2, dword3); -} -DEFINE_SSE_SPLIT(instr_660FF5, safe_read128s, read_xmm128s) - -void instr_0FF6(union reg64 source, int32_t r) { - c_comment("psadbw mm, mm/m64"); - union reg64 destination = read_mmx64s(r); - uint32_t sum = 0; - - for(uint32_t i = 0; i < 8; i++) - { - sum += abs(destination.u8[i] - source.u8[i]); - } - - write_mmx64(r, sum, 0); -} -DEFINE_SSE_SPLIT(instr_0FF6, safe_read64s, read_mmx64s) - -void instr_660FF6(union reg128 source, int32_t r) { - c_comment("psadbw xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg128 destination = read_xmm128s(r); - uint32_t sum0 = 0; - uint32_t sum1 = 0; - - for(uint32_t i = 0; i < 8; i++) - { - sum0 += abs(destination.u8[i] - source.u8[i]); - sum1 += abs(destination.u8[i + 8] - source.u8[i + 8]); - } - - write_xmm128(r, sum0, 0, sum1, 0); -} -DEFINE_SSE_SPLIT(instr_660FF6, safe_read128s, read_xmm128s) - -void instr_0FF7_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_0FF7_reg(int32_t r1, int32_t r2) { - c_comment("maskmovq mm, mm"); - union reg64 source = read_mmx64s(r2); - union reg64 mask = read_mmx64s(r1); - int32_t addr = get_seg_prefix(DS) + get_reg_asize(EDI); - - writable_or_pagefault(addr, 8); - for(uint32_t i = 0; i < 8; i++) - { - if(mask.u8[i] & 0x80) - { - safe_write8(addr + i, source.u8[i]); - } - } -} - -void instr_660FF7_mem(int32_t addr, int32_t r) { trigger_ud(); } -void instr_660FF7_reg(int32_t r1, int32_t r2) { - c_comment("maskmovdqu xmm, xmm"); - union reg128 source = read_xmm128s(r2); - union reg128 mask = read_xmm128s(r1); - int32_t addr = get_seg_prefix(DS) + get_reg_asize(EDI); - - writable_or_pagefault(addr, 16); - for(uint32_t i = 0; i < 16; i++) - { - if(mask.u8[i] & 0x80) - { - safe_write8(addr + i, source.u8[i]); - } - } -} - -void instr_0FF8(union reg64 source, int32_t r) { - c_comment("psubb mm, mm/m64"); - - union reg64 destination = read_mmx64s(r); - union reg64 result = { { 0 } }; - - for(uint32_t i = 0; i < 8; i++) - { - result.u8[i] = (destination.i8[i] - source.i8[i]) & 0xFF; - } - - write_mmx_reg64(r, result); -} -DEFINE_SSE_SPLIT(instr_0FF8, safe_read64s, read_mmx64s) - -void instr_660FF8(union reg128 source, int32_t r) { - c_comment("psubb xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - union reg128 result = { { 0 } }; - - for(uint32_t i = 0; i < 16; i++) - { - result.i8[i] = (destination.i8[i] - source.i8[i]) & 0xFF; - } - - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660FF8, safe_read128s, read_xmm128s) - -void instr_0FF9(union reg64 source, int32_t r) { - c_comment("psubw mm, mm/m64"); - - union reg64 destination = read_mmx64s(r); - - int32_t word0 = (destination.u32[0] - source.u32[0]) & 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.u16[3]) - source.u16[3]) & 0xFFFF; - int32_t high = word2 | word3 << 16; - - write_mmx64(r, low, high); -} -DEFINE_SSE_SPLIT(instr_0FF9, safe_read64s, read_mmx64s) - -void instr_660FF9(union reg128 source, int32_t r) { - c_comment("psubw xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - union reg128 result = { { 0 } }; - - for(uint32_t i = 0; i < 8; i++) - { - result.i16[i] = (destination.i16[i] - source.i16[i]) & 0xFFFF; - } - - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660FF9, safe_read128s, read_xmm128s) - -void instr_0FFA(union reg64 source, int32_t r) { - c_comment("psubd mm, mm/m64"); - - union reg64 destination = read_mmx64s(r); - - write_mmx64( - r, - destination.u32[0] - source.u32[0], - destination.u32[1] - source.u32[1] - ); -} -DEFINE_SSE_SPLIT(instr_0FFA, safe_read64s, read_mmx64s) - -void instr_660FFA(union reg128 source, int32_t r) { - c_comment("psubd xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - - 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) - -void instr_0FFB(union reg64 source, int32_t r) { - c_comment("psubq mm, mm/m64"); - union reg64 destination = read_mmx64s(r); - - destination.u64[0] = destination.u64[0] - source.u64[0]; - write_mmx_reg64(r, destination); -} -DEFINE_SSE_SPLIT(instr_0FFB, safe_read64s, read_mmx64s) - -void instr_660FFB(union reg128 source, int32_t r) { - c_comment("psubq xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - union reg128 destination = read_xmm128s(r); - - destination.u64[0] = destination.u64[0] - source.u64[0]; - destination.u64[1] = destination.u64[1] - source.u64[1]; - - write_xmm_reg128(r, destination); -} -DEFINE_SSE_SPLIT(instr_660FFB, safe_read128s, read_xmm128s) - -void instr_0FFC(union reg64 source, int32_t r) { - c_comment("paddb mm, mm/m64"); - - union reg64 destination = read_mmx64s(r); - union reg64 result = { { 0 } }; - - for(uint32_t i = 0; i < 8; i++) - { - result.u8[i] = (destination.u8[i] + source.u8[i]) & 0xFF; - } - - write_mmx_reg64(r, result); -} -DEFINE_SSE_SPLIT(instr_0FFC, safe_read64s, read_mmx64s) - -void instr_660FFC(union reg128 source, int32_t r) { - c_comment("paddb xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - union reg128 result = { { 0 } }; - - for(uint32_t i = 0; i < 16; i++) - { - result.u8[i] = (destination.u8[i] + source.u8[i]) & 0xFF; - } - - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660FFC, safe_read128s, read_xmm128s) - -void instr_0FFD(union reg64 source, int32_t r) { - c_comment("paddw mm, mm/m64"); - - union reg64 destination = read_mmx64s(r); - - int32_t word0 = (destination.u32[0] + source.u32[0]) & 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.u16[3] + source.u16[3]) & 0xFFFF; - int32_t high = word2 | word3 << 16; - - write_mmx64(r, low, high); -} -DEFINE_SSE_SPLIT(instr_0FFD, safe_read64s, read_mmx64s) - -void instr_660FFD(union reg128 source, int32_t r) { - c_comment("paddw xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - union reg128 result = { { 0 } }; - - for(uint32_t i = 0; i < 8; i++) - { - result.u16[i] = (destination.u16[i] + source.u16[i]) & 0xFFFF; - } - - write_xmm_reg128(r, result); -} -DEFINE_SSE_SPLIT(instr_660FFD, safe_read128s, read_xmm128s) - -void instr_0FFE(union reg64 source, int32_t r) { - c_comment("paddd mm, mm/m64"); - - 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_mmx64(r, low, high); -} -DEFINE_SSE_SPLIT(instr_0FFE, safe_read64s, read_mmx64s) - -void instr_660FFE(union reg128 source, int32_t r) { - c_comment("paddd xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - - int32_t dword0 = destination.u32[0] + source.u32[0]; - int32_t dword1 = destination.u32[1] + source.u32[1]; - int32_t dword2 = destination.u32[2] + source.u32[2]; - int32_t dword3 = destination.u32[3] + source.u32[3]; - - write_xmm128(r, dword0, dword1, dword2, dword3); -} -DEFINE_SSE_SPLIT(instr_660FFE, safe_read128s, read_xmm128s) - -void instr_0FFF() { - c_comment("Windows 98"); - dbg_log("#ud: 0F FF"); - trigger_ud(); -} - -//void run_instruction0f_16(int32_t opcode) -//{ -//#include "../../build/interpreter0f_16.c" -//} - -//void run_instruction0f_32(int32_t opcode) -//{ -//#include "../../build/interpreter0f_32.c" -//} - -#pragma clang diagnostic pop diff --git a/src/native/instructions_0f.h b/src/native/instructions_0f.h deleted file mode 100644 index 0b2f4340..00000000 --- a/src/native/instructions_0f.h +++ /dev/null @@ -1,983 +0,0 @@ -#pragma once - -#include - -#include "shared.h" -#include "cpu.h" -#include "instructions.h" - -#define DEFINE_MODRM_INSTR_READ16(name, fun) \ - void name ## _mem(int32_t addr, int32_t r) { int32_t ___ = safe_read16(addr); fun; } \ - void name ## _reg(int32_t r1, int32_t r) { int32_t ___ = read_reg16(r1); fun; } - -#define DEFINE_MODRM_INSTR_READ32(name, fun) \ - void name ## _mem(int32_t addr, int32_t r) { int32_t ___ = safe_read32s(addr); fun; } \ - void name ## _reg(int32_t r1, int32_t r) { int32_t ___ = read_reg32(r1); fun; } - - -#define DEFINE_MODRM_INSTR_IMM_READ_WRITE_16(name, fun) \ - void name ## _mem(int32_t addr, int32_t r, int32_t imm) { SAFE_READ_WRITE16(addr, fun); } \ - 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) \ - void name ## _mem(int32_t addr, int32_t r, int32_t imm) { SAFE_READ_WRITE32(addr, fun); } \ - 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) \ - void name ## _mem(int32_t addr, int32_t r) { SAFE_READ_WRITE8(addr, fun); } \ - 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) \ - void name ## _mem(int32_t addr, int32_t r) { SAFE_READ_WRITE16(addr, fun); } \ - 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) \ - void name ## _mem(int32_t addr, int32_t r) { SAFE_READ_WRITE32(addr, fun); } \ - 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) \ - void name ## _reg(int32_t r1, int32_t r2) { name(reg_fn(r1), r2); } \ - void name ## _mem(int32_t addr, int32_t r) { name(mem_fn(addr), r); } \ - -#define DEFINE_SSE_SPLIT_IMM(name, mem_fn, reg_fn) \ - void name ## _reg(int32_t r1, int32_t r2, int32_t imm) { name(reg_fn(r1), r2, imm); } \ - 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) \ - void name ## _reg(int32_t r1, int32_t r2) { reg_fn(r1, name(r2)); } \ - void name ## _mem(int32_t addr, int32_t r) { mem_fn(addr, name(r)); } \ - -void instr_0F00_0_mem(int32_t addr); -void instr_0F00_0_reg(int32_t r); -void instr_0F00_1_mem(int32_t addr); -void instr_0F00_1_reg(int32_t r); -void instr_0F00_2_mem(int32_t addr); -void instr_0F00_2_reg(int32_t r); -void instr_0F00_3_mem(int32_t addr); -void instr_0F00_3_reg(int32_t r); -void instr_0F00_4_mem(int32_t addr); -void instr_0F00_4_reg(int32_t r); -void instr_0F00_5_mem(int32_t addr); -void instr_0F00_5_reg(int32_t r); -void instr_0F01_0_reg(int32_t r); -void instr_0F01_0_mem(int32_t addr); -void instr_0F01_1_reg(int32_t r); -void instr_0F01_1_mem(int32_t addr); -void instr_0F01_2_reg(int32_t r); -void instr_0F01_2_mem(int32_t addr); -void instr_0F01_3_reg(int32_t r); -void instr_0F01_3_mem(int32_t addr); -void instr_0F01_4_reg(int32_t r); -void instr_0F01_4_mem(int32_t addr); -void lmsw(int32_t new_cr0); -void instr_0F01_6_reg(int32_t r); -void instr_0F01_6_mem(int32_t addr); -void instr_0F01_7_reg(int32_t r); -void instr_0F01_7_mem(int32_t addr); -void instr16_0F02_mem(int32_t addr, int32_t r); -void instr16_0F02_reg(int32_t r1, int32_t r); -void instr32_0F02_mem(int32_t addr, int32_t r); -void instr32_0F02_reg(int32_t r1, int32_t r); -void instr16_0F03_mem(int32_t addr, int32_t r); -void instr16_0F03_reg(int32_t r1, int32_t r); -void instr32_0F03_mem(int32_t addr, int32_t r); -void instr32_0F03_reg(int32_t r1, int32_t r); -void instr_0F04(void); -void instr_0F05(void); -void instr_0F06(void); -void instr_0F07(void); -void instr_0F08(void); -void instr_0F09(void); -void instr_0F0A(void); -void instr_0F0B(void); -void instr_0F0C(void); -void instr_0F0D(void); -void instr_0F0E(void); -void instr_0F0F(void); -void instr_0F10(union reg128 source, int32_t r); -void instr_0F10_reg(int32_t r1, int32_t r2); -void instr_0F10_mem(int32_t addr, int32_t r); -void instr_F30F10_reg(int32_t r1, int32_t r2); -void instr_F30F10_mem(int32_t addr, int32_t r); -void instr_660F10(union reg128 source, int32_t r); -void instr_660F10_reg(int32_t r1, int32_t r2); -void instr_660F10_mem(int32_t addr, int32_t r); -void instr_F20F10_reg(int32_t r1, int32_t r2); -void instr_F20F10_mem(int32_t addr, int32_t r); -void instr_0F11_reg(int32_t r1, int32_t r2); -void instr_0F11_mem(int32_t addr, int32_t r); -void instr_F30F11_reg(int32_t rm_dest, int32_t reg_src); -void instr_F30F11_mem(int32_t addr, int32_t r); -void instr_660F11_reg(int32_t r1, int32_t r2); -void instr_660F11_mem(int32_t addr, int32_t r); -void instr_F20F11_reg(int32_t r1, int32_t r2); -void instr_F20F11_mem(int32_t addr, int32_t r); -void instr_0F12_mem(int32_t addr, int32_t r); -void instr_0F12_reg(int32_t r1, int32_t r2); -void instr_660F12_reg(int32_t r1, int32_t r); -void instr_660F12_mem(int32_t addr, int32_t r); -void instr_F20F12_mem(int32_t addr, int32_t r); -void instr_F20F12_reg(int32_t r1, int32_t r2); -void instr_F30F12_mem(int32_t addr, int32_t r); -void instr_F30F12_reg(int32_t r1, int32_t r2); -void instr_0F13_mem(int32_t addr, int32_t r); -void instr_0F13_reg(int32_t r1, int32_t r2); -void instr_660F13_reg(int32_t r1, int32_t r); -void instr_660F13_mem(int32_t addr, int32_t r); -void instr_0F14(union reg64 source, int32_t r); -void instr_0F14_reg(int32_t r1, int32_t r2); -void instr_0F14_mem(int32_t addr, int32_t r); -void instr_660F14(union reg64 source, int32_t r); -void instr_660F14_reg(int32_t r1, int32_t r2); -void instr_660F14_mem(int32_t addr, int32_t r); -void instr_0F15(union reg128 source, int32_t r); -void instr_0F15_reg(int32_t r1, int32_t r2); -void instr_0F15_mem(int32_t addr, int32_t r); -void instr_660F15(union reg128 source, int32_t r); -void instr_660F15_reg(int32_t r1, int32_t r2); -void instr_660F15_mem(int32_t addr, int32_t r); -void instr_0F16_mem(int32_t addr, int32_t r); -void instr_0F16_reg(int32_t r1, int32_t r2); -void instr_660F16_mem(int32_t addr, int32_t r); -void instr_660F16_reg(int32_t r1, int32_t r2); -void instr_0F17_mem(int32_t addr, int32_t r); -void instr_0F17_reg(int32_t r1, int32_t r2); -void instr_660F17_mem(int32_t addr, int32_t r); -void instr_660F17_reg(int32_t r1, int32_t r2); -void instr_0F18_reg(int32_t r1, int32_t r2); -void instr_0F18_mem(int32_t addr, int32_t r); -void instr_0F19(void); -void instr_0F1A(void); -void instr_0F1B(void); -void instr_0F1C(void); -void instr_0F1D(void); -void instr_0F1E(void); -void instr_0F1F_reg(int32_t r1, int32_t r2); -void instr_0F1F_mem(int32_t addr, int32_t r); -void instr_0F20(int32_t r, int32_t creg); -void instr_0F21(int32_t r, int32_t dreg_index); -void instr_0F22(int32_t r, int32_t creg); -void instr_0F23(int32_t r, int32_t dreg_index); -void instr_0F24(void); -void instr_0F25(void); -void instr_0F26(void); -void instr_0F27(void); -void instr_0F28(union reg128 source, int32_t r); -void instr_0F28_reg(int32_t r1, int32_t r2); -void instr_0F28_mem(int32_t addr, int32_t r); -void instr_660F28(union reg128 source, int32_t r); -void instr_660F28_reg(int32_t r1, int32_t r2); -void instr_660F28_mem(int32_t addr, int32_t r); -void instr_0F29_mem(int32_t addr, int32_t r); -void instr_0F29_reg(int32_t r1, int32_t r2); -void instr_660F29_mem(int32_t addr, int32_t r); -void instr_660F29_reg(int32_t r1, int32_t r2); -void instr_0F2B_reg(int32_t r1, int32_t r2); -void instr_0F2B_mem(int32_t addr, int32_t r); -void instr_660F2B_reg(int32_t r1, int32_t r2); -void instr_660F2B_mem(int32_t addr, int32_t r); -void instr_0F2C_mem(int32_t addr, int32_t r); -void instr_0F2C_reg(int32_t r1, int32_t r2); -void instr_660F2C_mem(int32_t addr, int32_t r); -void instr_660F2C_reg(int32_t r1, int32_t r2); -void instr_F20F2C(union reg64 source, int32_t r); -void instr_F20F2C_reg(int32_t r1, int32_t r2); -void instr_F20F2C_mem(int32_t addr, int32_t r); -void instr_F30F2C_mem(int32_t addr, int32_t r); -void instr_F30F2C_reg(int32_t r1, int32_t r2); -void instr_0F2E(void); -void instr_0F2F(void); -void instr_0F30(void); -void instr_0F31(void); -void instr_0F32(void); -void instr_0F33(void); -void instr_0F34(void); -void instr_0F35(void); -void instr_0F36(void); -void instr_0F37(void); -void instr_0F38(void); -void instr_0F39(void); -void instr_0F3A(void); -void instr_0F3B(void); -void instr_0F3C(void); -void instr_0F3D(void); -void instr_0F3E(void); -void instr_0F3F(void); -void instr16_0F40_mem(int32_t addr, int32_t r); -void instr16_0F40_reg(int32_t r1, int32_t r); -void instr32_0F40_mem(int32_t addr, int32_t r); -void instr32_0F40_reg(int32_t r1, int32_t r); -void instr16_0F41_mem(int32_t addr, int32_t r); -void instr16_0F41_reg(int32_t r1, int32_t r); -void instr32_0F41_mem(int32_t addr, int32_t r); -void instr32_0F41_reg(int32_t r1, int32_t r); -void instr16_0F42_mem(int32_t addr, int32_t r); -void instr16_0F42_reg(int32_t r1, int32_t r); -void instr32_0F42_mem(int32_t addr, int32_t r); -void instr32_0F42_reg(int32_t r1, int32_t r); -void instr16_0F43_mem(int32_t addr, int32_t r); -void instr16_0F43_reg(int32_t r1, int32_t r); -void instr32_0F43_mem(int32_t addr, int32_t r); -void instr32_0F43_reg(int32_t r1, int32_t r); -void instr16_0F44_mem(int32_t addr, int32_t r); -void instr16_0F44_reg(int32_t r1, int32_t r); -void instr32_0F44_mem(int32_t addr, int32_t r); -void instr32_0F44_reg(int32_t r1, int32_t r); -void instr16_0F45_mem(int32_t addr, int32_t r); -void instr16_0F45_reg(int32_t r1, int32_t r); -void instr32_0F45_mem(int32_t addr, int32_t r); -void instr32_0F45_reg(int32_t r1, int32_t r); -void instr16_0F46_mem(int32_t addr, int32_t r); -void instr16_0F46_reg(int32_t r1, int32_t r); -void instr32_0F46_mem(int32_t addr, int32_t r); -void instr32_0F46_reg(int32_t r1, int32_t r); -void instr16_0F47_mem(int32_t addr, int32_t r); -void instr16_0F47_reg(int32_t r1, int32_t r); -void instr32_0F47_mem(int32_t addr, int32_t r); -void instr32_0F47_reg(int32_t r1, int32_t r); -void instr16_0F48_mem(int32_t addr, int32_t r); -void instr16_0F48_reg(int32_t r1, int32_t r); -void instr32_0F48_mem(int32_t addr, int32_t r); -void instr32_0F48_reg(int32_t r1, int32_t r); -void instr16_0F49_mem(int32_t addr, int32_t r); -void instr16_0F49_reg(int32_t r1, int32_t r); -void instr32_0F49_mem(int32_t addr, int32_t r); -void instr32_0F49_reg(int32_t r1, int32_t r); -void instr16_0F4A_mem(int32_t addr, int32_t r); -void instr16_0F4A_reg(int32_t r1, int32_t r); -void instr32_0F4A_mem(int32_t addr, int32_t r); -void instr32_0F4A_reg(int32_t r1, int32_t r); -void instr16_0F4B_mem(int32_t addr, int32_t r); -void instr16_0F4B_reg(int32_t r1, int32_t r); -void instr32_0F4B_mem(int32_t addr, int32_t r); -void instr32_0F4B_reg(int32_t r1, int32_t r); -void instr16_0F4C_mem(int32_t addr, int32_t r); -void instr16_0F4C_reg(int32_t r1, int32_t r); -void instr32_0F4C_mem(int32_t addr, int32_t r); -void instr32_0F4C_reg(int32_t r1, int32_t r); -void instr16_0F4D_mem(int32_t addr, int32_t r); -void instr16_0F4D_reg(int32_t r1, int32_t r); -void instr32_0F4D_mem(int32_t addr, int32_t r); -void instr32_0F4D_reg(int32_t r1, int32_t r); -void instr16_0F4E_mem(int32_t addr, int32_t r); -void instr16_0F4E_reg(int32_t r1, int32_t r); -void instr32_0F4E_mem(int32_t addr, int32_t r); -void instr32_0F4E_reg(int32_t r1, int32_t r); -void instr16_0F4F_mem(int32_t addr, int32_t r); -void instr16_0F4F_reg(int32_t r1, int32_t r); -void instr32_0F4F_mem(int32_t addr, int32_t r); -void instr32_0F4F_reg(int32_t r1, int32_t r); -void instr_0F50_reg(int32_t r1, int32_t r2); -void instr_0F50_mem(int32_t addr, int32_t r1); -void instr_660F50_reg(int32_t r1, int32_t r2); -void instr_660F50_mem(int32_t addr, int32_t r1); -void instr_0F54(union reg128 source, int32_t r); -void instr_0F54_reg(int32_t r1, int32_t r2); -void instr_0F54_mem(int32_t addr, int32_t r); -void instr_660F54(union reg128 source, int32_t r); -void instr_660F54_reg(int32_t r1, int32_t r2); -void instr_660F54_mem(int32_t addr, int32_t r); -void instr_0F55(union reg128 source, int32_t r); -void instr_0F55_reg(int32_t r1, int32_t r2); -void instr_0F55_mem(int32_t addr, int32_t r); -void instr_660F55(union reg128 source, int32_t r); -void instr_660F55_reg(int32_t r1, int32_t r2); -void instr_660F55_mem(int32_t addr, int32_t r); -void instr_0F56(union reg128 source, int32_t r); -void instr_0F56_reg(int32_t r1, int32_t r2); -void instr_0F56_mem(int32_t addr, int32_t r); -void instr_660F56(union reg128 source, int32_t r); -void instr_660F56_reg(int32_t r1, int32_t r2); -void instr_660F56_mem(int32_t addr, int32_t r); -void instr_0F57(union reg128 source, int32_t r); -void instr_0F57_reg(int32_t r1, int32_t r2); -void instr_0F57_mem(int32_t addr, int32_t r); -void instr_660F57(union reg128 source, int32_t r); -void instr_660F57_reg(int32_t r1, int32_t r2); -void instr_660F57_mem(int32_t addr, int32_t r); - -void instr_0F60(int32_t source, int32_t r); -void instr_0F60_reg(int32_t r1, int32_t r2); -void instr_0F60_mem(int32_t addr, int32_t r); -void instr_660F60(union reg64 source, int32_t r); -void instr_660F60_reg(int32_t r1, int32_t r2); -void instr_660F60_mem(int32_t addr, int32_t r); -void instr_0F61(int32_t source, int32_t r); -void instr_0F61_reg(int32_t r1, int32_t r2); -void instr_0F61_mem(int32_t addr, int32_t r); -void instr_660F61(union reg64 source, int32_t r); -void instr_660F61_reg(int32_t r1, int32_t r2); -void instr_660F61_mem(int32_t addr, int32_t r); -void instr_0F62(int32_t source, int32_t r); -void instr_0F62_reg(int32_t r1, int32_t r2); -void instr_0F62_mem(int32_t addr, int32_t r); -void instr_660F62(union reg128 source, int32_t r); -void instr_660F62_reg(int32_t r1, int32_t r2); -void instr_660F62_mem(int32_t addr, int32_t r); -void instr_0F63(union reg64 source, int32_t r); -void instr_0F63_reg(int32_t r1, int32_t r2); -void instr_0F63_mem(int32_t addr, int32_t r); -void instr_660F63(union reg128 source, int32_t r); -void instr_660F63_reg(int32_t r1, int32_t r2); -void instr_660F63_mem(int32_t addr, int32_t r); -void instr_0F64(union reg64 source, int32_t r); -void instr_0F64_reg(int32_t r1, int32_t r2); -void instr_0F64_mem(int32_t addr, int32_t r); -void instr_660F64(union reg128 source, int32_t r); -void instr_660F64_reg(int32_t r1, int32_t r2); -void instr_660F64_mem(int32_t addr, int32_t r); -void instr_0F65(union reg64 source, int32_t r); -void instr_0F65_reg(int32_t r1, int32_t r2); -void instr_0F65_mem(int32_t addr, int32_t r); -void instr_660F65(union reg128 source, int32_t r); -void instr_660F65_reg(int32_t r1, int32_t r2); -void instr_660F65_mem(int32_t addr, int32_t r); -void instr_0F66(union reg64 source, int32_t r); -void instr_0F66_reg(int32_t r1, int32_t r2); -void instr_0F66_mem(int32_t addr, int32_t r); -void instr_660F66(union reg128 source, int32_t r); -void instr_660F66_reg(int32_t r1, int32_t r2); -void instr_660F66_mem(int32_t addr, int32_t r); -void instr_0F67(union reg64 source, int32_t r); -void instr_0F67_reg(int32_t r1, int32_t r2); -void instr_0F67_mem(int32_t addr, int32_t r); -void instr_660F67(union reg128 source, int32_t r); -void instr_660F67_reg(int32_t r1, int32_t r2); -void instr_660F67_mem(int32_t addr, int32_t r); -void instr_0F68(union reg64 source, int32_t r); -void instr_0F68_reg(int32_t r1, int32_t r2); -void instr_0F68_mem(int32_t addr, int32_t r); -void instr_660F68(union reg128 source, int32_t r); -void instr_660F68_reg(int32_t r1, int32_t r2); -void instr_660F68_mem(int32_t addr, int32_t r); -void instr_0F69(union reg64 source, int32_t r); -void instr_0F69_reg(int32_t r1, int32_t r2); -void instr_0F69_mem(int32_t addr, int32_t r); -void instr_660F69(union reg128 source, int32_t r); -void instr_660F69_reg(int32_t r1, int32_t r2); -void instr_660F69_mem(int32_t addr, int32_t r); -void instr_0F6A(union reg64 source, int32_t r); -void instr_0F6A_reg(int32_t r1, int32_t r2); -void instr_0F6A_mem(int32_t addr, int32_t r); -void instr_660F6A(union reg128 source, int32_t r); -void instr_660F6A_reg(int32_t r1, int32_t r2); -void instr_660F6A_mem(int32_t addr, int32_t r); -void instr_0F6B(union reg64 source, int32_t r); -void instr_0F6B_reg(int32_t r1, int32_t r2); -void instr_0F6B_mem(int32_t addr, int32_t r); -void instr_660F6B(union reg128 source, int32_t r); -void instr_660F6B_reg(int32_t r1, int32_t r2); -void instr_660F6B_mem(int32_t addr, int32_t r); -void instr_0F6C_mem(int32_t addr, int32_t r); -void instr_0F6C_reg(int32_t r1, int32_t r2); -void instr_660F6C(union reg128 source, int32_t r); -void instr_660F6C_reg(int32_t r1, int32_t r2); -void instr_660F6C_mem(int32_t addr, int32_t r); -void instr_0F6D_mem(int32_t addr, int32_t r); -void instr_0F6D_reg(int32_t r1, int32_t r2); -void instr_660F6D(union reg128 source, int32_t r); -void instr_660F6D_reg(int32_t r1, int32_t r2); -void instr_660F6D_mem(int32_t addr, int32_t r); -void instr_0F6E(int32_t source, int32_t r); -void instr_0F6E_reg(int32_t r1, int32_t r2); -void instr_0F6E_mem(int32_t addr, int32_t r); -void instr_660F6E(int32_t source, int32_t r); -void instr_660F6E_reg(int32_t r1, int32_t r2); -void instr_660F6E_mem(int32_t addr, int32_t r); -void instr_0F6F(union reg64 source, int32_t r); -void instr_0F6F_reg(int32_t r1, int32_t r2); -void instr_0F6F_mem(int32_t addr, int32_t r); -void instr_660F6F(union reg128 source, int32_t r); -void instr_660F6F_reg(int32_t r1, int32_t r2); -void instr_660F6F_mem(int32_t addr, int32_t r); -void instr_F30F6F(union reg128 source, int32_t r); -void instr_F30F6F_reg(int32_t r1, int32_t r2); -void instr_F30F6F_mem(int32_t addr, int32_t r); -void instr_0F70(union reg64 source, int32_t r, int32_t imm8); -void instr_0F70_reg(int32_t r1, int32_t r2, int32_t imm); -void instr_0F70_mem(int32_t addr, int32_t r, int32_t imm); -void instr_660F70(union reg128 source, int32_t r, int32_t imm8); -void instr_660F70_reg(int32_t r1, int32_t r2, int32_t imm); -void instr_660F70_mem(int32_t addr, int32_t r, int32_t imm); -void instr_F20F70(union reg128 source, int32_t r, int32_t imm8); -void instr_F20F70_reg(int32_t r1, int32_t r2, int32_t imm); -void instr_F20F70_mem(int32_t addr, int32_t r, int32_t imm); -void instr_F30F70(union reg128 source, int32_t r, int32_t imm8); -void instr_F30F70_reg(int32_t r1, int32_t r2, int32_t imm); -void instr_F30F70_mem(int32_t addr, int32_t r, int32_t imm); -void instr_0F71_2_mem(int32_t addr, int32_t r); -void instr_0F71_4_mem(int32_t addr, int32_t r); -void instr_0F71_6_mem(int32_t addr, int32_t r); -void instr_0F71_2_reg(int32_t r, int32_t imm8); -void instr_0F71_4_reg(int32_t r, int32_t imm8); -void instr_0F71_6_reg(int32_t r, int32_t imm8); -void instr_660F71_2_mem(int32_t addr, int32_t r); -void instr_660F71_4_mem(int32_t addr, int32_t r); -void instr_660F71_6_mem(int32_t addr, int32_t r); -void instr_660F71_2_reg(int32_t r, int32_t imm8); -void instr_660F71_4_reg(int32_t r, int32_t imm8); -void instr_660F71_6_reg(int32_t r, int32_t imm8); -void instr_0F72_2_mem(int32_t addr, int32_t r); -void instr_0F72_4_mem(int32_t addr, int32_t r); -void instr_0F72_6_mem(int32_t addr, int32_t r); -void instr_0F72_2_reg(int32_t r, int32_t imm8); -void instr_0F72_4_reg(int32_t r, int32_t imm8); -void instr_0F72_6_reg(int32_t r, int32_t imm8); -void instr_660F72_2_mem(int32_t addr, int32_t r); -void instr_660F72_4_mem(int32_t addr, int32_t r); -void instr_660F72_6_mem(int32_t addr, int32_t r); -void instr_660F72_2_reg(int32_t r, int32_t imm8); -void instr_660F72_4_reg(int32_t r, int32_t imm8); -void instr_660F72_6_reg(int32_t r, int32_t imm8); -void instr_0F73_2_mem(int32_t addr, int32_t r); -void instr_0F73_6_mem(int32_t addr, int32_t r); -void instr_0F73_2_reg(int32_t r, int32_t imm8); -void instr_0F73_6_reg(int32_t r, int32_t imm8); -void instr_660F73_2_mem(int32_t addr, int32_t r); -void instr_660F73_3_mem(int32_t addr, int32_t r); -void instr_660F73_6_mem(int32_t addr, int32_t r); -void instr_660F73_7_mem(int32_t addr, int32_t r); -void instr_660F73_2_reg(int32_t r, int32_t imm8); -void instr_660F73_3_reg(int32_t r, int32_t imm8); -void instr_660F73_6_reg(int32_t r, int32_t imm8); -void instr_660F73_7_reg(int32_t r, int32_t imm8); -void instr_0F74(union reg64 source, int32_t r); -void instr_0F74_reg(int32_t r1, int32_t r2); -void instr_0F74_mem(int32_t addr, int32_t r); -void instr_660F74(union reg128 source, int32_t r); -void instr_660F74_reg(int32_t r1, int32_t r2); -void instr_660F74_mem(int32_t addr, int32_t r); -void instr_0F75(union reg64 source, int32_t r); -void instr_0F75_reg(int32_t r1, int32_t r2); -void instr_0F75_mem(int32_t addr, int32_t r); -void instr_660F75(union reg128 source, int32_t r); -void instr_660F75_reg(int32_t r1, int32_t r2); -void instr_660F75_mem(int32_t addr, int32_t r); -void instr_0F76(union reg64 source, int32_t r); -void instr_0F76_reg(int32_t r1, int32_t r2); -void instr_0F76_mem(int32_t addr, int32_t r); -void instr_660F76(union reg128 source, int32_t r); -void instr_660F76_reg(int32_t r1, int32_t r2); -void instr_660F76_mem(int32_t addr, int32_t r); -void instr_0F77(void); -void instr_0F78(void); -void instr_0F79(void); -void instr_0F7A(void); -void instr_0F7B(void); -void instr_0F7C(void); -void instr_0F7D(void); -int32_t instr_0F7E(int32_t r); -void instr_0F7E_reg(int32_t r1, int32_t r2); -void instr_0F7E_mem(int32_t addr, int32_t r); -int32_t instr_660F7E(int32_t r); -void instr_660F7E_reg(int32_t r1, int32_t r2); -void instr_660F7E_mem(int32_t addr, int32_t r); -void instr_F30F7E_mem(int32_t addr, int32_t r); -void instr_F30F7E_reg(int32_t r1, int32_t r2); -void instr_0F7F_mem(int32_t addr, int32_t r); -void instr_0F7F_reg(int32_t r1, int32_t r2); -void instr_660F7F_mem(int32_t addr, int32_t r); -void instr_660F7F_reg(int32_t r1, int32_t r2); -void instr_F30F7F_mem(int32_t addr, int32_t r); -void instr_F30F7F_reg(int32_t r1, int32_t r2); -void instr16_0F80(int32_t imm); -void instr32_0F80(int32_t imm); -void instr16_0F81(int32_t imm); -void instr32_0F81(int32_t imm); -void instr16_0F82(int32_t imm); -void instr32_0F82(int32_t imm); -void instr16_0F83(int32_t imm); -void instr32_0F83(int32_t imm); -void instr16_0F84(int32_t imm); -void instr32_0F84(int32_t imm); -void instr16_0F85(int32_t imm); -void instr32_0F85(int32_t imm); -void instr16_0F86(int32_t imm); -void instr32_0F86(int32_t imm); -void instr16_0F87(int32_t imm); -void instr32_0F87(int32_t imm); -void instr16_0F88(int32_t imm); -void instr32_0F88(int32_t imm); -void instr16_0F89(int32_t imm); -void instr32_0F89(int32_t imm); -void instr16_0F8A(int32_t imm); -void instr32_0F8A(int32_t imm); -void instr16_0F8B(int32_t imm); -void instr32_0F8B(int32_t imm); -void instr16_0F8C(int32_t imm); -void instr32_0F8C(int32_t imm); -void instr16_0F8D(int32_t imm); -void instr32_0F8D(int32_t imm); -void instr16_0F8E(int32_t imm); -void instr32_0F8E(int32_t imm); -void instr16_0F8F(int32_t imm); -void instr32_0F8F(int32_t imm); -void instr_0F90_reg(int32_t r, int32_t unused); -void instr_0F91_reg(int32_t r, int32_t unused); -void instr_0F92_reg(int32_t r, int32_t unused); -void instr_0F93_reg(int32_t r, int32_t unused); -void instr_0F94_reg(int32_t r, int32_t unused); -void instr_0F95_reg(int32_t r, int32_t unused); -void instr_0F96_reg(int32_t r, int32_t unused); -void instr_0F97_reg(int32_t r, int32_t unused); -void instr_0F98_reg(int32_t r, int32_t unused); -void instr_0F99_reg(int32_t r, int32_t unused); -void instr_0F9A_reg(int32_t r, int32_t unused); -void instr_0F9B_reg(int32_t r, int32_t unused); -void instr_0F9C_reg(int32_t r, int32_t unused); -void instr_0F9D_reg(int32_t r, int32_t unused); -void instr_0F9E_reg(int32_t r, int32_t unused); -void instr_0F9F_reg(int32_t r, int32_t unused); -void instr_0F90_mem(int32_t addr, int32_t unused); -void instr_0F91_mem(int32_t addr, int32_t unused); -void instr_0F92_mem(int32_t addr, int32_t unused); -void instr_0F93_mem(int32_t addr, int32_t unused); -void instr_0F94_mem(int32_t addr, int32_t unused); -void instr_0F95_mem(int32_t addr, int32_t unused); -void instr_0F96_mem(int32_t addr, int32_t unused); -void instr_0F97_mem(int32_t addr, int32_t unused); -void instr_0F98_mem(int32_t addr, int32_t unused); -void instr_0F99_mem(int32_t addr, int32_t unused); -void instr_0F9A_mem(int32_t addr, int32_t unused); -void instr_0F9B_mem(int32_t addr, int32_t unused); -void instr_0F9C_mem(int32_t addr, int32_t unused); -void instr_0F9D_mem(int32_t addr, int32_t unused); -void instr_0F9E_mem(int32_t addr, int32_t unused); -void instr_0F9F_mem(int32_t addr, int32_t unused); -void instr16_0FA0(void); -void instr32_0FA0(void); -void instr16_0FA1(void); -void instr32_0FA1(void); -void instr_0FA2(void); -void instr16_0FA3_reg(int32_t r1, int32_t r2); -void instr16_0FA3_mem(int32_t addr, int32_t r); -void instr32_0FA3_reg(int32_t r1, int32_t r2); -void instr32_0FA3_mem(int32_t addr, int32_t r); -void instr16_0FA4_mem(int32_t addr, int32_t r, int32_t imm); -void instr16_0FA4_reg(int32_t r1, int32_t r, int32_t imm); -void instr32_0FA4_mem(int32_t addr, int32_t r, int32_t imm); -void instr32_0FA4_reg(int32_t r1, int32_t r, int32_t imm); -void instr16_0FA5_mem(int32_t addr, int32_t r); -void instr16_0FA5_reg(int32_t r1, int32_t r); -void instr32_0FA5_mem(int32_t addr, int32_t r); -void instr32_0FA5_reg(int32_t r1, int32_t r); -void instr_0FA6(void); -void instr_0FA7(void); -void instr16_0FA8(void); -void instr32_0FA8(void); -void instr16_0FA9(void); -void instr32_0FA9(void); -void instr_0FAA(void); -void instr16_0FAB_reg(int32_t r1, int32_t r2); -void instr16_0FAB_mem(int32_t addr, int32_t r); -void instr32_0FAB_reg(int32_t r1, int32_t r2); -void instr32_0FAB_mem(int32_t addr, int32_t r); -void instr16_0FAC_mem(int32_t addr, int32_t r, int32_t imm); -void instr16_0FAC_reg(int32_t r1, int32_t r, int32_t imm); -void instr32_0FAC_mem(int32_t addr, int32_t r, int32_t imm); -void instr32_0FAC_reg(int32_t r1, int32_t r, int32_t imm); -void instr16_0FAD_mem(int32_t addr, int32_t r); -void instr16_0FAD_reg(int32_t r1, int32_t r); -void instr32_0FAD_mem(int32_t addr, int32_t r); -void instr32_0FAD_reg(int32_t r1, int32_t r); -void instr_0FAE_0_reg(int32_t r); -void instr_0FAE_0_mem(int32_t addr); -void instr_0FAE_1_reg(int32_t r); -void instr_0FAE_1_mem(int32_t addr); -void instr_0FAE_2_reg(int32_t r); -void instr_0FAE_2_mem(int32_t addr); -void instr_0FAE_3_reg(int32_t r); -void instr_0FAE_3_mem(int32_t addr); -void instr_0FAE_4_reg(int32_t r); -void instr_0FAE_4_mem(int32_t addr); -void instr_0FAE_5_reg(int32_t r); -void instr_0FAE_5_mem(int32_t addr); -void instr_0FAE_6_reg(int32_t r); -void instr_0FAE_6_mem(int32_t addr); -void instr_0FAE_7_reg(int32_t r); -void instr_0FAE_7_mem(int32_t addr); -void instr16_0FAF_mem(int32_t addr, int32_t r); -void instr16_0FAF_reg(int32_t r1, int32_t r); -void instr32_0FAF_mem(int32_t addr, int32_t r); -void instr32_0FAF_reg(int32_t r1, int32_t r); -void instr_0FB0_reg(int32_t r1, int32_t r2); -void instr_0FB0_mem(int32_t addr, int32_t r); -void instr16_0FB1_reg(int32_t r1, int32_t r2); -void instr16_0FB1_mem(int32_t addr, int32_t r); -void instr32_0FB1_reg(int32_t r1, int32_t r2); -void instr32_0FB1_mem(int32_t addr, int32_t r); -void instr16_0FB2_reg(int32_t unused, int32_t unused2); -void instr16_0FB2_mem(int32_t addr, int32_t r); -void instr32_0FB2_reg(int32_t unused, int32_t unused2); -void instr32_0FB2_mem(int32_t addr, int32_t r); -void instr16_0FB3_reg(int32_t r1, int32_t r2); -void instr16_0FB3_mem(int32_t addr, int32_t r); -void instr32_0FB3_reg(int32_t r1, int32_t r2); -void instr32_0FB3_mem(int32_t addr, int32_t r); -void instr16_0FB4_reg(int32_t unused, int32_t unused2); -void instr16_0FB4_mem(int32_t addr, int32_t r); -void instr32_0FB4_reg(int32_t unused, int32_t unused2); -void instr32_0FB4_mem(int32_t addr, int32_t r); -void instr16_0FB5_reg(int32_t unused, int32_t unused2); -void instr16_0FB5_mem(int32_t addr, int32_t r); -void instr32_0FB5_reg(int32_t unused, int32_t unused2); -void instr32_0FB5_mem(int32_t addr, int32_t r); -void instr16_0FB6_mem(int32_t addr, int32_t r); -void instr16_0FB6_reg(int32_t r1, int32_t r); -void instr32_0FB6_mem(int32_t addr, int32_t r); -void instr32_0FB6_reg(int32_t r1, int32_t r); -void instr16_0FB7_mem(int32_t addr, int32_t r); -void instr16_0FB7_reg(int32_t r1, int32_t r); -void instr32_0FB7_mem(int32_t addr, int32_t r); -void instr32_0FB7_reg(int32_t r1, int32_t r); -void instr16_0FB8_reg(int32_t r1, int32_t r2); -void instr16_0FB8_mem(int32_t addr, int32_t r); -void instr16_F30FB8_mem(int32_t addr, int32_t r); -void instr16_F30FB8_reg(int32_t r1, int32_t r); -void instr32_0FB8_reg(int32_t r1, int32_t r2); -void instr32_0FB8_mem(int32_t addr, int32_t r); -void instr32_F30FB8_mem(int32_t addr, int32_t r); -void instr32_F30FB8_reg(int32_t r1, int32_t r); -void instr_0FB9(void); -void instr16_0FBA_4_reg(int32_t r, int32_t imm); -void instr16_0FBA_4_mem(int32_t addr, int32_t imm); -void instr16_0FBA_5_reg(int32_t r, int32_t imm); -void instr16_0FBA_5_mem(int32_t addr, int32_t imm); -void instr16_0FBA_6_reg(int32_t r, int32_t imm); -void instr16_0FBA_6_mem(int32_t addr, int32_t imm); -void instr16_0FBA_7_reg(int32_t r, int32_t imm); -void instr16_0FBA_7_mem(int32_t addr, int32_t imm); -void instr32_0FBA_4_reg(int32_t r, int32_t imm); -void instr32_0FBA_4_mem(int32_t addr, int32_t imm); -void instr32_0FBA_5_reg(int32_t r, int32_t imm); -void instr32_0FBA_5_mem(int32_t addr, int32_t imm); -void instr32_0FBA_6_reg(int32_t r, int32_t imm); -void instr32_0FBA_6_mem(int32_t addr, int32_t imm); -void instr32_0FBA_7_reg(int32_t r, int32_t imm); -void instr32_0FBA_7_mem(int32_t addr, int32_t imm); -void instr16_0FBB_reg(int32_t r1, int32_t r2); -void instr16_0FBB_mem(int32_t addr, int32_t r); -void instr32_0FBB_reg(int32_t r1, int32_t r2); -void instr32_0FBB_mem(int32_t addr, int32_t r); -void instr16_0FBC_mem(int32_t addr, int32_t r); -void instr16_0FBC_reg(int32_t r1, int32_t r); -void instr32_0FBC_mem(int32_t addr, int32_t r); -void instr32_0FBC_reg(int32_t r1, int32_t r); -void instr16_0FBD_mem(int32_t addr, int32_t r); -void instr16_0FBD_reg(int32_t r1, int32_t r); -void instr32_0FBD_mem(int32_t addr, int32_t r); -void instr32_0FBD_reg(int32_t r1, int32_t r); -void instr16_0FBE_mem(int32_t addr, int32_t r); -void instr16_0FBE_reg(int32_t r1, int32_t r); -void instr32_0FBE_mem(int32_t addr, int32_t r); -void instr32_0FBE_reg(int32_t r1, int32_t r); -void instr16_0FBF_mem(int32_t addr, int32_t r); -void instr16_0FBF_reg(int32_t r1, int32_t r); -void instr32_0FBF_mem(int32_t addr, int32_t r); -void instr32_0FBF_reg(int32_t r1, int32_t r); -void instr_0FC0_mem(int32_t addr, int32_t r); -void instr_0FC0_reg(int32_t r1, int32_t r); -void instr16_0FC1_mem(int32_t addr, int32_t r); -void instr16_0FC1_reg(int32_t r1, int32_t r); -void instr32_0FC1_mem(int32_t addr, int32_t r); -void instr32_0FC1_reg(int32_t r1, int32_t r); -void instr_0FC3_reg(int32_t r1, int32_t r2); -void instr_0FC3_mem(int32_t addr, int32_t r); -void instr_0FC4(int32_t source, int32_t r, int32_t imm8); -void instr_0FC4_reg(int32_t r1, int32_t r2, int32_t imm); -void instr_0FC4_mem(int32_t addr, int32_t r, int32_t imm); -void instr_660FC4(int32_t source, int32_t r, int32_t imm8); -void instr_660FC4_reg(int32_t r1, int32_t r2, int32_t imm); -void instr_660FC4_mem(int32_t addr, int32_t r, int32_t imm); -void instr_0FC5_mem(int32_t addr, int32_t r, int32_t imm8); -void instr_0FC5_reg(int32_t r1, int32_t r2, int32_t imm8); -void instr_660FC5_mem(int32_t addr, int32_t r, int32_t imm8); -void instr_660FC5_reg(int32_t r1, int32_t r2, int32_t imm8); -void instr_0FC6(void); -void instr_0FC7_1_reg(int32_t r); -void instr_0FC7_1_mem(int32_t addr); -void instr_0FC7_6_reg(int32_t r); -void instr_0FC7_6_mem(int32_t addr); -void instr_0FC8(void); -void instr_0FC9(void); -void instr_0FCA(void); -void instr_0FCB(void); -void instr_0FCC(void); -void instr_0FCD(void); -void instr_0FCE(void); -void instr_0FCF(void); -void instr_0FD0(void); -void instr_0FD1(union reg64 source, int32_t r); -void instr_0FD1_reg(int32_t r1, int32_t r2); -void instr_0FD1_mem(int32_t addr, int32_t r); -void instr_660FD1(union reg128 source, int32_t r); -void instr_660FD1_reg(int32_t r1, int32_t r2); -void instr_660FD1_mem(int32_t addr, int32_t r); -void instr_0FD2(union reg64 source, int32_t r); -void instr_0FD2_reg(int32_t r1, int32_t r2); -void instr_0FD2_mem(int32_t addr, int32_t r); -void instr_660FD2(union reg128 source, int32_t r); -void instr_660FD2_reg(int32_t r1, int32_t r2); -void instr_660FD2_mem(int32_t addr, int32_t r); -void instr_0FD3(union reg64 source, int32_t r); -void instr_0FD3_reg(int32_t r1, int32_t r2); -void instr_0FD3_mem(int32_t addr, int32_t r); -void instr_660FD3(union reg128 source, int32_t r); -void instr_660FD3_reg(int32_t r1, int32_t r2); -void instr_660FD3_mem(int32_t addr, int32_t r); -void instr_0FD4(union reg64 source, int32_t r); -void instr_0FD4_reg(int32_t r1, int32_t r2); -void instr_0FD4_mem(int32_t addr, int32_t r); -void instr_660FD4(union reg128 source, int32_t r); -void instr_660FD4_reg(int32_t r1, int32_t r2); -void instr_660FD4_mem(int32_t addr, int32_t r); -void instr_0FD5(union reg64 source, int32_t r); -void instr_0FD5_reg(int32_t r1, int32_t r2); -void instr_0FD5_mem(int32_t addr, int32_t r); -void instr_660FD5(union reg128 source, int32_t r); -void instr_660FD5_reg(int32_t r1, int32_t r2); -void instr_660FD5_mem(int32_t addr, int32_t r); -void instr_0FD6_mem(int32_t addr, int32_t r); -void instr_0FD6_reg(int32_t r1, int32_t r2); -void instr_660FD6_mem(int32_t addr, int32_t r); -void instr_660FD6_reg(int32_t r1, int32_t r2); -void instr_F20FD6_mem(int32_t addr, int32_t r); -void instr_F20FD6_reg(int32_t r1, int32_t r2); -void instr_F30FD6_mem(int32_t addr, int32_t r); -void instr_F30FD6_reg(int32_t r1, int32_t r2); -void instr_0FD7_mem(int32_t addr, int32_t r); -void instr_0FD7_reg(int32_t r1, int32_t r2); -void instr_660FD7_mem(int32_t addr, int32_t r); -void instr_660FD7_reg(int32_t r1, int32_t r2); -void instr_0FD8(union reg64 source, int32_t r); -void instr_0FD8_reg(int32_t r1, int32_t r2); -void instr_0FD8_mem(int32_t addr, int32_t r); -void instr_660FD8(union reg128 source, int32_t r); -void instr_660FD8_reg(int32_t r1, int32_t r2); -void instr_660FD8_mem(int32_t addr, int32_t r); -void instr_0FD9(union reg64 source, int32_t r); -void instr_0FD9_reg(int32_t r1, int32_t r2); -void instr_0FD9_mem(int32_t addr, int32_t r); -void instr_660FD9(union reg128 source, int32_t r); -void instr_660FD9_reg(int32_t r1, int32_t r2); -void instr_660FD9_mem(int32_t addr, int32_t r); -void instr_0FDA(union reg64 source, int32_t r); -void instr_0FDA_reg(int32_t r1, int32_t r2); -void instr_0FDA_mem(int32_t addr, int32_t r); -void instr_660FDA(union reg128 source, int32_t r); -void instr_660FDA_reg(int32_t r1, int32_t r2); -void instr_660FDA_mem(int32_t addr, int32_t r); -void instr_0FDB(union reg64 source, int32_t r); -void instr_0FDB_reg(int32_t r1, int32_t r2); -void instr_0FDB_mem(int32_t addr, int32_t r); -void instr_660FDB(union reg128 source, int32_t r); -void instr_660FDB_reg(int32_t r1, int32_t r2); -void instr_660FDB_mem(int32_t addr, int32_t r); -void instr_0FDC(union reg64 source, int32_t r); -void instr_0FDC_reg(int32_t r1, int32_t r2); -void instr_0FDC_mem(int32_t addr, int32_t r); -void instr_660FDC(union reg128 source, int32_t r); -void instr_660FDC_reg(int32_t r1, int32_t r2); -void instr_660FDC_mem(int32_t addr, int32_t r); -void instr_0FDD(union reg64 source, int32_t r); -void instr_0FDD_reg(int32_t r1, int32_t r2); -void instr_0FDD_mem(int32_t addr, int32_t r); -void instr_660FDD(union reg128 source, int32_t r); -void instr_660FDD_reg(int32_t r1, int32_t r2); -void instr_660FDD_mem(int32_t addr, int32_t r); -void instr_0FDE(union reg64 source, int32_t r); -void instr_0FDE_reg(int32_t r1, int32_t r2); -void instr_0FDE_mem(int32_t addr, int32_t r); -void instr_660FDE(union reg128 source, int32_t r); -void instr_660FDE_reg(int32_t r1, int32_t r2); -void instr_660FDE_mem(int32_t addr, int32_t r); -void instr_0FDF(union reg64 source, int32_t r); -void instr_0FDF_reg(int32_t r1, int32_t r2); -void instr_0FDF_mem(int32_t addr, int32_t r); -void instr_660FDF(union reg128 source, int32_t r); -void instr_660FDF_reg(int32_t r1, int32_t r2); -void instr_660FDF_mem(int32_t addr, int32_t r); -void instr_0FE0(union reg64 source, int32_t r); -void instr_0FE0_reg(int32_t r1, int32_t r2); -void instr_0FE0_mem(int32_t addr, int32_t r); -void instr_660FE0(union reg128 source, int32_t r); -void instr_660FE0_reg(int32_t r1, int32_t r2); -void instr_660FE0_mem(int32_t addr, int32_t r); -void instr_0FE1(union reg64 source, int32_t r); -void instr_0FE1_reg(int32_t r1, int32_t r2); -void instr_0FE1_mem(int32_t addr, int32_t r); -void instr_660FE1(union reg128 source, int32_t r); -void instr_660FE1_reg(int32_t r1, int32_t r2); -void instr_660FE1_mem(int32_t addr, int32_t r); -void instr_0FE2(union reg64 source, int32_t r); -void instr_0FE2_reg(int32_t r1, int32_t r2); -void instr_0FE2_mem(int32_t addr, int32_t r); -void instr_660FE2(union reg128 source, int32_t r); -void instr_660FE2_reg(int32_t r1, int32_t r2); -void instr_660FE2_mem(int32_t addr, int32_t r); -void instr_0FE3(union reg64 source, int32_t r); -void instr_0FE3_reg(int32_t r1, int32_t r2); -void instr_0FE3_mem(int32_t addr, int32_t r); -void instr_660FE3(union reg128 source, int32_t r); -void instr_660FE3_reg(int32_t r1, int32_t r2); -void instr_660FE3_mem(int32_t addr, int32_t r); -void instr_0FE4(union reg64 source, int32_t r); -void instr_0FE4_reg(int32_t r1, int32_t r2); -void instr_0FE4_mem(int32_t addr, int32_t r); -void instr_660FE4(union reg128 source, int32_t r); -void instr_660FE4_reg(int32_t r1, int32_t r2); -void instr_660FE4_mem(int32_t addr, int32_t r); -void instr_0FE5(union reg64 source, int32_t r); -void instr_0FE5_reg(int32_t r1, int32_t r2); -void instr_0FE5_mem(int32_t addr, int32_t r); -void instr_660FE5(union reg128 source, int32_t r); -void instr_660FE5_reg(int32_t r1, int32_t r2); -void instr_660FE5_mem(int32_t addr, int32_t r); -void instr_0FE6_mem(int32_t addr, int32_t r); -void instr_0FE6_reg(int32_t r1, int32_t r2); -void instr_660FE6_mem(int32_t addr, int32_t r); -void instr_660FE6_reg(int32_t r1, int32_t r2); -void instr_F20FE6_mem(int32_t addr, int32_t r); -void instr_F20FE6_reg(int32_t r1, int32_t r2); -void instr_F30FE6_mem(int32_t addr, int32_t r); -void instr_F30FE6_reg(int32_t r1, int32_t r2); -void instr_0FE7_mem(int32_t addr, int32_t r); -void instr_0FE7_reg(int32_t r1, int32_t r2); -void instr_660FE7_reg(int32_t r1, int32_t r2); -void instr_660FE7_mem(int32_t addr, int32_t r); -void instr_0FE8(union reg64 source, int32_t r); -void instr_0FE8_reg(int32_t r1, int32_t r2); -void instr_0FE8_mem(int32_t addr, int32_t r); -void instr_660FE8(union reg128 source, int32_t r); -void instr_660FE8_reg(int32_t r1, int32_t r2); -void instr_660FE8_mem(int32_t addr, int32_t r); -void instr_0FE9(union reg64 source, int32_t r); -void instr_0FE9_reg(int32_t r1, int32_t r2); -void instr_0FE9_mem(int32_t addr, int32_t r); -void instr_660FE9(union reg128 source, int32_t r); -void instr_660FE9_reg(int32_t r1, int32_t r2); -void instr_660FE9_mem(int32_t addr, int32_t r); -void instr_0FEA(union reg64 source, int32_t r); -void instr_0FEA_reg(int32_t r1, int32_t r2); -void instr_0FEA_mem(int32_t addr, int32_t r); -void instr_660FEA(union reg128 source, int32_t r); -void instr_660FEA_reg(int32_t r1, int32_t r2); -void instr_660FEA_mem(int32_t addr, int32_t r); -void instr_0FEB(union reg64 source, int32_t r); -void instr_0FEB_reg(int32_t r1, int32_t r2); -void instr_0FEB_mem(int32_t addr, int32_t r); -void instr_660FEB(union reg128 source, int32_t r); -void instr_660FEB_reg(int32_t r1, int32_t r2); -void instr_660FEB_mem(int32_t addr, int32_t r); -void instr_0FEC(union reg64 source, int32_t r); -void instr_0FEC_reg(int32_t r1, int32_t r2); -void instr_0FEC_mem(int32_t addr, int32_t r); -void instr_660FEC(union reg128 source, int32_t r); -void instr_660FEC_reg(int32_t r1, int32_t r2); -void instr_660FEC_mem(int32_t addr, int32_t r); -void instr_0FED(union reg64 source, int32_t r); -void instr_0FED_reg(int32_t r1, int32_t r2); -void instr_0FED_mem(int32_t addr, int32_t r); -void instr_660FED(union reg128 source, int32_t r); -void instr_660FED_reg(int32_t r1, int32_t r2); -void instr_660FED_mem(int32_t addr, int32_t r); -void instr_0FEE(union reg64 source, int32_t r); -void instr_0FEE_reg(int32_t r1, int32_t r2); -void instr_0FEE_mem(int32_t addr, int32_t r); -void instr_660FEE(union reg128 source, int32_t r); -void instr_660FEE_reg(int32_t r1, int32_t r2); -void instr_660FEE_mem(int32_t addr, int32_t r); -void instr_0FEF(union reg64 source, int32_t r); -void instr_0FEF_reg(int32_t r1, int32_t r2); -void instr_0FEF_mem(int32_t addr, int32_t r); -void instr_660FEF(union reg128 source, int32_t r); -void instr_660FEF_reg(int32_t r1, int32_t r2); -void instr_660FEF_mem(int32_t addr, int32_t r); -void instr_0FF0(void); -void instr_0FF1(union reg64 source, int32_t r); -void instr_0FF1_reg(int32_t r1, int32_t r2); -void instr_0FF1_mem(int32_t addr, int32_t r); -void instr_660FF1(union reg128 source, int32_t r); -void instr_660FF1_reg(int32_t r1, int32_t r2); -void instr_660FF1_mem(int32_t addr, int32_t r); -void instr_0FF2(union reg64 source, int32_t r); -void instr_0FF2_reg(int32_t r1, int32_t r2); -void instr_0FF2_mem(int32_t addr, int32_t r); -void instr_660FF2(union reg128 source, int32_t r); -void instr_660FF2_reg(int32_t r1, int32_t r2); -void instr_660FF2_mem(int32_t addr, int32_t r); -void instr_0FF3(union reg64 source, int32_t r); -void instr_0FF3_reg(int32_t r1, int32_t r2); -void instr_0FF3_mem(int32_t addr, int32_t r); -void instr_660FF3(union reg128 source, int32_t r); -void instr_660FF3_reg(int32_t r1, int32_t r2); -void instr_660FF3_mem(int32_t addr, int32_t r); -void instr_0FF4(union reg64 source, int32_t r); -void instr_0FF4_reg(int32_t r1, int32_t r2); -void instr_0FF4_mem(int32_t addr, int32_t r); -void instr_660FF4(union reg128 source, int32_t r); -void instr_660FF4_reg(int32_t r1, int32_t r2); -void instr_660FF4_mem(int32_t addr, int32_t r); -void instr_0FF5(union reg64 source, int32_t r); -void instr_0FF5_reg(int32_t r1, int32_t r2); -void instr_0FF5_mem(int32_t addr, int32_t r); -void instr_660FF5(union reg128 source, int32_t r); -void instr_660FF5_reg(int32_t r1, int32_t r2); -void instr_660FF5_mem(int32_t addr, int32_t r); -void instr_0FF6(union reg64 source, int32_t r); -void instr_0FF6_reg(int32_t r1, int32_t r2); -void instr_0FF6_mem(int32_t addr, int32_t r); -void instr_660FF6(union reg128 source, int32_t r); -void instr_660FF6_reg(int32_t r1, int32_t r2); -void instr_660FF6_mem(int32_t addr, int32_t r); -void instr_0FF7_mem(int32_t addr, int32_t r); -void instr_0FF7_reg(int32_t r1, int32_t r2); -void instr_660FF7_mem(int32_t addr, int32_t r); -void instr_660FF7_reg(int32_t r1, int32_t r2); -void instr_0FF8(union reg64 source, int32_t r); -void instr_0FF8_reg(int32_t r1, int32_t r2); -void instr_0FF8_mem(int32_t addr, int32_t r); -void instr_660FF8(union reg128 source, int32_t r); -void instr_660FF8_reg(int32_t r1, int32_t r2); -void instr_660FF8_mem(int32_t addr, int32_t r); -void instr_0FF9(union reg64 source, int32_t r); -void instr_0FF9_reg(int32_t r1, int32_t r2); -void instr_0FF9_mem(int32_t addr, int32_t r); -void instr_660FF9(union reg128 source, int32_t r); -void instr_660FF9_reg(int32_t r1, int32_t r2); -void instr_660FF9_mem(int32_t addr, int32_t r); -void instr_0FFA(union reg64 source, int32_t r); -void instr_0FFA_reg(int32_t r1, int32_t r2); -void instr_0FFA_mem(int32_t addr, int32_t r); -void instr_660FFA(union reg128 source, int32_t r); -void instr_660FFA_reg(int32_t r1, int32_t r2); -void instr_660FFA_mem(int32_t addr, int32_t r); -void instr_0FFB(union reg64 source, int32_t r); -void instr_0FFB_reg(int32_t r1, int32_t r2); -void instr_0FFB_mem(int32_t addr, int32_t r); -void instr_660FFB(union reg128 source, int32_t r); -void instr_660FFB_reg(int32_t r1, int32_t r2); -void instr_660FFB_mem(int32_t addr, int32_t r); -void instr_0FFC(union reg64 source, int32_t r); -void instr_0FFC_reg(int32_t r1, int32_t r2); -void instr_0FFC_mem(int32_t addr, int32_t r); -void instr_660FFC(union reg128 source, int32_t r); -void instr_660FFC_reg(int32_t r1, int32_t r2); -void instr_660FFC_mem(int32_t addr, int32_t r); -void instr_0FFD(union reg64 source, int32_t r); -void instr_0FFD_reg(int32_t r1, int32_t r2); -void instr_0FFD_mem(int32_t addr, int32_t r); -void instr_660FFD(union reg128 source, int32_t r); -void instr_660FFD_reg(int32_t r1, int32_t r2); -void instr_660FFD_mem(int32_t addr, int32_t r); -void instr_0FFE(union reg64 source, int32_t r); -void instr_0FFE_reg(int32_t r1, int32_t r2); -void instr_0FFE_mem(int32_t addr, int32_t r); -void instr_660FFE(union reg128 source, int32_t r); -void instr_660FFE_reg(int32_t r1, int32_t r2); -void instr_660FFE_mem(int32_t addr, int32_t r); -void instr_0FFF(void); -void run_instruction0f_16(int32_t opcode); -void run_instruction0f_32(int32_t opcode); diff --git a/src/native/js_imports.h b/src/native/js_imports.h deleted file mode 100644 index 39beae76..00000000 --- a/src/native/js_imports.h +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include "cpu.h" - -// like memcpy, but only efficient for large (approximately 10k) sizes -// See memcpy in https://github.com/kripken/emscripten/blob/master/src/library.js -extern void* memcpy_large(void* dest, const void* src, size_t n); -extern bool cpu_exception_hook(int32_t); -extern bool has_rand_int(void); -extern int32_t arpl(int32_t, int32_t); -extern int32_t bswap(int32_t); -extern int32_t get_rand_int(void); -extern int32_t int_log2(int32_t); -extern int32_t lar(int32_t, int32_t); -extern int32_t lsl(int32_t, int32_t); -extern int32_t mmap_read16(uint32_t); -extern int32_t mmap_read32(uint32_t); -extern int32_t mmap_read8(uint32_t); -extern int32_t verr(int32_t); -extern int32_t verw(int32_t); - -extern void cpuid(void); -extern void enter16(int32_t, int32_t); -extern void enter32(int32_t, int32_t); -extern void far_jump(int32_t, int32_t, int32_t); -extern void far_return(int32_t, int32_t, int32_t); -extern void handle_irqs(void); -extern void hlt_op(void); -extern void invlpg(int32_t); -extern void iret16(void); -extern void iret32(void); -extern void load_ldt(int32_t); -extern void load_tr(int32_t); -extern void mmap_write128(uint32_t, int32_t, int32_t, int32_t, int32_t); -extern void mmap_write16(uint32_t, int32_t); -extern void mmap_write32(uint32_t, int32_t); -extern void mmap_write8(uint32_t, int32_t); -extern void undefined_instruction(void); -extern void unimplemented_sse(void); -extern void update_eflags(int32_t); -extern bool switch_seg(int32_t, int32_t); -extern void lss16(int32_t, int32_t, int32_t); -extern void lss32(int32_t, int32_t, int32_t); -extern int32_t io_port_read8(int32_t); -extern int32_t io_port_read16(int32_t); -extern int32_t io_port_read32(int32_t); -extern void io_port_write8(int32_t, int32_t); -extern void io_port_write16(int32_t, int32_t); -extern void io_port_write32(int32_t, int32_t); -extern int32_t convert_f64_to_i32(double_t); -extern void jit_clear_func(int32_t index); -extern void throw_cpu_exception(void); -extern double_t microtick(void); diff --git a/src/native/llvm-prof.ll b/src/native/llvm-prof.ll deleted file mode 100644 index ef392f50..00000000 --- a/src/native/llvm-prof.ll +++ /dev/null @@ -1,18 +0,0 @@ -target datalayout = "e-p:32:32-i64:64-v128:32:128-n32-S128" -target triple = "asmjs-unknown-emscripten" - -declare void @coverage_log(i8* %arg1, i32 %arg2, i32 %arg3) - -; See: -; - https://llvm.org/doxygen/classllvm_1_1InstrProfIncrementInst.html#details -; - https://llvm.org/doxygen/IntrinsicInst_8h_source.html#l00715 -; - https://llvm.org/docs/CoverageMappingFormat.html#coverage-mapping-counter - -; LLVM wouldn't let us redefine an intrinsic (llvm.instrprof.increment), but we can override it -; anyway because Emscripten converts it to the following: - -define void @llvm_instrprof_increment(i8* %func_name, i64 %func_hash, i32 %num_counters, i32 %index) -{ - call void @coverage_log(i8* %func_name, i32 %num_counters, i32 %index) - ret void -} diff --git a/src/native/log.h b/src/native/log.h deleted file mode 100644 index 65d595f2..00000000 --- a/src/native/log.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "config.h" - -extern void logop(int32_t, int32_t); -extern void _dbg_trace(void); - -//#define dbg_log(...) { if(DEBUG) { printf(__VA_ARGS__); } } -//#define dbg_trace(...) { if(DEBUG) { _dbg_trace(__VA_ARGS__); } } -//#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 deleted file mode 100644 index 41dc72ea..00000000 --- a/src/native/memory.c +++ /dev/null @@ -1,237 +0,0 @@ -#include -#include -#include - -#include "const.h" -#include "global_pointers.h" -#include "js_imports.h" -#include "log.h" -#include "memory.h" -#include "profiler/profiler.h" -#include "rust_imports.h" - -const bool USE_A20 = false; - -bool in_mapped_range(uint32_t addr) -{ - return (addr >= 0xA0000 && addr < 0xC0000) || addr >= *memory_size; -} - -int32_t read8(uint32_t addr) -{ - if(USE_A20 && *a20_enabled) addr &= A20_MASK; - - if(in_mapped_range(addr)) - { - return mmap_read8(addr); - } - else - { - return mem8[addr]; - } -} - -int32_t read16(uint32_t addr) -{ - if(USE_A20 && !*a20_enabled) addr &= A20_MASK; - - if(in_mapped_range(addr)) - { - return mmap_read16(addr); - } - else - { - return *(uint16_t*)(mem8 + addr); - } -} - -int32_t read_aligned16(uint32_t addr) -{ - dbg_assert(addr < 0x80000000); - if(USE_A20 && !*a20_enabled) addr &= A20_MASK16; - - if(in_mapped_range(addr << 1)) - { - return mmap_read16(addr << 1); - } - else - { - return mem16[addr]; - } -} - -int32_t read32s(uint32_t addr) -{ - if(USE_A20 && *a20_enabled) addr &= A20_MASK; - - if(in_mapped_range(addr)) - { - return mmap_read32(addr); - } - else - { - return *(int32_t*)(mem8 + 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) -{ - dbg_assert(addr < 0x40000000); - if(USE_A20 && !*a20_enabled) addr &= A20_MASK32; - - if(in_mapped_range(addr << 2)) - { - return mmap_read32(addr << 2); - } - else - { - return mem32s[addr]; - } -} - -union reg128 read128(uint32_t addr) -{ - if(USE_A20 && *a20_enabled) addr &= A20_MASK; - union reg128 value = { { 0 } }; - - if(in_mapped_range(addr)) - { - value.i32[0] = mmap_read32(addr); - value.i32[1] = mmap_read32(addr + 4); - value.i32[2] = mmap_read32(addr + 8); - value.i32[3] = mmap_read32(addr + 12); - } - else - { - value.i64[0] = *(int64_t*)(mem8 + addr); - value.i64[1] = *(int64_t*)(mem8 + addr + 8); - } - return value; -} - -void write8(uint32_t addr, int32_t value) -{ - if(USE_A20 && !*a20_enabled) addr &= A20_MASK; - - if(in_mapped_range(addr)) - { - mmap_write8(addr, value); - } - else - { - jit_dirty_cache_single(addr); - mem8[addr] = value; - } -} - -void write16(uint32_t addr, int32_t value) -{ - if(USE_A20 && !*a20_enabled) addr &= A20_MASK; - - if(in_mapped_range(addr)) - { - mmap_write16(addr, value); - } - else - { - jit_dirty_cache_small(addr, addr + 2); - *(uint16_t*)(mem8 + addr) = value; - } -} - -void write_aligned16(uint32_t addr, uint32_t value) -{ - dbg_assert(addr < 0x80000000); - if(USE_A20 && !*a20_enabled) addr &= A20_MASK16; - - uint32_t phys_addr = addr << 1; - - if(in_mapped_range(phys_addr)) - { - mmap_write16(phys_addr, value); - } - else - { - jit_dirty_cache_small(phys_addr, phys_addr + 2); - mem16[addr] = value; - } -} - -void write32(uint32_t addr, int32_t value) -{ - if(USE_A20 && !*a20_enabled) addr &= A20_MASK; - - if(in_mapped_range(addr)) - { - mmap_write32(addr, value); - } - else - { - jit_dirty_cache_small(addr, addr + 4); - *(int32_t*)(mem8 + addr) = value; - } -} - -void write_aligned32(uint32_t addr, int32_t value) -{ - dbg_assert(addr < 0x40000000); - if(USE_A20 && !*a20_enabled) addr &= A20_MASK32; - - uint32_t phys_addr = addr << 2; - - if(in_mapped_range(phys_addr)) - { - mmap_write32(phys_addr, value); - } - else - { - jit_dirty_cache_small(phys_addr, phys_addr + 4); - mem32s[addr] = 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 - { - jit_dirty_cache_small(addr, addr + 8); - *(int64_t*)(mem8 + addr) = value; - } -} - -void write128(uint32_t addr, union reg128 value) -{ - if(USE_A20 && !*a20_enabled) addr &= A20_MASK; - - if(in_mapped_range(addr)) - { - mmap_write128(addr, value.i32[0], value.i32[1], value.i32[2], value.i32[3]); - } - else - { - jit_dirty_cache_small(addr, addr + 16); - *(int64_t*)(mem8 + addr) = value.i64[0]; - *(int64_t*)(mem8 + addr + 8) = value.i64[1]; - } -} diff --git a/src/native/memory.h b/src/native/memory.h deleted file mode 100644 index fa6e5d28..00000000 --- a/src/native/memory.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include -#include - -#include "cpu.h" - -bool in_mapped_range(uint32_t addr); -int32_t read8(uint32_t addr); -int32_t read16(uint32_t addr); -int32_t read_aligned16(uint32_t addr); -int32_t read32s(uint32_t addr); -int64_t read64s(uint32_t addr); -int32_t read_aligned32(uint32_t addr); -union reg128 read128(uint32_t addr); -void write8(uint32_t addr, int32_t value); -void write16(uint32_t addr, int32_t value); -void write_aligned16(uint32_t addr, uint32_t value); -void write32(uint32_t addr, int32_t value); -void write_aligned32(uint32_t addr, int32_t value); -void write64(uint32_t addr, int64_t value); -void write128(uint32_t addr, union reg128 value); diff --git a/src/native/misc_instr.c b/src/native/misc_instr.c deleted file mode 100644 index bd2c12ff..00000000 --- a/src/native/misc_instr.c +++ /dev/null @@ -1,450 +0,0 @@ -#include -#include -#include -#include - -#include "const.h" -#include "cpu.h" -#include "fpu.h" -#include "global_pointers.h" -#include "js_imports.h" -#include "log.h" -#include "misc_instr.h" - -bool getcf() -{ - if(*flags_changed & 1) - { - return (*last_op1 ^ (*last_op1 ^ *last_op2) & (*last_op2 ^ *last_add_result)) >> *last_op_size & 1; - } - else - { - return *flags & 1; - } -} - -bool getpf() -{ - if(*flags_changed & FLAG_PARITY) - { - c_comment("inverted lookup table"); - return 0x9669 << 2 >> ((*last_result ^ *last_result >> 4) & 0xF) & FLAG_PARITY; - } - else - { - return *flags & FLAG_PARITY; - } -} - -bool getaf() -{ - if(*flags_changed & FLAG_ADJUST) - { - return (*last_op1 ^ *last_op2 ^ *last_add_result) & FLAG_ADJUST; - } - else - { - return *flags & FLAG_ADJUST; - } -} - -bool getzf() -{ - if(*flags_changed & FLAG_ZERO) - { - return (~*last_result & *last_result - 1) >> *last_op_size & 1; - } - else - { - return *flags & FLAG_ZERO; - } -} - -bool getsf() -{ - if(*flags_changed & FLAG_SIGN) - { - return *last_result >> *last_op_size & 1; - } - else - { - return *flags & FLAG_SIGN; - } -} - -bool getof() -{ - if(*flags_changed & FLAG_OVERFLOW) - { - return ((*last_op1 ^ *last_add_result) & (*last_op2 ^ *last_add_result)) >> *last_op_size & 1; - } - else - { - return *flags & FLAG_OVERFLOW; - } -} - -bool test_o() { return getof(); } -bool test_b() { return getcf(); } -bool test_z() { return getzf(); } -bool test_s() { return getsf(); } -bool test_p() { return getpf(); } -bool test_be() { return getcf() || getzf(); } -bool test_l() { return getsf() != getof(); } -bool test_le() { return getzf() || getsf() != getof(); } - -bool test_no() { return !test_o(); } -bool test_nb() { return !test_b(); } -bool test_nz() { return !test_z(); } -bool test_ns() { return !test_s(); } -bool test_np() { return !test_p(); } -bool test_nbe() { return !test_be(); } -bool test_nl() { return !test_l(); } -bool test_nle() { return !test_le(); } - -void jmp_rel16(int32_t rel16) -{ - int32_t cs_offset = get_seg_cs(); - - c_comment("limit ip to 16 bit"); - *instruction_pointer = cs_offset + ((*instruction_pointer - cs_offset + rel16) & 0xFFFF); -} - -void jmpcc16(bool condition, int32_t imm16) -{ - if(condition) - { - jmp_rel16(imm16); - } -} - -void jmpcc32(bool condition, int32_t imm32) -{ - if(condition) - { - *instruction_pointer += imm32; - } -} - -void loopne16(int32_t imm8s) { jmpcc16(decr_ecx_asize() && !getzf(), imm8s); } -void loope16(int32_t imm8s) { jmpcc16(decr_ecx_asize() && getzf(), imm8s); } -void loop16(int32_t imm8s) { jmpcc16(decr_ecx_asize(), imm8s); } -void jcxz16(int32_t imm8s) { jmpcc16(get_reg_asize(ECX) == 0, imm8s); } - -void loopne32(int32_t imm8s) { jmpcc32(decr_ecx_asize() && !getzf(), imm8s); } -void loope32(int32_t imm8s) { jmpcc32(decr_ecx_asize() && getzf(), imm8s); } -void loop32(int32_t imm8s) { jmpcc32(decr_ecx_asize(), imm8s); } -void jcxz32(int32_t imm8s) { jmpcc32(get_reg_asize(ECX) == 0, imm8s); } - -void cmovcc16(bool condition, int32_t value, int32_t r) -{ - if(condition) - { - write_reg16(r, value); - } -} - -void cmovcc32(bool condition, int32_t value, int32_t r) -{ - if(condition) - { - write_reg32(r, value); - } -} - -int32_t get_stack_pointer(int32_t offset) -{ - if(*stack_size_32) - { - return get_seg_ss() + reg32s[ESP] + offset; - } - else - { - return get_seg_ss() + (reg16[SP] + offset & 0xFFFF); - } -} - -void adjust_stack_reg(int32_t adjustment) -{ - if(*stack_size_32) - { - reg32s[ESP] += adjustment; - } - else - { - reg16[SP] += adjustment; - } -} - -__attribute__((always_inline)) -void push16_ss16(int32_t imm16) -{ - int32_t sp = get_seg_ss() + (reg16[SP] - 2 & 0xFFFF); - safe_write16(sp, imm16); - reg16[SP] += -2; -} - -__attribute__((always_inline)) -void push16_ss32(int32_t imm16) -{ - int32_t sp = get_seg_ss() + reg32s[ESP] - 2; - safe_write16(sp, imm16); - reg32s[ESP] += -2; -} - -void push16_ss16_mem(int32_t addr) { push16_ss16(safe_read16(addr)); } -void push16_ss32_mem(int32_t addr) { push16_ss32(safe_read16(addr)); } - -void push16(int32_t imm16) -{ - if(*stack_size_32) - { - push16_ss32(imm16); - } - else - { - push16_ss16(imm16); - } -} - -__attribute__((always_inline)) -void push32_ss16(int32_t imm32) -{ - int32_t new_sp = reg16[SP] - 4 & 0xFFFF; - safe_write32(get_seg_ss() + new_sp, imm32); - reg16[SP] = new_sp; -} - -__attribute__((always_inline)) -void push32_ss32(int32_t imm32) -{ - int32_t new_esp = reg32s[ESP] - 4; - safe_write32(get_seg_ss() + new_esp, imm32); - reg32s[ESP] = new_esp; -} - -void push32_ss16_mem(int32_t addr) { push32_ss16(safe_read32s(addr)); } -void push32_ss32_mem(int32_t addr) { push32_ss32(safe_read32s(addr)); } - -__attribute__((always_inline)) -void push32(int32_t imm32) -{ - if(*stack_size_32) - { - push32_ss32(imm32); - } - else - { - push32_ss16(imm32); - } -} - -__attribute__((always_inline)) -int32_t pop16_ss16() -{ - int32_t sp = get_seg_ss() + reg16[SP]; - int32_t result = safe_read16(sp); - - reg16[SP] += 2; - return result; -} - -__attribute__((always_inline)) -int32_t pop16_ss32() -{ - int32_t esp = get_seg_ss() + reg32s[ESP]; - int32_t result = safe_read16(esp); - - reg32s[ESP] += 2; - return result; -} - -__attribute__((always_inline)) -int32_t pop16() -{ - if(*stack_size_32) - { - return pop16_ss32(); - } - else - { - return pop16_ss16(); - } -} - -__attribute__((always_inline)) -int32_t pop32s_ss16() -{ - int32_t sp = reg16[SP]; - int32_t result = safe_read32s(get_seg_ss() + sp); - reg16[SP] = sp + 4; - return result; -} - -__attribute__((always_inline)) -int32_t pop32s_ss32() -{ - int32_t esp = reg32s[ESP]; - int32_t result = safe_read32s(get_seg_ss() + esp); - reg32s[ESP] = esp + 4; - return result; -} - -__attribute__((always_inline)) -int32_t pop32s() -{ - if(*stack_size_32) - { - return pop32s_ss32(); - } - else - { - return pop32s_ss16(); - } -} - -void pusha16() -{ - uint16_t temp = reg16[SP]; - - c_comment("make sure we don't get a pagefault after having"); - c_comment("pushed several registers already"); - writable_or_pagefault(get_stack_pointer(-16), 16); - - push16(reg16[AX]); - push16(reg16[CX]); - push16(reg16[DX]); - push16(reg16[BX]); - push16(temp); - push16(reg16[BP]); - push16(reg16[SI]); - push16(reg16[DI]); -} - -void pusha32() -{ - int32_t temp = reg32s[ESP]; - - writable_or_pagefault(get_stack_pointer(-32), 32); - - push32(reg32s[EAX]); - push32(reg32s[ECX]); - push32(reg32s[EDX]); - push32(reg32s[EBX]); - push32(temp); - push32(reg32s[EBP]); - push32(reg32s[ESI]); - push32(reg32s[EDI]); -} - -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); -} - -void fxsave(uint32_t addr) -{ - writable_or_pagefault(addr, 512); - - safe_write16(addr + 0, *fpu_control_word); - safe_write16(addr + 2, fpu_load_status_word()); - safe_write8( addr + 4, ~*fpu_stack_empty & 0xFF); - safe_write16(addr + 6, *fpu_opcode); - safe_write32(addr + 8, *fpu_ip); - safe_write16(addr + 12, *fpu_ip_selector); - safe_write32(addr + 16, *fpu_dp); - safe_write16(addr + 20, *fpu_dp_selector); - - safe_write32(addr + 24, *mxcsr); - safe_write32(addr + 28, MXCSR_MASK); - - for(int32_t i = 0; i < 8; i++) - { - fpu_store_m80(addr + 32 + (i << 4), fpu_st[*fpu_stack_ptr + i & 7]); - } - - c_comment("If the OSFXSR bit in control register CR4 is not set, the FXSAVE"); - c_comment("instruction may not save these registers. This behavior is"); - c_comment("implementation dependent."); - for(int32_t i = 0; i < 8; i++) - { - safe_write128(addr + 160 + (i << 4), reg_xmm[i]); - } -} - -void fxrstor(uint32_t addr) -{ - translate_address_read(addr); - translate_address_read(addr + 511); - - int32_t new_mxcsr = safe_read32s(addr + 24); - - if(new_mxcsr & ~MXCSR_MASK) - { - dbg_log("#gp Invalid mxcsr bits"); - trigger_gp_non_raising(0); - return; - } - - *fpu_control_word = safe_read16(addr + 0); - fpu_set_status_word(safe_read16(addr + 2)); - *fpu_stack_empty = ~safe_read8(addr + 4) & 0xFF; - *fpu_opcode = safe_read16(addr + 6); - *fpu_ip = safe_read32s(addr + 8); - *fpu_ip = safe_read16(addr + 12); - *fpu_dp = safe_read32s(addr + 16); - *fpu_dp_selector = safe_read16(addr + 20); - - *mxcsr = new_mxcsr; - - for(int32_t i = 0; i < 8; i++) - { - fpu_st[*fpu_stack_ptr + i & 7] = fpu_load_m80(addr + 32 + (i << 4)); - } - - for(int32_t i = 0; i < 8; i++) - { - 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/misc_instr.h b/src/native/misc_instr.h deleted file mode 100644 index 1e12adeb..00000000 --- a/src/native/misc_instr.h +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once - -#include -#include - -bool getcf(void); -bool getpf(void); -bool getaf(void); -bool getzf(void); -bool getsf(void); -bool getof(void); - -bool test_o(void); -bool test_b(void); -bool test_z(void); -bool test_s(void); -bool test_p(void); -bool test_be(void); -bool test_l(void); -bool test_le(void); - -bool test_no(void); -bool test_nb(void); -bool test_nz(void); -bool test_ns(void); -bool test_np(void); -bool test_nbe(void); -bool test_nl(void); -bool test_nle(void); - -void jmp_rel16(int32_t rel16); -void jmpcc16(bool condition, int32_t imm16); -void jmpcc32(bool condition, int32_t imm32); - -void loope16(int32_t imm8s); -void loopne16(int32_t imm8s); -void loop16(int32_t imm8s); -void jcxz16(int32_t imm8s); -void loope32(int32_t imm8s); -void loopne32(int32_t imm8s); -void loop32(int32_t imm8s); -void jcxz32(int32_t imm8s); - -void cmovcc16(bool condition, int32_t value, int32_t r); -void cmovcc32(bool condition, int32_t value, int32_t r); -int32_t get_stack_pointer(int32_t offset); -void adjust_stack_reg(int32_t adjustment); - -void push16_ss16(int32_t imm16); -void push16_ss32(int32_t imm16); -void push16_ss16_mem(int32_t addr); -void push16_ss32_mem(int32_t addr); -void push16(int32_t imm16); - -void push32_ss16(int32_t imm32); -void push32_ss32(int32_t imm32); -void push32_ss16_mem(int32_t addr); -void push32_ss32_mem(int32_t addr); -void push32(int32_t imm32); - -int32_t pop16(void); -int32_t pop32_ss16(void); -int32_t pop32_ss32(void); -int32_t pop32s(void); - -void pusha16(void); -void pusha32(void); -void setcc_reg(bool condition, int32_t r); -void setcc_mem(bool condition, int32_t addr); -void fxsave(uint32_t addr); -void fxrstor(uint32_t addr); -int32_t xchg8(int32_t data, int32_t r8); -int32_t xchg16(int32_t data, int32_t r16); -void xchg16r(int32_t r16); -int32_t xchg32(int32_t data, int32_t r32); -void xchg32r(int32_t r32); diff --git a/src/native/modrm.c b/src/native/modrm.c deleted file mode 100644 index 54418da1..00000000 --- a/src/native/modrm.c +++ /dev/null @@ -1,235 +0,0 @@ -#include -#include -#include - -#include "const.h" -#include "cpu.h" -#include "global_pointers.h" -#include "modrm.h" - -//static int32_t resolve_sib_(bool mod); -//static int32_t resolve_modrm32_(int32_t modrm_byte); -static int32_t resolve_sib(bool mod); - -#define ds get_seg_prefix_ds -#define ss get_seg_prefix_ss - -int32_t MODRM_ENTRY() { return 0; } -int32_t MODRM_ENTRY16() { return 0; } -int32_t MODRM_ENTRY32() { return 0; } - - -#define MODRM_ENTRY(n, offset)\ - 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:\ - return offset; - -#define MODRM_ENTRY16(row, seg, value)\ - MODRM_ENTRY(0x00 | (row), seg(((value) & 0xFFFF)))\ - MODRM_ENTRY(0x40 | (row), seg(((value) + read_imm8s() & 0xFFFF)))\ - MODRM_ENTRY(0x80 | (row), seg(((value) + read_imm16() & 0xFFFF)))\ - -int32_t resolve_modrm16(int32_t modrm_byte) -{ - switch(modrm_byte) - { - MODRM_ENTRY16(0, ds, reg16[BX] + reg16[SI]); - MODRM_ENTRY16(1, ds, reg16[BX] + reg16[DI]); - MODRM_ENTRY16(2, ss, reg16[BP] + reg16[SI]); - MODRM_ENTRY16(3, ss, reg16[BP] + reg16[DI]); - MODRM_ENTRY16(4, ds, reg16[SI]); - MODRM_ENTRY16(5, ds, reg16[DI]); - - // special case - MODRM_ENTRY(0x00 | 6, ds(read_imm16())); - MODRM_ENTRY(0x40 | 6, ss(reg16[BP] + read_imm8s() & 0xFFFF)); - MODRM_ENTRY(0x80 | 6, ss(reg16[BP] + read_imm16() & 0xFFFF)); - - MODRM_ENTRY16(7, ds, reg16[BX]); - - default: - assert(false); - } - - return 0; -} - -#undef MODRM_ENTRY16 - -#define MODRM_ENTRY32(row, seg, value)\ - MODRM_ENTRY(0x00 | (row), seg((value)))\ - MODRM_ENTRY(0x40 | (row), seg((value) + read_imm8s()))\ - MODRM_ENTRY(0x80 | (row), seg((value) + read_imm32s()))\ - -int32_t resolve_modrm32_(int32_t modrm_byte) -{ - switch(modrm_byte) - { - MODRM_ENTRY32(0, ds, reg32s[EAX]); - MODRM_ENTRY32(1, ds, reg32s[ECX]); - MODRM_ENTRY32(2, ds, reg32s[EDX]); - MODRM_ENTRY32(3, ds, reg32s[EBX]); - - // special cases - MODRM_ENTRY(0x00 | 4, resolve_sib(false)); - MODRM_ENTRY(0x40 | 4, resolve_sib(true) + read_imm8s()); - MODRM_ENTRY(0x80 | 4, resolve_sib(true) + read_imm32s()); - MODRM_ENTRY(0x00 | 5, ds(read_imm32s())); - MODRM_ENTRY(0x40 | 5, ss(reg32s[EBP] + read_imm8s())); - MODRM_ENTRY(0x80 | 5, ss(reg32s[EBP] + read_imm32s())); - - MODRM_ENTRY32(6, ds, reg32s[ESI]); - MODRM_ENTRY32(7, ds, reg32s[EDI]); - - default: - assert(false); - } - - return 0; -} - -#undef MODRM_ENTRY32 -#undef MODRM_ENTRY - - -#define SIB_ENTRY_LEVEL3(n, offset)\ - case n: return offset; - -#define SIB_ENTRY_LEVEL2(n, offset)\ - SIB_ENTRY_LEVEL3((n) | 0, ds((offset) + reg32s[EAX]))\ - SIB_ENTRY_LEVEL3((n) | 1, ds((offset) + reg32s[ECX]))\ - SIB_ENTRY_LEVEL3((n) | 2, ds((offset) + reg32s[EDX]))\ - SIB_ENTRY_LEVEL3((n) | 3, ds((offset) + reg32s[EBX]))\ - SIB_ENTRY_LEVEL3((n) | 4, ss((offset) + reg32s[ESP]))\ - SIB_ENTRY_LEVEL3((n) | 5, (mod ? ss((offset) + reg32s[EBP]) : ds((offset) + read_imm32s())))\ - SIB_ENTRY_LEVEL3((n) | 6, ds((offset) + reg32s[ESI]))\ - SIB_ENTRY_LEVEL3((n) | 7, ds((offset) + reg32s[EDI])) - -#define SIB_ENTRY_LEVEL1(n, reg1)\ - SIB_ENTRY_LEVEL2(0x00 | (n) << 3, (reg1))\ - SIB_ENTRY_LEVEL2(0x40 | (n) << 3, (reg1) << 1)\ - SIB_ENTRY_LEVEL2(0x80 | (n) << 3, (reg1) << 2)\ - SIB_ENTRY_LEVEL2(0xC0 | (n) << 3, (reg1) << 3) - -#if 0 -static inline int32_t resolve_sib_(bool mod) -{ - switch(read_imm8()) - { - SIB_ENTRY_LEVEL1(0, reg32s[EAX]); - SIB_ENTRY_LEVEL1(1, reg32s[ECX]); - SIB_ENTRY_LEVEL1(2, reg32s[EDX]); - SIB_ENTRY_LEVEL1(3, reg32s[EBX]); - SIB_ENTRY_LEVEL1(4, 0 ); - SIB_ENTRY_LEVEL1(5, reg32s[EBP]); - SIB_ENTRY_LEVEL1(6, reg32s[ESI]); - SIB_ENTRY_LEVEL1(7, reg32s[EDI]); - - default: - assert(false); - } - - return 0; -} -#endif - -#undef SIB_ENTRY_LEVEL3 -#undef SIB_ENTRY_LEVEL2 -#undef SIB_ENTRY_LEVEL1 - -#undef ds -#undef ss - - -static int32_t 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; - int32_t seg; - - if(r == 4) - { - base = reg32s[ESP]; - seg = SS; - } - else if(r == 5) - { - if(mod) - { - base = reg32s[EBP]; - seg = SS; - } - else - { - base = read_imm32s(); - seg = DS; - } - } - else - { - base = reg32s[r]; - seg = DS; - } - - int32_t offset; - if(m == 4) - { - offset = 0; - } - else - { - uint8_t s = sib_byte >> 6 & 3; - offset = reg32s[m] << s; - } - - return get_seg_prefix(seg) + base + offset; -} - -int32_t resolve_modrm32(int32_t modrm_byte) -{ - uint8_t r = modrm_byte & 7; - assert(modrm_byte < 0xC0); - - if(r == 4) - { - if(modrm_byte < 0x40) - { - return resolve_sib(false); - } - else - { - return resolve_sib(true) + (modrm_byte < 0x80 ? read_imm8s() : read_imm32s()); - } - } - else if(r == 5) - { - if(modrm_byte < 0x40) - { - return get_seg_prefix_ds(read_imm32s()); - } - else - { - return get_seg_prefix_ss(reg32s[EBP] + (modrm_byte < 0x80 ? read_imm8s() : read_imm32s())); - } - } - else - { - if(modrm_byte < 0x40) - { - return get_seg_prefix_ds(reg32s[r]); - } - else - { - return get_seg_prefix_ds(reg32s[r] + (modrm_byte < 0x80 ? read_imm8s() : read_imm32s())); - } - } -} diff --git a/src/native/modrm.h b/src/native/modrm.h deleted file mode 100644 index 9712443d..00000000 --- a/src/native/modrm.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include -#include - -int32_t resolve_modrm16(int32_t modrm_byte); -int32_t resolve_modrm32(int32_t modrm_byte); diff --git a/src/native/profiler/profiler.c b/src/native/profiler/profiler.c deleted file mode 100644 index 4b68834f..00000000 --- a/src/native/profiler/profiler.c +++ /dev/null @@ -1,53 +0,0 @@ -#include -#include -#include - -#include "../const.h" -#include "../log.h" -#include "../shared.h" -#include "profiler.h" - -#if ENABLE_PROFILER - -struct profiler_stat profiler_stat_arr[PROFILER_STAT_COUNT] = {{0}}; - -void profiler_init(void) -{ - for(uint32_t i = 0; i < PROFILER_STAT_COUNT; i++) - { - profiler_stat_arr[i].count = 0; - } -} - -void profiler_stat_increment(enum stat_name stat) -{ - profiler_stat_increment_by(stat, 1); -} - -void profiler_stat_increment_by(enum stat_name stat, int32_t by) -{ - profiler_stat_arr[stat].count += by; -} - -// to be called from JS -void profiler_stat_increment_do_run() -{ - profiler_stat_increment(S_DO_RUN); -} - -int32_t profiler_stat_get(enum stat_name stat) -{ - return profiler_stat_arr[stat].count; -} - -#else -// Disable profiler - -void profiler_init(void) {} -void profiler_stat_increment(enum stat_name stat) { UNUSED(stat); } -void profiler_stat_increment_by(enum stat_name stat, int32_t by) { UNUSED(stat); UNUSED(by); } -void profiler_stat_increment_do_run() {} -int32_t profiler_stat_get(enum stat_name stat) { UNUSED(stat); return 0; } - - -#endif diff --git a/src/native/profiler/profiler.h b/src/native/profiler/profiler.h deleted file mode 100644 index 8a6fdb79..00000000 --- a/src/native/profiler/profiler.h +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once - -#include -#include - -enum stat_name { - S_COMPILE, - S_COMPILE_SUCCESS, - S_COMPILE_CUT_OFF_AT_END_OF_PAGE, - S_COMPILE_WITH_LOOP_SAFETY, - S_COMPILE_BASIC_BLOCK, - S_COMPILE_ENTRY_POINT, - S_CACHE_MISMATCH, - - S_RUN_INTERPRETED, - S_RUN_INTERPRETED_PENDING, - S_RUN_INTERPRETED_NEAR_END_OF_PAGE, - S_RUN_INTERPRETED_DIFFERENT_STATE, - S_RUN_INTERPRETED_STEPS, - - S_RUN_FROM_CACHE, - S_RUN_FROM_CACHE_STEPS, - - S_TRIGGER_CPU_EXCEPTION, - - S_SAFE_READ32_FAST, - S_SAFE_READ32_SLOW_PAGE_CROSSED, - S_SAFE_READ32_SLOW_NOT_VALID, - S_SAFE_READ32_SLOW_NOT_USER, - S_SAFE_READ32_SLOW_IN_MAPPED_RANGE, - - S_SAFE_WRITE32_FAST, - S_SAFE_WRITE32_SLOW_PAGE_CROSSED, - S_SAFE_WRITE32_SLOW_NOT_VALID, - S_SAFE_WRITE32_SLOW_NOT_USER, - S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE, - S_SAFE_WRITE32_SLOW_READ_ONLY, - S_SAFE_WRITE32_SLOW_HAS_CODE, - - S_DO_RUN, - S_DO_MANY_CYCLES, - S_CYCLE_INTERNAL, - - S_INVALIDATE_PAGE, - S_INVALIDATE_CACHE_ENTRY, - - S_NONFAULTING_OPTIMIZATION, - - S_CLEAR_TLB, - S_FULL_CLEAR_TLB, - S_TLB_FULL, - S_TLB_GLOBAL_FULL, -}; -#define PROFILER_STAT_COUNT (S_TLB_GLOBAL_FULL - S_COMPILE + 1) - -struct profiler_stat { - int32_t count; -}; - -extern struct profiler_stat profiler_stat_arr[PROFILER_STAT_COUNT]; - -void profiler_init(void); - -void profiler_stat_increment(enum stat_name stat); -void profiler_stat_increment_by(enum stat_name stat, int32_t by); -int32_t profiler_stat_get(enum stat_name stat); - -// JS import -extern double get_time(void); diff --git a/src/native/rust_imports.h b/src/native/rust_imports.h deleted file mode 100644 index 61dd4529..00000000 --- a/src/native/rust_imports.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "cpu.h" -#include - -uint32_t jit_find_cache_entry(uint32_t phys_addr, cached_state_flags flags); -void jit_increase_hotness_and_maybe_compile(uint32_t phys_addr, uint32_t cs_offset, cached_state_flags flags); - -void jit_dirty_cache_single(uint32_t phys_addr); -void jit_dirty_cache_small(uint32_t phys_start_addr, uint32_t phys_end_addr); - -bool jit_page_has_code(uint32_t physical_page); - -uint32_t jit_unused_cache_stat(void); -uint32_t jit_get_entry_length(int32_t i); -uint32_t jit_get_entry_address(int32_t i); -bool jit_get_entry_pending(int32_t i); diff --git a/src/native/shared.c b/src/native/shared.c deleted file mode 100644 index ea215992..00000000 --- a/src/native/shared.c +++ /dev/null @@ -1,103 +0,0 @@ -#include -#include -#include -#include -#include - -//void assert(bool x) {} -//void dbg_assert(bool x) {} -//void dbg_assert_message(bool x, const char* msg) {} -//void dbg_log(const char* m) {} -//void dbg_log1(const char* m, int32_t x) {} -//void dbg_log2(const char* m, int32_t x, int32_t y) {} -//void dbg_log3(const char* m, int32_t x, int32_t y, int32_t z) {} -//void dbg_log5(const char* m, int32_t x, int32_t y, int32_t z, int32_t i, int32_t j) {} -//void dbg_trace() {} -bool isnan_XXX(double f) { return f != f; } -bool isfinite_XXX(double f) { return f == INFINITY || f == -INFINITY || !isnan_XXX(f); } - -// via musl libc - -//void *memset(void *dest, int c, size_t n) -//{ -// unsigned char *s = (unsigned char *)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; -//} diff --git a/src/native/shared.h b/src/native/shared.h deleted file mode 100644 index 32ac6721..00000000 --- a/src/native/shared.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include -#include -#include - -#define UNUSED(x) (void)(x) - -//void *memset(void *dest, int c, size_t n); - -void assert(bool x); -void dbg_assert(bool x); -void dbg_assert_message(bool x, const char* msg); -void dbg_log(const char* m); -void dbg_log1(const char* m, int32_t x); -void dbg_log2(const char* m, int32_t x, int32_t y); -void dbg_log3(const char* m, int32_t x, int32_t y, int32_t z); -void dbg_log5(const char* m, int32_t x, int32_t y, int32_t z, int32_t i, int32_t j); -void dbg_log6(const char* m, int32_t x, int32_t y, int32_t z, int32_t i, int32_t j, int32_t k); -void dbg_trace(void); -void c_comment(const char* m); -bool isnan_XXX(double f); -bool isfinite_XXX(double f); diff --git a/src/native/sse_instr.c b/src/native/sse_instr.c deleted file mode 100644 index 2c8c374b..00000000 --- a/src/native/sse_instr.c +++ /dev/null @@ -1,446 +0,0 @@ -#include - -#include "cpu.h" -#include "shared.h" -#include "sse_instr.h" - -void mov_r_m64(int32_t addr, int32_t r) -{ - c_comment("mov* m64, mm"); - union reg64 data = read_mmx64s(r); - safe_write64(addr, data.u64[0]); -} - -void movl_r128_m64(int32_t addr, int32_t r) -{ - c_comment("mov* m64, xmm"); - union reg64 data = read_xmm64s(r); - safe_write64(addr, data.u64[0]); -} - -void mov_r_r128(int32_t r1, int32_t r2) -{ - c_comment("mov* xmm, xmm"); - union reg128 data = read_xmm128s(r2); - write_xmm_reg128(r1, data); -} - -void mov_r_m128(int32_t addr, int32_t r) -{ - c_comment("mov* m128, xmm"); - union reg128 data = read_xmm128s(r); - safe_write128(addr, data); -} - -void mov_rm_r128(union reg128 source, int32_t r) -{ - c_comment("mov* xmm, xmm/m128"); - write_xmm_reg128(r, source); -} - -void movh_m64_r128(int32_t addr, int32_t r) -{ - c_comment("movhp* xmm, m64"); - union reg64 data = safe_read64s(addr); - union reg128 orig = read_xmm128s(r); - write_xmm128(r, orig.u32[0], orig.u32[1], data.u32[0], data.u32[1]); -} - -void movh_r128_m64(int32_t addr, int32_t r) -{ - c_comment("movhp* m64, xmm"); - union reg128 data = read_xmm128s(r); - safe_write64(addr, data.u64[1]); -} - -void pand_r128(union reg128 source, int32_t r) -{ - c_comment("pand xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - union reg128 result = { { 0 } }; - - result.u64[0] = source.u64[0] & destination.u64[0]; - result.u64[1] = source.u64[1] & destination.u64[1]; - - write_xmm_reg128(r, result); -} - -void pandn_r128(union reg128 source, int32_t r) -{ - c_comment("pandn xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - union reg128 result = { { 0 } }; - - result.u64[0] = source.u64[0] & ~destination.u64[0]; - result.u64[1] = source.u64[1] & ~destination.u64[1]; - - write_xmm_reg128(r, result); -} - -void pxor_r128(union reg128 source, int32_t r) -{ - c_comment("pxor xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - union reg128 result = { { 0 } }; - - result.u64[0] = source.u64[0] ^ destination.u64[0]; - result.u64[1] = source.u64[1] ^ destination.u64[1]; - - write_xmm_reg128(r, result); -} - -void por_r128(union reg128 source, int32_t r) -{ - c_comment("por xmm, xmm/m128"); - c_comment("XXX: Aligned access or #gp"); - - union reg128 destination = read_xmm128s(r); - union reg128 result = { { 0 } }; - - result.u64[0] = source.u64[0] | destination.u64[0]; - result.u64[1] = source.u64[1] | destination.u64[1]; - - write_xmm_reg128(r, result); -} - -void psrlw_r64(int32_t r, uint32_t shift) -{ - c_comment("psrlw mm, {shift}"); - union reg64 destination = read_mmx64s(r); - int32_t dword0 = 0; - int32_t dword1 = 0; - - if(shift <= 15) - { - dword0 = (destination.u16[0] >> shift) | (destination.u16[1] >> shift) << 16; - dword1 = (destination.u16[2] >> shift) | (destination.u16[3] >> shift) << 16; - } - - write_mmx64(r, dword0, dword1); -} - -void psraw_r64(int32_t r, uint32_t shift) -{ - c_comment("psraw mm, {shift}"); - union reg64 destination = read_mmx64s(r); - int32_t shift_clamped = shift > 15 ? 16 : shift; - - int32_t dword0 = (destination.i16[0] >> shift_clamped) & 0xFFFF | - (destination.i16[1] >> shift_clamped) << 16; - int32_t dword1 = (destination.i16[2] >> shift_clamped) & 0xFFFF | - (destination.i16[3] >> shift_clamped) << 16; - write_mmx64(r, dword0, dword1); -} - -void psllw_r64(int32_t r, uint32_t shift) -{ - c_comment("psllw mm, {shift}"); - union reg64 destination = read_mmx64s(r); - - int32_t dword0 = 0; - int32_t dword1 = 0; - - if(shift <= 15) - { - dword0 = (destination.u16[0] << shift & 0xFFFF) | - (destination.u16[1] << shift) << 16; - dword1 = (destination.u16[2] << shift & 0xFFFF) | - (destination.u16[3] << shift) << 16; - } - - write_mmx64(r, dword0, dword1); -} - -void psrld_r64(int32_t r, uint32_t shift) -{ - c_comment("psrld mm, {shift}"); - union reg64 destination = read_mmx64s(r); - - int32_t dword0 = 0; - int32_t dword1 = 0; - - if(shift <= 31) - { - dword0 = destination.u32[0] >> shift; - dword1 = destination.u32[1] >> shift; - } - - write_mmx64(r, dword0, dword1); -} - -void psrad_r64(int32_t r, uint32_t shift) -{ - c_comment("psrad mm, {shift}"); - union reg64 destination = read_mmx64s(r); - int32_t shift_clamped = shift > 31 ? 31 : shift; - - int32_t dword0 = destination.i32[0] >> shift_clamped; - int32_t dword1 = destination.i32[1] >> shift_clamped; - - write_mmx64(r, dword0, dword1); -} - -void pslld_r64(int32_t r, uint32_t shift) -{ - c_comment("pslld mm, {shift}"); - union reg64 destination = read_mmx64s(r); - - int32_t dword0 = 0; - int32_t dword1 = 0; - - if(shift <= 31) - { - dword0 = destination.i32[0] << shift; - dword1 = destination.i32[1] << shift; - } - - write_mmx64(r, dword0, dword1); -} - -void psrlq_r64(int32_t r, uint32_t shift) -{ - c_comment("psrlq mm, {shift}"); - - if(shift == 0) - { - return; - } - - union reg64 destination = read_mmx64s(r); - union reg64 result = { { 0 } }; - - if(shift <= 63) - { - result.u64[0] = destination.u64[0] >> shift; - } - - write_mmx_reg64(r, result); -} - -void psllq_r64(int32_t r, uint32_t shift) -{ - c_comment("psllq mm, {shift}"); - union reg64 destination = read_mmx64s(r); - - if(shift == 0) - { - return; - } - - union reg64 result = { { 0 } }; - - if(shift <= 63) - { - result.u64[0] = destination.u64[0] << shift; - } - - write_mmx_reg64(r, result); -} - -void psrlw_r128(int32_t r, uint32_t shift) -{ - c_comment("psrlw xmm, {shift}"); - union reg128 destination = read_xmm128s(r); - int32_t dword0 = 0; - int32_t dword1 = 0; - int32_t dword2 = 0; - int32_t dword3 = 0; - - if(shift <= 15) - { - dword0 = (destination.u16[0] >> shift) | (destination.u16[1] >> shift) << 16; - dword1 = (destination.u16[2] >> shift) | (destination.u16[3] >> shift) << 16; - dword2 = (destination.u16[4] >> shift) | (destination.u16[5] >> shift) << 16; - dword3 = (destination.u16[6] >> shift) | (destination.u16[7] >> shift) << 16; - } - - write_xmm128(r, dword0, dword1, dword2, dword3); -} - -void psraw_r128(int32_t r, uint32_t shift) -{ - c_comment("psraw xmm, {shift}"); - union reg128 destination = read_xmm128s(r); - int32_t shift_clamped = shift > 15 ? 16 : shift; - - int32_t dword0 = (destination.i16[0] >> shift_clamped) & 0xFFFF | - (destination.i16[1] >> shift_clamped) << 16; - int32_t dword1 = (destination.i16[2] >> shift_clamped) & 0xFFFF | - (destination.i16[3] >> shift_clamped) << 16; - int32_t dword2 = (destination.i16[4] >> shift_clamped) & 0xFFFF | - (destination.i16[5] >> shift_clamped) << 16; - int32_t dword3 = (destination.i16[6] >> shift_clamped) & 0xFFFF | - (destination.i16[7] >> shift_clamped) << 16; - write_xmm128(r, dword0, dword1, dword2, dword3); -} - -void psllw_r128(int32_t r, uint32_t shift) -{ - c_comment("psllw xmm, {shift}"); - union reg128 destination = read_xmm128s(r); - - int32_t dword0 = 0; - int32_t dword1 = 0; - int32_t dword2 = 0; - int32_t dword3 = 0; - - if(shift <= 15) - { - dword0 = (destination.u16[0] << shift & 0xFFFF) | (destination.u16[1] << shift) << 16; - dword1 = (destination.u16[2] << shift & 0xFFFF) | (destination.u16[3] << shift) << 16; - dword2 = (destination.u16[4] << shift & 0xFFFF) | (destination.u16[5] << shift) << 16; - dword3 = (destination.u16[6] << shift & 0xFFFF) | (destination.u16[7] << shift) << 16; - } - - write_xmm128(r, dword0, dword1, dword2, dword3); -} - -void psrld_r128(int32_t r, uint32_t shift) -{ - c_comment("psrld xmm, {shift}"); - union reg128 destination = read_xmm128s(r); - - int32_t dword0 = 0; - int32_t dword1 = 0; - int32_t dword2 = 0; - int32_t dword3 = 0; - - if(shift <= 31) - { - dword0 = destination.u32[0] >> shift; - dword1 = destination.u32[1] >> shift; - dword2 = destination.u32[2] >> shift; - dword3 = destination.u32[3] >> shift; - } - - write_xmm128(r, dword0, dword1, dword2, dword3); -} - -void psrad_r128(int32_t r, uint32_t shift) -{ - c_comment("psrad xmm, {shift}"); - union reg128 destination = read_xmm128s(r); - int32_t shift_clamped = shift > 31 ? 31 : shift; - - int32_t dword0 = destination.i32[0] >> shift_clamped; - int32_t dword1 = destination.i32[1] >> shift_clamped; - int32_t dword2 = destination.i32[2] >> shift_clamped; - int32_t dword3 = destination.i32[3] >> shift_clamped; - - write_xmm128(r, dword0, dword1, dword2, dword3); -} - -void pslld_r128(int32_t r, uint32_t shift) -{ - c_comment("pslld xmm, {shift}"); - union reg128 destination = read_xmm128s(r); - - int32_t dword0 = 0; - int32_t dword1 = 0; - int32_t dword2 = 0; - int32_t dword3 = 0; - - if(shift <= 31) - { - dword0 = destination.i32[0] << shift; - dword1 = destination.i32[1] << shift; - dword2 = destination.i32[2] << shift; - dword3 = destination.i32[3] << shift; - } - - write_xmm128(r, dword0, dword1, dword2, dword3); -} - -void psrlq_r128(int32_t r, uint32_t shift) -{ - c_comment("psrlq xmm, {shift}"); - - if(shift == 0) - { - return; - } - - union reg128 destination = read_xmm128s(r); - union reg128 result = { { 0 } }; - - if(shift <= 63) - { - result.u64[0] = destination.u64[0] >> shift; - result.u64[1] = destination.u64[1] >> shift; - } - - write_xmm_reg128(r, result); -} - -void psllq_r128(int32_t r, uint32_t shift) -{ - c_comment("psllq xmm, {shift}"); - union reg128 destination = read_xmm128s(r); - - if(shift == 0) - { - return; - } - - union reg128 result = { { 0 } }; - - if(shift <= 63) - { - result.u64[0] = destination.u64[0] << shift; - result.u64[1] = destination.u64[1] << shift; - } - - write_xmm_reg128(r, result); -} - -bool sse_comparison(int32_t op, double_t x, double_t y) -{ - c_comment("TODO: Signaling"); - - switch(op & 7) - { - case 0: return x == y; - case 1: return x < y; - case 2: return x <= y; - case 3: return isnan_XXX(x) || isnan_XXX(y); - case 4: return x != y || isnan_XXX(x) || isnan_XXX(y); - case 5: return x >= y || isnan_XXX(x) || isnan_XXX(y); - case 6: return x > y || isnan_XXX(x) || isnan_XXX(y); - case 7: return !isnan_XXX(x) && !isnan_XXX(y); - } - - assert(false); - return false; -} - -double_t sse_min(double_t x, double_t y) -{ - c_comment("if both x and y are 0 or x is nan, y is returned"); - return x < y ? x : y; -} - -double_t sse_max(double_t x, double_t y) -{ - c_comment("if both x and y are 0 or x is nan, y is returned"); - return x > y ? x : y; -} - -int32_t sse_convert_f64_to_i32(double_t x) -{ - c_comment("TODO: Rounding modes"); - if(x >= -0x80000000 && x < 0x80000000) - { - return (int64_t)x; - } - else - { - c_comment("TODO: Signal"); - return -0x80000000; - } -} diff --git a/src/native/sse_instr.h b/src/native/sse_instr.h deleted file mode 100644 index 0151e1ed..00000000 --- a/src/native/sse_instr.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include - -#include "cpu.h" - -void mov_r_m64(int32_t addr, int32_t r); -void movl_r128_m64(int32_t addr, int32_t r); -void mov_r_r128(int32_t r1, int32_t r2); -void mov_r_m128(int32_t addr, int32_t r); -void mov_rm_r128(union reg128 source, int32_t r); -void movh_m64_r128(int32_t addr, int32_t r); -void movh_r128_m64(int32_t addr, int32_t r); -void pand_r128(union reg128 source, int32_t r); -void pandn_r128(union reg128 source, int32_t r); -void pxor_r128(union reg128 source, int32_t r); -void por_r128(union reg128 source, int32_t r); -void psrlw_r64(int32_t r, uint32_t shift); -void psraw_r64(int32_t r, uint32_t shift); -void psllw_r64(int32_t r, uint32_t shift); -void psrld_r64(int32_t r, uint32_t shift); -void psrad_r64(int32_t r, uint32_t shift); -void pslld_r64(int32_t r, uint32_t shift); -void psrlq_r64(int32_t r, uint32_t shift); -void psllq_r64(int32_t r, uint32_t shift); -void psrlw_r128(int32_t r, uint32_t shift); -void psraw_r128(int32_t r, uint32_t shift); -void psllw_r128(int32_t r, uint32_t shift); -void psrld_r128(int32_t r, uint32_t shift); -void psrad_r128(int32_t r, uint32_t shift); -void pslld_r128(int32_t r, uint32_t shift); -void psrlq_r128(int32_t r, uint32_t shift); -void psllq_r128(int32_t r, uint32_t shift); - -bool sse_comparison(int32_t op, double_t x, double_t y); -double_t sse_min(double_t x, double_t y); -double_t sse_max(double_t x, double_t y); -int32_t sse_convert_f64_to_i32(double_t x); diff --git a/src/native/string.c b/src/native/string.c deleted file mode 100644 index efa24f2d..00000000 --- a/src/native/string.c +++ /dev/null @@ -1,1141 +0,0 @@ -#include -#include - -#include "arith.h" -#include "cpu.h" -#include "global_pointers.h" -#include "js_imports.h" -#include "log.h" -#include "memory.h" -#include "string.h" -#include "shared.h" - -const int32_t MAX_COUNT_PER_CYCLE = 0x1000; -#define MIN(x, y) ((x) < (y) ? (x) : (y)) - -int32_t string_get_cycle_count(int32_t size, int32_t address) -{ - dbg_assert(size && size <= 4 && size >= -4); - - if(size < 0) - { - size = -size; - address = 0x1000 - address - size; - } - - assert((address & (size - 1)) == 0); - - c_comment("1 -> 0; 2 -> 1; 4 -> 2"); - int32_t shift = size >> 1; - - return (0x1000 - (address & 0xFFF)) >> shift; -} - -int32_t string_get_cycle_count2(int32_t size, int32_t addr1, int32_t addr2) -{ - int32_t c1 = string_get_cycle_count(size, addr1); - int32_t c2 = string_get_cycle_count(size, addr2); - - return MIN(c1, c2); -} - -void movsb_rep() -{ - int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); - 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); - if(count == 0) return; - int32_t cont = false; - int32_t start_count = count; - int32_t cycle_counter = string_get_cycle_count2(size, src, dest); - int32_t phys_src = translate_address_read(src); - int32_t phys_dest = translate_address_write(dest); - do - { - write8(phys_dest, read8(phys_src)); - phys_dest += size; - phys_src += size; - cont = --count != 0; - } - while(cont && --cycle_counter); - int32_t diff = size * (start_count - count); - add_reg_asize(EDI, diff); - add_reg_asize(ESI, diff); - set_ecx_asize(count); - *timestamp_counter += start_count - count; - if(cont) - { - *instruction_pointer = *previous_ip; - } -} - -void movsb_no_rep() -{ - int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); - int32_t dest = get_seg(ES) + get_reg_asize(EDI); - int32_t size = *flags & FLAG_DIRECTION ? -1 : 1; - - safe_write8(dest, safe_read8(src)); - add_reg_asize(EDI, size); - add_reg_asize(ESI, size); -} - -void movsw_rep() -{ - int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); - 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); - if(count == 0) return; - int32_t cont = false; - int32_t start_count = count; - int32_t cycle_counter = MAX_COUNT_PER_CYCLE; - if(!(dest & 1) && !(src & 1)) - { - int32_t single_size = size < 0 ? -1 : 1; - int32_t phys_src = translate_address_read(src) >> 1; - int32_t phys_dest = translate_address_write(dest) >> 1; - cycle_counter = string_get_cycle_count2(size, src, dest); - do - { - write_aligned16(phys_dest, read_aligned16(phys_src)); - phys_dest += single_size; - phys_src += single_size; - cont = --count != 0; - } - while(cont && --cycle_counter); - int32_t diff = size * (start_count - count); - add_reg_asize(EDI, diff); - add_reg_asize(ESI, diff); - set_ecx_asize(count); - *timestamp_counter += start_count - count; - } - else - { - do - { - safe_write16(dest, safe_read16(src)); - dest += size; - add_reg_asize(EDI, size); - src += size; - add_reg_asize(ESI, size); - cont = decr_ecx_asize() != 0; - } - while(cont && --cycle_counter); - } - if(cont) - { - *instruction_pointer = *previous_ip; - } -} - -void movsw_no_rep() -{ - int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); - int32_t dest = get_seg(ES) + get_reg_asize(EDI); - int32_t size = *flags & FLAG_DIRECTION ? -2 : 2; - - safe_write16(dest, safe_read16(src)); - add_reg_asize(EDI, size); - add_reg_asize(ESI, size); -} - -void movsd_rep() -{ - int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); - 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); - if(count == 0) return; - int32_t cont = false; - int32_t start_count = count; - int32_t cycle_counter = MAX_COUNT_PER_CYCLE; - if(!(dest & 3) && !(src & 3)) - { - int32_t single_size = size < 0 ? -1 : 1; - int32_t phys_src = translate_address_read(src) >> 2; - int32_t phys_dest = translate_address_write(dest) >> 2; - cycle_counter = string_get_cycle_count2(size, src, dest); - do - { - write_aligned32(phys_dest, read_aligned32(phys_src)); - phys_dest += single_size; - phys_src += single_size; - cont = --count != 0; - } - while(cont && --cycle_counter); - int32_t diff = size * (start_count - count); - add_reg_asize(EDI, diff); - add_reg_asize(ESI, diff); - set_ecx_asize(count); - *timestamp_counter += start_count - count; - } - else - { - do - { - safe_write32(dest, safe_read32s(src)); - dest += size; - add_reg_asize(EDI, size); - src += size; - add_reg_asize(ESI, size); - cont = decr_ecx_asize() != 0; - } - while(cont && --cycle_counter); - } - if(cont) - { - *instruction_pointer = *previous_ip; - } -} - -void movsd_no_rep() -{ - int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); - int32_t dest = get_seg(ES) + get_reg_asize(EDI); - int32_t size = *flags & FLAG_DIRECTION ? -4 : 4; - - safe_write32(dest, safe_read32s(src)); - add_reg_asize(EDI, size); - add_reg_asize(ESI, size); -} - -void cmpsb_rep(int32_t prefix_flag) -{ - int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); - int32_t dest = get_seg(ES) + get_reg_asize(EDI); - int32_t data_src, data_dest; - int32_t size = *flags & FLAG_DIRECTION ? -1 : 1; - - int32_t count = get_reg_asize(ECX); - if(count == 0) return; - int32_t cont = false; - int32_t start_count = count; - int32_t is_repz = prefix_flag == PREFIX_REPZ; - int32_t cycle_counter = string_get_cycle_count2(size, src, dest); - int32_t phys_src = translate_address_read(src); - int32_t phys_dest = translate_address_read(dest); - do - { - data_dest = read8(phys_dest); - data_src = read8(phys_src); - phys_dest += size; - phys_src += size; - cont = --count != 0 && (data_src == data_dest) == is_repz; - } - while(cont && --cycle_counter); - int32_t diff = size * (start_count - count); - add_reg_asize(EDI, diff); - add_reg_asize(ESI, diff); - set_ecx_asize(count); - *timestamp_counter += start_count - count; - if(cont) - { - *instruction_pointer = *previous_ip; - } - - cmp8(data_src, data_dest); -} - -void cmpsb_no_rep() -{ - int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); - int32_t dest = get_seg(ES) + get_reg_asize(EDI); - int32_t data_src, data_dest; - int32_t size = *flags & FLAG_DIRECTION ? -1 : 1; - - data_src = safe_read8(src); - data_dest = safe_read8(dest); - add_reg_asize(EDI, size); - add_reg_asize(ESI, size); - - cmp8(data_src, data_dest); -} - -void cmpsw_rep(int32_t prefix_flag) -{ - int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); - int32_t dest = get_seg(ES) + get_reg_asize(EDI); - int32_t data_src, data_dest; - int32_t size = *flags & FLAG_DIRECTION ? -2 : 2; - - int32_t count = get_reg_asize(ECX); - if(count == 0) return; - int32_t cont = false; - int32_t start_count = count; - int32_t is_repz = prefix_flag == PREFIX_REPZ; - int32_t cycle_counter = MAX_COUNT_PER_CYCLE; - if(!(dest & 1) && !(src & 1)) - { - int32_t single_size = size < 0 ? -1 : 1; - int32_t phys_src = translate_address_read(src) >> 1; - int32_t phys_dest = translate_address_read(dest) >> 1; - cycle_counter = string_get_cycle_count2(size, src, dest); - do - { - data_dest = read_aligned16(phys_dest); - data_src = read_aligned16(phys_src); - phys_dest += single_size; - phys_src += single_size; - cont = --count != 0 && (data_src == data_dest) == is_repz; - } - while(cont && --cycle_counter); - int32_t diff = size * (start_count - count); - add_reg_asize(EDI, diff); - add_reg_asize(ESI, diff); - set_ecx_asize(count); - *timestamp_counter += start_count - count; - } - else - { - do - { - data_dest = safe_read16(dest); - data_src = safe_read16(src); - dest += size; - add_reg_asize(EDI, size); - src += size; - add_reg_asize(ESI, size); - cont = decr_ecx_asize() != 0 && (data_src == data_dest) == is_repz; - } - while(cont && --cycle_counter); - } - if(cont) - { - *instruction_pointer = *previous_ip; - } - - cmp16(data_src, data_dest); -} - -void cmpsw_no_rep() -{ - int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); - int32_t dest = get_seg(ES) + get_reg_asize(EDI); - int32_t data_src, data_dest; - int32_t size = *flags & FLAG_DIRECTION ? -2 : 2; - - data_dest = safe_read16(dest); - data_src = safe_read16(src); - add_reg_asize(EDI, size); - add_reg_asize(ESI, size); - - cmp16(data_src, data_dest); -} - -void cmpsd_rep(int32_t prefix_flag) -{ - int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); - int32_t dest = get_seg(ES) + get_reg_asize(EDI); - int32_t data_src, data_dest; - int32_t size = *flags & FLAG_DIRECTION ? -4 : 4; - - int32_t count = get_reg_asize(ECX); - if(count == 0) return; - int32_t cont = false; - int32_t start_count = count; - int32_t is_repz = prefix_flag == PREFIX_REPZ; - int32_t cycle_counter = MAX_COUNT_PER_CYCLE; - if(!(dest & 3) && !(src & 3)) - { - int32_t single_size = size < 0 ? -1 : 1; - int32_t phys_src = translate_address_read(src) >> 2; - int32_t phys_dest = translate_address_read(dest) >> 2; - cycle_counter = string_get_cycle_count2(size, src, dest); - do - { - data_dest = read_aligned32(phys_dest); - data_src = read_aligned32(phys_src); - phys_dest += single_size; - phys_src += single_size; - cont = --count != 0 && (data_src == data_dest) == is_repz; - } - while(cont && --cycle_counter); - int32_t diff = size * (start_count - count); - add_reg_asize(EDI, diff); - add_reg_asize(ESI, diff); - set_ecx_asize(count); - *timestamp_counter += start_count - count; - } - else - { - do - { - data_dest = safe_read32s(dest); - data_src = safe_read32s(src); - dest += size; - add_reg_asize(EDI, size); - src += size; - add_reg_asize(ESI, size); - cont = decr_ecx_asize() != 0 && (data_src == data_dest) == is_repz; - } - while(cont && --cycle_counter); - } - if(cont) - { - *instruction_pointer = *previous_ip; - } - - cmp32(data_src, data_dest); -} - -void cmpsd_no_rep() -{ - int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); - int32_t dest = get_seg(ES) + get_reg_asize(EDI); - int32_t data_src, data_dest; - int32_t size = *flags & FLAG_DIRECTION ? -4 : 4; - - data_dest = safe_read32s(dest); - data_src = safe_read32s(src); - add_reg_asize(EDI, size); - add_reg_asize(ESI, size); - - cmp32(data_src, data_dest); -} - -void stosb_rep() -{ - int32_t data = reg8[AL]; - 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); - if(count == 0) return; - int32_t cont = false; - int32_t start_count = count; - int32_t cycle_counter = string_get_cycle_count(size, dest); - int32_t phys_dest = translate_address_write(dest); - do - { - write8(phys_dest, data); - phys_dest += size; - cont = --count != 0; - } - while(cont && --cycle_counter); - int32_t diff = size * (start_count - count); - add_reg_asize(EDI, diff); - set_ecx_asize(count); - *timestamp_counter += start_count - count; - if(cont) - { - *instruction_pointer = *previous_ip; - } -} - -void stosb_no_rep() -{ - int32_t data = reg8[AL]; - int32_t dest = get_seg(ES) + get_reg_asize(EDI); - int32_t size = *flags & FLAG_DIRECTION ? -1 : 1; - - safe_write8(dest, data); - add_reg_asize(EDI, size); -} - -void stosw_rep() -{ - int32_t data = reg16[AX]; - 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); - if(count == 0) return; - int32_t cont = false; - int32_t start_count = count; - int32_t cycle_counter = MAX_COUNT_PER_CYCLE; - if(!(dest & 1)) - { - int32_t single_size = size < 0 ? -1 : 1; - int32_t phys_dest = translate_address_write(dest) >> 1; - cycle_counter = string_get_cycle_count(size, dest); - do - { - write_aligned16(phys_dest, data); - phys_dest += single_size; - cont = --count != 0; - } - while(cont && --cycle_counter); - int32_t diff = size * (start_count - count); - add_reg_asize(EDI, diff); - set_ecx_asize(count); - *timestamp_counter += start_count - count; - } - else - { - do - { - safe_write16(dest, data); - dest += size; - add_reg_asize(EDI, size); - cont = decr_ecx_asize() != 0; - } - while(cont && --cycle_counter); - } - if(cont) - { - *instruction_pointer = *previous_ip; - } -} - -void stosw_no_rep() -{ - int32_t data = reg16[AX]; - int32_t dest = get_seg(ES) + get_reg_asize(EDI); - int32_t size = *flags & FLAG_DIRECTION ? -2 : 2; - - safe_write16(dest, data); - add_reg_asize(EDI, size); -} - -void stosd_rep() -{ - int32_t data = reg32s[EAX]; - 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); - if(count == 0) return; - int32_t cont = false; - int32_t start_count = count; - int32_t cycle_counter = MAX_COUNT_PER_CYCLE; - if(!(dest & 3)) - { - int32_t single_size = size < 0 ? -1 : 1; - int32_t phys_dest = translate_address_write(dest) >> 2; - cycle_counter = string_get_cycle_count(size, dest); - do - { - write_aligned32(phys_dest, data); - phys_dest += single_size; - cont = --count != 0; - } - while(cont && --cycle_counter); - int32_t diff = size * (start_count - count); - add_reg_asize(EDI, diff); - set_ecx_asize(count); - *timestamp_counter += start_count - count; - } - else - { - do - { - safe_write32(dest, data); - dest += size; - add_reg_asize(EDI, size); - cont = decr_ecx_asize() != 0; - } - while(cont && --cycle_counter); - } - if(cont) - { - *instruction_pointer = *previous_ip; - } -} - -void stosd_no_rep() -{ - int32_t data = reg32s[EAX]; - int32_t dest = get_seg(ES) + get_reg_asize(EDI); - int32_t size = *flags & FLAG_DIRECTION ? -4 : 4; - - safe_write32(dest, data); - add_reg_asize(EDI, size); -} - -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); - if(count == 0) return; - int32_t cont = false; - int32_t start_count = count; - int32_t cycle_counter = string_get_cycle_count(size, src); - int32_t phys_src = translate_address_read(src); - do - { - reg8[AL] = read8(phys_src); - phys_src += size; - cont = --count != 0; - } - while(cont && --cycle_counter); - int32_t diff = size * (start_count - count); - add_reg_asize(ESI, diff); - set_ecx_asize(count); - *timestamp_counter += start_count - count; - if(cont) - { - *instruction_pointer = *previous_ip; - } -} - -void lodsb_no_rep() -{ - int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); - int32_t size = *flags & FLAG_DIRECTION ? -1 : 1; - reg8[AL] = safe_read8(src); - add_reg_asize(ESI, size); -} - -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)); - if(count == 0) return; - bool cont = false; - uint32_t cycle_counter = MAX_COUNT_PER_CYCLE; - do - { - reg16[AX] = safe_read16(src); - src += size; - add_reg_asize(ESI, size); - cont = decr_ecx_asize() != 0; - } - while(cont && --cycle_counter); - if(cont) - { - *instruction_pointer = *previous_ip; - } -} - -void lodsw_no_rep() -{ - int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); - int32_t size = *flags & FLAG_DIRECTION ? -2 : 2; - - reg16[AX] = safe_read16(src); - add_reg_asize(ESI, size); - -} - -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); - if(count == 0) return; - int32_t cont = false; - int32_t cycle_counter = MAX_COUNT_PER_CYCLE; - do - { - reg32s[EAX] = safe_read32s(src); - src += size; - add_reg_asize(ESI, size); - cont = decr_ecx_asize() != 0; - } - while(cont && --cycle_counter); - if(cont) - { - *instruction_pointer = *previous_ip; - } -} - -void lodsd_no_rep() -{ - int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); - int32_t size = *flags & FLAG_DIRECTION ? -4 : 4; - - reg32s[EAX] = safe_read32s(src); - add_reg_asize(ESI, size); -} - -void scasb_rep(int32_t prefix_flag) -{ - int32_t dest = get_seg(ES) + get_reg_asize(EDI); - int32_t size = *flags & FLAG_DIRECTION ? -1 : 1; - int32_t data_dest; - int32_t data_src = reg8[AL]; - - int32_t count = get_reg_asize(ECX); - if(count == 0) return; - int32_t cont = false; - int32_t start_count = count; - int32_t is_repz = prefix_flag == PREFIX_REPZ; - int32_t cycle_counter = string_get_cycle_count(size, dest); - int32_t phys_dest = translate_address_read(dest); - do - { - data_dest = read8(phys_dest); - phys_dest += size; - cont = --count != 0 && (data_src == data_dest) == is_repz; - } - while(cont && --cycle_counter); - int32_t diff = size * (start_count - count); - add_reg_asize(EDI, diff); - set_ecx_asize(count); - *timestamp_counter += start_count - count; - if(cont) - { - *instruction_pointer = *previous_ip; - } - cmp8(data_src, data_dest); -} - -void scasb_no_rep() -{ - int32_t dest = get_seg(ES) + get_reg_asize(EDI); - int32_t size = *flags & FLAG_DIRECTION ? -1 : 1; - int32_t data_dest; - int32_t data_src = reg8[AL]; - - data_dest = safe_read8(dest); - add_reg_asize(EDI, size); - cmp8(data_src, data_dest); -} - -void scasw_rep(int32_t prefix_flag) -{ - int32_t dest = get_seg(ES) + get_reg_asize(EDI); - int32_t size = *flags & FLAG_DIRECTION ? -2 : 2; - int32_t data_dest; - int32_t data_src = reg16[AL]; - - int32_t count = get_reg_asize(ECX); - if(count == 0) return; - int32_t cont = false; - int32_t start_count = count; - int32_t is_repz = prefix_flag == PREFIX_REPZ; - int32_t cycle_counter = MAX_COUNT_PER_CYCLE; - if(!(dest & 1)) - { - int32_t single_size = size < 0 ? -1 : 1; - int32_t phys_dest = translate_address_read(dest) >> 1; - cycle_counter = string_get_cycle_count(size, dest); - do - { - data_dest = read_aligned16(phys_dest); - phys_dest += single_size; - cont = --count != 0 && (data_src == data_dest) == is_repz; - } - while(cont && --cycle_counter); - int32_t diff = size * (start_count - count); - add_reg_asize(EDI, diff); - set_ecx_asize(count); - *timestamp_counter += start_count - count; - } - else - { - do - { - data_dest = safe_read16(dest); - dest += size; - add_reg_asize(EDI, size); - cont = decr_ecx_asize() != 0 && (data_src == data_dest) == is_repz; - } - while(cont && --cycle_counter); - } - if(cont) - { - *instruction_pointer = *previous_ip; - } - cmp16(data_src, data_dest); -} - -void scasw_no_rep() -{ - int32_t dest = get_seg(ES) + get_reg_asize(EDI); - int32_t size = *flags & FLAG_DIRECTION ? -2 : 2; - int32_t data_dest; - int32_t data_src = reg16[AL]; - - data_dest = safe_read16(dest); - add_reg_asize(EDI, size); - cmp16(data_src, data_dest); -} - -void scasd_rep(int32_t prefix_flag) -{ - int32_t dest = get_seg(ES) + get_reg_asize(EDI); - int32_t size = *flags & FLAG_DIRECTION ? -4 : 4; - int32_t data_dest; - int32_t data_src = reg32s[EAX]; - - int32_t count = get_reg_asize(ECX); - if(count == 0) return; - int32_t cont = false; - int32_t start_count = count; - int32_t is_repz = prefix_flag == PREFIX_REPZ; - int32_t cycle_counter = MAX_COUNT_PER_CYCLE; - if(!(dest & 3)) - { - int32_t single_size = size < 0 ? -1 : 1; - int32_t phys_dest = translate_address_read(dest) >> 2; - cycle_counter = string_get_cycle_count(size, dest); - do - { - data_dest = read_aligned32(phys_dest); - phys_dest += single_size; - cont = --count != 0 && (data_src == data_dest) == is_repz; - } - while(cont && --cycle_counter); - int32_t diff = size * (start_count - count); - add_reg_asize(EDI, diff); - set_ecx_asize(count); - *timestamp_counter += start_count - count; - } - else - { - do - { - data_dest = safe_read32s(dest); - dest += size; - add_reg_asize(EDI, size); - cont = decr_ecx_asize() != 0 && (data_src == data_dest) == is_repz; - } - while(cont && --cycle_counter); - } - if(cont) - { - *instruction_pointer = *previous_ip; - } - cmp32(data_src, data_dest); -} - -void scasd_no_rep() -{ - int32_t dest = get_seg(ES) + get_reg_asize(EDI); - int32_t size = *flags & FLAG_DIRECTION ? -4 : 4; - int32_t data_dest; - int32_t data_src = reg32s[EAX]; - - data_dest = safe_read32s(dest); - add_reg_asize(EDI, size); - cmp32(data_src, data_dest); -} - - -void insb_rep() -{ - int32_t port = reg16[DX]; - if(!test_privileges_for_io(port, 1)) return; - - 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); - if(count == 0) return; - int32_t cont = false; - int32_t start_count = count; - int32_t cycle_counter = string_get_cycle_count(size, dest); - int32_t phys_dest = translate_address_write(dest); - do - { - write8(phys_dest, io_port_read8(port)); - phys_dest += size; - cont = --count != 0; - } - while(cont && --cycle_counter); - int32_t diff = size * (start_count - count); - add_reg_asize(EDI, diff); - set_ecx_asize(count); - *timestamp_counter += start_count - count; - if(cont) - { - *instruction_pointer = *previous_ip; - } -} - -void insb_no_rep() -{ - int32_t port = reg16[DX]; - if(!test_privileges_for_io(port, 1)) return; - - int32_t dest = get_seg(ES) + get_reg_asize(EDI); - int32_t size = *flags & FLAG_DIRECTION ? -1 : 1; - - writable_or_pagefault(dest, 1); - safe_write8(dest, io_port_read8(port)); - add_reg_asize(EDI, size); -} - -void insw_rep() -{ - int32_t port = reg16[DX]; - if(!test_privileges_for_io(port, 2)) return; - - 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); - if(count == 0) return; - int32_t cont = false; - int32_t start_count = count; - int32_t cycle_counter = MAX_COUNT_PER_CYCLE; - if(!(dest & 1)) - { - int32_t single_size = size < 0 ? -1 : 1; - int32_t phys_dest = translate_address_write(dest) >> 1; - cycle_counter = string_get_cycle_count(size, dest); - do - { - write_aligned16(phys_dest, io_port_read16(port)); - phys_dest += single_size; - cont = --count != 0; - } - while(cont && --cycle_counter); - int32_t diff = size * (start_count - count); - add_reg_asize(EDI, diff); - set_ecx_asize(count); - *timestamp_counter += start_count - count; - } - else - { - do - { - writable_or_pagefault(dest, 2); - safe_write16(dest, io_port_read16(port)); - dest += size; - add_reg_asize(EDI, size); - cont = decr_ecx_asize() != 0; - } - while(cont && --cycle_counter); - } - if(cont) - { - *instruction_pointer = *previous_ip; - } -} - -void insw_no_rep() -{ - int32_t port = reg16[DX]; - if(!test_privileges_for_io(port, 2)) return; - - int32_t dest = get_seg(ES) + get_reg_asize(EDI); - int32_t size = *flags & FLAG_DIRECTION ? -2 : 2; - - writable_or_pagefault(dest, 2); - safe_write16(dest, io_port_read16(port)); - add_reg_asize(EDI, size); -} - -void insd_rep() -{ - int32_t port = reg16[DX]; - if(!test_privileges_for_io(port, 4)) return; - - 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); - if(count == 0) return; - int32_t cont = false; - int32_t start_count = count; - int32_t cycle_counter = MAX_COUNT_PER_CYCLE; - if(!(dest & 3)) - { - int32_t single_size = size < 0 ? -1 : 1; - int32_t phys_dest = translate_address_write(dest) >> 2; - cycle_counter = string_get_cycle_count(size, dest); - do - { - write_aligned32(phys_dest, io_port_read32(port)); - phys_dest += single_size; - cont = --count != 0; - } - while(cont && --cycle_counter); - int32_t diff = size * (start_count - count); - add_reg_asize(EDI, diff); - set_ecx_asize(count); - *timestamp_counter += start_count - count; - } - else - { - do - { - writable_or_pagefault(dest, 4); - safe_write32(dest, io_port_read32(port)); - dest += size; - add_reg_asize(EDI, size); - cont = decr_ecx_asize() != 0; - } - while(cont && --cycle_counter); - } - if(cont) - { - *instruction_pointer = *previous_ip; - } -} - -void insd_no_rep() -{ - int32_t port = reg16[DX]; - if(!test_privileges_for_io(port, 4)) return; - - int32_t dest = get_seg(ES) + get_reg_asize(EDI); - int32_t size = *flags & FLAG_DIRECTION ? -4 : 4; - - writable_or_pagefault(dest, 4); - safe_write32(dest, io_port_read32(port)); - add_reg_asize(EDI, size); -} - -void outsb_rep() -{ - int32_t port = reg16[DX]; - if(!test_privileges_for_io(port, 1)) return; - - 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); - if(count == 0) return; - int32_t cont = false; - int32_t start_count = count; - int32_t cycle_counter = string_get_cycle_count(size, src); - int32_t phys_src = translate_address_read(src); - do - { - io_port_write8(port, read8(phys_src)); - phys_src += size; - cont = --count != 0; - } - while(cont && --cycle_counter); - int32_t diff = size * (start_count - count); - add_reg_asize(ESI, diff); - set_ecx_asize(count); - *timestamp_counter += start_count - count; - if(cont) - { - *instruction_pointer = *previous_ip; - } -} - -void outsb_no_rep() -{ - int32_t port = reg16[DX]; - if(!test_privileges_for_io(port, 1)) return; - - int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); - int32_t size = *flags & FLAG_DIRECTION ? -1 : 1; - - io_port_write8(port, safe_read8(src)); - add_reg_asize(ESI, size); -} - - -void outsw_rep() -{ - int32_t port = reg16[DX]; - if(!test_privileges_for_io(port, 2)) return; - - 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); - if(count == 0) return; - int32_t cont = false; - int32_t start_count = count; - int32_t cycle_counter = MAX_COUNT_PER_CYCLE; - if(!(src & 1)) - { - int32_t single_size = size < 0 ? -1 : 1; - int32_t phys_src = translate_address_read(src) >> 1; - cycle_counter = string_get_cycle_count(size, src); - do - { - io_port_write16(port, read_aligned16(phys_src)); - phys_src += single_size; - cont = --count != 0; - } - while(cont && --cycle_counter); - int32_t diff = size * (start_count - count); - add_reg_asize(ESI, diff); - set_ecx_asize(count); - *timestamp_counter += start_count - count; - } - else - { - do - { - io_port_write16(port, safe_read16(src)); - src += size; - add_reg_asize(ESI, size); - cont = decr_ecx_asize() != 0; - } - while(cont && --cycle_counter); - } - if(cont) - { - *instruction_pointer = *previous_ip; - } -} - -void outsw_no_rep() -{ - int32_t port = reg16[DX]; - if(!test_privileges_for_io(port, 2)) return; - - int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); - int32_t size = *flags & FLAG_DIRECTION ? -2 : 2; - - io_port_write16(port, safe_read16(src)); - add_reg_asize(ESI, size); -} - -void outsd_rep() -{ - int32_t port = reg16[DX]; - if(!test_privileges_for_io(port, 4)) return; - - 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); - if(count == 0) return; - int32_t cont = false; - int32_t start_count = count; - int32_t cycle_counter = MAX_COUNT_PER_CYCLE; - if(!(src & 3)) - { - int32_t single_size = size < 0 ? -1 : 1; - int32_t phys_src = translate_address_read(src) >> 2; - cycle_counter = string_get_cycle_count(size, src); - do - { - io_port_write32(port, read_aligned32(phys_src)); - phys_src += single_size; - cont = --count != 0; - } - while(cont && --cycle_counter); - int32_t diff = size * (start_count - count); - add_reg_asize(ESI, diff); - set_ecx_asize(count); - *timestamp_counter += start_count - count; - } - else - { - do - { - io_port_write32(port, safe_read32s(src)); - src += size; - add_reg_asize(ESI, size); - cont = decr_ecx_asize() != 0; - } - while(cont && --cycle_counter); - } - if(cont) - { - *instruction_pointer = *previous_ip; - } -} - -void outsd_no_rep() -{ - int32_t port = reg16[DX]; - if(!test_privileges_for_io(port, 4)) return; - - int32_t src = get_seg_prefix(DS) + get_reg_asize(ESI); - int32_t size = *flags & FLAG_DIRECTION ? -4 : 4; - - io_port_write32(port, safe_read32s(src)); - add_reg_asize(ESI, size); -} diff --git a/src/native/string.h b/src/native/string.h deleted file mode 100644 index 94d92fd3..00000000 --- a/src/native/string.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include - -int32_t string_get_cycle_count(int32_t size, int32_t address); -int32_t string_get_cycle_count2(int32_t size, int32_t addr1, int32_t addr2); - -void movsb_rep(void); -void movsb_no_rep(void); -void movsw_rep(void); -void movsw_no_rep(void); -void movsd_rep(void); -void movsd_no_rep(void); - -void cmpsb_rep(int32_t); -void cmpsb_no_rep(void); -void cmpsw_rep(int32_t); -void cmpsw_no_rep(void); -void cmpsd_rep(int32_t); -void cmpsd_no_rep(void); - -void stosb_rep(void); -void stosb_no_rep(void); -void stosw_rep(void); -void stosw_no_rep(void); -void stosd_rep(void); -void stosd_no_rep(void); - -void lodsb_rep(void); -void lodsb_no_rep(void); -void lodsw_rep(void); -void lodsw_no_rep(void); -void lodsd_rep(void); -void lodsd_no_rep(void); - -void scasb_rep(int32_t); -void scasb_no_rep(void); -void scasw_rep(int32_t); -void scasw_no_rep(void); -void scasd_rep(int32_t); -void scasd_no_rep(void); - -void insb_rep(void); -void insb_no_rep(void); -void insw_rep(void); -void insw_no_rep(void); -void insd_rep(void); -void insd_no_rep(void); - -void outsb_rep(void); -void outsb_no_rep(void); -void outsw_rep(void); -void outsw_no_rep(void); -void outsd_rep(void); -void outsd_no_rep(void); From 618062299da21d71a187d9da09fa5a0a01baceb5 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 1 Oct 2018 18:51:28 -0300 Subject: [PATCH 1396/2137] Remove emscripten from docker test image --- docker/test-image/Dockerfile | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docker/test-image/Dockerfile b/docker/test-image/Dockerfile index 02fbb8bc..5a5e599f 100644 --- a/docker/test-image/Dockerfile +++ b/docker/test-image/Dockerfile @@ -1,9 +1,9 @@ -FROM ttt43ttt/emscripten +FROM ubuntu:latest RUN \ dpkg --add-architecture i386 && \ apt-get update -qq && \ - apt-get install -y clang-tidy gcc-multilib nasm gdb unzip openjdk-8-jre wget python python3 qemu-system-x86 && \ + apt-get install -y nasm gdb unzip openjdk-8-jre wget python python3 qemu-system-x86 git-core build-essential libc6-dev-i386-cross libc6-dev-i386 && \ wget https://nodejs.org/dist/v8.9.4/node-v8.9.4-linux-x64.tar.xz && \ tar xfv node-v8.9.4-linux-x64.tar.xz && \ rm node-v8.9.4-linux-x64.tar.xz && \ @@ -14,4 +14,8 @@ RUN \ rustup toolchain install nightly && \ rustup default nightly && \ rustup target add wasm32-unknown-unknown --toolchain nightly && \ - rustup component add rustfmt-preview --toolchain nightly + rustup component add rustfmt-preview --toolchain nightly && \ + apt-get clean && \ + apt-get autoclean && \ + apt-get autoremove && \ + rm -rf /var/lib/apt/lists/* From 7796d9dcb4d62cd9bd77a652933a29aee33e22bc Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 1 Oct 2018 20:08:48 -0300 Subject: [PATCH 1397/2137] Clean up wasm loading, remove unused code for emscripten --- src/browser/lib.js | 124 +---------------------- src/browser/starter.js | 223 +++++++++-------------------------------- 2 files changed, 47 insertions(+), 300 deletions(-) diff --git a/src/browser/lib.js b/src/browser/lib.js index 0d47432f..80388df7 100644 --- a/src/browser/lib.js +++ b/src/browser/lib.js @@ -18,62 +18,13 @@ var ASYNC_SAFE = false; v86util.AsyncFileBuffer = AsyncFileBuffer; v86util.SyncFileBuffer = SyncFileBuffer; - /** - * Decode a buffer into an unsigned LEB-128 integer - * @param {Uint8Array} view Byte-stream of encoded integer - * @param {number=} max_bits Maximum number of bits that are represented; see - * https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md#varuintn - */ - v86util.decode_leb128_u = function(view, max_bits=256) - { - dbg_assert(view instanceof Uint8Array); - - const result = { - value: 0, - next_index: 0, - }; - let shift = 0; - const max_bytes = Math.ceil(max_bits / 7); - - while(result.next_index < view.length && result.next_index < max_bytes) - { - let byte = view[result.next_index++]; - result.value |= (byte & 127) << shift; - if((byte & 128) === 0) - { - break; - } - shift += 7; - } - return result; - }; - - v86util.decode_dylink = function(module) - { - // Details on dylink section: - // https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md - const dylink_sections = WebAssembly.Module.customSections(module, "dylink"); - dbg_assert(dylink_sections && dylink_sections.length === 1); - const dylink_section = dylink_sections[0]; - const view = new Uint8Array(dylink_section); - const { value: memory_size, next_index: table_size_start } = - v86util.decode_leb128_u(view, 32); - const table_size = v86util.decode_leb128_u(view.subarray(table_size_start), 32).value; - - return { - memory_size, - table_size, - }; - }; - // Reads len characters at offset from Memory object mem as a JS string v86util.read_sized_string_from_mem = function read_sized_string_from_mem(mem, offset, len) { return String.fromCharCode(...new Uint8Array(mem.buffer, offset, len)); }; - //XXX: figure out a better way to handle dylink issue than duplicating above function - v86util.minimal_load_wasm = function minimal_load_wasm(filename, imports, cb) + v86util.load_wasm = function load_wasm(filename, imports, cb) { function load_cb(bytes) { @@ -92,79 +43,6 @@ var ASYNC_SAFE = false; v86util.load_file(filename, { done: load_cb }); }; - /** - * Fetches, compiles, and instantiates a wasm file - * @param {string} filename - * @param {Object} imports Object used for WebAssembly module's imports - * @param {number} memory_size Bytes of memory the module wants for itself, excluding the space - * the dylink section requests. - * @param {number} table_size Number of table entries the module wants for itself, excluding - * what the dylink section requests. - * @param {function(Object)} cb Callback function that receives custom object with instance, memory, - * exported functions, imports, and the filename. - */ - v86util.load_wasm = function load_wasm(filename, imports, memory_size, table_size, cb) - { - dbg_assert(memory_size > 0); - dbg_assert(typeof imports["env"] === "object"); - - function load_cb(buffer) - { - WebAssembly.compile(buffer) - .then(module => { - const dylink = v86util.decode_dylink(module); - let total_mem_pages = Math.ceil( - (dylink.memory_size + memory_size) / WASM_PAGE_SIZE - ); - - // emscripten seems to require a minimum of 256 pages (16 MB) - total_mem_pages = Math.max(256, total_mem_pages); - - try - { - imports["env"]["memory"] = new WebAssembly.Memory({ - "initial": total_mem_pages, - "maximum": total_mem_pages, - }); - } - catch(e) - { - console.error( - "Failed to allocate WASM memory of %d pages", - total_mem_pages - ); - throw e; - } - imports["env"]["memoryBase"] = memory_size; - - // XXX: Emscripten forces EMULATED_FUNCTION_POINTERS when - // using SIDE_MODULE=1, which we use. Newer versions of emscripten add - // all exported functions to the WebAssembly.Table, so we need extra space - // here - const EXTRA_TABLE_SPACE_FOR_EMULATED_FP = 10000; - - imports["env"][WASM_EXPORT_TABLE_NAME] = new WebAssembly.Table({ - "initial": dylink.table_size + table_size + EXTRA_TABLE_SPACE_FOR_EMULATED_FP, - "element": "anyfunc", - }); - imports["env"]["tableBase"] = table_size; - - return WebAssembly.instantiate(module, imports) - .then(instance => ({ instance, module })); - }) - .then(({ instance, module }) => { - cb({ - memory: imports["env"]["memory"], - exports: instance["exports"], - instance, - imports, - filename, - }); - }); - } - v86util.load_file(filename, { done: load_cb }); - }; - /** * @param {string} filename * @param {Object} options diff --git a/src/browser/starter.js b/src/browser/starter.js index 24318e8e..2a46f20f 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -89,93 +89,31 @@ function V86Starter(options) this.cpu_is_running = false; - var bus = Bus.create(); - var adapter_bus = this.bus = bus[0]; + const bus = Bus.create(); + const adapter_bus = this.bus = bus[0]; this.emulator_bus = bus[1]; - var emulator; - var cpu; - var v86oxide; - const coverage_logger = new CoverageLogger(); - //if(coverage_logger.ENABLED) - //{ - // this.bus.register("emulator-stopped", function() - // { - // coverage_logger.dump_to_files(); - // }, this); - //} + var cpu; + var wasm_memory; const wasm_table = new WebAssembly.Table({ element: "anyfunc", "initial": WASM_TABLE_SIZE + WASM_TABLE_OFFSET }); - var wasm_shared_funcs = { - "__assert_fail": (condition, file, line, fun) => { - const memory = new Uint8Array(v86oxide.exports.memory.buffer); - - function read_string(memory, offset) - { - memory = memory.subarray(offset); - - const zero = memory.indexOf(0); - if(zero !== -1) - { - memory = memory.subarray(0, zero); - } - return String.fromCharCode.apply(String, memory); - } - - console.error("Assertion Failed: '%s' at %s:%d in %s", - read_string(memory, condition), - read_string(memory, file), - line, - read_string(memory, fun)); - - dbg_assert(false); - }, + const wasm_shared_funcs = { "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_trace": function() { return dbg_trace(); }, "logop": function(eip, op) { return cpu.debug.logop(eip, op); }, "undefined_instruction": function() { return cpu.undefined_instruction.apply(cpu, arguments); }, "unimplemented_sse": function() { return cpu.unimplemented_sse(); }, "microtick": v86.microtick, "get_rand_int": function() { return v86util.get_rand_int(); }, "has_rand_int": function() { return v86util.has_rand_int(); }, - "dbg_log": function(string_offset) - { - }, - "dbg_log1": function(string_offset) - { - }, - "dbg_log2": function(string_offset) - { - }, - "dbg_log3": function(string_offset) - { - }, - "dbg_log5": function(string_offset) - { - }, "dbg_trace": function() { dbg_trace(); }, - //"printf": function(format_string_offset, stack_top) { - // dbg_assert(arguments.length === 2); - // dbg_log_wasm(v86oxide.exports.memory.buffer, format_string_offset, stack_top); - //}, - "memcpy_large": function(dest, source, length) { - const mem8 = new Uint8Array(v86oxide.exports.memory.buffer); - mem8.set(mem8.subarray(source, source + length), dest); - return dest; - }, - "memcpy": function(dest, source, length) { - const mem8 = new Uint8Array(v86oxide.exports.memory.buffer); - mem8.set(mem8.subarray(source, source + length), dest); - return dest; - }, "far_jump": function(eip, selector, is_call) { return cpu.far_jump(eip, selector, !!is_call); }, "far_return": function(eip, selector, stack_adjust) { return cpu.far_return(eip, selector, stack_adjust); }, @@ -193,10 +131,12 @@ function V86Starter(options) "mmap_read8": function(addr) { return cpu.mmap_read8(addr); }, "mmap_read16": function(addr) { return cpu.mmap_read16(addr); }, "mmap_read32": function(addr) { return cpu.mmap_read32(addr); }, - "mmap_write8": function(addr, value) { return cpu.mmap_write8(addr, value); }, - "mmap_write16": function(addr, value) { return cpu.mmap_write16(addr, value); }, - "mmap_write32": function(addr, value) { return cpu.mmap_write32(addr, value); }, - "mmap_write128": function(addr, value0, value1, value2, value3) { return cpu.mmap_write128(addr, value0, value1, value2, value3); }, + "mmap_write8": function(addr, value) { cpu.mmap_write8(addr, value); }, + "mmap_write16": function(addr, value) { cpu.mmap_write16(addr, value); }, + "mmap_write32": function(addr, value) { cpu.mmap_write32(addr, value); }, + "mmap_write128": function(addr, value0, value1, value2, value3) { + cpu.mmap_write128(addr, value0, value1, value2, value3); + }, "arpl": function() { return cpu.arpl.apply(cpu, arguments); }, @@ -215,137 +155,69 @@ function V86Starter(options) "enter16": function() { return cpu.enter16.apply(cpu, arguments); }, "enter32": function() { return cpu.enter32.apply(cpu, arguments); }, - "get_time": Date.now, - - "coverage_log": (fn_name_offset, num_blocks, visited_block) => { - //coverage_logger.log(fn_name_offset, num_blocks, visited_block); - }, - - // see https://github.com/kripken/emscripten/blob/incoming/src/library.js "Math_atan2": Math.atan2, - "sin": Math.sin, - "cos": Math.cos, "Math_tan": Math.tan, - "trunc": Math.trunc, - "fmod": (x, y) => x % y, - "llvm_exp2_f64": (x) => Math.pow(2, x), - "log": Math.log, - "round": Math.round, + // https://github.com/rust-lang/rust/blob/56e46255b39058725d25e74200e03c0c70a0d0d3/src/etc/wasm32-shim.js#L105-L117 "ldexp": function(x, exp) { return x * Math.pow(2, exp); }, - "llvm_round_f64": function(d) { - d = +d; - return d >= +0 ? +Math.floor(d + 0.5) : +Math.ceil(d - 0.5); - }, - "llvm_trunc_f64": Math.trunc, "log_from_wasm": function(offset, len) { - const str = v86util.read_sized_string_from_mem(v86oxide.exports.memory, offset, len); + const str = v86util.read_sized_string_from_mem(wasm_memory, offset, len); dbg_log(str, LOG_CPU); }, "console_log_from_wasm": function(offset, len) { - const str = v86util.read_sized_string_from_mem(v86oxide.exports.memory, offset, len); + const str = v86util.read_sized_string_from_mem(wasm_memory, offset, len); console.error(str); }, - "codegen_finalize": (wasm_table_index, start, end, first_opcode, state_flags) => cpu.codegen_finalize(wasm_table_index, start, end, first_opcode, state_flags), - "jit_clear_func": (wasm_table_index) => cpu.jit_clear_func(wasm_table_index), - "__indirect_function_table": wasm_table, - "floor": Math.floor, - "ceil": Math.ceil, - "fabs": Math.abs, - "abs": Math.abs, + "codegen_finalize": (wasm_table_index, start, end, first_opcode, state_flags) => { + cpu.codegen_finalize(wasm_table_index, start, end, first_opcode, state_flags); + }, + "jit_clear_func": (wasm_table_index) => cpu.jit_clear_func(wasm_table_index), "do_task_switch": (selector, has_error_code, error_code) => { cpu.do_task_switch(selector, has_error_code, error_code); }, // XXX: Port to Rust "switch_cs_real_mode": (selector) => cpu.switch_cs_real_mode(selector), + + "__indirect_function_table": wasm_table, }; - const wasm_globals = { - "Infinity": Infinity, - "NaN": NaN, - }; - - //const v86oxide_mem = new WebAssembly.Memory({ "initial": 250 }); - //const v86oxide_externs = { - // "memory": v86oxide_mem, - // "read8": addr => cpu.read8(addr), - // "read16": addr => cpu.read16(addr), - // "read32": addr => cpu.read32s(addr), - // "tlb_set_has_code": (page, has_code) => cpu.wm.exports["_tlb_set_has_code"](page, has_code), - // "check_tlb_invariants": () => cpu.wm.exports["_check_tlb_invariants"](), - // "profiler_stat_increment": (name) => cpu.wm.exports["_profiler_stat_increment"](name), - //}; - - let wasm_file = DEBUG ? "v86-debug.wasm" : "v86.wasm"; let v86oxide_bin = DEBUG ? "v86oxide-debug.wasm" : "v86oxide.wasm"; - if(typeof window === "undefined" && typeof __dirname === "string") + if(options["oxide_path"]) + { + v86oxide_bin = options["oxide_path"]; + } + else if(typeof window === "undefined" && typeof __dirname === "string") { - wasm_file = __dirname + "/" + wasm_file; v86oxide_bin = __dirname + "/" + v86oxide_bin; } else { - wasm_file = "build/" + wasm_file; v86oxide_bin = "build/" + v86oxide_bin; } - const v86oxide_exports = [ - // For C: - "jit_get_entry_pending", - "jit_get_entry_address", - "jit_get_entry_length", - "jit_unused_cache_stat", - "jit_dirty_cache_single", - "jit_dirty_cache_small", - "jit_page_has_code", - "jit_increase_hotness_and_maybe_compile", - "jit_find_cache_entry", + v86util.load_wasm( + v86oxide_bin, + { "env": wasm_shared_funcs }, + v86oxide => { + v86oxide.exports["rust_setup"](); - // For JS: - "jit_empty_cache", - "codegen_finalize_finished", - "rust_setup", - "jit_dirty_cache", - ]; + wasm_memory = v86oxide.exports.memory; - v86util.minimal_load_wasm(v86oxide_bin, { "env": wasm_shared_funcs }, (v86oxide_) => { - v86oxide = v86oxide_; - //for(const fn_name of v86oxide_exports) - //{ - // dbg_assert(typeof v86oxide.exports[fn_name] === "function", `Function ${fn_name} not found in v86oxide exports`); - // wasm_shared_funcs[`_${fn_name}`] = v86oxide.exports[fn_name]; - //} - v86oxide.exports["rust_setup"](); + const wm = v86oxide; - //v86oxide.exports[WASM_EXPORT_TABLE_NAME].grow(WASM_TABLE_SIZE); + const emulator = this.v86 = new v86(this.emulator_bus, wm, v86oxide); + cpu = emulator.cpu; - const wm = v86oxide; + this.continue_init(emulator, options); + }); +} - //mem = v86oxide.exports.memory.buffer; - //mem8 = new Uint8Array(mem); - emulator = this.v86 = new v86(this.emulator_bus, wm, v86oxide, coverage_logger); - cpu = emulator.cpu; - - //XXX: fix indentation break - - //v86util.load_wasm( - // wasm_file, - // { "env": wasm_shared_funcs, "global" : wasm_globals }, - // options["memory_size"] + GUEST_MEMORY_START, - // WASM_TABLE_SIZE, - // wm => { - // mem = wm.memory.buffer; - // mem8 = new Uint8Array(mem); - // wm.instance.exports["__post_instantiate"](); - // coverage_logger.init(wm); - // emulator = this.v86 = new v86(this.emulator_bus, wm, v86oxide, coverage_logger); - // cpu = emulator.cpu; - - // XXX: Leaving unindented to minimize diff; still a part of the cb to load_wasm! +V86Starter.prototype.continue_init = function(emulator, options) +{ this.bus.register("emulator-stopped", function() { this.cpu_is_running = false; @@ -376,31 +248,31 @@ function V86Starter(options) if(options["network_relay_url"]) { - this.network_adapter = new NetworkAdapter(options["network_relay_url"], adapter_bus); + this.network_adapter = new NetworkAdapter(options["network_relay_url"], this.bus); settings.enable_ne2k = true; } if(!options["disable_keyboard"]) { - this.keyboard_adapter = new KeyboardAdapter(adapter_bus); + this.keyboard_adapter = new KeyboardAdapter(this.bus); } if(!options["disable_mouse"]) { - this.mouse_adapter = new MouseAdapter(adapter_bus, options["screen_container"]); + this.mouse_adapter = new MouseAdapter(this.bus, options["screen_container"]); } if(options["screen_container"]) { - this.screen_adapter = new ScreenAdapter(options["screen_container"], adapter_bus); + this.screen_adapter = new ScreenAdapter(options["screen_container"], this.bus); } else if(options["screen_dummy"]) { - this.screen_adapter = new DummyScreenAdapter(adapter_bus); + this.screen_adapter = new DummyScreenAdapter(this.bus); } if(options["serial_container"]) { - this.serial_adapter = new SerialAdapter(options["serial_container"], adapter_bus); + this.serial_adapter = new SerialAdapter(options["serial_container"], this.bus); } // ugly, but required for closure compiler compilation @@ -691,10 +563,7 @@ function V86Starter(options) }.bind(this), 0); }.bind(this), 0); } - - //}); - }); -} +}; /** * Start emulation. Do nothing if emulator is running already. Can be From 53bd41614f1c82e807a92eef7427ec63dd1ae8eb Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 1 Oct 2018 20:11:45 -0300 Subject: [PATCH 1398/2137] Fix minor problem with Rust port of call_interrupt_vector --- src/rust/cpu2/cpu.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index b258be67..86ec59ba 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -358,9 +358,7 @@ impl InterruptDescriptor { pub fn gate_type(&self) -> u8 { self.access_byte() & 7 } pub fn is_32(&self) -> bool { self.access_byte() & 8 == 8 } pub fn is_present(&self) -> bool { self.access_byte() & 0x80 == 0x80 } - pub fn reserved_zeros_are_valid(&self) -> bool { - self.raw >> 36 & 7 == 0 && self.access_byte() & 16 == 0 - } + pub fn reserved_zeros_are_valid(&self) -> bool { self.access_byte() & 16 == 0 } const TASK_GATE: u8 = 0b101; const INTERRUPT_GATE: u8 = 0b110; @@ -472,8 +470,9 @@ pub unsafe fn call_interrupt_vector( if !is_valid_type || !descriptor.reserved_zeros_are_valid() { // invalid gate_type dbg_log!( - "gate type invalid or reserved 0s violated. gate_type=0b{:b}", - gate_type + "gate type invalid or reserved 0s violated. gate_type=0b{:b} raw={:b}", + gate_type, + descriptor.raw ); dbg_log!( "addr={:x} offset={:x} selector={:x}", @@ -518,7 +517,7 @@ pub unsafe fn call_interrupt_vector( // inter privilege level interrupt // interrupt from vm86 mode - if old_flags & FLAG_VM != 0 && cs_segment_descriptor.dpl() == 0 { + if old_flags & FLAG_VM != 0 && cs_segment_descriptor.dpl() != 0 { panic!("Unimplemented: #GP handler for non-0 cs segment dpl when in vm86 mode"); } From 2ee68c960a15f1a62bcfa1a832aa3a1f5f111b5f Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 1 Oct 2018 20:30:30 -0300 Subject: [PATCH 1399/2137] Make --strip-debug configurable (for release builds) --- Makefile | 7 ++++++- tools/rust-lld-wrapper | 8 +++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 232b7c92..ef117ad6 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,11 @@ JIT_DEPENDENCIES=$(GEN_DEPENDENCIES) gen/generate_jit.js INTERPRETER_DEPENDENCIES=$(GEN_DEPENDENCIES) gen/generate_interpreter.js ANALYZER_DEPENDENCIES=$(GEN_DEPENDENCIES) gen/generate_analyzer.js +STRIP_DEBUG= +ifeq ($(strip_debug),true) +STRIP_DEBUG=--v86-strip-debug +endif + all: build/v86_all.js build/libv86.js build/v86oxide.wasm all-debug: build/libv86-debug.js build/v86oxide-debug.wasm browser: build/v86_all.js @@ -83,7 +88,7 @@ CARGO_FLAGS=\ --target wasm32-unknown-unknown \ -- \ -C linker=tools/rust-lld-wrapper \ - -C link-args="--import-table --global-base=8388608" \ + -C link-args="--import-table --global-base=8388608 $(STRIP_DEBUG)" \ --verbose CORE_FILES=const.js config.js io.js main.js lib.js coverage.js ide.js pci.js floppy.js \ diff --git a/tools/rust-lld-wrapper b/tools/rust-lld-wrapper index e86cba96..865cad37 100755 --- a/tools/rust-lld-wrapper +++ b/tools/rust-lld-wrapper @@ -10,14 +10,20 @@ from os import path def main(): args = sys.argv[1:] + strip_debug = "--v86-strip-debug" in args + # filter out args inserted by rustc TO_REMOVE = { "--export-table", "--stack-first", - "--strip-debug", # TODO: Make this configurable + "--strip-debug", + "--v86-strip-debug", } args = list(filter(lambda arg: arg not in TO_REMOVE, args)) + if strip_debug: + args += ["--strip-debug"] + lld = find_rust_lld() result = subprocess.run([lld] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) From 57b51d440d7383786af15dcf3f6840269c5f4586 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 1 Oct 2018 20:33:36 -0300 Subject: [PATCH 1400/2137] nodejs: Prefer perf_hooks module over custom shim for performance.now --- src/main.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main.js b/src/main.js index bf744545..b397e5d7 100644 --- a/src/main.js +++ b/src/main.js @@ -179,6 +179,11 @@ if(typeof performance === "object" && performance.now) { v86.microtick = performance.now.bind(performance); } +else if(typeof require === "function") +{ + const { performance } = require("perf_hooks"); + v86.microtick = performance.now.bind(performance); +} else if(typeof process === "object" && process.hrtime) { v86.microtick = function() From cb0ca91f58bfcced47cf51b30cded5c19ceb0609 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 1 Oct 2018 20:57:47 -0300 Subject: [PATCH 1401/2137] Resolve some internal imports directly --- src/rust/cpu.rs | 17 ++++++----------- src/rust/cpu2/cpu.rs | 4 ++-- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/rust/cpu.rs b/src/rust/cpu.rs index cf76419c..a76c6666 100644 --- a/src/rust/cpu.rs +++ b/src/rust/cpu.rs @@ -1,16 +1,11 @@ // TODO: Make this an instance, so we can plug in a fake cpu +use cpu2; use page::Page; use state_flags::CachedStateFlags; mod unsafe_cpu { extern "C" { - pub fn tlb_set_has_code(physical_page: u32, has_code: bool); - pub fn read8(addr: u32) -> u8; - pub fn read16(addr: u32) -> u16; - pub fn read32s(addr: u32) -> u32; - pub fn check_tlb_invariants(); - pub fn codegen_finalize( wasm_table_index: u16, phys_addr: u32, @@ -29,15 +24,15 @@ pub enum BitSize { DWORD, } -pub fn read8(addr: u32) -> u8 { unsafe { unsafe_cpu::read8(addr) } } -pub fn read16(addr: u32) -> u16 { unsafe { unsafe_cpu::read16(addr) } } -pub fn read32(addr: u32) -> u32 { unsafe { unsafe_cpu::read32s(addr) } } +pub fn read8(addr: u32) -> u8 { unsafe { cpu2::memory::read8(addr) as u8 } } +pub fn read16(addr: u32) -> u16 { unsafe { cpu2::memory::read16(addr) as u16 } } +pub fn read32(addr: u32) -> u32 { unsafe { cpu2::memory::read32s(addr) as u32 } } pub fn tlb_set_has_code(physical_page: Page, has_code: bool) { - unsafe { unsafe_cpu::tlb_set_has_code(physical_page.to_u32(), has_code) } + unsafe { cpu2::cpu::tlb_set_has_code(physical_page, has_code) } } -pub fn check_tlb_invariants() { unsafe { unsafe_cpu::check_tlb_invariants() } } +pub fn check_tlb_invariants() { unsafe { cpu2::cpu::check_tlb_invariants() } } pub fn codegen_finalize( wasm_table_index: u16, diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 86ec59ba..12d15067 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1034,8 +1034,8 @@ pub unsafe fn translate_address_write(address: i32) -> OrPageFault { } #[no_mangle] -pub unsafe fn tlb_set_has_code(physical_page: u32, has_code: bool) { - dbg_assert!(physical_page < (1 << 20) as u32); +pub unsafe fn tlb_set_has_code(physical_page: Page, has_code: bool) { + let physical_page = physical_page.to_u32(); for i in 0..valid_tlb_entries_count { let page: i32 = valid_tlb_entries[i as usize]; let entry: i32 = *tlb_data.offset(page as isize); From e149b9d372aa93e6d97aaee09568fdb7e04f595c Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 1 Oct 2018 21:02:35 -0300 Subject: [PATCH 1402/2137] Remove unused doc generation scripts --- docs/build.js | 16 ------- docs/template.md.ejs | 107 ------------------------------------------- 2 files changed, 123 deletions(-) delete mode 100755 docs/build.js delete mode 100644 docs/template.md.ejs diff --git a/docs/build.js b/docs/build.js deleted file mode 100755 index 3af6248c..00000000 --- a/docs/build.js +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env node - -var markdox = require("markdox"); - -var options = { - output: __dirname + "/api.md", - template: __dirname + "/template.md.ejs" -}; - -var files = [ - __dirname + "/../src/browser/starter.js", -]; - -markdox.process(files, options, function() { - console.log("Ok. %s written.", options.output); -}); diff --git a/docs/template.md.ejs b/docs/template.md.ejs deleted file mode 100644 index b03af236..00000000 --- a/docs/template.md.ejs +++ /dev/null @@ -1,107 +0,0 @@ -.]/g, ""); - str = str.replace(/[^a-z0-9_-]+/gi, "-"); - str = str.toLowerCase(); - - return str; -} - -docfiles.forEach(function(doc) -{ - doc.javadoc.forEach(function(comment) - { - var tags = comment.raw.tags; - - comment.tagsByType = comment.raw.tags.reduce(function(result, tag) - { - result[tag.type] = tag; - return result; - }, {}); - - comment.ignore = "ignore" in comment.tagsByType; - - if(comment.name && !comment.ignore) - { - if(comment.isMethod || comment.isFunction) - { - var args = comment.paramTags.map(function(c) - { - return c.joinedTypes + " " + c.name; - }).join(", "); - - var returnVal = ""; - - if(comment.returnTags[0]) - { - returnVal = " -> " + comment.returnTags[0].joinedTypes; - } - comment.args = args; - comment.returnVal = returnVal; - comment.longName = comment.name + "(" + comment.args + ")" + comment.returnVal; - - ?># \n" ?> - - From 8d6baff91c2578ec32325fae9cfed080ef7ba1fc Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 1 Oct 2018 23:43:53 -0300 Subject: [PATCH 1403/2137] Fix rustfmt --- src/rust/cpu2/instructions_0f.rs | 6 ++++-- src/rust/cpu2/misc_instr.rs | 6 ++++-- src/rust/jit.rs | 3 ++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index e1da1219..ba2387de 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -5216,7 +5216,8 @@ pub unsafe fn instr_0FF7_reg(r1: i32, r2: i32) { safe_write8( (addr as u32).wrapping_add(i) as i32, source.u8_0[i as usize] as i32, - ).unwrap(); + ) + .unwrap(); } } transition_fpu_to_mmx(); @@ -5235,7 +5236,8 @@ pub unsafe fn instr_660FF7_reg(r1: i32, r2: i32) { safe_write8( (addr as u32).wrapping_add(i) as i32, source.u8_0[i as usize] as i32, - ).unwrap(); + ) + .unwrap(); } } } diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index ca117f34..bc39dc68 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -344,7 +344,8 @@ pub unsafe fn fxsave(addr: i32) { safe_write64( addr + 32 + (i << 4), (*reg_mmx.offset(reg_index as isize)).i64_0[0], - ).unwrap(); + ) + .unwrap(); safe_write64(addr + 32 + (i << 4) | 8, 0).unwrap(); } } @@ -356,7 +357,8 @@ pub unsafe fn fxsave(addr: i32) { safe_write128( addr.wrapping_add(160).wrapping_add(i << 4) as i32, *reg_xmm.offset(i as isize), - ).unwrap(); + ) + .unwrap(); } } #[no_mangle] diff --git a/src/rust/jit.rs b/src/rust/jit.rs index bac0daa4..f9a32498 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -445,7 +445,8 @@ pub fn record_entry_point(ctx: &mut JitState, phys_address: u32) { .or_insert_with(|| { is_new = true; HashSet::new() - }).insert(offset_in_page); + }) + .insert(offset_in_page); if is_new { cpu::tlb_set_has_code(page, true); From fe8d462b6c1a6acf9967cdfc4bc9b3cd95e0500d Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 2 Oct 2018 12:41:58 -0300 Subject: [PATCH 1404/2137] Update readme --- Readme.md | 37 +++++++++++++++++++++++++----------- docker/debian-full/Readme.md | 9 +++++++++ 2 files changed, 35 insertions(+), 11 deletions(-) create mode 100644 docker/debian-full/Readme.md diff --git a/Readme.md b/Readme.md index 36250db0..008860b1 100644 --- a/Readme.md +++ b/Readme.md @@ -1,17 +1,32 @@ -[![Join the chat at https://gitter.im/copy/v86](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/copy/v86?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - - -Demos +Building - -- [Windows 98](https://copy.sh/v86/?profile=windows98) -- [Linux](https://copy.sh/v86/?profile=linux26) -- [Linux 3](https://copy.sh/v86/?profile=linux3) -- [KolibriOS](https://copy.sh/v86/?profile=kolibrios) -- [FreeDOS](https://copy.sh/v86/?profile=freedos) -- [Windows 1.01](https://copy.sh/v86/?profile=windows1) -- [Archlinux](https://copy.sh/v86/?profile=archlinux) +See `docker/test-image/Dockerfile` for a full setup on Debian. +You need: + +- java +- gcc, make, libc-i386 +- nasm, gdb and qemu (for running tests) +- rust-nightly with the wasm32-unknown-unknown target +- nodejs (a latest version is required, 10.11.0 is known to be working) + +Run `make all-debug` to build the debug build (at `debug.html`). +Run `make all` to build the optimized build (at `index.html`). + +Testing +- + +Run all tests: `make jshint rustfmt kvm-unit-test nasmtests nasmtests-force-jit expect-tests jitpagingtests qemutests rust-test tests` + +Creating a Linux image for use in v86 +- + +See `docker/debian-full/Readme.md`. + + +Below is the readme of the open-source version of v86 (not everything applies) += API examples - diff --git a/docker/debian-full/Readme.md b/docker/debian-full/Readme.md new file mode 100644 index 00000000..bcbbdfc9 --- /dev/null +++ b/docker/debian-full/Readme.md @@ -0,0 +1,9 @@ +You can build a Linux image for use with v86: + +1. Run `./build-container.sh` to build the Docker container (requires dockerd) +2. Run `./create-9p-from-container.sh` to extract the files for v86 from the Docker container (requires root) +3. Run `./build-state.js` to build a state image in order to skip the boot process + +Go to `debug.html?profile=debian` to start the generated container. + +You can modify the `Dockerfile` to customize the generated Linux image. From e33c8a85ae2257f4a75cc3eda5c37b3a545b8bd1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 2 Oct 2018 16:19:21 -0300 Subject: [PATCH 1405/2137] Remove fluxbox theme --- docker/debian-full/fluxbox/init | 2 +- .../Clearlooks/pixmaps/bullet-active.xpm | 32 ----- .../styles/Clearlooks/pixmaps/bullet.xpm | 22 --- .../Clearlooks/pixmaps/close-active.xpm | 28 ---- .../Clearlooks/pixmaps/close-inactive.xpm | 25 ---- .../Clearlooks/pixmaps/close-pressed.xpm | 19 --- .../styles/Clearlooks/pixmaps/label-focus.xpm | 28 ---- .../Clearlooks/pixmaps/label-unfocus.xpm | 28 ---- .../Clearlooks/pixmaps/maximize-active.xpm | 28 ---- .../Clearlooks/pixmaps/maximize-inactive.xpm | 25 ---- .../Clearlooks/pixmaps/maximize-pressed.xpm | 19 --- .../styles/Clearlooks/pixmaps/menu-active.xpm | 28 ---- .../styles/Clearlooks/pixmaps/menu-hilite.xpm | 37 ----- .../Clearlooks/pixmaps/menu-inactive.xpm | 25 ---- .../Clearlooks/pixmaps/menu-pressed.xpm | 19 --- .../Clearlooks/pixmaps/minimize-active.xpm | 28 ---- .../Clearlooks/pixmaps/minimize-inactive.xpm | 25 ---- .../Clearlooks/pixmaps/minimize-pressed.xpm | 19 --- .../Clearlooks/pixmaps/selected-active.xpm | 49 ------- .../styles/Clearlooks/pixmaps/selected.xpm | 49 ------- .../Clearlooks/pixmaps/shade-active.xpm | 28 ---- .../Clearlooks/pixmaps/shade-inactive.xpm | 25 ---- .../Clearlooks/pixmaps/shade-pressed.xpm | 19 --- .../pixmaps/shade-toggled-active.xpm | 28 ---- .../pixmaps/shade-toggled-inactive.xpm | 25 ---- .../pixmaps/shade-toggled-pressed.xpm | 19 --- .../Clearlooks/pixmaps/stick-active.xpm | 28 ---- .../Clearlooks/pixmaps/stick-inactive.xpm | 25 ---- .../Clearlooks/pixmaps/stick-pressed.xpm | 19 --- .../pixmaps/stick-toggled-active.xpm | 28 ---- .../pixmaps/stick-toggled-inactive.xpm | 25 ---- .../styles/Clearlooks/pixmaps/title-focus.xpm | 40 ------ .../Clearlooks/pixmaps/title-unfocus.xpm | 40 ------ .../pixmaps/toolbar-iconbar-focus.xpm | 44 ------ .../pixmaps/toolbar-iconbar-unfocus.xpm | 38 ------ .../Clearlooks/pixmaps/unselected-active.xpm | 19 --- .../styles/Clearlooks/pixmaps/unselected.xpm | 19 --- .../fluxbox/styles/Clearlooks/theme.cfg | 129 ------------------ 38 files changed, 1 insertion(+), 1132 deletions(-) delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/bullet-active.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/bullet.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-active.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-inactive.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-pressed.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/label-focus.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/label-unfocus.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-active.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-inactive.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-pressed.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-active.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-hilite.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-inactive.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-pressed.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-active.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-inactive.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-pressed.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/selected-active.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/selected.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-active.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-inactive.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-pressed.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-active.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-inactive.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-pressed.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-active.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-inactive.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-pressed.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-toggled-active.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-toggled-inactive.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/title-focus.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/title-unfocus.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/toolbar-iconbar-focus.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/toolbar-iconbar-unfocus.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/unselected-active.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/unselected.xpm delete mode 100644 docker/debian-full/fluxbox/styles/Clearlooks/theme.cfg diff --git a/docker/debian-full/fluxbox/init b/docker/debian-full/fluxbox/init index e4054272..e68efbde 100644 --- a/docker/debian-full/fluxbox/init +++ b/docker/debian-full/fluxbox/init @@ -3,7 +3,7 @@ session.menuFile: ~/.fluxbox/menu session.keyFile: ~/.fluxbox/keys -session.styleFile: ~/.fluxbox/styles/Clearlooks +#session.styleFile: ~/.fluxbox/styles/Clearlooks session.screen0.rootCommand: fbsetroot -solid black diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/bullet-active.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/bullet-active.xpm deleted file mode 100644 index ecff74f3..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/bullet-active.xpm +++ /dev/null @@ -1,32 +0,0 @@ -/* XPM */ -static char * bullet_active_xpm[] = { -"6 10 19 1", -" c None", -". c #CEDEF2", -"+ c #CFDFF2", -"@ c #CEDEF1", -"# c #FFFFFF", -"$ c #CDDDF1", -"% c #CDDDF2", -"& c #CFDEF2", -"* c #F7FAFD", -"= c #CCDCF1", -"- c #F7F9FD", -"; c #C9DAEF", -"> c #CBDBEF", -", c #C8D9EF", -"' c #C6D8EE", -") c #C7D8EE", -"! c #C6D7ED", -"~ c #C5D7ED", -"{ c #C5D7EE", -".+ ", -"@#. ", -" $#% ", -" &#$ ", -" *#=", -" -#;", -" >#, ", -" '#) ", -"!#' ", -"~{ "}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/bullet.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/bullet.xpm deleted file mode 100644 index 6515a9f7..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/bullet.xpm +++ /dev/null @@ -1,22 +0,0 @@ -/* XPM */ -static char * bullet_xpm[] = { -"12 12 7 1", -" c None", -". c #808080", -"+ c #7F7F7F", -"@ c #000000", -"# c #797979", -"$ c #131313", -"% c #787878", -" ", -" .+ ", -" .@+ ", -" .@+ ", -" #@+ ", -" $@+ ", -" $@+ ", -" %@+ ", -" .@+ ", -" .@+ ", -" .+ ", -" "}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-active.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-active.xpm deleted file mode 100644 index 9b5f38a1..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-active.xpm +++ /dev/null @@ -1,28 +0,0 @@ -/* XPM */ -static char * close_active_xpm[] = { -"12 12 13 1", -" c None", -". c #49678B", -"+ c #ADC7E9", -"@ c #A7C3E7", -"# c #A1BFE5", -"$ c #F4F5F6", -"% c #9BBAE2", -"& c #90B2DE", -"* c #86ABD9", -"= c #84AAD8", -"- c #82A8D6", -"; c #7FA6D5", -"> c #7CA4D3", -"............", -".++++++++++.", -".@@@@@@@@@@.", -".##$$##$$##.", -".%%$$$$$$%%.", -".&&&$$$$&&&.", -".***$$$$***.", -".==$$$$$$==.", -".--$$--$$--.", -".;;;;;;;;;;.", -".>>>>>>>>>>.", -"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-inactive.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-inactive.xpm deleted file mode 100644 index 0ce800e4..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-inactive.xpm +++ /dev/null @@ -1,25 +0,0 @@ -/* XPM */ -static char * close_inactive_xpm[] = { -"12 12 10 1", -" c None", -". c #928F8B", -"+ c #FFFFFF", -"@ c #6D6C6C", -"# c #FEFDFD", -"$ c #F9F8F8", -"% c #FAF9F9", -"& c #FBFAFA", -"* c #FCFBFB", -"= c #FDFDFD", -"............", -".++++++++++.", -".++++++++++.", -".++@@++@@++.", -".++@@@@@@++.", -".###@@@@###.", -".$$$@@@@$$$.", -".%%@@@@@@%%.", -".&&@@&&@@&&.", -".**********.", -".==========.", -"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-pressed.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-pressed.xpm deleted file mode 100644 index 5f39960c..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/close-pressed.xpm +++ /dev/null @@ -1,19 +0,0 @@ -/* XPM */ -static char * close_pressed_xpm[] = { -"12 12 4 1", -" c None", -". c #49678B", -"+ c #7AA1D2", -"@ c #F4F5F6", -"............", -".++++++++++.", -".++++++++++.", -".++@@++@@++.", -".++@@@@@@++.", -".+++@@@@+++.", -".+++@@@@+++.", -".++@@@@@@++.", -".++@@++@@++.", -".++++++++++.", -".++++++++++.", -"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/label-focus.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/label-focus.xpm deleted file mode 100644 index f1424dab..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/label-focus.xpm +++ /dev/null @@ -1,28 +0,0 @@ -/* XPM */ -static char * label_focus_xpm[] = { -"1 12 13 1", -" c None", -". c #94B6E0", -"+ c #93B5DF", -"@ c #91B4DF", -"# c #90B3DE", -"$ c #8EB1DD", -"% c #8BAFDB", -"& c #86ABD9", -"* c #85AAD8", -"= c #84A9D7", -"- c #82A8D6", -"; c #81A7D5", -"> c #80A6D5", -".", -"+", -"@", -"#", -"$", -"%", -"&", -"*", -"=", -"-", -";", -">"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/label-unfocus.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/label-unfocus.xpm deleted file mode 100644 index 5dbc311d..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/label-unfocus.xpm +++ /dev/null @@ -1,28 +0,0 @@ -/* XPM */ -static char * label_unfocus_xpm[] = { -"1 12 13 1", -" c None", -". c #E8E7E6", -"+ c #E7E6E5", -"@ c #E6E5E3", -"# c #E5E4E2", -"$ c #E4E3E1", -"% c #E2E1DF", -"& c #DEDCDA", -"* c #DDDBD9", -"= c #DCDAD8", -"- c #DBD9D7", -"; c #DAD8D6", -"> c #D9D7D5", -".", -"+", -"@", -"#", -"$", -"%", -"&", -"*", -"=", -"-", -";", -">"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-active.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-active.xpm deleted file mode 100644 index 6ff48713..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-active.xpm +++ /dev/null @@ -1,28 +0,0 @@ -/* XPM */ -static char * maximize_active_xpm[] = { -"12 12 13 1", -" c None", -". c #49678B", -"+ c #ADC7E9", -"@ c #A7C3E7", -"# c #A1BFE5", -"$ c #F4F5F6", -"% c #9BBAE2", -"& c #90B2DE", -"* c #86ABD9", -"= c #84AAD8", -"- c #82A8D6", -"; c #7FA6D5", -"> c #7CA4D3", -"............", -".++++++++++.", -".@@@@@@@@@@.", -".##$$$$$$##.", -".%%$$$$$$%%.", -".&&$&&&&$&&.", -".**$****$**.", -".==$====$==.", -".--$$$$$$--.", -".;;;;;;;;;;.", -".>>>>>>>>>>.", -"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-inactive.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-inactive.xpm deleted file mode 100644 index 6e9e17ad..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-inactive.xpm +++ /dev/null @@ -1,25 +0,0 @@ -/* XPM */ -static char * maximize_inactive_xpm[] = { -"12 12 10 1", -" c None", -". c #928F8B", -"+ c #FFFFFF", -"@ c #6D6C6C", -"# c #FEFDFD", -"$ c #F9F8F8", -"% c #FAF9F9", -"& c #FBFAFA", -"* c #FCFBFB", -"= c #FDFDFD", -"............", -".++++++++++.", -".++++++++++.", -".++@@@@@@++.", -".++@@@@@@++.", -".##@####@##.", -".$$@$$$$@$$.", -".%%@%%%%@%%.", -".&&@@@@@@&&.", -".**********.", -".==========.", -"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-pressed.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-pressed.xpm deleted file mode 100644 index f670fb28..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/maximize-pressed.xpm +++ /dev/null @@ -1,19 +0,0 @@ -/* XPM */ -static char * maximize_pressed_xpm[] = { -"12 12 4 1", -" c None", -". c #49678B", -"+ c #7AA1D2", -"@ c #F4F5F6", -"............", -".++++++++++.", -".++++++++++.", -".++@@@@@@++.", -".++@@@@@@++.", -".++@++++@++.", -".++@++++@++.", -".++@++++@++.", -".++@@@@@@++.", -".++++++++++.", -".++++++++++.", -"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-active.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-active.xpm deleted file mode 100644 index f4eac268..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-active.xpm +++ /dev/null @@ -1,28 +0,0 @@ -/* XPM */ -static char * menu_active_xpm[] = { -"12 12 13 1", -" c None", -". c #49678B", -"+ c #ADC7E9", -"@ c #A7C3E7", -"# c #A1BFE5", -"$ c #F4F5F6", -"% c #9BBAE2", -"& c #90B2DE", -"* c #86ABD9", -"= c #84AAD8", -"- c #82A8D6", -"; c #7FA6D5", -"> c #7CA4D3", -"............", -".++++++++++.", -".@@@@@@@@@@.", -".####$$####.", -".%%%%$$%%%%.", -".&&$$$$$$&&.", -".**$$$$$$**.", -".====$$====.", -".----$$----.", -".;;;;;;;;;;.", -".>>>>>>>>>>.", -"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-hilite.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-hilite.xpm deleted file mode 100644 index 9f3bae85..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-hilite.xpm +++ /dev/null @@ -1,37 +0,0 @@ -/* XPM */ -static char * menu_hilite_xpm[] = { -"1 17 17 1", -" c None", -". c #4B6E99", -"+ c #A6C4E8", -"@ c #A4C2E7", -"# c #A2C0E6", -"$ c #A0BFE5", -"% c #9EBDE5", -"& c #9CBCE4", -"* c #9ABAE3", -"= c #96B7E1", -"- c #91B3DE", -"; c #8FB2DD", -"> c #8DB0DC", -", c #8BAFDB", -"' c #89ADDA", -") c #87ACD9", -"! c #85AAD8", -".", -"+", -"@", -"#", -"$", -"%", -"&", -"*", -"=", -"-", -";", -">", -",", -"'", -")", -"!", -"."}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-inactive.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-inactive.xpm deleted file mode 100644 index f3b07db0..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-inactive.xpm +++ /dev/null @@ -1,25 +0,0 @@ -/* XPM */ -static char * menu_inactive_xpm[] = { -"12 12 10 1", -" c None", -". c #928F8B", -"+ c #FFFFFF", -"@ c #6D6C6C", -"# c #FEFDFD", -"$ c #F9F8F8", -"% c #FAF9F9", -"& c #FBFAFA", -"* c #FCFBFB", -"= c #FDFDFD", -"............", -".++++++++++.", -".++++++++++.", -".++++@@++++.", -".++++@@++++.", -".##@@@@@@##.", -".$$@@@@@@$$.", -".%%%%@@%%%%.", -".&&&&@@&&&&.", -".**********.", -".==========.", -"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-pressed.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-pressed.xpm deleted file mode 100644 index 0cab5b9e..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/menu-pressed.xpm +++ /dev/null @@ -1,19 +0,0 @@ -/* XPM */ -static char * menu_pressed_xpm[] = { -"12 12 4 1", -" c None", -". c #49678B", -"+ c #7AA1D2", -"@ c #F4F5F6", -"............", -".++++++++++.", -".++++++++++.", -".++++@@++++.", -".++++@@++++.", -".++@@@@@@++.", -".++@@@@@@++.", -".++++@@++++.", -".++++@@++++.", -".++++++++++.", -".++++++++++.", -"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-active.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-active.xpm deleted file mode 100644 index dc6c9ec7..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-active.xpm +++ /dev/null @@ -1,28 +0,0 @@ -/* XPM */ -static char * hide_active_xpm[] = { -"12 12 13 1", -" c None", -". c #49678B", -"+ c #ADC7E9", -"@ c #A7C3E7", -"# c #A1BFE5", -"$ c #9BBAE2", -"% c #90B2DE", -"& c #86ABD9", -"* c #84AAD8", -"= c #FFFFFF", -"- c #82A8D6", -"; c #7FA6D5", -"> c #7CA4D3", -"............", -".++++++++++.", -".@@@@@@@@@@.", -".##########.", -".$$$$$$$$$$.", -".%%%%%%%%%%.", -".&&&&&&&&&&.", -".**======**.", -".--======--.", -".;;;;;;;;;;.", -".>>>>>>>>>>.", -"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-inactive.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-inactive.xpm deleted file mode 100644 index 8551a432..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-inactive.xpm +++ /dev/null @@ -1,25 +0,0 @@ -/* XPM */ -static char * hide_inactive_xpm[] = { -"12 12 10 1", -" c None", -". c #928F8B", -"+ c #FFFFFF", -"@ c #FEFDFD", -"# c #F9F8F8", -"$ c #FAF9F9", -"% c #6D6C6C", -"& c #FBFAFA", -"* c #FCFBFB", -"= c #FDFDFD", -"............", -".++++++++++.", -".++++++++++.", -".++++++++++.", -".++++++++++.", -".@@@@@@@@@@.", -".##########.", -".$$%%%%%%$$.", -".&&%%%%%%&&.", -".**********.", -".==========.", -"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-pressed.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-pressed.xpm deleted file mode 100644 index 3474dac0..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/minimize-pressed.xpm +++ /dev/null @@ -1,19 +0,0 @@ -/* XPM */ -static char * hide_pressed_xpm[] = { -"12 12 4 1", -" c None", -". c #49678B", -"+ c #7AA1D2", -"@ c #F4F5F6", -"............", -".++++++++++.", -".++++++++++.", -".++++++++++.", -".++++++++++.", -".++++++++++.", -".++++++++++.", -".++@@@@@@++.", -".++@@@@@@++.", -".++++++++++.", -".++++++++++.", -"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/selected-active.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/selected-active.xpm deleted file mode 100644 index e67ad166..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/selected-active.xpm +++ /dev/null @@ -1,49 +0,0 @@ -/* XPM */ -static char * selected_active_xpm[] = { -"13 13 33 1", -" c None", -". c #4B6E99", -"+ c #C9DAEF", -"@ c #BDCDE0", -"# c #53585F", -"$ c #AEBDCE", -"% c #BACADD", -"& c #36393C", -"* c #1A1A1A", -"= c #717A84", -"- c #C7D7EC", -"; c #414549", -"> c #767F8A", -", c #A9B7C8", -"' c #939EAD", -") c #7B8590", -"! c #606770", -"~ c #C6D7EB", -"{ c #373A3D", -"] c #1D1D1E", -"^ c #909BA9", -"/ c #B8C8DB", -"( c #222223", -"_ c #2E3032", -": c #C1D1E5", -"< c #292A2C", -"[ c #1E1E1F", -"} c #484C52", -"| c #8D98A6", -"1 c #2F3133", -"2 c #28292B", -"3 c #767F8B", -"4 c #B4C2D5", -".............", -".+++++++++++.", -".+++++++@#$+.", -".++++++%&*=+.", -".+++++-;*>++.", -".+,'++)*!+++.", -".~{]^/(_:+++.", -".+,<[}*|++++.", -".++,<*1~++++.", -".+++,23+++++.", -".++++,4+++++.", -".+++++++++++.", -"............."}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/selected.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/selected.xpm deleted file mode 100644 index d22783f7..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/selected.xpm +++ /dev/null @@ -1,49 +0,0 @@ -/* XPM */ -static char * selected_xpm[] = { -"13 13 33 1", -" c None", -". c #797979", -"+ c #FFFFFF", -"@ c #EFEFEF", -"# c #646464", -"$ c #DCDCDC", -"% c #ECECEC", -"& c #3F3F3F", -"* c #1A1A1A", -"= c #8C8C8C", -"- c #FCFCFC", -"; c #4D4D4D", -"> c #929292", -", c #D5D5D5", -"' c #B8B8B8", -") c #999999", -"! c #767676", -"~ c #FBFBFB", -"{ c #404040", -"] c #1E1E1E", -"^ c #B4B4B4", -"/ c #E9E9E9", -"( c #242424", -"_ c #343434", -": c #F4F4F4", -"< c #2D2D2D", -"[ c #1F1F1F", -"} c #565656", -"| c #B0B0B0", -"1 c #353535", -"2 c #2C2C2C", -"3 c #939393", -"4 c #E3E3E3", -".............", -".+++++++++++.", -".+++++++@#$+.", -".++++++%&*=+.", -".+++++-;*>++.", -".+,'++)*!+++.", -".~{]^/(_:+++.", -".+,<[}*|++++.", -".++,<*1~++++.", -".+++,23+++++.", -".++++,4+++++.", -".+++++++++++.", -"............."}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-active.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-active.xpm deleted file mode 100644 index 07a3e607..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-active.xpm +++ /dev/null @@ -1,28 +0,0 @@ -/* XPM */ -static char * shade_active_xpm[] = { -"12 12 13 1", -" c None", -". c #49678B", -"+ c #ADC7E9", -"@ c #A7C3E7", -"# c #A1BFE5", -"$ c #F4F5F6", -"% c #9BBAE2", -"& c #90B2DE", -"* c #86ABD9", -"= c #84AAD8", -"- c #82A8D6", -"; c #7FA6D5", -"> c #7CA4D3", -"............", -".++++++++++.", -".@@@@@@@@@@.", -".##$$$$$$##.", -".%%$$$$$$%%.", -".&&&&&&&&&&.", -".**********.", -".==========.", -".----------.", -".;;;;;;;;;;.", -".>>>>>>>>>>.", -"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-inactive.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-inactive.xpm deleted file mode 100644 index 8c8e5ba8..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-inactive.xpm +++ /dev/null @@ -1,25 +0,0 @@ -/* XPM */ -static char * shade_inactive_xpm[] = { -"12 12 10 1", -" c None", -". c #928F8B", -"+ c #FFFFFF", -"@ c #6D6C6C", -"# c #FEFDFD", -"$ c #F9F8F8", -"% c #FAF9F9", -"& c #FBFAFA", -"* c #FCFBFB", -"= c #FDFDFD", -"............", -".++++++++++.", -".++++++++++.", -".++@@@@@@++.", -".++@@@@@@++.", -".##########.", -".$$$$$$$$$$.", -".%%%%%%%%%%.", -".&&&&&&&&&&.", -".**********.", -".==========.", -"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-pressed.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-pressed.xpm deleted file mode 100644 index 33d539fe..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-pressed.xpm +++ /dev/null @@ -1,19 +0,0 @@ -/* XPM */ -static char * shade_pressed_xpm[] = { -"12 12 4 1", -" c None", -". c #49678B", -"+ c #7AA1D2", -"@ c #F4F5F6", -"............", -".++++++++++.", -".++++++++++.", -".++@@@@@@++.", -".++@@@@@@++.", -".++++++++++.", -".++++++++++.", -".++++++++++.", -".++++++++++.", -".++++++++++.", -".++++++++++.", -"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-active.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-active.xpm deleted file mode 100644 index 675a0ba0..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-active.xpm +++ /dev/null @@ -1,28 +0,0 @@ -/* XPM */ -static char * shade_toggled_active_xpm[] = { -"12 12 13 1", -" c None", -". c #49678B", -"+ c #ADC7E9", -"@ c #A7C3E7", -"# c #A1BFE5", -"$ c #F4F5F6", -"% c #9BBAE2", -"& c #90B2DE", -"* c #86ABD9", -"= c #84AAD8", -"- c #82A8D6", -"; c #7FA6D5", -"> c #7CA4D3", -"............", -".++++++++++.", -".@@@@@@@@@@.", -".##$$$$$$##.", -".%%$$$$$$%%.", -".&&&&&&&&&&.", -".***$$$$***.", -".====$$====.", -".----------.", -".;;;;;;;;;;.", -".>>>>>>>>>>.", -"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-inactive.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-inactive.xpm deleted file mode 100644 index 14069b0f..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-inactive.xpm +++ /dev/null @@ -1,25 +0,0 @@ -/* XPM */ -static char * shade_toggled_inactive_xpm[] = { -"12 12 10 1", -" c None", -". c #928F8B", -"+ c #FFFFFF", -"@ c #6D6C6C", -"# c #FEFDFD", -"$ c #F9F8F8", -"% c #FAF9F9", -"& c #FBFAFA", -"* c #FCFBFB", -"= c #FDFDFD", -"............", -".++++++++++.", -".++++++++++.", -".++@@@@@@++.", -".++@@@@@@++.", -".##########.", -".$$$@@@@$$$.", -".%%%%@@%%%%.", -".&&&&&&&&&&.", -".**********.", -".==========.", -"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-pressed.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-pressed.xpm deleted file mode 100644 index e97d62e0..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/shade-toggled-pressed.xpm +++ /dev/null @@ -1,19 +0,0 @@ -/* XPM */ -static char * shade_toggled_pressed_xpm[] = { -"12 12 4 1", -" c None", -". c #49678B", -"+ c #7AA1D2", -"@ c #F4F5F6", -"............", -".++++++++++.", -".++++++++++.", -".++@@@@@@++.", -".++@@@@@@++.", -".++++++++++.", -".+++@@@@+++.", -".++++@@++++.", -".++++++++++.", -".++++++++++.", -".++++++++++.", -"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-active.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-active.xpm deleted file mode 100644 index 7b5c1147..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-active.xpm +++ /dev/null @@ -1,28 +0,0 @@ -/* XPM */ -static char * stick_active_xpm[] = { -"12 12 13 1", -" c None", -". c #49678B", -"+ c #ADC7E9", -"@ c #A7C3E7", -"# c #A1BFE5", -"$ c #F4F5F6", -"% c #9BBAE2", -"& c #90B2DE", -"* c #86ABD9", -"= c #84AAD8", -"- c #82A8D6", -"; c #7FA6D5", -"> c #7CA4D3", -"............", -".++++++++++.", -".@@@@@@@@@@.", -".##$$##$$##.", -".%%$$%%$$%%.", -".&&&&&&&&&&.", -".**********.", -".==$$==$$==.", -".--$$--$$--.", -".;;;;;;;;;;.", -".>>>>>>>>>>.", -"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-inactive.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-inactive.xpm deleted file mode 100644 index 7d63a5d7..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-inactive.xpm +++ /dev/null @@ -1,25 +0,0 @@ -/* XPM */ -static char * stick_inactive_xpm[] = { -"12 12 10 1", -" c None", -". c #928F8B", -"+ c #FFFFFF", -"@ c #6D6C6C", -"# c #FEFDFD", -"$ c #F9F8F8", -"% c #FAF9F9", -"& c #FBFAFA", -"* c #FCFBFB", -"= c #FDFDFD", -"............", -".++++++++++.", -".++++++++++.", -".++@@++@@++.", -".++@@++@@++.", -".##########.", -".$$$$$$$$$$.", -".%%@@%%@@%%.", -".&&@@&&@@&&.", -".**********.", -".==========.", -"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-pressed.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-pressed.xpm deleted file mode 100644 index 01af6c17..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-pressed.xpm +++ /dev/null @@ -1,19 +0,0 @@ -/* XPM */ -static char * stick_pressed_xpm[] = { -"12 12 4 1", -" c None", -". c #49678B", -"+ c #7AA1D2", -"@ c #F4F5F6", -"............", -".++++++++++.", -".++++++++++.", -".++@@++@@++.", -".++@@++@@++.", -".++++++++++.", -".++++++++++.", -".++@@++@@++.", -".++@@++@@++.", -".++++++++++.", -".++++++++++.", -"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-toggled-active.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-toggled-active.xpm deleted file mode 100644 index 745312e9..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-toggled-active.xpm +++ /dev/null @@ -1,28 +0,0 @@ -/* XPM */ -static char * stick_toggled_active_xpm[] = { -"12 12 13 1", -" c None", -". c #49678B", -"+ c #ADC7E9", -"@ c #A7C3E7", -"# c #A1BFE5", -"$ c #9BBAE2", -"% c #F4F5F6", -"& c #90B2DE", -"* c #86ABD9", -"= c #84AAD8", -"- c #82A8D6", -"; c #7FA6D5", -"> c #7CA4D3", -"............", -".++++++++++.", -".@@@@@@@@@@.", -".##########.", -".$$$%%%%$$$.", -".&&&%&%%&&&.", -".***%%*%***.", -".===%%%%===.", -".----------.", -".;;;;;;;;;;.", -".>>>>>>>>>>.", -"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-toggled-inactive.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-toggled-inactive.xpm deleted file mode 100644 index e644facc..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/stick-toggled-inactive.xpm +++ /dev/null @@ -1,25 +0,0 @@ -/* XPM */ -static char * stick_toggled_inactive_xpm[] = { -"12 12 10 1", -" c None", -". c #928F8B", -"+ c #FFFFFF", -"@ c #6D6C6C", -"# c #FEFDFD", -"$ c #F9F8F8", -"% c #FAF9F9", -"& c #FBFAFA", -"* c #FCFBFB", -"= c #FDFDFD", -"............", -".++++++++++.", -".++++++++++.", -".++++++++++.", -".+++@@@@+++.", -".###@#@@###.", -".$$$@@$@$$$.", -".%%%@@@@%%%.", -".&&&&&&&&&&.", -".**********.", -".==========.", -"............"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/title-focus.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/title-focus.xpm deleted file mode 100644 index 6371404a..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/title-focus.xpm +++ /dev/null @@ -1,40 +0,0 @@ -/* XPM */ -static char * title_focus_xpm[] = { -"1 18 19 1", -" c None", -". c #ADD3FF", -"+ c #98B9E2", -"@ c #96B8E1", -"# c #94B6E0", -"$ c #93B5DF", -"% c #91B4DF", -"& c #90B3DE", -"* c #8EB1DD", -"= c #8BAFDB", -"- c #86ABD9", -"; c #85AAD8", -"> c #84A9D7", -", c #82A8D6", -"' c #81A7D5", -") c #80A6D5", -"! c #7EA4D4", -"~ c #7DA3D3", -"{ c #7A9FCE", -".", -"+", -"@", -"#", -"$", -"%", -"&", -"*", -"=", -"-", -";", -">", -",", -"'", -")", -"!", -"~", -"{"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/title-unfocus.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/title-unfocus.xpm deleted file mode 100644 index 3fa23d1a..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/title-unfocus.xpm +++ /dev/null @@ -1,40 +0,0 @@ -/* XPM */ -static char * title_unfocus_xpm[] = { -"1 18 19 1", -" c None", -". c #FFFFFF", -"+ c #EAE9E8", -"@ c #E9E8E7", -"# c #E8E7E6", -"$ c #E7E6E5", -"% c #E6E5E3", -"& c #E5E4E2", -"* c #E4E3E1", -"= c #E2E1DF", -"- c #DEDCDA", -"; c #DDDBD9", -"> c #DCDAD8", -", c #DBD9D7", -"' c #DAD8D6", -") c #D9D7D5", -"! c #D8D6D4", -"~ c #D7D5D3", -"{ c #D2D0CE", -".", -"+", -"@", -"#", -"$", -"%", -"&", -"*", -"=", -"-", -";", -">", -",", -"'", -")", -"!", -"~", -"{"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/toolbar-iconbar-focus.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/toolbar-iconbar-focus.xpm deleted file mode 100644 index 9d1cf257..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/toolbar-iconbar-focus.xpm +++ /dev/null @@ -1,44 +0,0 @@ -/* XPM */ -static char * toolbar_iconbar_focus_xpm[] = { -"1 20 21 1", -" c None", -". c #CCC9C7", -"+ c #D1CFCC", -"@ c #D6D3D1", -"# c #D6D4D2", -"$ c #D5D3D1", -"% c #D4D2D0", -"& c #D3D1CF", -"* c #D2D0CE", -"= c #D0CECC", -"- c #CFCDCB", -"; c #CAC8C5", -"> c #C9C7C4", -", c #C8C6C3", -"' c #C7C4C1", -") c #C6C3C0", -"! c #C4C2BF", -"~ c #C3C1BE", -"{ c #C2C0BD", -"] c #C1BEBB", -"^ c #C0BDBA", -".", -"+", -"@", -"#", -"$", -"%", -"&", -"*", -"=", -"-", -";", -">", -",", -"'", -")", -"!", -"~", -"{", -"]", -"^"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/toolbar-iconbar-unfocus.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/toolbar-iconbar-unfocus.xpm deleted file mode 100644 index 9fc1446f..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/toolbar-iconbar-unfocus.xpm +++ /dev/null @@ -1,38 +0,0 @@ -/* XPM */ -static char * toolbar_iconbar_unfocus_xpm[] = { -"1 20 15 1", -" c None", -". c #FEFEFE", -"+ c #FDFDFD", -"@ c #FCFCFC", -"# c #FBFBFB", -"$ c #F5F5F4", -"% c #F3F3F2", -"& c #F2F2F1", -"* c #F1F0EF", -"= c #EFEFEE", -"- c #EEEDEC", -"; c #ECECEB", -"> c #EBEAE9", -", c #EAE9E8", -"' c #E8E7E6", -".", -".", -".", -"+", -"+", -"@", -"@", -"@", -"#", -"#", -"$", -"%", -"&", -"*", -"=", -"-", -";", -">", -",", -"'"}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/unselected-active.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/unselected-active.xpm deleted file mode 100644 index 09d95cfc..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/unselected-active.xpm +++ /dev/null @@ -1,19 +0,0 @@ -/* XPM */ -static char * unselected_active_xpm[] = { -"13 13 3 1", -" c None", -". c #4B6E99", -"+ c #C9DAEF", -".............", -".+++++++++++.", -".+++++++++++.", -".+++++++++++.", -".+++++++++++.", -".+++++++++++.", -".+++++++++++.", -".+++++++++++.", -".+++++++++++.", -".+++++++++++.", -".+++++++++++.", -".+++++++++++.", -"............."}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/unselected.xpm b/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/unselected.xpm deleted file mode 100644 index f05df80b..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/pixmaps/unselected.xpm +++ /dev/null @@ -1,19 +0,0 @@ -/* XPM */ -static char * unselected_xpm[] = { -"13 13 3 1", -" c None", -". c #797979", -"+ c #FFFFFF", -".............", -".+++++++++++.", -".+++++++++++.", -".+++++++++++.", -".+++++++++++.", -".+++++++++++.", -".+++++++++++.", -".+++++++++++.", -".+++++++++++.", -".+++++++++++.", -".+++++++++++.", -".+++++++++++.", -"............."}; diff --git a/docker/debian-full/fluxbox/styles/Clearlooks/theme.cfg b/docker/debian-full/fluxbox/styles/Clearlooks/theme.cfg deleted file mode 100644 index 4a936075..00000000 --- a/docker/debian-full/fluxbox/styles/Clearlooks/theme.cfg +++ /dev/null @@ -1,129 +0,0 @@ -! vim: set ft=xdefaults: -! Clearlooks theme, port from Openbox -! 29.04.2012 - -! Menu -menu.bevelWidth: 0 -menu.borderWidth: 1 -menu.borderColor: #AAAAAA -menu.bullet: empty -menu.submenu.pixmap: bullet.xpm -menu.hilite.submenu.pixmap: bullet-active.xpm -menu.selected.pixmap: selected.xpm -menu.hilite.selected.pixmap: selected-active.xpm -menu.unselected.pixmap: unselected.xpm -menu.hilite.unselected.pixmap: unselected-active.xpm -menu.bullet.position: right -menu.itemHeight: 17 -menu.title: flat -menu.title.justify: Center -menu.title.color: #E6E7E6 -menu.title.textColor: #111111 -menu.titleHeight: 17 -menu.frame: flat -menu.frame.justify: left -menu.frame.color: #FFFFFF -menu.frame.textColor: #111111 -menu.frame.disableColor: #AAAAAA -menu.hilite.pixmap: menu-hilite.xpm -menu.hilite.textColor: #FFFFFF - -! Window -window.bevelWidth: 3 -window.borderWidth: 1 -window.borderColor: #585A5D -window.title.height: 18 -window.justify: right -window.label.focus: ParentRelative -window.label.unfocus: ParentRelative -#window.label.focus.pixmap: label-focus.xpm -#window.label.unfocus.pixmap: label-unfocus.xpm -window.label.focus.textColor: #FFFFFF -window.label.unfocus.textColor: #70747D -window.title.focus.pixmap: title-focus.xpm -window.title.unfocus.pixmap: title-unfocus.xpm -window.handleWidth: 0 -window.handle.focus: flat -window.handle.focus.color: #EAEBEC -window.handle.unfocus: flat -window.handle.unfocus.color: #EAEBEC -window.grip.focus: flat -window.grip.focus.color: #EAEBEC -window.grip.unfocus: flat -window.grip.unfocus.color: #EAEBEC -window.close.pixmap: close-active.xpm -window.close.pressed.pixmap: close-pressed.xpm -window.close.unfocus.pixmap: close-inactive.xpm -window.iconify.pixmap: minimize-active.xpm -window.iconify.pressed.pixmap: minimize-pressed.xpm -window.iconify.unfocus.pixmap: minimize-inactive.xpm -window.maximize.pixmap: maximize-active.xpm -window.maximize.pressed.pixmap: maximize-pressed.xpm -window.maximize.unfocus.pixmap: maximize-inactive.xpm -window.menuicon.pixmap: menu-active.xpm -window.menuicon.pressed.pixmap: menu-pressed.xpm -window.menuicon.unfocus.pixmap: menu-inactive.xpm -window.shade.pixmap: shade-active.xpm -window.shade.unfocus.pixmap: shade-inactive.xpm -window.shade.pressed.pixmap: shade-pressed.xpm -window.unshade.pixmap: shade-toggled-active.xpm -window.unshade.unfocus.pixmap: shade-toggled-inactive.xpm -window.unshade.pressed.pixmap: shade-toggled-pressed.xpm -window.stick.pixmap: stick-active.xpm -window.stick.unfocus.pixmap: stick-inactive.xpm -window.stick.pressed.pixmap: stick-pressed.xpm -window.stuck.pixmap: stick-toggled-active.xpm -window.stuck.unfocus.pixmap: stick-toggled-inactive.xpm - -! Toolbar -toolbar.bevelWidth: 1 -toolbar.borderWidth: 1 -toolbar.borderColor: #585A5D -toolbar.height: 20 -toolbar: flat -toolbar.color: #EAEBEC -toolbar.clock: flat -toolbar.clock.borderWidth: 0 -toolbar.clock.borderColor: #A9A5A2 -toolbar.clock.justify: center -toolbar.clock.textColor: #111111 -toolbar.clock.color: #EDECEB -toolbar.systray: flat -toolbar.systray.borderWidth: 0 -toolbar.systray.borderColor: #A9A5A2 -toolbar.systray.color: #EDECEB -toolbar.workspace: flat -toolbar.workspace.borderWidth: 0 -toolbar.workspace.borderColor: #A9A5A2 -toolbar.workspace.justify: center -toolbar.workspace.textColor: #111111 -toolbar.workspace.color: #EDECEB -toolbar.button: flat -toolbar.button.borderWidth: 0 -toolbar.button.borderColor: #A9A5A2 -toolbar.button.picColor: #111111 -toolbar.button.color: #EDECEB -toolbar.button.pressed.picColor: #111111 -toolbar.button.pressed.color: #CFCDCB -toolbar.iconbar.empty: flat -toolbar.iconbar.empty.color: #EDECEB -toolbar.iconbar.focused.pixmap: toolbar-iconbar-focus.xpm -toolbar.iconbar.focused.borderWidth: 1 -toolbar.iconbar.focused.borderColor: #A9A5A2 -toolbar.iconbar.focused.justify: center -toolbar.iconbar.focused.textColor: #111111 -toolbar.iconbar.unfocused.pixmap: toolbar-iconbar-unfocus.xpm -toolbar.iconbar.unfocused.borderWidth: 1 -toolbar.iconbar.unfocused.borderColor: #A9A5A2 -toolbar.iconbar.unfocused.justify: center -toolbar.iconbar.unfocused.textColor: #111111 - -! Slit -slit: flat -slit.bevelWidth: 0 -slit.borderColor: #585A5D -slit.borderWidth: 1 -slit.color: #EDECEB - -! Font -*.font: Sans-8 From 148be5352538f524b7b8cd9057236f1bff1229b8 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 2 Oct 2018 18:53:14 -0300 Subject: [PATCH 1406/2137] Try fixing nasmtests hang for gdb 8.2 --- tests/nasm/gen_fixtures.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/nasm/gen_fixtures.js b/tests/nasm/gen_fixtures.js index 883dfc6a..357999bc 100755 --- a/tests/nasm/gen_fixtures.js +++ b/tests/nasm/gen_fixtures.js @@ -120,7 +120,7 @@ for(let i = 0; i < nr_of_cpus; i++) console.log(CYAN_FMT, "[DEBUG]", "gdb", gdb_args.join(" ")); } - if(SYNC_GDB_EXECUTION) + if(SYNC_GDB_EXECUTION || nr_of_cpus === 1) { const { status: code } = spawnSync("gdb", gdb_args); on_proc_close(code, i); From 753fcb25c703e9901e848ae8a959a0eab8dc6fe9 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 4 Oct 2018 00:20:37 -0300 Subject: [PATCH 1407/2137] Simplify multiboot buffer during init --- src/browser/starter.js | 2 +- src/cpu.js | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 2a46f20f..4f1c3642 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -297,7 +297,7 @@ V86Starter.prototype.continue_init = function(emulator, options) break; case "multiboot": - settings.multiboot = this.disk_images["multiboot"] = buffer; + settings.multiboot = this.disk_images["multiboot"] = buffer.buffer; break; case "bios": diff --git a/src/cpu.js b/src/cpu.js index 6a072d28..d9a9a6ba 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -860,8 +860,7 @@ CPU.prototype.init = function(settings, device_bus) if(settings.multiboot) { - dbg_assert(settings.multiboot.buffer); - this.load_multiboot(settings.multiboot.buffer); + this.load_multiboot(settings.multiboot); } if(DEBUG) From 04d282c298e9e726969a433b9fe8dbf9fe6058b8 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 5 Oct 2018 16:43:44 -0300 Subject: [PATCH 1408/2137] Firmware port: Pretend to be qemu, implement all indexes used by seabios --- src/const.js | 12 ++++ src/cpu.js | 103 +++++++++++++++++++++++++++---- src/rust/cpu2/global_pointers.rs | 2 +- 3 files changed, 103 insertions(+), 14 deletions(-) diff --git a/src/const.js b/src/const.js index d677fd51..bfdf8820 100644 --- a/src/const.js +++ b/src/const.js @@ -304,9 +304,21 @@ var IA32_APIC_BASE_EN = 1 << 11; /** @const */ var TSR_LDT = 0x60; +// https://github.com/qemu/seabios/blob/14221cd86eadba82255fdc55ed174d401c7a0a04/src/fw/paravirt.c#L205-L219 + /** @const */ var FW_CFG_SIGNATURE = 0x00; +/** @const */ var FW_CFG_ID = 0x01; /** @const */ var FW_CFG_RAM_SIZE = 0x03; /** @const */ var FW_CFG_NB_CPUS = 0x05; +/** @const */ var FW_CFG_MAX_CPUS = 0x0F; +/** @const */ var FW_CFG_NUMA = 0x0D; +/** @const */ var FW_CFG_FILE_DIR = 0x19; + +/** @const */ var FW_CFG_CUSTOM_START = 0x8000; +// This value is specific to v86, choosen to hopefully not collide with other indexes +/** @const */ var FW_CFG_FILE_START = 0xC000; + +/** @const */ var FW_CFG_SIGNATURE_QEMU = 0x554D4551; /** @const */ diff --git a/src/cpu.js b/src/cpu.js index d9a9a6ba..13f54fa9 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -231,7 +231,9 @@ function CPU(bus, wm, v86oxide, coverage_logger) // debug registers this.dreg = v86util.view(Int32Array, memory, 684, 8); - this.fw_value = v86util.view(Int32Array, memory, 720, 1); + this.fw_value = []; + this.fw_pointer = 0; + this.option_roms = []; this.io = undefined; @@ -439,7 +441,7 @@ CPU.prototype.get_state = function() state[60] = this.devices.pic; state[61] = this.a20_enabled[0]; - state[62] = this.fw_value[0]; + state[62] = this.fw_value; state[63] = this.devices.ioapic; @@ -531,7 +533,7 @@ CPU.prototype.set_state = function(state) this.devices.pic = state[60]; this.a20_enabled[0] = state[61]; - this.fw_value[0] = state[62]; + this.fw_value[0] = state; this.devices.ioapic = state[63]; @@ -676,7 +678,7 @@ CPU.prototype.reset = function() this.devices.virtio.reset(); } - this.fw_value[0] = 0; + this.fw_value = []; this.jit_clear_cache(); }; @@ -756,32 +758,107 @@ CPU.prototype.init = function(settings, device_bus) io.register_read(0x511, this, function() { // bios config port (used by seabios and kvm-unit-test) - let result = this.fw_value[0] & 0xFF; - this.fw_value[0] >>>= 8; - return result; + if(this.fw_pointer < this.fw_value.length) + { + return this.fw_value[this.fw_pointer++]; + } + else + { + dbg_assert(false, "config port: Read past value"); + return 0; + } }); io.register_write(0x510, this, undefined, function(value) { dbg_log("bios config port, index=" + h(value)); + function i32(x) + { + return new Uint8Array(new Int32Array([x]).buffer); + } + + function i64(x0, x1) + { + return new Uint8Array(new Int32Array([x0, x1]).buffer); + } + + function to_be16(x) + { + return x >> 8 | x << 8 & 0xFF00; + } + + function to_be32(x) + { + return x << 24 | x << 8 & 0xFF0000 | x >> 8 & 0xFF00 | x >>> 24; + } + + this.fw_pointer = 0; + if(value === FW_CFG_SIGNATURE) { - // We could pretend to be QEMU here to control certain options in - // seabios, but for now this isn't needed - this.fw_value[0] = 0xfab0fab0|0; + // Pretend to be qemu (for seabios) + this.fw_value = i32(FW_CFG_SIGNATURE_QEMU); + } + else if(value === FW_CFG_ID) + { + this.fw_value = i32(0); } else if(value === FW_CFG_RAM_SIZE) { - this.fw_value[0] = this.memory_size[0]; + this.fw_value = i32(this.memory_size[0]); } else if(value === FW_CFG_NB_CPUS) { - this.fw_value[0] = 1; + this.fw_value = i32(1); + } + else if(value === FW_CFG_MAX_CPUS) + { + this.fw_value = i32(1); + } + else if(value === FW_CFG_NUMA) + { + this.fw_value = i64(0); + } + else if(value === FW_CFG_FILE_DIR) + { + const buffer_size = 4 + 64 * this.option_roms.length; + const buffer32 = new Int32Array(buffer_size); + const buffer8 = new Uint8Array(buffer32.buffer); + + buffer32[0] = to_be32(this.option_roms.length); + + for(let i = 0; i < this.option_roms.length; i++) + { + const { name, data } = this.option_roms[i]; + const file_struct_ptr = 4 + 64 * i; + + dbg_assert(FW_CFG_FILE_START + i < 0x10000); + buffer32[file_struct_ptr + 0 >> 2] = to_be32(data.length); + buffer32[file_struct_ptr + 4 >> 2] = to_be16(FW_CFG_FILE_START + i); + + dbg_assert(name.length < 64 - 8); + + for(let j = 0; j < name.length; j++) + { + buffer8[file_struct_ptr + 8 + j] = name.charCodeAt(j); + } + } + + this.fw_value = buffer8; + } + else if(value >= FW_CFG_CUSTOM_START && value < FW_CFG_FILE_START) + { + this.fw_value = i32(0); + } + else if(value >= FW_CFG_FILE_START && value - FW_CFG_FILE_START < this.option_roms.length) + { + const i = value - FW_CFG_FILE_START; + this.fw_value = this.option_roms[i].data; } else { dbg_assert(false, "Unimplemented fw index: " + h(value)); - this.fw_value[0] = 0; + this.fw_value = i32(0); } }); diff --git a/src/rust/cpu2/global_pointers.rs b/src/rust/cpu2/global_pointers.rs index bb91bb25..e6298e42 100644 --- a/src/rust/cpu2/global_pointers.rs +++ b/src/rust/cpu2/global_pointers.rs @@ -36,7 +36,7 @@ pub const prefixes: *mut u8 = 648 as *mut u8; pub const timestamp_counter: *mut u32 = 664 as *mut u32; pub const sreg: *mut u16 = 668 as *mut u16; pub const dreg: *mut i32 = 684 as *mut i32; -pub const fw_value: *mut i32 = 720 as *mut i32; + pub const segment_is_null: *mut bool = 724 as *mut bool; pub const segment_offsets: *mut i32 = 736 as *mut i32; pub const segment_limits: *mut u32 = 768 as *mut u32; From e1c6116a0f0ca818251a3867b081c1d57c1a0b75 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 5 Oct 2018 16:57:57 -0300 Subject: [PATCH 1409/2137] Implement Linux kernel boot protocol, accept bzimage/initrd as boot configuration --- Makefile | 2 +- loader.js | 2 +- src/browser/main.js | 6 ++ src/browser/starter.js | 11 +- src/cpu.js | 16 ++- src/kernel.js | 234 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 267 insertions(+), 4 deletions(-) create mode 100644 src/kernel.js diff --git a/Makefile b/Makefile index ef117ad6..c680dfd4 100644 --- a/Makefile +++ b/Makefile @@ -95,7 +95,7 @@ CORE_FILES=const.js config.js io.js main.js lib.js coverage.js ide.js pci.js flo memory.js 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 debug.js \ - elf.js + elf.js kernel.js LIB_FILES=9p.js filesystem.js jor1k.js marshall.js utf8.js BROWSER_FILES=screen.js \ keyboard.js mouse.js serial.js \ diff --git a/loader.js b/loader.js index 9b15d6a8..256f0b51 100644 --- a/loader.js +++ b/loader.js @@ -8,7 +8,7 @@ "const.js config.js log.js lib.js coverage.js cpu.js debug.js " + "io.js main.js ide.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"; + "ne2k.js state.js virtio.js bus.js elf.js kernel.js"; var BROWSER_FILES = "main.js screen.js keyboard.js mouse.js serial.js lib.js network.js starter.js worker_bus.js print_stats.js filestorage.js"; var LIB_FILES = ""; diff --git a/src/browser/main.js b/src/browser/main.js index bc299e60..678f3d1f 100644 --- a/src/browser/main.js +++ b/src/browser/main.js @@ -545,6 +545,9 @@ settings.cdrom = infos.cdrom; settings.hda = infos.hda; settings.multiboot = infos.multiboot; + settings.bzimage = infos.bzimage; + settings.initrd = infos.initrd; + settings.cmdline = infos.cmdline; settings.memory_size = infos.memory_size; settings.vga_memory_size = infos.vga_memory_size; @@ -767,6 +770,9 @@ "cdrom": settings.cdrom, "multiboot": settings.multiboot, + "bzimage": settings.bzimage, + "initrd": settings.initrd, + "cmdline": settings.cmdline, "initial_state": settings.initial_state, "filesystem": settings.filesystem || {}, diff --git a/src/browser/starter.js b/src/browser/starter.js index 4f1c3642..83dc6d80 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -245,6 +245,7 @@ V86Starter.prototype.continue_init = function(emulator, options) settings.boot_order = options["boot_order"] || 0x213; settings.fda = undefined; settings.fdb = undefined; + settings.cmdline = options["cmdline"]; if(options["network_relay_url"]) { @@ -299,6 +300,12 @@ V86Starter.prototype.continue_init = function(emulator, options) case "multiboot": settings.multiboot = this.disk_images["multiboot"] = buffer.buffer; break; + case "bzimage": + settings.bzimage = this.disk_images["bzimage"] = buffer.buffer; + break; + case "initrd": + settings.initrd = this.disk_images["initrd"] = buffer.buffer; + break; case "bios": settings.bios = buffer.buffer; @@ -345,7 +352,8 @@ V86Starter.prototype.continue_init = function(emulator, options) }; if(name === "bios" || name === "vga_bios" || - name === "initial_state" || name === "multiboot") + name === "initial_state" || name === "multiboot" || + name === "bzimage" || name === "initrd") { // Ignore async for these because they must be availabe before boot. // This should make result.buffer available after the object is loaded @@ -425,6 +433,7 @@ V86Starter.prototype.continue_init = function(emulator, options) "bios", "vga_bios", "cdrom", "hda", "hdb", "fda", "fdb", "initial_state", "multiboot", + "bzimage", "initrd", ]; for(var i = 0; i < image_names.length; i++) diff --git a/src/cpu.js b/src/cpu.js index 13f54fa9..980875bd 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -533,7 +533,7 @@ CPU.prototype.set_state = function(state) this.devices.pic = state[60]; this.a20_enabled[0] = state[61]; - this.fw_value[0] = state; + this.fw_value = state[62]; this.devices.ioapic = state[63]; @@ -736,6 +736,17 @@ CPU.prototype.init = function(settings, device_bus) this.load_bios(); + if(settings.bzimage) + { + dbg_assert(settings.cmdline); + const { option_rom } = load_kernel(this.mem8, settings.bzimage, settings.initrd, settings.cmdline); + + if(option_rom) + { + this.option_roms.push(option_rom); + } + } + var a20_byte = 0; io.register_read(0xB3, this, function() @@ -770,6 +781,9 @@ CPU.prototype.init = function(settings, device_bus) }); io.register_write(0x510, this, undefined, function(value) { + // https://wiki.osdev.org/QEMU_fw_cfg + // https://github.com/qemu/qemu/blob/master/docs/specs/fw_cfg.txt + dbg_log("bios config port, index=" + h(value)); function i32(x) diff --git a/src/kernel.js b/src/kernel.js new file mode 100644 index 00000000..10a134b0 --- /dev/null +++ b/src/kernel.js @@ -0,0 +1,234 @@ +"use strict"; + +// https://www.kernel.org/doc/Documentation/x86/boot.txt + +const LINUX_BOOT_HDR_SETUP_SECTS = 0x1F1; +const LINUX_BOOT_HDR_SYSSIZE = 0x1F4; +const LINUX_BOOT_HDR_VIDMODE = 0x1FA; +const LINUX_BOOT_HDR_BOOT_FLAG = 0x1FE; +const LINUX_BOOT_HDR_HEADER = 0x202; +const LINUX_BOOT_HDR_VERSION = 0x206; +const LINUX_BOOT_HDR_TYPE_OF_LOADER = 0x210; +const LINUX_BOOT_HDR_LOADFLAGS = 0x211; +const LINUX_BOOT_HDR_CODE32_START = 0x214; +const LINUX_BOOT_HDR_RAMDISK_IMAGE = 0x218; +const LINUX_BOOT_HDR_RAMDISK_SIZE = 0x21C; +const LINUX_BOOT_HDR_HEAP_END_PTR = 0x224; +const LINUX_BOOT_HDR_CMD_LINE_PTR = 0x228; +const LINUX_BOOT_HDR_INITRD_ADDR_MAX = 0x22C; +const LINUX_BOOT_HDR_KERNEL_ALIGNMENT = 0x230; +const LINUX_BOOT_HDR_RELOCATABLE_KERNEL = 0x234; +const LINUX_BOOT_HDR_MIN_ALIGNMENT = 0x235; +const LINUX_BOOT_HDR_XLOADFLAGS = 0x236; +const LINUX_BOOT_HDR_CMDLINE_SIZE = 0x238; +const LINUX_BOOT_HDR_PAYLOAD_OFFSET = 0x248; +const LINUX_BOOT_HDR_PAYLOAD_LENGTH = 0x24C; +const LINUX_BOOT_HDR_PREF_ADDRESS = 0x258; +const LINUX_BOOT_HDR_INIT_SIZE = 0x260; + +const LINUX_BOOT_HDR_CHECKSUM1 = 0xAA55; +const LINUX_BOOT_HDR_CHECKSUM2 = 0x53726448; + +const LINUX_BOOT_HDR_TYPE_OF_LOADER_NOT_ASSIGNED = 0xFF; + +const LINUX_BOOT_HDR_LOADFLAGS_LOADED_HIGH = 1 << 0; +const LINUX_BOOT_HDR_LOADFLAGS_QUIET_FLAG = 1 << 5; +const LINUX_BOOT_HDR_LOADFLAGS_KEEP_SEGMENTS = 1 << 6; +const LINUX_BOOT_HDR_LOADFLAGS_CAN_USE_HEAPS = 1 << 7; + + +function load_kernel(mem8, bzimage, initrd, cmdline) +{ + dbg_log("Trying to load kernel of size " + bzimage.length); + + const KERNEL_HIGH_ADDRESS = 0x100000; + + // Puts the initrd at the 32 mb boundary. This means the mininum memory size + // is 32 mb plus the size of the initrd + const INITRD_ADDRESS = 32 << 20; + + const quiet = false; + + const bzimage8 = new Uint8Array(bzimage); + const bzimage16 = new Uint16Array(bzimage); + const bzimage32 = new Uint32Array(bzimage); + + const setup_sects = bzimage8[LINUX_BOOT_HDR_SETUP_SECTS] || 4; + const syssize = bzimage32[LINUX_BOOT_HDR_SYSSIZE >> 2] << 4; + + const vidmode = bzimage16[LINUX_BOOT_HDR_VIDMODE >> 1]; + + const checksum1 = bzimage16[LINUX_BOOT_HDR_BOOT_FLAG >> 1]; + if(checksum1 !== LINUX_BOOT_HDR_CHECKSUM1) + { + dbg_log("Bad checksum1: " + h(checksum1)); + return; + } + + // Not aligned, so split into two 16-bit reads + const checksum2 = + bzimage16[LINUX_BOOT_HDR_HEADER >> 1] | + bzimage16[LINUX_BOOT_HDR_HEADER + 2 >> 1] << 16; + if(checksum2 !== LINUX_BOOT_HDR_CHECKSUM2) + { + dbg_log("Bad checksum2: " + h(checksum2)); + return; + } + + const protocol = bzimage16[LINUX_BOOT_HDR_VERSION >> 1]; + dbg_assert(protocol >= 0x202); // older not supported by us + + const flags = bzimage8[LINUX_BOOT_HDR_LOADFLAGS]; + dbg_assert(flags & LINUX_BOOT_HDR_LOADFLAGS_LOADED_HIGH); // low kernels not supported by us + + // we don't relocate the kernel, so we don't care much about most of these + + const flags2 = bzimage16[LINUX_BOOT_HDR_XLOADFLAGS >> 1]; + const initrd_addr_max = bzimage32[LINUX_BOOT_HDR_INITRD_ADDR_MAX >> 2]; + const kernel_alignment = bzimage32[LINUX_BOOT_HDR_KERNEL_ALIGNMENT >> 2]; + const relocatable_kernel = bzimage8[LINUX_BOOT_HDR_RELOCATABLE_KERNEL]; + const min_alignment = bzimage8[LINUX_BOOT_HDR_MIN_ALIGNMENT]; + const cmdline_size = bzimage32[LINUX_BOOT_HDR_CMDLINE_SIZE >> 2]; + const payload_offset = bzimage32[LINUX_BOOT_HDR_PAYLOAD_OFFSET >> 2]; + const payload_length = bzimage32[LINUX_BOOT_HDR_PAYLOAD_LENGTH >> 2]; + const pref_address = bzimage32[LINUX_BOOT_HDR_PREF_ADDRESS >> 2]; + const pref_address_high = bzimage32[LINUX_BOOT_HDR_PREF_ADDRESS + 4 >> 2]; + const init_size = bzimage32[LINUX_BOOT_HDR_INIT_SIZE >> 2]; + + dbg_log("kernel boot protocol version: " + h(protocol)); + dbg_log("flags=" + h(flags) + " xflags=" + h(flags2)); + dbg_log("code32_start=" + h(bzimage32[LINUX_BOOT_HDR_CODE32_START >> 2])); + dbg_log("initrd_addr_max=" + h(initrd_addr_max)); + dbg_log("kernel_alignment=" + h(kernel_alignment)); + dbg_log("relocatable=" + relocatable_kernel); + dbg_log("min_alignment=" + h(min_alignment)); + dbg_log("cmdline max=" + h(cmdline_size)); + dbg_log("payload offset=" + h(payload_offset) + " size=" + h(payload_length)); + dbg_log("pref_address=" + h(pref_address_high) + ":" + h(pref_address)); + dbg_log("init_size=" + h(init_size)); + + const real_mode_segment = 0x8000; + const base_ptr = real_mode_segment << 4; + + const heap_end = 0xE000; + const heap_end_ptr = heap_end - 0x200; + + // fill in the kernel boot header with infos the kernel needs to know + + bzimage8[LINUX_BOOT_HDR_TYPE_OF_LOADER] = LINUX_BOOT_HDR_TYPE_OF_LOADER_NOT_ASSIGNED; + + const new_flags = + (quiet ? flags | LINUX_BOOT_HDR_LOADFLAGS_QUIET_FLAG : flags & ~LINUX_BOOT_HDR_LOADFLAGS_QUIET_FLAG) + & ~LINUX_BOOT_HDR_LOADFLAGS_KEEP_SEGMENTS + | LINUX_BOOT_HDR_LOADFLAGS_CAN_USE_HEAPS; + bzimage8[LINUX_BOOT_HDR_LOADFLAGS] = new_flags; + + bzimage16[LINUX_BOOT_HDR_HEAP_END_PTR >> 1] = heap_end_ptr; + + // should parse the vga=... paramter from cmdline here, but we don't really care + bzimage16[LINUX_BOOT_HDR_VIDMODE >> 1] = 0xFFFF; // normal + + dbg_log("heap_end_ptr=" + h(heap_end_ptr)); + + cmdline += "\x00"; + dbg_assert(cmdline.length < cmdline_size); + + const cmd_line_ptr = base_ptr + heap_end; + dbg_log("cmd_line_ptr=" + h(cmd_line_ptr)); + + bzimage32[LINUX_BOOT_HDR_CMD_LINE_PTR >> 2] = cmd_line_ptr; + for(let i = 0; i < cmdline.length; i++) + { + mem8[cmd_line_ptr + i] = cmdline.charCodeAt(i); + } + + const prot_mode_kernel_start = (setup_sects + 1) * 512; + dbg_log("prot_mode_kernel_start=" + h(prot_mode_kernel_start)); + + const real_mode_kernel = new Uint8Array(bzimage, 0, prot_mode_kernel_start); + const protected_mode_kernel = new Uint8Array(bzimage, prot_mode_kernel_start); + + let ramdisk_address = 0; + let ramdisk_size = 0; + + if(initrd) + { + ramdisk_address = INITRD_ADDRESS; + ramdisk_size = initrd.byteLength; + + dbg_assert(KERNEL_HIGH_ADDRESS + protected_mode_kernel.length < ramdisk_address); + + mem8.set(new Uint8Array(initrd), ramdisk_address); + } + + bzimage32[LINUX_BOOT_HDR_RAMDISK_IMAGE >> 2] = ramdisk_address; + bzimage32[LINUX_BOOT_HDR_RAMDISK_SIZE >> 2] = ramdisk_size; + + dbg_assert(base_ptr + real_mode_kernel.length < 0xA0000); + + mem8.set(real_mode_kernel, base_ptr); + mem8.set(protected_mode_kernel, KERNEL_HIGH_ADDRESS); + + return { + option_rom: + { + name: "genroms/kernel.bin", + data: make_linux_boot_rom(real_mode_segment, heap_end), + } + }; +} + +function make_linux_boot_rom(real_mode_segment, heap_end) +{ + // This rom will be executed by seabios after its initialisation + // It sets up segment registers, the stack and calls the kernel real mode entry point + + const SIZE = 0x200; + + const data8 = new Uint8Array(0x100); + const data16 = new Uint16Array(data8.buffer); + + data16[0] = 0xAA55; + data8[2] = SIZE / 0x200; + + let i = 3; + + data8[i++] = 0xFA; // cli + data8[i++] = 0xB8; // mov ax, real_mode_segment + data8[i++] = real_mode_segment >> 0; + data8[i++] = real_mode_segment >> 8; + data8[i++] = 0x8E; // mov es, ax + data8[i++] = 0xC0; + data8[i++] = 0x8E; // mov ds, ax + data8[i++] = 0xD8; + data8[i++] = 0x8E; // mov fs, ax + data8[i++] = 0xE0; + data8[i++] = 0x8E; // mov gs, ax + data8[i++] = 0xE8; + data8[i++] = 0x8E; // mov ss, ax + data8[i++] = 0xD0; + data8[i++] = 0xBC; // mov sp, heap_end + data8[i++] = heap_end >> 0; + data8[i++] = heap_end >> 8; + data8[i++] = 0xEA; // jmp (real_mode_segment+0x20):0x0 + data8[i++] = 0x00; + data8[i++] = 0x00; + data8[i++] = real_mode_segment + 0x20 >> 0; + data8[i++] = real_mode_segment + 0x20 >> 8; + + dbg_assert(i < SIZE); + + const checksum_index = i; + data8[checksum_index] = 0; + + let checksum = 0; + + for(let i = 0; i < data8.length; i++) + { + checksum += data8[i]; + } + + data8[checksum_index] = -checksum; + + return data8; +} From 9ffbba7bcd222006773325e573dfd8054723ba23 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 5 Oct 2018 17:17:57 -0300 Subject: [PATCH 1410/2137] Use bzimage loader for debian-full, remove ugly build script for the 9p boot hard drive image --- docker/debian-full/build-state.js | 8 ++- .../debian-full/create-9p-from-container.sh | 70 +------------------ src/browser/main.js | 22 ++++-- 3 files changed, 26 insertions(+), 74 deletions(-) diff --git a/docker/debian-full/build-state.js b/docker/debian-full/build-state.js index 25056c3d..abce5ef7 100755 --- a/docker/debian-full/build-state.js +++ b/docker/debian-full/build-state.js @@ -23,11 +23,17 @@ process.stdin.setEncoding("utf8"); var emulator = new V86({ bios: { url: path.join(V86_ROOT, "/bios/seabios.bin") }, vga_bios: { url: path.join(V86_ROOT, "/bios/vgabios.bin") }, - hda: { url: path.join(V86_ROOT, "/images/debian-9p-boot.img"), async: true, }, autostart: true, memory_size: 512 * 1024 * 1024, vga_memory_size: 8 * 1024 * 1024, network_relay_url: "", + bzimage: { + url: path.join(V86_ROOT, "/images/debian-9p-rootfs/vmlinuz"), + }, + initrd: { + url: path.join(V86_ROOT, "/images/debian-9p-rootfs/initrd.img"), + }, + cmdline: "rw init=/bin/systemd root=host9p console=ttyS0 spectre_v2=off pti=off", filesystem: { basefs: { url: path.join(V86_ROOT, "/images/debian-base-fs.json"), diff --git a/docker/debian-full/create-9p-from-container.sh b/docker/debian-full/create-9p-from-container.sh index 1f599841..b796722e 100755 --- a/docker/debian-full/create-9p-from-container.sh +++ b/docker/debian-full/create-9p-from-container.sh @@ -7,51 +7,11 @@ then exit 1 fi -OUTFILE=$(dirname "$0")/../../images/debian-9p-boot.img OUT_ROOTFS=$(dirname "$0")/../../images/debian-9p-rootfs OUT_ROOTFS_FLAT=$(dirname "$0")/../../images/debian-9p-rootfs-flat OUT_FSJSON=$(dirname "$0")/../../images/debian-base-fs.json CONTAINER_NAME=debian-full -# vmlinuz, initrd.img and grub take about 25M as of time of this writing, be on -# the safe side with 64M -dd if=/dev/zero of=$OUTFILE bs=1k count=64k - -( -echo o # Create a new empty DOS partition table -echo n # Add a new partition -echo p # Primary partition -echo 1 # Partition number -echo 2048 # First sector -echo # Last sector (Accept default: varies) -echo a # make bootable -echo w # Write changes -echo q # quit -) | fdisk $OUTFILE - -# 1048576 is 2048 (first sector) * 512 (sector size) -mkfs.ext4 -F -E offset=1048576 $OUTFILE - -KPARTX_OUTPUT=$(kpartx -a -v $OUTFILE) -echo $KPARTX_OUTPUT -LOOP_PARTITION=$(echo $KPARTX_OUTPUT | grep -o 'loop[0-9]\+p[0-9]\+') -LOOP_DEV=$(echo $LOOP_PARTITION | grep -o 'loop[0-9]\+') -echo $LOOP_PARTITION -echo $LOOP_DEV - -function finish_kpartx { - kpartx -d $OUTFILE -} -trap finish_kpartx EXIT - -ls -lah /dev/mapper/$LOOP_PARTITION -mount /dev/mapper/$LOOP_PARTITION /mnt -function finish_mount { - umount /mnt - finish_kpartx -} -trap finish_mount EXIT - rm -rf $OUT_ROOTFS/ && mkdir $OUT_ROOTFS/ docker export $CONTAINER_NAME | tar -xvC $OUT_ROOTFS/ @@ -64,32 +24,4 @@ $(dirname "$0")/../../tools/copy-to-sha256.py $OUT_ROOTFS $OUT_ROOTFS_FLAT #find $OUT_ROOTFS/ -type d -exec chmod 755 {} ";" #find $OUT_ROOTFS/ -type f -exec chmod 644 {} ";" -cp -r -av $OUT_ROOTFS/boot/ /mnt/boot/ -cp -av $OUT_ROOTFS/{initrd*,vmlinuz*} /mnt/ - - -grub-install --recheck --target=i386-pc --locales= --themes= --fonts= --root-directory /mnt/ /dev/$LOOP_DEV - -cat > /mnt/boot/grub/grub.cfg << 'EOF' -set root='hd0' # XXX: I believe this has no significance, but is required to exist by grub - -set timeout_style=menu -set timeout=0 - -menuentry 'Linux' { - #insmod ext2 - #insmod gzio - #insmod fat - set root='hd0,msdos1' - - echo 'Loading Linux linux ...' - #linux /vmlinuz rw root=/dev/sda1 rootfstype=ext4 init=/bin/systemd - linux /vmlinuz rw init=/bin/systemd root=host9p console=ttyS0 - #linux /boot/vmlinuz debug verbose rw root=/dev/sda1 rootfstype=ext4 - - echo 'Loading initial ramdisk ...' - initrd /initrd.img -} -EOF - -echo $OUTFILE created. +echo $OUT_ROOTFS and $OUT_ROOTFS_FLAT created. diff --git a/src/browser/main.js b/src/browser/main.js index 678f3d1f..7662142c 100644 --- a/src/browser/main.js +++ b/src/browser/main.js @@ -278,11 +278,25 @@ name: "Debian", memory_size: 512 * 1024 * 1024, vga_memory_size: 8 * 1024 * 1024, - hda: { - "url": "", - "size": 5, - "async": true, + filesystem: { + "basefs": { + "url": HOST + "images/debian-base-fs.json", + }, + "baseurl": HOST + "images/debian-9p-rootfs-flat/", }, + }, + { + id: "debian-boot", + name: "Debian", + memory_size: 512 * 1024 * 1024, + bzimage: { + "url": "images/debian-9p-rootfs/vmlinuz", + }, + initrd: { + "url": "images/debian-9p-rootfs/initrd.img", + }, + cmdline: "rw init=/bin/systemd root=host9p console=ttyS0 spectre_v2=off pti=off", + vga_memory_size: 8 * 1024 * 1024, filesystem: { "basefs": { "url": HOST + "images/debian-base-fs.json", From 58695b1ddbdf5e6310281bc82c94be0a8b974346 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 5 Oct 2018 17:43:50 -0300 Subject: [PATCH 1411/2137] Quote variables properly --- docker/debian-full/create-9p-from-container.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docker/debian-full/create-9p-from-container.sh b/docker/debian-full/create-9p-from-container.sh index b796722e..12aaa936 100755 --- a/docker/debian-full/create-9p-from-container.sh +++ b/docker/debian-full/create-9p-from-container.sh @@ -12,16 +12,16 @@ OUT_ROOTFS_FLAT=$(dirname "$0")/../../images/debian-9p-rootfs-flat OUT_FSJSON=$(dirname "$0")/../../images/debian-base-fs.json CONTAINER_NAME=debian-full -rm -rf $OUT_ROOTFS/ && mkdir $OUT_ROOTFS/ -docker export $CONTAINER_NAME | tar -xvC $OUT_ROOTFS/ +rm -rf "$OUT_ROOTFS/" && mkdir "$OUT_ROOTFS/" +docker export "$CONTAINER_NAME" | tar -xvC "$OUT_ROOTFS/" -$(dirname "$0")/../../tools/fs2json.py --out $OUT_FSJSON $OUT_ROOTFS/ -chmod 644 $OUT_FSJSON +$(dirname "$0")/../../tools/fs2json.py --out "$OUT_FSJSON" "$OUT_ROOTFS/" +chmod 644 "$OUT_FSJSON" # Note: Not deleting old files here -$(dirname "$0")/../../tools/copy-to-sha256.py $OUT_ROOTFS $OUT_ROOTFS_FLAT +$(dirname "$0")/../../tools/copy-to-sha256.py "$OUT_ROOTFS" "$OUT_ROOTFS_FLAT" #find $OUT_ROOTFS/ -type d -exec chmod 755 {} ";" #find $OUT_ROOTFS/ -type f -exec chmod 644 {} ";" -echo $OUT_ROOTFS and $OUT_ROOTFS_FLAT created. +echo "$OUT_ROOTFS" and "$OUT_ROOTFS_FLAT" created. From e94c30ef6ff57b2f127e3db98e14caee49078791 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 7 Oct 2018 22:42:01 -0300 Subject: [PATCH 1412/2137] Don't wrap text in SyncBuffer --- src/browser/starter.js | 4 ++-- src/lib.js | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 83dc6d80..6771a67e 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -317,7 +317,7 @@ V86Starter.prototype.continue_init = function(emulator, options) settings.initial_state = buffer.buffer; break; case "fs9p_json": - settings.fs9p_json = buffer.buffer; + settings.fs9p_json = buffer; break; default: dbg_assert(false, name); @@ -501,7 +501,7 @@ V86Starter.prototype.continue_init = function(emulator, options) v86util.load_file(f.url, { done: function(result) { - put_on_settings.call(this, f.name, new SyncBuffer(result)); + put_on_settings.call(this, f.name, f.as_text ? result : new SyncBuffer(result)); cont(index + 1); }.bind(this), progress: function progress(e) diff --git a/src/lib.js b/src/lib.js index 2e04fa9d..206d7fed 100644 --- a/src/lib.js +++ b/src/lib.js @@ -114,6 +114,8 @@ else */ function SyncBuffer(buffer) { + dbg_assert(buffer instanceof ArrayBuffer); + this.buffer = buffer; this.byteLength = buffer.byteLength; this.onload = undefined; From 23a2ac9c449ca889b6ce962e24b78759f99d34e1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 8 Oct 2018 14:06:56 -0300 Subject: [PATCH 1413/2137] Default to synchronous execution for nasm tests --- tests/nasm/gen_fixtures.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/nasm/gen_fixtures.js b/tests/nasm/gen_fixtures.js index 357999bc..2cd073dc 100755 --- a/tests/nasm/gen_fixtures.js +++ b/tests/nasm/gen_fixtures.js @@ -9,7 +9,8 @@ const { spawn, spawnSync } = require("child_process"); const DEBUG = process.env.DEBUG || false; // Maximum number of gdb processes to spawn in parallel const MAX_PARALLEL_PROCS = +process.env.MAX_PARALLEL_PROCS || 32; -const SYNC_GDB_EXECUTION = process.env.SYNC_GDB_EXECUTION || false; +// Default to true for now. It's slower, but async execution occasionally gets stuck +const SYNC_GDB_EXECUTION = process.env.SYNC_GDB_EXECUTION || true; // Usage: console.log(CYAN_FMT, "This shows up in cyan!") const CYAN_FMT = "\x1b[36m%s\x1b[0m"; From 3f79814e056501007d379188c1acc0d10f183bd9 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 8 Oct 2018 16:19:50 -0300 Subject: [PATCH 1414/2137] Detect initrd/bzimage in 9p filesystem and load before boot --- lib/filesystem.js | 28 +++++++++++ src/browser/main.js | 9 ++-- src/browser/starter.js | 111 ++++++++++++++++++++++++++++++++--------- 3 files changed, 119 insertions(+), 29 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 604f452e..e339587a 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -1931,3 +1931,31 @@ FS.prototype.Lock = function(id, request, flags) return P9_LOCK_SUCCESS; }; + +FS.prototype.read_dir = function(path) +{ + const p = this.SearchPath(path); + + if(p.id === -1) + { + return Promise.resolve(null); + } + + const dir = this.GetInode(p.id); + + return Array.from(dir.direntries.keys()).filter(path => path !== "." && path !== ".."); +}; + +FS.prototype.read_file = function(file) +{ + const p = this.SearchPath(file); + + if(p.id === -1) + { + return undefined; + } + + const inode = this.GetInode(p.id); + + return this.Read(p.id, 0, inode.size); +}; diff --git a/src/browser/main.js b/src/browser/main.js index 7662142c..01a9134c 100644 --- a/src/browser/main.js +++ b/src/browser/main.js @@ -289,12 +289,7 @@ id: "debian-boot", name: "Debian", memory_size: 512 * 1024 * 1024, - bzimage: { - "url": "images/debian-9p-rootfs/vmlinuz", - }, - initrd: { - "url": "images/debian-9p-rootfs/initrd.img", - }, + bzimage_initrd_from_filesystem: true, cmdline: "rw init=/bin/systemd root=host9p console=ttyS0 spectre_v2=off pti=off", vga_memory_size: 8 * 1024 * 1024, filesystem: { @@ -562,6 +557,7 @@ settings.bzimage = infos.bzimage; settings.initrd = infos.initrd; settings.cmdline = infos.cmdline; + settings.bzimage_initrd_from_filesystem = infos.bzimage_initrd_from_filesystem; settings.memory_size = infos.memory_size; settings.vga_memory_size = infos.vga_memory_size; @@ -787,6 +783,7 @@ "bzimage": settings.bzimage, "initrd": settings.initrd, "cmdline": settings.cmdline, + "bzimage_initrd_from_filesystem": settings.bzimage_initrd_from_filesystem, "initial_state": settings.initial_state, "filesystem": settings.filesystem || {}, diff --git a/src/browser/starter.js b/src/browser/starter.js index 6771a67e..77150b52 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -27,6 +27,12 @@ * - `hda Object` (No hard drive) - First hard disk, see below. * - `fda Object` (No floppy disk) - First floppy disk, see below. * - `cdrom Object` (No CD) - See below. + * + * - `bzimage Object` - A Linux kernel image to boot (only bzimage format), see below. + * - `initrd Object` - A Linux ramdisk image, see below. + * - `bzimage_initrd_from_filesystem boolean` - Automatically fetch bzimage and + * initrd from the specified `filesystem`. + * * - `initial_state Object` (Normal boot) - An initial state to load, see * [`restore_state`](#restore_statearraybuffer-state) and below. * @@ -542,38 +548,97 @@ V86Starter.prototype.continue_init = function(emulator, options) // settings.memory_size = 0; //} - this.bus.send("cpu-init", settings); - - setTimeout(function() + if(settings.fs9p && settings.fs9p_json) { - if(settings.fs9p && settings.fs9p_json) + settings.fs9p.OnJSONLoaded(settings.fs9p_json); + + if(options["bzimage_initrd_from_filesystem"]) { - settings.fs9p.OnJSONLoaded(settings.fs9p_json); + const { bzimage, initrd } = this.get_bzimage_initrd_from_filesystem(settings.fs9p); + + dbg_log("Found bzimage: " + bzimage + " and initrd: " + initrd); + + Promise.all([ + settings.fs9p.read_file(initrd), + settings.fs9p.read_file(bzimage), + ]).then(([initrd, bzimage]) => { + put_on_settings.call(this, "initrd", new SyncBuffer(initrd.buffer)); + put_on_settings.call(this, "bzimage", new SyncBuffer(bzimage.buffer)); + finish.call(this); + }); + } + else + { + finish.call(this); + } + } + else + { + console.assert( + !options["bzimage_initrd_from_filesystem"], + "bzimage_initrd_from_filesystem: Requires a filesystem"); + finish.call(this); + } + + function finish() + { + this.bus.send("cpu-init", settings); + + if(settings.initial_state) + { + emulator.restore_state(settings.initial_state); + + // The GC can't free settings, since it is referenced from + // several closures. This isn't needed anymore, so we delete it + // here + settings.initial_state = undefined; } - setTimeout(function() + if(options["autostart"]) { - if(settings.initial_state) - { - emulator.restore_state(settings.initial_state); + this.bus.send("cpu-run"); + } - // The GC can't free settings, since it is referenced from - // several closures. This isn't needed anymore, so we delete it - // here - settings.initial_state = undefined; - } - - if(options["autostart"]) - { - this.bus.send("cpu-run"); - } - - this.emulator_bus.send("emulator-loaded"); - }.bind(this), 0); - }.bind(this), 0); + this.emulator_bus.send("emulator-loaded"); + } } }; +V86Starter.prototype.get_bzimage_initrd_from_filesystem = function(filesystem) +{ + const root = (filesystem.read_dir("/") || []).map(x => "/" + x); + const boot = (filesystem.read_dir("/boot/") || []).map(x => "/boot/" + x); + + let initrd; + let bzimage; + + for(let f of [].concat(root, boot)) + { + const old = /old/.test(f) || /fallback/.test(f); + const is_bzimage = /vmlinuz/.test(f); + const is_initrd = /initrd/.test(f) || /initramfs/.test(f); + + if(is_bzimage && (!bzimage || !old)) + { + bzimage = f; + } + + if(is_initrd && (!initrd || !old)) + { + initrd = f; + } + } + + if(!initrd || !bzimage) + { + console.log("Failed to find bzimage or initrd in filesystem. Files:"); + console.log(root.join(" ")); + console.log(boot.join(" ")); + } + + return { initrd, bzimage }; +}; + /** * Start emulation. Do nothing if emulator is running already. Can be * asynchronous. From af0f153640c21dc71f6e3a884558da761d2b2f85 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 8 Oct 2018 16:34:12 -0300 Subject: [PATCH 1415/2137] Refactor using new filesystem function --- src/browser/starter.js | 39 ++++++++++----------------------------- 1 file changed, 10 insertions(+), 29 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 77150b52..43d1afcc 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -1145,35 +1145,16 @@ V86Starter.prototype.read_file = function(file, callback) return; } - var path_infos = fs.SearchPath(file); - var id = path_infos.id; - - if(id === -1) - { - callback(new FileNotFoundError(), null); - } - else - { - fs.OpenInode(id, undefined); - fs.AddEvent( - id, - function() - { - const size = fs.GetInode(id).size; - fs.Read(id, 0, size).then(data => - { - if(data) - { - callback(null, data); - } - else - { - callback(new FileNotFoundError(), null); - } - }); - } - ); - } + fs.read_file(file).then((result) => { + if(result) + { + callback(null, result); + } + else + { + callback(new FileNotFoundError(), null); + } + }); }; /** From 68c59d10a57d44b5ccacaa668c263b6767193307 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 8 Oct 2018 16:49:48 -0300 Subject: [PATCH 1416/2137] copy-to-sha256 and fs2json: Support for tar files, refactor debian-full script to not require root --- docker/debian-full/Readme.md | 5 +- docker/debian-full/build-container.sh | 23 +++- .../debian-full/create-9p-from-container.sh | 27 ----- tools/copy-to-sha256.py | 40 +++++- tools/fs2json.py | 114 +++++++++++++++--- 5 files changed, 155 insertions(+), 54 deletions(-) delete mode 100755 docker/debian-full/create-9p-from-container.sh diff --git a/docker/debian-full/Readme.md b/docker/debian-full/Readme.md index bcbbdfc9..d79c5079 100644 --- a/docker/debian-full/Readme.md +++ b/docker/debian-full/Readme.md @@ -1,8 +1,7 @@ You can build a Linux image for use with v86: -1. Run `./build-container.sh` to build the Docker container (requires dockerd) -2. Run `./create-9p-from-container.sh` to extract the files for v86 from the Docker container (requires root) -3. Run `./build-state.js` to build a state image in order to skip the boot process +1. Run `./build-container.sh` to build the Docker container and v86 images (requires dockerd) +2. Run `./build-state.js` to build a state image in order to skip the boot process Go to `debug.html?profile=debian` to start the generated container. diff --git a/docker/debian-full/build-container.sh b/docker/debian-full/build-container.sh index e157f14f..1e6c97b3 100755 --- a/docker/debian-full/build-container.sh +++ b/docker/debian-full/build-container.sh @@ -1,6 +1,21 @@ #!/usr/bin/env bash -set -e +set -veu -docker build . --rm --tag i386/debian-full -docker rm debian-full || true -docker create -t -i --name debian-full i386/debian-full bash +OUT_ROOTFS_TAR=$(dirname "$0")/../../images/debian-9p-rootfs.tar +OUT_ROOTFS_FLAT=$(dirname "$0")/../../images/debian-9p-rootfs-flat +OUT_FSJSON=$(dirname "$0")/../../images/debian-base-fs.json +CONTAINER_NAME=debian-full +IMAGE_NAME=i386/debian-full + +docker build . --rm --tag "$IMAGE_NAME" +docker rm "$CONTAINER_NAME" || true +docker create -t -i --name "$CONTAINER_NAME" "$IMAGE_NAME" bash + +docker export "$CONTAINER_NAME" > "$OUT_ROOTFS_TAR" + +$(dirname "$0")/../../tools/fs2json.py --out "$OUT_FSJSON" "$OUT_ROOTFS_TAR" + +# Note: Not deleting old files here +$(dirname "$0")/../../tools/copy-to-sha256.py "$OUT_ROOTFS_TAR" "$OUT_ROOTFS_FLAT" + +echo "$OUT_ROOTFS_TAR", "$OUT_ROOTFS_FLAT" and "$OUT_FSJSON" created. diff --git a/docker/debian-full/create-9p-from-container.sh b/docker/debian-full/create-9p-from-container.sh deleted file mode 100755 index 12aaa936..00000000 --- a/docker/debian-full/create-9p-from-container.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash -set -veu - -if [ $(id -u) != "0" ] -then - echo "Please run as root" - exit 1 -fi - -OUT_ROOTFS=$(dirname "$0")/../../images/debian-9p-rootfs -OUT_ROOTFS_FLAT=$(dirname "$0")/../../images/debian-9p-rootfs-flat -OUT_FSJSON=$(dirname "$0")/../../images/debian-base-fs.json -CONTAINER_NAME=debian-full - -rm -rf "$OUT_ROOTFS/" && mkdir "$OUT_ROOTFS/" -docker export "$CONTAINER_NAME" | tar -xvC "$OUT_ROOTFS/" - -$(dirname "$0")/../../tools/fs2json.py --out "$OUT_FSJSON" "$OUT_ROOTFS/" -chmod 644 "$OUT_FSJSON" - -# Note: Not deleting old files here -$(dirname "$0")/../../tools/copy-to-sha256.py "$OUT_ROOTFS" "$OUT_ROOTFS_FLAT" - -#find $OUT_ROOTFS/ -type d -exec chmod 755 {} ";" -#find $OUT_ROOTFS/ -type f -exec chmod 644 {} ";" - -echo "$OUT_ROOTFS" and "$OUT_ROOTFS_FLAT" created. diff --git a/tools/copy-to-sha256.py b/tools/copy-to-sha256.py index 10fd1986..be6cf955 100755 --- a/tools/copy-to-sha256.py +++ b/tools/copy-to-sha256.py @@ -6,14 +6,18 @@ import stat import argparse import hashlib import shutil +import tarfile + def hash_file(filename): - h = hashlib.sha256() with open(filename, "rb", buffering=0) as f: - for b in iter(lambda: f.read(128 * 1024), b""): - h.update(b) - return h.hexdigest() + return hash_fileobj(f) +def hash_fileobj(f): + h = hashlib.sha256() + for b in iter(lambda: f.read(128*1024), b""): + h.update(b) + return h.hexdigest() def main(): logging.basicConfig(format="%(message)s") @@ -30,6 +34,17 @@ def main(): from_path = os.path.normpath(args.from_path) to_path = os.path.normpath(args.to_path) + try: + tar = tarfile.open(from_path, "r") + except IsADirectoryError: + tar = None + + if tar: + handle_tar(logger, tar, to_path) + else: + handle_dir(logger, path, to_path) + +def handle_dir(logger, from_path, to_path): def onerror(oserror): logger.warning(oserror) @@ -56,5 +71,22 @@ def main(): logger.info("cp {} {}".format(absname, to_abs)) shutil.copyfile(absname, to_abs) +def handle_tar(logger, tar, to_path): + for member in tar.getmembers(): + if member.isfile() or member.islnk(): + f = tar.extractfile(member) + sha256 = hash_fileobj(f) + + to_abs = os.path.join(to_path, sha256) + + if os.path.exists(to_abs): + logger.info("Exists, skipped {}".format(to_abs)) + else: + logger.info("Extracted {}".format(to_abs)) + to_file = open(to_abs, "wb") + f.seek(0) + shutil.copyfileobj(f, to_file) + + if __name__ == "__main__": main() diff --git a/tools/fs2json.py b/tools/fs2json.py index 9f087b6f..71350d54 100755 --- a/tools/fs2json.py +++ b/tools/fs2json.py @@ -1,5 +1,10 @@ #!/usr/bin/env python +# Note: +# - Hardlinks are copied +# - The size of symlinks and directories is meaningless, it depends on whatever +# the filesystem/tar file reports + import argparse import json import os @@ -8,6 +13,7 @@ import sys import itertools import logging import hashlib +import tarfile VERSION = 3 @@ -26,12 +32,14 @@ IDX_SHA256 = 6 def hash_file(filename): - h = hashlib.sha256() with open(filename, "rb", buffering=0) as f: - for b in iter(lambda : f.read(128*1024), b""): - h.update(b) - return h.hexdigest() + return hash_fileobj(f) +def hash_fileobj(f): + h = hashlib.sha256() + for b in iter(lambda: f.read(128*1024), b""): + h.update(b) + return h.hexdigest() def main(): logging.basicConfig(format="%(message)s") @@ -53,14 +61,46 @@ def main(): help="File to write to (defaults to stdout)", default=sys.stdout) args.add_argument("path", - metavar="path", - help="Base path to include in JSON") + metavar="path-or-tar", + help="Base path or tar file to include in JSON") args = args.parse_args() path = os.path.normpath(args.path) + + try: + tar = tarfile.open(path, "r") + except IsADirectoryError: + tar = None + + if tar: + (root, total_size) = handle_tar(logger, tar) + else: + (root, total_size) = handle_dir(logger, path, args.exclude) + + if False: + # normalize the order of children, useful to debug differences between + # the tar and filesystem reader + def sort_children(children): + for c in children: + if isinstance(c[IDX_TARGET], list): + sort_children(c[IDX_TARGET]) + children.sort() + + sort_children(root) + + result = { + "fsroot": root, + "version": VERSION, + "size": total_size, + } + + logger.info("Creating json ...") + json.dump(result, args.out, check_circular=False, separators=(',', ':')) + +def handle_dir(logger, path, exclude): path = path + "/" - exclude = args.exclude or [] + exclude = exclude or [] exclude = [os.path.join("/", os.path.normpath(p)) for p in exclude] exclude = set(exclude) @@ -72,11 +112,7 @@ def main(): prevpath = [] mainroot = [] - result = { - "fsroot": mainroot, - "version": VERSION, - "size": 0, - } + total_size = 0 rootstack = [mainroot] def make_node(st, name): @@ -90,7 +126,8 @@ def main(): obj[IDX_UID] = st.st_uid obj[IDX_GID] = st.st_gid - result["size"] += st.st_size + nonlocal total_size + total_size += st.st_size # Missing: # int(st.st_atime), @@ -116,7 +153,7 @@ def main(): break depth += 1 - for name in prevpath[depth:]: + for _name in prevpath[depth:]: rootstack.pop() oldroot = rootstack[-1] @@ -162,9 +199,54 @@ def main(): prevpath = pathparts - logger.info("Creating json ...") + return (mainroot, total_size) + +def handle_tar(logger, tar): + mainroot = [] + total_size = 0 + + for member in tar.getmembers(): + parts = member.name.split("/") + name = parts.pop() + + dir = mainroot + + for p in parts: + for c in dir: + if c[IDX_NAME] == p: + dir = c[IDX_TARGET] + + obj = [None] * 7 + obj[IDX_NAME] = name + obj[IDX_SIZE] = member.size + obj[IDX_MTIME] = member.mtime + obj[IDX_MODE] = member.mode + obj[IDX_UID] = member.uid + obj[IDX_GID] = member.gid + + if member.isfile() or member.islnk(): + f = tar.extractfile(member) + obj[IDX_SHA256] = hash_fileobj(f) + if member.islnk(): + # fix size for hard links + f.seek(0, os.SEEK_END) + obj[IDX_SIZE] = int(f.tell()) + elif member.isdir(): + obj[IDX_TARGET] = [] + elif member.issym(): + obj[IDX_TARGET] = member.linkname + else: + logger.error("Unsupported type: {} ({})".format(member.type, name)) + + total_size += obj[IDX_SIZE] + + while obj[-1] is None: + obj.pop() + + dir.append(obj) + + return mainroot, total_size - json.dump(result, args.out, check_circular=False, separators=(',', ':')) if __name__ == "__main__": main() From e1ad19ed309e24a28b6eb9d2ebf96e36aa41210f Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 8 Oct 2018 18:33:37 -0300 Subject: [PATCH 1417/2137] Update debian dockerfile (add mesa utils, networking tools, disable dhcpcd on boot) --- docker/debian-full/Dockerfile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docker/debian-full/Dockerfile b/docker/debian-full/Dockerfile index 046637fe..81558373 100644 --- a/docker/debian-full/Dockerfile +++ b/docker/debian-full/Dockerfile @@ -18,7 +18,11 @@ RUN apt-get update && \ winbind cabextract \ dhcpcd5 \ wget curl \ + net-tools netcat \ + wmctrl xdotool \ + mesa-utils libgl1-mesa-dri \ && \ + touch /root/.Xdefaults && \ echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen \ locale-gen \ chsh -s /bin/bash && \ @@ -31,6 +35,7 @@ RUN apt-get update && \ systemctl disable systemd-timesyncd.service && \ systemctl disable apt-daily.timer && \ systemctl disable apt-daily-upgrade.timer && \ + systemctl disable dhcpcd.service && \ echo "tmpfs /tmp tmpfs nodev,nosuid 0 0" >> /etc/fstab COPY getty-noclear.conf getty-override.conf /etc/systemd/system/getty@tty1.service.d/ From aea2409b1d614816ba30d1b32d78489afc1cca01 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 8 Oct 2018 18:42:20 -0300 Subject: [PATCH 1418/2137] Ignore filesystem base when state image is provided --- src/browser/starter.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 43d1afcc..1576ef74 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -550,7 +550,14 @@ V86Starter.prototype.continue_init = function(emulator, options) if(settings.fs9p && settings.fs9p_json) { - settings.fs9p.OnJSONLoaded(settings.fs9p_json); + if(!settings.initial_state) + { + settings.fs9p.OnJSONLoaded(settings.fs9p_json); + } + else + { + dbg_log("Filesystem basefs ignored: Overridden by state image"); + } if(options["bzimage_initrd_from_filesystem"]) { From 028e131ddba4c7edc1174417a314782aab1a1a44 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 8 Oct 2018 18:45:27 -0300 Subject: [PATCH 1419/2137] Rename OnJSONLoaded & small refactor --- lib/filesystem.js | 8 +++----- src/browser/starter.js | 5 ++--- tests/devices/virtio_9p.js | 6 +----- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index e339587a..0c4dd6c7 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -56,7 +56,6 @@ function FS(storage, qidcounter) { this.storage = storage; this.qidcounter = qidcounter || { last_qidnumber: 0 }; - this.OnLoaded = function() {}; //this.tar = new TAR(this); @@ -159,11 +158,11 @@ FS.prototype.HandleEvent = function(id) { this.events = newevents; }; -FS.prototype.OnJSONLoaded = function(fs) +FS.prototype.load_from_json = function(fs, done) { if(DEBUG) { - console.assert(fs, "Invalid fs passed to OnJSONLoaded"); + console.assert(fs, "Invalid fs passed to load_from_json"); } //console.time("parse"); @@ -198,8 +197,7 @@ FS.prototype.OnJSONLoaded = function(fs) // console.timeEnd("Check"); //} - me.OnLoaded(); - me.OnLoaded = function() {}; + done(); }, 0); }; diff --git a/src/browser/starter.js b/src/browser/starter.js index 1576ef74..87dc18e5 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -552,7 +552,7 @@ V86Starter.prototype.continue_init = function(emulator, options) { if(!settings.initial_state) { - settings.fs9p.OnJSONLoaded(settings.fs9p_json); + settings.fs9p.load_from_json(settings.fs9p_json); } else { @@ -1084,8 +1084,7 @@ V86Starter.prototype.mount_fs = function(path, baseurl, basefs, callback) if(baseurl) { dbg_assert(typeof basefs === "string", "Filesystem: basefs must be a JSON string"); - newfs.OnJSONLoaded(basefs); - newfs.OnLoaded = mount; + newfs.load_from_json(basefs, () => mount()); } else { diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index e7b8c238..79a77427 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -1652,11 +1652,7 @@ function reload_fsjson() if(tests[test_num].use_fsjson) { console.log(" Reloading files from json"); - emulator.fs9p.OnJSONLoaded(testfsjson); - emulator.fs9p.OnLoaded = () => - { - do_mounts(); - }; + emulator.fs9p.load_from_json(testfsjson, () => do_mounts()); } else { From ae4733a25e3b5f8472e1ec367d9e584757c45b66 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 9 Oct 2018 16:15:28 -0300 Subject: [PATCH 1420/2137] Integration test: Boot from bzimage --- tests/full/run.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/full/run.js b/tests/full/run.js index 317390c4..06c335c3 100755 --- a/tests/full/run.js +++ b/tests/full/run.js @@ -216,6 +216,18 @@ if(cluster.isMaster) ], expect_mouse_registered: true, }, + { + name: "Linux 4 bzImage", + skip_if_disk_image_missing: true, + bzimage: root_path + "/images/bzImage", + cmdline: "auto", + timeout: 200, + expected_texts: [ + "~%", + "Files send via emulator appear in", + ], + expect_mouse_registered: true, + }, { name: "OpenBSD", fda: root_path + "/images/openbsd.img", @@ -449,7 +461,7 @@ function run_test(test, done) { console.log("Starting test: %s", test.name); - let image = test.fda || test.hda || test.cdrom; + let image = test.fda || test.hda || test.cdrom || test.bzimage; console.assert(image, "Bootable drive expected"); if(!fs.existsSync(image)) @@ -508,6 +520,11 @@ function run_test(test, done) { settings.hda = { url: test.hda, async: true, }; } + if(test.bzimage) + { + settings.bzimage = { url: test.bzimage, async: true, }; + } + settings.cmdline = test.cmdline; if(test.expected_texts) { From 987ed08192c787524776602d2e13db77915a0afb Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 9 Oct 2018 16:23:41 -0300 Subject: [PATCH 1421/2137] Add p7zip to the docker test image --- docker/test-image/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/test-image/Dockerfile b/docker/test-image/Dockerfile index 5a5e599f..cc1deec7 100644 --- a/docker/test-image/Dockerfile +++ b/docker/test-image/Dockerfile @@ -3,7 +3,7 @@ FROM ubuntu:latest RUN \ dpkg --add-architecture i386 && \ apt-get update -qq && \ - apt-get install -y nasm gdb unzip openjdk-8-jre wget python python3 qemu-system-x86 git-core build-essential libc6-dev-i386-cross libc6-dev-i386 && \ + apt-get install -y nasm gdb unzip p7zip-full openjdk-8-jre wget python python3 qemu-system-x86 git-core build-essential libc6-dev-i386-cross libc6-dev-i386 && \ wget https://nodejs.org/dist/v8.9.4/node-v8.9.4-linux-x64.tar.xz && \ tar xfv node-v8.9.4-linux-x64.tar.xz && \ rm node-v8.9.4-linux-x64.tar.xz && \ From 99a7bdd6e3da533a55c0e785f1030a80df3521c3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 12 Oct 2018 12:19:45 -0300 Subject: [PATCH 1422/2137] Fix error message when libv86-debug.js hasn't been built --- tests/full/run.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/full/run.js b/tests/full/run.js index 06c335c3..c73103d7 100755 --- a/tests/full/run.js +++ b/tests/full/run.js @@ -16,7 +16,7 @@ try } catch(e) { - console.error("Failed to import build/libv86.js. Run `make build/libv86.js first."); + console.error("Failed to import build/libv86-debug.js. Run `make build/libv86-debug.js first."); process.exit(1); } From fe5a1f5322801e942ce762fe70ad219c5d32872e Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 15 Oct 2018 12:03:24 -0300 Subject: [PATCH 1423/2137] Fix error case in read_dir/read_file --- lib/filesystem.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 0c4dd6c7..c80da828 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -1936,7 +1936,7 @@ FS.prototype.read_dir = function(path) if(p.id === -1) { - return Promise.resolve(null); + return undefined; } const dir = this.GetInode(p.id); @@ -1950,7 +1950,7 @@ FS.prototype.read_file = function(file) if(p.id === -1) { - return undefined; + return Promise.resolve(null); } const inode = this.GetInode(p.id); From eb93fa5db7bfc46852fd4ed6b45fc2c5ebb49822 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 15 Oct 2018 12:04:14 -0300 Subject: [PATCH 1424/2137] Filesystem: Temporarily cache inode data until storage is chunked properly --- lib/filesystem.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index c80da828..0d5b0b94 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -1089,7 +1089,13 @@ FS.prototype.get_data = async function(idx) // jshint ignore:line dbg_assert(inode, `Filesystem get_data: idx ${idx} does not point to an inode`); if(this.inodedata[idx]) return this.inodedata[idx]; - if(inode.sha256sum && this.storage) return await this.storage.get(inode.sha256sum); // jshint ignore:line + if(inode.sha256sum && this.storage) + { + const data = await this.storage.get(inode.sha256sum); // jshint ignore:line + // XXX: Temporary cache until storage can properly chunk + this.inodedata[idx] = data; + return data; + } return null; }; // jshint ignore:line From 5a4b161db02183211aa2593156a529f4b9ab020d Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 15 Oct 2018 12:04:54 -0300 Subject: [PATCH 1425/2137] build-container.sh: Create directory if it doesn't exist --- docker/debian-full/build-container.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/debian-full/build-container.sh b/docker/debian-full/build-container.sh index 1e6c97b3..be1fe981 100755 --- a/docker/debian-full/build-container.sh +++ b/docker/debian-full/build-container.sh @@ -16,6 +16,7 @@ docker export "$CONTAINER_NAME" > "$OUT_ROOTFS_TAR" $(dirname "$0")/../../tools/fs2json.py --out "$OUT_FSJSON" "$OUT_ROOTFS_TAR" # Note: Not deleting old files here +mkdir -p "$OUT_ROOTFS_FLAT" $(dirname "$0")/../../tools/copy-to-sha256.py "$OUT_ROOTFS_TAR" "$OUT_ROOTFS_FLAT" echo "$OUT_ROOTFS_TAR", "$OUT_ROOTFS_FLAT" and "$OUT_FSJSON" created. From 66eb93621d08b534295e77ac18f8b6a86f797198 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 15 Oct 2018 12:05:22 -0300 Subject: [PATCH 1426/2137] build-state.js: Use new method of loading bzimage/initrd --- docker/debian-full/build-state.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/docker/debian-full/build-state.js b/docker/debian-full/build-state.js index abce5ef7..cecbe460 100755 --- a/docker/debian-full/build-state.js +++ b/docker/debian-full/build-state.js @@ -27,19 +27,13 @@ var emulator = new V86({ memory_size: 512 * 1024 * 1024, vga_memory_size: 8 * 1024 * 1024, network_relay_url: "", - bzimage: { - url: path.join(V86_ROOT, "/images/debian-9p-rootfs/vmlinuz"), - }, - initrd: { - url: path.join(V86_ROOT, "/images/debian-9p-rootfs/initrd.img"), - }, + bzimage_initrd_from_filesystem: true, cmdline: "rw init=/bin/systemd root=host9p console=ttyS0 spectre_v2=off pti=off", filesystem: { basefs: { url: path.join(V86_ROOT, "/images/debian-base-fs.json"), }, baseurl: path.join(V86_ROOT, "/images/debian-9p-rootfs-flat/"), - //baseurl: path.join(V86_ROOT, "/images/debian-9p-rootfs/"), }, screen_dummy: true, }); From f7c22266c9fab4c4f7b1e61b1e791fd43db9a4b8 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 15 Oct 2018 12:06:14 -0300 Subject: [PATCH 1427/2137] initrd/bzimage detection: Ignore case --- src/browser/starter.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 87dc18e5..006d71b3 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -621,9 +621,9 @@ V86Starter.prototype.get_bzimage_initrd_from_filesystem = function(filesystem) for(let f of [].concat(root, boot)) { - const old = /old/.test(f) || /fallback/.test(f); - const is_bzimage = /vmlinuz/.test(f); - const is_initrd = /initrd/.test(f) || /initramfs/.test(f); + const old = /old/i.test(f) || /fallback/i.test(f); + const is_bzimage = /vmlinuz/i.test(f) || /bzimage/i.test(f); + const is_initrd = /initrd/i.test(f) || /initramfs/i.test(f); if(is_bzimage && (!bzimage || !old)) { From 44bbeb20e62881364a117405130cbe67f1c9a23d Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 15 Oct 2018 12:31:04 -0300 Subject: [PATCH 1428/2137] Remove old api docs (see starter.js) --- docs/api.md | 274 ---------------------------------------------------- 1 file changed, 274 deletions(-) delete mode 100644 docs/api.md diff --git a/docs/api.md b/docs/api.md deleted file mode 100644 index 52414037..00000000 --- a/docs/api.md +++ /dev/null @@ -1,274 +0,0 @@ -# V86Starter -- [`run()`](#run) -- [`stop()`](#stop) -- [`restart()`](#restart) -- [`add_listener(string event, function(*) listener)`](#add_listenerstring-event-function-listener) -- [`remove_listener(string event, function(*) listener)`](#remove_listenerstring-event-function-listener) -- [`restore_state(ArrayBuffer state)`](#restore_statearraybuffer-state) -- [`save_state(function(Object, ArrayBuffer) callback)`](#save_statefunctionobject-arraybuffer-callback) -- [`get_statistics() -> Object`](#get_statistics---object) -- [`is_running() -> boolean`](#is_running---boolean) -- [`keyboard_send_scancodes(Array. codes)`](#keyboard_send_scancodesarraynumber-codes) -- [`mouse_set_status(boolean enabled)`](#mouse_set_statusboolean-enabled) -- [`keyboard_set_status(boolean enabled)`](#keyboard_set_statusboolean-enabled) -- [`serial0_send(string data)`](#serial0_sendstring-data) -- [`create_file(string file, Uint8Array data, function(Object) callback)`](#create_filestring-file-uint8array-data-functionobject-callback) -- [`read_file(string file, function(Object, Uint8Array) callback)`](#read_filestring-file-functionobject-uint8array-callback) - -*** -## `V86Starter` -Constructor for emulator instances. - -Usage: `var emulator = new V86Starter(options);` - -Options can have the following properties (all optional, default in parenthesis): - -- `memory_size number` (16 * 1024 * 1024) - The memory size in bytes, should - be a power of 2. -- `vga_memory_size number` (8 * 1024 * 1024) - VGA memory size in bytes. - -- `autostart boolean` (false) - If emulation should be started when emulator - is ready. - -- `disable_keyboard boolean` (false) - If the keyboard should be disabled. -- `disable_mouse boolean` (false) - If the mouse should be disabled. - -- `network_relay_url string` (No network card) - The url of a server running - websockproxy. See [networking.md](networking.md). Setting this will - enable an emulated network card. - -- `bios Object` (No bios) - Either a url pointing to a bios or an - ArrayBuffer, see below. -- `vga_bios Object` (No VGA bios) - VGA bios, see below. -- `hda Object` (No hard drive) - First hard disk, see below. -- `fda Object` (No floppy disk) - First floppy disk, see below. -- `cdrom Object` (No CD) - See below. -- `initial_state Object` (Normal boot) - An initial state to load, see - [`restore_state`](#restore_statearraybuffer-state) and below. - -- `filesystem Object` (No 9p filesystem) - A 9p filesystem, see - [filesystem.md](filesystem.md). - -- `serial_container HTMLTextAreaElement` (No serial terminal) - A textarea - that will receive and send data to the emulated serial terminal. - Alternatively the serial terminal can also be accessed programatically, - see [serial.html](../examples/serial.html). - -- `screen_container HTMLElement` (No screen) - An HTMLElement. This should - have a certain structure, see [basic.html](../examples/basic.html). - -*** - -There are two ways to load images (`bios`, `vga_bios`, `cdrom`, `hda`, ...): - -- Pass an object that has a url. Optionally, `async: true` and `size: - size_in_bytes` can be added to the object, so that sectors of the image - are loaded on demand instead of being loaded before boot (slower, but - strongly recommended for big files). In that case, the `Range: bytes=...` - header must be supported on the server. Note: the python SimpleHTTPServer - does not support this, so it won't work with the default webserver used - by `make run`. - - ```javascript - // download file before boot - options.bios = { - url: "bios/seabios.bin" - } - // download file sectors as requested, size is required - options.hda = { - url: "disk/linux.iso", - async: true, - size: 16 * 1024 * 1024 - } - ``` - -- Pass an `ArrayBuffer` or `File` object as `buffer` property. - - ```javascript - // use - options.bios = { - buffer: document.all.hd_image.files[0] - } - // start with empty hard drive - options.hda = { - buffer: new ArrayBuffer(16 * 1024 * 1024) - } - ``` - -*** - -**Parameters:** - -1. **`Object`** options – Options to initialize the emulator with. - -*** -#### `run()` -Start emulation. Do nothing if emulator is running already. Can be -asynchronous. - -*** -#### `stop()` -Stop emulation. Do nothing if emulator is not running. Can be asynchronous. - -*** -#### `restart()` -Restart (force a reboot). - -*** -#### `add_listener(string event, function(*) listener)` -Add an event listener (the emulator is an event emitter). A list of events -can be found at [events.md](events.md). - -The callback function gets a single argument which depends on the event. - -**Parameters:** - -1. **`string`** event – Name of the event. -2. **`function(*)`** listener – The callback function. - -*** -#### `remove_listener(string event, function(*) listener)` -Remove an event listener. - -**Parameters:** - -1. **`string`** event -2. **`function(*)`** listener - -*** -#### `restore_state(ArrayBuffer state)` -Restore the emulator state from the given state, which must be an -ArrayBuffer returned by -[`save_state`](#save_statefunctionobject-arraybuffer-callback). - -Note that the state can only be restored correctly if this constructor has -been created with the same options as the original instance (e.g., same disk -images, memory size, etc.). - -Different versions of the emulator might use a different format for the -state buffer. - -**Parameters:** - -1. **`ArrayBuffer`** state - -*** -#### `save_state(function(Object, ArrayBuffer) callback)` -Asynchronously save the current state of the emulator. The first argument to -the callback is an Error object if something went wrong and is null -otherwise. - -**Parameters:** - -1. **`function(Object, ArrayBuffer)`** callback - -*** -#### `get_statistics() -> Object` - -**Deprecated - Might be removed in a later release.** - -Return an object with several statistics. Return value looks similar to -(but can be subject to change in future versions or different -configurations, so use defensively): - -```javascript -{ - "cpu": { - "instruction_counter": 2821610069 - }, - "hda": { - "sectors_read": 95240, - "sectors_written": 952, - "bytes_read": 48762880, - "bytes_written": 487424, - "loading": false - }, - "cdrom": { - "sectors_read": 0, - "sectors_written": 0, - "bytes_read": 0, - "bytes_written": 0, - "loading": false - }, - "mouse": { - "enabled": true - }, - "vga": { - "is_graphical": true, - "res_x": 800, - "res_y": 600, - "bpp": 32 - } -} -``` - -**Returns:** - -* **`Object`** - -*** -#### `is_running() -> boolean` - -**Returns:** - -* **`boolean`** - -*** -#### `keyboard_send_scancodes(Array. codes)` -Send a sequence of scan codes to the emulated PS2 controller. A list of -codes can be found at http://stanislavs.org/helppc/make_codes.html. -Do nothing if there is no keyboard controller. - -**Parameters:** - -1. **`Array.`** codes - -*** -#### `mouse_set_status(boolean enabled)` -Enable or disable sending mouse events to the emulated PS2 controller. - -**Parameters:** - -1. **`boolean`** enabled - -*** -#### `keyboard_set_status(boolean enabled)` -Enable or disable sending keyboard events to the emulated PS2 controller. - -**Parameters:** - -1. **`boolean`** enabled - -*** -#### `serial0_send(string data)` -Send a string to the first emulated serial terminal. - -**Parameters:** - -1. **`string`** data - -*** -#### `create_file(string file, Uint8Array data, function(Object) callback)` -Write to a file in the 9p filesystem. Nothing happens if no filesystem has -been initialized. First argument to the callback is an error object if -something went wrong and null otherwise. - -**Parameters:** - -1. **`string`** file -2. **`Uint8Array`** data -3. **`function(Object)`** (optional) callback - -*** -#### `read_file(string file, function(Object, Uint8Array) callback)` -Read a file in the 9p filesystem. Nothing happens if no filesystem has been -initialized. - -**Parameters:** - -1. **`string`** file -2. **`function(Object, Uint8Array)`** callback - - - - From d2f86799e9e9045b2d94012290909066cc733704 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 15 Oct 2018 12:33:52 -0300 Subject: [PATCH 1429/2137] Simplify load_from_json: Accept json object directly, don't run asynchronously --- lib/filesystem.js | 37 +++++++++++-------------------------- src/browser/lib.js | 10 +++++++++- src/browser/starter.js | 8 ++++---- tests/devices/virtio_9p.js | 2 +- 4 files changed, 25 insertions(+), 32 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 0d5b0b94..963b31ee 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -165,40 +165,25 @@ FS.prototype.load_from_json = function(fs, done) console.assert(fs, "Invalid fs passed to load_from_json"); } - //console.time("parse"); - var fsdata = JSON.parse(fs); - //console.timeEnd("parse"); - - if(fsdata["version"] !== JSONFS_VERSION) + if(fs["version"] !== JSONFS_VERSION) { throw "The filesystem JSON format has changed. " + "Please update your fs2json (https://github.com/copy/fs2json) and recreate the filesystem JSON."; } - var fsroot = fsdata["fsroot"]; - this.used_size = fsdata["size"]; + var fsroot = fs["fsroot"]; + this.used_size = fs["size"]; - var me = this; + for(var i = 0; i < fsroot.length; i++) { + this.LoadRecursive(fsroot[i], 0); + } - setTimeout(function() - { - //console.time("Load"); - //console.profile("Load"); - for(var i = 0; i < fsroot.length; i++) { - me.LoadRecursive(fsroot[i], 0); - } - //console.profileEnd("Load"); - //console.timeEnd("Load"); + //if(DEBUG) + //{ + // this.Check(); + //} - //if(DEBUG) - //{ - // console.time("Check"); - // me.Check(); - // console.timeEnd("Check"); - //} - - done(); - }, 0); + done && done(); }; FS.prototype.LoadRecursive = function(data, parentid) diff --git a/src/browser/lib.js b/src/browser/lib.js index 80388df7..2132418d 100644 --- a/src/browser/lib.js +++ b/src/browser/lib.js @@ -53,7 +53,15 @@ var ASYNC_SAFE = false; http.open(options.method || "get", filename, true); - if(!options.as_text) + if(options.as_text) + { + // the default + } + else if(options.as_json) + { + http.responseType = "json"; + } + else { http.responseType = "arraybuffer"; } diff --git a/src/browser/starter.js b/src/browser/starter.js index 006d71b3..6c45d1e4 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -475,7 +475,7 @@ V86Starter.prototype.continue_init = function(emulator, options) name: "fs9p_json", url: fs_url, size: size, - as_text: true, + as_json: true, }); } } @@ -507,7 +507,7 @@ V86Starter.prototype.continue_init = function(emulator, options) v86util.load_file(f.url, { done: function(result) { - put_on_settings.call(this, f.name, f.as_text ? result : new SyncBuffer(result)); + put_on_settings.call(this, f.name, f.as_json ? result : new SyncBuffer(result)); cont(index + 1); }.bind(this), progress: function progress(e) @@ -534,7 +534,7 @@ V86Starter.prototype.continue_init = function(emulator, options) }); } }, - as_text: f.as_text, + as_json: f.as_json, }); } }.bind(this); @@ -1083,7 +1083,7 @@ V86Starter.prototype.mount_fs = function(path, baseurl, basefs, callback) }; if(baseurl) { - dbg_assert(typeof basefs === "string", "Filesystem: basefs must be a JSON string"); + dbg_assert(typeof basefs === "object", "Filesystem: basefs must be a JSON object"); newfs.load_from_json(basefs, () => mount()); } else diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index 79a77427..ce3e48c2 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -5,7 +5,7 @@ process.on("unhandledRejection", exn => { throw exn; }); const V86 = require("../../build/libv86-debug.js").V86; const fs = require("fs"); -const testfsjson = JSON.stringify(require('./testfs.json')); +const testfsjson = require("./testfs.json"); const SHOW_LOGS = false; function log_pass(msg, ...args) From 93a10651cab0e2c742969ff6bc74ae4117b9466d Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 15 Oct 2018 13:54:01 -0300 Subject: [PATCH 1430/2137] Improve log notice --- docker/debian-full/build-state.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/debian-full/build-state.js b/docker/debian-full/build-state.js index cecbe460..3f9ccb1e 100755 --- a/docker/debian-full/build-state.js +++ b/docker/debian-full/build-state.js @@ -6,7 +6,7 @@ const path = require("path"); // TODO: // - Timeout -console.log("Don't forget to run make build/libv86.js before running this script"); +console.log("Don't forget to run `make all` before running this script"); var fs = require("fs"); var V86 = require("./../../build/libv86.js").V86; From 99f93a77403053a1c46b923fb2e97e15f088f432 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 15 Oct 2018 13:57:44 -0300 Subject: [PATCH 1431/2137] Exit the process after state file has been built --- docker/debian-full/build-state.js | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/debian-full/build-state.js b/docker/debian-full/build-state.js index 3f9ccb1e..ce958655 100755 --- a/docker/debian-full/build-state.js +++ b/docker/debian-full/build-state.js @@ -82,6 +82,7 @@ emulator.add_listener("serial0-output-char", function(c) if(e) throw e; console.error("Saved as " + OUTPUT_FILE); emulator.stop(); + setTimeout(() => process.exit(0), 5000); }); }); }, 5000); From e5fbbd0f2db6a65b73225c95a9d9b6956daa0898 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 16 Oct 2018 15:01:01 -0300 Subject: [PATCH 1432/2137] Implement json loading for nodejs --- src/browser/lib.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/browser/lib.js b/src/browser/lib.js index 2132418d..0115c13b 100644 --- a/src/browser/lib.js +++ b/src/browser/lib.js @@ -116,7 +116,7 @@ var ASYNC_SAFE = false; if(options.range) { - dbg_assert(!options.as_text); + dbg_assert(!options.as_text && !options.as_json); fs["open"](filename, "r", (err, fd) => { @@ -141,7 +141,7 @@ var ASYNC_SAFE = false; else { var o = { - encoding: options.as_text ? "utf-8" : null, + encoding: options.as_text || options.as_json ? "utf-8" : null, }; fs["readFile"](filename, o, function(err, data) @@ -154,7 +154,14 @@ var ASYNC_SAFE = false; { var result = data; - if(!options.as_text) + if(options.as_text) + { + } + else if(options.as_json) + { + result = JSON.parse(result); + } + else { result = new Uint8Array(result).buffer; } From 8aa06b54e0d0c9bac8fefd581f13a4a4f8c8d151 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Mon, 1 Oct 2018 23:10:53 +0530 Subject: [PATCH 1433/2137] cpu: Port switch_cs_real_mode to Rust --- src/browser/starter.js | 2 -- src/cpu.js | 10 +--------- src/rust/cpu2/cpu.rs | 11 +++++++++-- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 6c45d1e4..44e15f37 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -184,8 +184,6 @@ function V86Starter(options) "do_task_switch": (selector, has_error_code, error_code) => { cpu.do_task_switch(selector, has_error_code, error_code); }, - // XXX: Port to Rust - "switch_cs_real_mode": (selector) => cpu.switch_cs_real_mode(selector), "__indirect_function_table": wasm_table, }; diff --git a/src/cpu.js b/src/cpu.js index 980875bd..4b9180e6 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -307,6 +307,7 @@ CPU.prototype.wasm_patch = function(wm) this.trigger_np = get_import("trigger_np"); this.trigger_ss = get_import("trigger_ss"); + this.switch_cs_real_mode = get_import("switch_cs_real_mode"); this.call_interrupt_vector = get_import("call_interrupt_vector_js"); this.get_tss_stack_addr = get_import("get_tss_stack_addr_js"); @@ -1838,15 +1839,6 @@ CPU.prototype.iret = function(is_16) this.handle_irqs(); }; -CPU.prototype.switch_cs_real_mode = function(selector) -{ - dbg_assert(!this.protected_mode[0] || this.vm86_mode()); - - this.sreg[reg_cs] = selector; - this.segment_is_null[reg_cs] = 0; - this.segment_offsets[reg_cs] = selector << 4; -}; - CPU.prototype.far_return = function(eip, selector, stack_adjust) { dbg_assert(typeof selector === "number" && selector < 0x10000 && selector >= 0); diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 12d15067..8c194eab 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -6,8 +6,6 @@ extern "C" { #[no_mangle] fn do_task_switch(selector: i32, has_error_code: bool, error_code: i32); #[no_mangle] - fn switch_cs_real_mode(selector: i32); - #[no_mangle] fn dbg_trace(); //#[no_mangle] //fn logop(addr: i32, op: i32); @@ -381,6 +379,15 @@ pub unsafe fn call_interrupt_vector_js( call_interrupt_vector(interrupt_nr, is_software_int, ec); } +#[no_mangle] +pub unsafe fn switch_cs_real_mode(selector: i32) { + dbg_assert!(!*protected_mode || vm86_mode()); + + *sreg.offset(CS as isize) = selector as u16; + *segment_is_null.offset(CS as isize) = false; + *segment_offsets.offset(CS as isize) = selector << 4; +} + pub unsafe fn get_tss_stack_addr(dpl: u8) -> OrPageFault { let (tss_stack_offset, page_boundary) = if *tss_size_32 { (((dpl << 3) + 4) as u32, 0x1000 - 6) From 1d5e0052b453ed3562f331beff183faa1be513dc Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Fri, 19 Oct 2018 16:09:08 +0530 Subject: [PATCH 1434/2137] cpu: Port iret, iret16, iret32 to Rust --- src/browser/starter.js | 2 - src/cpu.js | 293 ---------------------------------- src/rust/cpu2/cpu.rs | 267 +++++++++++++++++++++++++++++++ src/rust/cpu2/instructions.rs | 4 - 4 files changed, 267 insertions(+), 299 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 44e15f37..15edb2de 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -123,8 +123,6 @@ function V86Starter(options) "far_jump": function(eip, selector, is_call) { return cpu.far_jump(eip, selector, !!is_call); }, "far_return": function(eip, selector, stack_adjust) { return cpu.far_return(eip, selector, stack_adjust); }, - "iret16": function() { return cpu.iret16(); }, - "iret32": function() { return cpu.iret32(); }, "pic_acknowledge": function() { cpu.pic_acknowledge(); }, "io_port_read8": function(addr) { return cpu.io.port_read8(addr); }, diff --git a/src/cpu.js b/src/cpu.js index 4b9180e6..7c716852 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -1546,299 +1546,6 @@ CPU.prototype.jit_clear_cache = function() } }; -CPU.prototype.iret16 = function() -{ - this.iret(true); -}; - -CPU.prototype.iret32 = function() -{ - this.iret(false); -}; - -CPU.prototype.iret = function(is_16) -{ - //dbg_log("iret is_16=" + is_16, LOG_CPU); - CPU_LOG_VERBOSE && this.debug.dump_state("iret" + (is_16 ? "16" : "32") + " start"); - //this.debug.dump_regs(); - - if(this.vm86_mode() && this.getiopl() < 3) - { - // vm86 mode, iopl != 3 - dbg_log("#gp iret vm86 mode, iopl != 3", LOG_CPU); - this.trigger_gp_non_raising(0); - return; - } - - if(is_16) - { - var new_eip = this.safe_read16(this.get_stack_pointer(0)); - var new_cs = this.safe_read16(this.get_stack_pointer(2)); - var new_flags = this.safe_read16(this.get_stack_pointer(4)); - } - else - { - var new_eip = this.safe_read32s(this.get_stack_pointer(0)); - var new_cs = this.safe_read16(this.get_stack_pointer(4)); - var new_flags = this.safe_read32s(this.get_stack_pointer(8)); - } - - if(!this.protected_mode[0] || (this.vm86_mode() && this.getiopl() === 3)) - { - if(new_eip & 0xFFFF0000) - { - throw this.debug.unimpl("#GP handler"); - } - - this.switch_cs_real_mode(new_cs); - this.instruction_pointer[0] = new_eip + this.get_seg(reg_cs) | 0; - - if(is_16) - { - this.update_eflags(new_flags | this.flags[0] & ~0xFFFF); - this.adjust_stack_reg(3 * 2); - } - else - { - this.update_eflags(new_flags); - this.adjust_stack_reg(3 * 4); - } - - //dbg_log("iret32 to:", LOG_CPU); - CPU_LOG_VERBOSE && this.debug.dump_state("iret end"); - - this.handle_irqs(); - return; - } - - dbg_assert(!this.vm86_mode()); - - if(this.flags[0] & flag_nt) - { - if(DEBUG) throw this.debug.unimpl("nt"); - this.trigger_gp_non_raising(0); - return; - } - - if(new_flags & flag_vm) - { - if(this.cpl[0] === 0) - { - // return to virtual 8086 mode - - // vm86 cannot be set in 16 bit flag - dbg_assert(!is_16); - - dbg_assert((new_eip & ~0xFFFF) === 0); - - //dbg_log("in vm86 mode now " + - // " cs:eip=" + h(new_cs, 4) + ":" + h(this.instruction_pointer >>> 0, 8) + - // " iopl=" + this.getiopl() + " flags=" + h(new_flags, 8), LOG_CPU); - - - var temp_esp = this.safe_read32s(this.get_stack_pointer(12)); - var temp_ss = this.safe_read16(this.get_stack_pointer(16)); - - var new_es = this.safe_read16(this.get_stack_pointer(20)); - var new_ds = this.safe_read16(this.get_stack_pointer(24)); - var new_fs = this.safe_read16(this.get_stack_pointer(28)); - var new_gs = this.safe_read16(this.get_stack_pointer(32)); - - // no exceptions below - - this.update_eflags(new_flags); - this.flags[0] |= flag_vm; - - this.switch_cs_real_mode(new_cs); - this.instruction_pointer[0] = (new_eip & 0xFFFF) + this.get_seg(reg_cs) | 0; - - if( - !this.switch_seg(reg_es, new_es) || - !this.switch_seg(reg_ds, new_ds) || - !this.switch_seg(reg_fs, new_fs) || - !this.switch_seg(reg_gs, new_gs) - ) - { - // XXX: Should be checked before side effects - dbg_assert(false); - } - - this.adjust_stack_reg(9 * 4); // 9 dwords: eip, cs, flags, esp, ss, es, ds, fs, gs - - this.reg32s[reg_esp] = temp_esp; - if(!this.switch_seg(reg_ss, temp_ss)) dbg_assert(false); // XXX - - this.cpl[0] = 3; - this.cpl_changed(); - - this.update_cs_size(false); - - //dbg_log("iret32 to:", LOG_CPU); - CPU_LOG_VERBOSE && this.debug.dump_state("iret end"); - //this.debug.dump_regs(); - - return; - } - else - { - dbg_log("vm86 flag ignored because cpl != 0", LOG_CPU); - new_flags &= ~flag_vm; - } - } - - // protected mode return - - var info = this.lookup_segment_selector(new_cs); - - dbg_assert(info.is_valid); - dbg_assert((new_eip >>> 0) <= info.effective_limit); - - if(info.is_null) - { - throw this.debug.unimpl("is null"); - } - if(!info.is_present) - { - throw this.debug.unimpl("not present"); - } - if(!info.is_executable) - { - throw this.debug.unimpl("not exec"); - } - if(info.rpl < this.cpl[0]) - { - throw this.debug.unimpl("rpl < cpl"); - } - if(info.dc_bit && info.dpl > info.rpl) - { - throw this.debug.unimpl("conforming and dpl > rpl"); - } - - if(!info.dc_bit && info.rpl !== info.dpl) - { - dbg_log("#gp iret: non-conforming cs and rpl != dpl, dpl=" + info.dpl + " rpl=" + info.rpl, LOG_CPU); - this.trigger_gp_non_raising(new_cs & ~3); - return; - } - - if(info.rpl > this.cpl[0]) - { - // outer privilege return - if(is_16) - { - var temp_esp = this.safe_read16(this.get_stack_pointer(6)); - var temp_ss = this.safe_read16(this.get_stack_pointer(8)); - } - else - { - var temp_esp = this.safe_read32s(this.get_stack_pointer(12)); - var temp_ss = this.safe_read16(this.get_stack_pointer(16)); - } - - var ss_info = this.lookup_segment_selector(temp_ss); - var new_cpl = info.rpl; - - if(ss_info.is_null) - { - dbg_log("#GP for loading 0 in SS sel=" + h(temp_ss, 4), LOG_CPU); - dbg_trace(LOG_CPU); - this.trigger_gp_non_raising(0); - return; - } - - if(!ss_info.is_valid || - ss_info.is_system || - ss_info.rpl !== new_cpl || - !ss_info.is_writable || - ss_info.dpl !== new_cpl) - { - dbg_log("#GP for loading invalid in SS sel=" + h(temp_ss, 4), LOG_CPU); - dbg_trace(LOG_CPU); - this.trigger_gp_non_raising(temp_ss & ~3); - return; - } - - if(!ss_info.is_present) - { - dbg_log("#SS for loading non-present in SS sel=" + h(temp_ss, 4), LOG_CPU); - dbg_trace(LOG_CPU); - this.trigger_ss(temp_ss & ~3); - return; - } - - // no exceptions below - - if(is_16) - { - this.update_eflags(new_flags | this.flags[0] & ~0xFFFF); - } - else - { - this.update_eflags(new_flags); - } - - this.cpl[0] = info.rpl; - this.cpl_changed(); - - //dbg_log("outer privilege return: from=" + this.cpl[0] + " to=" + info.rpl + " ss:esp=" + h(temp_ss, 4) + ":" + h(temp_esp >>> 0, 8), LOG_CPU); - - if(!this.switch_seg(reg_ss, temp_ss)) dbg_assert(false); // XXX - - this.set_stack_reg(temp_esp); - - if(this.cpl[0] === 0) - { - this.flags[0] = this.flags[0] & ~flag_vif & ~flag_vip | (new_flags & (flag_vif | flag_vip)); - } - - - // XXX: Set segment to 0 if it's not usable in the new cpl - // XXX: Use cached segment information - //var ds_info = this.lookup_segment_selector(this.sreg[reg_ds]); - //if(this.cpl[0] > ds_info.dpl && (!ds_info.is_executable || !ds_info.dc_bit)) if(!this.switch_seg(reg_ds, 0)) ...; - // ... - } - else if(info.rpl === this.cpl[0]) - { - // same privilege return - // no exceptions below - if(is_16) - { - this.adjust_stack_reg(3 * 2); - this.update_eflags(new_flags | this.flags[0] & ~0xFFFF); - } - else - { - this.adjust_stack_reg(3 * 4); - this.update_eflags(new_flags); - } - - // update vip and vif, which are not changed by update_eflags - if(this.cpl[0] === 0) - { - this.flags[0] = this.flags[0] & ~flag_vif & ~flag_vip | (new_flags & (flag_vif | flag_vip)); - } - } - else - { - dbg_assert(false); - } - - this.sreg[reg_cs] = new_cs; - dbg_assert((new_cs & 3) === this.cpl[0]); - - this.update_cs_size(info.size); - - this.segment_limits[reg_cs] = info.effective_limit; - this.segment_offsets[reg_cs] = info.base; - - this.instruction_pointer[0] = new_eip + this.get_seg(reg_cs) | 0; - - CPU_LOG_VERBOSE && this.debug.dump_state("iret" + (is_16 ? "16" : "32") + " end"); - - this.handle_irqs(); -}; - CPU.prototype.far_return = function(eip, selector, stack_adjust) { dbg_assert(typeof selector === "number" && selector < 0x10000 && selector >= 0); diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 8c194eab..4aa5ced0 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -407,6 +407,273 @@ pub unsafe fn get_tss_stack_addr(dpl: u8) -> OrPageFault { Ok(translate_address_system_read(tss_stack_addr as i32)?) } +pub unsafe fn iret16() { iret(true); } +pub unsafe fn iret32() { iret(false); } + +pub unsafe fn iret(is_16: bool) { + if vm86_mode() && getiopl() < 3 { + // vm86 mode, iopl != 3 + dbg_log!("#gp iret vm86 mode, iopl != 3"); + trigger_gp_non_raising(0); + return; + } + + let (new_eip, new_cs, mut new_flags) = if is_16 { + ( + return_on_pagefault!(safe_read16(get_stack_pointer(0))), + return_on_pagefault!(safe_read16(get_stack_pointer(2))), + return_on_pagefault!(safe_read16(get_stack_pointer(4))), + ) + } + else { + ( + return_on_pagefault!(safe_read32s(get_stack_pointer(0))), + return_on_pagefault!(safe_read16(get_stack_pointer(4))), + return_on_pagefault!(safe_read32s(get_stack_pointer(8))), + ) + }; + + if !*protected_mode || (vm86_mode() && getiopl() == 3) { + if new_eip as u32 & 0xFFFF0000 != 0 { + panic!("#GP handler"); + } + + switch_cs_real_mode(new_cs); + *instruction_pointer = get_seg(CS) + new_eip; + + if is_16 { + update_eflags(new_flags | *flags & !0xFFFF); + adjust_stack_reg(3 * 2); + } + else { + update_eflags(new_flags); + adjust_stack_reg(3 * 4); + } + + handle_irqs(); + return; + } + + dbg_assert!(!vm86_mode()); + + if *flags & FLAG_NT != 0 { + if DEBUG { + panic!("NT"); + } + trigger_gp_non_raising(0); + return; + } + + if new_flags & FLAG_VM != 0 { + if *cpl == 0 { + // return to virtual 8086 mode + + // vm86 cannot be set in 16 bit flag + dbg_assert!(!is_16); + + dbg_assert!((new_eip & !0xFFFF) == 0); + + let temp_esp = return_on_pagefault!(safe_read32s(get_stack_pointer(12))); + let temp_ss = return_on_pagefault!(safe_read16(get_stack_pointer(16))); + + let new_es = return_on_pagefault!(safe_read16(get_stack_pointer(20))); + let new_ds = return_on_pagefault!(safe_read16(get_stack_pointer(24))); + let new_fs = return_on_pagefault!(safe_read16(get_stack_pointer(28))); + let new_gs = return_on_pagefault!(safe_read16(get_stack_pointer(32))); + + // no exceptions below + + update_eflags(new_flags); + *flags |= FLAG_VM; + + switch_cs_real_mode(new_cs); + *instruction_pointer = get_seg(CS) + (new_eip & 0xFFFF); + + if !switch_seg(ES, new_es) + || !switch_seg(DS, new_ds) + || !switch_seg(FS, new_fs) + || !switch_seg(GS, new_gs) + { + // XXX: Should be checked before side effects + dbg_assert!(false); + } + + adjust_stack_reg(9 * 4); // 9 dwords: eip, cs, flags, esp, ss, es, ds, fs, gs + + *reg32s.offset(ESP as isize) = temp_esp; + if !switch_seg(SS, temp_ss) { + // XXX + dbg_assert!(false); + } + + *cpl = 3; + cpl_changed(); + + update_cs_size(false); + + // iret end + return; + } + else { + dbg_log!("vm86 flag ignored because cpl != 0"); + new_flags &= !FLAG_VM; + } + } + + // protected mode return + + let (cs_descriptor, cs_selector) = match return_on_pagefault!(lookup_segment_selector(new_cs)) { + Ok((desc, sel)) => (desc, sel), + Err(selector_unusable) => match selector_unusable { + SelectorNullOrInvalid::IsNull => { + panic!("Unimplemented: CS selector is null"); + }, + SelectorNullOrInvalid::IsInvalid => { + panic!("Unimplemented: CS selector is invalid"); + }, + }, + }; + + dbg_assert!(new_eip as u32 <= cs_descriptor.effective_limit()); + + if !cs_descriptor.is_present() { + panic!("not present"); + } + if !cs_descriptor.is_executable() { + panic!("not exec"); + } + if cs_selector.rpl() < *cpl { + panic!("rpl < cpl"); + } + if cs_descriptor.is_dc() && cs_descriptor.dpl() > cs_selector.rpl() { + panic!("conforming and dpl > rpl"); + } + + if !cs_descriptor.is_dc() && cs_selector.rpl() != cs_descriptor.dpl() { + dbg_log!( + "#gp iret: non-conforming cs and rpl != dpl, dpl={} rpl={}", + cs_descriptor.dpl(), + cs_selector.rpl() + ); + trigger_gp_non_raising(new_cs & !3); + return; + } + + if cs_selector.rpl() > *cpl { + // outer privilege return + let (temp_esp, temp_ss) = if is_16 { + ( + return_on_pagefault!(safe_read16(get_stack_pointer(6))), + return_on_pagefault!(safe_read16(get_stack_pointer(8))), + ) + } + else { + ( + return_on_pagefault!(safe_read32s(get_stack_pointer(12))), + return_on_pagefault!(safe_read16(get_stack_pointer(16))), + ) + }; + + let (ss_descriptor, ss_selector) = + match return_on_pagefault!(lookup_segment_selector(temp_ss)) { + Ok((desc, sel)) => (desc, sel), + Err(selector_unusable) => match selector_unusable { + SelectorNullOrInvalid::IsNull => { + dbg_log!("#GP for loading 0 in SS sel={:x}", temp_ss); + dbg_trace(); + trigger_gp_non_raising(0); + return; + }, + SelectorNullOrInvalid::IsInvalid => { + dbg_log!("#GP for loading invalid in SS sel={:x}", temp_ss); + trigger_gp_non_raising(temp_ss & !3); + return; + }, + }, + }; + let new_cpl = cs_selector.rpl(); + + if ss_descriptor.is_system() + || ss_selector.rpl() != new_cpl + || !ss_descriptor.is_writable() + || ss_descriptor.dpl() != new_cpl + { + dbg_log!("#GP for loading invalid in SS sel={:x}", temp_ss); + dbg_trace(); + trigger_gp_non_raising(temp_ss & !3); + return; + } + + if !ss_descriptor.is_present() { + dbg_log!("#SS for loading non-present in SS sel={:x}", temp_ss); + dbg_trace(); + trigger_ss(temp_ss & !3); + return; + } + + // no exceptions below + + if is_16 { + update_eflags(new_flags | *flags & !0xFFFF); + } + else { + update_eflags(new_flags); + } + + *cpl = cs_selector.rpl(); + cpl_changed(); + + if !switch_seg(SS, temp_ss) { + // XXX + dbg_assert!(false); + } + + set_stack_reg(temp_esp); + + if *cpl == 0 { + *flags = *flags & !FLAG_VIF & !FLAG_VIP | (new_flags & (FLAG_VIF | FLAG_VIP)); + } + + // XXX: Set segment to 0 if it's not usable in the new cpl + // XXX: Use cached segment information + // ... + } + else if cs_selector.rpl() == *cpl { + // same privilege return + // no exceptions below + if is_16 { + adjust_stack_reg(3 * 2); + update_eflags(new_flags | *flags & !0xFFFF); + } + else { + adjust_stack_reg(3 * 4); + update_eflags(new_flags); + } + + // update vip and vif, which are not changed by update_eflags + if *cpl == 0 { + *flags = *flags & !FLAG_VIF & !FLAG_VIP | (new_flags & (FLAG_VIF | FLAG_VIP)); + } + } + else { + dbg_assert!(false); + } + + *sreg.offset(CS as isize) = new_cs as u16; + dbg_assert!((new_cs & 3) == *cpl as i32); + + update_cs_size(cs_descriptor.is_32()); + + *segment_limits.offset(CS as isize) = cs_descriptor.effective_limit(); + *segment_offsets.offset(CS as isize) = cs_descriptor.base(); + + *instruction_pointer = new_eip + get_seg(CS); + + // iret end + + handle_irqs(); +} + pub unsafe fn call_interrupt_vector( interrupt_nr: i32, is_software_int: bool, diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index fed3f291..1e9e4c6f 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -16,10 +16,6 @@ extern "C" { fn far_jump(eip: i32, selector: i32, is_call: bool); #[no_mangle] fn far_return(eip: i32, selector: i32, stack_adjust: i32); - #[no_mangle] - fn iret16(); - #[no_mangle] - fn iret32(); #[no_mangle] fn hlt_op(); From 3eb15d328de46f551aae518a00d7d0c9082a8745 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Mon, 22 Oct 2018 17:47:06 +0530 Subject: [PATCH 1435/2137] cpu: Update iret for minor fixes from manual Citations for these changes: https://imgur.com/a/QgNekKL --- src/rust/cpu2/cpu.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 4aa5ced0..4b38bf99 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -446,7 +446,12 @@ pub unsafe fn iret(is_16: bool) { adjust_stack_reg(3 * 2); } else { - update_eflags(new_flags); + if !*protected_mode { + update_eflags((new_flags & 0x257FD5) | (*flags & 0x1A0000)); + } + else { + update_eflags(new_flags); + } adjust_stack_reg(3 * 4); } @@ -630,7 +635,7 @@ pub unsafe fn iret(is_16: bool) { set_stack_reg(temp_esp); - if *cpl == 0 { + if *cpl == 0 && !is_16 { *flags = *flags & !FLAG_VIF & !FLAG_VIP | (new_flags & (FLAG_VIF | FLAG_VIP)); } @@ -651,7 +656,7 @@ pub unsafe fn iret(is_16: bool) { } // update vip and vif, which are not changed by update_eflags - if *cpl == 0 { + if *cpl == 0 && !is_16 { *flags = *flags & !FLAG_VIF & !FLAG_VIP | (new_flags & (FLAG_VIF | FLAG_VIP)); } } From 32606a26ac93aad7faf199921587539c1bd3d1df Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 29 Oct 2018 15:52:06 -0600 Subject: [PATCH 1436/2137] rtc: Implement alarm interrupt --- src/rtc.js | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 3 deletions(-) diff --git a/src/rtc.js b/src/rtc.js index b0eba22c..22247f5b 100644 --- a/src/rtc.js +++ b/src/rtc.js @@ -61,6 +61,9 @@ function RTC(cpu) // used for periodic interrupt this.next_interrupt = 0; + // next alarm interrupt + this.next_interrupt_alarm = 0; + this.periodic_interrupt = false; // corresponds to default value for cmos_a @@ -91,7 +94,7 @@ RTC.prototype.get_state = function() state[2] = this.rtc_time; state[3] = this.last_update; state[4] = this.next_interrupt; - + state[5] = this.next_interrupt_alarm; state[6] = this.periodic_interrupt; state[7] = this.periodic_interrupt_time; state[8] = this.cmos_a; @@ -109,7 +112,7 @@ RTC.prototype.set_state = function(state) this.rtc_time = state[2]; this.last_update = state[3]; this.next_interrupt = state[4]; - + this.next_interrupt_alarm = state[5]; this.periodic_interrupt = state[6]; this.periodic_interrupt_time = state[7]; this.cmos_a = state[8]; @@ -134,6 +137,13 @@ RTC.prototype.timer = function(time, legacy_mode) return Math.max(0, time - this.next_interrupt); } + else if(this.next_interrupt_alarm && this.next_interrupt_alarm < time) + { + this.cpu.device_raise_irq(8); + this.cmos_c |= 1 << 5 | 1 << 7; + + this.next_interrupt_alarm = 0; + } return 100; }; @@ -156,6 +166,18 @@ RTC.prototype.bcd_pack = function(n) return result; }; +RTC.prototype.bcd_unpack = function(n) +{ + const low = n & 0xF; + const high = n >> 4 & 0xF; + + dbg_assert(n < 0x100); + dbg_assert(low < 10); + dbg_assert(high < 10); + + return low + 10 * high; +}; + RTC.prototype.encode_time = function(t) { if(this.cmos_b & 4) @@ -169,6 +191,19 @@ RTC.prototype.encode_time = function(t) } }; +RTC.prototype.decode_time = function(t) +{ + if(this.cmos_b & 4) + { + // binary mode + return t; + } + else + { + return this.bcd_unpack(t); + } +}; + // TODO // - interrupt on update // - countdown @@ -248,11 +283,38 @@ RTC.prototype.cmos_port_write = function(data_byte) this.next_interrupt = Date.now(); } - if(this.cmos_b & 0x20) dbg_log("Unimplemented: alarm interrupt", LOG_RTC); + if(this.cmos_b & 0x20) + { + const now = new Date(); + + const seconds = this.decode_time(this.cmos_data[CMOS_RTC_SECONDS_ALARM]); + const minutes = this.decode_time(this.cmos_data[CMOS_RTC_MINUTES_ALARM]); + const hours = this.decode_time(this.cmos_data[CMOS_RTC_HOURS_ALARM]); + + const alarm_date = new Date(Date.UTC( + now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), + hours, minutes, seconds + )); + + const ms_from_now = alarm_date - now; + dbg_log("RTC alarm scheduled for " + alarm_date + + " hh:mm:ss=" + hours + ":" + minutes + ":" + seconds + + " ms_from_now=" + ms_from_now, LOG_RTC); + + this.next_interrupt_alarm = +alarm_date; + } + if(this.cmos_b & 0x10) dbg_log("Unimplemented: updated interrupt", LOG_RTC); dbg_log("cmos b=" + h(this.cmos_b, 2), LOG_RTC); break; + + case CMOS_RTC_SECONDS_ALARM: + case CMOS_RTC_MINUTES_ALARM: + case CMOS_RTC_HOURS_ALARM: + this.cmos_write(this.cmos_index, data_byte); + break; + default: dbg_log("cmos write index " + h(this.cmos_index) + ": " + h(data_byte), LOG_RTC); } From 58b8c49fb04bf989f07bca3bf019a896e851dba2 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 31 Oct 2018 11:50:33 -0600 Subject: [PATCH 1437/2137] Pack memory in state image, reduces memory use during state loading --- src/cpu.js | 83 +++++++++++++++++++++++++++++++++++++++++++++++++----- src/lib.js | 42 +++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 7 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index 7c716852..da5273b3 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -419,7 +419,6 @@ CPU.prototype.get_state = function() state[39] = this.reg32s; state[40] = this.sreg; state[41] = this.dreg; - state[42] = this.mem8; this.store_current_tsc(); state[43] = this.current_tsc; @@ -463,12 +462,22 @@ CPU.prototype.get_state = function() state[76] = this.fxsave_store_fpu_mask; + const { packed_memory, bitmap } = this.pack_memory(); + state[77] = packed_memory; + state[78] = new Uint8Array(bitmap.get_buffer()); + return state; }; CPU.prototype.set_state = function(state) { this.memory_size[0] = state[0]; + + if(this.mem8.length !== this.memory_size[0]) + { + console.warn("Note: Memory size mismatch. we=" + this.mem8.length + " state=" + this.memory_size[0]); + } + this.segment_is_null.set(state[1]); this.segment_offsets.set(state[2]); this.segment_limits.set(state[3]); @@ -508,12 +517,6 @@ CPU.prototype.set_state = function(state) this.sreg.set(state[40]); this.dreg.set(state[41]); - if(this.mem8.length !== state[42].length) - { - console.warn("Note: Memory size mismatch. we=" + this.mem8.length + " state=" + state[42].length); - } - this.mem8.set(state[42]); - this.set_tsc(state[43][0], state[43][1]); this.devices.virtio_9p = state[45]; @@ -555,11 +558,77 @@ CPU.prototype.set_state = function(state) this.fxsave_store_fpu_mask = state[76]; + const bitmap = new v86util.Bitmap(state[78].buffer); + const packed_memory = state[77]; + this.unpack_memory(bitmap, packed_memory); + this.full_clear_tlb(); this.update_operand_size(); }; +CPU.prototype.pack_memory = function() +{ + dbg_assert((this.mem8.length & 0xFFF) === 0); + + const page_count = this.mem8.length >> 12; + const nonzero_pages = []; + + for(let page = 0; page < page_count; page++) + { + const offset = page << 12; + const view = this.mem32s.subarray(offset >> 2, offset + 0x1000 >> 2); + let is_zero = true; + + for(let i = 0; i < view.length; i++) + { + if(view[i] !== 0) + { + is_zero = false; + break; + } + } + + if(!is_zero) + { + nonzero_pages.push(page); + } + } + + const bitmap = new v86util.Bitmap(page_count); + const packed_memory = new Uint8Array(nonzero_pages.length << 12); + + for(let [i, page] of nonzero_pages.entries()) + { + bitmap.set(page, 1); + + const offset = page << 12; + const page_contents = this.mem8.subarray(offset, offset + 0x1000); + packed_memory.set(page_contents, i << 12); + } + + return { bitmap, packed_memory }; +}; + +CPU.prototype.unpack_memory = function(bitmap, packed_memory) +{ + // TODO: Skip zeroing memory if the memory has just been allocated + this.mem8.fill(0); + + const page_count = this.memory_size[0] >> 12; + let packed_page = 0; + + for(let page = 0; page < page_count; page++) + { + if(bitmap.get(page)) + { + let offset = packed_page << 12; + let view = packed_memory.subarray(offset, offset + 0x1000); + this.mem8.set(view, page << 12); + packed_page++; + } + } +}; /** * @return {number} time in ms until this method should becalled again diff --git a/src/lib.js b/src/lib.js index 206d7fed..6f69d654 100644 --- a/src/lib.js +++ b/src/lib.js @@ -336,3 +336,45 @@ CircularQueue.prototype.set = function(new_data) this.data = new_data; this.index = 0; }; + +/** + * A simple 1d bitmap + */ +v86util.Bitmap = function(length_or_buffer) +{ + if(typeof length_or_buffer === "number") + { + this.view = new Uint8Array(length_or_buffer + 7 >> 3); + } + else if(length_or_buffer instanceof ArrayBuffer) + { + this.view = new Uint8Array(length_or_buffer); + } + else + { + console.assert(false); + } +}; + +v86util.Bitmap.prototype.set = function(index, value) +{ + const bit_index = index & 7; + const byte_index = index >> 3; + const bit_mask = 1 << bit_index; + + this.view[byte_index] = + value ? this.view[byte_index] | bit_mask : this.view[byte_index] & ~bit_mask; +}; + +v86util.Bitmap.prototype.get = function(index) +{ + const bit_index = index & 7; + const byte_index = index >> 3; + + return this.view[byte_index] >> bit_index & 1; +}; + +v86util.Bitmap.prototype.get_buffer = function() +{ + return this.view.buffer; +}; From 400673646f9e4c728fe604c2fd1e6852fff9ab6d Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 1 Nov 2018 19:24:27 -0600 Subject: [PATCH 1438/2137] Remove unused constants --- src/const.js | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/const.js b/src/const.js index bfdf8820..bd0795df 100644 --- a/src/const.js +++ b/src/const.js @@ -346,17 +346,6 @@ 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 = 1; -/** @const */ -const P_GEN_INSTR = 2; -/** @const */ -const P_RUN_FROM_CACHE = 3; -/** @const */ -const P_RUN_INTERPRETED = 4; - /** @const */ var WASM_TABLE_SIZE = 0x10000; From e7c16e6d96989c7dbcbae7c4c2dd549c68418171 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 4 Nov 2018 15:32:17 -0600 Subject: [PATCH 1439/2137] Use emulator.stop() to exit --- docker/debian-full/build-state.js | 42 +++++++++++++++---------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/docker/debian-full/build-state.js b/docker/debian-full/build-state.js index ce958655..c9dd8a67 100755 --- a/docker/debian-full/build-state.js +++ b/docker/debian-full/build-state.js @@ -19,6 +19,7 @@ var SCREEN_FILE = "/tmp/screen_debian_full.txt"; process.stdin.setRawMode(true); process.stdin.resume(); process.stdin.setEncoding("utf8"); +process.stdin.on("data", handle_key); var emulator = new V86({ bios: { url: path.join(V86_ROOT, "/bios/seabios.bin") }, @@ -43,19 +44,6 @@ console.log("Now booting, please stand by ..."); var boot_start = Date.now(); var serial_text = ""; -process.stdin.on("data", function(c) -{ - if(c === "\u0003") - { - // ctrl c - process.exit(); - } - else - { - emulator.serial0_send(c); - } -}); - emulator.add_listener("serial0-output-char", function(c) { process.stdout.write(c); @@ -81,18 +69,28 @@ emulator.add_listener("serial0-output-char", function(c) { if(e) throw e; console.error("Saved as " + OUTPUT_FILE); - emulator.stop(); - setTimeout(() => process.exit(0), 5000); + stop(); }); }); }, 5000); } }); -//function save_screen() -//{ -// var screen = emulator.screen_adapter.get_text_screen(); -// fs.writeFile(SCREEN_FILE, screen.join("\n"), function(e) { if(e) throw e; }); -//} -// -//setInterval(save_screen, 1000); +function handle_key(c) +{ + if(c === "\u0003") + { + // ctrl c + stop(); + } + else + { + emulator.serial0_send(c); + } +} + +function stop() +{ + emulator.stop(); + process.stdin.pause(); +} From 92346f51ed3ff710625170d533138de2570f4159 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 4 Nov 2018 15:36:29 -0600 Subject: [PATCH 1440/2137] Add test for clean shutdown --- Makefile | 1 + tests/api/clean-shutdown.js | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100755 tests/api/clean-shutdown.js diff --git a/Makefile b/Makefile index c680dfd4..1959e36b 100644 --- a/Makefile +++ b/Makefile @@ -275,6 +275,7 @@ rust-test-intensive: QUICKCHECK_TESTS=100000000 make rust-test api-tests: all-debug + ./tests/api/clean-shutdown.js ./tests/api/state.js covreport: diff --git a/tests/api/clean-shutdown.js b/tests/api/clean-shutdown.js new file mode 100755 index 00000000..77e458e6 --- /dev/null +++ b/tests/api/clean-shutdown.js @@ -0,0 +1,31 @@ +#!/usr/bin/env node +"use strict"; + +// This test checks that calling emulator.stop() will remove all event +// listeners, so that the nodejs process cleanly and automatically exits. + +const fs = require("fs"); +const V86 = require("../../build/libv86-debug.js").V86; + +process.on("unhandledRejection", exn => { throw exn; }); + +const config = { + bios: { url: __dirname + "/../../bios/seabios.bin" }, + vga_bios: { url: __dirname + "/../../bios/vgabios.bin" }, + cdrom: { url: __dirname + "/../../images/linux3.iso", async: true }, + network_relay_url: "", + autostart: true, + memory_size: 32 * 1024 * 1024, + filesystem: {}, + log_level: 0, + screen_dummy: true, +}; + +const emulator = new V86(config); + +setTimeout(function() + { + console.error("Calling stop()"); + emulator.stop(); + console.error("Called stop()"); + }, 3000); From 1650bf85fb5191119d462d60250e83e2c88579b8 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 21 Oct 2018 15:54:49 -0300 Subject: [PATCH 1441/2137] Add networking.sh for docker --- docker/debian-full/Dockerfile | 1 + docker/debian-full/networking.sh | 4 ++++ 2 files changed, 5 insertions(+) create mode 100644 docker/debian-full/networking.sh diff --git a/docker/debian-full/Dockerfile b/docker/debian-full/Dockerfile index 81558373..53269d77 100644 --- a/docker/debian-full/Dockerfile +++ b/docker/debian-full/Dockerfile @@ -46,6 +46,7 @@ COPY logind.conf /etc/systemd/logind.conf #COPY xinitrc /root/.xinitrc COPY xorg.conf /etc/X11/ COPY fluxbox /root/.fluxbox +COPY networking.sh /root/ COPY boot-9p /etc/initramfs-tools/scripts/boot-9p diff --git a/docker/debian-full/networking.sh b/docker/debian-full/networking.sh new file mode 100644 index 00000000..ba18fe5a --- /dev/null +++ b/docker/debian-full/networking.sh @@ -0,0 +1,4 @@ +rmmod ne2k-pci && modprobe ne2k-pci +ifconfig enp0s5 192.168.1.5 netmask 255.255.255.0 up +route add default gw 192.168.1.1 +echo "nameserver 8.8.8.8" > /etc/resolv.conf From 38b8435c880b2b8cb02f0494c53d6704a5e66977 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 4 Nov 2018 15:49:49 -0600 Subject: [PATCH 1442/2137] Print eip on bad instruction encodings --- gen/generate_interpreter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gen/generate_interpreter.js b/gen/generate_interpreter.js index 3006f87b..0b4c1db7 100755 --- a/gen/generate_interpreter.js +++ b/gen/generate_interpreter.js @@ -210,7 +210,7 @@ function gen_instruction_body_after_prefix(encodings, size) default_case: { body: [ - "assert!(false);", + `if DEBUG { panic!("Bad instruction at {:x}", *instruction_pointer); }`, "trigger_ud();", ], } From fa540e6e86700c48051c3a2bfded5c547eccb65b Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 4 Nov 2018 16:57:04 -0600 Subject: [PATCH 1443/2137] fs2json: Handle tar files that don't report file type in mode bits --- tools/fs2json.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/fs2json.py b/tools/fs2json.py index 71350d54..dea6d3ec 100755 --- a/tools/fs2json.py +++ b/tools/fs2json.py @@ -30,6 +30,9 @@ IDX_GID = 5 IDX_TARGET = 6 IDX_SHA256 = 6 +S_IFLNK = 0xA000 +S_IFREG = 0x8000 +S_IFDIR = 0x4000 def hash_file(filename): with open(filename, "rb", buffering=0) as f: @@ -225,6 +228,7 @@ def handle_tar(logger, tar): obj[IDX_GID] = member.gid if member.isfile() or member.islnk(): + obj[IDX_MODE] |= S_IFREG f = tar.extractfile(member) obj[IDX_SHA256] = hash_fileobj(f) if member.islnk(): @@ -232,8 +236,10 @@ def handle_tar(logger, tar): f.seek(0, os.SEEK_END) obj[IDX_SIZE] = int(f.tell()) elif member.isdir(): + obj[IDX_MODE] |= S_IFDIR obj[IDX_TARGET] = [] elif member.issym(): + obj[IDX_MODE] |= S_IFLNK obj[IDX_TARGET] = member.linkname else: logger.error("Unsupported type: {} ({})".format(member.type, name)) From 7a319220783acb292e54e75d9fa50946f1ada754 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 4 Nov 2018 16:58:20 -0600 Subject: [PATCH 1444/2137] Add test for bzimage_initrd_from_filesystem --- Makefile | 6 ++++++ tests/full/run.js | 26 +++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 1959e36b..9ccfbaee 100644 --- a/Makefile +++ b/Makefile @@ -232,6 +232,12 @@ $(CLOSURE): rm $(CLOSURE_DIR)/compiler-latest.zip tests: all-debug + mkdir -p images/integration-test-fs/flat + cp images/bzImage images/integration-test-fs/ + touch images/integration-test-fs/initrd + cd images/integration-test-fs && tar cfv fs.tar bzImage initrd + ./tools/fs2json.py images/integration-test-fs/fs.tar --out images/integration-test-fs/fs.json + ./tools/copy-to-sha256.py images/integration-test-fs/fs.tar images/integration-test-fs/flat ./tests/full/run.js nasmtests: all-debug diff --git a/tests/full/run.js b/tests/full/run.js index c73103d7..1485638e 100755 --- a/tests/full/run.js +++ b/tests/full/run.js @@ -228,6 +228,21 @@ if(cluster.isMaster) ], expect_mouse_registered: true, }, + { + name: "Linux 4 with bzImage from filesystem", + bzimage_initrd_from_filesystem: true, + filesystem: { + basefs: "./images/integration-test-fs/fs.json", + baseurl: "./images/integration-test-fs/flat/", + }, + cmdline: "auto", + timeout: 200, + expected_texts: [ + "~%", + "Files send via emulator appear in", + ], + expect_mouse_registered: true, + }, { name: "OpenBSD", fda: root_path + "/images/openbsd.img", @@ -461,7 +476,7 @@ function run_test(test, done) { console.log("Starting test: %s", test.name); - let image = test.fda || test.hda || test.cdrom || test.bzimage; + let image = test.fda || test.hda || test.cdrom || test.bzimage || test.filesystem.basefs; console.assert(image, "Bootable drive expected"); if(!fs.existsSync(image)) @@ -518,13 +533,18 @@ function run_test(test, done) } if(test.hda) { - settings.hda = { url: test.hda, async: true, }; + settings.hda = { url: test.hda, async: true }; } if(test.bzimage) { - settings.bzimage = { url: test.bzimage, async: true, }; + settings.bzimage = { url: test.bzimage }; + } + if(test.filesystem) + { + settings.filesystem = test.filesystem; } settings.cmdline = test.cmdline; + settings.bzimage_initrd_from_filesystem = test.bzimage_initrd_from_filesystem; if(test.expected_texts) { From 7720f9a8e6da123881924d2bd5b8344fa8a5e231 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 4 Nov 2018 17:05:58 -0600 Subject: [PATCH 1445/2137] Print opcode on unimplemented sse instructions --- src/cpu.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cpu.js b/src/cpu.js index da5273b3..48bbd7a4 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -2386,7 +2386,8 @@ CPU.prototype.undefined_instruction = function() CPU.prototype.unimplemented_sse = function() { - dbg_log("No SSE", LOG_CPU); + const opcode = this.safe_read32s(this.previous_ip[0]); + console.log("No SSE: " + h(opcode & 0xFF) + " " + h(opcode >> 8 & 0xFF) + " " + h(opcode >> 16 & 0xFF), LOG_CPU); dbg_assert(false); this.trigger_ud(); }; From ff3945bab4298b21a2e499d8e2071e44e412efbc Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 4 Nov 2018 17:11:57 -0600 Subject: [PATCH 1446/2137] Don't skip Linux 4 bzImage test --- tests/full/run.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/full/run.js b/tests/full/run.js index 1485638e..d20eaf2f 100755 --- a/tests/full/run.js +++ b/tests/full/run.js @@ -218,7 +218,6 @@ if(cluster.isMaster) }, { name: "Linux 4 bzImage", - skip_if_disk_image_missing: true, bzimage: root_path + "/images/bzImage", cmdline: "auto", timeout: 200, From 02f657b83628f46d50829acd47d0c380716289bc Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 4 Nov 2018 17:29:21 -0600 Subject: [PATCH 1447/2137] tools: Force python 3 --- tools/copy-to-sha256.py | 2 +- tools/fs2json.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/copy-to-sha256.py b/tools/copy-to-sha256.py index be6cf955..c3191b7c 100755 --- a/tools/copy-to-sha256.py +++ b/tools/copy-to-sha256.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import os import logging diff --git a/tools/fs2json.py b/tools/fs2json.py index dea6d3ec..99a95ef4 100755 --- a/tools/fs2json.py +++ b/tools/fs2json.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Note: # - Hardlinks are copied From 2233b069b3e7b1bf7366f8cb675d2d28d49058a0 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 4 Nov 2018 17:30:50 -0600 Subject: [PATCH 1448/2137] Mark Bitmap as constructor --- src/lib.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib.js b/src/lib.js index 6f69d654..811f134d 100644 --- a/src/lib.js +++ b/src/lib.js @@ -339,6 +339,7 @@ CircularQueue.prototype.set = function(new_data) /** * A simple 1d bitmap + * @constructor */ v86util.Bitmap = function(length_or_buffer) { From 01697a7ebb739b81a031360f196765863cabc4f6 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 4 Nov 2018 17:34:46 -0600 Subject: [PATCH 1449/2137] Delete some dead code --- src/cpu.js | 46 +++------------------------------------------- 1 file changed, 3 insertions(+), 43 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index 48bbd7a4..69d34463 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -21,13 +21,11 @@ function CPU(bus, wm, v86oxide, coverage_logger) const memory = v86oxide.instance.exports.memory; - if(false) Object.defineProperty(this, "memory_size", { get: () => { return new Uint32Array(memory.buffer, 812, 1); } }); this.memory_size = v86util.view(Uint32Array, memory, 812, 1); // Note: Currently unused (degrades performance and not required by any OS // that we support) this.a20_enabled = v86util.view(Int32Array, memory, 552, 1); - if(false) Object.defineProperty(this, "a20_enabled", { get: () => { return new Int32Array(memory.buffer, 552, 1); } }); this.a20_enabled[0] = +true; this.mem8 = new Uint8Array(0); @@ -35,24 +33,16 @@ function CPU(bus, wm, v86oxide, coverage_logger) this.mem32s = new Int32Array(this.mem8.buffer); this.segment_is_null = v86util.view(Uint8Array, memory, 724, 8); - if(false) Object.defineProperty(this, "segment_is_null", { get: () => { return new Uint8Array(memory.buffer, 724, 8); } }); - this.segment_offsets = v86util.view(Int32Array, memory, 736, 8); - if(false) Object.defineProperty(this, "segment_offsets", { get: () => { return new Int32Array(memory.buffer, 736, 8); } }); - this.segment_limits = v86util.view(Uint32Array, memory, 768, 8); - if(false) Object.defineProperty(this, "segment_limits", { get: () => { return new Uint32Array(memory.buffer, 768, 8); } }); /** * Wheter or not in protected mode */ this.protected_mode = v86util.view(Int32Array, memory, 800, 1); - if(false) Object.defineProperty(this, "protected_mode", { get: () => { return new Int32Array(memory.buffer, 800, 1); } }); this.idtr_size = v86util.view(Int32Array, memory, 564, 1); this.idtr_offset = v86util.view(Int32Array, memory, 568, 1); - if(false) Object.defineProperty(this, "idtr_size", { get: () => { return new Int32Array(memory.buffer, 564, 1); } }); - if(false) Object.defineProperty(this, "idtr_offset", { get: () => { return new Int32Array(memory.buffer, 568, 1); } }); /** * global descriptor table register @@ -60,19 +50,14 @@ function CPU(bus, wm, v86oxide, coverage_logger) this.gdtr_size = v86util.view(Int32Array, memory, 572, 1); this.gdtr_offset = v86util.view(Int32Array, memory, 576, 1); - if(false) Object.defineProperty(this, "gdtr_size", { get: () => { return new Int32Array(memory.buffer, 572, 1); } }); - if(false) Object.defineProperty(this, "gdtr_offset", { get: () => { return new Int32Array(memory.buffer, 576, 1); } }); - this.tss_size_32 = v86util.view(Int32Array, memory, 1128, 1); /* * whether or not a page fault occured */ this.page_fault = v86util.view(Uint32Array, memory, 540, 8); - if(false) Object.defineProperty(this, "page_fault", { get: () => { return new Uint32Array(memory.buffer, 540, 8); } }); this.cr = v86util.view(Int32Array, memory, 580, 8); - if(false) Object.defineProperty(this, "cr", { get: () => { return new Int32Array(memory.buffer, 580, 8); } }); /** @type {number} */ this.cr[0] = 0; @@ -85,27 +70,21 @@ function CPU(bus, wm, v86oxide, coverage_logger) // current privilege level this.cpl = v86util.view(Int32Array, memory, 612, 1); - if(false) Object.defineProperty(this, "cpl", { get: () => { return new Int32Array(memory.buffer, 612, 1); } }); // current operand/address size this.is_32 = v86util.view(Int32Array, memory, 804, 1); - if(false) Object.defineProperty(this, "is_32", { get: () => { return new Int32Array(memory.buffer, 804, 1); } }); this.stack_size_32 = v86util.view(Int32Array, memory, 808, 1); - if(false) Object.defineProperty(this, "stack_size_32", { get: () => { return new Int32Array(memory.buffer, 808, 1); } }); /** * Was the last instruction a hlt? */ this.in_hlt = v86util.view(Uint8Array, memory, 616, 1); - if(false) Object.defineProperty(this, "in_hlt", { get: () => { return new Uint8Array(memory.buffer, 616, 1); } }); this.last_virt_eip = v86util.view(Int32Array, memory, 620, 1); - this.eip_phys = v86util.view(Int32Array, memory, 624, 1); this.last_virt_esp = v86util.view(Int32Array, memory, 628, 1); - this.esp_phys = v86util.view(Int32Array, memory, 632, 1); @@ -116,33 +95,24 @@ function CPU(bus, wm, v86oxide, coverage_logger) this.sysenter_eip = v86util.view(Int32Array, memory, 644, 1); this.prefixes = v86util.view(Int32Array, memory, 648, 1); - if(false) Object.defineProperty(this, "prefixes", { get: () => { return new Int32Array(memory.buffer, 648, 1); } }); this.flags = v86util.view(Int32Array, memory, 536, 1); - if(false) Object.defineProperty(this, "flags", { get: () => { return new Int32Array(memory.buffer, 536, 1); } }); /** * bitmap of flags which are not updated in the flags variable * changed by arithmetic instructions, so only relevant to arithmetic flags */ this.flags_changed = v86util.view(Int32Array, memory, 532, 1); - if(false) Object.defineProperty(this, "flags_changed", { get: () => { return new Int32Array(memory.buffer, 532, 1); } }); /** * the last 2 operators and the result and size of the last arithmetic operation */ this.last_op1 = v86util.view(Int32Array, memory, 512, 1); - if(false) Object.defineProperty(this, "last_op1", { get: () => { return new Int32Array(memory.buffer, 512, 1); } }); this.last_op2 = v86util.view(Int32Array, memory, 516, 1); - if(false) Object.defineProperty(this, "last_op2", { get: () => { return new Int32Array(memory.buffer, 516, 1); } }); this.last_op_size = v86util.view(Int32Array, memory, 520, 1); - if(false) Object.defineProperty(this, "last_op_size", { get: () => { return new Int32Array(memory.buffer, 520, 1); } }); this.last_add_result = v86util.view(Int32Array, memory, 524, 1); - if(false) Object.defineProperty(this, "last_add_result", { get: () => { return new Int32Array(memory.buffer, 524, 1); } }); - this.last_result = v86util.view(Int32Array, memory, 528, 1); - if(false) Object.defineProperty(this, "last_result", { get: () => { return new Int32Array(memory.buffer, 528, 1); } }); this.current_tsc = v86util.view(Uint32Array, memory, 956, 2); // 64 bit @@ -150,10 +120,7 @@ function CPU(bus, wm, v86oxide, coverage_logger) this.devices = {}; this.instruction_pointer = v86util.view(Int32Array, memory, 556, 1); - if(false) Object.defineProperty(this, "instruction_pointer", { get: () => { return new Int32Array(memory.buffer, 556, 1); } }); - this.previous_ip = v86util.view(Int32Array, memory, 560, 1); - if(false) Object.defineProperty(this, "previous_ip", { get: () => { return new Int32Array(memory.buffer, 560, 1); } }); this.apic_enabled = true; @@ -172,7 +139,6 @@ function CPU(bus, wm, v86oxide, coverage_logger) vga: null, }; - if(false) Object.defineProperty(this, "timestamp_counter", { get: () => { return new Int32Array(memory.buffer, 664, 1); } }); this.timestamp_counter = v86util.view(Uint32Array, memory, 664, 1); // registers @@ -182,12 +148,6 @@ function CPU(bus, wm, v86oxide, coverage_logger) this.reg16 = v86util.view(Uint16Array, memory, 4, 16); this.reg8s = v86util.view(Int8Array, memory, 4, 32); this.reg8 = v86util.view(Uint8Array, memory, 4, 32); - if(false) Object.defineProperty(this, "reg32s", { get: () => { return new Int32Array(memory.buffer, 4, 8); } }); - if(false) Object.defineProperty(this, "reg32", { get: () => { return new Uint32Array(memory.buffer, 4, 8); } }); - if(false) Object.defineProperty(this, "reg16s", { get: () => { return new Int16Array(memory.buffer, 4, 16); } }); - if(false) Object.defineProperty(this, "reg16", { get: () => { return new Uint16Array(memory.buffer, 4, 16); } }); - if(false) Object.defineProperty(this, "reg8s", { get: () => { return new Int8Array(memory.buffer, 4, 32); } }); - if(false) Object.defineProperty(this, "reg8", { get: () => { return new Uint8Array(memory.buffer, 4, 32); } }); // Why no Float80Array :-( this.fpu_st = v86util.view(Float64Array, memory, 968, 8); @@ -226,7 +186,6 @@ function CPU(bus, wm, v86oxide, coverage_logger) // segment registers, tr and ldtr this.sreg = v86util.view(Uint16Array, memory, 668, 8); - if(false) Object.defineProperty(this, "sreg", { get: () => { return new Uint16Array(memory.buffer, 668, 8); } }); // debug registers this.dreg = v86util.view(Int32Array, memory, 684, 8); @@ -1412,7 +1371,6 @@ var seen_code_uncompiled = {}; CPU.prototype.codegen_finalize = function(wasm_table_index, start, end, first_opcode, state_flags) { dbg_assert(wasm_table_index >= 0 && wasm_table_index < WASM_TABLE_SIZE); - //dbg_log("finalize"); const code = this.wasmgen_get_module_code(); if(DEBUG) @@ -1421,7 +1379,9 @@ CPU.prototype.codegen_finalize = function(wasm_table_index, start, end, first_op { this.debug.dump_wasm(code); - if(false) + const DUMP_ASSEMBLY = false; + + if(DUMP_ASSEMBLY) { if((start ^ end) & ~0xFFF) { From 608559fa94f3bb7a55d41878d854005ee16dfc15 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 4 Nov 2018 17:40:29 -0600 Subject: [PATCH 1450/2137] Call hlt_loop immediately on an hlt instruction --- src/cpu.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index 69d34463..6b7b12b2 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -1322,12 +1322,7 @@ CPU.prototype.do_run = function() if(this.in_hlt[0]) { - let t = this.hlt_loop(); - - if(this.in_hlt[0]) - { - return t; - } + return; } now = v86.microtick(); @@ -2336,6 +2331,11 @@ CPU.prototype.hlt_op = function() // get out of here and into hlt_loop this.in_hlt[0] = +true; + + // Try an hlt loop right now: This will run timer interrupts, and if one is + // due it will immediately call call_interrupt_vector and continue + // execution without an unnecessary cycle through do_run + this.hlt_loop(); }; CPU.prototype.undefined_instruction = function() From 639ec0019bb2c176a8ab3f327cd0f32036dce858 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 4 Nov 2018 17:46:58 -0600 Subject: [PATCH 1451/2137] Commit a temporary workaround --- lib/9p.js | 6 ++++++ tests/devices/virtio_9p.js | 1 + 2 files changed, 7 insertions(+) diff --git a/lib/9p.js b/lib/9p.js index 4146bf22..05f6c66b 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -824,6 +824,11 @@ Virtio9p.prototype.ReceiveRequest = async function (bufchain) { // jshint ignore var newfid = req[1]; var name = req[2]; message.Debug("[xattrwalk]: fid=" + req[0] + " newfid=" + req[1] + " name=" + req[2]); + + // Workaround for Linux restarts writes until full blocksize + this.SendError(tag, "Setxattr not supported", EOPNOTSUPP); + this.SendReply(bufchain); + /* this.fids[newfid] = this.Createfid(this.fids[fid].inodeid, FID_NONE, this.fids[fid].uid, this.fids[fid].dbg_name); //this.fids[newfid].inodeid = this.fids[fid].inodeid; //this.fids[newfid].type = FID_NONE; @@ -835,6 +840,7 @@ Virtio9p.prototype.ReceiveRequest = async function (bufchain) { // jshint ignore marshall.Marshall(["d"], [length], this.replybuffer, 7); this.BuildReply(id, tag, 8); this.SendReply(bufchain); + */ break; default: diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index ce3e48c2..c46ef55d 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -927,6 +927,7 @@ const tests = { name: "Report All Security Capabilities", timeout: 60, + allow_failure: true, start: () => { emulator.serial0_send("touch /mnt/file\n"); From 88f482fae09bdc2969bd47d9ae4ad2af3aa6f28c Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 4 Nov 2018 17:48:19 -0600 Subject: [PATCH 1452/2137] Commit temporary workaround --- src/virtio.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/virtio.js b/src/virtio.js index 75f4e633..d4793b31 100644 --- a/src/virtio.js +++ b/src/virtio.js @@ -1190,7 +1190,8 @@ VirtQueue.prototype.flush_replies = function() has_passed = used_event < new_idx || old_idx <= used_event; } - if(has_passed) + // Commented out: Workaround for sometimes loading from the filesystem hangs and the emulator stays idle + //if(has_passed) { this.virtio.raise_irq(VIRTIO_ISR_QUEUE); } From df1ebec737df25d2a152e126ee54f814c70360b3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 4 Nov 2018 18:47:31 -0600 Subject: [PATCH 1453/2137] sync & drop caches before saving state --- docker/debian-full/build-state.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docker/debian-full/build-state.js b/docker/debian-full/build-state.js index c9dd8a67..e9e95b51 100755 --- a/docker/debian-full/build-state.js +++ b/docker/debian-full/build-state.js @@ -43,6 +43,7 @@ console.log("Now booting, please stand by ..."); var boot_start = Date.now(); var serial_text = ""; +let booted = false; emulator.add_listener("serial0-output-char", function(c) { @@ -50,11 +51,13 @@ emulator.add_listener("serial0-output-char", function(c) serial_text += c; - if(serial_text.endsWith("root@localhost:~# ")) + if(!booted && serial_text.endsWith("root@localhost:~# ")) { console.error("\nBooted in %d", (Date.now() - boot_start) / 1000); + booted = true; - // wait a few seconds as the serial console finishes faster than the screen terminal + // sync and drop caches: Makes it safer to change the filesystem as fewer files are rendered + emulator.serial0_send("sync;echo 3 >/proc/sys/vm/drop_caches\n"); setTimeout(function () { @@ -72,7 +75,7 @@ emulator.add_listener("serial0-output-char", function(c) stop(); }); }); - }, 5000); + }, 10 * 1000); } }); From 6a06a7108abca5cf02afa4e638e6e9e0d3f7c85b Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Thu, 27 Sep 2018 12:12:24 +1200 Subject: [PATCH 1454/2137] Tidy: file_storage snake case and interface naming convention --- lib/filesystem.js | 2 +- src/browser/filestorage.js | 10 +++++----- src/browser/starter.js | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 963b31ee..a7aaa235 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -45,7 +45,7 @@ var STATUS_FORWARDING = 0x5; /** * @constructor - * @param {FileStorage=} storage + * @param {FileStorageInterface=} storage * @param {{ last_qidnumber: number }=} qidcounter Another fs's qidcounter to synchronise with. */ function FS(storage, qidcounter) { diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index 154204f7..0fa30c29 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -7,24 +7,24 @@ const INDEXEDDB_STORAGE_KEYPATH = "sha256sum"; const INDEXEDDB_STORAGE_VALUEPATH = "data"; /** @interface */ -function FileStorage() {} +function FileStorageInterface() {} /** * @param {string} sha256sum * @return {!Promise} */ -FileStorage.prototype.get = function(sha256sum) {}; +FileStorageInterface.prototype.get = function(sha256sum) {}; /** * @param {string} sha256sum * @param {!Uint8Array} data * @return {!Promise} */ -FileStorage.prototype.set = function(sha256sum, buffer) {}; +FileStorageInterface.prototype.set = function(sha256sum, buffer) {}; /** * @constructor - * @implements {FileStorage} + * @implements {FileStorageInterface} * @param {string=} baseurl */ function MemoryFileStorage(baseurl) @@ -101,7 +101,7 @@ MemoryFileStorage.prototype.set = function(sha256sum, buffer) /** * @constructor - * @implements {FileStorage} + * @implements {FileStorageInterface} * @param {string=} baseurl */ function IndexedDBFileStorage(baseurl) diff --git a/src/browser/starter.js b/src/browser/starter.js index 15edb2de..6307f71e 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -448,10 +448,10 @@ V86Starter.prototype.continue_init = function(emulator, options) var fs_url = options["filesystem"]["basefs"]; var base_url = options["filesystem"]["baseurl"]; - const fileStorage = typeof indexedDB === "undefined" ? + const file_storage = typeof indexedDB === "undefined" ? new MemoryFileStorage(base_url) : new IndexedDBFileStorage(base_url); - this.fs9p = new FS(fileStorage); + this.fs9p = new FS(file_storage); settings.fs9p = this.fs9p; if(fs_url) @@ -1048,10 +1048,10 @@ V86Starter.prototype.serial0_send = function(data) */ V86Starter.prototype.mount_fs = function(path, baseurl, basefs, callback) { - const fileStorage = typeof indexedDB === "undefined" ? + const file_storage = typeof indexedDB === "undefined" ? new MemoryFileStorage(baseurl) : new IndexedDBFileStorage(baseurl); - const newfs = new FS(fileStorage, this.fs9p.qidcounter); + const newfs = new FS(file_storage, this.fs9p.qidcounter); const mount = () => { const idx = this.fs9p.Mount(path, newfs); From c0299449655f9982bfa7bee15ba3009b0401599b Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 30 Sep 2018 11:57:56 +1300 Subject: [PATCH 1455/2137] Filesystem: Distinguish server file via inode status. Also make file_storage a mandatory argument to FS. --- lib/filesystem.js | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index a7aaa235..7fd63763 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -26,6 +26,7 @@ var O_ACCMODE = 0x0003; // mask for above modes var STATUS_INVALID = -0x1; var STATUS_OK = 0x0; +var STATUS_ON_SERVER = 0x2; var STATUS_UNLINKED = 0x4; var STATUS_FORWARDING = 0x5; @@ -45,7 +46,7 @@ var STATUS_FORWARDING = 0x5; /** * @constructor - * @param {FileStorageInterface=} storage + * @param {!FileStorageInterface} storage * @param {{ last_qidnumber: number }=} qidcounter Another fs's qidcounter to synchronise with. */ function FS(storage, qidcounter) { @@ -127,7 +128,7 @@ FS.prototype.set_state = function(state) FS.prototype.AddEvent = function(id, OnEvent) { var inode = this.inodes[id]; - if (inode.status == STATUS_OK) { + if (inode.status == STATUS_OK || inode.status == STATUS_ON_SERVER) { OnEvent(); } else if(this.is_forwarder(inode)) @@ -209,6 +210,7 @@ FS.prototype.LoadRecursive = function(data, parentid) } else if(ifmt === S_IFREG) { + inode.status = STATUS_ON_SERVER; inode.sha256sum = data[JSONFS_IDX_SHA256]; this.PushInode(inode, parentid, name); } @@ -1073,15 +1075,19 @@ FS.prototype.get_data = async function(idx) // jshint ignore:line const inode = this.inodes[idx]; dbg_assert(inode, `Filesystem get_data: idx ${idx} does not point to an inode`); - if(this.inodedata[idx]) return this.inodedata[idx]; - if(inode.sha256sum && this.storage) + if(this.inodedata[idx]) { - const data = await this.storage.get(inode.sha256sum); // jshint ignore:line - // XXX: Temporary cache until storage can properly chunk - this.inodedata[idx] = data; - return data; + return this.inodedata[idx]; + } + else if(inode.status === STATUS_ON_SERVER) + { + dbg_assert(inode.sha256sum, "Filesystem get_data: found inode on server without sha256sum"); + return await this.storage.get(inode.sha256sum); // jshint ignore:line + } + else + { + return null; } - return null; }; // jshint ignore:line /** From c2dcb440dd745dbd32084fe95c1587db448a8bab Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Tue, 13 Nov 2018 01:28:03 +1300 Subject: [PATCH 1456/2137] Filestorage: Refactor fallback and load-from-server Fallback logic is moved to the caller's responsibility. Empty FileStorages and FileStorages that load from the server are separated into different classes. This is to avoid faults where the caller of the constructor forgets to pass in a `baseurl` parameter and leads to some confusing bug. --- src/browser/filestorage.js | 254 ++++++++++++++++++++++--------------- src/browser/starter.js | 43 +++++-- 2 files changed, 185 insertions(+), 112 deletions(-) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index 0fa30c29..420b0b9c 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -25,12 +25,9 @@ FileStorageInterface.prototype.set = function(sha256sum, buffer) {}; /** * @constructor * @implements {FileStorageInterface} - * @param {string=} baseurl */ -function MemoryFileStorage(baseurl) +function MemoryFileStorage() { - this.baseurl = baseurl; - /** * From sha256sum to file data. * @type {Map} @@ -39,95 +36,64 @@ function MemoryFileStorage(baseurl) } /** - * @private * @param {string} sha256sum - * @return {!Promise} + * @return {Uint8Array} */ -MemoryFileStorage.prototype.load_from_server = function(sha256sum) -{ - return new Promise((resolve, reject) => - { - if(!this.baseurl) - { - resolve(null); - return; - } - - v86util.load_file(this.baseurl + sha256sum, { done: buffer => - { - const data = new Uint8Array(buffer); - this.filedata.set(sha256sum, data); - resolve(data); - }}); - }); -}; - -/** - * @param {string} sha256sum - * @return {!Promise} - */ -MemoryFileStorage.prototype.get = function(sha256sum) +MemoryFileStorage.prototype.get = async function(sha256sum) // jshint ignore:line { dbg_assert(sha256sum !== "", "MemoryFileStorage get: sha256sum should not be an empty string"); - - return new Promise((resolve, reject) => - { - if(this.filedata.has(sha256sum)) - { - resolve(this.filedata.get(sha256sum)); - } - else - { - this.load_from_server(sha256sum).then(data => resolve(data)); - } - }); -}; + return this.filedata.get(sha256sum); +}; // jshint ignore:line /** * @param {string} sha256sum * @param {!Uint8Array} data - * @return {!Promise} */ -MemoryFileStorage.prototype.set = function(sha256sum, buffer) +MemoryFileStorage.prototype.set = async function(sha256sum, buffer) // jshint ignore:line { dbg_assert(sha256sum !== "", "MemoryFileStorage set: sha256sum should not be an empty string"); - - return new Promise((resolve, reject) => - { - this.filedata.set(sha256sum, buffer); - resolve(); - }); -}; + this.filedata.set(sha256sum, buffer); +}; // jshint ignore:line /** * @constructor * @implements {FileStorageInterface} - * @param {string=} baseurl */ -function IndexedDBFileStorage(baseurl) +function IndexedDBFileStorage() { - this.fallback_storage = new MemoryFileStorage(baseurl); - this.baseurl = baseurl; + dbg_assert(window.indexedDB, "IndexedDBFileStorage - indexedDB not available."); this.db = null; +} - if(typeof indexedDB === "undefined") +IndexedDBFileStorage.try_create = async function() // jshint ignore:line +{ + if(typeof window === "undefined" || !window.indexedDB) { - dbg_log("IndexedDB not available. Using MemoryFileStorage as fallback.", LOG_9P); + throw new Error("IndexedDB is not available"); } - else + const file_storage = new IndexedDBFileStorage(); + await file_storage.init(); // jshint ignore:line + return file_storage; +}; // jshint ignore:line + +IndexedDBFileStorage.prototype.init = function() +{ + dbg_assert(!this.db, "IndexedDBFileStorage init: Database already intiialised"); + + return new Promise((resolve, reject) => { const open_request = indexedDB.open(INDEXEDDB_STORAGE_NAME, INDEXEDDB_STORAGE_VERSION); open_request.onblocked = event => { dbg_log("IndexedDB blocked by an older database version being opened.", LOG_9P); - dbg_log("Using MemoryFileStorage until unblocked.", LOG_9P); }; open_request.onerror = event => { - dbg_log("Error opening IndexedDB! Are you in private browsing mode? ", LOG_9P); - dbg_log("Falling back to MemoryFileStorage. Error: " + open_request.error, LOG_9P); + dbg_log("Error opening IndexedDB! Are you in private browsing mode? Error:", LOG_9P); + dbg_log(open_request.error, LOG_9P); + reject(); }; open_request.onupgradeneeded = event => @@ -138,9 +104,6 @@ function IndexedDBFileStorage(baseurl) open_request.onsuccess = event => { - // Fallback no longer needed. - this.fallback_storage = null; - this.db = open_request.result; this.db.onabort = event => { @@ -156,34 +119,12 @@ function IndexedDBFileStorage(baseurl) }; this.db.onversionchange = event => { + // TODO: double check this message dbg_log("Warning: another v86 instance is trying to open IndexedDB database but " + "is blocked by this current v86 instance.", LOG_9P); }; + resolve(); }; - } -} - -/** - * @private - * @param {string} sha256sum - * @return {!Promise} - */ -IndexedDBFileStorage.prototype.load_from_server = function(sha256sum) -{ - dbg_assert(this.db, "IndexedDBFileStorage load_from_server called without opening database"); - - return new Promise((resolve, reject) => - { - if(!this.baseurl) - { - resolve(null); - return; - } - v86util.load_file(this.baseurl + sha256sum, { done: buffer => - { - const data = new Uint8Array(buffer); - this.set(sha256sum, data).then(() => resolve(data)); - }}); }); }; @@ -193,13 +134,9 @@ IndexedDBFileStorage.prototype.load_from_server = function(sha256sum) */ IndexedDBFileStorage.prototype.get = function(sha256sum) { + dbg_assert(this.db, "IndexedDBFileStorage get: Database is not initialised"); dbg_assert(sha256sum !== "", "IndexedDBFileStorage get: sha256sum should not be an empty string"); - if(!this.db) - { - return this.fallback_storage.get(sha256sum); - } - return new Promise((resolve, reject) => { const transaction = this.db.transaction(INDEXEDDB_STORAGE_STORE, "readonly"); @@ -216,7 +153,7 @@ IndexedDBFileStorage.prototype.get = function(sha256sum) } else { - this.load_from_server(sha256sum).then(data => resolve(data)); + resolve(null); } }; }); @@ -229,13 +166,9 @@ IndexedDBFileStorage.prototype.get = function(sha256sum) */ IndexedDBFileStorage.prototype.set = function(sha256sum, data) { + dbg_assert(this.db, "IndexedDBFileStorage set: Database is not initialised"); dbg_assert(sha256sum !== "", "IndexedDBFileStorage set: sha256sum should not be an empty string"); - if(!this.db) - { - return this.fallback_storage.get(sha256sum); - } - return new Promise((resolve, reject) => { const transaction = this.db.transaction(INDEXEDDB_STORAGE_STORE, "readwrite"); @@ -247,3 +180,124 @@ IndexedDBFileStorage.prototype.set = function(sha256sum, data) request.onsuccess = event => resolve(); }); }; + +/** + * @constructor + * @implements {FileStorageInterface} + * @param {string} baseurl + */ +function ServerMemoryFileStorage(baseurl) +{ + dbg_assert(baseurl, "ServerMemoryFileStorage: baseurl should not be empty"); + + this.empty_storage = new MemoryFileStorage(); + this.baseurl = baseurl; +} + +/** + * @private + * @param {string} sha256sum + * @return {!Promise} + */ +ServerMemoryFileStorage.prototype.load_from_server = function(sha256sum) +{ + return new Promise((resolve, reject) => + { + v86util.load_file(this.baseurl + sha256sum, { done: buffer => + { + const data = new Uint8Array(buffer); + this.set(sha256sum, data).then(() => resolve(data)); + }}); + }); +}; + +/** + * @param {string} sha256sum + * @return {Uint8Array} + */ +ServerMemoryFileStorage.prototype.get = async function(sha256sum) // jshint ignore:line +{ + const data = await this.empty_storage.get(sha256sum); // jshint ignore:line + if(!data) + { + return await this.load_from_server(sha256sum); // jshint ignore:line + } + return data; +}; // jshint ignore:line + +/** + * @param {string} sha256sum + * @param {!Uint8Array} data + */ +ServerMemoryFileStorage.prototype.set = async function(sha256sum, data) // jshint ignore:line +{ + await this.empty_storage.set(sha256sum, data); // jshint ignore:line +}; // jshint ignore:line + +/** + * @constructor + * @implements {FileStorageInterface} + * @param {string} baseurl + */ +function ServerIndexedDBFileStorage(baseurl) +{ + dbg_assert(baseurl, "ServerIndexedDBFileStorage: baseurl should not be empty"); + + this.empty_storage = new IndexedDBFileStorage(); + this.baseurl = baseurl; +} + +/** + * @param {string} baseurl + * @return {IndexedDBFileStorage} + */ +ServerIndexedDBFileStorage.try_create = async function(baseurl) // jshint ignore:line +{ + if(typeof window === "undefined" || !window.indexedDB) + { + throw new Error("IndexedDB is not available"); + } + const file_storage = new ServerIndexedDBFileStorage(baseurl); + await file_storage.empty_storage.init(); // jshint ignore:line + return file_storage; +}; // jshint ignore:line + +/** + * @private + * @param {string} sha256sum + * @return {!Promise} + */ +ServerIndexedDBFileStorage.prototype.load_from_server = function(sha256sum) +{ + return new Promise((resolve, reject) => + { + v86util.load_file(this.baseurl + sha256sum, { done: buffer => + { + const data = new Uint8Array(buffer); + this.set(sha256sum, data).then(() => resolve(data)); + }}); + }); +}; + +/** + * @param {string} sha256sum + * @return {Uint8Array} + */ +ServerIndexedDBFileStorage.prototype.get = async function(sha256sum) // jshint ignore:line +{ + const data = await this.empty_storage.get(sha256sum); // jshint ignore:line + if(!data) + { + return await this.load_from_server(sha256sum); // jshint ignore:line + } + return data; +}; // jshint ignore:line + +/** + * @param {string} sha256sum + * @param {!Uint8Array} data + */ +ServerIndexedDBFileStorage.prototype.set = async function(sha256sum, data) // jshint ignore:line +{ + await this.empty_storage.set(sha256sum, data); // jshint ignore:line +}; // jshint ignore:line diff --git a/src/browser/starter.js b/src/browser/starter.js index 6307f71e..d916a726 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -218,7 +218,7 @@ function V86Starter(options) }); } -V86Starter.prototype.continue_init = function(emulator, options) +V86Starter.prototype.continue_init = async function(emulator, options) // jshint ignore:line { this.bus.register("emulator-stopped", function() { @@ -448,11 +448,20 @@ V86Starter.prototype.continue_init = function(emulator, options) var fs_url = options["filesystem"]["basefs"]; var base_url = options["filesystem"]["baseurl"]; - const file_storage = typeof indexedDB === "undefined" ? - new MemoryFileStorage(base_url) : - new IndexedDBFileStorage(base_url); - this.fs9p = new FS(file_storage); - settings.fs9p = this.fs9p; + const IdealFileStorage = base_url ? ServerIndexedDBFileStorage : IndexedDBFileStorage; + const FallbackFileStorage = base_url ? ServerMemoryFileStorage : MemoryFileStorage; + let file_storage; + try + { + file_storage = await IdealFileStorage.try_create(base_url); // jshint ignore:line + } + catch(e) + { + dbg_log("Initializing IndexedDBFileStorage failed due to Error: " + e); + dbg_log("Falling back to MemoryFileStorage instead."); + file_storage = new FallbackFileStorage(base_url); + } + settings.fs9p = this.fs9p = new FS(file_storage); if(fs_url) { @@ -605,7 +614,7 @@ V86Starter.prototype.continue_init = function(emulator, options) this.emulator_bus.send("emulator-loaded"); } } -}; +}; // jshint ignore:line V86Starter.prototype.get_bzimage_initrd_from_filesystem = function(filesystem) { @@ -1046,11 +1055,21 @@ V86Starter.prototype.serial0_send = function(data) * @param {function(Object)=} callback * @export */ -V86Starter.prototype.mount_fs = function(path, baseurl, basefs, callback) +V86Starter.prototype.mount_fs = async function(path, baseurl, basefs, callback) // jshint ignore:line { - const file_storage = typeof indexedDB === "undefined" ? - new MemoryFileStorage(baseurl) : - new IndexedDBFileStorage(baseurl); + const IdealFileStorage = baseurl ? ServerIndexedDBFileStorage : IndexedDBFileStorage; + const FallbackFileStorage = baseurl ? ServerMemoryFileStorage : MemoryFileStorage; + let file_storage; + try + { + file_storage = await IdealFileStorage.try_create(baseurl); // jshint ignore:line + } + catch(e) + { + dbg_log("Initializing IndexedDBFileStorage failed due to Error: " + e); + dbg_log("Falling back to MemoryFileStorage instead."); + file_storage = new FallbackFileStorage(baseurl); + } const newfs = new FS(file_storage, this.fs9p.qidcounter); const mount = () => { @@ -1086,7 +1105,7 @@ V86Starter.prototype.mount_fs = function(path, baseurl, basefs, callback) { mount(); } -}; +}; // jshint ignore:line /** * Write to a file in the 9p filesystem. Nothing happens if no filesystem has From a85dd50169654bb595076bb7029ed2aa43d73b2c Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Tue, 13 Nov 2018 10:58:44 +1300 Subject: [PATCH 1457/2137] Filestorage: Improve assert coverage and robustness Checks that sha256sum is also not undefrined nor null. Avoids ReferenceError when window is not defined e.g. on NodeJS. --- src/browser/filestorage.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index 420b0b9c..9ff997d9 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -41,7 +41,7 @@ function MemoryFileStorage() */ MemoryFileStorage.prototype.get = async function(sha256sum) // jshint ignore:line { - dbg_assert(sha256sum !== "", "MemoryFileStorage get: sha256sum should not be an empty string"); + dbg_assert(sha256sum, "MemoryFileStorage get: sha256sum should be a non-empty string"); return this.filedata.get(sha256sum); }; // jshint ignore:line @@ -51,7 +51,7 @@ MemoryFileStorage.prototype.get = async function(sha256sum) // jshint ignore:lin */ MemoryFileStorage.prototype.set = async function(sha256sum, buffer) // jshint ignore:line { - dbg_assert(sha256sum !== "", "MemoryFileStorage set: sha256sum should not be an empty string"); + dbg_assert(sha256sum, "MemoryFileStorage set: sha256sum should be a non-empty string"); this.filedata.set(sha256sum, buffer); }; // jshint ignore:line @@ -61,7 +61,8 @@ MemoryFileStorage.prototype.set = async function(sha256sum, buffer) // jshint ig */ function IndexedDBFileStorage() { - dbg_assert(window.indexedDB, "IndexedDBFileStorage - indexedDB not available."); + dbg_assert(typeof window !== "undefined" && window.indexedDB, + "IndexedDBFileStorage - indexedDB not available."); this.db = null; } @@ -78,7 +79,7 @@ IndexedDBFileStorage.try_create = async function() // jshint ignore:line IndexedDBFileStorage.prototype.init = function() { - dbg_assert(!this.db, "IndexedDBFileStorage init: Database already intiialised"); + dbg_assert(!this.db, "IndexedDBFileStorage init: Database already intiialized"); return new Promise((resolve, reject) => { @@ -134,8 +135,8 @@ IndexedDBFileStorage.prototype.init = function() */ IndexedDBFileStorage.prototype.get = function(sha256sum) { - dbg_assert(this.db, "IndexedDBFileStorage get: Database is not initialised"); - dbg_assert(sha256sum !== "", "IndexedDBFileStorage get: sha256sum should not be an empty string"); + dbg_assert(this.db, "IndexedDBFileStorage get: Database is not initialized"); + dbg_assert(sha256sum, "IndexedDBFileStorage get: sha256sum should be a non-empty string"); return new Promise((resolve, reject) => { @@ -166,8 +167,8 @@ IndexedDBFileStorage.prototype.get = function(sha256sum) */ IndexedDBFileStorage.prototype.set = function(sha256sum, data) { - dbg_assert(this.db, "IndexedDBFileStorage set: Database is not initialised"); - dbg_assert(sha256sum !== "", "IndexedDBFileStorage set: sha256sum should not be an empty string"); + dbg_assert(this.db, "IndexedDBFileStorage set: Database is not initialized"); + dbg_assert(sha256sum, "IndexedDBFileStorage set: sha256sum should be a non-empty string"); return new Promise((resolve, reject) => { From 93d9f6923e9eeabf050da1a94feac4234d921f9b Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Tue, 13 Nov 2018 10:59:52 +1300 Subject: [PATCH 1458/2137] Filestorage: Prevent overlapped reinitialization of IndexedDB Catches cases when IndexDBFileStorage#init is accidentally called in multiple places. --- src/browser/filestorage.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index 9ff997d9..8205c8de 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -64,6 +64,7 @@ function IndexedDBFileStorage() dbg_assert(typeof window !== "undefined" && window.indexedDB, "IndexedDBFileStorage - indexedDB not available."); this.db = null; + this.initializing = false; } IndexedDBFileStorage.try_create = async function() // jshint ignore:line @@ -80,6 +81,8 @@ IndexedDBFileStorage.try_create = async function() // jshint ignore:line IndexedDBFileStorage.prototype.init = function() { dbg_assert(!this.db, "IndexedDBFileStorage init: Database already intiialized"); + dbg_assert(!this.initializing, "IndexedDBFileStorage init: Database already intiializing"); + this.initializing = true; return new Promise((resolve, reject) => { @@ -94,6 +97,7 @@ IndexedDBFileStorage.prototype.init = function() { dbg_log("Error opening IndexedDB! Are you in private browsing mode? Error:", LOG_9P); dbg_log(open_request.error, LOG_9P); + this.initializing = false; reject(); }; @@ -105,6 +109,7 @@ IndexedDBFileStorage.prototype.init = function() open_request.onsuccess = event => { + this.initializing = false; this.db = open_request.result; this.db.onabort = event => { From 83b283ebbeb28a8b278553a5ca37d35fae3e7673 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Tue, 13 Nov 2018 11:57:06 +1300 Subject: [PATCH 1459/2137] Filestorage: Replace the two server classes with a wrapper class Simplifies both the filestorage.js code as well as the starter.js code that uses these FileStorage classes. Now, the ServerFileStorageWrapper decorates the other FileStorage classes by loading from the server when the file is not available. Moreover, the previous starter.js was incorrectly passing the `baseurl` parameter (it was passing it when baseurl was not defined nor needed). --- src/browser/filestorage.js | 83 ++++---------------------------------- src/browser/starter.js | 20 +++++---- 2 files changed, 20 insertions(+), 83 deletions(-) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index 8205c8de..3a084db8 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -190,13 +190,14 @@ IndexedDBFileStorage.prototype.set = function(sha256sum, data) /** * @constructor * @implements {FileStorageInterface} + * @param {FileStorageInterface} file_storage * @param {string} baseurl */ -function ServerMemoryFileStorage(baseurl) +function ServerFileStorageWrapper(file_storage, baseurl) { dbg_assert(baseurl, "ServerMemoryFileStorage: baseurl should not be empty"); - this.empty_storage = new MemoryFileStorage(); + this.storage = file_storage; this.baseurl = baseurl; } @@ -205,7 +206,7 @@ function ServerMemoryFileStorage(baseurl) * @param {string} sha256sum * @return {!Promise} */ -ServerMemoryFileStorage.prototype.load_from_server = function(sha256sum) +ServerFileStorageWrapper.prototype.load_from_server = function(sha256sum) { return new Promise((resolve, reject) => { @@ -221,9 +222,9 @@ ServerMemoryFileStorage.prototype.load_from_server = function(sha256sum) * @param {string} sha256sum * @return {Uint8Array} */ -ServerMemoryFileStorage.prototype.get = async function(sha256sum) // jshint ignore:line +ServerFileStorageWrapper.prototype.get = async function(sha256sum) // jshint ignore:line { - const data = await this.empty_storage.get(sha256sum); // jshint ignore:line + const data = await this.storage.get(sha256sum); // jshint ignore:line if(!data) { return await this.load_from_server(sha256sum); // jshint ignore:line @@ -235,75 +236,7 @@ ServerMemoryFileStorage.prototype.get = async function(sha256sum) // jshint igno * @param {string} sha256sum * @param {!Uint8Array} data */ -ServerMemoryFileStorage.prototype.set = async function(sha256sum, data) // jshint ignore:line +ServerFileStorageWrapper.prototype.set = async function(sha256sum, data) // jshint ignore:line { - await this.empty_storage.set(sha256sum, data); // jshint ignore:line -}; // jshint ignore:line - -/** - * @constructor - * @implements {FileStorageInterface} - * @param {string} baseurl - */ -function ServerIndexedDBFileStorage(baseurl) -{ - dbg_assert(baseurl, "ServerIndexedDBFileStorage: baseurl should not be empty"); - - this.empty_storage = new IndexedDBFileStorage(); - this.baseurl = baseurl; -} - -/** - * @param {string} baseurl - * @return {IndexedDBFileStorage} - */ -ServerIndexedDBFileStorage.try_create = async function(baseurl) // jshint ignore:line -{ - if(typeof window === "undefined" || !window.indexedDB) - { - throw new Error("IndexedDB is not available"); - } - const file_storage = new ServerIndexedDBFileStorage(baseurl); - await file_storage.empty_storage.init(); // jshint ignore:line - return file_storage; -}; // jshint ignore:line - -/** - * @private - * @param {string} sha256sum - * @return {!Promise} - */ -ServerIndexedDBFileStorage.prototype.load_from_server = function(sha256sum) -{ - return new Promise((resolve, reject) => - { - v86util.load_file(this.baseurl + sha256sum, { done: buffer => - { - const data = new Uint8Array(buffer); - this.set(sha256sum, data).then(() => resolve(data)); - }}); - }); -}; - -/** - * @param {string} sha256sum - * @return {Uint8Array} - */ -ServerIndexedDBFileStorage.prototype.get = async function(sha256sum) // jshint ignore:line -{ - const data = await this.empty_storage.get(sha256sum); // jshint ignore:line - if(!data) - { - return await this.load_from_server(sha256sum); // jshint ignore:line - } - return data; -}; // jshint ignore:line - -/** - * @param {string} sha256sum - * @param {!Uint8Array} data - */ -ServerIndexedDBFileStorage.prototype.set = async function(sha256sum, data) // jshint ignore:line -{ - await this.empty_storage.set(sha256sum, data); // jshint ignore:line + await this.storage.set(sha256sum, data); // jshint ignore:line }; // jshint ignore:line diff --git a/src/browser/starter.js b/src/browser/starter.js index d916a726..15cc321c 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -448,18 +448,20 @@ V86Starter.prototype.continue_init = async function(emulator, options) // jshint var fs_url = options["filesystem"]["basefs"]; var base_url = options["filesystem"]["baseurl"]; - const IdealFileStorage = base_url ? ServerIndexedDBFileStorage : IndexedDBFileStorage; - const FallbackFileStorage = base_url ? ServerMemoryFileStorage : MemoryFileStorage; let file_storage; try { - file_storage = await IdealFileStorage.try_create(base_url); // jshint ignore:line + file_storage = await IndexedDBFileStorage.try_create(); // jshint ignore:line } catch(e) { dbg_log("Initializing IndexedDBFileStorage failed due to Error: " + e); dbg_log("Falling back to MemoryFileStorage instead."); - file_storage = new FallbackFileStorage(base_url); + file_storage = new MemoryFileStorage(); + } + if (base_url) + { + file_storage = new ServerFileStorageWrapper(file_storage, base_url); } settings.fs9p = this.fs9p = new FS(file_storage); @@ -1057,18 +1059,20 @@ V86Starter.prototype.serial0_send = function(data) */ V86Starter.prototype.mount_fs = async function(path, baseurl, basefs, callback) // jshint ignore:line { - const IdealFileStorage = baseurl ? ServerIndexedDBFileStorage : IndexedDBFileStorage; - const FallbackFileStorage = baseurl ? ServerMemoryFileStorage : MemoryFileStorage; let file_storage; try { - file_storage = await IdealFileStorage.try_create(baseurl); // jshint ignore:line + file_storage = await IndexedDBFileStorage.try_create(); // jshint ignore:line } catch(e) { dbg_log("Initializing IndexedDBFileStorage failed due to Error: " + e); dbg_log("Falling back to MemoryFileStorage instead."); - file_storage = new FallbackFileStorage(baseurl); + file_storage = new MemoryFileStorage(); + } + if(baseurl) + { + file_storage = new ServerFileStorageWrapper(file_storage, baseurl); } const newfs = new FS(file_storage, this.fs9p.qidcounter); const mount = () => From 8b64844d27eb1f192f64f270531bd229fe6b6f4f Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 14 Nov 2018 10:59:06 +1300 Subject: [PATCH 1460/2137] Filestorage: Give project-related name for IndexedDB Storage --- src/browser/filestorage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index 3a084db8..016599df 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -1,8 +1,8 @@ "use strict"; const INDEXEDDB_STORAGE_VERSION = 1; -const INDEXEDDB_STORAGE_NAME = "IndexedDBFileStorage"; -const INDEXEDDB_STORAGE_STORE = "Store"; +const INDEXEDDB_STORAGE_NAME = "v86-filesystem-storage"; +const INDEXEDDB_STORAGE_STORE = "store"; const INDEXEDDB_STORAGE_KEYPATH = "sha256sum"; const INDEXEDDB_STORAGE_VALUEPATH = "data"; From dfb47f59075b21d2b481c1fb8aac963ea1c97c67 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Thu, 15 Nov 2018 10:27:03 +1300 Subject: [PATCH 1461/2137] Filesystem Tests: Add stopping-on-first-failure option --- tests/devices/virtio_9p.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index c46ef55d..863ea244 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -7,6 +7,7 @@ const fs = require("fs"); const testfsjson = require("./testfs.json"); const SHOW_LOGS = false; +const STOP_ON_FIRST_FAILURE = false; function log_pass(msg, ...args) { @@ -1807,6 +1808,11 @@ function report_test() else { log_fail("Test #%d failed: %s", test_num, tests[test_num].name); + + if(STOP_ON_FIRST_FAILURE) + { + finish_tests(); + } } test_has_failed = false; } From 7cfe865556040c4836cb2987de535733fd8b1349 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 18 Nov 2018 12:07:38 +1300 Subject: [PATCH 1462/2137] Filestorage: Draft chunking behind existing FileStorage interface --- src/browser/filestorage.js | 138 ++++++++++++++++++++++++++++--------- 1 file changed, 104 insertions(+), 34 deletions(-) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index 016599df..a0eb81ae 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -3,8 +3,14 @@ const INDEXEDDB_STORAGE_VERSION = 1; const INDEXEDDB_STORAGE_NAME = "v86-filesystem-storage"; const INDEXEDDB_STORAGE_STORE = "store"; -const INDEXEDDB_STORAGE_KEYPATH = "sha256sum"; -const INDEXEDDB_STORAGE_VALUEPATH = "data"; +const INDEXEDDB_STORAGE_KEY_PATH = "sha256sum"; +const INDEXEDDB_STORAGE_DATA_PATH = "data"; +const INDEXEDDB_STORAGE_EXTRABLOCKCOUNT_PATH = "extra-block-count"; +const INDEXEDDB_STORAGE_BLOCKSIZE_PATH = "block-size"; +const INDEXEDDB_STORAGE_TOTALSIZE_PATH = "total-size"; +const INDEXEDDB_STORAGE_GET_BLOCK_KEY = (sha256sum, block_number) => `${sha256sum}-${block_number}`; +const INDEXEDDB_STORAGE_CHUNKING_THRESHOLD = 4096; +const INDEXEDDB_STORAGE_BLOCKSIZE = 4096; /** @interface */ function FileStorageInterface() {} @@ -104,7 +110,7 @@ IndexedDBFileStorage.prototype.init = function() open_request.onupgradeneeded = event => { const db = open_request.result; - db.createObjectStore(INDEXEDDB_STORAGE_STORE, { keyPath: INDEXEDDB_STORAGE_KEYPATH }); + db.createObjectStore(INDEXEDDB_STORAGE_STORE, { keyPath: INDEXEDDB_STORAGE_KEY_PATH }); }; open_request.onsuccess = event => @@ -135,58 +141,122 @@ IndexedDBFileStorage.prototype.init = function() }; /** - * @param {string} sha256sum - * @return {!Promise} + * @param {string} key + * @return {!Promise} */ -IndexedDBFileStorage.prototype.get = function(sha256sum) +IndexedDBFileStorage.prototype.db_get = function(key) { - dbg_assert(this.db, "IndexedDBFileStorage get: Database is not initialized"); - dbg_assert(sha256sum, "IndexedDBFileStorage get: sha256sum should be a non-empty string"); - return new Promise((resolve, reject) => { const transaction = this.db.transaction(INDEXEDDB_STORAGE_STORE, "readonly"); const store = transaction.objectStore(INDEXEDDB_STORAGE_STORE); - const request = store.get(sha256sum); - request.onsuccess = event => - { - dbg_assert(!request.result || request.result.data instanceof Uint8Array, - "IndexedDBFileStorage get: invalid entry format: " + request.result); - - if(request.result && request.result.data instanceof Uint8Array) - { - resolve(request.result.data); - } - else - { - resolve(null); - } - }; + const request = store.get(key); + request.onsuccess = event => resolve(request.result); }); }; /** - * @param {string} sha256sum - * @param {!Uint8Array} data + * @param {Object} value * @return {!Promise} */ -IndexedDBFileStorage.prototype.set = function(sha256sum, data) +IndexedDBFileStorage.prototype.db_set = function(value) { - dbg_assert(this.db, "IndexedDBFileStorage set: Database is not initialized"); - dbg_assert(sha256sum, "IndexedDBFileStorage set: sha256sum should be a non-empty string"); - return new Promise((resolve, reject) => { const transaction = this.db.transaction(INDEXEDDB_STORAGE_STORE, "readwrite"); const store = transaction.objectStore(INDEXEDDB_STORAGE_STORE); - const request = store.put({ - [INDEXEDDB_STORAGE_KEYPATH]: sha256sum, - [INDEXEDDB_STORAGE_VALUEPATH]: data, - }); + const request = store.put(value); request.onsuccess = event => resolve(); }); }; +/** + * TODO: Convert this into a single atomic transaction. + * @param {string} sha256sum + * @return {!Uint8Array} + */ +IndexedDBFileStorage.prototype.get = async function(sha256sum) // jshint ignore:line +{ + dbg_assert(this.db, "IndexedDBFileStorage get: Database is not initialized"); + dbg_assert(sha256sum, "IndexedDBFileStorage get: sha256sum should be a non-empty string"); + + const entry = await this.db_get(sha256sum); // jshint ignore:line + + if(!entry) + { + return null; + } + + const base_data = entry[INDEXEDDB_STORAGE_DATA_PATH]; + const extra_block_count = entry[INDEXEDDB_STORAGE_EXTRABLOCKCOUNT_PATH]; + const block_size = entry[INDEXEDDB_STORAGE_BLOCKSIZE_PATH]; + const total_size = entry[INDEXEDDB_STORAGE_TOTALSIZE_PATH]; + + dbg_assert(base_data instanceof Uint8Array, + `IndexedDBFileStorage get: Invalid base entry without the data Uint8Array field: ${base_data}`); + dbg_assert(Number.isInteger(extra_block_count), + `IndexedDBFileStorage get: Invalid base entry with non-integer block_count: ${extra_block_count}`); + dbg_assert(Number.isInteger(block_size), + `IndexedDBFileStorage get: Invalid base entry with non-integer block_size: ${block_size}`); + dbg_assert(Number.isInteger(total_size) && total_size >= base_data.length, + `IndexedDBFileStorage get: Invalid base entry with invalid total_size: ${total_size}`); + + const file_data = new Uint8Array(total_size); + file_data.set(base_data); + + for(let i = 0, offset = base_data.length; i < extra_block_count; i++, offset += block_size) + { + const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, i); + const block_entry = await this.db_get(block_key); // jshint ignore:line + + dbg_assert(block_entry, `IndexedDBFileStorage get: Missing entry for block-${i}`); + + const block_data = block_entry[INDEXEDDB_STORAGE_DATA_PATH]; + dbg_assert(block_data instanceof Uint8Array, + `IndexedDBFileStorage get: Entry for block-${i} without Uint8Array data field: ${block_data}`); + + file_data.set(block_data, offset); + } + + return file_data; +}; // jshint ignore:line + +/** + * XXX: When shrinking a large file, the old blocks aren't deleted. This is ok for now with the + * current scheme of keeping IndexedDB contents read-only. + * @param {string} sha256sum + * @param {!Uint8Array} data + */ +IndexedDBFileStorage.prototype.set = async function(sha256sum, data) // jshint ignore:line +{ + dbg_assert(this.db, "IndexedDBFileStorage set: Database is not initialized"); + dbg_assert(sha256sum, "IndexedDBFileStorage set: sha256sum should be a non-empty string"); + + const extra_block_count = Math.ceil( + (data.length - INDEXEDDB_STORAGE_CHUNKING_THRESHOLD) / + INDEXEDDB_STORAGE_BLOCKSIZE + ); + + await this.db_set({ // jshint ignore:line + [INDEXEDDB_STORAGE_KEY_PATH]: sha256sum, + [INDEXEDDB_STORAGE_DATA_PATH]: data.subarray(0, INDEXEDDB_STORAGE_CHUNKING_THRESHOLD), + [INDEXEDDB_STORAGE_BLOCKSIZE_PATH]: INDEXEDDB_STORAGE_BLOCKSIZE, + [INDEXEDDB_STORAGE_TOTALSIZE_PATH]: data.length, + [INDEXEDDB_STORAGE_EXTRABLOCKCOUNT_PATH]: extra_block_count, + }); + + let offset = INDEXEDDB_STORAGE_CHUNKING_THRESHOLD; + for(let i = 0; offset < data.length; i++, offset += INDEXEDDB_STORAGE_BLOCKSIZE) + { + const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, i); + const block_data = data.subarray(offset, offset + INDEXEDDB_STORAGE_BLOCKSIZE); + await this.db_set({ //jshint ignore:line + [INDEXEDDB_STORAGE_KEY_PATH]: block_key, + [INDEXEDDB_STORAGE_DATA_PATH]: block_data, + }); + } +}; // jshint ignore:line + /** * @constructor * @implements {FileStorageInterface} From efa45a3d1176cd5309223241848b35534efac928 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 18 Nov 2018 12:39:54 +1300 Subject: [PATCH 1463/2137] Filestorage: Make filestorage .get .set atomic ...by sticking to the same transaction throughout an operation. --- src/browser/filestorage.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index a0eb81ae..2fb76c21 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -141,14 +141,14 @@ IndexedDBFileStorage.prototype.init = function() }; /** + * @param {IDBTransaction} transaction * @param {string} key * @return {!Promise} */ -IndexedDBFileStorage.prototype.db_get = function(key) +IndexedDBFileStorage.prototype.db_get = function(transaction, key) { return new Promise((resolve, reject) => { - const transaction = this.db.transaction(INDEXEDDB_STORAGE_STORE, "readonly"); const store = transaction.objectStore(INDEXEDDB_STORAGE_STORE); const request = store.get(key); request.onsuccess = event => resolve(request.result); @@ -156,14 +156,14 @@ IndexedDBFileStorage.prototype.db_get = function(key) }; /** + * @param {IDBTransaction} transaction * @param {Object} value * @return {!Promise} */ -IndexedDBFileStorage.prototype.db_set = function(value) +IndexedDBFileStorage.prototype.db_set = function(transaction, value) { return new Promise((resolve, reject) => { - const transaction = this.db.transaction(INDEXEDDB_STORAGE_STORE, "readwrite"); const store = transaction.objectStore(INDEXEDDB_STORAGE_STORE); const request = store.put(value); request.onsuccess = event => resolve(); @@ -171,7 +171,6 @@ IndexedDBFileStorage.prototype.db_set = function(value) }; /** - * TODO: Convert this into a single atomic transaction. * @param {string} sha256sum * @return {!Uint8Array} */ @@ -180,6 +179,8 @@ IndexedDBFileStorage.prototype.get = async function(sha256sum) // jshint ignore: dbg_assert(this.db, "IndexedDBFileStorage get: Database is not initialized"); dbg_assert(sha256sum, "IndexedDBFileStorage get: sha256sum should be a non-empty string"); + const transaction = this.db.transaction(INDEXEDDB_STORAGE_STORE, "readonly"); + const entry = await this.db_get(sha256sum); // jshint ignore:line if(!entry) @@ -207,7 +208,7 @@ IndexedDBFileStorage.prototype.get = async function(sha256sum) // jshint ignore: for(let i = 0, offset = base_data.length; i < extra_block_count; i++, offset += block_size) { const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, i); - const block_entry = await this.db_get(block_key); // jshint ignore:line + const block_entry = await this.db_get(transaction, block_key); // jshint ignore:line dbg_assert(block_entry, `IndexedDBFileStorage get: Missing entry for block-${i}`); @@ -232,12 +233,14 @@ IndexedDBFileStorage.prototype.set = async function(sha256sum, data) // jshint i dbg_assert(this.db, "IndexedDBFileStorage set: Database is not initialized"); dbg_assert(sha256sum, "IndexedDBFileStorage set: sha256sum should be a non-empty string"); + const transaction = this.db.transaction(INDEXEDDB_STORAGE_STORE, "readwrite"); + const extra_block_count = Math.ceil( (data.length - INDEXEDDB_STORAGE_CHUNKING_THRESHOLD) / INDEXEDDB_STORAGE_BLOCKSIZE ); - await this.db_set({ // jshint ignore:line + await this.db_set(transaction, { // jshint ignore:line [INDEXEDDB_STORAGE_KEY_PATH]: sha256sum, [INDEXEDDB_STORAGE_DATA_PATH]: data.subarray(0, INDEXEDDB_STORAGE_CHUNKING_THRESHOLD), [INDEXEDDB_STORAGE_BLOCKSIZE_PATH]: INDEXEDDB_STORAGE_BLOCKSIZE, @@ -250,7 +253,7 @@ IndexedDBFileStorage.prototype.set = async function(sha256sum, data) // jshint i { const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, i); const block_data = data.subarray(offset, offset + INDEXEDDB_STORAGE_BLOCKSIZE); - await this.db_set({ //jshint ignore:line + await this.db_set(transaction, { //jshint ignore:line [INDEXEDDB_STORAGE_KEY_PATH]: block_key, [INDEXEDDB_STORAGE_DATA_PATH]: block_data, }); From afd27597d717002525f28c3dcfef2e18e2ef21d8 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 18 Nov 2018 19:28:38 +1300 Subject: [PATCH 1464/2137] Filestorage: Draft chunking behind new FileStorage interface --- src/browser/filestorage.js | 214 ++++++++++++++++++++++++++++--------- 1 file changed, 163 insertions(+), 51 deletions(-) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index 2fb76c21..364e059e 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -6,7 +6,6 @@ const INDEXEDDB_STORAGE_STORE = "store"; const INDEXEDDB_STORAGE_KEY_PATH = "sha256sum"; const INDEXEDDB_STORAGE_DATA_PATH = "data"; const INDEXEDDB_STORAGE_EXTRABLOCKCOUNT_PATH = "extra-block-count"; -const INDEXEDDB_STORAGE_BLOCKSIZE_PATH = "block-size"; const INDEXEDDB_STORAGE_TOTALSIZE_PATH = "total-size"; const INDEXEDDB_STORAGE_GET_BLOCK_KEY = (sha256sum, block_number) => `${sha256sum}-${block_number}`; const INDEXEDDB_STORAGE_CHUNKING_THRESHOLD = 4096; @@ -17,16 +16,25 @@ function FileStorageInterface() {} /** * @param {string} sha256sum - * @return {!Promise} + * @param {number} offset + * @param {number} count + * @return {!Promise} null if file does not exist. */ -FileStorageInterface.prototype.get = function(sha256sum) {}; +FileStorageInterface.prototype.read = function(sha256sum, offset, count) {}; /** * @param {string} sha256sum - * @param {!Uint8Array} data - * @return {!Promise} + * @param {number} offset + * @param {!Uint8Array} buffer + * @return {!Promise} Promise to the new file size as file may have grown. */ -FileStorageInterface.prototype.set = function(sha256sum, buffer) {}; +FileStorageInterface.prototype.write = function(sha256sum, offset, buffer) {}; + +/** + * @param {string} sha256sum + * @param {number} length + */ +FileStorageInterface.prototype.change_size = function(sha256sum, length) {}; /** * @constructor @@ -43,22 +51,52 @@ function MemoryFileStorage() /** * @param {string} sha256sum - * @return {Uint8Array} + * @param {number} offset + * @param {number} count + * @return {!Uint8Array} null if file does not exist. */ -MemoryFileStorage.prototype.get = async function(sha256sum) // jshint ignore:line +MemoryFileStorage.prototype.read = async function(sha256sum, offset, count) // jshint ignore:line { dbg_assert(sha256sum, "MemoryFileStorage get: sha256sum should be a non-empty string"); - return this.filedata.get(sha256sum); + const data = this.filedata.get(sha256sum); + + if(!data) + { + return null; + } + + return data.subarray(offset, offset + count); }; // jshint ignore:line /** * @param {string} sha256sum + * @param {number} offset * @param {!Uint8Array} data + * @return {number} New file size as file may have grown after writing. */ -MemoryFileStorage.prototype.set = async function(sha256sum, buffer) // jshint ignore:line +MemoryFileStorage.prototype.write = async function(sha256sum, offset, buffer) // jshint ignore:line { dbg_assert(sha256sum, "MemoryFileStorage set: sha256sum should be a non-empty string"); - this.filedata.set(sha256sum, buffer); + + const needed_size = offset + buffer.length; + let data = this.filedata.get(sha256sum); + + if(!data) + { + data = new Uint8Array(needed_size); + } + + if(data.length < needed_size) + { + const old_data = data; + data = new Uint8Array(needed_size); + data.set(old_data); + } + + data.set(buffer, offset); + this.filedata.set(sha256sum, data); + + return data.length; }; // jshint ignore:line /** @@ -172,16 +210,17 @@ IndexedDBFileStorage.prototype.db_set = function(transaction, value) /** * @param {string} sha256sum - * @return {!Uint8Array} + * @param {number} offset + * @param {number} count + * @return {!Uint8Array} null if file does not exist. */ -IndexedDBFileStorage.prototype.get = async function(sha256sum) // jshint ignore:line +IndexedDBFileStorage.prototype.read = async function(sha256sum, offset, count) // jshint ignore:line { dbg_assert(this.db, "IndexedDBFileStorage get: Database is not initialized"); dbg_assert(sha256sum, "IndexedDBFileStorage get: sha256sum should be a non-empty string"); const transaction = this.db.transaction(INDEXEDDB_STORAGE_STORE, "readonly"); - - const entry = await this.db_get(sha256sum); // jshint ignore:line + const entry = await this.db_get(transaction, sha256sum); // jshint ignore:line if(!entry) { @@ -190,74 +229,142 @@ IndexedDBFileStorage.prototype.get = async function(sha256sum) // jshint ignore: const base_data = entry[INDEXEDDB_STORAGE_DATA_PATH]; const extra_block_count = entry[INDEXEDDB_STORAGE_EXTRABLOCKCOUNT_PATH]; - const block_size = entry[INDEXEDDB_STORAGE_BLOCKSIZE_PATH]; const total_size = entry[INDEXEDDB_STORAGE_TOTALSIZE_PATH]; dbg_assert(base_data instanceof Uint8Array, `IndexedDBFileStorage get: Invalid base entry without the data Uint8Array field: ${base_data}`); dbg_assert(Number.isInteger(extra_block_count), `IndexedDBFileStorage get: Invalid base entry with non-integer block_count: ${extra_block_count}`); - dbg_assert(Number.isInteger(block_size), - `IndexedDBFileStorage get: Invalid base entry with non-integer block_size: ${block_size}`); dbg_assert(Number.isInteger(total_size) && total_size >= base_data.length, `IndexedDBFileStorage get: Invalid base entry with invalid total_size: ${total_size}`); - const file_data = new Uint8Array(total_size); - file_data.set(base_data); + const read_data = new Uint8Array(count); + let read_count = 0; - for(let i = 0, offset = base_data.length; i < extra_block_count; i++, offset += block_size) + if(offset < base_data.length) { - const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, i); + const chunk = base_data.subarray(offset, offset + count); + read_data.set(chunk); + read_count += chunk.length; + } + + let block_number = Math.floor( + (offset + read_count - base_data.length) / + INDEXEDDB_STORAGE_BLOCKSIZE + ); + for(; read_count < count && block_number < extra_block_count; block_number++) + { + const block_offset = base_data.length + block_number * INDEXEDDB_STORAGE_BLOCKSIZE; + const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, block_number); const block_entry = await this.db_get(transaction, block_key); // jshint ignore:line - dbg_assert(block_entry, `IndexedDBFileStorage get: Missing entry for block-${i}`); + dbg_assert(block_entry, `IndexedDBFileStorage get: Missing entry for block-${block_number}`); const block_data = block_entry[INDEXEDDB_STORAGE_DATA_PATH]; dbg_assert(block_data instanceof Uint8Array, - `IndexedDBFileStorage get: Entry for block-${i} without Uint8Array data field: ${block_data}`); + `IndexedDBFileStorage get: Entry for block-${block_number} without Uint8Array data field: ${block_data}`); - file_data.set(block_data, offset); + const chunk_start = offset + read_count - block_offset; + const chunk_end = offset + count - block_offset; + const chunk = block_data.subarray(chunk_start, chunk_end); + read_data.set(chunk, read_count); + read_count += chunk.length; } - return file_data; + return read_data.subarray(0, read_count); }; // jshint ignore:line /** - * XXX: When shrinking a large file, the old blocks aren't deleted. This is ok for now with the - * current scheme of keeping IndexedDB contents read-only. * @param {string} sha256sum - * @param {!Uint8Array} data + * @param {number} offset + * @param {!Uint8Array} write_data + * @return {number} New file size */ -IndexedDBFileStorage.prototype.set = async function(sha256sum, data) // jshint ignore:line +IndexedDBFileStorage.prototype.write = async function(sha256sum, offset, write_data) // jshint ignore:line { dbg_assert(this.db, "IndexedDBFileStorage set: Database is not initialized"); dbg_assert(sha256sum, "IndexedDBFileStorage set: sha256sum should be a non-empty string"); const transaction = this.db.transaction(INDEXEDDB_STORAGE_STORE, "readwrite"); + const entry = await this.db_get(sha256sum); // jshint ignore:line - const extra_block_count = Math.ceil( - (data.length - INDEXEDDB_STORAGE_CHUNKING_THRESHOLD) / + let old_extra_block_count = 0; + let old_total_size = 0; + let base_data = null; + if(entry) + { + base_data = entry[INDEXEDDB_STORAGE_DATA_PATH]; + old_extra_block_count = entry[INDEXEDDB_STORAGE_EXTRABLOCKCOUNT_PATH]; + old_total_size = entry[INDEXEDDB_STORAGE_TOTALSIZE_PATH]; + } + + const needed_size = offset + write_data.length; + const new_total_size = Math.max(old_total_size, needed_size); + + let write_count = 0; + + if(offset < INDEXEDDB_STORAGE_CHUNKING_THRESHOLD) + { + const chunk = write_data.subarray(0, INDEXEDDB_STORAGE_CHUNKING_THRESHOLD - offset); + const chunk_end = chunk.length + offset; + if(!base_data || base_data.length < chunk_end) + { + const old_base_data = base_data; + base_data = new Uint8Array(chunk_end); + if(old_base_data) base_data.set(old_base_data); + } + base_data.set(chunk, offset); + write_count += chunk.length; + } + + let block_number = Math.floor( + (offset + write_count - base_data.length) / INDEXEDDB_STORAGE_BLOCKSIZE ); - - await this.db_set(transaction, { // jshint ignore:line - [INDEXEDDB_STORAGE_KEY_PATH]: sha256sum, - [INDEXEDDB_STORAGE_DATA_PATH]: data.subarray(0, INDEXEDDB_STORAGE_CHUNKING_THRESHOLD), - [INDEXEDDB_STORAGE_BLOCKSIZE_PATH]: INDEXEDDB_STORAGE_BLOCKSIZE, - [INDEXEDDB_STORAGE_TOTALSIZE_PATH]: data.length, - [INDEXEDDB_STORAGE_EXTRABLOCKCOUNT_PATH]: extra_block_count, - }); - - let offset = INDEXEDDB_STORAGE_CHUNKING_THRESHOLD; - for(let i = 0; offset < data.length; i++, offset += INDEXEDDB_STORAGE_BLOCKSIZE) + for(; write_count < write_data.length; block_number++) { - const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, i); - const block_data = data.subarray(offset, offset + INDEXEDDB_STORAGE_BLOCKSIZE); + const block_offset = base_data.length + block_number * INDEXEDDB_STORAGE_BLOCKSIZE; + const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, block_number); + + const chunk_start = offset + write_count - block_offset; + const chunk_writable = INDEXEDDB_STORAGE_BLOCKSIZE - chunk_start; + const write_remaining = write_data.length - write_count; + const chunk = write_data.subarray(write_count, Math.min(chunk_writable, write_remaining)); + + let block_data = chunk; + + if(chunk.length !== INDEXEDDB_STORAGE_BLOCKSIZE) + { + // Chunk to be written does not fully replace the current block. + + const block_entry = await this.db_get(transaction, block_key); // jshint ignore:line + + block_data = block_entry ? + block_entry[INDEXEDDB_STORAGE_DATA_PATH] : + new Uint8Array(INDEXEDDB_STORAGE_BLOCKSIZE); + + dbg_assert(block_data instanceof Uint8Array, + `IndexedDBFileStorage get: Entry for block-${block_number} without Uint8Array data field: ${block_data}`); + + block_data.set(chunk, chunk_start); + } + await this.db_set(transaction, { //jshint ignore:line [INDEXEDDB_STORAGE_KEY_PATH]: block_key, [INDEXEDDB_STORAGE_DATA_PATH]: block_data, }); } + + const new_extra_block_count = Math.max(old_extra_block_count, block_number); + + await this.db_set(transaction, { // jshint ignore:line + [INDEXEDDB_STORAGE_KEY_PATH]: sha256sum, + [INDEXEDDB_STORAGE_DATA_PATH]: base_data, + [INDEXEDDB_STORAGE_TOTALSIZE_PATH]: new_total_size, + [INDEXEDDB_STORAGE_EXTRABLOCKCOUNT_PATH]: new_extra_block_count, + }); + + return new_total_size; }; // jshint ignore:line /** @@ -286,30 +393,35 @@ ServerFileStorageWrapper.prototype.load_from_server = function(sha256sum) v86util.load_file(this.baseurl + sha256sum, { done: buffer => { const data = new Uint8Array(buffer); - this.set(sha256sum, data).then(() => resolve(data)); + this.write(sha256sum, 0, data).then(() => resolve(data)); }}); }); }; /** * @param {string} sha256sum + * @param {number} offset + * @param {number} count * @return {Uint8Array} */ -ServerFileStorageWrapper.prototype.get = async function(sha256sum) // jshint ignore:line +ServerFileStorageWrapper.prototype.read = async function(sha256sum, offset, count) // jshint ignore:line { - const data = await this.storage.get(sha256sum); // jshint ignore:line + const data = await this.storage.read(sha256sum, offset, count); // jshint ignore:line if(!data) { - return await this.load_from_server(sha256sum); // jshint ignore:line + const full_file = await this.load_from_server(sha256sum); // jshint ignore:line + return full_file.subarray(offset, offset + count); } return data; }; // jshint ignore:line /** * @param {string} sha256sum + * @param {number} offset * @param {!Uint8Array} data + * @return {number} New file size */ -ServerFileStorageWrapper.prototype.set = async function(sha256sum, data) // jshint ignore:line +ServerFileStorageWrapper.prototype.write = async function(sha256sum, offset, data) // jshint ignore:line { - await this.storage.set(sha256sum, data); // jshint ignore:line + return await this.storage.write(sha256sum, offset, data); // jshint ignore:line }; // jshint ignore:line From 62c880b4152e479519495847c99892d0204ae454 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 18 Nov 2018 21:18:14 +1300 Subject: [PATCH 1465/2137] Filestorage: Integrate chunking and revert unnecessary chunking - Integrate new FileStorage interface with lib/filesystem.js - Simplify the FileStorage interface with the intention that it only serves read-only files. --- lib/filesystem.js | 24 +++---- src/browser/filestorage.js | 143 +++++++++---------------------------- 2 files changed, 42 insertions(+), 125 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 7fd63763..70db466f 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -842,12 +842,12 @@ FS.prototype.Write = async function(id, offset, count, buffer) { // jshint ignor } inode.dirty = true; - var data = await this.get_data(id); // jshint ignore:line + var data = await this.get_data(id, 0, inode.size); // jshint ignore:line if (!data || data.length < (offset+count)) { await this.ChangeSize(id, Math.floor(((offset+count)*3)/2)); // jshint ignore:line inode.size = offset + count; - data = await this.get_data(id); // jshint ignore:line + data = await this.get_data(id, 0, inode.size); // jshint ignore:line } else if (inode.size < (offset+count)) { inode.size = offset + count; @@ -868,15 +868,7 @@ FS.prototype.Read = async function(inodeid, offset, count) // jshint ignore:line return await this.follow_fs(inode).Read(foreign_id, offset, count); // jshint ignore:line } - const data = await this.get_data(inodeid); // jshint ignore:line - if(!data) - { - return null; - } - else - { - return data.subarray(offset, offset + count); - } + return await this.get_data(inodeid, offset, count); // jshint ignore:line }; // jshint ignore:line FS.prototype.Search = function(parentid, name) { @@ -1068,21 +1060,23 @@ FS.prototype.DeleteData = async function(idx) // jshint ignore:line /** * @private * @param {number} idx + * @param {number} offset + * @param {number} count * @return {Uint8Array} */ -FS.prototype.get_data = async function(idx) // jshint ignore:line +FS.prototype.get_data = async function(idx, offset, count) // jshint ignore:line { const inode = this.inodes[idx]; dbg_assert(inode, `Filesystem get_data: idx ${idx} does not point to an inode`); if(this.inodedata[idx]) { - return this.inodedata[idx]; + return this.inodedata[idx].subarray(offset, offset + count); } else if(inode.status === STATUS_ON_SERVER) { dbg_assert(inode.sha256sum, "Filesystem get_data: found inode on server without sha256sum"); - return await this.storage.get(inode.sha256sum); // jshint ignore:line + return await this.storage.read(inode.sha256sum, offset, count); // jshint ignore:line } else { @@ -1122,7 +1116,7 @@ FS.prototype.GetInode = function(idx) FS.prototype.ChangeSize = async function(idx, newsize) // jshint ignore:line { var inode = this.GetInode(idx); - var temp = await this.get_data(idx); // jshint ignore:line + var temp = await this.get_data(idx, 0, inode.size); // jshint ignore:line inode.dirty = true; //message.Debug("change size to: " + newsize); if (newsize == inode.size) return; diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index 364e059e..f58c453f 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -15,6 +15,7 @@ const INDEXEDDB_STORAGE_BLOCKSIZE = 4096; function FileStorageInterface() {} /** + * Read a portion of a file. * @param {string} sha256sum * @param {number} offset * @param {number} count @@ -23,18 +24,12 @@ function FileStorageInterface() {} FileStorageInterface.prototype.read = function(sha256sum, offset, count) {}; /** + * Add a read-only file to the filestorage. * @param {string} sha256sum - * @param {number} offset - * @param {!Uint8Array} buffer - * @return {!Promise} Promise to the new file size as file may have grown. + * @param {!Uint8Array} data + * @return {!Promise} */ -FileStorageInterface.prototype.write = function(sha256sum, offset, buffer) {}; - -/** - * @param {string} sha256sum - * @param {number} length - */ -FileStorageInterface.prototype.change_size = function(sha256sum, length) {}; +FileStorageInterface.prototype.set = function(sha256sum, data) {}; /** * @constructor @@ -70,36 +65,19 @@ MemoryFileStorage.prototype.read = async function(sha256sum, offset, count) // j /** * @param {string} sha256sum - * @param {number} offset * @param {!Uint8Array} data - * @return {number} New file size as file may have grown after writing. */ -MemoryFileStorage.prototype.write = async function(sha256sum, offset, buffer) // jshint ignore:line +MemoryFileStorage.prototype.set = async function(sha256sum, data) // jshint ignore:line { dbg_assert(sha256sum, "MemoryFileStorage set: sha256sum should be a non-empty string"); + dbg_assert(!this.filedata.has(sha256sum), "MemoryFileStorage set: Storage should be read-only"); - const needed_size = offset + buffer.length; - let data = this.filedata.get(sha256sum); - - if(!data) - { - data = new Uint8Array(needed_size); - } - - if(data.length < needed_size) - { - const old_data = data; - data = new Uint8Array(needed_size); - data.set(old_data); - } - - data.set(buffer, offset); this.filedata.set(sha256sum, data); - - return data.length; }; // jshint ignore:line /** + * Use IndexedDBFileStorage.try_create() instead. + * @private * @constructor * @implements {FileStorageInterface} */ @@ -122,6 +100,9 @@ IndexedDBFileStorage.try_create = async function() // jshint ignore:line return file_storage; }; // jshint ignore:line +/** + * @private + */ IndexedDBFileStorage.prototype.init = function() { dbg_assert(!this.db, "IndexedDBFileStorage init: Database already intiialized"); @@ -179,6 +160,7 @@ IndexedDBFileStorage.prototype.init = function() }; /** + * @private * @param {IDBTransaction} transaction * @param {string} key * @return {!Promise} @@ -194,6 +176,7 @@ IndexedDBFileStorage.prototype.db_get = function(transaction, key) }; /** + * @private * @param {IDBTransaction} transaction * @param {Object} value * @return {!Promise} @@ -276,95 +259,37 @@ IndexedDBFileStorage.prototype.read = async function(sha256sum, offset, count) / /** * @param {string} sha256sum - * @param {number} offset - * @param {!Uint8Array} write_data - * @return {number} New file size + * @param {!Uint8Array} data */ -IndexedDBFileStorage.prototype.write = async function(sha256sum, offset, write_data) // jshint ignore:line +IndexedDBFileStorage.prototype.set = async function(sha256sum, data) // jshint ignore:line { dbg_assert(this.db, "IndexedDBFileStorage set: Database is not initialized"); dbg_assert(sha256sum, "IndexedDBFileStorage set: sha256sum should be a non-empty string"); const transaction = this.db.transaction(INDEXEDDB_STORAGE_STORE, "readwrite"); - const entry = await this.db_get(sha256sum); // jshint ignore:line - let old_extra_block_count = 0; - let old_total_size = 0; - let base_data = null; - if(entry) - { - base_data = entry[INDEXEDDB_STORAGE_DATA_PATH]; - old_extra_block_count = entry[INDEXEDDB_STORAGE_EXTRABLOCKCOUNT_PATH]; - old_total_size = entry[INDEXEDDB_STORAGE_TOTALSIZE_PATH]; - } - - const needed_size = offset + write_data.length; - const new_total_size = Math.max(old_total_size, needed_size); - - let write_count = 0; - - if(offset < INDEXEDDB_STORAGE_CHUNKING_THRESHOLD) - { - const chunk = write_data.subarray(0, INDEXEDDB_STORAGE_CHUNKING_THRESHOLD - offset); - const chunk_end = chunk.length + offset; - if(!base_data || base_data.length < chunk_end) - { - const old_base_data = base_data; - base_data = new Uint8Array(chunk_end); - if(old_base_data) base_data.set(old_base_data); - } - base_data.set(chunk, offset); - write_count += chunk.length; - } - - let block_number = Math.floor( - (offset + write_count - base_data.length) / + const extra_block_count = Math.ceil( + (data.length - INDEXEDDB_STORAGE_CHUNKING_THRESHOLD) / INDEXEDDB_STORAGE_BLOCKSIZE ); - for(; write_count < write_data.length; block_number++) + + await this.db_set(transaction, { // jshint ignore:line + [INDEXEDDB_STORAGE_KEY_PATH]: sha256sum, + [INDEXEDDB_STORAGE_DATA_PATH]: data.subarray(0, INDEXEDDB_STORAGE_CHUNKING_THRESHOLD), + [INDEXEDDB_STORAGE_TOTALSIZE_PATH]: data.length, + [INDEXEDDB_STORAGE_EXTRABLOCKCOUNT_PATH]: extra_block_count, + }); + + let offset = INDEXEDDB_STORAGE_CHUNKING_THRESHOLD; + for(let i = 0; offset < data.length; i++, offset += INDEXEDDB_STORAGE_BLOCKSIZE) { - const block_offset = base_data.length + block_number * INDEXEDDB_STORAGE_BLOCKSIZE; - const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, block_number); - - const chunk_start = offset + write_count - block_offset; - const chunk_writable = INDEXEDDB_STORAGE_BLOCKSIZE - chunk_start; - const write_remaining = write_data.length - write_count; - const chunk = write_data.subarray(write_count, Math.min(chunk_writable, write_remaining)); - - let block_data = chunk; - - if(chunk.length !== INDEXEDDB_STORAGE_BLOCKSIZE) - { - // Chunk to be written does not fully replace the current block. - - const block_entry = await this.db_get(transaction, block_key); // jshint ignore:line - - block_data = block_entry ? - block_entry[INDEXEDDB_STORAGE_DATA_PATH] : - new Uint8Array(INDEXEDDB_STORAGE_BLOCKSIZE); - - dbg_assert(block_data instanceof Uint8Array, - `IndexedDBFileStorage get: Entry for block-${block_number} without Uint8Array data field: ${block_data}`); - - block_data.set(chunk, chunk_start); - } - + const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, i); + const block_data = data.subarray(offset, offset + INDEXEDDB_STORAGE_BLOCKSIZE); await this.db_set(transaction, { //jshint ignore:line [INDEXEDDB_STORAGE_KEY_PATH]: block_key, [INDEXEDDB_STORAGE_DATA_PATH]: block_data, }); } - - const new_extra_block_count = Math.max(old_extra_block_count, block_number); - - await this.db_set(transaction, { // jshint ignore:line - [INDEXEDDB_STORAGE_KEY_PATH]: sha256sum, - [INDEXEDDB_STORAGE_DATA_PATH]: base_data, - [INDEXEDDB_STORAGE_TOTALSIZE_PATH]: new_total_size, - [INDEXEDDB_STORAGE_EXTRABLOCKCOUNT_PATH]: new_extra_block_count, - }); - - return new_total_size; }; // jshint ignore:line /** @@ -393,7 +318,7 @@ ServerFileStorageWrapper.prototype.load_from_server = function(sha256sum) v86util.load_file(this.baseurl + sha256sum, { done: buffer => { const data = new Uint8Array(buffer); - this.write(sha256sum, 0, data).then(() => resolve(data)); + this.set(sha256sum, data).then(() => resolve(data)); }}); }); }; @@ -417,11 +342,9 @@ ServerFileStorageWrapper.prototype.read = async function(sha256sum, offset, coun /** * @param {string} sha256sum - * @param {number} offset * @param {!Uint8Array} data - * @return {number} New file size */ -ServerFileStorageWrapper.prototype.write = async function(sha256sum, offset, data) // jshint ignore:line +ServerFileStorageWrapper.prototype.set = async function(sha256sum, data) // jshint ignore:line { - return await this.storage.write(sha256sum, offset, data); // jshint ignore:line + return await this.storage.set(sha256sum, data); // jshint ignore:line }; // jshint ignore:line From 04d2b722484839cc882d11cbac2b17319f20fcda Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 18 Nov 2018 23:20:31 +1300 Subject: [PATCH 1466/2137] 9p: Simplify read - OpenInode is not asynchronous --- lib/9p.js | 48 ++++++++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/lib/9p.js b/lib/9p.js index 05f6c66b..7a77c962 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -591,37 +591,33 @@ Virtio9p.prototype.ReceiveRequest = async function (bufchain) { // jshint ignore this.SendReply(bufchain); } else { this.fs.OpenInode(this.fids[fid].inodeid, undefined); - this.fs.AddEvent(this.fids[fid].inodeid, - async function() { // jshint ignore:line - const inodeid = this.fids[fid].inodeid; + const inodeid = this.fids[fid].inodeid; - if (inode.size < offset+count) count = inode.size - offset; - else if(id == 40) - { - // for directories, return whole number of dir-entries. - count = this.fs.RoundToDirentry(inodeid, offset + count) - offset; - } - if(offset > inode.size) - { - // offset can be greater than available - should return count of zero. - // See http://ericvh.github.io/9p-rfc/rfc9p2000.html#anchor30 - count = 0; - } + if (inode.size < offset+count) count = inode.size - offset; + else if(id == 40) + { + // for directories, return whole number of dir-entries. + count = this.fs.RoundToDirentry(inodeid, offset + count) - offset; + } + if(offset > inode.size) + { + // offset can be greater than available - should return count of zero. + // See http://ericvh.github.io/9p-rfc/rfc9p2000.html#anchor30 + count = 0; + } - this.bus.send("9p-read-start", [this.fids[fid].dbg_name]); + this.bus.send("9p-read-start", [this.fids[fid].dbg_name]); - const data = await this.fs.Read(inodeid, offset, count); // jshint ignore:line + const data = await this.fs.Read(inodeid, offset, count); // jshint ignore:line - this.bus.send("9p-read-end", [this.fids[fid].dbg_name, count]); + this.bus.send("9p-read-end", [this.fids[fid].dbg_name, count]); - if(data) { - this.replybuffer.set(data, 7 + 4); - } - marshall.Marshall(["w"], [count], this.replybuffer, 7); - this.BuildReply(id, tag, 4 + count); - this.SendReply(bufchain); - }.bind(this) // jshint ignore:line - ); // jshint ignore:line + if(data) { + this.replybuffer.set(data, 7 + 4); + } + marshall.Marshall(["w"], [count], this.replybuffer, 7); + this.BuildReply(id, tag, 4 + count); + this.SendReply(bufchain); } break; From 3a74e66b7272fc0bb54e60d621647bae9bcceaea Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 18 Nov 2018 23:24:48 +1300 Subject: [PATCH 1467/2137] Filestorage: Expose load_from_server --- src/browser/filestorage.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index f58c453f..21a600dd 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -307,7 +307,6 @@ function ServerFileStorageWrapper(file_storage, baseurl) } /** - * @private * @param {string} sha256sum * @return {!Promise} */ From c625bba498b095a5f393e329a217e37c2fbd2f11 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Mon, 19 Nov 2018 00:00:02 +1300 Subject: [PATCH 1468/2137] Filestorage: Implement cache cleanup - avoid memory growth --- lib/filesystem.js | 9 +++++++++ src/browser/filestorage.js | 31 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/lib/filesystem.js b/lib/filesystem.js index 70db466f..45f86d19 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -700,6 +700,10 @@ FS.prototype.CloseInode = async function(id) { // jshint ignore:line { return this.follow_fs(inode).CloseInode(inode.foreign_id); } + if(inode.status === STATUS_ON_SERVER) + { + this.storage.can_uncache(inode.sha256sum); + } if (inode.status == STATUS_UNLINKED) { //message.Debug("Filesystem: Delete unlinked file"); inode.status = STATUS_INVALID; @@ -1093,6 +1097,11 @@ FS.prototype.set_data = async function(idx, buffer) // jshint ignore:line { // Current scheme: Save all modified buffers into local inodedata. this.inodedata[idx] = buffer; + if(this.inodes[idx].status === STATUS_ON_SERVER) + { + this.inodes[idx].status = STATUS_OK; + this.storage.can_uncache(this.inodes[idx].sha256sum); + } }; // jshint ignore:line /** diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index 21a600dd..bf693bf7 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -31,6 +31,13 @@ FileStorageInterface.prototype.read = function(sha256sum, offset, count) {}; */ FileStorageInterface.prototype.set = function(sha256sum, data) {}; +/** + * Call this when the file won't be used soon, e.g. when a file closes or when this immutable + * version is already out of date. It is used to help prevent accumulation of unused files in + * memory in the long run for some FileStorage mediums. + */ +FileStorageInterface.prototype.can_uncache = function(sha256sum) {}; + /** * @constructor * @implements {FileStorageInterface} @@ -75,6 +82,14 @@ MemoryFileStorage.prototype.set = async function(sha256sum, data) // jshint igno this.filedata.set(sha256sum, data); }; // jshint ignore:line +/** + * @param {string} sha256sum + */ +MemoryFileStorage.prototype.can_uncache = function(sha256sum) +{ + this.filedata.delete(sha256sum); +}; + /** * Use IndexedDBFileStorage.try_create() instead. * @private @@ -292,6 +307,14 @@ IndexedDBFileStorage.prototype.set = async function(sha256sum, data) // jshint i } }; // jshint ignore:line +/** + * @param {string} sha256sum + */ +IndexedDBFileStorage.prototype.can_uncache = function(sha256sum) +{ + // No-op. +}; + /** * @constructor * @implements {FileStorageInterface} @@ -347,3 +370,11 @@ ServerFileStorageWrapper.prototype.set = async function(sha256sum, data) // jshi { return await this.storage.set(sha256sum, data); // jshint ignore:line }; // jshint ignore:line + +/** + * @param {string} sha256sum + */ +ServerFileStorageWrapper.prototype.can_uncache = function(sha256sum) +{ + this.storage.can_uncache(sha256sum); +}; From 2f4520619a8dae646e320e0bea8ec55c0f03c638 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Mon, 19 Nov 2018 00:02:52 +1300 Subject: [PATCH 1469/2137] Filesystem: Tidy naming of STATUS_ON_SERVER to ON_STORAGE --- lib/filesystem.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 45f86d19..1a6ca890 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -26,7 +26,7 @@ var O_ACCMODE = 0x0003; // mask for above modes var STATUS_INVALID = -0x1; var STATUS_OK = 0x0; -var STATUS_ON_SERVER = 0x2; +var STATUS_ON_STORAGE = 0x2; var STATUS_UNLINKED = 0x4; var STATUS_FORWARDING = 0x5; @@ -128,7 +128,7 @@ FS.prototype.set_state = function(state) FS.prototype.AddEvent = function(id, OnEvent) { var inode = this.inodes[id]; - if (inode.status == STATUS_OK || inode.status == STATUS_ON_SERVER) { + if (inode.status == STATUS_OK || inode.status == STATUS_ON_STORAGE) { OnEvent(); } else if(this.is_forwarder(inode)) @@ -210,7 +210,7 @@ FS.prototype.LoadRecursive = function(data, parentid) } else if(ifmt === S_IFREG) { - inode.status = STATUS_ON_SERVER; + inode.status = STATUS_ON_STORAGE; inode.sha256sum = data[JSONFS_IDX_SHA256]; this.PushInode(inode, parentid, name); } @@ -700,7 +700,7 @@ FS.prototype.CloseInode = async function(id) { // jshint ignore:line { return this.follow_fs(inode).CloseInode(inode.foreign_id); } - if(inode.status === STATUS_ON_SERVER) + if(inode.status === STATUS_ON_STORAGE) { this.storage.can_uncache(inode.sha256sum); } @@ -1077,7 +1077,7 @@ FS.prototype.get_data = async function(idx, offset, count) // jshint ignore:line { return this.inodedata[idx].subarray(offset, offset + count); } - else if(inode.status === STATUS_ON_SERVER) + else if(inode.status === STATUS_ON_STORAGE) { dbg_assert(inode.sha256sum, "Filesystem get_data: found inode on server without sha256sum"); return await this.storage.read(inode.sha256sum, offset, count); // jshint ignore:line @@ -1097,7 +1097,7 @@ FS.prototype.set_data = async function(idx, buffer) // jshint ignore:line { // Current scheme: Save all modified buffers into local inodedata. this.inodedata[idx] = buffer; - if(this.inodes[idx].status === STATUS_ON_SERVER) + if(this.inodes[idx].status === STATUS_ON_STORAGE) { this.inodes[idx].status = STATUS_OK; this.storage.can_uncache(this.inodes[idx].sha256sum); From 9db722f71fd7c5790fa1a27173531e89dba21cda Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Mon, 19 Nov 2018 00:09:02 +1300 Subject: [PATCH 1470/2137] Filestorage: Improve usefulness of IndexedDB error messages --- src/browser/filestorage.js | 43 +++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index bf693bf7..294cf793 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -59,7 +59,7 @@ function MemoryFileStorage() */ MemoryFileStorage.prototype.read = async function(sha256sum, offset, count) // jshint ignore:line { - dbg_assert(sha256sum, "MemoryFileStorage get: sha256sum should be a non-empty string"); + dbg_assert(sha256sum, "MemoryFileStorage read: sha256sum should be a non-empty string"); const data = this.filedata.get(sha256sum); if(!data) @@ -138,7 +138,7 @@ IndexedDBFileStorage.prototype.init = function() dbg_log("Error opening IndexedDB! Are you in private browsing mode? Error:", LOG_9P); dbg_log(open_request.error, LOG_9P); this.initializing = false; - reject(); + reject(open_request.error); }; open_request.onupgradeneeded = event => @@ -159,15 +159,17 @@ IndexedDBFileStorage.prototype.init = function() { dbg_assert(false, "IndexedDBFileStorage: connection closed unexpectedly"); }; - this.db.onerror = error => + this.db.onerror = event => { - dbg_assert(false, "IndexedDBFileStorage: unexpected error: " + error); + const error = event.originalTarget.error; + dbg_log("IndexedDBFileStorage: unexpected error: " + error, LOG_9P); + throw error; }; this.db.onversionchange = event => { - // TODO: double check this message - dbg_log("Warning: another v86 instance is trying to open IndexedDB database but " + - "is blocked by this current v86 instance.", LOG_9P); + dbg_log("Caution: Another v86 instance might be trying to upgrade the IndexedDB " + + "database to a newer version, or a request has been issued to delete the " + + "database, but is blocked by this current v86 instance ", LOG_9P); }; resolve(); }; @@ -214,10 +216,17 @@ IndexedDBFileStorage.prototype.db_set = function(transaction, value) */ IndexedDBFileStorage.prototype.read = async function(sha256sum, offset, count) // jshint ignore:line { - dbg_assert(this.db, "IndexedDBFileStorage get: Database is not initialized"); - dbg_assert(sha256sum, "IndexedDBFileStorage get: sha256sum should be a non-empty string"); + dbg_assert(this.db, "IndexedDBFileStorage read: Database is not initialized"); + dbg_assert(sha256sum, "IndexedDBFileStorage read: sha256sum should be a non-empty string"); const transaction = this.db.transaction(INDEXEDDB_STORAGE_STORE, "readonly"); + transaction.onerror = event => + { + const error = event.originalTarget.error; + dbg_log(`IndexedDBFileStorage read: Error with transaction: ${error}`, LOG_9P); + throw error; + }; + const entry = await this.db_get(transaction, sha256sum); // jshint ignore:line if(!entry) @@ -230,11 +239,11 @@ IndexedDBFileStorage.prototype.read = async function(sha256sum, offset, count) / const total_size = entry[INDEXEDDB_STORAGE_TOTALSIZE_PATH]; dbg_assert(base_data instanceof Uint8Array, - `IndexedDBFileStorage get: Invalid base entry without the data Uint8Array field: ${base_data}`); + `IndexedDBFileStorage read: Invalid base entry without the data Uint8Array field: ${base_data}`); dbg_assert(Number.isInteger(extra_block_count), - `IndexedDBFileStorage get: Invalid base entry with non-integer block_count: ${extra_block_count}`); + `IndexedDBFileStorage read: Invalid base entry with non-integer block_count: ${extra_block_count}`); dbg_assert(Number.isInteger(total_size) && total_size >= base_data.length, - `IndexedDBFileStorage get: Invalid base entry with invalid total_size: ${total_size}`); + `IndexedDBFileStorage read: Invalid base entry with invalid total_size: ${total_size}`); const read_data = new Uint8Array(count); let read_count = 0; @@ -256,11 +265,11 @@ IndexedDBFileStorage.prototype.read = async function(sha256sum, offset, count) / const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, block_number); const block_entry = await this.db_get(transaction, block_key); // jshint ignore:line - dbg_assert(block_entry, `IndexedDBFileStorage get: Missing entry for block-${block_number}`); + dbg_assert(block_entry, `IndexedDBFileStorage read: Missing entry for block-${block_number}`); const block_data = block_entry[INDEXEDDB_STORAGE_DATA_PATH]; dbg_assert(block_data instanceof Uint8Array, - `IndexedDBFileStorage get: Entry for block-${block_number} without Uint8Array data field: ${block_data}`); + `IndexedDBFileStorage read: Entry for block-${block_number} without Uint8Array data field: ${block_data}`); const chunk_start = offset + read_count - block_offset; const chunk_end = offset + count - block_offset; @@ -282,6 +291,12 @@ IndexedDBFileStorage.prototype.set = async function(sha256sum, data) // jshint i dbg_assert(sha256sum, "IndexedDBFileStorage set: sha256sum should be a non-empty string"); const transaction = this.db.transaction(INDEXEDDB_STORAGE_STORE, "readwrite"); + transaction.onerror = event => + { + const error = event.originalTarget.error; + dbg_log(`IndexedDBFileStorage set: Error with transaction: ${error}`, LOG_9P); + throw error; + }; const extra_block_count = Math.ceil( (data.length - INDEXEDDB_STORAGE_CHUNKING_THRESHOLD) / From 738edf7b6c19b3d05b8840b9390a800934bff227 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Mon, 19 Nov 2018 21:26:04 +1300 Subject: [PATCH 1471/2137] Filestorage: Initialise IndexedDB before constructor Simplifies several checks --- src/browser/filestorage.js | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index 294cf793..06a260f8 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -94,14 +94,12 @@ MemoryFileStorage.prototype.can_uncache = function(sha256sum) * Use IndexedDBFileStorage.try_create() instead. * @private * @constructor + * @param {!IDBDatabase} db The IndexedDB database opened via init_db(). * @implements {FileStorageInterface} */ -function IndexedDBFileStorage() +function IndexedDBFileStorage(db) { - dbg_assert(typeof window !== "undefined" && window.indexedDB, - "IndexedDBFileStorage - indexedDB not available."); - this.db = null; - this.initializing = false; + this.db = db; } IndexedDBFileStorage.try_create = async function() // jshint ignore:line @@ -110,20 +108,16 @@ IndexedDBFileStorage.try_create = async function() // jshint ignore:line { throw new Error("IndexedDB is not available"); } - const file_storage = new IndexedDBFileStorage(); - await file_storage.init(); // jshint ignore:line + const db = await IndexedDBFileStorage.init_db(); // jshint ignore:line + const file_storage = new IndexedDBFileStorage(db); return file_storage; }; // jshint ignore:line /** - * @private + * @return {!Promise} */ -IndexedDBFileStorage.prototype.init = function() +IndexedDBFileStorage.init_db = function() { - dbg_assert(!this.db, "IndexedDBFileStorage init: Database already intiialized"); - dbg_assert(!this.initializing, "IndexedDBFileStorage init: Database already intiializing"); - this.initializing = true; - return new Promise((resolve, reject) => { const open_request = indexedDB.open(INDEXEDDB_STORAGE_NAME, INDEXEDDB_STORAGE_VERSION); @@ -137,7 +131,6 @@ IndexedDBFileStorage.prototype.init = function() { dbg_log("Error opening IndexedDB! Are you in private browsing mode? Error:", LOG_9P); dbg_log(open_request.error, LOG_9P); - this.initializing = false; reject(open_request.error); }; @@ -149,29 +142,28 @@ IndexedDBFileStorage.prototype.init = function() open_request.onsuccess = event => { - this.initializing = false; - this.db = open_request.result; - this.db.onabort = event => + const db = open_request.result; + db.onabort = event => { dbg_assert(false, "IndexedDBFileStorage: transaction aborted unexpectedly"); }; - this.db.onclose = event => + db.onclose = event => { dbg_assert(false, "IndexedDBFileStorage: connection closed unexpectedly"); }; - this.db.onerror = event => + db.onerror = event => { const error = event.originalTarget.error; dbg_log("IndexedDBFileStorage: unexpected error: " + error, LOG_9P); throw error; }; - this.db.onversionchange = event => + db.onversionchange = event => { dbg_log("Caution: Another v86 instance might be trying to upgrade the IndexedDB " + "database to a newer version, or a request has been issued to delete the " + "database, but is blocked by this current v86 instance ", LOG_9P); }; - resolve(); + resolve(db); }; }); }; @@ -216,7 +208,6 @@ IndexedDBFileStorage.prototype.db_set = function(transaction, value) */ IndexedDBFileStorage.prototype.read = async function(sha256sum, offset, count) // jshint ignore:line { - dbg_assert(this.db, "IndexedDBFileStorage read: Database is not initialized"); dbg_assert(sha256sum, "IndexedDBFileStorage read: sha256sum should be a non-empty string"); const transaction = this.db.transaction(INDEXEDDB_STORAGE_STORE, "readonly"); @@ -287,7 +278,6 @@ IndexedDBFileStorage.prototype.read = async function(sha256sum, offset, count) / */ IndexedDBFileStorage.prototype.set = async function(sha256sum, data) // jshint ignore:line { - dbg_assert(this.db, "IndexedDBFileStorage set: Database is not initialized"); dbg_assert(sha256sum, "IndexedDBFileStorage set: sha256sum should be a non-empty string"); const transaction = this.db.transaction(INDEXEDDB_STORAGE_STORE, "readwrite"); From d6bfa143ed5cd50768bee7a3cc9d97bebd6e9c5e Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Mon, 19 Nov 2018 21:38:25 +1300 Subject: [PATCH 1472/2137] Filestorage: Don't rely on errors to select type of storage --- src/browser/starter.js | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 15cc321c..ed911aad 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -448,17 +448,9 @@ V86Starter.prototype.continue_init = async function(emulator, options) // jshint var fs_url = options["filesystem"]["basefs"]; var base_url = options["filesystem"]["baseurl"]; - let file_storage; - try - { - file_storage = await IndexedDBFileStorage.try_create(); // jshint ignore:line - } - catch(e) - { - dbg_log("Initializing IndexedDBFileStorage failed due to Error: " + e); - dbg_log("Falling back to MemoryFileStorage instead."); - file_storage = new MemoryFileStorage(); - } + let file_storage = typeof window === "undefined" || !window.indexedDB ? + new MemoryFileStorage() : + await IndexedDBFileStorage.try_create(); // jshint ignore:line if (base_url) { file_storage = new ServerFileStorageWrapper(file_storage, base_url); @@ -1059,17 +1051,9 @@ V86Starter.prototype.serial0_send = function(data) */ V86Starter.prototype.mount_fs = async function(path, baseurl, basefs, callback) // jshint ignore:line { - let file_storage; - try - { - file_storage = await IndexedDBFileStorage.try_create(); // jshint ignore:line - } - catch(e) - { - dbg_log("Initializing IndexedDBFileStorage failed due to Error: " + e); - dbg_log("Falling back to MemoryFileStorage instead."); - file_storage = new MemoryFileStorage(); - } + let file_storage = typeof window === "undefined" || !window.indexedDB ? + new MemoryFileStorage() : + await IndexedDBFileStorage.try_create(); // jshint ignore:line if(baseurl) { file_storage = new ServerFileStorageWrapper(file_storage, baseurl); From 840415a05256dba7044235c5fe1cae3e01225235 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Mon, 19 Nov 2018 21:44:24 +1300 Subject: [PATCH 1473/2137] Filestorage: (minor) Improve naming can_uncache() -> uncache() --- lib/filesystem.js | 4 ++-- src/browser/filestorage.js | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 1a6ca890..040d3e3e 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -702,7 +702,7 @@ FS.prototype.CloseInode = async function(id) { // jshint ignore:line } if(inode.status === STATUS_ON_STORAGE) { - this.storage.can_uncache(inode.sha256sum); + this.storage.uncache(inode.sha256sum); } if (inode.status == STATUS_UNLINKED) { //message.Debug("Filesystem: Delete unlinked file"); @@ -1100,7 +1100,7 @@ FS.prototype.set_data = async function(idx, buffer) // jshint ignore:line if(this.inodes[idx].status === STATUS_ON_STORAGE) { this.inodes[idx].status = STATUS_OK; - this.storage.can_uncache(this.inodes[idx].sha256sum); + this.storage.uncache(this.inodes[idx].sha256sum); } }; // jshint ignore:line diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index 06a260f8..eb5b49a8 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -36,7 +36,7 @@ FileStorageInterface.prototype.set = function(sha256sum, data) {}; * version is already out of date. It is used to help prevent accumulation of unused files in * memory in the long run for some FileStorage mediums. */ -FileStorageInterface.prototype.can_uncache = function(sha256sum) {}; +FileStorageInterface.prototype.uncache = function(sha256sum) {}; /** * @constructor @@ -85,7 +85,7 @@ MemoryFileStorage.prototype.set = async function(sha256sum, data) // jshint igno /** * @param {string} sha256sum */ -MemoryFileStorage.prototype.can_uncache = function(sha256sum) +MemoryFileStorage.prototype.uncache = function(sha256sum) { this.filedata.delete(sha256sum); }; @@ -315,7 +315,7 @@ IndexedDBFileStorage.prototype.set = async function(sha256sum, data) // jshint i /** * @param {string} sha256sum */ -IndexedDBFileStorage.prototype.can_uncache = function(sha256sum) +IndexedDBFileStorage.prototype.uncache = function(sha256sum) { // No-op. }; @@ -379,7 +379,7 @@ ServerFileStorageWrapper.prototype.set = async function(sha256sum, data) // jshi /** * @param {string} sha256sum */ -ServerFileStorageWrapper.prototype.can_uncache = function(sha256sum) +ServerFileStorageWrapper.prototype.uncache = function(sha256sum) { - this.storage.can_uncache(sha256sum); + this.storage.uncache(sha256sum); }; From bf35f0ab0b2bc58fc3b8fcca4e29c27021291d17 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Mon, 19 Nov 2018 21:51:32 +1300 Subject: [PATCH 1474/2137] Filestorage: Avoid additional allocation for small files --- src/browser/filestorage.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index eb5b49a8..f524e83b 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -236,6 +236,12 @@ IndexedDBFileStorage.prototype.read = async function(sha256sum, offset, count) / dbg_assert(Number.isInteger(total_size) && total_size >= base_data.length, `IndexedDBFileStorage read: Invalid base entry with invalid total_size: ${total_size}`); + if(extra_block_count === 0 || offset + count <= base_data.length) + { + // Avoid additional allocation and copying for smaller files. + return base_data.subarray(offset, offset + count); + } + const read_data = new Uint8Array(count); let read_count = 0; From a841194d281777767b9132175bcb1e5a72c790dc Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Mon, 19 Nov 2018 22:09:21 +1300 Subject: [PATCH 1475/2137] Filestorage: Reuse IDBObjectStore throughout transaction - More like passing the same reference to it when calling db_get/set. - In reality, it was still the same store object being accessed, but this commit improves the coherence of the db_get/set helper methods. --- src/browser/filestorage.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index f524e83b..bd19c1de 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -170,15 +170,14 @@ IndexedDBFileStorage.init_db = function() /** * @private - * @param {IDBTransaction} transaction + * @param {IDBObjectStore} store * @param {string} key * @return {!Promise} */ -IndexedDBFileStorage.prototype.db_get = function(transaction, key) +IndexedDBFileStorage.prototype.db_get = function(store, key) { return new Promise((resolve, reject) => { - const store = transaction.objectStore(INDEXEDDB_STORAGE_STORE); const request = store.get(key); request.onsuccess = event => resolve(request.result); }); @@ -186,15 +185,14 @@ IndexedDBFileStorage.prototype.db_get = function(transaction, key) /** * @private - * @param {IDBTransaction} transaction + * @param {IDBObjectStore} store * @param {Object} value * @return {!Promise} */ -IndexedDBFileStorage.prototype.db_set = function(transaction, value) +IndexedDBFileStorage.prototype.db_set = function(store, value) { return new Promise((resolve, reject) => { - const store = transaction.objectStore(INDEXEDDB_STORAGE_STORE); const request = store.put(value); request.onsuccess = event => resolve(); }); @@ -217,8 +215,9 @@ IndexedDBFileStorage.prototype.read = async function(sha256sum, offset, count) / dbg_log(`IndexedDBFileStorage read: Error with transaction: ${error}`, LOG_9P); throw error; }; + const store = transaction.objectStore(INDEXEDDB_STORAGE_STORE); - const entry = await this.db_get(transaction, sha256sum); // jshint ignore:line + const entry = await this.db_get(store, sha256sum); // jshint ignore:line if(!entry) { @@ -260,7 +259,7 @@ IndexedDBFileStorage.prototype.read = async function(sha256sum, offset, count) / { const block_offset = base_data.length + block_number * INDEXEDDB_STORAGE_BLOCKSIZE; const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, block_number); - const block_entry = await this.db_get(transaction, block_key); // jshint ignore:line + const block_entry = await this.db_get(store, block_key); // jshint ignore:line dbg_assert(block_entry, `IndexedDBFileStorage read: Missing entry for block-${block_number}`); @@ -293,13 +292,14 @@ IndexedDBFileStorage.prototype.set = async function(sha256sum, data) // jshint i dbg_log(`IndexedDBFileStorage set: Error with transaction: ${error}`, LOG_9P); throw error; }; + const store = transaction.objectStore(INDEXEDDB_STORAGE_STORE); const extra_block_count = Math.ceil( (data.length - INDEXEDDB_STORAGE_CHUNKING_THRESHOLD) / INDEXEDDB_STORAGE_BLOCKSIZE ); - await this.db_set(transaction, { // jshint ignore:line + await this.db_set(store, { // jshint ignore:line [INDEXEDDB_STORAGE_KEY_PATH]: sha256sum, [INDEXEDDB_STORAGE_DATA_PATH]: data.subarray(0, INDEXEDDB_STORAGE_CHUNKING_THRESHOLD), [INDEXEDDB_STORAGE_TOTALSIZE_PATH]: data.length, @@ -311,7 +311,7 @@ IndexedDBFileStorage.prototype.set = async function(sha256sum, data) // jshint i { const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, i); const block_data = data.subarray(offset, offset + INDEXEDDB_STORAGE_BLOCKSIZE); - await this.db_set(transaction, { //jshint ignore:line + await this.db_set(store, { //jshint ignore:line [INDEXEDDB_STORAGE_KEY_PATH]: block_key, [INDEXEDDB_STORAGE_DATA_PATH]: block_data, }); From c273741405dac469a2abd5816cc05788d57c39da Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Tue, 20 Nov 2018 12:28:41 +1300 Subject: [PATCH 1476/2137] Add tests for file storage chunking --- Makefile | 1 + src/browser/filestorage.js | 4 + tests/devices/filestorage.js | 146 +++++++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+) create mode 100755 tests/devices/filestorage.js diff --git a/Makefile b/Makefile index 9ccfbaee..8902296b 100644 --- a/Makefile +++ b/Makefile @@ -271,6 +271,7 @@ expect-tests: all-debug build/libwabt.js ./tests/expect/run.js devices-test: all-debug + ./tests/devices/filestorage.js ./tests/devices/virtio_9p.js rust-test: $(RUST_FILES) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index bd19c1de..1df76fe1 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -389,3 +389,7 @@ ServerFileStorageWrapper.prototype.uncache = function(sha256sum) { this.storage.uncache(sha256sum); }; + +module.exports["MemoryFileStorage"] = MemoryFileStorage; +module.exports["IndexedDBFileStorage"] = IndexedDBFileStorage; +module.exports["ServerFileStorageWrapper"] = ServerFileStorageWrapper; diff --git a/tests/devices/filestorage.js b/tests/devices/filestorage.js new file mode 100755 index 00000000..9048e6c9 --- /dev/null +++ b/tests/devices/filestorage.js @@ -0,0 +1,146 @@ +#!/usr/bin/env node +"use strict"; + +process.on("unhandledRejection", exn => { throw exn; }); +const util = require('util'); +const { MemoryFileStorage, IndexedDBFileStorage } = require("../../build/libv86-debug.js"); + +const MAX_TESTFILE_SIZE = 16384; +const NUMBER_OF_TESTFILES = 16; +const NUMBER_OF_TESTREADS = 64; + +function log_pass(msg, ...args) +{ + console.log(`\x1b[92m[+] ${msg}\x1b[0m`, ...args); +} + +function log_fail(msg, ...args) +{ + console.error(`\x1b[91m[-] ${msg}\x1b[0m`, ...args); +} + +function assert_uint8array_equal(actual, expected) +{ + if(actual === null || expected === null) + { + if(actual !== null || expected !== null) + { + const the_null = actual ? "expected" : "actual"; + const not_null = actual ? "actual" : "expected"; + log_fail("Failed assert equal. %s is null but %s is not", the_null, not_null); + return false; + } + else + { + return true; + } + } + if(actual.length !== expected.length) + { + log_fail("Failed assert equal - lengths differ. Actual length: %d, Expected length: %d", + actual.length, expected.length); + return false; + } + for(let i = 0; i < actual.length; i++) + { + if(actual[i] !== expected[i]) + { + log_fail("Failed assert equal at position %d. Actual: %d, Expected %d", + i, actual[i], expected[i]); + return false; + } + } + return true; +} + +const db = new Map(); +function mock_indexeddb() +{ + return { + transaction(store_name, mode) { + return { + objectStore(store_name) { + return { + get(key) { + const result = db.get(key); + const request = { result }; + setTimeout(() => request.onsuccess(), 0); + return request; + }, + put(value) { + const key = value["sha256sum"]; + db.set(key, value); + const request = {}; + setTimeout(() => request.onsuccess(), 0); + return request; + }, + }; + }, + }; + }, + }; +} + +// Oracle without chunking. +const memory_file_storage = new MemoryFileStorage(); + +// IUT with chunking. +const indexeddb_file_storage = new IndexedDBFileStorage(mock_indexeddb()); + +async function test_read(key, offset, count) // jshint ignore:line +{ + const expected = await memory_file_storage.read(key, offset, count); // jshint ignore:line + const actual = await indexeddb_file_storage.read(key, offset, count); // jshint ignore:line + return assert_uint8array_equal(actual, expected); +} + +async function test_with_file(key, file_data) // jshint ignore:line +{ + console.log("Testing file with size: %d", file_data.length); + await memory_file_storage.set(key, file_data); // jshint ignore:line + await indexeddb_file_storage.set(key, file_data); // jshint ignore:line + + // Some boundary values. + if(!await test_read(key, 0, 0)) return; // jshint ignore:line + if(!await test_read(key, 0, 1)) return; // jshint ignore:line + if(!await test_read(key, 0, 4096)) return; // jshint ignore:line + if(!await test_read(key, 0, 4097)) return; // jshint ignore:line + if(!await test_read(key, 4095, 2)) return; // jshint ignore:line + if(!await test_read(key, 4096, 1)) return; // jshint ignore:line + if(!await test_read(key, 4096, 4096)) return; // jshint ignore:line + if(!await test_read(key, 4097, 1)) return; // jshint ignore:line + if(!await test_read(key, 4097, 4095)) return; // jshint ignore:line + + // Random ranges. + for(let i = 0; i < NUMBER_OF_TESTREADS; i++) + { + const offset = Math.floor(Math.random() * MAX_TESTFILE_SIZE); + const count = Math.floor(Math.random() * MAX_TESTFILE_SIZE); + const pass = await test_read(key, offset, count); // jshint ignore:line + if(!pass) + { + log_fail("Test case offset=%d, count=%d", offset, count); + return false; + } + } + + return true; +} + +async function test_start() // jshint ignore:line +{ + if(!await test_with_file("empty", new Uint8Array(0))) return; // jshint ignore:line + if(!await test_with_file("single", new Uint8Array(1).map(v => Math.random() * 0xFF))) return; // jshint ignore:line + if(!await test_with_file("1block", new Uint8Array(4096).map(v => Math.random() * 0xFF))) return; // jshint ignore:line + + for(let i = 0; i < NUMBER_OF_TESTFILES; i++) + { + const size = Math.floor(Math.random() * MAX_TESTFILE_SIZE); + const file_data = new Uint8Array(size).map(v => Math.random() * 0xFF); + const pass = await test_with_file(i.toString(), file_data); // jshint ignore:line + if(!pass) return; + } + log_pass("All tests passed!"); +} + +test_start(); From c9289645624b8c55edff3b23686ac47ebfd1d4e9 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 21 Nov 2018 11:08:43 +1300 Subject: [PATCH 1477/2137] Minor: Tidy quotes and spacing --- src/browser/starter.js | 2 +- tests/devices/filestorage.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index ed911aad..b5cc28e6 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -451,7 +451,7 @@ V86Starter.prototype.continue_init = async function(emulator, options) // jshint let file_storage = typeof window === "undefined" || !window.indexedDB ? new MemoryFileStorage() : await IndexedDBFileStorage.try_create(); // jshint ignore:line - if (base_url) + if(base_url) { file_storage = new ServerFileStorageWrapper(file_storage, base_url); } diff --git a/tests/devices/filestorage.js b/tests/devices/filestorage.js index 9048e6c9..7da0637c 100755 --- a/tests/devices/filestorage.js +++ b/tests/devices/filestorage.js @@ -2,7 +2,7 @@ "use strict"; process.on("unhandledRejection", exn => { throw exn; }); -const util = require('util'); +const util = require("util"); const { MemoryFileStorage, IndexedDBFileStorage } = require("../../build/libv86-debug.js"); const MAX_TESTFILE_SIZE = 16384; From ba8a67f249b360d6bbba096de5bd2e501d4354af Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 21 Nov 2018 21:41:14 +1300 Subject: [PATCH 1478/2137] Filestorage tests: Avoid globals to improve script readability --- tests/devices/filestorage.js | 55 ++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/tests/devices/filestorage.js b/tests/devices/filestorage.js index 7da0637c..b8bc3043 100755 --- a/tests/devices/filestorage.js +++ b/tests/devices/filestorage.js @@ -53,9 +53,9 @@ function assert_uint8array_equal(actual, expected) return true; } -const db = new Map(); function mock_indexeddb() { + const db = new Map(); return { transaction(store_name, mode) { return { @@ -81,42 +81,36 @@ function mock_indexeddb() }; } -// Oracle without chunking. -const memory_file_storage = new MemoryFileStorage(); - -// IUT with chunking. -const indexeddb_file_storage = new IndexedDBFileStorage(mock_indexeddb()); - -async function test_read(key, offset, count) // jshint ignore:line +async function test_read(oracle, iut, key, offset, count) // jshint ignore:line { - const expected = await memory_file_storage.read(key, offset, count); // jshint ignore:line - const actual = await indexeddb_file_storage.read(key, offset, count); // jshint ignore:line + const expected = await oracle.read(key, offset, count); // jshint ignore:line + const actual = await iut.read(key, offset, count); // jshint ignore:line return assert_uint8array_equal(actual, expected); } -async function test_with_file(key, file_data) // jshint ignore:line +async function test_with_file(oracle, iut, key, file_data) // jshint ignore:line { console.log("Testing file with size: %d", file_data.length); - await memory_file_storage.set(key, file_data); // jshint ignore:line - await indexeddb_file_storage.set(key, file_data); // jshint ignore:line + await oracle.set(key, file_data); // jshint ignore:line + await iut.set(key, file_data); // jshint ignore:line // Some boundary values. - if(!await test_read(key, 0, 0)) return; // jshint ignore:line - if(!await test_read(key, 0, 1)) return; // jshint ignore:line - if(!await test_read(key, 0, 4096)) return; // jshint ignore:line - if(!await test_read(key, 0, 4097)) return; // jshint ignore:line - if(!await test_read(key, 4095, 2)) return; // jshint ignore:line - if(!await test_read(key, 4096, 1)) return; // jshint ignore:line - if(!await test_read(key, 4096, 4096)) return; // jshint ignore:line - if(!await test_read(key, 4097, 1)) return; // jshint ignore:line - if(!await test_read(key, 4097, 4095)) return; // jshint ignore:line + if(!await test_read(oracle, iut, key, 0, 0)) return; // jshint ignore:line + if(!await test_read(oracle, iut, key, 0, 1)) return; // jshint ignore:line + if(!await test_read(oracle, iut, key, 0, 4096)) return; // jshint ignore:line + if(!await test_read(oracle, iut, key, 0, 4097)) return; // jshint ignore:line + if(!await test_read(oracle, iut, key, 4095, 2)) return; // jshint ignore:line + if(!await test_read(oracle, iut, key, 4096, 1)) return; // jshint ignore:line + if(!await test_read(oracle, iut, key, 4096, 4096)) return; // jshint ignore:line + if(!await test_read(oracle, iut, key, 4097, 1)) return; // jshint ignore:line + if(!await test_read(oracle, iut, key, 4097, 4095)) return; // jshint ignore:line // Random ranges. for(let i = 0; i < NUMBER_OF_TESTREADS; i++) { const offset = Math.floor(Math.random() * MAX_TESTFILE_SIZE); const count = Math.floor(Math.random() * MAX_TESTFILE_SIZE); - const pass = await test_read(key, offset, count); // jshint ignore:line + const pass = await test_read(oracle, iut, key, offset, count); // jshint ignore:line if(!pass) { log_fail("Test case offset=%d, count=%d", offset, count); @@ -129,17 +123,24 @@ async function test_with_file(key, file_data) // jshint ignore:line async function test_start() // jshint ignore:line { - if(!await test_with_file("empty", new Uint8Array(0))) return; // jshint ignore:line - if(!await test_with_file("single", new Uint8Array(1).map(v => Math.random() * 0xFF))) return; // jshint ignore:line - if(!await test_with_file("1block", new Uint8Array(4096).map(v => Math.random() * 0xFF))) return; // jshint ignore:line + // Test oracle without chunking. + const oracle = new MemoryFileStorage(); + + // Implementation under test with chunking. + const iut = new IndexedDBFileStorage(mock_indexeddb()); + + if(!await test_with_file(oracle, iut, "empty", new Uint8Array(0))) return; // jshint ignore:line + if(!await test_with_file(oracle, iut, "single", new Uint8Array(1).map(v => Math.random() * 0xFF))) return; // jshint ignore:line + if(!await test_with_file(oracle, iut, "1block", new Uint8Array(4096).map(v => Math.random() * 0xFF))) return; // jshint ignore:line for(let i = 0; i < NUMBER_OF_TESTFILES; i++) { const size = Math.floor(Math.random() * MAX_TESTFILE_SIZE); const file_data = new Uint8Array(size).map(v => Math.random() * 0xFF); - const pass = await test_with_file(i.toString(), file_data); // jshint ignore:line + const pass = await test_with_file(oracle, iut, i.toString(), file_data); // jshint ignore:line if(!pass) return; } + log_pass("All tests passed!"); } From ad3bf2afe0978840356ec344a1d9e0f0f6f9da12 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 21 Nov 2018 21:47:17 +1300 Subject: [PATCH 1479/2137] Filestorage: Export classes properly to all platforms --- src/browser/filestorage.js | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index 1df76fe1..d5a2bfb0 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -390,6 +390,23 @@ ServerFileStorageWrapper.prototype.uncache = function(sha256sum) this.storage.uncache(sha256sum); }; -module.exports["MemoryFileStorage"] = MemoryFileStorage; -module.exports["IndexedDBFileStorage"] = IndexedDBFileStorage; -module.exports["ServerFileStorageWrapper"] = ServerFileStorageWrapper; +// Closure Compiler's way of exporting +if(typeof window !== "undefined") +{ + window["MemoryFileStorage"] = MemoryFileStorage; + window["IndexedDBFileStorage"] = IndexedDBFileStorage; + window["ServerFileStorageWrapper"] = ServerFileStorageWrapper; +} +else if(typeof module !== "undefined" && typeof module.exports !== "undefined") +{ + module.exports["MemoryFileStorage"] = MemoryFileStorage; + module.exports["IndexedDBFileStorage"] = IndexedDBFileStorage; + module.exports["ServerFileStorageWrapper"] = ServerFileStorageWrapper; +} +else if(typeof importScripts === "function") +{ + // web worker + self["MemoryFileStorage"] = MemoryFileStorage; + self["IndexedDBFileStorage"] = IndexedDBFileStorage; + self["ServerFileStorageWrapper"] = ServerFileStorageWrapper; +} From b96e36ddd40f02eb6616e9b138bf101aa67247c1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 5 Nov 2018 15:10:35 -0600 Subject: [PATCH 1480/2137] Allow dev tools on electron --- src/browser/keyboard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/keyboard.js b/src/browser/keyboard.js index f4207fb2..d9659596 100644 --- a/src/browser/keyboard.js +++ b/src/browser/keyboard.js @@ -284,7 +284,7 @@ function KeyboardAdapter(bus) function may_handle(e) { - if(e.shiftKey && e.ctrlKey && (e.keyCode === 74 || e.keyCode === 75)) + if(e.shiftKey && e.ctrlKey && (e.keyCode === 73 || e.keyCode === 74 || e.keyCode === 75)) { // don't prevent opening chromium dev tools // maybe add other important combinations here, too From 3f3446b5dd7222b5a8f6cd8e86b5b6f48bf76101 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 19 Nov 2018 12:56:03 -0600 Subject: [PATCH 1481/2137] Update linux-boot benchmark script --- src/browser/print_stats.js | 5 ++ tests/benchmark/linux-boot.js | 91 +++++++++++++++++------------------ 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index ccdcf0e0..081f4352 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -245,3 +245,8 @@ const print_stats = { return text; }, }; + +if(typeof module !== "undefined" && typeof module.exports !== "undefined") +{ + module.exports["print_stats"] = print_stats; +} diff --git a/tests/benchmark/linux-boot.js b/tests/benchmark/linux-boot.js index 91178c32..e6803758 100755 --- a/tests/benchmark/linux-boot.js +++ b/tests/benchmark/linux-boot.js @@ -1,17 +1,44 @@ #!/usr/bin/env node "use strict"; -var V86 = require("../../build/libv86.js").V86; -var fs = require("fs"); -const LOG_SERIAL = false; +const V86 = require("../../build/libv86.js").V86; +const print_stats = require("../../build/libv86.js").print_stats; +const fs = require("fs"); +const path = require("path"); +const V86_ROOT = path.join(__dirname, "../.."); -var emulator = new V86({ - bios: { url: __dirname + "/../../bios/seabios.bin" }, - vga_bios: { url: __dirname + "/../../bios/vgabios.bin" }, - cdrom: { url: __dirname + "/../../images/linux3.iso" }, - autostart: true, - memory_size: 32 * 1024 * 1024, -}); +const LOG_SERIAL = true; + +if(false) +{ + var emulator = new V86({ + bios: { url: __dirname + "/../../bios/seabios.bin" }, + vga_bios: { url: __dirname + "/../../bios/vgabios.bin" }, + cdrom: { url: __dirname + "/../../images/linux3.iso" }, + autostart: true, + memory_size: 32 * 1024 * 1024, + }); +} +else +{ + var emulator = new V86({ + bios: { url: path.join(V86_ROOT, "/bios/seabios.bin") }, + vga_bios: { url: path.join(V86_ROOT, "/bios/vgabios.bin") }, + autostart: true, + memory_size: 512 * 1024 * 1024, + vga_memory_size: 8 * 1024 * 1024, + network_relay_url: "", + bzimage_initrd_from_filesystem: true, + cmdline: "rw init=/bin/systemd root=host9p console=ttyS0 spectre_v2=off pti=off", + filesystem: { + basefs: { + url: path.join(V86_ROOT, "/images/debian-base-fs.json"), + }, + baseurl: path.join(V86_ROOT, "/images/debian-9p-rootfs-flat/"), + }, + screen_dummy: true, + }); +} emulator.bus.register("emulator-started", function() { @@ -19,27 +46,16 @@ emulator.bus.register("emulator-started", function() start_time = Date.now(); }); -var line = ""; +var serial_text = ""; var start_time; -emulator.add_listener("serial0-output-char", function(chr) +emulator.add_listener("serial0-output-char", function(c) { - if(chr < " " && chr !== "\n" && chr !== "\t" || chr > "~") - { - return; - } + if(LOG_SERIAL) process.stdout.write(c); - if(chr === "\n") - { - if(LOG_SERIAL) console.error("Serial: %s", line); - line = ""; - } - else - { - line += chr; - } + serial_text += c; - if(line.endsWith("~% ")) + if(serial_text.endsWith("~% ") || serial_text.endsWith("root@localhost:~# ")) { const end_time = Date.now(); const elapsed = end_time - start_time; @@ -47,27 +63,6 @@ emulator.add_listener("serial0-output-char", function(chr) emulator.stop(); const cpu = emulator.v86.cpu; - const stat_names = [ - "COMPILE", - "COMPILE_SUCCESS", - "RUN_INTERPRETED", - "RUN_FROM_CACHE", - "CACHE_MISMATCH", - "NONFAULTING_OPTIMIZATION", - "CLEAR_TLB", - "FULL_CLEAR_TLB", - "TLB_FULL", - "TLB_GLOBAL_FULL", - ]; - let text = ""; - - for(let i = 0; i < stat_names.length; i++) - { - let stat = cpu.wm.exports["_profiler_stat_get"](i); - stat = stat > 9999 ? Math.round(stat / 1000) + "k" : stat; - text += stat_names[i] + "=" + stat + " "; - } - - console.log(text); + console.log(print_stats.stats_to_string(cpu)); } }); From 0e16983dd334a455362b00520fdf67f8f4ec7fdb Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 14 Nov 2018 14:49:13 -0600 Subject: [PATCH 1482/2137] Handle case when wasm table is full (fixes #35) Also fix jit_empty_cache when callbacks are pending (fixes #53) This is also a preparation for setting WASM_TABLE_SIZE to a low value to work around memory limitations in browsers. --- src/browser/starter.js | 8 +++---- src/rust/cpu.rs | 3 +++ src/rust/jit.rs | 52 ++++++++++++++++++++++++++++++------------ 3 files changed, 43 insertions(+), 20 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index b5cc28e6..2e9ed561 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -179,6 +179,7 @@ function V86Starter(options) cpu.codegen_finalize(wasm_table_index, start, end, first_opcode, state_flags); }, "jit_clear_func": (wasm_table_index) => cpu.jit_clear_func(wasm_table_index), + "jit_clear_cache": () => cpu.jit_clear_cache(), "do_task_switch": (selector, has_error_code, error_code) => { cpu.do_task_switch(selector, has_error_code, error_code); }, @@ -205,13 +206,10 @@ function V86Starter(options) v86oxide_bin, { "env": wasm_shared_funcs }, v86oxide => { + wasm_memory = v86oxide.exports.memory; v86oxide.exports["rust_setup"](); - wasm_memory = v86oxide.exports.memory; - - const wm = v86oxide; - - const emulator = this.v86 = new v86(this.emulator_bus, wm, v86oxide); + const emulator = this.v86 = new v86(this.emulator_bus, v86oxide, v86oxide); cpu = emulator.cpu; this.continue_init(emulator, options); diff --git a/src/rust/cpu.rs b/src/rust/cpu.rs index a76c6666..2727cf3d 100644 --- a/src/rust/cpu.rs +++ b/src/rust/cpu.rs @@ -14,6 +14,7 @@ mod unsafe_cpu { state_flags: u32, ); pub fn jit_clear_func(wasm_table_index: u16); + pub fn jit_clear_cache(); } } @@ -55,3 +56,5 @@ pub fn codegen_finalize( pub fn jit_clear_func(wasm_table_index: u16) { unsafe { unsafe_cpu::jit_clear_func(wasm_table_index) } } + +pub fn jit_clear_cache() { unsafe { unsafe_cpu::jit_clear_cache() } } diff --git a/src/rust/jit.rs b/src/rust/jit.rs index f9a32498..5c0f48ee 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -1,4 +1,5 @@ use std::collections::{BTreeMap, HashMap, HashSet}; +use std::iter::FromIterator; use analysis::AnalysisType; use codegen; @@ -326,10 +327,14 @@ pub struct JitState { impl JitState { pub fn create_and_initialise() -> JitState { let mut wasm_builder = WasmBuilder::new(); + jit_cache_array::clear(); wasm_builder.init(); + + // don't assign 0 (XXX: Check) + let wasm_table_indices = 1..=(WASM_TABLE_SIZE - 1) as u16; let mut c = JitState { hot_code_addresses: [0; HASH_PRIME as usize], - wasm_table_index_free_list: vec![], + wasm_table_index_free_list: Vec::from_iter(wasm_table_indices), wasm_table_index_pending_free: vec![], entry_points: HashMap::new(), wasm_builder, @@ -784,12 +789,28 @@ fn jit_analyze_and_generate( // ); //} - jit_generate_module( - &basic_blocks, - requires_loop_limit, - cpu.clone(), - &mut ctx.wasm_builder, - ); + if ctx.wasm_table_index_free_list.is_empty() { + dbg_log!( + "wasm_table_index_free_list empty ({} pending_free), clearing cache", + ctx.wasm_table_index_pending_free.len(), + ); + + // When no free slots are available, delete all cached modules. We could increase the + // size of the table, but this way the initial size acts as an upper bound for the + // number of wasm modules that we generate, which we want anyway to avoid getting our + // tab killed by browsers due to memory constraints. + cpu::jit_clear_cache(); + + dbg_log!( + "after jit_clear_cache: {} pending_free {} free", + ctx.wasm_table_index_pending_free.len(), + ctx.wasm_table_index_free_list.len(), + ); + + // This assertion can fail if all entries are pending (not possible unless + // WASM_TABLE_SIZE is set very low) + dbg_assert!(!ctx.wasm_table_index_free_list.is_empty()); + } // allocate an index in the wasm table let wasm_table_index = ctx @@ -798,6 +819,13 @@ fn jit_analyze_and_generate( .expect("allocate wasm table index"); dbg_assert!(wasm_table_index != 0); + jit_generate_module( + &basic_blocks, + requires_loop_limit, + cpu.clone(), + &mut ctx.wasm_builder, + ); + // create entries for each basic block that is marked as an entry point let mut entry_point_count = 0; @@ -1352,16 +1380,10 @@ pub fn jit_dirty_cache_small(ctx: &mut JitState, start_addr: u32, end_addr: u32) } pub fn jit_empty_cache(ctx: &mut JitState) { - jit_cache_array::clear(); - ctx.entry_points.clear(); - ctx.wasm_table_index_pending_free.clear(); - ctx.wasm_table_index_free_list.clear(); - - for i in 0..0xFFFF { - // don't assign 0 (XXX: Check) - ctx.wasm_table_index_free_list.push(i as u16 + 1); + for page_index in 0..0x100000 { + jit_dirty_page(ctx, Page::page_of(page_index << 12)) } } From 52b6e0caae98895c4e7709821e70de2ede6ae1d9 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 14 Nov 2018 16:44:08 -0600 Subject: [PATCH 1483/2137] Normalise memory offset in output wast in expect tests --- tests/expect/run.js | 21 ++++++++++++++++++++- tests/expect/tests/call.wast | 4 ++-- tests/expect/tests/mov16.wast | 8 ++++---- tests/expect/tests/mov32-mem.wast | 8 ++++---- tests/expect/tests/pop.wast | 2 +- tests/expect/tests/push.wast | 2 +- 6 files changed, 32 insertions(+), 13 deletions(-) diff --git a/tests/expect/run.js b/tests/expect/run.js index 70dd307f..aba1713d 100755 --- a/tests/expect/run.js +++ b/tests/expect/run.js @@ -75,6 +75,25 @@ function readline() return line; } +// Remove parts that may not be stable between multiple runs +function normalise_wast(wast) +{ + wast = wast.replace(/offset=(\d+)/g, function(match, offset) + { + offset = Number(offset); + + if(offset >= 8388608) + { + return "offset={normalised output}"; + } + else + { + return match; + } + }); + return wast; +} + function run_test({ name, executable_file, expect_file, actual_file, actual_wasm, asm_file }, onfinished) { const emulator = new V86({ @@ -98,7 +117,7 @@ function run_test({ name, executable_file, expect_file, actual_file, actual_wasm cpu.test_hook_did_generate_wasm = function(wasm) { - const wast = disassemble_wasm(wasm); + const wast = normalise_wast(disassemble_wasm(wasm)); clearTimeout(hook_not_called_timeout); fs.writeFileSync(actual_file, wast); diff --git a/tests/expect/tests/call.wast b/tests/expect/tests/call.wast index 8346cada..c599e13d 100644 --- a/tests/expect/tests/call.wast +++ b/tests/expect/tests/call.wast @@ -78,7 +78,7 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.store offset=20221952 align=1 + (i32.store offset={normalised output} align=1 (i32.xor (i32.and (get_local $l4) @@ -179,7 +179,7 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.load offset=20221952 align=1 + (i32.load offset={normalised output} align=1 (i32.xor (i32.and (get_local $l3) diff --git a/tests/expect/tests/mov16.wast b/tests/expect/tests/mov16.wast index 86fd0d84..0c4a3b54 100644 --- a/tests/expect/tests/mov16.wast +++ b/tests/expect/tests/mov16.wast @@ -59,7 +59,7 @@ (i32.const 4095)) (i32.const 4094))) (then - (i32.load16_u offset=20221952 align=1 + (i32.load16_u offset={normalised output} align=1 (i32.xor (i32.and (get_local $l2) @@ -106,7 +106,7 @@ (i32.const 4095)) (i32.const 4094))) (then - (i32.load16_u offset=20221952 align=1 + (i32.load16_u offset={normalised output} align=1 (i32.xor (i32.and (get_local $l1) @@ -167,7 +167,7 @@ (i32.const 4095)) (i32.const 4094))) (then - (i32.store16 offset=20221952 align=1 + (i32.store16 offset={normalised output} align=1 (i32.xor (i32.and (get_local $l3) @@ -224,7 +224,7 @@ (i32.const 4095)) (i32.const 4094))) (then - (i32.store16 offset=20221952 align=1 + (i32.store16 offset={normalised output} align=1 (i32.xor (i32.and (get_local $l3) diff --git a/tests/expect/tests/mov32-mem.wast b/tests/expect/tests/mov32-mem.wast index 87212d6a..fcbd4167 100644 --- a/tests/expect/tests/mov32-mem.wast +++ b/tests/expect/tests/mov32-mem.wast @@ -61,7 +61,7 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.store offset=20221952 align=1 + (i32.store offset={normalised output} align=1 (i32.xor (i32.and (get_local $l3) @@ -115,7 +115,7 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.store offset=20221952 align=1 + (i32.store offset={normalised output} align=1 (i32.xor (i32.and (get_local $l3) @@ -167,7 +167,7 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.load offset=20221952 align=1 + (i32.load offset={normalised output} align=1 (i32.xor (i32.and (get_local $l2) @@ -217,7 +217,7 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.load offset=20221952 align=1 + (i32.load offset={normalised output} align=1 (i32.xor (i32.and (get_local $l1) diff --git a/tests/expect/tests/pop.wast b/tests/expect/tests/pop.wast index 457be2bf..da63b466 100644 --- a/tests/expect/tests/pop.wast +++ b/tests/expect/tests/pop.wast @@ -56,7 +56,7 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.load offset=20221952 align=1 + (i32.load offset={normalised output} align=1 (i32.xor (i32.and (get_local $l3) diff --git a/tests/expect/tests/push.wast b/tests/expect/tests/push.wast index 5908ff96..cfb02828 100644 --- a/tests/expect/tests/push.wast +++ b/tests/expect/tests/push.wast @@ -61,7 +61,7 @@ (i32.const 4095)) (i32.const 4092))) (then - (i32.store offset=20221952 align=1 + (i32.store offset={normalised output} align=1 (i32.xor (i32.and (get_local $l4) From 71093270cdea5238122a95d79dfeacf6bb012d1f Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 19 Nov 2018 10:47:58 -0600 Subject: [PATCH 1484/2137] Add stat to track running out of wasm indices --- src/browser/print_stats.js | 1 + src/rust/jit.rs | 2 ++ src/rust/profiler.rs | 1 + 3 files changed, 4 insertions(+) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index 081f4352..27eb01b5 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -45,6 +45,7 @@ const print_stats = { "DO_RUN", "DO_MANY_CYCLES", "CYCLE_INTERNAL", + "INVALIDATE_ALL_MODULES_NO_FREE_WASM_INDICES", "INVALIDATE_PAGE", "INVALIDATE_MODULE", "INVALIDATE_CACHE_ENTRY", diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 5c0f48ee..60c090f6 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -801,6 +801,8 @@ fn jit_analyze_and_generate( // tab killed by browsers due to memory constraints. cpu::jit_clear_cache(); + profiler::stat_increment(stat::INVALIDATE_ALL_MODULES_NO_FREE_WASM_INDICES); + dbg_log!( "after jit_clear_cache: {} pending_free {} free", ctx.wasm_table_index_pending_free.len(), diff --git a/src/rust/profiler.rs b/src/rust/profiler.rs index e1515694..ee0b4ad2 100644 --- a/src/rust/profiler.rs +++ b/src/rust/profiler.rs @@ -37,6 +37,7 @@ pub enum stat { DO_MANY_CYCLES, CYCLE_INTERNAL, + INVALIDATE_ALL_MODULES_NO_FREE_WASM_INDICES, INVALIDATE_PAGE, INVALIDATE_MODULE, INVALIDATE_CACHE_ENTRY, From 562c66ac6c794cee3720c05cb4ba57451d6f6aef Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 19 Nov 2018 10:50:39 -0600 Subject: [PATCH 1485/2137] Remove unused clang-tidy config --- .clang-tidy | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 .clang-tidy diff --git a/.clang-tidy b/.clang-tidy deleted file mode 100644 index 33243ca1..00000000 --- a/.clang-tidy +++ /dev/null @@ -1,2 +0,0 @@ -Checks: '*,-llvm-header-guard,-readability-braces-around-statements,-readability-else-after-return,-google-readability-todo,-misc-unused-parameters,-*-function-size,-clang-diagnostic-unused-function,-hicpp-signed-bitwise,-hicpp-braces-around-statements' -WarningsAsErrors: '*' From 23c5ebdf61db6c4f3284be0847e2b7b1514c0dbc Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 20 Nov 2018 16:28:55 -0600 Subject: [PATCH 1486/2137] Reduce value of WASM_TABLE_SIZE and incraese JIT_THRESHOLD Now that WASM_TABLE_SIZE may be capped, we set it slightly below the limit under which chromium crashes: https://bugs.chromium.org/p/v8/issues/detail?id=8427 JIT_THRESHOLD is also reduced due to two reasons: - With the lower WASM_TABLE_SIZE, we want to avoid compiling too many modules - It has occasionally been observed that under node, the engine's wasm compiler can't catch up with the number of modules we produce, thus resulting in 100s of pending compiled modules. This most likely happens only under node as we don't render the screen and the main loop (based on setImmediate) is faster. The new value doesn't seem to exhibit this problem, but we may want to increase the threshold further if the problem appears again --- src/const.js | 4 ++-- src/rust/jit.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/const.js b/src/const.js index bd0795df..01c58284 100644 --- a/src/const.js +++ b/src/const.js @@ -346,9 +346,9 @@ var PREFIX_66 = PREFIX_MASK_OPSIZE; // alias /** @const */ var MXCSR_MASK = (0xFFFF & ~(1 << 6)); - +// See same constant in jit.rs /** @const */ -var WASM_TABLE_SIZE = 0x10000; +var WASM_TABLE_SIZE = 900; /** @const */ var WASM_TABLE_OFFSET = 1024; diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 60c090f6..f23ff445 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -15,7 +15,7 @@ use wasmgen::module_init; use wasmgen::module_init::WasmBuilder; use wasmgen::wasm_util::WasmBuf; -pub const WASM_TABLE_SIZE: u32 = 0x10000; +pub const WASM_TABLE_SIZE: u32 = 900; pub const HASH_PRIME: u32 = 6151; @@ -25,7 +25,7 @@ pub const JIT_MAX_ITERATIONS_PER_FUNCTION: u32 = 10000; pub const JIT_ALWAYS_USE_LOOP_SAFETY: bool = true; -pub const JIT_THRESHOLD: u32 = 8 * 10000; +pub const JIT_THRESHOLD: u32 = 200 * 1000; const CONDITION_FUNCTIONS: [&str; 16] = [ "test_o", "test_no", "test_b", "test_nb", "test_z", "test_nz", "test_be", "test_nbe", "test_s", From 5b95165de2b444ec9e8b30a5f595bd866102029a Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 20 Nov 2018 16:42:32 -0600 Subject: [PATCH 1487/2137] Add TEST_RELEASE_BUILD to run tests on release build --- tests/api/clean-shutdown.js | 4 +++- tests/api/state.js | 4 +++- tests/devices/virtio_9p.js | 5 ++++- tests/expect/run.js | 5 +++-- tests/full/run.js | 3 ++- tests/jit-paging/run.js | 4 +++- tests/kvm-unit-tests/run.js | 4 +++- tests/nasm/run.js | 3 ++- tests/qemu/run.js | 4 +++- 9 files changed, 26 insertions(+), 10 deletions(-) diff --git a/tests/api/clean-shutdown.js b/tests/api/clean-shutdown.js index 77e458e6..4fa59b9f 100755 --- a/tests/api/clean-shutdown.js +++ b/tests/api/clean-shutdown.js @@ -4,8 +4,10 @@ // This test checks that calling emulator.stop() will remove all event // listeners, so that the nodejs process cleanly and automatically exits. +const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD; + const fs = require("fs"); -const V86 = require("../../build/libv86-debug.js").V86; +var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86; process.on("unhandledRejection", exn => { throw exn; }); diff --git a/tests/api/state.js b/tests/api/state.js index 014648e4..a2c4a2db 100755 --- a/tests/api/state.js +++ b/tests/api/state.js @@ -3,7 +3,9 @@ process.on("unhandledRejection", exn => { throw exn; }); -var V86 = require("../../build/libv86-debug.js").V86; +const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD; + +var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86; var fs = require("fs"); const config_async_cdrom = { diff --git a/tests/devices/virtio_9p.js b/tests/devices/virtio_9p.js index 863ea244..12d58e8d 100755 --- a/tests/devices/virtio_9p.js +++ b/tests/devices/virtio_9p.js @@ -2,7 +2,10 @@ "use strict"; process.on("unhandledRejection", exn => { throw exn; }); -const V86 = require("../../build/libv86-debug.js").V86; + +const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD; + +var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86; const fs = require("fs"); const testfsjson = require("./testfs.json"); diff --git a/tests/expect/run.js b/tests/expect/run.js index aba1713d..53ac0cc0 100755 --- a/tests/expect/run.js +++ b/tests/expect/run.js @@ -1,15 +1,16 @@ #!/usr/bin/env node "use strict"; +const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD; + const fs = require("fs"); const path = require("path"); -const process = require("process"); const { spawnSync } = require("child_process"); const libwabt = require("../../build/libwabt.js"); try { - var V86 = require("../../build/libv86-debug.js").V86; + var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86; } catch(e) { console.error(e); diff --git a/tests/full/run.js b/tests/full/run.js index d20eaf2f..50494757 100755 --- a/tests/full/run.js +++ b/tests/full/run.js @@ -6,13 +6,14 @@ process.on("unhandledRejection", exn => { throw exn; }); var TIMEOUT_EXTRA_FACTOR = +process.env.TIMEOUT_EXTRA_FACTOR || 1; var MAX_PARALLEL_TESTS = +process.env.MAX_PARALLEL_TESTS || 4; var TEST_NAME = process.env.TEST_NAME; +const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD; const VERBOSE = false; const RUN_SLOW_TESTS = false; try { - var V86 = require("../../build/libv86-debug.js").V86; + var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86; } catch(e) { diff --git a/tests/jit-paging/run.js b/tests/jit-paging/run.js index ed045a64..b14d0c06 100755 --- a/tests/jit-paging/run.js +++ b/tests/jit-paging/run.js @@ -3,7 +3,9 @@ process.on("unhandledRejection", exn => { throw exn; }); -var V86 = require("../../build/libv86-debug.js").V86; +const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD; + +var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86; var fs = require("fs"); var test_executable = new Uint8Array(fs.readFileSync(__dirname + "/test-jit")); diff --git a/tests/kvm-unit-tests/run.js b/tests/kvm-unit-tests/run.js index a7441afa..bf38be2a 100755 --- a/tests/kvm-unit-tests/run.js +++ b/tests/kvm-unit-tests/run.js @@ -3,7 +3,9 @@ process.on("unhandledRejection", exn => { throw exn; }); -var V86 = require("../../build/libv86-debug.js").V86; +const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD; + +var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86; var fs = require("fs"); function readfile(path) diff --git a/tests/nasm/run.js b/tests/nasm/run.js index 4bd78de0..c16b127d 100755 --- a/tests/nasm/run.js +++ b/tests/nasm/run.js @@ -23,6 +23,7 @@ const cluster = require("cluster"); const MAX_PARALLEL_TESTS = +process.env.MAX_PARALLEL_TESTS || 99; const TEST_NAME = process.env.TEST_NAME; const SINGLE_TEST_TIMEOUT = 10000; +const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD; const TEST_DIR = __dirname + "/build/"; const DONE_MSG = "DONE"; @@ -33,7 +34,7 @@ const FORCE_JIT = process.argv.includes("--force-jit"); const MASK_ARITH = 1 | 1 << 2 | 1 << 4 | 1 << 6 | 1 << 7 | 1 << 11; try { - var V86 = require("../../build/libv86-debug.js").V86; + var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86; } catch(e) { console.error(e); diff --git a/tests/qemu/run.js b/tests/qemu/run.js index 19a2f3d6..838153b0 100755 --- a/tests/qemu/run.js +++ b/tests/qemu/run.js @@ -3,7 +3,9 @@ process.on("unhandledRejection", exn => { throw exn; }); -var V86 = require("../../build/libv86-debug.js").V86; +const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD; + +var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86; var fs = require("fs"); var test_executable = new Uint8Array(fs.readFileSync(__dirname + "/test-i386")); From 9e13650c19db7ddf392c5dffcb65a2af91e5d966 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 21 Nov 2018 15:20:19 -0600 Subject: [PATCH 1488/2137] fixup expect tests --- tests/expect/run.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/expect/run.js b/tests/expect/run.js index 53ac0cc0..7d09e67e 100755 --- a/tests/expect/run.js +++ b/tests/expect/run.js @@ -22,6 +22,7 @@ catch(e) { const TEST_NAME = process.env.TEST_NAME; const LOG_LEVEL = 0; +const V86OXIDE_GLOBAL_BASE = 8388608; const GIT_DIFF_FLAGS = ["--no-index", "--patience", "--color=always"]; @@ -83,7 +84,7 @@ function normalise_wast(wast) { offset = Number(offset); - if(offset >= 8388608) + if(offset >= V86OXIDE_GLOBAL_BASE) { return "offset={normalised output}"; } From 11831d1b601577d6f9406d737f279fc5a2b30f58 Mon Sep 17 00:00:00 2001 From: Amaan Cheval Date: Sat, 24 Nov 2018 20:35:13 +0530 Subject: [PATCH 1489/2137] Upcase strip_debug for consistency in Makefile --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 8902296b..ed5d3cfe 100644 --- a/Makefile +++ b/Makefile @@ -14,9 +14,9 @@ JIT_DEPENDENCIES=$(GEN_DEPENDENCIES) gen/generate_jit.js INTERPRETER_DEPENDENCIES=$(GEN_DEPENDENCIES) gen/generate_interpreter.js ANALYZER_DEPENDENCIES=$(GEN_DEPENDENCIES) gen/generate_analyzer.js -STRIP_DEBUG= -ifeq ($(strip_debug),true) -STRIP_DEBUG=--v86-strip-debug +STRIP_DEBUG_FLAG= +ifeq ($(STRIP_DEBUG),true) +STRIP_DEBUG_FLAG=--v86-strip-debug endif all: build/v86_all.js build/libv86.js build/v86oxide.wasm @@ -88,7 +88,7 @@ CARGO_FLAGS=\ --target wasm32-unknown-unknown \ -- \ -C linker=tools/rust-lld-wrapper \ - -C link-args="--import-table --global-base=8388608 $(STRIP_DEBUG)" \ + -C link-args="--import-table --global-base=8388608 $(STRIP_DEBUG_FLAG)" \ --verbose CORE_FILES=const.js config.js io.js main.js lib.js coverage.js ide.js pci.js floppy.js \ From bea53fdfb2ed05e8f4905c8f38548ad2054ca907 Mon Sep 17 00:00:00 2001 From: Fabian Date: Fri, 23 Nov 2018 10:59:49 -0600 Subject: [PATCH 1490/2137] Fix profiler build --- src/rust/jit.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/rust/jit.rs b/src/rust/jit.rs index f23ff445..5db5242f 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -1430,8 +1430,9 @@ pub fn check_missed_entry_points(phys_address: u32, state_flags: CachedStateFlag { profiler::stat_increment(stat::RUN_INTERPRETED_MISSED_COMPILED_ENTRY_LOOKUP); - let last_jump_type = unsafe { cpu2::cpu::debug_last_jump.name() }; - let last_jump_addr = unsafe { cpu2::cpu::debug_last_jump.phys_address() }.unwrap_or(0); + let last_jump_type = unsafe { ::cpu2::cpu::debug_last_jump.name() }; + let last_jump_addr = + unsafe { ::cpu2::cpu::debug_last_jump.phys_address() }.unwrap_or(0); let last_jump_opcode = if last_jump_addr != 0 { cpu::read32(last_jump_addr) } From 0d70c87796feef4fac90a20066107f69c6f90977 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 24 Nov 2018 15:24:56 -0600 Subject: [PATCH 1491/2137] Implement rdrand on Node (for __x86_rdrand) --- src/lib.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/lib.js b/src/lib.js index 811f134d..e30d401f 100644 --- a/src/lib.js +++ b/src/lib.js @@ -94,6 +94,20 @@ if(typeof window !== "undefined" && window.crypto && window.crypto.getRandomValu return rand_data[0]; }; } +else if(typeof require !== "undefined") +{ + const crypto = require("crypto"); + + v86util.has_rand_int = function() + { + return true; + }; + + v86util.get_rand_int = function() + { + return new Int32Array(crypto.randomBytes(4)); + }; +} else { v86util.has_rand_int = function() From 47e91de6014e4bafbb4a1f42f13b4664764d5b5a Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 24 Nov 2018 15:29:42 -0600 Subject: [PATCH 1492/2137] Remove has_rand_int, always require get_rand_int to be available --- src/browser/starter.js | 1 - src/lib.js | 20 +------------------- src/rust/cpu2/instructions_0f.rs | 10 ++-------- 3 files changed, 3 insertions(+), 28 deletions(-) diff --git a/src/browser/starter.js b/src/browser/starter.js index 2e9ed561..25944f00 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -115,7 +115,6 @@ function V86Starter(options) "unimplemented_sse": function() { return cpu.unimplemented_sse(); }, "microtick": v86.microtick, "get_rand_int": function() { return v86util.get_rand_int(); }, - "has_rand_int": function() { return v86util.has_rand_int(); }, "dbg_trace": function() { dbg_trace(); diff --git a/src/lib.js b/src/lib.js index e30d401f..6da48772 100644 --- a/src/lib.js +++ b/src/lib.js @@ -83,11 +83,6 @@ if(typeof window !== "undefined" && window.crypto && window.crypto.getRandomValu { let rand_data = new Int32Array(1); - v86util.has_rand_int = function() - { - return true; - }; - v86util.get_rand_int = function() { window.crypto.getRandomValues(rand_data); @@ -98,11 +93,6 @@ else if(typeof require !== "undefined") { const crypto = require("crypto"); - v86util.has_rand_int = function() - { - return true; - }; - v86util.get_rand_int = function() { return new Int32Array(crypto.randomBytes(4)); @@ -110,15 +100,7 @@ else if(typeof require !== "undefined") } else { - v86util.has_rand_int = function() - { - return false; - }; - - v86util.get_rand_int = function() - { - console.assert(false); - }; + dbg_assert(false, "Unsupported platform: No cryptographic random values"); } diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index ba2387de..817ff829 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -12,8 +12,6 @@ extern "C" { #[no_mangle] fn get_rand_int() -> i32; #[no_mangle] - fn has_rand_int() -> bool; - #[no_mangle] fn cpuid(); #[no_mangle] fn lsl(r: i32, v: i32) -> i32; @@ -3838,14 +3836,10 @@ pub unsafe fn instr_0FC7_1_mem(addr: i32) { #[no_mangle] pub unsafe fn instr_0FC7_6_reg(r: i32) { // rdrand - let has_rand: i32 = has_rand_int() as i32; - let mut rand: i32 = 0; - if 0 != has_rand { - rand = get_rand_int() - } + let rand = get_rand_int(); write_reg_osize(r, rand); *flags &= !FLAGS_ALL; - *flags |= has_rand; + *flags |= 1; *flags_changed = 0; } #[no_mangle] From dc44667642b055ad4d8d3dbb7537f1cc007e2f1b Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 24 Nov 2018 15:44:04 -0600 Subject: [PATCH 1493/2137] Minor: Remove unused --- docker/debian-full/build-state.js | 1 - 1 file changed, 1 deletion(-) diff --git a/docker/debian-full/build-state.js b/docker/debian-full/build-state.js index e9e95b51..33d55688 100755 --- a/docker/debian-full/build-state.js +++ b/docker/debian-full/build-state.js @@ -14,7 +14,6 @@ var V86 = require("./../../build/libv86.js").V86; const V86_ROOT = path.join(__dirname, "../.."); var OUTPUT_FILE = path.join(V86_ROOT, "images/debian-state-base.bin"); -var SCREEN_FILE = "/tmp/screen_debian_full.txt"; process.stdin.setRawMode(true); process.stdin.resume(); From aadae9242ce2f958f344fc04e249c5cdb072a9ea Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 25 Nov 2018 14:05:04 +1300 Subject: [PATCH 1494/2137] Filestorage: Clone array views to avoid serializing full array buffer IndexedDB uses the StructuredSerializeForStorage algorithm to store records into the database. It appears that the html5 spec defines the StructuredSerializeForStorage algorithm in a way that, when we serialize a TypedArray, the associated ArrayBuffer is also serialized. Meaning even if the TypedArray is a view of a single byte in the ArrayBuffer, the potentially-megabytes of data in the ArrayBuffer are also copied over. This makes sense. After deserialization, you'd expect the TypedArray to function the same way as before meaning it should have the same `.byteOffset` and `.buffer` properties. However, it is easy to overlook this and think that a TypedArray viewing 2 bytes will only have the 2 bytes stored in the database. This commit fixes a source of crashes. When calling IndexedDBFileStorage#set() with a 3Mb file, the file is to be stored as approx 800 lots of 4k blocks. However, in reality, 800 lots of 3 Mb array buffers are being stored into the database. As the transaction is not committed until the last request has been placed, I suspect that Chrome was trying to store those 2.4 Gb worth of data in memory and did not handle this case properly, leading to out-of-memory. This commit also fixes a source of poor performance. When calling IndexedDBFileStorage#read() to read 4k of a 48 Mb file, the browser seems to be deserializing the entire 48 Mb into memory and garbage collecting it even though only 4k is needed. --- src/browser/filestorage.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index d5a2bfb0..5a7919f9 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -301,7 +301,8 @@ IndexedDBFileStorage.prototype.set = async function(sha256sum, data) // jshint i await this.db_set(store, { // jshint ignore:line [INDEXEDDB_STORAGE_KEY_PATH]: sha256sum, - [INDEXEDDB_STORAGE_DATA_PATH]: data.subarray(0, INDEXEDDB_STORAGE_CHUNKING_THRESHOLD), + // Note: Without cloning, the entire backing ArrayBuffer is serialized into the database. + [INDEXEDDB_STORAGE_DATA_PATH]: data.slice(0, INDEXEDDB_STORAGE_CHUNKING_THRESHOLD), [INDEXEDDB_STORAGE_TOTALSIZE_PATH]: data.length, [INDEXEDDB_STORAGE_EXTRABLOCKCOUNT_PATH]: extra_block_count, }); @@ -310,7 +311,8 @@ IndexedDBFileStorage.prototype.set = async function(sha256sum, data) // jshint i for(let i = 0; offset < data.length; i++, offset += INDEXEDDB_STORAGE_BLOCKSIZE) { const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, i); - const block_data = data.subarray(offset, offset + INDEXEDDB_STORAGE_BLOCKSIZE); + // Note: Without cloning, the entire backing ArrayBuffer is serialized into the database. + const block_data = data.slice(offset, offset + INDEXEDDB_STORAGE_BLOCKSIZE); await this.db_set(store, { //jshint ignore:line [INDEXEDDB_STORAGE_KEY_PATH]: block_key, [INDEXEDDB_STORAGE_DATA_PATH]: block_data, From 75bee02ac7b422ce754cef81393032b50dd582a1 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 25 Nov 2018 14:23:12 +1300 Subject: [PATCH 1495/2137] Filestorage: Don't wait before issuing next store.put request --- src/browser/filestorage.js | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index 5a7919f9..2c5967ba 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -183,21 +183,6 @@ IndexedDBFileStorage.prototype.db_get = function(store, key) }); }; -/** - * @private - * @param {IDBObjectStore} store - * @param {Object} value - * @return {!Promise} - */ -IndexedDBFileStorage.prototype.db_set = function(store, value) -{ - return new Promise((resolve, reject) => - { - const request = store.put(value); - request.onsuccess = event => resolve(); - }); -}; - /** * @param {string} sha256sum * @param {number} offset @@ -299,7 +284,7 @@ IndexedDBFileStorage.prototype.set = async function(sha256sum, data) // jshint i INDEXEDDB_STORAGE_BLOCKSIZE ); - await this.db_set(store, { // jshint ignore:line + store.put({ // jshint ignore:line [INDEXEDDB_STORAGE_KEY_PATH]: sha256sum, // Note: Without cloning, the entire backing ArrayBuffer is serialized into the database. [INDEXEDDB_STORAGE_DATA_PATH]: data.slice(0, INDEXEDDB_STORAGE_CHUNKING_THRESHOLD), @@ -313,11 +298,15 @@ IndexedDBFileStorage.prototype.set = async function(sha256sum, data) // jshint i const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, i); // Note: Without cloning, the entire backing ArrayBuffer is serialized into the database. const block_data = data.slice(offset, offset + INDEXEDDB_STORAGE_BLOCKSIZE); - await this.db_set(store, { //jshint ignore:line + store.put({ //jshint ignore:line [INDEXEDDB_STORAGE_KEY_PATH]: block_key, [INDEXEDDB_STORAGE_DATA_PATH]: block_data, }); } + + await new Promise((resolve, reject) => { // jshint ignore:line + transaction.oncomplete = event => resolve(); + }); }; // jshint ignore:line /** From 602cfe0e3c43f1650f2b7448ebd1b78d703d5e47 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 25 Nov 2018 15:06:27 +1300 Subject: [PATCH 1496/2137] Filestorage: Fix IndexedDB error logging --- src/browser/filestorage.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index 2c5967ba..9fd00f59 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -153,7 +153,7 @@ IndexedDBFileStorage.init_db = function() }; db.onerror = event => { - const error = event.originalTarget.error; + const error = event.target.error; dbg_log("IndexedDBFileStorage: unexpected error: " + error, LOG_9P); throw error; }; @@ -196,7 +196,7 @@ IndexedDBFileStorage.prototype.read = async function(sha256sum, offset, count) / const transaction = this.db.transaction(INDEXEDDB_STORAGE_STORE, "readonly"); transaction.onerror = event => { - const error = event.originalTarget.error; + const error = event.target.error; dbg_log(`IndexedDBFileStorage read: Error with transaction: ${error}`, LOG_9P); throw error; }; @@ -273,7 +273,7 @@ IndexedDBFileStorage.prototype.set = async function(sha256sum, data) // jshint i const transaction = this.db.transaction(INDEXEDDB_STORAGE_STORE, "readwrite"); transaction.onerror = event => { - const error = event.originalTarget.error; + const error = event.target.error; dbg_log(`IndexedDBFileStorage set: Error with transaction: ${error}`, LOG_9P); throw error; }; From 27b365b30abcedae9db148aa144428f0348084f3 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 25 Nov 2018 15:51:14 +1300 Subject: [PATCH 1497/2137] Filestorage tests: Set failure exit code --- tests/devices/filestorage.js | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/tests/devices/filestorage.js b/tests/devices/filestorage.js index b8bc3043..be1bc596 100755 --- a/tests/devices/filestorage.js +++ b/tests/devices/filestorage.js @@ -95,15 +95,15 @@ async function test_with_file(oracle, iut, key, file_data) // jshint ignore:line await iut.set(key, file_data); // jshint ignore:line // Some boundary values. - if(!await test_read(oracle, iut, key, 0, 0)) return; // jshint ignore:line - if(!await test_read(oracle, iut, key, 0, 1)) return; // jshint ignore:line - if(!await test_read(oracle, iut, key, 0, 4096)) return; // jshint ignore:line - if(!await test_read(oracle, iut, key, 0, 4097)) return; // jshint ignore:line - if(!await test_read(oracle, iut, key, 4095, 2)) return; // jshint ignore:line - if(!await test_read(oracle, iut, key, 4096, 1)) return; // jshint ignore:line - if(!await test_read(oracle, iut, key, 4096, 4096)) return; // jshint ignore:line - if(!await test_read(oracle, iut, key, 4097, 1)) return; // jshint ignore:line - if(!await test_read(oracle, iut, key, 4097, 4095)) return; // jshint ignore:line + if(!await test_read(oracle, iut, key, 0, 0)) return false; // jshint ignore:line + if(!await test_read(oracle, iut, key, 0, 1)) return false; // jshint ignore:line + if(!await test_read(oracle, iut, key, 0, 4096)) return false; // jshint ignore:line + if(!await test_read(oracle, iut, key, 0, 4097)) return false; // jshint ignore:line + if(!await test_read(oracle, iut, key, 4095, 2)) return false; // jshint ignore:line + if(!await test_read(oracle, iut, key, 4096, 1)) return false; // jshint ignore:line + if(!await test_read(oracle, iut, key, 4096, 4096)) return false; // jshint ignore:line + if(!await test_read(oracle, iut, key, 4097, 1)) return false; // jshint ignore:line + if(!await test_read(oracle, iut, key, 4097, 4095)) return false; // jshint ignore:line // Random ranges. for(let i = 0; i < NUMBER_OF_TESTREADS; i++) @@ -129,19 +129,20 @@ async function test_start() // jshint ignore:line // Implementation under test with chunking. const iut = new IndexedDBFileStorage(mock_indexeddb()); - if(!await test_with_file(oracle, iut, "empty", new Uint8Array(0))) return; // jshint ignore:line - if(!await test_with_file(oracle, iut, "single", new Uint8Array(1).map(v => Math.random() * 0xFF))) return; // jshint ignore:line - if(!await test_with_file(oracle, iut, "1block", new Uint8Array(4096).map(v => Math.random() * 0xFF))) return; // jshint ignore:line + if(!await test_with_file(oracle, iut, "empty", new Uint8Array(0))) return false; // jshint ignore:line + if(!await test_with_file(oracle, iut, "single", new Uint8Array(1).map(v => Math.random() * 0xFF))) return false; // jshint ignore:line + if(!await test_with_file(oracle, iut, "1block", new Uint8Array(4096).map(v => Math.random() * 0xFF))) return false; // jshint ignore:line for(let i = 0; i < NUMBER_OF_TESTFILES; i++) { const size = Math.floor(Math.random() * MAX_TESTFILE_SIZE); const file_data = new Uint8Array(size).map(v => Math.random() * 0xFF); const pass = await test_with_file(oracle, iut, i.toString(), file_data); // jshint ignore:line - if(!pass) return; + if(!pass) return false; } log_pass("All tests passed!"); + return true; } -test_start(); +test_start().then(pass => pass || process.exit(1)); From 9e82dde504388fd03589a4af5a2b78fd92bd5f59 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 25 Nov 2018 15:53:53 +1300 Subject: [PATCH 1498/2137] Filestorage tests: Mock idb transaction.oncomplete --- tests/devices/filestorage.js | 46 +++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/tests/devices/filestorage.js b/tests/devices/filestorage.js index be1bc596..c9f31186 100755 --- a/tests/devices/filestorage.js +++ b/tests/devices/filestorage.js @@ -58,25 +58,65 @@ function mock_indexeddb() const db = new Map(); return { transaction(store_name, mode) { - return { + const transaction = { objectStore(store_name) { return { get(key) { + assert_transaction_active(`get ${key}`); const result = db.get(key); const request = { result }; - setTimeout(() => request.onsuccess(), 0); + mock_request_completion(request); return request; }, put(value) { + assert_transaction_active(`put ${value}`); const key = value["sha256sum"]; db.set(key, value); const request = {}; - setTimeout(() => request.onsuccess(), 0); + mock_request_completion(request); return request; }, }; }, }; + + let completed = false; + let pending_requests = 0; + + function assert_transaction_active(verb) + { + if(completed) + { + log_fail(`Attempted to ${verb} after transaction expired`); + process.exit(1); + } + } + function mock_request_completion(request) + { + pending_requests++; + setTimeout(() => + { + pending_requests--; + + setTimeout(() => + { + if(!pending_requests) + { + completed = true; + if(transaction.oncomplete) + { + transaction.oncomplete(); + } + } + }, 0); + + if(request.onsuccess) + { + request.onsuccess(); + } + }, 0); + } + return transaction; }, }; } From 1155faae2515c3c977eae5b9914a8ee1394df65f Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Mon, 26 Nov 2018 22:41:00 +1300 Subject: [PATCH 1499/2137] Filestorage: Simplify IndexedDBFileStorage#set - remove async --- src/browser/filestorage.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index 9fd00f59..ad1a3588 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -264,9 +264,9 @@ IndexedDBFileStorage.prototype.read = async function(sha256sum, offset, count) / /** * @param {string} sha256sum - * @param {!Uint8Array} data + * @param {!Promise} data */ -IndexedDBFileStorage.prototype.set = async function(sha256sum, data) // jshint ignore:line +IndexedDBFileStorage.prototype.set = function(sha256sum, data) { dbg_assert(sha256sum, "IndexedDBFileStorage set: sha256sum should be a non-empty string"); @@ -284,7 +284,7 @@ IndexedDBFileStorage.prototype.set = async function(sha256sum, data) // jshint i INDEXEDDB_STORAGE_BLOCKSIZE ); - store.put({ // jshint ignore:line + store.put({ [INDEXEDDB_STORAGE_KEY_PATH]: sha256sum, // Note: Without cloning, the entire backing ArrayBuffer is serialized into the database. [INDEXEDDB_STORAGE_DATA_PATH]: data.slice(0, INDEXEDDB_STORAGE_CHUNKING_THRESHOLD), @@ -298,16 +298,16 @@ IndexedDBFileStorage.prototype.set = async function(sha256sum, data) // jshint i const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, i); // Note: Without cloning, the entire backing ArrayBuffer is serialized into the database. const block_data = data.slice(offset, offset + INDEXEDDB_STORAGE_BLOCKSIZE); - store.put({ //jshint ignore:line + store.put({ [INDEXEDDB_STORAGE_KEY_PATH]: block_key, [INDEXEDDB_STORAGE_DATA_PATH]: block_data, }); } - await new Promise((resolve, reject) => { // jshint ignore:line + return new Promise((resolve, reject) => { transaction.oncomplete = event => resolve(); }); -}; // jshint ignore:line +}; /** * @param {string} sha256sum From 7e04f313bab46c0c1ce66f4e9d270b6a7cbb8c77 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 28 Nov 2018 15:18:01 -0600 Subject: [PATCH 1500/2137] Remove unused as_text option --- src/browser/lib.js | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/browser/lib.js b/src/browser/lib.js index 0115c13b..9bb1c4e3 100644 --- a/src/browser/lib.js +++ b/src/browser/lib.js @@ -53,11 +53,7 @@ var ASYNC_SAFE = false; http.open(options.method || "get", filename, true); - if(options.as_text) - { - // the default - } - else if(options.as_json) + if(options.as_json) { http.responseType = "json"; } @@ -116,7 +112,7 @@ var ASYNC_SAFE = false; if(options.range) { - dbg_assert(!options.as_text && !options.as_json); + dbg_assert(!options.as_json); fs["open"](filename, "r", (err, fd) => { @@ -141,7 +137,7 @@ var ASYNC_SAFE = false; else { var o = { - encoding: options.as_text || options.as_json ? "utf-8" : null, + encoding: options.as_json ? "utf-8" : null, }; fs["readFile"](filename, o, function(err, data) @@ -154,10 +150,7 @@ var ASYNC_SAFE = false; { var result = data; - if(options.as_text) - { - } - else if(options.as_json) + if(options.as_json) { result = JSON.parse(result); } From 4827732a4c0e01860e5b4fd1170a6517a9996953 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 28 Nov 2018 15:18:12 -0600 Subject: [PATCH 1501/2137] Make closure compiler happy --- src/cpu.js | 2 +- src/lib.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cpu.js b/src/cpu.js index 6b7b12b2..7ebc999b 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -860,7 +860,7 @@ CPU.prototype.init = function(settings, device_bus) } else if(value === FW_CFG_NUMA) { - this.fw_value = i64(0); + this.fw_value = i64(0, 0); } else if(value === FW_CFG_FILE_DIR) { diff --git a/src/lib.js b/src/lib.js index 6da48772..4d0c7a1e 100644 --- a/src/lib.js +++ b/src/lib.js @@ -91,6 +91,7 @@ if(typeof window !== "undefined" && window.crypto && window.crypto.getRandomValu } else if(typeof require !== "undefined") { + /** @type {{ randomBytes: Function }} */ const crypto = require("crypto"); v86util.get_rand_int = function() From ad16fb0656e55a58866dc431bd70f97e54958075 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Thu, 29 Nov 2018 11:33:49 +1300 Subject: [PATCH 1502/2137] Filesystem: Add missing awaits to async function calls --- lib/filesystem.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 040d3e3e..9e3a7652 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -632,7 +632,7 @@ FS.prototype.CreateTextFile = async function(filename, parentid, str) { // jshin if(this.is_forwarder(parent_inode)) { const foreign_parentid = parent_inode.foreign_id; - const foreign_id = + const foreign_id = await // jshint ignore:line this.follow_fs(parent_inode).CreateTextFile(filename, foreign_parentid, str); return this.create_forwarder(parent_inode.mount_id, foreign_id); } @@ -656,7 +656,7 @@ FS.prototype.CreateBinaryFile = async function(filename, parentid, buffer) { // if(this.is_forwarder(parent_inode)) { const foreign_parentid = parent_inode.foreign_id; - const foreign_id = + const foreign_id = await // jshint ignore:line this.follow_fs(parent_inode).CreateBinaryFile(filename, foreign_parentid, buffer); return this.create_forwarder(parent_inode.mount_id, foreign_id); } @@ -698,7 +698,7 @@ FS.prototype.CloseInode = async function(id) { // jshint ignore:line var inode = this.inodes[id]; if(this.is_forwarder(inode)) { - return this.follow_fs(inode).CloseInode(inode.foreign_id); + return await this.follow_fs(inode).CloseInode(inode.foreign_id); // jshint ignore:line } if(inode.status === STATUS_ON_STORAGE) { @@ -1054,7 +1054,7 @@ FS.prototype.DeleteData = async function(idx) // jshint ignore:line const inode = this.inodes[idx]; if(this.is_forwarder(inode)) { - this.follow_fs(inode).DeleteData(inode.foreign_id); + await this.follow_fs(inode).DeleteData(inode.foreign_id); // jshint ignore:line return; } inode.size = 0; From 4651e28177f0510a48abf2b475317d48ecfd8105 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Thu, 29 Nov 2018 11:35:55 +1300 Subject: [PATCH 1503/2137] Fix type annotations for async functions --- lib/filesystem.js | 4 ++-- src/browser/filestorage.js | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 9e3a7652..89a153ff 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -712,7 +712,7 @@ FS.prototype.CloseInode = async function(id) { // jshint ignore:line }; // jshint ignore:line /** - * @return {number} 0 if success, or -errno if failured. + * @return {!Promise} 0 if success, or -errno if failured. */ FS.prototype.Rename = async function(olddirid, oldname, newdirid, newname) { // jshint ignore:line // message.Debug("Rename " + oldname + " to " + newname); @@ -1066,7 +1066,7 @@ FS.prototype.DeleteData = async function(idx) // jshint ignore:line * @param {number} idx * @param {number} offset * @param {number} count - * @return {Uint8Array} + * @return {!Promise} */ FS.prototype.get_data = async function(idx, offset, count) // jshint ignore:line { diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index ad1a3588..e76dfaf2 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -55,7 +55,7 @@ function MemoryFileStorage() * @param {string} sha256sum * @param {number} offset * @param {number} count - * @return {!Uint8Array} null if file does not exist. + * @return {!Promise} null if file does not exist. */ MemoryFileStorage.prototype.read = async function(sha256sum, offset, count) // jshint ignore:line { @@ -114,7 +114,7 @@ IndexedDBFileStorage.try_create = async function() // jshint ignore:line }; // jshint ignore:line /** - * @return {!Promise} + * @return {!Promise} */ IndexedDBFileStorage.init_db = function() { @@ -187,7 +187,7 @@ IndexedDBFileStorage.prototype.db_get = function(store, key) * @param {string} sha256sum * @param {number} offset * @param {number} count - * @return {!Uint8Array} null if file does not exist. + * @return {!Promise} null if file does not exist. */ IndexedDBFileStorage.prototype.read = async function(sha256sum, offset, count) // jshint ignore:line { @@ -264,7 +264,7 @@ IndexedDBFileStorage.prototype.read = async function(sha256sum, offset, count) / /** * @param {string} sha256sum - * @param {!Promise} data + * @param {!Uint8Array} data */ IndexedDBFileStorage.prototype.set = function(sha256sum, data) { @@ -351,7 +351,7 @@ ServerFileStorageWrapper.prototype.load_from_server = function(sha256sum) * @param {string} sha256sum * @param {number} offset * @param {number} count - * @return {Uint8Array} + * @return {!Promise} */ ServerFileStorageWrapper.prototype.read = async function(sha256sum, offset, count) // jshint ignore:line { From e5e1f68244ed2963444b802a41af75537435162b Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Thu, 29 Nov 2018 11:37:51 +1300 Subject: [PATCH 1504/2137] Fix type error for logging filestorage error --- src/browser/filestorage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index e76dfaf2..2a940703 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -130,7 +130,7 @@ IndexedDBFileStorage.init_db = function() open_request.onerror = event => { dbg_log("Error opening IndexedDB! Are you in private browsing mode? Error:", LOG_9P); - dbg_log(open_request.error, LOG_9P); + dbg_log(open_request.error.toString(), LOG_9P); reject(open_request.error); }; From c20a54a9e435e08ec6e027f0ac40a2c9bc209e27 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 3 Dec 2018 09:37:07 -0600 Subject: [PATCH 1505/2137] Don't print full array in assertion (slow) --- src/browser/filestorage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index 2a940703..0b122b93 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -214,7 +214,7 @@ IndexedDBFileStorage.prototype.read = async function(sha256sum, offset, count) / const total_size = entry[INDEXEDDB_STORAGE_TOTALSIZE_PATH]; dbg_assert(base_data instanceof Uint8Array, - `IndexedDBFileStorage read: Invalid base entry without the data Uint8Array field: ${base_data}`); + `IndexedDBFileStorage read: Invalid base entry without the data Uint8Array field: ${base_data.constructor}`); dbg_assert(Number.isInteger(extra_block_count), `IndexedDBFileStorage read: Invalid base entry with non-integer block_count: ${extra_block_count}`); dbg_assert(Number.isInteger(total_size) && total_size >= base_data.length, @@ -250,7 +250,7 @@ IndexedDBFileStorage.prototype.read = async function(sha256sum, offset, count) / const block_data = block_entry[INDEXEDDB_STORAGE_DATA_PATH]; dbg_assert(block_data instanceof Uint8Array, - `IndexedDBFileStorage read: Entry for block-${block_number} without Uint8Array data field: ${block_data}`); + `IndexedDBFileStorage read: Entry for block-${block_number} without Uint8Array data field: ${block_data.constructor}`); const chunk_start = offset + read_count - block_offset; const chunk_end = offset + count - block_offset; From c46d12f92140ed5e082ee12e05e1d3bae9d8a71d Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 3 Dec 2018 09:38:10 -0600 Subject: [PATCH 1506/2137] Allow using libv86-debug.js with v86oxide.wasm --- src/cpu.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index 7ebc999b..72c088b6 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -249,9 +249,13 @@ CPU.prototype.create_jit_imports = function() CPU.prototype.wasm_patch = function(wm) { + const get_optional_import = (name) => { + return this.v86oxide.exports[name]; + }; + const get_import = (name) => { - const f = this.v86oxide.exports[name]; + const f = get_optional_import(name); console.assert(f, "Missing import: " + name); return f; }; @@ -311,7 +315,7 @@ CPU.prototype.wasm_patch = function(wm) if(DEBUG) { - this.jit_force_generate_unsafe = get_import("jit_force_generate_unsafe"); + this.jit_force_generate_unsafe = get_optional_import("jit_force_generate_unsafe"); } this.jit_empty_cache = get_import("jit_empty_cache"); @@ -326,6 +330,12 @@ CPU.prototype.wasm_patch = function(wm) CPU.prototype.jit_force_generate = function(addr) { + if(!this.jit_force_generate_unsafe) + { + dbg_assert(false, "Not supported in this wasm build: jit_force_generate_unsafe"); + return; + } + const cs_offset = this.get_seg(reg_cs); const state_flags = this.pack_current_state_flags(); this.jit_force_generate_unsafe(addr, cs_offset, state_flags); From 18cdd2107f167f88598d2155f31e3d6d9babacdc Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 3 Dec 2018 09:39:56 -0600 Subject: [PATCH 1507/2137] Reset fpu state in cpu.reset --- src/cpu.js | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index 72c088b6..be6a51dd 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -153,7 +153,7 @@ function CPU(bus, wm, v86oxide, coverage_logger) this.fpu_st = v86util.view(Float64Array, memory, 968, 8); this.fpu_stack_empty = v86util.view(Int32Array, memory, 816, 1); - this.fpu_stack_empty[0] = 0xff; + this.fpu_stack_empty[0] = 0xFF; this.fpu_stack_ptr = v86util.view(Uint32Array, memory, 1032, 1); this.fpu_stack_ptr[0] = 0; @@ -647,15 +647,20 @@ CPU.prototype.reset = function() this.sreg.fill(0); this.dreg.fill(0); - for(let i = 0; i < this.reg_mmxs.length; i++) - { - this.reg_mmxs[i] = 0; - } + this.fpu_st.fill(0); + this.fpu_stack_empty[0] = 0xFF; + this.fpu_stack_ptr[0] = 0; + this.fpu_control_word[0] = 0x37F; + this.fpu_status_word[0] = 0; + this.fpu_ip[0] = 0; + this.fpu_ip_selector[0] = 0; + this.fpu_opcode[0] = 0; + this.fpu_dp[0] = 0; + this.fpu_dp_selector[0] = 0; + + this.reg_mmxs.fill(0); + this.reg_xmm32s.fill(0); - for(let i = 0; i < this.reg_xmm32s.length; i++) - { - this.reg_xmm32s[i] = 0; - } this.mxcsr[0] = 0x1F80; this.full_clear_tlb(); From a179d2ec7eb71450678534afedac35a1b0b0eba4 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 3 Dec 2018 09:41:25 -0600 Subject: [PATCH 1508/2137] Reduce default logging in ne2k --- src/ne2k.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/ne2k.js b/src/ne2k.js index c7b34d24..17eebb3f 100644 --- a/src/ne2k.js +++ b/src/ne2k.js @@ -1,5 +1,6 @@ "use strict"; +const NE2K_LOG_VERBOSE = false; /** @const */ var E8390_CMD = 0x00; /* The command register (for all pages) */ @@ -558,9 +559,12 @@ Ne2k.prototype.update_irq = function() Ne2k.prototype.data_port_write = function(data_byte) { - dbg_log("Write data port: data=" + h(data_byte & 0xFF, 2) + - " rsar=" + h(this.rsar, 4) + - " rcnt=" + h(this.rcnt, 4), LOG_NET); + if(NE2K_LOG_VERBOSE) + { + dbg_log("Write data port: data=" + h(data_byte & 0xFF, 2) + + " rsar=" + h(this.rsar, 4) + + " rcnt=" + h(this.rcnt, 4), LOG_NET); + } if(this.rsar > 0x10 && this.rsar < (START_PAGE << 8)) { @@ -604,9 +608,12 @@ Ne2k.prototype.data_port_read = function() { var data = this.memory[this.rsar++]; - dbg_log("Read data port: data=" + h(data, 2) + - " rsar=" + h(this.rsar - 1, 4) + - " rcnt=" + h(this.rcnt, 4), LOG_NET); + if(NE2K_LOG_VERBOSE) + { + dbg_log("Read data port: data=" + h(data, 2) + + " rsar=" + h(this.rsar - 1, 4) + + " rcnt=" + h(this.rcnt, 4), LOG_NET); + } this.rcnt--; if(this.rsar >= (this.pstop << 8)) From bb0e58ace96a8f9cc0bbfb67295be42f7934da37 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 3 Dec 2018 10:50:34 -0600 Subject: [PATCH 1509/2137] More precise emulation of fpu instructions --- src/rust/cpu2/fpu.rs | 85 +++++++++++++++++++------ src/rust/cpu2/instructions.rs | 114 +++++++++++++++++++++++++--------- 2 files changed, 149 insertions(+), 50 deletions(-) diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index cc380af0..8c9bb0ec 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -18,7 +18,7 @@ pub const M_LN10: f64 = 2.302585092994046f64; pub const M_PI: f64 = 3.141592653589793f64; const FPU_C0: i32 = 0x100; pub const FPU_C1: i32 = 0x200; -const FPU_C2: i32 = 0x400; +pub const FPU_C2: i32 = 0x400; const FPU_C3: i32 = 0x4000; const FPU_RESULT_FLAGS: i32 = FPU_C0 | FPU_C1 | FPU_C2 | FPU_C3; const INDEFINITE_NAN: f64 = ::std::f64::NAN; @@ -88,6 +88,14 @@ pub unsafe fn fpu_stack_fault() { // TODO: Interrupt *fpu_status_word |= FPU_EX_SF | FPU_EX_I; } + +#[no_mangle] +pub unsafe fn fpu_sti_empty(mut i: i32) -> bool { + dbg_assert!(i >= 0 && i < 8); + i = ((i as u32).wrapping_add(*fpu_stack_ptr) & 7) as i32; + return 0 != *fpu_stack_empty >> i & 1; +} + #[no_mangle] pub unsafe fn fpu_get_sti(mut i: i32) -> f64 { dbg_assert!(i >= 0 && i < 8); @@ -232,10 +240,18 @@ pub unsafe fn fpu_fadd(target_index: i32, val: f64) { pub unsafe fn fpu_fclex() { *fpu_status_word = 0; } #[no_mangle] pub unsafe fn fpu_fcmovcc(condition: bool, r: i32) { - if condition { - fpu_write_st(*fpu_stack_ptr as i32, fpu_get_sti(r)); - *fpu_stack_empty &= !(1 << *fpu_stack_ptr) - }; + // outside of the condition is correct: A stack fault happens even if the condition is not + // fulfilled + let x = fpu_get_sti(r); + if fpu_sti_empty(r) { + fpu_write_st(*fpu_stack_ptr as i32, INDEFINITE_NAN) + } + else { + if condition { + fpu_write_st(*fpu_stack_ptr as i32, x); + *fpu_stack_empty &= !(1 << *fpu_stack_ptr) + }; + } } #[no_mangle] pub unsafe fn fpu_fcom(y: f64) { @@ -257,8 +273,8 @@ pub unsafe fn fpu_fcom(y: f64) { pub unsafe fn fpu_fcomi(r: i32) { let y: f64 = fpu_get_sti(r); let x: f64 = *fpu_st.offset(*fpu_stack_ptr as isize); - *flags_changed &= !(1 | FLAG_PARITY | FLAG_ZERO); - *flags &= !(1 | FLAG_PARITY | FLAG_ZERO); + *flags_changed &= !(1 | FLAG_PARITY | FLAG_ZERO | FLAG_ADJUST | FLAG_SIGN | FLAG_OVERFLOW); + *flags &= !(1 | FLAG_PARITY | FLAG_ZERO | FLAG_ADJUST | FLAG_SIGN | FLAG_OVERFLOW); if !(x > y) { if y > x { *flags |= 1 @@ -443,23 +459,52 @@ pub unsafe fn fpu_fnstsw_mem(addr: i32) { #[no_mangle] pub unsafe fn fpu_fnstsw_reg() { *reg16.offset(AX as isize) = fpu_load_status_word() as u16; } #[no_mangle] -pub unsafe fn fpu_fprem() { - // XXX: This implementation differs from the description in Intel's manuals +pub unsafe fn fpu_fprem(ieee: bool) { + // false: Faster, passes qemutests + // true: Slower, passes nasmtests + let intel_compatibility = false; + let st0: f64 = fpu_get_st0(); let st1: f64 = fpu_get_sti(1); - let fprem_quotient: i32 = convert_f64_to_i32(trunc(st0 / st1)); - fpu_write_st(*fpu_stack_ptr as i32, fmod(st0, st1)); - *fpu_status_word &= !(FPU_C0 | FPU_C1 | FPU_C3); - if 0 != fprem_quotient & 1 { - *fpu_status_word |= FPU_C1 + let exp0 = st0.log2(); + let exp1 = st1.log2(); + let d = (exp0 - exp1).abs(); + if !intel_compatibility || d < 64.0 { + let fprem_quotient: i32 = convert_f64_to_i32(if ieee { + round(st0 / st1) + } + else { + trunc(st0 / st1) + }); + fpu_write_st(*fpu_stack_ptr as i32, fmod(st0, st1)); + *fpu_status_word &= !(FPU_C0 | FPU_C1 | FPU_C3); + if 0 != fprem_quotient & 1 { + *fpu_status_word |= FPU_C1 + } + if 0 != fprem_quotient & 1 << 1 { + *fpu_status_word |= FPU_C3 + } + if 0 != fprem_quotient & 1 << 2 { + *fpu_status_word |= FPU_C0 + } + *fpu_status_word &= !FPU_C2; } - if 0 != fprem_quotient & 1 << 1 { - *fpu_status_word |= FPU_C3 + else { + let n = 32.0; + let fprem_quotient: i32 = convert_f64_to_i32( + if ieee { + round(st0 / st1) + } + else { + trunc(st0 / st1) + } / pow(2.0, d - n), + ); + fpu_write_st( + *fpu_stack_ptr as i32, + st0 - st1 * (fprem_quotient as f64) * pow(2.0, d - n), + ); + *fpu_status_word |= FPU_C2; } - if 0 != fprem_quotient & 1 << 2 { - *fpu_status_word |= FPU_C0 - } - *fpu_status_word &= !FPU_C2; } #[no_mangle] pub unsafe fn fpu_frstor(mut addr: i32) { diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index 1e9e4c6f..ae94aaf1 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -3603,6 +3603,7 @@ pub unsafe fn instr16_F3AF() { scasw_rep(PREFIX_F3); } pub unsafe fn instr32_F2AF() { scasd_rep(PREFIX_F2); } #[no_mangle] pub unsafe fn instr32_F3AF() { scasd_rep(PREFIX_F3); } + #[no_mangle] pub unsafe fn instr_D8_0_mem(addr: i32) { let ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); @@ -3711,10 +3712,7 @@ pub unsafe fn instr_D9_2_reg(r: i32) { #[no_mangle] pub unsafe fn instr_D9_3_mem(addr: i32) { fpu_fstm32p(addr); } #[no_mangle] -pub unsafe fn instr_D9_3_reg(r: i32) { - dbg_log!("fstp1"); - trigger_ud(); -} +pub unsafe fn instr_D9_3_reg(r: i32) { fpu_fstp(r) } #[no_mangle] pub unsafe fn instr_D9_4_mem(addr: i32) { fpu_fldenv(addr); } #[no_mangle] @@ -3783,10 +3781,18 @@ pub unsafe fn instr_D9_6_reg(r: i32) { match r { 0 => { // f2xm1 - fpu_write_st(*fpu_stack_ptr as i32, pow(2.0, st0) - 1.0) + let mut r = pow(2.0, st0) - 1.0; + if r == -1.0 { + // Intel ... + r = -3.475818901301751e+184 + } + fpu_write_st(*fpu_stack_ptr as i32, r) }, 1 => { // fyl2x + if st0 < 0.0 { + fpu_invalid_arithmetic(); + } fpu_write_st( *fpu_stack_ptr as i32 + 1 & 7, fpu_get_sti(1) * st0.ln() / M_LN2, @@ -3795,9 +3801,15 @@ pub unsafe fn instr_D9_6_reg(r: i32) { }, 2 => { // fptan - fpu_write_st(*fpu_stack_ptr as i32, st0.tan()); - // no bug: push constant 1 - fpu_push(1.0); + if pow(-2.0, 63.0) < st0 && st0 < pow(2.0, 63.0) { + fpu_write_st(*fpu_stack_ptr as i32, st0.tan()); + // no bug: push constant 1 + fpu_push(1.0); + *fpu_status_word &= !FPU_C2; + } + else { + *fpu_status_word |= FPU_C2; + } }, 3 => { // fpatan @@ -3809,7 +3821,7 @@ pub unsafe fn instr_D9_6_reg(r: i32) { }, 5 => { // fprem1 - fpu_write_st(*fpu_stack_ptr as i32, fmod(st0, fpu_get_sti(1))); + fpu_fprem(true); }, 6 => { // fdecstp @@ -3833,7 +3845,8 @@ pub unsafe fn instr_D9_7_reg(r: i32) { let st0: f64 = fpu_get_st0(); match r { 0 => { - fpu_fprem(); + // fprem + fpu_fprem(false); }, 1 => { // fyl2xp1: y * log2(x+1) and pop @@ -3841,10 +3854,22 @@ pub unsafe fn instr_D9_7_reg(r: i32) { fpu_write_st(*fpu_stack_ptr as i32 + 1 & 7, y); fpu_pop(); }, - 2 => fpu_write_st(*fpu_stack_ptr as i32, st0.sqrt()), + 2 => { + if st0 < 0.0 { + fpu_invalid_arithmetic(); + } + fpu_write_st(*fpu_stack_ptr as i32, st0.sqrt()) + }, 3 => { - fpu_write_st(*fpu_stack_ptr as i32, st0.sin()); - fpu_push(st0.cos()); + // fsincos + if pow(-2.0, 63.0) < st0 && st0 < pow(2.0, 63.0) { + fpu_write_st(*fpu_stack_ptr as i32, st0.sin()); + fpu_push(st0.cos()); + *fpu_status_word &= !FPU_C2; + } + else { + *fpu_status_word |= FPU_C2; + } }, 4 => { // frndint @@ -3855,8 +3880,24 @@ pub unsafe fn instr_D9_7_reg(r: i32) { let y = st0 * pow(2.0, trunc(fpu_get_sti(1))); fpu_write_st(*fpu_stack_ptr as i32, y); }, - 6 => fpu_write_st(*fpu_stack_ptr as i32, st0.sin()), - 7 => fpu_write_st(*fpu_stack_ptr as i32, st0.cos()), + 6 => { + if pow(-2.0, 63.0) < st0 && st0 < pow(2.0, 63.0) { + fpu_write_st(*fpu_stack_ptr as i32, st0.sin()); + *fpu_status_word &= !FPU_C2; + } + else { + *fpu_status_word |= FPU_C2; + } + }, + 7 => { + if pow(-2.0, 63.0) < st0 && st0 < pow(2.0, 63.0) { + fpu_write_st(*fpu_stack_ptr as i32, st0.cos()); + *fpu_status_word &= !FPU_C2; + } + else { + *fpu_status_word |= FPU_C2; + } + }, _ => { dbg_assert!(false); }, @@ -3920,7 +3961,10 @@ pub unsafe fn instr_DA_7_reg(r: i32) { trigger_ud(); } #[no_mangle] pub unsafe fn instr_DB_0_mem(addr: i32) { fpu_fldm32(addr); } #[no_mangle] -pub unsafe fn instr_DB_1_mem(addr: i32) { trigger_ud(); } +pub unsafe fn instr_DB_1_mem(addr: i32) { + dbg_log!("fisttp"); + fpu_unimpl(); +} #[no_mangle] pub unsafe fn instr_DB_2_mem(addr: i32) { fpu_fistm32(addr); } #[no_mangle] @@ -3946,8 +3990,8 @@ pub unsafe fn instr_DB_4_reg(r: i32) { if r == 3 { fpu_finit(); } - else if r == 4 || r == 1 { - // fsetpm and fdisi; treated as nop + else if r == 4 || r == 1 || r == 0 { + // fsetpm, fdisi, fneni; treated as nop } else if r == 2 { fpu_fclex(); @@ -3999,7 +4043,7 @@ pub unsafe fn instr_DD_0_mem(addr: i32) { fpu_fldm64(addr); } #[no_mangle] pub unsafe fn instr_DD_1_mem(addr: i32) { dbg_log!("fisttp"); - trigger_ud(); + fpu_unimpl(); } #[no_mangle] pub unsafe fn instr_DD_2_mem(addr: i32) { fpu_fstm64(addr); } @@ -4019,7 +4063,7 @@ pub unsafe fn instr_DD_7_mem(addr: i32) { fpu_fnstsw_mem(addr); } #[no_mangle] pub unsafe fn instr_DD_0_reg(r: i32) { fpu_ffree(r); } #[no_mangle] -pub unsafe fn instr_DD_1_reg(r: i32) { trigger_ud(); } +pub unsafe fn instr_DD_1_reg(r: i32) { fpu_fxch(r) } #[no_mangle] pub unsafe fn instr_DD_2_reg(r: i32) { fpu_fst(r); } #[no_mangle] @@ -4081,8 +4125,13 @@ pub unsafe fn instr_DE_2_reg(r: i32) { } #[no_mangle] pub unsafe fn instr_DE_3_reg(r: i32) { - fpu_fcomp(fpu_get_sti(r)); - fpu_pop(); + if r == 1 { + fpu_fcomp(fpu_get_sti(r)); + fpu_pop(); + } + else { + trigger_ud(); + } } #[no_mangle] pub unsafe fn instr_DE_4_reg(r: i32) { @@ -4110,8 +4159,8 @@ pub unsafe fn instr_DF_0_mem(addr: i32) { } #[no_mangle] pub unsafe fn instr_DF_1_mem(addr: i32) { - dbg_log!("df/fisttp"); - trigger_ud(); + dbg_log!("fisttp"); + fpu_unimpl(); } #[no_mangle] pub unsafe fn instr_DF_2_mem(addr: i32) { fpu_fistm16(addr); } @@ -4120,25 +4169,29 @@ pub unsafe fn instr_DF_3_mem(addr: i32) { fpu_fistm16p(addr); } #[no_mangle] pub unsafe fn instr_DF_4_mem(addr: i32) { dbg_log!("fbld"); - trigger_ud(); + fpu_unimpl(); } #[no_mangle] pub unsafe fn instr_DF_5_mem(addr: i32) { fpu_fildm64(addr); } #[no_mangle] pub unsafe fn instr_DF_6_mem(addr: i32) { dbg_log!("fbstp"); - trigger_ud(); + fpu_unimpl(); } #[no_mangle] pub unsafe fn instr_DF_7_mem(addr: i32) { fpu_fistm64p(addr); } #[no_mangle] -pub unsafe fn instr_DF_0_reg(r: i32) { trigger_ud(); } + +pub unsafe fn instr_DF_0_reg(r: i32) { + fpu_ffree(r); + fpu_pop(); +} #[no_mangle] -pub unsafe fn instr_DF_1_reg(r: i32) { trigger_ud(); } +pub unsafe fn instr_DF_1_reg(r: i32) { fpu_fxch(r) } #[no_mangle] -pub unsafe fn instr_DF_2_reg(r: i32) { trigger_ud(); } +pub unsafe fn instr_DF_2_reg(r: i32) { fpu_fstp(r); } #[no_mangle] -pub unsafe fn instr_DF_3_reg(r: i32) { trigger_ud(); } +pub unsafe fn instr_DF_3_reg(r: i32) { fpu_fstp(r); } #[no_mangle] pub unsafe fn instr_DF_4_reg(r: i32) { if r == 0 { @@ -4154,6 +4207,7 @@ pub unsafe fn instr_DF_5_reg(r: i32) { fpu_fucomip(r); } pub unsafe fn instr_DF_6_reg(r: i32) { fpu_fcomip(r); } #[no_mangle] pub unsafe fn instr_DF_7_reg(r: i32) { trigger_ud(); } + #[no_mangle] pub unsafe fn instr16_E0(imm8s: i32) { loopne16(imm8s); } #[no_mangle] From 05296b05864152e55191bbf2d954034a1eaa00da Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 3 Dec 2018 13:42:24 -0600 Subject: [PATCH 1510/2137] Enable fpu instructions in nasm tests --- gen/x86_table.js | 83 ++++++++++++++++++++++--- src/cpu.js | 3 + tests/nasm/create_tests.js | 44 ++++++++----- tests/nasm/gdb-extract-def | 50 ++++++++++++++- tests/nasm/run.js | 122 +++++++++++++++++++++++++++++++------ 5 files changed, 260 insertions(+), 42 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 51f1bd88..d72c8e0c 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -273,6 +273,78 @@ const encodings = [ // XXX: Temporary block boundary { opcode: 0xD7, skip: 1, block_boundary: 1, }, + { opcode: 0xD8, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD8, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD8, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD8, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD8, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD8, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD8, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD8, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, }, + + { opcode: 0xD9, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD9, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD9, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD9, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD9, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // fldenv (only memory). TODO: Make reg variant non-block-boundary + { opcode: 0xD9, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD9, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, skip: 1, }, // fstenv (mem), fprem (reg) + { opcode: 0xD9, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, only_mem: 1, }, // fprem + + { opcode: 0xDA, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDA, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDA, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDA, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDA, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDA, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDA, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDA, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, }, + + { opcode: 0xDB, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDB, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // unimplemented: fisttp (sse3) + { opcode: 0xDB, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDB, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDB, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDB, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDB, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDB, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, }, + + { opcode: 0xDC, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDC, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDC, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDC, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDC, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDC, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDC, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDC, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, }, + + { opcode: 0xDD, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDD, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // XXX: Test should fail + { opcode: 0xDD, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDD, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDD, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // frstor + { opcode: 0xDD, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDD, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // fsave + { opcode: 0xDD, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, }, + + { opcode: 0xDE, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDE, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDE, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDE, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDE, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDE, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDE, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDE, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, }, + + { opcode: 0xDF, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1 }, + { opcode: 0xDF, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // unimplemented: fisttp (sse3) + { opcode: 0xDF, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1 }, + { opcode: 0xDF, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1 }, + { opcode: 0xDF, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // mem exists, but not implemented + { opcode: 0xDF, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDF, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // mem exists, but not implemented + { opcode: 0xDF, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, }, + // loop, jcxz, etc. // Conditional jumps, but condition code not supported by code generator // (these are never generated by modern compilers) @@ -722,7 +794,7 @@ const encodings = [ { sse: 1, opcode: 0x660F75, e: 1, }, { sse: 1, opcode: 0x0F76, e: 1, }, { sse: 1, opcode: 0x660F76, e: 1, }, - { sse: 1, opcode: 0x0F77 }, + { sse: 1, opcode: 0x0F77, skip: 1 }, // emms (skip as it breaks gdb printing of float registers) // vmx instructions { opcode: 0x0F78, skip: 1, block_boundary: 1, }, @@ -892,15 +964,6 @@ for(let i = 0; i < 8; i++) { opcode: 0xD1, os: 1, e: 1, fixed_g: i, mask_flags: af, custom: 1, }, { opcode: 0xD2, e: 1, fixed_g: i, mask_flags: of | af, }, { opcode: 0xD3, os: 1, e: 1, fixed_g: i, mask_flags: of | af, custom: 1, }, - - { opcode: 0xD8, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, }, - { opcode: 0xD9, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, }, - { opcode: 0xDA, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, }, - { opcode: 0xDB, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, }, - { opcode: 0xDC, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, }, - { opcode: 0xDD, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, }, - { opcode: 0xDE, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, }, - { opcode: 0xDF, e: 1, fixed_g: i, skip: 1, task_switch_test: 1, }, ]); } diff --git a/src/cpu.js b/src/cpu.js index be6a51dd..087934b5 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -290,6 +290,9 @@ CPU.prototype.wasm_patch = function(wm) this.set_stack_reg = get_import("set_stack_reg"); + this.fpu_load_tag_word = get_import("fpu_load_tag_word"); + this.fpu_load_status_word = get_import("fpu_load_status_word"); + this.translate_address_read = get_import("translate_address_read_js"); this.translate_address_system_read = get_import("translate_address_system_read_js"); this.translate_address_system_write = get_import("translate_address_system_write_js"); diff --git a/tests/nasm/create_tests.js b/tests/nasm/create_tests.js index ffc7221b..a70a5bbd 100755 --- a/tests/nasm/create_tests.js +++ b/tests/nasm/create_tests.js @@ -188,7 +188,7 @@ function create_nasm(op, config) codes.push("mov " + reg + ", " + rand); } - if(true) // generate random mmx registers + if(!op.is_fpu) // generate random mmx registers { codes.push("sub esp, 8"); for(let i = 0; i < 8; i++) @@ -199,6 +199,25 @@ function create_nasm(op, config) } codes.push("add esp, 8"); } + else // generate random fpu registers + { + codes.push("finit"); + codes.push("sub esp, 8"); + + for(let i = 0; i < 8; i++) + { + codes.push("mov dword [esp], " + op_rand.next()); + codes.push("mov dword [esp + 4], " + op_rand.next()); + codes.push("fld qword [esp]"); + } + + for(let i = 0; i < 4; i++) // half full stack + { + codes.push("fstp qword [esp]"); + } + + codes.push("add esp, 8"); + } if(true) // generate random xmm registers { @@ -294,24 +313,21 @@ function create_nasm(op, config) g = op.fixed_g; } - let e; - let sib; - if(config.mem) { - e = 0x04; // [esp] - sib = 0x24; + const e = 0x04; // [esp] + const sib = 0x24; + + codes.push("db " + (e | g << 3)); + codes.push("db " + sib); } else // op.only_mem { - e = 0xc2; // edx - sib = ""; - } - - codes.push("db " + (e | g << 3)); - if(e < 0xC0) - { - codes.push("db " + sib); + const es = op.is_fpu ? [0, 1, 2, 3, 4, 5, 6, 7] : [ + 2 // edx + ]; + const modrm_bytes = es.map(e => "db " + (0xC0 | g << 3 | e)); + codes.push(modrm_bytes); } } } diff --git a/tests/nasm/gdb-extract-def b/tests/nasm/gdb-extract-def index 80adb895..1e17896b 100644 --- a/tests/nasm/gdb-extract-def +++ b/tests/nasm/gdb-extract-def @@ -25,6 +25,52 @@ define extract-state printf " %d,\n", $ebp printf " %d,\n", $esi printf " %d,\n", $edi + + printf " \n" + + # For fpu registers, check the tag register first. If the tag index is + # invalid and you try to access to corresponding register, gdb exits with an + # error. + if ($ftag & (3 << 0)) != (2 << 0) + printf " %.100e,\n", $st0 + else + printf " \"invalid\"," + end + if ($ftag & (3 << 2)) != (2 << 2) + printf " %.100e,\n", $st1 + else + printf " \"invalid\"," + end + if ($ftag & (3 << 4)) != (2 << 4) + printf " %.100e,\n", $st2 + else + printf " \"invalid\"," + end + if ($ftag & (3 << 6)) != (2 << 6) + printf " %.100e,\n", $st3 + else + printf " \"invalid\"," + end + if ($ftag & (3 << 8)) != (2 << 8) + printf " %.100e,\n", $st4 + else + printf " \"invalid\"," + end + if ($ftag & (3 << 10)) != (2 << 10) + printf " %.100e,\n", $st5 + else + printf " \"invalid\"," + end + if ($ftag & (3 << 12)) != (2 << 12) + printf " %.100e,\n", $st6 + else + printf " \"invalid\"," + end + if ($ftag & (3 << 14)) != (2 << 14) + printf " %.100e,\n", $st7 + else + printf " \"invalid\"," + end printf " \n" printf " %d,\n", $mm0.v2_int32[0] @@ -97,7 +143,9 @@ define extract-state printf " %d,\n", *(int*)($STACK_TOP-4) printf " \n" - printf " %d\n", $eflags + printf " %d,\n", $eflags + printf " %d,\n", $ftag + printf " %d\n", $fstat printf "]\n" printf "---END JSON---\n" diff --git a/tests/nasm/run.js b/tests/nasm/run.js index c16b127d..afa09202 100755 --- a/tests/nasm/run.js +++ b/tests/nasm/run.js @@ -31,7 +31,16 @@ const TERMINATE_MSG = "DONE"; const FORCE_JIT = process.argv.includes("--force-jit"); +// alternative representation for infinity for json +const JSON_POS_INFINITY = "+INFINITY"; +const JSON_NEG_INFINITY = "-INFINITY"; +const JSON_POS_NAN = "+NAN"; +const JSON_NEG_NAN = "-NAN"; + const MASK_ARITH = 1 | 1 << 2 | 1 << 4 | 1 << 6 | 1 << 7 | 1 << 11; +const FPU_TAG_ALL_INVALID = 0xAAAA; +const FPU_STATUS_MASK = 0xFFFF & ~(1 << 9 | 1 << 5 | 1 << 3); // bits that are not correctly implemented by v86 +const FP_COMPARISON_SIGNIFICANT_DIGITS = 7; try { var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86; @@ -43,6 +52,39 @@ catch(e) { process.exit(1); } +function float_equal(x, y) +{ + console.assert(typeof x === "number"); + console.assert(typeof y === "number"); + + if(x === Infinity && y === Infinity || x === -Infinity && y === -Infinity || isNaN(x) && isNaN(y)) + { + return true; + } + + const epsilon = Math.pow(10, -FP_COMPARISON_SIGNIFICANT_DIGITS); + return Math.abs(x - y) < epsilon; +} + +function format_value(v) +{ + if(typeof v === "number") + { + if((v >>> 0) !== v) + { + return String(v); + } + else + { + return "0x" + (v >>> 0).toString(16); + } + } + else + { + return String(v); + } +} + if(cluster.isMaster) { function extract_json(name, fixture_text) @@ -67,7 +109,13 @@ if(cluster.isMaster) throw new Error("Test was killed during execution by gdb: " + name + "\n" + fixture_text); } - const json_regex = /---BEGIN JSON---([\s\[\]\w":\-,]*)---END JSON---/; + fixture_text = fixture_text.toString() + .replace(/-inf\b/g, JSON.stringify(JSON_NEG_INFINITY)) + .replace(/\binf\b/g, JSON.stringify(JSON_POS_INFINITY)) + .replace(/-nan\b/g, JSON.stringify(JSON_NEG_NAN)) + .replace(/\bnan\b/g, JSON.stringify(JSON_POS_NAN)); + + const json_regex = /---BEGIN JSON---([\s\[\]\.\+\w":\-,]*)---END JSON---/; const regex_match = json_regex.exec(fixture_text); if (!regex_match || regex_match.length < 2) { throw new Error("Could not find JSON in fixture text: " + fixture_text + "\nTest: " + name); @@ -180,15 +228,9 @@ if(cluster.isMaster) console.error("\n[-] %s:", test_failure.img_name); 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)); + console.error("\tActual: " + failure.actual); + console.error("\tExpected: " + failure.expected); }); }); process.exit(1); @@ -300,23 +342,36 @@ else { emulator.stop(); var cpu = emulator.v86.cpu; - const filename = TEST_DIR + current_test.img_name; + const evaluated_fpu_regs = new Float64Array(8).map((_, i) => cpu.fpu_st[i + cpu.fpu_stack_ptr[0] & 7]); const evaluated_mmxs = cpu.reg_mmxs; const evaluated_xmms = cpu.reg_xmm32s; - const esp = cpu.reg32s[4]; const evaluated_memory = new Int32Array(cpu.mem8.slice(0x120000 - 16 * 4, 0x120000).buffer); + const evaluated_fpu_tag = cpu.fpu_load_tag_word(); + const evaluated_fpu_status = cpu.fpu_load_status_word() & FPU_STATUS_MASK; + let individual_failures = []; console.assert(current_test.fixture.array || current_test.fixture.exception); + const FLOAT_TRANSLATION = { + [JSON_POS_INFINITY]: Infinity, + [JSON_NEG_INFINITY]: -Infinity, + [JSON_POS_NAN]: NaN, + [JSON_NEG_NAN]: NaN, // XXX: Ignore sign of NaN + }; + if(current_test.fixture.array) { let offset = 0; const expected_reg32s = current_test.fixture.array.slice(offset, offset += 8); + const expected_fpu_regs = + current_test.fixture.array.slice(offset, offset += 8) .map(x => x in FLOAT_TRANSLATION ? FLOAT_TRANSLATION[x] : x); const expected_mmx_registers = current_test.fixture.array.slice(offset, offset += 16); const expected_xmm_registers = current_test.fixture.array.slice(offset, offset += 32); const expected_memory = current_test.fixture.array.slice(offset, offset += 16); - const expected_eflags = current_test.fixture.array[offset] & MASK_ARITH; + const expected_eflags = current_test.fixture.array[offset++] & MASK_ARITH; + const fpu_tag = current_test.fixture.array[offset++]; + const fpu_status = current_test.fixture.array[offset++] & FPU_STATUS_MASK; for (let i = 0; i < cpu.reg32s.length; i++) { let reg = cpu.reg32s[i]; @@ -329,15 +384,40 @@ else { } } - for (let i = 0; i < evaluated_mmxs.length; i++) { - if (evaluated_mmxs[i] !== expected_mmx_registers[i]) { + if(fpu_tag !== FPU_TAG_ALL_INVALID) + { + for (let i = 0; i < evaluated_fpu_regs.length; i++) { + if (expected_fpu_regs[i] !== "invalid" && + !float_equal(evaluated_fpu_regs[i], expected_fpu_regs[i])) { + individual_failures.push({ + name: "st" + i, + expected: expected_fpu_regs[i], + actual: evaluated_fpu_regs[i], + }); + } + } + + if(fpu_status !== evaluated_fpu_status) + { individual_failures.push({ - name: "mm" + (i >> 1) + ".int32[" + (i & 1) + "] (cpu.reg_mmx[" + i + "])", - expected: expected_mmx_registers[i], - actual: evaluated_mmxs[i], + name: "fpu status word", + expected: fpu_status, + actual: evaluated_fpu_status, }); } } + else + { + for (let i = 0; i < evaluated_mmxs.length; i++) { + if (evaluated_mmxs[i] !== expected_mmx_registers[i]) { + individual_failures.push({ + name: "mm" + (i >> 1) + ".int32[" + (i & 1) + "] (cpu.reg_mmx[" + i + "])", + expected: expected_mmx_registers[i], + actual: evaluated_mmxs[i], + }); + } + } + } for (let i = 0; i < evaluated_xmms.length; i++) { if (evaluated_xmms[i] !== expected_xmm_registers[i]) { @@ -379,6 +459,14 @@ else { }); } + individual_failures = individual_failures.map(({ name, actual, expected }) => { + return { + name, + actual: format_value(actual), + expected: format_value(expected), + }; + }); + recorded_exceptions = []; if (individual_failures.length > 0) { From 66c96bd1b1cfaa41088c8010c3d35694deeed5ac Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 3 Dec 2018 15:46:55 -0600 Subject: [PATCH 1511/2137] Clean up old C code --- src/rust/cpu2/instructions.rs | 90 +++++++---------------------------- 1 file changed, 18 insertions(+), 72 deletions(-) diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index ae94aaf1..70371499 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -3605,95 +3605,41 @@ pub unsafe fn instr32_F2AF() { scasd_rep(PREFIX_F2); } pub unsafe fn instr32_F3AF() { scasd_rep(PREFIX_F3); } #[no_mangle] -pub unsafe fn instr_D8_0_mem(addr: i32) { - let ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); - fpu_fadd(0, ____0); -} +pub unsafe fn instr_D8_0_mem(addr: i32) { fpu_fadd(0, return_on_pagefault!(fpu_load_m32(addr))); } #[no_mangle] -pub unsafe fn instr_D8_0_reg(r: i32) { - let ____0: f64 = fpu_get_sti(r); - fpu_fadd(0, ____0); -} +pub unsafe fn instr_D8_0_reg(r: i32) { fpu_fadd(0, fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_D8_1_mem(addr: i32) { - let ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); - fpu_fmul(0, ____0); -} +pub unsafe fn instr_D8_1_mem(addr: i32) { fpu_fmul(0, return_on_pagefault!(fpu_load_m32(addr))); } #[no_mangle] -pub unsafe fn instr_D8_1_reg(r: i32) { - let ____0: f64 = fpu_get_sti(r); - fpu_fmul(0, ____0); -} +pub unsafe fn instr_D8_1_reg(r: i32) { fpu_fmul(0, fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_D8_2_mem(addr: i32) { - let ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); - fpu_fcom(____0); -} +pub unsafe fn instr_D8_2_mem(addr: i32) { fpu_fcom(return_on_pagefault!(fpu_load_m32(addr))); } #[no_mangle] -pub unsafe fn instr_D8_2_reg(r: i32) { - let ____0: f64 = fpu_get_sti(r); - fpu_fcom(____0); -} +pub unsafe fn instr_D8_2_reg(r: i32) { fpu_fcom(fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_D8_3_mem(addr: i32) { - let ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); - fpu_fcomp(____0); -} +pub unsafe fn instr_D8_3_mem(addr: i32) { fpu_fcomp(return_on_pagefault!(fpu_load_m32(addr))); } #[no_mangle] -pub unsafe fn instr_D8_3_reg(r: i32) { - let ____0: f64 = fpu_get_sti(r); - fpu_fcomp(____0); -} +pub unsafe fn instr_D8_3_reg(r: i32) { fpu_fcomp(fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_D8_4_mem(addr: i32) { - let ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); - fpu_fsub(0, ____0); -} +pub unsafe fn instr_D8_4_mem(addr: i32) { fpu_fsub(0, return_on_pagefault!(fpu_load_m32(addr))); } #[no_mangle] -pub unsafe fn instr_D8_4_reg(r: i32) { - let ____0: f64 = fpu_get_sti(r); - fpu_fsub(0, ____0); -} +pub unsafe fn instr_D8_4_reg(r: i32) { fpu_fsub(0, fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_D8_5_mem(addr: i32) { - let ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); - fpu_fsubr(0, ____0); -} +pub unsafe fn instr_D8_5_mem(addr: i32) { fpu_fsubr(0, return_on_pagefault!(fpu_load_m32(addr))); } #[no_mangle] -pub unsafe fn instr_D8_5_reg(r: i32) { - let ____0: f64 = fpu_get_sti(r); - fpu_fsubr(0, ____0); -} +pub unsafe fn instr_D8_5_reg(r: i32) { fpu_fsubr(0, fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_D8_6_mem(addr: i32) { - let ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); - fpu_fdiv(0, ____0); -} +pub unsafe fn instr_D8_6_mem(addr: i32) { fpu_fdiv(0, return_on_pagefault!(fpu_load_m32(addr))); } #[no_mangle] -pub unsafe fn instr_D8_6_reg(r: i32) { - let ____0: f64 = fpu_get_sti(r); - fpu_fdiv(0, ____0); -} +pub unsafe fn instr_D8_6_reg(r: i32) { fpu_fdiv(0, fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_D8_7_mem(addr: i32) { - let ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); - fpu_fdivr(0, ____0); -} +pub unsafe fn instr_D8_7_mem(addr: i32) { fpu_fdivr(0, return_on_pagefault!(fpu_load_m32(addr))); } #[no_mangle] -pub unsafe fn instr_D8_7_reg(r: i32) { - let ____0: f64 = fpu_get_sti(r); - fpu_fdivr(0, ____0); -} +pub unsafe fn instr_D8_7_reg(r: i32) { fpu_fdivr(0, fpu_get_sti(r)); } #[no_mangle] -pub unsafe fn instr_D9_0_mem(addr: i32) { - let ____0: f64 = return_on_pagefault!(fpu_load_m32(addr)); - fpu_push(____0); -} +pub unsafe fn instr_D9_0_mem(addr: i32) { fpu_push(return_on_pagefault!(fpu_load_m32(addr))); } #[no_mangle] -pub unsafe fn instr_D9_0_reg(r: i32) { - let ____0: f64 = fpu_get_sti(r); - fpu_push(____0); -} +pub unsafe fn instr_D9_0_reg(r: i32) { fpu_push(fpu_get_sti(r)); } #[no_mangle] pub unsafe fn instr_D9_1_mem(addr: i32) { dbg_log!("d9/1"); From ec059a9f274fbcc1c8e35c8dd80ae6b5bf66ffd8 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 3 Dec 2018 16:00:05 -0600 Subject: [PATCH 1512/2137] Codegen for fpu instructions (D8 group) --- gen/generate_analyzer.js | 2 +- gen/generate_jit.js | 2 +- gen/x86_table.js | 16 ++++---- src/rust/codegen.rs | 29 ++++++++++++++ src/rust/jit_instructions.rs | 67 +++++++++++++++++++++++++++++++++ src/rust/wasmgen/module_init.rs | 29 +++++++++++++- src/rust/wasmgen/wasm_util.rs | 8 ++++ 7 files changed, 142 insertions(+), 11 deletions(-) diff --git a/gen/generate_analyzer.js b/gen/generate_analyzer.js index 95deb0b7..0a1e9200 100755 --- a/gen/generate_analyzer.js +++ b/gen/generate_analyzer.js @@ -217,7 +217,7 @@ function gen_instruction_body_after_fixed_g(encoding, size) const imm_read = gen_read_imm_call(encoding, size); const instruction_postfix = []; - if(encoding.block_boundary && !encoding.jump_offset_imm || (!encoding.custom && encoding.e) || encoding.sse || encoding.task_switch_test) + if(encoding.block_boundary && !encoding.jump_offset_imm || (!encoding.custom && encoding.e) || encoding.sse) { instruction_postfix.push("analysis.ty = ::analysis::AnalysisType::BlockBoundary;"); } diff --git a/gen/generate_jit.js b/gen/generate_jit.js index 6b3f4669..7f649733 100755 --- a/gen/generate_jit.js +++ b/gen/generate_jit.js @@ -216,7 +216,7 @@ function gen_instruction_body_after_fixed_g(encoding, size) { const instruction_postfix = []; - if(encoding.block_boundary || (!encoding.custom && encoding.e) || encoding.sse || encoding.task_switch_test) + if(encoding.block_boundary || (!encoding.custom && encoding.e) || encoding.sse) { instruction_postfix.push("*instr_flags |= ::jit::JIT_INSTR_BLOCK_BOUNDARY_FLAG;"); } diff --git a/gen/x86_table.js b/gen/x86_table.js index d72c8e0c..496ca868 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -273,14 +273,14 @@ const encodings = [ // XXX: Temporary block boundary { opcode: 0xD7, skip: 1, block_boundary: 1, }, - { opcode: 0xD8, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xD8, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xD8, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xD8, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xD8, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xD8, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xD8, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xD8, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD8, e: 1, fixed_g: 0, custom: 1, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD8, e: 1, fixed_g: 1, custom: 1, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD8, e: 1, fixed_g: 2, custom: 1, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD8, e: 1, fixed_g: 3, custom: 1, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD8, e: 1, fixed_g: 4, custom: 1, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD8, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD8, e: 1, fixed_g: 6, custom: 1, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD8, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, }, diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 6f9aa5af..7c7d3cc8 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -120,6 +120,12 @@ pub fn gen_call_fn1_ret(builder: &mut WasmBuilder, name: &str) { builder.instruction_body.call_fn(fn_idx); } +pub fn gen_call_fn1_ret_f64(builder: &mut WasmBuilder, name: &str) { + // generates: fn( _ ) where _ must be left on the stack before calling this, and fn returns a value + let fn_idx = builder.get_fn_idx(name, module_init::FN1_RET_F64_TYPE_INDEX); + builder.instruction_body.call_fn(fn_idx); +} + pub fn gen_fn2_const(builder: &mut WasmBuilder, name: &str, arg0: u32, arg1: u32) { let fn_idx = builder.get_fn_idx(name, module_init::FN2_TYPE_INDEX); builder.instruction_body.const_i32(arg0 as i32); @@ -139,6 +145,18 @@ pub fn gen_call_fn2(builder: &mut WasmBuilder, name: &str) { builder.instruction_body.call_fn(fn_idx); } +pub fn gen_call_fn2_i32_f64(builder: &mut WasmBuilder, name: &str) { + // generates: fn( _, _ ) where _ must be left on the stack before calling this + let fn_idx = builder.get_fn_idx(name, module_init::FN2_I32_F64_TYPE_INDEX); + builder.instruction_body.call_fn(fn_idx); +} + +pub fn gen_call_fn1_f64(builder: &mut WasmBuilder, name: &str) { + // generates: fn( _, _ ) where _ must be left on the stack before calling this + let fn_idx = builder.get_fn_idx(name, module_init::FN1_F64_TYPE_INDEX); + builder.instruction_body.call_fn(fn_idx); +} + pub fn gen_call_fn2_ret(builder: &mut WasmBuilder, name: &str) { // generates: fn( _, _ ) where _ must be left on the stack before calling this, and fn returns a value let fn_idx = builder.get_fn_idx(name, module_init::FN2_RET_TYPE_INDEX); @@ -962,6 +980,17 @@ pub fn gen_safe_read_write( ctx.builder.free_local(entry_local); } +pub fn gen_fpu_get_sti(ctx: &mut JitContext, i: u32) { + ctx.builder.instruction_body.const_i32(i as i32); + gen_call_fn1_ret_f64(ctx.builder, "fpu_get_sti"); +} + +pub fn gen_fpu_load_m32(ctx: &mut JitContext) { + gen_safe_read32(ctx); + ctx.builder.instruction_body.reinterpret_i32_as_f32(); + ctx.builder.instruction_body.promote_f32_to_f64(); +} + pub fn gen_profiler_stat_increment(builder: &mut WasmBuilder, stat: profiler::stat) { let addr = unsafe { profiler::stat_array.as_mut_ptr().offset(stat as isize) } as u32; gen_increment_variable(builder, addr, 1) diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index f42621dc..027d8841 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1850,6 +1850,73 @@ define_instruction_read_write_mem32!( cl ); +fn instr_group_D8_mem_jit(ctx: &mut JitContext, modrm_byte: u8, op: &str) { + ctx.builder.instruction_body.const_i32(0); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_fpu_load_m32(ctx); + codegen::gen_call_fn2_i32_f64(ctx.builder, op) +} +fn instr_group_D8_reg_jit(ctx: &mut JitContext, r: u32, op: &str) { + ctx.builder.instruction_body.const_i32(0); + codegen::gen_fpu_get_sti(ctx, r); + codegen::gen_call_fn2_i32_f64(ctx.builder, op) +} + +pub fn instr_D8_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + instr_group_D8_mem_jit(ctx, modrm_byte, "fpu_fadd") +} +pub fn instr_D8_0_reg_jit(ctx: &mut JitContext, r: u32) { + instr_group_D8_reg_jit(ctx, r, "fpu_fadd") +} +pub fn instr_D8_1_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + instr_group_D8_mem_jit(ctx, modrm_byte, "fpu_fmul") +} +pub fn instr_D8_1_reg_jit(ctx: &mut JitContext, r: u32) { + instr_group_D8_reg_jit(ctx, r, "fpu_fmul") +} +pub fn instr_D8_2_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_fpu_load_m32(ctx); + codegen::gen_call_fn1_f64(ctx.builder, "fpu_fcom") +} +pub fn instr_D8_2_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_fpu_get_sti(ctx, r); + codegen::gen_call_fn1_f64(ctx.builder, "fpu_fcom") +} +pub fn instr_D8_3_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_fpu_load_m32(ctx); + codegen::gen_call_fn1_f64(ctx.builder, "fpu_fcomp") +} +pub fn instr_D8_3_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_fpu_get_sti(ctx, r); + codegen::gen_call_fn1_f64(ctx.builder, "fpu_fcomp") +} +pub fn instr_D8_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + instr_group_D8_mem_jit(ctx, modrm_byte, "fpu_fsub") +} +pub fn instr_D8_4_reg_jit(ctx: &mut JitContext, r: u32) { + instr_group_D8_reg_jit(ctx, r, "fpu_fsub") +} +pub fn instr_D8_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + instr_group_D8_mem_jit(ctx, modrm_byte, "fpu_fsubr") +} +pub fn instr_D8_5_reg_jit(ctx: &mut JitContext, r: u32) { + instr_group_D8_reg_jit(ctx, r, "fpu_fsubr") +} +pub fn instr_D8_6_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + instr_group_D8_mem_jit(ctx, modrm_byte, "fpu_fdiv") +} +pub fn instr_D8_6_reg_jit(ctx: &mut JitContext, r: u32) { + instr_group_D8_reg_jit(ctx, r, "fpu_fdiv") +} +pub fn instr_D8_7_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + instr_group_D8_mem_jit(ctx, modrm_byte, "fpu_fdivr") +} +pub fn instr_D8_7_reg_jit(ctx: &mut JitContext, r: u32) { + instr_group_D8_reg_jit(ctx, r, "fpu_fdivr") +} + pub fn instr16_EB_jit(ctx: &mut JitContext, imm8: u32) { codegen::gen_jmp_rel16(ctx.builder, imm8 as u16); // dbg_assert(is_asize_32() || get_real_eip() < 0x10000); diff --git a/src/rust/wasmgen/module_init.rs b/src/rust/wasmgen/module_init.rs index 9530165a..b5f807e6 100644 --- a/src/rust/wasmgen/module_init.rs +++ b/src/rust/wasmgen/module_init.rs @@ -18,7 +18,14 @@ pub const FN1_RET_TYPE_INDEX: u8 = 5; #[allow(dead_code)] pub const FN2_RET_TYPE_INDEX: u8 = 6; -pub const NR_FN_TYPE_INDEXES: u8 = 7; +#[allow(dead_code)] +pub const FN1_RET_F64_TYPE_INDEX: u8 = 7; +#[allow(dead_code)] +pub const FN2_I32_F64_TYPE_INDEX: u8 = 8; +#[allow(dead_code)] +pub const FN1_F64_TYPE_INDEX: u8 = 9; + +pub const NR_FN_TYPE_INDEXES: u8 = 10; pub struct WasmBuilder { pub output: Vec, @@ -189,6 +196,26 @@ impl WasmBuilder { self.output.push(1); self.output.push(op::TYPE_I32); + // FN1_RET_F64 + self.output.push(op::TYPE_FUNC); + self.output.push(1); + self.output.push(op::TYPE_I32); + self.output.push(1); + self.output.push(op::TYPE_F64); + + // FN2_I32_F64 + self.output.push(op::TYPE_FUNC); + self.output.push(2); + self.output.push(op::TYPE_I32); + self.output.push(op::TYPE_F64); + self.output.push(0); + + // FN1_F64 + self.output.push(op::TYPE_FUNC); + self.output.push(1); + self.output.push(op::TYPE_F64); + self.output.push(0); + let new_len = self.output.len(); let size = (new_len - 1) - idx_section_size; self.output[idx_section_size] = size.safe_to_u8(); diff --git a/src/rust/wasmgen/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs index 841ddb2f..c45a2eb8 100644 --- a/src/rust/wasmgen/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -39,6 +39,10 @@ pub trait WasmBuf { fn store_unaligned_u16(&mut self, byte_offset: u32); fn store_unaligned_i32(&mut self, byte_offset: u32); + fn reinterpret_i32_as_f32(&mut self); + fn reinterpret_i64_as_f64(&mut self); + fn promote_f32_to_f64(&mut self); + fn shr_u_i32(&mut self); fn shr_s_i32(&mut self); fn eqz_i32(&mut self); @@ -196,6 +200,10 @@ impl WasmBuf for Vec { self.write_leb_u32(byte_offset); } + fn reinterpret_i32_as_f32(&mut self) { self.push(op::OP_F32REINTERPRETI32); } + fn reinterpret_i64_as_f64(&mut self) { self.push(op::OP_F64REINTERPRETI64); } + fn promote_f32_to_f64(&mut self) { self.push(op::OP_F64PROMOTEF32); } + fn shr_u_i32(&mut self) { self.push(op::OP_I32SHRU); } fn shr_s_i32(&mut self) { self.push(op::OP_I32SHRS); } From f6718c3ead7efae0559539177371f5977cb3f5e6 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 4 Dec 2018 15:11:34 -0600 Subject: [PATCH 1513/2137] Fix a few missing local frees --- src/rust/jit.rs | 5 +++++ src/rust/jit_instructions.rs | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 5db5242f..c4ed6086 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -1133,6 +1133,11 @@ fn jit_generate_module( builder.instruction_body.block_end(); // loop + builder.free_local(gen_local_state); + if let Some(local) = gen_local_iteration_counter { + builder.free_local(local); + } + builder.finish(); } diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 027d8841..8e70b289 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -2435,6 +2435,8 @@ macro_rules! define_setcc( ctx.builder.instruction_body.ne_i32(); let value_local = ctx.builder.set_new_local(); codegen::gen_safe_write8(ctx, &address_local, &value_local); + ctx.builder.free_local(address_local); + ctx.builder.free_local(value_local); } pub fn $name_reg(ctx: &mut JitContext, r1: u32, _r2: u32) { From 4c3f8dcde898ca27b037760446c7338e6a609162 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 4 Dec 2018 15:58:16 -0600 Subject: [PATCH 1514/2137] Support for i64 locals --- src/rust/lib.rs | 1 + src/rust/wasmgen/module_init.rs | 102 +++++++++++++++++++++++++++----- src/rust/wasmgen/wasm_util.rs | 8 ++- 3 files changed, 96 insertions(+), 15 deletions(-) diff --git a/src/rust/lib.rs b/src/rust/lib.rs index 230db563..369d132c 100644 --- a/src/rust/lib.rs +++ b/src/rust/lib.rs @@ -1,5 +1,6 @@ #![feature(const_fn)] #![feature(extern_types)] +#![feature(range_contains)] #[cfg(test)] #[macro_use] diff --git a/src/rust/wasmgen/module_init.rs b/src/rust/wasmgen/module_init.rs index b5f807e6..aab2715a 100644 --- a/src/rust/wasmgen/module_init.rs +++ b/src/rust/wasmgen/module_init.rs @@ -27,6 +27,8 @@ pub const FN1_F64_TYPE_INDEX: u8 = 9; pub const NR_FN_TYPE_INDEXES: u8 = 10; +pub const WASM_MODULE_ARGUMENT_COUNT: u8 = 1; + pub struct WasmBuilder { pub output: Vec, pub instruction_body: Vec, @@ -40,7 +42,8 @@ pub struct WasmBuilder { initial_static_size: usize, // size of module after initialization, rest is drained on reset - free_locals: Vec, + free_locals_i32: Vec, + free_locals_i64: Vec, local_count: u8, pub arg_local_initial_state: WasmLocal, } @@ -50,6 +53,11 @@ impl WasmLocal { pub fn idx(&self) -> u8 { self.0 } } +pub struct WasmLocalI64(u8); +impl WasmLocalI64 { + pub fn idx(&self) -> u8 { self.0 } +} + impl WasmBuilder { pub fn new() -> Self { WasmBuilder { @@ -65,8 +73,9 @@ impl WasmBuilder { initial_static_size: 0, - free_locals: Vec::with_capacity(8), - local_count: 1, // for the argument + free_locals_i32: Vec::with_capacity(8), + free_locals_i64: Vec::with_capacity(8), + local_count: 0, arg_local_initial_state: WasmLocal(0), } } @@ -92,7 +101,8 @@ impl WasmBuilder { self.set_import_table_size(2); self.set_import_count(0); self.instruction_body.clear(); - self.free_locals.clear(); + self.free_locals_i32.clear(); + self.free_locals_i64.clear(); self.local_count = 0; } @@ -119,10 +129,42 @@ impl WasmBuilder { self.output.push(0); self.output.push(0); - self.output.push(1); // count of local blocks - dbg_assert!(self.local_count < 128); - self.output.push(self.local_count); - self.output.push(op::TYPE_I32); + dbg_assert!( + self.local_count as usize == self.free_locals_i32.len() + self.free_locals_i64.len(), + "All locals should have been freed" + ); + + let free_locals_i32 = &self.free_locals_i32; + let free_locals_i64 = &self.free_locals_i64; + + let locals = (0..self.local_count).map(|i| { + let local_index = WASM_MODULE_ARGUMENT_COUNT + i; + if free_locals_i64.iter().any(|v| v.idx() == local_index) { + op::TYPE_I64 + } + else { + dbg_assert!(free_locals_i32.iter().any(|v| v.idx() == local_index)); + op::TYPE_I32 + } + }); + let mut groups = vec![]; + for local_type in locals { + if let Some(last) = groups.last_mut() { + let (last_type, last_count) = *last; + if last_type == local_type { + *last = (local_type, last_count + 1); + continue; + } + } + groups.push((local_type, 1)); + } + dbg_assert!(groups.len() < 128); + self.output.push(groups.len().safe_to_u8()); + for (local_type, count) in groups { + dbg_assert!(count < 128); + self.output.push(count); + self.output.push(local_type); + } self.output.append(&mut self.instruction_body); @@ -351,10 +393,10 @@ impl WasmBuilder { #[must_use = "local allocated but not used"] fn alloc_local(&mut self) -> WasmLocal { - match self.free_locals.pop() { + match self.free_locals_i32.pop() { Some(local) => local, None => { - let new_idx = self.local_count; + let new_idx = self.local_count + WASM_MODULE_ARGUMENT_COUNT; self.local_count += 1; WasmLocal(new_idx) }, @@ -362,8 +404,11 @@ impl WasmBuilder { } pub fn free_local(&mut self, local: WasmLocal) { - dbg_assert!(local.0 < self.local_count); - self.free_locals.push(local) + dbg_assert!( + (WASM_MODULE_ARGUMENT_COUNT..self.local_count + WASM_MODULE_ARGUMENT_COUNT) + .contains(&local.0) + ); + self.free_locals_i32.push(local) } #[must_use = "local allocated but not used"] @@ -381,6 +426,34 @@ impl WasmBuilder { self.instruction_body.push(local.idx()); local } + + #[must_use = "local allocated but not used"] + fn alloc_local_i64(&mut self) -> WasmLocalI64 { + match self.free_locals_i64.pop() { + Some(local) => local, + None => { + let new_idx = self.local_count + WASM_MODULE_ARGUMENT_COUNT; + self.local_count += 1; + WasmLocalI64(new_idx) + }, + } + } + + pub fn free_local_i64(&mut self, local: WasmLocalI64) { + dbg_assert!( + (WASM_MODULE_ARGUMENT_COUNT..self.local_count + WASM_MODULE_ARGUMENT_COUNT) + .contains(&local.0) + ); + self.free_locals_i64.push(local) + } + + #[must_use = "local allocated but not used"] + pub fn set_new_local_i64(&mut self) -> WasmLocalI64 { + let local = self.alloc_local_i64(); + self.instruction_body.push(op::OP_SETLOCAL); + self.instruction_body.push(local.idx()); + local + } } #[cfg(test)] @@ -410,7 +483,8 @@ mod tests { let bar_index = m.get_fn_idx("bar", FN0_TYPE_INDEX); m.instruction_body.call_fn(bar_index); - let _ = m.alloc_local(); // for ensuring that reset clears previous locals + let local0 = m.alloc_local(); // for ensuring that reset clears previous locals + m.free_local(local0); m.finish(); m.reset(); @@ -434,7 +508,7 @@ mod tests { m.free_local(local1); let local3 = m.alloc_local(); - assert_eq!(local3.idx(), 0); + assert_eq!(local3.idx(), WASM_MODULE_ARGUMENT_COUNT); m.free_local(local2); m.free_local(local3); diff --git a/src/rust/wasmgen/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs index c45a2eb8..4b576d24 100644 --- a/src/rust/wasmgen/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -1,5 +1,5 @@ use leb::{write_fixed_leb16_at_idx, write_fixed_leb32_at_idx, write_leb_i32, write_leb_u32}; -use wasmgen::module_init::WasmLocal; +use wasmgen::module_init::{WasmLocal, WasmLocalI64}; use wasmgen::wasm_opcodes as op; pub trait WasmBuf { @@ -56,6 +56,7 @@ pub trait WasmBuf { fn brtable_and_cases(&mut self, cases_count: u32); fn br(&mut self, depth: u32); fn get_local(&mut self, local: &WasmLocal); + fn get_local_i64(&mut self, local: &WasmLocalI64); fn set_local(&mut self, local: &WasmLocal); fn tee_local(&mut self, local: &WasmLocal); fn unreachable(&mut self); @@ -254,6 +255,11 @@ impl WasmBuf for Vec { self.push(local.idx()); } + fn get_local_i64(&mut self, local: &WasmLocalI64) { + self.push(op::OP_GETLOCAL); + self.push(local.idx()); + } + fn set_local(&mut self, local: &WasmLocal) { self.push(op::OP_SETLOCAL); self.push(local.idx()); From f797ce10c9955fc9b924989737f21b17a3ea1965 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 3 Dec 2018 16:08:19 -0600 Subject: [PATCH 1515/2137] 64-bit operations for gen_safe_{read,write,read_write} --- src/rust/codegen.rs | 46 ++++++++++++++++++++++++++++++--- src/rust/cpu.rs | 11 ++++++++ src/rust/cpu2/cpu.rs | 22 ++++++++++++++++ src/rust/wasmgen/module_init.rs | 12 ++++++++- src/rust/wasmgen/wasm_util.rs | 19 ++++++++++++++ 5 files changed, 105 insertions(+), 5 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 7c7d3cc8..57689fb9 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -126,6 +126,12 @@ pub fn gen_call_fn1_ret_f64(builder: &mut WasmBuilder, name: &str) { builder.instruction_body.call_fn(fn_idx); } +pub fn gen_call_fn1_ret_i64(builder: &mut WasmBuilder, name: &str) { + // generates: fn( _ ) where _ must be left on the stack before calling this, and fn returns a value + let fn_idx = builder.get_fn_idx(name, module_init::FN1_RET_I64_TYPE_INDEX); + builder.instruction_body.call_fn(fn_idx); +} + pub fn gen_fn2_const(builder: &mut WasmBuilder, name: &str, arg0: u32, arg1: u32) { let fn_idx = builder.get_fn_idx(name, module_init::FN2_TYPE_INDEX); builder.instruction_body.const_i32(arg0 as i32); @@ -230,6 +236,7 @@ pub fn gen_set_reg32_r(ctx: &mut JitContext, dest: u32, src: u32) { pub fn gen_safe_read8(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::BYTE) } pub fn gen_safe_read16(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::WORD) } pub fn gen_safe_read32(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::DWORD) } +pub fn gen_safe_read64(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::QWORD) } pub fn gen_safe_write8(ctx: &mut JitContext, address_local: &WasmLocal, value_local: &WasmLocal) { gen_safe_write(ctx, BitSize::BYTE, address_local, value_local) @@ -283,7 +290,7 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { builder.instruction_body.and_i32(); builder .instruction_body - .const_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 }); + .const_i32(0x1000 - bits.bytes() as i32); builder.instruction_body.le_i32(); builder.instruction_body.and_i32(); @@ -291,7 +298,12 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { // Pseudo: // if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]); - builder.instruction_body.if_i32(); + if bits == BitSize::QWORD { + builder.instruction_body.if_i64(); + } + else { + builder.instruction_body.if_i32(); + } if cfg!(feature = "profiler") { gen_profiler_stat_increment(builder, profiler::stat::SAFE_READ_FAST); @@ -319,6 +331,11 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { .instruction_body .load_unaligned_i32_from_stack(unsafe { mem8 } as u32); }, + BitSize::QWORD => { + builder + .instruction_body + .load_unaligned_i64_from_stack(unsafe { mem8 } as u32); + }, } // Pseudo: @@ -362,6 +379,9 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { BitSize::DWORD => { gen_call_fn1_ret(builder, "safe_read32s_slow_jit"); }, + BitSize::QWORD => { + gen_call_fn1_ret_i64(builder, "safe_read64s_slow_jit"); + }, } builder @@ -421,7 +441,7 @@ fn gen_safe_write( builder.instruction_body.and_i32(); builder .instruction_body - .const_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 }); + .const_i32(0x1000 - bits.bytes() as i32); builder.instruction_body.le_i32(); builder.instruction_body.and_i32(); @@ -462,6 +482,11 @@ fn gen_safe_write( .instruction_body .store_unaligned_i32(unsafe { mem8 } as u32); }, + BitSize::QWORD => { + builder + .instruction_body + .store_unaligned_i64(unsafe { mem8 } as u32); + }, } // Pseudo: @@ -506,6 +531,9 @@ fn gen_safe_write( BitSize::DWORD => { gen_call_fn2(builder, "safe_write32_slow_jit"); }, + BitSize::QWORD => { + gen_call_fn2(builder, "safe_write64_slow_jit"); + }, } builder @@ -870,7 +898,7 @@ pub fn gen_safe_read_write( ctx.builder.instruction_body.and_i32(); ctx.builder .instruction_body - .const_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 }); + .const_i32(0x1000 - bits.bytes() as i32); ctx.builder.instruction_body.le_i32(); ctx.builder.instruction_body.and_i32(); } @@ -909,6 +937,11 @@ pub fn gen_safe_read_write( .instruction_body .load_unaligned_i32_from_stack(unsafe { mem8 } as u32); }, + BitSize::QWORD => { + ctx.builder + .instruction_body + .load_unaligned_i64_from_stack(unsafe { mem8 } as u32); + }, } f(ctx); @@ -929,6 +962,11 @@ pub fn gen_safe_read_write( .instruction_body .store_unaligned_i32(unsafe { mem8 } as u32); }, + BitSize::QWORD => { + ctx.builder + .instruction_body + .store_unaligned_i64(unsafe { mem8 } as u32); + }, }; ctx.builder.free_local(phys_addr_local); diff --git a/src/rust/cpu.rs b/src/rust/cpu.rs index 2727cf3d..f407ac58 100644 --- a/src/rust/cpu.rs +++ b/src/rust/cpu.rs @@ -23,6 +23,17 @@ pub enum BitSize { BYTE, WORD, DWORD, + QWORD, +} +impl BitSize { + pub fn bytes(&self) -> u32 { + match self { + BitSize::BYTE => 1, + BitSize::WORD => 2, + BitSize::DWORD => 4, + BitSize::QWORD => 8, + } + } } pub fn read8(addr: u32) -> u8 { unsafe { cpu2::memory::read8(addr) as u8 } } diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 4b38bf99..d7b8ba09 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -2193,6 +2193,20 @@ pub unsafe fn safe_read64s(addr: i32) -> OrPageFault { Ok(x) } +#[no_mangle] +pub unsafe fn safe_read64s_slow_jit(addr: i32) -> i64 { + match safe_read64s(addr) { + Ok(v) => { + *page_fault = false; + v.i64_0[0] + }, + Err(()) => { + *page_fault = true; + 0 + }, + } +} + pub unsafe fn safe_read128s(addr: i32) -> OrPageFault { let mut x: reg128 = reg128 { i8_0: [0; 16] }; if addr & 0xFFF > 0x1000 - 16 { @@ -2340,6 +2354,14 @@ pub unsafe fn safe_write64(addr: i32, value: i64) -> OrPageFault<()> { Ok(()) } +#[no_mangle] +pub unsafe fn safe_write64_slow_jit(addr: i32, value: i64) { + match safe_write64(addr, value) { + Ok(()) => *page_fault = false, + Err(()) => *page_fault = true, + } +} + pub unsafe fn safe_write128(addr: i32, value: reg128) -> OrPageFault<()> { if addr & 0xFFF > 0x1000 - 16 { writable_or_pagefault(addr, 16)?; diff --git a/src/rust/wasmgen/module_init.rs b/src/rust/wasmgen/module_init.rs index aab2715a..c6356ac3 100644 --- a/src/rust/wasmgen/module_init.rs +++ b/src/rust/wasmgen/module_init.rs @@ -25,7 +25,10 @@ pub const FN2_I32_F64_TYPE_INDEX: u8 = 8; #[allow(dead_code)] pub const FN1_F64_TYPE_INDEX: u8 = 9; -pub const NR_FN_TYPE_INDEXES: u8 = 10; +#[allow(dead_code)] +pub const FN1_RET_I64_TYPE_INDEX: u8 = 10; + +pub const NR_FN_TYPE_INDEXES: u8 = 11; pub const WASM_MODULE_ARGUMENT_COUNT: u8 = 1; @@ -258,6 +261,13 @@ impl WasmBuilder { self.output.push(op::TYPE_F64); self.output.push(0); + // FN1_RET_I64 + self.output.push(op::TYPE_FUNC); + self.output.push(1); + self.output.push(op::TYPE_I32); + self.output.push(1); + self.output.push(op::TYPE_I64); + let new_len = self.output.len(); let size = (new_len - 1) - idx_section_size; self.output[idx_section_size] = size.safe_to_u8(); diff --git a/src/rust/wasmgen/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs index 4b576d24..43ba6d7e 100644 --- a/src/rust/wasmgen/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -21,6 +21,7 @@ pub trait WasmBuf { fn ge_i32(&mut self); fn gt_i32(&mut self); fn if_i32(&mut self); + fn if_i64(&mut self); fn block_i32(&mut self); fn xor_i32(&mut self); @@ -28,6 +29,7 @@ pub trait WasmBuf { fn load_u8_from_stack(&mut self, byte_offset: u32); fn load_aligned_u16(&mut self, addr: u32); fn load_aligned_i32(&mut self, addr: u32); + fn load_unaligned_i64_from_stack(&mut self, byte_offset: u32); fn load_unaligned_i32_from_stack(&mut self, byte_offset: u32); fn load_unaligned_u16_from_stack(&mut self, byte_offset: u32); fn load_aligned_i32_from_stack(&mut self, byte_offset: u32); @@ -38,6 +40,7 @@ pub trait WasmBuf { fn store_aligned_i32(&mut self, byte_offset: u32); fn store_unaligned_u16(&mut self, byte_offset: u32); fn store_unaligned_i32(&mut self, byte_offset: u32); + fn store_unaligned_i64(&mut self, byte_offset: u32); fn reinterpret_i32_as_f32(&mut self); fn reinterpret_i64_as_f64(&mut self); @@ -145,6 +148,10 @@ impl WasmBuf for Vec { self.push(op::OP_IF); self.push(op::TYPE_I32); } + fn if_i64(&mut self) { + self.push(op::OP_IF); + self.push(op::TYPE_I64); + } fn block_i32(&mut self) { self.push(op::OP_BLOCK); @@ -153,6 +160,12 @@ impl WasmBuf for Vec { fn xor_i32(&mut self) { self.push(op::OP_I32XOR); } + fn load_unaligned_i64_from_stack(&mut self, byte_offset: u32) { + self.push(op::OP_I64LOAD); + self.push(op::MEM_NO_ALIGN); + self.write_leb_u32(byte_offset); + } + fn load_unaligned_i32_from_stack(&mut self, byte_offset: u32) { self.push(op::OP_I32LOAD); self.push(op::MEM_NO_ALIGN); @@ -201,6 +214,12 @@ impl WasmBuf for Vec { self.write_leb_u32(byte_offset); } + fn store_unaligned_i64(&mut self, byte_offset: u32) { + self.push(op::OP_I64STORE); + self.push(op::MEM_NO_ALIGN); + self.write_leb_u32(byte_offset); + } + fn reinterpret_i32_as_f32(&mut self) { self.push(op::OP_F32REINTERPRETI32); } fn reinterpret_i64_as_f64(&mut self) { self.push(op::OP_F64REINTERPRETI64); } fn promote_f32_to_f64(&mut self) { self.push(op::OP_F64PROMOTEF32); } From 21caefbffd599809ddc2299a7a9609340ac6f3c1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 3 Dec 2018 16:49:52 -0600 Subject: [PATCH 1516/2137] Codegen for fpu instructions (DC group) --- gen/x86_table.js | 16 ++++----- src/rust/codegen.rs | 5 +++ src/rust/jit_instructions.rs | 67 ++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 8 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 496ca868..7294ad48 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -309,14 +309,14 @@ const encodings = [ { opcode: 0xDB, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDB, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDC, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDC, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDC, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDC, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDC, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDC, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDC, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDC, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDC, e: 1, fixed_g: 0, custom: 1, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDC, e: 1, fixed_g: 1, custom: 1, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDC, e: 1, fixed_g: 2, custom: 1, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDC, e: 1, fixed_g: 3, custom: 1, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDC, e: 1, fixed_g: 4, custom: 1, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDC, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDC, e: 1, fixed_g: 6, custom: 1, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDC, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDD, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDD, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // XXX: Test should fail diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 57689fb9..33de61a9 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -1029,6 +1029,11 @@ pub fn gen_fpu_load_m32(ctx: &mut JitContext) { ctx.builder.instruction_body.promote_f32_to_f64(); } +pub fn gen_fpu_load_m64(ctx: &mut JitContext) { + gen_safe_read64(ctx); + ctx.builder.instruction_body.reinterpret_i64_as_f64(); +} + pub fn gen_profiler_stat_increment(builder: &mut WasmBuilder, stat: profiler::stat) { let addr = unsafe { profiler::stat_array.as_mut_ptr().offset(stat as isize) } as u32; gen_increment_variable(builder, addr, 1) diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 8e70b289..9c54e169 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1917,6 +1917,73 @@ pub fn instr_D8_7_reg_jit(ctx: &mut JitContext, r: u32) { instr_group_D8_reg_jit(ctx, r, "fpu_fdivr") } +fn instr_group_DC_mem_jit(ctx: &mut JitContext, modrm_byte: u8, op: &str) { + ctx.builder.instruction_body.const_i32(0); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_fpu_load_m64(ctx); + codegen::gen_call_fn2_i32_f64(ctx.builder, op) +} +fn instr_group_DC_reg_jit(ctx: &mut JitContext, r: u32, op: &str) { + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_fpu_get_sti(ctx, r); + codegen::gen_call_fn2_i32_f64(ctx.builder, op) +} + +pub fn instr_DC_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + instr_group_DC_mem_jit(ctx, modrm_byte, "fpu_fadd") +} +pub fn instr_DC_0_reg_jit(ctx: &mut JitContext, r: u32) { + instr_group_DC_reg_jit(ctx, r, "fpu_fadd") +} +pub fn instr_DC_1_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + instr_group_DC_mem_jit(ctx, modrm_byte, "fpu_fmul") +} +pub fn instr_DC_1_reg_jit(ctx: &mut JitContext, r: u32) { + instr_group_DC_reg_jit(ctx, r, "fpu_fmul") +} +pub fn instr_DC_2_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_fpu_load_m64(ctx); + codegen::gen_call_fn1_f64(ctx.builder, "fpu_fcom") +} +pub fn instr_DC_2_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_fpu_get_sti(ctx, r); + codegen::gen_call_fn1_f64(ctx.builder, "fpu_fcom") +} +pub fn instr_DC_3_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_fpu_load_m64(ctx); + codegen::gen_call_fn1_f64(ctx.builder, "fpu_fcomp") +} +pub fn instr_DC_3_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_fpu_get_sti(ctx, r); + codegen::gen_call_fn1_f64(ctx.builder, "fpu_fcomp") +} +pub fn instr_DC_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + instr_group_DC_mem_jit(ctx, modrm_byte, "fpu_fsub") +} +pub fn instr_DC_4_reg_jit(ctx: &mut JitContext, r: u32) { + instr_group_DC_reg_jit(ctx, r, "fpu_fsub") +} +pub fn instr_DC_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + instr_group_DC_mem_jit(ctx, modrm_byte, "fpu_fsubr") +} +pub fn instr_DC_5_reg_jit(ctx: &mut JitContext, r: u32) { + instr_group_DC_reg_jit(ctx, r, "fpu_fsubr") +} +pub fn instr_DC_6_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + instr_group_DC_mem_jit(ctx, modrm_byte, "fpu_fdiv") +} +pub fn instr_DC_6_reg_jit(ctx: &mut JitContext, r: u32) { + instr_group_DC_reg_jit(ctx, r, "fpu_fdiv") +} +pub fn instr_DC_7_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + instr_group_DC_mem_jit(ctx, modrm_byte, "fpu_fdivr") +} +pub fn instr_DC_7_reg_jit(ctx: &mut JitContext, r: u32) { + instr_group_DC_reg_jit(ctx, r, "fpu_fdivr") +} + pub fn instr16_EB_jit(ctx: &mut JitContext, imm8: u32) { codegen::gen_jmp_rel16(ctx.builder, imm8 as u16); // dbg_assert(is_asize_32() || get_real_eip() < 0x10000); From c452c357dd846c3da353ded10dd50641b6e64f63 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 3 Dec 2018 17:46:35 -0600 Subject: [PATCH 1517/2137] Codegen for fpu instructions (DE group) --- gen/x86_table.js | 16 +++---- src/rust/codegen.rs | 5 +++ src/rust/jit_instructions.rs | 81 +++++++++++++++++++++++++++++++++++ src/rust/wasmgen/wasm_util.rs | 2 + 4 files changed, 96 insertions(+), 8 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 7294ad48..74ca289d 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -327,14 +327,14 @@ const encodings = [ { opcode: 0xDD, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // fsave { opcode: 0xDD, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDE, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDE, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDE, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDE, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDE, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDE, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDE, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDE, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDE, e: 1, fixed_g: 0, custom: 1, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDE, e: 1, fixed_g: 1, custom: 1, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDE, e: 1, fixed_g: 2, custom: 1, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDE, e: 1, fixed_g: 3, custom: 1, is_fpu: 1, task_switch_test: 1, only_mem: 1, }, // skipped: #ud not supported by nasmtests in compiled code + { opcode: 0xDE, e: 1, fixed_g: 4, custom: 1, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDE, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDE, e: 1, fixed_g: 6, custom: 1, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDE, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDF, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1 }, { opcode: 0xDF, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // unimplemented: fisttp (sse3) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 33de61a9..a8542d6a 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -1034,6 +1034,11 @@ pub fn gen_fpu_load_m64(ctx: &mut JitContext) { ctx.builder.instruction_body.reinterpret_i64_as_f64(); } +pub fn gen_trigger_ud(ctx: &mut JitContext) { + gen_fn0_const(ctx.builder, "trigger_ud"); + ctx.builder.instruction_body.return_(); +} + pub fn gen_profiler_stat_increment(builder: &mut WasmBuilder, stat: profiler::stat) { let addr = unsafe { profiler::stat_array.as_mut_ptr().offset(stat as isize) } as u32; gen_increment_variable(builder, addr, 1) diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 9c54e169..c5554f10 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1984,6 +1984,87 @@ pub fn instr_DC_7_reg_jit(ctx: &mut JitContext, r: u32) { instr_group_DC_reg_jit(ctx, r, "fpu_fdivr") } +fn instr_group_DE_mem_jit(ctx: &mut JitContext, modrm_byte: u8, op: &str) { + ctx.builder.instruction_body.const_i32(0); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read16(ctx); + codegen::sign_extend_i16(ctx.builder); + ctx.builder.instruction_body.convert_i32_to_f64(); + codegen::gen_call_fn2_i32_f64(ctx.builder, op) +} +fn instr_group_DE_reg_jit(ctx: &mut JitContext, r: u32, op: &str) { + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_fpu_get_sti(ctx, r); + codegen::gen_call_fn2_i32_f64(ctx.builder, op); + codegen::gen_fn0_const(ctx.builder, "fpu_pop") +} + +pub fn instr_DE_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + instr_group_DE_mem_jit(ctx, modrm_byte, "fpu_fadd") +} +pub fn instr_DE_0_reg_jit(ctx: &mut JitContext, r: u32) { + instr_group_DE_reg_jit(ctx, r, "fpu_fadd") +} +pub fn instr_DE_1_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + instr_group_DE_mem_jit(ctx, modrm_byte, "fpu_fmul") +} +pub fn instr_DE_1_reg_jit(ctx: &mut JitContext, r: u32) { + instr_group_DE_reg_jit(ctx, r, "fpu_fmul") +} +pub fn instr_DE_2_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read16(ctx); + codegen::sign_extend_i16(ctx.builder); + ctx.builder.instruction_body.convert_i32_to_f64(); + codegen::gen_call_fn1_f64(ctx.builder, "fpu_fcom") +} +pub fn instr_DE_2_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_fpu_get_sti(ctx, r); + codegen::gen_call_fn1_f64(ctx.builder, "fpu_fcom"); + codegen::gen_fn0_const(ctx.builder, "fpu_pop") +} +pub fn instr_DE_3_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read16(ctx); + codegen::sign_extend_i16(ctx.builder); + ctx.builder.instruction_body.convert_i32_to_f64(); + codegen::gen_call_fn1_f64(ctx.builder, "fpu_fcomp") +} +pub fn instr_DE_3_reg_jit(ctx: &mut JitContext, r: u32) { + if r == 1 { + codegen::gen_fpu_get_sti(ctx, r); + codegen::gen_call_fn1_f64(ctx.builder, "fpu_fcomp"); + codegen::gen_fn0_const(ctx.builder, "fpu_pop") + } + else { + codegen::gen_trigger_ud(ctx); + } +} +pub fn instr_DE_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + instr_group_DE_mem_jit(ctx, modrm_byte, "fpu_fsub") +} +pub fn instr_DE_4_reg_jit(ctx: &mut JitContext, r: u32) { + instr_group_DE_reg_jit(ctx, r, "fpu_fsub") +} +pub fn instr_DE_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + instr_group_DE_mem_jit(ctx, modrm_byte, "fpu_fsubr") +} +pub fn instr_DE_5_reg_jit(ctx: &mut JitContext, r: u32) { + instr_group_DE_reg_jit(ctx, r, "fpu_fsubr") +} +pub fn instr_DE_6_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + instr_group_DE_mem_jit(ctx, modrm_byte, "fpu_fdiv") +} +pub fn instr_DE_6_reg_jit(ctx: &mut JitContext, r: u32) { + instr_group_DE_reg_jit(ctx, r, "fpu_fdiv") +} +pub fn instr_DE_7_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + instr_group_DE_mem_jit(ctx, modrm_byte, "fpu_fdivr") +} +pub fn instr_DE_7_reg_jit(ctx: &mut JitContext, r: u32) { + instr_group_DE_reg_jit(ctx, r, "fpu_fdivr") +} + pub fn instr16_EB_jit(ctx: &mut JitContext, imm8: u32) { codegen::gen_jmp_rel16(ctx.builder, imm8 as u16); // dbg_assert(is_asize_32() || get_real_eip() < 0x10000); diff --git a/src/rust/wasmgen/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs index 43ba6d7e..316b9946 100644 --- a/src/rust/wasmgen/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -45,6 +45,7 @@ pub trait WasmBuf { fn reinterpret_i32_as_f32(&mut self); fn reinterpret_i64_as_f64(&mut self); fn promote_f32_to_f64(&mut self); + fn convert_i32_to_f64(&mut self); fn shr_u_i32(&mut self); fn shr_s_i32(&mut self); @@ -223,6 +224,7 @@ impl WasmBuf for Vec { fn reinterpret_i32_as_f32(&mut self) { self.push(op::OP_F32REINTERPRETI32); } fn reinterpret_i64_as_f64(&mut self) { self.push(op::OP_F64REINTERPRETI64); } fn promote_f32_to_f64(&mut self) { self.push(op::OP_F64PROMOTEF32); } + fn convert_i32_to_f64(&mut self) { self.push(op::OP_F64CONVERTSI32); } fn shr_u_i32(&mut self) { self.push(op::OP_I32SHRU); } From 7c99bdae7423224efca7278f6783092440139c6a Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 3 Dec 2018 18:09:41 -0600 Subject: [PATCH 1518/2137] Codegen for fpu instructions (memory loads: fld, fild) (D9_0, DB_0, DD_0, DF_5) --- gen/x86_table.js | 8 +++---- src/rust/jit_instructions.rs | 39 +++++++++++++++++++++++++++++++++++ src/rust/wasmgen/wasm_util.rs | 2 ++ 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 74ca289d..7b9a51c3 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -282,7 +282,7 @@ const encodings = [ { opcode: 0xD8, e: 1, fixed_g: 6, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xD8, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xD9, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD9, e: 1, fixed_g: 0, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, }, @@ -300,7 +300,7 @@ const encodings = [ { opcode: 0xDA, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDA, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDB, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDB, e: 1, fixed_g: 0, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDB, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // unimplemented: fisttp (sse3) { opcode: 0xDB, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDB, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, }, @@ -318,7 +318,7 @@ const encodings = [ { opcode: 0xDC, e: 1, fixed_g: 6, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDC, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDD, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDD, e: 1, fixed_g: 0, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDD, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // XXX: Test should fail { opcode: 0xDD, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDD, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, }, @@ -341,7 +341,7 @@ const encodings = [ { opcode: 0xDF, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1 }, { opcode: 0xDF, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1 }, { opcode: 0xDF, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // mem exists, but not implemented - { opcode: 0xDF, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDF, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDF, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // mem exists, but not implemented { opcode: 0xDF, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, }, diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index c5554f10..2cf77e0e 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1917,6 +1917,26 @@ pub fn instr_D8_7_reg_jit(ctx: &mut JitContext, r: u32) { instr_group_D8_reg_jit(ctx, r, "fpu_fdivr") } +pub fn instr_D9_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_fpu_load_m32(ctx); + codegen::gen_call_fn1_f64(ctx.builder, "fpu_push"); +} +pub fn instr_D9_0_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_fpu_get_sti(ctx, r); + codegen::gen_call_fn1_f64(ctx.builder, "fpu_push"); +} + +pub fn instr_DB_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read32(ctx); + ctx.builder.instruction_body.convert_i32_to_f64(); + codegen::gen_call_fn1_f64(ctx.builder, "fpu_push"); +} +pub fn instr_DB_0_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_fn1_const(ctx.builder, "instr_DB_0_reg", r); +} + fn instr_group_DC_mem_jit(ctx: &mut JitContext, modrm_byte: u8, op: &str) { ctx.builder.instruction_body.const_i32(0); codegen::gen_modrm_resolve(ctx, modrm_byte); @@ -1984,6 +2004,15 @@ pub fn instr_DC_7_reg_jit(ctx: &mut JitContext, r: u32) { instr_group_DC_reg_jit(ctx, r, "fpu_fdivr") } +pub fn instr_DD_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_fpu_load_m64(ctx); + codegen::gen_call_fn1_f64(ctx.builder, "fpu_push"); +} +pub fn instr_DD_0_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_fn1_const(ctx.builder, "fpu_ffree", r); +} + fn instr_group_DE_mem_jit(ctx: &mut JitContext, modrm_byte: u8, op: &str) { ctx.builder.instruction_body.const_i32(0); codegen::gen_modrm_resolve(ctx, modrm_byte); @@ -2065,6 +2094,16 @@ pub fn instr_DE_7_reg_jit(ctx: &mut JitContext, r: u32) { instr_group_DE_reg_jit(ctx, r, "fpu_fdivr") } +pub fn instr_DF_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read64(ctx); + ctx.builder.instruction_body.convert_i64_to_f64(); + codegen::gen_call_fn1_f64(ctx.builder, "fpu_push"); +} +pub fn instr_DF_5_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_fn1_const(ctx.builder, "fpu_fucomip", r); +} + pub fn instr16_EB_jit(ctx: &mut JitContext, imm8: u32) { codegen::gen_jmp_rel16(ctx.builder, imm8 as u16); // dbg_assert(is_asize_32() || get_real_eip() < 0x10000); diff --git a/src/rust/wasmgen/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs index 316b9946..01637450 100644 --- a/src/rust/wasmgen/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -46,6 +46,7 @@ pub trait WasmBuf { fn reinterpret_i64_as_f64(&mut self); fn promote_f32_to_f64(&mut self); fn convert_i32_to_f64(&mut self); + fn convert_i64_to_f64(&mut self); fn shr_u_i32(&mut self); fn shr_s_i32(&mut self); @@ -225,6 +226,7 @@ impl WasmBuf for Vec { fn reinterpret_i64_as_f64(&mut self) { self.push(op::OP_F64REINTERPRETI64); } fn promote_f32_to_f64(&mut self) { self.push(op::OP_F64PROMOTEF32); } fn convert_i32_to_f64(&mut self) { self.push(op::OP_F64CONVERTSI32); } + fn convert_i64_to_f64(&mut self) { self.push(op::OP_F64CONVERTSI64); } fn shr_u_i32(&mut self) { self.push(op::OP_I32SHRU); } From b11b2725bb2016bf12db65b7f8d870de396a62b0 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 4 Dec 2018 16:05:21 -0600 Subject: [PATCH 1519/2137] Use i64 locals for gen_safe_write64 --- src/rust/codegen.rs | 73 +++++++++++++++++++++++++-------- src/rust/wasmgen/module_init.rs | 12 +++++- 2 files changed, 65 insertions(+), 20 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index a8542d6a..2d48af3c 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -6,7 +6,7 @@ use modrm; use profiler; use regs; use wasmgen::module_init; -use wasmgen::module_init::{WasmBuilder, WasmLocal}; +use wasmgen::module_init::{WasmBuilder, WasmLocal, WasmLocalI64}; use wasmgen::wasm_util::WasmBuf; extern "C" { @@ -157,6 +157,12 @@ pub fn gen_call_fn2_i32_f64(builder: &mut WasmBuilder, name: &str) { builder.instruction_body.call_fn(fn_idx); } +pub fn gen_call_fn2_i32_i64(builder: &mut WasmBuilder, name: &str) { + // generates: fn( _, _ ) where _ must be left on the stack before calling this + let fn_idx = builder.get_fn_idx(name, module_init::FN2_I32_I64_TYPE_INDEX); + builder.instruction_body.call_fn(fn_idx); +} + pub fn gen_call_fn1_f64(builder: &mut WasmBuilder, name: &str) { // generates: fn( _, _ ) where _ must be left on the stack before calling this let fn_idx = builder.get_fn_idx(name, module_init::FN1_F64_TYPE_INDEX); @@ -238,14 +244,47 @@ pub fn gen_safe_read16(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::WORD) pub fn gen_safe_read32(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::DWORD) } pub fn gen_safe_read64(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::QWORD) } +// only used internally for gen_safe_write +enum I32OrI64Local<'a> { + I32(&'a WasmLocal), + I64(&'a WasmLocalI64), +} + pub fn gen_safe_write8(ctx: &mut JitContext, address_local: &WasmLocal, value_local: &WasmLocal) { - gen_safe_write(ctx, BitSize::BYTE, address_local, value_local) + gen_safe_write( + ctx, + BitSize::BYTE, + address_local, + I32OrI64Local::I32(value_local), + ) } pub fn gen_safe_write16(ctx: &mut JitContext, address_local: &WasmLocal, value_local: &WasmLocal) { - gen_safe_write(ctx, BitSize::WORD, address_local, value_local) + gen_safe_write( + ctx, + BitSize::WORD, + address_local, + I32OrI64Local::I32(value_local), + ) } pub fn gen_safe_write32(ctx: &mut JitContext, address_local: &WasmLocal, value_local: &WasmLocal) { - gen_safe_write(ctx, BitSize::DWORD, address_local, value_local) + gen_safe_write( + ctx, + BitSize::DWORD, + address_local, + I32OrI64Local::I32(value_local), + ) +} +pub fn gen_safe_write64( + ctx: &mut JitContext, + address_local: &WasmLocal, + value_local: &WasmLocalI64, +) { + gen_safe_write( + ctx, + BitSize::QWORD, + address_local, + I32OrI64Local::I64(value_local), + ) } fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { @@ -403,7 +442,7 @@ fn gen_safe_write( ctx: &mut JitContext, bits: BitSize, address_local: &WasmLocal, - value_local: &WasmLocal, + value_local: I32OrI64Local, ) { // Generates safe_writeXX' fast-path inline, bailing to safe_writeXX_slow if necessary. @@ -467,7 +506,10 @@ fn gen_safe_write( // /* continued within can_use_fast_path branch */ // mem8[phys_addr] = value; - builder.instruction_body.get_local(&value_local); + match value_local { + I32OrI64Local::I32(local) => builder.instruction_body.get_local(local), + I32OrI64Local::I64(local) => builder.instruction_body.get_local_i64(local), + } match bits { BitSize::BYTE => { builder.instruction_body.store_u8(unsafe { mem8 } as u32); @@ -520,7 +562,10 @@ fn gen_safe_write( builder.instruction_body.store_aligned_i32(0); builder.instruction_body.get_local(&address_local); - builder.instruction_body.get_local(&value_local); + match value_local { + I32OrI64Local::I32(local) => builder.instruction_body.get_local(local), + I32OrI64Local::I64(local) => builder.instruction_body.get_local_i64(local), + } match bits { BitSize::BYTE => { gen_call_fn2(builder, "safe_write8_slow_jit"); @@ -532,7 +577,7 @@ fn gen_safe_write( gen_call_fn2(builder, "safe_write32_slow_jit"); }, BitSize::QWORD => { - gen_call_fn2(builder, "safe_write64_slow_jit"); + gen_call_fn2_i32_i64(builder, "safe_write64_slow_jit"); }, } @@ -937,11 +982,7 @@ pub fn gen_safe_read_write( .instruction_body .load_unaligned_i32_from_stack(unsafe { mem8 } as u32); }, - BitSize::QWORD => { - ctx.builder - .instruction_body - .load_unaligned_i64_from_stack(unsafe { mem8 } as u32); - }, + BitSize::QWORD => assert!(false), // not used } f(ctx); @@ -962,11 +1003,7 @@ pub fn gen_safe_read_write( .instruction_body .store_unaligned_i32(unsafe { mem8 } as u32); }, - BitSize::QWORD => { - ctx.builder - .instruction_body - .store_unaligned_i64(unsafe { mem8 } as u32); - }, + BitSize::QWORD => assert!(false), // not used }; ctx.builder.free_local(phys_addr_local); diff --git a/src/rust/wasmgen/module_init.rs b/src/rust/wasmgen/module_init.rs index c6356ac3..21f9d4a7 100644 --- a/src/rust/wasmgen/module_init.rs +++ b/src/rust/wasmgen/module_init.rs @@ -24,11 +24,12 @@ pub const FN1_RET_F64_TYPE_INDEX: u8 = 7; pub const FN2_I32_F64_TYPE_INDEX: u8 = 8; #[allow(dead_code)] pub const FN1_F64_TYPE_INDEX: u8 = 9; - #[allow(dead_code)] pub const FN1_RET_I64_TYPE_INDEX: u8 = 10; +#[allow(dead_code)] +pub const FN2_I32_I64_TYPE_INDEX: u8 = 11; -pub const NR_FN_TYPE_INDEXES: u8 = 11; +pub const NR_FN_TYPE_INDEXES: u8 = 12; pub const WASM_MODULE_ARGUMENT_COUNT: u8 = 1; @@ -268,6 +269,13 @@ impl WasmBuilder { self.output.push(1); self.output.push(op::TYPE_I64); + // FN2_I32_I64 + self.output.push(op::TYPE_FUNC); + self.output.push(2); + self.output.push(op::TYPE_I32); + self.output.push(op::TYPE_I64); + self.output.push(0); + let new_len = self.output.len(); let size = (new_len - 1) - idx_section_size; self.output[idx_section_size] = size.safe_to_u8(); From fdce557820d2654980f3f4092ebb60175dcdeaf4 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 5 Dec 2018 16:40:42 -0600 Subject: [PATCH 1520/2137] Codegen for fpu instructions (memory stores: fst/fstp/fist/fistp) (D9_[23], DB_[23], DD_[23], DF_[237]) --- gen/x86_table.js | 26 +++---- src/rust/codegen.rs | 12 +++ src/rust/cpu2/fpu.rs | 50 +++++++++---- src/rust/jit_instructions.rs | 129 ++++++++++++++++++++++++++++++++ src/rust/wasmgen/module_init.rs | 20 ++++- src/rust/wasmgen/wasm_util.rs | 6 ++ 6 files changed, 213 insertions(+), 30 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 7b9a51c3..a4fd3d9d 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -284,9 +284,9 @@ const encodings = [ { opcode: 0xD9, e: 1, fixed_g: 0, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xD9, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xD9, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xD9, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // fldenv (only memory). TODO: Make reg variant non-block-boundary + { opcode: 0xD9, e: 1, fixed_g: 2, custom: 1, is_fpu: 1, task_switch_test: 1, only_mem: 1 }, // skipped: #ud not supported by nasmtests in compiled code + { opcode: 0xD9, e: 1, fixed_g: 3, custom: 1, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD9, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // fldenv { opcode: 0xD9, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, skip: 1, }, // fstenv (mem), fprem (reg) { opcode: 0xD9, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, only_mem: 1, }, // fprem @@ -302,8 +302,8 @@ const encodings = [ { opcode: 0xDB, e: 1, fixed_g: 0, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDB, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // unimplemented: fisttp (sse3) - { opcode: 0xDB, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDB, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDB, e: 1, fixed_g: 2, custom: 2, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDB, e: 1, fixed_g: 3, custom: 2, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDB, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDB, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDB, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, }, @@ -319,9 +319,9 @@ const encodings = [ { opcode: 0xDC, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDD, e: 1, fixed_g: 0, custom: 1, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDD, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // XXX: Test should fail - { opcode: 0xDD, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDD, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDD, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, + { opcode: 0xDD, e: 1, fixed_g: 2, custom: 1, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDD, e: 1, fixed_g: 3, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDD, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // frstor { opcode: 0xDD, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDD, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // fsave @@ -338,12 +338,12 @@ const encodings = [ { opcode: 0xDF, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1 }, { opcode: 0xDF, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // unimplemented: fisttp (sse3) - { opcode: 0xDF, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1 }, - { opcode: 0xDF, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1 }, - { opcode: 0xDF, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // mem exists, but not implemented + { opcode: 0xDF, e: 1, fixed_g: 2, custom: 1, is_fpu: 1, task_switch_test: 1 }, + { opcode: 0xDF, e: 1, fixed_g: 3, custom: 1, is_fpu: 1, task_switch_test: 1 }, + { opcode: 0xDF, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // unimplemented: Binary Coded Decimals { opcode: 0xDF, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDF, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // mem exists, but not implemented - { opcode: 0xDF, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDF, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // unimplemented: Binary Coded Decimals + { opcode: 0xDF, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, only_mem: 1 }, // skipped: #ud not supported by nasmtests in compiled code // loop, jcxz, etc. // Conditional jumps, but condition code not supported by code generator diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 2d48af3c..a923bc87 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -126,6 +126,18 @@ pub fn gen_call_fn1_ret_f64(builder: &mut WasmBuilder, name: &str) { builder.instruction_body.call_fn(fn_idx); } +pub fn gen_call_fn1_f64_ret_i32(builder: &mut WasmBuilder, name: &str) { + // generates: fn( _ ) where _ must be left on the stack before calling this, and fn returns a value + let fn_idx = builder.get_fn_idx(name, module_init::FN1_F64_RET_I32_TYPE_INDEX); + builder.instruction_body.call_fn(fn_idx); +} + +pub fn gen_call_fn1_f64_ret_i64(builder: &mut WasmBuilder, name: &str) { + // generates: fn( _ ) where _ must be left on the stack before calling this, and fn returns a value + let fn_idx = builder.get_fn_idx(name, module_init::FN1_F64_RET_I64_TYPE_INDEX); + builder.instruction_body.call_fn(fn_idx); +} + pub fn gen_call_fn1_ret_i64(builder: &mut WasmBuilder, name: &str) { // generates: fn( _ ) where _ must be left on the stack before calling this, and fn returns a value let fn_idx = builder.get_fn_idx(name, module_init::FN1_RET_I64_TYPE_INDEX); diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 8c9bb0ec..f690bb22 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -346,54 +346,72 @@ pub unsafe fn fpu_finit() { *fpu_stack_empty = 255; *fpu_stack_ptr = 0; } + #[no_mangle] -pub unsafe fn fpu_fistm16(addr: i32) { - let st0: f64 = fpu_integer_round(fpu_get_st0()); +pub unsafe fn fpu_invalid_arithmetic() { *fpu_status_word |= FPU_EX_I; } + +#[no_mangle] +pub unsafe fn fpu_convert_to_i16(f: f64) -> i16 { + let st0: f64 = fpu_integer_round(f); if st0 <= 32767.0 && st0 >= -32768.0 { - return_on_pagefault!(safe_write16(addr, st0 as i32)); + st0 as i16 } else { fpu_invalid_arithmetic(); - return_on_pagefault!(safe_write16(addr, 32768)); - }; + -0x8000 + } } #[no_mangle] -pub unsafe fn fpu_invalid_arithmetic() { *fpu_status_word |= FPU_EX_I; } +pub unsafe fn fpu_fistm16(addr: i32) { + let v = fpu_convert_to_i16(fpu_get_st0()); + return_on_pagefault!(safe_write16(addr, v as i32)); +} #[no_mangle] pub unsafe fn fpu_fistm16p(addr: i32) { fpu_fistm16(addr); fpu_pop(); } + #[no_mangle] -pub unsafe fn fpu_fistm32(addr: i32) { - let st0: f64 = fpu_integer_round(fpu_get_st0()); - let i: i32 = convert_f64_to_i32(st0); +pub unsafe fn fpu_convert_to_i32(f: f64) -> i32 { + let st0 = fpu_integer_round(f); + let i = convert_f64_to_i32(st0); if i == -0x80000000 { // XXX: Probably not correct if st0 == 0x80000000 // (input fits, but same value as error value) fpu_invalid_arithmetic(); } - return_on_pagefault!(safe_write32(addr, i)); + i +} +#[no_mangle] +pub unsafe fn fpu_fistm32(addr: i32) { + let v = fpu_convert_to_i32(fpu_get_st0()); + return_on_pagefault!(safe_write32(addr, v)); } #[no_mangle] pub unsafe fn fpu_fistm32p(addr: i32) { fpu_fistm32(addr); fpu_pop(); } + #[no_mangle] -pub unsafe fn fpu_fistm64p(addr: i32) { - let st0: f64 = fpu_integer_round(fpu_get_st0()); - let value; +pub unsafe fn fpu_convert_to_i64(f: f64) -> i64 { + let st0: f64 = fpu_integer_round(f); if st0 < TWO_POW_63 && st0 >= -TWO_POW_63 { - value = st0 as i64 + st0 as i64 } else { - value = -0x80000000_00000000; fpu_invalid_arithmetic(); + -0x80000000_00000000 } - return_on_pagefault!(safe_write64(addr, value)); +} +#[no_mangle] +pub unsafe fn fpu_fistm64p(addr: i32) { + let v = fpu_convert_to_i64(fpu_get_st0()); + return_on_pagefault!(safe_write64(addr, v)); fpu_pop(); } + #[no_mangle] pub unsafe fn fpu_fldcw(addr: i32) { let word: i32 = return_on_pagefault!(safe_read16(addr)); diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 2cf77e0e..093e6527 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1927,6 +1927,38 @@ pub fn instr_D9_0_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_call_fn1_f64(ctx.builder, "fpu_push"); } +pub fn instr_D9_2_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_fpu_get_sti(ctx, 0); + ctx.builder.instruction_body.demote_f64_to_f32(); + ctx.builder.instruction_body.reinterpret_f32_as_i32(); + let value_local = ctx.builder.set_new_local(); + codegen::gen_safe_write32(ctx, &address_local, &value_local); + ctx.builder.free_local(address_local); + ctx.builder.free_local(value_local); +} +pub fn instr_D9_2_reg_jit(ctx: &mut JitContext, r: u32) { + if r != 0 { + codegen::gen_trigger_ud(ctx); + } +} +pub fn instr_D9_3_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_fpu_get_sti(ctx, 0); + ctx.builder.instruction_body.demote_f64_to_f32(); + ctx.builder.instruction_body.reinterpret_f32_as_i32(); + let value_local = ctx.builder.set_new_local(); + codegen::gen_safe_write32(ctx, &address_local, &value_local); + codegen::gen_fn0_const(ctx.builder, "fpu_pop"); + ctx.builder.free_local(address_local); + ctx.builder.free_local(value_local); +} +pub fn instr_D9_3_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_fn1_const(ctx.builder, "fpu_fstp", r); +} + pub fn instr_DB_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); @@ -1937,6 +1969,34 @@ pub fn instr_DB_0_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_fn1_const(ctx.builder, "instr_DB_0_reg", r); } +pub fn instr_DB_2_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_fpu_get_sti(ctx, 0); + codegen::gen_call_fn1_f64_ret_i32(ctx.builder, "fpu_convert_to_i32"); + let value_local = ctx.builder.set_new_local(); + codegen::gen_safe_write32(ctx, &address_local, &value_local); + ctx.builder.free_local(address_local); + ctx.builder.free_local(value_local); +} +pub fn instr_DB_2_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_fn1_const(ctx.builder, "instr_DB_2_reg", r); +} +pub fn instr_DB_3_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_fpu_get_sti(ctx, 0); + codegen::gen_call_fn1_f64_ret_i32(ctx.builder, "fpu_convert_to_i32"); + let value_local = ctx.builder.set_new_local(); + codegen::gen_safe_write32(ctx, &address_local, &value_local); + ctx.builder.free_local(address_local); + ctx.builder.free_local(value_local); + codegen::gen_fn0_const(ctx.builder, "fpu_pop"); +} +pub fn instr_DB_3_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_fn1_const(ctx.builder, "instr_DB_3_reg", r); +} + fn instr_group_DC_mem_jit(ctx: &mut JitContext, modrm_byte: u8, op: &str) { ctx.builder.instruction_body.const_i32(0); codegen::gen_modrm_resolve(ctx, modrm_byte); @@ -2013,6 +2073,34 @@ pub fn instr_DD_0_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_fn1_const(ctx.builder, "fpu_ffree", r); } +pub fn instr_DD_2_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_fpu_get_sti(ctx, 0); + ctx.builder.instruction_body.reinterpret_f64_as_i64(); + let value_local = ctx.builder.set_new_local_i64(); + codegen::gen_safe_write64(ctx, &address_local, &value_local); + ctx.builder.free_local(address_local); + ctx.builder.free_local_i64(value_local); +} +pub fn instr_DD_2_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_fn1_const(ctx.builder, "fpu_fst", r); +} +pub fn instr_DD_3_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_fpu_get_sti(ctx, 0); + ctx.builder.instruction_body.reinterpret_f64_as_i64(); + let value_local = ctx.builder.set_new_local_i64(); + codegen::gen_safe_write64(ctx, &address_local, &value_local); + codegen::gen_fn0_const(ctx.builder, "fpu_pop"); + ctx.builder.free_local(address_local); + ctx.builder.free_local_i64(value_local); +} +pub fn instr_DD_3_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_fn1_const(ctx.builder, "fpu_fstp", r); +} + fn instr_group_DE_mem_jit(ctx: &mut JitContext, modrm_byte: u8, op: &str) { ctx.builder.instruction_body.const_i32(0); codegen::gen_modrm_resolve(ctx, modrm_byte); @@ -2094,6 +2182,34 @@ pub fn instr_DE_7_reg_jit(ctx: &mut JitContext, r: u32) { instr_group_DE_reg_jit(ctx, r, "fpu_fdivr") } +pub fn instr_DF_2_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_fpu_get_sti(ctx, 0); + codegen::gen_call_fn1_f64_ret_i32(ctx.builder, "fpu_convert_to_i16"); + let value_local = ctx.builder.set_new_local(); + codegen::gen_safe_write16(ctx, &address_local, &value_local); + ctx.builder.free_local(address_local); + ctx.builder.free_local(value_local); +} +pub fn instr_DF_2_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_fn1_const(ctx.builder, "fpu_fstp", r); +} +pub fn instr_DF_3_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_fpu_get_sti(ctx, 0); + codegen::gen_call_fn1_f64_ret_i32(ctx.builder, "fpu_convert_to_i16"); + let value_local = ctx.builder.set_new_local(); + codegen::gen_safe_write16(ctx, &address_local, &value_local); + ctx.builder.free_local(address_local); + ctx.builder.free_local(value_local); + codegen::gen_fn0_const(ctx.builder, "fpu_pop"); +} +pub fn instr_DF_3_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_fn1_const(ctx.builder, "fpu_fstp", r); +} + pub fn instr_DF_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read64(ctx); @@ -2104,6 +2220,19 @@ pub fn instr_DF_5_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_fn1_const(ctx.builder, "fpu_fucomip", r); } +pub fn instr_DF_7_reg_jit(ctx: &mut JitContext, _r: u32) { codegen::gen_trigger_ud(ctx); } +pub fn instr_DF_7_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_fpu_get_sti(ctx, 0); + codegen::gen_call_fn1_f64_ret_i64(ctx.builder, "fpu_convert_to_i64"); + let value_local = ctx.builder.set_new_local_i64(); + codegen::gen_safe_write64(ctx, &address_local, &value_local); + ctx.builder.free_local(address_local); + ctx.builder.free_local_i64(value_local); + codegen::gen_fn0_const(ctx.builder, "fpu_pop"); +} + pub fn instr16_EB_jit(ctx: &mut JitContext, imm8: u32) { codegen::gen_jmp_rel16(ctx.builder, imm8 as u16); // dbg_assert(is_asize_32() || get_real_eip() < 0x10000); diff --git a/src/rust/wasmgen/module_init.rs b/src/rust/wasmgen/module_init.rs index 21f9d4a7..ca9dfa96 100644 --- a/src/rust/wasmgen/module_init.rs +++ b/src/rust/wasmgen/module_init.rs @@ -28,8 +28,12 @@ pub const FN1_F64_TYPE_INDEX: u8 = 9; pub const FN1_RET_I64_TYPE_INDEX: u8 = 10; #[allow(dead_code)] pub const FN2_I32_I64_TYPE_INDEX: u8 = 11; +#[allow(dead_code)] +pub const FN1_F64_RET_I32_TYPE_INDEX: u8 = 12; +#[allow(dead_code)] +pub const FN1_F64_RET_I64_TYPE_INDEX: u8 = 13; -pub const NR_FN_TYPE_INDEXES: u8 = 12; +pub const NR_FN_TYPE_INDEXES: u8 = 14; pub const WASM_MODULE_ARGUMENT_COUNT: u8 = 1; @@ -276,6 +280,20 @@ impl WasmBuilder { self.output.push(op::TYPE_I64); self.output.push(0); + // FN1_F64_RET_I32 + self.output.push(op::TYPE_FUNC); + self.output.push(1); + self.output.push(op::TYPE_F64); + self.output.push(1); + self.output.push(op::TYPE_I32); + + // FN1_F64_RET_I64 + self.output.push(op::TYPE_FUNC); + self.output.push(1); + self.output.push(op::TYPE_F64); + self.output.push(1); + self.output.push(op::TYPE_I64); + let new_len = self.output.len(); let size = (new_len - 1) - idx_section_size; self.output[idx_section_size] = size.safe_to_u8(); diff --git a/src/rust/wasmgen/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs index 01637450..801e5bfa 100644 --- a/src/rust/wasmgen/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -43,8 +43,11 @@ pub trait WasmBuf { fn store_unaligned_i64(&mut self, byte_offset: u32); fn reinterpret_i32_as_f32(&mut self); + fn reinterpret_f32_as_i32(&mut self); fn reinterpret_i64_as_f64(&mut self); + fn reinterpret_f64_as_i64(&mut self); fn promote_f32_to_f64(&mut self); + fn demote_f64_to_f32(&mut self); fn convert_i32_to_f64(&mut self); fn convert_i64_to_f64(&mut self); @@ -223,8 +226,11 @@ impl WasmBuf for Vec { } fn reinterpret_i32_as_f32(&mut self) { self.push(op::OP_F32REINTERPRETI32); } + fn reinterpret_f32_as_i32(&mut self) { self.push(op::OP_I32REINTERPRETF32); } fn reinterpret_i64_as_f64(&mut self) { self.push(op::OP_F64REINTERPRETI64); } + fn reinterpret_f64_as_i64(&mut self) { self.push(op::OP_I64REINTERPRETF64); } fn promote_f32_to_f64(&mut self) { self.push(op::OP_F64PROMOTEF32); } + fn demote_f64_to_f32(&mut self) { self.push(op::OP_F32DEMOTEF64); } fn convert_i32_to_f64(&mut self) { self.push(op::OP_F64CONVERTSI32); } fn convert_i64_to_f64(&mut self) { self.push(op::OP_F64CONVERTSI64); } From 29395181d287224a8c0c6230f8ce91645bf575f0 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 5 Dec 2018 17:29:34 -0600 Subject: [PATCH 1521/2137] Update expect test results --- tests/expect/tests/call.wast | 61 +++-- tests/expect/tests/do-while.wast | 23 +- tests/expect/tests/if.wast | 25 +- tests/expect/tests/indirect-call.wast | 19 +- tests/expect/tests/mov16.wast | 249 +++++++++--------- tests/expect/tests/mov32-mem.wast | 251 ++++++++++--------- tests/expect/tests/mov32-reg.wast | 19 +- tests/expect/tests/pop.wast | 35 +-- tests/expect/tests/push.wast | 43 ++-- tests/expect/tests/task_switch_test.wast | 74 +++--- tests/expect/tests/task_switch_test_sse.wast | 19 +- tests/expect/tests/while-do.wast | 25 +- 12 files changed, 458 insertions(+), 385 deletions(-) diff --git a/tests/expect/tests/call.wast b/tests/expect/tests/call.wast index c599e13d..97258b48 100644 --- a/tests/expect/tests/call.wast +++ b/tests/expect/tests/call.wast @@ -6,6 +6,13 @@ (type $t4 (func (result i32))) (type $t5 (func (param i32) (result i32))) (type $t6 (func (param i32 i32) (result i32))) + (type $t7 (func (param i32) (result f64))) + (type $t8 (func (param i32 f64))) + (type $t9 (func (param f64))) + (type $t10 (func (param i32) (result i64))) + (type $t11 (func (param i32 i64))) + (type $t12 (func (param f64) (result i32))) + (type $t13 (func (param f64) (result i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "safe_write32_slow_jit" (func $e.safe_write32_slow_jit (type $t2))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) @@ -14,18 +21,18 @@ (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) - (set_local $p0 - (get_local $p0)) (set_local $l0 + (get_local $p0)) + (set_local $l1 (i32.const 10000)) (loop $L0 - (set_local $l0 + (set_local $l1 (i32.add - (get_local $l0) + (get_local $l1) (i32.const -1))) (if $I1 (i32.eqz - (get_local $l0)) + (get_local $l1)) (then (return))) (block $B2 @@ -33,7 +40,7 @@ (block $B4 (block $B5 (br_table $B5 $B4 $B3 $B2 - (get_local $p0))) + (get_local $l0))) (i32.store (i32.const 560) (i32.load @@ -44,15 +51,15 @@ (i32.load (i32.const 556)) (i32.const 5))) - (set_local $l1 + (set_local $l2 (i32.sub (i32.load (i32.const 556)) (i32.load (i32.const 740)))) - (set_local $l3 + (set_local $l4 (i32.add - (tee_local $l2 + (tee_local $l3 (i32.sub (i32.load (i32.const 20)) @@ -63,28 +70,28 @@ (i32.and (i32.eq (i32.and - (tee_local $l4 + (tee_local $l5 (i32.load offset=4194304 (i32.shl (i32.shr_u - (get_local $l3) + (get_local $l4) (i32.const 12)) (i32.const 2)))) (i32.const 4075)) (i32.const 1)) (i32.le_s (i32.and - (get_local $l3) + (get_local $l4) (i32.const 4095)) (i32.const 4092))) (then (i32.store offset={normalised output} align=1 (i32.xor (i32.and - (get_local $l4) + (get_local $l5) (i32.const -4096)) - (get_local $l3)) - (get_local $l1))) + (get_local $l4)) + (get_local $l2))) (else (i32.store (i32.const 560) @@ -95,8 +102,8 @@ (i32.const -4096)) (i32.const 0))) (call $e.safe_write32_slow_jit - (get_local $l3) - (get_local $l1)) + (get_local $l4) + (get_local $l2)) (if $I7 (i32.load8_u (i32.const 540)) @@ -104,7 +111,7 @@ (return))))) (i32.store (i32.const 20) - (get_local $l2)) + (get_local $l3)) (i32.store (i32.const 556) (i32.add @@ -117,7 +124,7 @@ (i32.load (i32.const 664)) (i32.const 1))) - (set_local $p0 + (set_local $l0 (i32.const 2)) (br $L0)) (i32.store @@ -158,13 +165,13 @@ (i32.and (i32.eq (i32.and - (tee_local $l3 + (tee_local $l4 (i32.load offset=4194304 (i32.shl (i32.shr_u - (tee_local $l2 + (tee_local $l3 (i32.add - (tee_local $l1 + (tee_local $l2 (i32.load (i32.const 20))) (i32.load @@ -175,16 +182,16 @@ (i32.const 1)) (i32.le_s (i32.and - (get_local $l2) + (get_local $l3) (i32.const 4095)) (i32.const 4092))) (then (i32.load offset={normalised output} align=1 (i32.xor (i32.and - (get_local $l3) + (get_local $l4) (i32.const -4096)) - (get_local $l2)))) + (get_local $l3)))) (else (i32.store (i32.const 560) @@ -195,7 +202,7 @@ (i32.const -4096)) (i32.const 7))) (call $e.safe_read32s_slow_jit - (get_local $l2)) + (get_local $l3)) (if $I9 (i32.load8_u (i32.const 540)) @@ -204,7 +211,7 @@ (i32.store (i32.const 20) (i32.add - (get_local $l1) + (get_local $l2) (i32.const 4))) (i32.add) (i32.store) diff --git a/tests/expect/tests/do-while.wast b/tests/expect/tests/do-while.wast index 5d5fa859..3cc37555 100644 --- a/tests/expect/tests/do-while.wast +++ b/tests/expect/tests/do-while.wast @@ -6,6 +6,13 @@ (type $t4 (func (result i32))) (type $t5 (func (param i32) (result i32))) (type $t6 (func (param i32 i32) (result i32))) + (type $t7 (func (param i32) (result f64))) + (type $t8 (func (param i32 f64))) + (type $t9 (func (param f64))) + (type $t10 (func (param i32) (result i64))) + (type $t11 (func (param i32 i64))) + (type $t12 (func (param f64) (result i32))) + (type $t13 (func (param f64) (result i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "instr32_43" (func $e.instr32_43 (type $t0))) (import "e" "cmp32" (func $e.cmp32 (type $t2))) @@ -14,25 +21,25 @@ (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) (local $l0 i32) (local $l1 i32) - (set_local $p0 - (get_local $p0)) (set_local $l0 + (get_local $p0)) + (set_local $l1 (i32.const 10000)) (loop $L0 - (set_local $l0 + (set_local $l1 (i32.add - (get_local $l0) + (get_local $l1) (i32.const -1))) (if $I1 (i32.eqz - (get_local $l0)) + (get_local $l1)) (then (return))) (block $B2 (block $B3 (block $B4 (br_table $B4 $B3 $B2 - (get_local $p0))) + (get_local $l0))) (call $e.instr32_43) (call $e.cmp32 (i32.load @@ -65,10 +72,10 @@ (i32.load (i32.const 556)) (i32.const -6))) - (set_local $p0 + (set_local $l0 (i32.const 0))) (else - (set_local $p0 + (set_local $l0 (i32.const 1)))) (br $L0)) (i32.store diff --git a/tests/expect/tests/if.wast b/tests/expect/tests/if.wast index 67938e35..294b8445 100644 --- a/tests/expect/tests/if.wast +++ b/tests/expect/tests/if.wast @@ -6,6 +6,13 @@ (type $t4 (func (result i32))) (type $t5 (func (param i32) (result i32))) (type $t6 (func (param i32 i32) (result i32))) + (type $t7 (func (param i32) (result f64))) + (type $t8 (func (param i32 f64))) + (type $t9 (func (param f64))) + (type $t10 (func (param i32) (result i64))) + (type $t11 (func (param i32 i64))) + (type $t12 (func (param f64) (result i32))) + (type $t13 (func (param f64) (result i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "cmp32" (func $e.cmp32 (type $t2))) (import "e" "test_nle" (func $e.test_nle (type $t4))) @@ -15,18 +22,18 @@ (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) (local $l0 i32) (local $l1 i32) - (set_local $p0 - (get_local $p0)) (set_local $l0 + (get_local $p0)) + (set_local $l1 (i32.const 10000)) (loop $L0 - (set_local $l0 + (set_local $l1 (i32.add - (get_local $l0) + (get_local $l1) (i32.const -1))) (if $I1 (i32.eqz - (get_local $l0)) + (get_local $l1)) (then (return))) (block $B2 @@ -34,7 +41,7 @@ (block $B4 (block $B5 (br_table $B5 $B4 $B3 $B2 - (get_local $p0))) + (get_local $l0))) (call $e.cmp32 (i32.load (i32.const 4)) @@ -66,10 +73,10 @@ (i32.load (i32.const 556)) (i32.const 1))) - (set_local $p0 + (set_local $l0 (i32.const 2))) (else - (set_local $p0 + (set_local $l0 (i32.const 1)))) (br $L0)) (i32.store @@ -89,7 +96,7 @@ (i32.load (i32.const 664)) (i32.const 1))) - (set_local $p0 + (set_local $l0 (i32.const 2)) (br $L0)) (call $e.instr32_43) diff --git a/tests/expect/tests/indirect-call.wast b/tests/expect/tests/indirect-call.wast index 9692ea76..67be19be 100644 --- a/tests/expect/tests/indirect-call.wast +++ b/tests/expect/tests/indirect-call.wast @@ -6,31 +6,38 @@ (type $t4 (func (result i32))) (type $t5 (func (param i32) (result i32))) (type $t6 (func (param i32 i32) (result i32))) + (type $t7 (func (param i32) (result f64))) + (type $t8 (func (param i32 f64))) + (type $t9 (func (param f64))) + (type $t10 (func (param i32) (result i64))) + (type $t11 (func (param i32 i64))) + (type $t12 (func (param f64) (result i32))) + (type $t13 (func (param f64) (result i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "instr32_FF_2_mem" (func $e.instr32_FF_2_mem (type $t1))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) (local $l0 i32) (local $l1 i32) - (set_local $p0 - (get_local $p0)) (set_local $l0 + (get_local $p0)) + (set_local $l1 (i32.const 10000)) (loop $L0 - (set_local $l0 + (set_local $l1 (i32.add - (get_local $l0) + (get_local $l1) (i32.const -1))) (if $I1 (i32.eqz - (get_local $l0)) + (get_local $l1)) (then (return))) (block $B2 (block $B3 (block $B4 (br_table $B4 $B3 $B2 - (get_local $p0))) + (get_local $l0))) (i32.store (i32.const 560) (i32.load diff --git a/tests/expect/tests/mov16.wast b/tests/expect/tests/mov16.wast index 0c4a3b54..ee3b62d7 100644 --- a/tests/expect/tests/mov16.wast +++ b/tests/expect/tests/mov16.wast @@ -6,6 +6,13 @@ (type $t4 (func (result i32))) (type $t5 (func (param i32) (result i32))) (type $t6 (func (param i32 i32) (result i32))) + (type $t7 (func (param i32) (result f64))) + (type $t8 (func (param i32 f64))) + (type $t9 (func (param f64))) + (type $t10 (func (param i32) (result i64))) + (type $t11 (func (param i32 i64))) + (type $t12 (func (param f64) (result i32))) + (type $t13 (func (param f64) (result i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "instr16_B8" (func $e.instr16_B8 (type $t1))) (import "e" "safe_read16_slow_jit" (func $e.safe_read16_slow_jit (type $t5))) @@ -14,24 +21,24 @@ (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) - (set_local $p0 - (get_local $p0)) (set_local $l0 + (get_local $p0)) + (set_local $l1 (i32.const 10000)) (loop $L0 - (set_local $l0 + (set_local $l1 (i32.add - (get_local $l0) + (get_local $l1) (i32.const -1))) (if $I1 (i32.eqz - (get_local $l0)) + (get_local $l1)) (then (return))) (block $B2 (block $B3 (br_table $B3 $B2 - (get_local $p0))) + (get_local $l0))) (call $e.instr16_B8 (i32.const 51966)) (i32.store16 @@ -40,60 +47,13 @@ (i32.and (i32.eq (i32.and - (tee_local $l2 - (i32.load offset=4194304 - (i32.shl - (i32.shr_u - (tee_local $l1 - (i32.add - (i32.const 32) - (call $e.get_seg - (i32.const 3)))) - (i32.const 12)) - (i32.const 2)))) - (i32.const 4041)) - (i32.const 1)) - (i32.le_s - (i32.and - (get_local $l1) - (i32.const 4095)) - (i32.const 4094))) - (then - (i32.load16_u offset={normalised output} align=1 - (i32.xor - (i32.and - (get_local $l2) - (i32.const -4096)) - (get_local $l1)))) - (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 3))) - (call $e.safe_read16_slow_jit - (get_local $l1)) - (if $I5 - (i32.load8_u - (i32.const 540)) - (then - (return)))))) - (i32.store16 - (i32.const 12) - (if $I6 (result i32) - (i32.and - (i32.eq - (i32.and - (tee_local $l1 + (tee_local $l3 (i32.load offset=4194304 (i32.shl (i32.shr_u (tee_local $l2 (i32.add - (i32.const 36) + (i32.const 32) (call $e.get_seg (i32.const 3)))) (i32.const 12)) @@ -109,7 +69,7 @@ (i32.load16_u offset={normalised output} align=1 (i32.xor (i32.and - (get_local $l1) + (get_local $l3) (i32.const -4096)) (get_local $l2)))) (else @@ -120,9 +80,56 @@ (i32.load (i32.const 556)) (i32.const -4096)) - (i32.const 7))) + (i32.const 3))) (call $e.safe_read16_slow_jit (get_local $l2)) + (if $I5 + (i32.load8_u + (i32.const 540)) + (then + (return)))))) + (i32.store16 + (i32.const 12) + (if $I6 (result i32) + (i32.and + (i32.eq + (i32.and + (tee_local $l2 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (tee_local $l3 + (i32.add + (i32.const 36) + (call $e.get_seg + (i32.const 3)))) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4041)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l3) + (i32.const 4095)) + (i32.const 4094))) + (then + (i32.load16_u offset={normalised output} align=1 + (i32.xor + (i32.and + (get_local $l2) + (i32.const -4096)) + (get_local $l3)))) + (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 7))) + (call $e.safe_read16_slow_jit + (get_local $l3)) (if $I7 (i32.load8_u (i32.const 540)) @@ -134,7 +141,7 @@ (i32.store16 (i32.const 28) (i32.const 32)) - (set_local $l1 + (set_local $l2 (i32.add (i32.and (i32.add @@ -145,71 +152,14 @@ (i32.const 65535)) (call $e.get_seg (i32.const 3)))) - (set_local $l2 + (set_local $l3 (i32.load16_u (i32.const 4))) (if $I8 (i32.and (i32.eq (i32.and - (tee_local $l3 - (i32.load offset=4194304 - (i32.shl - (i32.shr_u - (get_local $l1) - (i32.const 12)) - (i32.const 2)))) - (i32.const 4075)) - (i32.const 1)) - (i32.le_s - (i32.and - (get_local $l1) - (i32.const 4095)) - (i32.const 4094))) - (then - (i32.store16 offset={normalised output} align=1 - (i32.xor - (i32.and - (get_local $l3) - (i32.const -4096)) - (get_local $l1)) - (get_local $l2))) - (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 19))) - (call $e.safe_write16_slow_jit - (get_local $l1) - (get_local $l2)) - (if $I9 - (i32.load8_u - (i32.const 540)) - (then - (return))))) - (set_local $l2 - (i32.add - (i32.and - (i32.add - (i32.load16_u - (i32.const 16)) - (i32.load16_u - (i32.const 28))) - (i32.const 65535)) - (call $e.get_seg - (i32.const 3)))) - (set_local $l1 - (i32.load16_u - (i32.const 8))) - (if $I10 - (i32.and - (i32.eq - (i32.and - (tee_local $l3 + (tee_local $l4 (i32.load offset=4194304 (i32.shl (i32.shr_u @@ -227,10 +177,67 @@ (i32.store16 offset={normalised output} align=1 (i32.xor (i32.and - (get_local $l3) + (get_local $l4) (i32.const -4096)) (get_local $l2)) - (get_local $l1))) + (get_local $l3))) + (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 19))) + (call $e.safe_write16_slow_jit + (get_local $l2) + (get_local $l3)) + (if $I9 + (i32.load8_u + (i32.const 540)) + (then + (return))))) + (set_local $l3 + (i32.add + (i32.and + (i32.add + (i32.load16_u + (i32.const 16)) + (i32.load16_u + (i32.const 28))) + (i32.const 65535)) + (call $e.get_seg + (i32.const 3)))) + (set_local $l2 + (i32.load16_u + (i32.const 8))) + (if $I10 + (i32.and + (i32.eq + (i32.and + (tee_local $l4 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (get_local $l3) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4075)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l3) + (i32.const 4095)) + (i32.const 4094))) + (then + (i32.store16 offset={normalised output} align=1 + (i32.xor + (i32.and + (get_local $l4) + (i32.const -4096)) + (get_local $l3)) + (get_local $l2))) (else (i32.store (i32.const 560) @@ -241,8 +248,8 @@ (i32.const -4096)) (i32.const 21))) (call $e.safe_write16_slow_jit - (get_local $l2) - (get_local $l1)) + (get_local $l3) + (get_local $l2)) (if $I11 (i32.load8_u (i32.const 540)) diff --git a/tests/expect/tests/mov32-mem.wast b/tests/expect/tests/mov32-mem.wast index fcbd4167..0a646a0d 100644 --- a/tests/expect/tests/mov32-mem.wast +++ b/tests/expect/tests/mov32-mem.wast @@ -6,6 +6,13 @@ (type $t4 (func (result i32))) (type $t5 (func (param i32) (result i32))) (type $t6 (func (param i32 i32) (result i32))) + (type $t7 (func (param i32) (result f64))) + (type $t8 (func (param i32 f64))) + (type $t9 (func (param f64))) + (type $t10 (func (param i32) (result i64))) + (type $t11 (func (param i32 i64))) + (type $t12 (func (param f64) (result i32))) + (type $t13 (func (param f64) (result i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "safe_write32_slow_jit" (func $e.safe_write32_slow_jit (type $t2))) (import "e" "safe_read32s_slow_jit" (func $e.safe_read32s_slow_jit (type $t5))) @@ -13,25 +20,25 @@ (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) - (set_local $p0 - (get_local $p0)) (set_local $l0 + (get_local $p0)) + (set_local $l1 (i32.const 10000)) (loop $L0 - (set_local $l0 + (set_local $l1 (i32.add - (get_local $l0) + (get_local $l1) (i32.const -1))) (if $I1 (i32.eqz - (get_local $l0)) + (get_local $l1)) (then (return))) (block $B2 (block $B3 (br_table $B3 $B2 - (get_local $p0))) - (set_local $l1 + (get_local $l0))) + (set_local $l2 (i32.add (i32.add (i32.load @@ -39,68 +46,14 @@ (i32.const 32)) (call $e.get_seg (i32.const 3)))) - (set_local $l2 + (set_local $l3 (i32.load (i32.const 4))) (if $I4 (i32.and (i32.eq (i32.and - (tee_local $l3 - (i32.load offset=4194304 - (i32.shl - (i32.shr_u - (get_local $l1) - (i32.const 12)) - (i32.const 2)))) - (i32.const 4075)) - (i32.const 1)) - (i32.le_s - (i32.and - (get_local $l1) - (i32.const 4095)) - (i32.const 4092))) - (then - (i32.store offset={normalised output} align=1 - (i32.xor - (i32.and - (get_local $l3) - (i32.const -4096)) - (get_local $l1)) - (get_local $l2))) - (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 0))) - (call $e.safe_write32_slow_jit - (get_local $l1) - (get_local $l2)) - (if $I5 - (i32.load8_u - (i32.const 540)) - (then - (return))))) - (set_local $l2 - (i32.add - (i32.add - (i32.load - (i32.const 12)) - (i32.const 28)) - (call $e.get_seg - (i32.const 3)))) - (set_local $l1 - (i32.load - (i32.const 8))) - (if $I6 - (i32.and - (i32.eq - (i32.and - (tee_local $l3 + (tee_local $l4 (i32.load offset=4194304 (i32.shl (i32.shr_u @@ -118,10 +71,64 @@ (i32.store offset={normalised output} align=1 (i32.xor (i32.and - (get_local $l3) + (get_local $l4) (i32.const -4096)) (get_local $l2)) - (get_local $l1))) + (get_local $l3))) + (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 0))) + (call $e.safe_write32_slow_jit + (get_local $l2) + (get_local $l3)) + (if $I5 + (i32.load8_u + (i32.const 540)) + (then + (return))))) + (set_local $l3 + (i32.add + (i32.add + (i32.load + (i32.const 12)) + (i32.const 28)) + (call $e.get_seg + (i32.const 3)))) + (set_local $l2 + (i32.load + (i32.const 8))) + (if $I6 + (i32.and + (i32.eq + (i32.and + (tee_local $l4 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (get_local $l3) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4075)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l3) + (i32.const 4095)) + (i32.const 4092))) + (then + (i32.store offset={normalised output} align=1 + (i32.xor + (i32.and + (get_local $l4) + (i32.const -4096)) + (get_local $l3)) + (get_local $l2))) (else (i32.store (i32.const 560) @@ -132,8 +139,8 @@ (i32.const -4096)) (i32.const 6))) (call $e.safe_write32_slow_jit - (get_local $l2) - (get_local $l1)) + (get_local $l3) + (get_local $l2)) (if $I7 (i32.load8_u (i32.const 540)) @@ -145,57 +152,7 @@ (i32.and (i32.eq (i32.and - (tee_local $l2 - (i32.load offset=4194304 - (i32.shl - (i32.shr_u - (tee_local $l1 - (i32.add - (i32.add - (i32.load - (i32.const 16)) - (i32.const 28)) - (call $e.get_seg - (i32.const 3)))) - (i32.const 12)) - (i32.const 2)))) - (i32.const 4041)) - (i32.const 1)) - (i32.le_s - (i32.and - (get_local $l1) - (i32.const 4095)) - (i32.const 4092))) - (then - (i32.load offset={normalised output} align=1 - (i32.xor - (i32.and - (get_local $l2) - (i32.const -4096)) - (get_local $l1)))) - (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 12))) - (call $e.safe_read32s_slow_jit - (get_local $l1)) - (if $I9 - (i32.load8_u - (i32.const 540)) - (then - (return)))))) - (i32.store - (i32.const 32) - (if $I10 (result i32) - (i32.and - (i32.eq - (i32.and - (tee_local $l1 + (tee_local $l3 (i32.load offset=4194304 (i32.shl (i32.shr_u @@ -203,8 +160,8 @@ (i32.add (i32.add (i32.load - (i32.const 12)) - (i32.const 32)) + (i32.const 16)) + (i32.const 28)) (call $e.get_seg (i32.const 3)))) (i32.const 12)) @@ -220,7 +177,7 @@ (i32.load offset={normalised output} align=1 (i32.xor (i32.and - (get_local $l1) + (get_local $l3) (i32.const -4096)) (get_local $l2)))) (else @@ -231,9 +188,59 @@ (i32.load (i32.const 556)) (i32.const -4096)) - (i32.const 18))) + (i32.const 12))) (call $e.safe_read32s_slow_jit (get_local $l2)) + (if $I9 + (i32.load8_u + (i32.const 540)) + (then + (return)))))) + (i32.store + (i32.const 32) + (if $I10 (result i32) + (i32.and + (i32.eq + (i32.and + (tee_local $l2 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (tee_local $l3 + (i32.add + (i32.add + (i32.load + (i32.const 12)) + (i32.const 32)) + (call $e.get_seg + (i32.const 3)))) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4041)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l3) + (i32.const 4095)) + (i32.const 4092))) + (then + (i32.load offset={normalised output} align=1 + (i32.xor + (i32.and + (get_local $l2) + (i32.const -4096)) + (get_local $l3)))) + (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 18))) + (call $e.safe_read32s_slow_jit + (get_local $l3)) (if $I11 (i32.load8_u (i32.const 540)) diff --git a/tests/expect/tests/mov32-reg.wast b/tests/expect/tests/mov32-reg.wast index d77c42a5..2e7d1553 100644 --- a/tests/expect/tests/mov32-reg.wast +++ b/tests/expect/tests/mov32-reg.wast @@ -6,6 +6,13 @@ (type $t4 (func (result i32))) (type $t5 (func (param i32) (result i32))) (type $t6 (func (param i32 i32) (result i32))) + (type $t7 (func (param i32) (result f64))) + (type $t8 (func (param i32 f64))) + (type $t9 (func (param f64))) + (type $t10 (func (param i32) (result i64))) + (type $t11 (func (param i32 i64))) + (type $t12 (func (param f64) (result i32))) + (type $t13 (func (param f64) (result i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "instr32_B8" (func $e.instr32_B8 (type $t1))) (import "e" "instr32_B9" (func $e.instr32_B9 (type $t1))) @@ -15,24 +22,24 @@ (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) (local $l0 i32) (local $l1 i32) - (set_local $p0 - (get_local $p0)) (set_local $l0 + (get_local $p0)) + (set_local $l1 (i32.const 10000)) (loop $L0 - (set_local $l0 + (set_local $l1 (i32.add - (get_local $l0) + (get_local $l1) (i32.const -1))) (if $I1 (i32.eqz - (get_local $l0)) + (get_local $l1)) (then (return))) (block $B2 (block $B3 (br_table $B3 $B2 - (get_local $p0))) + (get_local $l0))) (call $e.instr32_B8 (i32.const -889270259)) (call $e.instr32_B9 diff --git a/tests/expect/tests/pop.wast b/tests/expect/tests/pop.wast index da63b466..c3d04718 100644 --- a/tests/expect/tests/pop.wast +++ b/tests/expect/tests/pop.wast @@ -6,42 +6,49 @@ (type $t4 (func (result i32))) (type $t5 (func (param i32) (result i32))) (type $t6 (func (param i32 i32) (result i32))) + (type $t7 (func (param i32) (result f64))) + (type $t8 (func (param i32 f64))) + (type $t9 (func (param f64))) + (type $t10 (func (param i32) (result i64))) + (type $t11 (func (param i32 i64))) + (type $t12 (func (param f64) (result i32))) + (type $t13 (func (param f64) (result i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "safe_read32s_slow_jit" (func $e.safe_read32s_slow_jit (type $t5))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) - (set_local $p0 - (get_local $p0)) (set_local $l0 + (get_local $p0)) + (set_local $l1 (i32.const 10000)) (loop $L0 - (set_local $l0 + (set_local $l1 (i32.add - (get_local $l0) + (get_local $l1) (i32.const -1))) (if $I1 (i32.eqz - (get_local $l0)) + (get_local $l1)) (then (return))) (block $B2 (block $B3 (br_table $B3 $B2 - (get_local $p0))) + (get_local $l0))) (i32.const 4) (if $I4 (result i32) (i32.and (i32.eq (i32.and - (tee_local $l3 + (tee_local $l4 (i32.load offset=4194304 (i32.shl (i32.shr_u - (tee_local $l2 + (tee_local $l3 (i32.add - (tee_local $l1 + (tee_local $l2 (i32.load (i32.const 20))) (i32.load @@ -52,16 +59,16 @@ (i32.const 1)) (i32.le_s (i32.and - (get_local $l2) + (get_local $l3) (i32.const 4095)) (i32.const 4092))) (then (i32.load offset={normalised output} align=1 (i32.xor (i32.and - (get_local $l3) + (get_local $l4) (i32.const -4096)) - (get_local $l2)))) + (get_local $l3)))) (else (i32.store (i32.const 560) @@ -72,7 +79,7 @@ (i32.const -4096)) (i32.const 0))) (call $e.safe_read32s_slow_jit - (get_local $l2)) + (get_local $l3)) (if $I5 (i32.load8_u (i32.const 540)) @@ -81,7 +88,7 @@ (i32.store (i32.const 20) (i32.add - (get_local $l1) + (get_local $l2) (i32.const 4))) (i32.store) (i32.store diff --git a/tests/expect/tests/push.wast b/tests/expect/tests/push.wast index cfb02828..4c40292b 100644 --- a/tests/expect/tests/push.wast +++ b/tests/expect/tests/push.wast @@ -6,36 +6,43 @@ (type $t4 (func (result i32))) (type $t5 (func (param i32) (result i32))) (type $t6 (func (param i32 i32) (result i32))) + (type $t7 (func (param i32) (result f64))) + (type $t8 (func (param i32 f64))) + (type $t9 (func (param f64))) + (type $t10 (func (param i32) (result i64))) + (type $t11 (func (param i32 i64))) + (type $t12 (func (param f64) (result i32))) + (type $t13 (func (param f64) (result i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "safe_write32_slow_jit" (func $e.safe_write32_slow_jit (type $t2))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) - (set_local $p0 - (get_local $p0)) (set_local $l0 + (get_local $p0)) + (set_local $l1 (i32.const 10000)) (loop $L0 - (set_local $l0 + (set_local $l1 (i32.add - (get_local $l0) + (get_local $l1) (i32.const -1))) (if $I1 (i32.eqz - (get_local $l0)) + (get_local $l1)) (then (return))) (block $B2 (block $B3 (br_table $B3 $B2 - (get_local $p0))) - (set_local $l1 + (get_local $l0))) + (set_local $l2 (i32.load (i32.const 4))) - (set_local $l3 + (set_local $l4 (i32.add - (tee_local $l2 + (tee_local $l3 (i32.sub (i32.load (i32.const 20)) @@ -46,28 +53,28 @@ (i32.and (i32.eq (i32.and - (tee_local $l4 + (tee_local $l5 (i32.load offset=4194304 (i32.shl (i32.shr_u - (get_local $l3) + (get_local $l4) (i32.const 12)) (i32.const 2)))) (i32.const 4075)) (i32.const 1)) (i32.le_s (i32.and - (get_local $l3) + (get_local $l4) (i32.const 4095)) (i32.const 4092))) (then (i32.store offset={normalised output} align=1 (i32.xor (i32.and - (get_local $l4) + (get_local $l5) (i32.const -4096)) - (get_local $l3)) - (get_local $l1))) + (get_local $l4)) + (get_local $l2))) (else (i32.store (i32.const 560) @@ -78,8 +85,8 @@ (i32.const -4096)) (i32.const 0))) (call $e.safe_write32_slow_jit - (get_local $l3) - (get_local $l1)) + (get_local $l4) + (get_local $l2)) (if $I5 (i32.load8_u (i32.const 540)) @@ -87,7 +94,7 @@ (return))))) (i32.store (i32.const 20) - (get_local $l2)) + (get_local $l3)) (i32.store (i32.const 560) (i32.add diff --git a/tests/expect/tests/task_switch_test.wast b/tests/expect/tests/task_switch_test.wast index b3ddc0e1..436f2ec6 100644 --- a/tests/expect/tests/task_switch_test.wast +++ b/tests/expect/tests/task_switch_test.wast @@ -6,75 +6,71 @@ (type $t4 (func (result i32))) (type $t5 (func (param i32) (result i32))) (type $t6 (func (param i32 i32) (result i32))) + (type $t7 (func (param i32) (result f64))) + (type $t8 (func (param i32 f64))) + (type $t9 (func (param f64))) + (type $t10 (func (param i32) (result i64))) + (type $t11 (func (param i32 i64))) + (type $t12 (func (param f64) (result i32))) + (type $t13 (func (param f64) (result i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "task_switch_test_void" (func $e.task_switch_test_void (type $t0))) - (import "e" "instr_DE_0_reg" (func $e.instr_DE_0_reg (type $t1))) + (import "e" "fpu_get_sti" (func $e.fpu_get_sti (type $t7))) + (import "e" "fpu_fadd" (func $e.fpu_fadd (type $t8))) + (import "e" "fpu_pop" (func $e.fpu_pop (type $t0))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) (local $l0 i32) (local $l1 i32) - (set_local $p0 - (get_local $p0)) (set_local $l0 + (get_local $p0)) + (set_local $l1 (i32.const 10000)) (loop $L0 - (set_local $l0 + (set_local $l1 (i32.add - (get_local $l0) + (get_local $l1) (i32.const -1))) (if $I1 (i32.eqz - (get_local $l0)) + (get_local $l1)) (then (return))) (block $B2 (block $B3 - (block $B4 - (br_table $B4 $B3 $B2 - (get_local $p0))) - (i32.store - (i32.const 560) + (br_table $B3 $B2 + (get_local $l0))) + (if $I4 + (i32.and (i32.load - (i32.const 556))) - (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 2))) - (if $I5 - (i32.and - (i32.load - (i32.const 580)) - (i32.const 12)) - (then - (call $e.task_switch_test_void) - (return))) - (call $e.instr_DE_0_reg - (i32.const 1)) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 1))) - (return)) + (i32.const 580)) + (i32.const 12)) + (then + (call $e.task_switch_test_void) + (return))) + (call $e.fpu_fadd + (i32.const 1) + (call $e.fpu_get_sti + (i32.const 1))) + (call $e.fpu_pop) (i32.store (i32.const 560) - (i32.load - (i32.const 556))) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 2))) (i32.store (i32.const 556) (i32.add (i32.load (i32.const 556)) - (i32.const 1))) + (i32.const 3))) (call $e.instr_F4) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) - (i32.const 1))) + (i32.const 2))) (return)) (unreachable)))) diff --git a/tests/expect/tests/task_switch_test_sse.wast b/tests/expect/tests/task_switch_test_sse.wast index 33d00123..f84e21eb 100644 --- a/tests/expect/tests/task_switch_test_sse.wast +++ b/tests/expect/tests/task_switch_test_sse.wast @@ -6,6 +6,13 @@ (type $t4 (func (result i32))) (type $t5 (func (param i32) (result i32))) (type $t6 (func (param i32 i32) (result i32))) + (type $t7 (func (param i32) (result f64))) + (type $t8 (func (param i32 f64))) + (type $t9 (func (param f64))) + (type $t10 (func (param i32) (result i64))) + (type $t11 (func (param i32 i64))) + (type $t12 (func (param f64) (result i32))) + (type $t13 (func (param f64) (result i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "task_switch_test_mmx_void" (func $e.task_switch_test_mmx_void (type $t0))) (import "e" "instr_660F54_reg" (func $e.instr_660F54_reg (type $t2))) @@ -13,25 +20,25 @@ (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) (local $l0 i32) (local $l1 i32) - (set_local $p0 - (get_local $p0)) (set_local $l0 + (get_local $p0)) + (set_local $l1 (i32.const 10000)) (loop $L0 - (set_local $l0 + (set_local $l1 (i32.add - (get_local $l0) + (get_local $l1) (i32.const -1))) (if $I1 (i32.eqz - (get_local $l0)) + (get_local $l1)) (then (return))) (block $B2 (block $B3 (block $B4 (br_table $B4 $B3 $B2 - (get_local $p0))) + (get_local $l0))) (i32.store (i32.const 560) (i32.load diff --git a/tests/expect/tests/while-do.wast b/tests/expect/tests/while-do.wast index 1ac550ae..b2e4966b 100644 --- a/tests/expect/tests/while-do.wast +++ b/tests/expect/tests/while-do.wast @@ -6,6 +6,13 @@ (type $t4 (func (result i32))) (type $t5 (func (param i32) (result i32))) (type $t6 (func (param i32 i32) (result i32))) + (type $t7 (func (param i32) (result f64))) + (type $t8 (func (param i32 f64))) + (type $t9 (func (param f64))) + (type $t10 (func (param i32) (result i64))) + (type $t11 (func (param i32 i64))) + (type $t12 (func (param f64) (result i32))) + (type $t13 (func (param f64) (result i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "cmp32" (func $e.cmp32 (type $t2))) (import "e" "test_z" (func $e.test_z (type $t4))) @@ -14,18 +21,18 @@ (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) (local $l0 i32) (local $l1 i32) - (set_local $p0 - (get_local $p0)) (set_local $l0 + (get_local $p0)) + (set_local $l1 (i32.const 10000)) (loop $L0 - (set_local $l0 + (set_local $l1 (i32.add - (get_local $l0) + (get_local $l1) (i32.const -1))) (if $I1 (i32.eqz - (get_local $l0)) + (get_local $l1)) (then (return))) (block $B2 @@ -33,7 +40,7 @@ (block $B4 (block $B5 (br_table $B5 $B4 $B3 $B2 - (get_local $p0))) + (get_local $l0))) (call $e.cmp32 (i32.load (i32.const 4)) @@ -65,10 +72,10 @@ (i32.load (i32.const 556)) (i32.const 3))) - (set_local $p0 + (set_local $l0 (i32.const 2))) (else - (set_local $p0 + (set_local $l0 (i32.const 1)))) (br $L0)) (call $e.instr32_43) @@ -96,7 +103,7 @@ (i32.load (i32.const 664)) (i32.const 2))) - (set_local $p0 + (set_local $l0 (i32.const 0)) (br $L0)) (i32.store From 1eab44746bb98b64d2ecc4a6765aabc5804dc2e7 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 6 Dec 2018 11:37:40 -0600 Subject: [PATCH 1522/2137] Codegen for fpu instructions (fldcw/fstcw) (D9_5, D9_7) --- gen/x86_table.js | 4 ++-- src/rust/global_pointers.rs | 1 + src/rust/jit_instructions.rs | 30 ++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index a4fd3d9d..023a568e 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -287,9 +287,9 @@ const encodings = [ { opcode: 0xD9, e: 1, fixed_g: 2, custom: 1, is_fpu: 1, task_switch_test: 1, only_mem: 1 }, // skipped: #ud not supported by nasmtests in compiled code { opcode: 0xD9, e: 1, fixed_g: 3, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // fldenv - { opcode: 0xD9, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD9, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, skip: 1, }, // fstenv (mem), fprem (reg) - { opcode: 0xD9, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, only_mem: 1, }, // fprem + { opcode: 0xD9, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, only_mem: 1, }, // fprem { opcode: 0xDA, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDA, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, }, diff --git a/src/rust/global_pointers.rs b/src/rust/global_pointers.rs index f1be2ef4..6e00cf8d 100644 --- a/src/rust/global_pointers.rs +++ b/src/rust/global_pointers.rs @@ -8,6 +8,7 @@ pub const TIMESTAMP_COUNTER: u32 = 664; pub const SEGMENT_OFFSETS: u32 = 736; pub const OPSTATS_BUFFER: u32 = 0x1000; pub const OPSTATS_BUFFER_0F: u32 = 0x1400; +pub const FPU_CONTROL_WORD: u32 = 1036; pub const TLB_DATA: u32 = 0x400000; pub fn get_reg8_offset(r: u32) -> u32 { diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 093e6527..ded47f51 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1959,6 +1959,36 @@ pub fn instr_D9_3_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_fn1_const(ctx.builder, "fpu_fstp", r); } +pub fn instr_D9_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + ctx.builder + .instruction_body + .const_i32(global_pointers::FPU_CONTROL_WORD as i32); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read16(ctx); + ctx.builder.instruction_body.store_aligned_u16(0); +} +pub fn instr_D9_5_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_fn1_const(ctx.builder, "instr_D9_5_reg", r); +} +pub fn instr_D9_7_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + ctx.builder + .instruction_body + .const_i32(global_pointers::FPU_CONTROL_WORD as i32); + ctx.builder + .instruction_body + .const_i32(global_pointers::FPU_CONTROL_WORD as i32); + ctx.builder.instruction_body.load_aligned_u16_from_stack(0); + let value_local = ctx.builder.set_new_local(); + codegen::gen_safe_write16(ctx, &address_local, &value_local); + ctx.builder.free_local(address_local); + ctx.builder.free_local(value_local); +} +pub fn instr_D9_7_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_fn1_const(ctx.builder, "instr_D9_7_reg", r); +} + pub fn instr_DB_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); From ec846b34d941168991051e0c01cfd2562cc3cfad Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 6 Dec 2018 12:32:19 -0600 Subject: [PATCH 1523/2137] Codegen for fpu instructions (misc instructions) (D9_[14], DB_5, DD_5, DF_4) --- gen/x86_table.js | 11 ++++---- src/rust/jit_instructions.rs | 54 ++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 023a568e..4105a42b 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -283,10 +283,10 @@ const encodings = [ { opcode: 0xD8, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: 0, custom: 1, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xD9, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD9, e: 1, fixed_g: 1, custom: 1, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // skipped: #ud not supported by nasmtests in compiled code { opcode: 0xD9, e: 1, fixed_g: 2, custom: 1, is_fpu: 1, task_switch_test: 1, only_mem: 1 }, // skipped: #ud not supported by nasmtests in compiled code { opcode: 0xD9, e: 1, fixed_g: 3, custom: 1, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xD9, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // fldenv + { opcode: 0xD9, e: 1, fixed_g: 4, custom: 1, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // fldenv { opcode: 0xD9, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, skip: 1, }, // fstenv (mem), fprem (reg) { opcode: 0xD9, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, only_mem: 1, }, // fprem @@ -305,7 +305,7 @@ const encodings = [ { opcode: 0xDB, e: 1, fixed_g: 2, custom: 2, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDB, e: 1, fixed_g: 3, custom: 2, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDB, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDB, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDB, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // skipped: #ud not supported by nasmtests in compiled code { opcode: 0xDB, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDB, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, }, @@ -323,7 +323,7 @@ const encodings = [ { opcode: 0xDD, e: 1, fixed_g: 2, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDD, e: 1, fixed_g: 3, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDD, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // frstor - { opcode: 0xDD, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDD, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // skipped: #ud not supported by nasmtests in compiled code { opcode: 0xDD, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // fsave { opcode: 0xDD, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, }, @@ -340,7 +340,8 @@ const encodings = [ { opcode: 0xDF, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // unimplemented: fisttp (sse3) { opcode: 0xDF, e: 1, fixed_g: 2, custom: 1, is_fpu: 1, task_switch_test: 1 }, { opcode: 0xDF, e: 1, fixed_g: 3, custom: 1, is_fpu: 1, task_switch_test: 1 }, - { opcode: 0xDF, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // unimplemented: Binary Coded Decimals + { opcode: 0xDF, e: 1, fixed_g: 4, custom: 1, is_fpu: 1, task_switch_test: 1, skip: 1 }, // unimplemented (mem): Binary Coded Decimals + // skipped (reg): #ud not supported by nasmtests in compiled code { opcode: 0xDF, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDF, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // unimplemented: Binary Coded Decimals { opcode: 0xDF, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, only_mem: 1 }, // skipped: #ud not supported by nasmtests in compiled code diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index ded47f51..0c7f3af3 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1927,6 +1927,15 @@ pub fn instr_D9_0_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_call_fn1_f64(ctx.builder, "fpu_push"); } +pub fn instr_D9_1_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_trigger_ud(ctx); +} +pub fn instr_D9_1_reg_jit(ctx: &mut JitContext, r: u32) { + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_call_fn1(ctx.builder, "fpu_fxch"); +} + pub fn instr_D9_2_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); @@ -1959,6 +1968,17 @@ pub fn instr_D9_3_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_fn1_const(ctx.builder, "fpu_fstp", r); } +pub fn instr_D9_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_call_fn1(ctx.builder, "fpu_fldenv"); + // XXX: generated because fldenv might page-fault, but doesn't generate a proper block boundary + ctx.builder.instruction_body.return_(); +} +pub fn instr_D9_4_reg_jit(ctx: &mut JitContext, r: u32) { + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_call_fn1(ctx.builder, "instr_D9_4_reg"); +} + pub fn instr_D9_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { ctx.builder .instruction_body @@ -2027,6 +2047,17 @@ pub fn instr_DB_3_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_fn1_const(ctx.builder, "instr_DB_3_reg", r); } +pub fn instr_DB_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_call_fn1(ctx.builder, "fpu_fldm80"); + // XXX: generated because fpu_fldm80 might page-fault, but doesn't generate a proper block boundary + ctx.builder.instruction_body.return_(); +} +pub fn instr_DB_5_reg_jit(ctx: &mut JitContext, r: u32) { + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_call_fn1(ctx.builder, "fpu_fucomi"); +} + fn instr_group_DC_mem_jit(ctx: &mut JitContext, modrm_byte: u8, op: &str) { ctx.builder.instruction_body.const_i32(0); codegen::gen_modrm_resolve(ctx, modrm_byte); @@ -2131,6 +2162,15 @@ pub fn instr_DD_3_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_fn1_const(ctx.builder, "fpu_fstp", r); } +pub fn instr_DD_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_trigger_ud(ctx); +} +pub fn instr_DD_5_reg_jit(ctx: &mut JitContext, r: u32) { + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_call_fn1(ctx.builder, "fpu_fucomp"); +} + fn instr_group_DE_mem_jit(ctx: &mut JitContext, modrm_byte: u8, op: &str) { ctx.builder.instruction_body.const_i32(0); codegen::gen_modrm_resolve(ctx, modrm_byte); @@ -2240,6 +2280,20 @@ pub fn instr_DF_3_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_fn1_const(ctx.builder, "fpu_fstp", r); } +pub fn instr_DF_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + dbg_log!("fbld"); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_trigger_ud(ctx); +} +pub fn instr_DF_4_reg_jit(ctx: &mut JitContext, r: u32) { + if r == 0 { + codegen::gen_fn0_const(ctx.builder, "fpu_fnstsw_reg"); + } + else { + codegen::gen_trigger_ud(ctx); + }; +} + pub fn instr_DF_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read64(ctx); From e2ab5eabddc0712e395d2b9bc394465966a7aba3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 6 Dec 2018 15:48:09 -0600 Subject: [PATCH 1524/2137] Code generation for missing memory operations (8-bit shifts, shrd, shld, xadd) --- gen/x86_table.js | 20 +- src/rust/codegen.rs | 5 + src/rust/cpu2/arith.rs | 9 + src/rust/cpu2/cpu.rs | 4 +- src/rust/jit_instructions.rs | 368 ++++++++++++++++++++++++++++++++ src/rust/wasmgen/module_init.rs | 14 +- 6 files changed, 407 insertions(+), 13 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 4105a42b..58ee21c9 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -388,10 +388,10 @@ const encodings = [ { opcode: 0xF7, os: 1, e: 1, fixed_g: 0, imm1632: 1, custom: 1 }, { opcode: 0xF7, os: 1, e: 1, fixed_g: 1, imm1632: 1, custom: 1 }, - { opcode: 0xF7, os: 1, e: 1, fixed_g: 2, }, - { opcode: 0xF7, os: 1, e: 1, fixed_g: 3, }, - { opcode: 0xF7, os: 1, e: 1, fixed_g: 4, mask_flags: zf | af, }, - { opcode: 0xF7, os: 1, e: 1, fixed_g: 5, mask_flags: zf | af, }, + { opcode: 0xF7, os: 1, e: 1, fixed_g: 2, custom: 1 }, + { opcode: 0xF7, os: 1, e: 1, fixed_g: 3, custom: 1 }, + { opcode: 0xF7, os: 1, e: 1, fixed_g: 4, mask_flags: zf | af, custom: 1 }, + { opcode: 0xF7, os: 1, e: 1, fixed_g: 5, mask_flags: zf | af, custom: 1 }, { opcode: 0xF7, os: 1, e: 1, fixed_g: 6, block_boundary: 1, }, // div/idiv: Not a block boundary, but doesn't use control flow exceptions { opcode: 0xF7, os: 1, e: 1, fixed_g: 7, block_boundary: 1, }, @@ -561,10 +561,10 @@ const encodings = [ { 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: 0x0FA4, os: 1, e: 1, custom: 1, imm8: 1, mask_flags: af | of, }, // shld + { opcode: 0x0FA5, os: 1, e: 1, custom: 1, mask_flags: af | of, }, + { opcode: 0x0FAC, os: 1, e: 1, custom: 1, imm8: 1, mask_flags: af | of, }, + { opcode: 0x0FAD, os: 1, e: 1, custom: 1, mask_flags: af | of, }, { opcode: 0x0FA6, skip: 1, block_boundary: 1, }, // ud { opcode: 0x0FA7, skip: 1, block_boundary: 1, }, // ud @@ -604,7 +604,7 @@ const encodings = [ { opcode: 0x0FBF, os: 1, e: 1, custom: 1 }, { opcode: 0x0FC0, e: 1, }, // xadd - { opcode: 0x0FC1, os: 1, e: 1, }, + { opcode: 0x0FC1, os: 1, e: 1, custom: 1 }, { opcode: 0x0FC8, }, // bswap { opcode: 0x0FC9, }, @@ -959,7 +959,7 @@ for(let i = 0; i < 8; i++) // 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: 0xC0, e: 1, fixed_g: i, imm8: 1, mask_flags: of | af, custom: 1, }, { opcode: 0xC1, os: 1, e: 1, fixed_g: i, imm8: 1, mask_flags: of | af, custom: 1, }, { opcode: 0xD0, e: 1, fixed_g: i, mask_flags: af, }, { opcode: 0xD1, os: 1, e: 1, fixed_g: i, mask_flags: af, custom: 1, }, diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index a923bc87..0ee855fe 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -192,6 +192,11 @@ pub fn gen_call_fn3(builder: &mut WasmBuilder, name: &str) { builder.instruction_body.call_fn(fn_idx); } +pub fn gen_call_fn3_ret(builder: &mut WasmBuilder, name: &str) { + let fn_idx = builder.get_fn_idx(name, module_init::FN3_RET_TYPE_INDEX); + builder.instruction_body.call_fn(fn_idx); +} + pub fn gen_fn3_const(builder: &mut WasmBuilder, name: &str, arg0: u32, arg1: u32, arg2: u32) { let fn_idx = builder.get_fn_idx(name, module_init::FN3_TYPE_INDEX); builder.instruction_body.const_i32(arg0 as i32); diff --git a/src/rust/cpu2/arith.rs b/src/rust/cpu2/arith.rs index 2e25bc27..a064f293 100644 --- a/src/rust/cpu2/arith.rs +++ b/src/rust/cpu2/arith.rs @@ -117,6 +117,14 @@ pub unsafe fn dec8(x: i32) -> i32 { return dec(x, OPSIZE_8); } pub unsafe fn dec16(x: i32) -> i32 { return dec(x, OPSIZE_16); } #[no_mangle] pub unsafe fn dec32(x: i32) -> i32 { return dec(x, OPSIZE_32); } + +#[no_mangle] +pub unsafe fn not8(x: i32) -> i32 { return !x; } +#[no_mangle] +pub unsafe fn not16(x: i32) -> i32 { return !x; } +#[no_mangle] +pub unsafe fn not32(x: i32) -> i32 { return !x; } + #[no_mangle] pub unsafe fn neg(dest_operand: i32, op_size: i32) -> i32 { let res: i32 = -dest_operand; @@ -134,6 +142,7 @@ pub unsafe fn neg8(x: i32) -> i32 { return neg(x, OPSIZE_8); } pub unsafe fn neg16(x: i32) -> i32 { return neg(x, OPSIZE_16); } #[no_mangle] pub unsafe fn neg32(x: i32) -> i32 { return neg(x, OPSIZE_32); } + #[no_mangle] pub unsafe fn mul8(source_operand: i32) { let result: i32 = source_operand * *reg8.offset(AL as isize) as i32; diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index d7b8ba09..e733423b 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -2375,7 +2375,7 @@ pub unsafe fn safe_write128(addr: i32, value: reg128) -> OrPageFault<()> { Ok(()) } -pub unsafe fn get_reg8_index(index: i32) -> i32 { return index << 2 & 12 | index >> 2 & 1; } +pub fn get_reg8_index(index: i32) -> i32 { return index << 2 & 12 | index >> 2 & 1; } pub unsafe fn read_reg8(index: i32) -> i32 { return *reg8.offset(get_reg8_index(index) as isize) as i32; @@ -2385,7 +2385,7 @@ pub unsafe fn write_reg8(index: i32, value: i32) { *reg8.offset(get_reg8_index(index) as isize) = value as u8; } -pub unsafe fn get_reg16_index(index: i32) -> i32 { return index << 1; } +pub fn get_reg16_index(index: i32) -> i32 { return index << 1; } pub unsafe fn read_reg16(index: i32) -> i32 { return *reg16.offset(get_reg16_index(index) as isize) as i32; diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 0c7f3af3..14e93c43 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -457,6 +457,63 @@ macro_rules! define_instruction_read_write_mem16( } ); + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, reg, cl) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_safe_read_write(ctx, BitSize::WORD, &address_local, &|ref mut ctx| { + codegen::gen_get_reg16(ctx.builder, r); + codegen::gen_get_reg8(ctx.builder, regs::CL); + ctx.builder.instruction_body.const_i32(31); + ctx.builder.instruction_body.and_i32(); + codegen::gen_call_fn3_ret(ctx.builder, $fn); + }, &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_call_fn2(ctx.builder, $fallback_fn) + }); + ctx.builder.free_local(address_local); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { + ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r1) as i32); + codegen::gen_get_reg16(ctx.builder, r1); + codegen::gen_get_reg16(ctx.builder, r2); + codegen::gen_get_reg8(ctx.builder, regs::CL); + ctx.builder.instruction_body.const_i32(31); + ctx.builder.instruction_body.and_i32(); + codegen::gen_call_fn3_ret(ctx.builder, $fn); + ctx.builder.instruction_body.store_aligned_u16(0); + } + ); + + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, reg, $imm:ident) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + let imm = make_imm_read!(ctx, $imm) as i32; + codegen::gen_safe_read_write(ctx, BitSize::WORD, &address_local, &|ref mut ctx| { + codegen::gen_get_reg16(ctx.builder, r); + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn3_ret(ctx.builder, $fn); + }, &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(r as i32); + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn3(ctx.builder, $fallback_fn) + }); + ctx.builder.free_local(address_local); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32, imm: u32) { + let imm = mask_imm!(imm, $imm); + ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r1) as i32); + codegen::gen_get_reg16(ctx.builder, r1); + codegen::gen_get_reg16(ctx.builder, r2); + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn3_ret(ctx.builder, $fn); + ctx.builder.instruction_body.store_aligned_u16(0); + } + ); + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, none) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); @@ -575,6 +632,63 @@ macro_rules! define_instruction_read_write_mem32( } ); + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, reg, cl) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { + codegen::gen_get_reg32(ctx.builder, r); + codegen::gen_get_reg8(ctx.builder, regs::CL); + ctx.builder.instruction_body.const_i32(31); + ctx.builder.instruction_body.and_i32(); + codegen::gen_call_fn3_ret(ctx.builder, $fn); + }, &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_call_fn2(ctx.builder, $fallback_fn) + }); + ctx.builder.free_local(address_local); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { + ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r1) as i32); + codegen::gen_get_reg32(ctx.builder, r1); + codegen::gen_get_reg32(ctx.builder, r2); + codegen::gen_get_reg8(ctx.builder, regs::CL); + ctx.builder.instruction_body.const_i32(31); + ctx.builder.instruction_body.and_i32(); + codegen::gen_call_fn3_ret(ctx.builder, $fn); + ctx.builder.instruction_body.store_aligned_i32(0); + } + ); + + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, reg, $imm:ident) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + let imm = make_imm_read!(ctx, $imm) as i32; + codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { + codegen::gen_get_reg32(ctx.builder, r); + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn3_ret(ctx.builder, $fn); + }, &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(r as i32); + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn3(ctx.builder, $fallback_fn) + }); + ctx.builder.free_local(address_local); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32, imm: u32) { + let imm = mask_imm!(imm, $imm); + ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r1) as i32); + codegen::gen_get_reg32(ctx.builder, r1); + codegen::gen_get_reg32(ctx.builder, r2); + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_call_fn3_ret(ctx.builder, $fn); + ctx.builder.instruction_body.store_aligned_i32(0); + } + ); + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, none) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); @@ -1610,6 +1724,63 @@ pub fn instr32_C3_jit(ctx: &mut JitContext) { ctx.builder.instruction_body.store_aligned_i32(0); } +define_instruction_read_write_mem8!( + "rol8", + "instr_C0_0_mem", + instr_C0_0_mem_jit, + instr_C0_0_reg_jit, + imm8_5bits +); +define_instruction_read_write_mem8!( + "ror8", + "instr_C0_1_mem", + instr_C0_1_mem_jit, + instr_C0_1_reg_jit, + imm8_5bits +); +define_instruction_read_write_mem8!( + "rcl8", + "instr_C0_2_mem", + instr_C0_2_mem_jit, + instr_C0_2_reg_jit, + imm8_5bits +); +define_instruction_read_write_mem8!( + "rcr8", + "instr_C0_3_mem", + instr_C0_3_mem_jit, + instr_C0_3_reg_jit, + imm8_5bits +); +define_instruction_read_write_mem8!( + "shl8", + "instr_C0_4_mem", + instr_C0_4_mem_jit, + instr_C0_4_reg_jit, + imm8_5bits +); +define_instruction_read_write_mem8!( + "shr8", + "instr_C0_5_mem", + instr_C0_5_mem_jit, + instr_C0_5_reg_jit, + imm8_5bits +); +define_instruction_read_write_mem8!( + "shl8", + "instr_C0_6_mem", + instr_C0_6_mem_jit, + instr_C0_6_reg_jit, + imm8_5bits +); +define_instruction_read_write_mem8!( + "sar8", + "instr_C0_7_mem", + instr_C0_7_mem_jit, + instr_C0_7_reg_jit, + imm8_5bits +); + define_instruction_read_write_mem16!( "rol16", "instr16_D1_0_mem", @@ -2391,6 +2562,75 @@ pub fn instr32_F7_1_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { instr32_F7_0_reg_jit(ctx, r, imm) } +define_instruction_read_write_mem16!( + "not16", + "instr16_F7_2_mem", + instr16_F7_2_mem_jit, + instr16_F7_2_reg_jit, + none +); +define_instruction_read_write_mem32!( + "not32", + "instr32_F7_2_mem", + instr32_F7_2_mem_jit, + instr32_F7_2_reg_jit, + none +); +define_instruction_read_write_mem16!( + "neg16", + "instr16_F7_3_mem", + instr16_F7_3_mem_jit, + instr16_F7_3_reg_jit, + none +); +define_instruction_read_write_mem32!( + "neg32", + "instr32_F7_3_mem", + instr32_F7_3_mem_jit, + instr32_F7_3_reg_jit, + none +); + +pub fn instr16_F7_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read16(ctx); + codegen::gen_call_fn1(ctx.builder, "mul16") +} +pub fn instr16_F7_4_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_get_reg16(ctx.builder, r); + codegen::gen_call_fn1(ctx.builder, "mul16") +} +pub fn instr32_F7_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read32(ctx); + codegen::gen_call_fn1(ctx.builder, "mul32") +} +pub fn instr32_F7_4_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_get_reg32(ctx.builder, r); + codegen::gen_call_fn1(ctx.builder, "mul32") +} + +pub fn instr16_F7_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read16(ctx); + codegen::sign_extend_i16(ctx.builder); + codegen::gen_call_fn1(ctx.builder, "imul16") +} +pub fn instr16_F7_5_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_get_reg16(ctx.builder, r); + codegen::sign_extend_i16(ctx.builder); + codegen::gen_call_fn1(ctx.builder, "imul16") +} +pub fn instr32_F7_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read32(ctx); + codegen::gen_call_fn1(ctx.builder, "imul32") +} +pub fn instr32_F7_5_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_get_reg32(ctx.builder, r); + codegen::gen_call_fn1(ctx.builder, "imul32") +} + define_instruction_read_write_mem16!( "inc16", "instr16_FF_0_mem", @@ -2547,6 +2787,72 @@ pub fn instr_0F1F_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) { } pub fn instr_0F1F_reg_jit(_ctx: &mut JitContext, _r1: u32, _r2: u32) {} +define_instruction_read_write_mem16!( + "shld16", + "instr16_0FA4_mem", + instr16_0FA4_mem_jit, + instr16_0FA4_reg_jit, + reg, + imm8_5bits +); +define_instruction_read_write_mem32!( + "shld32", + "instr32_0FA4_mem", + instr32_0FA4_mem_jit, + instr32_0FA4_reg_jit, + reg, + imm8_5bits +); +define_instruction_read_write_mem16!( + "shld16", + "instr16_0FA5_mem", + instr16_0FA5_mem_jit, + instr16_0FA5_reg_jit, + reg, + cl +); +define_instruction_read_write_mem32!( + "shld32", + "instr32_0FA5_mem", + instr32_0FA5_mem_jit, + instr32_0FA5_reg_jit, + reg, + cl +); + +define_instruction_read_write_mem16!( + "shrd16", + "instr16_0FAC_mem", + instr16_0FAC_mem_jit, + instr16_0FAC_reg_jit, + reg, + imm8_5bits +); +define_instruction_read_write_mem32!( + "shrd32", + "instr32_0FAC_mem", + instr32_0FAC_mem_jit, + instr32_0FAC_reg_jit, + reg, + imm8_5bits +); +define_instruction_read_write_mem16!( + "shrd16", + "instr16_0FAD_mem", + instr16_0FAD_mem_jit, + instr16_0FAD_reg_jit, + reg, + cl +); +define_instruction_read_write_mem32!( + "shrd32", + "instr32_0FAD_mem", + instr32_0FAD_mem_jit, + instr32_0FAD_reg_jit, + reg, + cl +); + pub fn instr16_0FB6_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { let builder = &mut ctx.builder; builder @@ -2688,6 +2994,68 @@ pub fn instr32_0FBF_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { ctx.builder.instruction_body.store_aligned_i32(0); } +pub fn instr16_0FC1_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_safe_read_write( + ctx, + BitSize::WORD, + &address_local, + &|ref mut ctx| { + ctx.builder + .instruction_body + .const_i32(::cpu2::cpu::get_reg16_index(r as i32)); + codegen::gen_call_fn2_ret(ctx.builder, "xadd16"); + }, + &|ref mut ctx| { + ctx.builder + .instruction_body + .const_i32(::cpu2::cpu::get_reg16_index(r as i32)); + codegen::gen_call_fn2(ctx.builder, "instr16_0FC1_mem") + }, + ); + ctx.builder.free_local(address_local); +} +pub fn instr16_0FC1_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg16_offset(r1) as i32); + codegen::gen_get_reg16(ctx.builder, r1); + ctx.builder + .instruction_body + .const_i32(::cpu2::cpu::get_reg16_index(r2 as i32)); + codegen::gen_call_fn2_ret(ctx.builder, "xadd16"); + ctx.builder.instruction_body.store_aligned_u16(0); +} + +pub fn instr32_0FC1_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_safe_read_write( + ctx, + BitSize::DWORD, + &address_local, + &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_call_fn2_ret(ctx.builder, "xadd32"); + }, + &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_call_fn2(ctx.builder, "instr32_0FC1_mem") + }, + ); + ctx.builder.free_local(address_local); +} +pub fn instr32_0FC1_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg32_offset(r1) as i32); + codegen::gen_get_reg32(ctx.builder, r1); + ctx.builder.instruction_body.const_i32(r2 as i32); + codegen::gen_call_fn2_ret(ctx.builder, "xadd32"); + ctx.builder.instruction_body.store_aligned_i32(0); +} + pub fn instr_C6_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { // reg8[r] = imm; ctx.builder diff --git a/src/rust/wasmgen/module_init.rs b/src/rust/wasmgen/module_init.rs index ca9dfa96..dac5c0d5 100644 --- a/src/rust/wasmgen/module_init.rs +++ b/src/rust/wasmgen/module_init.rs @@ -33,7 +33,10 @@ pub const FN1_F64_RET_I32_TYPE_INDEX: u8 = 12; #[allow(dead_code)] pub const FN1_F64_RET_I64_TYPE_INDEX: u8 = 13; -pub const NR_FN_TYPE_INDEXES: u8 = 14; +#[allow(dead_code)] +pub const FN3_RET_TYPE_INDEX: u8 = 14; + +pub const NR_FN_TYPE_INDEXES: u8 = 15; pub const WASM_MODULE_ARGUMENT_COUNT: u8 = 1; @@ -294,6 +297,15 @@ impl WasmBuilder { self.output.push(1); self.output.push(op::TYPE_I64); + // FN3_RET + self.output.push(op::TYPE_FUNC); + self.output.push(3); + self.output.push(op::TYPE_I32); + self.output.push(op::TYPE_I32); + self.output.push(op::TYPE_I32); + self.output.push(1); + self.output.push(op::TYPE_I32); + let new_len = self.output.len(); let size = (new_len - 1) - idx_section_size; self.output[idx_section_size] = size.safe_to_u8(); From 440b67eda52d324a4cc1c7a961b98a895d47a3ae Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 6 Dec 2018 16:44:13 -0600 Subject: [PATCH 1525/2137] Support for gen_safe_write128 and code generation for MOVAPS/MOVDQA (0F29/660F7F) --- gen/generate_analyzer.js | 2 +- gen/generate_jit.js | 2 +- gen/x86_table.js | 4 +- src/rust/codegen.rs | 77 +++++++++++++++++++++++++++----- src/rust/cpu.rs | 2 + src/rust/cpu2/cpu.rs | 17 ++++++- src/rust/global_pointers.rs | 10 +++++ src/rust/jit_instructions.rs | 32 +++++++++++++ src/rust/wasmgen/module_init.rs | 12 ++++- src/rust/wasmgen/wasm_opcodes.rs | 1 + src/rust/wasmgen/wasm_util.rs | 7 +++ 11 files changed, 147 insertions(+), 19 deletions(-) diff --git a/gen/generate_analyzer.js b/gen/generate_analyzer.js index 0a1e9200..0e9463f8 100755 --- a/gen/generate_analyzer.js +++ b/gen/generate_analyzer.js @@ -217,7 +217,7 @@ function gen_instruction_body_after_fixed_g(encoding, size) const imm_read = gen_read_imm_call(encoding, size); const instruction_postfix = []; - if(encoding.block_boundary && !encoding.jump_offset_imm || (!encoding.custom && encoding.e) || encoding.sse) + if(encoding.block_boundary && !encoding.jump_offset_imm || (!encoding.custom && encoding.e)) { instruction_postfix.push("analysis.ty = ::analysis::AnalysisType::BlockBoundary;"); } diff --git a/gen/generate_jit.js b/gen/generate_jit.js index 7f649733..2c890734 100755 --- a/gen/generate_jit.js +++ b/gen/generate_jit.js @@ -216,7 +216,7 @@ function gen_instruction_body_after_fixed_g(encoding, size) { const instruction_postfix = []; - if(encoding.block_boundary || (!encoding.custom && encoding.e) || encoding.sse) + if(encoding.block_boundary || (!encoding.custom && encoding.e)) { instruction_postfix.push("*instr_flags |= ::jit::JIT_INSTR_BLOCK_BOUNDARY_FLAG;"); } diff --git a/gen/x86_table.js b/gen/x86_table.js index 58ee21c9..99e13bde 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -645,7 +645,7 @@ const encodings = [ { sse: 1, opcode: 0x0F28, e: 1 }, { sse: 1, opcode: 0x660F28, e: 1 }, - { sse: 1, opcode: 0x0F29, e: 1 }, + { sse: 1, opcode: 0x0F29, e: 1, custom: 1 }, { sse: 1, opcode: 0x660F29, e: 1 }, { sse: 1, opcode: 0x0F2A, e: 1, }, { sse: 1, opcode: 0x660F2A, e: 1, }, @@ -810,7 +810,7 @@ const encodings = [ { sse: 1, opcode: 0x660F7E, e: 1 }, { sse: 1, opcode: 0xF30F7E, e: 1 }, { sse: 1, opcode: 0x0F7F, e: 1 }, - { sse: 1, opcode: 0x660F7F, e: 1 }, + { sse: 1, opcode: 0x660F7F, e: 1, custom: 1 }, { sse: 1, opcode: 0xF30F7F, e: 1 }, { sse: 1, opcode: 0x0FC2, e: 1, imm8: 1 }, diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 0ee855fe..c8db1d2b 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -192,6 +192,12 @@ pub fn gen_call_fn3(builder: &mut WasmBuilder, name: &str) { builder.instruction_body.call_fn(fn_idx); } +pub fn gen_call_fn3_i32_i64_i64(builder: &mut WasmBuilder, name: &str) { + // generates: fn( _, _ ) where _ must be left on the stack before calling this + let fn_idx = builder.get_fn_idx(name, module_init::FN3_I32_I64_I64_TYPE_INDEX); + builder.instruction_body.call_fn(fn_idx); +} + pub fn gen_call_fn3_ret(builder: &mut WasmBuilder, name: &str) { let fn_idx = builder.get_fn_idx(name, module_init::FN3_RET_TYPE_INDEX); builder.instruction_body.call_fn(fn_idx); @@ -262,9 +268,10 @@ pub fn gen_safe_read32(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::DWORD pub fn gen_safe_read64(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::QWORD) } // only used internally for gen_safe_write -enum I32OrI64Local<'a> { +enum GenSafeWriteValue<'a> { I32(&'a WasmLocal), I64(&'a WasmLocalI64), + TwoI64s(&'a WasmLocalI64, &'a WasmLocalI64), } pub fn gen_safe_write8(ctx: &mut JitContext, address_local: &WasmLocal, value_local: &WasmLocal) { @@ -272,7 +279,7 @@ pub fn gen_safe_write8(ctx: &mut JitContext, address_local: &WasmLocal, value_lo ctx, BitSize::BYTE, address_local, - I32OrI64Local::I32(value_local), + GenSafeWriteValue::I32(value_local), ) } pub fn gen_safe_write16(ctx: &mut JitContext, address_local: &WasmLocal, value_local: &WasmLocal) { @@ -280,7 +287,7 @@ pub fn gen_safe_write16(ctx: &mut JitContext, address_local: &WasmLocal, value_l ctx, BitSize::WORD, address_local, - I32OrI64Local::I32(value_local), + GenSafeWriteValue::I32(value_local), ) } pub fn gen_safe_write32(ctx: &mut JitContext, address_local: &WasmLocal, value_local: &WasmLocal) { @@ -288,7 +295,7 @@ pub fn gen_safe_write32(ctx: &mut JitContext, address_local: &WasmLocal, value_l ctx, BitSize::DWORD, address_local, - I32OrI64Local::I32(value_local), + GenSafeWriteValue::I32(value_local), ) } pub fn gen_safe_write64( @@ -300,7 +307,21 @@ pub fn gen_safe_write64( ctx, BitSize::QWORD, address_local, - I32OrI64Local::I64(value_local), + GenSafeWriteValue::I64(value_local), + ) +} + +pub fn gen_safe_write128( + ctx: &mut JitContext, + address_local: &WasmLocal, + value_local_low: &WasmLocalI64, + value_local_high: &WasmLocalI64, +) { + gen_safe_write( + ctx, + BitSize::DQWORD, + address_local, + GenSafeWriteValue::TwoI64s(value_local_low, value_local_high), ) } @@ -392,6 +413,9 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { .instruction_body .load_unaligned_i64_from_stack(unsafe { mem8 } as u32); }, + BitSize::DQWORD => { + assert!(false); // TODO + }, } // Pseudo: @@ -438,6 +462,9 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { BitSize::QWORD => { gen_call_fn1_ret_i64(builder, "safe_read64s_slow_jit"); }, + BitSize::DQWORD => { + assert!(false); // TODO + }, } builder @@ -459,7 +486,7 @@ fn gen_safe_write( ctx: &mut JitContext, bits: BitSize, address_local: &WasmLocal, - value_local: I32OrI64Local, + value_local: GenSafeWriteValue, ) { // Generates safe_writeXX' fast-path inline, bailing to safe_writeXX_slow if necessary. @@ -524,8 +551,24 @@ fn gen_safe_write( // mem8[phys_addr] = value; match value_local { - I32OrI64Local::I32(local) => builder.instruction_body.get_local(local), - I32OrI64Local::I64(local) => builder.instruction_body.get_local_i64(local), + GenSafeWriteValue::I32(local) => builder.instruction_body.get_local(local), + GenSafeWriteValue::I64(local) => builder.instruction_body.get_local_i64(local), + GenSafeWriteValue::TwoI64s(local1, local2) => { + assert!(bits == BitSize::DQWORD); + + let virt_address_local = builder.tee_new_local(); + builder.instruction_body.get_local_i64(local1); + builder + .instruction_body + .store_unaligned_i64(unsafe { mem8 } as u32); + + builder.instruction_body.get_local(&virt_address_local); + builder.instruction_body.get_local_i64(local2); + builder + .instruction_body + .store_unaligned_i64(unsafe { mem8 } as u32 + 8); + builder.free_local(virt_address_local); + }, } match bits { BitSize::BYTE => { @@ -546,6 +589,7 @@ fn gen_safe_write( .instruction_body .store_unaligned_i64(unsafe { mem8 } as u32); }, + BitSize::DQWORD => {}, // handled above } // Pseudo: @@ -580,8 +624,12 @@ fn gen_safe_write( builder.instruction_body.get_local(&address_local); match value_local { - I32OrI64Local::I32(local) => builder.instruction_body.get_local(local), - I32OrI64Local::I64(local) => builder.instruction_body.get_local_i64(local), + GenSafeWriteValue::I32(local) => builder.instruction_body.get_local(local), + GenSafeWriteValue::I64(local) => builder.instruction_body.get_local_i64(local), + GenSafeWriteValue::TwoI64s(local1, local2) => { + builder.instruction_body.get_local_i64(local1); + builder.instruction_body.get_local_i64(local2) + }, } match bits { BitSize::BYTE => { @@ -596,6 +644,9 @@ fn gen_safe_write( BitSize::QWORD => { gen_call_fn2_i32_i64(builder, "safe_write64_slow_jit"); }, + BitSize::DQWORD => { + gen_call_fn3_i32_i64_i64(builder, "safe_write128_slow_jit"); + }, } builder @@ -999,7 +1050,8 @@ pub fn gen_safe_read_write( .instruction_body .load_unaligned_i32_from_stack(unsafe { mem8 } as u32); }, - BitSize::QWORD => assert!(false), // not used + BitSize::QWORD => assert!(false), // not used + BitSize::DQWORD => assert!(false), // not used } f(ctx); @@ -1020,7 +1072,8 @@ pub fn gen_safe_read_write( .instruction_body .store_unaligned_i32(unsafe { mem8 } as u32); }, - BitSize::QWORD => assert!(false), // not used + BitSize::QWORD => assert!(false), // not used + BitSize::DQWORD => assert!(false), // not used }; ctx.builder.free_local(phys_addr_local); diff --git a/src/rust/cpu.rs b/src/rust/cpu.rs index f407ac58..3e8ecfa1 100644 --- a/src/rust/cpu.rs +++ b/src/rust/cpu.rs @@ -24,6 +24,7 @@ pub enum BitSize { WORD, DWORD, QWORD, + DQWORD, } impl BitSize { pub fn bytes(&self) -> u32 { @@ -32,6 +33,7 @@ impl BitSize { BitSize::WORD => 2, BitSize::DWORD => 4, BitSize::QWORD => 8, + BitSize::DQWORD => 16, } } } diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index e733423b..aa6309b8 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -2094,7 +2094,7 @@ pub fn report_safe_read_jit_slow(address: u32, entry: i32) { else if entry & TLB_NO_USER != 0 { profiler::stat_increment(SAFE_READ_SLOW_NOT_USER); } - else if address & 0xFFF > 0x1000 - 4 { + else if address & 0xFFF > 0x1000 - 16 { profiler::stat_increment(SAFE_READ_SLOW_PAGE_CROSSED); } else { @@ -2121,7 +2121,7 @@ pub fn report_safe_write_jit_slow(address: u32, entry: i32) { else if entry & TLB_NO_USER != 0 { profiler::stat_increment(SAFE_WRITE_SLOW_NOT_USER); } - else if address & 0xFFF > 0x1000 - 4 { + else if address & 0xFFF > 0x1000 - 16 { profiler::stat_increment(SAFE_WRITE_SLOW_PAGE_CROSSED); } else { @@ -2375,6 +2375,19 @@ pub unsafe fn safe_write128(addr: i32, value: reg128) -> OrPageFault<()> { Ok(()) } +#[no_mangle] +pub unsafe fn safe_write128_slow_jit(addr: i32, value_low: i64, value_high: i64) { + match safe_write128( + addr, + reg128 { + i64_0: [value_low, value_high], + }, + ) { + Ok(()) => *page_fault = false, + Err(()) => *page_fault = true, + } +} + pub fn get_reg8_index(index: i32) -> i32 { return index << 2 & 12 | index >> 2 & 1; } pub unsafe fn read_reg8(index: i32) -> i32 { diff --git a/src/rust/global_pointers.rs b/src/rust/global_pointers.rs index 6e00cf8d..957ef895 100644 --- a/src/rust/global_pointers.rs +++ b/src/rust/global_pointers.rs @@ -8,6 +8,7 @@ pub const TIMESTAMP_COUNTER: u32 = 664; pub const SEGMENT_OFFSETS: u32 = 736; pub const OPSTATS_BUFFER: u32 = 0x1000; pub const OPSTATS_BUFFER_0F: u32 = 0x1400; +pub const REG_XMM: u32 = 828; pub const FPU_CONTROL_WORD: u32 = 1036; pub const TLB_DATA: u32 = 0x400000; @@ -24,6 +25,15 @@ pub fn get_reg32_offset(r: u32) -> u32 { REG + 4 * r } +pub fn get_reg_xmm_low_offset(r: u32) -> u32 { + dbg_assert!(r < 8); + REG_XMM + 16 * r +} +pub fn get_reg_xmm_high_offset(r: u32) -> u32 { + dbg_assert!(r < 8); + REG_XMM + 16 * r + 8 +} + pub fn get_seg_offset(s: u32) -> u32 { dbg_assert!(s < 8); SEGMENT_OFFSETS + 4 * s diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 14e93c43..70df14ae 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -3236,3 +3236,35 @@ define_setcc!("test_l", instr_0F9C_mem_jit, instr_0F9C_reg_jit); define_setcc!("test_nl", instr_0F9D_mem_jit, instr_0F9D_reg_jit); define_setcc!("test_le", instr_0F9E_mem_jit, instr_0F9E_reg_jit); define_setcc!("test_nle", instr_0F9F_mem_jit, instr_0F9F_reg_jit); + +pub fn instr_0F29_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + // XXX: Aligned write or #gp + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg_xmm_low_offset(r) as i32); + ctx.builder.instruction_body.load_aligned_i64_from_stack(0); + let value_local_low = ctx.builder.set_new_local_i64(); + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg_xmm_high_offset(r) as i32); + ctx.builder.instruction_body.load_aligned_i64_from_stack(0); + let value_local_high = ctx.builder.set_new_local_i64(); + codegen::gen_safe_write128(ctx, &address_local, &value_local_low, &value_local_high); + ctx.builder.free_local(address_local); + ctx.builder.free_local_i64(value_local_low); + ctx.builder.free_local_i64(value_local_high); +} +pub fn instr_0F29_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + ctx.builder.instruction_body.const_i32(r1 as i32); + ctx.builder.instruction_body.const_i32(r2 as i32); + codegen::gen_call_fn2(ctx.builder, "instr_0F29_reg") +} + +pub fn instr_660F7F_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + instr_0F29_mem_jit(ctx, modrm_byte, r); +} +pub fn instr_660F7F_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + instr_0F29_reg_jit(ctx, r1, r2) +} diff --git a/src/rust/wasmgen/module_init.rs b/src/rust/wasmgen/module_init.rs index dac5c0d5..00f5e88a 100644 --- a/src/rust/wasmgen/module_init.rs +++ b/src/rust/wasmgen/module_init.rs @@ -35,8 +35,10 @@ pub const FN1_F64_RET_I64_TYPE_INDEX: u8 = 13; #[allow(dead_code)] pub const FN3_RET_TYPE_INDEX: u8 = 14; +#[allow(dead_code)] +pub const FN3_I32_I64_I64_TYPE_INDEX: u8 = 15; -pub const NR_FN_TYPE_INDEXES: u8 = 15; +pub const NR_FN_TYPE_INDEXES: u8 = 16; pub const WASM_MODULE_ARGUMENT_COUNT: u8 = 1; @@ -306,6 +308,14 @@ impl WasmBuilder { self.output.push(1); self.output.push(op::TYPE_I32); + // FN3_I32_I64_I64 + self.output.push(op::TYPE_FUNC); + self.output.push(3); + self.output.push(op::TYPE_I32); + self.output.push(op::TYPE_I64); + self.output.push(op::TYPE_I64); + self.output.push(0); + let new_len = self.output.len(); let size = (new_len - 1) - idx_section_size; self.output[idx_section_size] = size.safe_to_u8(); diff --git a/src/rust/wasmgen/wasm_opcodes.rs b/src/rust/wasmgen/wasm_opcodes.rs index cd26f2b5..d50f9929 100644 --- a/src/rust/wasmgen/wasm_opcodes.rs +++ b/src/rust/wasmgen/wasm_opcodes.rs @@ -218,3 +218,4 @@ c!(OP_F64REINTERPRETI64, 0xbf); c!(MEM_NO_ALIGN, 0); c!(MEM_ALIGN16, 1); c!(MEM_ALIGN32, 2); +c!(MEM_ALIGN64, 3); diff --git a/src/rust/wasmgen/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs index 801e5bfa..7ee22ce5 100644 --- a/src/rust/wasmgen/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -32,6 +32,7 @@ pub trait WasmBuf { fn load_unaligned_i64_from_stack(&mut self, byte_offset: u32); fn load_unaligned_i32_from_stack(&mut self, byte_offset: u32); fn load_unaligned_u16_from_stack(&mut self, byte_offset: u32); + fn load_aligned_i64_from_stack(&mut self, byte_offset: u32); fn load_aligned_i32_from_stack(&mut self, byte_offset: u32); fn load_aligned_u16_from_stack(&mut self, byte_offset: u32); @@ -183,6 +184,12 @@ impl WasmBuf for Vec { self.write_leb_u32(byte_offset); } + fn load_aligned_i64_from_stack(&mut self, byte_offset: u32) { + self.push(op::OP_I64LOAD); + self.push(op::MEM_ALIGN64); + self.write_leb_u32(byte_offset); + } + fn load_aligned_i32_from_stack(&mut self, byte_offset: u32) { self.push(op::OP_I32LOAD); self.push(op::MEM_ALIGN32); From dca6be2d94dd825a99218a7b85387c617069f63d Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 8 Dec 2018 15:44:46 -0600 Subject: [PATCH 1526/2137] Also generate nop for prefetch instruction --- gen/x86_table.js | 2 +- src/rust/jit_instructions.rs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 99e13bde..299fda02 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -448,7 +448,7 @@ const encodings = [ { opcode: 0x0F0E, skip: 1, block_boundary: 1, }, { opcode: 0x0F0F, skip: 1, block_boundary: 1, }, - { opcode: 0x0F18, e: 1, }, + { opcode: 0x0F18, e: 1, custom: 1 }, { opcode: 0x0F19, non_faulting: 1, custom: 1, e: 1, }, { opcode: 0x0F1A, skip: 1, block_boundary: 1, }, { opcode: 0x0F1B, skip: 1, block_boundary: 1, }, diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 70df14ae..adb2e29b 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -2765,6 +2765,11 @@ pub fn instr32_A3_jit(ctx: &mut JitContext, immaddr: u32) { ctx.builder.free_local(value_local); } +pub fn instr_0F18_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) { + modrm::skip(ctx.cpu, modrm_byte); +} +pub fn instr_0F18_reg_jit(_ctx: &mut JitContext, _r1: u32, _r2: u32) {} + pub fn instr_0F19_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) { modrm::skip(ctx.cpu, modrm_byte); } From 70cc242eb1d4c446ada934a28be7bba144b8da80 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 9 Dec 2018 20:26:47 -0600 Subject: [PATCH 1527/2137] Simplify call_interrupt_vector from js --- src/cpu.js | 8 +------- src/rust/cpu2/cpu.rs | 22 ++++++---------------- 2 files changed, 7 insertions(+), 23 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index 087934b5..78231a1e 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -271,7 +271,7 @@ CPU.prototype.wasm_patch = function(wm) this.trigger_ss = get_import("trigger_ss"); this.switch_cs_real_mode = get_import("switch_cs_real_mode"); - this.call_interrupt_vector = get_import("call_interrupt_vector_js"); + this.pic_call_irq = get_import("pic_call_irq"); this.get_tss_stack_addr = get_import("get_tss_stack_addr_js"); this.do_many_cycles_native = get_import("do_many_cycles_native"); @@ -2370,12 +2370,6 @@ CPU.prototype.unimplemented_sse = function() this.trigger_ud(); }; -CPU.prototype.pic_call_irq = function(int) -{ - this.previous_ip[0] = this.instruction_pointer[0]; // XXX: What if called after instruction (port IO) - this.call_interrupt_vector(int, false, false, 0); -}; - CPU.prototype.handle_irqs = function() { //dbg_assert(this.prefixes[0] === 0); diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index aa6309b8..7fdaaefe 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -363,22 +363,6 @@ impl InterruptDescriptor { const TRAP_GATE: u8 = 0b111; } -#[no_mangle] -pub unsafe fn call_interrupt_vector_js( - interrupt_nr: i32, - is_software_int: bool, - has_error_code: bool, - error_code: i32, -) { - let ec = if has_error_code { - Some(error_code) - } - else { - None - }; - call_interrupt_vector(interrupt_nr, is_software_int, ec); -} - #[no_mangle] pub unsafe fn switch_cs_real_mode(selector: i32) { dbg_assert!(!*protected_mode || vm86_mode()); @@ -2809,3 +2793,9 @@ pub unsafe fn handle_irqs() { pic_acknowledge() } } + +#[no_mangle] +pub unsafe fn pic_call_irq(interrupt_nr: i32) { + *previous_ip = *instruction_pointer; // XXX: What if called after instruction (port IO) + call_interrupt_vector(interrupt_nr, false, None); +} From 2837ccd06ba9799c3eadffdb25077e955011e556 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 10 Dec 2018 09:34:11 -0600 Subject: [PATCH 1528/2137] Support for gen_safe_read128 and code generation for MOVDQU (F30F6F) --- gen/x86_table.js | 2 +- src/rust/codegen.rs | 46 +++++++++++++++++++++++++++++------- src/rust/cpu2/cpu.rs | 13 ++++++++++ src/rust/jit_instructions.rs | 11 +++++++++ 4 files changed, 63 insertions(+), 9 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 299fda02..50a9b467 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -759,7 +759,7 @@ const encodings = [ { sse: 1, opcode: 0x0F6D, e: 1, block_boundary: 1, }, // ud { sse: 1, opcode: 0x660F6E, e: 1 }, { sse: 1, opcode: 0x0F6E, e: 1 }, - { sse: 1, opcode: 0xF30F6F, e: 1 }, + { sse: 1, opcode: 0xF30F6F, e: 1, custom: 1 }, { sse: 1, opcode: 0x660F6F, e: 1 }, { sse: 1, opcode: 0x0F6F, e: 1 }, diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index c8db1d2b..ee751c70 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -262,10 +262,13 @@ pub fn gen_set_reg32_r(ctx: &mut JitContext, dest: u32, src: u32) { builder.instruction_body.store_aligned_i32(0); } -pub fn gen_safe_read8(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::BYTE) } -pub fn gen_safe_read16(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::WORD) } -pub fn gen_safe_read32(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::DWORD) } -pub fn gen_safe_read64(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::QWORD) } +pub fn gen_safe_read8(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::BYTE, None) } +pub fn gen_safe_read16(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::WORD, None) } +pub fn gen_safe_read32(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::DWORD, None) } +pub fn gen_safe_read64(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::QWORD, None) } +pub fn gen_safe_read128(ctx: &mut JitContext, where_to_write: u32) { + gen_safe_read(ctx, BitSize::DQWORD, Some(where_to_write)) +} // only used internally for gen_safe_write enum GenSafeWriteValue<'a> { @@ -325,7 +328,7 @@ pub fn gen_safe_write128( ) } -fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { +fn gen_safe_read(ctx: &mut JitContext, bits: BitSize, where_to_write: Option) { // Assumes virtual address has been pushed to the stack, and generates safe_readXX's fast-path // inline, bailing to safe_readXX_slow if necessary let builder = &mut ctx.builder; @@ -375,7 +378,10 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { // Pseudo: // if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]); - if bits == BitSize::QWORD { + if bits == BitSize::DQWORD { + builder.instruction_body.if_void(); + } + else if bits == BitSize::QWORD { builder.instruction_body.if_i64(); } else { @@ -392,6 +398,9 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { builder.instruction_body.get_local(&address_local); builder.instruction_body.xor_i32(); + // where_to_write is only used by dqword + dbg_assert!((where_to_write != None) == (bits == BitSize::DQWORD)); + match bits { BitSize::BYTE => { builder @@ -414,7 +423,25 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { .load_unaligned_i64_from_stack(unsafe { mem8 } as u32); }, BitSize::DQWORD => { - assert!(false); // TODO + let where_to_write = where_to_write.unwrap(); + let virt_address_local = builder.set_new_local(); + builder.instruction_body.const_i32(0); + builder.instruction_body.get_local(&virt_address_local); + builder + .instruction_body + .load_unaligned_i64_from_stack(unsafe { mem8 } as u32); + builder.instruction_body.store_unaligned_i64(where_to_write); + + builder.instruction_body.const_i32(0); + builder.instruction_body.get_local(&virt_address_local); + builder + .instruction_body + .load_unaligned_i64_from_stack(unsafe { mem8 } as u32 + 8); + builder + .instruction_body + .store_unaligned_i64(where_to_write + 8); + + builder.free_local(virt_address_local); }, } @@ -463,7 +490,10 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) { gen_call_fn1_ret_i64(builder, "safe_read64s_slow_jit"); }, BitSize::DQWORD => { - assert!(false); // TODO + builder + .instruction_body + .const_i32(where_to_write.unwrap() as i32); + gen_call_fn2(builder, "safe_read128s_slow_jit"); }, } diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 7fdaaefe..4e0fcca8 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -2204,6 +2204,19 @@ pub unsafe fn safe_read128s(addr: i32) -> OrPageFault { Ok(x) } +#[no_mangle] +pub unsafe fn safe_read128s_slow_jit(addr: i32, where_to_write: u32) { + match safe_read128s(addr) { + Ok(v) => { + *page_fault = false; + *(where_to_write as *mut reg128) = v; + }, + Err(()) => { + *page_fault = true; + }, + } +} + pub unsafe fn safe_write8(addr: i32, value: i32) -> OrPageFault<()> { write8(translate_address_write(addr)?, value); Ok(()) diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index adb2e29b..113f4c2f 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -3267,6 +3267,17 @@ pub fn instr_0F29_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_call_fn2(ctx.builder, "instr_0F29_reg") } +pub fn instr_F30F6F_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let dest = global_pointers::get_reg_xmm_low_offset(r); + codegen::gen_safe_read128(ctx, dest); +} +pub fn instr_F30F6F_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + ctx.builder.instruction_body.const_i32(r1 as i32); + ctx.builder.instruction_body.const_i32(r2 as i32); + codegen::gen_call_fn2(ctx.builder, "instr_F30F6F_reg") +} + pub fn instr_660F7F_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { instr_0F29_mem_jit(ctx, modrm_byte, r); } From 2c23ffc2cfa2e0f1725552546f60160bf19e6326 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 10 Dec 2018 09:37:40 -0600 Subject: [PATCH 1529/2137] Use get_eflags_no_arith over flags[0] (minor performance) --- src/cpu.js | 9 +++++---- src/rust/cpu2/cpu.rs | 3 +++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index 78231a1e..347f1c23 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -263,6 +263,7 @@ CPU.prototype.wasm_patch = function(wm) this.getiopl = get_import("getiopl"); this.vm86_mode = get_import("vm86_mode"); this.get_eflags = get_import("get_eflags"); + this.get_eflags_no_arith = get_import("get_eflags_no_arith"); this.update_eflags = get_import("update_eflags"); this.trigger_gp_non_raising = get_import("trigger_gp_non_raising"); @@ -1534,7 +1535,7 @@ CPU.prototype.dbg_assert = function(x) CPU.prototype.hlt_loop = function() { - if(this.flags[0] & flag_interrupt) + if(this.get_eflags_no_arith() & flag_interrupt) { //dbg_log("In HLT loop", LOG_CPU); @@ -2341,7 +2342,7 @@ CPU.prototype.hlt_op = function() return; } - if((this.flags[0] & flag_interrupt) === 0) + if((this.get_eflags_no_arith() & flag_interrupt) === 0) { // execution can never resume (until NMIs are supported) this.bus.send("cpu-event-halt"); @@ -2374,7 +2375,7 @@ CPU.prototype.handle_irqs = function() { //dbg_assert(this.prefixes[0] === 0); - if(this.flags[0] & flag_interrupt) + if(this.get_eflags_no_arith() & flag_interrupt) { this.pic_acknowledge(); } @@ -2382,7 +2383,7 @@ CPU.prototype.handle_irqs = function() CPU.prototype.pic_acknowledge = function() { - dbg_assert(this.flags[0] & flag_interrupt); + dbg_assert(this.get_eflags_no_arith() & flag_interrupt); if(this.devices.pic) { diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 4e0fcca8..ced90c28 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1010,6 +1010,9 @@ pub unsafe fn get_eflags() -> i32 { | (getof() as i32) << 11; } +#[no_mangle] +pub unsafe fn get_eflags_no_arith() -> i32 { return *flags; } + pub unsafe fn translate_address_read(address: i32) -> OrPageFault { let base: i32 = (address as u32 >> 12) as i32; let entry: i32 = *tlb_data.offset(base as isize); From 958fb7b9d6d2607f4f4c801b5670848135a7cb5c Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 10 Dec 2018 09:50:31 -0600 Subject: [PATCH 1530/2137] Update expect tests --- tests/expect/tests/call.wast | 2 ++ tests/expect/tests/do-while.wast | 2 ++ tests/expect/tests/if.wast | 2 ++ tests/expect/tests/indirect-call.wast | 2 ++ tests/expect/tests/mov16.wast | 2 ++ tests/expect/tests/mov32-mem.wast | 2 ++ tests/expect/tests/mov32-reg.wast | 2 ++ tests/expect/tests/pop.wast | 2 ++ tests/expect/tests/push.wast | 2 ++ tests/expect/tests/task_switch_test.wast | 2 ++ tests/expect/tests/task_switch_test_sse.wast | 2 ++ tests/expect/tests/while-do.wast | 2 ++ 12 files changed, 24 insertions(+) diff --git a/tests/expect/tests/call.wast b/tests/expect/tests/call.wast index 97258b48..ea6b37e1 100644 --- a/tests/expect/tests/call.wast +++ b/tests/expect/tests/call.wast @@ -13,6 +13,8 @@ (type $t11 (func (param i32 i64))) (type $t12 (func (param f64) (result i32))) (type $t13 (func (param f64) (result i64))) + (type $t14 (func (param i32 i32 i32) (result i32))) + (type $t15 (func (param i32 i64 i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "safe_write32_slow_jit" (func $e.safe_write32_slow_jit (type $t2))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) diff --git a/tests/expect/tests/do-while.wast b/tests/expect/tests/do-while.wast index 3cc37555..2ab4909b 100644 --- a/tests/expect/tests/do-while.wast +++ b/tests/expect/tests/do-while.wast @@ -13,6 +13,8 @@ (type $t11 (func (param i32 i64))) (type $t12 (func (param f64) (result i32))) (type $t13 (func (param f64) (result i64))) + (type $t14 (func (param i32 i32 i32) (result i32))) + (type $t15 (func (param i32 i64 i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "instr32_43" (func $e.instr32_43 (type $t0))) (import "e" "cmp32" (func $e.cmp32 (type $t2))) diff --git a/tests/expect/tests/if.wast b/tests/expect/tests/if.wast index 294b8445..c083dccb 100644 --- a/tests/expect/tests/if.wast +++ b/tests/expect/tests/if.wast @@ -13,6 +13,8 @@ (type $t11 (func (param i32 i64))) (type $t12 (func (param f64) (result i32))) (type $t13 (func (param f64) (result i64))) + (type $t14 (func (param i32 i32 i32) (result i32))) + (type $t15 (func (param i32 i64 i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "cmp32" (func $e.cmp32 (type $t2))) (import "e" "test_nle" (func $e.test_nle (type $t4))) diff --git a/tests/expect/tests/indirect-call.wast b/tests/expect/tests/indirect-call.wast index 67be19be..05c14952 100644 --- a/tests/expect/tests/indirect-call.wast +++ b/tests/expect/tests/indirect-call.wast @@ -13,6 +13,8 @@ (type $t11 (func (param i32 i64))) (type $t12 (func (param f64) (result i32))) (type $t13 (func (param f64) (result i64))) + (type $t14 (func (param i32 i32 i32) (result i32))) + (type $t15 (func (param i32 i64 i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "instr32_FF_2_mem" (func $e.instr32_FF_2_mem (type $t1))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) diff --git a/tests/expect/tests/mov16.wast b/tests/expect/tests/mov16.wast index ee3b62d7..0f5f8e3e 100644 --- a/tests/expect/tests/mov16.wast +++ b/tests/expect/tests/mov16.wast @@ -13,6 +13,8 @@ (type $t11 (func (param i32 i64))) (type $t12 (func (param f64) (result i32))) (type $t13 (func (param f64) (result i64))) + (type $t14 (func (param i32 i32 i32) (result i32))) + (type $t15 (func (param i32 i64 i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "instr16_B8" (func $e.instr16_B8 (type $t1))) (import "e" "safe_read16_slow_jit" (func $e.safe_read16_slow_jit (type $t5))) diff --git a/tests/expect/tests/mov32-mem.wast b/tests/expect/tests/mov32-mem.wast index 0a646a0d..f52970a0 100644 --- a/tests/expect/tests/mov32-mem.wast +++ b/tests/expect/tests/mov32-mem.wast @@ -13,6 +13,8 @@ (type $t11 (func (param i32 i64))) (type $t12 (func (param f64) (result i32))) (type $t13 (func (param f64) (result i64))) + (type $t14 (func (param i32 i32 i32) (result i32))) + (type $t15 (func (param i32 i64 i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "safe_write32_slow_jit" (func $e.safe_write32_slow_jit (type $t2))) (import "e" "safe_read32s_slow_jit" (func $e.safe_read32s_slow_jit (type $t5))) diff --git a/tests/expect/tests/mov32-reg.wast b/tests/expect/tests/mov32-reg.wast index 2e7d1553..8600e047 100644 --- a/tests/expect/tests/mov32-reg.wast +++ b/tests/expect/tests/mov32-reg.wast @@ -13,6 +13,8 @@ (type $t11 (func (param i32 i64))) (type $t12 (func (param f64) (result i32))) (type $t13 (func (param f64) (result i64))) + (type $t14 (func (param i32 i32 i32) (result i32))) + (type $t15 (func (param i32 i64 i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "instr32_B8" (func $e.instr32_B8 (type $t1))) (import "e" "instr32_B9" (func $e.instr32_B9 (type $t1))) diff --git a/tests/expect/tests/pop.wast b/tests/expect/tests/pop.wast index c3d04718..b11b2e16 100644 --- a/tests/expect/tests/pop.wast +++ b/tests/expect/tests/pop.wast @@ -13,6 +13,8 @@ (type $t11 (func (param i32 i64))) (type $t12 (func (param f64) (result i32))) (type $t13 (func (param f64) (result i64))) + (type $t14 (func (param i32 i32 i32) (result i32))) + (type $t15 (func (param i32 i64 i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "safe_read32s_slow_jit" (func $e.safe_read32s_slow_jit (type $t5))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) diff --git a/tests/expect/tests/push.wast b/tests/expect/tests/push.wast index 4c40292b..b178d2a0 100644 --- a/tests/expect/tests/push.wast +++ b/tests/expect/tests/push.wast @@ -13,6 +13,8 @@ (type $t11 (func (param i32 i64))) (type $t12 (func (param f64) (result i32))) (type $t13 (func (param f64) (result i64))) + (type $t14 (func (param i32 i32 i32) (result i32))) + (type $t15 (func (param i32 i64 i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "safe_write32_slow_jit" (func $e.safe_write32_slow_jit (type $t2))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) diff --git a/tests/expect/tests/task_switch_test.wast b/tests/expect/tests/task_switch_test.wast index 436f2ec6..73fcf3e7 100644 --- a/tests/expect/tests/task_switch_test.wast +++ b/tests/expect/tests/task_switch_test.wast @@ -13,6 +13,8 @@ (type $t11 (func (param i32 i64))) (type $t12 (func (param f64) (result i32))) (type $t13 (func (param f64) (result i64))) + (type $t14 (func (param i32 i32 i32) (result i32))) + (type $t15 (func (param i32 i64 i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "task_switch_test_void" (func $e.task_switch_test_void (type $t0))) (import "e" "fpu_get_sti" (func $e.fpu_get_sti (type $t7))) diff --git a/tests/expect/tests/task_switch_test_sse.wast b/tests/expect/tests/task_switch_test_sse.wast index f84e21eb..0cd438f1 100644 --- a/tests/expect/tests/task_switch_test_sse.wast +++ b/tests/expect/tests/task_switch_test_sse.wast @@ -13,6 +13,8 @@ (type $t11 (func (param i32 i64))) (type $t12 (func (param f64) (result i32))) (type $t13 (func (param f64) (result i64))) + (type $t14 (func (param i32 i32 i32) (result i32))) + (type $t15 (func (param i32 i64 i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "task_switch_test_mmx_void" (func $e.task_switch_test_mmx_void (type $t0))) (import "e" "instr_660F54_reg" (func $e.instr_660F54_reg (type $t2))) diff --git a/tests/expect/tests/while-do.wast b/tests/expect/tests/while-do.wast index b2e4966b..858d7ba4 100644 --- a/tests/expect/tests/while-do.wast +++ b/tests/expect/tests/while-do.wast @@ -13,6 +13,8 @@ (type $t11 (func (param i32 i64))) (type $t12 (func (param f64) (result i32))) (type $t13 (func (param f64) (result i64))) + (type $t14 (func (param i32 i32 i32) (result i32))) + (type $t15 (func (param i32 i64 i64))) (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "cmp32" (func $e.cmp32 (type $t2))) (import "e" "test_z" (func $e.test_z (type $t4))) From 5a085f32e30a25ad97b07d890526096b9b9e5279 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 5 Dec 2018 10:12:10 +1300 Subject: [PATCH 1531/2137] Filestorage tests: Check for unexpected early exits --- tests/devices/filestorage.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/devices/filestorage.js b/tests/devices/filestorage.js index c9f31186..90be16d3 100755 --- a/tests/devices/filestorage.js +++ b/tests/devices/filestorage.js @@ -161,8 +161,19 @@ async function test_with_file(oracle, iut, key, file_data) // jshint ignore:line return true; } +function on_unexpected_exit(exit_code) +{ + if(exit_code === 0) + { + log_fail("Event loop unexpectedly empty."); + process.exit(1); + } +} + async function test_start() // jshint ignore:line { + process.on("exit", on_unexpected_exit); + // Test oracle without chunking. const oracle = new MemoryFileStorage(); @@ -182,6 +193,7 @@ async function test_start() // jshint ignore:line } log_pass("All tests passed!"); + process.removeListener("exit", on_unexpected_exit); return true; } From 79928bae4d7bbfcbb9a7510f2e607295b97bd5af Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 5 Dec 2018 10:12:53 +1300 Subject: [PATCH 1532/2137] Filestorage tests: Mock transaction.abort and store.count --- tests/devices/filestorage.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/devices/filestorage.js b/tests/devices/filestorage.js index 90be16d3..05732e61 100755 --- a/tests/devices/filestorage.js +++ b/tests/devices/filestorage.js @@ -68,6 +68,13 @@ function mock_indexeddb() mock_request_completion(request); return request; }, + count(key) { + assert_transaction_active(`get ${key}`); + const result = db.get(key) ? 1 : 0; + const request = { result }; + mock_request_completion(request); + return request; + }, put(value) { assert_transaction_active(`put ${value}`); const key = value["sha256sum"]; @@ -78,6 +85,9 @@ function mock_indexeddb() }, }; }, + abort() { + // No-op. + }, }; let completed = false; From 1d410540013cf964551484271d034f2cefdec361 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 5 Dec 2018 10:15:48 +1300 Subject: [PATCH 1533/2137] style(Filestorage tests): Move openning braces to new lines --- tests/devices/filestorage.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/tests/devices/filestorage.js b/tests/devices/filestorage.js index 05732e61..4ea96fa5 100755 --- a/tests/devices/filestorage.js +++ b/tests/devices/filestorage.js @@ -57,25 +57,30 @@ function mock_indexeddb() { const db = new Map(); return { - transaction(store_name, mode) { + transaction(store_name, mode) + { const transaction = { - objectStore(store_name) { + objectStore(store_name) + { return { - get(key) { + get(key) + { assert_transaction_active(`get ${key}`); const result = db.get(key); const request = { result }; mock_request_completion(request); return request; }, - count(key) { + count(key) + { assert_transaction_active(`get ${key}`); const result = db.get(key) ? 1 : 0; const request = { result }; mock_request_completion(request); return request; }, - put(value) { + put(value) + { assert_transaction_active(`put ${value}`); const key = value["sha256sum"]; db.set(key, value); @@ -85,7 +90,8 @@ function mock_indexeddb() }, }; }, - abort() { + abort() + { // No-op. }, }; From 607078f59d8006d15b17c7486d7f4087c8f08bd8 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Wed, 5 Dec 2018 10:22:23 +1300 Subject: [PATCH 1534/2137] Filestorage: Optimise .read to single IndexedDB request for 4k block Reusing the naming scheme of sha256sum sha256sum-0 sha256sum-1 sha256sum-2 etc but the extra metadata such as total file size and block count are no longer needed in the first block. --- src/browser/filestorage.js | 164 ++++++++++++++++++++----------------- 1 file changed, 88 insertions(+), 76 deletions(-) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index 0b122b93..ac589b9b 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -1,14 +1,12 @@ "use strict"; -const INDEXEDDB_STORAGE_VERSION = 1; +const INDEXEDDB_STORAGE_VERSION = 2; const INDEXEDDB_STORAGE_NAME = "v86-filesystem-storage"; const INDEXEDDB_STORAGE_STORE = "store"; const INDEXEDDB_STORAGE_KEY_PATH = "sha256sum"; const INDEXEDDB_STORAGE_DATA_PATH = "data"; -const INDEXEDDB_STORAGE_EXTRABLOCKCOUNT_PATH = "extra-block-count"; -const INDEXEDDB_STORAGE_TOTALSIZE_PATH = "total-size"; -const INDEXEDDB_STORAGE_GET_BLOCK_KEY = (sha256sum, block_number) => `${sha256sum}-${block_number}`; -const INDEXEDDB_STORAGE_CHUNKING_THRESHOLD = 4096; +const INDEXEDDB_STORAGE_GET_BLOCK_KEY = (sha256sum, block_number) => + block_number === 0 ? sha256sum : `${sha256sum}-${block_number - 1}`; const INDEXEDDB_STORAGE_BLOCKSIZE = 4096; /** @interface */ @@ -134,10 +132,20 @@ IndexedDBFileStorage.init_db = function() reject(open_request.error); }; + /** @suppress{uselessCode} */ open_request.onupgradeneeded = event => { const db = open_request.result; - db.createObjectStore(INDEXEDDB_STORAGE_STORE, { keyPath: INDEXEDDB_STORAGE_KEY_PATH }); + if(event.oldVersion < 1) + { + // Initial version. + db.createObjectStore(INDEXEDDB_STORAGE_STORE, { keyPath: INDEXEDDB_STORAGE_KEY_PATH }); + } + if(event.oldVersion < 2) + { + // Version 2 removes total_size and extra_block_count from the base entries. + // No changes needed, but new files written are not backwards compatible. + } }; open_request.onsuccess = event => @@ -171,15 +179,15 @@ IndexedDBFileStorage.init_db = function() /** * @private * @param {IDBObjectStore} store - * @param {string} key - * @return {!Promise} + * @param {string} sha256sum + * @return {!Promise} */ -IndexedDBFileStorage.prototype.db_get = function(store, key) +IndexedDBFileStorage.prototype.db_has_file = function(store, sha256sum) { return new Promise((resolve, reject) => { - const request = store.get(key); - request.onsuccess = event => resolve(request.result); + const request = store.count(sha256sum); + request.onsuccess = event => resolve(/** @type {number} **/ (request.result) > 0); }); }; @@ -189,7 +197,7 @@ IndexedDBFileStorage.prototype.db_get = function(store, key) * @param {number} count * @return {!Promise} null if file does not exist. */ -IndexedDBFileStorage.prototype.read = async function(sha256sum, offset, count) // jshint ignore:line +IndexedDBFileStorage.prototype.read = function(sha256sum, offset, count) { dbg_assert(sha256sum, "IndexedDBFileStorage read: sha256sum should be a non-empty string"); @@ -202,65 +210,80 @@ IndexedDBFileStorage.prototype.read = async function(sha256sum, offset, count) / }; const store = transaction.objectStore(INDEXEDDB_STORAGE_STORE); - const entry = await this.db_get(store, sha256sum); // jshint ignore:line + const block_number_start = Math.floor(offset / INDEXEDDB_STORAGE_BLOCKSIZE); + const block_number_end = count > 0 ? + Math.floor((offset + count - 1) / INDEXEDDB_STORAGE_BLOCKSIZE) : + block_number_start; - if(!entry) - { - return null; - } - - const base_data = entry[INDEXEDDB_STORAGE_DATA_PATH]; - const extra_block_count = entry[INDEXEDDB_STORAGE_EXTRABLOCKCOUNT_PATH]; - const total_size = entry[INDEXEDDB_STORAGE_TOTALSIZE_PATH]; - - dbg_assert(base_data instanceof Uint8Array, - `IndexedDBFileStorage read: Invalid base entry without the data Uint8Array field: ${base_data.constructor}`); - dbg_assert(Number.isInteger(extra_block_count), - `IndexedDBFileStorage read: Invalid base entry with non-integer block_count: ${extra_block_count}`); - dbg_assert(Number.isInteger(total_size) && total_size >= base_data.length, - `IndexedDBFileStorage read: Invalid base entry with invalid total_size: ${total_size}`); - - if(extra_block_count === 0 || offset + count <= base_data.length) - { - // Avoid additional allocation and copying for smaller files. - return base_data.subarray(offset, offset + count); - } - - const read_data = new Uint8Array(count); + // Allocate only when the read spans more than one block. + const is_single_read = block_number_start === block_number_end; + const read_data = is_single_read ? null : new Uint8Array(count); let read_count = 0; - if(offset < base_data.length) + return new Promise((resolve, reject) => { - const chunk = base_data.subarray(offset, offset + count); - read_data.set(chunk); - read_count += chunk.length; - } + for(let block_number = block_number_start; block_number <= block_number_end; block_number++) + { + const block_offset = block_number * INDEXEDDB_STORAGE_BLOCKSIZE; + const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, block_number); + const block_request = store.get(block_key); + block_request.onsuccess = async event => // jshint ignore:line + { + const block_entry = block_request.result; - let block_number = Math.floor( - (offset + read_count - base_data.length) / - INDEXEDDB_STORAGE_BLOCKSIZE - ); - for(; read_count < count && block_number < extra_block_count; block_number++) - { - const block_offset = base_data.length + block_number * INDEXEDDB_STORAGE_BLOCKSIZE; - const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, block_number); - const block_entry = await this.db_get(store, block_key); // jshint ignore:line + if(!block_entry) + { + // If the first requested block doesn't exist, then the remaining blocks + // cannot exist. + if(block_number === block_number_start) + { + const file_is_nonexistent = + block_number_start === 0 || + !await this.db_has_file(store, sha256sum); // jshint ignore:line - dbg_assert(block_entry, `IndexedDBFileStorage read: Missing entry for block-${block_number}`); + if(file_is_nonexistent) + { + // Not aborting transaction here because: + // - Abort is treated like an error, + // - AbortError sometimes indicate a different error we want to notice, + // - Most read calls only read a single block anyway. + resolve(null); + } + else if(is_single_read) + { + // File exists but the read was out-of-range. + resolve(new Uint8Array(0)); + } + } + return; + } - const block_data = block_entry[INDEXEDDB_STORAGE_DATA_PATH]; - dbg_assert(block_data instanceof Uint8Array, - `IndexedDBFileStorage read: Entry for block-${block_number} without Uint8Array data field: ${block_data.constructor}`); + const block_data = block_entry[INDEXEDDB_STORAGE_DATA_PATH]; + dbg_assert(block_data instanceof Uint8Array, "IndexedDBFileStorage read: " + + `Entry for block-${block_number} without Uint8Array data field.`); - const chunk_start = offset + read_count - block_offset; - const chunk_end = offset + count - block_offset; - const chunk = block_data.subarray(chunk_start, chunk_end); - read_data.set(chunk, read_count); - read_count += chunk.length; - } + const chunk_start = Math.max(0, offset - block_offset); + const chunk_end = offset + count - block_offset; + const chunk = block_data.subarray(chunk_start, chunk_end); - return read_data.subarray(0, read_count); -}; // jshint ignore:line + if(is_single_read) + { + resolve(chunk); + } + else + { + read_data.set(chunk, block_offset + chunk_start - offset); + read_count += chunk.length; + } + }; + } + + if(!is_single_read) + { + transaction.oncomplete = event => resolve(read_data.subarray(0, read_count)); + } + }); +}; /** * @param {string} sha256sum @@ -279,21 +302,10 @@ IndexedDBFileStorage.prototype.set = function(sha256sum, data) }; const store = transaction.objectStore(INDEXEDDB_STORAGE_STORE); - const extra_block_count = Math.ceil( - (data.length - INDEXEDDB_STORAGE_CHUNKING_THRESHOLD) / - INDEXEDDB_STORAGE_BLOCKSIZE - ); + // Ensure at least a single entry is added for empty files. + const offset_upper_bound = data.length || 1; - store.put({ - [INDEXEDDB_STORAGE_KEY_PATH]: sha256sum, - // Note: Without cloning, the entire backing ArrayBuffer is serialized into the database. - [INDEXEDDB_STORAGE_DATA_PATH]: data.slice(0, INDEXEDDB_STORAGE_CHUNKING_THRESHOLD), - [INDEXEDDB_STORAGE_TOTALSIZE_PATH]: data.length, - [INDEXEDDB_STORAGE_EXTRABLOCKCOUNT_PATH]: extra_block_count, - }); - - let offset = INDEXEDDB_STORAGE_CHUNKING_THRESHOLD; - for(let i = 0; offset < data.length; i++, offset += INDEXEDDB_STORAGE_BLOCKSIZE) + for(let i = 0, offset = 0; offset < offset_upper_bound; i++, offset += INDEXEDDB_STORAGE_BLOCKSIZE) { const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, i); // Note: Without cloning, the entire backing ArrayBuffer is serialized into the database. From 22412f3815c489f775f60f0d1840968745de150e Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Tue, 11 Dec 2018 18:15:01 +1300 Subject: [PATCH 1535/2137] Filestorage tests: Test non-existent files --- tests/devices/filestorage.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tests/devices/filestorage.js b/tests/devices/filestorage.js index 4ea96fa5..bb6ed22d 100755 --- a/tests/devices/filestorage.js +++ b/tests/devices/filestorage.js @@ -146,9 +146,16 @@ async function test_read(oracle, iut, key, offset, count) // jshint ignore:line async function test_with_file(oracle, iut, key, file_data) // jshint ignore:line { - console.log("Testing file with size: %d", file_data.length); - await oracle.set(key, file_data); // jshint ignore:line - await iut.set(key, file_data); // jshint ignore:line + if(file_data) + { + console.log("Testing file with size: %d", file_data.length); + await oracle.set(key, file_data); // jshint ignore:line + await iut.set(key, file_data); // jshint ignore:line + } + else + { + console.log("Testing nonexistent file"); + } // Some boundary values. if(!await test_read(oracle, iut, key, 0, 0)) return false; // jshint ignore:line @@ -196,6 +203,7 @@ async function test_start() // jshint ignore:line // Implementation under test with chunking. const iut = new IndexedDBFileStorage(mock_indexeddb()); + if(!await test_with_file(oracle, iut, "nonexistent")) return false; // jshint ignore:line if(!await test_with_file(oracle, iut, "empty", new Uint8Array(0))) return false; // jshint ignore:line if(!await test_with_file(oracle, iut, "single", new Uint8Array(1).map(v => Math.random() * 0xFF))) return false; // jshint ignore:line if(!await test_with_file(oracle, iut, "1block", new Uint8Array(4096).map(v => Math.random() * 0xFF))) return false; // jshint ignore:line From 644d2cfca84c6c2088c1d5cb8cb312a47fc480f9 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 16 Dec 2018 22:09:48 +1300 Subject: [PATCH 1536/2137] Filestorage tests: Improve mock transaction lifetimes - Assert that transaction operations are done within their callback scopes. - Improve test performance by using setImmediate for queueing macrotasks instead of using setTimeout. - Check for in-progress callbacks before completing transactions. Note that promise callbacks are run as microtasks. When request onsuccess callbacks are run, the transaction becomes active again and allows further requests to be placed against that transaction. The transaction becomes inactive when the program reaches the end of the event loop iteration. However, all microtasks are exhausted before the event loop iteration ends, so the transaction remains active even within the promise callbacks. --- tests/devices/filestorage.js | 50 ++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/tests/devices/filestorage.js b/tests/devices/filestorage.js index bb6ed22d..12c89057 100755 --- a/tests/devices/filestorage.js +++ b/tests/devices/filestorage.js @@ -96,42 +96,60 @@ function mock_indexeddb() }, }; - let completed = false; + let is_active = true; let pending_requests = 0; + let pending_callbacks = 1; function assert_transaction_active(verb) { - if(completed) + if(!is_active) { - log_fail(`Attempted to ${verb} after transaction expired`); + log_fail(`Attempted to ${verb} when transaction is inactive`); process.exit(1); } } function mock_request_completion(request) { pending_requests++; - setTimeout(() => + setImmediate(() => { pending_requests--; + pending_callbacks++; - setTimeout(() => - { - if(!pending_requests) - { - completed = true; - if(transaction.oncomplete) - { - transaction.oncomplete(); - } - } - }, 0); + // Transaction is active during onsuccess callback and during its microtasks. + is_active = true; + + // Queue before the onsuccess callback queues any other macrotask. + queue_transaction_deactivate(); if(request.onsuccess) { request.onsuccess(); } - }, 0); + }); } + function queue_transaction_deactivate() + { + // Deactivate transaction only after all microtasks (e.g. promise callbacks) have + // been completed. + setImmediate(() => + { + is_active = false; + pending_callbacks--; + + // Complete transaction when it can no longer become active. + if(!pending_requests && !pending_callbacks) + { + if(transaction.oncomplete) + { + transaction.oncomplete(); + } + } + }); + } + + queue_transaction_deactivate(); + return transaction; }, }; From dbfa0edc3c28963b780013883a7fb11a9774a3f0 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 16 Dec 2018 22:22:59 +1300 Subject: [PATCH 1537/2137] Filestorage: Split read() logic into different cases for readability --- src/browser/filestorage.js | 129 ++++++++++++++++++++++++------------- 1 file changed, 84 insertions(+), 45 deletions(-) diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index ac589b9b..cc426c75 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -215,72 +215,111 @@ IndexedDBFileStorage.prototype.read = function(sha256sum, offset, count) Math.floor((offset + count - 1) / INDEXEDDB_STORAGE_BLOCKSIZE) : block_number_start; - // Allocate only when the read spans more than one block. - const is_single_read = block_number_start === block_number_end; - const read_data = is_single_read ? null : new Uint8Array(count); - let read_count = 0; - return new Promise((resolve, reject) => { - for(let block_number = block_number_start; block_number <= block_number_end; block_number++) + if(block_number_end === 0) { - const block_offset = block_number * INDEXEDDB_STORAGE_BLOCKSIZE; - const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, block_number); + // Only first block to be read. + + const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, 0); const block_request = store.get(block_key); block_request.onsuccess = async event => // jshint ignore:line { const block_entry = block_request.result; - if(!block_entry) { - // If the first requested block doesn't exist, then the remaining blocks - // cannot exist. - if(block_number === block_number_start) - { - const file_is_nonexistent = - block_number_start === 0 || - !await this.db_has_file(store, sha256sum); // jshint ignore:line + resolve(null); + return; + } + const block_data = block_entry[INDEXEDDB_STORAGE_DATA_PATH]; + dbg_assert(block_data instanceof Uint8Array, "IndexedDBFileStorage read: " + + `Entry for block-0 without Uint8Array data field.`); + const chunk = block_data.subarray(offset, offset + count); + resolve(chunk); + }; + } + else if(block_number_start === block_number_end) + { + // Only one block to be read. - if(file_is_nonexistent) - { - // Not aborting transaction here because: - // - Abort is treated like an error, - // - AbortError sometimes indicate a different error we want to notice, - // - Most read calls only read a single block anyway. - resolve(null); - } - else if(is_single_read) - { - // File exists but the read was out-of-range. - resolve(new Uint8Array(0)); - } + const block_offset = block_number_start * INDEXEDDB_STORAGE_BLOCKSIZE; + const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, block_number_start); + const block_request = store.get(block_key); + block_request.onsuccess = async event => // jshint ignore:line + { + const block_entry = block_request.result; + if(!block_entry) + { + if(!await this.db_has_file(store, sha256sum)) // jshint ignore:line + { + resolve(null); + } + else // jshint ignore:line + { + resolve(new Uint8Array(0)); } return; } - const block_data = block_entry[INDEXEDDB_STORAGE_DATA_PATH]; dbg_assert(block_data instanceof Uint8Array, "IndexedDBFileStorage read: " + - `Entry for block-${block_number} without Uint8Array data field.`); - + `Entry for block-${block_number_start} without Uint8Array data field.`); const chunk_start = Math.max(0, offset - block_offset); const chunk_end = offset + count - block_offset; const chunk = block_data.subarray(chunk_start, chunk_end); - - if(is_single_read) - { - resolve(chunk); - } - else - { - read_data.set(chunk, block_offset + chunk_start - offset); - read_count += chunk.length; - } + resolve(chunk); }; } - - if(!is_single_read) + else { - transaction.oncomplete = event => resolve(read_data.subarray(0, read_count)); + // Multiple blocks to be read. + + const read_data = new Uint8Array(count); + let read_count = 0; + for(let block_number = block_number_start; block_number <= block_number_end; block_number++) + { + const block_offset = block_number * INDEXEDDB_STORAGE_BLOCKSIZE; + const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, block_number); + const block_request = store.get(block_key); + block_request.onsuccess = async event => // jshint ignore:line + { + const block_entry = block_request.result; + + if(!block_entry) + { + // If the first requested block doesn't exist, then the remaining blocks + // cannot exist. + if(block_number === block_number_start) + { + if(!await this.db_has_file(store, sha256sum)) // jshint ignore:line + { + // Not aborting transaction here because: + // - Abort is treated like an error, + // - AbortError sometimes indicate a different error we want to notice, + // - Most read calls only read a single block anyway. + resolve(null); + } + } + + return; + } + + const block_data = block_entry[INDEXEDDB_STORAGE_DATA_PATH]; + dbg_assert(block_data instanceof Uint8Array, "IndexedDBFileStorage read: " + + `Entry for block-${block_number} without Uint8Array data field.`); + + const chunk_start = Math.max(0, offset - block_offset); + const chunk_end = offset + count - block_offset; + const chunk = block_data.subarray(chunk_start, chunk_end); + + read_data.set(chunk, block_offset + chunk_start - offset); + read_count += chunk.length; + }; + } + + transaction.oncomplete = event => + { + resolve(read_data.subarray(0, read_count)); + }; } }); }; From 3dde97f14ad2bb23e875fe49e3690fed9088f979 Mon Sep 17 00:00:00 2001 From: Ernest Wong Date: Sun, 16 Dec 2018 22:37:11 +1300 Subject: [PATCH 1538/2137] Filesystem: Work on entire buffer when writing to file The Uint8Array that stores the file data is usually larger than the file size itself, to improve the amortized complexity of resizing the array. When we previously switched over to using FileStorages, the method fs#Write() was modified to retrieve only the subarray of the Uint8Array that contains the file (i.e. excluding the unused padding at the end), so appending to a file always tries to resize the array even though the ArrayBuffer that backs it has enough space for the new data. --- lib/filesystem.js | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 89a153ff..c5fda25f 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -846,12 +846,12 @@ FS.prototype.Write = async function(id, offset, count, buffer) { // jshint ignor } inode.dirty = true; - var data = await this.get_data(id, 0, inode.size); // jshint ignore:line + var data = await this.get_buffer(id); // jshint ignore:line if (!data || data.length < (offset+count)) { await this.ChangeSize(id, Math.floor(((offset+count)*3)/2)); // jshint ignore:line inode.size = offset + count; - data = await this.get_data(id, 0, inode.size); // jshint ignore:line + data = await this.get_buffer(id); // jshint ignore:line } else if (inode.size < (offset+count)) { inode.size = offset + count; @@ -1061,6 +1061,33 @@ FS.prototype.DeleteData = async function(idx) // jshint ignore:line delete this.inodedata[idx]; }; // jshint ignore:line +/** + * @private + * @param {number} idx + * @return {!Promise} The buffer that contains the file contents, which may be larger + * than the data itself. To ensure that any modifications done to this buffer is reflected + * to the file, call set_data with the modified buffer. + */ +FS.prototype.get_buffer = async function(idx) // jshint ignore:line +{ + const inode = this.inodes[idx]; + dbg_assert(inode, `Filesystem get_buffer: idx ${idx} does not point to an inode`); + + if(this.inodedata[idx]) + { + return this.inodedata[idx]; + } + else if(inode.status === STATUS_ON_STORAGE) + { + dbg_assert(inode.sha256sum, "Filesystem get_data: found inode on server without sha256sum"); + return await this.storage.read(inode.sha256sum, 0, inode.size); // jshint ignore:line + } + else + { + return null; + } +}; // jshint ignore:line + /** * @private * @param {number} idx From c9163c2df5b9e7499eb7f1d336ba9d719e030099 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 13 Dec 2018 17:19:27 -0600 Subject: [PATCH 1539/2137] Custom code generation for mov reg, imm (B0-BF) --- gen/x86_table.js | 4 +-- src/rust/cpu2/instructions.rs | 26 ++---------------- src/rust/jit_instructions.rs | 51 +++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 26 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 50a9b467..ee9e95d0 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -954,8 +954,8 @@ for(let i = 0; i < 8; i++) { opcode: 0x82, e: 1, fixed_g: i, imm8: 1, }, { opcode: 0x83, os: 1, e: 1, fixed_g: i, imm8s: 1, custom: 1, }, - { opcode: 0xB0 | i, imm8: 1, }, - { opcode: 0xB8 | i, os: 1, imm1632: 1, }, + { opcode: 0xB0 | i, custom: 1, imm8: 1, }, + { opcode: 0xB8 | i, custom: 1, 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 diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index 70371499..68e74d8b 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -1867,54 +1867,32 @@ pub unsafe fn instr_AE() { scasb_no_rep(); } pub unsafe fn instr16_AF() { scasw_no_rep(); } #[no_mangle] pub unsafe fn instr32_AF() { scasd_no_rep(); } -#[no_mangle] + pub unsafe fn instr_B0(imm8: i32) { *reg8.offset(AL as isize) = imm8 as u8; } -#[no_mangle] pub unsafe fn instr_B1(imm8: i32) { *reg8.offset(CL as isize) = imm8 as u8; } -#[no_mangle] pub unsafe fn instr_B2(imm8: i32) { *reg8.offset(DL as isize) = imm8 as u8; } -#[no_mangle] pub unsafe fn instr_B3(imm8: i32) { *reg8.offset(BL as isize) = imm8 as u8; } -#[no_mangle] pub unsafe fn instr_B4(imm8: i32) { *reg8.offset(AH as isize) = imm8 as u8; } -#[no_mangle] pub unsafe fn instr_B5(imm8: i32) { *reg8.offset(CH as isize) = imm8 as u8; } -#[no_mangle] pub unsafe fn instr_B6(imm8: i32) { *reg8.offset(DH as isize) = imm8 as u8; } -#[no_mangle] pub unsafe fn instr_B7(imm8: i32) { *reg8.offset(BH as isize) = imm8 as u8; } -#[no_mangle] pub unsafe fn instr16_B8(imm: i32) { *reg16.offset(AX as isize) = imm as u16; } -#[no_mangle] pub unsafe fn instr32_B8(imm: i32) { *reg32s.offset(EAX as isize) = imm; } -#[no_mangle] pub unsafe fn instr16_B9(imm: i32) { *reg16.offset(CX as isize) = imm as u16; } -#[no_mangle] pub unsafe fn instr32_B9(imm: i32) { *reg32s.offset(ECX as isize) = imm; } -#[no_mangle] pub unsafe fn instr16_BA(imm: i32) { *reg16.offset(DX as isize) = imm as u16; } -#[no_mangle] pub unsafe fn instr32_BA(imm: i32) { *reg32s.offset(EDX as isize) = imm; } -#[no_mangle] pub unsafe fn instr16_BB(imm: i32) { *reg16.offset(BX as isize) = imm as u16; } -#[no_mangle] pub unsafe fn instr32_BB(imm: i32) { *reg32s.offset(EBX as isize) = imm; } -#[no_mangle] pub unsafe fn instr16_BC(imm: i32) { *reg16.offset(SP as isize) = imm as u16; } -#[no_mangle] pub unsafe fn instr32_BC(imm: i32) { *reg32s.offset(ESP as isize) = imm; } -#[no_mangle] pub unsafe fn instr16_BD(imm: i32) { *reg16.offset(BP as isize) = imm as u16; } -#[no_mangle] pub unsafe fn instr32_BD(imm: i32) { *reg32s.offset(EBP as isize) = imm; } -#[no_mangle] pub unsafe fn instr16_BE(imm: i32) { *reg16.offset(SI as isize) = imm as u16; } -#[no_mangle] pub unsafe fn instr32_BE(imm: i32) { *reg32s.offset(ESI as isize) = imm; } -#[no_mangle] pub unsafe fn instr16_BF(imm: i32) { *reg16.offset(DI as isize) = imm as u16; } -#[no_mangle] pub unsafe fn instr32_BF(imm: i32) { *reg32s.offset(EDI as isize) = imm; } + #[no_mangle] pub unsafe fn instr_C0_0_mem(addr: i32, imm: i32) { SAFE_READ_WRITE8!(___, addr, rol8(___, imm & 31)); diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 113f4c2f..0ab23382 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1724,6 +1724,57 @@ pub fn instr32_C3_jit(ctx: &mut JitContext) { ctx.builder.instruction_body.store_aligned_i32(0); } +pub fn gen_mov_reg8_imm(ctx: &mut JitContext, r: u32, imm: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg8_offset(r) as i32); + ctx.builder.instruction_body.const_i32(imm as i32); + ctx.builder.instruction_body.store_u8(0); +} + +pub fn instr_B0_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg8_imm(ctx, 0, imm) } +pub fn instr_B1_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg8_imm(ctx, 1, imm) } +pub fn instr_B2_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg8_imm(ctx, 2, imm) } +pub fn instr_B3_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg8_imm(ctx, 3, imm) } +pub fn instr_B4_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg8_imm(ctx, 4, imm) } +pub fn instr_B5_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg8_imm(ctx, 5, imm) } +pub fn instr_B6_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg8_imm(ctx, 6, imm) } +pub fn instr_B7_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg8_imm(ctx, 7, imm) } + +pub fn gen_mov_reg16_imm(ctx: &mut JitContext, r: u32, imm: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg16_offset(r) as i32); + ctx.builder.instruction_body.const_i32(imm as i32); + ctx.builder.instruction_body.store_aligned_u16(0); +} + +pub fn instr16_B8_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg16_imm(ctx, 0, imm) } +pub fn instr16_B9_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg16_imm(ctx, 1, imm) } +pub fn instr16_BA_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg16_imm(ctx, 2, imm) } +pub fn instr16_BB_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg16_imm(ctx, 3, imm) } +pub fn instr16_BC_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg16_imm(ctx, 4, imm) } +pub fn instr16_BD_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg16_imm(ctx, 5, imm) } +pub fn instr16_BE_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg16_imm(ctx, 6, imm) } +pub fn instr16_BF_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg16_imm(ctx, 7, imm) } + +pub fn gen_mov_reg32_imm(ctx: &mut JitContext, r: u32, imm: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg32_offset(r) as i32); + ctx.builder.instruction_body.const_i32(imm as i32); + ctx.builder.instruction_body.store_aligned_i32(0); +} + +pub fn instr32_B8_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg32_imm(ctx, 0, imm) } +pub fn instr32_B9_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg32_imm(ctx, 1, imm) } +pub fn instr32_BA_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg32_imm(ctx, 2, imm) } +pub fn instr32_BB_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg32_imm(ctx, 3, imm) } +pub fn instr32_BC_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg32_imm(ctx, 4, imm) } +pub fn instr32_BD_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg32_imm(ctx, 5, imm) } +pub fn instr32_BE_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg32_imm(ctx, 6, imm) } +pub fn instr32_BF_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg32_imm(ctx, 7, imm) } + define_instruction_read_write_mem8!( "rol8", "instr_C0_0_mem", From 69b834c8de5f7f2c3583965def5de529b0f0bf18 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 13 Dec 2018 17:33:23 -0600 Subject: [PATCH 1540/2137] Move condition function generation into codegen module and use it for cmovcc/setcc --- src/rust/codegen.rs | 11 ++++ src/rust/jit.rs | 11 +--- src/rust/jit_instructions.rs | 108 +++++++++++++++++------------------ 3 files changed, 66 insertions(+), 64 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index ee751c70..b7f16b6c 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -14,6 +14,11 @@ extern "C" { static mut mem8: *mut u8; } +const CONDITION_FUNCTIONS: [&str; 16] = [ + "test_o", "test_no", "test_b", "test_nb", "test_z", "test_nz", "test_be", "test_nbe", "test_s", + "test_ns", "test_p", "test_np", "test_l", "test_nl", "test_le", "test_nle", +]; + pub fn gen_set_previous_eip_offset_from_eip(builder: &mut WasmBuilder, n: u32) { let cs = &mut builder.instruction_body; cs.const_i32(global_pointers::PREVIOUS_IP as i32); // store address of previous ip @@ -1176,6 +1181,12 @@ pub fn gen_trigger_ud(ctx: &mut JitContext) { ctx.builder.instruction_body.return_(); } +pub fn gen_condition_fn(builder: &mut WasmBuilder, condition: u8) { + dbg_assert!(condition < 16); + let condition_name = CONDITION_FUNCTIONS[condition as usize]; + gen_fn0_const_ret(builder, condition_name); +} + pub fn gen_profiler_stat_increment(builder: &mut WasmBuilder, stat: profiler::stat) { let addr = unsafe { profiler::stat_array.as_mut_ptr().offset(stat as isize) } as u32; gen_increment_variable(builder, addr, 1) diff --git a/src/rust/jit.rs b/src/rust/jit.rs index c4ed6086..1c002a2d 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -27,11 +27,6 @@ pub const JIT_ALWAYS_USE_LOOP_SAFETY: bool = true; pub const JIT_THRESHOLD: u32 = 200 * 1000; -const CONDITION_FUNCTIONS: [&str; 16] = [ - "test_o", "test_no", "test_b", "test_nb", "test_z", "test_nz", "test_be", "test_nbe", "test_s", - "test_ns", "test_p", "test_np", "test_l", "test_nl", "test_le", "test_nle", -]; - const CODE_CACHE_SEARCH_SIZE: u32 = 8; const MAX_INSTRUCTION_LENGTH: u32 = 16; @@ -1067,11 +1062,7 @@ fn jit_generate_module( // Conditional jump to next basic block // - jnz, jc, etc. - dbg_assert!(condition < 16); - let condition = CONDITION_FUNCTIONS[condition as usize]; - - codegen::gen_fn0_const_ret(builder, condition); - + codegen::gen_condition_fn(builder, condition); builder.instruction_body.if_void(); // Branch taken diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 0ab23382..b0231dd5 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -3178,7 +3178,7 @@ define_instruction_write_reg32!("imul_reg32", instr32_0FAF_mem_jit, instr32_0FAF macro_rules! define_cmovcc16( ($cond:expr, $name_mem:ident, $name_reg:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_fn0_const_ret(ctx.builder, $cond); + codegen::gen_condition_fn(ctx.builder, $cond); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read16(ctx); ctx.builder.instruction_body.const_i32(r as i32); @@ -3186,7 +3186,7 @@ macro_rules! define_cmovcc16( } pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { - codegen::gen_fn0_const_ret(ctx.builder, $cond); + codegen::gen_condition_fn(ctx.builder, $cond); codegen::gen_get_reg16(ctx.builder, r1); ctx.builder.instruction_body.const_i32(r2 as i32); codegen::gen_call_fn3(ctx.builder, "cmovcc16") @@ -3197,7 +3197,7 @@ macro_rules! define_cmovcc16( macro_rules! define_cmovcc32( ($cond:expr, $name_mem:ident, $name_reg:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_fn0_const_ret(ctx.builder, $cond); + codegen::gen_condition_fn(&mut ctx.builder, $cond); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); ctx.builder.instruction_body.const_i32(r as i32); @@ -3205,7 +3205,7 @@ macro_rules! define_cmovcc32( } pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { - codegen::gen_fn0_const_ret(ctx.builder, $cond); + codegen::gen_condition_fn(&mut ctx.builder, $cond); codegen::gen_get_reg32(ctx.builder, r1); ctx.builder.instruction_body.const_i32(r2 as i32); codegen::gen_call_fn3(ctx.builder, "cmovcc32") @@ -3213,48 +3213,48 @@ macro_rules! define_cmovcc32( ); ); -define_cmovcc16!("test_o", instr16_0F40_mem_jit, instr16_0F40_reg_jit); -define_cmovcc16!("test_no", instr16_0F41_mem_jit, instr16_0F41_reg_jit); -define_cmovcc16!("test_b", instr16_0F42_mem_jit, instr16_0F42_reg_jit); -define_cmovcc16!("test_nb", instr16_0F43_mem_jit, instr16_0F43_reg_jit); -define_cmovcc16!("test_z", instr16_0F44_mem_jit, instr16_0F44_reg_jit); -define_cmovcc16!("test_nz", instr16_0F45_mem_jit, instr16_0F45_reg_jit); -define_cmovcc16!("test_be", instr16_0F46_mem_jit, instr16_0F46_reg_jit); -define_cmovcc16!("test_nbe", instr16_0F47_mem_jit, instr16_0F47_reg_jit); +define_cmovcc16!(0x0, instr16_0F40_mem_jit, instr16_0F40_reg_jit); +define_cmovcc16!(0x1, instr16_0F41_mem_jit, instr16_0F41_reg_jit); +define_cmovcc16!(0x2, instr16_0F42_mem_jit, instr16_0F42_reg_jit); +define_cmovcc16!(0x3, instr16_0F43_mem_jit, instr16_0F43_reg_jit); +define_cmovcc16!(0x4, instr16_0F44_mem_jit, instr16_0F44_reg_jit); +define_cmovcc16!(0x5, instr16_0F45_mem_jit, instr16_0F45_reg_jit); +define_cmovcc16!(0x6, instr16_0F46_mem_jit, instr16_0F46_reg_jit); +define_cmovcc16!(0x7, instr16_0F47_mem_jit, instr16_0F47_reg_jit); -define_cmovcc16!("test_s", instr16_0F48_mem_jit, instr16_0F48_reg_jit); -define_cmovcc16!("test_ns", instr16_0F49_mem_jit, instr16_0F49_reg_jit); -define_cmovcc16!("test_p", instr16_0F4A_mem_jit, instr16_0F4A_reg_jit); -define_cmovcc16!("test_np", instr16_0F4B_mem_jit, instr16_0F4B_reg_jit); -define_cmovcc16!("test_l", instr16_0F4C_mem_jit, instr16_0F4C_reg_jit); -define_cmovcc16!("test_nl", instr16_0F4D_mem_jit, instr16_0F4D_reg_jit); -define_cmovcc16!("test_le", instr16_0F4E_mem_jit, instr16_0F4E_reg_jit); -define_cmovcc16!("test_nle", instr16_0F4F_mem_jit, instr16_0F4F_reg_jit); +define_cmovcc16!(0x8, instr16_0F48_mem_jit, instr16_0F48_reg_jit); +define_cmovcc16!(0x9, instr16_0F49_mem_jit, instr16_0F49_reg_jit); +define_cmovcc16!(0xA, instr16_0F4A_mem_jit, instr16_0F4A_reg_jit); +define_cmovcc16!(0xB, instr16_0F4B_mem_jit, instr16_0F4B_reg_jit); +define_cmovcc16!(0xC, instr16_0F4C_mem_jit, instr16_0F4C_reg_jit); +define_cmovcc16!(0xD, instr16_0F4D_mem_jit, instr16_0F4D_reg_jit); +define_cmovcc16!(0xE, instr16_0F4E_mem_jit, instr16_0F4E_reg_jit); +define_cmovcc16!(0xF, instr16_0F4F_mem_jit, instr16_0F4F_reg_jit); -define_cmovcc32!("test_o", instr32_0F40_mem_jit, instr32_0F40_reg_jit); -define_cmovcc32!("test_no", instr32_0F41_mem_jit, instr32_0F41_reg_jit); -define_cmovcc32!("test_b", instr32_0F42_mem_jit, instr32_0F42_reg_jit); -define_cmovcc32!("test_nb", instr32_0F43_mem_jit, instr32_0F43_reg_jit); -define_cmovcc32!("test_z", instr32_0F44_mem_jit, instr32_0F44_reg_jit); -define_cmovcc32!("test_nz", instr32_0F45_mem_jit, instr32_0F45_reg_jit); -define_cmovcc32!("test_be", instr32_0F46_mem_jit, instr32_0F46_reg_jit); -define_cmovcc32!("test_nbe", instr32_0F47_mem_jit, instr32_0F47_reg_jit); +define_cmovcc32!(0x0, instr32_0F40_mem_jit, instr32_0F40_reg_jit); +define_cmovcc32!(0x1, instr32_0F41_mem_jit, instr32_0F41_reg_jit); +define_cmovcc32!(0x2, instr32_0F42_mem_jit, instr32_0F42_reg_jit); +define_cmovcc32!(0x3, instr32_0F43_mem_jit, instr32_0F43_reg_jit); +define_cmovcc32!(0x4, instr32_0F44_mem_jit, instr32_0F44_reg_jit); +define_cmovcc32!(0x5, instr32_0F45_mem_jit, instr32_0F45_reg_jit); +define_cmovcc32!(0x6, instr32_0F46_mem_jit, instr32_0F46_reg_jit); +define_cmovcc32!(0x7, instr32_0F47_mem_jit, instr32_0F47_reg_jit); -define_cmovcc32!("test_s", instr32_0F48_mem_jit, instr32_0F48_reg_jit); -define_cmovcc32!("test_ns", instr32_0F49_mem_jit, instr32_0F49_reg_jit); -define_cmovcc32!("test_p", instr32_0F4A_mem_jit, instr32_0F4A_reg_jit); -define_cmovcc32!("test_np", instr32_0F4B_mem_jit, instr32_0F4B_reg_jit); -define_cmovcc32!("test_l", instr32_0F4C_mem_jit, instr32_0F4C_reg_jit); -define_cmovcc32!("test_nl", instr32_0F4D_mem_jit, instr32_0F4D_reg_jit); -define_cmovcc32!("test_le", instr32_0F4E_mem_jit, instr32_0F4E_reg_jit); -define_cmovcc32!("test_nle", instr32_0F4F_mem_jit, instr32_0F4F_reg_jit); +define_cmovcc32!(0x8, instr32_0F48_mem_jit, instr32_0F48_reg_jit); +define_cmovcc32!(0x9, instr32_0F49_mem_jit, instr32_0F49_reg_jit); +define_cmovcc32!(0xA, instr32_0F4A_mem_jit, instr32_0F4A_reg_jit); +define_cmovcc32!(0xB, instr32_0F4B_mem_jit, instr32_0F4B_reg_jit); +define_cmovcc32!(0xC, instr32_0F4C_mem_jit, instr32_0F4C_reg_jit); +define_cmovcc32!(0xD, instr32_0F4D_mem_jit, instr32_0F4D_reg_jit); +define_cmovcc32!(0xE, instr32_0F4E_mem_jit, instr32_0F4E_reg_jit); +define_cmovcc32!(0xF, instr32_0F4F_mem_jit, instr32_0F4F_reg_jit); macro_rules! define_setcc( ($cond:expr, $name_mem:ident, $name_reg:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, _r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); - codegen::gen_fn0_const_ret(ctx.builder, $cond); + codegen::gen_condition_fn(&mut ctx.builder, $cond); ctx.builder.instruction_body.const_i32(0); ctx.builder.instruction_body.ne_i32(); let value_local = ctx.builder.set_new_local(); @@ -3267,7 +3267,7 @@ macro_rules! define_setcc( ctx.builder .instruction_body .const_i32(global_pointers::get_reg8_offset(r1) as i32); - codegen::gen_fn0_const_ret(ctx.builder, $cond); + codegen::gen_condition_fn(&mut ctx.builder, $cond); ctx.builder.instruction_body.const_i32(0); ctx.builder.instruction_body.ne_i32(); ctx.builder.instruction_body.store_u8(0); @@ -3275,23 +3275,23 @@ macro_rules! define_setcc( ); ); -define_setcc!("test_o", instr_0F90_mem_jit, instr_0F90_reg_jit); -define_setcc!("test_no", instr_0F91_mem_jit, instr_0F91_reg_jit); -define_setcc!("test_b", instr_0F92_mem_jit, instr_0F92_reg_jit); -define_setcc!("test_nb", instr_0F93_mem_jit, instr_0F93_reg_jit); -define_setcc!("test_z", instr_0F94_mem_jit, instr_0F94_reg_jit); -define_setcc!("test_nz", instr_0F95_mem_jit, instr_0F95_reg_jit); -define_setcc!("test_be", instr_0F96_mem_jit, instr_0F96_reg_jit); -define_setcc!("test_nbe", instr_0F97_mem_jit, instr_0F97_reg_jit); +define_setcc!(0x0, instr_0F90_mem_jit, instr_0F90_reg_jit); +define_setcc!(0x1, instr_0F91_mem_jit, instr_0F91_reg_jit); +define_setcc!(0x2, instr_0F92_mem_jit, instr_0F92_reg_jit); +define_setcc!(0x3, instr_0F93_mem_jit, instr_0F93_reg_jit); +define_setcc!(0x4, instr_0F94_mem_jit, instr_0F94_reg_jit); +define_setcc!(0x5, instr_0F95_mem_jit, instr_0F95_reg_jit); +define_setcc!(0x6, instr_0F96_mem_jit, instr_0F96_reg_jit); +define_setcc!(0x7, instr_0F97_mem_jit, instr_0F97_reg_jit); -define_setcc!("test_s", instr_0F98_mem_jit, instr_0F98_reg_jit); -define_setcc!("test_ns", instr_0F99_mem_jit, instr_0F99_reg_jit); -define_setcc!("test_p", instr_0F9A_mem_jit, instr_0F9A_reg_jit); -define_setcc!("test_np", instr_0F9B_mem_jit, instr_0F9B_reg_jit); -define_setcc!("test_l", instr_0F9C_mem_jit, instr_0F9C_reg_jit); -define_setcc!("test_nl", instr_0F9D_mem_jit, instr_0F9D_reg_jit); -define_setcc!("test_le", instr_0F9E_mem_jit, instr_0F9E_reg_jit); -define_setcc!("test_nle", instr_0F9F_mem_jit, instr_0F9F_reg_jit); +define_setcc!(0x8, instr_0F98_mem_jit, instr_0F98_reg_jit); +define_setcc!(0x9, instr_0F99_mem_jit, instr_0F99_reg_jit); +define_setcc!(0xA, instr_0F9A_mem_jit, instr_0F9A_reg_jit); +define_setcc!(0xB, instr_0F9B_mem_jit, instr_0F9B_reg_jit); +define_setcc!(0xC, instr_0F9C_mem_jit, instr_0F9C_reg_jit); +define_setcc!(0xD, instr_0F9D_mem_jit, instr_0F9D_reg_jit); +define_setcc!(0xE, instr_0F9E_mem_jit, instr_0F9E_reg_jit); +define_setcc!(0xF, instr_0F9F_mem_jit, instr_0F9F_reg_jit); pub fn instr_0F29_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { // XXX: Aligned write or #gp From aef22e38ad764c8539b74293d8374299800e6ab7 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 13 Dec 2018 17:38:10 -0600 Subject: [PATCH 1541/2137] Add missing tracking of jit exit points --- src/rust/codegen.rs | 1 + src/rust/jit_instructions.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index b7f16b6c..1c3b3518 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -1178,6 +1178,7 @@ pub fn gen_fpu_load_m64(ctx: &mut JitContext) { pub fn gen_trigger_ud(ctx: &mut JitContext) { gen_fn0_const(ctx.builder, "trigger_ud"); + gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); ctx.builder.instruction_body.return_(); } diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index b0231dd5..f5fd618c 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -2194,6 +2194,7 @@ pub fn instr_D9_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_call_fn1(ctx.builder, "fpu_fldenv"); // XXX: generated because fldenv might page-fault, but doesn't generate a proper block boundary + codegen::gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); ctx.builder.instruction_body.return_(); } pub fn instr_D9_4_reg_jit(ctx: &mut JitContext, r: u32) { @@ -2273,6 +2274,7 @@ pub fn instr_DB_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_call_fn1(ctx.builder, "fpu_fldm80"); // XXX: generated because fpu_fldm80 might page-fault, but doesn't generate a proper block boundary + codegen::gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); ctx.builder.instruction_body.return_(); } pub fn instr_DB_5_reg_jit(ctx: &mut JitContext, r: u32) { From f14e9528d685391b9b547dc466331e1dfe23ca83 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 13 Dec 2018 17:55:11 -0600 Subject: [PATCH 1542/2137] Custom code generation for cmovcc (0F40-0F4F) --- src/rust/cpu2/misc_instr.rs | 4 ++-- src/rust/jit_instructions.rs | 36 +++++++++++++++++++++++++----------- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index bc39dc68..8d9a1887 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -129,18 +129,18 @@ pub unsafe fn loopne32(imm8s: i32) { jmpcc32(0 != decr_ecx_asize() && !getzf(), pub unsafe fn loop32(imm8s: i32) { jmpcc32(0 != decr_ecx_asize(), imm8s); } #[no_mangle] pub unsafe fn jcxz32(imm8s: i32) { jmpcc32(get_reg_asize(ECX) == 0, imm8s); } -#[no_mangle] + pub unsafe fn cmovcc16(condition: bool, value: i32, r: i32) { if condition { write_reg16(r, value); }; } -#[no_mangle] pub unsafe fn cmovcc32(condition: bool, value: i32, r: i32) { if condition { write_reg32(r, value); }; } + #[no_mangle] pub unsafe fn get_stack_pointer(offset: i32) -> i32 { if *stack_size_32 { diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index f5fd618c..86d05179 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -3180,18 +3180,25 @@ define_instruction_write_reg32!("imul_reg32", instr32_0FAF_mem_jit, instr32_0FAF macro_rules! define_cmovcc16( ($cond:expr, $name_mem:ident, $name_reg:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_condition_fn(ctx.builder, $cond); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read16(ctx); - ctx.builder.instruction_body.const_i32(r as i32); - codegen::gen_call_fn3(ctx.builder, "cmovcc16") + let value = ctx.builder.set_new_local(); + codegen::gen_condition_fn(ctx.builder, $cond); + ctx.builder.instruction_body.if_void(); + ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r) as i32); + ctx.builder.instruction_body.get_local(&value); + ctx.builder.instruction_body.store_aligned_u16(0); + ctx.builder.instruction_body.block_end(); + ctx.builder.free_local(value); } pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_condition_fn(ctx.builder, $cond); + ctx.builder.instruction_body.if_void(); + ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r2) as i32); codegen::gen_get_reg16(ctx.builder, r1); - ctx.builder.instruction_body.const_i32(r2 as i32); - codegen::gen_call_fn3(ctx.builder, "cmovcc16") + ctx.builder.instruction_body.store_aligned_u16(0); + ctx.builder.instruction_body.block_end(); } ); ); @@ -3199,18 +3206,25 @@ macro_rules! define_cmovcc16( macro_rules! define_cmovcc32( ($cond:expr, $name_mem:ident, $name_reg:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_condition_fn(&mut ctx.builder, $cond); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); - ctx.builder.instruction_body.const_i32(r as i32); - codegen::gen_call_fn3(ctx.builder, "cmovcc32") + let value = ctx.builder.set_new_local(); + codegen::gen_condition_fn(ctx.builder, $cond); + ctx.builder.instruction_body.if_void(); + ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r) as i32); + ctx.builder.instruction_body.get_local(&value); + ctx.builder.instruction_body.store_aligned_i32(0); + ctx.builder.instruction_body.block_end(); + ctx.builder.free_local(value); } pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { - codegen::gen_condition_fn(&mut ctx.builder, $cond); + codegen::gen_condition_fn(ctx.builder, $cond); + ctx.builder.instruction_body.if_void(); + ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r2) as i32); codegen::gen_get_reg32(ctx.builder, r1); - ctx.builder.instruction_body.const_i32(r2 as i32); - codegen::gen_call_fn3(ctx.builder, "cmovcc32") + ctx.builder.instruction_body.store_aligned_i32(0); + ctx.builder.instruction_body.block_end(); } ); ); From 04281702edc2c575ced26a96adfe8069fc98d680 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 18 Dec 2018 11:07:29 -0600 Subject: [PATCH 1543/2137] Track jit exits to same/different page --- src/browser/print_stats.js | 2 ++ src/rust/cpu2/cpu.rs | 7 +++++++ src/rust/profiler.rs | 3 +++ 3 files changed, 12 insertions(+) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index 27eb01b5..ac0e68eb 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -51,6 +51,8 @@ const print_stats = { "INVALIDATE_CACHE_ENTRY", "INVALIDATE_MODULE_CACHE_FULL", "INVALIDATE_SINGLE_ENTRY_CACHE_FULL", + "RUN_FROM_CACHE_EXIT_SAME_PAGE", + "RUN_FROM_CACHE_EXIT_DIFFERENT_PAGE", "CLEAR_TLB", "FULL_CLEAR_TLB", "TLB_FULL", diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index ced90c28..a49f9faa 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1733,6 +1733,13 @@ pub unsafe fn cycle_internal() { RUN_FROM_CACHE_STEPS, (*timestamp_counter - initial_tsc) as u64, ); + + if Page::page_of(*previous_ip as u32) == Page::page_of(*instruction_pointer as u32) { + profiler::stat_increment(RUN_FROM_CACHE_EXIT_SAME_PAGE); + } + else { + profiler::stat_increment(RUN_FROM_CACHE_EXIT_DIFFERENT_PAGE); + } } else { ::jit::record_entry_point(::c_api::get_module(), phys_addr); diff --git a/src/rust/profiler.rs b/src/rust/profiler.rs index ee0b4ad2..ffdda98a 100644 --- a/src/rust/profiler.rs +++ b/src/rust/profiler.rs @@ -45,6 +45,9 @@ pub enum stat { INVALIDATE_MODULE_CACHE_FULL, INVALIDATE_SINGLE_ENTRY_CACHE_FULL, + RUN_FROM_CACHE_EXIT_SAME_PAGE, + RUN_FROM_CACHE_EXIT_DIFFERENT_PAGE, + CLEAR_TLB, FULL_CLEAR_TLB, TLB_FULL, From fc954cecea623eae88701e342e11f4ffe8b814a7 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 18 Dec 2018 12:00:51 -0600 Subject: [PATCH 1544/2137] Update libwabt (fix failing decoding of large generated modules) --- Makefile | 6 +++--- src/debug.js | 2 +- src/externs.js | 2 +- tests/expect/run.js | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index ed5d3cfe..f6f10806 100644 --- a/Makefile +++ b/Makefile @@ -304,6 +304,6 @@ build/capstone-x86.min.js: build/libwabt.js: mkdir -p build - wget -P build https://github.com/WebAssembly/wabt/archive/1.0.1.zip - unzip -j -d build/ build/1.0.1.zip wabt-1.0.1/demo/libwabt.js - rm build/1.0.1.zip + wget -P build https://github.com/WebAssembly/wabt/archive/1.0.6.zip + unzip -j -d build/ build/1.0.6.zip wabt-1.0.6/demo/libwabt.js + rm build/1.0.6.zip diff --git a/src/debug.js b/src/debug.js index 9bd993af..1e4782e5 100644 --- a/src/debug.js +++ b/src/debug.js @@ -786,7 +786,7 @@ CPU.prototype.debug_init = function() } else { - wabt = window.wabt; + wabt = new window.WabtModule; } if(wabt === undefined) diff --git a/src/externs.js b/src/externs.js index 87148df5..25d34572 100644 --- a/src/externs.js +++ b/src/externs.js @@ -23,7 +23,7 @@ var WebAssembly = { }; WebAssembly.Module.customSections = function(module, section) {}; -var wabt = { +var WabtModule = { readWasm: function(buf, opt) {}, generateNames: function() {}, applyNames: function() {}, diff --git a/tests/expect/run.js b/tests/expect/run.js index 7d09e67e..c3e33c88 100755 --- a/tests/expect/run.js +++ b/tests/expect/run.js @@ -7,7 +7,7 @@ const fs = require("fs"); const path = require("path"); const { spawnSync } = require("child_process"); -const libwabt = require("../../build/libwabt.js"); +const libwabt = require("../../build/libwabt.js")(); try { var V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86; From c0f1d2a487cc44f2f7a4d7563a45f90068ad7acc Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 18 Dec 2018 13:29:30 -0600 Subject: [PATCH 1545/2137] Custom code generation for arith al/ax/eax, imm (group [0123][45CD], A8/A9) --- gen/x86_table.js | 8 +- src/rust/jit_instructions.rs | 140 +++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+), 4 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index ee9e95d0..9313a2b6 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -222,8 +222,8 @@ const encodings = [ { opcode: 0xF2A7, block_boundary: 1, is_string: 1, os: 1, }, { opcode: 0xF3A7, block_boundary: 1, is_string: 1, os: 1, }, - { opcode: 0xA8, imm8: 1, }, - { opcode: 0xA9, os: 1, imm1632: 1, }, + { opcode: 0xA8, custom: 1, imm8: 1, }, + { opcode: 0xA9, custom: 1, os: 1, imm1632: 1, }, { opcode: 0xAA, block_boundary: 1, is_string: 1, }, { opcode: 0xF2AA, block_boundary: 1, is_string: 1, }, @@ -943,8 +943,8 @@ const encodings = [ for(let i = 0; i < 8; i++) { encodings.push.apply(encodings, [ - { opcode: 0x04 | i << 3, eax: 1, imm8: 1, }, - { opcode: 0x05 | i << 3, os: 1, eax: 1, imm1632: 1, }, + { opcode: 0x04 | i << 3, custom: 1, imm8: 1, }, + { opcode: 0x05 | i << 3, custom: 1, os: 1, imm1632: 1, }, { opcode: 0x70 | i, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, os: 1, imm8s: 1, custom: 1, skip: 1, }, { opcode: 0x78 | i, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, os: 1, imm8s: 1, custom: 1, skip: 1, }, diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 86d05179..2d5e1a34 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -160,6 +160,36 @@ fn pop32_reg_jit(ctx: &mut JitContext, reg: u32) { ctx.builder.instruction_body.store_aligned_i32(0); } +fn group_arith_al_imm8(ctx: &mut JitContext, op: &str, imm8: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg8_offset(0) as i32); + codegen::gen_get_reg8(ctx.builder, 0); + ctx.builder.instruction_body.const_i32(imm8 as i32); + codegen::gen_call_fn2_ret(ctx.builder, op); + ctx.builder.instruction_body.store_u8(0); +} + +fn group_arith_ax_imm16(ctx: &mut JitContext, op: &str, imm16: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg16_offset(0) as i32); + codegen::gen_get_reg16(ctx.builder, 0); + ctx.builder.instruction_body.const_i32(imm16 as i32); + codegen::gen_call_fn2_ret(ctx.builder, op); + ctx.builder.instruction_body.store_aligned_u16(0); +} + +fn group_arith_eax_imm32(ctx: &mut JitContext, op: &str, imm32: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg32_offset(0) as i32); + codegen::gen_get_reg32(ctx.builder, 0); + ctx.builder.instruction_body.const_i32(imm32 as i32); + codegen::gen_call_fn2_ret(ctx.builder, op); + ctx.builder.instruction_body.store_aligned_i32(0); +} + macro_rules! define_instruction_read8( ($fn:expr, $name_mem:ident, $name_reg:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { @@ -761,6 +791,14 @@ define_instruction_write_reg8!("add8", instr_02_mem_jit, instr_02_reg_jit); define_instruction_write_reg16!("add16", instr16_03_mem_jit, instr16_03_reg_jit); define_instruction_write_reg32!("add32", instr32_03_mem_jit, instr32_03_reg_jit); +pub fn instr_04_jit(ctx: &mut JitContext, imm8: u32) { group_arith_al_imm8(ctx, "add8", imm8); } +pub fn instr16_05_jit(ctx: &mut JitContext, imm16: u32) { + group_arith_ax_imm16(ctx, "add16", imm16); +} +pub fn instr32_05_jit(ctx: &mut JitContext, imm32: u32) { + group_arith_eax_imm32(ctx, "add32", imm32); +} + define_instruction_read_write_mem8!( "or8", "instr_08_mem", @@ -787,6 +825,14 @@ define_instruction_write_reg8!("or8", instr_0A_mem_jit, instr_0A_reg_jit); define_instruction_write_reg16!("or16", instr16_0B_mem_jit, instr16_0B_reg_jit); define_instruction_write_reg32!("or32", instr32_0B_mem_jit, instr32_0B_reg_jit); +pub fn instr_0C_jit(ctx: &mut JitContext, imm8: u32) { group_arith_al_imm8(ctx, "or8", imm8); } +pub fn instr16_0D_jit(ctx: &mut JitContext, imm16: u32) { + group_arith_ax_imm16(ctx, "or16", imm16); +} +pub fn instr32_0D_jit(ctx: &mut JitContext, imm32: u32) { + group_arith_eax_imm32(ctx, "or32", imm32); +} + define_instruction_read_write_mem8!( "adc8", "instr_10_mem", @@ -813,6 +859,14 @@ define_instruction_write_reg8!("adc8", instr_12_mem_jit, instr_12_reg_jit); define_instruction_write_reg16!("adc16", instr16_13_mem_jit, instr16_13_reg_jit); define_instruction_write_reg32!("adc32", instr32_13_mem_jit, instr32_13_reg_jit); +pub fn instr_14_jit(ctx: &mut JitContext, imm8: u32) { group_arith_al_imm8(ctx, "adc8", imm8); } +pub fn instr16_15_jit(ctx: &mut JitContext, imm16: u32) { + group_arith_ax_imm16(ctx, "adc16", imm16); +} +pub fn instr32_15_jit(ctx: &mut JitContext, imm32: u32) { + group_arith_eax_imm32(ctx, "adc32", imm32); +} + define_instruction_read_write_mem8!( "sbb8", "instr_18_mem", @@ -839,6 +893,14 @@ define_instruction_write_reg8!("sbb8", instr_1A_mem_jit, instr_1A_reg_jit); define_instruction_write_reg16!("sbb16", instr16_1B_mem_jit, instr16_1B_reg_jit); define_instruction_write_reg32!("sbb32", instr32_1B_mem_jit, instr32_1B_reg_jit); +pub fn instr_1C_jit(ctx: &mut JitContext, imm8: u32) { group_arith_al_imm8(ctx, "sbb8", imm8); } +pub fn instr16_1D_jit(ctx: &mut JitContext, imm16: u32) { + group_arith_ax_imm16(ctx, "sbb16", imm16); +} +pub fn instr32_1D_jit(ctx: &mut JitContext, imm32: u32) { + group_arith_eax_imm32(ctx, "sbb32", imm32); +} + define_instruction_read_write_mem8!( "and8", "instr_20_mem", @@ -865,6 +927,14 @@ define_instruction_write_reg8!("and8", instr_22_mem_jit, instr_22_reg_jit); define_instruction_write_reg16!("and16", instr16_23_mem_jit, instr16_23_reg_jit); define_instruction_write_reg32!("and32", instr32_23_mem_jit, instr32_23_reg_jit); +pub fn instr_24_jit(ctx: &mut JitContext, imm8: u32) { group_arith_al_imm8(ctx, "and8", imm8); } +pub fn instr16_25_jit(ctx: &mut JitContext, imm16: u32) { + group_arith_ax_imm16(ctx, "and16", imm16); +} +pub fn instr32_25_jit(ctx: &mut JitContext, imm32: u32) { + group_arith_eax_imm32(ctx, "and32", imm32); +} + define_instruction_read_write_mem8!( "sub8", "instr_28_mem", @@ -891,6 +961,14 @@ define_instruction_write_reg8!("sub8", instr_2A_mem_jit, instr_2A_reg_jit); define_instruction_write_reg16!("sub16", instr16_2B_mem_jit, instr16_2B_reg_jit); define_instruction_write_reg32!("sub32", instr32_2B_mem_jit, instr32_2B_reg_jit); +pub fn instr_2C_jit(ctx: &mut JitContext, imm8: u32) { group_arith_al_imm8(ctx, "sub8", imm8); } +pub fn instr16_2D_jit(ctx: &mut JitContext, imm16: u32) { + group_arith_ax_imm16(ctx, "sub16", imm16); +} +pub fn instr32_2D_jit(ctx: &mut JitContext, imm32: u32) { + group_arith_eax_imm32(ctx, "sub32", imm32); +} + define_instruction_read_write_mem8!( "xor8", "instr_30_mem", @@ -917,6 +995,14 @@ define_instruction_write_reg8!("xor8", instr_32_mem_jit, instr_32_reg_jit); define_instruction_write_reg16!("xor16", instr16_33_mem_jit, instr16_33_reg_jit); define_instruction_write_reg32!("xor32", instr32_33_mem_jit, instr32_33_reg_jit); +pub fn instr_34_jit(ctx: &mut JitContext, imm8: u32) { group_arith_al_imm8(ctx, "xor8", imm8); } +pub fn instr16_35_jit(ctx: &mut JitContext, imm16: u32) { + group_arith_ax_imm16(ctx, "xor16", imm16); +} +pub fn instr32_35_jit(ctx: &mut JitContext, imm32: u32) { + group_arith_eax_imm32(ctx, "xor32", imm32); +} + define_instruction_read8!("cmp8", instr_38_mem_jit, instr_38_reg_jit); define_instruction_read16!("cmp16", instr16_39_mem_jit, instr16_39_reg_jit); define_instruction_read32!("cmp32", instr32_39_mem_jit, instr32_39_reg_jit); @@ -960,6 +1046,33 @@ pub fn instr32_3B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_call_fn2(ctx.builder, "cmp32") } +pub fn instr_3C_jit(ctx: &mut JitContext, imm8: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg8_offset(0) as i32); + codegen::gen_get_reg8(ctx.builder, 0); + ctx.builder.instruction_body.const_i32(imm8 as i32); + codegen::gen_call_fn2(ctx.builder, "cmp8"); +} + +pub fn instr16_3D_jit(ctx: &mut JitContext, imm16: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg16_offset(0) as i32); + codegen::gen_get_reg16(ctx.builder, 0); + ctx.builder.instruction_body.const_i32(imm16 as i32); + codegen::gen_call_fn2(ctx.builder, "cmp16"); +} + +pub fn instr32_3D_jit(ctx: &mut JitContext, imm32: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg32_offset(0) as i32); + codegen::gen_get_reg32(ctx.builder, 0); + ctx.builder.instruction_body.const_i32(imm32 as i32); + codegen::gen_call_fn2(ctx.builder, "cmp32"); +} + pub fn instr16_50_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, AX); } pub fn instr32_50_jit(ctx: &mut JitContext) { push32_reg_jit(ctx, EAX); } pub fn instr16_51_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, CX); } @@ -2818,6 +2931,33 @@ pub fn instr32_A3_jit(ctx: &mut JitContext, immaddr: u32) { ctx.builder.free_local(value_local); } +pub fn instr_A8_jit(ctx: &mut JitContext, imm8: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg8_offset(0) as i32); + codegen::gen_get_reg8(ctx.builder, 0); + ctx.builder.instruction_body.const_i32(imm8 as i32); + codegen::gen_call_fn2(ctx.builder, "test8"); +} + +pub fn instr16_A9_jit(ctx: &mut JitContext, imm16: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg16_offset(0) as i32); + codegen::gen_get_reg16(ctx.builder, 0); + ctx.builder.instruction_body.const_i32(imm16 as i32); + codegen::gen_call_fn2(ctx.builder, "test16"); +} + +pub fn instr32_A9_jit(ctx: &mut JitContext, imm32: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg32_offset(0) as i32); + codegen::gen_get_reg32(ctx.builder, 0); + ctx.builder.instruction_body.const_i32(imm32 as i32); + codegen::gen_call_fn2(ctx.builder, "test32"); +} + pub fn instr_0F18_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) { modrm::skip(ctx.cpu, modrm_byte); } From 837e6ff362119c9896530573934f86485175257a Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 18 Dec 2018 16:06:01 -0600 Subject: [PATCH 1546/2137] Custom code generation for ret imm (C2) --- gen/x86_table.js | 2 +- src/rust/codegen.rs | 21 +++++++++++++++++++++ src/rust/jit_instructions.rs | 25 +++++++++++++++++++++++++ tests/nasm/ret-imm.asm | 15 +++++++++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 tests/nasm/ret-imm.asm diff --git a/gen/x86_table.js b/gen/x86_table.js index 9313a2b6..e4a3660e 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -246,7 +246,7 @@ const encodings = [ { opcode: 0xF2AF, block_boundary: 1, is_string: 1, os: 1, }, { opcode: 0xF3AF, block_boundary: 1, is_string: 1, os: 1, }, - { opcode: 0xC2, block_boundary: 1, no_next_instruction: 1, os: 1, imm16: 1, skip: 1, }, // ret + { opcode: 0xC2, custom: 1, block_boundary: 1, no_next_instruction: 1, os: 1, imm16: 1, skip: 1, }, // ret { opcode: 0xC3, custom: 1, block_boundary: 1, no_next_instruction: 1, os: 1, skip: 1, }, { opcode: 0xC4, block_boundary: 1, os: 1, e: 1, skip: 1, }, // les diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 1c3b3518..b72ce8d7 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -880,6 +880,27 @@ pub fn gen_pop32s(ctx: &mut JitContext) { } } +pub fn gen_adjust_stack_reg(ctx: &mut JitContext, offset: u32) { + if ctx.cpu.ssize_32() { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg32_offset(regs::ESP) as i32); + gen_get_reg32(ctx.builder, regs::ESP); + ctx.builder.instruction_body.const_i32(offset as i32); + ctx.builder.instruction_body.add_i32(); + ctx.builder.instruction_body.store_aligned_i32(0); + } + else { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg16_offset(regs::SP) as i32); + gen_get_reg16(ctx.builder, regs::SP); + ctx.builder.instruction_body.const_i32(offset as i32); + ctx.builder.instruction_body.add_i32(); + ctx.builder.instruction_body.store_aligned_u16(0); + } +} + pub fn gen_task_switch_test(ctx: &mut JitContext) { // generate if(cr[0] & (CR0_EM | CR0_TS)) { task_switch_test_void(); return; } let cr0_offset = global_pointers::get_creg_offset(0); diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 2d5e1a34..aa2b613c 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1802,6 +1802,31 @@ pub fn instr32_E9_jit(ctx: &mut JitContext, imm: u32) { codegen::gen_relative_jump(ctx.builder, imm as i32); } +pub fn instr16_C2_jit(ctx: &mut JitContext, imm16: u32) { + let cs_addr = global_pointers::get_seg_offset(CS); + ctx.builder + .instruction_body + .const_i32(global_pointers::INSTRUCTION_POINTER as i32); + ctx.builder.instruction_body.load_aligned_i32(cs_addr); + codegen::gen_pop16(ctx); + codegen::gen_adjust_stack_reg(ctx, imm16); + ctx.builder.instruction_body.add_i32(); + ctx.builder.instruction_body.store_aligned_i32(0); +} + +pub fn instr32_C2_jit(ctx: &mut JitContext, imm16: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::INSTRUCTION_POINTER as i32); + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_seg_offset(CS)); + codegen::gen_pop32s(ctx); + codegen::gen_adjust_stack_reg(ctx, imm16); + ctx.builder.instruction_body.add_i32(); + ctx.builder.instruction_body.store_aligned_i32(0); +} + pub fn instr16_C3_jit(ctx: &mut JitContext) { let cs_addr = global_pointers::get_seg_offset(CS); diff --git a/tests/nasm/ret-imm.asm b/tests/nasm/ret-imm.asm new file mode 100644 index 00000000..bff7dbb8 --- /dev/null +++ b/tests/nasm/ret-imm.asm @@ -0,0 +1,15 @@ +global _start + +%include "header.inc" + + jmp start +foo: + mov eax, esp + ret 123 + +start: + call foo + mov dword [eax], 0 ; clear the address pushed by the call instruction + + +%include "footer.inc" From 0c42ea0d1f01c74cb7372bf47efac9ed0b7e56ec Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 18 Dec 2018 16:57:21 -0600 Subject: [PATCH 1547/2137] Custom code generation for leave (C9) --- gen/x86_table.js | 2 +- src/rust/codegen.rs | 65 ++++++++++++++++++++++++++++++++++++ src/rust/jit_instructions.rs | 3 ++ tests/nasm/leave16.asm | 10 ++++++ tests/nasm/leave32.asm | 9 +++++ 5 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 tests/nasm/leave16.asm create mode 100644 tests/nasm/leave32.asm diff --git a/gen/x86_table.js b/gen/x86_table.js index e4a3660e..2706c6d2 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -257,7 +257,7 @@ const encodings = [ // XXX: Temporary block boundary { opcode: 0xC8, os: 1, imm16: 1, extra_imm8: 1, block_boundary: 1, }, // enter - { opcode: 0xC9, os: 1, skip: 1, block_boundary: 1, }, // leave: requires valid ebp + { opcode: 0xC9, custom: 1, os: 1, skip: 1 }, // leave { opcode: 0xCA, block_boundary: 1, no_next_instruction: 1, os: 1, imm16: 1, skip: 1, }, // retf { opcode: 0xCB, block_boundary: 1, no_next_instruction: 1, os: 1, skip: 1, }, diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index b72ce8d7..02c73912 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -901,6 +901,71 @@ pub fn gen_adjust_stack_reg(ctx: &mut JitContext, offset: u32) { } } +pub fn gen_leave(ctx: &mut JitContext, os32: bool) { + // [e]bp = safe_read{16,32}([e]bp) + if os32 { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg32_offset(regs::EBP) as i32); + } + else { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg16_offset(regs::BP) as i32); + } + + if ctx.cpu.ssize_32() { + gen_get_reg32(ctx.builder, regs::EBP); + } + else { + gen_get_reg16(ctx.builder, regs::BP); + } + + let old_vbp = ctx.builder.tee_new_local(); + + if !ctx.cpu.has_flat_segmentation() { + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_seg_offset(regs::SS)); + ctx.builder.instruction_body.add_i32(); + } + if os32 { + gen_safe_read32(ctx); + ctx.builder.instruction_body.store_aligned_i32(0); + } + else { + gen_safe_read16(ctx); + ctx.builder.instruction_body.store_aligned_u16(0); + } + + // [e]sp = [e]bp + (os32 ? 4 : 2) + + if ctx.cpu.ssize_32() { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg32_offset(regs::ESP) as i32); + ctx.builder.instruction_body.get_local(&old_vbp); + ctx.builder + .instruction_body + .const_i32(if os32 { 4 } else { 2 }); + ctx.builder.instruction_body.add_i32(); + ctx.builder.instruction_body.store_aligned_i32(0); + } + else { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg16_offset(regs::SP) as i32); + ctx.builder.instruction_body.get_local(&old_vbp); + ctx.builder + .instruction_body + .const_i32(if os32 { 4 } else { 2 }); + ctx.builder.instruction_body.add_i32(); + ctx.builder.instruction_body.store_aligned_u16(0); + } + + ctx.builder.free_local(old_vbp); +} + pub fn gen_task_switch_test(ctx: &mut JitContext) { // generate if(cr[0] & (CR0_EM | CR0_TS)) { task_switch_test_void(); return; } let cr0_offset = global_pointers::get_creg_offset(0); diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index aa2b613c..052e2ec1 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1862,6 +1862,9 @@ pub fn instr32_C3_jit(ctx: &mut JitContext) { ctx.builder.instruction_body.store_aligned_i32(0); } +pub fn instr16_C9_jit(ctx: &mut JitContext) { codegen::gen_leave(ctx, false); } +pub fn instr32_C9_jit(ctx: &mut JitContext) { codegen::gen_leave(ctx, true); } + pub fn gen_mov_reg8_imm(ctx: &mut JitContext, r: u32, imm: u32) { ctx.builder .instruction_body diff --git a/tests/nasm/leave16.asm b/tests/nasm/leave16.asm new file mode 100644 index 00000000..1aee353b --- /dev/null +++ b/tests/nasm/leave16.asm @@ -0,0 +1,10 @@ +global _start + +%include "header.inc" + + lea ebp, [esp+10h] + mov dword [ebp], 123456789 + db 0x66 + leave + +%include "footer.inc" diff --git a/tests/nasm/leave32.asm b/tests/nasm/leave32.asm new file mode 100644 index 00000000..fa6bb72e --- /dev/null +++ b/tests/nasm/leave32.asm @@ -0,0 +1,9 @@ +global _start + +%include "header.inc" + + lea ebp, [esp+10h] + mov dword [ebp], 123456789 + leave + +%include "footer.inc" From 4d35564761319f21abd6f9e5cb4f1a6825420c26 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 18 Dec 2018 17:35:48 -0600 Subject: [PATCH 1548/2137] Simplify get_seg: Generate code inline, avoid importing it in every module --- src/rust/jit.rs | 6 ------ src/rust/modrm.rs | 6 ++++-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 1c002a2d..1a555c78 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -11,7 +11,6 @@ use profiler; use profiler::stat; use state_flags::CachedStateFlags; use util::SafeToU16; -use wasmgen::module_init; use wasmgen::module_init::WasmBuilder; use wasmgen::wasm_util::WasmBuf; @@ -384,8 +383,6 @@ pub struct JitContext<'a> { pub const JIT_INSTR_BLOCK_BOUNDARY_FLAG: u32 = 1 << 0; -pub const FN_GET_SEG_IDX: u16 = 0; - fn jit_hot_hash_page(page: Page) -> u32 { page.to_u32() % HASH_PRIME } fn is_near_end_of_page(address: u32) -> bool { address & 0xFFF >= 0x1000 - MAX_INSTRUCTION_LENGTH } @@ -945,9 +942,6 @@ fn jit_generate_module( ) { builder.reset(); - let fn_get_seg_idx = builder.get_fn_idx("get_seg", module_init::FN1_RET_TYPE_INDEX); - dbg_assert!(fn_get_seg_idx == FN_GET_SEG_IDX); - let basic_block_indices: HashMap = basic_blocks .iter() .enumerate() diff --git a/src/rust/modrm.rs b/src/rust/modrm.rs index b4a92a81..897a23de 100644 --- a/src/rust/modrm.rs +++ b/src/rust/modrm.rs @@ -1,5 +1,6 @@ use codegen; use cpu_context::CpuContext; +use global_pointers; use jit::JitContext; use prefix::{PREFIX_MASK_SEGMENT, SEG_PREFIX_ZERO}; use regs::{BP, BX, DI, SI}; @@ -324,7 +325,8 @@ pub fn jit_add_seg_offset(ctx: &mut JitContext, default_segment: u32) { return; } - ctx.builder.instruction_body.const_i32(seg as i32); - ctx.builder.instruction_body.call_fn(::jit::FN_GET_SEG_IDX); + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_seg_offset(seg)); ctx.builder.instruction_body.add_i32(); } From c2508bc61e7ac1c50039b64410876fbd028ec99f Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 18 Dec 2018 17:52:14 -0600 Subject: [PATCH 1549/2137] Update expect tests --- tests/expect/tests/call.wast | 1 - tests/expect/tests/do-while.wast | 1 - tests/expect/tests/if.wast | 1 - tests/expect/tests/indirect-call.wast | 5 ++--- tests/expect/tests/mov16.wast | 21 ++++++++++---------- tests/expect/tests/mov32-mem.wast | 17 ++++++++-------- tests/expect/tests/mov32-reg.wast | 17 ++++++++-------- tests/expect/tests/pop.wast | 1 - tests/expect/tests/push.wast | 1 - tests/expect/tests/task_switch_test.wast | 1 - tests/expect/tests/task_switch_test_sse.wast | 1 - tests/expect/tests/while-do.wast | 1 - 12 files changed, 28 insertions(+), 40 deletions(-) diff --git a/tests/expect/tests/call.wast b/tests/expect/tests/call.wast index ea6b37e1..206cd37f 100644 --- a/tests/expect/tests/call.wast +++ b/tests/expect/tests/call.wast @@ -15,7 +15,6 @@ (type $t13 (func (param f64) (result i64))) (type $t14 (func (param i32 i32 i32) (result i32))) (type $t15 (func (param i32 i64 i64))) - (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "safe_write32_slow_jit" (func $e.safe_write32_slow_jit (type $t2))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "instr32_40" (func $e.instr32_40 (type $t0))) diff --git a/tests/expect/tests/do-while.wast b/tests/expect/tests/do-while.wast index 2ab4909b..a856a14e 100644 --- a/tests/expect/tests/do-while.wast +++ b/tests/expect/tests/do-while.wast @@ -15,7 +15,6 @@ (type $t13 (func (param f64) (result i64))) (type $t14 (func (param i32 i32 i32) (result i32))) (type $t15 (func (param i32 i64 i64))) - (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "instr32_43" (func $e.instr32_43 (type $t0))) (import "e" "cmp32" (func $e.cmp32 (type $t2))) (import "e" "test_nz" (func $e.test_nz (type $t4))) diff --git a/tests/expect/tests/if.wast b/tests/expect/tests/if.wast index c083dccb..fb985e2d 100644 --- a/tests/expect/tests/if.wast +++ b/tests/expect/tests/if.wast @@ -15,7 +15,6 @@ (type $t13 (func (param f64) (result i64))) (type $t14 (func (param i32 i32 i32) (result i32))) (type $t15 (func (param i32 i64 i64))) - (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "cmp32" (func $e.cmp32 (type $t2))) (import "e" "test_nle" (func $e.test_nle (type $t4))) (import "e" "instr32_41" (func $e.instr32_41 (type $t0))) diff --git a/tests/expect/tests/indirect-call.wast b/tests/expect/tests/indirect-call.wast index 05c14952..c6a46aa6 100644 --- a/tests/expect/tests/indirect-call.wast +++ b/tests/expect/tests/indirect-call.wast @@ -15,7 +15,6 @@ (type $t13 (func (param f64) (result i64))) (type $t14 (func (param i32 i32 i32) (result i32))) (type $t15 (func (param i32 i64 i64))) - (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "instr32_FF_2_mem" (func $e.instr32_FF_2_mem (type $t1))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) @@ -54,8 +53,8 @@ (i32.add (i32.load (i32.const 4)) - (call $e.get_seg - (i32.const 3)))) + (i32.load + (i32.const 748)))) (i32.store (i32.const 664) (i32.add diff --git a/tests/expect/tests/mov16.wast b/tests/expect/tests/mov16.wast index 0f5f8e3e..1913db72 100644 --- a/tests/expect/tests/mov16.wast +++ b/tests/expect/tests/mov16.wast @@ -15,8 +15,6 @@ (type $t13 (func (param f64) (result i64))) (type $t14 (func (param i32 i32 i32) (result i32))) (type $t15 (func (param i32 i64 i64))) - (import "e" "get_seg" (func $e.get_seg (type $t5))) - (import "e" "instr16_B8" (func $e.instr16_B8 (type $t1))) (import "e" "safe_read16_slow_jit" (func $e.safe_read16_slow_jit (type $t5))) (import "e" "safe_write16_slow_jit" (func $e.safe_write16_slow_jit (type $t2))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) @@ -41,7 +39,8 @@ (block $B3 (br_table $B3 $B2 (get_local $l0))) - (call $e.instr16_B8 + (i32.store16 + (i32.const 4) (i32.const 51966)) (i32.store16 (i32.const 8) @@ -56,8 +55,8 @@ (tee_local $l2 (i32.add (i32.const 32) - (call $e.get_seg - (i32.const 3)))) + (i32.load + (i32.const 748)))) (i32.const 12)) (i32.const 2)))) (i32.const 4041)) @@ -103,8 +102,8 @@ (tee_local $l3 (i32.add (i32.const 36) - (call $e.get_seg - (i32.const 3)))) + (i32.load + (i32.const 748)))) (i32.const 12)) (i32.const 2)))) (i32.const 4041)) @@ -152,8 +151,8 @@ (i32.load16_u (i32.const 32))) (i32.const 65535)) - (call $e.get_seg - (i32.const 3)))) + (i32.load + (i32.const 748)))) (set_local $l3 (i32.load16_u (i32.const 4))) @@ -209,8 +208,8 @@ (i32.load16_u (i32.const 28))) (i32.const 65535)) - (call $e.get_seg - (i32.const 3)))) + (i32.load + (i32.const 748)))) (set_local $l2 (i32.load16_u (i32.const 8))) diff --git a/tests/expect/tests/mov32-mem.wast b/tests/expect/tests/mov32-mem.wast index f52970a0..05e8f8ea 100644 --- a/tests/expect/tests/mov32-mem.wast +++ b/tests/expect/tests/mov32-mem.wast @@ -15,7 +15,6 @@ (type $t13 (func (param f64) (result i64))) (type $t14 (func (param i32 i32 i32) (result i32))) (type $t15 (func (param i32 i64 i64))) - (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "safe_write32_slow_jit" (func $e.safe_write32_slow_jit (type $t2))) (import "e" "safe_read32s_slow_jit" (func $e.safe_read32s_slow_jit (type $t5))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) @@ -46,8 +45,8 @@ (i32.load (i32.const 16)) (i32.const 32)) - (call $e.get_seg - (i32.const 3)))) + (i32.load + (i32.const 748)))) (set_local $l3 (i32.load (i32.const 4))) @@ -100,8 +99,8 @@ (i32.load (i32.const 12)) (i32.const 28)) - (call $e.get_seg - (i32.const 3)))) + (i32.load + (i32.const 748)))) (set_local $l2 (i32.load (i32.const 8))) @@ -164,8 +163,8 @@ (i32.load (i32.const 16)) (i32.const 28)) - (call $e.get_seg - (i32.const 3)))) + (i32.load + (i32.const 748)))) (i32.const 12)) (i32.const 2)))) (i32.const 4041)) @@ -214,8 +213,8 @@ (i32.load (i32.const 12)) (i32.const 32)) - (call $e.get_seg - (i32.const 3)))) + (i32.load + (i32.const 748)))) (i32.const 12)) (i32.const 2)))) (i32.const 4041)) diff --git a/tests/expect/tests/mov32-reg.wast b/tests/expect/tests/mov32-reg.wast index 8600e047..6439a1e5 100644 --- a/tests/expect/tests/mov32-reg.wast +++ b/tests/expect/tests/mov32-reg.wast @@ -15,11 +15,6 @@ (type $t13 (func (param f64) (result i64))) (type $t14 (func (param i32 i32 i32) (result i32))) (type $t15 (func (param i32 i64 i64))) - (import "e" "get_seg" (func $e.get_seg (type $t5))) - (import "e" "instr32_B8" (func $e.instr32_B8 (type $t1))) - (import "e" "instr32_B9" (func $e.instr32_B9 (type $t1))) - (import "e" "instr32_BA" (func $e.instr32_BA (type $t1))) - (import "e" "instr32_BB" (func $e.instr32_BB (type $t1))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) @@ -42,13 +37,17 @@ (block $B3 (br_table $B3 $B2 (get_local $l0))) - (call $e.instr32_B8 + (i32.store + (i32.const 4) (i32.const -889270259)) - (call $e.instr32_B9 + (i32.store + (i32.const 8) (i32.const -1091583778)) - (call $e.instr32_BA + (i32.store + (i32.const 12) (i32.const 0)) - (call $e.instr32_BB + (i32.store + (i32.const 16) (i32.const 0)) (i32.store (i32.const 8) diff --git a/tests/expect/tests/pop.wast b/tests/expect/tests/pop.wast index b11b2e16..9ea5b717 100644 --- a/tests/expect/tests/pop.wast +++ b/tests/expect/tests/pop.wast @@ -15,7 +15,6 @@ (type $t13 (func (param f64) (result i64))) (type $t14 (func (param i32 i32 i32) (result i32))) (type $t15 (func (param i32 i64 i64))) - (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "safe_read32s_slow_jit" (func $e.safe_read32s_slow_jit (type $t5))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) diff --git a/tests/expect/tests/push.wast b/tests/expect/tests/push.wast index b178d2a0..04d09f4b 100644 --- a/tests/expect/tests/push.wast +++ b/tests/expect/tests/push.wast @@ -15,7 +15,6 @@ (type $t13 (func (param f64) (result i64))) (type $t14 (func (param i32 i32 i32) (result i32))) (type $t15 (func (param i32 i64 i64))) - (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "safe_write32_slow_jit" (func $e.safe_write32_slow_jit (type $t2))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "m" (memory $e.m 256)) diff --git a/tests/expect/tests/task_switch_test.wast b/tests/expect/tests/task_switch_test.wast index 73fcf3e7..69c252cc 100644 --- a/tests/expect/tests/task_switch_test.wast +++ b/tests/expect/tests/task_switch_test.wast @@ -15,7 +15,6 @@ (type $t13 (func (param f64) (result i64))) (type $t14 (func (param i32 i32 i32) (result i32))) (type $t15 (func (param i32 i64 i64))) - (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "task_switch_test_void" (func $e.task_switch_test_void (type $t0))) (import "e" "fpu_get_sti" (func $e.fpu_get_sti (type $t7))) (import "e" "fpu_fadd" (func $e.fpu_fadd (type $t8))) diff --git a/tests/expect/tests/task_switch_test_sse.wast b/tests/expect/tests/task_switch_test_sse.wast index 0cd438f1..99c93f9b 100644 --- a/tests/expect/tests/task_switch_test_sse.wast +++ b/tests/expect/tests/task_switch_test_sse.wast @@ -15,7 +15,6 @@ (type $t13 (func (param f64) (result i64))) (type $t14 (func (param i32 i32 i32) (result i32))) (type $t15 (func (param i32 i64 i64))) - (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "task_switch_test_mmx_void" (func $e.task_switch_test_mmx_void (type $t0))) (import "e" "instr_660F54_reg" (func $e.instr_660F54_reg (type $t2))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) diff --git a/tests/expect/tests/while-do.wast b/tests/expect/tests/while-do.wast index 858d7ba4..109ca72a 100644 --- a/tests/expect/tests/while-do.wast +++ b/tests/expect/tests/while-do.wast @@ -15,7 +15,6 @@ (type $t13 (func (param f64) (result i64))) (type $t14 (func (param i32 i32 i32) (result i32))) (type $t15 (func (param i32 i64 i64))) - (import "e" "get_seg" (func $e.get_seg (type $t5))) (import "e" "cmp32" (func $e.cmp32 (type $t2))) (import "e" "test_z" (func $e.test_z (type $t4))) (import "e" "instr32_43" (func $e.instr32_43 (type $t0))) From 32f988a08d2e863005b3090b3b86284c8ed1c258 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 19 Dec 2018 13:34:29 -0600 Subject: [PATCH 1550/2137] Pass JitContext to gen_get_reg* (preparation for registers-in-locals) --- src/rust/codegen.rs | 63 +++++---- src/rust/jit_instructions.rs | 250 +++++++++++++++++------------------ src/rust/modrm.rs | 16 +-- 3 files changed, 160 insertions(+), 169 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 02c73912..446a197b 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -66,25 +66,25 @@ pub fn gen_increment_mem32(builder: &mut WasmBuilder, addr: u32) { builder.instruction_body.increment_mem32(addr) } -pub fn gen_get_reg8(builder: &mut WasmBuilder, r: u32) { - builder +pub fn gen_get_reg8(ctx: &mut JitContext, r: u32) { + ctx.builder .instruction_body .const_i32(global_pointers::get_reg8_offset(r) as i32); - builder.instruction_body.load_u8_from_stack(0); + ctx.builder.instruction_body.load_u8_from_stack(0); } -pub fn gen_get_reg16(builder: &mut WasmBuilder, r: u32) { - builder +pub fn gen_get_reg16(ctx: &mut JitContext, r: u32) { + ctx.builder .instruction_body .const_i32(global_pointers::get_reg16_offset(r) as i32); - builder.instruction_body.load_aligned_u16_from_stack(0); + ctx.builder.instruction_body.load_aligned_u16_from_stack(0); } -pub fn gen_get_reg32(builder: &mut WasmBuilder, r: u32) { - builder +pub fn gen_get_reg32(ctx: &mut JitContext, r: u32) { + ctx.builder .instruction_body .const_i32(global_pointers::get_reg32_offset(r) as i32); - builder.instruction_body.load_aligned_i32_from_stack(0); + ctx.builder.instruction_body.load_aligned_i32_from_stack(0); } /// sign-extend a byte value on the stack and leave it on the stack @@ -241,30 +241,27 @@ pub fn gen_modrm_resolve(ctx: &mut JitContext, modrm_byte: u8) { modrm::gen(ctx, pub fn gen_set_reg8_r(ctx: &mut JitContext, dest: u32, src: u32) { // generates: reg8[r_dest] = reg8[r_src] - let builder = &mut ctx.builder; - builder + ctx.builder .instruction_body .const_i32(global_pointers::get_reg8_offset(dest) as i32); - gen_get_reg8(builder, src); - builder.instruction_body.store_u8(0); + gen_get_reg8(ctx, src); + ctx.builder.instruction_body.store_u8(0); } pub fn gen_set_reg16_r(ctx: &mut JitContext, dest: u32, src: u32) { // generates: reg16[r_dest] = reg16[r_src] - let builder = &mut ctx.builder; - builder + ctx.builder .instruction_body .const_i32(global_pointers::get_reg16_offset(dest) as i32); - gen_get_reg16(builder, src); - builder.instruction_body.store_aligned_u16(0); + gen_get_reg16(ctx, src); + ctx.builder.instruction_body.store_aligned_u16(0); } pub fn gen_set_reg32_r(ctx: &mut JitContext, dest: u32, src: u32) { // generates: reg32s[r_dest] = reg32s[r_src] - let builder = &mut ctx.builder; - builder + ctx.builder .instruction_body .const_i32(global_pointers::get_reg32_offset(dest) as i32); - gen_get_reg32(builder, src); - builder.instruction_body.store_aligned_i32(0); + gen_get_reg32(ctx, src); + ctx.builder.instruction_body.store_aligned_i32(0); } pub fn gen_safe_read8(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::BYTE, None) } @@ -750,7 +747,7 @@ pub fn gen_jmp_rel16(builder: &mut WasmBuilder, rel16: u16) { pub fn gen_pop16_ss16(ctx: &mut JitContext) { // sp = segment_offsets[SS] + reg16[SP] (or just reg16[SP] if has_flat_segmentation) - gen_get_reg16(ctx.builder, regs::SP); + gen_get_reg16(ctx, regs::SP); let sp_local = ctx.builder.tee_new_local(); if !ctx.cpu.has_flat_segmentation() { @@ -779,7 +776,7 @@ pub fn gen_pop16_ss16(ctx: &mut JitContext) { pub fn gen_pop16_ss32(ctx: &mut JitContext) { // esp = segment_offsets[SS] + reg32s[ESP] (or just reg32s[ESP] if has_flat_segmentation) - gen_get_reg32(ctx.builder, regs::ESP); + gen_get_reg32(ctx, regs::ESP); let esp_local = ctx.builder.tee_new_local(); if !ctx.cpu.has_flat_segmentation() { @@ -816,7 +813,7 @@ pub fn gen_pop16(ctx: &mut JitContext) { pub fn gen_pop32s_ss16(ctx: &mut JitContext) { // sp = reg16[SP] - gen_get_reg16(ctx.builder, regs::SP); + gen_get_reg16(ctx, regs::SP); let local_sp = ctx.builder.tee_new_local(); // result = safe_read32s(segment_offsets[SS] + sp) (or just sp if has_flat_segmentation) @@ -845,7 +842,7 @@ pub fn gen_pop32s_ss16(ctx: &mut JitContext) { pub fn gen_pop32s_ss32(ctx: &mut JitContext) { // esp = reg32s[ESP] - gen_get_reg32(ctx.builder, regs::ESP); + gen_get_reg32(ctx, regs::ESP); let local_esp = ctx.builder.tee_new_local(); // result = safe_read32s(segment_offsets[SS] + esp) (or just esp if has_flat_segmentation) @@ -885,7 +882,7 @@ pub fn gen_adjust_stack_reg(ctx: &mut JitContext, offset: u32) { ctx.builder .instruction_body .const_i32(global_pointers::get_reg32_offset(regs::ESP) as i32); - gen_get_reg32(ctx.builder, regs::ESP); + gen_get_reg32(ctx, regs::ESP); ctx.builder.instruction_body.const_i32(offset as i32); ctx.builder.instruction_body.add_i32(); ctx.builder.instruction_body.store_aligned_i32(0); @@ -894,7 +891,7 @@ pub fn gen_adjust_stack_reg(ctx: &mut JitContext, offset: u32) { ctx.builder .instruction_body .const_i32(global_pointers::get_reg16_offset(regs::SP) as i32); - gen_get_reg16(ctx.builder, regs::SP); + gen_get_reg16(ctx, regs::SP); ctx.builder.instruction_body.const_i32(offset as i32); ctx.builder.instruction_body.add_i32(); ctx.builder.instruction_body.store_aligned_u16(0); @@ -915,10 +912,10 @@ pub fn gen_leave(ctx: &mut JitContext, os32: bool) { } if ctx.cpu.ssize_32() { - gen_get_reg32(ctx.builder, regs::EBP); + gen_get_reg32(ctx, regs::EBP); } else { - gen_get_reg16(ctx.builder, regs::BP); + gen_get_reg16(ctx, regs::BP); } let old_vbp = ctx.builder.tee_new_local(); @@ -1008,11 +1005,11 @@ pub fn gen_task_switch_test_mmx(ctx: &mut JitContext) { pub fn gen_push16(ctx: &mut JitContext, value_local: &WasmLocal) { let sp_reg = if ctx.cpu.ssize_32() { - gen_get_reg32(ctx.builder, regs::ESP); + gen_get_reg32(ctx, regs::ESP); global_pointers::get_reg32_offset(regs::ESP) } else { - gen_get_reg16(ctx.builder, regs::SP); + gen_get_reg16(ctx, regs::SP); global_pointers::get_reg16_offset(regs::SP) }; @@ -1047,11 +1044,11 @@ pub fn gen_push16(ctx: &mut JitContext, value_local: &WasmLocal) { pub fn gen_push32(ctx: &mut JitContext, value_local: &WasmLocal) { let sp_reg = if ctx.cpu.ssize_32() { - gen_get_reg32(ctx.builder, regs::ESP); + gen_get_reg32(ctx, regs::ESP); global_pointers::get_reg32_offset(regs::ESP) } else { - gen_get_reg16(ctx.builder, regs::SP); + gen_get_reg16(ctx, regs::SP); global_pointers::get_reg16_offset(regs::SP) }; diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 052e2ec1..0bba9f7f 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -104,7 +104,7 @@ pub fn instr_F3_jit(ctx: &mut JitContext, instr_flags: &mut u32) { } fn push16_reg_jit(ctx: &mut JitContext, r: u32) { - codegen::gen_get_reg16(ctx.builder, r); + codegen::gen_get_reg16(ctx, r); let value_local = ctx.builder.set_new_local(); codegen::gen_push16(ctx, &value_local); ctx.builder.free_local(value_local); @@ -164,7 +164,7 @@ fn group_arith_al_imm8(ctx: &mut JitContext, op: &str, imm8: u32) { ctx.builder .instruction_body .const_i32(global_pointers::get_reg8_offset(0) as i32); - codegen::gen_get_reg8(ctx.builder, 0); + codegen::gen_get_reg8(ctx, 0); ctx.builder.instruction_body.const_i32(imm8 as i32); codegen::gen_call_fn2_ret(ctx.builder, op); ctx.builder.instruction_body.store_u8(0); @@ -174,7 +174,7 @@ fn group_arith_ax_imm16(ctx: &mut JitContext, op: &str, imm16: u32) { ctx.builder .instruction_body .const_i32(global_pointers::get_reg16_offset(0) as i32); - codegen::gen_get_reg16(ctx.builder, 0); + codegen::gen_get_reg16(ctx, 0); ctx.builder.instruction_body.const_i32(imm16 as i32); codegen::gen_call_fn2_ret(ctx.builder, op); ctx.builder.instruction_body.store_aligned_u16(0); @@ -184,7 +184,7 @@ fn group_arith_eax_imm32(ctx: &mut JitContext, op: &str, imm32: u32) { ctx.builder .instruction_body .const_i32(global_pointers::get_reg32_offset(0) as i32); - codegen::gen_get_reg32(ctx.builder, 0); + codegen::gen_get_reg32(ctx, 0); ctx.builder.instruction_body.const_i32(imm32 as i32); codegen::gen_call_fn2_ret(ctx.builder, op); ctx.builder.instruction_body.store_aligned_i32(0); @@ -195,13 +195,13 @@ macro_rules! define_instruction_read8( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read8(ctx); - codegen::gen_get_reg8(ctx.builder, r); + codegen::gen_get_reg8(ctx, r); codegen::gen_call_fn2(ctx.builder, $fn) } pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { - codegen::gen_get_reg8(ctx.builder, r1); - codegen::gen_get_reg8(ctx.builder, r2); + codegen::gen_get_reg8(ctx, r1); + codegen::gen_get_reg8(ctx, r2); codegen::gen_call_fn2(ctx.builder, $fn) } ); @@ -215,7 +215,7 @@ macro_rules! define_instruction_read8( } pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { - codegen::gen_get_reg8(ctx.builder, r1); + codegen::gen_get_reg8(ctx, r1); ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn2(ctx.builder, $fn) } @@ -227,13 +227,13 @@ macro_rules! define_instruction_read16( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read16(ctx); - codegen::gen_get_reg16(ctx.builder, r); + codegen::gen_get_reg16(ctx, r); codegen::gen_call_fn2(ctx.builder, $fn) } pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { - codegen::gen_get_reg16(ctx.builder, r1); - codegen::gen_get_reg16(ctx.builder, r2); + codegen::gen_get_reg16(ctx, r1); + codegen::gen_get_reg16(ctx, r2); codegen::gen_call_fn2(ctx.builder, $fn) } ); @@ -247,7 +247,7 @@ macro_rules! define_instruction_read16( } pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { - codegen::gen_get_reg16(ctx.builder, r1); + codegen::gen_get_reg16(ctx, r1); ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn2(ctx.builder, $fn) } @@ -259,13 +259,13 @@ macro_rules! define_instruction_read32( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); - codegen::gen_get_reg32(ctx.builder, r); + codegen::gen_get_reg32(ctx, r); codegen::gen_call_fn2(ctx.builder, $fn) } pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { - codegen::gen_get_reg32(ctx.builder, r1); - codegen::gen_get_reg32(ctx.builder, r2); + codegen::gen_get_reg32(ctx, r1); + codegen::gen_get_reg32(ctx, r2); codegen::gen_call_fn2(ctx.builder, $fn) } ); @@ -279,18 +279,18 @@ macro_rules! define_instruction_read32( } pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { - codegen::gen_get_reg32(ctx.builder, r1); + codegen::gen_get_reg32(ctx, r1); ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn2(ctx.builder, $fn) } - ) + ); ); macro_rules! define_instruction_write_reg8( ($fn:expr, $name_mem:ident, $name_reg:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { ctx.builder.instruction_body.const_i32(global_pointers::get_reg8_offset(r) as i32); - codegen::gen_get_reg8(ctx.builder, r); + codegen::gen_get_reg8(ctx, r); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read8(ctx); codegen::gen_call_fn2_ret(ctx.builder, $fn); @@ -299,8 +299,8 @@ macro_rules! define_instruction_write_reg8( pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { ctx.builder.instruction_body.const_i32(global_pointers::get_reg8_offset(r2) as i32); - codegen::gen_get_reg8(ctx.builder, r2); - codegen::gen_get_reg8(ctx.builder, r1); + codegen::gen_get_reg8(ctx, r2); + codegen::gen_get_reg8(ctx, r1); codegen::gen_call_fn2_ret(ctx.builder, $fn); ctx.builder.instruction_body.store_u8(0); } @@ -311,7 +311,7 @@ macro_rules! define_instruction_write_reg16( ($fn:expr, $name_mem:ident, $name_reg:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r) as i32); - codegen::gen_get_reg16(ctx.builder, r); + codegen::gen_get_reg16(ctx, r); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read16(ctx); codegen::gen_call_fn2_ret(ctx.builder, $fn); @@ -320,8 +320,8 @@ macro_rules! define_instruction_write_reg16( pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r2) as i32); - codegen::gen_get_reg16(ctx.builder, r2); - codegen::gen_get_reg16(ctx.builder, r1); + codegen::gen_get_reg16(ctx, r2); + codegen::gen_get_reg16(ctx, r1); codegen::gen_call_fn2_ret(ctx.builder, $fn); ctx.builder.instruction_body.store_aligned_u16(0); } @@ -332,7 +332,7 @@ macro_rules! define_instruction_write_reg32( ($fn:expr, $name_mem:ident, $name_reg:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r) as i32); - codegen::gen_get_reg32(ctx.builder, r); + codegen::gen_get_reg32(ctx, r); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); codegen::gen_call_fn2_ret(ctx.builder, $fn); @@ -341,8 +341,8 @@ macro_rules! define_instruction_write_reg32( pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r2) as i32); - codegen::gen_get_reg32(ctx.builder, r2); - codegen::gen_get_reg32(ctx.builder, r1); + codegen::gen_get_reg32(ctx, r2); + codegen::gen_get_reg32(ctx, r1); codegen::gen_call_fn2_ret(ctx.builder, $fn); ctx.builder.instruction_body.store_aligned_i32(0); } @@ -371,7 +371,7 @@ macro_rules! define_instruction_read_write_mem8( codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); codegen::gen_safe_read_write(ctx, BitSize::BYTE, &address_local, &|ref mut ctx| { - codegen::gen_get_reg8(ctx.builder, r); + codegen::gen_get_reg8(ctx, r); codegen::gen_call_fn2_ret(ctx.builder, $fn); }, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(r as i32); @@ -382,8 +382,8 @@ macro_rules! define_instruction_read_write_mem8( pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { ctx.builder.instruction_body.const_i32(global_pointers::get_reg8_offset(r1) as i32); - codegen::gen_get_reg8(ctx.builder, r1); - codegen::gen_get_reg8(ctx.builder, r2); + codegen::gen_get_reg8(ctx, r1); + codegen::gen_get_reg8(ctx, r2); codegen::gen_call_fn2_ret(ctx.builder, $fn); ctx.builder.instruction_body.store_u8(0); } @@ -407,7 +407,7 @@ macro_rules! define_instruction_read_write_mem8( pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { let imm = mask_imm!(imm, $imm); ctx.builder.instruction_body.const_i32(global_pointers::get_reg8_offset(r1) as i32); - codegen::gen_get_reg8(ctx.builder, r1); + codegen::gen_get_reg8(ctx, r1); ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn2_ret(ctx.builder, $fn); ctx.builder.instruction_body.store_u8(0); @@ -421,7 +421,7 @@ macro_rules! define_instruction_read_write_mem16( codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); codegen::gen_safe_read_write(ctx, BitSize::WORD, &address_local, &|ref mut ctx| { - codegen::gen_get_reg16(ctx.builder, r); + codegen::gen_get_reg16(ctx, r); codegen::gen_call_fn2_ret(ctx.builder, $fn); }, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(r as i32); @@ -432,8 +432,8 @@ macro_rules! define_instruction_read_write_mem16( pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r1) as i32); - codegen::gen_get_reg16(ctx.builder, r1); - codegen::gen_get_reg16(ctx.builder, r2); + codegen::gen_get_reg16(ctx, r1); + codegen::gen_get_reg16(ctx, r2); codegen::gen_call_fn2_ret(ctx.builder, $fn); ctx.builder.instruction_body.store_aligned_u16(0); } @@ -454,7 +454,7 @@ macro_rules! define_instruction_read_write_mem16( pub fn $name_reg(ctx: &mut JitContext, r1: u32) { ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r1) as i32); - codegen::gen_get_reg16(ctx.builder, r1); + codegen::gen_get_reg16(ctx, r1); ctx.builder.instruction_body.const_i32(1); codegen::gen_call_fn2_ret(ctx.builder, $fn); ctx.builder.instruction_body.store_aligned_u16(0); @@ -466,7 +466,7 @@ macro_rules! define_instruction_read_write_mem16( codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); codegen::gen_safe_read_write(ctx, BitSize::WORD, &address_local, &|ref mut ctx| { - codegen::gen_get_reg8(ctx.builder, regs::CL); + codegen::gen_get_reg8(ctx, regs::CL); ctx.builder.instruction_body.const_i32(31); ctx.builder.instruction_body.and_i32(); codegen::gen_call_fn2_ret(ctx.builder, $fn); @@ -478,8 +478,8 @@ macro_rules! define_instruction_read_write_mem16( pub fn $name_reg(ctx: &mut JitContext, r1: u32) { ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r1) as i32); - codegen::gen_get_reg16(ctx.builder, r1); - codegen::gen_get_reg8(ctx.builder, regs::CL); + codegen::gen_get_reg16(ctx, r1); + codegen::gen_get_reg8(ctx, regs::CL); ctx.builder.instruction_body.const_i32(31); ctx.builder.instruction_body.and_i32(); codegen::gen_call_fn2_ret(ctx.builder, $fn); @@ -492,8 +492,8 @@ macro_rules! define_instruction_read_write_mem16( codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); codegen::gen_safe_read_write(ctx, BitSize::WORD, &address_local, &|ref mut ctx| { - codegen::gen_get_reg16(ctx.builder, r); - codegen::gen_get_reg8(ctx.builder, regs::CL); + codegen::gen_get_reg16(ctx, r); + codegen::gen_get_reg8(ctx, regs::CL); ctx.builder.instruction_body.const_i32(31); ctx.builder.instruction_body.and_i32(); codegen::gen_call_fn3_ret(ctx.builder, $fn); @@ -506,9 +506,9 @@ macro_rules! define_instruction_read_write_mem16( pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r1) as i32); - codegen::gen_get_reg16(ctx.builder, r1); - codegen::gen_get_reg16(ctx.builder, r2); - codegen::gen_get_reg8(ctx.builder, regs::CL); + codegen::gen_get_reg16(ctx, r1); + codegen::gen_get_reg16(ctx, r2); + codegen::gen_get_reg8(ctx, regs::CL); ctx.builder.instruction_body.const_i32(31); ctx.builder.instruction_body.and_i32(); codegen::gen_call_fn3_ret(ctx.builder, $fn); @@ -522,7 +522,7 @@ macro_rules! define_instruction_read_write_mem16( let address_local = ctx.builder.set_new_local(); let imm = make_imm_read!(ctx, $imm) as i32; codegen::gen_safe_read_write(ctx, BitSize::WORD, &address_local, &|ref mut ctx| { - codegen::gen_get_reg16(ctx.builder, r); + codegen::gen_get_reg16(ctx, r); ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn3_ret(ctx.builder, $fn); }, &|ref mut ctx| { @@ -536,8 +536,8 @@ macro_rules! define_instruction_read_write_mem16( pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32, imm: u32) { let imm = mask_imm!(imm, $imm); ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r1) as i32); - codegen::gen_get_reg16(ctx.builder, r1); - codegen::gen_get_reg16(ctx.builder, r2); + codegen::gen_get_reg16(ctx, r1); + codegen::gen_get_reg16(ctx, r2); ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn3_ret(ctx.builder, $fn); ctx.builder.instruction_body.store_aligned_u16(0); @@ -558,7 +558,7 @@ macro_rules! define_instruction_read_write_mem16( pub fn $name_reg(ctx: &mut JitContext, r1: u32) { ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r1) as i32); - codegen::gen_get_reg16(ctx.builder, r1); + codegen::gen_get_reg16(ctx, r1); codegen::gen_call_fn1_ret(ctx.builder, $fn); ctx.builder.instruction_body.store_aligned_u16(0); } @@ -582,7 +582,7 @@ macro_rules! define_instruction_read_write_mem16( pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { let imm = mask_imm!(imm, $imm); ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r1) as i32); - codegen::gen_get_reg16(ctx.builder, r1); + codegen::gen_get_reg16(ctx, r1); ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn2_ret(ctx.builder, $fn); ctx.builder.instruction_body.store_aligned_u16(0); @@ -596,7 +596,7 @@ macro_rules! define_instruction_read_write_mem32( codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { - codegen::gen_get_reg32(ctx.builder, r); + codegen::gen_get_reg32(ctx, r); codegen::gen_call_fn2_ret(ctx.builder, $fn); }, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(r as i32); @@ -607,8 +607,8 @@ macro_rules! define_instruction_read_write_mem32( pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r1) as i32); - codegen::gen_get_reg32(ctx.builder, r1); - codegen::gen_get_reg32(ctx.builder, r2); + codegen::gen_get_reg32(ctx, r1); + codegen::gen_get_reg32(ctx, r2); codegen::gen_call_fn2_ret(ctx.builder, $fn); ctx.builder.instruction_body.store_aligned_i32(0); } @@ -629,7 +629,7 @@ macro_rules! define_instruction_read_write_mem32( pub fn $name_reg(ctx: &mut JitContext, r1: u32) { ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r1) as i32); - codegen::gen_get_reg32(ctx.builder, r1); + codegen::gen_get_reg32(ctx, r1); ctx.builder.instruction_body.const_i32(1); codegen::gen_call_fn2_ret(ctx.builder, $fn); ctx.builder.instruction_body.store_aligned_i32(0); @@ -641,7 +641,7 @@ macro_rules! define_instruction_read_write_mem32( codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { - codegen::gen_get_reg8(ctx.builder, regs::CL); + codegen::gen_get_reg8(ctx, regs::CL); ctx.builder.instruction_body.const_i32(31); ctx.builder.instruction_body.and_i32(); codegen::gen_call_fn2_ret(ctx.builder, $fn); @@ -653,8 +653,8 @@ macro_rules! define_instruction_read_write_mem32( pub fn $name_reg(ctx: &mut JitContext, r1: u32) { ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r1) as i32); - codegen::gen_get_reg32(ctx.builder, r1); - codegen::gen_get_reg8(ctx.builder, regs::CL); + codegen::gen_get_reg32(ctx, r1); + codegen::gen_get_reg8(ctx, regs::CL); ctx.builder.instruction_body.const_i32(31); ctx.builder.instruction_body.and_i32(); codegen::gen_call_fn2_ret(ctx.builder, $fn); @@ -667,8 +667,8 @@ macro_rules! define_instruction_read_write_mem32( codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { - codegen::gen_get_reg32(ctx.builder, r); - codegen::gen_get_reg8(ctx.builder, regs::CL); + codegen::gen_get_reg32(ctx, r); + codegen::gen_get_reg8(ctx, regs::CL); ctx.builder.instruction_body.const_i32(31); ctx.builder.instruction_body.and_i32(); codegen::gen_call_fn3_ret(ctx.builder, $fn); @@ -681,9 +681,9 @@ macro_rules! define_instruction_read_write_mem32( pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r1) as i32); - codegen::gen_get_reg32(ctx.builder, r1); - codegen::gen_get_reg32(ctx.builder, r2); - codegen::gen_get_reg8(ctx.builder, regs::CL); + codegen::gen_get_reg32(ctx, r1); + codegen::gen_get_reg32(ctx, r2); + codegen::gen_get_reg8(ctx, regs::CL); ctx.builder.instruction_body.const_i32(31); ctx.builder.instruction_body.and_i32(); codegen::gen_call_fn3_ret(ctx.builder, $fn); @@ -697,7 +697,7 @@ macro_rules! define_instruction_read_write_mem32( let address_local = ctx.builder.set_new_local(); let imm = make_imm_read!(ctx, $imm) as i32; codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { - codegen::gen_get_reg32(ctx.builder, r); + codegen::gen_get_reg32(ctx, r); ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn3_ret(ctx.builder, $fn); }, &|ref mut ctx| { @@ -711,8 +711,8 @@ macro_rules! define_instruction_read_write_mem32( pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32, imm: u32) { let imm = mask_imm!(imm, $imm); ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r1) as i32); - codegen::gen_get_reg32(ctx.builder, r1); - codegen::gen_get_reg32(ctx.builder, r2); + codegen::gen_get_reg32(ctx, r1); + codegen::gen_get_reg32(ctx, r2); ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn3_ret(ctx.builder, $fn); ctx.builder.instruction_body.store_aligned_i32(0); @@ -733,7 +733,7 @@ macro_rules! define_instruction_read_write_mem32( pub fn $name_reg(ctx: &mut JitContext, r1: u32) { ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r1) as i32); - codegen::gen_get_reg32(ctx.builder, r1); + codegen::gen_get_reg32(ctx, r1); codegen::gen_call_fn1_ret(ctx.builder, $fn); ctx.builder.instruction_body.store_aligned_i32(0); } @@ -757,7 +757,7 @@ macro_rules! define_instruction_read_write_mem32( pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { let imm = mask_imm!(imm, $imm); ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r1) as i32); - codegen::gen_get_reg32(ctx.builder, r1); + codegen::gen_get_reg32(ctx, r1); ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn2_ret(ctx.builder, $fn); ctx.builder.instruction_body.store_aligned_i32(0); @@ -1008,41 +1008,41 @@ define_instruction_read16!("cmp16", instr16_39_mem_jit, instr16_39_reg_jit); define_instruction_read32!("cmp32", instr32_39_mem_jit, instr32_39_reg_jit); pub fn instr_3A_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_get_reg8(ctx.builder, r); + codegen::gen_get_reg8(ctx, r); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read8(ctx); codegen::gen_call_fn2(ctx.builder, "cmp8") } pub fn instr_3A_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - codegen::gen_get_reg8(ctx.builder, r2); - codegen::gen_get_reg8(ctx.builder, r1); + codegen::gen_get_reg8(ctx, r2); + codegen::gen_get_reg8(ctx, r1); codegen::gen_call_fn2(ctx.builder, "cmp8") } pub fn instr16_3B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_get_reg16(ctx.builder, r); + codegen::gen_get_reg16(ctx, r); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read16(ctx); codegen::gen_call_fn2(ctx.builder, "cmp16") } pub fn instr16_3B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - codegen::gen_get_reg16(ctx.builder, r2); - codegen::gen_get_reg16(ctx.builder, r1); + codegen::gen_get_reg16(ctx, r2); + codegen::gen_get_reg16(ctx, r1); codegen::gen_call_fn2(ctx.builder, "cmp16") } pub fn instr32_3B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_get_reg32(ctx.builder, r); + codegen::gen_get_reg32(ctx, r); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); codegen::gen_call_fn2(ctx.builder, "cmp32") } pub fn instr32_3B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - codegen::gen_get_reg32(ctx.builder, r2); - codegen::gen_get_reg32(ctx.builder, r1); + codegen::gen_get_reg32(ctx, r2); + codegen::gen_get_reg32(ctx, r1); codegen::gen_call_fn2(ctx.builder, "cmp32") } @@ -1050,7 +1050,7 @@ pub fn instr_3C_jit(ctx: &mut JitContext, imm8: u32) { ctx.builder .instruction_body .const_i32(global_pointers::get_reg8_offset(0) as i32); - codegen::gen_get_reg8(ctx.builder, 0); + codegen::gen_get_reg8(ctx, 0); ctx.builder.instruction_body.const_i32(imm8 as i32); codegen::gen_call_fn2(ctx.builder, "cmp8"); } @@ -1059,7 +1059,7 @@ pub fn instr16_3D_jit(ctx: &mut JitContext, imm16: u32) { ctx.builder .instruction_body .const_i32(global_pointers::get_reg16_offset(0) as i32); - codegen::gen_get_reg16(ctx.builder, 0); + codegen::gen_get_reg16(ctx, 0); ctx.builder.instruction_body.const_i32(imm16 as i32); codegen::gen_call_fn2(ctx.builder, "cmp16"); } @@ -1068,7 +1068,7 @@ pub fn instr32_3D_jit(ctx: &mut JitContext, imm32: u32) { ctx.builder .instruction_body .const_i32(global_pointers::get_reg32_offset(0) as i32); - codegen::gen_get_reg32(ctx.builder, 0); + codegen::gen_get_reg32(ctx, 0); ctx.builder.instruction_body.const_i32(imm32 as i32); codegen::gen_call_fn2(ctx.builder, "cmp32"); } @@ -1126,7 +1126,7 @@ pub fn instr16_69_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm16: u32) { ctx.builder .instruction_body .const_i32(global_pointers::get_reg16_offset(r2) as i32); - codegen::gen_get_reg16(ctx.builder, r1); + codegen::gen_get_reg16(ctx, r1); ctx.builder.instruction_body.const_i32(imm16 as i32); codegen::gen_call_fn2_ret(ctx.builder, "imul_reg16"); ctx.builder.instruction_body.store_aligned_u16(0); @@ -1147,7 +1147,7 @@ pub fn instr32_69_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm32: u32) { ctx.builder .instruction_body .const_i32(global_pointers::get_reg32_offset(r2) as i32); - codegen::gen_get_reg32(ctx.builder, r1); + codegen::gen_get_reg32(ctx, r1); ctx.builder.instruction_body.const_i32(imm32 as i32); codegen::gen_call_fn2_ret(ctx.builder, "imul_reg32"); ctx.builder.instruction_body.store_aligned_i32(0); @@ -1168,7 +1168,7 @@ pub fn instr16_6B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm8s: u32) { ctx.builder .instruction_body .const_i32(global_pointers::get_reg16_offset(r2) as i32); - codegen::gen_get_reg16(ctx.builder, r1); + codegen::gen_get_reg16(ctx, r1); ctx.builder.instruction_body.const_i32(imm8s as i32); codegen::gen_call_fn2_ret(ctx.builder, "imul_reg16"); ctx.builder.instruction_body.store_aligned_u16(0); @@ -1189,7 +1189,7 @@ pub fn instr32_6B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm8s: u32) { ctx.builder .instruction_body .const_i32(global_pointers::get_reg32_offset(r2) as i32); - codegen::gen_get_reg32(ctx.builder, r1); + codegen::gen_get_reg32(ctx, r1); ctx.builder.instruction_body.const_i32(imm8s as i32); codegen::gen_call_fn2_ret(ctx.builder, "imul_reg32"); ctx.builder.instruction_body.store_aligned_i32(0); @@ -1524,7 +1524,7 @@ pub fn instr16_89_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { let address_local = ctx.builder.set_new_local(); - codegen::gen_get_reg16(ctx.builder, r); + codegen::gen_get_reg16(ctx, r); let value_local = ctx.builder.set_new_local(); codegen::gen_safe_write16(ctx, &address_local, &value_local); @@ -1625,7 +1625,7 @@ pub fn instr16_8F_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { ctx.builder .instruction_body .const_i32(global_pointers::get_reg16_offset(regs::SP) as i32); - codegen::gen_get_reg16(ctx.builder, regs::SP); + codegen::gen_get_reg16(ctx, regs::SP); ctx.builder.instruction_body.const_i32(2); ctx.builder.instruction_body.add_i32(); ctx.builder.instruction_body.store_aligned_u16(0); @@ -1640,7 +1640,7 @@ pub fn instr32_8F_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { ctx.builder .instruction_body .const_i32(global_pointers::get_reg32_offset(regs::ESP) as i32); - codegen::gen_get_reg32(ctx.builder, regs::ESP); + codegen::gen_get_reg32(ctx, regs::ESP); ctx.builder.instruction_body.const_i32(4); ctx.builder.instruction_body.add_i32(); ctx.builder.instruction_body.store_aligned_i32(0); @@ -2702,7 +2702,7 @@ pub fn instr_F6_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { } pub fn instr_F6_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { - codegen::gen_get_reg8(ctx.builder, r); + codegen::gen_get_reg8(ctx, r); ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn2(ctx.builder, "test8") } @@ -2723,7 +2723,7 @@ pub fn instr16_F7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { } pub fn instr16_F7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { - codegen::gen_get_reg16(ctx.builder, r); + codegen::gen_get_reg16(ctx, r); ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn2(ctx.builder, "test16") } @@ -2744,7 +2744,7 @@ pub fn instr32_F7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { } pub fn instr32_F7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { - codegen::gen_get_reg32(ctx.builder, r); + codegen::gen_get_reg32(ctx, r); ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn2(ctx.builder, "test32") } @@ -2791,7 +2791,7 @@ pub fn instr16_F7_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_call_fn1(ctx.builder, "mul16") } pub fn instr16_F7_4_reg_jit(ctx: &mut JitContext, r: u32) { - codegen::gen_get_reg16(ctx.builder, r); + codegen::gen_get_reg16(ctx, r); codegen::gen_call_fn1(ctx.builder, "mul16") } pub fn instr32_F7_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { @@ -2800,7 +2800,7 @@ pub fn instr32_F7_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_call_fn1(ctx.builder, "mul32") } pub fn instr32_F7_4_reg_jit(ctx: &mut JitContext, r: u32) { - codegen::gen_get_reg32(ctx.builder, r); + codegen::gen_get_reg32(ctx, r); codegen::gen_call_fn1(ctx.builder, "mul32") } @@ -2811,7 +2811,7 @@ pub fn instr16_F7_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_call_fn1(ctx.builder, "imul16") } pub fn instr16_F7_5_reg_jit(ctx: &mut JitContext, r: u32) { - codegen::gen_get_reg16(ctx.builder, r); + codegen::gen_get_reg16(ctx, r); codegen::sign_extend_i16(ctx.builder); codegen::gen_call_fn1(ctx.builder, "imul16") } @@ -2821,7 +2821,7 @@ pub fn instr32_F7_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_call_fn1(ctx.builder, "imul32") } pub fn instr32_F7_5_reg_jit(ctx: &mut JitContext, r: u32) { - codegen::gen_get_reg32(ctx.builder, r); + codegen::gen_get_reg32(ctx, r); codegen::gen_call_fn1(ctx.builder, "imul32") } @@ -2932,7 +2932,7 @@ pub fn instr_A2_jit(ctx: &mut JitContext, immaddr: u32) { ctx.builder.instruction_body.const_i32(immaddr as i32); jit_add_seg_offset(ctx, regs::DS); let address_local = ctx.builder.set_new_local(); - codegen::gen_get_reg8(ctx.builder, regs::AL); + codegen::gen_get_reg8(ctx, regs::AL); let value_local = ctx.builder.set_new_local(); codegen::gen_safe_write8(ctx, &address_local, &value_local); ctx.builder.free_local(address_local); @@ -2942,7 +2942,7 @@ pub fn instr16_A3_jit(ctx: &mut JitContext, immaddr: u32) { ctx.builder.instruction_body.const_i32(immaddr as i32); jit_add_seg_offset(ctx, regs::DS); let address_local = ctx.builder.set_new_local(); - codegen::gen_get_reg16(ctx.builder, regs::AX); + codegen::gen_get_reg16(ctx, regs::AX); let value_local = ctx.builder.set_new_local(); codegen::gen_safe_write16(ctx, &address_local, &value_local); ctx.builder.free_local(address_local); @@ -2952,7 +2952,7 @@ pub fn instr32_A3_jit(ctx: &mut JitContext, immaddr: u32) { ctx.builder.instruction_body.const_i32(immaddr as i32); jit_add_seg_offset(ctx, regs::DS); let address_local = ctx.builder.set_new_local(); - codegen::gen_get_reg32(ctx.builder, regs::EAX); + codegen::gen_get_reg32(ctx, regs::EAX); let value_local = ctx.builder.set_new_local(); codegen::gen_safe_write32(ctx, &address_local, &value_local); ctx.builder.free_local(address_local); @@ -2963,7 +2963,7 @@ pub fn instr_A8_jit(ctx: &mut JitContext, imm8: u32) { ctx.builder .instruction_body .const_i32(global_pointers::get_reg8_offset(0) as i32); - codegen::gen_get_reg8(ctx.builder, 0); + codegen::gen_get_reg8(ctx, 0); ctx.builder.instruction_body.const_i32(imm8 as i32); codegen::gen_call_fn2(ctx.builder, "test8"); } @@ -2972,7 +2972,7 @@ pub fn instr16_A9_jit(ctx: &mut JitContext, imm16: u32) { ctx.builder .instruction_body .const_i32(global_pointers::get_reg16_offset(0) as i32); - codegen::gen_get_reg16(ctx.builder, 0); + codegen::gen_get_reg16(ctx, 0); ctx.builder.instruction_body.const_i32(imm16 as i32); codegen::gen_call_fn2(ctx.builder, "test16"); } @@ -2981,7 +2981,7 @@ pub fn instr32_A9_jit(ctx: &mut JitContext, imm32: u32) { ctx.builder .instruction_body .const_i32(global_pointers::get_reg32_offset(0) as i32); - codegen::gen_get_reg32(ctx.builder, 0); + codegen::gen_get_reg32(ctx, 0); ctx.builder.instruction_body.const_i32(imm32 as i32); codegen::gen_call_fn2(ctx.builder, "test32"); } @@ -3080,12 +3080,11 @@ define_instruction_read_write_mem32!( ); pub fn instr16_0FB6_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - let builder = &mut ctx.builder; - builder + ctx.builder .instruction_body .const_i32(global_pointers::get_reg16_offset(r2) as i32); - codegen::gen_get_reg8(builder, r1); - builder.instruction_body.store_aligned_u16(0); + codegen::gen_get_reg8(ctx, r1); + ctx.builder.instruction_body.store_aligned_u16(0); } pub fn instr16_0FB6_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { ctx.builder @@ -3097,12 +3096,11 @@ pub fn instr16_0FB6_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { } pub fn instr32_0FB6_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - let builder = &mut ctx.builder; - builder + ctx.builder .instruction_body .const_i32(global_pointers::get_reg32_offset(r2) as i32); - codegen::gen_get_reg8(builder, r1); - builder.instruction_body.store_aligned_i32(0); + codegen::gen_get_reg8(ctx, r1); + ctx.builder.instruction_body.store_aligned_i32(0); } pub fn instr32_0FB6_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { ctx.builder @@ -3122,12 +3120,11 @@ pub fn instr16_0FB7_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { ctx.builder.instruction_body.store_aligned_u16(0); } pub fn instr16_0FB7_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - let builder = &mut ctx.builder; - builder + ctx.builder .instruction_body .const_i32(global_pointers::get_reg16_offset(r2) as i32); - codegen::gen_get_reg16(builder, r1); - builder.instruction_body.store_aligned_u16(0); + codegen::gen_get_reg16(ctx, r1); + ctx.builder.instruction_body.store_aligned_u16(0); } pub fn instr32_0FB7_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { ctx.builder @@ -3138,22 +3135,20 @@ pub fn instr32_0FB7_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { ctx.builder.instruction_body.store_aligned_i32(0); } pub fn instr32_0FB7_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - let builder = &mut ctx.builder; - builder + ctx.builder .instruction_body .const_i32(global_pointers::get_reg32_offset(r2) as i32); - codegen::gen_get_reg16(builder, r1); - builder.instruction_body.store_aligned_i32(0); + codegen::gen_get_reg16(ctx, r1); + ctx.builder.instruction_body.store_aligned_i32(0); } pub fn instr16_0FBE_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - let builder = &mut ctx.builder; - builder + ctx.builder .instruction_body .const_i32(global_pointers::get_reg16_offset(r2) as i32); - codegen::gen_get_reg8(builder, r1); - codegen::sign_extend_i8(builder); - builder.instruction_body.store_aligned_u16(0); + codegen::gen_get_reg8(ctx, r1); + codegen::sign_extend_i8(ctx.builder); + ctx.builder.instruction_body.store_aligned_u16(0); } pub fn instr16_0FBE_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { ctx.builder @@ -3166,13 +3161,12 @@ pub fn instr16_0FBE_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { } pub fn instr32_0FBE_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - let builder = &mut ctx.builder; - builder + ctx.builder .instruction_body .const_i32(global_pointers::get_reg32_offset(r2) as i32); - codegen::gen_get_reg8(builder, r1); - codegen::sign_extend_i8(builder); - builder.instruction_body.store_aligned_i32(0); + codegen::gen_get_reg8(ctx, r1); + codegen::sign_extend_i8(ctx.builder); + ctx.builder.instruction_body.store_aligned_i32(0); } pub fn instr32_0FBE_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { ctx.builder @@ -3188,7 +3182,7 @@ pub fn instr16_0FBF_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { ctx.builder .instruction_body .const_i32(global_pointers::get_reg16_offset(r2) as i32); - codegen::gen_get_reg16(ctx.builder, r1); + codegen::gen_get_reg16(ctx, r1); codegen::sign_extend_i16(ctx.builder); ctx.builder.instruction_body.store_aligned_u16(0); } @@ -3206,7 +3200,7 @@ pub fn instr32_0FBF_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { ctx.builder .instruction_body .const_i32(global_pointers::get_reg32_offset(r2) as i32); - codegen::gen_get_reg16(ctx.builder, r1); + codegen::gen_get_reg16(ctx, r1); codegen::sign_extend_i16(ctx.builder); ctx.builder.instruction_body.store_aligned_i32(0); } @@ -3246,7 +3240,7 @@ pub fn instr16_0FC1_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { ctx.builder .instruction_body .const_i32(global_pointers::get_reg16_offset(r1) as i32); - codegen::gen_get_reg16(ctx.builder, r1); + codegen::gen_get_reg16(ctx, r1); ctx.builder .instruction_body .const_i32(::cpu2::cpu::get_reg16_index(r2 as i32)); @@ -3276,7 +3270,7 @@ pub fn instr32_0FC1_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { ctx.builder .instruction_body .const_i32(global_pointers::get_reg32_offset(r1) as i32); - codegen::gen_get_reg32(ctx.builder, r1); + codegen::gen_get_reg32(ctx, r1); ctx.builder.instruction_body.const_i32(r2 as i32); codegen::gen_call_fn2_ret(ctx.builder, "xadd32"); ctx.builder.instruction_body.store_aligned_i32(0); @@ -3364,7 +3358,7 @@ macro_rules! define_cmovcc16( codegen::gen_condition_fn(ctx.builder, $cond); ctx.builder.instruction_body.if_void(); ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r2) as i32); - codegen::gen_get_reg16(ctx.builder, r1); + codegen::gen_get_reg16(ctx, r1); ctx.builder.instruction_body.store_aligned_u16(0); ctx.builder.instruction_body.block_end(); } @@ -3390,7 +3384,7 @@ macro_rules! define_cmovcc32( codegen::gen_condition_fn(ctx.builder, $cond); ctx.builder.instruction_body.if_void(); ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r2) as i32); - codegen::gen_get_reg32(ctx.builder, r1); + codegen::gen_get_reg32(ctx, r1); ctx.builder.instruction_body.store_aligned_i32(0); ctx.builder.instruction_body.block_end(); } diff --git a/src/rust/modrm.rs b/src/rust/modrm.rs index 897a23de..f5c597f1 100644 --- a/src/rust/modrm.rs +++ b/src/rust/modrm.rs @@ -110,7 +110,7 @@ fn gen16_case(ctx: &mut JitContext, seg: u32, offset: Offset16, imm: Imm16) { .const_i32(immediate_value & 0xFFFF); }, Offset16::One(r) => { - codegen::gen_get_reg16(ctx.builder, r); + codegen::gen_get_reg16(ctx, r); if immediate_value != 0 { ctx.builder.instruction_body.const_i32(immediate_value); @@ -121,8 +121,8 @@ fn gen16_case(ctx: &mut JitContext, seg: u32, offset: Offset16, imm: Imm16) { } }, Offset16::Two(r1, r2) => { - codegen::gen_get_reg16(ctx.builder, r1); - codegen::gen_get_reg16(ctx.builder, r2); + codegen::gen_get_reg16(ctx, r1); + codegen::gen_get_reg16(ctx, r2); ctx.builder.instruction_body.add_i32(); if immediate_value != 0 { @@ -206,7 +206,7 @@ fn gen32_case(ctx: &mut JitContext, seg: u32, offset: Offset, imm: Imm32) { Imm32::Imm8 => ctx.cpu.read_imm8s() as i32, Imm32::Imm32 => ctx.cpu.read_imm32() as i32, }; - codegen::gen_get_reg32(ctx.builder, r); + codegen::gen_get_reg32(ctx, r); if immediate_value != 0 { ctx.builder.instruction_body.const_i32(immediate_value); ctx.builder.instruction_body.add_i32(); @@ -270,12 +270,12 @@ fn gen_sib(ctx: &mut JitContext, mod_is_nonzero: bool) { if r == 4 { seg = SS; - codegen::gen_get_reg32(ctx.builder, ESP); + codegen::gen_get_reg32(ctx, ESP); } else if r == 5 { if mod_is_nonzero { seg = SS; - codegen::gen_get_reg32(ctx.builder, EBP); + codegen::gen_get_reg32(ctx, EBP); } else { seg = DS; @@ -285,7 +285,7 @@ fn gen_sib(ctx: &mut JitContext, mod_is_nonzero: bool) { } else { seg = DS; - codegen::gen_get_reg32(ctx.builder, r as u32); + codegen::gen_get_reg32(ctx, r as u32); } jit_add_seg_offset(ctx, seg); @@ -301,7 +301,7 @@ fn gen_sib(ctx: &mut JitContext, mod_is_nonzero: bool) { let s = sib_byte >> 6 & 3; - codegen::gen_get_reg32(ctx.builder, m as u32); + codegen::gen_get_reg32(ctx, m as u32); ctx.builder.instruction_body.const_i32(s as i32); ctx.builder.instruction_body.shl_i32(); From f5540d9edf5b11a6744c7c972bcbf52661b7f047 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 20 Dec 2018 19:52:36 -0600 Subject: [PATCH 1551/2137] Use pop16_reg_jit for pop esp --- gen/x86_table.js | 2 +- src/rust/jit_instructions.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 2706c6d2..bdb2c572 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -134,7 +134,7 @@ const encodings = [ { opcode: 0x59, custom: 1, os: 1, }, { opcode: 0x5A, custom: 1, os: 1, }, { opcode: 0x5B, custom: 1, os: 1, }, - { opcode: 0x5C, os: 1, block_boundary: 1 }, + { opcode: 0x5C, custom: 1, os: 1, }, { opcode: 0x5D, custom: 1, os: 1, }, { opcode: 0x5E, custom: 1, os: 1, }, { opcode: 0x5F, custom: 1, os: 1, }, diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 0bba9f7f..b23b4724 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1098,7 +1098,8 @@ pub fn instr16_5A_jit(ctx: &mut JitContext) { pop16_reg_jit(ctx, DX); } pub fn instr32_5A_jit(ctx: &mut JitContext) { pop32_reg_jit(ctx, EDX); } pub fn instr16_5B_jit(ctx: &mut JitContext) { pop16_reg_jit(ctx, BX); } pub fn instr32_5B_jit(ctx: &mut JitContext) { pop32_reg_jit(ctx, EBX); } -// hole for pop esp +pub fn instr16_5C_jit(ctx: &mut JitContext) { pop16_reg_jit(ctx, SP); } +pub fn instr32_5C_jit(ctx: &mut JitContext) { pop32_reg_jit(ctx, ESP); } pub fn instr16_5D_jit(ctx: &mut JitContext) { pop16_reg_jit(ctx, BP); } pub fn instr32_5D_jit(ctx: &mut JitContext) { pop32_reg_jit(ctx, EBP); } pub fn instr16_5E_jit(ctx: &mut JitContext) { pop16_reg_jit(ctx, SI); } From 730919e317f51a4536c16bef2c58d3c9921e58f8 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 20 Dec 2018 19:56:21 -0600 Subject: [PATCH 1552/2137] Use gen_trigger_ud for invalid LEA encodings --- src/rust/jit_instructions.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index b23b4724..d7d84202 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1614,12 +1614,12 @@ pub fn instr32_8D_mem_jit(ctx: &mut JitContext, modrm_byte: u8, reg: u32) { ctx.builder.instruction_body.store_aligned_i32(0); } -pub fn instr16_8D_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - codegen::gen_fn2_const(ctx.builder, "instr16_8D_reg", r1, r2); +pub fn instr16_8D_reg_jit(ctx: &mut JitContext, _r1: u32, _r2: u32) { + codegen::gen_trigger_ud(ctx); } -pub fn instr32_8D_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - codegen::gen_fn2_const(ctx.builder, "instr32_8D_reg", r1, r2); +pub fn instr32_8D_reg_jit(ctx: &mut JitContext, _r1: u32, _r2: u32) { + codegen::gen_trigger_ud(ctx); } pub fn instr16_8F_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { From ed5ecda0ae0970ed5f6e7031b5695b4b38b992a4 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 20 Dec 2018 20:02:09 -0600 Subject: [PATCH 1553/2137] Custom implementation for pop [mem] (preparation for registers-in-locals) --- src/rust/cpu2/instructions.rs | 16 ---------- src/rust/jit_instructions.rs | 57 +++++++++++++++++++++-------------- 2 files changed, 35 insertions(+), 38 deletions(-) diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index 68e74d8b..a5e53b3e 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -1604,14 +1604,6 @@ pub unsafe fn instr16_8F_0_mem(modrm_byte: i32) { } } -#[no_mangle] -pub unsafe fn instr16_8F_0_mem_jit(addr: i32) { - adjust_stack_reg(-2); - let stack_value: i32 = return_on_pagefault!(safe_read16(get_stack_pointer(0))); - return_on_pagefault!(safe_write16(addr, stack_value)); - adjust_stack_reg(2); -} - #[no_mangle] pub unsafe fn instr16_8F_0_reg(r: i32) { write_reg16(r, return_on_pagefault!(pop16())); } #[no_mangle] @@ -1632,14 +1624,6 @@ pub unsafe fn instr32_8F_0_mem(modrm_byte: i32) { } } -#[no_mangle] -pub unsafe fn instr32_8F_0_mem_jit(addr: i32) { - adjust_stack_reg(-4); - let stack_value: i32 = return_on_pagefault!(safe_read32s(get_stack_pointer(0))); - return_on_pagefault!(safe_write32(addr, stack_value)); - adjust_stack_reg(4); -} - #[no_mangle] pub unsafe fn instr32_8F_0_reg(r: i32) { write_reg32(r, return_on_pagefault!(pop32s())); } diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index d7d84202..4a5540e0 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1623,35 +1623,48 @@ pub fn instr32_8D_reg_jit(ctx: &mut JitContext, _r1: u32, _r2: u32) { } pub fn instr16_8F_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(regs::SP) as i32); - codegen::gen_get_reg16(ctx, regs::SP); - ctx.builder.instruction_body.const_i32(2); - ctx.builder.instruction_body.add_i32(); - ctx.builder.instruction_body.store_aligned_u16(0); + // before gen_modrm_resolve, update esp to the new value + codegen::gen_adjust_stack_reg(ctx, 2); codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_modrm_fn0(ctx.builder, "instr16_8F_0_mem_jit"); -} -pub fn instr16_8F_0_reg_jit(ctx: &mut JitContext, r: u32) { - codegen::gen_fn1_const(ctx.builder, "instr16_8F_0_reg", r); + let address_local = ctx.builder.set_new_local(); + + // pop takes care of updating esp, so undo the previous change + codegen::gen_adjust_stack_reg(ctx, (-2i32) as u32); + codegen::gen_pop16(ctx); + let value_local = ctx.builder.set_new_local(); + + // undo the esp change of pop, as safe_write16 can fail + codegen::gen_adjust_stack_reg(ctx, (-2i32) as u32); + + codegen::gen_safe_write16(ctx, &address_local, &value_local); + + ctx.builder.free_local(address_local); + ctx.builder.free_local(value_local); + + // finally, actually update esp + codegen::gen_adjust_stack_reg(ctx, 2); } +pub fn instr16_8F_0_reg_jit(ctx: &mut JitContext, r: u32) { pop16_reg_jit(ctx, r); } pub fn instr32_8F_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(regs::ESP) as i32); - codegen::gen_get_reg32(ctx, regs::ESP); - ctx.builder.instruction_body.const_i32(4); - ctx.builder.instruction_body.add_i32(); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_adjust_stack_reg(ctx, 4); codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_modrm_fn0(ctx.builder, "instr32_8F_0_mem_jit"); -} -pub fn instr32_8F_0_reg_jit(ctx: &mut JitContext, r: u32) { - codegen::gen_fn1_const(ctx.builder, "instr32_8F_0_reg", r); + let address_local = ctx.builder.set_new_local(); + + codegen::gen_adjust_stack_reg(ctx, (-4i32) as u32); + codegen::gen_pop32s(ctx); + let value_local = ctx.builder.set_new_local(); + codegen::gen_adjust_stack_reg(ctx, (-4i32) as u32); + + codegen::gen_safe_write32(ctx, &address_local, &value_local); + + ctx.builder.free_local(address_local); + ctx.builder.free_local(value_local); + + codegen::gen_adjust_stack_reg(ctx, 4); } +pub fn instr32_8F_0_reg_jit(ctx: &mut JitContext, r: u32) { pop32_reg_jit(ctx, r); } define_instruction_read_write_mem16!( "rol16", From 9959e758d5f8046406c581c4c156a8804de0726c Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 20 Dec 2018 20:34:14 -0600 Subject: [PATCH 1554/2137] nasmtests: Fix display of integers --- tests/nasm/run.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/nasm/run.js b/tests/nasm/run.js index afa09202..750f5b7a 100755 --- a/tests/nasm/run.js +++ b/tests/nasm/run.js @@ -70,7 +70,7 @@ function format_value(v) { if(typeof v === "number") { - if((v >>> 0) !== v) + if((v >>> 0) !== v && (v | 0) !== v) { return String(v); } From 8838e263c39388ec845f70fbd4ef7a1fdedcab5e Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 20 Dec 2018 21:03:46 -0600 Subject: [PATCH 1555/2137] Profiler: Track number of page faults and wasm bytes generated --- src/browser/print_stats.js | 2 ++ src/rust/cpu2/cpu.rs | 1 + src/rust/jit.rs | 5 +++++ src/rust/profiler.rs | 3 +++ 4 files changed, 11 insertions(+) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index ac0e68eb..9bed9670 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -20,6 +20,7 @@ const print_stats = { "COMPILE_WITH_LOOP_SAFETY", "COMPILE_BASIC_BLOCK", "COMPILE_ENTRY_POINT", + "COMPILE_WASM_TOTAL_BYTES", "CACHE_MISMATCH", "RUN_INTERPRETED", "RUN_INTERPRETED_PENDING", @@ -42,6 +43,7 @@ const print_stats = { "SAFE_WRITE_SLOW_IN_MAPPED_RANGE", "SAFE_WRITE_SLOW_READ_ONLY", "SAFE_WRITE_SLOW_HAS_CODE", + "PAGE_FAULT", "DO_RUN", "DO_MANY_CYCLES", "CYCLE_INTERNAL", diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index a49f9faa..b17b826e 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1267,6 +1267,7 @@ pub unsafe fn trigger_pagefault(write: bool, user: bool, present: bool) { dbg_assert!(false); } } + profiler::stat_increment(PAGE_FAULT); //if *page_fault { // dbg_log!(("double fault")); // dbg_trace(); diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 1a555c78..5977870f 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -857,6 +857,11 @@ fn jit_analyze_and_generate( } } + profiler::stat_increment_by( + stat::COMPILE_WASM_TOTAL_BYTES, + ::c_api::jit_get_op_len() as u64, + ); + dbg_assert!(entry_point_count > 0); cpu::tlb_set_has_code(page, true); diff --git a/src/rust/profiler.rs b/src/rust/profiler.rs index ffdda98a..adf0f2b6 100644 --- a/src/rust/profiler.rs +++ b/src/rust/profiler.rs @@ -6,6 +6,7 @@ pub enum stat { COMPILE_WITH_LOOP_SAFETY, COMPILE_BASIC_BLOCK, COMPILE_ENTRY_POINT, + COMPILE_WASM_TOTAL_BYTES, CACHE_MISMATCH, RUN_INTERPRETED, @@ -33,6 +34,8 @@ pub enum stat { SAFE_WRITE_SLOW_READ_ONLY, SAFE_WRITE_SLOW_HAS_CODE, + PAGE_FAULT, + DO_RUN, DO_MANY_CYCLES, CYCLE_INTERNAL, From 56dc1af7ccda73ab9d93b8cda498c0248bccb3b6 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 25 Dec 2018 00:53:27 +0100 Subject: [PATCH 1556/2137] Split SAFE_WRITE stat into WRITE and READ_WRITE --- src/browser/print_stats.js | 7 +++++++ src/rust/codegen.rs | 4 ++-- src/rust/cpu2/cpu.rs | 26 ++++++++++++++++++++++++++ src/rust/profiler.rs | 8 ++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index 9bed9670..86fa1052 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -43,6 +43,13 @@ const print_stats = { "SAFE_WRITE_SLOW_IN_MAPPED_RANGE", "SAFE_WRITE_SLOW_READ_ONLY", "SAFE_WRITE_SLOW_HAS_CODE", + "SAFE_READ_WRITE_FAST", + "SAFE_READ_WRITE_SLOW_PAGE_CROSSED", + "SAFE_READ_WRITE_SLOW_NOT_VALID", + "SAFE_READ_WRITE_SLOW_NOT_USER", + "SAFE_READ_WRITE_SLOW_IN_MAPPED_RANGE", + "SAFE_READ_WRITE_SLOW_READ_ONLY", + "SAFE_READ_WRITE_SLOW_HAS_CODE", "PAGE_FAULT", "DO_RUN", "DO_MANY_CYCLES", diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 446a197b..c4a8c0d4 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -1139,7 +1139,7 @@ pub fn gen_safe_read_write( ctx.builder.instruction_body.if_void(); if cfg!(feature = "profiler") { - gen_profiler_stat_increment(ctx.builder, profiler::stat::SAFE_WRITE_FAST); + gen_profiler_stat_increment(ctx.builder, profiler::stat::SAFE_READ_WRITE_FAST); } ctx.builder.instruction_body.get_local(&entry_local); @@ -1206,7 +1206,7 @@ pub fn gen_safe_read_write( if cfg!(feature = "profiler") { ctx.builder.instruction_body.get_local(&address_local); ctx.builder.instruction_body.get_local(&entry_local); - gen_call_fn2(ctx.builder, "report_safe_write_jit_slow"); + gen_call_fn2(ctx.builder, "report_safe_read_write_jit_slow"); } ctx.builder diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index b17b826e..a2c208b0 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -2124,6 +2124,32 @@ pub fn report_safe_write_jit_slow(address: u32, entry: i32) { } } +#[no_mangle] +#[cfg(feature = "profiler")] +pub fn report_safe_read_write_jit_slow(address: u32, entry: i32) { + if entry & TLB_VALID == 0 { + profiler::stat_increment(SAFE_READ_WRITE_SLOW_NOT_VALID); + } + else if entry & TLB_IN_MAPPED_RANGE != 0 { + profiler::stat_increment(SAFE_READ_WRITE_SLOW_IN_MAPPED_RANGE); + } + else if entry & TLB_HAS_CODE != 0 { + profiler::stat_increment(SAFE_READ_WRITE_SLOW_HAS_CODE); + } + else if entry & TLB_READONLY != 0 { + profiler::stat_increment(SAFE_READ_WRITE_SLOW_READ_ONLY); + } + else if entry & TLB_NO_USER != 0 { + profiler::stat_increment(SAFE_READ_WRITE_SLOW_NOT_USER); + } + else if address & 0xFFF > 0x1000 - 16 { + profiler::stat_increment(SAFE_READ_WRITE_SLOW_PAGE_CROSSED); + } + else { + dbg_assert!(false); + } +} + pub unsafe fn safe_read32s_slow(addr: i32) -> OrPageFault { if addr & 0xFFF >= 0xFFD { return Ok(safe_read16(addr)? | safe_read16(addr + 2)? << 16); diff --git a/src/rust/profiler.rs b/src/rust/profiler.rs index adf0f2b6..d05d59af 100644 --- a/src/rust/profiler.rs +++ b/src/rust/profiler.rs @@ -34,6 +34,14 @@ pub enum stat { SAFE_WRITE_SLOW_READ_ONLY, SAFE_WRITE_SLOW_HAS_CODE, + SAFE_READ_WRITE_FAST, + SAFE_READ_WRITE_SLOW_PAGE_CROSSED, + SAFE_READ_WRITE_SLOW_NOT_VALID, + SAFE_READ_WRITE_SLOW_NOT_USER, + SAFE_READ_WRITE_SLOW_IN_MAPPED_RANGE, + SAFE_READ_WRITE_SLOW_READ_ONLY, + SAFE_READ_WRITE_SLOW_HAS_CODE, + PAGE_FAULT, DO_RUN, From a8308b988d9559c99783a7ee306d5abb32508f21 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 25 Dec 2018 11:42:03 +0100 Subject: [PATCH 1557/2137] Store registers in locals This changes registers to be temporarily stored in wasm locals, across each complete wasm module. Registers are moved from memory to locals upon entering the wasm module and moved from locals to memory upon leaving. Additionally, calls to functions that modify registers are wrapped between moving registers to memory before and moving back to locals after. This affects: 1. All non-custom instructions 2. safe_{read,write}_slow, since it may page fault (the slow path of all memory accesses) 3. task_switch_test* and trigger_ud 4. All block boundaries 5. The fallback functions of gen_safe_read_write (read-modify-write memory accesses) The performance benefits are currently mostly eaten up by 1. and 4. (if one calculates the total number of read/writes to registers in memory, they are higher after this patch, as each instructions of typ 1. or 4. requires moving all 8 register twice). This can be improved later by the relatively mechanical work of making instructions custom (not necessarily full code generation, only the part of the instruction where registers are accessed). Multi-page wasm module generation will significantly reduce the number of type 4. instructions. Due to 2., the overall code size has significantly increased. This case (the slow path of memory access) is often generated but rarely executed. These moves can be removed in a later patch by a different scheme for safe_{read,write}_slow, which has been left out of this patch for simplicity of reviewing. This also simplifies our code generation for storing registers, as instructions_body.const_i32(register_offset); // some computations ... instruction_body.store_i32(); turns into: // some computations ... write_register(register_index); I.e., a prefix is not necessary anymore as locals are indexed directly. Further patches will allow getting rid of some temporary locals, as registers now can be used directly. --- gen/generate_analyzer.js | 12 + gen/generate_jit.js | 17 ++ gen/x86_table.js | 10 +- src/rust/analysis.rs | 2 + src/rust/codegen.rs | 486 ++++++++++++++++++++--------------- src/rust/jit.rs | 152 ++++++----- src/rust/jit_instructions.rs | 446 +++++++++++--------------------- src/rust/regs.rs | 6 + 8 files changed, 551 insertions(+), 580 deletions(-) diff --git a/gen/generate_analyzer.js b/gen/generate_analyzer.js index 0e9463f8..ef831c23 100755 --- a/gen/generate_analyzer.js +++ b/gen/generate_analyzer.js @@ -227,6 +227,18 @@ function gen_instruction_body_after_fixed_g(encoding, size) instruction_postfix.push("analysis.no_next_instruction = true;"); } + if(!encoding.prefix) + { + if(encoding.custom && !encoding.unguarded_register || encoding.no_register) + { + instruction_postfix.push("analysis.unguarded_register = false;"); + } + else + { + instruction_postfix.push("analysis.unguarded_register = true;"); + } + } + if(encoding.prefix) { const instruction_name = "::analysis::" + make_instruction_name(encoding, size) + "_analyze"; diff --git a/gen/generate_jit.js b/gen/generate_jit.js index 2c890734..a8c37062 100755 --- a/gen/generate_jit.js +++ b/gen/generate_jit.js @@ -239,6 +239,23 @@ function gen_instruction_body_after_fixed_g(encoding, size) const instruction_name = make_instruction_name(encoding, size); + if(!encoding.prefix) + { + if(encoding.custom && !encoding.unguarded_register || encoding.no_register) + { + } + else + { + instruction_prefix.push( + gen_call("::codegen::gen_move_registers_from_locals_to_memory", ["ctx"]) + ); + instruction_postfix.push( + gen_call("::codegen::gen_move_registers_from_memory_to_locals", ["ctx"]) + ); + + } + } + if(encoding.e) { const reg_postfix = []; diff --git a/gen/x86_table.js b/gen/x86_table.js index bdb2c572..57bcc33d 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -390,8 +390,8 @@ const encodings = [ { opcode: 0xF7, os: 1, e: 1, fixed_g: 1, imm1632: 1, custom: 1 }, { opcode: 0xF7, os: 1, e: 1, fixed_g: 2, custom: 1 }, { opcode: 0xF7, os: 1, e: 1, fixed_g: 3, custom: 1 }, - { opcode: 0xF7, os: 1, e: 1, fixed_g: 4, mask_flags: zf | af, custom: 1 }, - { opcode: 0xF7, os: 1, e: 1, fixed_g: 5, mask_flags: zf | af, custom: 1 }, + { opcode: 0xF7, os: 1, e: 1, fixed_g: 4, mask_flags: zf | af, custom: 0, unguarded_register: 1 }, // XXX: Put custom back + { opcode: 0xF7, os: 1, e: 1, fixed_g: 5, mask_flags: zf | af, custom: 0, unguarded_register: 1 }, // XXX: Put custom back { opcode: 0xF7, os: 1, e: 1, fixed_g: 6, block_boundary: 1, }, // div/idiv: Not a block boundary, but doesn't use control flow exceptions { opcode: 0xF7, os: 1, e: 1, fixed_g: 7, block_boundary: 1, }, @@ -401,8 +401,8 @@ const encodings = [ { opcode: 0xFA, block_boundary: 1, skip: 1, }, // sti: not a jump, but can cause a change in eip { opcode: 0xFB, block_boundary: 1, skip: 1, }, - { opcode: 0xFC, }, - { opcode: 0xFD, }, + { opcode: 0xFC, no_register: 1, }, + { opcode: 0xFD, no_register: 1, }, { opcode: 0xFE, e: 1, fixed_g: 0, }, { opcode: 0xFE, e: 1, fixed_g: 1, }, @@ -604,7 +604,7 @@ const encodings = [ { opcode: 0x0FBF, os: 1, e: 1, custom: 1 }, { opcode: 0x0FC0, e: 1, }, // xadd - { opcode: 0x0FC1, os: 1, e: 1, custom: 1 }, + { opcode: 0x0FC1, os: 1, e: 1, custom: 0, unguarded_register: 1 }, // XXX: Add custom back { opcode: 0x0FC8, }, // bswap { opcode: 0x0FC9, }, diff --git a/src/rust/analysis.rs b/src/rust/analysis.rs index d537b2ff..c0ac7a25 100644 --- a/src/rust/analysis.rs +++ b/src/rust/analysis.rs @@ -18,12 +18,14 @@ pub enum AnalysisType { pub struct Analysis { pub no_next_instruction: bool, pub ty: AnalysisType, + pub unguarded_register: bool, } pub fn analyze_step(mut cpu: &mut CpuContext) -> Analysis { let mut analysis = Analysis { no_next_instruction: false, ty: AnalysisType::Normal, + unguarded_register: false, }; cpu.prefixes = 0; let opcode = cpu.read_imm8() as u32 | (cpu.osize_32() as u32) << 8; diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index c4a8c0d4..a2c24484 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -67,24 +67,103 @@ pub fn gen_increment_mem32(builder: &mut WasmBuilder, addr: u32) { } pub fn gen_get_reg8(ctx: &mut JitContext, r: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg8_offset(r) as i32); - ctx.builder.instruction_body.load_u8_from_stack(0); + match r { + regs::AL | regs::CL | regs::DL | regs::BL => { + ctx.builder + .instruction_body + .get_local(&ctx.register_locals[r as usize]); + ctx.builder.instruction_body.const_i32(0xFF); + ctx.builder.instruction_body.and_i32(); + }, + regs::AH | regs::CH | regs::DH | regs::BH => { + ctx.builder + .instruction_body + .get_local(&ctx.register_locals[(r - 4) as usize]); + ctx.builder.instruction_body.const_i32(8); + ctx.builder.instruction_body.shr_u_i32(); + ctx.builder.instruction_body.const_i32(0xFF); + ctx.builder.instruction_body.and_i32(); + }, + _ => assert!(false), + } } pub fn gen_get_reg16(ctx: &mut JitContext, r: u32) { ctx.builder .instruction_body - .const_i32(global_pointers::get_reg16_offset(r) as i32); - ctx.builder.instruction_body.load_aligned_u16_from_stack(0); + .get_local(&ctx.register_locals[r as usize]); + ctx.builder.instruction_body.const_i32(0xFFFF); + ctx.builder.instruction_body.and_i32(); } pub fn gen_get_reg32(ctx: &mut JitContext, r: u32) { ctx.builder .instruction_body - .const_i32(global_pointers::get_reg32_offset(r) as i32); - ctx.builder.instruction_body.load_aligned_i32_from_stack(0); + .get_local(&ctx.register_locals[r as usize]); +} + +pub fn gen_set_reg8(ctx: &mut JitContext, r: u32) { + match r { + regs::AL | regs::CL | regs::DL | regs::BL => { + // reg32[r] = stack_value & 0xFF | reg32[r] & ~0xFF + ctx.builder.instruction_body.const_i32(0xFF); + ctx.builder.instruction_body.and_i32(); + + ctx.builder + .instruction_body + .get_local(&ctx.register_locals[r as usize]); + ctx.builder.instruction_body.const_i32(!0xFF); + ctx.builder.instruction_body.and_i32(); + + ctx.builder.instruction_body.or_i32(); + ctx.builder + .instruction_body + .set_local(&ctx.register_locals[r as usize]); + }, + regs::AH | regs::CH | regs::DH | regs::BH => { + // reg32[r] = stack_value << 8 & 0xFF00 | reg32[r] & ~0xFF00 + ctx.builder.instruction_body.const_i32(8); + ctx.builder.instruction_body.shl_i32(); + ctx.builder.instruction_body.const_i32(0xFF00); + ctx.builder.instruction_body.and_i32(); + + ctx.builder + .instruction_body + .get_local(&ctx.register_locals[(r - 4) as usize]); + ctx.builder.instruction_body.const_i32(!0xFF00); + ctx.builder.instruction_body.and_i32(); + + ctx.builder.instruction_body.or_i32(); + ctx.builder + .instruction_body + .set_local(&ctx.register_locals[(r - 4) as usize]); + }, + _ => assert!(false), + } +} + +pub fn gen_set_reg16(ctx: &mut JitContext, r: u32) { + // reg32[r] = v & 0xFFFF | reg32[r] & ~0xFFFF + + ctx.builder.instruction_body.const_i32(0xFFFF); + ctx.builder.instruction_body.and_i32(); + + ctx.builder + .instruction_body + .get_local(&ctx.register_locals[r as usize]); + ctx.builder.instruction_body.const_i32(!0xFFFF); + ctx.builder.instruction_body.and_i32(); + + ctx.builder.instruction_body.or_i32(); + ctx.builder + .instruction_body + .set_local(&ctx.register_locals[r as usize]); +} + +pub fn gen_set_reg32(ctx: &mut JitContext, r: u32) { + ctx.builder + .instruction_body + .set_local(&ctx.register_locals[r as usize]); } /// sign-extend a byte value on the stack and leave it on the stack @@ -241,27 +320,18 @@ pub fn gen_modrm_resolve(ctx: &mut JitContext, modrm_byte: u8) { modrm::gen(ctx, pub fn gen_set_reg8_r(ctx: &mut JitContext, dest: u32, src: u32) { // generates: reg8[r_dest] = reg8[r_src] - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg8_offset(dest) as i32); gen_get_reg8(ctx, src); - ctx.builder.instruction_body.store_u8(0); + gen_set_reg8(ctx, dest); } pub fn gen_set_reg16_r(ctx: &mut JitContext, dest: u32, src: u32) { // generates: reg16[r_dest] = reg16[r_src] - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(dest) as i32); gen_get_reg16(ctx, src); - ctx.builder.instruction_body.store_aligned_u16(0); + gen_set_reg16(ctx, dest); } pub fn gen_set_reg32_r(ctx: &mut JitContext, dest: u32, src: u32) { // generates: reg32s[r_dest] = reg32s[r_src] - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(dest) as i32); gen_get_reg32(ctx, src); - ctx.builder.instruction_body.store_aligned_i32(0); + gen_set_reg32(ctx, dest); } pub fn gen_safe_read8(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::BYTE, None) } @@ -333,117 +403,118 @@ pub fn gen_safe_write128( fn gen_safe_read(ctx: &mut JitContext, bits: BitSize, where_to_write: Option) { // Assumes virtual address has been pushed to the stack, and generates safe_readXX's fast-path // inline, bailing to safe_readXX_slow if necessary - let builder = &mut ctx.builder; - let address_local = builder.tee_new_local(); + let address_local = ctx.builder.tee_new_local(); // Pseudo: base_on_stack = (uint32_t)address >> 12; - builder.instruction_body.const_i32(12); - builder.instruction_body.shr_u_i32(); + ctx.builder.instruction_body.const_i32(12); + ctx.builder.instruction_body.shr_u_i32(); // scale index - builder.instruction_body.const_i32(2); - builder.instruction_body.shl_i32(); + ctx.builder.instruction_body.const_i32(2); + ctx.builder.instruction_body.shl_i32(); // Pseudo: entry = tlb_data[base_on_stack]; - builder + ctx.builder .instruction_body .load_aligned_i32_from_stack(global_pointers::TLB_DATA); - let entry_local = builder.tee_new_local(); + let entry_local = ctx.builder.tee_new_local(); // Pseudo: bool can_use_fast_path = // (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~TLB_HAS_CODE & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && // (bitsize == 8 ? true : (address & 0xFFF) <= (0x1000 - (bitsize / 8))); - builder.instruction_body.const_i32( + ctx.builder.instruction_body.const_i32( (0xFFF & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32, ); - builder.instruction_body.and_i32(); + ctx.builder.instruction_body.and_i32(); - builder.instruction_body.const_i32(TLB_VALID as i32); - builder.instruction_body.eq_i32(); + ctx.builder.instruction_body.const_i32(TLB_VALID as i32); + ctx.builder.instruction_body.eq_i32(); if bits != BitSize::BYTE { - builder.instruction_body.get_local(&address_local); - builder.instruction_body.const_i32(0xFFF); - builder.instruction_body.and_i32(); - builder + ctx.builder.instruction_body.get_local(&address_local); + ctx.builder.instruction_body.const_i32(0xFFF); + ctx.builder.instruction_body.and_i32(); + ctx.builder .instruction_body .const_i32(0x1000 - bits.bytes() as i32); - builder.instruction_body.le_i32(); + ctx.builder.instruction_body.le_i32(); - builder.instruction_body.and_i32(); + ctx.builder.instruction_body.and_i32(); } // Pseudo: // if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]); if bits == BitSize::DQWORD { - builder.instruction_body.if_void(); + ctx.builder.instruction_body.if_void(); } else if bits == BitSize::QWORD { - builder.instruction_body.if_i64(); + ctx.builder.instruction_body.if_i64(); } else { - builder.instruction_body.if_i32(); + ctx.builder.instruction_body.if_i32(); } if cfg!(feature = "profiler") { - gen_profiler_stat_increment(builder, profiler::stat::SAFE_READ_FAST); + gen_profiler_stat_increment(ctx.builder, profiler::stat::SAFE_READ_FAST); } - builder.instruction_body.get_local(&entry_local); - builder.instruction_body.const_i32(!0xFFF); - builder.instruction_body.and_i32(); - builder.instruction_body.get_local(&address_local); - builder.instruction_body.xor_i32(); + ctx.builder.instruction_body.get_local(&entry_local); + ctx.builder.instruction_body.const_i32(!0xFFF); + ctx.builder.instruction_body.and_i32(); + ctx.builder.instruction_body.get_local(&address_local); + ctx.builder.instruction_body.xor_i32(); // where_to_write is only used by dqword dbg_assert!((where_to_write != None) == (bits == BitSize::DQWORD)); match bits { BitSize::BYTE => { - builder + ctx.builder .instruction_body .load_u8_from_stack(unsafe { mem8 } as u32); }, BitSize::WORD => { - builder + ctx.builder .instruction_body .load_unaligned_u16_from_stack(unsafe { mem8 } as u32); }, BitSize::DWORD => { - builder + ctx.builder .instruction_body .load_unaligned_i32_from_stack(unsafe { mem8 } as u32); }, BitSize::QWORD => { - builder + ctx.builder .instruction_body .load_unaligned_i64_from_stack(unsafe { mem8 } as u32); }, BitSize::DQWORD => { let where_to_write = where_to_write.unwrap(); - let virt_address_local = builder.set_new_local(); - builder.instruction_body.const_i32(0); - builder.instruction_body.get_local(&virt_address_local); - builder + let virt_address_local = ctx.builder.set_new_local(); + ctx.builder.instruction_body.const_i32(0); + ctx.builder.instruction_body.get_local(&virt_address_local); + ctx.builder .instruction_body .load_unaligned_i64_from_stack(unsafe { mem8 } as u32); - builder.instruction_body.store_unaligned_i64(where_to_write); + ctx.builder + .instruction_body + .store_unaligned_i64(where_to_write); - builder.instruction_body.const_i32(0); - builder.instruction_body.get_local(&virt_address_local); - builder + ctx.builder.instruction_body.const_i32(0); + ctx.builder.instruction_body.get_local(&virt_address_local); + ctx.builder .instruction_body .load_unaligned_i64_from_stack(unsafe { mem8 } as u32 + 8); - builder + ctx.builder .instruction_body .store_unaligned_i64(where_to_write + 8); - builder.free_local(virt_address_local); + ctx.builder.free_local(virt_address_local); }, } @@ -453,65 +524,68 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize, where_to_write: Option { - gen_call_fn1_ret(builder, "safe_read8_slow_jit"); + gen_call_fn1_ret(ctx.builder, "safe_read8_slow_jit"); }, BitSize::WORD => { - gen_call_fn1_ret(builder, "safe_read16_slow_jit"); + gen_call_fn1_ret(ctx.builder, "safe_read16_slow_jit"); }, BitSize::DWORD => { - gen_call_fn1_ret(builder, "safe_read32s_slow_jit"); + gen_call_fn1_ret(ctx.builder, "safe_read32s_slow_jit"); }, BitSize::QWORD => { - gen_call_fn1_ret_i64(builder, "safe_read64s_slow_jit"); + gen_call_fn1_ret_i64(ctx.builder, "safe_read64s_slow_jit"); }, BitSize::DQWORD => { - builder + ctx.builder .instruction_body .const_i32(where_to_write.unwrap() as i32); - gen_call_fn2(builder, "safe_read128s_slow_jit"); + gen_call_fn2(ctx.builder, "safe_read128s_slow_jit"); }, } + gen_move_registers_from_memory_to_locals(ctx); - builder + ctx.builder .instruction_body .load_u8(global_pointers::PAGE_FAULT); - builder.instruction_body.if_void(); - gen_debug_track_jit_exit(builder, ctx.start_of_current_instruction); - builder.instruction_body.return_(); - builder.instruction_body.block_end(); + ctx.builder.instruction_body.if_void(); + gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); + gen_move_registers_from_locals_to_memory(ctx); + ctx.builder.instruction_body.return_(); + ctx.builder.instruction_body.block_end(); - builder.instruction_body.block_end(); + ctx.builder.instruction_body.block_end(); - builder.free_local(address_local); - builder.free_local(entry_local); + ctx.builder.free_local(address_local); + ctx.builder.free_local(entry_local); } fn gen_safe_write( @@ -522,102 +596,102 @@ fn gen_safe_write( ) { // Generates safe_writeXX' fast-path inline, bailing to safe_writeXX_slow if necessary. - let builder = &mut ctx.builder; - - builder.instruction_body.get_local(&address_local); + ctx.builder.instruction_body.get_local(&address_local); // Pseudo: base_on_stack = (uint32_t)address >> 12; - builder.instruction_body.const_i32(12); - builder.instruction_body.shr_u_i32(); + ctx.builder.instruction_body.const_i32(12); + ctx.builder.instruction_body.shr_u_i32(); // scale index - builder.instruction_body.const_i32(2); - builder.instruction_body.shl_i32(); + ctx.builder.instruction_body.const_i32(2); + ctx.builder.instruction_body.shl_i32(); // Pseudo: entry = tlb_data[base_on_stack]; - builder + ctx.builder .instruction_body .load_aligned_i32_from_stack(global_pointers::TLB_DATA); - let entry_local = builder.tee_new_local(); + let entry_local = ctx.builder.tee_new_local(); // Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID && // (address & 0xFFF) <= (0x1000 - bitsize / 8)); - builder + ctx.builder .instruction_body .const_i32((0xFFF & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32); - builder.instruction_body.and_i32(); + ctx.builder.instruction_body.and_i32(); - builder.instruction_body.const_i32(TLB_VALID as i32); - builder.instruction_body.eq_i32(); + ctx.builder.instruction_body.const_i32(TLB_VALID as i32); + ctx.builder.instruction_body.eq_i32(); if bits != BitSize::BYTE { - builder.instruction_body.get_local(&address_local); - builder.instruction_body.const_i32(0xFFF); - builder.instruction_body.and_i32(); - builder + ctx.builder.instruction_body.get_local(&address_local); + ctx.builder.instruction_body.const_i32(0xFFF); + ctx.builder.instruction_body.and_i32(); + ctx.builder .instruction_body .const_i32(0x1000 - bits.bytes() as i32); - builder.instruction_body.le_i32(); + ctx.builder.instruction_body.le_i32(); - builder.instruction_body.and_i32(); + ctx.builder.instruction_body.and_i32(); } // Pseudo: // if(can_use_fast_path) // { // phys_addr = entry & ~0xFFF ^ address; - builder.instruction_body.if_void(); + ctx.builder.instruction_body.if_void(); if cfg!(feature = "profiler") { - gen_profiler_stat_increment(builder, profiler::stat::SAFE_WRITE_FAST); + gen_profiler_stat_increment(ctx.builder, profiler::stat::SAFE_WRITE_FAST); } - builder.instruction_body.get_local(&entry_local); - builder.instruction_body.const_i32(!0xFFF); - builder.instruction_body.and_i32(); - builder.instruction_body.get_local(&address_local); - builder.instruction_body.xor_i32(); + ctx.builder.instruction_body.get_local(&entry_local); + ctx.builder.instruction_body.const_i32(!0xFFF); + ctx.builder.instruction_body.and_i32(); + ctx.builder.instruction_body.get_local(&address_local); + ctx.builder.instruction_body.xor_i32(); // Pseudo: // /* continued within can_use_fast_path branch */ // mem8[phys_addr] = value; match value_local { - GenSafeWriteValue::I32(local) => builder.instruction_body.get_local(local), - GenSafeWriteValue::I64(local) => builder.instruction_body.get_local_i64(local), + GenSafeWriteValue::I32(local) => ctx.builder.instruction_body.get_local(local), + GenSafeWriteValue::I64(local) => ctx.builder.instruction_body.get_local_i64(local), GenSafeWriteValue::TwoI64s(local1, local2) => { assert!(bits == BitSize::DQWORD); - let virt_address_local = builder.tee_new_local(); - builder.instruction_body.get_local_i64(local1); - builder + let virt_address_local = ctx.builder.tee_new_local(); + ctx.builder.instruction_body.get_local_i64(local1); + ctx.builder .instruction_body .store_unaligned_i64(unsafe { mem8 } as u32); - builder.instruction_body.get_local(&virt_address_local); - builder.instruction_body.get_local_i64(local2); - builder + ctx.builder.instruction_body.get_local(&virt_address_local); + ctx.builder.instruction_body.get_local_i64(local2); + ctx.builder .instruction_body .store_unaligned_i64(unsafe { mem8 } as u32 + 8); - builder.free_local(virt_address_local); + ctx.builder.free_local(virt_address_local); }, } match bits { BitSize::BYTE => { - builder.instruction_body.store_u8(unsafe { mem8 } as u32); + ctx.builder + .instruction_body + .store_u8(unsafe { mem8 } as u32); }, BitSize::WORD => { - builder + ctx.builder .instruction_body .store_unaligned_u16(unsafe { mem8 } as u32); }, BitSize::DWORD => { - builder + ctx.builder .instruction_body .store_unaligned_i32(unsafe { mem8 } as u32); }, BitSize::QWORD => { - builder + ctx.builder .instruction_body .store_unaligned_i64(unsafe { mem8 } as u32); }, @@ -630,69 +704,72 @@ fn gen_safe_write( // safe_write*_slow(address, value); // if(page_fault) return; // } - builder.instruction_body.else_(); + ctx.builder.instruction_body.else_(); if cfg!(feature = "profiler") { - builder.instruction_body.get_local(&address_local); - builder.instruction_body.get_local(&entry_local); - gen_call_fn2(builder, "report_safe_write_jit_slow"); + ctx.builder.instruction_body.get_local(&address_local); + ctx.builder.instruction_body.get_local(&entry_local); + gen_call_fn2(ctx.builder, "report_safe_write_jit_slow"); } - builder + ctx.builder .instruction_body .const_i32(global_pointers::PREVIOUS_IP as i32); - builder + ctx.builder .instruction_body .load_aligned_i32(global_pointers::INSTRUCTION_POINTER); - builder.instruction_body.const_i32(!0xFFF); - builder.instruction_body.and_i32(); - builder + ctx.builder.instruction_body.const_i32(!0xFFF); + ctx.builder.instruction_body.and_i32(); + ctx.builder .instruction_body .const_i32(ctx.start_of_current_instruction as i32 & 0xFFF); - builder.instruction_body.or_i32(); + ctx.builder.instruction_body.or_i32(); - builder.instruction_body.store_aligned_i32(0); + ctx.builder.instruction_body.store_aligned_i32(0); - builder.instruction_body.get_local(&address_local); + ctx.builder.instruction_body.get_local(&address_local); match value_local { - GenSafeWriteValue::I32(local) => builder.instruction_body.get_local(local), - GenSafeWriteValue::I64(local) => builder.instruction_body.get_local_i64(local), + GenSafeWriteValue::I32(local) => ctx.builder.instruction_body.get_local(local), + GenSafeWriteValue::I64(local) => ctx.builder.instruction_body.get_local_i64(local), GenSafeWriteValue::TwoI64s(local1, local2) => { - builder.instruction_body.get_local_i64(local1); - builder.instruction_body.get_local_i64(local2) + ctx.builder.instruction_body.get_local_i64(local1); + ctx.builder.instruction_body.get_local_i64(local2) }, } + gen_move_registers_from_locals_to_memory(ctx); match bits { BitSize::BYTE => { - gen_call_fn2(builder, "safe_write8_slow_jit"); + gen_call_fn2(ctx.builder, "safe_write8_slow_jit"); }, BitSize::WORD => { - gen_call_fn2(builder, "safe_write16_slow_jit"); + gen_call_fn2(ctx.builder, "safe_write16_slow_jit"); }, BitSize::DWORD => { - gen_call_fn2(builder, "safe_write32_slow_jit"); + gen_call_fn2(ctx.builder, "safe_write32_slow_jit"); }, BitSize::QWORD => { - gen_call_fn2_i32_i64(builder, "safe_write64_slow_jit"); + gen_call_fn2_i32_i64(ctx.builder, "safe_write64_slow_jit"); }, BitSize::DQWORD => { - gen_call_fn3_i32_i64_i64(builder, "safe_write128_slow_jit"); + gen_call_fn3_i32_i64_i64(ctx.builder, "safe_write128_slow_jit"); }, } + gen_move_registers_from_memory_to_locals(ctx); - builder + ctx.builder .instruction_body .load_u8(global_pointers::PAGE_FAULT); - builder.instruction_body.if_void(); - gen_debug_track_jit_exit(builder, ctx.start_of_current_instruction); - builder.instruction_body.return_(); - builder.instruction_body.block_end(); + ctx.builder.instruction_body.if_void(); + gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); + gen_move_registers_from_locals_to_memory(ctx); + ctx.builder.instruction_body.return_(); + ctx.builder.instruction_body.block_end(); - builder.instruction_body.block_end(); + ctx.builder.instruction_body.block_end(); - builder.free_local(entry_local); + ctx.builder.free_local(entry_local); } pub fn gen_clear_prefixes(ctx: &mut JitContext) { @@ -761,13 +838,10 @@ pub fn gen_pop16_ss16(ctx: &mut JitContext) { gen_safe_read16(ctx); // reg16[SP] += 2; - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(regs::SP) as i32); ctx.builder.instruction_body.get_local(&sp_local); ctx.builder.instruction_body.const_i32(2); ctx.builder.instruction_body.add_i32(); - ctx.builder.instruction_body.store_aligned_u16(0); + gen_set_reg16(ctx, regs::SP); ctx.builder.free_local(sp_local); @@ -790,13 +864,10 @@ pub fn gen_pop16_ss32(ctx: &mut JitContext) { gen_safe_read16(ctx); // reg32s[ESP] += 2; - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(regs::ESP) as i32); ctx.builder.instruction_body.get_local(&esp_local); ctx.builder.instruction_body.const_i32(2); ctx.builder.instruction_body.add_i32(); - ctx.builder.instruction_body.store_aligned_i32(0); + gen_set_reg32(ctx, regs::ESP); ctx.builder.free_local(esp_local); // return value is already on stack @@ -827,13 +898,10 @@ pub fn gen_pop32s_ss16(ctx: &mut JitContext) { gen_safe_read32(ctx); // reg16[SP] = sp + 4; - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(regs::SP) as i32); ctx.builder.instruction_body.get_local(&local_sp); ctx.builder.instruction_body.const_i32(4); ctx.builder.instruction_body.add_i32(); - ctx.builder.instruction_body.store_aligned_u16(0); + gen_set_reg16(ctx, regs::SP); ctx.builder.free_local(local_sp); @@ -855,13 +923,10 @@ pub fn gen_pop32s_ss32(ctx: &mut JitContext) { gen_safe_read32(ctx); // reg32s[ESP] = esp + 4; - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(regs::ESP) as i32); ctx.builder.instruction_body.get_local(&local_esp); ctx.builder.instruction_body.const_i32(4); ctx.builder.instruction_body.add_i32(); - ctx.builder.instruction_body.store_aligned_i32(0); + gen_set_reg32(ctx, regs::ESP); ctx.builder.free_local(local_esp); @@ -879,37 +944,21 @@ pub fn gen_pop32s(ctx: &mut JitContext) { pub fn gen_adjust_stack_reg(ctx: &mut JitContext, offset: u32) { if ctx.cpu.ssize_32() { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(regs::ESP) as i32); gen_get_reg32(ctx, regs::ESP); ctx.builder.instruction_body.const_i32(offset as i32); ctx.builder.instruction_body.add_i32(); - ctx.builder.instruction_body.store_aligned_i32(0); + gen_set_reg32(ctx, regs::ESP); } else { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(regs::SP) as i32); gen_get_reg16(ctx, regs::SP); ctx.builder.instruction_body.const_i32(offset as i32); ctx.builder.instruction_body.add_i32(); - ctx.builder.instruction_body.store_aligned_u16(0); + gen_set_reg16(ctx, regs::SP); } } pub fn gen_leave(ctx: &mut JitContext, os32: bool) { // [e]bp = safe_read{16,32}([e]bp) - if os32 { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(regs::EBP) as i32); - } - else { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(regs::BP) as i32); - } if ctx.cpu.ssize_32() { gen_get_reg32(ctx, regs::EBP); @@ -928,36 +977,30 @@ pub fn gen_leave(ctx: &mut JitContext, os32: bool) { } if os32 { gen_safe_read32(ctx); - ctx.builder.instruction_body.store_aligned_i32(0); + gen_set_reg32(ctx, regs::EBP); } else { gen_safe_read16(ctx); - ctx.builder.instruction_body.store_aligned_u16(0); + gen_set_reg16(ctx, regs::BP); } // [e]sp = [e]bp + (os32 ? 4 : 2) if ctx.cpu.ssize_32() { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(regs::ESP) as i32); ctx.builder.instruction_body.get_local(&old_vbp); ctx.builder .instruction_body .const_i32(if os32 { 4 } else { 2 }); ctx.builder.instruction_body.add_i32(); - ctx.builder.instruction_body.store_aligned_i32(0); + gen_set_reg32(ctx, regs::ESP); } else { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(regs::SP) as i32); ctx.builder.instruction_body.get_local(&old_vbp); ctx.builder .instruction_body .const_i32(if os32 { 4 } else { 2 }); ctx.builder.instruction_body.add_i32(); - ctx.builder.instruction_body.store_aligned_u16(0); + gen_set_reg16(ctx, regs::SP); } ctx.builder.free_local(old_vbp); @@ -975,6 +1018,7 @@ pub fn gen_task_switch_test(ctx: &mut JitContext) { ctx.builder.instruction_body.if_void(); + gen_move_registers_from_locals_to_memory(ctx); gen_fn0_const(ctx.builder, "task_switch_test_void"); gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); @@ -995,6 +1039,7 @@ pub fn gen_task_switch_test_mmx(ctx: &mut JitContext) { ctx.builder.instruction_body.if_void(); + gen_move_registers_from_locals_to_memory(ctx); gen_fn0_const(ctx.builder, "task_switch_test_mmx_void"); gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); @@ -1004,13 +1049,11 @@ pub fn gen_task_switch_test_mmx(ctx: &mut JitContext) { } pub fn gen_push16(ctx: &mut JitContext, value_local: &WasmLocal) { - let sp_reg = if ctx.cpu.ssize_32() { + if ctx.cpu.ssize_32() { gen_get_reg32(ctx, regs::ESP); - global_pointers::get_reg32_offset(regs::ESP) } else { gen_get_reg16(ctx, regs::SP); - global_pointers::get_reg16_offset(regs::SP) }; ctx.builder.instruction_body.const_i32(2); @@ -1031,25 +1074,22 @@ pub fn gen_push16(ctx: &mut JitContext, value_local: &WasmLocal) { let sp_local = ctx.builder.set_new_local(); gen_safe_write16(ctx, &sp_local, &value_local); ctx.builder.free_local(sp_local); - ctx.builder.instruction_body.const_i32(sp_reg as i32); ctx.builder.instruction_body.get_local(®_updated_local); if ctx.cpu.ssize_32() { - ctx.builder.instruction_body.store_aligned_i32(0) + gen_set_reg32(ctx, regs::ESP); } else { - ctx.builder.instruction_body.store_aligned_u16(0) + gen_set_reg16(ctx, regs::SP); }; ctx.builder.free_local(reg_updated_local); } pub fn gen_push32(ctx: &mut JitContext, value_local: &WasmLocal) { - let sp_reg = if ctx.cpu.ssize_32() { + if ctx.cpu.ssize_32() { gen_get_reg32(ctx, regs::ESP); - global_pointers::get_reg32_offset(regs::ESP) } else { gen_get_reg16(ctx, regs::SP); - global_pointers::get_reg16_offset(regs::SP) }; ctx.builder.instruction_body.const_i32(4); @@ -1072,13 +1112,12 @@ pub fn gen_push32(ctx: &mut JitContext, value_local: &WasmLocal) { gen_safe_write32(ctx, &sp_local, &value_local); ctx.builder.free_local(sp_local); - ctx.builder.instruction_body.const_i32(sp_reg as i32); ctx.builder.instruction_body.get_local(&new_sp_local); if ctx.cpu.ssize_32() { - ctx.builder.instruction_body.store_aligned_i32(0) + gen_set_reg32(ctx, regs::ESP); } else { - ctx.builder.instruction_body.store_aligned_u16(0) + gen_set_reg16(ctx, regs::SP); }; ctx.builder.free_local(new_sp_local); } @@ -1235,6 +1274,7 @@ pub fn gen_safe_read_write( ctx.builder.instruction_body.if_void(); gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); + gen_move_registers_from_locals_to_memory(ctx); ctx.builder.instruction_body.return_(); ctx.builder.instruction_body.block_end(); @@ -1260,6 +1300,7 @@ pub fn gen_fpu_load_m64(ctx: &mut JitContext) { } pub fn gen_trigger_ud(ctx: &mut JitContext) { + gen_move_registers_from_locals_to_memory(ctx); gen_fn0_const(ctx.builder, "trigger_ud"); gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); ctx.builder.instruction_body.return_(); @@ -1271,6 +1312,31 @@ pub fn gen_condition_fn(builder: &mut WasmBuilder, condition: u8) { gen_fn0_const_ret(builder, condition_name); } +pub fn gen_move_registers_from_locals_to_memory(ctx: &mut JitContext) { + let instruction = ::cpu::read32(ctx.start_of_current_instruction); + + for i in 0..8 { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg32_offset(i as u32) as i32); + ctx.builder + .instruction_body + .get_local(&ctx.register_locals[i]); + ctx.builder.instruction_body.store_aligned_i32(0); + } +} +pub fn gen_move_registers_from_memory_to_locals(ctx: &mut JitContext) { + for i in 0..8 { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg32_offset(i as u32) as i32); + ctx.builder.instruction_body.load_aligned_i32_from_stack(0); + ctx.builder + .instruction_body + .set_local(&ctx.register_locals[i]); + } +} + pub fn gen_profiler_stat_increment(builder: &mut WasmBuilder, stat: profiler::stat) { let addr = unsafe { profiler::stat_array.as_mut_ptr().offset(stat as isize) } as u32; gen_increment_variable(builder, addr, 1) diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 5977870f..799d92b3 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -5,13 +5,14 @@ use analysis::AnalysisType; use codegen; use cpu; use cpu_context::CpuContext; +use global_pointers; use jit_instructions; use page::Page; use profiler; use profiler::stat; use state_flags::CachedStateFlags; use util::SafeToU16; -use wasmgen::module_init::WasmBuilder; +use wasmgen::module_init::{WasmBuilder, WasmLocal}; use wasmgen::wasm_util::WasmBuf; pub const WASM_TABLE_SIZE: u32 = 900; @@ -378,6 +379,7 @@ impl cached_code { pub struct JitContext<'a> { pub cpu: &'a mut CpuContext, pub builder: &'a mut WasmBuilder, + pub register_locals: &'a mut Vec, pub start_of_current_instruction: u32, } @@ -970,69 +972,83 @@ fn jit_generate_module( None }; + let mut register_locals = (0..8) + .map(|i| { + builder + .instruction_body + .const_i32(global_pointers::get_reg32_offset(i) as i32); + builder.instruction_body.load_aligned_i32_from_stack(0); + let local = builder.set_new_local(); + local + }) + .collect(); + + let ctx = &mut JitContext { + cpu: &mut cpu, + builder, + register_locals: &mut register_locals, + start_of_current_instruction: 0, + }; + // main state machine loop - builder.instruction_body.loop_void(); + ctx.builder.instruction_body.loop_void(); if let Some(gen_local_iteration_counter) = gen_local_iteration_counter.as_ref() { profiler::stat_increment(stat::COMPILE_WITH_LOOP_SAFETY); // decrement max_iterations - builder + ctx.builder .instruction_body .get_local(gen_local_iteration_counter); - builder.instruction_body.const_i32(-1); - builder.instruction_body.add_i32(); - builder + ctx.builder.instruction_body.const_i32(-1); + ctx.builder.instruction_body.add_i32(); + ctx.builder .instruction_body .set_local(gen_local_iteration_counter); // if max_iterations == 0: return - builder + ctx.builder .instruction_body .get_local(gen_local_iteration_counter); - builder.instruction_body.eqz_i32(); - builder.instruction_body.if_void(); - codegen::gen_debug_track_jit_exit(builder, 0); - builder.instruction_body.return_(); - builder.instruction_body.block_end(); + ctx.builder.instruction_body.eqz_i32(); + ctx.builder.instruction_body.if_void(); + codegen::gen_debug_track_jit_exit(ctx.builder, 0); + codegen::gen_move_registers_from_locals_to_memory(ctx); + ctx.builder.instruction_body.return_(); + ctx.builder.instruction_body.block_end(); } - builder.instruction_body.block_void(); // for the default case + ctx.builder.instruction_body.block_void(); // for the default case // generate the opening blocks for the cases for _ in 0..basic_blocks.len() { - builder.instruction_body.block_void(); + ctx.builder.instruction_body.block_void(); } - builder.instruction_body.get_local(&gen_local_state); - builder + ctx.builder.instruction_body.get_local(&gen_local_state); + ctx.builder .instruction_body .brtable_and_cases(basic_blocks.len() as u32); for (i, block) in basic_blocks.iter().enumerate() { // Case [i] will jump after the [i]th block, so we first generate the // block end opcode and then the code for that block - builder.instruction_body.block_end(); + ctx.builder.instruction_body.block_end(); dbg_assert!(block.addr < block.end_addr); - jit_generate_basic_block( - &mut cpu, - builder, - block.addr, - block.last_instruction_addr, - block.end_addr, - ); + jit_generate_basic_block(ctx, block.addr, block.last_instruction_addr, block.end_addr); - let invalid_connection_to_next_block = block.end_addr != cpu.eip; + let invalid_connection_to_next_block = block.end_addr != ctx.cpu.eip; dbg_assert!(!invalid_connection_to_next_block); match &block.ty { BasicBlockType::Exit => { // Exit this function - codegen::gen_debug_track_jit_exit(builder, block.last_instruction_addr); - builder.instruction_body.return_(); + codegen::gen_debug_track_jit_exit(ctx.builder, block.last_instruction_addr); + codegen::gen_move_registers_from_locals_to_memory(ctx); + ctx.builder.instruction_body.return_(); }, BasicBlockType::Normal { next_block_addr } => { // Unconditional jump to next basic block @@ -1044,10 +1060,10 @@ fn jit_generate_module( .expect("basic_block_indices.get (Normal)"); // set state variable to next basic block - builder.instruction_body.const_i32(next_bb_index as i32); - builder.instruction_body.set_local(&gen_local_state); + ctx.builder.instruction_body.const_i32(next_bb_index as i32); + ctx.builder.instruction_body.set_local(&gen_local_state); - builder + ctx.builder .instruction_body .br(basic_blocks.len() as u32 - i as u32); // to the loop }, @@ -1061,16 +1077,16 @@ fn jit_generate_module( // Conditional jump to next basic block // - jnz, jc, etc. - codegen::gen_condition_fn(builder, condition); - builder.instruction_body.if_void(); + codegen::gen_condition_fn(ctx.builder, condition); + ctx.builder.instruction_body.if_void(); // Branch taken if jump_offset_is_32 { - codegen::gen_relative_jump(builder, jump_offset); + codegen::gen_relative_jump(ctx.builder, jump_offset); } else { - codegen::gen_jmp_rel16(builder, jump_offset as u16); + codegen::gen_jmp_rel16(ctx.builder, jump_offset as u16); } if let Some(next_block_branch_taken_addr) = next_block_branch_taken_addr { @@ -1078,18 +1094,19 @@ fn jit_generate_module( .get(&next_block_branch_taken_addr) .expect("basic_block_indices.get (branch taken)"); - builder + ctx.builder .instruction_body .const_i32(next_basic_block_branch_taken_index as i32); - builder.instruction_body.set_local(&gen_local_state); + ctx.builder.instruction_body.set_local(&gen_local_state); } else { // Jump to different page - codegen::gen_debug_track_jit_exit(builder, block.last_instruction_addr); - builder.instruction_body.return_(); + codegen::gen_debug_track_jit_exit(ctx.builder, block.last_instruction_addr); + codegen::gen_move_registers_from_locals_to_memory(ctx); + ctx.builder.instruction_body.return_(); } - builder.instruction_body.else_(); + ctx.builder.instruction_body.else_(); if let Some(next_block_addr) = next_block_addr { // Branch not taken @@ -1098,42 +1115,46 @@ fn jit_generate_module( .get(&next_block_addr) .expect("basic_block_indices.get (branch not taken)"); - builder + ctx.builder .instruction_body .const_i32(next_basic_block_index as i32); - builder.instruction_body.set_local(&gen_local_state); + ctx.builder.instruction_body.set_local(&gen_local_state); } else { // End of this page - codegen::gen_debug_track_jit_exit(builder, block.last_instruction_addr); - builder.instruction_body.return_(); + codegen::gen_debug_track_jit_exit(ctx.builder, block.last_instruction_addr); + codegen::gen_move_registers_from_locals_to_memory(ctx); + ctx.builder.instruction_body.return_(); } - builder.instruction_body.block_end(); + ctx.builder.instruction_body.block_end(); - builder + ctx.builder .instruction_body .br(basic_blocks.len() as u32 - i as u32); // to the loop }, } } - builder.instruction_body.block_end(); // default case - builder.instruction_body.unreachable(); + ctx.builder.instruction_body.block_end(); // default case + ctx.builder.instruction_body.unreachable(); - builder.instruction_body.block_end(); // loop + ctx.builder.instruction_body.block_end(); // loop - builder.free_local(gen_local_state); + ctx.builder.free_local(gen_local_state); if let Some(local) = gen_local_iteration_counter { - builder.free_local(local); + ctx.builder.free_local(local); } - builder.finish(); + for local in ctx.register_locals.drain(..) { + ctx.builder.free_local(local); + } + + ctx.builder.finish(); } fn jit_generate_basic_block( - mut cpu: &mut CpuContext, - builder: &mut WasmBuilder, + ctx: &mut JitContext, start_addr: u32, last_instruction_addr: u32, stop_addr: u32, @@ -1143,30 +1164,31 @@ fn jit_generate_basic_block( // First iteration of do-while assumes the caller confirms this condition dbg_assert!(!is_near_end_of_page(start_addr)); - cpu.eip = start_addr; + ctx.cpu.eip = start_addr; loop { - if false { - let instruction = cpu::read32(cpu.eip); - ::opstats::gen_opstats(builder, instruction); + if cfg!(feature = "profiler") { + let instruction = cpu::read32(ctx.cpu.eip); + ::opstats::gen_opstats(ctx.builder, instruction); ::opstats::record_opstat_compiled(instruction); } - if cpu.eip == last_instruction_addr { + if ctx.cpu.eip == last_instruction_addr { // Before the last instruction: // - Set eip to *after* the instruction // - Set previous_eip to *before* the instruction codegen::gen_set_previous_eip_offset_from_eip( - builder, + ctx.builder, last_instruction_addr - start_addr, ); - codegen::gen_increment_instruction_pointer(builder, stop_addr - start_addr); + codegen::gen_increment_instruction_pointer(ctx.builder, stop_addr - start_addr); } - let start_eip = cpu.eip; + ctx.start_of_current_instruction = ctx.cpu.eip; + let start_eip = ctx.cpu.eip; let mut instruction_flags = 0; - jit_instructions::jit_instruction(&mut cpu, builder, &mut instruction_flags); - let end_eip = cpu.eip; + jit_instructions::jit_instruction(ctx, &mut instruction_flags); + let end_eip = ctx.cpu.eip; let instruction_length = end_eip - start_eip; let was_block_boundary = instruction_flags & JIT_INSTR_BLOCK_BOUNDARY_FLAG != 0; @@ -1174,7 +1196,7 @@ fn jit_generate_basic_block( dbg_assert!((end_eip == stop_addr) == (start_eip == last_instruction_addr)); dbg_assert!(instruction_length < MAX_INSTRUCTION_LENGTH); - let end_addr = cpu.eip; + let end_addr = ctx.cpu.eip; count += 1; if end_addr == stop_addr { @@ -1192,7 +1214,7 @@ fn jit_generate_basic_block( } } - codegen::gen_increment_timestamp_counter(builder, count); + codegen::gen_increment_timestamp_counter(ctx.builder, count); } pub fn jit_increase_hotness_and_maybe_compile( diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 4a5540e0..a9a3f663 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -2,7 +2,6 @@ use codegen; use cpu::BitSize; -use cpu_context::CpuContext; use global_pointers; use jit::JitContext; use modrm; @@ -13,17 +12,12 @@ use regs; use regs::{AX, BP, BX, CX, DI, DX, SI, SP}; use regs::{CS, DS, ES, FS, GS, SS}; use regs::{EAX, EBP, EBX, ECX, EDI, EDX, ESI, ESP}; -use wasmgen::module_init::WasmBuilder; +use wasmgen::module_init::{WasmBuilder, WasmLocal}; use wasmgen::wasm_util::WasmBuf; -pub fn jit_instruction(cpu: &mut CpuContext, builder: &mut WasmBuilder, instr_flags: &mut u32) { - cpu.prefixes = 0; - let start_of_current_instruction = cpu.eip; - let ctx = &mut JitContext { - cpu, - builder, - start_of_current_instruction, - }; +pub fn jit_instruction(ctx: &mut JitContext, instr_flags: &mut u32) { + ctx.cpu.prefixes = 0; + ctx.start_of_current_instruction = ctx.cpu.eip; ::gen::jit::jit( ctx.cpu.read_imm8() as u32 | (ctx.cpu.osize_32() as u32) << 8, ctx, @@ -110,9 +104,7 @@ fn push16_reg_jit(ctx: &mut JitContext, r: u32) { ctx.builder.free_local(value_local); } fn push32_reg_jit(ctx: &mut JitContext, r: u32) { - ctx.builder - .instruction_body - .load_aligned_i32(global_pointers::get_reg32_offset(r)); + codegen::gen_get_reg32(ctx, r); let value_local = ctx.builder.set_new_local(); codegen::gen_push32(ctx, &value_local); ctx.builder.free_local(value_local); @@ -145,49 +137,34 @@ fn push32_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { } fn pop16_reg_jit(ctx: &mut JitContext, reg: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(reg) as i32); codegen::gen_pop16(ctx); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, reg); } fn pop32_reg_jit(ctx: &mut JitContext, reg: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(reg) as i32); codegen::gen_pop32s(ctx); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, reg); } fn group_arith_al_imm8(ctx: &mut JitContext, op: &str, imm8: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg8_offset(0) as i32); - codegen::gen_get_reg8(ctx, 0); + codegen::gen_get_reg8(ctx, regs::AL); ctx.builder.instruction_body.const_i32(imm8 as i32); codegen::gen_call_fn2_ret(ctx.builder, op); - ctx.builder.instruction_body.store_u8(0); + codegen::gen_set_reg8(ctx, regs::AL); } fn group_arith_ax_imm16(ctx: &mut JitContext, op: &str, imm16: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(0) as i32); - codegen::gen_get_reg16(ctx, 0); + codegen::gen_get_reg16(ctx, regs::AX); ctx.builder.instruction_body.const_i32(imm16 as i32); codegen::gen_call_fn2_ret(ctx.builder, op); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, regs::AX); } fn group_arith_eax_imm32(ctx: &mut JitContext, op: &str, imm32: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(0) as i32); - codegen::gen_get_reg32(ctx, 0); + codegen::gen_get_reg32(ctx, regs::EAX); ctx.builder.instruction_body.const_i32(imm32 as i32); codegen::gen_call_fn2_ret(ctx.builder, op); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, regs::EAX); } macro_rules! define_instruction_read8( @@ -289,20 +266,18 @@ macro_rules! define_instruction_read32( macro_rules! define_instruction_write_reg8( ($fn:expr, $name_mem:ident, $name_reg:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - ctx.builder.instruction_body.const_i32(global_pointers::get_reg8_offset(r) as i32); codegen::gen_get_reg8(ctx, r); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read8(ctx); codegen::gen_call_fn2_ret(ctx.builder, $fn); - ctx.builder.instruction_body.store_u8(0); + codegen::gen_set_reg8(ctx, r); } pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { - ctx.builder.instruction_body.const_i32(global_pointers::get_reg8_offset(r2) as i32); codegen::gen_get_reg8(ctx, r2); codegen::gen_get_reg8(ctx, r1); codegen::gen_call_fn2_ret(ctx.builder, $fn); - ctx.builder.instruction_body.store_u8(0); + codegen::gen_set_reg8(ctx, r2); } ) ); @@ -310,20 +285,18 @@ macro_rules! define_instruction_write_reg8( macro_rules! define_instruction_write_reg16( ($fn:expr, $name_mem:ident, $name_reg:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r) as i32); codegen::gen_get_reg16(ctx, r); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read16(ctx); codegen::gen_call_fn2_ret(ctx.builder, $fn); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r); } pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { - ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r2) as i32); codegen::gen_get_reg16(ctx, r2); codegen::gen_get_reg16(ctx, r1); codegen::gen_call_fn2_ret(ctx.builder, $fn); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r2); } ) ); @@ -331,20 +304,18 @@ macro_rules! define_instruction_write_reg16( macro_rules! define_instruction_write_reg32( ($fn:expr, $name_mem:ident, $name_reg:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r) as i32); codegen::gen_get_reg32(ctx, r); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); codegen::gen_call_fn2_ret(ctx.builder, $fn); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r); } pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { - ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r2) as i32); codegen::gen_get_reg32(ctx, r2); codegen::gen_get_reg32(ctx, r1); codegen::gen_call_fn2_ret(ctx.builder, $fn); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r2); } ) ); @@ -375,17 +346,18 @@ macro_rules! define_instruction_read_write_mem8( codegen::gen_call_fn2_ret(ctx.builder, $fn); }, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(r as i32); - codegen::gen_call_fn2(ctx.builder, $fallback_fn) + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn2(ctx.builder, $fallback_fn); + codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { - ctx.builder.instruction_body.const_i32(global_pointers::get_reg8_offset(r1) as i32); codegen::gen_get_reg8(ctx, r1); codegen::gen_get_reg8(ctx, r2); codegen::gen_call_fn2_ret(ctx.builder, $fn); - ctx.builder.instruction_body.store_u8(0); + codegen::gen_set_reg8(ctx, r1); } ); @@ -399,18 +371,19 @@ macro_rules! define_instruction_read_write_mem8( codegen::gen_call_fn2_ret(ctx.builder, $fn); }, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(imm as i32); - codegen::gen_call_fn2(ctx.builder, $fallback_fn) + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn2(ctx.builder, $fallback_fn); + codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { let imm = mask_imm!(imm, $imm); - ctx.builder.instruction_body.const_i32(global_pointers::get_reg8_offset(r1) as i32); codegen::gen_get_reg8(ctx, r1); ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn2_ret(ctx.builder, $fn); - ctx.builder.instruction_body.store_u8(0); + codegen::gen_set_reg8(ctx, r1); } ); ); @@ -425,17 +398,18 @@ macro_rules! define_instruction_read_write_mem16( codegen::gen_call_fn2_ret(ctx.builder, $fn); }, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(r as i32); - codegen::gen_call_fn2(ctx.builder, $fallback_fn) + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn2(ctx.builder, $fallback_fn); + codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { - ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r1) as i32); codegen::gen_get_reg16(ctx, r1); codegen::gen_get_reg16(ctx, r2); codegen::gen_call_fn2_ret(ctx.builder, $fn); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r1); } ); @@ -447,17 +421,18 @@ macro_rules! define_instruction_read_write_mem16( ctx.builder.instruction_body.const_i32(1); codegen::gen_call_fn2_ret(ctx.builder, $fn); }, &|ref mut ctx| { - codegen::gen_call_fn1(ctx.builder, $fallback_fn) + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn1(ctx.builder, $fallback_fn); + codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } pub fn $name_reg(ctx: &mut JitContext, r1: u32) { - ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r1) as i32); codegen::gen_get_reg16(ctx, r1); ctx.builder.instruction_body.const_i32(1); codegen::gen_call_fn2_ret(ctx.builder, $fn); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r1); } ); @@ -471,19 +446,20 @@ macro_rules! define_instruction_read_write_mem16( ctx.builder.instruction_body.and_i32(); codegen::gen_call_fn2_ret(ctx.builder, $fn); }, &|ref mut ctx| { - codegen::gen_call_fn1(ctx.builder, $fallback_fn) + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn1(ctx.builder, $fallback_fn); + codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } pub fn $name_reg(ctx: &mut JitContext, r1: u32) { - ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r1) as i32); codegen::gen_get_reg16(ctx, r1); codegen::gen_get_reg8(ctx, regs::CL); ctx.builder.instruction_body.const_i32(31); ctx.builder.instruction_body.and_i32(); codegen::gen_call_fn2_ret(ctx.builder, $fn); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r1); } ); @@ -499,20 +475,21 @@ macro_rules! define_instruction_read_write_mem16( codegen::gen_call_fn3_ret(ctx.builder, $fn); }, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(r as i32); - codegen::gen_call_fn2(ctx.builder, $fallback_fn) + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn2(ctx.builder, $fallback_fn); + codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { - ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r1) as i32); codegen::gen_get_reg16(ctx, r1); codegen::gen_get_reg16(ctx, r2); codegen::gen_get_reg8(ctx, regs::CL); ctx.builder.instruction_body.const_i32(31); ctx.builder.instruction_body.and_i32(); codegen::gen_call_fn3_ret(ctx.builder, $fn); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r1); } ); @@ -528,19 +505,20 @@ macro_rules! define_instruction_read_write_mem16( }, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(r as i32); ctx.builder.instruction_body.const_i32(imm as i32); - codegen::gen_call_fn3(ctx.builder, $fallback_fn) + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn3(ctx.builder, $fallback_fn); + codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32, imm: u32) { let imm = mask_imm!(imm, $imm); - ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r1) as i32); codegen::gen_get_reg16(ctx, r1); codegen::gen_get_reg16(ctx, r2); ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn3_ret(ctx.builder, $fn); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r1); } ); @@ -551,16 +529,17 @@ macro_rules! define_instruction_read_write_mem16( codegen::gen_safe_read_write(ctx, BitSize::WORD, &address_local, &|ref mut ctx| { codegen::gen_call_fn1_ret(ctx.builder, $fn); }, &|ref mut ctx| { - codegen::gen_call_fn1(ctx.builder, $fallback_fn) + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn1(ctx.builder, $fallback_fn); + codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } pub fn $name_reg(ctx: &mut JitContext, r1: u32) { - ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r1) as i32); codegen::gen_get_reg16(ctx, r1); codegen::gen_call_fn1_ret(ctx.builder, $fn); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r1); } ); @@ -574,18 +553,19 @@ macro_rules! define_instruction_read_write_mem16( codegen::gen_call_fn2_ret(ctx.builder, $fn); }, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(imm as i32); - codegen::gen_call_fn2(ctx.builder, $fallback_fn) + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn2(ctx.builder, $fallback_fn); + codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { let imm = mask_imm!(imm, $imm); - ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r1) as i32); codegen::gen_get_reg16(ctx, r1); ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn2_ret(ctx.builder, $fn); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r1); } ); ); @@ -600,17 +580,18 @@ macro_rules! define_instruction_read_write_mem32( codegen::gen_call_fn2_ret(ctx.builder, $fn); }, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(r as i32); - codegen::gen_call_fn2(ctx.builder, $fallback_fn) + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn2(ctx.builder, $fallback_fn); + codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { - ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r1) as i32); codegen::gen_get_reg32(ctx, r1); codegen::gen_get_reg32(ctx, r2); codegen::gen_call_fn2_ret(ctx.builder, $fn); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r1); } ); @@ -622,17 +603,18 @@ macro_rules! define_instruction_read_write_mem32( ctx.builder.instruction_body.const_i32(1); codegen::gen_call_fn2_ret(ctx.builder, $fn); }, &|ref mut ctx| { - codegen::gen_call_fn1(ctx.builder, $fallback_fn) + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn1(ctx.builder, $fallback_fn); + codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } pub fn $name_reg(ctx: &mut JitContext, r1: u32) { - ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r1) as i32); codegen::gen_get_reg32(ctx, r1); ctx.builder.instruction_body.const_i32(1); codegen::gen_call_fn2_ret(ctx.builder, $fn); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r1); } ); @@ -646,19 +628,20 @@ macro_rules! define_instruction_read_write_mem32( ctx.builder.instruction_body.and_i32(); codegen::gen_call_fn2_ret(ctx.builder, $fn); }, &|ref mut ctx| { - codegen::gen_call_fn1(ctx.builder, $fallback_fn) + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn1(ctx.builder, $fallback_fn); + codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } pub fn $name_reg(ctx: &mut JitContext, r1: u32) { - ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r1) as i32); codegen::gen_get_reg32(ctx, r1); codegen::gen_get_reg8(ctx, regs::CL); ctx.builder.instruction_body.const_i32(31); ctx.builder.instruction_body.and_i32(); codegen::gen_call_fn2_ret(ctx.builder, $fn); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r1); } ); @@ -674,20 +657,21 @@ macro_rules! define_instruction_read_write_mem32( codegen::gen_call_fn3_ret(ctx.builder, $fn); }, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(r as i32); - codegen::gen_call_fn2(ctx.builder, $fallback_fn) + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn2(ctx.builder, $fallback_fn); + codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { - ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r1) as i32); codegen::gen_get_reg32(ctx, r1); codegen::gen_get_reg32(ctx, r2); codegen::gen_get_reg8(ctx, regs::CL); ctx.builder.instruction_body.const_i32(31); ctx.builder.instruction_body.and_i32(); codegen::gen_call_fn3_ret(ctx.builder, $fn); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r1); } ); @@ -703,19 +687,20 @@ macro_rules! define_instruction_read_write_mem32( }, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(r as i32); ctx.builder.instruction_body.const_i32(imm as i32); - codegen::gen_call_fn3(ctx.builder, $fallback_fn) + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn3(ctx.builder, $fallback_fn); + codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32, imm: u32) { let imm = mask_imm!(imm, $imm); - ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r1) as i32); codegen::gen_get_reg32(ctx, r1); codegen::gen_get_reg32(ctx, r2); ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn3_ret(ctx.builder, $fn); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r1); } ); @@ -726,16 +711,17 @@ macro_rules! define_instruction_read_write_mem32( codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { codegen::gen_call_fn1_ret(ctx.builder, $fn); }, &|ref mut ctx| { - codegen::gen_call_fn1(ctx.builder, $fallback_fn) + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn1(ctx.builder, $fallback_fn); + codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } pub fn $name_reg(ctx: &mut JitContext, r1: u32) { - ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r1) as i32); codegen::gen_get_reg32(ctx, r1); codegen::gen_call_fn1_ret(ctx.builder, $fn); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r1); } ); @@ -749,18 +735,19 @@ macro_rules! define_instruction_read_write_mem32( codegen::gen_call_fn2_ret(ctx.builder, $fn); }, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(imm as i32); - codegen::gen_call_fn2(ctx.builder, $fallback_fn) + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn2(ctx.builder, $fallback_fn); + codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { let imm = mask_imm!(imm, $imm); - ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r1) as i32); codegen::gen_get_reg32(ctx, r1); ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn2_ret(ctx.builder, $fn); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r1); } ); ); @@ -1047,27 +1034,18 @@ pub fn instr32_3B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { } pub fn instr_3C_jit(ctx: &mut JitContext, imm8: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg8_offset(0) as i32); codegen::gen_get_reg8(ctx, 0); ctx.builder.instruction_body.const_i32(imm8 as i32); codegen::gen_call_fn2(ctx.builder, "cmp8"); } pub fn instr16_3D_jit(ctx: &mut JitContext, imm16: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(0) as i32); codegen::gen_get_reg16(ctx, 0); ctx.builder.instruction_body.const_i32(imm16 as i32); codegen::gen_call_fn2(ctx.builder, "cmp16"); } pub fn instr32_3D_jit(ctx: &mut JitContext, imm32: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(0) as i32); codegen::gen_get_reg32(ctx, 0); ctx.builder.instruction_body.const_i32(imm32 as i32); codegen::gen_call_fn2(ctx.builder, "cmp32"); @@ -1113,87 +1091,63 @@ pub fn instr16_6A_jit(ctx: &mut JitContext, imm16: u32) { push16_imm_jit(ctx, im pub fn instr32_6A_jit(ctx: &mut JitContext, imm32: u32) { push32_imm_jit(ctx, imm32) } pub fn instr16_69_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(r) as i32); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read16(ctx); let imm16 = ctx.cpu.read_imm16(); ctx.builder.instruction_body.const_i32(imm16 as i32); codegen::gen_call_fn2_ret(ctx.builder, "imul_reg16"); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r); } pub fn instr16_69_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm16: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(r2) as i32); codegen::gen_get_reg16(ctx, r1); ctx.builder.instruction_body.const_i32(imm16 as i32); codegen::gen_call_fn2_ret(ctx.builder, "imul_reg16"); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r2); } pub fn instr32_69_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(r) as i32); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); let imm32 = ctx.cpu.read_imm32(); ctx.builder.instruction_body.const_i32(imm32 as i32); codegen::gen_call_fn2_ret(ctx.builder, "imul_reg32"); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r); } pub fn instr32_69_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm32: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(r2) as i32); codegen::gen_get_reg32(ctx, r1); ctx.builder.instruction_body.const_i32(imm32 as i32); codegen::gen_call_fn2_ret(ctx.builder, "imul_reg32"); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r2); } pub fn instr16_6B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(r) as i32); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read16(ctx); let imm8s = ctx.cpu.read_imm8s(); ctx.builder.instruction_body.const_i32(imm8s as i32); codegen::gen_call_fn2_ret(ctx.builder, "imul_reg16"); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r); } pub fn instr16_6B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm8s: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(r2) as i32); codegen::gen_get_reg16(ctx, r1); ctx.builder.instruction_body.const_i32(imm8s as i32); codegen::gen_call_fn2_ret(ctx.builder, "imul_reg16"); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r2); } pub fn instr32_6B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(r) as i32); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); let imm8s = ctx.cpu.read_imm8s(); ctx.builder.instruction_body.const_i32(imm8s as i32); codegen::gen_call_fn2_ret(ctx.builder, "imul_reg32"); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r); } pub fn instr32_6B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm8s: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(r2) as i32); codegen::gen_get_reg32(ctx, r1); ctx.builder.instruction_body.const_i32(imm8s as i32); codegen::gen_call_fn2_ret(ctx.builder, "imul_reg32"); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r2); } // Code for conditional jumps is generated automatically by the basic block codegen @@ -1506,10 +1460,7 @@ pub fn instr_88_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { let address_local = ctx.builder.set_new_local(); - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg8_offset(r) as i32); - ctx.builder.instruction_body.load_u8_from_stack(0); + codegen::gen_get_reg8(ctx, r); let value_local = ctx.builder.set_new_local(); codegen::gen_safe_write8(ctx, &address_local, &value_local); @@ -1540,10 +1491,7 @@ pub fn instr32_89_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(r) as i32); - ctx.builder.instruction_body.load_aligned_i32_from_stack(0); + codegen::gen_get_reg32(ctx, r); let value_local = ctx.builder.set_new_local(); codegen::gen_safe_write32(ctx, &address_local, &value_local); @@ -1556,14 +1504,10 @@ pub fn instr32_89_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { pub fn instr_8A_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { // Pseudo: reg8[r] = safe_read8(modrm_resolve(modrm_byte)); - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg8_offset(r) as i32); - codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read8(ctx); - ctx.builder.instruction_body.store_u8(0); + codegen::gen_set_reg8(ctx, r); } pub fn instr_8A_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_set_reg8_r(ctx, r2, r1); @@ -1571,47 +1515,34 @@ pub fn instr_8A_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { pub fn instr16_8B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { // Pseudo: reg16[r] = safe_read16(modrm_resolve(modrm_byte)); - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(r) as i32); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read16(ctx); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r); } pub fn instr16_8B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_set_reg16_r(ctx, r2, r1); } pub fn instr32_8B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { // Pseudo: reg32s[r] = safe_read32s(modrm_resolve(modrm_byte)); - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(r) as i32); - codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r); } pub fn instr32_8B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_set_reg32_r(ctx, r2, r1); } pub fn instr16_8D_mem_jit(ctx: &mut JitContext, modrm_byte: u8, reg: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(reg) as i32); ctx.cpu.prefixes |= SEG_PREFIX_ZERO; codegen::gen_modrm_resolve(ctx, modrm_byte); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, reg); } pub fn instr32_8D_mem_jit(ctx: &mut JitContext, modrm_byte: u8, reg: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(reg) as i32); ctx.cpu.prefixes |= SEG_PREFIX_ZERO; codegen::gen_modrm_resolve(ctx, modrm_byte); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, reg); } pub fn instr16_8D_reg_jit(ctx: &mut JitContext, _r1: u32, _r2: u32) { @@ -1880,11 +1811,8 @@ pub fn instr16_C9_jit(ctx: &mut JitContext) { codegen::gen_leave(ctx, false); } pub fn instr32_C9_jit(ctx: &mut JitContext) { codegen::gen_leave(ctx, true); } pub fn gen_mov_reg8_imm(ctx: &mut JitContext, r: u32, imm: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg8_offset(r) as i32); ctx.builder.instruction_body.const_i32(imm as i32); - ctx.builder.instruction_body.store_u8(0); + codegen::gen_set_reg8(ctx, r); } pub fn instr_B0_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg8_imm(ctx, 0, imm) } @@ -1897,11 +1825,8 @@ pub fn instr_B6_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg8_imm(ctx, 6, i pub fn instr_B7_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg8_imm(ctx, 7, imm) } pub fn gen_mov_reg16_imm(ctx: &mut JitContext, r: u32, imm: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(r) as i32); ctx.builder.instruction_body.const_i32(imm as i32); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r); } pub fn instr16_B8_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg16_imm(ctx, 0, imm) } @@ -1914,11 +1839,8 @@ pub fn instr16_BE_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg16_imm(ctx, 6 pub fn instr16_BF_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg16_imm(ctx, 7, imm) } pub fn gen_mov_reg32_imm(ctx: &mut JitContext, r: u32, imm: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(r) as i32); ctx.builder.instruction_body.const_i32(imm as i32); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r); } pub fn instr32_B8_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg32_imm(ctx, 0, imm) } @@ -2347,13 +2269,16 @@ pub fn instr_D9_3_reg_jit(ctx: &mut JitContext, r: u32) { pub fn instr_D9_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_call_fn1(ctx.builder, "fpu_fldenv"); // XXX: generated because fldenv might page-fault, but doesn't generate a proper block boundary + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn1(ctx.builder, "fpu_fldenv"); codegen::gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); + codegen::gen_clear_prefixes(ctx); ctx.builder.instruction_body.return_(); } pub fn instr_D9_4_reg_jit(ctx: &mut JitContext, r: u32) { ctx.builder.instruction_body.const_i32(r as i32); + // XXX: May call trigger_ud codegen::gen_call_fn1(ctx.builder, "instr_D9_4_reg"); } @@ -2366,6 +2291,7 @@ pub fn instr_D9_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { ctx.builder.instruction_body.store_aligned_u16(0); } pub fn instr_D9_5_reg_jit(ctx: &mut JitContext, r: u32) { + // XXX: May call trigger_ud codegen::gen_fn1_const(ctx.builder, "instr_D9_5_reg", r); } pub fn instr_D9_7_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { @@ -2427,9 +2353,11 @@ pub fn instr_DB_3_reg_jit(ctx: &mut JitContext, r: u32) { pub fn instr_DB_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_call_fn1(ctx.builder, "fpu_fldm80"); // XXX: generated because fpu_fldm80 might page-fault, but doesn't generate a proper block boundary + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn1(ctx.builder, "fpu_fldm80"); codegen::gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); + codegen::gen_clear_prefixes(ctx); ctx.builder.instruction_body.return_(); } pub fn instr_DB_5_reg_jit(ctx: &mut JitContext, r: u32) { @@ -2666,7 +2594,9 @@ pub fn instr_DF_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { } pub fn instr_DF_4_reg_jit(ctx: &mut JitContext, r: u32) { if r == 0 { + codegen::gen_move_registers_from_locals_to_memory(ctx); codegen::gen_fn0_const(ctx.builder, "fpu_fnstsw_reg"); + codegen::gen_move_registers_from_memory_to_locals(ctx); } else { codegen::gen_trigger_ud(ctx); @@ -2915,31 +2845,22 @@ pub fn instr32_0F8F_jit(_ctx: &mut JitContext, _imm: u32) {} pub fn instr_90_jit(_ctx: &mut JitContext) {} pub fn instr_A0_jit(ctx: &mut JitContext, immaddr: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg8_offset(regs::AL) as i32); ctx.builder.instruction_body.const_i32(immaddr as i32); jit_add_seg_offset(ctx, regs::DS); codegen::gen_safe_read8(ctx); - ctx.builder.instruction_body.store_u8(0); + codegen::gen_set_reg8(ctx, regs::AL); } pub fn instr16_A1_jit(ctx: &mut JitContext, immaddr: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(regs::AX) as i32); ctx.builder.instruction_body.const_i32(immaddr as i32); jit_add_seg_offset(ctx, regs::DS); codegen::gen_safe_read16(ctx); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, regs::AX); } pub fn instr32_A1_jit(ctx: &mut JitContext, immaddr: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(regs::EAX) as i32); ctx.builder.instruction_body.const_i32(immaddr as i32); jit_add_seg_offset(ctx, regs::DS); codegen::gen_safe_read32(ctx); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, regs::EAX); } pub fn instr_A2_jit(ctx: &mut JitContext, immaddr: u32) { @@ -2974,27 +2895,18 @@ pub fn instr32_A3_jit(ctx: &mut JitContext, immaddr: u32) { } pub fn instr_A8_jit(ctx: &mut JitContext, imm8: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg8_offset(0) as i32); codegen::gen_get_reg8(ctx, 0); ctx.builder.instruction_body.const_i32(imm8 as i32); codegen::gen_call_fn2(ctx.builder, "test8"); } pub fn instr16_A9_jit(ctx: &mut JitContext, imm16: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(0) as i32); codegen::gen_get_reg16(ctx, 0); ctx.builder.instruction_body.const_i32(imm16 as i32); codegen::gen_call_fn2(ctx.builder, "test16"); } pub fn instr32_A9_jit(ctx: &mut JitContext, imm32: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(0) as i32); codegen::gen_get_reg32(ctx, 0); ctx.builder.instruction_body.const_i32(imm32 as i32); codegen::gen_call_fn2(ctx.builder, "test32"); @@ -3094,138 +3006,90 @@ define_instruction_read_write_mem32!( ); pub fn instr16_0FB6_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(r2) as i32); codegen::gen_get_reg8(ctx, r1); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r2); } pub fn instr16_0FB6_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(r) as i32); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read8(ctx); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r); } pub fn instr32_0FB6_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(r2) as i32); codegen::gen_get_reg8(ctx, r1); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r2); } pub fn instr32_0FB6_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(r) as i32); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read8(ctx); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r); } pub fn instr16_0FB7_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(r) as i32); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read16(ctx); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r); } pub fn instr16_0FB7_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(r2) as i32); codegen::gen_get_reg16(ctx, r1); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r2); } pub fn instr32_0FB7_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(r) as i32); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read16(ctx); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r); } pub fn instr32_0FB7_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(r2) as i32); codegen::gen_get_reg16(ctx, r1); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r2); } pub fn instr16_0FBE_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(r2) as i32); codegen::gen_get_reg8(ctx, r1); codegen::sign_extend_i8(ctx.builder); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r2); } pub fn instr16_0FBE_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(r) as i32); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read8(ctx); codegen::sign_extend_i8(ctx.builder); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r); } pub fn instr32_0FBE_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(r2) as i32); codegen::gen_get_reg8(ctx, r1); codegen::sign_extend_i8(ctx.builder); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r2); } pub fn instr32_0FBE_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(r) as i32); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read8(ctx); codegen::sign_extend_i8(ctx.builder); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r); } pub fn instr16_0FBF_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(r2) as i32); codegen::gen_get_reg16(ctx, r1); codegen::sign_extend_i16(ctx.builder); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r2); } pub fn instr16_0FBF_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(r) as i32); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read16(ctx); codegen::sign_extend_i16(ctx.builder); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r); } pub fn instr32_0FBF_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(r2) as i32); codegen::gen_get_reg16(ctx, r1); codegen::sign_extend_i16(ctx.builder); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r2); } pub fn instr32_0FBF_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(r) as i32); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read16(ctx); codegen::sign_extend_i16(ctx.builder); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r); } pub fn instr16_0FC1_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { @@ -3245,21 +3109,20 @@ pub fn instr16_0FC1_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { ctx.builder .instruction_body .const_i32(::cpu2::cpu::get_reg16_index(r as i32)); - codegen::gen_call_fn2(ctx.builder, "instr16_0FC1_mem") + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn2(ctx.builder, "instr16_0FC1_mem"); + codegen::gen_move_registers_from_memory_to_locals(ctx); }, ); ctx.builder.free_local(address_local); } pub fn instr16_0FC1_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(r1) as i32); codegen::gen_get_reg16(ctx, r1); ctx.builder .instruction_body .const_i32(::cpu2::cpu::get_reg16_index(r2 as i32)); codegen::gen_call_fn2_ret(ctx.builder, "xadd16"); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r1); } pub fn instr32_0FC1_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { @@ -3275,28 +3138,24 @@ pub fn instr32_0FC1_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { }, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(r as i32); - codegen::gen_call_fn2(ctx.builder, "instr32_0FC1_mem") + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn2(ctx.builder, "instr32_0FC1_mem"); + codegen::gen_move_registers_from_memory_to_locals(ctx); }, ); ctx.builder.free_local(address_local); } pub fn instr32_0FC1_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(r1) as i32); codegen::gen_get_reg32(ctx, r1); ctx.builder.instruction_body.const_i32(r2 as i32); codegen::gen_call_fn2_ret(ctx.builder, "xadd32"); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r1); } pub fn instr_C6_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { // reg8[r] = imm; - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg8_offset(r) as i32); ctx.builder.instruction_body.const_i32(imm as i32); - ctx.builder.instruction_body.store_u8(0); + codegen::gen_set_reg8(ctx, r); } pub fn instr_C6_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { @@ -3312,11 +3171,8 @@ pub fn instr_C6_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { pub fn instr16_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { // reg16[r] = imm; - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg16_offset(r) as i32); ctx.builder.instruction_body.const_i32(imm as i32); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r); } pub fn instr16_C7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { @@ -3332,11 +3188,8 @@ pub fn instr16_C7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { pub fn instr32_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { // reg32s[r] = imm; - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg32_offset(r) as i32); ctx.builder.instruction_body.const_i32(imm as i32); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r); } pub fn instr32_C7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { @@ -3361,9 +3214,8 @@ macro_rules! define_cmovcc16( let value = ctx.builder.set_new_local(); codegen::gen_condition_fn(ctx.builder, $cond); ctx.builder.instruction_body.if_void(); - ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r) as i32); ctx.builder.instruction_body.get_local(&value); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r); ctx.builder.instruction_body.block_end(); ctx.builder.free_local(value); } @@ -3371,9 +3223,8 @@ macro_rules! define_cmovcc16( pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_condition_fn(ctx.builder, $cond); ctx.builder.instruction_body.if_void(); - ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r2) as i32); codegen::gen_get_reg16(ctx, r1); - ctx.builder.instruction_body.store_aligned_u16(0); + codegen::gen_set_reg16(ctx, r2); ctx.builder.instruction_body.block_end(); } ); @@ -3387,9 +3238,8 @@ macro_rules! define_cmovcc32( let value = ctx.builder.set_new_local(); codegen::gen_condition_fn(ctx.builder, $cond); ctx.builder.instruction_body.if_void(); - ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r) as i32); ctx.builder.instruction_body.get_local(&value); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r); ctx.builder.instruction_body.block_end(); ctx.builder.free_local(value); } @@ -3397,9 +3247,8 @@ macro_rules! define_cmovcc32( pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_condition_fn(ctx.builder, $cond); ctx.builder.instruction_body.if_void(); - ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r2) as i32); codegen::gen_get_reg32(ctx, r1); - ctx.builder.instruction_body.store_aligned_i32(0); + codegen::gen_set_reg32(ctx, r2); ctx.builder.instruction_body.block_end(); } ); @@ -3456,13 +3305,10 @@ macro_rules! define_setcc( } pub fn $name_reg(ctx: &mut JitContext, r1: u32, _r2: u32) { - ctx.builder - .instruction_body - .const_i32(global_pointers::get_reg8_offset(r1) as i32); codegen::gen_condition_fn(&mut ctx.builder, $cond); ctx.builder.instruction_body.const_i32(0); ctx.builder.instruction_body.ne_i32(); - ctx.builder.instruction_body.store_u8(0); + codegen::gen_set_reg8(ctx, r1); } ); ); diff --git a/src/rust/regs.rs b/src/rust/regs.rs index 18eb746c..007953dc 100644 --- a/src/rust/regs.rs +++ b/src/rust/regs.rs @@ -25,6 +25,12 @@ pub const DI: u32 = 7; pub const AL: u32 = 0; pub const CL: u32 = 1; +pub const DL: u32 = 2; +pub const BL: u32 = 3; +pub const AH: u32 = 4; +pub const CH: u32 = 5; +pub const DH: u32 = 6; +pub const BH: u32 = 7; pub const CR0_EM: u32 = 1 << 2; pub const CR0_TS: u32 = 1 << 3; From 7024207fa4348eb0bf85aca9743b29333175a5c9 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 25 Dec 2018 12:40:00 +0100 Subject: [PATCH 1558/2137] Codegen for inc/dec (group 40-4F) --- gen/x86_table.js | 32 ++++++++++---------- src/rust/jit_instructions.rs | 58 ++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 16 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 57bcc33d..c7f24678 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -103,23 +103,23 @@ const encodings = [ { 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: 0x40, os: 1, custom: 1 }, + { opcode: 0x41, os: 1, custom: 1 }, + { opcode: 0x42, os: 1, custom: 1 }, + { opcode: 0x43, os: 1, custom: 1 }, + { opcode: 0x44, os: 1, custom: 1 }, + { opcode: 0x45, os: 1, custom: 1 }, + { opcode: 0x46, os: 1, custom: 1 }, + { opcode: 0x47, os: 1, custom: 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: 0x48, os: 1, custom: 1 }, + { opcode: 0x49, os: 1, custom: 1 }, + { opcode: 0x4A, os: 1, custom: 1 }, + { opcode: 0x4B, os: 1, custom: 1 }, + { opcode: 0x4C, os: 1, custom: 1 }, + { opcode: 0x4D, os: 1, custom: 1 }, + { opcode: 0x4E, os: 1, custom: 1 }, + { opcode: 0x4F, os: 1, custom: 1 }, { opcode: 0x50, custom: 1, os: 1 }, { opcode: 0x51, custom: 1, os: 1 }, diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index a9a3f663..2e5b1ea6 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1051,6 +1051,64 @@ pub fn instr32_3D_jit(ctx: &mut JitContext, imm32: u32) { codegen::gen_call_fn2(ctx.builder, "cmp32"); } +fn gen_inc16(ctx: &mut JitContext, r: u32) { + codegen::gen_get_reg16(ctx, r); + codegen::gen_call_fn1_ret(ctx.builder, "inc16"); + codegen::gen_set_reg16(ctx, r); +} + +fn gen_inc32(ctx: &mut JitContext, r: u32) { + codegen::gen_get_reg32(ctx, r); + codegen::gen_call_fn1_ret(ctx.builder, "inc32"); + codegen::gen_set_reg32(ctx, r); +} + +fn gen_dec16(ctx: &mut JitContext, r: u32) { + codegen::gen_get_reg16(ctx, r); + codegen::gen_call_fn1_ret(ctx.builder, "dec16"); + codegen::gen_set_reg16(ctx, r); +} + +fn gen_dec32(ctx: &mut JitContext, r: u32) { + codegen::gen_get_reg32(ctx, r); + codegen::gen_call_fn1_ret(ctx.builder, "dec32"); + codegen::gen_set_reg32(ctx, r); +} + +pub fn instr16_40_jit(ctx: &mut JitContext) { gen_inc16(ctx, AX); } +pub fn instr32_40_jit(ctx: &mut JitContext) { gen_inc32(ctx, EAX); } +pub fn instr16_41_jit(ctx: &mut JitContext) { gen_inc16(ctx, CX); } +pub fn instr32_41_jit(ctx: &mut JitContext) { gen_inc32(ctx, ECX); } +pub fn instr16_42_jit(ctx: &mut JitContext) { gen_inc16(ctx, DX); } +pub fn instr32_42_jit(ctx: &mut JitContext) { gen_inc32(ctx, EDX); } +pub fn instr16_43_jit(ctx: &mut JitContext) { gen_inc16(ctx, BX); } +pub fn instr32_43_jit(ctx: &mut JitContext) { gen_inc32(ctx, EBX); } +pub fn instr16_44_jit(ctx: &mut JitContext) { gen_inc16(ctx, SP); } +pub fn instr32_44_jit(ctx: &mut JitContext) { gen_inc32(ctx, ESP); } +pub fn instr16_45_jit(ctx: &mut JitContext) { gen_inc16(ctx, BP); } +pub fn instr32_45_jit(ctx: &mut JitContext) { gen_inc32(ctx, EBP); } +pub fn instr16_46_jit(ctx: &mut JitContext) { gen_inc16(ctx, SI); } +pub fn instr32_46_jit(ctx: &mut JitContext) { gen_inc32(ctx, ESI); } +pub fn instr16_47_jit(ctx: &mut JitContext) { gen_inc16(ctx, DI); } +pub fn instr32_47_jit(ctx: &mut JitContext) { gen_inc32(ctx, EDI); } + +pub fn instr16_48_jit(ctx: &mut JitContext) { gen_dec16(ctx, AX); } +pub fn instr32_48_jit(ctx: &mut JitContext) { gen_dec32(ctx, EAX); } +pub fn instr16_49_jit(ctx: &mut JitContext) { gen_dec16(ctx, CX); } +pub fn instr32_49_jit(ctx: &mut JitContext) { gen_dec32(ctx, ECX); } +pub fn instr16_4A_jit(ctx: &mut JitContext) { gen_dec16(ctx, DX); } +pub fn instr32_4A_jit(ctx: &mut JitContext) { gen_dec32(ctx, EDX); } +pub fn instr16_4B_jit(ctx: &mut JitContext) { gen_dec16(ctx, BX); } +pub fn instr32_4B_jit(ctx: &mut JitContext) { gen_dec32(ctx, EBX); } +pub fn instr16_4C_jit(ctx: &mut JitContext) { gen_dec16(ctx, SP); } +pub fn instr32_4C_jit(ctx: &mut JitContext) { gen_dec32(ctx, ESP); } +pub fn instr16_4D_jit(ctx: &mut JitContext) { gen_dec16(ctx, BP); } +pub fn instr32_4D_jit(ctx: &mut JitContext) { gen_dec32(ctx, EBP); } +pub fn instr16_4E_jit(ctx: &mut JitContext) { gen_dec16(ctx, SI); } +pub fn instr32_4E_jit(ctx: &mut JitContext) { gen_dec32(ctx, ESI); } +pub fn instr16_4F_jit(ctx: &mut JitContext) { gen_dec16(ctx, DI); } +pub fn instr32_4F_jit(ctx: &mut JitContext) { gen_dec32(ctx, EDI); } + pub fn instr16_50_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, AX); } pub fn instr32_50_jit(ctx: &mut JitContext) { push32_reg_jit(ctx, EAX); } pub fn instr16_51_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, CX); } From 799171ba03063fd267efd0755c696853b3a7edf0 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 25 Dec 2018 20:00:30 +0100 Subject: [PATCH 1559/2137] Refactor do_page_translation into do_page_walk which does the page walk without calling in case of a fault --- src/rust/cpu2/cpu.rs | 89 ++++++++++++++++++++++++++++++++------------ 1 file changed, 65 insertions(+), 24 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index a2c208b0..2faf753b 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1018,14 +1018,31 @@ pub unsafe fn translate_address_read(address: i32) -> OrPageFault { let entry: i32 = *tlb_data.offset(base as isize); let user: bool = *cpl as i32 == 3; if entry & (TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0 }) == TLB_VALID { - return Ok((entry & !0xFFF ^ address) as u32); + Ok((entry & !0xFFF ^ address) as u32) } else { - return Ok((do_page_translation(address, false, user)? | address & 0xFFF) as u32); - }; + Ok((do_page_translation(address, false, user)? | address & 0xFFF) as u32) + } +} + +pub struct PageFault { + addr: i32, + for_writing: bool, + user: bool, + present: bool, } pub unsafe fn do_page_translation(addr: i32, for_writing: bool, user: bool) -> OrPageFault { + match do_page_walk(addr, for_writing, user) { + Ok(phys_addr) => Ok(phys_addr), + Err(pagefault) => { + trigger_pagefault(pagefault); + Err(()) + }, + } +} + +pub unsafe fn do_page_walk(addr: i32, for_writing: bool, user: bool) -> Result { let mut can_write: bool = true; let global; let mut allow_user: bool = true; @@ -1048,25 +1065,34 @@ pub unsafe fn do_page_translation(addr: i32, for_writing: bool, user: bool) -> O // - set cr2 = addr (which caused the page fault) // - call_interrupt_vector with id 14, error code 0-7 (requires information if read or write) // - prevent execution of the function that triggered this call - *cr.offset(2) = addr; - trigger_pagefault(for_writing, user, false); - return Err(()); + return Err(PageFault { + addr, + for_writing, + user, + present: false, + }); } if page_dir_entry & PAGE_TABLE_RW_MASK == 0 && !kernel_write_override { can_write = false; if for_writing { - *cr.offset(2) = addr; - trigger_pagefault(for_writing, user, true); - return Err(()); + return Err(PageFault { + addr, + for_writing, + user, + present: true, + }); } } if page_dir_entry & PAGE_TABLE_USER_MASK == 0 { allow_user = false; if user { // Page Fault: page table accessed by non-supervisor - *cr.offset(2) = addr; - trigger_pagefault(for_writing, user, true); - return Err(()); + return Err(PageFault { + addr, + for_writing, + user, + present: true, + }); } } if 0 != page_dir_entry & PAGE_TABLE_PSE_MASK && 0 != *cr.offset(4) & CR4_PSE { @@ -1092,24 +1118,33 @@ pub unsafe fn do_page_translation(addr: i32, for_writing: bool, user: bool) -> O .wrapping_add((page & 1023) as u32) as i32; let page_table_entry: i32 = read_aligned32(page_table_addr as u32); if page_table_entry & PAGE_TABLE_PRESENT_MASK == 0 { - *cr.offset(2) = addr; - trigger_pagefault(for_writing, user, false); - return Err(()); + return Err(PageFault { + addr, + for_writing, + user, + present: false, + }); } if page_table_entry & PAGE_TABLE_RW_MASK == 0 && !kernel_write_override { can_write = false; if for_writing { - *cr.offset(2) = addr; - trigger_pagefault(for_writing, user, true); - return Err(()); + return Err(PageFault { + addr, + for_writing, + user, + present: true, + }); } } if page_table_entry & PAGE_TABLE_USER_MASK == 0 { allow_user = false; if user { - *cr.offset(2) = addr; - trigger_pagefault(for_writing, user, true); - return Err(()); + return Err(PageFault { + addr, + for_writing, + user, + present: true, + }); } } @@ -1248,7 +1283,12 @@ pub unsafe fn clear_tlb() { }; } -pub unsafe fn trigger_pagefault(write: bool, user: bool, present: bool) { +pub unsafe fn trigger_pagefault(fault: PageFault) { + let write = fault.for_writing; + let addr = fault.addr; + let present = fault.present; + let user = fault.user; + if false { dbg_log!( "page fault w={} u={} p={} eip={:x} cr2={:x}", @@ -1256,7 +1296,7 @@ pub unsafe fn trigger_pagefault(write: bool, user: bool, present: bool) { user as i32, present as i32, *previous_ip, - *cr.offset(2) + addr ); dbg_trace(); } @@ -1274,7 +1314,8 @@ pub unsafe fn trigger_pagefault(write: bool, user: bool, present: bool) { // dbg_assert!(false); //} // invalidate tlb entry - let page: i32 = (*cr.offset(2) as u32 >> 12) as i32; + *cr.offset(2) = addr; + let page = ((addr as u32) >> 12) as i32; *tlb_data.offset(page as isize) = 0; *prefixes = 0; *instruction_pointer = *previous_ip; From 723f78c14f83ad92e0ae9cfe7d54f97eff0b1969 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Dec 2018 14:25:46 +0100 Subject: [PATCH 1560/2137] Reduce code size by creating a block to jump to that handles the page fault case --- src/rust/codegen.rs | 10 ++++++---- src/rust/jit.rs | 21 ++++++++++++++++----- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index a2c24484..62dfca56 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -578,8 +578,9 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize, where_to_write: Option { pub builder: &'a mut WasmBuilder, pub register_locals: &'a mut Vec, pub start_of_current_instruction: u32, + pub current_brtable_depth: u32, } pub const JIT_INSTR_BLOCK_BOUNDARY_FLAG: u32 = 1 << 0; @@ -988,6 +989,7 @@ fn jit_generate_module( builder, register_locals: &mut register_locals, start_of_current_instruction: 0, + current_brtable_depth: 0, }; // main state machine loop @@ -1020,6 +1022,8 @@ fn jit_generate_module( ctx.builder.instruction_body.block_void(); // for the default case + ctx.builder.instruction_body.block_void(); // for the exit-with-pagefault case + // generate the opening blocks for the cases for _ in 0..basic_blocks.len() { @@ -1029,13 +1033,15 @@ fn jit_generate_module( ctx.builder.instruction_body.get_local(&gen_local_state); ctx.builder .instruction_body - .brtable_and_cases(basic_blocks.len() as u32); + .brtable_and_cases(basic_blocks.len() as u32 + 1); // plus one for the exit-with-pagefault case for (i, block) in basic_blocks.iter().enumerate() { // Case [i] will jump after the [i]th block, so we first generate the // block end opcode and then the code for that block ctx.builder.instruction_body.block_end(); + ctx.current_brtable_depth = basic_blocks.len() as u32 + 1 - i as u32; + dbg_assert!(block.addr < block.end_addr); jit_generate_basic_block(ctx, block.addr, block.last_instruction_addr, block.end_addr); @@ -1063,9 +1069,7 @@ fn jit_generate_module( ctx.builder.instruction_body.const_i32(next_bb_index as i32); ctx.builder.instruction_body.set_local(&gen_local_state); - ctx.builder - .instruction_body - .br(basic_blocks.len() as u32 - i as u32); // to the loop + ctx.builder.instruction_body.br(ctx.current_brtable_depth); // to the loop }, &BasicBlockType::ConditionalJump { next_block_addr, @@ -1131,11 +1135,18 @@ fn jit_generate_module( ctx.builder .instruction_body - .br(basic_blocks.len() as u32 - i as u32); // to the loop + .br(basic_blocks.len() as u32 + 1 - i as u32); // to the loop }, } } + { + // exit-with-pagefault case + ctx.builder.instruction_body.block_end(); + codegen::gen_move_registers_from_locals_to_memory(ctx); + ctx.builder.instruction_body.return_(); + } + ctx.builder.instruction_body.block_end(); // default case ctx.builder.instruction_body.unreachable(); From 724090b3197c47d2a8b5e941bbbabd4151067aa9 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Dec 2018 15:22:08 +0100 Subject: [PATCH 1561/2137] Reduce code size by removing register restoring around safe_{read,write}*_jit --- src/rust/codegen.rs | 12 +- src/rust/cpu2/cpu.rs | 249 +++++++++++++++++++++++++++++-- src/rust/cpu2/global_pointers.rs | 1 + src/rust/jit.rs | 1 + 4 files changed, 245 insertions(+), 18 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 62dfca56..ec3f123f 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -521,8 +521,8 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize, where_to_write: Option { gen_call_fn1_ret(ctx.builder, "safe_read8_slow_jit"); @@ -570,7 +569,6 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize, where_to_write: Option { gen_call_fn2(ctx.builder, "safe_write8_slow_jit"); @@ -756,7 +753,6 @@ fn gen_safe_write( gen_call_fn3_i32_i64_i64(ctx.builder, "safe_write128_slow_jit"); }, } - gen_move_registers_from_memory_to_locals(ctx); ctx.builder .instruction_body diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 2faf753b..d276bd35 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1025,6 +1025,24 @@ pub unsafe fn translate_address_read(address: i32) -> OrPageFault { } } +pub unsafe fn translate_address_read_jit(address: i32) -> OrPageFault { + let base: i32 = (address as u32 >> 12) as i32; + let entry: i32 = *tlb_data.offset(base as isize); + let user: bool = *cpl as i32 == 3; + if entry & (TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0 }) == TLB_VALID { + Ok((entry & !0xFFF ^ address) as u32) + } + else { + match do_page_walk(address, false, user) { + Ok(phys_addr_high) => Ok((phys_addr_high | address & 0xFFF) as u32), + Err(pagefault) => { + trigger_pagefault_jit(pagefault); + Err(()) + }, + } + } +} + pub struct PageFault { addr: i32, for_writing: bool, @@ -1283,6 +1301,66 @@ pub unsafe fn clear_tlb() { }; } +/// Pagefault handling with the jit works as follows: +/// - If the slow path is taken, it calls safe_{read,write}*_jit +/// - safe_{read,write}*_jit call translate_address_{read,write}_jit +/// - translate_address_{read,write}_jit do the normal page walk and call this method instead of +/// trigger_pagefault when a page fault happens +/// - this method prepares a page fault by setting cr2, eip, prefixes and writes the error code +/// into page_fault_error_code. This method *doesn't* trigger the interrupt, as registers are +/// still stored in the wasm module +/// - back in the wasm module, the generated code detects the page fault, restores the registers +/// and finally calls trigger_pagefault_end_jit, which does the interrupt +pub unsafe fn trigger_pagefault_jit(fault: PageFault) { + let write = fault.for_writing; + let addr = fault.addr; + let present = fault.present; + let user = fault.user; + + if false { + dbg_log!( + "page fault jit w={} u={} p={} eip={:x} cr2={:x}", + write as i32, + user as i32, + present as i32, + *previous_ip, + addr + ); + dbg_trace(); + } + if DEBUG { + if must_not_fault { + dbg_log!("Unexpected page fault"); + dbg_trace(); + dbg_assert!(false); + } + } + profiler::stat_increment(PAGE_FAULT); + if DEBUG { + if cpu_exception_hook(CPU_EXCEPTION_PF) { + return; + } + } + //if *page_fault { + // dbg_log!(("double fault")); + // dbg_trace(); + // dbg_assert!(false); + //} + // invalidate tlb entry + *cr.offset(2) = addr; + let page = ((addr as u32) >> 12) as i32; + *tlb_data.offset(page as isize) = 0; + *prefixes = 0; + *instruction_pointer = *previous_ip; + *page_fault_error_code = (user as i32) << 2 | (write as i32) << 1 | present as i32; + //*page_fault = true; +} + +#[no_mangle] +pub unsafe fn trigger_pagefault_end_jit() { + call_interrupt_vector(CPU_EXCEPTION_PF, false, Some(*page_fault_error_code)); +} + pub unsafe fn trigger_pagefault(fault: PageFault) { let write = fault.for_writing; let addr = fault.addr; @@ -1341,6 +1419,26 @@ pub unsafe fn translate_address_write(address: i32) -> OrPageFault { }; } +pub unsafe fn translate_address_write_jit(address: i32) -> OrPageFault { + let base: i32 = (address as u32 >> 12) as i32; + let entry: i32 = *tlb_data.offset(base as isize); + let user: bool = *cpl as i32 == 3; + if entry & (TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0 } | TLB_READONLY) + == TLB_VALID + { + Ok((entry & !0xFFF ^ address) as u32) + } + else { + match do_page_walk(address, true, user) { + Ok(phys_addr_high) => Ok((phys_addr_high | address & 0xFFF) as u32), + Err(pagefault) => { + trigger_pagefault_jit(pagefault); + Err(()) + }, + } + } +} + #[no_mangle] pub unsafe fn tlb_set_has_code(physical_page: Page, has_code: bool) { let physical_page = physical_page.to_u32(); @@ -1405,6 +1503,32 @@ pub unsafe fn writable_or_pagefault(addr: i32, size: i32) -> OrPageFault<()> { }; } +pub unsafe fn writable_or_pagefault_jit(addr: i32, size: i32) -> OrPageFault<()> { + dbg_assert!(size < 0x1000); + dbg_assert!(size > 0); + if *cr & CR0_PG == 0 { + return Ok(()); + } + else { + let user: bool = *cpl as i32 == 3; + let mask: i32 = TLB_READONLY | TLB_VALID | if 0 != user as i32 { TLB_NO_USER } else { 0 }; + let expect: i32 = TLB_VALID; + let page: i32 = (addr as u32 >> 12) as i32; + if *tlb_data.offset(page as isize) & mask != expect { + translate_address_write_jit(addr)?; + } + let next_page: i32 = ((addr + size - 1) as u32 >> 12) as i32; + if page != next_page { + dbg_assert!(next_page == page + 1); + // XXX: possibly out of bounds + if *tlb_data.offset(next_page as isize) & mask != expect { + translate_address_write_jit(next_page << 12)?; + } + } + return Ok(()); + }; +} + pub unsafe fn read_imm8() -> OrPageFault { let eip: i32 = *instruction_pointer; if 0 != eip & !0xFFF ^ *last_virt_eip { @@ -2202,7 +2326,7 @@ pub unsafe fn safe_read32s_slow(addr: i32) -> OrPageFault { #[no_mangle] pub unsafe fn safe_read8_slow_jit(addr: i32) -> i32 { - match safe_read8(addr) { + match safe_read8_slow_jit2(addr) { Ok(v) => { *page_fault = false; v @@ -2214,9 +2338,31 @@ pub unsafe fn safe_read8_slow_jit(addr: i32) -> i32 { } } +unsafe fn safe_read8_slow_jit2(addr: i32) -> OrPageFault { + Ok(read8(translate_address_read_jit(addr)?)) +} + +unsafe fn safe_read16_slow_jit2(addr: i32) -> OrPageFault { + if addr & 0xFFF == 0xFFF { + return Ok(safe_read8_slow_jit2(addr)? | safe_read8_slow_jit2(addr + 1)? << 8); + } + else { + return Ok(read16(translate_address_read_jit(addr)?)); + }; +} + +unsafe fn safe_read32s_slow_jit2(addr: i32) -> OrPageFault { + if addr & 0xFFF >= 0xFFD { + return Ok(safe_read16_slow_jit2(addr)? | safe_read16_slow_jit2(addr + 2)? << 16); + } + else { + return Ok(read32s(translate_address_read_jit(addr)?)); + }; +} + #[no_mangle] pub unsafe fn safe_read16_slow_jit(addr: i32) -> i32 { - match safe_read16_slow(addr) { + match safe_read16_slow_jit2(addr) { Ok(v) => { *page_fault = false; v @@ -2230,7 +2376,7 @@ pub unsafe fn safe_read16_slow_jit(addr: i32) -> i32 { #[no_mangle] pub unsafe fn safe_read32s_slow_jit(addr: i32) -> i32 { - match safe_read32s_slow(addr) { + match safe_read32s_slow_jit2(addr) { Ok(v) => { *page_fault = false; v @@ -2255,9 +2401,22 @@ pub unsafe fn safe_read64s(addr: i32) -> OrPageFault { Ok(x) } +pub unsafe fn safe_read64s_slow_jit2(addr: i32) -> OrPageFault { + let mut x: reg64 = reg64 { i8_0: [0; 8] }; + if addr & 0xFFF > 0x1000 - 8 { + x.u32_0[0] = safe_read32s_slow_jit2(addr)? as u32; + x.u32_0[1] = safe_read32s_slow_jit2(addr + 4)? as u32 + } + else { + let addr_phys = translate_address_read_jit(addr)?; + x.u64_0[0] = read64s(addr_phys) as u64 + } + Ok(x) +} + #[no_mangle] pub unsafe fn safe_read64s_slow_jit(addr: i32) -> i64 { - match safe_read64s(addr) { + match safe_read64s_slow_jit2(addr) { Ok(v) => { *page_fault = false; v.i64_0[0] @@ -2282,9 +2441,22 @@ pub unsafe fn safe_read128s(addr: i32) -> OrPageFault { Ok(x) } +pub unsafe fn safe_read128s_slow_jit2(addr: i32) -> OrPageFault { + let mut x: reg128 = reg128 { i8_0: [0; 16] }; + if addr & 0xFFF > 0x1000 - 16 { + x.u64_0[0] = safe_read64s_slow_jit2(addr)?.u64_0[0]; + x.u64_0[1] = safe_read64s_slow_jit2(addr + 8)?.u64_0[0] + } + else { + let addr_phys = translate_address_read_jit(addr)?; + x = read128(addr_phys) + } + Ok(x) +} + #[no_mangle] pub unsafe fn safe_read128s_slow_jit(addr: i32, where_to_write: u32) { - match safe_read128s(addr) { + match safe_read128s_slow_jit2(addr) { Ok(v) => { *page_fault = false; *(where_to_write as *mut reg128) = v; @@ -2392,25 +2564,56 @@ pub unsafe fn safe_write32_slow(addr: i32, value: i32) -> OrPageFault<()> { Ok(()) } +pub unsafe fn safe_write8_slow_jit2(addr: i32, value: i32) -> OrPageFault<()> { + write8(translate_address_write_jit(addr)?, value); + Ok(()) +} + #[no_mangle] pub unsafe fn safe_write8_slow_jit(addr: i32, value: i32) { - match safe_write8(addr, value) { + match safe_write8_slow_jit2(addr, value) { Ok(()) => *page_fault = false, Err(()) => *page_fault = true, } } +pub unsafe fn safe_write16_slow_jit2(addr: i32, value: i32) -> OrPageFault<()> { + let phys_low = translate_address_write_jit(addr)?; + if addr & 0xFFF == 0xFFF { + virt_boundary_write16(phys_low, translate_address_write_jit(addr + 1)?, value); + } + else { + write16(phys_low as u32, value); + }; + Ok(()) +} + #[no_mangle] pub unsafe fn safe_write16_slow_jit(addr: i32, value: i32) { - match safe_write16_slow(addr, value) { + match safe_write16_slow_jit2(addr, value) { Ok(()) => *page_fault = false, Err(()) => *page_fault = true, } } +pub unsafe fn safe_write32_slow_jit2(addr: i32, value: i32) -> OrPageFault<()> { + let phys_low = translate_address_write_jit(addr)?; + if addr & 0xFFF > 0x1000 - 4 { + virt_boundary_write32( + phys_low, + translate_address_write_jit(addr + 3 & !3)? | (addr as u32 + 3 & 3), + value, + ); + } + else { + write32(phys_low as u32, value); + }; + Ok(()) +} + #[no_mangle] pub unsafe fn safe_write32_slow_jit(addr: i32, value: i32) { - match safe_write32_slow(addr, value) { + match safe_write32_slow_jit2(addr, value) { Ok(()) => *page_fault = false, Err(()) => *page_fault = true, } @@ -2429,9 +2632,22 @@ pub unsafe fn safe_write64(addr: i32, value: i64) -> OrPageFault<()> { Ok(()) } +pub unsafe fn safe_write64_slow_jit2(addr: i32, value: i64) -> OrPageFault<()> { + if addr & 0xFFF > 0x1000 - 8 { + writable_or_pagefault_jit(addr, 8)?; + safe_write32_slow_jit2(addr, value as i32).unwrap(); + safe_write32_slow_jit2(addr + 4, (value >> 32) as i32).unwrap(); + } + else { + let phys = translate_address_write_jit(addr)?; + write64(phys, value); + }; + Ok(()) +} + #[no_mangle] pub unsafe fn safe_write64_slow_jit(addr: i32, value: i64) { - match safe_write64(addr, value) { + match safe_write64_slow_jit2(addr, value) { Ok(()) => *page_fault = false, Err(()) => *page_fault = true, } @@ -2450,9 +2666,22 @@ pub unsafe fn safe_write128(addr: i32, value: reg128) -> OrPageFault<()> { Ok(()) } +pub unsafe fn safe_write128_slow_jit2(addr: i32, value: reg128) -> OrPageFault<()> { + if addr & 0xFFF > 0x1000 - 16 { + writable_or_pagefault_jit(addr, 16)?; + safe_write64_slow_jit2(addr, value.u64_0[0] as i64).unwrap(); + safe_write64_slow_jit2(addr + 8, value.u64_0[1] as i64).unwrap(); + } + else { + let phys = translate_address_write_jit(addr)?; + write128(phys, value); + }; + Ok(()) +} + #[no_mangle] pub unsafe fn safe_write128_slow_jit(addr: i32, value_low: i64, value_high: i64) { - match safe_write128( + match safe_write128_slow_jit2( addr, reg128 { i64_0: [value_low, value_high], diff --git a/src/rust/cpu2/global_pointers.rs b/src/rust/cpu2/global_pointers.rs index e6298e42..1cdd4a5a 100644 --- a/src/rust/cpu2/global_pointers.rs +++ b/src/rust/cpu2/global_pointers.rs @@ -15,6 +15,7 @@ pub const last_result: *mut i32 = 528 as *mut i32; pub const flags_changed: *mut i32 = 532 as *mut i32; pub const flags: *mut i32 = 536 as *mut i32; pub const page_fault: *mut bool = 540 as *mut bool; +pub const page_fault_error_code: *mut i32 = 544 as *mut i32; pub const a20_enabled: *mut bool = 552 as *mut bool; pub const instruction_pointer: *mut i32 = 556 as *mut i32; pub const previous_ip: *mut i32 = 560 as *mut i32; diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 82bebdcd..83134557 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -1144,6 +1144,7 @@ fn jit_generate_module( // exit-with-pagefault case ctx.builder.instruction_body.block_end(); codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_fn0_const(ctx.builder, "trigger_pagefault_end_jit"); ctx.builder.instruction_body.return_(); } From 0269e9cecf14f2964fc86092ec40710d0de4e7c2 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Dec 2018 16:46:20 +0100 Subject: [PATCH 1562/2137] Fix fxtract --- src/rust/cpu2/fpu.rs | 2 +- tests/nasm/fxtract.asm | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 tests/nasm/fxtract.asm diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index f690bb22..50e1fe37 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -769,7 +769,7 @@ pub unsafe fn fpu_fxtract() { *fpu_stack_ptr as i32, f.exponent as f64 - F64_EXPONENT_BIAS as f64, ); - f.exponent = 0x7FF; + f.exponent = 0x3FF; fpu_push(f.to_f64()); } #[no_mangle] diff --git a/tests/nasm/fxtract.asm b/tests/nasm/fxtract.asm new file mode 100644 index 00000000..95c0959b --- /dev/null +++ b/tests/nasm/fxtract.asm @@ -0,0 +1,12 @@ +global _start + +section .data + align 16 + +%include "header.inc" + + push 12345 + fild dword [esp] + fxtract + +%include "footer.inc" From 158bb75fec5dfcf7f340db413552c3194b474b81 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Dec 2018 17:05:57 +0100 Subject: [PATCH 1563/2137] FPU: Implement zero divide fault --- src/rust/cpu2/fpu.rs | 50 ++++++++++++++++++++++++++++++----- src/rust/cpu2/instructions.rs | 9 +------ tests/nasm/fdiv-zero.asm | 14 ++++++++++ tests/nasm/fxtract-zero.asm | 12 +++++++++ tests/nasm/fyl2x-zero.asm | 14 ++++++++++ 5 files changed, 84 insertions(+), 15 deletions(-) create mode 100644 tests/nasm/fdiv-zero.asm create mode 100644 tests/nasm/fxtract-zero.asm create mode 100644 tests/nasm/fyl2x-zero.asm diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 50e1fe37..98e81f56 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -3,6 +3,7 @@ use std::mem::transmute; use cpu2::cpu::*; use cpu2::global_pointers::*; use paging::OrPageFault; +use std::f64; pub fn round(x: f64) -> f64 { x.round() } pub fn floor(x: f64) -> f64 { x.floor() } @@ -23,6 +24,7 @@ const FPU_C3: i32 = 0x4000; const FPU_RESULT_FLAGS: i32 = FPU_C0 | FPU_C1 | FPU_C2 | FPU_C3; const INDEFINITE_NAN: f64 = ::std::f64::NAN; const FPU_EX_I: i32 = 1 << 0; +const FPU_EX_Z: i32 = 1 << 2; const FPU_EX_SF: i32 = 1 << 6; const TWO_POW_63: f64 = 0x8000000000000000u64 as f64; @@ -89,6 +91,12 @@ pub unsafe fn fpu_stack_fault() { *fpu_status_word |= FPU_EX_SF | FPU_EX_I; } +#[no_mangle] +pub unsafe fn fpu_zero_fault() { + // TODO: Interrupt + *fpu_status_word |= FPU_EX_Z; +} + #[no_mangle] pub unsafe fn fpu_sti_empty(mut i: i32) -> bool { dbg_assert!(i >= 0 && i < 8); @@ -305,11 +313,17 @@ pub unsafe fn fpu_fcomp(val: f64) { #[no_mangle] pub unsafe fn fpu_fdiv(target_index: i32, val: f64) { let st0: f64 = fpu_get_st0(); + if val == 0.0 { + fpu_zero_fault(); + } fpu_write_st(*fpu_stack_ptr as i32 + target_index & 7, st0 / val); } #[no_mangle] pub unsafe fn fpu_fdivr(target_index: i32, val: f64) { let st0: f64 = fpu_get_st0(); + if st0 == 0.0 { + fpu_zero_fault(); + } fpu_write_st(*fpu_stack_ptr as i32 + target_index & 7, val / st0); } #[no_mangle] @@ -762,15 +776,37 @@ pub unsafe fn fpu_fxch(i: i32) { fpu_write_st(*fpu_stack_ptr as i32 + i & 7, fpu_get_st0()); fpu_write_st(*fpu_stack_ptr as i32, sti); } +pub unsafe fn fpu_fyl2x() { + let st0 = fpu_get_st0(); + if st0 < 0.0 { + fpu_invalid_arithmetic(); + } + else if st0 == 0.0 { + fpu_zero_fault(); + } + fpu_write_st( + *fpu_stack_ptr as i32 + 1 & 7, + fpu_get_sti(1) * st0.ln() / M_LN2, + ); + fpu_pop(); +} #[no_mangle] pub unsafe fn fpu_fxtract() { - let mut f = FloatParts::of_f64(fpu_get_st0()); - fpu_write_st( - *fpu_stack_ptr as i32, - f.exponent as f64 - F64_EXPONENT_BIAS as f64, - ); - f.exponent = 0x3FF; - fpu_push(f.to_f64()); + let st0 = fpu_get_st0(); + if st0 == 0.0 { + fpu_zero_fault(); + fpu_write_st(*fpu_stack_ptr as i32, f64::NEG_INFINITY); + fpu_push(st0); + } + else { + let mut f = FloatParts::of_f64(st0); + fpu_write_st( + *fpu_stack_ptr as i32, + f.exponent as f64 - F64_EXPONENT_BIAS as f64, + ); + f.exponent = 0x3FF; + fpu_push(f.to_f64()); + } } #[no_mangle] pub unsafe fn fwait() { diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index a5e53b3e..7f8b4a39 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -3698,14 +3698,7 @@ pub unsafe fn instr_D9_6_reg(r: i32) { }, 1 => { // fyl2x - if st0 < 0.0 { - fpu_invalid_arithmetic(); - } - fpu_write_st( - *fpu_stack_ptr as i32 + 1 & 7, - fpu_get_sti(1) * st0.ln() / M_LN2, - ); - fpu_pop(); + fpu_fyl2x(); }, 2 => { // fptan diff --git a/tests/nasm/fdiv-zero.asm b/tests/nasm/fdiv-zero.asm new file mode 100644 index 00000000..8b0d9a6e --- /dev/null +++ b/tests/nasm/fdiv-zero.asm @@ -0,0 +1,14 @@ +global _start + +section .data + align 16 + +%include "header.inc" + + push 1234 + fild dword [esp] + push 0 + fild dword [esp] + fdiv + +%include "footer.inc" diff --git a/tests/nasm/fxtract-zero.asm b/tests/nasm/fxtract-zero.asm new file mode 100644 index 00000000..a14aa941 --- /dev/null +++ b/tests/nasm/fxtract-zero.asm @@ -0,0 +1,12 @@ +global _start + +section .data + align 16 + +%include "header.inc" + + push 0 + fild dword [esp] + fxtract + +%include "footer.inc" diff --git a/tests/nasm/fyl2x-zero.asm b/tests/nasm/fyl2x-zero.asm new file mode 100644 index 00000000..a4290005 --- /dev/null +++ b/tests/nasm/fyl2x-zero.asm @@ -0,0 +1,14 @@ +global _start + +section .data + align 16 + +%include "header.inc" + + push 1234 + fild dword [esp] + push 0 + fild dword [esp] + fyl2x + +%include "footer.inc" From 7c4ed66c200590e13e9364250e52848506794486 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Dec 2018 18:32:39 +0100 Subject: [PATCH 1564/2137] Cleanup: Rename trigger_gp_non_raising to trigger_gp --- src/cpu.js | 44 ++++++++++++++++---------------- src/rust/cpu2/cpu.rs | 32 +++++++++++------------ src/rust/cpu2/instructions.rs | 12 ++++----- src/rust/cpu2/instructions_0f.rs | 44 ++++++++++++++++---------------- src/rust/cpu2/misc_instr.rs | 2 +- 5 files changed, 67 insertions(+), 67 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index 347f1c23..0bc3d8b9 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -266,7 +266,7 @@ CPU.prototype.wasm_patch = function(wm) this.get_eflags_no_arith = get_import("get_eflags_no_arith"); this.update_eflags = get_import("update_eflags"); - this.trigger_gp_non_raising = get_import("trigger_gp_non_raising"); + this.trigger_gp = get_import("trigger_gp"); this.trigger_ud = get_import("trigger_ud"); this.trigger_np = get_import("trigger_np"); this.trigger_ss = get_import("trigger_ss"); @@ -1615,49 +1615,49 @@ CPU.prototype.far_return = function(eip, selector, stack_adjust) if(info.is_null) { dbg_log("null cs", LOG_CPU); - this.trigger_gp_non_raising(0); + this.trigger_gp(0); return; } if(!info.is_valid) { dbg_log("invalid cs: " + h(selector), LOG_CPU); - this.trigger_gp_non_raising(selector & ~3); + this.trigger_gp(selector & ~3); return; } if(info.is_system) { dbg_assert(false, "is system in far return"); - this.trigger_gp_non_raising(selector & ~3); + this.trigger_gp(selector & ~3); return; } if(!info.is_executable) { dbg_log("non-executable cs: " + h(selector), LOG_CPU); - this.trigger_gp_non_raising(selector & ~3); + this.trigger_gp(selector & ~3); return; } if(info.rpl < this.cpl[0]) { dbg_log("cs rpl < cpl: " + h(selector), LOG_CPU); - this.trigger_gp_non_raising(selector & ~3); + this.trigger_gp(selector & ~3); return; } if(info.dc_bit && info.dpl > info.rpl) { dbg_log("cs conforming and dpl > rpl: " + h(selector), LOG_CPU); - this.trigger_gp_non_raising(selector & ~3); + this.trigger_gp(selector & ~3); return; } if(!info.dc_bit && info.dpl !== info.rpl) { dbg_log("cs non-conforming and dpl != rpl: " + h(selector), LOG_CPU); - this.trigger_gp_non_raising(selector & ~3); + this.trigger_gp(selector & ~3); return; } @@ -1781,14 +1781,14 @@ CPU.prototype.far_jump = function(eip, selector, is_call) if(info.is_null) { dbg_log("#gp null cs", LOG_CPU); - this.trigger_gp_non_raising(0); + this.trigger_gp(0); return; } if(!info.is_valid) { dbg_log("#gp invalid cs: " + h(selector), LOG_CPU); - this.trigger_gp_non_raising(selector & ~3); + this.trigger_gp(selector & ~3); return; } @@ -1806,7 +1806,7 @@ CPU.prototype.far_jump = function(eip, selector, is_call) if(info.dpl < this.cpl[0] || info.dpl < info.rpl) { dbg_log("#gp cs gate dpl < cpl or dpl < rpl: " + h(selector), LOG_CPU); - this.trigger_gp_non_raising(selector & ~3); + this.trigger_gp(selector & ~3); return; } @@ -1823,28 +1823,28 @@ CPU.prototype.far_jump = function(eip, selector, is_call) if(cs_info.is_null) { dbg_log("#gp null cs", LOG_CPU); - this.trigger_gp_non_raising(0); + this.trigger_gp(0); return; } if(!cs_info.is_valid) { dbg_log("#gp invalid cs: " + h(cs_selector), LOG_CPU); - this.trigger_gp_non_raising(cs_selector & ~3); + this.trigger_gp(cs_selector & ~3); return; } if(!cs_info.is_executable) { dbg_log("#gp non-executable cs: " + h(cs_selector), LOG_CPU); - this.trigger_gp_non_raising(cs_selector & ~3); + this.trigger_gp(cs_selector & ~3); return; } if(cs_info.dpl > this.cpl[0]) { dbg_log("#gp dpl > cpl: " + h(cs_selector), LOG_CPU); - this.trigger_gp_non_raising(cs_selector & ~3); + this.trigger_gp(cs_selector & ~3); return; } @@ -2038,7 +2038,7 @@ CPU.prototype.far_jump = function(eip, selector, is_call) if(!info.is_executable) { dbg_log("#gp non-executable cs: " + h(selector), LOG_CPU); - this.trigger_gp_non_raising(selector & ~3); + this.trigger_gp(selector & ~3); return; } @@ -2048,7 +2048,7 @@ CPU.prototype.far_jump = function(eip, selector, is_call) if(info.dpl > this.cpl[0]) { dbg_log("#gp cs dpl > cpl: " + h(selector), LOG_CPU); - this.trigger_gp_non_raising(selector & ~3); + this.trigger_gp(selector & ~3); return; } } @@ -2059,7 +2059,7 @@ CPU.prototype.far_jump = function(eip, selector, is_call) if(info.rpl > this.cpl[0] || info.dpl !== this.cpl[0]) { dbg_log("#gp cs rpl > cpl or dpl != cpl: " + h(selector), LOG_CPU); - this.trigger_gp_non_raising(selector & ~3); + this.trigger_gp(selector & ~3); return; } } @@ -2338,7 +2338,7 @@ CPU.prototype.hlt_op = function() if(this.cpl[0]) { dbg_log("#gp hlt with cpl != 0", LOG_CPU); - this.trigger_gp_non_raising(0); + this.trigger_gp(0); return; } @@ -2739,7 +2739,7 @@ CPU.prototype.switch_seg = function(reg, selector) { dbg_log("#GP for loading 0 in SS sel=" + h(selector, 4), LOG_CPU); dbg_trace(LOG_CPU); - this.trigger_gp_non_raising(0); + this.trigger_gp(0); return false; } @@ -2751,7 +2751,7 @@ CPU.prototype.switch_seg = function(reg, selector) { dbg_log("#GP for loading invalid in SS sel=" + h(selector, 4), LOG_CPU); dbg_trace(LOG_CPU); - this.trigger_gp_non_raising(selector & ~3); + this.trigger_gp(selector & ~3); return false; } @@ -2792,7 +2792,7 @@ CPU.prototype.switch_seg = function(reg, selector) this.debug.dump_state(); this.debug.dump_regs(); dbg_trace(LOG_CPU); - this.trigger_gp_non_raising(selector & ~3); + this.trigger_gp(selector & ~3); return false; } diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index d276bd35..1318be4e 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -398,7 +398,7 @@ pub unsafe fn iret(is_16: bool) { if vm86_mode() && getiopl() < 3 { // vm86 mode, iopl != 3 dbg_log!("#gp iret vm86 mode, iopl != 3"); - trigger_gp_non_raising(0); + trigger_gp(0); return; } @@ -449,7 +449,7 @@ pub unsafe fn iret(is_16: bool) { if DEBUG { panic!("NT"); } - trigger_gp_non_raising(0); + trigger_gp(0); return; } @@ -544,7 +544,7 @@ pub unsafe fn iret(is_16: bool) { cs_descriptor.dpl(), cs_selector.rpl() ); - trigger_gp_non_raising(new_cs & !3); + trigger_gp(new_cs & !3); return; } @@ -570,12 +570,12 @@ pub unsafe fn iret(is_16: bool) { SelectorNullOrInvalid::IsNull => { dbg_log!("#GP for loading 0 in SS sel={:x}", temp_ss); dbg_trace(); - trigger_gp_non_raising(0); + trigger_gp(0); return; }, SelectorNullOrInvalid::IsInvalid => { dbg_log!("#GP for loading invalid in SS sel={:x}", temp_ss); - trigger_gp_non_raising(temp_ss & !3); + trigger_gp(temp_ss & !3); return; }, }, @@ -589,7 +589,7 @@ pub unsafe fn iret(is_16: bool) { { dbg_log!("#GP for loading invalid in SS sel={:x}", temp_ss); dbg_trace(); - trigger_gp_non_raising(temp_ss & !3); + trigger_gp(temp_ss & !3); return; } @@ -680,7 +680,7 @@ pub unsafe fn call_interrupt_vector( if vm86_mode() && is_software_int && getiopl() < 3 { dbg_log!("call_interrupt_vector #GP. vm86 && software int && iopl < 3"); dbg_trace(); - trigger_gp_non_raising(0); + trigger_gp(0); return; } @@ -709,7 +709,7 @@ pub unsafe fn call_interrupt_vector( if is_software_int && dpl < *cpl { dbg_log!("#gp software interrupt ({:x}) and dpl < cpl", interrupt_nr); dbg_trace(); - trigger_gp_non_raising(interrupt_nr << 3 | 2); + trigger_gp(interrupt_nr << 3 | 2); return; } @@ -889,7 +889,7 @@ pub unsafe fn call_interrupt_vector( if *flags & FLAG_VM != 0 { dbg_assert!(false, "check error code"); - trigger_gp_non_raising(selector & !3); + trigger_gp(selector & !3); return; } @@ -1633,7 +1633,7 @@ pub unsafe fn switch_seg(reg: i32, selector_raw: i32) -> bool { if selector_unusable == SelectorNullOrInvalid::IsNull { if reg == SS { dbg_log!("#GP for loading 0 in SS sel={:x}", selector_raw); - trigger_gp_non_raising(0); + trigger_gp(0); return false; } else if reg != CS { @@ -1649,7 +1649,7 @@ pub unsafe fn switch_seg(reg: i32, selector_raw: i32) -> bool { reg, selector_raw ); - trigger_gp_non_raising(selector_raw & !3); + trigger_gp(selector_raw & !3); return false; } @@ -1665,7 +1665,7 @@ pub unsafe fn switch_seg(reg: i32, selector_raw: i32) -> bool { || descriptor.dpl() != *cpl { dbg_log!("#GP for loading invalid in SS sel={:x}", selector_raw); - trigger_gp_non_raising(selector_raw & !3); + trigger_gp(selector_raw & !3); return false; } @@ -1692,7 +1692,7 @@ pub unsafe fn switch_seg(reg: i32, selector_raw: i32) -> bool { reg, selector_raw, ); - trigger_gp_non_raising(selector_raw & !3); + trigger_gp(selector_raw & !3); return false; } @@ -1764,7 +1764,7 @@ pub unsafe fn test_privileges_for_io(port: i32, size: i32) -> bool { if *protected_mode && (*cpl > getiopl() as u8 || (*flags & FLAG_VM != 0)) { if !*tss_size_32 { dbg_log!("#GP for port io, 16-bit TSS port={:x} size={}", port, size); - trigger_gp_non_raising(0); + trigger_gp(0); return false; } @@ -1802,7 +1802,7 @@ pub unsafe fn test_privileges_for_io(port: i32, size: i32) -> bool { } dbg_log!("#GP for port io port={:x} size={}", port, size); - trigger_gp_non_raising(0); + trigger_gp(0); return false; } @@ -2108,7 +2108,7 @@ pub unsafe fn trigger_nm() { } #[no_mangle] -pub unsafe fn trigger_gp_non_raising(code: i32) { +pub unsafe fn trigger_gp(code: i32) { if DEBUG { if cpu_exception_hook(CPU_EXCEPTION_GP) { return; diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index 7f8b4a39..c2acf957 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -1701,7 +1701,7 @@ pub unsafe fn instr16_9C() { if 0 != *flags & FLAG_VM && getiopl() < 3 { dbg_assert!(*protected_mode); dbg_log!("pushf #gp"); - trigger_gp_non_raising(0); + trigger_gp(0); } else { return_on_pagefault!(push16(get_eflags())); @@ -1714,7 +1714,7 @@ pub unsafe fn instr32_9C() { // trap to virtual 8086 monitor dbg_assert!(*protected_mode); dbg_log!("pushf #gp"); - trigger_gp_non_raising(0); + trigger_gp(0); } else { // vm and rf flag are cleared in image stored on the stack @@ -1726,7 +1726,7 @@ pub unsafe fn instr16_9D() { // popf if 0 != *flags & FLAG_VM && getiopl() < 3 { dbg_log!("popf #gp"); - trigger_gp_non_raising(0); + trigger_gp(0); return; } else { @@ -1747,7 +1747,7 @@ pub unsafe fn instr32_9D() { // popf if 0 != *flags & FLAG_VM && getiopl() < 3 { dbg_log!("popf #gp"); - trigger_gp_non_raising(0); + trigger_gp(0); return; } else { @@ -3172,7 +3172,7 @@ pub unsafe fn instr_FA() { } else { dbg_log!("cli #gp"); - trigger_gp_non_raising(0); + trigger_gp(0); }; } #[no_mangle] @@ -3200,7 +3200,7 @@ pub unsafe fn instr_FB() { } else { dbg_log!("sti #gp"); - trigger_gp_non_raising(0); + trigger_gp(0); }; } #[no_mangle] diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 817ff829..acf9ee6b 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -103,7 +103,7 @@ pub unsafe fn instr_0F00_2_mem(addr: i32) { return; } else if 0 != *cpl { - trigger_gp_non_raising(0); + trigger_gp(0); return; } else { @@ -118,7 +118,7 @@ pub unsafe fn instr_0F00_2_reg(r: i32) { return; } else if 0 != *cpl { - trigger_gp_non_raising(0); + trigger_gp(0); return; } else { @@ -134,7 +134,7 @@ pub unsafe fn instr_0F00_3_mem(addr: i32) { return; } else if 0 != *cpl { - trigger_gp_non_raising(0); + trigger_gp(0); return; } else { @@ -149,7 +149,7 @@ pub unsafe fn instr_0F00_3_reg(r: i32) { return; } else if 0 != *cpl { - trigger_gp_non_raising(0); + trigger_gp(0); return; } else { @@ -237,7 +237,7 @@ pub unsafe fn instr_0F01_2_reg(r: i32) { trigger_ud(); } pub unsafe fn instr_0F01_2_mem(addr: i32) { // lgdt if 0 != *cpl { - trigger_gp_non_raising(0); + trigger_gp(0); return; } else { @@ -260,7 +260,7 @@ pub unsafe fn instr_0F01_3_reg(r: i32) { trigger_ud(); } pub unsafe fn instr_0F01_3_mem(addr: i32) { // lidt if 0 != *cpl { - trigger_gp_non_raising(0); + trigger_gp(0); return; } else { @@ -298,7 +298,7 @@ pub unsafe fn lmsw(mut new_cr0: i32) { #[no_mangle] pub unsafe fn instr_0F01_6_reg(r: i32) { if 0 != *cpl { - trigger_gp_non_raising(0); + trigger_gp(0); return; } else { @@ -309,7 +309,7 @@ pub unsafe fn instr_0F01_6_reg(r: i32) { #[no_mangle] pub unsafe fn instr_0F01_6_mem(addr: i32) { if 0 != *cpl { - trigger_gp_non_raising(0); + trigger_gp(0); return; } else { @@ -323,7 +323,7 @@ pub unsafe fn instr_0F01_7_reg(r: i32) { trigger_ud(); } pub unsafe fn instr_0F01_7_mem(addr: i32) { // invlpg if 0 != *cpl { - trigger_gp_non_raising(0); + trigger_gp(0); return; } else { @@ -380,7 +380,7 @@ pub unsafe fn instr_0F06() { // clts if 0 != *cpl { dbg_log!("clts #gp"); - trigger_gp_non_raising(0); + trigger_gp(0); } else { if false { @@ -400,7 +400,7 @@ pub unsafe fn instr_0F08() { pub unsafe fn instr_0F09() { if 0 != *cpl { dbg_log!("wbinvd #gp"); - trigger_gp_non_raising(0); + trigger_gp(0); } else { // wbinvd @@ -733,7 +733,7 @@ pub unsafe fn instr_0F1F_mem(addr: i32, r: i32) {} #[no_mangle] pub unsafe fn instr_0F20(r: i32, creg: i32) { if 0 != *cpl { - trigger_gp_non_raising(0); + trigger_gp(0); return; } else { @@ -761,7 +761,7 @@ pub unsafe fn instr_0F20(r: i32, creg: i32) { #[no_mangle] pub unsafe fn instr_0F21(r: i32, mut dreg_index: i32) { if 0 != *cpl { - trigger_gp_non_raising(0); + trigger_gp(0); return; } else { @@ -790,7 +790,7 @@ pub unsafe fn instr_0F21(r: i32, mut dreg_index: i32) { #[no_mangle] pub unsafe fn instr_0F22(r: i32, creg: i32) { if 0 != *cpl { - trigger_gp_non_raising(0); + trigger_gp(0); return; } else { @@ -822,7 +822,7 @@ pub unsafe fn instr_0F22(r: i32, creg: i32) { & ((1 << 11 | 1 << 12 | 1 << 15 | 1 << 16 | 1 << 19) as u32 | 0xFFC00000) { dbg_log!("trigger_gp: Invalid cr4 bit"); - trigger_gp_non_raising(0); + trigger_gp(0); return; } else { @@ -846,7 +846,7 @@ pub unsafe fn instr_0F22(r: i32, creg: i32) { #[no_mangle] pub unsafe fn instr_0F23(r: i32, mut dreg_index: i32) { if 0 != *cpl { - trigger_gp_non_raising(0); + trigger_gp(0); return; } else { @@ -1119,7 +1119,7 @@ pub unsafe fn instr_660F2F_mem(addr: i32, r: i32) { pub unsafe fn instr_0F30() { // wrmsr - write maschine specific register if 0 != *cpl { - trigger_gp_non_raising(0); + trigger_gp(0); return; } else { @@ -1193,14 +1193,14 @@ pub unsafe fn instr_0F31() { } } else { - trigger_gp_non_raising(0); + trigger_gp(0); }; } #[no_mangle] pub unsafe fn instr_0F32() { // rdmsr - read maschine specific register if 0 != *cpl { - trigger_gp_non_raising(0); + trigger_gp(0); return; } else { @@ -1271,7 +1271,7 @@ pub unsafe fn instr_0F34() { // sysenter let seg: i32 = *sysenter_cs & 0xFFFC; if !*protected_mode || seg == 0 { - trigger_gp_non_raising(0); + trigger_gp(0); return; } else { @@ -1298,7 +1298,7 @@ pub unsafe fn instr_0F35() { // sysexit let seg: i32 = *sysenter_cs & 0xFFFC; if !*protected_mode || 0 != *cpl as i32 || seg == 0 { - trigger_gp_non_raising(0); + trigger_gp(0); return; } else { @@ -3288,7 +3288,7 @@ pub unsafe fn instr_0FAE_2_mem(addr: i32) { let new_mxcsr: i32 = return_on_pagefault!(safe_read32s(addr)); if 0 != new_mxcsr & !MXCSR_MASK { dbg_log!("Invalid mxcsr bits: {:x}", new_mxcsr & !MXCSR_MASK); - trigger_gp_non_raising(0); + trigger_gp(0); return; } else { diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index 8d9a1887..455bf457 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -369,7 +369,7 @@ pub unsafe fn fxrstor(addr: i32) { let new_mxcsr: i32 = safe_read32s(addr.wrapping_add(24) as i32).unwrap(); if 0 != new_mxcsr & !MXCSR_MASK { dbg_log!("#gp Invalid mxcsr bits"); - trigger_gp_non_raising(0); + trigger_gp(0); return; } else { From 447307c27f9375936b68027f536f50ae9b86b2c8 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 27 Dec 2018 12:52:00 +0100 Subject: [PATCH 1565/2137] Minor: Remove unnecessary parens --- src/rust/cpu2/instructions_0f.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index acf9ee6b..871c9417 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -812,7 +812,7 @@ pub unsafe fn instr_0F22(r: i32, creg: i32) { dbg_log!("cr3 <- {:x}", data); } data &= !0b111111100111; - dbg_assert!(data & 0xFFF == 0, ("TODO")); + dbg_assert!(data & 0xFFF == 0, "TODO"); *cr.offset(3) = data; clear_tlb(); }, @@ -1149,7 +1149,7 @@ pub unsafe fn instr_0F30() { address == APIC_ADDRESS, ("Changing APIC address not supported") ); - dbg_assert!(low & IA32_APIC_BASE_EXTD == 0, ("x2apic not supported")); + dbg_assert!(low & IA32_APIC_BASE_EXTD == 0, "x2apic not supported"); apic_enabled = low & IA32_APIC_BASE_EN == IA32_APIC_BASE_EN } else if index == IA32_TIME_STAMP_COUNTER { @@ -3313,7 +3313,7 @@ pub unsafe fn instr_0FAE_4_mem(addr: i32) { #[no_mangle] pub unsafe fn instr_0FAE_5_reg(r: i32) { // lfence - dbg_assert!(r == 0, ("Unexpected lfence encoding")); + dbg_assert!(r == 0, "Unexpected lfence encoding"); } #[no_mangle] pub unsafe fn instr_0FAE_5_mem(addr: i32) { @@ -3323,7 +3323,7 @@ pub unsafe fn instr_0FAE_5_mem(addr: i32) { #[no_mangle] pub unsafe fn instr_0FAE_6_reg(r: i32) { // mfence - dbg_assert!(r == 0, ("Unexpected mfence encoding")); + dbg_assert!(r == 0, "Unexpected mfence encoding"); } #[no_mangle] pub unsafe fn instr_0FAE_6_mem(addr: i32) { @@ -3333,7 +3333,7 @@ pub unsafe fn instr_0FAE_6_mem(addr: i32) { #[no_mangle] pub unsafe fn instr_0FAE_7_reg(r: i32) { // sfence - dbg_assert!(r == 0, ("Unexpected sfence encoding")); + dbg_assert!(r == 0, "Unexpected sfence encoding"); } #[no_mangle] pub unsafe fn instr_0FAE_7_mem(addr: i32) { From ce10336747c53f5d7c00037c72dbdefa1bf2e04a Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 27 Dec 2018 19:26:56 +0100 Subject: [PATCH 1566/2137] Minor: Remove unused functions --- src/rust/cpu2/misc_instr.rs | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/rust/cpu2/misc_instr.rs b/src/rust/cpu2/misc_instr.rs index 455bf457..94a258fd 100644 --- a/src/rust/cpu2/misc_instr.rs +++ b/src/rust/cpu2/misc_instr.rs @@ -175,21 +175,11 @@ pub unsafe fn push16_ss32(imm16: i32) -> OrPageFault<()> { Ok(()) } -#[no_mangle] -pub unsafe fn push16_ss16_jit(imm16: i32) { return_on_pagefault!(push16_ss16(imm16)) } -#[no_mangle] -pub unsafe fn push16_ss32_jit(imm16: i32) { return_on_pagefault!(push16_ss32(imm16)) } - #[no_mangle] pub unsafe fn push16_ss16_mem(addr: i32) -> OrPageFault<()> { push16_ss16(safe_read16(addr)?) } #[no_mangle] pub unsafe fn push16_ss32_mem(addr: i32) -> OrPageFault<()> { push16_ss32(safe_read16(addr)?) } -#[no_mangle] -pub unsafe fn push16_ss16_mem_jit(addr: i32) { return_on_pagefault!(push16_ss16_mem(addr)) } -#[no_mangle] -pub unsafe fn push16_ss32_mem_jit(addr: i32) { return_on_pagefault!(push16_ss32_mem(addr)) } - #[no_mangle] pub unsafe fn push16(imm16: i32) -> OrPageFault<()> { if *stack_size_32 { @@ -215,21 +205,11 @@ pub unsafe fn push32_ss32(imm32: i32) -> OrPageFault<()> { Ok(()) } -#[no_mangle] -pub unsafe fn push32_ss16_jit(imm32: i32) { return_on_pagefault!(push32_ss16(imm32)) } -#[no_mangle] -pub unsafe fn push32_ss32_jit(imm32: i32) { return_on_pagefault!(push32_ss32(imm32)) } - #[no_mangle] pub unsafe fn push32_ss16_mem(addr: i32) -> OrPageFault<()> { push32_ss16(safe_read32s(addr)?) } #[no_mangle] pub unsafe fn push32_ss32_mem(addr: i32) -> OrPageFault<()> { push32_ss32(safe_read32s(addr)?) } -#[no_mangle] -pub unsafe fn push32_ss16_mem_jit(addr: i32) { return_on_pagefault!(push32_ss16_mem(addr)) } -#[no_mangle] -pub unsafe fn push32_ss32_mem_jit(addr: i32) { return_on_pagefault!(push32_ss32_mem(addr)) } - #[no_mangle] pub unsafe fn push32(imm32: i32) -> OrPageFault<()> { if *stack_size_32 { From ac9ef7d447678a039a4eed40fda64c2b05839251 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 27 Dec 2018 19:30:37 +0100 Subject: [PATCH 1567/2137] gen_pop/gen_push: Avoid some unnecessary locals after registers-in-locals --- src/rust/codegen.rs | 106 ++++++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 47 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index ec3f123f..a2545275 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -823,7 +823,6 @@ pub fn gen_jmp_rel16(builder: &mut WasmBuilder, rel16: u16) { pub fn gen_pop16_ss16(ctx: &mut JitContext) { // sp = segment_offsets[SS] + reg16[SP] (or just reg16[SP] if has_flat_segmentation) gen_get_reg16(ctx, regs::SP); - let sp_local = ctx.builder.tee_new_local(); if !ctx.cpu.has_flat_segmentation() { ctx.builder @@ -836,20 +835,17 @@ pub fn gen_pop16_ss16(ctx: &mut JitContext) { gen_safe_read16(ctx); // reg16[SP] += 2; - ctx.builder.instruction_body.get_local(&sp_local); + gen_get_reg16(ctx, regs::SP); ctx.builder.instruction_body.const_i32(2); ctx.builder.instruction_body.add_i32(); gen_set_reg16(ctx, regs::SP); - ctx.builder.free_local(sp_local); - // return value is already on stack } pub fn gen_pop16_ss32(ctx: &mut JitContext) { // esp = segment_offsets[SS] + reg32s[ESP] (or just reg32s[ESP] if has_flat_segmentation) gen_get_reg32(ctx, regs::ESP); - let esp_local = ctx.builder.tee_new_local(); if !ctx.cpu.has_flat_segmentation() { ctx.builder @@ -862,11 +858,10 @@ pub fn gen_pop16_ss32(ctx: &mut JitContext) { gen_safe_read16(ctx); // reg32s[ESP] += 2; - ctx.builder.instruction_body.get_local(&esp_local); + gen_get_reg32(ctx, regs::ESP); ctx.builder.instruction_body.const_i32(2); ctx.builder.instruction_body.add_i32(); gen_set_reg32(ctx, regs::ESP); - ctx.builder.free_local(esp_local); // return value is already on stack } @@ -883,7 +878,6 @@ pub fn gen_pop16(ctx: &mut JitContext) { pub fn gen_pop32s_ss16(ctx: &mut JitContext) { // sp = reg16[SP] gen_get_reg16(ctx, regs::SP); - let local_sp = ctx.builder.tee_new_local(); // result = safe_read32s(segment_offsets[SS] + sp) (or just sp if has_flat_segmentation) if !ctx.cpu.has_flat_segmentation() { @@ -896,20 +890,17 @@ pub fn gen_pop32s_ss16(ctx: &mut JitContext) { gen_safe_read32(ctx); // reg16[SP] = sp + 4; - ctx.builder.instruction_body.get_local(&local_sp); + gen_get_reg16(ctx, regs::SP); ctx.builder.instruction_body.const_i32(4); ctx.builder.instruction_body.add_i32(); gen_set_reg16(ctx, regs::SP); - ctx.builder.free_local(local_sp); - // return value is already on stack } pub fn gen_pop32s_ss32(ctx: &mut JitContext) { // esp = reg32s[ESP] gen_get_reg32(ctx, regs::ESP); - let local_esp = ctx.builder.tee_new_local(); // result = safe_read32s(segment_offsets[SS] + esp) (or just esp if has_flat_segmentation) if !ctx.cpu.has_flat_segmentation() { @@ -921,13 +912,11 @@ pub fn gen_pop32s_ss32(ctx: &mut JitContext) { gen_safe_read32(ctx); // reg32s[ESP] = esp + 4; - ctx.builder.instruction_body.get_local(&local_esp); + gen_get_reg32(ctx, regs::ESP); ctx.builder.instruction_body.const_i32(4); ctx.builder.instruction_body.add_i32(); gen_set_reg32(ctx, regs::ESP); - ctx.builder.free_local(local_esp); - // return value is already on stack } @@ -1056,23 +1045,35 @@ pub fn gen_push16(ctx: &mut JitContext, value_local: &WasmLocal) { ctx.builder.instruction_body.const_i32(2); ctx.builder.instruction_body.sub_i32(); - let reg_updated_local = ctx.builder.tee_new_local(); - if !ctx.cpu.ssize_32() { - ctx.builder.instruction_body.const_i32(0xFFFF); - ctx.builder.instruction_body.and_i32(); - } - if !ctx.cpu.has_flat_segmentation() { - ctx.builder - .instruction_body - .load_aligned_i32(global_pointers::get_seg_offset(regs::SS)); - ctx.builder.instruction_body.add_i32(); - } + let reg_updated_local = if !ctx.cpu.ssize_32() || !ctx.cpu.has_flat_segmentation() { + let reg_updated_local = ctx.builder.tee_new_local(); + if !ctx.cpu.ssize_32() { + ctx.builder.instruction_body.const_i32(0xFFFF); + ctx.builder.instruction_body.and_i32(); + } + + if !ctx.cpu.has_flat_segmentation() { + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_seg_offset(regs::SS)); + ctx.builder.instruction_body.add_i32(); + } + + let sp_local = ctx.builder.set_new_local(); + gen_safe_write16(ctx, &sp_local, &value_local); + ctx.builder.free_local(sp_local); + + ctx.builder.instruction_body.get_local(®_updated_local); + reg_updated_local + } + else { + // short path: The address written to is equal to ESP/SP minus two + let reg_updated_local = ctx.builder.tee_new_local(); + gen_safe_write16(ctx, ®_updated_local, &value_local); + reg_updated_local + }; - let sp_local = ctx.builder.set_new_local(); - gen_safe_write16(ctx, &sp_local, &value_local); - ctx.builder.free_local(sp_local); - ctx.builder.instruction_body.get_local(®_updated_local); if ctx.cpu.ssize_32() { gen_set_reg32(ctx, regs::ESP); } @@ -1092,25 +1093,36 @@ pub fn gen_push32(ctx: &mut JitContext, value_local: &WasmLocal) { ctx.builder.instruction_body.const_i32(4); ctx.builder.instruction_body.sub_i32(); - if !ctx.cpu.ssize_32() { - ctx.builder.instruction_body.const_i32(0xFFFF); - ctx.builder.instruction_body.and_i32(); + + let new_sp_local = if !ctx.cpu.ssize_32() || !ctx.cpu.has_flat_segmentation() { + let new_sp_local = ctx.builder.tee_new_local(); + if !ctx.cpu.ssize_32() { + ctx.builder.instruction_body.const_i32(0xFFFF); + ctx.builder.instruction_body.and_i32(); + } + + if !ctx.cpu.has_flat_segmentation() { + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_seg_offset(regs::SS)); + ctx.builder.instruction_body.add_i32(); + } + + let sp_local = ctx.builder.set_new_local(); + + gen_safe_write32(ctx, &sp_local, &value_local); + ctx.builder.free_local(sp_local); + + ctx.builder.instruction_body.get_local(&new_sp_local); + new_sp_local } - let new_sp_local = ctx.builder.tee_new_local(); + else { + // short path: The address written to is equal to ESP/SP minus four + let new_sp_local = ctx.builder.tee_new_local(); + gen_safe_write32(ctx, &new_sp_local, &value_local); + new_sp_local + }; - if !ctx.cpu.has_flat_segmentation() { - ctx.builder - .instruction_body - .load_aligned_i32(global_pointers::get_seg_offset(regs::SS)); - ctx.builder.instruction_body.add_i32(); - } - - let sp_local = ctx.builder.set_new_local(); - - gen_safe_write32(ctx, &sp_local, &value_local); - ctx.builder.free_local(sp_local); - - ctx.builder.instruction_body.get_local(&new_sp_local); if ctx.cpu.ssize_32() { gen_set_reg32(ctx, regs::ESP); } From b774db3f81b06ae10bbfde7caec5c3e49dc85575 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 27 Dec 2018 19:35:16 +0100 Subject: [PATCH 1568/2137] Fix: Clear prefixes when leaving instruction early --- src/rust/codegen.rs | 4 ++++ src/rust/jit.rs | 1 + 2 files changed, 5 insertions(+) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index a2545275..594f96c6 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -1009,6 +1009,7 @@ pub fn gen_task_switch_test(ctx: &mut JitContext) { gen_fn0_const(ctx.builder, "task_switch_test_void"); gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); + gen_clear_prefixes(ctx); ctx.builder.instruction_body.return_(); ctx.builder.instruction_body.block_end(); @@ -1030,6 +1031,7 @@ pub fn gen_task_switch_test_mmx(ctx: &mut JitContext) { gen_fn0_const(ctx.builder, "task_switch_test_mmx_void"); gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); + gen_clear_prefixes(ctx); ctx.builder.instruction_body.return_(); ctx.builder.instruction_body.block_end(); @@ -1285,6 +1287,7 @@ pub fn gen_safe_read_write( ctx.builder.instruction_body.if_void(); gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); gen_move_registers_from_locals_to_memory(ctx); + gen_clear_prefixes(ctx); ctx.builder.instruction_body.return_(); ctx.builder.instruction_body.block_end(); @@ -1313,6 +1316,7 @@ pub fn gen_trigger_ud(ctx: &mut JitContext) { gen_move_registers_from_locals_to_memory(ctx); gen_fn0_const(ctx.builder, "trigger_ud"); gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); + gen_clear_prefixes(ctx); ctx.builder.instruction_body.return_(); } diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 83134557..5d7c7fde 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -1145,6 +1145,7 @@ fn jit_generate_module( ctx.builder.instruction_body.block_end(); codegen::gen_move_registers_from_locals_to_memory(ctx); codegen::gen_fn0_const(ctx.builder, "trigger_pagefault_end_jit"); + codegen::gen_clear_prefixes(ctx); ctx.builder.instruction_body.return_(); } From f22325ecf4694a962aec93deabeccd78b2d7f451 Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 2 Jan 2019 15:37:21 +0100 Subject: [PATCH 1569/2137] Minor: Use hex constant --- src/rust/cpu2/arith.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rust/cpu2/arith.rs b/src/rust/cpu2/arith.rs index a064f293..e7b7ee09 100644 --- a/src/rust/cpu2/arith.rs +++ b/src/rust/cpu2/arith.rs @@ -724,7 +724,7 @@ pub unsafe fn div32(source_operand: u32) { let target_high: u32 = *reg32s.offset(EDX as isize) as u32; let target_operand: u64 = (target_high as u64) << 32 | target_low as u64; let result: u64 = target_operand.wrapping_div(source_operand as u64); - if result > 4294967295 { + if result > 0xFFFFFFFF { trigger_de(); return; } From 0d938fb3da4b310b9c1bfa1ca82cf611feec3974 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 5 Jan 2019 19:29:42 +0100 Subject: [PATCH 1570/2137] Minor: Flatten pattern match --- src/rust/jit.rs | 136 ++++++++++++++++++++++++++---------------------- 1 file changed, 75 insertions(+), 61 deletions(-) diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 5d7c7fde..657c3d4c 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -510,8 +510,10 @@ fn jit_find_basic_blocks( AnalysisType::Jump { offset, is_32, - condition, + condition: Some(condition), } => { + // conditional jump: continue at next and continue at jump target + let jump_target = if is_32 { current_address.wrapping_add(offset as u32) } @@ -524,74 +526,86 @@ fn jit_find_basic_blocks( ) }; - if let Some(condition) = condition { - // conditional jump: continue at next and continue at jump target + dbg_assert!(has_next_instruction); + to_visit_stack.push(current_address as u16 & 0xFFF); - dbg_assert!(has_next_instruction); - to_visit_stack.push(current_address as u16 & 0xFFF); + let next_block_branch_taken_addr; - let next_block_branch_taken_addr; + if Page::page_of(jump_target) == page && !is_near_end_of_page(jump_target) { + to_visit_stack.push(jump_target as u16 & 0xFFF); - if Page::page_of(jump_target) == page && !is_near_end_of_page(jump_target) { - to_visit_stack.push(jump_target as u16 & 0xFFF); + next_block_branch_taken_addr = Some(jump_target); - next_block_branch_taken_addr = Some(jump_target); - - // Very simple heuristic for "infinite loops": This - // detects Linux's "calibrating delay loop" - if jump_target == current_block.addr { - dbg_log!("Basic block looping back to front"); - requires_loop_limit = true; - } + // Very simple heuristic for "infinite loops": This + // detects Linux's "calibrating delay loop" + if jump_target == current_block.addr { + dbg_log!("Basic block looping back to front"); + requires_loop_limit = true; } - else { - next_block_branch_taken_addr = None; - } - - let next_block_addr = if is_near_end_of_page(current_address) { - None - } - else { - Some(current_address) - }; - - current_block.ty = BasicBlockType::ConditionalJump { - next_block_addr, - next_block_branch_taken_addr, - condition, - jump_offset: offset, - jump_offset_is_32: is_32, - }; - - current_block.last_instruction_addr = addr_before_instruction; - current_block.end_addr = current_address; - - break; } else { - // non-conditional jump: continue at jump target - - if has_next_instruction { - // Execution will eventually come back to the next instruction (CALL) - marked_as_entry.insert(current_address as u16 & 0xFFF); - to_visit_stack.push(current_address as u16 & 0xFFF); - } - - if Page::page_of(jump_target) == page && !is_near_end_of_page(jump_target) { - current_block.ty = BasicBlockType::Normal { - next_block_addr: jump_target, - }; - to_visit_stack.push(jump_target as u16 & 0xFFF); - } - else { - current_block.ty = BasicBlockType::Exit; - } - - current_block.last_instruction_addr = addr_before_instruction; - current_block.end_addr = current_address; - - break; + next_block_branch_taken_addr = None; } + + let next_block_addr = if is_near_end_of_page(current_address) { + None + } + else { + Some(current_address) + }; + + current_block.ty = BasicBlockType::ConditionalJump { + next_block_addr, + next_block_branch_taken_addr, + condition, + jump_offset: offset, + jump_offset_is_32: is_32, + }; + + current_block.last_instruction_addr = addr_before_instruction; + current_block.end_addr = current_address; + + break; + }, + AnalysisType::Jump { + offset, + is_32, + condition: None, + } => { + // non-conditional jump: continue at jump target + + let jump_target = if is_32 { + current_address.wrapping_add(offset as u32) + } + else { + ctx.cs_offset.wrapping_add( + (current_address + .wrapping_sub(ctx.cs_offset) + .wrapping_add(offset as u32)) + & 0xFFFF, + ) + }; + + if has_next_instruction { + // Execution will eventually come back to the next instruction (CALL) + marked_as_entry.insert(current_address as u16 & 0xFFF); + to_visit_stack.push(current_address as u16 & 0xFFF); + } + + if Page::page_of(jump_target) == page && !is_near_end_of_page(jump_target) { + current_block.ty = BasicBlockType::Normal { + next_block_addr: jump_target, + }; + to_visit_stack.push(jump_target as u16 & 0xFFF); + } + else { + current_block.ty = BasicBlockType::Exit; + } + + current_block.last_instruction_addr = addr_before_instruction; + current_block.end_addr = current_address; + + break; }, AnalysisType::BlockBoundary => { // a block boundary but not a jump, get out From c086c710ad151217b292529b3ec14a5d43a21419 Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 6 Jan 2019 12:09:28 +0100 Subject: [PATCH 1571/2137] Stat: Count duplicate entries --- src/browser/print_stats.js | 1 + src/rust/jit.rs | 10 ++++++++-- src/rust/profiler.rs | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index 86fa1052..fc04dd21 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -20,6 +20,7 @@ const print_stats = { "COMPILE_WITH_LOOP_SAFETY", "COMPILE_BASIC_BLOCK", "COMPILE_ENTRY_POINT", + "COMPILE_DUPLICATE_ENTRY", "COMPILE_WASM_TOTAL_BYTES", "CACHE_MISMATCH", "RUN_INTERPRETED", diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 657c3d4c..ab8b77aa 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -693,9 +693,15 @@ fn create_cache_entry(ctx: &mut JitState, entry: jit_cache_array::Entry) { for i in 0..CODE_CACHE_SEARCH_SIZE { let addr_index = (phys_addr + i) & jit_cache_array::MASK; - let entry = jit_cache_array::get(addr_index); + let existing_entry = jit_cache_array::get(addr_index); - if entry.start_addr == 0 { + if existing_entry.start_addr == entry.start_addr + && existing_entry.state_flags == entry.state_flags + { + profiler::stat_increment(stat::COMPILE_DUPLICATE_ENTRY); + } + + if existing_entry.start_addr == 0 { found_entry_index = Some(addr_index); break; } diff --git a/src/rust/profiler.rs b/src/rust/profiler.rs index d05d59af..bb5d1daa 100644 --- a/src/rust/profiler.rs +++ b/src/rust/profiler.rs @@ -6,6 +6,7 @@ pub enum stat { COMPILE_WITH_LOOP_SAFETY, COMPILE_BASIC_BLOCK, COMPILE_ENTRY_POINT, + COMPILE_DUPLICATE_ENTRY, COMPILE_WASM_TOTAL_BYTES, CACHE_MISMATCH, From 8eae31295d5fab85c975ed7094f15ae4b983b84b Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 7 Jan 2019 14:58:10 +0100 Subject: [PATCH 1572/2137] nasmtests: Handle exceptions in forced-jit mode --- tests/nasm/run.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/nasm/run.js b/tests/nasm/run.js index 750f5b7a..d28413ae 100755 --- a/tests/nasm/run.js +++ b/tests/nasm/run.js @@ -308,6 +308,8 @@ else { emulator.cpu_exception_hook = function(n) { + emulator.v86.cpu.timestamp_counter[0] += 100000; // always make progress + if(waiting_to_receive_next_test) { return true; @@ -331,11 +333,21 @@ else { // currently don't have this ability, so we record the exception // and continue execution recorded_exceptions.push(exception); + finish_test(); return true; }; emulator.bus.register("cpu-event-halt", function() { - console.assert(!waiting_to_receive_next_test); + finish_test(); + }); + + function finish_test() + { + if(waiting_to_receive_next_test) + { + return; + } + waiting_to_receive_next_test = true; clearTimeout(test_timeout); @@ -478,7 +490,7 @@ else { else { process.send(DONE_MSG); } - }); + } cluster.worker.on("message", function(message) { if(message === TERMINATE_MSG) From 58292cfbc815f77abc03b5e3c8bee9c78912456a Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 7 Jan 2019 15:00:01 +0100 Subject: [PATCH 1573/2137] namstests: Handle pagefaults --- tests/nasm/gen_fixtures.js | 1 + tests/nasm/run.js | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/tests/nasm/gen_fixtures.js b/tests/nasm/gen_fixtures.js index 2cd073dc..690ff7ed 100755 --- a/tests/nasm/gen_fixtures.js +++ b/tests/nasm/gen_fixtures.js @@ -29,6 +29,7 @@ const GDB_DEFAULT_ARGS = [ "--eval-command=catch signal SIGFPE", "--eval-command=catch signal SIGILL", "--eval-command=catch signal SIGSEGV", + "--eval-command=catch signal SIGBUS", ]; /* Split up an array into semi-evenly sized chunks */ diff --git a/tests/nasm/run.js b/tests/nasm/run.js index d28413ae..32db02ef 100755 --- a/tests/nasm/run.js +++ b/tests/nasm/run.js @@ -104,6 +104,11 @@ if(cluster.isMaster) return { exception: "GP", }; } + if(fixture_text.includes("(signal SIGBUS)")) + { + return { exception: "PF", }; + } + if(fixture_text.includes("Program received signal") || fixture_text.includes("SIGILL")) { throw new Error("Test was killed during execution by gdb: " + name + "\n" + fixture_text); From 1f74ee534cfe8dcfe4936296d63c0b0c009a58af Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 7 Jan 2019 15:03:27 +0100 Subject: [PATCH 1574/2137] Simplify cmpxchg using SAFE_READ_WRITE macro --- src/rust/cpu2/arith.rs | 38 +++++++++++++- src/rust/cpu2/instructions_0f.rs | 87 ++++++-------------------------- 2 files changed, 52 insertions(+), 73 deletions(-) diff --git a/src/rust/cpu2/arith.rs b/src/rust/cpu2/arith.rs index e7b7ee09..81b476c0 100644 --- a/src/rust/cpu2/arith.rs +++ b/src/rust/cpu2/arith.rs @@ -1,7 +1,7 @@ use cpu2::cpu::*; use cpu2::global_pointers::*; use cpu2::memory::{read8, write8}; -use cpu2::misc_instr::{getaf, getcf}; +use cpu2::misc_instr::{getaf, getcf, getzf}; pub fn int_log2(x: i32) -> i32 { 31 - x.leading_zeros() as i32 } @@ -270,6 +270,7 @@ pub unsafe fn imul_reg32(operand1: i32, operand2: i32) -> i32 { *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW; return result_low; } + #[no_mangle] pub unsafe fn xadd8(source_operand: i32, reg: i32) -> i32 { let tmp: i32 = *reg8.offset(reg as isize) as i32; @@ -288,6 +289,41 @@ pub unsafe fn xadd32(source_operand: i32, reg: i32) -> i32 { *reg32s.offset(reg as isize) = source_operand; return add(source_operand, tmp, OPSIZE_32); } + +#[no_mangle] +pub unsafe fn cmpxchg8(data: i32, r: i32) -> i32 { + cmp8(*reg8.offset(AL as isize) as i32, data); + if getzf() { + read_reg8(r) + } + else { + *reg8.offset(AL as isize) = data as u8; + data + } +} +#[no_mangle] +pub unsafe fn cmpxchg16(data: i32, r: i32) -> i32 { + cmp16(*reg16.offset(AX as isize) as i32, data); + if getzf() { + read_reg16(r) + } + else { + *reg16.offset(AX as isize) = data as u16; + data + } +} +#[no_mangle] +pub unsafe fn cmpxchg32(data: i32, r: i32) -> i32 { + cmp32(*reg32s.offset(EAX as isize), data); + if getzf() { + read_reg32(r) + } + else { + *reg32s.offset(EAX as isize) = data; + data + } +} + #[no_mangle] pub unsafe fn bcd_daa() { let old_al: i32 = *reg8.offset(AL as isize) as i32; diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 871c9417..0310bf06 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -29,20 +29,21 @@ extern "C" { use cpu2::arith::{ bsf16, bsf32, bsr16, bsr32, bt_mem, bt_reg, btc_mem, btc_reg, btr_mem, btr_reg, bts_mem, - bts_reg, popcnt, shld16, shld32, shrd16, shrd32, xadd16, xadd32, xadd8, + bts_reg, cmpxchg16, cmpxchg32, cmpxchg8, popcnt, shld16, shld32, shrd16, shrd32, xadd16, + xadd32, xadd8, }; use cpu2::arith::{ - cmp16, cmp32, cmp8, imul_reg16, imul_reg32, saturate_sd_to_sb, saturate_sd_to_sw, - saturate_sd_to_ub, saturate_sw_to_sb, saturate_sw_to_ub, saturate_ud_to_ub, saturate_uw, + imul_reg16, imul_reg32, saturate_sd_to_sb, saturate_sd_to_sw, saturate_sd_to_ub, + saturate_sw_to_sb, saturate_sw_to_ub, saturate_ud_to_ub, saturate_uw, }; use cpu2::cpu::*; use cpu2::fpu::fpu_load_m32; use cpu2::fpu::fpu_set_tag_word; use cpu2::global_pointers::*; use cpu2::misc_instr::{ - adjust_stack_reg, bswap, cmovcc16, cmovcc32, fxrstor, fxsave, get_stack_pointer, getzf, - jmpcc16, jmpcc32, push16, push32, setcc_mem, setcc_reg, test_b, test_be, test_l, test_le, - test_o, test_p, test_s, test_z, + adjust_stack_reg, bswap, cmovcc16, cmovcc32, fxrstor, fxsave, get_stack_pointer, jmpcc16, + jmpcc32, push16, push32, setcc_mem, setcc_reg, test_b, test_be, test_l, test_le, test_o, + test_p, test_s, test_z, }; use cpu2::sse_instr::*; @@ -3360,84 +3361,26 @@ pub unsafe fn instr32_0FAF_reg(r1: i32, r: i32) { let ____0: i32 = read_reg32(r1); write_reg32(r, imul_reg32(read_reg32(r), ____0)); } + #[no_mangle] -pub unsafe fn instr_0FB0_reg(r1: i32, r2: i32) { - // cmpxchg8 - let data: i32 = read_reg8(r1); - cmp8(*reg8.offset(AL as isize) as i32, data); - if getzf() { - write_reg8(r1, read_reg8(r2)); - } - else { - *reg8.offset(AL as isize) = data as u8 - }; -} +pub unsafe fn instr_0FB0_reg(r1: i32, r2: i32) { write_reg8(r1, cmpxchg8(read_reg8(r1), r2)); } #[no_mangle] pub unsafe fn instr_0FB0_mem(addr: i32, r: i32) { - // cmpxchg8 - return_on_pagefault!(writable_or_pagefault(addr, 1)); - let data: i32 = return_on_pagefault!(safe_read8(addr)); - cmp8(*reg8.offset(AL as isize) as i32, data); - if getzf() { - safe_write8(addr, read_reg8(r)).unwrap(); - } - else { - safe_write8(addr, data).unwrap(); - *reg8.offset(AL as isize) = data as u8 - }; + SAFE_READ_WRITE8!(___, addr, cmpxchg8(___, r)); } #[no_mangle] -pub unsafe fn instr16_0FB1_reg(r1: i32, r2: i32) { - // cmpxchg16 - let data: i32 = read_reg16(r1); - cmp16(*reg16.offset(AX as isize) as i32, data); - if getzf() { - write_reg16(r1, read_reg16(r2)); - } - else { - *reg16.offset(AX as isize) = data as u16 - }; -} +pub unsafe fn instr16_0FB1_reg(r1: i32, r2: i32) { write_reg16(r1, cmpxchg16(read_reg16(r1), r2)); } #[no_mangle] pub unsafe fn instr16_0FB1_mem(addr: i32, r: i32) { - // cmpxchg16 - return_on_pagefault!(writable_or_pagefault(addr, 2)); - let data: i32 = return_on_pagefault!(safe_read16(addr)); - cmp16(*reg16.offset(AX as isize) as i32, data); - if getzf() { - safe_write16(addr, read_reg16(r)).unwrap(); - } - else { - safe_write16(addr, data).unwrap(); - *reg16.offset(AX as isize) = data as u16 - }; + SAFE_READ_WRITE16!(___, addr, cmpxchg16(___, r)); } #[no_mangle] -pub unsafe fn instr32_0FB1_reg(r1: i32, r2: i32) { - // cmpxchg32 - let data: i32 = read_reg32(r1); - cmp32(*reg32s.offset(EAX as isize), data); - if getzf() { - write_reg32(r1, read_reg32(r2)); - } - else { - *reg32s.offset(EAX as isize) = data - }; -} +pub unsafe fn instr32_0FB1_reg(r1: i32, r2: i32) { write_reg32(r1, cmpxchg32(read_reg32(r1), r2)); } #[no_mangle] pub unsafe fn instr32_0FB1_mem(addr: i32, r: i32) { - // cmpxchg32 - return_on_pagefault!(writable_or_pagefault(addr, 4)); - let data: i32 = return_on_pagefault!(safe_read32s(addr)); - cmp32(*reg32s.offset(EAX as isize), data); - if getzf() { - safe_write32(addr, read_reg32(r)).unwrap(); - } - else { - safe_write32(addr, data).unwrap(); - *reg32s.offset(EAX as isize) = data - }; + SAFE_READ_WRITE32!(___, addr, cmpxchg32(___, r)); } + #[no_mangle] pub unsafe fn instr16_0FB2_reg(unused: i32, unused2: i32) { trigger_ud(); } #[no_mangle] From 2a3e4bfa86fa49c40818919a9f0f9ab8023c6a7a Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 7 Jan 2019 15:07:54 +0100 Subject: [PATCH 1575/2137] Minor: Remove unused --- src/rust/codegen.rs | 2 -- src/rust/global_pointers.rs | 8 -------- src/rust/jit_instructions.rs | 1 - 3 files changed, 11 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 594f96c6..d806c071 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -1327,8 +1327,6 @@ pub fn gen_condition_fn(builder: &mut WasmBuilder, condition: u8) { } pub fn gen_move_registers_from_locals_to_memory(ctx: &mut JitContext) { - let instruction = ::cpu::read32(ctx.start_of_current_instruction); - for i in 0..8 { ctx.builder .instruction_body diff --git a/src/rust/global_pointers.rs b/src/rust/global_pointers.rs index 957ef895..a7c10d42 100644 --- a/src/rust/global_pointers.rs +++ b/src/rust/global_pointers.rs @@ -12,14 +12,6 @@ pub const REG_XMM: u32 = 828; pub const FPU_CONTROL_WORD: u32 = 1036; pub const TLB_DATA: u32 = 0x400000; -pub fn get_reg8_offset(r: u32) -> u32 { - dbg_assert!(r < 8); - REG + (r << 2 & 12 | r >> 2 & 1) -} -pub fn get_reg16_offset(r: u32) -> u32 { - dbg_assert!(r < 8); - REG + 4 * r -} pub fn get_reg32_offset(r: u32) -> u32 { dbg_assert!(r < 8); REG + 4 * r diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 2e5b1ea6..045064e0 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -12,7 +12,6 @@ use regs; use regs::{AX, BP, BX, CX, DI, DX, SI, SP}; use regs::{CS, DS, ES, FS, GS, SS}; use regs::{EAX, EBP, EBX, ECX, EDI, EDX, ESI, ESP}; -use wasmgen::module_init::{WasmBuilder, WasmLocal}; use wasmgen::wasm_util::WasmBuf; pub fn jit_instruction(ctx: &mut JitContext, instr_flags: &mut u32) { From 874818866a282998132bf7b5723e63d945d150a1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 7 Jan 2019 15:16:33 +0100 Subject: [PATCH 1576/2137] Codegen for mul32 + custom mul/imul (F7_[45]) --- gen/x86_table.js | 4 +-- src/rust/codegen.rs | 47 ++++++++++++++++++++++++++ src/rust/global_pointers.rs | 4 +++ src/rust/jit_instructions.rs | 59 ++++++++++++++++++++++++++++----- src/rust/wasmgen/module_init.rs | 8 +++++ src/rust/wasmgen/wasm_util.rs | 15 +++++++++ 6 files changed, 127 insertions(+), 10 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index c7f24678..81918305 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -390,8 +390,8 @@ const encodings = [ { opcode: 0xF7, os: 1, e: 1, fixed_g: 1, imm1632: 1, custom: 1 }, { opcode: 0xF7, os: 1, e: 1, fixed_g: 2, custom: 1 }, { opcode: 0xF7, os: 1, e: 1, fixed_g: 3, custom: 1 }, - { opcode: 0xF7, os: 1, e: 1, fixed_g: 4, mask_flags: zf | af, custom: 0, unguarded_register: 1 }, // XXX: Put custom back - { opcode: 0xF7, os: 1, e: 1, fixed_g: 5, mask_flags: zf | af, custom: 0, unguarded_register: 1 }, // XXX: Put custom back + { opcode: 0xF7, os: 1, e: 1, fixed_g: 4, mask_flags: zf | af, custom: 1 }, + { opcode: 0xF7, os: 1, e: 1, fixed_g: 5, mask_flags: zf | af, custom: 1 }, { opcode: 0xF7, os: 1, e: 1, fixed_g: 6, block_boundary: 1, }, // div/idiv: Not a block boundary, but doesn't use control flow exceptions { opcode: 0xF7, os: 1, e: 1, fixed_g: 7, block_boundary: 1, }, diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index d806c071..802a0802 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -1296,6 +1296,53 @@ pub fn gen_safe_read_write( ctx.builder.free_local(entry_local); } +pub fn gen_set_last_result(builder: &mut WasmBuilder, source: &WasmLocal) { + builder + .instruction_body + .const_i32(global_pointers::LAST_RESULT as i32); + builder.instruction_body.get_local(&source); + builder.instruction_body.store_aligned_i32(0); +} + +pub fn gen_set_last_op_size(builder: &mut WasmBuilder, value: i32) { + builder + .instruction_body + .const_i32(global_pointers::LAST_OP_SIZE as i32); + builder.instruction_body.const_i32(value); + builder.instruction_body.store_aligned_i32(0); +} + +pub fn gen_set_flags_changed(builder: &mut WasmBuilder, value: i32) { + builder + .instruction_body + .const_i32(global_pointers::FLAGS_CHANGED as i32); + builder.instruction_body.const_i32(value); + builder.instruction_body.store_aligned_i32(0); +} + +pub fn gen_set_flags_bits(builder: &mut WasmBuilder, bits_to_set: i32) { + builder + .instruction_body + .const_i32(global_pointers::FLAGS as i32); + builder + .instruction_body + .load_aligned_i32(global_pointers::FLAGS); + builder.instruction_body.const_i32(bits_to_set); + builder.instruction_body.or_i32(); + builder.instruction_body.store_aligned_i32(0); +} + +pub fn gen_clear_flags_bits(builder: &mut WasmBuilder, bits_to_clear: i32) { + builder + .instruction_body + .const_i32(global_pointers::FLAGS as i32); + builder + .instruction_body + .load_aligned_i32(global_pointers::FLAGS); + builder.instruction_body.const_i32(!bits_to_clear); + builder.instruction_body.and_i32(); + builder.instruction_body.store_aligned_i32(0); +} pub fn gen_fpu_get_sti(ctx: &mut JitContext, i: u32) { ctx.builder.instruction_body.const_i32(i as i32); gen_call_fn1_ret_f64(ctx.builder, "fpu_get_sti"); diff --git a/src/rust/global_pointers.rs b/src/rust/global_pointers.rs index a7c10d42..45e082c5 100644 --- a/src/rust/global_pointers.rs +++ b/src/rust/global_pointers.rs @@ -1,4 +1,8 @@ pub const REG: u32 = 4; +pub const LAST_OP_SIZE: u32 = 520; +pub const LAST_RESULT: u32 = 528; +pub const FLAGS_CHANGED: u32 = 532; +pub const FLAGS: u32 = 536; pub const PAGE_FAULT: u32 = 540; pub const INSTRUCTION_POINTER: u32 = 556; pub const PREVIOUS_IP: u32 = 560; diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 045064e0..7fd0688f 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -2,6 +2,7 @@ use codegen; use cpu::BitSize; +use cpu2::cpu::{FLAGS_ALL, FLAG_OVERFLOW, OPSIZE_32}; use global_pointers; use jit::JitContext; use modrm; @@ -751,6 +752,36 @@ macro_rules! define_instruction_read_write_mem32( ); ); +fn gen_mul32(ctx: &mut JitContext) { + ctx.builder.instruction_body.extend_unsigned_i32_to_i64(); + + codegen::gen_get_reg32(ctx, regs::EAX); + ctx.builder.instruction_body.extend_unsigned_i32_to_i64(); + ctx.builder.instruction_body.mul_i64(); + + let result = ctx.builder.tee_new_local_i64(); + ctx.builder.instruction_body.const_i64(32); + ctx.builder.instruction_body.shr_u_i64(); + ctx.builder.instruction_body.wrap_i64_to_i32(); + codegen::gen_set_reg32(ctx, regs::EDX); + + ctx.builder.instruction_body.get_local_i64(&result); + ctx.builder.free_local_i64(result); + ctx.builder.instruction_body.wrap_i64_to_i32(); + codegen::gen_set_reg32(ctx, regs::EAX); + + codegen::gen_get_reg32(ctx, regs::EDX); + ctx.builder.instruction_body.if_void(); + codegen::gen_set_flags_bits(ctx.builder, 1 | FLAG_OVERFLOW); + ctx.builder.instruction_body.else_(); + codegen::gen_clear_flags_bits(ctx.builder, 1 | FLAG_OVERFLOW); + ctx.builder.instruction_body.block_end(); + + codegen::gen_set_last_result(ctx.builder, &ctx.register_locals[regs::EAX as usize]); + codegen::gen_set_last_op_size(ctx.builder, OPSIZE_32); + codegen::gen_set_flags_changed(ctx.builder, FLAGS_ALL & !1 & !FLAG_OVERFLOW); +} + define_instruction_read_write_mem8!( "add8", "instr_00_mem", @@ -2789,41 +2820,53 @@ define_instruction_read_write_mem32!( pub fn instr16_F7_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read16(ctx); - codegen::gen_call_fn1(ctx.builder, "mul16") + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn1(ctx.builder, "mul16"); + codegen::gen_move_registers_from_memory_to_locals(ctx); } pub fn instr16_F7_4_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_get_reg16(ctx, r); - codegen::gen_call_fn1(ctx.builder, "mul16") + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn1(ctx.builder, "mul16"); + codegen::gen_move_registers_from_memory_to_locals(ctx); } pub fn instr32_F7_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); - codegen::gen_call_fn1(ctx.builder, "mul32") + gen_mul32(ctx); } pub fn instr32_F7_4_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_get_reg32(ctx, r); - codegen::gen_call_fn1(ctx.builder, "mul32") + gen_mul32(ctx); } pub fn instr16_F7_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read16(ctx); codegen::sign_extend_i16(ctx.builder); - codegen::gen_call_fn1(ctx.builder, "imul16") + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn1(ctx.builder, "imul16"); + codegen::gen_move_registers_from_memory_to_locals(ctx); } pub fn instr16_F7_5_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_get_reg16(ctx, r); codegen::sign_extend_i16(ctx.builder); - codegen::gen_call_fn1(ctx.builder, "imul16") + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn1(ctx.builder, "imul16"); + codegen::gen_move_registers_from_memory_to_locals(ctx); } pub fn instr32_F7_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); - codegen::gen_call_fn1(ctx.builder, "imul32") + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn1(ctx.builder, "imul32"); + codegen::gen_move_registers_from_memory_to_locals(ctx); } pub fn instr32_F7_5_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_get_reg32(ctx, r); - codegen::gen_call_fn1(ctx.builder, "imul32") + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn1(ctx.builder, "imul32"); + codegen::gen_move_registers_from_memory_to_locals(ctx); } define_instruction_read_write_mem16!( diff --git a/src/rust/wasmgen/module_init.rs b/src/rust/wasmgen/module_init.rs index 00f5e88a..b25fe819 100644 --- a/src/rust/wasmgen/module_init.rs +++ b/src/rust/wasmgen/module_init.rs @@ -512,6 +512,14 @@ impl WasmBuilder { self.instruction_body.push(local.idx()); local } + + #[must_use = "local allocated but not used"] + pub fn tee_new_local_i64(&mut self) -> WasmLocalI64 { + let local = self.alloc_local_i64(); + self.instruction_body.push(op::OP_TEELOCAL); + self.instruction_body.push(local.idx()); + local + } } #[cfg(test)] diff --git a/src/rust/wasmgen/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs index 7ee22ce5..befa037c 100644 --- a/src/rust/wasmgen/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -8,11 +8,13 @@ pub trait WasmBuf { fn write_fixed_leb16_at_idx(&mut self, idx: usize, x: u16); fn write_fixed_leb32_at_idx(&mut self, idx: usize, x: u32); fn const_i32(&mut self, v: i32); + fn const_i64(&mut self, v: i64); fn add_i32(&mut self); fn sub_i32(&mut self); fn and_i32(&mut self); fn or_i32(&mut self); fn shl_i32(&mut self); + fn mul_i64(&mut self); fn call_fn(&mut self, fn_idx: u16); fn eq_i32(&mut self); fn ne_i32(&mut self); @@ -51,9 +53,12 @@ pub trait WasmBuf { fn demote_f64_to_f32(&mut self); fn convert_i32_to_f64(&mut self); fn convert_i64_to_f64(&mut self); + fn extend_unsigned_i32_to_i64(&mut self); + fn wrap_i64_to_i32(&mut self); fn shr_u_i32(&mut self); fn shr_s_i32(&mut self); + fn shr_u_i64(&mut self); fn eqz_i32(&mut self); fn if_void(&mut self); fn else_(&mut self); @@ -91,6 +96,11 @@ impl WasmBuf for Vec { self.write_leb_i32(v); } + fn const_i64(&mut self, v: i64) { + self.push(op::OP_I64CONST); + self.write_leb_i32(v as i32); // XXX + } + fn load_aligned_u16(&mut self, addr: u32) { // doesn't cause a failure in the generated code, but it will be much slower dbg_assert!((addr & 1) == 0); @@ -130,6 +140,8 @@ impl WasmBuf for Vec { fn shl_i32(&mut self) { self.push(op::OP_I32SHL); } + fn mul_i64(&mut self) { self.push(op::OP_I64MUL); } + fn call_fn(&mut self, fn_idx: u16) { self.push(op::OP_CALL); let buf_len = self.len(); @@ -240,8 +252,11 @@ impl WasmBuf for Vec { fn demote_f64_to_f32(&mut self) { self.push(op::OP_F32DEMOTEF64); } fn convert_i32_to_f64(&mut self) { self.push(op::OP_F64CONVERTSI32); } fn convert_i64_to_f64(&mut self) { self.push(op::OP_F64CONVERTSI64); } + fn extend_unsigned_i32_to_i64(&mut self) { self.push(op::OP_I64EXTENDUI32); } + fn wrap_i64_to_i32(&mut self) { self.push(op::OP_I32WRAPI64); } fn shr_u_i32(&mut self) { self.push(op::OP_I32SHRU); } + fn shr_u_i64(&mut self) { self.push(op::OP_I64SHRU); } fn shr_s_i32(&mut self) { self.push(op::OP_I32SHRS); } From fdd1dc377d2548b7aa10923830469911f2ceda6c Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 7 Jan 2019 15:35:57 +0100 Subject: [PATCH 1577/2137] Custom codegen for xadd (0FC1) --- gen/x86_table.js | 2 +- src/rust/codegen.rs | 24 ++++++++++++++++ src/rust/global_pointers.rs | 3 ++ src/rust/jit_instructions.rs | 55 +++++++++++++++++++++++++++++++----- 4 files changed, 76 insertions(+), 8 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 81918305..67c3f93c 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -604,7 +604,7 @@ const encodings = [ { opcode: 0x0FBF, os: 1, e: 1, custom: 1 }, { opcode: 0x0FC0, e: 1, }, // xadd - { opcode: 0x0FC1, os: 1, e: 1, custom: 0, unguarded_register: 1 }, // XXX: Add custom back + { opcode: 0x0FC1, os: 1, e: 1, custom: 1 }, { opcode: 0x0FC8, }, // bswap { opcode: 0x0FC9, }, diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 802a0802..4e2f3524 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -1296,6 +1296,30 @@ pub fn gen_safe_read_write( ctx.builder.free_local(entry_local); } +pub fn gen_set_last_op1(builder: &mut WasmBuilder, source: &WasmLocal) { + builder + .instruction_body + .const_i32(global_pointers::LAST_OP1 as i32); + builder.instruction_body.get_local(&source); + builder.instruction_body.store_aligned_i32(0); +} + +pub fn gen_set_last_op2(builder: &mut WasmBuilder, source: &WasmLocal) { + builder + .instruction_body + .const_i32(global_pointers::LAST_OP2 as i32); + builder.instruction_body.get_local(&source); + builder.instruction_body.store_aligned_i32(0); +} + +pub fn gen_set_last_add_result(builder: &mut WasmBuilder, source: &WasmLocal) { + builder + .instruction_body + .const_i32(global_pointers::LAST_ADD_RESULT as i32); + builder.instruction_body.get_local(&source); + builder.instruction_body.store_aligned_i32(0); +} + pub fn gen_set_last_result(builder: &mut WasmBuilder, source: &WasmLocal) { builder .instruction_body diff --git a/src/rust/global_pointers.rs b/src/rust/global_pointers.rs index 45e082c5..9f88e760 100644 --- a/src/rust/global_pointers.rs +++ b/src/rust/global_pointers.rs @@ -1,5 +1,8 @@ pub const REG: u32 = 4; +pub const LAST_OP1: u32 = 512; +pub const LAST_OP2: u32 = 516; pub const LAST_OP_SIZE: u32 = 520; +pub const LAST_ADD_RESULT: u32 = 524; pub const LAST_RESULT: u32 = 528; pub const FLAGS_CHANGED: u32 = 532; pub const FLAGS: u32 = 536; diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 7fd0688f..62ed9bcd 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -13,6 +13,7 @@ use regs; use regs::{AX, BP, BX, CX, DI, DX, SI, SP}; use regs::{CS, DS, ES, FS, GS, SS}; use regs::{EAX, EBP, EBX, ECX, EDI, EDX, ESI, ESP}; +use wasmgen::module_init::WasmBuilder; use wasmgen::wasm_util::WasmBuf; pub fn jit_instruction(ctx: &mut JitContext, instr_flags: &mut u32) { @@ -752,6 +753,46 @@ macro_rules! define_instruction_read_write_mem32( ); ); +pub fn gen_add32(builder: &mut WasmBuilder) { + let source_operand = builder.set_new_local(); + let dest_operand = builder.set_new_local(); + + builder.instruction_body.get_local(&dest_operand); + builder.instruction_body.get_local(&source_operand); + builder.instruction_body.add_i32(); + let result = builder.set_new_local(); + + codegen::gen_set_last_op1(builder, &dest_operand); + codegen::gen_set_last_op2(builder, &source_operand); + codegen::gen_set_last_add_result(builder, &result); + codegen::gen_set_last_result(builder, &result); + codegen::gen_set_last_op_size(builder, OPSIZE_32); + codegen::gen_set_flags_changed(builder, FLAGS_ALL); + + // leave result on stack + builder.instruction_body.get_local(&result); + + builder.free_local(dest_operand); + builder.free_local(source_operand); + builder.free_local(result); +} + +fn gen_xadd32(ctx: &mut JitContext, r: u32) { + let source = ctx.builder.set_new_local(); + codegen::gen_get_reg32(ctx, r); + let tmp = ctx.builder.set_new_local(); + + ctx.builder.instruction_body.get_local(&source); + codegen::gen_set_reg32(ctx, r); + + ctx.builder.instruction_body.get_local(&source); + ctx.builder.instruction_body.get_local(&tmp); + gen_add32(ctx.builder); + + ctx.builder.free_local(source); + ctx.builder.free_local(tmp); +} + fn gen_mul32(ctx: &mut JitContext) { ctx.builder.instruction_body.extend_unsigned_i32_to_i64(); @@ -3203,12 +3244,12 @@ pub fn instr16_0FC1_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { ctx.builder .instruction_body .const_i32(::cpu2::cpu::get_reg16_index(r as i32)); + codegen::gen_move_registers_from_locals_to_memory(ctx); codegen::gen_call_fn2_ret(ctx.builder, "xadd16"); + codegen::gen_move_registers_from_memory_to_locals(ctx); }, &|ref mut ctx| { - ctx.builder - .instruction_body - .const_i32(::cpu2::cpu::get_reg16_index(r as i32)); + ctx.builder.instruction_body.const_i32(r as i32); codegen::gen_move_registers_from_locals_to_memory(ctx); codegen::gen_call_fn2(ctx.builder, "instr16_0FC1_mem"); codegen::gen_move_registers_from_memory_to_locals(ctx); @@ -3221,7 +3262,9 @@ pub fn instr16_0FC1_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { ctx.builder .instruction_body .const_i32(::cpu2::cpu::get_reg16_index(r2 as i32)); + codegen::gen_move_registers_from_locals_to_memory(ctx); codegen::gen_call_fn2_ret(ctx.builder, "xadd16"); + codegen::gen_move_registers_from_memory_to_locals(ctx); codegen::gen_set_reg16(ctx, r1); } @@ -3233,8 +3276,7 @@ pub fn instr32_0FC1_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { BitSize::DWORD, &address_local, &|ref mut ctx| { - ctx.builder.instruction_body.const_i32(r as i32); - codegen::gen_call_fn2_ret(ctx.builder, "xadd32"); + gen_xadd32(ctx, r); }, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(r as i32); @@ -3247,8 +3289,7 @@ pub fn instr32_0FC1_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { } pub fn instr32_0FC1_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_get_reg32(ctx, r1); - ctx.builder.instruction_body.const_i32(r2 as i32); - codegen::gen_call_fn2_ret(ctx.builder, "xadd32"); + gen_xadd32(ctx, r2); codegen::gen_set_reg32(ctx, r1); } From 815e5d338e3e7c283d70073de237f741c7b01ae4 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 7 Jan 2019 15:45:10 +0100 Subject: [PATCH 1578/2137] Codegen more fpu instructions and run their tests (D9_6, DA_5) --- gen/x86_table.js | 18 +++++++++--------- src/rust/jit_instructions.rs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 67c3f93c..0dc290eb 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -283,12 +283,12 @@ const encodings = [ { opcode: 0xD8, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: 0, custom: 1, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xD9, e: 1, fixed_g: 1, custom: 1, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // skipped: #ud not supported by nasmtests in compiled code - { opcode: 0xD9, e: 1, fixed_g: 2, custom: 1, is_fpu: 1, task_switch_test: 1, only_mem: 1 }, // skipped: #ud not supported by nasmtests in compiled code + { opcode: 0xD9, e: 1, fixed_g: 1, custom: 1, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD9, e: 1, fixed_g: 2, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: 3, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: 4, custom: 1, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // fldenv { opcode: 0xD9, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xD9, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, skip: 1, }, // fstenv (mem), fprem (reg) + { opcode: 0xD9, e: 1, fixed_g: 6, custom: 1, is_fpu: 1, task_switch_test: 1, skip: 1, }, // fstenv (mem), fprem (reg) { opcode: 0xD9, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, only_mem: 1, }, // fprem { opcode: 0xDA, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, }, @@ -296,7 +296,7 @@ const encodings = [ { opcode: 0xDA, e: 1, fixed_g: 2, custom: 0, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDA, e: 1, fixed_g: 3, custom: 0, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDA, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDA, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xDA, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDA, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDA, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, }, @@ -305,7 +305,7 @@ const encodings = [ { opcode: 0xDB, e: 1, fixed_g: 2, custom: 2, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDB, e: 1, fixed_g: 3, custom: 2, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDB, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDB, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // skipped: #ud not supported by nasmtests in compiled code + { opcode: 0xDB, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // XXX: skipped: Seems to page fault or so { opcode: 0xDB, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDB, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, }, @@ -323,14 +323,14 @@ const encodings = [ { opcode: 0xDD, e: 1, fixed_g: 2, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDD, e: 1, fixed_g: 3, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDD, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // frstor - { opcode: 0xDD, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // skipped: #ud not supported by nasmtests in compiled code + { opcode: 0xDD, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDD, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // fsave { opcode: 0xDD, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDE, e: 1, fixed_g: 0, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDE, e: 1, fixed_g: 1, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDE, e: 1, fixed_g: 2, custom: 1, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDE, e: 1, fixed_g: 3, custom: 1, is_fpu: 1, task_switch_test: 1, only_mem: 1, }, // skipped: #ud not supported by nasmtests in compiled code + { opcode: 0xDE, e: 1, fixed_g: 3, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDE, e: 1, fixed_g: 4, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDE, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDE, e: 1, fixed_g: 6, custom: 1, is_fpu: 1, task_switch_test: 1, }, @@ -341,10 +341,10 @@ const encodings = [ { opcode: 0xDF, e: 1, fixed_g: 2, custom: 1, is_fpu: 1, task_switch_test: 1 }, { opcode: 0xDF, e: 1, fixed_g: 3, custom: 1, is_fpu: 1, task_switch_test: 1 }, { opcode: 0xDF, e: 1, fixed_g: 4, custom: 1, is_fpu: 1, task_switch_test: 1, skip: 1 }, // unimplemented (mem): Binary Coded Decimals - // skipped (reg): #ud not supported by nasmtests in compiled code + // skipped (reg): fnstsw { opcode: 0xDF, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDF, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // unimplemented: Binary Coded Decimals - { opcode: 0xDF, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, only_mem: 1 }, // skipped: #ud not supported by nasmtests in compiled code + { opcode: 0xDF, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, }, // loop, jcxz, etc. // Conditional jumps, but condition code not supported by code generator diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 62ed9bcd..33b36fed 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -2423,6 +2423,20 @@ pub fn instr_D9_5_reg_jit(ctx: &mut JitContext, r: u32) { // XXX: May call trigger_ud codegen::gen_fn1_const(ctx.builder, "instr_D9_5_reg", r); } + +pub fn instr_D9_6_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + // XXX: generated because fpu_fstenv might page-fault, but doesn't generate a proper block boundary + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn1(ctx.builder, "fpu_fstenv"); + codegen::gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); + codegen::gen_clear_prefixes(ctx); + ctx.builder.instruction_body.return_(); +} +pub fn instr_D9_6_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_fn1_const(ctx.builder, "instr_D9_6_reg", r); +} + pub fn instr_D9_7_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); @@ -2442,6 +2456,22 @@ pub fn instr_D9_7_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_fn1_const(ctx.builder, "instr_D9_7_reg", r); } +pub fn instr_DA_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + ctx.builder.instruction_body.const_i32(0); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read32(ctx); + ctx.builder.instruction_body.convert_i32_to_f64(); + codegen::gen_call_fn2_i32_f64(ctx.builder, "fpu_fsubr") +} +pub fn instr_DA_5_reg_jit(ctx: &mut JitContext, r: u32) { + if r == 1 { + codegen::gen_fn0_const(ctx.builder, "fpu_fucompp"); + } + else { + codegen::gen_trigger_ud(ctx); + }; +} + pub fn instr_DB_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); From 75e5c2a56ff7683dcb3d293e683fa70c1f3104b9 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 7 Jan 2019 15:47:02 +0100 Subject: [PATCH 1579/2137] Codegen for 8-bit shifts (D0/D2) --- gen/x86_table.js | 4 +- src/rust/jit_instructions.rs | 164 +++++++++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+), 2 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 0dc290eb..33538b17 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -961,9 +961,9 @@ for(let i = 0; i < 8; i++) // 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, custom: 1, }, { opcode: 0xC1, os: 1, e: 1, fixed_g: i, imm8: 1, mask_flags: of | af, custom: 1, }, - { opcode: 0xD0, e: 1, fixed_g: i, mask_flags: af, }, + { opcode: 0xD0, e: 1, fixed_g: i, mask_flags: af, custom: 1 }, { opcode: 0xD1, os: 1, e: 1, fixed_g: i, mask_flags: af, custom: 1, }, - { opcode: 0xD2, e: 1, fixed_g: i, mask_flags: of | af, }, + { opcode: 0xD2, e: 1, fixed_g: i, mask_flags: of | af, custom: 1 }, { opcode: 0xD3, os: 1, e: 1, fixed_g: i, mask_flags: of | af, custom: 1, }, ]); } diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 33b36fed..1f6a8b44 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -362,6 +362,56 @@ macro_rules! define_instruction_read_write_mem8( } ); + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, constant_one) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_safe_read_write(ctx, BitSize::BYTE, &address_local, &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(1); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + }, &|ref mut ctx| { + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn1(ctx.builder, $fallback_fn); + codegen::gen_move_registers_from_memory_to_locals(ctx); + }); + ctx.builder.free_local(address_local); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32) { + codegen::gen_get_reg8(ctx, r1); + ctx.builder.instruction_body.const_i32(1); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + codegen::gen_set_reg8(ctx, r1); + } + ); + + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, cl) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_safe_read_write(ctx, BitSize::BYTE, &address_local, &|ref mut ctx| { + codegen::gen_get_reg8(ctx, regs::CL); + ctx.builder.instruction_body.const_i32(31); + ctx.builder.instruction_body.and_i32(); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + }, &|ref mut ctx| { + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn1(ctx.builder, $fallback_fn); + codegen::gen_move_registers_from_memory_to_locals(ctx); + }); + ctx.builder.free_local(address_local); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32) { + codegen::gen_get_reg8(ctx, r1); + codegen::gen_get_reg8(ctx, regs::CL); + ctx.builder.instruction_body.const_i32(31); + ctx.builder.instruction_body.and_i32(); + codegen::gen_call_fn2_ret(ctx.builder, $fn); + codegen::gen_set_reg8(ctx, r1); + } + ); + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, $imm:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); @@ -2038,6 +2088,63 @@ define_instruction_read_write_mem8!( imm8_5bits ); +define_instruction_read_write_mem8!( + "rol8", + "instr_D0_0_mem", + instr_D0_0_mem_jit, + instr_D0_0_reg_jit, + constant_one +); +define_instruction_read_write_mem8!( + "ror8", + "instr_D0_1_mem", + instr_D0_1_mem_jit, + instr_D0_1_reg_jit, + constant_one +); +define_instruction_read_write_mem8!( + "rcl8", + "instr_D0_2_mem", + instr_D0_2_mem_jit, + instr_D0_2_reg_jit, + constant_one +); +define_instruction_read_write_mem8!( + "rcr8", + "instr_D0_3_mem", + instr_D0_3_mem_jit, + instr_D0_3_reg_jit, + constant_one +); +define_instruction_read_write_mem8!( + "shl8", + "instr_D0_4_mem", + instr_D0_4_mem_jit, + instr_D0_4_reg_jit, + constant_one +); +define_instruction_read_write_mem8!( + "shr8", + "instr_D0_5_mem", + instr_D0_5_mem_jit, + instr_D0_5_reg_jit, + constant_one +); +define_instruction_read_write_mem8!( + "shl8", + "instr_D0_6_mem", + instr_D0_6_mem_jit, + instr_D0_6_reg_jit, + constant_one +); +define_instruction_read_write_mem8!( + "sar8", + "instr_D0_7_mem", + instr_D0_7_mem_jit, + instr_D0_7_reg_jit, + constant_one +); + define_instruction_read_write_mem16!( "rol16", "instr16_D1_0_mem", @@ -2158,6 +2265,63 @@ define_instruction_read_write_mem32!( constant_one ); +define_instruction_read_write_mem8!( + "rol8", + "instr_D2_0_mem", + instr_D2_0_mem_jit, + instr_D2_0_reg_jit, + cl +); +define_instruction_read_write_mem8!( + "ror8", + "instr_D2_1_mem", + instr_D2_1_mem_jit, + instr_D2_1_reg_jit, + cl +); +define_instruction_read_write_mem8!( + "rcl8", + "instr_D2_2_mem", + instr_D2_2_mem_jit, + instr_D2_2_reg_jit, + cl +); +define_instruction_read_write_mem8!( + "rcr8", + "instr_D2_3_mem", + instr_D2_3_mem_jit, + instr_D2_3_reg_jit, + cl +); +define_instruction_read_write_mem8!( + "shl8", + "instr_D2_4_mem", + instr_D2_4_mem_jit, + instr_D2_4_reg_jit, + cl +); +define_instruction_read_write_mem8!( + "shr8", + "instr_D2_5_mem", + instr_D2_5_mem_jit, + instr_D2_5_reg_jit, + cl +); +define_instruction_read_write_mem8!( + "shl8", + "instr_D2_6_mem", + instr_D2_6_mem_jit, + instr_D2_6_reg_jit, + cl +); +define_instruction_read_write_mem8!( + "sar8", + "instr_D2_7_mem", + instr_D2_7_mem_jit, + instr_D2_7_reg_jit, + cl +); + define_instruction_read_write_mem16!( "rol16", "instr16_D3_0_mem", From 93ffd5096918aa19ffdebf017dcb4338cb7e3c30 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 7 Jan 2019 15:51:28 +0100 Subject: [PATCH 1580/2137] Custom codegen for more sse move aliases (660F29/660F6F/F30F7F) --- gen/x86_table.js | 6 +++--- src/rust/jit_instructions.rs | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 33538b17..2c492187 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -646,7 +646,7 @@ const encodings = [ { sse: 1, opcode: 0x0F28, e: 1 }, { sse: 1, opcode: 0x660F28, e: 1 }, { sse: 1, opcode: 0x0F29, e: 1, custom: 1 }, - { sse: 1, opcode: 0x660F29, e: 1 }, + { sse: 1, opcode: 0x660F29, e: 1, custom: 1 }, { sse: 1, opcode: 0x0F2A, e: 1, }, { sse: 1, opcode: 0x660F2A, e: 1, }, { sse: 1, opcode: 0xF20F2A, e: 1, }, @@ -760,7 +760,7 @@ const encodings = [ { sse: 1, opcode: 0x660F6E, e: 1 }, { sse: 1, opcode: 0x0F6E, e: 1 }, { sse: 1, opcode: 0xF30F6F, e: 1, custom: 1 }, - { sse: 1, opcode: 0x660F6F, e: 1 }, + { sse: 1, opcode: 0x660F6F, e: 1, custom: 1 }, { sse: 1, opcode: 0x0F6F, e: 1 }, { sse: 1, opcode: 0x0F70, e: 1, imm8: 1, }, @@ -811,7 +811,7 @@ const encodings = [ { sse: 1, opcode: 0xF30F7E, e: 1 }, { sse: 1, opcode: 0x0F7F, e: 1 }, { sse: 1, opcode: 0x660F7F, e: 1, custom: 1 }, - { sse: 1, opcode: 0xF30F7F, e: 1 }, + { sse: 1, opcode: 0xF30F7F, e: 1, custom: 1 }, { sse: 1, opcode: 0x0FC2, e: 1, imm8: 1 }, { sse: 1, opcode: 0x660FC2, e: 1, imm8: 1 }, diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 1f6a8b44..0c5b9bd8 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -3691,6 +3691,24 @@ pub fn instr_0F29_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_call_fn2(ctx.builder, "instr_0F29_reg") } +pub fn instr_660F29_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + instr_0F29_mem_jit(ctx, modrm_byte, r); +} +pub fn instr_660F29_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + instr_0F29_reg_jit(ctx, r1, r2) +} + +pub fn instr_660F6F_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + // XXX: Aligned read or #gp + codegen::gen_modrm_resolve(ctx, modrm_byte); + let dest = global_pointers::get_reg_xmm_low_offset(r); + codegen::gen_safe_read128(ctx, dest); +} +pub fn instr_660F6F_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + ctx.builder.instruction_body.const_i32(r1 as i32); + ctx.builder.instruction_body.const_i32(r2 as i32); + codegen::gen_call_fn2(ctx.builder, "instr_660F6F_reg") +} pub fn instr_F30F6F_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); let dest = global_pointers::get_reg_xmm_low_offset(r); @@ -3708,3 +3726,9 @@ pub fn instr_660F7F_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { pub fn instr_660F7F_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { instr_0F29_reg_jit(ctx, r1, r2) } +pub fn instr_F30F7F_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + instr_0F29_mem_jit(ctx, modrm_byte, r); +} +pub fn instr_F30F7F_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + instr_0F29_reg_jit(ctx, r1, r2) +} From aadaf138544ec65d8b2e16bf5ada9c99a465170b Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 7 Jan 2019 16:24:07 +0100 Subject: [PATCH 1581/2137] Update expect tests --- tests/expect/tests/call.wast | 468 +++++++++---- tests/expect/tests/do-while.wast | 240 +++++-- tests/expect/tests/if.wast | 261 +++++-- tests/expect/tests/indirect-call.wast | 270 +++++++- tests/expect/tests/mov16.wast | 690 ++++++++++++------- tests/expect/tests/mov32-mem.wast | 583 ++++++++++------ tests/expect/tests/mov32-reg.wast | 221 ++++-- tests/expect/tests/pop.wast | 285 ++++++-- tests/expect/tests/push.wast | 296 ++++++-- tests/expect/tests/task_switch_test.wast | 240 ++++++- tests/expect/tests/task_switch_test_sse.wast | 322 ++++++++- tests/expect/tests/while-do.wast | 256 +++++-- 12 files changed, 3097 insertions(+), 1035 deletions(-) diff --git a/tests/expect/tests/call.wast b/tests/expect/tests/call.wast index 206cd37f..b021d2b7 100644 --- a/tests/expect/tests/call.wast +++ b/tests/expect/tests/call.wast @@ -17,15 +17,40 @@ (type $t15 (func (param i32 i64 i64))) (import "e" "safe_write32_slow_jit" (func $e.safe_write32_slow_jit (type $t2))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) - (import "e" "instr32_40" (func $e.instr32_40 (type $t0))) + (import "e" "inc32" (func $e.inc32 (type $t5))) (import "e" "safe_read32s_slow_jit" (func $e.safe_read32s_slow_jit (type $t5))) + (import "e" "trigger_pagefault_end_jit" (func $e.trigger_pagefault_end_jit (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (local $l10 i32) (local $l11 i32) (local $l12 i32) (local $l13 i32) (set_local $l0 (get_local $p0)) (set_local $l1 (i32.const 10000)) + (set_local $l2 + (i32.load + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) (loop $L0 (set_local $l1 (i32.add @@ -35,13 +60,122 @@ (i32.eqz (get_local $l1)) (then + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) (return))) (block $B2 (block $B3 (block $B4 (block $B5 - (br_table $B5 $B4 $B3 $B2 - (get_local $l0))) + (block $B6 + (br_table $B6 $B5 $B4 $B3 $B2 + (get_local $l0))) + (i32.store + (i32.const 560) + (i32.load + (i32.const 556))) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 5))) + (set_local $l10 + (i32.sub + (i32.load + (i32.const 556)) + (i32.load + (i32.const 740)))) + (set_local $l12 + (i32.add + (tee_local $l11 + (i32.sub + (get_local $l6) + (i32.const 4))) + (i32.load + (i32.const 744)))) + (if $I7 + (i32.and + (i32.eq + (i32.and + (tee_local $l13 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (get_local $l12) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4075)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l12) + (i32.const 4095)) + (i32.const 4092))) + (then + (i32.store offset={normalised output} align=1 + (i32.xor + (i32.and + (get_local $l13) + (i32.const -4096)) + (get_local $l12)) + (get_local $l10))) + (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 0))) + (call $e.safe_write32_slow_jit + (get_local $l12) + (get_local $l10)) + (if $I8 + (i32.load8_u + (i32.const 540)) + (then + (br $B3))))) + (set_local $l6 + (get_local $l11)) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 1))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) + (set_local $l0 + (i32.const 2)) + (br $L0)) (i32.store (i32.const 560) (i32.load @@ -51,176 +185,214 @@ (i32.add (i32.load (i32.const 556)) - (i32.const 5))) - (set_local $l2 - (i32.sub - (i32.load - (i32.const 556)) - (i32.load - (i32.const 740)))) - (set_local $l4 - (i32.add - (tee_local $l3 - (i32.sub - (i32.load - (i32.const 20)) - (i32.const 4))) - (i32.load - (i32.const 744)))) - (if $I6 - (i32.and - (i32.eq - (i32.and - (tee_local $l5 - (i32.load offset=4194304 - (i32.shl - (i32.shr_u - (get_local $l4) - (i32.const 12)) - (i32.const 2)))) - (i32.const 4075)) - (i32.const 1)) - (i32.le_s - (i32.and - (get_local $l4) - (i32.const 4095)) - (i32.const 4092))) - (then - (i32.store offset={normalised output} align=1 - (i32.xor - (i32.and - (get_local $l5) - (i32.const -4096)) - (get_local $l4)) - (get_local $l2))) - (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 0))) - (call $e.safe_write32_slow_jit - (get_local $l4) - (get_local $l2)) - (if $I7 - (i32.load8_u - (i32.const 540)) - (then - (return))))) + (i32.const 1))) (i32.store - (i32.const 20) + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) (get_local $l3)) (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 1))) + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.instr_F4) + (set_local $l2 + (i32.load + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 1))) - (set_local $l0 - (i32.const 2)) - (br $L0)) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (return)) + (set_local $l2 + (call $e.inc32 + (get_local $l2))) (i32.store (i32.const 560) - (i32.load - (i32.const 556))) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 1))) (i32.store (i32.const 556) (i32.add (i32.load (i32.const 556)) - (i32.const 1))) - (call $e.instr_F4) + (i32.const 2))) + (i32.const 556) + (i32.load + (i32.const 740)) + (if $I9 (result i32) + (i32.and + (i32.eq + (i32.and + (tee_local $l11 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (tee_local $l10 + (i32.add + (get_local $l6) + (i32.load + (i32.const 744)))) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4041)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l10) + (i32.const 4095)) + (i32.const 4092))) + (then + (i32.load offset={normalised output} align=1 + (i32.xor + (i32.and + (get_local $l11) + (i32.const -4096)) + (get_local $l10)))) + (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 7))) + (call $e.safe_read32s_slow_jit + (get_local $l10)) + (if $I10 + (i32.load8_u + (i32.const 540)) + (then + (br $B3))))) + (set_local $l6 + (i32.add + (get_local $l6) + (i32.const 4))) + (i32.add) + (i32.store) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) - (i32.const 1))) + (i32.const 2))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) (return)) - (call $e.instr32_40) (i32.store - (i32.const 560) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 1))) + (i32.const 4) + (get_local $l2)) (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 2))) - (i32.const 556) - (i32.load - (i32.const 740)) - (if $I8 (result i32) - (i32.and - (i32.eq - (i32.and - (tee_local $l4 - (i32.load offset=4194304 - (i32.shl - (i32.shr_u - (tee_local $l3 - (i32.add - (tee_local $l2 - (i32.load - (i32.const 20))) - (i32.load - (i32.const 744)))) - (i32.const 12)) - (i32.const 2)))) - (i32.const 4041)) - (i32.const 1)) - (i32.le_s - (i32.and - (get_local $l3) - (i32.const 4095)) - (i32.const 4092))) - (then - (i32.load offset={normalised output} align=1 - (i32.xor - (i32.and - (get_local $l4) - (i32.const -4096)) - (get_local $l3)))) - (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 7))) - (call $e.safe_read32s_slow_jit - (get_local $l3)) - (if $I9 - (i32.load8_u - (i32.const 540)) - (then - (return))))) + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) (i32.store (i32.const 20) - (i32.add - (get_local $l2) - (i32.const 4))) - (i32.add) - (i32.store) + (get_local $l6)) (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 2))) + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.trigger_pagefault_end_jit) + (i32.store + (i32.const 648) + (i32.const 0)) (return)) (unreachable)))) diff --git a/tests/expect/tests/do-while.wast b/tests/expect/tests/do-while.wast index a856a14e..37e97f57 100644 --- a/tests/expect/tests/do-while.wast +++ b/tests/expect/tests/do-while.wast @@ -15,17 +15,42 @@ (type $t13 (func (param f64) (result i64))) (type $t14 (func (param i32 i32 i32) (result i32))) (type $t15 (func (param i32 i64 i64))) - (import "e" "instr32_43" (func $e.instr32_43 (type $t0))) + (import "e" "inc32" (func $e.inc32 (type $t5))) (import "e" "cmp32" (func $e.cmp32 (type $t2))) (import "e" "test_nz" (func $e.test_nz (type $t4))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) + (import "e" "trigger_pagefault_end_jit" (func $e.trigger_pagefault_end_jit (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (set_local $l0 (get_local $p0)) (set_local $l1 (i32.const 10000)) + (set_local $l2 + (i32.load + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) (loop $L0 (set_local $l1 (i32.add @@ -35,66 +60,193 @@ (i32.eqz (get_local $l1)) (then + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) (return))) (block $B2 (block $B3 (block $B4 - (br_table $B4 $B3 $B2 - (get_local $l0))) - (call $e.instr32_43) - (call $e.cmp32 - (i32.load - (i32.const 4)) - (i32.const 10)) + (block $B5 + (br_table $B5 $B4 $B3 $B2 + (get_local $l0))) + (set_local $l5 + (call $e.inc32 + (get_local $l5))) + (call $e.cmp32 + (get_local $l2) + (i32.const 10)) + (i32.store + (i32.const 560) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 4))) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 6))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 3))) + (if $I6 + (call $e.test_nz) + (then + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const -6))) + (set_local $l0 + (i32.const 0))) + (else + (set_local $l0 + (i32.const 1)))) + (br $L0)) (i32.store (i32.const 560) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 4))) + (i32.load + (i32.const 556))) (i32.store (i32.const 556) (i32.add (i32.load (i32.const 556)) - (i32.const 6))) + (i32.const 1))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.instr_F4) + (set_local $l2 + (i32.load + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) - (i32.const 3))) - (if $I5 - (call $e.test_nz) - (then - (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const -6))) - (set_local $l0 - (i32.const 0))) - (else - (set_local $l0 - (i32.const 1)))) - (br $L0)) + (i32.const 1))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (return)) (i32.store - (i32.const 560) - (i32.load - (i32.const 556))) + (i32.const 4) + (get_local $l2)) (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 1))) - (call $e.instr_F4) + (i32.const 8) + (get_local $l3)) (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 1))) + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.trigger_pagefault_end_jit) + (i32.store + (i32.const 648) + (i32.const 0)) (return)) (unreachable)))) diff --git a/tests/expect/tests/if.wast b/tests/expect/tests/if.wast index fb985e2d..f5b98829 100644 --- a/tests/expect/tests/if.wast +++ b/tests/expect/tests/if.wast @@ -17,16 +17,40 @@ (type $t15 (func (param i32 i64 i64))) (import "e" "cmp32" (func $e.cmp32 (type $t2))) (import "e" "test_nle" (func $e.test_nle (type $t4))) - (import "e" "instr32_41" (func $e.instr32_41 (type $t0))) - (import "e" "instr32_43" (func $e.instr32_43 (type $t0))) + (import "e" "inc32" (func $e.inc32 (type $t5))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) + (import "e" "trigger_pagefault_end_jit" (func $e.trigger_pagefault_end_jit (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (set_local $l0 (get_local $p0)) (set_local $l1 (i32.const 10000)) + (set_local $l2 + (i32.load + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) (loop $L0 (set_local $l1 (i32.add @@ -36,89 +60,218 @@ (i32.eqz (get_local $l1)) (then + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) (return))) (block $B2 (block $B3 (block $B4 (block $B5 - (br_table $B5 $B4 $B3 $B2 - (get_local $l0))) - (call $e.cmp32 - (i32.load - (i32.const 4)) - (i32.const 5)) + (block $B6 + (br_table $B6 $B5 $B4 $B3 $B2 + (get_local $l0))) + (call $e.cmp32 + (get_local $l2) + (i32.const 5)) + (i32.store + (i32.const 560) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 3))) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 5))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 2))) + (if $I7 + (call $e.test_nle) + (then + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 1))) + (set_local $l0 + (i32.const 2))) + (else + (set_local $l0 + (i32.const 1)))) + (br $L0)) (i32.store (i32.const 560) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 3))) + (i32.load + (i32.const 556))) (i32.store (i32.const 556) (i32.add (i32.load (i32.const 556)) - (i32.const 5))) + (i32.const 1))) + (set_local $l3 + (call $e.inc32 + (get_local $l3))) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) - (i32.const 2))) - (if $I6 - (call $e.test_nle) - (then - (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 1))) - (set_local $l0 - (i32.const 2))) - (else - (set_local $l0 - (i32.const 1)))) + (i32.const 1))) + (set_local $l0 + (i32.const 2)) (br $L0)) + (set_local $l5 + (call $e.inc32 + (get_local $l5))) (i32.store (i32.const 560) - (i32.load - (i32.const 556))) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 1))) (i32.store (i32.const 556) (i32.add (i32.load (i32.const 556)) - (i32.const 1))) - (call $e.instr32_41) + (i32.const 2))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.instr_F4) + (set_local $l2 + (i32.load + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) - (i32.const 1))) - (set_local $l0 - (i32.const 2)) - (br $L0)) - (call $e.instr32_43) + (i32.const 2))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (return)) (i32.store - (i32.const 560) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 1))) + (i32.const 4) + (get_local $l2)) (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 2))) - (call $e.instr_F4) + (i32.const 8) + (get_local $l3)) (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 2))) + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.trigger_pagefault_end_jit) + (i32.store + (i32.const 648) + (i32.const 0)) (return)) (unreachable)))) diff --git a/tests/expect/tests/indirect-call.wast b/tests/expect/tests/indirect-call.wast index c6a46aa6..5570057d 100644 --- a/tests/expect/tests/indirect-call.wast +++ b/tests/expect/tests/indirect-call.wast @@ -17,13 +17,38 @@ (type $t15 (func (param i32 i64 i64))) (import "e" "instr32_FF_2_mem" (func $e.instr32_FF_2_mem (type $t1))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) + (import "e" "trigger_pagefault_end_jit" (func $e.trigger_pagefault_end_jit (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (set_local $l0 (get_local $p0)) (set_local $l1 (i32.const 10000)) + (set_local $l2 + (i32.load + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) (loop $L0 (set_local $l1 (i32.add @@ -33,12 +58,131 @@ (i32.eqz (get_local $l1)) (then + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) (return))) (block $B2 (block $B3 (block $B4 - (br_table $B4 $B3 $B2 - (get_local $l0))) + (block $B5 + (br_table $B5 $B4 $B3 $B2 + (get_local $l0))) + (i32.store + (i32.const 560) + (i32.load + (i32.const 556))) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 2))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.instr32_FF_2_mem + (i32.add + (get_local $l2) + (i32.load + (i32.const 748)))) + (set_local $l2 + (i32.load + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (return)) (i32.store (i32.const 560) (i32.load @@ -48,36 +192,114 @@ (i32.add (i32.load (i32.const 556)) - (i32.const 2))) - (call $e.instr32_FF_2_mem - (i32.add - (i32.load - (i32.const 4)) - (i32.load - (i32.const 748)))) + (i32.const 1))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.instr_F4) + (set_local $l2 + (i32.load + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 1))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) (return)) (i32.store - (i32.const 560) - (i32.load - (i32.const 556))) + (i32.const 4) + (get_local $l2)) (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 1))) - (call $e.instr_F4) + (i32.const 8) + (get_local $l3)) (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 1))) + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.trigger_pagefault_end_jit) + (i32.store + (i32.const 648) + (i32.const 0)) (return)) (unreachable)))) diff --git a/tests/expect/tests/mov16.wast b/tests/expect/tests/mov16.wast index 1913db72..683ac92a 100644 --- a/tests/expect/tests/mov16.wast +++ b/tests/expect/tests/mov16.wast @@ -18,13 +18,38 @@ (import "e" "safe_read16_slow_jit" (func $e.safe_read16_slow_jit (type $t5))) (import "e" "safe_write16_slow_jit" (func $e.safe_write16_slow_jit (type $t2))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) + (import "e" "trigger_pagefault_end_jit" (func $e.trigger_pagefault_end_jit (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (local $l10 i32) (local $l11 i32) (local $l12 i32) (set_local $l0 (get_local $p0)) (set_local $l1 (i32.const 10000)) + (set_local $l2 + (i32.load + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) (loop $L0 (set_local $l1 (i32.add @@ -34,262 +59,443 @@ (i32.eqz (get_local $l1)) (then + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) (return))) (block $B2 (block $B3 - (br_table $B3 $B2 - (get_local $l0))) - (i32.store16 - (i32.const 4) - (i32.const 51966)) - (i32.store16 - (i32.const 8) - (if $I4 (result i32) - (i32.and - (i32.eq - (i32.and - (tee_local $l3 - (i32.load offset=4194304 - (i32.shl - (i32.shr_u - (tee_local $l2 - (i32.add - (i32.const 32) - (i32.load - (i32.const 748)))) - (i32.const 12)) - (i32.const 2)))) - (i32.const 4041)) - (i32.const 1)) - (i32.le_s - (i32.and - (get_local $l2) - (i32.const 4095)) - (i32.const 4094))) - (then - (i32.load16_u offset={normalised output} align=1 - (i32.xor - (i32.and - (get_local $l3) - (i32.const -4096)) - (get_local $l2)))) - (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 3))) - (call $e.safe_read16_slow_jit - (get_local $l2)) - (if $I5 - (i32.load8_u - (i32.const 540)) - (then - (return)))))) - (i32.store16 - (i32.const 12) - (if $I6 (result i32) - (i32.and - (i32.eq - (i32.and - (tee_local $l2 - (i32.load offset=4194304 - (i32.shl - (i32.shr_u - (tee_local $l3 - (i32.add - (i32.const 36) - (i32.load - (i32.const 748)))) - (i32.const 12)) - (i32.const 2)))) - (i32.const 4041)) - (i32.const 1)) - (i32.le_s - (i32.and - (get_local $l3) - (i32.const 4095)) - (i32.const 4094))) - (then - (i32.load16_u offset={normalised output} align=1 - (i32.xor - (i32.and - (get_local $l2) - (i32.const -4096)) - (get_local $l3)))) - (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 7))) - (call $e.safe_read16_slow_jit - (get_local $l3)) - (if $I7 - (i32.load8_u - (i32.const 540)) - (then - (return)))))) - (i32.store16 - (i32.const 32) - (i32.const 36)) - (i32.store16 - (i32.const 28) - (i32.const 32)) - (set_local $l2 - (i32.add - (i32.and - (i32.add - (i32.load16_u - (i32.const 16)) - (i32.load16_u - (i32.const 32))) - (i32.const 65535)) - (i32.load - (i32.const 748)))) - (set_local $l3 - (i32.load16_u - (i32.const 4))) - (if $I8 - (i32.and - (i32.eq + (block $B4 + (br_table $B4 $B3 $B2 + (get_local $l0))) + (set_local $l2 + (i32.or (i32.and - (tee_local $l4 - (i32.load offset=4194304 - (i32.shl - (i32.shr_u - (get_local $l2) - (i32.const 12)) - (i32.const 2)))) - (i32.const 4075)) - (i32.const 1)) - (i32.le_s + (i32.const 51966) + (i32.const 65535)) (i32.and (get_local $l2) - (i32.const 4095)) - (i32.const 4094))) - (then - (i32.store16 offset={normalised output} align=1 - (i32.xor - (i32.and - (get_local $l4) - (i32.const -4096)) - (get_local $l2)) - (get_local $l3))) - (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 19))) - (call $e.safe_write16_slow_jit - (get_local $l2) - (get_local $l3)) - (if $I9 - (i32.load8_u - (i32.const 540)) - (then - (return))))) - (set_local $l3 - (i32.add - (i32.and - (i32.add - (i32.load16_u - (i32.const 16)) - (i32.load16_u - (i32.const 28))) - (i32.const 65535)) - (i32.load - (i32.const 748)))) - (set_local $l2 - (i32.load16_u - (i32.const 8))) - (if $I10 - (i32.and - (i32.eq + (i32.const -65536)))) + (set_local $l3 + (i32.or (i32.and - (tee_local $l4 - (i32.load offset=4194304 - (i32.shl - (i32.shr_u - (get_local $l3) - (i32.const 12)) - (i32.const 2)))) - (i32.const 4075)) - (i32.const 1)) - (i32.le_s + (if $I5 (result i32) + (i32.and + (i32.eq + (i32.and + (tee_local $l11 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (tee_local $l10 + (i32.add + (i32.const 32) + (i32.load + (i32.const 748)))) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4041)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l10) + (i32.const 4095)) + (i32.const 4094))) + (then + (i32.load16_u offset={normalised output} align=1 + (i32.xor + (i32.and + (get_local $l11) + (i32.const -4096)) + (get_local $l10)))) + (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 3))) + (call $e.safe_read16_slow_jit + (get_local $l10)) + (if $I6 + (i32.load8_u + (i32.const 540)) + (then + (br $B3))))) + (i32.const 65535)) (i32.and (get_local $l3) - (i32.const 4095)) - (i32.const 4094))) - (then - (i32.store16 offset={normalised output} align=1 - (i32.xor + (i32.const -65536)))) + (set_local $l4 + (i32.or + (i32.and + (if $I7 (result i32) + (i32.and + (i32.eq + (i32.and + (tee_local $l10 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (tee_local $l11 + (i32.add + (i32.const 36) + (i32.load + (i32.const 748)))) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4041)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l11) + (i32.const 4095)) + (i32.const 4094))) + (then + (i32.load16_u offset={normalised output} align=1 + (i32.xor + (i32.and + (get_local $l10) + (i32.const -4096)) + (get_local $l11)))) + (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 7))) + (call $e.safe_read16_slow_jit + (get_local $l11)) + (if $I8 + (i32.load8_u + (i32.const 540)) + (then + (br $B3))))) + (i32.const 65535)) + (i32.and + (get_local $l4) + (i32.const -65536)))) + (set_local $l9 + (i32.or + (i32.and + (i32.const 36) + (i32.const 65535)) + (i32.and + (get_local $l9) + (i32.const -65536)))) + (set_local $l8 + (i32.or + (i32.and + (i32.const 32) + (i32.const 65535)) + (i32.and + (get_local $l8) + (i32.const -65536)))) + (set_local $l10 + (i32.add + (i32.and + (i32.add + (i32.and + (get_local $l5) + (i32.const 65535)) + (i32.and + (get_local $l9) + (i32.const 65535))) + (i32.const 65535)) + (i32.load + (i32.const 748)))) + (set_local $l11 + (i32.and + (get_local $l2) + (i32.const 65535))) + (if $I9 + (i32.and + (i32.eq (i32.and - (get_local $l4) - (i32.const -4096)) - (get_local $l3)) - (get_local $l2))) - (else - (i32.store - (i32.const 560) - (i32.or + (tee_local $l12 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (get_local $l10) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4075)) + (i32.const 1)) + (i32.le_s (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 21))) - (call $e.safe_write16_slow_jit + (get_local $l10) + (i32.const 4095)) + (i32.const 4094))) + (then + (i32.store16 offset={normalised output} align=1 + (i32.xor + (i32.and + (get_local $l12) + (i32.const -4096)) + (get_local $l10)) + (get_local $l11))) + (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 19))) + (call $e.safe_write16_slow_jit + (get_local $l10) + (get_local $l11)) + (if $I10 + (i32.load8_u + (i32.const 540)) + (then + (br $B3))))) + (set_local $l11 + (i32.add + (i32.and + (i32.add + (i32.and + (get_local $l5) + (i32.const 65535)) + (i32.and + (get_local $l8) + (i32.const 65535))) + (i32.const 65535)) + (i32.load + (i32.const 748)))) + (set_local $l10 + (i32.and (get_local $l3) - (get_local $l2)) - (if $I11 - (i32.load8_u - (i32.const 540)) - (then - (return))))) - (i32.store16 - (i32.const 8) - (i32.load16_u - (i32.const 28))) - (i32.store16 - (i32.const 12) - (i32.load16_u - (i32.const 32))) - (i32.store16 - (i32.const 12) - (i32.load16_u - (i32.const 4))) - (i32.store16 + (i32.const 65535))) + (if $I11 + (i32.and + (i32.eq + (i32.and + (tee_local $l12 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (get_local $l11) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4075)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l11) + (i32.const 4095)) + (i32.const 4094))) + (then + (i32.store16 offset={normalised output} align=1 + (i32.xor + (i32.and + (get_local $l12) + (i32.const -4096)) + (get_local $l11)) + (get_local $l10))) + (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 21))) + (call $e.safe_write16_slow_jit + (get_local $l11) + (get_local $l10)) + (if $I12 + (i32.load8_u + (i32.const 540)) + (then + (br $B3))))) + (set_local $l3 + (i32.or + (i32.and + (i32.and + (get_local $l8) + (i32.const 65535)) + (i32.const 65535)) + (i32.and + (get_local $l3) + (i32.const -65536)))) + (set_local $l4 + (i32.or + (i32.and + (i32.and + (get_local $l9) + (i32.const 65535)) + (i32.const 65535)) + (i32.and + (get_local $l4) + (i32.const -65536)))) + (set_local $l4 + (i32.or + (i32.and + (i32.and + (get_local $l2) + (i32.const 65535)) + (i32.const 65535)) + (i32.and + (get_local $l4) + (i32.const -65536)))) + (set_local $l2 + (i32.or + (i32.and + (i32.and + (get_local $l3) + (i32.const 65535)) + (i32.const 65535)) + (i32.and + (get_local $l2) + (i32.const -65536)))) + (i32.store + (i32.const 560) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 31))) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 32))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.instr_F4) + (set_local $l2 + (i32.load + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 12))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (return)) + (i32.store (i32.const 4) - (i32.load16_u - (i32.const 8))) + (get_local $l2)) (i32.store - (i32.const 560) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 31))) + (i32.const 8) + (get_local $l3)) (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 32))) - (call $e.instr_F4) + (i32.const 12) + (get_local $l4)) (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 12))) + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.trigger_pagefault_end_jit) + (i32.store + (i32.const 648) + (i32.const 0)) (return)) (unreachable)))) diff --git a/tests/expect/tests/mov32-mem.wast b/tests/expect/tests/mov32-mem.wast index 05e8f8ea..363d0b7f 100644 --- a/tests/expect/tests/mov32-mem.wast +++ b/tests/expect/tests/mov32-mem.wast @@ -18,13 +18,38 @@ (import "e" "safe_write32_slow_jit" (func $e.safe_write32_slow_jit (type $t2))) (import "e" "safe_read32s_slow_jit" (func $e.safe_read32s_slow_jit (type $t5))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) + (import "e" "trigger_pagefault_end_jit" (func $e.trigger_pagefault_end_jit (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (local $l10 i32) (local $l11 i32) (local $l12 i32) (set_local $l0 (get_local $p0)) (set_local $l1 (i32.const 10000)) + (set_local $l2 + (i32.load + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) (loop $L0 (set_local $l1 (i32.add @@ -34,237 +59,355 @@ (i32.eqz (get_local $l1)) (then + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) (return))) (block $B2 (block $B3 - (br_table $B3 $B2 - (get_local $l0))) - (set_local $l2 - (i32.add + (block $B4 + (br_table $B4 $B3 $B2 + (get_local $l0))) + (set_local $l10 + (i32.add + (i32.add + (get_local $l5) + (i32.const 32)) + (i32.load + (i32.const 748)))) + (set_local $l11 + (get_local $l2)) + (if $I5 + (i32.and + (i32.eq + (i32.and + (tee_local $l12 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (get_local $l10) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4075)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l10) + (i32.const 4095)) + (i32.const 4092))) + (then + (i32.store offset={normalised output} align=1 + (i32.xor + (i32.and + (get_local $l12) + (i32.const -4096)) + (get_local $l10)) + (get_local $l11))) + (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 0))) + (call $e.safe_write32_slow_jit + (get_local $l10) + (get_local $l11)) + (if $I6 + (i32.load8_u + (i32.const 540)) + (then + (br $B3))))) + (set_local $l11 + (i32.add + (i32.add + (get_local $l4) + (i32.const 28)) + (i32.load + (i32.const 748)))) + (set_local $l10 + (get_local $l3)) + (if $I7 + (i32.and + (i32.eq + (i32.and + (tee_local $l12 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (get_local $l11) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4075)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l11) + (i32.const 4095)) + (i32.const 4092))) + (then + (i32.store offset={normalised output} align=1 + (i32.xor + (i32.and + (get_local $l12) + (i32.const -4096)) + (get_local $l11)) + (get_local $l10))) + (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 6))) + (call $e.safe_write32_slow_jit + (get_local $l11) + (get_local $l10)) + (if $I8 + (i32.load8_u + (i32.const 540)) + (then + (br $B3))))) + (set_local $l8 + (if $I9 (result i32) + (i32.and + (i32.eq + (i32.and + (tee_local $l11 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (tee_local $l10 + (i32.add + (i32.add + (get_local $l5) + (i32.const 28)) + (i32.load + (i32.const 748)))) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4041)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l10) + (i32.const 4095)) + (i32.const 4092))) + (then + (i32.load offset={normalised output} align=1 + (i32.xor + (i32.and + (get_local $l11) + (i32.const -4096)) + (get_local $l10)))) + (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 12))) + (call $e.safe_read32s_slow_jit + (get_local $l10)) + (if $I10 + (i32.load8_u + (i32.const 540)) + (then + (br $B3)))))) + (set_local $l9 + (if $I11 (result i32) + (i32.and + (i32.eq + (i32.and + (tee_local $l10 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (tee_local $l11 + (i32.add + (i32.add + (get_local $l4) + (i32.const 32)) + (i32.load + (i32.const 748)))) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4041)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l11) + (i32.const 4095)) + (i32.const 4092))) + (then + (i32.load offset={normalised output} align=1 + (i32.xor + (i32.and + (get_local $l10) + (i32.const -4096)) + (get_local $l11)))) + (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 18))) + (call $e.safe_read32s_slow_jit + (get_local $l11)) + (if $I12 + (i32.load8_u + (i32.const 540)) + (then + (br $B3)))))) + (i32.store + (i32.const 560) (i32.add (i32.load - (i32.const 16)) - (i32.const 32)) - (i32.load - (i32.const 748)))) - (set_local $l3 - (i32.load - (i32.const 4))) - (if $I4 - (i32.and - (i32.eq - (i32.and - (tee_local $l4 - (i32.load offset=4194304 - (i32.shl - (i32.shr_u - (get_local $l2) - (i32.const 12)) - (i32.const 2)))) - (i32.const 4075)) - (i32.const 1)) - (i32.le_s - (i32.and - (get_local $l2) - (i32.const 4095)) - (i32.const 4092))) - (then - (i32.store offset={normalised output} align=1 - (i32.xor - (i32.and - (get_local $l4) - (i32.const -4096)) - (get_local $l2)) - (get_local $l3))) - (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 0))) - (call $e.safe_write32_slow_jit - (get_local $l2) - (get_local $l3)) - (if $I5 - (i32.load8_u - (i32.const 540)) - (then - (return))))) - (set_local $l3 - (i32.add + (i32.const 556)) + (i32.const 24))) + (i32.store + (i32.const 556) (i32.add (i32.load - (i32.const 12)) - (i32.const 28)) + (i32.const 556)) + (i32.const 25))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.instr_F4) + (set_local $l2 (i32.load - (i32.const 748)))) - (set_local $l2 - (i32.load - (i32.const 8))) - (if $I6 - (i32.and - (i32.eq - (i32.and - (tee_local $l4 - (i32.load offset=4194304 - (i32.shl - (i32.shr_u - (get_local $l3) - (i32.const 12)) - (i32.const 2)))) - (i32.const 4075)) - (i32.const 1)) - (i32.le_s - (i32.and - (get_local $l3) - (i32.const 4095)) - (i32.const 4092))) - (then - (i32.store offset={normalised output} align=1 - (i32.xor - (i32.and - (get_local $l4) - (i32.const -4096)) - (get_local $l3)) - (get_local $l2))) - (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 6))) - (call $e.safe_write32_slow_jit - (get_local $l3) - (get_local $l2)) - (if $I7 - (i32.load8_u - (i32.const 540)) - (then - (return))))) + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 5))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (return)) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) (i32.store (i32.const 28) - (if $I8 (result i32) - (i32.and - (i32.eq - (i32.and - (tee_local $l3 - (i32.load offset=4194304 - (i32.shl - (i32.shr_u - (tee_local $l2 - (i32.add - (i32.add - (i32.load - (i32.const 16)) - (i32.const 28)) - (i32.load - (i32.const 748)))) - (i32.const 12)) - (i32.const 2)))) - (i32.const 4041)) - (i32.const 1)) - (i32.le_s - (i32.and - (get_local $l2) - (i32.const 4095)) - (i32.const 4092))) - (then - (i32.load offset={normalised output} align=1 - (i32.xor - (i32.and - (get_local $l3) - (i32.const -4096)) - (get_local $l2)))) - (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 12))) - (call $e.safe_read32s_slow_jit - (get_local $l2)) - (if $I9 - (i32.load8_u - (i32.const 540)) - (then - (return)))))) + (get_local $l8)) (i32.store (i32.const 32) - (if $I10 (result i32) - (i32.and - (i32.eq - (i32.and - (tee_local $l2 - (i32.load offset=4194304 - (i32.shl - (i32.shr_u - (tee_local $l3 - (i32.add - (i32.add - (i32.load - (i32.const 12)) - (i32.const 32)) - (i32.load - (i32.const 748)))) - (i32.const 12)) - (i32.const 2)))) - (i32.const 4041)) - (i32.const 1)) - (i32.le_s - (i32.and - (get_local $l3) - (i32.const 4095)) - (i32.const 4092))) - (then - (i32.load offset={normalised output} align=1 - (i32.xor - (i32.and - (get_local $l2) - (i32.const -4096)) - (get_local $l3)))) - (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 18))) - (call $e.safe_read32s_slow_jit - (get_local $l3)) - (if $I11 - (i32.load8_u - (i32.const 540)) - (then - (return)))))) + (get_local $l9)) + (call $e.trigger_pagefault_end_jit) (i32.store - (i32.const 560) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 24))) - (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 25))) - (call $e.instr_F4) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 5))) + (i32.const 648) + (i32.const 0)) (return)) (unreachable)))) diff --git a/tests/expect/tests/mov32-reg.wast b/tests/expect/tests/mov32-reg.wast index 6439a1e5..30ac8ccc 100644 --- a/tests/expect/tests/mov32-reg.wast +++ b/tests/expect/tests/mov32-reg.wast @@ -16,13 +16,38 @@ (type $t14 (func (param i32 i32 i32) (result i32))) (type $t15 (func (param i32 i64 i64))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) + (import "e" "trigger_pagefault_end_jit" (func $e.trigger_pagefault_end_jit (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (set_local $l0 (get_local $p0)) (set_local $l1 (i32.const 10000)) + (set_local $l2 + (i32.load + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) (loop $L0 (set_local $l1 (i32.add @@ -32,57 +57,171 @@ (i32.eqz (get_local $l1)) (then + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) (return))) (block $B2 (block $B3 - (br_table $B3 $B2 - (get_local $l0))) + (block $B4 + (br_table $B4 $B3 $B2 + (get_local $l0))) + (set_local $l2 + (i32.const -889270259)) + (set_local $l3 + (i32.const -1091583778)) + (set_local $l4 + (i32.const 0)) + (set_local $l5 + (i32.const 0)) + (set_local $l3 + (get_local $l8)) + (set_local $l4 + (get_local $l9)) + (set_local $l4 + (get_local $l2)) + (set_local $l2 + (get_local $l3)) + (i32.store + (i32.const 560) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 28))) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 29))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.instr_F4) + (set_local $l2 + (i32.load + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 9))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (return)) (i32.store (i32.const 4) - (i32.const -889270259)) + (get_local $l2)) (i32.store (i32.const 8) - (i32.const -1091583778)) + (get_local $l3)) (i32.store (i32.const 12) - (i32.const 0)) + (get_local $l4)) (i32.store (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.trigger_pagefault_end_jit) + (i32.store + (i32.const 648) (i32.const 0)) - (i32.store - (i32.const 8) - (i32.load - (i32.const 28))) - (i32.store - (i32.const 12) - (i32.load - (i32.const 32))) - (i32.store - (i32.const 12) - (i32.load - (i32.const 4))) - (i32.store - (i32.const 4) - (i32.load - (i32.const 8))) - (i32.store - (i32.const 560) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 28))) - (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 29))) - (call $e.instr_F4) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 9))) (return)) (unreachable)))) diff --git a/tests/expect/tests/pop.wast b/tests/expect/tests/pop.wast index 9ea5b717..bf17df2d 100644 --- a/tests/expect/tests/pop.wast +++ b/tests/expect/tests/pop.wast @@ -17,13 +17,38 @@ (type $t15 (func (param i32 i64 i64))) (import "e" "safe_read32s_slow_jit" (func $e.safe_read32s_slow_jit (type $t5))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) + (import "e" "trigger_pagefault_end_jit" (func $e.trigger_pagefault_end_jit (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (local $l10 i32) (local $l11 i32) (set_local $l0 (get_local $p0)) (set_local $l1 (i32.const 10000)) + (set_local $l2 + (i32.load + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) (loop $L0 (set_local $l1 (i32.add @@ -33,83 +58,205 @@ (i32.eqz (get_local $l1)) (then + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) (return))) (block $B2 (block $B3 - (br_table $B3 $B2 - (get_local $l0))) - (i32.const 4) - (if $I4 (result i32) - (i32.and - (i32.eq - (i32.and - (tee_local $l4 - (i32.load offset=4194304 - (i32.shl - (i32.shr_u - (tee_local $l3 - (i32.add - (tee_local $l2 + (block $B4 + (br_table $B4 $B3 $B2 + (get_local $l0))) + (if $I5 (result i32) + (i32.and + (i32.eq + (i32.and + (tee_local $l11 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (tee_local $l10 + (i32.add + (get_local $l6) (i32.load - (i32.const 20))) - (i32.load - (i32.const 744)))) - (i32.const 12)) - (i32.const 2)))) - (i32.const 4041)) - (i32.const 1)) - (i32.le_s - (i32.and - (get_local $l3) - (i32.const 4095)) - (i32.const 4092))) - (then - (i32.load offset={normalised output} align=1 - (i32.xor + (i32.const 744)))) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4041)) + (i32.const 1)) + (i32.le_s (i32.and - (get_local $l4) - (i32.const -4096)) - (get_local $l3)))) - (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 0))) - (call $e.safe_read32s_slow_jit - (get_local $l3)) - (if $I5 - (i32.load8_u - (i32.const 540)) - (then - (return))))) + (get_local $l10) + (i32.const 4095)) + (i32.const 4092))) + (then + (i32.load offset={normalised output} align=1 + (i32.xor + (i32.and + (get_local $l11) + (i32.const -4096)) + (get_local $l10)))) + (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 0))) + (call $e.safe_read32s_slow_jit + (get_local $l10)) + (if $I6 + (i32.load8_u + (i32.const 540)) + (then + (br $B3))))) + (set_local $l6 + (i32.add + (get_local $l6) + (i32.const 4))) + (set_local $l2) + (i32.store + (i32.const 560) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 1))) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 2))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.instr_F4) + (set_local $l2 + (i32.load + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 2))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (return)) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) (i32.store (i32.const 20) - (i32.add - (get_local $l2) - (i32.const 4))) - (i32.store) + (get_local $l6)) (i32.store - (i32.const 560) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 1))) + (i32.const 24) + (get_local $l7)) (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 2))) - (call $e.instr_F4) + (i32.const 28) + (get_local $l8)) (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 2))) + (i32.const 32) + (get_local $l9)) + (call $e.trigger_pagefault_end_jit) + (i32.store + (i32.const 648) + (i32.const 0)) (return)) (unreachable)))) diff --git a/tests/expect/tests/push.wast b/tests/expect/tests/push.wast index 04d09f4b..b22e8acc 100644 --- a/tests/expect/tests/push.wast +++ b/tests/expect/tests/push.wast @@ -17,13 +17,38 @@ (type $t15 (func (param i32 i64 i64))) (import "e" "safe_write32_slow_jit" (func $e.safe_write32_slow_jit (type $t2))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) + (import "e" "trigger_pagefault_end_jit" (func $e.trigger_pagefault_end_jit (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (local $l10 i32) (local $l11 i32) (local $l12 i32) (local $l13 i32) (set_local $l0 (get_local $p0)) (set_local $l1 (i32.const 10000)) + (set_local $l2 + (i32.load + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) (loop $L0 (set_local $l1 (i32.add @@ -33,87 +58,210 @@ (i32.eqz (get_local $l1)) (then + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) (return))) (block $B2 (block $B3 - (br_table $B3 $B2 - (get_local $l0))) - (set_local $l2 - (i32.load - (i32.const 4))) - (set_local $l4 - (i32.add - (tee_local $l3 - (i32.sub - (i32.load - (i32.const 20)) - (i32.const 4))) + (block $B4 + (br_table $B4 $B3 $B2 + (get_local $l0))) + (set_local $l10 + (get_local $l2)) + (set_local $l12 + (i32.add + (tee_local $l11 + (i32.sub + (get_local $l6) + (i32.const 4))) + (i32.load + (i32.const 744)))) + (if $I5 + (i32.and + (i32.eq + (i32.and + (tee_local $l13 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (get_local $l12) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4075)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l12) + (i32.const 4095)) + (i32.const 4092))) + (then + (i32.store offset={normalised output} align=1 + (i32.xor + (i32.and + (get_local $l13) + (i32.const -4096)) + (get_local $l12)) + (get_local $l10))) + (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 0))) + (call $e.safe_write32_slow_jit + (get_local $l12) + (get_local $l10)) + (if $I6 + (i32.load8_u + (i32.const 540)) + (then + (br $B3))))) + (set_local $l6 + (get_local $l11)) + (i32.store + (i32.const 560) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 1))) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 2))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.instr_F4) + (set_local $l2 (i32.load - (i32.const 744)))) - (if $I4 - (i32.and - (i32.eq - (i32.and - (tee_local $l5 - (i32.load offset=4194304 - (i32.shl - (i32.shr_u - (get_local $l4) - (i32.const 12)) - (i32.const 2)))) - (i32.const 4075)) - (i32.const 1)) - (i32.le_s - (i32.and - (get_local $l4) - (i32.const 4095)) - (i32.const 4092))) - (then - (i32.store offset={normalised output} align=1 - (i32.xor - (i32.and - (get_local $l5) - (i32.const -4096)) - (get_local $l4)) - (get_local $l2))) - (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 0))) - (call $e.safe_write32_slow_jit - (get_local $l4) - (get_local $l2)) - (if $I5 - (i32.load8_u - (i32.const 540)) - (then - (return))))) + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 2))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (return)) (i32.store - (i32.const 20) + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) (get_local $l3)) (i32.store - (i32.const 560) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 1))) + (i32.const 12) + (get_local $l4)) (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 2))) - (call $e.instr_F4) + (i32.const 16) + (get_local $l5)) (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 2))) + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.trigger_pagefault_end_jit) + (i32.store + (i32.const 648) + (i32.const 0)) (return)) (unreachable)))) diff --git a/tests/expect/tests/task_switch_test.wast b/tests/expect/tests/task_switch_test.wast index 69c252cc..a15402eb 100644 --- a/tests/expect/tests/task_switch_test.wast +++ b/tests/expect/tests/task_switch_test.wast @@ -20,13 +20,38 @@ (import "e" "fpu_fadd" (func $e.fpu_fadd (type $t8))) (import "e" "fpu_pop" (func $e.fpu_pop (type $t0))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) + (import "e" "trigger_pagefault_end_jit" (func $e.trigger_pagefault_end_jit (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (set_local $l0 (get_local $p0)) (set_local $l1 (i32.const 10000)) + (set_local $l2 + (i32.load + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) (loop $L0 (set_local $l1 (i32.add @@ -36,42 +61,195 @@ (i32.eqz (get_local $l1)) (then + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) (return))) (block $B2 (block $B3 - (br_table $B3 $B2 - (get_local $l0))) - (if $I4 - (i32.and + (block $B4 + (br_table $B4 $B3 $B2 + (get_local $l0))) + (if $I5 + (i32.and + (i32.load + (i32.const 580)) + (i32.const 12)) + (then + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.task_switch_test_void) + (i32.store + (i32.const 648) + (i32.const 0)) + (return))) + (call $e.fpu_fadd + (i32.const 1) + (call $e.fpu_get_sti + (i32.const 1))) + (call $e.fpu_pop) + (i32.store + (i32.const 560) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 2))) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 3))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.instr_F4) + (set_local $l2 (i32.load - (i32.const 580)) - (i32.const 12)) - (then - (call $e.task_switch_test_void) - (return))) - (call $e.fpu_fadd - (i32.const 1) - (call $e.fpu_get_sti - (i32.const 1))) - (call $e.fpu_pop) + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 2))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (return)) (i32.store - (i32.const 560) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 2))) + (i32.const 4) + (get_local $l2)) (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 3))) - (call $e.instr_F4) + (i32.const 8) + (get_local $l3)) (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 2))) + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.trigger_pagefault_end_jit) + (i32.store + (i32.const 648) + (i32.const 0)) (return)) (unreachable)))) diff --git a/tests/expect/tests/task_switch_test_sse.wast b/tests/expect/tests/task_switch_test_sse.wast index 99c93f9b..77c9995e 100644 --- a/tests/expect/tests/task_switch_test_sse.wast +++ b/tests/expect/tests/task_switch_test_sse.wast @@ -18,13 +18,38 @@ (import "e" "task_switch_test_mmx_void" (func $e.task_switch_test_mmx_void (type $t0))) (import "e" "instr_660F54_reg" (func $e.instr_660F54_reg (type $t2))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) + (import "e" "trigger_pagefault_end_jit" (func $e.trigger_pagefault_end_jit (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (set_local $l0 (get_local $p0)) (set_local $l1 (i32.const 10000)) + (set_local $l2 + (i32.load + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) (loop $L0 (set_local $l1 (i32.add @@ -34,12 +59,173 @@ (i32.eqz (get_local $l1)) (then + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) (return))) (block $B2 (block $B3 (block $B4 - (br_table $B4 $B3 $B2 - (get_local $l0))) + (block $B5 + (br_table $B5 $B4 $B3 $B2 + (get_local $l0))) + (i32.store + (i32.const 560) + (i32.load + (i32.const 556))) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 4))) + (i32.store + (i32.const 648) + (i32.or + (i32.load + (i32.const 648)) + (i32.const 32))) + (if $I6 + (i32.and + (i32.load + (i32.const 580)) + (i32.const 12)) + (then + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.task_switch_test_mmx_void) + (i32.store + (i32.const 648) + (i32.const 0)) + (return))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.instr_660F54_reg + (i32.const 1) + (i32.const 0)) + (set_local $l2 + (i32.load + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) + (i32.store + (i32.const 648) + (i32.const 0)) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (return)) (i32.store (i32.const 560) (i32.load @@ -49,50 +235,114 @@ (i32.add (i32.load (i32.const 556)) + (i32.const 1))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.instr_F4) + (set_local $l2 + (i32.load (i32.const 4))) - (i32.store - (i32.const 648) - (i32.or - (i32.load - (i32.const 648)) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load (i32.const 32))) - (if $I5 - (i32.and - (i32.load - (i32.const 580)) - (i32.const 12)) - (then - (call $e.task_switch_test_mmx_void) - (return))) - (call $e.instr_660F54_reg - (i32.const 1) - (i32.const 0)) - (i32.store - (i32.const 648) - (i32.const 0)) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 1))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) (return)) (i32.store - (i32.const 560) - (i32.load - (i32.const 556))) + (i32.const 4) + (get_local $l2)) (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 1))) - (call $e.instr_F4) + (i32.const 8) + (get_local $l3)) (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 1))) + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.trigger_pagefault_end_jit) + (i32.store + (i32.const 648) + (i32.const 0)) (return)) (unreachable)))) diff --git a/tests/expect/tests/while-do.wast b/tests/expect/tests/while-do.wast index 109ca72a..88ab125c 100644 --- a/tests/expect/tests/while-do.wast +++ b/tests/expect/tests/while-do.wast @@ -17,15 +17,40 @@ (type $t15 (func (param i32 i64 i64))) (import "e" "cmp32" (func $e.cmp32 (type $t2))) (import "e" "test_z" (func $e.test_z (type $t4))) - (import "e" "instr32_43" (func $e.instr32_43 (type $t0))) + (import "e" "inc32" (func $e.inc32 (type $t5))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) + (import "e" "trigger_pagefault_end_jit" (func $e.trigger_pagefault_end_jit (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (set_local $l0 (get_local $p0)) (set_local $l1 (i32.const 10000)) + (set_local $l2 + (i32.load + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) (loop $L0 (set_local $l1 (i32.add @@ -35,19 +60,85 @@ (i32.eqz (get_local $l1)) (then + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) (return))) (block $B2 (block $B3 (block $B4 (block $B5 - (br_table $B5 $B4 $B3 $B2 - (get_local $l0))) - (call $e.cmp32 - (i32.load - (i32.const 4)) - (i32.const 10)) + (block $B6 + (br_table $B6 $B5 $B4 $B3 $B2 + (get_local $l0))) + (call $e.cmp32 + (get_local $l2) + (i32.const 10)) + (i32.store + (i32.const 560) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 3))) + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 5))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 2))) + (if $I7 + (call $e.test_z) + (then + (i32.store + (i32.const 556) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 3))) + (set_local $l0 + (i32.const 2))) + (else + (set_local $l0 + (i32.const 1)))) + (br $L0)) + (set_local $l5 + (call $e.inc32 + (get_local $l5))) (i32.store (i32.const 560) + (i32.add + (i32.load + (i32.const 556)) + (i32.const 1))) + (i32.store + (i32.const 556) (i32.add (i32.load (i32.const 556)) @@ -57,72 +148,133 @@ (i32.add (i32.load (i32.const 556)) - (i32.const 5))) + (i32.const -8))) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) (i32.const 2))) - (if $I6 - (call $e.test_z) - (then - (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 3))) - (set_local $l0 - (i32.const 2))) - (else - (set_local $l0 - (i32.const 1)))) + (set_local $l0 + (i32.const 0)) (br $L0)) - (call $e.instr32_43) (i32.store (i32.const 560) + (i32.load + (i32.const 556))) + (i32.store + (i32.const 556) (i32.add (i32.load (i32.const 556)) (i32.const 1))) (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 3))) + (i32.const 4) + (get_local $l2)) (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const -8))) + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.instr_F4) + (set_local $l2 + (i32.load + (i32.const 4))) + (set_local $l3 + (i32.load + (i32.const 8))) + (set_local $l4 + (i32.load + (i32.const 12))) + (set_local $l5 + (i32.load + (i32.const 16))) + (set_local $l6 + (i32.load + (i32.const 20))) + (set_local $l7 + (i32.load + (i32.const 24))) + (set_local $l8 + (i32.load + (i32.const 28))) + (set_local $l9 + (i32.load + (i32.const 32))) (i32.store (i32.const 664) (i32.add (i32.load (i32.const 664)) - (i32.const 2))) - (set_local $l0 - (i32.const 0)) - (br $L0)) + (i32.const 1))) + (i32.store + (i32.const 4) + (get_local $l2)) + (i32.store + (i32.const 8) + (get_local $l3)) + (i32.store + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (return)) (i32.store - (i32.const 560) - (i32.load - (i32.const 556))) + (i32.const 4) + (get_local $l2)) (i32.store - (i32.const 556) - (i32.add - (i32.load - (i32.const 556)) - (i32.const 1))) - (call $e.instr_F4) + (i32.const 8) + (get_local $l3)) (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 1))) + (i32.const 12) + (get_local $l4)) + (i32.store + (i32.const 16) + (get_local $l5)) + (i32.store + (i32.const 20) + (get_local $l6)) + (i32.store + (i32.const 24) + (get_local $l7)) + (i32.store + (i32.const 28) + (get_local $l8)) + (i32.store + (i32.const 32) + (get_local $l9)) + (call $e.trigger_pagefault_end_jit) + (i32.store + (i32.const 648) + (i32.const 0)) (return)) (unreachable)))) From c04ca292b9bd0982aaa4887f04294b7b0e6ed095 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1582/2137] Run latest rustfmt --- src/rust/cpu2/cpu.rs | 43 +++++++++++++------------ src/rust/cpu2/instructions.rs | 59 +++++++++++++++++++++-------------- src/rust/cpu2/modrm.rs | 39 ++++++++++++----------- 3 files changed, 79 insertions(+), 62 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 1318be4e..72ff5e14 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -829,13 +829,13 @@ pub unsafe fn call_interrupt_vector( let bytes_per_arg = if descriptor.is_32() { 4 } else { 2 }; let stack_space = bytes_per_arg * (5 + error_code_space + vm86_space); - let new_stack_pointer = ss_segment_descriptor.base() + if ss_segment_descriptor.is_32() - { - new_esp - stack_space - } - else { - new_esp - stack_space & 0xFFFF - }; + let new_stack_pointer = ss_segment_descriptor.base() + + if ss_segment_descriptor.is_32() { + new_esp - stack_space + } + else { + new_esp - stack_space & 0xFFFF + }; return_on_pagefault!(translate_address_system_write(new_stack_pointer)); return_on_pagefault!(translate_address_system_write( @@ -1117,12 +1117,14 @@ pub unsafe fn do_page_walk(addr: i32, for_writing: bool, user: bool) -> Result Result= *cpl as i32) as i32 - } { + if !*protected_mode + || 0 != if 0 != *flags & FLAG_VM { + (getiopl() == 3) as i32 + } + else { + (getiopl() >= *cpl as i32) as i32 + } + { *flags &= !FLAG_INTERRUPT; } - else if false && getiopl() < 3 && 0 != if 0 != *flags & FLAG_VM { - *cr.offset(4) & CR4_VME - } - else { - (*cpl as i32 == 3 && 0 != *cr.offset(4) & CR4_PVI) as i32 - } { + else if false + && getiopl() < 3 + && 0 != if 0 != *flags & FLAG_VM { + *cr.offset(4) & CR4_VME + } + else { + (*cpl as i32 == 3 && 0 != *cr.offset(4) & CR4_PVI) as i32 + } + { *flags &= !FLAG_VIF } else { @@ -3179,23 +3184,29 @@ pub unsafe fn instr_FA() { pub unsafe fn instr_FB() { // sti let old_if: i32 = *flags & FLAG_INTERRUPT; - if !*protected_mode || 0 != if 0 != *flags & FLAG_VM { - (getiopl() == 3) as i32 - } - else { - (getiopl() >= *cpl as i32) as i32 - } { + if !*protected_mode + || 0 != if 0 != *flags & FLAG_VM { + (getiopl() == 3) as i32 + } + else { + (getiopl() >= *cpl as i32) as i32 + } + { *flags |= FLAG_INTERRUPT; if old_if == 0 { handle_irqs(); } } - else if false && getiopl() < 3 && *flags & FLAG_VIP == 0 && 0 != if 0 != *flags & FLAG_VM { - *cr.offset(4) & CR4_VME - } - else { - (*cpl as i32 == 3 && 0 != *cr.offset(4) & CR4_PVI) as i32 - } { + else if false + && getiopl() < 3 + && *flags & FLAG_VIP == 0 + && 0 != if 0 != *flags & FLAG_VM { + *cr.offset(4) & CR4_VME + } + else { + (*cpl as i32 == 3 && 0 != *cr.offset(4) & CR4_PVI) as i32 + } + { *flags |= FLAG_VIF } else { diff --git a/src/rust/cpu2/modrm.rs b/src/rust/cpu2/modrm.rs index 06056d85..7d2388b3 100644 --- a/src/rust/cpu2/modrm.rs +++ b/src/rust/cpu2/modrm.rs @@ -97,12 +97,13 @@ pub unsafe fn resolve_modrm32_(modrm_byte: i32) -> OrPageFault { resolve_sib(false)? } else { - resolve_sib(true)? + if modrm_byte < 128 { - read_imm8s()? - } - else { - read_imm32s()? - } + resolve_sib(true)? + + if modrm_byte < 128 { + read_imm8s()? + } + else { + read_imm32s()? + } } } else if r as i32 == 5 { @@ -111,12 +112,13 @@ pub unsafe fn resolve_modrm32_(modrm_byte: i32) -> OrPageFault { } else { get_seg_prefix_ss( - *reg32s.offset(EBP as isize) + if modrm_byte < 128 { - read_imm8s()? - } - else { - read_imm32s()? - }, + *reg32s.offset(EBP as isize) + + if modrm_byte < 128 { + read_imm8s()? + } + else { + read_imm32s()? + }, ) } } @@ -125,12 +127,13 @@ pub unsafe fn resolve_modrm32_(modrm_byte: i32) -> OrPageFault { } else { get_seg_prefix_ds( - *reg32s.offset(r as isize) + if modrm_byte < 128 { - read_imm8s()? - } - else { - read_imm32s()? - }, + *reg32s.offset(r as isize) + + if modrm_byte < 128 { + read_imm8s()? + } + else { + read_imm32s()? + }, ) }) } From 091b2324d922058dc2949437c8474d4faa1c258f Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1583/2137] Custom codegen for 8C --- gen/x86_table.js | 2 +- src/rust/codegen.rs | 6 +++++ src/rust/global_pointers.rs | 6 +++++ src/rust/jit_instructions.rs | 47 ++++++++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 1 deletion(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 2c492187..9eab3e9d 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -176,7 +176,7 @@ const encodings = [ { opcode: 0x8A, custom: 1, e: 1, }, { opcode: 0x8B, custom: 1, os: 1, e: 1, }, - { opcode: 0x8C, block_boundary: 1, os: 1, e: 1, skip: 1, }, // mov reg, sreg: block_boundary as it can trigger #ud + { opcode: 0x8C, os: 1, e: 1, custom: 1 }, // mov reg, sreg { opcode: 0x8D, reg_ud: 1, os: 1, e: 1, custom_modrm_resolve: 1, custom: 1, }, // lea { opcode: 0x8E, block_boundary: 1, e: 1, skip: 1, }, // mov sreg { opcode: 0x8F, os: 1, e: 1, fixed_g: 0, custom_modrm_resolve: 1, custom: 1, block_boundary: 1, }, // pop r/m diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 4e2f3524..569369bd 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -166,6 +166,12 @@ pub fn gen_set_reg32(ctx: &mut JitContext, r: u32) { .set_local(&ctx.register_locals[r as usize]); } +pub fn gen_get_sreg(ctx: &mut JitContext, r: u32) { + ctx.builder + .instruction_body + .load_aligned_u16(global_pointers::get_sreg_offset(r)); +} + /// sign-extend a byte value on the stack and leave it on the stack pub fn sign_extend_i8(builder: &mut WasmBuilder) { builder.instruction_body.const_i32(24); diff --git a/src/rust/global_pointers.rs b/src/rust/global_pointers.rs index 9f88e760..de788ad8 100644 --- a/src/rust/global_pointers.rs +++ b/src/rust/global_pointers.rs @@ -12,6 +12,7 @@ pub const PREVIOUS_IP: u32 = 560; pub const CR: u32 = 580; pub const PREFIXES: u32 = 648; pub const TIMESTAMP_COUNTER: u32 = 664; +pub const SREG: u32 = 668; pub const SEGMENT_OFFSETS: u32 = 736; pub const OPSTATS_BUFFER: u32 = 0x1000; pub const OPSTATS_BUFFER_0F: u32 = 0x1400; @@ -33,6 +34,11 @@ pub fn get_reg_xmm_high_offset(r: u32) -> u32 { REG_XMM + 16 * r + 8 } +pub fn get_sreg_offset(s: u32) -> u32 { + dbg_assert!(s < 6); + SREG + 2 * s +} + pub fn get_seg_offset(s: u32) -> u32 { dbg_assert!(s < 8); SEGMENT_OFFSETS + 4 * s diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 0c5b9bd8..e6def07c 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1713,6 +1713,53 @@ pub fn instr32_8B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_set_reg32_r(ctx, r2, r1); } +pub fn instr16_8C_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + if r >= 6 { + codegen::gen_trigger_ud(ctx); + } + else { + codegen::gen_get_sreg(ctx, r); + let value_local = ctx.builder.set_new_local(); + codegen::gen_safe_write16(ctx, &address_local, &value_local); + ctx.builder.free_local(value_local); + } + ctx.builder.free_local(address_local); +} +pub fn instr32_8C_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + if r >= 6 { + codegen::gen_trigger_ud(ctx); + } + else { + codegen::gen_get_sreg(ctx, r); + let value_local = ctx.builder.set_new_local(); + codegen::gen_safe_write32(ctx, &address_local, &value_local); + ctx.builder.free_local(value_local); + } + ctx.builder.free_local(address_local); +} +pub fn instr16_8C_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + if r2 >= 6 { + codegen::gen_trigger_ud(ctx); + } + else { + codegen::gen_get_sreg(ctx, r2); + codegen::gen_set_reg16(ctx, r1); + } +} +pub fn instr32_8C_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + if r2 >= 6 { + codegen::gen_trigger_ud(ctx); + } + else { + codegen::gen_get_sreg(ctx, r2); + codegen::gen_set_reg32(ctx, r1); + } +} + pub fn instr16_8D_mem_jit(ctx: &mut JitContext, modrm_byte: u8, reg: u32) { ctx.cpu.prefixes |= SEG_PREFIX_ZERO; codegen::gen_modrm_resolve(ctx, modrm_byte); From a9dac09ceb9e9ec7fef2a56edab2c0604e747d9b Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1584/2137] Custom codegen for xchg (91-98) --- gen/x86_table.js | 14 +++++++------- src/rust/jit_instructions.rs | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 9eab3e9d..2e9a43ec 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -182,13 +182,13 @@ const encodings = [ { opcode: 0x8F, os: 1, e: 1, fixed_g: 0, custom_modrm_resolve: 1, custom: 1, block_boundary: 1, }, // pop r/m { opcode: 0x90, custom: 1, }, - { 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: 0x91, custom: 1, os: 1, }, + { opcode: 0x92, custom: 1, os: 1, }, + { opcode: 0x93, custom: 1, os: 1, }, + { opcode: 0x94, custom: 1, os: 1, }, + { opcode: 0x95, custom: 1, os: 1, }, + { opcode: 0x96, custom: 1, os: 1, }, + { opcode: 0x97, custom: 1, os: 1, }, { opcode: 0x98, os: 1, }, { opcode: 0x99, os: 1, }, diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index e6def07c..d89624f0 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -3226,6 +3226,42 @@ pub fn instr32_0F8F_jit(_ctx: &mut JitContext, _imm: u32) {} pub fn instr_90_jit(_ctx: &mut JitContext) {} +fn gen_xchg_reg16(ctx: &mut JitContext, r: u32) { + codegen::gen_get_reg16(ctx, r); + let tmp = ctx.builder.set_new_local(); + codegen::gen_get_reg16(ctx, regs::AX); + codegen::gen_set_reg16(ctx, r); + ctx.builder.instruction_body.get_local(&tmp); + codegen::gen_set_reg16(ctx, regs::AX); + ctx.builder.free_local(tmp); +} + +fn gen_xchg_reg32(ctx: &mut JitContext, r: u32) { + codegen::gen_get_reg32(ctx, r); + let tmp = ctx.builder.set_new_local(); + codegen::gen_get_reg32(ctx, regs::EAX); + codegen::gen_set_reg32(ctx, r); + ctx.builder.instruction_body.get_local(&tmp); + codegen::gen_set_reg32(ctx, regs::EAX); + ctx.builder.free_local(tmp); +} + +pub fn instr16_91_jit(ctx: &mut JitContext) { gen_xchg_reg16(ctx, regs::CX); } +pub fn instr16_92_jit(ctx: &mut JitContext) { gen_xchg_reg16(ctx, regs::DX); } +pub fn instr16_93_jit(ctx: &mut JitContext) { gen_xchg_reg16(ctx, regs::BX); } +pub fn instr16_94_jit(ctx: &mut JitContext) { gen_xchg_reg16(ctx, regs::SP); } +pub fn instr16_95_jit(ctx: &mut JitContext) { gen_xchg_reg16(ctx, regs::BP); } +pub fn instr16_96_jit(ctx: &mut JitContext) { gen_xchg_reg16(ctx, regs::SI); } +pub fn instr16_97_jit(ctx: &mut JitContext) { gen_xchg_reg16(ctx, regs::DI); } + +pub fn instr32_91_jit(ctx: &mut JitContext) { gen_xchg_reg32(ctx, regs::CX); } +pub fn instr32_92_jit(ctx: &mut JitContext) { gen_xchg_reg32(ctx, regs::DX); } +pub fn instr32_93_jit(ctx: &mut JitContext) { gen_xchg_reg32(ctx, regs::BX); } +pub fn instr32_94_jit(ctx: &mut JitContext) { gen_xchg_reg32(ctx, regs::SP); } +pub fn instr32_95_jit(ctx: &mut JitContext) { gen_xchg_reg32(ctx, regs::BP); } +pub fn instr32_96_jit(ctx: &mut JitContext) { gen_xchg_reg32(ctx, regs::SI); } +pub fn instr32_97_jit(ctx: &mut JitContext) { gen_xchg_reg32(ctx, regs::DI); } + pub fn instr_A0_jit(ctx: &mut JitContext, immaddr: u32) { ctx.builder.instruction_body.const_i32(immaddr as i32); jit_add_seg_offset(ctx, regs::DS); From b240a8fde901091a9c4a20d96df013c71b601304 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1585/2137] Custom codegen for push sreg (06/0E/16/1E/0FA0/0FA8) --- gen/x86_table.js | 14 +++---- src/rust/jit_instructions.rs | 77 ++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 8 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 2e9a43ec..acc28b3d 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -86,13 +86,13 @@ const encodings = [ { opcode: 0x3A, custom: 1, e: 1, }, { opcode: 0x3B, custom: 1, os: 1, e: 1, }, - { opcode: 0x06, os: 1, skip: 1, }, + { opcode: 0x06, os: 1, custom: 1 }, { opcode: 0x07, os: 1, skip: 1, block_boundary: 1, }, // pop es: block_boundary since it uses non-raising cpu exceptions - { opcode: 0x0E, os: 1, skip: 1, }, + { opcode: 0x0E, os: 1, custom: 1 }, { opcode: 0x0F, os: 1, prefix: 1, }, - { opcode: 0x16, os: 1, skip: 1, }, + { opcode: 0x16, os: 1, custom: 1 }, { opcode: 0x17, block_boundary: 1, os: 1, skip: 1, }, // pop ss - { opcode: 0x1E, os: 1, skip: 1, }, + { opcode: 0x1E, os: 1, custom: 1 }, { opcode: 0x1F, block_boundary: 1, os: 1, skip: 1, }, // pop ds { opcode: 0x26, prefix: 1, }, { opcode: 0x27, mask_flags: of, }, @@ -537,14 +537,12 @@ const encodings = [ { opcode: 0x0F9E, e: 1, custom: 1, }, { opcode: 0x0F9F, e: 1, custom: 1, }, - // XXX: Temporary block boundary - { opcode: 0x0FA0, os: 1, skip: 1, block_boundary: 1, }, + { opcode: 0x0FA0, os: 1, custom: 1, }, { opcode: 0x0FA1, os: 1, block_boundary: 1, skip: 1, }, // pop fs: block_boundary since it uses non-raising cpu exceptions { opcode: 0x0FA2, skip: 1, }, - // XXX: Temporary block boundary - { opcode: 0x0FA8, os: 1, skip: 1, block_boundary: 1, }, + { opcode: 0x0FA8, os: 1, custom: 1, }, { opcode: 0x0FA9, os: 1, block_boundary: 1, skip: 1, }, // pop gs { opcode: 0x0FA3, os: 1, e: 1, only_reg: 1, }, // bt (can also index memory, but not supported by test right now) diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index d89624f0..6c409e80 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1196,6 +1196,58 @@ fn gen_dec32(ctx: &mut JitContext, r: u32) { codegen::gen_set_reg32(ctx, r); } +pub fn instr16_06_jit(ctx: &mut JitContext) { + codegen::gen_get_sreg(ctx, regs::ES); + let sreg = ctx.builder.set_new_local(); + codegen::gen_push16(ctx, &sreg); + ctx.builder.free_local(sreg); +} +pub fn instr32_06_jit(ctx: &mut JitContext) { + codegen::gen_get_sreg(ctx, regs::ES); + let sreg = ctx.builder.set_new_local(); + codegen::gen_push32(ctx, &sreg); + ctx.builder.free_local(sreg); +} + +pub fn instr16_0E_jit(ctx: &mut JitContext) { + codegen::gen_get_sreg(ctx, regs::CS); + let sreg = ctx.builder.set_new_local(); + codegen::gen_push16(ctx, &sreg); + ctx.builder.free_local(sreg); +} +pub fn instr32_0E_jit(ctx: &mut JitContext) { + codegen::gen_get_sreg(ctx, regs::CS); + let sreg = ctx.builder.set_new_local(); + codegen::gen_push32(ctx, &sreg); + ctx.builder.free_local(sreg); +} + +pub fn instr16_16_jit(ctx: &mut JitContext) { + codegen::gen_get_sreg(ctx, regs::SS); + let sreg = ctx.builder.set_new_local(); + codegen::gen_push16(ctx, &sreg); + ctx.builder.free_local(sreg); +} +pub fn instr32_16_jit(ctx: &mut JitContext) { + codegen::gen_get_sreg(ctx, regs::SS); + let sreg = ctx.builder.set_new_local(); + codegen::gen_push32(ctx, &sreg); + ctx.builder.free_local(sreg); +} + +pub fn instr16_1E_jit(ctx: &mut JitContext) { + codegen::gen_get_sreg(ctx, regs::DS); + let sreg = ctx.builder.set_new_local(); + codegen::gen_push16(ctx, &sreg); + ctx.builder.free_local(sreg); +} +pub fn instr32_1E_jit(ctx: &mut JitContext) { + codegen::gen_get_sreg(ctx, regs::DS); + let sreg = ctx.builder.set_new_local(); + codegen::gen_push32(ctx, &sreg); + ctx.builder.free_local(sreg); +} + pub fn instr16_40_jit(ctx: &mut JitContext) { gen_inc16(ctx, AX); } pub fn instr32_40_jit(ctx: &mut JitContext) { gen_inc32(ctx, EAX); } pub fn instr16_41_jit(ctx: &mut JitContext) { gen_inc16(ctx, CX); } @@ -3815,3 +3867,28 @@ pub fn instr_F30F7F_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { pub fn instr_F30F7F_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { instr_0F29_reg_jit(ctx, r1, r2) } + +pub fn instr16_0FA0_jit(ctx: &mut JitContext) { + codegen::gen_get_sreg(ctx, regs::FS); + let sreg = ctx.builder.set_new_local(); + codegen::gen_push16(ctx, &sreg); + ctx.builder.free_local(sreg); +} +pub fn instr32_0FA0_jit(ctx: &mut JitContext) { + codegen::gen_get_sreg(ctx, regs::FS); + let sreg = ctx.builder.set_new_local(); + codegen::gen_push32(ctx, &sreg); + ctx.builder.free_local(sreg); +} +pub fn instr16_0FA8_jit(ctx: &mut JitContext) { + codegen::gen_get_sreg(ctx, regs::GS); + let sreg = ctx.builder.set_new_local(); + codegen::gen_push16(ctx, &sreg); + ctx.builder.free_local(sreg); +} +pub fn instr32_0FA8_jit(ctx: &mut JitContext) { + codegen::gen_get_sreg(ctx, regs::GS); + let sreg = ctx.builder.set_new_local(); + codegen::gen_push32(ctx, &sreg); + ctx.builder.free_local(sreg); +} From fb7e4d376a18b13360cdbe159a85f86cf36ecf85 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1586/2137] Custom codegen for lfence (0FAE_5) --- gen/x86_table.js | 2 +- src/rust/jit_instructions.rs | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index acc28b3d..814af08a 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -575,7 +575,7 @@ const encodings = [ { opcode: 0x0FAE, e: 1, fixed_g: 3, reg_ud: 1, sse: 1, skip: 1, block_boundary: 1, }, // stmxcsr { opcode: 0x0FAE, e: 1, fixed_g: 4, reg_ud: 1, skip: 1, block_boundary: 1, }, // xsave (mem, not implemented) - { opcode: 0x0FAE, e: 1, fixed_g: 5, skip: 1, block_boundary: 1, }, // lfence (reg, only 0), xrstor (mem, not implemented) + { opcode: 0x0FAE, e: 1, fixed_g: 5, skip: 1, block_boundary: 1, custom: 1 }, // lfence (reg, only 0), xrstor (mem, not implemented) { opcode: 0x0FAE, e: 1, fixed_g: 6, skip: 1, block_boundary: 1, }, // mfence (reg, only 0), xsaveopt (mem, not implemented) { opcode: 0x0FAE, e: 1, fixed_g: 7, skip: 1, block_boundary: 1, }, // sfence (reg, only 0), clflush (mem) diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 6c409e80..9bd70876 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -3892,3 +3892,11 @@ pub fn instr32_0FA8_jit(ctx: &mut JitContext) { codegen::gen_push32(ctx, &sreg); ctx.builder.free_local(sreg); } + +pub fn instr_0FAE_5_mem_jit(ctx: &mut JitContext, _modrm_byte: u8) { + dbg_log!("Generating #ud for unimplemented instruction: instr_0FAE_5_mem_jit"); + codegen::gen_trigger_ud(ctx); +} +pub fn instr_0FAE_5_reg_jit(_ctx: &mut JitContext, r: u32) { + dbg_assert!(r == 0, "Unexpected lfence encoding"); +} From b5a72061fbcb314bb378f5da313988cbf059b5c1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1587/2137] Custom codegen for absolute jmp/call (FF_2/FF_4) --- gen/x86_table.js | 4 +- src/rust/codegen.rs | 15 +++ src/rust/jit_instructions.rs | 86 ++++++++++++++ tests/expect/tests/indirect-call.wast | 163 ++++++++++++++++++-------- 4 files changed, 214 insertions(+), 54 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 814af08a..23df4be6 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -408,9 +408,9 @@ const encodings = [ { opcode: 0xFE, e: 1, fixed_g: 1, }, { opcode: 0xFF, os: 1, e: 1, fixed_g: 0, custom: 1, }, { opcode: 0xFF, os: 1, e: 1, fixed_g: 1, custom: 1, }, - { opcode: 0xFF, os: 1, e: 1, fixed_g: 2, block_boundary: 1, skip: 1, }, + { opcode: 0xFF, os: 1, e: 1, fixed_g: 2, custom: 1, block_boundary: 1, skip: 1, }, { opcode: 0xFF, os: 1, e: 1, fixed_g: 3, block_boundary: 1, skip: 1, }, - { opcode: 0xFF, os: 1, e: 1, fixed_g: 4, block_boundary: 1, no_next_instruction: 1, skip: 1, }, + { opcode: 0xFF, os: 1, e: 1, fixed_g: 4, custom: 1, block_boundary: 1, no_next_instruction: 1, skip: 1, }, { opcode: 0xFF, os: 1, e: 1, fixed_g: 5, block_boundary: 1, no_next_instruction: 1, skip: 1, }, { opcode: 0xFF, custom: 1, os: 1, e: 1, fixed_g: 6, }, diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 569369bd..030631c3 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -19,6 +19,13 @@ const CONDITION_FUNCTIONS: [&str; 16] = [ "test_ns", "test_p", "test_np", "test_l", "test_nl", "test_le", "test_nle", ]; +pub fn gen_add_cs_offset(ctx: &mut JitContext) { + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_seg_offset(regs::CS)); + ctx.builder.instruction_body.add_i32(); +} + pub fn gen_set_previous_eip_offset_from_eip(builder: &mut WasmBuilder, n: u32) { let cs = &mut builder.instruction_body; cs.const_i32(global_pointers::PREVIOUS_IP as i32); // store address of previous ip @@ -52,6 +59,14 @@ pub fn gen_relative_jump(builder: &mut WasmBuilder, n: i32) { instruction_body.store_aligned_i32(0); } +pub fn gen_set_eip(ctx: &mut JitContext, from: &WasmLocal) { + ctx.builder + .instruction_body + .const_i32(global_pointers::INSTRUCTION_POINTER as i32); + ctx.builder.instruction_body.get_local(&from); + ctx.builder.instruction_body.store_aligned_i32(0); +} + pub fn gen_increment_variable(builder: &mut WasmBuilder, variable_address: u32, n: i32) { builder .instruction_body diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 9bd70876..c0ba5984 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -3233,6 +3233,92 @@ define_instruction_read_write_mem32!( none ); +pub fn instr16_FF_2_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read16(ctx); + codegen::gen_add_cs_offset(ctx); + let new_eip = ctx.builder.set_new_local(); + + codegen::gen_get_real_eip(ctx); + let value_local = ctx.builder.set_new_local(); + codegen::gen_push16(ctx, &value_local); + ctx.builder.free_local(value_local); + + codegen::gen_set_eip(ctx, &new_eip); + ctx.builder.free_local(new_eip); +} +pub fn instr16_FF_2_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_get_reg16(ctx, r); + codegen::gen_add_cs_offset(ctx); + let new_eip = ctx.builder.set_new_local(); + + codegen::gen_get_real_eip(ctx); + let value_local = ctx.builder.set_new_local(); + codegen::gen_push16(ctx, &value_local); + ctx.builder.free_local(value_local); + + codegen::gen_set_eip(ctx, &new_eip); + ctx.builder.free_local(new_eip); +} +pub fn instr32_FF_2_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read32(ctx); + codegen::gen_add_cs_offset(ctx); + let new_eip = ctx.builder.set_new_local(); + + codegen::gen_get_real_eip(ctx); + let value_local = ctx.builder.set_new_local(); + codegen::gen_push32(ctx, &value_local); + ctx.builder.free_local(value_local); + + codegen::gen_set_eip(ctx, &new_eip); + ctx.builder.free_local(new_eip); +} +pub fn instr32_FF_2_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_get_reg32(ctx, r); + codegen::gen_add_cs_offset(ctx); + let new_eip = ctx.builder.set_new_local(); + + codegen::gen_get_real_eip(ctx); + let value_local = ctx.builder.set_new_local(); + codegen::gen_push32(ctx, &value_local); + ctx.builder.free_local(value_local); + + codegen::gen_set_eip(ctx, &new_eip); + ctx.builder.free_local(new_eip); +} + +pub fn instr16_FF_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read16(ctx); + codegen::gen_add_cs_offset(ctx); + let new_eip = ctx.builder.set_new_local(); + codegen::gen_set_eip(ctx, &new_eip); + ctx.builder.free_local(new_eip); +} +pub fn instr16_FF_4_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_get_reg16(ctx, r); + codegen::gen_add_cs_offset(ctx); + let new_eip = ctx.builder.set_new_local(); + codegen::gen_set_eip(ctx, &new_eip); + ctx.builder.free_local(new_eip); +} +pub fn instr32_FF_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read32(ctx); + codegen::gen_add_cs_offset(ctx); + let new_eip = ctx.builder.set_new_local(); + codegen::gen_set_eip(ctx, &new_eip); + ctx.builder.free_local(new_eip); +} +pub fn instr32_FF_4_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_get_reg32(ctx, r); + codegen::gen_add_cs_offset(ctx); + let new_eip = ctx.builder.set_new_local(); + codegen::gen_set_eip(ctx, &new_eip); + ctx.builder.free_local(new_eip); +} + pub fn instr16_FF_6_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { push16_mem_jit(ctx, modrm_byte) } diff --git a/tests/expect/tests/indirect-call.wast b/tests/expect/tests/indirect-call.wast index 5570057d..db8901c9 100644 --- a/tests/expect/tests/indirect-call.wast +++ b/tests/expect/tests/indirect-call.wast @@ -15,12 +15,13 @@ (type $t13 (func (param f64) (result i64))) (type $t14 (func (param i32 i32 i32) (result i32))) (type $t15 (func (param i32 i64 i64))) - (import "e" "instr32_FF_2_mem" (func $e.instr32_FF_2_mem (type $t1))) + (import "e" "safe_read32s_slow_jit" (func $e.safe_read32s_slow_jit (type $t5))) + (import "e" "safe_write32_slow_jit" (func $e.safe_write32_slow_jit (type $t2))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "trigger_pagefault_end_jit" (func $e.trigger_pagefault_end_jit (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (local $l10 i32) (local $l11 i32) (local $l12 i32) (local $l13 i32) (local $l14 i32) (set_local $l0 (get_local $p0)) (set_local $l1 @@ -99,59 +100,117 @@ (i32.load (i32.const 556)) (i32.const 2))) - (i32.store - (i32.const 4) - (get_local $l2)) - (i32.store - (i32.const 8) - (get_local $l3)) - (i32.store - (i32.const 12) - (get_local $l4)) - (i32.store - (i32.const 16) - (get_local $l5)) - (i32.store - (i32.const 20) - (get_local $l6)) - (i32.store - (i32.const 24) - (get_local $l7)) - (i32.store - (i32.const 28) - (get_local $l8)) - (i32.store - (i32.const 32) - (get_local $l9)) - (call $e.instr32_FF_2_mem + (set_local $l11 (i32.add - (get_local $l2) + (if $I6 (result i32) + (i32.and + (i32.eq + (i32.and + (tee_local $l11 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (tee_local $l10 + (i32.add + (get_local $l2) + (i32.load + (i32.const 748)))) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4041)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l10) + (i32.const 4095)) + (i32.const 4092))) + (then + (i32.load offset={normalised output} align=1 + (i32.xor + (i32.and + (get_local $l11) + (i32.const -4096)) + (get_local $l10)))) + (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 0))) + (call $e.safe_read32s_slow_jit + (get_local $l10)) + (if $I7 + (i32.load8_u + (i32.const 540)) + (then + (br $B3))))) (i32.load - (i32.const 748)))) - (set_local $l2 - (i32.load - (i32.const 4))) - (set_local $l3 - (i32.load - (i32.const 8))) - (set_local $l4 - (i32.load - (i32.const 12))) - (set_local $l5 - (i32.load - (i32.const 16))) + (i32.const 740)))) + (set_local $l10 + (i32.sub + (i32.load + (i32.const 556)) + (i32.load + (i32.const 740)))) + (set_local $l13 + (i32.add + (tee_local $l12 + (i32.sub + (get_local $l6) + (i32.const 4))) + (i32.load + (i32.const 744)))) + (if $I8 + (i32.and + (i32.eq + (i32.and + (tee_local $l14 + (i32.load offset=4194304 + (i32.shl + (i32.shr_u + (get_local $l13) + (i32.const 12)) + (i32.const 2)))) + (i32.const 4075)) + (i32.const 1)) + (i32.le_s + (i32.and + (get_local $l13) + (i32.const 4095)) + (i32.const 4092))) + (then + (i32.store offset={normalised output} align=1 + (i32.xor + (i32.and + (get_local $l14) + (i32.const -4096)) + (get_local $l13)) + (get_local $l10))) + (else + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 0))) + (call $e.safe_write32_slow_jit + (get_local $l13) + (get_local $l10)) + (if $I9 + (i32.load8_u + (i32.const 540)) + (then + (br $B3))))) (set_local $l6 - (i32.load - (i32.const 20))) - (set_local $l7 - (i32.load - (i32.const 24))) - (set_local $l8 - (i32.load - (i32.const 28))) - (set_local $l9 - (i32.load - (i32.const 32))) + (get_local $l12)) + (i32.store + (i32.const 556) + (get_local $l11)) (i32.store (i32.const 664) (i32.add From ff64866e2573364d0514d6337c4d2c0ab7fecff4 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1588/2137] Custom codegen for absolute cmpxchg (0FB1) --- gen/x86_table.js | 2 +- src/rust/jit_instructions.rs | 62 ++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 23df4be6..3bcc2b54 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -582,7 +582,7 @@ const encodings = [ { opcode: 0x0FAF, os: 1, e: 1, mask_flags: af | zf, custom: 1, }, // imul { opcode: 0x0FB0, e: 1 }, // cmxchg - { opcode: 0x0FB1, os: 1, e: 1 }, + { opcode: 0x0FB1, os: 1, e: 1, custom: 1 }, { opcode: 0x0FC7, e: 1, fixed_g: 1, reg_ud: 1, }, // cmpxchg8b (memory) { opcode: 0x0FC7, e: 1, fixed_g: 6, mem_ud: 1, skip: 1, }, // rdrand diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index c0ba5984..279993de 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -3561,6 +3561,68 @@ define_instruction_read_write_mem32!( cl ); +pub fn instr16_0FB1_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_get_reg16(ctx, r1); + ctx.builder.instruction_body.const_i32(r2 as i32); + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn2_ret(ctx.builder, "cmpxchg16"); + codegen::gen_move_registers_from_memory_to_locals(ctx); + codegen::gen_set_reg16(ctx, r1); +} +pub fn instr16_0FB1_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_safe_read_write( + ctx, + BitSize::WORD, + &address_local, + &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn2_ret(ctx.builder, "cmpxchg16"); + codegen::gen_move_registers_from_memory_to_locals(ctx); + }, + &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn2(ctx.builder, "instr16_0FB1_mem"); + codegen::gen_move_registers_from_memory_to_locals(ctx); + }, + ); + ctx.builder.free_local(address_local); +} + +pub fn instr32_0FB1_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_get_reg32(ctx, r1); + ctx.builder.instruction_body.const_i32(r2 as i32); + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn2_ret(ctx.builder, "cmpxchg32"); + codegen::gen_move_registers_from_memory_to_locals(ctx); + codegen::gen_set_reg32(ctx, r1); +} +pub fn instr32_0FB1_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_safe_read_write( + ctx, + BitSize::DWORD, + &address_local, + &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn2_ret(ctx.builder, "cmpxchg32"); + codegen::gen_move_registers_from_memory_to_locals(ctx); + }, + &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn2(ctx.builder, "instr32_0FB1_mem"); + codegen::gen_move_registers_from_memory_to_locals(ctx); + }, + ); + ctx.builder.free_local(address_local); +} + pub fn instr16_0FB6_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_get_reg8(ctx, r1); codegen::gen_set_reg16(ctx, r2); From 701d59e0dde02e129ec4d7034faa97ef49d64ff7 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1589/2137] Custom codegen for absolute cli (FA) --- gen/x86_table.js | 3 +-- src/rust/codegen.rs | 8 ++++++++ src/rust/cpu2/instructions.rs | 14 +++++++++++--- src/rust/jit_instructions.rs | 8 ++++++++ 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 3bcc2b54..a69db021 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -397,8 +397,7 @@ const encodings = [ { opcode: 0xF8, }, { opcode: 0xF9, }, - // cli: block_boundary since it uses non-raising cpu exceptions - { opcode: 0xFA, block_boundary: 1, skip: 1, }, + { opcode: 0xFA, custom: 1, skip: 1 }, // sti: not a jump, but can cause a change in eip { opcode: 0xFB, block_boundary: 1, skip: 1, }, { opcode: 0xFC, no_register: 1, }, diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 030631c3..62408787 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -1412,6 +1412,14 @@ pub fn gen_trigger_ud(ctx: &mut JitContext) { ctx.builder.instruction_body.return_(); } +pub fn gen_trigger_gp(ctx: &mut JitContext, error_code: u32) { + gen_move_registers_from_locals_to_memory(ctx); + gen_fn1_const(ctx.builder, "trigger_gp", error_code); + gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); + gen_clear_prefixes(ctx); + ctx.builder.instruction_body.return_(); +} + pub fn gen_condition_fn(builder: &mut WasmBuilder, condition: u8) { dbg_assert!(condition < 16); let condition_name = CONDITION_FUNCTIONS[condition as usize]; diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index 45db74a9..ff407fb0 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -3152,7 +3152,7 @@ pub unsafe fn instr_F9() { *flags_changed &= !1; } #[no_mangle] -pub unsafe fn instr_FA() { +pub unsafe fn instr_FA_without_fault() -> bool { // cli if !*protected_mode || 0 != if 0 != *flags & FLAG_VM { @@ -3163,6 +3163,7 @@ pub unsafe fn instr_FA() { } { *flags &= !FLAG_INTERRUPT; + return true; } else if false && getiopl() < 3 @@ -3173,14 +3174,21 @@ pub unsafe fn instr_FA() { (*cpl as i32 == 3 && 0 != *cr.offset(4) & CR4_PVI) as i32 } { - *flags &= !FLAG_VIF + *flags &= !FLAG_VIF; + return true; } else { dbg_log!("cli #gp"); - trigger_gp(0); + return false; }; } #[no_mangle] +pub unsafe fn instr_FA() { + if !instr_FA_without_fault() { + trigger_gp(0); + } +} +#[no_mangle] pub unsafe fn instr_FB() { // sti let old_if: i32 = *flags & FLAG_INTERRUPT; diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 279993de..3a96c07c 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -3203,6 +3203,14 @@ pub fn instr32_F7_5_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_move_registers_from_memory_to_locals(ctx); } +pub fn instr_FA_jit(ctx: &mut JitContext) { + codegen::gen_fn0_const_ret(ctx.builder, "instr_FA_without_fault"); + ctx.builder.instruction_body.eqz_i32(); + ctx.builder.instruction_body.if_void(); + codegen::gen_trigger_gp(ctx, 0); + ctx.builder.instruction_body.block_end(); +} + define_instruction_read_write_mem16!( "inc16", "instr16_FF_0_mem", From 5da6cde13ffb06b9c8e011eaa63353109209cf54 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1590/2137] Custom codegen for cbw/cwde/cwd/cdq/pushf/sahf (98/99/9C/9E) --- gen/x86_table.js | 9 ++-- src/rust/cpu2/instructions.rs | 6 ++- src/rust/jit_instructions.rs | 81 ++++++++++++++++++++++++++++++++++- 3 files changed, 88 insertions(+), 8 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index a69db021..ccadd38c 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -190,15 +190,14 @@ const encodings = [ { opcode: 0x96, custom: 1, os: 1, }, { opcode: 0x97, custom: 1, os: 1, }, - { opcode: 0x98, os: 1, }, - { opcode: 0x99, os: 1, }, + { opcode: 0x98, os: 1, custom: 1 }, + { opcode: 0x99, os: 1, custom: 1 }, { opcode: 0x9A, os: 1, imm1632: 1, extra_imm16: 1, skip: 1, block_boundary: 1, }, // callf { opcode: 0x9B, skip: 1, }, // fwait: block_boundary since it uses non-raising cpu exceptions - // pushf: block_boundary since it uses non-raising cpu exceptions - { opcode: 0x9C, os: 1, block_boundary: 1, }, + { opcode: 0x9C, os: 1, custom: 1 }, // popf: not a jump, but can cause an eip change due to updating the interrupt flag { opcode: 0x9D, os: 1, block_boundary: 1, skip: 1, }, - { opcode: 0x9E, }, + { opcode: 0x9E, custom: 1 }, { opcode: 0x9F, }, { opcode: 0xA0, custom: 1, immaddr: 1 }, diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index ff407fb0..eb4b103e 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -1696,9 +1696,11 @@ pub unsafe fn instr_9B() { }; } #[no_mangle] +pub unsafe fn instr_9C_check() -> bool { 0 != *flags & FLAG_VM && getiopl() < 3 } +#[no_mangle] pub unsafe fn instr16_9C() { // pushf - if 0 != *flags & FLAG_VM && getiopl() < 3 { + if instr_9C_check() { dbg_assert!(*protected_mode); dbg_log!("pushf #gp"); trigger_gp(0); @@ -1710,7 +1712,7 @@ pub unsafe fn instr16_9C() { #[no_mangle] pub unsafe fn instr32_9C() { // pushf - if 0 != *flags & FLAG_VM && getiopl() < 3 { + if instr_9C_check() { // trap to virtual 8086 monitor dbg_assert!(*protected_mode); dbg_log!("pushf #gp"); diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 3a96c07c..0380bb74 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -2,7 +2,7 @@ use codegen; use cpu::BitSize; -use cpu2::cpu::{FLAGS_ALL, FLAG_OVERFLOW, OPSIZE_32}; +use cpu2::cpu::{FLAGS_ALL, FLAGS_DEFAULT, FLAGS_MASK, FLAG_OVERFLOW, OPSIZE_32}; use global_pointers; use jit::JitContext; use modrm; @@ -3408,6 +3408,85 @@ pub fn instr32_95_jit(ctx: &mut JitContext) { gen_xchg_reg32(ctx, regs::BP); } pub fn instr32_96_jit(ctx: &mut JitContext) { gen_xchg_reg32(ctx, regs::SI); } pub fn instr32_97_jit(ctx: &mut JitContext) { gen_xchg_reg32(ctx, regs::DI); } +pub fn instr16_98_jit(ctx: &mut JitContext) { + codegen::gen_get_reg8(ctx, regs::AL); + codegen::sign_extend_i8(ctx.builder); + codegen::gen_set_reg16(ctx, regs::AX); +} +pub fn instr32_98_jit(ctx: &mut JitContext) { + codegen::gen_get_reg16(ctx, regs::AX); + codegen::sign_extend_i16(ctx.builder); + codegen::gen_set_reg32(ctx, regs::EAX); +} + +pub fn instr16_99_jit(ctx: &mut JitContext) { + codegen::gen_get_reg16(ctx, regs::AX); + ctx.builder.instruction_body.const_i32(16); + ctx.builder.instruction_body.shl_i32(); + ctx.builder.instruction_body.const_i32(31); + ctx.builder.instruction_body.shr_s_i32(); + codegen::gen_set_reg16(ctx, regs::DX); +} +pub fn instr32_99_jit(ctx: &mut JitContext) { + codegen::gen_get_reg32(ctx, regs::EAX); + ctx.builder.instruction_body.const_i32(31); + ctx.builder.instruction_body.shr_s_i32(); + codegen::gen_set_reg32(ctx, regs::EDX); +} + +pub fn instr16_9C_jit(ctx: &mut JitContext) { + codegen::gen_fn0_const_ret(ctx.builder, "instr_9C_check"); + ctx.builder.instruction_body.if_void(); + codegen::gen_trigger_gp(ctx, 0); + ctx.builder.instruction_body.else_(); + codegen::gen_fn0_const_ret(ctx.builder, "get_eflags"); + let value = ctx.builder.set_new_local(); + codegen::gen_push16(ctx, &value); + ctx.builder.instruction_body.block_end(); + ctx.builder.free_local(value); +} +pub fn instr32_9C_jit(ctx: &mut JitContext) { + codegen::gen_fn0_const_ret(ctx.builder, "instr_9C_check"); + ctx.builder.instruction_body.if_void(); + codegen::gen_trigger_gp(ctx, 0); + ctx.builder.instruction_body.else_(); + codegen::gen_fn0_const_ret(ctx.builder, "get_eflags"); + ctx.builder.instruction_body.const_i32(0xFCFFFF); + ctx.builder.instruction_body.and_i32(); + let value = ctx.builder.set_new_local(); + codegen::gen_push32(ctx, &value); + ctx.builder.instruction_body.block_end(); + ctx.builder.free_local(value); +} + +pub fn instr_9E_jit(ctx: &mut JitContext) { + ctx.builder + .instruction_body + .const_i32(global_pointers::FLAGS as i32); + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::FLAGS); + ctx.builder.instruction_body.const_i32(!0xFF); + ctx.builder.instruction_body.and_i32(); + codegen::gen_get_reg8(ctx, regs::AH); + ctx.builder.instruction_body.or_i32(); + ctx.builder.instruction_body.const_i32(FLAGS_MASK); + ctx.builder.instruction_body.and_i32(); + ctx.builder.instruction_body.const_i32(FLAGS_DEFAULT); + ctx.builder.instruction_body.or_i32(); + ctx.builder.instruction_body.store_aligned_i32(0); + + ctx.builder + .instruction_body + .const_i32(global_pointers::FLAGS_CHANGED as i32); + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::FLAGS_CHANGED); + ctx.builder.instruction_body.const_i32(!0xFF); + ctx.builder.instruction_body.and_i32(); + ctx.builder.instruction_body.store_aligned_i32(0); +} + pub fn instr_A0_jit(ctx: &mut JitContext, immaddr: u32) { ctx.builder.instruction_body.const_i32(immaddr as i32); jit_add_seg_offset(ctx, regs::DS); From e0473dae182acc2860af518aa95e87796e4c5051 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1591/2137] profiler: Count generated simple/complex modrm address expressions --- src/browser/print_stats.js | 2 ++ src/rust/modrm.rs | 8 ++++++++ src/rust/profiler.rs | 3 +++ 3 files changed, 13 insertions(+) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index fc04dd21..7c44c9cf 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -67,6 +67,8 @@ const print_stats = { "FULL_CLEAR_TLB", "TLB_FULL", "TLB_GLOBAL_FULL", + "MODRM_SIMPLE_REG", + "MODRM_COMPLEX", ]; for(let i = 0; i < stat_names.length; i++) diff --git a/src/rust/modrm.rs b/src/rust/modrm.rs index f5c597f1..14f349ee 100644 --- a/src/rust/modrm.rs +++ b/src/rust/modrm.rs @@ -3,6 +3,7 @@ use cpu_context::CpuContext; use global_pointers; use jit::JitContext; use prefix::{PREFIX_MASK_SEGMENT, SEG_PREFIX_ZERO}; +use profiler; use regs::{BP, BX, DI, SI}; use regs::{DS, SS}; use regs::{EAX, EBP, EBX, ECX, EDI, EDX, ESI, ESP}; @@ -199,6 +200,8 @@ fn gen32_case(ctx: &mut JitContext, seg: u32, offset: Offset, imm: Imm32) { ctx.builder.instruction_body.const_i32(immediate_value); ctx.builder.instruction_body.add_i32(); } + + profiler::stat_increment(profiler::stat::MODRM_COMPLEX); }, Offset::Reg(r) => { let immediate_value = match imm { @@ -210,10 +213,15 @@ fn gen32_case(ctx: &mut JitContext, seg: u32, offset: Offset, imm: Imm32) { if immediate_value != 0 { ctx.builder.instruction_body.const_i32(immediate_value); ctx.builder.instruction_body.add_i32(); + profiler::stat_increment(profiler::stat::MODRM_COMPLEX); + } + else { + profiler::stat_increment(profiler::stat::MODRM_SIMPLE_REG); } jit_add_seg_offset(ctx, seg); }, Offset::None => { + profiler::stat_increment(profiler::stat::MODRM_SIMPLE_REG); let immediate_value = match imm { Imm32::None => 0, Imm32::Imm8 => ctx.cpu.read_imm8s() as i32, diff --git a/src/rust/profiler.rs b/src/rust/profiler.rs index bb5d1daa..f89b8c7a 100644 --- a/src/rust/profiler.rs +++ b/src/rust/profiler.rs @@ -64,6 +64,9 @@ pub enum stat { FULL_CLEAR_TLB, TLB_FULL, TLB_GLOBAL_FULL, + + MODRM_SIMPLE_REG, + MODRM_COMPLEX, } #[no_mangle] From af5d01fff66d19ab12bc1ac836951c46c0210255 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1592/2137] Makefile: Add tests-release target --- Makefile | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Makefile b/Makefile index f6f10806..d026b0e2 100644 --- a/Makefile +++ b/Makefile @@ -240,6 +240,15 @@ tests: all-debug ./tools/copy-to-sha256.py images/integration-test-fs/fs.tar images/integration-test-fs/flat ./tests/full/run.js +tests-release: all + mkdir -p images/integration-test-fs/flat + cp images/bzImage images/integration-test-fs/ + touch images/integration-test-fs/initrd + cd images/integration-test-fs && tar cfv fs.tar bzImage initrd + ./tools/fs2json.py images/integration-test-fs/fs.tar --out images/integration-test-fs/fs.json + ./tools/copy-to-sha256.py images/integration-test-fs/fs.tar images/integration-test-fs/flat + TEST_RELEASE_BUILD=1 ./tests/full/run.js + nasmtests: all-debug $(MAKE) -C $(NASM_TEST_DIR) all $(NASM_TEST_DIR)/gen_fixtures.js From 970739f60b6cab525812e786ba399b51514a9adf Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1593/2137] Generate custom code for getzf/getcf/test_be --- src/rust/codegen.rs | 124 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 121 insertions(+), 3 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 62408787..a914066f 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -1,5 +1,7 @@ use cpu::BitSize; -use cpu2::cpu::{TLB_GLOBAL, TLB_HAS_CODE, TLB_NO_USER, TLB_READONLY, TLB_VALID}; +use cpu2::cpu::{ + FLAG_CARRY, FLAG_ZERO, TLB_GLOBAL, TLB_HAS_CODE, TLB_NO_USER, TLB_READONLY, TLB_VALID, +}; use global_pointers; use jit::JitContext; use modrm; @@ -1388,6 +1390,99 @@ pub fn gen_clear_flags_bits(builder: &mut WasmBuilder, bits_to_clear: i32) { builder.instruction_body.and_i32(); builder.instruction_body.store_aligned_i32(0); } + +pub fn gen_getzf(builder: &mut WasmBuilder) { + builder + .instruction_body + .load_aligned_i32(global_pointers::FLAGS_CHANGED); + builder.instruction_body.const_i32(FLAG_ZERO); + builder.instruction_body.and_i32(); + builder.instruction_body.if_i32(); + + builder + .instruction_body + .load_aligned_i32(global_pointers::LAST_RESULT); + let last_result = builder.tee_new_local(); + builder.instruction_body.const_i32(-1); + builder.instruction_body.xor_i32(); + builder.instruction_body.get_local(&last_result); + builder.free_local(last_result); + builder.instruction_body.const_i32(1); + builder.instruction_body.sub_i32(); + builder.instruction_body.and_i32(); + builder + .instruction_body + .load_aligned_i32(global_pointers::LAST_OP_SIZE); + builder.instruction_body.shr_u_i32(); + builder.instruction_body.const_i32(1); + builder.instruction_body.and_i32(); + + builder.instruction_body.else_(); + builder + .instruction_body + .load_aligned_i32(global_pointers::FLAGS); + builder.instruction_body.const_i32(FLAG_ZERO); + builder.instruction_body.and_i32(); + builder.instruction_body.block_end(); +} + +pub fn gen_getcf(builder: &mut WasmBuilder) { + builder + .instruction_body + .load_aligned_i32(global_pointers::FLAGS_CHANGED); + builder.instruction_body.const_i32(FLAG_CARRY); + builder.instruction_body.and_i32(); + builder.instruction_body.if_i32(); + + builder + .instruction_body + .load_aligned_i32(global_pointers::LAST_OP1); + let last_op1 = builder.tee_new_local(); + + builder + .instruction_body + .load_aligned_i32(global_pointers::LAST_OP2); + let last_op2 = builder.tee_new_local(); + + builder.instruction_body.xor_i32(); + + builder.instruction_body.get_local(&last_op2); + builder + .instruction_body + .load_aligned_i32(global_pointers::LAST_ADD_RESULT); + builder.instruction_body.xor_i32(); + + builder.instruction_body.and_i32(); + + builder.instruction_body.get_local(&last_op1); + builder.instruction_body.xor_i32(); + + builder.free_local(last_op1); + builder.free_local(last_op2); + + builder + .instruction_body + .load_aligned_i32(global_pointers::LAST_OP_SIZE); + builder.instruction_body.shr_u_i32(); + builder.instruction_body.const_i32(1); + builder.instruction_body.and_i32(); + + builder.instruction_body.else_(); + builder + .instruction_body + .load_aligned_i32(global_pointers::FLAGS); + builder.instruction_body.const_i32(FLAG_CARRY); + builder.instruction_body.and_i32(); + builder.instruction_body.block_end(); +} + +pub fn gen_test_be(builder: &mut WasmBuilder) { + // TODO: Could be made lazy + gen_getcf(builder); + gen_getzf(builder); + builder.instruction_body.or_i32(); +} + pub fn gen_fpu_get_sti(ctx: &mut JitContext, i: u32) { ctx.builder.instruction_body.const_i32(i as i32); gen_call_fn1_ret_f64(ctx.builder, "fpu_get_sti"); @@ -1422,8 +1517,31 @@ pub fn gen_trigger_gp(ctx: &mut JitContext, error_code: u32) { pub fn gen_condition_fn(builder: &mut WasmBuilder, condition: u8) { dbg_assert!(condition < 16); - let condition_name = CONDITION_FUNCTIONS[condition as usize]; - gen_fn0_const_ret(builder, condition_name); + if condition == 2 { + gen_getcf(builder); + } + else if condition == 3 { + gen_getcf(builder); + builder.instruction_body.eqz_i32(); + } + else if condition == 4 { + gen_getzf(builder); + } + else if condition == 5 { + gen_getzf(builder); + builder.instruction_body.eqz_i32(); + } + else if condition == 6 { + gen_test_be(builder); + } + else if condition == 7 { + gen_test_be(builder); + builder.instruction_body.eqz_i32(); + } + else { + let condition_name = CONDITION_FUNCTIONS[condition as usize]; + gen_fn0_const_ret(builder, condition_name); + } } pub fn gen_move_registers_from_locals_to_memory(ctx: &mut JitContext) { From d98e1b2f70ea4f66a04a8514fa8cdd3ef72ee9c1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1594/2137] Generate code (instead of call) for 32-bit arithmetic operations --- src/rust/jit_instructions.rs | 408 +++++++++++++++++++++++++++++------ 1 file changed, 344 insertions(+), 64 deletions(-) diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 0380bb74..3360d1b1 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -2,7 +2,9 @@ use codegen; use cpu::BitSize; -use cpu2::cpu::{FLAGS_ALL, FLAGS_DEFAULT, FLAGS_MASK, FLAG_OVERFLOW, OPSIZE_32}; +use cpu2::cpu::{ + FLAGS_ALL, FLAGS_DEFAULT, FLAGS_MASK, FLAG_ADJUST, FLAG_CARRY, FLAG_OVERFLOW, OPSIZE_32, +}; use global_pointers; use jit::JitContext; use modrm; @@ -161,10 +163,10 @@ fn group_arith_ax_imm16(ctx: &mut JitContext, op: &str, imm16: u32) { codegen::gen_set_reg16(ctx, regs::AX); } -fn group_arith_eax_imm32(ctx: &mut JitContext, op: &str, imm32: u32) { +fn group_arith_eax_imm32(ctx: &mut JitContext, op: &Fn(&mut WasmBuilder), imm32: u32) { codegen::gen_get_reg32(ctx, regs::EAX); ctx.builder.instruction_body.const_i32(imm32 as i32); - codegen::gen_call_fn2_ret(ctx.builder, op); + op(ctx.builder); codegen::gen_set_reg32(ctx, regs::EAX); } @@ -248,6 +250,51 @@ macro_rules! define_instruction_read32( } ); + ($fn:expr, $name_mem:ident, $name_reg:ident, xreg) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read32(ctx); + codegen::gen_get_reg32(ctx, r); + $fn(ctx.builder); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_get_reg32(ctx, r1); + codegen::gen_get_reg32(ctx, r2); + $fn(ctx.builder); + } + ); + + ($fn:expr, $name_mem:ident, $name_reg:ident, ximm8s) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read32(ctx); + ctx.builder.instruction_body.const_i32(make_imm_read!(ctx, imm8s) as i32); + $fn(ctx.builder); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { + codegen::gen_get_reg32(ctx, r1); + ctx.builder.instruction_body.const_i32(imm as i32); + $fn(ctx.builder); + } + ); + + ($fn:expr, $name_mem:ident, $name_reg:ident, ximm32) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read32(ctx); + ctx.builder.instruction_body.const_i32(make_imm_read!(ctx, imm32) as i32); + $fn(ctx.builder); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { + codegen::gen_get_reg32(ctx, r1); + ctx.builder.instruction_body.const_i32(imm as i32); + $fn(ctx.builder); + } + ); + ($fn:expr, $name_mem:ident, $name_reg:ident, $imm:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); @@ -318,7 +365,24 @@ macro_rules! define_instruction_write_reg32( codegen::gen_call_fn2_ret(ctx.builder, $fn); codegen::gen_set_reg32(ctx, r2); } - ) + ); + + ($fn:expr, $name_mem:ident, $name_reg:ident, xreg) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_get_reg32(ctx, r); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read32(ctx); + $fn(ctx.builder); + codegen::gen_set_reg32(ctx, r); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_get_reg32(ctx, r2); + codegen::gen_get_reg32(ctx, r1); + $fn(ctx.builder); + codegen::gen_set_reg32(ctx, r2); + } + ); ); macro_rules! mask_imm( @@ -646,6 +710,30 @@ macro_rules! define_instruction_read_write_mem32( } ); + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, xreg) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { + codegen::gen_get_reg32(ctx, r); + $fn(ctx.builder); + }, &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn2(ctx.builder, $fallback_fn); + codegen::gen_move_registers_from_memory_to_locals(ctx); + }); + ctx.builder.free_local(address_local); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_get_reg32(ctx, r1); + codegen::gen_get_reg32(ctx, r2); + $fn(ctx.builder); + codegen::gen_set_reg32(ctx, r1); + } + ); + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, constant_one) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); @@ -776,6 +864,58 @@ macro_rules! define_instruction_read_write_mem32( } ); + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, ximm32) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + let imm = make_imm_read!(ctx, imm32) as i32; + codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(imm as i32); + $fn(ctx.builder); + }, &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn2(ctx.builder, $fallback_fn); + codegen::gen_move_registers_from_memory_to_locals(ctx); + }); + ctx.builder.free_local(address_local); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { + let imm = mask_imm!(imm, imm32); + codegen::gen_get_reg32(ctx, r1); + ctx.builder.instruction_body.const_i32(imm as i32); + $fn(ctx.builder); + codegen::gen_set_reg32(ctx, r1); + } + ); + + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, ximm8s) => ( + pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + let imm = make_imm_read!(ctx, imm8s) as i32; + codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(imm as i32); + $fn(ctx.builder); + }, &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(imm as i32); + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn2(ctx.builder, $fallback_fn); + codegen::gen_move_registers_from_memory_to_locals(ctx); + }); + ctx.builder.free_local(address_local); + } + + pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { + let imm = mask_imm!(imm, imm8s); + codegen::gen_get_reg32(ctx, r1); + ctx.builder.instruction_body.const_i32(imm as i32); + $fn(ctx.builder); + codegen::gen_set_reg32(ctx, r1); + } + ); + ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, $imm:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); @@ -827,6 +967,124 @@ pub fn gen_add32(builder: &mut WasmBuilder) { builder.free_local(result); } +pub fn gen_sub32(builder: &mut WasmBuilder) { + let source_operand = builder.set_new_local(); + let dest_operand = builder.set_new_local(); + + builder.instruction_body.get_local(&dest_operand); + builder.instruction_body.get_local(&source_operand); + builder.instruction_body.sub_i32(); + let result = builder.set_new_local(); + + codegen::gen_set_last_op1(builder, &result); + codegen::gen_set_last_op2(builder, &source_operand); + codegen::gen_set_last_add_result(builder, &dest_operand); + codegen::gen_set_last_result(builder, &result); + codegen::gen_set_last_op_size(builder, OPSIZE_32); + codegen::gen_set_flags_changed(builder, FLAGS_ALL); + + // leave result on stack + builder.instruction_body.get_local(&result); + + builder.free_local(dest_operand); + builder.free_local(source_operand); + builder.free_local(result); +} + +pub fn gen_cmp32(builder: &mut WasmBuilder) { + let source_operand = builder.set_new_local(); + let dest_operand = builder.set_new_local(); + + builder.instruction_body.get_local(&dest_operand); + builder.instruction_body.get_local(&source_operand); + builder.instruction_body.sub_i32(); + let result = builder.set_new_local(); + + codegen::gen_set_last_op1(builder, &result); + codegen::gen_set_last_op2(builder, &source_operand); + codegen::gen_set_last_add_result(builder, &dest_operand); + codegen::gen_set_last_result(builder, &result); + codegen::gen_set_last_op_size(builder, OPSIZE_32); + codegen::gen_set_flags_changed(builder, FLAGS_ALL); + + builder.free_local(dest_operand); + builder.free_local(source_operand); + builder.free_local(result); +} + +pub fn gen_adc32(builder: &mut WasmBuilder) { codegen::gen_call_fn2_ret(builder, "adc32"); } + +pub fn gen_sbb32(builder: &mut WasmBuilder) { codegen::gen_call_fn2_ret(builder, "sbb32"); } + +pub fn gen_and32(builder: &mut WasmBuilder) { + builder.instruction_body.and_i32(); + let result = builder.set_new_local(); + + codegen::gen_set_last_result(builder, &result); + codegen::gen_set_last_op_size(builder, OPSIZE_32); + codegen::gen_set_flags_changed( + builder, + FLAGS_ALL & !FLAG_CARRY & !FLAG_OVERFLOW & !FLAG_ADJUST, + ); + codegen::gen_clear_flags_bits(builder, FLAG_CARRY | FLAG_OVERFLOW | FLAG_ADJUST); + + // leave result on stack + builder.instruction_body.get_local(&result); + + builder.free_local(result); +} + +pub fn gen_test32(builder: &mut WasmBuilder) { + builder.instruction_body.and_i32(); + let result = builder.set_new_local(); + + codegen::gen_set_last_result(builder, &result); + codegen::gen_set_last_op_size(builder, OPSIZE_32); + codegen::gen_set_flags_changed( + builder, + FLAGS_ALL & !FLAG_CARRY & !FLAG_OVERFLOW & !FLAG_ADJUST, + ); + codegen::gen_clear_flags_bits(builder, FLAG_CARRY | FLAG_OVERFLOW | FLAG_ADJUST); + + builder.free_local(result); +} + +pub fn gen_or32(builder: &mut WasmBuilder) { + builder.instruction_body.or_i32(); + let result = builder.set_new_local(); + + codegen::gen_set_last_result(builder, &result); + codegen::gen_set_last_op_size(builder, OPSIZE_32); + codegen::gen_set_flags_changed( + builder, + FLAGS_ALL & !FLAG_CARRY & !FLAG_OVERFLOW & !FLAG_ADJUST, + ); + codegen::gen_clear_flags_bits(builder, FLAG_CARRY | FLAG_OVERFLOW | FLAG_ADJUST); + + // leave result on stack + builder.instruction_body.get_local(&result); + + builder.free_local(result); +} + +pub fn gen_xor32(builder: &mut WasmBuilder) { + builder.instruction_body.xor_i32(); + let result = builder.set_new_local(); + + codegen::gen_set_last_result(builder, &result); + codegen::gen_set_last_op_size(builder, OPSIZE_32); + codegen::gen_set_flags_changed( + builder, + FLAGS_ALL & !FLAG_CARRY & !FLAG_OVERFLOW & !FLAG_ADJUST, + ); + codegen::gen_clear_flags_bits(builder, FLAG_CARRY | FLAG_OVERFLOW | FLAG_ADJUST); + + // leave result on stack + builder.instruction_body.get_local(&result); + + builder.free_local(result); +} + fn gen_xadd32(ctx: &mut JitContext, r: u32) { let source = ctx.builder.set_new_local(); codegen::gen_get_reg32(ctx, r); @@ -843,6 +1101,24 @@ fn gen_xadd32(ctx: &mut JitContext, r: u32) { ctx.builder.free_local(tmp); } +fn gen_cmpxchg32(ctx: &mut JitContext, r: u32) { + let source = ctx.builder.set_new_local(); + codegen::gen_get_reg32(ctx, regs::EAX); + ctx.builder.instruction_body.get_local(&source); + gen_cmp32(ctx.builder); + + codegen::gen_getzf(ctx.builder); + ctx.builder.instruction_body.if_i32(); + codegen::gen_get_reg32(ctx, r); + ctx.builder.instruction_body.else_(); + ctx.builder.instruction_body.get_local(&source); + codegen::gen_set_reg32(ctx, regs::EAX); + ctx.builder.instruction_body.get_local(&source); + ctx.builder.instruction_body.block_end(); + + ctx.builder.free_local(source); +} + fn gen_mul32(ctx: &mut JitContext) { ctx.builder.instruction_body.extend_unsigned_i32_to_i64(); @@ -888,23 +1164,23 @@ define_instruction_read_write_mem16!( reg ); define_instruction_read_write_mem32!( - "add32", + gen_add32, "instr32_01_mem", instr32_01_mem_jit, instr32_01_reg_jit, - reg + xreg ); define_instruction_write_reg8!("add8", instr_02_mem_jit, instr_02_reg_jit); define_instruction_write_reg16!("add16", instr16_03_mem_jit, instr16_03_reg_jit); -define_instruction_write_reg32!("add32", instr32_03_mem_jit, instr32_03_reg_jit); +define_instruction_write_reg32!(gen_add32, instr32_03_mem_jit, instr32_03_reg_jit, xreg); pub fn instr_04_jit(ctx: &mut JitContext, imm8: u32) { group_arith_al_imm8(ctx, "add8", imm8); } pub fn instr16_05_jit(ctx: &mut JitContext, imm16: u32) { group_arith_ax_imm16(ctx, "add16", imm16); } pub fn instr32_05_jit(ctx: &mut JitContext, imm32: u32) { - group_arith_eax_imm32(ctx, "add32", imm32); + group_arith_eax_imm32(ctx, &gen_add32, imm32); } define_instruction_read_write_mem8!( @@ -922,23 +1198,23 @@ define_instruction_read_write_mem16!( reg ); define_instruction_read_write_mem32!( - "or32", + gen_or32, "instr32_09_mem", instr32_09_mem_jit, instr32_09_reg_jit, - reg + xreg ); define_instruction_write_reg8!("or8", instr_0A_mem_jit, instr_0A_reg_jit); define_instruction_write_reg16!("or16", instr16_0B_mem_jit, instr16_0B_reg_jit); -define_instruction_write_reg32!("or32", instr32_0B_mem_jit, instr32_0B_reg_jit); +define_instruction_write_reg32!(gen_or32, instr32_0B_mem_jit, instr32_0B_reg_jit, xreg); pub fn instr_0C_jit(ctx: &mut JitContext, imm8: u32) { group_arith_al_imm8(ctx, "or8", imm8); } pub fn instr16_0D_jit(ctx: &mut JitContext, imm16: u32) { group_arith_ax_imm16(ctx, "or16", imm16); } pub fn instr32_0D_jit(ctx: &mut JitContext, imm32: u32) { - group_arith_eax_imm32(ctx, "or32", imm32); + group_arith_eax_imm32(ctx, &gen_or32, imm32); } define_instruction_read_write_mem8!( @@ -972,7 +1248,7 @@ pub fn instr16_15_jit(ctx: &mut JitContext, imm16: u32) { group_arith_ax_imm16(ctx, "adc16", imm16); } pub fn instr32_15_jit(ctx: &mut JitContext, imm32: u32) { - group_arith_eax_imm32(ctx, "adc32", imm32); + group_arith_eax_imm32(ctx, &gen_adc32, imm32); } define_instruction_read_write_mem8!( @@ -1006,7 +1282,7 @@ pub fn instr16_1D_jit(ctx: &mut JitContext, imm16: u32) { group_arith_ax_imm16(ctx, "sbb16", imm16); } pub fn instr32_1D_jit(ctx: &mut JitContext, imm32: u32) { - group_arith_eax_imm32(ctx, "sbb32", imm32); + group_arith_eax_imm32(ctx, &gen_sbb32, imm32); } define_instruction_read_write_mem8!( @@ -1024,23 +1300,23 @@ define_instruction_read_write_mem16!( reg ); define_instruction_read_write_mem32!( - "and32", + gen_and32, "instr32_21_mem", instr32_21_mem_jit, instr32_21_reg_jit, - reg + xreg ); define_instruction_write_reg8!("and8", instr_22_mem_jit, instr_22_reg_jit); define_instruction_write_reg16!("and16", instr16_23_mem_jit, instr16_23_reg_jit); -define_instruction_write_reg32!("and32", instr32_23_mem_jit, instr32_23_reg_jit); +define_instruction_write_reg32!(gen_and32, instr32_23_mem_jit, instr32_23_reg_jit, xreg); pub fn instr_24_jit(ctx: &mut JitContext, imm8: u32) { group_arith_al_imm8(ctx, "and8", imm8); } pub fn instr16_25_jit(ctx: &mut JitContext, imm16: u32) { group_arith_ax_imm16(ctx, "and16", imm16); } pub fn instr32_25_jit(ctx: &mut JitContext, imm32: u32) { - group_arith_eax_imm32(ctx, "and32", imm32); + group_arith_eax_imm32(ctx, &gen_and32, imm32); } define_instruction_read_write_mem8!( @@ -1058,23 +1334,23 @@ define_instruction_read_write_mem16!( reg ); define_instruction_read_write_mem32!( - "sub32", + gen_sub32, "instr32_29_mem", instr32_29_mem_jit, instr32_29_reg_jit, - reg + xreg ); define_instruction_write_reg8!("sub8", instr_2A_mem_jit, instr_2A_reg_jit); define_instruction_write_reg16!("sub16", instr16_2B_mem_jit, instr16_2B_reg_jit); -define_instruction_write_reg32!("sub32", instr32_2B_mem_jit, instr32_2B_reg_jit); +define_instruction_write_reg32!(gen_sub32, instr32_2B_mem_jit, instr32_2B_reg_jit, xreg); pub fn instr_2C_jit(ctx: &mut JitContext, imm8: u32) { group_arith_al_imm8(ctx, "sub8", imm8); } pub fn instr16_2D_jit(ctx: &mut JitContext, imm16: u32) { group_arith_ax_imm16(ctx, "sub16", imm16); } pub fn instr32_2D_jit(ctx: &mut JitContext, imm32: u32) { - group_arith_eax_imm32(ctx, "sub32", imm32); + group_arith_eax_imm32(ctx, &gen_sub32, imm32); } define_instruction_read_write_mem8!( @@ -1092,28 +1368,28 @@ define_instruction_read_write_mem16!( reg ); define_instruction_read_write_mem32!( - "xor32", + gen_xor32, "instr32_31_mem", instr32_31_mem_jit, instr32_31_reg_jit, - reg + xreg ); define_instruction_write_reg8!("xor8", instr_32_mem_jit, instr_32_reg_jit); define_instruction_write_reg16!("xor16", instr16_33_mem_jit, instr16_33_reg_jit); -define_instruction_write_reg32!("xor32", instr32_33_mem_jit, instr32_33_reg_jit); +define_instruction_write_reg32!(gen_xor32, instr32_33_mem_jit, instr32_33_reg_jit, xreg); pub fn instr_34_jit(ctx: &mut JitContext, imm8: u32) { group_arith_al_imm8(ctx, "xor8", imm8); } pub fn instr16_35_jit(ctx: &mut JitContext, imm16: u32) { group_arith_ax_imm16(ctx, "xor16", imm16); } pub fn instr32_35_jit(ctx: &mut JitContext, imm32: u32) { - group_arith_eax_imm32(ctx, "xor32", imm32); + group_arith_eax_imm32(ctx, &gen_xor32, imm32); } define_instruction_read8!("cmp8", instr_38_mem_jit, instr_38_reg_jit); define_instruction_read16!("cmp16", instr16_39_mem_jit, instr16_39_reg_jit); -define_instruction_read32!("cmp32", instr32_39_mem_jit, instr32_39_reg_jit); +define_instruction_read32!(gen_cmp32, instr32_39_mem_jit, instr32_39_reg_jit, xreg); pub fn instr_3A_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_get_reg8(ctx, r); @@ -1145,13 +1421,13 @@ pub fn instr32_3B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_get_reg32(ctx, r); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); - codegen::gen_call_fn2(ctx.builder, "cmp32") + gen_cmp32(ctx.builder); } pub fn instr32_3B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_get_reg32(ctx, r2); codegen::gen_get_reg32(ctx, r1); - codegen::gen_call_fn2(ctx.builder, "cmp32") + gen_cmp32(ctx.builder); } pub fn instr_3C_jit(ctx: &mut JitContext, imm8: u32) { @@ -1169,7 +1445,7 @@ pub fn instr16_3D_jit(ctx: &mut JitContext, imm16: u32) { pub fn instr32_3D_jit(ctx: &mut JitContext, imm32: u32) { codegen::gen_get_reg32(ctx, 0); ctx.builder.instruction_body.const_i32(imm32 as i32); - codegen::gen_call_fn2(ctx.builder, "cmp32"); + gen_cmp32(ctx.builder); } fn gen_inc16(ctx: &mut JitContext, r: u32) { @@ -1473,11 +1749,11 @@ define_instruction_read_write_mem16!( imm16 ); define_instruction_read_write_mem32!( - "add32", + gen_add32, "instr32_81_0_mem", instr32_81_0_mem_jit, instr32_81_0_reg_jit, - imm32 + ximm32 ); define_instruction_read_write_mem16!( @@ -1488,11 +1764,11 @@ define_instruction_read_write_mem16!( imm16 ); define_instruction_read_write_mem32!( - "or32", + gen_or32, "instr32_81_1_mem", instr32_81_1_mem_jit, instr32_81_1_reg_jit, - imm32 + ximm32 ); define_instruction_read_write_mem16!( @@ -1533,11 +1809,11 @@ define_instruction_read_write_mem16!( imm16 ); define_instruction_read_write_mem32!( - "and32", + gen_and32, "instr32_81_4_mem", instr32_81_4_mem_jit, instr32_81_4_reg_jit, - imm32 + ximm32 ); define_instruction_read_write_mem16!( @@ -1548,11 +1824,11 @@ define_instruction_read_write_mem16!( imm16 ); define_instruction_read_write_mem32!( - "sub32", + gen_sub32, "instr32_81_5_mem", instr32_81_5_mem_jit, instr32_81_5_reg_jit, - imm32 + ximm32 ); define_instruction_read_write_mem16!( @@ -1563,11 +1839,11 @@ define_instruction_read_write_mem16!( imm16 ); define_instruction_read_write_mem32!( - "xor32", + gen_xor32, "instr32_81_6_mem", instr32_81_6_mem_jit, instr32_81_6_reg_jit, - imm32 + ximm32 ); define_instruction_read_write_mem16!( @@ -1578,11 +1854,11 @@ define_instruction_read_write_mem16!( imm8s ); define_instruction_read_write_mem32!( - "add32", + gen_add32, "instr32_83_0_mem", instr32_83_0_mem_jit, instr32_83_0_reg_jit, - imm8s + ximm8s ); define_instruction_read_write_mem16!( @@ -1593,11 +1869,11 @@ define_instruction_read_write_mem16!( imm8s ); define_instruction_read_write_mem32!( - "or32", + gen_or32, "instr32_83_1_mem", instr32_83_1_mem_jit, instr32_83_1_reg_jit, - imm8s + ximm8s ); define_instruction_read_write_mem16!( @@ -1638,11 +1914,11 @@ define_instruction_read_write_mem16!( imm8s ); define_instruction_read_write_mem32!( - "and32", + gen_and32, "instr32_83_4_mem", instr32_83_4_mem_jit, instr32_83_4_reg_jit, - imm8s + ximm8s ); define_instruction_read_write_mem16!( @@ -1653,11 +1929,11 @@ define_instruction_read_write_mem16!( imm8s ); define_instruction_read_write_mem32!( - "sub32", + gen_sub32, "instr32_83_5_mem", instr32_83_5_mem_jit, instr32_83_5_reg_jit, - imm8s + ximm8s ); define_instruction_read_write_mem16!( @@ -1668,23 +1944,33 @@ define_instruction_read_write_mem16!( imm8s ); define_instruction_read_write_mem32!( - "xor32", + gen_xor32, "instr32_83_6_mem", instr32_83_6_mem_jit, instr32_83_6_reg_jit, - imm8s + ximm8s ); define_instruction_read8!("cmp8", instr_80_7_mem_jit, instr_80_7_reg_jit, imm8); define_instruction_read16!("cmp16", instr16_81_7_mem_jit, instr16_81_7_reg_jit, imm16); -define_instruction_read32!("cmp32", instr32_81_7_mem_jit, instr32_81_7_reg_jit, imm32); +define_instruction_read32!( + gen_cmp32, + instr32_81_7_mem_jit, + instr32_81_7_reg_jit, + ximm32 +); define_instruction_read16!("cmp16", instr16_83_7_mem_jit, instr16_83_7_reg_jit, imm8s); -define_instruction_read32!("cmp32", instr32_83_7_mem_jit, instr32_83_7_reg_jit, imm8s); +define_instruction_read32!( + gen_cmp32, + instr32_83_7_mem_jit, + instr32_83_7_reg_jit, + ximm8s +); define_instruction_read8!("test8", instr_84_mem_jit, instr_84_reg_jit); define_instruction_read16!("test16", instr16_85_mem_jit, instr16_85_reg_jit); -define_instruction_read32!("test32", instr32_85_mem_jit, instr32_85_reg_jit); +define_instruction_read32!(gen_test32, instr32_85_mem_jit, instr32_85_reg_jit, xreg); pub fn instr_88_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); @@ -3106,13 +3392,13 @@ pub fn instr32_F7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_safe_read32(ctx); let imm = ctx.cpu.read_imm32(); ctx.builder.instruction_body.const_i32(imm as i32); - codegen::gen_call_fn2(ctx.builder, "test32") + gen_test32(ctx.builder); } pub fn instr32_F7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { codegen::gen_get_reg32(ctx, r); ctx.builder.instruction_body.const_i32(imm as i32); - codegen::gen_call_fn2(ctx.builder, "test32") + gen_test32(ctx.builder); } pub fn instr32_F7_1_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { @@ -3552,7 +3838,7 @@ pub fn instr16_A9_jit(ctx: &mut JitContext, imm16: u32) { pub fn instr32_A9_jit(ctx: &mut JitContext, imm32: u32) { codegen::gen_get_reg32(ctx, 0); ctx.builder.instruction_body.const_i32(imm32 as i32); - codegen::gen_call_fn2(ctx.builder, "test32"); + gen_test32(ctx.builder); } pub fn instr_0F18_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) { @@ -3681,10 +3967,7 @@ pub fn instr16_0FB1_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { pub fn instr32_0FB1_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_get_reg32(ctx, r1); - ctx.builder.instruction_body.const_i32(r2 as i32); - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn2_ret(ctx.builder, "cmpxchg32"); - codegen::gen_move_registers_from_memory_to_locals(ctx); + gen_cmpxchg32(ctx, r2); codegen::gen_set_reg32(ctx, r1); } pub fn instr32_0FB1_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { @@ -3695,10 +3978,7 @@ pub fn instr32_0FB1_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { BitSize::DWORD, &address_local, &|ref mut ctx| { - ctx.builder.instruction_body.const_i32(r as i32); - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn2_ret(ctx.builder, "cmpxchg32"); - codegen::gen_move_registers_from_memory_to_locals(ctx); + gen_cmpxchg32(ctx, r); }, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(r as i32); From 5f31a8aba23bda5ccb47827f687bd234e00cbf9a Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1595/2137] Update expect tests for flags and arithmetic code generation (last two commits) --- tests/expect/tests/do-while.wast | 60 ++++++++++++++++++++++++++++---- tests/expect/tests/if.wast | 30 +++++++++++++--- tests/expect/tests/while-do.wast | 59 +++++++++++++++++++++++++++---- 3 files changed, 131 insertions(+), 18 deletions(-) diff --git a/tests/expect/tests/do-while.wast b/tests/expect/tests/do-while.wast index 37e97f57..8b45b5f3 100644 --- a/tests/expect/tests/do-while.wast +++ b/tests/expect/tests/do-while.wast @@ -16,13 +16,11 @@ (type $t14 (func (param i32 i32 i32) (result i32))) (type $t15 (func (param i32 i64 i64))) (import "e" "inc32" (func $e.inc32 (type $t5))) - (import "e" "cmp32" (func $e.cmp32 (type $t2))) - (import "e" "test_nz" (func $e.test_nz (type $t4))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "trigger_pagefault_end_jit" (func $e.trigger_pagefault_end_jit (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (local $l10 i32) (local $l11 i32) (local $l12 i32) (set_local $l0 (get_local $p0)) (set_local $l1 @@ -94,9 +92,32 @@ (set_local $l5 (call $e.inc32 (get_local $l5))) - (call $e.cmp32 - (get_local $l2) + (get_local $l2) + (set_local $l10 (i32.const 10)) + (set_local $l11) + (set_local $l12 + (i32.sub + (get_local $l11) + (get_local $l10))) + (i32.store + (i32.const 512) + (get_local $l12)) + (i32.store + (i32.const 516) + (get_local $l10)) + (i32.store + (i32.const 524) + (get_local $l11)) + (i32.store + (i32.const 528) + (get_local $l12)) + (i32.store + (i32.const 520) + (i32.const 31)) + (i32.store + (i32.const 532) + (i32.const 2261)) (i32.store (i32.const 560) (i32.add @@ -115,8 +136,33 @@ (i32.load (i32.const 664)) (i32.const 3))) - (if $I6 - (call $e.test_nz) + (if $I7 + (i32.eqz + (if $I6 (result i32) + (i32.and + (i32.load + (i32.const 532)) + (i32.const 64)) + (then + (i32.and + (i32.shr_u + (i32.and + (i32.xor + (tee_local $l12 + (i32.load + (i32.const 528))) + (i32.const -1)) + (i32.sub + (get_local $l12) + (i32.const 1))) + (i32.load + (i32.const 520))) + (i32.const 1))) + (else + (i32.and + (i32.load + (i32.const 536)) + (i32.const 64))))) (then (i32.store (i32.const 556) diff --git a/tests/expect/tests/if.wast b/tests/expect/tests/if.wast index f5b98829..0e9405d8 100644 --- a/tests/expect/tests/if.wast +++ b/tests/expect/tests/if.wast @@ -15,14 +15,13 @@ (type $t13 (func (param f64) (result i64))) (type $t14 (func (param i32 i32 i32) (result i32))) (type $t15 (func (param i32 i64 i64))) - (import "e" "cmp32" (func $e.cmp32 (type $t2))) (import "e" "test_nle" (func $e.test_nle (type $t4))) (import "e" "inc32" (func $e.inc32 (type $t5))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "trigger_pagefault_end_jit" (func $e.trigger_pagefault_end_jit (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (local $l10 i32) (local $l11 i32) (local $l12 i32) (set_local $l0 (get_local $p0)) (set_local $l1 @@ -92,9 +91,32 @@ (block $B6 (br_table $B6 $B5 $B4 $B3 $B2 (get_local $l0))) - (call $e.cmp32 - (get_local $l2) + (get_local $l2) + (set_local $l10 (i32.const 5)) + (set_local $l11) + (set_local $l12 + (i32.sub + (get_local $l11) + (get_local $l10))) + (i32.store + (i32.const 512) + (get_local $l12)) + (i32.store + (i32.const 516) + (get_local $l10)) + (i32.store + (i32.const 524) + (get_local $l11)) + (i32.store + (i32.const 528) + (get_local $l12)) + (i32.store + (i32.const 520) + (i32.const 31)) + (i32.store + (i32.const 532) + (i32.const 2261)) (i32.store (i32.const 560) (i32.add diff --git a/tests/expect/tests/while-do.wast b/tests/expect/tests/while-do.wast index 88ab125c..d16c0db9 100644 --- a/tests/expect/tests/while-do.wast +++ b/tests/expect/tests/while-do.wast @@ -15,14 +15,12 @@ (type $t13 (func (param f64) (result i64))) (type $t14 (func (param i32 i32 i32) (result i32))) (type $t15 (func (param i32 i64 i64))) - (import "e" "cmp32" (func $e.cmp32 (type $t2))) - (import "e" "test_z" (func $e.test_z (type $t4))) (import "e" "inc32" (func $e.inc32 (type $t5))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "trigger_pagefault_end_jit" (func $e.trigger_pagefault_end_jit (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (local $l10 i32) (local $l11 i32) (local $l12 i32) (set_local $l0 (get_local $p0)) (set_local $l1 @@ -92,9 +90,32 @@ (block $B6 (br_table $B6 $B5 $B4 $B3 $B2 (get_local $l0))) - (call $e.cmp32 - (get_local $l2) + (get_local $l2) + (set_local $l10 (i32.const 10)) + (set_local $l11) + (set_local $l12 + (i32.sub + (get_local $l11) + (get_local $l10))) + (i32.store + (i32.const 512) + (get_local $l12)) + (i32.store + (i32.const 516) + (get_local $l10)) + (i32.store + (i32.const 524) + (get_local $l11)) + (i32.store + (i32.const 528) + (get_local $l12)) + (i32.store + (i32.const 520) + (i32.const 31)) + (i32.store + (i32.const 532) + (i32.const 2261)) (i32.store (i32.const 560) (i32.add @@ -113,8 +134,32 @@ (i32.load (i32.const 664)) (i32.const 2))) - (if $I7 - (call $e.test_z) + (if $I8 + (if $I7 (result i32) + (i32.and + (i32.load + (i32.const 532)) + (i32.const 64)) + (then + (i32.and + (i32.shr_u + (i32.and + (i32.xor + (tee_local $l12 + (i32.load + (i32.const 528))) + (i32.const -1)) + (i32.sub + (get_local $l12) + (i32.const 1))) + (i32.load + (i32.const 520))) + (i32.const 1))) + (else + (i32.and + (i32.load + (i32.const 536)) + (i32.const 64)))) (then (i32.store (i32.const 556) From 0e8c8a1ddac016f86f92d3534d6cd6336a47c860 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1596/2137] More opstats --- Cargo.toml | 1 + src/browser/print_stats.js | 108 +++++++++------- src/cpu.js | 7 ++ src/rust/codegen.rs | 41 +++++-- src/rust/cpu2/cpu.rs | 48 ++++++-- src/rust/cpu2/global_pointers.rs | 9 +- src/rust/global_pointers.rs | 4 +- src/rust/jit.rs | 8 +- src/rust/opstats.rs | 204 +++++++++++++++++++++++++++---- 9 files changed, 333 insertions(+), 97 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2a9205cc..49d17450 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ quickcheck = "0.6.2" [features] default = [] profiler = [] +profiler_instrument = [] [lib] crate-type = ["cdylib"] diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index 7c44c9cf..abec840a 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -75,12 +75,7 @@ const print_stats = { { let stat = cpu.v86oxide.exports["profiler_stat_get"](i); stat = stat >= 100e6 ? Math.round(stat / 1e6) + "m" : stat >= 100e3 ? Math.round(stat / 1e3) + "k" : stat; - text += stat_names[i] + "=" + stat + " "; - - if(((i + 1) % Math.floor(stat_names.length / 3) === 0)) - { - text += "\n"; - } + text += stat_names[i] + "=" + stat + "\n"; } text += "\n"; @@ -172,23 +167,41 @@ const print_stats = { print_instruction_counts: function(cpu) { - return print_stats.print_instruction_counts_offset(cpu, 0) + "\n\n" + - print_stats.print_instruction_counts_offset(cpu, 0x200); + return [ + print_stats.print_instruction_counts_offset(cpu, false, false, false, false), + print_stats.print_instruction_counts_offset(cpu, true, false, false, false), + print_stats.print_instruction_counts_offset(cpu, false, true, false, false), + print_stats.print_instruction_counts_offset(cpu, false, false, true, false), + print_stats.print_instruction_counts_offset(cpu, false, false, false, true), + ].join("\n\n"); }, - print_instruction_counts_offset: function(cpu, offset) + print_instruction_counts_offset: function(cpu, compiled, jit_exit, unguarded_register, wasm_size) { let text = ""; const counts = []; - for(let i = 0; i < 0x100; i++) - { - const count = cpu.v86oxide.exports["get_opstats_buffer"](i + offset); - counts.push([i, count]); + const label = + compiled ? "compiled" : + jit_exit ? "jit exit" : + unguarded_register ? "unguarded register" : + wasm_size ? "wasm size" : + "executed"; - const count_0f = cpu.v86oxide.exports["get_opstats_buffer"](i + 0x100 + offset); - counts.push([0x0f00 | i, count_0f]); + for(let opcode = 0; opcode < 0x100; opcode++) + { + for(let fixed_g = 0; fixed_g < 8; fixed_g++) + { + for(let is_mem of [false, true]) + { + const count = cpu.v86oxide.exports["get_opstats_buffer"](compiled, jit_exit, unguarded_register, wasm_size, opcode, false, is_mem, fixed_g); + counts.push({ opcode, count, is_mem, fixed_g }); + + const count_0f = cpu.v86oxide.exports["get_opstats_buffer"](compiled, jit_exit, unguarded_register, wasm_size, opcode, true, is_mem, fixed_g); + counts.push({ opcode: 0x0f00 | opcode, count: count_0f, is_mem, fixed_g }); + } + } } let total = 0; @@ -197,9 +210,12 @@ const print_stats = { 0x64, 0x65, 0x66, 0x67, 0xF0, 0xF2, 0xF3, ]); - for(let [i, count] of counts) + for(let { count, opcode } of counts) { - total += i < 0x100 && !prefixes.has(i) ? count : 0; + if(!prefixes.has(opcode)) + { + total += count; + } } if(total === 0) @@ -207,53 +223,63 @@ const print_stats = { return ""; } + const per_opcode = new Uint32Array(0x100); + const per_opcode0f = new Uint32Array(0x100); + + for(let { opcode, count } of counts) + { + if((opcode & 0xFF00) == 0x0F00) + { + per_opcode0f[opcode & 0xFF] += count; + } + else + { + per_opcode[opcode & 0xFF] += count; + } + } + text += "------------------\n"; text += "Total: " + total + "\n"; const factor = total > 1e7 ? 1000 : 1; const max_count = Math.max.apply(Math, - counts.map(([_, count]) => Math.round(count / factor)) + counts.map(({ count }) => Math.round(count / factor)) ); const pad_length = String(max_count).length; - text += `Instruction counts (in ${factor}):\n`; + text += `Instruction counts ${label} (in ${factor}):\n`; - for(let [i, count] of counts) + for(let i = 0; i < 0x100; i++) { - if((i & 0xFF00) === 0) - { - text += h(i, 2).slice(2) + ":" + v86util.pads(Math.round(count / factor), pad_length); + text += h(i, 2).slice(2) + ":" + v86util.pads(Math.round(per_opcode[i] / factor), pad_length); - if(i % 16 == 15) - text += "\n"; - else - text += " "; - } + if(i % 16 == 15) + text += "\n"; + else + text += " "; } text += "\n"; - text += `Instruction counts (0f, in ${factor}):\n`; + text += `Instruction counts ${label} (0f, in ${factor}):\n`; - for(let [i, count] of counts) + for(let i = 0; i < 0x100; i++) { - if((i & 0xFF00) === 0x0F00) - { - text += h(i & 0xFF, 2).slice(2) + ":" + v86util.pads(Math.round(count / factor), pad_length); + text += h(i & 0xFF, 2).slice(2) + ":" + v86util.pads(Math.round(per_opcode0f[i] / factor), pad_length); - if(i % 16 == 15) - text += "\n"; - else - text += " "; - } + if(i % 16 == 15) + text += "\n"; + else + text += " "; } text += "\n"; - const top_counts = counts.sort(([o1, c1], [o2, c2]) => c2 - c1); + const top_counts = counts.filter(({ count }) => count).sort(({ count: count1 }, { count: count2 }) => count2 - count1); - for(let [opcode, count] of top_counts.slice(0, 100)) + for(let { opcode, is_mem, fixed_g, count } of top_counts.slice(0, 200)) { - text += opcode.toString(16) + ":" + (count / total * 100).toFixed(1) + " "; + let opcode_description = opcode.toString(16) + "_" + fixed_g + (is_mem ? "_m" : "_r"); + text += opcode_description + ":" + (count / total * 100).toFixed(2) + " "; } text += "\n"; diff --git a/src/cpu.js b/src/cpu.js index 0bc3d8b9..3e70800a 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -21,6 +21,8 @@ function CPU(bus, wm, v86oxide, coverage_logger) const memory = v86oxide.instance.exports.memory; + this.wasm_memory = memory; + this.memory_size = v86util.view(Uint32Array, memory, 812, 1); // Note: Currently unused (degrades performance and not required by any OS @@ -207,6 +209,11 @@ function CPU(bus, wm, v86oxide, coverage_logger) //Object.seal(this); } +CPU.prototype.clear_opstats = function() +{ + new Uint8Array(this.wasm_memory.buffer, 0x8000, 0x20000).fill(0); +}; + CPU.prototype.wasmgen_get_module_code = function() { const ptr = this.jit_get_op_ptr(); diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index a914066f..7b898633 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -482,9 +482,7 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize, where_to_write: Option true, + _ => false, + }); + let last_jump_addr = ::cpu2::cpu::debug_last_jump.phys_address().unwrap(); + let last_jump_opcode = if last_jump_addr != 0 { + read32s(last_jump_addr) + } + else { + // Happens during exit due to loop iteration limit + 0 + }; + ::opstats::record_opstat_jit_exit(last_jump_opcode as u32); + } + if Page::page_of(*previous_ip as u32) == Page::page_of(*instruction_pointer as u32) { profiler::stat_increment(RUN_FROM_CACHE_EXIT_SAME_PAGE); } @@ -2524,7 +2540,7 @@ pub unsafe fn safe_write32(address: i32, value: i32) -> OrPageFault<()> { *(mem8.offset(phys_address as isize) as *mut i32) = value; } else { - if false { + if true { if address & 0xFFF > 0x1000 - 4 { profiler::stat_increment(SAFE_WRITE_SLOW_PAGE_CROSSED); } @@ -2973,19 +2989,31 @@ pub unsafe fn vm86_mode() -> bool { return *flags & FLAG_VM == FLAG_VM; } pub unsafe fn getiopl() -> i32 { return *flags >> 12 & 3; } #[no_mangle] -pub unsafe fn get_opstats_buffer(index: i32) -> i32 { - dbg_assert!(index >= 0 && index < 0x400); - if index < 0x100 { - return *opstats_buffer.offset(index as isize) as i32; +pub unsafe fn get_opstats_buffer( + compiled: bool, + jit_exit: bool, + unguarded_register: bool, + wasm_size: bool, + opcode: u8, + is_0f: bool, + is_mem: bool, + fixed_g: u8, +) -> u32 { + let index = (is_0f as u32) << 12 | (opcode as u32) << 4 | (is_mem as u32) << 3 | fixed_g as u32; + if compiled { + *opstats_compiled_buffer.offset(index as isize) } - else if index < 0x200 { - return *opstats_buffer_0f.offset((index - 0x100) as isize) as i32; + else if jit_exit { + *opstats_jit_exit_buffer.offset(index as isize) } - else if index < 0x300 { - return *opstats_compiled_buffer.offset((index - 0x200) as isize) as i32; + else if unguarded_register { + *opstats_unguarded_register_buffer.offset(index as isize) + } + else if wasm_size { + *opstats_wasm_size.offset(index as isize) } else { - return *opstats_compiled_buffer_0f.offset((index - 0x300) as isize) as i32; + *opstats_buffer.offset(index as isize) } } diff --git a/src/rust/cpu2/global_pointers.rs b/src/rust/cpu2/global_pointers.rs index 1cdd4a5a..694ff59d 100644 --- a/src/rust/cpu2/global_pointers.rs +++ b/src/rust/cpu2/global_pointers.rs @@ -63,8 +63,9 @@ pub const fpu_dp_selector: *mut i32 = 1060 as *mut i32; pub const reg_mmx: *mut reg64 = 1064 as *mut reg64; pub const tss_size_32: *mut bool = 1128 as *mut bool; pub const fxsave_store_fpu_mask: *mut u8 = 1132 as *mut u8; -pub const opstats_buffer: *mut u32 = 0x1000 as *mut u32; -pub const opstats_buffer_0f: *mut u32 = 0x1400 as *mut u32; -pub const opstats_compiled_buffer: *mut u32 = 0x1800 as *mut u32; -pub const opstats_compiled_buffer_0f: *mut u32 = 0x1C00 as *mut u32; +pub const opstats_buffer: *mut u32 = 0x08000 as *mut u32; +pub const opstats_compiled_buffer: *mut u32 = 0x10000 as *mut u32; +pub const opstats_jit_exit_buffer: *mut u32 = 0x18000 as *mut u32; +pub const opstats_unguarded_register_buffer: *mut u32 = 0x20000 as *mut u32; +pub const opstats_wasm_size: *mut u32 = 0x28000 as *mut u32; pub const tlb_data: *mut i32 = 0x400000 as *mut i32; diff --git a/src/rust/global_pointers.rs b/src/rust/global_pointers.rs index de788ad8..6443b128 100644 --- a/src/rust/global_pointers.rs +++ b/src/rust/global_pointers.rs @@ -14,10 +14,10 @@ pub const PREFIXES: u32 = 648; pub const TIMESTAMP_COUNTER: u32 = 664; pub const SREG: u32 = 668; pub const SEGMENT_OFFSETS: u32 = 736; -pub const OPSTATS_BUFFER: u32 = 0x1000; -pub const OPSTATS_BUFFER_0F: u32 = 0x1400; pub const REG_XMM: u32 = 828; pub const FPU_CONTROL_WORD: u32 = 1036; +pub const OPSTATS_BUFFER: u32 = 0x08000; +pub const OPSTATS_UNGUARDED_REGISTER_BUFFER: u32 = 0x20000; pub const TLB_DATA: u32 = 0x400000; pub fn get_reg32_offset(r: u32) -> u32 { diff --git a/src/rust/jit.rs b/src/rust/jit.rs index ab8b77aa..50ef3dee 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -1200,8 +1200,9 @@ fn jit_generate_basic_block( ctx.cpu.eip = start_addr; loop { + let mut instruction = 0; if cfg!(feature = "profiler") { - let instruction = cpu::read32(ctx.cpu.eip); + instruction = cpu::read32(ctx.cpu.eip); ::opstats::gen_opstats(ctx.builder, instruction); ::opstats::record_opstat_compiled(instruction); } @@ -1217,6 +1218,8 @@ fn jit_generate_basic_block( codegen::gen_increment_instruction_pointer(ctx.builder, stop_addr - start_addr); } + let wasm_length_before = ctx.builder.instruction_body.len(); + ctx.start_of_current_instruction = ctx.cpu.eip; let start_eip = ctx.cpu.eip; let mut instruction_flags = 0; @@ -1226,6 +1229,9 @@ fn jit_generate_basic_block( let instruction_length = end_eip - start_eip; let was_block_boundary = instruction_flags & JIT_INSTR_BLOCK_BOUNDARY_FLAG != 0; + let wasm_length = ctx.builder.instruction_body.len() - wasm_length_before; + ::opstats::record_opstat_size_wasm(instruction, wasm_length as u32); + dbg_assert!((end_eip == stop_addr) == (start_eip == last_instruction_addr)); dbg_assert!(instruction_length < MAX_INSTRUCTION_LENGTH); diff --git a/src/rust/opstats.rs b/src/rust/opstats.rs index 641fbf9b..a87c63a8 100644 --- a/src/rust/opstats.rs +++ b/src/rust/opstats.rs @@ -6,6 +6,8 @@ use wasmgen::module_init::WasmBuilder; struct Instruction { prefixes: Vec, opcode: u8, + fixed_g: u8, + is_mem: bool, is_0f: bool, } @@ -52,14 +54,101 @@ fn decode(mut instruction: u32) -> Instruction { } } + let has_modrm_byte = if is_0f { + match final_opcode { + 0x0 | 0x1 | 0x2 | 0x3 | 0x10 | 0x11 | 0x12 | 0x13 | 0x14 | 0x15 | 0x16 | 0x17 + | 0x18 | 0x19 | 0x20 | 0x21 | 0x22 | 0x23 | 0x28 | 0x29 | 0x40 | 0x41 | 0x42 | 0x43 + | 0x44 | 0x45 | 0x46 | 0x47 | 0x48 | 0x49 | 0x50 | 0x51 | 0x52 | 0x53 | 0x54 | 0x55 + | 0x56 | 0x57 | 0x58 | 0x59 | 0x60 | 0x61 | 0x62 | 0x63 | 0x64 | 0x65 | 0x66 | 0x67 + | 0x68 | 0x69 | 0x70 | 0x71 | 0x72 | 0x73 | 0x74 | 0x75 | 0x76 | 0x90 | 0x91 | 0x92 + | 0x93 | 0x94 | 0x95 | 0x96 | 0x97 | 0x98 | 0x99 | 0x1c | 0x1d | 0x1e | 0x1f | 0x2a + | 0x2b | 0x2c | 0x2d | 0x2e | 0x2f | 0x4a | 0x4b | 0x4c | 0x4d | 0x4e | 0x4f | 0x5a + | 0x5b | 0x5c | 0x5d | 0x5e | 0x5f | 0x6a | 0x6b | 0x6c | 0x6d | 0x6e | 0x6f | 0x7e + | 0x7f | 0x9a | 0x9b | 0x9c | 0x9d | 0x9e | 0x9f | 0xa3 | 0xa4 | 0xa5 | 0xab | 0xac + | 0xad | 0xae | 0xaf | 0xb0 | 0xb1 | 0xb2 | 0xb3 | 0xb4 | 0xb5 | 0xb6 | 0xb7 | 0xb8 + | 0xba | 0xbb | 0xbc | 0xbd | 0xbe | 0xbf | 0xc0 | 0xc1 | 0xc2 | 0xc3 | 0xc4 | 0xc5 + | 0xc6 | 0xc7 | 0xd1 | 0xd2 | 0xd3 | 0xd4 | 0xd5 | 0xd6 | 0xd7 | 0xd8 | 0xd9 | 0xda + | 0xdb | 0xdc | 0xdd | 0xde | 0xdf | 0xe0 | 0xe1 | 0xe2 | 0xe3 | 0xe4 | 0xe5 | 0xe6 + | 0xe7 | 0xe8 | 0xe9 | 0xea | 0xeb | 0xec | 0xed | 0xee | 0xef | 0xf1 | 0xf2 | 0xf3 + | 0xf4 | 0xf5 | 0xf6 | 0xf7 | 0xf8 | 0xf9 | 0xfa | 0xfb | 0xfc | 0xfd | 0xfe => true, + _ => false, + } + } + else { + match final_opcode { + 0x0 | 0x1 | 0x2 | 0x3 | 0x8 | 0x9 | 0x10 | 0x11 | 0x12 | 0x13 | 0x18 | 0x19 | 0x20 + | 0x21 | 0x22 | 0x23 | 0x28 | 0x29 | 0x30 | 0x31 | 0x32 | 0x33 | 0x38 | 0x39 | 0x62 + | 0x63 | 0x69 | 0x80 | 0x81 | 0x82 | 0x83 | 0x84 | 0x85 | 0x86 | 0x87 | 0x88 | 0x89 + | 0xa | 0xb | 0x1a | 0x1b | 0x2a | 0x2b | 0x3a | 0x3b | 0x6b | 0x8a | 0x8b | 0x8c + | 0x8d | 0x8e | 0x8f | 0xc0 | 0xc1 | 0xc4 | 0xc5 | 0xc6 | 0xc7 | 0xd0 | 0xd1 | 0xd2 + | 0xd3 | 0xd8 | 0xd9 | 0xda | 0xdb | 0xdc | 0xdd | 0xde | 0xdf | 0xf6 | 0xf7 | 0xfe + | 0xff => true, + _ => false, + } + }; + + let has_fixed_g = if is_0f { + final_opcode == 0x71 + || final_opcode == 0x72 + || final_opcode == 0x73 + || final_opcode == 0xAE + || final_opcode == 0xBA + || final_opcode == 0xC7 + } + else { + final_opcode >= 0x80 && final_opcode < 0x84 + || final_opcode >= 0xC0 && final_opcode < 0xC2 + || final_opcode >= 0xD0 && final_opcode < 0xD4 + || final_opcode >= 0xD8 && final_opcode < 0xE0 + || final_opcode >= 0xF6 && final_opcode < 0xF8 + || final_opcode == 0xFE + || final_opcode == 0xFF + }; + + let mut is_mem = false; + let mut fixed_g = 0; + + if has_fixed_g { + dbg_assert!(has_modrm_byte); + let modrm_byte = (instruction & 0xFF) as u8; + fixed_g = modrm_byte >> 3 & 7; + is_mem = modrm_byte < 0xC0 + } + if has_modrm_byte { + let modrm_byte = (instruction & 0xFF) as u8; + is_mem = modrm_byte < 0xC0 + } + Instruction { prefixes, opcode: final_opcode, + is_mem, + fixed_g, is_0f, } } pub fn gen_opstats(builder: &mut WasmBuilder, opcode: u32) { + if !cfg!(feature = "profiler") || !cfg!(feature = "profiler_instrument") { + return; + } + + let instruction = decode(opcode); + + for prefix in instruction.prefixes { + let index = (prefix as u32) << 4; + gen_increment_mem32(builder, global_pointers::OPSTATS_BUFFER + 4 * index); + } + + let index = (instruction.is_0f as u32) << 12 + | (instruction.opcode as u32) << 4 + | (instruction.is_mem as u32) << 3 + | instruction.fixed_g as u32; + + gen_increment_mem32(builder, global_pointers::OPSTATS_BUFFER + 4 * index); +} + +pub fn record_opstat_compiled(opcode: u32) { if !cfg!(feature = "profiler") { return; } @@ -67,39 +156,102 @@ pub fn gen_opstats(builder: &mut WasmBuilder, opcode: u32) { let instruction = decode(opcode); for prefix in instruction.prefixes { - gen_increment_mem32(builder, global_pointers::OPSTATS_BUFFER + 4 * prefix as u32); + let index = (prefix as u32) << 4; + unsafe { *cpu2::global_pointers::opstats_compiled_buffer.offset(index as isize) += 1 } } - if instruction.is_0f { - gen_increment_mem32( - builder, - global_pointers::OPSTATS_BUFFER_0F + 4 * instruction.opcode as u32, - ); - } - else { - gen_increment_mem32( - builder, - global_pointers::OPSTATS_BUFFER + 4 * instruction.opcode as u32, - ); - } + let index = (instruction.is_0f as u32) << 12 + | (instruction.opcode as u32) << 4 + | (instruction.is_mem as u32) << 3 + | instruction.fixed_g as u32; + + unsafe { *cpu2::global_pointers::opstats_compiled_buffer.offset(index as isize) += 1 } } -pub fn record_opstat_compiled(opcode: u32) { +pub fn record_opstat_jit_exit(opcode: u32) { + if !cfg!(feature = "profiler") { + return; + } + let instruction = decode(opcode); for prefix in instruction.prefixes { - unsafe { *cpu2::global_pointers::opstats_compiled_buffer.offset(prefix as isize) += 1 } + let index = (prefix as u32) << 4; + unsafe { *cpu2::global_pointers::opstats_jit_exit_buffer.offset(index as isize) += 1 } } - if instruction.is_0f { - unsafe { - *cpu2::global_pointers::opstats_compiled_buffer_0f - .offset(instruction.opcode as isize) += 1 - } - } - else { - unsafe { - *cpu2::global_pointers::opstats_compiled_buffer.offset(instruction.opcode as isize) += 1 - } - } + let index = (instruction.is_0f as u32) << 12 + | (instruction.opcode as u32) << 4 + | (instruction.is_mem as u32) << 3 + | instruction.fixed_g as u32; + + unsafe { *cpu2::global_pointers::opstats_jit_exit_buffer.offset(index as isize) += 1 } +} + +pub fn record_opstat_unguarded_register(opcode: u32) { + if !cfg!(feature = "profiler") { + return; + } + + let instruction = decode(opcode); + + for prefix in instruction.prefixes { + let index = (prefix as u32) << 4; + unsafe { + *cpu2::global_pointers::opstats_unguarded_register_buffer.offset(index as isize) += 1 + } + } + + let index = (instruction.is_0f as u32) << 12 + | (instruction.opcode as u32) << 4 + | (instruction.is_mem as u32) << 3 + | instruction.fixed_g as u32; + + unsafe { *cpu2::global_pointers::opstats_unguarded_register_buffer.offset(index as isize) += 1 } +} + +pub fn gen_opstat_unguarded_register(builder: &mut WasmBuilder, opcode: u32) { + if !cfg!(feature = "profiler") || !cfg!(feature = "profiler_instrument") { + return; + } + + let instruction = decode(opcode); + + for prefix in instruction.prefixes { + let index = (prefix as u32) << 4; + gen_increment_mem32( + builder, + global_pointers::OPSTATS_UNGUARDED_REGISTER_BUFFER + 4 * index, + ); + } + + let index = (instruction.is_0f as u32) << 12 + | (instruction.opcode as u32) << 4 + | (instruction.is_mem as u32) << 3 + | instruction.fixed_g as u32; + + gen_increment_mem32( + builder, + global_pointers::OPSTATS_UNGUARDED_REGISTER_BUFFER + 4 * index, + ); +} + +pub fn record_opstat_size_wasm(opcode: u32, size: u32) { + if !cfg!(feature = "profiler") { + return; + } + + let instruction = decode(opcode); + + for prefix in instruction.prefixes { + let index = (prefix as u32) << 4; + unsafe { *cpu2::global_pointers::opstats_wasm_size.offset(index as isize) += size } + } + + let index = (instruction.is_0f as u32) << 12 + | (instruction.opcode as u32) << 4 + | (instruction.is_mem as u32) << 3 + | instruction.fixed_g as u32; + + unsafe { *cpu2::global_pointers::opstats_wasm_size.offset(index as isize) += size } } From 0263764a5c1ee99d6a255cda76002ae2e877736b Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1597/2137] Remove unused unguarded_register property during analysis --- gen/generate_analyzer.js | 12 ------------ src/rust/analysis.rs | 2 -- 2 files changed, 14 deletions(-) diff --git a/gen/generate_analyzer.js b/gen/generate_analyzer.js index ef831c23..0e9463f8 100755 --- a/gen/generate_analyzer.js +++ b/gen/generate_analyzer.js @@ -227,18 +227,6 @@ function gen_instruction_body_after_fixed_g(encoding, size) instruction_postfix.push("analysis.no_next_instruction = true;"); } - if(!encoding.prefix) - { - if(encoding.custom && !encoding.unguarded_register || encoding.no_register) - { - instruction_postfix.push("analysis.unguarded_register = false;"); - } - else - { - instruction_postfix.push("analysis.unguarded_register = true;"); - } - } - if(encoding.prefix) { const instruction_name = "::analysis::" + make_instruction_name(encoding, size) + "_analyze"; diff --git a/src/rust/analysis.rs b/src/rust/analysis.rs index c0ac7a25..d537b2ff 100644 --- a/src/rust/analysis.rs +++ b/src/rust/analysis.rs @@ -18,14 +18,12 @@ pub enum AnalysisType { pub struct Analysis { pub no_next_instruction: bool, pub ty: AnalysisType, - pub unguarded_register: bool, } pub fn analyze_step(mut cpu: &mut CpuContext) -> Analysis { let mut analysis = Analysis { no_next_instruction: false, ty: AnalysisType::Normal, - unguarded_register: false, }; cpu.prefixes = 0; let opcode = cpu.read_imm8() as u32 | (cpu.osize_32() as u32) << 8; From 732cc2ee1c02704e45a90baeddaf4d83f249dd1f Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1598/2137] generate_interpreter: Don't stop after custom sse instructions (synchronised with check in generate_jit) --- gen/generate_interpreter.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/gen/generate_interpreter.js b/gen/generate_interpreter.js index 0b4c1db7..f8abd253 100755 --- a/gen/generate_interpreter.js +++ b/gen/generate_interpreter.js @@ -228,9 +228,8 @@ function gen_instruction_body_after_fixed_g(encoding, size) const instruction_prefix = []; const instruction_postfix = (encoding.block_boundary && !encoding.no_block_boundary_in_interpreted) || - (!encoding.custom && encoding.e) || - encoding.sse || - encoding.task_switch_test ? ["after_block_boundary();"] : []; + (!encoding.custom && encoding.e) ? + ["after_block_boundary();"] : []; if(encoding.task_switch_test || encoding.sse) { From e99da402150488b69373378b3b6d14ad70b869ac Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1599/2137] Make std/cld custom (FC/FD), remove unused unguarded_register and no_register properties from x86 table --- gen/generate_jit.js | 3 +-- gen/x86_table.js | 4 ++-- src/rust/jit_instructions.rs | 27 ++++++++++++++++++++++++++- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/gen/generate_jit.js b/gen/generate_jit.js index a8c37062..8cc9b3e7 100755 --- a/gen/generate_jit.js +++ b/gen/generate_jit.js @@ -241,7 +241,7 @@ function gen_instruction_body_after_fixed_g(encoding, size) if(!encoding.prefix) { - if(encoding.custom && !encoding.unguarded_register || encoding.no_register) + if(encoding.custom) { } else @@ -252,7 +252,6 @@ function gen_instruction_body_after_fixed_g(encoding, size) instruction_postfix.push( gen_call("::codegen::gen_move_registers_from_memory_to_locals", ["ctx"]) ); - } } diff --git a/gen/x86_table.js b/gen/x86_table.js index ccadd38c..52497fc9 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -399,8 +399,8 @@ const encodings = [ { opcode: 0xFA, custom: 1, skip: 1 }, // sti: not a jump, but can cause a change in eip { opcode: 0xFB, block_boundary: 1, skip: 1, }, - { opcode: 0xFC, no_register: 1, }, - { opcode: 0xFD, no_register: 1, }, + { opcode: 0xFC, custom: 1, }, + { opcode: 0xFD, custom: 1, }, { opcode: 0xFE, e: 1, fixed_g: 0, }, { opcode: 0xFE, e: 1, fixed_g: 1, }, diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 3360d1b1..45f006d8 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -3,7 +3,8 @@ use codegen; use cpu::BitSize; use cpu2::cpu::{ - FLAGS_ALL, FLAGS_DEFAULT, FLAGS_MASK, FLAG_ADJUST, FLAG_CARRY, FLAG_OVERFLOW, OPSIZE_32, + FLAGS_ALL, FLAGS_DEFAULT, FLAGS_MASK, FLAG_ADJUST, FLAG_CARRY, FLAG_DIRECTION, FLAG_OVERFLOW, + OPSIZE_32, }; use global_pointers; use jit::JitContext; @@ -3497,6 +3498,30 @@ pub fn instr_FA_jit(ctx: &mut JitContext) { ctx.builder.instruction_body.block_end(); } +pub fn instr_FC_jit(ctx: &mut JitContext) { + ctx.builder + .instruction_body + .const_i32(global_pointers::FLAGS as i32); + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::FLAGS); + ctx.builder.instruction_body.const_i32(!FLAG_DIRECTION); + ctx.builder.instruction_body.and_i32(); + ctx.builder.instruction_body.store_aligned_i32(0); +} + +pub fn instr_FD_jit(ctx: &mut JitContext) { + ctx.builder + .instruction_body + .const_i32(global_pointers::FLAGS as i32); + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::FLAGS); + ctx.builder.instruction_body.const_i32(FLAG_DIRECTION); + ctx.builder.instruction_body.or_i32(); + ctx.builder.instruction_body.store_aligned_i32(0); +} + define_instruction_read_write_mem16!( "inc16", "instr16_FF_0_mem", From 6e005a20588a8dab4d726b063b36a9950be8a56d Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1600/2137] Integration test: Mark Windows 3 as slow test, print diff output in qemu tests --- tests/full/run.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/full/run.js b/tests/full/run.js index 50494757..3e9016a4 100755 --- a/tests/full/run.js +++ b/tests/full/run.js @@ -128,7 +128,7 @@ if(cluster.isMaster) actions: [ { on_text: "/root%", - run: "cd tests; ./test-i386 > emu.test; diff emu.test reference.test > /dev/null && echo test pas''sed || echo failed\n", + run: "cd tests; ./test-i386 > emu.test; diff emu.test reference.test && echo test pas''sed || echo failed\n", }, ], }, @@ -192,7 +192,7 @@ if(cluster.isMaster) actions: [ { on_text: "/root%", - run: "cd tests; ./test-i386 > emu.test; diff emu.test reference.test > /dev/null && echo test pas''sed || echo failed\n", + run: "cd tests; ./test-i386 > emu.test; diff emu.test reference.test && echo test pas''sed || echo failed\n", }, ], }, @@ -251,6 +251,7 @@ if(cluster.isMaster) }, { name: "Windows 3.0", + slow: 1, skip_if_disk_image_missing: true, timeout: 10 * 60, cdrom: root_path + "/../v86-images/os/Win30.iso", From 63afa77167f59ccccac94afe89829be0f5351bf8 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1601/2137] Global pointers: Align general purpose registers, sse registers and flags --- src/cpu.js | 30 ++-- src/rust/cpu2/global_pointers.rs | 30 ++-- src/rust/global_pointers.rs | 19 +-- tests/expect/tests/call.wast | 112 ++++++------- tests/expect/tests/do-while.wast | 116 +++++++------- tests/expect/tests/if.wast | 108 ++++++------- tests/expect/tests/indirect-call.wast | 112 ++++++------- tests/expect/tests/mov16.wast | 96 +++++------ tests/expect/tests/mov32-mem.wast | 96 +++++------ tests/expect/tests/mov32-reg.wast | 96 +++++------ tests/expect/tests/pop.wast | 96 +++++------ tests/expect/tests/push.wast | 96 +++++------ tests/expect/tests/task_switch_test.wast | 112 ++++++------- tests/expect/tests/task_switch_test_sse.wast | 160 +++++++++---------- tests/expect/tests/while-do.wast | 116 +++++++------- 15 files changed, 699 insertions(+), 696 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index 3e70800a..41abe754 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -98,25 +98,25 @@ function CPU(bus, wm, v86oxide, coverage_logger) this.prefixes = v86util.view(Int32Array, memory, 648, 1); - this.flags = v86util.view(Int32Array, memory, 536, 1); + this.flags = v86util.view(Int32Array, memory, 120, 1); /** * bitmap of flags which are not updated in the flags variable * changed by arithmetic instructions, so only relevant to arithmetic flags */ - this.flags_changed = v86util.view(Int32Array, memory, 532, 1); + this.flags_changed = v86util.view(Int32Array, memory, 116, 1); /** * the last 2 operators and the result and size of the last arithmetic operation */ - this.last_op1 = v86util.view(Int32Array, memory, 512, 1); - this.last_op2 = v86util.view(Int32Array, memory, 516, 1); - this.last_op_size = v86util.view(Int32Array, memory, 520, 1); + this.last_op1 = v86util.view(Int32Array, memory, 96, 1); + this.last_op2 = v86util.view(Int32Array, memory, 100, 1); + this.last_op_size = v86util.view(Int32Array, memory, 104, 1); - this.last_add_result = v86util.view(Int32Array, memory, 524, 1); - this.last_result = v86util.view(Int32Array, memory, 528, 1); + this.last_add_result = v86util.view(Int32Array, memory, 108, 1); + this.last_result = v86util.view(Int32Array, memory, 112, 1); - this.current_tsc = v86util.view(Uint32Array, memory, 956, 2); // 64 bit + this.current_tsc = v86util.view(Uint32Array, memory, 960, 2); // 64 bit /** @type {!Object} */ this.devices = {}; @@ -144,12 +144,12 @@ function CPU(bus, wm, v86oxide, coverage_logger) this.timestamp_counter = v86util.view(Uint32Array, memory, 664, 1); // registers - this.reg32s = v86util.view(Int32Array, memory, 4, 8); - this.reg32 = v86util.view(Uint32Array, memory, 4, 8); - this.reg16s = v86util.view(Int16Array, memory, 4, 16); - this.reg16 = v86util.view(Uint16Array, memory, 4, 16); - this.reg8s = v86util.view(Int8Array, memory, 4, 32); - this.reg8 = v86util.view(Uint8Array, memory, 4, 32); + this.reg32s = v86util.view(Int32Array, memory, 64, 8); + this.reg32 = v86util.view(Uint32Array, memory, 64, 8); + this.reg16s = v86util.view(Int16Array, memory, 64, 16); + this.reg16 = v86util.view(Uint16Array, memory, 64, 16); + this.reg8s = v86util.view(Int8Array, memory, 64, 32); + this.reg8 = v86util.view(Uint8Array, memory, 64, 32); // Why no Float80Array :-( this.fpu_st = v86util.view(Float64Array, memory, 968, 8); @@ -182,7 +182,7 @@ function CPU(bus, wm, v86oxide, coverage_logger) this.fxsave_store_fpu_mask = v86util.view(Uint8Array, memory, 1132, 1); - this.reg_xmm32s = v86util.view(Int32Array, memory, 828, 8 * 4); + this.reg_xmm32s = v86util.view(Int32Array, memory, 832, 8 * 4); this.mxcsr = v86util.view(Int32Array, memory, 824, 1); diff --git a/src/rust/cpu2/global_pointers.rs b/src/rust/cpu2/global_pointers.rs index 694ff59d..ad774e94 100644 --- a/src/rust/cpu2/global_pointers.rs +++ b/src/rust/cpu2/global_pointers.rs @@ -2,18 +2,19 @@ use cpu2::cpu::{reg128, reg64}; -pub const reg8: *mut u8 = 4 as *mut u8; -pub const reg16: *mut u16 = 4 as *mut u16; -pub const reg8s: *mut i8 = 4 as *mut i8; -pub const reg16s: *mut i16 = 4 as *mut i16; -pub const reg32s: *mut i32 = 4 as *mut i32; -pub const last_op1: *mut i32 = 512 as *mut i32; -pub const last_op2: *mut i32 = 516 as *mut i32; -pub const last_op_size: *mut i32 = 520 as *mut i32; -pub const last_add_result: *mut i32 = 524 as *mut i32; -pub const last_result: *mut i32 = 528 as *mut i32; -pub const flags_changed: *mut i32 = 532 as *mut i32; -pub const flags: *mut i32 = 536 as *mut i32; +pub const reg8: *mut u8 = 64 as *mut u8; +pub const reg16: *mut u16 = 64 as *mut u16; +pub const reg8s: *mut i8 = 64 as *mut i8; +pub const reg16s: *mut i16 = 64 as *mut i16; +pub const reg32s: *mut i32 = 64 as *mut i32; +pub const last_op1: *mut i32 = 96 as *mut i32; +pub const last_op2: *mut i32 = 100 as *mut i32; +pub const last_op_size: *mut i32 = 104 as *mut i32; +pub const last_add_result: *mut i32 = 108 as *mut i32; +pub const last_result: *mut i32 = 112 as *mut i32; +pub const flags_changed: *mut i32 = 116 as *mut i32; +pub const flags: *mut i32 = 120 as *mut i32; + pub const page_fault: *mut bool = 540 as *mut bool; pub const page_fault_error_code: *mut i32 = 544 as *mut i32; pub const a20_enabled: *mut bool = 552 as *mut bool; @@ -47,8 +48,9 @@ pub const stack_size_32: *mut bool = 808 as *mut bool; pub const memory_size: *mut u32 = 812 as *mut u32; pub const fpu_stack_empty: *mut i32 = 816 as *mut i32; pub const mxcsr: *mut i32 = 824 as *mut i32; -pub const reg_xmm: *mut reg128 = 828 as *mut reg128; -pub const current_tsc: *mut u64 = 956 as *mut u64; +// gap +pub const reg_xmm: *mut reg128 = 832 as *mut reg128; +pub const current_tsc: *mut u64 = 960 as *mut u64; pub const fpu_st: *mut f64 = 968 as *mut f64; pub const fpu_st8: *mut u8 = 968 as *mut u8; pub const fpu_st32: *mut i32 = 968 as *mut i32; diff --git a/src/rust/global_pointers.rs b/src/rust/global_pointers.rs index 6443b128..d1e1a190 100644 --- a/src/rust/global_pointers.rs +++ b/src/rust/global_pointers.rs @@ -1,11 +1,12 @@ -pub const REG: u32 = 4; -pub const LAST_OP1: u32 = 512; -pub const LAST_OP2: u32 = 516; -pub const LAST_OP_SIZE: u32 = 520; -pub const LAST_ADD_RESULT: u32 = 524; -pub const LAST_RESULT: u32 = 528; -pub const FLAGS_CHANGED: u32 = 532; -pub const FLAGS: u32 = 536; +pub const REG: u32 = 64; +pub const LAST_OP1: u32 = 96; +pub const LAST_OP2: u32 = 100; +pub const LAST_OP_SIZE: u32 = 104; +pub const LAST_ADD_RESULT: u32 = 108; +pub const LAST_RESULT: u32 = 112; +pub const FLAGS_CHANGED: u32 = 116; +pub const FLAGS: u32 = 120; + pub const PAGE_FAULT: u32 = 540; pub const INSTRUCTION_POINTER: u32 = 556; pub const PREVIOUS_IP: u32 = 560; @@ -14,7 +15,7 @@ pub const PREFIXES: u32 = 648; pub const TIMESTAMP_COUNTER: u32 = 664; pub const SREG: u32 = 668; pub const SEGMENT_OFFSETS: u32 = 736; -pub const REG_XMM: u32 = 828; +pub const REG_XMM: u32 = 832; pub const FPU_CONTROL_WORD: u32 = 1036; pub const OPSTATS_BUFFER: u32 = 0x08000; pub const OPSTATS_UNGUARDED_REGISTER_BUFFER: u32 = 0x20000; diff --git a/tests/expect/tests/call.wast b/tests/expect/tests/call.wast index b021d2b7..27389b50 100644 --- a/tests/expect/tests/call.wast +++ b/tests/expect/tests/call.wast @@ -29,28 +29,28 @@ (i32.const 10000)) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (loop $L0 (set_local $l1 (i32.add @@ -61,28 +61,28 @@ (get_local $l1)) (then (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return))) (block $B2 @@ -187,54 +187,54 @@ (i32.const 556)) (i32.const 1))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.instr_F4) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (i32.store (i32.const 664) (i32.add @@ -242,28 +242,28 @@ (i32.const 664)) (i32.const 1))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return)) (set_local $l2 @@ -342,53 +342,53 @@ (i32.const 664)) (i32.const 2))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return)) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.trigger_pagefault_end_jit) (i32.store diff --git a/tests/expect/tests/do-while.wast b/tests/expect/tests/do-while.wast index 8b45b5f3..7391ae34 100644 --- a/tests/expect/tests/do-while.wast +++ b/tests/expect/tests/do-while.wast @@ -27,28 +27,28 @@ (i32.const 10000)) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (loop $L0 (set_local $l1 (i32.add @@ -59,28 +59,28 @@ (get_local $l1)) (then (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return))) (block $B2 @@ -101,22 +101,22 @@ (get_local $l11) (get_local $l10))) (i32.store - (i32.const 512) + (i32.const 96) (get_local $l12)) (i32.store - (i32.const 516) + (i32.const 100) (get_local $l10)) (i32.store - (i32.const 524) + (i32.const 108) (get_local $l11)) (i32.store - (i32.const 528) + (i32.const 112) (get_local $l12)) (i32.store - (i32.const 520) + (i32.const 104) (i32.const 31)) (i32.store - (i32.const 532) + (i32.const 116) (i32.const 2261)) (i32.store (i32.const 560) @@ -141,7 +141,7 @@ (if $I6 (result i32) (i32.and (i32.load - (i32.const 532)) + (i32.const 116)) (i32.const 64)) (then (i32.and @@ -150,18 +150,18 @@ (i32.xor (tee_local $l12 (i32.load - (i32.const 528))) + (i32.const 112))) (i32.const -1)) (i32.sub (get_local $l12) (i32.const 1))) (i32.load - (i32.const 520))) + (i32.const 104))) (i32.const 1))) (else (i32.and (i32.load - (i32.const 536)) + (i32.const 120)) (i32.const 64))))) (then (i32.store @@ -187,54 +187,54 @@ (i32.const 556)) (i32.const 1))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.instr_F4) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (i32.store (i32.const 664) (i32.add @@ -242,53 +242,53 @@ (i32.const 664)) (i32.const 1))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return)) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.trigger_pagefault_end_jit) (i32.store diff --git a/tests/expect/tests/if.wast b/tests/expect/tests/if.wast index 0e9405d8..a6a42250 100644 --- a/tests/expect/tests/if.wast +++ b/tests/expect/tests/if.wast @@ -28,28 +28,28 @@ (i32.const 10000)) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (loop $L0 (set_local $l1 (i32.add @@ -60,28 +60,28 @@ (get_local $l1)) (then (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return))) (block $B2 @@ -100,22 +100,22 @@ (get_local $l11) (get_local $l10))) (i32.store - (i32.const 512) + (i32.const 96) (get_local $l12)) (i32.store - (i32.const 516) + (i32.const 100) (get_local $l10)) (i32.store - (i32.const 524) + (i32.const 108) (get_local $l11)) (i32.store - (i32.const 528) + (i32.const 112) (get_local $l12)) (i32.store - (i32.const 520) + (i32.const 104) (i32.const 31)) (i32.store - (i32.const 532) + (i32.const 116) (i32.const 2261)) (i32.store (i32.const 560) @@ -188,54 +188,54 @@ (i32.const 556)) (i32.const 2))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.instr_F4) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (i32.store (i32.const 664) (i32.add @@ -243,53 +243,53 @@ (i32.const 664)) (i32.const 2))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return)) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.trigger_pagefault_end_jit) (i32.store diff --git a/tests/expect/tests/indirect-call.wast b/tests/expect/tests/indirect-call.wast index db8901c9..92dd7628 100644 --- a/tests/expect/tests/indirect-call.wast +++ b/tests/expect/tests/indirect-call.wast @@ -28,28 +28,28 @@ (i32.const 10000)) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (loop $L0 (set_local $l1 (i32.add @@ -60,28 +60,28 @@ (get_local $l1)) (then (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return))) (block $B2 @@ -218,28 +218,28 @@ (i32.const 664)) (i32.const 1))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return)) (i32.store @@ -253,54 +253,54 @@ (i32.const 556)) (i32.const 1))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.instr_F4) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (i32.store (i32.const 664) (i32.add @@ -308,53 +308,53 @@ (i32.const 664)) (i32.const 1))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return)) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.trigger_pagefault_end_jit) (i32.store diff --git a/tests/expect/tests/mov16.wast b/tests/expect/tests/mov16.wast index 683ac92a..43317d98 100644 --- a/tests/expect/tests/mov16.wast +++ b/tests/expect/tests/mov16.wast @@ -28,28 +28,28 @@ (i32.const 10000)) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (loop $L0 (set_local $l1 (i32.add @@ -60,28 +60,28 @@ (get_local $l1)) (then (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return))) (block $B2 @@ -390,54 +390,54 @@ (i32.const 556)) (i32.const 32))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.instr_F4) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (i32.store (i32.const 664) (i32.add @@ -445,53 +445,53 @@ (i32.const 664)) (i32.const 12))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return)) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.trigger_pagefault_end_jit) (i32.store diff --git a/tests/expect/tests/mov32-mem.wast b/tests/expect/tests/mov32-mem.wast index 363d0b7f..63502edf 100644 --- a/tests/expect/tests/mov32-mem.wast +++ b/tests/expect/tests/mov32-mem.wast @@ -28,28 +28,28 @@ (i32.const 10000)) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (loop $L0 (set_local $l1 (i32.add @@ -60,28 +60,28 @@ (get_local $l1)) (then (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return))) (block $B2 @@ -302,54 +302,54 @@ (i32.const 556)) (i32.const 25))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.instr_F4) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (i32.store (i32.const 664) (i32.add @@ -357,53 +357,53 @@ (i32.const 664)) (i32.const 5))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return)) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.trigger_pagefault_end_jit) (i32.store diff --git a/tests/expect/tests/mov32-reg.wast b/tests/expect/tests/mov32-reg.wast index 30ac8ccc..d344ce76 100644 --- a/tests/expect/tests/mov32-reg.wast +++ b/tests/expect/tests/mov32-reg.wast @@ -26,28 +26,28 @@ (i32.const 10000)) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (loop $L0 (set_local $l1 (i32.add @@ -58,28 +58,28 @@ (get_local $l1)) (then (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return))) (block $B2 @@ -116,54 +116,54 @@ (i32.const 556)) (i32.const 29))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.instr_F4) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (i32.store (i32.const 664) (i32.add @@ -171,53 +171,53 @@ (i32.const 664)) (i32.const 9))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return)) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.trigger_pagefault_end_jit) (i32.store diff --git a/tests/expect/tests/pop.wast b/tests/expect/tests/pop.wast index bf17df2d..03d9bea4 100644 --- a/tests/expect/tests/pop.wast +++ b/tests/expect/tests/pop.wast @@ -27,28 +27,28 @@ (i32.const 10000)) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (loop $L0 (set_local $l1 (i32.add @@ -59,28 +59,28 @@ (get_local $l1)) (then (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return))) (block $B2 @@ -151,54 +151,54 @@ (i32.const 556)) (i32.const 2))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.instr_F4) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (i32.store (i32.const 664) (i32.add @@ -206,53 +206,53 @@ (i32.const 664)) (i32.const 2))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return)) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.trigger_pagefault_end_jit) (i32.store diff --git a/tests/expect/tests/push.wast b/tests/expect/tests/push.wast index b22e8acc..1ba828ff 100644 --- a/tests/expect/tests/push.wast +++ b/tests/expect/tests/push.wast @@ -27,28 +27,28 @@ (i32.const 10000)) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (loop $L0 (set_local $l1 (i32.add @@ -59,28 +59,28 @@ (get_local $l1)) (then (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return))) (block $B2 @@ -156,54 +156,54 @@ (i32.const 556)) (i32.const 2))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.instr_F4) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (i32.store (i32.const 664) (i32.add @@ -211,53 +211,53 @@ (i32.const 664)) (i32.const 2))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return)) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.trigger_pagefault_end_jit) (i32.store diff --git a/tests/expect/tests/task_switch_test.wast b/tests/expect/tests/task_switch_test.wast index a15402eb..4f36f5e5 100644 --- a/tests/expect/tests/task_switch_test.wast +++ b/tests/expect/tests/task_switch_test.wast @@ -30,28 +30,28 @@ (i32.const 10000)) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (loop $L0 (set_local $l1 (i32.add @@ -62,28 +62,28 @@ (get_local $l1)) (then (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return))) (block $B2 @@ -98,28 +98,28 @@ (i32.const 12)) (then (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.task_switch_test_void) (i32.store @@ -144,54 +144,54 @@ (i32.const 556)) (i32.const 3))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.instr_F4) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (i32.store (i32.const 664) (i32.add @@ -199,53 +199,53 @@ (i32.const 664)) (i32.const 2))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return)) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.trigger_pagefault_end_jit) (i32.store diff --git a/tests/expect/tests/task_switch_test_sse.wast b/tests/expect/tests/task_switch_test_sse.wast index 77c9995e..1d624be7 100644 --- a/tests/expect/tests/task_switch_test_sse.wast +++ b/tests/expect/tests/task_switch_test_sse.wast @@ -28,28 +28,28 @@ (i32.const 10000)) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (loop $L0 (set_local $l1 (i32.add @@ -60,28 +60,28 @@ (get_local $l1)) (then (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return))) (block $B2 @@ -113,28 +113,28 @@ (i32.const 12)) (then (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.task_switch_test_mmx_void) (i32.store @@ -142,56 +142,56 @@ (i32.const 0)) (return))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.instr_660F54_reg (i32.const 1) (i32.const 0)) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (i32.store (i32.const 648) (i32.const 0)) @@ -202,28 +202,28 @@ (i32.const 664)) (i32.const 1))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return)) (i32.store @@ -237,54 +237,54 @@ (i32.const 556)) (i32.const 1))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.instr_F4) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (i32.store (i32.const 664) (i32.add @@ -292,53 +292,53 @@ (i32.const 664)) (i32.const 1))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return)) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.trigger_pagefault_end_jit) (i32.store diff --git a/tests/expect/tests/while-do.wast b/tests/expect/tests/while-do.wast index d16c0db9..46ece593 100644 --- a/tests/expect/tests/while-do.wast +++ b/tests/expect/tests/while-do.wast @@ -27,28 +27,28 @@ (i32.const 10000)) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (loop $L0 (set_local $l1 (i32.add @@ -59,28 +59,28 @@ (get_local $l1)) (then (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return))) (block $B2 @@ -99,22 +99,22 @@ (get_local $l11) (get_local $l10))) (i32.store - (i32.const 512) + (i32.const 96) (get_local $l12)) (i32.store - (i32.const 516) + (i32.const 100) (get_local $l10)) (i32.store - (i32.const 524) + (i32.const 108) (get_local $l11)) (i32.store - (i32.const 528) + (i32.const 112) (get_local $l12)) (i32.store - (i32.const 520) + (i32.const 104) (i32.const 31)) (i32.store - (i32.const 532) + (i32.const 116) (i32.const 2261)) (i32.store (i32.const 560) @@ -138,7 +138,7 @@ (if $I7 (result i32) (i32.and (i32.load - (i32.const 532)) + (i32.const 116)) (i32.const 64)) (then (i32.and @@ -147,18 +147,18 @@ (i32.xor (tee_local $l12 (i32.load - (i32.const 528))) + (i32.const 112))) (i32.const -1)) (i32.sub (get_local $l12) (i32.const 1))) (i32.load - (i32.const 520))) + (i32.const 104))) (i32.const 1))) (else (i32.and (i32.load - (i32.const 536)) + (i32.const 120)) (i32.const 64)))) (then (i32.store @@ -214,54 +214,54 @@ (i32.const 556)) (i32.const 1))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.instr_F4) (set_local $l2 (i32.load - (i32.const 4))) + (i32.const 64))) (set_local $l3 (i32.load - (i32.const 8))) + (i32.const 68))) (set_local $l4 (i32.load - (i32.const 12))) + (i32.const 72))) (set_local $l5 (i32.load - (i32.const 16))) + (i32.const 76))) (set_local $l6 (i32.load - (i32.const 20))) + (i32.const 80))) (set_local $l7 (i32.load - (i32.const 24))) + (i32.const 84))) (set_local $l8 (i32.load - (i32.const 28))) + (i32.const 88))) (set_local $l9 (i32.load - (i32.const 32))) + (i32.const 92))) (i32.store (i32.const 664) (i32.add @@ -269,53 +269,53 @@ (i32.const 664)) (i32.const 1))) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (return)) (i32.store - (i32.const 4) + (i32.const 64) (get_local $l2)) (i32.store - (i32.const 8) + (i32.const 68) (get_local $l3)) (i32.store - (i32.const 12) + (i32.const 72) (get_local $l4)) (i32.store - (i32.const 16) + (i32.const 76) (get_local $l5)) (i32.store - (i32.const 20) + (i32.const 80) (get_local $l6)) (i32.store - (i32.const 24) + (i32.const 84) (get_local $l7)) (i32.store - (i32.const 28) + (i32.const 88) (get_local $l8)) (i32.store - (i32.const 32) + (i32.const 92) (get_local $l9)) (call $e.trigger_pagefault_end_jit) (i32.store From 4619d4dd6d21fc19b0907b4862e0d42e5afb5a54 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1602/2137] Add info to assertion --- src/ide.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ide.js b/src/ide.js index 3bc80571..623bdc6c 100644 --- a/src/ide.js +++ b/src/ide.js @@ -1487,7 +1487,9 @@ IDEInterface.prototype.write_end = function() } else { - dbg_assert(this.current_command === 0x30 || this.current_command === 0x34); + dbg_assert(this.current_command === 0x30 || this.current_command === 0x34, + "Unexpected command: " + h(this.current_command)); + // XXX: Should advance here, but do_write does all the advancing //this.ata_advance(this.current_command, 1); this.status = 0x58; From 4bb3c14e57b03163374e7df6f0c0b5a8642a4bd7 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1603/2137] Comment --- gen/generate_analyzer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/gen/generate_analyzer.js b/gen/generate_analyzer.js index 0e9463f8..ff2171f5 100755 --- a/gen/generate_analyzer.js +++ b/gen/generate_analyzer.js @@ -217,6 +217,7 @@ function gen_instruction_body_after_fixed_g(encoding, size) const imm_read = gen_read_imm_call(encoding, size); const instruction_postfix = []; + // jump_offset_imm: Is a block boundary, but gets a different type (Jump) below if(encoding.block_boundary && !encoding.jump_offset_imm || (!encoding.custom && encoding.e)) { instruction_postfix.push("analysis.ty = ::analysis::AnalysisType::BlockBoundary;"); From 78ef12be681f47eaf1e60ba7864baea41eff114a Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1604/2137] Custom implementations for several sse instructions - mov dword/qword [mem], xmm - mov xmm, dword/qword [mem] - some arithmetic --- gen/x86_table.js | 36 +++--- src/rust/cpu2/instructions_0f.rs | 2 +- src/rust/global_pointers.rs | 1 + src/rust/jit_instructions.rs | 212 +++++++++++++++++++++++++++++++ src/rust/wasmgen/wasm_util.rs | 7 + 5 files changed, 239 insertions(+), 19 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 52497fc9..6cc5569d 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -724,9 +724,9 @@ const encodings = [ { sse: 1, opcode: 0xF20F5F, e: 1, }, { sse: 1, opcode: 0xF30F5F, e: 1, }, - { sse: 1, opcode: 0x660F60, e: 1 }, + { sse: 1, opcode: 0x660F60, e: 1, custom: 1 }, { sse: 1, opcode: 0x0F60, e: 1 }, - { sse: 1, opcode: 0x660F61, e: 1 }, + { sse: 1, opcode: 0x660F61, e: 1, custom: 1 }, { sse: 1, opcode: 0x0F61, e: 1 }, { sse: 1, opcode: 0x660F62, e: 1 }, { sse: 1, opcode: 0x0F62, e: 1 }, @@ -738,10 +738,10 @@ const encodings = [ { sse: 1, opcode: 0x0F65, e: 1 }, { sse: 1, opcode: 0x660F66, e: 1 }, { sse: 1, opcode: 0x0F66, e: 1 }, - { sse: 1, opcode: 0x660F67, e: 1 }, + { sse: 1, opcode: 0x660F67, e: 1, custom: 1 }, { sse: 1, opcode: 0x0F67, e: 1 }, - { sse: 1, opcode: 0x660F68, e: 1 }, + { sse: 1, opcode: 0x660F68, e: 1, custom: 1 }, { sse: 1, opcode: 0x0F68, e: 1 }, { sse: 1, opcode: 0x660F69, e: 1 }, { sse: 1, opcode: 0x0F69, e: 1 }, @@ -753,16 +753,16 @@ const encodings = [ { sse: 1, opcode: 0x0F6C, e: 1, block_boundary: 1, }, // ud { sse: 1, opcode: 0x660F6D, e: 1 }, { sse: 1, opcode: 0x0F6D, e: 1, block_boundary: 1, }, // ud - { sse: 1, opcode: 0x660F6E, e: 1 }, + { sse: 1, opcode: 0x660F6E, e: 1, custom: 1 }, { sse: 1, opcode: 0x0F6E, e: 1 }, { sse: 1, opcode: 0xF30F6F, e: 1, custom: 1 }, { sse: 1, opcode: 0x660F6F, e: 1, custom: 1 }, { sse: 1, opcode: 0x0F6F, e: 1 }, { sse: 1, opcode: 0x0F70, e: 1, imm8: 1, }, - { sse: 1, opcode: 0x660F70, e: 1, imm8: 1, }, - { sse: 1, opcode: 0xF20F70, e: 1, imm8: 1, }, - { sse: 1, opcode: 0xF30F70, e: 1, imm8: 1, }, + { sse: 1, opcode: 0x660F70, e: 1, imm8: 1, custom: 1 }, + { sse: 1, opcode: 0xF20F70, e: 1, imm8: 1, custom: 1 }, + { sse: 1, opcode: 0xF30F70, e: 1, imm8: 1, custom: 1 }, { sse: 1, opcode: 0x0F71, e: 1, fixed_g: 2, imm8: 1, mem_ud: 1, }, { sse: 1, opcode: 0x660F71, e: 1, fixed_g: 2, imm8: 1, mem_ud: 1 }, @@ -786,7 +786,7 @@ const encodings = [ { sse: 1, opcode: 0x660F73, e: 1, fixed_g: 7, imm8: 1, mem_ud: 1 }, { sse: 1, opcode: 0x0F74, e: 1, }, - { sse: 1, opcode: 0x660F74, e: 1, }, + { sse: 1, opcode: 0x660F74, e: 1, custom: 1 }, { sse: 1, opcode: 0x0F75, e: 1, }, { sse: 1, opcode: 0x660F75, e: 1, }, { sse: 1, opcode: 0x0F76, e: 1, }, @@ -803,8 +803,8 @@ const encodings = [ { sse: 1, opcode: 0x0F7D, skip: 1, block_boundary: 1, }, // sse3 { sse: 1, opcode: 0x0F7E, e: 1 }, - { sse: 1, opcode: 0x660F7E, e: 1 }, - { sse: 1, opcode: 0xF30F7E, e: 1 }, + { sse: 1, opcode: 0x660F7E, e: 1, custom: 1 }, + { sse: 1, opcode: 0xF30F7E, e: 1, custom: 1 }, { sse: 1, opcode: 0x0F7F, e: 1 }, { sse: 1, opcode: 0x660F7F, e: 1, custom: 1 }, { sse: 1, opcode: 0xF30F7F, e: 1, custom: 1 }, @@ -835,9 +835,9 @@ const encodings = [ { sse: 1, opcode: 0x0FD4, e: 1 }, { sse: 1, opcode: 0x660FD4, e: 1 }, { sse: 1, opcode: 0x0FD5, e: 1 }, - { sse: 1, opcode: 0x660FD5, e: 1 }, + { sse: 1, opcode: 0x660FD5, e: 1, custom: 1 }, - { sse: 1, opcode: 0x660FD6, e: 1 }, + { sse: 1, opcode: 0x660FD6, e: 1, custom: 1 }, { sse: 1, opcode: 0xF20FD6, mem_ud: 1, e: 1 }, { sse: 1, opcode: 0xF30FD6, mem_ud: 1, e: 1 }, { sse: 1, opcode: 0x0FD6, e: 1, block_boundary: 1, }, // ud @@ -854,9 +854,9 @@ const encodings = [ { sse: 1, opcode: 0x0FDB, e: 1 }, { sse: 1, opcode: 0x660FDB, e: 1 }, { sse: 1, opcode: 0x0FDC, e: 1 }, - { sse: 1, opcode: 0x660FDC, e: 1 }, + { sse: 1, opcode: 0x660FDC, e: 1, custom: 1 }, { sse: 1, opcode: 0x0FDD, e: 1 }, - { sse: 1, opcode: 0x660FDD, e: 1 }, + { sse: 1, opcode: 0x660FDD, e: 1, custom: 1 }, { sse: 1, opcode: 0x0FDE, e: 1 }, { sse: 1, opcode: 0x660FDE, e: 1 }, { sse: 1, opcode: 0x0FDF, e: 1 }, @@ -871,7 +871,7 @@ const encodings = [ { sse: 1, opcode: 0x0FE3, e: 1 }, { sse: 1, opcode: 0x660FE3, e: 1 }, { sse: 1, opcode: 0x0FE4, e: 1 }, - { sse: 1, opcode: 0x660FE4, e: 1 }, + { sse: 1, opcode: 0x660FE4, e: 1, custom: 1 }, { sse: 1, opcode: 0x0FE5, e: 1 }, { sse: 1, opcode: 0x660FE5, e: 1 }, @@ -889,7 +889,7 @@ const encodings = [ { sse: 1, opcode: 0x0FEA, e: 1 }, { sse: 1, opcode: 0x660FEA, e: 1 }, { sse: 1, opcode: 0x0FEB, e: 1 }, - { sse: 1, opcode: 0x660FEB, e: 1 }, + { sse: 1, opcode: 0x660FEB, e: 1, custom: 1 }, { sse: 1, opcode: 0x0FEC, e: 1 }, { sse: 1, opcode: 0x660FEC, e: 1 }, { sse: 1, opcode: 0x0FED, e: 1 }, @@ -897,7 +897,7 @@ const encodings = [ { sse: 1, opcode: 0x0FEE, e: 1 }, { sse: 1, opcode: 0x660FEE, e: 1 }, { sse: 1, opcode: 0x0FEF, e: 1 }, - { sse: 1, opcode: 0x660FEF, e: 1 }, + { sse: 1, opcode: 0x660FEF, e: 1, custom: 1 }, { sse: 1, opcode: 0x0FF0, skip: 1, block_boundary: 1, }, // sse3 diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 0310bf06..0152e1bb 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -2460,7 +2460,7 @@ pub unsafe fn instr_0F70_mem(addr: i32, r: i32, imm: i32) { } #[no_mangle] pub unsafe fn instr_660F70(source: reg128, r: i32, imm8: i32) { - // pshufd xmm, xmm/mem128 + // pshufd xmm, xmm/mem128, imm8 // XXX: Aligned access or #gp write_xmm128( r, diff --git a/src/rust/global_pointers.rs b/src/rust/global_pointers.rs index d1e1a190..16822fa3 100644 --- a/src/rust/global_pointers.rs +++ b/src/rust/global_pointers.rs @@ -17,6 +17,7 @@ pub const SREG: u32 = 668; pub const SEGMENT_OFFSETS: u32 = 736; pub const REG_XMM: u32 = 832; pub const FPU_CONTROL_WORD: u32 = 1036; +pub const SSE_SCRATCH_REGISTER: u32 = 1040; pub const OPSTATS_BUFFER: u32 = 0x08000; pub const OPSTATS_UNGUARDED_REGISTER_BUFFER: u32 = 0x20000; pub const TLB_DATA: u32 = 0x400000; diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 45f006d8..989d0157 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -101,6 +101,21 @@ pub fn instr_F3_jit(ctx: &mut JitContext, instr_flags: &mut u32) { jit_handle_prefix(ctx, instr_flags) } +pub fn sse_read128_xmm_mem(ctx: &mut JitContext, name: &str, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let dest = global_pointers::SSE_SCRATCH_REGISTER; + codegen::gen_safe_read128(ctx, dest); + ctx.builder.instruction_body.const_i32(dest as i32); + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_call_fn2(ctx.builder, name); +} +pub fn sse_read128_xmm_xmm(ctx: &mut JitContext, name: &str, r1: u32, r2: u32) { + let dest = global_pointers::get_reg_xmm_low_offset(r1); + ctx.builder.instruction_body.const_i32(dest as i32); + ctx.builder.instruction_body.const_i32(r2 as i32); + codegen::gen_call_fn2(ctx.builder, name); +} + fn push16_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_get_reg16(ctx, r); let value_local = ctx.builder.set_new_local(); @@ -4373,6 +4388,48 @@ pub fn instr_660F29_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { instr_0F29_reg_jit(ctx, r1, r2) } +pub fn instr_660F60_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + // Note: Only requires 64-bit read, but is allowed to do 128-bit read. Interpreted mode does + // 64-bit read. + sse_read128_xmm_mem(ctx, "instr_660F60", modrm_byte, r); +} +pub fn instr_660F60_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + sse_read128_xmm_xmm(ctx, "instr_660F60", r1, r2); +} +pub fn instr_660F61_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + // Note: Only requires 64-bit read, but is allowed to do 128-bit read. Interpreted mode does + // 64-bit read. + sse_read128_xmm_mem(ctx, "instr_660F61", modrm_byte, r); +} +pub fn instr_660F61_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + sse_read128_xmm_xmm(ctx, "instr_660F61", r1, r2); +} + +pub fn instr_660F67_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + sse_read128_xmm_mem(ctx, "instr_660F67", modrm_byte, r); +} +pub fn instr_660F67_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + sse_read128_xmm_xmm(ctx, "instr_660F67", r1, r2); +} +pub fn instr_660F68_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + sse_read128_xmm_mem(ctx, "instr_660F68", modrm_byte, r); +} +pub fn instr_660F68_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + sse_read128_xmm_xmm(ctx, "instr_660F68", r1, r2); +} + +pub fn instr_660F6E_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read32(ctx); + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_call_fn2(ctx.builder, "instr_660F6E") +} +pub fn instr_660F6E_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + codegen::gen_get_reg32(ctx, r1); + ctx.builder.instruction_body.const_i32(r2 as i32); + codegen::gen_call_fn2(ctx.builder, "instr_660F6E") +} + pub fn instr_660F6F_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { // XXX: Aligned read or #gp codegen::gen_modrm_resolve(ctx, modrm_byte); @@ -4395,6 +4452,103 @@ pub fn instr_F30F6F_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_call_fn2(ctx.builder, "instr_F30F6F_reg") } +pub fn instr_660F70_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let imm8 = ctx.cpu.read_imm8(); + let dest = global_pointers::SSE_SCRATCH_REGISTER; + codegen::gen_safe_read128(ctx, dest); + ctx.builder.instruction_body.const_i32(dest as i32); + ctx.builder.instruction_body.const_i32(r as i32); + ctx.builder.instruction_body.const_i32(imm8 as i32); + codegen::gen_call_fn3(ctx.builder, "instr_660F70"); +} +pub fn instr_660F70_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm8: u32) { + let dest = global_pointers::get_reg_xmm_low_offset(r1); + ctx.builder.instruction_body.const_i32(dest as i32); + ctx.builder.instruction_body.const_i32(r2 as i32); + ctx.builder.instruction_body.const_i32(imm8 as i32); + codegen::gen_call_fn3(ctx.builder, "instr_660F70"); +} +pub fn instr_F20F70_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let imm8 = ctx.cpu.read_imm8(); + let dest = global_pointers::SSE_SCRATCH_REGISTER; + codegen::gen_safe_read128(ctx, dest); + ctx.builder.instruction_body.const_i32(dest as i32); + ctx.builder.instruction_body.const_i32(r as i32); + ctx.builder.instruction_body.const_i32(imm8 as i32); + codegen::gen_call_fn3(ctx.builder, "instr_F20F70"); +} +pub fn instr_F20F70_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm8: u32) { + let dest = global_pointers::get_reg_xmm_low_offset(r1); + ctx.builder.instruction_body.const_i32(dest as i32); + ctx.builder.instruction_body.const_i32(r2 as i32); + ctx.builder.instruction_body.const_i32(imm8 as i32); + codegen::gen_call_fn3(ctx.builder, "instr_F20F70"); +} +pub fn instr_F30F70_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let imm8 = ctx.cpu.read_imm8(); + let dest = global_pointers::SSE_SCRATCH_REGISTER; + codegen::gen_safe_read128(ctx, dest); + ctx.builder.instruction_body.const_i32(dest as i32); + ctx.builder.instruction_body.const_i32(r as i32); + ctx.builder.instruction_body.const_i32(imm8 as i32); + codegen::gen_call_fn3(ctx.builder, "instr_F30F70"); +} +pub fn instr_F30F70_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm8: u32) { + let dest = global_pointers::get_reg_xmm_low_offset(r1); + ctx.builder.instruction_body.const_i32(dest as i32); + ctx.builder.instruction_body.const_i32(r2 as i32); + ctx.builder.instruction_body.const_i32(imm8 as i32); + codegen::gen_call_fn3(ctx.builder, "instr_F30F70"); +} + +pub fn instr_660F74_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + sse_read128_xmm_mem(ctx, "instr_660F74", modrm_byte, r); +} +pub fn instr_660F74_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + sse_read128_xmm_xmm(ctx, "instr_660F74", r1, r2); +} + +pub fn instr_660F7E_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_reg_xmm_low_offset(r)); + let value_local = ctx.builder.set_new_local(); + codegen::gen_safe_write32(ctx, &address_local, &value_local); + ctx.builder.free_local(address_local); + ctx.builder.free_local(value_local); +} +pub fn instr_660F7E_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + ctx.builder + .instruction_body + .load_aligned_i32(global_pointers::get_reg_xmm_low_offset(r2)); + codegen::gen_set_reg32(ctx, r1); +} + +pub fn instr_F30F7E_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg_xmm_low_offset(r) as i32); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read64(ctx); + ctx.builder.instruction_body.store_aligned_i64(0); + + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg_xmm_high_offset(r) as i32); + ctx.builder.instruction_body.const_i64(0); + ctx.builder.instruction_body.store_aligned_i64(0); +} +pub fn instr_F30F7E_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + ctx.builder.instruction_body.const_i32(r1 as i32); + ctx.builder.instruction_body.const_i32(r2 as i32); + codegen::gen_call_fn2(ctx.builder, "instr_F30F7E_reg"); +} + pub fn instr_660F7F_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { instr_0F29_mem_jit(ctx, modrm_byte, r); } @@ -4440,3 +4594,61 @@ pub fn instr_0FAE_5_mem_jit(ctx: &mut JitContext, _modrm_byte: u8) { pub fn instr_0FAE_5_reg_jit(_ctx: &mut JitContext, r: u32) { dbg_assert!(r == 0, "Unexpected lfence encoding"); } + +pub fn instr_660FD6_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + + ctx.builder + .instruction_body + .const_i32(global_pointers::get_reg_xmm_low_offset(r) as i32); + ctx.builder.instruction_body.load_aligned_i64_from_stack(0); + let value_local = ctx.builder.set_new_local_i64(); + + codegen::gen_safe_write64(ctx, &address_local, &value_local); + ctx.builder.free_local(address_local); + ctx.builder.free_local_i64(value_local); +} +pub fn instr_660FD6_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + ctx.builder.instruction_body.const_i32(r1 as i32); + ctx.builder.instruction_body.const_i32(r2 as i32); + codegen::gen_call_fn2(ctx.builder, "instr_660FD6_reg"); +} + +pub fn instr_660FDC_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + sse_read128_xmm_mem(ctx, "instr_660FDC", modrm_byte, r); +} +pub fn instr_660FDC_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + sse_read128_xmm_xmm(ctx, "instr_660FDC", r1, r2); +} +pub fn instr_660FDD_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + sse_read128_xmm_mem(ctx, "instr_660FDD", modrm_byte, r); +} +pub fn instr_660FDD_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + sse_read128_xmm_xmm(ctx, "instr_660FDD", r1, r2); +} +pub fn instr_660FD5_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + sse_read128_xmm_mem(ctx, "instr_660FD5", modrm_byte, r); +} +pub fn instr_660FD5_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + sse_read128_xmm_xmm(ctx, "instr_660FD5", r1, r2); +} + +pub fn instr_660FE4_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + sse_read128_xmm_mem(ctx, "instr_660FE4", modrm_byte, r); +} +pub fn instr_660FE4_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + sse_read128_xmm_xmm(ctx, "instr_660FE4", r1, r2); +} +pub fn instr_660FEB_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + sse_read128_xmm_mem(ctx, "instr_660FEB", modrm_byte, r); +} +pub fn instr_660FEB_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + sse_read128_xmm_xmm(ctx, "instr_660FEB", r1, r2); +} +pub fn instr_660FEF_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { + sse_read128_xmm_mem(ctx, "instr_660FEF", modrm_byte, r); +} +pub fn instr_660FEF_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + sse_read128_xmm_xmm(ctx, "instr_660FEF", r1, r2); +} diff --git a/src/rust/wasmgen/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs index befa037c..6524852c 100644 --- a/src/rust/wasmgen/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -41,6 +41,7 @@ pub trait WasmBuf { fn store_u8(&mut self, byte_offset: u32); fn store_aligned_u16(&mut self, byte_offset: u32); fn store_aligned_i32(&mut self, byte_offset: u32); + fn store_aligned_i64(&mut self, byte_offset: u32); fn store_unaligned_u16(&mut self, byte_offset: u32); fn store_unaligned_i32(&mut self, byte_offset: u32); fn store_unaligned_i64(&mut self, byte_offset: u32); @@ -226,6 +227,12 @@ impl WasmBuf for Vec { self.write_leb_u32(byte_offset); } + fn store_aligned_i64(&mut self, byte_offset: u32) { + self.push(op::OP_I64STORE); + self.push(op::MEM_ALIGN64); + self.write_leb_u32(byte_offset); + } + fn store_unaligned_u16(&mut self, byte_offset: u32) { self.push(op::OP_I32STORE16); self.push(op::MEM_NO_ALIGN); From f98f423d1bbb8439c3d874261cf734e82e402d08 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1605/2137] Comment --- src/rust/cpu2/cpu.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index db4dd5e8..b7079b86 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -69,7 +69,9 @@ pub union reg128 { pub f64_0: [f64; 2], } +/// Setting this to true will make execution extremely slow pub const CHECK_MISSED_ENTRY_POINTS: bool = false; + pub const INTERPRETER_ITERATION_LIMIT: u32 = 1000; pub const FLAG_CARRY: i32 = 1; From 1de8fe1888967b1aef17dbeabd21607f921c7782 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1606/2137] Fix unnecessary push to stack --- src/rust/jit_instructions.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 989d0157..b114a82a 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -3005,9 +3005,6 @@ pub fn instr_D9_6_reg_jit(ctx: &mut JitContext, r: u32) { pub fn instr_D9_7_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); - ctx.builder - .instruction_body - .const_i32(global_pointers::FPU_CONTROL_WORD as i32); ctx.builder .instruction_body .const_i32(global_pointers::FPU_CONTROL_WORD as i32); From 1278672998321b1a49a7274bd570368ab192c2c1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1607/2137] Split modrm stat into reg_with_offset and complex --- src/browser/print_stats.js | 1 + src/rust/modrm.rs | 2 +- src/rust/profiler.rs | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index abec840a..f496bd6d 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -68,6 +68,7 @@ const print_stats = { "TLB_FULL", "TLB_GLOBAL_FULL", "MODRM_SIMPLE_REG", + "MODRM_SIMPLE_REG_WITH_OFFSET", "MODRM_COMPLEX", ]; diff --git a/src/rust/modrm.rs b/src/rust/modrm.rs index 14f349ee..e8e6b8ba 100644 --- a/src/rust/modrm.rs +++ b/src/rust/modrm.rs @@ -213,7 +213,7 @@ fn gen32_case(ctx: &mut JitContext, seg: u32, offset: Offset, imm: Imm32) { if immediate_value != 0 { ctx.builder.instruction_body.const_i32(immediate_value); ctx.builder.instruction_body.add_i32(); - profiler::stat_increment(profiler::stat::MODRM_COMPLEX); + profiler::stat_increment(profiler::stat::MODRM_SIMPLE_REG_WITH_OFFSET); } else { profiler::stat_increment(profiler::stat::MODRM_SIMPLE_REG); diff --git a/src/rust/profiler.rs b/src/rust/profiler.rs index f89b8c7a..63f1788c 100644 --- a/src/rust/profiler.rs +++ b/src/rust/profiler.rs @@ -66,6 +66,7 @@ pub enum stat { TLB_GLOBAL_FULL, MODRM_SIMPLE_REG, + MODRM_SIMPLE_REG_WITH_OFFSET, MODRM_COMPLEX, } From bc3c73a607fbe09ce190f095de8f033543ced0e5 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1608/2137] wasm state machine: Fallthrough --- src/rust/jit.rs | 57 ++++++++++++++++++++++---------- tests/expect/tests/do-while.wast | 7 ++-- tests/expect/tests/if.wast | 12 ++----- tests/expect/tests/while-do.wast | 7 ++-- 4 files changed, 46 insertions(+), 37 deletions(-) diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 50ef3dee..3b9185a7 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -1081,15 +1081,22 @@ fn jit_generate_module( // - All instructions that don't change eip // - Unconditional jump - let next_bb_index = *basic_block_indices + let next_basic_block_index = *basic_block_indices .get(&next_block_addr) .expect("basic_block_indices.get (Normal)"); - // set state variable to next basic block - ctx.builder.instruction_body.const_i32(next_bb_index as i32); - ctx.builder.instruction_body.set_local(&gen_local_state); + if next_basic_block_index == (i as u32) + 1 { + // fallthru + } + else { + // set state variable to next basic block + ctx.builder + .instruction_body + .const_i32(next_basic_block_index as i32); + ctx.builder.instruction_body.set_local(&gen_local_state); - ctx.builder.instruction_body.br(ctx.current_brtable_depth); // to the loop + ctx.builder.instruction_body.br(ctx.current_brtable_depth); // to the loop + } }, &BasicBlockType::ConditionalJump { next_block_addr, @@ -1122,6 +1129,10 @@ fn jit_generate_module( .instruction_body .const_i32(next_basic_block_branch_taken_index as i32); ctx.builder.instruction_body.set_local(&gen_local_state); + + ctx.builder + .instruction_body + .br(basic_blocks.len() as u32 + 2 - i as u32); // to the loop } else { // Jump to different page @@ -1130,32 +1141,42 @@ fn jit_generate_module( ctx.builder.instruction_body.return_(); } - ctx.builder.instruction_body.else_(); - if let Some(next_block_addr) = next_block_addr { // Branch not taken - // TODO: Could use fall-through here + let next_basic_block_index = *basic_block_indices .get(&next_block_addr) .expect("basic_block_indices.get (branch not taken)"); - ctx.builder - .instruction_body - .const_i32(next_basic_block_index as i32); - ctx.builder.instruction_body.set_local(&gen_local_state); + if next_basic_block_index == (i as u32) + 1 { + // fallthru + ctx.builder.instruction_body.block_end(); + } + else { + ctx.builder.instruction_body.else_(); + + ctx.builder + .instruction_body + .const_i32(next_basic_block_index as i32); + ctx.builder.instruction_body.set_local(&gen_local_state); + + ctx.builder + .instruction_body + .br(basic_blocks.len() as u32 + 2 - i as u32); // to the loop + + ctx.builder.instruction_body.block_end(); + } } else { + ctx.builder.instruction_body.else_(); + // End of this page codegen::gen_debug_track_jit_exit(ctx.builder, block.last_instruction_addr); codegen::gen_move_registers_from_locals_to_memory(ctx); ctx.builder.instruction_body.return_(); + + ctx.builder.instruction_body.block_end(); } - - ctx.builder.instruction_body.block_end(); - - ctx.builder - .instruction_body - .br(basic_blocks.len() as u32 + 1 - i as u32); // to the loop }, } } diff --git a/tests/expect/tests/do-while.wast b/tests/expect/tests/do-while.wast index 7391ae34..98aa9258 100644 --- a/tests/expect/tests/do-while.wast +++ b/tests/expect/tests/do-while.wast @@ -171,11 +171,8 @@ (i32.const 556)) (i32.const -6))) (set_local $l0 - (i32.const 0))) - (else - (set_local $l0 - (i32.const 1)))) - (br $L0)) + (i32.const 0)) + (br $L0)))) (i32.store (i32.const 560) (i32.load diff --git a/tests/expect/tests/if.wast b/tests/expect/tests/if.wast index a6a42250..84c21142 100644 --- a/tests/expect/tests/if.wast +++ b/tests/expect/tests/if.wast @@ -145,11 +145,8 @@ (i32.const 556)) (i32.const 1))) (set_local $l0 - (i32.const 2))) - (else - (set_local $l0 - (i32.const 1)))) - (br $L0)) + (i32.const 2)) + (br $L0)))) (i32.store (i32.const 560) (i32.load @@ -168,10 +165,7 @@ (i32.add (i32.load (i32.const 664)) - (i32.const 1))) - (set_local $l0 - (i32.const 2)) - (br $L0)) + (i32.const 1)))) (set_local $l5 (call $e.inc32 (get_local $l5))) diff --git a/tests/expect/tests/while-do.wast b/tests/expect/tests/while-do.wast index 46ece593..a62a0025 100644 --- a/tests/expect/tests/while-do.wast +++ b/tests/expect/tests/while-do.wast @@ -168,11 +168,8 @@ (i32.const 556)) (i32.const 3))) (set_local $l0 - (i32.const 2))) - (else - (set_local $l0 - (i32.const 1)))) - (br $L0)) + (i32.const 2)) + (br $L0)))) (set_local $l5 (call $e.inc32 (get_local $l5))) From 1fa0430cb507805b7863ff21683d48b8214cb1c3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1609/2137] Remove unused macro rules --- src/rust/jit_instructions.rs | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index b114a82a..2ae1b7b0 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -251,21 +251,6 @@ macro_rules! define_instruction_read16( ); macro_rules! define_instruction_read32( - ($fn:expr, $name_mem:ident, $name_reg:ident) => ( - pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read32(ctx); - codegen::gen_get_reg32(ctx, r); - codegen::gen_call_fn2(ctx.builder, $fn) - } - - pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { - codegen::gen_get_reg32(ctx, r1); - codegen::gen_get_reg32(ctx, r2); - codegen::gen_call_fn2(ctx.builder, $fn) - } - ); - ($fn:expr, $name_mem:ident, $name_reg:ident, xreg) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); @@ -310,21 +295,6 @@ macro_rules! define_instruction_read32( $fn(ctx.builder); } ); - - ($fn:expr, $name_mem:ident, $name_reg:ident, $imm:ident) => ( - pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read32(ctx); - ctx.builder.instruction_body.const_i32(make_imm_read!(ctx, $imm) as i32); - codegen::gen_call_fn2(ctx.builder, $fn) - } - - pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { - codegen::gen_get_reg32(ctx, r1); - ctx.builder.instruction_body.const_i32(imm as i32); - codegen::gen_call_fn2(ctx.builder, $fn) - } - ); ); macro_rules! define_instruction_write_reg8( From 43fcdf9fc2c532cee3568b8eeac4819de676a09c Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1610/2137] Introduce LocalOrImmediate for more efficient parameter passing to cmp/test instructions --- src/rust/jit_instructions.rs | 170 +++++++++++++++++++++---------- tests/expect/tests/do-while.wast | 24 ++--- tests/expect/tests/if.wast | 20 ++-- tests/expect/tests/while-do.wast | 24 ++--- 4 files changed, 147 insertions(+), 91 deletions(-) diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 2ae1b7b0..2fd2dce2 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -16,9 +16,23 @@ use regs; use regs::{AX, BP, BX, CX, DI, DX, SI, SP}; use regs::{CS, DS, ES, FS, GS, SS}; use regs::{EAX, EBP, EBX, ECX, EDI, EDX, ESI, ESP}; -use wasmgen::module_init::WasmBuilder; +use wasmgen::module_init::{WasmBuilder, WasmLocal}; use wasmgen::wasm_util::WasmBuf; +pub enum LocalOrImmedate<'a> { + WasmLocal(&'a WasmLocal), + Immediate(i32), +} + +impl<'a> LocalOrImmedate<'a> { + pub fn gen_get(&self, builder: &mut WasmBuilder) { + match self { + LocalOrImmedate::WasmLocal(l) => builder.instruction_body.get_local(l), + LocalOrImmedate::Immediate(i) => builder.instruction_body.const_i32(*i), + } + } +} + pub fn jit_instruction(ctx: &mut JitContext, instr_flags: &mut u32) { ctx.cpu.prefixes = 0; ctx.start_of_current_instruction = ctx.cpu.eip; @@ -255,14 +269,21 @@ macro_rules! define_instruction_read32( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); - codegen::gen_get_reg32(ctx, r); - $fn(ctx.builder); + let dest_operand = ctx.builder.set_new_local(); + $fn( + ctx.builder, + &dest_operand, + &LocalOrImmedate::WasmLocal(&ctx.register_locals[r as usize]), + ); + ctx.builder.free_local(dest_operand); } pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { - codegen::gen_get_reg32(ctx, r1); - codegen::gen_get_reg32(ctx, r2); - $fn(ctx.builder); + $fn( + ctx.builder, + &ctx.register_locals[r1 as usize], + &LocalOrImmedate::WasmLocal(&ctx.register_locals[r2 as usize]) + ); } ); @@ -270,14 +291,22 @@ macro_rules! define_instruction_read32( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); - ctx.builder.instruction_body.const_i32(make_imm_read!(ctx, imm8s) as i32); - $fn(ctx.builder); + let dest_operand = ctx.builder.set_new_local(); + let imm = make_imm_read!(ctx, imm8s); + $fn( + ctx.builder, + &dest_operand, + &LocalOrImmedate::Immediate(imm as i32), + ); + ctx.builder.free_local(dest_operand); } - pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { - codegen::gen_get_reg32(ctx, r1); - ctx.builder.instruction_body.const_i32(imm as i32); - $fn(ctx.builder); + pub fn $name_reg(ctx: &mut JitContext, r: u32, imm: u32) { + $fn( + ctx.builder, + &ctx.register_locals[r as usize], + &LocalOrImmedate::Immediate(imm as i32), + ); } ); @@ -285,14 +314,22 @@ macro_rules! define_instruction_read32( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); - ctx.builder.instruction_body.const_i32(make_imm_read!(ctx, imm32) as i32); - $fn(ctx.builder); + let dest_operand = ctx.builder.set_new_local(); + let imm = make_imm_read!(ctx, imm32); + $fn( + ctx.builder, + &dest_operand, + &LocalOrImmedate::Immediate(imm as i32), + ); + ctx.builder.free_local(dest_operand); } - pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { - codegen::gen_get_reg32(ctx, r1); - ctx.builder.instruction_body.const_i32(imm as i32); - $fn(ctx.builder); + pub fn $name_reg(ctx: &mut JitContext, r: u32, imm: u32) { + $fn( + ctx.builder, + &ctx.register_locals[r as usize], + &LocalOrImmedate::Immediate(imm as i32), + ); } ); ); @@ -977,24 +1014,29 @@ pub fn gen_sub32(builder: &mut WasmBuilder) { builder.free_local(result); } -pub fn gen_cmp32(builder: &mut WasmBuilder) { - let source_operand = builder.set_new_local(); - let dest_operand = builder.set_new_local(); - +pub fn gen_cmp32( + builder: &mut WasmBuilder, + dest_operand: &WasmLocal, + source_operand: &LocalOrImmedate, +) { builder.instruction_body.get_local(&dest_operand); - builder.instruction_body.get_local(&source_operand); + source_operand.gen_get(builder); builder.instruction_body.sub_i32(); let result = builder.set_new_local(); codegen::gen_set_last_op1(builder, &result); - codegen::gen_set_last_op2(builder, &source_operand); - codegen::gen_set_last_add_result(builder, &dest_operand); + { + builder + .instruction_body + .const_i32(global_pointers::LAST_OP2 as i32); + source_operand.gen_get(builder); + builder.instruction_body.store_aligned_i32(0); + } + codegen::gen_set_last_add_result(builder, dest_operand); codegen::gen_set_last_result(builder, &result); codegen::gen_set_last_op_size(builder, OPSIZE_32); codegen::gen_set_flags_changed(builder, FLAGS_ALL); - builder.free_local(dest_operand); - builder.free_local(source_operand); builder.free_local(result); } @@ -1020,19 +1062,25 @@ pub fn gen_and32(builder: &mut WasmBuilder) { builder.free_local(result); } -pub fn gen_test32(builder: &mut WasmBuilder) { +pub fn gen_test32( + builder: &mut WasmBuilder, + dest_operand: &WasmLocal, + source_operand: &LocalOrImmedate, +) { + builder + .instruction_body + .const_i32(global_pointers::LAST_RESULT as i32); + builder.instruction_body.get_local(&dest_operand); + source_operand.gen_get(builder); builder.instruction_body.and_i32(); - let result = builder.set_new_local(); + builder.instruction_body.store_aligned_i32(0); - codegen::gen_set_last_result(builder, &result); codegen::gen_set_last_op_size(builder, OPSIZE_32); codegen::gen_set_flags_changed( builder, FLAGS_ALL & !FLAG_CARRY & !FLAG_OVERFLOW & !FLAG_ADJUST, ); codegen::gen_clear_flags_bits(builder, FLAG_CARRY | FLAG_OVERFLOW | FLAG_ADJUST); - - builder.free_local(result); } pub fn gen_or32(builder: &mut WasmBuilder) { @@ -1089,9 +1137,11 @@ fn gen_xadd32(ctx: &mut JitContext, r: u32) { fn gen_cmpxchg32(ctx: &mut JitContext, r: u32) { let source = ctx.builder.set_new_local(); - codegen::gen_get_reg32(ctx, regs::EAX); - ctx.builder.instruction_body.get_local(&source); - gen_cmp32(ctx.builder); + gen_cmp32( + ctx.builder, + &ctx.register_locals[0], + &LocalOrImmedate::WasmLocal(&source), + ); codegen::gen_getzf(ctx.builder); ctx.builder.instruction_body.if_i32(); @@ -1404,16 +1454,23 @@ pub fn instr16_3B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { } pub fn instr32_3B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_get_reg32(ctx, r); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); - gen_cmp32(ctx.builder); + let source_operand = ctx.builder.set_new_local(); + gen_cmp32( + ctx.builder, + &ctx.register_locals[r as usize], + &LocalOrImmedate::WasmLocal(&source_operand), + ); + ctx.builder.free_local(source_operand); } pub fn instr32_3B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { - codegen::gen_get_reg32(ctx, r2); - codegen::gen_get_reg32(ctx, r1); - gen_cmp32(ctx.builder); + gen_cmp32( + ctx.builder, + &ctx.register_locals[r2 as usize], + &LocalOrImmedate::WasmLocal(&ctx.register_locals[r1 as usize]), + ); } pub fn instr_3C_jit(ctx: &mut JitContext, imm8: u32) { @@ -1429,9 +1486,11 @@ pub fn instr16_3D_jit(ctx: &mut JitContext, imm16: u32) { } pub fn instr32_3D_jit(ctx: &mut JitContext, imm32: u32) { - codegen::gen_get_reg32(ctx, 0); - ctx.builder.instruction_body.const_i32(imm32 as i32); - gen_cmp32(ctx.builder); + gen_cmp32( + ctx.builder, + &ctx.register_locals[0], + &LocalOrImmedate::Immediate(imm32 as i32), + ); } fn gen_inc16(ctx: &mut JitContext, r: u32) { @@ -3373,15 +3432,22 @@ pub fn instr16_F7_1_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { pub fn instr32_F7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); + let dest_operand = ctx.builder.set_new_local(); let imm = ctx.cpu.read_imm32(); - ctx.builder.instruction_body.const_i32(imm as i32); - gen_test32(ctx.builder); + gen_test32( + ctx.builder, + &dest_operand, + &LocalOrImmedate::Immediate(imm as i32), + ); + ctx.builder.free_local(dest_operand); } pub fn instr32_F7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { - codegen::gen_get_reg32(ctx, r); - ctx.builder.instruction_body.const_i32(imm as i32); - gen_test32(ctx.builder); + gen_test32( + ctx.builder, + &ctx.register_locals[r as usize], + &LocalOrImmedate::Immediate(imm as i32), + ); } pub fn instr32_F7_1_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { @@ -3843,9 +3909,11 @@ pub fn instr16_A9_jit(ctx: &mut JitContext, imm16: u32) { } pub fn instr32_A9_jit(ctx: &mut JitContext, imm32: u32) { - codegen::gen_get_reg32(ctx, 0); - ctx.builder.instruction_body.const_i32(imm32 as i32); - gen_test32(ctx.builder); + gen_test32( + ctx.builder, + &ctx.register_locals[0], + &LocalOrImmedate::Immediate(imm32 as i32), + ); } pub fn instr_0F18_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) { diff --git a/tests/expect/tests/do-while.wast b/tests/expect/tests/do-while.wast index 98aa9258..b3d65150 100644 --- a/tests/expect/tests/do-while.wast +++ b/tests/expect/tests/do-while.wast @@ -20,7 +20,7 @@ (import "e" "trigger_pagefault_end_jit" (func $e.trigger_pagefault_end_jit (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (local $l10 i32) (local $l11 i32) (local $l12 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (local $l10 i32) (set_local $l0 (get_local $p0)) (set_local $l1 @@ -92,26 +92,22 @@ (set_local $l5 (call $e.inc32 (get_local $l5))) - (get_local $l2) (set_local $l10 - (i32.const 10)) - (set_local $l11) - (set_local $l12 (i32.sub - (get_local $l11) - (get_local $l10))) + (get_local $l2) + (i32.const 10))) (i32.store (i32.const 96) - (get_local $l12)) - (i32.store - (i32.const 100) (get_local $l10)) + (i32.store + (i32.const 100) + (i32.const 10)) (i32.store (i32.const 108) - (get_local $l11)) + (get_local $l2)) (i32.store (i32.const 112) - (get_local $l12)) + (get_local $l10)) (i32.store (i32.const 104) (i32.const 31)) @@ -148,12 +144,12 @@ (i32.shr_u (i32.and (i32.xor - (tee_local $l12 + (tee_local $l10 (i32.load (i32.const 112))) (i32.const -1)) (i32.sub - (get_local $l12) + (get_local $l10) (i32.const 1))) (i32.load (i32.const 104))) diff --git a/tests/expect/tests/if.wast b/tests/expect/tests/if.wast index 84c21142..80745826 100644 --- a/tests/expect/tests/if.wast +++ b/tests/expect/tests/if.wast @@ -21,7 +21,7 @@ (import "e" "trigger_pagefault_end_jit" (func $e.trigger_pagefault_end_jit (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (local $l10 i32) (local $l11 i32) (local $l12 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (local $l10 i32) (set_local $l0 (get_local $p0)) (set_local $l1 @@ -91,26 +91,22 @@ (block $B6 (br_table $B6 $B5 $B4 $B3 $B2 (get_local $l0))) - (get_local $l2) (set_local $l10 - (i32.const 5)) - (set_local $l11) - (set_local $l12 (i32.sub - (get_local $l11) - (get_local $l10))) + (get_local $l2) + (i32.const 5))) (i32.store (i32.const 96) - (get_local $l12)) - (i32.store - (i32.const 100) (get_local $l10)) + (i32.store + (i32.const 100) + (i32.const 5)) (i32.store (i32.const 108) - (get_local $l11)) + (get_local $l2)) (i32.store (i32.const 112) - (get_local $l12)) + (get_local $l10)) (i32.store (i32.const 104) (i32.const 31)) diff --git a/tests/expect/tests/while-do.wast b/tests/expect/tests/while-do.wast index a62a0025..9f49557b 100644 --- a/tests/expect/tests/while-do.wast +++ b/tests/expect/tests/while-do.wast @@ -20,7 +20,7 @@ (import "e" "trigger_pagefault_end_jit" (func $e.trigger_pagefault_end_jit (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (local $l10 i32) (local $l11 i32) (local $l12 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (local $l10 i32) (set_local $l0 (get_local $p0)) (set_local $l1 @@ -90,26 +90,22 @@ (block $B6 (br_table $B6 $B5 $B4 $B3 $B2 (get_local $l0))) - (get_local $l2) (set_local $l10 - (i32.const 10)) - (set_local $l11) - (set_local $l12 (i32.sub - (get_local $l11) - (get_local $l10))) + (get_local $l2) + (i32.const 10))) (i32.store (i32.const 96) - (get_local $l12)) - (i32.store - (i32.const 100) (get_local $l10)) + (i32.store + (i32.const 100) + (i32.const 10)) (i32.store (i32.const 108) - (get_local $l11)) + (get_local $l2)) (i32.store (i32.const 112) - (get_local $l12)) + (get_local $l10)) (i32.store (i32.const 104) (i32.const 31)) @@ -145,12 +141,12 @@ (i32.shr_u (i32.and (i32.xor - (tee_local $l12 + (tee_local $l10 (i32.load (i32.const 112))) (i32.const -1)) (i32.sub - (get_local $l12) + (get_local $l10) (i32.const 1))) (i32.load (i32.const 104))) From f620aceb5d24b79a4a6621ab0f617f86c26f38d4 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1611/2137] Use LocalOrImmediate for other arithmetic instructions --- src/rust/codegen.rs | 5 +- src/rust/jit_instructions.rs | 270 ++++++++++++++++++++--------------- 2 files changed, 160 insertions(+), 115 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 7b898633..4aa02eef 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -4,6 +4,7 @@ use cpu2::cpu::{ }; use global_pointers; use jit::JitContext; +use jit_instructions::LocalOrImmedate; use modrm; use profiler; use regs; @@ -1321,11 +1322,11 @@ pub fn gen_set_last_op1(builder: &mut WasmBuilder, source: &WasmLocal) { builder.instruction_body.store_aligned_i32(0); } -pub fn gen_set_last_op2(builder: &mut WasmBuilder, source: &WasmLocal) { +pub fn gen_set_last_op2(builder: &mut WasmBuilder, source: &LocalOrImmedate) { builder .instruction_body .const_i32(global_pointers::LAST_OP2 as i32); - builder.instruction_body.get_local(&source); + source.gen_get(builder); builder.instruction_body.store_aligned_i32(0); } diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 2fd2dce2..3c0acbff 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -193,11 +193,16 @@ fn group_arith_ax_imm16(ctx: &mut JitContext, op: &str, imm16: u32) { codegen::gen_set_reg16(ctx, regs::AX); } -fn group_arith_eax_imm32(ctx: &mut JitContext, op: &Fn(&mut WasmBuilder), imm32: u32) { - codegen::gen_get_reg32(ctx, regs::EAX); - ctx.builder.instruction_body.const_i32(imm32 as i32); - op(ctx.builder); - codegen::gen_set_reg32(ctx, regs::EAX); +fn group_arith_eax_imm32( + ctx: &mut JitContext, + op: &Fn(&mut WasmBuilder, &WasmLocal, &LocalOrImmedate), + imm32: u32, +) { + op( + ctx.builder, + &ctx.register_locals[regs::EAX as usize], + &LocalOrImmedate::Immediate(imm32 as i32), + ); } macro_rules! define_instruction_read8( @@ -392,18 +397,23 @@ macro_rules! define_instruction_write_reg32( ($fn:expr, $name_mem:ident, $name_reg:ident, xreg) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_get_reg32(ctx, r); codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx); - $fn(ctx.builder); - codegen::gen_set_reg32(ctx, r); + let source_operand = ctx.builder.set_new_local(); + $fn( + ctx.builder, + &ctx.register_locals[r as usize], + &LocalOrImmedate::WasmLocal(&source_operand), + ); + ctx.builder.free_local(source_operand); } pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { - codegen::gen_get_reg32(ctx, r2); - codegen::gen_get_reg32(ctx, r1); - $fn(ctx.builder); - codegen::gen_set_reg32(ctx, r2); + $fn( + ctx.builder, + &ctx.register_locals[r2 as usize], + &LocalOrImmedate::WasmLocal(&ctx.register_locals[r1 as usize]), + ); } ); ); @@ -738,8 +748,14 @@ macro_rules! define_instruction_read_write_mem32( codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { - codegen::gen_get_reg32(ctx, r); - $fn(ctx.builder); + let dest_operand = ctx.builder.set_new_local(); + $fn( + ctx.builder, + &dest_operand, + &LocalOrImmedate::WasmLocal(&ctx.register_locals[r as usize]), + ); + ctx.builder.instruction_body.get_local(&dest_operand); + ctx.builder.free_local(dest_operand); }, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(r as i32); codegen::gen_move_registers_from_locals_to_memory(ctx); @@ -750,10 +766,11 @@ macro_rules! define_instruction_read_write_mem32( } pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) { - codegen::gen_get_reg32(ctx, r1); - codegen::gen_get_reg32(ctx, r2); - $fn(ctx.builder); - codegen::gen_set_reg32(ctx, r1); + $fn( + ctx.builder, + &ctx.register_locals[r1 as usize], + &LocalOrImmedate::WasmLocal(&ctx.register_locals[r2 as usize]), + ); } ); @@ -893,8 +910,14 @@ macro_rules! define_instruction_read_write_mem32( let address_local = ctx.builder.set_new_local(); let imm = make_imm_read!(ctx, imm32) as i32; codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { - ctx.builder.instruction_body.const_i32(imm as i32); - $fn(ctx.builder); + let dest_operand = ctx.builder.set_new_local(); + $fn( + ctx.builder, + &dest_operand, + &LocalOrImmedate::Immediate(imm), + ); + ctx.builder.instruction_body.get_local(&dest_operand); + ctx.builder.free_local(dest_operand); }, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_move_registers_from_locals_to_memory(ctx); @@ -905,11 +928,12 @@ macro_rules! define_instruction_read_write_mem32( } pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { - let imm = mask_imm!(imm, imm32); - codegen::gen_get_reg32(ctx, r1); - ctx.builder.instruction_body.const_i32(imm as i32); - $fn(ctx.builder); - codegen::gen_set_reg32(ctx, r1); + let imm = mask_imm!(imm, imm32) as i32; + $fn( + ctx.builder, + &ctx.register_locals[r1 as usize], + &LocalOrImmedate::Immediate(imm), + ); } ); @@ -919,8 +943,14 @@ macro_rules! define_instruction_read_write_mem32( let address_local = ctx.builder.set_new_local(); let imm = make_imm_read!(ctx, imm8s) as i32; codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { - ctx.builder.instruction_body.const_i32(imm as i32); - $fn(ctx.builder); + let dest_operand = ctx.builder.set_new_local(); + $fn( + ctx.builder, + &dest_operand, + &LocalOrImmedate::Immediate(imm), + ); + ctx.builder.instruction_body.get_local(&dest_operand); + ctx.builder.free_local(dest_operand); }, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_move_registers_from_locals_to_memory(ctx); @@ -931,11 +961,12 @@ macro_rules! define_instruction_read_write_mem32( } pub fn $name_reg(ctx: &mut JitContext, r1: u32, imm: u32) { - let imm = mask_imm!(imm, imm8s); - codegen::gen_get_reg32(ctx, r1); - ctx.builder.instruction_body.const_i32(imm as i32); - $fn(ctx.builder); - codegen::gen_set_reg32(ctx, r1); + let imm = mask_imm!(imm, imm8s) as i32; + $fn( + ctx.builder, + &ctx.register_locals[r1 as usize], + &LocalOrImmedate::Immediate(imm), + ); } ); @@ -966,52 +997,42 @@ macro_rules! define_instruction_read_write_mem32( ); ); -pub fn gen_add32(builder: &mut WasmBuilder) { - let source_operand = builder.set_new_local(); - let dest_operand = builder.set_new_local(); +pub fn gen_add32( + builder: &mut WasmBuilder, + dest_operand: &WasmLocal, + source_operand: &LocalOrImmedate, +) { + codegen::gen_set_last_op1(builder, &dest_operand); builder.instruction_body.get_local(&dest_operand); - builder.instruction_body.get_local(&source_operand); + source_operand.gen_get(builder); builder.instruction_body.add_i32(); - let result = builder.set_new_local(); + builder.instruction_body.set_local(dest_operand); + + codegen::gen_set_last_op2(builder, &source_operand); + codegen::gen_set_last_add_result(builder, &dest_operand); + codegen::gen_set_last_result(builder, &dest_operand); + codegen::gen_set_last_op_size(builder, OPSIZE_32); + codegen::gen_set_flags_changed(builder, FLAGS_ALL); +} + +pub fn gen_sub32( + builder: &mut WasmBuilder, + dest_operand: &WasmLocal, + source_operand: &LocalOrImmedate, +) { + codegen::gen_set_last_add_result(builder, &dest_operand); + + builder.instruction_body.get_local(&dest_operand); + source_operand.gen_get(builder); + builder.instruction_body.sub_i32(); + builder.instruction_body.set_local(dest_operand); codegen::gen_set_last_op1(builder, &dest_operand); codegen::gen_set_last_op2(builder, &source_operand); - codegen::gen_set_last_add_result(builder, &result); - codegen::gen_set_last_result(builder, &result); + codegen::gen_set_last_result(builder, &dest_operand); codegen::gen_set_last_op_size(builder, OPSIZE_32); codegen::gen_set_flags_changed(builder, FLAGS_ALL); - - // leave result on stack - builder.instruction_body.get_local(&result); - - builder.free_local(dest_operand); - builder.free_local(source_operand); - builder.free_local(result); -} - -pub fn gen_sub32(builder: &mut WasmBuilder) { - let source_operand = builder.set_new_local(); - let dest_operand = builder.set_new_local(); - - builder.instruction_body.get_local(&dest_operand); - builder.instruction_body.get_local(&source_operand); - builder.instruction_body.sub_i32(); - let result = builder.set_new_local(); - - codegen::gen_set_last_op1(builder, &result); - codegen::gen_set_last_op2(builder, &source_operand); - codegen::gen_set_last_add_result(builder, &dest_operand); - codegen::gen_set_last_result(builder, &result); - codegen::gen_set_last_op_size(builder, OPSIZE_32); - codegen::gen_set_flags_changed(builder, FLAGS_ALL); - - // leave result on stack - builder.instruction_body.get_local(&result); - - builder.free_local(dest_operand); - builder.free_local(source_operand); - builder.free_local(result); } pub fn gen_cmp32( @@ -1025,13 +1046,7 @@ pub fn gen_cmp32( let result = builder.set_new_local(); codegen::gen_set_last_op1(builder, &result); - { - builder - .instruction_body - .const_i32(global_pointers::LAST_OP2 as i32); - source_operand.gen_get(builder); - builder.instruction_body.store_aligned_i32(0); - } + codegen::gen_set_last_op2(builder, &source_operand); codegen::gen_set_last_add_result(builder, dest_operand); codegen::gen_set_last_result(builder, &result); codegen::gen_set_last_op_size(builder, OPSIZE_32); @@ -1040,26 +1055,45 @@ pub fn gen_cmp32( builder.free_local(result); } -pub fn gen_adc32(builder: &mut WasmBuilder) { codegen::gen_call_fn2_ret(builder, "adc32"); } +pub fn gen_adc32( + builder: &mut WasmBuilder, + dest_operand: &WasmLocal, + source_operand: &LocalOrImmedate, +) { + builder.instruction_body.get_local(&dest_operand); + source_operand.gen_get(builder); + codegen::gen_call_fn2_ret(builder, "adc32"); + builder.instruction_body.set_local(dest_operand); +} -pub fn gen_sbb32(builder: &mut WasmBuilder) { codegen::gen_call_fn2_ret(builder, "sbb32"); } +pub fn gen_sbb32( + builder: &mut WasmBuilder, + dest_operand: &WasmLocal, + source_operand: &LocalOrImmedate, +) { + builder.instruction_body.get_local(&dest_operand); + source_operand.gen_get(builder); + codegen::gen_call_fn2_ret(builder, "sbb32"); + builder.instruction_body.set_local(dest_operand); +} -pub fn gen_and32(builder: &mut WasmBuilder) { +pub fn gen_and32( + builder: &mut WasmBuilder, + dest_operand: &WasmLocal, + source_operand: &LocalOrImmedate, +) { + builder.instruction_body.get_local(&dest_operand); + source_operand.gen_get(builder); builder.instruction_body.and_i32(); - let result = builder.set_new_local(); + builder.instruction_body.set_local(dest_operand); - codegen::gen_set_last_result(builder, &result); + codegen::gen_set_last_result(builder, &dest_operand); codegen::gen_set_last_op_size(builder, OPSIZE_32); codegen::gen_set_flags_changed( builder, FLAGS_ALL & !FLAG_CARRY & !FLAG_OVERFLOW & !FLAG_ADJUST, ); codegen::gen_clear_flags_bits(builder, FLAG_CARRY | FLAG_OVERFLOW | FLAG_ADJUST); - - // leave result on stack - builder.instruction_body.get_local(&result); - - builder.free_local(result); } pub fn gen_test32( @@ -1083,55 +1117,59 @@ pub fn gen_test32( codegen::gen_clear_flags_bits(builder, FLAG_CARRY | FLAG_OVERFLOW | FLAG_ADJUST); } -pub fn gen_or32(builder: &mut WasmBuilder) { +pub fn gen_or32( + builder: &mut WasmBuilder, + dest_operand: &WasmLocal, + source_operand: &LocalOrImmedate, +) { + builder.instruction_body.get_local(&dest_operand); + source_operand.gen_get(builder); builder.instruction_body.or_i32(); - let result = builder.set_new_local(); + builder.instruction_body.set_local(dest_operand); - codegen::gen_set_last_result(builder, &result); + codegen::gen_set_last_result(builder, &dest_operand); codegen::gen_set_last_op_size(builder, OPSIZE_32); codegen::gen_set_flags_changed( builder, FLAGS_ALL & !FLAG_CARRY & !FLAG_OVERFLOW & !FLAG_ADJUST, ); codegen::gen_clear_flags_bits(builder, FLAG_CARRY | FLAG_OVERFLOW | FLAG_ADJUST); - - // leave result on stack - builder.instruction_body.get_local(&result); - - builder.free_local(result); } -pub fn gen_xor32(builder: &mut WasmBuilder) { +pub fn gen_xor32( + builder: &mut WasmBuilder, + dest_operand: &WasmLocal, + source_operand: &LocalOrImmedate, +) { + builder.instruction_body.get_local(&dest_operand); + source_operand.gen_get(builder); builder.instruction_body.xor_i32(); - let result = builder.set_new_local(); + builder.instruction_body.set_local(dest_operand); - codegen::gen_set_last_result(builder, &result); + codegen::gen_set_last_result(builder, &dest_operand); codegen::gen_set_last_op_size(builder, OPSIZE_32); codegen::gen_set_flags_changed( builder, FLAGS_ALL & !FLAG_CARRY & !FLAG_OVERFLOW & !FLAG_ADJUST, ); codegen::gen_clear_flags_bits(builder, FLAG_CARRY | FLAG_OVERFLOW | FLAG_ADJUST); - - // leave result on stack - builder.instruction_body.get_local(&result); - - builder.free_local(result); } -fn gen_xadd32(ctx: &mut JitContext, r: u32) { - let source = ctx.builder.set_new_local(); - codegen::gen_get_reg32(ctx, r); +fn gen_xadd32(ctx: &mut JitContext, dest_operand: &WasmLocal, r: u32) { + ctx.builder + .instruction_body + .get_local(&ctx.register_locals[r as usize]); let tmp = ctx.builder.set_new_local(); - ctx.builder.instruction_body.get_local(&source); + ctx.builder.instruction_body.get_local(&dest_operand); codegen::gen_set_reg32(ctx, r); - ctx.builder.instruction_body.get_local(&source); - ctx.builder.instruction_body.get_local(&tmp); - gen_add32(ctx.builder); + gen_add32( + ctx.builder, + &dest_operand, + &LocalOrImmedate::WasmLocal(&tmp), + ); - ctx.builder.free_local(source); ctx.builder.free_local(tmp); } @@ -4195,7 +4233,10 @@ pub fn instr32_0FC1_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { BitSize::DWORD, &address_local, &|ref mut ctx| { - gen_xadd32(ctx, r); + let dest_operand = ctx.builder.set_new_local(); + gen_xadd32(ctx, &dest_operand, r); + ctx.builder.instruction_body.get_local(&dest_operand); + ctx.builder.free_local(dest_operand); }, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(r as i32); @@ -4208,8 +4249,11 @@ pub fn instr32_0FC1_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { } pub fn instr32_0FC1_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_get_reg32(ctx, r1); - gen_xadd32(ctx, r2); + let dest_operand = ctx.builder.set_new_local(); + gen_xadd32(ctx, &dest_operand, r2); + ctx.builder.instruction_body.get_local(&dest_operand); codegen::gen_set_reg32(ctx, r1); + ctx.builder.free_local(dest_operand); } pub fn instr_C6_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { From aad8072aa72238a10be646a9fbbe5554521428b1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:28 -0600 Subject: [PATCH 1612/2137] Optimise push reg --- src/rust/jit_instructions.rs | 6 ++---- src/rust/wasmgen/module_init.rs | 3 +++ tests/expect/tests/push.wast | 26 ++++++++++++-------------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 3c0acbff..f3449966 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -137,10 +137,8 @@ fn push16_reg_jit(ctx: &mut JitContext, r: u32) { ctx.builder.free_local(value_local); } fn push32_reg_jit(ctx: &mut JitContext, r: u32) { - codegen::gen_get_reg32(ctx, r); - let value_local = ctx.builder.set_new_local(); - codegen::gen_push32(ctx, &value_local); - ctx.builder.free_local(value_local); + let reg = ctx.register_locals[r as usize].unsafe_clone(); + codegen::gen_push32(ctx, ®); } fn push16_imm_jit(ctx: &mut JitContext, imm: u32) { ctx.builder.instruction_body.const_i32(imm as i32); diff --git a/src/rust/wasmgen/module_init.rs b/src/rust/wasmgen/module_init.rs index b25fe819..d7d8707a 100644 --- a/src/rust/wasmgen/module_init.rs +++ b/src/rust/wasmgen/module_init.rs @@ -64,6 +64,9 @@ pub struct WasmBuilder { pub struct WasmLocal(u8); impl WasmLocal { pub fn idx(&self) -> u8 { self.0 } + /// Unsafe: Can result in multiple free's. Should only be used for locals that are used during + /// the whole module (for example, registers) + pub fn unsafe_clone(&self) -> WasmLocal { WasmLocal(self.0) } } pub struct WasmLocalI64(u8); diff --git a/tests/expect/tests/push.wast b/tests/expect/tests/push.wast index 1ba828ff..136df313 100644 --- a/tests/expect/tests/push.wast +++ b/tests/expect/tests/push.wast @@ -20,7 +20,7 @@ (import "e" "trigger_pagefault_end_jit" (func $e.trigger_pagefault_end_jit (type $t0))) (import "e" "m" (memory $e.m 256)) (func $f (export "f") (type $t1) (param $p0 i32) - (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (local $l10 i32) (local $l11 i32) (local $l12 i32) (local $l13 i32) + (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32) (local $l6 i32) (local $l7 i32) (local $l8 i32) (local $l9 i32) (local $l10 i32) (local $l11 i32) (local $l12 i32) (set_local $l0 (get_local $p0)) (set_local $l1 @@ -88,11 +88,9 @@ (block $B4 (br_table $B4 $B3 $B2 (get_local $l0))) - (set_local $l10 - (get_local $l2)) - (set_local $l12 + (set_local $l11 (i32.add - (tee_local $l11 + (tee_local $l10 (i32.sub (get_local $l6) (i32.const 4))) @@ -102,28 +100,28 @@ (i32.and (i32.eq (i32.and - (tee_local $l13 + (tee_local $l12 (i32.load offset=4194304 (i32.shl (i32.shr_u - (get_local $l12) + (get_local $l11) (i32.const 12)) (i32.const 2)))) (i32.const 4075)) (i32.const 1)) (i32.le_s (i32.and - (get_local $l12) + (get_local $l11) (i32.const 4095)) (i32.const 4092))) (then (i32.store offset={normalised output} align=1 (i32.xor (i32.and - (get_local $l13) + (get_local $l12) (i32.const -4096)) - (get_local $l12)) - (get_local $l10))) + (get_local $l11)) + (get_local $l2))) (else (i32.store (i32.const 560) @@ -134,15 +132,15 @@ (i32.const -4096)) (i32.const 0))) (call $e.safe_write32_slow_jit - (get_local $l12) - (get_local $l10)) + (get_local $l11) + (get_local $l2)) (if $I6 (i32.load8_u (i32.const 540)) (then (br $B3))))) (set_local $l6 - (get_local $l11)) + (get_local $l10)) (i32.store (i32.const 560) (i32.add From c5cd93678e37150504f4afe02f1f7f2530cd9522 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1613/2137] Pass local to gen_safe_read, add single function for modrm_resolve and gen_safe_read (preparation for later optimisations) --- src/rust/codegen.rs | 79 +++++++++--- src/rust/jit_instructions.rs | 165 ++++++++++---------------- tests/expect/tests/call.wast | 11 +- tests/expect/tests/indirect-call.wast | 21 ++-- tests/expect/tests/mov16.wast | 32 ++--- tests/expect/tests/mov32-mem.wast | 40 ++++--- tests/expect/tests/pop.wast | 11 +- 7 files changed, 185 insertions(+), 174 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 4aa02eef..5181d352 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -358,12 +358,43 @@ pub fn gen_set_reg32_r(ctx: &mut JitContext, dest: u32, src: u32) { gen_set_reg32(ctx, dest); } -pub fn gen_safe_read8(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::BYTE, None) } -pub fn gen_safe_read16(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::WORD, None) } -pub fn gen_safe_read32(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::DWORD, None) } -pub fn gen_safe_read64(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::QWORD, None) } +pub fn gen_modrm_resolve_safe_read8(ctx: &mut JitContext, modrm_byte: u8) { + gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + gen_safe_read8(ctx, &address_local); + ctx.builder.free_local(address_local); +} +pub fn gen_modrm_resolve_safe_read16(ctx: &mut JitContext, modrm_byte: u8) { + gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + gen_safe_read16(ctx, &address_local); + ctx.builder.free_local(address_local); +} +pub fn gen_modrm_resolve_safe_read32(ctx: &mut JitContext, modrm_byte: u8) { + gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + gen_safe_read32(ctx, &address_local); + ctx.builder.free_local(address_local); +} + +pub fn gen_safe_read8(ctx: &mut JitContext, address_local: &WasmLocal) { + gen_safe_read(ctx, BitSize::BYTE, address_local, None); +} +pub fn gen_safe_read16(ctx: &mut JitContext, address_local: &WasmLocal) { + gen_safe_read(ctx, BitSize::WORD, address_local, None); +} +pub fn gen_safe_read32(ctx: &mut JitContext, address_local: &WasmLocal) { + gen_safe_read(ctx, BitSize::DWORD, address_local, None); +} +pub fn gen_safe_read64(ctx: &mut JitContext) { + let address_local = ctx.builder.set_new_local(); + gen_safe_read(ctx, BitSize::QWORD, &address_local, None); + ctx.builder.free_local(address_local); +} pub fn gen_safe_read128(ctx: &mut JitContext, where_to_write: u32) { - gen_safe_read(ctx, BitSize::DQWORD, Some(where_to_write)) + let address_local = ctx.builder.set_new_local(); + gen_safe_read(ctx, BitSize::DQWORD, &address_local, Some(where_to_write)); + ctx.builder.free_local(address_local); } // only used internally for gen_safe_write @@ -424,11 +455,16 @@ pub fn gen_safe_write128( ) } -fn gen_safe_read(ctx: &mut JitContext, bits: BitSize, where_to_write: Option) { +fn gen_safe_read( + ctx: &mut JitContext, + bits: BitSize, + address_local: &WasmLocal, + where_to_write: Option, +) { // Assumes virtual address has been pushed to the stack, and generates safe_readXX's fast-path // inline, bailing to safe_readXX_slow if necessary - let address_local = ctx.builder.tee_new_local(); + ctx.builder.instruction_body.get_local(&address_local); // Pseudo: base_on_stack = (uint32_t)address >> 12; ctx.builder.instruction_body.const_i32(12); @@ -605,7 +641,6 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize, where_to_write: Option ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read8(ctx); + codegen::gen_modrm_resolve_safe_read8(ctx, modrm_byte); codegen::gen_get_reg8(ctx, r); codegen::gen_call_fn2(ctx.builder, $fn) } @@ -221,8 +218,7 @@ macro_rules! define_instruction_read8( ($fn:expr, $name_mem:ident, $name_reg:ident, $imm:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read8(ctx); + codegen::gen_modrm_resolve_safe_read8(ctx, modrm_byte); ctx.builder.instruction_body.const_i32(make_imm_read!(ctx, $imm) as i32); codegen::gen_call_fn2(ctx.builder, $fn) } @@ -238,8 +234,7 @@ macro_rules! define_instruction_read8( macro_rules! define_instruction_read16( ($fn:expr, $name_mem:ident, $name_reg:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read16(ctx); + codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); codegen::gen_get_reg16(ctx, r); codegen::gen_call_fn2(ctx.builder, $fn) } @@ -253,8 +248,7 @@ macro_rules! define_instruction_read16( ($fn:expr, $name_mem:ident, $name_reg:ident, $imm:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read16(ctx); + codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); ctx.builder.instruction_body.const_i32(make_imm_read!(ctx, $imm) as i32); codegen::gen_call_fn2(ctx.builder, $fn) } @@ -270,8 +264,7 @@ macro_rules! define_instruction_read16( macro_rules! define_instruction_read32( ($fn:expr, $name_mem:ident, $name_reg:ident, xreg) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read32(ctx); + codegen::gen_modrm_resolve_safe_read32(ctx, modrm_byte); let dest_operand = ctx.builder.set_new_local(); $fn( ctx.builder, @@ -292,8 +285,7 @@ macro_rules! define_instruction_read32( ($fn:expr, $name_mem:ident, $name_reg:ident, ximm8s) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read32(ctx); + codegen::gen_modrm_resolve_safe_read32(ctx, modrm_byte); let dest_operand = ctx.builder.set_new_local(); let imm = make_imm_read!(ctx, imm8s); $fn( @@ -315,8 +307,7 @@ macro_rules! define_instruction_read32( ($fn:expr, $name_mem:ident, $name_reg:ident, ximm32) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read32(ctx); + codegen::gen_modrm_resolve_safe_read32(ctx, modrm_byte); let dest_operand = ctx.builder.set_new_local(); let imm = make_imm_read!(ctx, imm32); $fn( @@ -341,8 +332,7 @@ macro_rules! define_instruction_write_reg8( ($fn:expr, $name_mem:ident, $name_reg:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_get_reg8(ctx, r); - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read8(ctx); + codegen::gen_modrm_resolve_safe_read8(ctx, modrm_byte); codegen::gen_call_fn2_ret(ctx.builder, $fn); codegen::gen_set_reg8(ctx, r); } @@ -360,8 +350,7 @@ macro_rules! define_instruction_write_reg16( ($fn:expr, $name_mem:ident, $name_reg:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_get_reg16(ctx, r); - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read16(ctx); + codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); codegen::gen_call_fn2_ret(ctx.builder, $fn); codegen::gen_set_reg16(ctx, r); } @@ -379,8 +368,7 @@ macro_rules! define_instruction_write_reg32( ($fn:expr, $name_mem:ident, $name_reg:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_get_reg32(ctx, r); - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read32(ctx); + codegen::gen_modrm_resolve_safe_read32(ctx, modrm_byte); codegen::gen_call_fn2_ret(ctx.builder, $fn); codegen::gen_set_reg32(ctx, r); } @@ -395,8 +383,7 @@ macro_rules! define_instruction_write_reg32( ($fn:expr, $name_mem:ident, $name_reg:ident, xreg) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read32(ctx); + codegen::gen_modrm_resolve_safe_read32(ctx, modrm_byte); let source_operand = ctx.builder.set_new_local(); $fn( ctx.builder, @@ -1465,8 +1452,7 @@ define_instruction_read32!(gen_cmp32, instr32_39_mem_jit, instr32_39_reg_jit, xr pub fn instr_3A_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_get_reg8(ctx, r); - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read8(ctx); + codegen::gen_modrm_resolve_safe_read8(ctx, modrm_byte); codegen::gen_call_fn2(ctx.builder, "cmp8") } @@ -1478,8 +1464,7 @@ pub fn instr_3A_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { pub fn instr16_3B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_get_reg16(ctx, r); - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read16(ctx); + codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); codegen::gen_call_fn2(ctx.builder, "cmp16") } @@ -1490,8 +1475,7 @@ pub fn instr16_3B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { } pub fn instr32_3B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read32(ctx); + codegen::gen_modrm_resolve_safe_read32(ctx, modrm_byte); let source_operand = ctx.builder.set_new_local(); gen_cmp32( ctx.builder, @@ -1679,8 +1663,7 @@ pub fn instr16_6A_jit(ctx: &mut JitContext, imm16: u32) { push16_imm_jit(ctx, im pub fn instr32_6A_jit(ctx: &mut JitContext, imm32: u32) { push32_imm_jit(ctx, imm32) } pub fn instr16_69_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read16(ctx); + codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); let imm16 = ctx.cpu.read_imm16(); ctx.builder.instruction_body.const_i32(imm16 as i32); codegen::gen_call_fn2_ret(ctx.builder, "imul_reg16"); @@ -1694,8 +1677,7 @@ pub fn instr16_69_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm16: u32) { } pub fn instr32_69_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read32(ctx); + codegen::gen_modrm_resolve_safe_read32(ctx, modrm_byte); let imm32 = ctx.cpu.read_imm32(); ctx.builder.instruction_body.const_i32(imm32 as i32); codegen::gen_call_fn2_ret(ctx.builder, "imul_reg32"); @@ -1709,8 +1691,7 @@ pub fn instr32_69_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm32: u32) { } pub fn instr16_6B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read16(ctx); + codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); let imm8s = ctx.cpu.read_imm8s(); ctx.builder.instruction_body.const_i32(imm8s as i32); codegen::gen_call_fn2_ret(ctx.builder, "imul_reg16"); @@ -1724,8 +1705,7 @@ pub fn instr16_6B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm8s: u32) { } pub fn instr32_6B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read32(ctx); + codegen::gen_modrm_resolve_safe_read32(ctx, modrm_byte); let imm8s = ctx.cpu.read_imm8s(); ctx.builder.instruction_body.const_i32(imm8s as i32); codegen::gen_call_fn2_ret(ctx.builder, "imul_reg32"); @@ -2102,8 +2082,7 @@ pub fn instr32_89_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { pub fn instr_8A_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { // Pseudo: reg8[r] = safe_read8(modrm_resolve(modrm_byte)); - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read8(ctx); + codegen::gen_modrm_resolve_safe_read8(ctx, modrm_byte); codegen::gen_set_reg8(ctx, r); } @@ -2113,8 +2092,7 @@ pub fn instr_8A_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { pub fn instr16_8B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { // Pseudo: reg16[r] = safe_read16(modrm_resolve(modrm_byte)); - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read16(ctx); + codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); codegen::gen_set_reg16(ctx, r); } @@ -2123,8 +2101,7 @@ pub fn instr16_8B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { } pub fn instr32_8B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { // Pseudo: reg32s[r] = safe_read32s(modrm_resolve(modrm_byte)); - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read32(ctx); + codegen::gen_modrm_resolve_safe_read32(ctx, modrm_byte); codegen::gen_set_reg32(ctx, r); } @@ -3045,8 +3022,7 @@ pub fn instr_D9_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { ctx.builder .instruction_body .const_i32(global_pointers::FPU_CONTROL_WORD as i32); - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read16(ctx); + codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); ctx.builder.instruction_body.store_aligned_u16(0); } pub fn instr_D9_5_reg_jit(ctx: &mut JitContext, r: u32) { @@ -3085,8 +3061,7 @@ pub fn instr_D9_7_reg_jit(ctx: &mut JitContext, r: u32) { pub fn instr_DA_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { ctx.builder.instruction_body.const_i32(0); - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read32(ctx); + codegen::gen_modrm_resolve_safe_read32(ctx, modrm_byte); ctx.builder.instruction_body.convert_i32_to_f64(); codegen::gen_call_fn2_i32_f64(ctx.builder, "fpu_fsubr") } @@ -3100,8 +3075,7 @@ pub fn instr_DA_5_reg_jit(ctx: &mut JitContext, r: u32) { } pub fn instr_DB_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read32(ctx); + codegen::gen_modrm_resolve_safe_read32(ctx, modrm_byte); ctx.builder.instruction_body.convert_i32_to_f64(); codegen::gen_call_fn1_f64(ctx.builder, "fpu_push"); } @@ -3266,8 +3240,7 @@ pub fn instr_DD_5_reg_jit(ctx: &mut JitContext, r: u32) { fn instr_group_DE_mem_jit(ctx: &mut JitContext, modrm_byte: u8, op: &str) { ctx.builder.instruction_body.const_i32(0); - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read16(ctx); + codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); codegen::sign_extend_i16(ctx.builder); ctx.builder.instruction_body.convert_i32_to_f64(); codegen::gen_call_fn2_i32_f64(ctx.builder, op) @@ -3292,8 +3265,7 @@ pub fn instr_DE_1_reg_jit(ctx: &mut JitContext, r: u32) { instr_group_DE_reg_jit(ctx, r, "fpu_fmul") } pub fn instr_DE_2_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read16(ctx); + codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); codegen::sign_extend_i16(ctx.builder); ctx.builder.instruction_body.convert_i32_to_f64(); codegen::gen_call_fn1_f64(ctx.builder, "fpu_fcom") @@ -3304,8 +3276,7 @@ pub fn instr_DE_2_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_fn0_const(ctx.builder, "fpu_pop") } pub fn instr_DE_3_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read16(ctx); + codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); codegen::sign_extend_i16(ctx.builder); ctx.builder.instruction_body.convert_i32_to_f64(); codegen::gen_call_fn1_f64(ctx.builder, "fpu_fcomp") @@ -3424,8 +3395,7 @@ pub fn instr32_EB_jit(ctx: &mut JitContext, imm8: u32) { } pub fn instr_F6_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read8(ctx); + codegen::gen_modrm_resolve_safe_read8(ctx, modrm_byte); let imm = ctx.cpu.read_imm8(); ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn2(ctx.builder, "test8") @@ -3445,8 +3415,7 @@ pub fn instr_F6_1_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { } pub fn instr16_F7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read16(ctx); + codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); let imm = ctx.cpu.read_imm16(); ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn2(ctx.builder, "test16") @@ -3466,8 +3435,7 @@ pub fn instr16_F7_1_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { } pub fn instr32_F7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read32(ctx); + codegen::gen_modrm_resolve_safe_read32(ctx, modrm_byte); let dest_operand = ctx.builder.set_new_local(); let imm = ctx.cpu.read_imm32(); gen_test32( @@ -3523,8 +3491,7 @@ define_instruction_read_write_mem32!( ); pub fn instr16_F7_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read16(ctx); + codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); codegen::gen_move_registers_from_locals_to_memory(ctx); codegen::gen_call_fn1(ctx.builder, "mul16"); codegen::gen_move_registers_from_memory_to_locals(ctx); @@ -3536,8 +3503,7 @@ pub fn instr16_F7_4_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_move_registers_from_memory_to_locals(ctx); } pub fn instr32_F7_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read32(ctx); + codegen::gen_modrm_resolve_safe_read32(ctx, modrm_byte); gen_mul32(ctx); } pub fn instr32_F7_4_reg_jit(ctx: &mut JitContext, r: u32) { @@ -3546,8 +3512,7 @@ pub fn instr32_F7_4_reg_jit(ctx: &mut JitContext, r: u32) { } pub fn instr16_F7_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read16(ctx); + codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); codegen::sign_extend_i16(ctx.builder); codegen::gen_move_registers_from_locals_to_memory(ctx); codegen::gen_call_fn1(ctx.builder, "imul16"); @@ -3561,8 +3526,7 @@ pub fn instr16_F7_5_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_move_registers_from_memory_to_locals(ctx); } pub fn instr32_F7_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read32(ctx); + codegen::gen_modrm_resolve_safe_read32(ctx, modrm_byte); codegen::gen_move_registers_from_locals_to_memory(ctx); codegen::gen_call_fn1(ctx.builder, "imul32"); codegen::gen_move_registers_from_memory_to_locals(ctx); @@ -3637,8 +3601,7 @@ define_instruction_read_write_mem32!( ); pub fn instr16_FF_2_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read16(ctx); + codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); codegen::gen_add_cs_offset(ctx); let new_eip = ctx.builder.set_new_local(); @@ -3664,8 +3627,7 @@ pub fn instr16_FF_2_reg_jit(ctx: &mut JitContext, r: u32) { ctx.builder.free_local(new_eip); } pub fn instr32_FF_2_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read32(ctx); + codegen::gen_modrm_resolve_safe_read32(ctx, modrm_byte); codegen::gen_add_cs_offset(ctx); let new_eip = ctx.builder.set_new_local(); @@ -3692,8 +3654,7 @@ pub fn instr32_FF_2_reg_jit(ctx: &mut JitContext, r: u32) { } pub fn instr16_FF_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read16(ctx); + codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); codegen::gen_add_cs_offset(ctx); let new_eip = ctx.builder.set_new_local(); codegen::gen_set_eip(ctx, &new_eip); @@ -3707,8 +3668,7 @@ pub fn instr16_FF_4_reg_jit(ctx: &mut JitContext, r: u32) { ctx.builder.free_local(new_eip); } pub fn instr32_FF_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read32(ctx); + codegen::gen_modrm_resolve_safe_read32(ctx, modrm_byte); codegen::gen_add_cs_offset(ctx); let new_eip = ctx.builder.set_new_local(); codegen::gen_set_eip(ctx, &new_eip); @@ -3885,19 +3845,25 @@ pub fn instr_9E_jit(ctx: &mut JitContext) { pub fn instr_A0_jit(ctx: &mut JitContext, immaddr: u32) { ctx.builder.instruction_body.const_i32(immaddr as i32); jit_add_seg_offset(ctx, regs::DS); - codegen::gen_safe_read8(ctx); + let address_local = ctx.builder.set_new_local(); + codegen::gen_safe_read8(ctx, &address_local); + ctx.builder.free_local(address_local); codegen::gen_set_reg8(ctx, regs::AL); } pub fn instr16_A1_jit(ctx: &mut JitContext, immaddr: u32) { ctx.builder.instruction_body.const_i32(immaddr as i32); jit_add_seg_offset(ctx, regs::DS); - codegen::gen_safe_read16(ctx); + let address_local = ctx.builder.set_new_local(); + codegen::gen_safe_read16(ctx, &address_local); + ctx.builder.free_local(address_local); codegen::gen_set_reg16(ctx, regs::AX); } pub fn instr32_A1_jit(ctx: &mut JitContext, immaddr: u32) { ctx.builder.instruction_body.const_i32(immaddr as i32); jit_add_seg_offset(ctx, regs::DS); - codegen::gen_safe_read32(ctx); + let address_local = ctx.builder.set_new_local(); + codegen::gen_safe_read32(ctx, &address_local); + ctx.builder.free_local(address_local); codegen::gen_set_reg32(ctx, regs::EAX); } @@ -4106,8 +4072,7 @@ pub fn instr16_0FB6_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_set_reg16(ctx, r2); } pub fn instr16_0FB6_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read8(ctx); + codegen::gen_modrm_resolve_safe_read8(ctx, modrm_byte); codegen::gen_set_reg16(ctx, r); } @@ -4116,14 +4081,12 @@ pub fn instr32_0FB6_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_set_reg32(ctx, r2); } pub fn instr32_0FB6_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read8(ctx); + codegen::gen_modrm_resolve_safe_read8(ctx, modrm_byte); codegen::gen_set_reg32(ctx, r); } pub fn instr16_0FB7_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read16(ctx); + codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); codegen::gen_set_reg16(ctx, r); } pub fn instr16_0FB7_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { @@ -4131,8 +4094,7 @@ pub fn instr16_0FB7_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_set_reg16(ctx, r2); } pub fn instr32_0FB7_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read16(ctx); + codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); codegen::gen_set_reg32(ctx, r); } pub fn instr32_0FB7_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { @@ -4146,8 +4108,7 @@ pub fn instr16_0FBE_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_set_reg16(ctx, r2); } pub fn instr16_0FBE_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read8(ctx); + codegen::gen_modrm_resolve_safe_read8(ctx, modrm_byte); codegen::sign_extend_i8(ctx.builder); codegen::gen_set_reg16(ctx, r); } @@ -4158,8 +4119,7 @@ pub fn instr32_0FBE_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_set_reg32(ctx, r2); } pub fn instr32_0FBE_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read8(ctx); + codegen::gen_modrm_resolve_safe_read8(ctx, modrm_byte); codegen::sign_extend_i8(ctx.builder); codegen::gen_set_reg32(ctx, r); } @@ -4170,8 +4130,7 @@ pub fn instr16_0FBF_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_set_reg16(ctx, r2); } pub fn instr16_0FBF_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read16(ctx); + codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); codegen::sign_extend_i16(ctx.builder); codegen::gen_set_reg16(ctx, r); } @@ -4182,8 +4141,7 @@ pub fn instr32_0FBF_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_set_reg32(ctx, r2); } pub fn instr32_0FBF_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read16(ctx); + codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); codegen::sign_extend_i16(ctx.builder); codegen::gen_set_reg32(ctx, r); } @@ -4311,8 +4269,7 @@ define_instruction_write_reg32!("imul_reg32", instr32_0FAF_mem_jit, instr32_0FAF macro_rules! define_cmovcc16( ($cond:expr, $name_mem:ident, $name_reg:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read16(ctx); + codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); let value = ctx.builder.set_new_local(); codegen::gen_condition_fn(ctx.builder, $cond); ctx.builder.instruction_body.if_void(); @@ -4335,8 +4292,7 @@ macro_rules! define_cmovcc16( macro_rules! define_cmovcc32( ($cond:expr, $name_mem:ident, $name_reg:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read32(ctx); + codegen::gen_modrm_resolve_safe_read32(ctx, modrm_byte); let value = ctx.builder.set_new_local(); codegen::gen_condition_fn(ctx.builder, $cond); ctx.builder.instruction_body.if_void(); @@ -4496,8 +4452,7 @@ pub fn instr_660F68_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { } pub fn instr_660F6E_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read32(ctx); + codegen::gen_modrm_resolve_safe_read32(ctx, modrm_byte); ctx.builder.instruction_body.const_i32(r as i32); codegen::gen_call_fn2(ctx.builder, "instr_660F6E") } diff --git a/tests/expect/tests/call.wast b/tests/expect/tests/call.wast index 27389b50..643c3284 100644 --- a/tests/expect/tests/call.wast +++ b/tests/expect/tests/call.wast @@ -284,6 +284,11 @@ (i32.const 556) (i32.load (i32.const 740)) + (set_local $l10 + (i32.add + (get_local $l6) + (i32.load + (i32.const 744)))) (if $I9 (result i32) (i32.and (i32.eq @@ -292,11 +297,7 @@ (i32.load offset=4194304 (i32.shl (i32.shr_u - (tee_local $l10 - (i32.add - (get_local $l6) - (i32.load - (i32.const 744)))) + (get_local $l10) (i32.const 12)) (i32.const 2)))) (i32.const 4041)) diff --git a/tests/expect/tests/indirect-call.wast b/tests/expect/tests/indirect-call.wast index 92dd7628..ef02d950 100644 --- a/tests/expect/tests/indirect-call.wast +++ b/tests/expect/tests/indirect-call.wast @@ -100,7 +100,12 @@ (i32.load (i32.const 556)) (i32.const 2))) - (set_local $l11 + (set_local $l10 + (i32.add + (get_local $l2) + (i32.load + (i32.const 748)))) + (set_local $l10 (i32.add (if $I6 (result i32) (i32.and @@ -110,11 +115,7 @@ (i32.load offset=4194304 (i32.shl (i32.shr_u - (tee_local $l10 - (i32.add - (get_local $l2) - (i32.load - (i32.const 748)))) + (get_local $l10) (i32.const 12)) (i32.const 2)))) (i32.const 4041)) @@ -149,7 +150,7 @@ (br $B3))))) (i32.load (i32.const 740)))) - (set_local $l10 + (set_local $l11 (i32.sub (i32.load (i32.const 556)) @@ -188,7 +189,7 @@ (get_local $l14) (i32.const -4096)) (get_local $l13)) - (get_local $l10))) + (get_local $l11))) (else (i32.store (i32.const 560) @@ -200,7 +201,7 @@ (i32.const 0))) (call $e.safe_write32_slow_jit (get_local $l13) - (get_local $l10)) + (get_local $l11)) (if $I9 (i32.load8_u (i32.const 540)) @@ -210,7 +211,7 @@ (get_local $l12)) (i32.store (i32.const 556) - (get_local $l11)) + (get_local $l10)) (i32.store (i32.const 664) (i32.add diff --git a/tests/expect/tests/mov16.wast b/tests/expect/tests/mov16.wast index 43317d98..356bb112 100644 --- a/tests/expect/tests/mov16.wast +++ b/tests/expect/tests/mov16.wast @@ -97,6 +97,11 @@ (i32.and (get_local $l2) (i32.const -65536)))) + (set_local $l10 + (i32.add + (i32.const 32) + (i32.load + (i32.const 748)))) (set_local $l3 (i32.or (i32.and @@ -108,11 +113,7 @@ (i32.load offset=4194304 (i32.shl (i32.shr_u - (tee_local $l10 - (i32.add - (i32.const 32) - (i32.load - (i32.const 748)))) + (get_local $l10) (i32.const 12)) (i32.const 2)))) (i32.const 4041)) @@ -149,6 +150,11 @@ (i32.and (get_local $l3) (i32.const -65536)))) + (set_local $l10 + (i32.add + (i32.const 36) + (i32.load + (i32.const 748)))) (set_local $l4 (i32.or (i32.and @@ -156,31 +162,27 @@ (i32.and (i32.eq (i32.and - (tee_local $l10 + (tee_local $l11 (i32.load offset=4194304 (i32.shl (i32.shr_u - (tee_local $l11 - (i32.add - (i32.const 36) - (i32.load - (i32.const 748)))) + (get_local $l10) (i32.const 12)) (i32.const 2)))) (i32.const 4041)) (i32.const 1)) (i32.le_s (i32.and - (get_local $l11) + (get_local $l10) (i32.const 4095)) (i32.const 4094))) (then (i32.load16_u offset={normalised output} align=1 (i32.xor (i32.and - (get_local $l10) + (get_local $l11) (i32.const -4096)) - (get_local $l11)))) + (get_local $l10)))) (else (i32.store (i32.const 560) @@ -191,7 +193,7 @@ (i32.const -4096)) (i32.const 7))) (call $e.safe_read16_slow_jit - (get_local $l11)) + (get_local $l10)) (if $I8 (i32.load8_u (i32.const 540)) diff --git a/tests/expect/tests/mov32-mem.wast b/tests/expect/tests/mov32-mem.wast index 63502edf..75a87c89 100644 --- a/tests/expect/tests/mov32-mem.wast +++ b/tests/expect/tests/mov32-mem.wast @@ -193,6 +193,13 @@ (i32.const 540)) (then (br $B3))))) + (set_local $l10 + (i32.add + (i32.add + (get_local $l5) + (i32.const 28)) + (i32.load + (i32.const 748)))) (set_local $l8 (if $I9 (result i32) (i32.and @@ -202,13 +209,7 @@ (i32.load offset=4194304 (i32.shl (i32.shr_u - (tee_local $l10 - (i32.add - (i32.add - (get_local $l5) - (i32.const 28)) - (i32.load - (i32.const 748)))) + (get_local $l10) (i32.const 12)) (i32.const 2)))) (i32.const 4041)) @@ -241,38 +242,39 @@ (i32.const 540)) (then (br $B3)))))) + (set_local $l10 + (i32.add + (i32.add + (get_local $l4) + (i32.const 32)) + (i32.load + (i32.const 748)))) (set_local $l9 (if $I11 (result i32) (i32.and (i32.eq (i32.and - (tee_local $l10 + (tee_local $l11 (i32.load offset=4194304 (i32.shl (i32.shr_u - (tee_local $l11 - (i32.add - (i32.add - (get_local $l4) - (i32.const 32)) - (i32.load - (i32.const 748)))) + (get_local $l10) (i32.const 12)) (i32.const 2)))) (i32.const 4041)) (i32.const 1)) (i32.le_s (i32.and - (get_local $l11) + (get_local $l10) (i32.const 4095)) (i32.const 4092))) (then (i32.load offset={normalised output} align=1 (i32.xor (i32.and - (get_local $l10) + (get_local $l11) (i32.const -4096)) - (get_local $l11)))) + (get_local $l10)))) (else (i32.store (i32.const 560) @@ -283,7 +285,7 @@ (i32.const -4096)) (i32.const 18))) (call $e.safe_read32s_slow_jit - (get_local $l11)) + (get_local $l10)) (if $I12 (i32.load8_u (i32.const 540)) diff --git a/tests/expect/tests/pop.wast b/tests/expect/tests/pop.wast index 03d9bea4..2d60b759 100644 --- a/tests/expect/tests/pop.wast +++ b/tests/expect/tests/pop.wast @@ -88,6 +88,11 @@ (block $B4 (br_table $B4 $B3 $B2 (get_local $l0))) + (set_local $l10 + (i32.add + (get_local $l6) + (i32.load + (i32.const 744)))) (if $I5 (result i32) (i32.and (i32.eq @@ -96,11 +101,7 @@ (i32.load offset=4194304 (i32.shl (i32.shr_u - (tee_local $l10 - (i32.add - (get_local $l6) - (i32.load - (i32.const 744)))) + (get_local $l10) (i32.const 12)) (i32.const 2)))) (i32.const 4041)) From b23c4a9db2d116859cb68cd0a4f9b8b142d0b748 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1614/2137] Optimise pop reg --- src/rust/codegen.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 5181d352..dbea94ad 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -960,21 +960,21 @@ pub fn gen_pop32s_ss16(ctx: &mut JitContext) { } pub fn gen_pop32s_ss32(ctx: &mut JitContext) { - // esp = reg32s[ESP] - gen_get_reg32(ctx, regs::ESP); - - // result = safe_read32s(segment_offsets[SS] + esp) (or just esp if has_flat_segmentation) if !ctx.cpu.has_flat_segmentation() { + gen_get_reg32(ctx, regs::ESP); ctx.builder .instruction_body .load_aligned_i32(global_pointers::get_seg_offset(regs::SS)); ctx.builder.instruction_body.add_i32(); + let address_local = ctx.builder.set_new_local(); + gen_safe_read32(ctx, &address_local); + ctx.builder.free_local(address_local); + } + else { + let reg = ctx.register_locals[regs::ESP as usize].unsafe_clone(); + gen_safe_read32(ctx, ®); } - let address_local = ctx.builder.set_new_local(); - gen_safe_read32(ctx, &address_local); - ctx.builder.free_local(address_local); - // reg32s[ESP] = esp + 4; gen_get_reg32(ctx, regs::ESP); ctx.builder.instruction_body.const_i32(4); ctx.builder.instruction_body.add_i32(); From c97600f5cbb9352da9c839af3e72b7e1d6997ecc Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1615/2137] Also prepare gen_safe_read{64,128} for later optimisations --- src/rust/codegen.rs | 30 ++++++++++++-------- src/rust/jit_instructions.rs | 54 +++++++++++++----------------------- 2 files changed, 37 insertions(+), 47 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index dbea94ad..6b3a70c9 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -376,6 +376,18 @@ pub fn gen_modrm_resolve_safe_read32(ctx: &mut JitContext, modrm_byte: u8) { gen_safe_read32(ctx, &address_local); ctx.builder.free_local(address_local); } +pub fn gen_modrm_resolve_safe_read64(ctx: &mut JitContext, modrm_byte: u8) { + gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + gen_safe_read64(ctx, &address_local); + ctx.builder.free_local(address_local); +} +pub fn gen_modrm_resolve_safe_read128(ctx: &mut JitContext, modrm_byte: u8, where_to_write: u32) { + gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + gen_safe_read128(ctx, &address_local, where_to_write); + ctx.builder.free_local(address_local); +} pub fn gen_safe_read8(ctx: &mut JitContext, address_local: &WasmLocal) { gen_safe_read(ctx, BitSize::BYTE, address_local, None); @@ -386,15 +398,11 @@ pub fn gen_safe_read16(ctx: &mut JitContext, address_local: &WasmLocal) { pub fn gen_safe_read32(ctx: &mut JitContext, address_local: &WasmLocal) { gen_safe_read(ctx, BitSize::DWORD, address_local, None); } -pub fn gen_safe_read64(ctx: &mut JitContext) { - let address_local = ctx.builder.set_new_local(); +pub fn gen_safe_read64(ctx: &mut JitContext, address_local: &WasmLocal) { gen_safe_read(ctx, BitSize::QWORD, &address_local, None); - ctx.builder.free_local(address_local); } -pub fn gen_safe_read128(ctx: &mut JitContext, where_to_write: u32) { - let address_local = ctx.builder.set_new_local(); +pub fn gen_safe_read128(ctx: &mut JitContext, address_local: &WasmLocal, where_to_write: u32) { gen_safe_read(ctx, BitSize::DQWORD, &address_local, Some(where_to_write)); - ctx.builder.free_local(address_local); } // only used internally for gen_safe_write @@ -1530,16 +1538,14 @@ pub fn gen_fpu_get_sti(ctx: &mut JitContext, i: u32) { gen_call_fn1_ret_f64(ctx.builder, "fpu_get_sti"); } -pub fn gen_fpu_load_m32(ctx: &mut JitContext) { - let address_local = ctx.builder.set_new_local(); - gen_safe_read32(ctx, &address_local); - ctx.builder.free_local(address_local); +pub fn gen_fpu_load_m32(ctx: &mut JitContext, modrm_byte: u8) { + gen_modrm_resolve_safe_read32(ctx, modrm_byte); ctx.builder.instruction_body.reinterpret_i32_as_f32(); ctx.builder.instruction_body.promote_f32_to_f64(); } -pub fn gen_fpu_load_m64(ctx: &mut JitContext) { - gen_safe_read64(ctx); +pub fn gen_fpu_load_m64(ctx: &mut JitContext, modrm_byte: u8) { + gen_modrm_resolve_safe_read64(ctx, modrm_byte); ctx.builder.instruction_body.reinterpret_i64_as_f64(); } diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index dae2bd55..8d7ae1fb 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -116,9 +116,8 @@ pub fn instr_F3_jit(ctx: &mut JitContext, instr_flags: &mut u32) { } pub fn sse_read128_xmm_mem(ctx: &mut JitContext, name: &str, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); let dest = global_pointers::SSE_SCRATCH_REGISTER; - codegen::gen_safe_read128(ctx, dest); + codegen::gen_modrm_resolve_safe_read128(ctx, modrm_byte, dest); ctx.builder.instruction_body.const_i32(dest as i32); ctx.builder.instruction_body.const_i32(r as i32); codegen::gen_call_fn2(ctx.builder, name); @@ -2887,8 +2886,7 @@ define_instruction_read_write_mem32!( fn instr_group_D8_mem_jit(ctx: &mut JitContext, modrm_byte: u8, op: &str) { ctx.builder.instruction_body.const_i32(0); - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_fpu_load_m32(ctx); + codegen::gen_fpu_load_m32(ctx, modrm_byte); codegen::gen_call_fn2_i32_f64(ctx.builder, op) } fn instr_group_D8_reg_jit(ctx: &mut JitContext, r: u32, op: &str) { @@ -2910,8 +2908,7 @@ pub fn instr_D8_1_reg_jit(ctx: &mut JitContext, r: u32) { instr_group_D8_reg_jit(ctx, r, "fpu_fmul") } pub fn instr_D8_2_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_fpu_load_m32(ctx); + codegen::gen_fpu_load_m32(ctx, modrm_byte); codegen::gen_call_fn1_f64(ctx.builder, "fpu_fcom") } pub fn instr_D8_2_reg_jit(ctx: &mut JitContext, r: u32) { @@ -2919,8 +2916,7 @@ pub fn instr_D8_2_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_call_fn1_f64(ctx.builder, "fpu_fcom") } pub fn instr_D8_3_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_fpu_load_m32(ctx); + codegen::gen_fpu_load_m32(ctx, modrm_byte); codegen::gen_call_fn1_f64(ctx.builder, "fpu_fcomp") } pub fn instr_D8_3_reg_jit(ctx: &mut JitContext, r: u32) { @@ -2953,8 +2949,7 @@ pub fn instr_D8_7_reg_jit(ctx: &mut JitContext, r: u32) { } pub fn instr_D9_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_fpu_load_m32(ctx); + codegen::gen_fpu_load_m32(ctx, modrm_byte); codegen::gen_call_fn1_f64(ctx.builder, "fpu_push"); } pub fn instr_D9_0_reg_jit(ctx: &mut JitContext, r: u32) { @@ -3127,8 +3122,7 @@ pub fn instr_DB_5_reg_jit(ctx: &mut JitContext, r: u32) { fn instr_group_DC_mem_jit(ctx: &mut JitContext, modrm_byte: u8, op: &str) { ctx.builder.instruction_body.const_i32(0); - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_fpu_load_m64(ctx); + codegen::gen_fpu_load_m64(ctx, modrm_byte); codegen::gen_call_fn2_i32_f64(ctx.builder, op) } fn instr_group_DC_reg_jit(ctx: &mut JitContext, r: u32, op: &str) { @@ -3150,8 +3144,7 @@ pub fn instr_DC_1_reg_jit(ctx: &mut JitContext, r: u32) { instr_group_DC_reg_jit(ctx, r, "fpu_fmul") } pub fn instr_DC_2_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_fpu_load_m64(ctx); + codegen::gen_fpu_load_m64(ctx, modrm_byte); codegen::gen_call_fn1_f64(ctx.builder, "fpu_fcom") } pub fn instr_DC_2_reg_jit(ctx: &mut JitContext, r: u32) { @@ -3159,8 +3152,7 @@ pub fn instr_DC_2_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_call_fn1_f64(ctx.builder, "fpu_fcom") } pub fn instr_DC_3_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_fpu_load_m64(ctx); + codegen::gen_fpu_load_m64(ctx, modrm_byte); codegen::gen_call_fn1_f64(ctx.builder, "fpu_fcomp") } pub fn instr_DC_3_reg_jit(ctx: &mut JitContext, r: u32) { @@ -3193,8 +3185,7 @@ pub fn instr_DC_7_reg_jit(ctx: &mut JitContext, r: u32) { } pub fn instr_DD_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_fpu_load_m64(ctx); + codegen::gen_fpu_load_m64(ctx, modrm_byte); codegen::gen_call_fn1_f64(ctx.builder, "fpu_push"); } pub fn instr_DD_0_reg_jit(ctx: &mut JitContext, r: u32) { @@ -3361,8 +3352,7 @@ pub fn instr_DF_4_reg_jit(ctx: &mut JitContext, r: u32) { } pub fn instr_DF_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read64(ctx); + codegen::gen_modrm_resolve_safe_read64(ctx, modrm_byte); ctx.builder.instruction_body.convert_i64_to_f64(); codegen::gen_call_fn1_f64(ctx.builder, "fpu_push"); } @@ -4464,9 +4454,8 @@ pub fn instr_660F6E_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { pub fn instr_660F6F_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { // XXX: Aligned read or #gp - codegen::gen_modrm_resolve(ctx, modrm_byte); let dest = global_pointers::get_reg_xmm_low_offset(r); - codegen::gen_safe_read128(ctx, dest); + codegen::gen_modrm_resolve_safe_read128(ctx, modrm_byte, dest); } pub fn instr_660F6F_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { ctx.builder.instruction_body.const_i32(r1 as i32); @@ -4474,9 +4463,8 @@ pub fn instr_660F6F_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { codegen::gen_call_fn2(ctx.builder, "instr_660F6F_reg") } pub fn instr_F30F6F_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); let dest = global_pointers::get_reg_xmm_low_offset(r); - codegen::gen_safe_read128(ctx, dest); + codegen::gen_modrm_resolve_safe_read128(ctx, modrm_byte, dest); } pub fn instr_F30F6F_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { ctx.builder.instruction_body.const_i32(r1 as i32); @@ -4485,10 +4473,9 @@ pub fn instr_F30F6F_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { } pub fn instr_660F70_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - let imm8 = ctx.cpu.read_imm8(); let dest = global_pointers::SSE_SCRATCH_REGISTER; - codegen::gen_safe_read128(ctx, dest); + codegen::gen_modrm_resolve_safe_read128(ctx, modrm_byte, dest); + let imm8 = ctx.cpu.read_imm8(); ctx.builder.instruction_body.const_i32(dest as i32); ctx.builder.instruction_body.const_i32(r as i32); ctx.builder.instruction_body.const_i32(imm8 as i32); @@ -4502,10 +4489,9 @@ pub fn instr_660F70_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm8: u32) { codegen::gen_call_fn3(ctx.builder, "instr_660F70"); } pub fn instr_F20F70_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - let imm8 = ctx.cpu.read_imm8(); let dest = global_pointers::SSE_SCRATCH_REGISTER; - codegen::gen_safe_read128(ctx, dest); + codegen::gen_modrm_resolve_safe_read128(ctx, modrm_byte, dest); + let imm8 = ctx.cpu.read_imm8(); ctx.builder.instruction_body.const_i32(dest as i32); ctx.builder.instruction_body.const_i32(r as i32); ctx.builder.instruction_body.const_i32(imm8 as i32); @@ -4519,10 +4505,9 @@ pub fn instr_F20F70_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm8: u32) { codegen::gen_call_fn3(ctx.builder, "instr_F20F70"); } pub fn instr_F30F70_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { - codegen::gen_modrm_resolve(ctx, modrm_byte); - let imm8 = ctx.cpu.read_imm8(); let dest = global_pointers::SSE_SCRATCH_REGISTER; - codegen::gen_safe_read128(ctx, dest); + codegen::gen_modrm_resolve_safe_read128(ctx, modrm_byte, dest); + let imm8 = ctx.cpu.read_imm8(); ctx.builder.instruction_body.const_i32(dest as i32); ctx.builder.instruction_body.const_i32(r as i32); ctx.builder.instruction_body.const_i32(imm8 as i32); @@ -4565,8 +4550,7 @@ pub fn instr_F30F7E_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { ctx.builder .instruction_body .const_i32(global_pointers::get_reg_xmm_low_offset(r) as i32); - codegen::gen_modrm_resolve(ctx, modrm_byte); - codegen::gen_safe_read64(ctx); + codegen::gen_modrm_resolve_safe_read64(ctx, modrm_byte); ctx.builder.instruction_body.store_aligned_i64(0); ctx.builder From 17cca458fae45f0f6e5d8ffecfd5fe10cdb0bfb8 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1616/2137] Print stdout/stderr before failing --- tools/rust-lld-wrapper | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/rust-lld-wrapper b/tools/rust-lld-wrapper index 865cad37..60a092ea 100755 --- a/tools/rust-lld-wrapper +++ b/tools/rust-lld-wrapper @@ -27,11 +27,12 @@ def main(): lld = find_rust_lld() result = subprocess.run([lld] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - result.check_returncode() print(result.stderr, file=sys.stderr) print(result.stdout) + result.check_returncode() + def find_rust_lld(): which = subprocess.run(["rustup", "which", "rustc"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) which.check_returncode() From 753f67bfab31e35f744a58aae2763a19ac42927c Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1617/2137] Makefile: Clean up and add all-tests target --- Makefile | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index d026b0e2..72366d44 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,5 @@ CLOSURE_DIR=closure-compiler CLOSURE=$(CLOSURE_DIR)/compiler.jar -BROWSER=chromium NASM_TEST_DIR=./tests/nasm COVERAGE_DIR=./tests/coverage @@ -211,9 +210,7 @@ clean: $(MAKE) -C $(NASM_TEST_DIR) clean run: - python2 -m SimpleHTTPServer 2> /dev/null - #sleep 1 - #$(BROWSER) http://localhost:8000/index.html & + python3 -m http.server 2> /dev/null update_version: set -e ;\ @@ -232,7 +229,7 @@ $(CLOSURE): rm $(CLOSURE_DIR)/compiler-latest.zip tests: all-debug - mkdir -p images/integration-test-fs/flat + mkdir -p images/integration-test-fs/flat # XXX cp images/bzImage images/integration-test-fs/ touch images/integration-test-fs/initrd cd images/integration-test-fs && tar cfv fs.tar bzImage initrd @@ -241,7 +238,7 @@ tests: all-debug ./tests/full/run.js tests-release: all - mkdir -p images/integration-test-fs/flat + mkdir -p images/integration-test-fs/flat # XXX cp images/bzImage images/integration-test-fs/ touch images/integration-test-fs/initrd cd images/integration-test-fs && tar cfv fs.tar bzImage initrd @@ -281,7 +278,7 @@ expect-tests: all-debug build/libwabt.js devices-test: all-debug ./tests/devices/filestorage.js - ./tests/devices/virtio_9p.js + #./tests/devices/virtio_9p.js # XXX: Hangs rust-test: $(RUST_FILES) env RUST_BACKTRACE=full RUST_TEST_THREADS=1 RUSTFLAGS="-D warnings" cargo +nightly test -- --nocapture @@ -294,6 +291,11 @@ api-tests: all-debug ./tests/api/clean-shutdown.js ./tests/api/state.js +all-tests: jshint kvm-unit-test expect-tests qemutests jitpagingtests api-tests rust-test nasmtests nasmtests-force-jit tests + # Skipping: + # - debiantests (requires network) + # - devices-test (hangs) + covreport: mkdir -p $(COVERAGE_DIR)/build/ $(COVERAGE_DIR)/gen_report.js From c207400922d1f64e4421cfbcbc65d5a0baf2f600 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1618/2137] Fix Rust warnings --- gen/generate_analyzer.js | 6 ------ gen/generate_interpreter.js | 6 ------ gen/generate_jit.js | 6 ------ src/rust/codegen.rs | 4 ++-- src/rust/cpu2/fpu.rs | 2 +- src/rust/cpu2/imports.rs | 14 ++++++-------- src/rust/jit.rs | 2 +- src/rust/jit_instructions.rs | 2 +- src/rust/lib.rs | 1 - 9 files changed, 11 insertions(+), 32 deletions(-) diff --git a/gen/generate_analyzer.js b/gen/generate_analyzer.js index ff2171f5..0a462c61 100755 --- a/gen/generate_analyzer.js +++ b/gen/generate_analyzer.js @@ -429,17 +429,11 @@ function gen_table() type: "switch", condition: "opcode", cases: cases0f_16, - default_case: { - body: ["dbg_assert!(false);"] - }, }; const table0f_32 = { type: "switch", condition: "opcode", cases: cases0f_32, - default_case: { - body: ["dbg_assert!(false);"] - }, }; if(to_generate.analyzer0f_16) diff --git a/gen/generate_interpreter.js b/gen/generate_interpreter.js index f8abd253..db039ad8 100755 --- a/gen/generate_interpreter.js +++ b/gen/generate_interpreter.js @@ -461,17 +461,11 @@ function gen_table() 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);"] - }, }; if(to_generate.interpreter0f_16) diff --git a/gen/generate_jit.js b/gen/generate_jit.js index 8cc9b3e7..9d75fb3e 100755 --- a/gen/generate_jit.js +++ b/gen/generate_jit.js @@ -540,17 +540,11 @@ function gen_table() 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);"] - }, }; if(to_generate.jit0f_16) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 6b3a70c9..64636ccb 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -1220,8 +1220,8 @@ pub fn gen_safe_read_write( ctx: &mut JitContext, bits: BitSize, address_local: &WasmLocal, - f: &Fn(&mut JitContext), - fallback_fn: &Fn(&mut JitContext), + f: &dyn Fn(&mut JitContext), + fallback_fn: &dyn Fn(&mut JitContext), ) { ctx.builder.instruction_body.get_local(address_local); diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 98e81f56..01e283b8 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -633,7 +633,7 @@ pub unsafe fn fpu_fstenv(addr: i32) { pub unsafe fn fpu_load_tag_word() -> i32 { let mut tag_word: i32 = 0; for i in 0..8 { - let mut value: f64 = *fpu_st.offset(i as isize); + let value: f64 = *fpu_st.offset(i as isize); if 0 != *fpu_stack_empty >> i & 1 { tag_word |= 3 << (i << 1) } diff --git a/src/rust/cpu2/imports.rs b/src/rust/cpu2/imports.rs index bd08128b..fd06fda6 100644 --- a/src/rust/cpu2/imports.rs +++ b/src/rust/cpu2/imports.rs @@ -3,14 +3,12 @@ use std::alloc; #[no_mangle] pub fn call_indirect1(f: fn(u16), x: u16) { f(x); } -extern "C" { - #[no_mangle] - pub static mut mem8: *mut u8; - #[no_mangle] - pub static mut mem16: *mut u16; - #[no_mangle] - pub static mut mem32s: *mut i32; -} +#[no_mangle] +pub static mut mem8: *mut u8 = 0 as *mut u8; +#[no_mangle] +pub static mut mem16: *mut u16 = 0 as *mut u16; +#[no_mangle] +pub static mut mem32s: *mut i32 = 0 as *mut i32; #[no_mangle] pub fn allocate_memory(size: u32) -> u32 { diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 3b9185a7..b609870f 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -792,7 +792,7 @@ fn jit_analyze_and_generate( }; if let Some(entry_points) = entry_points { - let (mut basic_blocks, requires_loop_limit) = + let (basic_blocks, requires_loop_limit) = jit_find_basic_blocks(page, &entry_points, cpu.clone()); //for b in basic_blocks.iter() { diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 8d7ae1fb..82cec4be 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -190,7 +190,7 @@ fn group_arith_ax_imm16(ctx: &mut JitContext, op: &str, imm16: u32) { fn group_arith_eax_imm32( ctx: &mut JitContext, - op: &Fn(&mut WasmBuilder, &WasmLocal, &LocalOrImmedate), + op: &dyn Fn(&mut WasmBuilder, &WasmLocal, &LocalOrImmedate), imm32: u32, ) { op( diff --git a/src/rust/lib.rs b/src/rust/lib.rs index 369d132c..230db563 100644 --- a/src/rust/lib.rs +++ b/src/rust/lib.rs @@ -1,6 +1,5 @@ #![feature(const_fn)] #![feature(extern_types)] -#![feature(range_contains)] #[cfg(test)] #[macro_use] From 17f248868446ec815299c8be96f59c6cebd5f101 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1619/2137] Fix uses of writable_or_pagefault from JS --- src/cpu.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index 41abe754..dabd6a3b 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -1911,14 +1911,14 @@ CPU.prototype.far_jump = function(eip, selector, is_call) } if(ss_info.size) { - if(this.writable_or_pagefault(ss_info.base + new_esp - stack_space | 0, stack_space)) // , cs_info.dpl + if(!this.writable_or_pagefault(ss_info.base + new_esp - stack_space | 0, stack_space)) // , cs_info.dpl { return; } } else { - if(this.writable_or_pagefault(ss_info.base + (new_esp - stack_space & 0xFFFF) | 0, stack_space)) // , cs_info.dpl + if(!this.writable_or_pagefault(ss_info.base + (new_esp - stack_space & 0xFFFF) | 0, stack_space)) // , cs_info.dpl { return; } @@ -2163,7 +2163,7 @@ CPU.prototype.do_task_switch = function(selector, has_error_code, error_code) old_eflags &= ~flag_nt; } - if(this.writable_or_pagefault(tsr_offset, 0x66)) + if(!this.writable_or_pagefault(tsr_offset, 0x66)) { return; } From 1c474eabdb6b4e4d8fa13553629aea35b9baa3a0 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1620/2137] Fix mov [mem], sreg in 32-bit mode (should be 16-bit write) --- src/rust/cpu2/instructions.rs | 2 +- src/rust/jit_instructions.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index eb4b103e..ab067808 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -1530,7 +1530,7 @@ pub unsafe fn instr32_8C_reg(r: i32, seg: i32) { #[no_mangle] pub unsafe fn instr32_8C_mem(addr: i32, seg: i32) { if instr_8C_check_sreg(seg) { - return_on_pagefault!(safe_write32(addr, *sreg.offset(seg as isize) as i32)); + return_on_pagefault!(safe_write16(addr, *sreg.offset(seg as isize) as i32)); }; } #[no_mangle] diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 82cec4be..34700672 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -2131,7 +2131,7 @@ pub fn instr32_8C_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { else { codegen::gen_get_sreg(ctx, r); let value_local = ctx.builder.set_new_local(); - codegen::gen_safe_write32(ctx, &address_local, &value_local); + codegen::gen_safe_write16(ctx, &address_local, &value_local); ctx.builder.free_local(value_local); } ctx.builder.free_local(address_local); From 7f41e6fe4852c96204f9ee08d4994fcdc5139c4e Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1621/2137] Test for mov [mem], sreg --- tests/nasm/mov_sreg.asm | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tests/nasm/mov_sreg.asm diff --git a/tests/nasm/mov_sreg.asm b/tests/nasm/mov_sreg.asm new file mode 100644 index 00000000..aa8d901e --- /dev/null +++ b/tests/nasm/mov_sreg.asm @@ -0,0 +1,21 @@ +global _start + +section .data + align 16 +mydword: + dd 0 + +%include "header.inc" + + ; 32-bit register move should set higher bits to zero + mov eax, -1 + mov eax, ss + and eax, 0xffff0000 + + ; 32-bit memory move should preserver higher bits + mov dword [mydword], 0xdeadbeef + mov [mydword], ss + mov ebx, [mydword] + and ebx, 0xffff0000 + +%include "footer.inc" From 5e73b6f21bf749032e2409dccb5a7a918c52910c Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1622/2137] Remove invalid assertion on sfence/mfence/lfence (low bits of modrm byte are ignored) --- src/rust/cpu2/instructions_0f.rs | 9 +++------ src/rust/jit_instructions.rs | 4 ++-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 0152e1bb..6849dcd9 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -3312,9 +3312,8 @@ pub unsafe fn instr_0FAE_4_mem(addr: i32) { undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0FAE_5_reg(r: i32) { +pub unsafe fn instr_0FAE_5_reg(_r: i32) { // lfence - dbg_assert!(r == 0, "Unexpected lfence encoding"); } #[no_mangle] pub unsafe fn instr_0FAE_5_mem(addr: i32) { @@ -3322,9 +3321,8 @@ pub unsafe fn instr_0FAE_5_mem(addr: i32) { undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0FAE_6_reg(r: i32) { +pub unsafe fn instr_0FAE_6_reg(_r: i32) { // mfence - dbg_assert!(r == 0, "Unexpected mfence encoding"); } #[no_mangle] pub unsafe fn instr_0FAE_6_mem(addr: i32) { @@ -3332,9 +3330,8 @@ pub unsafe fn instr_0FAE_6_mem(addr: i32) { undefined_instruction(); } #[no_mangle] -pub unsafe fn instr_0FAE_7_reg(r: i32) { +pub unsafe fn instr_0FAE_7_reg(_r: i32) { // sfence - dbg_assert!(r == 0, "Unexpected sfence encoding"); } #[no_mangle] pub unsafe fn instr_0FAE_7_mem(addr: i32) { diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 34700672..7df4b962 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -4607,8 +4607,8 @@ pub fn instr_0FAE_5_mem_jit(ctx: &mut JitContext, _modrm_byte: u8) { dbg_log!("Generating #ud for unimplemented instruction: instr_0FAE_5_mem_jit"); codegen::gen_trigger_ud(ctx); } -pub fn instr_0FAE_5_reg_jit(_ctx: &mut JitContext, r: u32) { - dbg_assert!(r == 0, "Unexpected lfence encoding"); +pub fn instr_0FAE_5_reg_jit(_ctx: &mut JitContext, _r: u32) { + // For this instruction, the processor ignores the r/m field of the ModR/M byte. } pub fn instr_660FD6_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { From d2c01c31a3508765c2e6e589ecb721e9b0bfaf1a Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1623/2137] Fix memory dumps --- src/browser/main.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/browser/main.js b/src/browser/main.js index 01a9134c..68dc2d46 100644 --- a/src/browser/main.js +++ b/src/browser/main.js @@ -1094,7 +1094,8 @@ $("memory_dump").onclick = function() { - dump_file(emulator.v86.cpu.mem8, "v86memory.bin"); + const mem8 = emulator.v86.cpu.mem8; + dump_file(new Uint8Array(mem8.buffer, mem8.byteOffset, mem8.length), "v86memory.bin"); $("memory_dump").blur(); }; From c47b4b252cc3f93d7278ff710160eb33e7d8c018 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1624/2137] Optimise cr0 access in task_switch_test (only low byte needed) --- src/rust/codegen.rs | 6 ++++-- tests/expect/tests/task_switch_test.wast | 2 +- tests/expect/tests/task_switch_test_sse.wast | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 64636ccb..0d8d59bc 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -1072,7 +1072,8 @@ pub fn gen_task_switch_test(ctx: &mut JitContext) { // generate if(cr[0] & (CR0_EM | CR0_TS)) { task_switch_test_void(); return; } let cr0_offset = global_pointers::get_creg_offset(0); - ctx.builder.instruction_body.load_aligned_i32(cr0_offset); + dbg_assert!(regs::CR0_EM | regs::CR0_TS <= 0xFF); + ctx.builder.instruction_body.load_u8(cr0_offset); ctx.builder .instruction_body .const_i32((regs::CR0_EM | regs::CR0_TS) as i32); @@ -1094,7 +1095,8 @@ pub fn gen_task_switch_test_mmx(ctx: &mut JitContext) { // generate if(cr[0] & (CR0_EM | CR0_TS)) { task_switch_test_mmx_void(); return; } let cr0_offset = global_pointers::get_creg_offset(0); - ctx.builder.instruction_body.load_aligned_i32(cr0_offset); + dbg_assert!(regs::CR0_EM | regs::CR0_TS <= 0xFF); + ctx.builder.instruction_body.load_u8(cr0_offset); ctx.builder .instruction_body .const_i32((regs::CR0_EM | regs::CR0_TS) as i32); diff --git a/tests/expect/tests/task_switch_test.wast b/tests/expect/tests/task_switch_test.wast index 4f36f5e5..62207ea5 100644 --- a/tests/expect/tests/task_switch_test.wast +++ b/tests/expect/tests/task_switch_test.wast @@ -93,7 +93,7 @@ (get_local $l0))) (if $I5 (i32.and - (i32.load + (i32.load8_u (i32.const 580)) (i32.const 12)) (then diff --git a/tests/expect/tests/task_switch_test_sse.wast b/tests/expect/tests/task_switch_test_sse.wast index 1d624be7..896c0cd5 100644 --- a/tests/expect/tests/task_switch_test_sse.wast +++ b/tests/expect/tests/task_switch_test_sse.wast @@ -108,7 +108,7 @@ (i32.const 32))) (if $I6 (i32.and - (i32.load + (i32.load8_u (i32.const 580)) (i32.const 12)) (then From 4e9fa5e783573d290af5853254be51926c0b73cc Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1625/2137] refactor --- src/rust/codegen.rs | 74 +++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 40 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 0d8d59bc..862f4938 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -30,26 +30,42 @@ pub fn gen_add_cs_offset(ctx: &mut JitContext) { } pub fn gen_set_previous_eip_offset_from_eip(builder: &mut WasmBuilder, n: u32) { + // previous_ip = instruction_pointer + n let cs = &mut builder.instruction_body; - cs.const_i32(global_pointers::PREVIOUS_IP as i32); // store address of previous ip - cs.load_aligned_i32(global_pointers::INSTRUCTION_POINTER); // load ip + cs.const_i32(global_pointers::PREVIOUS_IP as i32); + cs.load_aligned_i32(global_pointers::INSTRUCTION_POINTER); if n != 0 { cs.const_i32(n as i32); - cs.add_i32(); // add constant to ip value + cs.add_i32(); } - cs.store_aligned_i32(0); // store it as previous ip + cs.store_aligned_i32(0); +} + +pub fn gen_set_previous_eip_offset_from_eip_with_low_bits( + builder: &mut WasmBuilder, + low_bits: i32, +) { + // previous_ip = instruction_pointer & ~0xFFF | low_bits; + builder + .instruction_body + .const_i32(global_pointers::PREVIOUS_IP as i32); + builder + .instruction_body + .load_aligned_i32(global_pointers::INSTRUCTION_POINTER); + builder.instruction_body.const_i32(!0xFFF); + builder.instruction_body.and_i32(); + builder.instruction_body.const_i32(low_bits); + builder.instruction_body.or_i32(); + builder.instruction_body.store_aligned_i32(0); } pub fn gen_increment_instruction_pointer(builder: &mut WasmBuilder, n: u32) { let cs = &mut builder.instruction_body; - cs.const_i32(global_pointers::INSTRUCTION_POINTER as i32); // store address of ip - - cs.load_aligned_i32(global_pointers::INSTRUCTION_POINTER); // load ip - + cs.const_i32(global_pointers::INSTRUCTION_POINTER as i32); + cs.load_aligned_i32(global_pointers::INSTRUCTION_POINTER); cs.const_i32(n as i32); - cs.add_i32(); - cs.store_aligned_i32(0); // store it back in + cs.store_aligned_i32(0); } pub fn gen_relative_jump(builder: &mut WasmBuilder, n: i32) { @@ -598,21 +614,10 @@ fn gen_safe_read( gen_call_fn2(ctx.builder, "report_safe_read_jit_slow"); } - ctx.builder - .instruction_body - .const_i32(global_pointers::PREVIOUS_IP as i32); - - ctx.builder - .instruction_body - .load_aligned_i32(global_pointers::INSTRUCTION_POINTER); - ctx.builder.instruction_body.const_i32(!0xFFF); - ctx.builder.instruction_body.and_i32(); - ctx.builder - .instruction_body - .const_i32(ctx.start_of_current_instruction as i32 & 0xFFF); - ctx.builder.instruction_body.or_i32(); - - ctx.builder.instruction_body.store_aligned_i32(0); + gen_set_previous_eip_offset_from_eip_with_low_bits( + ctx.builder, + ctx.start_of_current_instruction as i32 & 0xFFF, + ); ctx.builder.instruction_body.get_local(&address_local); match bits { @@ -774,21 +779,10 @@ fn gen_safe_write( gen_call_fn2(ctx.builder, "report_safe_write_jit_slow"); } - ctx.builder - .instruction_body - .const_i32(global_pointers::PREVIOUS_IP as i32); - - ctx.builder - .instruction_body - .load_aligned_i32(global_pointers::INSTRUCTION_POINTER); - ctx.builder.instruction_body.const_i32(!0xFFF); - ctx.builder.instruction_body.and_i32(); - ctx.builder - .instruction_body - .const_i32(ctx.start_of_current_instruction as i32 & 0xFFF); - ctx.builder.instruction_body.or_i32(); - - ctx.builder.instruction_body.store_aligned_i32(0); + gen_set_previous_eip_offset_from_eip_with_low_bits( + ctx.builder, + ctx.start_of_current_instruction as i32 & 0xFFF, + ); ctx.builder.instruction_body.get_local(&address_local); match value_local { From 0d76a7e99af6f5445b9611855d896d4eb7aba296 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1626/2137] Correctly set previous_ip before #nm (fixes segfaults in Linux) --- src/rust/codegen.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 862f4938..0ee23054 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -1075,10 +1075,16 @@ pub fn gen_task_switch_test(ctx: &mut JitContext) { ctx.builder.instruction_body.if_void(); + gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); + + gen_set_previous_eip_offset_from_eip_with_low_bits( + ctx.builder, + ctx.start_of_current_instruction as i32 & 0xFFF, + ); + gen_move_registers_from_locals_to_memory(ctx); gen_fn0_const(ctx.builder, "task_switch_test_void"); - gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); gen_clear_prefixes(ctx); ctx.builder.instruction_body.return_(); @@ -1098,10 +1104,16 @@ pub fn gen_task_switch_test_mmx(ctx: &mut JitContext) { ctx.builder.instruction_body.if_void(); + gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); + + gen_set_previous_eip_offset_from_eip_with_low_bits( + ctx.builder, + ctx.start_of_current_instruction as i32 & 0xFFF, + ); + gen_move_registers_from_locals_to_memory(ctx); gen_fn0_const(ctx.builder, "task_switch_test_mmx_void"); - gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); gen_clear_prefixes(ctx); ctx.builder.instruction_body.return_(); From cd0b6ce7537ed749e83459dab19fd75297530a12 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1627/2137] Fix off-by-on in assertion in write_blob/read_blob --- src/memory.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/memory.js b/src/memory.js index 7e05260b..f85bf55f 100644 --- a/src/memory.js +++ b/src/memory.js @@ -60,16 +60,23 @@ CPU.prototype.mmap_write128 = function(addr, value0, value1, value2, value3) CPU.prototype.write_blob = function(blob, offset) { dbg_assert(blob && blob.length >= 0); - dbg_assert(!this.in_mapped_range(offset)); - dbg_assert(!this.in_mapped_range(offset + blob.length)); - this.jit_dirty_cache(offset, offset + blob.length); - this.mem8.set(blob, offset); + if(blob.length) + { + dbg_assert(!this.in_mapped_range(offset)); + dbg_assert(!this.in_mapped_range(offset + blob.length - 1)); + + this.jit_dirty_cache(offset, offset + blob.length); + this.mem8.set(blob, offset); + } }; CPU.prototype.read_blob = function(offset, length) { - dbg_assert(!this.in_mapped_range(offset)); - dbg_assert(!this.in_mapped_range(offset + length)); + if(length) + { + dbg_assert(!this.in_mapped_range(offset)); + dbg_assert(!this.in_mapped_range(offset + length - 1)); + } return this.mem8.subarray(offset, offset + length); }; From 0c922cea95e7988aabd4d5a1a69ac4b56fa51eea Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1628/2137] Add config::LOG_PAGE_FAULTS --- src/rust/config.rs | 2 +- src/rust/cpu2/cpu.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rust/config.rs b/src/rust/config.rs index 8b137891..9eef738c 100644 --- a/src/rust/config.rs +++ b/src/rust/config.rs @@ -1 +1 @@ - +pub const LOG_PAGE_FAULTS: bool = false; diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index b7079b86..24ef50dc 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1322,7 +1322,7 @@ pub unsafe fn trigger_pagefault_jit(fault: PageFault) { let present = fault.present; let user = fault.user; - if false { + if ::config::LOG_PAGE_FAULTS { dbg_log!( "page fault jit w={} u={} p={} eip={:x} cr2={:x}", write as i32, @@ -1372,7 +1372,7 @@ pub unsafe fn trigger_pagefault(fault: PageFault) { let present = fault.present; let user = fault.user; - if false { + if ::config::LOG_PAGE_FAULTS { dbg_log!( "page fault w={} u={} p={} eip={:x} cr2={:x}", write as i32, From 492a2cf78e5e42f3eb48ade756b249cf97d18304 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1629/2137] Update previous_ip only if page fault is going to happen --- src/rust/codegen.rs | 22 ++++--- src/rust/cpu2/cpu.rs | 2 +- tests/expect/tests/call.wast | 32 +++++----- tests/expect/tests/indirect-call.wast | 32 +++++----- tests/expect/tests/mov16.wast | 64 ++++++++++---------- tests/expect/tests/mov32-mem.wast | 64 ++++++++++---------- tests/expect/tests/pop.wast | 16 ++--- tests/expect/tests/push.wast | 16 ++--- tests/expect/tests/task_switch_test.wast | 8 +++ tests/expect/tests/task_switch_test_sse.wast | 8 +++ 10 files changed, 141 insertions(+), 123 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 0ee23054..95049828 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -614,11 +614,6 @@ fn gen_safe_read( gen_call_fn2(ctx.builder, "report_safe_read_jit_slow"); } - gen_set_previous_eip_offset_from_eip_with_low_bits( - ctx.builder, - ctx.start_of_current_instruction as i32 & 0xFFF, - ); - ctx.builder.instruction_body.get_local(&address_local); match bits { BitSize::BYTE => { @@ -647,6 +642,12 @@ fn gen_safe_read( ctx.builder.instruction_body.if_void(); gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); + + gen_set_previous_eip_offset_from_eip_with_low_bits( + ctx.builder, + ctx.start_of_current_instruction as i32 & 0xFFF, + ); + // -2 for the exit-with-pagefault block, +2 for leaving the two nested ifs from this function let br_offset = ctx.current_brtable_depth - 2 + 2; ctx.builder.instruction_body.br(br_offset); @@ -779,11 +780,6 @@ fn gen_safe_write( gen_call_fn2(ctx.builder, "report_safe_write_jit_slow"); } - gen_set_previous_eip_offset_from_eip_with_low_bits( - ctx.builder, - ctx.start_of_current_instruction as i32 & 0xFFF, - ); - ctx.builder.instruction_body.get_local(&address_local); match value_local { GenSafeWriteValue::I32(local) => ctx.builder.instruction_body.get_local(local), @@ -817,6 +813,12 @@ fn gen_safe_write( ctx.builder.instruction_body.if_void(); gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); + + gen_set_previous_eip_offset_from_eip_with_low_bits( + ctx.builder, + ctx.start_of_current_instruction as i32 & 0xFFF, + ); + // -2 for the exit-with-pagefault block, +2 for leaving the two nested ifs from this function let br_offset = ctx.current_brtable_depth - 2 + 2; ctx.builder.instruction_body.br(br_offset); diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 24ef50dc..038b2a53 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1356,13 +1356,13 @@ pub unsafe fn trigger_pagefault_jit(fault: PageFault) { let page = ((addr as u32) >> 12) as i32; *tlb_data.offset(page as isize) = 0; *prefixes = 0; - *instruction_pointer = *previous_ip; *page_fault_error_code = (user as i32) << 2 | (write as i32) << 1 | present as i32; //*page_fault = true; } #[no_mangle] pub unsafe fn trigger_pagefault_end_jit() { + *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_PF, false, Some(*page_fault_error_code)); } diff --git a/tests/expect/tests/call.wast b/tests/expect/tests/call.wast index 643c3284..acab6911 100644 --- a/tests/expect/tests/call.wast +++ b/tests/expect/tests/call.wast @@ -143,14 +143,6 @@ (get_local $l12)) (get_local $l10))) (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 0))) (call $e.safe_write32_slow_jit (get_local $l12) (get_local $l10)) @@ -158,6 +150,14 @@ (i32.load8_u (i32.const 540)) (then + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 0))) (br $B3))))) (set_local $l6 (get_local $l11)) @@ -315,20 +315,20 @@ (i32.const -4096)) (get_local $l10)))) (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 7))) (call $e.safe_read32s_slow_jit (get_local $l10)) (if $I10 (i32.load8_u (i32.const 540)) (then + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 7))) (br $B3))))) (set_local $l6 (i32.add diff --git a/tests/expect/tests/indirect-call.wast b/tests/expect/tests/indirect-call.wast index ef02d950..79c8b639 100644 --- a/tests/expect/tests/indirect-call.wast +++ b/tests/expect/tests/indirect-call.wast @@ -133,20 +133,20 @@ (i32.const -4096)) (get_local $l10)))) (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 0))) (call $e.safe_read32s_slow_jit (get_local $l10)) (if $I7 (i32.load8_u (i32.const 540)) (then + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 0))) (br $B3))))) (i32.load (i32.const 740)))) @@ -191,14 +191,6 @@ (get_local $l13)) (get_local $l11))) (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 0))) (call $e.safe_write32_slow_jit (get_local $l13) (get_local $l11)) @@ -206,6 +198,14 @@ (i32.load8_u (i32.const 540)) (then + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 0))) (br $B3))))) (set_local $l6 (get_local $l12)) diff --git a/tests/expect/tests/mov16.wast b/tests/expect/tests/mov16.wast index 356bb112..6300b6fb 100644 --- a/tests/expect/tests/mov16.wast +++ b/tests/expect/tests/mov16.wast @@ -131,20 +131,20 @@ (i32.const -4096)) (get_local $l10)))) (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 3))) (call $e.safe_read16_slow_jit (get_local $l10)) (if $I6 (i32.load8_u (i32.const 540)) (then + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 3))) (br $B3))))) (i32.const 65535)) (i32.and @@ -184,20 +184,20 @@ (i32.const -4096)) (get_local $l10)))) (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 7))) (call $e.safe_read16_slow_jit (get_local $l10)) (if $I8 (i32.load8_u (i32.const 540)) (then + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 7))) (br $B3))))) (i32.const 65535)) (i32.and @@ -263,14 +263,6 @@ (get_local $l10)) (get_local $l11))) (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 19))) (call $e.safe_write16_slow_jit (get_local $l10) (get_local $l11)) @@ -278,6 +270,14 @@ (i32.load8_u (i32.const 540)) (then + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 19))) (br $B3))))) (set_local $l11 (i32.add @@ -323,14 +323,6 @@ (get_local $l11)) (get_local $l10))) (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 21))) (call $e.safe_write16_slow_jit (get_local $l11) (get_local $l10)) @@ -338,6 +330,14 @@ (i32.load8_u (i32.const 540)) (then + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 21))) (br $B3))))) (set_local $l3 (i32.or diff --git a/tests/expect/tests/mov32-mem.wast b/tests/expect/tests/mov32-mem.wast index 75a87c89..8c191199 100644 --- a/tests/expect/tests/mov32-mem.wast +++ b/tests/expect/tests/mov32-mem.wast @@ -125,14 +125,6 @@ (get_local $l10)) (get_local $l11))) (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 0))) (call $e.safe_write32_slow_jit (get_local $l10) (get_local $l11)) @@ -140,6 +132,14 @@ (i32.load8_u (i32.const 540)) (then + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 0))) (br $B3))))) (set_local $l11 (i32.add @@ -177,14 +177,6 @@ (get_local $l11)) (get_local $l10))) (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 6))) (call $e.safe_write32_slow_jit (get_local $l11) (get_local $l10)) @@ -192,6 +184,14 @@ (i32.load8_u (i32.const 540)) (then + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 6))) (br $B3))))) (set_local $l10 (i32.add @@ -227,20 +227,20 @@ (i32.const -4096)) (get_local $l10)))) (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 12))) (call $e.safe_read32s_slow_jit (get_local $l10)) (if $I10 (i32.load8_u (i32.const 540)) (then + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 12))) (br $B3)))))) (set_local $l10 (i32.add @@ -276,20 +276,20 @@ (i32.const -4096)) (get_local $l10)))) (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 18))) (call $e.safe_read32s_slow_jit (get_local $l10)) (if $I12 (i32.load8_u (i32.const 540)) (then + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 18))) (br $B3)))))) (i32.store (i32.const 560) diff --git a/tests/expect/tests/pop.wast b/tests/expect/tests/pop.wast index 2d60b759..973ffe28 100644 --- a/tests/expect/tests/pop.wast +++ b/tests/expect/tests/pop.wast @@ -119,20 +119,20 @@ (i32.const -4096)) (get_local $l10)))) (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 0))) (call $e.safe_read32s_slow_jit (get_local $l10)) (if $I6 (i32.load8_u (i32.const 540)) (then + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 0))) (br $B3))))) (set_local $l6 (i32.add diff --git a/tests/expect/tests/push.wast b/tests/expect/tests/push.wast index 136df313..b95e4677 100644 --- a/tests/expect/tests/push.wast +++ b/tests/expect/tests/push.wast @@ -123,14 +123,6 @@ (get_local $l11)) (get_local $l2))) (else - (i32.store - (i32.const 560) - (i32.or - (i32.and - (i32.load - (i32.const 556)) - (i32.const -4096)) - (i32.const 0))) (call $e.safe_write32_slow_jit (get_local $l11) (get_local $l2)) @@ -138,6 +130,14 @@ (i32.load8_u (i32.const 540)) (then + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 0))) (br $B3))))) (set_local $l6 (get_local $l10)) diff --git a/tests/expect/tests/task_switch_test.wast b/tests/expect/tests/task_switch_test.wast index 62207ea5..90b93570 100644 --- a/tests/expect/tests/task_switch_test.wast +++ b/tests/expect/tests/task_switch_test.wast @@ -97,6 +97,14 @@ (i32.const 580)) (i32.const 12)) (then + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 0))) (i32.store (i32.const 64) (get_local $l2)) diff --git a/tests/expect/tests/task_switch_test_sse.wast b/tests/expect/tests/task_switch_test_sse.wast index 896c0cd5..d51ad31c 100644 --- a/tests/expect/tests/task_switch_test_sse.wast +++ b/tests/expect/tests/task_switch_test_sse.wast @@ -112,6 +112,14 @@ (i32.const 580)) (i32.const 12)) (then + (i32.store + (i32.const 560) + (i32.or + (i32.and + (i32.load + (i32.const 556)) + (i32.const -4096)) + (i32.const 0))) (i32.store (i32.const 64) (get_local $l2)) From e2eecc729587068131853243ec1045d6394012ae Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1630/2137] task_switch_test*_jit: assert that jit agrees --- src/rust/codegen.rs | 4 ++-- src/rust/cpu2/cpu.rs | 10 ++++++++-- tests/expect/tests/task_switch_test.wast | 4 ++-- tests/expect/tests/task_switch_test_sse.wast | 4 ++-- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 95049828..61b17938 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -1085,7 +1085,7 @@ pub fn gen_task_switch_test(ctx: &mut JitContext) { ); gen_move_registers_from_locals_to_memory(ctx); - gen_fn0_const(ctx.builder, "task_switch_test_void"); + gen_fn0_const(ctx.builder, "task_switch_test_jit"); gen_clear_prefixes(ctx); ctx.builder.instruction_body.return_(); @@ -1114,7 +1114,7 @@ pub fn gen_task_switch_test_mmx(ctx: &mut JitContext) { ); gen_move_registers_from_locals_to_memory(ctx); - gen_fn0_const(ctx.builder, "task_switch_test_mmx_void"); + gen_fn0_const(ctx.builder, "task_switch_test_mmx_jit"); gen_clear_prefixes(ctx); ctx.builder.instruction_body.return_(); diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 038b2a53..7c7f662d 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -2842,7 +2842,10 @@ pub unsafe fn set_mxcsr(new_mxcsr: i32) { } #[no_mangle] -pub unsafe fn task_switch_test_void() { task_switch_test(); } +pub unsafe fn task_switch_test_jit() { + let did_fault = !task_switch_test(); + dbg_assert!(did_fault); +} pub unsafe fn task_switch_test_mmx() -> bool { if *cr.offset(4) & CR4_OSFXSR == 0 { @@ -2862,7 +2865,10 @@ pub unsafe fn task_switch_test_mmx() -> bool { } #[no_mangle] -pub unsafe fn task_switch_test_mmx_void() { task_switch_test_mmx(); } +pub unsafe fn task_switch_test_mmx_jit() { + let did_fault = !task_switch_test_mmx(); + dbg_assert!(did_fault); +} pub unsafe fn read_moffs() -> OrPageFault { // read 2 or 4 byte from ip, depending on address size attribute diff --git a/tests/expect/tests/task_switch_test.wast b/tests/expect/tests/task_switch_test.wast index 90b93570..1c9dc7c6 100644 --- a/tests/expect/tests/task_switch_test.wast +++ b/tests/expect/tests/task_switch_test.wast @@ -15,7 +15,7 @@ (type $t13 (func (param f64) (result i64))) (type $t14 (func (param i32 i32 i32) (result i32))) (type $t15 (func (param i32 i64 i64))) - (import "e" "task_switch_test_void" (func $e.task_switch_test_void (type $t0))) + (import "e" "task_switch_test_jit" (func $e.task_switch_test_jit (type $t0))) (import "e" "fpu_get_sti" (func $e.fpu_get_sti (type $t7))) (import "e" "fpu_fadd" (func $e.fpu_fadd (type $t8))) (import "e" "fpu_pop" (func $e.fpu_pop (type $t0))) @@ -129,7 +129,7 @@ (i32.store (i32.const 92) (get_local $l9)) - (call $e.task_switch_test_void) + (call $e.task_switch_test_jit) (i32.store (i32.const 648) (i32.const 0)) diff --git a/tests/expect/tests/task_switch_test_sse.wast b/tests/expect/tests/task_switch_test_sse.wast index d51ad31c..1998bbf4 100644 --- a/tests/expect/tests/task_switch_test_sse.wast +++ b/tests/expect/tests/task_switch_test_sse.wast @@ -15,7 +15,7 @@ (type $t13 (func (param f64) (result i64))) (type $t14 (func (param i32 i32 i32) (result i32))) (type $t15 (func (param i32 i64 i64))) - (import "e" "task_switch_test_mmx_void" (func $e.task_switch_test_mmx_void (type $t0))) + (import "e" "task_switch_test_mmx_jit" (func $e.task_switch_test_mmx_jit (type $t0))) (import "e" "instr_660F54_reg" (func $e.instr_660F54_reg (type $t2))) (import "e" "instr_F4" (func $e.instr_F4 (type $t0))) (import "e" "trigger_pagefault_end_jit" (func $e.trigger_pagefault_end_jit (type $t0))) @@ -144,7 +144,7 @@ (i32.store (i32.const 92) (get_local $l9)) - (call $e.task_switch_test_mmx_void) + (call $e.task_switch_test_mmx_jit) (i32.store (i32.const 648) (i32.const 0)) From 861aea3157f7cd00c9fa8237ba95f120d78b16f0 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1631/2137] Add recording serial adapter --- src/browser/serial.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/browser/serial.js b/src/browser/serial.js index dd5af3b0..338c8d21 100644 --- a/src/browser/serial.js +++ b/src/browser/serial.js @@ -192,3 +192,19 @@ function SerialAdapter(element, bus) } } } + +/** + * @constructor + * + * @param {BusConnector} bus + */ +function SerialRecordingAdapter(bus) +{ + var serial = this; + this.text = ""; + + bus.register("serial0-output-char", function(chr) + { + this.text += chr; + }, this); +} From 7d48636ddaf74f842a2591481c973fb65c061ffa Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1632/2137] Integration tests: Use debug bios --- tests/full/run.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/full/run.js b/tests/full/run.js index 3e9016a4..1dff70fa 100755 --- a/tests/full/run.js +++ b/tests/full/run.js @@ -510,11 +510,16 @@ function run_test(test, done) var bios = root_path + "/bios/bochs-bios.bin"; var vga_bios = root_path + "/bios/bochs-vgabios.bin"; } - else + else if(TEST_RELEASE_BUILD) { var bios = root_path + "/bios/seabios.bin"; var vga_bios = root_path + "/bios/vgabios.bin"; } + else + { + var bios = root_path + "/bios/seabios-debug.bin"; + var vga_bios = root_path + "/bios/vgabios-debug.bin"; + } var settings = { bios: { url: bios }, From 70e637b31bb316dacabbedfa3aa1da99d4927ba2 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1633/2137] Integration test: Check serial text --- tests/full/run.js | 55 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/tests/full/run.js b/tests/full/run.js index 1dff70fa..937a4483 100755 --- a/tests/full/run.js +++ b/tests/full/run.js @@ -210,11 +210,13 @@ if(cluster.isMaster) skip_if_disk_image_missing: true, cdrom: root_path + "/images/linux4.iso", timeout: 200, - // TODO: Check serial expected_texts: [ "~%", "Files send via emulator appear in", ], + expected_serial_text: [ + "Files send via emulator appear in", + ], expect_mouse_registered: true, }, { @@ -226,6 +228,9 @@ if(cluster.isMaster) "~%", "Files send via emulator appear in", ], + expected_serial_text: [ + "Files send via emulator appear in", + ], expect_mouse_registered: true, }, { @@ -241,6 +246,9 @@ if(cluster.isMaster) "~%", "Files send via emulator appear in", ], + expected_serial_text: [ + "Files send via emulator appear in", + ], expect_mouse_registered: true, }, { @@ -320,7 +328,6 @@ if(cluster.isMaster) } ], }, - // TODO: Check serial text { name: "Haiku", skip_if_disk_image_missing: true, @@ -561,6 +568,11 @@ function run_test(test, done) test.expected_texts = []; } + if(!test.expected_serial_text) + { + test.expected_serial_text = []; + } + var emulator = new V86(settings); var screen = new Uint8Array(SCREEN_WIDTH * 25); @@ -569,6 +581,11 @@ function run_test(test, done) return test.expected_texts.length === 0; } + function check_serial_test_done() + { + return test.expected_serial_text.length === 0; + } + var mouse_test_done = false; function check_mouse_test_done() { @@ -579,7 +596,7 @@ function run_test(test, done) var size_test_done = false; function check_grapical_test_done() { - return !test.expect_graphical_mode || (graphical_test_done && (!test.expect_graphical_size || size_test_done)); + return !test.expect_graphical_mode || (graphical_test_done && (!test.expect_graphical_size || size_test_done)); } var test_start = Date.now(); @@ -597,7 +614,10 @@ function run_test(test, done) return; } - if(check_text_test_done() && check_mouse_test_done() && check_grapical_test_done()) + if(check_text_test_done() && + check_mouse_test_done() && + check_grapical_test_done() && + check_serial_test_done()) { var end = Date.now(); @@ -703,6 +723,33 @@ function run_test(test, done) } }); + let serial_line = ""; + emulator.add_listener("serial0-output-char", function(c) + { + if(c === "\n") + { + if(VERBOSE) + { + console.log("Serial:", serial_line); + } + + if(test.expected_serial_text.length) + { + if(serial_line.includes(test.expected_serial_text[0])) + { + test.expected_serial_text.shift(); + check_test_done(); + } + } + + serial_line = ""; + } + else if(c >= " " && c <= "~") + { + serial_line += c; + } + }); + test.actions && test.actions.forEach(function(action) { if(action.on_text) From 85e846480fcc3bd17c33173bf1ca9c7dc8d80ca4 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1634/2137] Assert that TSC changes so that do_many_cycles_native is guaranteed to make progress --- src/rust/cpu2/cpu.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 7c7f662d..52abdff3 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1904,6 +1904,7 @@ pub unsafe fn cycle_internal() { RUN_FROM_CACHE_STEPS, (*timestamp_counter - initial_tsc) as u64, ); + dbg_assert!(*timestamp_counter != initial_tsc, "TSC didn't change"); if cfg!(feature = "profiler") && cfg!(feature = "profiler_instrument") { dbg_assert!(match ::cpu2::cpu::debug_last_jump { @@ -1960,6 +1961,7 @@ pub unsafe fn cycle_internal() { RUN_INTERPRETED_STEPS, (*timestamp_counter - initial_tsc) as u64, ); + dbg_assert!(*timestamp_counter != initial_tsc, "TSC didn't change"); }; } else { From 3f1ba044ed26e512dbdc8aa1e4ef45169dd3cedf Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1635/2137] Increment timestamp_counter before running basic block --- src/rust/jit.rs | 20 +++++------ tests/expect/tests/call.wast | 36 +++++++++---------- tests/expect/tests/do-while.wast | 24 ++++++------- tests/expect/tests/if.wast | 38 ++++++++++---------- tests/expect/tests/indirect-call.wast | 24 ++++++------- tests/expect/tests/mov16.wast | 12 +++---- tests/expect/tests/mov32-mem.wast | 12 +++---- tests/expect/tests/mov32-reg.wast | 12 +++---- tests/expect/tests/pop.wast | 12 +++---- tests/expect/tests/push.wast | 12 +++---- tests/expect/tests/task_switch_test.wast | 12 +++---- tests/expect/tests/task_switch_test_sse.wast | 24 ++++++------- tests/expect/tests/while-do.wast | 36 +++++++++---------- 13 files changed, 136 insertions(+), 138 deletions(-) diff --git a/src/rust/jit.rs b/src/rust/jit.rs index b609870f..30358b17 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -360,6 +360,7 @@ struct BasicBlock { end_addr: u32, is_entry_block: bool, ty: BasicBlockType, + number_of_instructions: u32, } #[repr(C)] @@ -482,6 +483,7 @@ fn jit_find_basic_blocks( end_addr: 0, ty: BasicBlockType::Exit, is_entry_block: false, + number_of_instructions: 0, }; loop { let addr_before_instruction = current_address; @@ -490,6 +492,7 @@ fn jit_find_basic_blocks( ..cpu }; let analysis = ::analysis::analyze_step(&mut ctx); + current_block.number_of_instructions += 1; let has_next_instruction = !analysis.no_next_instruction; current_address = ctx.eip; @@ -1064,7 +1067,7 @@ fn jit_generate_module( dbg_assert!(block.addr < block.end_addr); - jit_generate_basic_block(ctx, block.addr, block.last_instruction_addr, block.end_addr); + jit_generate_basic_block(ctx, block); let invalid_connection_to_next_block = block.end_addr != ctx.cpu.eip; dbg_assert!(!invalid_connection_to_next_block); @@ -1207,17 +1210,15 @@ fn jit_generate_module( ctx.builder.finish(); } -fn jit_generate_basic_block( - ctx: &mut JitContext, - start_addr: u32, - last_instruction_addr: u32, - stop_addr: u32, -) { - let mut count = 0; +fn jit_generate_basic_block(ctx: &mut JitContext, block: &BasicBlock) { + let start_addr = block.addr; + let last_instruction_addr = block.last_instruction_addr; + let stop_addr = block.end_addr; // First iteration of do-while assumes the caller confirms this condition dbg_assert!(!is_near_end_of_page(start_addr)); + codegen::gen_increment_timestamp_counter(ctx.builder, block.number_of_instructions as i32); ctx.cpu.eip = start_addr; loop { @@ -1257,7 +1258,6 @@ fn jit_generate_basic_block( dbg_assert!(instruction_length < MAX_INSTRUCTION_LENGTH); let end_addr = ctx.cpu.eip; - count += 1; if end_addr == stop_addr { // no page was crossed @@ -1273,8 +1273,6 @@ fn jit_generate_basic_block( break; } } - - codegen::gen_increment_timestamp_counter(ctx.builder, count); } pub fn jit_increase_hotness_and_maybe_compile( diff --git a/tests/expect/tests/call.wast b/tests/expect/tests/call.wast index acab6911..e6e3516e 100644 --- a/tests/expect/tests/call.wast +++ b/tests/expect/tests/call.wast @@ -92,6 +92,12 @@ (block $B6 (br_table $B6 $B5 $B4 $B3 $B2 (get_local $l0))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) (i32.store (i32.const 560) (i32.load @@ -167,15 +173,15 @@ (i32.load (i32.const 556)) (i32.const 1))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 1))) (set_local $l0 (i32.const 2)) (br $L0)) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) (i32.store (i32.const 560) (i32.load @@ -235,12 +241,6 @@ (set_local $l9 (i32.load (i32.const 92))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 1))) (i32.store (i32.const 64) (get_local $l2)) @@ -266,6 +266,12 @@ (i32.const 92) (get_local $l9)) (return)) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 2))) (set_local $l2 (call $e.inc32 (get_local $l2))) @@ -336,12 +342,6 @@ (i32.const 4))) (i32.add) (i32.store) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 2))) (i32.store (i32.const 64) (get_local $l2)) diff --git a/tests/expect/tests/do-while.wast b/tests/expect/tests/do-while.wast index b3d65150..7a32fe2e 100644 --- a/tests/expect/tests/do-while.wast +++ b/tests/expect/tests/do-while.wast @@ -89,6 +89,12 @@ (block $B5 (br_table $B5 $B4 $B3 $B2 (get_local $l0))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 3))) (set_local $l5 (call $e.inc32 (get_local $l5))) @@ -126,12 +132,6 @@ (i32.load (i32.const 556)) (i32.const 6))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 3))) (if $I7 (i32.eqz (if $I6 (result i32) @@ -169,6 +169,12 @@ (set_local $l0 (i32.const 0)) (br $L0)))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) (i32.store (i32.const 560) (i32.load @@ -228,12 +234,6 @@ (set_local $l9 (i32.load (i32.const 92))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 1))) (i32.store (i32.const 64) (get_local $l2)) diff --git a/tests/expect/tests/if.wast b/tests/expect/tests/if.wast index 80745826..a416c75c 100644 --- a/tests/expect/tests/if.wast +++ b/tests/expect/tests/if.wast @@ -91,6 +91,12 @@ (block $B6 (br_table $B6 $B5 $B4 $B3 $B2 (get_local $l0))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 2))) (set_local $l10 (i32.sub (get_local $l2) @@ -125,12 +131,6 @@ (i32.load (i32.const 556)) (i32.const 5))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 2))) (if $I7 (call $e.test_nle) (then @@ -143,6 +143,12 @@ (set_local $l0 (i32.const 2)) (br $L0)))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) (i32.store (i32.const 560) (i32.load @@ -155,13 +161,13 @@ (i32.const 1))) (set_local $l3 (call $e.inc32 - (get_local $l3))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 1)))) + (get_local $l3)))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 2))) (set_local $l5 (call $e.inc32 (get_local $l5))) @@ -226,12 +232,6 @@ (set_local $l9 (i32.load (i32.const 92))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 2))) (i32.store (i32.const 64) (get_local $l2)) diff --git a/tests/expect/tests/indirect-call.wast b/tests/expect/tests/indirect-call.wast index 79c8b639..5cbe1982 100644 --- a/tests/expect/tests/indirect-call.wast +++ b/tests/expect/tests/indirect-call.wast @@ -90,6 +90,12 @@ (block $B5 (br_table $B5 $B4 $B3 $B2 (get_local $l0))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) (i32.store (i32.const 560) (i32.load @@ -212,12 +218,6 @@ (i32.store (i32.const 556) (get_local $l10)) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 1))) (i32.store (i32.const 64) (get_local $l2)) @@ -243,6 +243,12 @@ (i32.const 92) (get_local $l9)) (return)) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) (i32.store (i32.const 560) (i32.load @@ -302,12 +308,6 @@ (set_local $l9 (i32.load (i32.const 92))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 1))) (i32.store (i32.const 64) (get_local $l2)) diff --git a/tests/expect/tests/mov16.wast b/tests/expect/tests/mov16.wast index 6300b6fb..2d1c34c5 100644 --- a/tests/expect/tests/mov16.wast +++ b/tests/expect/tests/mov16.wast @@ -89,6 +89,12 @@ (block $B4 (br_table $B4 $B3 $B2 (get_local $l0))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 12))) (set_local $l2 (i32.or (i32.and @@ -440,12 +446,6 @@ (set_local $l9 (i32.load (i32.const 92))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 12))) (i32.store (i32.const 64) (get_local $l2)) diff --git a/tests/expect/tests/mov32-mem.wast b/tests/expect/tests/mov32-mem.wast index 8c191199..7b74bc16 100644 --- a/tests/expect/tests/mov32-mem.wast +++ b/tests/expect/tests/mov32-mem.wast @@ -89,6 +89,12 @@ (block $B4 (br_table $B4 $B3 $B2 (get_local $l0))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 5))) (set_local $l10 (i32.add (i32.add @@ -352,12 +358,6 @@ (set_local $l9 (i32.load (i32.const 92))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 5))) (i32.store (i32.const 64) (get_local $l2)) diff --git a/tests/expect/tests/mov32-reg.wast b/tests/expect/tests/mov32-reg.wast index d344ce76..e2be82bf 100644 --- a/tests/expect/tests/mov32-reg.wast +++ b/tests/expect/tests/mov32-reg.wast @@ -87,6 +87,12 @@ (block $B4 (br_table $B4 $B3 $B2 (get_local $l0))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 9))) (set_local $l2 (i32.const -889270259)) (set_local $l3 @@ -164,12 +170,6 @@ (set_local $l9 (i32.load (i32.const 92))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 9))) (i32.store (i32.const 64) (get_local $l2)) diff --git a/tests/expect/tests/pop.wast b/tests/expect/tests/pop.wast index 973ffe28..c1e984cf 100644 --- a/tests/expect/tests/pop.wast +++ b/tests/expect/tests/pop.wast @@ -88,6 +88,12 @@ (block $B4 (br_table $B4 $B3 $B2 (get_local $l0))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 2))) (set_local $l10 (i32.add (get_local $l6) @@ -200,12 +206,6 @@ (set_local $l9 (i32.load (i32.const 92))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 2))) (i32.store (i32.const 64) (get_local $l2)) diff --git a/tests/expect/tests/push.wast b/tests/expect/tests/push.wast index b95e4677..71a5a4e1 100644 --- a/tests/expect/tests/push.wast +++ b/tests/expect/tests/push.wast @@ -88,6 +88,12 @@ (block $B4 (br_table $B4 $B3 $B2 (get_local $l0))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 2))) (set_local $l11 (i32.add (tee_local $l10 @@ -202,12 +208,6 @@ (set_local $l9 (i32.load (i32.const 92))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 2))) (i32.store (i32.const 64) (get_local $l2)) diff --git a/tests/expect/tests/task_switch_test.wast b/tests/expect/tests/task_switch_test.wast index 1c9dc7c6..5fb82871 100644 --- a/tests/expect/tests/task_switch_test.wast +++ b/tests/expect/tests/task_switch_test.wast @@ -91,6 +91,12 @@ (block $B4 (br_table $B4 $B3 $B2 (get_local $l0))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 2))) (if $I5 (i32.and (i32.load8_u @@ -200,12 +206,6 @@ (set_local $l9 (i32.load (i32.const 92))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 2))) (i32.store (i32.const 64) (get_local $l2)) diff --git a/tests/expect/tests/task_switch_test_sse.wast b/tests/expect/tests/task_switch_test_sse.wast index 1998bbf4..7559498a 100644 --- a/tests/expect/tests/task_switch_test_sse.wast +++ b/tests/expect/tests/task_switch_test_sse.wast @@ -90,6 +90,12 @@ (block $B5 (br_table $B5 $B4 $B3 $B2 (get_local $l0))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) (i32.store (i32.const 560) (i32.load @@ -203,12 +209,6 @@ (i32.store (i32.const 648) (i32.const 0)) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 1))) (i32.store (i32.const 64) (get_local $l2)) @@ -234,6 +234,12 @@ (i32.const 92) (get_local $l9)) (return)) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) (i32.store (i32.const 560) (i32.load @@ -293,12 +299,6 @@ (set_local $l9 (i32.load (i32.const 92))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 1))) (i32.store (i32.const 64) (get_local $l2)) diff --git a/tests/expect/tests/while-do.wast b/tests/expect/tests/while-do.wast index 9f49557b..54f69567 100644 --- a/tests/expect/tests/while-do.wast +++ b/tests/expect/tests/while-do.wast @@ -90,6 +90,12 @@ (block $B6 (br_table $B6 $B5 $B4 $B3 $B2 (get_local $l0))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 2))) (set_local $l10 (i32.sub (get_local $l2) @@ -124,12 +130,6 @@ (i32.load (i32.const 556)) (i32.const 5))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 2))) (if $I8 (if $I7 (result i32) (i32.and @@ -166,6 +166,12 @@ (set_local $l0 (i32.const 2)) (br $L0)))) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 2))) (set_local $l5 (call $e.inc32 (get_local $l5))) @@ -187,15 +193,15 @@ (i32.load (i32.const 556)) (i32.const -8))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 2))) (set_local $l0 (i32.const 0)) (br $L0)) + (i32.store + (i32.const 664) + (i32.add + (i32.load + (i32.const 664)) + (i32.const 1))) (i32.store (i32.const 560) (i32.load @@ -255,12 +261,6 @@ (set_local $l9 (i32.load (i32.const 92))) - (i32.store - (i32.const 664) - (i32.add - (i32.load - (i32.const 664)) - (i32.const 1))) (i32.store (i32.const 64) (get_local $l2)) From 48940e426a5b4e436dc9b72c04cc08d6b2a57380 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1636/2137] Fix fldm80/fstenv/fldenv: These instructions were generating and unconditional exit from jitted code but not updating eip. Changed to use the fallback mechanism for handling pagefaults --- src/rust/cpu2/fpu.rs | 31 +++++++++++++++++++++---- src/rust/jit_instructions.rs | 45 +++++++++++++++++++++++++++++++++--- 2 files changed, 69 insertions(+), 7 deletions(-) diff --git a/src/rust/cpu2/fpu.rs b/src/rust/cpu2/fpu.rs index 01e283b8..70c0d58a 100644 --- a/src/rust/cpu2/fpu.rs +++ b/src/rust/cpu2/fpu.rs @@ -435,8 +435,15 @@ pub unsafe fn fpu_fldcw(addr: i32) { pub unsafe fn fpu_fldenv(addr: i32) { if is_osize_32() { // TODO: Add readable_or_pagefault - return_on_pagefault!(translate_address_read(addr)); - return_on_pagefault!(translate_address_read(addr + 28)); + if let Err(()) = translate_address_read(addr) { + *page_fault = true; + return; + } + if let Err(()) = translate_address_read(addr + 28) { + *page_fault = true; + return; + } + *page_fault = false; *fpu_control_word = safe_read16(addr).unwrap(); fpu_set_status_word(safe_read16(addr + 4).unwrap()); fpu_set_tag_word(safe_read16(addr + 8).unwrap()); @@ -478,7 +485,17 @@ pub unsafe fn fpu_fldm32(addr: i32) { fpu_push(return_on_pagefault!(safe_read32s #[no_mangle] pub unsafe fn fpu_fldm64(addr: i32) { fpu_push(return_on_pagefault!(fpu_load_m64(addr))); } #[no_mangle] -pub unsafe fn fpu_fldm80(addr: i32) { fpu_push(return_on_pagefault!(fpu_load_m80(addr))); } +pub unsafe fn fpu_fldm80(addr: i32) { + match fpu_load_m80(addr) { + Ok(x) => { + *page_fault = false; + fpu_push(x) + }, + Err(()) => { + *page_fault = true; + }, + } +} #[no_mangle] pub unsafe fn fpu_fmul(target_index: i32, val: f64) { let st0: f64 = fpu_get_st0(); @@ -614,7 +631,13 @@ pub unsafe fn fpu_f64_to_f80(f: f64) -> (u64, u16) { #[no_mangle] pub unsafe fn fpu_fstenv(addr: i32) { if is_osize_32() { - return_on_pagefault!(writable_or_pagefault(addr, 26)); + match writable_or_pagefault(addr, 26) { + Ok(()) => *page_fault = false, + Err(()) => { + *page_fault = true; + return; + }, + } safe_write16(addr, *fpu_control_word).unwrap(); safe_write16(addr + 4, fpu_load_status_word()).unwrap(); safe_write16(addr + 8, fpu_load_tag_word()).unwrap(); diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 7df4b962..989a77c0 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -3000,12 +3000,25 @@ pub fn instr_D9_3_reg_jit(ctx: &mut JitContext, r: u32) { pub fn instr_D9_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); - // XXX: generated because fldenv might page-fault, but doesn't generate a proper block boundary + + codegen::gen_set_previous_eip_offset_from_eip_with_low_bits( + ctx.builder, + ctx.start_of_current_instruction as i32 & 0xFFF, + ); + codegen::gen_move_registers_from_locals_to_memory(ctx); codegen::gen_call_fn1(ctx.builder, "fpu_fldenv"); + codegen::gen_move_registers_from_memory_to_locals(ctx); + + ctx.builder + .instruction_body + .load_u8(global_pointers::PAGE_FAULT); + ctx.builder.instruction_body.if_void(); codegen::gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); + codegen::gen_move_registers_from_locals_to_memory(ctx); codegen::gen_clear_prefixes(ctx); ctx.builder.instruction_body.return_(); + ctx.builder.instruction_body.block_end(); } pub fn instr_D9_4_reg_jit(ctx: &mut JitContext, r: u32) { ctx.builder.instruction_body.const_i32(r as i32); @@ -3027,12 +3040,25 @@ pub fn instr_D9_5_reg_jit(ctx: &mut JitContext, r: u32) { pub fn instr_D9_6_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); - // XXX: generated because fpu_fstenv might page-fault, but doesn't generate a proper block boundary + + codegen::gen_set_previous_eip_offset_from_eip_with_low_bits( + ctx.builder, + ctx.start_of_current_instruction as i32 & 0xFFF, + ); + codegen::gen_move_registers_from_locals_to_memory(ctx); codegen::gen_call_fn1(ctx.builder, "fpu_fstenv"); + codegen::gen_move_registers_from_memory_to_locals(ctx); + + ctx.builder + .instruction_body + .load_u8(global_pointers::PAGE_FAULT); + ctx.builder.instruction_body.if_void(); codegen::gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); + codegen::gen_move_registers_from_locals_to_memory(ctx); codegen::gen_clear_prefixes(ctx); ctx.builder.instruction_body.return_(); + ctx.builder.instruction_body.block_end(); } pub fn instr_D9_6_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_fn1_const(ctx.builder, "instr_D9_6_reg", r); @@ -3108,12 +3134,25 @@ pub fn instr_DB_3_reg_jit(ctx: &mut JitContext, r: u32) { pub fn instr_DB_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); - // XXX: generated because fpu_fldm80 might page-fault, but doesn't generate a proper block boundary + + codegen::gen_set_previous_eip_offset_from_eip_with_low_bits( + ctx.builder, + ctx.start_of_current_instruction as i32 & 0xFFF, + ); + codegen::gen_move_registers_from_locals_to_memory(ctx); codegen::gen_call_fn1(ctx.builder, "fpu_fldm80"); + codegen::gen_move_registers_from_memory_to_locals(ctx); + + ctx.builder + .instruction_body + .load_u8(global_pointers::PAGE_FAULT); + ctx.builder.instruction_body.if_void(); codegen::gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); + codegen::gen_move_registers_from_locals_to_memory(ctx); codegen::gen_clear_prefixes(ctx); ctx.builder.instruction_body.return_(); + ctx.builder.instruction_body.block_end(); } pub fn instr_DB_5_reg_jit(ctx: &mut JitContext, r: u32) { ctx.builder.instruction_body.const_i32(r as i32); From cd909c4f026b4455bb9b6391273f7123f13645a9 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1637/2137] Add tests for fstenv/fldenv/fld [m80] --- gen/x86_table.js | 4 ++-- tests/nasm/fpu_m80.asm | 13 +++++++++++++ tests/nasm/fstenv.asm | 16 ++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 tests/nasm/fpu_m80.asm create mode 100644 tests/nasm/fstenv.asm diff --git a/gen/x86_table.js b/gen/x86_table.js index 6cc5569d..9f0842aa 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -285,7 +285,7 @@ const encodings = [ { opcode: 0xD9, e: 1, fixed_g: 1, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: 2, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: 3, custom: 1, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xD9, e: 1, fixed_g: 4, custom: 1, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // fldenv + { opcode: 0xD9, e: 1, fixed_g: 4, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: 6, custom: 1, is_fpu: 1, task_switch_test: 1, skip: 1, }, // fstenv (mem), fprem (reg) { opcode: 0xD9, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, only_mem: 1, }, // fprem @@ -304,7 +304,7 @@ const encodings = [ { opcode: 0xDB, e: 1, fixed_g: 2, custom: 2, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDB, e: 1, fixed_g: 3, custom: 2, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDB, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDB, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // XXX: skipped: Seems to page fault or so + { opcode: 0xDB, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDB, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDB, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, }, diff --git a/tests/nasm/fpu_m80.asm b/tests/nasm/fpu_m80.asm new file mode 100644 index 00000000..0888c9bf --- /dev/null +++ b/tests/nasm/fpu_m80.asm @@ -0,0 +1,13 @@ +global _start + +section .data + align 16 + +%include "header.inc" + + push 1 + push 0 + push 0 + fld tword [esp-8] + +%include "footer.inc" diff --git a/tests/nasm/fstenv.asm b/tests/nasm/fstenv.asm new file mode 100644 index 00000000..a41299bb --- /dev/null +++ b/tests/nasm/fstenv.asm @@ -0,0 +1,16 @@ +global _start + +section .data + align 16 + +%include "header.inc" + + fstenv [esp] + + ; zero undefined fields + mov word [esp + 0 + 2], 0 + mov word [esp + 4 + 2], 0 + mov word [esp + 8 + 2], 0 + mov word [esp + 24 + 2], 0 + +%include "footer.inc" From 5515c32e8d595520516814d4885c6181ddad70f6 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1638/2137] Correct codegen for some undefined fpu instructions --- src/rust/jit_instructions.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 989a77c0..c56a667d 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -3021,9 +3021,13 @@ pub fn instr_D9_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { ctx.builder.instruction_body.block_end(); } pub fn instr_D9_4_reg_jit(ctx: &mut JitContext, r: u32) { - ctx.builder.instruction_body.const_i32(r as i32); - // XXX: May call trigger_ud - codegen::gen_call_fn1(ctx.builder, "instr_D9_4_reg"); + match r { + 0 | 1 | 4 | 5 => { + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_call_fn1(ctx.builder, "instr_D9_4_reg"); + }, + _ => codegen::gen_trigger_ud(ctx), + } } pub fn instr_D9_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { @@ -3034,8 +3038,12 @@ pub fn instr_D9_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { ctx.builder.instruction_body.store_aligned_u16(0); } pub fn instr_D9_5_reg_jit(ctx: &mut JitContext, r: u32) { - // XXX: May call trigger_ud - codegen::gen_fn1_const(ctx.builder, "instr_D9_5_reg", r); + if r == 7 { + codegen::gen_trigger_ud(ctx); + } + else { + codegen::gen_fn1_const(ctx.builder, "instr_D9_5_reg", r); + } } pub fn instr_D9_6_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { From db381ef39f7eeb98560eb3a8341e1f78c01a8696 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1639/2137] Remove broken tests (exception is different in native and v86) --- tests/nasm/jcc8.asm | 33 --------------------------------- tests/nasm/jmp_near.asm | 39 --------------------------------------- tests/nasm/loop.asm | 35 ----------------------------------- 3 files changed, 107 deletions(-) delete mode 100644 tests/nasm/jcc8.asm delete mode 100644 tests/nasm/jmp_near.asm delete mode 100644 tests/nasm/loop.asm diff --git a/tests/nasm/jcc8.asm b/tests/nasm/jcc8.asm deleted file mode 100644 index 26058f71..00000000 --- a/tests/nasm/jcc8.asm +++ /dev/null @@ -1,33 +0,0 @@ -global _start - -section .data -re_entered: - db 0 - -%include "header.inc" - -align 0x10000 - - cmp byte [re_entered], 0 - jz ok - - ; force a #gp if the code section is re-entered - mov eax, -1 - mov cr4, eax - -ok: - mov byte [re_entered], 1 - - ; NOPs until the beginning of the next page minus two bytes - times ($$-$) % 0x10000 - 2 nop - inc al - - ; Next page starts here - - ; should jump to absolute address 0xfffe and #gp, as 16-bit eip wraps around - db 0x66 - jnz ($-3) - - ; this should never be executed - -%include "footer.inc" diff --git a/tests/nasm/jmp_near.asm b/tests/nasm/jmp_near.asm deleted file mode 100644 index e1f7aca8..00000000 --- a/tests/nasm/jmp_near.asm +++ /dev/null @@ -1,39 +0,0 @@ -global _start - -section .data -re_entered: - db 0 - -%include "header.inc" - -align 0x10000 - - cmp byte [re_entered], 0 - jz ok - - ; force a #gp if the code section is re-entered - mov eax, -1 - mov cr4, eax - hlt - -ok: - mov byte [re_entered], 1 - - jmp page_start - - ; NOPs until the beginning of the next page minus two bytes - times ($$-$) % 0x10000 - 2 nop - jmp fail - - ; Next page starts here - -page_start: - ; should jump to absolute address 0xfffe and #gp, as 16-bit eip wraps around - ; jumps to "fail" if 32-bit eip is used - db 0x66 - jmp ($-3) - -fail: - ; this should never be executed - -%include "footer.inc" diff --git a/tests/nasm/loop.asm b/tests/nasm/loop.asm deleted file mode 100644 index 55dc5228..00000000 --- a/tests/nasm/loop.asm +++ /dev/null @@ -1,35 +0,0 @@ -global _start - -section .data -re_entered: - db 0 - -%include "header.inc" - -align 0x10000 - - cmp byte [re_entered], 0 - jz ok - - ; force a #gp if the code section is re-entered - mov eax, -1 - mov cr4, eax - hlt - -ok: - mov byte [re_entered], 1 - - mov ecx, 2 ; loop counter variable - - ; NOPs until the beginning of the next page minus one byte - times ($$-$) % 0x10000 nop - - ; Next page starts here - - ; should jump to absolute address 0xfffe and #gp, as 16-bit eip wraps around - db 0x66 - loop ($-3) - - ; this should never be executed - -%include "footer.inc" From 6f366b127725cc369ed7168ddf66a22249f23277 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1640/2137] Refactor: Use gen_set_previous_eip_offset_from_eip_with_low_bits in gen_safe_read_write --- src/rust/codegen.rs | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index 61b17938..f6d34c47 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -1343,21 +1343,10 @@ pub fn gen_safe_read_write( gen_call_fn2(ctx.builder, "report_safe_read_write_jit_slow"); } - ctx.builder - .instruction_body - .const_i32(global_pointers::PREVIOUS_IP as i32); - - ctx.builder - .instruction_body - .load_aligned_i32(global_pointers::INSTRUCTION_POINTER); - ctx.builder.instruction_body.const_i32(!0xFFF); - ctx.builder.instruction_body.and_i32(); - ctx.builder - .instruction_body - .const_i32(ctx.start_of_current_instruction as i32 & 0xFFF); - ctx.builder.instruction_body.or_i32(); - - ctx.builder.instruction_body.store_aligned_i32(0); + gen_set_previous_eip_offset_from_eip_with_low_bits( + ctx.builder, + ctx.start_of_current_instruction as i32 & 0xFFF, + ); ctx.builder.instruction_body.get_local(&address_local); From 0c561ece3da3255193f1424ac1f06560a1927ee3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1641/2137] Enable nasm test for fnstsw --- gen/x86_table.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 9f0842aa..0f7944f4 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -339,8 +339,7 @@ const encodings = [ { opcode: 0xDF, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // unimplemented: fisttp (sse3) { opcode: 0xDF, e: 1, fixed_g: 2, custom: 1, is_fpu: 1, task_switch_test: 1 }, { opcode: 0xDF, e: 1, fixed_g: 3, custom: 1, is_fpu: 1, task_switch_test: 1 }, - { opcode: 0xDF, e: 1, fixed_g: 4, custom: 1, is_fpu: 1, task_switch_test: 1, skip: 1 }, // unimplemented (mem): Binary Coded Decimals - // skipped (reg): fnstsw + { opcode: 0xDF, e: 1, fixed_g: 4, custom: 1, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // unimplemented: Binary Coded Decimals { opcode: 0xDF, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDF, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // unimplemented: Binary Coded Decimals { opcode: 0xDF, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, }, From 591fccb5d8871b6769b71dda8076fc9f5ee92673 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1642/2137] Add some comments to unimplemented instructions --- gen/x86_table.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gen/x86_table.js b/gen/x86_table.js index 0f7944f4..17b995a2 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -288,7 +288,7 @@ const encodings = [ { opcode: 0xD9, e: 1, fixed_g: 4, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: 6, custom: 1, is_fpu: 1, task_switch_test: 1, skip: 1, }, // fstenv (mem), fprem (reg) - { opcode: 0xD9, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, only_mem: 1, }, // fprem + { opcode: 0xD9, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, only_mem: 1, }, // fprem, fyl2xp1 { opcode: 0xDA, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDA, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, }, @@ -318,7 +318,7 @@ const encodings = [ { opcode: 0xDC, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDD, e: 1, fixed_g: 0, custom: 1, is_fpu: 1, task_switch_test: 1, }, - { opcode: 0xDD, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, + { opcode: 0xDD, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // unimplemented: fisttp (sse3) { opcode: 0xDD, e: 1, fixed_g: 2, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDD, e: 1, fixed_g: 3, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDD, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1, }, // frstor From f058037006a709657729a895809924930449be0f Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1643/2137] Fix exception eip in #ud and #gp in jitted code --- src/rust/codegen.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index f6d34c47..b1d06423 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -1550,6 +1550,10 @@ pub fn gen_fpu_load_m64(ctx: &mut JitContext, modrm_byte: u8) { pub fn gen_trigger_ud(ctx: &mut JitContext) { gen_move_registers_from_locals_to_memory(ctx); + gen_set_previous_eip_offset_from_eip_with_low_bits( + ctx.builder, + ctx.start_of_current_instruction as i32 & 0xFFF, + ); gen_fn0_const(ctx.builder, "trigger_ud"); gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); gen_clear_prefixes(ctx); @@ -1558,6 +1562,10 @@ pub fn gen_trigger_ud(ctx: &mut JitContext) { pub fn gen_trigger_gp(ctx: &mut JitContext, error_code: u32) { gen_move_registers_from_locals_to_memory(ctx); + gen_set_previous_eip_offset_from_eip_with_low_bits( + ctx.builder, + ctx.start_of_current_instruction as i32 & 0xFFF, + ); gen_fn1_const(ctx.builder, "trigger_gp", error_code); gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); gen_clear_prefixes(ctx); From 28d70d6250da55e69922167ca440480c669b750c Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1644/2137] Add test for fsave and frstor --- tests/nasm/fsave_frstor.asm | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tests/nasm/fsave_frstor.asm diff --git a/tests/nasm/fsave_frstor.asm b/tests/nasm/fsave_frstor.asm new file mode 100644 index 00000000..b6d516b4 --- /dev/null +++ b/tests/nasm/fsave_frstor.asm @@ -0,0 +1,14 @@ +global _start + +section .data + align 16 + +%include "header.inc" + + sub esp, 128 + fldz + fld1 + fsave [esp] + frstor [esp] + +%include "footer.inc" From 9a38e6a654cf968a8446a244916980b348a83549 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1645/2137] nasmtests: Check exception eip --- src/rust/cpu2/cpu.rs | 40 +++++++++++--------- tests/nasm/Makefile | 2 +- tests/nasm/gdb-extract-def | 2 + tests/nasm/run.js | 77 ++++++++++++++++++++++++-------------- 4 files changed, 75 insertions(+), 46 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 52abdff3..84146e5a 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1341,11 +1341,6 @@ pub unsafe fn trigger_pagefault_jit(fault: PageFault) { } } profiler::stat_increment(PAGE_FAULT); - if DEBUG { - if cpu_exception_hook(CPU_EXCEPTION_PF) { - return; - } - } //if *page_fault { // dbg_log!(("double fault")); // dbg_trace(); @@ -1356,6 +1351,11 @@ pub unsafe fn trigger_pagefault_jit(fault: PageFault) { let page = ((addr as u32) >> 12) as i32; *tlb_data.offset(page as isize) = 0; *prefixes = 0; + if DEBUG { + if cpu_exception_hook(CPU_EXCEPTION_PF) { + return; + } + } *page_fault_error_code = (user as i32) << 2 | (write as i32) << 1 | present as i32; //*page_fault = true; } @@ -2095,13 +2095,14 @@ pub unsafe fn do_many_cycles_native() { } pub unsafe fn trigger_de() { + dbg_log!("#de"); + *prefixes = 0; + *instruction_pointer = *previous_ip; if DEBUG { if cpu_exception_hook(CPU_EXCEPTION_DE) { return; } } - *prefixes = 0; - *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_DE, false, None); } @@ -2109,36 +2110,39 @@ pub unsafe fn trigger_de() { pub unsafe fn trigger_ud() { dbg_log!("#ud"); dbg_trace(); + *prefixes = 0; + *instruction_pointer = *previous_ip; if DEBUG { if cpu_exception_hook(CPU_EXCEPTION_UD) { return; } } - *prefixes = 0; - *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_UD, false, None); } pub unsafe fn trigger_nm() { + dbg_log!("#nm eip={:x}", *previous_ip); + dbg_trace(); + *prefixes = 0; + *instruction_pointer = *previous_ip; if DEBUG { if cpu_exception_hook(CPU_EXCEPTION_NM) { return; } } - *prefixes = 0; - *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_NM, false, None); } #[no_mangle] pub unsafe fn trigger_gp(code: i32) { + dbg_log!("#gp"); + *prefixes = 0; + *instruction_pointer = *previous_ip; if DEBUG { if cpu_exception_hook(CPU_EXCEPTION_GP) { return; } } - *prefixes = 0; - *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_GP, false, Some(code)); } @@ -3124,25 +3128,27 @@ pub unsafe fn translate_address_system_write(address: i32) -> OrPageFault { #[no_mangle] pub unsafe fn trigger_np(code: i32) { + dbg_log!("#np"); + *prefixes = 0; + *instruction_pointer = *previous_ip; if DEBUG { if cpu_exception_hook(CPU_EXCEPTION_NP) { return; } } - *prefixes = 0; - *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_NP, false, Some(code)); } #[no_mangle] pub unsafe fn trigger_ss(code: i32) { + dbg_log!("#ss"); + *prefixes = 0; + *instruction_pointer = *previous_ip; if DEBUG { if cpu_exception_hook(CPU_EXCEPTION_SS) { return; } } - *prefixes = 0; - *instruction_pointer = *previous_ip; call_interrupt_vector(CPU_EXCEPTION_SS, false, Some(code)); } diff --git a/tests/nasm/Makefile b/tests/nasm/Makefile index 30237a52..44a92cd6 100644 --- a/tests/nasm/Makefile +++ b/tests/nasm/Makefile @@ -15,7 +15,7 @@ build/%.o: build/%.asm $(inc_files) # To run / debug locally build/%.bin: build/%.o - ld -g $< -m elf_i386 --section-start=.bss=0x100000 -o $@ + ld -g $< -m elf_i386 --section-start=.bss=0x100000 --section-start=.text=0x800000 -o $@ # To use as a multiboot kernel image for v86 build/%.img: build/%.o diff --git a/tests/nasm/gdb-extract-def b/tests/nasm/gdb-extract-def index 1e17896b..c7802eb5 100644 --- a/tests/nasm/gdb-extract-def +++ b/tests/nasm/gdb-extract-def @@ -25,7 +25,9 @@ define extract-state printf " %d,\n", $ebp printf " %d,\n", $esi printf " %d,\n", $edi + printf " \n" + printf " %d,\n", $eip printf " \n" # For fpu registers, check the tag register first. If the tag index is diff --git a/tests/nasm/run.js b/tests/nasm/run.js index 32db02ef..92fefcf1 100755 --- a/tests/nasm/run.js +++ b/tests/nasm/run.js @@ -31,6 +31,10 @@ const TERMINATE_MSG = "DONE"; const FORCE_JIT = process.argv.includes("--force-jit"); +// see --section-start= in makefile +const V86_TEXT_OFFSET = 0x8000; +const NASM_TEXT_OFFSET = 0x800000; + // alternative representation for infinity for json const JSON_POS_INFINITY = "+INFINITY"; const JSON_NEG_INFINITY = "-INFINITY"; @@ -89,27 +93,29 @@ if(cluster.isMaster) { function extract_json(name, fixture_text) { + let exception; + if(fixture_text.includes("(signal SIGFPE)")) { - return { exception: "DE", }; + exception = "DE"; } if(fixture_text.includes("(signal SIGILL)")) { - return { exception: "UD", }; + exception = "UD"; } if(fixture_text.includes("(signal SIGSEGV)")) { - return { exception: "GP", }; + exception = "GP"; } if(fixture_text.includes("(signal SIGBUS)")) { - return { exception: "PF", }; + exception = "PF"; } - if(fixture_text.includes("Program received signal") || fixture_text.includes("SIGILL")) + if(!exception && fixture_text.includes("Program received signal")) { throw new Error("Test was killed during execution by gdb: " + name + "\n" + fixture_text); } @@ -126,13 +132,11 @@ if(cluster.isMaster) throw new Error("Could not find JSON in fixture text: " + fixture_text + "\nTest: " + name); } - try { - let array = JSON.parse(regex_match[1]); - return { array: array }; - } - catch (e) { - throw e; - } + let array = JSON.parse(regex_match[1]); + return { + array: array, + exception, + }; } @@ -334,10 +338,12 @@ else { process.exit(1); } + const eip = emulator.v86.cpu.instruction_pointer[0]; + // XXX: On gdb execution is stopped at this point. On v86 we // currently don't have this ability, so we record the exception // and continue execution - recorded_exceptions.push(exception); + recorded_exceptions.push({ exception, eip }); finish_test(); return true; }; @@ -368,7 +374,7 @@ else { let individual_failures = []; - console.assert(current_test.fixture.array || current_test.fixture.exception); + console.assert(current_test.fixture.array); const FLOAT_TRANSLATION = { [JSON_POS_INFINITY]: Infinity, @@ -377,19 +383,20 @@ else { [JSON_NEG_NAN]: NaN, // XXX: Ignore sign of NaN }; - if(current_test.fixture.array) - { - let offset = 0; - const expected_reg32s = current_test.fixture.array.slice(offset, offset += 8); - const expected_fpu_regs = - current_test.fixture.array.slice(offset, offset += 8) .map(x => x in FLOAT_TRANSLATION ? FLOAT_TRANSLATION[x] : x); - const expected_mmx_registers = current_test.fixture.array.slice(offset, offset += 16); - const expected_xmm_registers = current_test.fixture.array.slice(offset, offset += 32); - const expected_memory = current_test.fixture.array.slice(offset, offset += 16); - const expected_eflags = current_test.fixture.array[offset++] & MASK_ARITH; - const fpu_tag = current_test.fixture.array[offset++]; - const fpu_status = current_test.fixture.array[offset++] & FPU_STATUS_MASK; + let offset = 0; + const expected_reg32s = current_test.fixture.array.slice(offset, offset += 8); + const expected_eip = current_test.fixture.array[offset++]; + const expected_fpu_regs = + current_test.fixture.array.slice(offset, offset += 8) .map(x => x in FLOAT_TRANSLATION ? FLOAT_TRANSLATION[x] : x); + const expected_mmx_registers = current_test.fixture.array.slice(offset, offset += 16); + const expected_xmm_registers = current_test.fixture.array.slice(offset, offset += 32); + const expected_memory = current_test.fixture.array.slice(offset, offset += 16); + const expected_eflags = current_test.fixture.array[offset++] & MASK_ARITH; + const fpu_tag = current_test.fixture.array[offset++]; + const fpu_status = current_test.fixture.array[offset++] & FPU_STATUS_MASK; + if(!current_test.fixture.exception) + { for (let i = 0; i < cpu.reg32s.length; i++) { let reg = cpu.reg32s[i]; if (reg !== expected_reg32s[i]) { @@ -467,11 +474,25 @@ else { } } - if(current_test.fixture.exception !== recorded_exceptions[0]) + if(current_test.fixture.exception) + { + const seen_eip = (recorded_exceptions[0] || {}).eip; + if(seen_eip - V86_TEXT_OFFSET !== expected_eip - NASM_TEXT_OFFSET) + { + individual_failures.push({ + name: "exception eip", + expected: expected_eip - NASM_TEXT_OFFSET, + actual: seen_eip === undefined ? "(none)" : seen_eip - V86_TEXT_OFFSET, + }); + } + } + + const seen_exception = (recorded_exceptions[0] || {}).exception; + if(current_test.fixture.exception !== seen_exception) { individual_failures.push({ name: "Exception", - actual: recorded_exceptions[0] || "(none)", + actual: seen_exception || "(none)", expected: current_test.fixture.exception, }); } From 60adbf9b1fa03dce99834d56b6b3fb86cde02e77 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1646/2137] Fix: Side-effects in lsl/lar/arpl even when #ud is triggered --- src/cpu.js | 20 ---------- src/rust/cpu2/instructions.rs | 10 +++++ src/rust/cpu2/instructions_0f.rs | 64 ++++++++++++++++++++++++-------- 3 files changed, 58 insertions(+), 36 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index dabd6a3b..f7db3918 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -2919,12 +2919,6 @@ CPU.prototype.load_ldt = function(selector) CPU.prototype.arpl = function(seg, r16) { - if(!this.protected_mode[0] || this.vm86_mode()) - { - this.trigger_ud(); - return; - } - this.flags_changed[0] &= ~flag_zero; if((seg & 3) < (r16 & 3)) @@ -2946,13 +2940,6 @@ 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(); - return; - } - /** @const */ var LAR_INVALID_TYPE = 1 << 0 | 1 << 6 | 1 << 7 | 1 << 8 | 1 << 0xA | 1 << 0xD | 1 << 0xE | 1 << 0xF; @@ -2984,13 +2971,6 @@ 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(); - return; - } - /** @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/rust/cpu2/instructions.rs b/src/rust/cpu2/instructions.rs index ab067808..90308e8d 100644 --- a/src/rust/cpu2/instructions.rs +++ b/src/rust/cpu2/instructions.rs @@ -893,10 +893,20 @@ pub unsafe fn instr_62_mem(addr: i32, r: i32) { } #[no_mangle] pub unsafe fn instr_63_mem(addr: i32, r: i32) { + if !*protected_mode || 0 != vm86_mode() as i32 { + dbg_log!("arpl #ud"); + trigger_ud(); + return; + } SAFE_READ_WRITE16!(___, addr, arpl(___, read_reg16(r))); } #[no_mangle] pub unsafe fn instr_63_reg(r1: i32, r: i32) { + if !*protected_mode || 0 != vm86_mode() as i32 { + dbg_log!("arpl #ud"); + trigger_ud(); + return; + } let ____0: i32 = read_reg16(r1); write_reg16(r1, arpl(____0, read_reg16(r))); } diff --git a/src/rust/cpu2/instructions_0f.rs b/src/rust/cpu2/instructions_0f.rs index 6849dcd9..6b4fd8f9 100644 --- a/src/rust/cpu2/instructions_0f.rs +++ b/src/rust/cpu2/instructions_0f.rs @@ -161,46 +161,38 @@ pub unsafe fn instr_0F00_3_reg(r: i32) { #[no_mangle] pub unsafe fn instr_0F00_4_mem(addr: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { + dbg_log!("verr #ud"); trigger_ud(); return; } - else { - verr(return_on_pagefault!(safe_read16(addr))); - return; - }; + verr(return_on_pagefault!(safe_read16(addr))); } #[no_mangle] pub unsafe fn instr_0F00_4_reg(r: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { + dbg_log!("verr #ud"); trigger_ud(); return; } - else { - verr(read_reg16(r)); - return; - }; + verr(read_reg16(r)); } #[no_mangle] pub unsafe fn instr_0F00_5_mem(addr: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { + dbg_log!("verw #ud"); trigger_ud(); return; } - else { - verw(return_on_pagefault!(safe_read16(addr))); - return; - }; + verw(return_on_pagefault!(safe_read16(addr))); } #[no_mangle] pub unsafe fn instr_0F00_5_reg(r: i32) { if !*protected_mode || 0 != vm86_mode() as i32 { + dbg_log!("verw #ud"); trigger_ud(); return; } - else { - verw(read_reg16(r)); - return; - }; + verw(read_reg16(r)); } #[no_mangle] pub unsafe fn instr_0F01_0_reg(r: i32) { trigger_ud(); } @@ -334,41 +326,81 @@ pub unsafe fn instr_0F01_7_mem(addr: i32) { } #[no_mangle] pub unsafe fn instr16_0F02_mem(addr: i32, r: i32) { + if !*protected_mode || 0 != vm86_mode() as i32 { + dbg_log!("lar #ud"); + trigger_ud(); + return; + } let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, lar(____0, read_reg16(r))); } #[no_mangle] pub unsafe fn instr16_0F02_reg(r1: i32, r: i32) { + if !*protected_mode || 0 != vm86_mode() as i32 { + dbg_log!("lar #ud"); + trigger_ud(); + return; + } let ____0: i32 = read_reg16(r1); write_reg16(r, lar(____0, read_reg16(r))); } #[no_mangle] pub unsafe fn instr32_0F02_mem(addr: i32, r: i32) { + if !*protected_mode || 0 != vm86_mode() as i32 { + dbg_log!("lar #ud"); + trigger_ud(); + return; + } let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg32(r, lar(____0, read_reg32(r))); } #[no_mangle] pub unsafe fn instr32_0F02_reg(r1: i32, r: i32) { + if !*protected_mode || 0 != vm86_mode() as i32 { + dbg_log!("lar #ud"); + trigger_ud(); + return; + } let ____0: i32 = read_reg16(r1); write_reg32(r, lar(____0, read_reg32(r))); } #[no_mangle] pub unsafe fn instr16_0F03_mem(addr: i32, r: i32) { + if !*protected_mode || 0 != vm86_mode() as i32 { + dbg_log!("lsl #ud"); + trigger_ud(); + return; + } let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg16(r, lsl(____0, read_reg16(r))); } #[no_mangle] pub unsafe fn instr16_0F03_reg(r1: i32, r: i32) { + if !*protected_mode || 0 != vm86_mode() as i32 { + dbg_log!("lsl #ud"); + trigger_ud(); + return; + } let ____0: i32 = read_reg16(r1); write_reg16(r, lsl(____0, read_reg16(r))); } #[no_mangle] pub unsafe fn instr32_0F03_mem(addr: i32, r: i32) { + if !*protected_mode || 0 != vm86_mode() as i32 { + dbg_log!("lsl #ud"); + trigger_ud(); + return; + } let ____0: i32 = return_on_pagefault!(safe_read16(addr)); write_reg32(r, lsl(____0, read_reg32(r))); } #[no_mangle] pub unsafe fn instr32_0F03_reg(r1: i32, r: i32) { + if !*protected_mode || 0 != vm86_mode() as i32 { + dbg_log!("lsl #ud"); + trigger_ud(); + return; + } let ____0: i32 = read_reg16(r1); write_reg32(r, lsl(____0, read_reg32(r))); } From b3a3d930e3416b78b357befda0a059952985e9b0 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1647/2137] make default makefile target the debug build --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 72366d44..ef6d9695 100644 --- a/Makefile +++ b/Makefile @@ -18,6 +18,7 @@ ifeq ($(STRIP_DEBUG),true) STRIP_DEBUG_FLAG=--v86-strip-debug endif +default: build/v86oxide-debug.wasm all: build/v86_all.js build/libv86.js build/v86oxide.wasm all-debug: build/libv86-debug.js build/v86oxide-debug.wasm browser: build/v86_all.js From 1665e9b358cec4c7504d6cb897a549e558ae329b Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1648/2137] Fix instruction counter wrap-around --- src/browser/main.js | 12 ++++++++++-- src/browser/starter.js | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/browser/main.js b/src/browser/main.js index 68dc2d46..abe92978 100644 --- a/src/browser/main.js +++ b/src/browser/main.js @@ -907,22 +907,30 @@ var last_instr_counter = 0; var interval; var os_uses_mouse = false; + var total_instructions = 0; function update_info() { var now = Date.now(); var instruction_counter = emulator.get_instruction_counter(); - var last_ips = instruction_counter - last_instr_counter; + if(instruction_counter < last_instr_counter) + { + // 32-bit wrap-around + last_instr_counter -= 0x100000000; + } + + var last_ips = instruction_counter - last_instr_counter; last_instr_counter = instruction_counter; + total_instructions += last_ips; var delta_time = now - last_tick; running_time += delta_time; last_tick = now; $("speed").textContent = last_ips / delta_time | 0; - $("avg_speed").textContent = instruction_counter / running_time | 0; + $("avg_speed").textContent = total_instructions / running_time | 0; $("running_time").textContent = format_timestamp(running_time / 1000 | 0); } diff --git a/src/browser/starter.js b/src/browser/starter.js index 25944f00..0928c450 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -844,7 +844,7 @@ V86Starter.prototype.get_instruction_counter = function() { if(this.v86) { - return this.v86.cpu.timestamp_counter[0]; + return this.v86.cpu.timestamp_counter[0] >>> 0; } else { From 9efade88ee11bff59cb55b4fdb321120b5634813 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1649/2137] Fix compilation with latest closure compiler --- Makefile | 6 ------ src/lib.js | 4 ++++ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index ef6d9695..51700af4 100644 --- a/Makefile +++ b/Makefile @@ -43,13 +43,10 @@ CLOSURE_SOURCE_MAP=\ #--jscomp_error newCheckTypes\ CLOSURE_FLAGS=\ - --js lib/closure-base.js\ --generate_exports\ --externs src/externs.js\ --warning_level VERBOSE\ --jscomp_error accessControls\ - --jscomp_error ambiguousFunctionDecl\ - --jscomp_error checkEventfulObjectDisposal\ --jscomp_error checkRegExp\ --jscomp_error checkTypes\ --jscomp_error checkVars\ @@ -59,12 +56,9 @@ CLOSURE_FLAGS=\ --jscomp_error deprecated\ --jscomp_error deprecatedAnnotations\ --jscomp_error duplicateMessage\ - --jscomp_error es3\ --jscomp_error es5Strict\ --jscomp_error externsValidation\ - --jscomp_error fileoverviewTags\ --jscomp_error globalThis\ - --jscomp_error internetExplorerChecks\ --jscomp_error invalidCasts\ --jscomp_error misplacedTypeAnnotation\ --jscomp_error missingGetCssName\ diff --git a/src/lib.js b/src/lib.js index 4d0c7a1e..bf57a2a4 100644 --- a/src/lib.js +++ b/src/lib.js @@ -1,5 +1,9 @@ "use strict"; +var goog = goog || {}; +goog.exportSymbol = function() {}; +goog.exportProperty = function() {}; + var v86util = v86util || {}; // pad string with spaces on the right From 33e608fa70e742d903064229758b9a5f7be2387b Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1650/2137] fix rust warning --- src/rust/jit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 30358b17..fddfe1a8 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -1465,7 +1465,7 @@ pub fn jit_empty_cache(ctx: &mut JitState) { } pub fn jit_page_has_code(ctx: &JitState, page: Page) -> bool { - (jit_cache_array::get_page_index(page) != None || ctx.entry_points.contains_key(&page)) + jit_cache_array::get_page_index(page) != None || ctx.entry_points.contains_key(&page) } #[cfg(debug_assertions)] From 13a506de524ee1a5b7dcf6d5d5005f3108a824b8 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1651/2137] fix kvm-unit-test with newer versions of gcc --- tests/kvm-unit-tests/x86/realmode.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/kvm-unit-tests/x86/realmode.c b/tests/kvm-unit-tests/x86/realmode.c index 64116543..34959eca 100644 --- a/tests/kvm-unit-tests/x86/realmode.c +++ b/tests/kvm-unit-tests/x86/realmode.c @@ -624,11 +624,11 @@ void test_push_pop() MK_INSN(push_es, "mov $0x231, %bx\n\t" //Just write a dummy value to see if it gets overwritten "mov $0x123, %ax\n\t" "mov %ax, %es\n\t" - "push %es\n\t" - "pop %bx \n\t" + "pushl %es\n\t" + "popl %bx \n\t" ); - MK_INSN(pop_es, "push %ax\n\t" - "pop %es\n\t" + MK_INSN(pop_es, "pushl %ax\n\t" + "popl %es\n\t" "mov %es, %bx\n\t" ); MK_INSN(push_pop_ss, "push %ss\n\t" @@ -732,7 +732,7 @@ void test_iret() "pushl %cs\n\t" "call 1f\n\t" /* a near call will push eip onto the stack */ "jmp 2f\n\t" - "1: iret\n\t" + "1: iretl\n\t" "2:\n\t" ); @@ -751,7 +751,7 @@ void test_iret() "pushl %cs\n\t" "call 1f\n\t" "jmp 2f\n\t" - "1: iret\n\t" + "1: iretl\n\t" "2:\n\t"); MK_INSN(iret_flags16, "pushfw\n\t" From c994dbc08c8fb7c4e4bd81ba6101bda77acfec40 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1652/2137] Fix spurious in index.html --- Makefile | 4 ++-- index.html | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 51700af4..5ae4e085 100644 --- a/Makefile +++ b/Makefile @@ -211,8 +211,8 @@ update_version: set -e ;\ COMMIT=`git log --format="%h" -n 1` ;\ DATE=`git log --date="format:%b %e, %Y %H:%m" --format="%cd" -n 1` ;\ - SEARCH='Version: [a-f0-9]\+ ([^(]\+)' ;\ - REPLACE='Version: '$$COMMIT' ('$$DATE')' ;\ + SEARCH='Version: [a-f0-9]\+ ([^(]\+)' ;\ + REPLACE='Version: '$$COMMIT' ('$$DATE')' ;\ sed -i "s@$$SEARCH@$$REPLACE@g" index.html ;\ grep $$COMMIT index.html diff --git a/index.html b/index.html index 3846ff30..764861e6 100644 --- a/index.html +++ b/index.html @@ -221,7 +221,7 @@ In Linux it can be accessed with `cat /dev/ttyS0`
-Version: 53caefc (Jan 22, 2016 23:01) +Version: b40c8ad2 (Apr 23, 2020 01:04)
Enable debug From b0a34e7a86828ddfe2dd5bd58add308299bf11c1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1653/2137] fs: assert that sha256 is present --- lib/filesystem.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/filesystem.js b/lib/filesystem.js index c5fda25f..27382920 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -212,6 +212,7 @@ FS.prototype.LoadRecursive = function(data, parentid) { inode.status = STATUS_ON_STORAGE; inode.sha256sum = data[JSONFS_IDX_SHA256]; + dbg_assert(inode.sha256sum); this.PushInode(inode, parentid, name); } else if(ifmt === S_IFLNK) From a7ae6603f01d40025d729cdd649012c9fffa5abd Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1654/2137] Temporarily disable broken tests --- tests/qemu/test-i386.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/qemu/test-i386.c b/tests/qemu/test-i386.c index 253ee993..b64b9405 100644 --- a/tests/qemu/test-i386.c +++ b/tests/qemu/test-i386.c @@ -1006,7 +1006,7 @@ void test_fcvt(double a) fa = a; la = a; printf("(float)%f = %f\n", a, fa); - printf("(long double)%f = %Lf\n", a, la); + //printf("(long double)%f = %Lf\n", a, la); // XXX: currently broken for infinity printf("a=" FMT64X "\n", *(uint64_t *)&a); printf("la=" FMT64X " %04x\n", *(uint64_t *)&la, *(unsigned short *)((char *)(&la) + 8)); @@ -1101,8 +1101,8 @@ void test_fenv(void) //TEST_ENV(&float_env16, "data16 fnstenv", "data16 fldenv"); //TEST_ENV(&float_env16, "data16 fnsave", "data16 frstor"); - TEST_ENV(&float_env32, "fnstenv", "fldenv"); - TEST_ENV(&float_env32, "fnsave", "frstor"); + //TEST_ENV(&float_env32, "fnstenv", "fldenv"); // XXX: Temporarily disabled + //TEST_ENV(&float_env32, "fnsave", "frstor"); // XXX: Temporarily disabled /* test for ffree */ for(i=0;i<5;i++) From 489f212c478a68973bc4a50878b230e38b19fedd Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1655/2137] Fix broken string test --- tests/qemu/test-i386.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/qemu/test-i386.c b/tests/qemu/test-i386.c index b64b9405..24e1f919 100644 --- a/tests/qemu/test-i386.c +++ b/tests/qemu/test-i386.c @@ -1686,10 +1686,10 @@ uint8_t __attribute__((aligned (4096))) str_buffer[STR_BUFFER_SIZE]; long esi, edi, eax, ecx, eflags, i;\ \ for(i = 0; i < (count + 1) * size_bytes; i++)\ - str_buffer[offset1 + i] = i + 0x56;\ - str_buffer[offset1 - i - 1] = i + 0x97;\ - str_buffer[offset2 + i] = i + 0xa5;\ - str_buffer[offset2 - i - 1] = i + 0x3e;\ + str_buffer[sizeof(str_buffer)/2 + offset1 + i] = i + 0x56;\ + str_buffer[sizeof(str_buffer)/2 + offset1 - i - 1] = i + 0x97;\ + str_buffer[sizeof(str_buffer)/2 + offset2 + i] = i + 0xa5;\ + str_buffer[sizeof(str_buffer)/2 + offset2 - i - 1] = i + 0x3e;\ \ esi = (long)(str_buffer + sizeof(str_buffer)/2 + offset1);\ edi = (long)(str_buffer + sizeof(str_buffer)/2 + offset2);\ From cd4977f5173b4a770da8bc6c339ae901219b0af9 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1656/2137] Simplify --- src/rust/cpu2/memory.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/cpu2/memory.rs b/src/rust/cpu2/memory.rs index 3760b1b4..42c6c388 100644 --- a/src/rust/cpu2/memory.rs +++ b/src/rust/cpu2/memory.rs @@ -132,7 +132,7 @@ pub unsafe fn write8(mut addr: u32, value: i32) { } else { ::c_api::jit_dirty_page(Page::page_of(addr)); - *mem8.offset(addr as isize) = value as u8 + write8_no_mmap_or_dirty_check(addr, value); }; } @@ -198,7 +198,7 @@ pub unsafe fn write_aligned32(mut addr: u32, value: i32) { } else { ::c_api::jit_dirty_cache_small(phys_addr, phys_addr.wrapping_add(4 as u32)); - *mem32s.offset(addr as isize) = value + write_aligned32_no_mmap_or_dirty_check(addr, value); }; } #[no_mangle] From caa08e8d4e5358c2c541d2d5af6907291da91862 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1657/2137] copy-to-sha256: Log name --- tools/copy-to-sha256.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/copy-to-sha256.py b/tools/copy-to-sha256.py index c3191b7c..1839bd09 100755 --- a/tools/copy-to-sha256.py +++ b/tools/copy-to-sha256.py @@ -66,7 +66,7 @@ def handle_dir(logger, from_path, to_path): to_abs = os.path.join(to_path, sha256) if os.path.exists(to_abs): - logger.info("Exists, skipped {}".format(to_abs)) + logger.info("Exists, skipped {} ({})".format(to_abs, absname)) else: logger.info("cp {} {}".format(absname, to_abs)) shutil.copyfile(absname, to_abs) @@ -80,9 +80,9 @@ def handle_tar(logger, tar, to_path): to_abs = os.path.join(to_path, sha256) if os.path.exists(to_abs): - logger.info("Exists, skipped {}".format(to_abs)) + logger.info("Exists, skipped {} ({})".format(to_abs, member.name)) else: - logger.info("Extracted {}".format(to_abs)) + logger.info("Extracted {} ({})".format(to_abs, member.name)) to_file = open(to_abs, "wb") f.seek(0) shutil.copyfileobj(f, to_file) From 941208c9481fd79cc0f19944053056e71f521495 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1658/2137] Remove defunct test coverage --- Makefile | 9 +-- loader.js | 2 +- src/config.js | 5 -- src/const.js | 5 -- src/coverage.js | 133 ----------------------------------- src/cpu.js | 8 +-- src/main.js | 5 +- tests/coverage/gen_report.js | 102 --------------------------- 8 files changed, 5 insertions(+), 264 deletions(-) delete mode 100644 src/coverage.js delete mode 100755 tests/coverage/gen_report.js diff --git a/Makefile b/Makefile index 5ae4e085..487dc56b 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,6 @@ CLOSURE_DIR=closure-compiler CLOSURE=$(CLOSURE_DIR)/compiler.jar NASM_TEST_DIR=./tests/nasm -COVERAGE_DIR=./tests/coverage INSTRUCTION_TABLES=src/rust/gen/jit.rs src/rust/gen/jit0f_16.rs src/rust/gen/jit0f_32.rs \ src/rust/gen/interpreter.rs src/rust/gen/interpreter0f_16.rs src/rust/gen/interpreter0f_32.rs \ @@ -85,7 +84,7 @@ CARGO_FLAGS=\ -C link-args="--import-table --global-base=8388608 $(STRIP_DEBUG_FLAG)" \ --verbose -CORE_FILES=const.js config.js io.js main.js lib.js coverage.js ide.js pci.js floppy.js \ +CORE_FILES=const.js config.js io.js main.js lib.js ide.js pci.js floppy.js \ memory.js 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 debug.js \ @@ -200,8 +199,6 @@ clean: -rm $(addsuffix .diff,$(INSTRUCTION_TABLES)) -rm build/*.map -rm build/*.wast - -rm build/coverage/coverage_data* - -rm $(COVERAGE_DIR)/build/* $(MAKE) -C $(NASM_TEST_DIR) clean run: @@ -291,10 +288,6 @@ all-tests: jshint kvm-unit-test expect-tests qemutests jitpagingtests api-tests # - debiantests (requires network) # - devices-test (hangs) -covreport: - mkdir -p $(COVERAGE_DIR)/build/ - $(COVERAGE_DIR)/gen_report.js - node_modules/.bin/jshint: npm install diff --git a/loader.js b/loader.js index 256f0b51..b6f13052 100644 --- a/loader.js +++ b/loader.js @@ -5,7 +5,7 @@ "use strict"; var CORE_FILES = - "const.js config.js log.js lib.js coverage.js cpu.js debug.js " + + "const.js config.js log.js lib.js cpu.js debug.js " + "io.js main.js ide.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 kernel.js"; diff --git a/src/config.js b/src/config.js index 75f096e8..ae0e7da1 100644 --- a/src/config.js +++ b/src/config.js @@ -71,8 +71,3 @@ var APIC_TIMER_FREQ = TSC_RATE; /** @const */ var VMWARE_HYPERVISOR_PORT = true; - -/** @const - * Whether the coverage logger should be enabled under the appropriate conditions - */ -const COVERAGE_LOGGER_ALLOW = true; diff --git a/src/const.js b/src/const.js index 01c58284..c90ddaed 100644 --- a/src/const.js +++ b/src/const.js @@ -361,8 +361,3 @@ const WASM_EXPORT_TABLE_NAME = "__indirect_function_table"; /** @const */ const WASM_PAGE_SIZE = 64 * 1024; - -/** @const */ -const COVERAGE_EXPORT_PREFIX = "___profn_"; -/** @const */ -const COVERAGE_FILE_PREFIX = "coverage_data"; diff --git a/src/coverage.js b/src/coverage.js deleted file mode 100644 index 83d34438..00000000 --- a/src/coverage.js +++ /dev/null @@ -1,133 +0,0 @@ -"use strict"; - -const is_env_node = v86util.check_env_node(); -const fs = is_env_node && require("fs"); -const path = is_env_node && require("path"); - -/** @constructor */ -function CoverageLogger() -{ - this.ENABLED = COVERAGE_LOGGER_ALLOW && DEBUG && is_env_node; - if(!this.ENABLED) - { - return; - } - this.should_log_coverage = false; - this.memory_base = 0; -} - -CoverageLogger.prototype.log_start = function() -{ - if(!this.ENABLED) - { - return; - } - this.should_log_coverage = true; -}; - -CoverageLogger.prototype.log_end = function() -{ - if(!this.ENABLED) - { - return; - } - this.should_log_coverage = false; -}; - -CoverageLogger.prototype.init = function(wm) -{ - if(!this.ENABLED) - { - return; - } - - this.coverage_map = {}; - this.memory_base = wm.imports.env["memoryBase"]; - this.COVERAGE_DATA_PATH = path.join(__dirname, "coverage"); - - for(let name of Object.keys(wm.exports)) - { - if(name.startsWith(COVERAGE_EXPORT_PREFIX)) - { - const fn_id = wm.exports[name]; - this.coverage_map[fn_id] = {}; - - const coverage_data = this.coverage_map[fn_id]; - // fn_id -> func_name - coverage_data.fn_name = name.slice(COVERAGE_EXPORT_PREFIX.length); - // fn_id -> block_covered ([0,2,3]) - coverage_data.visit_logs = new Uint8Array(8); - // Position within visit_logs from where to append data - coverage_data.pos = 0; - // Total number of conditional blocks in fn_id - coverage_data.total_blocks = 0; - } - } -}; - -CoverageLogger.prototype.log = function(fn_name_offset, num_blocks, visited_block) -{ - if(!this.ENABLED || !this.should_log_coverage) - { - return; - } - - // fn_name_offset is an offset in the data section to where the string of the function - // name is stored, so it varies by memoryBase, whereas the __profn exported fn_id doesn't - const fn_id = fn_name_offset - this.memory_base; - const coverage_data = this.coverage_map[fn_id]; - if(!coverage_data) - { - // Static functions may not be "discovered" in coverage_init - we currently simply - // skip them - return; - } - - const log_pos = coverage_data.pos; - const existing_entry = coverage_data.visit_logs.indexOf(visited_block); - if((existing_entry > -1 && existing_entry < log_pos) || num_blocks > 0xFF) - { - // If we'd like to profile frequency of code visited, we should be using counters - // instead. This approach was simply faster to measure coverage. - return; - } - - coverage_data.total_blocks = num_blocks; - coverage_data.visit_logs[log_pos] = visited_block; - coverage_data.pos++; - - if(log_pos >= coverage_data.visit_logs.length - 1) - { - this.dump_to_files(); - coverage_data.pos = 0; - } -}; - -CoverageLogger.prototype.dump_to_files = function() -{ - if(!this.ENABLED) - { - return; - } - - for(let fn_id of Object.keys(this.coverage_map)) - { - const coverage_data = this.coverage_map[fn_id]; - if(coverage_data.pos) - { - const fn_name = coverage_data.fn_name; - const total_blocks = coverage_data.total_blocks; - const filename = path.join( - this.COVERAGE_DATA_PATH, - `${COVERAGE_FILE_PREFIX}_${fn_name}_${total_blocks}` - ); - // XXX: Experiment more with async I/O - preliminarily it seemed to choke the nasm test - // even when limiting max files open simultaneously - fs["appendFileSync"]( - filename, - Buffer.from(coverage_data.visit_logs.buffer, 0, coverage_data.pos) - ); - coverage_data.pos = 0; - } - } -}; diff --git a/src/cpu.js b/src/cpu.js index f7db3918..59e64cb3 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -11,11 +11,10 @@ var CPU_LOG_VERBOSE = false; /** @constructor */ -function CPU(bus, wm, v86oxide, coverage_logger) +function CPU(bus, wm, v86oxide) { this.wm = wm; this.v86oxide = v86oxide; - this.coverage_logger = coverage_logger; this.wasm_patch(wm); this.create_jit_imports(); @@ -1360,9 +1359,6 @@ let do_many_cycles_total = 0; CPU.prototype.do_many_cycles = function() { - // Capture the total time we were executing instructions - //this.coverage_logger.log_start(); - if(ENABLE_PROFILER) { var start_time = v86.microtick(); @@ -1375,8 +1371,6 @@ CPU.prototype.do_many_cycles = function() do_many_cycles_total += v86.microtick() - start_time; do_many_cycles_count++; } - - //this.coverage_logger.log_end(); }; /** @export */ diff --git a/src/main.js b/src/main.js index b397e5d7..b692425f 100644 --- a/src/main.js +++ b/src/main.js @@ -4,9 +4,8 @@ * @constructor * @param {Object=} wm * @param {Object=} codegen - * @param {Object=} coverage_logger */ -function v86(bus, wm, codegen, coverage_logger) +function v86(bus, wm, codegen) { /** @type {boolean} */ this.running = false; @@ -15,7 +14,7 @@ function v86(bus, wm, codegen, coverage_logger) this.stopped = false; /** @type {CPU} */ - this.cpu = new CPU(bus, wm, codegen, coverage_logger); + this.cpu = new CPU(bus, wm, codegen); this.bus = bus; bus.register("cpu-init", this.init, this); diff --git a/tests/coverage/gen_report.js b/tests/coverage/gen_report.js deleted file mode 100755 index fdc1d9fb..00000000 --- a/tests/coverage/gen_report.js +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env node -"use strict"; - -const Buffer = require("buffer").Buffer; -const fs = require("fs"); -const path = require("path"); -const assert = require("assert"); - -const DATA_PATH = path.join(__dirname, "..", "..", "build", "coverage"); -const REPORT_PATH = path.join(__dirname, "build"); - -const data_regex = /^coverage_data_(.*)_([0-9]+)$/; -const data_files = fs.readdirSync(DATA_PATH); -const report_files = fs.readdirSync(REPORT_PATH); -const report_regex = /^report_([0-9]+)$/; -const report_num = report_files.filter(name => { - // Only report_* files - return report_regex.test(name); -}).map( - // report_{0,1} -> [0,1] - report => Number(report.match(report_regex)[1]) -).reduce( - // reduce to max report_num (1 in example), defaulting to 0 - (a, b) => (a > b ? a : b), - 0 -); - -const first_report = report_num === 0; -const prev_report_file = path.join(REPORT_PATH, `report_${report_num}`); -const prev_report_compare = path.join(REPORT_PATH, `report_{${report_num},${report_num + 1}}`); -const report_file = path.join(REPORT_PATH, `report_${report_num + 1}`); - -const raw_json_file = path.join(REPORT_PATH, "all_raw.json"); - -if(!first_report) -{ - // May fail if parsed Number != text number, such as report_001 vs. report_1 - assert.ok( - fs.existsSync(prev_report_file), - `Report filename format inconsistent. Expected latest: ${prev_report_file}` - ); -} - -let count_fns = 0; -const all_data = []; - -for(let file of data_files) -{ - const data_filename_fmt = file.match(data_regex); - if(!data_filename_fmt || data_filename_fmt.length !== 3) - { - continue; - } - - count_fns++; - const data = { - fn_name: data_filename_fmt[1], - total_blocks: Number(data_filename_fmt[2]), - untouched: [], - }; - - // When old coverage_data is not deleted, and the number of conditional blocks in a function change, - // this may trigger - assert.ok(!all_data.find(elem => elem.fn_name === data.fn_name), `Function from ${file} seen already`); - all_data.push(data); - - const buffer = fs.readFileSync(path.join(DATA_PATH, file)); - for(let block_index = 0; block_index < data.total_blocks; block_index++) - { - if(buffer.indexOf(block_index) === -1) - { - assert.ok(block_index !== 0, `0th block untouched in ${file}`); - data.untouched.push(block_index); - } - } - - // llvm logs the 0th block (function entry), which we don't want to consider - // XXX: The 0th block also implies an `else` block sometimes, which we miss - data.total_blocks--; - - const touched = data.total_blocks - data.untouched.length; - const total = data.total_blocks; - const untouched = data.untouched.length; - const percent = total === 0 ? 100 : (touched / total * 100).toFixed(0); - const log_str = `${percent}% | ${touched} / ${total}\ttouched in ${data.fn_name}; ` + - `untouched: ${data.untouched}\n`; - - fs.appendFileSync(report_file, log_str); -} -fs.writeFileSync(raw_json_file, JSON.stringify(all_data)); - -assert.ok(count_fns > 0, "No coverage data files found"); - -console.log("[+] Writing to", report_file); -console.log("[+] Total functions:", count_fns); -console.log("[+] Helpful commands:"); - -console.log(`\tsort -n ${report_file} | less`); -if(!first_report) -{ - console.log(`\tgit diff --no-index ${prev_report_compare}`); -} From 697bd4c64d8950aab6c68923e57d860924505bb1 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1659/2137] Disambiguate drop --- src/rust/wasmgen/wasm_util.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/wasmgen/wasm_util.rs b/src/rust/wasmgen/wasm_util.rs index 6524852c..4950709d 100644 --- a/src/rust/wasmgen/wasm_util.rs +++ b/src/rust/wasmgen/wasm_util.rs @@ -67,7 +67,7 @@ pub trait WasmBuf { fn block_void(&mut self); fn block_end(&mut self); fn return_(&mut self); - fn drop(&mut self); + fn drop_(&mut self); fn brtable_and_cases(&mut self, cases_count: u32); fn br(&mut self, depth: u32); fn get_local(&mut self, local: &WasmLocal); @@ -290,7 +290,7 @@ impl WasmBuf for Vec { fn return_(&mut self) { self.push(op::OP_RETURN); } - fn drop(&mut self) { self.push(op::OP_DROP); } + fn drop_(&mut self) { self.push(op::OP_DROP); } // Generate a br_table where an input of [i] will branch [i]th outer block, // where [i] is passed on the wasm stack From 4bfd024366dd1bacae74e55400b2a1c6a5313123 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1660/2137] Simplify gen_safe_read_write by removing fallback function --- src/rust/codegen.rs | 173 +++-- src/rust/cpu2/cpu.rs | 66 ++ src/rust/cpu2/instruction_helpers.rs | 23 +- src/rust/jit_instructions.rs | 1047 ++++---------------------- 4 files changed, 332 insertions(+), 977 deletions(-) diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index b1d06423..70ce8b54 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -1231,7 +1231,6 @@ pub fn gen_safe_read_write( bits: BitSize, address_local: &WasmLocal, f: &dyn Fn(&mut JitContext), - fallback_fn: &dyn Fn(&mut JitContext), ) { ctx.builder.instruction_body.get_local(address_local); @@ -1270,9 +1269,9 @@ pub fn gen_safe_read_write( ctx.builder.instruction_body.and_i32(); } - // Pseudo: - // if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]); - ctx.builder.instruction_body.if_void(); + let can_use_fast_path_local = ctx.builder.tee_new_local(); + + ctx.builder.instruction_body.if_i32(); gen_profiler_stat_increment(ctx.builder, profiler::stat::SAFE_READ_WRITE_FAST); @@ -1283,8 +1282,6 @@ pub fn gen_safe_read_write( ctx.builder.instruction_body.xor_i32(); let phys_addr_local = ctx.builder.tee_new_local(); - // now store the value on stack to phys_addr - ctx.builder.instruction_body.get_local(&phys_addr_local); match bits { BitSize::BYTE => { @@ -1306,68 +1303,140 @@ pub fn gen_safe_read_write( BitSize::DQWORD => assert!(false), // not used } - f(ctx); - - match bits { - BitSize::BYTE => { - ctx.builder - .instruction_body - .store_u8(unsafe { mem8 } as u32); - }, - BitSize::WORD => { - ctx.builder - .instruction_body - .store_unaligned_u16(unsafe { mem8 } as u32); - }, - BitSize::DWORD => { - ctx.builder - .instruction_body - .store_unaligned_i32(unsafe { mem8 } as u32); - }, - BitSize::QWORD => assert!(false), // not used - BitSize::DQWORD => assert!(false), // not used - }; - ctx.builder.free_local(phys_addr_local); - - // Pseudo: - // else { - // *previous_ip = *instruction_pointer & ~0xFFF | start_of_instruction; - // fallback_fn(); - // if(page_fault) return; - // } ctx.builder.instruction_body.else_(); + { + if cfg!(feature = "profiler") && cfg!(feature = "profiler_instrument") { + ctx.builder.instruction_body.get_local(&address_local); + ctx.builder.instruction_body.get_local(&entry_local); + gen_call_fn2(ctx.builder, "report_safe_read_write_jit_slow"); + } - if cfg!(feature = "profiler") && cfg!(feature = "profiler_instrument") { ctx.builder.instruction_body.get_local(&address_local); - ctx.builder.instruction_body.get_local(&entry_local); - gen_call_fn2(ctx.builder, "report_safe_read_write_jit_slow"); + + match bits { + BitSize::BYTE => { + gen_call_fn1_ret(ctx.builder, "safe_read_write8_slow_jit"); + }, + BitSize::WORD => { + gen_call_fn1_ret(ctx.builder, "safe_read_write16_slow_jit"); + }, + BitSize::DWORD => { + gen_call_fn1_ret(ctx.builder, "safe_read_write32s_slow_jit"); + }, + BitSize::QWORD => dbg_assert!(false), + BitSize::DQWORD => dbg_assert!(false), + } + + ctx.builder + .instruction_body + .load_u8(global_pointers::PAGE_FAULT); + + ctx.builder.instruction_body.if_void(); + { + gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); + + gen_set_previous_eip_offset_from_eip_with_low_bits( + ctx.builder, + ctx.start_of_current_instruction as i32 & 0xFFF, + ); + + // -2 for the exit-with-pagefault block, +2 for leaving the two nested ifs from this function + let br_offset = ctx.current_brtable_depth - 2 + 2; + ctx.builder.instruction_body.br(br_offset); + } + ctx.builder.instruction_body.block_end(); } + ctx.builder.instruction_body.block_end(); - gen_set_previous_eip_offset_from_eip_with_low_bits( - ctx.builder, - ctx.start_of_current_instruction as i32 & 0xFFF, - ); + // value is now on stack - ctx.builder.instruction_body.get_local(&address_local); - - fallback_fn(ctx); + f(ctx); + let value_local = ctx.builder.set_new_local(); ctx.builder .instruction_body - .load_u8(global_pointers::PAGE_FAULT); + .get_local(&can_use_fast_path_local); ctx.builder.instruction_body.if_void(); - gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction); - gen_move_registers_from_locals_to_memory(ctx); - gen_clear_prefixes(ctx); - ctx.builder.instruction_body.return_(); - ctx.builder.instruction_body.block_end(); - + { + ctx.builder.instruction_body.get_local(&phys_addr_local); + ctx.builder.instruction_body.get_local(&value_local); + + match bits { + BitSize::BYTE => { + ctx.builder + .instruction_body + .store_u8(unsafe { mem8 } as u32); + }, + BitSize::WORD => { + ctx.builder + .instruction_body + .store_unaligned_u16(unsafe { mem8 } as u32); + }, + BitSize::DWORD => { + ctx.builder + .instruction_body + .store_unaligned_i32(unsafe { mem8 } as u32); + }, + BitSize::QWORD => dbg_assert!(false), + BitSize::DQWORD => dbg_assert!(false), + } + } + ctx.builder.instruction_body.else_(); + { + ctx.builder.instruction_body.get_local(&address_local); + ctx.builder.instruction_body.get_local(&value_local); + + match bits { + BitSize::BYTE => { + gen_call_fn2(ctx.builder, "safe_write8_slow_jit"); + }, + BitSize::WORD => { + gen_call_fn2(ctx.builder, "safe_write16_slow_jit"); + }, + BitSize::DWORD => { + gen_call_fn2(ctx.builder, "safe_write32_slow_jit"); + }, + BitSize::QWORD => dbg_assert!(false), + BitSize::DQWORD => dbg_assert!(false), + } + + ctx.builder + .instruction_body + .load_u8(global_pointers::PAGE_FAULT); + + ctx.builder.instruction_body.if_void(); + { + // handled above + //ctx.builder.instruction_body.unreachable(); + ctx.builder.instruction_body.const_i32(match bits { + BitSize::BYTE => 8, + BitSize::WORD => 16, + BitSize::DWORD => 32, + _ => { + dbg_assert!(false); + 0 + }, + }); + ctx.builder.instruction_body.get_local(&address_local); + gen_call_fn2(ctx.builder, "bug_gen_safe_read_write_page_fault"); + } + ctx.builder.instruction_body.block_end(); + } ctx.builder.instruction_body.block_end(); + ctx.builder.free_local(value_local); + ctx.builder.free_local(can_use_fast_path_local); + ctx.builder.free_local(phys_addr_local); ctx.builder.free_local(entry_local); } +#[no_mangle] +pub fn bug_gen_safe_read_write_page_fault(bits: i32, addr: u32) { + dbg_log!("bug: gen_safe_read_write_page_fault {} {:x}", bits, addr); + dbg_assert!(false); +} + pub fn gen_set_last_op1(builder: &mut WasmBuilder, source: &WasmLocal) { builder .instruction_body diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 84146e5a..794432a9 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -2365,10 +2365,28 @@ pub unsafe fn safe_read8_slow_jit(addr: i32) -> i32 { } } +#[no_mangle] +pub unsafe fn safe_read_write8_slow_jit(addr: i32) -> i32 { + match safe_read_write8_slow_jit2(addr) { + Ok(v) => { + *page_fault = false; + v + }, + Err(()) => { + *page_fault = true; + -1 + }, + } +} + unsafe fn safe_read8_slow_jit2(addr: i32) -> OrPageFault { Ok(read8(translate_address_read_jit(addr)?)) } +unsafe fn safe_read_write8_slow_jit2(addr: i32) -> OrPageFault { + Ok(read8(translate_address_write_jit(addr)?)) +} + unsafe fn safe_read16_slow_jit2(addr: i32) -> OrPageFault { if addr & 0xFFF == 0xFFF { return Ok(safe_read8_slow_jit2(addr)? | safe_read8_slow_jit2(addr + 1)? << 8); @@ -2378,6 +2396,15 @@ unsafe fn safe_read16_slow_jit2(addr: i32) -> OrPageFault { }; } +unsafe fn safe_read_write16_slow_jit2(addr: i32) -> OrPageFault { + if addr & 0xFFF == 0xFFF { + return Ok(safe_read_write8_slow_jit2(addr)? | safe_read_write8_slow_jit2(addr + 1)? << 8); + } + else { + return Ok(read16(translate_address_write_jit(addr)?)); + }; +} + unsafe fn safe_read32s_slow_jit2(addr: i32) -> OrPageFault { if addr & 0xFFF >= 0xFFD { return Ok(safe_read16_slow_jit2(addr)? | safe_read16_slow_jit2(addr + 2)? << 16); @@ -2387,6 +2414,17 @@ unsafe fn safe_read32s_slow_jit2(addr: i32) -> OrPageFault { }; } +unsafe fn safe_read_write32s_slow_jit2(addr: i32) -> OrPageFault { + if addr & 0xFFF >= 0xFFD { + return Ok( + safe_read_write16_slow_jit2(addr)? | safe_read_write16_slow_jit2(addr + 2)? << 16 + ); + } + else { + return Ok(read32s(translate_address_write_jit(addr)?)); + }; +} + #[no_mangle] pub unsafe fn safe_read16_slow_jit(addr: i32) -> i32 { match safe_read16_slow_jit2(addr) { @@ -2401,6 +2439,20 @@ pub unsafe fn safe_read16_slow_jit(addr: i32) -> i32 { } } +#[no_mangle] +pub unsafe fn safe_read_write16_slow_jit(addr: i32) -> i32 { + match safe_read16_slow_jit2(addr) { + Ok(v) => { + *page_fault = false; + v + }, + Err(()) => { + *page_fault = true; + -1 + }, + } +} + #[no_mangle] pub unsafe fn safe_read32s_slow_jit(addr: i32) -> i32 { match safe_read32s_slow_jit2(addr) { @@ -2415,6 +2467,20 @@ pub unsafe fn safe_read32s_slow_jit(addr: i32) -> i32 { } } +#[no_mangle] +pub unsafe fn safe_read_write32s_slow_jit(addr: i32) -> i32 { + match safe_read_write32s_slow_jit2(addr) { + Ok(v) => { + *page_fault = false; + v + }, + Err(()) => { + *page_fault = true; + -1 + }, + } +} + pub unsafe fn safe_read64s(addr: i32) -> OrPageFault { let mut x: reg64 = reg64 { i8_0: [0; 8] }; if addr & 0xFFF > 0x1000 - 8 { diff --git a/src/rust/cpu2/instruction_helpers.rs b/src/rust/cpu2/instruction_helpers.rs index 298e7539..7390cd47 100644 --- a/src/rust/cpu2/instruction_helpers.rs +++ b/src/rust/cpu2/instruction_helpers.rs @@ -3,9 +3,8 @@ macro_rules! SAFE_READ_WRITE8 { use cpu2::cpu::translate_address_write; use cpu2::memory::{read8, write8}; match translate_address_write($addr) { - Err(()) => *page_fault = true, + Err(()) => {}, Ok(phys_addr) => { - *page_fault = false; let $value = read8(phys_addr); write8(phys_addr, $instruction); }, @@ -17,24 +16,18 @@ macro_rules! SAFE_READ_WRITE16 { use cpu2::cpu::{translate_address_write, virt_boundary_read16, virt_boundary_write16}; use cpu2::memory::{read16, write16}; match translate_address_write($addr) { - Err(()) => { - *page_fault = true; - }, + Err(()) => {}, Ok(phys_addr) => { if phys_addr & 0xFFF == 0xFFF { match translate_address_write($addr + 1) { - Err(()) => { - *page_fault = true; - }, + Err(()) => {}, Ok(phys_addr_high) => { - *page_fault = false; let $value = virt_boundary_read16(phys_addr, phys_addr_high); virt_boundary_write16(phys_addr, phys_addr_high, $instruction); }, } } else { - *page_fault = false; let $value = read16(phys_addr); write16(phys_addr, $instruction); } @@ -47,17 +40,12 @@ macro_rules! SAFE_READ_WRITE32 { use cpu2::cpu::{translate_address_write, virt_boundary_read32s, virt_boundary_write32}; use cpu2::memory::{read32s, write32}; match translate_address_write($addr) { - Err(()) => { - *page_fault = true; - }, + Err(()) => {}, Ok(phys_addr) => { if phys_addr & 0xFFF >= 0xFFD { match translate_address_write($addr + 3 & !3) { - Err(()) => { - *page_fault = true; - }, + Err(()) => {}, Ok(phys_addr_high) => { - *page_fault = false; let phys_addr_high = phys_addr_high | ($addr as u32) + 3 & 3; let $value = virt_boundary_read32s(phys_addr, phys_addr_high); virt_boundary_write32(phys_addr, phys_addr_high, $instruction); @@ -65,7 +53,6 @@ macro_rules! SAFE_READ_WRITE32 { } } else { - *page_fault = false; let $value = read32s(phys_addr); write32(phys_addr, $instruction); } diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index c56a667d..dc743c55 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -419,18 +419,13 @@ macro_rules! make_imm_read( ); macro_rules! define_instruction_read_write_mem8( - ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, reg) => ( + ($fn:expr, $name_mem:ident, $name_reg:ident, reg) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); codegen::gen_safe_read_write(ctx, BitSize::BYTE, &address_local, &|ref mut ctx| { codegen::gen_get_reg8(ctx, r); codegen::gen_call_fn2_ret(ctx.builder, $fn); - }, &|ref mut ctx| { - ctx.builder.instruction_body.const_i32(r as i32); - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn2(ctx.builder, $fallback_fn); - codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } @@ -443,17 +438,13 @@ macro_rules! define_instruction_read_write_mem8( } ); - ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, constant_one) => ( + ($fn:expr, $name_mem:ident, $name_reg:ident, constant_one) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); codegen::gen_safe_read_write(ctx, BitSize::BYTE, &address_local, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(1); codegen::gen_call_fn2_ret(ctx.builder, $fn); - }, &|ref mut ctx| { - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn1(ctx.builder, $fallback_fn); - codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } @@ -466,7 +457,7 @@ macro_rules! define_instruction_read_write_mem8( } ); - ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, cl) => ( + ($fn:expr, $name_mem:ident, $name_reg:ident, cl) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); @@ -475,10 +466,6 @@ macro_rules! define_instruction_read_write_mem8( ctx.builder.instruction_body.const_i32(31); ctx.builder.instruction_body.and_i32(); codegen::gen_call_fn2_ret(ctx.builder, $fn); - }, &|ref mut ctx| { - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn1(ctx.builder, $fallback_fn); - codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } @@ -493,7 +480,7 @@ macro_rules! define_instruction_read_write_mem8( } ); - ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, $imm:ident) => ( + ($fn:expr, $name_mem:ident, $name_reg:ident, $imm:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); @@ -501,11 +488,6 @@ macro_rules! define_instruction_read_write_mem8( codegen::gen_safe_read_write(ctx, BitSize::BYTE, &address_local, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn2_ret(ctx.builder, $fn); - }, &|ref mut ctx| { - ctx.builder.instruction_body.const_i32(imm as i32); - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn2(ctx.builder, $fallback_fn); - codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } @@ -521,18 +503,13 @@ macro_rules! define_instruction_read_write_mem8( ); macro_rules! define_instruction_read_write_mem16( - ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, reg) => ( + ($fn:expr, $name_mem:ident, $name_reg:ident, reg) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); codegen::gen_safe_read_write(ctx, BitSize::WORD, &address_local, &|ref mut ctx| { codegen::gen_get_reg16(ctx, r); codegen::gen_call_fn2_ret(ctx.builder, $fn); - }, &|ref mut ctx| { - ctx.builder.instruction_body.const_i32(r as i32); - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn2(ctx.builder, $fallback_fn); - codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } @@ -545,17 +522,13 @@ macro_rules! define_instruction_read_write_mem16( } ); - ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, constant_one) => ( + ($fn:expr, $name_mem:ident, $name_reg:ident, constant_one) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); codegen::gen_safe_read_write(ctx, BitSize::WORD, &address_local, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(1); codegen::gen_call_fn2_ret(ctx.builder, $fn); - }, &|ref mut ctx| { - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn1(ctx.builder, $fallback_fn); - codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } @@ -568,7 +541,7 @@ macro_rules! define_instruction_read_write_mem16( } ); - ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, cl) => ( + ($fn:expr, $name_mem:ident, $name_reg:ident, cl) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); @@ -577,10 +550,6 @@ macro_rules! define_instruction_read_write_mem16( ctx.builder.instruction_body.const_i32(31); ctx.builder.instruction_body.and_i32(); codegen::gen_call_fn2_ret(ctx.builder, $fn); - }, &|ref mut ctx| { - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn1(ctx.builder, $fallback_fn); - codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } @@ -595,7 +564,7 @@ macro_rules! define_instruction_read_write_mem16( } ); - ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, reg, cl) => ( + ($fn:expr, $name_mem:ident, $name_reg:ident, reg, cl) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); @@ -605,11 +574,6 @@ macro_rules! define_instruction_read_write_mem16( ctx.builder.instruction_body.const_i32(31); ctx.builder.instruction_body.and_i32(); codegen::gen_call_fn3_ret(ctx.builder, $fn); - }, &|ref mut ctx| { - ctx.builder.instruction_body.const_i32(r as i32); - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn2(ctx.builder, $fallback_fn); - codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } @@ -625,7 +589,7 @@ macro_rules! define_instruction_read_write_mem16( } ); - ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, reg, $imm:ident) => ( + ($fn:expr, $name_mem:ident, $name_reg:ident, reg, $imm:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); @@ -634,12 +598,6 @@ macro_rules! define_instruction_read_write_mem16( codegen::gen_get_reg16(ctx, r); ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn3_ret(ctx.builder, $fn); - }, &|ref mut ctx| { - ctx.builder.instruction_body.const_i32(r as i32); - ctx.builder.instruction_body.const_i32(imm as i32); - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn3(ctx.builder, $fallback_fn); - codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } @@ -654,16 +612,12 @@ macro_rules! define_instruction_read_write_mem16( } ); - ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, none) => ( + ($fn:expr, $name_mem:ident, $name_reg:ident, none) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); codegen::gen_safe_read_write(ctx, BitSize::WORD, &address_local, &|ref mut ctx| { codegen::gen_call_fn1_ret(ctx.builder, $fn); - }, &|ref mut ctx| { - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn1(ctx.builder, $fallback_fn); - codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } @@ -675,7 +629,7 @@ macro_rules! define_instruction_read_write_mem16( } ); - ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, $imm:ident) => ( + ($fn:expr, $name_mem:ident, $name_reg:ident, $imm:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); @@ -683,11 +637,6 @@ macro_rules! define_instruction_read_write_mem16( codegen::gen_safe_read_write(ctx, BitSize::WORD, &address_local, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn2_ret(ctx.builder, $fn); - }, &|ref mut ctx| { - ctx.builder.instruction_body.const_i32(imm as i32); - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn2(ctx.builder, $fallback_fn); - codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } @@ -703,18 +652,13 @@ macro_rules! define_instruction_read_write_mem16( ); macro_rules! define_instruction_read_write_mem32( - ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, reg) => ( + ($fn:expr, $name_mem:ident, $name_reg:ident, reg) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { codegen::gen_get_reg32(ctx, r); codegen::gen_call_fn2_ret(ctx.builder, $fn); - }, &|ref mut ctx| { - ctx.builder.instruction_body.const_i32(r as i32); - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn2(ctx.builder, $fallback_fn); - codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } @@ -727,7 +671,7 @@ macro_rules! define_instruction_read_write_mem32( } ); - ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, xreg) => ( + ($fn:expr, $name_mem:ident, $name_reg:ident, xreg) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); @@ -740,11 +684,6 @@ macro_rules! define_instruction_read_write_mem32( ); ctx.builder.instruction_body.get_local(&dest_operand); ctx.builder.free_local(dest_operand); - }, &|ref mut ctx| { - ctx.builder.instruction_body.const_i32(r as i32); - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn2(ctx.builder, $fallback_fn); - codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } @@ -758,17 +697,13 @@ macro_rules! define_instruction_read_write_mem32( } ); - ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, constant_one) => ( + ($fn:expr, $name_mem:ident, $name_reg:ident, constant_one) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(1); codegen::gen_call_fn2_ret(ctx.builder, $fn); - }, &|ref mut ctx| { - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn1(ctx.builder, $fallback_fn); - codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } @@ -781,7 +716,7 @@ macro_rules! define_instruction_read_write_mem32( } ); - ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, cl) => ( + ($fn:expr, $name_mem:ident, $name_reg:ident, cl) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); @@ -790,10 +725,6 @@ macro_rules! define_instruction_read_write_mem32( ctx.builder.instruction_body.const_i32(31); ctx.builder.instruction_body.and_i32(); codegen::gen_call_fn2_ret(ctx.builder, $fn); - }, &|ref mut ctx| { - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn1(ctx.builder, $fallback_fn); - codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } @@ -808,7 +739,7 @@ macro_rules! define_instruction_read_write_mem32( } ); - ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, reg, cl) => ( + ($fn:expr, $name_mem:ident, $name_reg:ident, reg, cl) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); @@ -818,11 +749,6 @@ macro_rules! define_instruction_read_write_mem32( ctx.builder.instruction_body.const_i32(31); ctx.builder.instruction_body.and_i32(); codegen::gen_call_fn3_ret(ctx.builder, $fn); - }, &|ref mut ctx| { - ctx.builder.instruction_body.const_i32(r as i32); - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn2(ctx.builder, $fallback_fn); - codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } @@ -838,7 +764,7 @@ macro_rules! define_instruction_read_write_mem32( } ); - ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, reg, $imm:ident) => ( + ($fn:expr, $name_mem:ident, $name_reg:ident, reg, $imm:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); @@ -847,12 +773,6 @@ macro_rules! define_instruction_read_write_mem32( codegen::gen_get_reg32(ctx, r); ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn3_ret(ctx.builder, $fn); - }, &|ref mut ctx| { - ctx.builder.instruction_body.const_i32(r as i32); - ctx.builder.instruction_body.const_i32(imm as i32); - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn3(ctx.builder, $fallback_fn); - codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } @@ -867,16 +787,12 @@ macro_rules! define_instruction_read_write_mem32( } ); - ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, none) => ( + ($fn:expr, $name_mem:ident, $name_reg:ident, none) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { codegen::gen_call_fn1_ret(ctx.builder, $fn); - }, &|ref mut ctx| { - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn1(ctx.builder, $fallback_fn); - codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } @@ -888,7 +804,7 @@ macro_rules! define_instruction_read_write_mem32( } ); - ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, ximm32) => ( + ($fn:expr, $name_mem:ident, $name_reg:ident, ximm32) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); @@ -902,11 +818,6 @@ macro_rules! define_instruction_read_write_mem32( ); ctx.builder.instruction_body.get_local(&dest_operand); ctx.builder.free_local(dest_operand); - }, &|ref mut ctx| { - ctx.builder.instruction_body.const_i32(imm as i32); - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn2(ctx.builder, $fallback_fn); - codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } @@ -921,7 +832,7 @@ macro_rules! define_instruction_read_write_mem32( } ); - ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, ximm8s) => ( + ($fn:expr, $name_mem:ident, $name_reg:ident, ximm8s) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); @@ -935,11 +846,6 @@ macro_rules! define_instruction_read_write_mem32( ); ctx.builder.instruction_body.get_local(&dest_operand); ctx.builder.free_local(dest_operand); - }, &|ref mut ctx| { - ctx.builder.instruction_body.const_i32(imm as i32); - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn2(ctx.builder, $fallback_fn); - codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } @@ -954,7 +860,7 @@ macro_rules! define_instruction_read_write_mem32( } ); - ($fn:expr, $fallback_fn:expr, $name_mem:ident, $name_reg:ident, $imm:ident) => ( + ($fn:expr, $name_mem:ident, $name_reg:ident, $imm:ident) => ( pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); @@ -962,11 +868,6 @@ macro_rules! define_instruction_read_write_mem32( codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { ctx.builder.instruction_body.const_i32(imm as i32); codegen::gen_call_fn2_ret(ctx.builder, $fn); - }, &|ref mut ctx| { - ctx.builder.instruction_body.const_i32(imm as i32); - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn2(ctx.builder, $fallback_fn); - codegen::gen_move_registers_from_memory_to_locals(ctx); }); ctx.builder.free_local(address_local); } @@ -1207,27 +1108,9 @@ fn gen_mul32(ctx: &mut JitContext) { codegen::gen_set_flags_changed(ctx.builder, FLAGS_ALL & !1 & !FLAG_OVERFLOW); } -define_instruction_read_write_mem8!( - "add8", - "instr_00_mem", - instr_00_mem_jit, - instr_00_reg_jit, - reg -); -define_instruction_read_write_mem16!( - "add16", - "instr16_01_mem", - instr16_01_mem_jit, - instr16_01_reg_jit, - reg -); -define_instruction_read_write_mem32!( - gen_add32, - "instr32_01_mem", - instr32_01_mem_jit, - instr32_01_reg_jit, - xreg -); +define_instruction_read_write_mem8!("add8", instr_00_mem_jit, instr_00_reg_jit, reg); +define_instruction_read_write_mem16!("add16", instr16_01_mem_jit, instr16_01_reg_jit, reg); +define_instruction_read_write_mem32!(gen_add32, instr32_01_mem_jit, instr32_01_reg_jit, xreg); define_instruction_write_reg8!("add8", instr_02_mem_jit, instr_02_reg_jit); define_instruction_write_reg16!("add16", instr16_03_mem_jit, instr16_03_reg_jit); @@ -1241,27 +1124,9 @@ pub fn instr32_05_jit(ctx: &mut JitContext, imm32: u32) { group_arith_eax_imm32(ctx, &gen_add32, imm32); } -define_instruction_read_write_mem8!( - "or8", - "instr_08_mem", - instr_08_mem_jit, - instr_08_reg_jit, - reg -); -define_instruction_read_write_mem16!( - "or16", - "instr16_09_mem", - instr16_09_mem_jit, - instr16_09_reg_jit, - reg -); -define_instruction_read_write_mem32!( - gen_or32, - "instr32_09_mem", - instr32_09_mem_jit, - instr32_09_reg_jit, - xreg -); +define_instruction_read_write_mem8!("or8", instr_08_mem_jit, instr_08_reg_jit, reg); +define_instruction_read_write_mem16!("or16", instr16_09_mem_jit, instr16_09_reg_jit, reg); +define_instruction_read_write_mem32!(gen_or32, instr32_09_mem_jit, instr32_09_reg_jit, xreg); define_instruction_write_reg8!("or8", instr_0A_mem_jit, instr_0A_reg_jit); define_instruction_write_reg16!("or16", instr16_0B_mem_jit, instr16_0B_reg_jit); @@ -1275,27 +1140,9 @@ pub fn instr32_0D_jit(ctx: &mut JitContext, imm32: u32) { group_arith_eax_imm32(ctx, &gen_or32, imm32); } -define_instruction_read_write_mem8!( - "adc8", - "instr_10_mem", - instr_10_mem_jit, - instr_10_reg_jit, - reg -); -define_instruction_read_write_mem16!( - "adc16", - "instr16_11_mem", - instr16_11_mem_jit, - instr16_11_reg_jit, - reg -); -define_instruction_read_write_mem32!( - "adc32", - "instr32_11_mem", - instr32_11_mem_jit, - instr32_11_reg_jit, - reg -); +define_instruction_read_write_mem8!("adc8", instr_10_mem_jit, instr_10_reg_jit, reg); +define_instruction_read_write_mem16!("adc16", instr16_11_mem_jit, instr16_11_reg_jit, reg); +define_instruction_read_write_mem32!("adc32", instr32_11_mem_jit, instr32_11_reg_jit, reg); define_instruction_write_reg8!("adc8", instr_12_mem_jit, instr_12_reg_jit); define_instruction_write_reg16!("adc16", instr16_13_mem_jit, instr16_13_reg_jit); @@ -1309,27 +1156,9 @@ pub fn instr32_15_jit(ctx: &mut JitContext, imm32: u32) { group_arith_eax_imm32(ctx, &gen_adc32, imm32); } -define_instruction_read_write_mem8!( - "sbb8", - "instr_18_mem", - instr_18_mem_jit, - instr_18_reg_jit, - reg -); -define_instruction_read_write_mem16!( - "sbb16", - "instr16_19_mem", - instr16_19_mem_jit, - instr16_19_reg_jit, - reg -); -define_instruction_read_write_mem32!( - "sbb32", - "instr32_19_mem", - instr32_19_mem_jit, - instr32_19_reg_jit, - reg -); +define_instruction_read_write_mem8!("sbb8", instr_18_mem_jit, instr_18_reg_jit, reg); +define_instruction_read_write_mem16!("sbb16", instr16_19_mem_jit, instr16_19_reg_jit, reg); +define_instruction_read_write_mem32!("sbb32", instr32_19_mem_jit, instr32_19_reg_jit, reg); define_instruction_write_reg8!("sbb8", instr_1A_mem_jit, instr_1A_reg_jit); define_instruction_write_reg16!("sbb16", instr16_1B_mem_jit, instr16_1B_reg_jit); @@ -1343,27 +1172,9 @@ pub fn instr32_1D_jit(ctx: &mut JitContext, imm32: u32) { group_arith_eax_imm32(ctx, &gen_sbb32, imm32); } -define_instruction_read_write_mem8!( - "and8", - "instr_20_mem", - instr_20_mem_jit, - instr_20_reg_jit, - reg -); -define_instruction_read_write_mem16!( - "and16", - "instr16_21_mem", - instr16_21_mem_jit, - instr16_21_reg_jit, - reg -); -define_instruction_read_write_mem32!( - gen_and32, - "instr32_21_mem", - instr32_21_mem_jit, - instr32_21_reg_jit, - xreg -); +define_instruction_read_write_mem8!("and8", instr_20_mem_jit, instr_20_reg_jit, reg); +define_instruction_read_write_mem16!("and16", instr16_21_mem_jit, instr16_21_reg_jit, reg); +define_instruction_read_write_mem32!(gen_and32, instr32_21_mem_jit, instr32_21_reg_jit, xreg); define_instruction_write_reg8!("and8", instr_22_mem_jit, instr_22_reg_jit); define_instruction_write_reg16!("and16", instr16_23_mem_jit, instr16_23_reg_jit); @@ -1377,27 +1188,9 @@ pub fn instr32_25_jit(ctx: &mut JitContext, imm32: u32) { group_arith_eax_imm32(ctx, &gen_and32, imm32); } -define_instruction_read_write_mem8!( - "sub8", - "instr_28_mem", - instr_28_mem_jit, - instr_28_reg_jit, - reg -); -define_instruction_read_write_mem16!( - "sub16", - "instr16_29_mem", - instr16_29_mem_jit, - instr16_29_reg_jit, - reg -); -define_instruction_read_write_mem32!( - gen_sub32, - "instr32_29_mem", - instr32_29_mem_jit, - instr32_29_reg_jit, - xreg -); +define_instruction_read_write_mem8!("sub8", instr_28_mem_jit, instr_28_reg_jit, reg); +define_instruction_read_write_mem16!("sub16", instr16_29_mem_jit, instr16_29_reg_jit, reg); +define_instruction_read_write_mem32!(gen_sub32, instr32_29_mem_jit, instr32_29_reg_jit, xreg); define_instruction_write_reg8!("sub8", instr_2A_mem_jit, instr_2A_reg_jit); define_instruction_write_reg16!("sub16", instr16_2B_mem_jit, instr16_2B_reg_jit); @@ -1411,27 +1204,9 @@ pub fn instr32_2D_jit(ctx: &mut JitContext, imm32: u32) { group_arith_eax_imm32(ctx, &gen_sub32, imm32); } -define_instruction_read_write_mem8!( - "xor8", - "instr_30_mem", - instr_30_mem_jit, - instr_30_reg_jit, - reg -); -define_instruction_read_write_mem16!( - "xor16", - "instr16_31_mem", - instr16_31_mem_jit, - instr16_31_reg_jit, - reg -); -define_instruction_read_write_mem32!( - gen_xor32, - "instr32_31_mem", - instr32_31_mem_jit, - instr32_31_reg_jit, - xreg -); +define_instruction_read_write_mem8!("xor8", instr_30_mem_jit, instr_30_reg_jit, reg); +define_instruction_read_write_mem16!("xor16", instr16_31_mem_jit, instr16_31_reg_jit, reg); +define_instruction_read_write_mem32!(gen_xor32, instr32_31_mem_jit, instr32_31_reg_jit, xreg); define_instruction_write_reg8!("xor8", instr_32_mem_jit, instr_32_reg_jit); define_instruction_write_reg16!("xor16", instr16_33_mem_jit, instr16_33_reg_jit); @@ -1751,261 +1526,91 @@ pub fn instr32_7E_jit(_ctx: &mut JitContext, _imm: u32) {} pub fn instr16_7F_jit(_ctx: &mut JitContext, _imm: u32) {} pub fn instr32_7F_jit(_ctx: &mut JitContext, _imm: u32) {} -define_instruction_read_write_mem8!( - "add8", - "instr_80_0_mem", - instr_80_0_mem_jit, - instr_80_0_reg_jit, - imm8 -); -define_instruction_read_write_mem8!( - "or8", - "instr_80_1_mem", - instr_80_1_mem_jit, - instr_80_1_reg_jit, - imm8 -); -define_instruction_read_write_mem8!( - "adc8", - "instr_80_2_mem", - instr_80_2_mem_jit, - instr_80_2_reg_jit, - imm8 -); -define_instruction_read_write_mem8!( - "sbb8", - "instr_80_3_mem", - instr_80_3_mem_jit, - instr_80_3_reg_jit, - imm8 -); -define_instruction_read_write_mem8!( - "and8", - "instr_80_4_mem", - instr_80_4_mem_jit, - instr_80_4_reg_jit, - imm8 -); -define_instruction_read_write_mem8!( - "sub8", - "instr_80_5_mem", - instr_80_5_mem_jit, - instr_80_5_reg_jit, - imm8 -); -define_instruction_read_write_mem8!( - "xor8", - "instr_80_6_mem", - instr_80_6_mem_jit, - instr_80_6_reg_jit, - imm8 -); +define_instruction_read_write_mem8!("add8", instr_80_0_mem_jit, instr_80_0_reg_jit, imm8); +define_instruction_read_write_mem8!("or8", instr_80_1_mem_jit, instr_80_1_reg_jit, imm8); +define_instruction_read_write_mem8!("adc8", instr_80_2_mem_jit, instr_80_2_reg_jit, imm8); +define_instruction_read_write_mem8!("sbb8", instr_80_3_mem_jit, instr_80_3_reg_jit, imm8); +define_instruction_read_write_mem8!("and8", instr_80_4_mem_jit, instr_80_4_reg_jit, imm8); +define_instruction_read_write_mem8!("sub8", instr_80_5_mem_jit, instr_80_5_reg_jit, imm8); +define_instruction_read_write_mem8!("xor8", instr_80_6_mem_jit, instr_80_6_reg_jit, imm8); -define_instruction_read_write_mem16!( - "add16", - "instr16_81_0_mem", - instr16_81_0_mem_jit, - instr16_81_0_reg_jit, - imm16 -); +define_instruction_read_write_mem16!("add16", instr16_81_0_mem_jit, instr16_81_0_reg_jit, imm16); define_instruction_read_write_mem32!( gen_add32, - "instr32_81_0_mem", instr32_81_0_mem_jit, instr32_81_0_reg_jit, ximm32 ); -define_instruction_read_write_mem16!( - "or16", - "instr16_81_1_mem", - instr16_81_1_mem_jit, - instr16_81_1_reg_jit, - imm16 -); -define_instruction_read_write_mem32!( - gen_or32, - "instr32_81_1_mem", - instr32_81_1_mem_jit, - instr32_81_1_reg_jit, - ximm32 -); +define_instruction_read_write_mem16!("or16", instr16_81_1_mem_jit, instr16_81_1_reg_jit, imm16); +define_instruction_read_write_mem32!(gen_or32, instr32_81_1_mem_jit, instr32_81_1_reg_jit, ximm32); -define_instruction_read_write_mem16!( - "adc16", - "instr16_81_2_mem", - instr16_81_2_mem_jit, - instr16_81_2_reg_jit, - imm16 -); -define_instruction_read_write_mem32!( - "adc32", - "instr32_81_2_mem", - instr32_81_2_mem_jit, - instr32_81_2_reg_jit, - imm32 -); +define_instruction_read_write_mem16!("adc16", instr16_81_2_mem_jit, instr16_81_2_reg_jit, imm16); +define_instruction_read_write_mem32!("adc32", instr32_81_2_mem_jit, instr32_81_2_reg_jit, imm32); -define_instruction_read_write_mem16!( - "sbb16", - "instr16_81_3_mem", - instr16_81_3_mem_jit, - instr16_81_3_reg_jit, - imm16 -); -define_instruction_read_write_mem32!( - "sbb32", - "instr32_81_3_mem", - instr32_81_3_mem_jit, - instr32_81_3_reg_jit, - imm32 -); +define_instruction_read_write_mem16!("sbb16", instr16_81_3_mem_jit, instr16_81_3_reg_jit, imm16); +define_instruction_read_write_mem32!("sbb32", instr32_81_3_mem_jit, instr32_81_3_reg_jit, imm32); -define_instruction_read_write_mem16!( - "and16", - "instr16_81_4_mem", - instr16_81_4_mem_jit, - instr16_81_4_reg_jit, - imm16 -); +define_instruction_read_write_mem16!("and16", instr16_81_4_mem_jit, instr16_81_4_reg_jit, imm16); define_instruction_read_write_mem32!( gen_and32, - "instr32_81_4_mem", instr32_81_4_mem_jit, instr32_81_4_reg_jit, ximm32 ); -define_instruction_read_write_mem16!( - "sub16", - "instr16_81_5_mem", - instr16_81_5_mem_jit, - instr16_81_5_reg_jit, - imm16 -); +define_instruction_read_write_mem16!("sub16", instr16_81_5_mem_jit, instr16_81_5_reg_jit, imm16); define_instruction_read_write_mem32!( gen_sub32, - "instr32_81_5_mem", instr32_81_5_mem_jit, instr32_81_5_reg_jit, ximm32 ); -define_instruction_read_write_mem16!( - "xor16", - "instr16_81_6_mem", - instr16_81_6_mem_jit, - instr16_81_6_reg_jit, - imm16 -); +define_instruction_read_write_mem16!("xor16", instr16_81_6_mem_jit, instr16_81_6_reg_jit, imm16); define_instruction_read_write_mem32!( gen_xor32, - "instr32_81_6_mem", instr32_81_6_mem_jit, instr32_81_6_reg_jit, ximm32 ); -define_instruction_read_write_mem16!( - "add16", - "instr16_83_0_mem", - instr16_83_0_mem_jit, - instr16_83_0_reg_jit, - imm8s -); +define_instruction_read_write_mem16!("add16", instr16_83_0_mem_jit, instr16_83_0_reg_jit, imm8s); define_instruction_read_write_mem32!( gen_add32, - "instr32_83_0_mem", instr32_83_0_mem_jit, instr32_83_0_reg_jit, ximm8s ); -define_instruction_read_write_mem16!( - "or16", - "instr16_83_1_mem", - instr16_83_1_mem_jit, - instr16_83_1_reg_jit, - imm8s -); -define_instruction_read_write_mem32!( - gen_or32, - "instr32_83_1_mem", - instr32_83_1_mem_jit, - instr32_83_1_reg_jit, - ximm8s -); +define_instruction_read_write_mem16!("or16", instr16_83_1_mem_jit, instr16_83_1_reg_jit, imm8s); +define_instruction_read_write_mem32!(gen_or32, instr32_83_1_mem_jit, instr32_83_1_reg_jit, ximm8s); -define_instruction_read_write_mem16!( - "adc16", - "instr16_83_2_mem", - instr16_83_2_mem_jit, - instr16_83_2_reg_jit, - imm8s -); -define_instruction_read_write_mem32!( - "adc32", - "instr32_83_2_mem", - instr32_83_2_mem_jit, - instr32_83_2_reg_jit, - imm8s -); +define_instruction_read_write_mem16!("adc16", instr16_83_2_mem_jit, instr16_83_2_reg_jit, imm8s); +define_instruction_read_write_mem32!("adc32", instr32_83_2_mem_jit, instr32_83_2_reg_jit, imm8s); -define_instruction_read_write_mem16!( - "sbb16", - "instr16_83_3_mem", - instr16_83_3_mem_jit, - instr16_83_3_reg_jit, - imm8s -); -define_instruction_read_write_mem32!( - "sbb32", - "instr32_83_3_mem", - instr32_83_3_mem_jit, - instr32_83_3_reg_jit, - imm8s -); +define_instruction_read_write_mem16!("sbb16", instr16_83_3_mem_jit, instr16_83_3_reg_jit, imm8s); +define_instruction_read_write_mem32!("sbb32", instr32_83_3_mem_jit, instr32_83_3_reg_jit, imm8s); -define_instruction_read_write_mem16!( - "and16", - "instr16_83_4_mem", - instr16_83_4_mem_jit, - instr16_83_4_reg_jit, - imm8s -); +define_instruction_read_write_mem16!("and16", instr16_83_4_mem_jit, instr16_83_4_reg_jit, imm8s); define_instruction_read_write_mem32!( gen_and32, - "instr32_83_4_mem", instr32_83_4_mem_jit, instr32_83_4_reg_jit, ximm8s ); -define_instruction_read_write_mem16!( - "sub16", - "instr16_83_5_mem", - instr16_83_5_mem_jit, - instr16_83_5_reg_jit, - imm8s -); +define_instruction_read_write_mem16!("sub16", instr16_83_5_mem_jit, instr16_83_5_reg_jit, imm8s); define_instruction_read_write_mem32!( gen_sub32, - "instr32_83_5_mem", instr32_83_5_mem_jit, instr32_83_5_reg_jit, ximm8s ); -define_instruction_read_write_mem16!( - "xor16", - "instr16_83_6_mem", - instr16_83_6_mem_jit, - instr16_83_6_reg_jit, - imm8s -); +define_instruction_read_write_mem16!("xor16", instr16_83_6_mem_jit, instr16_83_6_reg_jit, imm8s); define_instruction_read_write_mem32!( gen_xor32, - "instr32_83_6_mem", instr32_83_6_mem_jit, instr32_83_6_reg_jit, ximm8s @@ -2220,14 +1825,12 @@ pub fn instr32_8F_0_reg_jit(ctx: &mut JitContext, r: u32) { pop32_reg_jit(ctx, r define_instruction_read_write_mem16!( "rol16", - "instr16_C1_0_mem", instr16_C1_0_mem_jit, instr16_C1_0_reg_jit, imm8_5bits ); define_instruction_read_write_mem32!( "rol32", - "instr32_C1_0_mem", instr32_C1_0_mem_jit, instr32_C1_0_reg_jit, imm8_5bits @@ -2235,14 +1838,12 @@ define_instruction_read_write_mem32!( define_instruction_read_write_mem16!( "ror16", - "instr16_C1_1_mem", instr16_C1_1_mem_jit, instr16_C1_1_reg_jit, imm8_5bits ); define_instruction_read_write_mem32!( "ror32", - "instr32_C1_1_mem", instr32_C1_1_mem_jit, instr32_C1_1_reg_jit, imm8_5bits @@ -2250,14 +1851,12 @@ define_instruction_read_write_mem32!( define_instruction_read_write_mem16!( "rcl16", - "instr16_C1_2_mem", instr16_C1_2_mem_jit, instr16_C1_2_reg_jit, imm8_5bits ); define_instruction_read_write_mem32!( "rcl32", - "instr32_C1_2_mem", instr32_C1_2_mem_jit, instr32_C1_2_reg_jit, imm8_5bits @@ -2265,14 +1864,12 @@ define_instruction_read_write_mem32!( define_instruction_read_write_mem16!( "rcr16", - "instr16_C1_3_mem", instr16_C1_3_mem_jit, instr16_C1_3_reg_jit, imm8_5bits ); define_instruction_read_write_mem32!( "rcr32", - "instr32_C1_3_mem", instr32_C1_3_mem_jit, instr32_C1_3_reg_jit, imm8_5bits @@ -2280,14 +1877,12 @@ define_instruction_read_write_mem32!( define_instruction_read_write_mem16!( "shl16", - "instr16_C1_4_mem", instr16_C1_4_mem_jit, instr16_C1_4_reg_jit, imm8_5bits ); define_instruction_read_write_mem32!( "shl32", - "instr32_C1_4_mem", instr32_C1_4_mem_jit, instr32_C1_4_reg_jit, imm8_5bits @@ -2295,14 +1890,12 @@ define_instruction_read_write_mem32!( define_instruction_read_write_mem16!( "shr16", - "instr16_C1_5_mem", instr16_C1_5_mem_jit, instr16_C1_5_reg_jit, imm8_5bits ); define_instruction_read_write_mem32!( "shr32", - "instr32_C1_5_mem", instr32_C1_5_mem_jit, instr32_C1_5_reg_jit, imm8_5bits @@ -2310,14 +1903,12 @@ define_instruction_read_write_mem32!( define_instruction_read_write_mem16!( "shl16", - "instr16_C1_6_mem", instr16_C1_6_mem_jit, instr16_C1_6_reg_jit, imm8_5bits ); define_instruction_read_write_mem32!( "shl32", - "instr32_C1_6_mem", instr32_C1_6_mem_jit, instr32_C1_6_reg_jit, imm8_5bits @@ -2325,14 +1916,12 @@ define_instruction_read_write_mem32!( define_instruction_read_write_mem16!( "sar16", - "instr16_C1_7_mem", instr16_C1_7_mem_jit, instr16_C1_7_reg_jit, imm8_5bits ); define_instruction_read_write_mem32!( "sar32", - "instr32_C1_7_mem", instr32_C1_7_mem_jit, instr32_C1_7_reg_jit, imm8_5bits @@ -2473,130 +2062,32 @@ pub fn instr32_BD_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg32_imm(ctx, 5 pub fn instr32_BE_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg32_imm(ctx, 6, imm) } pub fn instr32_BF_jit(ctx: &mut JitContext, imm: u32) { gen_mov_reg32_imm(ctx, 7, imm) } -define_instruction_read_write_mem8!( - "rol8", - "instr_C0_0_mem", - instr_C0_0_mem_jit, - instr_C0_0_reg_jit, - imm8_5bits -); -define_instruction_read_write_mem8!( - "ror8", - "instr_C0_1_mem", - instr_C0_1_mem_jit, - instr_C0_1_reg_jit, - imm8_5bits -); -define_instruction_read_write_mem8!( - "rcl8", - "instr_C0_2_mem", - instr_C0_2_mem_jit, - instr_C0_2_reg_jit, - imm8_5bits -); -define_instruction_read_write_mem8!( - "rcr8", - "instr_C0_3_mem", - instr_C0_3_mem_jit, - instr_C0_3_reg_jit, - imm8_5bits -); -define_instruction_read_write_mem8!( - "shl8", - "instr_C0_4_mem", - instr_C0_4_mem_jit, - instr_C0_4_reg_jit, - imm8_5bits -); -define_instruction_read_write_mem8!( - "shr8", - "instr_C0_5_mem", - instr_C0_5_mem_jit, - instr_C0_5_reg_jit, - imm8_5bits -); -define_instruction_read_write_mem8!( - "shl8", - "instr_C0_6_mem", - instr_C0_6_mem_jit, - instr_C0_6_reg_jit, - imm8_5bits -); -define_instruction_read_write_mem8!( - "sar8", - "instr_C0_7_mem", - instr_C0_7_mem_jit, - instr_C0_7_reg_jit, - imm8_5bits -); +define_instruction_read_write_mem8!("rol8", instr_C0_0_mem_jit, instr_C0_0_reg_jit, imm8_5bits); +define_instruction_read_write_mem8!("ror8", instr_C0_1_mem_jit, instr_C0_1_reg_jit, imm8_5bits); +define_instruction_read_write_mem8!("rcl8", instr_C0_2_mem_jit, instr_C0_2_reg_jit, imm8_5bits); +define_instruction_read_write_mem8!("rcr8", instr_C0_3_mem_jit, instr_C0_3_reg_jit, imm8_5bits); +define_instruction_read_write_mem8!("shl8", instr_C0_4_mem_jit, instr_C0_4_reg_jit, imm8_5bits); +define_instruction_read_write_mem8!("shr8", instr_C0_5_mem_jit, instr_C0_5_reg_jit, imm8_5bits); +define_instruction_read_write_mem8!("shl8", instr_C0_6_mem_jit, instr_C0_6_reg_jit, imm8_5bits); +define_instruction_read_write_mem8!("sar8", instr_C0_7_mem_jit, instr_C0_7_reg_jit, imm8_5bits); -define_instruction_read_write_mem8!( - "rol8", - "instr_D0_0_mem", - instr_D0_0_mem_jit, - instr_D0_0_reg_jit, - constant_one -); -define_instruction_read_write_mem8!( - "ror8", - "instr_D0_1_mem", - instr_D0_1_mem_jit, - instr_D0_1_reg_jit, - constant_one -); -define_instruction_read_write_mem8!( - "rcl8", - "instr_D0_2_mem", - instr_D0_2_mem_jit, - instr_D0_2_reg_jit, - constant_one -); -define_instruction_read_write_mem8!( - "rcr8", - "instr_D0_3_mem", - instr_D0_3_mem_jit, - instr_D0_3_reg_jit, - constant_one -); -define_instruction_read_write_mem8!( - "shl8", - "instr_D0_4_mem", - instr_D0_4_mem_jit, - instr_D0_4_reg_jit, - constant_one -); -define_instruction_read_write_mem8!( - "shr8", - "instr_D0_5_mem", - instr_D0_5_mem_jit, - instr_D0_5_reg_jit, - constant_one -); -define_instruction_read_write_mem8!( - "shl8", - "instr_D0_6_mem", - instr_D0_6_mem_jit, - instr_D0_6_reg_jit, - constant_one -); -define_instruction_read_write_mem8!( - "sar8", - "instr_D0_7_mem", - instr_D0_7_mem_jit, - instr_D0_7_reg_jit, - constant_one -); +define_instruction_read_write_mem8!("rol8", instr_D0_0_mem_jit, instr_D0_0_reg_jit, constant_one); +define_instruction_read_write_mem8!("ror8", instr_D0_1_mem_jit, instr_D0_1_reg_jit, constant_one); +define_instruction_read_write_mem8!("rcl8", instr_D0_2_mem_jit, instr_D0_2_reg_jit, constant_one); +define_instruction_read_write_mem8!("rcr8", instr_D0_3_mem_jit, instr_D0_3_reg_jit, constant_one); +define_instruction_read_write_mem8!("shl8", instr_D0_4_mem_jit, instr_D0_4_reg_jit, constant_one); +define_instruction_read_write_mem8!("shr8", instr_D0_5_mem_jit, instr_D0_5_reg_jit, constant_one); +define_instruction_read_write_mem8!("shl8", instr_D0_6_mem_jit, instr_D0_6_reg_jit, constant_one); +define_instruction_read_write_mem8!("sar8", instr_D0_7_mem_jit, instr_D0_7_reg_jit, constant_one); define_instruction_read_write_mem16!( "rol16", - "instr16_D1_0_mem", instr16_D1_0_mem_jit, instr16_D1_0_reg_jit, constant_one ); define_instruction_read_write_mem32!( "rol32", - "instr32_D1_0_mem", instr32_D1_0_mem_jit, instr32_D1_0_reg_jit, constant_one @@ -2604,14 +2095,12 @@ define_instruction_read_write_mem32!( define_instruction_read_write_mem16!( "ror16", - "instr16_D1_1_mem", instr16_D1_1_mem_jit, instr16_D1_1_reg_jit, constant_one ); define_instruction_read_write_mem32!( "ror32", - "instr32_D1_1_mem", instr32_D1_1_mem_jit, instr32_D1_1_reg_jit, constant_one @@ -2619,14 +2108,12 @@ define_instruction_read_write_mem32!( define_instruction_read_write_mem16!( "rcl16", - "instr16_D1_2_mem", instr16_D1_2_mem_jit, instr16_D1_2_reg_jit, constant_one ); define_instruction_read_write_mem32!( "rcl32", - "instr32_D1_2_mem", instr32_D1_2_mem_jit, instr32_D1_2_reg_jit, constant_one @@ -2634,14 +2121,12 @@ define_instruction_read_write_mem32!( define_instruction_read_write_mem16!( "rcr16", - "instr16_D1_3_mem", instr16_D1_3_mem_jit, instr16_D1_3_reg_jit, constant_one ); define_instruction_read_write_mem32!( "rcr32", - "instr32_D1_3_mem", instr32_D1_3_mem_jit, instr32_D1_3_reg_jit, constant_one @@ -2649,14 +2134,12 @@ define_instruction_read_write_mem32!( define_instruction_read_write_mem16!( "shl16", - "instr16_D1_4_mem", instr16_D1_4_mem_jit, instr16_D1_4_reg_jit, constant_one ); define_instruction_read_write_mem32!( "shl32", - "instr32_D1_4_mem", instr32_D1_4_mem_jit, instr32_D1_4_reg_jit, constant_one @@ -2664,14 +2147,12 @@ define_instruction_read_write_mem32!( define_instruction_read_write_mem16!( "shr16", - "instr16_D1_5_mem", instr16_D1_5_mem_jit, instr16_D1_5_reg_jit, constant_one ); define_instruction_read_write_mem32!( "shr32", - "instr32_D1_5_mem", instr32_D1_5_mem_jit, instr32_D1_5_reg_jit, constant_one @@ -2679,14 +2160,12 @@ define_instruction_read_write_mem32!( define_instruction_read_write_mem16!( "shl16", - "instr16_D1_6_mem", instr16_D1_6_mem_jit, instr16_D1_6_reg_jit, constant_one ); define_instruction_read_write_mem32!( "shl32", - "instr32_D1_6_mem", instr32_D1_6_mem_jit, instr32_D1_6_reg_jit, constant_one @@ -2694,195 +2173,49 @@ define_instruction_read_write_mem32!( define_instruction_read_write_mem16!( "sar16", - "instr16_D1_7_mem", instr16_D1_7_mem_jit, instr16_D1_7_reg_jit, constant_one ); define_instruction_read_write_mem32!( "sar32", - "instr32_D1_7_mem", instr32_D1_7_mem_jit, instr32_D1_7_reg_jit, constant_one ); -define_instruction_read_write_mem8!( - "rol8", - "instr_D2_0_mem", - instr_D2_0_mem_jit, - instr_D2_0_reg_jit, - cl -); -define_instruction_read_write_mem8!( - "ror8", - "instr_D2_1_mem", - instr_D2_1_mem_jit, - instr_D2_1_reg_jit, - cl -); -define_instruction_read_write_mem8!( - "rcl8", - "instr_D2_2_mem", - instr_D2_2_mem_jit, - instr_D2_2_reg_jit, - cl -); -define_instruction_read_write_mem8!( - "rcr8", - "instr_D2_3_mem", - instr_D2_3_mem_jit, - instr_D2_3_reg_jit, - cl -); -define_instruction_read_write_mem8!( - "shl8", - "instr_D2_4_mem", - instr_D2_4_mem_jit, - instr_D2_4_reg_jit, - cl -); -define_instruction_read_write_mem8!( - "shr8", - "instr_D2_5_mem", - instr_D2_5_mem_jit, - instr_D2_5_reg_jit, - cl -); -define_instruction_read_write_mem8!( - "shl8", - "instr_D2_6_mem", - instr_D2_6_mem_jit, - instr_D2_6_reg_jit, - cl -); -define_instruction_read_write_mem8!( - "sar8", - "instr_D2_7_mem", - instr_D2_7_mem_jit, - instr_D2_7_reg_jit, - cl -); +define_instruction_read_write_mem8!("rol8", instr_D2_0_mem_jit, instr_D2_0_reg_jit, cl); +define_instruction_read_write_mem8!("ror8", instr_D2_1_mem_jit, instr_D2_1_reg_jit, cl); +define_instruction_read_write_mem8!("rcl8", instr_D2_2_mem_jit, instr_D2_2_reg_jit, cl); +define_instruction_read_write_mem8!("rcr8", instr_D2_3_mem_jit, instr_D2_3_reg_jit, cl); +define_instruction_read_write_mem8!("shl8", instr_D2_4_mem_jit, instr_D2_4_reg_jit, cl); +define_instruction_read_write_mem8!("shr8", instr_D2_5_mem_jit, instr_D2_5_reg_jit, cl); +define_instruction_read_write_mem8!("shl8", instr_D2_6_mem_jit, instr_D2_6_reg_jit, cl); +define_instruction_read_write_mem8!("sar8", instr_D2_7_mem_jit, instr_D2_7_reg_jit, cl); -define_instruction_read_write_mem16!( - "rol16", - "instr16_D3_0_mem", - instr16_D3_0_mem_jit, - instr16_D3_0_reg_jit, - cl -); -define_instruction_read_write_mem32!( - "rol32", - "instr32_D3_0_mem", - instr32_D3_0_mem_jit, - instr32_D3_0_reg_jit, - cl -); +define_instruction_read_write_mem16!("rol16", instr16_D3_0_mem_jit, instr16_D3_0_reg_jit, cl); +define_instruction_read_write_mem32!("rol32", instr32_D3_0_mem_jit, instr32_D3_0_reg_jit, cl); -define_instruction_read_write_mem16!( - "ror16", - "instr16_D3_1_mem", - instr16_D3_1_mem_jit, - instr16_D3_1_reg_jit, - cl -); -define_instruction_read_write_mem32!( - "ror32", - "instr32_D3_1_mem", - instr32_D3_1_mem_jit, - instr32_D3_1_reg_jit, - cl -); +define_instruction_read_write_mem16!("ror16", instr16_D3_1_mem_jit, instr16_D3_1_reg_jit, cl); +define_instruction_read_write_mem32!("ror32", instr32_D3_1_mem_jit, instr32_D3_1_reg_jit, cl); -define_instruction_read_write_mem16!( - "rcl16", - "instr16_D3_2_mem", - instr16_D3_2_mem_jit, - instr16_D3_2_reg_jit, - cl -); -define_instruction_read_write_mem32!( - "rcl32", - "instr32_D3_2_mem", - instr32_D3_2_mem_jit, - instr32_D3_2_reg_jit, - cl -); +define_instruction_read_write_mem16!("rcl16", instr16_D3_2_mem_jit, instr16_D3_2_reg_jit, cl); +define_instruction_read_write_mem32!("rcl32", instr32_D3_2_mem_jit, instr32_D3_2_reg_jit, cl); -define_instruction_read_write_mem16!( - "rcr16", - "instr16_D3_3_mem", - instr16_D3_3_mem_jit, - instr16_D3_3_reg_jit, - cl -); -define_instruction_read_write_mem32!( - "rcr32", - "instr32_D3_3_mem", - instr32_D3_3_mem_jit, - instr32_D3_3_reg_jit, - cl -); +define_instruction_read_write_mem16!("rcr16", instr16_D3_3_mem_jit, instr16_D3_3_reg_jit, cl); +define_instruction_read_write_mem32!("rcr32", instr32_D3_3_mem_jit, instr32_D3_3_reg_jit, cl); -define_instruction_read_write_mem16!( - "shl16", - "instr16_D3_4_mem", - instr16_D3_4_mem_jit, - instr16_D3_4_reg_jit, - cl -); -define_instruction_read_write_mem32!( - "shl32", - "instr32_D3_4_mem", - instr32_D3_4_mem_jit, - instr32_D3_4_reg_jit, - cl -); +define_instruction_read_write_mem16!("shl16", instr16_D3_4_mem_jit, instr16_D3_4_reg_jit, cl); +define_instruction_read_write_mem32!("shl32", instr32_D3_4_mem_jit, instr32_D3_4_reg_jit, cl); -define_instruction_read_write_mem16!( - "shr16", - "instr16_D3_5_mem", - instr16_D3_5_mem_jit, - instr16_D3_5_reg_jit, - cl -); -define_instruction_read_write_mem32!( - "shr32", - "instr32_D3_5_mem", - instr32_D3_5_mem_jit, - instr32_D3_5_reg_jit, - cl -); +define_instruction_read_write_mem16!("shr16", instr16_D3_5_mem_jit, instr16_D3_5_reg_jit, cl); +define_instruction_read_write_mem32!("shr32", instr32_D3_5_mem_jit, instr32_D3_5_reg_jit, cl); -define_instruction_read_write_mem16!( - "shl16", - "instr16_D3_6_mem", - instr16_D3_6_mem_jit, - instr16_D3_6_reg_jit, - cl -); -define_instruction_read_write_mem32!( - "shl32", - "instr32_D3_6_mem", - instr32_D3_6_mem_jit, - instr32_D3_6_reg_jit, - cl -); +define_instruction_read_write_mem16!("shl16", instr16_D3_6_mem_jit, instr16_D3_6_reg_jit, cl); +define_instruction_read_write_mem32!("shl32", instr32_D3_6_mem_jit, instr32_D3_6_reg_jit, cl); -define_instruction_read_write_mem16!( - "sar16", - "instr16_D3_7_mem", - instr16_D3_7_mem_jit, - instr16_D3_7_reg_jit, - cl -); -define_instruction_read_write_mem32!( - "sar32", - "instr32_D3_7_mem", - instr32_D3_7_mem_jit, - instr32_D3_7_reg_jit, - cl -); +define_instruction_read_write_mem16!("sar16", instr16_D3_7_mem_jit, instr16_D3_7_reg_jit, cl); +define_instruction_read_write_mem32!("sar32", instr32_D3_7_mem_jit, instr32_D3_7_reg_jit, cl); fn instr_group_D8_mem_jit(ctx: &mut JitContext, modrm_byte: u8, op: &str) { ctx.builder.instruction_body.const_i32(0); @@ -3498,34 +2831,10 @@ pub fn instr32_F7_1_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) { instr32_F7_0_reg_jit(ctx, r, imm) } -define_instruction_read_write_mem16!( - "not16", - "instr16_F7_2_mem", - instr16_F7_2_mem_jit, - instr16_F7_2_reg_jit, - none -); -define_instruction_read_write_mem32!( - "not32", - "instr32_F7_2_mem", - instr32_F7_2_mem_jit, - instr32_F7_2_reg_jit, - none -); -define_instruction_read_write_mem16!( - "neg16", - "instr16_F7_3_mem", - instr16_F7_3_mem_jit, - instr16_F7_3_reg_jit, - none -); -define_instruction_read_write_mem32!( - "neg32", - "instr32_F7_3_mem", - instr32_F7_3_mem_jit, - instr32_F7_3_reg_jit, - none -); +define_instruction_read_write_mem16!("not16", instr16_F7_2_mem_jit, instr16_F7_2_reg_jit, none); +define_instruction_read_write_mem32!("not32", instr32_F7_2_mem_jit, instr32_F7_2_reg_jit, none); +define_instruction_read_write_mem16!("neg16", instr16_F7_3_mem_jit, instr16_F7_3_reg_jit, none); +define_instruction_read_write_mem32!("neg32", instr32_F7_3_mem_jit, instr32_F7_3_reg_jit, none); pub fn instr16_F7_4_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); @@ -3607,35 +2916,11 @@ pub fn instr_FD_jit(ctx: &mut JitContext) { ctx.builder.instruction_body.store_aligned_i32(0); } -define_instruction_read_write_mem16!( - "inc16", - "instr16_FF_0_mem", - instr16_FF_0_mem_jit, - instr16_FF_0_reg_jit, - none -); -define_instruction_read_write_mem32!( - "inc32", - "instr32_FF_0_mem", - instr32_FF_0_mem_jit, - instr32_FF_0_reg_jit, - none -); +define_instruction_read_write_mem16!("inc16", instr16_FF_0_mem_jit, instr16_FF_0_reg_jit, none); +define_instruction_read_write_mem32!("inc32", instr32_FF_0_mem_jit, instr32_FF_0_reg_jit, none); -define_instruction_read_write_mem16!( - "dec16", - "instr16_FF_1_mem", - instr16_FF_1_mem_jit, - instr16_FF_1_reg_jit, - none -); -define_instruction_read_write_mem32!( - "dec32", - "instr32_FF_1_mem", - instr32_FF_1_mem_jit, - instr32_FF_1_reg_jit, - none -); +define_instruction_read_write_mem16!("dec16", instr16_FF_1_mem_jit, instr16_FF_1_reg_jit, none); +define_instruction_read_write_mem32!("dec32", instr32_FF_1_mem_jit, instr32_FF_1_reg_jit, none); pub fn instr16_FF_2_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); @@ -3984,7 +3269,6 @@ pub fn instr_0F1F_reg_jit(_ctx: &mut JitContext, _r1: u32, _r2: u32) {} define_instruction_read_write_mem16!( "shld16", - "instr16_0FA4_mem", instr16_0FA4_mem_jit, instr16_0FA4_reg_jit, reg, @@ -3992,7 +3276,6 @@ define_instruction_read_write_mem16!( ); define_instruction_read_write_mem32!( "shld32", - "instr32_0FA4_mem", instr32_0FA4_mem_jit, instr32_0FA4_reg_jit, reg, @@ -4000,7 +3283,6 @@ define_instruction_read_write_mem32!( ); define_instruction_read_write_mem16!( "shld16", - "instr16_0FA5_mem", instr16_0FA5_mem_jit, instr16_0FA5_reg_jit, reg, @@ -4008,7 +3290,6 @@ define_instruction_read_write_mem16!( ); define_instruction_read_write_mem32!( "shld32", - "instr32_0FA5_mem", instr32_0FA5_mem_jit, instr32_0FA5_reg_jit, reg, @@ -4017,7 +3298,6 @@ define_instruction_read_write_mem32!( define_instruction_read_write_mem16!( "shrd16", - "instr16_0FAC_mem", instr16_0FAC_mem_jit, instr16_0FAC_reg_jit, reg, @@ -4025,7 +3305,6 @@ define_instruction_read_write_mem16!( ); define_instruction_read_write_mem32!( "shrd32", - "instr32_0FAC_mem", instr32_0FAC_mem_jit, instr32_0FAC_reg_jit, reg, @@ -4033,7 +3312,6 @@ define_instruction_read_write_mem32!( ); define_instruction_read_write_mem16!( "shrd16", - "instr16_0FAD_mem", instr16_0FAD_mem_jit, instr16_0FAD_reg_jit, reg, @@ -4041,7 +3319,6 @@ define_instruction_read_write_mem16!( ); define_instruction_read_write_mem32!( "shrd32", - "instr32_0FAD_mem", instr32_0FAD_mem_jit, instr32_0FAD_reg_jit, reg, @@ -4059,23 +3336,12 @@ pub fn instr16_0FB1_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { pub fn instr16_0FB1_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); - codegen::gen_safe_read_write( - ctx, - BitSize::WORD, - &address_local, - &|ref mut ctx| { - ctx.builder.instruction_body.const_i32(r as i32); - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn2_ret(ctx.builder, "cmpxchg16"); - codegen::gen_move_registers_from_memory_to_locals(ctx); - }, - &|ref mut ctx| { - ctx.builder.instruction_body.const_i32(r as i32); - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn2(ctx.builder, "instr16_0FB1_mem"); - codegen::gen_move_registers_from_memory_to_locals(ctx); - }, - ); + codegen::gen_safe_read_write(ctx, BitSize::WORD, &address_local, &|ref mut ctx| { + ctx.builder.instruction_body.const_i32(r as i32); + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn2_ret(ctx.builder, "cmpxchg16"); + codegen::gen_move_registers_from_memory_to_locals(ctx); + }); ctx.builder.free_local(address_local); } @@ -4087,20 +3353,9 @@ pub fn instr32_0FB1_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { pub fn instr32_0FB1_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); - codegen::gen_safe_read_write( - ctx, - BitSize::DWORD, - &address_local, - &|ref mut ctx| { - gen_cmpxchg32(ctx, r); - }, - &|ref mut ctx| { - ctx.builder.instruction_body.const_i32(r as i32); - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn2(ctx.builder, "instr32_0FB1_mem"); - codegen::gen_move_registers_from_memory_to_locals(ctx); - }, - ); + codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { + gen_cmpxchg32(ctx, r); + }); ctx.builder.free_local(address_local); } @@ -4186,25 +3441,14 @@ pub fn instr32_0FBF_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { pub fn instr16_0FC1_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); - codegen::gen_safe_read_write( - ctx, - BitSize::WORD, - &address_local, - &|ref mut ctx| { - ctx.builder - .instruction_body - .const_i32(::cpu2::cpu::get_reg16_index(r as i32)); - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn2_ret(ctx.builder, "xadd16"); - codegen::gen_move_registers_from_memory_to_locals(ctx); - }, - &|ref mut ctx| { - ctx.builder.instruction_body.const_i32(r as i32); - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn2(ctx.builder, "instr16_0FC1_mem"); - codegen::gen_move_registers_from_memory_to_locals(ctx); - }, - ); + codegen::gen_safe_read_write(ctx, BitSize::WORD, &address_local, &|ref mut ctx| { + ctx.builder + .instruction_body + .const_i32(::cpu2::cpu::get_reg16_index(r as i32)); + codegen::gen_move_registers_from_locals_to_memory(ctx); + codegen::gen_call_fn2_ret(ctx.builder, "xadd16"); + codegen::gen_move_registers_from_memory_to_locals(ctx); + }); ctx.builder.free_local(address_local); } pub fn instr16_0FC1_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { @@ -4221,23 +3465,12 @@ pub fn instr16_0FC1_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { pub fn instr32_0FC1_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) { codegen::gen_modrm_resolve(ctx, modrm_byte); let address_local = ctx.builder.set_new_local(); - codegen::gen_safe_read_write( - ctx, - BitSize::DWORD, - &address_local, - &|ref mut ctx| { - let dest_operand = ctx.builder.set_new_local(); - gen_xadd32(ctx, &dest_operand, r); - ctx.builder.instruction_body.get_local(&dest_operand); - ctx.builder.free_local(dest_operand); - }, - &|ref mut ctx| { - ctx.builder.instruction_body.const_i32(r as i32); - codegen::gen_move_registers_from_locals_to_memory(ctx); - codegen::gen_call_fn2(ctx.builder, "instr32_0FC1_mem"); - codegen::gen_move_registers_from_memory_to_locals(ctx); - }, - ); + codegen::gen_safe_read_write(ctx, BitSize::DWORD, &address_local, &|ref mut ctx| { + let dest_operand = ctx.builder.set_new_local(); + gen_xadd32(ctx, &dest_operand, r); + ctx.builder.instruction_body.get_local(&dest_operand); + ctx.builder.free_local(dest_operand); + }); ctx.builder.free_local(address_local); } pub fn instr32_0FC1_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { From c97301842eed82f6e068ee0a49cc1e6c5f94484d Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1661/2137] Put jit_cache_array and jit_page_first_entry into global state, reduces the size of the .wasm files by 8MB because for some reason the rust compiler decides to put them into the data section --- Makefile | 2 +- src/rust/global_pointers.rs | 5 +- src/rust/jit.rs | 103 ++++++++++++++++++------------------ 3 files changed, 57 insertions(+), 53 deletions(-) diff --git a/Makefile b/Makefile index 487dc56b..25de8f42 100644 --- a/Makefile +++ b/Makefile @@ -81,7 +81,7 @@ CARGO_FLAGS=\ --target wasm32-unknown-unknown \ -- \ -C linker=tools/rust-lld-wrapper \ - -C link-args="--import-table --global-base=8388608 $(STRIP_DEBUG_FLAG)" \ + -C link-args="--import-table --global-base=18874368 $(STRIP_DEBUG_FLAG)" \ --verbose CORE_FILES=const.js config.js io.js main.js lib.js ide.js pci.js floppy.js \ diff --git a/src/rust/global_pointers.rs b/src/rust/global_pointers.rs index 16822fa3..cc197f2f 100644 --- a/src/rust/global_pointers.rs +++ b/src/rust/global_pointers.rs @@ -20,7 +20,10 @@ pub const FPU_CONTROL_WORD: u32 = 1036; pub const SSE_SCRATCH_REGISTER: u32 = 1040; pub const OPSTATS_BUFFER: u32 = 0x08000; pub const OPSTATS_UNGUARDED_REGISTER_BUFFER: u32 = 0x20000; -pub const TLB_DATA: u32 = 0x400000; +pub const TLB_DATA: u32 = 0x400000; // 2**20 32-bit words = 4MB + +pub const JIT_PAGE_FIRST_ENTRY: u32 = 0x800000; // 2**20 32-bit words = 4MB +pub const JIT_CACHE_ARRAY: u32 = 0xC00000; // jit_cache_array::SIZE * sizeof(jit_cache_array::Entry) = 0x40000 * 24 = 6MB pub fn get_reg32_offset(r: u32) -> u32 { dbg_assert!(r < 8); diff --git a/src/rust/jit.rs b/src/rust/jit.rs index fddfe1a8..2fd7f3a0 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -38,6 +38,7 @@ mod jit_cache_array { const NO_NEXT_ENTRY: u32 = 0xffff_ffff; + // When changing this, you also need to bump global-base pub const SIZE: u32 = 0x40000; pub const MASK: u32 = SIZE - 1; @@ -119,25 +120,22 @@ mod jit_cache_array { }; #[allow(non_upper_case_globals)] - static mut jit_cache_array: [Entry; SIZE as usize] = [Entry { - start_addr: 0, - next_index_same_page: 0, - wasm_table_index: 0, - initial_state: 0, - state_flags: CachedStateFlags::EMPTY, - pending: false, + pub const jit_cache_array: *mut Entry = ::global_pointers::JIT_CACHE_ARRAY as *mut Entry; - #[cfg(any(debug_assertions, feature = "profiler"))] - len: 0, - #[cfg(debug_assertions)] - opcode: 0, - }; SIZE as usize]; + #[allow(unreachable_code)] + #[cfg(debug_assertions)] + unsafe fn _static_assert() { std::mem::transmute::(panic!()); } + #[allow(unreachable_code)] + #[cfg(all(not(debug_assertions), not(feature = "profiler")))] + unsafe fn _static_assert() { std::mem::transmute::(panic!()); } + + // XXX: Probably doesn't need to be statically allocated #[allow(non_upper_case_globals)] - static mut page_first_entry: [u32; 0x100000] = [0; 0x100000]; + pub const page_first_entry: *mut u32 = ::global_pointers::JIT_PAGE_FIRST_ENTRY as *mut u32; pub fn get_page_index(page: Page) -> Option { - let index = unsafe { page_first_entry[page.to_u32() as usize] }; + let index = unsafe { *page_first_entry.offset(page.to_u32() as isize) }; if index == NO_NEXT_ENTRY { None } @@ -148,17 +146,15 @@ mod jit_cache_array { pub fn set_page_index(page: Page, index: Option) { let index = index.unwrap_or(NO_NEXT_ENTRY); - unsafe { page_first_entry[page.to_u32() as usize] = index } + unsafe { *page_first_entry.offset(page.to_u32() as isize) = index } } - pub fn get(i: u32) -> &'static Entry { unsafe { &jit_cache_array[i as usize] } } - pub fn get_mut(i: u32) -> &'static mut Entry { unsafe { &mut jit_cache_array[i as usize] } } - - pub fn get_unchecked(i: u32) -> &'static Entry { - unsafe { jit_cache_array.get_unchecked(i as usize) } + pub fn get(i: u32) -> &'static Entry { unsafe { &*jit_cache_array.offset(i as isize) } } + pub fn get_mut(i: u32) -> &'static mut Entry { + unsafe { &mut *jit_cache_array.offset(i as isize) } } - fn set(i: u32, entry: Entry) { unsafe { jit_cache_array[i as usize] = entry }; } + fn set(i: u32, entry: Entry) { unsafe { *jit_cache_array.offset(i as isize) = entry }; } pub fn insert(index: u32, mut entry: Entry) { let page = Page::page_of(entry.start_addr); @@ -182,21 +178,21 @@ mod jit_cache_array { } pub fn remove(index: u32) { - let page = Page::page_of(get(index).start_addr); + let page = Page::page_of((get(index)).start_addr); let mut page_index = get_page_index(page); let mut did_remove = false; if page_index == Some(index) { - set_page_index(page, get(index).next_index_same_page()); + set_page_index(page, (get(index)).next_index_same_page()); did_remove = true; } else { while let Some(page_index_ok) = page_index { - let next_index = get(page_index_ok).next_index_same_page(); + let next_index = (get(page_index_ok)).next_index_same_page(); if next_index == Some(index) { - get_mut(page_index_ok) - .set_next_index_same_page(get(index).next_index_same_page()); + (get_mut(page_index_ok)) + .set_next_index_same_page((get(index)).next_index_same_page()); did_remove = true; break; } @@ -204,21 +200,19 @@ mod jit_cache_array { } } - get_mut(index).set_next_index_same_page(None); + (get_mut(index)).set_next_index_same_page(None); dbg_assert!(did_remove); } - pub fn iter() -> ::std::slice::Iter<'static, Entry> { unsafe { jit_cache_array.iter() } } - pub fn clear() { unsafe { - for (i, _) in jit_cache_array.iter().enumerate() { - jit_cache_array[i] = DEFAULT_ENTRY; + for i in 0..SIZE { + *jit_cache_array.offset(i as isize) = DEFAULT_ENTRY; } - for (i, _) in page_first_entry.iter().enumerate() { - page_first_entry[i] = NO_NEXT_ENTRY; + for i in 0..0x100000 { + *page_first_entry.offset(i) = NO_NEXT_ENTRY; } } } @@ -235,11 +229,11 @@ mod jit_cache_array { let mut fast = slow; while let Some(fast_ok) = fast { - fast = get(fast_ok).next_index_same_page(); - slow = get(slow.unwrap()).next_index_same_page(); + fast = (get(fast_ok)).next_index_same_page(); + slow = (get(slow.unwrap())).next_index_same_page(); if let Some(fast_ok) = fast { - fast = get(fast_ok).next_index_same_page(); + fast = (get(fast_ok)).next_index_same_page(); } else { break; @@ -251,7 +245,8 @@ mod jit_cache_array { let mut wasm_table_index_to_jit_cache_index = [0; ::jit::WASM_TABLE_SIZE as usize]; - for (i, entry) in iter().enumerate() { + for i in 0..SIZE { + let entry = get(i); dbg_assert!(entry.next_index_same_page().map_or(true, |i| i < SIZE)); if entry.pending { @@ -400,7 +395,7 @@ pub fn jit_find_cache_entry(phys_address: u32, state_flags: CachedStateFlags) -> for i in 0..CODE_CACHE_SEARCH_SIZE { let index = (phys_address + i) & jit_cache_array::MASK; - let entry = jit_cache_array::get_unchecked(index); + let entry = jit_cache_array::get(index); if entry.start_addr == phys_address { if entry.pending { @@ -942,12 +937,12 @@ pub fn codegen_finalize_finished( while let Some(index) = cache_array_index { let mut entry = jit_cache_array::get_mut(index); - if entry.wasm_table_index == wasm_table_index { - dbg_assert!(entry.pending); - entry.pending = false; + if (*entry).wasm_table_index == wasm_table_index { + dbg_assert!((*entry).pending); + (*entry).pending = false; } - cache_array_index = entry.next_index_same_page(); + cache_array_index = (*entry).next_index_same_page(); } }, } @@ -957,7 +952,8 @@ pub fn codegen_finalize_finished( if CHECK_JIT_CACHE_ARRAY_INVARIANTS { // sanity check that the above iteration marked all entries as not pending - for entry in jit_cache_array::iter() { + for i in 0..jit_cache_array::SIZE { + let entry = jit_cache_array::get(i); if entry.wasm_table_index == wasm_table_index { dbg_assert!(!entry.pending); } @@ -1348,7 +1344,8 @@ fn remove_jit_cache_wasm_index(ctx: &mut JitState, page: Page, wasm_table_index: if CHECK_JIT_CACHE_ARRAY_INVARIANTS { // sanity check that the above iteration deleted all entries - for entry in jit_cache_array::iter() { + for i in 0..jit_cache_array::SIZE { + let entry = jit_cache_array::get(i); dbg_assert!(entry.wasm_table_index != wasm_table_index); } } @@ -1470,16 +1467,20 @@ pub fn jit_page_has_code(ctx: &JitState, page: Page) -> bool { #[cfg(debug_assertions)] pub fn jit_unused_cache_stat() -> u32 { - jit_cache_array::iter() - .filter(|e| e.start_addr == 0) - .count() as u32 + let mut count = 0; + for i in 0..jit_cache_array::SIZE { + if (jit_cache_array::get(i)).start_addr == 0 { + count += 1 + } + } + return count; } #[cfg(debug_assertions)] -pub fn jit_get_entry_length(i: u32) -> u32 { jit_cache_array::get(i).len } +pub fn jit_get_entry_length(i: u32) -> u32 { (jit_cache_array::get(i)).len } #[cfg(debug_assertions)] -pub fn jit_get_entry_address(i: u32) -> u32 { jit_cache_array::get(i).start_addr } +pub fn jit_get_entry_address(i: u32) -> u32 { (jit_cache_array::get(i)).start_addr } #[cfg(debug_assertions)] -pub fn jit_get_entry_pending(i: u32) -> bool { jit_cache_array::get(i).pending } +pub fn jit_get_entry_pending(i: u32) -> bool { (jit_cache_array::get(i)).pending } #[cfg(debug_assertions)] pub fn jit_get_wasm_table_index_free_list_count(ctx: &JitState) -> u32 { ctx.wasm_table_index_free_list.len() as u32 @@ -1496,7 +1497,7 @@ pub fn check_missed_entry_points(phys_address: u32, state_flags: CachedStateFlag // No need to check [CODE_CACHE_SEARCH_SIZE] entries here as we look at consecutive // addresses anyway let index = i & jit_cache_array::MASK; - let entry = jit_cache_array::get_unchecked(index); + let entry = jit_cache_array::get(index); if !entry.pending && entry.state_flags == state_flags From 4ab8ef9fdda72c63011a4b23925ed55cfba578b3 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1662/2137] Docs: Overview of SSE shifts --- docs/sse-shifts.txt | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 docs/sse-shifts.txt diff --git a/docs/sse-shifts.txt b/docs/sse-shifts.txt new file mode 100644 index 00000000..7fb5b2c6 --- /dev/null +++ b/docs/sse-shifts.txt @@ -0,0 +1,39 @@ + 0F F1 PSLLW mm mm/m64 mmx Shift Packed Data Left Logical +66 0F F1 PSLLW xmm xmm/m128 sse2 Shift Packed Data Left Logical + 0F F2 PSLLD mm mm/m64 mmx Shift Packed Data Left Logical +66 0F F2 PSLLD xmm xmm/m128 sse2 Shift Packed Data Left Logical + 0F F3 PSLLQ mm mm/m64 mmx Shift Packed Data Left Logical +66 0F F3 PSLLQ xmm xmm/m128 sse2 Shift Packed Data Left Logical + + 0F E1 PSRAW mm mm/m64 mmx Shift Packed Data Right Arithmetic +66 0F E1 PSRAW xmm xmm/m128 sse2 Shift Packed Data Right Arithmetic + 0F E2 PSRAD mm mm/m64 mmx Shift Packed Data Right Arithmetic +66 0F E2 PSRAD xmm xmm/m128 sse2 Shift Packed Data Right Arithmetic + + 0F D1 PSRLW mm mm/m64 mmx Shift Packed Data Right Logical +66 0F D1 PSRLW xmm xmm/m128 sse2 Shift Packed Data Right Logical + 0F D2 PSRLD mm mm/m64 mmx Shift Packed Data Right Logical +66 0F D2 PSRLD xmm xmm/m128 sse2 Shift Packed Data Right Logical + 0F D3 PSRLQ mm mm/m64 mmx Shift Packed Data Right Logical +66 0F D3 PSRLQ xmm xmm/m128 sse2 Shift Packed Data Right Logical + + 0F 71 PSRLW mm imm8 mmx Shift Packed Data Right Logical +66 0F 71 PSRLW xmm imm8 sse2 Shift Packed Data Right Logical + 0F 71 PSRAW mm imm8 mmx Shift Packed Data Right Arithmetic +66 0F 71 PSRAW xmm imm8 sse2 Shift Packed Data Right Arithmetic + 0F 71 PSLLW mm imm8 mmx Shift Packed Data Left Logical +66 0F 71 PSLLW xmm imm8 sse2 Shift Packed Data Left Logical + + 0F 72 PSRLD mm imm8 mmx Shift Double Quadword Right Logical +66 0F 72 PSRLD xmm imm8 sse2 Shift Double Quadword Right Logical + 0F 72 PSRAD mm imm8 mmx Shift Packed Data Right Arithmetic +66 0F 72 PSRAD xmm imm8 sse2 Shift Packed Data Right Arithmetic + 0F 72 PSLLD mm imm8 mmx Shift Packed Data Left Logical +66 0F 72 PSLLD xmm imm8 sse2 Shift Packed Data Left Logical + + 0F 73 PSRLQ mm imm8 mmx Shift Packed Data Right Logical +66 0F 73 PSRLQ xmm imm8 sse2 Shift Packed Data Right Logical +66 0F 73 PSRLDQ xmm imm8 sse2 Shift Double Quadword Right Logical + 0F 73 PSLLQ mm imm8 mmx Shift Packed Data Left Logical +66 0F 73 PSLLQ xmm imm8 sse2 Shift Packed Data Left Logical +66 0F 73 PSLLDQ xmm imm8 sse2 Shift Double Quadword Left Logical From 48a9847d1670a82a85a126a2d10633c328345745 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1663/2137] s/oxide// --- Cargo.toml | 2 +- Makefile | 26 +++++++++++++------------- src/browser/print_stats.js | 22 +++++++++++----------- src/browser/starter.js | 20 ++++++++++---------- src/cpu.js | 21 ++++++++++----------- src/main.js | 7 +++---- 6 files changed, 48 insertions(+), 50 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 49d17450..db07ddf1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "v86oxide" +name = "v86" version = "0.1.0" publish = false diff --git a/Makefile b/Makefile index 25de8f42..6ba2d521 100644 --- a/Makefile +++ b/Makefile @@ -17,9 +17,9 @@ ifeq ($(STRIP_DEBUG),true) STRIP_DEBUG_FLAG=--v86-strip-debug endif -default: build/v86oxide-debug.wasm -all: build/v86_all.js build/libv86.js build/v86oxide.wasm -all-debug: build/libv86-debug.js build/v86oxide-debug.wasm +default: build/v86-debug.wasm +all: build/v86_all.js build/libv86.js build/v86.wasm +all-debug: build/libv86-debug.js build/v86-debug.wasm browser: build/v86_all.js # Used for nodejs builds and in order to profile code. @@ -174,26 +174,26 @@ src/rust/gen/analyzer0f_16.rs: $(ANALYZER_DEPENDENCIES) src/rust/gen/analyzer0f_32.rs: $(ANALYZER_DEPENDENCIES) ./gen/generate_analyzer.js --output-dir build/ --table analyzer0f_32 -build/v86oxide.wasm: $(RUST_FILES) Cargo.toml +build/v86.wasm: $(RUST_FILES) Cargo.toml mkdir -p build/ - -ls -lh build/v86oxide.wasm + -ls -lh build/v86.wasm cargo +nightly rustc --release $(CARGO_FLAGS) - ./tools/wasm-patch-indirect-function-table.js < build/wasm32-unknown-unknown/release/v86oxide.wasm > build/v86oxide.wasm - ls -lh build/v86oxide.wasm + ./tools/wasm-patch-indirect-function-table.js < build/wasm32-unknown-unknown/release/v86.wasm > build/v86.wasm + ls -lh build/v86.wasm -build/v86oxide-debug.wasm: $(RUST_FILES) Cargo.toml +build/v86-debug.wasm: $(RUST_FILES) Cargo.toml mkdir -p build/ - -ls -lh build/v86oxide-debug.wasm + -ls -lh build/v86-debug.wasm cargo +nightly rustc $(CARGO_FLAGS) - ./tools/wasm-patch-indirect-function-table.js < build/wasm32-unknown-unknown/debug/v86oxide.wasm > build/v86oxide-debug.wasm - ls -lh build/v86oxide-debug.wasm + ./tools/wasm-patch-indirect-function-table.js < build/wasm32-unknown-unknown/debug/v86.wasm > build/v86-debug.wasm + ls -lh build/v86-debug.wasm clean: -rm build/libv86.js -rm build/libv86-debug.js -rm build/v86_all.js - -rm build/v86oxide.wasm - -rm build/v86oxide-debug.wasm + -rm build/v86.wasm + -rm build/v86-debug.wasm -rm $(INSTRUCTION_TABLES) -rm $(addsuffix .bak,$(INSTRUCTION_TABLES)) -rm $(addsuffix .diff,$(INSTRUCTION_TABLES)) diff --git a/src/browser/print_stats.js b/src/browser/print_stats.js index f496bd6d..bdb7d7b2 100644 --- a/src/browser/print_stats.js +++ b/src/browser/print_stats.js @@ -74,21 +74,21 @@ const print_stats = { for(let i = 0; i < stat_names.length; i++) { - let stat = cpu.v86oxide.exports["profiler_stat_get"](i); + let stat = cpu.wm.exports["profiler_stat_get"](i); stat = stat >= 100e6 ? Math.round(stat / 1e6) + "m" : stat >= 100e3 ? Math.round(stat / 1e3) + "k" : stat; text += stat_names[i] + "=" + stat + "\n"; } text += "\n"; - const tlb_entries = cpu.v86oxide.exports["get_valid_tlb_entries_count"](); - const global_tlb_entries = cpu.v86oxide.exports["get_valid_global_tlb_entries_count"](); + const tlb_entries = cpu.wm.exports["get_valid_tlb_entries_count"](); + const global_tlb_entries = cpu.wm.exports["get_valid_global_tlb_entries_count"](); const nonglobal_tlb_entries = tlb_entries - global_tlb_entries; text += "TLB_ENTRIES=" + tlb_entries + " (" + global_tlb_entries + " global, " + nonglobal_tlb_entries + " non-global)\n"; - text += "CACHE_UNUSED=" + cpu.v86oxide.exports["jit_unused_cache_stat"]() + "\n"; - text += "WASM_TABLE_FREE=" + cpu.v86oxide.exports["jit_get_wasm_table_index_free_list_count"]() + "\n"; - text += "FLAT_SEGMENTS=" + cpu.v86oxide.exports["has_flat_segmentation"]() + "\n"; + text += "CACHE_UNUSED=" + cpu.wm.exports["jit_unused_cache_stat"]() + "\n"; + text += "WASM_TABLE_FREE=" + cpu.wm.exports["jit_get_wasm_table_index_free_list_count"]() + "\n"; + text += "FLAT_SEGMENTS=" + cpu.wm.exports["has_flat_segmentation"]() + "\n"; text += "do_many_cycles avg: " + do_many_cycles_total / do_many_cycles_count + "\n"; @@ -105,7 +105,7 @@ const print_stats = { for(let i = 0; i < JIT_CACHE_ARRAY_SIZE; i++) { - const address = cpu.v86oxide.exports["jit_get_entry_address"](i); + const address = cpu.wm.exports["jit_get_entry_address"](i); if(address !== 0) { @@ -138,8 +138,8 @@ const print_stats = { for(let i = 0; i < JIT_CACHE_ARRAY_SIZE; i++) { - const length = cpu.v86oxide.exports["jit_get_entry_length"](i); - pending_count += cpu.v86oxide.exports["jit_get_entry_pending"](i); + const length = cpu.wm.exports["jit_get_entry_length"](i); + pending_count += cpu.wm.exports["jit_get_entry_pending"](i); histogram[length] = (histogram[length] || 0) + 1; } @@ -196,10 +196,10 @@ const print_stats = { { for(let is_mem of [false, true]) { - const count = cpu.v86oxide.exports["get_opstats_buffer"](compiled, jit_exit, unguarded_register, wasm_size, opcode, false, is_mem, fixed_g); + const count = cpu.wm.exports["get_opstats_buffer"](compiled, jit_exit, unguarded_register, wasm_size, opcode, false, is_mem, fixed_g); counts.push({ opcode, count, is_mem, fixed_g }); - const count_0f = cpu.v86oxide.exports["get_opstats_buffer"](compiled, jit_exit, unguarded_register, wasm_size, opcode, true, is_mem, fixed_g); + const count_0f = cpu.wm.exports["get_opstats_buffer"](compiled, jit_exit, unguarded_register, wasm_size, opcode, true, is_mem, fixed_g); counts.push({ opcode: 0x0f00 | opcode, count: count_0f, is_mem, fixed_g }); } } diff --git a/src/browser/starter.js b/src/browser/starter.js index 0928c450..96e70b98 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -186,29 +186,29 @@ function V86Starter(options) "__indirect_function_table": wasm_table, }; - let v86oxide_bin = DEBUG ? "v86oxide-debug.wasm" : "v86oxide.wasm"; + let v86_bin = DEBUG ? "v86-debug.wasm" : "v86.wasm"; - if(options["oxide_path"]) + if(options["wasm_path"]) { - v86oxide_bin = options["oxide_path"]; + v86_bin = options["wasm_path"]; } else if(typeof window === "undefined" && typeof __dirname === "string") { - v86oxide_bin = __dirname + "/" + v86oxide_bin; + v86_bin = __dirname + "/" + v86_bin; } else { - v86oxide_bin = "build/" + v86oxide_bin; + v86_bin = "build/" + v86_bin; } v86util.load_wasm( - v86oxide_bin, + v86_bin, { "env": wasm_shared_funcs }, - v86oxide => { - wasm_memory = v86oxide.exports.memory; - v86oxide.exports["rust_setup"](); + v86_wasm => { + wasm_memory = v86_wasm.exports.memory; + v86_wasm.exports["rust_setup"](); - const emulator = this.v86 = new v86(this.emulator_bus, v86oxide, v86oxide); + const emulator = this.v86 = new v86(this.emulator_bus, v86_wasm); cpu = emulator.cpu; this.continue_init(emulator, options); diff --git a/src/cpu.js b/src/cpu.js index 59e64cb3..138636b3 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -11,14 +11,13 @@ var CPU_LOG_VERBOSE = false; /** @constructor */ -function CPU(bus, wm, v86oxide) +function CPU(bus, wm) { this.wm = wm; - this.v86oxide = v86oxide; this.wasm_patch(wm); this.create_jit_imports(); - const memory = v86oxide.instance.exports.memory; + const memory = this.wm.instance.exports.memory; this.wasm_memory = memory; @@ -218,7 +217,7 @@ CPU.prototype.wasmgen_get_module_code = function() const ptr = this.jit_get_op_ptr(); const len = this.jit_get_op_len(); - const output_buffer_view = new Uint8Array(this.v86oxide.instance.exports.memory.buffer, ptr, len); + const output_buffer_view = new Uint8Array(this.wm.instance.exports.memory.buffer, ptr, len); return output_buffer_view; }; @@ -233,9 +232,9 @@ CPU.prototype.create_jit_imports = function() } // put all imports that don't change on the prototype - JITImports.prototype["m"] = this.v86oxide.memory; + JITImports.prototype["m"] = this.wm.memory; - const exports = this.v86oxide.instance.exports; + const exports = this.wm.instance.exports; JITImports.prototype["m"] = exports["memory"]; @@ -256,7 +255,7 @@ CPU.prototype.create_jit_imports = function() CPU.prototype.wasm_patch = function(wm) { const get_optional_import = (name) => { - return this.v86oxide.exports[name]; + return this.wm.exports[name]; }; const get_import = (name) => @@ -764,9 +763,9 @@ CPU.prototype.create_memory = function(size) const memory_offset = this.allocate_memory(size); - this.mem8 = v86util.view(Uint8Array, this.v86oxide.instance.exports.memory, memory_offset, size); - this.mem16 = v86util.view(Uint16Array, this.v86oxide.instance.exports.memory, memory_offset, size >> 1); - this.mem32s = v86util.view(Uint32Array, this.v86oxide.instance.exports.memory, memory_offset, size >> 2); + this.mem8 = v86util.view(Uint8Array, this.wm.instance.exports.memory, memory_offset, size); + this.mem16 = v86util.view(Uint16Array, this.wm.instance.exports.memory, memory_offset, size >> 1); + this.mem32s = v86util.view(Uint32Array, this.wm.instance.exports.memory, memory_offset, size >> 2); }; CPU.prototype.init = function(settings, device_bus) @@ -1499,7 +1498,7 @@ CPU.prototype.dump_function_code = function(block_ptr, count) const SIZEOF_BASIC_BLOCK_IN_DWORDS = 7; - const mem32 = new Int32Array(this.v86oxide.instance.exports.memory.buffer); + const mem32 = new Int32Array(this.wm.instance.exports.memory.buffer); dbg_assert((block_ptr & 3) === 0); diff --git a/src/main.js b/src/main.js index b692425f..81fae952 100644 --- a/src/main.js +++ b/src/main.js @@ -2,10 +2,9 @@ /** * @constructor - * @param {Object=} wm - * @param {Object=} codegen + * @param {Object=} wasm */ -function v86(bus, wm, codegen) +function v86(bus, wasm) { /** @type {boolean} */ this.running = false; @@ -14,7 +13,7 @@ function v86(bus, wm, codegen) this.stopped = false; /** @type {CPU} */ - this.cpu = new CPU(bus, wm, codegen); + this.cpu = new CPU(bus, wasm); this.bus = bus; bus.register("cpu-init", this.init, this); From b7e5f28104847342a083cc7d26144f408542b28f Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1664/2137] Fix rust warning --- src/rust/jit.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 2fd7f3a0..476ff3f1 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -852,6 +852,7 @@ fn jit_analyze_and_generate( let initial_state = i.safe_to_u16(); + #[allow(unused_mut)] let mut entry = jit_cache_array::Entry::create( block.addr, None, // to be filled in by create_cache_entry From d5c9b29942901b08e515f029e44884b115c8503e Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1665/2137] Upgrade jshint --- .jshint.json | 2 +- lib/9p.js | 14 +++--- lib/filesystem.js | 92 ++++++++++++++++++------------------ src/browser/filestorage.js | 40 ++++++++-------- src/browser/starter.js | 12 ++--- tests/devices/filestorage.js | 44 ++++++++--------- 6 files changed, 102 insertions(+), 102 deletions(-) diff --git a/.jshint.json b/.jshint.json index 1fba711f..ac873d6a 100644 --- a/.jshint.json +++ b/.jshint.json @@ -1,5 +1,5 @@ { - "esversion": 6, + "esversion": 8, "globalstrict": true, "sub": true, "expr": true, diff --git a/lib/9p.js b/lib/9p.js index 7a77c962..a035bad7 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -250,7 +250,7 @@ Virtio9p.prototype.SendReply = function (bufchain) { this.virtqueue.flush_replies(); }; -Virtio9p.prototype.ReceiveRequest = async function (bufchain) { // jshint ignore:line +Virtio9p.prototype.ReceiveRequest = async function (bufchain) { // TODO: split into header + data blobs to avoid unnecessary copying. const buffer = new Uint8Array(bufchain.length_readable); bufchain.get_next_blob(buffer); @@ -553,7 +553,7 @@ Virtio9p.prototype.ReceiveRequest = async function (bufchain) { // jshint ignore inode.mtime = req[8]; } if (req[1] & P9_SETATTR_SIZE) { - await this.fs.ChangeSize(this.fids[fid].inodeid, req[5]); // jshint ignore:line + await this.fs.ChangeSize(this.fids[fid].inodeid, req[5]); } this.BuildReply(id, tag, 0); this.SendReply(bufchain); @@ -608,7 +608,7 @@ Virtio9p.prototype.ReceiveRequest = async function (bufchain) { // jshint ignore this.bus.send("9p-read-start", [this.fids[fid].dbg_name]); - const data = await this.fs.Read(inodeid, offset, count); // jshint ignore:line + const data = await this.fs.Read(inodeid, offset, count); this.bus.send("9p-read-end", [this.fids[fid].dbg_name, count]); @@ -639,7 +639,7 @@ Virtio9p.prototype.ReceiveRequest = async function (bufchain) { // jshint ignore else { // XXX: Size of the subarray is unchecked - await this.fs.Write(this.fids[fid].inodeid, offset, count, buffer.subarray(state.offset)); // jshint ignore:line + await this.fs.Write(this.fids[fid].inodeid, offset, count, buffer.subarray(state.offset)); } this.bus.send("9p-write-end", [filename, count]); @@ -656,7 +656,7 @@ Virtio9p.prototype.ReceiveRequest = async function (bufchain) { // jshint ignore var newdirfid = req[2]; var newname = req[3]; message.Debug("[renameat]: oldname=" + oldname + " newname=" + newname); - var ret = await this.fs.Rename(this.fids[olddirfid].inodeid, oldname, this.fids[newdirfid].inodeid, newname); // jshint ignore:line + var ret = await this.fs.Rename(this.fids[olddirfid].inodeid, oldname, this.fids[newdirfid].inodeid, newname); if (ret < 0) { let error_message = ""; if(ret === -ENOENT) error_message = "No such file or directory"; @@ -789,7 +789,7 @@ Virtio9p.prototype.ReceiveRequest = async function (bufchain) { // jshint ignore var req = marshall.Unmarshall(["w"], buffer, state); message.Debug("[clunk]: fid=" + req[0]); if (this.fids[req[0]] && this.fids[req[0]].inodeid >= 0) { - await this.fs.CloseInode(this.fids[req[0]].inodeid); // jshint ignore:line + await this.fs.CloseInode(this.fids[req[0]].inodeid); this.fids[req[0]].inodeid = -1; this.fids[req[0]].type = FID_NONE; } @@ -849,4 +849,4 @@ Virtio9p.prototype.ReceiveRequest = async function (bufchain) { // jshint ignore //consistency checks if there are problems with the filesystem //this.fs.Check(); -}; // jshint ignore:line +}; diff --git a/lib/filesystem.js b/lib/filesystem.js index 27382920..ce7b0a69 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -628,12 +628,12 @@ FS.prototype.CreateSymlink = function(filename, parentid, symlink) { return this.inodes.length-1; }; -FS.prototype.CreateTextFile = async function(filename, parentid, str) { // jshint ignore:line +FS.prototype.CreateTextFile = async function(filename, parentid, str) { const parent_inode = this.inodes[parentid]; if(this.is_forwarder(parent_inode)) { const foreign_parentid = parent_inode.foreign_id; - const foreign_id = await // jshint ignore:line + const foreign_id = await this.follow_fs(parent_inode).CreateTextFile(filename, foreign_parentid, str); return this.create_forwarder(parent_inode.mount_id, foreign_id); } @@ -645,19 +645,19 @@ FS.prototype.CreateTextFile = async function(filename, parentid, str) { // jshin for (var j = 0; j < str.length; j++) { data[j] = str.charCodeAt(j); } - await this.set_data(id, data); // jshint ignore:line + await this.set_data(id, data); return id; -}; // jshint ignore:line +}; /** * @param {Uint8Array} buffer */ -FS.prototype.CreateBinaryFile = async function(filename, parentid, buffer) { // jshint ignore:line +FS.prototype.CreateBinaryFile = async function(filename, parentid, buffer) { const parent_inode = this.inodes[parentid]; if(this.is_forwarder(parent_inode)) { const foreign_parentid = parent_inode.foreign_id; - const foreign_id = await // jshint ignore:line + const foreign_id = await this.follow_fs(parent_inode).CreateBinaryFile(filename, foreign_parentid, buffer); return this.create_forwarder(parent_inode.mount_id, foreign_id); } @@ -666,10 +666,10 @@ FS.prototype.CreateBinaryFile = async function(filename, parentid, buffer) { // var data = new Uint8Array(buffer.length); x.dirty = true; data.set(buffer); - await this.set_data(id, data); // jshint ignore:line + await this.set_data(id, data); x.size = buffer.length; return id; -}; // jshint ignore:line +}; FS.prototype.OpenInode = function(id, mode) { @@ -694,12 +694,12 @@ FS.prototype.OpenInode = function(id, mode) { return true; }; -FS.prototype.CloseInode = async function(id) { // jshint ignore:line +FS.prototype.CloseInode = async function(id) { //message.Debug("close: " + this.GetFullPath(id)); var inode = this.inodes[id]; if(this.is_forwarder(inode)) { - return await this.follow_fs(inode).CloseInode(inode.foreign_id); // jshint ignore:line + return await this.follow_fs(inode).CloseInode(inode.foreign_id); } if(inode.status === STATUS_ON_STORAGE) { @@ -708,14 +708,14 @@ FS.prototype.CloseInode = async function(id) { // jshint ignore:line if (inode.status == STATUS_UNLINKED) { //message.Debug("Filesystem: Delete unlinked file"); inode.status = STATUS_INVALID; - await this.DeleteData(id); // jshint ignore:line + await this.DeleteData(id); } -}; // jshint ignore:line +}; /** * @return {!Promise} 0 if success, or -errno if failured. */ -FS.prototype.Rename = async function(olddirid, oldname, newdirid, newname) { // jshint ignore:line +FS.prototype.Rename = async function(olddirid, oldname, newdirid, newname) { // message.Debug("Rename " + oldname + " to " + newname); if ((olddirid == newdirid) && (oldname == newname)) { return 0; @@ -753,7 +753,7 @@ FS.prototype.Rename = async function(olddirid, oldname, newdirid, newname) { // { // Move inode within the same child filesystem. - const ret = await // jshint ignore:line + const ret = await this.follow_fs(olddir).Rename(olddir.foreign_id, oldname, newdir.foreign_id, newname); if(ret < 0) return ret; @@ -781,7 +781,7 @@ FS.prototype.Rename = async function(olddirid, oldname, newdirid, newname) { // const diverted_old_idx = this.divert(olddirid, oldname); const old_real_inode = this.GetInode(idx); - const data = await this.Read(diverted_old_idx, 0, old_real_inode.size); // jshint ignore:line + const data = await this.Read(diverted_old_idx, 0, old_real_inode.size); if(this.is_forwarder(newdir)) { @@ -808,10 +808,10 @@ FS.prototype.Rename = async function(olddirid, oldname, newdirid, newname) { // } // Rewrite data to newly created destination. - await this.ChangeSize(idx, old_real_inode.size); // jshint ignore:line + await this.ChangeSize(idx, old_real_inode.size); if(data && data.length) { - await this.Write(idx, 0, data.length, data); // jshint ignore:line + await this.Write(idx, 0, data.length, data); } // Move children to newly created destination. @@ -819,13 +819,13 @@ FS.prototype.Rename = async function(olddirid, oldname, newdirid, newname) { // { for(const child_filename of this.GetChildren(diverted_old_idx)) { - const ret = await this.Rename(diverted_old_idx, child_filename, idx, child_filename); // jshint ignore:line + const ret = await this.Rename(diverted_old_idx, child_filename, idx, child_filename); if(ret < 0) return ret; } } // Perform destructive changes only after migration succeeded. - await this.DeleteData(diverted_old_idx); // jshint ignore:line + await this.DeleteData(diverted_old_idx); const ret = this.Unlink(olddirid, oldname); if(ret < 0) return ret; } @@ -833,26 +833,26 @@ FS.prototype.Rename = async function(olddirid, oldname, newdirid, newname) { // this.NotifyListeners(idx, "rename", {oldpath: oldpath}); return 0; -}; // jshint ignore:line +}; -FS.prototype.Write = async function(id, offset, count, buffer) { // jshint ignore:line +FS.prototype.Write = async function(id, offset, count, buffer) { this.NotifyListeners(id, 'write'); var inode = this.inodes[id]; if(this.is_forwarder(inode)) { const foreign_id = inode.foreign_id; - await this.follow_fs(inode).Write(foreign_id, offset, count, buffer); // jshint ignore:line + await this.follow_fs(inode).Write(foreign_id, offset, count, buffer); return; } inode.dirty = true; - var data = await this.get_buffer(id); // jshint ignore:line + var data = await this.get_buffer(id); if (!data || data.length < (offset+count)) { - await this.ChangeSize(id, Math.floor(((offset+count)*3)/2)); // jshint ignore:line + await this.ChangeSize(id, Math.floor(((offset+count)*3)/2)); inode.size = offset + count; - data = await this.get_buffer(id); // jshint ignore:line + data = await this.get_buffer(id); } else if (inode.size < (offset+count)) { inode.size = offset + count; @@ -861,20 +861,20 @@ FS.prototype.Write = async function(id, offset, count, buffer) { // jshint ignor { data.set(buffer.subarray(0, count), offset); } - await this.set_data(id, data); // jshint ignore:line -}; // jshint ignore:line + await this.set_data(id, data); +}; -FS.prototype.Read = async function(inodeid, offset, count) // jshint ignore:line +FS.prototype.Read = async function(inodeid, offset, count) { const inode = this.inodes[inodeid]; if(this.is_forwarder(inode)) { const foreign_id = inode.foreign_id; - return await this.follow_fs(inode).Read(foreign_id, offset, count); // jshint ignore:line + return await this.follow_fs(inode).Read(foreign_id, offset, count); } - return await this.get_data(inodeid, offset, count); // jshint ignore:line -}; // jshint ignore:line + return await this.get_data(inodeid, offset, count); +}; FS.prototype.Search = function(parentid, name) { const parent_inode = this.inodes[parentid]; @@ -1050,17 +1050,17 @@ FS.prototype.Unlink = function(parentid, name) { return 0; }; -FS.prototype.DeleteData = async function(idx) // jshint ignore:line +FS.prototype.DeleteData = async function(idx) { const inode = this.inodes[idx]; if(this.is_forwarder(inode)) { - await this.follow_fs(inode).DeleteData(inode.foreign_id); // jshint ignore:line + await this.follow_fs(inode).DeleteData(inode.foreign_id); return; } inode.size = 0; delete this.inodedata[idx]; -}; // jshint ignore:line +}; /** * @private @@ -1069,7 +1069,7 @@ FS.prototype.DeleteData = async function(idx) // jshint ignore:line * than the data itself. To ensure that any modifications done to this buffer is reflected * to the file, call set_data with the modified buffer. */ -FS.prototype.get_buffer = async function(idx) // jshint ignore:line +FS.prototype.get_buffer = async function(idx) { const inode = this.inodes[idx]; dbg_assert(inode, `Filesystem get_buffer: idx ${idx} does not point to an inode`); @@ -1081,13 +1081,13 @@ FS.prototype.get_buffer = async function(idx) // jshint ignore:line else if(inode.status === STATUS_ON_STORAGE) { dbg_assert(inode.sha256sum, "Filesystem get_data: found inode on server without sha256sum"); - return await this.storage.read(inode.sha256sum, 0, inode.size); // jshint ignore:line + return await this.storage.read(inode.sha256sum, 0, inode.size); } else { return null; } -}; // jshint ignore:line +}; /** * @private @@ -1096,7 +1096,7 @@ FS.prototype.get_buffer = async function(idx) // jshint ignore:line * @param {number} count * @return {!Promise} */ -FS.prototype.get_data = async function(idx, offset, count) // jshint ignore:line +FS.prototype.get_data = async function(idx, offset, count) { const inode = this.inodes[idx]; dbg_assert(inode, `Filesystem get_data: idx ${idx} does not point to an inode`); @@ -1108,20 +1108,20 @@ FS.prototype.get_data = async function(idx, offset, count) // jshint ignore:line else if(inode.status === STATUS_ON_STORAGE) { dbg_assert(inode.sha256sum, "Filesystem get_data: found inode on server without sha256sum"); - return await this.storage.read(inode.sha256sum, offset, count); // jshint ignore:line + return await this.storage.read(inode.sha256sum, offset, count); } else { return null; } -}; // jshint ignore:line +}; /** * @private * @param {number} idx * @param {Uint8Array} buffer */ -FS.prototype.set_data = async function(idx, buffer) // jshint ignore:line +FS.prototype.set_data = async function(idx, buffer) { // Current scheme: Save all modified buffers into local inodedata. this.inodedata[idx] = buffer; @@ -1130,7 +1130,7 @@ FS.prototype.set_data = async function(idx, buffer) // jshint ignore:line this.inodes[idx].status = STATUS_OK; this.storage.uncache(this.inodes[idx].sha256sum); } -}; // jshint ignore:line +}; /** * @param {number} idx @@ -1150,10 +1150,10 @@ FS.prototype.GetInode = function(idx) return inode; }; -FS.prototype.ChangeSize = async function(idx, newsize) // jshint ignore:line +FS.prototype.ChangeSize = async function(idx, newsize) { var inode = this.GetInode(idx); - var temp = await this.get_data(idx, 0, inode.size); // jshint ignore:line + var temp = await this.get_data(idx, 0, inode.size); inode.dirty = true; //message.Debug("change size to: " + newsize); if (newsize == inode.size) return; @@ -1164,8 +1164,8 @@ FS.prototype.ChangeSize = async function(idx, newsize) // jshint ignore:line var size = Math.min(temp.length, inode.size); data.set(temp.subarray(0, size), 0); } - await this.set_data(idx, data); // jshint ignore:line -}; // jshint ignore:line + await this.set_data(idx, data); +}; FS.prototype.SearchPath = function(path) { //path = path.replace(/\/\//g, "/"); diff --git a/src/browser/filestorage.js b/src/browser/filestorage.js index cc426c75..381934ef 100644 --- a/src/browser/filestorage.js +++ b/src/browser/filestorage.js @@ -55,7 +55,7 @@ function MemoryFileStorage() * @param {number} count * @return {!Promise} null if file does not exist. */ -MemoryFileStorage.prototype.read = async function(sha256sum, offset, count) // jshint ignore:line +MemoryFileStorage.prototype.read = async function(sha256sum, offset, count) { dbg_assert(sha256sum, "MemoryFileStorage read: sha256sum should be a non-empty string"); const data = this.filedata.get(sha256sum); @@ -66,19 +66,19 @@ MemoryFileStorage.prototype.read = async function(sha256sum, offset, count) // j } return data.subarray(offset, offset + count); -}; // jshint ignore:line +}; /** * @param {string} sha256sum * @param {!Uint8Array} data */ -MemoryFileStorage.prototype.set = async function(sha256sum, data) // jshint ignore:line +MemoryFileStorage.prototype.set = async function(sha256sum, data) { dbg_assert(sha256sum, "MemoryFileStorage set: sha256sum should be a non-empty string"); dbg_assert(!this.filedata.has(sha256sum), "MemoryFileStorage set: Storage should be read-only"); this.filedata.set(sha256sum, data); -}; // jshint ignore:line +}; /** * @param {string} sha256sum @@ -100,16 +100,16 @@ function IndexedDBFileStorage(db) this.db = db; } -IndexedDBFileStorage.try_create = async function() // jshint ignore:line +IndexedDBFileStorage.try_create = async function() { if(typeof window === "undefined" || !window.indexedDB) { throw new Error("IndexedDB is not available"); } - const db = await IndexedDBFileStorage.init_db(); // jshint ignore:line + const db = await IndexedDBFileStorage.init_db(); const file_storage = new IndexedDBFileStorage(db); return file_storage; -}; // jshint ignore:line +}; /** * @return {!Promise} @@ -223,7 +223,7 @@ IndexedDBFileStorage.prototype.read = function(sha256sum, offset, count) const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, 0); const block_request = store.get(block_key); - block_request.onsuccess = async event => // jshint ignore:line + block_request.onsuccess = async event => { const block_entry = block_request.result; if(!block_entry) @@ -245,16 +245,16 @@ IndexedDBFileStorage.prototype.read = function(sha256sum, offset, count) const block_offset = block_number_start * INDEXEDDB_STORAGE_BLOCKSIZE; const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, block_number_start); const block_request = store.get(block_key); - block_request.onsuccess = async event => // jshint ignore:line + block_request.onsuccess = async event => { const block_entry = block_request.result; if(!block_entry) { - if(!await this.db_has_file(store, sha256sum)) // jshint ignore:line + if(!await this.db_has_file(store, sha256sum)) { resolve(null); } - else // jshint ignore:line + else { resolve(new Uint8Array(0)); } @@ -280,7 +280,7 @@ IndexedDBFileStorage.prototype.read = function(sha256sum, offset, count) const block_offset = block_number * INDEXEDDB_STORAGE_BLOCKSIZE; const block_key = INDEXEDDB_STORAGE_GET_BLOCK_KEY(sha256sum, block_number); const block_request = store.get(block_key); - block_request.onsuccess = async event => // jshint ignore:line + block_request.onsuccess = async event => { const block_entry = block_request.result; @@ -290,7 +290,7 @@ IndexedDBFileStorage.prototype.read = function(sha256sum, offset, count) // cannot exist. if(block_number === block_number_start) { - if(!await this.db_has_file(store, sha256sum)) // jshint ignore:line + if(!await this.db_has_file(store, sha256sum)) { // Not aborting transaction here because: // - Abort is treated like an error, @@ -404,25 +404,25 @@ ServerFileStorageWrapper.prototype.load_from_server = function(sha256sum) * @param {number} count * @return {!Promise} */ -ServerFileStorageWrapper.prototype.read = async function(sha256sum, offset, count) // jshint ignore:line +ServerFileStorageWrapper.prototype.read = async function(sha256sum, offset, count) { - const data = await this.storage.read(sha256sum, offset, count); // jshint ignore:line + const data = await this.storage.read(sha256sum, offset, count); if(!data) { - const full_file = await this.load_from_server(sha256sum); // jshint ignore:line + const full_file = await this.load_from_server(sha256sum); return full_file.subarray(offset, offset + count); } return data; -}; // jshint ignore:line +}; /** * @param {string} sha256sum * @param {!Uint8Array} data */ -ServerFileStorageWrapper.prototype.set = async function(sha256sum, data) // jshint ignore:line +ServerFileStorageWrapper.prototype.set = async function(sha256sum, data) { - return await this.storage.set(sha256sum, data); // jshint ignore:line -}; // jshint ignore:line + return await this.storage.set(sha256sum, data); +}; /** * @param {string} sha256sum diff --git a/src/browser/starter.js b/src/browser/starter.js index 96e70b98..4f94bbf5 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -215,7 +215,7 @@ function V86Starter(options) }); } -V86Starter.prototype.continue_init = async function(emulator, options) // jshint ignore:line +V86Starter.prototype.continue_init = async function(emulator, options) { this.bus.register("emulator-stopped", function() { @@ -447,7 +447,7 @@ V86Starter.prototype.continue_init = async function(emulator, options) // jshint let file_storage = typeof window === "undefined" || !window.indexedDB ? new MemoryFileStorage() : - await IndexedDBFileStorage.try_create(); // jshint ignore:line + await IndexedDBFileStorage.try_create(); if(base_url) { file_storage = new ServerFileStorageWrapper(file_storage, base_url); @@ -605,7 +605,7 @@ V86Starter.prototype.continue_init = async function(emulator, options) // jshint this.emulator_bus.send("emulator-loaded"); } } -}; // jshint ignore:line +}; V86Starter.prototype.get_bzimage_initrd_from_filesystem = function(filesystem) { @@ -1046,11 +1046,11 @@ V86Starter.prototype.serial0_send = function(data) * @param {function(Object)=} callback * @export */ -V86Starter.prototype.mount_fs = async function(path, baseurl, basefs, callback) // jshint ignore:line +V86Starter.prototype.mount_fs = async function(path, baseurl, basefs, callback) { let file_storage = typeof window === "undefined" || !window.indexedDB ? new MemoryFileStorage() : - await IndexedDBFileStorage.try_create(); // jshint ignore:line + await IndexedDBFileStorage.try_create(); if(baseurl) { file_storage = new ServerFileStorageWrapper(file_storage, baseurl); @@ -1090,7 +1090,7 @@ V86Starter.prototype.mount_fs = async function(path, baseurl, basefs, callback) { mount(); } -}; // jshint ignore:line +}; /** * Write to a file in the 9p filesystem. Nothing happens if no filesystem has diff --git a/tests/devices/filestorage.js b/tests/devices/filestorage.js index 12c89057..3d226221 100755 --- a/tests/devices/filestorage.js +++ b/tests/devices/filestorage.js @@ -155,20 +155,20 @@ function mock_indexeddb() }; } -async function test_read(oracle, iut, key, offset, count) // jshint ignore:line +async function test_read(oracle, iut, key, offset, count) { - const expected = await oracle.read(key, offset, count); // jshint ignore:line - const actual = await iut.read(key, offset, count); // jshint ignore:line + const expected = await oracle.read(key, offset, count); + const actual = await iut.read(key, offset, count); return assert_uint8array_equal(actual, expected); } -async function test_with_file(oracle, iut, key, file_data) // jshint ignore:line +async function test_with_file(oracle, iut, key, file_data) { if(file_data) { console.log("Testing file with size: %d", file_data.length); - await oracle.set(key, file_data); // jshint ignore:line - await iut.set(key, file_data); // jshint ignore:line + await oracle.set(key, file_data); + await iut.set(key, file_data); } else { @@ -176,22 +176,22 @@ async function test_with_file(oracle, iut, key, file_data) // jshint ignore:line } // Some boundary values. - if(!await test_read(oracle, iut, key, 0, 0)) return false; // jshint ignore:line - if(!await test_read(oracle, iut, key, 0, 1)) return false; // jshint ignore:line - if(!await test_read(oracle, iut, key, 0, 4096)) return false; // jshint ignore:line - if(!await test_read(oracle, iut, key, 0, 4097)) return false; // jshint ignore:line - if(!await test_read(oracle, iut, key, 4095, 2)) return false; // jshint ignore:line - if(!await test_read(oracle, iut, key, 4096, 1)) return false; // jshint ignore:line - if(!await test_read(oracle, iut, key, 4096, 4096)) return false; // jshint ignore:line - if(!await test_read(oracle, iut, key, 4097, 1)) return false; // jshint ignore:line - if(!await test_read(oracle, iut, key, 4097, 4095)) return false; // jshint ignore:line + if(!await test_read(oracle, iut, key, 0, 0)) return false; + if(!await test_read(oracle, iut, key, 0, 1)) return false; + if(!await test_read(oracle, iut, key, 0, 4096)) return false; + if(!await test_read(oracle, iut, key, 0, 4097)) return false; + if(!await test_read(oracle, iut, key, 4095, 2)) return false; + if(!await test_read(oracle, iut, key, 4096, 1)) return false; + if(!await test_read(oracle, iut, key, 4096, 4096)) return false; + if(!await test_read(oracle, iut, key, 4097, 1)) return false; + if(!await test_read(oracle, iut, key, 4097, 4095)) return false; // Random ranges. for(let i = 0; i < NUMBER_OF_TESTREADS; i++) { const offset = Math.floor(Math.random() * MAX_TESTFILE_SIZE); const count = Math.floor(Math.random() * MAX_TESTFILE_SIZE); - const pass = await test_read(oracle, iut, key, offset, count); // jshint ignore:line + const pass = await test_read(oracle, iut, key, offset, count); if(!pass) { log_fail("Test case offset=%d, count=%d", offset, count); @@ -211,7 +211,7 @@ function on_unexpected_exit(exit_code) } } -async function test_start() // jshint ignore:line +async function test_start() { process.on("exit", on_unexpected_exit); @@ -221,16 +221,16 @@ async function test_start() // jshint ignore:line // Implementation under test with chunking. const iut = new IndexedDBFileStorage(mock_indexeddb()); - if(!await test_with_file(oracle, iut, "nonexistent")) return false; // jshint ignore:line - if(!await test_with_file(oracle, iut, "empty", new Uint8Array(0))) return false; // jshint ignore:line - if(!await test_with_file(oracle, iut, "single", new Uint8Array(1).map(v => Math.random() * 0xFF))) return false; // jshint ignore:line - if(!await test_with_file(oracle, iut, "1block", new Uint8Array(4096).map(v => Math.random() * 0xFF))) return false; // jshint ignore:line + if(!await test_with_file(oracle, iut, "nonexistent")) return false; + if(!await test_with_file(oracle, iut, "empty", new Uint8Array(0))) return false; + if(!await test_with_file(oracle, iut, "single", new Uint8Array(1).map(v => Math.random() * 0xFF))) return false; + if(!await test_with_file(oracle, iut, "1block", new Uint8Array(4096).map(v => Math.random() * 0xFF))) return false; for(let i = 0; i < NUMBER_OF_TESTFILES; i++) { const size = Math.floor(Math.random() * MAX_TESTFILE_SIZE); const file_data = new Uint8Array(size).map(v => Math.random() * 0xFF); - const pass = await test_with_file(oracle, iut, i.toString(), file_data); // jshint ignore:line + const pass = await test_with_file(oracle, iut, i.toString(), file_data); if(!pass) return false; } From c84a814610f9bf331b983430ca0206c51499b59d Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1666/2137] Remove unused A20 stuff --- src/cpu.js | 13 +----- src/rust/cpu2/cpu.rs | 3 -- src/rust/cpu2/global_pointers.rs | 2 +- src/rust/cpu2/memory.rs | 72 +++++++------------------------- 4 files changed, 17 insertions(+), 73 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index 138636b3..3f34cace 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -23,11 +23,6 @@ function CPU(bus, wm) this.memory_size = v86util.view(Uint32Array, memory, 812, 1); - // Note: Currently unused (degrades performance and not required by any OS - // that we support) - this.a20_enabled = v86util.view(Int32Array, memory, 552, 1); - this.a20_enabled[0] = +true; - this.mem8 = new Uint8Array(0); this.mem16 = new Uint16Array(this.mem8.buffer); this.mem32s = new Int32Array(this.mem8.buffer); @@ -418,7 +413,6 @@ CPU.prototype.get_state = function() state[59] = this.devices.net; state[60] = this.devices.pic; - state[61] = this.a20_enabled[0]; state[62] = this.fw_value; state[63] = this.devices.ioapic; @@ -514,7 +508,6 @@ CPU.prototype.set_state = function(state) this.devices.net = state[59]; this.devices.pic = state[60]; - this.a20_enabled[0] = state[61]; this.fw_value = state[62]; this.devices.ioapic = state[63]; @@ -644,8 +637,6 @@ CPU.prototype.reboot_internal = function() CPU.prototype.reset = function() { - this.a20_enabled[0] = +true; - this.segment_is_null.fill(0); this.segment_limits.fill(0); //this.segment_infos = new Uint32Array(8); @@ -800,8 +791,6 @@ CPU.prototype.init = function(settings, device_bus) } } - var a20_byte = 0; - io.register_read(0xB3, this, function() { // seabios smm_relocate_and_restore @@ -809,6 +798,8 @@ CPU.prototype.init = function(settings, device_bus) return 0; }); + var a20_byte = 0; + io.register_read(0x92, this, function() { return a20_byte; diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 794432a9..09476aea 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -205,9 +205,6 @@ pub const PREFIX_F2: i32 = PREFIX_REPNZ; pub const PREFIX_F3: i32 = PREFIX_REPZ; pub const PREFIX_66: i32 = PREFIX_MASK_OPSIZE; pub const LOG_CPU: i32 = 2; -pub const A20_MASK: i32 = !(1 << 20); -pub const A20_MASK16: i32 = !(1 << 20 - 1); -pub const A20_MASK32: i32 = !(1 << 20 - 2); pub const MXCSR_MASK: i32 = 0xffff; pub const MXCSR_FZ: i32 = 1 << 15; diff --git a/src/rust/cpu2/global_pointers.rs b/src/rust/cpu2/global_pointers.rs index ad774e94..21e3193b 100644 --- a/src/rust/cpu2/global_pointers.rs +++ b/src/rust/cpu2/global_pointers.rs @@ -17,7 +17,7 @@ pub const flags: *mut i32 = 120 as *mut i32; pub const page_fault: *mut bool = 540 as *mut bool; pub const page_fault_error_code: *mut i32 = 544 as *mut i32; -pub const a20_enabled: *mut bool = 552 as *mut bool; + pub const instruction_pointer: *mut i32 = 556 as *mut i32; pub const previous_ip: *mut i32 = 560 as *mut i32; pub const idtr_size: *mut i32 = 564 as *mut i32; diff --git a/src/rust/cpu2/memory.rs b/src/rust/cpu2/memory.rs index 42c6c388..823452fd 100644 --- a/src/rust/cpu2/memory.rs +++ b/src/rust/cpu2/memory.rs @@ -20,18 +20,13 @@ use cpu2::cpu::*; use cpu2::global_pointers::*; use page::Page; -const USE_A20: bool = false; - #[no_mangle] pub unsafe fn in_mapped_range(addr: u32) -> bool { return addr >= 0xA0000 && addr < 0xC0000 || addr >= *memory_size; } #[no_mangle] -pub unsafe fn read8(mut addr: u32) -> i32 { - if 0 != USE_A20 as i32 && 0 != *a20_enabled as i32 { - addr &= A20_MASK as u32 - } +pub unsafe fn read8(addr: u32) -> i32 { if in_mapped_range(addr) { return mmap_read8(addr); } @@ -40,10 +35,7 @@ pub unsafe fn read8(mut addr: u32) -> i32 { }; } #[no_mangle] -pub unsafe fn read16(mut addr: u32) -> i32 { - if 0 != USE_A20 as i32 && !*a20_enabled { - addr &= A20_MASK as u32 - } +pub unsafe fn read16(addr: u32) -> i32 { if in_mapped_range(addr) { return mmap_read16(addr); } @@ -52,11 +44,8 @@ pub unsafe fn read16(mut addr: u32) -> i32 { }; } #[no_mangle] -pub unsafe fn read_aligned16(mut addr: u32) -> i32 { +pub unsafe fn read_aligned16(addr: u32) -> i32 { dbg_assert!(addr < 0x80000000); - if 0 != USE_A20 as i32 && !*a20_enabled { - addr &= A20_MASK16 as u32 - } if in_mapped_range(addr << 1) { return mmap_read16(addr << 1); } @@ -65,10 +54,7 @@ pub unsafe fn read_aligned16(mut addr: u32) -> i32 { }; } #[no_mangle] -pub unsafe fn read32s(mut addr: u32) -> i32 { - if 0 != USE_A20 as i32 && 0 != *a20_enabled as i32 { - addr &= A20_MASK as u32 - } +pub unsafe fn read32s(addr: u32) -> i32 { if in_mapped_range(addr) { return mmap_read32(addr); } @@ -77,10 +63,7 @@ pub unsafe fn read32s(mut addr: u32) -> i32 { }; } #[no_mangle] -pub unsafe fn read64s(mut addr: u32) -> i64 { - if 0 != USE_A20 as i32 && 0 != *a20_enabled as i32 { - addr &= A20_MASK as u32 - } +pub unsafe fn read64s(addr: u32) -> i64 { if in_mapped_range(addr) { return mmap_read32(addr) as i64 | (mmap_read32(addr.wrapping_add(4 as u32)) as i64) << 32; } @@ -89,11 +72,8 @@ pub unsafe fn read64s(mut addr: u32) -> i64 { }; } #[no_mangle] -pub unsafe fn read_aligned32(mut addr: u32) -> i32 { +pub unsafe fn read_aligned32(addr: u32) -> i32 { dbg_assert!(addr < 0x40000000 as u32); - if 0 != USE_A20 as i32 && !*a20_enabled { - addr &= A20_MASK32 as u32 - } if in_mapped_range(addr << 2) { return mmap_read32(addr << 2); } @@ -102,10 +82,7 @@ pub unsafe fn read_aligned32(mut addr: u32) -> i32 { }; } #[no_mangle] -pub unsafe fn read128(mut addr: u32) -> reg128 { - if 0 != USE_A20 as i32 && 0 != *a20_enabled as i32 { - addr &= A20_MASK as u32 - } +pub unsafe fn read128(addr: u32) -> reg128 { let mut value: reg128 = reg128 { i8_0: [0 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; @@ -123,10 +100,7 @@ pub unsafe fn read128(mut addr: u32) -> reg128 { } #[no_mangle] -pub unsafe fn write8(mut addr: u32, value: i32) { - if 0 != USE_A20 as i32 && !*a20_enabled { - addr &= A20_MASK as u32 - } +pub unsafe fn write8(addr: u32, value: i32) { if in_mapped_range(addr) { mmap_write8(addr, value); } @@ -141,10 +115,7 @@ pub unsafe fn write8_no_mmap_or_dirty_check(addr: u32, value: i32) { } #[no_mangle] -pub unsafe fn write16(mut addr: u32, value: i32) { - if 0 != USE_A20 as i32 && !*a20_enabled { - addr &= A20_MASK as u32 - } +pub unsafe fn write16(addr: u32, value: i32) { if in_mapped_range(addr) { mmap_write16(addr, value); } @@ -154,11 +125,8 @@ pub unsafe fn write16(mut addr: u32, value: i32) { }; } #[no_mangle] -pub unsafe fn write_aligned16(mut addr: u32, value: u32) { +pub unsafe fn write_aligned16(addr: u32, value: u32) { dbg_assert!(addr < 0x80000000); - if 0 != USE_A20 as i32 && !*a20_enabled { - addr &= A20_MASK16 as u32 - } let phys_addr: u32 = addr << 1; if in_mapped_range(phys_addr) { mmap_write16(phys_addr, value as i32); @@ -169,10 +137,7 @@ pub unsafe fn write_aligned16(mut addr: u32, value: u32) { }; } #[no_mangle] -pub unsafe fn write32(mut addr: u32, value: i32) { - if 0 != USE_A20 as i32 && !*a20_enabled { - addr &= A20_MASK as u32 - } +pub unsafe fn write32(addr: u32, value: i32) { if in_mapped_range(addr) { mmap_write32(addr, value); } @@ -187,11 +152,8 @@ pub unsafe fn write_aligned32_no_mmap_or_dirty_check(addr: u32, value: i32) { } #[no_mangle] -pub unsafe fn write_aligned32(mut addr: u32, value: i32) { +pub unsafe fn write_aligned32(addr: u32, value: i32) { dbg_assert!(addr < 0x40000000 as u32); - if 0 != USE_A20 as i32 && !*a20_enabled { - addr &= A20_MASK32 as u32 - } let phys_addr: u32 = addr << 2; if in_mapped_range(phys_addr) { mmap_write32(phys_addr, value); @@ -202,10 +164,7 @@ pub unsafe fn write_aligned32(mut addr: u32, value: i32) { }; } #[no_mangle] -pub unsafe fn write64(mut addr: u32, value: i64) { - if 0 != USE_A20 as i32 && !*a20_enabled { - addr &= A20_MASK as u32 - } +pub unsafe fn write64(addr: u32, value: i64) { if in_mapped_range(addr) { mmap_write32( addr.wrapping_add(0 as u32), @@ -219,10 +178,7 @@ pub unsafe fn write64(mut addr: u32, value: i64) { }; } #[no_mangle] -pub unsafe fn write128(mut addr: u32, value: reg128) { - if 0 != USE_A20 as i32 && !*a20_enabled { - addr &= A20_MASK as u32 - } +pub unsafe fn write128(addr: u32, value: reg128) { if in_mapped_range(addr) { mmap_write128( addr, From b5b1cbf7da76b0ce16cfd509cee68908106be0f5 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1667/2137] Simplify --- src/rust/cpu2/instruction_helpers.rs | 64 ++++++++++------------------ 1 file changed, 22 insertions(+), 42 deletions(-) diff --git a/src/rust/cpu2/instruction_helpers.rs b/src/rust/cpu2/instruction_helpers.rs index 7390cd47..55a3af3b 100644 --- a/src/rust/cpu2/instruction_helpers.rs +++ b/src/rust/cpu2/instruction_helpers.rs @@ -2,36 +2,24 @@ macro_rules! SAFE_READ_WRITE8 { ($value:ident, $addr:expr, $instruction:expr) => {{ use cpu2::cpu::translate_address_write; use cpu2::memory::{read8, write8}; - match translate_address_write($addr) { - Err(()) => {}, - Ok(phys_addr) => { - let $value = read8(phys_addr); - write8(phys_addr, $instruction); - }, - } + let phys_addr = return_on_pagefault!(translate_address_write($addr)); + let $value = read8(phys_addr); + write8(phys_addr, $instruction); }}; } macro_rules! SAFE_READ_WRITE16 { ($value:ident, $addr:expr, $instruction:expr) => {{ use cpu2::cpu::{translate_address_write, virt_boundary_read16, virt_boundary_write16}; use cpu2::memory::{read16, write16}; - match translate_address_write($addr) { - Err(()) => {}, - Ok(phys_addr) => { - if phys_addr & 0xFFF == 0xFFF { - match translate_address_write($addr + 1) { - Err(()) => {}, - Ok(phys_addr_high) => { - let $value = virt_boundary_read16(phys_addr, phys_addr_high); - virt_boundary_write16(phys_addr, phys_addr_high, $instruction); - }, - } - } - else { - let $value = read16(phys_addr); - write16(phys_addr, $instruction); - } - }, + let phys_addr = return_on_pagefault!(translate_address_write($addr)); + if phys_addr & 0xFFF == 0xFFF { + let phys_addr_high = return_on_pagefault!(translate_address_write($addr + 1)); + let $value = virt_boundary_read16(phys_addr, phys_addr_high); + virt_boundary_write16(phys_addr, phys_addr_high, $instruction); + } + else { + let $value = read16(phys_addr); + write16(phys_addr, $instruction); } }}; } @@ -39,24 +27,16 @@ macro_rules! SAFE_READ_WRITE32 { ($value:ident, $addr:expr, $instruction:expr) => {{ use cpu2::cpu::{translate_address_write, virt_boundary_read32s, virt_boundary_write32}; use cpu2::memory::{read32s, write32}; - match translate_address_write($addr) { - Err(()) => {}, - Ok(phys_addr) => { - if phys_addr & 0xFFF >= 0xFFD { - match translate_address_write($addr + 3 & !3) { - Err(()) => {}, - Ok(phys_addr_high) => { - let phys_addr_high = phys_addr_high | ($addr as u32) + 3 & 3; - let $value = virt_boundary_read32s(phys_addr, phys_addr_high); - virt_boundary_write32(phys_addr, phys_addr_high, $instruction); - }, - } - } - else { - let $value = read32s(phys_addr); - write32(phys_addr, $instruction); - } - }, + let phys_addr = return_on_pagefault!(translate_address_write($addr)); + if phys_addr & 0xFFF >= 0xFFD { + let phys_addr_high = return_on_pagefault!(translate_address_write($addr + 3 & !3)); + let phys_addr_high = phys_addr_high | ($addr as u32) + 3 & 3; + let $value = virt_boundary_read32s(phys_addr, phys_addr_high); + virt_boundary_write32(phys_addr, phys_addr_high, $instruction); + } + else { + let $value = read32s(phys_addr); + write32(phys_addr, $instruction); } }}; } From fe74b8d33244a2786968900fe5e8c114554fc30f Mon Sep 17 00:00:00 2001 From: copy Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1668/2137] Fix license - The end year was really unnecessary and mostly out of date - Talk about contributors in plural - Remove FreeBSD clause (as per readme) --- LICENSE | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/LICENSE b/LICENSE index 056b0224..5033d6de 100644 --- a/LICENSE +++ b/LICENSE @@ -1,14 +1,14 @@ -Copyright (c) 2012-2014, Fabian Hemmer +Copyright (c) 2012, The v86 contributors All rights reserved. Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: +modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. + list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. + and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -20,7 +20,3 @@ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The views and conclusions contained in the software and documentation are those -of the authors and should not be interpreted as representing official policies, -either expressed or implied, of the FreeBSD Project. From 6021ce80b04aef6f48b9ba3e6ef9b83668cda130 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1669/2137] images: Load external kolibri image even over https (server previously didn't support https) --- src/browser/main.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/browser/main.js b/src/browser/main.js index abe92978..557533c4 100644 --- a/src/browser/main.js +++ b/src/browser/main.js @@ -11,9 +11,6 @@ /** @const */ var OTHER_HOST = ON_LOCALHOST ? "" : "//j.copy.sh:8880/"; - /** @const */ - var ON_HTTPS = location.protocol === "https:"; - function dump_file(ab, name) { if(!(ab instanceof Array)) @@ -327,7 +324,7 @@ { id: "kolibrios", fda: { - "url": (ON_LOCALHOST || ON_HTTPS) ? + "url": ON_LOCALHOST ? "images/kolibri.img" : "//builds.kolibrios.org/eng/data/data/kolibri.img", "size": 1474560, From 5f38f0ffcf6bc1f0747addfdda4778d3e596cb45 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1670/2137] Remover "Other host" --- src/browser/main.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/browser/main.js b/src/browser/main.js index 557533c4..2ec9ca90 100644 --- a/src/browser/main.js +++ b/src/browser/main.js @@ -8,9 +8,6 @@ /** @const */ var HOST = ON_LOCALHOST ? "" : "//i.copy.sh/"; - /** @const */ - var OTHER_HOST = ON_LOCALHOST ? "" : "//j.copy.sh:8880/"; - function dump_file(ab, name) { if(!(ab instanceof Array)) @@ -406,8 +403,7 @@ "size": 142815292, }, hda: { - "url": ON_LOCALHOST ? "../v86-images/os/freebsd3.img" : - OTHER_HOST + "images/freebsd3.img", + "url": HOST + "images/freebsd3.img", "size": 17179869184, "async": true, }, From 2396a1b809fbff48b285d92ff00d09979aa2db3d Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1671/2137] Add some sources for the OS images --- src/browser/main.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/browser/main.js b/src/browser/main.js index 2ec9ca90..d1477d03 100644 --- a/src/browser/main.js +++ b/src/browser/main.js @@ -201,6 +201,7 @@ debug_onload(settings); } + // Abandonware OS images are from https://winworldpc.com/library/operating-systems var oses = [ { id: "archlinux", @@ -246,6 +247,7 @@ }, { id: "oberon", + // https://lists.inf.ethz.ch/pipermail/oberon/2013/006844.html fda: { "url": HOST + "images/oberon-boot.dsk", "size": 1440 * 1024, @@ -320,6 +322,7 @@ }, { id: "kolibrios", + // https://kolibrios.org/en/ fda: { "url": ON_LOCALHOST ? "images/kolibri.img" : @@ -347,6 +350,7 @@ { id: "solos", fda: { + // http://oby.ro/os/ "url": HOST + "images/os8.dsk", "size": 1474560, }, @@ -355,6 +359,7 @@ { id: "dexos", cdrom: { + // https://dex-os.github.io/ "url": HOST + "images/DexOSv6.iso", "size": 1837056, }, @@ -363,6 +368,7 @@ { id: "bootchess", fda: { + // http://www.pouet.net/prod.php?which=64962 "url": HOST + "images/bootchess.img", }, name: "Bootchess", From b5def60fb4f99c1c5c6fe4a267cbad250842c811 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1672/2137] Clean up --- src/rust/cpu2/cpu.rs | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index 09476aea..91dfc399 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -1338,13 +1338,8 @@ pub unsafe fn trigger_pagefault_jit(fault: PageFault) { } } profiler::stat_increment(PAGE_FAULT); - //if *page_fault { - // dbg_log!(("double fault")); - // dbg_trace(); - // dbg_assert!(false); - //} - // invalidate tlb entry *cr.offset(2) = addr; + // invalidate tlb entry let page = ((addr as u32) >> 12) as i32; *tlb_data.offset(page as isize) = 0; *prefixes = 0; @@ -1354,7 +1349,6 @@ pub unsafe fn trigger_pagefault_jit(fault: PageFault) { } } *page_fault_error_code = (user as i32) << 2 | (write as i32) << 1 | present as i32; - //*page_fault = true; } #[no_mangle] @@ -1388,18 +1382,12 @@ pub unsafe fn trigger_pagefault(fault: PageFault) { } } profiler::stat_increment(PAGE_FAULT); - //if *page_fault { - // dbg_log!(("double fault")); - // dbg_trace(); - // dbg_assert!(false); - //} - // invalidate tlb entry *cr.offset(2) = addr; + // invalidate tlb entry let page = ((addr as u32) >> 12) as i32; *tlb_data.offset(page as isize) = 0; *prefixes = 0; *instruction_pointer = *previous_ip; - //*page_fault = true; call_interrupt_vector( CPU_EXCEPTION_PF, false, From 04d9a6102c5f6645bd36757950cf43868c8b046c Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1673/2137] Fix file being created in PWD when compiling kvm-unit-test --- Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 6ba2d521..49af9cbe 100644 --- a/Makefile +++ b/Makefile @@ -260,8 +260,7 @@ qemutests: all-debug diff /tmp/v86-test-result /tmp/v86-test-reference kvm-unit-test: all-debug - (cd tests/kvm-unit-tests && ./configure) - $(MAKE) -C tests/kvm-unit-tests + (cd tests/kvm-unit-tests && ./configure && make) tests/kvm-unit-tests/run.js tests/kvm-unit-tests/x86/realmode.flat expect-tests: all-debug build/libwabt.js From 3be6e8aa0353f173428ad447f500bd4947585a74 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1674/2137] Dead --- gen/c_ast.js | 97 ---------------------------------------------------- 1 file changed, 97 deletions(-) delete mode 100644 gen/c_ast.js diff --git a/gen/c_ast.js b/gen/c_ast.js deleted file mode 100644 index 4cdcdded..00000000 --- a/gen/c_ast.js +++ /dev/null @@ -1,97 +0,0 @@ -"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, -}; From c0fd7051ee8e74e50139facdd1c894989183caef Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1675/2137] Robustness --- src/browser/main.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/browser/main.js b/src/browser/main.js index d1477d03..839fe717 100644 --- a/src/browser/main.js +++ b/src/browser/main.js @@ -904,7 +904,7 @@ var last_tick = 0; var running_time = 0; var last_instr_counter = 0; - var interval; + var interval = null; var os_uses_mouse = false; var total_instructions = 0; @@ -942,7 +942,10 @@ emulator.add_listener("emulator-stopped", function() { update_info(); - clearInterval(interval); + if(interval === null) + { + clearInterval(interval); + } }); var stats_9p = { From 3951e5f42b29246cec12e46832bd4022de72aa62 Mon Sep 17 00:00:00 2001 From: Fabian Date: Thu, 31 Dec 2020 19:14:29 -0600 Subject: [PATCH 1676/2137] Use mIPS over kIPS \o/ --- debug.html | 4 ++-- index.html | 4 ++-- src/browser/main.js | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/debug.html b/debug.html index 6682f5ff..ea23e473 100644 --- a/debug.html +++ b/debug.html @@ -194,8 +194,8 @@